summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Documentation/ABI/testing/debugfs-pktcdvd6
-rw-r--r--Documentation/ABI/testing/sysfs-devices-cache_disable18
-rw-r--r--Documentation/ABI/testing/sysfs-firmware-acpi8
-rw-r--r--Documentation/ABI/testing/sysfs-kernel-slab479
-rw-r--r--Documentation/CodingStyle4
-rw-r--r--Documentation/DMA-API.txt4
-rw-r--r--Documentation/DocBook/Makefile8
-rw-r--r--Documentation/DocBook/kernel-api.tmpl6
-rw-r--r--Documentation/DocBook/kgdb.tmpl2
-rw-r--r--Documentation/DocBook/tracepoint.tmpl89
-rw-r--r--Documentation/RCU/rculist_nulls.txt2
-rw-r--r--Documentation/RCU/trace.txt102
-rw-r--r--Documentation/SM501.txt2
-rw-r--r--Documentation/Smack.txt20
-rw-r--r--Documentation/SubmittingPatches9
-rw-r--r--Documentation/block/biodoc.txt19
-rw-r--r--Documentation/block/deadline-iosched.txt2
-rw-r--r--Documentation/braille-console.txt2
-rw-r--r--Documentation/cgroups/memory.txt55
-rw-r--r--Documentation/cgroups/resource_counter.txt27
-rw-r--r--Documentation/driver-model/devres.txt2
-rw-r--r--Documentation/driver-model/platform.txt59
-rw-r--r--Documentation/dvb/get_dvb_firmware6
-rw-r--r--Documentation/edac.txt8
-rw-r--r--Documentation/fb/sh7760fb.txt2
-rw-r--r--Documentation/feature-removal-schedule.txt10
-rw-r--r--Documentation/filesystems/00-INDEX4
-rw-r--r--Documentation/filesystems/Locking24
-rw-r--r--Documentation/filesystems/autofs4-mount-control.txt2
-rw-r--r--Documentation/filesystems/caching/cachefiles.txt8
-rw-r--r--Documentation/filesystems/caching/netfs-api.txt2
-rw-r--r--Documentation/filesystems/ext4.txt6
-rw-r--r--Documentation/filesystems/fiemap.txt2
-rw-r--r--Documentation/filesystems/nfs-rdma.txt2
-rw-r--r--Documentation/filesystems/pohmelfs/design_notes.txt5
-rw-r--r--Documentation/filesystems/pohmelfs/info.txt21
-rw-r--r--Documentation/filesystems/proc.txt4
-rw-r--r--Documentation/filesystems/sysfs-pci.txt2
-rw-r--r--Documentation/filesystems/vfat.txt8
-rw-r--r--Documentation/filesystems/vfs.txt3
-rw-r--r--Documentation/gpio.txt2
-rw-r--r--Documentation/hwmon/ibmaem2
-rw-r--r--Documentation/i2c/instantiating-devices44
-rw-r--r--Documentation/i2c/writing-clients16
-rw-r--r--Documentation/input/bcm5974.txt65
-rw-r--r--Documentation/input/input.txt2
-rw-r--r--Documentation/input/multi-touch-protocol.txt140
-rw-r--r--Documentation/input/rotary-encoder.txt9
-rw-r--r--Documentation/kbuild/makefiles.txt10
-rw-r--r--Documentation/kdump/kdump.txt4
-rw-r--r--Documentation/kernel-doc-nano-HOWTO.txt7
-rw-r--r--Documentation/kernel-parameters.txt104
-rw-r--r--Documentation/kmemleak.txt142
-rw-r--r--Documentation/kobject.txt2
-rw-r--r--Documentation/laptops/acer-wmi.txt2
-rw-r--r--Documentation/laptops/sony-laptop.txt2
-rw-r--r--Documentation/laptops/thinkpad-acpi.txt6
-rw-r--r--Documentation/lguest/.gitignore1
-rw-r--r--Documentation/lguest/lguest.txt11
-rw-r--r--Documentation/local_ops.txt2
-rw-r--r--Documentation/lockdep-design.txt6
-rw-r--r--Documentation/logo.gifbin0 -> 16335 bytes
-rw-r--r--Documentation/logo.svg2911
-rw-r--r--Documentation/logo.txt15
-rw-r--r--Documentation/memory-barriers.txt129
-rw-r--r--Documentation/memory-hotplug.txt8
-rw-r--r--Documentation/mn10300/ABI.txt2
-rw-r--r--Documentation/mtd/nand_ecc.txt12
-rw-r--r--Documentation/networking/bonding.txt6
-rw-r--r--Documentation/networking/can.txt2
-rw-r--r--Documentation/networking/dm9000.txt2
-rw-r--r--Documentation/networking/l2tp.txt2
-rw-r--r--Documentation/networking/netdevices.txt2
-rw-r--r--Documentation/networking/phonet.txt2
-rw-r--r--Documentation/networking/regulatory.txt2
-rw-r--r--Documentation/power/regulator/consumer.txt2
-rw-r--r--Documentation/power/regulator/overview.txt2
-rw-r--r--Documentation/power/s2ram.txt2
-rw-r--r--Documentation/power/userland-swsusp.txt2
-rw-r--r--Documentation/powerpc/booting-without-of.txt93
-rw-r--r--Documentation/powerpc/dts-bindings/ecm.txt64
-rw-r--r--Documentation/powerpc/dts-bindings/fsl/board.txt2
-rw-r--r--Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm.txt2
-rw-r--r--Documentation/powerpc/dts-bindings/fsl/cpm_qe/gpio.txt2
-rw-r--r--Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe.txt3
-rw-r--r--Documentation/powerpc/dts-bindings/fsl/i2c.txt46
-rw-r--r--Documentation/powerpc/dts-bindings/fsl/mcm.txt64
-rw-r--r--Documentation/powerpc/dts-bindings/fsl/msi-pic.txt2
-rw-r--r--Documentation/powerpc/dts-bindings/fsl/pmc.txt4
-rw-r--r--Documentation/powerpc/dts-bindings/mtd-physmap.txt80
-rw-r--r--Documentation/powerpc/qe_firmware.txt2
-rw-r--r--Documentation/rbtree.txt8
-rw-r--r--Documentation/rfkill.txt18
-rw-r--r--Documentation/s390/Debugging390.txt4
-rw-r--r--Documentation/scheduler/sched-nice-design.txt2
-rw-r--r--Documentation/scheduler/sched-rt-group.txt18
-rw-r--r--Documentation/scsi/aic79xx.txt2
-rw-r--r--Documentation/scsi/ncr53c8xx.txt4
-rw-r--r--Documentation/scsi/scsi_fc_transport.txt14
-rw-r--r--Documentation/scsi/scsi_mid_low_api.txt5
-rw-r--r--Documentation/scsi/sym53c8xx_2.txt2
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt13
-rw-r--r--Documentation/sound/alsa/HD-Audio-Models.txt11
-rw-r--r--Documentation/sound/alsa/HD-Audio.txt6
-rw-r--r--Documentation/sound/alsa/hda_codec.txt2
-rw-r--r--Documentation/sound/alsa/soc/dapm.txt1
-rw-r--r--Documentation/spi/spi-summary6
-rw-r--r--Documentation/sysctl/kernel.txt11
-rw-r--r--Documentation/sysctl/net.txt2
-rw-r--r--Documentation/sysctl/vm.txt8
-rw-r--r--Documentation/sysfs-rules.txt2
-rw-r--r--Documentation/timers/hpet.txt2
-rw-r--r--Documentation/timers/timer_stats.txt2
-rw-r--r--Documentation/tomoyo.txt55
-rw-r--r--Documentation/trace/events.txt135
-rw-r--r--Documentation/trace/ftrace.txt2
-rw-r--r--Documentation/trace/power.txt17
-rw-r--r--Documentation/usb/WUSB-Design-overview.txt8
-rw-r--r--Documentation/usb/anchors.txt4
-rw-r--r--Documentation/video4linux/CARDLIST.cx881
-rw-r--r--Documentation/video4linux/CARDLIST.em28xx1
-rw-r--r--Documentation/video4linux/CARDLIST.saa713418
-rw-r--r--Documentation/video4linux/cx18.txt2
-rw-r--r--Documentation/video4linux/gspca.txt7
-rw-r--r--Documentation/video4linux/pxa_camera.txt49
-rw-r--r--Documentation/video4linux/v4l2-framework.txt5
-rw-r--r--Documentation/vm/00-INDEX2
-rw-r--r--Documentation/vm/active_mm.txt83
-rw-r--r--Documentation/vm/slqbinfo.c1054
-rw-r--r--Documentation/vm/unevictable-lru.txt1041
-rw-r--r--MAINTAINERS181
-rw-r--r--Makefile19
-rw-r--r--arch/alpha/include/asm/barrier.h2
-rw-r--r--arch/alpha/include/asm/futex.h118
-rw-r--r--arch/alpha/include/asm/percpu.h2
-rw-r--r--arch/alpha/include/asm/uaccess.h2
-rw-r--r--arch/alpha/kernel/Makefile6
-rw-r--r--arch/alpha/kernel/binfmt_loader.c2
-rw-r--r--arch/alpha/kernel/err_ev6.c2
-rw-r--r--arch/alpha/kernel/err_ev7.c4
-rw-r--r--arch/alpha/kernel/err_impl.h10
-rw-r--r--arch/alpha/kernel/err_marvel.c2
-rw-r--r--arch/alpha/kernel/err_titan.c4
-rw-r--r--arch/alpha/kernel/head.S3
-rw-r--r--arch/alpha/kernel/osf_sys.c3
-rw-r--r--arch/alpha/kernel/proto.h5
-rw-r--r--arch/alpha/kernel/sys_dp264.c8
-rw-r--r--arch/alpha/kernel/sys_titan.c4
-rw-r--r--arch/alpha/kernel/vmlinux.lds.S2
-rw-r--r--arch/alpha/mm/extable.c40
-rw-r--r--arch/arm/Kconfig228
-rw-r--r--arch/arm/Makefile121
-rw-r--r--arch/arm/common/Kconfig7
-rw-r--r--arch/arm/common/gic.c4
-rw-r--r--arch/arm/common/vic.c230
-rw-r--r--arch/arm/configs/davinci_all_defconfig1784
-rw-r--r--arch/arm/configs/imx27ads_defconfig826
-rw-r--r--arch/arm/configs/kirkwood_defconfig92
-rw-r--r--arch/arm/configs/mv78xx0_defconfig429
-rw-r--r--arch/arm/configs/mx1_defconfig (renamed from arch/arm/configs/mx31ads_defconfig)536
-rw-r--r--arch/arm/configs/mx27_defconfig (renamed from arch/arm/configs/pcm038_defconfig)354
-rw-r--r--arch/arm/configs/mx31moboard_defconfig790
-rw-r--r--arch/arm/configs/mx3_defconfig (renamed from arch/arm/configs/mx31litekit_defconfig)781
-rw-r--r--arch/arm/configs/orion5x_defconfig363
-rw-r--r--arch/arm/configs/s3c2410_defconfig1112
-rw-r--r--arch/arm/configs/stmp378x_defconfig1141
-rw-r--r--arch/arm/configs/stmp37xx_defconfig1002
-rw-r--r--arch/arm/configs/viper_defconfig1
-rw-r--r--arch/arm/include/asm/elf.h16
-rw-r--r--arch/arm/include/asm/hardware/vic.h2
-rw-r--r--arch/arm/include/asm/pgtable.h2
-rw-r--r--arch/arm/include/asm/tlb.h25
-rw-r--r--arch/arm/include/asm/unistd.h2
-rw-r--r--arch/arm/kernel/calls.S2
-rw-r--r--arch/arm/kernel/module.c15
-rw-r--r--arch/arm/kernel/sys_oabi-compat.c20
-rw-r--r--arch/arm/kernel/vmlinux.lds.S2
-rw-r--r--arch/arm/mach-at91/at91rm9200_time.c2
-rw-r--r--arch/arm/mach-at91/at91sam926x_time.c2
-rw-r--r--arch/arm/mach-at91/clock.c151
-rw-r--r--arch/arm/mach-at91/include/mach/at91_pmc.h26
-rw-r--r--arch/arm/mach-davinci/Kconfig47
-rw-r--r--arch/arm/mach-davinci/Makefile9
-rw-r--r--arch/arm/mach-davinci/board-dm644x-evm.c (renamed from arch/arm/mach-davinci/board-evm.c)318
-rw-r--r--arch/arm/mach-davinci/clock.c385
-rw-r--r--arch/arm/mach-davinci/clock.h87
-rw-r--r--arch/arm/mach-davinci/devices.c7
-rw-r--r--arch/arm/mach-davinci/dm644x.c461
-rw-r--r--arch/arm/mach-davinci/dma.c1135
-rw-r--r--arch/arm/mach-davinci/gpio.c82
-rw-r--r--arch/arm/mach-davinci/id.c35
-rw-r--r--arch/arm/mach-davinci/include/mach/board-dm6446evm.h20
-rw-r--r--arch/arm/mach-davinci/include/mach/clkdev.h13
-rw-r--r--arch/arm/mach-davinci/include/mach/clock.h1
-rw-r--r--arch/arm/mach-davinci/include/mach/common.h6
-rw-r--r--arch/arm/mach-davinci/include/mach/cputype.h49
-rw-r--r--arch/arm/mach-davinci/include/mach/dm644x.h37
-rw-r--r--arch/arm/mach-davinci/include/mach/edma.h228
-rw-r--r--arch/arm/mach-davinci/include/mach/gpio.h27
-rw-r--r--arch/arm/mach-davinci/include/mach/hardware.h51
-rw-r--r--arch/arm/mach-davinci/include/mach/io.h20
-rw-r--r--arch/arm/mach-davinci/include/mach/irqs.h103
-rw-r--r--arch/arm/mach-davinci/include/mach/mux.h220
-rw-r--r--arch/arm/mach-davinci/include/mach/psc.h53
-rw-r--r--arch/arm/mach-davinci/include/mach/serial.h21
-rw-r--r--arch/arm/mach-davinci/io.c23
-rw-r--r--arch/arm/mach-davinci/irq.c156
-rw-r--r--arch/arm/mach-davinci/mux.c100
-rw-r--r--arch/arm/mach-davinci/mux.h51
-rw-r--r--arch/arm/mach-davinci/psc.c98
-rw-r--r--arch/arm/mach-davinci/serial.c95
-rw-r--r--arch/arm/mach-davinci/time.c105
-rw-r--r--arch/arm/mach-davinci/usb.c2
-rw-r--r--arch/arm/mach-ep93xx/Kconfig52
-rw-r--r--arch/arm/mach-ep93xx/Makefile8
-rw-r--r--arch/arm/mach-ep93xx/core.c21
-rw-r--r--arch/arm/mach-ep93xx/edb9302.c68
-rw-r--r--arch/arm/mach-ep93xx/edb9302a.c68
-rw-r--r--arch/arm/mach-ep93xx/edb9307.c68
-rw-r--r--arch/arm/mach-ep93xx/edb9307a.c80
-rw-r--r--arch/arm/mach-ep93xx/edb9312.c69
-rw-r--r--arch/arm/mach-ep93xx/edb9315.c68
-rw-r--r--arch/arm/mach-ep93xx/edb9315a.c68
-rw-r--r--arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h1
-rw-r--r--arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h42
-rw-r--r--arch/arm/mach-imx/include/mach/gpio.h1
-rw-r--r--arch/arm/mach-imx/time.c2
-rw-r--r--arch/arm/mach-ixp4xx/common.c2
-rw-r--r--arch/arm/mach-ixp4xx/ixp4xx_npe.c2
-rw-r--r--arch/arm/mach-kirkwood/common.c1
-rw-r--r--arch/arm/mach-kirkwood/include/mach/bridge-regs.h42
-rw-r--r--arch/arm/mach-kirkwood/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-kirkwood/include/mach/entry-macro.S2
-rw-r--r--arch/arm/mach-kirkwood/include/mach/kirkwood.h53
-rw-r--r--arch/arm/mach-kirkwood/include/mach/system.h3
-rw-r--r--arch/arm/mach-kirkwood/irq.c1
-rw-r--r--arch/arm/mach-loki/addr-map.c1
-rw-r--r--arch/arm/mach-loki/include/mach/bridge-regs.h33
-rw-r--r--arch/arm/mach-loki/include/mach/entry-macro.S2
-rw-r--r--arch/arm/mach-loki/include/mach/loki.h14
-rw-r--r--arch/arm/mach-loki/include/mach/system.h3
-rw-r--r--arch/arm/mach-loki/irq.c1
-rw-r--r--arch/arm/mach-mmp/include/mach/irqs.h1
-rw-r--r--arch/arm/mach-mmp/include/mach/mfp-pxa168.h27
-rw-r--r--arch/arm/mach-mmp/include/mach/mfp-pxa910.h8
-rw-r--r--arch/arm/mach-mmp/include/mach/pxa168.h44
-rw-r--r--arch/arm/mach-mmp/include/mach/pxa910.h44
-rw-r--r--arch/arm/mach-mmp/include/mach/regs-apbc.h14
-rw-r--r--arch/arm/mach-mmp/pxa168.c18
-rw-r--r--arch/arm/mach-mmp/pxa910.c18
-rw-r--r--arch/arm/mach-msm/timer.c4
-rw-r--r--arch/arm/mach-mv78xx0/common.c1
-rw-r--r--arch/arm/mach-mv78xx0/include/mach/bridge-regs.h39
-rw-r--r--arch/arm/mach-mv78xx0/include/mach/entry-macro.S2
-rw-r--r--arch/arm/mach-mv78xx0/include/mach/mv78xx0.h42
-rw-r--r--arch/arm/mach-mv78xx0/include/mach/system.h3
-rw-r--r--arch/arm/mach-mv78xx0/irq.c2
-rw-r--r--arch/arm/mach-mx1/mx1ads.c6
-rw-r--r--arch/arm/mach-mx2/clock_imx21.c8
-rw-r--r--arch/arm/mach-mx3/Kconfig2
-rw-r--r--arch/arm/mach-mx3/mx31ads.c4
-rw-r--r--arch/arm/mach-mx3/pcm037.c4
-rw-r--r--arch/arm/mach-mx3/qong.c28
-rw-r--r--arch/arm/mach-netx/generic.c2
-rw-r--r--arch/arm/mach-netx/time.c2
-rw-r--r--arch/arm/mach-ns9xxx/time-ns9360.c2
-rw-r--r--arch/arm/mach-omap1/board-h2-mmc.c14
-rw-r--r--arch/arm/mach-omap1/board-h3-mmc.c6
-rw-r--r--arch/arm/mach-omap1/board-h3.c101
-rw-r--r--arch/arm/mach-omap1/board-nokia770.c6
-rw-r--r--arch/arm/mach-omap1/mcbsp.c4
-rw-r--r--arch/arm/mach-omap1/time.c2
-rw-r--r--arch/arm/mach-omap2/board-h4.c95
-rw-r--r--arch/arm/mach-omap2/board-omap3beagle.c4
-rw-r--r--arch/arm/mach-omap2/board-rx51.c1
-rw-r--r--arch/arm/mach-omap2/clock24xx.c19
-rw-r--r--arch/arm/mach-omap2/clock24xx.h10
-rw-r--r--arch/arm/mach-omap2/clock34xx.h7
-rw-r--r--arch/arm/mach-omap2/devices.c33
-rw-r--r--arch/arm/mach-omap2/irq.c4
-rw-r--r--arch/arm/mach-omap2/timer-gp.c50
-rw-r--r--arch/arm/mach-omap2/usb-musb.c8
-rw-r--r--arch/arm/mach-omap2/usb-tusb6010.c2
-rw-r--r--arch/arm/mach-orion5x/addr-map.c2
-rw-r--r--arch/arm/mach-orion5x/include/mach/bridge-regs.h41
-rw-r--r--arch/arm/mach-orion5x/include/mach/entry-macro.S2
-rw-r--r--arch/arm/mach-orion5x/include/mach/orion5x.h68
-rw-r--r--arch/arm/mach-orion5x/include/mach/system.h3
-rw-r--r--arch/arm/mach-orion5x/irq.c2
-rw-r--r--arch/arm/mach-orion5x/mss2-setup.c1
-rw-r--r--arch/arm/mach-orion5x/pci.c1
-rw-r--r--arch/arm/mach-pxa/Kconfig11
-rw-r--r--arch/arm/mach-pxa/Makefile1
-rw-r--r--arch/arm/mach-pxa/cm-x300.c2
-rw-r--r--arch/arm/mach-pxa/corgi.c57
-rw-r--r--arch/arm/mach-pxa/csb726.c18
-rw-r--r--arch/arm/mach-pxa/devices.c4
-rw-r--r--arch/arm/mach-pxa/em-x270.c8
-rw-r--r--arch/arm/mach-pxa/ezx.c2
-rw-r--r--arch/arm/mach-pxa/generic.h3
-rw-r--r--arch/arm/mach-pxa/imote2.c21
-rw-r--r--arch/arm/mach-pxa/include/mach/audio.h10
-rw-r--r--arch/arm/mach-pxa/include/mach/colibri.h4
-rw-r--r--arch/arm/mach-pxa/include/mach/irqs.h16
-rw-r--r--arch/arm/mach-pxa/include/mach/palmasoc.h7
-rw-r--r--arch/arm/mach-pxa/include/mach/palmt5.h1
-rw-r--r--arch/arm/mach-pxa/include/mach/palmtx.h1
-rw-r--r--arch/arm/mach-pxa/littleton.c28
-rw-r--r--arch/arm/mach-pxa/magician.c12
-rw-r--r--arch/arm/mach-pxa/mainstone.c2
-rw-r--r--arch/arm/mach-pxa/mioa701.c8
-rw-r--r--arch/arm/mach-pxa/palmld.c18
-rw-r--r--arch/arm/mach-pxa/palmt5.c43
-rw-r--r--arch/arm/mach-pxa/palmte2.c32
-rw-r--r--arch/arm/mach-pxa/palmtx.c48
-rw-r--r--arch/arm/mach-pxa/pcm990-baseboard.c31
-rw-r--r--arch/arm/mach-pxa/poodle.c17
-rw-r--r--arch/arm/mach-pxa/pxa27x.c2
-rw-r--r--arch/arm/mach-pxa/pxa3xx.c4
-rw-r--r--arch/arm/mach-pxa/saar.c2
-rw-r--r--arch/arm/mach-pxa/spitz.c65
-rw-r--r--arch/arm/mach-pxa/time.c2
-rw-r--r--arch/arm/mach-pxa/tosa.c2
-rw-r--r--arch/arm/mach-pxa/trizeps4.c2
-rw-r--r--arch/arm/mach-pxa/viper.c2
-rw-r--r--arch/arm/mach-pxa/zylonite_pxa300.c7
-rw-r--r--arch/arm/mach-pxa/zylonite_pxa320.c1
-rw-r--r--arch/arm/mach-realview/core.c2
-rw-r--r--arch/arm/mach-s3c2410/Kconfig8
-rw-r--r--arch/arm/mach-s3c2410/include/mach/map.h2
-rw-r--r--arch/arm/mach-s3c2412/Kconfig3
-rw-r--r--arch/arm/mach-s3c2412/mach-jive.c5
-rw-r--r--arch/arm/mach-s3c2412/pm.c3
-rw-r--r--arch/arm/mach-s3c2440/Kconfig5
-rw-r--r--arch/arm/mach-s3c2440/mach-anubis.c2
-rw-r--r--arch/arm/mach-s3c2440/mach-osiris.c1
-rw-r--r--arch/arm/mach-s3c6400/include/mach/map.h5
-rw-r--r--arch/arm/mach-s3c6400/include/mach/regs-clock.h16
-rw-r--r--arch/arm/mach-s3c6410/Kconfig1
-rw-r--r--arch/arm/mach-s3c6410/mach-smdk6410.c5
-rw-r--r--arch/arm/mach-sa1100/lart.c1
-rw-r--r--arch/arm/mach-stmp378x/Makefile2
-rw-r--r--arch/arm/mach-stmp378x/Makefile.boot3
-rw-r--r--arch/arm/mach-stmp378x/include/mach/entry-macro.S35
-rw-r--r--arch/arm/mach-stmp378x/include/mach/irqs.h95
-rw-r--r--arch/arm/mach-stmp378x/include/mach/pins.h151
-rw-r--r--arch/arm/mach-stmp378x/include/mach/regs-apbh.h88
-rw-r--r--arch/arm/mach-stmp378x/include/mach/regs-apbx.h79
-rw-r--r--arch/arm/mach-stmp378x/include/mach/regs-clkctrl.h276
-rw-r--r--arch/arm/mach-stmp378x/include/mach/regs-icoll.h213
-rw-r--r--arch/arm/mach-stmp378x/include/mach/regs-pinctrl.h143
-rw-r--r--arch/arm/mach-stmp378x/include/mach/regs-power.h32
-rw-r--r--arch/arm/mach-stmp378x/include/mach/regs-timrot.h216
-rw-r--r--arch/arm/mach-stmp378x/stmp378x.c225
-rw-r--r--arch/arm/mach-stmp378x/stmp378x.h24
-rw-r--r--arch/arm/mach-stmp378x/stmp378x_devb.c80
-rw-r--r--arch/arm/mach-stmp37xx/Makefile2
-rw-r--r--arch/arm/mach-stmp37xx/Makefile.boot3
-rw-r--r--arch/arm/mach-stmp37xx/include/mach/entry-macro.S37
-rw-r--r--arch/arm/mach-stmp37xx/include/mach/irqs.h99
-rw-r--r--arch/arm/mach-stmp37xx/include/mach/pins.h147
-rw-r--r--arch/arm/mach-stmp37xx/include/mach/regs-apbh.h102
-rw-r--r--arch/arm/mach-stmp37xx/include/mach/regs-apbx.h109
-rw-r--r--arch/arm/mach-stmp37xx/include/mach/regs-clkctrl.h85
-rw-r--r--arch/arm/mach-stmp37xx/include/mach/regs-icoll.h36
-rw-r--r--arch/arm/mach-stmp37xx/include/mach/regs-pinctrl.h159
-rw-r--r--arch/arm/mach-stmp37xx/include/mach/regs-power.h31
-rw-r--r--arch/arm/mach-stmp37xx/include/mach/regs-timrot.h52
-rw-r--r--arch/arm/mach-stmp37xx/stmp37xx.c217
-rw-r--r--arch/arm/mach-stmp37xx/stmp37xx.h24
-rw-r--r--arch/arm/mach-stmp37xx/stmp37xx_devb.c83
-rw-r--r--arch/arm/mach-u300/Kconfig105
-rw-r--r--arch/arm/mach-u300/Makefile11
-rw-r--r--arch/arm/mach-u300/clock.c1487
-rw-r--r--arch/arm/mach-u300/clock.h53
-rw-r--r--arch/arm/mach-u300/core.c649
-rw-r--r--arch/arm/mach-u300/gpio.c701
-rw-r--r--arch/arm/mach-u300/include/mach/clkdev.h7
-rw-r--r--arch/arm/mach-u300/include/mach/debug-macro.S22
-rw-r--r--arch/arm/mach-u300/include/mach/entry-macro.S40
-rw-r--r--arch/arm/mach-u300/include/mach/gpio.h290
-rw-r--r--arch/arm/mach-u300/include/mach/hardware.h5
-rw-r--r--arch/arm/mach-u300/include/mach/io.h20
-rw-r--r--arch/arm/mach-u300/include/mach/irqs.h114
-rw-r--r--arch/arm/mach-u300/include/mach/memory.h42
-rw-r--r--arch/arm/mach-u300/include/mach/platform.h19
-rw-r--r--arch/arm/mach-u300/include/mach/syscon.h644
-rw-r--r--arch/arm/mach-u300/include/mach/system.h42
-rw-r--r--arch/arm/mach-u300/include/mach/timex.h17
-rw-r--r--arch/arm/mach-u300/include/mach/u300-regs.h187
-rw-r--r--arch/arm/mach-u300/include/mach/uncompress.h46
-rw-r--r--arch/arm/mach-u300/include/mach/vmalloc.h12
-rw-r--r--arch/arm/mach-u300/mmc.c216
-rw-r--r--arch/arm/mach-u300/mmc.h18
-rw-r--r--arch/arm/mach-u300/padmux.c58
-rw-r--r--arch/arm/mach-u300/padmux.h19
-rw-r--r--arch/arm/mach-u300/timer.c422
-rw-r--r--arch/arm/mach-u300/u300.c55
-rw-r--r--arch/arm/mach-versatile/core.c4
-rw-r--r--arch/arm/mach-w90x900/include/mach/irqs.h49
-rw-r--r--arch/arm/mach-w90x900/include/mach/map.h101
-rw-r--r--arch/arm/mach-w90x900/include/mach/regs-clock.h31
-rw-r--r--arch/arm/mach-w90x900/include/mach/regs-usb.h35
-rw-r--r--arch/arm/mach-w90x900/mach-w90p910evb.c89
-rw-r--r--arch/arm/mach-w90x900/w90p910.c9
-rw-r--r--arch/arm/mm/cache-v6.S33
-rw-r--r--arch/arm/mm/flush.c23
-rw-r--r--arch/arm/mm/mmu.c14
-rw-r--r--arch/arm/mm/proc-v6.S3
-rw-r--r--arch/arm/mm/proc-v7.S22
-rw-r--r--arch/arm/mm/tlb-v6.S3
-rw-r--r--arch/arm/mm/tlb-v7.S3
-rw-r--r--arch/arm/plat-mxc/dma-mx1-mx2.c17
-rw-r--r--arch/arm/plat-mxc/gpio.c2
-rw-r--r--arch/arm/plat-mxc/include/mach/board-mx27ads.h2
-rw-r--r--arch/arm/plat-mxc/include/mach/imx-uart.h2
-rw-r--r--arch/arm/plat-mxc/include/mach/iomux-mx3.h48
-rw-r--r--arch/arm/plat-mxc/include/mach/irqs.h2
-rw-r--r--arch/arm/plat-mxc/include/mach/mx21.h3
-rw-r--r--arch/arm/plat-mxc/irq.c14
-rw-r--r--arch/arm/plat-mxc/time.c2
-rw-r--r--arch/arm/plat-omap/clock.c7
-rw-r--r--arch/arm/plat-omap/common.c4
-rw-r--r--arch/arm/plat-omap/dma.c13
-rw-r--r--arch/arm/plat-omap/dmtimer.c28
-rw-r--r--arch/arm/plat-omap/gpio.c20
-rw-r--r--arch/arm/plat-omap/include/mach/dmtimer.h2
-rw-r--r--arch/arm/plat-omap/include/mach/eac.h100
-rw-r--r--arch/arm/plat-omap/include/mach/gpioexpander.h35
-rw-r--r--arch/arm/plat-omap/include/mach/irda.h4
-rw-r--r--arch/arm/plat-omap/include/mach/mmc.h1
-rw-r--r--arch/arm/plat-omap/include/mach/timer-gp.h17
-rw-r--r--arch/arm/plat-omap/mailbox.c54
-rw-r--r--arch/arm/plat-orion/time.c4
-rw-r--r--arch/arm/plat-pxa/Makefile2
-rw-r--r--arch/arm/plat-pxa/gpio.c23
-rw-r--r--arch/arm/plat-pxa/include/plat/i2c.h (renamed from arch/arm/mach-pxa/include/mach/i2c.h)0
-rw-r--r--arch/arm/plat-pxa/pwm.c (renamed from arch/arm/mach-pxa/pwm.c)119
-rw-r--r--arch/arm/plat-s3c/Kconfig14
-rw-r--r--arch/arm/plat-s3c/Makefile2
-rw-r--r--arch/arm/plat-s3c/dev-usb.c50
-rw-r--r--arch/arm/plat-s3c/gpio-config.c3
-rw-r--r--arch/arm/plat-s3c/gpio.c11
-rw-r--r--arch/arm/plat-s3c/include/plat/cpu.h3
-rw-r--r--arch/arm/plat-s3c/include/plat/devs.h1
-rw-r--r--arch/arm/plat-s3c/include/plat/gpio-core.h30
-rw-r--r--arch/arm/plat-s3c/include/plat/pm.h15
-rw-r--r--arch/arm/plat-s3c/include/plat/regs-serial.h5
-rw-r--r--arch/arm/plat-s3c/pm-gpio.c380
-rw-r--r--arch/arm/plat-s3c/pm.c19
-rw-r--r--arch/arm/plat-s3c24xx/adc.c19
-rw-r--r--arch/arm/plat-s3c24xx/devs.c30
-rw-r--r--arch/arm/plat-s3c24xx/gpiolib.c10
-rw-r--r--arch/arm/plat-s3c24xx/include/plat/map.h1
-rw-r--r--arch/arm/plat-s3c24xx/include/plat/pm-core.h5
-rw-r--r--arch/arm/plat-s3c24xx/pm.c213
-rw-r--r--arch/arm/plat-s3c64xx/Kconfig1
-rw-r--r--arch/arm/plat-s3c64xx/Makefile6
-rw-r--r--arch/arm/plat-s3c64xx/cpu.c19
-rw-r--r--arch/arm/plat-s3c64xx/gpiolib.c10
-rw-r--r--arch/arm/plat-s3c64xx/include/plat/irqs.h1
-rw-r--r--arch/arm/plat-s3c64xx/include/plat/pm-core.h98
-rw-r--r--arch/arm/plat-s3c64xx/include/plat/regs-clock.h1
-rw-r--r--arch/arm/plat-s3c64xx/irq-eint.c3
-rw-r--r--arch/arm/plat-s3c64xx/irq-pm.c111
-rw-r--r--arch/arm/plat-s3c64xx/irq.c9
-rw-r--r--arch/arm/plat-s3c64xx/pm.c175
-rw-r--r--arch/arm/plat-s3c64xx/sleep.S144
-rw-r--r--arch/arm/plat-stmp3xxx/Kconfig37
-rw-r--r--arch/arm/plat-stmp3xxx/Makefile5
-rw-r--r--arch/arm/plat-stmp3xxx/clock.c1112
-rw-r--r--arch/arm/plat-stmp3xxx/clock.h61
-rw-r--r--arch/arm/plat-stmp3xxx/core.c127
-rw-r--r--arch/arm/plat-stmp3xxx/dma.c462
-rw-r--r--arch/arm/plat-stmp3xxx/include/mach/clkdev.h18
-rw-r--r--arch/arm/plat-stmp3xxx/include/mach/cputype.h33
-rw-r--r--arch/arm/plat-stmp3xxx/include/mach/debug-macro.S42
-rw-r--r--arch/arm/plat-stmp3xxx/include/mach/dma.h155
-rw-r--r--arch/arm/plat-stmp3xxx/include/mach/gpio.h28
-rw-r--r--arch/arm/plat-stmp3xxx/include/mach/hardware.h32
-rw-r--r--arch/arm/plat-stmp3xxx/include/mach/io.h25
-rw-r--r--arch/arm/plat-stmp3xxx/include/mach/memory.h22
-rw-r--r--arch/arm/plat-stmp3xxx/include/mach/pinmux.h158
-rw-r--r--arch/arm/plat-stmp3xxx/include/mach/pins.h30
-rw-r--r--arch/arm/plat-stmp3xxx/include/mach/platform.h47
-rw-r--r--arch/arm/plat-stmp3xxx/include/mach/stmp3xxx.h34
-rw-r--r--arch/arm/plat-stmp3xxx/include/mach/stmp3xxx_regs.h195
-rw-r--r--arch/arm/plat-stmp3xxx/include/mach/system.h47
-rw-r--r--arch/arm/plat-stmp3xxx/include/mach/timex.h20
-rw-r--r--arch/arm/plat-stmp3xxx/include/mach/uncompress.h53
-rw-r--r--arch/arm/plat-stmp3xxx/include/mach/vmalloc.h12
-rw-r--r--arch/arm/plat-stmp3xxx/irq.c59
-rw-r--r--arch/arm/plat-stmp3xxx/pinmux.c545
-rw-r--r--arch/arm/plat-stmp3xxx/timer.c172
-rw-r--r--arch/avr32/Makefile2
-rw-r--r--arch/avr32/boards/merisc/setup.c7
-rw-r--r--arch/avr32/kernel/time.c2
-rw-r--r--arch/blackfin/kernel/time-ts.c12
-rw-r--r--arch/cris/Makefile14
-rw-r--r--arch/cris/arch-v10/boot/compressed/README25
-rw-r--r--arch/cris/arch-v10/boot/compressed/misc.c246
-rw-r--r--arch/cris/arch-v10/kernel/entry.S14
-rw-r--r--arch/cris/arch-v32/boot/Makefile20
-rw-r--r--arch/cris/arch-v32/boot/compressed/Makefile26
-rw-r--r--arch/cris/arch-v32/boot/rescue/Makefile26
-rw-r--r--arch/cris/arch-v32/drivers/mach-a3/gpio.c4
-rw-r--r--arch/cris/arch-v32/kernel/Makefile2
-rw-r--r--arch/cris/arch-v32/kernel/entry.S8
-rw-r--r--arch/cris/arch-v32/kernel/irq.c4
-rw-r--r--arch/cris/boot/.gitignore (renamed from arch/cris/arch-v10/boot/.gitignore)0
-rw-r--r--arch/cris/boot/Makefile (renamed from arch/cris/arch-v10/boot/Makefile)8
-rw-r--r--arch/cris/boot/compressed/Makefile (renamed from arch/cris/arch-v10/boot/compressed/Makefile)19
-rw-r--r--arch/cris/boot/compressed/README (renamed from arch/cris/arch-v32/boot/compressed/README)0
-rw-r--r--arch/cris/boot/compressed/decompress_v10.lds (renamed from arch/cris/arch-v10/boot/compressed/decompress.lds)0
-rw-r--r--arch/cris/boot/compressed/decompress_v32.lds (renamed from arch/cris/arch-v32/boot/compressed/decompress.lds)0
-rw-r--r--arch/cris/boot/compressed/head_v10.S (renamed from arch/cris/arch-v10/boot/compressed/head.S)4
-rw-r--r--arch/cris/boot/compressed/head_v32.S (renamed from arch/cris/arch-v32/boot/compressed/head.S)10
-rw-r--r--arch/cris/boot/compressed/misc.c (renamed from arch/cris/arch-v32/boot/compressed/misc.c)193
-rw-r--r--arch/cris/boot/rescue/Makefile (renamed from arch/cris/arch-v10/boot/rescue/Makefile)22
-rw-r--r--arch/cris/boot/rescue/head_v10.S (renamed from arch/cris/arch-v10/boot/rescue/head.S)2
-rw-r--r--arch/cris/boot/rescue/head_v32.S (renamed from arch/cris/arch-v32/boot/rescue/head.S)0
-rw-r--r--arch/cris/boot/rescue/kimagerescue.S (renamed from arch/cris/arch-v10/boot/rescue/kimagerescue.S)0
-rw-r--r--arch/cris/boot/rescue/rescue_v10.lds (renamed from arch/cris/arch-v10/boot/rescue/rescue.lds)0
-rw-r--r--arch/cris/boot/rescue/rescue_v32.lds (renamed from arch/cris/arch-v32/boot/rescue/rescue.lds)0
-rw-r--r--arch/cris/boot/rescue/testrescue.S (renamed from arch/cris/arch-v10/boot/rescue/testrescue.S)0
-rw-r--r--arch/cris/boot/tools/build.c (renamed from arch/cris/arch-v10/boot/tools/build.c)0
-rw-r--r--arch/cris/include/asm/unistd.h12
-rw-r--r--arch/frv/include/asm/bug.h5
-rw-r--r--arch/frv/include/asm/gdb-stub.h1
-rw-r--r--arch/frv/include/asm/init.h12
-rw-r--r--arch/frv/include/asm/unistd.h4
-rw-r--r--arch/frv/kernel/entry.S2
-rw-r--r--arch/frv/kernel/head-mmu-fr451.S3
-rw-r--r--arch/frv/kernel/head-uc-fr401.S3
-rw-r--r--arch/frv/kernel/head-uc-fr451.S3
-rw-r--r--arch/frv/kernel/head-uc-fr555.S3
-rw-r--r--arch/frv/kernel/head.S3
-rw-r--r--arch/frv/kernel/setup.c1
-rw-r--r--arch/frv/kernel/vmlinux.lds.S2
-rw-r--r--arch/frv/mb93090-mb00/pci-vdk.c63
-rw-r--r--arch/h8300/include/asm/timer.h (renamed from include/asm-h8300/timer.h)0
-rw-r--r--arch/ia64/hp/sim/hpsim_irq.c3
-rw-r--r--arch/ia64/include/asm/idle.h7
-rw-r--r--arch/ia64/include/asm/iommu.h1
-rw-r--r--arch/ia64/include/asm/kvm_host.h5
-rw-r--r--arch/ia64/include/asm/paravirt_privop.h2
-rw-r--r--arch/ia64/include/asm/pgtable.h2
-rw-r--r--arch/ia64/include/asm/smp.h2
-rw-r--r--arch/ia64/include/asm/xen/events.h7
-rw-r--r--arch/ia64/kernel/acpi.c5
-rw-r--r--arch/ia64/kernel/cyclone.c2
-rw-r--r--arch/ia64/kernel/iosapic.c10
-rw-r--r--arch/ia64/kernel/irq_ia64.c3
-rw-r--r--arch/ia64/kernel/msi_ia64.c16
-rw-r--r--arch/ia64/kernel/pci-dma.c2
-rw-r--r--arch/ia64/kernel/pci-swiotlb.c4
-rw-r--r--arch/ia64/kernel/smp.c14
-rw-r--r--arch/ia64/kernel/time.c4
-rw-r--r--arch/ia64/kvm/Kconfig2
-rw-r--r--arch/ia64/kvm/kvm-ia64.c267
-rw-r--r--arch/ia64/kvm/kvm_fw.c28
-rw-r--r--arch/ia64/kvm/lapic.h6
-rw-r--r--arch/ia64/kvm/optvfault.S30
-rw-r--r--arch/ia64/kvm/process.c5
-rw-r--r--arch/ia64/kvm/vcpu.c20
-rw-r--r--arch/ia64/kvm/vmm.c12
-rw-r--r--arch/ia64/kvm/vmm_ivt.S18
-rw-r--r--arch/ia64/kvm/vtlb.c3
-rw-r--r--arch/ia64/sn/kernel/irq.c4
-rw-r--r--arch/ia64/sn/kernel/msi_sn.c8
-rw-r--r--arch/ia64/sn/kernel/sn2/timer.c2
-rw-r--r--arch/ia64/xen/xensetup.S2
-rw-r--r--arch/m32r/boot/compressed/Makefile1
-rw-r--r--arch/m32r/include/asm/Kbuild (renamed from include/asm-m32r/Kbuild)0
-rw-r--r--arch/m32r/include/asm/addrspace.h (renamed from include/asm-m32r/addrspace.h)0
-rw-r--r--arch/m32r/include/asm/assembler.h (renamed from include/asm-m32r/assembler.h)7
-rw-r--r--arch/m32r/include/asm/atomic.h (renamed from include/asm-m32r/atomic.h)0
-rw-r--r--arch/m32r/include/asm/auxvec.h (renamed from include/asm-m32r/auxvec.h)0
-rw-r--r--arch/m32r/include/asm/bitops.h (renamed from include/asm-m32r/bitops.h)0
-rw-r--r--arch/m32r/include/asm/bug.h (renamed from include/asm-m32r/bug.h)0
-rw-r--r--arch/m32r/include/asm/bugs.h (renamed from include/asm-m32r/bugs.h)0
-rw-r--r--arch/m32r/include/asm/byteorder.h (renamed from include/asm-m32r/byteorder.h)0
-rw-r--r--arch/m32r/include/asm/cache.h (renamed from include/asm-m32r/cache.h)0
-rw-r--r--arch/m32r/include/asm/cachectl.h (renamed from include/asm-m32r/cachectl.h)0
-rw-r--r--arch/m32r/include/asm/cacheflush.h (renamed from include/asm-m32r/cacheflush.h)0
-rw-r--r--arch/m32r/include/asm/checksum.h (renamed from include/asm-m32r/checksum.h)0
-rw-r--r--arch/m32r/include/asm/cputime.h (renamed from include/asm-m32r/cputime.h)0
-rw-r--r--arch/m32r/include/asm/current.h (renamed from include/asm-m32r/current.h)0
-rw-r--r--arch/m32r/include/asm/delay.h (renamed from include/asm-m32r/delay.h)0
-rw-r--r--arch/m32r/include/asm/device.h (renamed from include/asm-m32r/device.h)0
-rw-r--r--arch/m32r/include/asm/div64.h (renamed from include/asm-m32r/div64.h)0
-rw-r--r--arch/m32r/include/asm/dma.h (renamed from include/asm-m32r/dma.h)0
-rw-r--r--arch/m32r/include/asm/elf.h (renamed from include/asm-m32r/elf.h)0
-rw-r--r--arch/m32r/include/asm/emergency-restart.h (renamed from include/asm-m32r/emergency-restart.h)0
-rw-r--r--arch/m32r/include/asm/errno.h (renamed from include/asm-m32r/errno.h)0
-rw-r--r--arch/m32r/include/asm/fb.h (renamed from include/asm-m32r/fb.h)0
-rw-r--r--arch/m32r/include/asm/fcntl.h (renamed from include/asm-m32r/fcntl.h)0
-rw-r--r--arch/m32r/include/asm/flat.h (renamed from include/asm-m32r/flat.h)0
-rw-r--r--arch/m32r/include/asm/ftrace.h (renamed from include/asm-m32r/ftrace.h)0
-rw-r--r--arch/m32r/include/asm/futex.h (renamed from include/asm-m32r/futex.h)0
-rw-r--r--arch/m32r/include/asm/hardirq.h (renamed from include/asm-m32r/hardirq.h)0
-rw-r--r--arch/m32r/include/asm/hw_irq.h (renamed from include/asm-m32r/hw_irq.h)0
-rw-r--r--arch/m32r/include/asm/io.h (renamed from include/asm-m32r/io.h)0
-rw-r--r--arch/m32r/include/asm/ioctl.h (renamed from include/asm-m32r/ioctl.h)0
-rw-r--r--arch/m32r/include/asm/ioctls.h (renamed from include/asm-m32r/ioctls.h)0
-rw-r--r--arch/m32r/include/asm/ipcbuf.h (renamed from include/asm-m32r/ipcbuf.h)0
-rw-r--r--arch/m32r/include/asm/irq.h (renamed from include/asm-m32r/irq.h)0
-rw-r--r--arch/m32r/include/asm/irq_regs.h (renamed from include/asm-m32r/irq_regs.h)0
-rw-r--r--arch/m32r/include/asm/kdebug.h (renamed from include/asm-m32r/kdebug.h)0
-rw-r--r--arch/m32r/include/asm/kmap_types.h (renamed from include/asm-m32r/kmap_types.h)0
-rw-r--r--arch/m32r/include/asm/linkage.h (renamed from include/asm-m32r/linkage.h)0
-rw-r--r--arch/m32r/include/asm/local.h (renamed from include/asm-m32r/local.h)0
-rw-r--r--arch/m32r/include/asm/m32102.h (renamed from include/asm-m32r/m32102.h)0
-rw-r--r--arch/m32r/include/asm/m32104ut/m32104ut_pld.h (renamed from include/asm-m32r/m32104ut/m32104ut_pld.h)0
-rw-r--r--arch/m32r/include/asm/m32700ut/m32700ut_lan.h (renamed from include/asm-m32r/m32700ut/m32700ut_lan.h)0
-rw-r--r--arch/m32r/include/asm/m32700ut/m32700ut_lcd.h (renamed from include/asm-m32r/m32700ut/m32700ut_lcd.h)0
-rw-r--r--arch/m32r/include/asm/m32700ut/m32700ut_pld.h (renamed from include/asm-m32r/m32700ut/m32700ut_pld.h)0
-rw-r--r--arch/m32r/include/asm/m32r.h (renamed from include/asm-m32r/m32r.h)0
-rw-r--r--arch/m32r/include/asm/m32r_mp_fpga.h (renamed from include/asm-m32r/m32r_mp_fpga.h)0
-rw-r--r--arch/m32r/include/asm/mappi2/mappi2_pld.h (renamed from include/asm-m32r/mappi2/mappi2_pld.h)0
-rw-r--r--arch/m32r/include/asm/mappi3/mappi3_pld.h (renamed from include/asm-m32r/mappi3/mappi3_pld.h)0
-rw-r--r--arch/m32r/include/asm/mc146818rtc.h (renamed from include/asm-m32r/mc146818rtc.h)0
-rw-r--r--arch/m32r/include/asm/mman.h (renamed from include/asm-m32r/mman.h)0
-rw-r--r--arch/m32r/include/asm/mmu.h (renamed from include/asm-m32r/mmu.h)0
-rw-r--r--arch/m32r/include/asm/mmu_context.h (renamed from include/asm-m32r/mmu_context.h)0
-rw-r--r--arch/m32r/include/asm/mmzone.h (renamed from include/asm-m32r/mmzone.h)0
-rw-r--r--arch/m32r/include/asm/module.h (renamed from include/asm-m32r/module.h)0
-rw-r--r--arch/m32r/include/asm/msgbuf.h (renamed from include/asm-m32r/msgbuf.h)0
-rw-r--r--arch/m32r/include/asm/mutex.h (renamed from include/asm-m32r/mutex.h)0
-rw-r--r--arch/m32r/include/asm/opsput/opsput_lan.h (renamed from include/asm-m32r/opsput/opsput_lan.h)0
-rw-r--r--arch/m32r/include/asm/opsput/opsput_lcd.h (renamed from include/asm-m32r/opsput/opsput_lcd.h)0
-rw-r--r--arch/m32r/include/asm/opsput/opsput_pld.h (renamed from include/asm-m32r/opsput/opsput_pld.h)0
-rw-r--r--arch/m32r/include/asm/page.h (renamed from include/asm-m32r/page.h)0
-rw-r--r--arch/m32r/include/asm/param.h (renamed from include/asm-m32r/param.h)0
-rw-r--r--arch/m32r/include/asm/pci.h (renamed from include/asm-m32r/pci.h)0
-rw-r--r--arch/m32r/include/asm/percpu.h (renamed from include/asm-m32r/percpu.h)0
-rw-r--r--arch/m32r/include/asm/pgalloc.h (renamed from include/asm-m32r/pgalloc.h)0
-rw-r--r--arch/m32r/include/asm/pgtable-2level.h (renamed from include/asm-m32r/pgtable-2level.h)0
-rw-r--r--arch/m32r/include/asm/pgtable.h (renamed from include/asm-m32r/pgtable.h)0
-rw-r--r--arch/m32r/include/asm/poll.h (renamed from include/asm-m32r/poll.h)0
-rw-r--r--arch/m32r/include/asm/posix_types.h (renamed from include/asm-m32r/posix_types.h)0
-rw-r--r--arch/m32r/include/asm/processor.h (renamed from include/asm-m32r/processor.h)0
-rw-r--r--arch/m32r/include/asm/ptrace.h (renamed from include/asm-m32r/ptrace.h)0
-rw-r--r--arch/m32r/include/asm/resource.h (renamed from include/asm-m32r/resource.h)0
-rw-r--r--arch/m32r/include/asm/rtc.h (renamed from include/asm-m32r/rtc.h)0
-rw-r--r--arch/m32r/include/asm/s1d13806.h (renamed from include/asm-m32r/s1d13806.h)0
-rw-r--r--arch/m32r/include/asm/scatterlist.h (renamed from include/asm-m32r/scatterlist.h)0
-rw-r--r--arch/m32r/include/asm/sections.h (renamed from include/asm-m32r/sections.h)0
-rw-r--r--arch/m32r/include/asm/segment.h (renamed from include/asm-m32r/segment.h)0
-rw-r--r--arch/m32r/include/asm/sembuf.h (renamed from include/asm-m32r/sembuf.h)0
-rw-r--r--arch/m32r/include/asm/serial.h (renamed from include/asm-m32r/serial.h)0
-rw-r--r--arch/m32r/include/asm/setup.h (renamed from include/asm-m32r/setup.h)0
-rw-r--r--arch/m32r/include/asm/shmbuf.h (renamed from include/asm-m32r/shmbuf.h)0
-rw-r--r--arch/m32r/include/asm/shmparam.h (renamed from include/asm-m32r/shmparam.h)0
-rw-r--r--arch/m32r/include/asm/sigcontext.h (renamed from include/asm-m32r/sigcontext.h)0
-rw-r--r--arch/m32r/include/asm/siginfo.h (renamed from include/asm-m32r/siginfo.h)0
-rw-r--r--arch/m32r/include/asm/signal.h (renamed from include/asm-m32r/signal.h)0
-rw-r--r--arch/m32r/include/asm/smp.h (renamed from include/asm-m32r/smp.h)0
-rw-r--r--arch/m32r/include/asm/socket.h (renamed from include/asm-m32r/socket.h)0
-rw-r--r--arch/m32r/include/asm/sockios.h (renamed from include/asm-m32r/sockios.h)0
-rw-r--r--arch/m32r/include/asm/spinlock.h (renamed from include/asm-m32r/spinlock.h)0
-rw-r--r--arch/m32r/include/asm/spinlock_types.h (renamed from include/asm-m32r/spinlock_types.h)0
-rw-r--r--arch/m32r/include/asm/stat.h (renamed from include/asm-m32r/stat.h)0
-rw-r--r--arch/m32r/include/asm/statfs.h (renamed from include/asm-m32r/statfs.h)0
-rw-r--r--arch/m32r/include/asm/string.h (renamed from include/asm-m32r/string.h)0
-rw-r--r--arch/m32r/include/asm/swab.h (renamed from include/asm-m32r/swab.h)0
-rw-r--r--arch/m32r/include/asm/syscall.h (renamed from include/asm-m32r/syscall.h)0
-rw-r--r--arch/m32r/include/asm/system.h (renamed from include/asm-m32r/system.h)0
-rw-r--r--arch/m32r/include/asm/termbits.h (renamed from include/asm-m32r/termbits.h)0
-rw-r--r--arch/m32r/include/asm/termios.h (renamed from include/asm-m32r/termios.h)0
-rw-r--r--arch/m32r/include/asm/thread_info.h (renamed from include/asm-m32r/thread_info.h)0
-rw-r--r--arch/m32r/include/asm/timex.h (renamed from include/asm-m32r/timex.h)0
-rw-r--r--arch/m32r/include/asm/tlb.h (renamed from include/asm-m32r/tlb.h)0
-rw-r--r--arch/m32r/include/asm/tlbflush.h (renamed from include/asm-m32r/tlbflush.h)0
-rw-r--r--arch/m32r/include/asm/topology.h (renamed from include/asm-m32r/topology.h)0
-rw-r--r--arch/m32r/include/asm/types.h (renamed from include/asm-m32r/types.h)0
-rw-r--r--arch/m32r/include/asm/uaccess.h (renamed from include/asm-m32r/uaccess.h)0
-rw-r--r--arch/m32r/include/asm/ucontext.h (renamed from include/asm-m32r/ucontext.h)0
-rw-r--r--arch/m32r/include/asm/unaligned.h (renamed from include/asm-m32r/unaligned.h)0
-rw-r--r--arch/m32r/include/asm/unistd.h (renamed from include/asm-m32r/unistd.h)0
-rw-r--r--arch/m32r/include/asm/user.h (renamed from include/asm-m32r/user.h)0
-rw-r--r--arch/m32r/include/asm/vga.h (renamed from include/asm-m32r/vga.h)0
-rw-r--r--arch/m32r/include/asm/xor.h (renamed from include/asm-m32r/xor.h)0
-rw-r--r--arch/m32r/kernel/Makefile2
-rw-r--r--arch/m32r/kernel/head.S2
-rw-r--r--arch/m32r/kernel/vmlinux.lds.S2
-rw-r--r--arch/m68k/configs/amiga_defconfig163
-rw-r--r--arch/m68k/configs/apollo_defconfig120
-rw-r--r--arch/m68k/configs/atari_defconfig155
-rw-r--r--arch/m68k/configs/bvme6000_defconfig119
-rw-r--r--arch/m68k/configs/hp300_defconfig120
-rw-r--r--arch/m68k/configs/mac_defconfig125
-rw-r--r--arch/m68k/configs/multi_defconfig157
-rw-r--r--arch/m68k/configs/mvme147_defconfig119
-rw-r--r--arch/m68k/configs/mvme16x_defconfig119
-rw-r--r--arch/m68k/configs/q40_defconfig122
-rw-r--r--arch/m68k/configs/sun3_defconfig120
-rw-r--r--arch/m68k/configs/sun3x_defconfig120
-rw-r--r--arch/m68k/include/asm/checksum.h160
-rw-r--r--arch/m68k/include/asm/checksum_mm.h148
-rw-r--r--arch/m68k/include/asm/checksum_no.h132
-rw-r--r--arch/m68k/include/asm/dma.h493
-rw-r--r--arch/m68k/include/asm/dma_mm.h16
-rw-r--r--arch/m68k/include/asm/dma_no.h494
-rw-r--r--arch/m68k/include/asm/hardirq.h21
-rw-r--r--arch/m68k/include/asm/hardirq_mm.h16
-rw-r--r--arch/m68k/include/asm/hardirq_no.h27
-rw-r--r--arch/m68k/include/asm/irq.h135
-rw-r--r--arch/m68k/include/asm/irq_mm.h126
-rw-r--r--arch/m68k/include/asm/irq_no.h26
-rw-r--r--arch/m68k/include/asm/m520xsim.h28
-rw-r--r--arch/m68k/include/asm/m523xsim.h9
-rw-r--r--arch/m68k/include/asm/m527xsim.h9
-rw-r--r--arch/m68k/include/asm/m528xsim.h8
-rw-r--r--arch/m68k/include/asm/m532xsim.h55
-rw-r--r--arch/m68k/include/asm/mcfsim.h14
-rw-r--r--arch/m68k/include/asm/processor.h171
-rw-r--r--arch/m68k/include/asm/processor_mm.h130
-rw-r--r--arch/m68k/include/asm/processor_no.h143
-rw-r--r--arch/m68k/include/asm/system_no.h107
-rw-r--r--arch/m68k/include/asm/unistd.h4
-rw-r--r--arch/m68k/kernel/entry.S2
-rw-r--r--arch/m68k/kernel/head.S2
-rw-r--r--arch/m68k/kernel/sun3-head.S3
-rw-r--r--arch/m68k/kernel/vmlinux-std.lds2
-rw-r--r--arch/m68k/kernel/vmlinux-sun3.lds2
-rw-r--r--arch/m68knommu/Kconfig1
-rw-r--r--arch/m68knommu/configs/m5208evb_defconfig163
-rw-r--r--arch/m68knommu/configs/m5249evb_defconfig268
-rw-r--r--arch/m68knommu/configs/m5272c3_defconfig (renamed from arch/arm/configs/pcm037_defconfig)556
-rw-r--r--arch/m68knommu/configs/m5275evb_defconfig167
-rw-r--r--arch/m68knommu/configs/m5307c3_defconfig231
-rw-r--r--arch/m68knommu/configs/m5407c3_defconfig179
-rw-r--r--arch/m68knommu/kernel/asm-offsets.c6
-rw-r--r--arch/m68knommu/kernel/dma.c37
-rw-r--r--arch/m68knommu/kernel/entry.S1
-rw-r--r--arch/m68knommu/kernel/irq.c21
-rw-r--r--arch/m68knommu/kernel/syscalltable.S2
-rw-r--r--arch/m68knommu/kernel/vmlinux.lds.S2
-rw-r--r--arch/m68knommu/lib/checksum.c9
-rw-r--r--arch/m68knommu/platform/5206/config.c18
-rw-r--r--arch/m68knommu/platform/5206e/config.c18
-rw-r--r--arch/m68knommu/platform/520x/config.c35
-rw-r--r--arch/m68knommu/platform/523x/config.c69
-rw-r--r--arch/m68knommu/platform/5249/config.c18
-rw-r--r--arch/m68knommu/platform/5272/config.c18
-rw-r--r--arch/m68knommu/platform/527x/config.c59
-rw-r--r--arch/m68knommu/platform/528x/config.c54
-rw-r--r--arch/m68knommu/platform/5307/config.c16
-rw-r--r--arch/m68knommu/platform/532x/config.c44
-rw-r--r--arch/m68knommu/platform/5407/config.c16
-rw-r--r--arch/m68knommu/platform/68328/ints.c72
-rw-r--r--arch/m68knommu/platform/68328/timers.c2
-rw-r--r--arch/m68knommu/platform/68360/ints.c44
-rw-r--r--arch/m68knommu/platform/coldfire/Makefile22
-rw-r--r--arch/m68knommu/platform/coldfire/dma_timer.c2
-rw-r--r--arch/m68knommu/platform/coldfire/intc-2.c93
-rw-r--r--arch/m68knommu/platform/coldfire/intc-simr.c78
-rw-r--r--arch/m68knommu/platform/coldfire/intc.c55
-rw-r--r--arch/m68knommu/platform/coldfire/pit.c10
-rw-r--r--arch/m68knommu/platform/coldfire/timers.c2
-rw-r--r--arch/m68knommu/platform/coldfire/vectors.c27
-rw-r--r--arch/microblaze/Makefile8
-rw-r--r--arch/microblaze/include/asm/auxvec.h1
-rw-r--r--arch/microblaze/include/asm/cache.h5
-rw-r--r--arch/microblaze/include/asm/cputable.h1
-rw-r--r--arch/microblaze/include/asm/entry.h4
-rw-r--r--arch/microblaze/include/asm/exceptions.h3
-rw-r--r--arch/microblaze/include/asm/ftrace.h1
-rw-r--r--arch/microblaze/include/asm/hw_irq.h1
-rw-r--r--arch/microblaze/include/asm/io.h1
-rw-r--r--arch/microblaze/include/asm/of_platform.h10
-rw-r--r--arch/microblaze/include/asm/processor.h21
-rw-r--r--arch/microblaze/include/asm/ptrace.h4
-rw-r--r--arch/microblaze/include/asm/socket.h3
-rw-r--r--arch/microblaze/include/asm/unistd.h4
-rw-r--r--arch/microblaze/include/asm/user.h1
-rw-r--r--arch/microblaze/include/asm/vga.h1
-rw-r--r--arch/microblaze/kernel/asm-offsets.c2
-rw-r--r--arch/microblaze/kernel/cpu/cache.c3
-rw-r--r--arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c9
-rw-r--r--arch/microblaze/kernel/cpu/cpuinfo-static.c4
-rw-r--r--arch/microblaze/kernel/cpu/cpuinfo.c2
-rw-r--r--arch/microblaze/kernel/cpu/mb.c4
-rw-r--r--arch/microblaze/kernel/early_printk.c2
-rw-r--r--arch/microblaze/kernel/of_device.c10
-rw-r--r--arch/microblaze/kernel/process.c23
-rw-r--r--arch/microblaze/kernel/prom.c1
-rw-r--r--arch/microblaze/kernel/ptrace.c1
-rw-r--r--arch/microblaze/kernel/signal.c15
-rw-r--r--arch/microblaze/kernel/sys_microblaze.c4
-rw-r--r--arch/microblaze/kernel/syscall_table.S2
-rw-r--r--arch/microblaze/kernel/timer.c2
-rw-r--r--arch/microblaze/kernel/traps.c2
-rw-r--r--arch/mips/Kconfig2
-rw-r--r--arch/mips/cavium-octeon/Makefile4
-rw-r--r--arch/mips/cavium-octeon/dma-octeon.c311
-rw-r--r--arch/mips/cavium-octeon/executive/Makefile1
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-helper-errata.c70
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-helper-jtag.c144
-rw-r--r--arch/mips/cavium-octeon/msi.c288
-rw-r--r--arch/mips/cavium-octeon/octeon-irq.c10
-rw-r--r--arch/mips/cavium-octeon/pci-common.c137
-rw-r--r--arch/mips/cavium-octeon/pci-common.h39
-rw-r--r--arch/mips/cavium-octeon/pci.c568
-rw-r--r--arch/mips/cavium-octeon/pcie.c1370
-rw-r--r--arch/mips/configs/bigsur_defconfig2
-rw-r--r--arch/mips/configs/mtx1_defconfig2
-rw-r--r--arch/mips/include/asm/irq.h2
-rw-r--r--arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h6
-rw-r--r--arch/mips/include/asm/mach-generic/dma-coherence.h6
-rw-r--r--arch/mips/include/asm/mach-ip27/dma-coherence.h6
-rw-r--r--arch/mips/include/asm/mach-ip32/dma-coherence.h6
-rw-r--r--arch/mips/include/asm/mach-jazz/dma-coherence.h6
-rw-r--r--arch/mips/include/asm/mach-lemote/dma-coherence.h6
-rw-r--r--arch/mips/include/asm/octeon/cvmx-helper-errata.h33
-rw-r--r--arch/mips/include/asm/octeon/cvmx-helper-jtag.h43
-rw-r--r--arch/mips/include/asm/octeon/cvmx-npei-defs.h2560
-rw-r--r--arch/mips/include/asm/octeon/cvmx-npi-defs.h1735
-rw-r--r--arch/mips/include/asm/octeon/cvmx-pci-defs.h1645
-rw-r--r--arch/mips/include/asm/octeon/cvmx-pcieep-defs.h1365
-rw-r--r--arch/mips/include/asm/octeon/cvmx-pciercx-defs.h1397
-rw-r--r--arch/mips/include/asm/octeon/cvmx-pescx-defs.h410
-rw-r--r--arch/mips/include/asm/octeon/cvmx-pexp-defs.h229
-rw-r--r--arch/mips/include/asm/octeon/cvmx.h12
-rw-r--r--arch/mips/include/asm/octeon/octeon.h2
-rw-r--r--arch/mips/include/asm/r4kcache.h1
-rw-r--r--arch/mips/include/asm/txx9/dmac.h51
-rw-r--r--arch/mips/include/asm/txx9/tx4927.h2
-rw-r--r--arch/mips/include/asm/txx9/tx4938.h1
-rw-r--r--arch/mips/include/asm/txx9/tx4939.h1
-rw-r--r--arch/mips/kernel/cevt-txx9.c69
-rw-r--r--arch/mips/kernel/csrc-bcm1480.c2
-rw-r--r--arch/mips/kernel/csrc-ioasic.c6
-rw-r--r--arch/mips/kernel/csrc-r4k.c2
-rw-r--r--arch/mips/kernel/csrc-sb1250.c2
-rw-r--r--arch/mips/kernel/i8253.c2
-rw-r--r--arch/mips/kernel/irq-gic.c5
-rw-r--r--arch/mips/mm/c-r4k.c12
-rw-r--r--arch/mips/mm/dma-default.c23
-rw-r--r--arch/mips/mti-malta/malta-smtc.c4
-rw-r--r--arch/mips/nxp/pnx8550/common/time.c2
-rw-r--r--arch/mips/sgi-ip27/ip27-timer.c2
-rw-r--r--arch/mips/sibyte/bcm1480/irq.c8
-rw-r--r--arch/mips/sibyte/sb1250/irq.c8
-rw-r--r--arch/mips/txx9/generic/setup.c55
-rw-r--r--arch/mips/txx9/generic/setup_tx4927.c12
-rw-r--r--arch/mips/txx9/generic/setup_tx4938.c21
-rw-r--r--arch/mips/txx9/generic/setup_tx4939.c21
-rw-r--r--arch/mips/txx9/rbtx4927/setup.c4
-rw-r--r--arch/mips/txx9/rbtx4938/setup.c1
-rw-r--r--arch/mips/txx9/rbtx4939/setup.c1
-rw-r--r--arch/mn10300/configs/asb2303_defconfig160
-rw-r--r--arch/mn10300/include/asm/bug.h10
-rw-r--r--arch/mn10300/include/asm/gdb-stub.h1
-rw-r--r--arch/mn10300/include/asm/unistd.h2
-rw-r--r--arch/mn10300/kernel/entry.S2
-rw-r--r--arch/mn10300/kernel/head.S3
-rw-r--r--arch/mn10300/kernel/setup.c4
-rw-r--r--arch/mn10300/kernel/vmlinux.lds.S5
-rw-r--r--arch/parisc/kernel/irq.c6
-rw-r--r--arch/powerpc/Kconfig6
-rw-r--r--arch/powerpc/boot/4xx.c56
-rw-r--r--arch/powerpc/boot/Makefile67
-rw-r--r--arch/powerpc/boot/dts/gef_ppc9a.dts15
-rw-r--r--arch/powerpc/boot/dts/gef_sbc310.dts14
-rw-r--r--arch/powerpc/boot/dts/gef_sbc610.dts14
-rw-r--r--arch/powerpc/boot/dts/ksi8560.dts13
-rw-r--r--arch/powerpc/boot/dts/lite5200b.dts39
-rw-r--r--arch/powerpc/boot/dts/mpc832x_mds.dts3
-rw-r--r--arch/powerpc/boot/dts/mpc832x_rdb.dts3
-rw-r--r--arch/powerpc/boot/dts/mpc8349emitx.dts2
-rw-r--r--arch/powerpc/boot/dts/mpc8349emitxgp.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc834x_mds.dts2
-rw-r--r--arch/powerpc/boot/dts/mpc836x_mds.dts3
-rw-r--r--arch/powerpc/boot/dts/mpc836x_rdk.dts2
-rw-r--r--arch/powerpc/boot/dts/mpc8377_mds.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc8378_mds.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc8379_mds.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc8536ds.dts18
-rw-r--r--arch/powerpc/boot/dts/mpc8540ads.dts15
-rw-r--r--arch/powerpc/boot/dts/mpc8541cds.dts16
-rw-r--r--arch/powerpc/boot/dts/mpc8544ds.dts18
-rw-r--r--arch/powerpc/boot/dts/mpc8548cds.dts17
-rw-r--r--arch/powerpc/boot/dts/mpc8555cds.dts16
-rw-r--r--arch/powerpc/boot/dts/mpc8560ads.dts15
-rw-r--r--arch/powerpc/boot/dts/mpc8568mds.dts35
-rw-r--r--arch/powerpc/boot/dts/mpc8569mds.dts567
-rw-r--r--arch/powerpc/boot/dts/mpc8572ds.dts17
-rw-r--r--arch/powerpc/boot/dts/mpc8572ds_36b.dts17
-rw-r--r--arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts16
-rw-r--r--arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts2
-rw-r--r--arch/powerpc/boot/dts/mpc8610_hpcd.dts16
-rw-r--r--arch/powerpc/boot/dts/mpc8641_hpcn.dts16
-rw-r--r--arch/powerpc/boot/dts/mpc8641_hpcn_36b.dts609
-rw-r--r--arch/powerpc/boot/dts/sbc8349.dts1
-rw-r--r--arch/powerpc/boot/dts/sbc8548.dts16
-rw-r--r--arch/powerpc/boot/dts/sbc8560.dts15
-rw-r--r--arch/powerpc/boot/dts/sbc8641d.dts16
-rw-r--r--arch/powerpc/boot/dts/socrates.dts15
-rw-r--r--arch/powerpc/boot/dts/stx_gp3_8560.dts15
-rw-r--r--arch/powerpc/boot/dts/tqm8540.dts19
-rw-r--r--arch/powerpc/boot/dts/tqm8541.dts19
-rw-r--r--arch/powerpc/boot/dts/tqm8548-bigflash.dts24
-rw-r--r--arch/powerpc/boot/dts/tqm8548.dts24
-rw-r--r--arch/powerpc/boot/dts/tqm8555.dts19
-rw-r--r--arch/powerpc/boot/dts/tqm8560.dts19
-rw-r--r--arch/powerpc/boot/simpleboot.c2
-rw-r--r--arch/powerpc/configs/40x/acadia_defconfig2
-rw-r--r--arch/powerpc/configs/40x/ep405_defconfig2
-rw-r--r--arch/powerpc/configs/40x/kilauea_defconfig2
-rw-r--r--arch/powerpc/configs/40x/makalu_defconfig2
-rw-r--r--arch/powerpc/configs/40x/virtex_defconfig2
-rw-r--r--arch/powerpc/configs/44x/arches_defconfig2
-rw-r--r--arch/powerpc/configs/44x/bamboo_defconfig2
-rw-r--r--arch/powerpc/configs/44x/canyonlands_defconfig6
-rw-r--r--arch/powerpc/configs/44x/ebony_defconfig2
-rw-r--r--arch/powerpc/configs/44x/katmai_defconfig2
-rw-r--r--arch/powerpc/configs/44x/rainier_defconfig2
-rw-r--r--arch/powerpc/configs/44x/redwood_defconfig2
-rw-r--r--arch/powerpc/configs/44x/sam440ep_defconfig2
-rw-r--r--arch/powerpc/configs/44x/sequoia_defconfig2
-rw-r--r--arch/powerpc/configs/44x/taishan_defconfig2
-rw-r--r--arch/powerpc/configs/44x/virtex5_defconfig2
-rw-r--r--arch/powerpc/configs/52xx/cm5200_defconfig69
-rw-r--r--arch/powerpc/configs/52xx/lite5200b_defconfig74
-rw-r--r--arch/powerpc/configs/52xx/motionpro_defconfig77
-rw-r--r--arch/powerpc/configs/52xx/pcm030_defconfig69
-rw-r--r--arch/powerpc/configs/52xx/tqm5200_defconfig76
-rw-r--r--arch/powerpc/configs/85xx/mpc8536_ds_defconfig1802
-rw-r--r--arch/powerpc/configs/85xx/mpc8544_ds_defconfig1802
-rw-r--r--arch/powerpc/configs/85xx/mpc8568mds_defconfig1309
-rw-r--r--arch/powerpc/configs/85xx/tqm8548_defconfig164
-rw-r--r--arch/powerpc/configs/mpc5200_defconfig188
-rw-r--r--arch/powerpc/configs/mpc85xx_defconfig252
-rw-r--r--arch/powerpc/configs/mpc85xx_smp_defconfig (renamed from arch/powerpc/configs/85xx/mpc8572_ds_defconfig)343
-rw-r--r--arch/powerpc/configs/ppc6xx_defconfig2
-rw-r--r--arch/powerpc/include/asm/cpm1.h2
-rw-r--r--arch/powerpc/include/asm/cpm2.h4
-rw-r--r--arch/powerpc/include/asm/elf.h4
-rw-r--r--arch/powerpc/include/asm/futex.h12
-rw-r--r--arch/powerpc/include/asm/mpc86xx.h33
-rw-r--r--arch/powerpc/include/asm/of_platform.h10
-rw-r--r--arch/powerpc/include/asm/parport.h2
-rw-r--r--arch/powerpc/include/asm/pci-bridge.h6
-rw-r--r--arch/powerpc/include/asm/ppc-opcode.h2
-rw-r--r--arch/powerpc/include/asm/ppc_asm.h5
-rw-r--r--arch/powerpc/include/asm/qe.h21
-rw-r--r--arch/powerpc/kernel/cputable.c15
-rw-r--r--arch/powerpc/kernel/head_32.S3
-rw-r--r--arch/powerpc/kernel/head_40x.S3
-rw-r--r--arch/powerpc/kernel/head_44x.S3
-rw-r--r--arch/powerpc/kernel/head_8xx.S3
-rw-r--r--arch/powerpc/kernel/head_fsl_booke.S3
-rw-r--r--arch/powerpc/kernel/prom_parse.c11
-rw-r--r--arch/powerpc/kernel/time.c8
-rw-r--r--arch/powerpc/kernel/vmlinux.lds.S5
-rw-r--r--arch/powerpc/kvm/powerpc.c6
-rw-r--r--arch/powerpc/mm/hash_utils_64.c2
-rw-r--r--arch/powerpc/mm/tlb_nohash.c1
-rw-r--r--arch/powerpc/mm/tlb_nohash_low.S2
-rw-r--r--arch/powerpc/oprofile/op_model_fsl_emb.c14
-rw-r--r--arch/powerpc/platforms/82xx/pq2ads.h13
-rw-r--r--arch/powerpc/platforms/85xx/Kconfig1
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_mds.c52
-rw-r--r--arch/powerpc/platforms/86xx/gef_ppc9a.c1
-rw-r--r--arch/powerpc/platforms/86xx/gef_sbc310.c1
-rw-r--r--arch/powerpc/platforms/86xx/gef_sbc610.c1
-rw-r--r--arch/powerpc/platforms/86xx/mpc8610_hpcd.c1
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_hpcn.c1
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_smp.c8
-rw-r--r--arch/powerpc/platforms/86xx/sbc8641d.c1
-rw-r--r--arch/powerpc/platforms/8xx/mpc885ads.h4
-rw-r--r--arch/powerpc/platforms/cell/Kconfig5
-rw-r--r--arch/powerpc/platforms/fsl_uli1575.c28
-rw-r--r--arch/powerpc/platforms/pasemi/setup.c4
-rw-r--r--arch/powerpc/platforms/ps3/os-area.c2
-rw-r--r--arch/powerpc/platforms/ps3/setup.c4
-rw-r--r--arch/powerpc/platforms/pseries/dtl.c1
-rw-r--r--arch/powerpc/platforms/pseries/eeh_driver.c2
-rw-r--r--arch/powerpc/platforms/pseries/xics.c12
-rw-r--r--arch/powerpc/sysdev/cpm2.c2
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c6
-rw-r--r--arch/powerpc/sysdev/fsl_rio.c28
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c14
-rw-r--r--arch/powerpc/sysdev/mpic.c4
-rw-r--r--arch/powerpc/sysdev/mpic.h2
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe.c75
-rw-r--r--arch/s390/Kconfig18
-rw-r--r--arch/s390/appldata/appldata_base.c34
-rw-r--r--arch/s390/appldata/appldata_mem.c2
-rw-r--r--arch/s390/defconfig63
-rw-r--r--arch/s390/include/asm/compat.h19
-rw-r--r--arch/s390/include/asm/cpu.h32
-rw-r--r--arch/s390/include/asm/cpuid.h25
-rw-r--r--arch/s390/include/asm/cputime.h23
-rw-r--r--arch/s390/include/asm/kvm_host.h1
-rw-r--r--arch/s390/include/asm/lowcore.h13
-rw-r--r--arch/s390/include/asm/processor.h17
-rw-r--r--arch/s390/include/asm/ptrace.h2
-rw-r--r--arch/s390/include/asm/seccomp.h16
-rw-r--r--arch/s390/include/asm/setup.h24
-rw-r--r--arch/s390/include/asm/spinlock.h19
-rw-r--r--arch/s390/include/asm/thread_info.h13
-rw-r--r--arch/s390/include/asm/timer.h1
-rw-r--r--arch/s390/include/asm/timex.h5
-rw-r--r--arch/s390/include/asm/unistd.h4
-rw-r--r--arch/s390/kernel/Makefile2
-rw-r--r--arch/s390/kernel/asm-offsets.c2
-rw-r--r--arch/s390/kernel/compat_linux.c18
-rw-r--r--arch/s390/kernel/compat_wrapper.S18
-rw-r--r--arch/s390/kernel/early.c19
-rw-r--r--arch/s390/kernel/entry.S18
-rw-r--r--arch/s390/kernel/entry64.S18
-rw-r--r--arch/s390/kernel/head.S85
-rw-r--r--arch/s390/kernel/ipl.c1
-rw-r--r--arch/s390/kernel/nmi.c7
-rw-r--r--arch/s390/kernel/process.c3
-rw-r--r--arch/s390/kernel/ptrace.c16
-rw-r--r--arch/s390/kernel/s390_ext.c2
-rw-r--r--arch/s390/kernel/sclp.S327
-rw-r--r--arch/s390/kernel/setup.c12
-rw-r--r--arch/s390/kernel/signal.c3
-rw-r--r--arch/s390/kernel/smp.c6
-rw-r--r--arch/s390/kernel/syscalls.S2
-rw-r--r--arch/s390/kernel/time.c79
-rw-r--r--arch/s390/kernel/vdso.c16
-rw-r--r--arch/s390/kernel/vmlinux.lds.S4
-rw-r--r--arch/s390/kernel/vtime.c85
-rw-r--r--arch/s390/kvm/interrupt.c6
-rw-r--r--arch/s390/lib/spinlock.c40
-rw-r--r--arch/s390/mm/fault.c3
-rw-r--r--arch/s390/mm/mmap.c11
-rw-r--r--arch/sh/Kconfig105
-rw-r--r--arch/sh/Kconfig.cpu5
-rw-r--r--arch/sh/Kconfig.debug23
-rw-r--r--arch/sh/Makefile57
-rw-r--r--arch/sh/boards/Kconfig6
-rw-r--r--arch/sh/boards/board-ap325rxa.c1
-rw-r--r--arch/sh/boards/board-urquell.c30
-rw-r--r--arch/sh/boards/mach-cayman/Makefile2
-rw-r--r--arch/sh/boards/mach-cayman/irq.c17
-rw-r--r--arch/sh/boards/mach-cayman/panic.c49
-rw-r--r--arch/sh/boards/mach-cayman/setup.c2
-rw-r--r--arch/sh/boards/mach-dreamcast/setup.c6
-rw-r--r--arch/sh/boards/mach-r2d/setup.c50
-rw-r--r--arch/sh/boards/mach-se/7751/Makefile2
-rw-r--r--arch/sh/boards/mach-se/7751/io.c16
-rw-r--r--arch/sh/boards/mach-se/7751/pci.c147
-rw-r--r--arch/sh/boards/mach-se/7780/irq.c27
-rw-r--r--arch/sh/boards/mach-sh03/rtc.c10
-rw-r--r--arch/sh/boards/mach-snapgear/io.c16
-rw-r--r--arch/sh/boards/mach-systemh/io.c16
-rw-r--r--arch/sh/boards/mach-titan/io.c20
-rw-r--r--arch/sh/boot/Makefile6
-rw-r--r--arch/sh/boot/compressed/Makefile50
-rw-r--r--arch/sh/boot/compressed/Makefile_3246
-rw-r--r--arch/sh/boot/compressed/Makefile_6443
-rw-r--r--arch/sh/boot/compressed/head_64.S5
-rw-r--r--arch/sh/boot/compressed/vmlinux_64.lds64
-rw-r--r--arch/sh/configs/ap325rxa_defconfig37
-rw-r--r--arch/sh/configs/cayman_defconfig71
-rw-r--r--arch/sh/configs/dreamcast_defconfig39
-rw-r--r--arch/sh/configs/edosk7705_defconfig29
-rw-r--r--arch/sh/configs/edosk7760_defconfig32
-rw-r--r--arch/sh/configs/espt_defconfig39
-rw-r--r--arch/sh/configs/hp6xx_defconfig35
-rw-r--r--arch/sh/configs/landisk_defconfig48
-rw-r--r--arch/sh/configs/lboxre2_defconfig44
-rw-r--r--arch/sh/configs/magicpanelr2_defconfig30
-rw-r--r--arch/sh/configs/microdev_defconfig36
-rw-r--r--arch/sh/configs/migor_defconfig36
-rw-r--r--arch/sh/configs/polaris_defconfig30
-rw-r--r--arch/sh/configs/r7780mp_defconfig38
-rw-r--r--arch/sh/configs/r7785rp_defconfig38
-rw-r--r--arch/sh/configs/rsk7201_defconfig37
-rw-r--r--arch/sh/configs/rsk7203_defconfig40
-rw-r--r--arch/sh/configs/rts7751r2d1_defconfig43
-rw-r--r--arch/sh/configs/rts7751r2dplus_defconfig130
-rw-r--r--arch/sh/configs/sdk7780_defconfig38
-rw-r--r--arch/sh/configs/se7206_defconfig35
-rw-r--r--arch/sh/configs/se7343_defconfig42
-rw-r--r--arch/sh/configs/se7619_defconfig35
-rw-r--r--arch/sh/configs/se7705_defconfig34
-rw-r--r--arch/sh/configs/se7712_defconfig30
-rw-r--r--arch/sh/configs/se7721_defconfig33
-rw-r--r--arch/sh/configs/se7722_defconfig38
-rw-r--r--arch/sh/configs/se7750_defconfig34
-rw-r--r--arch/sh/configs/se7751_defconfig34
-rw-r--r--arch/sh/configs/se7780_defconfig38
-rw-r--r--arch/sh/configs/sh03_defconfig43
-rw-r--r--arch/sh/configs/sh7710voipgw_defconfig35
-rw-r--r--arch/sh/configs/sh7724_generic_defconfig707
-rw-r--r--arch/sh/configs/sh7763rdp_defconfig35
-rw-r--r--arch/sh/configs/sh7785lcr_32bit_defconfig37
-rw-r--r--arch/sh/configs/sh7785lcr_defconfig59
-rw-r--r--arch/sh/configs/shmin_defconfig31
-rw-r--r--arch/sh/configs/shx3_defconfig32
-rw-r--r--arch/sh/configs/snapgear_defconfig40
-rw-r--r--arch/sh/configs/systemh_defconfig39
-rw-r--r--arch/sh/configs/titan_defconfig40
-rw-r--r--arch/sh/configs/ul2_defconfig37
-rw-r--r--arch/sh/configs/urquell_defconfig39
-rw-r--r--arch/sh/drivers/dma/Kconfig3
-rw-r--r--arch/sh/drivers/pci/Kconfig18
-rw-r--r--arch/sh/drivers/pci/Makefile28
-rw-r--r--arch/sh/drivers/pci/fixups-cayman.c (renamed from arch/sh/drivers/pci/ops-cayman.c)12
-rw-r--r--arch/sh/drivers/pci/fixups-dreamcast.c9
-rw-r--r--arch/sh/drivers/pci/fixups-landisk.c (renamed from arch/sh/drivers/pci/ops-landisk.c)33
-rw-r--r--arch/sh/drivers/pci/fixups-lboxre2.c41
-rw-r--r--arch/sh/drivers/pci/fixups-r7780rp.c41
-rw-r--r--arch/sh/drivers/pci/fixups-rts7751r2d.c48
-rw-r--r--arch/sh/drivers/pci/fixups-sdk7780.c63
-rw-r--r--arch/sh/drivers/pci/fixups-se7751.c111
-rw-r--r--arch/sh/drivers/pci/fixups-se7780.c60
-rw-r--r--arch/sh/drivers/pci/fixups-sh7785lcr.c46
-rw-r--r--arch/sh/drivers/pci/fixups-snapgear.c38
-rw-r--r--arch/sh/drivers/pci/fixups-titan.c (renamed from arch/sh/drivers/pci/ops-titan.c)39
-rw-r--r--arch/sh/drivers/pci/ops-dreamcast.c107
-rw-r--r--arch/sh/drivers/pci/ops-lboxre2.c63
-rw-r--r--arch/sh/drivers/pci/ops-r7780rp.c68
-rw-r--r--arch/sh/drivers/pci/ops-rts7751r2d.c74
-rw-r--r--arch/sh/drivers/pci/ops-sdk7780.c73
-rw-r--r--arch/sh/drivers/pci/ops-se7780.c96
-rw-r--r--arch/sh/drivers/pci/ops-sh03.c45
-rw-r--r--arch/sh/drivers/pci/ops-sh4.c79
-rw-r--r--arch/sh/drivers/pci/ops-sh5.c25
-rw-r--r--arch/sh/drivers/pci/ops-sh7785lcr.c61
-rw-r--r--arch/sh/drivers/pci/ops-snapgear.c94
-rw-r--r--arch/sh/drivers/pci/pci-auto.c545
-rw-r--r--arch/sh/drivers/pci/pci-dreamcast.c102
-rw-r--r--arch/sh/drivers/pci/pci-sh4.h19
-rw-r--r--arch/sh/drivers/pci/pci-sh5.c55
-rw-r--r--arch/sh/drivers/pci/pci-sh5.h3
-rw-r--r--arch/sh/drivers/pci/pci-sh7751.c216
-rw-r--r--arch/sh/drivers/pci/pci-sh7751.h12
-rw-r--r--arch/sh/drivers/pci/pci-sh7780.c227
-rw-r--r--arch/sh/drivers/pci/pci-sh7780.h16
-rw-r--r--arch/sh/drivers/pci/pci.c282
-rw-r--r--arch/sh/include/asm/cacheflush.h2
-rw-r--r--arch/sh/include/asm/clock.h4
-rw-r--r--arch/sh/include/asm/device.h2
-rw-r--r--arch/sh/include/asm/dma-mapping.h36
-rw-r--r--arch/sh/include/asm/io.h22
-rw-r--r--arch/sh/include/asm/kprobes.h2
-rw-r--r--arch/sh/include/asm/pci.h98
-rw-r--r--arch/sh/include/asm/pgtable.h4
-rw-r--r--arch/sh/include/asm/processor.h2
-rw-r--r--arch/sh/include/asm/ptrace.h7
-rw-r--r--arch/sh/include/asm/rtc.h11
-rw-r--r--arch/sh/include/asm/scatterlist.h11
-rw-r--r--arch/sh/include/asm/swab.h12
-rw-r--r--arch/sh/include/asm/system_32.h2
-rw-r--r--arch/sh/include/asm/timer.h17
-rw-r--r--arch/sh/include/asm/topology.h7
-rw-r--r--arch/sh/include/asm/types.h4
-rw-r--r--arch/sh/include/asm/ubc.h11
-rw-r--r--arch/sh/include/asm/unistd_32.h4
-rw-r--r--arch/sh/include/asm/unistd_64.h4
-rw-r--r--arch/sh/include/cpu-sh2a/cpu/ubc.h29
-rw-r--r--arch/sh/include/cpu-sh4/cpu/freq.h18
-rw-r--r--arch/sh/include/cpu-sh4/cpu/sh7724.h255
-rw-r--r--arch/sh/include/cpu-sh5/cpu/irq.h1
-rw-r--r--arch/sh/include/mach-common/mach/sh7785lcr.h10
-rw-r--r--arch/sh/include/mach-dreamcast/mach/pci.h2
-rw-r--r--arch/sh/kernel/Makefile_324
-rw-r--r--arch/sh/kernel/Makefile_647
-rw-r--r--arch/sh/kernel/cpu/clock.c62
-rw-r--r--arch/sh/kernel/cpu/irq/imask.c2
-rw-r--r--arch/sh/kernel/cpu/irq/intc-sh5.c26
-rw-r--r--arch/sh/kernel/cpu/sh2/setup-sh7619.c84
-rw-r--r--arch/sh/kernel/cpu/sh2a/setup-mxg.c111
-rw-r--r--arch/sh/kernel/cpu/sh2a/setup-sh7201.c115
-rw-r--r--arch/sh/kernel/cpu/sh2a/setup-sh7203.c154
-rw-r--r--arch/sh/kernel/cpu/sh2a/setup-sh7206.c187
-rw-r--r--arch/sh/kernel/cpu/sh4/probe.c6
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7750.c187
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7760.c140
-rw-r--r--arch/sh/kernel/cpu/sh4a/Makefile3
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7722.c112
-rw-r--r--arch/sh/kernel/cpu/sh4a/pinmux-sh7724.c2230
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7343.c18
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7366.c15
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7722.c118
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7723.c217
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7724.c562
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7780.c204
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7785.c204
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7786.c407
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-shx3.c209
-rw-r--r--arch/sh/kernel/cpu/sh5/Makefile3
-rw-r--r--arch/sh/kernel/cpu/sh5/clock-sh5.c2
-rw-r--r--arch/sh/kernel/cpu/sh5/entry.S70
-rw-r--r--arch/sh/kernel/cpu/sh5/setup-sh5.c195
-rw-r--r--arch/sh/kernel/head_32.S3
-rw-r--r--arch/sh/kernel/head_64.S5
-rw-r--r--arch/sh/kernel/io.c1
-rw-r--r--arch/sh/kernel/io_trapped.c2
-rw-r--r--arch/sh/kernel/kgdb.c4
-rw-r--r--arch/sh/kernel/localtimer.c (renamed from arch/sh/kernel/timers/timer-broadcast.c)0
-rw-r--r--arch/sh/kernel/module.c2
-rw-r--r--arch/sh/kernel/process_32.c4
-rw-r--r--arch/sh/kernel/ptrace_32.c8
-rw-r--r--arch/sh/kernel/setup.c14
-rw-r--r--arch/sh/kernel/sh_ksyms_32.c3
-rw-r--r--arch/sh/kernel/sh_ksyms_64.c2
-rw-r--r--arch/sh/kernel/sys_sh.c9
-rw-r--r--arch/sh/kernel/syscalls_32.S2
-rw-r--r--arch/sh/kernel/syscalls_64.S2
-rw-r--r--arch/sh/kernel/time.c150
-rw-r--r--arch/sh/kernel/time_32.c240
-rw-r--r--arch/sh/kernel/time_64.c363
-rw-r--r--arch/sh/kernel/timers/Makefile4
-rw-r--r--arch/sh/kernel/timers/timer-cmt.c188
-rw-r--r--arch/sh/kernel/timers/timer-mtu2.c202
-rw-r--r--arch/sh/kernel/timers/timer-tmu.c2
-rw-r--r--arch/sh/kernel/timers/timer.c6
-rw-r--r--arch/sh/kernel/traps.c6
-rw-r--r--arch/sh/kernel/traps_32.c15
-rw-r--r--arch/sh/kernel/traps_64.c35
-rw-r--r--arch/sh/kernel/vmlinux.lds.S179
-rw-r--r--arch/sh/kernel/vmlinux_32.lds.S154
-rw-r--r--arch/sh/kernel/vmlinux_64.lds.S163
-rw-r--r--arch/sh/lib64/.gitignore1
-rw-r--r--arch/sh/lib64/dbg.c182
-rw-r--r--arch/sh/lib64/panic.c43
-rw-r--r--arch/sh/lib64/sdivsi3.S6
-rw-r--r--arch/sh/lib64/udelay.c2
-rw-r--r--arch/sh/mm/Kconfig8
-rw-r--r--arch/sh/mm/cache-sh5.c8
-rw-r--r--arch/sh/mm/consistent.c31
-rw-r--r--arch/sh/mm/ioremap_32.c14
-rw-r--r--arch/sh/mm/ioremap_64.c265
-rw-r--r--arch/sh/mm/mmap.c136
-rw-r--r--arch/sh/oprofile/common.c1
-rw-r--r--arch/sparc/Kconfig3
-rw-r--r--arch/sparc/configs/sparc32_defconfig98
-rw-r--r--arch/sparc/configs/sparc64_defconfig182
-rw-r--r--arch/sparc/include/asm/atomic_32.h2
-rw-r--r--arch/sparc/include/asm/cpudata_64.h197
-rw-r--r--arch/sparc/include/asm/mdesc.h3
-rw-r--r--arch/sparc/include/asm/parport.h5
-rw-r--r--arch/sparc/include/asm/percpu_64.h8
-rw-r--r--arch/sparc/include/asm/prom.h2
-rw-r--r--arch/sparc/include/asm/thread_info_64.h4
-rw-r--r--arch/sparc/include/asm/trap_block.h207
-rw-r--r--arch/sparc/kernel/ds.c3
-rw-r--r--arch/sparc/kernel/head_32.S4
-rw-r--r--arch/sparc/kernel/head_64.S24
-rw-r--r--arch/sparc/kernel/irq_64.c12
-rw-r--r--arch/sparc/kernel/ldc.c6
-rw-r--r--arch/sparc/kernel/mdesc.c149
-rw-r--r--arch/sparc/kernel/of_device_32.c21
-rw-r--r--arch/sparc/kernel/of_device_64.c21
-rw-r--r--arch/sparc/kernel/prom.h1
-rw-r--r--arch/sparc/kernel/prom_64.c234
-rw-r--r--arch/sparc/kernel/prom_common.c2
-rw-r--r--arch/sparc/kernel/smp_64.c196
-rw-r--r--arch/sparc/kernel/sys_sparc32.c19
-rw-r--r--arch/sparc/kernel/time_64.c7
-rw-r--r--arch/sparc/kernel/traps_64.c170
-rw-r--r--arch/sparc/kernel/vmlinux.lds.S2
-rw-r--r--arch/sparc/mm/init_32.c1
-rw-r--r--arch/sparc/mm/init_64.c16
-rw-r--r--arch/um/Kconfig.rest2
-rw-r--r--arch/um/drivers/ubd_kern.c33
-rw-r--r--arch/um/kernel/time.c2
-rw-r--r--arch/x86/Kbuild16
-rw-r--r--arch/x86/Kconfig42
-rw-r--r--arch/x86/Kconfig.debug12
-rw-r--r--arch/x86/Makefile25
-rw-r--r--arch/x86/boot/Makefile5
-rw-r--r--arch/x86/boot/a20.c9
-rw-r--r--arch/x86/boot/apm.c76
-rw-r--r--arch/x86/boot/bioscall.S82
-rw-r--r--arch/x86/boot/boot.h48
-rw-r--r--arch/x86/boot/compressed/Makefile2
-rw-r--r--arch/x86/boot/compressed/head_32.S77
-rw-r--r--arch/x86/boot/compressed/head_64.S44
-rw-r--r--arch/x86/boot/compressed/vmlinux.lds.S (renamed from arch/x86/boot/compressed/vmlinux_64.lds)14
-rw-r--r--arch/x86/boot/compressed/vmlinux_32.lds43
-rw-r--r--arch/x86/boot/edd.c71
-rw-r--r--arch/x86/boot/header.S4
-rw-r--r--arch/x86/boot/main.c39
-rw-r--r--arch/x86/boot/mca.c27
-rw-r--r--arch/x86/boot/memory.c81
-rw-r--r--arch/x86/boot/regs.c29
-rw-r--r--arch/x86/boot/setup.ld6
-rw-r--r--arch/x86/boot/tty.c52
-rw-r--r--arch/x86/boot/video-bios.c27
-rw-r--r--arch/x86/boot/video-vesa.c137
-rw-r--r--arch/x86/boot/video-vga.c95
-rw-r--r--arch/x86/boot/video.c42
-rw-r--r--arch/x86/boot/video.h14
-rw-r--r--arch/x86/configs/x86_64_defconfig1
-rw-r--r--arch/x86/crypto/Makefile2
-rw-r--r--arch/x86/crypto/aesni-intel_glue.c267
-rw-r--r--arch/x86/crypto/fpu.c166
-rw-r--r--arch/x86/ia32/ia32entry.S1
-rw-r--r--arch/x86/ia32/sys_ia32.c19
-rw-r--r--arch/x86/include/asm/alternative.h59
-rw-r--r--arch/x86/include/asm/apic.h31
-rw-r--r--arch/x86/include/asm/boot.h13
-rw-r--r--arch/x86/include/asm/cpufeature.h4
-rw-r--r--arch/x86/include/asm/desc.h2
-rw-r--r--arch/x86/include/asm/ds.h82
-rw-r--r--arch/x86/include/asm/hardirq.h2
-rw-r--r--arch/x86/include/asm/hw_irq.h4
-rw-r--r--arch/x86/include/asm/i387.h31
-rw-r--r--arch/x86/include/asm/i8259.h4
-rw-r--r--arch/x86/include/asm/io_apic.h8
-rw-r--r--arch/x86/include/asm/iomap.h5
-rw-r--r--arch/x86/include/asm/iommu.h1
-rw-r--r--arch/x86/include/asm/irq_remapping.h2
-rw-r--r--arch/x86/include/asm/irq_vectors.h1
-rw-r--r--arch/x86/include/asm/k8.h13
-rw-r--r--arch/x86/include/asm/kvm.h1
-rw-r--r--arch/x86/include/asm/kvm_host.h34
-rw-r--r--arch/x86/include/asm/lguest_hcall.h2
-rw-r--r--arch/x86/include/asm/mce.h1
-rw-r--r--arch/x86/include/asm/mpspec.h4
-rw-r--r--arch/x86/include/asm/page_32_types.h4
-rw-r--r--arch/x86/include/asm/page_64_types.h6
-rw-r--r--arch/x86/include/asm/page_types.h6
-rw-r--r--arch/x86/include/asm/paravirt.h22
-rw-r--r--arch/x86/include/asm/pat.h4
-rw-r--r--arch/x86/include/asm/pci.h1
-rw-r--r--arch/x86/include/asm/pgtable.h4
-rw-r--r--arch/x86/include/asm/pgtable_64.h6
-rw-r--r--arch/x86/include/asm/pgtable_types.h1
-rw-r--r--arch/x86/include/asm/processor.h41
-rw-r--r--arch/x86/include/asm/ptrace.h9
-rw-r--r--arch/x86/include/asm/required-features.h8
-rw-r--r--arch/x86/include/asm/setup.h1
-rw-r--r--arch/x86/include/asm/svm.h1
-rw-r--r--arch/x86/include/asm/syscalls.h45
-rw-r--r--arch/x86/include/asm/thread_info.h4
-rw-r--r--arch/x86/include/asm/tlbflush.h10
-rw-r--r--arch/x86/include/asm/topology.h2
-rw-r--r--arch/x86/include/asm/traps.h2
-rw-r--r--arch/x86/include/asm/unistd_32.h1
-rw-r--r--arch/x86/include/asm/unistd_64.h2
-rw-r--r--arch/x86/include/asm/uv/uv_mmrs.h5
-rw-r--r--arch/x86/include/asm/xen/page.h3
-rw-r--r--arch/x86/kernel/Makefile3
-rw-r--r--arch/x86/kernel/acpi/boot.c8
-rw-r--r--arch/x86/kernel/acpi/cstate.c36
-rw-r--r--arch/x86/kernel/acpi/realmode/Makefile2
-rw-r--r--arch/x86/kernel/acpi/realmode/bioscall.S1
-rw-r--r--arch/x86/kernel/acpi/realmode/regs.c1
-rw-r--r--arch/x86/kernel/acpi/sleep.c2
-rw-r--r--arch/x86/kernel/amd_iommu_init.c16
-rw-r--r--arch/x86/kernel/apic/apic.c253
-rw-r--r--arch/x86/kernel/apic/es7000_32.c2
-rw-r--r--arch/x86/kernel/apic/io_apic.c549
-rw-r--r--arch/x86/kernel/apic/nmi.c7
-rw-r--r--arch/x86/kernel/apic/probe_32.c1
-rw-r--r--arch/x86/kernel/apic/probe_64.c2
-rw-r--r--arch/x86/kernel/apic/summit_32.c7
-rw-r--r--arch/x86/kernel/apic/x2apic_cluster.c2
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c36
-rw-r--r--arch/x86/kernel/bios_uv.c3
-rw-r--r--arch/x86/kernel/cpu/common.c2
-rw-r--r--arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c38
-rw-r--r--arch/x86/kernel/cpu/cpufreq/p4-clockmod.c1
-rw-r--r--arch/x86/kernel/cpu/cpufreq/powernow-k7.c2
-rw-r--r--arch/x86/kernel/cpu/cpufreq/powernow-k8.c134
-rw-r--r--arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c60
-rw-r--r--arch/x86/kernel/cpu/cpufreq/speedstep-ich.c81
-rw-r--r--arch/x86/kernel/cpu/cpufreq/speedstep-lib.c1
-rw-r--r--arch/x86/kernel/cpu/intel_cacheinfo.c153
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_64.c33
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_intel_64.c10
-rw-r--r--arch/x86/kernel/cpu/proc.c2
-rw-r--r--arch/x86/kernel/ds.c921
-rw-r--r--arch/x86/kernel/ds_selftest.c408
-rw-r--r--arch/x86/kernel/ds_selftest.h15
-rw-r--r--arch/x86/kernel/dumpstack.h1
-rw-r--r--arch/x86/kernel/e820.c11
-rw-r--r--arch/x86/kernel/early-quirks.c2
-rw-r--r--arch/x86/kernel/entry_64.S22
-rw-r--r--arch/x86/kernel/head_32.S7
-rw-r--r--arch/x86/kernel/hpet.c24
-rw-r--r--arch/x86/kernel/i8253.c2
-rw-r--r--arch/x86/kernel/irq.c20
-rw-r--r--arch/x86/kernel/irqinit.c (renamed from arch/x86/kernel/irqinit_32.c)149
-rw-r--r--arch/x86/kernel/irqinit_64.c177
-rw-r--r--arch/x86/kernel/kgdb.c3
-rw-r--r--arch/x86/kernel/kvm.c6
-rw-r--r--arch/x86/kernel/kvmclock.c7
-rw-r--r--arch/x86/kernel/machine_kexec_32.c4
-rw-r--r--arch/x86/kernel/machine_kexec_64.c4
-rw-r--r--arch/x86/kernel/microcode_core.c35
-rw-r--r--arch/x86/kernel/paravirt.c56
-rw-r--r--arch/x86/kernel/pci-calgary_64.c54
-rw-r--r--arch/x86/kernel/pci-dma.c6
-rw-r--r--arch/x86/kernel/pci-gart_64.c45
-rw-r--r--arch/x86/kernel/pci-swiotlb.c7
-rw-r--r--arch/x86/kernel/process.c6
-rw-r--r--arch/x86/kernel/process_32.c5
-rw-r--r--arch/x86/kernel/process_64.c5
-rw-r--r--arch/x86/kernel/ptrace.c284
-rw-r--r--arch/x86/kernel/quirks.c39
-rw-r--r--arch/x86/kernel/setup.c26
-rw-r--r--arch/x86/kernel/smp.c23
-rw-r--r--arch/x86/kernel/smpboot.c14
-rw-r--r--arch/x86/kernel/syscall_table_32.S1
-rw-r--r--arch/x86/kernel/tlb_uv.c189
-rw-r--r--arch/x86/kernel/traps.c10
-rw-r--r--arch/x86/kernel/tsc.c10
-rw-r--r--arch/x86/kernel/uv_sysfs.c4
-rw-r--r--arch/x86/kernel/uv_time.c10
-rw-r--r--arch/x86/kernel/vmi_32.c20
-rw-r--r--arch/x86/kernel/vmiclock_32.c2
-rw-r--r--arch/x86/kernel/vmlinux.lds.S431
-rw-r--r--arch/x86/kernel/vmlinux_32.lds.S229
-rw-r--r--arch/x86/kernel/vmlinux_64.lds.S298
-rw-r--r--arch/x86/kernel/xsave.c4
-rw-r--r--arch/x86/kvm/Makefile2
-rw-r--r--arch/x86/kvm/i8254.c109
-rw-r--r--arch/x86/kvm/i8254.h12
-rw-r--r--arch/x86/kvm/irq.c7
-rw-r--r--arch/x86/kvm/kvm_timer.h18
-rw-r--r--arch/x86/kvm/lapic.c251
-rw-r--r--arch/x86/kvm/lapic.h12
-rw-r--r--arch/x86/kvm/mmu.c165
-rw-r--r--arch/x86/kvm/mmu.h5
-rw-r--r--arch/x86/kvm/paging_tmpl.h16
-rw-r--r--arch/x86/kvm/svm.c352
-rw-r--r--arch/x86/kvm/timer.c46
-rw-r--r--arch/x86/kvm/vmx.c557
-rw-r--r--arch/x86/kvm/x86.c381
-rw-r--r--arch/x86/kvm/x86.h11
-rw-r--r--arch/x86/kvm/x86_emulate.c121
-rw-r--r--arch/x86/lguest/boot.c36
-rw-r--r--arch/x86/mm/dump_pagetables.c7
-rw-r--r--arch/x86/mm/fault.c57
-rw-r--r--arch/x86/mm/highmem_32.c2
-rw-r--r--arch/x86/mm/init.c89
-rw-r--r--arch/x86/mm/init_32.c57
-rw-r--r--arch/x86/mm/init_64.c43
-rw-r--r--arch/x86/mm/iomap_32.c1
-rw-r--r--arch/x86/mm/ioremap.c10
-rw-r--r--arch/x86/mm/kmmio.c106
-rw-r--r--arch/x86/mm/mmio-mod.c2
-rw-r--r--arch/x86/mm/numa_32.c2
-rw-r--r--arch/x86/mm/numa_64.c3
-rw-r--r--arch/x86/mm/pageattr.c141
-rw-r--r--arch/x86/mm/pat.c189
-rw-r--r--arch/x86/mm/srat_32.c2
-rw-r--r--arch/x86/mm/srat_64.c7
-rw-r--r--arch/x86/pci/amd_bus.c6
-rw-r--r--arch/x86/pci/common.c5
-rw-r--r--arch/x86/pci/i386.c4
-rw-r--r--arch/x86/pci/mmconfig-shared.c6
-rw-r--r--arch/x86/power/Makefile2
-rw-r--r--arch/x86/power/cpu.c (renamed from arch/x86/power/cpu_64.c)165
-rw-r--r--arch/x86/power/cpu_32.c148
-rw-r--r--arch/x86/vdso/vclock_gettime.c12
-rw-r--r--arch/x86/vdso/vma.c1
-rw-r--r--arch/x86/xen/enlighten.c99
-rw-r--r--arch/x86/xen/mmu.c142
-rw-r--r--arch/x86/xen/mmu.h3
-rw-r--r--arch/x86/xen/smp.c4
-rw-r--r--arch/x86/xen/time.c7
-rw-r--r--arch/x86/xen/xen-ops.h3
-rw-r--r--arch/xtensa/Kconfig6
-rw-r--r--arch/xtensa/include/asm/checksum.h6
-rw-r--r--arch/xtensa/kernel/head.S3
-rw-r--r--arch/xtensa/kernel/vmlinux.lds.S4
-rw-r--r--block/Kconfig11
-rw-r--r--block/as-iosched.c122
-rw-r--r--block/blk-barrier.c12
-rw-r--r--block/blk-core.c543
-rw-r--r--block/blk-exec.c1
-rw-r--r--block/blk-map.c6
-rw-r--r--block/blk-merge.c5
-rw-r--r--block/blk-settings.c20
-rw-r--r--block/blk-sysfs.c11
-rw-r--r--block/blk-timeout.c35
-rw-r--r--block/blk.h56
-rw-r--r--block/cfq-iosched.c304
-rw-r--r--block/compat_ioctl.c2
-rw-r--r--block/elevator.c145
-rw-r--r--block/genhd.c12
-rw-r--r--block/ioctl.c2
-rw-r--r--block/scsi_ioctl.c22
-rw-r--r--crypto/Kconfig10
-rw-r--r--crypto/algboss.c18
-rw-r--r--crypto/api.c8
-rw-r--r--crypto/cryptd.c14
-rw-r--r--crypto/eseqiv.c3
-rw-r--r--crypto/internal.h3
-rw-r--r--crypto/pcompress.c1
-rw-r--r--crypto/tcrypt.c25
-rw-r--r--crypto/testmgr.c286
-rw-r--r--crypto/testmgr.h645
-rw-r--r--drivers/Makefile4
-rw-r--r--drivers/acpi/acpica/Makefile27
-rw-r--r--drivers/acpi/acpica/acglobal.h3
-rw-r--r--drivers/acpi/acpica/dsobject.c5
-rw-r--r--drivers/acpi/acpica/dsopcode.c17
-rw-r--r--drivers/acpi/acpica/dswstate.c4
-rw-r--r--drivers/acpi/acpica/evxfevnt.c4
-rw-r--r--drivers/acpi/acpica/exmutex.c9
-rw-r--r--drivers/acpi/acpica/hwregs.c4
-rw-r--r--drivers/acpi/acpica/hwsleep.c43
-rw-r--r--drivers/acpi/acpica/hwvalid.c86
-rw-r--r--drivers/acpi/acpica/nsnames.c2
-rw-r--r--drivers/acpi/acpica/nspredef.c7
-rw-r--r--drivers/acpi/acpica/nssearch.c4
-rw-r--r--drivers/acpi/acpica/rscalc.c10
-rw-r--r--drivers/acpi/acpica/rscreate.c27
-rw-r--r--drivers/acpi/acpica/rsxface.c8
-rw-r--r--drivers/acpi/acpica/tbfadt.c16
-rw-r--r--drivers/acpi/acpica/tbinstal.c2
-rw-r--r--drivers/acpi/acpica/utcopy.c23
-rw-r--r--drivers/acpi/acpica/utdebug.c8
-rw-r--r--drivers/acpi/acpica/utmisc.c20
-rw-r--r--drivers/acpi/acpica/utmutex.c26
-rw-r--r--drivers/acpi/bus.c2
-rw-r--r--drivers/acpi/button.c140
-rw-r--r--drivers/acpi/ec.c1
-rw-r--r--drivers/acpi/osl.c4
-rw-r--r--drivers/acpi/pci_irq.c5
-rw-r--r--drivers/acpi/processor_idle.c54
-rw-r--r--drivers/acpi/processor_throttling.c72
-rw-r--r--drivers/acpi/sleep.c35
-rw-r--r--drivers/acpi/system.c11
-rw-r--r--drivers/acpi/thermal.c2
-rw-r--r--drivers/acpi/video.c92
-rw-r--r--drivers/ata/ahci.c17
-rw-r--r--drivers/ata/ata_piix.c18
-rw-r--r--drivers/ata/libata-acpi.c4
-rw-r--r--drivers/ata/libata-core.c29
-rw-r--r--drivers/ata/libata-eh.c36
-rw-r--r--drivers/ata/libata-scsi.c34
-rw-r--r--drivers/ata/libata-sff.c47
-rw-r--r--drivers/ata/pata_hpt37x.c22
-rw-r--r--drivers/ata/pata_legacy.c37
-rw-r--r--drivers/ata/pata_ninja32.c4
-rw-r--r--drivers/ata/pata_pdc202xx_old.c6
-rw-r--r--drivers/ata/pata_via.c74
-rw-r--r--drivers/ata/sata_mv.c127
-rw-r--r--drivers/ata/sata_sil.c2
-rw-r--r--drivers/ata/sata_sx4.c11
-rw-r--r--drivers/atm/solos-pci.c2
-rw-r--r--drivers/base/base.h2
-rw-r--r--drivers/base/core.c6
-rw-r--r--drivers/base/dd.c1
-rw-r--r--drivers/base/firmware_class.c129
-rw-r--r--drivers/base/iommu.c2
-rw-r--r--drivers/base/platform.c255
-rw-r--r--drivers/base/sys.c16
-rw-r--r--drivers/block/Kconfig2
-rw-r--r--drivers/block/amiflop.c15
-rw-r--r--drivers/block/ataflop.c18
-rw-r--r--drivers/block/brd.c5
-rw-r--r--drivers/block/cciss.c2
-rw-r--r--drivers/block/cpqarray.c3
-rw-r--r--drivers/block/hd.c63
-rw-r--r--drivers/block/loop.c26
-rw-r--r--drivers/block/mg_disk.c436
-rw-r--r--drivers/block/paride/pcd.c12
-rw-r--r--drivers/block/paride/pd.c5
-rw-r--r--drivers/block/paride/pf.c28
-rw-r--r--drivers/block/ps3disk.c11
-rw-r--r--drivers/block/sunvdc.c9
-rw-r--r--drivers/block/swim.c19
-rw-r--r--drivers/block/swim3.c53
-rw-r--r--drivers/block/sx8.c3
-rw-r--r--drivers/block/ub.c20
-rw-r--r--drivers/block/umem.c1
-rw-r--r--drivers/block/virtio_blk.c2
-rw-r--r--drivers/block/xd.c22
-rw-r--r--drivers/block/xen-blkfront.c6
-rw-r--r--drivers/block/xsysace.c4
-rw-r--r--drivers/block/z2ram.c4
-rw-r--r--drivers/cdrom/gdrom.c8
-rw-r--r--drivers/cdrom/viocd.c25
-rw-r--r--drivers/char/agp/generic.c4
-rw-r--r--drivers/char/agp/intel-agp.c3
-rw-r--r--drivers/char/amiserial.c2
-rw-r--r--drivers/char/cyclades.c288
-rw-r--r--drivers/char/epca.c4
-rw-r--r--drivers/char/hpet.c6
-rw-r--r--drivers/char/hw_random/omap-rng.c2
-rw-r--r--drivers/char/hw_random/virtio-rng.c4
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c211
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c150
-rw-r--r--drivers/char/isicom.c19
-rw-r--r--drivers/char/istallion.c8
-rw-r--r--drivers/char/keyboard.c2
-rw-r--r--drivers/char/mem.c27
-rw-r--r--drivers/char/mxser.c12
-rw-r--r--drivers/char/pcmcia/synclink_cs.c11
-rw-r--r--drivers/char/random.c19
-rw-r--r--drivers/char/rocket.c13
-rw-r--r--drivers/char/stallion.c6
-rw-r--r--drivers/char/synclink.c9
-rw-r--r--drivers/char/synclink_gt.c86
-rw-r--r--drivers/char/synclinkmp.c9
-rw-r--r--drivers/char/sysrq.c1
-rw-r--r--drivers/char/tty_port.c38
-rw-r--r--drivers/char/vt.c9
-rw-r--r--drivers/char/vt_ioctl.c6
-rw-r--r--drivers/clocksource/Makefile2
-rw-r--r--drivers/clocksource/acpi_pm.c12
-rw-r--r--drivers/clocksource/cyclone.c2
-rw-r--r--drivers/clocksource/scx200_hrt.c2
-rw-r--r--drivers/clocksource/sh_cmt.c116
-rw-r--r--drivers/clocksource/sh_mtu2.c357
-rw-r--r--drivers/clocksource/sh_tmu.c461
-rw-r--r--drivers/clocksource/tcb_clksrc.c2
-rw-r--r--drivers/crypto/Kconfig2
-rw-r--r--drivers/crypto/ixp4xx_crypto.c33
-rw-r--r--drivers/crypto/padlock-aes.c15
-rw-r--r--drivers/crypto/talitos.c713
-rw-r--r--drivers/dma/Kconfig8
-rw-r--r--drivers/dma/Makefile1
-rw-r--r--drivers/dma/dmaengine.c17
-rw-r--r--drivers/dma/dmatest.c4
-rw-r--r--drivers/dma/ioat_dma.c45
-rw-r--r--drivers/dma/ipu/ipu_idmac.c4
-rw-r--r--drivers/dma/txx9dmac.c1354
-rw-r--r--drivers/dma/txx9dmac.h307
-rw-r--r--drivers/edac/e752x_edac.c2
-rw-r--r--drivers/edac/edac_core.h12
-rw-r--r--drivers/edac/edac_device.c2
-rw-r--r--drivers/edac/edac_mc.c2
-rw-r--r--drivers/edac/edac_pci.c2
-rw-r--r--drivers/edac/mpc85xx_edac.c2
-rw-r--r--drivers/firmware/dcdbas.c49
-rw-r--r--drivers/firmware/iscsi_ibft.c4
-rw-r--r--drivers/gpu/drm/Kconfig6
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c19
-rw-r--r--drivers/gpu/drm/drm_drv.c3
-rw-r--r--drivers/gpu/drm/drm_stub.c26
-rw-r--r--drivers/gpu/drm/drm_sysfs.c3
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c8
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c2
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h15
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c191
-rw-r--r--drivers/gpu/drm/i915/i915_gem_debugfs.c93
-rw-r--r--drivers/gpu/drm/i915/i915_gem_tiling.c112
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c2
-rw-r--r--drivers/gpu/drm/i915/i915_opregion.c15
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h1
-rw-r--r--drivers/gpu/drm/i915/intel_display.c11
-rw-r--r--drivers/gpu/drm/i915/intel_fb.c4
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c23
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c22
-rw-r--r--drivers/gpu/drm/r128/r128_cce.c6
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.h3
-rw-r--r--drivers/gpu/drm/via/via_dma.c12
-rw-r--r--drivers/hid/Kconfig7
-rw-r--r--drivers/hid/Makefile1
-rw-r--r--drivers/hid/hid-apple.c2
-rw-r--r--drivers/hid/hid-core.c5
-rw-r--r--drivers/hid/hid-ids.h7
-rw-r--r--drivers/hid/hid-lg.c2
-rw-r--r--drivers/hid/hid-lgff.c2
-rw-r--r--drivers/hid/hid-wacom.c259
-rw-r--r--drivers/hid/hidraw.c12
-rw-r--r--drivers/hid/usbhid/hid-core.c4
-rw-r--r--drivers/hid/usbhid/hid-quirks.c3
-rw-r--r--drivers/hwmon/Kconfig12
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/asus_atk0110.c2
-rw-r--r--drivers/hwmon/hp_accel.c1
-rw-r--r--drivers/hwmon/ibmaem.c1
-rw-r--r--drivers/hwmon/sht15.c692
-rw-r--r--drivers/hwmon/w83781d.c3
-rw-r--r--drivers/i2c/algos/i2c-algo-bit.c2
-rw-r--r--drivers/i2c/algos/i2c-algo-pca.c11
-rw-r--r--drivers/i2c/busses/i2c-ali1535.c2
-rw-r--r--drivers/i2c/busses/i2c-ali15x3.c2
-rw-r--r--drivers/i2c/busses/i2c-amd756.c4
-rw-r--r--drivers/i2c/busses/i2c-i801.c8
-rw-r--r--drivers/i2c/busses/i2c-isch.c2
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c2
-rw-r--r--drivers/i2c/busses/i2c-pxa.c22
-rw-r--r--drivers/i2c/busses/i2c-sis5595.c2
-rw-r--r--drivers/i2c/busses/i2c-sis630.c2
-rw-r--r--drivers/i2c/busses/i2c-sis96x.c2
-rw-r--r--drivers/i2c/busses/i2c-voodoo3.c1
-rw-r--r--drivers/i2c/chips/Kconfig15
-rw-r--r--drivers/i2c/chips/Makefile1
-rw-r--r--drivers/i2c/i2c-core.c535
-rw-r--r--drivers/ide/alim15x3.c10
-rw-r--r--drivers/ide/cs5536.c1
-rw-r--r--drivers/ide/hpt366.c14
-rw-r--r--drivers/ide/ide-atapi.c170
-rw-r--r--drivers/ide/ide-cd.c99
-rw-r--r--drivers/ide/ide-cd.h4
-rw-r--r--drivers/ide/ide-disk.c1
-rw-r--r--drivers/ide/ide-dma.c20
-rw-r--r--drivers/ide/ide-floppy.c24
-rw-r--r--drivers/ide/ide-gd.c17
-rw-r--r--drivers/ide/ide-io.c25
-rw-r--r--drivers/ide/ide-ioctls.c1
-rw-r--r--drivers/ide/ide-park.c7
-rw-r--r--drivers/ide/ide-pm.c38
-rw-r--r--drivers/ide/ide-tape.c740
-rw-r--r--drivers/ide/ide-taskfile.c18
-rw-r--r--drivers/ide/palm_bk3710.c93
-rw-r--r--drivers/ide/pmac.c2
-rw-r--r--drivers/infiniband/hw/cxgb3/cxio_hal.c1
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cm.c8
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_qp.c1
-rw-r--r--drivers/infiniband/hw/ehca/ehca_main.c2
-rw-r--r--drivers/infiniband/hw/ehca/ehca_qp.c94
-rw-r--r--drivers/infiniband/hw/ehca/hcp_if.c6
-rw-r--r--drivers/infiniband/hw/ehca/hcp_if.h2
-rw-r--r--drivers/infiniband/hw/ehca/hcp_phyp.c11
-rw-r--r--drivers/infiniband/hw/ehca/hcp_phyp.h2
-rw-r--r--drivers/infiniband/hw/ehca/ipz_pt_fn.c19
-rw-r--r--drivers/infiniband/hw/ipath/ipath_fs.c2
-rw-r--r--drivers/infiniband/hw/mlx4/mlx4_ib.h1
-rw-r--r--drivers/infiniband/hw/mlx4/mr.c10
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.c16
-rw-r--r--drivers/infiniband/hw/nes/nes.h4
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.c84
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.h1
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.c30
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.c67
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.h1
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c6
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c5
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c1
-rw-r--r--drivers/input/evdev.c9
-rw-r--r--drivers/input/ff-memless.c2
-rw-r--r--drivers/input/gameport/fm801-gp.c1
-rw-r--r--drivers/input/gameport/gameport.c39
-rw-r--r--drivers/input/input.c37
-rw-r--r--drivers/input/joydev.c22
-rw-r--r--drivers/input/keyboard/Kconfig10
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/keyboard/atkbd.c36
-rw-r--r--drivers/input/keyboard/bf54x-keys.c2
-rw-r--r--drivers/input/keyboard/ep93xx_keypad.c470
-rw-r--r--drivers/input/keyboard/gpio_keys.c3
-rw-r--r--drivers/input/keyboard/omap-keypad.c16
-rw-r--r--drivers/input/misc/Kconfig21
-rw-r--r--drivers/input/misc/Makefile2
-rw-r--r--drivers/input/misc/dm355evm_keys.c329
-rw-r--r--drivers/input/misc/rotary_encoder.c61
-rw-r--r--drivers/input/misc/twl4030-pwrbutton.c145
-rw-r--r--drivers/input/mouse/alps.c19
-rw-r--r--drivers/input/mouse/appletouch.c24
-rw-r--r--drivers/input/mouse/bcm5974.c108
-rw-r--r--drivers/input/mouse/elantech.c48
-rw-r--r--drivers/input/mouse/elantech.h5
-rw-r--r--drivers/input/mouse/lifebook.c31
-rw-r--r--drivers/input/mouse/maplemouse.c43
-rw-r--r--drivers/input/mouse/pc110pad.c1
-rw-r--r--drivers/input/mousedev.c9
-rw-r--r--drivers/input/serio/hp_sdc.c24
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h28
-rw-r--r--drivers/input/serio/i8042.c54
-rw-r--r--drivers/input/serio/sa1111ps2.c2
-rw-r--r--drivers/input/serio/serio.c58
-rw-r--r--drivers/input/tablet/gtco.c1
-rw-r--r--drivers/input/tablet/wacom.h8
-rw-r--r--drivers/input/tablet/wacom_sys.c26
-rw-r--r--drivers/input/tablet/wacom_wac.c168
-rw-r--r--drivers/input/tablet/wacom_wac.h3
-rw-r--r--drivers/input/touchscreen/Kconfig15
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/ad7877.c4
-rw-r--r--drivers/input/touchscreen/ad7879.c3
-rw-r--r--drivers/input/touchscreen/ads7846.c12
-rw-r--r--drivers/input/touchscreen/atmel-wm97xx.c446
-rw-r--r--drivers/input/touchscreen/da9034-ts.c29
-rw-r--r--drivers/input/touchscreen/mainstone-wm97xx.c7
-rw-r--r--drivers/input/touchscreen/tsc2007.c7
-rw-r--r--drivers/input/touchscreen/ucb1400_ts.c2
-rw-r--r--drivers/input/touchscreen/wm97xx-core.c5
-rw-r--r--drivers/isdn/capi/capifs.c11
-rw-r--r--drivers/isdn/divert/isdn_divert.c2
-rw-r--r--drivers/isdn/hisax/st5481_usb.c9
-rw-r--r--drivers/isdn/mISDN/dsp_core.c2
-rw-r--r--drivers/lguest/lg.h3
-rw-r--r--drivers/lguest/segments.c13
-rw-r--r--drivers/lguest/x86/core.c9
-rw-r--r--drivers/macintosh/Kconfig2
-rw-r--r--drivers/macintosh/mediabay.c3
-rw-r--r--drivers/macintosh/therm_adt746x.c84
-rw-r--r--drivers/macintosh/therm_pm72.c95
-rw-r--r--drivers/macintosh/therm_windtunnel.c126
-rw-r--r--drivers/macintosh/windfarm_lm75_sensor.c129
-rw-r--r--drivers/macintosh/windfarm_max6690_sensor.c103
-rw-r--r--drivers/macintosh/windfarm_smu_sat.c109
-rw-r--r--drivers/md/bitmap.c36
-rw-r--r--drivers/md/dm-bio-list.h117
-rw-r--r--drivers/md/dm-crypt.c8
-rw-r--r--drivers/md/dm-delay.c8
-rw-r--r--drivers/md/dm-io.c14
-rw-r--r--drivers/md/dm-linear.c4
-rw-r--r--drivers/md/dm-mpath.c92
-rw-r--r--drivers/md/dm-raid1.c1
-rw-r--r--drivers/md/dm-region-hash.c3
-rw-r--r--drivers/md/dm-snap-persistent.c2
-rw-r--r--drivers/md/dm-snap.c12
-rw-r--r--drivers/md/dm-stripe.c15
-rw-r--r--drivers/md/dm-table.c121
-rw-r--r--drivers/md/dm.c195
-rw-r--r--drivers/md/md.c111
-rw-r--r--drivers/md/md.h21
-rw-r--r--drivers/md/raid1.c1
-rw-r--r--drivers/md/raid10.c13
-rw-r--r--drivers/md/raid5.c7
-rw-r--r--drivers/media/dvb/dvb-usb/af9015.c80
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_devices.c7
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h3
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb.h2
-rw-r--r--drivers/media/dvb/frontends/Kconfig22
-rw-r--r--drivers/media/dvb/frontends/Makefile4
-rw-r--r--drivers/media/dvb/frontends/isl6423.c308
-rw-r--r--drivers/media/dvb/frontends/isl6423.h63
-rw-r--r--drivers/media/dvb/frontends/stv0900_priv.h2
-rw-r--r--drivers/media/dvb/frontends/stv090x.c4299
-rw-r--r--drivers/media/dvb/frontends/stv090x.h106
-rw-r--r--drivers/media/dvb/frontends/stv090x_priv.h269
-rw-r--r--drivers/media/dvb/frontends/stv090x_reg.h2373
-rw-r--r--drivers/media/dvb/frontends/stv6110x.c373
-rw-r--r--drivers/media/dvb/frontends/stv6110x.h71
-rw-r--r--drivers/media/dvb/frontends/stv6110x_priv.h75
-rw-r--r--drivers/media/dvb/frontends/stv6110x_reg.h82
-rw-r--r--drivers/media/dvb/frontends/tda10048.c219
-rw-r--r--drivers/media/dvb/frontends/tda10048.h14
-rw-r--r--drivers/media/dvb/siano/smscoreapi.c36
-rw-r--r--drivers/media/dvb/siano/smscoreapi.h119
-rw-r--r--drivers/media/dvb/siano/smsendian.c100
-rw-r--r--drivers/media/dvb/siano/smsendian.h32
-rw-r--r--drivers/media/dvb/siano/smsir.c301
-rw-r--r--drivers/media/dvb/siano/smsir.h93
-rw-r--r--drivers/media/dvb/siano/smssdio.c354
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.c2
-rw-r--r--drivers/media/dvb/ttpci/budget.c85
-rw-r--r--drivers/media/radio/radio-sf16fmi.c2
-rw-r--r--drivers/media/radio/radio-sf16fmr2.c2
-rw-r--r--drivers/media/radio/radio-si470x.c3
-rw-r--r--drivers/media/video/Makefile9
-rw-r--r--drivers/media/video/au0828/au0828-core.c6
-rw-r--r--drivers/media/video/bt8xx/bttv-i2c.c21
-rw-r--r--drivers/media/video/cafe_ccic.c1
-rw-r--r--drivers/media/video/cx18/cx18-audio.c46
-rw-r--r--drivers/media/video/cx18/cx18-av-core.c234
-rw-r--r--drivers/media/video/cx18/cx18-av-firmware.c82
-rw-r--r--drivers/media/video/cx18/cx18-controls.c6
-rw-r--r--drivers/media/video/cx18/cx18-driver.c95
-rw-r--r--drivers/media/video/cx18/cx18-driver.h17
-rw-r--r--drivers/media/video/cx18/cx18-dvb.c1
-rw-r--r--drivers/media/video/cx18/cx18-fileops.c7
-rw-r--r--drivers/media/video/cx18/cx18-i2c.c16
-rw-r--r--drivers/media/video/cx18/cx18-mailbox.c114
-rw-r--r--drivers/media/video/cx18/cx18-mailbox.h2
-rw-r--r--drivers/media/video/cx18/cx18-queue.c85
-rw-r--r--drivers/media/video/cx18/cx18-streams.c35
-rw-r--r--drivers/media/video/cx18/cx18-streams.h20
-rw-r--r--drivers/media/video/cx18/cx18-version.h2
-rw-r--r--drivers/media/video/cx231xx/Kconfig44
-rw-r--r--drivers/media/video/cx231xx/cx231xx-avcore.c1
-rw-r--r--drivers/media/video/cx231xx/cx231xx-cards.c8
-rw-r--r--drivers/media/video/cx231xx/cx231xx-i2c.c32
-rw-r--r--drivers/media/video/cx231xx/cx231xx-input.c2
-rw-r--r--drivers/media/video/cx231xx/cx231xx-vbi.c1
-rw-r--r--drivers/media/video/cx231xx/cx231xx.h2
-rw-r--r--drivers/media/video/cx23885/cx23885-cards.c4
-rw-r--r--drivers/media/video/cx23885/cx23885-core.c10
-rw-r--r--drivers/media/video/cx23885/cx23885-dvb.c7
-rw-r--r--drivers/media/video/cx23885/cx23885-i2c.c12
-rw-r--r--drivers/media/video/cx88/Makefile2
-rw-r--r--drivers/media/video/cx88/cx88-cards.c13
-rw-r--r--drivers/media/video/cx88/cx88-core.c26
-rw-r--r--drivers/media/video/cx88/cx88-dsp.c312
-rw-r--r--drivers/media/video/cx88/cx88-i2c.c13
-rw-r--r--drivers/media/video/cx88/cx88-input.c2
-rw-r--r--drivers/media/video/cx88/cx88-tvaudio.c115
-rw-r--r--drivers/media/video/cx88/cx88.h11
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c70
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c2
-rw-r--r--drivers/media/video/em28xx/em28xx-dvb.c1
-rw-r--r--drivers/media/video/em28xx/em28xx-i2c.c25
-rw-r--r--drivers/media/video/em28xx/em28xx-input.c8
-rw-r--r--drivers/media/video/em28xx/em28xx.h3
-rw-r--r--drivers/media/video/gspca/finepix.c1
-rw-r--r--drivers/media/video/gspca/gspca.c50
-rw-r--r--drivers/media/video/gspca/gspca.h6
-rw-r--r--drivers/media/video/gspca/m5602/Makefile3
-rw-r--r--drivers/media/video/gspca/m5602/m5602_bridge.h26
-rw-r--r--drivers/media/video/gspca/m5602/m5602_core.c44
-rw-r--r--drivers/media/video/gspca/m5602/m5602_mt9m111.c400
-rw-r--r--drivers/media/video/gspca/m5602/m5602_mt9m111.h805
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov7660.c227
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov7660.h279
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov9650.c195
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov9650.h57
-rw-r--r--drivers/media/video/gspca/m5602/m5602_po1030.c494
-rw-r--r--drivers/media/video/gspca/m5602/m5602_po1030.h439
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k4aa.c385
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k4aa.h93
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k83a.c473
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k83a.h280
-rw-r--r--drivers/media/video/gspca/m5602/m5602_sensor.h9
-rw-r--r--drivers/media/video/gspca/mr97310a.c8
-rw-r--r--drivers/media/video/gspca/ov534.c30
-rw-r--r--drivers/media/video/gspca/sonixb.c2
-rw-r--r--drivers/media/video/gspca/sonixj.c66
-rw-r--r--drivers/media/video/gspca/spca500.c33
-rw-r--r--drivers/media/video/gspca/sq905.c1
-rw-r--r--drivers/media/video/gspca/sq905c.c1
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c76
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h10
-rw-r--r--drivers/media/video/gspca/sunplus.c33
-rw-r--r--drivers/media/video/gspca/t613.c2
-rw-r--r--drivers/media/video/gspca/vc032x.c22
-rw-r--r--drivers/media/video/gspca/zc3xx.c22
-rw-r--r--drivers/media/video/hdpvr/hdpvr-video.c2
-rw-r--r--drivers/media/video/ir-kbd-i2c.c222
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c16
-rw-r--r--drivers/media/video/ivtv/ivtv-gpio.c4
-rw-r--r--drivers/media/video/ivtv/ivtv-i2c.c36
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c5
-rw-r--r--drivers/media/video/ivtv/ivtv-irq.c2
-rw-r--r--drivers/media/video/ivtv/ivtv-yuv.c3
-rw-r--r--drivers/media/video/ivtv/ivtvfb.c3
-rw-r--r--drivers/media/video/mt9m001.c108
-rw-r--r--drivers/media/video/mt9m111.c73
-rw-r--r--drivers/media/video/mt9t031.c135
-rw-r--r--drivers/media/video/mt9v022.c138
-rw-r--r--drivers/media/video/mx1_camera.c50
-rw-r--r--drivers/media/video/mx3_camera.c44
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-devattr.c2
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c40
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-core.c24
-rw-r--r--drivers/media/video/pwc/pwc-ctrl.c238
-rw-r--r--drivers/media/video/pxa_camera.c120
-rw-r--r--drivers/media/video/s2255drv.c49
-rw-r--r--drivers/media/video/saa5246a.c3
-rw-r--r--drivers/media/video/saa5249.c4
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c436
-rw-r--r--drivers/media/video/saa7134/saa7134-i2c.c31
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c117
-rw-r--r--drivers/media/video/saa7134/saa7134.h16
-rw-r--r--drivers/media/video/sh_mobile_ceu_camera.c27
-rw-r--r--drivers/media/video/soc_camera.c106
-rw-r--r--drivers/media/video/tda7432.c14
-rw-r--r--drivers/media/video/tuner-core.c27
-rw-r--r--drivers/media/video/uvc/uvc_driver.c9
-rw-r--r--drivers/media/video/uvc/uvc_v4l2.c10
-rw-r--r--drivers/media/video/uvc/uvc_video.c2
-rw-r--r--drivers/media/video/v4l2-common.c4
-rw-r--r--drivers/media/video/v4l2-device.c29
-rw-r--r--drivers/media/video/v4l2-ioctl.c45
-rw-r--r--drivers/media/video/zoran/zoran_driver.c28
-rw-r--r--drivers/memstick/core/mspro_block.c2
-rw-r--r--drivers/message/fusion/lsi/mpi_history.txt6
-rw-r--r--drivers/message/fusion/mptbase.c2
-rw-r--r--drivers/message/i2o/i2o_block.c2
-rw-r--r--drivers/mfd/htc-pasic3.c4
-rw-r--r--drivers/mfd/pcf50633-core.c2
-rw-r--r--drivers/mfd/twl4030-core.c2
-rw-r--r--drivers/mfd/wm8350-core.c8
-rw-r--r--drivers/mfd/wm8350-regmap.c4
-rw-r--r--drivers/mfd/wm8400-core.c2
-rw-r--r--drivers/misc/eeprom/Kconfig14
-rw-r--r--drivers/misc/eeprom/Makefile1
-rw-r--r--drivers/misc/eeprom/at24.c8
-rw-r--r--drivers/misc/eeprom/at25.c5
-rw-r--r--drivers/misc/eeprom/max6875.c (renamed from drivers/i2c/chips/max6875.c)2
-rw-r--r--drivers/misc/isl29003.c9
-rw-r--r--drivers/misc/sgi-gru/grufile.c2
-rw-r--r--drivers/misc/sgi-xp/xp_main.c12
-rw-r--r--drivers/misc/sgi-xp/xpc.h254
-rw-r--r--drivers/misc/sgi-xp/xpc_channel.c138
-rw-r--r--drivers/misc/sgi-xp/xpc_main.c128
-rw-r--r--drivers/misc/sgi-xp/xpc_partition.c20
-rw-r--r--drivers/misc/sgi-xp/xpc_sn2.c164
-rw-r--r--drivers/misc/sgi-xp/xpc_uv.c257
-rw-r--r--drivers/mmc/card/block.c8
-rw-r--r--drivers/mmc/core/core.c103
-rw-r--r--drivers/mmc/host/atmel-mci.c12
-rw-r--r--drivers/mmc/host/mmc_spi.c12
-rw-r--r--drivers/mmc/host/mmci.c2
-rw-r--r--drivers/mmc/host/mvsdio.c11
-rw-r--r--drivers/mmc/host/omap.c5
-rw-r--r--drivers/mmc/host/omap_hsmmc.c2
-rw-r--r--drivers/mmc/host/sdhci-pci.c8
-rw-r--r--drivers/mmc/host/sdhci.c53
-rw-r--r--drivers/mmc/host/sdhci.h4
-rw-r--r--drivers/mtd/Kconfig3
-rw-r--r--drivers/mtd/devices/m25p80.c26
-rw-r--r--drivers/mtd/mtd_blkdevs.c22
-rw-r--r--drivers/mtd/mtdcore.c18
-rw-r--r--drivers/mtd/mtdsuper.c3
-rw-r--r--drivers/mtd/nand/cafe_nand.c2
-rw-r--r--drivers/net/appletalk/ltpc.c2
-rw-r--r--drivers/net/arm/ep93xx_eth.c2
-rw-r--r--drivers/net/arm/ixp4xx_eth.c31
-rw-r--r--drivers/net/atl1c/atl1c_main.c4
-rw-r--r--drivers/net/b44.h2
-rw-r--r--drivers/net/benet/be_main.c4
-rw-r--r--drivers/net/bonding/bond_3ad.h4
-rw-r--r--drivers/net/bonding/bond_main.c8
-rw-r--r--drivers/net/e100.c2
-rw-r--r--drivers/net/e1000e/e1000.h2
-rw-r--r--drivers/net/ehea/ehea.h2
-rw-r--r--drivers/net/igbvf/igbvf.h2
-rw-r--r--drivers/net/ipg.h2
-rw-r--r--drivers/net/jme.c8
-rw-r--r--drivers/net/mlx4/en_netdev.c2
-rw-r--r--drivers/net/mlx4/main.c2
-rw-r--r--drivers/net/netxen/netxen_nic.h3
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c13
-rw-r--r--drivers/net/netxen/netxen_nic_main.c75
-rw-r--r--drivers/net/niu.h4
-rw-r--r--drivers/net/qlge/qlge_mpi.c6
-rw-r--r--drivers/net/skfp/h/smt.h2
-rw-r--r--drivers/net/tokenring/3c359.c2
-rw-r--r--drivers/net/tokenring/lanstreamer.c2
-rw-r--r--drivers/net/tokenring/olympic.c2
-rw-r--r--drivers/net/ucc_geth.c24
-rw-r--r--drivers/net/ucc_geth.h4
-rw-r--r--drivers/net/ucc_geth_ethtool.c2
-rw-r--r--drivers/net/wan/ixp4xx_hss.c4
-rw-r--r--drivers/net/wireless/airo.c10
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c22
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.c51
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c59
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/phy.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/phy.h2
-rw-r--r--drivers/net/wireless/b43/rfkill.c1
-rw-r--r--drivers/net/wireless/b43legacy/rfkill.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c89
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c91
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-calib.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c62
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.c233
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.h39
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rfkill.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c56
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c2
-rw-r--r--drivers/net/wireless/mwl8k.c2
-rw-r--r--drivers/net/wireless/p54/p54pci.c4
-rw-r--r--drivers/net/wireless/rndis_wlan.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c2
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187.h57
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_dev.c13
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_rtl8225.c8
-rw-r--r--drivers/net/wireless/wavelan_cs.c2
-rw-r--r--drivers/net/wireless/wl12xx/Kconfig2
-rw-r--r--drivers/of/base.c1
-rw-r--r--drivers/parisc/iosapic.c6
-rw-r--r--drivers/parisc/superio.c3
-rw-r--r--drivers/pci/access.c4
-rw-r--r--drivers/pci/bus.c7
-rw-r--r--drivers/pci/dmar.c44
-rw-r--r--drivers/pci/hotplug/Kconfig2
-rw-r--r--drivers/pci/hotplug/cpqphp.h167
-rw-r--r--drivers/pci/hotplug/cpqphp_core.c1101
-rw-r--r--drivers/pci/hotplug/cpqphp_ctrl.c371
-rw-r--r--drivers/pci/hotplug/cpqphp_nvram.c97
-rw-r--r--drivers/pci/hotplug/cpqphp_pci.c599
-rw-r--r--drivers/pci/hotplug/ibmphp_core.c1
-rw-r--r--drivers/pci/htirq.c5
-rw-r--r--drivers/pci/intel-iommu.c342
-rw-r--r--drivers/pci/intr_remapping.c62
-rw-r--r--drivers/pci/msi.c2
-rw-r--r--drivers/pci/msi.h14
-rw-r--r--drivers/pci/pci-sysfs.c12
-rw-r--r--drivers/pci/pci.c70
-rw-r--r--drivers/pci/pcie/aer/aerdrv.h3
-rw-r--r--drivers/pci/pcie/portdrv_core.c2
-rw-r--r--drivers/pci/pcie/portdrv_pci.c2
-rw-r--r--drivers/pci/probe.c15
-rw-r--r--drivers/pci/quirks.c1
-rw-r--r--drivers/pci/search.c30
-rw-r--r--drivers/pci/setup-bus.c59
-rw-r--r--drivers/pci/setup-res.c49
-rw-r--r--drivers/pci/slot.c4
-rw-r--r--drivers/pcmcia/pxa2xx_sharpsl.c3
-rw-r--r--drivers/platform/x86/Kconfig13
-rw-r--r--drivers/platform/x86/Makefile1
-rw-r--r--drivers/platform/x86/acer-wmi.c1
-rw-r--r--drivers/platform/x86/hp-wmi.c3
-rw-r--r--drivers/platform/x86/oqo-wmi.c941
-rw-r--r--drivers/platform/x86/sony-laptop.c31
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c81
-rw-r--r--drivers/platform/x86/toshiba_acpi.c207
-rw-r--r--drivers/pnp/pnpacpi/core.c8
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c2
-rw-r--r--drivers/regulator/Kconfig19
-rw-r--r--drivers/regulator/Makefile2
-rw-r--r--drivers/regulator/bq24022.c3
-rw-r--r--drivers/regulator/core.c19
-rw-r--r--drivers/regulator/da903x.c2
-rw-r--r--drivers/regulator/fixed.c18
-rw-r--r--drivers/regulator/max1586.c249
-rw-r--r--drivers/regulator/pcf50633-regulator.c2
-rw-r--r--drivers/regulator/userspace-consumer.c200
-rw-r--r--drivers/regulator/virtual.c9
-rw-r--r--drivers/regulator/wm8350-regulator.c1
-rw-r--r--drivers/regulator/wm8400-regulator.c8
-rw-r--r--drivers/rtc/Kconfig23
-rw-r--r--drivers/rtc/Makefile2
-rw-r--r--drivers/rtc/rtc-cmos.c20
-rw-r--r--drivers/rtc/rtc-ep93xx.c149
-rw-r--r--drivers/rtc/rtc-msm6242.c268
-rw-r--r--drivers/rtc/rtc-rp5c01.c222
-rw-r--r--drivers/rtc/rtc-sh.c67
-rw-r--r--drivers/s390/block/dasd.c54
-rw-r--r--drivers/s390/block/dasd_eckd.c16
-rw-r--r--drivers/s390/char/tape.h2
-rw-r--r--drivers/s390/char/tape_34xx.c8
-rw-r--r--drivers/s390/char/tape_3590.c8
-rw-r--r--drivers/s390/char/tape_block.c15
-rw-r--r--drivers/s390/char/tape_core.c5
-rw-r--r--drivers/s390/cio/cio.c2
-rw-r--r--drivers/s390/cio/device_ops.c24
-rw-r--r--drivers/s390/cio/qdio_main.c85
-rw-r--r--drivers/s390/scsi/zfcp_aux.c11
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c1
-rw-r--r--drivers/s390/scsi/zfcp_cfdc.c3
-rw-r--r--drivers/s390/scsi/zfcp_def.h2
-rw-r--r--drivers/s390/scsi/zfcp_erp.c60
-rw-r--r--drivers/s390/scsi/zfcp_ext.h2
-rw-r--r--drivers/s390/scsi/zfcp_fc.c35
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c59
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c44
-rw-r--r--drivers/s390/scsi/zfcp_sysfs.c21
-rw-r--r--drivers/sbus/char/jsflash.c23
-rw-r--r--drivers/sbus/char/uctrl.c7
-rw-r--r--drivers/scsi/3w-9xxx.c8
-rw-r--r--drivers/scsi/Kconfig1
-rw-r--r--drivers/scsi/Makefile2
-rw-r--r--drivers/scsi/a4000t.c2
-rw-r--r--drivers/scsi/aacraid/aachba.c2
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i.h2
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_ddp.c32
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_iscsi.c5
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_offload.c4
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_pdu.c19
-rw-r--r--drivers/scsi/dpt/osd_util.h2
-rw-r--r--drivers/scsi/fcoe/fcoe.c59
-rw-r--r--drivers/scsi/fcoe/libfcoe.c2
-rw-r--r--drivers/scsi/ipr.c13
-rw-r--r--drivers/scsi/iscsi_tcp.c3
-rw-r--r--drivers/scsi/libfc/fc_disc.c54
-rw-r--r--drivers/scsi/libfc/fc_elsct.c2
-rw-r--r--drivers/scsi/libfc/fc_fcp.c7
-rw-r--r--drivers/scsi/libfc/fc_lport.c74
-rw-r--r--drivers/scsi/libfc/fc_rport.c82
-rw-r--r--drivers/scsi/libiscsi.c10
-rw-r--r--drivers/scsi/libiscsi_tcp.c5
-rw-r--r--drivers/scsi/lpfc/lpfc.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c266
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c45
-rw-r--r--drivers/scsi/lpfc/lpfc_disc.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c245
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c88
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c205
-rw-r--r--drivers/scsi/lpfc/lpfc_logmsg.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c63
-rw-r--r--drivers/scsi/lpfc/lpfc_mem.c19
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c18
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c132
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c401
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h6
-rw-r--r--drivers/scsi/lpfc/lpfc_vport.c10
-rw-r--r--drivers/scsi/megaraid.h2
-rw-r--r--drivers/scsi/megaraid/mbox_defs.h2
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c85
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h30
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.c216
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.h7
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c29
-rw-r--r--drivers/scsi/mvsas.c3222
-rw-r--r--drivers/scsi/mvsas/Kconfig42
-rw-r--r--drivers/scsi/mvsas/Makefile32
-rw-r--r--drivers/scsi/mvsas/mv_64xx.c793
-rw-r--r--drivers/scsi/mvsas/mv_64xx.h151
-rw-r--r--drivers/scsi/mvsas/mv_94xx.c672
-rw-r--r--drivers/scsi/mvsas/mv_94xx.h222
-rw-r--r--drivers/scsi/mvsas/mv_chips.h280
-rw-r--r--drivers/scsi/mvsas/mv_defs.h502
-rw-r--r--drivers/scsi/mvsas/mv_init.c703
-rw-r--r--drivers/scsi/mvsas/mv_sas.c2157
-rw-r--r--drivers/scsi/mvsas/mv_sas.h406
-rw-r--r--drivers/scsi/osd/osd_initiator.c125
-rw-r--r--drivers/scsi/osd/osd_uld.c20
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c81
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c7
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h34
-rw-r--r--drivers/scsi/qla2xxx/qla_fw.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h29
-rw-r--r--drivers/scsi/qla2xxx/qla_gs.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c90
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c59
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c236
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c90
-rw-r--r--drivers/scsi/qla2xxx/qla_mid.c118
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c233
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c38
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h2
-rw-r--r--drivers/scsi/scsi_lib.c7
-rw-r--r--drivers/scsi/scsi_scan.c2
-rw-r--r--drivers/scsi/scsi_transport_fc.c616
-rw-r--r--drivers/scsi/scsi_wait_scan.c11
-rw-r--r--drivers/scsi/sd.c15
-rw-r--r--drivers/scsi/sg.c14
-rw-r--r--drivers/scsi/sr_ioctl.c5
-rw-r--r--drivers/serial/8250_pci.c2
-rw-r--r--drivers/serial/bfin_5xx.c6
-rw-r--r--drivers/serial/crisv10.c173
-rw-r--r--drivers/serial/jsm/jsm.h2
-rw-r--r--drivers/serial/jsm/jsm_driver.c1
-rw-r--r--drivers/serial/s3c6400.c1
-rw-r--r--drivers/serial/samsung.c65
-rw-r--r--drivers/serial/samsung.h4
-rw-r--r--drivers/serial/sh-sci.c385
-rw-r--r--drivers/serial/sh-sci.h42
-rw-r--r--drivers/sh/intc.c35
-rw-r--r--drivers/spi/pxa2xx_spi.c15
-rw-r--r--drivers/spi/spi.c22
-rw-r--r--drivers/staging/android/binder.c201
-rw-r--r--drivers/staging/at76_usb/at76_usb.c20
-rw-r--r--drivers/staging/b3dfg/b3dfg.c2
-rw-r--r--drivers/staging/comedi/TODO1
-rw-r--r--drivers/staging/epl/VirtualEthernetLinux.c17
-rw-r--r--drivers/staging/et131x/et131x_netdev.c23
-rw-r--r--drivers/staging/go7007/go7007-driver.c26
-rw-r--r--drivers/staging/go7007/go7007-i2c.c83
-rw-r--r--drivers/staging/go7007/go7007-priv.h1
-rw-r--r--drivers/staging/go7007/go7007-usb.c14
-rw-r--r--drivers/staging/go7007/go7007.txt4
-rw-r--r--drivers/staging/go7007/s2250-board.c71
-rw-r--r--drivers/staging/go7007/wis-i2c.h9
-rw-r--r--drivers/staging/go7007/wis-ov7640.c56
-rw-r--r--drivers/staging/go7007/wis-saa7113.c60
-rw-r--r--drivers/staging/go7007/wis-saa7115.c60
-rw-r--r--drivers/staging/go7007/wis-sony-tuner.c62
-rw-r--r--drivers/staging/go7007/wis-tw2804.c57
-rw-r--r--drivers/staging/go7007/wis-tw9903.c60
-rw-r--r--drivers/staging/go7007/wis-uda1342.c52
-rw-r--r--drivers/staging/line6/audio.c9
-rw-r--r--drivers/staging/otus/usbdrv.c47
-rw-r--r--drivers/staging/otus/zdusb.c3
-rw-r--r--drivers/staging/otus/zdusb.h4
-rw-r--r--drivers/staging/panel/lcd-panel-cgram.txt2
-rw-r--r--drivers/staging/pohmelfs/config.c61
-rw-r--r--drivers/staging/pohmelfs/dir.c24
-rw-r--r--drivers/staging/pohmelfs/inode.c137
-rw-r--r--drivers/staging/pohmelfs/lock.c3
-rw-r--r--drivers/staging/pohmelfs/net.c72
-rw-r--r--drivers/staging/pohmelfs/netfs.h21
-rw-r--r--drivers/staging/pohmelfs/trans.c33
-rw-r--r--drivers/staging/rt2860/common/mlme.c2
-rw-r--r--drivers/staging/rt2860/rt_main_dev.c25
-rw-r--r--drivers/staging/rt2870/common/mlme.c2
-rw-r--r--drivers/staging/rt2870/rt2870.h2
-rw-r--r--drivers/staging/rt2870/rt_main_dev.c28
-rw-r--r--drivers/staging/rt3070/common/mlme.c2
-rw-r--r--drivers/staging/rt3070/rt_main_dev.c29
-rw-r--r--drivers/staging/rtl8187se/r8180.h2
-rw-r--r--drivers/staging/rtl8187se/r8180_core.c46
-rw-r--r--drivers/staging/slicoss/README31
-rw-r--r--drivers/staging/slicoss/slicoss.c25
-rw-r--r--drivers/staging/stlc45xx/Kconfig2
-rw-r--r--drivers/staging/sxg/sxg.c127
-rw-r--r--drivers/staging/uc2322/aten2011.c28
-rw-r--r--drivers/staging/winbond/wbusb.c9
-rw-r--r--drivers/staging/wlan-ng/p80211netdev.c20
-rw-r--r--drivers/uio/uio_cif.c1
-rw-r--r--drivers/usb/Makefile2
-rw-r--r--drivers/usb/class/cdc-acm.c446
-rw-r--r--drivers/usb/class/cdc-acm.h5
-rw-r--r--drivers/usb/class/cdc-wdm.c27
-rw-r--r--drivers/usb/core/buffer.c2
-rw-r--r--drivers/usb/core/devio.c2
-rw-r--r--drivers/usb/core/hcd.c26
-rw-r--r--drivers/usb/core/hcd.h14
-rw-r--r--drivers/usb/core/message.c58
-rw-r--r--drivers/usb/core/usb.c2
-rw-r--r--drivers/usb/gadget/ci13xxx_udc.c5
-rw-r--r--drivers/usb/gadget/file_storage.c20
-rw-r--r--drivers/usb/gadget/omap_udc.c3
-rw-r--r--drivers/usb/gadget/u_ether.c8
-rw-r--r--drivers/usb/gadget/usbstring.c6
-rw-r--r--drivers/usb/host/ehci-sched.c2
-rw-r--r--drivers/usb/host/whci/asl.c15
-rw-r--r--drivers/usb/host/whci/hcd.c23
-rw-r--r--drivers/usb/host/whci/pzl.c16
-rw-r--r--drivers/usb/host/whci/qset.c24
-rw-r--r--drivers/usb/host/whci/whcd.h1
-rw-r--r--drivers/usb/host/whci/whci-hc.h1
-rw-r--r--drivers/usb/musb/cppi_dma.c23
-rw-r--r--drivers/usb/musb/musb_core.c14
-rw-r--r--drivers/usb/musb/musb_gadget.c33
-rw-r--r--drivers/usb/musb/musb_host.c406
-rw-r--r--drivers/usb/musb/musbhsdma.c66
-rw-r--r--drivers/usb/musb/omap2430.c1
-rw-r--r--drivers/usb/musb/tusb6010.c1
-rw-r--r--drivers/usb/musb/tusb6010.h1
-rw-r--r--drivers/usb/otg/nop-usb-xceiv.c4
-rw-r--r--drivers/usb/otg/otg.c3
-rw-r--r--drivers/usb/serial/belkin_sa.c6
-rw-r--r--drivers/usb/serial/ch341.c46
-rw-r--r--drivers/usb/serial/console.c6
-rw-r--r--drivers/usb/serial/cp210x.c6
-rw-r--r--drivers/usb/serial/cyberjack.c13
-rw-r--r--drivers/usb/serial/cypress_m8.c85
-rw-r--r--drivers/usb/serial/digi_acceleport.c75
-rw-r--r--drivers/usb/serial/empeg.c12
-rw-r--r--drivers/usb/serial/ftdi_sio.c71
-rw-r--r--drivers/usb/serial/ftdi_sio.h13
-rw-r--r--drivers/usb/serial/garmin_gps.c11
-rw-r--r--drivers/usb/serial/generic.c9
-rw-r--r--drivers/usb/serial/io_edgeport.c18
-rw-r--r--drivers/usb/serial/io_ti.c13
-rw-r--r--drivers/usb/serial/ipaq.c12
-rw-r--r--drivers/usb/serial/ipw.c21
-rw-r--r--drivers/usb/serial/ir-usb.c6
-rw-r--r--drivers/usb/serial/iuu_phoenix.c26
-rw-r--r--drivers/usb/serial/keyspan.c13
-rw-r--r--drivers/usb/serial/keyspan.h8
-rw-r--r--drivers/usb/serial/keyspan_pda.c48
-rw-r--r--drivers/usb/serial/kl5kusb105.c6
-rw-r--r--drivers/usb/serial/kobil_sct.c15
-rw-r--r--drivers/usb/serial/mct_u232.c37
-rw-r--r--drivers/usb/serial/mos7720.c10
-rw-r--r--drivers/usb/serial/mos7840.c91
-rw-r--r--drivers/usb/serial/moto_modem.c1
-rw-r--r--drivers/usb/serial/navman.c3
-rw-r--r--drivers/usb/serial/omninet.c6
-rw-r--r--drivers/usb/serial/opticon.c11
-rw-r--r--drivers/usb/serial/option.c76
-rw-r--r--drivers/usb/serial/oti6858.c57
-rw-r--r--drivers/usb/serial/pl2303.c79
-rw-r--r--drivers/usb/serial/qcserial.c21
-rw-r--r--drivers/usb/serial/sierra.c89
-rw-r--r--drivers/usb/serial/spcp8x5.c85
-rw-r--r--drivers/usb/serial/symbolserial.c3
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c46
-rw-r--r--drivers/usb/serial/usb-serial.c218
-rw-r--r--drivers/usb/serial/visor.c14
-rw-r--r--drivers/usb/serial/whiteheat.c33
-rw-r--r--drivers/usb/storage/Makefile3
-rw-r--r--drivers/usb/storage/transport.c4
-rw-r--r--drivers/usb/storage/unusual_devs.h25
-rw-r--r--drivers/usb/wusbcore/devconnect.c21
-rw-r--r--drivers/usb/wusbcore/wusbhc.c32
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/asiliantfb.c1
-rw-r--r--drivers/video/aty/aty128fb.c2
-rw-r--r--drivers/video/aty/radeon_base.c4
-rw-r--r--drivers/video/backlight/backlight.c3
-rw-r--r--drivers/video/backlight/lcd.c3
-rw-r--r--drivers/video/cfbfillrect.c36
-rw-r--r--drivers/video/cirrusfb.c4
-rw-r--r--drivers/video/console/fbcon.c55
-rw-r--r--drivers/video/console/vgacon.c2
-rw-r--r--drivers/video/cyber2000fb.c9
-rw-r--r--drivers/video/efifb.c7
-rw-r--r--drivers/video/fb_draw.h21
-rw-r--r--drivers/video/fbmem.c19
-rw-r--r--drivers/video/intelfb/intelfb.h2
-rw-r--r--drivers/video/intelfb/intelfb_i2c.c1
-rw-r--r--drivers/video/intelfb/intelfbdrv.c1
-rw-r--r--drivers/video/intelfb/intelfbhw.c5
-rw-r--r--drivers/video/logo/logo_linux_clut224.ppm4428
-rw-r--r--drivers/video/logo/logo_linux_vga16.ppm4339
-rw-r--r--drivers/video/mx3fb.c14
-rw-r--r--drivers/video/pxafb.c16
-rw-r--r--drivers/video/s3fb.c6
-rw-r--r--drivers/video/sa1100fb.c15
-rw-r--r--drivers/video/sa1100fb.h7
-rw-r--r--drivers/video/sis/sis_main.c2
-rw-r--r--drivers/video/skeletonfb.c8
-rw-r--r--drivers/video/sysfillrect.c30
-rw-r--r--drivers/video/tdfxfb.c1
-rw-r--r--drivers/video/uvesafb.c45
-rw-r--r--drivers/video/vfb.c11
-rw-r--r--drivers/virtio/virtio_balloon.c3
-rw-r--r--drivers/watchdog/alim7101_wdt.c15
-rw-r--r--drivers/watchdog/ar7_wdt.c3
-rw-r--r--drivers/watchdog/at91rm9200_wdt.c3
-rw-r--r--drivers/watchdog/at91sam9_wdt.c3
-rw-r--r--drivers/watchdog/bfin_wdt.c14
-rw-r--r--drivers/watchdog/cpwd.c6
-rw-r--r--drivers/watchdog/davinci_wdt.c6
-rw-r--r--drivers/watchdog/iTCO_vendor_support.c6
-rw-r--r--drivers/watchdog/iTCO_wdt.c24
-rw-r--r--drivers/watchdog/indydog.c4
-rw-r--r--drivers/watchdog/iop_wdt.c2
-rw-r--r--drivers/watchdog/it8712f_wdt.c3
-rw-r--r--drivers/watchdog/ks8695_wdt.c4
-rw-r--r--drivers/watchdog/machzwd.c9
-rw-r--r--drivers/watchdog/mpcore_wdt.c7
-rw-r--r--drivers/watchdog/mtx-1_wdt.c6
-rw-r--r--drivers/watchdog/orion5x_wdt.c1
-rw-r--r--drivers/watchdog/pnx4008_wdt.c6
-rw-r--r--drivers/watchdog/rdc321x_wdt.c4
-rw-r--r--drivers/watchdog/rm9k_wdt.c6
-rw-r--r--drivers/watchdog/s3c2410_wdt.c32
-rw-r--r--drivers/watchdog/sb_wdog.c9
-rw-r--r--drivers/watchdog/sbc60xxwdt.c5
-rw-r--r--drivers/watchdog/sbc8360.c4
-rw-r--r--drivers/watchdog/sbc_epx_c3.c12
-rw-r--r--drivers/watchdog/scx200_wdt.c7
-rw-r--r--drivers/watchdog/shwdt.c4
-rw-r--r--drivers/watchdog/softdog.c7
-rw-r--r--drivers/watchdog/w83697hf_wdt.c3
-rw-r--r--drivers/watchdog/wdrtas.c7
-rw-r--r--drivers/xen/Kconfig20
-rw-r--r--drivers/xen/Makefile4
-rw-r--r--drivers/xen/balloon.c3
-rw-r--r--drivers/xen/cpu_hotplug.c40
-rw-r--r--drivers/xen/events.c20
-rw-r--r--drivers/xen/evtchn.c507
-rw-r--r--drivers/xen/manage.c14
-rw-r--r--drivers/xen/sys-hypervisor.c445
-rw-r--r--drivers/xen/xenbus/xenbus_probe.c61
-rw-r--r--drivers/xen/xenbus/xenbus_xs.c2
-rw-r--r--drivers/xen/xenfs/super.c19
-rw-r--r--fs/9p/vfs_super.c12
-rw-r--r--fs/Kconfig10
-rw-r--r--fs/adfs/super.c4
-rw-r--r--fs/affs/super.c8
-rw-r--r--fs/afs/file.c2
-rw-r--r--fs/afs/mntpt.c2
-rw-r--r--fs/afs/super.c11
-rw-r--r--fs/autofs/dirhash.c33
-rw-r--r--fs/autofs4/autofs_i.h6
-rw-r--r--fs/autofs4/dev-ioctl.c203
-rw-r--r--fs/autofs4/expire.c17
-rw-r--r--fs/autofs4/root.c7
-rw-r--r--fs/befs/linuxvfs.c5
-rw-r--r--fs/bfs/inode.c8
-rw-r--r--fs/binfmt_elf_fdpic.c4
-rw-r--r--fs/bio.c125
-rw-r--r--fs/block_dev.c32
-rw-r--r--fs/btrfs/Makefile19
-rw-r--r--fs/btrfs/acl.c18
-rw-r--r--fs/btrfs/async-thread.c60
-rw-r--r--fs/btrfs/async-thread.h2
-rw-r--r--fs/btrfs/ctree.c17
-rw-r--r--fs/btrfs/ctree.h6
-rw-r--r--fs/btrfs/disk-io.c102
-rw-r--r--fs/btrfs/extent-tree.c51
-rw-r--r--fs/btrfs/extent_io.c167
-rw-r--r--fs/btrfs/extent_map.c17
-rw-r--r--fs/btrfs/file.c95
-rw-r--r--fs/btrfs/free-space-cache.c15
-rw-r--r--fs/btrfs/inode-map.c2
-rw-r--r--fs/btrfs/inode.c190
-rw-r--r--fs/btrfs/ioctl.c58
-rw-r--r--fs/btrfs/ordered-data.c2
-rw-r--r--fs/btrfs/super.c67
-rw-r--r--fs/btrfs/transaction.c6
-rw-r--r--fs/btrfs/tree-log.c2
-rw-r--r--fs/btrfs/volumes.c159
-rw-r--r--fs/btrfs/volumes.h16
-rw-r--r--fs/buffer.c66
-rw-r--r--fs/cachefiles/interface.c4
-rw-r--r--fs/cifs/CHANGES16
-rw-r--r--fs/cifs/README10
-rw-r--r--fs/cifs/cifs_dfs_ref.c34
-rw-r--r--fs/cifs/cifs_spnego.c2
-rw-r--r--fs/cifs/cifs_unicode.c198
-rw-r--r--fs/cifs/cifs_unicode.h23
-rw-r--r--fs/cifs/cifsfs.c60
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifsglob.h19
-rw-r--r--fs/cifs/cifspdu.h8
-rw-r--r--fs/cifs/cifsproto.h5
-rw-r--r--fs/cifs/cifssmb.c223
-rw-r--r--fs/cifs/connect.c1357
-rw-r--r--fs/cifs/dir.c160
-rw-r--r--fs/cifs/dns_resolve.c2
-rw-r--r--fs/cifs/file.c141
-rw-r--r--fs/cifs/inode.c98
-rw-r--r--fs/cifs/link.c114
-rw-r--r--fs/cifs/misc.c71
-rw-r--r--fs/cifs/netmisc.c2
-rw-r--r--fs/cifs/nterr.h9
-rw-r--r--fs/cifs/ntlmssp.h68
-rw-r--r--fs/cifs/readdir.c78
-rw-r--r--fs/cifs/sess.c373
-rw-r--r--fs/cifs/smberr.h1
-rw-r--r--fs/compat.c58
-rw-r--r--fs/compat_ioctl.c9
-rw-r--r--fs/configfs/configfs_internal.h3
-rw-r--r--fs/configfs/dir.c193
-rw-r--r--fs/configfs/inode.c38
-rw-r--r--fs/configfs/symlink.c2
-rw-r--r--fs/dcache.c10
-rw-r--r--fs/devpts/inode.c5
-rw-r--r--fs/direct-io.c2
-rw-r--r--fs/dlm/lockspace.c17
-rw-r--r--fs/ecryptfs/crypto.c21
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h1
-rw-r--r--fs/ecryptfs/inode.c37
-rw-r--r--fs/ecryptfs/main.c19
-rw-r--r--fs/ecryptfs/messaging.c82
-rw-r--r--fs/ecryptfs/miscdev.c43
-rw-r--r--fs/ecryptfs/mmap.c11
-rw-r--r--fs/ecryptfs/read_write.c32
-rw-r--r--fs/ecryptfs/super.c12
-rw-r--r--fs/exec.c121
-rw-r--r--fs/exofs/super.c7
-rw-r--r--fs/ext2/ext2.h2
-rw-r--r--fs/ext2/inode.c44
-rw-r--r--fs/ext2/super.c11
-rw-r--r--fs/ext3/acl.c13
-rw-r--r--fs/ext3/balloc.c3
-rw-r--r--fs/ext3/ialloc.c3
-rw-r--r--fs/ext3/inode.c1
-rw-r--r--fs/ext3/resize.c2
-rw-r--r--fs/ext3/super.c30
-rw-r--r--fs/ext3/xattr.c1
-rw-r--r--fs/ext4/acl.c13
-rw-r--r--fs/ext4/balloc.c28
-rw-r--r--fs/ext4/ext4.h310
-rw-r--r--fs/ext4/ext4_i.h140
-rw-r--r--fs/ext4/ext4_sb.h161
-rw-r--r--fs/ext4/extents.c33
-rw-r--r--fs/ext4/group.h29
-rw-r--r--fs/ext4/ialloc.c76
-rw-r--r--fs/ext4/inode.c43
-rw-r--r--fs/ext4/mballoc.c145
-rw-r--r--fs/ext4/mballoc.h1
-rw-r--r--fs/ext4/namei.c22
-rw-r--r--fs/ext4/namei.h8
-rw-r--r--fs/ext4/resize.c36
-rw-r--r--fs/ext4/super.c233
-rw-r--r--fs/fat/Kconfig3
-rw-r--r--fs/fat/inode.c7
-rw-r--r--fs/fcntl.c6
-rw-r--r--fs/file_table.c40
-rw-r--r--fs/filesystems.c2
-rw-r--r--fs/freevxfs/vxfs_super.c4
-rw-r--r--fs/fs-writeback.c49
-rw-r--r--fs/fuse/Makefile1
-rw-r--r--fs/fuse/cuse.c610
-rw-r--r--fs/fuse/dev.c15
-rw-r--r--fs/fuse/dir.c33
-rw-r--r--fs/fuse/file.c354
-rw-r--r--fs/fuse/fuse_i.h47
-rw-r--r--fs/fuse/inode.c124
-rw-r--r--fs/gfs2/glock.c11
-rw-r--r--fs/gfs2/glops.c6
-rw-r--r--fs/gfs2/inode.c8
-rw-r--r--fs/gfs2/inode.h14
-rw-r--r--fs/gfs2/log.c8
-rw-r--r--fs/gfs2/lops.c14
-rw-r--r--fs/gfs2/meta_io.c104
-rw-r--r--fs/gfs2/ops_file.c41
-rw-r--r--fs/gfs2/ops_fstype.c13
-rw-r--r--fs/gfs2/ops_inode.c1
-rw-r--r--fs/gfs2/ops_super.c15
-rw-r--r--fs/gfs2/quota.c4
-rw-r--r--fs/gfs2/rgrp.c13
-rw-r--r--fs/hfs/inode.c4
-rw-r--r--fs/hfs/mdb.c1
-rw-r--r--fs/hfs/super.c6
-rw-r--r--fs/hfsplus/super.c7
-rw-r--r--fs/hpfs/super.c11
-rw-r--r--fs/hugetlbfs/inode.c3
-rw-r--r--fs/inode.c121
-rw-r--r--fs/internal.h17
-rw-r--r--fs/ioctl.c75
-rw-r--r--fs/isofs/inode.c5
-rw-r--r--fs/jbd/commit.c2
-rw-r--r--fs/jbd/revoke.c44
-rw-r--r--fs/jbd2/commit.c3
-rw-r--r--fs/jbd2/revoke.c21
-rw-r--r--fs/jffs2/super.c7
-rw-r--r--fs/jfs/super.c9
-rw-r--r--fs/libfs.c3
-rw-r--r--fs/lockd/svc.c15
-rw-r--r--fs/lockd/svclock.c2
-rw-r--r--fs/locks.c3
-rw-r--r--fs/minix/inode.c4
-rw-r--r--fs/namei.c144
-rw-r--r--fs/namespace.c357
-rw-r--r--fs/ncpfs/inode.c4
-rw-r--r--fs/ncpfs/ioctl.c21
-rw-r--r--fs/nfs/Kconfig9
-rw-r--r--fs/nfs/client.c124
-rw-r--r--fs/nfs/direct.c9
-rw-r--r--fs/nfs/file.c6
-rw-r--r--fs/nfs/internal.h62
-rw-r--r--fs/nfs/namespace.c2
-rw-r--r--fs/nfs/nfs3xdr.c3
-rw-r--r--fs/nfs/nfs4_fs.h37
-rw-r--r--fs/nfs/nfs4proc.c1229
-rw-r--r--fs/nfs/nfs4renewd.c6
-rw-r--r--fs/nfs/nfs4state.c130
-rw-r--r--fs/nfs/nfs4xdr.c1078
-rw-r--r--fs/nfs/read.c33
-rw-r--r--fs/nfs/super.c34
-rw-r--r--fs/nfs/unlink.c20
-rw-r--r--fs/nfs/write.c31
-rw-r--r--fs/nfsd/export.c91
-rw-r--r--fs/nfsd/nfs3xdr.c1
-rw-r--r--fs/nfsd/nfs4callback.c222
-rw-r--r--fs/nfsd/nfs4recover.c46
-rw-r--r--fs/nfsd/nfs4state.c120
-rw-r--r--fs/nfsd/nfs4xdr.c264
-rw-r--r--fs/nfsd/nfsctl.c284
-rw-r--r--fs/nfsd/vfs.c78
-rw-r--r--fs/nilfs2/bmap.c5
-rw-r--r--fs/nilfs2/ioctl.c281
-rw-r--r--fs/nilfs2/mdt.c15
-rw-r--r--fs/nilfs2/nilfs.h8
-rw-r--r--fs/nilfs2/page.c3
-rw-r--r--fs/nilfs2/recovery.c26
-rw-r--r--fs/nilfs2/segment.c5
-rw-r--r--fs/nilfs2/segment.h3
-rw-r--r--fs/nilfs2/sufile.c290
-rw-r--r--fs/nilfs2/sufile.h79
-rw-r--r--fs/nilfs2/super.c15
-rw-r--r--fs/nilfs2/the_nilfs.c4
-rw-r--r--fs/notify/inotify/inotify_user.c2
-rw-r--r--fs/ntfs/super.c6
-rw-r--r--fs/ocfs2/cluster/masklog.h35
-rw-r--r--fs/ocfs2/dcache.c15
-rw-r--r--fs/ocfs2/dir.c4
-rw-r--r--fs/ocfs2/export.c9
-rw-r--r--fs/ocfs2/file.c94
-rw-r--r--fs/ocfs2/journal.h5
-rw-r--r--fs/ocfs2/namei.c4
-rw-r--r--fs/ocfs2/suballoc.c21
-rw-r--r--fs/ocfs2/super.c18
-rw-r--r--fs/ocfs2/symlink.c77
-rw-r--r--fs/ocfs2/xattr.c5
-rw-r--r--fs/open.c6
-rw-r--r--fs/pipe.c42
-rw-r--r--fs/proc/array.c13
-rw-r--r--fs/proc/base.c15
-rw-r--r--fs/proc/internal.h25
-rw-r--r--fs/proc/meminfo.c2
-rw-r--r--fs/proc/proc_devtree.c1
-rw-r--r--fs/proc/root.c3
-rw-r--r--fs/proc/stat.c5
-rw-r--r--fs/proc/task_mmu.c4
-rw-r--r--fs/qnx4/inode.c9
-rw-r--r--fs/quota/Makefile9
-rw-r--r--fs/quota/quota.c25
-rw-r--r--fs/reiserfs/dir.c24
-rw-r--r--fs/reiserfs/namei.c17
-rw-r--r--fs/reiserfs/super.c37
-rw-r--r--fs/reiserfs/xattr.c181
-rw-r--r--fs/reiserfs/xattr_security.c12
-rw-r--r--fs/romfs/internal.h4
-rw-r--r--fs/romfs/storage.c68
-rw-r--r--fs/romfs/super.c7
-rw-r--r--fs/smbfs/inode.c4
-rw-r--r--fs/splice.c370
-rw-r--r--fs/squashfs/super.c4
-rw-r--r--fs/stat.c137
-rw-r--r--fs/super.c232
-rw-r--r--fs/sync.c119
-rw-r--r--fs/sysfs/bin.c13
-rw-r--r--fs/sysfs/file.c16
-rw-r--r--fs/sysv/inode.c9
-rw-r--r--fs/ubifs/budget.c3
-rw-r--r--fs/ubifs/super.c16
-rw-r--r--fs/udf/super.c5
-rw-r--r--fs/ufs/dir.c2
-rw-r--r--fs/ufs/file.c2
-rw-r--r--fs/ufs/super.c20
-rw-r--r--fs/ufs/ufs.h2
-rw-r--r--fs/xattr.c14
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c38
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.h1
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c9
-rw-r--r--fs/xfs/linux-2.6/xfs_fs_subr.c14
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c23
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c12
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c18
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c4
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.c78
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.h9
-rw-r--r--fs/xfs/xfs_bmap.c192
-rw-r--r--fs/xfs/xfs_dfrag.c8
-rw-r--r--fs/xfs/xfs_iget.c23
-rw-r--r--fs/xfs/xfs_inode.c2
-rw-r--r--fs/xfs/xfs_iomap.c61
-rw-r--r--fs/xfs/xfs_iomap.h3
-rw-r--r--fs/xfs/xfs_log.c78
-rw-r--r--fs/xfs/xfs_mount.c3
-rw-r--r--fs/xfs/xfs_mount.h2
-rw-r--r--fs/xfs/xfs_vnodeops.c7
-rw-r--r--include/Kbuild2
-rw-r--r--include/acpi/acpixf.h7
-rw-r--r--include/acpi/actypes.h20
-rw-r--r--include/acpi/platform/acgcc.h4
-rw-r--r--include/acpi/platform/aclinux.h63
-rw-r--r--include/acpi/processor.h1
-rw-r--r--include/acpi/video.h2
-rw-r--r--include/asm-arm/.gitignore2
-rw-r--r--include/asm-generic/atomic.h4
-rw-r--r--include/asm-generic/bug.h9
-rw-r--r--include/asm-generic/percpu.h35
-rw-r--r--include/asm-generic/pgtable.h21
-rw-r--r--include/asm-generic/siginfo.h2
-rw-r--r--include/asm-generic/vmlinux.lds.h9
-rw-r--r--include/drm/drm_pciids.h3
-rw-r--r--include/drm/i915_drm.h3
-rw-r--r--include/linux/Kbuild2
-rw-r--r--include/linux/acpi.h3
-rw-r--r--include/linux/atmel-mci.h2
-rw-r--r--include/linux/binfmts.h14
-rw-r--r--include/linux/bio.h110
-rw-r--r--include/linux/bitops.h19
-rw-r--r--include/linux/blkdev.h163
-rw-r--r--include/linux/blktrace_api.h32
-rw-r--r--include/linux/buffer_head.h3
-rw-r--r--include/linux/clocksource.h45
-rw-r--r--include/linux/compat.h2
-rw-r--r--include/linux/compiler.h5
-rw-r--r--include/linux/cpu.h5
-rw-r--r--include/linux/cyclades.h37
-rw-r--r--include/linux/dcache.h7
-rw-r--r--include/linux/debug_locks.h1
-rw-r--r--include/linux/device-mapper.h11
-rw-r--r--include/linux/device.h10
-rw-r--r--include/linux/dlm.h4
-rw-r--r--include/linux/dma-debug.h7
-rw-r--r--include/linux/dma_remapping.h8
-rw-r--r--include/linux/dmaengine.h6
-rw-r--r--include/linux/dmar.h3
-rw-r--r--include/linux/dynamic_debug.h2
-rw-r--r--include/linux/fb.h8
-rw-r--r--include/linux/fiemap.h2
-rw-r--r--include/linux/fs.h90
-rw-r--r--include/linux/fsl_devices.h8
-rw-r--r--include/linux/ftrace.h17
-rw-r--r--include/linux/ftrace_event.h156
-rw-r--r--include/linux/fuse.h31
-rw-r--r--include/linux/futex.h6
-rw-r--r--include/linux/gameport.h3
-rw-r--r--include/linux/genhd.h1
-rw-r--r--include/linux/i2c.h60
-rw-r--r--include/linux/ide.h27
-rw-r--r--include/linux/ieee80211.h8
-rw-r--r--include/linux/init.h13
-rw-r--r--include/linux/init_task.h18
-rw-r--r--include/linux/input.h24
-rw-r--r--include/linux/intel-iommu.h19
-rw-r--r--include/linux/interrupt.h2
-rw-r--r--include/linux/ioport.h2
-rw-r--r--include/linux/ipmi.h2
-rw-r--r--include/linux/ipmi_msgdefs.h8
-rw-r--r--include/linux/irq.h58
-rw-r--r--include/linux/jbd.h3
-rw-r--r--include/linux/jbd2.h3
-rw-r--r--include/linux/kernel.h9
-rw-r--r--include/linux/kgdb.h50
-rw-r--r--include/linux/kmemleak.h96
-rw-r--r--include/linux/kmemtrace.h25
-rw-r--r--include/linux/kvm.h48
-rw-r--r--include/linux/kvm_host.h23
-rw-r--r--include/linux/kvm_types.h27
-rw-r--r--include/linux/libata.h8
-rw-r--r--include/linux/loop.h3
-rw-r--r--include/linux/lsm_audit.h111
-rw-r--r--include/linux/magic.h5
-rw-r--r--include/linux/memcontrol.h6
-rw-r--r--include/linux/mg_disk.h206
-rw-r--r--include/linux/mm.h7
-rw-r--r--include/linux/mman.h9
-rw-r--r--include/linux/mmc/sdio_ids.h8
-rw-r--r--include/linux/mmiotrace.h2
-rw-r--r--include/linux/module.h8
-rw-r--r--include/linux/moduleparam.h40
-rw-r--r--include/linux/mount.h25
-rw-r--r--include/linux/mutex.h1
-rw-r--r--include/linux/namei.h6
-rw-r--r--include/linux/nfs4.h18
-rw-r--r--include/linux/nfs_fs_sb.h67
-rw-r--r--include/linux/nfs_xdr.h174
-rw-r--r--include/linux/nfsd/export.h6
-rw-r--r--include/linux/nfsd/nfsfh.h7
-rw-r--r--include/linux/nfsd/state.h24
-rw-r--r--include/linux/nfsd/xdr4.h17
-rw-r--r--include/linux/nl80211.h17
-rw-r--r--include/linux/nls.h19
-rw-r--r--include/linux/of_platform.h10
-rw-r--r--include/linux/page-flags.h2
-rw-r--r--include/linux/pci.h12
-rw-r--r--include/linux/pci_ids.h9
-rw-r--r--include/linux/pci_regs.h5
-rw-r--r--include/linux/percpu-defs.h84
-rw-r--r--include/linux/percpu.h49
-rw-r--r--include/linux/pipe_fs_i.h5
-rw-r--r--include/linux/pktcdvd.h1
-rw-r--r--include/linux/platform_device.h43
-rw-r--r--include/linux/poison.h16
-rw-r--r--include/linux/proc_fs.h24
-rw-r--r--include/linux/ptrace.h10
-rw-r--r--include/linux/quotaops.h20
-rw-r--r--include/linux/rcu_types.h18
-rw-r--r--include/linux/rculist.h30
-rw-r--r--include/linux/rcupdate.h11
-rw-r--r--include/linux/rcutree.h10
-rw-r--r--include/linux/regulator/driver.h1
-rw-r--r--include/linux/regulator/max1586.h52
-rw-r--r--include/linux/regulator/userspace-consumer.h25
-rw-r--r--include/linux/reiserfs_fs_sb.h5
-rw-r--r--include/linux/reiserfs_xattr.h3
-rw-r--r--include/linux/rfkill.h6
-rw-r--r--include/linux/ring_buffer.h52
-rw-r--r--include/linux/romfs_fs.h5
-rw-r--r--include/linux/rotary_encoder.h2
-rw-r--r--include/linux/sched.h30
-rw-r--r--include/linux/seccomp.h2
-rw-r--r--include/linux/section-names.h6
-rw-r--r--include/linux/serial_sci.h3
-rw-r--r--include/linux/serio.h9
-rw-r--r--include/linux/sh_cmt.h13
-rw-r--r--include/linux/sh_timer.h13
-rw-r--r--include/linux/sht15.h24
-rw-r--r--include/linux/signal.h2
-rw-r--r--include/linux/slab.h12
-rw-r--r--include/linux/slab_def.h2
-rw-r--r--include/linux/slow-work.h2
-rw-r--r--include/linux/slqb_def.h298
-rw-r--r--include/linux/slub_def.h2
-rw-r--r--include/linux/spi/ads7846.h1
-rw-r--r--include/linux/spi/spi.h7
-rw-r--r--include/linux/splice.h12
-rw-r--r--include/linux/sunrpc/clnt.h1
-rw-r--r--include/linux/sunrpc/sched.h1
-rw-r--r--include/linux/sunrpc/svc_xprt.h7
-rw-r--r--include/linux/sunrpc/svcsock.h7
-rw-r--r--include/linux/sunrpc/xprt.h1
-rw-r--r--include/linux/suspend.h36
-rw-r--r--include/linux/swiotlb.h3
-rw-r--r--include/linux/syscalls.h2
-rw-r--r--include/linux/thread_info.h3
-rw-r--r--include/linux/time.h15
-rw-r--r--include/linux/timex.h42
-rw-r--r--include/linux/trace_seq.h90
-rw-r--r--include/linux/tracepoint.h8
-rw-r--r--include/linux/tty.h6
-rw-r--r--include/linux/ultrasound.h2
-rw-r--r--include/linux/usb.h9
-rw-r--r--include/linux/usb/musb.h5
-rw-r--r--include/linux/usb/serial.h17
-rw-r--r--include/linux/wait.h2
-rw-r--r--include/linux/writeback.h1
-rw-r--r--include/media/ir-kbd-i2c.h10
-rw-r--r--include/media/soc_camera.h10
-rw-r--r--include/media/v4l2-device.h23
-rw-r--r--include/media/v4l2-subdev.h5
-rw-r--r--include/net/9p/client.h1
-rw-r--r--include/net/cfg80211.h24
-rw-r--r--include/net/mac80211.h28
-rw-r--r--include/scsi/Kbuild4
-rw-r--r--include/scsi/fc/fc_fs.h1
-rw-r--r--include/scsi/libfc.h1
-rw-r--r--include/scsi/libiscsi.h2
-rw-r--r--include/scsi/osd_protocol.h96
-rw-r--r--include/scsi/scsi_bsg_fc.h322
-rw-r--r--include/scsi/scsi_host.h9
-rw-r--r--include/scsi/scsi_transport_fc.h52
-rw-r--r--include/sound/core.h10
-rw-r--r--include/sound/driver.h1
-rw-r--r--include/sound/jack.h2
-rw-r--r--include/sound/pcm.h4
-rw-r--r--include/sound/pxa2xx-lib.h15
-rw-r--r--include/sound/soc-dai.h29
-rw-r--r--include/sound/soc-dapm.h19
-rw-r--r--include/sound/soc.h14
-rw-r--r--include/sound/version.h2
-rw-r--r--include/trace/block.h4
-rw-r--r--include/trace/define_trace.h75
-rw-r--r--include/trace/events/irq.h134
-rw-r--r--include/trace/events/kmem.h194
-rw-r--r--include/trace/events/lockdep.h96
-rw-r--r--include/trace/events/sched.h (renamed from include/trace/sched_event_types.h)20
-rw-r--r--include/trace/events/skb.h40
-rw-r--r--include/trace/ftrace.h509
-rw-r--r--include/trace/irq.h9
-rw-r--r--include/trace/irq_event_types.h55
-rw-r--r--include/trace/kmemtrace.h63
-rw-r--r--include/trace/lockdep.h9
-rw-r--r--include/trace/lockdep_event_types.h44
-rw-r--r--include/trace/sched.h9
-rw-r--r--include/trace/skb.h11
-rw-r--r--include/trace/trace_event_types.h5
-rw-r--r--include/trace/trace_events.h5
-rw-r--r--include/video/cyblafb.h175
-rw-r--r--include/xen/Kbuild1
-rw-r--r--include/xen/events.h3
-rw-r--r--include/xen/evtchn.h88
-rw-r--r--include/xen/interface/version.h3
-rw-r--r--include/xen/xenbus.h3
-rw-r--r--init/Kconfig30
-rw-r--r--init/initramfs.c18
-rw-r--r--init/main.c14
-rw-r--r--ipc/mq_sysctl.c2
-rw-r--r--ipc/sem.c4
-rw-r--r--kernel/Makefile1
-rw-r--r--kernel/audit_tree.c9
-rw-r--r--kernel/auditfilter.c4
-rw-r--r--kernel/cgroup.c3
-rw-r--r--kernel/compat.c11
-rw-r--r--kernel/cpu.c11
-rw-r--r--kernel/cred.c4
-rw-r--r--kernel/exit.c7
-rw-r--r--kernel/fork.c9
-rw-r--r--kernel/futex.c1200
-rw-r--r--kernel/irq/Makefile2
-rw-r--r--kernel/irq/chip.c12
-rw-r--r--kernel/irq/handle.c51
-rw-r--r--kernel/irq/internals.h5
-rw-r--r--kernel/irq/manage.c22
-rw-r--r--kernel/irq/migration.c14
-rw-r--r--kernel/irq/numa_migrate.c38
-rw-r--r--kernel/kgdb.c6
-rw-r--r--kernel/kprobes.c31
-rw-r--r--kernel/kthread.c5
-rw-r--r--kernel/lockdep.c38
-rw-r--r--kernel/module.c89
-rw-r--r--kernel/mutex.c29
-rw-r--r--kernel/panic.c15
-rw-r--r--kernel/params.c46
-rw-r--r--kernel/posix-cpu-timers.c8
-rw-r--r--kernel/power/disk.c51
-rw-r--r--kernel/power/main.c24
-rw-r--r--kernel/power/poweroff.c2
-rw-r--r--kernel/power/swap.c2
-rw-r--r--kernel/ptrace.c26
-rw-r--r--kernel/rcupdate.c18
-rw-r--r--kernel/rcupreempt.c8
-rw-r--r--kernel/rcutree.c42
-rw-r--r--kernel/rcutree_trace.c78
-rw-r--r--kernel/resource.c46
-rw-r--r--kernel/rtmutex.c248
-rw-r--r--kernel/rtmutex_common.h8
-rw-r--r--kernel/sched.c267
-rw-r--r--kernel/sched_fair.c13
-rw-r--r--kernel/signal.c71
-rw-r--r--kernel/slow-work.c4
-rw-r--r--kernel/softirq.c13
-rw-r--r--kernel/sys.c24
-rw-r--r--kernel/sysctl.c37
-rw-r--r--kernel/time/clockevents.c2
-rw-r--r--kernel/time/clocksource.c11
-rw-r--r--kernel/time/jiffies.c2
-rw-r--r--kernel/time/tick-broadcast.c2
-rw-r--r--kernel/time/tick-common.c12
-rw-r--r--kernel/time/timekeeping.c19
-rw-r--r--kernel/timer.c3
-rw-r--r--kernel/trace/Kconfig89
-rw-r--r--kernel/trace/Makefile15
-rw-r--r--kernel/trace/blktrace.c193
-rw-r--r--kernel/trace/events.c14
-rw-r--r--kernel/trace/ftrace.c726
-rw-r--r--kernel/trace/kmemtrace.c10
-rw-r--r--kernel/trace/ring_buffer.c657
-rw-r--r--kernel/trace/ring_buffer_benchmark.c413
-rw-r--r--kernel/trace/trace.c371
-rw-r--r--kernel/trace/trace.h243
-rw-r--r--kernel/trace/trace_boot.c5
-rw-r--r--kernel/trace/trace_branch.c16
-rw-r--r--kernel/trace/trace_event_profile.c24
-rw-r--r--kernel/trace/trace_event_types.h12
-rw-r--r--kernel/trace/trace_events.c830
-rw-r--r--kernel/trace/trace_events_filter.c1200
-rw-r--r--kernel/trace/trace_events_stage_1.h39
-rw-r--r--kernel/trace/trace_events_stage_2.h176
-rw-r--r--kernel/trace/trace_events_stage_3.h281
-rw-r--r--kernel/trace/trace_export.c110
-rw-r--r--kernel/trace/trace_functions_graph.c25
-rw-r--r--kernel/trace/trace_hw_branches.c203
-rw-r--r--kernel/trace/trace_mmiotrace.c6
-rw-r--r--kernel/trace/trace_output.c82
-rw-r--r--kernel/trace/trace_output.h28
-rw-r--r--kernel/trace/trace_power.c15
-rw-r--r--kernel/trace/trace_printk.c6
-rw-r--r--kernel/trace/trace_sched_switch.c12
-rw-r--r--kernel/trace/trace_sched_wakeup.c8
-rw-r--r--kernel/trace/trace_selftest.c58
-rw-r--r--kernel/trace/trace_stack.c13
-rw-r--r--kernel/trace/trace_stat.c2
-rw-r--r--kernel/trace/trace_stat.h2
-rw-r--r--kernel/trace/trace_sysprof.c6
-rw-r--r--kernel/trace/trace_workqueue.c2
-rw-r--r--kernel/wait.c2
-rw-r--r--lib/Kconfig.debug61
-rw-r--r--lib/Makefile2
-rw-r--r--lib/dma-debug.c125
-rw-r--r--lib/kobject.c3
-rw-r--r--lib/kobject_uevent.c4
-rw-r--r--lib/scatterlist.c9
-rw-r--r--lib/swiotlb.c119
-rw-r--r--lib/vsprintf.c56
-rw-r--r--mm/Kconfig30
-rw-r--r--mm/Makefile3
-rw-r--r--mm/filemap.c5
-rw-r--r--mm/kmemleak-test.c111
-rw-r--r--mm/kmemleak.c1498
-rw-r--r--mm/madvise.c8
-rw-r--r--mm/memcontrol.c40
-rw-r--r--mm/memory.c112
-rw-r--r--mm/mlock.c51
-rw-r--r--mm/mmap.c14
-rw-r--r--mm/nommu.c17
-rw-r--r--mm/oom_kill.c44
-rw-r--r--mm/page_alloc.c31
-rw-r--r--mm/percpu.c141
-rw-r--r--mm/shmem.c35
-rw-r--r--mm/slab.c34
-rw-r--r--mm/slob.c20
-rw-r--r--mm/slqb.c3746
-rw-r--r--mm/slub.c13
-rw-r--r--mm/swap.c46
-rw-r--r--mm/util.c27
-rw-r--r--mm/vmalloc.c31
-rw-r--r--mm/vmscan.c19
-rw-r--r--net/9p/client.c114
-rw-r--r--net/9p/trans_fd.c14
-rw-r--r--net/9p/trans_rdma.c1
-rw-r--r--net/9p/trans_virtio.c1
-rw-r--r--net/core/dev.c15
-rw-r--r--net/core/drop_monitor.c2
-rw-r--r--net/core/net-traces.c4
-rw-r--r--net/core/skbuff.c2
-rw-r--r--net/decnet/dn_nsp_in.c17
-rw-r--r--net/ipv4/Kconfig2
-rw-r--r--net/mac80211/cfg.c14
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/iface.c3
-rw-r--r--net/mac80211/main.c14
-rw-r--r--net/mac80211/mlme.c20
-rw-r--r--net/mac80211/rc80211_minstrel.c2
-rw-r--r--net/mac80211/rc80211_pid_algo.c2
-rw-r--r--net/mac80211/rx.c58
-rw-r--r--net/mac80211/scan.c32
-rw-r--r--net/mac80211/util.c60
-rw-r--r--net/mac80211/wext.c279
-rw-r--r--net/netfilter/ipvs/ip_vs_conn.c9
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c4
-rw-r--r--net/netfilter/nf_conntrack_acct.c2
-rw-r--r--net/rds/rds.h2
-rw-r--r--net/rfkill/rfkill.c45
-rw-r--r--net/sunrpc/clnt.c13
-rw-r--r--net/sunrpc/sched.c2
-rw-r--r--net/sunrpc/svc_xprt.c57
-rw-r--r--net/sunrpc/svcsock.c87
-rw-r--r--net/sunrpc/xprt.c6
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_recvfrom.c2
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_sendto.c3
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_transport.c3
-rw-r--r--net/sunrpc/xprtsock.c26
-rw-r--r--net/wimax/op-rfkill.c1
-rw-r--r--net/wireless/core.c10
-rw-r--r--net/wireless/core.h6
-rw-r--r--net/wireless/ibss.c60
-rw-r--r--net/wireless/nl80211.c81
-rw-r--r--net/wireless/util.c45
-rw-r--r--net/wireless/wext-compat.c285
-rw-r--r--net/wireless/wext.c22
-rw-r--r--samples/Kconfig6
-rw-r--r--samples/Makefile2
-rw-r--r--samples/trace_events/Makefile6
-rw-r--r--samples/trace_events/trace-events-sample.c52
-rw-r--r--samples/trace_events/trace-events-sample.h129
-rw-r--r--scripts/Makefile1
-rw-r--r--scripts/Makefile.build3
-rw-r--r--scripts/Makefile.lib9
-rw-r--r--scripts/dtc/Makefile54
-rw-r--r--scripts/dtc/Makefile.dtc (renamed from arch/powerpc/boot/dtc-src/Makefile.dtc)0
-rw-r--r--scripts/dtc/checks.c (renamed from arch/powerpc/boot/dtc-src/checks.c)0
-rw-r--r--scripts/dtc/data.c (renamed from arch/powerpc/boot/dtc-src/data.c)0
-rw-r--r--scripts/dtc/dtc-lexer.l (renamed from arch/powerpc/boot/dtc-src/dtc-lexer.l)0
-rw-r--r--scripts/dtc/dtc-lexer.lex.c_shipped (renamed from arch/powerpc/boot/dtc-src/dtc-lexer.lex.c_shipped)0
-rw-r--r--scripts/dtc/dtc-parser.tab.c_shipped (renamed from arch/powerpc/boot/dtc-src/dtc-parser.tab.c_shipped)0
-rw-r--r--scripts/dtc/dtc-parser.tab.h_shipped (renamed from arch/powerpc/boot/dtc-src/dtc-parser.tab.h_shipped)0
-rw-r--r--scripts/dtc/dtc-parser.y (renamed from arch/powerpc/boot/dtc-src/dtc-parser.y)0
-rw-r--r--scripts/dtc/dtc.c (renamed from arch/powerpc/boot/dtc-src/dtc.c)0
-rw-r--r--scripts/dtc/dtc.h (renamed from arch/powerpc/boot/dtc-src/dtc.h)0
-rw-r--r--scripts/dtc/flattree.c (renamed from arch/powerpc/boot/dtc-src/flattree.c)0
-rw-r--r--scripts/dtc/fstree.c (renamed from arch/powerpc/boot/dtc-src/fstree.c)0
-rw-r--r--scripts/dtc/libfdt/Makefile.libfdt (renamed from arch/powerpc/boot/libfdt/Makefile.libfdt)0
-rw-r--r--scripts/dtc/libfdt/fdt.c (renamed from arch/powerpc/boot/libfdt/fdt.c)0
-rw-r--r--scripts/dtc/libfdt/fdt.h (renamed from arch/powerpc/boot/libfdt/fdt.h)0
-rw-r--r--scripts/dtc/libfdt/fdt_ro.c (renamed from arch/powerpc/boot/libfdt/fdt_ro.c)0
-rw-r--r--scripts/dtc/libfdt/fdt_rw.c (renamed from arch/powerpc/boot/libfdt/fdt_rw.c)0
-rw-r--r--scripts/dtc/libfdt/fdt_strerror.c (renamed from arch/powerpc/boot/libfdt/fdt_strerror.c)0
-rw-r--r--scripts/dtc/libfdt/fdt_sw.c (renamed from arch/powerpc/boot/libfdt/fdt_sw.c)0
-rw-r--r--scripts/dtc/libfdt/fdt_wip.c (renamed from arch/powerpc/boot/libfdt/fdt_wip.c)0
-rw-r--r--scripts/dtc/libfdt/libfdt.h (renamed from arch/powerpc/boot/libfdt/libfdt.h)0
-rw-r--r--scripts/dtc/libfdt/libfdt_env.h (renamed from arch/powerpc/boot/dtc-src/libfdt_env.h)0
-rw-r--r--scripts/dtc/libfdt/libfdt_internal.h (renamed from arch/powerpc/boot/libfdt/libfdt_internal.h)0
-rw-r--r--scripts/dtc/livetree.c (renamed from arch/powerpc/boot/dtc-src/livetree.c)0
-rw-r--r--scripts/dtc/srcpos.c (renamed from arch/powerpc/boot/dtc-src/srcpos.c)0
-rw-r--r--scripts/dtc/srcpos.h (renamed from arch/powerpc/boot/dtc-src/srcpos.h)0
-rw-r--r--scripts/dtc/treesource.c (renamed from arch/powerpc/boot/dtc-src/treesource.c)0
-rw-r--r--scripts/dtc/version_gen.h (renamed from arch/powerpc/boot/dtc-src/version_gen.h)0
-rw-r--r--scripts/kconfig/lxdialog/checklist.c3
-rw-r--r--scripts/kconfig/mconf.c10
-rwxr-xr-xscripts/kernel-doc29
-rw-r--r--scripts/mod/modpost.c118
-rw-r--r--scripts/package/builddeb149
-rwxr-xr-xscripts/recordmcount.pl6
-rwxr-xr-xscripts/setlocalversion13
-rwxr-xr-xscripts/tags.sh2
-rw-r--r--security/Makefile3
-rw-r--r--security/commoncap.c32
-rw-r--r--security/integrity/ima/ima_audit.c30
-rw-r--r--security/integrity/ima/ima_fs.c4
-rw-r--r--security/integrity/ima/ima_main.c16
-rw-r--r--security/integrity/ima/ima_policy.c8
-rw-r--r--security/lsm_audit.c386
-rw-r--r--security/selinux/avc.c2
-rw-r--r--security/selinux/hooks.c26
-rw-r--r--security/selinux/include/security.h4
-rw-r--r--security/selinux/selinuxfs.c4
-rw-r--r--security/selinux/ss/services.c30
-rw-r--r--security/smack/smack.h108
-rw-r--r--security/smack/smack_access.c143
-rw-r--r--security/smack/smack_lsm.c401
-rw-r--r--security/smack/smackfs.c74
-rw-r--r--security/tomoyo/common.c12
-rw-r--r--security/tomoyo/common.h2
-rw-r--r--security/tomoyo/domain.c2
-rw-r--r--security/tomoyo/file.c2
-rw-r--r--security/tomoyo/realpath.c18
-rw-r--r--security/tomoyo/realpath.h2
-rw-r--r--security/tomoyo/tomoyo.c2
-rw-r--r--security/tomoyo/tomoyo.h2
-rw-r--r--sound/aoa/codecs/onyx.c76
-rw-r--r--sound/aoa/codecs/tas.c66
-rw-r--r--sound/arm/pxa2xx-ac97-lib.c2
-rw-r--r--sound/core/control.c35
-rw-r--r--sound/core/jack.c3
-rw-r--r--sound/core/pcm_compat.c11
-rw-r--r--sound/core/pcm_lib.c54
-rw-r--r--sound/core/pcm_native.c101
-rw-r--r--sound/core/seq/seq_compat.c9
-rw-r--r--sound/core/timer.c11
-rw-r--r--sound/drivers/serial-u16550.c11
-rw-r--r--sound/isa/Kconfig7
-rw-r--r--sound/isa/msnd/msnd.c6
-rw-r--r--sound/isa/sb/sb16_csp.c19
-rw-r--r--sound/isa/sc6000.c134
-rw-r--r--sound/isa/wavefront/wavefront_fx.c14
-rw-r--r--sound/isa/wavefront/wavefront_synth.c11
-rw-r--r--sound/pci/Kconfig10
-rw-r--r--sound/pci/Makefile1
-rw-r--r--sound/pci/ac97/ac97_codec.c2
-rw-r--r--sound/pci/atiixp.c6
-rw-r--r--sound/pci/aw2/aw2-saa7146.c2
-rw-r--r--sound/pci/bt87x.c6
-rw-r--r--sound/pci/cmipci.c2
-rw-r--r--sound/pci/echoaudio/indigodjx.c1
-rw-r--r--sound/pci/echoaudio/indigoiox.c1
-rw-r--r--sound/pci/emu10k1/emufx.c41
-rw-r--r--sound/pci/emu10k1/io.c2
-rw-r--r--sound/pci/hda/Kconfig13
-rw-r--r--sound/pci/hda/Makefile4
-rw-r--r--sound/pci/hda/hda_codec.c136
-rw-r--r--sound/pci/hda/hda_codec.h1
-rw-r--r--sound/pci/hda/hda_intel.c81
-rw-r--r--sound/pci/hda/patch_analog.c53
-rw-r--r--sound/pci/hda/patch_ca0110.c573
-rw-r--r--sound/pci/hda/patch_conexant.c21
-rw-r--r--sound/pci/hda/patch_realtek.c1734
-rw-r--r--sound/pci/hda/patch_sigmatel.c88
-rw-r--r--sound/pci/hda/patch_via.c111
-rw-r--r--sound/pci/intel8x0.c105
-rw-r--r--sound/pci/korg1212/korg1212.c6
-rw-r--r--sound/pci/lx6464es/Makefile2
-rw-r--r--sound/pci/lx6464es/lx6464es.c1152
-rw-r--r--sound/pci/lx6464es/lx6464es.h114
-rw-r--r--sound/pci/lx6464es/lx_core.c1444
-rw-r--r--sound/pci/lx6464es/lx_core.h242
-rw-r--r--sound/pci/lx6464es/lx_defs.h376
-rw-r--r--sound/pci/sis7019.h4
-rw-r--r--sound/pci/via82xx.c2
-rw-r--r--sound/pci/vx222/vx222_ops.c2
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c3
-rw-r--r--sound/ppc/keywest.c82
-rw-r--r--sound/soc/Kconfig1
-rw-r--r--sound/soc/Makefile1
-rw-r--r--sound/soc/au1x/dbdma2.c2
-rw-r--r--sound/soc/codecs/Kconfig12
-rw-r--r--sound/soc/codecs/Makefile7
-rw-r--r--sound/soc/codecs/ac97.c4
-rw-r--r--sound/soc/codecs/ad1980.c4
-rw-r--r--sound/soc/codecs/cs4270.c105
-rw-r--r--sound/soc/codecs/tlv320aic23.c2
-rw-r--r--sound/soc/codecs/twl4030.c691
-rw-r--r--sound/soc/codecs/twl4030.h29
-rw-r--r--sound/soc/codecs/wm8350.c2
-rw-r--r--sound/soc/codecs/wm8350.h1
-rw-r--r--sound/soc/codecs/wm8580.c16
-rw-r--r--sound/soc/codecs/wm8903.c119
-rw-r--r--sound/soc/codecs/wm8940.c955
-rw-r--r--sound/soc/codecs/wm8940.h104
-rw-r--r--sound/soc/codecs/wm8960.c969
-rw-r--r--sound/soc/codecs/wm8960.h127
-rw-r--r--sound/soc/codecs/wm8988.c1097
-rw-r--r--sound/soc/codecs/wm8988.h60
-rw-r--r--sound/soc/codecs/wm8990.c40
-rw-r--r--sound/soc/codecs/wm9705.c6
-rw-r--r--sound/soc/codecs/wm9712.c6
-rw-r--r--sound/soc/codecs/wm9713.c46
-rw-r--r--sound/soc/fsl/mpc5200_psc_i2s.c3
-rw-r--r--sound/soc/omap/n810.c11
-rw-r--r--sound/soc/omap/omap-mcbsp.c55
-rw-r--r--sound/soc/omap/omap-mcbsp.h3
-rw-r--r--sound/soc/omap/omap-pcm.c14
-rw-r--r--sound/soc/omap/omap-pcm.h3
-rw-r--r--sound/soc/omap/omap2evm.c2
-rw-r--r--sound/soc/omap/omap3beagle.c28
-rw-r--r--sound/soc/omap/omap3pandora.c4
-rw-r--r--sound/soc/omap/osk5912.c4
-rw-r--r--sound/soc/omap/overo.c2
-rw-r--r--sound/soc/omap/sdp3430.c2
-rw-r--r--sound/soc/pxa/Kconfig16
-rw-r--r--sound/soc/pxa/Makefile2
-rw-r--r--sound/soc/pxa/imote2.c114
-rw-r--r--sound/soc/pxa/magician.c2
-rw-r--r--sound/soc/pxa/palm27x.c29
-rw-r--r--sound/soc/pxa/pxa-ssp.c251
-rw-r--r--sound/soc/s3c24xx/Kconfig6
-rw-r--r--sound/soc/s3c24xx/jive_wm8750.c12
-rw-r--r--sound/soc/s3c24xx/s3c-i2s-v2.c108
-rw-r--r--sound/soc/s3c24xx/s3c2412-i2s.c4
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.c157
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.h6
-rw-r--r--sound/soc/s6000/Kconfig19
-rw-r--r--sound/soc/s6000/Makefile11
-rw-r--r--sound/soc/s6000/s6000-i2s.c629
-rw-r--r--sound/soc/s6000/s6000-i2s.h25
-rw-r--r--sound/soc/s6000/s6000-pcm.c497
-rw-r--r--sound/soc/s6000/s6000-pcm.h35
-rw-r--r--sound/soc/s6000/s6105-ipcam.c244
-rw-r--r--sound/soc/sh/dma-sh7760.c3
-rw-r--r--sound/soc/soc-core.c58
-rw-r--r--sound/soc/soc-dapm.c250
-rw-r--r--sound/sparc/dbri.c3
-rw-r--r--sound/usb/caiaq/Makefile4
-rw-r--r--sound/usb/caiaq/audio.c (renamed from sound/usb/caiaq/caiaq-audio.c)24
-rw-r--r--sound/usb/caiaq/audio.h (renamed from sound/usb/caiaq/caiaq-audio.h)0
-rw-r--r--sound/usb/caiaq/control.c (renamed from sound/usb/caiaq/caiaq-control.c)10
-rw-r--r--sound/usb/caiaq/control.h (renamed from sound/usb/caiaq/caiaq-control.h)0
-rw-r--r--sound/usb/caiaq/device.c (renamed from sound/usb/caiaq/caiaq-device.c)25
-rw-r--r--sound/usb/caiaq/device.h (renamed from sound/usb/caiaq/caiaq-device.h)0
-rw-r--r--sound/usb/caiaq/input.c (renamed from sound/usb/caiaq/caiaq-input.c)11
-rw-r--r--sound/usb/caiaq/input.h (renamed from sound/usb/caiaq/caiaq-input.h)0
-rw-r--r--sound/usb/caiaq/midi.c (renamed from sound/usb/caiaq/caiaq-midi.c)13
-rw-r--r--sound/usb/caiaq/midi.h (renamed from sound/usb/caiaq/caiaq-midi.h)0
-rw-r--r--sound/usb/usbaudio.c14
-rw-r--r--sound/usb/usbmixer.c2
-rw-r--r--sound/usb/usx2y/us122l.c22
-rw-r--r--sound/usb/usx2y/usX2Yhwdep.c13
-rw-r--r--sound/usb/usx2y/usb_stream.c67
-rw-r--r--sound/usb/usx2y/usbusx2yaudio.c3
-rw-r--r--virt/kvm/ioapic.c153
-rw-r--r--virt/kvm/ioapic.h27
-rw-r--r--virt/kvm/iommu.c27
-rw-r--r--virt/kvm/irq_comm.c111
-rw-r--r--virt/kvm/kvm_main.c674
3287 files changed, 156191 insertions, 67755 deletions
diff --git a/.gitignore b/.gitignore
index 869e1a3b64b6..51bd99d6a260 100644
--- a/.gitignore
+++ b/.gitignore
@@ -49,6 +49,7 @@ include/linux/compile.h
include/linux/version.h
include/linux/utsrelease.h
include/linux/bounds.h
+include/generated
# stgit generated dirs
patches-*
diff --git a/Documentation/ABI/testing/debugfs-pktcdvd b/Documentation/ABI/testing/debugfs-pktcdvd
index bf9c16b64c34..cf11736acb76 100644
--- a/Documentation/ABI/testing/debugfs-pktcdvd
+++ b/Documentation/ABI/testing/debugfs-pktcdvd
@@ -1,4 +1,4 @@
-What: /debug/pktcdvd/pktcdvd[0-7]
+What: /sys/kernel/debug/pktcdvd/pktcdvd[0-7]
Date: Oct. 2006
KernelVersion: 2.6.20
Contact: Thomas Maier <balagi@justmail.de>
@@ -10,10 +10,10 @@ debugfs interface
The pktcdvd module (packet writing driver) creates
these files in debugfs:
-/debug/pktcdvd/pktcdvd[0-7]/
+/sys/kernel/debug/pktcdvd/pktcdvd[0-7]/
info (0444) Lots of driver statistics and infos.
Example:
-------
-cat /debug/pktcdvd/pktcdvd0/info
+cat /sys/kernel/debug/pktcdvd/pktcdvd0/info
diff --git a/Documentation/ABI/testing/sysfs-devices-cache_disable b/Documentation/ABI/testing/sysfs-devices-cache_disable
new file mode 100644
index 000000000000..175bb4f70512
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-devices-cache_disable
@@ -0,0 +1,18 @@
+What: /sys/devices/system/cpu/cpu*/cache/index*/cache_disable_X
+Date: August 2008
+KernelVersion: 2.6.27
+Contact: mark.langsdorf@amd.com
+Description: These files exist in every cpu's cache index directories.
+ There are currently 2 cache_disable_# files in each
+ directory. Reading from these files on a supported
+ processor will return that cache disable index value
+ for that processor and node. Writing to one of these
+ files will cause the specificed cache index to be disabled.
+
+ Currently, only AMD Family 10h Processors support cache index
+ disable, and only for their L3 caches. See the BIOS and
+ Kernel Developer's Guide at
+ http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/31116-Public-GH-BKDG_3.20_2-4-09.pdf
+ for formatting information and other details on the
+ cache index disable.
+Users: joachim.deguara@amd.com
diff --git a/Documentation/ABI/testing/sysfs-firmware-acpi b/Documentation/ABI/testing/sysfs-firmware-acpi
index e8ffc70ffe12..4f9ba3c2fca7 100644
--- a/Documentation/ABI/testing/sysfs-firmware-acpi
+++ b/Documentation/ABI/testing/sysfs-firmware-acpi
@@ -69,9 +69,13 @@ Description:
gpe1F: 0 invalid
gpe_all: 1192
sci: 1194
+ sci_not: 0
- sci - The total number of times the ACPI SCI
- has claimed an interrupt.
+ sci - The number of times the ACPI SCI
+ has been called and claimed an interrupt.
+
+ sci_not - The number of times the ACPI SCI
+ has been called and NOT claimed an interrupt.
gpe_all - count of SCI caused by GPEs.
diff --git a/Documentation/ABI/testing/sysfs-kernel-slab b/Documentation/ABI/testing/sysfs-kernel-slab
new file mode 100644
index 000000000000..6dcf75e594fb
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-kernel-slab
@@ -0,0 +1,479 @@
+What: /sys/kernel/slab
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The /sys/kernel/slab directory contains a snapshot of the
+ internal state of the SLUB allocator for each cache. Certain
+ files may be modified to change the behavior of the cache (and
+ any cache it aliases, if any).
+Users: kernel memory tuning tools
+
+What: /sys/kernel/slab/cache/aliases
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The aliases file is read-only and specifies how many caches
+ have merged into this cache.
+
+What: /sys/kernel/slab/cache/align
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The align file is read-only and specifies the cache's object
+ alignment in bytes.
+
+What: /sys/kernel/slab/cache/alloc_calls
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The alloc_calls file is read-only and lists the kernel code
+ locations from which allocations for this cache were performed.
+ The alloc_calls file only contains information if debugging is
+ enabled for that cache (see Documentation/vm/slub.txt).
+
+What: /sys/kernel/slab/cache/alloc_fastpath
+Date: February 2008
+KernelVersion: 2.6.25
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The alloc_fastpath file is read-only and specifies how many
+ objects have been allocated using the fast path.
+ Available when CONFIG_SLUB_STATS is enabled.
+
+What: /sys/kernel/slab/cache/alloc_from_partial
+Date: February 2008
+KernelVersion: 2.6.25
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The alloc_from_partial file is read-only and specifies how
+ many times a cpu slab has been full and it has been refilled
+ by using a slab from the list of partially used slabs.
+ Available when CONFIG_SLUB_STATS is enabled.
+
+What: /sys/kernel/slab/cache/alloc_refill
+Date: February 2008
+KernelVersion: 2.6.25
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The alloc_refill file is read-only and specifies how many
+ times the per-cpu freelist was empty but there were objects
+ available as the result of remote cpu frees.
+ Available when CONFIG_SLUB_STATS is enabled.
+
+What: /sys/kernel/slab/cache/alloc_slab
+Date: February 2008
+KernelVersion: 2.6.25
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The alloc_slab file is read-only and specifies how many times
+ a new slab had to be allocated from the page allocator.
+ Available when CONFIG_SLUB_STATS is enabled.
+
+What: /sys/kernel/slab/cache/alloc_slowpath
+Date: February 2008
+KernelVersion: 2.6.25
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The alloc_slowpath file is read-only and specifies how many
+ objects have been allocated using the slow path because of a
+ refill or allocation from a partial or new slab.
+ Available when CONFIG_SLUB_STATS is enabled.
+
+What: /sys/kernel/slab/cache/cache_dma
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The cache_dma file is read-only and specifies whether objects
+ are from ZONE_DMA.
+ Available when CONFIG_ZONE_DMA is enabled.
+
+What: /sys/kernel/slab/cache/cpu_slabs
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The cpu_slabs file is read-only and displays how many cpu slabs
+ are active and their NUMA locality.
+
+What: /sys/kernel/slab/cache/cpuslab_flush
+Date: April 2009
+KernelVersion: 2.6.31
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The file cpuslab_flush is read-only and specifies how many
+ times a cache's cpu slabs have been flushed as the result of
+ destroying or shrinking a cache, a cpu going offline, or as
+ the result of forcing an allocation from a certain node.
+ Available when CONFIG_SLUB_STATS is enabled.
+
+What: /sys/kernel/slab/cache/ctor
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The ctor file is read-only and specifies the cache's object
+ constructor function, which is invoked for each object when a
+ new slab is allocated.
+
+What: /sys/kernel/slab/cache/deactivate_empty
+Date: February 2008
+KernelVersion: 2.6.25
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The file deactivate_empty is read-only and specifies how many
+ times an empty cpu slab was deactivated.
+ Available when CONFIG_SLUB_STATS is enabled.
+
+What: /sys/kernel/slab/cache/deactivate_full
+Date: February 2008
+KernelVersion: 2.6.25
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The file deactivate_full is read-only and specifies how many
+ times a full cpu slab was deactivated.
+ Available when CONFIG_SLUB_STATS is enabled.
+
+What: /sys/kernel/slab/cache/deactivate_remote_frees
+Date: February 2008
+KernelVersion: 2.6.25
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The file deactivate_remote_frees is read-only and specifies how
+ many times a cpu slab has been deactivated and contained free
+ objects that were freed remotely.
+ Available when CONFIG_SLUB_STATS is enabled.
+
+What: /sys/kernel/slab/cache/deactivate_to_head
+Date: February 2008
+KernelVersion: 2.6.25
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The file deactivate_to_head is read-only and specifies how
+ many times a partial cpu slab was deactivated and added to the
+ head of its node's partial list.
+ Available when CONFIG_SLUB_STATS is enabled.
+
+What: /sys/kernel/slab/cache/deactivate_to_tail
+Date: February 2008
+KernelVersion: 2.6.25
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The file deactivate_to_tail is read-only and specifies how
+ many times a partial cpu slab was deactivated and added to the
+ tail of its node's partial list.
+ Available when CONFIG_SLUB_STATS is enabled.
+
+What: /sys/kernel/slab/cache/destroy_by_rcu
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The destroy_by_rcu file is read-only and specifies whether
+ slabs (not objects) are freed by rcu.
+
+What: /sys/kernel/slab/cache/free_add_partial
+Date: February 2008
+KernelVersion: 2.6.25
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The file free_add_partial is read-only and specifies how many
+ times an object has been freed in a full slab so that it had to
+ added to its node's partial list.
+ Available when CONFIG_SLUB_STATS is enabled.
+
+What: /sys/kernel/slab/cache/free_calls
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The free_calls file is read-only and lists the locations of
+ object frees if slab debugging is enabled (see
+ Documentation/vm/slub.txt).
+
+What: /sys/kernel/slab/cache/free_fastpath
+Date: February 2008
+KernelVersion: 2.6.25
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The free_fastpath file is read-only and specifies how many
+ objects have been freed using the fast path because it was an
+ object from the cpu slab.
+ Available when CONFIG_SLUB_STATS is enabled.
+
+What: /sys/kernel/slab/cache/free_frozen
+Date: February 2008
+KernelVersion: 2.6.25
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The free_frozen file is read-only and specifies how many
+ objects have been freed to a frozen slab (i.e. a remote cpu
+ slab).
+ Available when CONFIG_SLUB_STATS is enabled.
+
+What: /sys/kernel/slab/cache/free_remove_partial
+Date: February 2008
+KernelVersion: 2.6.25
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The file free_remove_partial is read-only and specifies how
+ many times an object has been freed to a now-empty slab so
+ that it had to be removed from its node's partial list.
+ Available when CONFIG_SLUB_STATS is enabled.
+
+What: /sys/kernel/slab/cache/free_slab
+Date: February 2008
+KernelVersion: 2.6.25
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The free_slab file is read-only and specifies how many times an
+ empty slab has been freed back to the page allocator.
+ Available when CONFIG_SLUB_STATS is enabled.
+
+What: /sys/kernel/slab/cache/free_slowpath
+Date: February 2008
+KernelVersion: 2.6.25
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The free_slowpath file is read-only and specifies how many
+ objects have been freed using the slow path (i.e. to a full or
+ partial slab).
+ Available when CONFIG_SLUB_STATS is enabled.
+
+What: /sys/kernel/slab/cache/hwcache_align
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The hwcache_align file is read-only and specifies whether
+ objects are aligned on cachelines.
+
+What: /sys/kernel/slab/cache/min_partial
+Date: February 2009
+KernelVersion: 2.6.30
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ David Rientjes <rientjes@google.com>
+Description:
+ The min_partial file specifies how many empty slabs shall
+ remain on a node's partial list to avoid the overhead of
+ allocating new slabs. Such slabs may be reclaimed by utilizing
+ the shrink file.
+
+What: /sys/kernel/slab/cache/object_size
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The object_size file is read-only and specifies the cache's
+ object size.
+
+What: /sys/kernel/slab/cache/objects
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The objects file is read-only and displays how many objects are
+ active and from which nodes they are from.
+
+What: /sys/kernel/slab/cache/objects_partial
+Date: April 2008
+KernelVersion: 2.6.26
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The objects_partial file is read-only and displays how many
+ objects are on partial slabs and from which nodes they are
+ from.
+
+What: /sys/kernel/slab/cache/objs_per_slab
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The file objs_per_slab is read-only and specifies how many
+ objects may be allocated from a single slab of the order
+ specified in /sys/kernel/slab/cache/order.
+
+What: /sys/kernel/slab/cache/order
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The order file specifies the page order at which new slabs are
+ allocated. It is writable and can be changed to increase the
+ number of objects per slab. If a slab cannot be allocated
+ because of fragmentation, SLUB will retry with the minimum order
+ possible depending on its characteristics.
+
+What: /sys/kernel/slab/cache/order_fallback
+Date: April 2008
+KernelVersion: 2.6.26
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The file order_fallback is read-only and specifies how many
+ times an allocation of a new slab has not been possible at the
+ cache's order and instead fallen back to its minimum possible
+ order.
+ Available when CONFIG_SLUB_STATS is enabled.
+
+What: /sys/kernel/slab/cache/partial
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The partial file is read-only and displays how long many
+ partial slabs there are and how long each node's list is.
+
+What: /sys/kernel/slab/cache/poison
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The poison file specifies whether objects should be poisoned
+ when a new slab is allocated.
+
+What: /sys/kernel/slab/cache/reclaim_account
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The reclaim_account file specifies whether the cache's objects
+ are reclaimable (and grouped by their mobility).
+
+What: /sys/kernel/slab/cache/red_zone
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The red_zone file specifies whether the cache's objects are red
+ zoned.
+
+What: /sys/kernel/slab/cache/remote_node_defrag_ratio
+Date: January 2008
+KernelVersion: 2.6.25
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The file remote_node_defrag_ratio specifies the percentage of
+ times SLUB will attempt to refill the cpu slab with a partial
+ slab from a remote node as opposed to allocating a new slab on
+ the local node. This reduces the amount of wasted memory over
+ the entire system but can be expensive.
+ Available when CONFIG_NUMA is enabled.
+
+What: /sys/kernel/slab/cache/sanity_checks
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The sanity_checks file specifies whether expensive checks
+ should be performed on free and, at minimum, enables double free
+ checks. Caches that enable sanity_checks cannot be merged with
+ caches that do not.
+
+What: /sys/kernel/slab/cache/shrink
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The shrink file is written when memory should be reclaimed from
+ a cache. Empty partial slabs are freed and the partial list is
+ sorted so the slabs with the fewest available objects are used
+ first.
+
+What: /sys/kernel/slab/cache/slab_size
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The slab_size file is read-only and specifies the object size
+ with metadata (debugging information and alignment) in bytes.
+
+What: /sys/kernel/slab/cache/slabs
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The slabs file is read-only and displays how long many slabs
+ there are (both cpu and partial) and from which nodes they are
+ from.
+
+What: /sys/kernel/slab/cache/store_user
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The store_user file specifies whether the location of
+ allocation or free should be tracked for a cache.
+
+What: /sys/kernel/slab/cache/total_objects
+Date: April 2008
+KernelVersion: 2.6.26
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The total_objects file is read-only and displays how many total
+ objects a cache has and from which nodes they are from.
+
+What: /sys/kernel/slab/cache/trace
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ The trace file specifies whether object allocations and frees
+ should be traced.
+
+What: /sys/kernel/slab/cache/validate
+Date: May 2007
+KernelVersion: 2.6.22
+Contact: Pekka Enberg <penberg@cs.helsinki.fi>,
+ Christoph Lameter <cl@linux-foundation.org>
+Description:
+ Writing to the validate file causes SLUB to traverse all of its
+ cache's objects and check the validity of metadata.
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
index 72968cd5eaf3..8bb37237ebd2 100644
--- a/Documentation/CodingStyle
+++ b/Documentation/CodingStyle
@@ -698,8 +698,8 @@ very often is not. Abundant use of the inline keyword leads to a much bigger
kernel, which in turn slows the system as a whole down, due to a bigger
icache footprint for the CPU and simply because there is less memory
available for the pagecache. Just think about it; a pagecache miss causes a
-disk seek, which easily takes 5 miliseconds. There are a LOT of cpu cycles
-that can go into these 5 miliseconds.
+disk seek, which easily takes 5 milliseconds. There are a LOT of cpu cycles
+that can go into these 5 milliseconds.
A reasonable rule of thumb is to not put inline at functions that have more
than 3 lines of code in them. An exception to this rule are the cases where
diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index d9aa43d78bcc..04cc0bc3fd50 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -676,8 +676,8 @@ this directory the following files can currently be found:
dma-api/all_errors This file contains a numeric value. If this
value is not equal to zero the debugging code
will print a warning for every error it finds
- into the kernel log. Be carefull with this
- option. It can easily flood your logs.
+ into the kernel log. Be careful with this
+ option, as it can easily flood your logs.
dma-api/disabled This read-only file contains the character 'Y'
if the debugging code is disabled. This can
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 8918a32c6b3a..9632444f6c62 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -13,7 +13,8 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
mac80211.xml debugobjects.xml sh.xml regulator.xml \
- alsa-driver-api.xml writing-an-alsa-driver.xml
+ alsa-driver-api.xml writing-an-alsa-driver.xml \
+ tracepoint.xml
###
# The build process is as follows (targets):
@@ -143,7 +144,8 @@ quiet_cmd_db2pdf = PDF $@
$(call cmd,db2pdf)
-main_idx = Documentation/DocBook/index.html
+index = index.html
+main_idx = Documentation/DocBook/$(index)
build_main_index = rm -rf $(main_idx) && \
echo '<h1>Linux Kernel HTML Documentation</h1>' >> $(main_idx) && \
echo '<h2>Kernel Version: $(KERNELVERSION)</h2>' >> $(main_idx) && \
@@ -232,7 +234,7 @@ clean-files := $(DOCBOOKS) \
$(patsubst %.xml, %.pdf, $(DOCBOOKS)) \
$(patsubst %.xml, %.html, $(DOCBOOKS)) \
$(patsubst %.xml, %.9, $(DOCBOOKS)) \
- $(C-procfs-example)
+ $(C-procfs-example) $(index)
clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS)) man
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index d6ac5d61820e..44b3def961a2 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -190,16 +190,20 @@ X!Ekernel/module.c
!Edrivers/pci/pci.c
!Edrivers/pci/pci-driver.c
!Edrivers/pci/remove.c
-!Edrivers/pci/pci-acpi.c
!Edrivers/pci/search.c
!Edrivers/pci/msi.c
!Edrivers/pci/bus.c
+!Edrivers/pci/access.c
+!Edrivers/pci/irq.c
+!Edrivers/pci/htirq.c
<!-- FIXME: Removed for now since no structured comments in source
X!Edrivers/pci/hotplug.c
-->
!Edrivers/pci/probe.c
+!Edrivers/pci/slot.c
!Edrivers/pci/rom.c
!Edrivers/pci/iov.c
+!Idrivers/pci/pci-sysfs.c
</sect1>
<sect1><title>PCI Hotplug Support Library</title>
!Edrivers/pci/hotplug/pci_hotplug_core.c
diff --git a/Documentation/DocBook/kgdb.tmpl b/Documentation/DocBook/kgdb.tmpl
index 372dec20c8da..5cff41a5fa7c 100644
--- a/Documentation/DocBook/kgdb.tmpl
+++ b/Documentation/DocBook/kgdb.tmpl
@@ -281,7 +281,7 @@
seriously wrong while debugging, it will most often be the case
that you want to enable gdb to be verbose about its target
communications. You do this prior to issuing the <constant>target
- remote</constant> command by typing in: <constant>set remote debug 1</constant>
+ remote</constant> command by typing in: <constant>set debug remote 1</constant>
</para>
</chapter>
<chapter id="KGDBTestSuite">
diff --git a/Documentation/DocBook/tracepoint.tmpl b/Documentation/DocBook/tracepoint.tmpl
new file mode 100644
index 000000000000..b0756d0fd579
--- /dev/null
+++ b/Documentation/DocBook/tracepoint.tmpl
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="Tracepoints">
+ <bookinfo>
+ <title>The Linux Kernel Tracepoint API</title>
+
+ <authorgroup>
+ <author>
+ <firstname>Jason</firstname>
+ <surname>Baron</surname>
+ <affiliation>
+ <address>
+ <email>jbaron@redhat.com</email>
+ </address>
+ </affiliation>
+ </author>
+ </authorgroup>
+
+ <legalnotice>
+ <para>
+ This documentation is free software; you can redistribute
+ it and/or modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later
+ version.
+ </para>
+
+ <para>
+ This program is distributed in the hope that it will be
+ useful, but WITHOUT ANY WARRANTY; without even the implied
+ warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+ </para>
+
+ <para>
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ MA 02111-1307 USA
+ </para>
+
+ <para>
+ For more details see the file COPYING in the source
+ distribution of Linux.
+ </para>
+ </legalnotice>
+ </bookinfo>
+
+ <toc></toc>
+ <chapter id="intro">
+ <title>Introduction</title>
+ <para>
+ Tracepoints are static probe points that are located in strategic points
+ throughout the kernel. 'Probes' register/unregister with tracepoints
+ via a callback mechanism. The 'probes' are strictly typed functions that
+ are passed a unique set of parameters defined by each tracepoint.
+ </para>
+
+ <para>
+ From this simple callback mechanism, 'probes' can be used to profile, debug,
+ and understand kernel behavior. There are a number of tools that provide a
+ framework for using 'probes'. These tools include Systemtap, ftrace, and
+ LTTng.
+ </para>
+
+ <para>
+ Tracepoints are defined in a number of header files via various macros. Thus,
+ the purpose of this document is to provide a clear accounting of the available
+ tracepoints. The intention is to understand not only what tracepoints are
+ available but also to understand where future tracepoints might be added.
+ </para>
+
+ <para>
+ The API presented has functions of the form:
+ <function>trace_tracepointname(function parameters)</function>. These are the
+ tracepoints callbacks that are found throughout the code. Registering and
+ unregistering probes with these callback sites is covered in the
+ <filename>Documentation/trace/*</filename> directory.
+ </para>
+ </chapter>
+
+ <chapter id="irq">
+ <title>IRQ</title>
+!Iinclude/trace/events/irq.h
+ </chapter>
+
+</book>
diff --git a/Documentation/RCU/rculist_nulls.txt b/Documentation/RCU/rculist_nulls.txt
index 6389dec33459..93cb28d05dcd 100644
--- a/Documentation/RCU/rculist_nulls.txt
+++ b/Documentation/RCU/rculist_nulls.txt
@@ -118,7 +118,7 @@ to another chain) checking the final 'nulls' value if
the lookup met the end of chain. If final 'nulls' value
is not the slot number, then we must restart the lookup at
the beginning. If the object was moved to the same chain,
-then the reader doesnt care : It might eventually
+then the reader doesn't care : It might eventually
scan the list again without harm.
diff --git a/Documentation/RCU/trace.txt b/Documentation/RCU/trace.txt
index 068848240a8b..02cced183b2d 100644
--- a/Documentation/RCU/trace.txt
+++ b/Documentation/RCU/trace.txt
@@ -192,23 +192,24 @@ rcu/rcuhier (which displays the struct rcu_node hierarchy).
The output of "cat rcu/rcudata" looks as follows:
rcu:
- 0 c=4011 g=4012 pq=1 pqc=4011 qp=0 rpfq=1 rp=3c2a dt=23301/73 dn=2 df=1882 of=0 ri=2126 ql=2 b=10
- 1 c=4011 g=4012 pq=1 pqc=4011 qp=0 rpfq=3 rp=39a6 dt=78073/1 dn=2 df=1402 of=0 ri=1875 ql=46 b=10
- 2 c=4010 g=4010 pq=1 pqc=4010 qp=0 rpfq=-5 rp=1d12 dt=16646/0 dn=2 df=3140 of=0 ri=2080 ql=0 b=10
- 3 c=4012 g=4013 pq=1 pqc=4012 qp=1 rpfq=3 rp=2b50 dt=21159/1 dn=2 df=2230 of=0 ri=1923 ql=72 b=10
- 4 c=4012 g=4013 pq=1 pqc=4012 qp=1 rpfq=3 rp=1644 dt=5783/1 dn=2 df=3348 of=0 ri=2805 ql=7 b=10
- 5 c=4012 g=4013 pq=0 pqc=4011 qp=1 rpfq=3 rp=1aac dt=5879/1 dn=2 df=3140 of=0 ri=2066 ql=10 b=10
- 6 c=4012 g=4013 pq=1 pqc=4012 qp=1 rpfq=3 rp=ed8 dt=5847/1 dn=2 df=3797 of=0 ri=1266 ql=10 b=10
- 7 c=4012 g=4013 pq=1 pqc=4012 qp=1 rpfq=3 rp=1fa2 dt=6199/1 dn=2 df=2795 of=0 ri=2162 ql=28 b=10
+rcu:
+ 0 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=10951/1 dn=0 df=1101 of=0 ri=36 ql=0 b=10
+ 1 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=16117/1 dn=0 df=1015 of=0 ri=0 ql=0 b=10
+ 2 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=1445/1 dn=0 df=1839 of=0 ri=0 ql=0 b=10
+ 3 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=6681/1 dn=0 df=1545 of=0 ri=0 ql=0 b=10
+ 4 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=1003/1 dn=0 df=1992 of=0 ri=0 ql=0 b=10
+ 5 c=17829 g=17830 pq=1 pqc=17829 qp=1 dt=3887/1 dn=0 df=3331 of=0 ri=4 ql=2 b=10
+ 6 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=859/1 dn=0 df=3224 of=0 ri=0 ql=0 b=10
+ 7 c=17829 g=17830 pq=0 pqc=17829 qp=1 dt=3761/1 dn=0 df=1818 of=0 ri=0 ql=2 b=10
rcu_bh:
- 0 c=-268 g=-268 pq=1 pqc=-268 qp=0 rpfq=-145 rp=21d6 dt=23301/73 dn=2 df=0 of=0 ri=0 ql=0 b=10
- 1 c=-268 g=-268 pq=1 pqc=-268 qp=1 rpfq=-170 rp=20ce dt=78073/1 dn=2 df=26 of=0 ri=5 ql=0 b=10
- 2 c=-268 g=-268 pq=1 pqc=-268 qp=1 rpfq=-83 rp=fbd dt=16646/0 dn=2 df=28 of=0 ri=4 ql=0 b=10
- 3 c=-268 g=-268 pq=1 pqc=-268 qp=0 rpfq=-105 rp=178c dt=21159/1 dn=2 df=28 of=0 ri=2 ql=0 b=10
- 4 c=-268 g=-268 pq=1 pqc=-268 qp=1 rpfq=-30 rp=b54 dt=5783/1 dn=2 df=32 of=0 ri=0 ql=0 b=10
- 5 c=-268 g=-268 pq=1 pqc=-268 qp=1 rpfq=-29 rp=df5 dt=5879/1 dn=2 df=30 of=0 ri=3 ql=0 b=10
- 6 c=-268 g=-268 pq=1 pqc=-268 qp=1 rpfq=-28 rp=788 dt=5847/1 dn=2 df=32 of=0 ri=0 ql=0 b=10
- 7 c=-268 g=-268 pq=1 pqc=-268 qp=1 rpfq=-53 rp=1098 dt=6199/1 dn=2 df=30 of=0 ri=3 ql=0 b=10
+ 0 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=10951/1 dn=0 df=0 of=0 ri=0 ql=0 b=10
+ 1 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=16117/1 dn=0 df=13 of=0 ri=0 ql=0 b=10
+ 2 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=1445/1 dn=0 df=15 of=0 ri=0 ql=0 b=10
+ 3 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=6681/1 dn=0 df=9 of=0 ri=0 ql=0 b=10
+ 4 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=1003/1 dn=0 df=15 of=0 ri=0 ql=0 b=10
+ 5 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=3887/1 dn=0 df=15 of=0 ri=0 ql=0 b=10
+ 6 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=859/1 dn=0 df=15 of=0 ri=0 ql=0 b=10
+ 7 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=3761/1 dn=0 df=15 of=0 ri=0 ql=0 b=10
The first section lists the rcu_data structures for rcu, the second for
rcu_bh. Each section has one line per CPU, or eight for this 8-CPU system.
@@ -253,12 +254,6 @@ o "pqc" indicates which grace period the last-observed quiescent
o "qp" indicates that RCU still expects a quiescent state from
this CPU.
-o "rpfq" is the number of rcu_pending() calls on this CPU required
- to induce this CPU to invoke force_quiescent_state().
-
-o "rp" is low-order four hex digits of the count of how many times
- rcu_pending() has been invoked on this CPU.
-
o "dt" is the current value of the dyntick counter that is incremented
when entering or leaving dynticks idle state, either by the
scheduler or by irq. The number after the "/" is the interrupt
@@ -305,6 +300,9 @@ o "b" is the batch limit for this CPU. If more than this number
of RCU callbacks is ready to invoke, then the remainder will
be deferred.
+There is also an rcu/rcudata.csv file with the same information in
+comma-separated-variable spreadsheet format.
+
The output of "cat rcu/rcugp" looks as follows:
@@ -411,3 +409,63 @@ o Each element of the form "1/1 0:127 ^0" represents one struct
For example, the first entry at the lowest level shows
"^0", indicating that it corresponds to bit zero in
the first entry at the middle level.
+
+
+The output of "cat rcu/rcu_pending" looks as follows:
+
+rcu:
+ 0 np=255892 qsp=53936 cbr=0 cng=14417 gpc=10033 gps=24320 nf=6445 nn=146741
+ 1 np=261224 qsp=54638 cbr=0 cng=25723 gpc=16310 gps=2849 nf=5912 nn=155792
+ 2 np=237496 qsp=49664 cbr=0 cng=2762 gpc=45478 gps=1762 nf=1201 nn=136629
+ 3 np=236249 qsp=48766 cbr=0 cng=286 gpc=48049 gps=1218 nf=207 nn=137723
+ 4 np=221310 qsp=46850 cbr=0 cng=26 gpc=43161 gps=4634 nf=3529 nn=123110
+ 5 np=237332 qsp=48449 cbr=0 cng=54 gpc=47920 gps=3252 nf=201 nn=137456
+ 6 np=219995 qsp=46718 cbr=0 cng=50 gpc=42098 gps=6093 nf=4202 nn=120834
+ 7 np=249893 qsp=49390 cbr=0 cng=72 gpc=38400 gps=17102 nf=41 nn=144888
+rcu_bh:
+ 0 np=146741 qsp=1419 cbr=0 cng=6 gpc=0 gps=0 nf=2 nn=145314
+ 1 np=155792 qsp=12597 cbr=0 cng=0 gpc=4 gps=8 nf=3 nn=143180
+ 2 np=136629 qsp=18680 cbr=0 cng=0 gpc=7 gps=6 nf=0 nn=117936
+ 3 np=137723 qsp=2843 cbr=0 cng=0 gpc=10 gps=7 nf=0 nn=134863
+ 4 np=123110 qsp=12433 cbr=0 cng=0 gpc=4 gps=2 nf=0 nn=110671
+ 5 np=137456 qsp=4210 cbr=0 cng=0 gpc=6 gps=5 nf=0 nn=133235
+ 6 np=120834 qsp=9902 cbr=0 cng=0 gpc=6 gps=3 nf=2 nn=110921
+ 7 np=144888 qsp=26336 cbr=0 cng=0 gpc=8 gps=2 nf=0 nn=118542
+
+As always, this is once again split into "rcu" and "rcu_bh" portions.
+The fields are as follows:
+
+o "np" is the number of times that __rcu_pending() has been invoked
+ for the corresponding flavor of RCU.
+
+o "qsp" is the number of times that the RCU was waiting for a
+ quiescent state from this CPU.
+
+o "cbr" is the number of times that this CPU had RCU callbacks
+ that had passed through a grace period, and were thus ready
+ to be invoked.
+
+o "cng" is the number of times that this CPU needed another
+ grace period while RCU was idle.
+
+o "gpc" is the number of times that an old grace period had
+ completed, but this CPU was not yet aware of it.
+
+o "gps" is the number of times that a new grace period had started,
+ but this CPU was not yet aware of it.
+
+o "nf" is the number of times that this CPU suspected that the
+ current grace period had run for too long, and thus needed to
+ be forced.
+
+ Please note that "forcing" consists of sending resched IPIs
+ to holdout CPUs. If that CPU really still is in an old RCU
+ read-side critical section, then we really do have to wait for it.
+ The assumption behing "forcing" is that the CPU is not still in
+ an old RCU read-side critical section, but has not yet responded
+ for some other reason.
+
+o "nn" is the number of times that this CPU needed nothing. Alert
+ readers will note that the rcu "nn" number for a given CPU very
+ closely matches the rcu_bh "np" number for that same CPU. This
+ is due to short-circuit evaluation in rcu_pending().
diff --git a/Documentation/SM501.txt b/Documentation/SM501.txt
index 6fc656035925..561826f82093 100644
--- a/Documentation/SM501.txt
+++ b/Documentation/SM501.txt
@@ -5,7 +5,7 @@ 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.
+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.
Core
diff --git a/Documentation/Smack.txt b/Documentation/Smack.txt
index 629c92e99783..34614b4c708e 100644
--- a/Documentation/Smack.txt
+++ b/Documentation/Smack.txt
@@ -184,8 +184,9 @@ length. Single character labels using special characters, that being anything
other than a letter or digit, are reserved for use by the Smack development
team. Smack labels are unstructured, case sensitive, and the only operation
ever performed on them is comparison for equality. Smack labels cannot
-contain unprintable characters or the "/" (slash) character. Smack labels
-cannot begin with a '-', which is reserved for special options.
+contain unprintable characters, the "/" (slash), the "\" (backslash), the "'"
+(quote) and '"' (double-quote) characters.
+Smack labels cannot begin with a '-', which is reserved for special options.
There are some predefined labels:
@@ -523,3 +524,18 @@ Smack supports some mount options:
These mount options apply to all file system types.
+Smack auditing
+
+If you want Smack auditing of security events, you need to set CONFIG_AUDIT
+in your kernel configuration.
+By default, all denied events will be audited. You can change this behavior by
+writing a single character to the /smack/logging file :
+0 : no logging
+1 : log denied (default)
+2 : log accepted
+3 : log denied & accepted
+
+Events are logged as 'key=value' pairs, for each event you at least will get
+the subjet, the object, the rights requested, the action, the kernel function
+that triggered the event, plus other pairs depending on the type of event
+audited.
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index f309d3c6221c..6f29e29555c0 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -405,7 +405,14 @@ person it names. This tag documents that potentially interested parties
have been included in the discussion
-14) Using Tested-by: and Reviewed-by:
+14) Using Reported-by:, Tested-by: and Reviewed-by:
+
+If this patch fixes a problem reported by somebody else, consider adding a
+Reported-by: tag to credit the reporter for their contribution. Please
+note that this tag should not be added without the reporter's permission,
+especially if the problem was not reported in a public forum. That said,
+if we diligently credit our bug reporters, they will, hopefully, be
+inspired to help us again in the future.
A Tested-by: tag indicates that the patch has been successfully tested (in
some environment) by the person named. This tag informs maintainers that
diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
index ecad6ee75705..6fab97ea7e6b 100644
--- a/Documentation/block/biodoc.txt
+++ b/Documentation/block/biodoc.txt
@@ -1040,23 +1040,21 @@ Front merges are handled by the binary trees in AS and deadline schedulers.
iii. Plugging the queue to batch requests in anticipation of opportunities for
merge/sort optimizations
-This is just the same as in 2.4 so far, though per-device unplugging
-support is anticipated for 2.5. Also with a priority-based i/o scheduler,
-such decisions could be based on request priorities.
-
Plugging is an approach that the current i/o scheduling algorithm resorts to so
that it collects up enough requests in the queue to be able to take
advantage of the sorting/merging logic in the elevator. If the
queue is empty when a request comes in, then it plugs the request queue
-(sort of like plugging the bottom of a vessel to get fluid to build up)
+(sort of like plugging the bath tub of a vessel to get fluid to build up)
till it fills up with a few more requests, before starting to service
the requests. This provides an opportunity to merge/sort the requests before
passing them down to the device. There are various conditions when the queue is
unplugged (to open up the flow again), either through a scheduled task or
could be on demand. For example wait_on_buffer sets the unplugging going
-(by running tq_disk) so the read gets satisfied soon. So in the read case,
-the queue gets explicitly unplugged as part of waiting for completion,
-in fact all queues get unplugged as a side-effect.
+through sync_buffer() running blk_run_address_space(mapping). Or the caller
+can do it explicity through blk_unplug(bdev). So in the read case,
+the queue gets explicitly unplugged as part of waiting for completion on that
+buffer. For page driven IO, the address space ->sync_page() takes care of
+doing the blk_run_address_space().
Aside:
This is kind of controversial territory, as it's not clear if plugging is
@@ -1067,11 +1065,6 @@ Aside:
multi-page bios being queued in one shot, we may not need to wait to merge
a big request from the broken up pieces coming by.
- Per-queue granularity unplugging (still a Todo) may help reduce some of the
- concerns with just a single tq_disk flush approach. Something like
- blk_kick_queue() to unplug a specific queue (right away ?)
- or optionally, all queues, is in the plan.
-
4.4 I/O contexts
I/O contexts provide a dynamically allocated per process data area. They may
be used in I/O schedulers, and in the block layer (could be used for IO statis,
diff --git a/Documentation/block/deadline-iosched.txt b/Documentation/block/deadline-iosched.txt
index 72576769e0f4..2d82c80322cb 100644
--- a/Documentation/block/deadline-iosched.txt
+++ b/Documentation/block/deadline-iosched.txt
@@ -58,7 +58,7 @@ same criteria as reads.
front_merges (bool)
------------
-Sometimes it happens that a request enters the io scheduler that is contigious
+Sometimes it happens that a request enters the io scheduler that is contiguous
with a request that is already on the queue. Either it fits in the back of that
request, or it fits at the front. That is called either a back merge candidate
or a front merge candidate. Due to the way files are typically laid out,
diff --git a/Documentation/braille-console.txt b/Documentation/braille-console.txt
index 000b0fbdc105..d0d042c2fd5e 100644
--- a/Documentation/braille-console.txt
+++ b/Documentation/braille-console.txt
@@ -27,7 +27,7 @@ parameter.
For simplicity, only one braille console can be enabled, other uses of
console=brl,... will be discarded. Also note that it does not interfere with
-the console selection mecanism described in serial-console.txt
+the console selection mechanism described in serial-console.txt
For now, only the VisioBraille device is supported.
diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt
index a98a7fe7aabb..1a608877b14e 100644
--- a/Documentation/cgroups/memory.txt
+++ b/Documentation/cgroups/memory.txt
@@ -6,15 +6,14 @@ used here with the memory controller that is used in hardware.
Salient features
-a. Enable control of both RSS (mapped) and Page Cache (unmapped) pages
+a. Enable control of Anonymous, Page Cache (mapped and unmapped) and
+ Swap Cache memory pages.
b. The infrastructure allows easy addition of other types of memory to control
c. Provides *zero overhead* for non memory controller users
d. Provides a double LRU: global memory pressure causes reclaim from the
global LRU; a cgroup on hitting a limit, reclaims from the per
cgroup LRU
-NOTE: Swap Cache (unmapped) is not accounted now.
-
Benefits and Purpose of the memory controller
The memory controller isolates the memory behaviour of a group of tasks
@@ -290,34 +289,44 @@ will be charged as a new owner of it.
moved to the parent. If you want to avoid that, force_empty will be useful.
5.2 stat file
- memory.stat file includes following statistics (now)
- cache - # of pages from page-cache and shmem.
- rss - # of pages from anonymous memory.
- pgpgin - # of event of charging
- pgpgout - # of event of uncharging
- active_anon - # of pages on active lru of anon, shmem.
- inactive_anon - # of pages on active lru of anon, shmem
- active_file - # of pages on active lru of file-cache
- inactive_file - # of pages on inactive lru of file cache
- unevictable - # of pages cannot be reclaimed.(mlocked etc)
-
- Below is depend on CONFIG_DEBUG_VM.
- inactive_ratio - VM internal parameter. (see mm/page_alloc.c)
- recent_rotated_anon - VM internal parameter. (see mm/vmscan.c)
- recent_rotated_file - VM internal parameter. (see mm/vmscan.c)
- recent_scanned_anon - VM internal parameter. (see mm/vmscan.c)
- recent_scanned_file - VM internal parameter. (see mm/vmscan.c)
-
- Memo:
+
+memory.stat file includes following statistics
+
+cache - # of bytes of page cache memory.
+rss - # of bytes of anonymous and swap cache memory.
+pgpgin - # of pages paged in (equivalent to # of charging events).
+pgpgout - # of pages paged out (equivalent to # of uncharging events).
+active_anon - # of bytes of anonymous and swap cache memory on active
+ lru list.
+inactive_anon - # of bytes of anonymous memory and swap cache memory on
+ inactive lru list.
+active_file - # of bytes of file-backed memory on active lru list.
+inactive_file - # of bytes of file-backed memory on inactive lru list.
+unevictable - # of bytes of memory that cannot be reclaimed (mlocked etc).
+
+The following additional stats are dependent on CONFIG_DEBUG_VM.
+
+inactive_ratio - VM internal parameter. (see mm/page_alloc.c)
+recent_rotated_anon - VM internal parameter. (see mm/vmscan.c)
+recent_rotated_file - VM internal parameter. (see mm/vmscan.c)
+recent_scanned_anon - VM internal parameter. (see mm/vmscan.c)
+recent_scanned_file - VM internal parameter. (see mm/vmscan.c)
+
+Memo:
recent_rotated means recent frequency of lru rotation.
recent_scanned means recent # of scans to lru.
showing for better debug please see the code for meanings.
+Note:
+ Only anonymous and swap cache memory is listed as part of 'rss' stat.
+ This should not be confused with the true 'resident set size' or the
+ amount of physical memory used by the cgroup. Per-cgroup rss
+ accounting is not done yet.
5.3 swappiness
Similar to /proc/sys/vm/swappiness, but affecting a hierarchy of groups only.
- Following cgroup's swapiness can't be changed.
+ Following cgroups' swapiness can't be changed.
- root cgroup (uses /proc/sys/vm/swappiness).
- a cgroup which uses hierarchy and it has child cgroup.
- a cgroup which uses hierarchy and not the root of hierarchy.
diff --git a/Documentation/cgroups/resource_counter.txt b/Documentation/cgroups/resource_counter.txt
index f196ac1d7d25..95b24d766eab 100644
--- a/Documentation/cgroups/resource_counter.txt
+++ b/Documentation/cgroups/resource_counter.txt
@@ -47,13 +47,18 @@ to work with it.
2. Basic accounting routines
- a. void res_counter_init(struct res_counter *rc)
+ a. void res_counter_init(struct res_counter *rc,
+ struct res_counter *rc_parent)
Initializes the resource counter. As usual, should be the first
routine called for a new counter.
- b. int res_counter_charge[_locked]
- (struct res_counter *rc, unsigned long val)
+ The struct res_counter *parent can be used to define a hierarchical
+ child -> parent relationship directly in the res_counter structure,
+ NULL can be used to define no relationship.
+
+ c. int res_counter_charge(struct res_counter *rc, unsigned long val,
+ struct res_counter **limit_fail_at)
When a resource is about to be allocated it has to be accounted
with the appropriate resource counter (controller should determine
@@ -67,15 +72,25 @@ to work with it.
* if the charging is performed first, then it should be uncharged
on error path (if the one is called).
- c. void res_counter_uncharge[_locked]
+ If the charging fails and a hierarchical dependency exists, the
+ limit_fail_at parameter is set to the particular res_counter element
+ where the charging failed.
+
+ d. int res_counter_charge_locked
+ (struct res_counter *rc, unsigned long val)
+
+ The same as res_counter_charge(), but it must not acquire/release the
+ res_counter->lock internally (it must be called with res_counter->lock
+ held).
+
+ e. void res_counter_uncharge[_locked]
(struct res_counter *rc, unsigned long val)
When a resource is released (freed) it should be de-accounted
from the resource counter it was accounted to. This is called
"uncharging".
- The _locked routines imply that the res_counter->lock is taken.
-
+ The _locked routines imply that the res_counter->lock is taken.
2.1 Other accounting routines
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 387b8a720f4a..d79aead9418b 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -188,7 +188,7 @@ For example, you can do something like the following.
void my_midlayer_destroy_something()
{
- devres_release_group(dev, my_midlayer_create_soemthing);
+ devres_release_group(dev, my_midlayer_create_something);
}
diff --git a/Documentation/driver-model/platform.txt b/Documentation/driver-model/platform.txt
index 83009fdcbbc8..2e2c2ea90ceb 100644
--- a/Documentation/driver-model/platform.txt
+++ b/Documentation/driver-model/platform.txt
@@ -169,3 +169,62 @@ three different ways to find such a match:
be probed later if another device registers. (Which is OK, since
this interface is only for use with non-hotpluggable devices.)
+
+Early Platform Devices and Drivers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The early platform interfaces provide platform data to platform device
+drivers early on during the system boot. The code is built on top of the
+early_param() command line parsing and can be executed very early on.
+
+Example: "earlyprintk" class early serial console in 6 steps
+
+1. Registering early platform device data
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The architecture code registers platform device data using the function
+early_platform_add_devices(). In the case of early serial console this
+should be hardware configuration for the serial port. Devices registered
+at this point will later on be matched against early platform drivers.
+
+2. Parsing kernel command line
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The architecture code calls parse_early_param() to parse the kernel
+command line. This will execute all matching early_param() callbacks.
+User specified early platform devices will be registered at this point.
+For the early serial console case the user can specify port on the
+kernel command line as "earlyprintk=serial.0" where "earlyprintk" is
+the class string, "serial" is the name of the platfrom driver and
+0 is the platform device id. If the id is -1 then the dot and the
+id can be omitted.
+
+3. Installing early platform drivers belonging to a certain class
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The architecture code may optionally force registration of all early
+platform drivers belonging to a certain class using the function
+early_platform_driver_register_all(). User specified devices from
+step 2 have priority over these. This step is omitted by the serial
+driver example since the early serial driver code should be disabled
+unless the user has specified port on the kernel command line.
+
+4. Early platform driver registration
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Compiled-in platform drivers making use of early_platform_init() are
+automatically registered during step 2 or 3. The serial driver example
+should use early_platform_init("earlyprintk", &platform_driver).
+
+5. Probing of early platform drivers belonging to a certain class
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The architecture code calls early_platform_driver_probe() to match
+registered early platform devices associated with a certain class with
+registered early platform drivers. Matched devices will get probed().
+This step can be executed at any point during the early boot. As soon
+as possible may be good for the serial port case.
+
+6. Inside the early platform driver probe()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The driver code needs to take special care during early boot, especially
+when it comes to memory allocation and interrupt registration. The code
+in the probe() function can use is_early_platform_device() to check if
+it is called at early platform device or at the regular platform device
+time. The early serial driver performs register_console() at this point.
+
+For further information, see <linux/platform_device.h>.
diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware
index 2f21ecd4c205..815a57840a13 100644
--- a/Documentation/dvb/get_dvb_firmware
+++ b/Documentation/dvb/get_dvb_firmware
@@ -112,7 +112,7 @@ sub tda10045 {
sub tda10046 {
my $sourcefile = "TT_PCI_2.19h_28_11_2006.zip";
- my $url = "http://technotrend-online.com/download/software/219/$sourcefile";
+ my $url = "http://www.tt-download.com/download/updates/219/$sourcefile";
my $hash = "6a7e1e2f2644b162ff0502367553c72d";
my $outfile = "dvb-fe-tda10046.fw";
my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
@@ -129,8 +129,8 @@ sub tda10046 {
}
sub tda10046lifeview {
- my $sourcefile = "Drv_2.11.02.zip";
- my $url = "http://www.lifeview.com.tw/drivers/pci_card/FlyDVB-T/$sourcefile";
+ my $sourcefile = "7%5Cdrv_2.11.02.zip";
+ my $url = "http://www.lifeview.hk/dbimages/document/$sourcefile";
my $hash = "1ea24dee4eea8fe971686981f34fd2e0";
my $outfile = "dvb-fe-tda10046.fw";
my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
diff --git a/Documentation/edac.txt b/Documentation/edac.txt
index 8eda3fb66416..06f8f46692dc 100644
--- a/Documentation/edac.txt
+++ b/Documentation/edac.txt
@@ -23,8 +23,8 @@ first time, it was renamed to 'EDAC'.
The bluesmoke project at sourceforge.net is now utilized as a 'staging area'
for EDAC development, before it is sent upstream to kernel.org
-At the bluesmoke/EDAC project site, is a series of quilt patches against
-recent kernels, stored in a SVN respository. For easier downloading, there
+At the bluesmoke/EDAC project site is a series of quilt patches against
+recent kernels, stored in a SVN repository. For easier downloading, there
is also a tarball snapshot available.
============================================================================
@@ -73,9 +73,9 @@ the vendor should tie the parity status bits to 0 if they do not intend
to generate parity. Some vendors do not do this, and thus the parity bit
can "float" giving false positives.
-In the kernel there is a pci device attribute located in sysfs that is
+In the kernel there is a PCI device attribute located in sysfs that is
checked by the EDAC PCI scanning code. If that attribute is set,
-PCI parity/error scannining is skipped for that device. The attribute
+PCI parity/error scanning is skipped for that device. The attribute
is:
broken_parity_status
diff --git a/Documentation/fb/sh7760fb.txt b/Documentation/fb/sh7760fb.txt
index c87bfe5c630a..b994c3b10549 100644
--- a/Documentation/fb/sh7760fb.txt
+++ b/Documentation/fb/sh7760fb.txt
@@ -1,7 +1,7 @@
SH7760/SH7763 integrated LCDC Framebuffer driver
================================================
-0. Overwiew
+0. Overview
-----------
The SH7760/SH7763 have an integrated LCD Display controller (LCDC) which
supports (in theory) resolutions ranging from 1x1 to 1024x1024,
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index de491a3e2313..06d0fe15fea1 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -354,16 +354,6 @@ Who: Krzysztof Piotr Oledzki <ole@ans.pl>
---------------------------
-What: i2c_attach_client(), i2c_detach_client(), i2c_driver->detach_client(),
- i2c_adapter->client_register(), i2c_adapter->client_unregister
-When: 2.6.30
-Check: i2c_attach_client i2c_detach_client
-Why: Deprecated by the new (standard) device driver binding model. Use
- i2c_driver->probe() and ->remove() instead.
-Who: Jean Delvare <khali@linux-fr.org>
-
----------------------------
-
What: fscher and fscpos drivers
When: June 2009
Why: Deprecated by the new fschmd driver.
diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
index 8dd6db76171d..f15621ee5599 100644
--- a/Documentation/filesystems/00-INDEX
+++ b/Documentation/filesystems/00-INDEX
@@ -66,6 +66,10 @@ 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.
+nfs41-server.txt
+ - info on the Linux server implementation of NFSv4 minor version 1.
+nfs-rdma.txt
+ - how to install and setup the Linux NFS/RDMA client and server software.
nfsroot.txt
- short guide on setting up a diskless box with NFS root filesystem.
nilfs2.txt
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 76efe5b71d7d..3120f8dd2c31 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -512,16 +512,24 @@ locking rules:
BKL mmap_sem PageLocked(page)
open: no yes
close: no yes
-fault: no yes
-page_mkwrite: no yes no
+fault: no yes can return with page locked
+page_mkwrite: no yes can return with page locked
access: no yes
- ->page_mkwrite() is called when a previously read-only page is
-about to become writeable. The file system is responsible for
-protecting against truncate races. Once appropriate action has been
-taking to lock out truncate, the page range should be verified to be
-within i_size. The page mapping should also be checked that it is not
-NULL.
+ ->fault() is called when a previously not present pte is about
+to be faulted in. The filesystem must find and return the page associated
+with the passed in "pgoff" in the vm_fault structure. If it is possible that
+the page may be truncated and/or invalidated, then the filesystem must lock
+the page, then ensure it is not already truncated (the page lock will block
+subsequent truncate), and then return with VM_FAULT_LOCKED, and the page
+locked. The VM will unlock the page.
+
+ ->page_mkwrite() is called when a previously read-only pte is
+about to become writeable. The filesystem again must ensure that there are
+no truncate/invalidate races, and then return with the page locked. If
+the page has been truncated, the filesystem should not look up a new page
+like the ->fault() handler, but simply return with VM_FAULT_NOPAGE, which
+will cause the VM to retry the fault.
->access() is called when get_user_pages() fails in
acces_process_vm(), typically used to debug a process through
diff --git a/Documentation/filesystems/autofs4-mount-control.txt b/Documentation/filesystems/autofs4-mount-control.txt
index c6341745df37..8f78ded4b648 100644
--- a/Documentation/filesystems/autofs4-mount-control.txt
+++ b/Documentation/filesystems/autofs4-mount-control.txt
@@ -369,7 +369,7 @@ The call requires an initialized struct autofs_dev_ioctl. There are two
possible variations. Both use the path field set to the path of the mount
point to check and the size field adjusted appropriately. One uses the
ioctlfd field to identify a specific mount point to check while the other
-variation uses the path and optionaly arg1 set to an autofs mount type.
+variation uses the path and optionally arg1 set to an autofs mount type.
The call returns 1 if this is a mount point and sets arg1 to the device
number of the mount and field arg2 to the relevant super block magic
number (described below) or 0 if it isn't a mountpoint. In both cases
diff --git a/Documentation/filesystems/caching/cachefiles.txt b/Documentation/filesystems/caching/cachefiles.txt
index c78a49b7bba6..748a1ae49e12 100644
--- a/Documentation/filesystems/caching/cachefiles.txt
+++ b/Documentation/filesystems/caching/cachefiles.txt
@@ -407,7 +407,7 @@ A NOTE ON SECURITY
==================
CacheFiles makes use of the split security in the task_struct. It allocates
-its own task_security structure, and redirects current->act_as to point to it
+its own task_security structure, and redirects current->cred to point to it
when it acts on behalf of another process, in that process's context.
The reason it does this is that it calls vfs_mkdir() and suchlike rather than
@@ -429,9 +429,9 @@ This means it may lose signals or ptrace events for example, and affects what
the process looks like in /proc.
So CacheFiles makes use of a logical split in the security between the
-objective security (task->sec) and the subjective security (task->act_as). The
-objective security holds the intrinsic security properties of a process and is
-never overridden. This is what appears in /proc, and is what is used when a
+objective security (task->real_cred) and the subjective security (task->cred).
+The objective security holds the intrinsic security properties of a process and
+is never overridden. This is what appears in /proc, and is what is used when a
process is the target of an operation by some other process (SIGKILL for
example).
diff --git a/Documentation/filesystems/caching/netfs-api.txt b/Documentation/filesystems/caching/netfs-api.txt
index 4db125b3a5c6..2666b1ed5e9e 100644
--- a/Documentation/filesystems/caching/netfs-api.txt
+++ b/Documentation/filesystems/caching/netfs-api.txt
@@ -184,7 +184,7 @@ This has the following fields:
have index children.
If this function is not supplied or if it returns NULL then the first
- cache in the parent's list will be chosed, or failing that, the first
+ cache in the parent's list will be chosen, or failing that, the first
cache in the master list.
(4) A function to retrieve an object's key from the netfs [mandatory].
diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
index 97882df04865..608fdba97b72 100644
--- a/Documentation/filesystems/ext4.txt
+++ b/Documentation/filesystems/ext4.txt
@@ -294,7 +294,7 @@ max_batch_time=usec Maximum amount of time ext4 should wait for
amount of time (on average) that it takes to
finish committing a transaction. Call this time
the "commit time". If the time that the
- transactoin has been running is less than the
+ transaction has been running is less than the
commit time, ext4 will try sleeping for the
commit time to see if other operations will join
the transaction. The commit time is capped by
@@ -328,7 +328,7 @@ noauto_da_alloc replacing existing files via patterns such as
journal commit, in the default data=ordered
mode, the data blocks of the new file are forced
to disk before the rename() operation is
- commited. This provides roughly the same level
+ committed. This provides roughly the same level
of guarantees as ext3, and avoids the
"zero-length" problem that can happen when a
system crashes before the delayed allocation
@@ -358,7 +358,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. Curently ext4 does not have delayed
+outperforms all others modes. Currently ext4 does not have delayed
allocation support if this data journalling mode is selected.
References
diff --git a/Documentation/filesystems/fiemap.txt b/Documentation/filesystems/fiemap.txt
index 1e3defcfe50b..606233cd4618 100644
--- a/Documentation/filesystems/fiemap.txt
+++ b/Documentation/filesystems/fiemap.txt
@@ -204,7 +204,7 @@ fiemap_check_flags() helper:
int fiemap_check_flags(struct fiemap_extent_info *fieinfo, u32 fs_flags);
-The struct fieinfo should be passed in as recieved from ioctl_fiemap(). The
+The struct fieinfo should be passed in as received from ioctl_fiemap(). The
set of fiemap flags which the fs understands should be passed via fs_flags. If
fiemap_check_flags finds invalid user flags, it will place the bad values in
fieinfo->fi_flags and return -EBADR. If the file system gets -EBADR, from
diff --git a/Documentation/filesystems/nfs-rdma.txt b/Documentation/filesystems/nfs-rdma.txt
index 85eaeaddd27c..e386f7e4bcee 100644
--- a/Documentation/filesystems/nfs-rdma.txt
+++ b/Documentation/filesystems/nfs-rdma.txt
@@ -100,7 +100,7 @@ Installation
$ sudo cp utils/mount/mount.nfs /sbin/mount.nfs
In this location, mount.nfs will be invoked automatically for NFS mounts
- by the system mount commmand.
+ by the system mount command.
NOTE: mount.nfs and therefore nfs-utils-1.1.2 or greater is only needed
on the NFS client machine. You do not need this specific version of
diff --git a/Documentation/filesystems/pohmelfs/design_notes.txt b/Documentation/filesystems/pohmelfs/design_notes.txt
index 6d6db60d567d..dcf833587162 100644
--- a/Documentation/filesystems/pohmelfs/design_notes.txt
+++ b/Documentation/filesystems/pohmelfs/design_notes.txt
@@ -56,9 +56,10 @@ workloads and can fully utilize the bandwidth to the servers when doing bulk
data transfers.
POHMELFS clients operate with a working set of servers and are capable of balancing read-only
-operations (like lookups or directory listings) between them.
+operations (like lookups or directory listings) between them according to IO priorities.
Administrators can add or remove servers from the set at run-time via special commands (described
-in Documentation/pohmelfs/info.txt file). Writes are replicated to all servers.
+in Documentation/pohmelfs/info.txt file). Writes are replicated to all servers, which are connected
+with write permission turned on. IO priority and permissions can be changed in run-time.
POHMELFS is capable of full data channel encryption and/or strong crypto hashing.
One can select any kernel supported cipher, encryption mode, hash type and operation mode
diff --git a/Documentation/filesystems/pohmelfs/info.txt b/Documentation/filesystems/pohmelfs/info.txt
index 4e3d50157083..db2e41393626 100644
--- a/Documentation/filesystems/pohmelfs/info.txt
+++ b/Documentation/filesystems/pohmelfs/info.txt
@@ -1,6 +1,8 @@
POHMELFS usage information.
-Mount options:
+Mount options.
+All but index, number of crypto threads and maximum IO size can changed via remount.
+
idx=%u
Each mountpoint is associated with a special index via this option.
Administrator can add or remove servers from the given index, so all mounts,
@@ -52,16 +54,27 @@ mcache_timeout=%u
Usage examples.
-Add (or remove if it already exists) server server1.net:1025 into the working set with index $idx
+Add server server1.net:1025 into the working set with index $idx
with appropriate hash algorithm and key file and cipher algorithm, mode and key file:
-$cfg -a server1.net -p 1025 -i $idx -K $hash_key -k $cipher_key
+$cfg A add -a server1.net -p 1025 -i $idx -K $hash_key -k $cipher_key
Mount filesystem with given index $idx to /mnt mountpoint.
Client will connect to all servers specified in the working set via previous command:
mount -t pohmel -o idx=$idx q /mnt
-One can add or remove servers from working set after mounting too.
+Change permissions to read-only (-I 1 option, '-I 2' - write-only, 3 - rw):
+$cfg A modify -a server1.net -p 1025 -i $idx -I 1
+
+Change IO priority to 123 (node with the highest priority gets read requests).
+$cfg A modify -a server1.net -p 1025 -i $idx -P 123
+One can check currect status of all connections in the mountstats file:
+# cat /proc/$PID/mountstats
+...
+device none mounted on /mnt with fstype pohmel
+idx addr(:port) socket_type protocol active priority permissions
+0 server1.net:1026 1 6 1 250 1
+0 server2.net:1025 1 6 1 123 3
Server installation.
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index ce84cfc9eae0..cd8717a36271 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -366,7 +366,7 @@ just those considered 'most important'. The new vectors are:
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.
+ determine the occurrence of interrupts 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
@@ -551,7 +551,7 @@ Committed_AS: The amount of memory presently allocated on the system.
memory once that memory has been successfully allocated.
VmallocTotal: total size of vmalloc memory area
VmallocUsed: amount of vmalloc area which is used
-VmallocChunk: largest contigious block of vmalloc area which is free
+VmallocChunk: largest contiguous block of vmalloc area which is free
..............................................................................
diff --git a/Documentation/filesystems/sysfs-pci.txt b/Documentation/filesystems/sysfs-pci.txt
index 26e4b8bc53ee..85354b32d731 100644
--- a/Documentation/filesystems/sysfs-pci.txt
+++ b/Documentation/filesystems/sysfs-pci.txt
@@ -72,7 +72,7 @@ The 'rom' file is special in that it provides read-only access to the device's
ROM file, if available. It's disabled by default, however, so applications
should write the string "1" to the file to enable it before attempting a read
call, and disable it following the access by writing "0" to the file. Note
-that the device must be enabled for a rom read to return data succesfully.
+that the device must be enabled for a rom read to return data successfully.
In the event a driver is not bound to the device, it can be enabled using the
'enable' file, documented above.
diff --git a/Documentation/filesystems/vfat.txt b/Documentation/filesystems/vfat.txt
index 3a5ddc96901a..5147be5e13cd 100644
--- a/Documentation/filesystems/vfat.txt
+++ b/Documentation/filesystems/vfat.txt
@@ -124,10 +124,10 @@ sys_immutable -- If set, ATTR_SYS attribute on FAT is handled as
flush -- If set, the filesystem will try to flush to disk more
early than normal. Not set by default.
-rodir -- FAT has the ATTR_RO (read-only) attribute. But on Windows,
- the ATTR_RO of the directory will be just ignored actually,
- and is used by only applications as flag. E.g. it's setted
- for the customized folder.
+rodir -- FAT has the ATTR_RO (read-only) attribute. On Windows,
+ the ATTR_RO of the directory will just be ignored,
+ and is used only by applications as a flag (e.g. it's set
+ for the customized folder).
If you want to use ATTR_RO as read-only flag even for
the directory, set this option.
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index deeeed0faa8f..f49eecf2e573 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -277,8 +277,7 @@ or bottom half).
unfreeze_fs: called when VFS is unlocking a filesystem and making it writable
again.
- statfs: called when the VFS needs to get filesystem statistics. This
- is called with the kernel lock held
+ statfs: called when the VFS needs to get filesystem statistics.
remount_fs: called when the filesystem is remounted. This is called
with the kernel lock held
diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt
index 145c25a170c7..e4b6985044a2 100644
--- a/Documentation/gpio.txt
+++ b/Documentation/gpio.txt
@@ -458,7 +458,7 @@ debugfs interface, since it provides control over GPIO direction and
value instead of just showing a gpio state summary. Plus, it could be
present on production systems without debugging support.
-Given approprate hardware documentation for the system, userspace could
+Given appropriate hardware documentation for the system, userspace could
know for example that GPIO #23 controls the write protect line used to
protect boot loader segments in flash memory. System upgrade procedures
may need to temporarily remove that protection, first importing a GPIO,
diff --git a/Documentation/hwmon/ibmaem b/Documentation/hwmon/ibmaem
index e98bdfea3467..1e0d59e000b4 100644
--- a/Documentation/hwmon/ibmaem
+++ b/Documentation/hwmon/ibmaem
@@ -7,7 +7,7 @@ henceforth as AEM.
Supported systems:
* Any recent IBM System X server with AEM support.
This includes the x3350, x3550, x3650, x3655, x3755, x3850 M2,
- x3950 M2, and certain HS2x/LS2x/QS2x blades. The IPMI host interface
+ x3950 M2, and certain HC10/HS2x/LS2x/QS2x blades. The IPMI host interface
driver ("ipmi-si") needs to be loaded for this driver to do anything.
Prefix: 'ibmaem'
Datasheet: Not available
diff --git a/Documentation/i2c/instantiating-devices b/Documentation/i2c/instantiating-devices
index b55ce57a84db..c740b7b41088 100644
--- a/Documentation/i2c/instantiating-devices
+++ b/Documentation/i2c/instantiating-devices
@@ -165,3 +165,47 @@ was done there. Two significant differences are:
Once again, method 3 should be avoided wherever possible. Explicit device
instantiation (methods 1 and 2) is much preferred for it is safer and
faster.
+
+
+Method 4: Instantiate from user-space
+-------------------------------------
+
+In general, the kernel should know which I2C devices are connected and
+what addresses they live at. However, in certain cases, it does not, so a
+sysfs interface was added to let the user provide the information. This
+interface is made of 2 attribute files which are created in every I2C bus
+directory: new_device and delete_device. Both files are write only and you
+must write the right parameters to them in order to properly instantiate,
+respectively delete, an I2C device.
+
+File new_device takes 2 parameters: the name of the I2C device (a string)
+and the address of the I2C device (a number, typically expressed in
+hexadecimal starting with 0x, but can also be expressed in decimal.)
+
+File delete_device takes a single parameter: the address of the I2C
+device. As no two devices can live at the same address on a given I2C
+segment, the address is sufficient to uniquely identify the device to be
+deleted.
+
+Example:
+# echo eeprom 0x50 > /sys/class/i2c-adapter/i2c-3/new_device
+
+While this interface should only be used when in-kernel device declaration
+can't be done, there is a variety of cases where it can be helpful:
+* The I2C driver usually detects devices (method 3 above) but the bus
+ segment your device lives on doesn't have the proper class bit set and
+ thus detection doesn't trigger.
+* The I2C driver usually detects devices, but your device lives at an
+ unexpected address.
+* The I2C driver usually detects devices, but your device is not detected,
+ either because the detection routine is too strict, or because your
+ device is not officially supported yet but you know it is compatible.
+* You are developing a driver on a test board, where you soldered the I2C
+ device yourself.
+
+This interface is a replacement for the force_* module parameters some I2C
+drivers implement. Being implemented in i2c-core rather than in each
+device driver individually, it is much more efficient, and also has the
+advantage that you do not have to reload the driver to change a setting.
+You can also instantiate the device before the driver is loaded or even
+available, and you don't need to know what driver the device needs.
diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
index c1a06f989cf7..7860aafb483d 100644
--- a/Documentation/i2c/writing-clients
+++ b/Documentation/i2c/writing-clients
@@ -126,19 +126,9 @@ different) configuration information, as do drivers handling chip variants
that can't be distinguished by protocol probing, or which need some board
specific information to operate correctly.
-Accordingly, the I2C stack now has two models for associating I2C devices
-with their drivers: the original "legacy" model, and a newer one that's
-fully compatible with the Linux 2.6 driver model. These models do not mix,
-since the "legacy" model requires drivers to create "i2c_client" device
-objects after SMBus style probing, while the Linux driver model expects
-drivers to be given such device objects in their probe() routines.
-The legacy model is deprecated now and will soon be removed, so we no
-longer document it here.
-
-
-Standard Driver Model Binding ("New Style")
--------------------------------------------
+Device/Driver Binding
+---------------------
System infrastructure, typically board-specific initialization code or
boot firmware, reports what I2C devices exist. For example, there may be
@@ -201,7 +191,7 @@ a given I2C bus. This is for example the case of hardware monitoring
devices on a PC's SMBus. In that case, you may want to let your driver
detect supported devices automatically. This is how the legacy model
was working, and is now available as an extension to the standard
-driver model (so that we can finally get rid of the legacy model.)
+driver model.
You simply have to define a detect callback which will attempt to
identify supported devices (returning 0 for supported ones and -ENODEV
diff --git a/Documentation/input/bcm5974.txt b/Documentation/input/bcm5974.txt
new file mode 100644
index 000000000000..5e22dcf6d48d
--- /dev/null
+++ b/Documentation/input/bcm5974.txt
@@ -0,0 +1,65 @@
+BCM5974 Driver (bcm5974)
+------------------------
+ Copyright (C) 2008-2009 Henrik Rydberg <rydberg@euromail.se>
+
+The USB initialization and package decoding was made by Scott Shawcroft as
+part of the touchd user-space driver project:
+ Copyright (C) 2008 Scott Shawcroft (scott.shawcroft@gmail.com)
+
+The BCM5974 driver is based on the appletouch driver:
+ Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+ Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net)
+ Copyright (C) 2005 Stelian Pop (stelian@popies.net)
+ Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
+ Copyright (C) 2005 Peter Osterlund (petero2@telia.com)
+ Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch)
+ Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch)
+
+This driver adds support for the multi-touch trackpad on the new Apple
+Macbook Air and Macbook Pro laptops. It replaces the appletouch driver on
+those computers, and integrates well with the synaptics driver of the Xorg
+system.
+
+Known to work on Macbook Air, Macbook Pro Penryn and the new unibody
+Macbook 5 and Macbook Pro 5.
+
+Usage
+-----
+
+The driver loads automatically for the supported usb device ids, and
+becomes available both as an event device (/dev/input/event*) and as a
+mouse via the mousedev driver (/dev/input/mice).
+
+USB Race
+--------
+
+The Apple multi-touch trackpads report both mouse and keyboard events via
+different interfaces of the same usb device. This creates a race condition
+with the HID driver, which, if not told otherwise, will find the standard
+HID mouse and keyboard, and claim the whole device. To remedy, the usb
+product id must be listed in the mouse_ignore list of the hid driver.
+
+Debug output
+------------
+
+To ease the development for new hardware version, verbose packet output can
+be switched on with the debug kernel module parameter. The range [1-9]
+yields different levels of verbosity. Example (as root):
+
+echo -n 9 > /sys/module/bcm5974/parameters/debug
+
+tail -f /var/log/debug
+
+echo -n 0 > /sys/module/bcm5974/parameters/debug
+
+Trivia
+------
+
+The driver was developed at the ubuntu forums in June 2008 [1], and now has
+a more permanent home at bitmath.org [2].
+
+Links
+-----
+
+[1] http://ubuntuforums.org/showthread.php?t=840040
+[2] http://http://bitmath.org/code/
diff --git a/Documentation/input/input.txt b/Documentation/input/input.txt
index 686ee9932dff..b93c08442e3c 100644
--- a/Documentation/input/input.txt
+++ b/Documentation/input/input.txt
@@ -278,7 +278,7 @@ struct input_event {
};
'time' is the timestamp, it returns the time at which the event happened.
-Type is for example EV_REL for relative moment, REL_KEY for a keypress or
+Type is for example EV_REL for relative moment, EV_KEY for a keypress or
release. More types are defined in include/linux/input.h.
'code' is event code, for example REL_X or KEY_BACKSPACE, again a complete
diff --git a/Documentation/input/multi-touch-protocol.txt b/Documentation/input/multi-touch-protocol.txt
new file mode 100644
index 000000000000..9f09557aea39
--- /dev/null
+++ b/Documentation/input/multi-touch-protocol.txt
@@ -0,0 +1,140 @@
+Multi-touch (MT) Protocol
+-------------------------
+ Copyright (C) 2009 Henrik Rydberg <rydberg@euromail.se>
+
+
+Introduction
+------------
+
+In order to utilize the full power of the new multi-touch devices, a way to
+report detailed finger data to user space is needed. This document
+describes the multi-touch (MT) protocol which allows kernel drivers to
+report details for an arbitrary number of fingers.
+
+
+Usage
+-----
+
+Anonymous finger details are sent sequentially as separate packets of ABS
+events. Only the ABS_MT events are recognized as part of a finger
+packet. The end of a packet is marked by calling the input_mt_sync()
+function, which generates a SYN_MT_REPORT event. The end of multi-touch
+transfer is marked by calling the usual input_sync() function.
+
+A set of ABS_MT events with the desired properties is defined. The events
+are divided into categories, to allow for partial implementation. The
+minimum set consists of ABS_MT_TOUCH_MAJOR, ABS_MT_POSITION_X and
+ABS_MT_POSITION_Y, which allows for multiple fingers to be tracked. If the
+device supports it, the ABS_MT_WIDTH_MAJOR may be used to provide the size
+of the approaching finger. Anisotropy and direction may be specified with
+ABS_MT_TOUCH_MINOR, ABS_MT_WIDTH_MINOR and ABS_MT_ORIENTATION. Devices with
+more granular information may specify general shapes as blobs, i.e., as a
+sequence of rectangular shapes grouped together by an
+ABS_MT_BLOB_ID. Finally, the ABS_MT_TOOL_TYPE may be used to specify
+whether the touching tool is a finger or a pen or something else.
+
+
+Event Semantics
+---------------
+
+The word "contact" is used to describe a tool which is in direct contact
+with the surface. A finger, a pen or a rubber all classify as contacts.
+
+ABS_MT_TOUCH_MAJOR
+
+The length of the major axis of the contact. The length should be given in
+surface units. If the surface has an X times Y resolution, the largest
+possible value of ABS_MT_TOUCH_MAJOR is sqrt(X^2 + Y^2), the diagonal.
+
+ABS_MT_TOUCH_MINOR
+
+The length, in surface units, of the minor axis of the contact. If the
+contact is circular, this event can be omitted.
+
+ABS_MT_WIDTH_MAJOR
+
+The length, in surface units, of the major axis of the approaching
+tool. This should be understood as the size of the tool itself. The
+orientation of the contact and the approaching tool are assumed to be the
+same.
+
+ABS_MT_WIDTH_MINOR
+
+The length, in surface units, of the minor axis of the approaching
+tool. Omit if circular.
+
+The above four values can be used to derive additional information about
+the contact. The ratio ABS_MT_TOUCH_MAJOR / ABS_MT_WIDTH_MAJOR approximates
+the notion of pressure. The fingers of the hand and the palm all have
+different characteristic widths [1].
+
+ABS_MT_ORIENTATION
+
+The orientation of the ellipse. The value should describe half a revolution
+clockwise around the touch center. The scale of the value is arbitrary, but
+zero should be returned for an ellipse aligned along the Y axis of the
+surface. As an example, an index finger placed straight onto the axis could
+return zero orientation, something negative when twisted to the left, and
+something positive when twisted to the right. This value can be omitted if
+the touching object is circular, or if the information is not available in
+the kernel driver.
+
+ABS_MT_POSITION_X
+
+The surface X coordinate of the center of the touching ellipse.
+
+ABS_MT_POSITION_Y
+
+The surface Y coordinate of the center of the touching ellipse.
+
+ABS_MT_TOOL_TYPE
+
+The type of approaching tool. A lot of kernel drivers cannot distinguish
+between different tool types, such as a finger or a pen. In such cases, the
+event should be omitted. The protocol currently supports MT_TOOL_FINGER and
+MT_TOOL_PEN [2].
+
+ABS_MT_BLOB_ID
+
+The BLOB_ID groups several packets together into one arbitrarily shaped
+contact. This is a low-level anonymous grouping, and should not be confused
+with the high-level contactID, explained below. Most kernel drivers will
+not have this capability, and can safely omit the event.
+
+
+Finger Tracking
+---------------
+
+The kernel driver should generate an arbitrary enumeration of the set of
+anonymous contacts currently on the surface. The order in which the packets
+appear in the event stream is not important.
+
+The process of finger tracking, i.e., to assign a unique contactID to each
+initiated contact on the surface, is left to user space; preferably the
+multi-touch X driver [3]. In that driver, the contactID stays the same and
+unique until the contact vanishes (when the finger leaves the surface). The
+problem of assigning a set of anonymous fingers to a set of identified
+fingers is a euclidian bipartite matching problem at each event update, and
+relies on a sufficiently rapid update rate.
+
+Notes
+-----
+
+In order to stay compatible with existing applications, the data
+reported in a finger packet must not be recognized as single-touch
+events. In addition, all finger data must bypass input filtering,
+since subsequent events of the same type refer to different fingers.
+
+The first kernel driver to utilize the MT protocol is the bcm5974 driver,
+where examples can be found.
+
+[1] With the extension ABS_MT_APPROACH_X and ABS_MT_APPROACH_Y, the
+difference between the contact position and the approaching tool position
+could be used to derive tilt.
+[2] The list can of course be extended.
+[3] The multi-touch X driver is currently in the prototyping stage. At the
+time of writing (April 2009), the MT protocol is not yet merged, and the
+prototype implements finger matching, basic mouse support and two-finger
+scrolling. The project aims at improving the quality of current multi-touch
+functionality available in the synaptics X driver, and in addition
+implement more advanced gestures.
diff --git a/Documentation/input/rotary-encoder.txt b/Documentation/input/rotary-encoder.txt
index 435102a26d96..3a6aec40c0b0 100644
--- a/Documentation/input/rotary-encoder.txt
+++ b/Documentation/input/rotary-encoder.txt
@@ -67,7 +67,12 @@ data with it.
struct rotary_encoder_platform_data is declared in
include/linux/rotary-encoder.h and needs to be filled with the number of
steps the encoder has and can carry information about externally inverted
-signals (because of used invertig buffer or other reasons).
+signals (because of an inverting buffer or other reasons). The encoder
+can be set up to deliver input information as either an absolute or relative
+axes. For relative axes the input event returns +/-1 for each step. For
+absolute axes the position of the encoder can either roll over between zero
+and the number of steps or will clamp at the maximum and zero depending on
+the configuration.
Because GPIO to IRQ mapping is platform specific, this information must
be given in seperately to the driver. See the example below.
@@ -85,6 +90,8 @@ be given in seperately to the driver. See the example below.
static struct rotary_encoder_platform_data my_rotary_encoder_info = {
.steps = 24,
.axis = ABS_X,
+ .relative_axis = false,
+ .rollover = false,
.gpio_a = GPIO_ROTARY_A,
.gpio_b = GPIO_ROTARY_B,
.inverted_a = 0,
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index d4b05672f9f7..d76cfd8712e1 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -316,6 +316,16 @@ more details, with real examples.
#arch/m68k/fpsp040/Makefile
ldflags-y := -x
+ subdir-ccflags-y, subdir-asflags-y
+ The two flags listed above are similar to ccflags-y and as-falgs-y.
+ The difference is that the subdir- variants has effect for the kbuild
+ file where tey are present and all subdirectories.
+ Options specified using subdir-* are added to the commandline before
+ the options specified using the non-subdir variants.
+
+ Example:
+ subdir-ccflags-y := -Werror
+
CFLAGS_$@, AFLAGS_$@
CFLAGS_$@ and AFLAGS_$@ only apply to commands in current
diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt
index 3f4bc840da8b..cab61d842259 100644
--- a/Documentation/kdump/kdump.txt
+++ b/Documentation/kdump/kdump.txt
@@ -108,7 +108,7 @@ There are two possible methods of using Kdump.
2) Or use the system kernel binary itself as dump-capture kernel and there is
no need to build a separate dump-capture kernel. This is possible
- only with the architecutres which support a relocatable kernel. As
+ only with the architectures which support a relocatable kernel. As
of today, i386, x86_64, ppc64 and ia64 architectures support relocatable
kernel.
@@ -222,7 +222,7 @@ Dump-capture kernel config options (Arch Dependent, ia64)
----------------------------------------------------------
- No specific options are required to create a dump-capture kernel
- for ia64, other than those specified in the arch idependent section
+ for ia64, other than those specified in the arch independent section
above. This means that it is possible to use the system kernel
as a dump-capture kernel if desired.
diff --git a/Documentation/kernel-doc-nano-HOWTO.txt b/Documentation/kernel-doc-nano-HOWTO.txt
index 026ec7d57384..4d04572b6549 100644
--- a/Documentation/kernel-doc-nano-HOWTO.txt
+++ b/Documentation/kernel-doc-nano-HOWTO.txt
@@ -269,7 +269,10 @@ Use the argument mechanism to document members or constants.
Inside a struct description, you can use the "private:" and "public:"
comment tags. Structure fields that are inside a "private:" area
-are not listed in the generated output documentation.
+are not listed in the generated output documentation. The "private:"
+and "public:" tags must begin immediately following a "/*" comment
+marker. They may optionally include comments between the ":" and the
+ending "*/" marker.
Example:
@@ -283,7 +286,7 @@ Example:
struct my_struct {
int a;
int b;
-/* private: */
+/* private: internal use only */
int c;
};
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 6172e4360f60..a0ebbbbec63f 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -17,6 +17,12 @@ are specified on the kernel command line with the module name plus
usbcore.blinkenlights=1
+Hyphens (dashes) and underscores are equivalent in parameter names, so
+ log_buf_len=1M print-fatal-signals=1
+can also be entered as
+ log-buf-len=1M print_fatal_signals=1
+
+
This document may not be entirely up to date and comprehensive. The command
"modinfo -p ${modulename}" shows a current list of all parameters of a loadable
module. Loadable modules, after being loaded into the running kernel, also
@@ -134,7 +140,7 @@ and is between 256 and 4096 characters. It is defined in the file
./include/asm/setup.h as COMMAND_LINE_SIZE.
- acpi= [HW,ACPI,X86-64,i386]
+ acpi= [HW,ACPI,X86]
Advanced Configuration and Power Interface
Format: { force | off | ht | strict | noirq | rsdt }
force -- enable ACPI if default was off
@@ -218,7 +224,7 @@ and is between 256 and 4096 characters. It is defined in the file
acpi_osi="!string2" # remove built-in string2
acpi_osi= # disable all strings
- acpi_pm_good [X86-32,X86-64]
+ acpi_pm_good [X86]
Override the pmtimer bug detection: force the kernel
to assume that this machine's pmtimer latches its value
and always returns good values.
@@ -231,6 +237,35 @@ and is between 256 and 4096 characters. It is defined in the file
power state again in power transition.
1 : disable the power state check
+ acpi_sci= [HW,ACPI] ACPI System Control Interrupt trigger mode
+ Format: { level | edge | high | low }
+
+ acpi_serialize [HW,ACPI] force serialization of AML methods
+
+ acpi_skip_timer_override [HW,ACPI]
+ Recognize and ignore IRQ0/pin2 Interrupt Override.
+ For broken nForce2 BIOS resulting in XT-PIC timer.
+
+ acpi_sleep= [HW,ACPI] Sleep options
+ Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig,
+ old_ordering, s4_nonvs }
+ See Documentation/power/video.txt for information on
+ s3_bios and s3_mode.
+ s3_beep is for debugging; it makes the PC's speaker beep
+ as soon as the kernel's real-mode entry point is called.
+ s4_nohwsig prevents ACPI hardware signature from being
+ used during resume from hibernation.
+ old_ordering causes the ACPI 1.0 ordering of the _PTS
+ control method, with respect to putting devices into
+ low power states, to be enforced (the ACPI 2.0 ordering
+ of _PTS is used by default).
+ s4_nonvs prevents the kernel from saving/restoring the
+ ACPI NVS memory during hibernation.
+
+ acpi_use_timer_override [HW,ACPI]
+ Use timer override. For some broken Nvidia NF5 boards
+ that require a timer override, but don't have HPET
+
acpi_enforce_resources= [ACPI]
{ strict | lax | no }
Check for resource conflicts between native drivers
@@ -250,6 +285,9 @@ and is between 256 and 4096 characters. It is defined in the file
ad1848= [HW,OSS]
Format: <io>,<irq>,<dma>,<dma2>,<type>
+ add_efi_memmap [EFI; X86] Include EFI memory map in
+ kernel's map of available physical RAM.
+
advansys= [HW,SCSI]
See header of drivers/scsi/advansys.c.
@@ -313,7 +351,7 @@ and is between 256 and 4096 characters. It is defined in the file
not play well with APC CPU idle - disable it if you have
APC and your system crashes randomly.
- apic= [APIC,i386] Advanced Programmable Interrupt Controller
+ apic= [APIC,X86-32] Advanced Programmable Interrupt Controller
Change the output verbosity whilst booting
Format: { quiet (default) | verbose | debug }
Change the amount of debugging information output
@@ -459,7 +497,7 @@ and is between 256 and 4096 characters. It is defined in the file
Also note the kernel might malfunction if you disable
some critical bits.
- code_bytes [IA32/X86_64] How many bytes of object code to print
+ code_bytes [X86] How many bytes of object code to print
in an oops report.
Range: 0 - 8192
Default: 64
@@ -592,7 +630,7 @@ and is between 256 and 4096 characters. It is defined in the file
MTRR settings. This parameter disables that behavior,
possibly causing your machine to run very slowly.
- disable_timer_pin_1 [i386,x86-64]
+ disable_timer_pin_1 [X86]
Disable PIN 1 of APIC timer
Can be useful to work around chipset bugs.
@@ -624,7 +662,7 @@ 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.
- earlyprintk= [X86-32,X86-64,SH,BLACKFIN]
+ earlyprintk= [X86,SH,BLACKFIN]
earlyprintk=vga
earlyprintk=serial[,ttySn[,baudrate]]
earlyprintk=dbgp
@@ -659,7 +697,7 @@ and is between 256 and 4096 characters. It is defined in the file
See Documentation/block/as-iosched.txt and
Documentation/block/deadline-iosched.txt for details.
- elfcorehdr= [IA64,PPC,SH,X86-32,X86_64]
+ elfcorehdr= [IA64,PPC,SH,X86]
Specifies physical address of start of kernel core
image elf header. Generally kexec loader will
pass this option to capture kernel.
@@ -670,7 +708,7 @@ and is between 256 and 4096 characters. It is defined in the file
to discrete, to make X server driver able to add WB
entry later. This parameter enables that.
- enable_timer_pin_1 [i386,x86-64]
+ enable_timer_pin_1 [X86]
Enable PIN 1 of APIC timer
Can be useful to work around chipset bugs
(in particular on some ATI chipsets).
@@ -743,7 +781,7 @@ and is between 256 and 4096 characters. It is defined in the file
hashdist= [KNL,NUMA] Large hashes allocated during boot
are distributed across NUMA nodes. Defaults on
- for IA-64, off otherwise.
+ for 64bit NUMA, off otherwise.
Format: 0 | 1 (for off | on)
hcl= [IA-64] SGI's Hardware Graph compatibility layer
@@ -933,12 +971,13 @@ and is between 256 and 4096 characters. It is defined in the file
nomerge
forcesac
soft
+ pt [x86, IA64]
io7= [HW] IO7 for Marvel based alpha systems
See comment before marvel_specify_io7 in
arch/alpha/kernel/core_marvel.c.
- io_delay= [X86-32,X86-64] I/O delay method
+ io_delay= [X86] I/O delay method
0x80
Standard port 0x80 based delay
0xed
@@ -1000,7 +1039,7 @@ and is between 256 and 4096 characters. It is defined in the file
keepinitrd [HW,ARM]
- kernelcore=nn[KMG] [KNL,X86-32,IA-64,PPC,X86-64] This parameter
+ kernelcore=nn[KMG] [KNL,X86,IA-64,PPC] This parameter
specifies the amount of memory usable by the kernel
for non-movable allocations. The requested amount is
spread evenly throughout all nodes in the system. The
@@ -1027,14 +1066,18 @@ and is between 256 and 4096 characters. It is defined in the file
kgdboc= [HW] kgdb over consoles.
Requires a tty driver that supports console polling.
- (only serial suported for now)
+ (only serial supported for now)
Format: <serial_device>[,baud]
kmac= [MIPS] korina ethernet MAC address.
Configure the RouterBoard 532 series on-chip
Ethernet adapter MAC address.
- kstack=N [X86-32,X86-64] Print N words from the kernel stack
+ kmemleak= [KNL] Boot-time kmemleak enable/disable
+ Valid arguments: on, off
+ Default: on
+
+ kstack=N [X86] Print N words from the kernel stack
in oops dumps.
l2cr= [PPC]
@@ -1044,7 +1087,7 @@ and is between 256 and 4096 characters. It is defined in the file
lapic [X86-32,APIC] Enable the local APIC even if BIOS
disabled it.
- lapic_timer_c2_ok [X86-32,x86-64,APIC] trust the local apic timer
+ lapic_timer_c2_ok [X86,APIC] trust the local apic timer
in C2 power state.
libata.dma= [LIBATA] DMA control
@@ -1229,7 +1272,7 @@ and is between 256 and 4096 characters. It is defined in the file
[KNL,SH] Allow user to override the default size for
per-device physically contiguous DMA buffers.
- memmap=exactmap [KNL,X86-32,X86_64] Enable setting of an exact
+ memmap=exactmap [KNL,X86] Enable setting of an exact
E820 memory map, as specified by the user.
Such memmap=exactmap lines can be constructed based on
BIOS output or other requirements. See the memmap=nn@ss
@@ -1320,7 +1363,7 @@ and is between 256 and 4096 characters. It is defined in the file
mousedev.yres= [MOUSE] Vertical screen resolution, used for devices
reporting absolute coordinates, such as tablets
- movablecore=nn[KMG] [KNL,X86-32,IA-64,PPC,X86-64] This parameter
+ movablecore=nn[KMG] [KNL,X86,IA-64,PPC] This parameter
is similar to kernelcore except it specifies the
amount of memory used for migratable allocations.
If both kernelcore and movablecore is specified,
@@ -1352,7 +1395,7 @@ and is between 256 and 4096 characters. It is defined in the file
('y', default) or cooked coordinates ('n')
mtrr_chunk_size=nn[KMG] [X86]
- used for mtrr cleanup. It is largest continous chunk
+ used for mtrr cleanup. It is largest continuous chunk
that could hold holes aka. UC entries.
mtrr_gran_size=nn[KMG] [X86]
@@ -1422,7 +1465,7 @@ and is between 256 and 4096 characters. It is defined in the file
when a NMI is triggered.
Format: [state][,regs][,debounce][,die]
- nmi_watchdog= [KNL,BUGS=X86-32,X86-64] Debugging features for SMP kernels
+ nmi_watchdog= [KNL,BUGS=X86] Debugging features for SMP kernels
Format: [panic,][num]
Valid num: 0,1,2
0 - turn nmi_watchdog off
@@ -1475,11 +1518,11 @@ and is between 256 and 4096 characters. It is defined in the file
nodsp [SH] Disable hardware DSP at boot time.
- noefi [X86-32,X86-64] Disable EFI runtime services support.
+ noefi [X86] Disable EFI runtime services support.
noexec [IA-64]
- noexec [X86-32,X86-64]
+ noexec [X86]
On X86-32 available only on PAE configured kernels.
noexec=on: enable non-executable mappings (default)
noexec=off: disable non-executable mappings
@@ -1525,7 +1568,7 @@ and is between 256 and 4096 characters. It is defined in the file
noirqdebug [X86-32] Disables the code which attempts to detect and
disable unhandled interrupt sources.
- no_timer_check [X86-32,X86_64,APIC] Disables the code which tests for
+ no_timer_check [X86,APIC] Disables the code which tests for
broken timer IRQ sources.
noisapnp [ISAPNP] Disables ISA PnP code.
@@ -1533,6 +1576,9 @@ and is between 256 and 4096 characters. It is defined in the file
noinitrd [RAM] Tells the kernel not to load any configured
initial RAM disk.
+ nointremap [X86-64, Intel-IOMMU] Do not enable interrupt
+ remapping.
+
nointroute [IA-64]
nojitter [IA64] Disables jitter checking for ITC timers.
@@ -1588,6 +1634,8 @@ and is between 256 and 4096 characters. It is defined in the file
nowb [ARM]
+ nox2apic [X86-64,APIC] Do not enable x2APIC mode.
+
nptcg= [IA64] Override max number of concurrent global TLB
purges which is reported from either PAL_VM_SUMMARY or
SAL PALO.
@@ -1689,7 +1737,7 @@ and is between 256 and 4096 characters. It is defined in the file
disable the use of PCIE advanced error reporting.
nodomains [PCI] Disable support for multiple PCI
root domains (aka PCI segments, in ACPI-speak).
- nommconf [X86-32,X86_64] Disable use of MMCONFIG for PCI
+ nommconf [X86] Disable use of MMCONFIG for PCI
Configuration
nomsi [MSI] If the PCI_MSI kernel config parameter is
enabled, this kernel boot option can be used to
@@ -1838,6 +1886,12 @@ and is between 256 and 4096 characters. It is defined in the file
autoconfiguration.
Ranges are in pairs (memory base and size).
+ ports= [IP_VS_FTP] IPVS ftp helper module
+ Default is 21.
+ Up to 8 (IP_VS_APP_MAX_PORTS) ports
+ may be specified.
+ Format: <port>,<port>....
+
print-fatal-signals=
[KNL] debug: print fatal signals
print-fatal-signals=1: print segfault info to
@@ -2380,7 +2434,7 @@ and is between 256 and 4096 characters. It is defined in the file
reported either.
unknown_nmi_panic
- [X86-32,X86-64]
+ [X86]
Set unknown_nmi_panic=1 early on boot.
usbcore.autosuspend=
@@ -2447,12 +2501,12 @@ and is between 256 and 4096 characters. It is defined in the file
medium is write-protected).
Example: quirks=0419:aaf5:rl,0421:0433:rc
- vdso= [X86-32,SH,x86-64]
+ vdso= [X86,SH]
vdso=2: enable compat VDSO (default with COMPAT_VDSO)
vdso=1: enable VDSO (default)
vdso=0: disable VDSO mapping
- vdso32= [X86-32,X86-64]
+ vdso32= [X86]
vdso32=2: enable compat VDSO (default with COMPAT_VDSO)
vdso32=1: enable 32-bit VDSO (default)
vdso32=0: disable 32-bit VDSO mapping
diff --git a/Documentation/kmemleak.txt b/Documentation/kmemleak.txt
new file mode 100644
index 000000000000..0112da3b9ab8
--- /dev/null
+++ b/Documentation/kmemleak.txt
@@ -0,0 +1,142 @@
+Kernel Memory Leak Detector
+===========================
+
+Introduction
+------------
+
+Kmemleak provides a way of detecting possible kernel memory leaks in a
+way similar to a tracing garbage collector
+(http://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29#Tracing_garbage_collectors),
+with the difference that the orphan objects are not freed but only
+reported via /sys/kernel/debug/kmemleak. A similar method is used by the
+Valgrind tool (memcheck --leak-check) to detect the memory leaks in
+user-space applications.
+
+Usage
+-----
+
+CONFIG_DEBUG_KMEMLEAK in "Kernel hacking" has to be enabled. A kernel
+thread scans the memory every 10 minutes (by default) and prints any new
+unreferenced objects found. To trigger an intermediate scan and display
+all the possible memory leaks:
+
+ # mount -t debugfs nodev /sys/kernel/debug/
+ # cat /sys/kernel/debug/kmemleak
+
+Note that the orphan objects are listed in the order they were allocated
+and one object at the beginning of the list may cause other subsequent
+objects to be reported as orphan.
+
+Memory scanning parameters can be modified at run-time by writing to the
+/sys/kernel/debug/kmemleak file. The following parameters are supported:
+
+ off - disable kmemleak (irreversible)
+ stack=on - enable the task stacks scanning
+ stack=off - disable the tasks stacks scanning
+ scan=on - start the automatic memory scanning thread
+ scan=off - stop the automatic memory scanning thread
+ scan=<secs> - set the automatic memory scanning period in seconds (0
+ to disable it)
+
+Kmemleak can also be disabled at boot-time by passing "kmemleak=off" on
+the kernel command line.
+
+Basic Algorithm
+---------------
+
+The memory allocations via kmalloc, vmalloc, kmem_cache_alloc and
+friends are traced and the pointers, together with additional
+information like size and stack trace, are stored in a prio search tree.
+The corresponding freeing function calls are tracked and the pointers
+removed from the kmemleak data structures.
+
+An allocated block of memory is considered orphan if no pointer to its
+start address or to any location inside the block can be found by
+scanning the memory (including saved registers). This means that there
+might be no way for the kernel to pass the address of the allocated
+block to a freeing function and therefore the block is considered a
+memory leak.
+
+The scanning algorithm steps:
+
+ 1. mark all objects as white (remaining white objects will later be
+ considered orphan)
+ 2. scan the memory starting with the data section and stacks, checking
+ the values against the addresses stored in the prio search tree. If
+ a pointer to a white object is found, the object is added to the
+ gray list
+ 3. scan the gray objects for matching addresses (some white objects
+ can become gray and added at the end of the gray list) until the
+ gray set is finished
+ 4. the remaining white objects are considered orphan and reported via
+ /sys/kernel/debug/kmemleak
+
+Some allocated memory blocks have pointers stored in the kernel's
+internal data structures and they cannot be detected as orphans. To
+avoid this, kmemleak can also store the number of values pointing to an
+address inside the block address range that need to be found so that the
+block is not considered a leak. One example is __vmalloc().
+
+Kmemleak API
+------------
+
+See the include/linux/kmemleak.h header for the functions prototype.
+
+kmemleak_init - initialize kmemleak
+kmemleak_alloc - notify of a memory block allocation
+kmemleak_free - notify of a memory block freeing
+kmemleak_not_leak - mark an object as not a leak
+kmemleak_ignore - do not scan or report an object as leak
+kmemleak_scan_area - add scan areas inside a memory block
+kmemleak_no_scan - do not scan a memory block
+kmemleak_erase - erase an old value in a pointer variable
+kmemleak_alloc_recursive - as kmemleak_alloc but checks the recursiveness
+kmemleak_free_recursive - as kmemleak_free but checks the recursiveness
+
+Dealing with false positives/negatives
+--------------------------------------
+
+The false negatives are real memory leaks (orphan objects) but not
+reported by kmemleak because values found during the memory scanning
+point to such objects. To reduce the number of false negatives, kmemleak
+provides the kmemleak_ignore, kmemleak_scan_area, kmemleak_no_scan and
+kmemleak_erase functions (see above). The task stacks also increase the
+amount of false negatives and their scanning is not enabled by default.
+
+The false positives are objects wrongly reported as being memory leaks
+(orphan). For objects known not to be leaks, kmemleak provides the
+kmemleak_not_leak function. The kmemleak_ignore could also be used if
+the memory block is known not to contain other pointers and it will no
+longer be scanned.
+
+Some of the reported leaks are only transient, especially on SMP
+systems, because of pointers temporarily stored in CPU registers or
+stacks. Kmemleak defines MSECS_MIN_AGE (defaulting to 1000) representing
+the minimum age of an object to be reported as a memory leak.
+
+Limitations and Drawbacks
+-------------------------
+
+The main drawback is the reduced performance of memory allocation and
+freeing. To avoid other penalties, the memory scanning is only performed
+when the /sys/kernel/debug/kmemleak file is read. Anyway, this tool is
+intended for debugging purposes where the performance might not be the
+most important requirement.
+
+To keep the algorithm simple, kmemleak scans for values pointing to any
+address inside a block's address range. This may lead to an increased
+number of false negatives. However, it is likely that a real memory leak
+will eventually become visible.
+
+Another source of false negatives is the data stored in non-pointer
+values. In a future version, kmemleak could only scan the pointer
+members in the allocated structures. This feature would solve many of
+the false negative cases described above.
+
+The tool can report false positives. These are cases where an allocated
+block doesn't need to be freed (some cases in the init_call functions),
+the pointer is calculated by other methods than the usual container_of
+macro or the pointer is stored in a location not scanned by kmemleak.
+
+Page allocations and ioremap are not tracked. Only the ARM and x86
+architectures are currently supported.
diff --git a/Documentation/kobject.txt b/Documentation/kobject.txt
index b2e374586bd8..c79ab996dada 100644
--- a/Documentation/kobject.txt
+++ b/Documentation/kobject.txt
@@ -132,7 +132,7 @@ kobject_name():
const char *kobject_name(const struct kobject * kobj);
There is a helper function to both initialize and add the kobject to the
-kernel at the same time, called supprisingly enough kobject_init_and_add():
+kernel at the same time, called surprisingly enough kobject_init_and_add():
int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,
struct kobject *parent, const char *fmt, ...);
diff --git a/Documentation/laptops/acer-wmi.txt b/Documentation/laptops/acer-wmi.txt
index 5ee2a02b3b40..0768fcc3ba3e 100644
--- a/Documentation/laptops/acer-wmi.txt
+++ b/Documentation/laptops/acer-wmi.txt
@@ -40,7 +40,7 @@ NOTE: The Acer Aspire One is not supported hardware. It cannot work with
acer-wmi until Acer fix their ACPI-WMI implementation on them, so has been
blacklisted until that happens.
-Please see the website for the current list of known working hardare:
+Please see the website for the current list of known working hardware:
http://code.google.com/p/aceracpi/wiki/SupportedHardware
diff --git a/Documentation/laptops/sony-laptop.txt b/Documentation/laptops/sony-laptop.txt
index 8b2bc1572d98..23ce7d350d1a 100644
--- a/Documentation/laptops/sony-laptop.txt
+++ b/Documentation/laptops/sony-laptop.txt
@@ -22,7 +22,7 @@ If your laptop model supports it, you will find sysfs files in the
/sys/class/backlight/sony/
directory. You will be able to query and set the current screen
brightness:
- brightness get/set screen brightness (an iteger
+ brightness get/set screen brightness (an integer
between 0 and 7)
actual_brightness reading from this file will query the HW
to get real brightness value
diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
index 3d7650768bb5..78e354b42f67 100644
--- a/Documentation/laptops/thinkpad-acpi.txt
+++ b/Documentation/laptops/thinkpad-acpi.txt
@@ -1,7 +1,7 @@
ThinkPad ACPI Extras Driver
- Version 0.22
- November 23rd, 2008
+ Version 0.23
+ April 10th, 2009
Borislav Deianov <borislav@users.sf.net>
Henrique de Moraes Holschuh <hmh@hmh.eng.br>
@@ -506,7 +506,7 @@ generate input device EV_KEY events.
In addition to the EV_KEY events, thinkpad-acpi may also issue EV_SW
events for switches:
-SW_RFKILL_ALL T60 and later hardare rfkill rocker switch
+SW_RFKILL_ALL T60 and later hardware rfkill rocker switch
SW_TABLET_MODE Tablet ThinkPads HKEY events 0x5009 and 0x500A
Non hot-key ACPI HKEY event map:
diff --git a/Documentation/lguest/.gitignore b/Documentation/lguest/.gitignore
new file mode 100644
index 000000000000..115587fd5f65
--- /dev/null
+++ b/Documentation/lguest/.gitignore
@@ -0,0 +1 @@
+lguest
diff --git a/Documentation/lguest/lguest.txt b/Documentation/lguest/lguest.txt
index 29510dc51510..28c747362f95 100644
--- a/Documentation/lguest/lguest.txt
+++ b/Documentation/lguest/lguest.txt
@@ -3,11 +3,11 @@
/, /` - or, A Young Coder's Illustrated Hypervisor
\\"--\\ http://lguest.ozlabs.org
-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 (see drivers/lguest/README).
+Lguest is designed to be a minimal 32-bit x86 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 (see drivers/lguest/README).
Features:
@@ -37,6 +37,7 @@ Running Lguest:
"Paravirtualized guest support" = Y
"Lguest guest support" = Y
"High Memory Support" = off/4GB
+ "PAE (Physical Address Extension) Support" = N
"Alignment value to which kernel should be aligned" = 0x100000
(CONFIG_PARAVIRT=y, CONFIG_LGUEST_GUEST=y, CONFIG_HIGHMEM64G=n and
CONFIG_PHYSICAL_ALIGN=0x100000)
diff --git a/Documentation/local_ops.txt b/Documentation/local_ops.txt
index 23045b8b50f0..300da4bdfdbd 100644
--- a/Documentation/local_ops.txt
+++ b/Documentation/local_ops.txt
@@ -34,7 +34,7 @@ out of order wrt other memory writes by the owner CPU.
It can be done by slightly modifying the standard atomic operations : only
their UP variant must be kept. It typically means removing LOCK prefix (on
-i386 and x86_64) and any SMP sychronization barrier. If the architecture does
+i386 and x86_64) and any SMP synchronization barrier. If the architecture does
not have a different behavior between SMP and UP, including asm-generic/local.h
in your architecture's local.h is sufficient.
diff --git a/Documentation/lockdep-design.txt b/Documentation/lockdep-design.txt
index 938ea22f2cc0..e20d913d5914 100644
--- a/Documentation/lockdep-design.txt
+++ b/Documentation/lockdep-design.txt
@@ -54,9 +54,9 @@ locking error messages, inside curlies. A contrived example:
The bit position indicates STATE, STATE-read, for each of the states listed
above, and the character displayed in each indicates:
- '.' acquired while irqs disabled
- '+' acquired in irq context
- '-' acquired with irqs enabled
+ '.' acquired while irqs disabled and not in irq context
+ '-' acquired in irq context
+ '+' acquired with irqs enabled
'?' acquired in irq context with irqs enabled.
Unused mutexes cannot be part of the cause of an error.
diff --git a/Documentation/logo.gif b/Documentation/logo.gif
new file mode 100644
index 000000000000..2eae75fecfb9
--- /dev/null
+++ b/Documentation/logo.gif
Binary files differ
diff --git a/Documentation/logo.svg b/Documentation/logo.svg
deleted file mode 100644
index cb9e4851d8c3..000000000000
--- a/Documentation/logo.svg
+++ /dev/null
@@ -1,2911 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="1771.6534"
- height="1417.3228"
- id="svg2"
- sodipodi:version="0.32"
- inkscape:version="0.46"
- sodipodi:docname="tuz.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape"
- version="1.0"
- style="display:inline;enable-background:new"
- inkscape:export-filename="/home/cheeseness/Documents/LCA09/mascot/tuz_final.png"
- inkscape:export-xdpi="100.03588"
- inkscape:export-ydpi="100.03588">
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- gridtolerance="10000"
- guidetolerance="10"
- objecttolerance="10"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="0.25"
- inkscape:cx="-174.7931"
- inkscape:cy="784.26325"
- inkscape:document-units="px"
- inkscape:current-layer="svg2"
- showgrid="false"
- inkscape:window-width="1280"
- inkscape:window-height="823"
- inkscape:window-x="-4"
- inkscape:window-y="25"
- showguides="true"
- inkscape:guide-bbox="true"
- units="mm" />
- <defs
- id="defs4">
- <filter
- inkscape:collect="always"
- x="-0.084654994"
- width="1.16931"
- y="-0.36592469"
- height="1.7318494"
- id="filter11361">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="4.5740586"
- id="feGaussianBlur11363" />
- </filter>
- <inkscape:perspective
- sodipodi:type="inkscape:persp3d"
- inkscape:vp_x="0 : 564.0976 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_z="1445.8591 : 564.0976 : 1"
- inkscape:persp3d-origin="722.92957 : 376.06506 : 1"
- id="perspective8145" />
- <linearGradient
- id="linearGradient7622">
- <stop
- style="stop-color:#ffffff;stop-opacity:1;"
- offset="0"
- id="stop7624" />
- <stop
- style="stop-color:#ffffff;stop-opacity:0;"
- offset="1"
- id="stop7626" />
- </linearGradient>
- <linearGradient
- id="linearGradient4113">
- <stop
- style="stop-color:#000000;stop-opacity:0;"
- offset="0"
- id="stop4115" />
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="1"
- id="stop4117" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient3660">
- <stop
- style="stop-color:#ffffff;stop-opacity:1;"
- offset="0"
- id="stop3662" />
- <stop
- style="stop-color:#ffffff;stop-opacity:0;"
- offset="1"
- id="stop3664" />
- </linearGradient>
- <linearGradient
- id="linearGradient3627">
- <stop
- style="stop-color:#ffffff;stop-opacity:1;"
- offset="0"
- id="stop3629" />
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="1"
- id="stop3631" />
- </linearGradient>
- <linearGradient
- id="linearGradient2843">
- <stop
- id="stop2845"
- offset="0"
- style="stop-color:#000000;stop-opacity:1;" />
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0.02188784"
- id="stop2847" />
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0.75866222"
- id="stop2849" />
- <stop
- id="stop2851"
- offset="0.88508981"
- style="stop-color:#232323;stop-opacity:1;" />
- <stop
- id="stop2853"
- offset="1"
- style="stop-color:#595959;stop-opacity:1;" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient8964">
- <stop
- style="stop-color:#1a1a1a;stop-opacity:1;"
- offset="0"
- id="stop8966" />
- <stop
- style="stop-color:#1a1a1a;stop-opacity:0;"
- offset="1"
- id="stop8968" />
- </linearGradient>
- <linearGradient
- id="linearGradient8952">
- <stop
- style="stop-color:#0a0c0c;stop-opacity:1;"
- offset="0"
- id="stop8954" />
- <stop
- style="stop-color:#1f2727;stop-opacity:0;"
- offset="1"
- id="stop8956" />
- </linearGradient>
- <linearGradient
- id="linearGradient8430">
- <stop
- style="stop-color:#1e2323;stop-opacity:1;"
- offset="0"
- id="stop8432" />
- <stop
- id="stop8438"
- offset="0.55992389"
- style="stop-color:#181d1d;stop-opacity:1;" />
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="1"
- id="stop8434" />
- </linearGradient>
- <linearGradient
- id="linearGradient8398">
- <stop
- style="stop-color:#283131;stop-opacity:0;"
- offset="0"
- id="stop8400" />
- <stop
- id="stop8402"
- offset="0.5125587"
- style="stop-color:#1e2424;stop-opacity:0;" />
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="1"
- id="stop8404" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient4870">
- <stop
- style="stop-color:#c7bd80;stop-opacity:1;"
- offset="0"
- id="stop4872" />
- <stop
- style="stop-color:#c7bd80;stop-opacity:0;"
- offset="1"
- id="stop4874" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient4862">
- <stop
- style="stop-color:#e2e2e2;stop-opacity:1;"
- offset="0"
- id="stop4864" />
- <stop
- style="stop-color:#e2e2e2;stop-opacity:0;"
- offset="1"
- id="stop4866" />
- </linearGradient>
- <linearGradient
- id="linearGradient4478">
- <stop
- style="stop-color:#f9eed3;stop-opacity:1;"
- offset="0"
- id="stop4480" />
- <stop
- style="stop-color:#000000;stop-opacity:0;"
- offset="1"
- id="stop4482" />
- </linearGradient>
- <linearGradient
- id="linearGradient4106">
- <stop
- style="stop-color:#d9e002;stop-opacity:1;"
- offset="0"
- id="stop4108" />
- <stop
- id="stop4114"
- offset="0.5"
- style="stop-color:#a9ae01;stop-opacity:1;" />
- <stop
- style="stop-color:#717501;stop-opacity:1;"
- offset="1"
- id="stop4110" />
- </linearGradient>
- <linearGradient
- id="linearGradient4084">
- <stop
- style="stop-color:#7d7d00;stop-opacity:1;"
- offset="0"
- id="stop4086" />
- <stop
- id="stop4088"
- offset="0.3636601"
- style="stop-color:#c6c700;stop-opacity:1;" />
- <stop
- style="stop-color:#f6f800;stop-opacity:1;"
- offset="1"
- id="stop4090" />
- </linearGradient>
- <linearGradient
- id="linearGradient4041">
- <stop
- id="stop4043"
- offset="0"
- style="stop-color:#ffff00;stop-opacity:1;" />
- <stop
- id="stop4045"
- offset="1"
- style="stop-color:#ffff00;stop-opacity:0;" />
- </linearGradient>
- <linearGradient
- id="linearGradient4025">
- <stop
- style="stop-color:#ffffff;stop-opacity:1;"
- offset="0"
- id="stop4027" />
- <stop
- style="stop-color:#ffffff;stop-opacity:0;"
- offset="1"
- id="stop4031" />
- </linearGradient>
- <linearGradient
- id="linearGradient4013">
- <stop
- style="stop-color:#ffff00;stop-opacity:1;"
- offset="0"
- id="stop4015" />
- <stop
- style="stop-color:#b2b200;stop-opacity:1;"
- offset="1"
- id="stop4017" />
- </linearGradient>
- <linearGradient
- id="linearGradient3985">
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0"
- id="stop3987" />
- <stop
- style="stop-color:#1d1d1d;stop-opacity:1;"
- offset="1"
- id="stop3989" />
- </linearGradient>
- <linearGradient
- id="linearGradient3961">
- <stop
- style="stop-color:#283131;stop-opacity:0;"
- offset="0"
- id="stop3963" />
- <stop
- id="stop3965"
- offset="0.5"
- style="stop-color:#1e2424;stop-opacity:1;" />
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="1"
- id="stop3967" />
- </linearGradient>
- <linearGradient
- id="linearGradient3951">
- <stop
- id="stop3953"
- offset="0"
- style="stop-color:#344040;stop-opacity:1;" />
- <stop
- style="stop-color:#222929;stop-opacity:1;"
- offset="0.5"
- id="stop3955" />
- <stop
- id="stop3957"
- offset="1"
- style="stop-color:#000000;stop-opacity:1;" />
- </linearGradient>
- <linearGradient
- id="linearGradient3909">
- <stop
- style="stop-color:#283131;stop-opacity:1;"
- offset="0"
- id="stop3911" />
- <stop
- id="stop3917"
- offset="0.5"
- style="stop-color:#1e2424;stop-opacity:1;" />
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="1"
- id="stop3913" />
- </linearGradient>
- <linearGradient
- id="linearGradient3537">
- <stop
- style="stop-color:#ada469;stop-opacity:1;"
- offset="0"
- id="stop3539" />
- <stop
- id="stop3545"
- offset="0.81132078"
- style="stop-color:#ada469;stop-opacity:1;" />
- <stop
- style="stop-color:#ffffff;stop-opacity:1;"
- offset="1"
- id="stop3541" />
- </linearGradient>
- <linearGradient
- id="linearGradient3317">
- <stop
- style="stop-color:#cfc690;stop-opacity:1"
- offset="0"
- id="stop3319" />
- <stop
- id="stop3321"
- offset="0.21161865"
- style="stop-color:#afa775;stop-opacity:1;" />
- <stop
- id="stop3323"
- offset="0.53408515"
- style="stop-color:#615c3a;stop-opacity:1;" />
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0.76504093"
- id="stop3325" />
- <stop
- id="stop3327"
- offset="1"
- style="stop-color:#403518;stop-opacity:1;" />
- </linearGradient>
- <linearGradient
- id="linearGradient3239">
- <stop
- id="stop3251"
- offset="0"
- style="stop-color:#cfc690;stop-opacity:1;" />
- <stop
- style="stop-color:#afa775;stop-opacity:1;"
- offset="0.21161865"
- id="stop3267" />
- <stop
- style="stop-color:#615c3a;stop-opacity:1;"
- offset="0.53408515"
- id="stop3261" />
- <stop
- id="stop3265"
- offset="0.76504093"
- style="stop-color:#000000;stop-opacity:1;" />
- <stop
- style="stop-color:#403518;stop-opacity:1;"
- offset="1"
- id="stop3243" />
- </linearGradient>
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3239"
- id="radialGradient3281"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1.5480423,1.7414304,-1.9683515,1.7497638,-1130.5586,-1872.5121)"
- spreadMethod="pad"
- cx="806.52582"
- cy="212.68117"
- fx="806.52582"
- fy="212.68117"
- r="48.363216" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3317"
- id="radialGradient3315"
- cx="543.6698"
- cy="147.3131"
- fx="543.6698"
- fy="147.3131"
- r="47.863216"
- gradientTransform="matrix(2.1382256,0,0,2.3382884,-77.03847,-101.68704)"
- gradientUnits="userSpaceOnUse" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3537"
- id="radialGradient3543"
- cx="385"
- cy="237.00504"
- fx="385"
- fy="237.00504"
- r="86.928574"
- gradientTransform="matrix(1,0,0,0.8562038,0,34.080427)"
- gradientUnits="userSpaceOnUse" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3909"
- id="radialGradient3915"
- cx="418.30365"
- cy="342.47794"
- fx="418.30365"
- fy="342.47794"
- r="131.4509"
- gradientTransform="matrix(1.3957347,0.6211056,-0.4244067,0.9537174,-15.061913,-227.96711)"
- gradientUnits="userSpaceOnUse" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3951"
- id="radialGradient3933"
- cx="397.16388"
- cy="336.95245"
- fx="397.16388"
- fy="336.95245"
- r="36.75"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1.9449972,2.4894837e-7,-2.4894833e-7,1.9449969,-375.31868,-318.41912)" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3961"
- id="linearGradient3959"
- x1="398.21429"
- y1="343.52289"
- x2="379.28571"
- y2="265.30862"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(450.03125,73.843964)" />
- <filter
- inkscape:collect="always"
- id="filter3981"
- x="-0.30000001"
- width="1.6"
- y="-0.30000001"
- height="1.6">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="2"
- id="feGaussianBlur3983" />
- </filter>
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3985"
- id="radialGradient3991"
- cx="402.48898"
- cy="317.23578"
- fx="402.48898"
- fy="317.23578"
- r="23.714285"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(4.3776616,0,0,4.3776616,-1358.3025,-1070.7357)" />
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath3999">
- <path
- style="opacity:1;fill:#f5ff04;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline"
- d="M 179.64286,267.36218 C 157.23242,307.0651 119.02676,383.14247 110.35715,417.00504 C 101.70994,450.78014 101.58516,483.42158 110,503.43362 C 118.3602,523.31575 136.16398,539.06642 150.71428,544.86218 C 150.1179,530.48631 165.08723,501.57635 223.57143,472.36218 C 282.1977,443.07704 301.95306,445.23132 327.14285,425.21932 C 352.77291,404.85756 339.75316,358.17469 330.35714,331.29075 C 320.9229,304.29747 295.38973,272.16627 263.92857,261.6479 C 232.8953,251.27258 198.91081,256.79953 179.64286,267.36218 z"
- id="path4001"
- sodipodi:nodetypes="czzczzzzc" />
- </clipPath>
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4013"
- id="radialGradient4056"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1.1323239,0.7659488,-1.4550286,2.1510098,588.75376,-711.79716)"
- cx="228.81355"
- cy="440.26971"
- fx="228.81355"
- fy="440.26971"
- r="119.17509" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4041"
- id="radialGradient4060"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(5.911206e-2,2.6869855,-0.7234268,1.5914947e-2,408.72779,-424.56452)"
- cx="275.4422"
- cy="335.34866"
- fx="275.4422"
- fy="335.34866"
- r="36.75" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4025"
- id="radialGradient4062"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(5.911206e-2,2.6869855,-0.7234268,1.5914947e-2,408.72779,-424.56452)"
- cx="275.4422"
- cy="335.34866"
- fx="275.4422"
- fy="335.34866"
- r="36.75" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4084"
- id="linearGradient4082"
- gradientUnits="userSpaceOnUse"
- x1="182.35046"
- y1="256.11136"
- x2="145.53348"
- y2="542.20502" />
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4100">
- <path
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.9000755px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M 265.93541,126.68393 L 247.1682,295.54701 L 421.27363,222.42633 L 483.22803,311.08516 L 541.11243,279.09486 L 503.57801,99.035183 L 265.93541,126.68393 z"
- id="path4102"
- sodipodi:nodetypes="ccccccc" />
- </clipPath>
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4106"
- id="radialGradient4112"
- cx="250.22678"
- cy="475.09763"
- fx="250.22678"
- fy="475.09763"
- r="95.98877"
- gradientTransform="matrix(1.2259004,-0.7077739,0.1413989,0.2449102,322.22326,608.91815)"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4478"
- id="linearGradient4484"
- x1="412.08926"
- y1="404.91574"
- x2="417.375"
- y2="401.82648"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4478"
- id="linearGradient4486"
- x1="411.91071"
- y1="404.91577"
- x2="417.375"
- y2="401.82648"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4478"
- id="linearGradient4488"
- x1="411.91071"
- y1="405.54077"
- x2="417.375"
- y2="401.82648"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4478"
- id="linearGradient4490"
- x1="412.08926"
- y1="405.54077"
- x2="417.375"
- y2="401.82648"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4478"
- id="linearGradient4492"
- x1="411.73212"
- y1="405.54077"
- x2="417.375"
- y2="401.82648"
- gradientUnits="userSpaceOnUse" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4862"
- id="radialGradient4868"
- cx="429.56738"
- cy="377.42877"
- fx="429.56738"
- fy="377.42877"
- r="72.079735"
- gradientTransform="matrix(1,0,0,0.618034,0,144.16496)"
- gradientUnits="userSpaceOnUse" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4870"
- id="radialGradient4876"
- cx="437.6991"
- cy="391.21735"
- fx="437.6991"
- fy="391.21735"
- r="36.611931"
- gradientTransform="matrix(1,0,0,0.618034,0,149.43174)"
- gradientUnits="userSpaceOnUse" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4013"
- id="radialGradient3585"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1.1323239,0.7659488,-1.4550286,2.1510098,588.75376,-711.79716)"
- cx="228.81355"
- cy="440.26971"
- fx="228.81355"
- fy="440.26971"
- r="119.17509" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4084"
- id="linearGradient3587"
- gradientUnits="userSpaceOnUse"
- x1="182.35046"
- y1="256.11136"
- x2="145.53348"
- y2="542.20502" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3317"
- id="radialGradient8410"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1.0036478,-1.0345492e-7,1.7124628e-7,1.6613125,-753.99632,-302.76972)"
- cx="317.78754"
- cy="129.65378"
- fx="317.78754"
- fy="129.65378"
- r="47.863216" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient8398"
- id="radialGradient8412"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(2.0747661,-0.1577957,0.2382425,3.1325183,-1144.2358,-272.29325)"
- cx="325.30847"
- cy="80.909554"
- fx="325.30847"
- fy="80.909554"
- r="26.937988" />
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath8514">
- <path
- style="opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 352.24553,211.99185 C 348.4411,186.72762 335.43581,161.35383 335.08873,136.46662 C 334.90247,123.1111 338.36158,109.89571 348.84426,96.912574 C 385.19128,31.616739 465.78517,12.217889 534.77892,5.447147 C 621.70131,-5.569654 719.69159,23.387219 768.15026,100.84843 C 822.27428,176.58173 824.82502,273.38755 848.7623,360.37638 C 878.20009,487.50398 903.54144,616.59052 909.15454,747.22673 C 906.09106,825.40858 900.7282,912.41088 848.65133,975.36086 C 800.62479,1025.7183 725.86486,1025.4139 661.58145,1034.3632 C 571.02606,1039.0182 477.22992,1018.2174 399.79755,970.16496 C 335.02191,932.22495 304.06736,856.68633 302.51815,784.14538 C 294.12898,704.27022 328.90967,630.33687 354.13855,556.98577 C 361.60916,474.2247 363.55141,390.73802 363.79189,307.60093 C 362.95507,275.40549 356.70236,243.7836 352.24553,211.99185 z"
- id="path8516"
- sodipodi:nodetypes="cscccccccccccc" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath8604">
- <path
- style="opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 352.24553,211.99185 C 348.4411,186.72762 335.43581,161.35383 335.08873,136.46662 C 334.90247,123.1111 338.36158,109.89571 348.84426,96.912574 C 385.19128,31.616739 465.78517,12.217889 534.77892,5.447147 C 621.70131,-5.569654 719.69159,23.387219 768.15026,100.84843 C 822.27428,176.58173 824.82502,273.38755 848.7623,360.37638 C 878.20009,487.50398 903.54144,616.59052 909.15454,747.22673 C 906.09106,825.40858 900.7282,912.41088 848.65133,975.36086 C 800.62479,1025.7183 725.86486,1025.4139 661.58145,1034.3632 C 571.02606,1039.0182 477.22992,1018.2174 399.79755,970.16496 C 335.02191,932.22495 304.06736,856.68633 302.51815,784.14538 C 294.12898,704.27022 328.90967,630.33687 354.13855,556.98577 C 361.60916,474.2247 363.55141,390.73802 363.79189,307.60093 C 362.95507,275.40549 356.70236,243.7836 352.24553,211.99185 z"
- id="path8606"
- sodipodi:nodetypes="cscccccccccccc" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath8610">
- <path
- style="opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 352.24553,211.99185 C 348.4411,186.72762 335.43581,161.35383 335.08873,136.46662 C 334.90247,123.1111 338.36158,109.89571 348.84426,96.912574 C 385.19128,31.616739 465.78517,12.217889 534.77892,5.447147 C 621.70131,-5.569654 719.69159,23.387219 768.15026,100.84843 C 822.27428,176.58173 824.82502,273.38755 848.7623,360.37638 C 878.20009,487.50398 903.54144,616.59052 909.15454,747.22673 C 906.09106,825.40858 900.7282,912.41088 848.65133,975.36086 C 800.62479,1025.7183 725.86486,1025.4139 661.58145,1034.3632 C 571.02606,1039.0182 477.22992,1018.2174 399.79755,970.16496 C 335.02191,932.22495 304.06736,856.68633 302.51815,784.14538 C 294.12898,704.27022 328.90967,630.33687 354.13855,556.98577 C 361.60916,474.2247 363.55141,390.73802 363.79189,307.60093 C 362.95507,275.40549 356.70236,243.7836 352.24553,211.99185 z"
- id="path8612"
- sodipodi:nodetypes="cscccccccccccc" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath8616">
- <path
- style="opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 352.24553,211.99185 C 348.4411,186.72762 335.43581,161.35383 335.08873,136.46662 C 334.90247,123.1111 338.36158,109.89571 348.84426,96.912574 C 385.19128,31.616739 465.78517,12.217889 534.77892,5.447147 C 621.70131,-5.569654 719.69159,23.387219 768.15026,100.84843 C 822.27428,176.58173 824.82502,273.38755 848.7623,360.37638 C 878.20009,487.50398 903.54144,616.59052 909.15454,747.22673 C 906.09106,825.40858 900.7282,912.41088 848.65133,975.36086 C 800.62479,1025.7183 725.86486,1025.4139 661.58145,1034.3632 C 571.02606,1039.0182 477.22992,1018.2174 399.79755,970.16496 C 335.02191,932.22495 304.06736,856.68633 302.51815,784.14538 C 294.12898,704.27022 328.90967,630.33687 354.13855,556.98577 C 361.60916,474.2247 363.55141,390.73802 363.79189,307.60093 C 362.95507,275.40549 356.70236,243.7836 352.24553,211.99185 z"
- id="path8618"
- sodipodi:nodetypes="cscccccccccccc" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath8622">
- <path
- style="opacity:1;fill:#202020;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- d="M 821.64329,477.88997 C 821.64329,477.88997 844.26276,471.38316 857.38604,472.01724 C 870.50932,472.65133 888.02762,473.95586 901.09489,484.20343 C 914.16216,494.45099 926.16263,511.3435 935.20728,542.57308 C 944.25193,573.80266 936.9056,641.82509 929.03125,685.92043 C 921.1569,730.01577 900.76615,792.03341 884.03125,825.92043 C 867.29635,859.80745 834.23354,903.41563 823.46182,915.79659 C 812.0976,928.85856 767.25593,952.22276 744.03125,958.06326 C 749.33455,947.45666 792.93101,907.47442 779.03125,897.349 C 765.01228,887.13674 733.27116,943.33136 694.7381,926.38217 C 716.12041,913.25005 736.5175,875.19611 728.77871,859.78772 C 720.93846,844.17733 698.07378,908.54529 635.24317,896.8006 C 665.29521,869.27394 690.65023,825.89659 676.50587,813.8209 C 662.09071,801.51403 616.04412,868.11405 616.04412,868.11405 C 616.04412,868.11405 613.22222,826.41287 629.81732,799.50673 C 646.45667,772.52886 709.47029,717.89146 729.37045,687.80331 C 749.2706,657.71517 762.98301,621.79429 771.50587,595.28537 C 780.02873,568.77645 787.30681,518.18583 787.30681,518.18583"
- id="path8624"
- sodipodi:nodetypes="czzzzzzczczczczzzc" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath8642">
- <path
- style="opacity:1;fill:#0f0f0f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 366.88839,504.13471 C 366.88839,504.13471 337.33433,544.70776 319.03125,578.42042 C 300.72816,612.13309 260.41016,704.77736 248.67411,749.49185 C 236.91471,794.29529 186.17411,873.06329 186.17411,873.06329 L 262.24554,891.27757 C 262.24554,891.27757 274.05266,878.45422 293.31696,845.20614 C 312.58126,811.95806 353.67411,706.63471 353.67411,706.63471 L 366.88839,504.13471 z"
- id="path8644"
- sodipodi:nodetypes="czzcczcc" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath8658">
- <path
- style="opacity:1;fill:#0b0b0b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 569.03125,1018.7776 C 564.74554,1019.4919 541.4031,1022.3957 511.17411,1028.7776 C 480.94512,1035.1595 411.39918,1054.7395 368.31696,1064.4919 C 325.23474,1074.2443 251.05253,1099.3079 211.40434,1091.7573 C 171.75616,1084.2067 121.88839,1027.349 121.88839,1027.349 L 126.17411,933.06329 C 126.17411,933.06329 212.05962,916.86235 238.31696,899.49186 C 264.57431,882.12137 283.89934,849.82588 297.60268,828.06329 C 311.30602,806.3007 330.45982,756.63471 330.45982,756.63471 L 569.03125,1018.7776 z"
- id="path8660"
- sodipodi:nodetypes="czzzcczzcc" />
- </clipPath>
- <filter
- inkscape:collect="always"
- id="filter8802"
- x="-0.35311759"
- width="1.7062352"
- y="-0.1817714"
- height="1.3635428">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="48.038491"
- id="feGaussianBlur8804" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter8806"
- x="-0.61142862"
- width="2.2228572"
- y="-0.14930232"
- height="1.2986046">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="37.830213"
- id="feGaussianBlur8808" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter8810"
- x="-0.23519406"
- width="1.4703881"
- y="-0.24500646"
- height="1.4900129">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="58.328041"
- id="feGaussianBlur8812" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter8814"
- x="-0.20466694"
- width="1.4093339"
- y="-0.29007819"
- height="1.5801564">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="22.300169"
- id="feGaussianBlur8816" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter8818"
- x="-0.34381232"
- width="1.6876246"
- y="-0.18433961"
- height="1.3686792">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="34.542167"
- id="feGaussianBlur8820" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter8822"
- x="-0.2742857"
- width="1.5485713"
- y="-0.21333334"
- height="1.4266667">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="11.313708"
- id="feGaussianBlur8824" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter8826"
- x="-0.25894088"
- width="1.5178818"
- y="-0.2236412"
- height="1.4472824">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="19.631544"
- id="feGaussianBlur8828" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter8856"
- x="-0.3253231"
- width="1.6506462"
- y="-0.19013336"
- height="1.3802667">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="28.712591"
- id="feGaussianBlur8858" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter8860"
- x="-0.38093024"
- width="1.7618605"
- y="-0.17518716"
- height="1.3503743">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="19.304015"
- id="feGaussianBlur8862" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter8888"
- x="-0.2112188"
- width="1.4224375"
- y="-0.16808605"
- height="1.3361721">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="8.3693583"
- id="feGaussianBlur8890" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter8892"
- x="-0.18692794"
- width="1.3738559"
- y="-0.23646873"
- height="1.4729375">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="31.21228"
- id="feGaussianBlur8894" />
- </filter>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath8906">
- <path
- style="opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 352.24553,211.99185 C 348.4411,186.72762 335.43581,161.35383 335.08873,136.46662 C 334.90247,123.1111 338.36158,109.89571 348.84426,96.912574 C 385.19128,31.616739 465.78517,12.217889 534.77892,5.447147 C 621.70131,-5.569654 719.69159,23.387219 768.15026,100.84843 C 822.27428,176.58173 824.82502,273.38755 848.7623,360.37638 C 878.20009,487.50398 903.54144,616.59052 909.15454,747.22673 C 906.09106,825.40858 900.7282,912.41088 848.65133,975.36086 C 800.62479,1025.7183 725.86486,1025.4139 661.58145,1034.3632 C 571.02606,1039.0182 477.22992,1018.2174 399.79755,970.16496 C 335.02191,932.22495 304.06736,856.68633 302.51815,784.14538 C 294.12898,704.27022 328.90967,630.33687 354.13855,556.98577 C 361.60916,474.2247 363.55141,390.73802 363.79189,307.60093 C 362.95507,275.40549 356.70236,243.7836 352.24553,211.99185 z"
- id="path8908"
- sodipodi:nodetypes="cscccccccccccc" />
- </clipPath>
- <filter
- inkscape:collect="always"
- id="filter8940"
- x="-0.25152978"
- width="1.5030596"
- y="-0.053035267"
- height="1.1060705">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="13.024603"
- id="feGaussianBlur8942" />
- </filter>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient8952"
- id="linearGradient8958"
- x1="609.31244"
- y1="239.46866"
- x2="560.83142"
- y2="262.86206"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(450.03125,73.843964)" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient8964"
- id="linearGradient8970"
- x1="603.84064"
- y1="627.85303"
- x2="616.24396"
- y2="585.42664"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(450.03125,73.843964)" />
- <filter
- inkscape:collect="always"
- id="filter9020"
- x="-0.32861114"
- width="1.6572223"
- y="-0.182"
- height="1.364">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="20.912684"
- id="feGaussianBlur9022" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter9024"
- x="-0.55453134"
- width="2.1090627"
- y="-0.51434779"
- height="2.0286956">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="20.912684"
- id="feGaussianBlur9026" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter9044"
- x="-0.32631579"
- width="1.6526316"
- y="-0.84545463"
- height="2.6909094">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="21.92031"
- id="feGaussianBlur9046" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter9048"
- x="-0.40879121"
- width="1.8175824"
- y="-0.71538466"
- height="2.4307692">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="21.92031"
- id="feGaussianBlur9050" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter3587"
- x="-0.1">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="8.881432"
- id="feGaussianBlur3589" />
- </filter>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath3602">
- <path
- sodipodi:nodetypes="czzzzzzczczczczzzc"
- id="path3604"
- d="M 647.61204,540.04601 C 647.61204,540.04601 670.23151,533.5392 683.35479,534.17328 C 696.47807,534.80737 713.99637,536.1119 727.06364,546.35947 C 740.13091,556.60703 752.13138,573.49954 761.17603,604.72912 C 770.22068,635.9587 762.87435,703.98113 755,748.07647 C 747.12565,792.17181 726.7349,854.18945 710,888.07647 C 693.2651,921.96349 660.20229,965.57167 649.43057,977.95263 C 638.06635,991.0146 593.22468,1014.3788 570,1020.2193 C 575.3033,1009.6127 618.89976,969.63046 605,959.50504 C 590.98103,949.29278 559.23991,1005.4874 520.70685,988.53821 C 542.08916,975.40609 562.48625,937.35215 554.74746,921.94376 C 546.90721,906.33337 524.04253,970.70133 461.21192,958.95664 C 491.26396,931.42998 516.61898,888.05263 502.47462,875.97694 C 488.05946,863.67007 442.01287,930.27009 442.01287,930.27009 C 442.01287,930.27009 439.19097,888.56891 455.78607,861.66277 C 472.42542,834.6849 535.43904,780.0475 555.3392,749.95935 C 575.23935,719.87121 588.95176,683.95033 597.47462,657.44141 C 605.99748,630.93249 613.27556,580.34187 613.27556,580.34187"
- style="opacity:1;fill:#202020;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- </clipPath>
- <filter
- inkscape:collect="always"
- id="filter4120"
- x="-0.2770822"
- width="1.5541644"
- y="-0.32482043"
- height="1.6496409">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="19.956289"
- id="feGaussianBlur4122" />
- </filter>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath3631">
- <path
- style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- d="M 760.16396,935.83377 C 766.95806,954.73656 770.65765,969.13346 772.05426,987.04566 C 773.45088,1004.958 768.27158,1038.8465 769.1538,1057.7018 C 770.03555,1076.547 777.28749,1097.8008 796.49843,1106.6707 C 815.9173,1115.6365 845.81767,1116.882 870.61827,1103.5251 C 895.41887,1090.1681 928.01929,1033.1996 941.59253,1006.2164 C 955.21638,979.13246 980.3536,891.71903 986.25333,856.44781 C 992.15306,821.1766 988.80387,815.14704 981.63585,807.39232 C 984.27615,779.55217 980.13613,752.45689 994.74554,720.20614 C 964.49653,732.03184 957.36325,760.36684 946.42665,785.71122 C 938.42574,734.77829 946.63581,714.43803 949.74554,684.49186 C 920.68078,699.26977 906.88403,731.60588 904.74554,777.349 C 893.82159,776.0448 883.3541,772.91477 871.17411,776.63471 C 870.91007,730.61137 869.71055,699.7453 880.08474,662.42822 C 826.82927,683.45508 817.13746,769.02232 824.03125,775.20614 C 813.14843,775.74114 802.66017,773.90884 791.17411,778.06329 C 791.81303,735.49194 790.91365,693.15468 761.17411,655.20614 C 761.17411,655.20614 730.21605,736.12848 729.74554,758.77757 C 729.27503,781.42666 739.19713,798.94345 739.19713,798.94345 C 739.19713,798.94345 730.62906,835.68396 732.89854,857.17568 C 735.19439,878.91714 753.34144,916.85185 760.16396,935.83377 z"
- id="path3633"
- sodipodi:nodetypes="czzzzzzcccccccccczczz" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath3665">
- <path
- sodipodi:nodetypes="czzcczcc"
- id="path3667"
- d="M 366.88839,504.13471 C 366.88839,504.13471 337.33433,544.70776 319.03125,578.42042 C 300.72816,612.13309 260.41016,704.77736 248.67411,749.49185 C 236.91471,794.29529 186.17411,873.06329 186.17411,873.06329 L 262.24554,891.27757 C 262.24554,891.27757 274.05266,878.45422 293.31696,845.20614 C 312.58126,811.95806 353.67411,706.63471 353.67411,706.63471 L 366.88839,504.13471 z"
- style="opacity:1;fill:#0f0f0f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath3677">
- <path
- style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- d="M 586.13271,997.98981 C 592.92681,1016.8926 596.6264,1031.2895 598.02301,1049.2017 C 599.41963,1067.114 594.24033,1101.0025 595.12255,1119.8578 C 596.0043,1138.703 603.25624,1159.9568 622.46718,1168.8267 C 641.88605,1177.7925 671.78642,1179.038 696.58702,1165.6811 C 721.38762,1152.3241 753.98804,1095.3556 767.56128,1068.3724 C 781.18513,1041.2885 806.32235,953.87507 812.22208,918.60385 C 818.12181,883.33264 814.77262,877.30308 807.6046,869.54836 C 810.2449,841.70821 806.10488,814.61293 820.71429,782.36218 C 790.46528,794.18788 783.332,822.52288 772.3954,847.86726 C 764.39449,796.93433 772.60456,776.59407 775.71429,746.6479 C 746.64953,761.42581 732.85278,793.76192 730.71429,839.50504 C 719.79034,838.20084 709.32285,835.07081 697.14286,838.79075 C 696.87882,792.76741 695.6793,761.90134 706.05349,724.58426 C 652.79802,745.61112 643.10621,831.17836 650,837.36218 C 639.11718,837.89718 628.62892,836.06488 617.14286,840.21933 C 617.78178,797.64798 616.8824,755.31072 587.14286,717.36218 C 587.14286,717.36218 556.1848,798.28452 555.71429,820.93361 C 555.24378,843.5827 565.16588,861.09949 565.16588,861.09949 C 565.16588,861.09949 556.59781,897.84 558.86729,919.33172 C 561.16314,941.07318 579.31019,979.00789 586.13271,997.98981 z"
- id="path3679"
- sodipodi:nodetypes="czzzzzzcccccccccczczz" />
- </clipPath>
- <filter
- inkscape:collect="always"
- id="filter3898">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="10.892985"
- id="feGaussianBlur3900" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter4130"
- x="-0.49509686"
- width="1.9901937"
- y="-0.26708817"
- height="1.5341763">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="10.730622"
- id="feGaussianBlur4132" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter4141"
- x="-0.40611032"
- width="1.8122206"
- y="-0.30260596"
- height="1.6052119">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="9.8586086"
- id="feGaussianBlur4143" />
- </filter>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4177">
- <path
- sodipodi:nodetypes="czzzzzzcccccccccczczz"
- id="path4179"
- d="M 586.13271,997.98981 C 592.92681,1016.8926 596.6264,1031.2895 598.02301,1049.2017 C 599.41963,1067.114 594.24033,1101.0025 595.12255,1119.8578 C 596.0043,1138.703 603.25624,1159.9568 622.46718,1168.8267 C 641.88605,1177.7925 671.78642,1179.038 696.58702,1165.6811 C 721.38762,1152.3241 753.98804,1095.3556 767.56128,1068.3724 C 781.18513,1041.2885 806.32235,953.87507 812.22208,918.60385 C 818.12181,883.33264 814.77262,877.30308 807.6046,869.54836 C 810.2449,841.70821 806.10488,814.61293 820.71429,782.36218 C 790.46528,794.18788 783.332,822.52288 772.3954,847.86726 C 764.39449,796.93433 772.60456,776.59407 775.71429,746.6479 C 746.64953,761.42581 732.85278,793.76192 730.71429,839.50504 C 719.79034,838.20084 709.32285,835.07081 697.14286,838.79075 C 696.87882,792.76741 695.6793,761.90134 706.05349,724.58426 C 652.79802,745.61112 643.10621,831.17836 650,837.36218 C 639.11718,837.89718 628.62892,836.06488 617.14286,840.21933 C 617.78178,797.64798 616.8824,755.31072 587.14286,717.36218 C 587.14286,717.36218 556.1848,798.28452 555.71429,820.93361 C 555.24378,843.5827 565.16588,861.09949 565.16588,861.09949 C 565.16588,861.09949 556.59781,897.84 558.86729,919.33172 C 561.16314,941.07318 579.31019,979.00789 586.13271,997.98981 z"
- style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- </clipPath>
- <filter
- inkscape:collect="always"
- id="filter4185">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="3.6164709"
- id="feGaussianBlur4187" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter4105">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="3.8640966"
- id="feGaussianBlur4107" />
- </filter>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath2833">
- <path
- style="opacity:1;fill:#292929;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 569.03125,1018.7776 C 564.74554,1019.4919 541.4031,1022.3957 511.17411,1028.7776 C 480.94512,1035.1595 453.86016,1033.7437 375.38803,1046.1072 C 295.53625,1058.688 281.32367,1088.6495 267.26578,1093.1715 C 252.56564,1097.9001 121.88839,1027.349 121.88839,1027.349 L 126.17411,933.06329 C 126.17411,933.06329 212.05962,916.86235 238.31696,899.49186 C 264.57431,882.12137 283.89934,849.82588 297.60268,828.06329 C 311.30602,806.3007 330.45982,756.63471 330.45982,756.63471 L 569.03125,1018.7776 z"
- id="path2835"
- sodipodi:nodetypes="czzzcczzcc" />
- </clipPath>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient2843"
- id="linearGradient2841"
- gradientUnits="userSpaceOnUse"
- x1="347.89655"
- y1="1070.2124"
- x2="275.58191"
- y2="867.97992" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3627"
- id="linearGradient3688"
- gradientUnits="userSpaceOnUse"
- x1="699.32867"
- y1="269.76755"
- x2="698.97504"
- y2="346.1351" />
- <mask
- maskUnits="userSpaceOnUse"
- id="mask3684">
- <path
- sodipodi:type="arc"
- style="opacity:1;fill:url(#linearGradient3688);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.43724918px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path3686"
- sodipodi:cx="579.474"
- sodipodi:cy="260.57516"
- sodipodi:rx="192.6866"
- sodipodi:ry="164.04877"
- d="M 772.1606,260.57516 A 192.6866,164.04877 0 1 1 386.7874,260.57516 A 192.6866,164.04877 0 1 1 772.1606,260.57516 z"
- transform="translate(-174.03125,62.156036)" />
- </mask>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath3622">
- <path
- style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- d="M 266.27183,924.57186 C 264.86456,943.37307 265.12693,957.32289 268.35357,973.87514 C 271.58022,990.42748 284.75965,1019.7825 288.68797,1037.0589 C 292.61419,1054.326 291.3821,1075.3685 276.22853,1088.2071 C 260.91092,1101.1845 234.17726,1109.806 208.39623,1103.9409 C 182.61517,1098.0756 138.84716,1054.7175 119.80604,1033.7126 C 100.6939,1012.6293 56.045183,939.86194 41.867508,909.43681 C 27.689836,879.01169 29.207903,872.71824 33.747793,863.90708 C 24.381071,839.38658 21.334081,813.84027 0.035335518,788.33044 C 30.360815,791.44488 43.915625,815.28677 60.161025,835.47019 C 54.631129,787.39416 42.10631,771.05369 31.787073,744.74589 C 61.781368,750.82755 82.366433,776.61829 95.766856,817.45839 C 105.32101,813.54048 114.00462,808.08545 125.95427,808.39719 C 114.65677,766.70139 108.00481,738.48135 89.267015,707.32725 C 142.70898,712.99758 172.92404,787.96657 168.23844,795.28805 C 178.21641,793.04406 187.24409,788.75767 198.67497,789.63638 C 187.42601,751.28936 177.62716,712.76848 195.01526,670.9882 C 195.01526,670.9882 243.30204,736.42507 249.40492,756.79397 C 255.50779,777.16288 250.92373,795.49449 250.92373,795.49449 C 250.92373,795.49449 267.8833,826.57978 271.21765,846.58862 C 274.59075,866.82997 267.68496,905.69194 266.27183,924.57186 z"
- id="path3624"
- sodipodi:nodetypes="czzzzzzcccccccccczczz" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath3636">
- <path
- style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- d="M 760.16396,935.83377 C 766.95806,954.73656 770.65765,969.13346 772.05426,987.04566 C 773.45088,1004.958 768.27158,1038.8465 769.1538,1057.7018 C 770.03555,1076.547 777.28749,1097.8008 796.49843,1106.6707 C 815.9173,1115.6365 845.81767,1116.882 870.61827,1103.5251 C 895.41887,1090.1681 928.01929,1033.1996 941.59253,1006.2164 C 955.21638,979.13246 980.3536,891.71903 986.25333,856.44781 C 992.15306,821.1766 988.80387,815.14704 981.63585,807.39232 C 984.27615,779.55217 980.13613,752.45689 994.74554,720.20614 C 964.49653,732.03184 957.36325,760.36684 946.42665,785.71122 C 938.42574,734.77829 946.63581,714.43803 949.74554,684.49186 C 920.68078,699.26977 906.88403,731.60588 904.74554,777.349 C 893.82159,776.0448 883.3541,772.91477 871.17411,776.63471 C 870.91007,730.61137 869.71055,699.7453 880.08474,662.42822 C 826.82927,683.45508 817.13746,769.02232 824.03125,775.20614 C 813.14843,775.74114 802.66017,773.90884 791.17411,778.06329 C 791.81303,735.49194 790.91365,693.15468 761.17411,655.20614 C 761.17411,655.20614 730.21605,736.12848 729.74554,758.77757 C 729.27503,781.42666 739.19713,798.94345 739.19713,798.94345 C 739.19713,798.94345 730.62906,835.68396 732.89854,857.17568 C 735.19439,878.91714 753.34144,916.85185 760.16396,935.83377 z"
- id="path3638"
- sodipodi:nodetypes="czzzzzzcccccccccczczz" />
- </clipPath>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3660"
- id="linearGradient3666"
- x1="1255.7386"
- y1="667.09216"
- x2="893.69995"
- y2="858.01099"
- gradientUnits="userSpaceOnUse" />
- <filter
- inkscape:collect="always"
- id="filter3779"
- x="-0.087980822"
- width="1.1759616"
- y="-0.17728332"
- height="1.3545666">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="16.340344"
- id="feGaussianBlur3781" />
- </filter>
- <filter
- id="filter3785"
- inkscape:label="White Fur">
- <feTurbulence
- id="feTurbulence3787"
- in="SourceAlpha"
- type="fractalNoise"
- baseFrequency="0.24044943820224721"
- numOctaves="10"
- seed="655"
- result="result0" />
- <feDisplacementMap
- id="feDisplacementMap3789"
- in="SourceGraphic"
- in2="result0"
- scale="62"
- xChannelSelector="B"
- yChannelSelector="G" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter3677">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="2.0397518"
- id="feGaussianBlur3679" />
- </filter>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath3722">
- <path
- style="opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 709.28572,844.50504 C 763.57143,843.07647 835.32072,829.45305 879.28572,817.71932 C 923.33843,805.96218 1005.172,781.37208 1054.6428,759.86218 C 1103.9821,738.40946 1168.2465,700.58058 1208.9286,667.71933 C 1249.4367,634.99864 1261.3185,611.89952 1269.6429,634.1479 C 1278.012,656.51569 1253.2359,690.47352 1231.7857,715.21933 C 1210.1816,740.14273 1179.0544,767.92466 1132.8571,804.50504 C 1086.6598,841.08542 976.77458,906.08967 920,933.07647 C 862.93394,960.20183 791.79666,991.31489 747.85714,1005.5765 C 703.91762,1019.8381 616.42857,1036.6479 616.42857,1036.6479 L 709.28572,844.50504 z"
- id="path3724"
- sodipodi:nodetypes="czzzzzzzzcc" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath3986">
- <path
- style="opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 709.28572,844.50504 C 763.57143,843.07647 835.32072,829.45305 879.28572,817.71932 C 923.33843,805.96218 1005.172,781.37208 1054.6428,759.86218 C 1103.9821,738.40946 1168.2465,700.58058 1208.9286,667.71933 C 1249.4367,634.99864 1261.3185,611.89952 1269.6429,634.1479 C 1278.012,656.51569 1253.2359,690.47352 1231.7857,715.21933 C 1210.1816,740.14273 1179.0544,767.92466 1132.8571,804.50504 C 1086.6598,841.08542 976.77458,906.08967 920,933.07647 C 862.93394,960.20183 791.79666,991.31489 747.85714,1005.5765 C 703.91762,1019.8381 616.42857,1036.6479 616.42857,1036.6479 L 709.28572,844.50504 z"
- id="path3988"
- sodipodi:nodetypes="czzzzzzzzcc" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath3992">
- <path
- style="opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 709.28572,844.50504 C 763.57143,843.07647 835.32072,829.45305 879.28572,817.71932 C 923.33843,805.96218 1005.172,781.37208 1054.6428,759.86218 C 1103.9821,738.40946 1168.2465,700.58058 1208.9286,667.71933 C 1249.4367,634.99864 1261.3185,611.89952 1269.6429,634.1479 C 1278.012,656.51569 1253.2359,690.47352 1231.7857,715.21933 C 1210.1816,740.14273 1179.0544,767.92466 1132.8571,804.50504 C 1086.6598,841.08542 976.77458,906.08967 920,933.07647 C 862.93394,960.20183 791.79666,991.31489 747.85714,1005.5765 C 703.91762,1019.8381 616.42857,1036.6479 616.42857,1036.6479 L 709.28572,844.50504 z"
- id="path3994"
- sodipodi:nodetypes="czzzzzzzzcc" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath3998">
- <path
- style="opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 178.21428,274.14789 C 174.40985,248.88366 161.40456,223.50987 161.05748,198.62266 C 160.87122,185.26714 164.33033,172.05175 174.81301,159.06861 C 211.16003,93.772775 291.75392,74.373925 360.74767,67.603183 C 447.67006,56.586382 545.66034,85.543255 594.11901,163.00447 C 648.24303,238.73777 650.79377,335.54359 674.73105,422.53242 C 704.16884,549.66002 729.51019,678.74656 735.12329,809.38277 C 732.05981,887.56462 726.69695,974.56692 674.62008,1037.5169 C 626.59354,1087.8743 551.83361,1087.5699 487.5502,1096.5192 C 396.99481,1101.1742 303.19867,1080.3734 225.7663,1032.321 C 160.99066,994.38099 130.03611,918.84237 128.4869,846.30142 C 120.09773,766.42626 154.87842,692.49291 180.1073,619.14181 C 187.57791,536.38074 189.52016,452.89406 189.76064,369.75697 C 188.92382,337.56153 182.67111,305.93964 178.21428,274.14789 z"
- id="path4000"
- sodipodi:nodetypes="cscccccccccccc" />
- </clipPath>
- <filter
- inkscape:collect="always"
- id="filter4002"
- x="-0.24334238"
- width="1.4866848"
- y="-0.39104807"
- height="1.7820961">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="14.589518"
- id="feGaussianBlur4004" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter4010"
- x="-0.14577261"
- width="1.2915452"
- y="-0.23523259"
- height="1.4704652">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="4.4442907"
- id="feGaussianBlur4012" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter4053">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.6062947"
- id="feGaussianBlur4055" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter4079">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="6.5887624"
- id="feGaussianBlur4081" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter4083">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="1.5052066"
- id="feGaussianBlur4085" />
- </filter>
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4113"
- id="radialGradient4119"
- cx="296.33783"
- cy="427.17749"
- fx="296.33783"
- fy="427.17749"
- r="19.704132"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(2.9797125,0,0,2.9797125,-599.28727,-827.0855)" />
- <filter
- inkscape:collect="always"
- id="filter6949"
- x="-0.10294895"
- width="1.2058979"
- y="-0.34224695"
- height="1.6844939">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="1.1675612"
- id="feGaussianBlur6951" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter6953"
- x="-0.098320946"
- width="1.1966419"
- y="-0.19750816"
- height="1.3950163">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="1.1675612"
- id="feGaussianBlur6955" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter6957"
- x="-0.098213427"
- width="1.1964267"
- y="-0.19838208"
- height="1.3967642">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="1.1675612"
- id="feGaussianBlur6959" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter6961"
- x="-0.09919104"
- width="1.1983821"
- y="-0.22643611"
- height="1.4528722">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="1.1675612"
- id="feGaussianBlur6963" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter6965"
- x="-0.099081434"
- width="1.1981629"
- y="-0.22529824"
- height="1.4505965">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="1.1675612"
- id="feGaussianBlur6967" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter6969"
- x="-0.10450897"
- width="1.2090179"
- y="-0.40468886"
- height="1.8093777">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="1.1675612"
- id="feGaussianBlur6971" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter6973"
- x="-0.10330495"
- width="1.2066098"
- y="-0.36439717"
- height="1.7287945">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="1.1675612"
- id="feGaussianBlur6975" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter6977"
- x="-0.10224481"
- width="1.2044896"
- y="-0.32371372"
- height="1.6474274">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="1.1675612"
- id="feGaussianBlur6979" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter6981"
- x="-0.10052545"
- width="1.2010509"
- y="-0.2742162"
- height="1.5484324">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="1.1675612"
- id="feGaussianBlur6983" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter6985"
- x="-0.098428868"
- width="1.1968577"
- y="-0.20853186"
- height="1.4170637">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="1.1675612"
- id="feGaussianBlur6987" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter6989"
- x="-0.098428868"
- width="1.1968577"
- y="-0.20287035"
- height="1.4057407">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="1.1675612"
- id="feGaussianBlur6991" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter6993"
- x="-0.098213255"
- width="1.1964265"
- y="-0.19838208"
- height="1.3967642">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="1.1675612"
- id="feGaussianBlur6995" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter6997">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="1.1675612"
- id="feGaussianBlur6999" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter7001">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="1.1675612"
- id="feGaussianBlur7003" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter7285"
- x="-0.030884685"
- width="1.0617694"
- y="-0.10267408"
- height="1.2053483">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.35026836"
- id="feGaussianBlur7287" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter7289">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.35026836"
- id="feGaussianBlur7291" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter7293">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.35026836"
- id="feGaussianBlur7295" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter7297">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.35026836"
- id="feGaussianBlur7299" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter7301">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.35026836"
- id="feGaussianBlur7303" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter7305">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.35026836"
- id="feGaussianBlur7307" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter7309">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.35026836"
- id="feGaussianBlur7311" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter7313">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.35026836"
- id="feGaussianBlur7315" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter7317">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.35026836"
- id="feGaussianBlur7319" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter7321">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.35026836"
- id="feGaussianBlur7323" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter7325"
- x="-0.031352691"
- width="1.0627054"
- y="-0.12140666"
- height="1.2428133">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.35026836"
- id="feGaussianBlur7327" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter7329"
- x="-0.030991485"
- width="1.061983"
- y="-0.10931916"
- height="1.2186383">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.35026836"
- id="feGaussianBlur7331" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter7333">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.35026836"
- id="feGaussianBlur7335" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter7337">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.35026836"
- id="feGaussianBlur7339" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter7345">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="1.7233839"
- id="feGaussianBlur7347" />
- </filter>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath7421">
- <path
- sodipodi:type="inkscape:offset"
- inkscape:radius="0"
- inkscape:original="M 1111.4062 -285.9375 L 1107.4688 -284.0625 C 1107.4283 -284.05228 1107.3692 -284.04201 1107.3438 -284.03125 C 1106.925 -283.8184 1107.1791 -283.93067 1106.6875 -283.71875 C 1106.2014 -283.50919 1104.9499 -283.13456 1102.5938 -282.25 C 1099.2626 -280.99942 1096.7895 -280.10016 1095.5938 -279.1875 C 1094.0576 -279.16623 1091.8733 -278.95419 1089.9375 -278.46875 C 1086.956 -277.72108 1085.0823 -277.29474 1083.1875 -276.875 C 1081.2927 -276.45527 1081.512 -276.23281 1080.3125 -276 C 1079.0159 -275.74833 1078.5911 -276.00899 1074.875 -275.21875 C 1071.3851 -274.4766 1065.9802 -273.28768 1064.7188 -272.53125 C 1063.1348 -272.71203 1060.8513 -272.85303 1058.875 -272.5625 C 1055.8346 -272.11554 1053.9588 -271.88974 1052.0312 -271.65625 C 1051.3758 -271.57687 1050.9902 -271.45547 1050.6875 -271.375 C 1050.2613 -271.24334 1050.0017 -271.11498 1049.3125 -271.03125 C 1048.0009 -270.87188 1047.5503 -271.18808 1043.7812 -270.75 C 1040.2273 -270.33691 1034.7758 -269.47718 1033.5312 -268.8125 C 1031.9322 -269.10979 1029.6735 -269.34669 1027.6875 -269.15625 C 1024.6287 -268.86293 1022.7155 -268.67226 1020.7812 -268.5 C 1018.847 -268.32773 1019.0926 -268.07763 1017.875 -267.96875 C 1016.5588 -267.85105 1016.1152 -268.13238 1012.3438 -267.71875 C 1008.8017 -267.3303 1003.3359 -266.50948 1002.0625 -265.84375 C 1000.4636 -266.13844 998.1753 -266.35076 996.1875 -266.15625 C 993.12921 -265.857 991.2463 -265.67601 989.3125 -265.5 C 988.65501 -265.44015 988.27245 -265.32144 987.96875 -265.25 C 987.54105 -265.13104 987.28525 -265.03193 986.59375 -264.96875 C 985.27775 -264.84849 984.834 -265.16363 981.0625 -264.75 C 977.50631 -264.35998 972.0569 -263.51084 970.8125 -262.84375 C 969.21381 -263.13793 966.95265 -263.36747 964.96875 -263.15625 C 961.91305 -262.83092 959.9947 -262.63001 958.0625 -262.4375 C 956.13031 -262.24499 956.37275 -261.99662 955.15625 -261.875 C 953.84137 -261.74353 953.3932 -262.03954 949.625 -261.59375 C 946.08611 -261.17509 940.6473 -260.30158 939.375 -259.625 C 937.77741 -259.90604 935.51505 -260.04543 933.53125 -259.8125 C 930.47927 -259.45413 928.58625 -259.24464 926.65625 -259.03125 C 926.00007 -258.95869 925.6156 -258.85856 925.3125 -258.78125 C 924.88571 -258.65402 924.6276 -258.51405 923.9375 -258.4375 C 922.62411 -258.29181 922.17015 -258.61152 918.40625 -258.125 C 914.85737 -257.66624 909.4276 -256.70598 908.1875 -256 C 906.59441 -256.24424 904.3537 -256.38135 902.375 -256.125 C 899.32741 -255.73018 897.4243 -255.47655 895.5 -255.21875 C 893.57571 -254.96096 893.7739 -254.72522 892.5625 -254.5625 C 891.25301 -254.3866 890.8153 -254.66688 887.0625 -254.09375 C 883.53821 -253.55551 878.1393 -252.39458 876.875 -251.65625 C 875.28751 -251.85979 873.0295 -251.91098 871.0625 -251.5625 C 868.03631 -251.02638 866.1636 -250.70081 864.25 -250.375 C 863.59941 -250.26423 863.2363 -250.10406 862.9375 -250 C 862.51681 -249.83512 862.27405 -249.6687 861.59375 -249.53125 C 860.29905 -249.26966 859.86665 -249.53745 856.15625 -248.71875 C 852.65777 -247.9468 847.31035 -246.33582 846.09375 -245.5 C 844.53085 -245.57745 842.33625 -245.41472 840.40625 -244.90625 C 837.43387 -244.12312 835.58855 -243.67416 833.71875 -243.15625 C 831.84875 -242.63835 832.0521 -242.38897 830.875 -242.0625 C 829.60251 -241.7096 829.17795 -241.95541 825.53125 -240.875 C 822.10657 -239.86037 816.88185 -237.94183 815.65625 -237.03125 C 814.11747 -237.01851 811.93645 -236.75903 810.03125 -236.15625 C 807.10027 -235.22891 805.2809 -234.69783 803.4375 -234.09375 C 802.81071 -233.88837 802.44585 -233.70117 802.15625 -233.5625 C 801.74867 -233.34889 801.50295 -233.15375 800.84375 -232.9375 C 799.58925 -232.52596 799.1576 -232.74846 795.5625 -231.5 C 792.17261 -230.32283 786.96755 -228.2863 785.78125 -227.34375 C 784.25737 -227.28408 782.1312 -226.94888 780.25 -226.28125 C 777.35261 -225.25296 775.55095 -224.60577 773.71875 -223.96875 C 771.88655 -223.33174 772.0909 -223.12021 770.9375 -222.71875 C 769.69071 -222.28479 769.27395 -222.51903 765.71875 -221.15625 C 762.38005 -219.87645 757.23165 -217.6737 756.03125 -216.6875 C 754.52407 -216.57981 752.39555 -216.1887 750.53125 -215.46875 C 747.66307 -214.36115 745.90735 -213.68719 744.09375 -213 C 743.47705 -212.76637 743.0973 -212.55797 742.8125 -212.40625 C 742.81251 -212.40625 742.8125 -212.37673 742.8125 -212.375 L 734.8125 -209.1875 L 736.625 -194.46875 C 736.36701 -194.52956 742.8125 -191.15625 742.8125 -191.15625 C 743.03891 -191.30093 743.26145 -191.42886 743.53125 -191.53125 C 744.61177 -191.94123 745.70285 -191.74702 749.53125 -193.21875 C 753.35977 -194.69049 754.7553 -195.22373 755.4375 -195.625 C 756.11711 -196.02478 757.04925 -196.50437 757.65625 -197.15625 C 759.48317 -197.294 761.22705 -197.64948 762.59375 -198.15625 C 765.56175 -199.25677 767.4691 -199.96244 769.375 -200.625 C 771.28081 -201.28754 771.72915 -202.03987 772.78125 -202.40625 C 773.87287 -202.78636 774.97635 -202.57163 778.84375 -203.9375 C 782.71115 -205.30336 784.1269 -205.76458 784.8125 -206.15625 C 785.51361 -206.55677 786.5133 -207.08923 787.125 -207.75 C 789.09581 -207.80466 790.94195 -208.13463 792.40625 -208.625 C 795.40777 -209.63008 797.3324 -210.24671 799.25 -210.875 C 800.78861 -211.3791 801.42415 -211.92177 802.15625 -212.3125 C 802.38647 -212.44681 802.63215 -212.56623 802.90625 -212.65625 C 804.00457 -213.01673 805.0877 -212.73762 809 -213.96875 C 812.91231 -215.19988 814.366 -215.6417 815.0625 -216 C 815.75641 -216.35697 816.6926 -216.79261 817.3125 -217.40625 C 819.17771 -217.42891 820.94835 -217.67308 822.34375 -218.09375 C 825.37415 -219.00729 827.33615 -219.52385 829.28125 -220.0625 C 831.22637 -220.60114 831.70745 -221.32702 832.78125 -221.625 C 833.89527 -221.93415 835.00125 -221.61761 838.96875 -222.65625 C 842.93625 -223.69488 844.38625 -224.08898 845.09375 -224.40625 C 845.82855 -224.73584 846.90765 -225.15997 847.53125 -225.78125 C 849.52907 -225.66525 851.3887 -225.80134 852.875 -226.15625 C 855.95311 -226.89125 857.9584 -227.25719 859.9375 -227.65625 C 861.52541 -227.97643 862.1818 -228.4468 862.9375 -228.75 C 863.17501 -228.8568 863.4044 -228.94276 863.6875 -229 C 864.82091 -229.22919 865.99215 -228.79107 870.03125 -229.5 C 874.07067 -230.20893 875.5315 -230.42709 876.25 -230.6875 C 876.96581 -230.94694 877.95435 -231.25474 878.59375 -231.78125 C 880.51795 -231.54176 882.34165 -231.55672 883.78125 -231.78125 C 886.90767 -232.26887 888.9358 -232.48192 890.9375 -232.75 C 892.93921 -233.01807 893.42625 -233.69514 894.53125 -233.84375 C 895.67767 -233.99793 896.8071 -233.54218 900.875 -234.0625 C 904.94281 -234.58282 906.43525 -234.75823 907.15625 -235 C 907.89337 -235.24714 908.95435 -235.58623 909.59375 -236.125 C 911.64375 -235.78947 913.56745 -235.72704 915.09375 -235.90625 C 918.23595 -236.27521 920.27375 -236.46561 922.28125 -236.6875 C 923.89207 -236.86552 924.5459 -237.2957 925.3125 -237.53125 C 925.55341 -237.61677 925.80655 -237.68685 926.09375 -237.71875 C 927.24345 -237.84647 928.39505 -237.3721 932.46875 -237.84375 C 936.54245 -238.3154 938.0278 -238.45435 938.75 -238.6875 C 939.46941 -238.91977 940.45025 -239.16096 941.09375 -239.65625 C 943.03005 -239.32279 944.8638 -239.25201 946.3125 -239.40625 C 949.45851 -239.7412 951.49 -239.92484 953.5 -240.125 C 955.50991 -240.32514 955.98415 -240.95139 957.09375 -241.0625 C 958.24485 -241.17778 959.39025 -240.69744 963.46875 -241.125 C 967.54725 -241.55256 969.05765 -241.68709 969.78125 -241.90625 C 970.52047 -242.13011 971.57685 -242.4195 972.21875 -242.9375 C 974.27575 -242.53883 976.2206 -242.4441 977.75 -242.59375 C 980.89871 -242.90185 982.9258 -243.067 984.9375 -243.25 C 986.55151 -243.39682 987.20055 -243.81055 987.96875 -244.03125 C 988.21005 -244.11211 988.4623 -244.16116 988.75 -244.1875 C 989.90211 -244.29295 991.0429 -243.79475 995.125 -244.1875 C 999.20711 -244.58025 1000.7139 -244.71834 1001.4375 -244.9375 C 1002.1584 -245.15583 1003.1371 -245.3852 1003.7812 -245.875 C 1005.7193 -245.52501 1007.5501 -245.42062 1009 -245.5625 C 1012.1487 -245.8706 1014.1758 -246.03575 1016.1875 -246.21875 C 1018.1991 -246.40174 1018.7017 -247.05677 1019.8125 -247.15625 C 1020.9648 -247.25948 1022.1047 -246.77142 1026.1875 -247.15625 C 1030.2704 -247.54107 1031.7762 -247.65725 1032.5 -247.875 C 1033.2393 -248.09743 1034.2956 -248.38949 1034.9375 -248.90625 C 1036.9949 -248.50448 1038.9404 -248.40292 1040.4688 -248.5625 C 1043.6153 -248.89102 1045.6458 -249.0852 1047.6562 -249.28125 C 1049.2692 -249.43854 1049.9219 -249.91273 1050.6875 -250.15625 C 1050.9282 -250.24429 1051.1507 -250.27762 1051.4375 -250.3125 C 1052.5858 -250.4522 1053.7542 -249.97259 1057.8125 -250.5625 C 1061.8708 -251.15242 1063.3743 -251.33964 1064.0938 -251.59375 C 1064.8104 -251.84691 1065.7684 -252.15182 1066.4062 -252.6875 C 1068.3259 -252.47556 1070.1262 -252.53609 1071.5625 -252.78125 C 1074.6816 -253.31365 1076.6741 -253.70986 1078.6562 -254.09375 C 1080.6383 -254.47762 1081.1305 -255.1334 1082.2188 -255.375 C 1083.3475 -255.62566 1084.489 -255.25871 1088.4688 -256.25 C 1092.4483 -257.24127 1093.8983 -257.6693 1094.5938 -258.03125 C 1095.316 -258.40725 1096.3555 -258.90183 1096.9688 -259.5625 C 1098.9317 -259.57454 1100.7625 -259.85355 1102.1875 -260.40625 C 1105.1387 -261.55085 1107.0607 -262.27567 1108.875 -263.15625 C 1110.3307 -263.86277 1111.1941 -264.85828 1111.4062 -265.15625 C 1111.6185 -265.4542 1111.5051 -265.8848 1111.5312 -265.90625 C 1111.5742 -265.94148 1111.8716 -266.00028 1112.0312 -266.34375 C 1112.8902 -268.19082 1114.3544 -271.97139 1114.4688 -272.65625 C 1114.5825 -273.33839 1114.6368 -274.00902 1114.6875 -274.40625 C 1114.7169 -274.63575 1114.5404 -275.28515 1114.5625 -275.34375 C 1114.5934 -275.42579 1114.8508 -275.59432 1114.9062 -275.84375 C 1115.1725 -277.04206 1114.9953 -278.05111 1114.7812 -279.46875 C 1114.5673 -280.88638 1113.8096 -284.08338 1113.1562 -284.9375 C 1112.4973 -285.79922 1111.9314 -285.94801 1111.4062 -285.9375 z "
- style="fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- id="path7423"
- d="M 1111.4062,-285.9375 L 1107.4688,-284.0625 C 1107.4283,-284.05228 1107.3692,-284.04201 1107.3438,-284.03125 C 1106.925,-283.8184 1107.1791,-283.93067 1106.6875,-283.71875 C 1106.2014,-283.50919 1104.9499,-283.13456 1102.5938,-282.25 C 1099.2626,-280.99942 1096.7895,-280.10016 1095.5938,-279.1875 C 1094.0576,-279.16623 1091.8733,-278.95419 1089.9375,-278.46875 C 1086.956,-277.72108 1085.0823,-277.29474 1083.1875,-276.875 C 1081.2927,-276.45527 1081.512,-276.23281 1080.3125,-276 C 1079.0159,-275.74833 1078.5911,-276.00899 1074.875,-275.21875 C 1071.3851,-274.4766 1065.9802,-273.28768 1064.7188,-272.53125 C 1063.1348,-272.71203 1060.8513,-272.85303 1058.875,-272.5625 C 1055.8346,-272.11554 1053.9588,-271.88974 1052.0312,-271.65625 C 1051.3758,-271.57687 1050.9902,-271.45547 1050.6875,-271.375 C 1050.2613,-271.24334 1050.0017,-271.11498 1049.3125,-271.03125 C 1048.0009,-270.87188 1047.5503,-271.18808 1043.7812,-270.75 C 1040.2273,-270.33691 1034.7758,-269.47718 1033.5312,-268.8125 C 1031.9322,-269.10979 1029.6735,-269.34669 1027.6875,-269.15625 C 1024.6287,-268.86293 1022.7155,-268.67226 1020.7812,-268.5 C 1018.847,-268.32773 1019.0926,-268.07763 1017.875,-267.96875 C 1016.5588,-267.85105 1016.1152,-268.13238 1012.3438,-267.71875 C 1008.8017,-267.3303 1003.3359,-266.50948 1002.0625,-265.84375 C 1000.4636,-266.13844 998.1753,-266.35076 996.1875,-266.15625 C 993.12921,-265.857 991.2463,-265.67601 989.3125,-265.5 C 988.65501,-265.44015 988.27245,-265.32144 987.96875,-265.25 C 987.54105,-265.13104 987.28525,-265.03193 986.59375,-264.96875 C 985.27775,-264.84849 984.834,-265.16363 981.0625,-264.75 C 977.50631,-264.35998 972.0569,-263.51084 970.8125,-262.84375 C 969.21381,-263.13793 966.95265,-263.36747 964.96875,-263.15625 C 961.91305,-262.83092 959.9947,-262.63001 958.0625,-262.4375 C 956.13031,-262.24499 956.37275,-261.99662 955.15625,-261.875 C 953.84137,-261.74353 953.3932,-262.03954 949.625,-261.59375 C 946.08611,-261.17509 940.6473,-260.30158 939.375,-259.625 C 937.77741,-259.90604 935.51505,-260.04543 933.53125,-259.8125 C 930.47927,-259.45413 928.58625,-259.24464 926.65625,-259.03125 C 926.00007,-258.95869 925.6156,-258.85856 925.3125,-258.78125 C 924.88571,-258.65402 924.6276,-258.51405 923.9375,-258.4375 C 922.62411,-258.29181 922.17015,-258.61152 918.40625,-258.125 C 914.85737,-257.66624 909.4276,-256.70598 908.1875,-256 C 906.59441,-256.24424 904.3537,-256.38135 902.375,-256.125 C 899.32741,-255.73018 897.4243,-255.47655 895.5,-255.21875 C 893.57571,-254.96096 893.7739,-254.72522 892.5625,-254.5625 C 891.25301,-254.3866 890.8153,-254.66688 887.0625,-254.09375 C 883.53821,-253.55551 878.1393,-252.39458 876.875,-251.65625 C 875.28751,-251.85979 873.0295,-251.91098 871.0625,-251.5625 C 868.03631,-251.02638 866.1636,-250.70081 864.25,-250.375 C 863.59941,-250.26423 863.2363,-250.10406 862.9375,-250 C 862.51681,-249.83512 862.27405,-249.6687 861.59375,-249.53125 C 860.29905,-249.26966 859.86665,-249.53745 856.15625,-248.71875 C 852.65777,-247.9468 847.31035,-246.33582 846.09375,-245.5 C 844.53085,-245.57745 842.33625,-245.41472 840.40625,-244.90625 C 837.43387,-244.12312 835.58855,-243.67416 833.71875,-243.15625 C 831.84875,-242.63835 832.0521,-242.38897 830.875,-242.0625 C 829.60251,-241.7096 829.17795,-241.95541 825.53125,-240.875 C 822.10657,-239.86037 816.88185,-237.94183 815.65625,-237.03125 C 814.11747,-237.01851 811.93645,-236.75903 810.03125,-236.15625 C 807.10027,-235.22891 805.2809,-234.69783 803.4375,-234.09375 C 802.81071,-233.88837 802.44585,-233.70117 802.15625,-233.5625 C 801.74867,-233.34889 801.50295,-233.15375 800.84375,-232.9375 C 799.58925,-232.52596 799.1576,-232.74846 795.5625,-231.5 C 792.17261,-230.32283 786.96755,-228.2863 785.78125,-227.34375 C 784.25737,-227.28408 782.1312,-226.94888 780.25,-226.28125 C 777.35261,-225.25296 775.55095,-224.60577 773.71875,-223.96875 C 771.88655,-223.33174 772.0909,-223.12021 770.9375,-222.71875 C 769.69071,-222.28479 769.27395,-222.51903 765.71875,-221.15625 C 762.38005,-219.87645 757.23165,-217.6737 756.03125,-216.6875 C 754.52407,-216.57981 752.39555,-216.1887 750.53125,-215.46875 C 747.66307,-214.36115 745.90735,-213.68719 744.09375,-213 C 743.47705,-212.76637 743.0973,-212.55797 742.8125,-212.40625 C 742.81251,-212.40625 742.8125,-212.37673 742.8125,-212.375 L 734.8125,-209.1875 L 736.625,-194.46875 C 736.36701,-194.52956 742.8125,-191.15625 742.8125,-191.15625 C 743.03891,-191.30093 743.26145,-191.42886 743.53125,-191.53125 C 744.61177,-191.94123 745.70285,-191.74702 749.53125,-193.21875 C 753.35977,-194.69049 754.7553,-195.22373 755.4375,-195.625 C 756.11711,-196.02478 757.04925,-196.50437 757.65625,-197.15625 C 759.48317,-197.294 761.22705,-197.64948 762.59375,-198.15625 C 765.56175,-199.25677 767.4691,-199.96244 769.375,-200.625 C 771.28081,-201.28754 771.72915,-202.03987 772.78125,-202.40625 C 773.87287,-202.78636 774.97635,-202.57163 778.84375,-203.9375 C 782.71115,-205.30336 784.1269,-205.76458 784.8125,-206.15625 C 785.51361,-206.55677 786.5133,-207.08923 787.125,-207.75 C 789.09581,-207.80466 790.94195,-208.13463 792.40625,-208.625 C 795.40777,-209.63008 797.3324,-210.24671 799.25,-210.875 C 800.78861,-211.3791 801.42415,-211.92177 802.15625,-212.3125 C 802.38647,-212.44681 802.63215,-212.56623 802.90625,-212.65625 C 804.00457,-213.01673 805.0877,-212.73762 809,-213.96875 C 812.91231,-215.19988 814.366,-215.6417 815.0625,-216 C 815.75641,-216.35697 816.6926,-216.79261 817.3125,-217.40625 C 819.17771,-217.42891 820.94835,-217.67308 822.34375,-218.09375 C 825.37415,-219.00729 827.33615,-219.52385 829.28125,-220.0625 C 831.22637,-220.60114 831.70745,-221.32702 832.78125,-221.625 C 833.89527,-221.93415 835.00125,-221.61761 838.96875,-222.65625 C 842.93625,-223.69488 844.38625,-224.08898 845.09375,-224.40625 C 845.82855,-224.73584 846.90765,-225.15997 847.53125,-225.78125 C 849.52907,-225.66525 851.3887,-225.80134 852.875,-226.15625 C 855.95311,-226.89125 857.9584,-227.25719 859.9375,-227.65625 C 861.52541,-227.97643 862.1818,-228.4468 862.9375,-228.75 C 863.17501,-228.8568 863.4044,-228.94276 863.6875,-229 C 864.82091,-229.22919 865.99215,-228.79107 870.03125,-229.5 C 874.07067,-230.20893 875.5315,-230.42709 876.25,-230.6875 C 876.96581,-230.94694 877.95435,-231.25474 878.59375,-231.78125 C 880.51795,-231.54176 882.34165,-231.55672 883.78125,-231.78125 C 886.90767,-232.26887 888.9358,-232.48192 890.9375,-232.75 C 892.93921,-233.01807 893.42625,-233.69514 894.53125,-233.84375 C 895.67767,-233.99793 896.8071,-233.54218 900.875,-234.0625 C 904.94281,-234.58282 906.43525,-234.75823 907.15625,-235 C 907.89337,-235.24714 908.95435,-235.58623 909.59375,-236.125 C 911.64375,-235.78947 913.56745,-235.72704 915.09375,-235.90625 C 918.23595,-236.27521 920.27375,-236.46561 922.28125,-236.6875 C 923.89207,-236.86552 924.5459,-237.2957 925.3125,-237.53125 C 925.55341,-237.61677 925.80655,-237.68685 926.09375,-237.71875 C 927.24345,-237.84647 928.39505,-237.3721 932.46875,-237.84375 C 936.54245,-238.3154 938.0278,-238.45435 938.75,-238.6875 C 939.46941,-238.91977 940.45025,-239.16096 941.09375,-239.65625 C 943.03005,-239.32279 944.8638,-239.25201 946.3125,-239.40625 C 949.45851,-239.7412 951.49,-239.92484 953.5,-240.125 C 955.50991,-240.32514 955.98415,-240.95139 957.09375,-241.0625 C 958.24485,-241.17778 959.39025,-240.69744 963.46875,-241.125 C 967.54725,-241.55256 969.05765,-241.68709 969.78125,-241.90625 C 970.52047,-242.13011 971.57685,-242.4195 972.21875,-242.9375 C 974.27575,-242.53883 976.2206,-242.4441 977.75,-242.59375 C 980.89871,-242.90185 982.9258,-243.067 984.9375,-243.25 C 986.55151,-243.39682 987.20055,-243.81055 987.96875,-244.03125 C 988.21005,-244.11211 988.4623,-244.16116 988.75,-244.1875 C 989.90211,-244.29295 991.0429,-243.79475 995.125,-244.1875 C 999.20711,-244.58025 1000.7139,-244.71834 1001.4375,-244.9375 C 1002.1584,-245.15583 1003.1371,-245.3852 1003.7812,-245.875 C 1005.7193,-245.52501 1007.5501,-245.42062 1009,-245.5625 C 1012.1487,-245.8706 1014.1758,-246.03575 1016.1875,-246.21875 C 1018.1991,-246.40174 1018.7017,-247.05677 1019.8125,-247.15625 C 1020.9648,-247.25948 1022.1047,-246.77142 1026.1875,-247.15625 C 1030.2704,-247.54107 1031.7762,-247.65725 1032.5,-247.875 C 1033.2393,-248.09743 1034.2956,-248.38949 1034.9375,-248.90625 C 1036.9949,-248.50448 1038.9404,-248.40292 1040.4688,-248.5625 C 1043.6153,-248.89102 1045.6458,-249.0852 1047.6562,-249.28125 C 1049.2692,-249.43854 1049.9219,-249.91273 1050.6875,-250.15625 C 1050.9282,-250.24429 1051.1507,-250.27762 1051.4375,-250.3125 C 1052.5858,-250.4522 1053.7542,-249.97259 1057.8125,-250.5625 C 1061.8708,-251.15242 1063.3743,-251.33964 1064.0938,-251.59375 C 1064.8104,-251.84691 1065.7684,-252.15182 1066.4062,-252.6875 C 1068.3259,-252.47556 1070.1262,-252.53609 1071.5625,-252.78125 C 1074.6816,-253.31365 1076.6741,-253.70986 1078.6562,-254.09375 C 1080.6383,-254.47762 1081.1305,-255.1334 1082.2188,-255.375 C 1083.3475,-255.62566 1084.489,-255.25871 1088.4688,-256.25 C 1092.4483,-257.24127 1093.8983,-257.6693 1094.5938,-258.03125 C 1095.316,-258.40725 1096.3555,-258.90183 1096.9688,-259.5625 C 1098.9317,-259.57454 1100.7625,-259.85355 1102.1875,-260.40625 C 1105.1387,-261.55085 1107.0607,-262.27567 1108.875,-263.15625 C 1110.3307,-263.86277 1111.1941,-264.85828 1111.4062,-265.15625 C 1111.6185,-265.4542 1111.5051,-265.8848 1111.5312,-265.90625 C 1111.5742,-265.94148 1111.8716,-266.00028 1112.0312,-266.34375 C 1112.8902,-268.19082 1114.3544,-271.97139 1114.4688,-272.65625 C 1114.5825,-273.33839 1114.6368,-274.00902 1114.6875,-274.40625 C 1114.7169,-274.63575 1114.5404,-275.28515 1114.5625,-275.34375 C 1114.5934,-275.42579 1114.8508,-275.59432 1114.9062,-275.84375 C 1115.1725,-277.04206 1114.9953,-278.05111 1114.7812,-279.46875 C 1114.5673,-280.88638 1113.8096,-284.08338 1113.1562,-284.9375 C 1112.4973,-285.79922 1111.9314,-285.94801 1111.4062,-285.9375 z"
- transform="translate(8.0045714e-2,-3.125e-2)" />
- </clipPath>
- <filter
- inkscape:collect="always"
- id="filter7578"
- x="-0.08160872"
- width="1.1632174"
- y="-0.22659944"
- height="1.4531989">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="2.437399"
- id="feGaussianBlur7580" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter7594"
- x="-0.040804356"
- width="1.0816087"
- y="-0.11329972"
- height="1.2265995">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="1.2186995"
- id="feGaussianBlur7596" />
- </filter>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath7606">
- <path
- id="path7608"
- d="M 1049.205,-282.26672 L 1049.1152,-282.25891 C 1047.7278,-281.37446 1042.5119,-280.65171 1042.4862,-272.73547 C 1042.462,-265.31022 1057.4991,-255.64401 1059.6425,-254.64172 C 1061.3727,-253.83263 1063.2341,-253.23296 1065.0488,-252.92297 L 1066.4862,-252.70422 C 1068.4059,-252.49228 1070.2062,-252.55281 1071.6425,-252.79797 C 1074.7616,-253.33037 1076.7541,-253.72658 1078.7362,-254.11047 C 1080.7183,-254.49434 1081.2105,-255.15012 1082.2988,-255.39172 C 1083.4275,-255.64238 1084.569,-255.27543 1088.5488,-256.26672 C 1092.5283,-257.258 1093.9782,-257.68602 1094.6738,-258.04797 C 1095.396,-258.42398 1096.4355,-258.91855 1097.0488,-259.57922 C 1099.0117,-259.59127 1100.8425,-259.87027 1102.2675,-260.42297 C 1105.2187,-261.56758 1107.1407,-262.29239 1108.955,-263.17297 C 1110.4107,-263.8795 1111.2741,-264.875 1111.4862,-265.17297 C 1111.6985,-265.47093 1111.5852,-265.90152 1111.6112,-265.92297 C 1111.6542,-265.95821 1111.9517,-266.017 1112.1112,-266.36047 C 1112.9702,-268.20755 1114.4344,-271.98811 1114.5488,-272.67297 C 1114.6625,-273.35512 1114.7168,-274.02574 1114.7675,-274.42297 C 1114.7969,-274.65248 1114.6204,-275.30187 1114.6425,-275.36047 C 1114.6734,-275.44252 1114.9308,-275.61104 1114.9862,-275.86047 C 1115.2525,-277.05879 1115.0754,-278.06783 1114.8612,-279.48547 C 1114.6473,-280.90311 1113.8896,-284.1001 1113.2362,-284.95422 C 1112.8168,-285.50279 1112.4369,-285.74672 1112.08,-285.86047 C 1112.0129,-285.87776 1111.9561,-285.90721 1111.8925,-285.92297 C 1111.8715,-285.92695 1111.8508,-285.91983 1111.83,-285.92297 C 1111.5184,-285.99847 1111.2215,-286.08164 1110.6738,-286.14172 C 1109.6883,-286.24984 1108.2491,-286.40112 1106.705,-286.39172 C 1106.1903,-286.38859 1105.6679,-286.34408 1105.1425,-286.29797 C 1101.5836,-285.98569 1096.1327,-285.30689 1094.9238,-284.67297 C 1093.2907,-285.00699 1090.9756,-285.2852 1088.9862,-285.14172 C 1085.9222,-284.92075 1084.0185,-284.79953 1082.08,-284.67297 C 1080.1416,-284.54642 1080.3939,-284.28433 1079.1738,-284.20422 C 1077.8547,-284.11762 1077.3869,-284.42747 1073.6112,-284.11047 C 1070.0655,-283.81275 1064.6306,-283.1173 1063.3925,-282.48547 C 1061.7591,-282.81998 1059.4466,-283.09786 1057.455,-282.95422 C 1054.3908,-282.73324 1052.4872,-282.58078 1050.5488,-282.45422 C 1049.8896,-282.41119 1049.5064,-282.33029 1049.205,-282.26672 z"
- style="opacity:0.82448976;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- </clipPath>
- <filter
- inkscape:collect="always"
- id="filter7610"
- x="-0.021942979"
- width="1.0438859"
- y="-0.10017137"
- height="1.2003427">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.57530213"
- id="feGaussianBlur7612" />
- </filter>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath7616">
- <path
- id="path7618"
- d="M 205.47016,-408.97318 L 205.38003,-408.97164 C 203.9344,-408.18598 198.68082,-407.82829 198.10378,-399.93307 C 197.56244,-392.52754 211.88973,-381.83741 213.95811,-380.68826 C 215.62775,-379.76062 217.44286,-379.03275 219.23156,-378.59711 L 220.65023,-378.27877 C 222.5505,-377.93363 224.35065,-377.86862 225.80054,-378.01314 C 228.94914,-378.32698 230.9644,-378.58345 232.96843,-378.82834 C 234.97245,-379.07322 235.50913,-379.69312 236.61162,-379.85833 C 237.75504,-380.02976 238.86821,-379.58419 242.90739,-380.29586 C 246.94627,-381.00755 248.42246,-381.33354 249.14158,-381.64616 C 249.88822,-381.97095 250.95964,-382.39191 251.61747,-383.00826 C 253.57644,-382.88355 255.42223,-383.03435 256.88227,-383.48645 C 259.90603,-384.42272 261.87384,-385.01189 263.74507,-385.76396 C 265.24645,-386.36738 266.17709,-387.30032 266.40943,-387.58279 C 266.64197,-387.86524 266.55894,-388.30268 266.58637,-388.32227 C 266.63172,-388.35443 266.93259,-388.39235 267.11563,-388.72388 C 268.1012,-390.50664 269.82518,-394.17603 269.987,-394.85126 C 270.14794,-395.52383 270.24882,-396.18904 270.32707,-396.58177 C 270.37238,-396.80868 270.24154,-397.46878 270.26767,-397.5257 C 270.30421,-397.6054 270.57272,-397.75558 270.64536,-398.00055 C 270.99449,-399.17741 270.8881,-400.19633 270.77316,-401.62545 C 270.65853,-403.05454 270.12535,-406.29655 269.53303,-407.1941 C 269.15286,-407.77056 268.79088,-408.04035 268.44277,-408.17869 C 268.37703,-408.20061 268.32242,-408.23394 268.26007,-408.2541 C 268.2394,-408.25953 268.21826,-408.25387 268.19773,-408.25845 C 267.89214,-408.35547 267.60176,-408.45912 267.05957,-408.5572 C 266.084,-408.7337 264.65883,-408.98486 263.11782,-409.08304 C 262.60416,-409.11577 262.07992,-409.10775 261.55259,-409.09835 C 257.98058,-409.03472 252.49564,-408.73725 251.24552,-408.18907 C 249.63965,-408.63604 247.34955,-409.07483 245.35499,-409.07027 C 242.28304,-409.06325 240.37552,-409.07493 238.43292,-409.0837 C 236.49041,-409.09248 236.72384,-408.81345 235.50112,-408.81852 C 234.1792,-408.82401 233.73411,-409.16569 229.9455,-409.11245 C 226.38768,-409.06243 220.91754,-408.74723 219.63844,-408.20318 C 218.0323,-408.65065 215.74477,-409.08893 213.74801,-409.08436 C 210.67586,-409.07735 208.76626,-409.05786 206.82375,-409.06662 C 206.16316,-409.06961 205.77525,-409.0156 205.47016,-408.97318 z"
- style="opacity:0.82448976;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- </clipPath>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient7622"
- id="linearGradient7708"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-19.091883,4.2426407)"
- x1="774.97668"
- y1="-211.87105"
- x2="755.11584"
- y2="-202.67865" />
- <mask
- maskUnits="userSpaceOnUse"
- id="mask7704">
- <path
- style="fill:url(#linearGradient7708);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M 718.40812,-224.31217 L 751.65812,-168.31217 L 1027.6581,-192.31217 L 1187.1581,-240.56217 L 1120.6581,-323.31217 L 718.40812,-224.31217 z"
- id="path7706" />
- </mask>
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient8430"
- id="radialGradient7904"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(-0.3324832,0.9022288,-0.9582407,-0.3531242,305.29227,19.909497)"
- cx="142.95833"
- cy="107.09234"
- fx="142.95833"
- fy="107.09234"
- r="66.981766" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3317"
- id="radialGradient7906"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1.0036478,-1.0345492e-7,1.7124628e-7,1.6613125,-160.53487,-96.205369)"
- cx="317.78754"
- cy="129.65378"
- fx="317.78754"
- fy="129.65378"
- r="47.863216" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient8398"
- id="radialGradient7908"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(2.0747661,-0.1577957,0.2382425,3.1325183,-550.77432,-65.728909)"
- cx="325.30847"
- cy="80.909554"
- fx="325.30847"
- fy="80.909554"
- r="26.937988" />
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath8209">
- <path
- sodipodi:nodetypes="czcc"
- id="path8211"
- d="M 734.03125,519.49186 C 734.03125,519.49186 750.78638,556.50992 762.73266,573.44581 C 774.67895,590.3817 815.45982,629.49186 815.45982,629.49186 L 816.05699,490.90211"
- style="opacity:1;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- </clipPath>
- <filter
- inkscape:collect="always"
- id="filter8225">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="10.661912"
- id="feGaussianBlur8227" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter8333">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="7.18"
- id="feGaussianBlur8335" />
- </filter>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath8338">
- <path
- sodipodi:nodetypes="czzzzzzcccccccccczczz"
- id="path8340"
- d="M 266.27183,924.57185 C 264.86456,943.37307 265.12693,957.32289 268.35357,973.87513 C 271.58023,990.42751 284.75966,1019.7825 288.68798,1037.0589 C 292.61419,1054.326 291.38211,1075.3686 276.22854,1088.2071 C 260.91093,1101.1846 234.17727,1109.8061 208.39624,1103.9409 C 182.61518,1098.0756 138.84716,1054.7175 119.80605,1033.7126 C 100.6939,1012.6293 56.045182,939.86193 41.867507,909.4368 C 27.689835,879.01168 29.207902,872.71823 33.747792,863.90708 C 24.38107,839.38658 21.33408,813.84026 0.035334479,788.33044 C 30.360814,791.44487 43.915624,815.28676 60.161024,835.47019 C 54.631128,787.39416 42.106309,771.05368 31.787072,744.74589 C 61.781367,750.82754 82.366432,776.61828 95.766855,817.45839 C 105.32101,813.54047 114.00462,808.08545 125.95427,808.39719 C 114.65677,766.70139 108.0048,738.48134 89.267014,707.32725 C 142.70898,712.99757 172.92404,787.96657 168.23844,795.28805 C 178.21641,793.04406 187.24409,788.75767 198.67497,789.63638 C 187.426,751.28935 177.62715,712.76848 195.01526,670.98819 C 195.01526,670.98819 243.30204,736.42507 249.40491,756.79397 C 255.50779,777.16287 250.92373,795.49448 250.92373,795.49448 C 250.92373,795.49448 267.8833,826.57978 271.21765,846.58862 C 274.59075,866.82996 267.68496,905.69193 266.27183,924.57185 z"
- style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- </clipPath>
- <filter
- inkscape:collect="always"
- id="filter8354">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="6.82"
- id="feGaussianBlur8356" />
- </filter>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath8359">
- <path
- sodipodi:nodetypes="czzzzzzcccccccccczczz"
- id="path8361"
- d="M 266.27183,924.57185 C 264.86456,943.37307 265.12693,957.32289 268.35357,973.87513 C 271.58023,990.42751 284.75966,1019.7825 288.68798,1037.0589 C 292.61419,1054.326 291.38211,1075.3686 276.22854,1088.2071 C 260.91093,1101.1846 234.17727,1109.8061 208.39624,1103.9409 C 182.61518,1098.0756 138.84716,1054.7175 119.80605,1033.7126 C 100.6939,1012.6293 56.045182,939.86193 41.867507,909.4368 C 27.689835,879.01168 29.207902,872.71823 33.747792,863.90708 C 24.38107,839.38658 21.33408,813.84026 0.035334479,788.33044 C 30.360814,791.44487 43.915624,815.28676 60.161024,835.47019 C 54.631128,787.39416 42.106309,771.05368 31.787072,744.74589 C 61.781367,750.82754 82.366432,776.61828 95.766855,817.45839 C 105.32101,813.54047 114.00462,808.08545 125.95427,808.39719 C 114.65677,766.70139 108.0048,738.48134 89.267014,707.32725 C 142.70898,712.99757 172.92404,787.96657 168.23844,795.28805 C 178.21641,793.04406 187.24409,788.75767 198.67497,789.63638 C 187.426,751.28935 177.62715,712.76848 195.01526,670.98819 C 195.01526,670.98819 243.30204,736.42507 249.40491,756.79397 C 255.50779,777.16287 250.92373,795.49448 250.92373,795.49448 C 250.92373,795.49448 267.8833,826.57978 271.21765,846.58862 C 274.59075,866.82996 267.68496,905.69193 266.27183,924.57185 z"
- style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- </clipPath>
- <filter
- inkscape:collect="always"
- id="filter8379"
- x="-0.14413793"
- width="1.288276"
- y="-0.10278689"
- height="1.2055738">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="7.389266"
- id="feGaussianBlur8381" />
- </filter>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath8392">
- <path
- sodipodi:nodetypes="czzzzzzcccccccccczczz"
- id="path8394"
- d="M 760.16396,935.83377 C 766.95806,954.73656 770.65765,969.13346 772.05426,987.04566 C 773.45088,1004.958 768.27158,1038.8465 769.1538,1057.7018 C 770.03555,1076.547 777.28749,1097.8008 796.49843,1106.6707 C 815.9173,1115.6365 845.81767,1116.882 870.61827,1103.5251 C 895.41887,1090.1681 928.01929,1033.1996 941.59253,1006.2164 C 955.21638,979.13246 980.3536,891.71903 986.25333,856.44781 C 992.15306,821.1766 988.80387,815.14704 981.63585,807.39232 C 984.27615,779.55217 980.13613,752.45689 994.74554,720.20614 C 964.49653,732.03184 957.36325,760.36684 946.42665,785.71122 C 938.42574,734.77829 946.63581,714.43803 949.74554,684.49186 C 920.68078,699.26977 906.88403,731.60588 904.74554,777.349 C 893.82159,776.0448 883.3541,772.91477 871.17411,776.63471 C 870.91007,730.61137 869.71055,699.7453 880.08474,662.42822 C 826.82927,683.45508 817.13746,769.02232 824.03125,775.20614 C 813.14843,775.74114 802.66017,773.90884 791.17411,778.06329 C 791.81303,735.49194 790.91365,693.15468 761.17411,655.20614 C 761.17411,655.20614 730.21605,736.12848 729.74554,758.77757 C 729.27503,781.42666 739.19713,798.94345 739.19713,798.94345 C 739.19713,798.94345 730.62906,835.68396 732.89854,857.17568 C 735.19439,878.91714 753.34144,916.85185 760.16396,935.83377 z"
- style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- </clipPath>
- <filter
- inkscape:collect="always"
- id="filter8404"
- x="-0.090268657"
- width="1.1805373"
- y="-0.10250848"
- height="1.205017">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="5.3457272"
- id="feGaussianBlur8406" />
- </filter>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath8417">
- <path
- sodipodi:nodetypes="czzzzzzcccccccccczczz"
- id="path8419"
- d="M 760.16396,935.83377 C 766.95806,954.73656 770.65765,969.13346 772.05426,987.04566 C 773.45088,1004.958 768.27158,1038.8465 769.1538,1057.7018 C 770.03555,1076.547 777.28749,1097.8008 796.49843,1106.6707 C 815.9173,1115.6365 845.81767,1116.882 870.61827,1103.5251 C 895.41887,1090.1681 928.01929,1033.1996 941.59253,1006.2164 C 955.21638,979.13246 980.3536,891.71903 986.25333,856.44781 C 992.15306,821.1766 988.80387,815.14704 981.63585,807.39232 C 984.27615,779.55217 980.13613,752.45689 994.74554,720.20614 C 964.49653,732.03184 957.36325,760.36684 946.42665,785.71122 C 938.42574,734.77829 946.63581,714.43803 949.74554,684.49186 C 920.68078,699.26977 906.88403,731.60588 904.74554,777.349 C 893.82159,776.0448 883.3541,772.91477 871.17411,776.63471 C 870.91007,730.61137 869.71055,699.7453 880.08474,662.42822 C 826.82927,683.45508 817.13746,769.02232 824.03125,775.20614 C 813.14843,775.74114 802.66017,773.90884 791.17411,778.06329 C 791.81303,735.49194 790.91365,693.15468 761.17411,655.20614 C 761.17411,655.20614 730.21605,736.12848 729.74554,758.77757 C 729.27503,781.42666 739.19713,798.94345 739.19713,798.94345 C 739.19713,798.94345 730.62906,835.68396 732.89854,857.17568 C 735.19439,878.91714 753.34144,916.85185 760.16396,935.83377 z"
- style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- </clipPath>
- </defs>
- <metadata
- id="metadata7">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:groupmode="layer"
- id="layer1"
- inkscape:label="Shadow">
- <path
- style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter11361);enable-background:new"
- d="M 304.64285,526.6479 C 294.64285,527.00505 286.42857,529.50504 286.42857,529.50504 L 293.92857,535.57647 L 304.28571,539.1479 L 320.35714,539.50504 L 342.85714,534.1479 L 350.71428,535.21933 L 371.07143,533.07647 L 360.71428,539.86219 C 366.17351,538.83858 378.10757,543.4313 370.35714,545.21933 C 368.61714,545.62075 384.28571,540.57648 384.28571,540.57648 L 386.78571,535.93361 L 390.35714,526.6479 L 401.78571,526.6479 L 419.99999,522.00504 L 423.57143,517.00505 L 407.49999,518.07647 L 395.35714,520.21933 L 380.71428,515.21933 L 310.02218,531.92707 L 304.64285,526.6479 z"
- id="path10326"
- sodipodi:nodetypes="cccccccccsccccccccccc"
- transform="matrix(10.726753,0,0,10.726753,-2882.1235,-4565.4583)"
- inkscape:export-filename="/home/cheeseness/Documents/LCA09/mascot/tuz_new.png"
- inkscape:export-xdpi="142.10527"
- inkscape:export-ydpi="142.10527" />
- </g>
- <g
- inkscape:groupmode="layer"
- id="layer20"
- inkscape:label="New Ear">
- <g
- style="opacity:1;display:inline;enable-background:new"
- id="g7882"
- transform="matrix(0.71084,-0.1937433,0.262963,0.9648058,503.68027,136.48399)">
- <path
- sodipodi:nodetypes="czzzzcc"
- id="path7876"
- d="M 245.12255,100.05344 C 245.12255,100.05344 197.99444,68.406519 177.9079,64.252501 C 157.86998,60.108538 139.435,60.934923 125.97426,77.859824 C 112.51352,94.784725 113.89687,139.12502 112.43872,164.82937 C 110.98057,190.53372 114.98817,235.00638 130.04332,253.49489 C 145.09848,271.98339 175.92966,267.07991 179.97027,274.90859 C 182.1831,279.19595 245.12255,100.05344 245.12255,100.05344 z"
- style="opacity:1;fill:url(#radialGradient7904);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <path
- sodipodi:nodetypes="czzzzzc"
- id="path7878"
- d="M 135.37935,82.017807 C 135.37935,82.017807 161.7229,83.95659 173.01242,95.920995 C 184.42736,108.01833 186.74699,117.25251 188.30828,133.65558 C 189.87165,150.08057 187.45871,162.0737 180.49446,169.69292 C 173.53021,177.31214 179.49017,189.27624 154.57841,181.76399 C 129.66665,174.25174 127.54617,153.98101 128.06318,135.45924 C 128.58039,116.93026 135.37935,82.017807 135.37935,82.017807 z"
- style="opacity:1;fill:url(#radialGradient7906);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <path
- sodipodi:nodetypes="czccssc"
- id="path7880"
- d="M 135.648,81.927211 C 135.648,81.927211 131.00335,98.292286 136.23625,110.49031 C 141.72419,123.28285 163.4605,154.75038 163.4605,165.14596 L 186.11675,160.14596 C 188.65893,153.17952 189.32727,144.3939 188.30425,133.64596 C 186.74296,117.24289 184.43795,108.02455 173.023,95.927211 C 163.36812,85.695164 141.42989,82.552354 135.648,81.927211 z"
- style="opacity:1;fill:url(#radialGradient7908);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- </g>
- </g>
- <g
- inkscape:groupmode="layer"
- id="layer21"
- inkscape:label="Rendered2"
- style="display:inline">
- <path
- style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 845.03125,1154.7776 C 840.74554,1155.4919 817.4031,1158.3957 787.17411,1164.7776 C 756.94512,1171.1595 729.86016,1169.7437 651.38803,1182.1072 C 571.53625,1194.688 557.32367,1224.6495 543.26578,1229.1715 C 528.56564,1233.9001 397.88839,1163.349 397.88839,1163.349 L 402.17411,1069.0633 C 402.17411,1069.0633 488.05962,1052.8624 514.31696,1035.4919 C 540.57431,1018.1214 559.89934,985.82588 573.60268,964.06329 C 587.30602,942.3007 606.45982,892.63471 606.45982,892.63471 L 845.03125,1154.7776 z"
- id="path7917"
- sodipodi:nodetypes="czzzcczzcc" />
- <path
- style="opacity:0.5;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8888);enable-background:accumulate"
- d="M 332.34019,898.38549 L 299.60838,837.08593 L 261.99104,882.19239 C 264.16779,883.5095 267.76529,861.33636 307.59144,817.77531 L 332.34019,898.38549 z"
- id="path7919"
- clip-path="url(#clipPath8658)"
- sodipodi:nodetypes="ccccc"
- transform="translate(276,136)" />
- <path
- style="opacity:1;fill:url(#linearGradient2841);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8892);enable-background:accumulate"
- d="M 200.81833,863.03015 L 347.18943,811.41136 L 591.14127,1037.6855 L 349.31075,1177.6927 L 168.29141,1090.0114 L 200.81833,863.03015 z"
- id="path7923"
- clip-path="url(#clipPath2833)"
- sodipodi:nodetypes="cccccc"
- transform="translate(276,136)" />
- <path
- style="opacity:1;fill:#0f0f0f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 642.88839,640.13471 C 642.88839,640.13471 613.33433,680.70776 595.03125,714.42042 C 576.72816,748.13309 536.41016,840.77736 524.67411,885.49185 C 512.91471,930.29529 462.17411,1009.0633 462.17411,1009.0633 L 538.24554,1027.2776 C 538.24554,1027.2776 550.05266,1014.4542 569.31696,981.20614 C 588.58126,947.95806 629.67411,842.63471 629.67411,842.63471 L 642.88839,640.13471 z"
- id="path7921"
- sodipodi:nodetypes="czzcczcc" />
- <path
- style="opacity:0.4;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8856);enable-background:accumulate"
- d="M 430.28131,381.94122 C 423.21025,384.76965 194.10007,414.09303 194.10007,414.09303 L 154.46046,773.92607 L 244.65895,866.56568 L 296.98485,752.01438 L 397.45289,565.62246 L 430.28131,381.94122 z"
- id="path7925"
- sodipodi:nodetypes="ccccccc"
- clip-path="url(#clipPath3665)"
- transform="translate(276,136)" />
- <path
- style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 969.67051,1164.0346 C 969.67051,1164.0346 992.92679,1175.4283 1005.7383,1184.5107 C 1018.4357,1193.5122 1035.2107,1209.1598 1047.4307,1221.8712 C 1059.7362,1234.6714 1067.5434,1244.4699 1088.9634,1246.032 C 1110.3956,1247.5949 1142.2458,1237.2444 1162.2594,1221.3678 C 1182.2729,1205.4912 1207.9063,1152.135 1207.9063,1152.135 L 1080.7455,1009.0633"
- id="path7927"
- sodipodi:nodetypes="czzzzcc" />
- <path
- style="opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8860);enable-background:accumulate"
- d="M 331.34019,641.50471 L 216.17367,835.36467 L 260.2153,925.96265 L 357.79603,732.21539 L 331.34019,641.50471 z"
- id="path7929"
- clip-path="url(#clipPath8642)"
- sodipodi:nodetypes="ccccc"
- transform="translate(276,136)" />
- <g
- style="opacity:1;display:inline;enable-background:new"
- id="g7931"
- transform="matrix(0.9934486,0.1142802,-0.1142802,0.9934486,-9.24324,588.09054)"
- inkscape:transform-center-x="-347.89063"
- inkscape:transform-center-y="-28.255779">
- <path
- style="opacity:1;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- d="M 1049.205,-282.26672 L 1049.1152,-282.25891 C 1047.7278,-281.37446 1042.5119,-280.65171 1042.4862,-272.73547 C 1042.462,-265.31022 1057.4991,-255.64401 1059.6425,-254.64172 C 1061.3727,-253.83263 1063.2341,-253.23296 1065.0488,-252.92297 L 1066.4862,-252.70422 C 1068.4059,-252.49228 1070.2062,-252.55281 1071.6425,-252.79797 C 1074.7616,-253.33037 1076.7541,-253.72658 1078.7362,-254.11047 C 1080.7183,-254.49434 1081.2105,-255.15012 1082.2988,-255.39172 C 1083.4275,-255.64238 1084.569,-255.27543 1088.5488,-256.26672 C 1092.5283,-257.258 1093.9782,-257.68602 1094.6738,-258.04797 C 1095.396,-258.42398 1096.4355,-258.91855 1097.0488,-259.57922 C 1099.0117,-259.59127 1100.8425,-259.87027 1102.2675,-260.42297 C 1105.2187,-261.56758 1107.1407,-262.29239 1108.955,-263.17297 C 1110.4107,-263.8795 1111.2741,-264.875 1111.4862,-265.17297 C 1111.6985,-265.47093 1111.5852,-265.90152 1111.6112,-265.92297 C 1111.6542,-265.95821 1111.9517,-266.017 1112.1112,-266.36047 C 1112.9702,-268.20755 1114.4344,-271.98811 1114.5488,-272.67297 C 1114.6625,-273.35512 1114.7168,-274.02574 1114.7675,-274.42297 C 1114.7969,-274.65248 1114.6204,-275.30187 1114.6425,-275.36047 C 1114.6734,-275.44252 1114.9308,-275.61104 1114.9862,-275.86047 C 1115.2525,-277.05879 1115.0754,-278.06783 1114.8612,-279.48547 C 1114.6473,-280.90311 1113.8896,-284.1001 1113.2362,-284.95422 C 1112.8168,-285.50279 1112.4369,-285.74672 1112.08,-285.86047 C 1112.0129,-285.87776 1111.9561,-285.90721 1111.8925,-285.92297 C 1111.8715,-285.92695 1111.8508,-285.91983 1111.83,-285.92297 C 1111.5184,-285.99847 1111.2215,-286.08164 1110.6738,-286.14172 C 1109.6883,-286.24984 1108.2491,-286.40112 1106.705,-286.39172 C 1106.1903,-286.38859 1105.6679,-286.34408 1105.1425,-286.29797 C 1101.5836,-285.98569 1096.1327,-285.30689 1094.9238,-284.67297 C 1093.2907,-285.00699 1090.9756,-285.2852 1088.9862,-285.14172 C 1085.9222,-284.92075 1084.0185,-284.79953 1082.08,-284.67297 C 1080.1416,-284.54642 1080.3939,-284.28433 1079.1738,-284.20422 C 1077.8547,-284.11762 1077.3869,-284.42747 1073.6112,-284.11047 C 1070.0655,-283.81275 1064.6306,-283.1173 1063.3925,-282.48547 C 1061.7591,-282.81998 1059.4466,-283.09786 1057.455,-282.95422 C 1054.3908,-282.73324 1052.4872,-282.58078 1050.5488,-282.45422 C 1049.8896,-282.41119 1049.5064,-282.33029 1049.205,-282.26672 z"
- id="path7933" />
- <g
- clip-path="url(#clipPath7616)"
- style="display:inline;filter:url(#filter7610);enable-background:new"
- id="g7935"
- transform="matrix(0.9975712,-6.9654277e-2,6.9654277e-2,0.9975712,872.72062,140.02502)">
- <path
- sodipodi:nodetypes="ccssscsssscscsscsssccscssccsscssscc"
- id="path7937"
- d="M 229.94262,-409.12268 C 226.38481,-409.07267 220.91842,-408.76259 219.63928,-408.21854 C 218.03319,-408.66601 215.73612,-409.09985 213.73933,-409.09528 C 210.66734,-409.08826 208.77464,-409.08651 206.83206,-409.09528 C 206.17159,-409.09827 205.78447,-409.02811 205.47939,-408.98569 C 205.47939,-408.98569 205.47939,-407.88976 205.47939,-407.88976 C 205.59911,-408.06923 205.87191,-408.58022 206.42914,-408.65691 C 207.17672,-408.7598 211.59842,-408.80814 213.73933,-408.76651 C 215.51393,-408.73198 218.19456,-408.49224 220.12854,-407.80756 C 220.44994,-407.69378 220.74779,-407.53378 221.02073,-407.39659 C 222.98415,-406.40966 228.96409,-403.09505 228.96409,-403.09505 C 228.96409,-403.09505 222.33134,-407.04273 221.48122,-407.53358 C 221.27791,-407.65097 220.90658,-407.79127 220.44513,-407.94456 C 221.66576,-408.39235 225.5211,-408.56427 228.27336,-408.65691 C 231.29786,-408.75873 231.62112,-408.7465 233.68405,-408.46512 C 235.81336,-408.17469 237.02256,-407.86236 237.02256,-407.86236 C 237.02255,-407.86236 236.9442,-408.50354 238.05865,-408.65691 C 238.80622,-408.7598 243.22794,-408.80814 245.36884,-408.76651 C 247.43834,-408.72625 250.73489,-408.35935 252.65024,-407.39659 C 253.65356,-406.89226 255.68588,-405.82796 257.44559,-404.86088 L 257.5412,-404.88031 C 257.5412,-404.88031 253.96086,-407.04273 253.11073,-407.53358 C 252.90742,-407.65097 252.5361,-407.79127 252.07464,-407.94456 C 253.29526,-408.39235 257.12183,-408.56427 259.87409,-408.65691 C 262.89859,-408.75873 263.22184,-408.7465 265.28478,-408.46512 C 267.23794,-408.19872 268.2977,-407.93506 268.47939,-407.88976 C 268.47939,-407.88976 268.4523,-408.20122 268.4523,-408.20122 C 268.04327,-408.33767 267.73806,-408.43457 267.05192,-408.5587 C 265.75111,-408.79403 263.6528,-409.16026 261.54335,-409.12268 C 257.9714,-409.05904 252.49007,-408.76672 251.24001,-408.21854 C 249.63418,-408.66549 247.36339,-409.09984 245.36884,-409.09528 C 242.29685,-409.08826 240.37536,-409.08651 238.43279,-409.09528 C 236.49023,-409.10406 236.72011,-408.81621 235.49721,-408.8213 C 234.1753,-408.8268 233.73109,-409.17593 229.94262,-409.12268 C 229.94262,-409.12268 229.94262,-409.12268 229.94262,-409.12268"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- id="path7939"
- d="M 206.1989,-407.47878 C 208.11911,-406.66172 210.77605,-405.28595 212.35787,-404.08139 C 213.93971,-402.87683 215.26544,-402.30771 217.91246,-400.16344 C 218.79803,-399.44606 219.66111,-398.81359 220.50439,-398.2417 L 221.04496,-398.43181 C 220.33173,-398.9152 219.5772,-399.45212 218.77587,-400.05384 C 215.95364,-402.17305 215.14932,-402.86357 212.7608,-404.32798 C 210.37226,-405.79238 208.66132,-406.69374 206.1989,-407.47878 C 206.1989,-407.47878 206.1989,-407.47878 206.1989,-407.47878"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- sodipodi:nodetypes="cssccsscc" />
- <path
- id="path7941"
- d="M 237.79963,-407.47878 C 239.71984,-406.66172 242.40557,-405.28595 243.98738,-404.08139 C 244.80045,-403.46223 245.54587,-403.01097 246.43784,-402.42738 L 247.08684,-402.54404 C 246.28853,-403.12041 245.51507,-403.63839 244.39031,-404.32798 C 242.00177,-405.79238 240.26205,-406.69374 237.79963,-407.47878 C 237.79963,-407.47878 237.79963,-407.47878 237.79963,-407.47878"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- sodipodi:nodetypes="csccscc" />
- </g>
- <g
- clip-path="url(#clipPath7606)"
- id="g7943">
- <path
- style="opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7578);enable-background:new"
- d="M 1056.25,-278.80481 C 1060.3946,-280.28358 1066.25,-275.67981 1066.25,-275.67981 C 1067.149,-275.39889 1068.9751,-276.57428 1068.8743,-277.36595 C 1068.8743,-277.36595 1067.324,-279.22657 1068.5,-280.30481 C 1069.676,-281.38305 1073.796,-278.79743 1076,-278.67981 C 1078.204,-278.56219 1081.5621,-278.90922 1083,-279.42981 C 1084.4379,-279.9504 1084.1129,-280.8544 1085.625,-281.17981 C 1087.1371,-281.50522 1090.7439,-280.14227 1092.6855,-280.01098 C 1094.6271,-279.87969 1097.3336,-279.67671 1098.5,-280.17981 C 1099.6664,-280.68291 1098.6782,-281.33902 1100.375,-282.05481 C 1102.0718,-282.7706 1108.1352,-283.01143 1110,-282.17981 C 1111.8648,-281.34819 1111.8099,-281.66061 1112.625,-279.17981 C 1113.4401,-276.69901 1120.0648,-274.01696 1111.5,-265.80481 C 1102.9352,-257.59266 1052.1221,-252.01887 1045.875,-263.05481 C 1039.6279,-274.09075 1052.1054,-277.32604 1056.25,-278.80481 z"
- id="path7945"
- sodipodi:nodetypes="czzzzzzzzzzzzzz" />
- <path
- style="opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7594);enable-background:new"
- d="M 1058.5,-275.42981 C 1062.6446,-276.90858 1068.5,-272.30481 1068.5,-272.30481 C 1069.399,-272.02389 1071.2251,-273.19928 1071.1243,-273.99095 C 1071.1243,-273.99095 1069.574,-275.85157 1070.75,-276.92981 C 1071.926,-278.00805 1076.046,-275.42243 1078.25,-275.30481 C 1080.454,-275.18719 1083.8121,-275.53422 1085.25,-276.05481 C 1086.6879,-276.5754 1086.3629,-277.4794 1087.875,-277.80481 C 1089.3871,-278.13022 1092.9939,-276.76727 1094.9355,-276.63598 C 1096.8771,-276.50469 1099.5836,-276.30171 1100.75,-276.80481 C 1101.9164,-277.30791 1100.9282,-277.96402 1102.625,-278.67981 C 1104.3218,-279.3956 1110.3852,-279.63643 1112.25,-278.80481 C 1114.1148,-277.97319 1114.0599,-278.28561 1114.875,-275.80481 C 1115.6901,-273.32401 1122.3148,-270.64196 1113.75,-262.42981 C 1105.1852,-254.21766 1054.3721,-248.64387 1048.125,-259.67981 C 1041.8779,-270.71575 1054.3554,-273.95104 1058.5,-275.42981 z"
- id="path7947"
- sodipodi:nodetypes="czzzzzzzzzzzzzz" />
- </g>
- </g>
- <path
- style="opacity:1;fill:#101414;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 628.24553,347.99185 C 624.4411,322.72762 611.43581,297.35383 611.08873,272.46662 C 610.90247,259.1111 614.36158,245.89571 624.84426,232.91257 C 661.19128,167.61674 741.78517,148.21789 810.77892,141.44715 C 897.70131,130.43035 995.69159,159.38722 1044.1503,236.84843 C 1098.2743,312.58173 1100.825,409.38755 1124.7623,496.37638 C 1154.2001,623.50398 1179.5414,752.59052 1185.1545,883.22673 C 1182.0911,961.40858 1176.7282,1048.4109 1124.6513,1111.3609 C 1076.6248,1161.7183 1001.8649,1161.4139 937.58145,1170.3632 C 847.02606,1175.0182 753.22992,1154.2174 675.79755,1106.165 C 611.02191,1068.225 580.06736,992.68633 578.51815,920.14538 C 570.12898,840.27022 604.90967,766.33687 630.13855,692.98577 C 637.60916,610.2247 639.55141,526.73802 639.79189,443.60093 C 638.95507,411.40549 632.70236,379.7836 628.24553,347.99185 z"
- id="path7949"
- sodipodi:nodetypes="cscccccccccccc" />
- <path
- style="opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8940);enable-background:accumulate"
- d="M 311.83409,415.43155 L 321.73359,537.05392 L 261.62951,673.52553 L 277.18586,848.1809 C 292.79912,910.0601 309.37131,946.84995 351.56201,965.23473 C 355.88112,928.99475 312.95049,822.27485 312.31937,776.11489 C 311.68792,729.93044 323.14971,667.50703 342.99704,617.81842 C 363.04539,567.62654 379.89378,572.972 385.12193,525.22549 C 390.35008,477.47898 367.69553,375.83357 367.69553,375.83357 L 311.83409,415.43155 z"
- id="path7951"
- sodipodi:nodetypes="ccccczzzcc"
- clip-path="url(#clipPath8616)"
- transform="translate(276,136)" />
- <path
- style="opacity:1;fill:url(#linearGradient8970);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 1010.0312,655.49186 C 1010.0312,655.49186 1026.7864,692.50992 1038.7327,709.44581 C 1050.6789,726.3817 1091.4598,765.49186 1091.4598,765.49186 L 1144.057,637.90211"
- id="path7953"
- sodipodi:nodetypes="czcc" />
- <path
- style="opacity:0.07999998;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8822);enable-background:accumulate"
- d="M 730.31998,536.56864 C 730.31998,545.05392 772.86772,595.03667 772.86772,595.03667 L 785.47431,566.26713 L 730.31998,536.56864 z"
- id="path7955"
- sodipodi:nodetypes="cccc"
- clip-path="url(#clipPath8209)"
- transform="translate(276,136)" />
- <g
- transform="translate(450.03125,73.843964)"
- style="opacity:1;display:inline;enable-background:new"
- id="g7957"
- clip-path="url(#clipPath3998)">
- <g
- transform="translate(-174.03125,62.156036)"
- style="filter:url(#filter3677)"
- id="g7959">
- <g
- id="g7961"
- style="filter:url(#filter3785)">
- <path
- sodipodi:nodetypes="czzzzzzzzzz"
- id="path7963"
- d="M 425.88244,476.99186 C 436.68787,475.5132 450.62645,480.34637 470.5253,480.20614 C 490.42415,480.06591 527.97852,463.29492 552.66815,463.06328 C 577.35778,462.83164 615.41985,475.34734 631.95387,478.06328 C 648.48789,480.77922 654.80219,477.90476 659.45386,485.92043 C 664.10553,493.9361 661.38057,496.66767 649.09672,506.63472 C 636.81287,516.60177 608.30704,519.27104 583.02529,519.49186 C 557.74295,519.71268 512.644,526.57038 487.66815,523.42042 C 462.6923,520.27046 430.73059,515.59775 418.73958,505.56328 C 406.74857,495.52881 398.88874,488.83146 401.23958,481.63471 C 403.59042,474.43796 415.07701,478.47052 425.88244,476.99186 z"
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <rect
- y="412.60312"
- x="343.6539"
- height="181.01935"
- width="381.83765"
- id="rect7965"
- style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- </g>
- <g
- id="g7967"
- style="filter:url(#filter3785)">
- <path
- sodipodi:nodetypes="czzzcc"
- id="path7969"
- d="M 687.14286,452.36218 C 676.68117,462.07661 600.16326,471.36732 586.42857,481.6479 C 572.69388,491.92848 571.67605,494.53616 574.28571,501.6479 C 576.89537,508.75964 580.83098,511.05362 600,510.21932 C 619.16902,509.38502 698.57143,482.5976 698.57143,488.79075 L 687.14286,452.36218 z"
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- transform="translate(174.03125,-62.156036)" />
- <rect
- y="344.82138"
- x="702.86414"
- height="162.63455"
- width="207.8894"
- id="rect7971"
- style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- </g>
- </g>
- <g
- transform="translate(-174.03125,62.156036)"
- style="opacity:0.18000004;display:inline;enable-background:new"
- id="g7973">
- <g
- id="g7975"
- style="filter:url(#filter3785)">
- <path
- sodipodi:nodetypes="czzzzzzzzzz"
- id="path7977"
- d="M 425.88244,476.99186 C 436.68787,475.5132 450.62645,480.34637 470.5253,480.20614 C 490.42415,480.06591 527.97852,463.29492 552.66815,463.06328 C 577.35778,462.83164 615.41985,475.34734 631.95387,478.06328 C 648.48789,480.77922 654.80219,477.90476 659.45386,485.92043 C 664.10553,493.9361 661.38057,496.66767 649.09672,506.63472 C 636.81287,516.60177 608.30704,519.27104 583.02529,519.49186 C 557.74295,519.71268 512.644,526.57038 487.66815,523.42042 C 462.6923,520.27046 430.73059,515.59775 418.73958,505.56328 C 406.74857,495.52881 398.88874,488.83146 401.23958,481.63471 C 403.59042,474.43796 415.07701,478.47052 425.88244,476.99186 z"
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <rect
- y="412.60312"
- x="343.6539"
- height="181.01935"
- width="381.83765"
- id="rect7979"
- style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- </g>
- <g
- id="g7981"
- style="filter:url(#filter3785)">
- <path
- sodipodi:nodetypes="czzzcc"
- id="path7983"
- d="M 687.14286,452.36218 C 676.68117,462.07661 600.16326,471.36732 586.42857,481.6479 C 572.69388,491.92848 571.67605,494.53616 574.28571,501.6479 C 576.89537,508.75964 580.83098,511.05362 600,510.21932 C 619.16902,509.38502 698.57143,482.5976 698.57143,488.79075 L 687.14286,452.36218 z"
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- transform="translate(174.03125,-62.156036)" />
- <rect
- y="344.82138"
- x="702.86414"
- height="162.63455"
- width="207.8894"
- id="rect7985"
- style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- </g>
- </g>
- </g>
- <path
- style="opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8802);enable-background:accumulate"
- d="M 582.65599,-7.4183011 L 695.79307,78.848726 L 804.68752,337.64981 L 842.87128,545.5392 L 963.07944,637.46308 C 963.07944,637.46308 950.35151,350.37773 943.28044,323.50767 C 936.20938,296.63761 793.37381,-69.643698 793.37381,-69.643698 L 582.65599,-7.4183011 z"
- id="path7987"
- clip-path="url(#clipPath8604)"
- sodipodi:nodetypes="cccccscc"
- transform="translate(276,136)" />
- <path
- style="opacity:1;fill:url(#linearGradient8958);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 964.13839,239.599 C 964.13839,239.599 972.81571,250.49562 988.24554,251.56328 C 1003.6754,252.63094 1037.9672,211.61061 1058.4241,199.42043 C 1078.9034,187.2169 1105.4705,172.81818 1122.3527,179.06329 C 1139.2348,185.30839 1144.5105,205.49938 1150.2098,227.099 C 1155.9092,248.69861 1156.9284,288.91289 1147.5313,319.95615 C 1138.1341,350.9994 1097.028,393.0599 1082.1741,423.349 C 1067.3202,453.6381 1070.567,463.17043 1070.567,463.17043"
- id="path7989"
- sodipodi:nodetypes="czzzzzzc" />
- <path
- style="opacity:1;fill:url(#radialGradient3315);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- d="M 1124.4955,207.63471 C 1108.6027,206.74185 1074.7767,219.74054 1058.4241,231.92043 C 1041.9855,244.16433 1029.2032,256.03483 1029.1384,284.06328 C 1029.0732,312.26932 1042.2575,323.13969 1058.2455,331.02757 C 1074.2335,338.91546 1091.9317,338.14685 1110.2098,319.24186 C 1128.488,300.33686 1124.4955,207.63471 1124.4955,207.63471 z"
- id="path7991"
- sodipodi:nodetypes="czzzzc" />
- <path
- sodipodi:type="arc"
- style="opacity:0.75;fill:url(#radialGradient3543);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4120);enable-background:accumulate"
- id="path7993"
- sodipodi:cx="385"
- sodipodi:cy="237.00504"
- sodipodi:rx="86.428574"
- sodipodi:ry="73.928574"
- d="M 471.42857,237.00504 A 86.428574,73.928574 0 1 1 298.57143,237.00504 A 86.428574,73.928574 0 1 1 471.42857,237.00504 z"
- transform="matrix(0.9434749,-0.1239943,0.1440089,1.0957669,451.94827,134.5988)"
- clip-path="url(#clipPath4100)" />
- <path
- transform="translate(450.03125,73.843964)"
- style="opacity:1;fill:url(#radialGradient3915);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 527.60588,407.44884 C 527.60588,407.44884 405.56444,445.85232 340.09154,417.08065 C 274.61865,388.30899 265.71429,292.36218 265.71429,292.36218 C 265.71429,292.36218 339.09587,211.85825 395.63507,208.74742 C 451.46212,205.67578 486.20893,228.89074 510.50508,274.59913 C 534.85708,320.41261 527.60588,407.44884 527.60588,407.44884 z"
- id="path7995"
- sodipodi:nodetypes="csczzc"
- mask="url(#mask3684)" />
- <path
- style="opacity:1;fill:url(#linearGradient3959);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 772.17411,393.349 C 772.17411,393.349 808.39165,365.96653 823.78125,357.45614 C 838.95859,349.06313 849.49553,345.849 859.6741,345.849 L 844.13839,412.81328"
- id="path7997"
- sodipodi:nodetypes="czcc" />
- <path
- sodipodi:type="arc"
- style="opacity:1;fill:url(#radialGradient3933);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path7999"
- sodipodi:cx="409.28571"
- sodipodi:cy="306.64789"
- sodipodi:rx="36.25"
- sodipodi:ry="36.25"
- d="M 445.53571,306.64789 A 36.25,36.25 0 1 1 373.03571,306.64789 A 36.25,36.25 0 1 1 445.53571,306.64789 z"
- transform="translate(449.49554,74.915393)" />
- <path
- style="opacity:0.3;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8806);enable-background:accumulate"
- d="M 311.83409,415.43155 L 321.73359,537.05392 L 261.62951,673.52553 L 277.18586,848.1809 C 292.79912,910.0601 309.37131,946.84995 351.56201,965.23473 C 355.88112,928.99475 360.24362,892.86709 320.31937,742.11489 L 337.99704,672.81842 L 410.12193,534.22549 L 367.69553,375.83357 L 311.83409,415.43155 z"
- id="path8001"
- sodipodi:nodetypes="cccccccccc"
- clip-path="url(#clipPath8616)"
- transform="translate(276,136)" />
- <path
- style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8826);enable-background:accumulate"
- d="M 635.21025,581.13004 C 621.06811,593.85796 674.44372,615.71019 711.57778,605.17167 C 748.71184,594.63315 816.22265,569.6073 814.81537,525.97571 C 813.40809,482.34413 738.44784,397.28228 738.44784,397.28228 L 635.21025,581.13004 z"
- id="path8003"
- sodipodi:nodetypes="czzcc" />
- <path
- sodipodi:type="arc"
- style="opacity:1;fill:url(#radialGradient3991);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path8005"
- sodipodi:cx="410"
- sodipodi:cy="306.64789"
- sodipodi:rx="23.214285"
- sodipodi:ry="23.214285"
- d="M 433.21428,306.64789 A 23.214285,23.214285 0 1 1 386.78572,306.64789 A 23.214285,23.214285 0 1 1 433.21428,306.64789 z"
- transform="translate(449.67411,74.915393)" />
- <path
- sodipodi:type="arc"
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter3981);enable-background:accumulate"
- id="path8007"
- sodipodi:cx="414.28571"
- sodipodi:cy="303.07648"
- sodipodi:rx="7.5"
- sodipodi:ry="7.5"
- d="M 421.78571,303.07648 A 7.5,7.5 0 1 1 406.78571,303.07648 A 7.5,7.5 0 1 1 421.78571,303.07648 z"
- transform="translate(451.99554,73.486821)" />
- <path
- style="opacity:1;fill:url(#radialGradient4112);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 789.31696,478.349 C 789.31696,478.349 796.33977,497.91759 788.24553,513.349 C 780.15129,528.78041 745.92236,552.33722 720.74554,563.349 C 695.43582,574.41891 635.27254,596.31293 618.95982,605.31328 C 602.49834,614.39571 600.74554,617.99185 600.74554,617.99185 C 600.74554,617.99185 593.59861,598.92744 629.49553,566.20615 C 665.66764,533.23401 771.52265,518.15665 789.31696,478.349 z"
- id="path8009"
- sodipodi:nodetypes="czzzczc" />
- <g
- style="opacity:1;display:inline;enable-background:new"
- id="g8011"
- transform="translate(780.74553,74.55825)">
- <path
- transform="translate(-329.81481,0)"
- clip-path="url(#clipPath3999)"
- sodipodi:nodetypes="czzczzzszc"
- id="path8013"
- d="M 179.64286,267.36218 C 157.23242,307.0651 119.02676,383.14247 110.35715,417.00504 C 101.70994,450.78014 101.58516,483.42158 110,503.43362 C 118.3602,523.31575 136.16398,539.06642 150.71428,544.86218 C 150.1179,530.48631 165.08723,501.57635 223.57143,472.36218 C 282.1977,443.07704 301.95306,445.23132 327.14285,425.21932 C 352.77291,404.85756 335.34872,345.57268 330.35714,331.29075 C 325.36556,317.00882 329.12051,327.91101 328.41112,326.19774 C 317.72184,300.38182 294.1968,271.76744 263.92857,261.6479 C 233.66034,251.52836 198.91081,256.79953 179.64286,267.36218 z"
- style="opacity:1;fill:url(#radialGradient3585);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline" />
- <path
- transform="matrix(0.8823874,0.4705236,-0.4705236,0.8823874,-166.62245,2.387362)"
- d="M 248.28731,338.07648 A 64.715881,134.00607 0 1 1 118.85555,338.07648 A 64.715881,134.00607 0 1 1 248.28731,338.07648 z"
- sodipodi:ry="134.00607"
- sodipodi:rx="64.715881"
- sodipodi:cy="338.07648"
- sodipodi:cx="183.57143"
- id="path8015"
- style="opacity:1;fill:url(#radialGradient4060);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:type="arc" />
- <path
- transform="matrix(0.8823874,0.4705236,-0.4705236,0.8823874,-162.19388,-18.755495)"
- d="M 248.28731,338.07648 A 64.715881,134.00607 0 1 1 118.85555,338.07648 A 64.715881,134.00607 0 1 1 248.28731,338.07648 z"
- sodipodi:ry="134.00607"
- sodipodi:rx="64.715881"
- sodipodi:cy="338.07648"
- sodipodi:cx="183.57143"
- id="path8017"
- style="opacity:1;fill:url(#radialGradient4062);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:type="arc" />
- <path
- transform="translate(-329.81481,3e-7)"
- clip-path="url(#clipPath3999)"
- sodipodi:nodetypes="czzczzzszc"
- id="path8019"
- d="M 179.64286,267.36218 C 157.23242,307.0651 119.02676,383.14247 110.35715,417.00504 C 101.70994,450.78014 101.58516,483.42158 110,503.43362 C 118.3602,523.31575 136.16398,539.06642 150.71428,544.86218 C 150.1179,530.48631 165.08723,501.57635 223.57143,472.36218 C 282.1977,443.07704 301.95306,445.23132 327.14285,425.21932 C 352.77291,404.85756 335.34872,345.57268 330.35714,331.29075 C 325.36556,317.00882 329.12051,327.91101 328.41112,326.19774 C 317.72184,300.38182 294.1968,271.76744 263.92857,261.6479 C 233.66034,251.52836 198.91081,256.79953 179.64286,267.36218 z"
- style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3587);stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;filter:url(#filter4079);enable-background:new" />
- </g>
- <path
- sodipodi:type="arc"
- style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path8021"
- sodipodi:cx="310.71429"
- sodipodi:cy="398.07648"
- sodipodi:rx="19.704132"
- sodipodi:ry="19.704132"
- d="M 330.41843,398.07648 A 19.704132,19.704132 0 1 1 291.01016,398.07648 A 19.704132,19.704132 0 1 1 330.41843,398.07648 z"
- transform="translate(452.55663,72.581273)" />
- <path
- sodipodi:type="arc"
- style="opacity:1;fill:url(#radialGradient4056);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4082);stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4083);enable-background:accumulate"
- id="path8023"
- sodipodi:cx="310.71429"
- sodipodi:cy="398.07648"
- sodipodi:rx="19.704132"
- sodipodi:ry="19.704132"
- d="M 330.41843,398.07648 A 19.704132,19.704132 0 1 1 291.01016,398.07648 A 19.704132,19.704132 0 1 1 330.41843,398.07648 z"
- transform="translate(450.55663,72.581273)" />
- <path
- sodipodi:type="arc"
- style="opacity:1;fill:url(#radialGradient4119);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- id="path8025"
- sodipodi:cx="310.71429"
- sodipodi:cy="398.07648"
- sodipodi:rx="19.704132"
- sodipodi:ry="19.704132"
- d="M 330.41843,398.07648 A 19.704132,19.704132 0 1 1 291.01016,398.07648 A 19.704132,19.704132 0 1 1 330.41843,398.07648 z"
- transform="translate(450.55663,72.581273)" />
- <path
- sodipodi:type="arc"
- style="opacity:1;fill:url(#radialGradient4868);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4002);enable-background:accumulate"
- id="path8027"
- sodipodi:cx="429.56738"
- sodipodi:cy="377.42877"
- sodipodi:rx="72.079735"
- sodipodi:ry="44.547726"
- d="M 501.64712,377.42877 A 72.079735,44.547726 0 1 1 357.48765,377.42877 A 72.079735,44.547726 0 1 1 501.64712,377.42877 z"
- transform="matrix(0.9969564,-7.7961675e-2,7.7961675e-2,0.9969564,436.61877,125.29509)"
- inkscape:transform-center-x="-47.231976"
- inkscape:transform-center-y="-3.6935079" />
- <path
- sodipodi:type="arc"
- style="opacity:1;fill:url(#radialGradient4876);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4010);enable-background:accumulate"
- id="path8029"
- sodipodi:cx="437.6991"
- sodipodi:cy="391.21735"
- sodipodi:rx="36.611931"
- sodipodi:ry="22.627417"
- d="M 474.31103,391.21735 A 36.611931,22.627417 0 1 1 401.08717,391.21735 A 36.611931,22.627417 0 1 1 474.31103,391.21735 z"
- transform="matrix(1.4357951,-6.9991037e-2,6.9991037e-2,1.4357951,235.18065,-63.86546)"
- inkscape:transform-center-x="-20.955902"
- inkscape:transform-center-y="-13.056625" />
- <g
- transform="translate(450.03125,73.843964)"
- id="g8031"
- style="opacity:1;display:inline;filter:url(#filter4053);enable-background:new">
- <path
- d="M 416.87499,401.82648 A 3.2142856,3.2142856 0 1 1 410.44642,401.82648 A 3.2142856,3.2142856 0 1 1 416.87499,401.82648 z"
- sodipodi:ry="3.2142856"
- sodipodi:rx="3.2142856"
- sodipodi:cy="401.82648"
- sodipodi:cx="413.66071"
- id="path8033"
- style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4484);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:type="arc" />
- <path
- transform="translate(13.125009,8.1249913)"
- d="M 416.87499,401.82648 A 3.2142856,3.2142856 0 1 1 410.44642,401.82648 A 3.2142856,3.2142856 0 1 1 416.87499,401.82648 z"
- sodipodi:ry="3.2142856"
- sodipodi:rx="3.2142856"
- sodipodi:cy="401.82648"
- sodipodi:cx="413.66071"
- id="path8035"
- style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4486);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:type="arc" />
- <path
- transform="translate(32.946437,7.4999913)"
- d="M 416.87499,401.82648 A 3.2142856,3.2142856 0 1 1 410.44642,401.82648 A 3.2142856,3.2142856 0 1 1 416.87499,401.82648 z"
- sodipodi:ry="3.2142856"
- sodipodi:rx="3.2142856"
- sodipodi:cy="401.82648"
- sodipodi:cx="413.66071"
- id="path8037"
- style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4488);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:type="arc" />
- <path
- transform="translate(24.910723,-10.267866)"
- d="M 416.87499,401.82648 A 3.2142856,3.2142856 0 1 1 410.44642,401.82648 A 3.2142856,3.2142856 0 1 1 416.87499,401.82648 z"
- sodipodi:ry="3.2142856"
- sodipodi:rx="3.2142856"
- sodipodi:cy="401.82648"
- sodipodi:cx="413.66071"
- id="path8039"
- style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4490);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:type="arc" />
- <path
- transform="translate(47.589294,-0.6250087)"
- d="M 416.87499,401.82648 A 3.2142856,3.2142856 0 1 1 410.44642,401.82648 A 3.2142856,3.2142856 0 1 1 416.87499,401.82648 z"
- sodipodi:ry="3.2142856"
- sodipodi:rx="3.2142856"
- sodipodi:cy="401.82648"
- sodipodi:cx="413.66071"
- id="path8041"
- style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4492);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:type="arc" />
- </g>
- <path
- style="opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- d="M 896.20301,482.92837 C 897.1881,487.27845 900.74008,489.10785 903.58974,490.82019 C 908.05042,493.33311 910.1099,492.3423 912.74425,490.06258 C 914.3462,488.14141 923.42736,485.36393 928.33848,482.99151 C 932.66809,481.5326 937.24178,477.63278 941.723,474.65775 C 945.11814,473.03051 947.06964,475.01239 949.55168,475.6679 C 952.4958,476.38451 953.96285,477.83965 955.6126,479.20344 C 958.00876,480.37863 954.6847,482.34657 958.8956,483.49658 C 960.08651,483.71452 961.31255,484.07303 962.17859,482.99151"
- id="path8043"
- sodipodi:nodetypes="ccccccccc" />
- <path
- style="opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- d="M 910.85021,475.35223 C 913.16515,475.32025 914.02799,475.99476 916.34292,474.53148 C 919.79856,471.45035 921.74546,471.38671 924.29787,470.11206 C 927.32444,468.79683 930.83357,478.26375 934.3994,479.96105 C 936.79449,479.13963 935.68854,481.75484 935.85149,482.6127 C 935.90862,485.25954 938.65843,486.29076 940.20777,488.04227 C 943.52381,490.29776 947.583,494.33773 951.31945,493.34557 C 957.7647,490.4145 961.59867,492.06411 967.60816,485.95883 C 968.31221,484.77749 967.02391,479.06423 970.70175,478.76149 C 973.22574,479.01487 974.86842,478.81164 976.76267,479.32971 C 982.20367,481.4469 984.50045,485.77971 991.47301,487.28466 C 997.65591,488.25105 999.08565,491.07892 1005.3626,492.33542"
- id="path8045"
- sodipodi:nodetypes="cccccccccccc" />
- <path
- style="opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- d="M 876.98133,483.52197 C 879.37991,482.72817 883.08746,487.71407 885.15446,490.56765 C 885.74727,493.24717 886.30823,496.0541 885.91207,502.68948 C 886.6972,505.10702 888.59256,505.72043 890.7103,505.97248 C 893.82775,505.4357 896.58699,504.64818 898.0339,502.94202 C 899.9055,501.00035 903.34643,505.33596 906.11512,506.98263 C 909.72521,508.89472 913.8889,508.96149 917.98442,509.25547 C 919.688,509.02483 920.35482,513.77062 921.26741,517.3367 C 921.65155,521.71476 920.38197,524.23239 919.49965,527.18568 C 919.20535,529.68223 922.48815,530.71542 925.8131,531.73137 C 928.99554,532.47261 932.35734,533.39321 934.90447,533.49914 C 940.04633,534.37405 942.99321,536.18966 947.0263,537.53975 C 949.26544,538.3563 950.28649,539.78191 951.57199,541.07528"
- id="path8047"
- sodipodi:nodetypes="ccccccccccccc" />
- <path
- style="opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter8814);enable-background:new"
- d="M 332,187.69519 C 332,187.69519 389.5,162.19519 389.5,159.69519 C 389.5,157.19519 395,107.69519 395,107.69519 C 395,107.69519 486,59.195189 486.5,57.195189 C 487,55.195189 572.5,-4.8048114 572.5,-4.8048114 L 386.5,17.195189 L 311,123.19519 L 332,187.69519 z"
- id="path8049"
- clip-path="url(#clipPath8514)"
- transform="translate(276,136)" />
- <path
- style="opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 1697.2846,722.5514 C 1697.2846,722.5514 1581.3191,796.0905 1574.2481,800.33314 C 1567.177,804.57578 1343.7312,937.51186 1343.7312,937.51186 L 1347.9739,977.10984 L 1564.3486,876.70067 L 1681.7283,774.8773 L 1697.2846,722.5514 z"
- id="path8051" />
- <path
- style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8810);enable-background:accumulate"
- d="M 528.91587,556.85291 C 523.25902,555.4387 347.89654,631.80623 347.89654,631.80623 L 313.95541,812.82557 L 365.05087,1006.7738 L 622.25397,1074.4551 C 622.25397,1074.4551 828.72915,1227.1901 834.386,1222.9475 C 840.04286,1218.7049 1002.6774,1029.2002 1002.6774,1029.2002 L 842.87128,845.35248 L 796.20224,667.16157 L 528.91587,556.85291 z"
- id="path8053"
- clip-path="url(#clipPath8610)"
- sodipodi:nodetypes="cccccscccc"
- transform="translate(276,136)" />
- <path
- style="opacity:1;fill:#0c0c0c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- d="M 1097.6433,613.88997 C 1097.6433,613.88997 1120.2628,607.38316 1133.386,608.01724 C 1146.5093,608.65133 1164.0276,609.95586 1177.0949,620.20343 C 1190.1622,630.45099 1202.1626,647.3435 1211.2073,678.57308 C 1220.2519,709.80266 1212.9056,777.82509 1205.0312,821.92043 C 1197.1569,866.01577 1176.7661,928.03341 1160.0312,961.92043 C 1143.2964,995.80745 1110.2335,1039.4156 1099.4618,1051.7966 C 1088.0976,1064.8586 1043.2559,1088.2228 1020.0312,1094.0633 C 1025.3346,1083.4567 1068.931,1043.4744 1055.0312,1033.349 C 1041.0123,1023.1367 1009.2712,1079.3314 970.7381,1062.3822 C 992.12041,1049.2501 1012.5175,1011.1961 1004.7787,995.78772 C 996.93846,980.17733 974.07378,1044.5453 911.24317,1032.8006 C 941.29521,1005.2739 966.65023,961.89659 952.50587,949.8209 C 938.09071,937.51403 892.04412,1004.1141 892.04412,1004.1141 C 892.04412,1004.1141 889.22222,962.41287 905.81732,935.50673 C 922.45667,908.52886 985.47029,853.89146 1005.3704,823.80331 C 1025.2706,793.71517 1038.983,757.79429 1047.5059,731.28537 C 1056.0287,704.77645 1063.3068,654.18583 1063.3068,654.18583"
- id="path8055"
- sodipodi:nodetypes="czzzzzzczczczczzzc" />
- <path
- style="opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8818);enable-background:accumulate"
- d="M 770.74639,609.17881 L 719.8347,706.75955 L 639.93163,817.77531 L 674.57987,889.19309 L 717.00628,968.38906 L 789.13117,923.13422 L 803.27331,730.80117 L 824.48651,592.20825 L 810.34437,502.05213 L 770.74639,609.17881 z"
- id="path8057"
- clip-path="url(#clipPath8622)"
- sodipodi:nodetypes="cccccccccc"
- transform="translate(276,136)" />
- <path
- style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8810);enable-background:accumulate"
- d="M 295,846.19519 L 301.64488,777.27234 C 301.64488,777.27234 391.96439,866.27691 464,900.19519 C 536.03561,934.11347 772,962.19519 772,962.19519 L 926,936.19519 L 890,1098.1952 L 604,1124.1952 L 306,1035.1952 L 295,846.19519 z"
- id="path8059"
- clip-path="url(#clipPath8906)"
- sodipodi:nodetypes="cczcccccc"
- transform="translate(276,136)" />
- <path
- transform="translate(450.03125,73.843964)"
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter3587);enable-background:new"
- d="M 405.79629,845.99023 L 480.74961,911.04406 L 483.24924,927.92446 L 502.6526,938.08337 L 509.14464,961.13446 L 540.85369,952.76336 L 555.70293,1000.8466 C 567.95945,1013.5745 645.49637,887.7369 611.56436,1039.0304 L 550.75318,1055.2939 L 461.55026,960.60104 L 398.72523,906.80141 L 405.79629,845.99023 z"
- id="path8061"
- sodipodi:nodetypes="cccccccccccc"
- clip-path="url(#clipPath3602)" />
- <path
- style="opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="M 1159.317,918.349 C 1213.6027,916.92043 1285.352,903.29701 1329.317,891.56328 C 1373.3697,879.80614 1455.2033,855.21604 1504.674,833.70614 C 1554.0133,812.25342 1618.2778,774.42454 1658.9599,741.56329 C 1699.468,708.8426 1711.3498,685.74348 1719.6741,707.99186 C 1728.0432,730.35965 1703.2672,764.31748 1681.817,789.06329 C 1660.2128,813.98669 1629.0856,841.76862 1582.8883,878.349 C 1536.691,914.92938 1426.8058,979.93363 1370.0312,1006.9204 C 1312.9652,1034.0458 1241.8279,1065.1589 1197.8884,1079.4205 C 1153.9489,1093.6821 1066.4598,1110.4919 1066.4598,1110.4919 L 1159.317,918.349 z"
- id="path8063"
- sodipodi:nodetypes="czzzzzzzzcc" />
- <path
- transform="translate(450.03125,73.843964)"
- style="opacity:0.5;fill:url(#linearGradient3666);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter3779);enable-background:accumulate"
- d="M 1241.5965,652.95007 C 1241.5965,652.95007 1176.875,707.28713 1095.9326,751.94501 C 1013.9082,797.19985 811.67556,845.28311 811.67556,845.28311 C 811.67556,845.28311 796.57419,866.33507 856.93045,873.56739 C 917.28671,880.79971 1081.0124,820.2667 1135.5306,777.40085 C 1190.0488,734.535 1255.7387,665.67799 1255.7387,665.67799 L 1241.5965,652.95007 z"
- id="path8065"
- sodipodi:nodetypes="czczzcc"
- clip-path="url(#clipPath3992)" />
- <g
- transform="translate(450.03125,73.843964)"
- style="opacity:1;display:inline;enable-background:new"
- id="g8067"
- clip-path="url(#clipPath3986)">
- <g
- transform="translate(-174.03125,62.156036)"
- style="filter:url(#filter3677)"
- id="g8069">
- <g
- style="filter:url(#filter3785)"
- id="g8071">
- <path
- sodipodi:nodetypes="czzccccc"
- id="path8073"
- d="M 1094.2857,725.93361 C 1094.2857,725.93361 1093.9896,752.09452 1098.9285,763.79076 C 1103.8674,775.487 1118.9666,790.27741 1127.5,795.21933 C 1136.0334,800.16125 1146.4286,803.79075 1146.4286,803.79075 L 1264.2857,688.79075 L 1282.1429,613.07647 L 1185.7143,651.6479 L 1094.2857,725.93361 z"
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- transform="translate(174.03125,-62.156036)" />
- <rect
- y="486.14224"
- x="1197.8389"
- height="309.71277"
- width="333.75412"
- id="rect8075"
- style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- </g>
- </g>
- <g
- transform="translate(-174.03125,62.156036)"
- style="opacity:0.18000004;display:inline;enable-background:new"
- id="g8077">
- <g
- style="filter:url(#filter3785)"
- id="g8079">
- <path
- sodipodi:nodetypes="czzccccc"
- id="path8081"
- d="M 1094.2857,725.93361 C 1094.2857,725.93361 1093.9896,752.09452 1098.9285,763.79076 C 1103.8674,775.487 1118.9666,790.27741 1127.5,795.21933 C 1136.0334,800.16125 1146.4286,803.79075 1146.4286,803.79075 L 1264.2857,688.79075 L 1282.1429,613.07647 L 1185.7143,651.6479 L 1094.2857,725.93361 z"
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- transform="translate(174.03125,-62.156036)" />
- <rect
- y="486.14224"
- x="1197.8389"
- height="309.71277"
- width="333.75412"
- id="rect8083"
- style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- </g>
- </g>
- </g>
- <path
- transform="translate(450.03125,73.843964)"
- style="opacity:0.83300003;fill:#050505;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:15;stroke-linecap:butt;stroke-linejoin:miter;marker:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8225);enable-background:accumulate"
- d="M 1264.1875,605 C 1259.6964,605.73268 1256.0305,608.45509 1252.25,611.40625 C 1242.1687,619.27601 1224.0805,645.83149 1204.2188,661.875 C 1164.3514,694.07816 1100.2228,731.85201 1051.6562,752.96875 C 1003.0422,774.10613 921.11498,798.78676 877.34375,810.46875 C 833.94554,822.05121 762.29972,835.59982 709.09375,837 L 704.53125,837.125 L 702.53125,841.25 L 609.6875,1033.375 L 603.1875,1046.8438 L 617.84375,1044 C 617.84375,1044 705.11343,1027.3486 750.1875,1012.7188 C 794.9127,998.20213 865.97836,967.05197 923.21875,939.84375 C 980.82199,912.46306 1090.1551,847.86412 1137.5,810.375 C 1183.8608,773.66518 1215.3049,745.65818 1237.4375,720.125 C 1248.3386,707.549 1260.1823,692.59356 1268.4688,677.375 C 1276.7552,662.15644 1287.6285,633.15692 1282.1562,618.53125 C 1280.9385,615.27651 1279.6048,612.46995 1277.5625,610.03125 C 1275.5202,607.59255 1269.0878,608.45926 1269,605 C 1268.7902,596.73518 1265.6845,604.75577 1264.1875,605 z M 1266.3438,620.21875 C 1266.7586,620.80449 1267.3749,621.77641 1268.125,623.78125 C 1271.0218,631.52338 1266.6843,655.68 1259.3125,669.21875 C 1251.9407,682.7575 1236.6741,698.14269 1226.125,710.3125 C 1205.0496,734.62606 1174.2213,762.17406 1128.1875,798.625 C 1083.1379,834.29659 972.72717,899.71959 916.78125,926.3125 C 859.88952,953.35499 788.68509,984.4309 745.53125,998.4375 C 709.16634,1010.2406 649.68654,1022.2713 629.8125,1026.2188 L 714.09375,851.75 C 768.80066,849.7007 837.88634,836.53365 881.21875,824.96875 C 925.55297,813.1365 1007.2974,788.63242 1057.625,766.75 C 1107.737,744.96129 1170.1594,705.58184 1211.6562,672.0625 C 1232.3026,655.38529 1253.4011,629.51662 1261.4688,623.21875 C 1263.9058,621.31633 1265.5494,620.58295 1266.3438,620.21875 z"
- id="path8085"
- clip-path="url(#clipPath3722)"
- sodipodi:nodetypes="cssssccccccssssssssccssssssccssssc" />
- <g
- style="opacity:1;display:inline;enable-background:new"
- id="g8087"
- mask="url(#mask7704)"
- transform="matrix(0.9934486,0.1142802,-0.1142802,0.9934486,-9.24324,588.09054)"
- inkscape:transform-center-x="-185.09603"
- inkscape:transform-center-y="-12.859654">
- <path
- transform="translate(8.0045714e-2,-3.125e-2)"
- style="fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- d="M 1111.4062,-285.9375 L 1107.4688,-284.0625 C 1107.4283,-284.05228 1107.3692,-284.04201 1107.3438,-284.03125 C 1106.925,-283.8184 1107.1791,-283.93067 1106.6875,-283.71875 C 1106.2014,-283.50919 1104.9499,-283.13456 1102.5938,-282.25 C 1099.2626,-280.99942 1096.7895,-280.10016 1095.5938,-279.1875 C 1094.0576,-279.16623 1091.8733,-278.95419 1089.9375,-278.46875 C 1086.956,-277.72108 1085.0823,-277.29474 1083.1875,-276.875 C 1081.2927,-276.45527 1081.512,-276.23281 1080.3125,-276 C 1079.0159,-275.74833 1078.5911,-276.00899 1074.875,-275.21875 C 1071.3851,-274.4766 1065.9802,-273.28768 1064.7188,-272.53125 C 1063.1348,-272.71203 1060.8513,-272.85303 1058.875,-272.5625 C 1055.8346,-272.11554 1053.9588,-271.88974 1052.0312,-271.65625 C 1051.3758,-271.57687 1050.9902,-271.45547 1050.6875,-271.375 C 1050.2613,-271.24334 1050.0017,-271.11498 1049.3125,-271.03125 C 1048.0009,-270.87188 1047.5503,-271.18808 1043.7812,-270.75 C 1040.2273,-270.33691 1034.7758,-269.47718 1033.5312,-268.8125 C 1031.9322,-269.10979 1029.6735,-269.34669 1027.6875,-269.15625 C 1024.6287,-268.86293 1022.7155,-268.67226 1020.7812,-268.5 C 1018.847,-268.32773 1019.0926,-268.07763 1017.875,-267.96875 C 1016.5588,-267.85105 1016.1152,-268.13238 1012.3438,-267.71875 C 1008.8017,-267.3303 1003.3359,-266.50948 1002.0625,-265.84375 C 1000.4636,-266.13844 998.1753,-266.35076 996.1875,-266.15625 C 993.12921,-265.857 991.2463,-265.67601 989.3125,-265.5 C 988.65501,-265.44015 988.27245,-265.32144 987.96875,-265.25 C 987.54105,-265.13104 987.28525,-265.03193 986.59375,-264.96875 C 985.27775,-264.84849 984.834,-265.16363 981.0625,-264.75 C 977.50631,-264.35998 972.0569,-263.51084 970.8125,-262.84375 C 969.21381,-263.13793 966.95265,-263.36747 964.96875,-263.15625 C 961.91305,-262.83092 959.9947,-262.63001 958.0625,-262.4375 C 956.13031,-262.24499 956.37275,-261.99662 955.15625,-261.875 C 953.84137,-261.74353 953.3932,-262.03954 949.625,-261.59375 C 946.08611,-261.17509 940.6473,-260.30158 939.375,-259.625 C 937.77741,-259.90604 935.51505,-260.04543 933.53125,-259.8125 C 930.47927,-259.45413 928.58625,-259.24464 926.65625,-259.03125 C 926.00007,-258.95869 925.6156,-258.85856 925.3125,-258.78125 C 924.88571,-258.65402 924.6276,-258.51405 923.9375,-258.4375 C 922.62411,-258.29181 922.17015,-258.61152 918.40625,-258.125 C 914.85737,-257.66624 909.4276,-256.70598 908.1875,-256 C 906.59441,-256.24424 904.3537,-256.38135 902.375,-256.125 C 899.32741,-255.73018 897.4243,-255.47655 895.5,-255.21875 C 893.57571,-254.96096 893.7739,-254.72522 892.5625,-254.5625 C 891.25301,-254.3866 890.8153,-254.66688 887.0625,-254.09375 C 883.53821,-253.55551 878.1393,-252.39458 876.875,-251.65625 C 875.28751,-251.85979 873.0295,-251.91098 871.0625,-251.5625 C 868.03631,-251.02638 866.1636,-250.70081 864.25,-250.375 C 863.59941,-250.26423 863.2363,-250.10406 862.9375,-250 C 862.51681,-249.83512 862.27405,-249.6687 861.59375,-249.53125 C 860.29905,-249.26966 859.86665,-249.53745 856.15625,-248.71875 C 852.65777,-247.9468 847.31035,-246.33582 846.09375,-245.5 C 844.53085,-245.57745 842.33625,-245.41472 840.40625,-244.90625 C 837.43387,-244.12312 835.58855,-243.67416 833.71875,-243.15625 C 831.84875,-242.63835 832.0521,-242.38897 830.875,-242.0625 C 829.60251,-241.7096 829.17795,-241.95541 825.53125,-240.875 C 822.10657,-239.86037 816.88185,-237.94183 815.65625,-237.03125 C 814.11747,-237.01851 811.93645,-236.75903 810.03125,-236.15625 C 807.10027,-235.22891 805.2809,-234.69783 803.4375,-234.09375 C 802.81071,-233.88837 802.44585,-233.70117 802.15625,-233.5625 C 801.74867,-233.34889 801.50295,-233.15375 800.84375,-232.9375 C 799.58925,-232.52596 799.1576,-232.74846 795.5625,-231.5 C 792.17261,-230.32283 786.96755,-228.2863 785.78125,-227.34375 C 784.25737,-227.28408 782.1312,-226.94888 780.25,-226.28125 C 777.35261,-225.25296 775.55095,-224.60577 773.71875,-223.96875 C 771.88655,-223.33174 772.0909,-223.12021 770.9375,-222.71875 C 769.69071,-222.28479 769.27395,-222.51903 765.71875,-221.15625 C 762.38005,-219.87645 757.23165,-217.6737 756.03125,-216.6875 C 754.52407,-216.57981 752.39555,-216.1887 750.53125,-215.46875 C 747.66307,-214.36115 745.90735,-213.68719 744.09375,-213 C 743.47705,-212.76637 743.0973,-212.55797 742.8125,-212.40625 C 742.81251,-212.40625 742.8125,-212.37673 742.8125,-212.375 L 734.8125,-209.1875 L 722.3366,-205.69561 L 730.26626,-186.41789 C 729.67463,-184.44432 742.8125,-191.15625 742.8125,-191.15625 C 743.03891,-191.30093 743.26145,-191.42886 743.53125,-191.53125 C 744.61177,-191.94123 745.70285,-191.74702 749.53125,-193.21875 C 753.35977,-194.69049 754.7553,-195.22373 755.4375,-195.625 C 756.11711,-196.02478 757.04925,-196.50437 757.65625,-197.15625 C 759.48317,-197.294 761.22705,-197.64948 762.59375,-198.15625 C 765.56175,-199.25677 767.4691,-199.96244 769.375,-200.625 C 771.28081,-201.28754 771.72915,-202.03987 772.78125,-202.40625 C 773.87287,-202.78636 774.97635,-202.57163 778.84375,-203.9375 C 782.71115,-205.30336 784.1269,-205.76458 784.8125,-206.15625 C 785.51361,-206.55677 786.5133,-207.08923 787.125,-207.75 C 789.09581,-207.80466 790.94195,-208.13463 792.40625,-208.625 C 795.40777,-209.63008 797.3324,-210.24671 799.25,-210.875 C 800.78861,-211.3791 801.42415,-211.92177 802.15625,-212.3125 C 802.38647,-212.44681 802.63215,-212.56623 802.90625,-212.65625 C 804.00457,-213.01673 805.0877,-212.73762 809,-213.96875 C 812.91231,-215.19988 814.366,-215.6417 815.0625,-216 C 815.75641,-216.35697 816.6926,-216.79261 817.3125,-217.40625 C 819.17771,-217.42891 820.94835,-217.67308 822.34375,-218.09375 C 825.37415,-219.00729 827.33615,-219.52385 829.28125,-220.0625 C 831.22637,-220.60114 831.70745,-221.32702 832.78125,-221.625 C 833.89527,-221.93415 835.00125,-221.61761 838.96875,-222.65625 C 842.93625,-223.69488 844.38625,-224.08898 845.09375,-224.40625 C 845.82855,-224.73584 846.90765,-225.15997 847.53125,-225.78125 C 849.52907,-225.66525 851.3887,-225.80134 852.875,-226.15625 C 855.95311,-226.89125 857.9584,-227.25719 859.9375,-227.65625 C 861.52541,-227.97643 862.1818,-228.4468 862.9375,-228.75 C 863.17501,-228.8568 863.4044,-228.94276 863.6875,-229 C 864.82091,-229.22919 865.99215,-228.79107 870.03125,-229.5 C 874.07067,-230.20893 875.5315,-230.42709 876.25,-230.6875 C 876.96581,-230.94694 877.95435,-231.25474 878.59375,-231.78125 C 880.51795,-231.54176 882.34165,-231.55672 883.78125,-231.78125 C 886.90767,-232.26887 888.9358,-232.48192 890.9375,-232.75 C 892.93921,-233.01807 893.42625,-233.69514 894.53125,-233.84375 C 895.67767,-233.99793 896.8071,-233.54218 900.875,-234.0625 C 904.94281,-234.58282 906.43525,-234.75823 907.15625,-235 C 907.89337,-235.24714 908.95435,-235.58623 909.59375,-236.125 C 911.64375,-235.78947 913.56745,-235.72704 915.09375,-235.90625 C 918.23595,-236.27521 920.27375,-236.46561 922.28125,-236.6875 C 923.89207,-236.86552 924.5459,-237.2957 925.3125,-237.53125 C 925.55341,-237.61677 925.80655,-237.68685 926.09375,-237.71875 C 927.24345,-237.84647 928.39505,-237.3721 932.46875,-237.84375 C 936.54245,-238.3154 938.0278,-238.45435 938.75,-238.6875 C 939.46941,-238.91977 940.45025,-239.16096 941.09375,-239.65625 C 943.03005,-239.32279 944.8638,-239.25201 946.3125,-239.40625 C 949.45851,-239.7412 951.49,-239.92484 953.5,-240.125 C 955.50991,-240.32514 955.98415,-240.95139 957.09375,-241.0625 C 958.24485,-241.17778 959.39025,-240.69744 963.46875,-241.125 C 967.54725,-241.55256 969.05765,-241.68709 969.78125,-241.90625 C 970.52047,-242.13011 971.57685,-242.4195 972.21875,-242.9375 C 974.27575,-242.53883 976.2206,-242.4441 977.75,-242.59375 C 980.89871,-242.90185 982.9258,-243.067 984.9375,-243.25 C 986.55151,-243.39682 987.20055,-243.81055 987.96875,-244.03125 C 988.21005,-244.11211 988.4623,-244.16116 988.75,-244.1875 C 989.90211,-244.29295 991.0429,-243.79475 995.125,-244.1875 C 999.20711,-244.58025 1000.7139,-244.71834 1001.4375,-244.9375 C 1002.1584,-245.15583 1003.1371,-245.3852 1003.7812,-245.875 C 1005.7193,-245.52501 1007.5501,-245.42062 1009,-245.5625 C 1012.1487,-245.8706 1014.1758,-246.03575 1016.1875,-246.21875 C 1018.1991,-246.40174 1018.7017,-247.05677 1019.8125,-247.15625 C 1020.9648,-247.25948 1022.1047,-246.77142 1026.1875,-247.15625 C 1030.2704,-247.54107 1031.7762,-247.65725 1032.5,-247.875 C 1033.2393,-248.09743 1034.2956,-248.38949 1034.9375,-248.90625 C 1036.9949,-248.50448 1038.9404,-248.40292 1040.4688,-248.5625 C 1043.6153,-248.89102 1045.6458,-249.0852 1047.6562,-249.28125 C 1049.2692,-249.43854 1049.9219,-249.91273 1050.6875,-250.15625 C 1050.9282,-250.24429 1051.1507,-250.27762 1051.4375,-250.3125 C 1052.5858,-250.4522 1053.7542,-249.97259 1057.8125,-250.5625 C 1061.8708,-251.15242 1063.3743,-251.33964 1064.0938,-251.59375 C 1064.8104,-251.84691 1065.7684,-252.15182 1066.4062,-252.6875 C 1068.3259,-252.47556 1070.1262,-252.53609 1071.5625,-252.78125 C 1074.6816,-253.31365 1076.6741,-253.70986 1078.6562,-254.09375 C 1080.6383,-254.47762 1081.1305,-255.1334 1082.2188,-255.375 C 1083.3475,-255.62566 1084.489,-255.25871 1088.4688,-256.25 C 1092.4483,-257.24127 1093.8983,-257.6693 1094.5938,-258.03125 C 1095.316,-258.40725 1096.3555,-258.90183 1096.9688,-259.5625 C 1098.9317,-259.57454 1100.7625,-259.85355 1102.1875,-260.40625 C 1105.1387,-261.55085 1107.0607,-262.27567 1108.875,-263.15625 C 1110.3307,-263.86277 1111.1941,-264.85828 1111.4062,-265.15625 C 1111.6185,-265.4542 1111.5051,-265.8848 1111.5312,-265.90625 C 1111.5742,-265.94148 1111.8716,-266.00028 1112.0312,-266.34375 C 1112.8902,-268.19082 1114.3544,-271.97139 1114.4688,-272.65625 C 1114.5825,-273.33839 1114.6368,-274.00902 1114.6875,-274.40625 C 1114.7169,-274.63575 1114.5404,-275.28515 1114.5625,-275.34375 C 1114.5934,-275.42579 1114.8508,-275.59432 1114.9062,-275.84375 C 1115.1725,-277.04206 1114.9953,-278.05111 1114.7812,-279.46875 C 1114.5673,-280.88638 1113.8096,-284.08338 1113.1562,-284.9375 C 1112.4973,-285.79922 1111.9314,-285.94801 1111.4062,-285.9375 z"
- id="path8089"
- sodipodi:nodetypes="ccssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssscccccssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssssssssc" />
- <g
- clip-path="url(#clipPath7421)"
- id="g8091">
- <path
- id="path8093"
- d="M 1107.409,-284.04961 C 1106.9903,-283.83678 1107.2534,-283.95572 1106.7618,-283.7438 C 1106.2757,-283.53426 1105.0384,-283.16941 1102.6822,-282.28485 C 1099.3511,-281.03428 1096.852,-280.13141 1095.6563,-279.21875 C 1094.1202,-279.19749 1091.9358,-278.98544 1090,-278.5 C 1087.0185,-277.75234 1085.1448,-277.32599 1083.25,-276.90625 C 1081.3552,-276.48653 1081.5745,-276.26406 1080.375,-276.03125 C 1079.0784,-275.77959 1078.6536,-276.04024 1074.9375,-275.25 C 1071.4476,-274.50786 1066.0427,-273.31893 1064.7813,-272.5625 C 1063.1974,-272.74329 1060.9138,-272.88428 1058.9375,-272.59375 C 1055.8971,-272.1468 1054.0213,-271.92099 1052.0938,-271.6875 C 1051.4384,-271.60813 1051.0527,-271.48672 1050.75,-271.40625 C 1050.3238,-271.2746 1050.0642,-271.14623 1049.375,-271.0625 C 1048.0634,-270.90314 1047.6128,-271.21933 1043.8438,-270.78125 C 1040.2899,-270.36817 1034.8384,-269.50843 1033.5938,-268.84375 C 1031.9948,-269.14105 1029.736,-269.37794 1027.75,-269.1875 C 1024.6912,-268.89419 1022.778,-268.70351 1020.8438,-268.53125 C 1018.9095,-268.35899 1019.1551,-268.10888 1017.9375,-268 C 1016.6213,-267.88231 1016.1777,-268.16363 1012.4063,-267.75 C 1008.8644,-267.36156 1003.3984,-266.54073 1002.125,-265.875 C 1000.5261,-266.1697 998.23783,-266.38201 996.25,-266.1875 C 993.19176,-265.88826 991.30887,-265.70726 989.375,-265.53125 C 988.71751,-265.47141 988.33496,-265.35269 988.03125,-265.28125 C 987.6036,-265.1623 987.34774,-265.06318 986.65625,-265 C 985.34029,-264.87975 984.89649,-265.19488 981.125,-264.78125 C 977.56886,-264.39124 972.11946,-263.54209 970.875,-262.875 C 969.27637,-263.16919 967.01516,-263.39872 965.03125,-263.1875 C 961.97565,-262.86218 960.05721,-262.66126 958.125,-262.46875 C 956.19279,-262.27625 956.43513,-262.02787 955.21875,-261.90625 C 953.90387,-261.77479 953.45577,-262.07079 949.6875,-261.625 C 946.14863,-261.20635 940.70982,-260.33283 939.4375,-259.65625 C 937.83995,-259.9373 935.57754,-260.07668 933.59375,-259.84375 C 930.54177,-259.48539 928.64867,-259.27589 926.71875,-259.0625 C 926.06255,-258.98995 925.67809,-258.88981 925.375,-258.8125 C 924.94823,-258.68528 924.69009,-258.5453 924,-258.46875 C 922.68667,-258.32307 922.23254,-258.64277 918.46875,-258.15625 C 914.91986,-257.6975 909.49012,-256.73723 908.25,-256.03125 C 906.65695,-256.27549 904.41619,-256.4126 902.4375,-256.15625 C 899.38991,-255.76144 897.48679,-255.5078 895.5625,-255.25 C 893.63822,-254.99221 893.83639,-254.75647 892.625,-254.59375 C 891.31554,-254.41785 890.87781,-254.69813 887.125,-254.125 C 883.60071,-253.58676 878.20185,-252.42583 876.9375,-251.6875 C 875.35,-251.89104 873.092,-251.94223 871.125,-251.59375 C 868.09883,-251.05763 866.22611,-250.73206 864.3125,-250.40625 C 863.66189,-250.29548 863.29879,-250.13531 863,-250.03125 C 862.57933,-249.86637 862.33655,-249.69995 861.65625,-249.5625 C 860.3616,-249.30091 859.92913,-249.5687 856.21875,-248.75 C 852.72022,-247.97805 847.3728,-246.36707 846.15625,-245.53125 C 844.59347,-245.6087 842.39867,-245.44597 840.46875,-244.9375 C 837.49631,-244.15437 835.65114,-243.70541 833.78125,-243.1875 C 831.91137,-242.6696 832.11465,-242.42022 830.9375,-242.09375 C 829.66504,-241.74085 829.24047,-241.98666 825.59375,-240.90625 C 822.16905,-239.89162 816.94431,-237.97308 815.71875,-237.0625 C 814.17992,-237.04976 811.99892,-236.79028 810.09375,-236.1875 C 807.16269,-235.26016 805.34344,-234.72908 803.5,-234.125 C 802.87324,-233.91962 802.50827,-233.73242 802.21875,-233.59375 C 801.81112,-233.38014 801.56541,-233.185 800.90625,-232.96875 C 799.65179,-232.55721 799.22014,-232.77971 795.625,-231.53125 C 792.23515,-230.35408 787.03002,-228.31755 785.84375,-227.375 C 784.31986,-227.31533 782.1937,-226.98013 780.3125,-226.3125 C 777.41511,-225.28421 775.61342,-224.63702 773.78125,-224 C 771.94908,-223.36299 772.1534,-223.15146 771,-222.75 C 769.75322,-222.31604 769.33639,-222.55028 765.78125,-221.1875 C 762.44258,-219.9077 757.2941,-217.70495 756.09375,-216.71875 C 754.58657,-216.61106 752.45806,-216.21995 750.59375,-215.5 C 747.72557,-214.3924 745.96995,-213.71844 744.15625,-213.03125 C 743.53959,-212.79762 743.15984,-212.58922 742.875,-212.4375 C 742.875,-212.4375 742.875,-211.34375 742.875,-211.34375 C 742.98678,-211.56611 743.26099,-212.16118 743.78125,-212.4375 C 744.47922,-212.80822 748.59488,-214.43087 750.59375,-215.15625 C 752.25061,-215.7575 754.74764,-216.48493 756.5625,-216.46875 C 756.86412,-216.46606 757.15012,-216.41785 757.40625,-216.375 C 759.24874,-216.06675 764.875,-214.8125 764.875,-214.8125 C 764.87499,-214.8125 758.64151,-216.45925 757.84375,-216.65625 C 757.65296,-216.70336 757.30803,-216.72497 756.875,-216.71875 C 758.02046,-217.58846 761.636,-219.11226 764.21875,-220.15625 C 767.05697,-221.30352 767.33556,-221.40807 769.28125,-221.8125 C 771.28955,-222.22994 772.4375,-222.3125 772.4375,-222.3125 C 772.4375,-222.31249 772.35514,-222.91364 773.40625,-223.4375 C 774.11135,-223.78891 778.29327,-225.3299 780.3125,-226 C 782.2644,-226.64773 785.3699,-227.3585 787.1875,-227 C 789.05073,-226.6325 794.71875,-225.1875 794.71875,-225.1875 C 794.71876,-225.1875 788.43175,-227.05861 787.625,-227.28125 C 787.43208,-227.3345 787.09416,-227.36729 786.65625,-227.375 C 787.81459,-228.20788 791.45069,-229.57032 794.0625,-230.53125 C 796.93266,-231.58726 797.22984,-231.69305 799.1875,-232.0625 C 801.04099,-232.41229 802.04634,-232.48798 802.21875,-232.5 C 802.33235,-232.71724 802.5962,-233.31002 803.125,-233.5625 C 803.83444,-233.90124 808.05107,-235.27525 810.09375,-235.875 C 811.78692,-236.37211 814.33452,-236.91177 816.1875,-236.78125 C 816.49545,-236.75957 816.80099,-236.68399 817.0625,-236.625 C 818.94368,-236.20068 824.65625,-234.59375 824.65625,-234.59375 C 824.65626,-234.59375 818.31451,-236.659 817.5,-236.90625 C 817.30521,-236.96539 816.94212,-237.01019 816.5,-237.03125 C 817.66949,-237.8288 821.36302,-239.08747 824,-239.96875 C 826.89781,-240.93722 827.23301,-240.97207 829.21875,-241.25 C 831.2684,-241.53689 832.40625,-241.5625 832.40625,-241.5625 C 832.40623,-241.5625 832.3335,-242.16947 833.40625,-242.625 C 834.12585,-242.93057 838.39723,-244.12575 840.46875,-244.625 C 842.47119,-245.10758 845.66724,-245.55329 847.53125,-245.03125 C 849.44203,-244.4961 855.25,-242.53125 855.25,-242.53125 C 855.25,-242.53125 848.82734,-244.95476 848,-245.25 C 847.80216,-245.32061 847.41784,-245.39039 846.96875,-245.4375 C 848.15665,-246.16615 851.88402,-247.21158 854.5625,-247.9375 C 857.50592,-248.73525 857.85458,-248.70833 859.875,-248.84375 C 861.78789,-248.97198 862.82205,-248.91484 863,-248.90625 C 863.11728,-249.10991 863.39176,-249.68573 863.9375,-249.875 C 864.66969,-250.12894 869.01602,-250.92289 871.125,-251.25 C 872.87313,-251.52111 875.52588,-251.7347 877.4375,-251.34375 C 877.75516,-251.27879 878.04272,-251.15824 878.3125,-251.0625 C 880.25324,-250.37377 886.15625,-247.96875 886.15625,-247.96875 C 886.15626,-247.96875 879.62154,-250.91952 878.78125,-251.28125 C 878.58028,-251.36776 878.20612,-251.44804 877.75,-251.53125 C 878.9565,-252.16443 882.77956,-252.92685 885.5,-253.4375 C 888.48953,-253.99869 888.80023,-253.96704 890.84375,-253.96875 C 892.95301,-253.97052 894.15625,-253.84375 894.15625,-253.84375 C 894.15625,-253.84374 894.08354,-254.47494 895.1875,-254.78125 C 895.92802,-254.98672 900.31362,-255.61512 902.4375,-255.84375 C 904.49052,-256.06474 907.75613,-256.09597 909.65625,-255.375 C 911.60404,-254.63593 917.5,-252 917.5,-252 C 917.50002,-252 910.93712,-255.17897 910.09375,-255.5625 C 909.89207,-255.65423 909.55154,-255.74871 909.09375,-255.84375 C 910.30467,-256.44563 914.07817,-257.09259 916.8125,-257.5 C 919.8173,-257.94772 920.13801,-257.9517 922.1875,-257.90625 C 924.12795,-257.86323 925.19449,-257.71202 925.375,-257.6875 C 925.49392,-257.88066 925.7589,-258.45333 926.3125,-258.59375 C 927.05521,-258.78213 931.46679,-259.32803 933.59375,-259.53125 C 935.35678,-259.69967 938.01384,-259.76554 939.9375,-259.28125 C 940.25718,-259.20077 940.54101,-259.07766 940.8125,-258.96875 C 942.76543,-258.18526 948.71875,-255.5 948.71875,-255.5 C 948.71873,-255.5 942.12684,-258.75348 941.28125,-259.15625 C 941.07903,-259.25257 940.70899,-259.36328 940.25,-259.46875 C 941.46414,-260.04302 945.29366,-260.59094 948.03125,-260.96875 C 951.03963,-261.38395 951.35432,-261.41138 953.40625,-261.34375 C 955.52423,-261.27394 956.71875,-261.09375 956.71875,-261.09375 C 956.71873,-261.09375 956.6415,-261.73116 957.75,-262 C 958.49362,-262.18035 962.90176,-262.66355 965.03125,-262.84375 C 967.08972,-263.01792 970.37449,-262.96807 972.28125,-262.1875 C 974.23584,-261.38734 980.15625,-258.65625 980.15625,-258.65625 C 980.15623,-258.65625 973.59632,-261.96501 972.75,-262.375 C 972.54763,-262.47305 972.17814,-262.5781 971.71875,-262.6875 C 972.93392,-263.2514 976.72883,-263.8018 979.46875,-264.15625 C 982.47966,-264.54577 982.79006,-264.5539 984.84375,-264.46875 C 986.78814,-264.38815 987.85038,-264.21551 988.03125,-264.1875 C 988.15041,-264.37836 988.41402,-264.93281 988.96875,-265.0625 C 989.71301,-265.2365 994.11868,-265.71297 996.25,-265.875 C 998.01662,-266.00927 1000.6997,-266.00071 1002.625,-265.5 C 1002.945,-265.41679 1003.2283,-265.29873 1003.5,-265.1875 C 1005.4546,-264.38734 1011.4063,-261.625 1011.4063,-261.625 C 1011.4062,-261.625 1004.8151,-264.96501 1003.9688,-265.375 C 1003.7664,-265.47305 1003.3969,-265.57811 1002.9375,-265.6875 C 1004.1526,-266.2514 1007.9788,-266.77056 1010.7188,-267.125 C 1013.7297,-267.51453 1014.0713,-267.5539 1016.125,-267.46875 C 1018.2447,-267.38087 1019.4375,-267.15625 1019.4375,-267.15625 C 1019.4375,-267.15625 1019.3591,-267.80527 1020.4688,-268.0625 C 1021.2131,-268.23506 1025.6183,-268.68586 1027.75,-268.84375 C 1029.8106,-268.99635 1033.0929,-268.94052 1035,-268.15625 C 1036.955,-267.3523 1042.875,-264.65625 1042.875,-264.65625 C 1042.875,-264.65625 1036.3152,-267.93212 1035.4688,-268.34375 C 1035.2663,-268.44219 1034.897,-268.54597 1034.4375,-268.65625 C 1035.6529,-269.21779 1039.4494,-269.78403 1042.1875,-270.15625 C 1045.1965,-270.5653 1045.5102,-270.57183 1047.5625,-270.5 C 1049.5056,-270.43201 1050.5697,-270.33515 1050.75,-270.3125 C 1050.8688,-270.5069 1051.1346,-271.04131 1051.6875,-271.1875 C 1052.4293,-271.38362 1056.8186,-272.01628 1058.9375,-272.28125 C 1060.6939,-272.50086 1063.3428,-272.61356 1065.25,-272.25 C 1065.5669,-272.18959 1065.8558,-272.06062 1066.125,-271.96875 C 1068.0612,-271.30783 1073.9688,-269.03125 1073.9688,-269.03125 C 1073.9687,-269.03125 1067.4321,-271.8378 1066.5938,-272.1875 C 1066.3933,-272.27113 1066.0176,-272.36083 1065.5625,-272.4375 C 1066.7662,-273.08796 1070.5816,-273.80945 1073.2813,-274.4375 C 1076.248,-275.1277 1076.5702,-275.19257 1078.5938,-275.3125 C 1080.6824,-275.4363 1081.875,-275.34375 1081.875,-275.34375 C 1081.875,-275.34374 1081.788,-275.9758 1082.875,-276.375 C 1083.6042,-276.6428 1087.9222,-277.71297 1090,-278.1875 C 1092.0085,-278.64619 1095.1679,-279.2168 1097,-278.8125 C 1098.8781,-278.39804 1110.5782,-275.79687 1110.5782,-275.79687 C 1110.5782,-275.79687 1098.2507,-278.81953 1097.4375,-279.0625 C 1097.243,-279.12062 1096.8789,-279.16876 1096.4375,-279.1875 C 1097.6051,-279.99119 1099.9517,-280.8748 1102.5469,-281.89062 C 1104.2283,-282.5488 1103.4706,-282.26721 1105.3228,-282.89422 C 1107.0764,-283.48788 1107.8082,-283.90493 1107.9532,-284.00721 C 1108.2993,-284.21372 1107.5972,-284.12909 1107.409,-284.04961 z"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7001);enable-background:new"
- sodipodi:nodetypes="czscsssscssssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssccsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscc" />
- <path
- id="path8095"
- d="M 1082.625,-275.125 C 1084.498,-274.73152 1087.1211,-273.97945 1088.6563,-273.15625 C 1090.1915,-272.33306 1091.4785,-272.10025 1094.0313,-270.65625 C 1096.5579,-269.22699 1098.8271,-268.64929 1101,-268.125 C 1103.3476,-267.55858 1106.4354,-267.40977 1109.8438,-266.9375 C 1108.7549,-267.77725 1103.2364,-268.10995 1101.4375,-268.5 C 1099.6386,-268.89006 1097.5434,-269.51616 1094.8438,-270.8125 C 1092.1441,-272.10884 1091.3494,-272.61146 1089.0313,-273.5 C 1086.7131,-274.38854 1085.0269,-274.88314 1082.625,-275.125 z"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6949);enable-background:new" />
- <path
- id="path8097"
- d="M 1051.4688,-270 C 1053.3741,-269.42241 1055.9969,-268.38428 1057.5625,-267.40625 C 1059.1281,-266.42823 1060.4427,-266.04644 1063.0625,-264.28125 C 1065.6555,-262.53409 1068.0484,-261.57198 1070.3125,-260.6875 C 1072.7586,-259.73193 1075.9951,-259.03037 1079.7188,-257.625 C 1078.5292,-258.76284 1072.6557,-260.31175 1070.7813,-261 C 1068.9068,-261.68825 1066.6995,-262.5662 1063.9063,-264.28125 C 1061.113,-265.99629 1060.3327,-266.56515 1057.9688,-267.6875 C 1055.6047,-268.80984 1053.9121,-269.52205 1051.4688,-270 z"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6961);enable-background:new" />
- <path
- id="path8099"
- d="M 1020.2188,-266.84375 C 1022.1307,-266.20564 1024.8,-265.08839 1026.375,-264.03125 C 1027.9501,-262.9741 1029.2706,-262.52258 1031.9063,-260.625 C 1034.5149,-258.74679 1036.9347,-257.59497 1039.2188,-256.5625 C 1041.6865,-255.44705 1044.9833,-254.3892 1048.75,-252.71875 C 1047.5467,-253.94128 1041.5472,-256.03298 1039.6563,-256.84375 C 1037.7653,-257.65452 1035.5914,-258.73754 1032.7813,-260.59375 C 1029.9711,-262.44995 1029.1595,-263.07068 1026.7813,-264.3125 C 1024.403,-265.5543 1022.6706,-266.28819 1020.2188,-266.84375 z"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6957);enable-background:new" />
- <path
- id="path8101"
- d="M 1110.1719,-266.89063 C 1110.3227,-266.84207 1110.8599,-266.25963 1110.2813,-265.40625 C 1109.4712,-264.21166 1104.5764,-262.08196 1101.7188,-261.28125 C 1098.8739,-260.48413 1095.4287,-260.30351 1091.1563,-261.65625 C 1086.8547,-263.0182 1085.6866,-264.12497 1080.5,-265.96875 C 1085.164,-263.85358 1086.6953,-262.01642 1090.625,-260.625 C 1092.2457,-260.05113 1093.9921,-259.6854 1095.6875,-259.59375 C 1095.2424,-259.26812 1094.1572,-258.61045 1092.125,-258 C 1089.3295,-257.16031 1085.4759,-256.46622 1083.875,-256.375 C 1082.3604,-256.28868 1080.733,-256.88749 1080.4375,-257 C 1080.6042,-256.89692 1080.8107,-256.62266 1080.1875,-255.96875 C 1079.2882,-255.02512 1074.0401,-254.04575 1071.0625,-253.71875 C 1068.0982,-253.3932 1064.5409,-253.73471 1060.1563,-255.625 C 1056.1783,-257.33997 1054.8173,-258.54036 1050.75,-260.375 C 1050.75,-260.375 1050.75,-260.21875 1050.75,-260.21875 C 1054.3931,-258.12346 1056.034,-256.33548 1059.625,-254.65625 C 1061.3552,-253.84716 1063.2167,-253.24749 1065.0313,-252.9375 C 1064.4964,-252.65074 1063.4735,-252.22599 1061.5938,-251.90625 C 1058.7248,-251.41829 1054.7848,-251.09011 1053.1563,-251.15625 C 1052.3056,-251.19079 1051.4277,-251.34062 1050.75,-251.5625 C 1050.0652,-251.77738 1049.5603,-252.00717 1049.4375,-252.0625 C 1049.6069,-251.95529 1049.8686,-251.65962 1049.2188,-251.03125 C 1048.3091,-250.15163 1042.9727,-249.69487 1039.9688,-249.5625 C 1036.9783,-249.43071 1033.3799,-250.01313 1028.9688,-252.125 C 1024.5276,-254.25126 1023.3273,-255.5266 1018.0625,-257.90625 C 1022.7968,-255.30921 1024.349,-253.27715 1028.4063,-251.1875 C 1030.0796,-250.32565 1031.8915,-249.69325 1033.6563,-249.25 C 1033.193,-249.01668 1032.0669,-248.56186 1029.9688,-248.3125 C 1027.0825,-247.96952 1023.1342,-247.81962 1021.5,-247.9375 C 1019.9538,-248.049 1018.2688,-248.79446 1017.9688,-248.9375 C 1018.1379,-248.81721 1018.3826,-248.52702 1017.75,-247.9375 C 1016.8372,-247.08677 1011.5059,-246.67538 1008.5,-246.5625 C 1005.5075,-246.45013 1001.9103,-247.05293 997.5,-249.15625 C 993.49875,-251.06448 992.11197,-252.29408 988.03125,-254.25 C 988.03122,-254.25 988.03125,-254.09375 988.03125,-254.09375 C 991.68631,-251.88983 993.32546,-250.0412 996.9375,-248.1875 C 998.67779,-247.29435 1000.5745,-246.65923 1002.4063,-246.21875 C 1001.8663,-245.97045 1000.8282,-245.60342 998.9375,-245.375 C 996.05182,-245.02642 992.07145,-244.85405 990.4375,-244.96875 C 989.58405,-245.02865 988.71119,-245.22666 988.03125,-245.46875 C 987.34415,-245.70405 986.8419,-245.94101 986.71875,-246 C 986.88873,-245.88773 987.18323,-245.57775 986.53125,-244.96875 C 985.6186,-244.11625 980.25592,-243.67538 977.25,-243.5625 C 974.25754,-243.45013 970.65654,-244.09055 966.25,-246.15625 C 961.81347,-248.23603 960.60312,-249.48796 955.34375,-251.8125 C 960.07313,-249.26501 961.63449,-247.2347 965.6875,-245.1875 C 967.35905,-244.34317 969.17304,-243.72107 970.9375,-243.28125 C 970.47427,-243.04703 969.3478,-242.59718 967.25,-242.34375 C 964.36431,-241.99517 960.4138,-241.77423 958.78125,-241.875 C 957.23669,-241.97032 955.58094,-242.70385 955.28125,-242.84375 C 955.45024,-242.72522 955.66317,-242.4399 955.03125,-241.84375 C 954.11939,-240.98347 948.7846,-240.5135 945.78125,-240.375 C 942.7913,-240.2371 939.2138,-240.82568 934.8125,-242.84375 C 930.81942,-244.67464 929.44739,-245.87295 925.375,-247.75 C 925.37498,-247.75 925.375,-247.59375 925.375,-247.59375 C 929.02261,-245.46048 930.64533,-243.65888 934.25,-241.875 C 935.98675,-241.01549 937.85727,-240.42486 939.6875,-240 C 939.14803,-239.7471 938.13687,-239.35871 936.25,-239.09375 C 933.37022,-238.68939 929.41187,-238.44813 927.78125,-238.53125 C 926.92953,-238.57466 926.05355,-238.7398 925.375,-238.96875 C 924.68931,-239.19076 924.1854,-239.41214 924.0625,-239.46875 C 924.23209,-239.35976 924.4944,-239.0591 923.84375,-238.4375 C 922.93296,-237.56736 917.59354,-237.04598 914.59375,-236.875 C 911.60742,-236.70479 908.01994,-237.19077 903.625,-239.15625 C 899.20011,-241.13513 898.01904,-242.38444 892.78125,-244.53125 C 897.49122,-242.14358 899.05142,-240.14252 903.09375,-238.1875 C 904.7609,-237.38119 906.55418,-236.79092 908.3125,-236.40625 C 907.85087,-236.15755 906.7155,-235.694 904.625,-235.375 C 901.7494,-234.93624 897.8446,-234.6419 896.21875,-234.6875 C 894.68052,-234.73062 892.98595,-235.43272 892.6875,-235.5625 C 892.85583,-235.44968 893.09807,-235.14875 892.46875,-234.53125 C 891.56063,-233.64015 886.2658,-233.003 883.28125,-232.71875 C 880.31007,-232.43577 876.70783,-232.89455 872.34375,-234.65625 C 868.38441,-236.25456 867.0146,-237.45112 863,-238.96875 C 863.00003,-238.96875 863,-238.8125 863,-238.8125 C 866.5959,-237.00115 868.23831,-235.23017 871.8125,-233.65625 C 873.53457,-232.8979 875.39998,-232.3673 877.21875,-232.03125 C 876.68266,-231.75217 875.65217,-231.34362 873.78125,-230.96875 C 870.92586,-230.39665 866.99183,-229.94936 865.375,-229.9375 C 864.53049,-229.93129 863.66892,-230.01844 863,-230.1875 C 862.32409,-230.34901 861.83991,-230.51673 861.71875,-230.5625 C 861.88597,-230.46848 862.14142,-230.17902 861.5,-229.5 C 860.60213,-228.54948 855.31352,-227.58292 852.375,-227.0625 C 849.44966,-226.54441 845.94285,-226.68826 841.65625,-228.09375 C 837.34045,-229.50882 836.18348,-230.62369 831.09375,-232.0625 C 835.6706,-230.31149 837.1823,-228.50244 841.125,-227.0625 C 842.75108,-226.46861 844.49385,-226.10685 846.21875,-225.90625 C 845.7659,-225.60923 844.66397,-225.02286 842.625,-224.4375 C 839.82028,-223.63233 835.98614,-222.86167 834.40625,-222.6875 C 832.9115,-222.5227 831.29002,-223.00431 831,-223.09375 C 831.16356,-223.00368 831.39278,-222.73382 830.78125,-222.03125 C 829.89878,-221.0174 824.73673,-219.6596 821.84375,-218.96875 C 818.96373,-218.28097 815.50815,-218.20873 811.28125,-219.40625 C 807.4464,-220.4927 806.10867,-221.47862 802.21875,-222.53125 C 802.21874,-222.53125 802.21875,-222.375 802.21875,-222.375 C 805.70293,-220.98015 807.28816,-219.4556 810.75,-218.34375 C 812.41793,-217.80803 814.20578,-217.55701 815.96875,-217.46875 C 815.44911,-217.11663 814.46836,-216.55423 812.65625,-215.9375 C 809.89059,-214.99625 806.06601,-214.00213 804.5,-213.78125 C 803.68206,-213.66586 802.8669,-213.65842 802.21875,-213.75 C 801.56379,-213.83321 801.08615,-213.96827 800.96875,-214 C 801.13079,-213.92536 801.40274,-213.65956 800.78125,-212.90625 C 799.91125,-211.85172 794.77162,-210.247 791.90625,-209.46875 C 789.05372,-208.69399 785.64713,-208.51055 781.46875,-209.5625 C 777.26192,-210.62163 776.11206,-211.60416 771.125,-212.71875 C 775.60954,-211.25929 777.09435,-209.58352 780.9375,-208.46875 C 782.52254,-208.00898 784.22429,-207.8305 785.90625,-207.78125 C 785.46468,-207.44449 784.39374,-206.75352 782.40625,-206 C 779.67232,-204.96351 775.95427,-203.83731 774.40625,-203.5625 C 772.94163,-203.30248 771.34667,-203.67904 771.0625,-203.75 C 771.22275,-203.67035 771.44294,-203.42902 770.84375,-202.6875 C 769.97909,-201.61744 764.92723,-199.86935 762.09375,-199 C 759.27295,-198.13453 755.88625,-197.84369 751.75,-198.78125 C 747.99741,-199.63186 746.70215,-200.49772 742.875,-201.375 C 742.875,-201.375 742.875,-201.21875 742.875,-201.21875 C 746.30296,-199.98096 747.86241,-198.58645 751.25,-197.6875 C 752.88216,-197.25436 754.61704,-197.10449 756.34375,-197.125 C 755.83482,-196.74083 754.867,-196.10318 753.09375,-195.375 C 750.38741,-194.26366 746.65742,-193.06719 745.125,-192.75 C 744.3246,-192.58431 743.51269,-192.53138 742.875,-192.59375 C 742.875,-192.59375 742.875,-192.07823 742.875,-191.67146 C 742.875,-191.40639 742.875,-191.1875 742.875,-191.1875 C 743.10145,-191.33218 743.32391,-191.46011 743.59375,-191.5625 C 744.67427,-191.97248 745.76536,-191.77827 749.59375,-193.25 C 753.42218,-194.72174 754.81787,-195.25498 755.5,-195.65625 C 756.1796,-196.05603 757.11165,-196.53562 757.71875,-197.1875 C 759.5456,-197.32525 761.2895,-197.68073 762.65625,-198.1875 C 765.62437,-199.28802 767.53162,-199.99369 769.4375,-200.65625 C 771.34336,-201.31879 771.79159,-202.07112 772.84375,-202.4375 C 773.9353,-202.81761 775.03886,-202.60288 778.90625,-203.96875 C 782.7737,-205.33461 784.18941,-205.79583 784.875,-206.1875 C 785.57609,-206.58802 786.57581,-207.12048 787.1875,-207.78125 C 789.1583,-207.83591 791.00435,-208.16588 792.46875,-208.65625 C 795.47023,-209.66133 797.3949,-210.27796 799.3125,-210.90625 C 800.8511,-211.41035 801.48652,-211.95302 802.21875,-212.34375 C 802.44891,-212.47806 802.69449,-212.59748 802.96875,-212.6875 C 804.06698,-213.04798 805.1502,-212.76887 809.0625,-214 C 812.97483,-215.23113 814.42855,-215.67295 815.125,-216.03125 C 815.81888,-216.38822 816.75515,-216.82386 817.375,-217.4375 C 819.24021,-217.46016 821.01081,-217.70433 822.40625,-218.125 C 825.43668,-219.03854 827.39863,-219.5551 829.34375,-220.09375 C 831.28886,-220.63239 831.76993,-221.35827 832.84375,-221.65625 C 833.95776,-221.9654 835.06369,-221.64886 839.03125,-222.6875 C 842.99886,-223.72613 844.44883,-224.12023 845.15625,-224.4375 C 845.89112,-224.76709 846.97008,-225.19122 847.59375,-225.8125 C 849.59149,-225.6965 851.45118,-225.83259 852.9375,-226.1875 C 856.01561,-226.9225 858.02094,-227.28844 860,-227.6875 C 861.58792,-228.00768 862.24429,-228.47805 863,-228.78125 C 863.23757,-228.88805 863.46695,-228.97401 863.75,-229.03125 C 864.88347,-229.26044 866.05448,-228.82232 870.09375,-229.53125 C 874.13308,-230.24018 875.594,-230.45834 876.3125,-230.71875 C 877.02836,-230.97819 878.01678,-231.28599 878.65625,-231.8125 C 880.58052,-231.57301 882.40413,-231.58797 883.84375,-231.8125 C 886.97008,-232.30012 888.9983,-232.51317 891,-232.78125 C 893.00171,-233.04932 893.48869,-233.72639 894.59375,-233.875 C 895.74014,-234.02918 896.86967,-233.57343 900.9375,-234.09375 C 905.00534,-234.61407 906.49763,-234.78948 907.21875,-235.03125 C 907.95585,-235.27839 909.01684,-235.61748 909.65625,-236.15625 C 911.70632,-235.82072 913.63003,-235.75829 915.15625,-235.9375 C 918.29856,-236.30646 920.33619,-236.49686 922.34375,-236.71875 C 923.95451,-236.89677 924.60842,-237.32695 925.375,-237.5625 C 925.61594,-237.64802 925.86912,-237.7181 926.15625,-237.75 C 927.30603,-237.87772 928.45754,-237.40335 932.53125,-237.875 C 936.60499,-238.34665 938.09034,-238.4856 938.8125,-238.71875 C 939.53196,-238.95102 940.51274,-239.19221 941.15625,-239.6875 C 943.09262,-239.35404 944.92631,-239.28326 946.375,-239.4375 C 949.52102,-239.77245 951.55256,-239.95609 953.5625,-240.15625 C 955.57246,-240.35639 956.04664,-240.98264 957.15625,-241.09375 C 958.30739,-241.20903 959.45268,-240.72869 963.53125,-241.15625 C 967.60986,-241.58381 969.12011,-241.71834 969.84375,-241.9375 C 970.5829,-242.16136 971.63947,-242.45075 972.28125,-242.96875 C 974.33835,-242.57008 976.28312,-242.47535 977.8125,-242.625 C 980.96123,-242.9331 982.98834,-243.09825 985,-243.28125 C 986.61407,-243.42807 987.2631,-243.8418 988.03125,-244.0625 C 988.27267,-244.14336 988.52478,-244.19241 988.8125,-244.21875 C 989.96461,-244.3242 991.10546,-243.826 995.1875,-244.21875 C 999.26958,-244.6115 1000.7764,-244.74959 1001.5,-244.96875 C 1002.2209,-245.18708 1003.1997,-245.41645 1003.8438,-245.90625 C 1005.7818,-245.55626 1007.6126,-245.45187 1009.0625,-245.59375 C 1012.2112,-245.90185 1014.2383,-246.067 1016.25,-246.25 C 1018.2616,-246.43299 1018.7642,-247.08802 1019.875,-247.1875 C 1021.0273,-247.29073 1022.1672,-246.80267 1026.25,-247.1875 C 1030.3329,-247.57232 1031.8387,-247.6885 1032.5625,-247.90625 C 1033.3018,-248.12868 1034.3581,-248.42074 1035,-248.9375 C 1037.0574,-248.53573 1039.0029,-248.43417 1040.5313,-248.59375 C 1043.6779,-248.92227 1045.7084,-249.11645 1047.7188,-249.3125 C 1049.3318,-249.46979 1049.9844,-249.94398 1050.75,-250.1875 C 1050.9907,-250.27554 1051.2132,-250.30887 1051.5,-250.34375 C 1052.6483,-250.48345 1053.8167,-250.00384 1057.875,-250.59375 C 1061.9333,-251.18367 1063.4368,-251.37089 1064.1563,-251.625 C 1064.873,-251.87816 1065.8308,-252.18307 1066.4688,-252.71875 C 1068.3885,-252.50681 1070.1887,-252.56734 1071.625,-252.8125 C 1074.7441,-253.3449 1076.7366,-253.74111 1078.7188,-254.125 C 1080.7009,-254.50887 1081.1931,-255.16465 1082.2813,-255.40625 C 1083.4101,-255.65691 1084.5516,-255.28996 1088.5313,-256.28125 C 1092.5109,-257.27253 1093.9609,-257.70055 1094.6563,-258.0625 C 1095.3786,-258.43851 1096.4182,-258.93308 1097.0313,-259.59375 C 1098.9943,-259.6058 1100.825,-259.8848 1102.25,-260.4375 C 1105.2012,-261.58211 1107.1232,-262.30692 1108.9375,-263.1875 C 1110.3932,-263.89403 1111.2723,-264.87391 1111.4844,-265.17188 C 1111.6966,-265.46984 1111.5962,-265.91718 1111.6223,-265.93863 C 1111.6652,-265.97387 1111.9416,-266.0236 1112.1013,-266.36707 C 1112.9602,-268.21415 1114.4223,-272.01166 1114.5365,-272.69652 C 1114.6502,-273.37868 1114.7003,-274.04426 1114.751,-274.44149 C 1114.7804,-274.67101 1114.6043,-275.30693 1114.6264,-275.36553 C 1114.6573,-275.44759 1114.9309,-275.63081 1114.9863,-275.88024 C 1115.2526,-277.07857 1115.0752,-278.07153 1114.8612,-279.48917 C 1114.6472,-280.90681 1113.8775,-284.11131 1113.2243,-284.96543 C 1112.5654,-285.82715 1112.0014,-285.9766 1111.4764,-285.96609 C 1111.2678,-285.69633 1111.6132,-285.703 1111.639,-285.65348 C 1112.3196,-285.60269 1112.573,-285.28484 1113.0582,-284.75686 C 1113.5434,-284.22888 1114.501,-280.8173 1114.6376,-279.36691 C 1114.7742,-277.91652 1114.8276,-276.50671 1114.5496,-275.89827 C 1114.2715,-275.28982 1113.6054,-275.46963 1113.313,-275.40375 C 1113.844,-275.21786 1114.2038,-275.19053 1114.2654,-274.34607 C 1114.3247,-273.53269 1114.1322,-272.70638 1113.7456,-271.54045 C 1113.3544,-270.36044 1111.9004,-267.19047 1111.4599,-266.94168 C 1111.0076,-266.68617 1110.5075,-266.75969 1110.1719,-266.89063 z"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6997);enable-background:new"
- sodipodi:nodetypes="cssscscsscsssccscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssccscsscscssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsszsszssszzcczzzczzzc" />
- <path
- id="path8103"
- d="M 988.75,-263.84375 C 990.66161,-263.20935 993.30027,-262.08534 994.875,-261.03125 C 996.44977,-259.97716 997.7711,-259.54873 1000.4063,-257.65625 C 1003.0145,-255.78311 1005.4332,-254.64103 1007.7188,-253.59375 C 1010.1881,-252.46228 1013.4709,-251.43901 1017.25,-249.65625 C 1016.0428,-250.91465 1010.111,-253.0207 1008.2188,-253.84375 C 1006.3266,-254.66679 1004.0908,-255.77424 1001.2813,-257.625 C 998.47169,-259.47575 997.65906,-260.10654 995.28125,-261.34375 C 992.90343,-262.58094 991.20137,-263.29295 988.75,-263.84375 z"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6953);enable-background:new" />
- <path
- id="path8105"
- d="M 957.5,-260.78125 C 959.41,-260.16315 962.08288,-259.07191 963.65625,-258.03125 C 965.22964,-256.99059 966.55233,-256.54873 969.1875,-254.65625 C 971.79573,-252.7831 974.21442,-251.64104 976.5,-250.59375 C 978.96931,-249.46228 982.25213,-248.439 986.03125,-246.65625 C 984.82397,-247.91465 978.82971,-250.05195 976.9375,-250.875 C 975.04533,-251.69804 972.84084,-252.8055 970.03125,-254.65625 C 967.22167,-256.507 966.4383,-257.09557 964.0625,-258.3125 C 961.68672,-259.52941 959.94929,-260.25135 957.5,-260.78125 z"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6993);enable-background:new" />
- <path
- id="path8107"
- d="M 926.09375,-257.375 C 928.00147,-256.77755 930.64723,-255.71116 932.21875,-254.6875 C 933.79025,-253.66385 935.08897,-253.24779 937.71875,-251.40625 C 940.32166,-249.58352 942.74762,-248.43405 945.03125,-247.40625 C 947.49845,-246.29584 950.7866,-245.31302 954.5625,-243.5625 C 953.35627,-244.8106 947.3906,-246.88059 945.5,-247.6875 C 943.60942,-248.4944 941.39758,-249.57854 938.59375,-251.375 C 935.7899,-253.17144 934.96671,-253.77751 932.59375,-254.96875 C 930.22078,-256.15999 928.54013,-256.87158 926.09375,-257.375 z"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6989);enable-background:new" />
- <path
- id="path8109"
- d="M 894.90625,-253.5625 C 896.80838,-253.00895 899.49326,-251.97363 901.0625,-250.96875 C 902.63173,-249.96388 903.93651,-249.56011 906.5625,-247.75 C 909.16162,-245.95836 911.56284,-244.87811 913.84375,-243.875 C 916.30803,-242.79126 919.60359,-241.83471 923.375,-240.125 C 922.1702,-241.36007 916.20084,-243.36978 914.3125,-244.15625 C 912.42418,-244.94272 910.2373,-245.98705 907.4375,-247.75 C 904.63773,-249.51294 903.83831,-250.11836 901.46875,-251.28125 C 899.09918,-252.44413 897.3455,-253.11537 894.90625,-253.5625 z"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6985);enable-background:new" />
- <path
- id="path8111"
- d="M 863.71875,-248.65625 C 865.59937,-248.22716 868.22302,-247.27587 869.78125,-246.34375 C 871.33948,-245.41164 872.63358,-245.08599 875.25,-243.34375 C 877.83971,-241.61931 880.23067,-240.63573 882.5,-239.71875 C 884.95176,-238.72806 888.23959,-237.84168 892,-236.21875 C 890.79869,-237.42609 884.84751,-239.28484 882.96875,-240 C 881.09,-240.71517 878.88335,-241.68442 876.09375,-243.375 C 873.30412,-245.06557 872.50914,-245.60322 870.15625,-246.65625 C 867.80333,-247.70926 866.13041,-248.36873 863.71875,-248.65625 z"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6965);enable-background:new" />
- <path
- id="path8113"
- d="M 833.15625,-241.375 C 835.00461,-241.07856 837.6257,-240.39868 839.15625,-239.59375 C 840.68683,-238.78882 841.96999,-238.53802 844.53125,-237.0625 C 847.06629,-235.60204 849.42193,-234.73741 851.65625,-234 C 854.07024,-233.20332 857.31336,-232.53311 861.03125,-231.15625 C 859.84354,-232.28498 853.94353,-233.746 852.09375,-234.3125 C 850.24398,-234.879 848.09033,-235.68642 845.34375,-237.15625 C 842.59718,-238.62608 841.84239,-239.07653 839.53125,-239.9375 C 837.2201,-240.79845 835.52654,-241.25759 833.15625,-241.375 z"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6981);enable-background:new" />
- <path
- id="path8115"
- d="M 802.90625,-232.3125 C 804.72845,-232.10123 807.27201,-231.51193 808.78125,-230.78125 C 810.2905,-230.05059 811.53693,-229.85127 814.0625,-228.5 C 816.56226,-227.16254 818.89404,-226.45157 821.09375,-225.84375 C 823.47028,-225.18708 826.65839,-224.77087 830.3125,-223.65625 C 829.14515,-224.70121 823.38362,-225.75954 821.5625,-226.21875 C 819.74139,-226.67796 817.61025,-227.34571 814.90625,-228.65625 C 812.20222,-229.96677 811.43519,-230.37615 809.15625,-231.125 C 806.8773,-231.87383 805.243,-232.30431 802.90625,-232.3125 z"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6977);enable-background:new" />
- <path
- id="path8117"
- d="M 773.1875,-222.1875 C 774.99859,-222.0088 777.50809,-221.52244 779,-220.84375 C 780.49194,-220.16506 781.7534,-220.04553 784.25,-218.78125 C 786.72107,-217.52987 789.04005,-216.88511 791.21875,-216.34375 C 793.57262,-215.75887 796.71009,-215.44623 800.3125,-214.5 C 799.16166,-215.49116 793.45999,-216.2833 791.65625,-216.6875 C 789.85253,-217.0917 787.74072,-217.70866 785.0625,-218.9375 C 782.38432,-220.16634 781.65905,-220.54839 779.40625,-221.21875 C 777.15346,-221.88909 775.50998,-222.22107 773.1875,-222.1875 z"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6973);enable-background:new" />
- <path
- id="path8119"
- d="M 743.5625,-211.1875 C 745.35531,-211.05839 747.83563,-210.63785 749.3125,-210 C 750.7894,-209.36215 752.0286,-209.25844 754.5,-208.0625 C 756.94618,-206.87878 759.22054,-206.31584 761.375,-205.84375 C 763.70267,-205.33372 766.7946,-205.16311 770.375,-204.28125 C 769.23121,-205.25185 763.62741,-205.8719 761.84375,-206.21875 C 760.06008,-206.56559 757.9609,-207.10631 755.3125,-208.25 C 752.66409,-209.39368 751.91755,-209.76631 749.6875,-210.375 C 747.45742,-210.98368 745.86156,-211.28466 743.5625,-211.1875 z"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6969);enable-background:new" />
- <g
- id="g8121"
- style="fill:#ffffff;fill-opacity:1;filter:url(#filter7345)">
- <path
- sodipodi:nodetypes="czzzczzc"
- id="path8123"
- d="M 744.9375,-212.11731 C 744.9375,-212.11731 752.15979,-215.34049 754,-215.61731 C 755.84021,-215.89413 757.35225,-215.62054 760,-215.05481 C 762.64775,-214.48908 768.7357,-212.83963 771.1875,-211.67981 C 773.6393,-210.51999 776.5,-208.11731 776.5,-208.11731 C 776.5,-208.11731 769.35356,-210.8975 766.3125,-211.67981 C 763.27144,-212.46212 758.66789,-213.76355 755.9375,-213.99231 C 753.20711,-214.22107 744.9375,-212.11731 744.9375,-212.11731 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
- <path
- sodipodi:nodetypes="czzzczzc"
- id="path8125"
- d="M 735.46875,-206.95416 C 735.46875,-206.95416 739.12854,-209.17734 740.96875,-209.45416 C 742.80896,-209.73098 744.6335,-209.20739 747.28125,-208.64166 C 749.929,-208.07593 756.01695,-206.42648 758.46875,-205.26666 C 760.92055,-204.10684 765.03125,-203.14166 765.03125,-203.14166 C 765.03125,-203.14166 756.63481,-204.48435 753.59375,-205.26666 C 750.55269,-206.04897 745.63664,-207.6004 742.90625,-207.82916 C 740.17586,-208.05792 735.46875,-206.95416 735.46875,-206.95416 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- sodipodi:nodetypes="czzzczzc"
- id="path8127"
- d="M 759.85042,-217.61116 C 759.85042,-217.61116 768.39412,-220.90973 770.2482,-221.06902 C 772.10229,-221.22832 773.88986,-220.58982 776.4963,-219.85694 C 779.10274,-219.12406 785.07354,-217.091 787.44666,-215.77769 C 789.81978,-214.46438 793.86083,-213.23987 793.86083,-213.23987 C 793.86083,-213.23987 785.5667,-215.11352 782.58152,-216.08754 C 779.59633,-217.06156 774.78883,-218.92232 772.0785,-219.32416 C 769.36817,-219.726 759.85042,-217.61116 759.85042,-217.61116 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- sodipodi:nodetypes="czzzczzc"
- id="path8129"
- d="M 775.19813,-223.2266 C 775.19813,-223.2266 782.96946,-226.00904 784.82644,-226.13009 C 786.68341,-226.25113 788.45744,-225.57592 791.04822,-224.78947 C 793.63899,-224.00302 799.56662,-221.8473 801.91216,-220.48535 C 804.25771,-219.1234 808.27265,-217.81585 808.27265,-217.81585 C 808.27265,-217.81585 800.01892,-219.86008 797.05444,-220.89543 C 794.08997,-221.93078 789.32185,-223.89024 786.62038,-224.34786 C 783.91891,-224.80549 775.19813,-223.2266 775.19813,-223.2266 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- inkscape:transform-center-y="-4.3190906"
- inkscape:transform-center-x="13.852145"
- sodipodi:nodetypes="czzzczzc"
- id="path8131"
- d="M 789.64298,-227.95417 C 789.64298,-227.95417 798.32554,-231.47448 800.18452,-231.55952 C 802.04349,-231.64455 803.8041,-230.9351 806.37915,-230.09859 C 808.9542,-229.2621 814.83894,-226.99193 817.15766,-225.58479 C 819.47638,-224.17764 823.46523,-222.79255 823.46523,-222.79255 C 823.46523,-222.79255 815.25266,-224.99632 812.3088,-226.08891 C 809.36494,-227.1815 804.63568,-229.23299 801.94358,-229.74288 C 799.25149,-230.25276 789.64298,-227.95417 789.64298,-227.95417 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- inkscape:transform-center-y="-4.3190906"
- inkscape:transform-center-x="13.852145"
- sodipodi:nodetypes="czzzczzc"
- id="path8133"
- d="M 804.49513,-233.32948 C 804.49513,-233.32948 812.30269,-235.91229 814.16167,-235.99733 C 816.02064,-236.08236 817.78125,-235.37291 820.3563,-234.5364 C 822.93135,-233.69991 828.81609,-231.42974 831.13481,-230.0226 C 833.45353,-228.61545 837.44238,-227.23036 837.44238,-227.23036 C 837.44238,-227.23036 829.22981,-229.43413 826.28595,-230.52672 C 823.34209,-231.61931 818.61283,-233.6708 815.92073,-234.18069 C 813.22864,-234.69057 804.49513,-233.32948 804.49513,-233.32948 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- inkscape:transform-center-y="-4.3190906"
- inkscape:transform-center-x="13.852145"
- sodipodi:nodetypes="czzzczzc"
- id="path8135"
- d="M 819.55763,-237.57948 C 819.55763,-237.57948 828.11519,-240.16229 829.97417,-240.24733 C 831.83314,-240.33236 833.59375,-239.62291 836.1688,-238.7864 C 838.74385,-237.94991 844.62859,-235.67974 846.94731,-234.2726 C 849.26603,-232.86545 853.25488,-231.48036 853.25488,-231.48036 C 853.25488,-231.48036 845.04231,-233.68413 842.09845,-234.77672 C 839.15459,-235.86931 834.42533,-237.9208 831.73323,-238.43069 C 829.04114,-238.94057 819.55763,-237.57948 819.55763,-237.57948 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- inkscape:transform-center-y="-4.9269042"
- inkscape:transform-center-x="13.64141"
- sodipodi:nodetypes="czzzczzc"
- id="path8137"
- d="M 836.23395,-242.60125 C 836.23395,-242.60125 843.20097,-244.58848 845.06179,-244.56882 C 846.9226,-244.54915 848.64052,-243.7418 851.16444,-242.76177 C 853.68837,-241.78177 859.4361,-239.18419 861.672,-237.64886 C 863.9079,-236.11351 867.81253,-234.50625 867.81253,-234.50625 C 867.81253,-234.50625 859.73692,-237.16847 856.85917,-238.42491 C 853.98143,-239.68136 849.37505,-241.99561 846.71589,-242.65612 C 844.05674,-243.31661 836.23395,-242.60125 836.23395,-242.60125 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- inkscape:transform-center-y="-5.1542119"
- inkscape:transform-center-x="13.55068"
- sodipodi:nodetypes="czzzczzc"
- id="path8139"
- d="M 850.73028,-246.00461 C 850.73028,-246.00461 858.41812,-248.03229 860.2781,-247.97315 C 862.13807,-247.914 863.83848,-247.07036 866.34103,-246.03699 C 868.84358,-245.00365 874.5349,-242.28467 876.73771,-240.70224 C 878.94053,-239.11979 882.81016,-237.43004 882.81016,-237.43004 C 882.81016,-237.43004 874.79287,-240.26302 871.94244,-241.58026 C 869.09201,-242.89749 864.53578,-245.30898 861.89124,-246.02576 C 859.2467,-246.74254 850.73028,-246.00461 850.73028,-246.00461 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- inkscape:transform-center-y="-5.4740887"
- inkscape:transform-center-x="13.41151"
- sodipodi:nodetypes="czzzczzc"
- id="path8141"
- d="M 864.82496,-249.21081 C 864.82496,-249.21081 872.99448,-251.17987 874.85184,-251.06477 C 876.70919,-250.94965 878.38342,-250.05521 880.85374,-248.94698 C 883.32405,-247.83877 888.93094,-244.94971 891.08512,-243.30167 C 893.2393,-241.65363 897.05632,-239.84815 897.05632,-239.84815 C 897.05632,-239.84815 889.12793,-242.92121 886.31845,-244.32365 C 883.50896,-245.72609 879.02739,-248.27364 876.40562,-249.06971 C 873.78386,-249.86577 864.82496,-249.21081 864.82496,-249.21081 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- inkscape:transform-center-y="-5.79376"
- inkscape:transform-center-x="13.258805"
- sodipodi:nodetypes="czzzczzc"
- id="path8143"
- d="M 881.38485,-251.60282 C 881.38485,-251.60282 889.47021,-253.51091 891.32322,-253.33946 C 893.17622,-253.16799 894.82252,-252.22313 897.25804,-251.04038 C 899.69357,-249.85767 905.21013,-246.79968 907.31327,-245.08699 C 909.41641,-243.37429 913.17684,-241.45373 913.17684,-241.45373 C 913.17684,-241.45373 905.34544,-244.76613 902.57984,-246.25323 C 899.81423,-247.74035 895.41209,-250.42282 892.8157,-251.29814 C 890.21933,-252.17345 881.38485,-251.60282 881.38485,-251.60282 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- inkscape:transform-center-y="-5.7433893"
- inkscape:transform-center-x="13.28378"
- sodipodi:nodetypes="czzzczzc"
- id="path8145"
- d="M 896.58415,-254.34724 C 896.58415,-254.34724 904.22581,-255.77494 906.07962,-255.61239 C 907.93342,-255.44983 909.58424,-254.51289 912.02541,-253.34186 C 914.46659,-252.17086 919.99779,-249.1394 922.10913,-247.43684 C 924.22047,-245.73426 927.99009,-243.83179 927.99009,-243.83179 C 927.99009,-243.83179 920.14286,-247.10653 917.37014,-248.58034 C 914.59743,-250.05414 910.18245,-252.71543 907.58189,-253.57827 C 904.98134,-254.44109 896.58415,-254.34724 896.58415,-254.34724 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- inkscape:transform-center-y="-5.7433893"
- inkscape:transform-center-x="13.28378"
- sodipodi:nodetypes="czzzczzc"
- id="path8147"
- d="M 911.45328,-255.98544 C 911.45328,-255.98544 920.09494,-257.53814 921.94875,-257.37559 C 923.80255,-257.21303 925.45337,-256.27609 927.89454,-255.10506 C 930.33572,-253.93406 935.86692,-250.9026 937.97826,-249.20004 C 940.0896,-247.49746 943.85922,-245.59499 943.85922,-245.59499 C 943.85922,-245.59499 936.01199,-248.86973 933.23927,-250.34354 C 930.46656,-251.81734 926.05158,-254.47863 923.45102,-255.34147 C 920.85047,-256.20429 911.45328,-255.98544 911.45328,-255.98544 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- inkscape:transform-center-y="-5.7433893"
- inkscape:transform-center-x="13.28378"
- sodipodi:nodetypes="czzzczzc"
- id="path8149"
- d="M 927.70328,-258.29794 C 927.70328,-258.29794 935.34494,-259.16314 937.19875,-259.00059 C 939.05255,-258.83803 940.70337,-257.90109 943.14454,-256.73006 C 945.58572,-255.55906 951.11692,-252.5276 953.22826,-250.82504 C 955.3396,-249.12246 959.10922,-247.21999 959.10922,-247.21999 C 959.10922,-247.21999 951.26199,-250.49473 948.48927,-251.96854 C 945.71656,-253.44234 941.30158,-256.10363 938.70102,-256.96647 C 936.10047,-257.82929 927.70328,-258.29794 927.70328,-258.29794 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- inkscape:transform-center-y="-5.7433893"
- inkscape:transform-center-x="13.28378"
- sodipodi:nodetypes="czzzczzc"
- id="path8151"
- d="M 942.82828,-259.48544 C 942.82828,-259.48544 951.40744,-260.97564 953.26125,-260.81309 C 955.11505,-260.65053 956.76587,-259.71359 959.20704,-258.54256 C 961.64822,-257.37156 967.17942,-254.3401 969.29076,-252.63754 C 971.4021,-250.93496 975.17172,-249.03249 975.17172,-249.03249 C 975.17172,-249.03249 967.32449,-252.30723 964.55177,-253.78104 C 961.77906,-255.25484 957.36408,-257.91613 954.76352,-258.77897 C 952.16297,-259.64179 942.82828,-259.48544 942.82828,-259.48544 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- inkscape:transform-center-y="-5.7433893"
- inkscape:transform-center-x="13.28378"
- sodipodi:nodetypes="czzzczzc"
- id="path8153"
- d="M 959.07828,-261.54794 C 959.07828,-261.54794 966.90744,-262.35064 968.76125,-262.18809 C 970.61505,-262.02553 972.26587,-261.08859 974.70704,-259.91756 C 977.14822,-258.74656 982.67942,-255.7151 984.79076,-254.01254 C 986.9021,-252.30996 990.67172,-250.40749 990.67172,-250.40749 C 990.67172,-250.40749 982.82449,-253.68223 980.05177,-255.15604 C 977.27906,-256.62984 972.86408,-259.29113 970.26352,-260.15397 C 967.66297,-261.01679 959.07828,-261.54794 959.07828,-261.54794 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- inkscape:transform-center-y="-5.7433893"
- inkscape:transform-center-x="13.28378"
- sodipodi:nodetypes="czzzczzc"
- id="path8155"
- d="M 974.45328,-262.79794 C 974.45328,-262.79794 982.84494,-263.97564 984.69875,-263.81309 C 986.55255,-263.65053 988.20337,-262.71359 990.64454,-261.54256 C 993.08572,-260.37156 998.61692,-257.3401 1000.7283,-255.63754 C 1002.8396,-253.93496 1006.6092,-252.03249 1006.6092,-252.03249 C 1006.6092,-252.03249 998.76199,-255.30723 995.98927,-256.78104 C 993.21656,-258.25484 988.80158,-260.91613 986.20102,-261.77897 C 983.60047,-262.64179 974.45328,-262.79794 974.45328,-262.79794 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- inkscape:transform-center-y="-5.7433893"
- inkscape:transform-center-x="13.28378"
- sodipodi:nodetypes="czzzczzc"
- id="path8157"
- d="M 990.64078,-264.86044 C 990.64078,-264.86044 997.53244,-265.85064 999.38625,-265.68809 C 1001.2401,-265.52553 1002.8909,-264.58859 1005.332,-263.41756 C 1007.7732,-262.24656 1013.3044,-259.2151 1015.4158,-257.51254 C 1017.5271,-255.80996 1021.2967,-253.90749 1021.2967,-253.90749 C 1021.2967,-253.90749 1013.4495,-257.18223 1010.6768,-258.65604 C 1007.9041,-260.12984 1003.4891,-262.79113 1000.8885,-263.65397 C 998.28797,-264.51679 990.64078,-264.86044 990.64078,-264.86044 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- inkscape:transform-center-y="-5.7433893"
- inkscape:transform-center-x="13.28378"
- sodipodi:nodetypes="czzzczzc"
- id="path8159"
- d="M 1007.7658,-265.79794 C 1007.7658,-265.79794 1014.5949,-266.97564 1016.4488,-266.81309 C 1018.3026,-266.65053 1019.9534,-265.71359 1022.3945,-264.54256 C 1024.8357,-263.37156 1030.3669,-260.3401 1032.4783,-258.63754 C 1034.5896,-256.93496 1038.3592,-255.03249 1038.3592,-255.03249 C 1038.3592,-255.03249 1030.512,-258.30723 1027.7393,-259.78104 C 1024.9666,-261.25484 1020.5516,-263.91613 1017.951,-264.77897 C 1015.3505,-265.64179 1007.7658,-265.79794 1007.7658,-265.79794 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- inkscape:transform-center-y="-5.7433893"
- inkscape:transform-center-x="13.28378"
- sodipodi:nodetypes="czzzczzc"
- id="path8161"
- d="M 1023.8908,-267.79794 C 1023.8908,-267.79794 1029.9699,-268.22564 1031.8238,-268.06309 C 1033.6776,-267.90053 1035.3284,-266.96359 1037.7695,-265.79256 C 1040.2107,-264.62156 1045.7419,-261.5901 1047.8533,-259.88754 C 1049.9646,-258.18496 1053.7342,-256.28249 1053.7342,-256.28249 C 1053.7342,-256.28249 1045.887,-259.55723 1043.1143,-261.03104 C 1040.3416,-262.50484 1035.9266,-265.16613 1033.326,-266.02897 C 1030.7255,-266.89179 1023.8908,-267.79794 1023.8908,-267.79794 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- inkscape:transform-center-y="-5.7433893"
- inkscape:transform-center-x="13.28378"
- sodipodi:nodetypes="czzzczzc"
- id="path8163"
- d="M 1039.7033,-269.17294 C 1039.7033,-269.17294 1046.1574,-269.85064 1048.0113,-269.68809 C 1049.8651,-269.52553 1051.5159,-268.58859 1053.957,-267.41756 C 1056.3982,-266.24656 1061.9294,-263.2151 1064.0408,-261.51254 C 1066.1521,-259.80996 1069.9217,-257.90749 1069.9217,-257.90749 C 1069.9217,-257.90749 1062.0745,-261.18223 1059.3018,-262.65604 C 1056.5291,-264.12984 1052.1141,-266.79113 1049.5135,-267.65397 C 1046.913,-268.51679 1039.7033,-269.17294 1039.7033,-269.17294 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- inkscape:transform-center-y="-5.1360724"
- inkscape:transform-center-x="13.55813"
- sodipodi:nodetypes="czzzczzc"
- id="path8165"
- d="M 1055.2718,-271.03319 C 1055.2718,-271.03319 1060.7694,-271.94264 1062.6296,-271.88667 C 1064.4897,-271.83067 1066.1915,-270.98993 1068.6957,-269.96081 C 1071.2001,-268.93171 1076.896,-266.22241 1079.1015,-264.64372 C 1081.307,-263.06501 1085.1795,-261.38182 1085.1795,-261.38182 C 1085.1795,-261.38182 1077.1575,-264.20121 1074.3047,-265.5136 C 1071.4521,-266.82598 1066.8918,-269.22973 1064.246,-269.94203 C 1061.6003,-270.65431 1055.2718,-271.03319 1055.2718,-271.03319 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- inkscape:transform-center-y="-4.6370147"
- inkscape:transform-center-x="13.74758"
- sodipodi:nodetypes="czzzczzc"
- id="path8167"
- d="M 1072.7007,-273.48537 C 1072.7007,-273.48537 1077.2479,-274.64118 1079.1087,-274.67158 C 1080.9694,-274.70196 1082.7083,-273.94109 1085.2576,-273.02927 C 1087.807,-272.1175 1093.6225,-269.67541 1095.899,-268.20077 C 1098.1753,-266.72609 1102.1217,-265.22441 1102.1217,-265.22441 C 1102.1217,-265.22441 1093.9775,-267.66852 1091.067,-268.84713 C 1088.1565,-270.02573 1083.4896,-272.21528 1080.8136,-272.80404 C 1078.1377,-273.39279 1072.7007,-273.48537 1072.7007,-273.48537 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- inkscape:transform-center-y="-4.4842392"
- inkscape:transform-center-x="13.79933"
- sodipodi:nodetypes="czzzczzc"
- id="path8169"
- d="M 1087.1585,-276.5244 C 1087.1585,-276.5244 1093.1185,-278.29795 1094.9787,-278.35464 C 1096.8387,-278.41131 1098.5883,-277.67509 1101.1502,-276.79939 C 1103.7122,-275.92373 1103.6728,-275.94226 1106.4837,-275.30924 C 1109.2806,-274.67938 1113.5604,-273.79611 1113.5604,-273.79611 C 1113.5604,-273.79611 1109.9449,-273.81239 1106.7681,-274.26225 C 1103.6526,-274.70344 1099.3938,-275.9605 1096.7097,-276.51138 C 1094.0258,-277.06226 1087.1585,-276.5244 1087.1585,-276.5244 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
- <path
- sodipodi:nodetypes="czczc"
- id="path8171"
- d="M 1099.25,-279.92981 C 1099.4112,-279.66119 1110.4581,-284.53027 1111.4375,-284.61731 C 1112.4169,-284.70435 1113.4375,-281.49231 1113.4375,-281.49231 C 1113.4375,-281.49231 1112.6624,-282.99665 1110.5625,-282.55481 C 1108.4626,-282.11297 1099.2616,-279.8834 1099.25,-279.92981 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
- </g>
- <path
- id="path8173"
- d="M 1107.4532,-284.0938 C 1107.0345,-283.88097 1107.2976,-283.99991 1106.806,-283.78799 C 1106.3199,-283.57845 1105.0826,-283.2136 1102.7264,-282.32904 C 1099.3953,-281.07847 1096.8962,-280.1756 1095.7005,-279.26294 C 1094.1644,-279.24168 1091.98,-279.02963 1090.0442,-278.54419 C 1087.0627,-277.79653 1085.189,-277.37018 1083.2942,-276.95044 C 1081.3994,-276.53072 1081.6187,-276.30825 1080.4192,-276.07544 C 1079.1226,-275.82378 1078.6978,-276.08443 1074.9817,-275.29419 C 1071.4918,-274.55205 1066.0869,-273.36312 1064.8255,-272.60669 C 1063.2416,-272.78748 1060.958,-272.92847 1058.9817,-272.63794 C 1055.9413,-272.19099 1054.0655,-271.96518 1052.138,-271.73169 C 1051.4826,-271.65232 1051.0969,-271.53091 1050.7942,-271.45044 C 1050.368,-271.31879 1050.1084,-271.19042 1049.4192,-271.10669 C 1048.1076,-270.94733 1047.657,-271.26352 1043.888,-270.82544 C 1040.3341,-270.41236 1034.8826,-269.55262 1033.638,-268.88794 C 1032.039,-269.18524 1029.7802,-269.42213 1027.7942,-269.23169 C 1024.7354,-268.93838 1022.8222,-268.7477 1020.888,-268.57544 C 1018.9537,-268.40318 1019.1993,-268.15307 1017.9817,-268.04419 C 1016.6655,-267.9265 1016.2219,-268.20782 1012.4505,-267.79419 C 1008.9086,-267.40575 1003.4426,-266.58492 1002.1692,-265.91919 C 1000.5703,-266.21389 998.28202,-266.4262 996.29419,-266.23169 C 993.23595,-265.93245 991.35306,-265.75145 989.41919,-265.57544 C 988.7617,-265.5156 988.37915,-265.39688 988.07544,-265.32544 C 987.64779,-265.20649 987.39193,-265.10737 986.70044,-265.04419 C 985.38448,-264.92394 984.94068,-265.23907 981.16919,-264.82544 C 977.61305,-264.43543 972.16365,-263.58628 970.91919,-262.91919 C 969.32056,-263.21338 967.05935,-263.44291 965.07544,-263.23169 C 962.01984,-262.90637 960.1014,-262.70545 958.16919,-262.51294 C 956.23698,-262.32044 956.47932,-262.07206 955.26294,-261.95044 C 953.94806,-261.81898 953.49996,-262.11498 949.73169,-261.66919 C 946.19282,-261.25054 940.75401,-260.37702 939.48169,-259.70044 C 937.88414,-259.98149 935.62173,-260.12087 933.63794,-259.88794 C 930.58596,-259.52958 928.69286,-259.32008 926.76294,-259.10669 C 926.10674,-259.03414 925.72228,-258.934 925.41919,-258.85669 C 924.99242,-258.72947 924.73428,-258.58949 924.04419,-258.51294 C 922.73086,-258.36726 922.27673,-258.68696 918.51294,-258.20044 C 914.96405,-257.74169 909.53431,-256.78142 908.29419,-256.07544 C 906.70114,-256.31968 904.46038,-256.45679 902.48169,-256.20044 C 899.4341,-255.80563 897.53098,-255.55199 895.60669,-255.29419 C 893.68241,-255.0364 893.88058,-254.80066 892.66919,-254.63794 C 891.35973,-254.46204 890.922,-254.74232 887.16919,-254.16919 C 883.6449,-253.63095 878.24604,-252.47002 876.98169,-251.73169 C 875.39419,-251.93523 873.13619,-251.98642 871.16919,-251.63794 C 868.14302,-251.10182 866.2703,-250.77625 864.35669,-250.45044 C 863.70608,-250.33967 863.34298,-250.1795 863.04419,-250.07544 C 862.62352,-249.91056 862.38074,-249.74414 861.70044,-249.60669 C 860.40579,-249.3451 859.97332,-249.61289 856.26294,-248.79419 C 852.76441,-248.02224 847.41699,-246.41126 846.20044,-245.57544 C 844.63766,-245.65289 842.44286,-245.49016 840.51294,-244.98169 C 837.5405,-244.19856 835.69533,-243.7496 833.82544,-243.23169 C 831.95556,-242.71379 832.15884,-242.46441 830.98169,-242.13794 C 829.70923,-241.78504 829.28466,-242.03085 825.63794,-240.95044 C 822.21324,-239.93581 816.9885,-238.01727 815.76294,-237.10669 C 814.22411,-237.09395 812.04311,-236.83447 810.13794,-236.23169 C 807.20688,-235.30435 805.38763,-234.77327 803.54419,-234.16919 C 802.91743,-233.96381 802.55246,-233.77661 802.26294,-233.63794 C 801.85531,-233.42433 801.6096,-233.22919 800.95044,-233.01294 C 799.69598,-232.6014 799.26433,-232.8239 795.66919,-231.57544 C 792.27934,-230.39827 787.07421,-228.36174 785.88794,-227.41919 C 784.36405,-227.35952 782.23789,-227.02432 780.35669,-226.35669 C 777.4593,-225.3284 775.65761,-224.68121 773.82544,-224.04419 C 771.99327,-223.40718 772.19759,-223.19565 771.04419,-222.79419 C 769.79741,-222.36023 769.38058,-222.59447 765.82544,-221.23169 C 762.48677,-219.95189 757.33829,-217.74914 756.13794,-216.76294 C 754.63076,-216.65525 752.50225,-216.26414 750.63794,-215.54419 C 747.76976,-214.43659 746.01414,-213.76263 744.20044,-213.07544 C 743.58378,-212.84181 743.20403,-212.63341 742.91919,-212.48169 C 742.91919,-212.48169 742.91919,-211.38794 742.91919,-211.38794 C 743.03097,-211.6103 743.30518,-212.20537 743.82544,-212.48169 C 744.52341,-212.85241 748.63907,-214.47506 750.63794,-215.20044 C 752.2948,-215.80169 754.79183,-216.52912 756.60669,-216.51294 C 756.90831,-216.51025 757.19431,-216.46204 757.45044,-216.41919 C 759.29293,-216.11094 764.91919,-214.85669 764.91919,-214.85669 C 764.91918,-214.85669 758.6857,-216.50344 757.88794,-216.70044 C 757.69715,-216.74755 757.35222,-216.76916 756.91919,-216.76294 C 758.06465,-217.63265 761.68019,-219.15645 764.26294,-220.20044 C 767.10116,-221.34771 767.37975,-221.45226 769.32544,-221.85669 C 771.33374,-222.27413 772.48169,-222.35669 772.48169,-222.35669 C 772.48169,-222.35668 772.39933,-222.95783 773.45044,-223.48169 C 774.15554,-223.8331 778.33746,-225.37409 780.35669,-226.04419 C 782.30859,-226.69192 785.41409,-227.40269 787.23169,-227.04419 C 789.09492,-226.67669 794.76294,-225.23169 794.76294,-225.23169 C 794.76295,-225.23169 788.47594,-227.1028 787.66919,-227.32544 C 787.47627,-227.37869 787.13835,-227.41148 786.70044,-227.41919 C 787.85878,-228.25207 791.49488,-229.61451 794.10669,-230.57544 C 796.97685,-231.63145 797.27403,-231.73724 799.23169,-232.10669 C 801.08518,-232.45648 802.09053,-232.53217 802.26294,-232.54419 C 802.37654,-232.76143 802.64039,-233.35421 803.16919,-233.60669 C 803.87863,-233.94543 808.09526,-235.31944 810.13794,-235.91919 C 811.83111,-236.4163 814.37871,-236.95596 816.23169,-236.82544 C 816.53964,-236.80376 816.84518,-236.72818 817.10669,-236.66919 C 818.98787,-236.24487 824.70044,-234.63794 824.70044,-234.63794 C 824.70045,-234.63794 818.3587,-236.70319 817.54419,-236.95044 C 817.3494,-237.00958 816.98631,-237.05438 816.54419,-237.07544 C 817.71368,-237.87299 821.40721,-239.13166 824.04419,-240.01294 C 826.942,-240.98141 827.2772,-241.01626 829.26294,-241.29419 C 831.31259,-241.58108 832.45044,-241.60669 832.45044,-241.60669 C 832.45042,-241.60669 832.37769,-242.21366 833.45044,-242.66919 C 834.17004,-242.97476 838.44142,-244.16994 840.51294,-244.66919 C 842.51538,-245.15177 845.71143,-245.59748 847.57544,-245.07544 C 849.48622,-244.54029 855.29419,-242.57544 855.29419,-242.57544 C 855.29419,-242.57544 848.87153,-244.99895 848.04419,-245.29419 C 847.84635,-245.3648 847.46203,-245.43458 847.01294,-245.48169 C 848.20084,-246.21034 851.92821,-247.25577 854.60669,-247.98169 C 857.55011,-248.77944 857.89877,-248.75252 859.91919,-248.88794 C 861.83208,-249.01617 862.86624,-248.95903 863.04419,-248.95044 C 863.16147,-249.1541 863.43595,-249.72992 863.98169,-249.91919 C 864.71388,-250.17313 869.06021,-250.96708 871.16919,-251.29419 C 872.91732,-251.5653 875.57007,-251.77889 877.48169,-251.38794 C 877.79935,-251.32298 878.08691,-251.20243 878.35669,-251.10669 C 880.29743,-250.41796 886.20044,-248.01294 886.20044,-248.01294 C 886.20045,-248.01294 879.66573,-250.96371 878.82544,-251.32544 C 878.62447,-251.41195 878.25031,-251.49223 877.79419,-251.57544 C 879.00069,-252.20862 882.82375,-252.97104 885.54419,-253.48169 C 888.53372,-254.04288 888.84442,-254.01123 890.88794,-254.01294 C 892.9972,-254.01471 894.20044,-253.88794 894.20044,-253.88794 C 894.20044,-253.88793 894.12773,-254.51913 895.23169,-254.82544 C 895.97221,-255.03091 900.35781,-255.65931 902.48169,-255.88794 C 904.53471,-256.10893 907.80032,-256.14016 909.70044,-255.41919 C 911.64823,-254.68012 917.54419,-252.04419 917.54419,-252.04419 C 917.54421,-252.04419 910.98131,-255.22316 910.13794,-255.60669 C 909.93626,-255.69842 909.59573,-255.7929 909.13794,-255.88794 C 910.34886,-256.48982 914.12236,-257.13678 916.85669,-257.54419 C 919.86149,-257.99191 920.1822,-257.99589 922.23169,-257.95044 C 924.17214,-257.90742 925.23868,-257.75621 925.41919,-257.73169 C 925.53811,-257.92485 925.80309,-258.49752 926.35669,-258.63794 C 927.0994,-258.82632 931.51098,-259.37222 933.63794,-259.57544 C 935.40097,-259.74386 938.05803,-259.80973 939.98169,-259.32544 C 940.30137,-259.24496 940.5852,-259.12185 940.85669,-259.01294 C 942.80962,-258.22945 948.76294,-255.54419 948.76294,-255.54419 C 948.76292,-255.54419 942.17103,-258.79767 941.32544,-259.20044 C 941.12322,-259.29676 940.75318,-259.40747 940.29419,-259.51294 C 941.50833,-260.08721 945.33785,-260.63513 948.07544,-261.01294 C 951.08382,-261.42814 951.39851,-261.45557 953.45044,-261.38794 C 955.56842,-261.31813 956.76294,-261.13794 956.76294,-261.13794 C 956.76292,-261.13794 956.68569,-261.77535 957.79419,-262.04419 C 958.53781,-262.22454 962.94595,-262.70774 965.07544,-262.88794 C 967.13391,-263.06211 970.41868,-263.01226 972.32544,-262.23169 C 974.28003,-261.43153 980.20044,-258.70044 980.20044,-258.70044 C 980.20042,-258.70044 973.64051,-262.0092 972.79419,-262.41919 C 972.59182,-262.51724 972.22233,-262.62229 971.76294,-262.73169 C 972.97811,-263.29559 976.77302,-263.84599 979.51294,-264.20044 C 982.52385,-264.58996 982.83425,-264.59809 984.88794,-264.51294 C 986.83233,-264.43234 987.89457,-264.2597 988.07544,-264.23169 C 988.1946,-264.42255 988.45821,-264.977 989.01294,-265.10669 C 989.7572,-265.28069 994.16287,-265.75716 996.29419,-265.91919 C 998.06081,-266.05346 1000.7439,-266.0449 1002.6692,-265.54419 C 1002.9892,-265.46098 1003.2725,-265.34292 1003.5442,-265.23169 C 1005.4988,-264.43153 1011.4505,-261.66919 1011.4505,-261.66919 C 1011.4504,-261.66919 1004.8593,-265.0092 1004.013,-265.41919 C 1003.8106,-265.51724 1003.4411,-265.6223 1002.9817,-265.73169 C 1004.1968,-266.29559 1008.023,-266.81475 1010.763,-267.16919 C 1013.7739,-267.55872 1014.1155,-267.59809 1016.1692,-267.51294 C 1018.2889,-267.42506 1019.4817,-267.20044 1019.4817,-267.20044 C 1019.4817,-267.20044 1019.4033,-267.84946 1020.513,-268.10669 C 1021.2573,-268.27925 1025.6625,-268.73005 1027.7942,-268.88794 C 1029.8548,-269.04054 1033.1371,-268.98471 1035.0442,-268.20044 C 1036.9992,-267.39649 1042.9192,-264.70044 1042.9192,-264.70044 C 1042.9192,-264.70044 1036.3594,-267.97631 1035.513,-268.38794 C 1035.3105,-268.48638 1034.9412,-268.59016 1034.4817,-268.70044 C 1035.6971,-269.26198 1039.4936,-269.82822 1042.2317,-270.20044 C 1045.2407,-270.60949 1045.5544,-270.61602 1047.6067,-270.54419 C 1049.5498,-270.4762 1050.6139,-270.37934 1050.7942,-270.35669 C 1050.913,-270.55109 1051.1788,-271.0855 1051.7317,-271.23169 C 1052.4735,-271.42781 1056.8628,-272.06047 1058.9817,-272.32544 C 1060.7381,-272.54505 1063.387,-272.65775 1065.2942,-272.29419 C 1065.6111,-272.23378 1065.9,-272.10481 1066.1692,-272.01294 C 1068.1054,-271.35202 1074.013,-269.07544 1074.013,-269.07544 C 1074.0129,-269.07544 1067.4763,-271.88199 1066.638,-272.23169 C 1066.4375,-272.31532 1066.0618,-272.40502 1065.6067,-272.48169 C 1066.8104,-273.13215 1070.6258,-273.85364 1073.3255,-274.48169 C 1076.2922,-275.17189 1076.6144,-275.23676 1078.638,-275.35669 C 1080.7266,-275.48049 1081.9192,-275.38794 1081.9192,-275.38794 C 1081.9192,-275.38793 1081.8322,-276.01999 1082.9192,-276.41919 C 1083.6484,-276.68699 1087.9664,-277.75716 1090.0442,-278.23169 C 1092.0527,-278.69038 1095.2121,-279.26099 1097.0442,-278.85669 C 1098.9223,-278.44223 1110.6224,-275.84106 1110.6224,-275.84106 C 1110.6224,-275.84106 1098.2949,-278.86372 1097.4817,-279.10669 C 1097.2872,-279.16481 1096.9231,-279.21295 1096.4817,-279.23169 C 1097.6493,-280.03538 1099.9959,-280.91899 1102.5911,-281.93481 C 1104.2725,-282.59299 1103.5148,-282.3114 1105.367,-282.93841 C 1107.1206,-283.53207 1107.8524,-283.94912 1107.9974,-284.0514 C 1108.3435,-284.25791 1107.6414,-284.17328 1107.4532,-284.0938 z"
- style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7333);enable-background:new"
- sodipodi:nodetypes="czscsssscssssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssccsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscc" />
- <path
- id="path8175"
- d="M 1082.625,-275.125 C 1084.498,-274.73152 1087.1211,-273.97945 1088.6563,-273.15625 C 1090.1915,-272.33306 1091.4785,-272.10025 1094.0313,-270.65625 C 1096.5579,-269.22699 1098.8271,-268.64929 1101,-268.125 C 1103.3476,-267.55858 1106.4354,-267.40977 1109.8438,-266.9375 C 1108.7549,-267.77725 1103.2364,-268.10995 1101.4375,-268.5 C 1099.6386,-268.89006 1097.5434,-269.51616 1094.8438,-270.8125 C 1092.1441,-272.10884 1091.3494,-272.61146 1089.0313,-273.5 C 1086.7131,-274.38854 1085.0269,-274.88314 1082.625,-275.125 z"
- style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7285);enable-background:new" />
- <path
- id="path8177"
- d="M 1051.4688,-270 C 1053.3741,-269.42241 1055.9969,-268.38428 1057.5625,-267.40625 C 1059.1281,-266.42823 1060.4427,-266.04644 1063.0625,-264.28125 C 1065.6555,-262.53409 1068.0484,-261.57198 1070.3125,-260.6875 C 1072.7586,-259.73193 1075.9951,-259.03037 1079.7188,-257.625 C 1078.5292,-258.76284 1072.6557,-260.31175 1070.7813,-261 C 1068.9068,-261.68825 1066.6995,-262.5662 1063.9063,-264.28125 C 1061.113,-265.99629 1060.3327,-266.56515 1057.9688,-267.6875 C 1055.6047,-268.80984 1053.9121,-269.52205 1051.4688,-270 z"
- style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7289);enable-background:new" />
- <path
- id="path8179"
- d="M 1020.2188,-266.84375 C 1022.1307,-266.20564 1024.8,-265.08839 1026.375,-264.03125 C 1027.9501,-262.9741 1029.2706,-262.52258 1031.9063,-260.625 C 1034.5149,-258.74679 1036.9347,-257.59497 1039.2188,-256.5625 C 1041.6865,-255.44705 1044.9833,-254.3892 1048.75,-252.71875 C 1047.5467,-253.94128 1041.5472,-256.03298 1039.6563,-256.84375 C 1037.7653,-257.65452 1035.5914,-258.73754 1032.7813,-260.59375 C 1029.9711,-262.44995 1029.1595,-263.07068 1026.7813,-264.3125 C 1024.403,-265.5543 1022.6706,-266.28819 1020.2188,-266.84375 z"
- style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7293);enable-background:new" />
- <path
- id="path8181"
- d="M 1110.1719,-266.89063 C 1110.3227,-266.84207 1110.8599,-266.25963 1110.2813,-265.40625 C 1109.4712,-264.21166 1104.5764,-262.08196 1101.7188,-261.28125 C 1098.8739,-260.48413 1095.4287,-260.30351 1091.1563,-261.65625 C 1086.8547,-263.0182 1085.6866,-264.12497 1080.5,-265.96875 C 1085.164,-263.85358 1086.6953,-262.01642 1090.625,-260.625 C 1092.2457,-260.05113 1093.9921,-259.6854 1095.6875,-259.59375 C 1095.2424,-259.26812 1094.1572,-258.61045 1092.125,-258 C 1089.3295,-257.16031 1085.4759,-256.46622 1083.875,-256.375 C 1082.3604,-256.28868 1080.733,-256.88749 1080.4375,-257 C 1080.6042,-256.89692 1080.8107,-256.62266 1080.1875,-255.96875 C 1079.2882,-255.02512 1074.0401,-254.04575 1071.0625,-253.71875 C 1068.0982,-253.3932 1064.5409,-253.73471 1060.1563,-255.625 C 1056.1783,-257.33997 1054.8173,-258.54036 1050.75,-260.375 C 1050.75,-260.375 1050.75,-260.21875 1050.75,-260.21875 C 1054.3931,-258.12346 1056.034,-256.33548 1059.625,-254.65625 C 1061.3552,-253.84716 1063.2167,-253.24749 1065.0313,-252.9375 C 1064.4964,-252.65074 1063.4735,-252.22599 1061.5938,-251.90625 C 1058.7248,-251.41829 1054.7848,-251.09011 1053.1563,-251.15625 C 1052.3056,-251.19079 1051.4277,-251.34062 1050.75,-251.5625 C 1050.0652,-251.77738 1049.5603,-252.00717 1049.4375,-252.0625 C 1049.6069,-251.95529 1049.8686,-251.65962 1049.2188,-251.03125 C 1048.3091,-250.15163 1042.9727,-249.69487 1039.9688,-249.5625 C 1036.9783,-249.43071 1033.3799,-250.01313 1028.9688,-252.125 C 1024.5276,-254.25126 1023.3273,-255.5266 1018.0625,-257.90625 C 1022.7968,-255.30921 1024.349,-253.27715 1028.4063,-251.1875 C 1030.0796,-250.32565 1031.8915,-249.69325 1033.6563,-249.25 C 1033.193,-249.01668 1032.0669,-248.56186 1029.9688,-248.3125 C 1027.0825,-247.96952 1023.1342,-247.81962 1021.5,-247.9375 C 1019.9538,-248.049 1018.2688,-248.79446 1017.9688,-248.9375 C 1018.1379,-248.81721 1018.3826,-248.52702 1017.75,-247.9375 C 1016.8372,-247.08677 1011.5059,-246.67538 1008.5,-246.5625 C 1005.5075,-246.45013 1001.9103,-247.05293 997.5,-249.15625 C 993.49875,-251.06448 992.11197,-252.29408 988.03125,-254.25 C 988.03122,-254.25 988.03125,-254.09375 988.03125,-254.09375 C 991.68631,-251.88983 993.32546,-250.0412 996.9375,-248.1875 C 998.67779,-247.29435 1000.5745,-246.65923 1002.4063,-246.21875 C 1001.8663,-245.97045 1000.8282,-245.60342 998.9375,-245.375 C 996.05182,-245.02642 992.07145,-244.85405 990.4375,-244.96875 C 989.58405,-245.02865 988.71119,-245.22666 988.03125,-245.46875 C 987.34415,-245.70405 986.8419,-245.94101 986.71875,-246 C 986.88873,-245.88773 987.18323,-245.57775 986.53125,-244.96875 C 985.6186,-244.11625 980.25592,-243.67538 977.25,-243.5625 C 974.25754,-243.45013 970.65654,-244.09055 966.25,-246.15625 C 961.81347,-248.23603 960.60312,-249.48796 955.34375,-251.8125 C 960.07313,-249.26501 961.63449,-247.2347 965.6875,-245.1875 C 967.35905,-244.34317 969.17304,-243.72107 970.9375,-243.28125 C 970.47427,-243.04703 969.3478,-242.59718 967.25,-242.34375 C 964.36431,-241.99517 960.4138,-241.77423 958.78125,-241.875 C 957.23669,-241.97032 955.58094,-242.70385 955.28125,-242.84375 C 955.45024,-242.72522 955.66317,-242.4399 955.03125,-241.84375 C 954.11939,-240.98347 948.7846,-240.5135 945.78125,-240.375 C 942.7913,-240.2371 939.2138,-240.82568 934.8125,-242.84375 C 930.81942,-244.67464 929.44739,-245.87295 925.375,-247.75 C 925.37498,-247.75 925.375,-247.59375 925.375,-247.59375 C 929.02261,-245.46048 930.64533,-243.65888 934.25,-241.875 C 935.98675,-241.01549 937.85727,-240.42486 939.6875,-240 C 939.14803,-239.7471 938.13687,-239.35871 936.25,-239.09375 C 933.37022,-238.68939 929.41187,-238.44813 927.78125,-238.53125 C 926.92953,-238.57466 926.05355,-238.7398 925.375,-238.96875 C 924.68931,-239.19076 924.1854,-239.41214 924.0625,-239.46875 C 924.23209,-239.35976 924.4944,-239.0591 923.84375,-238.4375 C 922.93296,-237.56736 917.59354,-237.04598 914.59375,-236.875 C 911.60742,-236.70479 908.01994,-237.19077 903.625,-239.15625 C 899.20011,-241.13513 898.01904,-242.38444 892.78125,-244.53125 C 897.49122,-242.14358 899.05142,-240.14252 903.09375,-238.1875 C 904.7609,-237.38119 906.55418,-236.79092 908.3125,-236.40625 C 907.85087,-236.15755 906.7155,-235.694 904.625,-235.375 C 901.7494,-234.93624 897.8446,-234.6419 896.21875,-234.6875 C 894.68052,-234.73062 892.98595,-235.43272 892.6875,-235.5625 C 892.85583,-235.44968 893.09807,-235.14875 892.46875,-234.53125 C 891.56063,-233.64015 886.2658,-233.003 883.28125,-232.71875 C 880.31007,-232.43577 876.70783,-232.89455 872.34375,-234.65625 C 868.38441,-236.25456 867.0146,-237.45112 863,-238.96875 C 863.00003,-238.96875 863,-238.8125 863,-238.8125 C 866.5959,-237.00115 868.23831,-235.23017 871.8125,-233.65625 C 873.53457,-232.8979 875.39998,-232.3673 877.21875,-232.03125 C 876.68266,-231.75217 875.65217,-231.34362 873.78125,-230.96875 C 870.92586,-230.39665 866.99183,-229.94936 865.375,-229.9375 C 864.53049,-229.93129 863.66892,-230.01844 863,-230.1875 C 862.32409,-230.34901 861.83991,-230.51673 861.71875,-230.5625 C 861.88597,-230.46848 862.14142,-230.17902 861.5,-229.5 C 860.60213,-228.54948 855.31352,-227.58292 852.375,-227.0625 C 849.44966,-226.54441 845.94285,-226.68826 841.65625,-228.09375 C 837.34045,-229.50882 836.18348,-230.62369 831.09375,-232.0625 C 835.6706,-230.31149 837.1823,-228.50244 841.125,-227.0625 C 842.75108,-226.46861 844.49385,-226.10685 846.21875,-225.90625 C 845.7659,-225.60923 844.66397,-225.02286 842.625,-224.4375 C 839.82028,-223.63233 835.98614,-222.86167 834.40625,-222.6875 C 832.9115,-222.5227 831.29002,-223.00431 831,-223.09375 C 831.16356,-223.00368 831.39278,-222.73382 830.78125,-222.03125 C 829.89878,-221.0174 824.73673,-219.6596 821.84375,-218.96875 C 818.96373,-218.28097 815.50815,-218.20873 811.28125,-219.40625 C 807.4464,-220.4927 806.10867,-221.47862 802.21875,-222.53125 C 802.21874,-222.53125 802.21875,-222.375 802.21875,-222.375 C 805.70293,-220.98015 807.28816,-219.4556 810.75,-218.34375 C 812.41793,-217.80803 814.20578,-217.55701 815.96875,-217.46875 C 815.44911,-217.11663 814.46836,-216.55423 812.65625,-215.9375 C 809.89059,-214.99625 806.06601,-214.00213 804.5,-213.78125 C 803.68206,-213.66586 802.8669,-213.65842 802.21875,-213.75 C 801.56379,-213.83321 801.08615,-213.96827 800.96875,-214 C 801.13079,-213.92536 801.40274,-213.65956 800.78125,-212.90625 C 799.91125,-211.85172 794.77162,-210.247 791.90625,-209.46875 C 789.05372,-208.69399 785.64713,-208.51055 781.46875,-209.5625 C 777.26192,-210.62163 776.11206,-211.60416 771.125,-212.71875 C 775.60954,-211.25929 777.09435,-209.58352 780.9375,-208.46875 C 782.52254,-208.00898 784.22429,-207.8305 785.90625,-207.78125 C 785.46468,-207.44449 784.39374,-206.75352 782.40625,-206 C 779.67232,-204.96351 775.95427,-203.83731 774.40625,-203.5625 C 772.94163,-203.30248 771.34667,-203.67904 771.0625,-203.75 C 771.22275,-203.67035 771.44294,-203.42902 770.84375,-202.6875 C 769.97909,-201.61744 764.92723,-199.86935 762.09375,-199 C 759.27295,-198.13453 755.88625,-197.84369 751.75,-198.78125 C 747.99741,-199.63186 746.70215,-200.49772 742.875,-201.375 C 742.875,-201.375 742.875,-201.21875 742.875,-201.21875 C 746.30296,-199.98096 747.86241,-198.58645 751.25,-197.6875 C 752.88216,-197.25436 754.61704,-197.10449 756.34375,-197.125 C 755.83482,-196.74083 754.867,-196.10318 753.09375,-195.375 C 750.38741,-194.26366 746.65742,-193.06719 745.125,-192.75 C 744.3246,-192.58431 743.51269,-192.53138 742.875,-192.59375 C 742.875,-192.59375 742.875,-192.07823 742.875,-191.67146 C 742.875,-191.40639 742.875,-191.1875 742.875,-191.1875 C 743.10145,-191.33218 743.32391,-191.46011 743.59375,-191.5625 C 744.67427,-191.97248 745.76536,-191.77827 749.59375,-193.25 C 753.42218,-194.72174 754.81787,-195.25498 755.5,-195.65625 C 756.1796,-196.05603 757.11165,-196.53562 757.71875,-197.1875 C 759.5456,-197.32525 761.2895,-197.68073 762.65625,-198.1875 C 765.62437,-199.28802 767.53162,-199.99369 769.4375,-200.65625 C 771.34336,-201.31879 771.79159,-202.07112 772.84375,-202.4375 C 773.9353,-202.81761 775.03886,-202.60288 778.90625,-203.96875 C 782.7737,-205.33461 784.18941,-205.79583 784.875,-206.1875 C 785.57609,-206.58802 786.57581,-207.12048 787.1875,-207.78125 C 789.1583,-207.83591 791.00435,-208.16588 792.46875,-208.65625 C 795.47023,-209.66133 797.3949,-210.27796 799.3125,-210.90625 C 800.8511,-211.41035 801.48652,-211.95302 802.21875,-212.34375 C 802.44891,-212.47806 802.69449,-212.59748 802.96875,-212.6875 C 804.06698,-213.04798 805.1502,-212.76887 809.0625,-214 C 812.97483,-215.23113 814.42855,-215.67295 815.125,-216.03125 C 815.81888,-216.38822 816.75515,-216.82386 817.375,-217.4375 C 819.24021,-217.46016 821.01081,-217.70433 822.40625,-218.125 C 825.43668,-219.03854 827.39863,-219.5551 829.34375,-220.09375 C 831.28886,-220.63239 831.76993,-221.35827 832.84375,-221.65625 C 833.95776,-221.9654 835.06369,-221.64886 839.03125,-222.6875 C 842.99886,-223.72613 844.44883,-224.12023 845.15625,-224.4375 C 845.89112,-224.76709 846.97008,-225.19122 847.59375,-225.8125 C 849.59149,-225.6965 851.45118,-225.83259 852.9375,-226.1875 C 856.01561,-226.9225 858.02094,-227.28844 860,-227.6875 C 861.58792,-228.00768 862.24429,-228.47805 863,-228.78125 C 863.23757,-228.88805 863.46695,-228.97401 863.75,-229.03125 C 864.88347,-229.26044 866.05448,-228.82232 870.09375,-229.53125 C 874.13308,-230.24018 875.594,-230.45834 876.3125,-230.71875 C 877.02836,-230.97819 878.01678,-231.28599 878.65625,-231.8125 C 880.58052,-231.57301 882.40413,-231.58797 883.84375,-231.8125 C 886.97008,-232.30012 888.9983,-232.51317 891,-232.78125 C 893.00171,-233.04932 893.48869,-233.72639 894.59375,-233.875 C 895.74014,-234.02918 896.86967,-233.57343 900.9375,-234.09375 C 905.00534,-234.61407 906.49763,-234.78948 907.21875,-235.03125 C 907.95585,-235.27839 909.01684,-235.61748 909.65625,-236.15625 C 911.70632,-235.82072 913.63003,-235.75829 915.15625,-235.9375 C 918.29856,-236.30646 920.33619,-236.49686 922.34375,-236.71875 C 923.95451,-236.89677 924.60842,-237.32695 925.375,-237.5625 C 925.61594,-237.64802 925.86912,-237.7181 926.15625,-237.75 C 927.30603,-237.87772 928.45754,-237.40335 932.53125,-237.875 C 936.60499,-238.34665 938.09034,-238.4856 938.8125,-238.71875 C 939.53196,-238.95102 940.51274,-239.19221 941.15625,-239.6875 C 943.09262,-239.35404 944.92631,-239.28326 946.375,-239.4375 C 949.52102,-239.77245 951.55256,-239.95609 953.5625,-240.15625 C 955.57246,-240.35639 956.04664,-240.98264 957.15625,-241.09375 C 958.30739,-241.20903 959.45268,-240.72869 963.53125,-241.15625 C 967.60986,-241.58381 969.12011,-241.71834 969.84375,-241.9375 C 970.5829,-242.16136 971.63947,-242.45075 972.28125,-242.96875 C 974.33835,-242.57008 976.28312,-242.47535 977.8125,-242.625 C 980.96123,-242.9331 982.98834,-243.09825 985,-243.28125 C 986.61407,-243.42807 987.2631,-243.8418 988.03125,-244.0625 C 988.27267,-244.14336 988.52478,-244.19241 988.8125,-244.21875 C 989.96461,-244.3242 991.10546,-243.826 995.1875,-244.21875 C 999.26958,-244.6115 1000.7764,-244.74959 1001.5,-244.96875 C 1002.2209,-245.18708 1003.1997,-245.41645 1003.8438,-245.90625 C 1005.7818,-245.55626 1007.6126,-245.45187 1009.0625,-245.59375 C 1012.2112,-245.90185 1014.2383,-246.067 1016.25,-246.25 C 1018.2616,-246.43299 1018.7642,-247.08802 1019.875,-247.1875 C 1021.0273,-247.29073 1022.1672,-246.80267 1026.25,-247.1875 C 1030.3329,-247.57232 1031.8387,-247.6885 1032.5625,-247.90625 C 1033.3018,-248.12868 1034.3581,-248.42074 1035,-248.9375 C 1037.0574,-248.53573 1039.0029,-248.43417 1040.5313,-248.59375 C 1043.6779,-248.92227 1045.7084,-249.11645 1047.7188,-249.3125 C 1049.3318,-249.46979 1049.9844,-249.94398 1050.75,-250.1875 C 1050.9907,-250.27554 1051.2132,-250.30887 1051.5,-250.34375 C 1052.6483,-250.48345 1053.8167,-250.00384 1057.875,-250.59375 C 1061.9333,-251.18367 1063.4368,-251.37089 1064.1563,-251.625 C 1064.873,-251.87816 1065.8308,-252.18307 1066.4688,-252.71875 C 1068.3885,-252.50681 1070.1887,-252.56734 1071.625,-252.8125 C 1074.7441,-253.3449 1076.7366,-253.74111 1078.7188,-254.125 C 1080.7009,-254.50887 1081.1931,-255.16465 1082.2813,-255.40625 C 1083.4101,-255.65691 1084.5516,-255.28996 1088.5313,-256.28125 C 1092.5109,-257.27253 1093.9609,-257.70055 1094.6563,-258.0625 C 1095.3786,-258.43851 1096.4182,-258.93308 1097.0313,-259.59375 C 1098.9943,-259.6058 1100.825,-259.8848 1102.25,-260.4375 C 1105.2012,-261.58211 1107.1232,-262.30692 1108.9375,-263.1875 C 1110.3932,-263.89403 1111.2723,-264.87391 1111.4844,-265.17188 C 1111.6966,-265.46984 1111.5962,-265.91718 1111.6223,-265.93863 C 1111.6652,-265.97387 1111.9416,-266.0236 1112.1013,-266.36707 C 1112.9602,-268.21415 1114.4223,-272.01166 1114.5365,-272.69652 C 1114.6502,-273.37868 1114.7003,-274.04426 1114.751,-274.44149 C 1114.7804,-274.67101 1114.6043,-275.30693 1114.6264,-275.36553 C 1114.6573,-275.44759 1114.9309,-275.63081 1114.9863,-275.88024 C 1115.2526,-277.07857 1115.0752,-278.07153 1114.8612,-279.48917 C 1114.6472,-280.90681 1113.8775,-284.11131 1113.2243,-284.96543 C 1112.5654,-285.82715 1112.0014,-285.9766 1111.4764,-285.96609 C 1111.2678,-285.69633 1111.6132,-285.703 1111.639,-285.65348 C 1112.3196,-285.60269 1112.573,-285.28484 1113.0582,-284.75686 C 1113.5434,-284.22888 1114.28,-280.90569 1114.4166,-279.4553 C 1114.5532,-278.00491 1114.6066,-276.5951 1114.3286,-275.98666 C 1114.0505,-275.37821 1113.6054,-275.46963 1113.313,-275.40375 C 1113.844,-275.21786 1113.9828,-275.27892 1114.0444,-274.43446 C 1114.1037,-273.62108 1113.9112,-272.79477 1113.5246,-271.62884 C 1113.1334,-270.44883 1111.6794,-267.27886 1111.2389,-267.03007 C 1110.7866,-266.77456 1110.5075,-266.75969 1110.1719,-266.89063 z"
- style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7337);enable-background:new"
- sodipodi:nodetypes="cssscscsscsssccscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssccscsscscssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsszsszssszzcczzzczzzc" />
- <path
- id="path8183"
- d="M 988.75,-263.84375 C 990.66161,-263.20935 993.30027,-262.08534 994.875,-261.03125 C 996.44977,-259.97716 997.7711,-259.54873 1000.4063,-257.65625 C 1003.0145,-255.78311 1005.4332,-254.64103 1007.7188,-253.59375 C 1010.1881,-252.46228 1013.4709,-251.43901 1017.25,-249.65625 C 1016.0428,-250.91465 1010.111,-253.0207 1008.2188,-253.84375 C 1006.3266,-254.66679 1004.0908,-255.77424 1001.2813,-257.625 C 998.47169,-259.47575 997.65906,-260.10654 995.28125,-261.34375 C 992.90343,-262.58094 991.20137,-263.29295 988.75,-263.84375 z"
- style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7297);enable-background:new" />
- <path
- id="path8185"
- d="M 957.5,-260.78125 C 959.41,-260.16315 962.08288,-259.07191 963.65625,-258.03125 C 965.22964,-256.99059 966.55233,-256.54873 969.1875,-254.65625 C 971.79573,-252.7831 974.21442,-251.64104 976.5,-250.59375 C 978.96931,-249.46228 982.25213,-248.439 986.03125,-246.65625 C 984.82397,-247.91465 978.82971,-250.05195 976.9375,-250.875 C 975.04533,-251.69804 972.84084,-252.8055 970.03125,-254.65625 C 967.22167,-256.507 966.4383,-257.09557 964.0625,-258.3125 C 961.68672,-259.52941 959.94929,-260.25135 957.5,-260.78125 z"
- style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7301);enable-background:new" />
- <path
- id="path8187"
- d="M 926.09375,-257.375 C 928.00147,-256.77755 930.64723,-255.71116 932.21875,-254.6875 C 933.79025,-253.66385 935.08897,-253.24779 937.71875,-251.40625 C 940.32166,-249.58352 942.74762,-248.43405 945.03125,-247.40625 C 947.49845,-246.29584 950.7866,-245.31302 954.5625,-243.5625 C 953.35627,-244.8106 947.3906,-246.88059 945.5,-247.6875 C 943.60942,-248.4944 941.39758,-249.57854 938.59375,-251.375 C 935.7899,-253.17144 934.96671,-253.77751 932.59375,-254.96875 C 930.22078,-256.15999 928.54013,-256.87158 926.09375,-257.375 z"
- style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7305);enable-background:new" />
- <path
- id="path8189"
- d="M 894.90625,-253.5625 C 896.80838,-253.00895 899.49326,-251.97363 901.0625,-250.96875 C 902.63173,-249.96388 903.93651,-249.56011 906.5625,-247.75 C 909.16162,-245.95836 911.56284,-244.87811 913.84375,-243.875 C 916.30803,-242.79126 919.60359,-241.83471 923.375,-240.125 C 922.1702,-241.36007 916.20084,-243.36978 914.3125,-244.15625 C 912.42418,-244.94272 910.2373,-245.98705 907.4375,-247.75 C 904.63773,-249.51294 903.83831,-250.11836 901.46875,-251.28125 C 899.09918,-252.44413 897.3455,-253.11537 894.90625,-253.5625 z"
- style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7309);enable-background:new" />
- <path
- id="path8191"
- d="M 863.71875,-248.65625 C 865.59937,-248.22716 868.22302,-247.27587 869.78125,-246.34375 C 871.33948,-245.41164 872.63358,-245.08599 875.25,-243.34375 C 877.83971,-241.61931 880.23067,-240.63573 882.5,-239.71875 C 884.95176,-238.72806 888.23959,-237.84168 892,-236.21875 C 890.79869,-237.42609 884.84751,-239.28484 882.96875,-240 C 881.09,-240.71517 878.88335,-241.68442 876.09375,-243.375 C 873.30412,-245.06557 872.50914,-245.60322 870.15625,-246.65625 C 867.80333,-247.70926 866.13041,-248.36873 863.71875,-248.65625 z"
- style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7313);enable-background:new" />
- <path
- id="path8193"
- d="M 833.15625,-241.375 C 835.00461,-241.07856 837.6257,-240.39868 839.15625,-239.59375 C 840.68683,-238.78882 841.96999,-238.53802 844.53125,-237.0625 C 847.06629,-235.60204 849.42193,-234.73741 851.65625,-234 C 854.07024,-233.20332 857.31336,-232.53311 861.03125,-231.15625 C 859.84354,-232.28498 853.94353,-233.746 852.09375,-234.3125 C 850.24398,-234.879 848.09033,-235.68642 845.34375,-237.15625 C 842.59718,-238.62608 841.84239,-239.07653 839.53125,-239.9375 C 837.2201,-240.79845 835.52654,-241.25759 833.15625,-241.375 z"
- style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7317);enable-background:new" />
- <path
- id="path8195"
- d="M 802.90625,-232.3125 C 804.72845,-232.10123 807.27201,-231.51193 808.78125,-230.78125 C 810.2905,-230.05059 811.53693,-229.85127 814.0625,-228.5 C 816.56226,-227.16254 818.89404,-226.45157 821.09375,-225.84375 C 823.47028,-225.18708 826.65839,-224.77087 830.3125,-223.65625 C 829.14515,-224.70121 823.38362,-225.75954 821.5625,-226.21875 C 819.74139,-226.67796 817.61025,-227.34571 814.90625,-228.65625 C 812.20222,-229.96677 811.43519,-230.37615 809.15625,-231.125 C 806.8773,-231.87383 805.243,-232.30431 802.90625,-232.3125 z"
- style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7321);enable-background:new" />
- <path
- id="path8197"
- d="M 773.1875,-222.1875 C 774.99859,-222.0088 777.50809,-221.52244 779,-220.84375 C 780.49194,-220.16506 781.7534,-220.04553 784.25,-218.78125 C 786.72107,-217.52987 789.04005,-216.88511 791.21875,-216.34375 C 793.57262,-215.75887 796.71009,-215.44623 800.3125,-214.5 C 799.16166,-215.49116 793.45999,-216.2833 791.65625,-216.6875 C 789.85253,-217.0917 787.74072,-217.70866 785.0625,-218.9375 C 782.38432,-220.16634 781.65905,-220.54839 779.40625,-221.21875 C 777.15346,-221.88909 775.50998,-222.22107 773.1875,-222.1875 z"
- style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7329);enable-background:new" />
- <path
- id="path8199"
- d="M 743.5625,-211.1875 C 745.35531,-211.05839 747.83563,-210.63785 749.3125,-210 C 750.7894,-209.36215 752.0286,-209.25844 754.5,-208.0625 C 756.94618,-206.87878 759.22054,-206.31584 761.375,-205.84375 C 763.70267,-205.33372 766.7946,-205.16311 770.375,-204.28125 C 769.23121,-205.25185 763.62741,-205.8719 761.84375,-206.21875 C 760.06008,-206.56559 757.9609,-207.10631 755.3125,-208.25 C 752.66409,-209.39368 751.91755,-209.76631 749.6875,-210.375 C 747.45742,-210.98368 745.86156,-211.28466 743.5625,-211.1875 z"
- style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7325);enable-background:new" />
- </g>
- </g>
- <path
- style="opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- d="M 863.87812,475.6679 C 865.52024,472.4499 867.39593,469.93261 868.73948,465.81892 C 869.5382,462.16103 872.05152,463.78819 875.99995,457.42202 C 877.40188,455.18252 881.47648,457.81338 884.96505,455.02291 C 886.23577,454.21972 887.84993,454.6186 889.44761,454.95978 C 893.213,456.27874 895.27337,458.66333 897.78137,460.76815 C 903.92043,466.73838 918.31551,468.71142 921.26741,467.08161 C 922.70146,464.17687 929.14869,461.67273 933.64178,455.96993 C 934.38989,454.84726 945.37114,447.22547 948.28899,449.40394"
- id="path8201"
- sodipodi:nodetypes="ccccccccc" />
- <path
- style="opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- d="M 888.50059,465.25071 C 895.864,462.01774 902.31149,456.34231 909.20872,451.86619 C 912.51929,449.89665 916.07855,455.0822 920.00472,455.46485 C 922.30245,455.24672 923.71762,456.66744 925.68683,457.10635 C 930.84319,458.42414 928.08476,460.97123 935.66209,463.54607 C 941.8177,465.26647 944.56949,456.7476 950.56184,456.22247 C 955.43923,455.71948 958.66076,455.90644 962.17859,455.96993 C 966.10555,456.10882 966.25714,452.47233 968.23951,450.66663 C 971.22007,447.86141 975.39512,448.81691 978.38436,445.92573 C 979.4019,444.54105 980.33894,442.91488 981.11895,440.81764 C 982.00096,438.8173 984.15901,441.12362 985.91718,442.08033"
- id="path8203"
- sodipodi:nodetypes="ccccccccccc" />
- </g>
- <g
- inkscape:groupmode="layer"
- id="layer15"
- inkscape:label="Feet"
- style="display:inline">
- <path
- style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter9048);enable-background:accumulate"
- d="M 403.27922,1056.3058 L 459.84776,1013.8794 L 531.97265,1028.0215 L 485.30361,1080.3474 L 431.56349,1087.4185 L 403.27922,1056.3058 z"
- id="path8994" />
- <path
- style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- d="M 542.27183,1060.5719 C 540.86456,1079.3731 541.12693,1093.3229 544.35357,1109.8752 C 547.58023,1126.4275 560.75966,1155.7825 564.68798,1173.0589 C 568.61419,1190.326 567.38211,1211.3686 552.22854,1224.2072 C 536.91093,1237.1846 510.17726,1245.8061 484.39623,1239.9409 C 458.61518,1234.0757 414.84716,1190.7175 395.80604,1169.7126 C 376.6939,1148.6293 332.04518,1075.862 317.86751,1045.4368 C 303.68984,1015.0117 305.2079,1008.7182 309.74779,999.90708 C 300.38107,975.38658 297.33408,949.84027 276.03534,924.33044 C 306.36081,927.44488 319.91562,951.28677 336.16102,971.47019 C 330.63113,923.39416 318.10631,907.05369 307.78707,880.74589 C 337.78137,886.82754 358.36643,912.61828 371.76686,953.45839 C 381.32101,949.54048 390.00462,944.08545 401.95427,944.39719 C 390.65677,902.70139 384.00481,874.48135 365.26702,843.32725 C 418.70898,848.99758 448.92404,923.96657 444.23844,931.28805 C 454.21641,929.04406 463.24409,924.75767 474.67497,925.63638 C 463.426,887.28936 453.62716,848.76848 471.01526,806.98819 C 471.01526,806.98819 519.30204,872.42507 525.40492,892.79397 C 531.50779,913.16287 526.92373,931.49448 526.92373,931.49448 C 526.92373,931.49448 543.8833,962.57978 547.21765,982.58862 C 550.59075,1002.83 543.68496,1041.6919 542.27183,1060.5719 z"
- id="path4189"
- sodipodi:nodetypes="czzzzzzcccccccccczczz" />
- <path
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter3587);enable-background:accumulate"
- d="M 719.5,738.69519 L 737.81177,754.12715 L 782.2228,738.73894 L 805.5,713.19519 L 816.96397,732.41584 L 847.63558,745.19938 L 872.73295,750.92775 L 892,723.19519 L 908.02309,747.02126 L 947,752.19519 L 957.24541,745.99667 L 964.00012,754.69487 L 989.5,765.69519 L 991.5,725.19519 L 955.94866,710.6576 L 923.45591,689.1305 L 883.0038,677.66492 L 861.69668,662.13148 L 840,685.19519 L 755.02878,638.61208 L 722,676.69519 L 719.5,738.69519 z"
- id="path4191"
- sodipodi:nodetypes="cccccccccccccccccccccc"
- clip-path="url(#clipPath3631)"
- transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,995.28646,23.53493)" />
- <path
- style="opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;filter:url(#filter3898);enable-background:new"
- d="M 584,696.5 L 577.4375,713.65625 C 577.4375,713.65625 569.62598,734.02113 561.75,757.3125 C 557.81201,768.95818 553.86698,781.35395 550.8125,792.4375 C 547.75802,803.52105 545.47664,812.81736 545.3125,820.71875 C 544.91443,839.88071 551.05903,855.60705 554.25,862.46875 C 553.47847,866.02398 552.25863,871.92307 550.90625,880.5625 C 548.98583,892.83071 547.18798,907.71691 548.53125,920.4375 C 549.91334,933.52585 555.34347,948.62515 561.125,963.46875 C 566.90653,978.31235 573.17935,992.69586 576.34375,1001.5 C 582.97581,1019.9519 586.33671,1033.0763 587.65625,1050 C 588.2376,1057.4561 587.41398,1070.336 586.40625,1083.375 C 585.39852,1096.414 584.21964,1109.6764 584.71875,1120.3438 C 585.70786,1141.4836 594.04673,1167.1785 618.09375,1178.2812 C 640.86858,1188.7966 673.42057,1189.9834 701.53125,1174.8438 C 717.69117,1166.1404 731.60759,1147.7462 744.90625,1127.9375 C 758.20491,1108.1288 769.87542,1086.8841 776.84375,1073.0312 C 792.19667,1042.51 816.23728,957.56702 822.46875,920.3125 C 825.48734,902.26597 826.39041,891.24695 825.09375,882.28125 C 824.11522,875.51521 821.26556,870.13385 818.21875,866.0625 C 820.26149,838.55459 817.48668,814.69372 830.1875,786.65625 L 840.75,763.375 L 816.9375,772.6875 C 799.44775,779.52503 788.03586,791.73286 780.34375,804.75 C 780.02124,805.29577 779.78061,805.85776 779.46875,806.40625 C 779.69078,783.89104 783.87659,768.76866 786.0625,747.71875 L 788.03125,728.71875 L 771,737.375 C 740.40551,752.93071 725.30511,785.56821 721.28125,827.59375 C 717.03593,826.96828 712.44985,826.5741 707.46875,826.75 C 707.17726,787.56964 707.07246,759.71315 716.0625,727.375 L 721.65625,707.25 L 702.21875,714.90625 C 671.30938,727.11019 654.35921,756.83698 645.59375,783.28125 C 641.21102,796.50339 638.84793,809.08246 638,819.21875 C 637.76797,821.99248 637.68894,824.53007 637.6875,826.9375 C 634.44563,826.90109 631.26698,827.07339 627.625,827.4375 C 627.66662,788.43277 624.14076,747.68335 595.34375,710.9375 L 584,696.5 z M 589.8125,740.3125 C 606.61941,770.95633 607.28701,804.27978 606.75,840.0625 L 606.53125,855.125 L 618.56618,848.58579 C 627.22823,845.45277 638.12676,848.35827 650.5,847.75 L 665.17465,857.1066 L 658.84375,831.3125 C 658.7541,831.08253 658.62329,830.89581 658.59375,830.59375 C 658.39424,828.55389 658.37143,825.12068 658.71875,820.96875 C 659.41339,812.66489 661.50832,801.38351 665.34375,789.8125 C 670.49907,774.25956 678.83176,758.62002 690.46875,747.28125 C 685.78494,775.91923 687.25316,807.54059 687.45711,843.08639 L 684.69118,856.34803 L 700.1875,848.75 C 709.2169,845.99229 717.37647,848.40004 729.46875,849.84375 L 742.71507,859.28798 L 741.09375,840 C 742.54168,809.02823 749.31524,786.32192 761.8125,771.125 C 758.82562,790.90384 756.38207,812.9098 762.125,849.46875 L 763.19052,855.84193 L 760.25237,867.35878 L 770.86948,859.1906 L 780.05921,869.41258 L 778.51093,858.94898 L 781.9375,852 C 787.63852,838.78851 792.11032,825.78663 798.28125,815.34375 C 799.24111,813.71941 800.31278,812.27939 801.34375,810.78125 C 797.66309,831.9366 798.91659,850.9894 797.25,868.5625 L 792.56986,876.36948 L 799.96875,876.59375 C 803.1888,880.07736 803.83625,880.44443 804.53125,885.25 C 805.22625,890.05557 804.84987,899.65035 801.96875,916.875 C 796.40076,950.16292 770.12313,994.71481 758.22835,1018.3614 C 751.62344,1031.4918 739.70002,1075.8473 727.105,1094.6079 C 714.50998,1113.3684 698.57363,1134.3752 689.93296,1139.0288 C 668.44244,1150.603 645.37702,1164.5347 629.31407,1157.1183 C 614.93921,1150.4813 606.27438,1135.9256 605.5,1119.375 C 605.11689,1111.187 606.11279,1098.0658 607.125,1084.9688 C 608.13721,1071.8717 618.41391,1062.398 622.54839,1048.4062 C 627.92068,1030.2254 621.10152,1011.8118 610.04839,994.46875 C 603.56184,984.29097 586.07159,970.21085 580.5,955.90625 C 574.92841,941.60165 570.13249,926.9031 569.21875,918.25 C 568.29254,909.47887 569.64125,895.22498 571.4375,883.75 C 573.23375,872.27503 575.28125,863.46875 575.28125,863.46875 L 584.70403,859.85355 L 574.21875,855.96875 C 574.21875,855.96875 565.71986,840.65865 566.125,821.15625 C 566.19611,817.73309 567.96126,808.4282 570.84375,797.96875 C 573.72624,787.5093 577.60841,775.41604 581.46875,764 C 584.51314,754.99692 587.24938,747.39655 589.8125,740.3125 z"
- id="path4193"
- clip-path="url(#clipPath3677)"
- sodipodi:nodetypes="ccssscsssssssssssssccccscccccccccsscccccccccccssscccccccccccccccsccccssssssssssssscccsssc"
- transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,822.28931,10.93589)" />
- <g
- id="g3617"
- clip-path="url(#clipPath3622)"
- transform="translate(276,136)">
- <path
- transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,-52.200498,74.09707)"
- id="path4195"
- d="M -15.66751,843.48852 L -65.16499,827.93217 L -92.03504,880.25807 L -51.02285,925.51291 L -1.52538,887.32914 L -15.66751,843.48852 z"
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter9024);enable-background:accumulate" />
- <path
- sodipodi:nodetypes="ccccccccccccc"
- transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,-46.92842,75.511284)"
- id="path4197"
- d="M 118.70648,859.93048 L 63.552152,813.26144 L 19.711532,850.03099 L 53.652662,903.7711 L 40.055848,989.23313 L 0.61048221,1017.5253 L -40.401718,1028.839 L -43.230138,1075.508 L 13.338402,1100.9639 L 32.282389,1031.3139 L 55.738939,972.45727 L 102.08648,899.84236 L 118.70648,859.93048 z"
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter9020);enable-background:accumulate" />
- </g>
- <path
- style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter9044);enable-background:accumulate"
- d="M -70.82184,932.58397 L -10.01066,905.71392 L 90.3985,936.82662 L 26.75889,967.93931 L -55.26549,950.96875 L -70.82184,932.58397 z"
- id="path4199"
- transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,229.07158,211.51128)" />
- <path
- style="opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;filter:url(#filter4105);enable-background:new"
- d="M 583.0625,715.75 C 570.95641,750.19974 556.348,784.28333 551.3125,820.59375 C 550.48042,835.52242 555.90165,849.75318 560.15625,863.65625 C 554.24001,890.85751 550.01944,920.5562 561.3125,946.78125 C 574.82967,984.9421 596.31397,1022.4634 593.73529,1064.2495 C 592.78699,1093.5437 584.72085,1125.2436 599.125,1152.5312 C 609.32364,1171.866 632.26456,1179.8429 653.09285,1180.1988 C 680.95504,1181.3729 709.55546,1168.5772 725.09375,1144.9375 C 747.68924,1115.5658 766.89426,1083.4402 780.3324,1048.8777 C 797.22293,1003.3717 810.0042,956.31698 818.26642,908.4788 C 820.09082,895.53774 821.3675,881.00895 813.6875,869.65625 C 810.25635,862.31993 813.72957,854.09611 813.00293,846.34648 C 813.67693,821.35182 817.01525,795.68272 829.65625,773.75 C 811.92312,780.1946 794.58357,790.30971 785.65318,807.61425 C 781.7181,814.3238 778.04836,821.18838 774.28125,828 C 770.73126,797.98592 778.00088,768.35172 781.0625,738.71875 C 760.89646,747.77338 744.18578,764.37397 736.88755,785.40075 C 730.58292,800.98078 728.08533,817.71793 726.625,834.4375 C 718.37166,832.91825 709.94053,832.33595 701.5625,832.9375 C 700.59942,794.23963 701.09554,753.53035 712.53125,717.03125 C 693.85012,723.24901 677.36504,735.76676 666.90322,752.41848 C 653.05068,773.29827 645.64182,798.17243 643.84375,823.03125 C 644.42909,827.35579 643.78249,834.87134 637.5,832.90625 C 632.16882,832.9238 626.87092,833.58508 621.5625,834 C 622.71034,794.61852 618.22106,752.3718 594.5,719.78125 C 591.43929,716.14408 588.86315,712.09687 585.875,708.4375 C 584.9375,710.875 584,713.3125 583.0625,715.75 z M 590.8125,729.59375 C 609.37777,758.89004 613.295,794.41387 612.9375,828.46875 C 613.14159,833.64401 612.42094,840.29795 613.0625,844.53125 C 625.38106,838.4285 639.80162,842.09135 652.84375,842.34375 C 655.16087,843.567 656.03585,843.99618 654.75,840.9375 C 650.58545,826.98465 652.90172,812.3245 656.55504,798.52986 C 662.92191,772.23922 677.18332,747.44188 699.375,731.5 C 690.75791,768.73706 693.65842,808.06161 693.28125,845.46875 C 705.53469,838.55885 720.56004,842.02262 733.3125,845.21875 C 736.70472,848.75355 735.60185,844.48927 735.5,841.40625 C 735.01691,820.03567 739.63133,798.33662 749.1875,779.25 C 755.15016,768.56273 763.43088,759.44621 771.625,750.375 C 763.75344,784.2131 762.4221,819.71093 768.90625,853.875 C 770.6311,852.46382 773.51306,853.42086 774.5625,853.5 C 784.24619,832.26318 790.91362,808.11938 809.45266,792.75815 C 811.32595,792.38693 808.00448,801.2831 807.96875,804.65625 C 804.43387,826.50206 800.79359,848.79859 799.18454,870.87536 C 790.40075,873.21707 802.03289,873.1989 802.65329,874.93786 C 810.5764,885.50366 807.31628,899.34258 806.28494,911.2912 C 799.22089,956.32475 784.14263,998.65314 770.33139,1041.971 C 758.25663,1074.9203 742.95719,1100.8235 722.44331,1129.1725 C 711.49074,1142.7239 699.19859,1157.0238 681.59956,1161.6725 C 661.44355,1167.9138 637.3928,1172.5494 619,1161.7188 C 601.71034,1149.3774 597.97607,1126.0099 599.73774,1106.0324 C 599.78653,1090.2062 604.6766,1077.5203 604.14834,1062.5406 C 603.6101,1047.2777 601.85699,1031.9759 597.60573,1015.6743 C 593.35447,999.37268 588.56248,990.75636 581.48667,974.10092 C 574.24556,957.05636 566.41652,937.35229 563.28125,917.8125 C 561.53177,899.18536 566.17296,880.68988 569.0625,862.5625 C 572.35873,859.72554 567.46451,857.36591 566.75,854.375 C 559.14887,837.35992 558.34253,817.6001 564.00766,799.81502 C 571.13786,774.74272 579.76853,750.18261 588.6875,725.6875 C 589.39583,726.98958 590.10417,728.29167 590.8125,729.59375 z"
- id="path4201"
- sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccczzzcccccc"
- clip-path="url(#clipPath4177)"
- transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,822.28931,10.93589)" />
- <path
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4130);enable-background:accumulate"
- d="M 735.05635,733.03834 L 737.81177,754.12715 L 782.2228,738.73894 L 787.07343,716.34919 L 783.13726,694.29697 L 760.68563,657.70396 L 752.40559,688.0089 L 735.05635,733.03834 z"
- id="path4203"
- sodipodi:nodetypes="cccccccc"
- clip-path="url(#clipPath3631)"
- transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,995.28646,23.53493)" />
- <path
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4141);enable-background:accumulate"
- d="M 831.81321,730.29452 L 847.63558,745.19938 L 868.49031,748.09932 L 866.90002,708.17334 L 875.22563,677.66492 L 868.06064,671.32386 L 846.36395,692.26626 L 831.81321,730.29452 z"
- id="path4205"
- sodipodi:nodetypes="cccccccc"
- clip-path="url(#clipPath3631)"
- transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,995.28646,23.53493)" />
- <g
- id="g8317"
- style="filter:url(#filter8333)"
- clip-path="url(#clipPath8338)"
- transform="translate(276,136)">
- <path
- transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,719.28646,-112.46507)"
- clip-path="none"
- sodipodi:nodetypes="ccccc"
- id="path4209"
- d="M 964.00012,754.69487 L 982.42893,762.15966 L 991.5,725.19519 L 976.62969,730.03405 L 964.00012,754.69487 z"
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- y="757.19519"
- x="-55"
- height="177"
- width="182"
- id="rect8315"
- style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- </g>
- <g
- id="g8346"
- style="filter:url(#filter8354)"
- clip-path="url(#clipPath8359)"
- transform="translate(276,136)">
- <path
- transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,719.28646,-112.46507)"
- clip-path="none"
- sodipodi:nodetypes="ccccccc"
- id="path4207"
- d="M 910.14441,746.31415 L 942.75736,751.48808 L 942.39617,727.61189 L 949.5847,697.92968 L 941.13358,692.66603 L 919.31164,719.1768 L 910.14441,746.31415 z"
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- y="696.19519"
- x="-22"
- height="176"
- width="165"
- id="rect8344"
- style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- </g>
- </g>
- <g
- inkscape:groupmode="layer"
- id="layer16"
- inkscape:label="Left Foot"
- style="display:inline">
- <path
- style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
- d="M 1036.164,1071.8338 C 1042.9581,1090.7366 1046.6577,1105.1335 1048.0543,1123.0457 C 1049.4509,1140.958 1044.2716,1174.8465 1045.1538,1193.7018 C 1046.0356,1212.547 1053.2875,1233.8008 1072.4984,1242.6707 C 1091.9173,1251.6365 1121.8177,1252.882 1146.6183,1239.5251 C 1171.4189,1226.1681 1204.0193,1169.1996 1217.5925,1142.2164 C 1231.2164,1115.1325 1256.3536,1027.719 1262.2533,992.44781 C 1268.1531,957.1766 1264.8039,951.14704 1257.6359,943.39232 C 1260.2762,915.55217 1256.1361,888.45689 1270.7455,856.20614 C 1240.4965,868.03184 1233.3632,896.36684 1222.4266,921.71122 C 1214.4257,870.77829 1222.6358,850.43803 1225.7455,820.49186 C 1196.6808,835.26977 1182.884,867.60588 1180.7455,913.349 C 1169.8216,912.0448 1159.3541,908.91477 1147.1741,912.63471 C 1146.9101,866.61137 1145.7106,835.7453 1156.0847,798.42822 C 1102.8293,819.45508 1093.1375,905.02232 1100.0312,911.20614 C 1089.1484,911.74114 1078.6602,909.90884 1067.1741,914.06329 C 1067.813,871.49194 1066.9136,829.15468 1037.1741,791.20614 C 1037.1741,791.20614 1006.2161,872.12848 1005.7455,894.77757 C 1005.275,917.42666 1015.1971,934.94345 1015.1971,934.94345 C 1015.1971,934.94345 1006.6291,971.68396 1008.8985,993.17568 C 1011.1944,1014.9171 1029.3414,1052.8519 1036.164,1071.8338 z"
- id="path8848"
- sodipodi:nodetypes="czzzzzzcccccccccczczz" />
- <path
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter3587);enable-background:accumulate"
- d="M 719.5,738.69519 L 737.81177,754.12715 L 782.2228,738.73894 L 805.5,713.19519 L 816.96397,732.41584 L 847.63558,745.19938 L 872.73295,750.92775 L 892,723.19519 L 908.02309,747.02126 L 947,752.19519 L 957.24541,745.99667 L 964.00012,754.69487 L 989.5,765.69519 L 991.5,725.19519 L 955.94866,710.6576 L 923.45591,689.1305 L 883.0038,677.66492 L 861.69668,662.13148 L 840,685.19519 L 755.02878,638.61208 L 722,676.69519 L 719.5,738.69519 z"
- id="path3635"
- sodipodi:nodetypes="cccccccccccccccccccccc"
- clip-path="url(#clipPath3631)"
- transform="translate(276,136)" />
- <path
- transform="translate(450.03125,73.843964)"
- style="opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;filter:url(#filter3898);enable-background:new"
- d="M 584,696.5 L 577.4375,713.65625 C 577.4375,713.65625 569.62598,734.02113 561.75,757.3125 C 557.81201,768.95818 553.86698,781.35395 550.8125,792.4375 C 547.75802,803.52105 545.47664,812.81736 545.3125,820.71875 C 544.91443,839.88071 551.05903,855.60705 554.25,862.46875 C 553.47847,866.02398 552.25863,871.92307 550.90625,880.5625 C 548.98583,892.83071 547.18798,907.71691 548.53125,920.4375 C 549.91334,933.52585 555.34347,948.62515 561.125,963.46875 C 566.90653,978.31235 573.17935,992.69586 576.34375,1001.5 C 582.97581,1019.9519 586.33671,1033.0763 587.65625,1050 C 588.2376,1057.4561 587.41398,1070.336 586.40625,1083.375 C 585.39852,1096.414 584.21964,1109.6764 584.71875,1120.3438 C 585.70786,1141.4836 594.04673,1167.1785 618.09375,1178.2812 C 640.86858,1188.7966 673.42057,1189.9834 701.53125,1174.8438 C 717.69117,1166.1404 731.60759,1147.7462 744.90625,1127.9375 C 758.20491,1108.1288 769.87542,1086.8841 776.84375,1073.0312 C 792.19667,1042.51 816.23728,957.56702 822.46875,920.3125 C 825.48734,902.26597 826.39041,891.24695 825.09375,882.28125 C 824.11522,875.51521 821.26556,870.13385 818.21875,866.0625 C 820.26149,838.55459 817.48668,814.69372 830.1875,786.65625 L 840.75,763.375 L 816.9375,772.6875 C 799.44775,779.52503 788.03586,791.73286 780.34375,804.75 C 780.02124,805.29577 779.78061,805.85776 779.46875,806.40625 C 779.69078,783.89104 783.87659,768.76866 786.0625,747.71875 L 788.03125,728.71875 L 771,737.375 C 740.40551,752.93071 725.30511,785.56821 721.28125,827.59375 C 717.03593,826.96828 712.44985,826.5741 707.46875,826.75 C 707.17726,787.56964 707.07246,759.71315 716.0625,727.375 L 721.65625,707.25 L 702.21875,714.90625 C 671.30938,727.11019 654.35921,756.83698 645.59375,783.28125 C 641.21102,796.50339 638.84793,809.08246 638,819.21875 C 637.76797,821.99248 637.68894,824.53007 637.6875,826.9375 C 634.44563,826.90109 631.26698,827.07339 627.625,827.4375 C 627.66662,788.43277 624.14076,747.68335 595.34375,710.9375 L 584,696.5 z M 589.8125,740.3125 C 606.61941,770.95633 607.28701,804.27978 606.75,840.0625 L 606.53125,855.125 L 618.56618,848.58579 C 627.22823,845.45277 638.12676,848.35827 650.5,847.75 L 665.17465,857.1066 L 658.84375,831.3125 C 658.7541,831.08253 658.62329,830.89581 658.59375,830.59375 C 658.39424,828.55389 658.37143,825.12068 658.71875,820.96875 C 659.41339,812.66489 661.50832,801.38351 665.34375,789.8125 C 670.49907,774.25956 678.83176,758.62002 690.46875,747.28125 C 685.78494,775.91923 687.25316,807.54059 687.45711,843.08639 L 684.69118,856.34803 L 700.1875,848.75 C 709.2169,845.99229 717.37647,848.40004 729.46875,849.84375 L 742.71507,859.28798 L 741.09375,840 C 742.54168,809.02823 749.31524,786.32192 761.8125,771.125 C 758.82562,790.90384 756.38207,812.9098 762.125,849.46875 L 763.19052,855.84193 L 760.25237,867.35878 L 770.86948,859.1906 L 780.05921,869.41258 L 778.51093,858.94898 L 781.9375,852 C 787.63852,838.78851 792.11032,825.78663 798.28125,815.34375 C 799.24111,813.71941 800.31278,812.27939 801.34375,810.78125 C 797.66309,831.9366 798.91659,850.9894 797.25,868.5625 L 792.56986,876.36948 L 799.96875,876.59375 C 803.1888,880.07736 803.83625,880.44443 804.53125,885.25 C 805.22625,890.05557 804.84987,899.65035 801.96875,916.875 C 796.40076,950.16292 770.17603,1040.0409 758.28125,1063.6875 C 751.67634,1076.8179 740.25127,1097.5832 727.65625,1116.3438 C 715.06123,1135.1043 700.29692,1151.8776 691.65625,1156.5312 C 670.16573,1168.1054 642.87545,1166.7914 626.8125,1159.375 C 612.43764,1152.738 606.27438,1135.9256 605.5,1119.375 C 605.11689,1111.187 606.11279,1098.0658 607.125,1084.9688 C 608.13721,1071.8717 618.41391,1062.398 622.54839,1048.4062 C 627.92068,1030.2254 621.10152,1011.8118 610.04839,994.46875 C 603.56184,984.29097 586.07159,970.21085 580.5,955.90625 C 574.92841,941.60165 570.13249,926.9031 569.21875,918.25 C 568.29254,909.47887 569.64125,895.22498 571.4375,883.75 C 573.23375,872.27503 575.28125,863.46875 575.28125,863.46875 L 584.70403,859.85355 L 574.21875,855.96875 C 574.21875,855.96875 565.71986,840.65865 566.125,821.15625 C 566.19611,817.73309 567.96126,808.4282 570.84375,797.96875 C 573.72624,787.5093 577.60841,775.41604 581.46875,764 C 584.51314,754.99692 587.24938,747.39655 589.8125,740.3125 z"
- id="path3669"
- clip-path="url(#clipPath3677)"
- sodipodi:nodetypes="ccssscsssssssssssssccccscccccccccsscccccccccccssscccccccccccccccsccccssssssssssssscccsssc" />
- <g
- id="g3628"
- clip-path="url(#clipPath3636)"
- transform="translate(276,136)">
- <path
- id="path8988"
- d="M 824.48651,818.48242 L 774.98903,802.92607 L 748.11898,855.25197 L 789.13117,900.50681 L 838.62864,862.32304 L 824.48651,818.48242 z"
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter9024);enable-background:accumulate" />
- <path
- id="path8990"
- d="M 964.49365,855.25197 L 909.33932,808.58293 L 865.4987,845.35248 L 899.43983,899.09259 L 906.51089,965.56063 L 855.59921,1000.916 L 814.58701,1012.2297 L 811.75859,1058.8987 L 868.32713,1084.3546 L 931.96674,1007.987 L 956.00837,913.23473 L 964.49365,855.25197 z"
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter9020);enable-background:accumulate" />
- </g>
- <path
- style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter9044);enable-background:accumulate"
- d="M 1045.3322,1043.5779 L 1106.1434,1016.7078 L 1206.5525,1047.8205 L 1142.9129,1078.9332 L 1060.8885,1061.9626 L 1045.3322,1043.5779 z"
- id="path8992" />
- <path
- transform="translate(450.03125,73.843964)"
- style="opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;filter:url(#filter4185);enable-background:new"
- d="M 583.0625,715.75 C 570.95641,750.19974 556.348,784.28333 551.3125,820.59375 C 550.48042,835.52242 555.90165,849.75318 560.15625,863.65625 C 554.24001,890.85751 550.01944,920.5562 561.3125,946.78125 C 574.82967,984.9421 596.31397,1022.4634 593.73529,1064.2495 C 592.78699,1093.5437 584.72085,1125.2436 599.125,1152.5312 C 609.32364,1171.866 632.26456,1179.8429 653.09285,1180.1988 C 680.95504,1181.3729 709.55546,1168.5772 725.09375,1144.9375 C 747.68924,1115.5658 766.89426,1083.4402 780.3324,1048.8777 C 797.22293,1003.3717 810.0042,956.31698 818.26642,908.4788 C 820.09082,895.53774 821.3675,881.00895 813.6875,869.65625 C 810.25635,862.31993 813.72957,854.09611 813.00293,846.34648 C 813.67693,821.35182 817.01525,795.68272 829.65625,773.75 C 811.92312,780.1946 794.58357,790.30971 785.65318,807.61425 C 781.7181,814.3238 778.04836,821.18838 774.28125,828 C 770.73126,797.98592 778.00088,768.35172 781.0625,738.71875 C 760.89646,747.77338 744.18578,764.37397 736.88755,785.40075 C 730.58292,800.98078 728.08533,817.71793 726.625,834.4375 C 718.37166,832.91825 709.94053,832.33595 701.5625,832.9375 C 700.59942,794.23963 701.09554,753.53035 712.53125,717.03125 C 693.85012,723.24901 677.36504,735.76676 666.90322,752.41848 C 653.05068,773.29827 645.64182,798.17243 643.84375,823.03125 C 644.42909,827.35579 643.78249,834.87134 637.5,832.90625 C 632.16882,832.9238 626.87092,833.58508 621.5625,834 C 622.71034,794.61852 618.22106,752.3718 594.5,719.78125 C 591.43929,716.14408 588.86315,712.09687 585.875,708.4375 C 584.9375,710.875 584,713.3125 583.0625,715.75 z M 590.8125,729.59375 C 609.37777,758.89004 613.295,794.41387 612.9375,828.46875 C 613.14159,833.64401 612.42094,840.29795 613.0625,844.53125 C 625.38106,838.4285 639.80162,842.09135 652.84375,842.34375 C 655.16087,843.567 656.03585,843.99618 654.75,840.9375 C 650.58545,826.98465 652.90172,812.3245 656.55504,798.52986 C 662.92191,772.23922 677.18332,747.44188 699.375,731.5 C 690.75791,768.73706 693.65842,808.06161 693.28125,845.46875 C 705.53469,838.55885 720.56004,842.02262 733.3125,845.21875 C 736.70472,848.75355 735.60185,844.48927 735.5,841.40625 C 735.01691,820.03567 739.63133,798.33662 749.1875,779.25 C 755.15016,768.56273 763.43088,759.44621 771.625,750.375 C 763.75344,784.2131 762.4221,819.71093 768.90625,853.875 C 770.6311,852.46382 773.51306,853.42086 774.5625,853.5 C 784.24619,832.26318 790.91362,808.11938 809.45266,792.75815 C 811.32595,792.38693 808.00448,801.2831 807.96875,804.65625 C 804.43387,826.50206 804.67155,848.82948 803.0625,870.90625 C 801.75012,872.28304 805.91085,873.22979 806.53125,874.96875 C 814.45436,885.53455 809.65419,899.80024 808.62285,911.74886 C 801.5588,956.78241 786.85732,1000.1282 773.04608,1043.446 C 760.97132,1076.3953 742.32638,1106.526 721.8125,1134.875 C 710.85993,1148.4264 698.56778,1162.7263 680.96875,1167.375 C 660.81274,1173.6163 637.3928,1172.5494 619,1161.7188 C 601.71034,1149.3774 597.97607,1126.0099 599.73774,1106.0324 C 599.78653,1090.2062 602.10985,1078.2316 607.65521,1063.2271 C 613.20056,1048.2226 610.12626,1031.8954 605.875,1015.5938 C 601.62374,999.2922 593.69597,989.33378 584.05342,973.38963 C 574.41087,957.44548 566.41652,937.35229 563.28125,917.8125 C 561.53177,899.18536 566.17296,880.68988 569.0625,862.5625 C 572.35873,859.72554 567.46451,857.36591 566.75,854.375 C 559.14887,837.35992 558.34253,817.6001 564.00766,799.81502 C 571.13786,774.74272 579.76853,750.18261 588.6875,725.6875 C 589.39583,726.98958 590.10417,728.29167 590.8125,729.59375 z"
- id="path4149"
- sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccczzzcccccc"
- clip-path="url(#clipPath4177)" />
- <path
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4130);enable-background:accumulate"
- d="M 735.05635,733.03834 L 737.81177,754.12715 L 782.2228,738.73894 L 787.07343,716.34919 L 783.13726,694.29697 L 760.68563,657.70396 L 752.40559,688.0089 L 735.05635,733.03834 z"
- id="path3902"
- sodipodi:nodetypes="cccccccc"
- clip-path="url(#clipPath3631)"
- transform="translate(276,136)" />
- <path
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4141);enable-background:accumulate"
- d="M 831.81321,730.29452 L 847.63558,745.19938 L 868.49031,748.09932 L 866.90002,708.17334 L 875.22563,677.66492 L 868.06064,671.32386 L 846.36395,692.26626 L 831.81321,730.29452 z"
- id="path4135"
- sodipodi:nodetypes="cccccccc"
- clip-path="url(#clipPath3631)"
- transform="translate(276,136)" />
- <g
- id="g8367"
- style="filter:url(#filter8379)"
- clip-path="url(#clipPath8392)"
- transform="translate(276,136)">
- <path
- clip-path="none"
- sodipodi:nodetypes="ccccccc"
- id="path4145"
- d="M 910.14441,746.31415 L 942.75736,751.48808 L 942.39617,727.61189 L 949.5847,697.92968 L 941.13358,692.66603 L 919.31164,719.1768 L 910.14441,746.31415 z"
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- y="650.19098"
- x="877.51953"
- height="172.53406"
- width="123.03658"
- id="rect8365"
- style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- </g>
- <g
- id="g8400"
- style="filter:url(#filter8404)"
- clip-path="url(#clipPath8417)"
- transform="translate(276,136)">
- <path
- clip-path="none"
- sodipodi:nodetypes="ccccc"
- id="path4147"
- d="M 964.00012,754.69487 L 982.42893,762.15966 L 991.5,725.19519 L 976.62969,730.03405 L 964.00012,754.69487 z"
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- <rect
- y="677.06104"
- x="924.89569"
- height="125.1579"
- width="142.12846"
- id="rect8398"
- style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- </g>
- </g>
-</svg>
diff --git a/Documentation/logo.txt b/Documentation/logo.txt
index a2e62445e28e..296f0f7f67eb 100644
--- a/Documentation/logo.txt
+++ b/Documentation/logo.txt
@@ -1,4 +1,13 @@
-Tux is taking a three month sabbatical to work as a barber, so Tuz is
-standing in. He's taken pains to ensure you'll hardly notice.
+This is the full-colour version of the currently unofficial Linux logo
+("currently unofficial" just means that there has been no paperwork and
+that I have not really announced it yet). It was created by Larry Ewing,
+and is freely usable as long as you acknowledge Larry as the original
+artist.
+
+Note that there are black-and-white versions of this available that
+scale down to smaller sizes and are better for letterheads or whatever
+you want to use it for: for the full range of logos take a look at
+Larry's web-page:
+
+ http://www.isc.tamu.edu/~lewing/linux/
-Image by Andrew McGown and Josh Bush. Image is licensed CC BY-SA.
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index f5b7127f54ac..7f5809eddee6 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -31,6 +31,7 @@ Contents:
- Locking functions.
- Interrupt disabling functions.
+ - Sleep and wake-up functions.
- Miscellaneous functions.
(*) Inter-CPU locking barrier effects.
@@ -1217,6 +1218,132 @@ barriers are required in such a situation, they must be provided from some
other means.
+SLEEP AND WAKE-UP FUNCTIONS
+---------------------------
+
+Sleeping and waking on an event flagged in global data can be viewed as an
+interaction between two pieces of data: the task state of the task waiting for
+the event and the global data used to indicate the event. To make sure that
+these appear to happen in the right order, the primitives to begin the process
+of going to sleep, and the primitives to initiate a wake up imply certain
+barriers.
+
+Firstly, the sleeper normally follows something like this sequence of events:
+
+ for (;;) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ if (event_indicated)
+ break;
+ schedule();
+ }
+
+A general memory barrier is interpolated automatically by set_current_state()
+after it has altered the task state:
+
+ CPU 1
+ ===============================
+ set_current_state();
+ set_mb();
+ STORE current->state
+ <general barrier>
+ LOAD event_indicated
+
+set_current_state() may be wrapped by:
+
+ prepare_to_wait();
+ prepare_to_wait_exclusive();
+
+which therefore also imply a general memory barrier after setting the state.
+The whole sequence above is available in various canned forms, all of which
+interpolate the memory barrier in the right place:
+
+ wait_event();
+ wait_event_interruptible();
+ wait_event_interruptible_exclusive();
+ wait_event_interruptible_timeout();
+ wait_event_killable();
+ wait_event_timeout();
+ wait_on_bit();
+ wait_on_bit_lock();
+
+
+Secondly, code that performs a wake up normally follows something like this:
+
+ event_indicated = 1;
+ wake_up(&event_wait_queue);
+
+or:
+
+ event_indicated = 1;
+ wake_up_process(event_daemon);
+
+A write memory barrier is implied by wake_up() and co. if and only if they wake
+something up. The barrier occurs before the task state is cleared, and so sits
+between the STORE to indicate the event and the STORE to set TASK_RUNNING:
+
+ CPU 1 CPU 2
+ =============================== ===============================
+ set_current_state(); STORE event_indicated
+ set_mb(); wake_up();
+ STORE current->state <write barrier>
+ <general barrier> STORE current->state
+ LOAD event_indicated
+
+The available waker functions include:
+
+ complete();
+ wake_up();
+ wake_up_all();
+ wake_up_bit();
+ wake_up_interruptible();
+ wake_up_interruptible_all();
+ wake_up_interruptible_nr();
+ wake_up_interruptible_poll();
+ wake_up_interruptible_sync();
+ wake_up_interruptible_sync_poll();
+ wake_up_locked();
+ wake_up_locked_poll();
+ wake_up_nr();
+ wake_up_poll();
+ wake_up_process();
+
+
+[!] Note that the memory barriers implied by the sleeper and the waker do _not_
+order multiple stores before the wake-up with respect to loads of those stored
+values after the sleeper has called set_current_state(). For instance, if the
+sleeper does:
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (event_indicated)
+ break;
+ __set_current_state(TASK_RUNNING);
+ do_something(my_data);
+
+and the waker does:
+
+ my_data = value;
+ event_indicated = 1;
+ wake_up(&event_wait_queue);
+
+there's no guarantee that the change to event_indicated will be perceived by
+the sleeper as coming after the change to my_data. In such a circumstance, the
+code on both sides must interpolate its own memory barriers between the
+separate data accesses. Thus the above sleeper ought to do:
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (event_indicated) {
+ smp_rmb();
+ do_something(my_data);
+ }
+
+and the waker should do:
+
+ my_data = value;
+ smp_wmb();
+ event_indicated = 1;
+ wake_up(&event_wait_queue);
+
+
MISCELLANEOUS FUNCTIONS
-----------------------
@@ -1366,7 +1493,7 @@ WHERE ARE MEMORY BARRIERS NEEDED?
Under normal operation, memory operation reordering is generally not going to
be a problem as a single-threaded linear piece of code will still appear to
-work correctly, even if it's in an SMP kernel. There are, however, three
+work correctly, even if it's in an SMP kernel. There are, however, four
circumstances in which reordering definitely _could_ be a problem:
(*) Interprocessor interaction.
diff --git a/Documentation/memory-hotplug.txt b/Documentation/memory-hotplug.txt
index 4c2ecf537a4a..bbc8a6a36921 100644
--- a/Documentation/memory-hotplug.txt
+++ b/Documentation/memory-hotplug.txt
@@ -73,13 +73,13 @@ this phase is triggered automatically. ACPI can notify this event. If not,
(see Section 4.).
Logical Memory Hotplug phase is to change memory state into
-avaiable/unavailable for users. Amount of memory from user's view is
+available/unavailable for users. Amount of memory from user's view is
changed by this phase. The kernel makes all memory in it as free pages
when a memory range is available.
In this document, this phase is described as online/offline.
-Logical Memory Hotplug phase is triggred by write of sysfs file by system
+Logical Memory Hotplug phase is triggered by write of sysfs file by system
administrator. For the hot-add case, it must be executed after Physical Hotplug
phase by hand.
(However, if you writes udev's hotplug scripts for memory hotplug, these
@@ -334,7 +334,7 @@ MEMORY_CANCEL_ONLINE
Generated if MEMORY_GOING_ONLINE fails.
MEMORY_ONLINE
- Generated when memory has succesfully brought online. The callback may
+ Generated when memory has successfully brought online. The callback may
allocate pages from the new memory.
MEMORY_GOING_OFFLINE
@@ -359,7 +359,7 @@ 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;
+ int status_change_nid;
}
start_pfn is start_pfn of online/offline memory.
diff --git a/Documentation/mn10300/ABI.txt b/Documentation/mn10300/ABI.txt
index 1fef1f06dfd2..d3507bad428d 100644
--- a/Documentation/mn10300/ABI.txt
+++ b/Documentation/mn10300/ABI.txt
@@ -26,7 +26,7 @@ registers and the stack. If the first argument is a 64-bit value, it will be
passed in D0:D1. If the first argument is not a 64-bit value, but the second
is, the second will be passed entirely on the stack and D1 will be unused.
-Arguments smaller than 32-bits are not coelesced within a register or a stack
+Arguments smaller than 32-bits are not coalesced within a register or a stack
word. For example, two byte-sized arguments will always be passed in separate
registers or word-sized stack slots.
diff --git a/Documentation/mtd/nand_ecc.txt b/Documentation/mtd/nand_ecc.txt
index bdf93b7f0f24..274821b35a7f 100644
--- a/Documentation/mtd/nand_ecc.txt
+++ b/Documentation/mtd/nand_ecc.txt
@@ -50,7 +50,7 @@ byte 255: bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 rp1 rp3 rp5 ... rp15
cp5 cp5 cp5 cp5 cp4 cp4 cp4 cp4
This figure represents a sector of 256 bytes.
-cp is my abbreviaton for column parity, rp for row parity.
+cp is my abbreviation for column parity, rp for row parity.
Let's start to explain column parity.
cp0 is the parity that belongs to all bit0, bit2, bit4, bit6.
@@ -560,7 +560,7 @@ Measuring this code again showed big gain. When executing the original
linux code 1 million times, this took about 1 second on my system.
(using time to measure the performance). After this iteration I was back
to 0.075 sec. Actually I had to decide to start measuring over 10
-million interations in order not to loose too much accuracy. This one
+million iterations in order not to lose too much accuracy. This one
definitely seemed to be the jackpot!
There is a little bit more room for improvement though. There are three
@@ -571,8 +571,8 @@ loop; This eliminates 3 statements per loop. Of course after the loop we
need to correct by adding:
rp4 ^= rp4_6;
rp6 ^= rp4_6
-Furthermore there are 4 sequential assingments to rp8. This can be
-encoded slightly more efficient by saving tmppar before those 4 lines
+Furthermore there are 4 sequential assignments to rp8. This can be
+encoded slightly more efficiently by saving tmppar before those 4 lines
and later do rp8 = rp8 ^ tmppar ^ notrp8;
(where notrp8 is the value of rp8 before those 4 lines).
Again a use of the commutative property of xor.
@@ -622,7 +622,7 @@ Not a big change, but every penny counts :-)
Analysis 7
==========
-Acutally this made things worse. Not very much, but I don't want to move
+Actually this made things worse. Not very much, but I don't want to move
into the wrong direction. Maybe something to investigate later. Could
have to do with caching again.
@@ -642,7 +642,7 @@ Analysis 8
This makes things worse. Let's stick with attempt 6 and continue from there.
Although it seems that the code within the loop cannot be optimised
further there is still room to optimize the generation of the ecc codes.
-We can simply calcualate the total parity. If this is 0 then rp4 = rp5
+We can simply calculate the total parity. If this is 0 then rp4 = rp5
etc. If the parity is 1, then rp4 = !rp5;
But if rp4 = rp5 we do not need rp5 etc. We can just write the even bits
in the result byte and then do something like
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index 08762750f121..d5181ce9ff62 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -221,7 +221,7 @@ ad_select
- Any slave's 802.3ad association state changes
- - The bond's adminstrative state changes to up
+ - The bond's administrative state changes to up
count or 2
@@ -369,7 +369,7 @@ fail_over_mac
When this policy 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
+ susceptible to loss of the gratuitous ARP, and an
appropriate updelay setting may be required.
follow or 2
@@ -1794,7 +1794,7 @@ target to query.
generally referred to as "trunk failover." This is a feature of the
switch that causes the link state of a particular switch port to be set
down (or up) when the state of another switch port goes down (or up).
-It's purpose is to propogate link failures from logically "exterior" ports
+Its purpose is to propagate link failures from logically "exterior" ports
to the logically "interior" ports that bonding is able to monitor via
miimon. Availability and configuration for trunk failover varies by
switch, but this can be a viable alternative to the ARP monitor when using
diff --git a/Documentation/networking/can.txt b/Documentation/networking/can.txt
index 2035bc4932f2..463d9e029ef3 100644
--- a/Documentation/networking/can.txt
+++ b/Documentation/networking/can.txt
@@ -327,7 +327,7 @@ solution for a couple of reasons:
return 1;
}
- /* paraniod check ... */
+ /* paranoid check ... */
if (nbytes < sizeof(struct can_frame)) {
fprintf(stderr, "read: incomplete CAN frame\n");
return 1;
diff --git a/Documentation/networking/dm9000.txt b/Documentation/networking/dm9000.txt
index 65df3dea5561..5552e2e575c5 100644
--- a/Documentation/networking/dm9000.txt
+++ b/Documentation/networking/dm9000.txt
@@ -129,7 +129,7 @@ PHY Link state polling
----------------------
The driver keeps track of the link state and informs the network core
-about link (carrier) availablilty. This is managed by several methods
+about link (carrier) availability. This is managed by several methods
depending on the version of the chip and on which PHY is being used.
For the internal PHY, the original (and currently default) method is
diff --git a/Documentation/networking/l2tp.txt b/Documentation/networking/l2tp.txt
index 2451f551c505..63214b280e00 100644
--- a/Documentation/networking/l2tp.txt
+++ b/Documentation/networking/l2tp.txt
@@ -158,7 +158,7 @@ Sample Userspace Code
}
return 0;
-Miscellanous
+Miscellaneous
============
The PPPoL2TP driver was developed as part of the OpenL2TP project by
diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt
index a2ab6a0b116d..87b3d15f523a 100644
--- a/Documentation/networking/netdevices.txt
+++ b/Documentation/networking/netdevices.txt
@@ -74,7 +74,7 @@ dev->hard_start_xmit:
for this and return NETDEV_TX_LOCKED when the spin lock fails.
The locking there should also properly protect against
set_multicast_list. Note that the use of NETIF_F_LLTX is deprecated.
- Dont use it for new drivers.
+ Don't use it for new drivers.
Context: Process with BHs disabled or BH (timer),
will be called with interrupts disabled by netconsole.
diff --git a/Documentation/networking/phonet.txt b/Documentation/networking/phonet.txt
index 6a07e45d4a93..6e8ce09f9c73 100644
--- a/Documentation/networking/phonet.txt
+++ b/Documentation/networking/phonet.txt
@@ -36,7 +36,7 @@ Phonet packets have a common header as follows:
On Linux, the link-layer header includes the pn_media byte (see below).
The next 7 bytes are part of the network-layer header.
-The device ID is split: the 6 higher-order bits consitute the device
+The device ID is split: the 6 higher-order bits constitute the device
address, while the 2 lower-order bits are used for multiplexing, as are
the 8-bit object identifiers. As such, Phonet can be considered as a
network layer with 6 bits of address space and 10 bits for transport
diff --git a/Documentation/networking/regulatory.txt b/Documentation/networking/regulatory.txt
index dcf31648414a..eaa1a25946c1 100644
--- a/Documentation/networking/regulatory.txt
+++ b/Documentation/networking/regulatory.txt
@@ -89,7 +89,7 @@ added to this document when its support is enabled.
Device drivers who provide their own built regulatory domain
do not need a callback as the channels registered by them are
the only ones that will be allowed and therefore *additional*
-cannels cannot be enabled.
+channels cannot be enabled.
Example code - drivers hinting an alpha2:
------------------------------------------
diff --git a/Documentation/power/regulator/consumer.txt b/Documentation/power/regulator/consumer.txt
index 82b7a43aadba..5f83fd24ea84 100644
--- a/Documentation/power/regulator/consumer.txt
+++ b/Documentation/power/regulator/consumer.txt
@@ -178,5 +178,5 @@ Consumers can uregister interest by calling :-
int regulator_unregister_notifier(struct regulator *regulator,
struct notifier_block *nb);
-Regulators use the kernel notifier framework to send event to thier interested
+Regulators use the kernel notifier framework to send event to their interested
consumers.
diff --git a/Documentation/power/regulator/overview.txt b/Documentation/power/regulator/overview.txt
index bdcb332bd7fb..0cded696ca01 100644
--- a/Documentation/power/regulator/overview.txt
+++ b/Documentation/power/regulator/overview.txt
@@ -119,7 +119,7 @@ Some terms used in this document:-
battery power, USB power)
Regulator Domains: is the new current limit within the
- regulator operating parameters for input/ouput voltage.
+ regulator operating parameters for input/output voltage.
If the regulator request passes all the constraint tests
then the new regulator value is applied.
diff --git a/Documentation/power/s2ram.txt b/Documentation/power/s2ram.txt
index 2ebdc6091ce1..514b94fc931e 100644
--- a/Documentation/power/s2ram.txt
+++ b/Documentation/power/s2ram.txt
@@ -63,7 +63,7 @@ hardware during resume operations where a value can be set that will
survive a reboot.
Consequence is that after a resume (even if it is successful) your system
-clock will have a value corresponding to the magic mumber instead of the
+clock will have a value corresponding to the magic number instead of the
correct date/time! It is therefore advisable to use a program like ntp-date
or rdate to reset the correct date/time from an external time source when
using this trace option.
diff --git a/Documentation/power/userland-swsusp.txt b/Documentation/power/userland-swsusp.txt
index 7b99636564c8..b967cd9137d6 100644
--- a/Documentation/power/userland-swsusp.txt
+++ b/Documentation/power/userland-swsusp.txt
@@ -109,7 +109,7 @@ unfreeze user space processes frozen by SNAPSHOT_UNFREEZE if they are
still frozen when the device is being closed).
Currently it is assumed that the userland utilities reading/writing the
-snapshot image from/to the kernel will use a swap parition, called the resume
+snapshot image from/to the kernel will use a swap partition, called the resume
partition, or a swap file as storage space (if a swap file is used, the resume
partition is the partition that holds this file). However, this is not really
required, as they can use, for example, a special (blank) suspend partition or
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index 0ab0230cbcb0..8d999d862d0e 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -43,12 +43,11 @@ Table of Contents
2) Representing devices without a current OF specification
a) PHY nodes
b) Interrupt controllers
- c) CFI or JEDEC memory-mapped NOR flash
- d) 4xx/Axon EMAC ethernet nodes
- e) Xilinx IP cores
- f) USB EHCI controllers
- g) MDIO on GPIOs
- h) SPI busses
+ c) 4xx/Axon EMAC ethernet nodes
+ d) Xilinx IP cores
+ e) USB EHCI controllers
+ f) MDIO on GPIOs
+ g) SPI busses
VII - Marvell Discovery mv64[345]6x System Controller chips
1) The /system-controller node
@@ -999,7 +998,7 @@ compatibility.
translation of SOC addresses for memory mapped SOC registers.
- bus-frequency: Contains the bus frequency for the SOC node.
Typically, the value of this field is filled in by the boot
- loader.
+ loader.
Recommended properties:
@@ -1287,71 +1286,7 @@ platforms are moved over to use the flattened-device-tree model.
device_type = "open-pic";
};
- c) CFI or JEDEC memory-mapped NOR flash
-
- Flash chips (Memory Technology Devices) are often used for solid state
- file systems on embedded devices.
-
- - compatible : should contain the specific model of flash chip(s)
- used, if known, followed by either "cfi-flash" or "jedec-flash"
- - reg : Address range of the flash chip
- - bank-width : Width (in bytes) of the flash bank. Equal to the
- device width times the number of interleaved chips.
- - device-width : (optional) Width of a single flash chip. If
- omitted, assumed to be equal to 'bank-width'.
- - #address-cells, #size-cells : Must be present if the flash has
- sub-nodes representing partitions (see below). In this case
- both #address-cells and #size-cells must be equal to 1.
-
- For JEDEC compatible devices, the following additional properties
- are defined:
-
- - vendor-id : Contains the flash chip's vendor id (1 byte).
- - device-id : Contains the flash chip's device id (1 byte).
-
- In addition to the information on the flash bank itself, the
- device tree may optionally contain additional information
- describing partitions of the flash address space. This can be
- used on platforms which have strong conventions about which
- portions of the flash are used for what purposes, but which don't
- use an on-flash partition table such as RedBoot.
-
- Each partition is represented as a sub-node of the flash device.
- Each node's name represents the name of the corresponding
- partition of the flash device.
-
- Flash partitions
- - reg : The partition's offset and size within the flash bank.
- - label : (optional) The label / name for this flash partition.
- If omitted, the label is taken from the node name (excluding
- the unit address).
- - read-only : (optional) This parameter, if present, is a hint to
- Linux that this flash partition should only be mounted
- read-only. This is usually used for flash partitions
- containing early-boot firmware images or data which should not
- be clobbered.
-
- Example:
-
- flash@ff000000 {
- compatible = "amd,am29lv128ml", "cfi-flash";
- reg = <ff000000 01000000>;
- bank-width = <4>;
- device-width = <1>;
- #address-cells = <1>;
- #size-cells = <1>;
- fs@0 {
- label = "fs";
- reg = <0 f80000>;
- };
- firmware@f80000 {
- label ="firmware";
- reg = <f80000 80000>;
- read-only;
- };
- };
-
- d) 4xx/Axon EMAC ethernet nodes
+ c) 4xx/Axon EMAC ethernet nodes
The EMAC ethernet controller in IBM and AMCC 4xx chips, and also
the Axon bridge. To operate this needs to interact with a ths
@@ -1421,7 +1356,7 @@ platforms are moved over to use the flattened-device-tree model.
- phy-map : 1 cell, optional, bitmap of addresses to probe the PHY
for, used if phy-address is absent. bit 0x00000001 is
MDIO address 0.
- For Axon it can be absent, thouugh my current driver
+ For Axon it can be absent, though my current driver
doesn't handle phy-address yet so for now, keep
0x00ffffff in it.
- rx-fifo-size-gige : 1 cell, Rx fifo size in bytes for 1000 Mb/sec
@@ -1499,11 +1434,11 @@ platforms are moved over to use the flattened-device-tree model.
available.
For Axon: 0x0000012a
- e) Xilinx IP cores
+ d) 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
+ of standard device types (network, serial, etc.) and miscellaneous
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.
@@ -1761,7 +1696,7 @@ platforms are moved over to use the flattened-device-tree model.
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.
@@ -1793,7 +1728,7 @@ platforms are moved over to use the flattened-device-tree model.
- reg-offset : A value of 3 is required
- reg-shift : A value of 2 is required
- f) USB EHCI controllers
+ e) USB EHCI controllers
Required properties:
- compatible : should be "usb-ehci".
@@ -1819,7 +1754,7 @@ platforms are moved over to use the flattened-device-tree model.
big-endian;
};
- g) MDIO on GPIOs
+ f) MDIO on GPIOs
Currently defined compatibles:
- virtual,gpio-mdio
@@ -1839,7 +1774,7 @@ platforms are moved over to use the flattened-device-tree model.
&qe_pio_c 6>;
};
- h) SPI (Serial Peripheral Interface) busses
+ g) SPI (Serial Peripheral Interface) busses
SPI busses can be described with a node for the SPI master device
and a set of child nodes for each SPI slave on the bus. For this
diff --git a/Documentation/powerpc/dts-bindings/ecm.txt b/Documentation/powerpc/dts-bindings/ecm.txt
new file mode 100644
index 000000000000..f514f29c67d6
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/ecm.txt
@@ -0,0 +1,64 @@
+=====================================================================
+E500 LAW & Coherency Module Device Tree Binding
+Copyright (C) 2009 Freescale Semiconductor Inc.
+=====================================================================
+
+Local Access Window (LAW) Node
+
+The LAW node represents the region of CCSR space where local access
+windows are configured. For ECM based devices this is the first 4k
+of CCSR space that includes CCSRBAR, ALTCBAR, ALTCAR, BPTR, and some
+number of local access windows as specified by fsl,num-laws.
+
+PROPERTIES
+
+ - compatible
+ Usage: required
+ Value type: <string>
+ Definition: Must include "fsl,ecm-law"
+
+ - reg
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: A standard property. The value specifies the
+ physical address offset and length of the CCSR space
+ registers.
+
+ - fsl,num-laws
+ Usage: required
+ Value type: <u32>
+ Definition: The value specifies the number of local access
+ windows for this device.
+
+=====================================================================
+
+E500 Coherency Module Node
+
+The E500 LAW node represents the region of CCSR space where ECM config
+and error reporting registers exist, this is the second 4k (0x1000)
+of CCSR space.
+
+PROPERTIES
+
+ - compatible
+ Usage: required
+ Value type: <string>
+ Definition: Must include "fsl,CHIP-ecm", "fsl,ecm" where
+ CHIP is the processor (mpc8572, mpc8544, etc.)
+
+ - reg
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: A standard property. The value specifies the
+ physical address offset and length of the CCSR space
+ registers.
+
+ - interrupts
+ Usage: required
+ Value type: <prop-encoded-array>
+
+ - interrupt-parent
+ Usage: required
+ Value type: <phandle>
+
+=====================================================================
diff --git a/Documentation/powerpc/dts-bindings/fsl/board.txt b/Documentation/powerpc/dts-bindings/fsl/board.txt
index 6c974d28eeb4..e8b5bc24d0ac 100644
--- a/Documentation/powerpc/dts-bindings/fsl/board.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/board.txt
@@ -38,7 +38,7 @@ Required properities:
- reg : Should contain the address and the length of the GPIO bank
register.
- #gpio-cells : Should be two. The first cell is the pin number and the
- second cell is used to specify optional paramters (currently unused).
+ second cell is used to specify optional parameters (currently unused).
- gpio-controller : Marks the port as GPIO controller.
Example:
diff --git a/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm.txt b/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm.txt
index 088fc471e03a..160c752484b4 100644
--- a/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm.txt
@@ -19,7 +19,7 @@ Example:
reg = <119c0 30>;
}
-* Properties common to mulitple CPM/QE devices
+* Properties common to multiple CPM/QE devices
- fsl,cpm-command : This value is ORed with the opcode and command flag
to specify the device on which a CPM command operates.
diff --git a/Documentation/powerpc/dts-bindings/fsl/cpm_qe/gpio.txt b/Documentation/powerpc/dts-bindings/fsl/cpm_qe/gpio.txt
index 1815dfede1bc..349f79fd7076 100644
--- a/Documentation/powerpc/dts-bindings/fsl/cpm_qe/gpio.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/cpm_qe/gpio.txt
@@ -11,7 +11,7 @@ Required properties:
"fsl,cpm1-pario-bank-c", "fsl,cpm1-pario-bank-d",
"fsl,cpm1-pario-bank-e", "fsl,cpm2-pario-bank"
- #gpio-cells : Should be two. The first cell is the pin number and the
- second cell is used to specify optional paramters (currently unused).
+ second cell is used to specify optional parameters (currently unused).
- gpio-controller : Marks the port as GPIO controller.
Example of three SOC GPIO banks defined as gpio-controller nodes:
diff --git a/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe.txt b/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe.txt
index 78790d58dc2c..6e37be1eeb2d 100644
--- a/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe.txt
@@ -17,6 +17,9 @@ Required properties:
- model : precise model of the QE, Can be "QE", "CPM", or "CPM2"
- reg : offset and length of the device registers.
- bus-frequency : the clock frequency for QUICC Engine.
+- fsl,qe-num-riscs: define how many RISC engines the QE has.
+- fsl,qe-num-snums: define how many serial number(SNUM) the QE can use for the
+ threads.
Recommended properties
- brg-frequency : the internal clock source frequency for baud-rate
diff --git a/Documentation/powerpc/dts-bindings/fsl/i2c.txt b/Documentation/powerpc/dts-bindings/fsl/i2c.txt
index d0ab33e21fe6..b6d2e21474f9 100644
--- a/Documentation/powerpc/dts-bindings/fsl/i2c.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/i2c.txt
@@ -7,8 +7,10 @@ Required properties :
Recommended properties :
- - compatible : Should be "fsl-i2c" for parts compatible with
- Freescale I2C specifications.
+ - compatible : compatibility list with 2 entries, the first should
+ be "fsl,CHIP-i2c" where CHIP is the name of a compatible processor,
+ e.g. mpc8313, mpc8543, mpc8544, mpc5200 or mpc5200b. The second one
+ should be "fsl-i2c".
- interrupts : <a b> where a is the interrupt number and b is a
field that represents an encoding of the sense and level
information for the interrupt. This should be encoded based on
@@ -16,17 +18,31 @@ Recommended properties :
controller you have.
- interrupt-parent : the phandle for the interrupt controller that
services interrupts for this device.
- - dfsrr : boolean; if defined, indicates that this I2C device has
- a digital filter sampling rate register
- - fsl5200-clocking : boolean; if defined, indicated that this device
- uses the FSL 5200 clocking mechanism.
-
-Example :
- i2c@3000 {
- interrupt-parent = <40000>;
- interrupts = <1b 3>;
- reg = <3000 18>;
- device_type = "i2c";
- compatible = "fsl-i2c";
- dfsrr;
+ - fsl,preserve-clocking : boolean; if defined, the clock settings
+ from the bootloader are preserved (not touched).
+ - clock-frequency : desired I2C bus clock frequency in Hz.
+
+Examples :
+
+ i2c@3d00 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
+ cell-index = <0>;
+ reg = <0x3d00 0x40>;
+ interrupts = <2 15 0>;
+ interrupt-parent = <&mpc5200_pic>;
+ fsl,preserve-clocking;
};
+
+ i2c@3100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <1>;
+ compatible = "fsl,mpc8544-i2c", "fsl-i2c";
+ reg = <0x3100 0x100>;
+ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ clock-frequency = <400000>;
+ };
+
diff --git a/Documentation/powerpc/dts-bindings/fsl/mcm.txt b/Documentation/powerpc/dts-bindings/fsl/mcm.txt
new file mode 100644
index 000000000000..4ceda9b3b413
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/fsl/mcm.txt
@@ -0,0 +1,64 @@
+=====================================================================
+MPX LAW & Coherency Module Device Tree Binding
+Copyright (C) 2009 Freescale Semiconductor Inc.
+=====================================================================
+
+Local Access Window (LAW) Node
+
+The LAW node represents the region of CCSR space where local access
+windows are configured. For MCM based devices this is the first 4k
+of CCSR space that includes CCSRBAR, ALTCBAR, ALTCAR, BPTR, and some
+number of local access windows as specified by fsl,num-laws.
+
+PROPERTIES
+
+ - compatible
+ Usage: required
+ Value type: <string>
+ Definition: Must include "fsl,mcm-law"
+
+ - reg
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: A standard property. The value specifies the
+ physical address offset and length of the CCSR space
+ registers.
+
+ - fsl,num-laws
+ Usage: required
+ Value type: <u32>
+ Definition: The value specifies the number of local access
+ windows for this device.
+
+=====================================================================
+
+MPX Coherency Module Node
+
+The MPX LAW node represents the region of CCSR space where MCM config
+and error reporting registers exist, this is the second 4k (0x1000)
+of CCSR space.
+
+PROPERTIES
+
+ - compatible
+ Usage: required
+ Value type: <string>
+ Definition: Must include "fsl,CHIP-mcm", "fsl,mcm" where
+ CHIP is the processor (mpc8641, mpc8610, etc.)
+
+ - reg
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: A standard property. The value specifies the
+ physical address offset and length of the CCSR space
+ registers.
+
+ - interrupts
+ Usage: required
+ Value type: <prop-encoded-array>
+
+ - interrupt-parent
+ Usage: required
+ Value type: <phandle>
+
+=====================================================================
diff --git a/Documentation/powerpc/dts-bindings/fsl/msi-pic.txt b/Documentation/powerpc/dts-bindings/fsl/msi-pic.txt
index b26b91992c55..bcc30bac6831 100644
--- a/Documentation/powerpc/dts-bindings/fsl/msi-pic.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/msi-pic.txt
@@ -1,6 +1,6 @@
* Freescale MSI interrupt controller
-Reguired properities:
+Required properties:
- compatible : compatible list, contains 2 entries,
first is "fsl,CHIP-msi", where CHIP is the processor(mpc8610, mpc8572,
etc.) and the second is "fsl,mpic-msi" or "fsl,ipic-msi" depending on
diff --git a/Documentation/powerpc/dts-bindings/fsl/pmc.txt b/Documentation/powerpc/dts-bindings/fsl/pmc.txt
index 02f6f43ee1b7..07256b7ffcaa 100644
--- a/Documentation/powerpc/dts-bindings/fsl/pmc.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/pmc.txt
@@ -15,8 +15,8 @@ Properties:
compatible; all statements below that apply to "fsl,mpc8548-pmc" also
apply to "fsl,mpc8641d-pmc".
- Compatibility does not include bit assigments in SCCR/PMCDR/DEVDISR; these
- bit assigments are indicated via the sleep specifier in each device's
+ Compatibility does not include bit assignments in SCCR/PMCDR/DEVDISR; these
+ bit assignments are indicated via the sleep specifier in each device's
sleep property.
- reg: For devices compatible with "fsl,mpc8349-pmc", the first resource
diff --git a/Documentation/powerpc/dts-bindings/mtd-physmap.txt b/Documentation/powerpc/dts-bindings/mtd-physmap.txt
new file mode 100644
index 000000000000..667c9bde8699
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/mtd-physmap.txt
@@ -0,0 +1,80 @@
+CFI or JEDEC memory-mapped NOR flash
+
+Flash chips (Memory Technology Devices) are often used for solid state
+file systems on embedded devices.
+
+ - compatible : should contain the specific model of flash chip(s)
+ used, if known, followed by either "cfi-flash" or "jedec-flash"
+ - reg : Address range(s) of the flash chip(s)
+ It's possible to (optionally) define multiple "reg" tuples so that
+ non-identical NOR chips can be described in one flash node.
+ - bank-width : Width (in bytes) of the flash bank. Equal to the
+ device width times the number of interleaved chips.
+ - device-width : (optional) Width of a single flash chip. If
+ omitted, assumed to be equal to 'bank-width'.
+ - #address-cells, #size-cells : Must be present if the flash has
+ sub-nodes representing partitions (see below). In this case
+ both #address-cells and #size-cells must be equal to 1.
+
+For JEDEC compatible devices, the following additional properties
+are defined:
+
+ - vendor-id : Contains the flash chip's vendor id (1 byte).
+ - device-id : Contains the flash chip's device id (1 byte).
+
+In addition to the information on the flash bank itself, the
+device tree may optionally contain additional information
+describing partitions of the flash address space. This can be
+used on platforms which have strong conventions about which
+portions of the flash are used for what purposes, but which don't
+use an on-flash partition table such as RedBoot.
+
+Each partition is represented as a sub-node of the flash device.
+Each node's name represents the name of the corresponding
+partition of the flash device.
+
+Flash partitions
+ - reg : The partition's offset and size within the flash bank.
+ - label : (optional) The label / name for this flash partition.
+ If omitted, the label is taken from the node name (excluding
+ the unit address).
+ - read-only : (optional) This parameter, if present, is a hint to
+ Linux that this flash partition should only be mounted
+ read-only. This is usually used for flash partitions
+ containing early-boot firmware images or data which should not
+ be clobbered.
+
+Example:
+
+ flash@ff000000 {
+ compatible = "amd,am29lv128ml", "cfi-flash";
+ reg = <ff000000 01000000>;
+ bank-width = <4>;
+ device-width = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ fs@0 {
+ label = "fs";
+ reg = <0 f80000>;
+ };
+ firmware@f80000 {
+ label ="firmware";
+ reg = <f80000 80000>;
+ read-only;
+ };
+ };
+
+Here an example with multiple "reg" tuples:
+
+ flash@f0000000,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "intel,PC48F4400P0VB", "cfi-flash";
+ reg = <0 0x00000000 0x02000000
+ 0 0x02000000 0x02000000>;
+ bank-width = <2>;
+ partition@0 {
+ label = "test-part1";
+ reg = <0 0x04000000>;
+ };
+ };
diff --git a/Documentation/powerpc/qe_firmware.txt b/Documentation/powerpc/qe_firmware.txt
index 06da4d4b44f9..2031ddb33d09 100644
--- a/Documentation/powerpc/qe_firmware.txt
+++ b/Documentation/powerpc/qe_firmware.txt
@@ -225,7 +225,7 @@ For example, to match the 8323, revision 1.0:
soc.major = 1
soc.minor = 0
-'padding' is neccessary for structure alignment. This field ensures that the
+'padding' is necessary for structure alignment. This field ensures that the
'extended_modes' field is aligned on a 64-bit boundary.
'extended_modes' is a bitfield that defines special functionality which has an
diff --git a/Documentation/rbtree.txt b/Documentation/rbtree.txt
index 7224459b469e..77102148e67b 100644
--- a/Documentation/rbtree.txt
+++ b/Documentation/rbtree.txt
@@ -131,8 +131,8 @@ Example:
}
/* Add new node and rebalance tree. */
- rb_link_node(data->node, parent, new);
- rb_insert_color(data->node, root);
+ rb_link_node(&data->node, parent, new);
+ rb_insert_color(&data->node, root);
return TRUE;
}
@@ -146,10 +146,10 @@ To remove an existing node from a tree, call:
Example:
- struct mytype *data = mysearch(mytree, "walrus");
+ struct mytype *data = mysearch(&mytree, "walrus");
if (data) {
- rb_erase(data->node, mytree);
+ rb_erase(&data->node, &mytree);
myfree(data);
}
diff --git a/Documentation/rfkill.txt b/Documentation/rfkill.txt
index 40c3a3f10816..bb17c6525111 100644
--- a/Documentation/rfkill.txt
+++ b/Documentation/rfkill.txt
@@ -293,7 +293,7 @@ E.g:
[RFKILL slider switch] -- [GPIO hardware] -- [WLAN card rf-kill input]
(platform driver) (wireless card driver)
-The user is closer to the RFKILL slide switch plaform driver, so the driver
+The user is closer to the RFKILL slide switch platform driver, so the driver
which must issue input events is the platform driver looking at the GPIO
hardware, and NEVER the wireless card driver (which is just a slave). It is
very likely that there are other leaves than just the WLAN card rf-kill input
@@ -521,12 +521,16 @@ status of the system.
Input devices may issue events that are related to rfkill. These are the
various KEY_* events and SW_* events supported by rfkill-input.c.
-Userspace may not change the state of an rfkill switch in response to an
-input event, it should refrain from changing states entirely.
+******IMPORTANT******
+When rfkill-input is ACTIVE, userspace is NOT TO CHANGE THE STATE OF AN RFKILL
+SWITCH IN RESPONSE TO AN INPUT EVENT also handled by rfkill-input, unless it
+has set to true the user_claim attribute for that particular switch. This rule
+is *absolute*; do NOT violate it.
+******IMPORTANT******
-Userspace cannot assume it is the only source of control for rfkill switches.
-Their state can change due to firmware actions, direct user actions, and the
-rfkill-input EPO override for *_RFKILL_ALL.
+Userspace must not assume it is the only source of control for rfkill switches.
+Their state CAN and WILL change due to firmware actions, direct user actions,
+and the rfkill-input EPO override for *_RFKILL_ALL.
When rfkill-input is not active, userspace must initiate a rfkill status
change by writing to the "state" attribute in order for anything to happen.
@@ -544,7 +548,7 @@ The following sysfs entries will be created:
transmitter is forced off, but one can override it
by a write to the state attribute;
1: RFKILL_STATE_UNBLOCKED
- transmiter is NOT forced off, and may operate if
+ transmitter is NOT forced off, and may operate if
all other conditions for such operation are met
(such as interface is up and configured, etc);
2: RFKILL_STATE_HARD_BLOCKED
diff --git a/Documentation/s390/Debugging390.txt b/Documentation/s390/Debugging390.txt
index 10711d9f0788..1eb576a023bd 100644
--- a/Documentation/s390/Debugging390.txt
+++ b/Documentation/s390/Debugging390.txt
@@ -1984,7 +1984,7 @@ break *$pc
break *0x400618
-heres a really useful one for large programs
+Here's a really useful one for large programs
rbr
Set a breakpoint for all functions matching REGEXP
e.g.
@@ -2211,7 +2211,7 @@ Breakpoint 2 at 0x4d87a4: file top.c, line 2609.
#5 0x51692c in readline_internal () at readline.c:521
#6 0x5164fe in readline (prompt=0x7ffff810 "\177ÿøx\177ÿ÷Ø\177ÿøxÀ")
at readline.c:349
-#7 0x4d7a8a in command_line_input (prrompt=0x564420 "(gdb) ", repeat=1,
+#7 0x4d7a8a in command_line_input (prompt=0x564420 "(gdb) ", repeat=1,
annotation_suffix=0x4d6b44 "prompt") at top.c:2091
#8 0x4d6cf0 in command_loop () at top.c:1345
#9 0x4e25bc in main (argc=1, argv=0x7ffffdf4) at main.c:635
diff --git a/Documentation/scheduler/sched-nice-design.txt b/Documentation/scheduler/sched-nice-design.txt
index e2bae5a577e3..3ac1e46d5365 100644
--- a/Documentation/scheduler/sched-nice-design.txt
+++ b/Documentation/scheduler/sched-nice-design.txt
@@ -55,7 +55,7 @@ To sum it up: we always wanted to make nice levels more consistent, but
within the constraints of HZ and jiffies and their nasty design level
coupling to timeslices and granularity it was not really viable.
-The second (less frequent but still periodically occuring) complaint
+The second (less frequent but still periodically occurring) complaint
about Linux's nice level support was its assymetry around the origo
(which you can see demonstrated in the picture above), or more
accurately: the fact that nice level behavior depended on the _absolute_
diff --git a/Documentation/scheduler/sched-rt-group.txt b/Documentation/scheduler/sched-rt-group.txt
index 5ba4d3fc625a..eb74b014a3f8 100644
--- a/Documentation/scheduler/sched-rt-group.txt
+++ b/Documentation/scheduler/sched-rt-group.txt
@@ -4,6 +4,7 @@
CONTENTS
========
+0. WARNING
1. Overview
1.1 The problem
1.2 The solution
@@ -14,6 +15,23 @@ CONTENTS
3. Future plans
+0. WARNING
+==========
+
+ Fiddling with these settings can result in an unstable system, the knobs are
+ root only and assumes root knows what he is doing.
+
+Most notable:
+
+ * very small values in sched_rt_period_us can result in an unstable
+ system when the period is smaller than either the available hrtimer
+ resolution, or the time it takes to handle the budget refresh itself.
+
+ * very small values in sched_rt_runtime_us can result in an unstable
+ system when the runtime is so small the system has difficulty making
+ forward progress (NOTE: the migration thread and kstopmachine both
+ are real-time processes).
+
1. Overview
===========
diff --git a/Documentation/scsi/aic79xx.txt b/Documentation/scsi/aic79xx.txt
index 683ccae00ad4..c014eccaf19f 100644
--- a/Documentation/scsi/aic79xx.txt
+++ b/Documentation/scsi/aic79xx.txt
@@ -194,7 +194,7 @@ The following information is available in this file:
- Packetized SCSI Protocol at 160MB/s and 320MB/s
- Quick Arbitration Selection (QAS)
- Retained Training Information (Rev B. ASIC only)
- - Interrupt Coalessing
+ - Interrupt Coalescing
- Initiator Mode (target mode not currently
supported)
- Support for the PCI-X standard up to 133MHz
diff --git a/Documentation/scsi/ncr53c8xx.txt b/Documentation/scsi/ncr53c8xx.txt
index 230e30846ef2..08e2b4d04aab 100644
--- a/Documentation/scsi/ncr53c8xx.txt
+++ b/Documentation/scsi/ncr53c8xx.txt
@@ -206,7 +206,7 @@ of MOVE MEMORY instructions.
The 896 and the 895A allows handling of the phase mismatch context from
SCRIPTS (avoids the phase mismatch interrupt that stops the SCSI processor
until the C code has saved the context of the transfer).
-Implementing this without using LOAD/STORE instructions would be painfull
+Implementing this without using LOAD/STORE instructions would be painful
and I didn't even want to try it.
The 896 chip supports 64 bit PCI transactions and addressing, while the
@@ -240,7 +240,7 @@ characteristics. This feature may also reduce average command latency.
In order to really gain advantage of this feature, devices must have
a reasonable cache size (No miracle is to be expected for a low-end
hard disk with 128 KB or less).
-Some kown SCSI devices do not properly support tagged command queuing.
+Some known SCSI devices do not properly support tagged command queuing.
Generally, firmware revisions that fix this kind of problems are available
at respective vendor web/ftp sites.
All I can say is that the hard disks I use on my machines behave well with
diff --git a/Documentation/scsi/scsi_fc_transport.txt b/Documentation/scsi/scsi_fc_transport.txt
index e5b071d46619..d7f181701dc2 100644
--- a/Documentation/scsi/scsi_fc_transport.txt
+++ b/Documentation/scsi/scsi_fc_transport.txt
@@ -1,10 +1,11 @@
SCSI FC Tansport
=============================================
-Date: 4/12/2007
+Date: 11/18/2008
Kernel Revisions for features:
rports : <<TBS>>
- vports : 2.6.22 (? TBD)
+ vports : 2.6.22
+ bsg support : 2.6.30 (?TBD?)
Introduction
@@ -15,6 +16,7 @@ The FC transport can be found at:
drivers/scsi/scsi_transport_fc.c
include/scsi/scsi_transport_fc.h
include/scsi/scsi_netlink_fc.h
+ include/scsi/scsi_bsg_fc.h
This file is found at Documentation/scsi/scsi_fc_transport.txt
@@ -472,6 +474,14 @@ int
fc_vport_terminate(struct fc_vport *vport)
+FC BSG support (CT & ELS passthru, and more)
+========================================================================
+<< To Be Supplied >>
+
+
+
+
+
Credits
=======
The following people have contributed to this document:
diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt
index a6d5354639b2..de67229251d8 100644
--- a/Documentation/scsi/scsi_mid_low_api.txt
+++ b/Documentation/scsi/scsi_mid_low_api.txt
@@ -1271,6 +1271,11 @@ of interest:
hostdata[0] - area reserved for LLD at end of struct Scsi_Host. Size
is set by the second argument (named 'xtr_bytes') to
scsi_host_alloc() or scsi_register().
+ vendor_id - a unique value that identifies the vendor supplying
+ the LLD for the Scsi_Host. Used most often in validating
+ vendor-specific message requests. Value consists of an
+ identifier type and a vendor-specific value.
+ See scsi_netlink.h for a description of valid formats.
The scsi_host structure is defined in include/scsi/scsi_host.h
diff --git a/Documentation/scsi/sym53c8xx_2.txt b/Documentation/scsi/sym53c8xx_2.txt
index 49ea5c58c6bc..eb9a7b905b64 100644
--- a/Documentation/scsi/sym53c8xx_2.txt
+++ b/Documentation/scsi/sym53c8xx_2.txt
@@ -206,7 +206,7 @@ characteristics. This feature may also reduce average command latency.
In order to really gain advantage of this feature, devices must have
a reasonable cache size (No miracle is to be expected for a low-end
hard disk with 128 KB or less).
-Some kown old SCSI devices do not properly support tagged command queuing.
+Some known old SCSI devices do not properly support tagged command queuing.
Generally, firmware revisions that fix this kind of problems are available
at respective vendor web/ftp sites.
All I can say is that I never have had problem with tagged queuing using
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 012858d2b119..42470312b285 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -754,7 +754,7 @@ 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 =
+ power_save - Automatic power-saving timeout (in second, 0 =
disable)
power_save_controller - Reset HD-audio controller in power-saving mode
(default = on)
@@ -1093,6 +1093,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
This module supports multiple cards.
The driver requires the firmware loader support on kernel.
+ Module snd-lx6464es
+ -------------------
+
+ Module for Digigram LX6464ES boards
+
+ This module supports multiple cards.
+
Module snd-maestro3
-------------------
@@ -1543,13 +1550,15 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module snd-sc6000
-----------------
- Module for Gallant SC-6000 soundcard.
+ Module for Gallant SC-6000 soundcard and later models: SC-6600
+ and SC-7000.
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)
+ joystick - Enable gameport - 0 = disable (default), 1 = enable
This module supports multiple cards.
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index 8eec05bc079e..92c9d3a3e990 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -36,6 +36,7 @@ ALC260
acer Acer TravelMate
will Will laptops (PB V7900)
replacer Replacer 672V
+ favorit100 Maxdata Favorit 100XS
basic fixed pin assignment (old default model)
test for testing/debugging purpose, almost all controls can
adjusted. Appearing only when compiled with
@@ -85,10 +86,11 @@ ALC269
eeepc-p703 ASUS Eeepc P703 P900A
eeepc-p901 ASUS Eeepc P901 S101
fujitsu FSC Amilo
+ lifebook Fujitsu Lifebook S6420
auto auto-config reading BIOS (default)
-ALC662/663
-==========
+ALC662/663/272
+==============
3stack-dig 3-stack (2-channel) with SPDIF
3stack-6ch 3-stack (6-channel)
3stack-6ch-dig 3-stack (6-channel) with SPDIF
@@ -107,6 +109,8 @@ ALC662/663
asus-mode4 ASUS
asus-mode5 ASUS
asus-mode6 ASUS
+ dell Dell with ALC272
+ dell-zm1 Dell ZM1 with ALC272
auto auto-config reading BIOS (default)
ALC882/885
@@ -118,6 +122,7 @@ ALC882/885
asus-a7j ASUS A7J
asus-a7m ASUS A7M
macpro MacPro support
+ mb5 Macbook 5,1
mbp3 Macbook Pro rev3
imac24 iMac 24'' with jack detection
w2jc ASUS W2JC
@@ -150,6 +155,7 @@ ALC883/888
fujitsu-pi2515 Fujitsu AMILO Pi2515
fujitsu-xa3530 Fujitsu AMILO XA3530
3stack-6ch-intel Intel DG33* boards
+ asus-p5q ASUS P5Q-EM boards
auto auto-config reading BIOS (default)
ALC861/660
@@ -347,6 +353,7 @@ STAC92HD71B*
hp-m4 HP mini 1000
hp-dv5 HP dv series
hp-hdx HP HDX series
+ hp-dv4-1222nr HP dv4-1222nr (with LED support)
auto BIOS setup (default)
STAC92HD73*
diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt
index c5948f2f9a25..71ac995b1915 100644
--- a/Documentation/sound/alsa/HD-Audio.txt
+++ b/Documentation/sound/alsa/HD-Audio.txt
@@ -16,7 +16,7 @@ methods for the HD-audio hardware.
The HD-audio component consists of two parts: the controller chip and
the codec chips on the HD-audio bus. Linux provides a single driver
for all controllers, snd-hda-intel. Although the driver name contains
-a word of a well-known harware vendor, it's not specific to it but for
+a word of a well-known hardware vendor, it's not specific to it but for
all controller chips by other companies. Since the HD-audio
controllers are supposed to be compatible, the single snd-hda-driver
should work in most cases. But, not surprisingly, there are known
@@ -169,7 +169,7 @@ PCI SSID look-up.
What `model` option values are available depends on the codec chip.
Check your codec chip from the codec proc file (see "Codec Proc-File"
section below). It will show the vendor/product name of your codec
-chip. Then, see Documentation/sound/alsa/HD-Audio-Modelstxt file,
+chip. Then, see Documentation/sound/alsa/HD-Audio-Models.txt file,
the section of HD-audio driver. You can find a list of codecs
and `model` options belonging to each codec. For example, for Realtek
ALC262 codec chip, pass `model=ultra` for devices that are compatible
@@ -177,7 +177,7 @@ with Samsung Q1 Ultra.
Thus, the first thing you can do for any brand-new, unsupported and
non-working HD-audio hardware is to check HD-audio codec and several
-different `model` option values. If you have a luck, some of them
+different `model` option values. If you have any luck, some of them
might suit with your device well.
Some codecs such as ALC880 have a special model option `model=test`.
diff --git a/Documentation/sound/alsa/hda_codec.txt b/Documentation/sound/alsa/hda_codec.txt
index 34e87ec1379c..de8efbc7e4bd 100644
--- a/Documentation/sound/alsa/hda_codec.txt
+++ b/Documentation/sound/alsa/hda_codec.txt
@@ -114,7 +114,7 @@ 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,
+register states for the power-management 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
diff --git a/Documentation/sound/alsa/soc/dapm.txt b/Documentation/sound/alsa/soc/dapm.txt
index 9e6763264a2e..9ac842be9b4f 100644
--- a/Documentation/sound/alsa/soc/dapm.txt
+++ b/Documentation/sound/alsa/soc/dapm.txt
@@ -62,6 +62,7 @@ Audio DAPM widgets fall into a number of types:-
o Mic - Mic (and optional Jack)
o Line - Line Input/Output (and optional Jack)
o Speaker - Speaker
+ o Supply - Power or clock supply widget used by other widgets.
o Pre - Special PRE widget (exec before all others)
o Post - Special POST widget (exec after all others)
diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary
index 0f5122eb282b..4a02d2508bc8 100644
--- a/Documentation/spi/spi-summary
+++ b/Documentation/spi/spi-summary
@@ -511,10 +511,16 @@ SPI MASTER METHODS
This sets up the device clock rate, SPI mode, and word sizes.
Drivers may change the defaults provided by board_info, and then
call spi_setup(spi) to invoke this routine. It may sleep.
+
Unless each SPI slave has its own configuration registers, don't
change them right away ... otherwise drivers could corrupt I/O
that's in progress for other SPI devices.
+ ** BUG ALERT: for some reason the first version of
+ ** many spi_master drivers seems to get this wrong.
+ ** When you code setup(), ASSUME that the controller
+ ** is actively processing transfers for another device.
+
master->transfer(struct spi_device *spi, struct spi_message *message)
This must not sleep. Its responsibility is arrange that the
transfer happens and its complete() callback is issued. The two
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index f11ca7979fa6..322a00bb99d9 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -32,6 +32,7 @@ show up in /proc/sys/kernel:
- kstack_depth_to_print [ X86 only ]
- l2cr [ PPC only ]
- modprobe ==> Documentation/debugging-modules.txt
+- modules_disabled
- msgmax
- msgmnb
- msgmni
@@ -184,6 +185,16 @@ kernel stack.
==============================================================
+modules_disabled:
+
+A toggle value indicating if modules are allowed to be loaded
+in an otherwise modular kernel. This toggle defaults to off
+(0), but can be set true (1). Once true, modules can be
+neither loaded nor unloaded, and the toggle cannot be set back
+to false.
+
+==============================================================
+
osrelease, ostype & version:
# cat osrelease
diff --git a/Documentation/sysctl/net.txt b/Documentation/sysctl/net.txt
index a34d55b65441..df38ef046f8d 100644
--- a/Documentation/sysctl/net.txt
+++ b/Documentation/sysctl/net.txt
@@ -95,7 +95,7 @@ of struct cmsghdr structures with appended data.
There is only one file in this directory.
unix_dgram_qlen limits the max number of datagrams queued in Unix domain
-socket's buffer. It will not take effect unless PF_UNIX flag is spicified.
+socket's buffer. It will not take effect unless PF_UNIX flag is specified.
3. /proc/sys/net/ipv4 - IPV4 settings
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index 97c4b3284329..3fddcf32a696 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -90,6 +90,10 @@ will itself start writeback.
If dirty_bytes is written, dirty_ratio becomes a function of its value
(dirty_bytes / the amount of dirtyable system memory).
+Note: the minimum value allowed for dirty_bytes is two pages (in bytes); any
+value lower than this limit will be ignored and the old configuration will be
+retained.
+
==============================================================
dirty_expire_centisecs
@@ -356,7 +360,7 @@ nr_pdflush_threads
The current number of pdflush threads. This value is read-only.
The value changes according to the number of dirty pages in the system.
-When neccessary, additional pdflush threads are created, one per second, up to
+When necessary, additional pdflush threads are created, one per second, up to
nr_pdflush_threads_max.
==============================================================
@@ -589,7 +593,7 @@ swappiness
This control is used to define how aggressive the kernel will swap
memory pages. Higher values will increase agressiveness, lower values
-descrease the amount of swap.
+decrease the amount of swap.
The default value is 60.
diff --git a/Documentation/sysfs-rules.txt b/Documentation/sysfs-rules.txt
index 6049a2a84dda..5d8bc2cd250c 100644
--- a/Documentation/sysfs-rules.txt
+++ b/Documentation/sysfs-rules.txt
@@ -113,7 +113,7 @@ versions of the sysfs interface.
"devices" directory at /sys/subsystem/<name>/devices.
If /sys/subsystem exists, /sys/bus, /sys/class and /sys/block can be
- ignored. If it does not exist, you have always to scan all three
+ ignored. If it does not exist, you always have to scan all three
places, as the kernel is free to move a subsystem from one place to
the other, as long as the devices are still reachable by the same
subsystem name.
diff --git a/Documentation/timers/hpet.txt b/Documentation/timers/hpet.txt
index e7c09abcfab4..04763a325520 100644
--- a/Documentation/timers/hpet.txt
+++ b/Documentation/timers/hpet.txt
@@ -7,7 +7,7 @@ by Intel and Microsoft which can be found at
Each HPET has one fixed-rate counter (at 10+ MHz, hence "High Precision")
and up to 32 comparators. Normally three or more comparators are provided,
-each of which can generate oneshot interupts and at least one of which has
+each of which can generate oneshot interrupts and at least one of which has
additional hardware to support periodic interrupts. The comparators are
also called "timers", which can be misleading since usually timers are
independent of each other ... these share a counter, complicating resets.
diff --git a/Documentation/timers/timer_stats.txt b/Documentation/timers/timer_stats.txt
index 20d368c59814..9bd00fc2e823 100644
--- a/Documentation/timers/timer_stats.txt
+++ b/Documentation/timers/timer_stats.txt
@@ -62,7 +62,7 @@ Timerstats sample period: 3.888770 s
The first column is the number of events, the second column the pid, the third
column is the name of the process. The forth column shows the function which
-initialized the timer and in parantheses the callback function which was
+initialized the timer and in parenthesis the callback function which was
executed on expiry.
Thomas, Ingo
diff --git a/Documentation/tomoyo.txt b/Documentation/tomoyo.txt
new file mode 100644
index 000000000000..b3a232cae7f8
--- /dev/null
+++ b/Documentation/tomoyo.txt
@@ -0,0 +1,55 @@
+--- What is TOMOYO? ---
+
+TOMOYO is a name-based MAC extension (LSM module) for the Linux kernel.
+
+LiveCD-based tutorials are available at
+http://tomoyo.sourceforge.jp/en/1.6.x/1st-step/ubuntu8.04-live/
+http://tomoyo.sourceforge.jp/en/1.6.x/1st-step/centos5-live/ .
+Though these tutorials use non-LSM version of TOMOYO, they are useful for you
+to know what TOMOYO is.
+
+--- How to enable TOMOYO? ---
+
+Build the kernel with CONFIG_SECURITY_TOMOYO=y and pass "security=tomoyo" on
+kernel's command line.
+
+Please see http://tomoyo.sourceforge.jp/en/2.2.x/ for details.
+
+--- Where is documentation? ---
+
+User <-> Kernel interface documentation is available at
+http://tomoyo.sourceforge.jp/en/2.2.x/policy-reference.html .
+
+Materials we prepared for seminars and symposiums are available at
+http://sourceforge.jp/projects/tomoyo/docs/?category_id=532&language_id=1 .
+Below lists are chosen from three aspects.
+
+What is TOMOYO?
+ TOMOYO Linux Overview
+ http://sourceforge.jp/projects/tomoyo/docs/lca2009-takeda.pdf
+ TOMOYO Linux: pragmatic and manageable security for Linux
+ http://sourceforge.jp/projects/tomoyo/docs/freedomhectaipei-tomoyo.pdf
+ TOMOYO Linux: A Practical Method to Understand and Protect Your Own Linux Box
+ http://sourceforge.jp/projects/tomoyo/docs/PacSec2007-en-no-demo.pdf
+
+What can TOMOYO do?
+ Deep inside TOMOYO Linux
+ http://sourceforge.jp/projects/tomoyo/docs/lca2009-kumaneko.pdf
+ The role of "pathname based access control" in security.
+ http://sourceforge.jp/projects/tomoyo/docs/lfj2008-bof.pdf
+
+History of TOMOYO?
+ Realities of Mainlining
+ http://sourceforge.jp/projects/tomoyo/docs/lfj2008.pdf
+
+--- What is future plan? ---
+
+We believe that inode based security and name based security are complementary
+and both should be used together. But unfortunately, so far, we cannot enable
+multiple LSM modules at the same time. We feel sorry that you have to give up
+SELinux/SMACK/AppArmor etc. when you want to use TOMOYO.
+
+We hope that LSM becomes stackable in future. Meanwhile, you can use non-LSM
+version of TOMOYO, available at http://tomoyo.sourceforge.jp/en/1.6.x/ .
+LSM version of TOMOYO is a subset of non-LSM version of TOMOYO. We are planning
+to port non-LSM version's functionalities to LSM versions.
diff --git a/Documentation/trace/events.txt b/Documentation/trace/events.txt
new file mode 100644
index 000000000000..abdee664c0f6
--- /dev/null
+++ b/Documentation/trace/events.txt
@@ -0,0 +1,135 @@
+ Event Tracing
+
+ Documentation written by Theodore Ts'o
+
+Introduction
+============
+
+Tracepoints (see Documentation/trace/tracepoints.txt) can be used
+without creating custom kernel modules to register probe functions
+using the event tracing infrastructure.
+
+Not all tracepoints can be traced using the event tracing system;
+the kernel developer must provide code snippets which define how the
+tracing information is saved into the tracing buffer, and how the
+the tracing information should be printed.
+
+Using Event Tracing
+===================
+
+The events which are available for tracing can be found in the file
+/sys/kernel/debug/tracing/available_events.
+
+To enable a particular event, such as 'sched_wakeup', simply echo it
+to /sys/debug/tracing/set_event. For example:
+
+ # echo sched_wakeup > /sys/kernel/debug/tracing/set_event
+
+[ Note: events can also be enabled/disabled via the 'enabled' toggle
+ found in the /sys/kernel/tracing/events/ hierarchy of directories. ]
+
+To disable an event, echo the event name to the set_event file prefixed
+with an exclamation point:
+
+ # echo '!sched_wakeup' >> /sys/kernel/debug/tracing/set_event
+
+To disable events, echo an empty line to the set_event file:
+
+ # echo > /sys/kernel/debug/tracing/set_event
+
+The events are organized into subsystems, such as ext4, irq, sched,
+etc., and a full event name looks like this: <subsystem>:<event>. The
+subsystem name is optional, but it is displayed in the available_events
+file. All of the events in a subsystem can be specified via the syntax
+"<subsystem>:*"; for example, to enable all irq events, you can use the
+command:
+
+ # echo 'irq:*' > /sys/kernel/debug/tracing/set_event
+
+Defining an event-enabled tracepoint
+------------------------------------
+
+A kernel developer which wishes to define an event-enabled tracepoint
+must declare the tracepoint using TRACE_EVENT instead of DECLARE_TRACE.
+This is done via two header files in include/trace. For example, to
+event-enable the jbd2 subsystem, we must create two files,
+include/trace/jbd2.h and include/trace/jbd2_event_types.h. The
+include/trace/jbd2.h file should be included by kernel source files that
+will have a tracepoint inserted, and might look like this:
+
+#ifndef _TRACE_JBD2_H
+#define _TRACE_JBD2_H
+
+#include <linux/jbd2.h>
+#include <linux/tracepoint.h>
+
+#include <trace/jbd2_event_types.h>
+
+#endif
+
+In a file that utilizes a jbd2 tracepoint, this header file would be
+included. Note that you still have to use DEFINE_TRACE(). So for
+example, if fs/jbd2/commit.c planned to use the jbd2_start_commit
+tracepoint, it would have the following near the beginning of the file:
+
+#include <trace/jbd2.h>
+
+DEFINE_TRACE(jbd2_start_commit);
+
+Then in the function that would call the tracepoint, it would call the
+tracepoint function. (For more information, please see the tracepoint
+documentation in Documentation/trace/tracepoints.txt):
+
+ trace_jbd2_start_commit(journal, commit_transaction);
+
+The code snippets which allow jbd2_start_commit to be an event-enabled
+tracepoint are placed in the file include/trace/jbd2_event_types.h:
+
+/* use <trace/jbd2.h> instead */
+#ifndef TRACE_EVENT
+# error Do not include this file directly.
+# error Unless you know what you are doing.
+#endif
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM jbd2
+
+#include <linux/jbd2.h>
+
+TRACE_EVENT(jbd2_start_commit,
+ TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
+ TP_ARGS(journal, commit_transaction),
+ TP_STRUCT__entry(
+ __array( char, devname, BDEVNAME_SIZE+24 )
+ __field( int, transaction )
+ ),
+ TP_fast_assign(
+ memcpy(__entry->devname, journal->j_devname, BDEVNAME_SIZE+24);
+ __entry->transaction = commit_transaction->t_tid;
+ ),
+ TP_printk("dev %s transaction %d",
+ __entry->devname, __entry->transaction)
+);
+
+The TP_PROTO and TP_ARGS are unchanged from DECLARE_TRACE. The new
+arguments to TRACE_EVENT are TP_STRUCT__entry, TP_fast_assign, and
+TP_printk.
+
+TP_STRUCT__entry defines the data structure which will be stored in the
+trace buffer. Normally, fields in __entry will be arrays or simple
+types. It is possible to place data structures in __entry --- however,
+pointers in the data structure can not be trusted, since they will be
+accessed sometime later by TP_printk, and if the data structure contains
+fields that will not or cannot be used by TP_printk, this will waste
+space in the trace buffer. In general, data structures should be
+avoided, unless they do only contain non-pointer types and all of the
+fields will be used by TP_printk.
+
+TP_fast_assign defines the code snippet which saves information into the
+__entry data structure, using the passed-in arguments defined in
+TP_PROTO and TP_ARGS.
+
+Finally, TP_printk will print the __entry data structure. At the time
+when the code snippet defined by TP_printk is executed, it will not have
+access to the TP_ARGS arguments; it can only use the information saved
+in the __entry data structure.
diff --git a/Documentation/trace/ftrace.txt b/Documentation/trace/ftrace.txt
index fd9a3e693813..262562fb2953 100644
--- a/Documentation/trace/ftrace.txt
+++ b/Documentation/trace/ftrace.txt
@@ -1157,7 +1157,7 @@ int main(int argc, char *argv[]) {
Note: Here we hard coded the path name. The debugfs mount is not
guaranteed to be at /debug (and is more commonly at
/sys/kernel/debug). For simple one time traces, the above is
-sufficent. For anything else, a search through /proc/mounts may
+sufficient. For anything else, a search through /proc/mounts may
be needed to find where the debugfs file-system is mounted.
diff --git a/Documentation/trace/power.txt b/Documentation/trace/power.txt
new file mode 100644
index 000000000000..cd805e16dc27
--- /dev/null
+++ b/Documentation/trace/power.txt
@@ -0,0 +1,17 @@
+The power tracer collects detailed information about C-state and P-state
+transitions, instead of just looking at the high-level "average"
+information.
+
+There is a helper script found in scrips/tracing/power.pl in the kernel
+sources which can be used to parse this information and create a
+Scalable Vector Graphics (SVG) picture from the trace data.
+
+To use this tracer:
+
+ echo 0 > /sys/kernel/debug/tracing/tracing_enabled
+ echo power > /sys/kernel/debug/tracing/current_tracer
+ echo 1 > /sys/kernel/debug/tracing/tracing_enabled
+ sleep 1
+ echo 0 > /sys/kernel/debug/tracing/tracing_enabled
+ cat /sys/kernel/debug/tracing/trace | \
+ perl scripts/tracing/power.pl > out.sv
diff --git a/Documentation/usb/WUSB-Design-overview.txt b/Documentation/usb/WUSB-Design-overview.txt
index 4c3d62c7843a..c480e9c32dbd 100644
--- a/Documentation/usb/WUSB-Design-overview.txt
+++ b/Documentation/usb/WUSB-Design-overview.txt
@@ -84,7 +84,7 @@ The different logical parts of this driver are:
*UWB*: the Ultra-Wide-Band stack -- manages the radio and
associated spectrum to allow for devices sharing it. Allows to
- control bandwidth assingment, beaconing, scanning, etc
+ control bandwidth assignment, beaconing, scanning, etc
*
@@ -184,7 +184,7 @@ and sends the replies and notifications back to the API
[/uwb_rc_neh_grok()/]. Notifications are handled to the UWB daemon, that
is chartered, among other things, to keep the tab of how the UWB radio
neighborhood looks, creating and destroying devices as they show up or
-dissapear.
+disappear.
Command execution is very simple: a command block is sent and a event
block or reply is expected back. For sending/receiving command/events, a
@@ -333,7 +333,7 @@ read descriptors and move our data.
*Device life cycle and keep alives*
-Everytime there is a succesful transfer to/from a device, we update a
+Every time there is a successful transfer to/from a device, we update a
per-device activity timestamp. If not, every now and then we check and
if the activity timestamp gets old, we ping the device by sending it a
Keep Alive IE; it responds with a /DN_Alive/ pong during the DNTS (this
@@ -411,7 +411,7 @@ context (wa_xfer) and submit it. When the xfer is done, our callback is
called and we assign the status bits and release the xfer resources.
In dequeue() we are basically cancelling/aborting the transfer. We issue
-a xfer abort request to the HC, cancell all the URBs we had submitted
+a xfer abort request to the HC, cancel all the URBs we had submitted
and not yet done and when all that is done, the xfer callback will be
called--this will call the URB callback.
diff --git a/Documentation/usb/anchors.txt b/Documentation/usb/anchors.txt
index 6f24f566955a..fe6a99a32bbd 100644
--- a/Documentation/usb/anchors.txt
+++ b/Documentation/usb/anchors.txt
@@ -27,7 +27,7 @@ Association and disassociation of URBs with anchors
An association of URBs to an anchor is made by an explicit
call to usb_anchor_urb(). The association is maintained until
-an URB is finished by (successfull) completion. Thus disassociation
+an URB is finished by (successful) completion. Thus disassociation
is automatic. A function is provided to forcibly finish (kill)
all URBs associated with an anchor.
Furthermore, disassociation can be made with usb_unanchor_urb()
@@ -76,4 +76,4 @@ usb_get_from_anchor()
Returns the oldest anchored URB of an anchor. The URB is unanchored
and returned with a reference. As you may mix URBs to several
destinations in one anchor you have no guarantee the chronologically
-first submitted URB is returned. \ No newline at end of file
+first submitted URB is returned.
diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88
index 71e9db0b26f7..80527b292dd4 100644
--- a/Documentation/video4linux/CARDLIST.cx88
+++ b/Documentation/video4linux/CARDLIST.cx88
@@ -78,3 +78,4 @@
77 -> TBS 8910 DVB-S [8910:8888]
78 -> Prof 6200 DVB-S [b022:3022]
79 -> Terratec Cinergy HT PCI MKII [153b:1177]
+ 80 -> Hauppauge WinTV-IR Only [0070:9290]
diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx
index 78d0a6eed571..bf58d957e0df 100644
--- a/Documentation/video4linux/CARDLIST.em28xx
+++ b/Documentation/video4linux/CARDLIST.em28xx
@@ -61,3 +61,4 @@
63 -> Kaiomy TVnPC U2 (em2860) [eb1a:e303]
64 -> Easy Cap Capture DC-60 (em2860)
65 -> IO-DATA GV-MVP/SZ (em2820/em2840) [04bb:0515]
+ 66 -> Empire dual TV (em2880)
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
index 6dacf2825259..112ff4f4fd9a 100644
--- a/Documentation/video4linux/CARDLIST.saa7134
+++ b/Documentation/video4linux/CARDLIST.saa7134
@@ -124,10 +124,10 @@
123 -> Beholder BeholdTV 407 [0000:4070]
124 -> Beholder BeholdTV 407 FM [0000:4071]
125 -> Beholder BeholdTV 409 [0000:4090]
-126 -> Beholder BeholdTV 505 FM/RDS [0000:5051,0000:505B,5ace:5050]
-127 -> Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM [0000:5071,0000:507B,5ace:5070,5ace:5090]
+126 -> Beholder BeholdTV 505 FM [5ace:5050]
+127 -> Beholder BeholdTV 507 FM / BeholdTV 509 FM [5ace:5070,5ace:5090]
128 -> Beholder BeholdTV Columbus TVFM [0000:5201]
-129 -> Beholder BeholdTV 607 / BeholdTV 609 [5ace:6070,5ace:6071,5ace:6072,5ace:6073,5ace:6090,5ace:6091,5ace:6092,5ace:6093]
+129 -> Beholder BeholdTV 607 FM [5ace:6070]
130 -> Beholder BeholdTV M6 [5ace:6190]
131 -> Twinhan Hybrid DTV-DVB 3056 PCI [1822:0022]
132 -> Genius TVGO AM11MCE
@@ -155,3 +155,15 @@
154 -> Avermedia AVerTV GO 007 FM Plus [1461:f31d]
155 -> Hauppauge WinTV-HVR1120 ATSC/QAM-Hybrid [0070:6706,0070:6708]
156 -> Hauppauge WinTV-HVR1110r3 [0070:6707,0070:6709,0070:670a]
+157 -> Avermedia AVerTV Studio 507UA [1461:a11b]
+158 -> AVerMedia Cardbus TV/Radio (E501R) [1461:b7e9]
+159 -> Beholder BeholdTV 505 RDS [0000:505B]
+160 -> Beholder BeholdTV 507 RDS [0000:5071]
+161 -> Beholder BeholdTV 507 RDS [0000:507B]
+162 -> Beholder BeholdTV 607 FM [5ace:6071]
+163 -> Beholder BeholdTV 609 FM [5ace:6090]
+164 -> Beholder BeholdTV 609 FM [5ace:6091]
+165 -> Beholder BeholdTV 607 RDS [5ace:6072]
+166 -> Beholder BeholdTV 607 RDS [5ace:6073]
+167 -> Beholder BeholdTV 609 RDS [5ace:6092]
+168 -> Beholder BeholdTV 609 RDS [5ace:6093]
diff --git a/Documentation/video4linux/cx18.txt b/Documentation/video4linux/cx18.txt
index 914cb7e734a2..4652c0f5da32 100644
--- a/Documentation/video4linux/cx18.txt
+++ b/Documentation/video4linux/cx18.txt
@@ -11,7 +11,7 @@ encoder chip:
2) Some people have problems getting the i2c bus to work.
The symptom is that the eeprom cannot be read and the card is
unusable. This is probably fixed, but if you have problems
- then post to the video4linux or ivtv-users mailinglist.
+ then post to the video4linux or ivtv-users mailing list.
3) VBI (raw or sliced) has not yet been implemented.
diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt
index 98529e03a46e..1bb103fe9b8d 100644
--- a/Documentation/video4linux/gspca.txt
+++ b/Documentation/video4linux/gspca.txt
@@ -178,6 +178,7 @@ spca506 06e1:a190 ADS Instant VCD
ov534 06f8:3002 Hercules Blog Webcam
ov534 06f8:3003 Hercules Dualpix HD Weblog
sonixj 06f8:3004 Hercules Classic Silver
+sonixj 06f8:3008 Hercules Deluxe Optical Glass
spca508 0733:0110 ViewQuest VQ110
spca508 0130:0130 Clone Digital Webcam 11043
spca501 0733:0401 Intel Create and Share
@@ -209,6 +210,7 @@ sunplus 08ca:2050 Medion MD 41437
sunplus 08ca:2060 Aiptek PocketDV5300
tv8532 0923:010f ICM532 cams
mars 093a:050f Mars-Semi Pc-Camera
+mr97310a 093a:010f Sakar Digital no. 77379
pac207 093a:2460 Qtec Webcam 100
pac207 093a:2461 HP Webcam
pac207 093a:2463 Philips SPC 220 NC
@@ -265,6 +267,11 @@ sonixj 0c45:60ec SN9C105+MO4000
sonixj 0c45:60fb Surfer NoName
sonixj 0c45:60fc LG-LIC300
sonixj 0c45:60fe Microdia Audio
+sonixj 0c45:6100 PC Camera (SN9C128)
+sonixj 0c45:610a PC Camera (SN9C128)
+sonixj 0c45:610b PC Camera (SN9C128)
+sonixj 0c45:610c PC Camera (SN9C128)
+sonixj 0c45:610e PC Camera (SN9C128)
sonixj 0c45:6128 Microdia/Sonix SNP325
sonixj 0c45:612a Avant Camera
sonixj 0c45:612c Typhoon Rasy Cam 1.3MPix
diff --git a/Documentation/video4linux/pxa_camera.txt b/Documentation/video4linux/pxa_camera.txt
index b1137f9a53eb..4f6d0ca01956 100644
--- a/Documentation/video4linux/pxa_camera.txt
+++ b/Documentation/video4linux/pxa_camera.txt
@@ -26,6 +26,55 @@ Global video workflow
Once the last buffer is filled in, the QCI interface stops.
+ c) Capture global finite state machine schema
+
+ +----+ +---+ +----+
+ | DQ | | Q | | DQ |
+ | v | v | v
+ +-----------+ +------------------------+
+ | STOP | | Wait for capture start |
+ +-----------+ Q +------------------------+
++-> | QCI: stop | ------------------> | QCI: run | <------------+
+| | DMA: stop | | DMA: stop | |
+| +-----------+ +-----> +------------------------+ |
+| / | |
+| / +---+ +----+ | |
+|capture list empty / | Q | | DQ | | QCI Irq EOF |
+| / | v | v v |
+| +--------------------+ +----------------------+ |
+| | DMA hotlink missed | | Capture running | |
+| +--------------------+ +----------------------+ |
+| | QCI: run | +-----> | QCI: run | <-+ |
+| | DMA: stop | / | DMA: run | | |
+| +--------------------+ / +----------------------+ | Other |
+| ^ /DMA still | | channels |
+| | capture list / running | DMA Irq End | not |
+| | not empty / | | finished |
+| | / v | yet |
+| +----------------------+ +----------------------+ | |
+| | Videobuf released | | Channel completed | | |
+| +----------------------+ +----------------------+ | |
++-- | QCI: run | | QCI: run | --+ |
+ | DMA: run | | DMA: run | |
+ +----------------------+ +----------------------+ |
+ ^ / | |
+ | no overrun / | overrun |
+ | / v |
+ +--------------------+ / +----------------------+ |
+ | Frame completed | / | Frame overran | |
+ +--------------------+ <-----+ +----------------------+ restart frame |
+ | QCI: run | | QCI: stop | --------------+
+ | DMA: run | | DMA: stop |
+ +--------------------+ +----------------------+
+
+ Legend: - each box is a FSM state
+ - each arrow is the condition to transition to another state
+ - an arrow with a comment is a mandatory transition (no condition)
+ - arrow "Q" means : a buffer was enqueued
+ - arrow "DQ" means : a buffer was dequeued
+ - "QCI: stop" means the QCI interface is not enabled
+ - "DMA: stop" means all 3 DMA channels are stopped
+ - "DMA: run" means at least 1 DMA channel is still running
DMA usage
---------
diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
index 854808b67fae..d54c1e4c6a9c 100644
--- a/Documentation/video4linux/v4l2-framework.txt
+++ b/Documentation/video4linux/v4l2-framework.txt
@@ -89,6 +89,11 @@ from dev (driver name followed by the bus_id, to be precise). If you set it
up before calling v4l2_device_register then it will be untouched. If dev is
NULL, then you *must* setup v4l2_dev->name before calling v4l2_device_register.
+You can use v4l2_device_set_name() to set the name based on a driver name and
+a driver-global atomic_t instance. This will generate names like ivtv0, ivtv1,
+etc. If the name ends with a digit, then it will insert a dash: cx18-0,
+cx18-1, etc. This function returns the instance number.
+
The first 'dev' argument is normally the struct device pointer of a pci_dev,
usb_interface or platform_device. It is rare for dev to be NULL, but it happens
with ISA devices or when one device creates multiple PCI devices, thus making
diff --git a/Documentation/vm/00-INDEX b/Documentation/vm/00-INDEX
index 2131b00b63f6..2f77ced35df7 100644
--- a/Documentation/vm/00-INDEX
+++ b/Documentation/vm/00-INDEX
@@ -1,5 +1,7 @@
00-INDEX
- this file.
+active_mm.txt
+ - An explanation from Linus about tsk->active_mm vs tsk->mm.
balance
- various information on memory balancing.
hugetlbpage.txt
diff --git a/Documentation/vm/active_mm.txt b/Documentation/vm/active_mm.txt
new file mode 100644
index 000000000000..4ee1f643d897
--- /dev/null
+++ b/Documentation/vm/active_mm.txt
@@ -0,0 +1,83 @@
+List: linux-kernel
+Subject: Re: active_mm
+From: Linus Torvalds <torvalds () transmeta ! com>
+Date: 1999-07-30 21:36:24
+
+Cc'd to linux-kernel, because I don't write explanations all that often,
+and when I do I feel better about more people reading them.
+
+On Fri, 30 Jul 1999, David Mosberger wrote:
+>
+> Is there a brief description someplace on how "mm" vs. "active_mm" in
+> the task_struct are supposed to be used? (My apologies if this was
+> discussed on the mailing lists---I just returned from vacation and
+> wasn't able to follow linux-kernel for a while).
+
+Basically, the new setup is:
+
+ - we have "real address spaces" and "anonymous address spaces". The
+ difference is that an anonymous address space doesn't care about the
+ user-level page tables at all, so when we do a context switch into an
+ anonymous address space we just leave the previous address space
+ active.
+
+ The obvious use for a "anonymous address space" is any thread that
+ doesn't need any user mappings - all kernel threads basically fall into
+ this category, but even "real" threads can temporarily say that for
+ some amount of time they are not going to be interested in user space,
+ and that the scheduler might as well try to avoid wasting time on
+ switching the VM state around. Currently only the old-style bdflush
+ sync does that.
+
+ - "tsk->mm" points to the "real address space". For an anonymous process,
+ tsk->mm will be NULL, for the logical reason that an anonymous process
+ really doesn't _have_ a real address space at all.
+
+ - however, we obviously need to keep track of which address space we
+ "stole" for such an anonymous user. For that, we have "tsk->active_mm",
+ which shows what the currently active address space is.
+
+ The rule is that for a process with a real address space (ie tsk->mm is
+ non-NULL) the active_mm obviously always has to be the same as the real
+ one.
+
+ For a anonymous process, tsk->mm == NULL, and tsk->active_mm is the
+ "borrowed" mm while the anonymous process is running. When the
+ anonymous process gets scheduled away, the borrowed address space is
+ returned and cleared.
+
+To support all that, the "struct mm_struct" now has two counters: a
+"mm_users" counter that is how many "real address space users" there are,
+and a "mm_count" counter that is the number of "lazy" users (ie anonymous
+users) plus one if there are any real users.
+
+Usually there is at least one real user, but it could be that the real
+user exited on another CPU while a lazy user was still active, so you do
+actually get cases where you have a address space that is _only_ used by
+lazy users. That is often a short-lived state, because once that thread
+gets scheduled away in favour of a real thread, the "zombie" mm gets
+released because "mm_users" becomes zero.
+
+Also, a new rule is that _nobody_ ever has "init_mm" as a real MM any
+more. "init_mm" should be considered just a "lazy context when no other
+context is available", and in fact it is mainly used just at bootup when
+no real VM has yet been created. So code that used to check
+
+ if (current->mm == &init_mm)
+
+should generally just do
+
+ if (!current->mm)
+
+instead (which makes more sense anyway - the test is basically one of "do
+we have a user context", and is generally done by the page fault handler
+and things like that).
+
+Anyway, I put a pre-patch-2.3.13-1 on ftp.kernel.org just a moment ago,
+because it slightly changes the interfaces to accomodate the alpha (who
+would have thought it, but the alpha actually ends up having one of the
+ugliest context switch codes - unlike the other architectures where the MM
+and register state is separate, the alpha PALcode joins the two, and you
+need to switch both together).
+
+(From http://marc.info/?l=linux-kernel&m=93337278602211&w=2)
diff --git a/Documentation/vm/slqbinfo.c b/Documentation/vm/slqbinfo.c
new file mode 100644
index 000000000000..449e64913e89
--- /dev/null
+++ b/Documentation/vm/slqbinfo.c
@@ -0,0 +1,1054 @@
+/*
+ * Slabinfo: Tool to get reports about slabs
+ *
+ * (C) 2007 sgi, Christoph Lameter
+ *
+ * Reworked by Lin Ming <ming.m.lin@intel.com> for SLQB
+ *
+ * Compile by:
+ *
+ * gcc -o slabinfo slabinfo.c
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <strings.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <getopt.h>
+#include <regex.h>
+#include <errno.h>
+
+#define MAX_SLABS 500
+#define MAX_ALIASES 500
+#define MAX_NODES 1024
+
+struct slabinfo {
+ char *name;
+ int align, cache_dma, destroy_by_rcu;
+ int hwcache_align, object_size, objs_per_slab;
+ int slab_size, store_user;
+ int order, poison, reclaim_account, red_zone;
+ int batch;
+ unsigned long objects, slabs, total_objects;
+ unsigned long alloc, alloc_slab_fill, alloc_slab_new;
+ unsigned long free, free_remote;
+ unsigned long claim_remote_list, claim_remote_list_objects;
+ unsigned long flush_free_list, flush_free_list_objects, flush_free_list_remote;
+ unsigned long flush_rfree_list, flush_rfree_list_objects;
+ unsigned long flush_slab_free, flush_slab_partial;
+ int numa[MAX_NODES];
+ int numa_partial[MAX_NODES];
+} slabinfo[MAX_SLABS];
+
+int slabs = 0;
+int actual_slabs = 0;
+int highest_node = 0;
+
+char buffer[4096];
+
+int show_empty = 0;
+int show_report = 0;
+int show_slab = 0;
+int skip_zero = 1;
+int show_numa = 0;
+int show_track = 0;
+int validate = 0;
+int shrink = 0;
+int show_inverted = 0;
+int show_totals = 0;
+int sort_size = 0;
+int sort_active = 0;
+int set_debug = 0;
+int show_ops = 0;
+int show_activity = 0;
+
+/* Debug options */
+int sanity = 0;
+int redzone = 0;
+int poison = 0;
+int tracking = 0;
+int tracing = 0;
+
+int page_size;
+
+regex_t pattern;
+
+void fatal(const char *x, ...)
+{
+ va_list ap;
+
+ va_start(ap, x);
+ vfprintf(stderr, x, ap);
+ va_end(ap);
+ exit(EXIT_FAILURE);
+}
+
+void usage(void)
+{
+ printf("slabinfo 5/7/2007. (c) 2007 sgi.\n\n"
+ "slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n"
+ "-A|--activity Most active slabs first\n"
+ "-d<options>|--debug=<options> Set/Clear Debug options\n"
+ "-D|--display-active Switch line format to activity\n"
+ "-e|--empty Show empty slabs\n"
+ "-h|--help Show usage information\n"
+ "-i|--inverted Inverted list\n"
+ "-l|--slabs Show slabs\n"
+ "-n|--numa Show NUMA information\n"
+ "-o|--ops Show kmem_cache_ops\n"
+ "-s|--shrink Shrink slabs\n"
+ "-r|--report Detailed report on single slabs\n"
+ "-S|--Size Sort by size\n"
+ "-t|--tracking Show alloc/free information\n"
+ "-T|--Totals Show summary information\n"
+ "-v|--validate Validate slabs\n"
+ "-z|--zero Include empty slabs\n"
+ "\nValid debug options (FZPUT may be combined)\n"
+ "a / A Switch on all debug options (=FZUP)\n"
+ "- Switch off all debug options\n"
+ "f / F Sanity Checks (SLAB_DEBUG_FREE)\n"
+ "z / Z Redzoning\n"
+ "p / P Poisoning\n"
+ "u / U Tracking\n"
+ "t / T Tracing\n"
+ );
+}
+
+unsigned long read_obj(const char *name)
+{
+ FILE *f = fopen(name, "r");
+
+ if (!f)
+ buffer[0] = 0;
+ else {
+ if (!fgets(buffer, sizeof(buffer), f))
+ buffer[0] = 0;
+ fclose(f);
+ if (buffer[strlen(buffer)] == '\n')
+ buffer[strlen(buffer)] = 0;
+ }
+ return strlen(buffer);
+}
+
+
+/*
+ * Get the contents of an attribute
+ */
+unsigned long get_obj(const char *name)
+{
+ if (!read_obj(name))
+ return 0;
+
+ return atol(buffer);
+}
+
+unsigned long get_obj_and_str(const char *name, char **x)
+{
+ unsigned long result = 0;
+ char *p;
+
+ *x = NULL;
+
+ if (!read_obj(name)) {
+ x = NULL;
+ return 0;
+ }
+ result = strtoul(buffer, &p, 10);
+ while (*p == ' ')
+ p++;
+ if (*p)
+ *x = strdup(p);
+ return result;
+}
+
+void set_obj(struct slabinfo *s, const char *name, int n)
+{
+ char x[100];
+ FILE *f;
+
+ snprintf(x, 100, "%s/%s", s->name, name);
+ f = fopen(x, "w");
+ if (!f)
+ fatal("Cannot write to %s\n", x);
+
+ fprintf(f, "%d\n", n);
+ fclose(f);
+}
+
+unsigned long read_slab_obj(struct slabinfo *s, const char *name)
+{
+ char x[100];
+ FILE *f;
+ size_t l;
+
+ snprintf(x, 100, "%s/%s", s->name, name);
+ f = fopen(x, "r");
+ if (!f) {
+ buffer[0] = 0;
+ l = 0;
+ } else {
+ l = fread(buffer, 1, sizeof(buffer), f);
+ buffer[l] = 0;
+ fclose(f);
+ }
+ return l;
+}
+
+
+/*
+ * Put a size string together
+ */
+int store_size(char *buffer, unsigned long value)
+{
+ unsigned long divisor = 1;
+ char trailer = 0;
+ int n;
+
+ if (value > 1000000000UL) {
+ divisor = 100000000UL;
+ trailer = 'G';
+ } else if (value > 1000000UL) {
+ divisor = 100000UL;
+ trailer = 'M';
+ } else if (value > 1000UL) {
+ divisor = 100;
+ trailer = 'K';
+ }
+
+ value /= divisor;
+ n = sprintf(buffer, "%ld",value);
+ if (trailer) {
+ buffer[n] = trailer;
+ n++;
+ buffer[n] = 0;
+ }
+ if (divisor != 1) {
+ memmove(buffer + n - 2, buffer + n - 3, 4);
+ buffer[n-2] = '.';
+ n++;
+ }
+ return n;
+}
+
+void decode_numa_list(int *numa, char *t)
+{
+ int node;
+ int nr;
+
+ memset(numa, 0, MAX_NODES * sizeof(int));
+
+ if (!t)
+ return;
+
+ while (*t == 'N') {
+ t++;
+ node = strtoul(t, &t, 10);
+ if (*t == '=') {
+ t++;
+ nr = strtoul(t, &t, 10);
+ numa[node] = nr;
+ if (node > highest_node)
+ highest_node = node;
+ }
+ while (*t == ' ')
+ t++;
+ }
+}
+
+void slab_validate(struct slabinfo *s)
+{
+ if (strcmp(s->name, "*") == 0)
+ return;
+
+ set_obj(s, "validate", 1);
+}
+
+void slab_shrink(struct slabinfo *s)
+{
+ if (strcmp(s->name, "*") == 0)
+ return;
+
+ set_obj(s, "shrink", 1);
+}
+
+int line = 0;
+
+void first_line(void)
+{
+ if (show_activity)
+ printf("Name Objects Alloc Free %%Fill %%New "
+ "FlushR %%FlushR FlushR_Objs O\n");
+ else
+ printf("Name Objects Objsize Space "
+ " O/S O %%Ef Batch Flg\n");
+}
+
+unsigned long slab_size(struct slabinfo *s)
+{
+ return s->slabs * (page_size << s->order);
+}
+
+unsigned long slab_activity(struct slabinfo *s)
+{
+ return s->alloc + s->free;
+}
+
+void slab_numa(struct slabinfo *s, int mode)
+{
+ int node;
+
+ if (strcmp(s->name, "*") == 0)
+ return;
+
+ if (!highest_node) {
+ printf("\n%s: No NUMA information available.\n", s->name);
+ return;
+ }
+
+ if (skip_zero && !s->slabs)
+ return;
+
+ if (!line) {
+ printf("\n%-21s:", mode ? "NUMA nodes" : "Slab");
+ for(node = 0; node <= highest_node; node++)
+ printf(" %4d", node);
+ printf("\n----------------------");
+ for(node = 0; node <= highest_node; node++)
+ printf("-----");
+ printf("\n");
+ }
+ printf("%-21s ", mode ? "All slabs" : s->name);
+ for(node = 0; node <= highest_node; node++) {
+ char b[20];
+
+ store_size(b, s->numa[node]);
+ printf(" %4s", b);
+ }
+ printf("\n");
+ if (mode) {
+ printf("%-21s ", "Partial slabs");
+ for(node = 0; node <= highest_node; node++) {
+ char b[20];
+
+ store_size(b, s->numa_partial[node]);
+ printf(" %4s", b);
+ }
+ printf("\n");
+ }
+ line++;
+}
+
+void show_tracking(struct slabinfo *s)
+{
+ printf("\n%s: Kernel object allocation\n", s->name);
+ printf("-----------------------------------------------------------------------\n");
+ if (read_slab_obj(s, "alloc_calls"))
+ printf(buffer);
+ else
+ printf("No Data\n");
+
+ printf("\n%s: Kernel object freeing\n", s->name);
+ printf("------------------------------------------------------------------------\n");
+ if (read_slab_obj(s, "free_calls"))
+ printf(buffer);
+ else
+ printf("No Data\n");
+
+}
+
+void ops(struct slabinfo *s)
+{
+ if (strcmp(s->name, "*") == 0)
+ return;
+
+ if (read_slab_obj(s, "ops")) {
+ printf("\n%s: kmem_cache operations\n", s->name);
+ printf("--------------------------------------------\n");
+ printf(buffer);
+ } else
+ printf("\n%s has no kmem_cache operations\n", s->name);
+}
+
+const char *onoff(int x)
+{
+ if (x)
+ return "On ";
+ return "Off";
+}
+
+void slab_stats(struct slabinfo *s)
+{
+ unsigned long total_alloc;
+ unsigned long total_free;
+ unsigned long total;
+
+ total_alloc = s->alloc;
+ total_free = s->free;
+
+ if (!total_alloc)
+ return;
+
+ printf("\n");
+ printf("Slab Perf Counter\n");
+ printf("------------------------------------------------------------------------\n");
+ printf("Alloc: %8lu, partial %8lu, page allocator %8lu\n",
+ total_alloc,
+ s->alloc_slab_fill, s->alloc_slab_new);
+ printf("Free: %8lu, partial %8lu, page allocator %8lu, remote %5lu\n",
+ total_free,
+ s->flush_slab_partial,
+ s->flush_slab_free,
+ s->free_remote);
+ printf("Claim: %8lu, objects %8lu\n",
+ s->claim_remote_list,
+ s->claim_remote_list_objects);
+ printf("Flush: %8lu, objects %8lu, remote: %8lu\n",
+ s->flush_free_list,
+ s->flush_free_list_objects,
+ s->flush_free_list_remote);
+ printf("FlushR:%8lu, objects %8lu\n",
+ s->flush_rfree_list,
+ s->flush_rfree_list_objects);
+}
+
+void report(struct slabinfo *s)
+{
+ if (strcmp(s->name, "*") == 0)
+ return;
+
+ printf("\nSlabcache: %-20s Order : %2d Objects: %lu\n",
+ s->name, s->order, s->objects);
+ if (s->hwcache_align)
+ printf("** Hardware cacheline aligned\n");
+ if (s->cache_dma)
+ printf("** Memory is allocated in a special DMA zone\n");
+ if (s->destroy_by_rcu)
+ printf("** Slabs are destroyed via RCU\n");
+ if (s->reclaim_account)
+ printf("** Reclaim accounting active\n");
+
+ printf("\nSizes (bytes) Slabs Debug Memory\n");
+ printf("------------------------------------------------------------------------\n");
+ printf("Object : %7d Total : %7ld Sanity Checks : %s Total: %7ld\n",
+ s->object_size, s->slabs, "N/A",
+ s->slabs * (page_size << s->order));
+ printf("SlabObj: %7d Full : %7s Redzoning : %s Used : %7ld\n",
+ s->slab_size, "N/A",
+ onoff(s->red_zone), s->objects * s->object_size);
+ printf("SlabSiz: %7d Partial: %7s Poisoning : %s Loss : %7ld\n",
+ page_size << s->order, "N/A", onoff(s->poison),
+ s->slabs * (page_size << s->order) - s->objects * s->object_size);
+ printf("Loss : %7d CpuSlab: %7s Tracking : %s Lalig: %7ld\n",
+ s->slab_size - s->object_size, "N/A", onoff(s->store_user),
+ (s->slab_size - s->object_size) * s->objects);
+ printf("Align : %7d Objects: %7d Tracing : %s Lpadd: %7ld\n",
+ s->align, s->objs_per_slab, "N/A",
+ ((page_size << s->order) - s->objs_per_slab * s->slab_size) *
+ s->slabs);
+
+ ops(s);
+ show_tracking(s);
+ slab_numa(s, 1);
+ slab_stats(s);
+}
+
+void slabcache(struct slabinfo *s)
+{
+ char size_str[20];
+ char flags[20];
+ char *p = flags;
+
+ if (strcmp(s->name, "*") == 0)
+ return;
+
+ if (actual_slabs == 1) {
+ report(s);
+ return;
+ }
+
+ if (skip_zero && !show_empty && !s->slabs)
+ return;
+
+ if (show_empty && s->slabs)
+ return;
+
+ store_size(size_str, slab_size(s));
+
+ if (!line++)
+ first_line();
+
+ if (s->cache_dma)
+ *p++ = 'd';
+ if (s->hwcache_align)
+ *p++ = 'A';
+ if (s->poison)
+ *p++ = 'P';
+ if (s->reclaim_account)
+ *p++ = 'a';
+ if (s->red_zone)
+ *p++ = 'Z';
+ if (s->store_user)
+ *p++ = 'U';
+
+ *p = 0;
+ if (show_activity) {
+ unsigned long total_alloc;
+ unsigned long total_free;
+
+ total_alloc = s->alloc;
+ total_free = s->free;
+
+ printf("%-21s %8ld %10ld %10ld %5ld %5ld %7ld %5d %7ld %8d\n",
+ s->name, s->objects,
+ total_alloc, total_free,
+ total_alloc ? (s->alloc_slab_fill * 100 / total_alloc) : 0,
+ total_alloc ? (s->alloc_slab_new * 100 / total_alloc) : 0,
+ s->flush_rfree_list,
+ s->flush_rfree_list * 100 / (total_alloc + total_free),
+ s->flush_rfree_list_objects,
+ s->order);
+ }
+ else
+ printf("%-21s %8ld %7d %8s %4d %1d %3ld %4ld %s\n",
+ s->name, s->objects, s->object_size, size_str,
+ s->objs_per_slab, s->order,
+ s->slabs ? (s->objects * s->object_size * 100) /
+ (s->slabs * (page_size << s->order)) : 100,
+ s->batch, flags);
+}
+
+/*
+ * Analyze debug options. Return false if something is amiss.
+ */
+int debug_opt_scan(char *opt)
+{
+ if (!opt || !opt[0] || strcmp(opt, "-") == 0)
+ return 1;
+
+ if (strcasecmp(opt, "a") == 0) {
+ sanity = 1;
+ poison = 1;
+ redzone = 1;
+ tracking = 1;
+ return 1;
+ }
+
+ for ( ; *opt; opt++)
+ switch (*opt) {
+ case 'F' : case 'f':
+ if (sanity)
+ return 0;
+ sanity = 1;
+ break;
+ case 'P' : case 'p':
+ if (poison)
+ return 0;
+ poison = 1;
+ break;
+
+ case 'Z' : case 'z':
+ if (redzone)
+ return 0;
+ redzone = 1;
+ break;
+
+ case 'U' : case 'u':
+ if (tracking)
+ return 0;
+ tracking = 1;
+ break;
+
+ case 'T' : case 't':
+ if (tracing)
+ return 0;
+ tracing = 1;
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+int slab_empty(struct slabinfo *s)
+{
+ if (s->objects > 0)
+ return 0;
+
+ /*
+ * We may still have slabs even if there are no objects. Shrinking will
+ * remove them.
+ */
+ if (s->slabs != 0)
+ set_obj(s, "shrink", 1);
+
+ return 1;
+}
+
+void slab_debug(struct slabinfo *s)
+{
+ if (strcmp(s->name, "*") == 0)
+ return;
+
+ if (redzone && !s->red_zone) {
+ if (slab_empty(s))
+ set_obj(s, "red_zone", 1);
+ else
+ fprintf(stderr, "%s not empty cannot enable redzoning\n", s->name);
+ }
+ if (!redzone && s->red_zone) {
+ if (slab_empty(s))
+ set_obj(s, "red_zone", 0);
+ else
+ fprintf(stderr, "%s not empty cannot disable redzoning\n", s->name);
+ }
+ if (poison && !s->poison) {
+ if (slab_empty(s))
+ set_obj(s, "poison", 1);
+ else
+ fprintf(stderr, "%s not empty cannot enable poisoning\n", s->name);
+ }
+ if (!poison && s->poison) {
+ if (slab_empty(s))
+ set_obj(s, "poison", 0);
+ else
+ fprintf(stderr, "%s not empty cannot disable poisoning\n", s->name);
+ }
+ if (tracking && !s->store_user) {
+ if (slab_empty(s))
+ set_obj(s, "store_user", 1);
+ else
+ fprintf(stderr, "%s not empty cannot enable tracking\n", s->name);
+ }
+ if (!tracking && s->store_user) {
+ if (slab_empty(s))
+ set_obj(s, "store_user", 0);
+ else
+ fprintf(stderr, "%s not empty cannot disable tracking\n", s->name);
+ }
+}
+
+void totals(void)
+{
+ struct slabinfo *s;
+
+ int used_slabs = 0;
+ char b1[20], b2[20], b3[20], b4[20];
+ unsigned long long max = 1ULL << 63;
+
+ /* Object size */
+ unsigned long long min_objsize = max, max_objsize = 0, avg_objsize;
+
+ /* Number of partial slabs in a slabcache */
+ unsigned long long min_partial = max, max_partial = 0,
+ avg_partial, total_partial = 0;
+
+ /* Number of slabs in a slab cache */
+ unsigned long long min_slabs = max, max_slabs = 0,
+ avg_slabs, total_slabs = 0;
+
+ /* Size of the whole slab */
+ unsigned long long min_size = max, max_size = 0,
+ avg_size, total_size = 0;
+
+ /* Bytes used for object storage in a slab */
+ unsigned long long min_used = max, max_used = 0,
+ avg_used, total_used = 0;
+
+ /* Waste: Bytes used for alignment and padding */
+ unsigned long long min_waste = max, max_waste = 0,
+ avg_waste, total_waste = 0;
+ /* Number of objects in a slab */
+ unsigned long long min_objects = max, max_objects = 0,
+ avg_objects, total_objects = 0;
+ /* Waste per object */
+ unsigned long long min_objwaste = max,
+ max_objwaste = 0, avg_objwaste,
+ total_objwaste = 0;
+
+ /* Memory per object */
+ unsigned long long min_memobj = max,
+ max_memobj = 0, avg_memobj,
+ total_objsize = 0;
+
+ for (s = slabinfo; s < slabinfo + slabs; s++) {
+ unsigned long long size;
+ unsigned long used;
+ unsigned long long wasted;
+ unsigned long long objwaste;
+
+ if (!s->slabs || !s->objects)
+ continue;
+
+ used_slabs++;
+
+ size = slab_size(s);
+ used = s->objects * s->object_size;
+ wasted = size - used;
+ objwaste = s->slab_size - s->object_size;
+
+ if (s->object_size < min_objsize)
+ min_objsize = s->object_size;
+ if (s->slabs < min_slabs)
+ min_slabs = s->slabs;
+ if (size < min_size)
+ min_size = size;
+ if (wasted < min_waste)
+ min_waste = wasted;
+ if (objwaste < min_objwaste)
+ min_objwaste = objwaste;
+ if (s->objects < min_objects)
+ min_objects = s->objects;
+ if (used < min_used)
+ min_used = used;
+ if (s->slab_size < min_memobj)
+ min_memobj = s->slab_size;
+
+ if (s->object_size > max_objsize)
+ max_objsize = s->object_size;
+ if (s->slabs > max_slabs)
+ max_slabs = s->slabs;
+ if (size > max_size)
+ max_size = size;
+ if (wasted > max_waste)
+ max_waste = wasted;
+ if (objwaste > max_objwaste)
+ max_objwaste = objwaste;
+ if (s->objects > max_objects)
+ max_objects = s->objects;
+ if (used > max_used)
+ max_used = used;
+ if (s->slab_size > max_memobj)
+ max_memobj = s->slab_size;
+
+ total_slabs += s->slabs;
+ total_size += size;
+ total_waste += wasted;
+
+ total_objects += s->objects;
+ total_used += used;
+
+ total_objwaste += s->objects * objwaste;
+ total_objsize += s->objects * s->slab_size;
+ }
+
+ if (!total_objects) {
+ printf("No objects\n");
+ return;
+ }
+ if (!used_slabs) {
+ printf("No slabs\n");
+ return;
+ }
+
+ /* Per slab averages */
+ avg_slabs = total_slabs / used_slabs;
+ avg_size = total_size / used_slabs;
+ avg_waste = total_waste / used_slabs;
+
+ avg_objects = total_objects / used_slabs;
+ avg_used = total_used / used_slabs;
+
+ /* Per object object sizes */
+ avg_objsize = total_used / total_objects;
+ avg_objwaste = total_objwaste / total_objects;
+ avg_memobj = total_objsize / total_objects;
+
+ printf("Slabcache Totals\n");
+ printf("----------------\n");
+ printf("Slabcaches : %3d Active: %3d\n",
+ slabs, used_slabs);
+
+ store_size(b1, total_size);store_size(b2, total_waste);
+ store_size(b3, total_waste * 100 / total_used);
+ printf("Memory used: %6s # Loss : %6s MRatio:%6s%%\n", b1, b2, b3);
+
+ store_size(b1, total_objects);
+ printf("# Objects : %6s\n", b1);
+
+ printf("\n");
+ printf("Per Cache Average Min Max Total\n");
+ printf("---------------------------------------------------------\n");
+
+ store_size(b1, avg_objects);store_size(b2, min_objects);
+ store_size(b3, max_objects);store_size(b4, total_objects);
+ printf("#Objects %10s %10s %10s %10s\n",
+ b1, b2, b3, b4);
+
+ store_size(b1, avg_slabs);store_size(b2, min_slabs);
+ store_size(b3, max_slabs);store_size(b4, total_slabs);
+ printf("#Slabs %10s %10s %10s %10s\n",
+ b1, b2, b3, b4);
+
+ store_size(b1, avg_size);store_size(b2, min_size);
+ store_size(b3, max_size);store_size(b4, total_size);
+ printf("Memory %10s %10s %10s %10s\n",
+ b1, b2, b3, b4);
+
+ store_size(b1, avg_used);store_size(b2, min_used);
+ store_size(b3, max_used);store_size(b4, total_used);
+ printf("Used %10s %10s %10s %10s\n",
+ b1, b2, b3, b4);
+
+ store_size(b1, avg_waste);store_size(b2, min_waste);
+ store_size(b3, max_waste);store_size(b4, total_waste);
+ printf("Loss %10s %10s %10s %10s\n",
+ b1, b2, b3, b4);
+
+ printf("\n");
+ printf("Per Object Average Min Max\n");
+ printf("---------------------------------------------\n");
+
+ store_size(b1, avg_memobj);store_size(b2, min_memobj);
+ store_size(b3, max_memobj);
+ printf("Memory %10s %10s %10s\n",
+ b1, b2, b3);
+ store_size(b1, avg_objsize);store_size(b2, min_objsize);
+ store_size(b3, max_objsize);
+ printf("User %10s %10s %10s\n",
+ b1, b2, b3);
+
+ store_size(b1, avg_objwaste);store_size(b2, min_objwaste);
+ store_size(b3, max_objwaste);
+ printf("Loss %10s %10s %10s\n",
+ b1, b2, b3);
+}
+
+void sort_slabs(void)
+{
+ struct slabinfo *s1,*s2;
+
+ for (s1 = slabinfo; s1 < slabinfo + slabs; s1++) {
+ for (s2 = s1 + 1; s2 < slabinfo + slabs; s2++) {
+ int result;
+
+ if (sort_size)
+ result = slab_size(s1) < slab_size(s2);
+ else if (sort_active)
+ result = slab_activity(s1) < slab_activity(s2);
+ else
+ result = strcasecmp(s1->name, s2->name);
+
+ if (show_inverted)
+ result = -result;
+
+ if (result > 0) {
+ struct slabinfo t;
+
+ memcpy(&t, s1, sizeof(struct slabinfo));
+ memcpy(s1, s2, sizeof(struct slabinfo));
+ memcpy(s2, &t, sizeof(struct slabinfo));
+ }
+ }
+ }
+}
+
+int slab_mismatch(char *slab)
+{
+ return regexec(&pattern, slab, 0, NULL, 0);
+}
+
+void read_slab_dir(void)
+{
+ DIR *dir;
+ struct dirent *de;
+ struct slabinfo *slab = slabinfo;
+ char *p;
+ char *t;
+ int count;
+
+ if (chdir("/sys/kernel/slab") && chdir("/sys/slab"))
+ fatal("SYSFS support for SLUB not active\n");
+
+ dir = opendir(".");
+ while ((de = readdir(dir))) {
+ if (de->d_name[0] == '.' ||
+ (de->d_name[0] != ':' && slab_mismatch(de->d_name)))
+ continue;
+ switch (de->d_type) {
+ case DT_DIR:
+ if (chdir(de->d_name))
+ fatal("Unable to access slab %s\n", slab->name);
+ slab->name = strdup(de->d_name);
+ slab->align = get_obj("align");
+ slab->cache_dma = get_obj("cache_dma");
+ slab->destroy_by_rcu = get_obj("destroy_by_rcu");
+ slab->hwcache_align = get_obj("hwcache_align");
+ slab->object_size = get_obj("object_size");
+ slab->objects = get_obj("objects");
+ slab->total_objects = get_obj("total_objects");
+ slab->objs_per_slab = get_obj("objs_per_slab");
+ slab->order = get_obj("order");
+ slab->poison = get_obj("poison");
+ slab->reclaim_account = get_obj("reclaim_account");
+ slab->red_zone = get_obj("red_zone");
+ 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->batch = get_obj("batch");
+ slab->alloc = get_obj("alloc");
+ slab->alloc_slab_fill = get_obj("alloc_slab_fill");
+ slab->alloc_slab_new = get_obj("alloc_slab_new");
+ slab->free = get_obj("free");
+ slab->free_remote = get_obj("free_remote");
+ slab->claim_remote_list = get_obj("claim_remote_list");
+ slab->claim_remote_list_objects = get_obj("claim_remote_list_objects");
+ slab->flush_free_list = get_obj("flush_free_list");
+ slab->flush_free_list_objects = get_obj("flush_free_list_objects");
+ slab->flush_free_list_remote = get_obj("flush_free_list_remote");
+ slab->flush_rfree_list = get_obj("flush_rfree_list");
+ slab->flush_rfree_list_objects = get_obj("flush_rfree_list_objects");
+ slab->flush_slab_free = get_obj("flush_slab_free");
+ slab->flush_slab_partial = get_obj("flush_slab_partial");
+
+ chdir("..");
+ slab++;
+ break;
+ default :
+ fatal("Unknown file type %lx\n", de->d_type);
+ }
+ }
+ closedir(dir);
+ slabs = slab - slabinfo;
+ actual_slabs = slabs;
+ if (slabs > MAX_SLABS)
+ fatal("Too many slabs\n");
+}
+
+void output_slabs(void)
+{
+ struct slabinfo *slab;
+
+ for (slab = slabinfo; slab < slabinfo + slabs; slab++) {
+
+ if (show_numa)
+ slab_numa(slab, 0);
+ else if (show_track)
+ show_tracking(slab);
+ else if (validate)
+ slab_validate(slab);
+ else if (shrink)
+ slab_shrink(slab);
+ else if (set_debug)
+ slab_debug(slab);
+ else if (show_ops)
+ ops(slab);
+ else if (show_slab)
+ slabcache(slab);
+ else if (show_report)
+ report(slab);
+ }
+}
+
+struct option opts[] = {
+ { "activity", 0, NULL, 'A' },
+ { "debug", 2, NULL, 'd' },
+ { "display-activity", 0, NULL, 'D' },
+ { "empty", 0, NULL, 'e' },
+ { "help", 0, NULL, 'h' },
+ { "inverted", 0, NULL, 'i'},
+ { "numa", 0, NULL, 'n' },
+ { "ops", 0, NULL, 'o' },
+ { "report", 0, NULL, 'r' },
+ { "shrink", 0, NULL, 's' },
+ { "slabs", 0, NULL, 'l' },
+ { "track", 0, NULL, 't'},
+ { "validate", 0, NULL, 'v' },
+ { "zero", 0, NULL, 'z' },
+ { "1ref", 0, NULL, '1'},
+ { NULL, 0, NULL, 0 }
+};
+
+int main(int argc, char *argv[])
+{
+ int c;
+ int err;
+ char *pattern_source;
+
+ page_size = getpagesize();
+
+ while ((c = getopt_long(argc, argv, "Ad::Dehil1noprstvzTS",
+ opts, NULL)) != -1)
+ switch (c) {
+ case 'A':
+ sort_active = 1;
+ break;
+ case 'd':
+ set_debug = 1;
+ if (!debug_opt_scan(optarg))
+ fatal("Invalid debug option '%s'\n", optarg);
+ break;
+ case 'D':
+ show_activity = 1;
+ break;
+ case 'e':
+ show_empty = 1;
+ break;
+ case 'h':
+ usage();
+ return 0;
+ case 'i':
+ show_inverted = 1;
+ break;
+ case 'n':
+ show_numa = 1;
+ break;
+ case 'o':
+ show_ops = 1;
+ break;
+ case 'r':
+ show_report = 1;
+ break;
+ case 's':
+ shrink = 1;
+ break;
+ case 'l':
+ show_slab = 1;
+ break;
+ case 't':
+ show_track = 1;
+ break;
+ case 'v':
+ validate = 1;
+ break;
+ case 'z':
+ skip_zero = 0;
+ break;
+ case 'T':
+ show_totals = 1;
+ break;
+ case 'S':
+ sort_size = 1;
+ break;
+
+ default:
+ fatal("%s: Invalid option '%c'\n", argv[0], optopt);
+
+ }
+
+ if (!show_slab && !show_track && !show_report
+ && !validate && !shrink && !set_debug && !show_ops)
+ show_slab = 1;
+
+ if (argc > optind)
+ pattern_source = argv[optind];
+ else
+ pattern_source = ".*";
+
+ err = regcomp(&pattern, pattern_source, REG_ICASE|REG_NOSUB);
+ if (err)
+ fatal("%s: Invalid pattern '%s' code %d\n",
+ argv[0], pattern_source, err);
+ read_slab_dir();
+ if (show_totals)
+ totals();
+ else {
+ sort_slabs();
+ output_slabs();
+ }
+ return 0;
+}
diff --git a/Documentation/vm/unevictable-lru.txt b/Documentation/vm/unevictable-lru.txt
index 0706a7282a8c..2d70d0d95108 100644
--- a/Documentation/vm/unevictable-lru.txt
+++ b/Documentation/vm/unevictable-lru.txt
@@ -1,588 +1,691 @@
-
-This document describes the Linux memory management "Unevictable LRU"
-infrastructure and the use of this infrastructure to manage several types
-of "unevictable" pages. The document attempts to provide the overall
-rationale behind this mechanism and the rationale for some of the design
-decisions that drove the implementation. The latter design rationale is
-discussed in the context of an implementation description. Admittedly, one
-can obtain the implementation details--the "what does it do?"--by reading the
-code. One hopes that the descriptions below add value by provide the answer
-to "why does it do that?".
-
-Unevictable LRU Infrastructure:
-
-The Unevictable LRU adds an additional LRU list to track unevictable pages
-and to hide these pages from vmscan. This mechanism is based on a patch by
-Larry Woodman of Red Hat to address several scalability problems with page
+ ==============================
+ UNEVICTABLE LRU INFRASTRUCTURE
+ ==============================
+
+========
+CONTENTS
+========
+
+ (*) The Unevictable LRU
+
+ - The unevictable page list.
+ - Memory control group interaction.
+ - Marking address spaces unevictable.
+ - Detecting Unevictable Pages.
+ - vmscan's handling of unevictable pages.
+
+ (*) mlock()'d pages.
+
+ - History.
+ - Basic management.
+ - mlock()/mlockall() system call handling.
+ - Filtering special vmas.
+ - munlock()/munlockall() system call handling.
+ - Migrating mlocked pages.
+ - mmap(MAP_LOCKED) system call handling.
+ - munmap()/exit()/exec() system call handling.
+ - try_to_unmap().
+ - try_to_munlock() reverse map scan.
+ - Page reclaim in shrink_*_list().
+
+
+============
+INTRODUCTION
+============
+
+This document describes the Linux memory manager's "Unevictable LRU"
+infrastructure and the use of this to manage several types of "unevictable"
+pages.
+
+The document attempts to provide the overall rationale behind this mechanism
+and the rationale for some of the design decisions that drove the
+implementation. The latter design rationale is discussed in the context of an
+implementation description. Admittedly, one can obtain the implementation
+details - the "what does it do?" - by reading the code. One hopes that the
+descriptions below add value by provide the answer to "why does it do that?".
+
+
+===================
+THE UNEVICTABLE LRU
+===================
+
+The Unevictable LRU facility adds an additional LRU list to track unevictable
+pages and to hide these pages from vmscan. This mechanism is based on a patch
+by Larry Woodman of Red Hat to address several scalability problems with page
reclaim in Linux. The problems have been observed at customer sites on large
-memory x86_64 systems. For example, a non-numal x86_64 platform with 128GB
-of main memory will have over 32 million 4k pages in a single zone. When a
-large fraction of these pages are not evictable for any reason [see below],
-vmscan will spend a lot of time scanning the LRU lists looking for the small
-fraction of pages that are evictable. This can result in a situation where
-all cpus are spending 100% of their time in vmscan for hours or days on end,
-with the system completely unresponsive.
-
-The Unevictable LRU infrastructure addresses the following classes of
-unevictable pages:
-
-+ page owned by ramfs
-+ page mapped into SHM_LOCKed shared memory regions
-+ page mapped into VM_LOCKED [mlock()ed] vmas
-
-The infrastructure might be able to handle other conditions that make pages
+memory x86_64 systems.
+
+To illustrate this with an example, a non-NUMA x86_64 platform with 128GB of
+main memory will have over 32 million 4k pages in a single zone. When a large
+fraction of these pages are not evictable for any reason [see below], vmscan
+will spend a lot of time scanning the LRU lists looking for the small fraction
+of pages that are evictable. This can result in a situation where all CPUs are
+spending 100% of their time in vmscan for hours or days on end, with the system
+completely unresponsive.
+
+The unevictable list addresses the following classes of unevictable pages:
+
+ (*) Those owned by ramfs.
+
+ (*) Those mapped into SHM_LOCK'd shared memory regions.
+
+ (*) Those mapped into VM_LOCKED [mlock()ed] VMAs.
+
+The infrastructure may also be able to handle other conditions that make pages
unevictable, either by definition or by circumstance, in the future.
-The Unevictable LRU List
+THE UNEVICTABLE PAGE LIST
+-------------------------
The Unevictable LRU infrastructure consists of an additional, per-zone, LRU list
called the "unevictable" list and an associated page flag, PG_unevictable, to
-indicate that the page is being managed on the unevictable list. The
-PG_unevictable flag is analogous to, and mutually exclusive with, the PG_active
-flag in that it indicates on which LRU list a page resides when PG_lru is set.
-The unevictable LRU list is source configurable based on the UNEVICTABLE_LRU
-Kconfig option.
+indicate that the page is being managed on the unevictable list.
+
+The PG_unevictable flag is analogous to, and mutually exclusive with, the
+PG_active flag in that it indicates on which LRU list a page resides when
+PG_lru is set. The unevictable list is compile-time configurable based on the
+UNEVICTABLE_LRU Kconfig option.
The Unevictable LRU infrastructure maintains unevictable pages on an additional
LRU list for a few reasons:
-1) We get to "treat unevictable pages just like we treat other pages in the
- system, which means we get to use the same code to manipulate them, the
- same code to isolate them (for migrate, etc.), the same code to keep track
- of the statistics, etc..." [Rik van Riel]
+ (1) We get to "treat unevictable pages just like we treat other pages in the
+ system - which means we get to use the same code to manipulate them, the
+ same code to isolate them (for migrate, etc.), the same code to keep track
+ of the statistics, etc..." [Rik van Riel]
+
+ (2) We want to be able to migrate unevictable pages between nodes for memory
+ defragmentation, workload management and memory hotplug. The linux kernel
+ can only migrate pages that it can successfully isolate from the LRU
+ lists. If we were to maintain pages elsewhere than on an LRU-like list,
+ where they can be found by isolate_lru_page(), we would prevent their
+ migration, unless we reworked migration code to find the unevictable pages
+ itself.
-2) We want to be able to migrate unevictable pages between nodes--for memory
- defragmentation, workload management and memory hotplug. The linux kernel
- can only migrate pages that it can successfully isolate from the lru lists.
- If we were to maintain pages elsewise than on an lru-like list, where they
- can be found by isolate_lru_page(), we would prevent their migration, unless
- we reworked migration code to find the unevictable pages.
+The unevictable list does not differentiate between file-backed and anonymous,
+swap-backed pages. This differentiation is only important while the pages are,
+in fact, evictable.
-The unevictable LRU list does not differentiate between file backed and swap
-backed [anon] pages. This differentiation is only important while the pages
-are, in fact, evictable.
+The unevictable list benefits from the "arrayification" of the per-zone LRU
+lists and statistics originally proposed and posted by Christoph Lameter.
-The unevictable LRU list benefits from the "arrayification" of the per-zone
-LRU lists and statistics originally proposed and posted by Christoph Lameter.
+The unevictable list does not use the LRU pagevec mechanism. Rather,
+unevictable pages are placed directly on the page's zone's unevictable list
+under the zone lru_lock. This allows us to prevent the stranding of pages on
+the unevictable list when one task has the page isolated from the LRU and other
+tasks are changing the "evictability" state of the page.
-The unevictable list does not use the lru pagevec mechanism. Rather,
-unevictable pages are placed directly on the page's zone's unevictable
-list under the zone lru_lock. The reason for this is to prevent stranding
-of pages on the unevictable list when one task has the page isolated from the
-lru and other tasks are changing the "evictability" state of the page.
+MEMORY CONTROL GROUP INTERACTION
+--------------------------------
-Unevictable LRU and Memory Controller Interaction
+The unevictable LRU facility interacts with the memory control group [aka
+memory controller; see Documentation/cgroups/memory.txt] by extending the
+lru_list enum.
+
+The memory controller data structure automatically gets a per-zone unevictable
+list as a result of the "arrayification" of the per-zone LRU lists (one per
+lru_list enum element). The memory controller tracks the movement of pages to
+and from the unevictable list.
-The memory controller data structure automatically gets a per zone unevictable
-lru list as a result of the "arrayification" of the per-zone LRU lists. The
-memory controller tracks the movement of pages to and from the unevictable list.
When a memory control group comes under memory pressure, the controller will
not attempt to reclaim pages on the unevictable list. This has a couple of
-effects. Because the pages are "hidden" from reclaim on the unevictable list,
-the reclaim process can be more efficient, dealing only with pages that have
-a chance of being reclaimed. On the other hand, if too many of the pages
-charged to the control group are unevictable, the evictable portion of the
-working set of the tasks in the control group may not fit into the available
-memory. This can cause the control group to thrash or to oom-kill tasks.
-
-
-Unevictable LRU: Detecting Unevictable Pages
-
-The function page_evictable(page, vma) in vmscan.c determines whether a
-page is evictable or not. For ramfs pages and pages in SHM_LOCKed regions,
-page_evictable() tests a new address space flag, AS_UNEVICTABLE, in the page's
-address space using a wrapper function. Wrapper functions are used to set,
-clear and test the flag to reduce the requirement for #ifdef's throughout the
-source code. AS_UNEVICTABLE is set on ramfs inode/mapping when it is created.
-This flag remains for the life of the inode.
-
-For shared memory regions, AS_UNEVICTABLE is set when an application
-successfully SHM_LOCKs the region and is removed when the region is
-SHM_UNLOCKed. Note that shmctl(SHM_LOCK, ...) does not populate the page
-tables for the region as does, for example, mlock(). So, we make no special
-effort to push any pages in the SHM_LOCKed region to the unevictable list.
-Vmscan will do this when/if it encounters the pages during reclaim. On
-SHM_UNLOCK, shmctl() scans the pages in the region and "rescues" them from the
-unevictable list if no other condition keeps them unevictable. If a SHM_LOCKed
-region is destroyed, the pages are also "rescued" from the unevictable list in
-the process of freeing them.
-
-page_evictable() detects mlock()ed pages by testing an additional page flag,
-PG_mlocked via the PageMlocked() wrapper. If the page is NOT mlocked, and a
-non-NULL vma is supplied, page_evictable() will check whether the vma is
+effects:
+
+ (1) Because the pages are "hidden" from reclaim on the unevictable list, the
+ reclaim process can be more efficient, dealing only with pages that have a
+ chance of being reclaimed.
+
+ (2) On the other hand, if too many of the pages charged to the control group
+ are unevictable, the evictable portion of the working set of the tasks in
+ the control group may not fit into the available memory. This can cause
+ the control group to thrash or to OOM-kill tasks.
+
+
+MARKING ADDRESS SPACES UNEVICTABLE
+----------------------------------
+
+For facilities such as ramfs none of the pages attached to the address space
+may be evicted. To prevent eviction of any such pages, the AS_UNEVICTABLE
+address space flag is provided, and this can be manipulated by a filesystem
+using a number of wrapper functions:
+
+ (*) void mapping_set_unevictable(struct address_space *mapping);
+
+ Mark the address space as being completely unevictable.
+
+ (*) void mapping_clear_unevictable(struct address_space *mapping);
+
+ Mark the address space as being evictable.
+
+ (*) int mapping_unevictable(struct address_space *mapping);
+
+ Query the address space, and return true if it is completely
+ unevictable.
+
+These are currently used in two places in the kernel:
+
+ (1) By ramfs to mark the address spaces of its inodes when they are created,
+ and this mark remains for the life of the inode.
+
+ (2) By SYSV SHM to mark SHM_LOCK'd address spaces until SHM_UNLOCK is called.
+
+ Note that SHM_LOCK is not required to page in the locked pages if they're
+ swapped out; the application must touch the pages manually if it wants to
+ ensure they're in memory.
+
+
+DETECTING UNEVICTABLE PAGES
+---------------------------
+
+The function page_evictable() in vmscan.c determines whether a page is
+evictable or not using the query function outlined above [see section "Marking
+address spaces unevictable"] to check the AS_UNEVICTABLE flag.
+
+For address spaces that are so marked after being populated (as SHM regions
+might be), the lock action (eg: SHM_LOCK) can be lazy, and need not populate
+the page tables for the region as does, for example, mlock(), nor need it make
+any special effort to push any pages in the SHM_LOCK'd area to the unevictable
+list. Instead, vmscan will do this if and when it encounters the pages during
+a reclamation scan.
+
+On an unlock action (such as SHM_UNLOCK), the unlocker (eg: shmctl()) must scan
+the pages in the region and "rescue" them from the unevictable list if no other
+condition is keeping them unevictable. If an unevictable region is destroyed,
+the pages are also "rescued" from the unevictable list in the process of
+freeing them.
+
+page_evictable() also checks for mlocked pages by testing an additional page
+flag, PG_mlocked (as wrapped by PageMlocked()). If the page is NOT mlocked,
+and a non-NULL VMA is supplied, page_evictable() will check whether the VMA is
VM_LOCKED via is_mlocked_vma(). is_mlocked_vma() will SetPageMlocked() and
update the appropriate statistics if the vma is VM_LOCKED. This method allows
efficient "culling" of pages in the fault path that are being faulted in to
-VM_LOCKED vmas.
+VM_LOCKED VMAs.
-Unevictable Pages and Vmscan [shrink_*_list()]
+VMSCAN'S HANDLING OF UNEVICTABLE PAGES
+--------------------------------------
If unevictable pages are culled in the fault path, or moved to the unevictable
-list at mlock() or mmap() time, vmscan will never encounter the pages until
-they have become evictable again, for example, via munlock() and have been
-"rescued" from the unevictable list. However, there may be situations where we
-decide, for the sake of expediency, to leave a unevictable page on one of the
-regular active/inactive LRU lists for vmscan to deal with. Vmscan checks for
-such pages in all of the shrink_{active|inactive|page}_list() functions and
-will "cull" such pages that it encounters--that is, it diverts those pages to
-the unevictable list for the zone being scanned.
-
-There may be situations where a page is mapped into a VM_LOCKED vma, but the
-page is not marked as PageMlocked. Such pages will make it all the way to
+list at mlock() or mmap() time, vmscan will not encounter the pages until they
+have become evictable again (via munlock() for example) and have been "rescued"
+from the unevictable list. However, there may be situations where we decide,
+for the sake of expediency, to leave a unevictable page on one of the regular
+active/inactive LRU lists for vmscan to deal with. vmscan checks for such
+pages in all of the shrink_{active|inactive|page}_list() functions and will
+"cull" such pages that it encounters: that is, it diverts those pages to the
+unevictable list for the zone being scanned.
+
+There may be situations where a page is mapped into a VM_LOCKED VMA, but the
+page is not marked as PG_mlocked. Such pages will make it all the way to
shrink_page_list() where they will be detected when vmscan walks the reverse
-map in try_to_unmap(). If try_to_unmap() returns SWAP_MLOCK, shrink_page_list()
-will cull the page at that point.
+map in try_to_unmap(). If try_to_unmap() returns SWAP_MLOCK,
+shrink_page_list() will cull the page at that point.
-To "cull" an unevictable page, vmscan simply puts the page back on the lru
-list using putback_lru_page()--the inverse operation to isolate_lru_page()--
-after dropping the page lock. Because the condition which makes the page
-unevictable may change once the page is unlocked, putback_lru_page() will
-recheck the unevictable state of a page that it places on the unevictable lru
-list. If the page has become unevictable, putback_lru_page() removes it from
-the list and retries, including the page_unevictable() test. Because such a
-race is a rare event and movement of pages onto the unevictable list should be
-rare, these extra evictabilty checks should not occur in the majority of calls
-to putback_lru_page().
+To "cull" an unevictable page, vmscan simply puts the page back on the LRU list
+using putback_lru_page() - the inverse operation to isolate_lru_page() - after
+dropping the page lock. Because the condition which makes the page unevictable
+may change once the page is unlocked, putback_lru_page() will recheck the
+unevictable state of a page that it places on the unevictable list. If the
+page has become unevictable, putback_lru_page() removes it from the list and
+retries, including the page_unevictable() test. Because such a race is a rare
+event and movement of pages onto the unevictable list should be rare, these
+extra evictabilty checks should not occur in the majority of calls to
+putback_lru_page().
-Mlocked Page: Prior Work
+=============
+MLOCKED PAGES
+=============
-The "Unevictable Mlocked Pages" infrastructure is based on work originally
+The unevictable page list is also useful for mlock(), in addition to ramfs and
+SYSV SHM. Note that mlock() is only available in CONFIG_MMU=y situations; in
+NOMMU situations, all mappings are effectively mlocked.
+
+
+HISTORY
+-------
+
+The "Unevictable mlocked Pages" infrastructure is based on work originally
posted by Nick Piggin in an RFC patch entitled "mm: mlocked pages off LRU".
-Nick posted his patch as an alternative to a patch posted by Christoph
-Lameter to achieve the same objective--hiding mlocked pages from vmscan.
-In Nick's patch, he used one of the struct page lru list link fields as a count
-of VM_LOCKED vmas that map the page. This use of the link field for a count
-prevented the management of the pages on an LRU list. Thus, mlocked pages were
-not migratable as isolate_lru_page() could not find them and the lru list link
-field was not available to the migration subsystem. Nick resolved this by
-putting mlocked pages back on the lru list before attempting to isolate them,
-thus abandoning the count of VM_LOCKED vmas. When Nick's patch was integrated
-with the Unevictable LRU work, the count was replaced by walking the reverse
-map to determine whether any VM_LOCKED vmas mapped the page. More on this
-below.
-
-
-Mlocked Pages: Basic Management
-
-Mlocked pages--pages mapped into a VM_LOCKED vma--represent one class of
-unevictable pages. When such a page has been "noticed" by the memory
-management subsystem, the page is marked with the PG_mlocked [PageMlocked()]
-flag. A PageMlocked() page will be placed on the unevictable LRU list when
-it is added to the LRU. Pages can be "noticed" by memory management in
-several places:
-
-1) in the mlock()/mlockall() system call handlers.
-2) in the mmap() system call handler when mmap()ing a region with the
- MAP_LOCKED flag, or mmap()ing a region in a task that has called
- mlockall() with the MCL_FUTURE flag. Both of these conditions result
- in the VM_LOCKED flag being set for the vma.
-3) in the fault path, if mlocked pages are "culled" in the fault path,
- and when a VM_LOCKED stack segment is expanded.
-4) as mentioned above, in vmscan:shrink_page_list() when attempting to
- reclaim a page in a VM_LOCKED vma via try_to_unmap().
-
-Mlocked pages become unlocked and rescued from the unevictable list when:
-
-1) mapped in a range unlocked via the munlock()/munlockall() system calls.
-2) munmapped() out of the last VM_LOCKED vma that maps the page, including
- unmapping at task exit.
-3) when the page is truncated from the last VM_LOCKED vma of an mmap()ed file.
-4) before a page is COWed in a VM_LOCKED vma.
-
-
-Mlocked Pages: mlock()/mlockall() System Call Handling
+Nick posted his patch as an alternative to a patch posted by Christoph Lameter
+to achieve the same objective: hiding mlocked pages from vmscan.
+
+In Nick's patch, he used one of the struct page LRU list link fields as a count
+of VM_LOCKED VMAs that map the page. This use of the link field for a count
+prevented the management of the pages on an LRU list, and thus mlocked pages
+were not migratable as isolate_lru_page() could not find them, and the LRU list
+link field was not available to the migration subsystem.
+
+Nick resolved this by putting mlocked pages back on the lru list before
+attempting to isolate them, thus abandoning the count of VM_LOCKED VMAs. When
+Nick's patch was integrated with the Unevictable LRU work, the count was
+replaced by walking the reverse map to determine whether any VM_LOCKED VMAs
+mapped the page. More on this below.
+
+
+BASIC MANAGEMENT
+----------------
+
+mlocked pages - pages mapped into a VM_LOCKED VMA - are a class of unevictable
+pages. When such a page has been "noticed" by the memory management subsystem,
+the page is marked with the PG_mlocked flag. This can be manipulated using the
+PageMlocked() functions.
+
+A PG_mlocked page will be placed on the unevictable list when it is added to
+the LRU. Such pages can be "noticed" by memory management in several places:
+
+ (1) in the mlock()/mlockall() system call handlers;
+
+ (2) in the mmap() system call handler when mmapping a region with the
+ MAP_LOCKED flag;
+
+ (3) mmapping a region in a task that has called mlockall() with the MCL_FUTURE
+ flag
+
+ (4) in the fault path, if mlocked pages are "culled" in the fault path,
+ and when a VM_LOCKED stack segment is expanded; or
+
+ (5) as mentioned above, in vmscan:shrink_page_list() when attempting to
+ reclaim a page in a VM_LOCKED VMA via try_to_unmap()
+
+all of which result in the VM_LOCKED flag being set for the VMA if it doesn't
+already have it set.
+
+mlocked pages become unlocked and rescued from the unevictable list when:
+
+ (1) mapped in a range unlocked via the munlock()/munlockall() system calls;
+
+ (2) munmap()'d out of the last VM_LOCKED VMA that maps the page, including
+ unmapping at task exit;
+
+ (3) when the page is truncated from the last VM_LOCKED VMA of an mmapped file;
+ or
+
+ (4) before a page is COW'd in a VM_LOCKED VMA.
+
+
+mlock()/mlockall() SYSTEM CALL HANDLING
+---------------------------------------
Both [do_]mlock() and [do_]mlockall() system call handlers call mlock_fixup()
-for each vma in the range specified by the call. In the case of mlockall(),
+for each VMA in the range specified by the call. In the case of mlockall(),
this is the entire active address space of the task. Note that mlock_fixup()
-is used for both mlock()ing and munlock()ing a range of memory. A call to
-mlock() an already VM_LOCKED vma, or to munlock() a vma that is not VM_LOCKED
-is treated as a no-op--mlock_fixup() simply returns.
-
-If the vma passes some filtering described in "Mlocked Pages: Filtering Vmas"
-below, mlock_fixup() will attempt to merge the vma with its neighbors or split
-off a subset of the vma if the range does not cover the entire vma. Once the
-vma has been merged or split or neither, mlock_fixup() will call
-__mlock_vma_pages_range() to fault in the pages via get_user_pages() and
-to mark the pages as mlocked via mlock_vma_page().
-
-Note that the vma being mlocked might be mapped with PROT_NONE. In this case,
-get_user_pages() will be unable to fault in the pages. That's OK. If pages
-do end up getting faulted into this VM_LOCKED vma, we'll handle them in the
+is used for both mlocking and munlocking a range of memory. A call to mlock()
+an already VM_LOCKED VMA, or to munlock() a VMA that is not VM_LOCKED is
+treated as a no-op, and mlock_fixup() simply returns.
+
+If the VMA passes some filtering as described in "Filtering Special Vmas"
+below, mlock_fixup() will attempt to merge the VMA with its neighbors or split
+off a subset of the VMA if the range does not cover the entire VMA. Once the
+VMA has been merged or split or neither, mlock_fixup() will call
+__mlock_vma_pages_range() to fault in the pages via get_user_pages() and to
+mark the pages as mlocked via mlock_vma_page().
+
+Note that the VMA being mlocked might be mapped with PROT_NONE. In this case,
+get_user_pages() will be unable to fault in the pages. That's okay. If pages
+do end up getting faulted into this VM_LOCKED VMA, we'll handle them in the
fault path or in vmscan.
Also note that a page returned by get_user_pages() could be truncated or
-migrated out from under us, while we're trying to mlock it. To detect
-this, __mlock_vma_pages_range() tests the page_mapping after acquiring
-the page lock. If the page is still associated with its mapping, we'll
-go ahead and call mlock_vma_page(). If the mapping is gone, we just
-unlock the page and move on. Worse case, this results in page mapped
-in a VM_LOCKED vma remaining on a normal LRU list without being
-PageMlocked(). Again, vmscan will detect and cull such pages.
-
-mlock_vma_page(), called with the page locked [N.B., not "mlocked"], will
-TestSetPageMlocked() for each page returned by get_user_pages(). We use
-TestSetPageMlocked() because the page might already be mlocked by another
-task/vma and we don't want to do extra work. We especially do not want to
-count an mlocked page more than once in the statistics. If the page was
-already mlocked, mlock_vma_page() is done.
+migrated out from under us, while we're trying to mlock it. To detect this,
+__mlock_vma_pages_range() checks page_mapping() after acquiring the page lock.
+If the page is still associated with its mapping, we'll go ahead and call
+mlock_vma_page(). If the mapping is gone, we just unlock the page and move on.
+In the worst case, this will result in a page mapped in a VM_LOCKED VMA
+remaining on a normal LRU list without being PageMlocked(). Again, vmscan will
+detect and cull such pages.
+
+mlock_vma_page() will call TestSetPageMlocked() for each page returned by
+get_user_pages(). We use TestSetPageMlocked() because the page might already
+be mlocked by another task/VMA and we don't want to do extra work. We
+especially do not want to count an mlocked page more than once in the
+statistics. If the page was already mlocked, mlock_vma_page() need do nothing
+more.
If the page was NOT already mlocked, mlock_vma_page() attempts to isolate the
page from the LRU, as it is likely on the appropriate active or inactive list
-at that time. If the isolate_lru_page() succeeds, mlock_vma_page() will
-putback the page--putback_lru_page()--which will notice that the page is now
-mlocked and divert the page to the zone's unevictable LRU list. If
+at that time. If the isolate_lru_page() succeeds, mlock_vma_page() will put
+back the page - by calling putback_lru_page() - which will notice that the page
+is now mlocked and divert the page to the zone's unevictable list. If
mlock_vma_page() is unable to isolate the page from the LRU, vmscan will handle
-it later if/when it attempts to reclaim the page.
+it later if and when it attempts to reclaim the page.
-Mlocked Pages: Filtering Special Vmas
+FILTERING SPECIAL VMAS
+----------------------
-mlock_fixup() filters several classes of "special" vmas:
+mlock_fixup() filters several classes of "special" VMAs:
-1) vmas with VM_IO|VM_PFNMAP set are skipped entirely. The pages behind
+1) VMAs with VM_IO or VM_PFNMAP set are skipped entirely. The pages behind
these mappings are inherently pinned, so we don't need to mark them as
- mlocked. In any case, most of the pages have no struct page in which to
- so mark the page. Because of this, get_user_pages() will fail for these
- vmas, so there is no sense in attempting to visit them.
-
-2) vmas mapping hugetlbfs page are already effectively pinned into memory.
- We don't need nor want to mlock() these pages. However, to preserve the
- prior behavior of mlock()--before the unevictable/mlock changes--
- mlock_fixup() will call make_pages_present() in the hugetlbfs vma range
- to allocate the huge pages and populate the ptes.
-
-3) vmas with VM_DONTEXPAND|VM_RESERVED are generally user space mappings of
- kernel pages, such as the vdso page, relay channel pages, etc. These pages
+ mlocked. In any case, most of the pages have no struct page in which to so
+ mark the page. Because of this, get_user_pages() will fail for these VMAs,
+ so there is no sense in attempting to visit them.
+
+2) VMAs mapping hugetlbfs page are already effectively pinned into memory. We
+ neither need nor want to mlock() these pages. However, to preserve the
+ prior behavior of mlock() - before the unevictable/mlock changes -
+ mlock_fixup() will call make_pages_present() in the hugetlbfs VMA range to
+ allocate the huge pages and populate the ptes.
+
+3) VMAs with VM_DONTEXPAND or VM_RESERVED are generally userspace mappings of
+ kernel pages, such as the VDSO page, relay channel pages, etc. These pages
are inherently unevictable and are not managed on the LRU lists.
- mlock_fixup() treats these vmas the same as hugetlbfs vmas. It calls
+ mlock_fixup() treats these VMAs the same as hugetlbfs VMAs. It calls
make_pages_present() to populate the ptes.
-Note that for all of these special vmas, mlock_fixup() does not set the
+Note that for all of these special VMAs, mlock_fixup() does not set the
VM_LOCKED flag. Therefore, we won't have to deal with them later during
-munlock() or munmap()--for example, at task exit. Neither does mlock_fixup()
-account these vmas against the task's "locked_vm".
-
-Mlocked Pages: Downgrading the Mmap Semaphore.
-
-mlock_fixup() must be called with the mmap semaphore held for write, because
-it may have to merge or split vmas. However, mlocking a large region of
-memory can take a long time--especially if vmscan must reclaim pages to
-satisfy the regions requirements. Faulting in a large region with the mmap
-semaphore held for write can hold off other faults on the address space, in
-the case of a multi-threaded task. It can also hold off scans of the task's
-address space via /proc. While testing under heavy load, it was observed that
-the ps(1) command could be held off for many minutes while a large segment was
-mlock()ed down.
-
-To address this issue, and to make the system more responsive during mlock()ing
-of large segments, mlock_fixup() downgrades the mmap semaphore to read mode
-during the call to __mlock_vma_pages_range(). This works fine. However, the
-callers of mlock_fixup() expect the semaphore to be returned in write mode.
-So, mlock_fixup() "upgrades" the semphore to write mode. Linux does not
-support an atomic upgrade_sem() call, so mlock_fixup() must drop the semaphore
-and reacquire it in write mode. In a multi-threaded task, it is possible for
-the task memory map to change while the semaphore is dropped. Therefore,
-mlock_fixup() looks up the vma at the range start address after reacquiring
-the semaphore in write mode and verifies that it still covers the original
-range. If not, mlock_fixup() returns an error [-EAGAIN]. All callers of
-mlock_fixup() have been changed to deal with this new error condition.
-
-Note: when munlocking a region, all of the pages should already be resident--
-unless we have racing threads mlocking() and munlocking() regions. So,
-unlocking should not have to wait for page allocations nor faults of any kind.
-Therefore mlock_fixup() does not downgrade the semaphore for munlock().
-
-
-Mlocked Pages: munlock()/munlockall() System Call Handling
-
-The munlock() and munlockall() system calls are handled by the same functions--
-do_mlock[all]()--as the mlock() and mlockall() system calls with the unlock
-vs lock operation indicated by an argument. So, these system calls are also
-handled by mlock_fixup(). Again, if called for an already munlock()ed vma,
-mlock_fixup() simply returns. Because of the vma filtering discussed above,
-VM_LOCKED will not be set in any "special" vmas. So, these vmas will be
+munlock(), munmap() or task exit. Neither does mlock_fixup() account these
+VMAs against the task's "locked_vm".
+
+
+munlock()/munlockall() SYSTEM CALL HANDLING
+-------------------------------------------
+
+The munlock() and munlockall() system calls are handled by the same functions -
+do_mlock[all]() - as the mlock() and mlockall() system calls with the unlock vs
+lock operation indicated by an argument. So, these system calls are also
+handled by mlock_fixup(). Again, if called for an already munlocked VMA,
+mlock_fixup() simply returns. Because of the VMA filtering discussed above,
+VM_LOCKED will not be set in any "special" VMAs. So, these VMAs will be
ignored for munlock.
-If the vma is VM_LOCKED, mlock_fixup() again attempts to merge or split off
-the specified range. The range is then munlocked via the function
-__mlock_vma_pages_range()--the same function used to mlock a vma range--
+If the VMA is VM_LOCKED, mlock_fixup() again attempts to merge or split off the
+specified range. The range is then munlocked via the function
+__mlock_vma_pages_range() - the same function used to mlock a VMA range -
passing a flag to indicate that munlock() is being performed.
-Because the vma access protections could have been changed to PROT_NONE after
+Because the VMA access protections could have been changed to PROT_NONE after
faulting in and mlocking pages, get_user_pages() was unreliable for visiting
-these pages for munlocking. Because we don't want to leave pages mlocked(),
+these pages for munlocking. Because we don't want to leave pages mlocked,
get_user_pages() was enhanced to accept a flag to ignore the permissions when
-fetching the pages--all of which should be resident as a result of previous
-mlock()ing.
+fetching the pages - all of which should be resident as a result of previous
+mlocking.
For munlock(), __mlock_vma_pages_range() unlocks individual pages by calling
munlock_vma_page(). munlock_vma_page() unconditionally clears the PG_mlocked
-flag using TestClearPageMlocked(). As with mlock_vma_page(), munlock_vma_page()
-use the Test*PageMlocked() function to handle the case where the page might
-have already been unlocked by another task. If the page was mlocked,
-munlock_vma_page() updates that zone statistics for the number of mlocked
-pages. Note, however, that at this point we haven't checked whether the page
-is mapped by other VM_LOCKED vmas.
-
-We can't call try_to_munlock(), the function that walks the reverse map to check
-for other VM_LOCKED vmas, without first isolating the page from the LRU.
+flag using TestClearPageMlocked(). As with mlock_vma_page(),
+munlock_vma_page() use the Test*PageMlocked() function to handle the case where
+the page might have already been unlocked by another task. If the page was
+mlocked, munlock_vma_page() updates that zone statistics for the number of
+mlocked pages. Note, however, that at this point we haven't checked whether
+the page is mapped by other VM_LOCKED VMAs.
+
+We can't call try_to_munlock(), the function that walks the reverse map to
+check for other VM_LOCKED VMAs, without first isolating the page from the LRU.
try_to_munlock() is a variant of try_to_unmap() and thus requires that the page
-not be on an lru list. [More on these below.] However, the call to
-isolate_lru_page() could fail, in which case we couldn't try_to_munlock().
-So, we go ahead and clear PG_mlocked up front, as this might be the only chance
-we have. If we can successfully isolate the page, we go ahead and
+not be on an LRU list [more on these below]. However, the call to
+isolate_lru_page() could fail, in which case we couldn't try_to_munlock(). So,
+we go ahead and clear PG_mlocked up front, as this might be the only chance we
+have. If we can successfully isolate the page, we go ahead and
try_to_munlock(), which will restore the PG_mlocked flag and update the zone
-page statistics if it finds another vma holding the page mlocked. If we fail
+page statistics if it finds another VMA holding the page mlocked. If we fail
to isolate the page, we'll have left a potentially mlocked page on the LRU.
-This is fine, because we'll catch it later when/if vmscan tries to reclaim the
-page. This should be relatively rare.
-
-Mlocked Pages: Migrating Them...
-
-A page that is being migrated has been isolated from the lru lists and is
-held locked across unmapping of the page, updating the page's mapping
-[address_space] entry and copying the contents and state, until the
-page table entry has been replaced with an entry that refers to the new
-page. Linux supports migration of mlocked pages and other unevictable
-pages. This involves simply moving the PageMlocked and PageUnevictable states
-from the old page to the new page.
-
-Note that page migration can race with mlocking or munlocking of the same
-page. This has been discussed from the mlock/munlock perspective in the
-respective sections above. Both processes [migration, m[un]locking], hold
-the page locked. This provides the first level of synchronization. Page
-migration zeros out the page_mapping of the old page before unlocking it,
-so m[un]lock can skip these pages by testing the page mapping under page
-lock.
-
-When completing page migration, we place the new and old pages back onto the
-lru after dropping the page lock. The "unneeded" page--old page on success,
-new page on failure--will be freed when the reference count held by the
-migration process is released. To ensure that we don't strand pages on the
-unevictable list because of a race between munlock and migration, page
-migration uses the putback_lru_page() function to add migrated pages back to
-the lru.
-
-
-Mlocked Pages: mmap(MAP_LOCKED) System Call Handling
+This is fine, because we'll catch it later if and if vmscan tries to reclaim
+the page. This should be relatively rare.
+
+
+MIGRATING MLOCKED PAGES
+-----------------------
+
+A page that is being migrated has been isolated from the LRU lists and is held
+locked across unmapping of the page, updating the page's address space entry
+and copying the contents and state, until the page table entry has been
+replaced with an entry that refers to the new page. Linux supports migration
+of mlocked pages and other unevictable pages. This involves simply moving the
+PG_mlocked and PG_unevictable states from the old page to the new page.
+
+Note that page migration can race with mlocking or munlocking of the same page.
+This has been discussed from the mlock/munlock perspective in the respective
+sections above. Both processes (migration and m[un]locking) hold the page
+locked. This provides the first level of synchronization. Page migration
+zeros out the page_mapping of the old page before unlocking it, so m[un]lock
+can skip these pages by testing the page mapping under page lock.
+
+To complete page migration, we place the new and old pages back onto the LRU
+after dropping the page lock. The "unneeded" page - old page on success, new
+page on failure - will be freed when the reference count held by the migration
+process is released. To ensure that we don't strand pages on the unevictable
+list because of a race between munlock and migration, page migration uses the
+putback_lru_page() function to add migrated pages back to the LRU.
+
+
+mmap(MAP_LOCKED) SYSTEM CALL HANDLING
+-------------------------------------
In addition the the mlock()/mlockall() system calls, an application can request
-that a region of memory be mlocked using the MAP_LOCKED flag with the mmap()
+that a region of memory be mlocked supplying the MAP_LOCKED flag to the mmap()
call. Furthermore, any mmap() call or brk() call that expands the heap by a
task that has previously called mlockall() with the MCL_FUTURE flag will result
-in the newly mapped memory being mlocked. Before the unevictable/mlock changes,
-the kernel simply called make_pages_present() to allocate pages and populate
-the page table.
+in the newly mapped memory being mlocked. Before the unevictable/mlock
+changes, the kernel simply called make_pages_present() to allocate pages and
+populate the page table.
To mlock a range of memory under the unevictable/mlock infrastructure, the
mmap() handler and task address space expansion functions call
mlock_vma_pages_range() specifying the vma and the address range to mlock.
-mlock_vma_pages_range() filters vmas like mlock_fixup(), as described above in
-"Mlocked Pages: Filtering Vmas". It will clear the VM_LOCKED flag, which will
-have already been set by the caller, in filtered vmas. Thus these vma's need
-not be visited for munlock when the region is unmapped.
+mlock_vma_pages_range() filters VMAs like mlock_fixup(), as described above in
+"Filtering Special VMAs". It will clear the VM_LOCKED flag, which will have
+already been set by the caller, in filtered VMAs. Thus these VMA's need not be
+visited for munlock when the region is unmapped.
-For "normal" vmas, mlock_vma_pages_range() calls __mlock_vma_pages_range() to
+For "normal" VMAs, mlock_vma_pages_range() calls __mlock_vma_pages_range() to
fault/allocate the pages and mlock them. Again, like mlock_fixup(),
mlock_vma_pages_range() downgrades the mmap semaphore to read mode before
-attempting to fault/allocate and mlock the pages; and "upgrades" the semaphore
+attempting to fault/allocate and mlock the pages and "upgrades" the semaphore
back to write mode before returning.
-The callers of mlock_vma_pages_range() will have already added the memory
-range to be mlocked to the task's "locked_vm". To account for filtered vmas,
+The callers of mlock_vma_pages_range() will have already added the memory range
+to be mlocked to the task's "locked_vm". To account for filtered VMAs,
mlock_vma_pages_range() returns the number of pages NOT mlocked. All of the
-callers then subtract a non-negative return value from the task's locked_vm.
-A negative return value represent an error--for example, from get_user_pages()
-attempting to fault in a vma with PROT_NONE access. In this case, we leave
-the memory range accounted as locked_vm, as the protections could be changed
-later and pages allocated into that region.
+callers then subtract a non-negative return value from the task's locked_vm. A
+negative return value represent an error - for example, from get_user_pages()
+attempting to fault in a VMA with PROT_NONE access. In this case, we leave the
+memory range accounted as locked_vm, as the protections could be changed later
+and pages allocated into that region.
-Mlocked Pages: munmap()/exit()/exec() System Call Handling
+munmap()/exit()/exec() SYSTEM CALL HANDLING
+-------------------------------------------
When unmapping an mlocked region of memory, whether by an explicit call to
munmap() or via an internal unmap from exit() or exec() processing, we must
-munlock the pages if we're removing the last VM_LOCKED vma that maps the pages.
+munlock the pages if we're removing the last VM_LOCKED VMA that maps the pages.
Before the unevictable/mlock changes, mlocking did not mark the pages in any
way, so unmapping them required no processing.
To munlock a range of memory under the unevictable/mlock infrastructure, the
-munmap() hander and task address space tear down function call
+munmap() handler and task address space call tear down function
munlock_vma_pages_all(). The name reflects the observation that one always
-specifies the entire vma range when munlock()ing during unmap of a region.
-Because of the vma filtering when mlocking() regions, only "normal" vmas that
+specifies the entire VMA range when munlock()ing during unmap of a region.
+Because of the VMA filtering when mlocking() regions, only "normal" VMAs that
actually contain mlocked pages will be passed to munlock_vma_pages_all().
-munlock_vma_pages_all() clears the VM_LOCKED vma flag and, like mlock_fixup()
+munlock_vma_pages_all() clears the VM_LOCKED VMA flag and, like mlock_fixup()
for the munlock case, calls __munlock_vma_pages_range() to walk the page table
-for the vma's memory range and munlock_vma_page() each resident page mapped by
-the vma. This effectively munlocks the page, only if this is the last
-VM_LOCKED vma that maps the page.
-
+for the VMA's memory range and munlock_vma_page() each resident page mapped by
+the VMA. This effectively munlocks the page, only if this is the last
+VM_LOCKED VMA that maps the page.
-Mlocked Page: try_to_unmap()
-[Note: the code changes represented by this section are really quite small
-compared to the text to describe what happening and why, and to discuss the
-implications.]
+try_to_unmap()
+--------------
-Pages can, of course, be mapped into multiple vmas. Some of these vmas may
+Pages can, of course, be mapped into multiple VMAs. Some of these VMAs may
have VM_LOCKED flag set. It is possible for a page mapped into one or more
-VM_LOCKED vmas not to have the PG_mlocked flag set and therefore reside on one
-of the active or inactive LRU lists. This could happen if, for example, a
-task in the process of munlock()ing the page could not isolate the page from
-the LRU. As a result, vmscan/shrink_page_list() might encounter such a page
-as described in "Unevictable Pages and Vmscan [shrink_*_list()]". To
-handle this situation, try_to_unmap() has been enhanced to check for VM_LOCKED
-vmas while it is walking a page's reverse map.
+VM_LOCKED VMAs not to have the PG_mlocked flag set and therefore reside on one
+of the active or inactive LRU lists. This could happen if, for example, a task
+in the process of munlocking the page could not isolate the page from the LRU.
+As a result, vmscan/shrink_page_list() might encounter such a page as described
+in section "vmscan's handling of unevictable pages". To handle this situation,
+try_to_unmap() checks for VM_LOCKED VMAs while it is walking a page's reverse
+map.
try_to_unmap() is always called, by either vmscan for reclaim or for page
-migration, with the argument page locked and isolated from the LRU. BUG_ON()
-assertions enforce this requirement. Separate functions handle anonymous and
-mapped file pages, as these types of pages have different reverse map
-mechanisms.
-
- try_to_unmap_anon()
-
-To unmap anonymous pages, each vma in the list anchored in the anon_vma must be
-visited--at least until a VM_LOCKED vma is encountered. If the page is being
-unmapped for migration, VM_LOCKED vmas do not stop the process because mlocked
-pages are migratable. However, for reclaim, if the page is mapped into a
-VM_LOCKED vma, the scan stops. try_to_unmap() attempts to acquire the mmap
-semphore of the mm_struct to which the vma belongs in read mode. If this is
-successful, try_to_unmap() will mlock the page via mlock_vma_page()--we
-wouldn't have gotten to try_to_unmap() if the page were already mlocked--and
-will return SWAP_MLOCK, indicating that the page is unevictable. If the
-mmap semaphore cannot be acquired, we are not sure whether the page is really
-unevictable or not. In this case, try_to_unmap() will return SWAP_AGAIN.
-
- try_to_unmap_file() -- linear mappings
-
-Unmapping of a mapped file page works the same, except that the scan visits
-all vmas that maps the page's index/page offset in the page's mapping's
-reverse map priority search tree. It must also visit each vma in the page's
-mapping's non-linear list, if the list is non-empty. As for anonymous pages,
-on encountering a VM_LOCKED vma for a mapped file page, try_to_unmap() will
-attempt to acquire the associated mm_struct's mmap semaphore to mlock the page,
-returning SWAP_MLOCK if this is successful, and SWAP_AGAIN, if not.
-
- try_to_unmap_file() -- non-linear mappings
-
-If a page's mapping contains a non-empty non-linear mapping vma list, then
-try_to_un{map|lock}() must also visit each vma in that list to determine
-whether the page is mapped in a VM_LOCKED vma. Again, the scan must visit
-all vmas in the non-linear list to ensure that the pages is not/should not be
-mlocked. If a VM_LOCKED vma is found in the list, the scan could terminate.
-However, there is no easy way to determine whether the page is actually mapped
-in a given vma--either for unmapping or testing whether the VM_LOCKED vma
-actually pins the page.
-
-So, try_to_unmap_file() handles non-linear mappings by scanning a certain
-number of pages--a "cluster"--in each non-linear vma associated with the page's
-mapping, for each file mapped page that vmscan tries to unmap. If this happens
-to unmap the page we're trying to unmap, try_to_unmap() will notice this on
-return--(page_mapcount(page) == 0)--and return SWAP_SUCCESS. Otherwise, it
-will return SWAP_AGAIN, causing vmscan to recirculate this page. We take
-advantage of the cluster scan in try_to_unmap_cluster() as follows:
-
-For each non-linear vma, try_to_unmap_cluster() attempts to acquire the mmap
-semaphore of the associated mm_struct for read without blocking. If this
-attempt is successful and the vma is VM_LOCKED, try_to_unmap_cluster() will
-retain the mmap semaphore for the scan; otherwise it drops it here. Then,
-for each page in the cluster, if we're holding the mmap semaphore for a locked
-vma, try_to_unmap_cluster() calls mlock_vma_page() to mlock the page. This
-call is a no-op if the page is already locked, but will mlock any pages in
-the non-linear mapping that happen to be unlocked. If one of the pages so
-mlocked is the page passed in to try_to_unmap(), try_to_unmap_cluster() will
-return SWAP_MLOCK, rather than the default SWAP_AGAIN. This will allow vmscan
-to cull the page, rather than recirculating it on the inactive list. Again,
-if try_to_unmap_cluster() cannot acquire the vma's mmap sem, it returns
-SWAP_AGAIN, indicating that the page is mapped by a VM_LOCKED vma, but
-couldn't be mlocked.
-
-
-Mlocked pages: try_to_munlock() Reverse Map Scan
-
-TODO/FIXME: a better name might be page_mlocked()--analogous to the
-page_referenced() reverse map walker.
-
-When munlock_vma_page()--see "Mlocked Pages: munlock()/munlockall()
-System Call Handling" above--tries to munlock a page, it needs to
-determine whether or not the page is mapped by any VM_LOCKED vma, without
-actually attempting to unmap all ptes from the page. For this purpose, the
-unevictable/mlock infrastructure introduced a variant of try_to_unmap() called
-try_to_munlock().
+migration, with the argument page locked and isolated from the LRU. Separate
+functions handle anonymous and mapped file pages, as these types of pages have
+different reverse map mechanisms.
+
+ (*) try_to_unmap_anon()
+
+ To unmap anonymous pages, each VMA in the list anchored in the anon_vma
+ must be visited - at least until a VM_LOCKED VMA is encountered. If the
+ page is being unmapped for migration, VM_LOCKED VMAs do not stop the
+ process because mlocked pages are migratable. However, for reclaim, if
+ the page is mapped into a VM_LOCKED VMA, the scan stops.
+
+ try_to_unmap_anon() attempts to acquire in read mode the mmap semphore of
+ the mm_struct to which the VMA belongs. If this is successful, it will
+ mlock the page via mlock_vma_page() - we wouldn't have gotten to
+ try_to_unmap_anon() if the page were already mlocked - and will return
+ SWAP_MLOCK, indicating that the page is unevictable.
+
+ If the mmap semaphore cannot be acquired, we are not sure whether the page
+ is really unevictable or not. In this case, try_to_unmap_anon() will
+ return SWAP_AGAIN.
+
+ (*) try_to_unmap_file() - linear mappings
+
+ Unmapping of a mapped file page works the same as for anonymous mappings,
+ except that the scan visits all VMAs that map the page's index/page offset
+ in the page's mapping's reverse map priority search tree. It also visits
+ each VMA in the page's mapping's non-linear list, if the list is
+ non-empty.
+
+ As for anonymous pages, on encountering a VM_LOCKED VMA for a mapped file
+ page, try_to_unmap_file() will attempt to acquire the associated
+ mm_struct's mmap semaphore to mlock the page, returning SWAP_MLOCK if this
+ is successful, and SWAP_AGAIN, if not.
+
+ (*) try_to_unmap_file() - non-linear mappings
+
+ If a page's mapping contains a non-empty non-linear mapping VMA list, then
+ try_to_un{map|lock}() must also visit each VMA in that list to determine
+ whether the page is mapped in a VM_LOCKED VMA. Again, the scan must visit
+ all VMAs in the non-linear list to ensure that the pages is not/should not
+ be mlocked.
+
+ If a VM_LOCKED VMA is found in the list, the scan could terminate.
+ However, there is no easy way to determine whether the page is actually
+ mapped in a given VMA - either for unmapping or testing whether the
+ VM_LOCKED VMA actually pins the page.
+
+ try_to_unmap_file() handles non-linear mappings by scanning a certain
+ number of pages - a "cluster" - in each non-linear VMA associated with the
+ page's mapping, for each file mapped page that vmscan tries to unmap. If
+ this happens to unmap the page we're trying to unmap, try_to_unmap() will
+ notice this on return (page_mapcount(page) will be 0) and return
+ SWAP_SUCCESS. Otherwise, it will return SWAP_AGAIN, causing vmscan to
+ recirculate this page. We take advantage of the cluster scan in
+ try_to_unmap_cluster() as follows:
+
+ For each non-linear VMA, try_to_unmap_cluster() attempts to acquire the
+ mmap semaphore of the associated mm_struct for read without blocking.
+
+ If this attempt is successful and the VMA is VM_LOCKED,
+ try_to_unmap_cluster() will retain the mmap semaphore for the scan;
+ otherwise it drops it here.
+
+ Then, for each page in the cluster, if we're holding the mmap semaphore
+ for a locked VMA, try_to_unmap_cluster() calls mlock_vma_page() to
+ mlock the page. This call is a no-op if the page is already locked,
+ but will mlock any pages in the non-linear mapping that happen to be
+ unlocked.
+
+ If one of the pages so mlocked is the page passed in to try_to_unmap(),
+ try_to_unmap_cluster() will return SWAP_MLOCK, rather than the default
+ SWAP_AGAIN. This will allow vmscan to cull the page, rather than
+ recirculating it on the inactive list.
+
+ Again, if try_to_unmap_cluster() cannot acquire the VMA's mmap sem, it
+ returns SWAP_AGAIN, indicating that the page is mapped by a VM_LOCKED
+ VMA, but couldn't be mlocked.
+
+
+try_to_munlock() REVERSE MAP SCAN
+---------------------------------
+
+ [!] TODO/FIXME: a better name might be page_mlocked() - analogous to the
+ page_referenced() reverse map walker.
+
+When munlock_vma_page() [see section "munlock()/munlockall() System Call
+Handling" above] tries to munlock a page, it needs to determine whether or not
+the page is mapped by any VM_LOCKED VMA without actually attempting to unmap
+all PTEs from the page. For this purpose, the unevictable/mlock infrastructure
+introduced a variant of try_to_unmap() called try_to_munlock().
try_to_munlock() calls the same functions as try_to_unmap() for anonymous and
mapped file pages with an additional argument specifing unlock versus unmap
processing. Again, these functions walk the respective reverse maps looking
-for VM_LOCKED vmas. When such a vma is found for anonymous pages and file
+for VM_LOCKED VMAs. When such a VMA is found for anonymous pages and file
pages mapped in linear VMAs, as in the try_to_unmap() case, the functions
attempt to acquire the associated mmap semphore, mlock the page via
mlock_vma_page() and return SWAP_MLOCK. This effectively undoes the
pre-clearing of the page's PG_mlocked done by munlock_vma_page.
-If try_to_unmap() is unable to acquire a VM_LOCKED vma's associated mmap
-semaphore, it will return SWAP_AGAIN. This will allow shrink_page_list()
-to recycle the page on the inactive list and hope that it has better luck
-with the page next time.
-
-For file pages mapped into non-linear vmas, the try_to_munlock() logic works
-slightly differently. On encountering a VM_LOCKED non-linear vma that might
-map the page, try_to_munlock() returns SWAP_AGAIN without actually mlocking
-the page. munlock_vma_page() will just leave the page unlocked and let
-vmscan deal with it--the usual fallback position.
-
-Note that try_to_munlock()'s reverse map walk must visit every vma in a pages'
-reverse map to determine that a page is NOT mapped into any VM_LOCKED vma.
-However, the scan can terminate when it encounters a VM_LOCKED vma and can
-successfully acquire the vma's mmap semphore for read and mlock the page.
-Although try_to_munlock() can be called many [very many!] times when
-munlock()ing a large region or tearing down a large address space that has been
-mlocked via mlockall(), overall this is a fairly rare event.
-
-Mlocked Page: Page Reclaim in shrink_*_list()
-
-shrink_active_list() culls any obviously unevictable pages--i.e.,
-!page_evictable(page, NULL)--diverting these to the unevictable lru
-list. However, shrink_active_list() only sees unevictable pages that
-made it onto the active/inactive lru lists. Note that these pages do not
-have PageUnevictable set--otherwise, they would be on the unevictable list and
-shrink_active_list would never see them.
+If try_to_unmap() is unable to acquire a VM_LOCKED VMA's associated mmap
+semaphore, it will return SWAP_AGAIN. This will allow shrink_page_list() to
+recycle the page on the inactive list and hope that it has better luck with the
+page next time.
+
+For file pages mapped into non-linear VMAs, the try_to_munlock() logic works
+slightly differently. On encountering a VM_LOCKED non-linear VMA that might
+map the page, try_to_munlock() returns SWAP_AGAIN without actually mlocking the
+page. munlock_vma_page() will just leave the page unlocked and let vmscan deal
+with it - the usual fallback position.
+
+Note that try_to_munlock()'s reverse map walk must visit every VMA in a page's
+reverse map to determine that a page is NOT mapped into any VM_LOCKED VMA.
+However, the scan can terminate when it encounters a VM_LOCKED VMA and can
+successfully acquire the VMA's mmap semphore for read and mlock the page.
+Although try_to_munlock() might be called a great many times when munlocking a
+large region or tearing down a large address space that has been mlocked via
+mlockall(), overall this is a fairly rare event.
+
+
+PAGE RECLAIM IN shrink_*_list()
+-------------------------------
+
+shrink_active_list() culls any obviously unevictable pages - i.e.
+!page_evictable(page, NULL) - diverting these to the unevictable list.
+However, shrink_active_list() only sees unevictable pages that made it onto the
+active/inactive lru lists. Note that these pages do not have PageUnevictable
+set - otherwise they would be on the unevictable list and shrink_active_list
+would never see them.
Some examples of these unevictable pages on the LRU lists are:
-1) ramfs pages that have been placed on the lru lists when first allocated.
+ (1) ramfs pages that have been placed on the LRU lists when first allocated.
+
+ (2) SHM_LOCK'd shared memory pages. shmctl(SHM_LOCK) does not attempt to
+ allocate or fault in the pages in the shared memory region. This happens
+ when an application accesses the page the first time after SHM_LOCK'ing
+ the segment.
-2) SHM_LOCKed shared memory pages. shmctl(SHM_LOCK) does not attempt to
- allocate or fault in the pages in the shared memory region. This happens
- when an application accesses the page the first time after SHM_LOCKing
- the segment.
+ (3) mlocked pages that could not be isolated from the LRU and moved to the
+ unevictable list in mlock_vma_page().
-3) Mlocked pages that could not be isolated from the lru and moved to the
- unevictable list in mlock_vma_page().
+ (4) Pages mapped into multiple VM_LOCKED VMAs, but try_to_munlock() couldn't
+ acquire the VMA's mmap semaphore to test the flags and set PageMlocked.
+ munlock_vma_page() was forced to let the page back on to the normal LRU
+ list for vmscan to handle.
-3) Pages mapped into multiple VM_LOCKED vmas, but try_to_munlock() couldn't
- acquire the vma's mmap semaphore to test the flags and set PageMlocked.
- munlock_vma_page() was forced to let the page back on to the normal
- LRU list for vmscan to handle.
+shrink_inactive_list() also diverts any unevictable pages that it finds on the
+inactive lists to the appropriate zone's unevictable list.
-shrink_inactive_list() also culls any unevictable pages that it finds on
-the inactive lists, again diverting them to the appropriate zone's unevictable
-lru list. shrink_inactive_list() should only see SHM_LOCKed pages that became
-SHM_LOCKed after shrink_active_list() had moved them to the inactive list, or
-pages mapped into VM_LOCKED vmas that munlock_vma_page() couldn't isolate from
-the lru to recheck via try_to_munlock(). shrink_inactive_list() won't notice
-the latter, but will pass on to shrink_page_list().
+shrink_inactive_list() should only see SHM_LOCK'd pages that became SHM_LOCK'd
+after shrink_active_list() had moved them to the inactive list, or pages mapped
+into VM_LOCKED VMAs that munlock_vma_page() couldn't isolate from the LRU to
+recheck via try_to_munlock(). shrink_inactive_list() won't notice the latter,
+but will pass on to shrink_page_list().
shrink_page_list() again culls obviously unevictable pages that it could
encounter for similar reason to shrink_inactive_list(). Pages mapped into
-VM_LOCKED vmas but without PG_mlocked set will make it all the way to
+VM_LOCKED VMAs but without PG_mlocked set will make it all the way to
try_to_unmap(). shrink_page_list() will divert them to the unevictable list
when try_to_unmap() returns SWAP_MLOCK, as discussed above.
diff --git a/MAINTAINERS b/MAINTAINERS
index 3dfe1a7c9a93..1c4b9598f218 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -461,7 +461,7 @@ F: arch/x86/include/asm/amd_iommu*.h
AMD MICROCODE UPDATE SUPPORT
P: Andreas Herrmann
-M: andeas.herrmann3@amd.com
+M: andreas.herrmann3@amd.com
L: amd64-microcode@amd64.org
S: Supported
F: arch/x86/kernel/microcode_amd.c
@@ -543,6 +543,14 @@ S: Maintained
F: arch/arm/lib/floppydma.S
F: arch/arm/include/asm/floppy.h
+ARM PORT
+P: Russell King
+M: linux@arm.linux.org.uk
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+W: http://www.arm.linux.org.uk/
+S: Maintained
+F: arch/arm/
+
ARM PRIMECELL MMCI PL180/1 DRIVER
S: Orphan
F: drivers/mmc/host/mmci.*
@@ -592,6 +600,13 @@ M: kernel@wantstofly.org
L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
S: Maintained
+ARM/CLKDEV SUPPORT
+P: Russell King
+M: linux@arm.linux.org.uk
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+F: arch/arm/common/clkdev.c
+F: arch/arm/include/asm/clkdev.h
+
ARM/COMPULAB CM-X270/EM-X270 and CM-X300 MACHINE SUPPORT
P: Mike Rapoport
M: mike@compulab.co.il
@@ -610,6 +625,15 @@ L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
T: git git://gitorious.org/linux-gemini/mainline.git
S: Maintained
+ARM/EBSA110 MACHINE SUPPORT
+P: Russell King
+M: linux@arm.linux.org.uk
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+W: http://www.arm.linux.org.uk/
+S: Maintained
+F: arch/arm/mach-ebsa110/
+F: drivers/net/arm/am79c961a.*
+
ARM/EZX SMARTPHONES (A780, A910, A1200, E680, ROKR E2 and ROKR E6)
P: Daniel Ribeiro
M: drwyrm@gmail.com
@@ -627,6 +651,15 @@ M: paulius.zaleckas@teltonika.lt
L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
S: Maintained
+ARM/FOOTBRIDGE ARCHITECTURE
+P: Russell King
+M: linux@arm.linux.org.uk
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+W: http://www.arm.linux.org.uk/
+S: Maintained
+F: arch/arm/include/asm/hardware/dec21285.h
+F: arch/arm/mach-footbridge/
+
ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
P: Sascha Hauer
M: kernel@pengutronix.de
@@ -767,19 +800,27 @@ M: kernel@wantstofly.org
L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
S: Maintained
+ARM/RISCPC ARCHITECTURE
+P: Russell King
+M: linux@arm.linux.org.uk
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+W: http://www.arm.linux.org.uk/
+S: Maintained
+F: arch/arm/common/time-acorn.c
+F: arch/arm/include/asm/hardware/entry-macro-iomd.S
+F: arch/arm/include/asm/hardware/ioc.h
+F: arch/arm/include/asm/hardware/iomd.h
+F: arch/arm/include/asm/hardware/memc.h
+F: arch/arm/mach-rpc/
+F: drivers/net/arm/ether*
+F: drivers/scsi/arm/
+
ARM/SHARK MACHINE SUPPORT
P: Alexander Schulz
M: alex@shark-linux.de
W: http://www.shark-linux.de/shark.html
S: Maintained
-ARM/STRONGARM110 PORT
-P: Russell King
-M: rmk@arm.linux.org.uk
-L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
-W: http://www.arm.linux.org.uk/
-S: Maintained
-
ARM/S3C2410 ARM ARCHITECTURE
P: Ben Dooks
M: ben-linux@fluff.org
@@ -813,6 +854,14 @@ L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
W: http://www.mcuos.com
S: Maintained
+ARM/VFP SUPPORT
+P: Russell King
+M: linux@arm.linux.org.uk
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+W: http://www.arm.linux.org.uk/
+S: Maintained
+F: arch/arm/vfp/
+
ARPD SUPPORT
P: Jonathan Layes
L: netdev@vger.kernel.org
@@ -1244,6 +1293,14 @@ S: Maintained
F: Documentation/video4linux/bttv/
F: drivers/media/video/bt8xx/bttv*
+CACHEFILES: FS-CACHE BACKEND FOR CACHING ON MOUNTED FILESYSTEMS
+P: David Howells
+M: dhowells@redhat.com
+L: linux-cachefs@redhat.com
+S: Supported
+F: Documentation/filesystems/caching/cachefiles.txt
+F: fs/cachefiles/
+
CAFE CMOS INTEGRATED CAMERA CONTROLLER DRIVER
P: Jonathan Corbet
M: corbet@lwn.net
@@ -1286,12 +1343,9 @@ L: cbe-oss-dev@ozlabs.org
W: http://www.ibm.com/developerworks/power/cell/
S: Supported
F: arch/powerpc/include/asm/cell*.h
-F: arch/powerpc/include/asm/lv1call.h
-F: arch/powerpc/include/asm/ps3*.h
F: arch/powerpc/include/asm/spu*.h
F: arch/powerpc/oprofile/*cell*
F: arch/powerpc/platforms/cell/
-F: arch/powerpc/platforms/ps3/
CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM:
P: David Vrabel
@@ -1378,6 +1432,11 @@ S: Maintained
F: Documentation/input/cs461x.txt
F: sound/pci/cs46xx/
+CLK API
+P: Russell King
+M: linux@arm.linux.org.uk
+F: include/linux/clk.h
+
CODA FILE SYSTEM
P: Jan Harkes
M: jaharkes@cs.cmu.edu
@@ -1582,7 +1641,8 @@ F: drivers/infiniband/hw/cxgb3/
CYBERPRO FB DRIVER
P: Russell King
-M: rmk@arm.linux.org.uk
+M: linux@arm.linux.org.uk
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
W: http://www.arm.linux.org.uk/
S: Maintained
F: drivers/video/cyber2000fb.*
@@ -1900,7 +1960,7 @@ F: fs/ecryptfs/
EDAC-CORE
P: Doug Thompson
M: dougthompson@xmission.com
-L: bluesmoke-devel@lists.sourceforge.net
+L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
W: bluesmoke.sourceforge.net
S: Supported
F: Documentation/edac.txt
@@ -1912,7 +1972,7 @@ P: Mark Gross
P: Doug Thompson
M: mark.gross@intel.com
M: dougthompson@xmission.com
-L: bluesmoke-devel@lists.sourceforge.net
+L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/e752x_edac.c
@@ -1920,7 +1980,7 @@ F: drivers/edac/e752x_edac.c
EDAC-E7XXX
P: Doug Thompson
M: dougthompson@xmission.com
-L: bluesmoke-devel@lists.sourceforge.net
+L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/e7xxx_edac.c
@@ -1928,7 +1988,7 @@ F: drivers/edac/e7xxx_edac.c
EDAC-I82443BXGX
P: Tim Small
M: tim@buttersideup.com
-L: bluesmoke-devel@lists.sourceforge.net
+L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/i82443bxgx_edac.c
@@ -1936,7 +1996,7 @@ F: drivers/edac/i82443bxgx_edac.c
EDAC-I3000
P: Jason Uhlenkott
M: juhlenko@akamai.com
-L: bluesmoke-devel@lists.sourceforge.net
+L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/i3000_edac.c
@@ -1944,7 +2004,7 @@ F: drivers/edac/i3000_edac.c
EDAC-I5000
P: Doug Thompson
M: dougthompson@xmission.com
-L: bluesmoke-devel@lists.sourceforge.net
+L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/i5000_edac.c
@@ -1952,7 +2012,7 @@ F: drivers/edac/i5000_edac.c
EDAC-I5400
P: Mauro Carvalho Chehab
M: mchehab@redhat.com
-L: bluesmoke-devel@lists.sourceforge.net
+L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/i5400_edac.c
@@ -1962,7 +2022,7 @@ P: Ranganathan Desikan
P: Arvind R.
M: rdesikan@jetzbroadband.com
M: arvind@acarlab.com
-L: bluesmoke-devel@lists.sourceforge.net
+L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/i82975x_edac.c
@@ -1970,7 +2030,7 @@ F: drivers/edac/i82975x_edac.c
EDAC-PASEMI
P: Egor Martovetsky
M: egor@pasemi.com
-L: bluesmoke-devel@lists.sourceforge.net
+L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/pasemi_edac.c
@@ -1978,7 +2038,7 @@ F: drivers/edac/pasemi_edac.c
EDAC-R82600
P: Tim Small
M: tim@buttersideup.com
-L: bluesmoke-devel@lists.sourceforge.net
+L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/r82600_edac.c
@@ -2008,6 +2068,8 @@ F: drivers/infiniband/hw/ehca/
EMBEDDED LINUX
P: Paul Gortmaker
M: paul.gortmaker@windriver.com
+P: Matt Mackall
+M: mpm@selenic.com
P: David Woodhouse
M: dwmw2@infradead.org
L: linux-embedded@vger.kernel.org
@@ -2276,6 +2338,15 @@ F: Documentation/power/freezing-of-tasks.txt
F: include/linux/freezer.h
F: kernel/freezer.c
+FS-CACHE: LOCAL CACHING FOR NETWORK FILESYSTEMS
+P: David Howells
+M: dhowells@redhat.com
+L: linux-cachefs@redhat.com
+S: Supported
+F: Documentation/filesystems/caching/
+F: fs/fscache/
+F: include/linux/fscache*.h
+
FTRACE
P: Steven Rostedt
M: rostedt@goodmis.org
@@ -2496,7 +2567,6 @@ F: kernel/power/
F: include/linux/suspend.h
F: include/linux/freezer.h
F: include/linux/pm.h
-F: include/asm-*/suspend*.h
F: arch/*/include/asm/suspend*.h
HID CORE LAYER
@@ -2598,8 +2668,8 @@ S: Maintained
F: fs/hpfs/
HSO 3G MODEM DRIVER
-P: Denis Joseph Barrow
-M: d.barow@option.com
+P: Jan Dumon
+M: j.dumon@option.com
W: http://www.pharscape.org
S: Maintained
F: drivers/net/usb/hso.c
@@ -2694,7 +2764,7 @@ IDE SUBSYSTEM
P: Bartlomiej Zolnierkiewicz
M: bzolnier@gmail.com
L: linux-ide@vger.kernel.org
-T: quilt kernel.org/pub/linux/kernel/people/bart/pata-2.6/
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6.git
S: Maintained
F: Documentation/ide/
F: drivers/ide/
@@ -3274,10 +3344,16 @@ P: Eduard - Gabriel Munteanu
M: eduard.munteanu@linux360.ro
L: linux-kernel@vger.kernel.org
S: Maintained
-F: Documentation/vm/kmemtrace.txt
+F: Documentation/trace/kmemtrace.txt
F: include/trace/kmemtrace.h
F: kernel/trace/kmemtrace.c
+KMEMLEAK
+P: Catalin Marinas
+M: catalin.marinas@arm.com
+L: linux-kernel@vger.kernel.org
+S: Maintained
+
KPROBES
P: Ananth N Mavinakayanahalli
M: ananth@in.ibm.com
@@ -3370,11 +3446,10 @@ L: linuxppc-dev@ozlabs.org
S: Maintained
LINUX FOR POWERPC EMBEDDED MPC5XXX
-P: Sylvain Munaut
-M: tnt@246tNt.com
P: Grant Likely
M: grant.likely@secretlab.ca
L: linuxppc-dev@ozlabs.org
+T: git git://git.secretlab.ca/git/linux-2.6.git
S: Maintained
LINUX FOR POWERPC EMBEDDED PPC4XX
@@ -3384,7 +3459,7 @@ P: Matt Porter
M: mporter@kernel.crashing.org
W: http://www.penguinppc.org/
L: linuxppc-dev@ozlabs.org
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/jwboyer/powerpc.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jwboyer/powerpc-4xx.git
S: Maintained
LINUX FOR POWERPC EMBEDDED XILINX VIRTEX
@@ -3392,6 +3467,7 @@ P: Grant Likely
M: grant.likely@secretlab.ca
W: http://wiki.secretlab.ca/index.php/Linux_on_Xilinx_Virtex
L: linuxppc-dev@ozlabs.org
+T: git git://git.secretlab.ca/git/linux-2.6.git
S: Maintained
LINUX FOR POWERPC EMBEDDED PPC8XX
@@ -3686,6 +3762,7 @@ L: microblaze-uclinux@itee.uq.edu.au
W: http://www.monstr.eu/fdt/
T: git git://git.monstr.eu/linux-2.6-microblaze.git
S: Supported
+F: arch/microblaze/
MICROTEK X6 SCANNER
P: Oliver Neukum
@@ -4117,6 +4194,11 @@ F: arch/*/oprofile/
F: drivers/oprofile/
F: include/linux/oprofile.h
+OQO WMI EXTRAS DRIVER
+P: Matthew Garrett
+M: mjg59@srcf.ucam.org
+S: Maintained
+
ORACLE CLUSTER FILESYSTEM 2 (OCFS2)
P: Mark Fasheh
M: mfasheh@suse.com
@@ -4124,7 +4206,7 @@ P: Joel Becker
M: joel.becker@oracle.com
L: ocfs2-devel@oss.oracle.com (moderated for non-subscribers)
W: http://oss.oracle.com/projects/ocfs2/
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2.git
S: Supported
F: Documentation/filesystems/ocfs2.txt
F: Documentation/filesystems/dlmfs.txt
@@ -4446,7 +4528,9 @@ F: arch/powerpc/include/asm/ps3*.h
F: arch/powerpc/platforms/ps3/
F: drivers/*/ps3*
F: drivers/ps3/
+F: drivers/rtc/rtc-ps3.c
F: drivers/usb/host/*ps3.c
+F: sound/ppc/snd_ps3*
PS3VRAM DRIVER
P: Jim Paris
@@ -4454,6 +4538,19 @@ M: jim@jtan.com
L: cbe-oss-dev@ozlabs.org
S: Maintained
+PTRACE SUPPORT
+P: Roland McGrath
+M: roland@redhat.com
+P: Oleg Nesterov
+M: oleg@redhat.com
+L: linux-kernel@vger.kernel.org
+S: Maintained
+F: include/asm-generic/syscall.h
+F: include/linux/ptrace.h
+F: include/linux/regset.h
+F: include/linux/tracehook.h
+F: kernel/ptrace.c
+
PVRUSB2 VIDEO4LINUX DRIVER
P: Mike Isely
M: isely@pobox.com
@@ -4477,7 +4574,8 @@ F: drivers/pcmcia/pxa2xx*
F: drivers/spi/pxa2xx*
F: drivers/usb/gadget/pxa2*
F: include/sound/pxa2xx-lib.h
-F: sound/soc/pxa/pxa2xx*
+F: sound/arm/pxa*
+F: sound/soc/pxa
PXA168 SUPPORT
P: Eric Miao
@@ -4599,13 +4697,13 @@ F: kernel/rcutorture.c
RDC R-321X SoC
P: Florian Fainelli
-M: florian.fainelli@telecomint.eu
+M: florian@openwrt.org
L: linux-kernel@vger.kernel.org
S: Maintained
RDC R6040 FAST ETHERNET DRIVER
P: Florian Fainelli
-M: florian.fainelli@telecomint.eu
+M: florian@openwrt.org
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/r6040.c
@@ -4984,8 +5082,8 @@ S: Maintained for 2.6.
F: Documentation/sgi-visws.txt
SGI XP/XPC/XPNET DRIVER
-P: Dean Nelson
-M: dcn@sgi.com
+P: Robin Holt
+M: holt@sgi.com
S: Maintained
F: drivers/misc/sgi-xp/
@@ -5192,7 +5290,12 @@ M: perex@perex.cz
P: Takashi Iwai
M: tiwai@suse.de
L: alsa-devel@alsa-project.org (subscribers-only)
+W: http://www.alsa-project.org/
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git
+T: git git://git.alsa-project.org/alsa-kernel.git
S: Maintained
+F: Documentation/sound/
+F: include/sound/
F: sound/
SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
@@ -5205,6 +5308,7 @@ L: alsa-devel@alsa-project.org (subscribers-only)
W: http://alsa-project.org/main/index.php/ASoC
S: Supported
F: sound/soc/
+F: include/sound/soc*
SPARC + UltraSPARC (sparc/sparc64)
P: David S. Miller
@@ -5319,7 +5423,9 @@ L: linux-sh@vger.kernel.org
W: http://www.linux-sh.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git
S: Supported
+F: Documentation/sh/
F: arch/sh/
+F: drivers/sh/
SUSPEND TO RAM
P: Len Brown
@@ -5337,7 +5443,6 @@ F: kernel/power/
F: include/linux/suspend.h
F: include/linux/freezer.h
F: include/linux/pm.h
-F: include/asm-*/suspend.h
SVGA HANDLING
P: Martin Mares
@@ -5571,7 +5676,7 @@ L: uclinux-dev@uclinux.org (subscribers-only)
S: Maintained
F: arch/m68knommu/
-UCLINUX FOR RENESAS H8/300
+UCLINUX FOR RENESAS H8/300 (H8300)
P: Yoshinori Sato
M: ysato@users.sourceforge.jp
W: http://uclinux-h8.sourceforge.jp/
diff --git a/Makefile b/Makefile
index ad830bd45a4b..9b2b58c3b3db 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 30
-EXTRAVERSION = -rc1
-NAME = Temporary Tasmanian Devil
+EXTRAVERSION = -rc5
+NAME = Vindictive Armadillo
# *DOCUMENTATION*
# To see a list of typical targets execute "make help"
@@ -169,7 +169,7 @@ 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/sh.*/sh/ )
+ -e s/sh[234].*/sh/ )
# Cross compiling and selecting different set of gcc/bin-utils
# ---------------------------------------------------------------------------
@@ -210,6 +210,11 @@ ifeq ($(ARCH),sparc64)
SRCARCH := sparc
endif
+# Additional ARCH settings for sh
+ifeq ($(ARCH),sh64)
+ SRCARCH := sh
+endif
+
# Where to locate arch specific headers
hdr-arch := $(SRCARCH)
@@ -1195,7 +1200,7 @@ CLEAN_FILES += vmlinux System.map \
.tmp_kallsyms* .tmp_version .tmp_vmlinux* .tmp_System.map
# Directories & files removed with 'make mrproper'
-MRPROPER_DIRS += include/config include2 usr/include
+MRPROPER_DIRS += include/config include2 usr/include include/generated
MRPROPER_FILES += .config .config.old include/asm .version .old_version \
include/linux/autoconf.h include/linux/version.h \
include/linux/utsrelease.h \
@@ -1288,7 +1293,7 @@ help:
@echo ' dir/ - Build all files in dir and below'
@echo ' dir/file.[ois] - Build specified target only'
@echo ' dir/file.ko - Build module including final link'
- @echo ' prepare - Set up for building external modules'
+ @echo ' modules_prepare - Set up for building external modules'
@echo ' tags/TAGS - Generate tags file for editors'
@echo ' cscope - Generate cscope index'
@echo ' kernelrelease - Output the release version string'
@@ -1416,7 +1421,9 @@ $(clean-dirs):
$(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
clean: rm-dirs := $(MODVERDIR)
-clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers
+clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers \
+ $(KBUILD_EXTMOD)/Module.markers \
+ $(KBUILD_EXTMOD)/modules.order
clean: $(clean-dirs)
$(call cmd,rmdirs)
$(call cmd,rmfiles)
diff --git a/arch/alpha/include/asm/barrier.h b/arch/alpha/include/asm/barrier.h
index ac78eba909bc..ce8860a0b32d 100644
--- a/arch/alpha/include/asm/barrier.h
+++ b/arch/alpha/include/asm/barrier.h
@@ -16,11 +16,13 @@ __asm__ __volatile__("wmb": : :"memory")
__asm__ __volatile__("mb": : :"memory")
#ifdef CONFIG_SMP
+#define __ASM_SMP_MB "\tmb\n"
#define smp_mb() mb()
#define smp_rmb() rmb()
#define smp_wmb() wmb()
#define smp_read_barrier_depends() read_barrier_depends()
#else
+#define __ASM_SMP_MB
#define smp_mb() barrier()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
diff --git a/arch/alpha/include/asm/futex.h b/arch/alpha/include/asm/futex.h
index 6a332a9f099c..945de222ab91 100644
--- a/arch/alpha/include/asm/futex.h
+++ b/arch/alpha/include/asm/futex.h
@@ -1,6 +1,116 @@
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
+#ifndef _ASM_ALPHA_FUTEX_H
+#define _ASM_ALPHA_FUTEX_H
-#include <asm-generic/futex.h>
+#ifdef __KERNEL__
-#endif
+#include <linux/futex.h>
+#include <linux/uaccess.h>
+#include <asm/errno.h>
+#include <asm/barrier.h>
+
+#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
+ __asm__ __volatile__( \
+ __ASM_SMP_MB \
+ "1: ldl_l %0,0(%2)\n" \
+ insn \
+ "2: stl_c %1,0(%2)\n" \
+ " beq %1,4f\n" \
+ " mov $31,%1\n" \
+ "3: .subsection 2\n" \
+ "4: br 1b\n" \
+ " .previous\n" \
+ " .section __ex_table,\"a\"\n" \
+ " .long 1b-.\n" \
+ " lda $31,3b-1b(%1)\n" \
+ " .long 2b-.\n" \
+ " lda $31,3b-2b(%1)\n" \
+ " .previous\n" \
+ : "=&r" (oldval), "=&r"(ret) \
+ : "r" (uaddr), "r"(oparg) \
+ : "memory")
+
+static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret;
+ if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+ oparg = 1 << oparg;
+
+ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+ return -EFAULT;
+
+ pagefault_disable();
+
+ switch (op) {
+ case FUTEX_OP_SET:
+ __futex_atomic_op("mov %3,%1\n", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_ADD:
+ __futex_atomic_op("addl %0,%3,%1\n", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_OR:
+ __futex_atomic_op("or %0,%3,%1\n", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_ANDN:
+ __futex_atomic_op("andnot %0,%3,%1\n", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_XOR:
+ __futex_atomic_op("xor %0,%3,%1\n", ret, oldval, uaddr, oparg);
+ break;
+ default:
+ ret = -ENOSYS;
+ }
+
+ pagefault_enable();
+
+ if (!ret) {
+ switch (cmp) {
+ case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+ case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+ case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+ case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+ case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+ case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+ default: ret = -ENOSYS;
+ }
+ }
+ return ret;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+ int prev, cmp;
+
+ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+ return -EFAULT;
+
+ __asm__ __volatile__ (
+ __ASM_SMP_MB
+ "1: ldl_l %0,0(%2)\n"
+ " cmpeq %0,%3,%1\n"
+ " beq %1,3f\n"
+ " mov %4,%1\n"
+ "2: stl_c %1,0(%2)\n"
+ " beq %1,4f\n"
+ "3: .subsection 2\n"
+ "4: br 1b\n"
+ " .previous\n"
+ " .section __ex_table,\"a\"\n"
+ " .long 1b-.\n"
+ " lda $31,3b-1b(%0)\n"
+ " .long 2b-.\n"
+ " lda $31,3b-2b(%0)\n"
+ " .previous\n"
+ : "=&r"(prev), "=&r"(cmp)
+ : "r"(uaddr), "r"((long)oldval), "r"(newval)
+ : "memory");
+
+ return prev;
+}
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_ALPHA_FUTEX_H */
diff --git a/arch/alpha/include/asm/percpu.h b/arch/alpha/include/asm/percpu.h
index 3495e8e00d70..e9e0bb5a23bf 100644
--- a/arch/alpha/include/asm/percpu.h
+++ b/arch/alpha/include/asm/percpu.h
@@ -73,6 +73,6 @@ extern unsigned long __per_cpu_offset[NR_CPUS];
#endif /* SMP */
-#define DECLARE_PER_CPU(type, name) extern __typeof__(type) per_cpu_var(name)
+#include <asm-generic/percpu.h>
#endif /* __ALPHA_PERCPU_H */
diff --git a/arch/alpha/include/asm/uaccess.h b/arch/alpha/include/asm/uaccess.h
index 163f3053001c..b49ec2f8d6e3 100644
--- a/arch/alpha/include/asm/uaccess.h
+++ b/arch/alpha/include/asm/uaccess.h
@@ -507,5 +507,7 @@ struct exception_table_entry
(pc) + (_fixup)->fixup.bits.nextinsn; \
})
+#define ARCH_HAS_SORT_EXTABLE
+#define ARCH_HAS_SEARCH_EXTABLE
#endif /* __ALPHA_UACCESS_H */
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
index a427538252f8..7739a62440a7 100644
--- a/arch/alpha/kernel/Makefile
+++ b/arch/alpha/kernel/Makefile
@@ -8,7 +8,7 @@ EXTRA_CFLAGS := -Werror -Wno-sign-compare
obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
irq_alpha.o signal.o setup.o ptrace.o time.o \
- alpha_ksyms.o systbls.o err_common.o io.o binfmt_loader.o
+ alpha_ksyms.o systbls.o err_common.o io.o
obj-$(CONFIG_VGA_HOSE) += console.o
obj-$(CONFIG_SMP) += smp.o
@@ -43,6 +43,10 @@ else
# Misc support
obj-$(CONFIG_ALPHA_SRM) += srmcons.o
+ifdef CONFIG_BINFMT_AOUT
+obj-y += binfmt_loader.o
+endif
+
# Core logic support
obj-$(CONFIG_ALPHA_APECS) += core_apecs.o
obj-$(CONFIG_ALPHA_CIA) += core_cia.o
diff --git a/arch/alpha/kernel/binfmt_loader.c b/arch/alpha/kernel/binfmt_loader.c
index 4a0af906b00a..3fcfad410130 100644
--- a/arch/alpha/kernel/binfmt_loader.c
+++ b/arch/alpha/kernel/binfmt_loader.c
@@ -46,6 +46,6 @@ static struct linux_binfmt loader_format = {
static int __init init_loader_binfmt(void)
{
- return register_binfmt(&loader_format);
+ return insert_binfmt(&loader_format);
}
arch_initcall(init_loader_binfmt);
diff --git a/arch/alpha/kernel/err_ev6.c b/arch/alpha/kernel/err_ev6.c
index 985e5c1681ac..8ca6345bf131 100644
--- a/arch/alpha/kernel/err_ev6.c
+++ b/arch/alpha/kernel/err_ev6.c
@@ -229,7 +229,7 @@ ev6_process_logout_frame(struct el_common *mchk_header, int print)
}
void
-ev6_machine_check(u64 vector, u64 la_ptr)
+ev6_machine_check(unsigned long vector, unsigned long la_ptr)
{
struct el_common *mchk_header = (struct el_common *)la_ptr;
diff --git a/arch/alpha/kernel/err_ev7.c b/arch/alpha/kernel/err_ev7.c
index 73770c6ca013..d738a67112d4 100644
--- a/arch/alpha/kernel/err_ev7.c
+++ b/arch/alpha/kernel/err_ev7.c
@@ -117,7 +117,7 @@ ev7_collect_logout_frame_subpackets(struct el_subpacket *el_ptr,
}
void
-ev7_machine_check(u64 vector, u64 la_ptr)
+ev7_machine_check(unsigned long vector, unsigned long la_ptr)
{
struct el_subpacket *el_ptr = (struct el_subpacket *)la_ptr;
char *saved_err_prefix = err_print_prefix;
@@ -246,7 +246,7 @@ ev7_process_pal_subpacket(struct el_subpacket *header)
switch(header->type) {
case EL_TYPE__PAL__LOGOUT_FRAME:
- printk("%s*** MCHK occurred on LPID %ld (RBOX %llx)\n",
+ printk("%s*** MCHK occurred on LPID %lld (RBOX %llx)\n",
err_print_prefix,
packet->by_type.logout.whami,
packet->by_type.logout.rbox_whami);
diff --git a/arch/alpha/kernel/err_impl.h b/arch/alpha/kernel/err_impl.h
index 3c12258158e6..0c010ca4611e 100644
--- a/arch/alpha/kernel/err_impl.h
+++ b/arch/alpha/kernel/err_impl.h
@@ -60,26 +60,26 @@ extern struct ev7_lf_subpackets *
ev7_collect_logout_frame_subpackets(struct el_subpacket *,
struct ev7_lf_subpackets *);
extern void ev7_register_error_handlers(void);
-extern void ev7_machine_check(u64, u64);
+extern void ev7_machine_check(unsigned long, unsigned long);
/*
* err_ev6.c
*/
extern void ev6_register_error_handlers(void);
extern int ev6_process_logout_frame(struct el_common *, int);
-extern void ev6_machine_check(u64, u64);
+extern void ev6_machine_check(unsigned long, unsigned long);
/*
* err_marvel.c
*/
-extern void marvel_machine_check(u64, u64);
+extern void marvel_machine_check(unsigned long, unsigned long);
extern void marvel_register_error_handlers(void);
/*
* err_titan.c
*/
extern int titan_process_logout_frame(struct el_common *, int);
-extern void titan_machine_check(u64, u64);
+extern void titan_machine_check(unsigned long, unsigned long);
extern void titan_register_error_handlers(void);
extern int privateer_process_logout_frame(struct el_common *, int);
-extern void privateer_machine_check(u64, u64);
+extern void privateer_machine_check(unsigned long, unsigned long);
diff --git a/arch/alpha/kernel/err_marvel.c b/arch/alpha/kernel/err_marvel.c
index 6bfd243efba3..52a79dfc13c6 100644
--- a/arch/alpha/kernel/err_marvel.c
+++ b/arch/alpha/kernel/err_marvel.c
@@ -1042,7 +1042,7 @@ marvel_process_logout_frame(struct ev7_lf_subpackets *lf_subpackets, int print)
}
void
-marvel_machine_check(u64 vector, u64 la_ptr)
+marvel_machine_check(unsigned long vector, unsigned long la_ptr)
{
struct el_subpacket *el_ptr = (struct el_subpacket *)la_ptr;
int (*process_frame)(struct ev7_lf_subpackets *, int) = NULL;
diff --git a/arch/alpha/kernel/err_titan.c b/arch/alpha/kernel/err_titan.c
index c7e28a88d6e3..f7ed97ce0dfd 100644
--- a/arch/alpha/kernel/err_titan.c
+++ b/arch/alpha/kernel/err_titan.c
@@ -380,7 +380,7 @@ titan_process_logout_frame(struct el_common *mchk_header, int print)
}
void
-titan_machine_check(u64 vector, u64 la_ptr)
+titan_machine_check(unsigned long vector, unsigned long la_ptr)
{
struct el_common *mchk_header = (struct el_common *)la_ptr;
struct el_TITAN_sysdata_mcheck *tmchk =
@@ -702,7 +702,7 @@ privateer_process_logout_frame(struct el_common *mchk_header, int print)
}
void
-privateer_machine_check(u64 vector, u64 la_ptr)
+privateer_machine_check(unsigned long vector, unsigned long la_ptr)
{
struct el_common *mchk_header = (struct el_common *)la_ptr;
struct el_TITAN_sysdata_mcheck *tmchk =
diff --git a/arch/alpha/kernel/head.S b/arch/alpha/kernel/head.S
index 7ac1f1372c36..4bdd1d2ff353 100644
--- a/arch/alpha/kernel/head.S
+++ b/arch/alpha/kernel/head.S
@@ -7,10 +7,11 @@
* the kernel global pointer and jump to the kernel entry-point.
*/
+#include <linux/init.h>
#include <asm/system.h>
#include <asm/asm-offsets.h>
-.section .text.head, "ax"
+__HEAD
.globl swapper_pg_dir
.globl _stext
swapper_pg_dir=SWAPPER_PGD
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 42ee05981e71..9a3334ae282e 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -371,8 +371,6 @@ SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, char __user *, path,
int retval = -EINVAL;
char *name;
- lock_kernel();
-
name = getname(path);
retval = PTR_ERR(name);
if (IS_ERR(name))
@@ -392,7 +390,6 @@ SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, char __user *, path,
}
putname(name);
out:
- unlock_kernel();
return retval;
}
diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h
index 567f2598d090..3d2627ec9860 100644
--- a/arch/alpha/kernel/proto.h
+++ b/arch/alpha/kernel/proto.h
@@ -36,7 +36,6 @@ extern void cia_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
extern struct pci_ops irongate_pci_ops;
extern int irongate_pci_clr_err(void);
extern void irongate_init_arch(void);
-extern void irongate_machine_check(u64, u64);
#define irongate_pci_tbi ((void *)0)
/* core_lca.c */
@@ -49,7 +48,7 @@ extern void lca_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
extern struct pci_ops marvel_pci_ops;
extern void marvel_init_arch(void);
extern void marvel_kill_arch(int);
-extern void marvel_machine_check(u64, u64);
+extern void marvel_machine_check(unsigned long, unsigned long);
extern void marvel_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
extern int marvel_pa_to_nid(unsigned long);
extern int marvel_cpuid_to_nid(int);
@@ -86,7 +85,7 @@ extern void t2_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
extern struct pci_ops titan_pci_ops;
extern void titan_init_arch(void);
extern void titan_kill_arch(int);
-extern void titan_machine_check(u64, u64);
+extern void titan_machine_check(unsigned long, unsigned long);
extern void titan_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
extern struct _alpha_agp_info *titan_agp_info(void);
diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c
index 9c9d1fd4155f..5bd5259324b7 100644
--- a/arch/alpha/kernel/sys_dp264.c
+++ b/arch/alpha/kernel/sys_dp264.c
@@ -176,22 +176,26 @@ cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity)
}
}
-static void
+static int
dp264_set_affinity(unsigned int irq, const struct cpumask *affinity)
{
spin_lock(&dp264_irq_lock);
cpu_set_irq_affinity(irq, *affinity);
tsunami_update_irq_hw(cached_irq_mask);
spin_unlock(&dp264_irq_lock);
+
+ return 0;
}
-static void
+static int
clipper_set_affinity(unsigned int irq, const struct cpumask *affinity)
{
spin_lock(&dp264_irq_lock);
cpu_set_irq_affinity(irq - 16, *affinity);
tsunami_update_irq_hw(cached_irq_mask);
spin_unlock(&dp264_irq_lock);
+
+ return 0;
}
static struct hw_interrupt_type dp264_irq_type = {
diff --git a/arch/alpha/kernel/sys_titan.c b/arch/alpha/kernel/sys_titan.c
index 27f840a4ad3d..8dd239ebdb9e 100644
--- a/arch/alpha/kernel/sys_titan.c
+++ b/arch/alpha/kernel/sys_titan.c
@@ -157,13 +157,15 @@ titan_cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity)
}
-static void
+static int
titan_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
{
spin_lock(&titan_irq_lock);
titan_cpu_set_irq_affinity(irq - 16, *affinity);
titan_update_irq_hw(titan_cached_irq_mask);
spin_unlock(&titan_irq_lock);
+
+ return 0;
}
static void
diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S
index ef37fc1acaea..b9d6568e5f7f 100644
--- a/arch/alpha/kernel/vmlinux.lds.S
+++ b/arch/alpha/kernel/vmlinux.lds.S
@@ -16,7 +16,7 @@ SECTIONS
_text = .; /* Text and read-only data */
.text : {
- *(.text.head)
+ HEAD_TEXT
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
diff --git a/arch/alpha/mm/extable.c b/arch/alpha/mm/extable.c
index dc7aeda15773..62dc379d301a 100644
--- a/arch/alpha/mm/extable.c
+++ b/arch/alpha/mm/extable.c
@@ -3,11 +3,49 @@
*/
#include <linux/module.h>
+#include <linux/sort.h>
#include <asm/uaccess.h>
+static inline unsigned long ex_to_addr(const struct exception_table_entry *x)
+{
+ return (unsigned long)&x->insn + x->insn;
+}
+
+static void swap_ex(void *a, void *b, int size)
+{
+ struct exception_table_entry *ex_a = a, *ex_b = b;
+ unsigned long addr_a = ex_to_addr(ex_a), addr_b = ex_to_addr(ex_b);
+ unsigned int t = ex_a->fixup.unit;
+
+ ex_a->fixup.unit = ex_b->fixup.unit;
+ ex_b->fixup.unit = t;
+ ex_a->insn = (int)(addr_b - (unsigned long)&ex_a->insn);
+ ex_b->insn = (int)(addr_a - (unsigned long)&ex_b->insn);
+}
+
+/*
+ * The exception table needs to be sorted so that the binary
+ * search that we use to find entries in it works properly.
+ * This is used both for the kernel exception table and for
+ * the exception tables of modules that get loaded.
+ */
+static int cmp_ex(const void *a, const void *b)
+{
+ const struct exception_table_entry *x = a, *y = b;
+
+ /* avoid overflow */
+ if (ex_to_addr(x) > ex_to_addr(y))
+ return 1;
+ if (ex_to_addr(x) < ex_to_addr(y))
+ return -1;
+ return 0;
+}
+
void sort_extable(struct exception_table_entry *start,
struct exception_table_entry *finish)
{
+ sort(start, finish - start, sizeof(struct exception_table_entry),
+ cmp_ex, swap_ex);
}
const struct exception_table_entry *
@@ -20,7 +58,7 @@ search_extable(const struct exception_table_entry *first,
unsigned long mid_value;
mid = (last - first) / 2 + first;
- mid_value = (unsigned long)&mid->insn + mid->insn;
+ mid_value = ex_to_addr(mid);
if (mid_value == value)
return mid;
else if (mid_value < value)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index e02b893fb909..5b1434bbd5d7 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -253,6 +253,14 @@ config ARCH_CLPS711X
help
Support for Cirrus Logic 711x/721x based boards.
+config ARCH_GEMINI
+ bool "Cortina Systems Gemini"
+ select CPU_FA526
+ select GENERIC_GPIO
+ select ARCH_REQUIRE_GPIOLIB
+ help
+ Support for the Cortina Systems Gemini family SoCs
+
config ARCH_EBSA110
bool "EBSA-110"
select CPU_SA110
@@ -276,14 +284,6 @@ config ARCH_EP93XX
help
This enables support for the Cirrus EP93xx series of CPUs.
-config ARCH_GEMINI
- bool "Cortina Systems Gemini"
- select CPU_FA526
- select GENERIC_GPIO
- select ARCH_REQUIRE_GPIOLIB
- help
- Support for the Cortina Systems Gemini family SoCs
-
config ARCH_FOOTBRIDGE
bool "FootBridge"
select CPU_SA110
@@ -292,6 +292,30 @@ config ARCH_FOOTBRIDGE
Support for systems based on the DC21285 companion chip
("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
+config ARCH_MXC
+ bool "Freescale MXC/iMX-based"
+ select GENERIC_TIME
+ select GENERIC_CLOCKEVENTS
+ select ARCH_MTD_XIP
+ select GENERIC_GPIO
+ select ARCH_REQUIRE_GPIOLIB
+ select HAVE_CLK
+ help
+ Support for Freescale MXC/iMX-based family of processors
+
+config ARCH_STMP3XXX
+ bool "Freescale STMP3xxx"
+ select CPU_ARM926T
+ select HAVE_CLK
+ select COMMON_CLKDEV
+ select ARCH_REQUIRE_GPIOLIB
+ select GENERIC_TIME
+ select GENERIC_CLOCKEVENTS
+ select GENERIC_GPIO
+ select USB_ARCH_HAS_EHCI
+ help
+ Support for systems based on the Freescale 3xxx CPUs.
+
config ARCH_NETX
bool "Hilscher NetX based"
select CPU_ARM926T
@@ -404,28 +428,6 @@ config ARCH_KIRKWOOD
Support for the following Marvell Kirkwood series SoCs:
88F6180, 88F6192 and 88F6281.
-config ARCH_KS8695
- bool "Micrel/Kendin KS8695"
- select CPU_ARM922T
- select GENERIC_GPIO
- select ARCH_REQUIRE_GPIOLIB
- help
- Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based
- System-on-Chip devices.
-
-config ARCH_NS9XXX
- bool "NetSilicon NS9xxx"
- select CPU_ARM926T
- select GENERIC_GPIO
- select GENERIC_TIME
- select GENERIC_CLOCKEVENTS
- select HAVE_CLK
- help
- Say Y here if you intend to run this kernel on a NetSilicon NS9xxx
- System.
-
- <http://www.digi.com/products/microprocessors/index.jsp>
-
config ARCH_LOKI
bool "Marvell Loki (88RC8480)"
select CPU_FEROCEON
@@ -447,16 +449,6 @@ config ARCH_MV78XX0
Support for the following Marvell MV78xx0 series SoCs:
MV781x0, MV782x0.
-config ARCH_MXC
- bool "Freescale MXC/iMX-based"
- select GENERIC_TIME
- select GENERIC_CLOCKEVENTS
- select ARCH_MTD_XIP
- select GENERIC_GPIO
- select ARCH_REQUIRE_GPIOLIB
- help
- Support for Freescale MXC/iMX-based family of processors
-
config ARCH_ORION5X
bool "Marvell Orion"
depends on MMU
@@ -471,6 +463,49 @@ config ARCH_ORION5X
Orion-1 (5181), Orion-VoIP (5181L), Orion-NAS (5182),
Orion-2 (5281), Orion-1-90 (6183).
+config ARCH_MMP
+ bool "Marvell PXA168/910"
+ depends on MMU
+ select GENERIC_GPIO
+ select ARCH_REQUIRE_GPIOLIB
+ select HAVE_CLK
+ select COMMON_CLKDEV
+ select GENERIC_TIME
+ select GENERIC_CLOCKEVENTS
+ select TICK_ONESHOT
+ select PLAT_PXA
+ help
+ Support for Marvell's PXA168/910 processor line.
+
+config ARCH_KS8695
+ bool "Micrel/Kendin KS8695"
+ select CPU_ARM922T
+ select GENERIC_GPIO
+ select ARCH_REQUIRE_GPIOLIB
+ help
+ Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based
+ System-on-Chip devices.
+
+config ARCH_NS9XXX
+ bool "NetSilicon NS9xxx"
+ select CPU_ARM926T
+ select GENERIC_GPIO
+ select GENERIC_TIME
+ select GENERIC_CLOCKEVENTS
+ select HAVE_CLK
+ help
+ Say Y here if you intend to run this kernel on a NetSilicon NS9xxx
+ System.
+
+ <http://www.digi.com/products/microprocessors/index.jsp>
+
+config ARCH_W90X900
+ bool "Nuvoton W90X900 CPU"
+ select CPU_ARM926T
+ help
+ Support for Nuvoton (Winbond logic dept.) ARM9 processor,You
+ can login www.mcuos.com or www.nuvoton.com to know more.
+
config ARCH_PNX4008
bool "Philips Nexperia PNX4008 Mobile"
select CPU_ARM926T
@@ -486,8 +521,6 @@ config ARCH_PXA
select HAVE_CLK
select COMMON_CLKDEV
select ARCH_REQUIRE_GPIOLIB
- select HAVE_CLK
- select COMMON_CLKDEV
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
select TICK_ONESHOT
@@ -495,19 +528,16 @@ config ARCH_PXA
help
Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
-config ARCH_MMP
- bool "Marvell PXA168/910"
- depends on MMU
- select GENERIC_GPIO
- select ARCH_REQUIRE_GPIOLIB
- select HAVE_CLK
- select COMMON_CLKDEV
+config ARCH_MSM
+ bool "Qualcomm MSM"
+ select CPU_V6
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
- select TICK_ONESHOT
- select PLAT_PXA
help
- Support for Marvell's PXA168/910 processor line.
+ Support for Qualcomm MSM7K based systems. This runs on the ARM11
+ apps processor of the MSM7K and depends on a shared memory
+ interface to the ARM9 modem processor which runs the baseband stack
+ and controls some vital subsystems (clock and power control, etc).
config ARCH_RPC
bool "RiscPC"
@@ -576,6 +606,20 @@ config ARCH_LH7A40X
core with a wide array of integrated devices for
hand-held and low-power applications.
+config ARCH_U300
+ bool "ST-Ericsson U300 Series"
+ depends on MMU
+ select CPU_ARM926T
+ select ARM_AMBA
+ select ARM_VIC
+ select GENERIC_TIME
+ select GENERIC_CLOCKEVENTS
+ select HAVE_CLK
+ select COMMON_CLKDEV
+ select GENERIC_GPIO
+ help
+ Support for ST-Ericsson U300 series mobile platforms.
+
config ARCH_DAVINCI
bool "TI DaVinci"
select CPU_ARM926T
@@ -585,6 +629,8 @@ config ARCH_DAVINCI
select ARCH_REQUIRE_GPIOLIB
select HAVE_CLK
select ZONE_DMA
+ select HAVE_IDE
+ select COMMON_CLKDEV
help
Support for TI's DaVinci platform.
@@ -598,24 +644,6 @@ config ARCH_OMAP
help
Support for TI's OMAP platform (OMAP1 and OMAP2).
-config ARCH_MSM
- bool "Qualcomm MSM"
- select CPU_V6
- select GENERIC_TIME
- select GENERIC_CLOCKEVENTS
- help
- Support for Qualcomm MSM7K based systems. This runs on the ARM11
- apps processor of the MSM7K and depends on a shared memory
- interface to the ARM9 modem processor which runs the baseband stack
- and controls some vital subsystems (clock and power control, etc).
-
-config ARCH_W90X900
- bool "Nuvoton W90X900 CPU"
- select CPU_ARM926T
- help
- Support for Nuvoton (Winbond logic dept.) ARM9 processor,You
- can login www.mcuos.com or www.nuvoton.com to know more.
-
endchoice
source "arch/arm/mach-clps711x/Kconfig"
@@ -679,6 +707,8 @@ source "arch/arm/mach-s3c6400/Kconfig"
source "arch/arm/mach-s3c6410/Kconfig"
endif
+source "arch/arm/plat-stmp3xxx/Kconfig"
+
source "arch/arm/mach-lh7a40x/Kconfig"
source "arch/arm/mach-imx/Kconfig"
@@ -705,6 +735,8 @@ source "arch/arm/mach-ks8695/Kconfig"
source "arch/arm/mach-msm/Kconfig"
+source "arch/arm/mach-u300/Kconfig"
+
source "arch/arm/mach-w90x900/Kconfig"
# Definitions to make life easier
@@ -740,6 +772,56 @@ if !MMU
source "arch/arm/Kconfig-nommu"
endif
+config ARM_ERRATA_411920
+ bool "ARM errata: Invalidation of the Instruction Cache operation can fail"
+ depends on CPU_V6 && !SMP
+ help
+ Invalidation of the Instruction Cache operation can
+ fail. This erratum is present in 1136 (before r1p4), 1156 and 1176.
+ It does not affect the MPCore. This option enables the ARM Ltd.
+ recommended workaround.
+
+config ARM_ERRATA_430973
+ bool "ARM errata: Stale prediction on replaced interworking branch"
+ depends on CPU_V7
+ help
+ This option enables the workaround for the 430973 Cortex-A8
+ (r1p0..r1p2) erratum. If a code sequence containing an ARM/Thumb
+ interworking branch is replaced with another code sequence at the
+ same virtual address, whether due to self-modifying code or virtual
+ to physical address re-mapping, Cortex-A8 does not recover from the
+ stale interworking branch prediction. This results in Cortex-A8
+ executing the new code sequence in the incorrect ARM or Thumb state.
+ The workaround enables the BTB/BTAC operations by setting ACTLR.IBE
+ and also flushes the branch target cache at every context switch.
+ Note that setting specific bits in the ACTLR register may not be
+ available in non-secure mode.
+
+config ARM_ERRATA_458693
+ bool "ARM errata: Processor deadlock when a false hazard is created"
+ depends on CPU_V7
+ help
+ This option enables the workaround for the 458693 Cortex-A8 (r2p0)
+ erratum. For very specific sequences of memory operations, it is
+ possible for a hazard condition intended for a cache line to instead
+ be incorrectly associated with a different cache line. This false
+ hazard might then cause a processor deadlock. The workaround enables
+ the L1 caching of the NEON accesses and disables the PLD instruction
+ in the ACTLR register. Note that setting specific bits in the ACTLR
+ register may not be available in non-secure mode.
+
+config ARM_ERRATA_460075
+ bool "ARM errata: Data written to the L2 cache can be overwritten with stale data"
+ depends on CPU_V7
+ help
+ This option enables the workaround for the 460075 Cortex-A8 (r2p0)
+ erratum. Any asynchronous access to the L2 cache may encounter a
+ situation in which recent store transactions to the L2 cache are lost
+ and overwritten with stale memory contents from external memory. The
+ workaround disables the write-allocate mode for the L2 cache via the
+ ACTLR register. Note that setting specific bits in the ACTLR register
+ may not be available in non-secure mode.
+
endmenu
source "arch/arm/common/Kconfig"
@@ -1171,12 +1253,6 @@ config CPU_FREQ_IMX
If in doubt, say N.
-config CPU_FREQ_PXA
- bool
- depends on CPU_FREQ && ARCH_PXA && PXA25x
- default y
- select CPU_FREQ_DEFAULT_GOV_USERSPACE
-
endif
source "drivers/cpuidle/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index e84729bf13d4..a4f86e3d4cf0 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -99,64 +99,73 @@ CHECKFLAGS += -D__arm__
#Default value
head-y := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
textofs-y := 0x00008000
-
- machine-$(CONFIG_ARCH_RPC) := rpc
- machine-$(CONFIG_ARCH_EBSA110) := ebsa110
- machine-$(CONFIG_FOOTBRIDGE) := footbridge
- machine-$(CONFIG_ARCH_SHARK) := shark
- machine-$(CONFIG_ARCH_SA1100) := sa1100
-ifeq ($(CONFIG_ARCH_SA1100),y)
+textofs-$(CONFIG_ARCH_CLPS711X) := 0x00028000
# SA1111 DMA bug: we don't want the kernel to live in precious DMA-able memory
- textofs-$(CONFIG_SA1111) := 0x00208000
+ifeq ($(CONFIG_ARCH_SA1100),y)
+textofs-$(CONFIG_SA1111) := 0x00208000
endif
- machine-$(CONFIG_ARCH_PXA) := pxa
- machine-$(CONFIG_ARCH_MMP) := mmp
- plat-$(CONFIG_PLAT_PXA) := pxa
- machine-$(CONFIG_ARCH_L7200) := l7200
- machine-$(CONFIG_ARCH_INTEGRATOR) := integrator
- machine-$(CONFIG_ARCH_GEMINI) := gemini
- textofs-$(CONFIG_ARCH_CLPS711X) := 0x00028000
- machine-$(CONFIG_ARCH_CLPS711X) := clps711x
- machine-$(CONFIG_ARCH_IOP32X) := iop32x
- machine-$(CONFIG_ARCH_IOP33X) := iop33x
- machine-$(CONFIG_ARCH_IOP13XX) := iop13xx
- plat-$(CONFIG_PLAT_IOP) := iop
- machine-$(CONFIG_ARCH_IXP4XX) := ixp4xx
- machine-$(CONFIG_ARCH_IXP2000) := ixp2000
- machine-$(CONFIG_ARCH_IXP23XX) := ixp23xx
- machine-$(CONFIG_ARCH_OMAP1) := omap1
- machine-$(CONFIG_ARCH_OMAP2) := omap2
- machine-$(CONFIG_ARCH_OMAP3) := omap2
- plat-$(CONFIG_ARCH_OMAP) := omap
- machine-$(CONFIG_ARCH_S3C2410) := s3c2410 s3c2400 s3c2412 s3c2440 s3c2442 s3c2443
- machine-$(CONFIG_ARCH_S3C24A0) := s3c24a0
- plat-$(CONFIG_PLAT_S3C24XX) := s3c24xx s3c
- machine-$(CONFIG_ARCH_S3C64XX) := s3c6400 s3c6410
- plat-$(CONFIG_PLAT_S3C64XX) := s3c64xx s3c
- machine-$(CONFIG_ARCH_LH7A40X) := lh7a40x
- machine-$(CONFIG_ARCH_VERSATILE) := versatile
- machine-$(CONFIG_ARCH_IMX) := imx
- machine-$(CONFIG_ARCH_H720X) := h720x
- machine-$(CONFIG_ARCH_AAEC2000) := aaec2000
- machine-$(CONFIG_ARCH_REALVIEW) := realview
- machine-$(CONFIG_ARCH_AT91) := at91
- machine-$(CONFIG_ARCH_EP93XX) := ep93xx
- machine-$(CONFIG_ARCH_PNX4008) := pnx4008
- machine-$(CONFIG_ARCH_NETX) := netx
- machine-$(CONFIG_ARCH_NS9XXX) := ns9xxx
- machine-$(CONFIG_ARCH_DAVINCI) := davinci
- machine-$(CONFIG_ARCH_KIRKWOOD) := kirkwood
- machine-$(CONFIG_ARCH_KS8695) := ks8695
- plat-$(CONFIG_ARCH_MXC) := mxc
- machine-$(CONFIG_ARCH_MX2) := mx2
- machine-$(CONFIG_ARCH_MX3) := mx3
- machine-$(CONFIG_ARCH_MX1) := mx1
- machine-$(CONFIG_ARCH_ORION5X) := orion5x
- plat-$(CONFIG_PLAT_ORION) := orion
- machine-$(CONFIG_ARCH_MSM) := msm
- machine-$(CONFIG_ARCH_LOKI) := loki
- machine-$(CONFIG_ARCH_MV78XX0) := mv78xx0
- machine-$(CONFIG_ARCH_W90X900) := w90x900
+
+# Machine directory name. This list is sorted alphanumerically
+# by CONFIG_* macro name.
+machine-$(CONFIG_ARCH_AAEC2000) := aaec2000
+machine-$(CONFIG_ARCH_AT91) := at91
+machine-$(CONFIG_ARCH_CLPS711X) := clps711x
+machine-$(CONFIG_ARCH_DAVINCI) := davinci
+machine-$(CONFIG_ARCH_EBSA110) := ebsa110
+machine-$(CONFIG_ARCH_EP93XX) := ep93xx
+machine-$(CONFIG_ARCH_GEMINI) := gemini
+machine-$(CONFIG_ARCH_H720X) := h720x
+machine-$(CONFIG_ARCH_IMX) := imx
+machine-$(CONFIG_ARCH_INTEGRATOR) := integrator
+machine-$(CONFIG_ARCH_IOP13XX) := iop13xx
+machine-$(CONFIG_ARCH_IOP32X) := iop32x
+machine-$(CONFIG_ARCH_IOP33X) := iop33x
+machine-$(CONFIG_ARCH_IXP2000) := ixp2000
+machine-$(CONFIG_ARCH_IXP23XX) := ixp23xx
+machine-$(CONFIG_ARCH_IXP4XX) := ixp4xx
+machine-$(CONFIG_ARCH_KIRKWOOD) := kirkwood
+machine-$(CONFIG_ARCH_KS8695) := ks8695
+machine-$(CONFIG_ARCH_L7200) := l7200
+machine-$(CONFIG_ARCH_LH7A40X) := lh7a40x
+machine-$(CONFIG_ARCH_LOKI) := loki
+machine-$(CONFIG_ARCH_MMP) := mmp
+machine-$(CONFIG_ARCH_MSM) := msm
+machine-$(CONFIG_ARCH_MV78XX0) := mv78xx0
+machine-$(CONFIG_ARCH_MX1) := mx1
+machine-$(CONFIG_ARCH_MX2) := mx2
+machine-$(CONFIG_ARCH_MX3) := mx3
+machine-$(CONFIG_ARCH_NETX) := netx
+machine-$(CONFIG_ARCH_NS9XXX) := ns9xxx
+machine-$(CONFIG_ARCH_OMAP1) := omap1
+machine-$(CONFIG_ARCH_OMAP2) := omap2
+machine-$(CONFIG_ARCH_OMAP3) := omap2
+machine-$(CONFIG_ARCH_ORION5X) := orion5x
+machine-$(CONFIG_ARCH_PNX4008) := pnx4008
+machine-$(CONFIG_ARCH_PXA) := pxa
+machine-$(CONFIG_ARCH_REALVIEW) := realview
+machine-$(CONFIG_ARCH_RPC) := rpc
+machine-$(CONFIG_ARCH_S3C2410) := s3c2410 s3c2400 s3c2412 s3c2440 s3c2442 s3c2443
+machine-$(CONFIG_ARCH_S3C24A0) := s3c24a0
+machine-$(CONFIG_ARCH_S3C64XX) := s3c6400 s3c6410
+machine-$(CONFIG_ARCH_SA1100) := sa1100
+machine-$(CONFIG_ARCH_SHARK) := shark
+machine-$(CONFIG_ARCH_STMP378X) := stmp378x
+machine-$(CONFIG_ARCH_STMP37XX) := stmp37xx
+machine-$(CONFIG_ARCH_U300) := u300
+machine-$(CONFIG_ARCH_VERSATILE) := versatile
+machine-$(CONFIG_ARCH_W90X900) := w90x900
+machine-$(CONFIG_FOOTBRIDGE) := footbridge
+
+# Platform directory name. This list is sorted alphanumerically
+# by CONFIG_* macro name.
+plat-$(CONFIG_ARCH_MXC) := mxc
+plat-$(CONFIG_ARCH_OMAP) := omap
+plat-$(CONFIG_PLAT_IOP) := iop
+plat-$(CONFIG_PLAT_ORION) := orion
+plat-$(CONFIG_PLAT_PXA) := pxa
+plat-$(CONFIG_PLAT_S3C24XX) := s3c24xx s3c
+plat-$(CONFIG_PLAT_S3C64XX) := s3c64xx s3c
+plat-$(CONFIG_ARCH_STMP3XXX) := stmp3xxx
ifeq ($(CONFIG_ARCH_EBSA110),y)
# This is what happens if you forget the IOCS16 line.
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index a2cd9beaf37d..38518d450bc0 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -4,6 +4,13 @@ config ARM_GIC
config ARM_VIC
bool
+config ARM_VIC_NR
+ int
+ default 2
+ help
+ The maximum number of VICs available in the system, for
+ power management.
+
config ICST525
bool
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index c6884ba1d5ed..90f6b7f52d48 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -109,7 +109,7 @@ static void gic_unmask_irq(unsigned int irq)
}
#ifdef CONFIG_SMP
-static void gic_set_cpu(unsigned int irq, const struct cpumask *mask_val)
+static int gic_set_cpu(unsigned int irq, const struct cpumask *mask_val)
{
void __iomem *reg = gic_dist_base(irq) + GIC_DIST_TARGET + (gic_irq(irq) & ~3);
unsigned int shift = (irq % 4) * 8;
@@ -122,6 +122,8 @@ static void gic_set_cpu(unsigned int irq, const struct cpumask *mask_val)
val |= 1 << (cpu + shift);
writel(val, reg);
spin_unlock(&irq_controller_lock);
+
+ return 0;
}
#endif
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
index ecf0bfbab107..887c6eb3a18a 100644
--- a/arch/arm/common/vic.c
+++ b/arch/arm/common/vic.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/io.h>
+#include <linux/sysdev.h>
#include <asm/mach/irq.h>
#include <asm/hardware/vic.h>
@@ -39,11 +40,219 @@ static void vic_unmask_irq(unsigned int irq)
writel(1 << irq, base + VIC_INT_ENABLE);
}
+/**
+ * vic_init2 - common initialisation code
+ * @base: Base of the VIC.
+ *
+ * Common initialisation code for registeration
+ * and resume.
+*/
+static void vic_init2(void __iomem *base)
+{
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
+ writel(VIC_VECT_CNTL_ENABLE | i, reg);
+ }
+
+ writel(32, base + VIC_PL190_DEF_VECT_ADDR);
+}
+
+#if defined(CONFIG_PM)
+/**
+ * struct vic_device - VIC PM device
+ * @sysdev: The system device which is registered.
+ * @irq: The IRQ number for the base of the VIC.
+ * @base: The register base for the VIC.
+ * @resume_sources: A bitmask of interrupts for resume.
+ * @resume_irqs: The IRQs enabled for resume.
+ * @int_select: Save for VIC_INT_SELECT.
+ * @int_enable: Save for VIC_INT_ENABLE.
+ * @soft_int: Save for VIC_INT_SOFT.
+ * @protect: Save for VIC_PROTECT.
+ */
+struct vic_device {
+ struct sys_device sysdev;
+
+ void __iomem *base;
+ int irq;
+ u32 resume_sources;
+ u32 resume_irqs;
+ u32 int_select;
+ u32 int_enable;
+ u32 soft_int;
+ u32 protect;
+};
+
+/* we cannot allocate memory when VICs are initially registered */
+static struct vic_device vic_devices[CONFIG_ARM_VIC_NR];
+
+static inline struct vic_device *to_vic(struct sys_device *sys)
+{
+ return container_of(sys, struct vic_device, sysdev);
+}
+
+static int vic_id;
+
+static int vic_class_resume(struct sys_device *dev)
+{
+ struct vic_device *vic = to_vic(dev);
+ void __iomem *base = vic->base;
+
+ printk(KERN_DEBUG "%s: resuming vic at %p\n", __func__, base);
+
+ /* re-initialise static settings */
+ vic_init2(base);
+
+ writel(vic->int_select, base + VIC_INT_SELECT);
+ writel(vic->protect, base + VIC_PROTECT);
+
+ /* set the enabled ints and then clear the non-enabled */
+ writel(vic->int_enable, base + VIC_INT_ENABLE);
+ writel(~vic->int_enable, base + VIC_INT_ENABLE_CLEAR);
+
+ /* and the same for the soft-int register */
+
+ writel(vic->soft_int, base + VIC_INT_SOFT);
+ writel(~vic->soft_int, base + VIC_INT_SOFT_CLEAR);
+
+ return 0;
+}
+
+static int vic_class_suspend(struct sys_device *dev, pm_message_t state)
+{
+ struct vic_device *vic = to_vic(dev);
+ void __iomem *base = vic->base;
+
+ printk(KERN_DEBUG "%s: suspending vic at %p\n", __func__, base);
+
+ vic->int_select = readl(base + VIC_INT_SELECT);
+ vic->int_enable = readl(base + VIC_INT_ENABLE);
+ vic->soft_int = readl(base + VIC_INT_SOFT);
+ vic->protect = readl(base + VIC_PROTECT);
+
+ /* set the interrupts (if any) that are used for
+ * resuming the system */
+
+ writel(vic->resume_irqs, base + VIC_INT_ENABLE);
+ writel(~vic->resume_irqs, base + VIC_INT_ENABLE_CLEAR);
+
+ return 0;
+}
+
+struct sysdev_class vic_class = {
+ .name = "vic",
+ .suspend = vic_class_suspend,
+ .resume = vic_class_resume,
+};
+
+/**
+ * vic_pm_register - Register a VIC for later power management control
+ * @base: The base address of the VIC.
+ * @irq: The base IRQ for the VIC.
+ * @resume_sources: bitmask of interrupts allowed for resume sources.
+ *
+ * Register the VIC with the system device tree so that it can be notified
+ * of suspend and resume requests and ensure that the correct actions are
+ * taken to re-instate the settings on resume.
+ */
+static void __init vic_pm_register(void __iomem *base, unsigned int irq, u32 resume_sources)
+{
+ struct vic_device *v;
+
+ if (vic_id >= ARRAY_SIZE(vic_devices))
+ printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__);
+ else {
+ v = &vic_devices[vic_id];
+ v->base = base;
+ v->resume_sources = resume_sources;
+ v->irq = irq;
+ vic_id++;
+ }
+}
+
+/**
+ * vic_pm_init - initicall to register VIC pm
+ *
+ * This is called via late_initcall() to register
+ * the resources for the VICs due to the early
+ * nature of the VIC's registration.
+*/
+static int __init vic_pm_init(void)
+{
+ struct vic_device *dev = vic_devices;
+ int err;
+ int id;
+
+ if (vic_id == 0)
+ return 0;
+
+ err = sysdev_class_register(&vic_class);
+ if (err) {
+ printk(KERN_ERR "%s: cannot register class\n", __func__);
+ return err;
+ }
+
+ for (id = 0; id < vic_id; id++, dev++) {
+ dev->sysdev.id = id;
+ dev->sysdev.cls = &vic_class;
+
+ err = sysdev_register(&dev->sysdev);
+ if (err) {
+ printk(KERN_ERR "%s: failed to register device\n",
+ __func__);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+late_initcall(vic_pm_init);
+
+static struct vic_device *vic_from_irq(unsigned int irq)
+{
+ struct vic_device *v = vic_devices;
+ unsigned int base_irq = irq & ~31;
+ int id;
+
+ for (id = 0; id < vic_id; id++, v++) {
+ if (v->irq == base_irq)
+ return v;
+ }
+
+ return NULL;
+}
+
+static int vic_set_wake(unsigned int irq, unsigned int on)
+{
+ struct vic_device *v = vic_from_irq(irq);
+ unsigned int off = irq & 31;
+
+ if (!v)
+ return -EINVAL;
+
+ if (on)
+ v->resume_irqs |= 1 << off;
+ else
+ v->resume_irqs &= ~(1 << off);
+
+ return 0;
+}
+
+#else
+static inline void vic_pm_register(void __iomem *base, unsigned int irq, u32 arg1) { }
+
+#define vic_set_wake NULL
+#endif /* CONFIG_PM */
+
static struct irq_chip vic_chip = {
.name = "VIC",
.ack = vic_mask_irq,
.mask = vic_mask_irq,
.unmask = vic_unmask_irq,
+ .set_wake = vic_set_wake,
};
/**
@@ -51,9 +260,10 @@ static struct irq_chip vic_chip = {
* @base: iomem base address
* @irq_start: starting interrupt number, must be muliple of 32
* @vic_sources: bitmask of interrupt sources to allow
+ * @resume_sources: bitmask of interrupt sources to allow for resume
*/
void __init vic_init(void __iomem *base, unsigned int irq_start,
- u32 vic_sources)
+ u32 vic_sources, u32 resume_sources)
{
unsigned int i;
@@ -77,22 +287,18 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,
writel(value, base + VIC_PL190_VECT_ADDR);
}
- for (i = 0; i < 16; i++) {
- void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
- writel(VIC_VECT_CNTL_ENABLE | i, reg);
- }
-
- writel(32, base + VIC_PL190_DEF_VECT_ADDR);
+ vic_init2(base);
for (i = 0; i < 32; i++) {
- unsigned int irq = irq_start + i;
-
- set_irq_chip(irq, &vic_chip);
- set_irq_chip_data(irq, base);
-
if (vic_sources & (1 << i)) {
+ unsigned int irq = irq_start + i;
+
+ set_irq_chip(irq, &vic_chip);
+ set_irq_chip_data(irq, base);
set_irq_handler(irq, handle_level_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
}
+
+ vic_pm_register(base, irq_start, resume_sources);
}
diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig
new file mode 100644
index 000000000000..eb2738b5be5f
--- /dev/null
+++ b/arch/arm/configs/davinci_all_defconfig
@@ -0,0 +1,1784 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.30-rc2
+# Wed Apr 15 08:16:53 2009
+#
+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_HAVE_LATENCYTOP_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_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=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_STRIP_ASM_SYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+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_FREEZER is not set
+
+#
+# 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_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_GEMINI 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_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+CONFIG_ARCH_DAVINCI=y
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+
+#
+# TI DaVinci Implementations
+#
+
+#
+# DaVinci Core Type
+#
+CONFIG_ARCH_DAVINCI_DM644x=y
+
+#
+# DaVinci Board Type
+#
+CONFIG_MACH_DAVINCI_EVM=y
+CONFIG_DAVINCI_MUX=y
+CONFIG_DAVINCI_MUX_DEBUG=y
+CONFIG_DAVINCI_MUX_WARNINGS=y
+CONFIG_DAVINCI_RESET_CLOCKS=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_PABRT_NOIFAR=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=y
+# 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
+CONFIG_COMMON_CLKDEV=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=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM 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_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_LEDS=y
+# CONFIG_LEDS_CPU is not set
+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
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+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_XFRM_STATISTICS 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 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 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=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_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG 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 is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+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_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_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
+#
+# CONFIG_IP6_NF_QUEUE is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# 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_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_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
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+# CONFIG_MTD_JEDECPROBE is not set
+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=m
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=m
+# 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=m
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# 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=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_GPIO is not set
+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_ALAUDA is not set
+CONFIG_MTD_NAND_DAVINCI=m
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR 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=m
+# 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
+CONFIG_BLK_DEV_RAM_COUNT=1
+CONFIG_BLK_DEV_RAM_SIZE=32768
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=y
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+CONFIG_IDE=m
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+CONFIG_IDE_XFER_MODE=y
+CONFIG_IDE_TIMINGS=y
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_IDE_GD=m
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_PLATFORM is not set
+CONFIG_BLK_DEV_IDEDMA_SFF=y
+CONFIG_BLK_DEV_PALMCHIP_BK3710=m
+CONFIG_BLK_DEV_IDEDMA=y
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# 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_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_VETH 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=y
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+CONFIG_LSI_ET1011C_PHY=y
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_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
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+# 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=m
+CONFIG_NETCONSOLE=y
+# CONFIG_NETCONSOLE_DYNAMIC is not set
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# 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=m
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVBUG=m
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=m
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_XTKBD=m
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO 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_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+# CONFIG_VT_CONSOLE is not set
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=3
+CONFIG_SERIAL_8250_RUNTIME_UARTS=3
+# 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_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 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
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_DAVINCI=y
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+CONFIG_GPIO_PCF857X=m
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A 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_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 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_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_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_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_DAVINCI_WATCHDOG=m
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_COMMON=y
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=y
+
+#
+# Multimedia drivers
+#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=y
+CONFIG_MEDIA_TUNER_TDA8290=y
+CONFIG_MEDIA_TUNER_TDA9887=y
+CONFIG_MEDIA_TUNER_TEA5761=y
+CONFIG_MEDIA_TUNER_TEA5767=y
+CONFIG_MEDIA_TUNER_MT20XX=y
+CONFIG_MEDIA_TUNER_XC2028=y
+CONFIG_MEDIA_TUNER_XC5000=y
+CONFIG_MEDIA_TUNER_MC44S803=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_SOC_CAMERA is not set
+# CONFIG_V4L_USB_DRIVERS is not set
+# CONFIG_RADIO_ADAPTERS is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# 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_BOOT_VESA_SUPPORT 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
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# 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_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET 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 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
+CONFIG_SOUND=m
+# CONFIG_SOUND_OSS_CORE is not set
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_JACK=y
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_HRTIMER is not set
+# 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
+CONFIG_SND_DRIVERS=y
+# 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
+CONFIG_SND_ARM=y
+CONFIG_SND_USB=y
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+CONFIG_SND_SOC=m
+# CONFIG_SND_DAVINCI_SOC is not set
+CONFIG_SND_SOC_I2C_AND_SPI=m
+# CONFIG_SND_SOC_ALL_CODECS is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=m
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=m
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+# CONFIG_DRAGONRISE_FF is not set
+CONFIG_HID_EZKEY=m
+# CONFIG_HID_KYE is not set
+CONFIG_HID_GYRATION=m
+# CONFIG_HID_KENSINGTON is not set
+CONFIG_HID_LOGITECH=m
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+# CONFIG_HID_NTRIG is not set
+CONFIG_HID_PANTHERLORD=m
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_HID_SUNPLUS=m
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=m
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=m
+CONFIG_USB_MUSB_SOC=y
+
+#
+# DaVinci 35x and 644x USB support
+#
+# CONFIG_USB_MUSB_HOST is not set
+CONFIG_USB_MUSB_PERIPHERAL=y
+# CONFIG_USB_MUSB_OTG is not set
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_MUSB_PIO_ONLY=y
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_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=m
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG is not set
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+# CONFIG_USB_MIDI_GADGET is not set
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=m
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=m
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_GPIO_PLATFORM=y
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_BD2802 is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+# CONFIG_LEDS_TRIGGER_IDE_DISK is not set
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=m
+
+#
+# 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_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
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING 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=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4_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_FILE_LOCKING=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE 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_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=m
+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
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+CONFIG_MINIX_FS=m
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+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_ROOT_NFS=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# 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
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION 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
+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=m
+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=m
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_DEBUG_PREEMPT=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_PI_LIST=y
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+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 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_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=m
+# 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=m
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/arm/configs/imx27ads_defconfig b/arch/arm/configs/imx27ads_defconfig
deleted file mode 100644
index bcd95b8dd2df..000000000000
--- a/arch/arm/configs/imx27ads_defconfig
+++ /dev/null
@@ -1,826 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26-rc6
-# Fri Jun 20 16:29:34 2008
-#
-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_ARCH_SUPPORTS_AOUT=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_LOCK_KERNEL=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_SYSVIPC_SYSCTL=y
-CONFIG_POSIX_MQUEUE=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
-# CONFIG_GROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-# CONFIG_RELAY is not set
-# CONFIG_NAMESPACES 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_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_KALLSYMS=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
-CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
-CONFIG_SHMEM=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
-# CONFIG_SLOB is not set
-# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
-CONFIG_HAVE_OPROFILE=y
-# CONFIG_KPROBES is not set
-CONFIG_HAVE_KPROBES=y
-CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_DMA_ATTRS is not set
-CONFIG_PROC_PAGE_MONITOR=y
-CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-CONFIG_MODULES=y
-# CONFIG_MODULE_FORCE_LOAD is not set
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-# CONFIG_MODVERSIONS 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 is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-# CONFIG_DEFAULT_AS is not set
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-CONFIG_DEFAULT_NOOP=y
-CONFIG_DEFAULT_IOSCHED="noop"
-CONFIG_CLASSIC_RCU=y
-
-#
-# 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=y
-# CONFIG_ARCH_ORION5X 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 is not set
-# CONFIG_ARCH_MSM7X00A is not set
-
-#
-# Boot options
-#
-
-#
-# Power management
-#
-
-#
-# Freescale MXC Implementations
-#
-CONFIG_ARCH_MX2=y
-# CONFIG_ARCH_MX3 is not set
-
-#
-# MX2 family CPU support
-#
-CONFIG_MACH_MX27=y
-
-#
-# MX2 Platforms
-#
-CONFIG_MACH_MX27ADS=y
-# CONFIG_MACH_PCM038 is not set
-
-#
-# Processor Type
-#
-CONFIG_CPU_32=y
-CONFIG_CPU_ARM926T=y
-CONFIG_CPU_32v5=y
-CONFIG_CPU_ABRT_EV5TJ=y
-CONFIG_CPU_PABRT_NOIFAR=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=y
-# 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
-# CONFIG_PCCARD is not set
-
-#
-# Kernel Features
-#
-CONFIG_TICK_ONESHOT=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
-CONFIG_PREEMPT=y
-CONFIG_HZ=100
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT 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_SPARSEMEM_VMEMMAP_ENABLE is not set
-CONFIG_PAGEFLAGS_EXTENDED=y
-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_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 is not set
-CONFIG_ARCH_SUSPEND_POSSIBLE=y
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_UNIX=y
-# 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 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_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 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_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_CAN 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 is not set
-# 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
-# CONFIG_MTD_AR7_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
-# CONFIG_MTD_OOPS 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=y
-CONFIG_MTD_CFI_NOSWAP=y
-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
-# 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 is not set
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_OTP 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
-# CONFIG_MTD_XIP is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x00000000
-CONFIG_MTD_PHYSMAP_LEN=0x0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
-# CONFIG_MTD_ARM_INTEGRATOR is not set
-# 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 is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_CDROM_PKTCDVD is not set
-# CONFIG_ATA_OVER_ETH is not set
-# CONFIG_MISC_DEVICES is not set
-CONFIG_HAVE_IDE=y
-# 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 is not set
-# CONFIG_AX88796 is not set
-# CONFIG_SMC91X is not set
-# 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_FEC_OLD 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_IWLWIFI_LEDS is not set
-# CONFIG_WAN is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP 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_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_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_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-# CONFIG_SERIO is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-CONFIG_DEVKMEM=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_SERIAL_IMX is not set
-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
-# CONFIG_SPI is not set
-CONFIG_HAVE_GPIO_LIB=y
-
-#
-# GPIO Support
-#
-
-#
-# I2C GPIO expanders:
-#
-
-#
-# SPI GPIO expanders:
-#
-# 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
-#
-# CONFIG_MFD_SM501 is not set
-# CONFIG_MFD_ASIC3 is not set
-# CONFIG_HTC_EGPIO is not set
-# CONFIG_HTC_PASIC3 is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
-
-#
-# Graphics support
-#
-# 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
-
-#
-# 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
-# CONFIG_UIO 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_OCFS2_FS is not set
-# CONFIG_DNOTIFY is not set
-# CONFIG_INOTIFY is not set
-# CONFIG_QUOTA 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=y
-# CONFIG_TMPFS_POSIX_ACL 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_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_MINIX_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-CONFIG_NETWORK_FILESYSTEMS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFS_V4 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
-CONFIG_NLS=y
-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=m
-# 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=m
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-# CONFIG_DLM is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_WARN_DEPRECATED=y
-CONFIG_ENABLE_MUST_CHECK=y
-CONFIG_FRAME_WARN=1024
-# 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 is not set
-CONFIG_FRAME_POINTER=y
-# CONFIG_SAMPLES is not set
-# CONFIG_DEBUG_USER is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
-# 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/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig
index c367ae44012e..dcf8153a947d 100644
--- a/arch/arm/configs/kirkwood_defconfig
+++ b/arch/arm/configs/kirkwood_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc5
-# Tue Mar 3 21:45:57 2009
+# Linux kernel version: 2.6.30-rc4
+# Mon May 4 11:58:57 2009
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -66,20 +66,20 @@ CONFIG_NAMESPACES=y
# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -89,6 +89,7 @@ CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_PCI_QUIRKS=y
CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
@@ -101,6 +102,7 @@ CONFIG_KPROBES=y
CONFIG_KRETPROBES=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -113,7 +115,6 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -142,6 +143,7 @@ CONFIG_DEFAULT_IOSCHED="cfq"
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_EBSA110 is not set
# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_GEMINI is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_NETX is not set
# CONFIG_ARCH_H720X is not set
@@ -162,6 +164,7 @@ CONFIG_ARCH_KIRKWOOD=y
# CONFIG_ARCH_ORION5X is not set
# CONFIG_ARCH_PNX4008 is not set
# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MMP is not set
# CONFIG_ARCH_RPC is not set
# CONFIG_ARCH_SA1100 is not set
# CONFIG_ARCH_S3C2410 is not set
@@ -217,6 +220,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
# CONFIG_PCCARD is not set
#
@@ -237,6 +241,7 @@ CONFIG_AEABI=y
CONFIG_ARCH_FLATMEM_HAS_HOLES=y
# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -249,6 +254,8 @@ CONFIG_SPLIT_PTLOCK_CPUS=4096
CONFIG_ZONE_DMA_FLAG=0
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_ALIGNMENT_TRAP=y
#
@@ -293,7 +300,6 @@ CONFIG_NET=y
#
# Networking options
#
-CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -324,7 +330,7 @@ CONFIG_IP_PNP_BOOTP=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_LRO=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -357,6 +363,7 @@ CONFIG_NET_DSA_MV88E6123_61_65=y
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
# CONFIG_DCB is not set
@@ -365,20 +372,20 @@ CONFIG_NET_DSA_MV88E6123_61_65=y
#
CONFIG_NET_PKTGEN=m
# CONFIG_NET_TCPPROBE is not set
+# CONFIG_NET_DROP_MONITOR is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
CONFIG_WIRELESS=y
CONFIG_CFG80211=y
# CONFIG_CFG80211_REG_DEBUG is not set
-# CONFIG_NL80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
CONFIG_WIRELESS_EXT=y
CONFIG_WIRELESS_EXT_SYSFS=y
CONFIG_LIB80211=y
+# CONFIG_LIB80211_DEBUG is not set
CONFIG_MAC80211=y
#
@@ -513,7 +520,6 @@ CONFIG_MTD_NAND_ORION=y
# LPDDR flash memory drivers
#
# CONFIG_MTD_LPDDR is not set
-# CONFIG_MTD_QINFO_PROBE is not set
#
# UBI - Unsorted block images
@@ -592,8 +598,10 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -614,6 +622,7 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
@@ -687,6 +696,7 @@ CONFIG_SATA_MV=y
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -724,8 +734,10 @@ CONFIG_MII=y
# CONFIG_SMC91X is not set
# CONFIG_DM9000 is not set
# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
# CONFIG_SMC911X is not set
# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -763,6 +775,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_E1000E is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -777,6 +790,7 @@ CONFIG_MV643XX_ETH=y
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
# CONFIG_JME is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_TR is not set
@@ -789,10 +803,11 @@ CONFIG_WLAN_80211=y
CONFIG_LIBERTAS=y
# CONFIG_LIBERTAS_USB is not set
CONFIG_LIBERTAS_SDIO=y
+# CONFIG_LIBERTAS_SPI is not set
# CONFIG_LIBERTAS_DEBUG is not set
# CONFIG_LIBERTAS_THINFIRM is not set
-# CONFIG_HERMES is not set
# CONFIG_ATMEL is not set
+# CONFIG_AT76C50X_USB is not set
# CONFIG_PRISM54 is not set
# CONFIG_USB_ZD1201 is not set
# CONFIG_USB_NET_RNDIS_WLAN is not set
@@ -800,20 +815,20 @@ CONFIG_LIBERTAS_SDIO=y
# CONFIG_RTL8187 is not set
# CONFIG_ADM8211 is not set
# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_MWL8K is not set
# CONFIG_P54_COMMON is not set
# CONFIG_ATH5K is not set
# CONFIG_ATH9K is not set
+# CONFIG_AR9170_USB is not set
# CONFIG_IPW2100 is not set
# CONFIG_IPW2200 is not set
-# CONFIG_IWLCORE is not set
-# CONFIG_IWLWIFI_LEDS is not set
-# CONFIG_IWLAGN is not set
-# CONFIG_IWL3945 is not set
+# CONFIG_IWLWIFI is not set
# CONFIG_HOSTAP is not set
# CONFIG_B43 is not set
# CONFIG_B43LEGACY is not set
# CONFIG_ZD1211RW is not set
# CONFIG_RT2X00 is not set
+# CONFIG_HERMES is not set
#
# Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -908,6 +923,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=2
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_MAX3100 is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
@@ -982,7 +998,6 @@ CONFIG_I2C_MV64XXX=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -1082,15 +1097,17 @@ CONFIG_USB_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
+# CONFIG_DRAGONRISE_FF is not set
CONFIG_HID_EZKEY=y
+CONFIG_HID_KYE=y
CONFIG_HID_GYRATION=y
+CONFIG_HID_KENSINGTON=y
CONFIG_HID_LOGITECH=y
# CONFIG_LOGITECH_FF is not set
# CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -1152,11 +1169,11 @@ CONFIG_USB_PRINTER=m
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
#
#
-# see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -1198,7 +1215,6 @@ CONFIG_USB_STORAGE_JUMPSHOT=y
# 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
@@ -1215,6 +1231,7 @@ CONFIG_USB_STORAGE_JUMPSHOT=y
# OTG and related infrastructure
#
# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
# CONFIG_UWB is not set
CONFIG_MMC=y
# CONFIG_MMC_DEBUG is not set
@@ -1245,7 +1262,11 @@ CONFIG_LEDS_CLASS=y
#
# CONFIG_LEDS_PCA9532 is not set
CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_GPIO_PLATFORM=y
+# CONFIG_LEDS_LP5521 is not set
# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_BD2802 is not set
#
# LED Triggers
@@ -1255,6 +1276,10 @@ CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
@@ -1329,7 +1354,9 @@ CONFIG_DMA_ENGINE=y
# DMA Clients
#
# CONFIG_NET_DMA is not set
+# CONFIG_ASYNC_TX_DMA is not set
# CONFIG_DMATEST is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_REGULATOR is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
@@ -1341,6 +1368,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
@@ -1361,6 +1389,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=m
@@ -1419,6 +1452,7 @@ CONFIG_CRAMFS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -1430,7 +1464,6 @@ CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1502,6 +1535,9 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
# CONFIG_SCHED_DEBUG is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1538,10 +1574,12 @@ CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_PAGE_POISONING is not set
CONFIG_NOP_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_RING_BUFFER=y
CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -1551,11 +1589,15 @@ CONFIG_TRACING=y
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_FTRACE_STARTUP_TEST is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_DYNAMIC_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
@@ -1587,10 +1629,12 @@ CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_AUTHENC is not set
# CONFIG_CRYPTO_TEST is not set
@@ -1659,6 +1703,7 @@ CONFIG_CRYPTO_ARC4=y
# Compression
#
# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
#
@@ -1667,6 +1712,7 @@ CONFIG_CRYPTO_ARC4=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_BINARY_PRINTF=y
#
# Library routines
@@ -1682,7 +1728,7 @@ CONFIG_CRC32=y
CONFIG_LIBCRC32C=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/arm/configs/mv78xx0_defconfig b/arch/arm/configs/mv78xx0_defconfig
index b0698722e0cb..398274b0771a 100644
--- a/arch/arm/configs/mv78xx0_defconfig
+++ b/arch/arm/configs/mv78xx0_defconfig
@@ -1,11 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26-rc5
-# Fri Jun 13 02:57:32 2008
+# Linux kernel version: 2.6.30-rc4
+# Mon May 4 14:22:12 2009
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
-# CONFIG_GENERIC_GPIO is not set
+CONFIG_GENERIC_GPIO=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_MMU=y
@@ -22,8 +22,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
-CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_VECTORS_BASE=0xffff0000
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -43,10 +42,19 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -54,32 +62,35 @@ CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
CONFIG_EMBEDDED=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
# CONFIG_MARKERS is not set
CONFIG_OPROFILE=y
CONFIG_HAVE_OPROFILE=y
@@ -87,10 +98,9 @@ CONFIG_KPROBES=y
CONFIG_KRETPROBES=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_DMA_ATTRS is not set
-CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -98,12 +108,10 @@ 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
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -117,7 +125,7 @@ CONFIG_IOSCHED_CFQ=y
CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# System Type
@@ -127,11 +135,10 @@ CONFIG_CLASSIC_RCU=y
# 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_GEMINI is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_NETX is not set
# CONFIG_ARCH_H720X is not set
@@ -152,28 +159,23 @@ CONFIG_ARCH_MV78XX0=y
# CONFIG_ARCH_ORION5X is not set
# CONFIG_ARCH_PNX4008 is not set
# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MMP is not set
# CONFIG_ARCH_RPC is not set
# CONFIG_ARCH_SA1100 is not set
# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX 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_ARCH_MSM7X00A is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
#
# Marvell MV78xx0 Implementations
#
CONFIG_MACH_DB78X00_BP=y
CONFIG_MACH_RD78X00_MASA=y
-
-#
-# Boot options
-#
-
-#
-# Power management
-#
CONFIG_PLAT_ORION=y
#
@@ -199,6 +201,7 @@ CONFIG_ARM_THUMB=y
# CONFIG_CPU_DCACHE_DISABLE is not set
CONFIG_OUTER_CACHE=y
CONFIG_CACHE_FEROCEON_L2=y
+# CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH is not set
#
# Bus support
@@ -208,6 +211,8 @@ CONFIG_PCI_SYSCALL=y
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
# CONFIG_PCCARD is not set
#
@@ -217,25 +222,33 @@ CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
CONFIG_PREEMPT=y
CONFIG_HZ=100
CONFIG_AEABI=y
CONFIG_OABI_COMPAT=y
-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HIGHMEM=y
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_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4096
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_ALIGNMENT_TRAP=y
#
@@ -248,6 +261,11 @@ CONFIG_CMDLINE=""
# CONFIG_KEXEC is not set
#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
# Floating point emulation
#
@@ -263,6 +281,8 @@ CONFIG_VFP=y
# Userspace binary formats
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
# CONFIG_BINFMT_AOUT is not set
# CONFIG_BINFMT_MISC is not set
@@ -271,10 +291,6 @@ CONFIG_BINFMT_ELF=y
#
# CONFIG_PM is not set
CONFIG_ARCH_SUSPEND_POSSIBLE=y
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -310,7 +326,7 @@ CONFIG_IP_PNP_BOOTP=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_LRO=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -325,6 +341,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -334,26 +351,23 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
#
CONFIG_NET_PKTGEN=m
# CONFIG_NET_TCPPROBE is not set
+# CONFIG_NET_DROP_MONITOR is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_EXT=y
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -368,6 +382,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
# CONFIG_DEBUG_DRIVER is not set
# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
@@ -376,6 +392,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_AFS_PARTS is not set
@@ -429,9 +446,7 @@ CONFIG_MTD_CFI_UTIL=y
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x0
-CONFIG_MTD_PHYSMAP_LEN=0x0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
# CONFIG_MTD_IMPA7 is not set
# CONFIG_MTD_INTEL_VR_NOR is not set
@@ -456,6 +471,7 @@ CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_VERIFY_WRITE=y
# CONFIG_MTD_NAND_ECC_SMC is not set
# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
CONFIG_MTD_NAND_IDS=y
# CONFIG_MTD_NAND_DISKONCHIP is not set
# CONFIG_MTD_NAND_CAFE is not set
@@ -466,6 +482,11 @@ CONFIG_MTD_NAND_ORION=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -486,10 +507,20 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_ATA_OVER_ETH is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -547,7 +578,11 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
@@ -566,6 +601,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
@@ -632,11 +669,15 @@ CONFIG_SATA_MV=y
#
# IEEE 1394 (FireWire) support
#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -644,7 +685,26 @@ CONFIG_NETDEVICES=y
# CONFIG_TUN is not set
# CONFIG_VETH is not set
# CONFIG_ARCNET is not set
-# CONFIG_PHYLIB is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_AX88796 is not set
@@ -654,19 +714,25 @@ CONFIG_MII=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET 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_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
# CONFIG_AMD8111_ETH is not set
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -676,18 +742,20 @@ CONFIG_NET_PCI=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
# CONFIG_SC92031 is not set
+# CONFIG_ATL2 is not set
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
# CONFIG_E1000E is not set
-# CONFIG_E1000E_ENABLED is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -701,6 +769,9 @@ CONFIG_NETDEV_1000=y
CONFIG_MV643XX_ETH=y
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_JME is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_TR is not set
@@ -709,7 +780,10 @@ CONFIG_MV643XX_ETH=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
#
# USB Network Adapters
@@ -786,11 +860,11 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=16
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
-# CONFIG_NVRAM is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_RAW_DRIVER is not set
@@ -799,44 +873,63 @@ CONFIG_DEVPORT=y
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
#
# I2C Hardware Bus support
#
+
+#
+# PC SMBus host controller drivers
+#
# CONFIG_I2C_ALI1535 is not set
# CONFIG_I2C_ALI1563 is not set
# CONFIG_I2C_ALI15X3 is not set
# CONFIG_I2C_AMD756 is not set
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISCH is not set
# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_TINY_USB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_MV64XXX=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
# CONFIG_I2C_PCA_PLATFORM is not set
-CONFIG_I2C_MV64XXX=y
+# CONFIG_I2C_STUB is not set
#
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -848,6 +941,7 @@ CONFIG_I2C_MV64XXX=y
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
@@ -855,14 +949,17 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_F71882FG is not set
# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
@@ -877,10 +974,15 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 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_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_DME1737 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
@@ -900,20 +1002,28 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
-# CONFIG_MFD_ASIC3 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
#
# Multimedia devices
@@ -944,10 +1054,6 @@ CONFIG_SSB_POSSIBLE=y
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
@@ -958,9 +1064,36 @@ CONFIG_HID=y
# USB Input Devices
#
CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
+# CONFIG_HID_PID is not set
# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
@@ -978,6 +1111,9 @@ CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_OTG is not set
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
@@ -986,12 +1122,15 @@ CONFIG_USB_DEVICE_CLASS=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_USB_EHCI_TT_NEWSCHED=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
# CONFIG_USB_OHCI_HCD is not set
# CONFIG_USB_UHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
#
# USB Device Class drivers
@@ -999,20 +1138,20 @@ CONFIG_USB_EHCI_TT_NEWSCHED=y
# CONFIG_USB_ACM is not set
CONFIG_USB_PRINTER=y
# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
CONFIG_USB_STORAGE_DATAFAB=y
CONFIG_USB_STORAGE_FREECOM=y
# CONFIG_USB_STORAGE_ISD200 is not set
-CONFIG_USB_STORAGE_DPCM=y
# CONFIG_USB_STORAGE_USBAT is not set
CONFIG_USB_STORAGE_SDDR09=y
CONFIG_USB_STORAGE_SDDR55=y
@@ -1028,7 +1167,6 @@ CONFIG_USB_STORAGE_JUMPSHOT=y
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_MON is not set
#
# USB port drivers
@@ -1041,7 +1179,7 @@ CONFIG_USB_STORAGE_JUMPSHOT=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_SEVSEG is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
@@ -1049,7 +1187,6 @@ CONFIG_USB_STORAGE_JUMPSHOT=y
# 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
@@ -1059,14 +1196,29 @@ CONFIG_USB_STORAGE_JUMPSHOT=y
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
#
# LED drivers
#
+# CONFIG_LEDS_PCA9532 is not set
+# CONFIG_LEDS_GPIO is not set
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_BD2802 is not set
#
# LED Triggers
@@ -1074,7 +1226,12 @@ CONFIG_LEDS_CLASS=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
@@ -1105,6 +1262,8 @@ CONFIG_RTC_DRV_RS5C372=y
CONFIG_RTC_DRV_M41T80=y
# CONFIG_RTC_DRV_M41T80_WDT is not set
# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -1114,18 +1273,25 @@ CONFIG_RTC_DRV_M41T80=y
# Platform RTC drivers
#
# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
# on-CPU RTC drivers
#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_REGULATOR is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
@@ -1134,14 +1300,25 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_EXT4DEV_FS is not set
+CONFIG_EXT4_FS=m
+# CONFIG_EXT4DEV_COMPAT is not set
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=m
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -1151,6 +1328,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=m
@@ -1174,15 +1356,13 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
#
CONFIG_PROC_FS=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1202,25 +1382,27 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
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_NFSD is not set
CONFIG_ROOT_NFS=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
@@ -1301,11 +1483,16 @@ CONFIG_ENABLE_MUST_CHECK=y
CONFIG_FRAME_WARN=1024
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
CONFIG_SCHEDSTATS=y
# CONFIG_TIMER_STATS is not set
@@ -1320,22 +1507,55 @@ CONFIG_DEBUG_PREEMPT=y
# CONFIG_LOCK_STAT is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
-CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_KPROBES_SANITY_TEST is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_PAGE_POISONING is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
CONFIG_DEBUG_USER=y
CONFIG_DEBUG_ERRORS=y
# CONFIG_DEBUG_STACK_USAGE is not set
@@ -1347,17 +1567,27 @@ CONFIG_DEBUG_LL=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_ALGAPI2=m
+CONFIG_CRYPTO_AEAD2=m
CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=m
+CONFIG_CRYPTO_HASH2=m
+CONFIG_CRYPTO_RNG2=m
+CONFIG_CRYPTO_PCOMP=m
CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=m
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=m
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_AUTHENC is not set
# CONFIG_CRYPTO_TEST is not set
@@ -1393,6 +1623,10 @@ CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_MD4 is not set
# CONFIG_CRYPTO_MD5 is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
# CONFIG_CRYPTO_SHA1 is not set
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
@@ -1422,25 +1656,32 @@ CONFIG_CRYPTO_PCBC=m
# Compression
#
# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_BINARY_PRINTF=y
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
+CONFIG_CRC16=m
+# CONFIG_CRC_T10DIF is not set
CONFIG_CRC_ITU_T=m
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/arm/configs/mx31ads_defconfig b/arch/arm/configs/mx1_defconfig
index e05271753e15..0200d67e30ba 100644
--- a/arch/arm/configs/mx31ads_defconfig
+++ b/arch/arm/configs/mx1_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26-rc6
-# Fri Jun 20 16:21:11 2008
+# Linux kernel version: 2.6.30-rc1
+# Wed Apr 8 11:11:33 2009
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -12,6 +12,7 @@ CONFIG_MMU=y
# CONFIG_NO_IOPORT is not set
CONFIG_GENERIC_HARDIRQS=y
CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_HARDIRQS_SW_RESEND=y
@@ -21,9 +22,8 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
-CONFIG_ZONE_DMA=y
CONFIG_ARCH_MTD_XIP=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_VECTORS_BASE=0xffff0000
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -43,15 +43,24 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -59,26 +68,26 @@ CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
CONFIG_EMBEDDED=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
-CONFIG_SYSCTL_SYSCALL_CHECK=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_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
@@ -88,11 +97,10 @@ CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_DMA_ATTRS is not set
-CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -100,12 +108,10 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
# 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
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -119,7 +125,7 @@ CONFIG_IOSCHED_CFQ=y
CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
+CONFIG_FREEZER=y
#
# System Type
@@ -129,11 +135,10 @@ CONFIG_CLASSIC_RCU=y
# 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_GEMINI is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_NETX is not set
# CONFIG_ARCH_H720X is not set
@@ -145,55 +150,55 @@ CONFIG_CLASSIC_RCU=y
# CONFIG_ARCH_IXP2000 is not set
# CONFIG_ARCH_IXP4XX is not set
# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
# CONFIG_ARCH_KS8695 is not set
# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
CONFIG_ARCH_MXC=y
# CONFIG_ARCH_ORION5X is not set
# CONFIG_ARCH_PNX4008 is not set
# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MMP is not set
# CONFIG_ARCH_RPC is not set
# CONFIG_ARCH_SA1100 is not set
# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX 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_ARCH_MSM7X00A is not set
-
-#
-# Boot options
-#
-
-#
-# Power management
-#
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+CONFIG_ARCH_MX1ADS=y
#
# Freescale MXC Implementations
#
+CONFIG_ARCH_MX1=y
# CONFIG_ARCH_MX2 is not set
-CONFIG_ARCH_MX3=y
+# CONFIG_ARCH_MX3 is not set
#
-# MX3 Options
+# MX1 platforms:
#
-CONFIG_MACH_MX31ADS=y
-# CONFIG_MACH_PCM037 is not set
+CONFIG_MACH_MXLADS=y
+CONFIG_MACH_SCB9328=y
+CONFIG_MXC_IRQ_PRIOR=y
+# CONFIG_MXC_PWM is not set
#
# Processor Type
#
CONFIG_CPU_32=y
-CONFIG_CPU_V6=y
-# CONFIG_CPU_32v6K is not set
-CONFIG_CPU_32v6=y
-CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4T=y
+CONFIG_CPU_ABRT_EV4T=y
CONFIG_CPU_PABRT_NOIFAR=y
-CONFIG_CPU_CACHE_V6=y
-CONFIG_CPU_CACHE_VIPT=y
-CONFIG_CPU_COPY_V6=y
-CONFIG_CPU_TLB_V6=y
-CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CACHE_V4WT=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
@@ -203,7 +208,7 @@ CONFIG_CPU_CP15_MMU=y
CONFIG_ARM_THUMB=y
# CONFIG_CPU_ICACHE_DISABLE is not set
# CONFIG_CPU_DCACHE_DISABLE is not set
-# CONFIG_CPU_BPREDICT_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
# CONFIG_OUTER_CACHE is not set
#
@@ -220,25 +225,32 @@ CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
CONFIG_PREEMPT=y
CONFIG_HZ=100
CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM 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_PAGEFLAGS_EXTENDED=y
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_ALIGNMENT_TRAP=y
#
@@ -251,30 +263,41 @@ CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw ip=off"
# CONFIG_KEXEC is not set
#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
# Floating point emulation
#
#
# At least one emulation must be selected
#
-CONFIG_VFP=y
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
#
# Userspace binary formats
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
# CONFIG_BINFMT_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
# Power management options
#
-# CONFIG_PM is not set
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_VERBOSE is not set
+CONFIG_CAN_PM_TRACE=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
CONFIG_ARCH_SUSPEND_POSSIBLE=y
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -283,11 +306,6 @@ CONFIG_NET=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
-CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
-# CONFIG_XFRM_SUB_POLICY is not set
-# CONFIG_XFRM_MIGRATE is not set
-# CONFIG_XFRM_STATISTICS is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -306,12 +324,11 @@ CONFIG_IP_PNP_DHCP=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=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=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_INET_DIAG is not set
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
@@ -324,6 +341,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -333,7 +351,9 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -344,14 +364,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# 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_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -366,16 +380,16 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=m
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
# 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=y
-CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
-# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
-# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_AFS_PARTS is not set
# CONFIG_MTD_AR7_PARTS is not set
@@ -399,36 +413,31 @@ CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
# CONFIG_MTD_JEDECPROBE is not set
CONFIG_MTD_GEN_PROBE=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_NOSWAP=y
-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+# 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 is not set
+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 is not set
+CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I4 is not set
# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_OTP is not set
# CONFIG_MTD_CFI_INTELEXT is not set
-CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_AMDSTD is not set
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
-CONFIG_MTD_RAM=y
+# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
# CONFIG_MTD_PLATRAM is not set
@@ -446,17 +455,15 @@ CONFIG_MTD_RAM=y
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS 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_NANDSIM is not set
-# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_NAND is not set
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -476,23 +483,51 @@ CONFIG_HAVE_IDE=y
# CONFIG_ATA is not set
# CONFIG_MD is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
# 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_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=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_AX88796 is not set
# CONFIG_SMC91X is not set
-# CONFIG_DM9000 is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_DEBUGLEVEL=4
+# CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -502,7 +537,10 @@ CONFIG_MII=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -542,46 +580,124 @@ CONFIG_SERIAL_IMX_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# 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
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_IMX=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
# CONFIG_SPI is not set
-CONFIG_HAVE_GPIO_LIB=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_SYSFS is not set
#
-# GPIO Support
+# Memory mapped GPIO expanders:
#
#
# I2C GPIO expanders:
#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
#
# SPI GPIO expanders:
#
-# CONFIG_W1 is not set
+CONFIG_W1=y
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_DS2482 is not set
+CONFIG_W1_MASTER_MXC=y
+# CONFIG_W1_MASTER_GPIO is not set
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=y
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2431 is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+# CONFIG_W1_SLAVE_DS2760 is not set
+# CONFIG_W1_SLAVE_BQ27000 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_MFD_ASIC3 is not set
# CONFIG_HTC_EGPIO is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
#
# Multimedia devices
@@ -604,36 +720,131 @@ CONFIG_SSB_POSSIBLE=y
#
# CONFIG_VGASTATE is not set
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
-# CONFIG_FB is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT 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
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# 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_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+CONFIG_USB_SUPPORT=y
+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
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
#
-# Sound
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+CONFIG_USB_GADGET_IMX=y
+CONFIG_USB_IMX=y
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+# CONFIG_USB_ZERO is not set
+CONFIG_USB_ETH=y
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+
#
-# CONFIG_SOUND is not set
-# CONFIG_USB_SUPPORT is not set
-# CONFIG_MMC is not set
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_MXC=y
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_NEW_LEDS is not set
CONFIG_RTC_LIB=y
# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_REGULATOR is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
#
# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
# CONFIG_DNOTIFY is not set
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -643,6 +854,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -660,15 +876,13 @@ CONFIG_INOTIFY_USER=y
#
CONFIG_PROC_FS=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -687,25 +901,30 @@ CONFIG_JFFS2_ZLIB=y
# CONFIG_JFFS2_LZO is not set
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
-CONFIG_CRAMFS=y
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
CONFIG_ROOT_NFS=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_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
@@ -724,9 +943,9 @@ CONFIG_MSDOS_PARTITION=y
#
# Kernel hacking
#
-CONFIG_PRINTK_TIME=y
-CONFIG_ENABLE_WARN_DEPRECATED=y
-CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
CONFIG_FRAME_WARN=1024
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
@@ -734,8 +953,31 @@ CONFIG_FRAME_WARN=1024
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_ARM_UNWIND=y
# CONFIG_DEBUG_USER is not set
#
@@ -743,15 +985,28 @@ CONFIG_FRAME_POINTER=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
-# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_AUTHENC is not set
# CONFIG_CRYPTO_TEST is not set
@@ -766,7 +1021,7 @@ CONFIG_CRYPTO=y
#
# Block modes
#
-# CONFIG_CRYPTO_CBC is not set
+CONFIG_CRYPTO_CBC=y
# CONFIG_CRYPTO_CTR is not set
# CONFIG_CRYPTO_CTS is not set
# CONFIG_CRYPTO_ECB is not set
@@ -785,8 +1040,12 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_CRC32C is not set
# CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
# CONFIG_CRYPTO_SHA1 is not set
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
@@ -803,7 +1062,7 @@ CONFIG_CRYPTO=y
# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_CAST5 is not set
# CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_DES is not set
+CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_KHAZAD is not set
# CONFIG_CRYPTO_SALSA20 is not set
@@ -816,24 +1075,31 @@ CONFIG_CRYPTO=y
# Compression
#
# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
-# CONFIG_CRYPTO_HW is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T 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
+CONFIG_NLATTR=y
diff --git a/arch/arm/configs/pcm038_defconfig b/arch/arm/configs/mx27_defconfig
index 41429a00f58c..083516cd0d7f 100644
--- a/arch/arm/configs/pcm038_defconfig
+++ b/arch/arm/configs/mx27_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26-rc6
-# Fri Jun 20 16:38:36 2008
+# Linux kernel version: 2.6.30-rc1
+# Wed Apr 8 10:18:06 2009
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -12,6 +12,7 @@ CONFIG_MMU=y
# CONFIG_NO_IOPORT is not set
CONFIG_GENERIC_HARDIRQS=y
CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_HARDIRQS_SW_RESEND=y
@@ -21,9 +22,8 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
-CONFIG_ZONE_DMA=y
CONFIG_ARCH_MTD_XIP=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_VECTORS_BASE=0xffff0000
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -40,47 +40,58 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
CONFIG_EMBEDDED=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-# CONFIG_COMPAT_BRK is not set
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
CONFIG_MARKERS=y
CONFIG_OPROFILE=y
CONFIG_HAVE_OPROFILE=y
@@ -88,11 +99,10 @@ CONFIG_KPROBES=y
CONFIG_KRETPROBES=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_PROC_PAGE_MONITOR is not set
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -100,12 +110,10 @@ 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
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -119,7 +127,7 @@ CONFIG_IOSCHED_NOOP=y
# CONFIG_DEFAULT_CFQ is not set
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
-CONFIG_CLASSIC_RCU=y
+CONFIG_FREEZER=y
#
# System Type
@@ -129,11 +137,10 @@ CONFIG_CLASSIC_RCU=y
# 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_GEMINI is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_NETX is not set
# CONFIG_ARCH_H720X is not set
@@ -145,46 +152,44 @@ CONFIG_CLASSIC_RCU=y
# CONFIG_ARCH_IXP2000 is not set
# CONFIG_ARCH_IXP4XX is not set
# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
# CONFIG_ARCH_KS8695 is not set
# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
CONFIG_ARCH_MXC=y
# CONFIG_ARCH_ORION5X is not set
# CONFIG_ARCH_PNX4008 is not set
# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MMP is not set
# CONFIG_ARCH_RPC is not set
# CONFIG_ARCH_SA1100 is not set
# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX 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_ARCH_MSM7X00A is not set
-
-#
-# Boot options
-#
-
-#
-# Power management
-#
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
#
# Freescale MXC Implementations
#
+# CONFIG_ARCH_MX1 is not set
CONFIG_ARCH_MX2=y
# CONFIG_ARCH_MX3 is not set
-
-#
-# MX2 family CPU support
-#
+# CONFIG_MACH_MX21 is not set
CONFIG_MACH_MX27=y
#
-# MX2 Platforms
+# MX2 platforms:
#
-# CONFIG_MACH_MX27ADS is not set
+CONFIG_MACH_MX27ADS=y
CONFIG_MACH_PCM038=y
CONFIG_MACH_PCM970_BASEBOARD=y
+CONFIG_MXC_IRQ_PRIOR=y
+CONFIG_MXC_PWM=y
#
# Processor Type
@@ -209,6 +214,7 @@ CONFIG_ARM_THUMB=y
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
# CONFIG_OUTER_CACHE is not set
+CONFIG_COMMON_CLKDEV=y
#
# Bus support
@@ -224,25 +230,32 @@ CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
CONFIG_PREEMPT=y
CONFIG_HZ=100
CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM 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_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4096
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_ALIGNMENT_TRAP=y
#
@@ -255,30 +268,44 @@ CONFIG_CMDLINE=""
# CONFIG_KEXEC is not set
#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
# Floating point emulation
#
#
# At least one emulation must be selected
#
+CONFIG_FPE_NWFPE=y
+CONFIG_FPE_NWFPE_XP=y
+# CONFIG_FPE_FASTFPE is not set
# CONFIG_VFP is not set
#
# Userspace binary formats
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
# CONFIG_BINFMT_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
# Power management options
#
-# CONFIG_PM is not set
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_VERBOSE is not set
+CONFIG_CAN_PM_TRACE=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
CONFIG_ARCH_SUSPEND_POSSIBLE=y
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -293,7 +320,7 @@ CONFIG_IP_MULTICAST=y
# 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_DHCP=y
# CONFIG_IP_PNP_BOOTP is not set
# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
@@ -323,6 +350,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -332,26 +360,23 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NET_TCPPROBE is not set
+# CONFIG_NET_DROP_MONITOR is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -366,12 +391,15 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
# CONFIG_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_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_AFS_PARTS is not set
@@ -426,9 +454,7 @@ CONFIG_MTD_CFI_UTIL=y
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x00000000
-CONFIG_MTD_PHYSMAP_LEN=0x0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
# CONFIG_MTD_PLATRAM is not set
@@ -452,6 +478,11 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -477,7 +508,7 @@ CONFIG_HAVE_IDE=y
# CONFIG_ATA is not set
# CONFIG_MD is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -491,12 +522,20 @@ CONFIG_NET_ETHERNET=y
# CONFIG_SMC91X is not set
# CONFIG_DM9000 is not set
# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
-CONFIG_FEC_OLD=y
+CONFIG_FEC=y
+# CONFIG_FEC2 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -505,7 +544,10 @@ CONFIG_FEC_OLD=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -541,12 +583,15 @@ CONFIG_INPUT_TOUCHSCREEN=y
# CONFIG_TOUCHSCREEN_FUJITSU is not set
# CONFIG_TOUCHSCREEN_GUNZE is not set
# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO 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_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
# CONFIG_INPUT_MISC is not set
#
@@ -559,6 +604,7 @@ CONFIG_INPUT_TOUCHSCREEN=y
# Character devices
#
CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
@@ -573,42 +619,55 @@ CONFIG_DEVKMEM=y
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_MAX3100 is not set
CONFIG_SERIAL_IMX=y
CONFIG_SERIAL_IMX_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# 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=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_CHARDEV is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
#
# I2C Hardware Bus support
#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_IMX=y
# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_STUB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
#
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_TPS65010 is not set
+# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -622,47 +681,83 @@ CONFIG_SPI_MASTER=y
# SPI Master Controller Drivers
#
CONFIG_SPI_BITBANG=y
+# CONFIG_SPI_GPIO is not set
#
# SPI Protocol Masters
#
-# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
-CONFIG_HAVE_GPIO_LIB=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_SYSFS is not set
#
-# GPIO Support
+# Memory mapped GPIO expanders:
#
#
# I2C GPIO expanders:
#
+# CONFIG_GPIO_MAX732X is not set
# CONFIG_GPIO_PCA953X is not set
# CONFIG_GPIO_PCF857X is not set
#
+# PCI GPIO expanders:
+#
+
+#
# SPI GPIO expanders:
#
+# CONFIG_GPIO_MAX7301 is not set
# CONFIG_GPIO_MCP23S08 is not set
-# CONFIG_W1 is not set
+CONFIG_W1=y
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_DS2482 is not set
+CONFIG_W1_MASTER_MXC=y
+# CONFIG_W1_MASTER_GPIO is not set
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=y
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2431 is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+# CONFIG_W1_SLAVE_DS2760 is not set
+# CONFIG_W1_SLAVE_BQ27000 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_MFD_ASIC3 is not set
# CONFIG_HTC_EGPIO is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
#
# Multimedia devices
@@ -683,7 +778,7 @@ CONFIG_VIDEO_MEDIA=y
#
# CONFIG_MEDIA_ATTACH is not set
CONFIG_MEDIA_TUNER=y
-# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
CONFIG_MEDIA_TUNER_SIMPLE=y
CONFIG_MEDIA_TUNER_TDA8290=y
CONFIG_MEDIA_TUNER_TDA9887=y
@@ -692,16 +787,17 @@ CONFIG_MEDIA_TUNER_TEA5767=y
CONFIG_MEDIA_TUNER_MT20XX=y
CONFIG_MEDIA_TUNER_XC2028=y
CONFIG_MEDIA_TUNER_XC5000=y
+CONFIG_MEDIA_TUNER_MC44S803=y
CONFIG_VIDEO_V4L2=y
CONFIG_VIDEO_V4L1=y
CONFIG_VIDEO_CAPTURE_DRIVERS=y
# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
# CONFIG_VIDEO_VIVI is not set
# CONFIG_VIDEO_CPIA is not set
# CONFIG_VIDEO_SAA5246A is not set
# CONFIG_VIDEO_SAA5249 is not set
-# CONFIG_TUNER_3036 is not set
# CONFIG_SOC_CAMERA is not set
# CONFIG_RADIO_ADAPTERS is not set
# CONFIG_DAB is not set
@@ -714,9 +810,10 @@ CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
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_BOOT_VESA_SUPPORT 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
@@ -732,8 +829,12 @@ CONFIG_FB=y
#
# Frame buffer hardware drivers
#
+CONFIG_FB_IMX=y
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -761,14 +862,29 @@ CONFIG_FONT_8x8=y
# CONFIG_FONT_SUN12x22 is not set
# CONFIG_FONT_10x18 is not set
# CONFIG_LOGO is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
# CONFIG_HID_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
-# CONFIG_MMC is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_MXC=y
+# CONFIG_MMC_SPI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_NEW_LEDS is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
@@ -800,42 +916,56 @@ CONFIG_RTC_DRV_PCF8563=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
# CONFIG_RTC_DRV_MAX6902 is not set
# CONFIG_RTC_DRV_R9701 is not set
# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
#
# Platform RTC drivers
#
# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
# on-CPU RTC drivers
#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_REGULATOR is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
#
# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY is not set
# CONFIG_QUOTA is not set
@@ -844,6 +974,11 @@ CONFIG_RTC_DRV_PCF8563=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -861,15 +996,13 @@ CONFIG_RTC_DRV_PCF8563=y
#
CONFIG_PROC_FS=y
CONFIG_PROC_SYSCTL=y
+# CONFIG_PROC_PAGE_MONITOR is not set
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -889,25 +1022,27 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
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_NFSD is not set
CONFIG_ROOT_NFS=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
@@ -972,12 +1107,41 @@ CONFIG_ENABLE_MUST_CHECK=y
CONFIG_FRAME_WARN=1024
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
+CONFIG_STACKTRACE=y
# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_ARM_UNWIND=y
# CONFIG_DEBUG_USER is not set
#
@@ -985,24 +1149,26 @@ CONFIG_FRAME_POINTER=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
+CONFIG_BINARY_PRINTF=y
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T 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
+CONFIG_NLATTR=y
diff --git a/arch/arm/configs/mx31moboard_defconfig b/arch/arm/configs/mx31moboard_defconfig
deleted file mode 100644
index e90f86d6deef..000000000000
--- a/arch/arm/configs/mx31moboard_defconfig
+++ /dev/null
@@ -1,790 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc5
-# Fri Oct 24 11:41:22 2008
-#
-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_HAVE_LATENCYTOP_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_ARCH_SUPPORTS_AOUT=y
-CONFIG_ZONE_DMA=y
-CONFIG_ARCH_MTD_XIP=y
-CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
-CONFIG_VECTORS_BASE=0xffff0000
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# General setup
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_LOCK_KERNEL=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_AUDIT is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
-CONFIG_GROUP_SCHED=y
-CONFIG_FAIR_GROUP_SCHED=y
-# CONFIG_RT_GROUP_SCHED is not set
-CONFIG_USER_SCHED=y
-# CONFIG_CGROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-# CONFIG_RELAY is not set
-# CONFIG_NAMESPACES is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-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_COMPAT_BRK=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
-CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
-CONFIG_SHMEM=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
-# CONFIG_SLOB is not set
-# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
-CONFIG_HAVE_OPROFILE=y
-# CONFIG_KPROBES is not set
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_HAVE_IOREMAP_PROT is not set
-CONFIG_HAVE_KPROBES=y
-CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
-CONFIG_HAVE_GENERIC_DMA_COHERENT=y
-CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-CONFIG_MODULES=y
-# CONFIG_MODULE_FORCE_LOAD is not set
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# 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
-# CONFIG_BLK_DEV_INTEGRITY is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
-# CONFIG_DEFAULT_DEADLINE is not set
-CONFIG_DEFAULT_CFQ=y
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
-
-#
-# 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_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_KIRKWOOD is not set
-# CONFIG_ARCH_KS8695 is not set
-# CONFIG_ARCH_NS9XXX is not set
-# CONFIG_ARCH_LOKI is not set
-# CONFIG_ARCH_MV78XX0 is not set
-CONFIG_ARCH_MXC=y
-# CONFIG_ARCH_ORION5X 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 is not set
-# CONFIG_ARCH_MSM7X00A is not set
-
-#
-# Boot options
-#
-
-#
-# Power management
-#
-
-#
-# Freescale MXC Implementations
-#
-# CONFIG_ARCH_MX2 is not set
-CONFIG_ARCH_MX3=y
-
-#
-# MX3 Options
-#
-# CONFIG_MACH_MX31ADS is not set
-# CONFIG_MACH_PCM037 is not set
-# CONFIG_MACH_MX31LITE is not set
-CONFIG_MACH_MX31MOBOARD=y
-# CONFIG_MXC_IRQ_PRIOR is not set
-
-#
-# Processor Type
-#
-CONFIG_CPU_32=y
-CONFIG_CPU_V6=y
-# CONFIG_CPU_32v6K is not set
-CONFIG_CPU_32v6=y
-CONFIG_CPU_ABRT_EV6=y
-CONFIG_CPU_PABRT_NOIFAR=y
-CONFIG_CPU_CACHE_V6=y
-CONFIG_CPU_CACHE_VIPT=y
-CONFIG_CPU_COPY_V6=y
-CONFIG_CPU_TLB_V6=y
-CONFIG_CPU_HAS_ASID=y
-CONFIG_CPU_CP15=y
-CONFIG_CPU_CP15_MMU=y
-
-#
-# Processor Features
-#
-CONFIG_ARM_THUMB=y
-# CONFIG_CPU_ICACHE_DISABLE is not set
-# CONFIG_CPU_DCACHE_DISABLE is not set
-# CONFIG_CPU_BPREDICT_DISABLE is not set
-# CONFIG_OUTER_CACHE is not set
-
-#
-# 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=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
-CONFIG_PREEMPT=y
-CONFIG_HZ=100
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-CONFIG_ARCH_FLATMEM_HAS_HOLES=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_PAGEFLAGS_EXTENDED=y
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# 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="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw ip=off"
-# CONFIG_XIP_KERNEL is not set
-# CONFIG_KEXEC is not set
-
-#
-# Floating point emulation
-#
-
-#
-# At least one emulation must be selected
-#
-CONFIG_VFP=y
-
-#
-# 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_ARCH_SUSPEND_POSSIBLE=y
-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 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 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_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_CAN 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=m
-CONFIG_FIRMWARE_IN_KERNEL=y
-CONFIG_EXTRA_FIRMWARE=""
-# 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=y
-CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
-# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
-CONFIG_MTD_REDBOOT_PARTS_READONLY=y
-# CONFIG_MTD_CMDLINE_PARTS is not set
-# CONFIG_MTD_AFS_PARTS is not set
-# CONFIG_MTD_AR7_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
-# CONFIG_MTD_OOPS 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=y
-CONFIG_MTD_CFI_NOSWAP=y
-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
-# 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 is not set
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_OTP is not set
-# CONFIG_MTD_CFI_INTELEXT is not set
-CONFIG_MTD_CFI_AMDSTD=y
-# 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
-# CONFIG_MTD_XIP is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x0
-CONFIG_MTD_PHYSMAP_LEN=0x0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
-# CONFIG_MTD_ARM_INTEGRATOR is not set
-# 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 is not set
-# CONFIG_MISC_DEVICES is not set
-CONFIG_HAVE_IDE=y
-# 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_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_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_IWLWIFI_LEDS is not set
-# CONFIG_WAN is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP 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 is not set
-
-#
-# Hardware I/O ports
-#
-# CONFIG_SERIO is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-CONFIG_DEVKMEM=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_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
-# CONFIG_SPI is not set
-CONFIG_ARCH_REQUIRE_GPIOLIB=y
-CONFIG_GPIOLIB=y
-# CONFIG_GPIO_SYSFS is not set
-
-#
-# I2C GPIO expanders:
-#
-
-#
-# PCI GPIO expanders:
-#
-
-#
-# SPI GPIO expanders:
-#
-# 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
-#
-# CONFIG_MFD_CORE is not set
-# CONFIG_MFD_SM501 is not set
-# CONFIG_HTC_EGPIO is not set
-# CONFIG_HTC_PASIC3 is not set
-# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_T7L66XB is not set
-# CONFIG_MFD_TC6387XB is not set
-# CONFIG_MFD_TC6393XB is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
-
-#
-# Graphics support
-#
-# 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_SOUND 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
-# CONFIG_DMADEVICES is not set
-
-#
-# Voltage and Current regulators
-#
-# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
-# CONFIG_UIO 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_OCFS2_FS is not set
-# CONFIG_DNOTIFY is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA 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=y
-# CONFIG_TMPFS_POSIX_ACL 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_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_MINIX_FS is not set
-# CONFIG_OMFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-CONFIG_NETWORK_FILESYSTEMS=y
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-CONFIG_ROOT_NFS=y
-# CONFIG_NFSD is not set
-CONFIG_LOCKD=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# 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
-# CONFIG_NLS is not set
-# CONFIG_DLM is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_FRAME_WARN=1024
-# 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 is not set
-# CONFIG_DEBUG_MEMORY_INIT is not set
-CONFIG_FRAME_POINTER=y
-# CONFIG_LATENCYTOP is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_HAVE_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
-# CONFIG_IRQSOFF_TRACER is not set
-# CONFIG_PREEMPT_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_SAMPLES is not set
-CONFIG_HAVE_ARCH_KGDB=y
-# CONFIG_DEBUG_USER is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
-# CONFIG_CRC_T10DIF 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/mx31litekit_defconfig b/arch/arm/configs/mx3_defconfig
index 4f41c4135685..20ada526f6de 100644
--- a/arch/arm/configs/mx31litekit_defconfig
+++ b/arch/arm/configs/mx3_defconfig
@@ -1,17 +1,18 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26-rc5
-# Fri Jun 13 14:23:39 2008
+# Linux kernel version: 2.6.30-rc1
+# Wed Apr 8 11:06:37 2009
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
-# CONFIG_GENERIC_GPIO is not set
-# CONFIG_GENERIC_TIME is not set
-# CONFIG_GENERIC_CLOCKEVENTS is not set
+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_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_HARDIRQS_SW_RESEND=y
@@ -21,9 +22,8 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
-CONFIG_ZONE_DMA=y
CONFIG_ARCH_MTD_XIP=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_VECTORS_BASE=0xffff0000
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -43,11 +43,24 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-# CONFIG_GROUP_SCHED is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -55,27 +68,26 @@ CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
CONFIG_EMBEDDED=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
-CONFIG_SYSCTL_SYSCALL_CHECK=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_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
@@ -85,11 +97,10 @@ CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_DMA_ATTRS is not set
-CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -97,12 +108,10 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
# 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
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -116,7 +125,7 @@ CONFIG_IOSCHED_CFQ=y
CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
+CONFIG_FREEZER=y
#
# System Type
@@ -126,11 +135,10 @@ CONFIG_CLASSIC_RCU=y
# 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_GEMINI is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_NETX is not set
# CONFIG_ARCH_H720X is not set
@@ -142,39 +150,47 @@ CONFIG_CLASSIC_RCU=y
# CONFIG_ARCH_IXP2000 is not set
# CONFIG_ARCH_IXP4XX is not set
# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
# CONFIG_ARCH_KS8695 is not set
# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
CONFIG_ARCH_MXC=y
# CONFIG_ARCH_ORION5X is not set
# CONFIG_ARCH_PNX4008 is not set
# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MMP is not set
# CONFIG_ARCH_RPC is not set
# CONFIG_ARCH_SA1100 is not set
# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX 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_ARCH_MSM7X00A is not set
-
-#
-# Boot options
-#
-
-#
-# Power management
-#
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
#
# Freescale MXC Implementations
#
+# CONFIG_ARCH_MX1 is not set
+# CONFIG_ARCH_MX2 is not set
CONFIG_ARCH_MX3=y
+CONFIG_ARCH_MX31=y
#
-# MX3 Options
+# MX3 platforms:
#
-# CONFIG_MACH_MX31ADS is not set
+CONFIG_MACH_MX31ADS=y
+CONFIG_MACH_MX31ADS_WM1133_EV1=y
+CONFIG_MACH_PCM037=y
CONFIG_MACH_MX31LITE=y
+CONFIG_MACH_MX31_3DS=y
+CONFIG_MACH_MX31MOBOARD=y
+CONFIG_MACH_QONG=y
+CONFIG_MXC_IRQ_PRIOR=y
+CONFIG_MXC_PWM=y
#
# Processor Type
@@ -200,45 +216,50 @@ CONFIG_ARM_THUMB=y
# CONFIG_CPU_ICACHE_DISABLE is not set
# CONFIG_CPU_DCACHE_DISABLE is not set
# CONFIG_CPU_BPREDICT_DISABLE is not set
-# CONFIG_OUTER_CACHE is not set
+CONFIG_OUTER_CACHE=y
+CONFIG_CACHE_L2X0=y
+CONFIG_COMMON_CLKDEV=y
#
# Bus support
#
# CONFIG_PCI_SYSCALL is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
-CONFIG_PCCARD=m
-# CONFIG_PCMCIA_DEBUG is not set
-# CONFIG_PCMCIA is not set
-
-#
-# PC-card bridges
-#
+# CONFIG_PCCARD is not set
#
# Kernel Features
#
-# CONFIG_TICK_ONESHOT is not set
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
CONFIG_PREEMPT=y
-# CONFIG_NO_IDLE_HZ is not set
CONFIG_HZ=100
CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM 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_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_ALIGNMENT_TRAP=y
#
@@ -251,33 +272,42 @@ CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw ip=off"
# CONFIG_KEXEC is not set
#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
# Floating point emulation
#
#
# At least one emulation must be selected
#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
CONFIG_VFP=y
#
# Userspace binary formats
#
CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_AOUT=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
# Power management options
#
CONFIG_PM=y
-# CONFIG_PM_DEBUG is not set
-# CONFIG_SUSPEND is not set
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_VERBOSE is not set
+CONFIG_CAN_PM_TRACE=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
# CONFIG_APM_EMULATION is not set
CONFIG_ARCH_SUSPEND_POSSIBLE=y
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -286,11 +316,6 @@ CONFIG_NET=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
-CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
-# CONFIG_XFRM_SUB_POLICY is not set
-# CONFIG_XFRM_MIGRATE is not set
-# CONFIG_XFRM_STATISTICS is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -309,12 +334,11 @@ CONFIG_IP_PNP_DHCP=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=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=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_INET_DIAG is not set
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
@@ -327,6 +351,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -336,7 +361,9 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -347,14 +374,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# 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_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -369,18 +390,16 @@ 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_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
# 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=y
-CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
-# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
-# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_AFS_PARTS is not set
# CONFIG_MTD_AR7_PARTS is not set
@@ -404,36 +423,31 @@ CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
# CONFIG_MTD_JEDECPROBE is not set
CONFIG_MTD_GEN_PROBE=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_NOSWAP=y
-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+# 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 is not set
+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 is not set
+CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I4 is not set
# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_OTP is not set
# CONFIG_MTD_CFI_INTELEXT is not set
-CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_AMDSTD is not set
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
-CONFIG_MTD_RAM=y
+# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
# CONFIG_MTD_PLATRAM is not set
@@ -451,18 +465,15 @@ CONFIG_MTD_RAM=y
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS 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_NANDSIM is not set
-# CONFIG_MTD_NAND_PLATFORM is not set
-# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_NAND is not set
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -476,63 +487,58 @@ CONFIG_HAVE_IDE=y
# SCSI device support
#
# CONFIG_RAID_ATTRS is not set
-CONFIG_SCSI=y
-CONFIG_SCSI_DMA=y
-# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
# CONFIG_SCSI_NETLINK is not set
-CONFIG_SCSI_PROC_FS=y
-
-#
-# 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=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 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_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
# CONFIG_ATA is not set
# CONFIG_MD is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
# 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_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=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_AX88796 is not set
# CONFIG_SMC91X is not set
# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+CONFIG_SMSC911X=y
+# CONFIG_DNET is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
+CONFIG_CS89x0=y
+CONFIG_CS89x0_NONISA_IRQ=y
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -541,16 +547,10 @@ CONFIG_MII=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
#
-# USB Network Adapters
+# Enable WiMAX (Networking options) to see the WiMAX drivers
#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET is not set
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -562,43 +562,7 @@ CONFIG_MII=y
#
# 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_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_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
+# CONFIG_INPUT is not set
#
# Hardware I/O ports
@@ -609,10 +573,7 @@ CONFIG_INPUT_TOUCHSCREEN=y
#
# Character devices
#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_VT is not set
CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
@@ -624,45 +585,132 @@ CONFIG_DEVKMEM=y
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
# CONFIG_IPMI_HANDLER is not set
-CONFIG_HW_RANDOM=y
-# CONFIG_NVRAM is not set
+# CONFIG_HW_RANDOM 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
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_IMX=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
# CONFIG_SPI is not set
-# CONFIG_W1 is not set
-# CONFIG_POWER_SUPPLY is not set
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_SYSFS is not set
#
-# Watchdog Device Drivers
+# Memory mapped GPIO expanders:
#
-# CONFIG_SOFT_WATCHDOG is not set
#
-# USB-based Watchdog Cards
+# I2C GPIO expanders:
#
-# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
#
-# Sonics Silicon Backplane
+# PCI GPIO expanders:
#
+
+#
+# SPI GPIO expanders:
+#
+CONFIG_W1=y
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_DS2482 is not set
+CONFIG_W1_MASTER_MXC=y
+# CONFIG_W1_MASTER_GPIO is not set
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=y
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2431 is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+# CONFIG_W1_SLAVE_DS2760 is not set
+# CONFIG_W1_SLAVE_BQ27000 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+CONFIG_MFD_WM8350=y
+CONFIG_MFD_WM8350_CONFIG_MODE_0=y
+CONFIG_MFD_WM8352_CONFIG_MODE_0=y
+CONFIG_MFD_WM8350_I2C=y
+# CONFIG_MFD_PCF50633 is not set
#
# Multimedia devices
@@ -673,7 +721,7 @@ CONFIG_SSB_POSSIBLE=y
#
CONFIG_VIDEO_DEV=y
CONFIG_VIDEO_V4L2_COMMON=y
-CONFIG_VIDEO_ALLOW_V4L1=y
+# CONFIG_VIDEO_ALLOW_V4L1 is not set
CONFIG_VIDEO_V4L1_COMPAT=y
# CONFIG_DVB_CORE is not set
CONFIG_VIDEO_MEDIA=y
@@ -682,34 +730,38 @@ CONFIG_VIDEO_MEDIA=y
# Multimedia drivers
#
# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=y
+CONFIG_MEDIA_TUNER_TDA8290=y
+CONFIG_MEDIA_TUNER_TDA9887=y
+CONFIG_MEDIA_TUNER_TEA5761=y
+CONFIG_MEDIA_TUNER_TEA5767=y
+CONFIG_MEDIA_TUNER_MT20XX=y
+CONFIG_MEDIA_TUNER_XC2028=y
+CONFIG_MEDIA_TUNER_XC5000=y
+CONFIG_MEDIA_TUNER_MC44S803=y
CONFIG_VIDEO_V4L2=y
-CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEOBUF_GEN=y
+CONFIG_VIDEOBUF_DMA_CONTIG=y
CONFIG_VIDEO_CAPTURE_DRIVERS=y
# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
# CONFIG_VIDEO_VIVI is not set
-# CONFIG_VIDEO_CPIA is not set
-# CONFIG_VIDEO_CPIA2 is not set
-CONFIG_V4L_USB_DRIVERS=y
-# CONFIG_USB_VICAM is not set
-# CONFIG_USB_IBMCAM is not set
-# CONFIG_USB_KONICAWC is not set
-# CONFIG_USB_QUICKCAM_MESSENGER is not set
-# CONFIG_USB_ET61X251 is not set
-# CONFIG_USB_OV511 is not set
-# CONFIG_USB_SE401 is not set
-# CONFIG_USB_SN9C102 is not set
-# CONFIG_USB_STV680 is not set
-# CONFIG_USB_ZC0301 is not set
-# CONFIG_USB_PWC is not set
-# CONFIG_USB_ZR364XX is not set
-# CONFIG_USB_STKWEBCAM is not set
-# CONFIG_SOC_CAMERA is not set
-CONFIG_RADIO_ADAPTERS=y
-# CONFIG_USB_DSBR is not set
-# CONFIG_USB_SI470X is not set
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+CONFIG_SOC_CAMERA=y
+CONFIG_SOC_CAMERA_MT9M001=y
+CONFIG_SOC_CAMERA_MT9M111=y
+CONFIG_SOC_CAMERA_MT9T031=y
+CONFIG_SOC_CAMERA_MT9V022=y
+CONFIG_SOC_CAMERA_TW9910=y
+# CONFIG_SOC_CAMERA_PLATFORM is not set
+# CONFIG_SOC_CAMERA_OV772X is not set
+CONFIG_VIDEO_MX3=y
+# CONFIG_RADIO_ADAPTERS is not set
+# CONFIG_DAB is not set
#
# Graphics support
@@ -719,9 +771,10 @@ CONFIG_DAB=y
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_BOOT_VESA_SUPPORT 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
@@ -739,131 +792,79 @@ CONFIG_FB=y
#
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+CONFIG_FB_MX3=y
+# CONFIG_FB_BROADSHEET 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 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 is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-CONFIG_LOGO_LINUX_CLUT224=y
-
-#
-# Sound
-#
+# CONFIG_LOGO is not set
# CONFIG_SOUND is not set
-# CONFIG_HID_SUPPORT is not set
-CONFIG_USB_SUPPORT=y
-CONFIG_USB_ARCH_HAS_HCD=y
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-# CONFIG_USB_ARCH_HAS_EHCI is not set
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
#
-# Miscellaneous USB options
+# MMC/SD/SDIO Card Drivers
#
-# CONFIG_USB_DEVICEFS is not set
-CONFIG_USB_DEVICE_CLASS=y
-# CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_SUSPEND is not set
-# CONFIG_USB_OTG is not set
-# CONFIG_USB_OTG_WHITELIST is not set
-# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
#
-# USB Host Controller Drivers
+# MMC/SD/SDIO Host Controller Drivers
#
-# CONFIG_USB_C67X00_HCD is not set
-# CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_ISP1760_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
-# CONFIG_USB_WDM 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 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
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_MXC=y
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+CONFIG_DMADEVICES=y
#
-# USB port drivers
+# DMA Devices
#
-# CONFIG_USB_SERIAL is not set
+CONFIG_MX3_IPU=y
+CONFIG_MX3_IPU_IRQS=4
+CONFIG_DMA_ENGINE=y
#
-# USB Miscellaneous drivers
+# DMA Clients
#
-# 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_ISIGHTFW is not set
-# CONFIG_USB_GADGET is not set
-# CONFIG_MMC is not set
-# CONFIG_NEW_LEDS is not set
-CONFIG_RTC_LIB=y
-# CONFIG_RTC_CLASS is not set
+# CONFIG_NET_DMA is not set
+# CONFIG_ASYNC_TX_DMA is not set
+# CONFIG_DMATEST is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+CONFIG_REGULATOR_WM8350=y
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
#
# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
# CONFIG_DNOTIFY is not set
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -873,6 +874,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -890,15 +896,13 @@ CONFIG_INOTIFY_USER=y
#
CONFIG_PROC_FS=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -917,25 +921,30 @@ CONFIG_JFFS2_ZLIB=y
# CONFIG_JFFS2_LZO is not set
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
-CONFIG_CRAMFS=y
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
CONFIG_ROOT_NFS=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_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
@@ -954,65 +963,70 @@ CONFIG_MSDOS_PARTITION=y
#
# Kernel hacking
#
-CONFIG_PRINTK_TIME=y
-CONFIG_ENABLE_WARN_DEPRECATED=y
-CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
CONFIG_FRAME_WARN=1024
# 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_DETECT_SOFTLOCKUP=y
-CONFIG_SCHED_DEBUG=y
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_OBJECTS is not set
-# CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_PREEMPT=y
-# 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_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
-CONFIG_DEBUG_BUGVERBOSE=y
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_VM is not set
-# CONFIG_DEBUG_WRITECOUNT is not set
-# CONFIG_DEBUG_LIST is not set
-# CONFIG_DEBUG_SG is not set
-CONFIG_FRAME_POINTER=y
-# CONFIG_BOOT_PRINTK_DELAY is not set
-# CONFIG_RCU_TORTURE_TEST is not set
-# CONFIG_BACKTRACE_SELF_TEST is not set
-# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_ARM_UNWIND=y
# CONFIG_DEBUG_USER is not set
-CONFIG_DEBUG_ERRORS=y
-# CONFIG_DEBUG_STACK_USAGE is not set
-CONFIG_DEBUG_LL=y
-# CONFIG_DEBUG_ICEDCC is not set
#
# Security options
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
-# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_AUTHENC is not set
# CONFIG_CRYPTO_TEST is not set
@@ -1027,7 +1041,7 @@ CONFIG_CRYPTO=y
#
# Block modes
#
-# CONFIG_CRYPTO_CBC is not set
+CONFIG_CRYPTO_CBC=y
# CONFIG_CRYPTO_CTR is not set
# CONFIG_CRYPTO_CTS is not set
# CONFIG_CRYPTO_ECB is not set
@@ -1046,8 +1060,12 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_CRC32C is not set
# CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
# CONFIG_CRYPTO_SHA1 is not set
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
@@ -1064,7 +1082,7 @@ CONFIG_CRYPTO=y
# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_CAST5 is not set
# CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_DES is not set
+CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_KHAZAD is not set
# CONFIG_CRYPTO_SALSA20 is not set
@@ -1077,24 +1095,31 @@ CONFIG_CRYPTO=y
# Compression
#
# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
-CONFIG_CRC_CCITT=m
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T 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
+CONFIG_NLATTR=y
diff --git a/arch/arm/configs/orion5x_defconfig b/arch/arm/configs/orion5x_defconfig
index 020e6a8a9e5c..5b98f7645119 100644
--- a/arch/arm/configs/orion5x_defconfig
+++ b/arch/arm/configs/orion5x_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc4
-# Fri Aug 22 12:38:51 2008
+# Linux kernel version: 2.6.30-rc4
+# Mon May 4 14:07:25 2009
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -22,8 +22,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
-CONFIG_ZONE_DMA=y
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_VECTORS_BASE=0xffff0000
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -44,10 +42,19 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -55,48 +62,45 @@ CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
CONFIG_EMBEDDED=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
# CONFIG_MARKERS is not set
CONFIG_OPROFILE=y
CONFIG_HAVE_OPROFILE=y
CONFIG_KPROBES=y
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
CONFIG_KRETPROBES=y
-# CONFIG_HAVE_IOREMAP_PROT is not set
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -104,11 +108,8 @@ 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
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -124,7 +125,7 @@ CONFIG_IOSCHED_CFQ=y
CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# System Type
@@ -134,10 +135,10 @@ CONFIG_CLASSIC_RCU=y
# 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_EBSA110 is not set
# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_GEMINI is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_NETX is not set
# CONFIG_ARCH_H720X is not set
@@ -158,14 +159,17 @@ CONFIG_CLASSIC_RCU=y
CONFIG_ARCH_ORION5X=y
# CONFIG_ARCH_PNX4008 is not set
# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MMP is not set
# CONFIG_ARCH_RPC is not set
# CONFIG_ARCH_SA1100 is not set
# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX 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_ARCH_MSM7X00A is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
#
# Orion Implementations
@@ -175,6 +179,7 @@ CONFIG_MACH_RD88F5182=y
CONFIG_MACH_KUROBOX_PRO=y
CONFIG_MACH_DNS323=y
CONFIG_MACH_TS209=y
+CONFIG_MACH_TERASTATION_PRO2=y
CONFIG_MACH_LINKSTATION_PRO=y
CONFIG_MACH_LINKSTATION_MINI=y
CONFIG_MACH_TS409=y
@@ -187,14 +192,6 @@ CONFIG_MACH_WNR854T=y
CONFIG_MACH_RD88F5181L_GE=y
CONFIG_MACH_RD88F5181L_FXO=y
CONFIG_MACH_RD88F6183AP_GE=y
-
-#
-# Boot options
-#
-
-#
-# Power management
-#
CONFIG_PLAT_ORION=y
#
@@ -228,6 +225,8 @@ CONFIG_PCI_SYSCALL=y
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
# CONFIG_PCCARD is not set
#
@@ -237,25 +236,32 @@ CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
CONFIG_PREEMPT=y
CONFIG_HZ=100
CONFIG_AEABI=y
CONFIG_OABI_COMPAT=y
-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM 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_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4096
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_LEDS=y
CONFIG_LEDS_CPU=y
CONFIG_ALIGNMENT_TRAP=y
@@ -270,6 +276,11 @@ CONFIG_CMDLINE=""
# CONFIG_KEXEC is not set
#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
# Floating point emulation
#
@@ -285,13 +296,18 @@ CONFIG_VFP=y
# Userspace binary formats
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
# CONFIG_BINFMT_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
# Power management options
#
-# CONFIG_PM is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SUSPEND is not set
+# CONFIG_APM_EMULATION is not set
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_NET=y
@@ -328,7 +344,7 @@ CONFIG_IP_PNP_BOOTP=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_LRO=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -343,6 +359,15 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+CONFIG_NET_DSA=y
+CONFIG_NET_DSA_TAG_DSA=y
+CONFIG_NET_DSA_TAG_EDSA=y
+# CONFIG_NET_DSA_TAG_TRAILER is not set
+CONFIG_NET_DSA_MV88E6XXX=y
+# CONFIG_NET_DSA_MV88E6060 is not set
+CONFIG_NET_DSA_MV88E6XXX_NEED_PPU=y
+CONFIG_NET_DSA_MV88E6131=y
+CONFIG_NET_DSA_MV88E6123_61_65=y
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -352,27 +377,29 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
#
CONFIG_NET_PKTGEN=m
# CONFIG_NET_TCPPROBE is not set
+# CONFIG_NET_DROP_MONITOR is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
CONFIG_WIRELESS_EXT=y
CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -397,6 +424,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_AFS_PARTS is not set
@@ -450,9 +478,7 @@ CONFIG_MTD_CFI_UTIL=y
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x0
-CONFIG_MTD_PHYSMAP_LEN=0x0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
# CONFIG_MTD_IMPA7 is not set
# CONFIG_MTD_INTEL_VR_NOR is not set
@@ -477,6 +503,7 @@ CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_VERIFY_WRITE=y
# CONFIG_MTD_NAND_ECC_SMC is not set
# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
CONFIG_MTD_NAND_IDS=y
# CONFIG_MTD_NAND_DISKONCHIP is not set
# CONFIG_MTD_NAND_CAFE is not set
@@ -487,6 +514,11 @@ CONFIG_MTD_NAND_ORION=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -507,11 +539,20 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_ATA_OVER_ETH is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -569,7 +610,11 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
@@ -589,6 +634,7 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
@@ -663,6 +709,7 @@ CONFIG_SATA_MV=y
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -670,7 +717,26 @@ CONFIG_NETDEVICES=y
# CONFIG_TUN is not set
# CONFIG_VETH is not set
# CONFIG_ARCNET is not set
-# CONFIG_PHYLIB is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_AX88796 is not set
@@ -680,19 +746,25 @@ CONFIG_MII=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET 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_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
# CONFIG_AMD8111_ETH is not set
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -702,10 +774,12 @@ CONFIG_NET_PCI=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
# CONFIG_SC92031 is not set
+# CONFIG_ATL2 is not set
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
@@ -713,6 +787,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_E1000E is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -727,6 +802,8 @@ CONFIG_MV643XX_ETH=y
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_JME is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_TR is not set
@@ -735,7 +812,10 @@ CONFIG_MV643XX_ETH=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
#
# USB Network Adapters
@@ -819,11 +899,11 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=16
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
-# CONFIG_NVRAM is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_RAW_DRIVER is not set
@@ -886,12 +966,9 @@ CONFIG_I2C_MV64XXX=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_EEPROM_AT24 is not set
-# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -911,14 +988,17 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_F71882FG is not set
# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
@@ -933,10 +1013,15 @@ CONFIG_SENSORS_LM75=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 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_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_DME1737 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
@@ -956,12 +1041,14 @@ CONFIG_SENSORS_LM75=y
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -970,9 +1057,12 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_T7L66XB is not set
-# CONFIG_MFD_TC6387XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
#
# Multimedia devices
@@ -1013,9 +1103,36 @@ CONFIG_HID=y
# USB Input Devices
#
CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
+# CONFIG_HID_PID is not set
# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1030,10 +1147,13 @@ CONFIG_USB=y
CONFIG_USB_DEVICEFS=y
CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
# CONFIG_USB_OTG is not set
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
@@ -1042,12 +1162,15 @@ CONFIG_USB_DEVICE_CLASS=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_USB_EHCI_TT_NEWSCHED=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
# CONFIG_USB_OHCI_HCD is not set
# CONFIG_USB_UHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
#
# USB Device Class drivers
@@ -1055,20 +1178,20 @@ CONFIG_USB_EHCI_TT_NEWSCHED=y
# CONFIG_USB_ACM is not set
CONFIG_USB_PRINTER=y
# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
CONFIG_USB_STORAGE_DATAFAB=y
CONFIG_USB_STORAGE_FREECOM=y
# CONFIG_USB_STORAGE_ISD200 is not set
-CONFIG_USB_STORAGE_DPCM=y
# CONFIG_USB_STORAGE_USBAT is not set
CONFIG_USB_STORAGE_SDDR09=y
CONFIG_USB_STORAGE_SDDR55=y
@@ -1076,7 +1199,6 @@ CONFIG_USB_STORAGE_JUMPSHOT=y
# CONFIG_USB_STORAGE_ALAUDA is not set
# CONFIG_USB_STORAGE_ONETOUCH is not set
# CONFIG_USB_STORAGE_KARMA is not set
-# CONFIG_USB_STORAGE_SIERRA is not set
# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
# CONFIG_USB_LIBUSUAL is not set
@@ -1097,6 +1219,7 @@ CONFIG_USB_STORAGE_JUMPSHOT=y
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
@@ -1104,7 +1227,6 @@ CONFIG_USB_STORAGE_JUMPSHOT=y
# 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
@@ -1114,8 +1236,18 @@ CONFIG_USB_STORAGE_JUMPSHOT=y
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
@@ -1124,7 +1256,10 @@ CONFIG_LEDS_CLASS=y
#
# CONFIG_LEDS_PCA9532 is not set
CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_GPIO_PLATFORM=y
+# CONFIG_LEDS_LP5521 is not set
# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_BD2802 is not set
#
# LED Triggers
@@ -1132,7 +1267,12 @@ CONFIG_LEDS_GPIO=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
@@ -1164,6 +1304,7 @@ CONFIG_RTC_DRV_M41T80=y
# CONFIG_RTC_DRV_M41T80_WDT is not set
CONFIG_RTC_DRV_S35390A=y
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -1173,12 +1314,15 @@ CONFIG_RTC_DRV_S35390A=y
# Platform RTC drivers
#
# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_STK17TA8 is not set
CONFIG_RTC_DRV_M48T86=y
+# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
@@ -1196,16 +1340,12 @@ CONFIG_DMA_ENGINE=y
# DMA Clients
#
# CONFIG_NET_DMA is not set
+# CONFIG_ASYNC_TX_DMA is not set
# CONFIG_DMATEST is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_AUXDISPLAY is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
@@ -1214,14 +1354,25 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_EXT4DEV_FS is not set
+CONFIG_EXT4_FS=m
+# CONFIG_EXT4DEV_COMPAT is not set
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=m
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -1231,6 +1382,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=m
@@ -1254,15 +1410,13 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
#
CONFIG_PROC_FS=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1282,6 +1436,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1290,6 +1445,7 @@ CONFIG_CRAMFS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -1381,13 +1537,16 @@ CONFIG_ENABLE_MUST_CHECK=y
CONFIG_FRAME_WARN=1024
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
CONFIG_SCHEDSTATS=y
# CONFIG_TIMER_STATS is not set
@@ -1411,25 +1570,46 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
CONFIG_FRAME_POINTER=y
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_KPROBES_SANITY_TEST is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set
CONFIG_LATENCYTOP=y
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_HAVE_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_IRQSOFF_TRACER is not set
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
CONFIG_DEBUG_USER=y
CONFIG_DEBUG_ERRORS=y
# CONFIG_DEBUG_STACK_USAGE is not set
@@ -1441,18 +1621,27 @@ CONFIG_DEBUG_LL=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
-CONFIG_ASYNC_CORE=y
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_ALGAPI2=m
+CONFIG_CRYPTO_AEAD2=m
CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=m
+CONFIG_CRYPTO_HASH2=m
+CONFIG_CRYPTO_RNG2=m
+CONFIG_CRYPTO_PCOMP=m
CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=m
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=m
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_AUTHENC is not set
# CONFIG_CRYPTO_TEST is not set
@@ -1521,18 +1710,24 @@ CONFIG_CRYPTO_PCBC=m
# Compression
#
# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_BINARY_PRINTF=y
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
+CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
CONFIG_CRC_ITU_T=m
CONFIG_CRC32=y
@@ -1540,7 +1735,7 @@ CONFIG_CRC32=y
# 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
+CONFIG_NLATTR=y
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
index 65a583ee5df8..2d58b8fe59be 100644
--- a/arch/arm/configs/s3c2410_defconfig
+++ b/arch/arm/configs/s3c2410_defconfig
@@ -1,9 +1,9 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26-rc8
-# Mon Jul 7 16:59:23 2008
+# Linux kernel version: 2.6.30-rc2
#
CONFIG_ARM=y
+CONFIG_HAVE_PWM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
CONFIG_GENERIC_GPIO=y
# CONFIG_GENERIC_TIME is not set
@@ -12,6 +12,7 @@ CONFIG_MMU=y
CONFIG_NO_IOPORT=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_HARDIRQS_SW_RESEND=y
@@ -21,8 +22,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
-CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_VECTORS_BASE=0xffff0000
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -41,11 +41,20 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
CONFIG_IKCONFIG=m
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=16
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -54,31 +63,36 @@ CONFIG_NAMESPACES=y
# CONFIG_IPC_NS is not set
# CONFIG_USER_NS is not set
# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
@@ -88,11 +102,11 @@ CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_DMA_ATTRS is not set
-CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -100,12 +114,10 @@ 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
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -119,7 +131,7 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
+CONFIG_FREEZER=y
#
# System Type
@@ -129,11 +141,10 @@ CONFIG_CLASSIC_RCU=y
# 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_GEMINI is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_NETX is not set
# CONFIG_ARCH_H720X is not set
@@ -145,26 +156,38 @@ CONFIG_CLASSIC_RCU=y
# CONFIG_ARCH_IXP2000 is not set
# CONFIG_ARCH_IXP4XX is not set
# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
# CONFIG_ARCH_KS8695 is not set
# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
# CONFIG_ARCH_MXC is not set
# CONFIG_ARCH_ORION5X is not set
# CONFIG_ARCH_PNX4008 is not set
# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MMP is not set
# CONFIG_ARCH_RPC is not set
# CONFIG_ARCH_SA1100 is not set
CONFIG_ARCH_S3C2410=y
+# CONFIG_ARCH_S3C64XX 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_ARCH_MSM7X00A is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
CONFIG_PLAT_S3C24XX=y
+CONFIG_S3C2410_CLOCK=y
+CONFIG_S3C24XX_DCLK=y
CONFIG_CPU_S3C244X=y
-# CONFIG_S3C24XX_PWM is not set
+CONFIG_S3C24XX_PWM=y
+CONFIG_S3C24XX_GPIO_EXTRA=128
+CONFIG_S3C24XX_GPIO_EXTRA64=y
+CONFIG_S3C24XX_GPIO_EXTRA128=y
CONFIG_PM_SIMTEC=y
CONFIG_S3C2410_DMA=y
# CONFIG_S3C2410_DMA_DEBUG is not set
+CONFIG_S3C24XX_ADC=y
CONFIG_MACH_SMDK=y
CONFIG_PLAT_S3C=y
CONFIG_CPU_LLSERIAL_S3C2410=y
@@ -174,7 +197,8 @@ CONFIG_CPU_LLSERIAL_S3C2440=y
# Boot options
#
# CONFIG_S3C_BOOT_WATCHDOG is not set
-# CONFIG_S3C_BOOT_ERROR_RESET is not set
+CONFIG_S3C_BOOT_ERROR_RESET=y
+CONFIG_S3C_BOOT_UART_FORCE_FIFO=y
#
# Power management
@@ -182,6 +206,8 @@ CONFIG_CPU_LLSERIAL_S3C2440=y
# CONFIG_S3C2410_PM_DEBUG is not set
# CONFIG_S3C2410_PM_CHECK is not set
CONFIG_S3C_LOWLEVEL_UART_PORT=0
+CONFIG_S3C_GPIO_SPACE=0
+CONFIG_S3C_DEV_HSMMC=y
#
# S3C2400 Machines
@@ -190,7 +216,6 @@ CONFIG_CPU_S3C2410=y
CONFIG_CPU_S3C2410_DMA=y
CONFIG_S3C2410_PM=y
CONFIG_S3C2410_GPIO=y
-CONFIG_S3C2410_CLOCK=y
CONFIG_SIMTEC_NOR=y
CONFIG_MACH_BAST_IDE=y
@@ -205,7 +230,7 @@ CONFIG_ARCH_BAST=y
CONFIG_MACH_OTOM=y
CONFIG_MACH_AML_M5900=y
CONFIG_BAST_PC104_IRQ=y
-# CONFIG_MACH_TCT_HAMMER is not set
+CONFIG_MACH_TCT_HAMMER=y
CONFIG_MACH_VR1000=y
CONFIG_MACH_QT2410=y
CONFIG_CPU_S3C2412=y
@@ -215,10 +240,11 @@ CONFIG_S3C2412_PM=y
#
# S3C2412 Machines
#
-# CONFIG_MACH_JIVE is not set
+CONFIG_MACH_JIVE=y
+# CONFIG_MACH_JIVE_SHOW_BOOTLOADER is not set
CONFIG_MACH_SMDK2413=y
CONFIG_MACH_S3C2413=y
-# CONFIG_MACH_SMDK2412 is not set
+CONFIG_MACH_SMDK2412=y
CONFIG_MACH_VSTMS=y
CONFIG_CPU_S3C2440=y
CONFIG_S3C2440_DMA=y
@@ -232,7 +258,7 @@ CONFIG_MACH_RX3715=y
CONFIG_ARCH_S3C2440=y
CONFIG_MACH_NEXCODER_2440=y
CONFIG_SMDK2440_CPU2440=y
-# CONFIG_MACH_AT2440EVB is not set
+CONFIG_MACH_AT2440EVB=y
CONFIG_CPU_S3C2442=y
#
@@ -286,25 +312,31 @@ CONFIG_ISA=y
#
# Kernel Features
#
-# CONFIG_TICK_ONESHOT is not set
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
# CONFIG_PREEMPT is not set
CONFIG_HZ=200
# CONFIG_AEABI is not set
-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM 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_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4096
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_ALIGNMENT_TRAP=y
#
@@ -317,6 +349,11 @@ CONFIG_CMDLINE="root=/dev/hda1 ro init=/bin/bash console=ttySAC0"
# CONFIG_KEXEC is not set
#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
# Floating point emulation
#
@@ -332,6 +369,8 @@ CONFIG_FPE_NWFPE_XP=y
# Userspace binary formats
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
CONFIG_BINFMT_AOUT=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_ARTHUR is not set
@@ -346,10 +385,6 @@ CONFIG_SUSPEND=y
CONFIG_SUSPEND_FREEZER=y
CONFIG_APM_EMULATION=m
CONFIG_ARCH_SUSPEND_POSSIBLE=y
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -359,11 +394,13 @@ CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
+CONFIG_XFRM_USER=m
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
# CONFIG_XFRM_STATISTICS is not set
-# CONFIG_NET_KEY is not set
+CONFIG_XFRM_IPCOMP=m
+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
@@ -372,15 +409,16 @@ 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_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST 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_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=m
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
@@ -388,8 +426,25 @@ 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_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+# CONFIG_DEFAULT_BIC is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_RENO is not set
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
CONFIG_IPV6=m
@@ -413,12 +468,181 @@ CONFIG_IPV6_TUNNEL=m
# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_IPV6_MROUTE is not set
# CONFIG_NETWORK_SECMARK is not set
-# CONFIG_NETFILTER is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_HL=m
+CONFIG_NETFILTER_XT_TARGET_LED=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+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=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_IPV6 is not set
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+# CONFIG_IP_VS_PROTO_TCP is not set
+# CONFIG_IP_VS_PROTO_UDP is not set
+# CONFIG_IP_VS_PROTO_ESP is not set
+# CONFIG_IP_VS_PROTO_AH is not set
+
+#
+# IPVS scheduler
+#
+# CONFIG_IP_VS_RR is not set
+# CONFIG_IP_VS_WRR is not set
+# CONFIG_IP_VS_LC is not set
+# CONFIG_IP_VS_WLC is not set
+# CONFIG_IP_VS_LBLC is not set
+# CONFIG_IP_VS_LBLCR is not set
+# CONFIG_IP_VS_DH is not set
+# CONFIG_IP_VS_SH is not set
+# CONFIG_IP_VS_SED is not set
+# CONFIG_IP_VS_NQ is not set
+
+#
+# IPVS application helper
+#
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_DCCP=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
# CONFIG_IP_DCCP is not set
# CONFIG_IP_SCTP is not set
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -428,8 +652,10 @@ CONFIG_IPV6_TUNNEL=m
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
-CONFIG_NET_SCH_FIFO=y
+CONFIG_NET_CLS_ROUTE=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -451,8 +677,8 @@ CONFIG_BT_HIDP=m
#
# Bluetooth device drivers
#
-CONFIG_BT_HCIUSB=m
-CONFIG_BT_HCIUSB_SCO=y
+# CONFIG_BT_HCIBTUSB is not set
+# CONFIG_BT_HCIBTSDIO is not set
CONFIG_BT_HCIUART=m
CONFIG_BT_HCIUART_H4=y
CONFIG_BT_HCIUART_BCSP=y
@@ -462,35 +688,26 @@ CONFIG_BT_HCIBPA10X=m
CONFIG_BT_HCIBFUSB=m
CONFIG_BT_HCIVHCI=m
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+CONFIG_WIRELESS=y
CONFIG_CFG80211=m
-CONFIG_NL80211=y
+# CONFIG_CFG80211_REG_DEBUG is not set
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
CONFIG_MAC80211=m
#
# Rate control algorithm selection
#
-CONFIG_MAC80211_RC_DEFAULT_PID=y
-# CONFIG_MAC80211_RC_DEFAULT_NONE is not set
-
-#
-# Selecting 'y' for an algorithm will
-#
-
-#
-# build the algorithm into mac80211.
-#
-CONFIG_MAC80211_RC_DEFAULT="pid"
-CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_MINSTREL=y
+# CONFIG_MAC80211_RC_DEFAULT_PID is not set
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT="minstrel"
CONFIG_MAC80211_MESH=y
CONFIG_MAC80211_LEDS=y
-# CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT is not set
-# CONFIG_MAC80211_DEBUG is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -504,7 +721,9 @@ CONFIG_MAC80211_LEDS=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
# CONFIG_DEBUG_DRIVER is not set
# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
@@ -513,6 +732,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
CONFIG_MTD_REDBOOT_PARTS=y
CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
@@ -545,7 +765,7 @@ 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=y
+# 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
@@ -566,8 +786,6 @@ CONFIG_MTD_ROM=y
# CONFIG_MTD_PHYSMAP is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
# CONFIG_MTD_IMPA7 is not set
-CONFIG_MTD_BAST=y
-CONFIG_MTD_BAST_MAXSIZE=4
# CONFIG_MTD_PLATRAM is not set
#
@@ -590,6 +808,7 @@ 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_GPIO is not set
CONFIG_MTD_NAND_IDS=y
CONFIG_MTD_NAND_S3C2410=y
# CONFIG_MTD_NAND_S3C2410_DEBUG is not set
@@ -602,6 +821,11 @@ CONFIG_MTD_NAND_S3C2410=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -620,7 +844,7 @@ CONFIG_BLK_DEV=y
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_UB=m
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
@@ -628,32 +852,40 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_CDROM_PKTCDVD is not set
CONFIG_ATA_OVER_ETH=m
CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=m
+CONFIG_EEPROM_AT25=m
+CONFIG_EEPROM_LEGACY=m
+CONFIG_EEPROM_93CX6=m
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
#
# Please see Documentation/ide/ide.txt for help/info on IDE drives
#
+CONFIG_IDE_ATAPI=y
# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
CONFIG_BLK_DEV_IDETAPE=m
-CONFIG_BLK_DEV_IDEFLOPPY=m
-# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
#
# IDE chipset support/bugfixes
#
-# CONFIG_BLK_DEV_PLATFORM is not set
+CONFIG_BLK_DEV_PLATFORM=y
# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_BLK_DEV_HD is not set
#
# SCSI device support
@@ -699,6 +931,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_IN2000 is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DTC3280 is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GENERIC_NCR5380 is not set
@@ -711,11 +945,13 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_SYM53C416 is not set
# CONFIG_SCSI_T128 is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
# CONFIG_ATA is not set
CONFIG_HAVE_PATA_PLATFORM=y
# CONFIG_MD is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -731,9 +967,14 @@ CONFIG_MII=y
# CONFIG_NET_VENDOR_SMC is not set
# CONFIG_SMC91X is not set
CONFIG_DM9000=y
-# CONFIG_ENC28J60 is not set
CONFIG_DM9000_DEBUGLEVEL=4
+# CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_DNET is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
# CONFIG_HP100 is not set
@@ -742,11 +983,14 @@ CONFIG_DM9000_DEBUGLEVEL=4
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_NET_PCI is not set
# CONFIG_B44 is not set
+# CONFIG_CS89x0 is not set
# CONFIG_NET_POCKET is not set
CONFIG_NETDEV_1000=y
-# CONFIG_E1000E_ENABLED is not set
CONFIG_NETDEV_10000=y
# CONFIG_TR is not set
@@ -755,7 +999,10 @@ CONFIG_NETDEV_10000=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
#
# USB Network Adapters
@@ -778,7 +1025,7 @@ CONFIG_NETDEV_10000=y
# Input device support
#
CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
+CONFIG_INPUT_FF_MEMLESS=m
# CONFIG_INPUT_POLLDEV is not set
#
@@ -789,7 +1036,7 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
+CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_EVBUG is not set
#
@@ -808,20 +1055,88 @@ CONFIG_MOUSE_PS2=y
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_APPLETOUCH is not set
+CONFIG_MOUSE_APPLETOUCH=m
+CONFIG_MOUSE_BCM5974=m
# 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_GPIO is not set
-# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+# CONFIG_JOYSTICK_IFORCE_USB is not set
+# CONFIG_JOYSTICK_IFORCE_232 is not set
+# CONFIG_JOYSTICK_WARRIOR is not set
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_ZHENHUA=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_JOYSTICK_XPAD=m
+CONFIG_JOYSTICK_XPAD_FF=y
+CONFIG_JOYSTICK_XPAD_LEDS=y
# CONFIG_INPUT_TABLET is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+# CONFIG_TOUCHSCREEN_AD7879_SPI is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_HTCPEN is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_WM97XX is not set
+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
+CONFIG_TOUCHSCREEN_USB_EGALAX=y
+CONFIG_TOUCHSCREEN_USB_PANJIT=y
+CONFIG_TOUCHSCREEN_USB_3M=y
+CONFIG_TOUCHSCREEN_USB_ITM=y
+CONFIG_TOUCHSCREEN_USB_ETURBO=y
+CONFIG_TOUCHSCREEN_USB_GUNZE=y
+CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y
+CONFIG_TOUCHSCREEN_USB_IRTOUCH=y
+CONFIG_TOUCHSCREEN_USB_IDEALTEK=y
+CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y
+CONFIG_TOUCHSCREEN_USB_GOTOP=y
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_ATI_REMOTE=m
+CONFIG_INPUT_ATI_REMOTE2=m
+CONFIG_INPUT_KEYSPAN_REMOTE=m
+CONFIG_INPUT_POWERMATE=m
+CONFIG_INPUT_YEALINK=m
+CONFIG_INPUT_CM109=m
+CONFIG_INPUT_UINPUT=m
+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
#
# Hardware I/O ports
@@ -831,12 +1146,15 @@ CONFIG_SERIO_SERPORT=y
# CONFIG_SERIO_PARKBD is not set
CONFIG_SERIO_LIBPS2=y
# CONFIG_SERIO_RAW is not set
-# CONFIG_GAMEPORT is not set
+CONFIG_GAMEPORT=m
+# CONFIG_GAMEPORT_NS558 is not set
+# CONFIG_GAMEPORT_L4 is not set
#
# Character devices
#
CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
@@ -877,14 +1195,17 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
# Non-8250 serial port support
#
CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_UARTS=4
# CONFIG_SERIAL_SAMSUNG_DEBUG is not set
CONFIG_SERIAL_SAMSUNG_CONSOLE=y
CONFIG_SERIAL_S3C2410=y
CONFIG_SERIAL_S3C2412=y
CONFIG_SERIAL_S3C2440=y
+# CONFIG_SERIAL_MAX3100 is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
CONFIG_PRINTER=y
@@ -892,7 +1213,7 @@ CONFIG_PRINTER=y
CONFIG_PPDEV=y
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
-# CONFIG_NVRAM is not set
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
@@ -901,33 +1222,44 @@ CONFIG_DEVPORT=y
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_HELPER_AUTO=y
CONFIG_I2C_ALGOBIT=y
#
# I2C Hardware Bus support
#
-# CONFIG_I2C_ELEKTOR is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
# CONFIG_I2C_GPIO is not set
# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
CONFIG_I2C_S3C2410=y
CONFIG_I2C_SIMTEC=y
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_STUB is not set
# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_ELEKTOR is not set
# CONFIG_I2C_PCA_ISA is not set
# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
#
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-CONFIG_EEPROM_LEGACY=m
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_TPS65010 is not set
+# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -943,6 +1275,7 @@ CONFIG_SPI_MASTER=y
#
CONFIG_SPI_BITBANG=m
# CONFIG_SPI_BUTTERFLY is not set
+CONFIG_SPI_GPIO=m
# CONFIG_SPI_LM70_LLP is not set
CONFIG_SPI_S3C24XX=m
CONFIG_SPI_S3C24XX_GPIO=m
@@ -950,44 +1283,56 @@ CONFIG_SPI_S3C24XX_GPIO=m
#
# SPI Protocol Masters
#
-# CONFIG_EEPROM_AT25 is not set
-# CONFIG_SPI_SPIDEV is not set
-# CONFIG_SPI_TLE62X0 is not set
-CONFIG_HAVE_GPIO_LIB=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_SPI_TLE62X0=m
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
#
-# GPIO Support
+# Memory mapped GPIO expanders:
#
-# CONFIG_DEBUG_GPIO is not set
#
# I2C GPIO expanders:
#
+# CONFIG_GPIO_MAX732X is not set
# CONFIG_GPIO_PCA953X is not set
# CONFIG_GPIO_PCF857X is not set
#
+# PCI GPIO expanders:
+#
+
+#
# SPI GPIO expanders:
#
+# CONFIG_GPIO_MAX7301 is not set
# CONFIG_GPIO_MCP23S08 is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
CONFIG_HWMON_VID=m
+# CONFIG_SENSORS_AD7414 is not set
# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_F71882FG is not set
# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
@@ -1003,10 +1348,16 @@ CONFIG_SENSORS_LM85=m
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_MAX1111 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_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
# CONFIG_SENSORS_DME1737 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
@@ -1022,7 +1373,10 @@ CONFIG_SENSORS_LM85=m
# CONFIG_SENSORS_W83L786NG is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -1043,20 +1397,33 @@ CONFIG_S3C2410_WATCHDOG=y
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
CONFIG_MFD_SM501=y
+# CONFIG_MFD_SM501_GPIO is not set
# CONFIG_MFD_ASIC3 is not set
# CONFIG_HTC_EGPIO is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_UCB1400_CORE is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
#
# Multimedia devices
@@ -1065,14 +1432,189 @@ CONFIG_MFD_SM501=y
#
# Multimedia core support
#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
#
# Multimedia drivers
#
-# CONFIG_DAB is not set
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_MEDIA_TUNER_MXL5007T=m
+CONFIG_MEDIA_TUNER_MC44S803=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_VIVI=m
+CONFIG_VIDEO_PMS=m
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_VIDEO_AU0828=m
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+# CONFIG_USB_VIDEO_CLASS is not set
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+# CONFIG_USB_M5602 is not set
+# CONFIG_USB_STV06XX is not set
+# CONFIG_USB_GSPCA_CONEX is not set
+# CONFIG_USB_GSPCA_ETOMS is not set
+# CONFIG_USB_GSPCA_FINEPIX is not set
+# CONFIG_USB_GSPCA_MARS is not set
+# CONFIG_USB_GSPCA_MR97310A is not set
+# CONFIG_USB_GSPCA_OV519 is not set
+# CONFIG_USB_GSPCA_OV534 is not set
+# CONFIG_USB_GSPCA_PAC207 is not set
+# CONFIG_USB_GSPCA_PAC7311 is not set
+# CONFIG_USB_GSPCA_SONIXB is not set
+# CONFIG_USB_GSPCA_SONIXJ is not set
+# CONFIG_USB_GSPCA_SPCA500 is not set
+# CONFIG_USB_GSPCA_SPCA501 is not set
+# CONFIG_USB_GSPCA_SPCA505 is not set
+# CONFIG_USB_GSPCA_SPCA506 is not set
+# CONFIG_USB_GSPCA_SPCA508 is not set
+# CONFIG_USB_GSPCA_SPCA561 is not set
+# CONFIG_USB_GSPCA_SQ905 is not set
+# CONFIG_USB_GSPCA_SQ905C is not set
+# CONFIG_USB_GSPCA_STK014 is not set
+# CONFIG_USB_GSPCA_SUNPLUS is not set
+# CONFIG_USB_GSPCA_T613 is not set
+# CONFIG_USB_GSPCA_TV8532 is not set
+# CONFIG_USB_GSPCA_VC032X is not set
+# CONFIG_USB_GSPCA_ZC3XX is not set
+# CONFIG_VIDEO_PVRUSB2 is not set
+# CONFIG_VIDEO_HDPVR is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_CX231XX is not set
+# CONFIG_VIDEO_USBVISION is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_QUICKCAM_MESSENGER is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_ZC0301 is not set
+# CONFIG_USB_PWC is not set
+CONFIG_USB_PWC_INPUT_EVDEV=y
+# CONFIG_USB_ZR364XX is not set
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+CONFIG_RADIO_ADAPTERS=y
+CONFIG_RADIO_CADET=m
+CONFIG_RADIO_RTRACK=m
+CONFIG_RADIO_RTRACK2=m
+CONFIG_RADIO_AZTECH=m
+CONFIG_RADIO_GEMTEK=m
+CONFIG_RADIO_SF16FMI=m
+CONFIG_RADIO_SF16FMR2=m
+CONFIG_RADIO_TERRATEC=m
+CONFIG_RADIO_TRUST=m
+CONFIG_RADIO_TYPHOON=m
+CONFIG_RADIO_TYPHOON_PROC_FS=y
+CONFIG_RADIO_ZOLTRIX=m
+CONFIG_USB_DSBR=m
+CONFIG_USB_SI470X=m
+CONFIG_USB_MR800=m
+CONFIG_RADIO_TEA5764=m
+CONFIG_DVB_DYNAMIC_MINORS=y
+CONFIG_DVB_CAPTURE_DRIVERS=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+# CONFIG_DVB_USB_A800 is not set
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+# CONFIG_DVB_USB_GL861 is not set
+# CONFIG_DVB_USB_AU6610 is not set
+# CONFIG_DVB_USB_DIGITV is not set
+# CONFIG_DVB_USB_VP7045 is not set
+# CONFIG_DVB_USB_VP702X is not set
+# CONFIG_DVB_USB_GP8PSK is not set
+# CONFIG_DVB_USB_NOVA_T_USB2 is not set
+# CONFIG_DVB_USB_TTUSB2 is not set
+# CONFIG_DVB_USB_DTT200U is not set
+# CONFIG_DVB_USB_OPERA1 is not set
+CONFIG_DVB_USB_AF9005=m
+# CONFIG_DVB_USB_AF9005_REMOTE is not set
+# CONFIG_DVB_USB_DW2102 is not set
+# CONFIG_DVB_USB_CINERGY_T2 is not set
+# CONFIG_DVB_USB_ANYSEE is not set
+# CONFIG_DVB_USB_DTV5100 is not set
+# CONFIG_DVB_USB_AF9015 is not set
+# CONFIG_DVB_USB_CE6230 is not set
+# CONFIG_DVB_SIANO_SMS1XXX is not set
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+# CONFIG_DVB_B2C2_FLEXCOP is not set
+
+#
+# Supported DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3305=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+CONFIG_DVB_LGS8GL5=m
+CONFIG_DAB=y
+CONFIG_USB_DABUSB=m
#
# Graphics support
@@ -1082,6 +1624,7 @@ CONFIG_MFD_SM501=y
CONFIG_FB=y
CONFIG_FIRMWARE_EDID=y
# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
@@ -1105,7 +1648,19 @@ CONFIG_FB_S3C2410=y
# CONFIG_FB_S3C2410_DEBUG is not set
CONFIG_FB_SM501=y
# CONFIG_FB_VIRTUAL is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=m
+# CONFIG_LCD_LTV350QV is not set
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_TDO24M is not set
+# CONFIG_LCD_VGG2432A4 is not set
+# CONFIG_LCD_PLATFORM is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_GENERIC=m
+CONFIG_BACKLIGHT_PWM=m
#
# Display device support
@@ -1125,11 +1680,54 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
# CONFIG_LOGO is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_JACK=y
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY 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_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=y
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_VMASTER=y
+CONFIG_SND_AC97_CODEC=m
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_CAIAQ=m
+# CONFIG_SND_USB_CAIAQ_INPUT is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_AC97_BUS=y
+CONFIG_SND_S3C24XX_SOC=y
+CONFIG_SND_S3C24XX_SOC_I2S=m
+CONFIG_SND_S3C_I2SV2_SOC=m
+CONFIG_SND_S3C2412_SOC_I2S=m
+CONFIG_SND_S3C2443_SOC_AC97=m
+CONFIG_SND_S3C24XX_SOC_JIVE_WM8750=m
+CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710=m
+CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650=m
+CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X=m
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_AC97_CODEC=m
+CONFIG_SND_SOC_L3=m
+CONFIG_SND_SOC_UDA134X=m
+CONFIG_SND_SOC_WM8750=m
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=y
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
@@ -1139,12 +1737,12 @@ CONFIG_HID=y
# USB Input Devices
#
# CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
#
-# USB HID Boot Protocol drivers
+# Special HID drivers
#
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
+CONFIG_HID_APPLE=m
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1161,19 +1759,26 @@ CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_SUSPEND is not set
# CONFIG_USB_OTG is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
#
# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_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_U132_HCD is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
#
# USB Device Class drivers
@@ -1181,53 +1786,51 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
CONFIG_USB_ACM=m
CONFIG_USB_PRINTER=m
CONFIG_USB_WDM=m
+# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
#
CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_DATAFAB is not set
-# CONFIG_USB_STORAGE_FREECOM is not set
-# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_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_ONETOUCH is not set
-# CONFIG_USB_STORAGE_KARMA is not set
-# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+CONFIG_USB_STORAGE_DATAFAB=m
+CONFIG_USB_STORAGE_FREECOM=m
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_ALAUDA=m
+CONFIG_USB_STORAGE_ONETOUCH=m
+CONFIG_USB_STORAGE_KARMA=m
+CONFIG_USB_STORAGE_CYPRESS_ATACB=m
CONFIG_USB_LIBUSUAL=y
#
# USB Imaging devices
#
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_MICROTEK is not set
-CONFIG_USB_MON=y
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
#
# USB port drivers
#
-# CONFIG_USB_USS720 is not set
+CONFIG_USB_USS720=m
CONFIG_USB_SERIAL=y
# CONFIG_USB_SERIAL_CONSOLE is not set
# CONFIG_USB_EZUSB is not set
CONFIG_USB_SERIAL_GENERIC=y
# CONFIG_USB_SERIAL_AIRCABLE is not set
-# CONFIG_USB_SERIAL_AIRPRIME is not set
# CONFIG_USB_SERIAL_ARK3116 is not set
# CONFIG_USB_SERIAL_BELKIN is not set
# CONFIG_USB_SERIAL_CH341 is not set
# CONFIG_USB_SERIAL_WHITEHEAT is not set
# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
-# CONFIG_USB_SERIAL_CP2101 is not set
+# CONFIG_USB_SERIAL_CP210X is not set
# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
# CONFIG_USB_SERIAL_EMPEG is not set
CONFIG_USB_SERIAL_FTDI_SIO=y
@@ -1251,42 +1854,71 @@ CONFIG_USB_SERIAL_FTDI_SIO=y
CONFIG_USB_SERIAL_NAVMAN=m
CONFIG_USB_SERIAL_PL2303=y
# CONFIG_USB_SERIAL_OTI6858 is not set
+# CONFIG_USB_SERIAL_QUALCOMM is not set
# CONFIG_USB_SERIAL_SPCP8X5 is not set
# CONFIG_USB_SERIAL_HP4X is not set
# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+# CONFIG_USB_SERIAL_SYMBOL is not set
# CONFIG_USB_SERIAL_TI is not set
# CONFIG_USB_SERIAL_CYBERJACK is not set
# CONFIG_USB_SERIAL_XIRCOM is not set
CONFIG_USB_SERIAL_OPTION=m
# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_OPTICON is not set
# CONFIG_USB_SERIAL_DEBUG 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_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_ADUTUX=m
+CONFIG_USB_SEVSEG=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_BERRY_CHARGE=m
CONFIG_USB_LED=m
-# 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_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+CONFIG_USB_APPLEDISPLAY=m
CONFIG_USB_LD=m
-# CONFIG_USB_TRANCEVIBRATOR is not set
-# CONFIG_USB_IOWARRIOR is not set
-# CONFIG_USB_TEST is not set
+CONFIG_USB_TRANCEVIBRATOR=m
+CONFIG_USB_IOWARRIOR=m
+CONFIG_USB_TEST=m
# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
-# CONFIG_MMC is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=m
+CONFIG_MMC_TEST=m
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_SPI=m
+CONFIG_MMC_S3C=y
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=m
@@ -1295,7 +1927,14 @@ CONFIG_LEDS_CLASS=m
#
CONFIG_LEDS_S3C24XX=m
CONFIG_LEDS_H1940=m
-# CONFIG_LEDS_GPIO is not set
+CONFIG_LEDS_PCA9532=m
+CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_GPIO_PLATFORM=y
+CONFIG_LEDS_LP5521=m
+CONFIG_LEDS_PCA955X=m
+CONFIG_LEDS_DAC124S085=m
+CONFIG_LEDS_PWM=m
+CONFIG_LEDS_BD2802=m
#
# LED Triggers
@@ -1304,7 +1943,13 @@ CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=m
# CONFIG_LEDS_TRIGGER_IDE_DISK is not set
CONFIG_LEDS_TRIGGER_HEARTBEAT=m
-# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_GPIO=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
@@ -1335,31 +1980,43 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
# CONFIG_RTC_DRV_MAX6902 is not set
# CONFIG_RTC_DRV_R9701 is not set
# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
#
# Platform RTC drivers
#
# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
# on-CPU RTC drivers
#
CONFIG_RTC_DRV_S3C=y
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_REGULATOR is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
@@ -1370,27 +2027,40 @@ CONFIG_EXT2_FS_POSIX_ACL=y
CONFIG_EXT2_FS_SECURITY=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
+CONFIG_EXT4_FS=m
+# CONFIG_EXT4DEV_COMPAT is not set
+CONFIG_EXT4_FS_XATTR=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+# CONFIG_EXT4_FS_SECURITY is not set
CONFIG_JBD=y
+CONFIG_JBD2=m
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_FUSE_FS is not set
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
CONFIG_GENERIC_ACL=y
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
@@ -1416,15 +2086,13 @@ CONFIG_NTFS_FS=m
#
CONFIG_PROC_FS=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1444,27 +2112,49 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_BIND34 is not set
-# CONFIG_RPCSEC_GSS_KRB5 is not set
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
+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
@@ -1546,6 +2236,11 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1565,14 +2260,39 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
CONFIG_FRAME_POINTER=y
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
CONFIG_DEBUG_USER=y
CONFIG_DEBUG_ERRORS=y
# CONFIG_DEBUG_STACK_USAGE is not set
@@ -1586,19 +2306,29 @@ CONFIG_DEBUG_S3C_UART=0
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_ALGAPI2=m
CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=m
CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=m
CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_HASH2=m
+CONFIG_CRYPTO_RNG2=m
+CONFIG_CRYPTO_PCOMP=m
CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=m
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=m
# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_AUTHENC=m
# CONFIG_CRYPTO_TEST is not set
@@ -1630,10 +2360,14 @@ CONFIG_CRYPTO_HMAC=m
#
# Digest
#
-# CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_CRC32C=m
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=m
# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
CONFIG_CRYPTO_SHA1=m
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
@@ -1663,23 +2397,37 @@ CONFIG_CRYPTO_DES=m
# Compression
#
CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
+CONFIG_CRC16=m
+# CONFIG_CRC_T10DIF is not set
CONFIG_CRC_ITU_T=m
CONFIG_CRC32=y
-# CONFIG_CRC7 is not set
-# CONFIG_LIBCRC32C is not set
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
CONFIG_HAS_IOMEM=y
CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/arm/configs/stmp378x_defconfig b/arch/arm/configs/stmp378x_defconfig
new file mode 100644
index 000000000000..44461f197a17
--- /dev/null
+++ b/arch/arm/configs/stmp378x_defconfig
@@ -0,0 +1,1141 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.30-rc2
+# Thu Apr 23 02:44:13 2009
+#
+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_HAVE_LATENCYTOP_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_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION="-default"
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_INITRAMFS_COMPRESSION_NONE is not set
+CONFIG_INITRAMFS_COMPRESSION_GZIP=y
+# CONFIG_INITRAMFS_COMPRESSION_BZIP2 is not set
+# CONFIG_INITRAMFS_COMPRESSION_LZMA is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_TRACEPOINTS=y
+CONFIG_MARKERS=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_FREEZER is not set
+
+#
+# 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_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_GEMINI 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_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX 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_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+CONFIG_ARCH_STMP3XXX=y
+
+#
+# Freescale STMP3xxx implementations
+#
+# CONFIG_ARCH_STMP37XX is not set
+CONFIG_ARCH_STMP378X=y
+# CONFIG_MACH_STMP37XX is not set
+CONFIG_MACH_STMP378X=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_PABRT_NOIFAR=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=y
+# 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
+CONFIG_COMMON_CLKDEV=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=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HIGHMEM=y
+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_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttySDBG0,115200 mem=32M"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+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 is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=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_VERBOSE=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=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# 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_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_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_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+# CONFIG_NET_SCH_CBQ is not set
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_MULTIQ is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+# CONFIG_NET_SCH_TBF is not set
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_DRR is not set
+
+#
+# Classification
+#
+# CONFIG_NET_CLS_BASIC is not set
+# CONFIG_NET_CLS_TCINDEX is not set
+# CONFIG_NET_CLS_ROUTE4 is not set
+# 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_CLS_FLOW is not set
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_DROP_MONITOR is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_PARTITIONS is not set
+# CONFIG_MTD_TESTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLKDEVS is not set
+# CONFIG_MTD_BLOCK is not set
+# 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
+# CONFIG_MTD_OOPS 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_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=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_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+CONFIG_MTD_UBI_GLUEBI=y
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG 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=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=6144
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE 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=y
+
+#
+# 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=y
+# 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_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_NETDEVICES is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+CONFIG_INPUT_POLLDEV=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
+# CONFIG_INPUT_JOYDEV 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_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_AD7879 is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO 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_TOUCHIT213 is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM 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
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_COMMON=y
+# CONFIG_VIDEO_ALLOW_V4L1 is not set
+# CONFIG_VIDEO_V4L1_COMPAT is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=y
+
+#
+# Multimedia drivers
+#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+
+#
+# Encoders/decoders and other helper chips
+#
+
+#
+# Audio decoders
+#
+
+#
+# RDS decoders
+#
+
+#
+# Video decoders
+#
+
+#
+# Video and audio decoders
+#
+
+#
+# MPEG video encoders
+#
+# CONFIG_VIDEO_CX2341X is not set
+
+#
+# Video encoders
+#
+
+#
+# Video improvement chips
+#
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_SOC_CAMERA is not set
+# CONFIG_RADIO_ADAPTERS 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_BOOT_VESA_SUPPORT 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
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# 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_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_PLATFORM is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+
+#
+# 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 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
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE 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_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+# CONFIG_MISC_FILESYSTEMS is not set
+# CONFIG_NETWORK_FILESYSTEMS 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
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+CONFIG_DEBUG_OBJECTS=y
+CONFIG_DEBUG_OBJECTS_SELFTEST=y
+CONFIG_DEBUG_OBJECTS_FREE=y
+CONFIG_DEBUG_OBJECTS_TIMERS=y
+CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1
+CONFIG_DEBUG_SLAB=y
+CONFIG_DEBUG_SLAB_LEAK=y
+CONFIG_DEBUG_PREEMPT=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_PI_LIST=y
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_LOCK_ALLOC=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_LOCKDEP=y
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_LOCKDEP is not set
+CONFIG_TRACE_IRQFLAGS=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+CONFIG_DEBUG_KOBJECT=y
+# CONFIG_DEBUG_HIGHMEM is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_PAGE_POISONING is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+CONFIG_FUNCTION_TRACER=y
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+CONFIG_CONTEXT_SWITCH_TRACER=y
+# CONFIG_EVENT_TRACER is not set
+CONFIG_BOOT_TRACER=y
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_STACK_TRACER=y
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+CONFIG_BLK_DEV_IO_TRACE=y
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+# CONFIG_SECURITY_TOMOYO is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF 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_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/arm/configs/stmp37xx_defconfig b/arch/arm/configs/stmp37xx_defconfig
new file mode 100644
index 000000000000..401279d531d5
--- /dev/null
+++ b/arch/arm/configs/stmp37xx_defconfig
@@ -0,0 +1,1002 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29.1
+# Mon Apr 20 04:41:26 2009
+#
+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_HAVE_LATENCYTOP_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_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION="-default"
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=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_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_TRACEPOINTS=y
+CONFIG_MARKERS=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_FREEZER is not set
+
+#
+# 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_CLPS711X 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_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X 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_S3C64XX 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_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+CONFIG_ARCH_STMP3XXX=y
+
+#
+# Freescale STMP3xxx implementations
+#
+CONFIG_ARCH_STMP37XX=y
+# CONFIG_ARCH_STMP378X is not set
+CONFIG_MACH_STMP37XX=y
+# CONFIG_MACH_STMP378X is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_PABRT_NOIFAR=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=y
+# 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
+CONFIG_COMMON_CLKDEV=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=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL 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_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttySDBG0,115200 mem=32M lcd_panel=lms350 rdinit=/bin/sh ignore_loglevel"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+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 is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=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_VERBOSE=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=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# 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_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_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_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+# CONFIG_NET_SCH_CBQ is not set
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_MULTIQ is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+# CONFIG_NET_SCH_TBF is not set
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_DRR is not set
+
+#
+# Classification
+#
+# CONFIG_NET_CLS_BASIC is not set
+# CONFIG_NET_CLS_TCINDEX is not set
+# CONFIG_NET_CLS_ROUTE4 is not set
+# 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_CLS_FLOW is not set
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_FIB_RULES=y
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=6144
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE 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=y
+
+#
+# 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=y
+# 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_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_NETDEVICES is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+CONFIG_INPUT_POLLDEV=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
+# CONFIG_INPUT_JOYDEV 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_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_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO 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_TOUCHIT213 is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_UINPUT is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_STMP_DBG is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_COMMON=y
+# CONFIG_VIDEO_ALLOW_V4L1 is not set
+# CONFIG_VIDEO_V4L1_COMPAT is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=y
+
+#
+# Multimedia drivers
+#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+
+#
+# Encoders/decoders and other helper chips
+#
+
+#
+# Audio decoders
+#
+
+#
+# Video decoders
+#
+
+#
+# Video and audio decoders
+#
+
+#
+# MPEG video encoders
+#
+# CONFIG_VIDEO_CX2341X is not set
+
+#
+# Video encoders
+#
+
+#
+# Video improvement chips
+#
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_SOC_CAMERA is not set
+# CONFIG_RADIO_ADAPTERS 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_BOOT_VESA_SUPPORT 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
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# 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_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_PLATFORM is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+
+#
+# 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 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
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA 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_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+# CONFIG_MISC_FILESYSTEMS is not set
+# CONFIG_NETWORK_FILESYSTEMS 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
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_SECTION_MISMATCH=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+# 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_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+CONFIG_FUNCTION_TRACER=y
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_BOOT_TRACER=y
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_STACK_TRACER=y
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF 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_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index 30f463d2fa8a..6ab5dd5868de 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -298,7 +298,6 @@ 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_CPU_FREQ_PXA=y
#
# Floating point emulation
diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index d7da19bcf928..c207504de84d 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -45,13 +45,15 @@ typedef struct user_fp elf_fpregset_t;
#define EF_ARM_HASENTRY 0x00000002 /* All */
#define EF_ARM_RELEXEC 0x00000001 /* All */
-#define R_ARM_NONE 0
-#define R_ARM_PC24 1
-#define R_ARM_ABS32 2
-#define R_ARM_CALL 28
-#define R_ARM_JUMP24 29
-#define R_ARM_V4BX 40
-#define R_ARM_PREL31 42
+#define R_ARM_NONE 0
+#define R_ARM_PC24 1
+#define R_ARM_ABS32 2
+#define R_ARM_CALL 28
+#define R_ARM_JUMP24 29
+#define R_ARM_V4BX 40
+#define R_ARM_PREL31 42
+#define R_ARM_MOVW_ABS_NC 43
+#define R_ARM_MOVT_ABS 44
/*
* These are used to set parameters in the core dumps.
diff --git a/arch/arm/include/asm/hardware/vic.h b/arch/arm/include/asm/hardware/vic.h
index f87328d4a180..5d72550a8097 100644
--- a/arch/arm/include/asm/hardware/vic.h
+++ b/arch/arm/include/asm/hardware/vic.h
@@ -41,7 +41,7 @@
#define VIC_PL192_VECT_ADDR 0xF00
#ifndef __ASSEMBLY__
-void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources);
+void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources);
#endif
#endif
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 110295c5461d..1cd2d6416bda 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -342,7 +342,7 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
return __va(ptr);
}
-#define pmd_page(pmd) virt_to_page(__va(pmd_val(pmd)))
+#define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd)))
/*
* Conversion functions: convert a page and protection to a page entry,
diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h
index 857f1dfac794..321c83e43a1e 100644
--- a/arch/arm/include/asm/tlb.h
+++ b/arch/arm/include/asm/tlb.h
@@ -36,6 +36,8 @@
struct mmu_gather {
struct mm_struct *mm;
unsigned int fullmm;
+ unsigned long range_start;
+ unsigned long range_end;
};
DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
@@ -63,7 +65,19 @@ tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
put_cpu_var(mmu_gathers);
}
-#define tlb_remove_tlb_entry(tlb,ptep,address) do { } while (0)
+/*
+ * Memorize the range for the TLB flush.
+ */
+static inline void
+tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long addr)
+{
+ if (!tlb->fullmm) {
+ if (addr < tlb->range_start)
+ tlb->range_start = addr;
+ if (addr + PAGE_SIZE > tlb->range_end)
+ tlb->range_end = addr + PAGE_SIZE;
+ }
+}
/*
* In the case of tlb vma handling, we can optimise these away in the
@@ -73,15 +87,18 @@ tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
static inline void
tlb_start_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
{
- if (!tlb->fullmm)
+ if (!tlb->fullmm) {
flush_cache_range(vma, vma->vm_start, vma->vm_end);
+ tlb->range_start = TASK_SIZE;
+ tlb->range_end = 0;
+ }
}
static inline void
tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
{
- if (!tlb->fullmm)
- flush_tlb_range(vma, vma->vm_start, vma->vm_end);
+ if (!tlb->fullmm && tlb->range_end > 0)
+ flush_tlb_range(vma, tlb->range_start, tlb->range_end);
}
#define tlb_remove_page(tlb,page) free_page_and_swap_cache(page)
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
index 010618487cf1..94cc58ef61ae 100644
--- a/arch/arm/include/asm/unistd.h
+++ b/arch/arm/include/asm/unistd.h
@@ -387,6 +387,8 @@
#define __NR_dup3 (__NR_SYSCALL_BASE+358)
#define __NR_pipe2 (__NR_SYSCALL_BASE+359)
#define __NR_inotify_init1 (__NR_SYSCALL_BASE+360)
+#define __NR_preadv (__NR_SYSCALL_BASE+361)
+#define __NR_pwritev (__NR_SYSCALL_BASE+362)
/*
* The following SWIs are ARM private.
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 9ca8d13f05f7..1680e9e9c831 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -370,6 +370,8 @@
CALL(sys_dup3)
CALL(sys_pipe2)
/* 360 */ CALL(sys_inotify_init1)
+ CALL(sys_preadv)
+ CALL(sys_pwritev)
#ifndef syscalls_counted
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
#define syscalls_counted
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index d1731e39b496..bac03c81489d 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -169,6 +169,21 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
*(u32 *)loc = offset & 0x7fffffff;
break;
+ case R_ARM_MOVW_ABS_NC:
+ case R_ARM_MOVT_ABS:
+ offset = *(u32 *)loc;
+ offset = ((offset & 0xf0000) >> 4) | (offset & 0xfff);
+ offset = (offset ^ 0x8000) - 0x8000;
+
+ offset += sym->st_value;
+ if (ELF32_R_TYPE(rel->r_info) == R_ARM_MOVT_ABS)
+ offset >>= 16;
+
+ *(u32 *)loc &= 0xfff0f000;
+ *(u32 *)loc |= ((offset & 0xf000) << 4) |
+ (offset & 0x0fff);
+ break;
+
default:
printk(KERN_ERR "%s: unknown relocation: %u\n",
module->name, ELF32_R_TYPE(rel->r_info));
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c
index 42623db7f870..d59a0cd537f0 100644
--- a/arch/arm/kernel/sys_oabi-compat.c
+++ b/arch/arm/kernel/sys_oabi-compat.c
@@ -83,6 +83,7 @@
#include <linux/net.h>
#include <linux/ipc.h>
#include <linux/uaccess.h>
+#include <linux/slab.h>
struct oldabi_stat64 {
unsigned long long st_dev;
@@ -176,21 +177,12 @@ asmlinkage long sys_oabi_fstatat64(int dfd,
int flag)
{
struct kstat stat;
- int error = -EINVAL;
+ int error;
- if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
- goto out;
-
- if (flag & AT_SYMLINK_NOFOLLOW)
- error = vfs_lstat_fd(dfd, filename, &stat);
- else
- error = vfs_stat_fd(dfd, filename, &stat);
-
- if (!error)
- error = cp_oldabi_stat64(&stat, statbuf);
-
-out:
- return error;
+ error = vfs_fstatat(dfd, filename, &stat, flag);
+ if (error)
+ return error;
+ return cp_oldabi_stat64(&stat, statbuf);
}
struct oabi_flock64 {
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index c90f27250ead..6c0779792546 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -141,6 +141,7 @@ SECTIONS
.data : AT(__data_loc) {
_data = .; /* address in memory */
+ _sdata = .;
/*
* first, the init task union, aligned
@@ -192,6 +193,7 @@ SECTIONS
__bss_start = .; /* BSS */
*(.bss)
*(COMMON)
+ __bss_stop = .;
_end = .;
}
/* Stabs debugging sections. */
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
index 1ff1bda0a894..309f3511aa20 100644
--- a/arch/arm/mach-at91/at91rm9200_time.c
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -85,7 +85,7 @@ static struct irqaction at91rm9200_timer_irq = {
.handler = at91rm9200_timer_interrupt
};
-static cycle_t read_clk32k(void)
+static cycle_t read_clk32k(struct clocksource *cs)
{
return read_CRTR();
}
diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
index b63e1d5f1bad..4bd56aee4370 100644
--- a/arch/arm/mach-at91/at91sam926x_time.c
+++ b/arch/arm/mach-at91/at91sam926x_time.c
@@ -31,7 +31,7 @@ static u32 pit_cnt; /* access only w/system irq blocked */
* Clocksource: just a monotonic counter of MCK/16 cycles.
* We don't care whether or not PIT irqs are enabled.
*/
-static cycle_t read_pit_clk(void)
+static cycle_t read_pit_clk(struct clocksource *cs)
{
unsigned long flags;
u32 elapsed;
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c
index e4345106ee57..bac578fe0d3d 100644
--- a/arch/arm/mach-at91/clock.c
+++ b/arch/arm/mach-at91/clock.c
@@ -43,6 +43,25 @@
#define clk_is_sys(x) ((x)->type & CLK_TYPE_SYSTEM)
+/*
+ * Chips have some kind of clocks : group them by functionality
+ */
+#define cpu_has_utmi() ( cpu_is_at91cap9() \
+ || cpu_is_at91sam9rl())
+
+#define cpu_has_800M_plla() (cpu_is_at91sam9g20())
+
+#define cpu_has_pllb() (!cpu_is_at91sam9rl())
+
+#define cpu_has_upll() (0)
+
+/* USB host HS & FS */
+#define cpu_has_uhp() (!cpu_is_at91sam9rl())
+
+/* USB device FS only */
+#define cpu_has_udpfs() (!cpu_is_at91sam9rl())
+
+
static LIST_HEAD(clocks);
static DEFINE_SPINLOCK(clk_lock);
@@ -140,7 +159,7 @@ static struct clk utmi_clk = {
};
static struct clk uhpck = {
.name = "uhpck",
- .parent = &pllb,
+ /*.parent = ... we choose parent at runtime */
.mode = pmc_sys_mode,
};
@@ -173,7 +192,11 @@ static struct clk __init *at91_css_to_clk(unsigned long css)
case AT91_PMC_CSS_PLLA:
return &plla;
case AT91_PMC_CSS_PLLB:
- return &pllb;
+ if (cpu_has_upll())
+ /* CSS_PLLB == CSS_UPLL */
+ return &utmi_clk;
+ else if (cpu_has_pllb())
+ return &pllb;
}
return NULL;
@@ -322,7 +345,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
u32 pckr;
pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
- pckr &= AT91_PMC_CSS_PLLB; /* clock selection */
+ pckr &= AT91_PMC_CSS; /* clock selection */
pckr |= prescale << 2;
at91_sys_write(AT91_PMC_PCKR(clk->id), pckr);
clk->rate_hz = actual;
@@ -361,7 +384,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
}
EXPORT_SYMBOL(clk_set_parent);
-/* establish PCK0..PCK3 parentage and rate */
+/* establish PCK0..PCKN parentage and rate */
static void __init init_programmable_clock(struct clk *clk)
{
struct clk *parent;
@@ -389,11 +412,13 @@ static int at91_clk_show(struct seq_file *s, void *unused)
seq_printf(s, "MOR = %8x\n", at91_sys_read(AT91_CKGR_MOR));
seq_printf(s, "MCFR = %8x\n", at91_sys_read(AT91_CKGR_MCFR));
seq_printf(s, "PLLA = %8x\n", at91_sys_read(AT91_CKGR_PLLAR));
- if (!cpu_is_at91sam9rl())
+ if (cpu_has_pllb())
seq_printf(s, "PLLB = %8x\n", at91_sys_read(AT91_CKGR_PLLBR));
- if (cpu_is_at91cap9() || cpu_is_at91sam9rl())
+ if (cpu_has_utmi())
seq_printf(s, "UCKR = %8x\n", uckr = at91_sys_read(AT91_CKGR_UCKR));
seq_printf(s, "MCKR = %8x\n", at91_sys_read(AT91_PMC_MCKR));
+ if (cpu_has_upll())
+ seq_printf(s, "USB = %8x\n", at91_sys_read(AT91_PMC_USB));
seq_printf(s, "SR = %8x\n", sr = at91_sys_read(AT91_PMC_SR));
seq_printf(s, "\n");
@@ -554,16 +579,60 @@ static struct clk *const standard_pmc_clocks[] __initdata = {
&clk32k,
&main_clk,
&plla,
- &pllb,
-
- /* PLLB children (USB) */
- &udpck,
- &uhpck,
/* MCK */
&mck
};
+/* PLLB generated USB full speed clock init */
+static void __init at91_pllb_usbfs_clock_init(unsigned long main_clock)
+{
+ /*
+ * USB clock init: choose 48 MHz PLLB value,
+ * disable 48MHz clock during usb peripheral suspend.
+ *
+ * REVISIT: assumes MCK doesn't derive from PLLB!
+ */
+ uhpck.parent = &pllb;
+
+ at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M;
+ pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init);
+ if (cpu_is_at91rm9200()) {
+ uhpck.pmc_mask = AT91RM9200_PMC_UHP;
+ udpck.pmc_mask = AT91RM9200_PMC_UDP;
+ at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP);
+ } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
+ uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
+ udpck.pmc_mask = AT91SAM926x_PMC_UDP;
+ } else if (cpu_is_at91cap9()) {
+ uhpck.pmc_mask = AT91CAP9_PMC_UHP;
+ }
+ at91_sys_write(AT91_CKGR_PLLBR, 0);
+
+ udpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
+ uhpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
+}
+
+/* UPLL generated USB full speed clock init */
+static void __init at91_upll_usbfs_clock_init(unsigned long main_clock)
+{
+ /*
+ * USB clock init: choose 480 MHz from UPLL,
+ */
+ unsigned int usbr = AT91_PMC_USBS_UPLL;
+
+ /* Setup divider by 10 to reach 48 MHz */
+ usbr |= ((10 - 1) << 8) & AT91_PMC_OHCIUSBDIV;
+
+ at91_sys_write(AT91_PMC_USB, usbr);
+
+ /* Now set uhpck values */
+ uhpck.parent = &utmi_clk;
+ uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
+ uhpck.rate_hz = utmi_clk.parent->rate_hz;
+ uhpck.rate_hz /= 1 + ((at91_sys_read(AT91_PMC_USB) & AT91_PMC_OHCIUSBDIV) >> 8);
+}
+
int __init at91_clock_init(unsigned long main_clock)
{
unsigned tmp, freq, mckr;
@@ -585,43 +654,37 @@ int __init at91_clock_init(unsigned long main_clock)
/* report if PLLA is more than mildly overclocked */
plla.rate_hz = at91_pll_rate(&plla, main_clock, at91_sys_read(AT91_CKGR_PLLAR));
- if ((!cpu_is_at91sam9g20() && plla.rate_hz > 209000000)
- || (cpu_is_at91sam9g20() && plla.rate_hz > 800000000))
+ if ((!cpu_has_800M_plla() && plla.rate_hz > 209000000)
+ || (cpu_has_800M_plla() && plla.rate_hz > 800000000))
pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000);
- /*
- * USB clock init: choose 48 MHz PLLB value,
- * disable 48MHz clock during usb peripheral suspend.
- *
- * REVISIT: assumes MCK doesn't derive from PLLB!
- */
- at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M;
- pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init);
- if (cpu_is_at91rm9200()) {
- uhpck.pmc_mask = AT91RM9200_PMC_UHP;
- udpck.pmc_mask = AT91RM9200_PMC_UDP;
- at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP);
- } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
- uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
- udpck.pmc_mask = AT91SAM926x_PMC_UDP;
- } else if (cpu_is_at91cap9()) {
- uhpck.pmc_mask = AT91CAP9_PMC_UHP;
+
+ if (cpu_has_upll() && !cpu_has_pllb()) {
+ /* setup UTMI clock as the fourth primary clock
+ * (instead of pllb) */
+ utmi_clk.type |= CLK_TYPE_PRIMARY;
+ utmi_clk.id = 3;
}
- at91_sys_write(AT91_CKGR_PLLBR, 0);
- udpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
- uhpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
/*
* USB HS clock init
*/
- if (cpu_is_at91cap9() || cpu_is_at91sam9rl()) {
+ if (cpu_has_utmi())
/*
* multiplier is hard-wired to 40
* (obtain the USB High Speed 480 MHz when input is 12 MHz)
*/
utmi_clk.rate_hz = 40 * utmi_clk.parent->rate_hz;
- }
+
+ /*
+ * USB FS clock init
+ */
+ if (cpu_has_pllb())
+ at91_pllb_usbfs_clock_init(main_clock);
+ if (cpu_has_upll())
+ /* assumes that we choose UPLL for USB and not PLLA */
+ at91_upll_usbfs_clock_init(main_clock);
/*
* MCK and CPU derive from one of those primary clocks.
@@ -631,21 +694,31 @@ int __init at91_clock_init(unsigned long main_clock)
mck.parent = at91_css_to_clk(mckr & AT91_PMC_CSS);
freq = mck.parent->rate_hz;
freq /= (1 << ((mckr & AT91_PMC_PRES) >> 2)); /* prescale */
- if (cpu_is_at91rm9200())
+ if (cpu_is_at91rm9200()) {
mck.rate_hz = freq / (1 + ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */
- else if (cpu_is_at91sam9g20()) {
+ } else if (cpu_is_at91sam9g20()) {
mck.rate_hz = (mckr & AT91_PMC_MDIV) ?
freq / ((mckr & AT91_PMC_MDIV) >> 7) : freq; /* mdiv ; (x >> 7) = ((x >> 8) * 2) */
if (mckr & AT91_PMC_PDIV)
freq /= 2; /* processor clock division */
- } else
+ } else {
mck.rate_hz = freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */
+ }
/* Register the PMC's standard clocks */
for (i = 0; i < ARRAY_SIZE(standard_pmc_clocks); i++)
list_add_tail(&standard_pmc_clocks[i]->node, &clocks);
- if (cpu_is_at91cap9() || cpu_is_at91sam9rl())
+ if (cpu_has_pllb())
+ list_add_tail(&pllb.node, &clocks);
+
+ if (cpu_has_uhp())
+ list_add_tail(&uhpck.node, &clocks);
+
+ if (cpu_has_udpfs())
+ list_add_tail(&udpck.node, &clocks);
+
+ if (cpu_has_utmi())
list_add_tail(&utmi_clk.node, &clocks);
/* MCK and CPU clock are "always on" */
diff --git a/arch/arm/mach-at91/include/mach/at91_pmc.h b/arch/arm/mach-at91/include/mach/at91_pmc.h
index 9561e33b8a9a..64589eaaaee8 100644
--- a/arch/arm/mach-at91/include/mach/at91_pmc.h
+++ b/arch/arm/mach-at91/include/mach/at91_pmc.h
@@ -23,7 +23,7 @@
#define AT91_PMC_PCK (1 << 0) /* Processor Clock */
#define AT91RM9200_PMC_UDP (1 << 1) /* USB Devcice Port Clock [AT91RM9200 only] */
#define AT91RM9200_PMC_MCKUDP (1 << 2) /* USB Device Port Master Clock Automatic Disable on Suspend [AT91RM9200 only] */
-#define AT91CAP9_PMC_DDR (1 << 2) /* DDR Clock [AT91CAP9 revC only] */
+#define AT91CAP9_PMC_DDR (1 << 2) /* DDR Clock [CAP9 revC & some SAM9 only] */
#define AT91RM9200_PMC_UHP (1 << 4) /* USB Host Port Clock [AT91RM9200 only] */
#define AT91SAM926x_PMC_UHP (1 << 6) /* USB Host Port Clock [AT91SAM926x only] */
#define AT91CAP9_PMC_UHP (1 << 6) /* USB Host Port Clock [AT91CAP9 only] */
@@ -39,11 +39,11 @@
#define AT91_PMC_PCDR (AT91_PMC + 0x14) /* Peripheral Clock Disable Register */
#define AT91_PMC_PCSR (AT91_PMC + 0x18) /* Peripheral Clock Status Register */
-#define AT91_CKGR_UCKR (AT91_PMC + 0x1C) /* UTMI Clock Register [SAM9RL, CAP9] */
+#define AT91_CKGR_UCKR (AT91_PMC + 0x1C) /* UTMI Clock Register [some SAM9, CAP9] */
#define AT91_PMC_UPLLEN (1 << 16) /* UTMI PLL Enable */
#define AT91_PMC_UPLLCOUNT (0xf << 20) /* UTMI PLL Start-up Time */
#define AT91_PMC_BIASEN (1 << 24) /* UTMI BIAS Enable */
-#define AT91_PMC_BIASCOUNT (0xf << 28) /* UTMI PLL Start-up Time */
+#define AT91_PMC_BIASCOUNT (0xf << 28) /* UTMI BIAS Start-up Time */
#define AT91_CKGR_MOR (AT91_PMC + 0x20) /* Main Oscillator Register [not on SAM9RL] */
#define AT91_PMC_MOSCEN (1 << 0) /* Main Oscillator Enable */
@@ -72,6 +72,7 @@
#define AT91_PMC_CSS_MAIN (1 << 0)
#define AT91_PMC_CSS_PLLA (2 << 0)
#define AT91_PMC_CSS_PLLB (3 << 0)
+#define AT91_PMC_CSS_UPLL (3 << 0) /* [some SAM9 only] */
#define AT91_PMC_PRES (7 << 2) /* Master Clock Prescaler */
#define AT91_PMC_PRES_1 (0 << 2)
#define AT91_PMC_PRES_2 (1 << 2)
@@ -88,12 +89,25 @@
#define AT91SAM9_PMC_MDIV_1 (0 << 8) /* [SAM9,CAP9 only] */
#define AT91SAM9_PMC_MDIV_2 (1 << 8)
#define AT91SAM9_PMC_MDIV_4 (2 << 8)
-#define AT91SAM9_PMC_MDIV_6 (3 << 8)
+#define AT91SAM9_PMC_MDIV_6 (3 << 8) /* [some SAM9 only] */
+#define AT91SAM9_PMC_MDIV_3 (3 << 8) /* [some SAM9 only] */
#define AT91_PMC_PDIV (1 << 12) /* Processor Clock Division [some SAM9 only] */
#define AT91_PMC_PDIV_1 (0 << 12)
#define AT91_PMC_PDIV_2 (1 << 12)
+#define AT91_PMC_PLLADIV2 (1 << 12) /* PLLA divisor by 2 [some SAM9 only] */
+#define AT91_PMC_PLLADIV2_OFF (0 << 12)
+#define AT91_PMC_PLLADIV2_ON (1 << 12)
-#define AT91_PMC_PCKR(n) (AT91_PMC + 0x40 + ((n) * 4)) /* Programmable Clock 0-3 Registers */
+#define AT91_PMC_USB (AT91_PMC + 0x38) /* USB Clock Register [some SAM9 only] */
+#define AT91_PMC_USBS (0x1 << 0) /* USB OHCI Input clock selection */
+#define AT91_PMC_USBS_PLLA (0 << 0)
+#define AT91_PMC_USBS_UPLL (1 << 0)
+#define AT91_PMC_OHCIUSBDIV (0xF << 8) /* Divider for USB OHCI Clock */
+
+#define AT91_PMC_PCKR(n) (AT91_PMC + 0x40 + ((n) * 4)) /* Programmable Clock 0-N Registers */
+#define AT91_PMC_CSSMCK (0x1 << 8) /* CSS or Master Clock Selection */
+#define AT91_PMC_CSSMCK_CSS (0 << 8)
+#define AT91_PMC_CSSMCK_MCK (1 << 8)
#define AT91_PMC_IER (AT91_PMC + 0x60) /* Interrupt Enable Register */
#define AT91_PMC_IDR (AT91_PMC + 0x64) /* Interrupt Disable Register */
@@ -102,7 +116,7 @@
#define AT91_PMC_LOCKA (1 << 1) /* PLLA Lock */
#define AT91_PMC_LOCKB (1 << 2) /* PLLB Lock */
#define AT91_PMC_MCKRDY (1 << 3) /* Master Clock */
-#define AT91_PMC_LOCKU (1 << 6) /* UPLL Lock [AT91CAP9 only] */
+#define AT91_PMC_LOCKU (1 << 6) /* UPLL Lock [some SAM9, AT91CAP9 only] */
#define AT91_PMC_OSCSEL (1 << 7) /* Slow Clock Oscillator [AT91CAP9 revC only] */
#define AT91_PMC_PCK0RDY (1 << 8) /* Programmable Clock 0 */
#define AT91_PMC_PCK1RDY (1 << 9) /* Programmable Clock 1 */
diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
index bac988e7a4c3..a9c78bc72b84 100644
--- a/arch/arm/mach-davinci/Kconfig
+++ b/arch/arm/mach-davinci/Kconfig
@@ -4,19 +4,56 @@ menu "TI DaVinci Implementations"
comment "DaVinci Core Type"
-config ARCH_DAVINCI644x
- default y
+config ARCH_DAVINCI_DM644x
bool "DaVinci 644x based system"
comment "DaVinci Board Type"
config MACH_DAVINCI_EVM
- bool "TI DaVinci EVM"
+ bool "TI DM644x EVM"
default y
- depends on ARCH_DAVINCI644x
+ depends on ARCH_DAVINCI_DM644x
help
Configure this option to specify the whether the board used
- for development is a DaVinci EVM
+ for development is a DM644x EVM
+
+
+config DAVINCI_MUX
+ bool "DAVINCI multiplexing support"
+ depends on ARCH_DAVINCI
+ default y
+ help
+ Pin multiplexing support for DAVINCI boards. If your bootloader
+ sets the multiplexing correctly, say N. Otherwise, or if unsure,
+ say Y.
+
+config DAVINCI_MUX_DEBUG
+ bool "Multiplexing debug output"
+ depends on DAVINCI_MUX
+ help
+ Makes the multiplexing functions print out a lot of debug info.
+ This is useful if you want to find out the correct values of the
+ multiplexing registers.
+
+config DAVINCI_MUX_WARNINGS
+ bool "Warn about pins the bootloader didn't set up"
+ depends on DAVINCI_MUX
+ help
+ Choose Y here to warn whenever driver initialization logic needs
+ to change the pin multiplexing setup. When there are no warnings
+ printed, it's safe to deselect DAVINCI_MUX for your product.
+
+config DAVINCI_RESET_CLOCKS
+ bool "Reset unused clocks during boot"
+ depends on ARCH_DAVINCI
+ help
+ Say Y if you want to reset unused clocks during boot.
+ This option saves power, but assumes all drivers are
+ using the clock framework. Broken drivers that do not
+ yet use clock framework may not work with this option.
+ If you are booting from another operating system, you
+ probably do not want this option enabled until your
+ device drivers work properly.
endmenu
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
index 4dc458597f40..1674661942f3 100644
--- a/arch/arm/mach-davinci/Makefile
+++ b/arch/arm/mach-davinci/Makefile
@@ -5,7 +5,12 @@
# Common objects
obj-y := time.o irq.o clock.o serial.o io.o id.o psc.o \
- gpio.o mux.o devices.o usb.o
+ gpio.o devices.o dma.o usb.o
+
+obj-$(CONFIG_DAVINCI_MUX) += mux.o
+
+# Chip specific
+obj-$(CONFIG_ARCH_DAVINCI_DM644x) += dm644x.o
# Board specific
-obj-$(CONFIG_MACH_DAVINCI_EVM) += board-evm.o
+obj-$(CONFIG_MACH_DAVINCI_EVM) += board-dm644x-evm.o
diff --git a/arch/arm/mach-davinci/board-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index 0b97a528902b..b2e7f9c63bc5 100644
--- a/arch/arm/mach-davinci/board-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -15,15 +15,20 @@
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/leds.h>
+#include <linux/memory.h>
+#include <linux/etherdevice.h>
#include <linux/i2c.h>
#include <linux/i2c/pcf857x.h>
#include <linux/i2c/at24.h>
#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/io.h>
+#include <linux/phy.h>
+#include <linux/clk.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
@@ -32,25 +37,34 @@
#include <asm/mach/map.h>
#include <asm/mach/flash.h>
-#include <mach/hardware.h>
+#include <mach/dm644x.h>
#include <mach/common.h>
#include <mach/i2c.h>
+#include <mach/serial.h>
+#include <mach/mux.h>
+#include <mach/psc.h>
+#include <mach/nand.h>
-/* other misc. init functions */
-void __init davinci_psc_init(void);
-void __init davinci_irq_init(void);
-void __init davinci_map_common_io(void);
-void __init davinci_init_common_hw(void);
+#define DM644X_EVM_PHY_MASK (0x2)
+#define DM644X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */
-#if defined(CONFIG_MTD_PHYSMAP) || \
- defined(CONFIG_MTD_PHYSMAP_MODULE)
+#define DAVINCI_CFC_ATA_BASE 0x01C66000
+
+#define DAVINCI_ASYNC_EMIF_CONTROL_BASE 0x01e00000
+#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE 0x02000000
+#define DAVINCI_ASYNC_EMIF_DATA_CE1_BASE 0x04000000
+#define DAVINCI_ASYNC_EMIF_DATA_CE2_BASE 0x06000000
+#define DAVINCI_ASYNC_EMIF_DATA_CE3_BASE 0x08000000
+
+#define LXT971_PHY_ID (0x001378e2)
+#define LXT971_PHY_MASK (0xfffffff0)
static struct mtd_partition davinci_evm_norflash_partitions[] = {
- /* bootloader (U-Boot, etc) in first 4 sectors */
+ /* bootloader (UBL, U-Boot, etc) in first 5 sectors */
{
.name = "bootloader",
.offset = 0,
- .size = 4 * SZ_64K,
+ .size = 5 * SZ_64K,
.mask_flags = MTD_WRITEABLE, /* force read-only */
},
/* bootloader params in the next 1 sectors */
@@ -100,10 +114,89 @@ static struct platform_device davinci_evm_norflash_device = {
.resource = &davinci_evm_norflash_resource,
};
-#endif
+/* DM644x EVM includes a 64 MByte small-page NAND flash (16K blocks).
+ * It may used instead of the (default) NOR chip to boot, using TI's
+ * tools to install the secondary boot loader (UBL) and U-Boot.
+ */
+struct mtd_partition davinci_evm_nandflash_partition[] = {
+ /* Bootloader layout depends on whose u-boot is installed, but we
+ * can hide all the details.
+ * - block 0 for u-boot environment ... in mainline u-boot
+ * - block 1 for UBL (plus up to four backup copies in blocks 2..5)
+ * - blocks 6...? for u-boot
+ * - blocks 16..23 for u-boot environment ... in TI's u-boot
+ */
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = SZ_256K + SZ_128K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* Kernel */
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_4M,
+ .mask_flags = 0,
+ },
+ /* File system (older GIT kernels started this on the 5MB mark) */
+ {
+ .name = "filesystem",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0,
+ }
+ /* A few blocks at end hold a flash BBT ... created by TI's CCS
+ * using flashwriter_nand.out, but ignored by TI's versions of
+ * Linux and u-boot. We boot faster by using them.
+ */
+};
-#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \
- defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE)
+static struct davinci_nand_pdata davinci_evm_nandflash_data = {
+ .parts = davinci_evm_nandflash_partition,
+ .nr_parts = ARRAY_SIZE(davinci_evm_nandflash_partition),
+ .ecc_mode = NAND_ECC_HW,
+ .options = NAND_USE_FLASH_BBT,
+};
+
+static struct resource davinci_evm_nandflash_resource[] = {
+ {
+ .start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE,
+ .end = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_16M - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = DAVINCI_ASYNC_EMIF_CONTROL_BASE,
+ .end = DAVINCI_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device davinci_evm_nandflash_device = {
+ .name = "davinci_nand",
+ .id = 0,
+ .dev = {
+ .platform_data = &davinci_evm_nandflash_data,
+ },
+ .num_resources = ARRAY_SIZE(davinci_evm_nandflash_resource),
+ .resource = davinci_evm_nandflash_resource,
+};
+
+static u64 davinci_fb_dma_mask = DMA_BIT_MASK(32);
+
+static struct platform_device davinci_fb_device = {
+ .name = "davincifb",
+ .id = -1,
+ .dev = {
+ .dma_mask = &davinci_fb_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .num_resources = 0,
+};
+
+static struct platform_device rtc_dev = {
+ .name = "rtc_davinci_evm",
+ .id = -1,
+};
static struct resource ide_resources[] = {
{
@@ -131,8 +224,6 @@ static struct platform_device ide_dev = {
},
};
-#endif
-
/*----------------------------------------------------------------------*/
/*
@@ -311,7 +402,9 @@ evm_u35_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c)
gpio_request(gpio + 7, "nCF_SEL");
gpio_direction_output(gpio + 7, 1);
- /* irlml6401 sustains over 3A, switches 5V in under 8 msec */
+ /* irlml6401 switches over 1A, in under 8 msec;
+ * now it can be managed by nDRV_VBUS ...
+ */
setup_usb(500, 8);
return 0;
@@ -343,14 +436,120 @@ static struct pcf857x_platform_data pcf_data_u35 = {
* - 0x0039, 1 byte NTSC vs PAL (bit 0x80 == PAL)
* - ... newer boards may have more
*/
+static struct memory_accessor *at24_mem_acc;
+
+static void at24_setup(struct memory_accessor *mem_acc, void *context)
+{
+ DECLARE_MAC_BUF(mac_str);
+ char mac_addr[6];
+
+ at24_mem_acc = mem_acc;
+
+ /* Read MAC addr from EEPROM */
+ if (at24_mem_acc->read(at24_mem_acc, mac_addr, 0x7f00, 6) == 6) {
+ printk(KERN_INFO "Read MAC addr from EEPROM: %s\n",
+ print_mac(mac_str, mac_addr));
+ }
+}
+
static struct at24_platform_data eeprom_info = {
.byte_len = (256*1024) / 8,
.page_size = 64,
.flags = AT24_FLAG_ADDR16,
+ .setup = at24_setup,
};
+int dm6446evm_eeprom_read(void *buf, off_t off, size_t count)
+{
+ if (at24_mem_acc)
+ return at24_mem_acc->read(at24_mem_acc, buf, off, count);
+ return -ENODEV;
+}
+EXPORT_SYMBOL(dm6446evm_eeprom_read);
+
+int dm6446evm_eeprom_write(void *buf, off_t off, size_t count)
+{
+ if (at24_mem_acc)
+ return at24_mem_acc->write(at24_mem_acc, buf, off, count);
+ return -ENODEV;
+}
+EXPORT_SYMBOL(dm6446evm_eeprom_write);
+
+/*
+ * MSP430 supports RTC, card detection, input from IR remote, and
+ * a bit more. It triggers interrupts on GPIO(7) from pressing
+ * buttons on the IR remote, and for card detect switches.
+ */
+static struct i2c_client *dm6446evm_msp;
+
+static int dm6446evm_msp_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ dm6446evm_msp = client;
+ return 0;
+}
+
+static int dm6446evm_msp_remove(struct i2c_client *client)
+{
+ dm6446evm_msp = NULL;
+ return 0;
+}
+
+static const struct i2c_device_id dm6446evm_msp_ids[] = {
+ { "dm6446evm_msp", 0, },
+ { /* end of list */ },
+};
+
+static struct i2c_driver dm6446evm_msp_driver = {
+ .driver.name = "dm6446evm_msp",
+ .id_table = dm6446evm_msp_ids,
+ .probe = dm6446evm_msp_probe,
+ .remove = dm6446evm_msp_remove,
+};
+
+static int dm6444evm_msp430_get_pins(void)
+{
+ static const char txbuf[2] = { 2, 4, };
+ char buf[4];
+ struct i2c_msg msg[2] = {
+ {
+ .addr = dm6446evm_msp->addr,
+ .flags = 0,
+ .len = 2,
+ .buf = (void __force *)txbuf,
+ },
+ {
+ .addr = dm6446evm_msp->addr,
+ .flags = I2C_M_RD,
+ .len = 4,
+ .buf = buf,
+ },
+ };
+ int status;
+
+ if (!dm6446evm_msp)
+ return -ENXIO;
+
+ /* Command 4 == get input state, returns port 2 and port3 data
+ * S Addr W [A] len=2 [A] cmd=4 [A]
+ * RS Addr R [A] [len=4] A [cmd=4] A [port2] A [port3] N P
+ */
+ status = i2c_transfer(dm6446evm_msp->adapter, msg, 2);
+ if (status < 0)
+ return status;
+
+ dev_dbg(&dm6446evm_msp->dev,
+ "PINS: %02x %02x %02x %02x\n",
+ buf[0], buf[1], buf[2], buf[3]);
+
+ return (buf[3] << 8) | buf[2];
+}
+
static struct i2c_board_info __initdata i2c_info[] = {
{
+ I2C_BOARD_INFO("dm6446evm_msp", 0x23),
+ },
+ {
I2C_BOARD_INFO("pcf8574", 0x38),
.platform_data = &pcf_data_u2,
},
@@ -368,7 +567,6 @@ static struct i2c_board_info __initdata i2c_info[] = {
},
/* ALSO:
* - tvl320aic33 audio codec (0x1b)
- * - msp430 microcontroller (0x23)
* - tvp5146 video decoder (0x5d)
*/
};
@@ -384,51 +582,109 @@ static struct davinci_i2c_platform_data i2c_pdata = {
static void __init evm_init_i2c(void)
{
davinci_init_i2c(&i2c_pdata);
+ i2c_add_driver(&dm6446evm_msp_driver);
i2c_register_board_info(1, i2c_info, ARRAY_SIZE(i2c_info));
}
static struct platform_device *davinci_evm_devices[] __initdata = {
-#if defined(CONFIG_MTD_PHYSMAP) || \
- defined(CONFIG_MTD_PHYSMAP_MODULE)
- &davinci_evm_norflash_device,
-#endif
-#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \
- defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE)
- &ide_dev,
-#endif
+ &davinci_fb_device,
+ &rtc_dev,
+};
+
+static struct davinci_uart_config uart_config __initdata = {
+ .enabled_uarts = (1 << 0),
};
static void __init
davinci_evm_map_io(void)
{
davinci_map_common_io();
+ dm644x_init();
}
-static __init void davinci_evm_init(void)
+static int davinci_phy_fixup(struct phy_device *phydev)
{
- davinci_psc_init();
+ unsigned int control;
+ /* CRITICAL: Fix for increasing PHY signal drive strength for
+ * TX lockup issue. On DaVinci EVM, the Intel LXT971 PHY
+ * signal strength was low causing TX to fail randomly. The
+ * fix is to Set bit 11 (Increased MII drive strength) of PHY
+ * register 26 (Digital Config register) on this phy. */
+ control = phy_read(phydev, 26);
+ phy_write(phydev, 26, (control | 0x800));
+ return 0;
+}
#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \
defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE)
+#define HAS_ATA 1
+#else
+#define HAS_ATA 0
+#endif
+
#if defined(CONFIG_MTD_PHYSMAP) || \
defined(CONFIG_MTD_PHYSMAP_MODULE)
- printk(KERN_WARNING "WARNING: both IDE and NOR flash are enabled, "
- "but share pins.\n\t Disable IDE for NOR support.\n");
+#define HAS_NOR 1
+#else
+#define HAS_NOR 0
#endif
+
+#if defined(CONFIG_MTD_NAND_DAVINCI) || \
+ defined(CONFIG_MTD_NAND_DAVINCI_MODULE)
+#define HAS_NAND 1
+#else
+#define HAS_NAND 0
#endif
+static __init void davinci_evm_init(void)
+{
+ struct clk *aemif_clk;
+
+ aemif_clk = clk_get(NULL, "aemif");
+ clk_enable(aemif_clk);
+
+ if (HAS_ATA) {
+ if (HAS_NAND || HAS_NOR)
+ pr_warning("WARNING: both IDE and Flash are "
+ "enabled, but they share AEMIF pins.\n"
+ "\tDisable IDE for NAND/NOR support.\n");
+ davinci_cfg_reg(DM644X_HPIEN_DISABLE);
+ davinci_cfg_reg(DM644X_ATAEN);
+ davinci_cfg_reg(DM644X_HDIREN);
+ platform_device_register(&ide_dev);
+ } else if (HAS_NAND || HAS_NOR) {
+ davinci_cfg_reg(DM644X_HPIEN_DISABLE);
+ davinci_cfg_reg(DM644X_ATAEN_DISABLE);
+
+ /* only one device will be jumpered and detected */
+ if (HAS_NAND) {
+ platform_device_register(&davinci_evm_nandflash_device);
+ evm_leds[7].default_trigger = "nand-disk";
+ if (HAS_NOR)
+ pr_warning("WARNING: both NAND and NOR flash "
+ "are enabled; disable one of them.\n");
+ } else if (HAS_NOR)
+ platform_device_register(&davinci_evm_norflash_device);
+ }
+
platform_add_devices(davinci_evm_devices,
ARRAY_SIZE(davinci_evm_devices));
evm_init_i2c();
+
+ davinci_serial_init(&uart_config);
+
+ /* Register the fixup for PHY on DaVinci */
+ phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK,
+ davinci_phy_fixup);
+
}
static __init void davinci_evm_irq_init(void)
{
- davinci_init_common_hw();
davinci_irq_init();
}
-MACHINE_START(DAVINCI_EVM, "DaVinci EVM")
+MACHINE_START(DAVINCI_EVM, "DaVinci DM644x EVM")
/* Maintainer: MontaVista Software <source@mvista.com> */
.phys_io = IO_PHYS,
.io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
index abb92b7eca0c..f0baaa15a57e 100644
--- a/arch/arm/mach-davinci/clock.c
+++ b/arch/arm/mach-davinci/clock.c
@@ -1,7 +1,8 @@
/*
- * TI DaVinci clock config file
+ * Clock and PLL control for DaVinci devices
*
- * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2006-2007 Texas Instruments.
+ * Copyright (C) 2008-2009 Deep Root Systems, LLC
*
* 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
@@ -13,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
+#include <linux/clk.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
@@ -21,98 +23,50 @@
#include <mach/hardware.h>
#include <mach/psc.h>
+#include <mach/cputype.h>
#include "clock.h"
-/* PLL/Reset register offsets */
-#define PLLM 0x110
-
static LIST_HEAD(clocks);
static DEFINE_MUTEX(clocks_mutex);
static DEFINE_SPINLOCK(clockfw_lock);
-static unsigned int commonrate;
-static unsigned int armrate;
-static unsigned int fixedrate = 27000000; /* 27 MHZ */
-
-extern void davinci_psc_config(unsigned int domain, unsigned int id, char enable);
-
-/*
- * Returns a clock. Note that we first try to use device id on the bus
- * and clock name. If this fails, we try to use clock name only.
- */
-struct clk *clk_get(struct device *dev, const char *id)
+static unsigned psc_domain(struct clk *clk)
{
- struct clk *p, *clk = ERR_PTR(-ENOENT);
- int idno;
-
- if (dev == NULL || dev->bus != &platform_bus_type)
- idno = -1;
- else
- idno = to_platform_device(dev)->id;
-
- mutex_lock(&clocks_mutex);
-
- list_for_each_entry(p, &clocks, node) {
- if (p->id == idno &&
- strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
- clk = p;
- goto found;
- }
- }
-
- list_for_each_entry(p, &clocks, node) {
- if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
- clk = p;
- break;
- }
- }
-
-found:
- mutex_unlock(&clocks_mutex);
-
- return clk;
+ return (clk->flags & PSC_DSP)
+ ? DAVINCI_GPSC_DSPDOMAIN
+ : DAVINCI_GPSC_ARMDOMAIN;
}
-EXPORT_SYMBOL(clk_get);
-void clk_put(struct clk *clk)
+static void __clk_enable(struct clk *clk)
{
- if (clk && !IS_ERR(clk))
- module_put(clk->owner);
-}
-EXPORT_SYMBOL(clk_put);
-
-static int __clk_enable(struct clk *clk)
-{
- if (clk->flags & ALWAYS_ENABLED)
- return 0;
-
- davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 1);
- return 0;
+ if (clk->parent)
+ __clk_enable(clk->parent);
+ if (clk->usecount++ == 0 && (clk->flags & CLK_PSC))
+ davinci_psc_config(psc_domain(clk), clk->lpsc, 1);
}
static void __clk_disable(struct clk *clk)
{
- if (clk->usecount)
+ if (WARN_ON(clk->usecount == 0))
return;
-
- davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 0);
+ if (--clk->usecount == 0 && !(clk->flags & CLK_PLL))
+ davinci_psc_config(psc_domain(clk), clk->lpsc, 0);
+ if (clk->parent)
+ __clk_disable(clk->parent);
}
int clk_enable(struct clk *clk)
{
unsigned long flags;
- int ret = 0;
if (clk == NULL || IS_ERR(clk))
return -EINVAL;
- if (clk->usecount++ == 0) {
- spin_lock_irqsave(&clockfw_lock, flags);
- ret = __clk_enable(clk);
- spin_unlock_irqrestore(&clockfw_lock, flags);
- }
+ spin_lock_irqsave(&clockfw_lock, flags);
+ __clk_enable(clk);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
- return ret;
+ return 0;
}
EXPORT_SYMBOL(clk_enable);
@@ -123,11 +77,9 @@ void clk_disable(struct clk *clk)
if (clk == NULL || IS_ERR(clk))
return;
- if (clk->usecount > 0 && !(--clk->usecount)) {
- spin_lock_irqsave(&clockfw_lock, flags);
- __clk_disable(clk);
- spin_unlock_irqrestore(&clockfw_lock, flags);
- }
+ spin_lock_irqsave(&clockfw_lock, flags);
+ __clk_disable(clk);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
}
EXPORT_SYMBOL(clk_disable);
@@ -136,7 +88,7 @@ unsigned long clk_get_rate(struct clk *clk)
if (clk == NULL || IS_ERR(clk))
return -EINVAL;
- return *(clk->rate);
+ return clk->rate;
}
EXPORT_SYMBOL(clk_get_rate);
@@ -145,7 +97,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
if (clk == NULL || IS_ERR(clk))
return -EINVAL;
- return *(clk->rate);
+ return clk->rate;
}
EXPORT_SYMBOL(clk_round_rate);
@@ -164,10 +116,23 @@ int clk_register(struct clk *clk)
if (clk == NULL || IS_ERR(clk))
return -EINVAL;
+ if (WARN(clk->parent && !clk->parent->rate,
+ "CLK: %s parent %s has no rate!\n",
+ clk->name, clk->parent->name))
+ return -EINVAL;
+
mutex_lock(&clocks_mutex);
- list_add(&clk->node, &clocks);
+ list_add_tail(&clk->node, &clocks);
mutex_unlock(&clocks_mutex);
+ /* If rate is already set, use it */
+ if (clk->rate)
+ return 0;
+
+ /* Otherwise, default to parent rate */
+ if (clk->parent)
+ clk->rate = clk->parent->rate;
+
return 0;
}
EXPORT_SYMBOL(clk_register);
@@ -183,84 +148,150 @@ void clk_unregister(struct clk *clk)
}
EXPORT_SYMBOL(clk_unregister);
-static struct clk davinci_clks[] = {
- {
- .name = "ARMCLK",
- .rate = &armrate,
- .lpsc = -1,
- .flags = ALWAYS_ENABLED,
- },
- {
- .name = "UART",
- .rate = &fixedrate,
- .lpsc = DAVINCI_LPSC_UART0,
- },
- {
- .name = "EMACCLK",
- .rate = &commonrate,
- .lpsc = DAVINCI_LPSC_EMAC_WRAPPER,
- },
- {
- .name = "I2CCLK",
- .rate = &fixedrate,
- .lpsc = DAVINCI_LPSC_I2C,
- },
- {
- .name = "IDECLK",
- .rate = &commonrate,
- .lpsc = DAVINCI_LPSC_ATA,
- },
- {
- .name = "McBSPCLK",
- .rate = &commonrate,
- .lpsc = DAVINCI_LPSC_McBSP,
- },
- {
- .name = "MMCSDCLK",
- .rate = &commonrate,
- .lpsc = DAVINCI_LPSC_MMC_SD,
- },
- {
- .name = "SPICLK",
- .rate = &commonrate,
- .lpsc = DAVINCI_LPSC_SPI,
- },
- {
- .name = "gpio",
- .rate = &commonrate,
- .lpsc = DAVINCI_LPSC_GPIO,
- },
- {
- .name = "usb",
- .rate = &commonrate,
- .lpsc = DAVINCI_LPSC_USB,
- },
- {
- .name = "AEMIFCLK",
- .rate = &commonrate,
- .lpsc = DAVINCI_LPSC_AEMIF,
- .usecount = 1,
+#ifdef CONFIG_DAVINCI_RESET_CLOCKS
+/*
+ * Disable any unused clocks left on by the bootloader
+ */
+static int __init clk_disable_unused(void)
+{
+ struct clk *ck;
+
+ spin_lock_irq(&clockfw_lock);
+ list_for_each_entry(ck, &clocks, node) {
+ if (ck->usecount > 0)
+ continue;
+ if (!(ck->flags & CLK_PSC))
+ continue;
+
+ /* ignore if in Disabled or SwRstDisable states */
+ if (!davinci_psc_is_clk_active(ck->lpsc))
+ continue;
+
+ pr_info("Clocks: disable unused %s\n", ck->name);
+ davinci_psc_config(psc_domain(ck), ck->lpsc, 0);
}
-};
+ spin_unlock_irq(&clockfw_lock);
+
+ return 0;
+}
+late_initcall(clk_disable_unused);
+#endif
-int __init davinci_clk_init(void)
+static void clk_sysclk_recalc(struct clk *clk)
{
- struct clk *clkp;
- int count = 0;
- u32 pll_mult;
-
- pll_mult = davinci_readl(DAVINCI_PLL_CNTRL0_BASE + PLLM);
- commonrate = ((pll_mult + 1) * 27000000) / 6;
- armrate = ((pll_mult + 1) * 27000000) / 2;
-
- for (clkp = davinci_clks; count < ARRAY_SIZE(davinci_clks);
- count++, clkp++) {
- clk_register(clkp);
-
- /* Turn on clocks that have been enabled in the
- * table above */
- if (clkp->usecount)
- clk_enable(clkp);
+ u32 v, plldiv;
+ struct pll_data *pll;
+
+ /* If this is the PLL base clock, no more calculations needed */
+ if (clk->pll_data)
+ return;
+
+ if (WARN_ON(!clk->parent))
+ return;
+
+ clk->rate = clk->parent->rate;
+
+ /* Otherwise, the parent must be a PLL */
+ if (WARN_ON(!clk->parent->pll_data))
+ return;
+
+ pll = clk->parent->pll_data;
+
+ /* If pre-PLL, source clock is before the multiplier and divider(s) */
+ if (clk->flags & PRE_PLL)
+ clk->rate = pll->input_rate;
+
+ if (!clk->div_reg)
+ return;
+
+ v = __raw_readl(pll->base + clk->div_reg);
+ if (v & PLLDIV_EN) {
+ plldiv = (v & PLLDIV_RATIO_MASK) + 1;
+ if (plldiv)
+ clk->rate /= plldiv;
+ }
+}
+
+static void __init clk_pll_init(struct clk *clk)
+{
+ u32 ctrl, mult = 1, prediv = 1, postdiv = 1;
+ u8 bypass;
+ struct pll_data *pll = clk->pll_data;
+
+ pll->base = IO_ADDRESS(pll->phys_base);
+ ctrl = __raw_readl(pll->base + PLLCTL);
+ clk->rate = pll->input_rate = clk->parent->rate;
+
+ if (ctrl & PLLCTL_PLLEN) {
+ bypass = 0;
+ mult = __raw_readl(pll->base + PLLM);
+ mult = (mult & PLLM_PLLM_MASK) + 1;
+ } else
+ bypass = 1;
+
+ if (pll->flags & PLL_HAS_PREDIV) {
+ prediv = __raw_readl(pll->base + PREDIV);
+ if (prediv & PLLDIV_EN)
+ prediv = (prediv & PLLDIV_RATIO_MASK) + 1;
+ else
+ prediv = 1;
+ }
+
+ /* pre-divider is fixed, but (some?) chips won't report that */
+ if (cpu_is_davinci_dm355() && pll->num == 1)
+ prediv = 8;
+
+ if (pll->flags & PLL_HAS_POSTDIV) {
+ postdiv = __raw_readl(pll->base + POSTDIV);
+ if (postdiv & PLLDIV_EN)
+ postdiv = (postdiv & PLLDIV_RATIO_MASK) + 1;
+ else
+ postdiv = 1;
+ }
+
+ if (!bypass) {
+ clk->rate /= prediv;
+ clk->rate *= mult;
+ clk->rate /= postdiv;
+ }
+
+ pr_debug("PLL%d: input = %lu MHz [ ",
+ pll->num, clk->parent->rate / 1000000);
+ if (bypass)
+ pr_debug("bypass ");
+ if (prediv > 1)
+ pr_debug("/ %d ", prediv);
+ if (mult > 1)
+ pr_debug("* %d ", mult);
+ if (postdiv > 1)
+ pr_debug("/ %d ", postdiv);
+ pr_debug("] --> %lu MHz output.\n", clk->rate / 1000000);
+}
+
+int __init davinci_clk_init(struct davinci_clk *clocks)
+ {
+ struct davinci_clk *c;
+ struct clk *clk;
+
+ for (c = clocks; c->lk.clk; c++) {
+ clk = c->lk.clk;
+
+ if (clk->pll_data)
+ clk_pll_init(clk);
+
+ /* Calculate rates for PLL-derived clocks */
+ else if (clk->flags & CLK_PLL)
+ clk_sysclk_recalc(clk);
+
+ if (clk->lpsc)
+ clk->flags |= CLK_PSC;
+
+ clkdev_add(&c->lk);
+ clk_register(clk);
+
+ /* Turn on clocks that Linux doesn't otherwise manage */
+ if (clk->flags & ALWAYS_ENABLED)
+ clk_enable(clk);
}
return 0;
@@ -285,12 +316,52 @@ static void davinci_ck_stop(struct seq_file *m, void *v)
{
}
-static int davinci_ck_show(struct seq_file *m, void *v)
+#define CLKNAME_MAX 10 /* longest clock name */
+#define NEST_DELTA 2
+#define NEST_MAX 4
+
+static void
+dump_clock(struct seq_file *s, unsigned nest, struct clk *parent)
{
- struct clk *cp;
+ char *state;
+ char buf[CLKNAME_MAX + NEST_DELTA * NEST_MAX];
+ struct clk *clk;
+ unsigned i;
+
+ if (parent->flags & CLK_PLL)
+ state = "pll";
+ else if (parent->flags & CLK_PSC)
+ state = "psc";
+ else
+ state = "";
+
+ /* <nest spaces> name <pad to end> */
+ memset(buf, ' ', sizeof(buf) - 1);
+ buf[sizeof(buf) - 1] = 0;
+ i = strlen(parent->name);
+ memcpy(buf + nest, parent->name,
+ min(i, (unsigned)(sizeof(buf) - 1 - nest)));
+
+ seq_printf(s, "%s users=%2d %-3s %9ld Hz\n",
+ buf, parent->usecount, state, clk_get_rate(parent));
+ /* REVISIT show device associations too */
+
+ /* cost is now small, but not linear... */
+ list_for_each_entry(clk, &clocks, node) {
+ if (clk->parent == parent)
+ dump_clock(s, nest + NEST_DELTA, clk);
+ }
+}
- list_for_each_entry(cp, &clocks, node)
- seq_printf(m,"%s %d %d\n", cp->name, *(cp->rate), cp->usecount);
+static int davinci_ck_show(struct seq_file *m, void *v)
+{
+ /* Show clock tree; we know the main oscillator is first.
+ * We trust nonzero usecounts equate to PSC enables...
+ */
+ mutex_lock(&clocks_mutex);
+ if (!list_empty(&clocks))
+ dump_clock(m, 0, list_first_entry(&clocks, struct clk, node));
+ mutex_unlock(&clocks_mutex);
return 0;
}
@@ -321,4 +392,4 @@ static int __init davinci_ck_proc_init(void)
}
__initcall(davinci_ck_proc_init);
-#endif /* CONFIG_DEBUG_PROC_FS */
+#endif /* CONFIG_DEBUG_PROC_FS */
diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h
index ed47079a52e4..35736ec202f8 100644
--- a/arch/arm/mach-davinci/clock.h
+++ b/arch/arm/mach-davinci/clock.h
@@ -1,7 +1,8 @@
/*
* TI DaVinci clock definitions
*
- * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2006-2007 Texas Instruments.
+ * Copyright (C) 2008-2009 Deep Root Systems, LLC
*
* 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
@@ -11,23 +12,85 @@
#ifndef __ARCH_ARM_DAVINCI_CLOCK_H
#define __ARCH_ARM_DAVINCI_CLOCK_H
+#include <linux/list.h>
+#include <asm/clkdev.h>
+
+#define DAVINCI_PLL1_BASE 0x01c40800
+#define DAVINCI_PLL2_BASE 0x01c40c00
+#define MAX_PLL 2
+
+/* PLL/Reset register offsets */
+#define PLLCTL 0x100
+#define PLLCTL_PLLEN BIT(0)
+#define PLLCTL_CLKMODE BIT(8)
+
+#define PLLM 0x110
+#define PLLM_PLLM_MASK 0xff
+
+#define PREDIV 0x114
+#define PLLDIV1 0x118
+#define PLLDIV2 0x11c
+#define PLLDIV3 0x120
+#define POSTDIV 0x128
+#define BPDIV 0x12c
+#define PLLCMD 0x138
+#define PLLSTAT 0x13c
+#define PLLALNCTL 0x140
+#define PLLDCHANGE 0x144
+#define PLLCKEN 0x148
+#define PLLCKSTAT 0x14c
+#define PLLSYSTAT 0x150
+#define PLLDIV4 0x160
+#define PLLDIV5 0x164
+#define PLLDIV6 0x168
+#define PLLDIV7 0x16c
+#define PLLDIV8 0x170
+#define PLLDIV9 0x174
+#define PLLDIV_EN BIT(15)
+#define PLLDIV_RATIO_MASK 0x1f
+
+struct pll_data {
+ u32 phys_base;
+ void __iomem *base;
+ u32 num;
+ u32 flags;
+ u32 input_rate;
+};
+#define PLL_HAS_PREDIV 0x01
+#define PLL_HAS_POSTDIV 0x02
+
struct clk {
struct list_head node;
struct module *owner;
const char *name;
- unsigned int *rate;
- int id;
- __s8 usecount;
- __u8 flags;
- __u8 lpsc;
+ unsigned long rate;
+ u8 usecount;
+ u8 flags;
+ u8 lpsc;
+ struct clk *parent;
+ struct pll_data *pll_data;
+ u32 div_reg;
};
/* Clock flags */
-#define RATE_CKCTL 1
-#define RATE_FIXED 2
-#define RATE_PROPAGATES 4
-#define VIRTUAL_CLOCK 8
-#define ALWAYS_ENABLED 16
-#define ENABLE_REG_32BIT 32
+#define ALWAYS_ENABLED BIT(1)
+#define CLK_PSC BIT(2)
+#define PSC_DSP BIT(3) /* PSC uses DSP domain, not ARM */
+#define CLK_PLL BIT(4) /* PLL-derived clock */
+#define PRE_PLL BIT(5) /* source is before PLL mult/div */
+
+struct davinci_clk {
+ struct clk_lookup lk;
+};
+
+#define CLK(dev, con, ck) \
+ { \
+ .lk = { \
+ .dev_id = dev, \
+ .con_id = con, \
+ .clk = ck, \
+ }, \
+ }
+int davinci_clk_init(struct davinci_clk *clocks);
#endif
diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c
index 808633f9f03c..a31370b93dd2 100644
--- a/arch/arm/mach-davinci/devices.c
+++ b/arch/arm/mach-davinci/devices.c
@@ -21,6 +21,10 @@
#include <mach/hardware.h>
#include <mach/i2c.h>
#include <mach/irqs.h>
+#include <mach/cputype.h>
+#include <mach/mux.h>
+
+#define DAVINCI_I2C_BASE 0x01C21000
static struct resource i2c_resources[] = {
{
@@ -43,6 +47,9 @@ static struct platform_device davinci_i2c_device = {
void __init davinci_init_i2c(struct davinci_i2c_platform_data *pdata)
{
+ if (cpu_is_davinci_dm644x())
+ davinci_cfg_reg(DM644X_I2C);
+
davinci_i2c_device.dev.platform_data = pdata;
(void) platform_device_register(&davinci_i2c_device);
}
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
new file mode 100644
index 000000000000..d428ef192eac
--- /dev/null
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -0,0 +1,461 @@
+/*
+ * TI DaVinci DM644x chip specific setup
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * 2007 (c) Deep Root Systems, LLC. 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/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+#include <mach/dm644x.h>
+#include <mach/clock.h>
+#include <mach/cputype.h>
+#include <mach/edma.h>
+#include <mach/irqs.h>
+#include <mach/psc.h>
+#include <mach/mux.h>
+
+#include "clock.h"
+#include "mux.h"
+
+/*
+ * Device specific clocks
+ */
+#define DM644X_REF_FREQ 27000000
+
+static struct pll_data pll1_data = {
+ .num = 1,
+ .phys_base = DAVINCI_PLL1_BASE,
+};
+
+static struct pll_data pll2_data = {
+ .num = 2,
+ .phys_base = DAVINCI_PLL2_BASE,
+};
+
+static struct clk ref_clk = {
+ .name = "ref_clk",
+ .rate = DM644X_REF_FREQ,
+};
+
+static struct clk pll1_clk = {
+ .name = "pll1",
+ .parent = &ref_clk,
+ .pll_data = &pll1_data,
+ .flags = CLK_PLL,
+};
+
+static struct clk pll1_sysclk1 = {
+ .name = "pll1_sysclk1",
+ .parent = &pll1_clk,
+ .flags = CLK_PLL,
+ .div_reg = PLLDIV1,
+};
+
+static struct clk pll1_sysclk2 = {
+ .name = "pll1_sysclk2",
+ .parent = &pll1_clk,
+ .flags = CLK_PLL,
+ .div_reg = PLLDIV2,
+};
+
+static struct clk pll1_sysclk3 = {
+ .name = "pll1_sysclk3",
+ .parent = &pll1_clk,
+ .flags = CLK_PLL,
+ .div_reg = PLLDIV3,
+};
+
+static struct clk pll1_sysclk5 = {
+ .name = "pll1_sysclk5",
+ .parent = &pll1_clk,
+ .flags = CLK_PLL,
+ .div_reg = PLLDIV5,
+};
+
+static struct clk pll1_aux_clk = {
+ .name = "pll1_aux_clk",
+ .parent = &pll1_clk,
+ .flags = CLK_PLL | PRE_PLL,
+};
+
+static struct clk pll1_sysclkbp = {
+ .name = "pll1_sysclkbp",
+ .parent = &pll1_clk,
+ .flags = CLK_PLL | PRE_PLL,
+ .div_reg = BPDIV
+};
+
+static struct clk pll2_clk = {
+ .name = "pll2",
+ .parent = &ref_clk,
+ .pll_data = &pll2_data,
+ .flags = CLK_PLL,
+};
+
+static struct clk pll2_sysclk1 = {
+ .name = "pll2_sysclk1",
+ .parent = &pll2_clk,
+ .flags = CLK_PLL,
+ .div_reg = PLLDIV1,
+};
+
+static struct clk pll2_sysclk2 = {
+ .name = "pll2_sysclk2",
+ .parent = &pll2_clk,
+ .flags = CLK_PLL,
+ .div_reg = PLLDIV2,
+};
+
+static struct clk pll2_sysclkbp = {
+ .name = "pll2_sysclkbp",
+ .parent = &pll2_clk,
+ .flags = CLK_PLL | PRE_PLL,
+ .div_reg = BPDIV
+};
+
+static struct clk dsp_clk = {
+ .name = "dsp",
+ .parent = &pll1_sysclk1,
+ .lpsc = DAVINCI_LPSC_GEM,
+ .flags = PSC_DSP,
+ .usecount = 1, /* REVISIT how to disable? */
+};
+
+static struct clk arm_clk = {
+ .name = "arm",
+ .parent = &pll1_sysclk2,
+ .lpsc = DAVINCI_LPSC_ARM,
+ .flags = ALWAYS_ENABLED,
+};
+
+static struct clk vicp_clk = {
+ .name = "vicp",
+ .parent = &pll1_sysclk2,
+ .lpsc = DAVINCI_LPSC_IMCOP,
+ .flags = PSC_DSP,
+ .usecount = 1, /* REVISIT how to disable? */
+};
+
+static struct clk vpss_master_clk = {
+ .name = "vpss_master",
+ .parent = &pll1_sysclk3,
+ .lpsc = DAVINCI_LPSC_VPSSMSTR,
+ .flags = CLK_PSC,
+};
+
+static struct clk vpss_slave_clk = {
+ .name = "vpss_slave",
+ .parent = &pll1_sysclk3,
+ .lpsc = DAVINCI_LPSC_VPSSSLV,
+};
+
+static struct clk uart0_clk = {
+ .name = "uart0",
+ .parent = &pll1_aux_clk,
+ .lpsc = DAVINCI_LPSC_UART0,
+};
+
+static struct clk uart1_clk = {
+ .name = "uart1",
+ .parent = &pll1_aux_clk,
+ .lpsc = DAVINCI_LPSC_UART1,
+};
+
+static struct clk uart2_clk = {
+ .name = "uart2",
+ .parent = &pll1_aux_clk,
+ .lpsc = DAVINCI_LPSC_UART2,
+};
+
+static struct clk emac_clk = {
+ .name = "emac",
+ .parent = &pll1_sysclk5,
+ .lpsc = DAVINCI_LPSC_EMAC_WRAPPER,
+};
+
+static struct clk i2c_clk = {
+ .name = "i2c",
+ .parent = &pll1_aux_clk,
+ .lpsc = DAVINCI_LPSC_I2C,
+};
+
+static struct clk ide_clk = {
+ .name = "ide",
+ .parent = &pll1_sysclk5,
+ .lpsc = DAVINCI_LPSC_ATA,
+};
+
+static struct clk asp_clk = {
+ .name = "asp0",
+ .parent = &pll1_sysclk5,
+ .lpsc = DAVINCI_LPSC_McBSP,
+};
+
+static struct clk mmcsd_clk = {
+ .name = "mmcsd",
+ .parent = &pll1_sysclk5,
+ .lpsc = DAVINCI_LPSC_MMC_SD,
+};
+
+static struct clk spi_clk = {
+ .name = "spi",
+ .parent = &pll1_sysclk5,
+ .lpsc = DAVINCI_LPSC_SPI,
+};
+
+static struct clk gpio_clk = {
+ .name = "gpio",
+ .parent = &pll1_sysclk5,
+ .lpsc = DAVINCI_LPSC_GPIO,
+};
+
+static struct clk usb_clk = {
+ .name = "usb",
+ .parent = &pll1_sysclk5,
+ .lpsc = DAVINCI_LPSC_USB,
+};
+
+static struct clk vlynq_clk = {
+ .name = "vlynq",
+ .parent = &pll1_sysclk5,
+ .lpsc = DAVINCI_LPSC_VLYNQ,
+};
+
+static struct clk aemif_clk = {
+ .name = "aemif",
+ .parent = &pll1_sysclk5,
+ .lpsc = DAVINCI_LPSC_AEMIF,
+};
+
+static struct clk pwm0_clk = {
+ .name = "pwm0",
+ .parent = &pll1_aux_clk,
+ .lpsc = DAVINCI_LPSC_PWM0,
+};
+
+static struct clk pwm1_clk = {
+ .name = "pwm1",
+ .parent = &pll1_aux_clk,
+ .lpsc = DAVINCI_LPSC_PWM1,
+};
+
+static struct clk pwm2_clk = {
+ .name = "pwm2",
+ .parent = &pll1_aux_clk,
+ .lpsc = DAVINCI_LPSC_PWM2,
+};
+
+static struct clk timer0_clk = {
+ .name = "timer0",
+ .parent = &pll1_aux_clk,
+ .lpsc = DAVINCI_LPSC_TIMER0,
+};
+
+static struct clk timer1_clk = {
+ .name = "timer1",
+ .parent = &pll1_aux_clk,
+ .lpsc = DAVINCI_LPSC_TIMER1,
+};
+
+static struct clk timer2_clk = {
+ .name = "timer2",
+ .parent = &pll1_aux_clk,
+ .lpsc = DAVINCI_LPSC_TIMER2,
+ .usecount = 1, /* REVISIT: why cant' this be disabled? */
+};
+
+struct davinci_clk dm644x_clks[] = {
+ CLK(NULL, "ref", &ref_clk),
+ CLK(NULL, "pll1", &pll1_clk),
+ CLK(NULL, "pll1_sysclk1", &pll1_sysclk1),
+ CLK(NULL, "pll1_sysclk2", &pll1_sysclk2),
+ CLK(NULL, "pll1_sysclk3", &pll1_sysclk3),
+ CLK(NULL, "pll1_sysclk5", &pll1_sysclk5),
+ CLK(NULL, "pll1_aux", &pll1_aux_clk),
+ CLK(NULL, "pll1_sysclkbp", &pll1_sysclkbp),
+ CLK(NULL, "pll2", &pll2_clk),
+ CLK(NULL, "pll2_sysclk1", &pll2_sysclk1),
+ CLK(NULL, "pll2_sysclk2", &pll2_sysclk2),
+ CLK(NULL, "pll2_sysclkbp", &pll2_sysclkbp),
+ CLK(NULL, "dsp", &dsp_clk),
+ CLK(NULL, "arm", &arm_clk),
+ CLK(NULL, "vicp", &vicp_clk),
+ CLK(NULL, "vpss_master", &vpss_master_clk),
+ CLK(NULL, "vpss_slave", &vpss_slave_clk),
+ CLK(NULL, "arm", &arm_clk),
+ CLK(NULL, "uart0", &uart0_clk),
+ CLK(NULL, "uart1", &uart1_clk),
+ CLK(NULL, "uart2", &uart2_clk),
+ CLK("davinci_emac.1", NULL, &emac_clk),
+ CLK("i2c_davinci.1", NULL, &i2c_clk),
+ CLK("palm_bk3710", NULL, &ide_clk),
+ CLK("soc-audio.0", NULL, &asp_clk),
+ CLK("davinci_mmc.0", NULL, &mmcsd_clk),
+ CLK(NULL, "spi", &spi_clk),
+ CLK(NULL, "gpio", &gpio_clk),
+ CLK(NULL, "usb", &usb_clk),
+ CLK(NULL, "vlynq", &vlynq_clk),
+ CLK(NULL, "aemif", &aemif_clk),
+ CLK(NULL, "pwm0", &pwm0_clk),
+ CLK(NULL, "pwm1", &pwm1_clk),
+ CLK(NULL, "pwm2", &pwm2_clk),
+ CLK(NULL, "timer0", &timer0_clk),
+ CLK(NULL, "timer1", &timer1_clk),
+ CLK("watchdog", NULL, &timer2_clk),
+ CLK(NULL, NULL, NULL),
+};
+
+#if defined(CONFIG_TI_DAVINCI_EMAC) || defined(CONFIG_TI_DAVINCI_EMAC_MODULE)
+
+static struct resource dm644x_emac_resources[] = {
+ {
+ .start = DM644X_EMAC_BASE,
+ .end = DM644X_EMAC_BASE + 0x47ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_EMACINT,
+ .end = IRQ_EMACINT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device dm644x_emac_device = {
+ .name = "davinci_emac",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(dm644x_emac_resources),
+ .resource = dm644x_emac_resources,
+};
+
+#endif
+
+/*
+ * Device specific mux setup
+ *
+ * soc description mux mode mode mux dbg
+ * reg offset mask mode
+ */
+static const struct mux_config dm644x_pins[] = {
+MUX_CFG(DM644X, HDIREN, 0, 16, 1, 1, true)
+MUX_CFG(DM644X, ATAEN, 0, 17, 1, 1, true)
+MUX_CFG(DM644X, ATAEN_DISABLE, 0, 17, 1, 0, true)
+
+MUX_CFG(DM644X, HPIEN_DISABLE, 0, 29, 1, 0, true)
+
+MUX_CFG(DM644X, AEAW, 0, 0, 31, 31, true)
+
+MUX_CFG(DM644X, MSTK, 1, 9, 1, 0, false)
+
+MUX_CFG(DM644X, I2C, 1, 7, 1, 1, false)
+
+MUX_CFG(DM644X, MCBSP, 1, 10, 1, 1, false)
+
+MUX_CFG(DM644X, UART1, 1, 1, 1, 1, true)
+MUX_CFG(DM644X, UART2, 1, 2, 1, 1, true)
+
+MUX_CFG(DM644X, PWM0, 1, 4, 1, 1, false)
+
+MUX_CFG(DM644X, PWM1, 1, 5, 1, 1, false)
+
+MUX_CFG(DM644X, PWM2, 1, 6, 1, 1, false)
+
+MUX_CFG(DM644X, VLYNQEN, 0, 15, 1, 1, false)
+MUX_CFG(DM644X, VLSCREN, 0, 14, 1, 1, false)
+MUX_CFG(DM644X, VLYNQWD, 0, 12, 3, 3, false)
+
+MUX_CFG(DM644X, EMACEN, 0, 31, 1, 1, true)
+
+MUX_CFG(DM644X, GPIO3V, 0, 31, 1, 0, true)
+
+MUX_CFG(DM644X, GPIO0, 0, 24, 1, 0, true)
+MUX_CFG(DM644X, GPIO3, 0, 25, 1, 0, false)
+MUX_CFG(DM644X, GPIO43_44, 1, 7, 1, 0, false)
+MUX_CFG(DM644X, GPIO46_47, 0, 22, 1, 0, true)
+
+MUX_CFG(DM644X, RGB666, 0, 22, 1, 1, true)
+
+MUX_CFG(DM644X, LOEEN, 0, 24, 1, 1, true)
+MUX_CFG(DM644X, LFLDEN, 0, 25, 1, 1, false)
+};
+
+
+/*----------------------------------------------------------------------*/
+
+static const s8 dma_chan_dm644x_no_event[] = {
+ 0, 1, 12, 13, 14,
+ 15, 25, 30, 31, 45,
+ 46, 47, 55, 56, 57,
+ 58, 59, 60, 61, 62,
+ 63,
+ -1
+};
+
+static struct edma_soc_info dm644x_edma_info = {
+ .n_channel = 64,
+ .n_region = 4,
+ .n_slot = 128,
+ .n_tc = 2,
+ .noevent = dma_chan_dm644x_no_event,
+};
+
+static struct resource edma_resources[] = {
+ {
+ .name = "edma_cc",
+ .start = 0x01c00000,
+ .end = 0x01c00000 + SZ_64K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "edma_tc0",
+ .start = 0x01c10000,
+ .end = 0x01c10000 + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "edma_tc1",
+ .start = 0x01c10400,
+ .end = 0x01c10400 + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_CCINT0,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_CCERRINT,
+ .flags = IORESOURCE_IRQ,
+ },
+ /* not using TC*_ERR */
+};
+
+static struct platform_device dm644x_edma_device = {
+ .name = "edma",
+ .id = -1,
+ .dev.platform_data = &dm644x_edma_info,
+ .num_resources = ARRAY_SIZE(edma_resources),
+ .resource = edma_resources,
+};
+
+/*----------------------------------------------------------------------*/
+void __init dm644x_init(void)
+{
+ davinci_clk_init(dm644x_clks);
+ davinci_mux_register(dm644x_pins, ARRAY_SIZE(dm644x_pins));
+}
+
+static int __init dm644x_init_devices(void)
+{
+ if (!cpu_is_davinci_dm644x())
+ return 0;
+
+ platform_device_register(&dm644x_edma_device);
+ return 0;
+}
+postcore_initcall(dm644x_init_devices);
diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c
new file mode 100644
index 000000000000..15e9eb158bb7
--- /dev/null
+++ b/arch/arm/mach-davinci/dma.c
@@ -0,0 +1,1135 @@
+/*
+ * EDMA3 support for DaVinci
+ *
+ * Copyright (C) 2006-2009 Texas Instruments.
+ *
+ * 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.
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/compiler.h>
+#include <linux/io.h>
+
+#include <mach/cputype.h>
+#include <mach/memory.h>
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/edma.h>
+#include <mach/mux.h>
+
+
+/* Offsets matching "struct edmacc_param" */
+#define PARM_OPT 0x00
+#define PARM_SRC 0x04
+#define PARM_A_B_CNT 0x08
+#define PARM_DST 0x0c
+#define PARM_SRC_DST_BIDX 0x10
+#define PARM_LINK_BCNTRLD 0x14
+#define PARM_SRC_DST_CIDX 0x18
+#define PARM_CCNT 0x1c
+
+#define PARM_SIZE 0x20
+
+/* Offsets for EDMA CC global channel registers and their shadows */
+#define SH_ER 0x00 /* 64 bits */
+#define SH_ECR 0x08 /* 64 bits */
+#define SH_ESR 0x10 /* 64 bits */
+#define SH_CER 0x18 /* 64 bits */
+#define SH_EER 0x20 /* 64 bits */
+#define SH_EECR 0x28 /* 64 bits */
+#define SH_EESR 0x30 /* 64 bits */
+#define SH_SER 0x38 /* 64 bits */
+#define SH_SECR 0x40 /* 64 bits */
+#define SH_IER 0x50 /* 64 bits */
+#define SH_IECR 0x58 /* 64 bits */
+#define SH_IESR 0x60 /* 64 bits */
+#define SH_IPR 0x68 /* 64 bits */
+#define SH_ICR 0x70 /* 64 bits */
+#define SH_IEVAL 0x78
+#define SH_QER 0x80
+#define SH_QEER 0x84
+#define SH_QEECR 0x88
+#define SH_QEESR 0x8c
+#define SH_QSER 0x90
+#define SH_QSECR 0x94
+#define SH_SIZE 0x200
+
+/* Offsets for EDMA CC global registers */
+#define EDMA_REV 0x0000
+#define EDMA_CCCFG 0x0004
+#define EDMA_QCHMAP 0x0200 /* 8 registers */
+#define EDMA_DMAQNUM 0x0240 /* 8 registers (4 on OMAP-L1xx) */
+#define EDMA_QDMAQNUM 0x0260
+#define EDMA_QUETCMAP 0x0280
+#define EDMA_QUEPRI 0x0284
+#define EDMA_EMR 0x0300 /* 64 bits */
+#define EDMA_EMCR 0x0308 /* 64 bits */
+#define EDMA_QEMR 0x0310
+#define EDMA_QEMCR 0x0314
+#define EDMA_CCERR 0x0318
+#define EDMA_CCERRCLR 0x031c
+#define EDMA_EEVAL 0x0320
+#define EDMA_DRAE 0x0340 /* 4 x 64 bits*/
+#define EDMA_QRAE 0x0380 /* 4 registers */
+#define EDMA_QUEEVTENTRY 0x0400 /* 2 x 16 registers */
+#define EDMA_QSTAT 0x0600 /* 2 registers */
+#define EDMA_QWMTHRA 0x0620
+#define EDMA_QWMTHRB 0x0624
+#define EDMA_CCSTAT 0x0640
+
+#define EDMA_M 0x1000 /* global channel registers */
+#define EDMA_ECR 0x1008
+#define EDMA_ECRH 0x100C
+#define EDMA_SHADOW0 0x2000 /* 4 regions shadowing global channels */
+#define EDMA_PARM 0x4000 /* 128 param entries */
+
+#define DAVINCI_DMA_3PCC_BASE 0x01C00000
+
+#define PARM_OFFSET(param_no) (EDMA_PARM + ((param_no) << 5))
+
+#define EDMA_MAX_DMACH 64
+#define EDMA_MAX_PARAMENTRY 512
+#define EDMA_MAX_EVQUE 2 /* FIXME too small */
+
+
+/*****************************************************************************/
+
+static void __iomem *edmacc_regs_base;
+
+static inline unsigned int edma_read(int offset)
+{
+ return (unsigned int)__raw_readl(edmacc_regs_base + offset);
+}
+
+static inline void edma_write(int offset, int val)
+{
+ __raw_writel(val, edmacc_regs_base + offset);
+}
+static inline void edma_modify(int offset, unsigned and, unsigned or)
+{
+ unsigned val = edma_read(offset);
+ val &= and;
+ val |= or;
+ edma_write(offset, val);
+}
+static inline void edma_and(int offset, unsigned and)
+{
+ unsigned val = edma_read(offset);
+ val &= and;
+ edma_write(offset, val);
+}
+static inline void edma_or(int offset, unsigned or)
+{
+ unsigned val = edma_read(offset);
+ val |= or;
+ edma_write(offset, val);
+}
+static inline unsigned int edma_read_array(int offset, int i)
+{
+ return edma_read(offset + (i << 2));
+}
+static inline void edma_write_array(int offset, int i, unsigned val)
+{
+ edma_write(offset + (i << 2), val);
+}
+static inline void edma_modify_array(int offset, int i,
+ unsigned and, unsigned or)
+{
+ edma_modify(offset + (i << 2), and, or);
+}
+static inline void edma_or_array(int offset, int i, unsigned or)
+{
+ edma_or(offset + (i << 2), or);
+}
+static inline void edma_or_array2(int offset, int i, int j, unsigned or)
+{
+ edma_or(offset + ((i*2 + j) << 2), or);
+}
+static inline void edma_write_array2(int offset, int i, int j, unsigned val)
+{
+ edma_write(offset + ((i*2 + j) << 2), val);
+}
+static inline unsigned int edma_shadow0_read(int offset)
+{
+ return edma_read(EDMA_SHADOW0 + offset);
+}
+static inline unsigned int edma_shadow0_read_array(int offset, int i)
+{
+ return edma_read(EDMA_SHADOW0 + offset + (i << 2));
+}
+static inline void edma_shadow0_write(int offset, unsigned val)
+{
+ edma_write(EDMA_SHADOW0 + offset, val);
+}
+static inline void edma_shadow0_write_array(int offset, int i, unsigned val)
+{
+ edma_write(EDMA_SHADOW0 + offset + (i << 2), val);
+}
+static inline unsigned int edma_parm_read(int offset, int param_no)
+{
+ return edma_read(EDMA_PARM + offset + (param_no << 5));
+}
+static inline void edma_parm_write(int offset, int param_no, unsigned val)
+{
+ edma_write(EDMA_PARM + offset + (param_no << 5), val);
+}
+static inline void edma_parm_modify(int offset, int param_no,
+ unsigned and, unsigned or)
+{
+ edma_modify(EDMA_PARM + offset + (param_no << 5), and, or);
+}
+static inline void edma_parm_and(int offset, int param_no, unsigned and)
+{
+ edma_and(EDMA_PARM + offset + (param_no << 5), and);
+}
+static inline void edma_parm_or(int offset, int param_no, unsigned or)
+{
+ edma_or(EDMA_PARM + offset + (param_no << 5), or);
+}
+
+/*****************************************************************************/
+
+/* actual number of DMA channels and slots on this silicon */
+static unsigned num_channels;
+static unsigned num_slots;
+
+static struct dma_interrupt_data {
+ void (*callback)(unsigned channel, unsigned short ch_status,
+ void *data);
+ void *data;
+} intr_data[EDMA_MAX_DMACH];
+
+/* The edma_inuse bit for each PaRAM slot is clear unless the
+ * channel is in use ... by ARM or DSP, for QDMA, or whatever.
+ */
+static DECLARE_BITMAP(edma_inuse, EDMA_MAX_PARAMENTRY);
+
+/* The edma_noevent bit for each channel is clear unless
+ * it doesn't trigger DMA events on this platform. It uses a
+ * bit of SOC-specific initialization code.
+ */
+static DECLARE_BITMAP(edma_noevent, EDMA_MAX_DMACH);
+
+/* dummy param set used to (re)initialize parameter RAM slots */
+static const struct edmacc_param dummy_paramset = {
+ .link_bcntrld = 0xffff,
+ .ccnt = 1,
+};
+
+static const int __initconst
+queue_tc_mapping[EDMA_MAX_EVQUE + 1][2] = {
+/* {event queue no, TC no} */
+ {0, 0},
+ {1, 1},
+ {-1, -1}
+};
+
+static const int __initconst
+queue_priority_mapping[EDMA_MAX_EVQUE + 1][2] = {
+ /* {event queue no, Priority} */
+ {0, 3},
+ {1, 7},
+ {-1, -1}
+};
+
+/*****************************************************************************/
+
+static void map_dmach_queue(unsigned ch_no, enum dma_event_q queue_no)
+{
+ int bit = (ch_no & 0x7) * 4;
+
+ /* default to low priority queue */
+ if (queue_no == EVENTQ_DEFAULT)
+ queue_no = EVENTQ_1;
+
+ queue_no &= 7;
+ edma_modify_array(EDMA_DMAQNUM, (ch_no >> 3),
+ ~(0x7 << bit), queue_no << bit);
+}
+
+static void __init map_queue_tc(int queue_no, int tc_no)
+{
+ int bit = queue_no * 4;
+ edma_modify(EDMA_QUETCMAP, ~(0x7 << bit), ((tc_no & 0x7) << bit));
+}
+
+static void __init assign_priority_to_queue(int queue_no, int priority)
+{
+ int bit = queue_no * 4;
+ edma_modify(EDMA_QUEPRI, ~(0x7 << bit), ((priority & 0x7) << bit));
+}
+
+static inline void
+setup_dma_interrupt(unsigned lch,
+ void (*callback)(unsigned channel, u16 ch_status, void *data),
+ void *data)
+{
+ if (!callback) {
+ edma_shadow0_write_array(SH_IECR, lch >> 5,
+ (1 << (lch & 0x1f)));
+ }
+
+ intr_data[lch].callback = callback;
+ intr_data[lch].data = data;
+
+ if (callback) {
+ edma_shadow0_write_array(SH_ICR, lch >> 5,
+ (1 << (lch & 0x1f)));
+ edma_shadow0_write_array(SH_IESR, lch >> 5,
+ (1 << (lch & 0x1f)));
+ }
+}
+
+/******************************************************************************
+ *
+ * DMA interrupt handler
+ *
+ *****************************************************************************/
+static irqreturn_t dma_irq_handler(int irq, void *data)
+{
+ int i;
+ unsigned int cnt = 0;
+
+ dev_dbg(data, "dma_irq_handler\n");
+
+ if ((edma_shadow0_read_array(SH_IPR, 0) == 0)
+ && (edma_shadow0_read_array(SH_IPR, 1) == 0))
+ return IRQ_NONE;
+
+ while (1) {
+ int j;
+ if (edma_shadow0_read_array(SH_IPR, 0))
+ j = 0;
+ else if (edma_shadow0_read_array(SH_IPR, 1))
+ j = 1;
+ else
+ break;
+ dev_dbg(data, "IPR%d %08x\n", j,
+ edma_shadow0_read_array(SH_IPR, j));
+ for (i = 0; i < 32; i++) {
+ int k = (j << 5) + i;
+ if (edma_shadow0_read_array(SH_IPR, j) & (1 << i)) {
+ /* Clear the corresponding IPR bits */
+ edma_shadow0_write_array(SH_ICR, j, (1 << i));
+ if (intr_data[k].callback) {
+ intr_data[k].callback(k, DMA_COMPLETE,
+ intr_data[k].data);
+ }
+ }
+ }
+ cnt++;
+ if (cnt > 10)
+ break;
+ }
+ edma_shadow0_write(SH_IEVAL, 1);
+ return IRQ_HANDLED;
+}
+
+/******************************************************************************
+ *
+ * DMA error interrupt handler
+ *
+ *****************************************************************************/
+static irqreturn_t dma_ccerr_handler(int irq, void *data)
+{
+ int i;
+ unsigned int cnt = 0;
+
+ dev_dbg(data, "dma_ccerr_handler\n");
+
+ if ((edma_read_array(EDMA_EMR, 0) == 0) &&
+ (edma_read_array(EDMA_EMR, 1) == 0) &&
+ (edma_read(EDMA_QEMR) == 0) && (edma_read(EDMA_CCERR) == 0))
+ return IRQ_NONE;
+
+ while (1) {
+ int j = -1;
+ if (edma_read_array(EDMA_EMR, 0))
+ j = 0;
+ else if (edma_read_array(EDMA_EMR, 1))
+ j = 1;
+ if (j >= 0) {
+ dev_dbg(data, "EMR%d %08x\n", j,
+ edma_read_array(EDMA_EMR, j));
+ for (i = 0; i < 32; i++) {
+ int k = (j << 5) + i;
+ if (edma_read_array(EDMA_EMR, j) & (1 << i)) {
+ /* Clear the corresponding EMR bits */
+ edma_write_array(EDMA_EMCR, j, 1 << i);
+ /* Clear any SER */
+ edma_shadow0_write_array(SH_SECR, j,
+ (1 << i));
+ if (intr_data[k].callback) {
+ intr_data[k].callback(k,
+ DMA_CC_ERROR,
+ intr_data
+ [k].data);
+ }
+ }
+ }
+ } else if (edma_read(EDMA_QEMR)) {
+ dev_dbg(data, "QEMR %02x\n",
+ edma_read(EDMA_QEMR));
+ for (i = 0; i < 8; i++) {
+ if (edma_read(EDMA_QEMR) & (1 << i)) {
+ /* Clear the corresponding IPR bits */
+ edma_write(EDMA_QEMCR, 1 << i);
+ edma_shadow0_write(SH_QSECR, (1 << i));
+
+ /* NOTE: not reported!! */
+ }
+ }
+ } else if (edma_read(EDMA_CCERR)) {
+ dev_dbg(data, "CCERR %08x\n",
+ edma_read(EDMA_CCERR));
+ /* FIXME: CCERR.BIT(16) ignored! much better
+ * to just write CCERRCLR with CCERR value...
+ */
+ for (i = 0; i < 8; i++) {
+ if (edma_read(EDMA_CCERR) & (1 << i)) {
+ /* Clear the corresponding IPR bits */
+ edma_write(EDMA_CCERRCLR, 1 << i);
+
+ /* NOTE: not reported!! */
+ }
+ }
+ }
+ if ((edma_read_array(EDMA_EMR, 0) == 0)
+ && (edma_read_array(EDMA_EMR, 1) == 0)
+ && (edma_read(EDMA_QEMR) == 0)
+ && (edma_read(EDMA_CCERR) == 0)) {
+ break;
+ }
+ cnt++;
+ if (cnt > 10)
+ break;
+ }
+ edma_write(EDMA_EEVAL, 1);
+ return IRQ_HANDLED;
+}
+
+/******************************************************************************
+ *
+ * Transfer controller error interrupt handlers
+ *
+ *****************************************************************************/
+
+#define tc_errs_handled false /* disabled as long as they're NOPs */
+
+static irqreturn_t dma_tc0err_handler(int irq, void *data)
+{
+ dev_dbg(data, "dma_tc0err_handler\n");
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t dma_tc1err_handler(int irq, void *data)
+{
+ dev_dbg(data, "dma_tc1err_handler\n");
+ return IRQ_HANDLED;
+}
+
+/*-----------------------------------------------------------------------*/
+
+/* Resource alloc/free: dma channels, parameter RAM slots */
+
+/**
+ * edma_alloc_channel - allocate DMA channel and paired parameter RAM
+ * @channel: specific channel to allocate; negative for "any unmapped channel"
+ * @callback: optional; to be issued on DMA completion or errors
+ * @data: passed to callback
+ * @eventq_no: an EVENTQ_* constant, used to choose which Transfer
+ * Controller (TC) executes requests using this channel. Use
+ * EVENTQ_DEFAULT unless you really need a high priority queue.
+ *
+ * This allocates a DMA channel and its associated parameter RAM slot.
+ * The parameter RAM is initialized to hold a dummy transfer.
+ *
+ * Normal use is to pass a specific channel number as @channel, to make
+ * use of hardware events mapped to that channel. When the channel will
+ * be used only for software triggering or event chaining, channels not
+ * mapped to hardware events (or mapped to unused events) are preferable.
+ *
+ * DMA transfers start from a channel using edma_start(), or by
+ * chaining. When the transfer described in that channel's parameter RAM
+ * slot completes, that slot's data may be reloaded through a link.
+ *
+ * DMA errors are only reported to the @callback associated with the
+ * channel driving that transfer, but transfer completion callbacks can
+ * be sent to another channel under control of the TCC field in
+ * the option word of the transfer's parameter RAM set. Drivers must not
+ * use DMA transfer completion callbacks for channels they did not allocate.
+ * (The same applies to TCC codes used in transfer chaining.)
+ *
+ * Returns the number of the channel, else negative errno.
+ */
+int edma_alloc_channel(int channel,
+ void (*callback)(unsigned channel, u16 ch_status, void *data),
+ void *data,
+ enum dma_event_q eventq_no)
+{
+ if (channel < 0) {
+ channel = 0;
+ for (;;) {
+ channel = find_next_bit(edma_noevent,
+ num_channels, channel);
+ if (channel == num_channels)
+ return -ENOMEM;
+ if (!test_and_set_bit(channel, edma_inuse))
+ break;
+ channel++;
+ }
+ } else if (channel >= num_channels) {
+ return -EINVAL;
+ } else if (test_and_set_bit(channel, edma_inuse)) {
+ return -EBUSY;
+ }
+
+ /* ensure access through shadow region 0 */
+ edma_or_array2(EDMA_DRAE, 0, channel >> 5, 1 << (channel & 0x1f));
+
+ /* ensure no events are pending */
+ edma_stop(channel);
+ memcpy_toio(edmacc_regs_base + PARM_OFFSET(channel),
+ &dummy_paramset, PARM_SIZE);
+
+ if (callback)
+ setup_dma_interrupt(channel, callback, data);
+
+ map_dmach_queue(channel, eventq_no);
+
+ return channel;
+}
+EXPORT_SYMBOL(edma_alloc_channel);
+
+
+/**
+ * edma_free_channel - deallocate DMA channel
+ * @channel: dma channel returned from edma_alloc_channel()
+ *
+ * This deallocates the DMA channel and associated parameter RAM slot
+ * allocated by edma_alloc_channel().
+ *
+ * Callers are responsible for ensuring the channel is inactive, and
+ * will not be reactivated by linking, chaining, or software calls to
+ * edma_start().
+ */
+void edma_free_channel(unsigned channel)
+{
+ if (channel >= num_channels)
+ return;
+
+ setup_dma_interrupt(channel, NULL, NULL);
+ /* REVISIT should probably take out of shadow region 0 */
+
+ memcpy_toio(edmacc_regs_base + PARM_OFFSET(channel),
+ &dummy_paramset, PARM_SIZE);
+ clear_bit(channel, edma_inuse);
+}
+EXPORT_SYMBOL(edma_free_channel);
+
+/**
+ * edma_alloc_slot - allocate DMA parameter RAM
+ * @slot: specific slot to allocate; negative for "any unused slot"
+ *
+ * This allocates a parameter RAM slot, initializing it to hold a
+ * dummy transfer. Slots allocated using this routine have not been
+ * mapped to a hardware DMA channel, and will normally be used by
+ * linking to them from a slot associated with a DMA channel.
+ *
+ * Normal use is to pass EDMA_SLOT_ANY as the @slot, but specific
+ * slots may be allocated on behalf of DSP firmware.
+ *
+ * Returns the number of the slot, else negative errno.
+ */
+int edma_alloc_slot(int slot)
+{
+ if (slot < 0) {
+ slot = num_channels;
+ for (;;) {
+ slot = find_next_zero_bit(edma_inuse,
+ num_slots, slot);
+ if (slot == num_slots)
+ return -ENOMEM;
+ if (!test_and_set_bit(slot, edma_inuse))
+ break;
+ }
+ } else if (slot < num_channels || slot >= num_slots) {
+ return -EINVAL;
+ } else if (test_and_set_bit(slot, edma_inuse)) {
+ return -EBUSY;
+ }
+
+ memcpy_toio(edmacc_regs_base + PARM_OFFSET(slot),
+ &dummy_paramset, PARM_SIZE);
+
+ return slot;
+}
+EXPORT_SYMBOL(edma_alloc_slot);
+
+/**
+ * edma_free_slot - deallocate DMA parameter RAM
+ * @slot: parameter RAM slot returned from edma_alloc_slot()
+ *
+ * This deallocates the parameter RAM slot allocated by edma_alloc_slot().
+ * Callers are responsible for ensuring the slot is inactive, and will
+ * not be activated.
+ */
+void edma_free_slot(unsigned slot)
+{
+ if (slot < num_channels || slot >= num_slots)
+ return;
+
+ memcpy_toio(edmacc_regs_base + PARM_OFFSET(slot),
+ &dummy_paramset, PARM_SIZE);
+ clear_bit(slot, edma_inuse);
+}
+EXPORT_SYMBOL(edma_free_slot);
+
+/*-----------------------------------------------------------------------*/
+
+/* Parameter RAM operations (i) -- read/write partial slots */
+
+/**
+ * edma_set_src - set initial DMA source address in parameter RAM slot
+ * @slot: parameter RAM slot being configured
+ * @src_port: physical address of source (memory, controller FIFO, etc)
+ * @addressMode: INCR, except in very rare cases
+ * @fifoWidth: ignored unless @addressMode is FIFO, else specifies the
+ * width to use when addressing the fifo (e.g. W8BIT, W32BIT)
+ *
+ * Note that the source address is modified during the DMA transfer
+ * according to edma_set_src_index().
+ */
+void edma_set_src(unsigned slot, dma_addr_t src_port,
+ enum address_mode mode, enum fifo_width width)
+{
+ if (slot < num_slots) {
+ unsigned int i = edma_parm_read(PARM_OPT, slot);
+
+ if (mode) {
+ /* set SAM and program FWID */
+ i = (i & ~(EDMA_FWID)) | (SAM | ((width & 0x7) << 8));
+ } else {
+ /* clear SAM */
+ i &= ~SAM;
+ }
+ edma_parm_write(PARM_OPT, slot, i);
+
+ /* set the source port address
+ in source register of param structure */
+ edma_parm_write(PARM_SRC, slot, src_port);
+ }
+}
+EXPORT_SYMBOL(edma_set_src);
+
+/**
+ * edma_set_dest - set initial DMA destination address in parameter RAM slot
+ * @slot: parameter RAM slot being configured
+ * @dest_port: physical address of destination (memory, controller FIFO, etc)
+ * @addressMode: INCR, except in very rare cases
+ * @fifoWidth: ignored unless @addressMode is FIFO, else specifies the
+ * width to use when addressing the fifo (e.g. W8BIT, W32BIT)
+ *
+ * Note that the destination address is modified during the DMA transfer
+ * according to edma_set_dest_index().
+ */
+void edma_set_dest(unsigned slot, dma_addr_t dest_port,
+ enum address_mode mode, enum fifo_width width)
+{
+ if (slot < num_slots) {
+ unsigned int i = edma_parm_read(PARM_OPT, slot);
+
+ if (mode) {
+ /* set DAM and program FWID */
+ i = (i & ~(EDMA_FWID)) | (DAM | ((width & 0x7) << 8));
+ } else {
+ /* clear DAM */
+ i &= ~DAM;
+ }
+ edma_parm_write(PARM_OPT, slot, i);
+ /* set the destination port address
+ in dest register of param structure */
+ edma_parm_write(PARM_DST, slot, dest_port);
+ }
+}
+EXPORT_SYMBOL(edma_set_dest);
+
+/**
+ * edma_get_position - returns the current transfer points
+ * @slot: parameter RAM slot being examined
+ * @src: pointer to source port position
+ * @dst: pointer to destination port position
+ *
+ * Returns current source and destination addresses for a particular
+ * parameter RAM slot. Its channel should not be active when this is called.
+ */
+void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst)
+{
+ struct edmacc_param temp;
+
+ edma_read_slot(slot, &temp);
+ if (src != NULL)
+ *src = temp.src;
+ if (dst != NULL)
+ *dst = temp.dst;
+}
+EXPORT_SYMBOL(edma_get_position);
+
+/**
+ * edma_set_src_index - configure DMA source address indexing
+ * @slot: parameter RAM slot being configured
+ * @src_bidx: byte offset between source arrays in a frame
+ * @src_cidx: byte offset between source frames in a block
+ *
+ * Offsets are specified to support either contiguous or discontiguous
+ * memory transfers, or repeated access to a hardware register, as needed.
+ * When accessing hardware registers, both offsets are normally zero.
+ */
+void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx)
+{
+ if (slot < num_slots) {
+ edma_parm_modify(PARM_SRC_DST_BIDX, slot,
+ 0xffff0000, src_bidx);
+ edma_parm_modify(PARM_SRC_DST_CIDX, slot,
+ 0xffff0000, src_cidx);
+ }
+}
+EXPORT_SYMBOL(edma_set_src_index);
+
+/**
+ * edma_set_dest_index - configure DMA destination address indexing
+ * @slot: parameter RAM slot being configured
+ * @dest_bidx: byte offset between destination arrays in a frame
+ * @dest_cidx: byte offset between destination frames in a block
+ *
+ * Offsets are specified to support either contiguous or discontiguous
+ * memory transfers, or repeated access to a hardware register, as needed.
+ * When accessing hardware registers, both offsets are normally zero.
+ */
+void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx)
+{
+ if (slot < num_slots) {
+ edma_parm_modify(PARM_SRC_DST_BIDX, slot,
+ 0x0000ffff, dest_bidx << 16);
+ edma_parm_modify(PARM_SRC_DST_CIDX, slot,
+ 0x0000ffff, dest_cidx << 16);
+ }
+}
+EXPORT_SYMBOL(edma_set_dest_index);
+
+/**
+ * edma_set_transfer_params - configure DMA transfer parameters
+ * @slot: parameter RAM slot being configured
+ * @acnt: how many bytes per array (at least one)
+ * @bcnt: how many arrays per frame (at least one)
+ * @ccnt: how many frames per block (at least one)
+ * @bcnt_rld: used only for A-Synchronized transfers; this specifies
+ * the value to reload into bcnt when it decrements to zero
+ * @sync_mode: ASYNC or ABSYNC
+ *
+ * See the EDMA3 documentation to understand how to configure and link
+ * transfers using the fields in PaRAM slots. If you are not doing it
+ * all at once with edma_write_slot(), you will use this routine
+ * plus two calls each for source and destination, setting the initial
+ * address and saying how to index that address.
+ *
+ * An example of an A-Synchronized transfer is a serial link using a
+ * single word shift register. In that case, @acnt would be equal to
+ * that word size; the serial controller issues a DMA synchronization
+ * event to transfer each word, and memory access by the DMA transfer
+ * controller will be word-at-a-time.
+ *
+ * An example of an AB-Synchronized transfer is a device using a FIFO.
+ * In that case, @acnt equals the FIFO width and @bcnt equals its depth.
+ * The controller with the FIFO issues DMA synchronization events when
+ * the FIFO threshold is reached, and the DMA transfer controller will
+ * transfer one frame to (or from) the FIFO. It will probably use
+ * efficient burst modes to access memory.
+ */
+void edma_set_transfer_params(unsigned slot,
+ u16 acnt, u16 bcnt, u16 ccnt,
+ u16 bcnt_rld, enum sync_dimension sync_mode)
+{
+ if (slot < num_slots) {
+ edma_parm_modify(PARM_LINK_BCNTRLD, slot,
+ 0x0000ffff, bcnt_rld << 16);
+ if (sync_mode == ASYNC)
+ edma_parm_and(PARM_OPT, slot, ~SYNCDIM);
+ else
+ edma_parm_or(PARM_OPT, slot, SYNCDIM);
+ /* Set the acount, bcount, ccount registers */
+ edma_parm_write(PARM_A_B_CNT, slot, (bcnt << 16) | acnt);
+ edma_parm_write(PARM_CCNT, slot, ccnt);
+ }
+}
+EXPORT_SYMBOL(edma_set_transfer_params);
+
+/**
+ * edma_link - link one parameter RAM slot to another
+ * @from: parameter RAM slot originating the link
+ * @to: parameter RAM slot which is the link target
+ *
+ * The originating slot should not be part of any active DMA transfer.
+ */
+void edma_link(unsigned from, unsigned to)
+{
+ if (from >= num_slots)
+ return;
+ if (to >= num_slots)
+ return;
+ edma_parm_modify(PARM_LINK_BCNTRLD, from, 0xffff0000, PARM_OFFSET(to));
+}
+EXPORT_SYMBOL(edma_link);
+
+/**
+ * edma_unlink - cut link from one parameter RAM slot
+ * @from: parameter RAM slot originating the link
+ *
+ * The originating slot should not be part of any active DMA transfer.
+ * Its link is set to 0xffff.
+ */
+void edma_unlink(unsigned from)
+{
+ if (from >= num_slots)
+ return;
+ edma_parm_or(PARM_LINK_BCNTRLD, from, 0xffff);
+}
+EXPORT_SYMBOL(edma_unlink);
+
+/*-----------------------------------------------------------------------*/
+
+/* Parameter RAM operations (ii) -- read/write whole parameter sets */
+
+/**
+ * edma_write_slot - write parameter RAM data for slot
+ * @slot: number of parameter RAM slot being modified
+ * @param: data to be written into parameter RAM slot
+ *
+ * Use this to assign all parameters of a transfer at once. This
+ * allows more efficient setup of transfers than issuing multiple
+ * calls to set up those parameters in small pieces, and provides
+ * complete control over all transfer options.
+ */
+void edma_write_slot(unsigned slot, const struct edmacc_param *param)
+{
+ if (slot >= num_slots)
+ return;
+ memcpy_toio(edmacc_regs_base + PARM_OFFSET(slot), param, PARM_SIZE);
+}
+EXPORT_SYMBOL(edma_write_slot);
+
+/**
+ * edma_read_slot - read parameter RAM data from slot
+ * @slot: number of parameter RAM slot being copied
+ * @param: where to store copy of parameter RAM data
+ *
+ * Use this to read data from a parameter RAM slot, perhaps to
+ * save them as a template for later reuse.
+ */
+void edma_read_slot(unsigned slot, struct edmacc_param *param)
+{
+ if (slot >= num_slots)
+ return;
+ memcpy_fromio(param, edmacc_regs_base + PARM_OFFSET(slot), PARM_SIZE);
+}
+EXPORT_SYMBOL(edma_read_slot);
+
+/*-----------------------------------------------------------------------*/
+
+/* Various EDMA channel control operations */
+
+/**
+ * edma_pause - pause dma on a channel
+ * @channel: on which edma_start() has been called
+ *
+ * This temporarily disables EDMA hardware events on the specified channel,
+ * preventing them from triggering new transfers on its behalf
+ */
+void edma_pause(unsigned channel)
+{
+ if (channel < num_channels) {
+ unsigned int mask = (1 << (channel & 0x1f));
+
+ edma_shadow0_write_array(SH_EECR, channel >> 5, mask);
+ }
+}
+EXPORT_SYMBOL(edma_pause);
+
+/**
+ * edma_resume - resumes dma on a paused channel
+ * @channel: on which edma_pause() has been called
+ *
+ * This re-enables EDMA hardware events on the specified channel.
+ */
+void edma_resume(unsigned channel)
+{
+ if (channel < num_channels) {
+ unsigned int mask = (1 << (channel & 0x1f));
+
+ edma_shadow0_write_array(SH_EESR, channel >> 5, mask);
+ }
+}
+EXPORT_SYMBOL(edma_resume);
+
+/**
+ * edma_start - start dma on a channel
+ * @channel: channel being activated
+ *
+ * Channels with event associations will be triggered by their hardware
+ * events, and channels without such associations will be triggered by
+ * software. (At this writing there is no interface for using software
+ * triggers except with channels that don't support hardware triggers.)
+ *
+ * Returns zero on success, else negative errno.
+ */
+int edma_start(unsigned channel)
+{
+ if (channel < num_channels) {
+ int j = channel >> 5;
+ unsigned int mask = (1 << (channel & 0x1f));
+
+ /* EDMA channels without event association */
+ if (test_bit(channel, edma_noevent)) {
+ pr_debug("EDMA: ESR%d %08x\n", j,
+ edma_shadow0_read_array(SH_ESR, j));
+ edma_shadow0_write_array(SH_ESR, j, mask);
+ return 0;
+ }
+
+ /* EDMA channel with event association */
+ pr_debug("EDMA: ER%d %08x\n", j,
+ edma_shadow0_read_array(SH_ER, j));
+ /* Clear any pending error */
+ edma_write_array(EDMA_EMCR, j, mask);
+ /* Clear any SER */
+ edma_shadow0_write_array(SH_SECR, j, mask);
+ edma_shadow0_write_array(SH_EESR, j, mask);
+ pr_debug("EDMA: EER%d %08x\n", j,
+ edma_shadow0_read_array(SH_EER, j));
+ return 0;
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(edma_start);
+
+/**
+ * edma_stop - stops dma on the channel passed
+ * @channel: channel being deactivated
+ *
+ * When @lch is a channel, any active transfer is paused and
+ * all pending hardware events are cleared. The current transfer
+ * may not be resumed, and the channel's Parameter RAM should be
+ * reinitialized before being reused.
+ */
+void edma_stop(unsigned channel)
+{
+ if (channel < num_channels) {
+ int j = channel >> 5;
+ unsigned int mask = (1 << (channel & 0x1f));
+
+ edma_shadow0_write_array(SH_EECR, j, mask);
+ edma_shadow0_write_array(SH_ECR, j, mask);
+ edma_shadow0_write_array(SH_SECR, j, mask);
+ edma_write_array(EDMA_EMCR, j, mask);
+
+ pr_debug("EDMA: EER%d %08x\n", j,
+ edma_shadow0_read_array(SH_EER, j));
+
+ /* REVISIT: consider guarding against inappropriate event
+ * chaining by overwriting with dummy_paramset.
+ */
+ }
+}
+EXPORT_SYMBOL(edma_stop);
+
+/******************************************************************************
+ *
+ * It cleans ParamEntry qand bring back EDMA to initial state if media has
+ * been removed before EDMA has finished.It is usedful for removable media.
+ * Arguments:
+ * ch_no - channel no
+ *
+ * Return: zero on success, or corresponding error no on failure
+ *
+ * FIXME this should not be needed ... edma_stop() should suffice.
+ *
+ *****************************************************************************/
+
+void edma_clean_channel(unsigned channel)
+{
+ if (channel < num_channels) {
+ int j = (channel >> 5);
+ unsigned int mask = 1 << (channel & 0x1f);
+
+ pr_debug("EDMA: EMR%d %08x\n", j,
+ edma_read_array(EDMA_EMR, j));
+ edma_shadow0_write_array(SH_ECR, j, mask);
+ /* Clear the corresponding EMR bits */
+ edma_write_array(EDMA_EMCR, j, mask);
+ /* Clear any SER */
+ edma_shadow0_write_array(SH_SECR, j, mask);
+ edma_write(EDMA_CCERRCLR, (1 << 16) | 0x3);
+ }
+}
+EXPORT_SYMBOL(edma_clean_channel);
+
+/*
+ * edma_clear_event - clear an outstanding event on the DMA channel
+ * Arguments:
+ * channel - channel number
+ */
+void edma_clear_event(unsigned channel)
+{
+ if (channel >= num_channels)
+ return;
+ if (channel < 32)
+ edma_write(EDMA_ECR, 1 << channel);
+ else
+ edma_write(EDMA_ECRH, 1 << (channel - 32));
+}
+EXPORT_SYMBOL(edma_clear_event);
+
+/*-----------------------------------------------------------------------*/
+
+static int __init edma_probe(struct platform_device *pdev)
+{
+ struct edma_soc_info *info = pdev->dev.platform_data;
+ int i;
+ int status;
+ const s8 *noevent;
+ int irq = 0, err_irq = 0;
+ struct resource *r;
+ resource_size_t len;
+
+ if (!info)
+ return -ENODEV;
+
+ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "edma_cc");
+ if (!r)
+ return -ENODEV;
+
+ len = r->end - r->start + 1;
+
+ r = request_mem_region(r->start, len, r->name);
+ if (!r)
+ return -EBUSY;
+
+ edmacc_regs_base = ioremap(r->start, len);
+ if (!edmacc_regs_base) {
+ status = -EBUSY;
+ goto fail1;
+ }
+
+ num_channels = min_t(unsigned, info->n_channel, EDMA_MAX_DMACH);
+ num_slots = min_t(unsigned, info->n_slot, EDMA_MAX_PARAMENTRY);
+
+ dev_dbg(&pdev->dev, "DMA REG BASE ADDR=%p\n", edmacc_regs_base);
+
+ for (i = 0; i < num_slots; i++)
+ memcpy_toio(edmacc_regs_base + PARM_OFFSET(i),
+ &dummy_paramset, PARM_SIZE);
+
+ noevent = info->noevent;
+ if (noevent) {
+ while (*noevent != -1)
+ set_bit(*noevent++, edma_noevent);
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ status = request_irq(irq, dma_irq_handler, 0, "edma", &pdev->dev);
+ if (status < 0) {
+ dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
+ irq, status);
+ goto fail;
+ }
+
+ err_irq = platform_get_irq(pdev, 1);
+ status = request_irq(err_irq, dma_ccerr_handler, 0,
+ "edma_error", &pdev->dev);
+ if (status < 0) {
+ dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
+ err_irq, status);
+ goto fail;
+ }
+
+ if (tc_errs_handled) {
+ status = request_irq(IRQ_TCERRINT0, dma_tc0err_handler, 0,
+ "edma_tc0", &pdev->dev);
+ if (status < 0) {
+ dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
+ IRQ_TCERRINT0, status);
+ return status;
+ }
+ status = request_irq(IRQ_TCERRINT, dma_tc1err_handler, 0,
+ "edma_tc1", &pdev->dev);
+ if (status < 0) {
+ dev_dbg(&pdev->dev, "request_irq %d --> %d\n",
+ IRQ_TCERRINT, status);
+ return status;
+ }
+ }
+
+ /* Everything lives on transfer controller 1 until otherwise specified.
+ * This way, long transfers on the low priority queue
+ * started by the codec engine will not cause audio defects.
+ */
+ for (i = 0; i < num_channels; i++)
+ map_dmach_queue(i, EVENTQ_1);
+
+ /* Event queue to TC mapping */
+ for (i = 0; queue_tc_mapping[i][0] != -1; i++)
+ map_queue_tc(queue_tc_mapping[i][0], queue_tc_mapping[i][1]);
+
+ /* Event queue priority mapping */
+ for (i = 0; queue_priority_mapping[i][0] != -1; i++)
+ assign_priority_to_queue(queue_priority_mapping[i][0],
+ queue_priority_mapping[i][1]);
+
+ for (i = 0; i < info->n_region; i++) {
+ edma_write_array2(EDMA_DRAE, i, 0, 0x0);
+ edma_write_array2(EDMA_DRAE, i, 1, 0x0);
+ edma_write_array(EDMA_QRAE, i, 0x0);
+ }
+
+ return 0;
+
+fail:
+ if (err_irq)
+ free_irq(err_irq, NULL);
+ if (irq)
+ free_irq(irq, NULL);
+ iounmap(edmacc_regs_base);
+fail1:
+ release_mem_region(r->start, len);
+ return status;
+}
+
+
+static struct platform_driver edma_driver = {
+ .driver.name = "edma",
+};
+
+static int __init edma_init(void)
+{
+ return platform_driver_probe(&edma_driver, edma_probe);
+}
+arch_initcall(edma_init);
+
diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c
index b49e9d092aab..1aba41c6351e 100644
--- a/arch/arm/mach-davinci/gpio.c
+++ b/arch/arm/mach-davinci/gpio.c
@@ -20,6 +20,7 @@
#include <linux/irq.h>
#include <linux/bitops.h>
+#include <mach/cputype.h>
#include <mach/irqs.h>
#include <mach/hardware.h>
#include <mach/gpio.h>
@@ -36,9 +37,10 @@ struct davinci_gpio {
static struct davinci_gpio chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)];
+static unsigned __initdata ngpio;
/* create a non-inlined version */
-static struct gpio_controller *__iomem __init gpio2controller(unsigned gpio)
+static struct gpio_controller __iomem * __init gpio2controller(unsigned gpio)
{
return __gpio_to_controller(gpio);
}
@@ -114,9 +116,30 @@ static int __init davinci_gpio_setup(void)
{
int i, base;
- for (i = 0, base = 0;
- i < ARRAY_SIZE(chips);
- i++, base += 32) {
+ /* The gpio banks conceptually expose a segmented bitmap,
+ * and "ngpio" is one more than the largest zero-based
+ * bit index that's valid.
+ */
+ if (cpu_is_davinci_dm355()) { /* or dm335() */
+ ngpio = 104;
+ } else if (cpu_is_davinci_dm644x()) { /* or dm337() */
+ ngpio = 71;
+ } else if (cpu_is_davinci_dm646x()) {
+ /* NOTE: each bank has several "reserved" bits,
+ * unusable as GPIOs. Only 33 of the GPIO numbers
+ * are usable, and we're not rejecting the others.
+ */
+ ngpio = 43;
+ } else {
+ /* if cpu_is_davinci_dm643x() ngpio = 111 */
+ pr_err("GPIO setup: how many GPIOs?\n");
+ return -EINVAL;
+ }
+
+ if (WARN_ON(DAVINCI_N_GPIO < ngpio))
+ ngpio = DAVINCI_N_GPIO;
+
+ for (i = 0, base = 0; base < ngpio; i++, base += 32) {
chips[i].chip.label = "DaVinci";
chips[i].chip.direction_input = davinci_direction_in;
@@ -125,7 +148,7 @@ static int __init davinci_gpio_setup(void)
chips[i].chip.set = davinci_gpio_set;
chips[i].chip.base = base;
- chips[i].chip.ngpio = DAVINCI_N_GPIO - base;
+ chips[i].chip.ngpio = ngpio - base;
if (chips[i].chip.ngpio > 32)
chips[i].chip.ngpio = 32;
@@ -143,11 +166,11 @@ pure_initcall(davinci_gpio_setup);
* We expect irqs will normally be set up as input pins, but they can also be
* used as output pins ... which is convenient for testing.
*
- * NOTE: GPIO0..GPIO7 also have direct INTC hookups, which work in addition
- * to their GPIOBNK0 irq (but with a bit less overhead). But we don't have
- * a good way to hook those up ...
+ * NOTE: The first few GPIOs also have direct INTC hookups in addition
+ * to their GPIOBNK0 irq, with a bit less overhead but less flexibility
+ * on triggering (e.g. no edge options). We don't try to use those.
*
- * All those INTC hookups (GPIO0..GPIO7 plus five IRQ banks) can also
+ * All those INTC hookups (direct, plus several IRQ banks) can also
* serve as EDMA event triggers.
*/
@@ -235,29 +258,42 @@ gpio_irq_handler(unsigned irq, struct irq_desc *desc)
}
/*
- * NOTE: for suspend/resume, probably best to make a sysdev (and class)
- * with its suspend/resume calls hooking into the results of the set_wake()
+ * NOTE: for suspend/resume, probably best to make a platform_device with
+ * suspend_late/resume_resume calls hooking into results of the set_wake()
* calls ... so if no gpios are wakeup events the clock can be disabled,
* with outputs left at previously set levels, and so that VDD3P3V.IOPWDN0
- * can be set appropriately for GPIOV33 pins.
+ * (dm6446) can be set appropriately for GPIOV33 pins.
*/
static int __init davinci_gpio_irq_setup(void)
{
unsigned gpio, irq, bank;
+ unsigned bank_irq;
struct clk *clk;
+ u32 binten = 0;
+
+ if (cpu_is_davinci_dm355()) { /* or dm335() */
+ bank_irq = IRQ_DM355_GPIOBNK0;
+ } else if (cpu_is_davinci_dm644x()) {
+ bank_irq = IRQ_GPIOBNK0;
+ } else if (cpu_is_davinci_dm646x()) {
+ bank_irq = IRQ_DM646X_GPIOBNK0;
+ } else {
+ printk(KERN_ERR "Don't know first GPIO bank IRQ.\n");
+ return -EINVAL;
+ }
clk = clk_get(NULL, "gpio");
if (IS_ERR(clk)) {
printk(KERN_ERR "Error %ld getting gpio clock?\n",
PTR_ERR(clk));
- return 0;
+ return PTR_ERR(clk);
}
-
clk_enable(clk);
- for (gpio = 0, irq = gpio_to_irq(0), bank = IRQ_GPIOBNK0;
- gpio < DAVINCI_N_GPIO; bank++) {
+ for (gpio = 0, irq = gpio_to_irq(0), bank = 0;
+ gpio < ngpio;
+ bank++, bank_irq++) {
struct gpio_controller *__iomem g = gpio2controller(gpio);
unsigned i;
@@ -265,28 +301,28 @@ static int __init davinci_gpio_irq_setup(void)
__raw_writel(~0, &g->clr_rising);
/* set up all irqs in this bank */
- set_irq_chained_handler(bank, gpio_irq_handler);
- set_irq_chip_data(bank, g);
- set_irq_data(bank, (void *)irq);
+ set_irq_chained_handler(bank_irq, gpio_irq_handler);
+ set_irq_chip_data(bank_irq, g);
+ set_irq_data(bank_irq, (void *)irq);
- for (i = 0; i < 16 && gpio < DAVINCI_N_GPIO;
- i++, irq++, gpio++) {
+ for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) {
set_irq_chip(irq, &gpio_irqchip);
set_irq_chip_data(irq, g);
set_irq_handler(irq, handle_simple_irq);
set_irq_flags(irq, IRQF_VALID);
}
+
+ binten |= BIT(bank);
}
/* BINTEN -- per-bank interrupt enable. genirq would also let these
* bits be set/cleared dynamically.
*/
- __raw_writel(0x1f, (void *__iomem)
+ __raw_writel(binten, (void *__iomem)
IO_ADDRESS(DAVINCI_GPIO_BASE + 0x08));
printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0));
return 0;
}
-
arch_initcall(davinci_gpio_irq_setup);
diff --git a/arch/arm/mach-davinci/id.c b/arch/arm/mach-davinci/id.c
index bf067d604918..018b994cd794 100644
--- a/arch/arm/mach-davinci/id.c
+++ b/arch/arm/mach-davinci/id.c
@@ -15,7 +15,9 @@
#include <linux/init.h>
#include <linux/io.h>
-#define JTAG_ID_BASE 0x01c40028
+#define JTAG_ID_BASE IO_ADDRESS(0x01c40028)
+
+static unsigned int davinci_revision;
struct davinci_id {
u8 variant; /* JTAG ID bits 31:28 */
@@ -33,6 +35,20 @@ static struct davinci_id davinci_ids[] __initdata = {
.manufacturer = 0x017,
.type = 0x64460000,
},
+ {
+ /* DM646X */
+ .part_no = 0xb770,
+ .variant = 0x0,
+ .manufacturer = 0x017,
+ .type = 0x64670000,
+ },
+ {
+ /* DM355 */
+ .part_no = 0xb73b,
+ .variant = 0x0,
+ .manufacturer = 0x00f,
+ .type = 0x03550000,
+ },
};
/*
@@ -42,7 +58,7 @@ static u16 __init davinci_get_part_no(void)
{
u32 dev_id, part_no;
- dev_id = davinci_readl(JTAG_ID_BASE);
+ dev_id = __raw_readl(JTAG_ID_BASE);
part_no = ((dev_id >> 12) & 0xffff);
@@ -56,13 +72,19 @@ static u8 __init davinci_get_variant(void)
{
u32 variant;
- variant = davinci_readl(JTAG_ID_BASE);
+ variant = __raw_readl(JTAG_ID_BASE);
variant = (variant >> 28) & 0xf;
return variant;
}
+unsigned int davinci_rev(void)
+{
+ return davinci_revision >> 16;
+}
+EXPORT_SYMBOL(davinci_rev);
+
void __init davinci_check_revision(void)
{
int i;
@@ -75,7 +97,7 @@ void __init davinci_check_revision(void)
/* First check only the major version in a safe way */
for (i = 0; i < ARRAY_SIZE(davinci_ids); i++) {
if (part_no == (davinci_ids[i].part_no)) {
- system_rev = davinci_ids[i].type;
+ davinci_revision = davinci_ids[i].type;
break;
}
}
@@ -84,10 +106,11 @@ void __init davinci_check_revision(void)
for (i = 0; i < ARRAY_SIZE(davinci_ids); i++) {
if (part_no == davinci_ids[i].part_no &&
variant == davinci_ids[i].variant) {
- system_rev = davinci_ids[i].type;
+ davinci_revision = davinci_ids[i].type;
break;
}
}
- printk("DaVinci DM%04x variant 0x%x\n", system_rev >> 16, variant);
+ printk(KERN_INFO "DaVinci DM%04x variant 0x%x\n",
+ davinci_rev(), variant);
}
diff --git a/arch/arm/mach-davinci/include/mach/board-dm6446evm.h b/arch/arm/mach-davinci/include/mach/board-dm6446evm.h
new file mode 100644
index 000000000000..3216f21c1238
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/board-dm6446evm.h
@@ -0,0 +1,20 @@
+/*
+ * DaVinci DM6446 EVM board specific headers
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * 2007 (c) Deep Root Systems, LLC. 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 ifndef.
+ */
+
+#ifndef _MACH_DAVINCI_DM6446EVM_H
+#define _MACH_DAVINCI_DM6446EVM_H
+
+#include <linux/types.h>
+
+int dm6446evm_eeprom_read(char *buf, off_t off, size_t count);
+int dm6446evm_eeprom_write(char *buf, off_t off, size_t count);
+
+#endif
diff --git a/arch/arm/mach-davinci/include/mach/clkdev.h b/arch/arm/mach-davinci/include/mach/clkdev.h
new file mode 100644
index 000000000000..730c49d1ebd8
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/clkdev.h
@@ -0,0 +1,13 @@
+#ifndef __MACH_CLKDEV_H
+#define __MACH_CLKDEV_H
+
+static inline int __clk_get(struct clk *clk)
+{
+ return 1;
+}
+
+static inline void __clk_put(struct clk *clk)
+{
+}
+
+#endif
diff --git a/arch/arm/mach-davinci/include/mach/clock.h b/arch/arm/mach-davinci/include/mach/clock.h
index 38bdd49bc181..a3b040219876 100644
--- a/arch/arm/mach-davinci/include/mach/clock.h
+++ b/arch/arm/mach-davinci/include/mach/clock.h
@@ -17,6 +17,5 @@ struct clk;
extern int clk_register(struct clk *clk);
extern void clk_unregister(struct clk *clk);
-extern int davinci_clk_init(void);
#endif
diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h
index 4b522e5c70ec..191770976250 100644
--- a/arch/arm/mach-davinci/include/mach/common.h
+++ b/arch/arm/mach-davinci/include/mach/common.h
@@ -16,6 +16,12 @@ struct sys_timer;
extern struct sys_timer davinci_timer;
+extern void davinci_irq_init(void);
+extern void davinci_map_common_io(void);
+
+/* parameters describe VBUS sourcing for host mode */
+extern void setup_usb(unsigned mA, unsigned potpgt_msec);
+
/* parameters describe VBUS sourcing for host mode */
extern void setup_usb(unsigned mA, unsigned potpgt_msec);
diff --git a/arch/arm/mach-davinci/include/mach/cputype.h b/arch/arm/mach-davinci/include/mach/cputype.h
new file mode 100644
index 000000000000..27cfb1b3a662
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/cputype.h
@@ -0,0 +1,49 @@
+/*
+ * DaVinci CPU type detection
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * Defines the cpu_is_*() macros for runtime detection of DaVinci
+ * device type. In addtion, if support for a given device is not
+ * compiled in to the kernel, the macros return 0 so that
+ * resulting code can be optimized out.
+ *
+ * 2009 (c) Deep Root Systems, LLC. 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 _ASM_ARCH_CPU_H
+#define _ASM_ARCH_CPU_H
+
+extern unsigned int davinci_rev(void);
+
+#define IS_DAVINCI_CPU(type, id) \
+static inline int is_davinci_dm ##type(void) \
+{ \
+ return (davinci_rev() == (id)) ? 1 : 0; \
+}
+
+IS_DAVINCI_CPU(644x, 0x6446)
+IS_DAVINCI_CPU(646x, 0x6467)
+IS_DAVINCI_CPU(355, 0x355)
+
+#ifdef CONFIG_ARCH_DAVINCI_DM644x
+#define cpu_is_davinci_dm644x() is_davinci_dm644x()
+#else
+#define cpu_is_davinci_dm644x() 0
+#endif
+
+#ifdef CONFIG_ARCH_DAVINCI_DM646x
+#define cpu_is_davinci_dm646x() is_davinci_dm646x()
+#else
+#define cpu_is_davinci_dm646x() 0
+#endif
+
+#ifdef CONFIG_ARCH_DAVINCI_DM355
+#define cpu_is_davinci_dm355() is_davinci_dm355()
+#else
+#define cpu_is_davinci_dm355() 0
+#endif
+
+#endif
diff --git a/arch/arm/mach-davinci/include/mach/dm644x.h b/arch/arm/mach-davinci/include/mach/dm644x.h
new file mode 100644
index 000000000000..3dcb9f4e58b4
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/dm644x.h
@@ -0,0 +1,37 @@
+/*
+ * This file contains the processor specific definitions
+ * of the TI DM644x.
+ *
+ * Copyright (C) 2008 Texas Instruments.
+ *
+ * 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
+ *
+ */
+#ifndef __ASM_ARCH_DM644X_H
+#define __ASM_ARCH_DM644X_H
+
+#include <linux/platform_device.h>
+#include <mach/hardware.h>
+
+#define DM644X_EMAC_BASE (0x01C80000)
+#define DM644X_EMAC_CNTRL_OFFSET (0x0000)
+#define DM644X_EMAC_CNTRL_MOD_OFFSET (0x1000)
+#define DM644X_EMAC_CNTRL_RAM_OFFSET (0x2000)
+#define DM644X_EMAC_MDIO_OFFSET (0x4000)
+#define DM644X_EMAC_CNTRL_RAM_SIZE (0x2000)
+
+void __init dm644x_init(void);
+
+#endif /* __ASM_ARCH_DM644X_H */
diff --git a/arch/arm/mach-davinci/include/mach/edma.h b/arch/arm/mach-davinci/include/mach/edma.h
new file mode 100644
index 000000000000..f6fc5396dafc
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/edma.h
@@ -0,0 +1,228 @@
+/*
+ * TI DAVINCI dma definitions
+ *
+ * Copyright (C) 2006-2009 Texas Instruments.
+ *
+ * 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.
+ *
+ */
+
+/*
+ * This EDMA3 programming framework exposes two basic kinds of resource:
+ *
+ * Channel Triggers transfers, usually from a hardware event but
+ * also manually or by "chaining" from DMA completions.
+ * Each channel is coupled to a Parameter RAM (PaRAM) slot.
+ *
+ * Slot Each PaRAM slot holds a DMA transfer descriptor (PaRAM
+ * "set"), source and destination addresses, a link to a
+ * next PaRAM slot (if any), options for the transfer, and
+ * instructions for updating those addresses. There are
+ * more than twice as many slots as event channels.
+ *
+ * Each PaRAM set describes a sequence of transfers, either for one large
+ * buffer or for several discontiguous smaller buffers. An EDMA transfer
+ * is driven only from a channel, which performs the transfers specified
+ * in its PaRAM slot until there are no more transfers. When that last
+ * transfer completes, the "link" field may be used to reload the channel's
+ * PaRAM slot with a new transfer descriptor.
+ *
+ * The EDMA Channel Controller (CC) maps requests from channels into physical
+ * Transfer Controller (TC) requests when the channel triggers (by hardware
+ * or software events, or by chaining). The two physical DMA channels provided
+ * by the TCs are thus shared by many logical channels.
+ *
+ * DaVinci hardware also has a "QDMA" mechanism which is not currently
+ * supported through this interface. (DSP firmware uses it though.)
+ */
+
+#ifndef EDMA_H_
+#define EDMA_H_
+
+/* PaRAM slots are laid out like this */
+struct edmacc_param {
+ unsigned int opt;
+ unsigned int src;
+ unsigned int a_b_cnt;
+ unsigned int dst;
+ unsigned int src_dst_bidx;
+ unsigned int link_bcntrld;
+ unsigned int src_dst_cidx;
+ unsigned int ccnt;
+};
+
+#define CCINT0_INTERRUPT 16
+#define CCERRINT_INTERRUPT 17
+#define TCERRINT0_INTERRUPT 18
+#define TCERRINT1_INTERRUPT 19
+
+/* fields in edmacc_param.opt */
+#define SAM BIT(0)
+#define DAM BIT(1)
+#define SYNCDIM BIT(2)
+#define STATIC BIT(3)
+#define EDMA_FWID (0x07 << 8)
+#define TCCMODE BIT(11)
+#define EDMA_TCC(t) ((t) << 12)
+#define TCINTEN BIT(20)
+#define ITCINTEN BIT(21)
+#define TCCHEN BIT(22)
+#define ITCCHEN BIT(23)
+
+#define TRWORD (0x7<<2)
+#define PAENTRY (0x1ff<<5)
+
+/* Drivers should avoid using these symbolic names for dm644x
+ * channels, and use platform_device IORESOURCE_DMA resources
+ * instead. (Other DaVinci chips have different peripherals
+ * and thus have different DMA channel mappings.)
+ */
+#define DAVINCI_DMA_MCBSP_TX 2
+#define DAVINCI_DMA_MCBSP_RX 3
+#define DAVINCI_DMA_VPSS_HIST 4
+#define DAVINCI_DMA_VPSS_H3A 5
+#define DAVINCI_DMA_VPSS_PRVU 6
+#define DAVINCI_DMA_VPSS_RSZ 7
+#define DAVINCI_DMA_IMCOP_IMXINT 8
+#define DAVINCI_DMA_IMCOP_VLCDINT 9
+#define DAVINCI_DMA_IMCO_PASQINT 10
+#define DAVINCI_DMA_IMCOP_DSQINT 11
+#define DAVINCI_DMA_SPI_SPIX 16
+#define DAVINCI_DMA_SPI_SPIR 17
+#define DAVINCI_DMA_UART0_URXEVT0 18
+#define DAVINCI_DMA_UART0_UTXEVT0 19
+#define DAVINCI_DMA_UART1_URXEVT1 20
+#define DAVINCI_DMA_UART1_UTXEVT1 21
+#define DAVINCI_DMA_UART2_URXEVT2 22
+#define DAVINCI_DMA_UART2_UTXEVT2 23
+#define DAVINCI_DMA_MEMSTK_MSEVT 24
+#define DAVINCI_DMA_MMCRXEVT 26
+#define DAVINCI_DMA_MMCTXEVT 27
+#define DAVINCI_DMA_I2C_ICREVT 28
+#define DAVINCI_DMA_I2C_ICXEVT 29
+#define DAVINCI_DMA_GPIO_GPINT0 32
+#define DAVINCI_DMA_GPIO_GPINT1 33
+#define DAVINCI_DMA_GPIO_GPINT2 34
+#define DAVINCI_DMA_GPIO_GPINT3 35
+#define DAVINCI_DMA_GPIO_GPINT4 36
+#define DAVINCI_DMA_GPIO_GPINT5 37
+#define DAVINCI_DMA_GPIO_GPINT6 38
+#define DAVINCI_DMA_GPIO_GPINT7 39
+#define DAVINCI_DMA_GPIO_GPBNKINT0 40
+#define DAVINCI_DMA_GPIO_GPBNKINT1 41
+#define DAVINCI_DMA_GPIO_GPBNKINT2 42
+#define DAVINCI_DMA_GPIO_GPBNKINT3 43
+#define DAVINCI_DMA_GPIO_GPBNKINT4 44
+#define DAVINCI_DMA_TIMER0_TINT0 48
+#define DAVINCI_DMA_TIMER1_TINT1 49
+#define DAVINCI_DMA_TIMER2_TINT2 50
+#define DAVINCI_DMA_TIMER3_TINT3 51
+#define DAVINCI_DMA_PWM0 52
+#define DAVINCI_DMA_PWM1 53
+#define DAVINCI_DMA_PWM2 54
+
+/*ch_status paramater of callback function possible values*/
+#define DMA_COMPLETE 1
+#define DMA_CC_ERROR 2
+#define DMA_TC1_ERROR 3
+#define DMA_TC2_ERROR 4
+
+enum address_mode {
+ INCR = 0,
+ FIFO = 1
+};
+
+enum fifo_width {
+ W8BIT = 0,
+ W16BIT = 1,
+ W32BIT = 2,
+ W64BIT = 3,
+ W128BIT = 4,
+ W256BIT = 5
+};
+
+enum dma_event_q {
+ EVENTQ_0 = 0,
+ EVENTQ_1 = 1,
+ EVENTQ_DEFAULT = -1
+};
+
+enum sync_dimension {
+ ASYNC = 0,
+ ABSYNC = 1
+};
+
+#define EDMA_CHANNEL_ANY -1 /* for edma_alloc_channel() */
+#define EDMA_SLOT_ANY -1 /* for edma_alloc_slot() */
+
+/* alloc/free DMA channels and their dedicated parameter RAM slots */
+int edma_alloc_channel(int channel,
+ void (*callback)(unsigned channel, u16 ch_status, void *data),
+ void *data, enum dma_event_q);
+void edma_free_channel(unsigned channel);
+
+/* alloc/free parameter RAM slots */
+int edma_alloc_slot(int slot);
+void edma_free_slot(unsigned slot);
+
+/* calls that operate on part of a parameter RAM slot */
+void edma_set_src(unsigned slot, dma_addr_t src_port,
+ enum address_mode mode, enum fifo_width);
+void edma_set_dest(unsigned slot, dma_addr_t dest_port,
+ enum address_mode mode, enum fifo_width);
+void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst);
+void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx);
+void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx);
+void edma_set_transfer_params(unsigned slot, u16 acnt, u16 bcnt, u16 ccnt,
+ u16 bcnt_rld, enum sync_dimension sync_mode);
+void edma_link(unsigned from, unsigned to);
+void edma_unlink(unsigned from);
+
+/* calls that operate on an entire parameter RAM slot */
+void edma_write_slot(unsigned slot, const struct edmacc_param *params);
+void edma_read_slot(unsigned slot, struct edmacc_param *params);
+
+/* channel control operations */
+int edma_start(unsigned channel);
+void edma_stop(unsigned channel);
+void edma_clean_channel(unsigned channel);
+void edma_clear_event(unsigned channel);
+void edma_pause(unsigned channel);
+void edma_resume(unsigned channel);
+
+/* UNRELATED TO DMA */
+int davinci_alloc_iram(unsigned size);
+void davinci_free_iram(unsigned addr, unsigned size);
+
+/* platform_data for EDMA driver */
+struct edma_soc_info {
+
+ /* how many dma resources of each type */
+ unsigned n_channel;
+ unsigned n_region;
+ unsigned n_slot;
+ unsigned n_tc;
+
+ /* list of channels with no even trigger; terminated by "-1" */
+ const s8 *noevent;
+};
+
+#endif
diff --git a/arch/arm/mach-davinci/include/mach/gpio.h b/arch/arm/mach-davinci/include/mach/gpio.h
index b456f079f43f..efe3281364e6 100644
--- a/arch/arm/mach-davinci/include/mach/gpio.h
+++ b/arch/arm/mach-davinci/include/mach/gpio.h
@@ -15,9 +15,11 @@
#include <linux/io.h>
#include <asm-generic/gpio.h>
-#include <mach/hardware.h>
+
#include <mach/irqs.h>
+#define DAVINCI_GPIO_BASE 0x01C67000
+
/*
* basic gpio routines
*
@@ -26,23 +28,18 @@
* go through boot loaders.
*
* the gpio clock will be turned on when gpios are used, and you may also
- * need to pay attention to PINMUX0 and PINMUX1 to be sure those pins are
+ * need to pay attention to PINMUX registers to be sure those pins are
* used as gpios, not with other peripherals.
*
* On-chip GPIOs are numbered 0..(DAVINCI_N_GPIO-1). For documentation,
- * and maybe for later updates, code should write GPIO(N) or:
- * - GPIOV18(N) for 1.8V pins, N in 0..53; same as GPIO(0)..GPIO(53)
- * - GPIOV33(N) for 3.3V pins, N in 0..17; same as GPIO(54)..GPIO(70)
- *
- * For GPIO IRQs use gpio_to_irq(GPIO(N)) or gpio_to_irq(GPIOV33(N)) etc
- * for now, that's != GPIO(N)
+ * and maybe for later updates, code may write GPIO(N). These may be
+ * all 1.8V signals, all 3.3V ones, or a mix of the two. A given chip
+ * may not support all the GPIOs in that range.
*
* GPIOs can also be on external chips, numbered after the ones built-in
* to the DaVinci chip. For now, they won't be usable as IRQ sources.
*/
-#define GPIO(X) (X) /* 0 <= X <= 70 */
-#define GPIOV18(X) (X) /* 1.8V i/o; 0 <= X <= 53 */
-#define GPIOV33(X) ((X)+54) /* 3.3V i/o; 0 <= X <= 17 */
+#define GPIO(X) (X) /* 0 <= X <= (DAVINCI_N_GPIO - 1) */
struct gpio_controller {
u32 dir;
@@ -71,12 +68,14 @@ __gpio_to_controller(unsigned gpio)
{
void *__iomem ptr;
- if (gpio < 32)
+ if (gpio < 32 * 1)
ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10);
- else if (gpio < 64)
+ else if (gpio < 32 * 2)
ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38);
- else if (gpio < DAVINCI_N_GPIO)
+ else if (gpio < 32 * 3)
ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60);
+ else if (gpio < 32 * 4)
+ ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x88);
else
ptr = NULL;
return ptr;
diff --git a/arch/arm/mach-davinci/include/mach/hardware.h b/arch/arm/mach-davinci/include/mach/hardware.h
index a2e8969afaca..48c77934d519 100644
--- a/arch/arm/mach-davinci/include/mach/hardware.h
+++ b/arch/arm/mach-davinci/include/mach/hardware.h
@@ -1,9 +1,9 @@
/*
- * Common hardware definitions
+ * Hardware definitions common to all DaVinci family processors
*
- * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
+ * Author: Kevin Hilman, Deep Root Systems, LLC
*
- * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * 2007 (c) Deep Root Systems, LLC. 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.
@@ -12,41 +12,16 @@
#define __ASM_ARCH_HARDWARE_H
/*
- * Base register addresses
+ * Before you add anything to ths file:
+ *
+ * This header is for defines common to ALL DaVinci family chips.
+ * Anything that is chip specific should go in <chipname>.h,
+ * and the chip/board init code should then explicitly include
+ * <chipname>.h
*/
-#define DAVINCI_DMA_3PCC_BASE (0x01C00000)
-#define DAVINCI_DMA_3PTC0_BASE (0x01C10000)
-#define DAVINCI_DMA_3PTC1_BASE (0x01C10400)
-#define DAVINCI_I2C_BASE (0x01C21000)
-#define DAVINCI_PWM0_BASE (0x01C22000)
-#define DAVINCI_PWM1_BASE (0x01C22400)
-#define DAVINCI_PWM2_BASE (0x01C22800)
-#define DAVINCI_SYSTEM_MODULE_BASE (0x01C40000)
-#define DAVINCI_PLL_CNTRL0_BASE (0x01C40800)
-#define DAVINCI_PLL_CNTRL1_BASE (0x01C40C00)
-#define DAVINCI_PWR_SLEEP_CNTRL_BASE (0x01C41000)
-#define DAVINCI_SYSTEM_DFT_BASE (0x01C42000)
-#define DAVINCI_IEEE1394_BASE (0x01C60000)
-#define DAVINCI_USB_OTG_BASE (0x01C64000)
-#define DAVINCI_CFC_ATA_BASE (0x01C66000)
-#define DAVINCI_SPI_BASE (0x01C66800)
-#define DAVINCI_GPIO_BASE (0x01C67000)
-#define DAVINCI_UHPI_BASE (0x01C67800)
-#define DAVINCI_VPSS_REGS_BASE (0x01C70000)
-#define DAVINCI_EMAC_CNTRL_REGS_BASE (0x01C80000)
-#define DAVINCI_EMAC_WRAPPER_CNTRL_REGS_BASE (0x01C81000)
-#define DAVINCI_EMAC_WRAPPER_RAM_BASE (0x01C82000)
-#define DAVINCI_MDIO_CNTRL_REGS_BASE (0x01C84000)
-#define DAVINCI_IMCOP_BASE (0x01CC0000)
-#define DAVINCI_ASYNC_EMIF_CNTRL_BASE (0x01E00000)
-#define DAVINCI_VLYNQ_BASE (0x01E01000)
-#define DAVINCI_MCBSP_BASE (0x01E02000)
-#define DAVINCI_MMC_SD_BASE (0x01E10000)
-#define DAVINCI_MS_BASE (0x01E20000)
-#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE (0x02000000)
-#define DAVINCI_ASYNC_EMIF_DATA_CE1_BASE (0x04000000)
-#define DAVINCI_ASYNC_EMIF_DATA_CE2_BASE (0x06000000)
-#define DAVINCI_ASYNC_EMIF_DATA_CE3_BASE (0x08000000)
-#define DAVINCI_VLYNQ_REMOTE_BASE (0x0C000000)
+#define DAVINCI_SYSTEM_MODULE_BASE 0x01C40000
+
+/* System control register offsets */
+#define DM64XX_VDD3P3V_PWDN 0x48
#endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-davinci/include/mach/io.h b/arch/arm/mach-davinci/include/mach/io.h
index a48795fd2417..2479785405af 100644
--- a/arch/arm/mach-davinci/include/mach/io.h
+++ b/arch/arm/mach-davinci/include/mach/io.h
@@ -40,22 +40,12 @@
#else
#define IOMEM(x) ((void __force __iomem *)(x))
-/*
- * Functions to access the DaVinci IO region
- *
- * NOTE: - Use davinci_read/write[bwl] for physical register addresses
- * - Use __raw_read/write[bwl]() for virtual register addresses
- * - Use IO_ADDRESS(phys_addr) to convert registers to virtual addresses
- * - DO NOT use hardcoded virtual addresses to allow changing the
- * IO address space again if needed
- */
-#define davinci_readb(a) __raw_readb(IO_ADDRESS(a))
-#define davinci_readw(a) __raw_readw(IO_ADDRESS(a))
-#define davinci_readl(a) __raw_readl(IO_ADDRESS(a))
+#define __arch_ioremap(p, s, t) davinci_ioremap(p, s, t)
+#define __arch_iounmap(v) davinci_iounmap(v)
-#define davinci_writeb(v, a) __raw_writeb(v, IO_ADDRESS(a))
-#define davinci_writew(v, a) __raw_writew(v, IO_ADDRESS(a))
-#define davinci_writel(v, a) __raw_writel(v, IO_ADDRESS(a))
+void __iomem *davinci_ioremap(unsigned long phys, size_t size,
+ unsigned int type);
+void davinci_iounmap(volatile void __iomem *addr);
#endif /* __ASSEMBLER__ */
#endif /* __ASM_ARCH_IO_H */
diff --git a/arch/arm/mach-davinci/include/mach/irqs.h b/arch/arm/mach-davinci/include/mach/irqs.h
index f4c5ca6da9f4..18066074c995 100644
--- a/arch/arm/mach-davinci/include/mach/irqs.h
+++ b/arch/arm/mach-davinci/include/mach/irqs.h
@@ -96,10 +96,111 @@
#define IRQ_EMUINT 63
#define DAVINCI_N_AINTC_IRQ 64
-#define DAVINCI_N_GPIO 71
+#define DAVINCI_N_GPIO 104
#define NR_IRQS (DAVINCI_N_AINTC_IRQ + DAVINCI_N_GPIO)
#define ARCH_TIMER_IRQ IRQ_TINT1_TINT34
+/* DaVinci DM6467-specific Interrupts */
+#define IRQ_DM646X_VP_VERTINT0 0
+#define IRQ_DM646X_VP_VERTINT1 1
+#define IRQ_DM646X_VP_VERTINT2 2
+#define IRQ_DM646X_VP_VERTINT3 3
+#define IRQ_DM646X_VP_ERRINT 4
+#define IRQ_DM646X_RESERVED_1 5
+#define IRQ_DM646X_RESERVED_2 6
+#define IRQ_DM646X_WDINT 7
+#define IRQ_DM646X_CRGENINT0 8
+#define IRQ_DM646X_CRGENINT1 9
+#define IRQ_DM646X_TSIFINT0 10
+#define IRQ_DM646X_TSIFINT1 11
+#define IRQ_DM646X_VDCEINT 12
+#define IRQ_DM646X_USBINT 13
+#define IRQ_DM646X_USBDMAINT 14
+#define IRQ_DM646X_PCIINT 15
+#define IRQ_DM646X_TCERRINT2 20
+#define IRQ_DM646X_TCERRINT3 21
+#define IRQ_DM646X_IDE 22
+#define IRQ_DM646X_HPIINT 23
+#define IRQ_DM646X_EMACRXTHINT 24
+#define IRQ_DM646X_EMACRXINT 25
+#define IRQ_DM646X_EMACTXINT 26
+#define IRQ_DM646X_EMACMISCINT 27
+#define IRQ_DM646X_MCASP0TXINT 28
+#define IRQ_DM646X_MCASP0RXINT 29
+#define IRQ_DM646X_RESERVED_3 31
+#define IRQ_DM646X_MCASP1TXINT 32
+#define IRQ_DM646X_VLQINT 38
+#define IRQ_DM646X_UARTINT2 42
+#define IRQ_DM646X_SPINT0 43
+#define IRQ_DM646X_SPINT1 44
+#define IRQ_DM646X_DSP2ARMINT 45
+#define IRQ_DM646X_RESERVED_4 46
+#define IRQ_DM646X_PSCINT 47
+#define IRQ_DM646X_GPIO0 48
+#define IRQ_DM646X_GPIO1 49
+#define IRQ_DM646X_GPIO2 50
+#define IRQ_DM646X_GPIO3 51
+#define IRQ_DM646X_GPIO4 52
+#define IRQ_DM646X_GPIO5 53
+#define IRQ_DM646X_GPIO6 54
+#define IRQ_DM646X_GPIO7 55
+#define IRQ_DM646X_GPIOBNK0 56
+#define IRQ_DM646X_GPIOBNK1 57
+#define IRQ_DM646X_GPIOBNK2 58
+#define IRQ_DM646X_DDRINT 59
+#define IRQ_DM646X_AEMIFINT 60
+
+/* DaVinci DM355-specific Interrupts */
+#define IRQ_DM355_CCDC_VDINT0 0
+#define IRQ_DM355_CCDC_VDINT1 1
+#define IRQ_DM355_CCDC_VDINT2 2
+#define IRQ_DM355_IPIPE_HST 3
+#define IRQ_DM355_H3AINT 4
+#define IRQ_DM355_IPIPE_SDR 5
+#define IRQ_DM355_IPIPEIFINT 6
+#define IRQ_DM355_OSDINT 7
+#define IRQ_DM355_VENCINT 8
+#define IRQ_DM355_IMCOPINT 11
+#define IRQ_DM355_RTOINT 13
+#define IRQ_DM355_TINT4 13
+#define IRQ_DM355_TINT2_TINT12 13
+#define IRQ_DM355_UARTINT2 14
+#define IRQ_DM355_TINT5 14
+#define IRQ_DM355_TINT2_TINT34 14
+#define IRQ_DM355_TINT6 15
+#define IRQ_DM355_TINT3_TINT12 15
+#define IRQ_DM355_SPINT1_0 17
+#define IRQ_DM355_SPINT1_1 18
+#define IRQ_DM355_SPINT2_0 19
+#define IRQ_DM355_SPINT2_1 21
+#define IRQ_DM355_TINT7 22
+#define IRQ_DM355_TINT3_TINT34 22
+#define IRQ_DM355_SDIOINT0 23
+#define IRQ_DM355_MMCINT0 26
+#define IRQ_DM355_MSINT 26
+#define IRQ_DM355_MMCINT1 27
+#define IRQ_DM355_PWMINT3 28
+#define IRQ_DM355_SDIOINT1 31
+#define IRQ_DM355_SPINT0_0 42
+#define IRQ_DM355_SPINT0_1 43
+#define IRQ_DM355_GPIO0 44
+#define IRQ_DM355_GPIO1 45
+#define IRQ_DM355_GPIO2 46
+#define IRQ_DM355_GPIO3 47
+#define IRQ_DM355_GPIO4 48
+#define IRQ_DM355_GPIO5 49
+#define IRQ_DM355_GPIO6 50
+#define IRQ_DM355_GPIO7 51
+#define IRQ_DM355_GPIO8 52
+#define IRQ_DM355_GPIO9 53
+#define IRQ_DM355_GPIOBNK0 54
+#define IRQ_DM355_GPIOBNK1 55
+#define IRQ_DM355_GPIOBNK2 56
+#define IRQ_DM355_GPIOBNK3 57
+#define IRQ_DM355_GPIOBNK4 58
+#define IRQ_DM355_GPIOBNK5 59
+#define IRQ_DM355_GPIOBNK6 60
+
#endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h
index c24b6782804d..bae22cb3e27b 100644
--- a/arch/arm/mach-davinci/include/mach/mux.h
+++ b/arch/arm/mach-davinci/include/mach/mux.h
@@ -1,55 +1,183 @@
/*
- * DaVinci pin multiplexing defines
+ * Table of the DAVINCI register configurations for the PINMUX combinations
*
* Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
*
+ * Based on linux/include/asm-arm/arch-omap/mux.h:
+ * Copyright (C) 2003 - 2005 Nokia Corporation
+ *
+ * Written by Tony Lindgren
+ *
* 2007 (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.
+ *
+ * Copyright (C) 2008 Texas Instruments.
*/
-#ifndef __ASM_ARCH_MUX_H
-#define __ASM_ARCH_MUX_H
-
-#define DAVINCI_MUX_AEAW0 0
-#define DAVINCI_MUX_AEAW1 1
-#define DAVINCI_MUX_AEAW2 2
-#define DAVINCI_MUX_AEAW3 3
-#define DAVINCI_MUX_AEAW4 4
-#define DAVINCI_MUX_AECS4 10
-#define DAVINCI_MUX_AECS5 11
-#define DAVINCI_MUX_VLYNQWD0 12
-#define DAVINCI_MUX_VLYNQWD1 13
-#define DAVINCI_MUX_VLSCREN 14
-#define DAVINCI_MUX_VLYNQEN 15
-#define DAVINCI_MUX_HDIREN 16
-#define DAVINCI_MUX_ATAEN 17
-#define DAVINCI_MUX_RGB666 22
-#define DAVINCI_MUX_RGB888 23
-#define DAVINCI_MUX_LOEEN 24
-#define DAVINCI_MUX_LFLDEN 25
-#define DAVINCI_MUX_CWEN 26
-#define DAVINCI_MUX_CFLDEN 27
-#define DAVINCI_MUX_HPIEN 29
-#define DAVINCI_MUX_1394EN 30
-#define DAVINCI_MUX_EMACEN 31
-
-#define DAVINCI_MUX_LEVEL2 32
-#define DAVINCI_MUX_UART0 (DAVINCI_MUX_LEVEL2 + 0)
-#define DAVINCI_MUX_UART1 (DAVINCI_MUX_LEVEL2 + 1)
-#define DAVINCI_MUX_UART2 (DAVINCI_MUX_LEVEL2 + 2)
-#define DAVINCI_MUX_U2FLO (DAVINCI_MUX_LEVEL2 + 3)
-#define DAVINCI_MUX_PWM0 (DAVINCI_MUX_LEVEL2 + 4)
-#define DAVINCI_MUX_PWM1 (DAVINCI_MUX_LEVEL2 + 5)
-#define DAVINCI_MUX_PWM2 (DAVINCI_MUX_LEVEL2 + 6)
-#define DAVINCI_MUX_I2C (DAVINCI_MUX_LEVEL2 + 7)
-#define DAVINCI_MUX_SPI (DAVINCI_MUX_LEVEL2 + 8)
-#define DAVINCI_MUX_MSTK (DAVINCI_MUX_LEVEL2 + 9)
-#define DAVINCI_MUX_ASP (DAVINCI_MUX_LEVEL2 + 10)
-#define DAVINCI_MUX_CLK0 (DAVINCI_MUX_LEVEL2 + 16)
-#define DAVINCI_MUX_CLK1 (DAVINCI_MUX_LEVEL2 + 17)
-#define DAVINCI_MUX_TIMIN (DAVINCI_MUX_LEVEL2 + 18)
-
-extern void davinci_mux_peripheral(unsigned int mux, unsigned int enable);
-
-#endif /* __ASM_ARCH_MUX_H */
+
+#ifndef __INC_MACH_MUX_H
+#define __INC_MACH_MUX_H
+
+/* System module registers */
+#define PINMUX0 0x00
+#define PINMUX1 0x04
+/* dm355 only */
+#define PINMUX2 0x08
+#define PINMUX3 0x0c
+#define PINMUX4 0x10
+#define INTMUX 0x18
+#define EVTMUX 0x1c
+
+struct mux_config {
+ const char *name;
+ const char *mux_reg_name;
+ const unsigned char mux_reg;
+ const unsigned char mask_offset;
+ const unsigned char mask;
+ const unsigned char mode;
+ bool debug;
+};
+
+enum davinci_dm644x_index {
+ /* ATA and HDDIR functions */
+ DM644X_HDIREN,
+ DM644X_ATAEN,
+ DM644X_ATAEN_DISABLE,
+
+ /* HPI functions */
+ DM644X_HPIEN_DISABLE,
+
+ /* AEAW functions */
+ DM644X_AEAW,
+
+ /* Memory Stick */
+ DM644X_MSTK,
+
+ /* I2C */
+ DM644X_I2C,
+
+ /* ASP function */
+ DM644X_MCBSP,
+
+ /* UART1 */
+ DM644X_UART1,
+
+ /* UART2 */
+ DM644X_UART2,
+
+ /* PWM0 */
+ DM644X_PWM0,
+
+ /* PWM1 */
+ DM644X_PWM1,
+
+ /* PWM2 */
+ DM644X_PWM2,
+
+ /* VLYNQ function */
+ DM644X_VLYNQEN,
+ DM644X_VLSCREN,
+ DM644X_VLYNQWD,
+
+ /* EMAC and MDIO function */
+ DM644X_EMACEN,
+
+ /* GPIO3V[0:16] pins */
+ DM644X_GPIO3V,
+
+ /* GPIO pins */
+ DM644X_GPIO0,
+ DM644X_GPIO3,
+ DM644X_GPIO43_44,
+ DM644X_GPIO46_47,
+
+ /* VPBE */
+ DM644X_RGB666,
+
+ /* LCD */
+ DM644X_LOEEN,
+ DM644X_LFLDEN,
+};
+
+enum davinci_dm646x_index {
+ /* ATA function */
+ DM646X_ATAEN,
+
+ /* AUDIO Clock */
+ DM646X_AUDCK1,
+ DM646X_AUDCK0,
+
+ /* CRGEN Control */
+ DM646X_CRGMUX,
+
+ /* VPIF Control */
+ DM646X_STSOMUX_DISABLE,
+ DM646X_STSIMUX_DISABLE,
+ DM646X_PTSOMUX_DISABLE,
+ DM646X_PTSIMUX_DISABLE,
+
+ /* TSIF Control */
+ DM646X_STSOMUX,
+ DM646X_STSIMUX,
+ DM646X_PTSOMUX_PARALLEL,
+ DM646X_PTSIMUX_PARALLEL,
+ DM646X_PTSOMUX_SERIAL,
+ DM646X_PTSIMUX_SERIAL,
+};
+
+enum davinci_dm355_index {
+ /* MMC/SD 0 */
+ DM355_MMCSD0,
+
+ /* MMC/SD 1 */
+ DM355_SD1_CLK,
+ DM355_SD1_CMD,
+ DM355_SD1_DATA3,
+ DM355_SD1_DATA2,
+ DM355_SD1_DATA1,
+ DM355_SD1_DATA0,
+
+ /* I2C */
+ DM355_I2C_SDA,
+ DM355_I2C_SCL,
+
+ /* ASP0 function */
+ DM355_MCBSP0_BDX,
+ DM355_MCBSP0_X,
+ DM355_MCBSP0_BFSX,
+ DM355_MCBSP0_BDR,
+ DM355_MCBSP0_R,
+ DM355_MCBSP0_BFSR,
+
+ /* SPI0 */
+ DM355_SPI0_SDI,
+ DM355_SPI0_SDENA0,
+ DM355_SPI0_SDENA1,
+
+ /* IRQ muxing */
+ DM355_INT_EDMA_CC,
+ DM355_INT_EDMA_TC0_ERR,
+ DM355_INT_EDMA_TC1_ERR,
+
+ /* EDMA event muxing */
+ DM355_EVT8_ASP1_TX,
+ DM355_EVT9_ASP1_RX,
+ DM355_EVT26_MMC0_RX,
+};
+
+#ifdef CONFIG_DAVINCI_MUX
+/* setup pin muxing */
+extern void davinci_mux_init(void);
+extern int davinci_mux_register(const struct mux_config *pins,
+ unsigned long size);
+extern int davinci_cfg_reg(unsigned long reg_cfg);
+#else
+/* boot loader does it all (no warnings from CONFIG_DAVINCI_MUX_WARNINGS) */
+static inline void davinci_mux_init(void) {}
+static inline int davinci_mux_register(const struct mux_config *pins,
+ unsigned long size) { return 0; }
+static inline int davinci_cfg_reg(unsigned long reg_cfg) { return 0; }
+#endif
+
+#endif /* __INC_MACH_MUX_H */
diff --git a/arch/arm/mach-davinci/include/mach/psc.h b/arch/arm/mach-davinci/include/mach/psc.h
index 4977aa071e1e..55a90d419fac 100644
--- a/arch/arm/mach-davinci/include/mach/psc.h
+++ b/arch/arm/mach-davinci/include/mach/psc.h
@@ -38,8 +38,6 @@
#define DAVINCI_LPSC_TPTC1 4
#define DAVINCI_LPSC_EMAC 5
#define DAVINCI_LPSC_EMAC_WRAPPER 6
-#define DAVINCI_LPSC_MDIO 7
-#define DAVINCI_LPSC_IEEE1394 8
#define DAVINCI_LPSC_USB 9
#define DAVINCI_LPSC_ATA 10
#define DAVINCI_LPSC_VLYNQ 11
@@ -47,7 +45,6 @@
#define DAVINCI_LPSC_DDR_EMIF 13
#define DAVINCI_LPSC_AEMIF 14
#define DAVINCI_LPSC_MMC_SD 15
-#define DAVINCI_LPSC_MEMSTICK 16
#define DAVINCI_LPSC_McBSP 17
#define DAVINCI_LPSC_I2C 18
#define DAVINCI_LPSC_UART0 19
@@ -73,4 +70,54 @@
#define DAVINCI_LPSC_GEM 39
#define DAVINCI_LPSC_IMCOP 40
+#define DM355_LPSC_TIMER3 5
+#define DM355_LPSC_SPI1 6
+#define DM355_LPSC_MMC_SD1 7
+#define DM355_LPSC_McBSP1 8
+#define DM355_LPSC_PWM3 10
+#define DM355_LPSC_SPI2 11
+#define DM355_LPSC_RTO 12
+#define DM355_LPSC_VPSS_DAC 41
+
+/*
+ * LPSC Assignments
+ */
+#define DM646X_LPSC_ARM 0
+#define DM646X_LPSC_C64X_CPU 1
+#define DM646X_LPSC_HDVICP0 2
+#define DM646X_LPSC_HDVICP1 3
+#define DM646X_LPSC_TPCC 4
+#define DM646X_LPSC_TPTC0 5
+#define DM646X_LPSC_TPTC1 6
+#define DM646X_LPSC_TPTC2 7
+#define DM646X_LPSC_TPTC3 8
+#define DM646X_LPSC_PCI 13
+#define DM646X_LPSC_EMAC 14
+#define DM646X_LPSC_VDCE 15
+#define DM646X_LPSC_VPSSMSTR 16
+#define DM646X_LPSC_VPSSSLV 17
+#define DM646X_LPSC_TSIF0 18
+#define DM646X_LPSC_TSIF1 19
+#define DM646X_LPSC_DDR_EMIF 20
+#define DM646X_LPSC_AEMIF 21
+#define DM646X_LPSC_McASP0 22
+#define DM646X_LPSC_McASP1 23
+#define DM646X_LPSC_CRGEN0 24
+#define DM646X_LPSC_CRGEN1 25
+#define DM646X_LPSC_UART0 26
+#define DM646X_LPSC_UART1 27
+#define DM646X_LPSC_UART2 28
+#define DM646X_LPSC_PWM0 29
+#define DM646X_LPSC_PWM1 30
+#define DM646X_LPSC_I2C 31
+#define DM646X_LPSC_SPI 32
+#define DM646X_LPSC_GPIO 33
+#define DM646X_LPSC_TIMER0 34
+#define DM646X_LPSC_TIMER1 35
+#define DM646X_LPSC_ARM_INTC 45
+
+extern int davinci_psc_is_clk_active(unsigned int id);
+extern void davinci_psc_config(unsigned int domain, unsigned int id,
+ char enable);
+
#endif /* __ASM_ARCH_PSC_H */
diff --git a/arch/arm/mach-davinci/include/mach/serial.h b/arch/arm/mach-davinci/include/mach/serial.h
index fb8cb229bfd2..632847d74a1c 100644
--- a/arch/arm/mach-davinci/include/mach/serial.h
+++ b/arch/arm/mach-davinci/include/mach/serial.h
@@ -13,8 +13,23 @@
#include <mach/io.h>
-#define DAVINCI_UART0_BASE (IO_PHYS + 0x20000)
-#define DAVINCI_UART1_BASE (IO_PHYS + 0x20400)
-#define DAVINCI_UART2_BASE (IO_PHYS + 0x20800)
+#define DAVINCI_MAX_NR_UARTS 3
+#define DAVINCI_UART0_BASE (IO_PHYS + 0x20000)
+#define DAVINCI_UART1_BASE (IO_PHYS + 0x20400)
+#define DAVINCI_UART2_BASE (IO_PHYS + 0x20800)
+
+#define DM355_UART2_BASE (IO_PHYS + 0x206000)
+
+/* DaVinci UART register offsets */
+#define UART_DAVINCI_PWREMU 0x0c
+#define UART_DM646X_SCR 0x10
+#define UART_DM646X_SCR_TX_WATERMARK 0x08
+
+struct davinci_uart_config {
+ /* Bit field of UARTs present; bit 0 --> UART1 */
+ unsigned int enabled_uarts;
+};
+
+extern void davinci_serial_init(struct davinci_uart_config *);
#endif /* __ASM_ARCH_SERIAL_H */
diff --git a/arch/arm/mach-davinci/io.c b/arch/arm/mach-davinci/io.c
index 299515f70b8b..a548abb513e2 100644
--- a/arch/arm/mach-davinci/io.c
+++ b/arch/arm/mach-davinci/io.c
@@ -51,7 +51,26 @@ void __init davinci_map_common_io(void)
davinci_check_revision();
}
-void __init davinci_init_common_hw(void)
+#define BETWEEN(p, st, sz) ((p) >= (st) && (p) < ((st) + (sz)))
+#define XLATE(p, pst, vst) ((void __iomem *)((p) - (pst) + (vst)))
+
+/*
+ * Intercept ioremap() requests for addresses in our fixed mapping regions.
+ */
+void __iomem *davinci_ioremap(unsigned long p, size_t size, unsigned int type)
+{
+ if (BETWEEN(p, IO_PHYS, IO_SIZE))
+ return XLATE(p, IO_PHYS, IO_VIRT);
+
+ return __arm_ioremap(p, size, type);
+}
+EXPORT_SYMBOL(davinci_ioremap);
+
+void davinci_iounmap(volatile void __iomem *addr)
{
- davinci_clk_init();
+ unsigned long virt = (unsigned long)addr;
+
+ if (virt >= VMALLOC_START && virt < VMALLOC_END)
+ __iounmap(addr);
}
+EXPORT_SYMBOL(davinci_iounmap);
diff --git a/arch/arm/mach-davinci/irq.c b/arch/arm/mach-davinci/irq.c
index 38021af8359a..5a324c90e291 100644
--- a/arch/arm/mach-davinci/irq.c
+++ b/arch/arm/mach-davinci/irq.c
@@ -25,6 +25,7 @@
#include <linux/io.h>
#include <mach/hardware.h>
+#include <mach/cputype.h>
#include <asm/mach/irq.h>
#define IRQ_BIT(irq) ((irq) & 0x1f)
@@ -40,14 +41,18 @@
#define IRQ_INTPRI0_REG_OFFSET 0x0030
#define IRQ_INTPRI7_REG_OFFSET 0x004C
+const u8 *davinci_def_priorities;
+
+#define INTC_BASE IO_ADDRESS(DAVINCI_ARM_INTC_BASE)
+
static inline unsigned int davinci_irq_readl(int offset)
{
- return davinci_readl(DAVINCI_ARM_INTC_BASE + offset);
+ return __raw_readl(INTC_BASE + offset);
}
static inline void davinci_irq_writel(unsigned long value, int offset)
{
- davinci_writel(value, DAVINCI_ARM_INTC_BASE + offset);
+ __raw_writel(value, INTC_BASE + offset);
}
/* Disable interrupt */
@@ -108,9 +113,8 @@ static struct irq_chip davinci_irq_chip_0 = {
.unmask = davinci_unmask_irq,
};
-
/* FIQ are pri 0-1; otherwise 2-7, with 7 lowest priority */
-static const u8 default_priorities[DAVINCI_N_AINTC_IRQ] __initdata = {
+static const u8 dm644x_default_priorities[DAVINCI_N_AINTC_IRQ] __initdata = {
[IRQ_VDINT0] = 2,
[IRQ_VDINT1] = 6,
[IRQ_VDINT2] = 6,
@@ -177,11 +181,149 @@ static const u8 default_priorities[DAVINCI_N_AINTC_IRQ] __initdata = {
[IRQ_EMUINT] = 7,
};
+static const u8 dm646x_default_priorities[DAVINCI_N_AINTC_IRQ] = {
+ [IRQ_DM646X_VP_VERTINT0] = 7,
+ [IRQ_DM646X_VP_VERTINT1] = 7,
+ [IRQ_DM646X_VP_VERTINT2] = 7,
+ [IRQ_DM646X_VP_VERTINT3] = 7,
+ [IRQ_DM646X_VP_ERRINT] = 7,
+ [IRQ_DM646X_RESERVED_1] = 7,
+ [IRQ_DM646X_RESERVED_2] = 7,
+ [IRQ_DM646X_WDINT] = 7,
+ [IRQ_DM646X_CRGENINT0] = 7,
+ [IRQ_DM646X_CRGENINT1] = 7,
+ [IRQ_DM646X_TSIFINT0] = 7,
+ [IRQ_DM646X_TSIFINT1] = 7,
+ [IRQ_DM646X_VDCEINT] = 7,
+ [IRQ_DM646X_USBINT] = 7,
+ [IRQ_DM646X_USBDMAINT] = 7,
+ [IRQ_DM646X_PCIINT] = 7,
+ [IRQ_CCINT0] = 7, /* dma */
+ [IRQ_CCERRINT] = 7, /* dma */
+ [IRQ_TCERRINT0] = 7, /* dma */
+ [IRQ_TCERRINT] = 7, /* dma */
+ [IRQ_DM646X_TCERRINT2] = 7,
+ [IRQ_DM646X_TCERRINT3] = 7,
+ [IRQ_DM646X_IDE] = 7,
+ [IRQ_DM646X_HPIINT] = 7,
+ [IRQ_DM646X_EMACRXTHINT] = 7,
+ [IRQ_DM646X_EMACRXINT] = 7,
+ [IRQ_DM646X_EMACTXINT] = 7,
+ [IRQ_DM646X_EMACMISCINT] = 7,
+ [IRQ_DM646X_MCASP0TXINT] = 7,
+ [IRQ_DM646X_MCASP0RXINT] = 7,
+ [IRQ_AEMIFINT] = 7,
+ [IRQ_DM646X_RESERVED_3] = 7,
+ [IRQ_DM646X_MCASP1TXINT] = 7, /* clockevent */
+ [IRQ_TINT0_TINT34] = 7, /* clocksource */
+ [IRQ_TINT1_TINT12] = 7, /* DSP timer */
+ [IRQ_TINT1_TINT34] = 7, /* system tick */
+ [IRQ_PWMINT0] = 7,
+ [IRQ_PWMINT1] = 7,
+ [IRQ_DM646X_VLQINT] = 7,
+ [IRQ_I2C] = 7,
+ [IRQ_UARTINT0] = 7,
+ [IRQ_UARTINT1] = 7,
+ [IRQ_DM646X_UARTINT2] = 7,
+ [IRQ_DM646X_SPINT0] = 7,
+ [IRQ_DM646X_SPINT1] = 7,
+ [IRQ_DM646X_DSP2ARMINT] = 7,
+ [IRQ_DM646X_RESERVED_4] = 7,
+ [IRQ_DM646X_PSCINT] = 7,
+ [IRQ_DM646X_GPIO0] = 7,
+ [IRQ_DM646X_GPIO1] = 7,
+ [IRQ_DM646X_GPIO2] = 7,
+ [IRQ_DM646X_GPIO3] = 7,
+ [IRQ_DM646X_GPIO4] = 7,
+ [IRQ_DM646X_GPIO5] = 7,
+ [IRQ_DM646X_GPIO6] = 7,
+ [IRQ_DM646X_GPIO7] = 7,
+ [IRQ_DM646X_GPIOBNK0] = 7,
+ [IRQ_DM646X_GPIOBNK1] = 7,
+ [IRQ_DM646X_GPIOBNK2] = 7,
+ [IRQ_DM646X_DDRINT] = 7,
+ [IRQ_DM646X_AEMIFINT] = 7,
+ [IRQ_COMMTX] = 7,
+ [IRQ_COMMRX] = 7,
+ [IRQ_EMUINT] = 7,
+};
+
+static const u8 dm355_default_priorities[DAVINCI_N_AINTC_IRQ] = {
+ [IRQ_DM355_CCDC_VDINT0] = 2,
+ [IRQ_DM355_CCDC_VDINT1] = 6,
+ [IRQ_DM355_CCDC_VDINT2] = 6,
+ [IRQ_DM355_IPIPE_HST] = 6,
+ [IRQ_DM355_H3AINT] = 6,
+ [IRQ_DM355_IPIPE_SDR] = 6,
+ [IRQ_DM355_IPIPEIFINT] = 6,
+ [IRQ_DM355_OSDINT] = 7,
+ [IRQ_DM355_VENCINT] = 6,
+ [IRQ_ASQINT] = 6,
+ [IRQ_IMXINT] = 6,
+ [IRQ_USBINT] = 4,
+ [IRQ_DM355_RTOINT] = 4,
+ [IRQ_DM355_UARTINT2] = 7,
+ [IRQ_DM355_TINT6] = 7,
+ [IRQ_CCINT0] = 5, /* dma */
+ [IRQ_CCERRINT] = 5, /* dma */
+ [IRQ_TCERRINT0] = 5, /* dma */
+ [IRQ_TCERRINT] = 5, /* dma */
+ [IRQ_DM355_SPINT2_1] = 7,
+ [IRQ_DM355_TINT7] = 4,
+ [IRQ_DM355_SDIOINT0] = 7,
+ [IRQ_MBXINT] = 7,
+ [IRQ_MBRINT] = 7,
+ [IRQ_MMCINT] = 7,
+ [IRQ_DM355_MMCINT1] = 7,
+ [IRQ_DM355_PWMINT3] = 7,
+ [IRQ_DDRINT] = 7,
+ [IRQ_AEMIFINT] = 7,
+ [IRQ_DM355_SDIOINT1] = 4,
+ [IRQ_TINT0_TINT12] = 2, /* clockevent */
+ [IRQ_TINT0_TINT34] = 2, /* clocksource */
+ [IRQ_TINT1_TINT12] = 7, /* DSP timer */
+ [IRQ_TINT1_TINT34] = 7, /* system tick */
+ [IRQ_PWMINT0] = 7,
+ [IRQ_PWMINT1] = 7,
+ [IRQ_PWMINT2] = 7,
+ [IRQ_I2C] = 3,
+ [IRQ_UARTINT0] = 3,
+ [IRQ_UARTINT1] = 3,
+ [IRQ_DM355_SPINT0_0] = 3,
+ [IRQ_DM355_SPINT0_1] = 3,
+ [IRQ_DM355_GPIO0] = 3,
+ [IRQ_DM355_GPIO1] = 7,
+ [IRQ_DM355_GPIO2] = 4,
+ [IRQ_DM355_GPIO3] = 4,
+ [IRQ_DM355_GPIO4] = 7,
+ [IRQ_DM355_GPIO5] = 7,
+ [IRQ_DM355_GPIO6] = 7,
+ [IRQ_DM355_GPIO7] = 7,
+ [IRQ_DM355_GPIO8] = 7,
+ [IRQ_DM355_GPIO9] = 7,
+ [IRQ_DM355_GPIOBNK0] = 7,
+ [IRQ_DM355_GPIOBNK1] = 7,
+ [IRQ_DM355_GPIOBNK2] = 7,
+ [IRQ_DM355_GPIOBNK3] = 7,
+ [IRQ_DM355_GPIOBNK4] = 7,
+ [IRQ_DM355_GPIOBNK5] = 7,
+ [IRQ_DM355_GPIOBNK6] = 7,
+ [IRQ_COMMTX] = 7,
+ [IRQ_COMMRX] = 7,
+ [IRQ_EMUINT] = 7,
+};
+
/* ARM Interrupt Controller Initialization */
void __init davinci_irq_init(void)
{
unsigned i;
- const u8 *priority = default_priorities;
+
+ if (cpu_is_davinci_dm644x())
+ davinci_def_priorities = dm644x_default_priorities;
+ else if (cpu_is_davinci_dm646x())
+ davinci_def_priorities = dm646x_default_priorities;
+ else if (cpu_is_davinci_dm355())
+ davinci_def_priorities = dm355_default_priorities;
/* Clear all interrupt requests */
davinci_irq_writel(~0x0, FIQ_REG0_OFFSET);
@@ -209,8 +351,8 @@ void __init davinci_irq_init(void)
unsigned j;
u32 pri;
- for (j = 0, pri = 0; j < 32; j += 4, priority++)
- pri |= (*priority & 0x07) << j;
+ for (j = 0, pri = 0; j < 32; j += 4, davinci_def_priorities++)
+ pri |= (*davinci_def_priorities & 0x07) << j;
davinci_irq_writel(pri, i);
}
diff --git a/arch/arm/mach-davinci/mux.c b/arch/arm/mach-davinci/mux.c
index 8ff9d8aca60b..bbba0b247a44 100644
--- a/arch/arm/mach-davinci/mux.c
+++ b/arch/arm/mach-davinci/mux.c
@@ -1,41 +1,103 @@
/*
- * DaVinci pin multiplexing configurations
+ * Utility to set the DAVINCI MUX register from a table in mux.h
*
* Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
*
+ * Based on linux/arch/arm/plat-omap/mux.c:
+ * Copyright (C) 2003 - 2005 Nokia Corporation
+ *
+ * Written by Tony Lindgren
+ *
* 2007 (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.
+ *
+ * Copyright (C) 2008 Texas Instruments.
*/
#include <linux/io.h>
+#include <linux/module.h>
#include <linux/spinlock.h>
#include <mach/hardware.h>
-
#include <mach/mux.h>
-/* System control register offsets */
-#define PINMUX0 0x00
-#define PINMUX1 0x04
+static const struct mux_config *mux_table;
+static unsigned long pin_table_sz;
+
+int __init davinci_mux_register(const struct mux_config *pins,
+ unsigned long size)
+{
+ mux_table = pins;
+ pin_table_sz = size;
-static DEFINE_SPINLOCK(mux_lock);
+ return 0;
+}
-void davinci_mux_peripheral(unsigned int mux, unsigned int enable)
+/*
+ * Sets the DAVINCI MUX register based on the table
+ */
+int __init_or_module davinci_cfg_reg(const unsigned long index)
{
- u32 pinmux, muxreg = PINMUX0;
+ static DEFINE_SPINLOCK(mux_spin_lock);
+ void __iomem *base = IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE);
+ unsigned long flags;
+ const struct mux_config *cfg;
+ unsigned int reg_orig = 0, reg = 0;
+ unsigned int mask, warn = 0;
+
+ if (!mux_table)
+ BUG();
+
+ if (index >= pin_table_sz) {
+ printk(KERN_ERR "Invalid pin mux index: %lu (%lu)\n",
+ index, pin_table_sz);
+ dump_stack();
+ return -ENODEV;
+ }
+
+ cfg = &mux_table[index];
+
+ if (cfg->name == NULL) {
+ printk(KERN_ERR "No entry for the specified index\n");
+ return -ENODEV;
+ }
+
+ /* Update the mux register in question */
+ if (cfg->mask) {
+ unsigned tmp1, tmp2;
+
+ spin_lock_irqsave(&mux_spin_lock, flags);
+ reg_orig = __raw_readl(base + cfg->mux_reg);
+
+ mask = (cfg->mask << cfg->mask_offset);
+ tmp1 = reg_orig & mask;
+ reg = reg_orig & ~mask;
+
+ tmp2 = (cfg->mode << cfg->mask_offset);
+ reg |= tmp2;
+
+ if (tmp1 != tmp2)
+ warn = 1;
+
+ __raw_writel(reg, base + cfg->mux_reg);
+ spin_unlock_irqrestore(&mux_spin_lock, flags);
+ }
+
+ if (warn) {
+#ifdef CONFIG_DAVINCI_MUX_WARNINGS
+ printk(KERN_WARNING "MUX: initialized %s\n", cfg->name);
+#endif
+ }
- if (mux >= DAVINCI_MUX_LEVEL2) {
- muxreg = PINMUX1;
- mux -= DAVINCI_MUX_LEVEL2;
+#ifdef CONFIG_DAVINCI_MUX_DEBUG
+ if (cfg->debug || warn) {
+ printk(KERN_WARNING "MUX: Setting register %s\n", cfg->name);
+ printk(KERN_WARNING " %s (0x%08x) = 0x%08x -> 0x%08x\n",
+ cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg);
}
+#endif
- spin_lock(&mux_lock);
- pinmux = davinci_readl(DAVINCI_SYSTEM_MODULE_BASE + muxreg);
- if (enable)
- pinmux |= (1 << mux);
- else
- pinmux &= ~(1 << mux);
- davinci_writel(pinmux, DAVINCI_SYSTEM_MODULE_BASE + muxreg);
- spin_unlock(&mux_lock);
+ return 0;
}
+EXPORT_SYMBOL(davinci_cfg_reg);
diff --git a/arch/arm/mach-davinci/mux.h b/arch/arm/mach-davinci/mux.h
new file mode 100644
index 000000000000..adc869413371
--- /dev/null
+++ b/arch/arm/mach-davinci/mux.h
@@ -0,0 +1,51 @@
+/*
+ * Pin-multiplex helper macros for TI DaVinci family devices
+ *
+ * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2007 (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.
+ *
+ * Copyright (C) 2008 Texas Instruments.
+ */
+#ifndef _MACH_DAVINCI_MUX_H_
+#define _MACH_DAVINCI_MUX_H_
+
+#include <mach/mux.h>
+
+#define MUX_CFG(soc, desc, muxreg, mode_offset, mode_mask, mux_mode, dbg)\
+[soc##_##desc] = { \
+ .name = #desc, \
+ .debug = dbg, \
+ .mux_reg_name = "PINMUX"#muxreg, \
+ .mux_reg = PINMUX##muxreg, \
+ .mask_offset = mode_offset, \
+ .mask = mode_mask, \
+ .mode = mux_mode, \
+ },
+
+#define INT_CFG(soc, desc, mode_offset, mode_mask, mux_mode, dbg) \
+[soc##_##desc] = { \
+ .name = #desc, \
+ .debug = dbg, \
+ .mux_reg_name = "INTMUX", \
+ .mux_reg = INTMUX, \
+ .mask_offset = mode_offset, \
+ .mask = mode_mask, \
+ .mode = mux_mode, \
+ },
+
+#define EVT_CFG(soc, desc, mode_offset, mode_mask, mux_mode, dbg) \
+[soc##_##desc] = { \
+ .name = #desc, \
+ .debug = dbg, \
+ .mux_reg_name = "EVTMUX", \
+ .mux_reg = EVTMUX, \
+ .mask_offset = mode_offset, \
+ .mask = mode_mask, \
+ .mode = mux_mode, \
+ },
+
+#endif /* _MACH_DAVINCI_MUX_H */
diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c
index 58754f066d5b..84171abf5f7b 100644
--- a/arch/arm/mach-davinci/psc.c
+++ b/arch/arm/mach-davinci/psc.c
@@ -23,10 +23,13 @@
#include <linux/init.h>
#include <linux/io.h>
+#include <mach/cputype.h>
#include <mach/hardware.h>
#include <mach/psc.h>
#include <mach/mux.h>
+#define DAVINCI_PWR_SLEEP_CNTRL_BASE 0x01C41000
+
/* PSC register offsets */
#define EPCPR 0x070
#define PTCMD 0x120
@@ -36,102 +39,61 @@
#define MDSTAT 0x800
#define MDCTL 0xA00
-/* System control register offsets */
-#define VDD3P3V_PWDN 0x48
+#define MDSTAT_STATE_MASK 0x1f
-static void davinci_psc_mux(unsigned int id)
+/* Return nonzero iff the domain's clock is active */
+int __init davinci_psc_is_clk_active(unsigned int id)
{
- switch (id) {
- case DAVINCI_LPSC_ATA:
- davinci_mux_peripheral(DAVINCI_MUX_HDIREN, 1);
- davinci_mux_peripheral(DAVINCI_MUX_ATAEN, 1);
- break;
- case DAVINCI_LPSC_MMC_SD:
- /* VDD power manupulations are done in U-Boot for CPMAC
- * so applies to MMC as well
- */
- /*Set up the pull regiter for MMC */
- davinci_writel(0, DAVINCI_SYSTEM_MODULE_BASE + VDD3P3V_PWDN);
- davinci_mux_peripheral(DAVINCI_MUX_MSTK, 0);
- break;
- case DAVINCI_LPSC_I2C:
- davinci_mux_peripheral(DAVINCI_MUX_I2C, 1);
- break;
- case DAVINCI_LPSC_McBSP:
- davinci_mux_peripheral(DAVINCI_MUX_ASP, 1);
- break;
- default:
- break;
- }
+ void __iomem *psc_base = IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE);
+ u32 mdstat = __raw_readl(psc_base + MDSTAT + 4 * id);
+
+ /* if clocked, state can be "Enable" or "SyncReset" */
+ return mdstat & BIT(12);
}
/* Enable or disable a PSC domain */
void davinci_psc_config(unsigned int domain, unsigned int id, char enable)
{
- u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl, mdstat_mask;
+ u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl;
+ void __iomem *psc_base = IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE);
+ u32 next_state = enable ? 0x3 : 0x2; /* 0x3 enables, 0x2 disables */
- mdctl = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id);
- if (enable)
- mdctl |= 0x00000003; /* Enable Module */
- else
- mdctl &= 0xFFFFFFF2; /* Disable Module */
- davinci_writel(mdctl, DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id);
+ mdctl = __raw_readl(psc_base + MDCTL + 4 * id);
+ mdctl &= ~MDSTAT_STATE_MASK;
+ mdctl |= next_state;
+ __raw_writel(mdctl, psc_base + MDCTL + 4 * id);
- pdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDSTAT);
+ pdstat = __raw_readl(psc_base + PDSTAT);
if ((pdstat & 0x00000001) == 0) {
- pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+ pdctl1 = __raw_readl(psc_base + PDCTL1);
pdctl1 |= 0x1;
- davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+ __raw_writel(pdctl1, psc_base + PDCTL1);
ptcmd = 1 << domain;
- davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD);
+ __raw_writel(ptcmd, psc_base + PTCMD);
do {
- epcpr = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
- EPCPR);
+ epcpr = __raw_readl(psc_base + EPCPR);
} while ((((epcpr >> domain) & 1) == 0));
- pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+ pdctl1 = __raw_readl(psc_base + PDCTL1);
pdctl1 |= 0x100;
- davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+ __raw_writel(pdctl1, psc_base + PDCTL1);
do {
- ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+ ptstat = __raw_readl(psc_base +
PTSTAT);
} while (!(((ptstat >> domain) & 1) == 0));
} else {
ptcmd = 1 << domain;
- davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD);
+ __raw_writel(ptcmd, psc_base + PTCMD);
do {
- ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
- PTSTAT);
+ ptstat = __raw_readl(psc_base + PTSTAT);
} while (!(((ptstat >> domain) & 1) == 0));
}
- if (enable)
- mdstat_mask = 0x3;
- else
- mdstat_mask = 0x2;
-
do {
- mdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
- MDSTAT + 4 * id);
- } while (!((mdstat & 0x0000001F) == mdstat_mask));
-
- if (enable)
- davinci_psc_mux(id);
-}
-
-void __init davinci_psc_init(void)
-{
- davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_VPSSMSTR, 1);
- davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_VPSSSLV, 1);
- davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPCC, 1);
- davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC0, 1);
- davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC1, 1);
- davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_GPIO, 1);
-
- /* Turn on WatchDog timer LPSC. Needed for RESET to work */
- davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TIMER2, 1);
+ mdstat = __raw_readl(psc_base + MDSTAT + 4 * id);
+ } while (!((mdstat & MDSTAT_STATE_MASK) == next_state));
}
diff --git a/arch/arm/mach-davinci/serial.c b/arch/arm/mach-davinci/serial.c
index 3010f9971255..695075796522 100644
--- a/arch/arm/mach-davinci/serial.c
+++ b/arch/arm/mach-davinci/serial.c
@@ -32,32 +32,47 @@
#include <mach/hardware.h>
#include <mach/serial.h>
#include <mach/irqs.h>
+#include <mach/cputype.h>
+#include "clock.h"
-#define UART_DAVINCI_PWREMU 0x0c
-
-static inline unsigned int davinci_serial_in(struct plat_serial8250_port *up,
- int offset)
+static inline unsigned int serial_read_reg(struct plat_serial8250_port *up,
+ int offset)
{
offset <<= up->regshift;
- return (unsigned int)__raw_readb(up->membase + offset);
+ return (unsigned int)__raw_readl(IO_ADDRESS(up->mapbase) + offset);
}
-static inline void davinci_serial_outp(struct plat_serial8250_port *p,
- int offset, int value)
+static inline void serial_write_reg(struct plat_serial8250_port *p, int offset,
+ int value)
{
offset <<= p->regshift;
- __raw_writeb(value, p->membase + offset);
+ __raw_writel(value, IO_ADDRESS(p->mapbase) + offset);
}
static struct plat_serial8250_port serial_platform_data[] = {
{
- .membase = (char *)IO_ADDRESS(DAVINCI_UART0_BASE),
- .mapbase = (unsigned long)DAVINCI_UART0_BASE,
+ .mapbase = DAVINCI_UART0_BASE,
.irq = IRQ_UARTINT0,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
+ UPF_IOREMAP,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ },
+ {
+ .mapbase = DAVINCI_UART1_BASE,
+ .irq = IRQ_UARTINT1,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
+ UPF_IOREMAP,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ },
+ {
+ .mapbase = DAVINCI_UART2_BASE,
+ .irq = IRQ_UARTINT2,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
+ UPF_IOREMAP,
.iotype = UPIO_MEM,
.regshift = 2,
- .uartclk = 27000000,
},
{
.flags = 0
@@ -74,22 +89,68 @@ static struct platform_device serial_device = {
static void __init davinci_serial_reset(struct plat_serial8250_port *p)
{
- /* reset both transmitter and receiver: bits 14,13 = UTRST, URRST */
unsigned int pwremu = 0;
- davinci_serial_outp(p, UART_IER, 0); /* disable all interrupts */
+ serial_write_reg(p, UART_IER, 0); /* disable all interrupts */
- davinci_serial_outp(p, UART_DAVINCI_PWREMU, pwremu);
+ /* reset both transmitter and receiver: bits 14,13 = UTRST, URRST */
+ serial_write_reg(p, UART_DAVINCI_PWREMU, pwremu);
mdelay(10);
pwremu |= (0x3 << 13);
pwremu |= 0x1;
- davinci_serial_outp(p, UART_DAVINCI_PWREMU, pwremu);
+ serial_write_reg(p, UART_DAVINCI_PWREMU, pwremu);
+
+ if (cpu_is_davinci_dm646x())
+ serial_write_reg(p, UART_DM646X_SCR,
+ UART_DM646X_SCR_TX_WATERMARK);
+}
+
+void __init davinci_serial_init(struct davinci_uart_config *info)
+{
+ int i;
+ char name[16];
+ struct clk *uart_clk;
+ struct device *dev = &serial_device.dev;
+
+ /*
+ * Make sure the serial ports are muxed on at this point.
+ * You have to mux them off in device drivers later on
+ * if not needed.
+ */
+ for (i = 0; i < DAVINCI_MAX_NR_UARTS; i++) {
+ struct plat_serial8250_port *p = serial_platform_data + i;
+
+ if (!(info->enabled_uarts & (1 << i))) {
+ p->flags = 0;
+ continue;
+ }
+
+ if (cpu_is_davinci_dm646x())
+ p->iotype = UPIO_MEM32;
+
+ if (cpu_is_davinci_dm355()) {
+ if (i == 2) {
+ p->mapbase = (unsigned long)DM355_UART2_BASE;
+ p->irq = IRQ_DM355_UARTINT2;
+ }
+ }
+
+ sprintf(name, "uart%d", i);
+ uart_clk = clk_get(dev, name);
+ if (IS_ERR(uart_clk))
+ printk(KERN_ERR "%s:%d: failed to get UART%d clock\n",
+ __func__, __LINE__, i);
+ else {
+ clk_enable(uart_clk);
+ p->uartclk = clk_get_rate(uart_clk);
+ davinci_serial_reset(p);
+ }
+ }
}
static int __init davinci_init(void)
{
- davinci_serial_reset(&serial_platform_data[0]);
return platform_device_register(&serial_device);
}
diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c
index f8bcd29d17a6..494e01bff5c3 100644
--- a/arch/arm/mach-davinci/time.c
+++ b/arch/arm/mach-davinci/time.c
@@ -16,6 +16,9 @@
#include <linux/clockchips.h>
#include <linux/spinlock.h>
#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/device.h>
#include <mach/hardware.h>
#include <asm/system.h>
@@ -24,8 +27,11 @@
#include <asm/mach/time.h>
#include <asm/errno.h>
#include <mach/io.h>
+#include <mach/cputype.h>
+#include "clock.h"
static struct clock_event_device clockevent_davinci;
+static unsigned int davinci_clock_tick_rate;
#define DAVINCI_TIMER0_BASE (IO_PHYS + 0x21400)
#define DAVINCI_TIMER1_BASE (IO_PHYS + 0x21800)
@@ -99,9 +105,9 @@ struct timer_s {
unsigned int id;
unsigned long period;
unsigned long opts;
- unsigned long reg_base;
- unsigned long tim_reg;
- unsigned long prd_reg;
+ void __iomem *base;
+ unsigned long tim_off;
+ unsigned long prd_off;
unsigned long enamode_shift;
struct irqaction irqaction;
};
@@ -114,15 +120,15 @@ static struct timer_s timers[];
static int timer32_config(struct timer_s *t)
{
- u32 tcr = davinci_readl(t->reg_base + TCR);
+ u32 tcr = __raw_readl(t->base + TCR);
/* disable timer */
tcr &= ~(TCR_ENAMODE_MASK << t->enamode_shift);
- davinci_writel(tcr, t->reg_base + TCR);
+ __raw_writel(tcr, t->base + TCR);
/* reset counter to zero, set new period */
- davinci_writel(0, t->tim_reg);
- davinci_writel(t->period, t->prd_reg);
+ __raw_writel(0, t->base + t->tim_off);
+ __raw_writel(t->period, t->base + t->prd_off);
/* Set enable mode */
if (t->opts & TIMER_OPTS_ONESHOT) {
@@ -131,13 +137,13 @@ static int timer32_config(struct timer_s *t)
tcr |= TCR_ENAMODE_PERIODIC << t->enamode_shift;
}
- davinci_writel(tcr, t->reg_base + TCR);
+ __raw_writel(tcr, t->base + TCR);
return 0;
}
static inline u32 timer32_read(struct timer_s *t)
{
- return davinci_readl(t->tim_reg);
+ return __raw_readl(t->base + t->tim_off);
}
static irqreturn_t timer_interrupt(int irq, void *dev_id)
@@ -176,51 +182,54 @@ static struct timer_s timers[] = {
static void __init timer_init(void)
{
- u32 bases[] = {DAVINCI_TIMER0_BASE, DAVINCI_TIMER1_BASE};
+ u32 phys_bases[] = {DAVINCI_TIMER0_BASE, DAVINCI_TIMER1_BASE};
int i;
/* Global init of each 64-bit timer as a whole */
for(i=0; i<2; i++) {
- u32 tgcr, base = bases[i];
+ u32 tgcr;
+ void __iomem *base = IO_ADDRESS(phys_bases[i]);
/* Disabled, Internal clock source */
- davinci_writel(0, base + TCR);
+ __raw_writel(0, base + TCR);
/* reset both timers, no pre-scaler for timer34 */
tgcr = 0;
- davinci_writel(tgcr, base + TGCR);
+ __raw_writel(tgcr, base + TGCR);
/* Set both timers to unchained 32-bit */
tgcr = TGCR_TIMMODE_32BIT_UNCHAINED << TGCR_TIMMODE_SHIFT;
- davinci_writel(tgcr, base + TGCR);
+ __raw_writel(tgcr, base + TGCR);
/* Unreset timers */
tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) |
(TGCR_UNRESET << TGCR_TIM34RS_SHIFT);
- davinci_writel(tgcr, base + TGCR);
+ __raw_writel(tgcr, base + TGCR);
/* Init both counters to zero */
- davinci_writel(0, base + TIM12);
- davinci_writel(0, base + TIM34);
+ __raw_writel(0, base + TIM12);
+ __raw_writel(0, base + TIM34);
}
/* Init of each timer as a 32-bit timer */
for (i=0; i< ARRAY_SIZE(timers); i++) {
struct timer_s *t = &timers[i];
+ u32 phys_base;
if (t->name) {
t->id = i;
- t->reg_base = (IS_TIMER1(t->id) ?
+ phys_base = (IS_TIMER1(t->id) ?
DAVINCI_TIMER1_BASE : DAVINCI_TIMER0_BASE);
+ t->base = IO_ADDRESS(phys_base);
if (IS_TIMER_BOT(t->id)) {
t->enamode_shift = 6;
- t->tim_reg = t->reg_base + TIM12;
- t->prd_reg = t->reg_base + PRD12;
+ t->tim_off = TIM12;
+ t->prd_off = PRD12;
} else {
t->enamode_shift = 22;
- t->tim_reg = t->reg_base + TIM34;
- t->prd_reg = t->reg_base + PRD34;
+ t->tim_off = TIM34;
+ t->prd_off = PRD34;
}
/* Register interrupt */
@@ -238,7 +247,7 @@ static void __init timer_init(void)
/*
* clocksource
*/
-static cycle_t read_cycles(void)
+static cycle_t read_cycles(struct clocksource *cs)
{
struct timer_s *t = &timers[TID_CLOCKSOURCE];
@@ -274,7 +283,7 @@ static void davinci_set_mode(enum clock_event_mode mode,
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
- t->period = CLOCK_TICK_RATE / (HZ);
+ t->period = davinci_clock_tick_rate / (HZ);
t->opts = TIMER_OPTS_PERIODIC;
timer32_config(t);
break;
@@ -301,21 +310,29 @@ static struct clock_event_device clockevent_davinci = {
static void __init davinci_timer_init(void)
{
+ struct clk *timer_clk;
+
static char err[] __initdata = KERN_ERR
"%s: can't register clocksource!\n";
/* init timer hw */
timer_init();
+ timer_clk = clk_get(NULL, "timer0");
+ BUG_ON(IS_ERR(timer_clk));
+ clk_enable(timer_clk);
+
+ davinci_clock_tick_rate = clk_get_rate(timer_clk);
+
/* setup clocksource */
clocksource_davinci.mult =
- clocksource_khz2mult(CLOCK_TICK_RATE/1000,
+ clocksource_khz2mult(davinci_clock_tick_rate/1000,
clocksource_davinci.shift);
if (clocksource_register(&clocksource_davinci))
printk(err, clocksource_davinci.name);
/* setup clockevent */
- clockevent_davinci.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
+ clockevent_davinci.mult = div_sc(davinci_clock_tick_rate, NSEC_PER_SEC,
clockevent_davinci.shift);
clockevent_davinci.max_delta_ns =
clockevent_delta2ns(0xfffffffe, &clockevent_davinci);
@@ -333,42 +350,52 @@ struct sys_timer davinci_timer = {
/* reset board using watchdog timer */
void davinci_watchdog_reset(void) {
- u32 tgcr, wdtcr, base = DAVINCI_WDOG_BASE;
+ u32 tgcr, wdtcr;
+ void __iomem *base = IO_ADDRESS(DAVINCI_WDOG_BASE);
+ struct device dev;
+ struct clk *wd_clk;
+ char *name = "watchdog";
+
+ dev_set_name(&dev, name);
+ wd_clk = clk_get(&dev, NULL);
+ if (WARN_ON(IS_ERR(wd_clk)))
+ return;
+ clk_enable(wd_clk);
/* disable, internal clock source */
- davinci_writel(0, base + TCR);
+ __raw_writel(0, base + TCR);
/* reset timer, set mode to 64-bit watchdog, and unreset */
tgcr = 0;
- davinci_writel(tgcr, base + TCR);
+ __raw_writel(tgcr, base + TCR);
tgcr = TGCR_TIMMODE_64BIT_WDOG << TGCR_TIMMODE_SHIFT;
tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) |
(TGCR_UNRESET << TGCR_TIM34RS_SHIFT);
- davinci_writel(tgcr, base + TCR);
+ __raw_writel(tgcr, base + TCR);
/* clear counter and period regs */
- davinci_writel(0, base + TIM12);
- davinci_writel(0, base + TIM34);
- davinci_writel(0, base + PRD12);
- davinci_writel(0, base + PRD34);
+ __raw_writel(0, base + TIM12);
+ __raw_writel(0, base + TIM34);
+ __raw_writel(0, base + PRD12);
+ __raw_writel(0, base + PRD34);
/* enable */
- wdtcr = davinci_readl(base + WDTCR);
+ wdtcr = __raw_readl(base + WDTCR);
wdtcr |= WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT;
- davinci_writel(wdtcr, base + WDTCR);
+ __raw_writel(wdtcr, base + WDTCR);
/* put watchdog in pre-active state */
wdtcr = (WDTCR_WDKEY_SEQ0 << WDTCR_WDKEY_SHIFT) |
(WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT);
- davinci_writel(wdtcr, base + WDTCR);
+ __raw_writel(wdtcr, base + WDTCR);
/* put watchdog in active state */
wdtcr = (WDTCR_WDKEY_SEQ1 << WDTCR_WDKEY_SHIFT) |
(WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT);
- davinci_writel(wdtcr, base + WDTCR);
+ __raw_writel(wdtcr, base + WDTCR);
/* write an invalid value to the WDKEY field to trigger
* a watchdog reset */
wdtcr = 0x00004000;
- davinci_writel(wdtcr, base + WDTCR);
+ __raw_writel(wdtcr, base + WDTCR);
}
diff --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c
index 2429b79f6da2..abedb6337182 100644
--- a/arch/arm/mach-davinci/usb.c
+++ b/arch/arm/mach-davinci/usb.c
@@ -14,6 +14,8 @@
#include <mach/hardware.h>
#include <mach/irqs.h>
+#define DAVINCI_USB_OTG_BASE 0x01C64000
+
#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
static struct musb_hdrc_eps_bits musb_eps[] = {
{ "ep1_tx", 8, },
diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
index 56bddcef6905..9414eb641311 100644
--- a/arch/arm/mach-ep93xx/Kconfig
+++ b/arch/arm/mach-ep93xx/Kconfig
@@ -15,44 +15,62 @@ config MACH_ADSSPHERE
Say 'Y' here if you want your kernel to support the ADS
Sphere board.
+config MACH_EDB93XX
+ bool
+ default n
+
+config MACH_EDB9301
+ bool "Support Cirrus Logic EDB9301"
+ select MACH_EDB93XX
+ help
+ Say 'Y' here if you want your kernel to support the Cirrus
+ Logic EDB9301 Evaluation Board.
+
config MACH_EDB9302
bool "Support Cirrus Logic EDB9302"
+ select MACH_EDB93XX
help
Say 'Y' here if you want your kernel to support the Cirrus
Logic EDB9302 Evaluation Board.
config MACH_EDB9302A
bool "Support Cirrus Logic EDB9302A"
+ select MACH_EDB93XX
help
Say 'Y' here if you want your kernel to support the Cirrus
Logic EDB9302A Evaluation Board.
config MACH_EDB9307
bool "Support Cirrus Logic EDB9307"
+ select MACH_EDB93XX
help
Say 'Y' here if you want your kernel to support the Cirrus
Logic EDB9307 Evaluation Board.
config MACH_EDB9307A
bool "Support Cirrus Logic EDB9307A"
+ select MACH_EDB93XX
help
Say 'Y' here if you want your kernel to support the Cirrus
Logic EDB9307A Evaluation Board.
config MACH_EDB9312
bool "Support Cirrus Logic EDB9312"
+ select MACH_EDB93XX
help
Say 'Y' here if you want your kernel to support the Cirrus
Logic EDB9312 Evaluation Board.
config MACH_EDB9315
bool "Support Cirrus Logic EDB9315"
+ select MACH_EDB93XX
help
Say 'Y' here if you want your kernel to support the Cirrus
Logic EDB9315 Evaluation Board.
config MACH_EDB9315A
bool "Support Cirrus Logic EDB9315A"
+ select MACH_EDB93XX
help
Say 'Y' here if you want your kernel to support the Cirrus
Logic EDB9315A Evaluation Board.
@@ -64,29 +82,29 @@ config MACH_GESBC9312
GESBC-9312-sx board.
config MACH_MICRO9
- bool
- default n
+ bool
+ default n
config MACH_MICRO9H
- bool "Support Contec Hypercontrol Micro9-H"
- select MACH_MICRO9
- help
- Say 'Y' here if you want your kernel to support the
- Contec Hypercontrol Micro9-H board.
+ bool "Support Contec Hypercontrol Micro9-H"
+ select MACH_MICRO9
+ help
+ Say 'Y' here if you want your kernel to support the
+ Contec Hypercontrol Micro9-H board.
config MACH_MICRO9M
- bool "Support Contec Hypercontrol Micro9-M"
- select MACH_MICRO9
- help
- Say 'Y' here if you want your kernel to support the
- Contec Hypercontrol Micro9-M board.
+ bool "Support Contec Hypercontrol Micro9-M"
+ select MACH_MICRO9
+ help
+ Say 'Y' here if you want your kernel to support the
+ Contec Hypercontrol Micro9-M board.
config MACH_MICRO9L
- bool "Support Contec Hypercontrol Micro9-L"
- select MACH_MICRO9
- help
- Say 'Y' here if you want your kernel to support the
- Contec Hypercontrol Micro9-L board.
+ bool "Support Contec Hypercontrol Micro9-L"
+ select MACH_MICRO9
+ help
+ Say 'Y' here if you want your kernel to support the
+ Contec Hypercontrol Micro9-L board.
config MACH_TS72XX
bool "Support Technologic Systems TS-72xx SBC"
diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
index 9522e205b73f..eae6199a9891 100644
--- a/arch/arm/mach-ep93xx/Makefile
+++ b/arch/arm/mach-ep93xx/Makefile
@@ -7,13 +7,7 @@ obj-n :=
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_EDB9307A) += edb9307a.o
-obj-$(CONFIG_MACH_EDB9312) += edb9312.o
-obj-$(CONFIG_MACH_EDB9315) += edb9315.o
-obj-$(CONFIG_MACH_EDB9315A) += edb9315a.o
+obj-$(CONFIG_MACH_EDB93XX) += edb93xx.o
obj-$(CONFIG_MACH_GESBC9312) += gesbc9312.o
obj-$(CONFIG_MACH_MICRO9) += micro9.o
obj-$(CONFIG_MACH_TS72XX) += ts72xx.o
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 6d9152de6074..8611db978efc 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -100,7 +100,7 @@ static unsigned int last_jiffy_time;
#define TIMER4_TICKS_PER_JIFFY ((CLOCK_TICK_RATE + (HZ/2)) / HZ)
-static int ep93xx_timer_interrupt(int irq, void *dev_id)
+static irqreturn_t ep93xx_timer_interrupt(int irq, void *dev_id)
{
__raw_writel(1, EP93XX_TIMER1_CLEAR);
while ((signed long)
@@ -362,8 +362,8 @@ void __init ep93xx_init_irq(void)
{
int gpio_irq;
- vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK);
- vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK);
+ vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0);
+ vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0);
for (gpio_irq = gpio_to_irq(0);
gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
@@ -450,10 +450,19 @@ static struct amba_device uart3_device = {
};
+static struct resource ep93xx_rtc_resource[] = {
+ {
+ .start = EP93XX_RTC_PHYS_BASE,
+ .end = EP93XX_RTC_PHYS_BASE + 0x10c - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
static struct platform_device ep93xx_rtc_device = {
- .name = "ep93xx-rtc",
- .id = -1,
- .num_resources = 0,
+ .name = "ep93xx-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ep93xx_rtc_resource),
+ .resource = ep93xx_rtc_resource,
};
diff --git a/arch/arm/mach-ep93xx/edb9302.c b/arch/arm/mach-ep93xx/edb9302.c
deleted file mode 100644
index 8bf8d7c78f1a..000000000000
--- a/arch/arm/mach-ep93xx/edb9302.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/edb9302.c
- * Cirrus Logic EDB9302 support.
- *
- * Copyright (C) 2006 George Kashperko <george@chas.com.ua>
- *
- * 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 <linux/io.h>
-#include <linux/i2c.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-static struct physmap_flash_data edb9302_flash_data = {
- .width = 2,
-};
-
-static struct resource edb9302_flash_resource = {
- .start = EP93XX_CS6_PHYS_BASE,
- .end = EP93XX_CS6_PHYS_BASE + SZ_16M - 1,
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device edb9302_flash = {
- .name = "physmap-flash",
- .id = 0,
- .dev = {
- .platform_data = &edb9302_flash_data,
- },
- .num_resources = 1,
- .resource = &edb9302_flash_resource,
-};
-
-static struct ep93xx_eth_data edb9302_eth_data = {
- .phy_id = 1,
-};
-
-static void __init edb9302_init_machine(void)
-{
- ep93xx_init_devices();
- platform_device_register(&edb9302_flash);
-
- ep93xx_register_eth(&edb9302_eth_data, 1);
-}
-
-MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board")
- /* Maintainer: George Kashperko <george@chas.com.ua> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
- .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
- .map_io = ep93xx_map_io,
- .init_irq = ep93xx_init_irq,
- .timer = &ep93xx_timer,
- .init_machine = edb9302_init_machine,
-MACHINE_END
diff --git a/arch/arm/mach-ep93xx/edb9302a.c b/arch/arm/mach-ep93xx/edb9302a.c
deleted file mode 100644
index a352c57c7b46..000000000000
--- a/arch/arm/mach-ep93xx/edb9302a.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/edb9302a.c
- * Cirrus Logic EDB9302A support.
- *
- * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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 <linux/io.h>
-#include <linux/i2c.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-static struct physmap_flash_data edb9302a_flash_data = {
- .width = 2,
-};
-
-static struct resource edb9302a_flash_resource = {
- .start = EP93XX_CS6_PHYS_BASE,
- .end = EP93XX_CS6_PHYS_BASE + SZ_16M - 1,
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device edb9302a_flash = {
- .name = "physmap-flash",
- .id = 0,
- .dev = {
- .platform_data = &edb9302a_flash_data,
- },
- .num_resources = 1,
- .resource = &edb9302a_flash_resource,
-};
-
-static struct ep93xx_eth_data edb9302a_eth_data = {
- .phy_id = 1,
-};
-
-static void __init edb9302a_init_machine(void)
-{
- ep93xx_init_devices();
- platform_device_register(&edb9302a_flash);
-
- ep93xx_register_eth(&edb9302a_eth_data, 1);
-}
-
-MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board")
- /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
- .boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100,
- .map_io = ep93xx_map_io,
- .init_irq = ep93xx_init_irq,
- .timer = &ep93xx_timer,
- .init_machine = edb9302a_init_machine,
-MACHINE_END
diff --git a/arch/arm/mach-ep93xx/edb9307.c b/arch/arm/mach-ep93xx/edb9307.c
deleted file mode 100644
index 5ab22f63a4eb..000000000000
--- a/arch/arm/mach-ep93xx/edb9307.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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 <linux/io.h>
-#include <linux/i2c.h>
-#include <mach/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 = EP93XX_CS6_PHYS_BASE,
- .end = EP93XX_CS6_PHYS_BASE + SZ_32M - 1,
- .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 void __init edb9307_init_machine(void)
-{
- ep93xx_init_devices();
- platform_device_register(&edb9307_flash);
-
- ep93xx_register_eth(&edb9307_eth_data, 1);
-}
-
-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 = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
- .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-ep93xx/edb9307a.c b/arch/arm/mach-ep93xx/edb9307a.c
deleted file mode 100644
index 6171167d3315..000000000000
--- a/arch/arm/mach-ep93xx/edb9307a.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/edb9307a.c
- * Cirrus Logic EDB9307A support.
- *
- * Copyright (C) 2008 H Hartley Sweeten <hsweeten@visionengravers.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/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 <linux/io.h>
-#include <linux/i2c.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-static struct physmap_flash_data edb9307a_flash_data = {
- .width = 2,
-};
-
-static struct resource edb9307a_flash_resource = {
- .start = EP93XX_CS6_PHYS_BASE,
- .end = EP93XX_CS6_PHYS_BASE + SZ_16M - 1,
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device edb9307a_flash = {
- .name = "physmap-flash",
- .id = 0,
- .dev = {
- .platform_data = &edb9307a_flash_data,
- },
- .num_resources = 1,
- .resource = &edb9307a_flash_resource,
-};
-
-static struct ep93xx_eth_data edb9307a_eth_data = {
- .phy_id = 1,
-};
-
-static struct i2c_board_info __initdata edb9307a_i2c_data[] = {
- {
- /* On-board battery backed RTC */
- I2C_BOARD_INFO("isl1208", 0x6f),
- },
- /*
- * The I2C signals are also routed to the Expansion Connector (J4)
- */
-};
-
-static void __init edb9307a_init_machine(void)
-{
- ep93xx_init_devices();
- platform_device_register(&edb9307a_flash);
-
- ep93xx_register_eth(&edb9307a_eth_data, 1);
-
- ep93xx_init_i2c(edb9307a_i2c_data, ARRAY_SIZE(edb9307a_i2c_data));
-}
-
-MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board")
- /* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
- .boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100,
- .map_io = ep93xx_map_io,
- .init_irq = ep93xx_init_irq,
- .timer = &ep93xx_timer,
- .init_machine = edb9307a_init_machine,
-MACHINE_END
diff --git a/arch/arm/mach-ep93xx/edb9312.c b/arch/arm/mach-ep93xx/edb9312.c
deleted file mode 100644
index d7179f66d804..000000000000
--- a/arch/arm/mach-ep93xx/edb9312.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/edb9312.c
- * Cirrus Logic EDB9312 support.
- *
- * Copyright (C) 2006 Infosys Technologies Limited
- * Toufeeq Hussain <toufeeq_hussain@infosys.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/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 <linux/io.h>
-#include <linux/i2c.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-static struct physmap_flash_data edb9312_flash_data = {
- .width = 4,
-};
-
-static struct resource edb9312_flash_resource = {
- .start = EP93XX_CS6_PHYS_BASE,
- .end = EP93XX_CS6_PHYS_BASE + SZ_32M - 1,
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device edb9312_flash = {
- .name = "physmap-flash",
- .id = 0,
- .dev = {
- .platform_data = &edb9312_flash_data,
- },
- .num_resources = 1,
- .resource = &edb9312_flash_resource,
-};
-
-static struct ep93xx_eth_data edb9312_eth_data = {
- .phy_id = 1,
-};
-
-static void __init edb9312_init_machine(void)
-{
- ep93xx_init_devices();
- platform_device_register(&edb9312_flash);
-
- ep93xx_register_eth(&edb9312_eth_data, 1);
-}
-
-MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
- /* Maintainer: Toufeeq Hussain <toufeeq_hussain@infosys.com> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
- .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
- .map_io = ep93xx_map_io,
- .init_irq = ep93xx_init_irq,
- .timer = &ep93xx_timer,
- .init_machine = edb9312_init_machine,
-MACHINE_END
diff --git a/arch/arm/mach-ep93xx/edb9315.c b/arch/arm/mach-ep93xx/edb9315.c
deleted file mode 100644
index 025af6eaca10..000000000000
--- a/arch/arm/mach-ep93xx/edb9315.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/edb9315.c
- * Cirrus Logic EDB9315 support.
- *
- * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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 <linux/io.h>
-#include <linux/i2c.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-static struct physmap_flash_data edb9315_flash_data = {
- .width = 4,
-};
-
-static struct resource edb9315_flash_resource = {
- .start = EP93XX_CS6_PHYS_BASE,
- .end = EP93XX_CS6_PHYS_BASE + SZ_32M - 1,
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device edb9315_flash = {
- .name = "physmap-flash",
- .id = 0,
- .dev = {
- .platform_data = &edb9315_flash_data,
- },
- .num_resources = 1,
- .resource = &edb9315_flash_resource,
-};
-
-static struct ep93xx_eth_data edb9315_eth_data = {
- .phy_id = 1,
-};
-
-static void __init edb9315_init_machine(void)
-{
- ep93xx_init_devices();
- platform_device_register(&edb9315_flash);
-
- ep93xx_register_eth(&edb9315_eth_data, 1);
-}
-
-MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board")
- /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
- .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
- .map_io = ep93xx_map_io,
- .init_irq = ep93xx_init_irq,
- .timer = &ep93xx_timer,
- .init_machine = edb9315_init_machine,
-MACHINE_END
diff --git a/arch/arm/mach-ep93xx/edb9315a.c b/arch/arm/mach-ep93xx/edb9315a.c
deleted file mode 100644
index 4c9cc8a39f5c..000000000000
--- a/arch/arm/mach-ep93xx/edb9315a.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/edb9315a.c
- * Cirrus Logic EDB9315A support.
- *
- * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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 <linux/io.h>
-#include <linux/i2c.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-static struct physmap_flash_data edb9315a_flash_data = {
- .width = 2,
-};
-
-static struct resource edb9315a_flash_resource = {
- .start = EP93XX_CS6_PHYS_BASE,
- .end = EP93XX_CS6_PHYS_BASE + SZ_16M - 1,
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device edb9315a_flash = {
- .name = "physmap-flash",
- .id = 0,
- .dev = {
- .platform_data = &edb9315a_flash_data,
- },
- .num_resources = 1,
- .resource = &edb9315a_flash_resource,
-};
-
-static struct ep93xx_eth_data edb9315a_eth_data = {
- .phy_id = 1,
-};
-
-static void __init edb9315a_init_machine(void)
-{
- ep93xx_init_devices();
- platform_device_register(&edb9315a_flash);
-
- ep93xx_register_eth(&edb9315a_eth_data, 1);
-}
-
-MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board")
- /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
- .boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100,
- .map_io = ep93xx_map_io,
- .init_irq = ep93xx_init_irq,
- .timer = &ep93xx_timer,
- .init_machine = edb9315a_init_machine,
-MACHINE_END
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
index f66be12b856e..78ac1bddc8bc 100644
--- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
@@ -147,6 +147,7 @@
#define EP93XX_PWM_BASE (EP93XX_APB_VIRT_BASE + 0x00110000)
#define EP93XX_RTC_BASE (EP93XX_APB_VIRT_BASE + 0x00120000)
+#define EP93XX_RTC_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x00120000)
#define EP93XX_SYSCON_BASE (EP93XX_APB_VIRT_BASE + 0x00130000)
#define EP93XX_SYSCON_REG(x) (EP93XX_SYSCON_BASE + (x))
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h b/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h
new file mode 100644
index 000000000000..83f31cd0a274
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h
@@ -0,0 +1,42 @@
+/*
+ * arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h
+ */
+
+#ifndef __ASM_ARCH_EP93XX_KEYPAD_H
+#define __ASM_ARCH_EP93XX_KEYPAD_H
+
+#define MAX_MATRIX_KEY_ROWS (8)
+#define MAX_MATRIX_KEY_COLS (8)
+
+/* flags for the ep93xx_keypad driver */
+#define EP93XX_KEYPAD_DISABLE_3_KEY (1<<0) /* disable 3-key reset */
+#define EP93XX_KEYPAD_DIAG_MODE (1<<1) /* diagnostic mode */
+#define EP93XX_KEYPAD_BACK_DRIVE (1<<2) /* back driving mode */
+#define EP93XX_KEYPAD_TEST_MODE (1<<3) /* scan only column 0 */
+#define EP93XX_KEYPAD_KDIV (1<<4) /* 1/4 clock or 1/16 clock */
+#define EP93XX_KEYPAD_AUTOREPEAT (1<<5) /* enable key autorepeat */
+
+/**
+ * struct ep93xx_keypad_platform_data - platform specific device structure
+ * @matrix_key_rows: number of rows in the keypad matrix
+ * @matrix_key_cols: number of columns in the keypad matrix
+ * @matrix_key_map: array of keycodes defining the keypad matrix
+ * @matrix_key_map_size: ARRAY_SIZE(matrix_key_map)
+ * @debounce: debounce start count; terminal count is 0xff
+ * @prescale: row/column counter pre-scaler load value
+ * @flags: see above
+ */
+struct ep93xx_keypad_platform_data {
+ unsigned int matrix_key_rows;
+ unsigned int matrix_key_cols;
+ unsigned int *matrix_key_map;
+ int matrix_key_map_size;
+ unsigned int debounce;
+ unsigned int prescale;
+ unsigned int flags;
+};
+
+/* macro for creating the matrix_key_map table */
+#define KEY(row, col, val) (((row) << 28) | ((col) << 24) | (val))
+
+#endif /* __ASM_ARCH_EP93XX_KEYPAD_H */
diff --git a/arch/arm/mach-imx/include/mach/gpio.h b/arch/arm/mach-imx/include/mach/gpio.h
index 502d5aa2c093..6c2942f82922 100644
--- a/arch/arm/mach-imx/include/mach/gpio.h
+++ b/arch/arm/mach-imx/include/mach/gpio.h
@@ -1,6 +1,7 @@
#ifndef _IMX_GPIO_H
#include <linux/kernel.h>
+#include <mach/hardware.h>
#include <mach/imx-regs.h>
#define IMX_GPIO_ALLOC_MODE_NORMAL 0
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index aff0ebcfa847..5aef18b599e5 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -73,7 +73,7 @@ static void __init imx_timer_hardware_init(void)
IMX_TCTL(TIMER_BASE) = TCTL_FRR | TCTL_CLK_PCLK1 | TCTL_TEN;
}
-cycle_t imx_get_cycles(void)
+cycle_t imx_get_cycles(struct clocksource *cs)
{
return IMX_TCN(TIMER_BASE);
}
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index f4656d2ac8a8..1e93dfee7543 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -401,7 +401,7 @@ void __init ixp4xx_sys_init(void)
/*
* clocksource
*/
-cycle_t ixp4xx_get_cycles(void)
+cycle_t ixp4xx_get_cycles(struct clocksource *cs)
{
return *IXP4XX_OSTS;
}
diff --git a/arch/arm/mach-ixp4xx/ixp4xx_npe.c b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
index 252310234903..7bb8e778e4b6 100644
--- a/arch/arm/mach-ixp4xx/ixp4xx_npe.c
+++ b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
@@ -714,7 +714,7 @@ static int __init npe_init_module(void)
}
if (!found)
- return -ENOSYS;
+ return -ENODEV;
return 0;
}
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
index 16dc9ea08393..eeb00240d784 100644
--- a/arch/arm/mach-kirkwood/common.c
+++ b/arch/arm/mach-kirkwood/common.c
@@ -23,6 +23,7 @@
#include <asm/mach/map.h>
#include <asm/mach/time.h>
#include <mach/kirkwood.h>
+#include <mach/bridge-regs.h>
#include <plat/cache-feroceon-l2.h>
#include <plat/ehci-orion.h>
#include <plat/mvsdio.h>
diff --git a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
new file mode 100644
index 000000000000..4f7029f521cc
--- /dev/null
+++ b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
@@ -0,0 +1,42 @@
+/*
+ * arch/arm/mach-kirkwood/include/mach/bridge-regs.h
+ *
+ * Mbus-L to Mbus Bridge Registers
+ *
+ * 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 __ASM_ARCH_BRIDGE_REGS_H
+#define __ASM_ARCH_BRIDGE_REGS_H
+
+#include <mach/kirkwood.h>
+
+#define CPU_CONTROL (BRIDGE_VIRT_BASE | 0x0104)
+#define CPU_RESET 0x00000002
+
+#define RSTOUTn_MASK (BRIDGE_VIRT_BASE | 0x0108)
+#define SOFT_RESET_OUT_EN 0x00000004
+
+#define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE | 0x010c)
+#define SOFT_RESET 0x00000001
+
+#define BRIDGE_CAUSE (BRIDGE_VIRT_BASE | 0x0110)
+#define BRIDGE_MASK (BRIDGE_VIRT_BASE | 0x0114)
+#define BRIDGE_INT_TIMER0 0x0002
+#define BRIDGE_INT_TIMER1 0x0004
+#define BRIDGE_INT_TIMER1_CLR (~0x0004)
+
+#define IRQ_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0200)
+#define IRQ_CAUSE_LOW_OFF 0x0000
+#define IRQ_MASK_LOW_OFF 0x0004
+#define IRQ_CAUSE_HIGH_OFF 0x0010
+#define IRQ_MASK_HIGH_OFF 0x0014
+
+#define TIMER_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0300)
+
+#define L2_CONFIG_REG (BRIDGE_VIRT_BASE | 0x0128)
+#define L2_WRITETHROUGH 0x00000010
+
+#endif
diff --git a/arch/arm/mach-kirkwood/include/mach/debug-macro.S b/arch/arm/mach-kirkwood/include/mach/debug-macro.S
index c0cc5b5c82ac..a4a55c199d77 100644
--- a/arch/arm/mach-kirkwood/include/mach/debug-macro.S
+++ b/arch/arm/mach-kirkwood/include/mach/debug-macro.S
@@ -6,7 +6,7 @@
* published by the Free Software Foundation.
*/
-#include <mach/kirkwood.h>
+#include <mach/bridge-regs.h>
.macro addruart,rx
mrc p15, 0, \rx, c1, c0
diff --git a/arch/arm/mach-kirkwood/include/mach/entry-macro.S b/arch/arm/mach-kirkwood/include/mach/entry-macro.S
index 83e0cba77b36..8939d36f893c 100644
--- a/arch/arm/mach-kirkwood/include/mach/entry-macro.S
+++ b/arch/arm/mach-kirkwood/include/mach/entry-macro.S
@@ -8,7 +8,7 @@
* warranty of any kind, whether express or implied.
*/
-#include <mach/kirkwood.h>
+#include <mach/bridge-regs.h>
.macro disable_fiq
.endm
diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h
index 38c986853590..b3e13958821d 100644
--- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h
+++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h
@@ -44,44 +44,6 @@
#define KIRKWOOD_PCIE_MEM_SIZE SZ_128M
/*
- * MBUS bridge registers.
- */
-#define BRIDGE_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0x20000)
-#define CPU_CONTROL (BRIDGE_VIRT_BASE | 0x0104)
-#define CPU_RESET 0x00000002
-#define RSTOUTn_MASK (BRIDGE_VIRT_BASE | 0x0108)
-#define SOFT_RESET_OUT_EN 0x00000004
-#define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE | 0x010c)
-#define SOFT_RESET 0x00000001
-#define BRIDGE_CAUSE (BRIDGE_VIRT_BASE | 0x0110)
-#define BRIDGE_MASK (BRIDGE_VIRT_BASE | 0x0114)
-#define BRIDGE_INT_TIMER0 0x0002
-#define BRIDGE_INT_TIMER1 0x0004
-#define BRIDGE_INT_TIMER1_CLR (~0x0004)
-#define IRQ_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0200)
-#define IRQ_CAUSE_LOW_OFF 0x0000
-#define IRQ_MASK_LOW_OFF 0x0004
-#define IRQ_CAUSE_HIGH_OFF 0x0010
-#define IRQ_MASK_HIGH_OFF 0x0014
-#define TIMER_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0300)
-#define L2_CONFIG_REG (BRIDGE_VIRT_BASE | 0x0128)
-#define L2_WRITETHROUGH 0x00000010
-
-/*
- * Supported devices and revisions.
- */
-#define MV88F6281_DEV_ID 0x6281
-#define MV88F6281_REV_Z0 0
-#define MV88F6281_REV_A0 2
-
-#define MV88F6192_DEV_ID 0x6192
-#define MV88F6192_REV_Z0 0
-#define MV88F6192_REV_A0 2
-
-#define MV88F6180_DEV_ID 0x6180
-#define MV88F6180_REV_A0 2
-
-/*
* Register Map
*/
#define DDR_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0x00000)
@@ -99,6 +61,8 @@
#define UART1_PHYS_BASE (DEV_BUS_PHYS_BASE | 0x2100)
#define UART1_VIRT_BASE (DEV_BUS_VIRT_BASE | 0x2100)
+#define BRIDGE_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0x20000)
+
#define PCIE_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0x40000)
#define USB_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x50000)
@@ -119,5 +83,18 @@
#define SDIO_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x90000)
+/*
+ * Supported devices and revisions.
+ */
+#define MV88F6281_DEV_ID 0x6281
+#define MV88F6281_REV_Z0 0
+#define MV88F6281_REV_A0 2
+
+#define MV88F6192_DEV_ID 0x6192
+#define MV88F6192_REV_Z0 0
+#define MV88F6192_REV_A0 2
+
+#define MV88F6180_DEV_ID 0x6180
+#define MV88F6180_REV_A0 2
#endif
diff --git a/arch/arm/mach-kirkwood/include/mach/system.h b/arch/arm/mach-kirkwood/include/mach/system.h
index 23a1914c1da8..7568e95d279b 100644
--- a/arch/arm/mach-kirkwood/include/mach/system.h
+++ b/arch/arm/mach-kirkwood/include/mach/system.h
@@ -9,8 +9,7 @@
#ifndef __ASM_ARCH_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H
-#include <mach/hardware.h>
-#include <mach/kirkwood.h>
+#include <mach/bridge-regs.h>
static inline void arch_idle(void)
{
diff --git a/arch/arm/mach-kirkwood/irq.c b/arch/arm/mach-kirkwood/irq.c
index 06083b23bb44..28020abf49e1 100644
--- a/arch/arm/mach-kirkwood/irq.c
+++ b/arch/arm/mach-kirkwood/irq.c
@@ -12,6 +12,7 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/io.h>
+#include <mach/bridge-regs.h>
#include <plat/irq.h>
#include <asm/gpio.h>
#include "common.h"
diff --git a/arch/arm/mach-loki/addr-map.c b/arch/arm/mach-loki/addr-map.c
index 0332d8f5c18c..b9537c97beba 100644
--- a/arch/arm/mach-loki/addr-map.c
+++ b/arch/arm/mach-loki/addr-map.c
@@ -38,6 +38,7 @@
/*
* CPU Address Decode Windows registers
*/
+#define BRIDGE_REG(x) (BRIDGE_VIRT_BASE | (x))
#define CPU_WIN_CTRL(n) BRIDGE_REG(0x000 | ((n) << 4))
#define CPU_WIN_BASE(n) BRIDGE_REG(0x004 | ((n) << 4))
#define CPU_WIN_REMAP_LO(n) BRIDGE_REG(0x008 | ((n) << 4))
diff --git a/arch/arm/mach-loki/include/mach/bridge-regs.h b/arch/arm/mach-loki/include/mach/bridge-regs.h
new file mode 100644
index 000000000000..a3fabf70044f
--- /dev/null
+++ b/arch/arm/mach-loki/include/mach/bridge-regs.h
@@ -0,0 +1,33 @@
+/*
+ * arch/arm/mach-loki/include/mach/bridge-regs.h
+ *
+ * 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 __ASM_ARCH_BRIDGE_REGS_H
+#define __ASM_ARCH_BRIDGE_REGS_H
+
+#include <mach/loki.h>
+
+#define RSTOUTn_MASK (BRIDGE_VIRT_BASE | 0x0108)
+#define SOFT_RESET_OUT_EN 0x00000004
+
+#define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE | 0x010c)
+#define SOFT_RESET 0x00000001
+
+#define BRIDGE_CAUSE (BRIDGE_VIRT_BASE | 0x0110)
+
+#define BRIDGE_MASK (BRIDGE_VIRT_BASE | 0x0114)
+#define BRIDGE_INT_TIMER0 0x0002
+#define BRIDGE_INT_TIMER1 0x0004
+#define BRIDGE_INT_TIMER1_CLR 0x0004
+
+#define IRQ_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0200)
+#define IRQ_CAUSE_OFF 0x0000
+#define IRQ_MASK_OFF 0x0004
+
+#define TIMER_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0300)
+
+#endif
diff --git a/arch/arm/mach-loki/include/mach/entry-macro.S b/arch/arm/mach-loki/include/mach/entry-macro.S
index 332af38ec13c..bc917ed3a62d 100644
--- a/arch/arm/mach-loki/include/mach/entry-macro.S
+++ b/arch/arm/mach-loki/include/mach/entry-macro.S
@@ -8,7 +8,7 @@
* warranty of any kind, whether express or implied.
*/
-#include <mach/loki.h>
+#include <mach/bridge-regs.h>
.macro disable_fiq
.endm
diff --git a/arch/arm/mach-loki/include/mach/loki.h b/arch/arm/mach-loki/include/mach/loki.h
index c00af6ba5578..bfca7c265f43 100644
--- a/arch/arm/mach-loki/include/mach/loki.h
+++ b/arch/arm/mach-loki/include/mach/loki.h
@@ -58,20 +58,6 @@
#define UART1_VIRT_BASE (DEV_BUS_VIRT_BASE | 0x2100)
#define BRIDGE_VIRT_BASE (LOKI_REGS_VIRT_BASE | 0x20000)
-#define BRIDGE_REG(x) (BRIDGE_VIRT_BASE | (x))
-#define RSTOUTn_MASK (BRIDGE_VIRT_BASE | 0x0108)
-#define SOFT_RESET_OUT_EN 0x00000004
-#define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE | 0x010c)
-#define SOFT_RESET 0x00000001
-#define BRIDGE_CAUSE (BRIDGE_VIRT_BASE | 0x0110)
-#define BRIDGE_MASK (BRIDGE_VIRT_BASE | 0x0114)
-#define BRIDGE_INT_TIMER0 0x0002
-#define BRIDGE_INT_TIMER1 0x0004
-#define BRIDGE_INT_TIMER1_CLR 0x0004
-#define IRQ_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0200)
-#define IRQ_CAUSE_OFF 0x0000
-#define IRQ_MASK_OFF 0x0004
-#define TIMER_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0300)
#define PCIE0_VIRT_BASE (LOKI_REGS_VIRT_BASE | 0x30000)
diff --git a/arch/arm/mach-loki/include/mach/system.h b/arch/arm/mach-loki/include/mach/system.h
index c1de36fe9b37..71895199a534 100644
--- a/arch/arm/mach-loki/include/mach/system.h
+++ b/arch/arm/mach-loki/include/mach/system.h
@@ -9,8 +9,7 @@
#ifndef __ASM_ARCH_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H
-#include <mach/hardware.h>
-#include <mach/loki.h>
+#include <mach/bridge-regs.h>
static inline void arch_idle(void)
{
diff --git a/arch/arm/mach-loki/irq.c b/arch/arm/mach-loki/irq.c
index e1f97338d5b7..76b211bfcca2 100644
--- a/arch/arm/mach-loki/irq.c
+++ b/arch/arm/mach-loki/irq.c
@@ -12,6 +12,7 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/io.h>
+#include <mach/bridge-regs.h>
#include <plat/irq.h>
#include "common.h"
diff --git a/arch/arm/mach-mmp/include/mach/irqs.h b/arch/arm/mach-mmp/include/mach/irqs.h
index e83e45ebf7a4..16295cfd5e29 100644
--- a/arch/arm/mach-mmp/include/mach/irqs.h
+++ b/arch/arm/mach-mmp/include/mach/irqs.h
@@ -52,6 +52,7 @@
/*
* Interrupt numbers for PXA910
*/
+#define IRQ_PXA910_NONE (-1)
#define IRQ_PXA910_AIRQ 0
#define IRQ_PXA910_SSP3 1
#define IRQ_PXA910_SSP2 2
diff --git a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
index d0bdb6e3682b..d4bd393a26b0 100644
--- a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
+++ b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
@@ -248,6 +248,10 @@
#define GPIO58_LCD_PCLK_WR MFP_CFG(GPIO58, AF1)
#define GPIO85_LCD_VSYNC MFP_CFG(GPIO85, AF1)
+/* I2C */
+#define GPIO105_CI2C_SDA MFP_CFG(GPIO105, AF1)
+#define GPIO106_CI2C_SCL MFP_CFG(GPIO106, AF1)
+
/* I2S */
#define GPIO113_I2S_MCLK MFP_CFG(GPIO113,AF6)
#define GPIO114_I2S_FRM MFP_CFG(GPIO114,AF1)
@@ -255,4 +259,27 @@
#define GPIO116_I2S_RXD MFP_CFG(GPIO116,AF2)
#define GPIO117_I2S_TXD MFP_CFG(GPIO117,AF2)
+/* PWM */
+#define GPIO96_PWM3_OUT MFP_CFG(GPIO96, AF1)
+#define GPIO97_PWM2_OUT MFP_CFG(GPIO97, AF1)
+#define GPIO98_PWM1_OUT MFP_CFG(GPIO98, AF1)
+#define GPIO104_PWM4_OUT MFP_CFG(GPIO104, AF1)
+#define GPIO106_PWM2_OUT MFP_CFG(GPIO106, AF2)
+#define GPIO74_PWM4_OUT MFP_CFG(GPIO74, AF2)
+#define GPIO75_PWM3_OUT MFP_CFG(GPIO75, AF2)
+#define GPIO76_PWM2_OUT MFP_CFG(GPIO76, AF2)
+#define GPIO77_PWM1_OUT MFP_CFG(GPIO77, AF2)
+#define GPIO82_PWM4_OUT MFP_CFG(GPIO82, AF2)
+#define GPIO83_PWM3_OUT MFP_CFG(GPIO83, AF2)
+#define GPIO84_PWM2_OUT MFP_CFG(GPIO84, AF2)
+#define GPIO85_PWM1_OUT MFP_CFG(GPIO85, AF2)
+#define GPIO84_PWM1_OUT MFP_CFG(GPIO84, AF4)
+#define GPIO122_PWM3_OUT MFP_CFG(GPIO122, AF3)
+#define GPIO123_PWM1_OUT MFP_CFG(GPIO123, AF1)
+#define GPIO124_PWM2_OUT MFP_CFG(GPIO124, AF1)
+#define GPIO125_PWM3_OUT MFP_CFG(GPIO125, AF1)
+#define GPIO126_PWM4_OUT MFP_CFG(GPIO126, AF1)
+#define GPIO86_PWM1_OUT MFP_CFG(GPIO86, AF2)
+#define GPIO86_PWM2_OUT MFP_CFG(GPIO86, AF3)
+
#endif /* __ASM_MACH_MFP_PXA168_H */
diff --git a/arch/arm/mach-mmp/include/mach/mfp-pxa910.h b/arch/arm/mach-mmp/include/mach/mfp-pxa910.h
index 48a1cbc7c56b..1f1a53ea5817 100644
--- a/arch/arm/mach-mmp/include/mach/mfp-pxa910.h
+++ b/arch/arm/mach-mmp/include/mach/mfp-pxa910.h
@@ -154,4 +154,12 @@
#define MMC1_CD_MMC1_CD MFP_CFG_DRV(MMC1_CD, AF0, MEDIUM)
#define MMC1_WP_MMC1_WP MFP_CFG_DRV(MMC1_WP, AF0, MEDIUM)
+/* PWM */
+#define GPIO27 PWM3 AF2 MFP_CFG(GPIO27, AF2)
+#define GPIO51_PWM2_OUT MFP_CFG(GPIO51, AF2)
+#define GPIO117_PWM1_OUT MFP_CFG(GPIO117, AF2)
+#define GPIO118_PWM2_OUT MFP_CFG(GPIO118, AF2)
+#define GPIO119_PWM3_OUT MFP_CFG(GPIO119, AF2)
+#define GPIO120_PWM4_OUT MFP_CFG(GPIO120, AF2)
+
#endif /* __ASM_MACH MFP_PXA910_H */
diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h
index ef0a8a2076e9..6bf1f0eefcd1 100644
--- a/arch/arm/mach-mmp/include/mach/pxa168.h
+++ b/arch/arm/mach-mmp/include/mach/pxa168.h
@@ -1,10 +1,18 @@
#ifndef __ASM_MACH_PXA168_H
#define __ASM_MACH_PXA168_H
+#include <linux/i2c.h>
#include <mach/devices.h>
+#include <plat/i2c.h>
extern struct pxa_device_desc pxa168_device_uart1;
extern struct pxa_device_desc pxa168_device_uart2;
+extern struct pxa_device_desc pxa168_device_twsi0;
+extern struct pxa_device_desc pxa168_device_twsi1;
+extern struct pxa_device_desc pxa168_device_pwm1;
+extern struct pxa_device_desc pxa168_device_pwm2;
+extern struct pxa_device_desc pxa168_device_pwm3;
+extern struct pxa_device_desc pxa168_device_pwm4;
static inline int pxa168_add_uart(int id)
{
@@ -20,4 +28,40 @@ static inline int pxa168_add_uart(int id)
return pxa_register_device(d, NULL, 0);
}
+
+static inline int pxa168_add_twsi(int id, struct i2c_pxa_platform_data *data,
+ struct i2c_board_info *info, unsigned size)
+{
+ struct pxa_device_desc *d = NULL;
+ int ret;
+
+ switch (id) {
+ case 0: d = &pxa168_device_twsi0; break;
+ case 1: d = &pxa168_device_twsi1; break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = i2c_register_board_info(id, info, size);
+ if (ret)
+ return ret;
+
+ return pxa_register_device(d, data, sizeof(*data));
+}
+
+static inline int pxa168_add_pwm(int id)
+{
+ struct pxa_device_desc *d = NULL;
+
+ switch (id) {
+ case 1: d = &pxa168_device_pwm1; break;
+ case 2: d = &pxa168_device_pwm2; break;
+ case 3: d = &pxa168_device_pwm3; break;
+ case 4: d = &pxa168_device_pwm4; break;
+ default:
+ return -EINVAL;
+ }
+
+ return pxa_register_device(d, NULL, 0);
+}
#endif /* __ASM_MACH_PXA168_H */
diff --git a/arch/arm/mach-mmp/include/mach/pxa910.h b/arch/arm/mach-mmp/include/mach/pxa910.h
index b7aeaf574c36..6ae1ed7a0a9f 100644
--- a/arch/arm/mach-mmp/include/mach/pxa910.h
+++ b/arch/arm/mach-mmp/include/mach/pxa910.h
@@ -1,10 +1,18 @@
#ifndef __ASM_MACH_PXA910_H
#define __ASM_MACH_PXA910_H
+#include <linux/i2c.h>
#include <mach/devices.h>
+#include <plat/i2c.h>
extern struct pxa_device_desc pxa910_device_uart1;
extern struct pxa_device_desc pxa910_device_uart2;
+extern struct pxa_device_desc pxa910_device_twsi0;
+extern struct pxa_device_desc pxa910_device_twsi1;
+extern struct pxa_device_desc pxa910_device_pwm1;
+extern struct pxa_device_desc pxa910_device_pwm2;
+extern struct pxa_device_desc pxa910_device_pwm3;
+extern struct pxa_device_desc pxa910_device_pwm4;
static inline int pxa910_add_uart(int id)
{
@@ -20,4 +28,40 @@ static inline int pxa910_add_uart(int id)
return pxa_register_device(d, NULL, 0);
}
+
+static inline int pxa910_add_twsi(int id, struct i2c_pxa_platform_data *data,
+ struct i2c_board_info *info, unsigned size)
+{
+ struct pxa_device_desc *d = NULL;
+ int ret;
+
+ switch (id) {
+ case 0: d = &pxa910_device_twsi0; break;
+ case 1: d = &pxa910_device_twsi1; break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = i2c_register_board_info(id, info, size);
+ if (ret)
+ return ret;
+
+ return pxa_register_device(d, data, sizeof(*data));
+}
+
+static inline int pxa910_add_pwm(int id)
+{
+ struct pxa_device_desc *d = NULL;
+
+ switch (id) {
+ case 1: d = &pxa910_device_pwm1; break;
+ case 2: d = &pxa910_device_pwm2; break;
+ case 3: d = &pxa910_device_pwm3; break;
+ case 4: d = &pxa910_device_pwm4; break;
+ default:
+ return -EINVAL;
+ }
+
+ return pxa_register_device(d, NULL, 0);
+}
#endif /* __ASM_MACH_PXA910_H */
diff --git a/arch/arm/mach-mmp/include/mach/regs-apbc.h b/arch/arm/mach-mmp/include/mach/regs-apbc.h
index c6b8c9dc2026..98ccbee4bd0c 100644
--- a/arch/arm/mach-mmp/include/mach/regs-apbc.h
+++ b/arch/arm/mach-mmp/include/mach/regs-apbc.h
@@ -22,8 +22,10 @@
#define APBC_PXA168_UART1 APBC_REG(0x000)
#define APBC_PXA168_UART2 APBC_REG(0x004)
#define APBC_PXA168_GPIO APBC_REG(0x008)
-#define APBC_PXA168_PWM0 APBC_REG(0x00c)
-#define APBC_PXA168_PWM1 APBC_REG(0x010)
+#define APBC_PXA168_PWM1 APBC_REG(0x00c)
+#define APBC_PXA168_PWM2 APBC_REG(0x010)
+#define APBC_PXA168_PWM3 APBC_REG(0x014)
+#define APBC_PXA168_PWM4 APBC_REG(0x018)
#define APBC_PXA168_SSP1 APBC_REG(0x01c)
#define APBC_PXA168_SSP2 APBC_REG(0x020)
#define APBC_PXA168_RTC APBC_REG(0x028)
@@ -48,10 +50,10 @@
#define APBC_PXA910_UART0 APBC_REG(0x000)
#define APBC_PXA910_UART1 APBC_REG(0x004)
#define APBC_PXA910_GPIO APBC_REG(0x008)
-#define APBC_PXA910_PWM0 APBC_REG(0x00c)
-#define APBC_PXA910_PWM1 APBC_REG(0x010)
-#define APBC_PXA910_PWM2 APBC_REG(0x014)
-#define APBC_PXA910_PWM3 APBC_REG(0x018)
+#define APBC_PXA910_PWM1 APBC_REG(0x00c)
+#define APBC_PXA910_PWM2 APBC_REG(0x010)
+#define APBC_PXA910_PWM3 APBC_REG(0x014)
+#define APBC_PXA910_PWM4 APBC_REG(0x018)
#define APBC_PXA910_SSP1 APBC_REG(0x01c)
#define APBC_PXA910_SSP2 APBC_REG(0x020)
#define APBC_PXA910_IPC APBC_REG(0x024)
diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
index ae924468658c..71b1ae338753 100644
--- a/arch/arm/mach-mmp/pxa168.c
+++ b/arch/arm/mach-mmp/pxa168.c
@@ -65,11 +65,23 @@ void __init pxa168_init_irq(void)
/* APB peripheral clocks */
static APBC_CLK(uart1, PXA168_UART1, 1, 14745600);
static APBC_CLK(uart2, PXA168_UART2, 1, 14745600);
+static APBC_CLK(twsi0, PXA168_TWSI0, 1, 33000000);
+static APBC_CLK(twsi1, PXA168_TWSI1, 1, 33000000);
+static APBC_CLK(pwm1, PXA168_PWM1, 1, 13000000);
+static APBC_CLK(pwm2, PXA168_PWM2, 1, 13000000);
+static APBC_CLK(pwm3, PXA168_PWM3, 1, 13000000);
+static APBC_CLK(pwm4, PXA168_PWM4, 1, 13000000);
/* device and clock bindings */
static struct clk_lookup pxa168_clkregs[] = {
INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL),
INIT_CLKREG(&clk_uart2, "pxa2xx-uart.1", NULL),
+ INIT_CLKREG(&clk_twsi0, "pxa2xx-i2c.0", NULL),
+ INIT_CLKREG(&clk_twsi1, "pxa2xx-i2c.1", NULL),
+ INIT_CLKREG(&clk_pwm1, "pxa168-pwm.0", NULL),
+ INIT_CLKREG(&clk_pwm2, "pxa168-pwm.1", NULL),
+ INIT_CLKREG(&clk_pwm3, "pxa168-pwm.2", NULL),
+ INIT_CLKREG(&clk_pwm4, "pxa168-pwm.3", NULL),
};
static int __init pxa168_init(void)
@@ -109,3 +121,9 @@ struct sys_timer pxa168_timer = {
/* on-chip devices */
PXA168_DEVICE(uart1, "pxa2xx-uart", 0, UART1, 0xd4017000, 0x30, 21, 22);
PXA168_DEVICE(uart2, "pxa2xx-uart", 1, UART2, 0xd4018000, 0x30, 23, 24);
+PXA168_DEVICE(twsi0, "pxa2xx-i2c", 0, TWSI0, 0xd4011000, 0x28);
+PXA168_DEVICE(twsi1, "pxa2xx-i2c", 1, TWSI1, 0xd4025000, 0x28);
+PXA168_DEVICE(pwm1, "pxa168-pwm", 0, NONE, 0xd401a000, 0x10);
+PXA168_DEVICE(pwm2, "pxa168-pwm", 1, NONE, 0xd401a400, 0x10);
+PXA168_DEVICE(pwm3, "pxa168-pwm", 2, NONE, 0xd401a800, 0x10);
+PXA168_DEVICE(pwm4, "pxa168-pwm", 3, NONE, 0xd401ac00, 0x10);
diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c
index 453f8f7758bf..5882ca6b49fb 100644
--- a/arch/arm/mach-mmp/pxa910.c
+++ b/arch/arm/mach-mmp/pxa910.c
@@ -103,11 +103,23 @@ void __init pxa910_init_irq(void)
/* APB peripheral clocks */
static APBC_CLK(uart1, PXA910_UART0, 1, 14745600);
static APBC_CLK(uart2, PXA910_UART1, 1, 14745600);
+static APBC_CLK(twsi0, PXA168_TWSI0, 1, 33000000);
+static APBC_CLK(twsi1, PXA168_TWSI1, 1, 33000000);
+static APBC_CLK(pwm1, PXA910_PWM1, 1, 13000000);
+static APBC_CLK(pwm2, PXA910_PWM2, 1, 13000000);
+static APBC_CLK(pwm3, PXA910_PWM3, 1, 13000000);
+static APBC_CLK(pwm4, PXA910_PWM4, 1, 13000000);
/* device and clock bindings */
static struct clk_lookup pxa910_clkregs[] = {
INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL),
INIT_CLKREG(&clk_uart2, "pxa2xx-uart.1", NULL),
+ INIT_CLKREG(&clk_twsi0, "pxa2xx-i2c.0", NULL),
+ INIT_CLKREG(&clk_twsi1, "pxa2xx-i2c.1", NULL),
+ INIT_CLKREG(&clk_pwm1, "pxa910-pwm.0", NULL),
+ INIT_CLKREG(&clk_pwm2, "pxa910-pwm.1", NULL),
+ INIT_CLKREG(&clk_pwm3, "pxa910-pwm.2", NULL),
+ INIT_CLKREG(&clk_pwm4, "pxa910-pwm.3", NULL),
};
static int __init pxa910_init(void)
@@ -156,3 +168,9 @@ struct sys_timer pxa910_timer = {
*/
PXA910_DEVICE(uart1, "pxa2xx-uart", 0, UART2, 0xd4017000, 0x30, 21, 22);
PXA910_DEVICE(uart2, "pxa2xx-uart", 1, UART3, 0xd4018000, 0x30, 23, 24);
+PXA910_DEVICE(twsi0, "pxa2xx-i2c", 0, TWSI0, 0xd4011000, 0x28);
+PXA910_DEVICE(twsi1, "pxa2xx-i2c", 1, TWSI1, 0xd4025000, 0x28);
+PXA910_DEVICE(pwm1, "pxa910-pwm", 0, NONE, 0xd401a000, 0x10);
+PXA910_DEVICE(pwm2, "pxa910-pwm", 1, NONE, 0xd401a400, 0x10);
+PXA910_DEVICE(pwm3, "pxa910-pwm", 2, NONE, 0xd401a800, 0x10);
+PXA910_DEVICE(pwm4, "pxa910-pwm", 3, NONE, 0xd401ac00, 0x10);
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 444d9c0f5ca6..4855b8ca5101 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -57,12 +57,12 @@ static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static cycle_t msm_gpt_read(void)
+static cycle_t msm_gpt_read(struct clocksource *cs)
{
return readl(MSM_GPT_BASE + TIMER_COUNT_VAL);
}
-static cycle_t msm_dgt_read(void)
+static cycle_t msm_dgt_read(struct clocksource *cs)
{
return readl(MSM_DGT_BASE + TIMER_COUNT_VAL) >> MSM_DGT_SHIFT;
}
diff --git a/arch/arm/mach-mv78xx0/common.c b/arch/arm/mach-mv78xx0/common.c
index a575daaa62d1..9ba595083dab 100644
--- a/arch/arm/mach-mv78xx0/common.c
+++ b/arch/arm/mach-mv78xx0/common.c
@@ -20,6 +20,7 @@
#include <asm/mach/map.h>
#include <asm/mach/time.h>
#include <mach/mv78xx0.h>
+#include <mach/bridge-regs.h>
#include <plat/cache-feroceon-l2.h>
#include <plat/ehci-orion.h>
#include <plat/orion_nand.h>
diff --git a/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h b/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
new file mode 100644
index 000000000000..2d14c4fe294d
--- /dev/null
+++ b/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
@@ -0,0 +1,39 @@
+/*
+ * arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
+ *
+ * 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 __ASM_ARCH_BRIDGE_REGS_H
+#define __ASM_ARCH_BRIDGE_REGS_H
+
+#include <mach/mv78xx0.h>
+
+#define CPU_CONTROL (BRIDGE_VIRT_BASE | 0x0104)
+#define L2_WRITETHROUGH 0x00020000
+
+#define RSTOUTn_MASK (BRIDGE_VIRT_BASE | 0x0108)
+#define SOFT_RESET_OUT_EN 0x00000004
+
+#define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE | 0x010c)
+#define SOFT_RESET 0x00000001
+
+#define BRIDGE_CAUSE (BRIDGE_VIRT_BASE | 0x0110)
+#define BRIDGE_MASK (BRIDGE_VIRT_BASE | 0x0114)
+#define BRIDGE_INT_TIMER0 0x0002
+#define BRIDGE_INT_TIMER1 0x0004
+#define BRIDGE_INT_TIMER1_CLR (~0x0004)
+
+#define IRQ_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0200)
+#define IRQ_CAUSE_ERR_OFF 0x0000
+#define IRQ_CAUSE_LOW_OFF 0x0004
+#define IRQ_CAUSE_HIGH_OFF 0x0008
+#define IRQ_MASK_ERR_OFF 0x000c
+#define IRQ_MASK_LOW_OFF 0x0010
+#define IRQ_MASK_HIGH_OFF 0x0014
+
+#define TIMER_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0300)
+
+#endif
diff --git a/arch/arm/mach-mv78xx0/include/mach/entry-macro.S b/arch/arm/mach-mv78xx0/include/mach/entry-macro.S
index fbfb2693ce6c..66ae2d29e773 100644
--- a/arch/arm/mach-mv78xx0/include/mach/entry-macro.S
+++ b/arch/arm/mach-mv78xx0/include/mach/entry-macro.S
@@ -8,7 +8,7 @@
* warranty of any kind, whether express or implied.
*/
-#include <mach/mv78xx0.h>
+#include <mach/bridge-regs.h>
.macro disable_fiq
.endm
diff --git a/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h b/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h
index 582cffc733ad..d715b92b0908 100644
--- a/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h
+++ b/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h
@@ -59,37 +59,6 @@
* Core-specific peripheral registers.
*/
#define BRIDGE_VIRT_BASE (MV78XX0_CORE_REGS_VIRT_BASE)
-#define CPU_CONTROL (BRIDGE_VIRT_BASE | 0x0104)
-#define L2_WRITETHROUGH 0x00020000
-#define RSTOUTn_MASK (BRIDGE_VIRT_BASE | 0x0108)
-#define SOFT_RESET_OUT_EN 0x00000004
-#define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE | 0x010c)
-#define SOFT_RESET 0x00000001
-#define BRIDGE_CAUSE (BRIDGE_VIRT_BASE | 0x0110)
-#define BRIDGE_MASK (BRIDGE_VIRT_BASE | 0x0114)
-#define BRIDGE_INT_TIMER0 0x0002
-#define BRIDGE_INT_TIMER1 0x0004
-#define BRIDGE_INT_TIMER1_CLR (~0x0004)
-#define IRQ_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0200)
-#define IRQ_CAUSE_ERR_OFF 0x0000
-#define IRQ_CAUSE_LOW_OFF 0x0004
-#define IRQ_CAUSE_HIGH_OFF 0x0008
-#define IRQ_MASK_ERR_OFF 0x000c
-#define IRQ_MASK_LOW_OFF 0x0010
-#define IRQ_MASK_HIGH_OFF 0x0014
-#define TIMER_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0300)
-
-/*
- * Supported devices and revisions.
- */
-#define MV78X00_Z0_DEV_ID 0x6381
-#define MV78X00_REV_Z0 1
-
-#define MV78100_DEV_ID 0x7810
-#define MV78100_REV_A0 1
-
-#define MV78200_DEV_ID 0x7820
-#define MV78200_REV_A0 1
/*
* Register Map
@@ -135,5 +104,16 @@
#define SATA_PHYS_BASE (MV78XX0_REGS_PHYS_BASE | 0xa0000)
+/*
+ * Supported devices and revisions.
+ */
+#define MV78X00_Z0_DEV_ID 0x6381
+#define MV78X00_REV_Z0 1
+
+#define MV78100_DEV_ID 0x7810
+#define MV78100_REV_A0 1
+
+#define MV78200_DEV_ID 0x7820
+#define MV78200_REV_A0 1
#endif
diff --git a/arch/arm/mach-mv78xx0/include/mach/system.h b/arch/arm/mach-mv78xx0/include/mach/system.h
index 1d6350b22d0b..66e7ce4e90bd 100644
--- a/arch/arm/mach-mv78xx0/include/mach/system.h
+++ b/arch/arm/mach-mv78xx0/include/mach/system.h
@@ -9,8 +9,7 @@
#ifndef __ASM_ARCH_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H
-#include <mach/hardware.h>
-#include <mach/mv78xx0.h>
+#include <mach/bridge-regs.h>
static inline void arch_idle(void)
{
diff --git a/arch/arm/mach-mv78xx0/irq.c b/arch/arm/mach-mv78xx0/irq.c
index 30b7e4bcdbc7..f289b0ea7dcf 100644
--- a/arch/arm/mach-mv78xx0/irq.c
+++ b/arch/arm/mach-mv78xx0/irq.c
@@ -13,7 +13,7 @@
#include <linux/pci.h>
#include <linux/irq.h>
#include <asm/gpio.h>
-#include <mach/mv78xx0.h>
+#include <mach/bridge-regs.h>
#include <plat/irq.h>
#include "common.h"
diff --git a/arch/arm/mach-mx1/mx1ads.c b/arch/arm/mach-mx1/mx1ads.c
index 7ae229bc1b79..e54057fb855b 100644
--- a/arch/arm/mach-mx1/mx1ads.c
+++ b/arch/arm/mach-mx1/mx1ads.c
@@ -28,9 +28,7 @@
#include <mach/common.h>
#include <mach/imx-uart.h>
#include <mach/irqs.h>
-#ifdef CONFIG_I2C_IMX
#include <mach/i2c.h>
-#endif
#include <mach/iomux.h>
#include "devices.h"
@@ -114,7 +112,6 @@ static struct platform_device flash_device = {
* I2C
*/
-#ifdef CONFIG_I2C_IMX
static int i2c_pins[] = {
PA15_PF_I2C_SDA,
PA16_PF_I2C_SCL,
@@ -157,7 +154,6 @@ static struct i2c_board_info mx1ads_i2c_devices[] = {
.platform_data = &pcf857x_data[1],
},
};
-#endif
/*
* Board init
@@ -172,12 +168,10 @@ static void __init mx1ads_init(void)
mxc_register_device(&flash_device, &mx1ads_flash_data);
/* I2C */
-#ifdef CONFIG_I2C_IMX
i2c_register_board_info(0, mx1ads_i2c_devices,
ARRAY_SIZE(mx1ads_i2c_devices));
mxc_register_device(&imx_i2c_device, &mx1ads_i2c_data);
-#endif
}
static void __init mx1ads_timer_init(void)
diff --git a/arch/arm/mach-mx2/clock_imx21.c b/arch/arm/mach-mx2/clock_imx21.c
index 2dee5c87614c..999d013e06e3 100644
--- a/arch/arm/mach-mx2/clock_imx21.c
+++ b/arch/arm/mach-mx2/clock_imx21.c
@@ -919,19 +919,19 @@ static struct clk_lookup lookups[] __initdata = {
_REGISTER_CLOCK(NULL, "cspi1", cspi_clk[0])
_REGISTER_CLOCK(NULL, "cspi2", cspi_clk[1])
_REGISTER_CLOCK(NULL, "cspi3", cspi_clk[2])
- _REGISTER_CLOCK(NULL, "lcdc", lcdc_clk[0])
+ _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk[0])
_REGISTER_CLOCK(NULL, "csi", csi_clk[0])
_REGISTER_CLOCK(NULL, "usb", usb_clk[0])
_REGISTER_CLOCK(NULL, "ssi1", ssi_clk[0])
_REGISTER_CLOCK(NULL, "ssi2", ssi_clk[1])
- _REGISTER_CLOCK(NULL, "nfc", nfc_clk)
+ _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
_REGISTER_CLOCK(NULL, "dma", dma_clk[0])
_REGISTER_CLOCK(NULL, "brom", brom_clk)
_REGISTER_CLOCK(NULL, "emma", emma_clk[0])
_REGISTER_CLOCK(NULL, "slcdc", slcdc_clk[0])
- _REGISTER_CLOCK(NULL, "wdog", wdog_clk)
+ _REGISTER_CLOCK("imx-wdt.0", NULL, wdog_clk)
_REGISTER_CLOCK(NULL, "gpio", gpio_clk)
- _REGISTER_CLOCK(NULL, "i2c", i2c_clk)
+ _REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
_REGISTER_CLOCK("mxc-keypad", NULL, kpp_clk)
_REGISTER_CLOCK(NULL, "owire", owire_clk)
_REGISTER_CLOCK(NULL, "rtc", rtc_clk)
diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig
index d6235583e979..194b8428bba4 100644
--- a/arch/arm/mach-mx3/Kconfig
+++ b/arch/arm/mach-mx3/Kconfig
@@ -19,6 +19,8 @@ config MACH_MX31ADS
config MACH_MX31ADS_WM1133_EV1
bool "Support Wolfson Microelectronics 1133-EV1 module"
depends on MACH_MX31ADS
+ depends on MFD_WM8350_I2C
+ depends on REGULATOR_WM8350
select MFD_WM8350_CONFIG_MODE_0
select MFD_WM8352_CONFIG_MODE_0
help
diff --git a/arch/arm/mach-mx3/mx31ads.c b/arch/arm/mach-mx3/mx31ads.c
index 83e5e8e1276f..a6d6efefa6aa 100644
--- a/arch/arm/mach-mx3/mx31ads.c
+++ b/arch/arm/mach-mx3/mx31ads.c
@@ -102,7 +102,7 @@ static struct imxuart_platform_data uart_pdata = {
.flags = IMXUART_HAVE_RTSCTS,
};
-static int uart_pins[] = {
+static unsigned int uart_pins[] = {
MX31_PIN_CTS1__CTS1,
MX31_PIN_RTS1__RTS1,
MX31_PIN_TXD1__TXD1,
@@ -452,6 +452,8 @@ static int mx31_wm8350_init(struct wm8350 *wm8350)
wm8350->codec.platform_data = &imx32ads_wm8350_setup;
+ regulator_has_full_constraints();
+
return 0;
}
diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c
index c3648eff5137..b5227d837b2f 100644
--- a/arch/arm/mach-mx3/pcm037.c
+++ b/arch/arm/mach-mx3/pcm037.c
@@ -226,10 +226,10 @@ static void __init mxc_board_init(void)
mxc_iomux_setup_pin(MX31_PIN_BATT_LINE__OWIRE, "batt-0wire");
mxc_register_device(&mxc_w1_master_device, NULL);
- /* SMSC9215 IRQ pin */
+ /* LAN9217 IRQ pin */
if (!mxc_iomux_setup_pin(IOMUX_MODE(MX31_PIN_GPIO3_1, IOMUX_CONFIG_GPIO),
"pcm037-eth"))
- gpio_direction_input(MX31_PIN_GPIO3_1);
+ gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1));
#ifdef CONFIG_I2C_IMX
i2c_register_board_info(1, pcm037_i2c_devices,
diff --git a/arch/arm/mach-mx3/qong.c b/arch/arm/mach-mx3/qong.c
index 6c4283cec6f4..5a01e48fd8f1 100644
--- a/arch/arm/mach-mx3/qong.c
+++ b/arch/arm/mach-mx3/qong.c
@@ -251,32 +251,6 @@ static void __init qong_init_fpga(void)
}
/*
- * This structure defines the MX31 memory map.
- */
-static struct map_desc qong_io_desc[] __initdata = {
- {
- .virtual = AIPS1_BASE_ADDR_VIRT,
- .pfn = __phys_to_pfn(AIPS1_BASE_ADDR),
- .length = AIPS1_SIZE,
- .type = MT_DEVICE_NONSHARED
- }, {
- .virtual = AIPS2_BASE_ADDR_VIRT,
- .pfn = __phys_to_pfn(AIPS2_BASE_ADDR),
- .length = AIPS2_SIZE,
- .type = MT_DEVICE_NONSHARED
- }
-};
-
-/*
- * Set up static virtual mappings.
- */
-static void __init qong_map_io(void)
-{
- mxc_map_io();
- iotable_init(qong_io_desc, ARRAY_SIZE(qong_io_desc));
-}
-
-/*
* Board specific initialization.
*/
static void __init mxc_board_init(void)
@@ -305,7 +279,7 @@ MACHINE_START(QONG, "Dave/DENX QongEVB-LITE")
.phys_io = AIPS1_BASE_ADDR,
.io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
.boot_params = PHYS_OFFSET + 0x100,
- .map_io = qong_map_io,
+ .map_io = mxc_map_io,
.init_irq = mxc_init_irq,
.init_machine = mxc_board_init,
.timer = &qong_timer,
diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c
index 79df60c20e70..43da8bb4926b 100644
--- a/arch/arm/mach-netx/generic.c
+++ b/arch/arm/mach-netx/generic.c
@@ -168,7 +168,7 @@ void __init netx_init_irq(void)
{
int irq;
- vic_init(__io(io_p2v(NETX_PA_VIC)), 0, ~0);
+ vic_init(__io(io_p2v(NETX_PA_VIC)), 0, ~0, 0);
for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) {
set_irq_chip(irq, &netx_hif_chip);
diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c
index f201fddb594f..82801dbf0579 100644
--- a/arch/arm/mach-netx/time.c
+++ b/arch/arm/mach-netx/time.c
@@ -104,7 +104,7 @@ static struct irqaction netx_timer_irq = {
.handler = netx_timer_interrupt,
};
-cycle_t netx_get_cycles(void)
+cycle_t netx_get_cycles(struct clocksource *cs)
{
return readl(NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKSOURCE));
}
diff --git a/arch/arm/mach-ns9xxx/time-ns9360.c b/arch/arm/mach-ns9xxx/time-ns9360.c
index 41df69721769..77281260358a 100644
--- a/arch/arm/mach-ns9xxx/time-ns9360.c
+++ b/arch/arm/mach-ns9xxx/time-ns9360.c
@@ -25,7 +25,7 @@
#define TIMER_CLOCKEVENT 1
static u32 latch;
-static cycle_t ns9360_clocksource_read(void)
+static cycle_t ns9360_clocksource_read(struct clocksource *cs)
{
return __raw_readl(SYS_TR(TIMER_CLOCKSOURCE));
}
diff --git a/arch/arm/mach-omap1/board-h2-mmc.c b/arch/arm/mach-omap1/board-h2-mmc.c
index 44d4a966bed9..46098f546824 100644
--- a/arch/arm/mach-omap1/board-h2-mmc.c
+++ b/arch/arm/mach-omap1/board-h2-mmc.c
@@ -26,19 +26,13 @@
static int mmc_set_power(struct device *dev, int slot, int power_on,
int vdd)
{
- if (power_on)
- gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 1);
- else
- gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 0);
-
+ gpio_set_value(H2_TPS_GPIO_MMC_PWR_EN, power_on);
return 0;
}
static int mmc_late_init(struct device *dev)
{
- int ret;
-
- ret = gpio_request(H2_TPS_GPIO_MMC_PWR_EN, "MMC power");
+ int ret = gpio_request(H2_TPS_GPIO_MMC_PWR_EN, "MMC power");
if (ret < 0)
return ret;
@@ -47,7 +41,7 @@ static int mmc_late_init(struct device *dev)
return ret;
}
-static void mmc_shutdown(struct device *dev)
+static void mmc_cleanup(struct device *dev)
{
gpio_free(H2_TPS_GPIO_MMC_PWR_EN);
}
@@ -60,7 +54,7 @@ static void mmc_shutdown(struct device *dev)
static struct omap_mmc_platform_data mmc1_data = {
.nr_slots = 1,
.init = mmc_late_init,
- .shutdown = mmc_shutdown,
+ .cleanup = mmc_cleanup,
.dma_mask = 0xffffffff,
.slots[0] = {
.set_power = mmc_set_power,
diff --git a/arch/arm/mach-omap1/board-h3-mmc.c b/arch/arm/mach-omap1/board-h3-mmc.c
index 0d8a3c195e2e..5e8877ce35e0 100644
--- a/arch/arm/mach-omap1/board-h3-mmc.c
+++ b/arch/arm/mach-omap1/board-h3-mmc.c
@@ -26,11 +26,7 @@
static int mmc_set_power(struct device *dev, int slot, int power_on,
int vdd)
{
- if (power_on)
- gpio_direction_output(H3_TPS_GPIO_MMC_PWR_EN, 1);
- else
- gpio_direction_output(H3_TPS_GPIO_MMC_PWR_EN, 0);
-
+ gpio_set_value(H3_TPS_GPIO_MMC_PWR_EN, power_on);
return 0;
}
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index 4695965114c4..f597968733b4 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -39,12 +39,10 @@
#include <asm/mach/flash.h>
#include <asm/mach/map.h>
-#include <mach/gpioexpander.h>
#include <mach/irqs.h>
#include <mach/mux.h>
#include <mach/tc.h>
#include <mach/nand.h>
-#include <mach/irda.h>
#include <mach/usb.h>
#include <mach/keypad.h>
#include <mach/dma.h>
@@ -276,104 +274,6 @@ static struct platform_device h3_kp_device = {
.resource = h3_kp_resources,
};
-
-/* Select between the IrDA and aGPS module
- */
-static int h3_select_irda(struct device *dev, int state)
-{
- unsigned char expa;
- int err = 0;
-
- if ((err = read_gpio_expa(&expa, 0x26))) {
- printk(KERN_ERR "Error reading from I/O EXPANDER \n");
- return err;
- }
-
- /* 'P6' enable/disable IRDA_TX and IRDA_RX */
- if (state & IR_SEL) { /* IrDA */
- if ((err = write_gpio_expa(expa | 0x40, 0x26))) {
- printk(KERN_ERR "Error writing to I/O EXPANDER \n");
- return err;
- }
- } else {
- if ((err = write_gpio_expa(expa & ~0x40, 0x26))) {
- printk(KERN_ERR "Error writing to I/O EXPANDER \n");
- return err;
- }
- }
- return err;
-}
-
-static void set_trans_mode(struct work_struct *work)
-{
- struct omap_irda_config *irda_config =
- container_of(work, struct omap_irda_config, gpio_expa.work);
- int mode = irda_config->mode;
- unsigned char expa;
- int err = 0;
-
- if ((err = read_gpio_expa(&expa, 0x27)) != 0) {
- printk(KERN_ERR "Error reading from I/O expander\n");
- }
-
- expa &= ~0x03;
-
- if (mode & IR_SIRMODE) {
- expa |= 0x01;
- } else { /* MIR/FIR */
- expa |= 0x03;
- }
-
- if ((err = write_gpio_expa(expa, 0x27)) != 0) {
- printk(KERN_ERR "Error writing to I/O expander\n");
- }
-}
-
-static int h3_transceiver_mode(struct device *dev, int mode)
-{
- struct omap_irda_config *irda_config = dev->platform_data;
-
- irda_config->mode = mode;
- cancel_delayed_work(&irda_config->gpio_expa);
- PREPARE_DELAYED_WORK(&irda_config->gpio_expa, set_trans_mode);
- schedule_delayed_work(&irda_config->gpio_expa, 0);
-
- return 0;
-}
-
-static struct omap_irda_config h3_irda_data = {
- .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE,
- .transceiver_mode = h3_transceiver_mode,
- .select_irda = h3_select_irda,
- .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 h3_irda_resources[] = {
- [0] = {
- .start = INT_UART3,
- .end = INT_UART3,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-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,
-};
-
static struct platform_device h3_lcd_device = {
.name = "lcd_h3",
.id = -1,
@@ -395,7 +295,6 @@ static struct platform_device *devices[] __initdata = {
&nand_device,
&smc91x_device,
&intlat_device,
- &h3_irda_device,
&h3_kp_device,
&h3_lcd_device,
};
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index 7bc7a3cb9c51..d1ed1365319e 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -181,11 +181,7 @@ static struct omap_usb_config nokia770_usb_config __initdata = {
static int nokia770_mmc_set_power(struct device *dev, int slot, int power_on,
int vdd)
{
- if (power_on)
- gpio_set_value(NOKIA770_GPIO_MMC_POWER, 1);
- else
- gpio_set_value(NOKIA770_GPIO_MMC_POWER, 0);
-
+ gpio_set_value(NOKIA770_GPIO_MMC_POWER, power_on);
return 0;
}
diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
index d040c3f1027f..a2d7814896be 100644
--- a/arch/arm/mach-omap1/mcbsp.c
+++ b/arch/arm/mach-omap1/mcbsp.c
@@ -40,8 +40,8 @@ static void omap1_mcbsp_request(unsigned int id)
*/
if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) {
if (dsp_use++ == 0) {
- api_clk = clk_get(NULL, "api_clk");
- dsp_clk = clk_get(NULL, "dsp_clk");
+ api_clk = clk_get(NULL, "api_ck");
+ dsp_clk = clk_get(NULL, "dsp_ck");
if (!IS_ERR(api_clk) && !IS_ERR(dsp_clk)) {
clk_enable(api_clk);
clk_enable(dsp_clk);
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
index 495a32c287b4..4d56408d3cff 100644
--- a/arch/arm/mach-omap1/time.c
+++ b/arch/arm/mach-omap1/time.c
@@ -198,7 +198,7 @@ static struct irqaction omap_mpu_timer2_irq = {
.handler = omap_mpu_timer2_interrupt,
};
-static cycle_t mpu_read(void)
+static cycle_t mpu_read(struct clocksource *cs)
{
return ~omap_mpu_timer_read(1);
}
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index a0267a9ab466..e7d017cdc438 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -33,10 +33,8 @@
#include <mach/control.h>
#include <mach/gpio.h>
-#include <mach/gpioexpander.h>
#include <mach/mux.h>
#include <mach/usb.h>
-#include <mach/irda.h>
#include <mach/board.h>
#include <mach/common.h>
#include <mach/keypad.h>
@@ -138,98 +136,6 @@ static struct platform_device h4_flash_device = {
.resource = &h4_flash_resource,
};
-/* Select between the IrDA and aGPS module
- */
-static int h4_select_irda(struct device *dev, int state)
-{
- unsigned char expa;
- int err = 0;
-
- if ((err = read_gpio_expa(&expa, 0x21))) {
- printk(KERN_ERR "Error reading from I/O expander\n");
- return err;
- }
-
- /* 'P6' enable/disable IRDA_TX and IRDA_RX */
- if (state & IR_SEL) { /* IrDa */
- if ((err = write_gpio_expa(expa | 0x01, 0x21))) {
- printk(KERN_ERR "Error writing to I/O expander\n");
- return err;
- }
- } else {
- if ((err = write_gpio_expa(expa & ~0x01, 0x21))) {
- printk(KERN_ERR "Error writing to I/O expander\n");
- return err;
- }
- }
- return err;
-}
-
-static void set_trans_mode(struct work_struct *work)
-{
- struct omap_irda_config *irda_config =
- container_of(work, struct omap_irda_config, gpio_expa.work);
- int mode = irda_config->mode;
- unsigned char expa;
- int err = 0;
-
- if ((err = read_gpio_expa(&expa, 0x20)) != 0) {
- printk(KERN_ERR "Error reading from I/O expander\n");
- }
-
- expa &= ~0x01;
-
- if (!(mode & IR_SIRMODE)) { /* MIR/FIR */
- expa |= 0x01;
- }
-
- if ((err = write_gpio_expa(expa, 0x20)) != 0) {
- printk(KERN_ERR "Error writing to I/O expander\n");
- }
-}
-
-static int h4_transceiver_mode(struct device *dev, int mode)
-{
- struct omap_irda_config *irda_config = dev->platform_data;
-
- irda_config->mode = mode;
- cancel_delayed_work(&irda_config->gpio_expa);
- PREPARE_DELAYED_WORK(&irda_config->gpio_expa, set_trans_mode);
- schedule_delayed_work(&irda_config->gpio_expa, 0);
-
- return 0;
-}
-
-static struct omap_irda_config h4_irda_data = {
- .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE,
- .transceiver_mode = h4_transceiver_mode,
- .select_irda = h4_select_irda,
- .rx_channel = OMAP24XX_DMA_UART3_RX,
- .tx_channel = OMAP24XX_DMA_UART3_TX,
- .dest_start = OMAP_UART3_BASE,
- .src_start = OMAP_UART3_BASE,
- .tx_trigger = OMAP24XX_DMA_UART3_TX,
- .rx_trigger = OMAP24XX_DMA_UART3_RX,
-};
-
-static struct resource h4_irda_resources[] = {
- [0] = {
- .start = INT_24XX_UART3_IRQ,
- .end = INT_24XX_UART3_IRQ,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device h4_irda_device = {
- .name = "omapirda",
- .id = -1,
- .dev = {
- .platform_data = &h4_irda_data,
- },
- .num_resources = 1,
- .resource = h4_irda_resources,
-};
-
static struct omap_kp_platform_data h4_kp_data = {
.rows = 6,
.cols = 7,
@@ -255,7 +161,6 @@ static struct platform_device h4_lcd_device = {
static struct platform_device *h4_devices[] __initdata = {
&h4_flash_device,
- &h4_irda_device,
&h4_kp_device,
&h4_lcd_device,
};
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 744740ae1b9c..3a7a29d1f9a7 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -42,6 +42,7 @@
#include <mach/nand.h>
#include <mach/mux.h>
#include <mach/usb.h>
+#include <mach/timer-gp.h>
#include "mmc-twl4030.h"
@@ -186,6 +187,9 @@ static void __init omap3_beagle_init_irq(void)
{
omap2_init_common_hw(NULL);
omap_init_irq();
+#ifdef CONFIG_OMAP_32K_TIMER
+ omap2_gp_clockevent_set_gptimer(12);
+#endif
omap_gpio_init();
}
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index 3a0daac6c839..374ff63c3eb2 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -15,7 +15,6 @@
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/io.h>
-#include <linux/delay.h>
#include <linux/gpio.h>
#include <mach/hardware.h>
diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
index 1e839c5a28c5..efc59c49341b 100644
--- a/arch/arm/mach-omap2/clock24xx.c
+++ b/arch/arm/mach-omap2/clock24xx.c
@@ -60,12 +60,13 @@ struct omap_clk {
}, \
}
-#define CK_243X (1 << 0)
-#define CK_242X (1 << 1)
+#define CK_243X RATE_IN_243X
+#define CK_242X RATE_IN_242X
static struct omap_clk omap24xx_clks[] = {
/* external root sources */
CLK(NULL, "func_32k_ck", &func_32k_ck, CK_243X | CK_242X),
+ CLK(NULL, "secure_32k_ck", &secure_32k_ck, CK_243X | CK_242X),
CLK(NULL, "osc_ck", &osc_ck, CK_243X | CK_242X),
CLK(NULL, "sys_ck", &sys_ck, CK_243X | CK_242X),
CLK(NULL, "alt_ck", &alt_ck, CK_243X | CK_242X),
@@ -711,7 +712,7 @@ int __init omap2_clk_init(void)
{
struct prcm_config *prcm;
struct omap_clk *c;
- u32 clkrate, cpu_mask;
+ u32 clkrate;
if (cpu_is_omap242x())
cpu_mask = RATE_IN_242X;
@@ -720,21 +721,15 @@ int __init omap2_clk_init(void)
clk_init(&omap2_clk_functions);
+ for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++)
+ clk_init_one(c->lk.clk);
+
osc_ck.rate = omap2_osc_clk_recalc(&osc_ck);
propagate_rate(&osc_ck);
sys_ck.rate = omap2_sys_clk_recalc(&sys_ck);
propagate_rate(&sys_ck);
for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++)
- clk_init_one(c->lk.clk);
-
- cpu_mask = 0;
- if (cpu_is_omap2420())
- cpu_mask |= CK_242X;
- if (cpu_is_omap2430())
- cpu_mask |= CK_243X;
-
- for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++)
if (c->cpu & cpu_mask) {
clkdev_add(&c->lk);
clk_register(c->lk.clk);
diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h
index 33c3e5b14323..88c5acb40fcf 100644
--- a/arch/arm/mach-omap2/clock24xx.h
+++ b/arch/arm/mach-omap2/clock24xx.h
@@ -625,6 +625,14 @@ static struct clk func_32k_ck = {
.clkdm_name = "wkup_clkdm",
};
+static struct clk secure_32k_ck = {
+ .name = "secure_32k_ck",
+ .ops = &clkops_null,
+ .rate = 32768,
+ .flags = RATE_FIXED,
+ .clkdm_name = "wkup_clkdm",
+};
+
/* Typical 12/13MHz in standalone mode, will be 26Mhz in chassis mode */
static struct clk osc_ck = { /* (*12, *13, 19.2, *26, 38.4)MHz */
.name = "osc_ck",
@@ -1790,7 +1798,7 @@ static struct clk gpt12_ick = {
static struct clk gpt12_fck = {
.name = "gpt12_fck",
.ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
+ .parent = &secure_32k_ck,
.clkdm_name = "core_l4_clkdm",
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
.enable_bit = OMAP24XX_EN_GPT12_SHIFT,
diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
index 70ec10deb654..6763b8f73028 100644
--- a/arch/arm/mach-omap2/clock34xx.h
+++ b/arch/arm/mach-omap2/clock34xx.h
@@ -2052,7 +2052,7 @@ static struct clk dss_ick = {
static struct clk cam_mclk = {
.name = "cam_mclk",
- .ops = &clkops_omap2_dflt_wait,
+ .ops = &clkops_omap2_dflt,
.parent = &dpll4_m5x2_ck,
.enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
.enable_bit = OMAP3430_EN_CAM_SHIFT,
@@ -2063,7 +2063,7 @@ static struct clk cam_mclk = {
static struct clk cam_ick = {
/* Handles both L3 and L4 clocks */
.name = "cam_ick",
- .ops = &clkops_omap2_dflt_wait,
+ .ops = &clkops_omap2_dflt,
.parent = &l4_ick,
.init = &omap2_init_clk_clkdm,
.enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
@@ -2074,7 +2074,7 @@ static struct clk cam_ick = {
static struct clk csi2_96m_fck = {
.name = "csi2_96m_fck",
- .ops = &clkops_omap2_dflt_wait,
+ .ops = &clkops_omap2_dflt,
.parent = &core_96m_fck,
.init = &omap2_init_clk_clkdm,
.enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
@@ -2901,7 +2901,6 @@ static struct clk sr_l4_ick = {
/* SECURE_32K_FCK clocks */
-/* XXX This clock no longer exists in 3430 TRM rev F */
static struct clk gpt12_fck = {
.name = "gpt12_fck",
.ops = &clkops_null,
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index d6b4b2f8722f..496983ade97e 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -25,7 +25,6 @@
#include <mach/board.h>
#include <mach/mux.h>
#include <mach/gpio.h>
-#include <mach/eac.h>
#include <mach/mmc.h>
#if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE)
@@ -366,38 +365,6 @@ static void omap_init_mcspi(void)
static inline void omap_init_mcspi(void) {}
#endif
-#ifdef CONFIG_SND_OMAP24XX_EAC
-
-#define OMAP2_EAC_BASE 0x48090000
-
-static struct resource omap2_eac_resources[] = {
- {
- .start = OMAP2_EAC_BASE,
- .end = OMAP2_EAC_BASE + 0x109,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct platform_device omap2_eac_device = {
- .name = "omap24xx-eac",
- .id = -1,
- .num_resources = ARRAY_SIZE(omap2_eac_resources),
- .resource = omap2_eac_resources,
- .dev = {
- .platform_data = NULL,
- },
-};
-
-void omap_init_eac(struct eac_platform_data *pdata)
-{
- omap2_eac_device.dev.platform_data = pdata;
- platform_device_register(&omap2_eac_device);
-}
-
-#else
-void omap_init_eac(struct eac_platform_data *pdata) {}
-#endif
-
#ifdef CONFIG_OMAP_SHA1_MD5
static struct resource sha1_md5_resources[] = {
{
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index 9ba20d985dda..998c5c45587e 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -73,9 +73,9 @@ static int omap_check_spurious(unsigned int irq)
u32 sir, spurious;
sir = intc_bank_read_reg(&irq_banks[0], INTC_SIR);
- spurious = sir >> 6;
+ spurious = sir >> 7;
- if (spurious > 1) {
+ if (spurious) {
printk(KERN_WARNING "Spurious irq %i: 0x%08x, please flush "
"posted write for irq %i\n",
irq, sir, previous_irq);
diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
index 9fc13a2cc3f4..f36aba12090e 100644
--- a/arch/arm/mach-omap2/timer-gp.c
+++ b/arch/arm/mach-omap2/timer-gp.c
@@ -3,6 +3,8 @@
*
* OMAP2 GP timer support.
*
+ * Copyright (C) 2009 Nokia Corporation
+ *
* Update to use new clocksource/clockevent layers
* Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
* Copyright (C) 2007 MontaVista Software, Inc.
@@ -36,8 +38,13 @@
#include <asm/mach/time.h>
#include <mach/dmtimer.h>
+/* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
+#define MAX_GPTIMER_ID 12
+
static struct omap_dm_timer *gptimer;
static struct clock_event_device clockevent_gpt;
+static u8 __initdata gptimer_id = 1;
+static u8 __initdata inited;
static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
{
@@ -95,20 +102,53 @@ static struct clock_event_device clockevent_gpt = {
.set_mode = omap2_gp_timer_set_mode,
};
+/**
+ * omap2_gp_clockevent_set_gptimer - set which GPTIMER is used for clockevents
+ * @id: GPTIMER to use (1..MAX_GPTIMER_ID)
+ *
+ * Define the GPTIMER that the system should use for the tick timer.
+ * Meant to be called from board-*.c files in the event that GPTIMER1, the
+ * default, is unsuitable. Returns -EINVAL on error or 0 on success.
+ */
+int __init omap2_gp_clockevent_set_gptimer(u8 id)
+{
+ if (id < 1 || id > MAX_GPTIMER_ID)
+ return -EINVAL;
+
+ BUG_ON(inited);
+
+ gptimer_id = id;
+
+ return 0;
+}
+
static void __init omap2_gp_clockevent_init(void)
{
u32 tick_rate;
+ int src;
+
+ inited = 1;
- gptimer = omap_dm_timer_request_specific(1);
+ gptimer = omap_dm_timer_request_specific(gptimer_id);
BUG_ON(gptimer == NULL);
#if defined(CONFIG_OMAP_32K_TIMER)
- omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_32_KHZ);
+ src = OMAP_TIMER_SRC_32_KHZ;
#else
- omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_SYS_CLK);
+ src = OMAP_TIMER_SRC_SYS_CLK;
+ WARN(gptimer_id == 12, "WARNING: GPTIMER12 can only use the "
+ "secure 32KiHz clock source\n");
#endif
+
+ if (gptimer_id != 12)
+ WARN(IS_ERR_VALUE(omap_dm_timer_set_source(gptimer, src)),
+ "timer-gp: omap_dm_timer_set_source() failed\n");
+
tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer));
+ pr_info("OMAP clockevent source: GPTIMER%d at %u Hz\n",
+ gptimer_id, tick_rate);
+
omap2_gp_timer_irq.dev_id = (void *)gptimer;
setup_irq(omap_dm_timer_get_irq(gptimer), &omap2_gp_timer_irq);
omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW);
@@ -125,6 +165,8 @@ static void __init omap2_gp_clockevent_init(void)
clockevents_register_device(&clockevent_gpt);
}
+/* Clocksource code */
+
#ifdef CONFIG_OMAP_32K_TIMER
/*
* When 32k-timer is enabled, don't use GPTimer for clocksource
@@ -138,7 +180,7 @@ static inline void __init omap2_gp_clocksource_init(void) {}
* clocksource
*/
static struct omap_dm_timer *gpt_clocksource;
-static cycle_t clocksource_read_cycles(void)
+static cycle_t clocksource_read_cycles(struct clocksource *cs)
{
return (cycle_t)omap_dm_timer_read_counter(gpt_clocksource);
}
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index fc74e913c415..34a56a136efd 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -131,14 +131,14 @@ static struct musb_hdrc_platform_data musb_plat = {
.power = 50, /* up to 100 mA */
};
-static u64 musb_dmamask = DMA_32BIT_MASK;
+static u64 musb_dmamask = DMA_BIT_MASK(32);
static struct platform_device musb_device = {
.name = "musb_hdrc",
.id = -1,
.dev = {
.dma_mask = &musb_dmamask,
- .coherent_dma_mask = DMA_32BIT_MASK,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &musb_plat,
},
.num_resources = ARRAY_SIZE(musb_resources),
@@ -146,14 +146,14 @@ static struct platform_device musb_device = {
};
#ifdef CONFIG_NOP_USB_XCEIV
-static u64 nop_xceiv_dmamask = DMA_32BIT_MASK;
+static u64 nop_xceiv_dmamask = DMA_BIT_MASK(32);
static struct platform_device nop_xceiv_device = {
.name = "nop_usb_xceiv",
.id = -1,
.dev = {
.dma_mask = &nop_xceiv_dmamask,
- .coherent_dma_mask = DMA_32BIT_MASK,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = NULL,
},
};
diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c
index 15e509013def..8df55f40f4c0 100644
--- a/arch/arm/mach-omap2/usb-tusb6010.c
+++ b/arch/arm/mach-omap2/usb-tusb6010.c
@@ -187,7 +187,7 @@ int tusb6010_platform_retime(unsigned is_refclk)
unsigned sysclk_ps;
int status;
- if (!refclk_psec)
+ if (!refclk_psec || sysclk_ps == 0)
return -ENODEV;
sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60;
diff --git a/arch/arm/mach-orion5x/addr-map.c b/arch/arm/mach-orion5x/addr-map.c
index 719957e05d9e..c14d12137276 100644
--- a/arch/arm/mach-orion5x/addr-map.c
+++ b/arch/arm/mach-orion5x/addr-map.c
@@ -57,12 +57,14 @@
/*
* Helpers to get DDR bank info
*/
+#define ORION5X_DDR_REG(x) (ORION5X_DDR_VIRT_BASE | (x))
#define DDR_BASE_CS(n) ORION5X_DDR_REG(0x1500 + ((n) << 3))
#define DDR_SIZE_CS(n) ORION5X_DDR_REG(0x1504 + ((n) << 3))
/*
* CPU Address Decode Windows registers
*/
+#define ORION5X_BRIDGE_REG(x) (ORION5X_BRIDGE_VIRT_BASE | (x))
#define CPU_WIN_CTRL(n) ORION5X_BRIDGE_REG(0x000 | ((n) << 4))
#define CPU_WIN_BASE(n) ORION5X_BRIDGE_REG(0x004 | ((n) << 4))
#define CPU_WIN_REMAP_LO(n) ORION5X_BRIDGE_REG(0x008 | ((n) << 4))
diff --git a/arch/arm/mach-orion5x/include/mach/bridge-regs.h b/arch/arm/mach-orion5x/include/mach/bridge-regs.h
new file mode 100644
index 000000000000..be896e59d3e7
--- /dev/null
+++ b/arch/arm/mach-orion5x/include/mach/bridge-regs.h
@@ -0,0 +1,41 @@
+/*
+ * arch/arm/mach-orion5x/include/mach/bridge-regs.h
+ *
+ * Orion CPU Bridge Registers
+ *
+ * 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 __ASM_ARCH_BRIDGE_REGS_H
+#define __ASM_ARCH_BRIDGE_REGS_H
+
+#include <mach/orion5x.h>
+
+#define CPU_CONF (ORION5X_BRIDGE_VIRT_BASE | 0x100)
+
+#define CPU_CTRL (ORION5X_BRIDGE_VIRT_BASE | 0x104)
+
+#define CPU_RESET_MASK (ORION5X_BRIDGE_VIRT_BASE | 0x108)
+#define WDT_RESET 0x0002
+
+#define CPU_SOFT_RESET (ORION5X_BRIDGE_VIRT_BASE | 0x10c)
+
+#define POWER_MNG_CTRL_REG (ORION5X_BRIDGE_VIRT_BASE | 0x11C)
+
+#define BRIDGE_CAUSE (ORION5X_BRIDGE_VIRT_BASE | 0x110)
+#define WDT_INT_REQ 0x0008
+
+#define BRIDGE_MASK (ORION5X_BRIDGE_VIRT_BASE | 0x114)
+#define BRIDGE_INT_TIMER0 0x0002
+#define BRIDGE_INT_TIMER1 0x0004
+#define BRIDGE_INT_TIMER1_CLR (~0x0004)
+
+#define MAIN_IRQ_CAUSE (ORION5X_BRIDGE_VIRT_BASE | 0x200)
+
+#define MAIN_IRQ_MASK (ORION5X_BRIDGE_VIRT_BASE | 0x204)
+
+#define TIMER_VIRT_BASE (ORION5X_BRIDGE_VIRT_BASE | 0x300)
+
+#endif
diff --git a/arch/arm/mach-orion5x/include/mach/entry-macro.S b/arch/arm/mach-orion5x/include/mach/entry-macro.S
index 4351937035cd..d658992e5401 100644
--- a/arch/arm/mach-orion5x/include/mach/entry-macro.S
+++ b/arch/arm/mach-orion5x/include/mach/entry-macro.S
@@ -8,7 +8,7 @@
* warranty of any kind, whether express or implied.
*/
-#include <mach/orion5x.h>
+#include <mach/bridge-regs.h>
.macro disable_fiq
.endm
diff --git a/arch/arm/mach-orion5x/include/mach/orion5x.h b/arch/arm/mach-orion5x/include/mach/orion5x.h
index 67bda31406dd..377a773ae53f 100644
--- a/arch/arm/mach-orion5x/include/mach/orion5x.h
+++ b/arch/arm/mach-orion5x/include/mach/orion5x.h
@@ -61,30 +61,10 @@
#define ORION5X_PCI_MEM_SIZE SZ_128M
/*******************************************************************************
- * Supported Devices & Revisions
- ******************************************************************************/
-/* Orion-1 (88F5181) and Orion-VoIP (88F5181L) */
-#define MV88F5181_DEV_ID 0x5181
-#define MV88F5181_REV_B1 3
-#define MV88F5181L_REV_A0 8
-#define MV88F5181L_REV_A1 9
-/* Orion-NAS (88F5182) */
-#define MV88F5182_DEV_ID 0x5182
-#define MV88F5182_REV_A2 2
-/* Orion-2 (88F5281) */
-#define MV88F5281_DEV_ID 0x5281
-#define MV88F5281_REV_D0 4
-#define MV88F5281_REV_D1 5
-#define MV88F5281_REV_D2 6
-/* Orion-1-90 (88F6183) */
-#define MV88F6183_DEV_ID 0x6183
-#define MV88F6183_REV_B0 3
-
-/*******************************************************************************
* Orion Registers Map
******************************************************************************/
+
#define ORION5X_DDR_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x00000)
-#define ORION5X_DDR_REG(x) (ORION5X_DDR_VIRT_BASE | (x))
#define ORION5X_DEV_BUS_PHYS_BASE (ORION5X_REGS_PHYS_BASE | 0x10000)
#define ORION5X_DEV_BUS_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x10000)
@@ -97,34 +77,25 @@
#define UART1_VIRT_BASE (ORION5X_DEV_BUS_VIRT_BASE | 0x2100)
#define ORION5X_BRIDGE_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x20000)
-#define ORION5X_BRIDGE_REG(x) (ORION5X_BRIDGE_VIRT_BASE | (x))
-#define TIMER_VIRT_BASE (ORION5X_BRIDGE_VIRT_BASE | 0x300)
#define ORION5X_PCI_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x30000)
-#define ORION5X_PCI_REG(x) (ORION5X_PCI_VIRT_BASE | (x))
#define ORION5X_PCIE_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x40000)
-#define ORION5X_PCIE_REG(x) (ORION5X_PCIE_VIRT_BASE | (x))
#define ORION5X_USB0_PHYS_BASE (ORION5X_REGS_PHYS_BASE | 0x50000)
#define ORION5X_USB0_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x50000)
-#define ORION5X_USB0_REG(x) (ORION5X_USB0_VIRT_BASE | (x))
#define ORION5X_XOR_PHYS_BASE (ORION5X_REGS_PHYS_BASE | 0x60900)
#define ORION5X_XOR_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x60900)
-#define ORION5X_XOR_REG(x) (ORION5X_XOR_VIRT_BASE | (x))
#define ORION5X_ETH_PHYS_BASE (ORION5X_REGS_PHYS_BASE | 0x70000)
#define ORION5X_ETH_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x70000)
-#define ORION5X_ETH_REG(x) (ORION5X_ETH_VIRT_BASE | (x))
#define ORION5X_SATA_PHYS_BASE (ORION5X_REGS_PHYS_BASE | 0x80000)
#define ORION5X_SATA_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x80000)
-#define ORION5X_SATA_REG(x) (ORION5X_SATA_VIRT_BASE | (x))
#define ORION5X_USB1_PHYS_BASE (ORION5X_REGS_PHYS_BASE | 0xa0000)
#define ORION5X_USB1_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0xa0000)
-#define ORION5X_USB1_REG(x) (ORION5X_USB1_VIRT_BASE | (x))
/*******************************************************************************
* Device Bus Registers
@@ -142,23 +113,24 @@
#define DEV_BUS_INT_CAUSE ORION5X_DEV_BUS_REG(0x4d0)
#define DEV_BUS_INT_MASK ORION5X_DEV_BUS_REG(0x4d4)
-/***************************************************************************
- * Orion CPU Bridge Registers
- **************************************************************************/
-#define CPU_CONF ORION5X_BRIDGE_REG(0x100)
-#define CPU_CTRL ORION5X_BRIDGE_REG(0x104)
-#define CPU_RESET_MASK ORION5X_BRIDGE_REG(0x108)
-#define WDT_RESET 0x0002
-#define CPU_SOFT_RESET ORION5X_BRIDGE_REG(0x10c)
-#define POWER_MNG_CTRL_REG ORION5X_BRIDGE_REG(0x11C)
-#define BRIDGE_CAUSE ORION5X_BRIDGE_REG(0x110)
-#define WDT_INT_REQ 0x0008
-#define BRIDGE_MASK ORION5X_BRIDGE_REG(0x114)
-#define BRIDGE_INT_TIMER0 0x0002
-#define BRIDGE_INT_TIMER1 0x0004
-#define BRIDGE_INT_TIMER1_CLR (~0x0004)
-#define MAIN_IRQ_CAUSE ORION5X_BRIDGE_REG(0x200)
-#define MAIN_IRQ_MASK ORION5X_BRIDGE_REG(0x204)
-
+/*******************************************************************************
+ * Supported Devices & Revisions
+ ******************************************************************************/
+/* Orion-1 (88F5181) and Orion-VoIP (88F5181L) */
+#define MV88F5181_DEV_ID 0x5181
+#define MV88F5181_REV_B1 3
+#define MV88F5181L_REV_A0 8
+#define MV88F5181L_REV_A1 9
+/* Orion-NAS (88F5182) */
+#define MV88F5182_DEV_ID 0x5182
+#define MV88F5182_REV_A2 2
+/* Orion-2 (88F5281) */
+#define MV88F5281_DEV_ID 0x5281
+#define MV88F5281_REV_D0 4
+#define MV88F5281_REV_D1 5
+#define MV88F5281_REV_D2 6
+/* Orion-1-90 (88F6183) */
+#define MV88F6183_DEV_ID 0x6183
+#define MV88F6183_REV_B0 3
#endif
diff --git a/arch/arm/mach-orion5x/include/mach/system.h b/arch/arm/mach-orion5x/include/mach/system.h
index 9b8db1dcfa83..e912490fff23 100644
--- a/arch/arm/mach-orion5x/include/mach/system.h
+++ b/arch/arm/mach-orion5x/include/mach/system.h
@@ -11,8 +11,7 @@
#ifndef __ASM_ARCH_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H
-#include <mach/hardware.h>
-#include <mach/orion5x.h>
+#include <mach/bridge-regs.h>
static inline void arch_idle(void)
{
diff --git a/arch/arm/mach-orion5x/irq.c b/arch/arm/mach-orion5x/irq.c
index e03f7b45cb0d..d7512b925a85 100644
--- a/arch/arm/mach-orion5x/irq.c
+++ b/arch/arm/mach-orion5x/irq.c
@@ -15,7 +15,7 @@
#include <linux/irq.h>
#include <linux/io.h>
#include <asm/gpio.h>
-#include <mach/orion5x.h>
+#include <mach/bridge-regs.h>
#include <plat/irq.h>
#include "common.h"
diff --git a/arch/arm/mach-orion5x/mss2-setup.c b/arch/arm/mach-orion5x/mss2-setup.c
index 68acca98e638..41e6d5033d54 100644
--- a/arch/arm/mach-orion5x/mss2-setup.c
+++ b/arch/arm/mach-orion5x/mss2-setup.c
@@ -26,6 +26,7 @@
#include <asm/mach/arch.h>
#include <asm/mach/pci.h>
#include <mach/orion5x.h>
+#include <mach/bridge-regs.h>
#include "common.h"
#include "mpp.h"
diff --git a/arch/arm/mach-orion5x/pci.c b/arch/arm/mach-orion5x/pci.c
index d0a785a3b880..36dc5413cc97 100644
--- a/arch/arm/mach-orion5x/pci.c
+++ b/arch/arm/mach-orion5x/pci.c
@@ -196,6 +196,7 @@ static int __init pcie_setup(struct pci_sys_data *sys)
/*****************************************************************************
* PCI controller
****************************************************************************/
+#define ORION5X_PCI_REG(x) (ORION5X_PCI_VIRT_BASE | (x))
#define PCI_MODE ORION5X_PCI_REG(0xd00)
#define PCI_CMD ORION5X_PCI_REG(0xc00)
#define PCI_P2P_CONF ORION5X_PCI_REG(0x1d14)
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 3e66d9099eab..3b34f34db204 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -280,6 +280,7 @@ config MACH_ZYLONITE
select PXA3xx
select PXA_SSP
select HAVE_PWM
+ select PXA_HAVE_BOARD_IRQS
config MACH_LITTLETON
bool "PXA3xx Form Factor Platform (aka Littleton)"
@@ -289,12 +290,12 @@ config MACH_LITTLETON
config MACH_TAVOREVB
bool "PXA930 Evaluation Board (aka TavorEVB)"
select PXA3xx
- select PXA930
+ select CPU_PXA930
config MACH_SAAR
bool "PXA930 Handheld Platform (aka SAAR)"
select PXA3xx
- select PXA930
+ select CPU_PXA930
config MACH_ARMCORE
bool "CompuLab CM-X255/CM-X270 modules"
@@ -505,12 +506,6 @@ config PXA_SSP
help
Enable support for PXA2xx SSP ports
-config PXA_PWM
- tristate
- default BACKLIGHT_PWM
- help
- Enable support for PXA2xx/PXA3xx PWM controllers
-
config TOSA_BT
tristate "Control the state of built-in bluetooth chip on Sharp SL-6000"
depends on MACH_TOSA
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 682dbf4e14b0..47d01572a04d 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -15,7 +15,6 @@ endif
# Generic drivers that other drivers may depend upon
obj-$(CONFIG_PXA_SSP) += ssp.o
-obj-$(CONFIG_PXA_PWM) += pwm.o
# SoC-specific code
obj-$(CONFIG_PXA25x) += mfp-pxa2xx.o pxa2xx.o pxa25x.o
diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index a9f48b1cb54a..a97f87a90d0d 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -32,7 +32,7 @@
#include <mach/pxafb.h>
#include <mach/mmc.h>
#include <mach/ohci.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include <mach/pxa3xx_nand.h>
#include <asm/mach/map.h>
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index cdf21dd135b4..962dda2e154a 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -42,7 +42,7 @@
#include <asm/mach/irq.h>
#include <mach/pxa25x.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include <mach/irda.h>
#include <mach/mmc.h>
#include <mach/udc.h>
@@ -427,21 +427,26 @@ static struct pxa2xx_spi_master corgi_spi_info = {
.num_chipselect = 3,
};
+static void corgi_wait_for_hsync(void)
+{
+ while (gpio_get_value(CORGI_GPIO_HSYNC))
+ cpu_relax();
+
+ while (!gpio_get_value(CORGI_GPIO_HSYNC))
+ cpu_relax();
+}
+
static struct ads7846_platform_data corgi_ads7846_info = {
.model = 7846,
.vref_delay_usecs = 100,
.x_plate_ohms = 419,
.y_plate_ohms = 486,
.gpio_pendown = CORGI_GPIO_TP_INT,
+ .wait_for_sync = corgi_wait_for_hsync,
};
-static void corgi_ads7846_cs(u32 command)
-{
- gpio_set_value(CORGI_GPIO_ADS7846_CS, !(command == PXA2XX_CS_ASSERT));
-}
-
static struct pxa2xx_spi_chip corgi_ads7846_chip = {
- .cs_control = corgi_ads7846_cs,
+ .gpio_cs = CORGI_GPIO_ADS7846_CS,
};
static void corgi_bl_kick_battery(void)
@@ -465,22 +470,12 @@ static struct corgi_lcd_platform_data corgi_lcdcon_info = {
.kick_battery = corgi_bl_kick_battery,
};
-static void corgi_lcdcon_cs(u32 command)
-{
- gpio_set_value(CORGI_GPIO_LCDCON_CS, !(command == PXA2XX_CS_ASSERT));
-}
-
static struct pxa2xx_spi_chip corgi_lcdcon_chip = {
- .cs_control = corgi_lcdcon_cs,
+ .gpio_cs = CORGI_GPIO_LCDCON_CS,
};
-static void corgi_max1111_cs(u32 command)
-{
- gpio_set_value(CORGI_GPIO_MAX1111_CS, !(command == PXA2XX_CS_ASSERT));
-}
-
static struct pxa2xx_spi_chip corgi_max1111_chip = {
- .cs_control = corgi_max1111_cs,
+ .gpio_cs = CORGI_GPIO_MAX1111_CS,
};
static struct spi_board_info corgi_spi_devices[] = {
@@ -510,32 +505,8 @@ static struct spi_board_info corgi_spi_devices[] = {
static void __init corgi_init_spi(void)
{
- int err;
-
- err = gpio_request(CORGI_GPIO_ADS7846_CS, "ADS7846_CS");
- if (err)
- return;
-
- err = gpio_request(CORGI_GPIO_LCDCON_CS, "LCDCON_CS");
- if (err)
- goto err_free_1;
-
- err = gpio_request(CORGI_GPIO_MAX1111_CS, "MAX1111_CS");
- if (err)
- goto err_free_2;
-
- gpio_direction_output(CORGI_GPIO_ADS7846_CS, 1);
- gpio_direction_output(CORGI_GPIO_LCDCON_CS, 1);
- gpio_direction_output(CORGI_GPIO_MAX1111_CS, 1);
-
pxa2xx_set_spi_info(1, &corgi_spi_info);
spi_register_board_info(ARRAY_AND_SIZE(corgi_spi_devices));
- return;
-
-err_free_2:
- gpio_free(CORGI_GPIO_LCDCON_CS);
-err_free_1:
- gpio_free(CORGI_GPIO_ADS7846_CS);
}
#else
static inline void corgi_init_spi(void) {}
diff --git a/arch/arm/mach-pxa/csb726.c b/arch/arm/mach-pxa/csb726.c
index 2b289f83a61a..a7854e44d618 100644
--- a/arch/arm/mach-pxa/csb726.c
+++ b/arch/arm/mach-pxa/csb726.c
@@ -16,15 +16,17 @@
#include <linux/mtd/physmap.h>
#include <linux/mtd/partitions.h>
#include <linux/sm501.h>
+#include <linux/smsc911x.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/csb726.h>
#include <mach/mfp-pxa27x.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include <mach/mmc.h>
#include <mach/ohci.h>
#include <mach/pxa2xx-regs.h>
+#include <mach/audio.h>
#include "generic.h"
#include "devices.h"
@@ -275,13 +277,22 @@ static struct resource csb726_lan_resources[] = {
{
.start = CSB726_IRQ_LAN,
.end = CSB726_IRQ_LAN,
- .flags = IORESOURCE_IRQ,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
},
};
+struct smsc911x_platform_config csb726_lan_config = {
+ .irq_type = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+ .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+ .flags = SMSC911X_USE_32BIT,
+ .phy_interface = PHY_INTERFACE_MODE_MII,
+};
+
+
static struct platform_device csb726_lan = {
- .name = "smc911x",
+ .name = "smsc911x",
.id = -1,
+ .platform_data = &csb726_lan_config,
.num_resources = ARRAY_SIZE(csb726_lan_resources),
.resource = csb726_lan_resources,
};
@@ -303,6 +314,7 @@ static void __init csb726_init(void)
pxa27x_set_i2c_power_info(NULL);
pxa_set_mci_info(&csb726_mci);
pxa_set_ohci_info(&csb726_ohci_platform_data);
+ pxa_set_ac97_info(NULL);
platform_add_devices(devices, ARRAY_SIZE(devices));
}
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index d245e59c51b1..d3c3b7b025ae 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -8,7 +8,7 @@
#include <mach/pxafb.h>
#include <mach/mmc.h>
#include <mach/irda.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include <mach/ohci.h>
#include <mach/pxa27x_keypad.h>
#include <mach/pxa2xx_spi.h>
@@ -287,7 +287,7 @@ static struct resource pxa3xx_resources_i2c_power[] = {
};
struct platform_device pxa3xx_device_i2c_power = {
- .name = "pxa2xx-i2c",
+ .name = "pxa3xx-pwri2c",
.id = 1,
.resource = pxa3xx_resources_i2c_power,
.num_resources = ARRAY_SIZE(pxa3xx_resources_i2c_power),
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index 67611dadb44e..3503f523070b 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -28,7 +28,6 @@
#include <linux/spi/libertas_spi.h>
#include <linux/power_supply.h>
#include <linux/apm-emulation.h>
-#include <linux/delay.h>
#include <media/soc_camera.h>
@@ -42,7 +41,7 @@
#include <mach/ohci.h>
#include <mach/mmc.h>
#include <mach/pxa27x_keypad.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include <mach/camera.h>
#include <mach/pxa2xx_spi.h>
@@ -644,8 +643,9 @@ static struct pxa2xx_spi_master em_x270_spi_info = {
};
static struct pxa2xx_spi_chip em_x270_tdo24m_chip = {
- .rx_threshold = 1,
- .tx_threshold = 1,
+ .rx_threshold = 1,
+ .tx_threshold = 1,
+ .gpio_cs = -1,
};
static struct tdo24m_platform_data em_x270_tdo24m_pdata = {
diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c
index 92ba16e1b6fc..afc214a417bb 100644
--- a/arch/arm/mach-pxa/ezx.c
+++ b/arch/arm/mach-pxa/ezx.c
@@ -25,7 +25,7 @@
#include <mach/pxa27x.h>
#include <mach/pxafb.h>
#include <mach/ohci.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include <mach/hardware.h>
#include <mach/pxa27x_keypad.h>
diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
index 3465268ca716..485fede83d97 100644
--- a/arch/arm/mach-pxa/generic.h
+++ b/arch/arm/mach-pxa/generic.h
@@ -15,6 +15,9 @@ extern struct sys_timer pxa_timer;
extern void __init pxa_init_irq(int irq_nr,
int (*set_wake)(unsigned int, unsigned int));
extern void __init pxa25x_init_irq(void);
+#ifdef CONFIG_CPU_PXA26x
+extern void __init pxa26x_init_irq(void);
+#endif
extern void __init pxa27x_init_irq(void);
extern void __init pxa3xx_init_irq(void);
extern void __init pxa_map_io(void);
diff --git a/arch/arm/mach-pxa/imote2.c b/arch/arm/mach-pxa/imote2.c
index 2121309b2474..3ef98d43d303 100644
--- a/arch/arm/mach-pxa/imote2.c
+++ b/arch/arm/mach-pxa/imote2.c
@@ -29,7 +29,7 @@
#include <asm/mach/flash.h>
#include <mach/pxa27x.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include <mach/udc.h>
#include <mach/mmc.h>
#include <mach/pxa2xx_spi.h>
@@ -456,25 +456,12 @@ static struct pxa2xx_spi_master pxa_ssp_master_2_info = {
.num_chipselect = 1,
};
-/* Patch posted by Eric Miao <eric.miao@marvell.com> will remove
- * the need for these functions.
- */
-static void spi1control(u32 command)
-{
- gpio_set_value(24, command & PXA2XX_CS_ASSERT ? 0 : 1);
-};
-
-static void spi3control(u32 command)
-{
- gpio_set_value(39, command & PXA2XX_CS_ASSERT ? 0 : 1);
-};
-
static struct pxa2xx_spi_chip staccel_chip_info = {
.tx_threshold = 8,
.rx_threshold = 8,
.dma_burst_size = 8,
.timeout = 235,
- .cs_control = spi1control,
+ .gpio_cs = 24,
};
static struct pxa2xx_spi_chip cc2420_info = {
@@ -482,7 +469,7 @@ static struct pxa2xx_spi_chip cc2420_info = {
.rx_threshold = 8,
.dma_burst_size = 8,
.timeout = 235,
- .cs_control = spi3control,
+ .gpio_cs = 39,
};
static struct spi_board_info spi_board_info[] __initdata = {
@@ -538,8 +525,6 @@ static void __init imote2_init(void)
/* SPI chip select directions - all other directions should
* be handled by drivers.*/
gpio_direction_output(37, 0);
- gpio_direction_output(24, 0);
- gpio_direction_output(39, 0);
platform_add_devices(imote2_devices, ARRAY_SIZE(imote2_devices));
diff --git a/arch/arm/mach-pxa/include/mach/audio.h b/arch/arm/mach-pxa/include/mach/audio.h
index f82f96dd1053..16eb02552d5d 100644
--- a/arch/arm/mach-pxa/include/mach/audio.h
+++ b/arch/arm/mach-pxa/include/mach/audio.h
@@ -4,12 +4,22 @@
#include <sound/core.h>
#include <sound/pcm.h>
+/*
+ * @reset_gpio: AC97 reset gpio (normally gpio113 or gpio95)
+ * a -1 value means no gpio will be used for reset
+
+ * reset_gpio should only be specified for pxa27x CPUs where a silicon
+ * bug prevents correct operation of the reset line. If not specified,
+ * the default behaviour on these CPUs is to consider gpio 113 as the
+ * AC97 reset line, which is the default on most boards.
+ */
typedef struct {
int (*startup)(struct snd_pcm_substream *, void *);
void (*shutdown)(struct snd_pcm_substream *, void *);
void (*suspend)(void *);
void (*resume)(void *);
void *priv;
+ int reset_gpio;
} pxa2xx_audio_ops_t;
extern void pxa_set_ac97_info(pxa2xx_audio_ops_t *ops);
diff --git a/arch/arm/mach-pxa/include/mach/colibri.h b/arch/arm/mach-pxa/include/mach/colibri.h
index 90230c6f9925..a88d7caff0d1 100644
--- a/arch/arm/mach-pxa/include/mach/colibri.h
+++ b/arch/arm/mach-pxa/include/mach/colibri.h
@@ -10,13 +10,13 @@
#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
extern void colibri_pxa3xx_init_mmc(mfp_cfg_t *pins, int len, int detect_pin);
#else
-static inline void colibri_pxa3xx_init_mmc(mfp_cfg_t *, int, int) {}
+static inline void colibri_pxa3xx_init_mmc(mfp_cfg_t *pins, int len, int detect_pin) {}
#endif
#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
extern void colibri_pxa3xx_init_lcd(int bl_pin);
#else
-static inline void colibri_pxa3xx_init_lcd(int) {}
+static inline void colibri_pxa3xx_init_lcd(int bl_pin) {}
#endif
#if defined(CONFIG_AX88796)
diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h
index 32bb4a2eb7f1..ebf38bbb347f 100644
--- a/arch/arm/mach-pxa/include/mach/irqs.h
+++ b/arch/arm/mach-pxa/include/mach/irqs.h
@@ -91,13 +91,21 @@
#define IRQ_TO_GPIO(i) (((i) < IRQ_GPIO(2)) ? ((i) - IRQ_GPIO0) : IRQ_TO_GPIO_2_x(i))
/*
- * The next 16 interrupts are for board specific purposes. Since
+ * The following interrupts are for board specific purposes. Since
* the kernel can only run on one machine at a time, we can re-use
- * these. If you need more, increase IRQ_BOARD_END, but keep it
- * within sensible limits.
+ * these. There will be 16 IRQs by default. If it is not enough,
+ * IRQ_BOARD_END is allowed be customized for each board, but keep
+ * the numbers within sensible limits and in descending order, so
+ * when multiple config options are selected, the maximum will be
+ * used.
*/
#define IRQ_BOARD_START (PXA_GPIO_IRQ_BASE + PXA_GPIO_IRQ_NUM)
+
+#if defined(CONFIG_MACH_ZYLONITE)
+#define IRQ_BOARD_END (IRQ_BOARD_START + 32)
+#else
#define IRQ_BOARD_END (IRQ_BOARD_START + 16)
+#endif
#define IRQ_SA1111_START (IRQ_BOARD_END)
#define IRQ_GPAIN0 (IRQ_BOARD_END + 0)
@@ -188,8 +196,6 @@
#define NR_IRQS (IRQ_LOCOMO_SPI_TEND + 1)
#elif defined(CONFIG_PXA_HAVE_BOARD_IRQS)
#define NR_IRQS (IRQ_BOARD_END)
-#elif defined(CONFIG_MACH_ZYLONITE)
-#define NR_IRQS (IRQ_BOARD_START + 32)
#else
#define NR_IRQS (IRQ_BOARD_START)
#endif
diff --git a/arch/arm/mach-pxa/include/mach/palmasoc.h b/arch/arm/mach-pxa/include/mach/palmasoc.h
index 6c4b1f7de20a..58afb30d5298 100644
--- a/arch/arm/mach-pxa/include/mach/palmasoc.h
+++ b/arch/arm/mach-pxa/include/mach/palmasoc.h
@@ -1,13 +1,8 @@
#ifndef _INCLUDE_PALMASOC_H_
#define _INCLUDE_PALMASOC_H_
+
struct palm27x_asoc_info {
int jack_gpio;
};
-#ifdef CONFIG_SND_PXA2XX_SOC_PALM27X
-void __init palm27x_asoc_set_pdata(struct palm27x_asoc_info *data);
-#else
-static inline void palm27x_asoc_set_pdata(struct palm27x_asoc_info *data) {}
-#endif
-
#endif
diff --git a/arch/arm/mach-pxa/include/mach/palmt5.h b/arch/arm/mach-pxa/include/mach/palmt5.h
index 052bfe788ada..d15662aba008 100644
--- a/arch/arm/mach-pxa/include/mach/palmt5.h
+++ b/arch/arm/mach-pxa/include/mach/palmt5.h
@@ -37,7 +37,6 @@
/* USB */
#define GPIO_NR_PALMT5_USB_DETECT_N 15
-#define GPIO_NR_PALMT5_USB_POWER 95
#define GPIO_NR_PALMT5_USB_PULLUP 93
/* LCD/BACKLIGHT */
diff --git a/arch/arm/mach-pxa/include/mach/palmtx.h b/arch/arm/mach-pxa/include/mach/palmtx.h
index 9f7d62fb4cbb..e74082c872e1 100644
--- a/arch/arm/mach-pxa/include/mach/palmtx.h
+++ b/arch/arm/mach-pxa/include/mach/palmtx.h
@@ -38,7 +38,6 @@
/* USB */
#define GPIO_NR_PALMTX_USB_DETECT_N 13
-#define GPIO_NR_PALMTX_USB_POWER 95
#define GPIO_NR_PALMTX_USB_PULLUP 93
/* LCD/BACKLIGHT */
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index e13f6a81c223..94a32321ad43 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -43,7 +43,7 @@
#include <mach/pxafb.h>
#include <mach/ssp.h>
#include <mach/pxa2xx_spi.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include <mach/pxa27x_keypad.h>
#include <mach/pxa3xx_nand.h>
#include <mach/littleton.h>
@@ -179,15 +179,10 @@ static struct pxa2xx_spi_master littleton_spi_info = {
.num_chipselect = 1,
};
-static void littleton_tdo24m_cs(u32 cmd)
-{
- gpio_set_value(LITTLETON_GPIO_LCD_CS, !(cmd == PXA2XX_CS_ASSERT));
-}
-
static struct pxa2xx_spi_chip littleton_tdo24m_chip = {
.rx_threshold = 1,
.tx_threshold = 1,
- .cs_control = littleton_tdo24m_cs,
+ .gpio_cs = LITTLETON_GPIO_LCD_CS,
};
static struct spi_board_info littleton_spi_devices[] __initdata = {
@@ -202,16 +197,6 @@ static struct spi_board_info littleton_spi_devices[] __initdata = {
static void __init littleton_init_spi(void)
{
- int err;
-
- err = gpio_request(LITTLETON_GPIO_LCD_CS, "LCD_CS");
- if (err) {
- pr_warning("failed to request GPIO for LCS CS\n");
- return;
- }
-
- gpio_direction_output(LITTLETON_GPIO_LCD_CS, 1);
-
pxa2xx_set_spi_info(2, &littleton_spi_info);
spi_register_board_info(ARRAY_AND_SIZE(littleton_spi_devices));
}
@@ -334,6 +319,11 @@ static struct led_info littleton_da9034_leds[] = {
},
};
+static struct da9034_touch_pdata littleton_da9034_touch = {
+ .x_inverted = 1,
+ .interval_ms = 20,
+};
+
static struct da903x_subdev_info littleton_da9034_subdevs[] = {
{
.name = "da903x-led",
@@ -350,6 +340,10 @@ static struct da903x_subdev_info littleton_da9034_subdevs[] = {
}, {
.name = "da903x-backlight",
.id = DA9034_ID_WLED,
+ }, {
+ .name = "da9034-touch",
+ .id = DA9034_ID_TOUCH,
+ .platform_data = &littleton_da9034_touch,
},
};
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index c899bbd94dc0..34046c8bfaf5 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -36,7 +36,7 @@
#include <mach/pxa27x.h>
#include <mach/magician.h>
#include <mach/pxafb.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include <mach/mmc.h>
#include <mach/irda.h>
#include <mach/ohci.h>
@@ -745,6 +745,14 @@ static struct platform_device strataflash = {
};
/*
+ * I2C
+ */
+
+static struct i2c_pxa_platform_data i2c_info = {
+ .fast_mode = 1,
+};
+
+/*
* Platform devices
*/
@@ -779,7 +787,7 @@ static void __init magician_init(void)
pxa_set_ficp_info(&magician_ficp_info);
}
pxa27x_set_i2c_power_info(NULL);
- pxa_set_i2c_info(NULL);
+ pxa_set_i2c_info(&i2c_info);
pxa_set_mci_info(&magician_mci_info);
pxa_set_ohci_info(&magician_ohci_info);
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index a6c8429e975f..f4dabf0273ca 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -46,7 +46,7 @@
#include <mach/mainstone.h>
#include <mach/audio.h>
#include <mach/pxafb.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include <mach/mmc.h>
#include <mach/irda.h>
#include <mach/ohci.h>
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index 9203b069b35c..804c25c4a064 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -48,7 +48,7 @@
#include <mach/mmc.h>
#include <mach/udc.h>
#include <mach/pxa27x-udc.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include <mach/camera.h>
#include <mach/audio.h>
#include <media/soc_camera.h>
@@ -742,6 +742,10 @@ struct i2c_pxa_platform_data i2c_pdata = {
.fast_mode = 1,
};
+static pxa2xx_audio_ops_t mioa701_ac97_info = {
+ .reset_gpio = 95,
+};
+
/*
* Mio global
*/
@@ -815,7 +819,7 @@ static void __init mioa701_machine_init(void)
pxa_set_keypad_info(&mioa701_keypad_info);
wm97xx_bat_set_pdata(&mioa701_battery_data);
pxa_set_udc_info(&mioa701_udc_info);
- pxa_set_ac97_info(NULL);
+ pxa_set_ac97_info(&mioa701_ac97_info);
pm_power_off = mioa701_poweroff;
arm_pm_restart = mioa701_restart;
platform_add_devices(devices, ARRAY_SIZE(devices));
diff --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c
index ecf5910e39d7..1cec1806f002 100644
--- a/arch/arm/mach-pxa/palmld.c
+++ b/arch/arm/mach-pxa/palmld.c
@@ -477,10 +477,22 @@ static struct wm97xx_batt_info wm97xx_batt_pdata = {
/******************************************************************************
* aSoC audio
******************************************************************************/
-static struct palm27x_asoc_info palm27x_asoc_pdata = {
+static struct palm27x_asoc_info palmld_asoc_pdata = {
.jack_gpio = GPIO_NR_PALMLD_EARPHONE_DETECT,
};
+static pxa2xx_audio_ops_t palmld_ac97_pdata = {
+ .reset_gpio = 95,
+};
+
+static struct platform_device palmld_asoc = {
+ .name = "palm27x-asoc",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmld_asoc_pdata,
+ },
+};
+
/******************************************************************************
* Framebuffer
******************************************************************************/
@@ -544,6 +556,7 @@ static struct platform_device *devices[] __initdata = {
&palmld_backlight,
&palmld_leds,
&power_supply,
+ &palmld_asoc,
};
static struct map_desc palmld_io_desc[] __initdata = {
@@ -573,11 +586,10 @@ static void __init palmld_init(void)
set_pxa_fb_info(&palmld_lcd_screen);
pxa_set_mci_info(&palmld_mci_platform_data);
- pxa_set_ac97_info(NULL);
+ pxa_set_ac97_info(&palmld_ac97_pdata);
pxa_set_ficp_info(&palmld_ficp_platform_data);
pxa_set_keypad_info(&palmld_keypad_platform_data);
wm97xx_bat_set_pdata(&wm97xx_batt_pdata);
- palm27x_asoc_set_pdata(&palm27x_asoc_pdata);
platform_add_devices(devices, ARRAY_SIZE(devices));
}
diff --git a/arch/arm/mach-pxa/palmt5.c b/arch/arm/mach-pxa/palmt5.c
index 0680f1a575a3..1a1d8208b73d 100644
--- a/arch/arm/mach-pxa/palmt5.c
+++ b/arch/arm/mach-pxa/palmt5.c
@@ -26,6 +26,7 @@
#include <linux/gpio.h>
#include <linux/wm97xx_batt.h>
#include <linux/power_supply.h>
+#include <linux/usb/gpio_vbus.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -64,6 +65,7 @@ static unsigned long palmt5_pin_config[] __initdata = {
GPIO29_AC97_SDATA_IN_0,
GPIO30_AC97_SDATA_OUT,
GPIO31_AC97_SYNC,
+ GPIO95_AC97_nRESET,
/* IrDA */
GPIO40_GPIO, /* ir disable */
@@ -72,7 +74,7 @@ static unsigned long palmt5_pin_config[] __initdata = {
/* USB */
GPIO15_GPIO, /* usb detect */
- GPIO95_GPIO, /* usb power */
+ GPIO93_GPIO, /* usb power */
/* MATRIX KEYPAD */
GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH,
@@ -341,11 +343,18 @@ static struct pxaficp_platform_data palmt5_ficp_platform_data = {
/******************************************************************************
* UDC
******************************************************************************/
-static struct pxa2xx_udc_mach_info palmt5_udc_info __initdata = {
+static struct gpio_vbus_mach_info palmt5_udc_info = {
.gpio_vbus = GPIO_NR_PALMT5_USB_DETECT_N,
.gpio_vbus_inverted = 1,
- .gpio_pullup = GPIO_NR_PALMT5_USB_POWER,
- .gpio_pullup_inverted = 0,
+ .gpio_pullup = GPIO_NR_PALMT5_USB_PULLUP,
+};
+
+static struct platform_device palmt5_gpio_vbus = {
+ .name = "gpio-vbus",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmt5_udc_info,
+ },
};
/******************************************************************************
@@ -419,10 +428,22 @@ static struct wm97xx_batt_info wm97xx_batt_pdata = {
/******************************************************************************
* aSoC audio
******************************************************************************/
-static struct palm27x_asoc_info palm27x_asoc_pdata = {
+static struct palm27x_asoc_info palmt5_asoc_pdata = {
.jack_gpio = GPIO_NR_PALMT5_EARPHONE_DETECT,
};
+static pxa2xx_audio_ops_t palmt5_ac97_pdata = {
+ .reset_gpio = 95,
+};
+
+static struct platform_device palmt5_asoc = {
+ .name = "palm27x-asoc",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmt5_asoc_pdata,
+ },
+};
+
/******************************************************************************
* Framebuffer
******************************************************************************/
@@ -485,14 +506,16 @@ static struct platform_device *devices[] __initdata = {
#endif
&palmt5_backlight,
&power_supply,
+ &palmt5_asoc,
+ &palmt5_gpio_vbus,
};
/* setup udc GPIOs initial state */
static void __init palmt5_udc_init(void)
{
- if (!gpio_request(GPIO_NR_PALMT5_USB_POWER, "UDC Vbus")) {
- gpio_direction_output(GPIO_NR_PALMT5_USB_POWER, 1);
- gpio_free(GPIO_NR_PALMT5_USB_POWER);
+ if (!gpio_request(GPIO_NR_PALMT5_USB_PULLUP, "UDC Vbus")) {
+ gpio_direction_output(GPIO_NR_PALMT5_USB_PULLUP, 1);
+ gpio_free(GPIO_NR_PALMT5_USB_PULLUP);
}
}
@@ -503,12 +526,10 @@ static void __init palmt5_init(void)
set_pxa_fb_info(&palmt5_lcd_screen);
pxa_set_mci_info(&palmt5_mci_platform_data);
palmt5_udc_init();
- pxa_set_udc_info(&palmt5_udc_info);
- pxa_set_ac97_info(NULL);
+ pxa_set_ac97_info(&palmt5_ac97_pdata);
pxa_set_ficp_info(&palmt5_ficp_platform_data);
pxa_set_keypad_info(&palmt5_keypad_platform_data);
wm97xx_bat_set_pdata(&wm97xx_batt_pdata);
- palm27x_asoc_set_pdata(&palm27x_asoc_pdata);
platform_add_devices(devices, ARRAY_SIZE(devices));
}
diff --git a/arch/arm/mach-pxa/palmte2.c b/arch/arm/mach-pxa/palmte2.c
index 43fcf2e86887..d823b09801df 100644
--- a/arch/arm/mach-pxa/palmte2.c
+++ b/arch/arm/mach-pxa/palmte2.c
@@ -25,6 +25,7 @@
#include <linux/gpio.h>
#include <linux/wm97xx_batt.h>
#include <linux/power_supply.h>
+#include <linux/usb/gpio_vbus.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -37,6 +38,7 @@
#include <mach/mfp-pxa25x.h>
#include <mach/irda.h>
#include <mach/udc.h>
+#include <mach/palmasoc.h>
#include "generic.h"
#include "devices.h"
@@ -107,6 +109,7 @@ static unsigned long palmte2_pin_config[] __initdata = {
GPIO1_RST, /* reset */
GPIO4_GPIO, /* Hotsync button */
GPIO9_GPIO, /* power detect */
+ GPIO15_GPIO, /* earphone detect */
GPIO37_GPIO, /* LCD power */
GPIO56_GPIO, /* Backlight power */
};
@@ -318,11 +321,18 @@ static struct pxaficp_platform_data palmte2_ficp_platform_data = {
/******************************************************************************
* UDC
******************************************************************************/
-static struct pxa2xx_udc_mach_info palmte2_udc_info __initdata = {
+static struct gpio_vbus_mach_info palmte2_udc_info = {
.gpio_vbus = GPIO_NR_PALMTE2_USB_DETECT_N,
.gpio_vbus_inverted = 1,
.gpio_pullup = GPIO_NR_PALMTE2_USB_PULLUP,
- .gpio_pullup_inverted = 0,
+};
+
+static struct platform_device palmte2_gpio_vbus = {
+ .name = "gpio-vbus",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmte2_udc_info,
+ },
};
/******************************************************************************
@@ -395,6 +405,21 @@ static struct wm97xx_batt_info wm97xx_batt_pdata = {
};
/******************************************************************************
+ * aSoC audio
+ ******************************************************************************/
+static struct palm27x_asoc_info palmte2_asoc_pdata = {
+ .jack_gpio = GPIO_NR_PALMTE2_EARPHONE_DETECT,
+};
+
+static struct platform_device palmte2_asoc = {
+ .name = "palm27x-asoc",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmte2_asoc_pdata,
+ },
+};
+
+/******************************************************************************
* Framebuffer
******************************************************************************/
static struct pxafb_mode_info palmte2_lcd_modes[] = {
@@ -429,6 +454,8 @@ static struct platform_device *devices[] __initdata = {
#endif
&palmte2_backlight,
&power_supply,
+ &palmte2_asoc,
+ &palmte2_gpio_vbus,
};
/* setup udc GPIOs initial state */
@@ -447,7 +474,6 @@ static void __init palmte2_init(void)
set_pxa_fb_info(&palmte2_lcd_screen);
pxa_set_mci_info(&palmte2_mci_platform_data);
palmte2_udc_init();
- pxa_set_udc_info(&palmte2_udc_info);
pxa_set_ac97_info(NULL);
pxa_set_ficp_info(&palmte2_ficp_platform_data);
wm97xx_bat_set_pdata(&wm97xx_batt_pdata);
diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c
index 59d0c1cba556..81da4396fb07 100644
--- a/arch/arm/mach-pxa/palmtx.c
+++ b/arch/arm/mach-pxa/palmtx.c
@@ -27,6 +27,7 @@
#include <linux/gpio.h>
#include <linux/wm97xx_batt.h>
#include <linux/power_supply.h>
+#include <linux/usb/gpio_vbus.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -40,6 +41,7 @@
#include <mach/irda.h>
#include <mach/pxa27x_keypad.h>
#include <mach/udc.h>
+#include <mach/palmasoc.h>
#include "generic.h"
#include "devices.h"
@@ -64,6 +66,7 @@ static unsigned long palmtx_pin_config[] __initdata = {
GPIO29_AC97_SDATA_IN_0,
GPIO30_AC97_SDATA_OUT,
GPIO31_AC97_SYNC,
+ GPIO95_AC97_nRESET,
/* IrDA */
GPIO40_GPIO, /* ir disable */
@@ -75,7 +78,7 @@ static unsigned long palmtx_pin_config[] __initdata = {
/* USB */
GPIO13_GPIO, /* usb detect */
- GPIO95_GPIO, /* usb power */
+ GPIO93_GPIO, /* usb power */
/* PCMCIA */
GPIO48_nPOE,
@@ -356,11 +359,18 @@ static struct pxaficp_platform_data palmtx_ficp_platform_data = {
/******************************************************************************
* UDC
******************************************************************************/
-static struct pxa2xx_udc_mach_info palmtx_udc_info __initdata = {
+static struct gpio_vbus_mach_info palmtx_udc_info = {
.gpio_vbus = GPIO_NR_PALMTX_USB_DETECT_N,
.gpio_vbus_inverted = 1,
- .gpio_pullup = GPIO_NR_PALMTX_USB_POWER,
- .gpio_pullup_inverted = 0,
+ .gpio_pullup = GPIO_NR_PALMTX_USB_PULLUP,
+};
+
+static struct platform_device palmtx_gpio_vbus = {
+ .name = "gpio-vbus",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmtx_udc_info,
+ },
};
/******************************************************************************
@@ -433,6 +443,25 @@ static struct wm97xx_batt_info wm97xx_batt_pdata = {
};
/******************************************************************************
+ * aSoC audio
+ ******************************************************************************/
+static struct palm27x_asoc_info palmtx_asoc_pdata = {
+ .jack_gpio = GPIO_NR_PALMTX_EARPHONE_DETECT,
+};
+
+static pxa2xx_audio_ops_t palmtx_ac97_pdata = {
+ .reset_gpio = 95,
+};
+
+static struct platform_device palmtx_asoc = {
+ .name = "palm27x-asoc",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmtx_asoc_pdata,
+ },
+};
+
+/******************************************************************************
* Framebuffer
******************************************************************************/
static struct pxafb_mode_info palmtx_lcd_modes[] = {
@@ -494,6 +523,8 @@ static struct platform_device *devices[] __initdata = {
#endif
&palmtx_backlight,
&power_supply,
+ &palmtx_asoc,
+ &palmtx_gpio_vbus,
};
static struct map_desc palmtx_io_desc[] __initdata = {
@@ -514,9 +545,9 @@ static void __init palmtx_map_io(void)
/* setup udc GPIOs initial state */
static void __init palmtx_udc_init(void)
{
- if (!gpio_request(GPIO_NR_PALMTX_USB_POWER, "UDC Vbus")) {
- gpio_direction_output(GPIO_NR_PALMTX_USB_POWER, 1);
- gpio_free(GPIO_NR_PALMTX_USB_POWER);
+ if (!gpio_request(GPIO_NR_PALMTX_USB_PULLUP, "UDC Vbus")) {
+ gpio_direction_output(GPIO_NR_PALMTX_USB_PULLUP, 1);
+ gpio_free(GPIO_NR_PALMTX_USB_PULLUP);
}
}
@@ -528,8 +559,7 @@ static void __init palmtx_init(void)
set_pxa_fb_info(&palmtx_lcd_screen);
pxa_set_mci_info(&palmtx_mci_platform_data);
palmtx_udc_init();
- pxa_set_udc_info(&palmtx_udc_info);
- pxa_set_ac97_info(NULL);
+ pxa_set_ac97_info(&palmtx_ac97_pdata);
pxa_set_ficp_info(&palmtx_ficp_platform_data);
pxa_set_keypad_info(&palmtx_keypad_platform_data);
wm97xx_bat_set_pdata(&wm97xx_batt_pdata);
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
index 6112740b4ae9..01791d74e08e 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -28,7 +28,7 @@
#include <media/soc_camera.h>
#include <asm/gpio.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include <mach/camera.h>
#include <asm/mach/map.h>
#include <mach/pxa27x.h>
@@ -377,15 +377,15 @@ struct pxacamera_platform_data pcm990_pxacamera_platform_data = {
#include <linux/i2c/pca953x.h>
static struct pca953x_platform_data pca9536_data = {
- .gpio_base = NR_BUILTIN_GPIO + 1,
+ .gpio_base = NR_BUILTIN_GPIO,
};
-static int gpio_bus_switch;
+static int gpio_bus_switch = -EINVAL;
static int pcm990_camera_set_bus_param(struct soc_camera_link *link,
- unsigned long flags)
+ unsigned long flags)
{
- if (gpio_bus_switch <= 0) {
+ if (gpio_bus_switch < 0) {
if (flags == SOCAM_DATAWIDTH_10)
return 0;
else
@@ -404,25 +404,34 @@ static unsigned long pcm990_camera_query_bus_param(struct soc_camera_link *link)
{
int ret;
- if (!gpio_bus_switch) {
- ret = gpio_request(NR_BUILTIN_GPIO + 1, "camera");
+ if (gpio_bus_switch < 0) {
+ ret = gpio_request(NR_BUILTIN_GPIO, "camera");
if (!ret) {
- gpio_bus_switch = NR_BUILTIN_GPIO + 1;
+ gpio_bus_switch = NR_BUILTIN_GPIO;
gpio_direction_output(gpio_bus_switch, 0);
- } else
- gpio_bus_switch = -EINVAL;
+ }
}
- if (gpio_bus_switch > 0)
+ if (gpio_bus_switch >= 0)
return SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_10;
else
return SOCAM_DATAWIDTH_10;
}
+static void pcm990_camera_free_bus(struct soc_camera_link *link)
+{
+ if (gpio_bus_switch < 0)
+ return;
+
+ gpio_free(gpio_bus_switch);
+ gpio_bus_switch = -EINVAL;
+}
+
static struct soc_camera_link iclink = {
.bus_id = 0, /* Must match with the camera ID above */
.query_bus_param = pcm990_camera_query_bus_param,
.set_bus_param = pcm990_camera_set_bus_param,
+ .free_bus = pcm990_camera_free_bus,
};
/* Board I2C devices. */
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 036bbde4d221..ac431ed10399 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -39,7 +39,7 @@
#include <mach/pxa25x.h>
#include <mach/mmc.h>
#include <mach/udc.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include <mach/irda.h>
#include <mach/poodle.h>
#include <mach/pxafb.h>
@@ -214,13 +214,8 @@ static struct ads7846_platform_data poodle_ads7846_info = {
.gpio_pendown = POODLE_GPIO_TP_INT,
};
-static void ads7846_cs(u32 command)
-{
- gpio_set_value(POODLE_GPIO_TP_CS, !(command == PXA2XX_CS_ASSERT));
-}
-
static struct pxa2xx_spi_chip poodle_ads7846_chip = {
- .cs_control = ads7846_cs,
+ .gpio_cs = POODLE_GPIO_TP_CS,
};
static struct spi_board_info poodle_spi_devices[] = {
@@ -236,14 +231,6 @@ static struct spi_board_info poodle_spi_devices[] = {
static void __init poodle_init_spi(void)
{
- int err;
-
- err = gpio_request(POODLE_GPIO_TP_CS, "ADS7846_CS");
- if (err)
- return;
-
- gpio_direction_output(POODLE_GPIO_TP_CS, 1);
-
pxa2xx_set_spi_info(1, &poodle_spi_info);
spi_register_board_info(ARRAY_AND_SIZE(poodle_spi_devices));
}
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index a425ec71e657..c54ad8b3343c 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -27,7 +27,7 @@
#include <mach/ohci.h>
#include <mach/pm.h>
#include <mach/dma.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include "generic.h"
#include "devices.h"
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index b02d4544dc95..6f678d93bf4e 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -30,7 +30,7 @@
#include <mach/pm.h>
#include <mach/dma.h>
#include <mach/ssp.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include "generic.h"
#include "devices.h"
@@ -552,7 +552,7 @@ void __init pxa3xx_set_i2c_power_info(struct i2c_pxa_platform_data *info)
}
static struct platform_device *devices[] __initdata = {
-/* &pxa_device_udc, The UDC driver is PXA25x only */
+ &pxa27x_device_udc,
&pxa_device_ffuart,
&pxa_device_btuart,
&pxa_device_stuart,
diff --git a/arch/arm/mach-pxa/saar.c b/arch/arm/mach-pxa/saar.c
index ff8239991430..8241a63ea589 100644
--- a/arch/arm/mach-pxa/saar.c
+++ b/arch/arm/mach-pxa/saar.c
@@ -27,7 +27,7 @@
#include <asm/mach/arch.h>
#include <mach/pxa930.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include <mach/pxafb.h>
#include "devices.h"
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 8c61ddac119e..660ea4a75d8b 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -47,7 +47,7 @@
#include <mach/pxa27x.h>
#include <mach/pxa27x-udc.h>
#include <mach/reset.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include <mach/irda.h>
#include <mach/mmc.h>
#include <mach/ohci.h>
@@ -299,21 +299,26 @@ static struct pxa2xx_spi_master spitz_spi_info = {
.num_chipselect = 3,
};
+static void spitz_wait_for_hsync(void)
+{
+ while (gpio_get_value(SPITZ_GPIO_HSYNC))
+ cpu_relax();
+
+ while (!gpio_get_value(SPITZ_GPIO_HSYNC))
+ cpu_relax();
+}
+
static struct ads7846_platform_data spitz_ads7846_info = {
.model = 7846,
.vref_delay_usecs = 100,
.x_plate_ohms = 419,
.y_plate_ohms = 486,
.gpio_pendown = SPITZ_GPIO_TP_INT,
+ .wait_for_sync = spitz_wait_for_hsync,
};
-static void spitz_ads7846_cs(u32 command)
-{
- gpio_set_value(SPITZ_GPIO_ADS7846_CS, !(command == PXA2XX_CS_ASSERT));
-}
-
static struct pxa2xx_spi_chip spitz_ads7846_chip = {
- .cs_control = spitz_ads7846_cs,
+ .gpio_cs = SPITZ_GPIO_ADS7846_CS,
};
static void spitz_bl_kick_battery(void)
@@ -337,22 +342,12 @@ static struct corgi_lcd_platform_data spitz_lcdcon_info = {
.kick_battery = spitz_bl_kick_battery,
};
-static void spitz_lcdcon_cs(u32 command)
-{
- gpio_set_value(SPITZ_GPIO_LCDCON_CS, !(command == PXA2XX_CS_ASSERT));
-}
-
static struct pxa2xx_spi_chip spitz_lcdcon_chip = {
- .cs_control = spitz_lcdcon_cs,
+ .gpio_cs = SPITZ_GPIO_LCDCON_CS,
};
-static void spitz_max1111_cs(u32 command)
-{
- gpio_set_value(SPITZ_GPIO_MAX1111_CS, !(command == PXA2XX_CS_ASSERT));
-}
-
static struct pxa2xx_spi_chip spitz_max1111_chip = {
- .cs_control = spitz_max1111_cs,
+ .gpio_cs = SPITZ_GPIO_MAX1111_CS,
};
static struct spi_board_info spitz_spi_devices[] = {
@@ -382,30 +377,6 @@ static struct spi_board_info spitz_spi_devices[] = {
static void __init spitz_init_spi(void)
{
- int err;
-
- err = gpio_request(SPITZ_GPIO_ADS7846_CS, "ADS7846_CS");
- if (err)
- return;
-
- err = gpio_request(SPITZ_GPIO_LCDCON_CS, "LCDCON_CS");
- if (err)
- goto err_free_1;
-
- err = gpio_request(SPITZ_GPIO_MAX1111_CS, "MAX1111_CS");
- if (err)
- goto err_free_2;
-
- err = gpio_direction_output(SPITZ_GPIO_ADS7846_CS, 1);
- if (err)
- goto err_free_3;
- err = gpio_direction_output(SPITZ_GPIO_LCDCON_CS, 1);
- if (err)
- goto err_free_3;
- err = gpio_direction_output(SPITZ_GPIO_MAX1111_CS, 1);
- if (err)
- goto err_free_3;
-
if (machine_is_akita()) {
spitz_lcdcon_info.gpio_backlight_cont = AKITA_GPIO_BACKLIGHT_CONT;
spitz_lcdcon_info.gpio_backlight_on = AKITA_GPIO_BACKLIGHT_ON;
@@ -413,14 +384,6 @@ static void __init spitz_init_spi(void)
pxa2xx_set_spi_info(2, &spitz_spi_info);
spi_register_board_info(ARRAY_AND_SIZE(spitz_spi_devices));
- return;
-
-err_free_3:
- gpio_free(SPITZ_GPIO_MAX1111_CS);
-err_free_2:
- gpio_free(SPITZ_GPIO_LCDCON_CS);
-err_free_1:
- gpio_free(SPITZ_GPIO_ADS7846_CS);
}
#else
static inline void spitz_init_spi(void) {}
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 8eb3830fbb0b..750c448db672 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -125,7 +125,7 @@ static struct clock_event_device ckevt_pxa_osmr0 = {
.set_mode = pxa_osmr0_set_mode,
};
-static cycle_t pxa_read_oscr(void)
+static cycle_t pxa_read_oscr(struct clocksource *cs)
{
return OSCR;
}
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index afac5b6d3d78..196eebf06279 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -40,7 +40,7 @@
#include <mach/pxa25x.h>
#include <mach/reset.h>
#include <mach/irda.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include <mach/mmc.h>
#include <mach/udc.h>
#include <mach/tosa_bt.h>
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index f79c9cb70ae4..825f540176d2 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -47,7 +47,7 @@
#include <mach/mmc.h>
#include <mach/irda.h>
#include <mach/ohci.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include "generic.h"
#include "devices.h"
diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c
index 0e65344e9f53..af7c303171d7 100644
--- a/arch/arm/mach-pxa/viper.c
+++ b/arch/arm/mach-pxa/viper.c
@@ -45,7 +45,7 @@
#include <mach/pxa25x.h>
#include <mach/audio.h>
#include <mach/pxafb.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include <mach/viper.h>
#include <asm/setup.h>
diff --git a/arch/arm/mach-pxa/zylonite_pxa300.c b/arch/arm/mach-pxa/zylonite_pxa300.c
index c1f73205d078..cefd1c0a854a 100644
--- a/arch/arm/mach-pxa/zylonite_pxa300.c
+++ b/arch/arm/mach-pxa/zylonite_pxa300.c
@@ -21,7 +21,7 @@
#include <linux/gpio.h>
#include <mach/pxa300.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include <mach/zylonite.h>
#include "generic.h"
@@ -72,6 +72,7 @@ static mfp_cfg_t common_mfp_cfg[] __initdata = {
GPIO25_AC97_SDATA_IN_0,
GPIO27_AC97_SDATA_OUT,
GPIO28_AC97_SYNC,
+ GPIO17_GPIO, /* SDATA_IN_1 but unused - configure to GPIO */
/* SSP3 */
GPIO91_SSP3_SCLK,
@@ -126,6 +127,10 @@ static mfp_cfg_t common_mfp_cfg[] __initdata = {
/* Standard I2C */
GPIO21_I2C_SCL,
GPIO22_I2C_SDA,
+
+ /* GPIO */
+ GPIO18_GPIO, /* GPIO Expander #0 INT_N */
+ GPIO19_GPIO, /* GPIO Expander #1 INT_N */
};
static mfp_cfg_t pxa300_mfp_cfg[] __initdata = {
diff --git a/arch/arm/mach-pxa/zylonite_pxa320.c b/arch/arm/mach-pxa/zylonite_pxa320.c
index 4e1c488c6906..cc5a22833605 100644
--- a/arch/arm/mach-pxa/zylonite_pxa320.c
+++ b/arch/arm/mach-pxa/zylonite_pxa320.c
@@ -68,6 +68,7 @@ static mfp_cfg_t mfp_cfg[] __initdata = {
GPIO38_AC97_SYNC,
GPIO39_AC97_BITCLK,
GPIO40_AC97_nACRESET,
+ GPIO36_GPIO, /* SDATA_IN_1 but unused - configure to GPIO */
/* SSP3 */
GPIO89_SSP3_SCLK,
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 9ab947c14f26..942e1a7eb9b2 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -715,7 +715,7 @@ static struct irqaction realview_timer_irq = {
.handler = realview_timer_interrupt,
};
-static cycle_t realview_get_cycles(void)
+static cycle_t realview_get_cycles(struct clocksource *cs)
{
return ~readl(timer3_va_base + TIMER_VALUE);
}
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index 63a30d1dd425..41bb65d5b91f 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -59,6 +59,7 @@ config ARCH_H1940
bool "IPAQ H1940"
select CPU_S3C2410
select PM_H1940 if PM
+ select S3C_DEV_USB_HOST
help
Say Y here if you are using the HP IPAQ H1940
@@ -70,6 +71,7 @@ config PM_H1940
config MACH_N30
bool "Acer N30 family"
select CPU_S3C2410
+ select S3C_DEV_USB_HOST
help
Say Y here if you want suppt for the Acer N30, Acer N35,
Navman PiN570, Yakumo AlphaX or Airis NC05 PDAs.
@@ -82,6 +84,7 @@ config ARCH_BAST
select MACH_BAST_IDE
select S3C24XX_DCLK
select ISA
+ select S3C_DEV_USB_HOST
help
Say Y here if you are using the Simtec Electronics EB2410ITX
development board (also known as BAST)
@@ -89,6 +92,7 @@ config ARCH_BAST
config MACH_OTOM
bool "NexVision OTOM Board"
select CPU_S3C2410
+ select S3C_DEV_USB_HOST
help
Say Y here if you are using the Nex Vision OTOM board
@@ -96,6 +100,7 @@ config MACH_AML_M5900
bool "AML M5900 Series"
select CPU_S3C2410
select PM_SIMTEC if PM
+ select S3C_DEV_USB_HOST
help
Say Y here if you are using the American Microsystems M5900 Series
<http://www.amltd.com>
@@ -111,6 +116,7 @@ config BAST_PC104_IRQ
config MACH_TCT_HAMMER
bool "TCT Hammer Board"
select CPU_S3C2410
+ select S3C_DEV_USB_HOST
help
Say Y here if you are using the TinCanTools Hammer Board
<http://www.tincantools.com>
@@ -122,12 +128,14 @@ config MACH_VR1000
select SIMTEC_NOR
select MACH_BAST_IDE
select CPU_S3C2410
+ select S3C_DEV_USB_HOST
help
Say Y here if you are using the Thorcom VR1000 board.
config MACH_QT2410
bool "QT2410"
select CPU_S3C2410
+ select S3C_DEV_USB_HOST
help
Say Y here if you are using the Armzone QT2410
diff --git a/arch/arm/mach-s3c2410/include/mach/map.h b/arch/arm/mach-s3c2410/include/mach/map.h
index 255fdfeaf957..e99b212cb1ca 100644
--- a/arch/arm/mach-s3c2410/include/mach/map.h
+++ b/arch/arm/mach-s3c2410/include/mach/map.h
@@ -84,7 +84,6 @@
#define S3C24XX_PA_IRQ S3C2410_PA_IRQ
#define S3C24XX_PA_MEMCTRL S3C2410_PA_MEMCTRL
-#define S3C24XX_PA_USBHOST S3C2410_PA_USBHOST
#define S3C24XX_PA_DMA S3C2410_PA_DMA
#define S3C24XX_PA_CLKPWR S3C2410_PA_CLKPWR
#define S3C24XX_PA_LCD S3C2410_PA_LCD
@@ -102,6 +101,7 @@
#define S3C_PA_IIC S3C2410_PA_IIC
#define S3C_PA_UART S3C24XX_PA_UART
+#define S3C_PA_USBHOST S3C2410_PA_USBHOST
#define S3C_PA_HSMMC0 S3C2443_PA_HSMMC
#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s3c2412/Kconfig b/arch/arm/mach-s3c2412/Kconfig
index ca99564ae4b5..63586ffd0ae7 100644
--- a/arch/arm/mach-s3c2412/Kconfig
+++ b/arch/arm/mach-s3c2412/Kconfig
@@ -38,6 +38,7 @@ menu "S3C2412 Machines"
config MACH_JIVE
bool "Logitech Jive"
select CPU_S3C2412
+ select S3C_DEV_USB_HOST
help
Say Y here if you are using the Logitech Jive.
@@ -50,6 +51,7 @@ config MACH_SMDK2413
select CPU_S3C2412
select MACH_S3C2413
select MACH_SMDK
+ select S3C_DEV_USB_HOST
help
Say Y here if you are using an SMDK2413
@@ -72,6 +74,7 @@ config MACH_SMDK2412
config MACH_VSTMS
bool "VMSTMS"
select CPU_S3C2412
+ select S3C_DEV_USB_HOST
help
Say Y here if you are using an VSTMS board
diff --git a/arch/arm/mach-s3c2412/mach-jive.c b/arch/arm/mach-s3c2412/mach-jive.c
index 332bd3263eaf..8f0d37d43b43 100644
--- a/arch/arm/mach-s3c2412/mach-jive.c
+++ b/arch/arm/mach-s3c2412/mach-jive.c
@@ -52,7 +52,6 @@
#include <plat/cpu.h>
#include <plat/pm.h>
#include <plat/udc.h>
-#include <plat/iic.h>
static struct map_desc jive_iodesc[] __initdata = {
};
@@ -278,7 +277,7 @@ __setup("mtdset=", jive_mtdset);
#define LCD_HTOT (LCD_HSYNC + LCD_LEFT_MARGIN + LCD_XRES + LCD_RIGHT_MARGIN)
#define LCD_VTOT (LCD_VSYNC + LCD_LOWER_MARGIN + LCD_YRES + LCD_UPPER_MARGIN)
-struct s3c2410fb_display jive_vgg2432a4_display[] = {
+static struct s3c2410fb_display jive_vgg2432a4_display[] = {
[0] = {
.width = LCD_XRES,
.height = LCD_YRES,
@@ -311,7 +310,7 @@ struct s3c2410fb_display jive_vgg2432a4_display[] = {
#define S3C2410_GPCCON_MASK(x) (3 << ((x) * 2))
#define S3C2410_GPDCON_MASK(x) (3 << ((x) * 2))
-struct s3c2410fb_mach_info jive_lcd_config = {
+static struct s3c2410fb_mach_info jive_lcd_config = {
.displays = jive_vgg2432a4_display,
.num_displays = ARRAY_SIZE(jive_vgg2432a4_display),
.default_display = 0,
diff --git a/arch/arm/mach-s3c2412/pm.c b/arch/arm/mach-s3c2412/pm.c
index c9cfe40e21f6..a7417c479ffe 100644
--- a/arch/arm/mach-s3c2412/pm.c
+++ b/arch/arm/mach-s3c2412/pm.c
@@ -21,6 +21,7 @@
#include <linux/io.h>
#include <mach/hardware.h>
+#include <asm/cacheflush.h>
#include <asm/irq.h>
#include <mach/regs-power.h>
@@ -39,6 +40,8 @@ static void s3c2412_cpu_suspend(void)
{
unsigned long tmp;
+ flush_cache_all();
+
/* set our standby method to sleep */
tmp = __raw_readl(S3C2412_PWRCFG);
diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig
index cde5ae9a4340..5df73cbf2b40 100644
--- a/arch/arm/mach-s3c2440/Kconfig
+++ b/arch/arm/mach-s3c2440/Kconfig
@@ -33,6 +33,7 @@ config MACH_ANUBIS
select PM_SIMTEC if PM
select HAVE_PATA_PLATFORM
select S3C24XX_GPIO_EXTRA64
+ select S3C_DEV_USB_HOST
help
Say Y here if you are using the Simtec Electronics ANUBIS
development system
@@ -43,6 +44,7 @@ config MACH_OSIRIS
select S3C24XX_DCLK
select PM_SIMTEC if PM
select S3C24XX_GPIO_EXTRA128
+ select S3C_DEV_USB_HOST
help
Say Y here if you are using the Simtec IM2440D20 module, also
known as the Osiris.
@@ -58,12 +60,14 @@ config ARCH_S3C2440
bool "SMDK2440"
select CPU_S3C2440
select MACH_SMDK
+ select S3C_DEV_USB_HOST
help
Say Y here if you are using the SMDK2440.
config MACH_NEXCODER_2440
bool "NexVision NEXCODER 2440 Light Board"
select CPU_S3C2440
+ select S3C_DEV_USB_HOST
help
Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board
@@ -76,6 +80,7 @@ config SMDK2440_CPU2440
config MACH_AT2440EVB
bool "Avantech AT2440EVB development board"
select CPU_S3C2440
+ select S3C_DEV_USB_HOST
help
Say Y here if you are using the AT2440EVB development board
diff --git a/arch/arm/mach-s3c2440/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c
index b05d56e230a1..9c6abf9fb540 100644
--- a/arch/arm/mach-s3c2440/mach-anubis.c
+++ b/arch/arm/mach-s3c2440/mach-anubis.c
@@ -243,7 +243,7 @@ static struct s3c2410_platform_nand anubis_nand_info = {
/* IDE channels */
-struct pata_platform_info anubis_ide_platdata = {
+static struct pata_platform_info anubis_ide_platdata = {
.ioport_shift = 5,
};
diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c
index 41a00f57e5da..c8a46685ce38 100644
--- a/arch/arm/mach-s3c2440/mach-osiris.c
+++ b/arch/arm/mach-s3c2440/mach-osiris.c
@@ -413,7 +413,6 @@ MACHINE_START(OSIRIS, "Simtec-OSIRIS")
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = osiris_map_io,
- .init_machine = osiris_init,
.init_irq = s3c24xx_init_irq,
.init_machine = osiris_init,
.timer = &s3c24xx_timer,
diff --git a/arch/arm/mach-s3c6400/include/mach/map.h b/arch/arm/mach-s3c6400/include/mach/map.h
index baf1c0f1ea5a..46acb9259f41 100644
--- a/arch/arm/mach-s3c6400/include/mach/map.h
+++ b/arch/arm/mach-s3c6400/include/mach/map.h
@@ -40,6 +40,8 @@
#define S3C64XX_PA_FB (0x77100000)
#define S3C64XX_PA_SYSCON (0x7E00F000)
+#define S3C64XX_PA_IIS0 (0x7F002000)
+#define S3C64XX_PA_IIS1 (0x7F003000)
#define S3C64XX_PA_TIMER (0x7F006000)
#define S3C64XX_PA_IIC0 (0x7F004000)
#define S3C64XX_PA_IIC1 (0x7F00F000)
@@ -55,6 +57,8 @@
#define S3C64XX_PA_MODEM (0x74108000)
#define S3C64XX_VA_MODEM S3C_ADDR(0x00600000)
+#define S3C64XX_PA_USBHOST (0x74300000)
+
/* place VICs close together */
#define S3C_VA_VIC0 (S3C_VA_IRQ + 0x00)
#define S3C_VA_VIC1 (S3C_VA_IRQ + 0x10000)
@@ -67,5 +71,6 @@
#define S3C_PA_IIC S3C64XX_PA_IIC0
#define S3C_PA_IIC1 S3C64XX_PA_IIC1
#define S3C_PA_FB S3C64XX_PA_FB
+#define S3C_PA_USBHOST S3C64XX_PA_USBHOST
#endif /* __ASM_ARCH_6400_MAP_H */
diff --git a/arch/arm/mach-s3c6400/include/mach/regs-clock.h b/arch/arm/mach-s3c6400/include/mach/regs-clock.h
new file mode 100644
index 000000000000..a6c7f4eb3a1b
--- /dev/null
+++ b/arch/arm/mach-s3c6400/include/mach/regs-clock.h
@@ -0,0 +1,16 @@
+/* linux/arch/arm/mach-s3c6400/include/mach/regs-clock.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C64XX - clock register compatibility with s3c24xx
+ *
+ * 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 <plat/regs-clock.h>
+
diff --git a/arch/arm/mach-s3c6410/Kconfig b/arch/arm/mach-s3c6410/Kconfig
index 1d5010070027..0c8df9797e55 100644
--- a/arch/arm/mach-s3c6410/Kconfig
+++ b/arch/arm/mach-s3c6410/Kconfig
@@ -26,6 +26,7 @@ config MACH_SMDK6410
select S3C_DEV_HSMMC1
select S3C_DEV_I2C1
select S3C_DEV_FB
+ select S3C_DEV_USB_HOST
select S3C6410_SETUP_SDHCI
select S3C64XX_SETUP_I2C1
select S3C64XX_SETUP_FB_24BPP
diff --git a/arch/arm/mach-s3c6410/mach-smdk6410.c b/arch/arm/mach-s3c6410/mach-smdk6410.c
index 25f7935576f8..678b728fee12 100644
--- a/arch/arm/mach-s3c6410/mach-smdk6410.c
+++ b/arch/arm/mach-s3c6410/mach-smdk6410.c
@@ -141,6 +141,7 @@ static struct platform_device *smdk6410_devices[] __initdata = {
&s3c_device_i2c0,
&s3c_device_i2c1,
&s3c_device_fb,
+ &s3c_device_usb,
&smdk6410_lcd_powerdev,
};
@@ -166,6 +167,10 @@ static void __init smdk6410_machine_init(void)
s3c_i2c1_set_platdata(NULL);
s3c_fb_set_platdata(&smdk6410_lcd_pdata);
+ gpio_request(S3C64XX_GPN(5), "LCD power");
+ gpio_request(S3C64XX_GPF(13), "LCD power");
+ gpio_request(S3C64XX_GPF(15), "LCD power");
+
i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c
index 0cd52692d2f7..1f940df0e5af 100644
--- a/arch/arm/mach-sa1100/lart.c
+++ b/arch/arm/mach-sa1100/lart.c
@@ -9,6 +9,7 @@
#include <mach/hardware.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
+#include <asm/page.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
diff --git a/arch/arm/mach-stmp378x/Makefile b/arch/arm/mach-stmp378x/Makefile
new file mode 100644
index 000000000000..d156f76b379f
--- /dev/null
+++ b/arch/arm/mach-stmp378x/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_ARCH_STMP378X) += stmp378x.o
+obj-$(CONFIG_MACH_STMP378X) += stmp378x_devb.o
diff --git a/arch/arm/mach-stmp378x/Makefile.boot b/arch/arm/mach-stmp378x/Makefile.boot
new file mode 100644
index 000000000000..1568ad404d59
--- /dev/null
+++ b/arch/arm/mach-stmp378x/Makefile.boot
@@ -0,0 +1,3 @@
+ zreladdr-y := 0x40008000
+params_phys-y := 0x40000100
+initrd_phys-y := 0x40800000
diff --git a/arch/arm/mach-stmp378x/include/mach/entry-macro.S b/arch/arm/mach-stmp378x/include/mach/entry-macro.S
new file mode 100644
index 000000000000..731a92286da2
--- /dev/null
+++ b/arch/arm/mach-stmp378x/include/mach/entry-macro.S
@@ -0,0 +1,35 @@
+/*
+ * Low-level IRQ helper macros for Freescale STMP378X
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+ mov \base, #0xf0000000 @ vm address of IRQ controller
+ ldr \irqnr, [\base, #0x70] @ HW_ICOLL_STAT
+ cmp \irqnr, #0x7f
+ moveqs \irqnr, #0 @ Zero flag set for no IRQ
+
+ .endm
+
+ .macro get_irqnr_preamble, base, tmp
+ .endm
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
diff --git a/arch/arm/mach-stmp378x/include/mach/irqs.h b/arch/arm/mach-stmp378x/include/mach/irqs.h
new file mode 100644
index 000000000000..cc59673becdd
--- /dev/null
+++ b/arch/arm/mach-stmp378x/include/mach/irqs.h
@@ -0,0 +1,95 @@
+/*
+ * Freescale STMP378X interrupts
+ *
+ * Copyright (C) 2005 Sigmatel Inc
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#define IRQ_DEBUG_UART 0
+#define IRQ_COMMS_RX 1
+#define IRQ_COMMS_TX 1
+#define IRQ_SSP2_ERROR 2
+#define IRQ_VDD5V 3
+#define IRQ_HEADPHONE_SHORT 4
+#define IRQ_DAC_DMA 5
+#define IRQ_DAC_ERROR 6
+#define IRQ_ADC_DMA 7
+#define IRQ_ADC_ERROR 8
+#define IRQ_SPDIF_DMA 9
+#define IRQ_SAIF2_DMA 9
+#define IRQ_SPDIF_ERROR 10
+#define IRQ_SAIF1_IRQ 10
+#define IRQ_SAIF2_IRQ 10
+#define IRQ_USB_CTRL 11
+#define IRQ_USB_WAKEUP 12
+#define IRQ_GPMI_DMA 13
+#define IRQ_SSP1_DMA 14
+#define IRQ_SSP_ERROR 15
+#define IRQ_GPIO0 16
+#define IRQ_GPIO1 17
+#define IRQ_GPIO2 18
+#define IRQ_SAIF1_DMA 19
+#define IRQ_SSP2_DMA 20
+#define IRQ_ECC8_IRQ 21
+#define IRQ_RTC_ALARM 22
+#define IRQ_UARTAPP_TX_DMA 23
+#define IRQ_UARTAPP_INTERNAL 24
+#define IRQ_UARTAPP_RX_DMA 25
+#define IRQ_I2C_DMA 26
+#define IRQ_I2C_ERROR 27
+#define IRQ_TIMER0 28
+#define IRQ_TIMER1 29
+#define IRQ_TIMER2 30
+#define IRQ_TIMER3 31
+#define IRQ_BATT_BRNOUT 32
+#define IRQ_VDDD_BRNOUT 33
+#define IRQ_VDDIO_BRNOUT 34
+#define IRQ_VDD18_BRNOUT 35
+#define IRQ_TOUCH_DETECT 36
+#define IRQ_LRADC_CH0 37
+#define IRQ_LRADC_CH1 38
+#define IRQ_LRADC_CH2 39
+#define IRQ_LRADC_CH3 40
+#define IRQ_LRADC_CH4 41
+#define IRQ_LRADC_CH5 42
+#define IRQ_LRADC_CH6 43
+#define IRQ_LRADC_CH7 44
+#define IRQ_LCDIF_DMA 45
+#define IRQ_LCDIF_ERROR 46
+#define IRQ_DIGCTL_DEBUG_TRAP 47
+#define IRQ_RTC_1MSEC 48
+#define IRQ_DRI_DMA 49
+#define IRQ_DRI_ATTENTION 50
+#define IRQ_GPMI_ATTENTION 51
+#define IRQ_IR 52
+#define IRQ_DCP_VMI 53
+#define IRQ_DCP 54
+#define IRQ_BCH 56
+#define IRQ_PXP 57
+#define IRQ_UARTAPP2_TX_DMA 58
+#define IRQ_UARTAPP2_INTERNAL 59
+#define IRQ_UARTAPP2_RX_DMA 60
+#define IRQ_VDAC_DETECT 61
+#define IRQ_VDD5V_DROOP 64
+#define IRQ_DCDC4P2_BO 65
+
+
+#define NR_REAL_IRQS 128
+#define NR_IRQS (NR_REAL_IRQS + 32 * 3)
+
+/* All interrupts are FIQ capable */
+#define FIQ_START IRQ_DEBUG_UART
+
+/* Hard disk IRQ is a GPMI attention IRQ */
+#define IRQ_HARDDISK IRQ_GPMI_ATTENTION
diff --git a/arch/arm/mach-stmp378x/include/mach/pins.h b/arch/arm/mach-stmp378x/include/mach/pins.h
new file mode 100644
index 000000000000..93f952d35969
--- /dev/null
+++ b/arch/arm/mach-stmp378x/include/mach/pins.h
@@ -0,0 +1,151 @@
+/*
+ * Freescale STMP378X SoC pin multiplexing
+ *
+ * Author: Vladislav Buzov <vbuzov@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_ARCH_PINS_H
+#define __ASM_ARCH_PINS_H
+
+/*
+ * Define all STMP378x pins, a pin name corresponds to a STMP378x hardware
+ * interface this pin belongs to.
+ */
+
+/* Bank 0 */
+#define PINID_GPMI_D00 STMP3XXX_PINID(0, 0)
+#define PINID_GPMI_D01 STMP3XXX_PINID(0, 1)
+#define PINID_GPMI_D02 STMP3XXX_PINID(0, 2)
+#define PINID_GPMI_D03 STMP3XXX_PINID(0, 3)
+#define PINID_GPMI_D04 STMP3XXX_PINID(0, 4)
+#define PINID_GPMI_D05 STMP3XXX_PINID(0, 5)
+#define PINID_GPMI_D06 STMP3XXX_PINID(0, 6)
+#define PINID_GPMI_D07 STMP3XXX_PINID(0, 7)
+#define PINID_GPMI_D08 STMP3XXX_PINID(0, 8)
+#define PINID_GPMI_D09 STMP3XXX_PINID(0, 9)
+#define PINID_GPMI_D10 STMP3XXX_PINID(0, 10)
+#define PINID_GPMI_D11 STMP3XXX_PINID(0, 11)
+#define PINID_GPMI_D12 STMP3XXX_PINID(0, 12)
+#define PINID_GPMI_D13 STMP3XXX_PINID(0, 13)
+#define PINID_GPMI_D14 STMP3XXX_PINID(0, 14)
+#define PINID_GPMI_D15 STMP3XXX_PINID(0, 15)
+#define PINID_GPMI_CLE STMP3XXX_PINID(0, 16)
+#define PINID_GPMI_ALE STMP3XXX_PINID(0, 17)
+#define PINID_GMPI_CE2N STMP3XXX_PINID(0, 18)
+#define PINID_GPMI_RDY0 STMP3XXX_PINID(0, 19)
+#define PINID_GPMI_RDY1 STMP3XXX_PINID(0, 20)
+#define PINID_GPMI_RDY2 STMP3XXX_PINID(0, 21)
+#define PINID_GPMI_RDY3 STMP3XXX_PINID(0, 22)
+#define PINID_GPMI_WPN STMP3XXX_PINID(0, 23)
+#define PINID_GPMI_WRN STMP3XXX_PINID(0, 24)
+#define PINID_GPMI_RDN STMP3XXX_PINID(0, 25)
+#define PINID_AUART1_CTS STMP3XXX_PINID(0, 26)
+#define PINID_AUART1_RTS STMP3XXX_PINID(0, 27)
+#define PINID_AUART1_RX STMP3XXX_PINID(0, 28)
+#define PINID_AUART1_TX STMP3XXX_PINID(0, 29)
+#define PINID_I2C_SCL STMP3XXX_PINID(0, 30)
+#define PINID_I2C_SDA STMP3XXX_PINID(0, 31)
+
+/* Bank 1 */
+#define PINID_LCD_D00 STMP3XXX_PINID(1, 0)
+#define PINID_LCD_D01 STMP3XXX_PINID(1, 1)
+#define PINID_LCD_D02 STMP3XXX_PINID(1, 2)
+#define PINID_LCD_D03 STMP3XXX_PINID(1, 3)
+#define PINID_LCD_D04 STMP3XXX_PINID(1, 4)
+#define PINID_LCD_D05 STMP3XXX_PINID(1, 5)
+#define PINID_LCD_D06 STMP3XXX_PINID(1, 6)
+#define PINID_LCD_D07 STMP3XXX_PINID(1, 7)
+#define PINID_LCD_D08 STMP3XXX_PINID(1, 8)
+#define PINID_LCD_D09 STMP3XXX_PINID(1, 9)
+#define PINID_LCD_D10 STMP3XXX_PINID(1, 10)
+#define PINID_LCD_D11 STMP3XXX_PINID(1, 11)
+#define PINID_LCD_D12 STMP3XXX_PINID(1, 12)
+#define PINID_LCD_D13 STMP3XXX_PINID(1, 13)
+#define PINID_LCD_D14 STMP3XXX_PINID(1, 14)
+#define PINID_LCD_D15 STMP3XXX_PINID(1, 15)
+#define PINID_LCD_D16 STMP3XXX_PINID(1, 16)
+#define PINID_LCD_D17 STMP3XXX_PINID(1, 17)
+#define PINID_LCD_RESET STMP3XXX_PINID(1, 18)
+#define PINID_LCD_RS STMP3XXX_PINID(1, 19)
+#define PINID_LCD_WR STMP3XXX_PINID(1, 20)
+#define PINID_LCD_CS STMP3XXX_PINID(1, 21)
+#define PINID_LCD_DOTCK STMP3XXX_PINID(1, 22)
+#define PINID_LCD_ENABLE STMP3XXX_PINID(1, 23)
+#define PINID_LCD_HSYNC STMP3XXX_PINID(1, 24)
+#define PINID_LCD_VSYNC STMP3XXX_PINID(1, 25)
+#define PINID_PWM0 STMP3XXX_PINID(1, 26)
+#define PINID_PWM1 STMP3XXX_PINID(1, 27)
+#define PINID_PWM2 STMP3XXX_PINID(1, 28)
+#define PINID_PWM3 STMP3XXX_PINID(1, 29)
+#define PINID_PWM4 STMP3XXX_PINID(1, 30)
+
+/* Bank 2 */
+#define PINID_SSP1_CMD STMP3XXX_PINID(2, 0)
+#define PINID_SSP1_DETECT STMP3XXX_PINID(2, 1)
+#define PINID_SSP1_DATA0 STMP3XXX_PINID(2, 2)
+#define PINID_SSP1_DATA1 STMP3XXX_PINID(2, 3)
+#define PINID_SSP1_DATA2 STMP3XXX_PINID(2, 4)
+#define PINID_SSP1_DATA3 STMP3XXX_PINID(2, 5)
+#define PINID_SSP1_SCK STMP3XXX_PINID(2, 6)
+#define PINID_ROTARYA STMP3XXX_PINID(2, 7)
+#define PINID_ROTARYB STMP3XXX_PINID(2, 8)
+#define PINID_EMI_A00 STMP3XXX_PINID(2, 9)
+#define PINID_EMI_A01 STMP3XXX_PINID(2, 10)
+#define PINID_EMI_A02 STMP3XXX_PINID(2, 11)
+#define PINID_EMI_A03 STMP3XXX_PINID(2, 12)
+#define PINID_EMI_A04 STMP3XXX_PINID(2, 13)
+#define PINID_EMI_A05 STMP3XXX_PINID(2, 14)
+#define PINID_EMI_A06 STMP3XXX_PINID(2, 15)
+#define PINID_EMI_A07 STMP3XXX_PINID(2, 16)
+#define PINID_EMI_A08 STMP3XXX_PINID(2, 17)
+#define PINID_EMI_A09 STMP3XXX_PINID(2, 18)
+#define PINID_EMI_A10 STMP3XXX_PINID(2, 19)
+#define PINID_EMI_A11 STMP3XXX_PINID(2, 20)
+#define PINID_EMI_A12 STMP3XXX_PINID(2, 21)
+#define PINID_EMI_BA0 STMP3XXX_PINID(2, 22)
+#define PINID_EMI_BA1 STMP3XXX_PINID(2, 23)
+#define PINID_EMI_CASN STMP3XXX_PINID(2, 24)
+#define PINID_EMI_CE0N STMP3XXX_PINID(2, 25)
+#define PINID_EMI_CE1N STMP3XXX_PINID(2, 26)
+#define PINID_GPMI_CE1N STMP3XXX_PINID(2, 27)
+#define PINID_GPMI_CE0N STMP3XXX_PINID(2, 28)
+#define PINID_EMI_CKE STMP3XXX_PINID(2, 29)
+#define PINID_EMI_RASN STMP3XXX_PINID(2, 30)
+#define PINID_EMI_WEN STMP3XXX_PINID(2, 31)
+
+/* Bank 3 */
+#define PINID_EMI_D00 STMP3XXX_PINID(3, 0)
+#define PINID_EMI_D01 STMP3XXX_PINID(3, 1)
+#define PINID_EMI_D02 STMP3XXX_PINID(3, 2)
+#define PINID_EMI_D03 STMP3XXX_PINID(3, 3)
+#define PINID_EMI_D04 STMP3XXX_PINID(3, 4)
+#define PINID_EMI_D05 STMP3XXX_PINID(3, 5)
+#define PINID_EMI_D06 STMP3XXX_PINID(3, 6)
+#define PINID_EMI_D07 STMP3XXX_PINID(3, 7)
+#define PINID_EMI_D08 STMP3XXX_PINID(3, 8)
+#define PINID_EMI_D09 STMP3XXX_PINID(3, 9)
+#define PINID_EMI_D10 STMP3XXX_PINID(3, 10)
+#define PINID_EMI_D11 STMP3XXX_PINID(3, 11)
+#define PINID_EMI_D12 STMP3XXX_PINID(3, 12)
+#define PINID_EMI_D13 STMP3XXX_PINID(3, 13)
+#define PINID_EMI_D14 STMP3XXX_PINID(3, 14)
+#define PINID_EMI_D15 STMP3XXX_PINID(3, 15)
+#define PINID_EMI_DQM0 STMP3XXX_PINID(3, 16)
+#define PINID_EMI_DQM1 STMP3XXX_PINID(3, 17)
+#define PINID_EMI_DQS0 STMP3XXX_PINID(3, 18)
+#define PINID_EMI_DQS1 STMP3XXX_PINID(3, 19)
+#define PINID_EMI_CLK STMP3XXX_PINID(3, 20)
+#define PINID_EMI_CLKN STMP3XXX_PINID(3, 21)
+
+#endif /* __ASM_ARCH_PINS_H */
diff --git a/arch/arm/mach-stmp378x/include/mach/regs-apbh.h b/arch/arm/mach-stmp378x/include/mach/regs-apbh.h
new file mode 100644
index 000000000000..db63b041e4f0
--- /dev/null
+++ b/arch/arm/mach-stmp378x/include/mach/regs-apbh.h
@@ -0,0 +1,88 @@
+/*
+ * STMP APBH Register Definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ARCH_ARM___APBH_H
+#define __ARCH_ARM___APBH_H 1
+
+#include <mach/stmp3xxx_regs.h>
+
+#define REGS_APBH_BASE (REGS_BASE + 0x4000)
+#define REGS_APBH_BASE_PHYS (0x80004000)
+#define REGS_APBH_SIZE 0x00002000
+HW_REGISTER(HW_APBH_CTRL0, REGS_APBH_BASE, 0x00000000)
+#define HW_APBH_CTRL0_ADDR (REGS_APBH_BASE + 0x00000000)
+#define BM_APBH_CTRL0_SFTRST 0x80000000
+#define BM_APBH_CTRL0_CLKGATE 0x40000000
+#define BM_APBH_CTRL0_AHB_BURST8_EN 0x20000000
+#define BM_APBH_CTRL0_APB_BURST4_EN 0x10000000
+#define BP_APBH_CTRL0_RESET_CHANNEL 16
+#define BM_APBH_CTRL0_RESET_CHANNEL 0x00FF0000
+#define BF_APBH_CTRL0_RESET_CHANNEL(v) \
+ (((v) << 16) & BM_APBH_CTRL0_RESET_CHANNEL)
+HW_REGISTER(HW_APBH_CTRL1, REGS_APBH_BASE, 0x00000010)
+#define HW_APBH_CTRL1_ADDR (REGS_APBH_BASE + 0x00000010)
+HW_REGISTER(HW_APBH_CTRL2, REGS_APBH_BASE, 0x00000020)
+HW_REGISTER_0(HW_APBH_DEVSEL, REGS_APBH_BASE, 0x00000030)
+HW_REGISTER_0_INDEXED(HW_APBH_CHn_CURCMDAR, REGS_APBH_BASE, 0x00000040, 0x70)
+#define BP_APBH_CHn_CURCMDAR_CMD_ADDR 0
+#define BM_APBH_CHn_CURCMDAR_CMD_ADDR 0xFFFFFFFF
+#define BF_APBH_CHn_CURCMDAR_CMD_ADDR(v) (v)
+HW_REGISTER_0_INDEXED(HW_APBH_CHn_NXTCMDAR, REGS_APBH_BASE, 0x00000050, 0x70)
+HW_REGISTER_0_INDEXED(HW_APBH_CHn_CMD, REGS_APBH_BASE, 0x00000060, 0x70)
+#define BP_APBH_CHn_CMD_XFER_COUNT 16
+#define BM_APBH_CHn_CMD_XFER_COUNT 0xFFFF0000
+#define BF_APBH_CHn_CMD_XFER_COUNT(v) \
+ (((v) << 16) & BM_APBH_CHn_CMD_XFER_COUNT)
+#define BP_APBH_CHn_CMD_CMDWORDS 12
+#define BM_APBH_CHn_CMD_CMDWORDS 0x0000F000
+#define BF_APBH_CHn_CMD_CMDWORDS(v) \
+ (((v) << 12) & BM_APBH_CHn_CMD_CMDWORDS)
+#define BM_APBH_CHn_CMD_HALTONTERMINATE 0x00000100
+#define BM_APBH_CHn_CMD_WAIT4ENDCMD 0x00000080
+#define BM_APBH_CHn_CMD_SEMAPHORE 0x00000040
+#define BM_APBH_CHn_CMD_NANDWAIT4READY 0x00000020
+#define BM_APBH_CHn_CMD_NANDLOCK 0x00000010
+#define BM_APBH_CHn_CMD_IRQONCMPLT 0x00000008
+#define BM_APBH_CHn_CMD_CHAIN 0x00000004
+#define BP_APBH_CHn_CMD_COMMAND 0
+#define BM_APBH_CHn_CMD_COMMAND 0x00000003
+#define BF_APBH_CHn_CMD_COMMAND(v) \
+ (((v) << 0) & BM_APBH_CHn_CMD_COMMAND)
+#define BV_APBH_CHn_CMD_COMMAND__NO_DMA_XFER 0x0
+#define BV_APBH_CHn_CMD_COMMAND__DMA_WRITE 0x1
+#define BV_APBH_CHn_CMD_COMMAND__DMA_READ 0x2
+#define BV_APBH_CHn_CMD_COMMAND__DMA_SENSE 0x3
+HW_REGISTER_0_INDEXED(HW_APBH_CHn_BAR, REGS_APBH_BASE, 0x00000070, 0x70)
+HW_REGISTER_0_INDEXED(HW_APBH_CHn_SEMA, REGS_APBH_BASE, 0x00000080, 0x70)
+#define BP_APBH_CHn_SEMA_PHORE 16
+#define BM_APBH_CHn_SEMA_PHORE 0x00FF0000
+#define BF_APBH_CHn_SEMA_PHORE(v) \
+ (((v) << 16) & BM_APBH_CHn_SEMA_PHORE)
+#define BP_APBH_CHn_SEMA_INCREMENT_SEMA 0
+#define BM_APBH_CHn_SEMA_INCREMENT_SEMA 0x000000FF
+#define BF_APBH_CHn_SEMA_INCREMENT_SEMA(v) \
+ (((v) << 0) & BM_APBH_CHn_SEMA_INCREMENT_SEMA)
+HW_REGISTER_0_INDEXED(HW_APBH_CHn_DEBUG1, REGS_APBH_BASE, 0x00000090, 0x70)
+HW_REGISTER_0_INDEXED(HW_APBH_CHn_DEBUG2, REGS_APBH_BASE, 0x000000a0, 0x70)
+HW_REGISTER_0(HW_APBH_VERSION, REGS_APBH_BASE, 0x000003f0)
+#endif /* __ARCH_ARM___APBH_H */
diff --git a/arch/arm/mach-stmp378x/include/mach/regs-apbx.h b/arch/arm/mach-stmp378x/include/mach/regs-apbx.h
new file mode 100644
index 000000000000..d0e8e9fe1cce
--- /dev/null
+++ b/arch/arm/mach-stmp378x/include/mach/regs-apbx.h
@@ -0,0 +1,79 @@
+/*
+ * STMP APBX Register Definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __ARCH_ARM___APBX_H
+#define __ARCH_ARM___APBX_H 1
+
+#include <mach/stmp3xxx_regs.h>
+
+#define REGS_APBX_BASE (REGS_BASE + 0x24000)
+#define REGS_APBX_BASE_PHYS (0x80024000)
+#define REGS_APBX_SIZE 0x00002000
+HW_REGISTER(HW_APBX_CTRL0, REGS_APBX_BASE, 0x00000000)
+#define HW_APBX_CTRL0_ADDR (REGS_APBX_BASE + 0x00000000)
+#define BM_APBX_CTRL0_SFTRST 0x80000000
+#define BM_APBX_CTRL0_CLKGATE 0x40000000
+HW_REGISTER(HW_APBX_CTRL1, REGS_APBX_BASE, 0x00000010)
+HW_REGISTER(HW_APBX_CTRL2, REGS_APBX_BASE, 0x00000020)
+HW_REGISTER(HW_APBX_CHANNEL_CTRL, REGS_APBX_BASE, 0x00000030)
+#define BP_APBX_CHANNEL_CTRL_RESET_CHANNEL 16
+#define BM_APBX_CHANNEL_CTRL_RESET_CHANNEL 0xFFFF0000
+#define BF_APBX_CHANNEL_CTRL_RESET_CHANNEL(v) \
+ (((v) << BP_APBX_CHANNEL_CTRL_RESET_CHANNEL) & \
+ BM_APBX_CHANNEL_CTRL_RESET_CHANNEL)
+HW_REGISTER_0(HW_APBX_DEVSEL, REGS_APBX_BASE, 0x00000040)
+HW_REGISTER_0_INDEXED(HW_APBX_CHn_CURCMDAR, REGS_APBX_BASE, 0x00000100, 0x70)
+HW_REGISTER_0_INDEXED(HW_APBX_CHn_NXTCMDAR, REGS_APBX_BASE, 0x00000110, 0x70)
+HW_REGISTER_0_INDEXED(HW_APBX_CHn_CMD, REGS_APBX_BASE, 0x00000120, 0x70)
+#define BP_APBX_CHn_CMD_XFER_COUNT 16
+#define BM_APBX_CHn_CMD_XFER_COUNT 0xFFFF0000
+#define BF_APBX_CHn_CMD_XFER_COUNT(v) \
+ (((v) << 16) & BM_APBX_CHn_CMD_XFER_COUNT)
+#define BP_APBX_CHn_CMD_CMDWORDS 12
+#define BM_APBX_CHn_CMD_CMDWORDS 0x0000F000
+#define BF_APBX_CHn_CMD_CMDWORDS(v) \
+ (((v) << 12) & BM_APBX_CHn_CMD_CMDWORDS)
+#define BM_APBX_CHn_CMD_HALTONTERMINATE 0x00000100
+#define BM_APBX_CHn_CMD_WAIT4ENDCMD 0x00000080
+#define BM_APBX_CHn_CMD_SEMAPHORE 0x00000040
+#define BM_APBX_CHn_CMD_IRQONCMPLT 0x00000008
+#define BM_APBX_CHn_CMD_CHAIN 0x00000004
+#define BP_APBX_CHn_CMD_COMMAND 0
+#define BM_APBX_CHn_CMD_COMMAND 0x00000003
+#define BF_APBX_CHn_CMD_COMMAND(v) \
+ (((v) << 0) & BM_APBX_CHn_CMD_COMMAND)
+#define BV_APBX_CHn_CMD_COMMAND__NO_DMA_XFER 0x0
+#define BV_APBX_CHn_CMD_COMMAND__DMA_WRITE 0x1
+#define BV_APBX_CHn_CMD_COMMAND__DMA_READ 0x2
+HW_REGISTER_0_INDEXED(HW_APBX_CHn_BAR, REGS_APBX_BASE, 0x00000130, 0x70)
+HW_REGISTER_0_INDEXED(HW_APBX_CHn_SEMA, REGS_APBX_BASE, 0x00000140, 0x70)
+#define BP_APBX_CHn_SEMA_PHORE 16
+#define BM_APBX_CHn_SEMA_PHORE 0x00FF0000
+#define BF_APBX_CHn_SEMA_PHORE(v) \
+ (((v) << 16) & BM_APBX_CHn_SEMA_PHORE)
+#define BP_APBX_CHn_SEMA_INCREMENT_SEMA 0
+#define BM_APBX_CHn_SEMA_INCREMENT_SEMA 0x000000FF
+#define BF_APBX_CHn_SEMA_INCREMENT_SEMA(v) \
+ (((v) << 0) & BM_APBX_CHn_SEMA_INCREMENT_SEMA)
+HW_REGISTER_0_INDEXED(HW_APBX_CHn_DEBUG1, REGS_APBX_BASE, 0x00000150, 0x70)
+HW_REGISTER_0_INDEXED(HW_APBX_CHn_DEBUG2, REGS_APBX_BASE, 0x00000160, 0x70)
+HW_REGISTER_0(HW_APBX_VERSION, REGS_APBX_BASE, 0x00000800)
+#endif /* __ARCH_ARM___APBX_H */
diff --git a/arch/arm/mach-stmp378x/include/mach/regs-clkctrl.h b/arch/arm/mach-stmp378x/include/mach/regs-clkctrl.h
new file mode 100644
index 000000000000..a421d9e0cbff
--- /dev/null
+++ b/arch/arm/mach-stmp378x/include/mach/regs-clkctrl.h
@@ -0,0 +1,276 @@
+/*
+ * STMP CLKCTRL Register Definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ARCH_ARM___CLKCTRL_H
+#define __ARCH_ARM___CLKCTRL_H 1
+
+#include <mach/stmp3xxx_regs.h>
+
+#define REGS_CLKCTRL_BASE (REGS_BASE + 0x40000)
+#define REGS_CLKCTRL_BASE_PHYS (0x80040000)
+#define REGS_CLKCTRL_SIZE 0x00002000
+HW_REGISTER(HW_CLKCTRL_PLLCTRL0, REGS_CLKCTRL_BASE, 0x00000000)
+#define HW_CLKCTRL_PLLCTRL0_ADDR (REGS_CLKCTRL_BASE + 0x00000000)
+#define BP_CLKCTRL_PLLCTRL0_LFR_SEL 28
+#define BM_CLKCTRL_PLLCTRL0_LFR_SEL 0x30000000
+#define BF_CLKCTRL_PLLCTRL0_LFR_SEL(v) \
+ (((v) << 28) & BM_CLKCTRL_PLLCTRL0_LFR_SEL)
+#define BV_CLKCTRL_PLLCTRL0_LFR_SEL__DEFAULT 0x0
+#define BV_CLKCTRL_PLLCTRL0_LFR_SEL__TIMES_2 0x1
+#define BV_CLKCTRL_PLLCTRL0_LFR_SEL__TIMES_05 0x2
+#define BV_CLKCTRL_PLLCTRL0_LFR_SEL__UNDEFINED 0x3
+#define BP_CLKCTRL_PLLCTRL0_CP_SEL 24
+#define BM_CLKCTRL_PLLCTRL0_CP_SEL 0x03000000
+#define BF_CLKCTRL_PLLCTRL0_CP_SEL(v) \
+ (((v) << 24) & BM_CLKCTRL_PLLCTRL0_CP_SEL)
+#define BV_CLKCTRL_PLLCTRL0_CP_SEL__DEFAULT 0x0
+#define BV_CLKCTRL_PLLCTRL0_CP_SEL__TIMES_2 0x1
+#define BV_CLKCTRL_PLLCTRL0_CP_SEL__TIMES_05 0x2
+#define BV_CLKCTRL_PLLCTRL0_CP_SEL__UNDEFINED 0x3
+#define BP_CLKCTRL_PLLCTRL0_DIV_SEL 20
+#define BM_CLKCTRL_PLLCTRL0_DIV_SEL 0x00300000
+#define BF_CLKCTRL_PLLCTRL0_DIV_SEL(v) \
+ (((v) << 20) & BM_CLKCTRL_PLLCTRL0_DIV_SEL)
+#define BV_CLKCTRL_PLLCTRL0_DIV_SEL__DEFAULT 0x0
+#define BV_CLKCTRL_PLLCTRL0_DIV_SEL__LOWER 0x1
+#define BV_CLKCTRL_PLLCTRL0_DIV_SEL__LOWEST 0x2
+#define BV_CLKCTRL_PLLCTRL0_DIV_SEL__UNDEFINED 0x3
+#define BM_CLKCTRL_PLLCTRL0_EN_USB_CLKS 0x00040000
+#define BM_CLKCTRL_PLLCTRL0_POWER 0x00010000
+HW_REGISTER_0(HW_CLKCTRL_PLLCTRL1, REGS_CLKCTRL_BASE, 0x00000010)
+#define HW_CLKCTRL_PLLCTRL1_ADDR (REGS_CLKCTRL_BASE + 0x00000010)
+#define BM_CLKCTRL_PLLCTRL1_LOCK 0x80000000
+#define BM_CLKCTRL_PLLCTRL1_FORCE_LOCK 0x40000000
+#define BP_CLKCTRL_PLLCTRL1_LOCK_COUNT 0
+#define BM_CLKCTRL_PLLCTRL1_LOCK_COUNT 0x0000FFFF
+#define BF_CLKCTRL_PLLCTRL1_LOCK_COUNT(v) \
+ (((v) << 0) & BM_CLKCTRL_PLLCTRL1_LOCK_COUNT)
+HW_REGISTER(HW_CLKCTRL_CPU, REGS_CLKCTRL_BASE, 0x00000020)
+#define HW_CLKCTRL_CPU_ADDR (REGS_CLKCTRL_BASE + 0x00000020)
+#define BM_CLKCTRL_CPU_BUSY_REF_XTAL 0x20000000
+#define BM_CLKCTRL_CPU_BUSY_REF_CPU 0x10000000
+#define BM_CLKCTRL_CPU_DIV_XTAL_FRAC_EN 0x04000000
+#define BP_CLKCTRL_CPU_DIV_XTAL 16
+#define BM_CLKCTRL_CPU_DIV_XTAL 0x03FF0000
+#define BF_CLKCTRL_CPU_DIV_XTAL(v) \
+ (((v) << 16) & BM_CLKCTRL_CPU_DIV_XTAL)
+#define BM_CLKCTRL_CPU_INTERRUPT_WAIT 0x00001000
+#define BM_CLKCTRL_CPU_DIV_CPU_FRAC_EN 0x00000400
+#define BP_CLKCTRL_CPU_DIV_CPU 0
+#define BM_CLKCTRL_CPU_DIV_CPU 0x0000003F
+#define BF_CLKCTRL_CPU_DIV_CPU(v) \
+ (((v) << 0) & BM_CLKCTRL_CPU_DIV_CPU)
+HW_REGISTER(HW_CLKCTRL_HBUS, REGS_CLKCTRL_BASE, 0x00000030)
+#define HW_CLKCTRL_HBUS_ADDR (REGS_CLKCTRL_BASE + 0x00000030)
+#define BM_CLKCTRL_HBUS_BUSY 0x20000000
+#define BM_CLKCTRL_HBUS_DCP_AS_ENABLE 0x10000000
+#define BM_CLKCTRL_HBUS_PXP_AS_ENABLE 0x08000000
+#define BM_CLKCTRL_HBUS_APBHDMA_AS_ENABLE 0x04000000
+#define BM_CLKCTRL_HBUS_APBXDMA_AS_ENABLE 0x02000000
+#define BM_CLKCTRL_HBUS_TRAFFIC_JAM_AS_ENABLE 0x01000000
+#define BM_CLKCTRL_HBUS_TRAFFIC_AS_ENABLE 0x00800000
+#define BM_CLKCTRL_HBUS_CPU_DATA_AS_ENABLE 0x00400000
+#define BM_CLKCTRL_HBUS_CPU_INSTR_AS_ENABLE 0x00200000
+#define BM_CLKCTRL_HBUS_AUTO_SLOW_MODE 0x00100000
+#define BP_CLKCTRL_HBUS_SLOW_DIV 16
+#define BM_CLKCTRL_HBUS_SLOW_DIV 0x00070000
+#define BF_CLKCTRL_HBUS_SLOW_DIV(v) \
+ (((v) << 16) & BM_CLKCTRL_HBUS_SLOW_DIV)
+#define BV_CLKCTRL_HBUS_SLOW_DIV__BY1 0x0
+#define BV_CLKCTRL_HBUS_SLOW_DIV__BY2 0x1
+#define BV_CLKCTRL_HBUS_SLOW_DIV__BY4 0x2
+#define BV_CLKCTRL_HBUS_SLOW_DIV__BY8 0x3
+#define BV_CLKCTRL_HBUS_SLOW_DIV__BY16 0x4
+#define BV_CLKCTRL_HBUS_SLOW_DIV__BY32 0x5
+#define BM_CLKCTRL_HBUS_DIV_FRAC_EN 0x00000020
+#define BP_CLKCTRL_HBUS_DIV 0
+#define BM_CLKCTRL_HBUS_DIV 0x0000001F
+#define BF_CLKCTRL_HBUS_DIV(v) \
+ (((v) << 0) & BM_CLKCTRL_HBUS_DIV)
+HW_REGISTER_0(HW_CLKCTRL_XBUS, REGS_CLKCTRL_BASE, 0x00000040)
+#define HW_CLKCTRL_XBUS_ADDR (REGS_CLKCTRL_BASE + 0x00000040)
+#define BM_CLKCTRL_XBUS_BUSY 0x80000000
+#define BM_CLKCTRL_XBUS_DIV_FRAC_EN 0x00000400
+#define BP_CLKCTRL_XBUS_DIV 0
+#define BM_CLKCTRL_XBUS_DIV 0x000003FF
+#define BF_CLKCTRL_XBUS_DIV(v) \
+ (((v) << 0) & BM_CLKCTRL_XBUS_DIV)
+HW_REGISTER(HW_CLKCTRL_XTAL, REGS_CLKCTRL_BASE, 0x00000050)
+#define HW_CLKCTRL_XTAL_ADDR (REGS_CLKCTRL_BASE + 0x00000050)
+#define BM_CLKCTRL_XTAL_UART_CLK_GATE 0x80000000
+#define BM_CLKCTRL_XTAL_FILT_CLK24M_GATE 0x40000000
+#define BM_CLKCTRL_XTAL_PWM_CLK24M_GATE 0x20000000
+#define BM_CLKCTRL_XTAL_DRI_CLK24M_GATE 0x10000000
+#define BM_CLKCTRL_XTAL_DIGCTRL_CLK1M_GATE 0x08000000
+#define BM_CLKCTRL_XTAL_TIMROT_CLK32K_GATE 0x04000000
+#define BP_CLKCTRL_XTAL_DIV_UART 0
+#define BM_CLKCTRL_XTAL_DIV_UART 0x00000003
+#define BF_CLKCTRL_XTAL_DIV_UART(v) \
+ (((v) << 0) & BM_CLKCTRL_XTAL_DIV_UART)
+HW_REGISTER_0(HW_CLKCTRL_PIX, REGS_CLKCTRL_BASE, 0x00000060)
+#define HW_CLKCTRL_PIX_ADDR (REGS_CLKCTRL_BASE + 0x00000060)
+#define BM_CLKCTRL_PIX_CLKGATE 0x80000000
+#define BM_CLKCTRL_PIX_BUSY 0x20000000
+#define BM_CLKCTRL_PIX_DIV_FRAC_EN 0x00001000
+#define BP_CLKCTRL_PIX_DIV 0
+#define BM_CLKCTRL_PIX_DIV 0x00000FFF
+#define BF_CLKCTRL_PIX_DIV(v) \
+ (((v) << 0) & BM_CLKCTRL_PIX_DIV)
+HW_REGISTER_0(HW_CLKCTRL_SSP, REGS_CLKCTRL_BASE, 0x00000070)
+#define HW_CLKCTRL_SSP_ADDR (REGS_CLKCTRL_BASE + 0x00000070)
+#define BM_CLKCTRL_SSP_CLKGATE 0x80000000
+#define BM_CLKCTRL_SSP_BUSY 0x20000000
+#define BM_CLKCTRL_SSP_DIV_FRAC_EN 0x00000200
+#define BP_CLKCTRL_SSP_DIV 0
+#define BM_CLKCTRL_SSP_DIV 0x000001FF
+#define BF_CLKCTRL_SSP_DIV(v) \
+ (((v) << 0) & BM_CLKCTRL_SSP_DIV)
+HW_REGISTER_0(HW_CLKCTRL_GPMI, REGS_CLKCTRL_BASE, 0x00000080)
+#define HW_CLKCTRL_GPMI_ADDR (REGS_CLKCTRL_BASE + 0x00000080)
+#define BM_CLKCTRL_GPMI_CLKGATE 0x80000000
+#define BM_CLKCTRL_GPMI_BUSY 0x20000000
+#define BM_CLKCTRL_GPMI_DIV_FRAC_EN 0x00000400
+#define BP_CLKCTRL_GPMI_DIV 0
+#define BM_CLKCTRL_GPMI_DIV 0x000003FF
+#define BF_CLKCTRL_GPMI_DIV(v) \
+ (((v) << 0) & BM_CLKCTRL_GPMI_DIV)
+HW_REGISTER_0(HW_CLKCTRL_SPDIF, REGS_CLKCTRL_BASE, 0x00000090)
+#define HW_CLKCTRL_SPDIF_ADDR (REGS_CLKCTRL_BASE + 0x00000090)
+#define BM_CLKCTRL_SPDIF_CLKGATE 0x80000000
+HW_REGISTER_0(HW_CLKCTRL_EMI, REGS_CLKCTRL_BASE, 0x000000a0)
+#define HW_CLKCTRL_EMI_ADDR (REGS_CLKCTRL_BASE + 0x000000a0)
+#define BM_CLKCTRL_EMI_CLKGATE 0x80000000
+#define BM_CLKCTRL_EMI_SYNC_MODE_EN 0x40000000
+#define BM_CLKCTRL_EMI_BUSY_REF_XTAL 0x20000000
+#define BM_CLKCTRL_EMI_BUSY_REF_EMI 0x10000000
+#define BM_CLKCTRL_EMI_BUSY_REF_CPU 0x08000000
+#define BM_CLKCTRL_EMI_BUSY_SYNC_MODE 0x04000000
+#define BM_CLKCTRL_EMI_BUSY_DCC_RESYNC 0x00020000
+#define BM_CLKCTRL_EMI_DCC_RESYNC_ENABLE 0x00010000
+#define BP_CLKCTRL_EMI_DIV_XTAL 8
+#define BM_CLKCTRL_EMI_DIV_XTAL 0x00000F00
+#define BF_CLKCTRL_EMI_DIV_XTAL(v) \
+ (((v) << 8) & BM_CLKCTRL_EMI_DIV_XTAL)
+#define BP_CLKCTRL_EMI_DIV_EMI 0
+#define BM_CLKCTRL_EMI_DIV_EMI 0x0000003F
+#define BF_CLKCTRL_EMI_DIV_EMI(v) \
+ (((v) << 0) & BM_CLKCTRL_EMI_DIV_EMI)
+HW_REGISTER_0(HW_CLKCTRL_IR, REGS_CLKCTRL_BASE, 0x000000b0)
+#define HW_CLKCTRL_IR_ADDR (REGS_CLKCTRL_BASE + 0x000000b0)
+#define BM_CLKCTRL_IR_CLKGATE 0x80000000
+#define BM_CLKCTRL_IR_AUTO_DIV 0x20000000
+#define BM_CLKCTRL_IR_IR_BUSY 0x10000000
+#define BM_CLKCTRL_IR_IROV_BUSY 0x08000000
+#define BP_CLKCTRL_IR_IROV_DIV 16
+#define BM_CLKCTRL_IR_IROV_DIV 0x01FF0000
+#define BF_CLKCTRL_IR_IROV_DIV(v) \
+ (((v) << 16) & BM_CLKCTRL_IR_IROV_DIV)
+#define BP_CLKCTRL_IR_IR_DIV 0
+#define BM_CLKCTRL_IR_IR_DIV 0x000003FF
+#define BF_CLKCTRL_IR_IR_DIV(v) \
+ (((v) << 0) & BM_CLKCTRL_IR_IR_DIV)
+HW_REGISTER_0(HW_CLKCTRL_SAIF, REGS_CLKCTRL_BASE, 0x000000c0)
+#define HW_CLKCTRL_SAIF_ADDR (REGS_CLKCTRL_BASE + 0x000000c0)
+#define BM_CLKCTRL_SAIF_CLKGATE 0x80000000
+#define BM_CLKCTRL_SAIF_BUSY 0x20000000
+#define BM_CLKCTRL_SAIF_DIV_FRAC_EN 0x00010000
+#define BP_CLKCTRL_SAIF_DIV 0
+#define BM_CLKCTRL_SAIF_DIV 0x0000FFFF
+#define BF_CLKCTRL_SAIF_DIV(v) \
+ (((v) << 0) & BM_CLKCTRL_SAIF_DIV)
+HW_REGISTER_0(HW_CLKCTRL_TV, REGS_CLKCTRL_BASE, 0x000000d0)
+#define HW_CLKCTRL_TV_ADDR (REGS_CLKCTRL_BASE + 0x000000d0)
+#define BM_CLKCTRL_TV_CLK_TV108M_GATE 0x80000000
+#define BM_CLKCTRL_TV_CLK_TV_GATE 0x40000000
+HW_REGISTER_0(HW_CLKCTRL_ETM, REGS_CLKCTRL_BASE, 0x000000e0)
+#define HW_CLKCTRL_ETM_ADDR (REGS_CLKCTRL_BASE + 0x000000e0)
+#define BM_CLKCTRL_ETM_CLKGATE 0x80000000
+#define BM_CLKCTRL_ETM_BUSY 0x20000000
+#define BM_CLKCTRL_ETM_DIV_FRAC_EN 0x00000040
+#define BP_CLKCTRL_ETM_DIV 0
+#define BM_CLKCTRL_ETM_DIV 0x0000003F
+#define BF_CLKCTRL_ETM_DIV(v) \
+ (((v) << 0) & BM_CLKCTRL_ETM_DIV)
+HW_REGISTER(HW_CLKCTRL_FRAC, REGS_CLKCTRL_BASE, 0x000000f0)
+#define HW_CLKCTRL_FRAC_ADDR (REGS_CLKCTRL_BASE + 0x000000f0)
+#define BM_CLKCTRL_FRAC_CLKGATEIO 0x80000000
+#define BM_CLKCTRL_FRAC_IO_STABLE 0x40000000
+#define BP_CLKCTRL_FRAC_IOFRAC 24
+#define BM_CLKCTRL_FRAC_IOFRAC 0x3F000000
+#define BF_CLKCTRL_FRAC_IOFRAC(v) \
+ (((v) << 24) & BM_CLKCTRL_FRAC_IOFRAC)
+#define BM_CLKCTRL_FRAC_CLKGATEPIX 0x00800000
+#define BM_CLKCTRL_FRAC_PIX_STABLE 0x00400000
+#define BP_CLKCTRL_FRAC_PIXFRAC 16
+#define BM_CLKCTRL_FRAC_PIXFRAC 0x003F0000
+#define BF_CLKCTRL_FRAC_PIXFRAC(v) \
+ (((v) << 16) & BM_CLKCTRL_FRAC_PIXFRAC)
+#define BM_CLKCTRL_FRAC_CLKGATEEMI 0x00008000
+#define BM_CLKCTRL_FRAC_EMI_STABLE 0x00004000
+#define BP_CLKCTRL_FRAC_EMIFRAC 8
+#define BM_CLKCTRL_FRAC_EMIFRAC 0x00003F00
+#define BF_CLKCTRL_FRAC_EMIFRAC(v) \
+ (((v) << 8) & BM_CLKCTRL_FRAC_EMIFRAC)
+#define BM_CLKCTRL_FRAC_CLKGATECPU 0x00000080
+#define BM_CLKCTRL_FRAC_CPU_STABLE 0x00000040
+#define BP_CLKCTRL_FRAC_CPUFRAC 0
+#define BM_CLKCTRL_FRAC_CPUFRAC 0x0000003F
+#define BF_CLKCTRL_FRAC_CPUFRAC(v) \
+ (((v) << 0) & BM_CLKCTRL_FRAC_CPUFRAC)
+HW_REGISTER(HW_CLKCTRL_FRAC1, REGS_CLKCTRL_BASE, 0x00000100)
+#define HW_CLKCTRL_FRAC1_ADDR (REGS_CLKCTRL_BASE + 0x00000100)
+#define BM_CLKCTRL_FRAC1_CLKGATEVID 0x80000000
+#define BM_CLKCTRL_FRAC1_VID_STABLE 0x40000000
+HW_REGISTER(HW_CLKCTRL_CLKSEQ, REGS_CLKCTRL_BASE, 0x00000110)
+#define HW_CLKCTRL_CLKSEQ_ADDR (REGS_CLKCTRL_BASE + 0x00000110)
+#define BM_CLKCTRL_CLKSEQ_BYPASS_ETM 0x00000100
+#define BM_CLKCTRL_CLKSEQ_BYPASS_CPU 0x00000080
+#define BM_CLKCTRL_CLKSEQ_BYPASS_EMI 0x00000040
+#define BM_CLKCTRL_CLKSEQ_BYPASS_SSP 0x00000020
+#define BM_CLKCTRL_CLKSEQ_BYPASS_GPMI 0x00000010
+#define BM_CLKCTRL_CLKSEQ_BYPASS_IR 0x00000008
+#define BM_CLKCTRL_CLKSEQ_BYPASS_PIX 0x00000002
+#define BM_CLKCTRL_CLKSEQ_BYPASS_SAIF 0x00000001
+HW_REGISTER_0(HW_CLKCTRL_RESET, REGS_CLKCTRL_BASE, 0x00000120)
+#define HW_CLKCTRL_RESET_ADDR (REGS_CLKCTRL_BASE + 0x00000120)
+#define BM_CLKCTRL_RESET_CHIP 0x00000002
+#define BM_CLKCTRL_RESET_DIG 0x00000001
+HW_REGISTER_0(HW_CLKCTRL_STATUS, REGS_CLKCTRL_BASE, 0x00000130)
+#define HW_CLKCTRL_STATUS_ADDR (REGS_CLKCTRL_BASE + 0x00000130)
+#define BP_CLKCTRL_STATUS_CPU_LIMIT 30
+#define BM_CLKCTRL_STATUS_CPU_LIMIT 0xC0000000
+#define BF_CLKCTRL_STATUS_CPU_LIMIT(v) \
+ (((v) << 30) & BM_CLKCTRL_STATUS_CPU_LIMIT)
+HW_REGISTER_0(HW_CLKCTRL_VERSION, REGS_CLKCTRL_BASE, 0x00000140)
+#define HW_CLKCTRL_VERSION_ADDR (REGS_CLKCTRL_BASE + 0x00000140)
+#define BP_CLKCTRL_VERSION_MAJOR 24
+#define BM_CLKCTRL_VERSION_MAJOR 0xFF000000
+#define BF_CLKCTRL_VERSION_MAJOR(v) \
+ (((v) << 24) & BM_CLKCTRL_VERSION_MAJOR)
+#define BP_CLKCTRL_VERSION_MINOR 16
+#define BM_CLKCTRL_VERSION_MINOR 0x00FF0000
+#define BF_CLKCTRL_VERSION_MINOR(v) \
+ (((v) << 16) & BM_CLKCTRL_VERSION_MINOR)
+#define BP_CLKCTRL_VERSION_STEP 0
+#define BM_CLKCTRL_VERSION_STEP 0x0000FFFF
+#define BF_CLKCTRL_VERSION_STEP(v) \
+ (((v) << 0) & BM_CLKCTRL_VERSION_STEP)
+#endif /* __ARCH_ARM___CLKCTRL_H */
diff --git a/arch/arm/mach-stmp378x/include/mach/regs-icoll.h b/arch/arm/mach-stmp378x/include/mach/regs-icoll.h
new file mode 100644
index 000000000000..a5a530c6440d
--- /dev/null
+++ b/arch/arm/mach-stmp378x/include/mach/regs-icoll.h
@@ -0,0 +1,213 @@
+/*
+ * STMP ICOLL Register Definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ARCH_ARM___ICOLL_H
+#define __ARCH_ARM___ICOLL_H 1
+
+#include <mach/stmp3xxx_regs.h>
+
+#define REGS_ICOLL_BASE (REGS_BASE + 0x0)
+#define REGS_ICOLL_BASE_PHYS (0x80000000)
+#define REGS_ICOLL_SIZE 0x00002000
+HW_REGISTER(HW_ICOLL_VECTOR, REGS_ICOLL_BASE, 0x00000000)
+#define HW_ICOLL_VECTOR_ADDR (REGS_ICOLL_BASE + 0x00000000)
+#define BP_ICOLL_VECTOR_IRQVECTOR 2
+#define BM_ICOLL_VECTOR_IRQVECTOR 0xFFFFFFFC
+#define BF_ICOLL_VECTOR_IRQVECTOR(v) \
+ (((v) << 2) & BM_ICOLL_VECTOR_IRQVECTOR)
+HW_REGISTER_0(HW_ICOLL_LEVELACK, REGS_ICOLL_BASE, 0x00000010)
+#define HW_ICOLL_LEVELACK_ADDR (REGS_ICOLL_BASE + 0x00000010)
+#define BP_ICOLL_LEVELACK_IRQLEVELACK 0
+#define BM_ICOLL_LEVELACK_IRQLEVELACK 0x0000000F
+#define BF_ICOLL_LEVELACK_IRQLEVELACK(v) \
+ (((v) << 0) & BM_ICOLL_LEVELACK_IRQLEVELACK)
+#define BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0 0x1
+#define BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL1 0x2
+#define BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL2 0x4
+#define BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL3 0x8
+HW_REGISTER(HW_ICOLL_CTRL, REGS_ICOLL_BASE, 0x00000020)
+#define HW_ICOLL_CTRL_ADDR (REGS_ICOLL_BASE + 0x00000020)
+#define BM_ICOLL_CTRL_SFTRST 0x80000000
+#define BV_ICOLL_CTRL_SFTRST__RUN 0x0
+#define BV_ICOLL_CTRL_SFTRST__IN_RESET 0x1
+#define BM_ICOLL_CTRL_CLKGATE 0x40000000
+#define BV_ICOLL_CTRL_CLKGATE__RUN 0x0
+#define BV_ICOLL_CTRL_CLKGATE__NO_CLOCKS 0x1
+#define BP_ICOLL_CTRL_VECTOR_PITCH 21
+#define BM_ICOLL_CTRL_VECTOR_PITCH 0x00E00000
+#define BF_ICOLL_CTRL_VECTOR_PITCH(v) \
+ (((v) << 21) & BM_ICOLL_CTRL_VECTOR_PITCH)
+#define BV_ICOLL_CTRL_VECTOR_PITCH__DEFAULT_BY4 0x0
+#define BV_ICOLL_CTRL_VECTOR_PITCH__BY4 0x1
+#define BV_ICOLL_CTRL_VECTOR_PITCH__BY8 0x2
+#define BV_ICOLL_CTRL_VECTOR_PITCH__BY12 0x3
+#define BV_ICOLL_CTRL_VECTOR_PITCH__BY16 0x4
+#define BV_ICOLL_CTRL_VECTOR_PITCH__BY20 0x5
+#define BV_ICOLL_CTRL_VECTOR_PITCH__BY24 0x6
+#define BV_ICOLL_CTRL_VECTOR_PITCH__BY28 0x7
+#define BM_ICOLL_CTRL_BYPASS_FSM 0x00100000
+#define BV_ICOLL_CTRL_BYPASS_FSM__NORMAL 0x0
+#define BV_ICOLL_CTRL_BYPASS_FSM__BYPASS 0x1
+#define BM_ICOLL_CTRL_NO_NESTING 0x00080000
+#define BV_ICOLL_CTRL_NO_NESTING__NORMAL 0x0
+#define BV_ICOLL_CTRL_NO_NESTING__NO_NEST 0x1
+#define BM_ICOLL_CTRL_ARM_RSE_MODE 0x00040000
+#define BM_ICOLL_CTRL_FIQ_FINAL_ENABLE 0x00020000
+#define BV_ICOLL_CTRL_FIQ_FINAL_ENABLE__DISABLE 0x0
+#define BV_ICOLL_CTRL_FIQ_FINAL_ENABLE__ENABLE 0x1
+#define BM_ICOLL_CTRL_IRQ_FINAL_ENABLE 0x00010000
+#define BV_ICOLL_CTRL_IRQ_FINAL_ENABLE__DISABLE 0x0
+#define BV_ICOLL_CTRL_IRQ_FINAL_ENABLE__ENABLE 0x1
+HW_REGISTER(HW_ICOLL_VBASE, REGS_ICOLL_BASE, 0x00000040)
+#define HW_ICOLL_VBASE_ADDR (REGS_ICOLL_BASE + 0x00000040)
+#define BP_ICOLL_VBASE_TABLE_ADDRESS 2
+#define BM_ICOLL_VBASE_TABLE_ADDRESS 0xFFFFFFFC
+#define BF_ICOLL_VBASE_TABLE_ADDRESS(v) \
+ (((v) << 2) & BM_ICOLL_VBASE_TABLE_ADDRESS)
+HW_REGISTER_0(HW_ICOLL_STAT, REGS_ICOLL_BASE, 0x00000070)
+#define HW_ICOLL_STAT_ADDR (REGS_ICOLL_BASE + 0x00000070)
+#define BP_ICOLL_STAT_VECTOR_NUMBER 0
+#define BM_ICOLL_STAT_VECTOR_NUMBER 0x0000007F
+#define BF_ICOLL_STAT_VECTOR_NUMBER(v) \
+ (((v) << 0) & BM_ICOLL_STAT_VECTOR_NUMBER)
+/*
+ * multi-register-define name HW_ICOLL_RAWn
+ * base 0x000000A0
+ * count 4
+ * offset 0x10
+ */
+HW_REGISTER_0_INDEXED(HW_ICOLL_RAWn, REGS_ICOLL_BASE, 0x000000a0, 0x10)
+#define BP_ICOLL_RAWn_RAW_IRQS 0
+#define BM_ICOLL_RAWn_RAW_IRQS 0xFFFFFFFF
+#define BF_ICOLL_RAWn_RAW_IRQS(v) (v)
+/*
+ * multi-register-define name HW_ICOLL_INTERRUPTn
+ * base 0x00000120
+ * count 128
+ * offset 0x10
+ */
+HW_REGISTER_INDEXED(HW_ICOLL_INTERRUPTn, REGS_ICOLL_BASE, 0x00000120, 0x10)
+#define BM_ICOLL_INTERRUPTn_ENFIQ 0x00000010
+#define BV_ICOLL_INTERRUPTn_ENFIQ__DISABLE 0x0
+#define BV_ICOLL_INTERRUPTn_ENFIQ__ENABLE 0x1
+#define BM_ICOLL_INTERRUPTn_SOFTIRQ 0x00000008
+#define BV_ICOLL_INTERRUPTn_SOFTIRQ__NO_INTERRUPT 0x0
+#define BV_ICOLL_INTERRUPTn_SOFTIRQ__FORCE_INTERRUPT 0x1
+#define BM_ICOLL_INTERRUPTn_ENABLE 0x00000004
+#define BV_ICOLL_INTERRUPTn_ENABLE__DISABLE 0x0
+#define BV_ICOLL_INTERRUPTn_ENABLE__ENABLE 0x1
+#define BP_ICOLL_INTERRUPTn_PRIORITY 0
+#define BM_ICOLL_INTERRUPTn_PRIORITY 0x00000003
+#define BF_ICOLL_INTERRUPTn_PRIORITY(v) \
+ (((v) << 0) & BM_ICOLL_INTERRUPTn_PRIORITY)
+#define BV_ICOLL_INTERRUPTn_PRIORITY__LEVEL0 0x0
+#define BV_ICOLL_INTERRUPTn_PRIORITY__LEVEL1 0x1
+#define BV_ICOLL_INTERRUPTn_PRIORITY__LEVEL2 0x2
+#define BV_ICOLL_INTERRUPTn_PRIORITY__LEVEL3 0x3
+HW_REGISTER(HW_ICOLL_DEBUG, REGS_ICOLL_BASE, 0x00001120)
+#define HW_ICOLL_DEBUG_ADDR (REGS_ICOLL_BASE + 0x00001120)
+#define BP_ICOLL_DEBUG_INSERVICE 28
+#define BM_ICOLL_DEBUG_INSERVICE 0xF0000000
+#define BF_ICOLL_DEBUG_INSERVICE(v) \
+ (((v) << 28) & BM_ICOLL_DEBUG_INSERVICE)
+#define BV_ICOLL_DEBUG_INSERVICE__LEVEL0 0x1
+#define BV_ICOLL_DEBUG_INSERVICE__LEVEL1 0x2
+#define BV_ICOLL_DEBUG_INSERVICE__LEVEL2 0x4
+#define BV_ICOLL_DEBUG_INSERVICE__LEVEL3 0x8
+#define BP_ICOLL_DEBUG_LEVEL_REQUESTS 24
+#define BM_ICOLL_DEBUG_LEVEL_REQUESTS 0x0F000000
+#define BF_ICOLL_DEBUG_LEVEL_REQUESTS(v) \
+ (((v) << 24) & BM_ICOLL_DEBUG_LEVEL_REQUESTS)
+#define BV_ICOLL_DEBUG_LEVEL_REQUESTS__LEVEL0 0x1
+#define BV_ICOLL_DEBUG_LEVEL_REQUESTS__LEVEL1 0x2
+#define BV_ICOLL_DEBUG_LEVEL_REQUESTS__LEVEL2 0x4
+#define BV_ICOLL_DEBUG_LEVEL_REQUESTS__LEVEL3 0x8
+#define BP_ICOLL_DEBUG_REQUESTS_BY_LEVEL 20
+#define BM_ICOLL_DEBUG_REQUESTS_BY_LEVEL 0x00F00000
+#define BF_ICOLL_DEBUG_REQUESTS_BY_LEVEL(v) \
+ (((v) << 20) & BM_ICOLL_DEBUG_REQUESTS_BY_LEVEL)
+#define BV_ICOLL_DEBUG_REQUESTS_BY_LEVEL__LEVEL0 0x1
+#define BV_ICOLL_DEBUG_REQUESTS_BY_LEVEL__LEVEL1 0x2
+#define BV_ICOLL_DEBUG_REQUESTS_BY_LEVEL__LEVEL2 0x4
+#define BV_ICOLL_DEBUG_REQUESTS_BY_LEVEL__LEVEL3 0x8
+#define BM_ICOLL_DEBUG_FIQ 0x00020000
+#define BV_ICOLL_DEBUG_FIQ__NO_FIQ_REQUESTED 0x0
+#define BV_ICOLL_DEBUG_FIQ__FIQ_REQUESTED 0x1
+#define BM_ICOLL_DEBUG_IRQ 0x00010000
+#define BV_ICOLL_DEBUG_IRQ__NO_IRQ_REQUESTED 0x0
+#define BV_ICOLL_DEBUG_IRQ__IRQ_REQUESTED 0x1
+#define BP_ICOLL_DEBUG_VECTOR_FSM 0
+#define BM_ICOLL_DEBUG_VECTOR_FSM 0x000003FF
+#define BF_ICOLL_DEBUG_VECTOR_FSM(v) \
+ (((v) << 0) & BM_ICOLL_DEBUG_VECTOR_FSM)
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_IDLE 0x000
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_MULTICYCLE1 0x001
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_MULTICYCLE2 0x002
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_PENDING 0x004
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_MULTICYCLE3 0x008
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_MULTICYCLE4 0x010
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_ISR_RUNNING1 0x020
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_ISR_RUNNING2 0x040
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_ISR_RUNNING3 0x080
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_MULTICYCLE5 0x100
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_MULTICYCLE6 0x200
+HW_REGISTER(HW_ICOLL_DBGREAD0, REGS_ICOLL_BASE, 0x00001130)
+#define HW_ICOLL_DBGREAD0_ADDR (REGS_ICOLL_BASE + 0x00001130)
+#define BP_ICOLL_DBGREAD0_VALUE 0
+#define BM_ICOLL_DBGREAD0_VALUE 0xFFFFFFFF
+#define BF_ICOLL_DBGREAD0_VALUE(v) (v)
+HW_REGISTER(HW_ICOLL_DBGREAD1, REGS_ICOLL_BASE, 0x00001140)
+#define HW_ICOLL_DBGREAD1_ADDR (REGS_ICOLL_BASE + 0x00001140)
+#define BP_ICOLL_DBGREAD1_VALUE 0
+#define BM_ICOLL_DBGREAD1_VALUE 0xFFFFFFFF
+#define BF_ICOLL_DBGREAD1_VALUE(v) (v)
+HW_REGISTER(HW_ICOLL_DBGFLAG, REGS_ICOLL_BASE, 0x00001150)
+#define HW_ICOLL_DBGFLAG_ADDR (REGS_ICOLL_BASE + 0x00001150)
+#define BP_ICOLL_DBGFLAG_FLAG 0
+#define BM_ICOLL_DBGFLAG_FLAG 0x0000FFFF
+#define BF_ICOLL_DBGFLAG_FLAG(v) \
+ (((v) << 0) & BM_ICOLL_DBGFLAG_FLAG)
+/*
+ * multi-register-define name HW_ICOLL_DBGREQUESTn
+ * base 0x00001160
+ * count 4
+ * offset 0x10
+ */
+HW_REGISTER_0_INDEXED(HW_ICOLL_DBGREQUESTn, REGS_ICOLL_BASE, 0x00001160,
+ 0x10)
+#define BP_ICOLL_DBGREQUESTn_BITS 0
+#define BM_ICOLL_DBGREQUESTn_BITS 0xFFFFFFFF
+#define BF_ICOLL_DBGREQUESTn_BITS(v) (v)
+HW_REGISTER_0(HW_ICOLL_VERSION, REGS_ICOLL_BASE, 0x000011e0)
+#define HW_ICOLL_VERSION_ADDR (REGS_ICOLL_BASE + 0x000011e0)
+#define BP_ICOLL_VERSION_MAJOR 24
+#define BM_ICOLL_VERSION_MAJOR 0xFF000000
+#define BF_ICOLL_VERSION_MAJOR(v) \
+ (((v) << 24) & BM_ICOLL_VERSION_MAJOR)
+#define BP_ICOLL_VERSION_MINOR 16
+#define BM_ICOLL_VERSION_MINOR 0x00FF0000
+#define BF_ICOLL_VERSION_MINOR(v) \
+ (((v) << 16) & BM_ICOLL_VERSION_MINOR)
+#define BP_ICOLL_VERSION_STEP 0
+#define BM_ICOLL_VERSION_STEP 0x0000FFFF
+#define BF_ICOLL_VERSION_STEP(v) \
+ (((v) << 0) & BM_ICOLL_VERSION_STEP)
+#endif /* __ARCH_ARM___ICOLL_H */
diff --git a/arch/arm/mach-stmp378x/include/mach/regs-pinctrl.h b/arch/arm/mach-stmp378x/include/mach/regs-pinctrl.h
new file mode 100644
index 000000000000..6c42d2a47c19
--- /dev/null
+++ b/arch/arm/mach-stmp378x/include/mach/regs-pinctrl.h
@@ -0,0 +1,143 @@
+/*
+ * STMP PINCTRL Register Definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ARCH_ARM___PINCTRL_H
+#define __ARCH_ARM___PINCTRL_H 1
+
+#include <mach/stmp3xxx_regs.h>
+
+#define REGS_PINCTRL_BASE (REGS_BASE + 0x18000)
+#define REGS_PINCTRL_BASE_PHYS (0x80018000)
+#define REGS_PINCTRL_SIZE 0x00002000
+HW_REGISTER(HW_PINCTRL_CTRL, REGS_PINCTRL_BASE, 0x00000000)
+#define HW_PINCTRL_CTRL_ADDR (REGS_PINCTRL_BASE + 0x00000000)
+#define BM_PINCTRL_CTRL_SFTRST 0x80000000
+#define BM_PINCTRL_CTRL_CLKGATE 0x40000000
+#define BM_PINCTRL_CTRL_PRESENT3 0x08000000
+#define BM_PINCTRL_CTRL_PRESENT2 0x04000000
+#define BM_PINCTRL_CTRL_PRESENT1 0x02000000
+#define BM_PINCTRL_CTRL_PRESENT0 0x01000000
+#define BM_PINCTRL_CTRL_IRQOUT2 0x00000004
+#define BM_PINCTRL_CTRL_IRQOUT1 0x00000002
+#define BM_PINCTRL_CTRL_IRQOUT0 0x00000001
+HW_REGISTER(HW_PINCTRL_MUXSEL0, REGS_PINCTRL_BASE, 0x00000100)
+#define HW_PINCTRL_MUXSEL0_ADDR (REGS_PINCTRL_BASE + 0x00000100)
+HW_REGISTER(HW_PINCTRL_MUXSEL1, REGS_PINCTRL_BASE, 0x00000110)
+#define HW_PINCTRL_MUXSEL1_ADDR (REGS_PINCTRL_BASE + 0x00000110)
+HW_REGISTER(HW_PINCTRL_MUXSEL2, REGS_PINCTRL_BASE, 0x00000120)
+#define HW_PINCTRL_MUXSEL2_ADDR (REGS_PINCTRL_BASE + 0x00000120)
+HW_REGISTER(HW_PINCTRL_MUXSEL3, REGS_PINCTRL_BASE, 0x00000130)
+#define HW_PINCTRL_MUXSEL3_ADDR (REGS_PINCTRL_BASE + 0x00000130)
+HW_REGISTER(HW_PINCTRL_MUXSEL4, REGS_PINCTRL_BASE, 0x00000140)
+#define HW_PINCTRL_MUXSEL4_ADDR (REGS_PINCTRL_BASE + 0x00000140)
+HW_REGISTER(HW_PINCTRL_MUXSEL5, REGS_PINCTRL_BASE, 0x00000150)
+#define HW_PINCTRL_MUXSEL5_ADDR (REGS_PINCTRL_BASE + 0x00000150)
+HW_REGISTER(HW_PINCTRL_MUXSEL6, REGS_PINCTRL_BASE, 0x00000160)
+#define HW_PINCTRL_MUXSEL6_ADDR (REGS_PINCTRL_BASE + 0x00000160)
+HW_REGISTER(HW_PINCTRL_MUXSEL7, REGS_PINCTRL_BASE, 0x00000170)
+#define HW_PINCTRL_MUXSEL7_ADDR (REGS_PINCTRL_BASE + 0x00000170)
+HW_REGISTER(HW_PINCTRL_DRIVE0, REGS_PINCTRL_BASE, 0x00000200)
+#define HW_PINCTRL_DRIVE0_ADDR (REGS_PINCTRL_BASE + 0x00000200)
+HW_REGISTER(HW_PINCTRL_DRIVE1, REGS_PINCTRL_BASE, 0x00000210)
+#define HW_PINCTRL_DRIVE1_ADDR (REGS_PINCTRL_BASE + 0x00000210)
+HW_REGISTER(HW_PINCTRL_DRIVE2, REGS_PINCTRL_BASE, 0x00000220)
+#define HW_PINCTRL_DRIVE2_ADDR (REGS_PINCTRL_BASE + 0x00000220)
+HW_REGISTER(HW_PINCTRL_DRIVE3, REGS_PINCTRL_BASE, 0x00000230)
+#define HW_PINCTRL_DRIVE3_ADDR (REGS_PINCTRL_BASE + 0x00000230)
+HW_REGISTER(HW_PINCTRL_DRIVE4, REGS_PINCTRL_BASE, 0x00000240)
+#define HW_PINCTRL_DRIVE4_ADDR (REGS_PINCTRL_BASE + 0x00000240)
+HW_REGISTER(HW_PINCTRL_DRIVE5, REGS_PINCTRL_BASE, 0x00000250)
+#define HW_PINCTRL_DRIVE5_ADDR (REGS_PINCTRL_BASE + 0x00000250)
+HW_REGISTER(HW_PINCTRL_DRIVE6, REGS_PINCTRL_BASE, 0x00000260)
+#define HW_PINCTRL_DRIVE6_ADDR (REGS_PINCTRL_BASE + 0x00000260)
+HW_REGISTER(HW_PINCTRL_DRIVE7, REGS_PINCTRL_BASE, 0x00000270)
+#define HW_PINCTRL_DRIVE7_ADDR (REGS_PINCTRL_BASE + 0x00000270)
+HW_REGISTER(HW_PINCTRL_DRIVE8, REGS_PINCTRL_BASE, 0x00000280)
+#define HW_PINCTRL_DRIVE8_ADDR (REGS_PINCTRL_BASE + 0x00000280)
+HW_REGISTER(HW_PINCTRL_DRIVE9, REGS_PINCTRL_BASE, 0x00000290)
+#define HW_PINCTRL_DRIVE9_ADDR (REGS_PINCTRL_BASE + 0x00000290)
+HW_REGISTER(HW_PINCTRL_DRIVE10, REGS_PINCTRL_BASE, 0x000002a0)
+#define HW_PINCTRL_DRIVE10_ADDR (REGS_PINCTRL_BASE + 0x000002a0)
+HW_REGISTER(HW_PINCTRL_DRIVE11, REGS_PINCTRL_BASE, 0x000002b0)
+#define HW_PINCTRL_DRIVE11_ADDR (REGS_PINCTRL_BASE + 0x000002b0)
+HW_REGISTER(HW_PINCTRL_DRIVE12, REGS_PINCTRL_BASE, 0x000002c0)
+#define HW_PINCTRL_DRIVE12_ADDR (REGS_PINCTRL_BASE + 0x000002c0)
+HW_REGISTER(HW_PINCTRL_DRIVE13, REGS_PINCTRL_BASE, 0x000002d0)
+#define HW_PINCTRL_DRIVE13_ADDR (REGS_PINCTRL_BASE + 0x000002d0)
+HW_REGISTER(HW_PINCTRL_DRIVE14, REGS_PINCTRL_BASE, 0x000002e0)
+#define HW_PINCTRL_DRIVE14_ADDR (REGS_PINCTRL_BASE + 0x000002e0)
+HW_REGISTER(HW_PINCTRL_PULL0, REGS_PINCTRL_BASE, 0x00000400)
+#define HW_PINCTRL_PULL0_ADDR (REGS_PINCTRL_BASE + 0x00000400)
+HW_REGISTER(HW_PINCTRL_PULL1, REGS_PINCTRL_BASE, 0x00000410)
+#define HW_PINCTRL_PULL1_ADDR (REGS_PINCTRL_BASE + 0x00000410)
+HW_REGISTER(HW_PINCTRL_PULL2, REGS_PINCTRL_BASE, 0x00000420)
+#define HW_PINCTRL_PULL2_ADDR (REGS_PINCTRL_BASE + 0x00000420)
+HW_REGISTER(HW_PINCTRL_PULL3, REGS_PINCTRL_BASE, 0x00000430)
+#define HW_PINCTRL_PULL3_ADDR (REGS_PINCTRL_BASE + 0x00000430)
+HW_REGISTER(HW_PINCTRL_DOUT0, REGS_PINCTRL_BASE, 0x00000500)
+#define HW_PINCTRL_DOUT0_ADDR (REGS_PINCTRL_BASE + 0x00000500)
+HW_REGISTER(HW_PINCTRL_DOUT1, REGS_PINCTRL_BASE, 0x00000510)
+#define HW_PINCTRL_DOUT1_ADDR (REGS_PINCTRL_BASE + 0x00000510)
+HW_REGISTER(HW_PINCTRL_DOUT2, REGS_PINCTRL_BASE, 0x00000520)
+#define HW_PINCTRL_DOUT2_ADDR (REGS_PINCTRL_BASE + 0x00000520)
+HW_REGISTER(HW_PINCTRL_DIN0, REGS_PINCTRL_BASE, 0x00000600)
+#define HW_PINCTRL_DIN0_ADDR (REGS_PINCTRL_BASE + 0x00000600)
+HW_REGISTER(HW_PINCTRL_DIN1, REGS_PINCTRL_BASE, 0x00000610)
+#define HW_PINCTRL_DIN1_ADDR (REGS_PINCTRL_BASE + 0x00000610)
+HW_REGISTER(HW_PINCTRL_DIN2, REGS_PINCTRL_BASE, 0x00000620)
+#define HW_PINCTRL_DIN2_ADDR (REGS_PINCTRL_BASE + 0x00000620)
+HW_REGISTER(HW_PINCTRL_DOE0, REGS_PINCTRL_BASE, 0x00000700)
+#define HW_PINCTRL_DOE0_ADDR (REGS_PINCTRL_BASE + 0x00000700)
+HW_REGISTER(HW_PINCTRL_DOE1, REGS_PINCTRL_BASE, 0x00000710)
+#define HW_PINCTRL_DOE1_ADDR (REGS_PINCTRL_BASE + 0x00000710)
+HW_REGISTER(HW_PINCTRL_DOE2, REGS_PINCTRL_BASE, 0x00000720)
+#define HW_PINCTRL_DOE2_ADDR (REGS_PINCTRL_BASE + 0x00000720)
+HW_REGISTER(HW_PINCTRL_PIN2IRQ0, REGS_PINCTRL_BASE, 0x00000800)
+#define HW_PINCTRL_PIN2IRQ0_ADDR (REGS_PINCTRL_BASE + 0x00000800)
+HW_REGISTER(HW_PINCTRL_PIN2IRQ1, REGS_PINCTRL_BASE, 0x00000810)
+#define HW_PINCTRL_PIN2IRQ1_ADDR (REGS_PINCTRL_BASE + 0x00000810)
+HW_REGISTER(HW_PINCTRL_PIN2IRQ2, REGS_PINCTRL_BASE, 0x00000820)
+#define HW_PINCTRL_PIN2IRQ2_ADDR (REGS_PINCTRL_BASE + 0x00000820)
+HW_REGISTER(HW_PINCTRL_IRQEN0, REGS_PINCTRL_BASE, 0x00000900)
+#define HW_PINCTRL_IRQEN0_ADDR (REGS_PINCTRL_BASE + 0x00000900)
+HW_REGISTER(HW_PINCTRL_IRQEN1, REGS_PINCTRL_BASE, 0x00000910)
+#define HW_PINCTRL_IRQEN1_ADDR (REGS_PINCTRL_BASE + 0x00000910)
+HW_REGISTER(HW_PINCTRL_IRQEN2, REGS_PINCTRL_BASE, 0x00000920)
+#define HW_PINCTRL_IRQEN2_ADDR (REGS_PINCTRL_BASE + 0x00000920)
+HW_REGISTER(HW_PINCTRL_IRQLEVEL0, REGS_PINCTRL_BASE, 0x00000a00)
+#define HW_PINCTRL_IRQLEVEL0_ADDR (REGS_PINCTRL_BASE + 0x00000a00)
+HW_REGISTER(HW_PINCTRL_IRQLEVEL1, REGS_PINCTRL_BASE, 0x00000a10)
+#define HW_PINCTRL_IRQLEVEL1_ADDR (REGS_PINCTRL_BASE + 0x00000a10)
+HW_REGISTER(HW_PINCTRL_IRQLEVEL2, REGS_PINCTRL_BASE, 0x00000a20)
+#define HW_PINCTRL_IRQLEVEL2_ADDR (REGS_PINCTRL_BASE + 0x00000a20)
+HW_REGISTER(HW_PINCTRL_IRQPOL0, REGS_PINCTRL_BASE, 0x00000b00)
+#define HW_PINCTRL_IRQPOL0_ADDR (REGS_PINCTRL_BASE + 0x00000b00)
+HW_REGISTER(HW_PINCTRL_IRQPOL1, REGS_PINCTRL_BASE, 0x00000b10)
+#define HW_PINCTRL_IRQPOL1_ADDR (REGS_PINCTRL_BASE + 0x00000b10)
+HW_REGISTER(HW_PINCTRL_IRQPOL2, REGS_PINCTRL_BASE, 0x00000b20)
+#define HW_PINCTRL_IRQPOL2_ADDR (REGS_PINCTRL_BASE + 0x00000b20)
+HW_REGISTER(HW_PINCTRL_IRQSTAT0, REGS_PINCTRL_BASE, 0x00000c00)
+#define HW_PINCTRL_IRQSTAT0_ADDR (REGS_PINCTRL_BASE + 0x00000c00)
+HW_REGISTER(HW_PINCTRL_IRQSTAT1, REGS_PINCTRL_BASE, 0x00000c10)
+#define HW_PINCTRL_IRQSTAT1_ADDR (REGS_PINCTRL_BASE + 0x00000c10)
+HW_REGISTER(HW_PINCTRL_IRQSTAT2, REGS_PINCTRL_BASE, 0x00000c20)
+#define HW_PINCTRL_IRQSTAT2_ADDR (REGS_PINCTRL_BASE + 0x00000c20)
+#endif /* __ARCH_ARM___PINCTRL_H */
diff --git a/arch/arm/mach-stmp378x/include/mach/regs-power.h b/arch/arm/mach-stmp378x/include/mach/regs-power.h
new file mode 100644
index 000000000000..1c81afeed531
--- /dev/null
+++ b/arch/arm/mach-stmp378x/include/mach/regs-power.h
@@ -0,0 +1,32 @@
+/*
+ * STMP POWER Register Definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ARCH_ARM___POWER_H
+#define __ARCH_ARM___POWER_H 1
+
+#include <mach/stmp3xxx_regs.h>
+
+#define REGS_POWER_BASE (void __iomem *)(REGS_BASE + 0x44000)
+#define REGS_POWER_BASE_PHYS (0x80044000)
+#define REGS_POWER_SIZE 0x00002000
+HW_REGISTER(HW_POWER_MINPWR, REGS_POWER_BASE, 0x00000020)
+HW_REGISTER(HW_POWER_CHARGE, REGS_POWER_BASE, 0x00000030)
+#endif /* __ARCH_ARM___POWER_H */
diff --git a/arch/arm/mach-stmp378x/include/mach/regs-timrot.h b/arch/arm/mach-stmp378x/include/mach/regs-timrot.h
new file mode 100644
index 000000000000..bb6355acdfd1
--- /dev/null
+++ b/arch/arm/mach-stmp378x/include/mach/regs-timrot.h
@@ -0,0 +1,216 @@
+/*
+ * STMP TIMROT Register Definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ARCH_ARM___TIMROT_H
+#define __ARCH_ARM___TIMROT_H 1
+
+#include <mach/stmp3xxx_regs.h>
+
+#define REGS_TIMROT_BASE (REGS_BASE + 0x68000)
+#define REGS_TIMROT_BASE_PHYS (0x80068000)
+#define REGS_TIMROT_SIZE 0x00002000
+HW_REGISTER(HW_TIMROT_ROTCTRL, REGS_TIMROT_BASE, 0x00000000)
+#define HW_TIMROT_ROTCTRL_ADDR (REGS_TIMROT_BASE + 0x00000000)
+#define BM_TIMROT_ROTCTRL_SFTRST 0x80000000
+#define BM_TIMROT_ROTCTRL_CLKGATE 0x40000000
+#define BM_TIMROT_ROTCTRL_ROTARY_PRESENT 0x20000000
+#define BM_TIMROT_ROTCTRL_TIM3_PRESENT 0x10000000
+#define BM_TIMROT_ROTCTRL_TIM2_PRESENT 0x08000000
+#define BM_TIMROT_ROTCTRL_TIM1_PRESENT 0x04000000
+#define BM_TIMROT_ROTCTRL_TIM0_PRESENT 0x02000000
+#define BP_TIMROT_ROTCTRL_STATE 22
+#define BM_TIMROT_ROTCTRL_STATE 0x01C00000
+#define BF_TIMROT_ROTCTRL_STATE(v) \
+ (((v) << 22) & BM_TIMROT_ROTCTRL_STATE)
+#define BP_TIMROT_ROTCTRL_DIVIDER 16
+#define BM_TIMROT_ROTCTRL_DIVIDER 0x003F0000
+#define BF_TIMROT_ROTCTRL_DIVIDER(v) \
+ (((v) << 16) & BM_TIMROT_ROTCTRL_DIVIDER)
+#define BM_TIMROT_ROTCTRL_RELATIVE 0x00001000
+#define BP_TIMROT_ROTCTRL_OVERSAMPLE 10
+#define BM_TIMROT_ROTCTRL_OVERSAMPLE 0x00000C00
+#define BF_TIMROT_ROTCTRL_OVERSAMPLE(v) \
+ (((v) << 10) & BM_TIMROT_ROTCTRL_OVERSAMPLE)
+#define BV_TIMROT_ROTCTRL_OVERSAMPLE__8X 0x0
+#define BV_TIMROT_ROTCTRL_OVERSAMPLE__4X 0x1
+#define BV_TIMROT_ROTCTRL_OVERSAMPLE__2X 0x2
+#define BV_TIMROT_ROTCTRL_OVERSAMPLE__1X 0x3
+#define BM_TIMROT_ROTCTRL_POLARITY_B 0x00000200
+#define BM_TIMROT_ROTCTRL_POLARITY_A 0x00000100
+#define BP_TIMROT_ROTCTRL_SELECT_B 4
+#define BM_TIMROT_ROTCTRL_SELECT_B 0x00000070
+#define BF_TIMROT_ROTCTRL_SELECT_B(v) \
+ (((v) << 4) & BM_TIMROT_ROTCTRL_SELECT_B)
+#define BV_TIMROT_ROTCTRL_SELECT_B__NEVER_TICK 0x0
+#define BV_TIMROT_ROTCTRL_SELECT_B__PWM0 0x1
+#define BV_TIMROT_ROTCTRL_SELECT_B__PWM1 0x2
+#define BV_TIMROT_ROTCTRL_SELECT_B__PWM2 0x3
+#define BV_TIMROT_ROTCTRL_SELECT_B__PWM3 0x4
+#define BV_TIMROT_ROTCTRL_SELECT_B__PWM4 0x5
+#define BV_TIMROT_ROTCTRL_SELECT_B__ROTARYA 0x6
+#define BV_TIMROT_ROTCTRL_SELECT_B__ROTARYB 0x7
+#define BP_TIMROT_ROTCTRL_SELECT_A 0
+#define BM_TIMROT_ROTCTRL_SELECT_A 0x00000007
+#define BF_TIMROT_ROTCTRL_SELECT_A(v) \
+ (((v) << 0) & BM_TIMROT_ROTCTRL_SELECT_A)
+#define BV_TIMROT_ROTCTRL_SELECT_A__NEVER_TICK 0x0
+#define BV_TIMROT_ROTCTRL_SELECT_A__PWM0 0x1
+#define BV_TIMROT_ROTCTRL_SELECT_A__PWM1 0x2
+#define BV_TIMROT_ROTCTRL_SELECT_A__PWM2 0x3
+#define BV_TIMROT_ROTCTRL_SELECT_A__PWM3 0x4
+#define BV_TIMROT_ROTCTRL_SELECT_A__PWM4 0x5
+#define BV_TIMROT_ROTCTRL_SELECT_A__ROTARYA 0x6
+#define BV_TIMROT_ROTCTRL_SELECT_A__ROTARYB 0x7
+HW_REGISTER_0(HW_TIMROT_ROTCOUNT, REGS_TIMROT_BASE, 0x00000010)
+#define HW_TIMROT_ROTCOUNT_ADDR (REGS_TIMROT_BASE + 0x00000010)
+#define BP_TIMROT_ROTCOUNT_UPDOWN 0
+#define BM_TIMROT_ROTCOUNT_UPDOWN 0x0000FFFF
+#define BF_TIMROT_ROTCOUNT_UPDOWN(v) \
+ (((v) << 0) & BM_TIMROT_ROTCOUNT_UPDOWN)
+/*
+ * multi-register-define name HW_TIMROT_TIMCTRLn
+ * base 0x00000020
+ * count 3
+ * offset 0x20
+ */
+HW_REGISTER_INDEXED(HW_TIMROT_TIMCTRLn, REGS_TIMROT_BASE, 0x00000020, 0x20)
+#define BM_TIMROT_TIMCTRLn_IRQ 0x00008000
+#define BM_TIMROT_TIMCTRLn_IRQ_EN 0x00004000
+#define BM_TIMROT_TIMCTRLn_POLARITY 0x00000100
+#define BM_TIMROT_TIMCTRLn_UPDATE 0x00000080
+#define BM_TIMROT_TIMCTRLn_RELOAD 0x00000040
+#define BP_TIMROT_TIMCTRLn_PRESCALE 4
+#define BM_TIMROT_TIMCTRLn_PRESCALE 0x00000030
+#define BF_TIMROT_TIMCTRLn_PRESCALE(v) \
+ (((v) << 4) & BM_TIMROT_TIMCTRLn_PRESCALE)
+#define BV_TIMROT_TIMCTRLn_PRESCALE__DIV_BY_1 0x0
+#define BV_TIMROT_TIMCTRLn_PRESCALE__DIV_BY_2 0x1
+#define BV_TIMROT_TIMCTRLn_PRESCALE__DIV_BY_4 0x2
+#define BV_TIMROT_TIMCTRLn_PRESCALE__DIV_BY_8 0x3
+#define BP_TIMROT_TIMCTRLn_SELECT 0
+#define BM_TIMROT_TIMCTRLn_SELECT 0x0000000F
+#define BF_TIMROT_TIMCTRLn_SELECT(v) \
+ (((v) << 0) & BM_TIMROT_TIMCTRLn_SELECT)
+#define BV_TIMROT_TIMCTRLn_SELECT__NEVER_TICK 0x0
+#define BV_TIMROT_TIMCTRLn_SELECT__PWM0 0x1
+#define BV_TIMROT_TIMCTRLn_SELECT__PWM1 0x2
+#define BV_TIMROT_TIMCTRLn_SELECT__PWM2 0x3
+#define BV_TIMROT_TIMCTRLn_SELECT__PWM3 0x4
+#define BV_TIMROT_TIMCTRLn_SELECT__PWM4 0x5
+#define BV_TIMROT_TIMCTRLn_SELECT__ROTARYA 0x6
+#define BV_TIMROT_TIMCTRLn_SELECT__ROTARYB 0x7
+#define BV_TIMROT_TIMCTRLn_SELECT__32KHZ_XTAL 0x8
+#define BV_TIMROT_TIMCTRLn_SELECT__8KHZ_XTAL 0x9
+#define BV_TIMROT_TIMCTRLn_SELECT__4KHZ_XTAL 0xA
+#define BV_TIMROT_TIMCTRLn_SELECT__1KHZ_XTAL 0xB
+#define BV_TIMROT_TIMCTRLn_SELECT__TICK_ALWAYS 0xC
+/*
+ * multi-register-define name HW_TIMROT_TIMCOUNTn
+ * base 0x00000030
+ * count 3
+ * offset 0x20
+ */
+HW_REGISTER_0_INDEXED(HW_TIMROT_TIMCOUNTn, REGS_TIMROT_BASE, 0x00000030,
+ 0x20)
+#define BP_TIMROT_TIMCOUNTn_RUNNING_COUNT 16
+#define BM_TIMROT_TIMCOUNTn_RUNNING_COUNT 0xFFFF0000
+#define BF_TIMROT_TIMCOUNTn_RUNNING_COUNT(v) \
+ (((v) << 16) & BM_TIMROT_TIMCOUNTn_RUNNING_COUNT)
+#define BP_TIMROT_TIMCOUNTn_FIXED_COUNT 0
+#define BM_TIMROT_TIMCOUNTn_FIXED_COUNT 0x0000FFFF
+#define BF_TIMROT_TIMCOUNTn_FIXED_COUNT(v) \
+ (((v) << 0) & BM_TIMROT_TIMCOUNTn_FIXED_COUNT)
+HW_REGISTER(HW_TIMROT_TIMCTRL3, REGS_TIMROT_BASE, 0x00000080)
+#define HW_TIMROT_TIMCTRL3_ADDR (REGS_TIMROT_BASE + 0x00000080)
+#define BP_TIMROT_TIMCTRL3_TEST_SIGNAL 16
+#define BM_TIMROT_TIMCTRL3_TEST_SIGNAL 0x000F0000
+#define BF_TIMROT_TIMCTRL3_TEST_SIGNAL(v) \
+ (((v) << 16) & BM_TIMROT_TIMCTRL3_TEST_SIGNAL)
+#define BV_TIMROT_TIMCTRL3_TEST_SIGNAL__NEVER_TICK 0x0
+#define BV_TIMROT_TIMCTRL3_TEST_SIGNAL__PWM0 0x1
+#define BV_TIMROT_TIMCTRL3_TEST_SIGNAL__PWM1 0x2
+#define BV_TIMROT_TIMCTRL3_TEST_SIGNAL__PWM2 0x3
+#define BV_TIMROT_TIMCTRL3_TEST_SIGNAL__PWM3 0x4
+#define BV_TIMROT_TIMCTRL3_TEST_SIGNAL__PWM4 0x5
+#define BV_TIMROT_TIMCTRL3_TEST_SIGNAL__ROTARYA 0x6
+#define BV_TIMROT_TIMCTRL3_TEST_SIGNAL__ROTARYB 0x7
+#define BV_TIMROT_TIMCTRL3_TEST_SIGNAL__32KHZ_XTAL 0x8
+#define BV_TIMROT_TIMCTRL3_TEST_SIGNAL__8KHZ_XTAL 0x9
+#define BV_TIMROT_TIMCTRL3_TEST_SIGNAL__4KHZ_XTAL 0xA
+#define BV_TIMROT_TIMCTRL3_TEST_SIGNAL__1KHZ_XTAL 0xB
+#define BV_TIMROT_TIMCTRL3_TEST_SIGNAL__TICK_ALWAYS 0xC
+#define BM_TIMROT_TIMCTRL3_IRQ 0x00008000
+#define BM_TIMROT_TIMCTRL3_IRQ_EN 0x00004000
+#define BM_TIMROT_TIMCTRL3_DUTY_VALID 0x00000400
+#define BM_TIMROT_TIMCTRL3_DUTY_CYCLE 0x00000200
+#define BM_TIMROT_TIMCTRL3_POLARITY 0x00000100
+#define BM_TIMROT_TIMCTRL3_UPDATE 0x00000080
+#define BM_TIMROT_TIMCTRL3_RELOAD 0x00000040
+#define BP_TIMROT_TIMCTRL3_PRESCALE 4
+#define BM_TIMROT_TIMCTRL3_PRESCALE 0x00000030
+#define BF_TIMROT_TIMCTRL3_PRESCALE(v) \
+ (((v) << 4) & BM_TIMROT_TIMCTRL3_PRESCALE)
+#define BV_TIMROT_TIMCTRL3_PRESCALE__DIV_BY_1 0x0
+#define BV_TIMROT_TIMCTRL3_PRESCALE__DIV_BY_2 0x1
+#define BV_TIMROT_TIMCTRL3_PRESCALE__DIV_BY_4 0x2
+#define BV_TIMROT_TIMCTRL3_PRESCALE__DIV_BY_8 0x3
+#define BP_TIMROT_TIMCTRL3_SELECT 0
+#define BM_TIMROT_TIMCTRL3_SELECT 0x0000000F
+#define BF_TIMROT_TIMCTRL3_SELECT(v) \
+ (((v) << 0) & BM_TIMROT_TIMCTRL3_SELECT)
+#define BV_TIMROT_TIMCTRL3_SELECT__NEVER_TICK 0x0
+#define BV_TIMROT_TIMCTRL3_SELECT__PWM0 0x1
+#define BV_TIMROT_TIMCTRL3_SELECT__PWM1 0x2
+#define BV_TIMROT_TIMCTRL3_SELECT__PWM2 0x3
+#define BV_TIMROT_TIMCTRL3_SELECT__PWM3 0x4
+#define BV_TIMROT_TIMCTRL3_SELECT__PWM4 0x5
+#define BV_TIMROT_TIMCTRL3_SELECT__ROTARYA 0x6
+#define BV_TIMROT_TIMCTRL3_SELECT__ROTARYB 0x7
+#define BV_TIMROT_TIMCTRL3_SELECT__32KHZ_XTAL 0x8
+#define BV_TIMROT_TIMCTRL3_SELECT__8KHZ_XTAL 0x9
+#define BV_TIMROT_TIMCTRL3_SELECT__4KHZ_XTAL 0xA
+#define BV_TIMROT_TIMCTRL3_SELECT__1KHZ_XTAL 0xB
+#define BV_TIMROT_TIMCTRL3_SELECT__TICK_ALWAYS 0xC
+HW_REGISTER_0(HW_TIMROT_TIMCOUNT3, REGS_TIMROT_BASE, 0x00000090)
+#define HW_TIMROT_TIMCOUNT3_ADDR (REGS_TIMROT_BASE + 0x00000090)
+#define BP_TIMROT_TIMCOUNT3_LOW_RUNNING_COUNT 16
+#define BM_TIMROT_TIMCOUNT3_LOW_RUNNING_COUNT 0xFFFF0000
+#define BF_TIMROT_TIMCOUNT3_LOW_RUNNING_COUNT(v) \
+ (((v) << 16) & BM_TIMROT_TIMCOUNT3_LOW_RUNNING_COUNT)
+#define BP_TIMROT_TIMCOUNT3_HIGH_FIXED_COUNT 0
+#define BM_TIMROT_TIMCOUNT3_HIGH_FIXED_COUNT 0x0000FFFF
+#define BF_TIMROT_TIMCOUNT3_HIGH_FIXED_COUNT(v) \
+ (((v) << 0) & BM_TIMROT_TIMCOUNT3_HIGH_FIXED_COUNT)
+HW_REGISTER_0(HW_TIMROT_VERSION, REGS_TIMROT_BASE, 0x000000a0)
+#define HW_TIMROT_VERSION_ADDR (REGS_TIMROT_BASE + 0x000000a0)
+#define BP_TIMROT_VERSION_MAJOR 24
+#define BM_TIMROT_VERSION_MAJOR 0xFF000000
+#define BF_TIMROT_VERSION_MAJOR(v) \
+ (((v) << 24) & BM_TIMROT_VERSION_MAJOR)
+#define BP_TIMROT_VERSION_MINOR 16
+#define BM_TIMROT_VERSION_MINOR 0x00FF0000
+#define BF_TIMROT_VERSION_MINOR(v) \
+ (((v) << 16) & BM_TIMROT_VERSION_MINOR)
+#define BP_TIMROT_VERSION_STEP 0
+#define BM_TIMROT_VERSION_STEP 0x0000FFFF
+#define BF_TIMROT_VERSION_STEP(v) \
+ (((v) << 0) & BM_TIMROT_VERSION_STEP)
+#endif /* __ARCH_ARM___TIMROT_H */
diff --git a/arch/arm/mach-stmp378x/stmp378x.c b/arch/arm/mach-stmp378x/stmp378x.c
new file mode 100644
index 000000000000..f156ec7306c0
--- /dev/null
+++ b/arch/arm/mach-stmp378x/stmp378x.c
@@ -0,0 +1,225 @@
+/*
+ * Freescale STMP378X platform support
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+
+#include <asm/dma.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+
+#include <mach/pins.h>
+#include <mach/pinmux.h>
+#include <mach/dma.h>
+#include <mach/hardware.h>
+#include <mach/system.h>
+#include <mach/platform.h>
+#include <mach/stmp3xxx.h>
+#include <mach/regs-icoll.h>
+#include <mach/regs-apbh.h>
+#include <mach/regs-apbx.h>
+
+#include "stmp378x.h"
+/*
+ * IRQ handling
+ */
+static void stmp378x_ack_irq(unsigned int irq)
+{
+ /* Tell ICOLL to release IRQ line */
+ HW_ICOLL_VECTOR_WR(0x0);
+
+ /* ACK current interrupt */
+ HW_ICOLL_LEVELACK_WR(BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0);
+
+ /* Barrier */
+ (void) HW_ICOLL_STAT_RD();
+}
+
+static void stmp378x_mask_irq(unsigned int irq)
+{
+ /* IRQ disable */
+ HW_ICOLL_INTERRUPTn_CLR(irq, BM_ICOLL_INTERRUPTn_ENABLE);
+}
+
+static void stmp378x_unmask_irq(unsigned int irq)
+{
+ /* IRQ enable */
+ HW_ICOLL_INTERRUPTn_SET(irq, BM_ICOLL_INTERRUPTn_ENABLE);
+}
+
+static struct irq_chip stmp378x_chip = {
+ .ack = stmp378x_ack_irq,
+ .mask = stmp378x_mask_irq,
+ .unmask = stmp378x_unmask_irq,
+};
+
+void __init stmp378x_init_irq(void)
+{
+ stmp3xxx_init_irq(&stmp378x_chip);
+}
+
+/*
+ * DMA interrupt handling
+ */
+void stmp3xxx_arch_dma_enable_interrupt(int channel)
+{
+ int dmabus = channel / 16;
+
+ switch (dmabus) {
+ case STMP3XXX_BUS_APBH:
+ HW_APBH_CTRL1_SET(1 << (16 + (channel % 16)));
+ HW_APBH_CTRL2_SET(1 << (16 + (channel % 16)));
+ break;
+
+ case STMP3XXX_BUS_APBX:
+ HW_APBX_CTRL1_SET(1 << (16 + (channel % 16)));
+ HW_APBX_CTRL2_SET(1 << (16 + (channel % 16)));
+ break;
+ }
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_enable_interrupt);
+
+void stmp3xxx_arch_dma_clear_interrupt(int channel)
+{
+ int dmabus = channel / 16;
+
+ switch (dmabus) {
+ case STMP3XXX_BUS_APBH:
+ HW_APBH_CTRL1_CLR(1 << (channel % 16));
+ HW_APBH_CTRL2_CLR(1 << (channel % 16));
+ break;
+
+ case STMP3XXX_BUS_APBX:
+ HW_APBX_CTRL1_CLR(1 << (channel % 16));
+ HW_APBX_CTRL2_CLR(1 << (channel % 16));
+ break;
+ }
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_clear_interrupt);
+
+int stmp3xxx_arch_dma_is_interrupt(int channel)
+{
+ int dmabus = channel / 16;
+ int r = 0;
+
+ switch (dmabus) {
+ case STMP3XXX_BUS_APBH:
+ r = HW_APBH_CTRL1_RD() & (1 << (channel % 16));
+ break;
+
+ case STMP3XXX_BUS_APBX:
+ r = HW_APBX_CTRL1_RD() & (1 << (channel % 16));
+ break;
+ }
+ return r;
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_is_interrupt);
+
+void stmp3xxx_arch_dma_reset_channel(int channel)
+{
+ int dmabus = channel / 16;
+ unsigned chbit = 1 << (channel % 16);
+
+ switch (dmabus) {
+ case STMP3XXX_BUS_APBH:
+ /* Reset channel and wait for it to complete */
+ HW_APBH_CTRL0_SET(chbit <<
+ BP_APBH_CTRL0_RESET_CHANNEL);
+ while (HW_APBH_CTRL0_RD() &
+ (chbit << BP_APBH_CTRL0_RESET_CHANNEL))
+ continue;
+ break;
+
+ case STMP3XXX_BUS_APBX:
+ /* Reset channel and wait for it to complete */
+ HW_APBX_CHANNEL_CTRL_SET(
+ BF_APBX_CHANNEL_CTRL_RESET_CHANNEL(chbit));
+ while (HW_APBX_CHANNEL_CTRL_RD() &
+ BF_APBX_CHANNEL_CTRL_RESET_CHANNEL(chbit))
+ continue;
+ break;
+ }
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_reset_channel);
+
+void stmp3xxx_arch_dma_freeze(int channel)
+{
+ int dmabus = channel / 16;
+ unsigned chbit = 1 << (channel % 16);
+
+ switch (dmabus) {
+ case STMP3XXX_BUS_APBH:
+ HW_APBH_CTRL0_SET(1<<chbit);
+ break;
+ case STMP3XXX_BUS_APBX:
+ HW_APBX_CHANNEL_CTRL_SET(1<<chbit);
+ break;
+ }
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_freeze);
+
+void stmp3xxx_arch_dma_unfreeze(int channel)
+{
+ int dmabus = channel / 16;
+ unsigned chbit = 1 << (channel % 16);
+
+ switch (dmabus) {
+ case STMP3XXX_BUS_APBH:
+ HW_APBH_CTRL0_CLR(1<<chbit);
+ break;
+ case STMP3XXX_BUS_APBX:
+ HW_APBX_CHANNEL_CTRL_CLR(1<<chbit);
+ break;
+ }
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_unfreeze);
+
+/*
+ * The registers are all very closely mapped, so we might as well map them all
+ * with a single mapping
+ *
+ * Logical Physical
+ * f0000000 80000000 On-chip registers
+ * f1000000 00000000 256k on-chip SRAM
+ */
+
+static struct map_desc stmp378x_io_desc[] __initdata = {
+ {
+ .virtual = (u32)STMP3XXX_REGS_BASE,
+ .pfn = __phys_to_pfn(STMP3XXX_REGS_PHBASE),
+ .length = STMP3XXX_REGS_SIZE,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = (u32)STMP3XXX_OCRAM_BASE,
+ .pfn = __phys_to_pfn(STMP3XXX_OCRAM_PHBASE),
+ .length = STMP3XXX_OCRAM_SIZE,
+ .type = MT_DEVICE,
+ },
+};
+
+void __init stmp378x_map_io(void)
+{
+ iotable_init(stmp378x_io_desc, ARRAY_SIZE(stmp378x_io_desc));
+}
diff --git a/arch/arm/mach-stmp378x/stmp378x.h b/arch/arm/mach-stmp378x/stmp378x.h
new file mode 100644
index 000000000000..473de64cf8f7
--- /dev/null
+++ b/arch/arm/mach-stmp378x/stmp378x.h
@@ -0,0 +1,24 @@
+/*
+ * Freescale STMP37XX/STMP378X internal functions and data declarations
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __MACH_STMP378X_H
+#define __MACH_STMP378X_H
+
+void stmp378x_map_io(void);
+void stmp378x_init_irq(void);
+
+#endif /* __MACH_STMP378X_COMMON_H */
diff --git a/arch/arm/mach-stmp378x/stmp378x_devb.c b/arch/arm/mach-stmp378x/stmp378x_devb.c
new file mode 100644
index 000000000000..bc643f686b11
--- /dev/null
+++ b/arch/arm/mach-stmp378x/stmp378x_devb.c
@@ -0,0 +1,80 @@
+/*
+ * Freescale STMP378X development board support
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/pins.h>
+#include <mach/pinmux.h>
+#include <mach/stmp3xxx.h>
+
+#include "stmp378x.h"
+
+static struct platform_device *devices[] = {
+ &stmp3xxx_dbguart,
+};
+
+static struct pin_desc dbguart_pins_0[] = {
+ { PINID_PWM0, PIN_FUN3, },
+ { PINID_PWM1, PIN_FUN3, },
+};
+
+static struct pin_group dbguart_pins[] = {
+ [0] = {
+ .pins = dbguart_pins_0,
+ .nr_pins = ARRAY_SIZE(dbguart_pins_0),
+ },
+};
+
+static int dbguart_pins_control(int id, int request)
+{
+ int r = 0;
+
+ if (request)
+ r = stmp3xxx_request_pin_group(&dbguart_pins[id], "debug uart");
+ else
+ stmp3xxx_release_pin_group(&dbguart_pins[id], "debug uart");
+ return r;
+}
+
+static void __init stmp378x_devb_init(void)
+{
+ stmp3xxx_pinmux_init(NR_REAL_IRQS);
+
+ /* init stmp3xxx platform */
+ stmp3xxx_init();
+
+ stmp3xxx_dbguart.dev.platform_data = dbguart_pins_control;
+
+ /* add board's devices */
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+MACHINE_START(STMP378X, "STMP378X")
+ .phys_io = 0x80000000,
+ .io_pg_offst = ((0xf0000000) >> 18) & 0xfffc,
+ .boot_params = 0x40000100,
+ .map_io = stmp378x_map_io,
+ .init_irq = stmp378x_init_irq,
+ .timer = &stmp3xxx_timer,
+ .init_machine = stmp378x_devb_init,
+MACHINE_END
diff --git a/arch/arm/mach-stmp37xx/Makefile b/arch/arm/mach-stmp37xx/Makefile
new file mode 100644
index 000000000000..57deffd09fbf
--- /dev/null
+++ b/arch/arm/mach-stmp37xx/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_ARCH_STMP37XX) += stmp37xx.o
+obj-$(CONFIG_MACH_STMP37XX) += stmp37xx_devb.o
diff --git a/arch/arm/mach-stmp37xx/Makefile.boot b/arch/arm/mach-stmp37xx/Makefile.boot
new file mode 100644
index 000000000000..1568ad404d59
--- /dev/null
+++ b/arch/arm/mach-stmp37xx/Makefile.boot
@@ -0,0 +1,3 @@
+ zreladdr-y := 0x40008000
+params_phys-y := 0x40000100
+initrd_phys-y := 0x40800000
diff --git a/arch/arm/mach-stmp37xx/include/mach/entry-macro.S b/arch/arm/mach-stmp37xx/include/mach/entry-macro.S
new file mode 100644
index 000000000000..fed2787b6c34
--- /dev/null
+++ b/arch/arm/mach-stmp37xx/include/mach/entry-macro.S
@@ -0,0 +1,37 @@
+/*
+ * Low-level IRQ helper macros for Freescale STMP37XX
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+ mov \base, #0xf0000000 @ vm address of IRQ controller
+ ldr \irqnr, [\base, #0x30] @ HW_ICOLL_STAT
+ cmp \irqnr, #0x3f
+ movne \irqstat, #0 @ Ack this IRQ
+ strne \irqstat, [\base, #0x00]@ HW_ICOLL_VECTOR
+ moveqs \irqnr, #0 @ Zero flag set for no IRQ
+
+ .endm
+
+ .macro get_irqnr_preamble, base, tmp
+ .endm
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
diff --git a/arch/arm/mach-stmp37xx/include/mach/irqs.h b/arch/arm/mach-stmp37xx/include/mach/irqs.h
new file mode 100644
index 000000000000..98f12938550d
--- /dev/null
+++ b/arch/arm/mach-stmp37xx/include/mach/irqs.h
@@ -0,0 +1,99 @@
+/*
+ * Freescale STMP37XX interrupts
+ *
+ * Copyright (C) 2005 Sigmatel Inc
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef _ASM_ARCH_IRQS_H
+#define _ASM_ARCH_IRQS_H
+
+#define IRQ_DEBUG_UART 0
+#define IRQ_COMMS_RX 1
+#define IRQ_COMMS_TX 1
+#define IRQ_SSP2_ERROR 2
+#define IRQ_VDD5V 3
+#define IRQ_HEADPHONE_SHORT 4
+#define IRQ_DAC_DMA 5
+#define IRQ_DAC_ERROR 6
+#define IRQ_ADC_DMA 7
+#define IRQ_ADC_ERROR 8
+#define IRQ_SPDIF_DMA 9
+#define IRQ_SAIF2_DMA 9
+#define IRQ_SPDIF_ERROR 10
+#define IRQ_SAIF1_IRQ 10
+#define IRQ_SAIF2_IRQ 10
+#define IRQ_USB_CTRL 11
+#define IRQ_USB_WAKEUP 12
+#define IRQ_GPMI_DMA 13
+#define IRQ_SSP1_DMA 14
+#define IRQ_SSP_ERROR 15
+#define IRQ_GPIO0 16
+#define IRQ_GPIO1 17
+#define IRQ_GPIO2 18
+#define IRQ_SAIF1_DMA 19
+#define IRQ_SSP2_DMA 20
+#define IRQ_ECC8_IRQ 21
+#define IRQ_RTC_ALARM 22
+#define IRQ_UARTAPP_TX_DMA 23
+#define IRQ_UARTAPP_INTERNAL 24
+#define IRQ_UARTAPP_RX_DMA 25
+#define IRQ_I2C_DMA 26
+#define IRQ_I2C_ERROR 27
+#define IRQ_TIMER0 28
+#define IRQ_TIMER1 29
+#define IRQ_TIMER2 30
+#define IRQ_TIMER3 31
+#define IRQ_BATT_BRNOUT 32
+#define IRQ_VDDD_BRNOUT 33
+#define IRQ_VDDIO_BRNOUT 34
+#define IRQ_VDD18_BRNOUT 35
+#define IRQ_TOUCH_DETECT 36
+#define IRQ_LRADC_CH0 37
+#define IRQ_LRADC_CH1 38
+#define IRQ_LRADC_CH2 39
+#define IRQ_LRADC_CH3 40
+#define IRQ_LRADC_CH4 41
+#define IRQ_LRADC_CH5 42
+#define IRQ_LRADC_CH6 43
+#define IRQ_LRADC_CH7 44
+#define IRQ_LCDIF_DMA 45
+#define IRQ_LCDIF_ERROR 46
+#define IRQ_DIGCTL_DEBUG_TRAP 47
+#define IRQ_RTC_1MSEC 48
+#define IRQ_DRI_DMA 49
+#define IRQ_DRI_ATTENTION 50
+#define IRQ_GPMI_ATTENTION 51
+#define IRQ_IR 52
+#define IRQ_DCP_VMI 53
+#define IRQ_DCP 54
+#define IRQ_RESERVED_55 55
+#define IRQ_RESERVED_56 56
+#define IRQ_RESERVED_57 57
+#define IRQ_RESERVED_58 58
+#define IRQ_RESERVED_59 59
+#define SW_IRQ_60 60
+#define SW_IRQ_61 61
+#define SW_IRQ_62 62
+#define SW_IRQ_63 63
+
+#define NR_REAL_IRQS 64
+#define NR_IRQS (NR_REAL_IRQS + 32 * 3)
+
+/* TIMER and BRNOUT are FIQ capable */
+#define FIQ_START IRQ_TIMER0
+
+/* Hard disk IRQ is a GPMI attention IRQ */
+#define IRQ_HARDDISK IRQ_GPMI_ATTENTION
+
+#endif /* _ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-stmp37xx/include/mach/pins.h b/arch/arm/mach-stmp37xx/include/mach/pins.h
new file mode 100644
index 000000000000..d56de0c471d8
--- /dev/null
+++ b/arch/arm/mach-stmp37xx/include/mach/pins.h
@@ -0,0 +1,147 @@
+/*
+ * Freescale STMP37XX SoC pin multiplexing
+ *
+ * Author: Vladislav Buzov <vbuzov@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_ARCH_PINS_H
+#define __ASM_ARCH_PINS_H
+
+/*
+ * Define all STMP37XX pins, a pin name corresponds to a STMP37xx hardware
+ * interface this pin belongs to.
+ */
+
+/* Bank 0 */
+#define PINID_GPMI_D00 STMP3XXX_PINID(0, 0)
+#define PINID_GPMI_D01 STMP3XXX_PINID(0, 1)
+#define PINID_GPMI_D02 STMP3XXX_PINID(0, 2)
+#define PINID_GPMI_D03 STMP3XXX_PINID(0, 3)
+#define PINID_GPMI_D04 STMP3XXX_PINID(0, 4)
+#define PINID_GPMI_D05 STMP3XXX_PINID(0, 5)
+#define PINID_GPMI_D06 STMP3XXX_PINID(0, 6)
+#define PINID_GPMI_D07 STMP3XXX_PINID(0, 7)
+#define PINID_GPMI_D08 STMP3XXX_PINID(0, 8)
+#define PINID_GPMI_D09 STMP3XXX_PINID(0, 9)
+#define PINID_GPMI_D10 STMP3XXX_PINID(0, 10)
+#define PINID_GPMI_D11 STMP3XXX_PINID(0, 11)
+#define PINID_GPMI_D12 STMP3XXX_PINID(0, 12)
+#define PINID_GPMI_D13 STMP3XXX_PINID(0, 13)
+#define PINID_GPMI_D14 STMP3XXX_PINID(0, 14)
+#define PINID_GPMI_D15 STMP3XXX_PINID(0, 15)
+#define PINID_GPMI_A0 STMP3XXX_PINID(0, 16)
+#define PINID_GPMI_A1 STMP3XXX_PINID(0, 17)
+#define PINID_GPMI_A2 STMP3XXX_PINID(0, 18)
+#define PINID_GPMI_RDY0 STMP3XXX_PINID(0, 19)
+#define PINID_GPMI_RDY2 STMP3XXX_PINID(0, 20)
+#define PINID_GPMI_RDY3 STMP3XXX_PINID(0, 21)
+#define PINID_GPMI_RESETN STMP3XXX_PINID(0, 22)
+#define PINID_GPMI_IRQ STMP3XXX_PINID(0, 23)
+#define PINID_GPMI_WRN STMP3XXX_PINID(0, 24)
+#define PINID_GPMI_RDN STMP3XXX_PINID(0, 25)
+#define PINID_UART2_CTS STMP3XXX_PINID(0, 26)
+#define PINID_UART2_RTS STMP3XXX_PINID(0, 27)
+#define PINID_UART2_RX STMP3XXX_PINID(0, 28)
+#define PINID_UART2_TX STMP3XXX_PINID(0, 29)
+
+/* Bank 1 */
+#define PINID_LCD_D00 STMP3XXX_PINID(1, 0)
+#define PINID_LCD_D01 STMP3XXX_PINID(1, 1)
+#define PINID_LCD_D02 STMP3XXX_PINID(1, 2)
+#define PINID_LCD_D03 STMP3XXX_PINID(1, 3)
+#define PINID_LCD_D04 STMP3XXX_PINID(1, 4)
+#define PINID_LCD_D05 STMP3XXX_PINID(1, 5)
+#define PINID_LCD_D06 STMP3XXX_PINID(1, 6)
+#define PINID_LCD_D07 STMP3XXX_PINID(1, 7)
+#define PINID_LCD_D08 STMP3XXX_PINID(1, 8)
+#define PINID_LCD_D09 STMP3XXX_PINID(1, 9)
+#define PINID_LCD_D10 STMP3XXX_PINID(1, 10)
+#define PINID_LCD_D11 STMP3XXX_PINID(1, 11)
+#define PINID_LCD_D12 STMP3XXX_PINID(1, 12)
+#define PINID_LCD_D13 STMP3XXX_PINID(1, 13)
+#define PINID_LCD_D14 STMP3XXX_PINID(1, 14)
+#define PINID_LCD_D15 STMP3XXX_PINID(1, 15)
+#define PINID_LCD_RESET STMP3XXX_PINID(1, 16)
+#define PINID_LCD_RS STMP3XXX_PINID(1, 17)
+#define PINID_LCD_WR_RWN STMP3XXX_PINID(1, 18)
+#define PINID_LCD_RD_E STMP3XXX_PINID(1, 19)
+#define PINID_LCD_CS STMP3XXX_PINID(1, 20)
+#define PINID_LCD_BUSY STMP3XXX_PINID(1, 21)
+#define PINID_SSP1_CMD STMP3XXX_PINID(1, 22)
+#define PINID_SSP1_SCK STMP3XXX_PINID(1, 23)
+#define PINID_SSP1_DATA0 STMP3XXX_PINID(1, 24)
+#define PINID_SSP1_DATA1 STMP3XXX_PINID(1, 25)
+#define PINID_SSP1_DATA2 STMP3XXX_PINID(1, 26)
+#define PINID_SSP1_DATA3 STMP3XXX_PINID(1, 27)
+#define PINID_SSP1_DETECT STMP3XXX_PINID(1, 28)
+
+/* Bank 2 */
+#define PINID_PWM0 STMP3XXX_PINID(2, 0)
+#define PINID_PWM1 STMP3XXX_PINID(2, 1)
+#define PINID_PWM2 STMP3XXX_PINID(2, 2)
+#define PINID_PWM3 STMP3XXX_PINID(2, 3)
+#define PINID_PWM4 STMP3XXX_PINID(2, 4)
+#define PINID_I2C_SCL STMP3XXX_PINID(2, 5)
+#define PINID_I2C_SDA STMP3XXX_PINID(2, 6)
+#define PINID_ROTTARYA STMP3XXX_PINID(2, 7)
+#define PINID_ROTTARYB STMP3XXX_PINID(2, 8)
+#define PINID_EMI_CKE STMP3XXX_PINID(2, 9)
+#define PINID_EMI_RASN STMP3XXX_PINID(2, 10)
+#define PINID_EMI_CASN STMP3XXX_PINID(2, 11)
+#define PINID_EMI_CE0N STMP3XXX_PINID(2, 12)
+#define PINID_EMI_CE1N STMP3XXX_PINID(2, 13)
+#define PINID_EMI_CE2N STMP3XXX_PINID(2, 14)
+#define PINID_EMI_CE3N STMP3XXX_PINID(2, 15)
+#define PINID_EMI_A00 STMP3XXX_PINID(2, 16)
+#define PINID_EMI_A01 STMP3XXX_PINID(2, 17)
+#define PINID_EMI_A02 STMP3XXX_PINID(2, 18)
+#define PINID_EMI_A03 STMP3XXX_PINID(2, 19)
+#define PINID_EMI_A04 STMP3XXX_PINID(2, 20)
+#define PINID_EMI_A05 STMP3XXX_PINID(2, 21)
+#define PINID_EMI_A06 STMP3XXX_PINID(2, 22)
+#define PINID_EMI_A07 STMP3XXX_PINID(2, 23)
+#define PINID_EMI_A08 STMP3XXX_PINID(2, 24)
+#define PINID_EMI_A09 STMP3XXX_PINID(2, 25)
+#define PINID_EMI_A10 STMP3XXX_PINID(2, 26)
+#define PINID_EMI_A11 STMP3XXX_PINID(2, 27)
+#define PINID_EMI_A12 STMP3XXX_PINID(2, 28)
+#define PINID_EMI_A13 STMP3XXX_PINID(2, 29)
+#define PINID_EMI_A14 STMP3XXX_PINID(2, 30)
+#define PINID_EMI_WEN STMP3XXX_PINID(2, 31)
+
+/* Bank 3 */
+#define PINID_EMI_D00 STMP3XXX_PINID(3, 0)
+#define PINID_EMI_D01 STMP3XXX_PINID(3, 1)
+#define PINID_EMI_D02 STMP3XXX_PINID(3, 2)
+#define PINID_EMI_D03 STMP3XXX_PINID(3, 3)
+#define PINID_EMI_D04 STMP3XXX_PINID(3, 4)
+#define PINID_EMI_D05 STMP3XXX_PINID(3, 5)
+#define PINID_EMI_D06 STMP3XXX_PINID(3, 6)
+#define PINID_EMI_D07 STMP3XXX_PINID(3, 7)
+#define PINID_EMI_D08 STMP3XXX_PINID(3, 8)
+#define PINID_EMI_D09 STMP3XXX_PINID(3, 9)
+#define PINID_EMI_D10 STMP3XXX_PINID(3, 10)
+#define PINID_EMI_D11 STMP3XXX_PINID(3, 11)
+#define PINID_EMI_D12 STMP3XXX_PINID(3, 12)
+#define PINID_EMI_D13 STMP3XXX_PINID(3, 13)
+#define PINID_EMI_D14 STMP3XXX_PINID(3, 14)
+#define PINID_EMI_D15 STMP3XXX_PINID(3, 15)
+#define PINID_EMI_DQS0 STMP3XXX_PINID(3, 16)
+#define PINID_EMI_DQS1 STMP3XXX_PINID(3, 17)
+#define PINID_EMI_DQM0 STMP3XXX_PINID(3, 18)
+#define PINID_EMI_DQM1 STMP3XXX_PINID(3, 19)
+#define PINID_EMI_CLK STMP3XXX_PINID(3, 20)
+#define PINID_EMI_CLKN STMP3XXX_PINID(3, 21)
+
+#endif /* __ASM_ARCH_PINS_H */
diff --git a/arch/arm/mach-stmp37xx/include/mach/regs-apbh.h b/arch/arm/mach-stmp37xx/include/mach/regs-apbh.h
new file mode 100644
index 000000000000..3044c20ad90c
--- /dev/null
+++ b/arch/arm/mach-stmp37xx/include/mach/regs-apbh.h
@@ -0,0 +1,102 @@
+/*
+ * STMP APBH Register Definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef _INCLUDE_ASM_ARCH_REGS_APBH_H
+#define _INCLUDE_ASM_ARCH_REGS_APBH_H
+
+#include <mach/stmp3xxx_regs.h>
+
+#ifndef REGS_APBH_BASE
+#define REGS_APBH_BASE (REGS_BASE + 0x00004000)
+#endif
+
+HW_REGISTER(HW_APBH_CTRL0, REGS_APBH_BASE, 0x00)
+#define BP_APBH_CTRL0_SFTRST 31
+#define BM_APBH_CTRL0_SFTRST 0x80000000
+#define BP_APBH_CTRL0_CLKGATE 30
+#define BM_APBH_CTRL0_CLKGATE 0x40000000
+#define BP_APBH_CTRL0_RESET_CHANNEL 16
+#define BM_APBH_CTRL0_RESET_CHANNEL 0x00FF0000
+#define BF_APBH_CTRL0_RESET_CHANNEL(v) \
+ (((v) << BP_APBH_CTRL0_RESET_CHANNEL) & BM_APBH_CTRL0_RESET_CHANNEL)
+HW_REGISTER(HW_APBH_CTRL1, REGS_APBH_BASE, 0x10)
+#define BP_APBH_CTRL1_CH1_CMDCMPLT_IRQ_EN 9
+#define BM_APBH_CTRL1_CH1_CMDCMPLT_IRQ_EN 0x00000200
+#define BP_APBH_CTRL1_CH0_CMDCMPLT_IRQ_EN 8
+#define BM_APBH_CTRL1_CH0_CMDCMPLT_IRQ_EN 0x00000100
+#define BP_APBH_CTRL1_CH7_CMDCMPLT_IRQ 7
+#define BM_APBH_CTRL1_CH7_CMDCMPLT_IRQ 0x00000080
+#define BP_APBH_CTRL1_CH1_CMDCMPLT_IRQ 1
+#define BM_APBH_CTRL1_CH1_CMDCMPLT_IRQ 0x00000002
+#define BP_APBH_CTRL1_CH0_CMDCMPLT_IRQ 0
+#define BM_APBH_CTRL1_CH0_CMDCMPLT_IRQ 0x00000001
+#define BP_APBH_CTRL1_CH1_ERR_IRQ 17
+#define BM_APBH_CTRL1_CH1_ERR_IRQ 0x00020000
+HW_REGISTER_0(HW_APBH_DEVSEL, REGS_APBH_BASE, 0x20)
+HW_REGISTER_RO_INDEXED(HW_APBH_CHn_CURCMDAR, REGS_APBH_BASE, 0x40, 0x70)
+HW_REGISTER_0_INDEXED(HW_APBH_CHn_NXTCMDAR, REGS_APBH_BASE, 0x50, 0x70)
+#define BP_APBH_CHn_NXTCMDAR_CMD_ADDR 0
+#define BM_APBH_CHn_NXTCMDAR_CMD_ADDR 0xFFFFFFFF
+#define BF_APBH_CHn_NXTCMDAR_CMD_ADDR(v) ((u32) v)
+HW_REGISTER_RO_INDEXED(HW_APBH_CHn_CMD, REGS_APBH_BASE, 0x60, 0x70)
+#define BM_APBH_CHn_CMD_XFER_COUNT 0xFFFF0000
+#define BP_APBH_CHn_CMD_XFER_COUNT 16
+#define BF_APBH_CHn_CMD_XFER_COUNT(v) \
+ (((v) << BP_APBH_CHn_CMD_XFER_COUNT) & BM_APBH_CHn_CMD_XFER_COUNT)
+#define BM_APBH_CHn_CMD_CMDWORDS 0x0000F000
+#define BP_APBH_CHn_CMD_CMDWORDS 12
+#define BF_APBH_CHn_CMD_CMDWORDS(v) \
+ (((v) << BP_APBH_CHn_CMD_CMDWORDS) & BM_APBH_CHn_CMD_CMDWORDS)
+#define BM_APBH_CHn_CMD_WAIT4ENDCMD 0x00000080
+#define BM_APBH_CHn_CMD_SEMAPHORE 0x00000040
+#define BP_APBH_CHn_CMD_SEMAPHORE 6
+#define BF_APBH_CHn_CMD_SEMAPHORE(v) \
+ (((v) << BP_APBH_CHn_CMD_SEMAPHORE) & BM_APBH_CHn_CMD_SEMAPHORE)
+#define BM_APBH_CHn_CMD_NANDWAIT4READY 0x00000020
+#define BP_APBH_CHn_CMD_NANDLOCK 4
+#define BM_APBH_CHn_CMD_NANDLOCK 0x00000010
+#define BF_APBH_CHn_CMD_NANDLOCK(v) \
+ (((v) << BP_APBH_CHn_CMD_NANDLOCK) & BM_APBH_CHn_CMD_NANDLOCK)
+#define BM_APBH_CHn_CMD_IRQONCMPLT 0x00000008
+#define BM_APBH_CHn_CMD_CHAIN 0x00000004
+#define BM_APBH_CHn_CMD_DMA_READ 0x00000003
+#define BP_APBH_CHn_CMD_DMA_READ 0
+#define BF_APBH_CHn_CMD_DMA_READ(v) \
+ (((v) << BP_APBH_CHn_CMD_DMA_READ) & BM_APBH_CHn_CMD_DMA_READ)
+#define BF_APBH_CHn_CMD_COMMAND(v) \
+ (((v) << BP_APBH_CHn_CMD_DMA_READ) & BM_APBH_CHn_CMD_DMA_READ)
+#define BV_APBH_CHn_CMD_COMMAND__NO_DMA_XFER 0x0
+#define BV_APBH_CHn_CMD_COMMAND__DMA_WRITE 0x1
+#define BV_APBH_CHn_CMD_COMMAND__DMA_READ 0x2
+#define BV_APBH_CHn_CMD_COMMAND__DMA_SENSE 0x3
+HW_REGISTER_INDEXED(HW_APBH_CHn_BAR, REGS_APBH_BASE, 0x70, 0x70)
+HW_REGISTER_0_INDEXED(HW_APBH_CHn_SEMA, REGS_APBH_BASE, 0x80, 0x70)
+#define BP_APBH_CHn_SEMA_INCREMENT_SEMA 0
+#define BM_APBH_CHn_SEMA_INCREMENT_SEMA 0x000000FF
+#define BF_APBH_CHn_SEMA_INCREMENT_SEMA(v) \
+ (((v) << BP_APBH_CHn_SEMA_INCREMENT_SEMA) & \
+ BM_APBH_CHn_SEMA_INCREMENT_SEMA)
+#define BP_APBH_CHn_SEMA_PHORE 16
+#define BM_APBH_CHn_SEMA_PHORE 0x00FF0000
+HW_REGISTER_RO_INDEXED(HW_APBH_CHn_DEBUG1, REGS_APBH_BASE, 0x90, 0x70)
+HW_REGISTER_RO_INDEXED(HW_APBH_CHn_DEBUG2, REGS_APBH_BASE, 0xA0, 0x70)
+HW_REGISTER_RO(HW_APBH_VERSION, REGS_APBH_BASE, 0x3F0)
+
+#endif /* _INCLUDE_ASM_ARCH_REGS_APBH_H */
diff --git a/arch/arm/mach-stmp37xx/include/mach/regs-apbx.h b/arch/arm/mach-stmp37xx/include/mach/regs-apbx.h
new file mode 100644
index 000000000000..a14ddb97639a
--- /dev/null
+++ b/arch/arm/mach-stmp37xx/include/mach/regs-apbx.h
@@ -0,0 +1,109 @@
+/*
+ * STMP APBX Register Definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef _INCLUDE_ASM_ARCH_REGS_APBX_H
+#define _INCLUDE_ASM_ARCH_REGS_APBX_H
+
+#include <mach/stmp3xxx_regs.h>
+
+#ifndef REGS_APBX_BASE
+#define REGS_APBX_BASE (REGS_BASE + 0x00024000)
+#endif
+
+HW_REGISTER(HW_APBX_CTRL0, REGS_APBX_BASE, 0x00)
+#define BP_APBX_CTRL0_SFTRST 31
+#define BM_APBX_CTRL0_SFTRST 0x80000000
+#define BP_APBX_CTRL0_CLKGATE 30
+#define BM_APBX_CTRL0_CLKGATE 0x40000000
+#define BP_APBX_CTRL0_RESET_CHANNEL 16
+#define BM_APBX_CTRL0_RESET_CHANNEL 0x00FF0000
+#define BF_APBX_CTRL0_RESET_CHANNEL(v) \
+ (((v) << BP_APBX_CTRL0_RESET_CHANNEL) & BM_APBX_CTRL0_RESET_CHANNEL)
+HW_REGISTER(HW_APBX_CTRL1, REGS_APBX_BASE, 0x10)
+HW_REGISTER_0(HW_APBX_DEVSEL, REGS_APBX_BASE, 0x20)
+#define BP_APBX_DEVSEL_CH7 28
+#define BM_APBX_DEVSEL_CH7 0xF0000000
+#define BF_APBX_DEVSEL_CH7(v) \
+ (((v) << BP_APBX_DEVSEL_CH7) & BM_APBX_DEVSEL_CH7)
+#define BV_APBX_DEVSEL_CH7__USE_UART 0x0
+#define BV_APBX_DEVSEL_CH7__USE_IRDA 0x1
+#define BP_APBX_DEVSEL_CH6 24
+#define BM_APBX_DEVSEL_CH6 0x0F000000
+#define BF_APBX_DEVSEL_CH6(v) \
+ (((v) << BP_APBX_DEVSEL_CH6) & BM_APBX_DEVSEL_CH6)
+#define BV_APBX_DEVSEL_CH6__USE_UART 0x0
+#define BV_APBX_DEVSEL_CH6__USE_IRDA 0x1
+#define BP_APBX_CTRL1_CH7_AHB_ERROR_IRQ 23
+#define BM_APBX_CTRL1_CH7_AHB_ERROR_IRQ 0x00800000
+#define BP_APBX_CTRL1_CH6_AHB_ERROR_IRQ 22
+#define BM_APBX_CTRL1_CH6_AHB_ERROR_IRQ 0x00400000
+#define BP_APBX_CTRL1_CH7_CMDCMPLT_IRQ_EN 15
+#define BM_APBX_CTRL1_CH7_CMDCMPLT_IRQ_EN 0x00008000
+#define BP_APBX_CTRL1_CH6_CMDCMPLT_IRQ_EN 14
+#define BM_APBX_CTRL1_CH6_CMDCMPLT_IRQ_EN 0x00004000
+
+HW_REGISTER_RO_INDEXED(HW_APBX_CHn_CURCMDAR, REGS_APBX_BASE, 0x40, 0x70)
+HW_REGISTER_0_INDEXED(HW_APBX_CHn_NXTCMDAR, REGS_APBX_BASE, 0x50, 0x70)
+#define BP_APBX_CHn_NXTCMDAR_CMD_ADDR 0
+#define BM_APBX_CHn_NXTCMDAR_CMD_ADDR 0xFFFFFFFF
+#define BF_APBX_CHn_NXTCMDAR_CMD_ADDR(v) ((u32) v)
+HW_REGISTER_RO_INDEXED(HW_APBX_CHn_CMD, REGS_APBX_BASE, 0x60, 0x70)
+#define BP_APBX_CHn_CMD_XFER_COUNT 16
+#define BM_APBX_CHn_CMD_XFER_COUNT 0xFFFF0000
+#define BF_APBX_CHn_CMD_XFER_COUNT(v) \
+ (((v) << BP_APBX_CHn_CMD_XFER_COUNT) & BM_APBX_CHn_CMD_XFER_COUNT)
+#define BP_APBX_CHn_CMD_CMDWORDS 12
+#define BM_APBX_CHn_CMD_CMDWORDS 0x0000F000
+#define BF_APBX_CHn_CMD_CMDWORDS(v) \
+ (((v) << BP_APBX_CHn_CMD_CMDWORDS) & BM_APBX_CHn_CMD_CMDWORDS)
+#define BP_APBX_CHn_CMD_WAIT4ENDCMD 7
+#define BM_APBX_CHn_CMD_WAIT4ENDCMD 0x00000080
+#define BP_APBX_CHn_CMD_SEMAPHORE 6
+#define BM_APBX_CHn_CMD_SEMAPHORE 0x00000040
+#define BP_APBX_CHn_CMD_IRQONCMPLT 3
+#define BM_APBX_CHn_CMD_IRQONCMPLT 0x00000008
+#define BP_APBX_CHn_CMD_CHAIN 2
+#define BM_APBX_CHn_CMD_CHAIN 0x00000004
+#define BM_APBX_CHn_CMD_DMA_READ 0x00000003
+#define BP_APBX_CHn_CMD_DMA_READ 0
+#define BF_APBX_CHn_CMD_DMA_READ(v) \
+ (((v) << BP_APBX_CHn_CMD_DMA_READ) & BM_APBX_CHn_CMD_DMA_READ)
+#define BP_APBX_CHn_CMD_COMMAND 0
+#define BM_APBX_CHn_CMD_COMMAND 0x00000003
+#define BF_APBX_CHn_CMD_COMMAND(v) \
+ (((v) << BP_APBX_CHn_CMD_COMMAND) & BM_APBX_CHn_CMD_COMMAND)
+#define BV_APBX_CHn_CMD_COMMAND__NO_DMA_XFER 0x0
+#define BV_APBX_CHn_CMD_COMMAND__DMA_WRITE 0x1
+#define BV_APBX_CHn_CMD_COMMAND__DMA_READ 0x2
+
+HW_REGISTER_RO_INDEXED(HW_APBX_CHn_BAR, REGS_APBX_BASE, 0x70, 0x70)
+HW_REGISTER_0_INDEXED(HW_APBX_CHn_SEMA, REGS_APBX_BASE, 0x80, 0x70)
+#define BP_APBX_CHn_SEMA_INCREMENT_SEMA 0
+#define BM_APBX_CHn_SEMA_INCREMENT_SEMA 0x000000FF
+#define BF_APBX_CHn_SEMA_INCREMENT_SEMA(v) \
+ (((v) << BP_APBX_CHn_SEMA_INCREMENT_SEMA) & \
+ BM_APBX_CHn_SEMA_INCREMENT_SEMA)
+#define BP_APBX_CHn_SEMA_PHORE 16
+#define BM_APBX_CHn_SEMA_PHORE 0x00FF0000
+HW_REGISTER_RO_INDEXED(HW_APBX_CHn_DEBUG1, REGS_APBX_BASE, 0x90, 0x70)
+HW_REGISTER_RO_INDEXED(HW_APBX_CHn_DEBUG2, REGS_APBX_BASE, 0xA0, 0x70)
+HW_REGISTER_RO(HW_APBX_VERSION, REGS_APBX_BASE, 0x3F0)
+
+#endif /* _INCLUDE_ASM_ARCH_REGS_APBX_H */
diff --git a/arch/arm/mach-stmp37xx/include/mach/regs-clkctrl.h b/arch/arm/mach-stmp37xx/include/mach/regs-clkctrl.h
new file mode 100644
index 000000000000..229ee75f90d9
--- /dev/null
+++ b/arch/arm/mach-stmp37xx/include/mach/regs-clkctrl.h
@@ -0,0 +1,85 @@
+#ifndef _INCLUDE_ASM_ARCH_REGS_CLKCTRL_H
+#define _INCLUDE_ASM_ARCH_REGS_CLKCTRL_H
+
+#include <mach/stmp3xxx_regs.h>
+
+#define REGS_CLKCTRL_BASE (REGS_BASE + 0x00040000)
+
+#define HW_CLKCTRL_PLLCTRL0_ADDR (REGS_CLKCTRL_BASE + 0x00)
+HW_REGISTER(HW_CLKCTRL_PLLCTRL0, REGS_CLKCTRL_BASE, 0x00)
+#define BM_CLKCTRL_PLLCTRL0_EN_USB_CLKS 0x00040000
+#define HW_CLKCTRL_PLLCTRL1_ADDR (REGS_CLKCTRL_BASE + 0x10)
+HW_REGISTER(HW_CLKCTRL_PLLCTRL1, REGS_CLKCTRL_BASE, 0x10)
+
+#define HW_CLKCTRL_CPU_ADDR (REGS_CLKCTRL_BASE + 0x20)
+HW_REGISTER(HW_CLKCTRL_CPU, REGS_CLKCTRL_BASE, 0x20)
+#define BM_CLKCTRL_CPU_DIV_CPU 0x0000003F
+#define BF_CLKCTRL_CPU_DIV_CPU(v) \
+ (((v) << 0) & BM_CLKCTRL_CPU_DIV_CPU)
+
+#define HW_CLKCTRL_HBUS_ADDR (REGS_CLKCTRL_BASE + 0x30)
+HW_REGISTER(HW_CLKCTRL_HBUS, REGS_CLKCTRL_BASE, 0x30)
+#define BM_CLKCTRL_HBUS_DIV_FRAC_EN 0 /* for compatitibility */
+#define BM_CLKCTRL_HBUS_DIV 0x0000001F
+#define BF_CLKCTRL_HBUS_DIV(v) \
+ (((v) << 0) & BM_CLKCTRL_HBUS_DIV)
+#define HW_CLKCTRL_XBUS_ADDR (REGS_CLKCTRL_BASE + 0x40)
+HW_REGISTER(HW_CLKCTRL_XBUS, REGS_CLKCTRL_BASE, 0x40)
+#define HW_CLKCTRL_XTAL_ADDR (REGS_CLKCTRL_BASE + 0x50)
+HW_REGISTER(HW_CLKCTRL_XTAL, REGS_CLKCTRL_BASE, 0x50)
+#define HW_CLKCTRL_PIX_ADDR (REGS_CLKCTRL_BASE + 0x60)
+HW_REGISTER(HW_CLKCTRL_PIX, REGS_CLKCTRL_BASE, 0x60)
+#define BM_CLKCTRL_PIX_CLKGATE 0x80000000
+#define BM_CLKCTRL_PIX_BUSY 0x20000000
+#define BM_CLKCTRL_PIX_DIV 0x00007FFF
+#define BP_CLKCTRL_PIX_DIV 0
+#define BF_CLKCTRL_PIX_DIV(v) \
+ (((v) << BP_CLKCTRL_PIX_DIV) & BM_CLKCTRL_PIX_DIV)
+#define HW_CLKCTRL_SSP_ADDR (REGS_CLKCTRL_BASE + 0x70)
+HW_REGISTER(HW_CLKCTRL_SSP, REGS_CLKCTRL_BASE, 0x70)
+#define HW_CLKCTRL_GPMI_ADDR (REGS_CLKCTRL_BASE + 0x80)
+HW_REGISTER(HW_CLKCTRL_GPMI, REGS_CLKCTRL_BASE, 0x80)
+#define HW_CLKCTRL_SPDIF_ADDR (REGS_CLKCTRL_BASE + 0x90)
+HW_REGISTER(HW_CLKCTRL_SPDIF, REGS_CLKCTRL_BASE, 0x90)
+#define HW_CLKCTRL_EMI_ADDR (REGS_CLKCTRL_BASE + 0xA0)
+HW_REGISTER(HW_CLKCTRL_EMI, REGS_CLKCTRL_BASE, 0xA0)
+#define HW_CLKCTRL_IR_ADDR (REGS_CLKCTRL_BASE + 0xB0)
+HW_REGISTER(HW_CLKCTRL_IR, REGS_CLKCTRL_BASE, 0xB0)
+#define HW_CLKCTRL_SAIF_ADDR (REGS_CLKCTRL_BASE + 0xC0)
+HW_REGISTER(HW_CLKCTRL_SAIF, REGS_CLKCTRL_BASE, 0xC0)
+#define HW_CLKCTRL_FRAC_ADDR (REGS_CLKCTRL_BASE + 0xD0)
+HW_REGISTER(HW_CLKCTRL_FRAC, REGS_CLKCTRL_BASE, 0xD0)
+#define BM_CLKCTRL_FRAC_CLKGATEIO 0x80000000
+#define BM_CLKCTRL_FRAC_IO_STABLE 0x40000000
+#define BM_CLKCTRL_FRAC_IOFRAC 0x3F000000
+#define BP_CLKCTRL_FRAC_IOFRAC 24
+#define BF_CLKCTRL_FRAC_IOFRAC(v) \
+ (((v) << BP_CLKCTRL_FRAC_IOFRAC) & BM_CLKCTRL_FRAC_IOFRAC)
+#define BM_CLKCTRL_FRAC_CLKGATEPIX 0x00800000
+#define BM_CLKCTRL_FRAC_PIXFRAC 0x003F0000
+#define BP_CLKCTRL_FRAC_PIXFRAC 16
+#define BF_CLKCTRL_FRAC_PIXFRAC(v) \
+ (((v) << BP_CLKCTRL_FRAC_PIXFRAC) & BM_CLKCTRL_FRAC_PIXFRAC)
+#define BM_CLKCTRL_FRAC_CLKGATEEMI 0x00008000
+#define BM_CLKCTRL_FRAC_EMIFRAC 0x00003F00
+#define BP_CLKCTRL_FRAC_EMIFRAC 8
+#define BF_CLKCTRL_FRAC_EMIFRAC(v) \
+ (((v) << BP_CLKCTRL_FRAC_EMIFRAC) & BM_CLKCTRL_FRAC_EMIFRAC)
+#define BM_CLKCTRL_FRAC_CLKGATECPU 0x00000080
+#define BM_CLKCTRL_FRAC_CPUFRAC 0x0000003F
+#define BP_CLKCTRL_FRAC_CPUFRAC 0
+#define BF_CLKCTRL_FRAC_CPUFRAC(v) \
+ (((v) << BP_CLKCTRL_FRAC_CPUFRAC) & BM_CLKCTRL_FRAC_CPUFRAC)
+#define HW_CLKCTRL_CLKSEQ_ADDR (REGS_CLKCTRL_BASE + 0xE0)
+HW_REGISTER(HW_CLKCTRL_CLKSEQ, REGS_CLKCTRL_BASE, 0xE0)
+#define BM_CLKCTRL_CLKSEQ_BYPASS_CPU 0x00000080
+#define BM_CLKCTRL_CLKSEQ_BYPASS_EMI 0x00000040
+#define BM_CLKCTRL_CLKSEQ_BYPASS_SSP 0x00000020
+#define BM_CLKCTRL_CLKSEQ_BYPASS_GPMI 0x00000010
+#define BM_CLKCTRL_CLKSEQ_BYPASS_IR 0x00000008
+#define BM_CLKCTRL_CLKSEQ_BYPASS_PIX 0x00000002
+#define BM_CLKCTRL_CLKSEQ_BYPASS_SAIF 0x00000001
+HW_REGISTER_WO(HW_CLKCTRL_RESET, REGS_CLKCTRL_BASE, 0xF0)
+#define BM_CLKCTRL_RESET_CHIP 0x00000002
+#define BM_CLKCTRL_RESET_DIG 0x00000001
+#endif /* _INCLUDE_ASM_ARCH_REGS_CLKCTRL_H */
diff --git a/arch/arm/mach-stmp37xx/include/mach/regs-icoll.h b/arch/arm/mach-stmp37xx/include/mach/regs-icoll.h
new file mode 100644
index 000000000000..8a92f923f6bd
--- /dev/null
+++ b/arch/arm/mach-stmp37xx/include/mach/regs-icoll.h
@@ -0,0 +1,36 @@
+/*
+ * Freescale STMP378X: clock registers definitions
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef _INCLUDE_ASM_ARCH_REGS_ICOLL_H
+#define _INCLUDE_ASM_ARCH_REGS_ICOLL_H
+
+
+#include <mach/stmp3xxx_regs.h>
+
+#define REGS_ICOLL_BASE (REGS_BASE + 0x00000000)
+
+HW_REGISTER(HW_ICOLL_VECTOR, REGS_ICOLL_BASE, 0x00)
+HW_REGISTER_WO(HW_ICOLL_LEVELACK, REGS_ICOLL_BASE, 0x10)
+HW_REGISTER(HW_ICOLL_CTRL, REGS_ICOLL_BASE, 0x20)
+#define BM_ICOLL_CTRL_CLKGATE 0x40000000
+#define BM_ICOLL_CTRL_SFTRST 0x80000000
+HW_REGISTER_RO(HW_ICOLL_STAT, REGS_ICOLL_BASE, 0x30)
+
+HW_REGISTER_INDEXED(HW_ICOLL_PRIORITYn, REGS_ICOLL_BASE, 0x60, 0x10)
+
+#endif /* _INCLUDE_ASM_ARCH_REGS_CLKCTRL_H */
diff --git a/arch/arm/mach-stmp37xx/include/mach/regs-pinctrl.h b/arch/arm/mach-stmp37xx/include/mach/regs-pinctrl.h
new file mode 100644
index 000000000000..b114ecd9a5eb
--- /dev/null
+++ b/arch/arm/mach-stmp37xx/include/mach/regs-pinctrl.h
@@ -0,0 +1,159 @@
+/*
+ * STMP pinmux register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ *
+ * 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
+ */
+#ifndef _INCLUDE_ASM_ARCH_REGS_PINCTRL_H
+#define _INCLUDE_ASM_ARCH_REGS_PINCTRL_H
+
+#include <mach/stmp3xxx_regs.h>
+
+#ifndef REGS_PINCTRL_BASE
+#define REGS_PINCTRL_BASE (REGS_BASE + 0x00018000)
+#endif /* REGS_PINCTRL_BASE */
+
+HW_REGISTER(HW_PINCTRL_CTRL, REGS_PINCTRL_BASE, 0)
+
+#define HW_PINCTRL_MUXSEL0_ADDR (REGS_PINCTRL_BASE + 0x100)
+HW_REGISTER(HW_PINCTRL_MUXSEL0, REGS_PINCTRL_BASE, 0x100)
+#define HW_PINCTRL_MUXSEL1_ADDR (REGS_PINCTRL_BASE + 0x110)
+HW_REGISTER(HW_PINCTRL_MUXSEL1, REGS_PINCTRL_BASE, 0x110)
+#define HW_PINCTRL_MUXSEL2_ADDR (REGS_PINCTRL_BASE + 0x120)
+HW_REGISTER(HW_PINCTRL_MUXSEL2, REGS_PINCTRL_BASE, 0x120)
+#define HW_PINCTRL_MUXSEL3_ADDR (REGS_PINCTRL_BASE + 0x130)
+HW_REGISTER(HW_PINCTRL_MUXSEL3, REGS_PINCTRL_BASE, 0x130)
+#define BM_PINCTRL_MUXSEL3_BANK1_PIN28 0x03000000
+#define HW_PINCTRL_MUXSEL4_ADDR (REGS_PINCTRL_BASE + 0x140)
+HW_REGISTER(HW_PINCTRL_MUXSEL4, REGS_PINCTRL_BASE, 0x140)
+#define BM_PINCTRL_MUXSEL4_BANK2_PIN03 0x000000C0
+#define BM_PINCTRL_MUXSEL4_BANK2_PIN04 0x00000300
+#define HW_PINCTRL_MUXSEL5_ADDR (REGS_PINCTRL_BASE + 0x150)
+HW_REGISTER(HW_PINCTRL_MUXSEL5, REGS_PINCTRL_BASE, 0x150)
+#define HW_PINCTRL_MUXSEL6_ADDR (REGS_PINCTRL_BASE + 0x160)
+HW_REGISTER(HW_PINCTRL_MUXSEL6, REGS_PINCTRL_BASE, 0x160)
+#define HW_PINCTRL_MUXSEL7_ADDR (REGS_PINCTRL_BASE + 0x170)
+HW_REGISTER(HW_PINCTRL_MUXSEL7, REGS_PINCTRL_BASE, 0x170)
+
+HW_REGISTER(HW_PINCTRL_DRIVE0, REGS_PINCTRL_BASE, 0x200)
+#define HW_PINCTRL_DRIVE0_ADDR (REGS_PINCTRL_BASE + 0x200)
+HW_REGISTER(HW_PINCTRL_DRIVE1, REGS_PINCTRL_BASE, 0x210)
+#define HW_PINCTRL_DRIVE1_ADDR (REGS_PINCTRL_BASE + 0x210)
+HW_REGISTER(HW_PINCTRL_DRIVE2, REGS_PINCTRL_BASE, 0x220)
+#define HW_PINCTRL_DRIVE2_ADDR (REGS_PINCTRL_BASE + 0x220)
+HW_REGISTER(HW_PINCTRL_DRIVE3, REGS_PINCTRL_BASE, 0x230)
+#define HW_PINCTRL_DRIVE3_ADDR (REGS_PINCTRL_BASE + 0x230)
+HW_REGISTER(HW_PINCTRL_DRIVE4, REGS_PINCTRL_BASE, 0x240)
+#define HW_PINCTRL_DRIVE4_ADDR (REGS_PINCTRL_BASE + 0x240)
+HW_REGISTER(HW_PINCTRL_DRIVE5, REGS_PINCTRL_BASE, 0x250)
+#define HW_PINCTRL_DRIVE5_ADDR (REGS_PINCTRL_BASE + 0x250)
+HW_REGISTER(HW_PINCTRL_DRIVE6, REGS_PINCTRL_BASE, 0x260)
+#define HW_PINCTRL_DRIVE6_ADDR (REGS_PINCTRL_BASE + 0x260)
+HW_REGISTER(HW_PINCTRL_DRIVE7, REGS_PINCTRL_BASE, 0x270)
+#define HW_PINCTRL_DRIVE7_ADDR (REGS_PINCTRL_BASE + 0x270)
+HW_REGISTER(HW_PINCTRL_DRIVE8, REGS_PINCTRL_BASE, 0x280)
+#define HW_PINCTRL_DRIVE8_ADDR (REGS_PINCTRL_BASE + 0x280)
+HW_REGISTER(HW_PINCTRL_DRIVE9, REGS_PINCTRL_BASE, 0x290)
+#define HW_PINCTRL_DRIVE9_ADDR (REGS_PINCTRL_BASE + 0x290)
+HW_REGISTER(HW_PINCTRL_DRIVE10, REGS_PINCTRL_BASE, 0x2a0)
+#define HW_PINCTRL_DRIVE10_ADDR (REGS_PINCTRL_BASE + 0x2a0)
+HW_REGISTER(HW_PINCTRL_DRIVE11, REGS_PINCTRL_BASE, 0x2b0)
+#define HW_PINCTRL_DRIVE11_ADDR (REGS_PINCTRL_BASE + 0x2b0)
+HW_REGISTER(HW_PINCTRL_DRIVE12, REGS_PINCTRL_BASE, 0x2c0)
+#define HW_PINCTRL_DRIVE12_ADDR (REGS_PINCTRL_BASE + 0x2c0)
+HW_REGISTER(HW_PINCTRL_DRIVE13, REGS_PINCTRL_BASE, 0x2d0)
+#define HW_PINCTRL_DRIVE13_ADDR (REGS_PINCTRL_BASE + 0x2d0)
+HW_REGISTER(HW_PINCTRL_DRIVE14, REGS_PINCTRL_BASE, 0x2e0)
+#define HW_PINCTRL_DRIVE14_ADDR (REGS_PINCTRL_BASE + 0x2e0)
+
+
+HW_REGISTER(HW_PINCTRL_PULL0, REGS_PINCTRL_BASE, 0x300)
+#define HW_PINCTRL_PULL0_ADDR (REGS_PINCTRL_BASE + 0x300)
+#define BM_PINCTRL_PULL0_BANK0_PIN01 0x00000002
+#define BM_PINCTRL_PULL0_BANK0_PIN02 0x00000004
+#define BM_PINCTRL_PULL0_BANK0_PIN03 0x00000008
+#define BM_PINCTRL_PULL0_BANK0_PIN04 0x00000010
+#define BM_PINCTRL_PULL0_BANK0_PIN20 0x00100000
+HW_REGISTER(HW_PINCTRL_PULL1, REGS_PINCTRL_BASE, 0x310)
+#define HW_PINCTRL_PULL1_ADDR (REGS_PINCTRL_BASE + 0x310)
+#define BM_PINCTRL_PULL1_BANK1_PIN22 0x00400000
+#define BM_PINCTRL_PULL1_BANK1_PIN24 0x01000000
+#define BM_PINCTRL_PULL1_BANK1_PIN25 0x02000000
+#define BM_PINCTRL_PULL1_BANK1_PIN26 0x04000000
+#define BM_PINCTRL_PULL1_BANK1_PIN27 0x08000000
+HW_REGISTER(HW_PINCTRL_PULL2, REGS_PINCTRL_BASE, 0x320)
+#define HW_PINCTRL_PULL2_ADDR (REGS_PINCTRL_BASE + 0x320)
+HW_REGISTER(HW_PINCTRL_PULL3, REGS_PINCTRL_BASE, 0x330)
+#define HW_PINCTRL_PULL3_ADDR (REGS_PINCTRL_BASE + 0x330)
+
+#define HW_PINCTRL_DOUT0_ADDR (REGS_PINCTRL_BASE + 0x400)
+HW_REGISTER(HW_PINCTRL_DOUT0, REGS_PINCTRL_BASE, 0x400)
+#define HW_PINCTRL_DOUT1_ADDR (REGS_PINCTRL_BASE + 0x410)
+HW_REGISTER(HW_PINCTRL_DOUT1, REGS_PINCTRL_BASE, 0x410)
+#define HW_PINCTRL_DOUT2_ADDR (REGS_PINCTRL_BASE + 0x420)
+HW_REGISTER(HW_PINCTRL_DOUT2, REGS_PINCTRL_BASE, 0x420)
+
+#define HW_PINCTRL_DIN0_ADDR (REGS_PINCTRL_BASE + 0x500)
+HW_REGISTER_RO(HW_PINCTRL_DIN0, REGS_PINCTRL_BASE, 0x500)
+#define HW_PINCTRL_DIN1_ADDR (REGS_PINCTRL_BASE + 0x510)
+HW_REGISTER_RO(HW_PINCTRL_DIN1, REGS_PINCTRL_BASE, 0x510)
+#define HW_PINCTRL_DIN2_ADDR (REGS_PINCTRL_BASE + 0x520)
+HW_REGISTER_RO(HW_PINCTRL_DIN2, REGS_PINCTRL_BASE, 0x520)
+
+#define HW_PINCTRL_DOE0_ADDR (REGS_PINCTRL_BASE + 0x600)
+HW_REGISTER(HW_PINCTRL_DOE0, REGS_PINCTRL_BASE, 0x600)
+#define HW_PINCTRL_DOE1_ADDR (REGS_PINCTRL_BASE + 0x610)
+HW_REGISTER(HW_PINCTRL_DOE1, REGS_PINCTRL_BASE, 0x610)
+#define HW_PINCTRL_DOE2_ADDR (REGS_PINCTRL_BASE + 0x620)
+HW_REGISTER(HW_PINCTRL_DOE2, REGS_PINCTRL_BASE, 0x620)
+
+HW_REGISTER(HW_PINCTRL_PIN2IRQ0, REGS_PINCTRL_BASE, 0x700)
+#define HW_PINCTRL_PIN2IRQ0_ADDR (REGS_PINCTRL_BASE + 0x700)
+HW_REGISTER(HW_PINCTRL_PIN2IRQ1, REGS_PINCTRL_BASE, 0x710)
+#define HW_PINCTRL_PIN2IRQ1_ADDR (REGS_PINCTRL_BASE + 0x710)
+HW_REGISTER(HW_PINCTRL_PIN2IRQ2, REGS_PINCTRL_BASE, 0x720)
+#define HW_PINCTRL_PIN2IRQ2_ADDR (REGS_PINCTRL_BASE + 0x720)
+
+HW_REGISTER(HW_PINCTRL_IRQEN0, REGS_PINCTRL_BASE, 0x800)
+#define HW_PINCTRL_IRQEN0_ADDR (REGS_PINCTRL_BASE + 0x800)
+HW_REGISTER(HW_PINCTRL_IRQEN1, REGS_PINCTRL_BASE, 0x810)
+#define HW_PINCTRL_IRQEN1_ADDR (REGS_PINCTRL_BASE + 0x810)
+HW_REGISTER(HW_PINCTRL_IRQEN2, REGS_PINCTRL_BASE, 0x820)
+#define HW_PINCTRL_IRQEN2_ADDR (REGS_PINCTRL_BASE + 0x820)
+
+HW_REGISTER(HW_PINCTRL_IRQLEVEL0, REGS_PINCTRL_BASE, 0x900)
+#define HW_PINCTRL_IRQLEVEL0_ADDR (REGS_PINCTRL_BASE + 0x900)
+HW_REGISTER(HW_PINCTRL_IRQLEVEL1, REGS_PINCTRL_BASE, 0x910)
+#define HW_PINCTRL_IRQLEVEL1_ADDR (REGS_PINCTRL_BASE + 0x910)
+HW_REGISTER(HW_PINCTRL_IRQLEVEL2, REGS_PINCTRL_BASE, 0x920)
+#define HW_PINCTRL_IRQLEVEL2_ADDR (REGS_PINCTRL_BASE + 0x920)
+
+HW_REGISTER(HW_PINCTRL_IRQPOL0, REGS_PINCTRL_BASE, 0xA00)
+#define HW_PINCTRL_IRQPOL0_ADDR (REGS_PINCTRL_BASE + 0xa00)
+HW_REGISTER(HW_PINCTRL_IRQPOL1, REGS_PINCTRL_BASE, 0xA10)
+#define HW_PINCTRL_IRQPOL1_ADDR (REGS_PINCTRL_BASE + 0xa10)
+HW_REGISTER(HW_PINCTRL_IRQPOL2, REGS_PINCTRL_BASE, 0xA20)
+#define HW_PINCTRL_IRQPOL2_ADDR (REGS_PINCTRL_BASE + 0xa20)
+
+HW_REGISTER(HW_PINCTRL_IRQSTAT0, REGS_PINCTRL_BASE, 0xB00)
+#define HW_PINCTRL_IRQSTAT0_ADDR (REGS_PINCTRL_BASE + 0xb00)
+HW_REGISTER(HW_PINCTRL_IRQSTAT1, REGS_PINCTRL_BASE, 0xB10)
+#define HW_PINCTRL_IRQSTAT1_ADDR (REGS_PINCTRL_BASE + 0xb10)
+HW_REGISTER(HW_PINCTRL_IRQSTAT2, REGS_PINCTRL_BASE, 0xB20)
+#define HW_PINCTRL_IRQSTAT2_ADDR (REGS_PINCTRL_BASE + 0xb20)
+
+#endif /* _INCLUDE_ASM_ARCH_REGS_PINCTRL_H */
+
diff --git a/arch/arm/mach-stmp37xx/include/mach/regs-power.h b/arch/arm/mach-stmp37xx/include/mach/regs-power.h
new file mode 100644
index 000000000000..d15cd6601e7f
--- /dev/null
+++ b/arch/arm/mach-stmp37xx/include/mach/regs-power.h
@@ -0,0 +1,31 @@
+/*
+ * STMP POWER Register Definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ *
+ * 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
+ */
+
+#ifndef __ARCH_ARM___POWER_H
+#define __ARCH_ARM___POWER_H 1
+
+#include <mach/stmp3xxx_regs.h>
+
+#define REGS_POWER_BASE (void __iomem *)(REGS_BASE + 0x44000)
+#define REGS_POWER_BASE_PHYS (0x80044000)
+#define REGS_POWER_SIZE 0x00002000
+HW_REGISTER(HW_POWER_MINPWR, REGS_POWER_BASE, 0x00000020)
+HW_REGISTER(HW_POWER_CHARGE, REGS_POWER_BASE, 0x00000030)
+#endif /* __ARCH_ARM___POWER_H */
diff --git a/arch/arm/mach-stmp37xx/include/mach/regs-timrot.h b/arch/arm/mach-stmp37xx/include/mach/regs-timrot.h
new file mode 100644
index 000000000000..7f000306e890
--- /dev/null
+++ b/arch/arm/mach-stmp37xx/include/mach/regs-timrot.h
@@ -0,0 +1,52 @@
+/*
+ * include/asm-arm/arch-stmp3xxx/regstimer.h
+ *
+ * Copyright (c) 2008 SigmaTel Inc
+ * Copyright (c) 2008 Embedded Alley Solutions, 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
+ */
+#ifndef __ARCH_ARM_REGS_TIMROT_H
+#define __ARCH_ARM_REGS_TIMROT_H
+
+#include <mach/stmp3xxx_regs.h>
+
+#define REGS_TIMROT_BASE (REGS_BASE + 0x00068000)
+
+HW_REGISTER(HW_TIMROT_ROTCTRL, REGS_TIMROT_BASE, 0)
+#define BM_TIMROT_ROTCTRL_SFTRST 0x80000000
+#define BM_TIMROT_ROTCTRL_CLKGATE 0x40000000
+
+HW_REGISTER_INDEXED(HW_TIMROT_TIMCTRLn, REGS_TIMROT_BASE, 0x20, 0x20)
+#define BM_TIMROT_TIMCTRLn_SELECT 0x0000000F
+#define BF_TIMROT_TIMCTRLn_SELECT(v) (((v) << 0) & BM_TIMROT_TIMCTRLn_SELECT)
+#define BM_TIMROT_TIMCTRLn_PRESCALE 0x00000030
+#define BF_TIMROT_TIMCTRLn_PRESCALE(v) \
+ (((v) << 4) & BM_TIMROT_TIMCTRLn_PRESCALE)
+#define BM_TIMROT_TIMCTRLn_RELOAD 0x00000040
+#define BF_TIMROT_TIMCTRLn_RELOAD(v) (((v) << 6) & BM_TIMROT_TIMCTRLn_RELOAD)
+#define BM_TIMROT_TIMCTRLn_UPDATE 0x00000080
+#define BF_TIMROT_TIMCTRLn_UPDATE(v) (((v) << 7) & BM_TIMROT_TIMCTRLn_UPDATE)
+#define BM_TIMROT_TIMCTRLn_POLARITY 0x00000100
+#define BF_TIMROT_TIMCTRLn_POLARITY(v) \
+ (((v) << 8) & BM_TIMROT_TIMCTRLn_POLARITY)
+#define BM_TIMROT_TIMCTRLn_IRQ_EN 0x00004000
+#define BF_TIMROT_TIMCTRLn_IRQ_EN(v) \
+ (((v) << 14) & BM_TIMROT_TIMCTRLn_IRQ_EN)
+#define BM_TIMROT_TIMCTRLn_IRQ 0x00008000
+#define BF_TIMROT_TIMCTRLn_IRQ(v) (((v) << 15) & BM_TIMROT_TIMCTRLn_IRQ)
+HW_REGISTER_0_INDEXED(HW_TIMROT_TIMCOUNTn, REGS_TIMROT_BASE, 0x30, 0x20)
+
+#endif /* __ARCH_ARM_REGSTIMER_H */
diff --git a/arch/arm/mach-stmp37xx/stmp37xx.c b/arch/arm/mach-stmp37xx/stmp37xx.c
new file mode 100644
index 000000000000..83a41c90c252
--- /dev/null
+++ b/arch/arm/mach-stmp37xx/stmp37xx.c
@@ -0,0 +1,217 @@
+/*
+ * Freescale STMP37XX platform support
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+
+#include <mach/stmp3xxx.h>
+#include <mach/dma.h>
+
+#include <mach/regs-icoll.h>
+#include <mach/regs-apbh.h>
+#include <mach/regs-apbx.h>
+#include "stmp37xx.h"
+
+/*
+ * IRQ handling
+ */
+static void stmp37xx_ack_irq(unsigned int irq)
+{
+ /* Disable IRQ */
+ HW_ICOLL_PRIORITYn_CLR(irq / 4, 0x04 << ((irq % 4) * 8));
+
+ /* ACK current interrupt */
+ HW_ICOLL_LEVELACK_WR(1);
+
+ /* Barrier */
+ (void) HW_ICOLL_STAT_RD();
+}
+
+static void stmp37xx_mask_irq(unsigned int irq)
+{
+ /* IRQ disable */
+ HW_ICOLL_PRIORITYn_CLR(irq / 4, 0x04 << ((irq % 4) * 8));
+}
+
+static void stmp37xx_unmask_irq(unsigned int irq)
+{
+ /* IRQ enable */
+ HW_ICOLL_PRIORITYn_SET(irq / 4, 0x04 << ((irq % 4) * 8));
+}
+
+static struct irq_chip stmp37xx_chip = {
+ .ack = stmp37xx_ack_irq,
+ .mask = stmp37xx_mask_irq,
+ .unmask = stmp37xx_unmask_irq,
+};
+
+void __init stmp37xx_init_irq(void)
+{
+ stmp3xxx_init_irq(&stmp37xx_chip);
+}
+
+/*
+ * DMA interrupt handling
+ */
+void stmp3xxx_arch_dma_enable_interrupt(int channel)
+{
+ int dmabus = channel / 16;
+
+ switch (dmabus) {
+ case STMP3XXX_BUS_APBH:
+ HW_APBH_CTRL1_SET(1 << (8 + (channel % 16)));
+ break;
+
+ case STMP3XXX_BUS_APBX:
+ HW_APBX_CTRL1_SET(1 << (8 + (channel % 16)));
+ break;
+ }
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_enable_interrupt);
+
+void stmp3xxx_arch_dma_clear_interrupt(int channel)
+{
+ int dmabus = channel / 16;
+
+ switch (dmabus) {
+ case STMP3XXX_BUS_APBH:
+ HW_APBH_CTRL1_CLR(1 << (channel % 16));
+ break;
+
+ case STMP3XXX_BUS_APBX:
+ HW_APBX_CTRL1_CLR(1 << (channel % 16));
+ break;
+ }
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_clear_interrupt);
+
+int stmp3xxx_arch_dma_is_interrupt(int channel)
+{
+ int r = 0;
+
+ int dmabus = channel / 16;
+
+ switch (dmabus) {
+ case STMP3XXX_BUS_APBH:
+ r = HW_APBH_CTRL1_RD() & (1 << (channel % 16));
+ break;
+
+ case STMP3XXX_BUS_APBX:
+ r = HW_APBX_CTRL1_RD() & (1 << (channel % 16));
+ break;
+ }
+ return r;
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_is_interrupt);
+
+void stmp3xxx_arch_dma_reset_channel(int channel)
+{
+ int dmabus = channel / 16;
+ unsigned chbit = 1 << (channel % 16);
+
+ switch (dmabus) {
+ case STMP3XXX_BUS_APBH:
+ /* Reset channel and wait for it to complete */
+ HW_APBH_CTRL0_SET(chbit << BP_APBH_CTRL0_RESET_CHANNEL);
+ while (HW_APBH_CTRL0_RD() &
+ (chbit << BP_APBH_CTRL0_RESET_CHANNEL))
+ continue;
+ break;
+
+ case STMP3XXX_BUS_APBX:
+ /* Reset channel and wait for it to complete */
+ HW_APBX_CTRL0_SET(chbit << BP_APBX_CTRL0_RESET_CHANNEL);
+ while (HW_APBX_CTRL0_RD() &
+ (chbit << BP_APBX_CTRL0_RESET_CHANNEL))
+ continue;
+ break;
+ }
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_reset_channel);
+
+void stmp3xxx_arch_dma_freeze(int channel)
+{
+ int dmabus = channel / 16;
+ unsigned chbit = 1 << (channel % 16);
+
+ switch (dmabus) {
+ case STMP3XXX_BUS_APBH:
+ HW_APBH_CTRL0_SET(1<<chbit);
+ break;
+ case STMP3XXX_BUS_APBX:
+ HW_APBX_CTRL0_SET(1<<chbit);
+ break;
+ }
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_freeze);
+
+void stmp3xxx_arch_dma_unfreeze(int channel)
+{
+ int dmabus = channel / 16;
+ unsigned chbit = 1 << (channel % 16);
+
+ switch (dmabus) {
+ case STMP3XXX_BUS_APBH:
+ HW_APBH_CTRL0_CLR(1<<chbit);
+ break;
+ case STMP3XXX_BUS_APBX:
+ HW_APBX_CTRL0_CLR(1<<chbit);
+ break;
+ }
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_unfreeze);
+
+/*
+ * The registers are all very closely mapped, so we might as well map them all
+ * with a single mapping
+ *
+ * Logical Physical
+ * f0000000 80000000 On-chip registers
+ * f1000000 00000000 256k on-chip SRAM
+ */
+static struct map_desc stmp37xx_io_desc[] __initdata = {
+ {
+ .virtual = (u32)STMP3XXX_REGS_BASE,
+ .pfn = __phys_to_pfn(STMP3XXX_REGS_PHBASE),
+ .length = SZ_1M,
+ .type = MT_DEVICE
+ },
+ {
+ .virtual = (u32)STMP3XXX_OCRAM_BASE,
+ .pfn = __phys_to_pfn(STMP3XXX_OCRAM_PHBASE),
+ .length = STMP3XXX_OCRAM_SIZE,
+ .type = MT_DEVICE,
+ },
+};
+
+void __init stmp37xx_map_io(void)
+{
+ iotable_init(stmp37xx_io_desc, ARRAY_SIZE(stmp37xx_io_desc));
+}
diff --git a/arch/arm/mach-stmp37xx/stmp37xx.h b/arch/arm/mach-stmp37xx/stmp37xx.h
new file mode 100644
index 000000000000..0b75fb796a64
--- /dev/null
+++ b/arch/arm/mach-stmp37xx/stmp37xx.h
@@ -0,0 +1,24 @@
+/*
+ * Freescale STMP37XX/STMP378X internal functions and data declarations
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __MACH_STMP37XX_H
+#define __MACH_STMP37XX_H
+
+void stmp37xx_map_io(void);
+void stmp37xx_init_irq(void);
+
+#endif /* __MACH_STMP37XX_H */
diff --git a/arch/arm/mach-stmp37xx/stmp37xx_devb.c b/arch/arm/mach-stmp37xx/stmp37xx_devb.c
new file mode 100644
index 000000000000..adfbdc7f8e27
--- /dev/null
+++ b/arch/arm/mach-stmp37xx/stmp37xx_devb.c
@@ -0,0 +1,83 @@
+/*
+ * Freescale STMP37XX development board support
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/stmp3xxx.h>
+#include <mach/pins.h>
+#include <mach/pinmux.h>
+#include "stmp37xx.h"
+
+/*
+ * List of STMP37xx development board specific devices
+ */
+static struct platform_device *stmp37xx_devb_devices[] = {
+ &stmp3xxx_dbguart,
+};
+
+static struct pin_desc dbguart_pins_0[] = {
+ { PINID_PWM0, PIN_FUN3, },
+ { PINID_PWM1, PIN_FUN3, },
+};
+
+static struct pin_group dbguart_pins[] = {
+ [0] = {
+ .pins = dbguart_pins_0,
+ .nr_pins = ARRAY_SIZE(dbguart_pins_0),
+ },
+};
+
+static int dbguart_pins_control(int id, int request)
+{
+ int r = 0;
+
+ if (request)
+ r = stmp3xxx_request_pin_group(&dbguart_pins[id], "debug uart");
+ else
+ stmp3xxx_release_pin_group(&dbguart_pins[id], "debug uart");
+ return r;
+}
+
+
+static void __init stmp37xx_devb_init(void)
+{
+ stmp3xxx_pinmux_init(NR_REAL_IRQS);
+
+ /* Init STMP3xxx platform */
+ stmp3xxx_init();
+
+ stmp3xxx_dbguart.dev.platform_data = dbguart_pins_control;
+ /* Add STMP37xx development board devices */
+ platform_add_devices(stmp37xx_devb_devices,
+ ARRAY_SIZE(stmp37xx_devb_devices));
+}
+
+MACHINE_START(STMP37XX, "STMP37XX")
+ .phys_io = 0x80000000,
+ .io_pg_offst = ((0xf0000000) >> 18) & 0xfffc,
+ .boot_params = 0x40000100,
+ .map_io = stmp37xx_map_io,
+ .init_irq = stmp37xx_init_irq,
+ .timer = &stmp3xxx_timer,
+ .init_machine = stmp37xx_devb_init,
+MACHINE_END
diff --git a/arch/arm/mach-u300/Kconfig b/arch/arm/mach-u300/Kconfig
new file mode 100644
index 000000000000..337b9aabce49
--- /dev/null
+++ b/arch/arm/mach-u300/Kconfig
@@ -0,0 +1,105 @@
+if ARCH_U300
+
+menu "ST-Ericsson AB U300/U330/U335/U365 Platform"
+
+comment "ST-Ericsson Mobile Platform Products"
+
+config MACH_U300
+ bool "U300"
+
+comment "ST-Ericsson U300/U330/U335/U365 Feature Selections"
+
+choice
+ prompt "U300/U330/U335/U365 system type"
+ default MACH_U300_BS2X
+ ---help---
+ You need to select the target system, i.e. the
+ U300/U330/U335/U365 board that you want to compile your kernel
+ for.
+
+config MACH_U300_BS2X
+ bool "S26/S26/B25/B26 Test Products"
+ depends on MACH_U300
+ help
+ Select this if you're developing on the
+ S26/S25 test products. (Also works on
+ B26/B25 big boards.)
+
+config MACH_U300_BS330
+ bool "S330/B330 Test Products"
+ depends on MACH_U300
+ help
+ Select this if you're developing on the
+ S330/B330 test products.
+
+config MACH_U300_BS335
+ bool "S335/B335 Test Products"
+ depends on MACH_U300
+ help
+ Select this if you're developing on the
+ S335/B335 test products.
+
+config MACH_U300_BS365
+ bool "S365/B365 Test Products"
+ depends on MACH_U300
+ help
+ Select this if you're developing on the
+ S365/B365 test products.
+
+endchoice
+
+choice
+ prompt "Memory configuration"
+ default MACH_U300_SINGLE_RAM
+ ---help---
+ You have to config the kernel according to the physical memory
+ configuration.
+
+config MACH_U300_SINGLE_RAM
+ bool "Single RAM"
+ help
+ Select this if you want support for Single RAM phones.
+
+config MACH_U300_DUAL_RAM
+ bool "Dual RAM"
+ help
+ Select this if you want support for Dual RAM phones.
+ This is two RAM memorys on different EMIFs.
+endchoice
+
+config U300_DEBUG
+ bool "Debug support for U300"
+ depends on PM
+ help
+ Debug support for U300 in sysfs, procfs etc.
+
+config MACH_U300_SEMI_IS_SHARED
+ bool "The SEMI is used by both the access and application side"
+ depends on MACH_U300
+ help
+ This makes it possible to use the SEMI (Shared External
+ Memory Interface) from both from access and application
+ side.
+
+comment "All the settings below must match the bootloader's settings"
+
+config MACH_U300_ACCESS_MEM_SIZE
+ int "Access CPU memory allocation"
+ range 7 25
+ depends on MACH_U300_SINGLE_RAM
+ default 13
+ help
+ How much memory in MiB that the Access side CPU has allocated
+
+config MACH_U300_2MB_ALIGNMENT_FIX
+ bool "2MiB alignment fix"
+ depends on MACH_U300_SINGLE_RAM
+ default y
+ help
+ If yes and the Access side CPU has allocated an odd size in
+ MiB, this fix gives you one MiB extra that would otherwise be
+ lost due to Linux 2 MiB alignment policy.
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-u300/Makefile b/arch/arm/mach-u300/Makefile
new file mode 100644
index 000000000000..24950e0df4b4
--- /dev/null
+++ b/arch/arm/mach-u300/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the linux kernel, U300 machine.
+#
+
+obj-y := core.o clock.o timer.o gpio.o padmux.o
+obj-m :=
+obj-n :=
+obj- :=
+
+obj-$(CONFIG_ARCH_U300) += u300.o
+obj-$(CONFIG_MMC) += mmc.o
diff --git a/arch/arm/mach-u300/clock.c b/arch/arm/mach-u300/clock.c
new file mode 100644
index 000000000000..d6f8232757ff
--- /dev/null
+++ b/arch/arm/mach-u300/clock.c
@@ -0,0 +1,1487 @@
+/*
+ *
+ * arch/arm/mach-u300/clock.c
+ *
+ *
+ * Copyright (C) 2007-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Define clocks in the app platform.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/io.h>
+
+#include <asm/clkdev.h>
+#include <mach/hardware.h>
+#include <mach/syscon.h>
+
+#include "clock.h"
+
+/*
+ * TODO:
+ * - move all handling of the CCR register into this file and create
+ * a spinlock for the CCR register
+ * - switch to the clkdevice lookup mechanism that maps clocks to
+ * device ID:s instead when it becomes available in kernel 2.6.29.
+ * - implement rate get/set for all clocks that need it.
+ */
+
+/*
+ * Syscon clock I/O registers lock so clock requests don't collide
+ * NOTE: this is a local lock only used to lock access to clock and
+ * reset registers in syscon.
+ */
+static DEFINE_SPINLOCK(syscon_clkreg_lock);
+static DEFINE_SPINLOCK(syscon_resetreg_lock);
+
+/*
+ * The clocking hierarchy currently looks like this.
+ * NOTE: the idea is NOT to show how the clocks are routed on the chip!
+ * The ideas is to show dependencies, so a clock higher up in the
+ * hierarchy has to be on in order for another clock to be on. Now,
+ * both CPU and DMA can actually be on top of the hierarchy, and that
+ * is not modeled currently. Instead we have the backbone AMBA bus on
+ * top. This bus cannot be programmed in any way but conceptually it
+ * needs to be active for the bridges and devices to transport data.
+ *
+ * Please be aware that a few clocks are hw controlled, which mean that
+ * the hw itself can turn on/off or change the rate of the clock when
+ * needed!
+ *
+ * AMBA bus
+ * |
+ * +- CPU
+ * +- NANDIF NAND Flash interface
+ * +- SEMI Shared Memory interface
+ * +- ISP Image Signal Processor (U335 only)
+ * +- CDS (U335 only)
+ * +- DMA Direct Memory Access Controller
+ * +- AAIF APP/ACC Inteface (Mobile Scalable Link, MSL)
+ * +- APEX
+ * +- VIDEO_ENC AVE2/3 Video Encoder
+ * +- XGAM Graphics Accelerator Controller
+ * +- AHB
+ * |
+ * +- ahb:0 AHB Bridge
+ * | |
+ * | +- ahb:1 INTCON Interrupt controller
+ * | +- ahb:3 MSPRO Memory Stick Pro controller
+ * | +- ahb:4 EMIF External Memory interface
+ * |
+ * +- fast:0 FAST bridge
+ * | |
+ * | +- fast:1 MMCSD MMC/SD card reader controller
+ * | +- fast:2 I2S0 PCM I2S channel 0 controller
+ * | +- fast:3 I2S1 PCM I2S channel 1 controller
+ * | +- fast:4 I2C0 I2C channel 0 controller
+ * | +- fast:5 I2C1 I2C channel 1 controller
+ * | +- fast:6 SPI SPI controller
+ * | +- fast:7 UART1 Secondary UART (U335 only)
+ * |
+ * +- slow:0 SLOW bridge
+ * |
+ * +- slow:1 SYSCON (not possible to control)
+ * +- slow:2 WDOG Watchdog
+ * +- slow:3 UART0 primary UART
+ * +- slow:4 TIMER_APP Application timer - used in Linux
+ * +- slow:5 KEYPAD controller
+ * +- slow:6 GPIO controller
+ * +- slow:7 RTC controller
+ * +- slow:8 BT Bus Tracer (not used currently)
+ * +- slow:9 EH Event Handler (not used currently)
+ * +- slow:a TIMER_ACC Access style timer (not used currently)
+ * +- slow:b PPM (U335 only, what is that?)
+ */
+
+/*
+ * Reset control functions. We remember if a block has been
+ * taken out of reset and don't remove the reset assertion again
+ * and vice versa. Currently we only remove resets so the
+ * enablement function is defined out.
+ */
+static void syscon_block_reset_enable(struct clk *clk)
+{
+ u16 val;
+ unsigned long iflags;
+
+ /* Not all blocks support resetting */
+ if (!clk->res_reg || !clk->res_mask)
+ return;
+ spin_lock_irqsave(&syscon_resetreg_lock, iflags);
+ val = readw(clk->res_reg);
+ val |= clk->res_mask;
+ writew(val, clk->res_reg);
+ spin_unlock_irqrestore(&syscon_resetreg_lock, iflags);
+ clk->reset = true;
+}
+
+static void syscon_block_reset_disable(struct clk *clk)
+{
+ u16 val;
+ unsigned long iflags;
+
+ /* Not all blocks support resetting */
+ if (!clk->res_reg || !clk->res_mask)
+ return;
+ spin_lock_irqsave(&syscon_resetreg_lock, iflags);
+ val = readw(clk->res_reg);
+ val &= ~clk->res_mask;
+ writew(val, clk->res_reg);
+ spin_unlock_irqrestore(&syscon_resetreg_lock, iflags);
+ clk->reset = false;
+}
+
+int __clk_get(struct clk *clk)
+{
+ u16 val;
+
+ /* The MMC and MSPRO clocks need some special set-up */
+ if (!strcmp(clk->name, "MCLK")) {
+ /* Set default MMC clock divisor to 18.9 MHz */
+ writew(0x0054U, U300_SYSCON_VBASE + U300_SYSCON_MMF0R);
+ val = readw(U300_SYSCON_VBASE + U300_SYSCON_MMCR);
+ /* Disable the MMC feedback clock */
+ val &= ~U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE;
+ /* Disable MSPRO frequency */
+ val &= ~U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_MMCR);
+ }
+ if (!strcmp(clk->name, "MSPRO")) {
+ val = readw(U300_SYSCON_VBASE + U300_SYSCON_MMCR);
+ /* Disable the MMC feedback clock */
+ val &= ~U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE;
+ /* Enable MSPRO frequency */
+ val |= U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_MMCR);
+ }
+ return 1;
+}
+EXPORT_SYMBOL(__clk_get);
+
+void __clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(__clk_put);
+
+static void syscon_clk_disable(struct clk *clk)
+{
+ unsigned long iflags;
+
+ /* Don't touch the hardware controlled clocks */
+ if (clk->hw_ctrld)
+ return;
+
+ spin_lock_irqsave(&syscon_clkreg_lock, iflags);
+ writew(clk->clk_val, U300_SYSCON_VBASE + U300_SYSCON_SBCDR);
+ spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
+}
+
+static void syscon_clk_enable(struct clk *clk)
+{
+ unsigned long iflags;
+
+ /* Don't touch the hardware controlled clocks */
+ if (clk->hw_ctrld)
+ return;
+
+ spin_lock_irqsave(&syscon_clkreg_lock, iflags);
+ writew(clk->clk_val, U300_SYSCON_VBASE + U300_SYSCON_SBCER);
+ spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
+}
+
+static u16 syscon_clk_get_rate(void)
+{
+ u16 val;
+ unsigned long iflags;
+
+ spin_lock_irqsave(&syscon_clkreg_lock, iflags);
+ val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
+ val &= U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK;
+ spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
+ return val;
+}
+
+#ifdef CONFIG_MACH_U300_USE_I2S_AS_MASTER
+static void enable_i2s0_vcxo(void)
+{
+ u16 val;
+ unsigned long iflags;
+
+ spin_lock_irqsave(&syscon_clkreg_lock, iflags);
+ /* Set I2S0 to use the VCXO 26 MHz clock */
+ val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
+ val |= U300_SYSCON_CCR_TURN_VCXO_ON;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+ val |= U300_SYSCON_CCR_I2S0_USE_VCXO;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+ val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR);
+ val |= U300_SYSCON_CEFR_I2S0_CLK_EN;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR);
+ spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
+}
+
+static void enable_i2s1_vcxo(void)
+{
+ u16 val;
+ unsigned long iflags;
+
+ spin_lock_irqsave(&syscon_clkreg_lock, iflags);
+ /* Set I2S1 to use the VCXO 26 MHz clock */
+ val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
+ val |= U300_SYSCON_CCR_TURN_VCXO_ON;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+ val |= U300_SYSCON_CCR_I2S1_USE_VCXO;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+ val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR);
+ val |= U300_SYSCON_CEFR_I2S1_CLK_EN;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR);
+ spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
+}
+
+static void disable_i2s0_vcxo(void)
+{
+ u16 val;
+ unsigned long iflags;
+
+ spin_lock_irqsave(&syscon_clkreg_lock, iflags);
+ /* Disable I2S0 use of the VCXO 26 MHz clock */
+ val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
+ val &= ~U300_SYSCON_CCR_I2S0_USE_VCXO;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+ /* Deactivate VCXO if noone else is using VCXO */
+ if (!(val & U300_SYSCON_CCR_I2S1_USE_VCXO))
+ val &= ~U300_SYSCON_CCR_TURN_VCXO_ON;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+ val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR);
+ val &= ~U300_SYSCON_CEFR_I2S0_CLK_EN;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR);
+ spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
+}
+
+static void disable_i2s1_vcxo(void)
+{
+ u16 val;
+ unsigned long iflags;
+
+ spin_lock_irqsave(&syscon_clkreg_lock, iflags);
+ /* Disable I2S1 use of the VCXO 26 MHz clock */
+ val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
+ val &= ~U300_SYSCON_CCR_I2S1_USE_VCXO;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+ /* Deactivate VCXO if noone else is using VCXO */
+ if (!(val & U300_SYSCON_CCR_I2S0_USE_VCXO))
+ val &= ~U300_SYSCON_CCR_TURN_VCXO_ON;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+ val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR);
+ val &= ~U300_SYSCON_CEFR_I2S0_CLK_EN;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR);
+ spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
+}
+#endif /* CONFIG_MACH_U300_USE_I2S_AS_MASTER */
+
+
+static void syscon_clk_rate_set_mclk(unsigned long rate)
+{
+ u16 val;
+ u32 reg;
+ unsigned long iflags;
+
+ switch (rate) {
+ case 18900000:
+ val = 0x0054;
+ break;
+ case 20800000:
+ val = 0x0044;
+ break;
+ case 23100000:
+ val = 0x0043;
+ break;
+ case 26000000:
+ val = 0x0033;
+ break;
+ case 29700000:
+ val = 0x0032;
+ break;
+ case 34700000:
+ val = 0x0022;
+ break;
+ case 41600000:
+ val = 0x0021;
+ break;
+ case 52000000:
+ val = 0x0011;
+ break;
+ case 104000000:
+ val = 0x0000;
+ break;
+ default:
+ printk(KERN_ERR "Trying to set MCLK to unknown speed! %ld\n",
+ rate);
+ return;
+ }
+
+ spin_lock_irqsave(&syscon_clkreg_lock, iflags);
+ reg = readw(U300_SYSCON_VBASE + U300_SYSCON_MMF0R) &
+ ~U300_SYSCON_MMF0R_MASK;
+ writew(reg | val, U300_SYSCON_VBASE + U300_SYSCON_MMF0R);
+ spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
+}
+
+void syscon_clk_rate_set_cpuclk(unsigned long rate)
+{
+ u16 val;
+ unsigned long iflags;
+
+ switch (rate) {
+ case 13000000:
+ val = U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER;
+ break;
+ case 52000000:
+ val = U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE;
+ break;
+ case 104000000:
+ val = U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH;
+ break;
+ case 208000000:
+ val = U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST;
+ break;
+ default:
+ return;
+ }
+ spin_lock_irqsave(&syscon_clkreg_lock, iflags);
+ val |= readw(U300_SYSCON_VBASE + U300_SYSCON_CCR) &
+ ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK ;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+ spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
+}
+EXPORT_SYMBOL(syscon_clk_rate_set_cpuclk);
+
+void clk_disable(struct clk *clk)
+{
+ unsigned long iflags;
+
+ spin_lock_irqsave(&clk->lock, iflags);
+ if (clk->usecount > 0 && !(--clk->usecount)) {
+ /* some blocks lack clocking registers and cannot be disabled */
+ if (clk->disable)
+ clk->disable(clk);
+ if (likely((u32)clk->parent))
+ clk_disable(clk->parent);
+ }
+#ifdef CONFIG_MACH_U300_USE_I2S_AS_MASTER
+ if (unlikely(!strcmp(clk->name, "I2S0")))
+ disable_i2s0_vcxo();
+ if (unlikely(!strcmp(clk->name, "I2S1")))
+ disable_i2s1_vcxo();
+#endif
+ spin_unlock_irqrestore(&clk->lock, iflags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+int clk_enable(struct clk *clk)
+{
+ int ret = 0;
+ unsigned long iflags;
+
+ spin_lock_irqsave(&clk->lock, iflags);
+ if (clk->usecount++ == 0) {
+ if (likely((u32)clk->parent))
+ ret = clk_enable(clk->parent);
+
+ if (unlikely(ret != 0))
+ clk->usecount--;
+ else {
+ /* remove reset line (we never enable reset again) */
+ syscon_block_reset_disable(clk);
+ /* clocks without enable function are always on */
+ if (clk->enable)
+ clk->enable(clk);
+#ifdef CONFIG_MACH_U300_USE_I2S_AS_MASTER
+ if (unlikely(!strcmp(clk->name, "I2S0")))
+ enable_i2s0_vcxo();
+ if (unlikely(!strcmp(clk->name, "I2S1")))
+ enable_i2s1_vcxo();
+#endif
+ }
+ }
+ spin_unlock_irqrestore(&clk->lock, iflags);
+ return ret;
+
+}
+EXPORT_SYMBOL(clk_enable);
+
+/* Returns the clock rate in Hz */
+static unsigned long clk_get_rate_cpuclk(struct clk *clk)
+{
+ u16 val;
+
+ val = syscon_clk_get_rate();
+
+ switch (val) {
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
+ return 13000000;
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
+ return 52000000;
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
+ return 104000000;
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST:
+ return 208000000;
+ default:
+ break;
+ }
+ return clk->rate;
+}
+
+static unsigned long clk_get_rate_ahb_clk(struct clk *clk)
+{
+ u16 val;
+
+ val = syscon_clk_get_rate();
+
+ switch (val) {
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
+ return 6500000;
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
+ return 26000000;
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST:
+ return 52000000;
+ default:
+ break;
+ }
+ return clk->rate;
+
+}
+
+static unsigned long clk_get_rate_emif_clk(struct clk *clk)
+{
+ u16 val;
+
+ val = syscon_clk_get_rate();
+
+ switch (val) {
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
+ return 13000000;
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
+ return 52000000;
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST:
+ return 104000000;
+ default:
+ break;
+ }
+ return clk->rate;
+
+}
+
+static unsigned long clk_get_rate_xgamclk(struct clk *clk)
+{
+ u16 val;
+
+ val = syscon_clk_get_rate();
+
+ switch (val) {
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
+ return 6500000;
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
+ return 26000000;
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST:
+ return 52000000;
+ default:
+ break;
+ }
+
+ return clk->rate;
+}
+
+static unsigned long clk_get_rate_mclk(struct clk *clk)
+{
+ u16 val;
+
+ val = syscon_clk_get_rate();
+
+ switch (val) {
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
+ /*
+ * Here, the 208 MHz PLL gets shut down and the always
+ * on 13 MHz PLL used for RTC etc kicks into use
+ * instead.
+ */
+ return 13000000;
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST:
+ {
+ /*
+ * This clock is under program control. The register is
+ * divided in two nybbles, bit 7-4 gives cycles-1 to count
+ * high, bit 3-0 gives cycles-1 to count low. Distribute
+ * these with no more than 1 cycle difference between
+ * low and high and add low and high to get the actual
+ * divisor. The base PLL is 208 MHz. Writing 0x00 will
+ * divide by 1 and 1 so the highest frequency possible
+ * is 104 MHz.
+ *
+ * e.g. 0x54 =>
+ * f = 208 / ((5+1) + (4+1)) = 208 / 11 = 18.9 MHz
+ */
+ u16 val = readw(U300_SYSCON_VBASE + U300_SYSCON_MMF0R) &
+ U300_SYSCON_MMF0R_MASK;
+ switch (val) {
+ case 0x0054:
+ return 18900000;
+ case 0x0044:
+ return 20800000;
+ case 0x0043:
+ return 23100000;
+ case 0x0033:
+ return 26000000;
+ case 0x0032:
+ return 29700000;
+ case 0x0022:
+ return 34700000;
+ case 0x0021:
+ return 41600000;
+ case 0x0011:
+ return 52000000;
+ case 0x0000:
+ return 104000000;
+ default:
+ break;
+ }
+ }
+ default:
+ break;
+ }
+
+ return clk->rate;
+}
+
+static unsigned long clk_get_rate_i2s_i2c_spi(struct clk *clk)
+{
+ u16 val;
+
+ val = syscon_clk_get_rate();
+
+ switch (val) {
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
+ return 13000000;
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
+ case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST:
+ return 26000000;
+ default:
+ break;
+ }
+
+ return clk->rate;
+}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ if (clk->get_rate)
+ return clk->get_rate(clk);
+ else
+ return clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+static unsigned long clk_round_rate_mclk(struct clk *clk, unsigned long rate)
+{
+ if (rate >= 18900000)
+ return 18900000;
+ if (rate >= 20800000)
+ return 20800000;
+ if (rate >= 23100000)
+ return 23100000;
+ if (rate >= 26000000)
+ return 26000000;
+ if (rate >= 29700000)
+ return 29700000;
+ if (rate >= 34700000)
+ return 34700000;
+ if (rate >= 41600000)
+ return 41600000;
+ if (rate >= 52000000)
+ return 52000000;
+ return -EINVAL;
+}
+
+static unsigned long clk_round_rate_cpuclk(struct clk *clk, unsigned long rate)
+{
+ if (rate >= 13000000)
+ return 13000000;
+ if (rate >= 52000000)
+ return 52000000;
+ if (rate >= 104000000)
+ return 104000000;
+ if (rate >= 208000000)
+ return 208000000;
+ return -EINVAL;
+}
+
+/*
+ * This adjusts a requested rate to the closest exact rate
+ * a certain clock can provide. For a fixed clock it's
+ * mostly clk->rate.
+ */
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ /* TODO: get apropriate switches for EMIFCLK, AHBCLK and MCLK */
+ /* Else default to fixed value */
+
+ if (clk->round_rate) {
+ return (long) clk->round_rate(clk, rate);
+ } else {
+ printk(KERN_ERR "clock: Failed to round rate of %s\n",
+ clk->name);
+ }
+ return (long) clk->rate;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+static int clk_set_rate_mclk(struct clk *clk, unsigned long rate)
+{
+ syscon_clk_rate_set_mclk(clk_round_rate(clk, rate));
+ return 0;
+}
+
+static int clk_set_rate_cpuclk(struct clk *clk, unsigned long rate)
+{
+ syscon_clk_rate_set_cpuclk(clk_round_rate(clk, rate));
+ return 0;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ /* TODO: set for EMIFCLK and AHBCLK */
+ /* Else assume the clock is fixed and fail */
+ if (clk->set_rate) {
+ return clk->set_rate(clk, rate);
+ } else {
+ printk(KERN_ERR "clock: Failed to set %s to %ld hz\n",
+ clk->name, rate);
+ return -1;
+ }
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+/*
+ * Clock definitions. The clock parents are set to respective
+ * bridge and the clock framework makes sure that the clocks have
+ * parents activated and are brought out of reset when in use.
+ *
+ * Clocks that have hw_ctrld = true are hw controlled, and the hw
+ * can by itself turn these clocks on and off.
+ * So in other words, we don't really have to care about them.
+ */
+
+static struct clk amba_clk = {
+ .name = "AMBA",
+ .rate = 52000000, /* this varies! */
+ .hw_ctrld = true,
+ .reset = false,
+};
+
+/*
+ * These blocks are connected directly to the AMBA bus
+ * with no bridge.
+ */
+
+static struct clk cpu_clk = {
+ .name = "CPU",
+ .parent = &amba_clk,
+ .rate = 208000000, /* this varies! */
+ .hw_ctrld = true,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+ .res_mask = U300_SYSCON_RRR_CPU_RESET_EN,
+ .set_rate = clk_set_rate_cpuclk,
+ .get_rate = clk_get_rate_cpuclk,
+ .round_rate = clk_round_rate_cpuclk,
+};
+
+static struct clk nandif_clk = {
+ .name = "NANDIF",
+ .parent = &amba_clk,
+ .hw_ctrld = false,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+ .res_mask = U300_SYSCON_RRR_NANDIF_RESET_EN,
+ .clk_val = U300_SYSCON_SBCER_NANDIF_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+};
+
+static struct clk semi_clk = {
+ .name = "SEMI",
+ .parent = &amba_clk,
+ .rate = 0, /* FIXME */
+ /* It is not possible to reset SEMI */
+ .hw_ctrld = false,
+ .reset = false,
+ .clk_val = U300_SYSCON_SBCER_SEMI_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+};
+
+#ifdef CONFIG_MACH_U300_BS335
+static struct clk isp_clk = {
+ .name = "ISP",
+ .parent = &amba_clk,
+ .rate = 0, /* FIXME */
+ .hw_ctrld = false,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+ .res_mask = U300_SYSCON_RRR_ISP_RESET_EN,
+ .clk_val = U300_SYSCON_SBCER_ISP_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+};
+
+static struct clk cds_clk = {
+ .name = "CDS",
+ .parent = &amba_clk,
+ .rate = 0, /* FIXME */
+ .hw_ctrld = false,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+ .res_mask = U300_SYSCON_RRR_CDS_RESET_EN,
+ .clk_val = U300_SYSCON_SBCER_CDS_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+};
+#endif
+
+static struct clk dma_clk = {
+ .name = "DMA",
+ .parent = &amba_clk,
+ .rate = 52000000, /* this varies! */
+ .hw_ctrld = true,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+ .res_mask = U300_SYSCON_RRR_DMAC_RESET_EN,
+ .clk_val = U300_SYSCON_SBCER_DMAC_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+};
+
+static struct clk aaif_clk = {
+ .name = "AAIF",
+ .parent = &amba_clk,
+ .rate = 52000000, /* this varies! */
+ .hw_ctrld = true,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+ .res_mask = U300_SYSCON_RRR_AAIF_RESET_EN,
+ .clk_val = U300_SYSCON_SBCER_AAIF_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+};
+
+static struct clk apex_clk = {
+ .name = "APEX",
+ .parent = &amba_clk,
+ .rate = 0, /* FIXME */
+ .hw_ctrld = true,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+ .res_mask = U300_SYSCON_RRR_APEX_RESET_EN,
+ .clk_val = U300_SYSCON_SBCER_APEX_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+};
+
+static struct clk video_enc_clk = {
+ .name = "VIDEO_ENC",
+ .parent = &amba_clk,
+ .rate = 208000000, /* this varies! */
+ .hw_ctrld = false,
+ .reset = false,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+ /* This has XGAM in the name but refers to the video encoder */
+ .res_mask = U300_SYSCON_RRR_XGAM_VC_SYNC_RESET_EN,
+ .clk_val = U300_SYSCON_SBCER_VIDEO_ENC_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+};
+
+static struct clk xgam_clk = {
+ .name = "XGAMCLK",
+ .parent = &amba_clk,
+ .rate = 52000000, /* this varies! */
+ .hw_ctrld = false,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+ .res_mask = U300_SYSCON_RRR_XGAM_RESET_EN,
+ .clk_val = U300_SYSCON_SBCER_XGAM_CLK_EN,
+ .get_rate = clk_get_rate_xgamclk,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+};
+
+/* This clock is used to activate the video encoder */
+static struct clk ahb_clk = {
+ .name = "AHB",
+ .parent = &amba_clk,
+ .rate = 52000000, /* this varies! */
+ .hw_ctrld = false, /* This one is set to false due to HW bug */
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+ .res_mask = U300_SYSCON_RRR_AHB_RESET_EN,
+ .clk_val = U300_SYSCON_SBCER_AHB_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+ .get_rate = clk_get_rate_ahb_clk,
+};
+
+
+/*
+ * Clocks on the AHB bridge
+ */
+
+static struct clk ahb_subsys_clk = {
+ .name = "AHB_SUBSYS",
+ .parent = &amba_clk,
+ .rate = 52000000, /* this varies! */
+ .hw_ctrld = true,
+ .reset = false,
+ .clk_val = U300_SYSCON_SBCER_AHB_SUBSYS_BRIDGE_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+ .get_rate = clk_get_rate_ahb_clk,
+};
+
+static struct clk intcon_clk = {
+ .name = "INTCON",
+ .parent = &ahb_subsys_clk,
+ .rate = 52000000, /* this varies! */
+ .hw_ctrld = false,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+ .res_mask = U300_SYSCON_RRR_INTCON_RESET_EN,
+ /* INTCON can be reset but not clock-gated */
+};
+
+static struct clk mspro_clk = {
+ .name = "MSPRO",
+ .parent = &ahb_subsys_clk,
+ .rate = 0, /* FIXME */
+ .hw_ctrld = false,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+ .res_mask = U300_SYSCON_RRR_MSPRO_RESET_EN,
+ .clk_val = U300_SYSCON_SBCER_MSPRO_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+};
+
+static struct clk emif_clk = {
+ .name = "EMIF",
+ .parent = &ahb_subsys_clk,
+ .rate = 104000000, /* this varies! */
+ .hw_ctrld = false,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+ .res_mask = U300_SYSCON_RRR_EMIF_RESET_EN,
+ .clk_val = U300_SYSCON_SBCER_EMIF_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+ .get_rate = clk_get_rate_emif_clk,
+};
+
+
+/*
+ * Clocks on the FAST bridge
+ */
+static struct clk fast_clk = {
+ .name = "FAST_BRIDGE",
+ .parent = &amba_clk,
+ .rate = 13000000, /* this varies! */
+ .hw_ctrld = true,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR,
+ .res_mask = U300_SYSCON_RFR_FAST_BRIDGE_RESET_ENABLE,
+ .clk_val = U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+};
+
+static struct clk mmcsd_clk = {
+ .name = "MCLK",
+ .parent = &fast_clk,
+ .rate = 18900000, /* this varies! */
+ .hw_ctrld = false,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR,
+ .res_mask = U300_SYSCON_RFR_MMC_RESET_ENABLE,
+ .clk_val = U300_SYSCON_SBCER_MMC_CLK_EN,
+ .get_rate = clk_get_rate_mclk,
+ .set_rate = clk_set_rate_mclk,
+ .round_rate = clk_round_rate_mclk,
+ .disable = syscon_clk_disable,
+ .enable = syscon_clk_enable,
+};
+
+static struct clk i2s0_clk = {
+ .name = "i2s0",
+ .parent = &fast_clk,
+ .rate = 26000000, /* this varies! */
+ .hw_ctrld = true,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR,
+ .res_mask = U300_SYSCON_RFR_PCM_I2S0_RESET_ENABLE,
+ .clk_val = U300_SYSCON_SBCER_I2S0_CORE_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+ .get_rate = clk_get_rate_i2s_i2c_spi,
+};
+
+static struct clk i2s1_clk = {
+ .name = "i2s1",
+ .parent = &fast_clk,
+ .rate = 26000000, /* this varies! */
+ .hw_ctrld = true,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR,
+ .res_mask = U300_SYSCON_RFR_PCM_I2S1_RESET_ENABLE,
+ .clk_val = U300_SYSCON_SBCER_I2S1_CORE_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+ .get_rate = clk_get_rate_i2s_i2c_spi,
+};
+
+static struct clk i2c0_clk = {
+ .name = "I2C0",
+ .parent = &fast_clk,
+ .rate = 26000000, /* this varies! */
+ .hw_ctrld = false,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR,
+ .res_mask = U300_SYSCON_RFR_I2C0_RESET_ENABLE,
+ .clk_val = U300_SYSCON_SBCER_I2C0_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+ .get_rate = clk_get_rate_i2s_i2c_spi,
+};
+
+static struct clk i2c1_clk = {
+ .name = "I2C1",
+ .parent = &fast_clk,
+ .rate = 26000000, /* this varies! */
+ .hw_ctrld = false,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR,
+ .res_mask = U300_SYSCON_RFR_I2C1_RESET_ENABLE,
+ .clk_val = U300_SYSCON_SBCER_I2C1_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+ .get_rate = clk_get_rate_i2s_i2c_spi,
+};
+
+static struct clk spi_clk = {
+ .name = "SPI",
+ .parent = &fast_clk,
+ .rate = 26000000, /* this varies! */
+ .hw_ctrld = false,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR,
+ .res_mask = U300_SYSCON_RFR_SPI_RESET_ENABLE,
+ .clk_val = U300_SYSCON_SBCER_SPI_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+ .get_rate = clk_get_rate_i2s_i2c_spi,
+};
+
+#ifdef CONFIG_MACH_U300_BS335
+static struct clk uart1_clk = {
+ .name = "UART1",
+ .parent = &fast_clk,
+ .rate = 13000000,
+ .hw_ctrld = false,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR,
+ .res_mask = U300_SYSCON_RFR_UART1_RESET_ENABLE,
+ .clk_val = U300_SYSCON_SBCER_UART1_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+};
+#endif
+
+
+/*
+ * Clocks on the SLOW bridge
+ */
+static struct clk slow_clk = {
+ .name = "SLOW_BRIDGE",
+ .parent = &amba_clk,
+ .rate = 13000000,
+ .hw_ctrld = true,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR,
+ .res_mask = U300_SYSCON_RSR_SLOW_BRIDGE_RESET_EN,
+ .clk_val = U300_SYSCON_SBCER_SLOW_BRIDGE_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+};
+
+/* TODO: implement SYSCON clock? */
+
+static struct clk wdog_clk = {
+ .name = "WDOG",
+ .parent = &slow_clk,
+ .hw_ctrld = false,
+ .rate = 32768,
+ .reset = false,
+ /* This is always on, cannot be enabled/disabled or reset */
+};
+
+/* This one is hardwired to PLL13 */
+static struct clk uart_clk = {
+ .name = "UARTCLK",
+ .parent = &slow_clk,
+ .rate = 13000000,
+ .hw_ctrld = false,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR,
+ .res_mask = U300_SYSCON_RSR_UART_RESET_EN,
+ .clk_val = U300_SYSCON_SBCER_UART_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+};
+
+static struct clk keypad_clk = {
+ .name = "KEYPAD",
+ .parent = &slow_clk,
+ .rate = 32768,
+ .hw_ctrld = false,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR,
+ .res_mask = U300_SYSCON_RSR_KEYPAD_RESET_EN,
+ .clk_val = U300_SYSCON_SBCER_KEYPAD_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+};
+
+static struct clk gpio_clk = {
+ .name = "GPIO",
+ .parent = &slow_clk,
+ .rate = 13000000,
+ .hw_ctrld = true,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR,
+ .res_mask = U300_SYSCON_RSR_GPIO_RESET_EN,
+ .clk_val = U300_SYSCON_SBCER_GPIO_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+};
+
+static struct clk rtc_clk = {
+ .name = "RTC",
+ .parent = &slow_clk,
+ .rate = 32768,
+ .hw_ctrld = true,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR,
+ .res_mask = U300_SYSCON_RSR_RTC_RESET_EN,
+ /* This clock is always on, cannot be enabled/disabled */
+};
+
+static struct clk bustr_clk = {
+ .name = "BUSTR",
+ .parent = &slow_clk,
+ .rate = 13000000,
+ .hw_ctrld = true,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR,
+ .res_mask = U300_SYSCON_RSR_BTR_RESET_EN,
+ .clk_val = U300_SYSCON_SBCER_BTR_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+};
+
+static struct clk evhist_clk = {
+ .name = "EVHIST",
+ .parent = &slow_clk,
+ .rate = 13000000,
+ .hw_ctrld = true,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR,
+ .res_mask = U300_SYSCON_RSR_EH_RESET_EN,
+ .clk_val = U300_SYSCON_SBCER_EH_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+};
+
+static struct clk timer_clk = {
+ .name = "TIMER",
+ .parent = &slow_clk,
+ .rate = 13000000,
+ .hw_ctrld = true,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR,
+ .res_mask = U300_SYSCON_RSR_ACC_TMR_RESET_EN,
+ .clk_val = U300_SYSCON_SBCER_ACC_TMR_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+};
+
+static struct clk app_timer_clk = {
+ .name = "TIMER_APP",
+ .parent = &slow_clk,
+ .rate = 13000000,
+ .hw_ctrld = true,
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR,
+ .res_mask = U300_SYSCON_RSR_APP_TMR_RESET_EN,
+ .clk_val = U300_SYSCON_SBCER_APP_TMR_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+};
+
+#ifdef CONFIG_MACH_U300_BS335
+static struct clk ppm_clk = {
+ .name = "PPM",
+ .parent = &slow_clk,
+ .rate = 0, /* FIXME */
+ .hw_ctrld = true, /* TODO: Look up if it is hw ctrld or not */
+ .reset = true,
+ .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR,
+ .res_mask = U300_SYSCON_RSR_PPM_RESET_EN,
+ .clk_val = U300_SYSCON_SBCER_PPM_CLK_EN,
+ .enable = syscon_clk_enable,
+ .disable = syscon_clk_disable,
+};
+#endif
+
+#define DEF_LOOKUP(devid, clkref) \
+ { \
+ .dev_id = devid, \
+ .clk = clkref, \
+ }
+
+/*
+ * Here we only define clocks that are meaningful to
+ * look up through clockdevice.
+ */
+static struct clk_lookup lookups[] = {
+ /* Connected directly to the AMBA bus */
+ DEF_LOOKUP("amba", &amba_clk),
+ DEF_LOOKUP("cpu", &cpu_clk),
+ DEF_LOOKUP("nandif", &nandif_clk),
+ DEF_LOOKUP("semi", &semi_clk),
+#ifdef CONFIG_MACH_U300_BS335
+ DEF_LOOKUP("isp", &isp_clk),
+ DEF_LOOKUP("cds", &cds_clk),
+#endif
+ DEF_LOOKUP("dma", &dma_clk),
+ DEF_LOOKUP("aaif", &aaif_clk),
+ DEF_LOOKUP("apex", &apex_clk),
+ DEF_LOOKUP("video_enc", &video_enc_clk),
+ DEF_LOOKUP("xgam", &xgam_clk),
+ DEF_LOOKUP("ahb", &ahb_clk),
+ /* AHB bridge clocks */
+ DEF_LOOKUP("ahb", &ahb_subsys_clk),
+ DEF_LOOKUP("intcon", &intcon_clk),
+ DEF_LOOKUP("mspro", &mspro_clk),
+ DEF_LOOKUP("pl172", &emif_clk),
+ /* FAST bridge clocks */
+ DEF_LOOKUP("fast", &fast_clk),
+ DEF_LOOKUP("mmci", &mmcsd_clk),
+ /*
+ * The .0 and .1 identifiers on these comes from the platform device
+ * .id field and are assigned when the platform devices are registered.
+ */
+ DEF_LOOKUP("i2s.0", &i2s0_clk),
+ DEF_LOOKUP("i2s.1", &i2s1_clk),
+ DEF_LOOKUP("stddci2c.0", &i2c0_clk),
+ DEF_LOOKUP("stddci2c.1", &i2c1_clk),
+ DEF_LOOKUP("pl022", &spi_clk),
+#ifdef CONFIG_MACH_U300_BS335
+ DEF_LOOKUP("uart1", &uart1_clk),
+#endif
+ /* SLOW bridge clocks */
+ DEF_LOOKUP("slow", &slow_clk),
+ DEF_LOOKUP("wdog", &wdog_clk),
+ DEF_LOOKUP("uart0", &uart_clk),
+ DEF_LOOKUP("apptimer", &app_timer_clk),
+ DEF_LOOKUP("keypad", &keypad_clk),
+ DEF_LOOKUP("u300-gpio", &gpio_clk),
+ DEF_LOOKUP("rtc0", &rtc_clk),
+ DEF_LOOKUP("bustr", &bustr_clk),
+ DEF_LOOKUP("evhist", &evhist_clk),
+ DEF_LOOKUP("timer", &timer_clk),
+#ifdef CONFIG_MACH_U300_BS335
+ DEF_LOOKUP("ppm", &ppm_clk),
+#endif
+};
+
+static void __init clk_register(void)
+{
+ int i;
+
+ /* Register the lookups */
+ for (i = 0; i < ARRAY_SIZE(lookups); i++)
+ clkdev_add(&lookups[i]);
+}
+
+/*
+ * These are the clocks for cells registered as primecell drivers
+ * on the AMBA bus. These must be on during AMBA device registration
+ * since the bus probe will attempt to read magic configuration
+ * registers for these devices. If they are deactivated these probes
+ * will fail.
+ *
+ *
+ * Please note that on emif, both RAM and NAND is connected in dual
+ * RAM phones. On single RAM phones, ram is on semi and NAND on emif.
+ *
+ */
+void u300_clock_primecells(void)
+{
+ clk_enable(&intcon_clk);
+ clk_enable(&uart_clk);
+#ifdef CONFIG_MACH_U300_BS335
+ clk_enable(&uart1_clk);
+#endif
+ clk_enable(&spi_clk);
+
+ clk_enable(&mmcsd_clk);
+
+}
+EXPORT_SYMBOL(u300_clock_primecells);
+
+void u300_unclock_primecells(void)
+{
+
+ clk_disable(&intcon_clk);
+ clk_disable(&uart_clk);
+#ifdef CONFIG_MACH_U300_BS335
+ clk_disable(&uart1_clk);
+#endif
+ clk_disable(&spi_clk);
+ clk_disable(&mmcsd_clk);
+
+}
+EXPORT_SYMBOL(u300_unclock_primecells);
+
+/*
+ * The interrupt controller is enabled before the clock API is registered.
+ */
+void u300_enable_intcon_clock(void)
+{
+ clk_enable(&intcon_clk);
+}
+EXPORT_SYMBOL(u300_enable_intcon_clock);
+
+/*
+ * The timer is enabled before the clock API is registered.
+ */
+void u300_enable_timer_clock(void)
+{
+ clk_enable(&app_timer_clk);
+}
+EXPORT_SYMBOL(u300_enable_timer_clock);
+
+#if (defined(CONFIG_DEBUG_FS) && defined(CONFIG_U300_DEBUG))
+/*
+ * The following makes it possible to view the status (especially
+ * reference count and reset status) for the clocks in the platform
+ * by looking into the special file <debugfs>/u300_clocks
+ */
+
+/* A list of all clocks in the platform */
+static struct clk *clks[] = {
+ /* Top node clock for the AMBA bus */
+ &amba_clk,
+ /* Connected directly to the AMBA bus */
+ &cpu_clk,
+ &nandif_clk,
+ &semi_clk,
+#ifdef CONFIG_MACH_U300_BS335
+ &isp_clk,
+ &cds_clk,
+#endif
+ &dma_clk,
+ &aaif_clk,
+ &apex_clk,
+ &video_enc_clk,
+ &xgam_clk,
+ &ahb_clk,
+
+ /* AHB bridge clocks */
+ &ahb_subsys_clk,
+ &intcon_clk,
+ &mspro_clk,
+ &emif_clk,
+ /* FAST bridge clocks */
+ &fast_clk,
+ &mmcsd_clk,
+ &i2s0_clk,
+ &i2s1_clk,
+ &i2c0_clk,
+ &i2c1_clk,
+ &spi_clk,
+#ifdef CONFIG_MACH_U300_BS335
+ &uart1_clk,
+#endif
+ /* SLOW bridge clocks */
+ &slow_clk,
+ &wdog_clk,
+ &uart_clk,
+ &app_timer_clk,
+ &keypad_clk,
+ &gpio_clk,
+ &rtc_clk,
+ &bustr_clk,
+ &evhist_clk,
+ &timer_clk,
+#ifdef CONFIG_MACH_U300_BS335
+ &ppm_clk,
+#endif
+};
+
+static int u300_clocks_show(struct seq_file *s, void *data)
+{
+ struct clk *clk;
+ int i;
+
+ seq_printf(s, "CLOCK DEVICE RESET STATE\t" \
+ "ACTIVE\tUSERS\tHW CTRL FREQ\n");
+ seq_printf(s, "---------------------------------------------" \
+ "-----------------------------------------\n");
+ for (i = 0; i < ARRAY_SIZE(clks); i++) {
+ clk = clks[i];
+ if (clk != ERR_PTR(-ENOENT)) {
+ /* Format clock and device name nicely */
+ char cdp[33];
+ int chars;
+
+ chars = snprintf(&cdp[0], 17, "%s", clk->name);
+ while (chars < 16) {
+ cdp[chars] = ' ';
+ chars++;
+ }
+ chars = snprintf(&cdp[16], 17, "%s", clk->dev ?
+ dev_name(clk->dev) : "N/A");
+ while (chars < 16) {
+ cdp[chars+16] = ' ';
+ chars++;
+ }
+ cdp[32] = '\0';
+ if (clk->get_rate)
+ seq_printf(s,
+ "%s%s\t%s\t%d\t%s\t%lu Hz\n",
+ &cdp[0],
+ clk->reset ?
+ "ASSERTED" : "RELEASED",
+ clk->usecount ? "ON" : "OFF",
+ clk->usecount,
+ clk->hw_ctrld ? "YES" : "NO ",
+ clk->get_rate(clk));
+ else
+ seq_printf(s,
+ "%s%s\t%s\t%d\t%s\t" \
+ "(unknown rate)\n",
+ &cdp[0],
+ clk->reset ?
+ "ASSERTED" : "RELEASED",
+ clk->usecount ? "ON" : "OFF",
+ clk->usecount,
+ clk->hw_ctrld ? "YES" : "NO ");
+ }
+ }
+ return 0;
+}
+
+static int u300_clocks_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, u300_clocks_show, NULL);
+}
+
+static const struct file_operations u300_clocks_operations = {
+ .open = u300_clocks_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static void init_clk_read_procfs(void)
+{
+ /* Expose a simple debugfs interface to view all clocks */
+ (void) debugfs_create_file("u300_clocks", S_IFREG | S_IRUGO,
+ NULL, NULL, &u300_clocks_operations);
+}
+#else
+static inline void init_clk_read_procfs(void)
+{
+}
+#endif
+
+static int __init u300_clock_init(void)
+{
+ u16 val;
+
+ /*
+ * FIXME: shall all this powermanagement stuff really live here???
+ */
+
+ /* Set system to run at PLL208, max performance, a known state. */
+ val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
+ val &= ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+ /* Wait for the PLL208 to lock if not locked in yet */
+ while (!(readw(U300_SYSCON_VBASE + U300_SYSCON_CSR) &
+ U300_SYSCON_CSR_PLL208_LOCK_IND));
+
+ /* Power management enable */
+ val = readw(U300_SYSCON_VBASE + U300_SYSCON_PMCR);
+ val |= U300_SYSCON_PMCR_PWR_MGNT_ENABLE;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_PMCR);
+
+ clk_register();
+
+ init_clk_read_procfs();
+
+ /*
+ * Some of these may be on when we boot the system so make sure they
+ * are turned OFF.
+ */
+ syscon_block_reset_enable(&timer_clk);
+ timer_clk.disable(&timer_clk);
+
+ /*
+ * These shall be turned on by default when we boot the system
+ * so make sure they are ON. (Adding CPU here is a bit too much.)
+ * These clocks will be claimed by drivers later.
+ */
+ syscon_block_reset_disable(&semi_clk);
+ syscon_block_reset_disable(&emif_clk);
+ semi_clk.enable(&semi_clk);
+ emif_clk.enable(&emif_clk);
+
+ return 0;
+}
+/* initialize clocking early to be available later in the boot */
+core_initcall(u300_clock_init);
diff --git a/arch/arm/mach-u300/clock.h b/arch/arm/mach-u300/clock.h
new file mode 100644
index 000000000000..fc6d9ccfe7e3
--- /dev/null
+++ b/arch/arm/mach-u300/clock.h
@@ -0,0 +1,53 @@
+/*
+ * arch/arm/mach-u300/include/mach/clock.h
+ *
+ * Copyright (C) 2004 - 2005 Nokia corporation
+ * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc
+ * Copyright (C) 2007-2009 ST-Ericsson AB
+ * Adopted to ST-Ericsson U300 platforms by
+ * Jonas Aaberg <jonas.aberg@stericsson.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 __MACH_CLOCK_H
+#define __MACH_CLOCK_H
+
+#include <linux/clk.h>
+
+struct clk {
+ struct list_head node;
+ struct module *owner;
+ struct device *dev;
+ const char *name;
+ struct clk *parent;
+
+ spinlock_t lock;
+ unsigned long rate;
+ bool reset;
+ __u16 clk_val;
+ __s8 usecount;
+ __u32 res_reg;
+ __u16 res_mask;
+
+ bool hw_ctrld;
+
+ void (*recalc) (struct clk *);
+ int (*set_rate) (struct clk *, unsigned long);
+ unsigned long (*get_rate) (struct clk *);
+ unsigned long (*round_rate) (struct clk *, unsigned long);
+ void (*init) (struct clk *);
+ void (*enable) (struct clk *);
+ void (*disable) (struct clk *);
+};
+
+void u300_clock_primecells(void);
+void u300_unclock_primecells(void);
+void u300_enable_intcon_clock(void);
+void u300_enable_timer_clock(void);
+
+#endif
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
new file mode 100644
index 000000000000..1f2ed21a0ab1
--- /dev/null
+++ b/arch/arm/mach-u300/core.c
@@ -0,0 +1,649 @@
+/*
+ *
+ * arch/arm/mach-u300/core.c
+ *
+ *
+ * Copyright (C) 2007-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Core platform support, IRQ handling and device definitions.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/termios.h>
+#include <linux/amba/bus.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware/vic.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/syscon.h>
+
+#include "clock.h"
+#include "mmc.h"
+
+/*
+ * Static I/O mappings that are needed for booting the U300 platforms. The
+ * only things we need are the areas where we find the timer, syscon and
+ * intcon, since the remaining device drivers will map their own memory
+ * physical to virtual as the need arise.
+ */
+static struct map_desc u300_io_desc[] __initdata = {
+ {
+ .virtual = U300_SLOW_PER_VIRT_BASE,
+ .pfn = __phys_to_pfn(U300_SLOW_PER_PHYS_BASE),
+ .length = SZ_64K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = U300_AHB_PER_VIRT_BASE,
+ .pfn = __phys_to_pfn(U300_AHB_PER_PHYS_BASE),
+ .length = SZ_32K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = U300_FAST_PER_VIRT_BASE,
+ .pfn = __phys_to_pfn(U300_FAST_PER_PHYS_BASE),
+ .length = SZ_32K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = 0xffff2000, /* TCM memory */
+ .pfn = __phys_to_pfn(0xffff2000),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+
+ /*
+ * This overlaps with the IRQ vectors etc at 0xffff0000, so these
+ * may have to be moved to 0x00000000 in order to use the ROM.
+ */
+ /*
+ {
+ .virtual = U300_BOOTROM_VIRT_BASE,
+ .pfn = __phys_to_pfn(U300_BOOTROM_PHYS_BASE),
+ .length = SZ_64K,
+ .type = MT_ROM,
+ },
+ */
+};
+
+void __init u300_map_io(void)
+{
+ iotable_init(u300_io_desc, ARRAY_SIZE(u300_io_desc));
+}
+
+/*
+ * Declaration of devices found on the U300 board and
+ * their respective memory locations.
+ */
+static struct amba_device uart0_device = {
+ .dev = {
+ .init_name = "uart0", /* Slow device at 0x3000 offset */
+ .platform_data = NULL,
+ },
+ .res = {
+ .start = U300_UART0_BASE,
+ .end = U300_UART0_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = { IRQ_U300_UART0, NO_IRQ },
+};
+
+/* The U335 have an additional UART1 on the APP CPU */
+#ifdef CONFIG_MACH_U300_BS335
+static struct amba_device uart1_device = {
+ .dev = {
+ .init_name = "uart1", /* Fast device at 0x7000 offset */
+ .platform_data = NULL,
+ },
+ .res = {
+ .start = U300_UART1_BASE,
+ .end = U300_UART1_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = { IRQ_U300_UART1, NO_IRQ },
+};
+#endif
+
+static struct amba_device pl172_device = {
+ .dev = {
+ .init_name = "pl172", /* AHB device at 0x4000 offset */
+ .platform_data = NULL,
+ },
+ .res = {
+ .start = U300_EMIF_CFG_BASE,
+ .end = U300_EMIF_CFG_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+
+/*
+ * Everything within this next ifdef deals with external devices connected to
+ * the APP SPI bus.
+ */
+static struct amba_device pl022_device = {
+ .dev = {
+ .coherent_dma_mask = ~0,
+ .init_name = "pl022", /* Fast device at 0x6000 offset */
+ },
+ .res = {
+ .start = U300_SPI_BASE,
+ .end = U300_SPI_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = {IRQ_U300_SPI, NO_IRQ },
+ /*
+ * This device has a DMA channel but the Linux driver does not use
+ * it currently.
+ */
+};
+
+static struct amba_device mmcsd_device = {
+ .dev = {
+ .init_name = "mmci", /* Fast device at 0x1000 offset */
+ .platform_data = NULL, /* Added later */
+ },
+ .res = {
+ .start = U300_MMCSD_BASE,
+ .end = U300_MMCSD_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = {IRQ_U300_MMCSD_MCIINTR0, IRQ_U300_MMCSD_MCIINTR1 },
+ /*
+ * This device has a DMA channel but the Linux driver does not use
+ * it currently.
+ */
+};
+
+/*
+ * The order of device declaration may be important, since some devices
+ * have dependencies on other devices being initialized first.
+ */
+static struct amba_device *amba_devs[] __initdata = {
+ &uart0_device,
+#ifdef CONFIG_MACH_U300_BS335
+ &uart1_device,
+#endif
+ &pl022_device,
+ &pl172_device,
+ &mmcsd_device,
+};
+
+/* Here follows a list of all hw resources that the platform devices
+ * allocate. Note, clock dependencies are not included
+ */
+
+static struct resource gpio_resources[] = {
+ {
+ .start = U300_GPIO_BASE,
+ .end = (U300_GPIO_BASE + SZ_4K - 1),
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "gpio0",
+ .start = IRQ_U300_GPIO_PORT0,
+ .end = IRQ_U300_GPIO_PORT0,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "gpio1",
+ .start = IRQ_U300_GPIO_PORT1,
+ .end = IRQ_U300_GPIO_PORT1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "gpio2",
+ .start = IRQ_U300_GPIO_PORT2,
+ .end = IRQ_U300_GPIO_PORT2,
+ .flags = IORESOURCE_IRQ,
+ },
+#ifdef U300_COH901571_3
+ {
+ .name = "gpio3",
+ .start = IRQ_U300_GPIO_PORT3,
+ .end = IRQ_U300_GPIO_PORT3,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "gpio4",
+ .start = IRQ_U300_GPIO_PORT4,
+ .end = IRQ_U300_GPIO_PORT4,
+ .flags = IORESOURCE_IRQ,
+ },
+#ifdef CONFIG_MACH_U300_BS335
+ {
+ .name = "gpio5",
+ .start = IRQ_U300_GPIO_PORT5,
+ .end = IRQ_U300_GPIO_PORT5,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "gpio6",
+ .start = IRQ_U300_GPIO_PORT6,
+ .end = IRQ_U300_GPIO_PORT6,
+ .flags = IORESOURCE_IRQ,
+ },
+#endif /* CONFIG_MACH_U300_BS335 */
+#endif /* U300_COH901571_3 */
+};
+
+static struct resource keypad_resources[] = {
+ {
+ .start = U300_KEYPAD_BASE,
+ .end = U300_KEYPAD_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "coh901461-press",
+ .start = IRQ_U300_KEYPAD_KEYBF,
+ .end = IRQ_U300_KEYPAD_KEYBF,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "coh901461-release",
+ .start = IRQ_U300_KEYPAD_KEYBR,
+ .end = IRQ_U300_KEYPAD_KEYBR,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource rtc_resources[] = {
+ {
+ .start = U300_RTC_BASE,
+ .end = U300_RTC_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_U300_RTC,
+ .end = IRQ_U300_RTC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/*
+ * Fsmc does have IRQs: #43 and #44 (NFIF and NFIF2)
+ * but these are not yet used by the driver.
+ */
+static struct resource fsmc_resources[] = {
+ {
+ .start = U300_NAND_IF_PHYS_BASE,
+ .end = U300_NAND_IF_PHYS_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct resource i2c0_resources[] = {
+ {
+ .start = U300_I2C0_BASE,
+ .end = U300_I2C0_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_U300_I2C0,
+ .end = IRQ_U300_I2C0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource i2c1_resources[] = {
+ {
+ .start = U300_I2C1_BASE,
+ .end = U300_I2C1_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_U300_I2C1,
+ .end = IRQ_U300_I2C1,
+ .flags = IORESOURCE_IRQ,
+ },
+
+};
+
+static struct resource wdog_resources[] = {
+ {
+ .start = U300_WDOG_BASE,
+ .end = U300_WDOG_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_U300_WDOG,
+ .end = IRQ_U300_WDOG,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+/* TODO: These should be protected by suitable #ifdef's */
+static struct resource ave_resources[] = {
+ {
+ .name = "AVE3e I/O Area",
+ .start = U300_VIDEOENC_BASE,
+ .end = U300_VIDEOENC_BASE + SZ_512K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "AVE3e IRQ0",
+ .start = IRQ_U300_VIDEO_ENC_0,
+ .end = IRQ_U300_VIDEO_ENC_0,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "AVE3e IRQ1",
+ .start = IRQ_U300_VIDEO_ENC_1,
+ .end = IRQ_U300_VIDEO_ENC_1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "AVE3e Physmem Area",
+ .start = 0, /* 0 will be remapped to reserved memory */
+ .end = SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ /*
+ * The AVE3e requires two regions of 256MB that it considers
+ * "invisible". The hardware will not be able to access these
+ * adresses, so they should never point to system RAM.
+ */
+ {
+ .name = "AVE3e Reserved 0",
+ .start = 0xd0000000,
+ .end = 0xd0000000 + SZ_256M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "AVE3e Reserved 1",
+ .start = 0xe0000000,
+ .end = 0xe0000000 + SZ_256M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device wdog_device = {
+ .name = "wdog",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(wdog_resources),
+ .resource = wdog_resources,
+};
+
+static struct platform_device i2c0_device = {
+ .name = "stddci2c",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(i2c0_resources),
+ .resource = i2c0_resources,
+};
+
+static struct platform_device i2c1_device = {
+ .name = "stddci2c",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(i2c1_resources),
+ .resource = i2c1_resources,
+};
+
+static struct platform_device gpio_device = {
+ .name = "u300-gpio",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(gpio_resources),
+ .resource = gpio_resources,
+};
+
+static struct platform_device keypad_device = {
+ .name = "keypad",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(keypad_resources),
+ .resource = keypad_resources,
+};
+
+static struct platform_device rtc_device = {
+ .name = "rtc0",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+ .resource = rtc_resources,
+};
+
+static struct platform_device fsmc_device = {
+ .name = "nandif",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(fsmc_resources),
+ .resource = fsmc_resources,
+};
+
+static struct platform_device ave_device = {
+ .name = "video_enc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ave_resources),
+ .resource = ave_resources,
+};
+
+/*
+ * Notice that AMBA devices are initialized before platform devices.
+ *
+ */
+static struct platform_device *platform_devs[] __initdata = {
+ &i2c0_device,
+ &i2c1_device,
+ &keypad_device,
+ &rtc_device,
+ &gpio_device,
+ &fsmc_device,
+ &wdog_device,
+ &ave_device
+};
+
+
+/*
+ * Interrupts: the U300 platforms have two pl190 ARM PrimeCells connected
+ * together so some interrupts are connected to the first one and some
+ * to the second one.
+ */
+void __init u300_init_irq(void)
+{
+ u32 mask[2] = {0, 0};
+ int i;
+
+ for (i = 0; i < NR_IRQS; i++)
+ set_bit(i, (unsigned long *) &mask[0]);
+ u300_enable_intcon_clock();
+ vic_init((void __iomem *) U300_INTCON0_VBASE, 0, mask[0]);
+ vic_init((void __iomem *) U300_INTCON1_VBASE, 32, mask[1]);
+}
+
+
+/*
+ * U300 platforms peripheral handling
+ */
+struct db_chip {
+ u16 chipid;
+ const char *name;
+};
+
+/*
+ * This is a list of the Digital Baseband chips used in the U300 platform.
+ */
+static struct db_chip db_chips[] __initdata = {
+ {
+ .chipid = 0xb800,
+ .name = "DB3000",
+ },
+ {
+ .chipid = 0xc000,
+ .name = "DB3100",
+ },
+ {
+ .chipid = 0xc800,
+ .name = "DB3150",
+ },
+ {
+ .chipid = 0xd800,
+ .name = "DB3200",
+ },
+ {
+ .chipid = 0xe000,
+ .name = "DB3250",
+ },
+ {
+ .chipid = 0xe800,
+ .name = "DB3210",
+ },
+ {
+ .chipid = 0xf000,
+ .name = "DB3350 P1x",
+ },
+ {
+ .chipid = 0xf100,
+ .name = "DB3350 P2x",
+ },
+ {
+ .chipid = 0x0000, /* List terminator */
+ .name = NULL,
+ }
+};
+
+static void u300_init_check_chip(void)
+{
+
+ u16 val;
+ struct db_chip *chip;
+ const char *chipname;
+ const char unknown[] = "UNKNOWN";
+
+ /* Read out and print chip ID */
+ val = readw(U300_SYSCON_VBASE + U300_SYSCON_CIDR);
+ /* This is in funky bigendian order... */
+ val = (val & 0xFFU) << 8 | (val >> 8);
+ chip = db_chips;
+ chipname = unknown;
+
+ for ( ; chip->chipid; chip++) {
+ if (chip->chipid == (val & 0xFF00U)) {
+ chipname = chip->name;
+ break;
+ }
+ }
+ printk(KERN_INFO "Initializing U300 system on %s baseband chip " \
+ "(chip ID 0x%04x)\n", chipname, val);
+
+#ifdef CONFIG_MACH_U300_BS26
+ if ((val & 0xFF00U) != 0xc800) {
+ printk(KERN_ERR "Platform configured for BS25/BS26 " \
+ "with DB3150 but %s detected, expect problems!",
+ chipname);
+ }
+#endif
+#ifdef CONFIG_MACH_U300_BS330
+ if ((val & 0xFF00U) != 0xd800) {
+ printk(KERN_ERR "Platform configured for BS330 " \
+ "with DB3200 but %s detected, expect problems!",
+ chipname);
+ }
+#endif
+#ifdef CONFIG_MACH_U300_BS335
+ if ((val & 0xFF00U) != 0xf000 && (val & 0xFF00U) != 0xf100) {
+ printk(KERN_ERR "Platform configured for BS365 " \
+ " with DB3350 but %s detected, expect problems!",
+ chipname);
+ }
+#endif
+#ifdef CONFIG_MACH_U300_BS365
+ if ((val & 0xFF00U) != 0xe800) {
+ printk(KERN_ERR "Platform configured for BS365 " \
+ "with DB3210 but %s detected, expect problems!",
+ chipname);
+ }
+#endif
+
+
+}
+
+/*
+ * Some devices and their resources require reserved physical memory from
+ * the end of the available RAM. This function traverses the list of devices
+ * and assigns actual adresses to these.
+ */
+static void __init u300_assign_physmem(void)
+{
+ unsigned long curr_start = __pa(high_memory);
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(platform_devs); i++) {
+ for (j = 0; j < platform_devs[i]->num_resources; j++) {
+ struct resource *const res =
+ &platform_devs[i]->resource[j];
+
+ if (IORESOURCE_MEM == res->flags &&
+ 0 == res->start) {
+ res->start = curr_start;
+ res->end += curr_start;
+ curr_start += (res->end - res->start + 1);
+
+ printk(KERN_INFO "core.c: Mapping RAM " \
+ "%#x-%#x to device %s:%s\n",
+ res->start, res->end,
+ platform_devs[i]->name, res->name);
+ }
+ }
+ }
+}
+
+void __init u300_init_devices(void)
+{
+ int i;
+ u16 val;
+
+ /* Check what platform we run and print some status information */
+ u300_init_check_chip();
+
+ /* Set system to run at PLL208, max performance, a known state. */
+ val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
+ val &= ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+ /* Wait for the PLL208 to lock if not locked in yet */
+ while (!(readw(U300_SYSCON_VBASE + U300_SYSCON_CSR) &
+ U300_SYSCON_CSR_PLL208_LOCK_IND));
+
+ /* Register the AMBA devices in the AMBA bus abstraction layer */
+ u300_clock_primecells();
+ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+ struct amba_device *d = amba_devs[i];
+ amba_device_register(d, &iomem_resource);
+ }
+ u300_unclock_primecells();
+
+ u300_assign_physmem();
+
+ /* Register the platform devices */
+ platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
+
+#ifndef CONFIG_MACH_U300_SEMI_IS_SHARED
+ /*
+ * Enable SEMI self refresh. Self-refresh of the SDRAM is entered when
+ * both subsystems are requesting this mode.
+ * If we not share the Acc SDRAM, this is never the case. Therefore
+ * enable it here from the App side.
+ */
+ val = readw(U300_SYSCON_VBASE + U300_SYSCON_SMCR) |
+ U300_SYSCON_SMCR_SEMI_SREFREQ_ENABLE;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_SMCR);
+#endif /* CONFIG_MACH_U300_SEMI_IS_SHARED */
+}
+
+static int core_module_init(void)
+{
+ /*
+ * This needs to be initialized later: it needs the input framework
+ * to be initialized first.
+ */
+ return mmc_init(&mmcsd_device);
+}
+module_init(core_module_init);
diff --git a/arch/arm/mach-u300/gpio.c b/arch/arm/mach-u300/gpio.c
new file mode 100644
index 000000000000..2d5ae8ecb8c8
--- /dev/null
+++ b/arch/arm/mach-u300/gpio.c
@@ -0,0 +1,701 @@
+/*
+ *
+ * arch/arm/mach-u300/gpio.c
+ *
+ *
+ * Copyright (C) 2007-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * U300 GPIO module.
+ * This can driver either of the two basic GPIO cores
+ * available in the U300 platforms:
+ * COH 901 335 - Used in DB3150 (U300 1.0) and DB3200 (U330 1.0)
+ * COH 901 571/3 - Used in DB3210 (U365 2.0) and DB3350 (U335 1.0)
+ * Notice that you also have inline macros in <asm-arch/gpio.h>
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
+ *
+ */
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+/* Need access to SYSCON registers for PADmuxing */
+#include <mach/syscon.h>
+
+#include "padmux.h"
+
+/* Reference to GPIO block clock */
+static struct clk *clk;
+
+/* Memory resource */
+static struct resource *memres;
+static void __iomem *virtbase;
+
+struct u300_gpio_port {
+ const char *name;
+ int irq;
+ int number;
+};
+
+
+static struct u300_gpio_port gpio_ports[] = {
+ {
+ .name = "gpio0",
+ .number = 0,
+ },
+ {
+ .name = "gpio1",
+ .number = 1,
+ },
+ {
+ .name = "gpio2",
+ .number = 2,
+ },
+#ifdef U300_COH901571_3
+ {
+ .name = "gpio3",
+ .number = 3,
+ },
+ {
+ .name = "gpio4",
+ .number = 4,
+ },
+#ifdef CONFIG_MACH_U300_BS335
+ {
+ .name = "gpio5",
+ .number = 5,
+ },
+ {
+ .name = "gpio6",
+ .number = 6,
+ },
+#endif
+#endif
+
+};
+
+
+#ifdef U300_COH901571_3
+
+/* Default input value */
+#define DEFAULT_OUTPUT_LOW 0
+#define DEFAULT_OUTPUT_HIGH 1
+
+/* GPIO Pull-Up status */
+#define DISABLE_PULL_UP 0
+#define ENABLE_PULL_UP 1
+
+#define GPIO_NOT_USED 0
+#define GPIO_IN 1
+#define GPIO_OUT 2
+
+struct u300_gpio_configuration_data {
+ unsigned char pin_usage;
+ unsigned char default_output_value;
+ unsigned char pull_up;
+};
+
+/* Initial configuration */
+const struct u300_gpio_configuration_data
+u300_gpio_config[U300_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
+#ifdef CONFIG_MACH_U300_BS335
+ /* Port 0, pins 0-7 */
+ {
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_HIGH, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
+ },
+ /* Port 1, pins 0-7 */
+ {
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_HIGH, DISABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
+ },
+ /* Port 2, pins 0-7 */
+ {
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}
+ },
+ /* Port 3, pins 0-7 */
+ {
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
+ },
+ /* Port 4, pins 0-7 */
+ {
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
+ },
+ /* Port 5, pins 0-7 */
+ {
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
+ },
+ /* Port 6, pind 0-7 */
+ {
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
+ }
+#endif
+
+#ifdef CONFIG_MACH_U300_BS365
+ /* Port 0, pins 0-7 */
+ {
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
+ },
+ /* Port 1, pins 0-7 */
+ {
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_HIGH, DISABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
+ },
+ /* Port 2, pins 0-7 */
+ {
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}
+ },
+ /* Port 3, pins 0-7 */
+ {
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}
+ },
+ /* Port 4, pins 0-7 */
+ {
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ /* These 4 pins doesn't exist on DB3210 */
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ {GPIO_OUT, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}
+ }
+#endif
+};
+#endif
+
+
+/* No users == we can power down GPIO */
+static int gpio_users;
+
+struct gpio_struct {
+ int (*callback)(void *);
+ void *data;
+ int users;
+};
+
+static struct gpio_struct gpio_pin[U300_GPIO_MAX];
+
+/*
+ * Let drivers register callback in order to get notified when there is
+ * an interrupt on the gpio pin
+ */
+int gpio_register_callback(unsigned gpio, int (*func)(void *arg), void *data)
+{
+ if (gpio_pin[gpio].callback)
+ printk(KERN_WARNING "GPIO: %s: WARNING: callback already " \
+ "registered for gpio pin#%d\n", __func__, gpio);
+ gpio_pin[gpio].callback = func;
+ gpio_pin[gpio].data = data;
+
+ return 0;
+}
+EXPORT_SYMBOL(gpio_register_callback);
+
+int gpio_unregister_callback(unsigned gpio)
+{
+ if (!gpio_pin[gpio].callback)
+ printk(KERN_WARNING "GPIO: %s: WARNING: callback already " \
+ "unregistered for gpio pin#%d\n", __func__, gpio);
+ gpio_pin[gpio].callback = NULL;
+ gpio_pin[gpio].data = NULL;
+
+ return 0;
+}
+EXPORT_SYMBOL(gpio_unregister_callback);
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ if (gpio_pin[gpio].users)
+ return -EINVAL;
+ else
+ gpio_pin[gpio].users++;
+
+ gpio_users++;
+
+ return 0;
+}
+EXPORT_SYMBOL(gpio_request);
+
+void gpio_free(unsigned gpio)
+{
+ gpio_users--;
+ gpio_pin[gpio].users--;
+ if (unlikely(gpio_pin[gpio].users < 0)) {
+ printk(KERN_WARNING "GPIO: Warning: gpio#%d release mismatch\n",
+ gpio);
+ gpio_pin[gpio].users = 0;
+ }
+
+ return;
+}
+EXPORT_SYMBOL(gpio_free);
+
+/* This returns zero or nonzero */
+int gpio_get_value(unsigned gpio)
+{
+ return readl(virtbase + U300_GPIO_PXPDIR +
+ PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING) & (1 << (gpio & 0x07));
+}
+EXPORT_SYMBOL(gpio_get_value);
+
+/*
+ * We hope that the compiler will optimize away the unused branch
+ * in case "value" is a constant
+ */
+void gpio_set_value(unsigned gpio, int value)
+{
+ u32 val;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ if (value) {
+ /* set */
+ val = readl(virtbase + U300_GPIO_PXPDOR +
+ PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING)
+ & (1 << (gpio & 0x07));
+ writel(val | (1 << (gpio & 0x07)), virtbase +
+ U300_GPIO_PXPDOR +
+ PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
+ } else {
+ /* clear */
+ val = readl(virtbase + U300_GPIO_PXPDOR +
+ PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING)
+ & (1 << (gpio & 0x07));
+ writel(val & ~(1 << (gpio & 0x07)), virtbase +
+ U300_GPIO_PXPDOR +
+ PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
+ }
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_set_value);
+
+int gpio_direction_input(unsigned gpio)
+{
+ unsigned long flags;
+ u32 val;
+
+ if (gpio > U300_GPIO_MAX)
+ return -EINVAL;
+
+ local_irq_save(flags);
+ val = readl(virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
+ U300_GPIO_PORTX_SPACING);
+ /* Mask out this pin*/
+ val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((gpio & 0x07) << 1));
+ /* This is not needed since it sets the bits to zero.*/
+ /* val |= (U300_GPIO_PXPCR_PIN_MODE_INPUT << (gpio*2)); */
+ writel(val, virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
+ U300_GPIO_PORTX_SPACING);
+ local_irq_restore(flags);
+ return 0;
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ unsigned long flags;
+ u32 val;
+
+ if (gpio > U300_GPIO_MAX)
+ return -EINVAL;
+
+ local_irq_save(flags);
+ val = readl(virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
+ U300_GPIO_PORTX_SPACING);
+ /* Mask out this pin */
+ val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((gpio & 0x07) << 1));
+ /*
+ * FIXME: configure for push/pull, open drain or open source per pin
+ * in setup. The current driver will only support push/pull.
+ */
+ val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL
+ << ((gpio & 0x07) << 1));
+ writel(val, virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
+ U300_GPIO_PORTX_SPACING);
+ gpio_set_value(gpio, value);
+ local_irq_restore(flags);
+ return 0;
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+/*
+ * Enable an IRQ, edge is rising edge (!= 0) or falling edge (==0).
+ */
+void enable_irq_on_gpio_pin(unsigned gpio, int edge)
+{
+ u32 val;
+ unsigned long flags;
+ local_irq_save(flags);
+
+ val = readl(virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
+ U300_GPIO_PORTX_SPACING);
+ val |= (1 << (gpio & 0x07));
+ writel(val, virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
+ U300_GPIO_PORTX_SPACING);
+ val = readl(virtbase + U300_GPIO_PXICR + PIN_TO_PORT(gpio) *
+ U300_GPIO_PORTX_SPACING);
+ if (edge)
+ val |= (1 << (gpio & 0x07));
+ else
+ val &= ~(1 << (gpio & 0x07));
+ writel(val, virtbase + U300_GPIO_PXICR + PIN_TO_PORT(gpio) *
+ U300_GPIO_PORTX_SPACING);
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(enable_irq_on_gpio_pin);
+
+void disable_irq_on_gpio_pin(unsigned gpio)
+{
+ u32 val;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ val = readl(virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
+ U300_GPIO_PORTX_SPACING);
+ val &= ~(1 << (gpio & 0x07));
+ writel(val, virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
+ U300_GPIO_PORTX_SPACING);
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(disable_irq_on_gpio_pin);
+
+/* Enable (value == 0) or disable (value == 1) internal pullup */
+void gpio_pullup(unsigned gpio, int value)
+{
+ u32 val;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ if (value) {
+ val = readl(virtbase + U300_GPIO_PXPER + PIN_TO_PORT(gpio) *
+ U300_GPIO_PORTX_SPACING);
+ writel(val | (1 << (gpio & 0x07)), virtbase + U300_GPIO_PXPER +
+ PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
+ } else {
+ val = readl(virtbase + U300_GPIO_PXPER + PIN_TO_PORT(gpio) *
+ U300_GPIO_PORTX_SPACING);
+ writel(val & ~(1 << (gpio & 0x07)), virtbase + U300_GPIO_PXPER +
+ PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
+ }
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_pullup);
+
+static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
+{
+ struct u300_gpio_port *port = dev_id;
+ u32 val;
+ int pin;
+
+ /* Read event register */
+ val = readl(virtbase + U300_GPIO_PXIEV + port->number *
+ U300_GPIO_PORTX_SPACING);
+ /* Mask with enable register */
+ val &= readl(virtbase + U300_GPIO_PXIEV + port->number *
+ U300_GPIO_PORTX_SPACING);
+ /* Mask relevant bits */
+ val &= U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK;
+ /* ACK IRQ (clear event) */
+ writel(val, virtbase + U300_GPIO_PXIEV + port->number *
+ U300_GPIO_PORTX_SPACING);
+ /* Print message */
+ while (val != 0) {
+ unsigned gpio;
+
+ pin = __ffs(val);
+ /* mask off this pin */
+ val &= ~(1 << pin);
+ gpio = (port->number << 3) + pin;
+
+ if (gpio_pin[gpio].callback)
+ (void)gpio_pin[gpio].callback(gpio_pin[gpio].data);
+ else
+ printk(KERN_DEBUG "GPIO: Stray GPIO IRQ on line %d\n",
+ gpio);
+ }
+ return IRQ_HANDLED;
+}
+
+static void gpio_set_initial_values(void)
+{
+#ifdef U300_COH901571_3
+ int i, j;
+ unsigned long flags;
+ u32 val;
+
+ /* Write default values to all pins */
+ for (i = 0; i < U300_GPIO_NUM_PORTS; i++) {
+ val = 0;
+ for (j = 0; j < 8; j++)
+ val |= (u32) (u300_gpio_config[i][j].default_output_value != DEFAULT_OUTPUT_LOW) << j;
+ local_irq_save(flags);
+ writel(val, virtbase + U300_GPIO_PXPDOR + i * U300_GPIO_PORTX_SPACING);
+ local_irq_restore(flags);
+ }
+
+ /*
+ * Put all pins that are set to either 'GPIO_OUT' or 'GPIO_NOT_USED'
+ * to output and 'GPIO_IN' to input for each port. And initalize
+ * default value on outputs.
+ */
+ for (i = 0; i < U300_GPIO_NUM_PORTS; i++) {
+ for (j = 0; j < U300_GPIO_PINS_PER_PORT; j++) {
+ local_irq_save(flags);
+ val = readl(virtbase + U300_GPIO_PXPCR +
+ i * U300_GPIO_PORTX_SPACING);
+ /* Mask out this pin */
+ val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << (j << 1));
+
+ if (u300_gpio_config[i][j].pin_usage != GPIO_IN)
+ val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL << (j << 1));
+ writel(val, virtbase + U300_GPIO_PXPCR +
+ i * U300_GPIO_PORTX_SPACING);
+ local_irq_restore(flags);
+ }
+ }
+
+ /* Enable or disable the internal pull-ups in the GPIO ASIC block */
+ for (i = 0; i < U300_GPIO_MAX; i++) {
+ val = 0;
+ for (j = 0; j < 8; j++)
+ val |= (u32)((u300_gpio_config[i][j].pull_up == DISABLE_PULL_UP)) << j;
+ local_irq_save(flags);
+ writel(val, virtbase + U300_GPIO_PXPER + i * U300_GPIO_PORTX_SPACING);
+ local_irq_restore(flags);
+ }
+#endif
+}
+
+static int __devinit gpio_probe(struct platform_device *pdev)
+{
+ u32 val;
+ int err = 0;
+ int i;
+ int num_irqs;
+
+ memset(gpio_pin, 0, sizeof(gpio_pin));
+
+ /* Get GPIO clock */
+ clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk)) {
+ err = PTR_ERR(clk);
+ printk(KERN_ERR "GPIO: could not get GPIO clock\n");
+ goto err_no_clk;
+ }
+ err = clk_enable(clk);
+ if (err) {
+ printk(KERN_ERR "GPIO: could not enable GPIO clock\n");
+ goto err_no_clk_enable;
+ }
+
+ memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!memres)
+ goto err_no_resource;
+
+ if (request_mem_region(memres->start, memres->end - memres->start, "GPIO Controller")
+ == NULL) {
+ err = -ENODEV;
+ goto err_no_ioregion;
+ }
+
+ virtbase = ioremap(memres->start, memres->end - memres->start + 1);
+ if (!virtbase) {
+ err = -ENOMEM;
+ goto err_no_ioremap;
+ }
+
+#ifdef U300_COH901335
+ printk(KERN_INFO "GPIO: Initializing GPIO Controller COH 901 335\n");
+ /* Turn on the GPIO block */
+ writel(U300_GPIO_CR_BLOCK_CLOCK_ENABLE, virtbase + U300_GPIO_CR);
+#endif
+
+#ifdef U300_COH901571_3
+ printk(KERN_INFO "GPIO: Initializing GPIO Controller COH 901 571/3\n");
+ val = readl(virtbase + U300_GPIO_CR);
+ printk(KERN_INFO "GPIO: COH901571/3 block version: %d, " \
+ "number of cores: %d\n",
+ ((val & 0x0000FE00) >> 9),
+ ((val & 0x000001FC) >> 2));
+ writel(U300_GPIO_CR_BLOCK_CLKRQ_ENABLE, virtbase + U300_GPIO_CR);
+#endif
+
+ /* Set up some padmuxing here */
+#ifdef CONFIG_MMC
+ pmx_set_mission_mode_mmc();
+#endif
+#ifdef CONFIG_SPI_PL022
+ pmx_set_mission_mode_spi();
+#endif
+
+ gpio_set_initial_values();
+
+ for (num_irqs = 0 ; num_irqs < U300_GPIO_NUM_PORTS; num_irqs++) {
+
+ gpio_ports[num_irqs].irq =
+ platform_get_irq_byname(pdev,
+ gpio_ports[num_irqs].name);
+
+ err = request_irq(gpio_ports[num_irqs].irq,
+ gpio_irq_handler, IRQF_DISABLED,
+ gpio_ports[num_irqs].name,
+ &gpio_ports[num_irqs]);
+ if (err) {
+ printk(KERN_CRIT "GPIO: Cannot allocate IRQ for %s!\n",
+ gpio_ports[num_irqs].name);
+ goto err_no_irq;
+ }
+ /* Turns off PortX_irq_force */
+ writel(0x0, virtbase + U300_GPIO_PXIFR +
+ num_irqs * U300_GPIO_PORTX_SPACING);
+ }
+ printk(KERN_INFO "GPIO: U300 gpio module loaded\n");
+
+ return 0;
+
+ err_no_irq:
+ for (i = 0; i < num_irqs; i++)
+ free_irq(gpio_ports[i].irq, &gpio_ports[i]);
+ iounmap(virtbase);
+ err_no_ioremap:
+ release_mem_region(memres->start, memres->end - memres->start);
+ err_no_ioregion:
+ err_no_resource:
+ clk_disable(clk);
+ err_no_clk_enable:
+ clk_put(clk);
+ err_no_clk:
+ printk(KERN_INFO "GPIO: module ERROR:%d\n", err);
+ return err;
+}
+
+static int __devexit gpio_remove(struct platform_device *pdev)
+{
+ int i;
+
+ /* Turn off the GPIO block */
+ writel(0x00000000U, virtbase + U300_GPIO_CR);
+ for (i = 0 ; i < U300_GPIO_NUM_PORTS; i++)
+ free_irq(gpio_ports[i].irq, &gpio_ports[i]);
+ iounmap(virtbase);
+ release_mem_region(memres->start, memres->end - memres->start);
+ clk_disable(clk);
+ clk_put(clk);
+ return 0;
+}
+
+static struct platform_driver gpio_driver = {
+ .driver = {
+ .name = "u300-gpio",
+ },
+ .probe = gpio_probe,
+ .remove = __devexit_p(gpio_remove),
+};
+
+
+static int __init u300_gpio_init(void)
+{
+ return platform_driver_register(&gpio_driver);
+}
+
+static void __exit u300_gpio_exit(void)
+{
+ platform_driver_unregister(&gpio_driver);
+}
+
+arch_initcall(u300_gpio_init);
+module_exit(u300_gpio_exit);
+
+MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
+
+#ifdef U300_COH901571_3
+MODULE_DESCRIPTION("ST-Ericsson AB COH 901 571/3 GPIO driver");
+#endif
+
+#ifdef U300_COH901335
+MODULE_DESCRIPTION("ST-Ericsson AB COH 901 335 GPIO driver");
+#endif
+
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-u300/include/mach/clkdev.h b/arch/arm/mach-u300/include/mach/clkdev.h
new file mode 100644
index 000000000000..92e3cc872c66
--- /dev/null
+++ b/arch/arm/mach-u300/include/mach/clkdev.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_CLKDEV_H
+#define __MACH_CLKDEV_H
+
+int __clk_get(struct clk *clk);
+void __clk_put(struct clk *clk);
+
+#endif
diff --git a/arch/arm/mach-u300/include/mach/debug-macro.S b/arch/arm/mach-u300/include/mach/debug-macro.S
new file mode 100644
index 000000000000..f3a1cbbeeab3
--- /dev/null
+++ b/arch/arm/mach-u300/include/mach/debug-macro.S
@@ -0,0 +1,22 @@
+/*
+ *
+ * arch-arm/mach-u300/include/mach/debug-macro.S
+ *
+ *
+ * Copyright (C) 2006-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Debugging macro include header.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+#include <mach/hardware.h>
+
+ .macro addruart,rx
+ /* If we move the adress using MMU, use this. */
+ mrc p15, 0, \rx, c1, c0
+ tst \rx, #1 @ MMU enabled?
+ ldreq \rx, = U300_SLOW_PER_PHYS_BASE @ MMU off, physical address
+ ldrne \rx, = U300_SLOW_PER_VIRT_BASE @ MMU on, virtual address
+ orr \rx, \rx, #0x00003000
+ .endm
+
+#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-u300/include/mach/entry-macro.S b/arch/arm/mach-u300/include/mach/entry-macro.S
new file mode 100644
index 000000000000..20731ae39d38
--- /dev/null
+++ b/arch/arm/mach-u300/include/mach/entry-macro.S
@@ -0,0 +1,40 @@
+/*
+ *
+ * arch-arm/mach-u300/include/mach/entry-macro.S
+ *
+ *
+ * Copyright (C) 2006-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Low-level IRQ helper macros for ST-Ericsson U300
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+#include <mach/hardware.h>
+#include <asm/hardware/vic.h>
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_preamble, base, tmp
+ .endm
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ ldr \base, = U300_AHB_PER_VIRT_BASE-U300_AHB_PER_PHYS_BASE+U300_INTCON0_BASE
+ ldr \irqstat, [\base, #VIC_IRQ_STATUS] @ get masked status
+ mov \irqnr, #0
+ teq \irqstat, #0
+ bne 1002f
+1001: ldr \base, = U300_AHB_PER_VIRT_BASE-U300_AHB_PER_PHYS_BASE+U300_INTCON1_BASE
+ ldr \irqstat, [\base, #VIC_IRQ_STATUS] @ get masked status
+ mov \irqnr, #32
+ teq \irqstat, #0
+ beq 1003f
+1002: tst \irqstat, #1
+ bne 1003f
+ add \irqnr, \irqnr, #1
+ movs \irqstat, \irqstat, lsr #1
+ bne 1002b
+1003: /* EQ will be set if no irqs pending */
+ .endm
diff --git a/arch/arm/mach-u300/include/mach/gpio.h b/arch/arm/mach-u300/include/mach/gpio.h
new file mode 100644
index 000000000000..c8174128d7eb
--- /dev/null
+++ b/arch/arm/mach-u300/include/mach/gpio.h
@@ -0,0 +1,290 @@
+/*
+ *
+ * arch/arm/mach-u300/include/mach/gpio.h
+ *
+ *
+ * Copyright (C) 2007-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * GPIO block resgister definitions and inline macros for
+ * U300 GPIO COH 901 335 or COH 901 571/3
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+
+#ifndef __MACH_U300_GPIO_H
+#define __MACH_U300_GPIO_H
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include <asm/irq.h>
+
+/* Switch type depending on platform/chip variant */
+#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
+#define U300_COH901335
+#endif
+#if defined(CONFIG_MACH_U300_BS365) || defined(CONFIG_MACH_U300_BS335)
+#define U300_COH901571_3
+#endif
+
+/* Get base address for regs here */
+#include "u300-regs.h"
+/* IRQ numbers */
+#include "irqs.h"
+
+/*
+ * This is the GPIO block definitions. GPIO (General Purpose I/O) can be
+ * used for anything, and often is. The event/enable etc figures are for
+ * the lowermost pin (pin 0 on each port), shift this left to match your
+ * pin if you're gonna use these values.
+ */
+#ifdef U300_COH901335
+#define U300_GPIO_PORTX_SPACING (0x1C)
+/* Port X Pin Data Register 32bit, this is both input and output (R/W) */
+#define U300_GPIO_PXPDIR (0x00)
+#define U300_GPIO_PXPDOR (0x00)
+/* Port X Pin Config Register 32bit (R/W) */
+#define U300_GPIO_PXPCR (0x04)
+#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK (0x0000FFFFUL)
+#define U300_GPIO_PXPCR_PIN_MODE_MASK (0x00000003UL)
+#define U300_GPIO_PXPCR_PIN_MODE_SHIFT (0x00000002UL)
+#define U300_GPIO_PXPCR_PIN_MODE_INPUT (0x00000000UL)
+#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL (0x00000001UL)
+#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN (0x00000002UL)
+#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE (0x00000003UL)
+/* Port X Interrupt Event Register 32bit (R/W) */
+#define U300_GPIO_PXIEV (0x08)
+#define U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK (0x000000FFUL)
+#define U300_GPIO_PXIEV_IRQ_EVENT (0x00000001UL)
+/* Port X Interrupt Enable Register 32bit (R/W) */
+#define U300_GPIO_PXIEN (0x0C)
+#define U300_GPIO_PXIEN_ALL_IRQ_ENABLE_MASK (0x000000FFUL)
+#define U300_GPIO_PXIEN_IRQ_ENABLE (0x00000001UL)
+/* Port X Interrupt Force Register 32bit (R/W) */
+#define U300_GPIO_PXIFR (0x10)
+#define U300_GPIO_PXIFR_ALL_IRQ_FORCE_MASK (0x000000FFUL)
+#define U300_GPIO_PXIFR_IRQ_FORCE (0x00000001UL)
+/* Port X Interrupt Config Register 32bit (R/W) */
+#define U300_GPIO_PXICR (0x14)
+#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK (0x000000FFUL)
+#define U300_GPIO_PXICR_IRQ_CONFIG_MASK (0x00000001UL)
+#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE (0x00000000UL)
+#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE (0x00000001UL)
+/* Port X Pull-up Enable Register 32bit (R/W) */
+#define U300_GPIO_PXPER (0x18)
+#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK (0x000000FFUL)
+#define U300_GPIO_PXPER_PULL_UP_DISABLE (0x00000001UL)
+/* Control Register 32bit (R/W) */
+#define U300_GPIO_CR (0x54)
+#define U300_GPIO_CR_BLOCK_CLOCK_ENABLE (0x00000001UL)
+/* three ports of 8 bits each = GPIO pins 0..23 */
+#define U300_GPIO_NUM_PORTS 3
+#define U300_GPIO_PINS_PER_PORT 8
+#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS - 1)
+#endif
+
+#ifdef U300_COH901571_3
+/*
+ * Control Register 32bit (R/W)
+ * bit 15-9 (mask 0x0000FE00) contains the number of cores. 8*cores
+ * gives the number of GPIO pins.
+ * bit 8-2 (mask 0x000001FC) contains the core version ID.
+ */
+#define U300_GPIO_CR (0x00)
+#define U300_GPIO_CR_SYNC_SEL_ENABLE (0x00000002UL)
+#define U300_GPIO_CR_BLOCK_CLKRQ_ENABLE (0x00000001UL)
+#define U300_GPIO_PORTX_SPACING (0x30)
+/* Port X Pin Data INPUT Register 32bit (R/W) */
+#define U300_GPIO_PXPDIR (0x04)
+/* Port X Pin Data OUTPUT Register 32bit (R/W) */
+#define U300_GPIO_PXPDOR (0x08)
+/* Port X Pin Config Register 32bit (R/W) */
+#define U300_GPIO_PXPCR (0x0C)
+#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK (0x0000FFFFUL)
+#define U300_GPIO_PXPCR_PIN_MODE_MASK (0x00000003UL)
+#define U300_GPIO_PXPCR_PIN_MODE_SHIFT (0x00000002UL)
+#define U300_GPIO_PXPCR_PIN_MODE_INPUT (0x00000000UL)
+#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL (0x00000001UL)
+#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN (0x00000002UL)
+#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE (0x00000003UL)
+/* Port X Pull-up Enable Register 32bit (R/W) */
+#define U300_GPIO_PXPER (0x10)
+#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK (0x000000FFUL)
+#define U300_GPIO_PXPER_PULL_UP_DISABLE (0x00000001UL)
+/* Port X Interrupt Event Register 32bit (R/W) */
+#define U300_GPIO_PXIEV (0x14)
+#define U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK (0x000000FFUL)
+#define U300_GPIO_PXIEV_IRQ_EVENT (0x00000001UL)
+/* Port X Interrupt Enable Register 32bit (R/W) */
+#define U300_GPIO_PXIEN (0x18)
+#define U300_GPIO_PXIEN_ALL_IRQ_ENABLE_MASK (0x000000FFUL)
+#define U300_GPIO_PXIEN_IRQ_ENABLE (0x00000001UL)
+/* Port X Interrupt Force Register 32bit (R/W) */
+#define U300_GPIO_PXIFR (0x1C)
+#define U300_GPIO_PXIFR_ALL_IRQ_FORCE_MASK (0x000000FFUL)
+#define U300_GPIO_PXIFR_IRQ_FORCE (0x00000001UL)
+/* Port X Interrupt Config Register 32bit (R/W) */
+#define U300_GPIO_PXICR (0x20)
+#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK (0x000000FFUL)
+#define U300_GPIO_PXICR_IRQ_CONFIG_MASK (0x00000001UL)
+#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE (0x00000000UL)
+#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE (0x00000001UL)
+#ifdef CONFIG_MACH_U300_BS335
+/* seven ports of 8 bits each = GPIO pins 0..55 */
+#define U300_GPIO_NUM_PORTS 7
+#else
+/* five ports of 8 bits each = GPIO pins 0..39 */
+#define U300_GPIO_NUM_PORTS 5
+#endif
+#define U300_GPIO_PINS_PER_PORT 8
+#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS - 1)
+#endif
+
+/*
+ * Individual pin assignments for the B26/S26. Notice that the
+ * actual usage of these pins depends on the PAD MUX settings, that
+ * is why the same number can potentially appear several times.
+ * In the reference design each pin is only used for one purpose.
+ * These were determined by inspecting the B26/S26 schematic:
+ * 2/1911-ROA 128 1603
+ */
+#ifdef CONFIG_MACH_U300_BS2X
+#define U300_GPIO_PIN_UART_RX 0
+#define U300_GPIO_PIN_UART_TX 1
+#define U300_GPIO_PIN_GPIO02 2 /* Unrouted */
+#define U300_GPIO_PIN_GPIO03 3 /* Unrouted */
+#define U300_GPIO_PIN_CAM_SLEEP 4
+#define U300_GPIO_PIN_CAM_REG_EN 5
+#define U300_GPIO_PIN_GPIO06 6 /* Unrouted */
+#define U300_GPIO_PIN_GPIO07 7 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO08 8 /* Service point SP2321 */
+#define U300_GPIO_PIN_GPIO09 9 /* Service point SP2322 */
+#define U300_GPIO_PIN_PHFSENSE 10 /* Headphone jack sensing */
+#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */
+#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */
+#define U300_GPIO_PIN_FLIPSENSE 13 /* Mechanical flip sensing */
+#define U300_GPIO_PIN_GPIO14 14 /* DSP JTAG Port RTCK */
+#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO16 16 /* Unrouted */
+#define U300_GPIO_PIN_GPIO17 17 /* Unrouted */
+#define U300_GPIO_PIN_GPIO18 18 /* Unrouted */
+#define U300_GPIO_PIN_GPIO19 19 /* Unrouted */
+#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */
+#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */
+#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */
+#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */
+#endif
+
+/*
+ * Individual pin assignments for the B330/S330 and B365/S365.
+ * Notice that the actual usage of these pins depends on the
+ * PAD MUX settings, that is why the same number can potentially
+ * appear several times. In the reference design each pin is only
+ * used for one purpose. These were determined by inspecting the
+ * S365 schematic.
+ */
+#if defined(CONFIG_MACH_U300_BS330) || defined(CONFIG_MACH_U300_BS365) || \
+ defined(CONFIG_MACH_U300_BS335)
+#define U300_GPIO_PIN_UART_RX 0
+#define U300_GPIO_PIN_UART_TX 1
+#define U300_GPIO_PIN_UART_CTS 2
+#define U300_GPIO_PIN_UART_RTS 3
+#define U300_GPIO_PIN_CAM_MAIN_STANDBY 4 /* Camera MAIN standby */
+#define U300_GPIO_PIN_GPIO05 5 /* Unrouted */
+#define U300_GPIO_PIN_MS_CD 6 /* Memory Stick Card insertion */
+#define U300_GPIO_PIN_GPIO07 7 /* Test point TP2430 */
+
+#define U300_GPIO_PIN_GPIO08 8 /* Test point TP2437 */
+#define U300_GPIO_PIN_GPIO09 9 /* Test point TP2431 */
+#define U300_GPIO_PIN_GPIO10 10 /* Test point TP2432 */
+#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */
+#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */
+#define U300_GPIO_PIN_CAM_SUB_STANDBY 13 /* Camera SUB standby */
+#define U300_GPIO_PIN_GPIO14 14 /* Test point TP2436 */
+#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO16 16 /* Test point TP2438 */
+#define U300_GPIO_PIN_PHFSENSE 17 /* Headphone jack sensing */
+#define U300_GPIO_PIN_GPIO18 18 /* Test point TP2439 */
+#define U300_GPIO_PIN_GPIO19 19 /* Routed somewhere */
+#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */
+#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */
+#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */
+#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO24 24 /* Unrouted */
+#define U300_GPIO_PIN_GPIO25 25 /* Unrouted */
+#define U300_GPIO_PIN_GPIO26 26 /* Unrouted */
+#define U300_GPIO_PIN_GPIO27 27 /* Unrouted */
+#define U300_GPIO_PIN_GPIO28 28 /* Unrouted */
+#define U300_GPIO_PIN_GPIO29 29 /* Unrouted */
+#define U300_GPIO_PIN_GPIO30 30 /* Unrouted */
+#define U300_GPIO_PIN_GPIO31 31 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO32 32 /* Unrouted */
+#define U300_GPIO_PIN_GPIO33 33 /* Unrouted */
+#define U300_GPIO_PIN_GPIO34 34 /* Unrouted */
+#define U300_GPIO_PIN_GPIO35 35 /* Unrouted */
+#define U300_GPIO_PIN_GPIO36 36 /* Unrouted */
+#define U300_GPIO_PIN_GPIO37 37 /* Unrouted */
+#define U300_GPIO_PIN_GPIO38 38 /* Unrouted */
+#define U300_GPIO_PIN_GPIO39 39 /* Unrouted */
+
+#ifdef CONFIG_MACH_U300_BS335
+
+#define U300_GPIO_PIN_GPIO40 40 /* Unrouted */
+#define U300_GPIO_PIN_GPIO41 41 /* Unrouted */
+#define U300_GPIO_PIN_GPIO42 42 /* Unrouted */
+#define U300_GPIO_PIN_GPIO43 43 /* Unrouted */
+#define U300_GPIO_PIN_GPIO44 44 /* Unrouted */
+#define U300_GPIO_PIN_GPIO45 45 /* Unrouted */
+#define U300_GPIO_PIN_GPIO46 46 /* Unrouted */
+#define U300_GPIO_PIN_GPIO47 47 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO48 48 /* Unrouted */
+#define U300_GPIO_PIN_GPIO49 49 /* Unrouted */
+#define U300_GPIO_PIN_GPIO50 50 /* Unrouted */
+#define U300_GPIO_PIN_GPIO51 51 /* Unrouted */
+#define U300_GPIO_PIN_GPIO52 52 /* Unrouted */
+#define U300_GPIO_PIN_GPIO53 53 /* Unrouted */
+#define U300_GPIO_PIN_GPIO54 54 /* Unrouted */
+#define U300_GPIO_PIN_GPIO55 55 /* Unrouted */
+#endif
+
+#endif
+
+/* translates a pin number to a port number */
+#define PIN_TO_PORT(val) (val >> 3)
+
+/* These can be found in arch/arm/mach-u300/gpio.c */
+extern int gpio_request(unsigned gpio, const char *label);
+extern void gpio_free(unsigned gpio);
+extern int gpio_direction_input(unsigned gpio);
+extern int gpio_direction_output(unsigned gpio, int value);
+extern int gpio_register_callback(unsigned gpio,
+ int (*func)(void *arg),
+ void *);
+extern int gpio_unregister_callback(unsigned gpio);
+extern void enable_irq_on_gpio_pin(unsigned gpio, int edge);
+extern void disable_irq_on_gpio_pin(unsigned gpio);
+extern void gpio_pullup(unsigned gpio, int value);
+extern int gpio_get_value(unsigned gpio);
+extern void gpio_set_value(unsigned gpio, int value);
+
+/* wrappers to sleep-enable the previous two functions */
+static inline unsigned gpio_to_irq(unsigned gpio)
+{
+ return PIN_TO_PORT(gpio) + IRQ_U300_GPIO_PORT0;
+}
+
+static inline unsigned irq_to_gpio(unsigned irq)
+{
+ /*
+ * FIXME: This is no 1-1 mapping at all, it points to the
+ * whole block of 8 pins.
+ */
+ return (irq - IRQ_U300_GPIO_PORT0) << 3;
+}
+
+#endif
diff --git a/arch/arm/mach-u300/include/mach/hardware.h b/arch/arm/mach-u300/include/mach/hardware.h
new file mode 100644
index 000000000000..b99d4ce0ac2b
--- /dev/null
+++ b/arch/arm/mach-u300/include/mach/hardware.h
@@ -0,0 +1,5 @@
+/*
+ * arch/arm/mach-u300/include/mach/hardware.h
+ */
+#include <asm/sizes.h>
+#include <mach/u300-regs.h>
diff --git a/arch/arm/mach-u300/include/mach/io.h b/arch/arm/mach-u300/include/mach/io.h
new file mode 100644
index 000000000000..5d6b4c13b3a0
--- /dev/null
+++ b/arch/arm/mach-u300/include/mach/io.h
@@ -0,0 +1,20 @@
+/*
+ *
+ * arch/arm/mach-u300/include/mach/io.h
+ *
+ *
+ * Copyright (C) 2006-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Dummy IO map for being able to use writew()/readw(),
+ * writel()/readw() and similar accessor functions.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+#ifndef __MACH_IO_H
+#define __MACH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a) __typesafe_io(a)
+#define __mem_pci(a) (a)
+
+#endif
diff --git a/arch/arm/mach-u300/include/mach/irqs.h b/arch/arm/mach-u300/include/mach/irqs.h
new file mode 100644
index 000000000000..a6867b12773e
--- /dev/null
+++ b/arch/arm/mach-u300/include/mach/irqs.h
@@ -0,0 +1,114 @@
+/*
+ *
+ * arch/arm/mach-u300/include/mach/irqs.h
+ *
+ *
+ * Copyright (C) 2006-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * IRQ channel definitions for the U300 platforms.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+
+#ifndef __MACH_IRQS_H
+#define __MACH_IRQS_H
+
+#define IRQ_U300_INTCON0_START 0
+#define IRQ_U300_INTCON1_START 32
+/* These are on INTCON0 - 30 lines */
+#define IRQ_U300_IRQ0_EXT 0
+#define IRQ_U300_IRQ1_EXT 1
+#define IRQ_U300_DMA 2
+#define IRQ_U300_VIDEO_ENC_0 3
+#define IRQ_U300_VIDEO_ENC_1 4
+#define IRQ_U300_AAIF_RX 5
+#define IRQ_U300_AAIF_TX 6
+#define IRQ_U300_AAIF_VGPIO 7
+#define IRQ_U300_AAIF_WAKEUP 8
+#define IRQ_U300_PCM_I2S0_FRAME 9
+#define IRQ_U300_PCM_I2S0_FIFO 10
+#define IRQ_U300_PCM_I2S1_FRAME 11
+#define IRQ_U300_PCM_I2S1_FIFO 12
+#define IRQ_U300_XGAM_GAMCON 13
+#define IRQ_U300_XGAM_CDI 14
+#define IRQ_U300_XGAM_CDICON 15
+#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
+/* MMIACC not used on the DB3210 or DB3350 chips */
+#define IRQ_U300_XGAM_MMIACC 16
+#endif
+#define IRQ_U300_XGAM_PDI 17
+#define IRQ_U300_XGAM_PDICON 18
+#define IRQ_U300_XGAM_GAMEACC 19
+#define IRQ_U300_XGAM_MCIDCT 20
+#define IRQ_U300_APEX 21
+#define IRQ_U300_UART0 22
+#define IRQ_U300_SPI 23
+#define IRQ_U300_TIMER_APP_OS 24
+#define IRQ_U300_TIMER_APP_DD 25
+#define IRQ_U300_TIMER_APP_GP1 26
+#define IRQ_U300_TIMER_APP_GP2 27
+#define IRQ_U300_TIMER_OS 28
+#define IRQ_U300_TIMER_MS 29
+#define IRQ_U300_KEYPAD_KEYBF 30
+#define IRQ_U300_KEYPAD_KEYBR 31
+/* These are on INTCON1 - 32 lines */
+#define IRQ_U300_GPIO_PORT0 32
+#define IRQ_U300_GPIO_PORT1 33
+#define IRQ_U300_GPIO_PORT2 34
+
+#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330) || \
+ defined(CONFIG_MACH_U300_BS335)
+/* These are for DB3150, DB3200 and DB3350 */
+#define IRQ_U300_WDOG 35
+#define IRQ_U300_EVHIST 36
+#define IRQ_U300_MSPRO 37
+#define IRQ_U300_MMCSD_MCIINTR0 38
+#define IRQ_U300_MMCSD_MCIINTR1 39
+#define IRQ_U300_I2C0 40
+#define IRQ_U300_I2C1 41
+#define IRQ_U300_RTC 42
+#define IRQ_U300_NFIF 43
+#define IRQ_U300_NFIF2 44
+#endif
+
+/* DB3150 and DB3200 have only 45 IRQs */
+#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
+#define U300_NR_IRQS 45
+#endif
+
+/* The DB3350-specific interrupt lines */
+#ifdef CONFIG_MACH_U300_BS335
+#define IRQ_U300_ISP_F0 45
+#define IRQ_U300_ISP_F1 46
+#define IRQ_U300_ISP_F2 47
+#define IRQ_U300_ISP_F3 48
+#define IRQ_U300_ISP_F4 49
+#define IRQ_U300_GPIO_PORT3 50
+#define IRQ_U300_SYSCON_PLL_LOCK 51
+#define IRQ_U300_UART1 52
+#define IRQ_U300_GPIO_PORT4 53
+#define IRQ_U300_GPIO_PORT5 54
+#define IRQ_U300_GPIO_PORT6 55
+#define U300_NR_IRQS 56
+#endif
+
+/* The DB3210-specific interrupt lines */
+#ifdef CONFIG_MACH_U300_BS365
+#define IRQ_U300_GPIO_PORT3 35
+#define IRQ_U300_GPIO_PORT4 36
+#define IRQ_U300_WDOG 37
+#define IRQ_U300_EVHIST 38
+#define IRQ_U300_MSPRO 39
+#define IRQ_U300_MMCSD_MCIINTR0 40
+#define IRQ_U300_MMCSD_MCIINTR1 41
+#define IRQ_U300_I2C0 42
+#define IRQ_U300_I2C1 43
+#define IRQ_U300_RTC 44
+#define IRQ_U300_NFIF 45
+#define IRQ_U300_NFIF2 46
+#define IRQ_U300_SYSCON_PLL_LOCK 47
+#define U300_NR_IRQS 48
+#endif
+
+#define NR_IRQS U300_NR_IRQS
+
+#endif
diff --git a/arch/arm/mach-u300/include/mach/memory.h b/arch/arm/mach-u300/include/mach/memory.h
new file mode 100644
index 000000000000..bf134bcc129d
--- /dev/null
+++ b/arch/arm/mach-u300/include/mach/memory.h
@@ -0,0 +1,42 @@
+/*
+ *
+ * arch/arm/mach-u300/include/mach/memory.h
+ *
+ *
+ * Copyright (C) 2007-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Memory virtual/physical mapping constants.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
+ */
+
+#ifndef __MACH_MEMORY_H
+#define __MACH_MEMORY_H
+
+#ifdef CONFIG_MACH_U300_DUAL_RAM
+
+#define PHYS_OFFSET UL(0x48000000)
+#define BOOT_PARAMS_OFFSET (PHYS_OFFSET + 0x100)
+
+#else
+
+#ifdef CONFIG_MACH_U300_2MB_ALIGNMENT_FIX
+#define PHYS_OFFSET (0x28000000 + \
+ (CONFIG_MACH_U300_ACCESS_MEM_SIZE - \
+ (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
+#else
+#define PHYS_OFFSET (0x28000000 + \
+ (CONFIG_MACH_U300_ACCESS_MEM_SIZE + \
+ (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
+#endif
+#define BOOT_PARAMS_OFFSET (0x28000000 + \
+ (CONFIG_MACH_U300_ACCESS_MEM_SIZE + \
+ (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024 + 0x100)
+#endif
+
+/*
+ * We enable a real big DMA buffer if need be.
+ */
+#define CONSISTENT_DMA_SIZE SZ_4M
+
+#endif
diff --git a/arch/arm/mach-u300/include/mach/platform.h b/arch/arm/mach-u300/include/mach/platform.h
new file mode 100644
index 000000000000..77d9210a82e2
--- /dev/null
+++ b/arch/arm/mach-u300/include/mach/platform.h
@@ -0,0 +1,19 @@
+/*
+ *
+ * arch/arm/mach-u300/include/mach/platform.h
+ *
+ *
+ * Copyright (C) 2006-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Basic platform init and mapping functions.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+
+#ifndef __ASSEMBLY__
+
+void u300_map_io(void);
+void u300_init_irq(void);
+void u300_init_devices(void);
+extern struct sys_timer u300_timer;
+
+#endif
diff --git a/arch/arm/mach-u300/include/mach/syscon.h b/arch/arm/mach-u300/include/mach/syscon.h
new file mode 100644
index 000000000000..1c90d1b1ccb6
--- /dev/null
+++ b/arch/arm/mach-u300/include/mach/syscon.h
@@ -0,0 +1,644 @@
+/*
+ *
+ * arch/arm/mach-u300/include/mach/syscon.h
+ *
+ *
+ * Copyright (C) 2008 ST-Ericsson AB
+ *
+ * Author: Rickard Andersson <rickard.andersson@stericsson.com>
+ */
+
+#ifndef __MACH_SYSCON_H
+#define __MACH_SYSCON_H
+
+/*
+ * All register defines for SYSCON registers that concerns individual
+ * block clocks and reset lines are registered here. This is because
+ * we don't want any other file to try to fool around with this stuff.
+ */
+
+/* APP side SYSCON registers */
+/* TODO: this is incomplete. Add all from asic_syscon_map.h eventually. */
+/* CLK Control Register 16bit (R/W) */
+#define U300_SYSCON_CCR (0x0000)
+#define U300_SYSCON_CCR_I2S1_USE_VCXO (0x0040)
+#define U300_SYSCON_CCR_I2S0_USE_VCXO (0x0020)
+#define U300_SYSCON_CCR_TURN_VCXO_ON (0x0008)
+#define U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK (0x0007)
+#define U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER (0x04)
+#define U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW (0x03)
+#define U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE (0x02)
+#define U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH (0x01)
+#define U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST (0x00)
+/* CLK Status Register 16bit (R/W) */
+#define U300_SYSCON_CSR (0x0004)
+#define U300_SYSCON_CSR_PLL208_LOCK_IND (0x0002)
+#define U300_SYSCON_CSR_PLL13_LOCK_IND (0x0001)
+/* Reset lines for SLOW devices 16bit (R/W) */
+#define U300_SYSCON_RSR (0x0014)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_RSR_PPM_RESET_EN (0x0200)
+#endif
+#define U300_SYSCON_RSR_ACC_TMR_RESET_EN (0x0100)
+#define U300_SYSCON_RSR_APP_TMR_RESET_EN (0x0080)
+#define U300_SYSCON_RSR_RTC_RESET_EN (0x0040)
+#define U300_SYSCON_RSR_KEYPAD_RESET_EN (0x0020)
+#define U300_SYSCON_RSR_GPIO_RESET_EN (0x0010)
+#define U300_SYSCON_RSR_EH_RESET_EN (0x0008)
+#define U300_SYSCON_RSR_BTR_RESET_EN (0x0004)
+#define U300_SYSCON_RSR_UART_RESET_EN (0x0002)
+#define U300_SYSCON_RSR_SLOW_BRIDGE_RESET_EN (0x0001)
+/* Reset lines for FAST devices 16bit (R/W) */
+#define U300_SYSCON_RFR (0x0018)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_RFR_UART1_RESET_ENABLE (0x0080)
+#endif
+#define U300_SYSCON_RFR_SPI_RESET_ENABLE (0x0040)
+#define U300_SYSCON_RFR_MMC_RESET_ENABLE (0x0020)
+#define U300_SYSCON_RFR_PCM_I2S1_RESET_ENABLE (0x0010)
+#define U300_SYSCON_RFR_PCM_I2S0_RESET_ENABLE (0x0008)
+#define U300_SYSCON_RFR_I2C1_RESET_ENABLE (0x0004)
+#define U300_SYSCON_RFR_I2C0_RESET_ENABLE (0x0002)
+#define U300_SYSCON_RFR_FAST_BRIDGE_RESET_ENABLE (0x0001)
+/* Reset lines for the rest of the peripherals 16bit (R/W) */
+#define U300_SYSCON_RRR (0x001c)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_RRR_CDS_RESET_EN (0x4000)
+#define U300_SYSCON_RRR_ISP_RESET_EN (0x2000)
+#endif
+#define U300_SYSCON_RRR_INTCON_RESET_EN (0x1000)
+#define U300_SYSCON_RRR_MSPRO_RESET_EN (0x0800)
+#define U300_SYSCON_RRR_XGAM_RESET_EN (0x0100)
+#define U300_SYSCON_RRR_XGAM_VC_SYNC_RESET_EN (0x0080)
+#define U300_SYSCON_RRR_NANDIF_RESET_EN (0x0040)
+#define U300_SYSCON_RRR_EMIF_RESET_EN (0x0020)
+#define U300_SYSCON_RRR_DMAC_RESET_EN (0x0010)
+#define U300_SYSCON_RRR_CPU_RESET_EN (0x0008)
+#define U300_SYSCON_RRR_APEX_RESET_EN (0x0004)
+#define U300_SYSCON_RRR_AHB_RESET_EN (0x0002)
+#define U300_SYSCON_RRR_AAIF_RESET_EN (0x0001)
+/* Clock enable for SLOW peripherals 16bit (R/W) */
+#define U300_SYSCON_CESR (0x0020)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_CESR_PPM_CLK_EN (0x0200)
+#endif
+#define U300_SYSCON_CESR_ACC_TMR_CLK_EN (0x0100)
+#define U300_SYSCON_CESR_APP_TMR_CLK_EN (0x0080)
+#define U300_SYSCON_CESR_KEYPAD_CLK_EN (0x0040)
+#define U300_SYSCON_CESR_GPIO_CLK_EN (0x0010)
+#define U300_SYSCON_CESR_EH_CLK_EN (0x0008)
+#define U300_SYSCON_CESR_BTR_CLK_EN (0x0004)
+#define U300_SYSCON_CESR_UART_CLK_EN (0x0002)
+#define U300_SYSCON_CESR_SLOW_BRIDGE_CLK_EN (0x0001)
+/* Clock enable for FAST peripherals 16bit (R/W) */
+#define U300_SYSCON_CEFR (0x0024)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_CEFR_UART1_CLK_EN (0x0200)
+#endif
+#define U300_SYSCON_CEFR_I2S1_CORE_CLK_EN (0x0100)
+#define U300_SYSCON_CEFR_I2S0_CORE_CLK_EN (0x0080)
+#define U300_SYSCON_CEFR_SPI_CLK_EN (0x0040)
+#define U300_SYSCON_CEFR_MMC_CLK_EN (0x0020)
+#define U300_SYSCON_CEFR_I2S1_CLK_EN (0x0010)
+#define U300_SYSCON_CEFR_I2S0_CLK_EN (0x0008)
+#define U300_SYSCON_CEFR_I2C1_CLK_EN (0x0004)
+#define U300_SYSCON_CEFR_I2C0_CLK_EN (0x0002)
+#define U300_SYSCON_CEFR_FAST_BRIDGE_CLK_EN (0x0001)
+/* Clock enable for the rest of the peripherals 16bit (R/W) */
+#define U300_SYSCON_CERR (0x0028)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_CERR_CDS_CLK_EN (0x2000)
+#define U300_SYSCON_CERR_ISP_CLK_EN (0x1000)
+#endif
+#define U300_SYSCON_CERR_MSPRO_CLK_EN (0x0800)
+#define U300_SYSCON_CERR_AHB_SUBSYS_BRIDGE_CLK_EN (0x0400)
+#define U300_SYSCON_CERR_SEMI_CLK_EN (0x0200)
+#define U300_SYSCON_CERR_XGAM_CLK_EN (0x0100)
+#define U300_SYSCON_CERR_VIDEO_ENC_CLK_EN (0x0080)
+#define U300_SYSCON_CERR_NANDIF_CLK_EN (0x0040)
+#define U300_SYSCON_CERR_EMIF_CLK_EN (0x0020)
+#define U300_SYSCON_CERR_DMAC_CLK_EN (0x0010)
+#define U300_SYSCON_CERR_CPU_CLK_EN (0x0008)
+#define U300_SYSCON_CERR_APEX_CLK_EN (0x0004)
+#define U300_SYSCON_CERR_AHB_CLK_EN (0x0002)
+#define U300_SYSCON_CERR_AAIF_CLK_EN (0x0001)
+/* Single block clock enable 16bit (-/W) */
+#define U300_SYSCON_SBCER (0x002c)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_SBCER_PPM_CLK_EN (0x0009)
+#endif
+#define U300_SYSCON_SBCER_ACC_TMR_CLK_EN (0x0008)
+#define U300_SYSCON_SBCER_APP_TMR_CLK_EN (0x0007)
+#define U300_SYSCON_SBCER_KEYPAD_CLK_EN (0x0006)
+#define U300_SYSCON_SBCER_GPIO_CLK_EN (0x0004)
+#define U300_SYSCON_SBCER_EH_CLK_EN (0x0003)
+#define U300_SYSCON_SBCER_BTR_CLK_EN (0x0002)
+#define U300_SYSCON_SBCER_UART_CLK_EN (0x0001)
+#define U300_SYSCON_SBCER_SLOW_BRIDGE_CLK_EN (0x0000)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_SBCER_UART1_CLK_EN (0x0019)
+#endif
+#define U300_SYSCON_SBCER_I2S1_CORE_CLK_EN (0x0018)
+#define U300_SYSCON_SBCER_I2S0_CORE_CLK_EN (0x0017)
+#define U300_SYSCON_SBCER_SPI_CLK_EN (0x0016)
+#define U300_SYSCON_SBCER_MMC_CLK_EN (0x0015)
+#define U300_SYSCON_SBCER_I2S1_CLK_EN (0x0014)
+#define U300_SYSCON_SBCER_I2S0_CLK_EN (0x0013)
+#define U300_SYSCON_SBCER_I2C1_CLK_EN (0x0012)
+#define U300_SYSCON_SBCER_I2C0_CLK_EN (0x0011)
+#define U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN (0x0010)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_SBCER_CDS_CLK_EN (0x002D)
+#define U300_SYSCON_SBCER_ISP_CLK_EN (0x002C)
+#endif
+#define U300_SYSCON_SBCER_MSPRO_CLK_EN (0x002B)
+#define U300_SYSCON_SBCER_AHB_SUBSYS_BRIDGE_CLK_EN (0x002A)
+#define U300_SYSCON_SBCER_SEMI_CLK_EN (0x0029)
+#define U300_SYSCON_SBCER_XGAM_CLK_EN (0x0028)
+#define U300_SYSCON_SBCER_VIDEO_ENC_CLK_EN (0x0027)
+#define U300_SYSCON_SBCER_NANDIF_CLK_EN (0x0026)
+#define U300_SYSCON_SBCER_EMIF_CLK_EN (0x0025)
+#define U300_SYSCON_SBCER_DMAC_CLK_EN (0x0024)
+#define U300_SYSCON_SBCER_CPU_CLK_EN (0x0023)
+#define U300_SYSCON_SBCER_APEX_CLK_EN (0x0022)
+#define U300_SYSCON_SBCER_AHB_CLK_EN (0x0021)
+#define U300_SYSCON_SBCER_AAIF_CLK_EN (0x0020)
+/* Single block clock disable 16bit (-/W) */
+#define U300_SYSCON_SBCDR (0x0030)
+/* Same values as above for SBCER */
+/* Clock force SLOW peripherals 16bit (R/W) */
+#define U300_SYSCON_CFSR (0x003c)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_CFSR_PPM_CLK_FORCE_EN (0x0200)
+#endif
+#define U300_SYSCON_CFSR_ACC_TMR_CLK_FORCE_EN (0x0100)
+#define U300_SYSCON_CFSR_APP_TMR_CLK_FORCE_EN (0x0080)
+#define U300_SYSCON_CFSR_KEYPAD_CLK_FORCE_EN (0x0020)
+#define U300_SYSCON_CFSR_GPIO_CLK_FORCE_EN (0x0010)
+#define U300_SYSCON_CFSR_EH_CLK_FORCE_EN (0x0008)
+#define U300_SYSCON_CFSR_BTR_CLK_FORCE_EN (0x0004)
+#define U300_SYSCON_CFSR_UART_CLK_FORCE_EN (0x0002)
+#define U300_SYSCON_CFSR_SLOW_BRIDGE_CLK_FORCE_EN (0x0001)
+/* Clock force FAST peripherals 16bit (R/W) */
+#define U300_SYSCON_CFFR (0x40)
+/* Values not defined. Define if you want to use them. */
+/* Clock force the rest of the peripherals 16bit (R/W) */
+#define U300_SYSCON_CFRR (0x44)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_CFRR_CDS_CLK_FORCE_EN (0x2000)
+#define U300_SYSCON_CFRR_ISP_CLK_FORCE_EN (0x1000)
+#endif
+#define U300_SYSCON_CFRR_MSPRO_CLK_FORCE_EN (0x0800)
+#define U300_SYSCON_CFRR_AHB_SUBSYS_BRIDGE_CLK_FORCE_EN (0x0400)
+#define U300_SYSCON_CFRR_SEMI_CLK_FORCE_EN (0x0200)
+#define U300_SYSCON_CFRR_XGAM_CLK_FORCE_EN (0x0100)
+#define U300_SYSCON_CFRR_VIDEO_ENC_CLK_FORCE_EN (0x0080)
+#define U300_SYSCON_CFRR_NANDIF_CLK_FORCE_EN (0x0040)
+#define U300_SYSCON_CFRR_EMIF_CLK_FORCE_EN (0x0020)
+#define U300_SYSCON_CFRR_DMAC_CLK_FORCE_EN (0x0010)
+#define U300_SYSCON_CFRR_CPU_CLK_FORCE_EN (0x0008)
+#define U300_SYSCON_CFRR_APEX_CLK_FORCE_EN (0x0004)
+#define U300_SYSCON_CFRR_AHB_CLK_FORCE_EN (0x0002)
+#define U300_SYSCON_CFRR_AAIF_CLK_FORCE_EN (0x0001)
+/* PLL208 Frequency Control 16bit (R/W) */
+#define U300_SYSCON_PFCR (0x48)
+#define U300_SYSCON_PFCR_DPLL_MULT_NUM (0x000F)
+/* Power Management Control 16bit (R/W) */
+#define U300_SYSCON_PMCR (0x50)
+#define U300_SYSCON_PMCR_DCON_ENABLE (0x0002)
+#define U300_SYSCON_PMCR_PWR_MGNT_ENABLE (0x0001)
+/*
+ * All other clocking registers moved to clock.c!
+ */
+/* Reset Out 16bit (R/W) */
+#define U300_SYSCON_RCR (0x6c)
+#define U300_SYSCON_RCR_RESOUT0_RST_N_DISABLE (0x0001)
+/* EMIF Slew Rate Control 16bit (R/W) */
+#define U300_SYSCON_SRCLR (0x70)
+#define U300_SYSCON_SRCLR_MASK (0x03FF)
+#define U300_SYSCON_SRCLR_VALUE (0x03FF)
+#define U300_SYSCON_SRCLR_EMIF_1_SLRC_5_B (0x0200)
+#define U300_SYSCON_SRCLR_EMIF_1_SLRC_5_A (0x0100)
+#define U300_SYSCON_SRCLR_EMIF_1_SLRC_4_B (0x0080)
+#define U300_SYSCON_SRCLR_EMIF_1_SLRC_4_A (0x0040)
+#define U300_SYSCON_SRCLR_EMIF_1_SLRC_3_B (0x0020)
+#define U300_SYSCON_SRCLR_EMIF_1_SLRC_3_A (0x0010)
+#define U300_SYSCON_SRCLR_EMIF_1_SLRC_2_B (0x0008)
+#define U300_SYSCON_SRCLR_EMIF_1_SLRC_2_A (0x0004)
+#define U300_SYSCON_SRCLR_EMIF_1_SLRC_1_B (0x0002)
+#define U300_SYSCON_SRCLR_EMIF_1_SLRC_1_A (0x0001)
+/* EMIF Clock Control Register 16bit (R/W) */
+#define U300_SYSCON_ECCR (0x0078)
+#define U300_SYSCON_ECCR_MASK (0x000F)
+#define U300_SYSCON_ECCR_EMIF_1_STATIC_CLK_EN_N_DISABLE (0x0008)
+#define U300_SYSCON_ECCR_EMIF_1_RET_OUT_CLK_EN_N_DISABLE (0x0004)
+#define U300_SYSCON_ECCR_EMIF_MEMCLK_RET_EN_N_DISABLE (0x0002)
+#define U300_SYSCON_ECCR_EMIF_SDRCLK_RET_EN_N_DISABLE (0x0001)
+/* PAD MUX Control register 1 (LOW) 16bit (R/W) */
+#define U300_SYSCON_PMC1LR (0x007C)
+#define U300_SYSCON_PMC1LR_MASK (0xFFFF)
+#define U300_SYSCON_PMC1LR_CDI_MASK (0xC000)
+#define U300_SYSCON_PMC1LR_CDI_CDI (0x0000)
+#define U300_SYSCON_PMC1LR_CDI_EMIF (0x4000)
+#define U300_SYSCON_PMC1LR_CDI_GPIO (0x8000)
+#define U300_SYSCON_PMC1LR_CDI_WCDMA (0xC000)
+#define U300_SYSCON_PMC1LR_PDI_MASK (0x3000)
+#define U300_SYSCON_PMC1LR_PDI_PDI (0x0000)
+#define U300_SYSCON_PMC1LR_PDI_EGG (0x1000)
+#define U300_SYSCON_PMC1LR_PDI_WCDMA (0x3000)
+#define U300_SYSCON_PMC1LR_MMCSD_MASK (0x0C00)
+#define U300_SYSCON_PMC1LR_MMCSD_MMCSD (0x0000)
+#define U300_SYSCON_PMC1LR_MMCSD_MSPRO (0x0400)
+#define U300_SYSCON_PMC1LR_MMCSD_DSP (0x0800)
+#define U300_SYSCON_PMC1LR_MMCSD_WCDMA (0x0C00)
+#define U300_SYSCON_PMC1LR_ETM_MASK (0x0300)
+#define U300_SYSCON_PMC1LR_ETM_ACC (0x0000)
+#define U300_SYSCON_PMC1LR_ETM_APP (0x0100)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS2_MASK (0x00C0)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC (0x0000)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS2_NFIF (0x0040)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS2_SDRAM (0x0080)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC_2GB (0x00C0)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS1_MASK (0x0030)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS1_STATIC (0x0000)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS1_NFIF (0x0010)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SDRAM (0x0020)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SEMI (0x0030)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS0_MASK (0x000C)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS0_STATIC (0x0000)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS0_NFIF (0x0004)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SDRAM (0x0008)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SEMI (0x000C)
+#define U300_SYSCON_PMC1LR_EMIF_1_MASK (0x0003)
+#define U300_SYSCON_PMC1LR_EMIF_1_STATIC (0x0000)
+#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM0 (0x0001)
+#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM1 (0x0002)
+#define U300_SYSCON_PMC1LR_EMIF_1 (0x0003)
+/* PAD MUX Control register 2 (HIGH) 16bit (R/W) */
+#define U300_SYSCON_PMC1HR (0x007E)
+#define U300_SYSCON_PMC1HR_MASK (0xFFFF)
+#define U300_SYSCON_PMC1HR_MISC_2_MASK (0xC000)
+#define U300_SYSCON_PMC1HR_MISC_2_APP_GPIO (0x0000)
+#define U300_SYSCON_PMC1HR_MISC_2_MSPRO (0x4000)
+#define U300_SYSCON_PMC1HR_MISC_2_DSP (0x8000)
+#define U300_SYSCON_PMC1HR_MISC_2_AAIF (0xC000)
+#define U300_SYSCON_PMC1HR_APP_GPIO_2_MASK (0x3000)
+#define U300_SYSCON_PMC1HR_APP_GPIO_2_APP_GPIO (0x0000)
+#define U300_SYSCON_PMC1HR_APP_GPIO_2_NFIF (0x1000)
+#define U300_SYSCON_PMC1HR_APP_GPIO_2_DSP (0x2000)
+#define U300_SYSCON_PMC1HR_APP_GPIO_2_AAIF (0x3000)
+#define U300_SYSCON_PMC1HR_APP_GPIO_1_MASK (0x0C00)
+#define U300_SYSCON_PMC1HR_APP_GPIO_1_APP_GPIO (0x0000)
+#define U300_SYSCON_PMC1HR_APP_GPIO_1_MMC (0x0400)
+#define U300_SYSCON_PMC1HR_APP_GPIO_1_DSP (0x0800)
+#define U300_SYSCON_PMC1HR_APP_GPIO_1_AAIF (0x0C00)
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK (0x0300)
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_APP_GPIO (0x0000)
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI (0x0100)
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_AAIF (0x0300)
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK (0x00C0)
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_APP_GPIO (0x0000)
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI (0x0040)
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_AAIF (0x00C0)
+#define U300_SYSCON_PMC1HR_APP_SPI_2_MASK (0x0030)
+#define U300_SYSCON_PMC1HR_APP_SPI_2_APP_GPIO (0x0000)
+#define U300_SYSCON_PMC1HR_APP_SPI_2_SPI (0x0010)
+#define U300_SYSCON_PMC1HR_APP_SPI_2_DSP (0x0020)
+#define U300_SYSCON_PMC1HR_APP_SPI_2_AAIF (0x0030)
+#define U300_SYSCON_PMC1HR_APP_UART0_2_MASK (0x000C)
+#define U300_SYSCON_PMC1HR_APP_UART0_2_APP_GPIO (0x0000)
+#define U300_SYSCON_PMC1HR_APP_UART0_2_UART0 (0x0004)
+#define U300_SYSCON_PMC1HR_APP_UART0_2_NFIF_CS (0x0008)
+#define U300_SYSCON_PMC1HR_APP_UART0_2_AAIF (0x000C)
+#define U300_SYSCON_PMC1HR_APP_UART0_1_MASK (0x0003)
+#define U300_SYSCON_PMC1HR_APP_UART0_1_APP_GPIO (0x0000)
+#define U300_SYSCON_PMC1HR_APP_UART0_1_UART0 (0x0001)
+#define U300_SYSCON_PMC1HR_APP_UART0_1_AAIF (0x0003)
+/* Step one for killing the applications system 16bit (-/W) */
+#define U300_SYSCON_KA1R (0x0080)
+#define U300_SYSCON_KA1R_MASK (0xFFFF)
+#define U300_SYSCON_KA1R_VALUE (0xFFFF)
+/* Step two for killing the application system 16bit (-/W) */
+#define U300_SYSCON_KA2R (0x0084)
+#define U300_SYSCON_KA2R_MASK (0xFFFF)
+#define U300_SYSCON_KA2R_VALUE (0xFFFF)
+/* MMC/MSPRO frequency divider register 0 16bit (R/W) */
+#define U300_SYSCON_MMF0R (0x90)
+#define U300_SYSCON_MMF0R_MASK (0x00FF)
+#define U300_SYSCON_MMF0R_FREQ_0_HIGH_MASK (0x00F0)
+#define U300_SYSCON_MMF0R_FREQ_0_LOW_MASK (0x000F)
+/* MMC/MSPRO frequency divider register 1 16bit (R/W) */
+#define U300_SYSCON_MMF1R (0x94)
+#define U300_SYSCON_MMF1R_MASK (0x00FF)
+#define U300_SYSCON_MMF1R_FREQ_1_HIGH_MASK (0x00F0)
+#define U300_SYSCON_MMF1R_FREQ_1_LOW_MASK (0x000F)
+/* AAIF control register 16 bit (R/W) */
+#define U300_SYSCON_AAIFCR (0x98)
+#define U300_SYSCON_AAIFCR_MASK (0x0003)
+#define U300_SYSCON_AAIFCR_AASW_CTRL_MASK (0x0003)
+#define U300_SYSCON_AAIFCR_AASW_CTRL_FUNCTIONAL (0x0000)
+#define U300_SYSCON_AAIFCR_AASW_CTRL_MONITORING (0x0001)
+#define U300_SYSCON_AAIFCR_AASW_CTRL_ACC_TO_EXT (0x0002)
+#define U300_SYSCON_AAIFCR_AASW_CTRL_APP_TO_EXT (0x0003)
+/* Clock control for the MMC and MSPRO blocks 16bit (R/W) */
+#define U300_SYSCON_MMCR (0x9C)
+#define U300_SYSCON_MMCR_MASK (0x0003)
+#define U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE (0x0002)
+#define U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE (0x0001)
+
+/* TODO: More SYSCON registers missing */
+#define U300_SYSCON_PMC3R (0x10c)
+#define U300_SYSCON_PMC3R_APP_MISC_11_MASK (0xc000)
+#define U300_SYSCON_PMC3R_APP_MISC_11_SPI (0x4000)
+#define U300_SYSCON_PMC3R_APP_MISC_10_MASK (0x3000)
+#define U300_SYSCON_PMC3R_APP_MISC_10_SPI (0x1000)
+/* TODO: Missing other configs, I just added the SPI stuff */
+
+/* SYS_0_CLK_CONTROL first clock control 16bit (R/W) */
+#define U300_SYSCON_S0CCR (0x120)
+#define U300_SYSCON_S0CCR_FIELD_MASK (0x43FF)
+#define U300_SYSCON_S0CCR_CLOCK_REQ (0x4000)
+#define U300_SYSCON_S0CCR_CLOCK_INV (0x0200)
+#define U300_SYSCON_S0CCR_CLOCK_FREQ_MASK (0x01E0)
+#define U300_SYSCON_S0CCR_CLOCK_SELECT_MASK (0x001E)
+#define U300_SYSCON_S0CCR_CLOCK_ENABLE (0x0001)
+#define U300_SYSCON_S0CCR_SEL_MCLK (0x8<<1)
+#define U300_SYSCON_S0CCR_SEL_ACC_FSM_CLK (0xA<<1)
+#define U300_SYSCON_S0CCR_SEL_PLL60_48_CLK (0xC<<1)
+#define U300_SYSCON_S0CCR_SEL_PLL60_60_CLK (0xD<<1)
+#define U300_SYSCON_S0CCR_SEL_ACC_PLL208_CLK (0xE<<1)
+#define U300_SYSCON_S0CCR_SEL_APP_PLL13_CLK (0x0<<1)
+#define U300_SYSCON_S0CCR_SEL_APP_FSM_CLK (0x2<<1)
+#define U300_SYSCON_S0CCR_SEL_RTC_CLK (0x4<<1)
+#define U300_SYSCON_S0CCR_SEL_APP_PLL208_CLK (0x6<<1)
+/* SYS_1_CLK_CONTROL second clock control 16 bit (R/W) */
+#define U300_SYSCON_S1CCR (0x124)
+#define U300_SYSCON_S1CCR_FIELD_MASK (0x43FF)
+#define U300_SYSCON_S1CCR_CLOCK_REQ (0x4000)
+#define U300_SYSCON_S1CCR_CLOCK_INV (0x0200)
+#define U300_SYSCON_S1CCR_CLOCK_FREQ_MASK (0x01E0)
+#define U300_SYSCON_S1CCR_CLOCK_SELECT_MASK (0x001E)
+#define U300_SYSCON_S1CCR_CLOCK_ENABLE (0x0001)
+#define U300_SYSCON_S1CCR_SEL_MCLK (0x8<<1)
+#define U300_SYSCON_S1CCR_SEL_ACC_FSM_CLK (0xA<<1)
+#define U300_SYSCON_S1CCR_SEL_PLL60_48_CLK (0xC<<1)
+#define U300_SYSCON_S1CCR_SEL_PLL60_60_CLK (0xD<<1)
+#define U300_SYSCON_S1CCR_SEL_ACC_PLL208_CLK (0xE<<1)
+#define U300_SYSCON_S1CCR_SEL_ACC_PLL13_CLK (0x0<<1)
+#define U300_SYSCON_S1CCR_SEL_APP_FSM_CLK (0x2<<1)
+#define U300_SYSCON_S1CCR_SEL_RTC_CLK (0x4<<1)
+#define U300_SYSCON_S1CCR_SEL_APP_PLL208_CLK (0x6<<1)
+/* SYS_2_CLK_CONTROL third clock contol 16 bit (R/W) */
+#define U300_SYSCON_S2CCR (0x128)
+#define U300_SYSCON_S2CCR_FIELD_MASK (0xC3FF)
+#define U300_SYSCON_S2CCR_CLK_STEAL (0x8000)
+#define U300_SYSCON_S2CCR_CLOCK_REQ (0x4000)
+#define U300_SYSCON_S2CCR_CLOCK_INV (0x0200)
+#define U300_SYSCON_S2CCR_CLOCK_FREQ_MASK (0x01E0)
+#define U300_SYSCON_S2CCR_CLOCK_SELECT_MASK (0x001E)
+#define U300_SYSCON_S2CCR_CLOCK_ENABLE (0x0001)
+#define U300_SYSCON_S2CCR_SEL_MCLK (0x8<<1)
+#define U300_SYSCON_S2CCR_SEL_ACC_FSM_CLK (0xA<<1)
+#define U300_SYSCON_S2CCR_SEL_PLL60_48_CLK (0xC<<1)
+#define U300_SYSCON_S2CCR_SEL_PLL60_60_CLK (0xD<<1)
+#define U300_SYSCON_S2CCR_SEL_ACC_PLL208_CLK (0xE<<1)
+#define U300_SYSCON_S2CCR_SEL_ACC_PLL13_CLK (0x0<<1)
+#define U300_SYSCON_S2CCR_SEL_APP_FSM_CLK (0x2<<1)
+#define U300_SYSCON_S2CCR_SEL_RTC_CLK (0x4<<1)
+#define U300_SYSCON_S2CCR_SEL_APP_PLL208_CLK (0x6<<1)
+/* SYS_MISC_CONTROL, miscellaneous 16bit (R/W) */
+#define U300_SYSCON_MCR (0x12c)
+#define U300_SYSCON_MCR_FIELD_MASK (0x00FF)
+#define U300_SYSCON_MCR_PMGEN_CR_4_MASK (0x00C0)
+#define U300_SYSCON_MCR_PMGEN_CR_4_GPIO (0x0000)
+#define U300_SYSCON_MCR_PMGEN_CR_4_SPI (0x0040)
+#define U300_SYSCON_MCR_PMGEN_CR_4_AAIF (0x00C0)
+#define U300_SYSCON_MCR_PMGEN_CR_2_MASK (0x0030)
+#define U300_SYSCON_MCR_PMGEN_CR_2_GPIO (0x0000)
+#define U300_SYSCON_MCR_PMGEN_CR_2_EMIF_1_STATIC (0x0010)
+#define U300_SYSCON_MCR_PMGEN_CR_2_DSP (0x0020)
+#define U300_SYSCON_MCR_PMGEN_CR_2_AAIF (0x0030)
+#define U300_SYSCON_MCR_PMGEN_CR_0_MASK (0x000C)
+#define U300_SYSCON_MCR_PMGEN_CR_0_EMIF_1_SDRAM_M1 (0x0000)
+#define U300_SYSCON_MCR_PMGEN_CR_0_EMIF_1_SDRAM_M2 (0x0004)
+#define U300_SYSCON_MCR_PMGEN_CR_0_EMIF_1_SDRAM_M3 (0x0008)
+#define U300_SYSCON_MCR_PMGEN_CR_0_EMIF_0_SDRAM (0x000C)
+#define U300_SYSCON_MCR_PM1G_MODE_ENABLE (0x0002)
+#define U300_SYSCON_MCR_PMTG5_MODE_ENABLE (0x0001)
+/* Clock activity observability register 0 */
+#define U300_SYSCON_C0OAR (0x140)
+#define U300_SYSCON_C0OAR_MASK (0xFFFF)
+#define U300_SYSCON_C0OAR_VALUE (0xFFFF)
+#define U300_SYSCON_C0OAR_BT_H_CLK (0x8000)
+#define U300_SYSCON_C0OAR_ASPB_P_CLK (0x4000)
+#define U300_SYSCON_C0OAR_APP_SEMI_H_CLK (0x2000)
+#define U300_SYSCON_C0OAR_APP_SEMI_CLK (0x1000)
+#define U300_SYSCON_C0OAR_APP_MMC_MSPRO_CLK (0x0800)
+#define U300_SYSCON_C0OAR_APP_I2S1_CLK (0x0400)
+#define U300_SYSCON_C0OAR_APP_I2S0_CLK (0x0200)
+#define U300_SYSCON_C0OAR_APP_CPU_CLK (0x0100)
+#define U300_SYSCON_C0OAR_APP_52_CLK (0x0080)
+#define U300_SYSCON_C0OAR_APP_208_CLK (0x0040)
+#define U300_SYSCON_C0OAR_APP_104_CLK (0x0020)
+#define U300_SYSCON_C0OAR_APEX_CLK (0x0010)
+#define U300_SYSCON_C0OAR_AHPB_M_H_CLK (0x0008)
+#define U300_SYSCON_C0OAR_AHB_CLK (0x0004)
+#define U300_SYSCON_C0OAR_AFPB_P_CLK (0x0002)
+#define U300_SYSCON_C0OAR_AAIF_CLK (0x0001)
+/* Clock activity observability register 1 */
+#define U300_SYSCON_C1OAR (0x144)
+#define U300_SYSCON_C1OAR_MASK (0x3FFE)
+#define U300_SYSCON_C1OAR_VALUE (0x3FFE)
+#define U300_SYSCON_C1OAR_NFIF_F_CLK (0x2000)
+#define U300_SYSCON_C1OAR_MSPRO_CLK (0x1000)
+#define U300_SYSCON_C1OAR_MMC_P_CLK (0x0800)
+#define U300_SYSCON_C1OAR_MMC_CLK (0x0400)
+#define U300_SYSCON_C1OAR_KP_P_CLK (0x0200)
+#define U300_SYSCON_C1OAR_I2C1_P_CLK (0x0100)
+#define U300_SYSCON_C1OAR_I2C0_P_CLK (0x0080)
+#define U300_SYSCON_C1OAR_GPIO_CLK (0x0040)
+#define U300_SYSCON_C1OAR_EMIF_MPMC_CLK (0x0020)
+#define U300_SYSCON_C1OAR_EMIF_H_CLK (0x0010)
+#define U300_SYSCON_C1OAR_EVHIST_CLK (0x0008)
+#define U300_SYSCON_C1OAR_PPM_CLK (0x0004)
+#define U300_SYSCON_C1OAR_DMA_CLK (0x0002)
+/* Clock activity observability register 2 */
+#define U300_SYSCON_C2OAR (0x148)
+#define U300_SYSCON_C2OAR_MASK (0x0FFF)
+#define U300_SYSCON_C2OAR_VALUE (0x0FFF)
+#define U300_SYSCON_C2OAR_XGAM_CDI_CLK (0x0800)
+#define U300_SYSCON_C2OAR_XGAM_CLK (0x0400)
+#define U300_SYSCON_C2OAR_VC_H_CLK (0x0200)
+#define U300_SYSCON_C2OAR_VC_CLK (0x0100)
+#define U300_SYSCON_C2OAR_UA_P_CLK (0x0080)
+#define U300_SYSCON_C2OAR_TMR1_CLK (0x0040)
+#define U300_SYSCON_C2OAR_TMR0_CLK (0x0020)
+#define U300_SYSCON_C2OAR_SPI_P_CLK (0x0010)
+#define U300_SYSCON_C2OAR_PCM_I2S1_CORE_CLK (0x0008)
+#define U300_SYSCON_C2OAR_PCM_I2S1_CLK (0x0004)
+#define U300_SYSCON_C2OAR_PCM_I2S0_CORE_CLK (0x0002)
+#define U300_SYSCON_C2OAR_PCM_I2S0_CLK (0x0001)
+
+/* Chip ID register 16bit (R/-) */
+#define U300_SYSCON_CIDR (0x400)
+/* Video IRQ clear 16bit (R/W) */
+#define U300_SYSCON_VICR (0x404)
+#define U300_SYSCON_VICR_VIDEO1_IRQ_CLEAR_ENABLE (0x0002)
+#define U300_SYSCON_VICR_VIDEO0_IRQ_CLEAR_ENABLE (0x0001)
+/* SMCR */
+#define U300_SYSCON_SMCR (0x4d0)
+#define U300_SYSCON_SMCR_FIELD_MASK (0x000e)
+#define U300_SYSCON_SMCR_SEMI_SREFACK_IND (0x0008)
+#define U300_SYSCON_SMCR_SEMI_SREFREQ_ENABLE (0x0004)
+#define U300_SYSCON_SMCR_SEMI_EXT_BOOT_MODE_ENABLE (0x0002)
+/* CPU_SW_DBGEN Software Debug Enable 16bit (R/W) */
+#define U300_SYSCON_CSDR (0x4f0)
+#define U300_SYSCON_CSDR_SW_DEBUG_ENABLE (0x0001)
+/* PRINT_CONTROL Print Control 16bit (R/-) */
+#define U300_SYSCON_PCR (0x4f8)
+#define U300_SYSCON_PCR_SERV_IND (0x0001)
+/* BOOT_CONTROL 16bit (R/-) */
+#define U300_SYSCON_BCR (0x4fc)
+#define U300_SYSCON_BCR_ACC_CPU_SUBSYS_VINITHI_IND (0x0400)
+#define U300_SYSCON_BCR_APP_CPU_SUBSYS_VINITHI_IND (0x0200)
+#define U300_SYSCON_BCR_EXTRA_BOOT_OPTION_MASK (0x01FC)
+#define U300_SYSCON_BCR_APP_BOOT_SERV_MASK (0x0003)
+
+
+/* CPU clock defines */
+/**
+ * CPU high frequency in MHz
+ */
+#define SYSCON_CPU_CLOCK_HIGH 208
+/**
+ * CPU medium frequency in MHz
+ */
+#define SYSCON_CPU_CLOCK_MEDIUM 104
+/**
+ * CPU low frequency in MHz
+ */
+#define SYSCON_CPU_CLOCK_LOW 13
+
+/* EMIF clock defines */
+/**
+ * EMIF high frequency in MHz
+ */
+#define SYSCON_EMIF_CLOCK_HIGH 104
+/**
+ * EMIF medium frequency in MHz
+ */
+#define SYSCON_EMIF_CLOCK_MEDIUM 104
+/**
+ * EMIF low frequency in MHz
+ */
+#define SYSCON_EMIF_CLOCK_LOW 13
+
+/* AHB clock defines */
+/**
+ * AHB high frequency in MHz
+ */
+#define SYSCON_AHB_CLOCK_HIGH 52
+/**
+ * AHB medium frequency in MHz
+ */
+#define SYSCON_AHB_CLOCK_MEDIUM 52
+/**
+ * AHB low frequency in MHz
+ */
+#define SYSCON_AHB_CLOCK_LOW 7 /* i.e 13/2=6.5MHz */
+
+enum syscon_busmaster {
+ SYSCON_BM_DMAC,
+ SYSCON_BM_XGAM,
+ SYSCON_BM_VIDEO_ENC
+};
+
+/*
+ * Note that this array must match the order of the array "clk_reg"
+ * in syscon.c
+ */
+enum syscon_clk {
+ SYSCON_CLKCONTROL_SLOW_BRIDGE,
+ SYSCON_CLKCONTROL_UART,
+ SYSCON_CLKCONTROL_BTR,
+ SYSCON_CLKCONTROL_EH,
+ SYSCON_CLKCONTROL_GPIO,
+ SYSCON_CLKCONTROL_KEYPAD,
+ SYSCON_CLKCONTROL_APP_TIMER,
+ SYSCON_CLKCONTROL_ACC_TIMER,
+ SYSCON_CLKCONTROL_FAST_BRIDGE,
+ SYSCON_CLKCONTROL_I2C0,
+ SYSCON_CLKCONTROL_I2C1,
+ SYSCON_CLKCONTROL_I2S0,
+ SYSCON_CLKCONTROL_I2S1,
+ SYSCON_CLKCONTROL_MMC,
+ SYSCON_CLKCONTROL_SPI,
+ SYSCON_CLKCONTROL_I2S0_CORE,
+ SYSCON_CLKCONTROL_I2S1_CORE,
+ SYSCON_CLKCONTROL_AAIF,
+ SYSCON_CLKCONTROL_AHB,
+ SYSCON_CLKCONTROL_APEX,
+ SYSCON_CLKCONTROL_CPU,
+ SYSCON_CLKCONTROL_DMA,
+ SYSCON_CLKCONTROL_EMIF,
+ SYSCON_CLKCONTROL_NAND_IF,
+ SYSCON_CLKCONTROL_VIDEO_ENC,
+ SYSCON_CLKCONTROL_XGAM,
+ SYSCON_CLKCONTROL_SEMI,
+ SYSCON_CLKCONTROL_AHB_SUBSYS,
+ SYSCON_CLKCONTROL_MSPRO
+};
+
+enum syscon_sysclk_mode {
+ SYSCON_SYSCLK_DISABLED,
+ SYSCON_SYSCLK_M_CLK,
+ SYSCON_SYSCLK_ACC_FSM,
+ SYSCON_SYSCLK_PLL60_48,
+ SYSCON_SYSCLK_PLL60_60,
+ SYSCON_SYSCLK_ACC_PLL208,
+ SYSCON_SYSCLK_APP_PLL13,
+ SYSCON_SYSCLK_APP_FSM,
+ SYSCON_SYSCLK_RTC,
+ SYSCON_SYSCLK_APP_PLL208
+};
+
+enum syscon_sysclk_req {
+ SYSCON_SYSCLKREQ_DISABLED,
+ SYSCON_SYSCLKREQ_ACTIVE_LOW
+};
+
+enum syscon_clk_mode {
+ SYSCON_CLKMODE_OFF,
+ SYSCON_CLKMODE_DEFAULT,
+ SYSCON_CLKMODE_LOW,
+ SYSCON_CLKMODE_MEDIUM,
+ SYSCON_CLKMODE_HIGH,
+ SYSCON_CLKMODE_PERMANENT,
+ SYSCON_CLKMODE_ON,
+};
+
+enum syscon_call_mode {
+ SYSCON_CLKCALL_NOWAIT,
+ SYSCON_CLKCALL_WAIT,
+};
+
+int syscon_dc_on(bool keep_power_on);
+int syscon_set_busmaster_active_state(enum syscon_busmaster busmaster,
+ bool active);
+bool syscon_get_busmaster_active_state(void);
+int syscon_set_sleep_mask(enum syscon_clk,
+ bool sleep_ctrl);
+int syscon_config_sysclk(u32 sysclk,
+ enum syscon_sysclk_mode sysclkmode,
+ bool inverse,
+ u32 divisor,
+ enum syscon_sysclk_req sysclkreq);
+bool syscon_can_turn_off_semi_clock(void);
+
+/* This function is restricted to core.c */
+int syscon_request_normal_power(bool req);
+
+/* This function is restricted to be used by platform_speed.c */
+int syscon_speed_request(enum syscon_call_mode wait_mode,
+ enum syscon_clk_mode req_clk_mode);
+#endif /* __MACH_SYSCON_H */
diff --git a/arch/arm/mach-u300/include/mach/system.h b/arch/arm/mach-u300/include/mach/system.h
new file mode 100644
index 000000000000..8daf13634ce0
--- /dev/null
+++ b/arch/arm/mach-u300/include/mach/system.h
@@ -0,0 +1,42 @@
+/*
+ *
+ * arch/arm/mach-u300/include/mach/system.h
+ *
+ *
+ * Copyright (C) 2007-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * System shutdown and reset functions.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+#include <mach/hardware.h>
+#include <asm/io.h>
+#include <asm/hardware/vic.h>
+#include <asm/irq.h>
+
+/* Forward declare this function from the watchdog */
+void coh901327_watchdog_reset(void);
+
+static inline void arch_idle(void)
+{
+ cpu_do_idle();
+}
+
+static void arch_reset(char mode, const char *cmd)
+{
+ switch (mode) {
+ case 's':
+ case 'h':
+ printk(KERN_CRIT "RESET: shutting down/rebooting system\n");
+ /* Disable interrupts */
+ local_irq_disable();
+#ifdef CONFIG_COH901327_WATCHDOG
+ coh901327_watchdog_reset();
+#endif
+ break;
+ default:
+ /* Do nothing */
+ break;
+ }
+ /* Wait for system do die/reset. */
+ while (1);
+}
diff --git a/arch/arm/mach-u300/include/mach/timex.h b/arch/arm/mach-u300/include/mach/timex.h
new file mode 100644
index 000000000000..f233b72633f6
--- /dev/null
+++ b/arch/arm/mach-u300/include/mach/timex.h
@@ -0,0 +1,17 @@
+/*
+ *
+ * arch/arm/mach-u300/include/mach/timex.h
+ *
+ *
+ * Copyright (C) 2006-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Platform tick rate definition.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+#ifndef __MACH_TIMEX_H
+#define __MACH_TIMEX_H
+
+/* This is for the APP OS GP1 (General Purpose 1) timer */
+#define CLOCK_TICK_RATE 1000000
+
+#endif
diff --git a/arch/arm/mach-u300/include/mach/u300-regs.h b/arch/arm/mach-u300/include/mach/u300-regs.h
new file mode 100644
index 000000000000..88333dfb19fc
--- /dev/null
+++ b/arch/arm/mach-u300/include/mach/u300-regs.h
@@ -0,0 +1,187 @@
+/*
+ *
+ * arch/arm/mach-u300/include/mach/u300-regs.h
+ *
+ *
+ * Copyright (C) 2006-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Basic register address definitions in physical memory and
+ * some block defintions for core devices like the timer.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+
+#ifndef __MACH_U300_REGS_H
+#define __MACH_U300_REGS_H
+
+/*
+ * These are the large blocks of memory allocated for I/O.
+ * the defines are used for setting up the I/O memory mapping.
+ */
+
+/* NAND Flash CS0 */
+#define U300_NAND_CS0_PHYS_BASE 0x80000000
+#define U300_NAND_CS0_VIRT_BASE 0xff040000
+
+/* NFIF */
+#define U300_NAND_IF_PHYS_BASE 0x9f800000
+#define U300_NAND_IF_VIRT_BASE 0xff030000
+
+/* AHB Peripherals */
+#define U300_AHB_PER_PHYS_BASE 0xa0000000
+#define U300_AHB_PER_VIRT_BASE 0xff010000
+
+/* FAST Peripherals */
+#define U300_FAST_PER_PHYS_BASE 0xc0000000
+#define U300_FAST_PER_VIRT_BASE 0xff020000
+
+/* SLOW Peripherals */
+#define U300_SLOW_PER_PHYS_BASE 0xc0010000
+#define U300_SLOW_PER_VIRT_BASE 0xff000000
+
+/* Boot ROM */
+#define U300_BOOTROM_PHYS_BASE 0xffff0000
+#define U300_BOOTROM_VIRT_BASE 0xffff0000
+
+/* SEMI config base */
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SEMI_CONFIG_BASE 0x2FFE0000
+#else
+#define U300_SEMI_CONFIG_BASE 0x30000000
+#endif
+
+/*
+ * All the following peripherals are specified at their PHYSICAL address,
+ * so if you need to access them (in the kernel), you MUST use the macros
+ * defined in <asm/io.h> to map to the IO_ADDRESS_AHB() IO_ADDRESS_FAST()
+ * etc.
+ */
+
+/*
+ * AHB peripherals
+ */
+
+/* AHB Peripherals Bridge Controller */
+#define U300_AHB_BRIDGE_BASE (U300_AHB_PER_PHYS_BASE+0x0000)
+
+/* Vectored Interrupt Controller 0, servicing 32 interrupts */
+#define U300_INTCON0_BASE (U300_AHB_PER_PHYS_BASE+0x1000)
+#define U300_INTCON0_VBASE (U300_AHB_PER_VIRT_BASE+0x1000)
+
+/* Vectored Interrupt Controller 1, servicing 32 interrupts */
+#define U300_INTCON1_BASE (U300_AHB_PER_PHYS_BASE+0x2000)
+#define U300_INTCON1_VBASE (U300_AHB_PER_VIRT_BASE+0x2000)
+
+/* Memory Stick Pro (MSPRO) controller */
+#define U300_MSPRO_BASE (U300_AHB_PER_PHYS_BASE+0x3000)
+
+/* EMIF Configuration Area */
+#define U300_EMIF_CFG_BASE (U300_AHB_PER_PHYS_BASE+0x4000)
+
+
+/*
+ * FAST peripherals
+ */
+
+/* FAST bridge control */
+#define U300_FAST_BRIDGE_BASE (U300_FAST_PER_PHYS_BASE+0x0000)
+
+/* MMC/SD controller */
+#define U300_MMCSD_BASE (U300_FAST_PER_PHYS_BASE+0x1000)
+
+/* PCM I2S0 controller */
+#define U300_PCM_I2S0_BASE (U300_FAST_PER_PHYS_BASE+0x2000)
+
+/* PCM I2S1 controller */
+#define U300_PCM_I2S1_BASE (U300_FAST_PER_PHYS_BASE+0x3000)
+
+/* I2C0 controller */
+#define U300_I2C0_BASE (U300_FAST_PER_PHYS_BASE+0x4000)
+
+/* I2C1 controller */
+#define U300_I2C1_BASE (U300_FAST_PER_PHYS_BASE+0x5000)
+
+/* SPI controller */
+#define U300_SPI_BASE (U300_FAST_PER_PHYS_BASE+0x6000)
+
+#ifdef CONFIG_MACH_U300_BS335
+/* Fast UART1 on U335 only */
+#define U300_UART1_BASE (U300_SLOW_PER_PHYS_BASE+0x7000)
+#endif
+
+/*
+ * SLOW peripherals
+ */
+
+/* SLOW bridge control */
+#define U300_SLOW_BRIDGE_BASE (U300_SLOW_PER_PHYS_BASE)
+
+/* SYSCON */
+#define U300_SYSCON_BASE (U300_SLOW_PER_PHYS_BASE+0x1000)
+#define U300_SYSCON_VBASE (U300_SLOW_PER_VIRT_BASE+0x1000)
+
+/* Watchdog */
+#define U300_WDOG_BASE (U300_SLOW_PER_PHYS_BASE+0x2000)
+
+/* UART0 */
+#define U300_UART0_BASE (U300_SLOW_PER_PHYS_BASE+0x3000)
+
+/* APP side special timer */
+#define U300_TIMER_APP_BASE (U300_SLOW_PER_PHYS_BASE+0x4000)
+#define U300_TIMER_APP_VBASE (U300_SLOW_PER_VIRT_BASE+0x4000)
+
+/* Keypad */
+#define U300_KEYPAD_BASE (U300_SLOW_PER_PHYS_BASE+0x5000)
+
+/* GPIO */
+#define U300_GPIO_BASE (U300_SLOW_PER_PHYS_BASE+0x6000)
+
+/* RTC */
+#define U300_RTC_BASE (U300_SLOW_PER_PHYS_BASE+0x7000)
+
+/* Bus tracer */
+#define U300_BUSTR_BASE (U300_SLOW_PER_PHYS_BASE+0x8000)
+
+/* Event handler (hardware queue) */
+#define U300_EVHIST_BASE (U300_SLOW_PER_PHYS_BASE+0x9000)
+
+/* Genric Timer */
+#define U300_TIMER_BASE (U300_SLOW_PER_PHYS_BASE+0xa000)
+
+/* PPM */
+#define U300_PPM_BASE (U300_SLOW_PER_PHYS_BASE+0xb000)
+
+
+/*
+ * REST peripherals
+ */
+
+/* ISP (image signal processor) is only available in U335 */
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_ISP_BASE (0xA0008000)
+#endif
+
+/* DMA Controller base */
+#define U300_DMAC_BASE (0xC0020000)
+
+/* MSL Base */
+#define U300_MSL_BASE (0xc0022000)
+
+/* APEX Base */
+#define U300_APEX_BASE (0xc0030000)
+
+/* Video Encoder Base */
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_VIDEOENC_BASE (0xc0080000)
+#else
+#define U300_VIDEOENC_BASE (0xc0040000)
+#endif
+
+/* XGAM Base */
+#define U300_XGAM_BASE (0xd0000000)
+
+/*
+ * Virtual accessor macros for static devices
+ */
+
+
+#endif
diff --git a/arch/arm/mach-u300/include/mach/uncompress.h b/arch/arm/mach-u300/include/mach/uncompress.h
new file mode 100644
index 000000000000..29acb718acf7
--- /dev/null
+++ b/arch/arm/mach-u300/include/mach/uncompress.h
@@ -0,0 +1,46 @@
+/*
+ * arch/arm/mach-u300/include/mach/uncompress.h
+ *
+ * Copyright (C) 2003 ARM Limited
+ *
+ * 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 AMBA_UART_DR (*(volatile unsigned char *)0xc0013000)
+#define AMBA_UART_LCRH (*(volatile unsigned char *)0xc001302C)
+#define AMBA_UART_CR (*(volatile unsigned char *)0xc0013030)
+#define AMBA_UART_FR (*(volatile unsigned char *)0xc0013018)
+
+/*
+ * This does not append a newline
+ */
+static inline void putc(int c)
+{
+ while (AMBA_UART_FR & (1 << 5))
+ barrier();
+
+ AMBA_UART_DR = c;
+}
+
+static inline void flush(void)
+{
+ while (AMBA_UART_FR & (1 << 3))
+ barrier();
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/arch/arm/mach-u300/include/mach/vmalloc.h b/arch/arm/mach-u300/include/mach/vmalloc.h
new file mode 100644
index 000000000000..b00c51a66fbe
--- /dev/null
+++ b/arch/arm/mach-u300/include/mach/vmalloc.h
@@ -0,0 +1,12 @@
+/*
+ *
+ * arch/arm/mach-u300/include/mach/vmalloc.h
+ *
+ *
+ * Copyright (C) 2006-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Virtual memory allocations
+ * End must be above the I/O registers and on an even 2MiB boundary.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+#define VMALLOC_END 0xfe800000
diff --git a/arch/arm/mach-u300/mmc.c b/arch/arm/mach-u300/mmc.c
new file mode 100644
index 000000000000..3138d3955c9e
--- /dev/null
+++ b/arch/arm/mach-u300/mmc.c
@@ -0,0 +1,216 @@
+/*
+ *
+ * arch/arm/mach-u300/mmc.c
+ *
+ *
+ * Copyright (C) 2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ * Author: Johan Lundin <johan.lundin@stericsson.com>
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
+ */
+#include <linux/device.h>
+#include <linux/amba/bus.h>
+#include <linux/mmc/host.h>
+#include <linux/input.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/machine.h>
+#include <linux/gpio.h>
+
+#include <asm/mach/mmc.h>
+#include "mmc.h"
+
+struct mmci_card_event {
+ struct input_dev *mmc_input;
+ int mmc_inserted;
+ struct work_struct workq;
+ struct mmc_platform_data mmc0_plat_data;
+};
+
+static unsigned int mmc_status(struct device *dev)
+{
+ struct mmci_card_event *mmci_card = container_of(
+ dev->platform_data,
+ struct mmci_card_event, mmc0_plat_data);
+
+ return mmci_card->mmc_inserted;
+}
+
+/*
+ * Here follows a large chunk of code which will only be enabled if you
+ * have both the AB3100 chip mounted and the MMC subsystem activated.
+ */
+
+static u32 mmc_translate_vdd(struct device *dev, unsigned int voltage)
+{
+ int v;
+
+ /*
+ * MMC Spec:
+ * bit 7: 1.70 - 1.95V
+ * bit 8 - 14: 2.0 - 2.6V
+ * bit 15 - 23: 2.7 - 3.6V
+ *
+ * ab3100 voltages:
+ * 000 - 2.85V
+ * 001 - 2.75V
+ * 010 - 1.8V
+ * 011 - 1.5V
+ */
+ switch (voltage) {
+ case 8:
+ v = 3;
+ break;
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ v = 1;
+ break;
+ case 16:
+ v = 1;
+ break;
+ case 17:
+ case 18:
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ v = 0;
+ break;
+ default:
+ v = 0;
+ break;
+ }
+
+ /* PL180 voltage register bits */
+ return v << 2;
+}
+
+
+
+static int mmci_callback(void *data)
+{
+ struct mmci_card_event *mmci_card = data;
+
+ disable_irq_on_gpio_pin(U300_GPIO_PIN_MMC_CD);
+ schedule_work(&mmci_card->workq);
+
+ return 0;
+}
+
+
+static ssize_t gpio_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct mmci_card_event *mmci_card = container_of(
+ dev->platform_data,
+ struct mmci_card_event, mmc0_plat_data);
+
+
+ return sprintf(buf, "%d\n", !mmci_card->mmc_inserted);
+}
+
+static DEVICE_ATTR(mmc_inserted, S_IRUGO, gpio_show, NULL);
+
+static void _mmci_callback(struct work_struct *ws)
+{
+
+ struct mmci_card_event *mmci_card = container_of(
+ ws,
+ struct mmci_card_event, workq);
+
+ mdelay(20);
+
+ mmci_card->mmc_inserted = !!gpio_get_value(U300_GPIO_PIN_MMC_CD);
+
+ input_report_switch(mmci_card->mmc_input, KEY_INSERT,
+ !mmci_card->mmc_inserted);
+ input_sync(mmci_card->mmc_input);
+
+ pr_debug("MMC/SD card was %s\n",
+ mmci_card->mmc_inserted ? "removed" : "inserted");
+
+ enable_irq_on_gpio_pin(U300_GPIO_PIN_MMC_CD, !mmci_card->mmc_inserted);
+}
+
+int __devinit mmc_init(struct amba_device *adev)
+{
+ struct mmci_card_event *mmci_card;
+ struct device *mmcsd_device = &adev->dev;
+ int ret = 0;
+
+ mmci_card = kzalloc(sizeof(struct mmci_card_event), GFP_KERNEL);
+ if (!mmci_card)
+ return -ENOMEM;
+
+ /* Nominally 2.85V on our platform */
+ mmci_card->mmc0_plat_data.ocr_mask = MMC_VDD_28_29;
+ mmci_card->mmc0_plat_data.translate_vdd = mmc_translate_vdd;
+ mmci_card->mmc0_plat_data.status = mmc_status;
+
+ mmcsd_device->platform_data = (void *) &mmci_card->mmc0_plat_data;
+
+ INIT_WORK(&mmci_card->workq, _mmci_callback);
+
+ ret = gpio_request(U300_GPIO_PIN_MMC_CD, "MMC card detection");
+ if (ret) {
+ printk(KERN_CRIT "Could not allocate MMC card detection " \
+ "GPIO pin\n");
+ goto out;
+ }
+
+ ret = gpio_direction_input(U300_GPIO_PIN_MMC_CD);
+ if (ret) {
+ printk(KERN_CRIT "Invalid GPIO pin requested\n");
+ goto out;
+ }
+
+ ret = sysfs_create_file(&mmcsd_device->kobj,
+ &dev_attr_mmc_inserted.attr);
+ if (ret)
+ goto out;
+
+ mmci_card->mmc_input = input_allocate_device();
+ if (!mmci_card->mmc_input) {
+ printk(KERN_CRIT "Could not allocate MMC input device\n");
+ return -ENOMEM;
+ }
+
+ mmci_card->mmc_input->name = "MMC insert notification";
+ mmci_card->mmc_input->id.bustype = BUS_HOST;
+ mmci_card->mmc_input->id.vendor = 0;
+ mmci_card->mmc_input->id.product = 0;
+ mmci_card->mmc_input->id.version = 0x0100;
+ mmci_card->mmc_input->dev.parent = mmcsd_device;
+ input_set_capability(mmci_card->mmc_input, EV_SW, KEY_INSERT);
+
+ /*
+ * Since this must always be compiled into the kernel, this input
+ * is never unregistered or free:ed.
+ */
+ ret = input_register_device(mmci_card->mmc_input);
+ if (ret) {
+ input_free_device(mmci_card->mmc_input);
+ goto out;
+ }
+
+ input_set_drvdata(mmci_card->mmc_input, mmci_card);
+
+ ret = gpio_register_callback(U300_GPIO_PIN_MMC_CD, mmci_callback,
+ mmci_card);
+
+ schedule_work(&mmci_card->workq);
+
+ printk(KERN_INFO "Registered MMC insert/remove notification\n");
+out:
+ return ret;
+}
diff --git a/arch/arm/mach-u300/mmc.h b/arch/arm/mach-u300/mmc.h
new file mode 100644
index 000000000000..92b85125abb3
--- /dev/null
+++ b/arch/arm/mach-u300/mmc.h
@@ -0,0 +1,18 @@
+/*
+ *
+ * arch/arm/mach-u300/mmc.h
+ *
+ *
+ * Copyright (C) 2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
+ */
+#ifndef MMC_H
+#define MMC_H
+
+#include <linux/amba/bus.h>
+
+int __devinit mmc_init(struct amba_device *adev);
+
+#endif
diff --git a/arch/arm/mach-u300/padmux.c b/arch/arm/mach-u300/padmux.c
new file mode 100644
index 000000000000..f3664564f086
--- /dev/null
+++ b/arch/arm/mach-u300/padmux.c
@@ -0,0 +1,58 @@
+/*
+ *
+ * arch/arm/mach-u300/padmux.c
+ *
+ *
+ * Copyright (C) 2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * U300 PADMUX functions
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ *
+ */
+#include <linux/io.h>
+#include <linux/err.h>
+#include <mach/u300-regs.h>
+#include <mach/syscon.h>
+
+#include "padmux.h"
+
+/* Set the PAD MUX to route the MMC reader correctly to GPIO0. */
+void pmx_set_mission_mode_mmc(void)
+{
+ u16 val;
+
+ val = readw(U300_SYSCON_VBASE + U300_SYSCON_PMC1LR);
+ val &= ~U300_SYSCON_PMC1LR_MMCSD_MASK;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_PMC1LR);
+ val = readw(U300_SYSCON_VBASE + U300_SYSCON_PMC1HR);
+ val &= ~U300_SYSCON_PMC1HR_APP_GPIO_1_MASK;
+ val |= U300_SYSCON_PMC1HR_APP_GPIO_1_MMC;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_PMC1HR);
+}
+
+void pmx_set_mission_mode_spi(void)
+{
+ u16 val;
+
+ /* Set up padmuxing so the SPI port and its chipselects are active */
+ val = readw(U300_SYSCON_VBASE + U300_SYSCON_PMC1HR);
+ /*
+ * Activate the SPI port (disable the use of these pins for generic
+ * GPIO, DSP, AAIF
+ */
+ val &= ~U300_SYSCON_PMC1HR_APP_SPI_2_MASK;
+ val |= U300_SYSCON_PMC1HR_APP_SPI_2_SPI;
+ /*
+ * Use GPIO pin SPI CS1 for CS1 actually (it can be used for other
+ * things also)
+ */
+ val &= ~U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK;
+ val |= U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI;
+ /*
+ * Use GPIO pin SPI CS2 for CS2 actually (it can be used for other
+ * things also)
+ */
+ val &= ~U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK;
+ val |= U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI;
+ writew(val, U300_SYSCON_VBASE + U300_SYSCON_PMC1HR);
+}
diff --git a/arch/arm/mach-u300/padmux.h b/arch/arm/mach-u300/padmux.h
new file mode 100644
index 000000000000..8c2099ac5046
--- /dev/null
+++ b/arch/arm/mach-u300/padmux.h
@@ -0,0 +1,19 @@
+/*
+ *
+ * arch/arm/mach-u300/padmux.h
+ *
+ *
+ * Copyright (C) 2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * U300 PADMUX API
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ *
+ */
+
+#ifndef __MACH_U300_PADMUX_H
+#define __MACH_U300_PADMUX_H
+
+void pmx_set_mission_mode_mmc(void);
+void pmx_set_mission_mode_spi(void);
+
+#endif
diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c
new file mode 100644
index 000000000000..57b5351b1816
--- /dev/null
+++ b/arch/arm/mach-u300/timer.c
@@ -0,0 +1,422 @@
+/*
+ *
+ * arch/arm/mach-u300/timer.c
+ *
+ *
+ * Copyright (C) 2007-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Timer COH 901 328, runs the OS timer interrupt.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/types.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+
+/* Generic stuff */
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+
+#include "clock.h"
+
+/*
+ * APP side special timer registers
+ * This timer contains four timers which can fire an interrupt each.
+ * OS (operating system) timer @ 32768 Hz
+ * DD (device driver) timer @ 1 kHz
+ * GP1 (general purpose 1) timer @ 1MHz
+ * GP2 (general purpose 2) timer @ 1MHz
+ */
+
+/* Reset OS Timer 32bit (-/W) */
+#define U300_TIMER_APP_ROST (0x0000)
+#define U300_TIMER_APP_ROST_TIMER_RESET (0x00000000)
+/* Enable OS Timer 32bit (-/W) */
+#define U300_TIMER_APP_EOST (0x0004)
+#define U300_TIMER_APP_EOST_TIMER_ENABLE (0x00000000)
+/* Disable OS Timer 32bit (-/W) */
+#define U300_TIMER_APP_DOST (0x0008)
+#define U300_TIMER_APP_DOST_TIMER_DISABLE (0x00000000)
+/* OS Timer Mode Register 32bit (-/W) */
+#define U300_TIMER_APP_SOSTM (0x000c)
+#define U300_TIMER_APP_SOSTM_MODE_CONTINUOUS (0x00000000)
+#define U300_TIMER_APP_SOSTM_MODE_ONE_SHOT (0x00000001)
+/* OS Timer Status Register 32bit (R/-) */
+#define U300_TIMER_APP_OSTS (0x0010)
+#define U300_TIMER_APP_OSTS_TIMER_STATE_MASK (0x0000000F)
+#define U300_TIMER_APP_OSTS_TIMER_STATE_IDLE (0x00000001)
+#define U300_TIMER_APP_OSTS_TIMER_STATE_ACTIVE (0x00000002)
+#define U300_TIMER_APP_OSTS_ENABLE_IND (0x00000010)
+#define U300_TIMER_APP_OSTS_MODE_MASK (0x00000020)
+#define U300_TIMER_APP_OSTS_MODE_CONTINUOUS (0x00000000)
+#define U300_TIMER_APP_OSTS_MODE_ONE_SHOT (0x00000020)
+#define U300_TIMER_APP_OSTS_IRQ_ENABLED_IND (0x00000040)
+#define U300_TIMER_APP_OSTS_IRQ_PENDING_IND (0x00000080)
+/* OS Timer Current Count Register 32bit (R/-) */
+#define U300_TIMER_APP_OSTCC (0x0014)
+/* OS Timer Terminal Count Register 32bit (R/W) */
+#define U300_TIMER_APP_OSTTC (0x0018)
+/* OS Timer Interrupt Enable Register 32bit (-/W) */
+#define U300_TIMER_APP_OSTIE (0x001c)
+#define U300_TIMER_APP_OSTIE_IRQ_DISABLE (0x00000000)
+#define U300_TIMER_APP_OSTIE_IRQ_ENABLE (0x00000001)
+/* OS Timer Interrupt Acknowledge Register 32bit (-/W) */
+#define U300_TIMER_APP_OSTIA (0x0020)
+#define U300_TIMER_APP_OSTIA_IRQ_ACK (0x00000080)
+
+/* Reset DD Timer 32bit (-/W) */
+#define U300_TIMER_APP_RDDT (0x0040)
+#define U300_TIMER_APP_RDDT_TIMER_RESET (0x00000000)
+/* Enable DD Timer 32bit (-/W) */
+#define U300_TIMER_APP_EDDT (0x0044)
+#define U300_TIMER_APP_EDDT_TIMER_ENABLE (0x00000000)
+/* Disable DD Timer 32bit (-/W) */
+#define U300_TIMER_APP_DDDT (0x0048)
+#define U300_TIMER_APP_DDDT_TIMER_DISABLE (0x00000000)
+/* DD Timer Mode Register 32bit (-/W) */
+#define U300_TIMER_APP_SDDTM (0x004c)
+#define U300_TIMER_APP_SDDTM_MODE_CONTINUOUS (0x00000000)
+#define U300_TIMER_APP_SDDTM_MODE_ONE_SHOT (0x00000001)
+/* DD Timer Status Register 32bit (R/-) */
+#define U300_TIMER_APP_DDTS (0x0050)
+#define U300_TIMER_APP_DDTS_TIMER_STATE_MASK (0x0000000F)
+#define U300_TIMER_APP_DDTS_TIMER_STATE_IDLE (0x00000001)
+#define U300_TIMER_APP_DDTS_TIMER_STATE_ACTIVE (0x00000002)
+#define U300_TIMER_APP_DDTS_ENABLE_IND (0x00000010)
+#define U300_TIMER_APP_DDTS_MODE_MASK (0x00000020)
+#define U300_TIMER_APP_DDTS_MODE_CONTINUOUS (0x00000000)
+#define U300_TIMER_APP_DDTS_MODE_ONE_SHOT (0x00000020)
+#define U300_TIMER_APP_DDTS_IRQ_ENABLED_IND (0x00000040)
+#define U300_TIMER_APP_DDTS_IRQ_PENDING_IND (0x00000080)
+/* DD Timer Current Count Register 32bit (R/-) */
+#define U300_TIMER_APP_DDTCC (0x0054)
+/* DD Timer Terminal Count Register 32bit (R/W) */
+#define U300_TIMER_APP_DDTTC (0x0058)
+/* DD Timer Interrupt Enable Register 32bit (-/W) */
+#define U300_TIMER_APP_DDTIE (0x005c)
+#define U300_TIMER_APP_DDTIE_IRQ_DISABLE (0x00000000)
+#define U300_TIMER_APP_DDTIE_IRQ_ENABLE (0x00000001)
+/* DD Timer Interrupt Acknowledge Register 32bit (-/W) */
+#define U300_TIMER_APP_DDTIA (0x0060)
+#define U300_TIMER_APP_DDTIA_IRQ_ACK (0x00000080)
+
+/* Reset GP1 Timer 32bit (-/W) */
+#define U300_TIMER_APP_RGPT1 (0x0080)
+#define U300_TIMER_APP_RGPT1_TIMER_RESET (0x00000000)
+/* Enable GP1 Timer 32bit (-/W) */
+#define U300_TIMER_APP_EGPT1 (0x0084)
+#define U300_TIMER_APP_EGPT1_TIMER_ENABLE (0x00000000)
+/* Disable GP1 Timer 32bit (-/W) */
+#define U300_TIMER_APP_DGPT1 (0x0088)
+#define U300_TIMER_APP_DGPT1_TIMER_DISABLE (0x00000000)
+/* GP1 Timer Mode Register 32bit (-/W) */
+#define U300_TIMER_APP_SGPT1M (0x008c)
+#define U300_TIMER_APP_SGPT1M_MODE_CONTINUOUS (0x00000000)
+#define U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT (0x00000001)
+/* GP1 Timer Status Register 32bit (R/-) */
+#define U300_TIMER_APP_GPT1S (0x0090)
+#define U300_TIMER_APP_GPT1S_TIMER_STATE_MASK (0x0000000F)
+#define U300_TIMER_APP_GPT1S_TIMER_STATE_IDLE (0x00000001)
+#define U300_TIMER_APP_GPT1S_TIMER_STATE_ACTIVE (0x00000002)
+#define U300_TIMER_APP_GPT1S_ENABLE_IND (0x00000010)
+#define U300_TIMER_APP_GPT1S_MODE_MASK (0x00000020)
+#define U300_TIMER_APP_GPT1S_MODE_CONTINUOUS (0x00000000)
+#define U300_TIMER_APP_GPT1S_MODE_ONE_SHOT (0x00000020)
+#define U300_TIMER_APP_GPT1S_IRQ_ENABLED_IND (0x00000040)
+#define U300_TIMER_APP_GPT1S_IRQ_PENDING_IND (0x00000080)
+/* GP1 Timer Current Count Register 32bit (R/-) */
+#define U300_TIMER_APP_GPT1CC (0x0094)
+/* GP1 Timer Terminal Count Register 32bit (R/W) */
+#define U300_TIMER_APP_GPT1TC (0x0098)
+/* GP1 Timer Interrupt Enable Register 32bit (-/W) */
+#define U300_TIMER_APP_GPT1IE (0x009c)
+#define U300_TIMER_APP_GPT1IE_IRQ_DISABLE (0x00000000)
+#define U300_TIMER_APP_GPT1IE_IRQ_ENABLE (0x00000001)
+/* GP1 Timer Interrupt Acknowledge Register 32bit (-/W) */
+#define U300_TIMER_APP_GPT1IA (0x00a0)
+#define U300_TIMER_APP_GPT1IA_IRQ_ACK (0x00000080)
+
+/* Reset GP2 Timer 32bit (-/W) */
+#define U300_TIMER_APP_RGPT2 (0x00c0)
+#define U300_TIMER_APP_RGPT2_TIMER_RESET (0x00000000)
+/* Enable GP2 Timer 32bit (-/W) */
+#define U300_TIMER_APP_EGPT2 (0x00c4)
+#define U300_TIMER_APP_EGPT2_TIMER_ENABLE (0x00000000)
+/* Disable GP2 Timer 32bit (-/W) */
+#define U300_TIMER_APP_DGPT2 (0x00c8)
+#define U300_TIMER_APP_DGPT2_TIMER_DISABLE (0x00000000)
+/* GP2 Timer Mode Register 32bit (-/W) */
+#define U300_TIMER_APP_SGPT2M (0x00cc)
+#define U300_TIMER_APP_SGPT2M_MODE_CONTINUOUS (0x00000000)
+#define U300_TIMER_APP_SGPT2M_MODE_ONE_SHOT (0x00000001)
+/* GP2 Timer Status Register 32bit (R/-) */
+#define U300_TIMER_APP_GPT2S (0x00d0)
+#define U300_TIMER_APP_GPT2S_TIMER_STATE_MASK (0x0000000F)
+#define U300_TIMER_APP_GPT2S_TIMER_STATE_IDLE (0x00000001)
+#define U300_TIMER_APP_GPT2S_TIMER_STATE_ACTIVE (0x00000002)
+#define U300_TIMER_APP_GPT2S_ENABLE_IND (0x00000010)
+#define U300_TIMER_APP_GPT2S_MODE_MASK (0x00000020)
+#define U300_TIMER_APP_GPT2S_MODE_CONTINUOUS (0x00000000)
+#define U300_TIMER_APP_GPT2S_MODE_ONE_SHOT (0x00000020)
+#define U300_TIMER_APP_GPT2S_IRQ_ENABLED_IND (0x00000040)
+#define U300_TIMER_APP_GPT2S_IRQ_PENDING_IND (0x00000080)
+/* GP2 Timer Current Count Register 32bit (R/-) */
+#define U300_TIMER_APP_GPT2CC (0x00d4)
+/* GP2 Timer Terminal Count Register 32bit (R/W) */
+#define U300_TIMER_APP_GPT2TC (0x00d8)
+/* GP2 Timer Interrupt Enable Register 32bit (-/W) */
+#define U300_TIMER_APP_GPT2IE (0x00dc)
+#define U300_TIMER_APP_GPT2IE_IRQ_DISABLE (0x00000000)
+#define U300_TIMER_APP_GPT2IE_IRQ_ENABLE (0x00000001)
+/* GP2 Timer Interrupt Acknowledge Register 32bit (-/W) */
+#define U300_TIMER_APP_GPT2IA (0x00e0)
+#define U300_TIMER_APP_GPT2IA_IRQ_ACK (0x00000080)
+
+/* Clock request control register - all four timers */
+#define U300_TIMER_APP_CRC (0x100)
+#define U300_TIMER_APP_CRC_CLOCK_REQUEST_ENABLE (0x00000001)
+
+#define TICKS_PER_JIFFY ((CLOCK_TICK_RATE + (HZ/2)) / HZ)
+#define US_PER_TICK ((1000000 + (HZ/2)) / HZ)
+
+/*
+ * The u300_set_mode() function is always called first, if we
+ * have oneshot timer active, the oneshot scheduling function
+ * u300_set_next_event() is called immediately after.
+ */
+static void u300_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ /* Disable interrupts on GPT1 */
+ writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE);
+ /* Disable GP1 while we're reprogramming it. */
+ writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_DGPT1);
+ /*
+ * Set the periodic mode to a certain number of ticks per
+ * jiffy.
+ */
+ writel(TICKS_PER_JIFFY,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1TC);
+ /*
+ * Set continuous mode, so the timer keeps triggering
+ * interrupts.
+ */
+ writel(U300_TIMER_APP_SGPT1M_MODE_CONTINUOUS,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_SGPT1M);
+ /* Enable timer interrupts */
+ writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE);
+ /* Then enable the OS timer again */
+ writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT1);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ /* Just break; here? */
+ /*
+ * The actual event will be programmed by the next event hook,
+ * so we just set a dummy value somewhere at the end of the
+ * universe here.
+ */
+ /* Disable interrupts on GPT1 */
+ writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE);
+ /* Disable GP1 while we're reprogramming it. */
+ writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_DGPT1);
+ /*
+ * Expire far in the future, u300_set_next_event() will be
+ * called soon...
+ */
+ writel(0xFFFFFFFF, U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1TC);
+ /* We run one shot per tick here! */
+ writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_SGPT1M);
+ /* Enable interrupts for this timer */
+ writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE);
+ /* Enable timer */
+ writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT1);
+ break;
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ /* Disable interrupts on GP1 */
+ writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE);
+ /* Disable GP1 */
+ writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_DGPT1);
+ break;
+ case CLOCK_EVT_MODE_RESUME:
+ /* Ignore this call */
+ break;
+ }
+}
+
+/*
+ * The app timer in one shot mode obviously has to be reprogrammed
+ * in EXACTLY this sequence to work properly. Do NOT try to e.g. replace
+ * the interrupt disable + timer disable commands with a reset command,
+ * it will fail miserably. Apparently (and I found this the hard way)
+ * the timer is very sensitive to the instruction order, though you don't
+ * get that impression from the data sheet.
+ */
+static int u300_set_next_event(unsigned long cycles,
+ struct clock_event_device *evt)
+
+{
+ /* Disable interrupts on GPT1 */
+ writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE);
+ /* Disable GP1 while we're reprogramming it. */
+ writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_DGPT1);
+ /* Reset the General Purpose timer 1. */
+ writel(U300_TIMER_APP_RGPT1_TIMER_RESET,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_RGPT1);
+ /* IRQ in n * cycles */
+ writel(cycles, U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1TC);
+ /*
+ * We run one shot per tick here! (This is necessary to reconfigure,
+ * the timer will tilt if you don't!)
+ */
+ writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_SGPT1M);
+ /* Enable timer interrupts */
+ writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE);
+ /* Then enable the OS timer again */
+ writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT1);
+ return 0;
+}
+
+
+/* Use general purpose timer 1 as clock event */
+static struct clock_event_device clockevent_u300_1mhz = {
+ .name = "GPT1",
+ .rating = 300, /* Reasonably fast and accurate clock event */
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ /* 22 calculated using the algorithm in arch/mips/kernel/time.c */
+ .shift = 22,
+ .set_next_event = u300_set_next_event,
+ .set_mode = u300_set_mode,
+};
+
+/* Clock event timer interrupt handler */
+static irqreturn_t u300_timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = &clockevent_u300_1mhz;
+ /* ACK/Clear timer IRQ for the APP GPT1 Timer */
+ writel(U300_TIMER_APP_GPT1IA_IRQ_ACK,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IA);
+ evt->event_handler(evt);
+ return IRQ_HANDLED;
+}
+
+static struct irqaction u300_timer_irq = {
+ .name = "U300 Timer Tick",
+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+ .handler = u300_timer_interrupt,
+};
+
+/* Use general purpose timer 2 as clock source */
+static cycle_t u300_get_cycles(void)
+{
+ return (cycles_t) readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC);
+}
+
+static struct clocksource clocksource_u300_1mhz = {
+ .name = "GPT2",
+ .rating = 300, /* Reasonably fast and accurate clock source */
+ .read = u300_get_cycles,
+ .mask = CLOCKSOURCE_MASK(32), /* 32 bits */
+ /* 22 calculated using the algorithm in arch/mips/kernel/time.c */
+ .shift = 22,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+
+/*
+ * This sets up the system timers, clock source and clock event.
+ */
+static void __init u300_timer_init(void)
+{
+ u300_enable_timer_clock();
+ /*
+ * Disable the "OS" and "DD" timers - these are designed for Symbian!
+ * Example usage in cnh1601578 cpu subsystem pd_timer_app.c
+ */
+ writel(U300_TIMER_APP_CRC_CLOCK_REQUEST_ENABLE,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_CRC);
+ writel(U300_TIMER_APP_ROST_TIMER_RESET,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_ROST);
+ writel(U300_TIMER_APP_DOST_TIMER_DISABLE,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_DOST);
+ writel(U300_TIMER_APP_RDDT_TIMER_RESET,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_RDDT);
+ writel(U300_TIMER_APP_DDDT_TIMER_DISABLE,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_DDDT);
+
+ /* Reset the General Purpose timer 1. */
+ writel(U300_TIMER_APP_RGPT1_TIMER_RESET,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_RGPT1);
+
+ /* Set up the IRQ handler */
+ setup_irq(IRQ_U300_TIMER_APP_GP1, &u300_timer_irq);
+
+ /* Reset the General Purpose timer 2 */
+ writel(U300_TIMER_APP_RGPT2_TIMER_RESET,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_RGPT2);
+ /* Set this timer to run around forever */
+ writel(0xFFFFFFFFU, U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2TC);
+ /* Set continuous mode so it wraps around */
+ writel(U300_TIMER_APP_SGPT2M_MODE_CONTINUOUS,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_SGPT2M);
+ /* Disable timer interrupts */
+ writel(U300_TIMER_APP_GPT2IE_IRQ_DISABLE,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2IE);
+ /* Then enable the GP2 timer to use as a free running us counter */
+ writel(U300_TIMER_APP_EGPT2_TIMER_ENABLE,
+ U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT2);
+
+ /* This is a pure microsecond clock source */
+ clocksource_u300_1mhz.mult =
+ clocksource_khz2mult(1000, clocksource_u300_1mhz.shift);
+ if (clocksource_register(&clocksource_u300_1mhz))
+ printk(KERN_ERR "timer: failed to initialize clock "
+ "source %s\n", clocksource_u300_1mhz.name);
+
+ clockevent_u300_1mhz.mult =
+ div_sc(1000000, NSEC_PER_SEC, clockevent_u300_1mhz.shift);
+ /* 32bit counter, so 32bits delta is max */
+ clockevent_u300_1mhz.max_delta_ns =
+ clockevent_delta2ns(0xffffffff, &clockevent_u300_1mhz);
+ /* This timer is slow enough to set for 1 cycle == 1 MHz */
+ clockevent_u300_1mhz.min_delta_ns =
+ clockevent_delta2ns(1, &clockevent_u300_1mhz);
+ clockevent_u300_1mhz.cpumask = cpumask_of(0);
+ clockevents_register_device(&clockevent_u300_1mhz);
+ /*
+ * TODO: init and register the rest of the timers too, they can be
+ * used by hrtimers!
+ */
+}
+
+/*
+ * Very simple system timer that only register the clock event and
+ * clock source.
+ */
+struct sys_timer u300_timer = {
+ .init = u300_timer_init,
+};
diff --git a/arch/arm/mach-u300/u300.c b/arch/arm/mach-u300/u300.c
new file mode 100644
index 000000000000..d2a0b8847a18
--- /dev/null
+++ b/arch/arm/mach-u300/u300.c
@@ -0,0 +1,55 @@
+/*
+ *
+ * arch/arm/mach-u300/u300.c
+ *
+ *
+ * Copyright (C) 2006-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Platform machine definition.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+#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/platform_device.h>
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include <mach/memory.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static void __init u300_init_machine(void)
+{
+ u300_init_devices();
+}
+
+#ifdef CONFIG_MACH_U300_BS2X
+#define MACH_U300_STRING "Ericsson AB U300 S25/S26/B25/B26 Prototype Board"
+#endif
+
+#ifdef CONFIG_MACH_U300_BS330
+#define MACH_U300_STRING "Ericsson AB U330 S330/B330 Prototype Board"
+#endif
+
+#ifdef CONFIG_MACH_U300_BS335
+#define MACH_U300_STRING "Ericsson AB U335 S335/B335 Prototype Board"
+#endif
+
+#ifdef CONFIG_MACH_U300_BS365
+#define MACH_U300_STRING "Ericsson AB U365 S365/B365 Prototype Board"
+#endif
+
+MACHINE_START(U300, MACH_U300_STRING)
+ /* Maintainer: Linus Walleij <linus.walleij@stericsson.com> */
+ .phys_io = U300_AHB_PER_PHYS_BASE,
+ .io_pg_offst = ((U300_AHB_PER_VIRT_BASE) >> 18) & 0xfffc,
+ .boot_params = BOOT_PARAMS_OFFSET,
+ .map_io = u300_map_io,
+ .init_irq = u300_init_irq,
+ .timer = &u300_timer,
+ .init_machine = u300_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 565776680d8c..c39c788e2731 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -116,7 +116,7 @@ void __init versatile_init_irq(void)
{
unsigned int i;
- vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0);
+ vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0);
set_irq_chained_handler(IRQ_VICSOURCE31, sic_handle_irq);
@@ -948,7 +948,7 @@ static struct irqaction versatile_timer_irq = {
.handler = versatile_timer_interrupt,
};
-static cycle_t versatile_get_cycles(void)
+static cycle_t versatile_get_cycles(struct clocksource *cs)
{
return ~readl(TIMER3_VA_BASE + TIMER_VALUE);
}
diff --git a/arch/arm/mach-w90x900/include/mach/irqs.h b/arch/arm/mach-w90x900/include/mach/irqs.h
index 1c583f9cbcde..9d5cba3a509f 100644
--- a/arch/arm/mach-w90x900/include/mach/irqs.h
+++ b/arch/arm/mach-w90x900/include/mach/irqs.h
@@ -1,8 +1,7 @@
/*
* arch/arm/mach-w90x900/include/mach/irqs.h
*
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
+ * Copyright (c) 2008 Nuvoton technology corporation.
*
* Wan ZongShun <mcuos.com@gmail.com>
*
@@ -10,8 +9,7 @@
*
* 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.
*
*/
@@ -31,6 +29,11 @@
/* Main cpu interrupts */
#define IRQ_WDT W90X900_IRQ(1)
+#define IRQ_GROUP0 W90X900_IRQ(2)
+#define IRQ_GROUP1 W90X900_IRQ(3)
+#define IRQ_ACTL W90X900_IRQ(4)
+#define IRQ_LCD W90X900_IRQ(5)
+#define IRQ_RTC W90X900_IRQ(6)
#define IRQ_UART0 W90X900_IRQ(7)
#define IRQ_UART1 W90X900_IRQ(8)
#define IRQ_UART2 W90X900_IRQ(9)
@@ -39,7 +42,45 @@
#define IRQ_TIMER0 W90X900_IRQ(12)
#define IRQ_TIMER1 W90X900_IRQ(13)
#define IRQ_T_INT_GROUP W90X900_IRQ(14)
+#define IRQ_USBH W90X900_IRQ(15)
+#define IRQ_EMCTX W90X900_IRQ(16)
+#define IRQ_EMCRX W90X900_IRQ(17)
+#define IRQ_GDMAGROUP W90X900_IRQ(18)
+#define IRQ_DMAC W90X900_IRQ(19)
+#define IRQ_FMI W90X900_IRQ(20)
+#define IRQ_USBD W90X900_IRQ(21)
+#define IRQ_ATAPI W90X900_IRQ(22)
+#define IRQ_G2D W90X900_IRQ(23)
+#define IRQ_PCI W90X900_IRQ(24)
+#define IRQ_SCGROUP W90X900_IRQ(25)
+#define IRQ_I2CGROUP W90X900_IRQ(26)
+#define IRQ_SSP W90X900_IRQ(27)
+#define IRQ_PWM W90X900_IRQ(28)
+#define IRQ_KPI W90X900_IRQ(29)
+#define IRQ_P2SGROUP W90X900_IRQ(30)
#define IRQ_ADC W90X900_IRQ(31)
#define NR_IRQS (IRQ_ADC+1)
+/*for irq group*/
+
+#define IRQ_PS2_PORT0 0x10000000
+#define IRQ_PS2_PORT1 0x20000000
+#define IRQ_I2C_LINE0 0x04000000
+#define IRQ_I2C_LINE1 0x08000000
+#define IRQ_SC_CARD0 0x01000000
+#define IRQ_SC_CARD1 0x02000000
+#define IRQ_GDMA_CH0 0x00100000
+#define IRQ_GDMA_CH1 0x00200000
+#define IRQ_TIMER2 0x00010000
+#define IRQ_TIMER3 0x00020000
+#define IRQ_TIMER4 0x00040000
+#define IRQ_GROUP0_IRQ0 0x00000001
+#define IRQ_GROUP0_IRQ1 0x00000002
+#define IRQ_GROUP0_IRQ2 0x00000004
+#define IRQ_GROUP0_IRQ3 0x00000008
+#define IRQ_GROUP1_IRQ4 0x00000010
+#define IRQ_GROUP1_IRQ5 0x00000020
+#define IRQ_GROUP1_IRQ6 0x00000040
+#define IRQ_GROUP1_IRQ7 0x00000080
+
#endif /* __ASM_ARCH_IRQ_H */
diff --git a/arch/arm/mach-w90x900/include/mach/map.h b/arch/arm/mach-w90x900/include/mach/map.h
index 79320ebe614b..1a2095304117 100644
--- a/arch/arm/mach-w90x900/include/mach/map.h
+++ b/arch/arm/mach-w90x900/include/mach/map.h
@@ -1,8 +1,7 @@
/*
* arch/arm/mach-w90x900/include/mach/map.h
*
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
+ * Copyright (c) 2008 Nuvoton technology corporation.
*
* Wan ZongShun <mcuos.com@gmail.com>
*
@@ -10,8 +9,7 @@
*
* 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.
*
*/
@@ -34,7 +32,6 @@
* interrupt controller is the first thing we put in, to make
* the assembly code for the irq detection easier
*/
-
#define W90X900_VA_IRQ W90X900_ADDR(0x00000000)
#define W90X900_PA_IRQ (0xB8002000)
#define W90X900_SZ_IRQ SZ_4K
@@ -44,33 +41,117 @@
#define W90X900_SZ_GCR SZ_4K
/* Clock and Power management */
-
#define W90X900_VA_CLKPWR (W90X900_VA_GCR+0x200)
#define W90X900_PA_CLKPWR (0xB0000200)
#define W90X900_SZ_CLKPWR SZ_4K
/* EBI management */
-
#define W90X900_VA_EBI W90X900_ADDR(0x00001000)
#define W90X900_PA_EBI (0xB0001000)
#define W90X900_SZ_EBI SZ_4K
/* UARTs */
-
#define W90X900_VA_UART W90X900_ADDR(0x08000000)
#define W90X900_PA_UART (0xB8000000)
#define W90X900_SZ_UART SZ_4K
/* Timers */
-
#define W90X900_VA_TIMER W90X900_ADDR(0x08001000)
#define W90X900_PA_TIMER (0xB8001000)
#define W90X900_SZ_TIMER SZ_4K
/* GPIO ports */
-
#define W90X900_VA_GPIO W90X900_ADDR(0x08003000)
#define W90X900_PA_GPIO (0xB8003000)
#define W90X900_SZ_GPIO SZ_4K
+/* GDMA control */
+#define W90X900_VA_GDMA W90X900_ADDR(0x00004000)
+#define W90X900_PA_GDMA (0xB0004000)
+#define W90X900_SZ_GDMA SZ_4K
+
+/* USB host controller*/
+#define W90X900_VA_USBEHCIHOST W90X900_ADDR(0x00005000)
+#define W90X900_PA_USBEHCIHOST (0xB0005000)
+#define W90X900_SZ_USBEHCIHOST SZ_4K
+
+#define W90X900_VA_USBOHCIHOST W90X900_ADDR(0x00007000)
+#define W90X900_PA_USBOHCIHOST (0xB0007000)
+#define W90X900_SZ_USBOHCIHOST SZ_4K
+
+/* I2C hardware controller */
+#define W90X900_VA_I2C W90X900_ADDR(0x08006000)
+#define W90X900_PA_I2C (0xB8006000)
+#define W90X900_SZ_I2C SZ_4K
+
+/* Keypad Interface*/
+#define W90X900_VA_KPI W90X900_ADDR(0x08008000)
+#define W90X900_PA_KPI (0xB8008000)
+#define W90X900_SZ_KPI SZ_4K
+
+/* Smart card host*/
+#define W90X900_VA_SC W90X900_ADDR(0x08005000)
+#define W90X900_PA_SC (0xB8005000)
+#define W90X900_SZ_SC SZ_4K
+
+/* LCD controller*/
+#define W90X900_VA_LCD W90X900_ADDR(0x00008000)
+#define W90X900_PA_LCD (0xB0008000)
+#define W90X900_SZ_LCD SZ_4K
+
+/* 2D controller*/
+#define W90X900_VA_GE W90X900_ADDR(0x0000B000)
+#define W90X900_PA_GE (0xB000B000)
+#define W90X900_SZ_GE SZ_4K
+
+/* ATAPI */
+#define W90X900_VA_ATAPI W90X900_ADDR(0x0000A000)
+#define W90X900_PA_ATAPI (0xB000A000)
+#define W90X900_SZ_ATAPI SZ_4K
+
+/* ADC */
+#define W90X900_VA_ADC W90X900_ADDR(0x0800A000)
+#define W90X900_PA_ADC (0xB800A000)
+#define W90X900_SZ_ADC SZ_4K
+
+/* PS2 Interface*/
+#define W90X900_VA_PS2 W90X900_ADDR(0x08009000)
+#define W90X900_PA_PS2 (0xB8009000)
+#define W90X900_SZ_PS2 SZ_4K
+
+/* RTC */
+#define W90X900_VA_RTC W90X900_ADDR(0x08004000)
+#define W90X900_PA_RTC (0xB8004000)
+#define W90X900_SZ_RTC SZ_4K
+
+/* Pulse Width Modulation(PWM) Registers */
+#define W90X900_VA_PWM W90X900_ADDR(0x08007000)
+#define W90X900_PA_PWM (0xB8007000)
+#define W90X900_SZ_PWM SZ_4K
+
+/* Audio Controller controller */
+#define W90X900_VA_ACTL W90X900_ADDR(0x00009000)
+#define W90X900_PA_ACTL (0xB0009000)
+#define W90X900_SZ_ACTL SZ_4K
+
+/* DMA controller */
+#define W90X900_VA_DMA W90X900_ADDR(0x0000c000)
+#define W90X900_PA_DMA (0xB000c000)
+#define W90X900_SZ_DMA SZ_4K
+
+/* FMI controller */
+#define W90X900_VA_FMI W90X900_ADDR(0x0000d000)
+#define W90X900_PA_FMI (0xB000d000)
+#define W90X900_SZ_FMI SZ_4K
+
+/* USB Device port */
+#define W90X900_VA_USBDEV W90X900_ADDR(0x00006000)
+#define W90X900_PA_USBDEV (0xB0006000)
+#define W90X900_SZ_USBDEV SZ_4K
+
+/* External MAC control*/
+#define W90X900_VA_EMC W90X900_ADDR(0x00003000)
+#define W90X900_PA_EMC (0xB0003000)
+#define W90X900_SZ_EMC SZ_4K
+
#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-w90x900/include/mach/regs-clock.h b/arch/arm/mach-w90x900/include/mach/regs-clock.h
new file mode 100644
index 000000000000..f10b6a8dc069
--- /dev/null
+++ b/arch/arm/mach-w90x900/include/mach/regs-clock.h
@@ -0,0 +1,31 @@
+/*
+ * arch/arm/mach-w90x900/include/mach/regs-clock.h
+ *
+ * Copyright (c) 2008 Nuvoton technology corporation.
+ *
+ * Wan ZongShun <mcuos.com@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation;version 2 of the License.
+ *
+ */
+
+#ifndef __ASM_ARCH_REGS_CLOCK_H
+#define __ASM_ARCH_REGS_CLOCK_H
+
+/* Clock Control Registers */
+#define CLK_BA W90X900_VA_CLKPWR
+#define REG_CLKEN (CLK_BA + 0x00)
+#define REG_CLKSEL (CLK_BA + 0x04)
+#define REG_CLKDIV (CLK_BA + 0x08)
+#define REG_PLLCON0 (CLK_BA + 0x0C)
+#define REG_PLLCON1 (CLK_BA + 0x10)
+#define REG_PMCON (CLK_BA + 0x14)
+#define REG_IRQWAKECON (CLK_BA + 0x18)
+#define REG_IRQWAKEFLAG (CLK_BA + 0x1C)
+#define REG_IPSRST (CLK_BA + 0x20)
+#define REG_CLKEN1 (CLK_BA + 0x24)
+#define REG_CLKDIV1 (CLK_BA + 0x28)
+
+#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/mach-w90x900/include/mach/regs-usb.h b/arch/arm/mach-w90x900/include/mach/regs-usb.h
new file mode 100644
index 000000000000..ab74b0c2480b
--- /dev/null
+++ b/arch/arm/mach-w90x900/include/mach/regs-usb.h
@@ -0,0 +1,35 @@
+/*
+ * arch/arm/mach-w90x900/include/mach/regs-usb.h
+ *
+ * Copyright (c) 2008 Nuvoton technology corporation.
+ *
+ * Wan ZongShun <mcuos.com@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation;version 2 of the License.
+ *
+ */
+
+#ifndef __ASM_ARCH_REGS_USB_H
+#define __ASM_ARCH_REGS_USB_H
+
+/* usb Control Registers */
+#define USBH_BA W90X900_VA_USBEHCIHOST
+#define USBD_BA W90X900_VA_USBDEV
+#define USBO_BA W90X900_VA_USBOHCIHOST
+
+/* USB Host Control Registers */
+#define REG_UPSCR0 (USBH_BA+0x064)
+#define REG_UPSCR1 (USBH_BA+0x068)
+#define REG_USBPCR0 (USBH_BA+0x0C4)
+#define REG_USBPCR1 (USBH_BA+0x0C8)
+
+/* USBH OHCI Control Registers */
+#define REG_OpModEn (USBO_BA+0x204)
+/*This bit controls the polarity of over
+*current flag from external power IC.
+*/
+#define OCALow 0x08
+
+#endif /* __ASM_ARCH_REGS_USB_H */
diff --git a/arch/arm/mach-w90x900/mach-w90p910evb.c b/arch/arm/mach-w90x900/mach-w90p910evb.c
index 726ff6798a56..26de71f73f47 100644
--- a/arch/arm/mach-w90x900/mach-w90p910evb.c
+++ b/arch/arm/mach-w90x900/mach-w90p910evb.c
@@ -3,15 +3,13 @@
*
* Based on mach-s3c2410/mach-smdk2410.c by Jonas Dietsche
*
- * Copyright (C) 2008 Nuvoton technology corporation
- * All rights reserved.
+ * Copyright (C) 2008 Nuvoton technology corporation.
*
* Wan ZongShun <mcuos.com@gmail.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.
+ * published by the Free Software Foundation;version 2 of the License.
*
*/
@@ -80,6 +78,86 @@ static struct platform_device w90p910_flash_device = {
.num_resources = ARRAY_SIZE(w90p910_flash_resources),
};
+/* USB EHCI Host Controller */
+
+static struct resource w90x900_usb_ehci_resource[] = {
+ [0] = {
+ .start = W90X900_PA_USBEHCIHOST,
+ .end = W90X900_PA_USBEHCIHOST + W90X900_SZ_USBEHCIHOST - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_USBH,
+ .end = IRQ_USBH,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static u64 w90x900_device_usb_ehci_dmamask = 0xffffffffUL;
+
+struct platform_device w90x900_device_usb_ehci = {
+ .name = "w90x900-ehci",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(w90x900_usb_ehci_resource),
+ .resource = w90x900_usb_ehci_resource,
+ .dev = {
+ .dma_mask = &w90x900_device_usb_ehci_dmamask,
+ .coherent_dma_mask = 0xffffffffUL
+ }
+};
+EXPORT_SYMBOL(w90x900_device_usb_ehci);
+
+/* USB OHCI Host Controller */
+
+static struct resource w90x900_usb_ohci_resource[] = {
+ [0] = {
+ .start = W90X900_PA_USBOHCIHOST,
+ .end = W90X900_PA_USBOHCIHOST + W90X900_SZ_USBOHCIHOST - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_USBH,
+ .end = IRQ_USBH,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static u64 w90x900_device_usb_ohci_dmamask = 0xffffffffUL;
+struct platform_device w90x900_device_usb_ohci = {
+ .name = "w90x900-ohci",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(w90x900_usb_ohci_resource),
+ .resource = w90x900_usb_ohci_resource,
+ .dev = {
+ .dma_mask = &w90x900_device_usb_ohci_dmamask,
+ .coherent_dma_mask = 0xffffffffUL
+ }
+};
+EXPORT_SYMBOL(w90x900_device_usb_ohci);
+
+/*TouchScreen controller*/
+
+static struct resource w90x900_ts_resource[] = {
+ [0] = {
+ .start = W90X900_PA_ADC,
+ .end = W90X900_PA_ADC + W90X900_SZ_ADC-1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_ADC,
+ .end = IRQ_ADC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device w90x900_device_ts = {
+ .name = "w90x900-ts",
+ .id = -1,
+ .resource = w90x900_ts_resource,
+ .num_resources = ARRAY_SIZE(w90x900_ts_resource),
+};
+EXPORT_SYMBOL(w90x900_device_ts);
+
static struct map_desc w90p910_iodesc[] __initdata = {
};
@@ -88,6 +166,9 @@ static struct map_desc w90p910_iodesc[] __initdata = {
static struct platform_device *w90p910evb_dev[] __initdata = {
&w90p910_serial_device,
&w90p910_flash_device,
+ &w90x900_device_usb_ehci,
+ &w90x900_device_usb_ohci,
+ &w90x900_device_ts,
};
static void __init w90p910evb_map_io(void)
diff --git a/arch/arm/mach-w90x900/w90p910.c b/arch/arm/mach-w90x900/w90p910.c
index 2bcbaa681b99..d2e4a16c9e00 100644
--- a/arch/arm/mach-w90x900/w90p910.c
+++ b/arch/arm/mach-w90x900/w90p910.c
@@ -3,8 +3,7 @@
*
* Based on linux/arch/arm/plat-s3c24xx/s3c244x.c by Ben Dooks
*
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
+ * Copyright (c) 2008 Nuvoton technology corporation.
*
* Wan ZongShun <mcuos.com@gmail.com>
*
@@ -12,8 +11,7 @@
*
* 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.
*
*/
@@ -45,6 +43,9 @@ static struct map_desc w90p910_iodesc[] __initdata = {
IODESC_ENT(UART),
IODESC_ENT(TIMER),
IODESC_ENT(EBI),
+ IODESC_ENT(USBEHCIHOST),
+ IODESC_ENT(USBOHCIHOST),
+ IODESC_ENT(ADC),
/*IODESC_ENT(LCD),*/
};
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S
index 2c6c2a7c05a0..8f5c13f4c936 100644
--- a/arch/arm/mm/cache-v6.S
+++ b/arch/arm/mm/cache-v6.S
@@ -20,6 +20,31 @@
#define D_CACHE_LINE_SIZE 32
#define BTB_FLUSH_SIZE 8
+#ifdef CONFIG_ARM_ERRATA_411920
+/*
+ * Invalidate the entire I cache (this code is a workaround for the ARM1136
+ * erratum 411920 - Invalidate Instruction Cache operation can fail. This
+ * erratum is present in 1136, 1156 and 1176. It does not affect the MPCore.
+ *
+ * Registers:
+ * r0 - set to 0
+ * r1 - corrupted
+ */
+ENTRY(v6_icache_inval_all)
+ mov r0, #0
+ mrs r1, cpsr
+ cpsid ifa @ disable interrupts
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache
+ msr cpsr_cx, r1 @ restore interrupts
+ .rept 11 @ ARM Ltd recommends at least
+ nop @ 11 NOPs
+ .endr
+ mov pc, lr
+#endif
+
/*
* v6_flush_cache_all()
*
@@ -31,8 +56,12 @@ ENTRY(v6_flush_kern_cache_all)
mov r0, #0
#ifdef HARVARD_CACHE
mcr p15, 0, r0, c7, c14, 0 @ D cache clean+invalidate
+#ifndef CONFIG_ARM_ERRATA_411920
mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
#else
+ b v6_icache_inval_all
+#endif
+#else
mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate
#endif
mov pc, lr
@@ -103,8 +132,12 @@ ENTRY(v6_coherent_user_range)
mov r0, #0
#ifdef HARVARD_CACHE
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
+#ifndef CONFIG_ARM_ERRATA_411920
mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
#else
+ b v6_icache_inval_all
+#endif
+#else
mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB
#endif
mov pc, lr
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index 4e283481cee1..c07222eb5ce0 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -18,6 +18,10 @@
#include "mm.h"
+#ifdef CONFIG_ARM_ERRATA_411920
+extern void v6_icache_inval_all(void);
+#endif
+
#ifdef CONFIG_CPU_CACHE_VIPT
#define ALIAS_FLUSH_START 0xffff4000
@@ -32,10 +36,15 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
asm( "mcrr p15, 0, %1, %0, c14\n"
" mcr p15, 0, %2, c7, c10, 4\n"
+#ifndef CONFIG_ARM_ERRATA_411920
" mcr p15, 0, %2, c7, c5, 0\n"
+#endif
:
: "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES), "r" (zero)
: "cc");
+#ifdef CONFIG_ARM_ERRATA_411920
+ v6_icache_inval_all();
+#endif
}
void flush_cache_mm(struct mm_struct *mm)
@@ -48,11 +57,16 @@ void flush_cache_mm(struct mm_struct *mm)
if (cache_is_vipt_aliasing()) {
asm( "mcr p15, 0, %0, c7, c14, 0\n"
+ " mcr p15, 0, %0, c7, c10, 4\n"
+#ifndef CONFIG_ARM_ERRATA_411920
" mcr p15, 0, %0, c7, c5, 0\n"
- " mcr p15, 0, %0, c7, c10, 4"
+#endif
:
: "r" (0)
: "cc");
+#ifdef CONFIG_ARM_ERRATA_411920
+ v6_icache_inval_all();
+#endif
}
}
@@ -67,11 +81,16 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned
if (cache_is_vipt_aliasing()) {
asm( "mcr p15, 0, %0, c7, c14, 0\n"
+ " mcr p15, 0, %0, c7, c10, 4\n"
+#ifndef CONFIG_ARM_ERRATA_411920
" mcr p15, 0, %0, c7, c5, 0\n"
- " mcr p15, 0, %0, c7, c10, 4"
+#endif
:
: "r" (0)
: "cc");
+#ifdef CONFIG_ARM_ERRATA_411920
+ v6_icache_inval_all();
+#endif
}
}
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index e6344ece00ce..39fca4e416e2 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -839,6 +839,20 @@ void __init reserve_node_zero(pg_data_t *pgdat)
reserve_bootmem_node(pgdat, 0xa0200000, 0x1000,
BOOTMEM_EXCLUSIVE);
+ /*
+ * U300 - This platform family can share physical memory
+ * between two ARM cpus, one running Linux and the other
+ * running another OS.
+ */
+ if (machine_is_u300()) {
+#ifdef CONFIG_MACH_U300_SINGLE_RAM
+#if ((CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1) == 1) && \
+ CONFIG_MACH_U300_2MB_ALIGNMENT_FIX
+ res_size = 0x00100000;
+#endif
+#endif
+ }
+
#ifdef CONFIG_SA1111
/*
* Because of the SA1111 DMA bug, we want to preserve our
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index f0cc599facb7..087e239704df 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -10,6 +10,7 @@
*
* This is the "shell" of the ARMv6 processor support.
*/
+#include <linux/init.h>
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <asm/asm-offsets.h>
@@ -132,7 +133,7 @@ cpu_v6_name:
.asciz "ARMv6-compatible processor"
.align
- .section ".text.init", #alloc, #execinstr
+ __INIT
/*
* __v6_setup
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index d1ebec42521d..3397f1e64d76 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -9,6 +9,7 @@
*
* This is the "shell" of the ARMv7 processor support.
*/
+#include <linux/init.h>
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <asm/asm-offsets.h>
@@ -95,6 +96,9 @@ ENTRY(cpu_v7_switch_mm)
mov r2, #0
ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id
orr r0, r0, #TTB_FLAGS
+#ifdef CONFIG_ARM_ERRATA_430973
+ mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
+#endif
mcr p15, 0, r2, c13, c0, 1 @ set reserved context ID
isb
1: mcr p15, 0, r0, c2, c0, 0 @ set TTB 0
@@ -153,7 +157,7 @@ cpu_v7_name:
.ascii "ARMv7 Processor"
.align
- .section ".text.init", #alloc, #execinstr
+ __INIT
/*
* __v7_setup
@@ -180,6 +184,22 @@ __v7_setup:
stmia r12, {r0-r5, r7, r9, r11, lr}
bl v7_flush_dcache_all
ldmia r12, {r0-r5, r7, r9, r11, lr}
+#ifdef CONFIG_ARM_ERRATA_430973
+ mrc p15, 0, r10, c1, c0, 1 @ read aux control register
+ orr r10, r10, #(1 << 6) @ set IBE to 1
+ mcr p15, 0, r10, c1, c0, 1 @ write aux control register
+#endif
+#ifdef CONFIG_ARM_ERRATA_458693
+ mrc p15, 0, r10, c1, c0, 1 @ read aux control register
+ orr r10, r10, #(1 << 5) @ set L1NEON to 1
+ orr r10, r10, #(1 << 9) @ set PLDNOP to 1
+ mcr p15, 0, r10, c1, c0, 1 @ write aux control register
+#endif
+#ifdef CONFIG_ARM_ERRATA_460075
+ mrc p15, 1, r10, c9, c0, 2 @ read L2 cache aux ctrl register
+ orr r10, r10, #(1 << 22) @ set the Write Allocate disable bit
+ mcr p15, 1, r10, c9, c0, 2 @ write the L2 cache aux ctrl register
+#endif
mov r10, #0
#ifdef HARVARD_CACHE
mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate
diff --git a/arch/arm/mm/tlb-v6.S b/arch/arm/mm/tlb-v6.S
index 20f84bbaa9bb..73d7d89b04c4 100644
--- a/arch/arm/mm/tlb-v6.S
+++ b/arch/arm/mm/tlb-v6.S
@@ -10,6 +10,7 @@
* ARM architecture version 6 TLB handling functions.
* These assume a split I/D TLB.
*/
+#include <linux/init.h>
#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/page.h>
@@ -87,7 +88,7 @@ ENTRY(v6wbi_flush_kern_tlb_range)
mcr p15, 0, r2, c7, c5, 4 @ prefetch flush
mov pc, lr
- .section ".text.init", #alloc, #execinstr
+ __INIT
.type v6wbi_tlb_fns, #object
ENTRY(v6wbi_tlb_fns)
diff --git a/arch/arm/mm/tlb-v7.S b/arch/arm/mm/tlb-v7.S
index 24ba5109f2e7..b637e7380ab7 100644
--- a/arch/arm/mm/tlb-v7.S
+++ b/arch/arm/mm/tlb-v7.S
@@ -11,6 +11,7 @@
* ARM architecture version 6 TLB handling functions.
* These assume a split I/D TLB.
*/
+#include <linux/init.h>
#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/page.h>
@@ -80,7 +81,7 @@ ENTRY(v7wbi_flush_kern_tlb_range)
mov pc, lr
ENDPROC(v7wbi_flush_kern_tlb_range)
- .section ".text.init", #alloc, #execinstr
+ __INIT
.type v7wbi_tlb_fns, #object
ENTRY(v7wbi_tlb_fns)
diff --git a/arch/arm/plat-mxc/dma-mx1-mx2.c b/arch/arm/plat-mxc/dma-mx1-mx2.c
index e364a5ed10f1..77646436c00e 100644
--- a/arch/arm/plat-mxc/dma-mx1-mx2.c
+++ b/arch/arm/plat-mxc/dma-mx1-mx2.c
@@ -693,12 +693,15 @@ int imx_dma_request(int channel, const char *name)
local_irq_restore(flags);
return -EBUSY;
}
+ memset(imxdma, 0, sizeof(imxdma));
+ imxdma->name = name;
+ local_irq_restore(flags); /* request_irq() can block */
#ifdef CONFIG_ARCH_MX2
ret = request_irq(MXC_INT_DMACH0 + channel, dma_irq_handler, 0, "DMA",
NULL);
if (ret) {
- local_irq_restore(flags);
+ imxdma->name = NULL;
printk(KERN_CRIT "Can't register IRQ %d for DMA channel %d\n",
MXC_INT_DMACH0 + channel, channel);
return ret;
@@ -708,13 +711,6 @@ int imx_dma_request(int channel, const char *name)
imxdma->watchdog.data = channel;
#endif
- imxdma->name = name;
- imxdma->irq_handler = NULL;
- imxdma->err_handler = NULL;
- imxdma->data = NULL;
- imxdma->sg = NULL;
-
- local_irq_restore(flags);
return ret;
}
EXPORT_SYMBOL(imx_dma_request);
@@ -737,10 +733,7 @@ void imx_dma_free(int channel)
local_irq_save(flags);
/* Disable interrupts */
- __raw_writel(__raw_readl(DMA_BASE + DMA_DIMR) | (1 << channel),
- DMA_BASE + DMA_DIMR);
- __raw_writel(__raw_readl(DMA_BASE + DMA_CCR(channel)) & ~CCR_CEN,
- DMA_BASE + DMA_CCR(channel));
+ imx_dma_disable(channel);
imxdma->name = NULL;
#ifdef CONFIG_ARCH_MX2
diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c
index c6483bad8a26..89e95798cc3b 100644
--- a/arch/arm/plat-mxc/gpio.c
+++ b/arch/arm/plat-mxc/gpio.c
@@ -124,7 +124,7 @@ static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)
irq_stat = __raw_readl(port->base + GPIO_ISR) &
__raw_readl(port->base + GPIO_IMR);
- BUG_ON(!irq_stat);
+
mxc_gpio_irq_handler(port, irq_stat);
}
#endif
diff --git a/arch/arm/plat-mxc/include/mach/board-mx27ads.h b/arch/arm/plat-mxc/include/mach/board-mx27ads.h
index 1cac9d1135cd..d42f4e6116f8 100644
--- a/arch/arm/plat-mxc/include/mach/board-mx27ads.h
+++ b/arch/arm/plat-mxc/include/mach/board-mx27ads.h
@@ -47,7 +47,7 @@
/*
* Base address of PBC controller, CS4
*/
-#define PBC_BASE_ADDRESS 0xEB000000
+#define PBC_BASE_ADDRESS 0xf4300000
#define PBC_REG_ADDR(offset) (void __force __iomem *) \
(PBC_BASE_ADDRESS + (offset))
diff --git a/arch/arm/plat-mxc/include/mach/imx-uart.h b/arch/arm/plat-mxc/include/mach/imx-uart.h
index 83fb72c4048a..599217b2e13f 100644
--- a/arch/arm/plat-mxc/include/mach/imx-uart.h
+++ b/arch/arm/plat-mxc/include/mach/imx-uart.h
@@ -27,6 +27,4 @@ struct imxuart_platform_data {
unsigned int flags;
};
-int __init imx_init_uart(int uart_no, struct imxuart_platform_data *pdata);
-
#endif
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx3.h b/arch/arm/plat-mxc/include/mach/iomux-mx3.h
index ab838cfe94f9..57e927a1fd3a 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx3.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx3.h
@@ -518,6 +518,8 @@ enum iomux_pins {
*/
#define MX31_PIN_CSPI3_MOSI__RXD3 IOMUX_MODE(MX31_PIN_CSPI3_MOSI, IOMUX_CONFIG_ALT1)
#define MX31_PIN_CSPI3_MISO__TXD3 IOMUX_MODE(MX31_PIN_CSPI3_MISO, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI3_SCLK__RTS3 IOMUX_MODE(MX31_PIN_CSPI3_SCLK, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI3_SPI_RDY__CTS3 IOMUX_MODE(MX31_PIN_CSPI3_SPI_RDY, IOMUX_CONFIG_ALT1)
#define MX31_PIN_CTS1__CTS1 IOMUX_MODE(MX31_PIN_CTS1, IOMUX_CONFIG_FUNC)
#define MX31_PIN_RTS1__RTS1 IOMUX_MODE(MX31_PIN_RTS1, IOMUX_CONFIG_FUNC)
#define MX31_PIN_TXD1__TXD1 IOMUX_MODE(MX31_PIN_TXD1, IOMUX_CONFIG_FUNC)
@@ -558,6 +560,16 @@ enum iomux_pins {
#define MX31_PIN_SD1_DATA0__SD1_DATA0 IOMUX_MODE(MX31_PIN_SD1_DATA0, IOMUX_CONFIG_FUNC)
#define MX31_PIN_SD1_CLK__SD1_CLK IOMUX_MODE(MX31_PIN_SD1_CLK, IOMUX_CONFIG_FUNC)
#define MX31_PIN_SD1_CMD__SD1_CMD IOMUX_MODE(MX31_PIN_SD1_CMD, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_ATA_CS0__GPIO3_26 IOMUX_MODE(MX31_PIN_ATA_CS0, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_ATA_CS1__GPIO3_27 IOMUX_MODE(MX31_PIN_ATA_CS1, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_PC_PWRON__SD2_DATA3 IOMUX_MODE(MX31_PIN_PC_PWRON, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_PC_VS1__SD2_DATA2 IOMUX_MODE(MX31_PIN_PC_VS1, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_PC_READY__SD2_DATA1 IOMUX_MODE(MX31_PIN_PC_READY, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_PC_WAIT_B__SD2_DATA0 IOMUX_MODE(MX31_PIN_PC_WAIT_B, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_PC_CD2_B__SD2_CLK IOMUX_MODE(MX31_PIN_PC_CD2_B, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_PC_CD1_B__SD2_CMD IOMUX_MODE(MX31_PIN_PC_CD1_B, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_ATA_DIOR__GPIO3_28 IOMUX_MODE(MX31_PIN_ATA_DIOR, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_ATA_DIOW__GPIO3_29 IOMUX_MODE(MX31_PIN_ATA_DIOW, IOMUX_CONFIG_GPIO)
#define MX31_PIN_LD0__LD0 IOMUX_MODE(MX31_PIN_LD0, IOMUX_CONFIG_FUNC)
#define MX31_PIN_LD1__LD1 IOMUX_MODE(MX31_PIN_LD1, IOMUX_CONFIG_FUNC)
#define MX31_PIN_LD2__LD2 IOMUX_MODE(MX31_PIN_LD2, IOMUX_CONFIG_FUNC)
@@ -585,6 +597,42 @@ enum iomux_pins {
#define MX31_PIN_D3_SPL__D3_SPL IOMUX_MODE(MX31_PIN_D3_SPL, IOMUX_CONFIG_FUNC)
#define MX31_PIN_D3_CLS__D3_CLS IOMUX_MODE(MX31_PIN_D3_CLS, IOMUX_CONFIG_FUNC)
#define MX31_PIN_LCS0__GPI03_23 IOMUX_MODE(MX31_PIN_LCS0, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_GPIO1_1__GPIO IOMUX_MODE(MX31_PIN_GPIO1_1, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_I2C_CLK__SCL IOMUX_MODE(MX31_PIN_I2C_CLK, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_I2C_DAT__SDA IOMUX_MODE(MX31_PIN_I2C_DAT, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_DCD_DTE1__I2C2_SDA IOMUX_MODE(MX31_PIN_DCD_DTE1, IOMUX_CONFIG_ALT2)
+#define MX31_PIN_RI_DTE1__I2C2_SCL IOMUX_MODE(MX31_PIN_RI_DTE1, IOMUX_CONFIG_ALT2)
+#define MX31_PIN_CSI_D4__CSI_D4 IOMUX_MODE(MX31_PIN_CSI_D4, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D5__CSI_D5 IOMUX_MODE(MX31_PIN_CSI_D5, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D6__CSI_D6 IOMUX_MODE(MX31_PIN_CSI_D6, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D7__CSI_D7 IOMUX_MODE(MX31_PIN_CSI_D7, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D8__CSI_D8 IOMUX_MODE(MX31_PIN_CSI_D8, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D9__CSI_D9 IOMUX_MODE(MX31_PIN_CSI_D9, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D10__CSI_D10 IOMUX_MODE(MX31_PIN_CSI_D10, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D11__CSI_D11 IOMUX_MODE(MX31_PIN_CSI_D11, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D12__CSI_D12 IOMUX_MODE(MX31_PIN_CSI_D12, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D13__CSI_D13 IOMUX_MODE(MX31_PIN_CSI_D13, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D14__CSI_D14 IOMUX_MODE(MX31_PIN_CSI_D14, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D15__CSI_D15 IOMUX_MODE(MX31_PIN_CSI_D15, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_HSYNC__CSI_HSYNC IOMUX_MODE(MX31_PIN_CSI_HSYNC, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_MCLK__CSI_MCLK IOMUX_MODE(MX31_PIN_CSI_MCLK, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_PIXCLK__CSI_PIXCLK IOMUX_MODE(MX31_PIN_CSI_PIXCLK, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_VSYNC__CSI_VSYNC IOMUX_MODE(MX31_PIN_CSI_VSYNC, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_GPIO3_0__GPIO3_0 IOMUX_MODE(MX31_PIN_GPIO3_0, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_GPIO3_1__GPIO3_1 IOMUX_MODE(MX31_PIN_GPIO3_1, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_TXD2__GPIO1_28 IOMUX_MODE(MX31_PIN_TXD2, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_USBOTG_DATA0__USBOTG_DATA0 IOMUX_MODE(MX31_PIN_USBOTG_DATA0, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DATA1__USBOTG_DATA1 IOMUX_MODE(MX31_PIN_USBOTG_DATA1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DATA2__USBOTG_DATA2 IOMUX_MODE(MX31_PIN_USBOTG_DATA2, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DATA3__USBOTG_DATA3 IOMUX_MODE(MX31_PIN_USBOTG_DATA3, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DATA4__USBOTG_DATA4 IOMUX_MODE(MX31_PIN_USBOTG_DATA4, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DATA5__USBOTG_DATA5 IOMUX_MODE(MX31_PIN_USBOTG_DATA5, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DATA6__USBOTG_DATA6 IOMUX_MODE(MX31_PIN_USBOTG_DATA6, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DATA7__USBOTG_DATA7 IOMUX_MODE(MX31_PIN_USBOTG_DATA7, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_CLK__USBOTG_CLK IOMUX_MODE(MX31_PIN_USBOTG_CLK, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DIR__USBOTG_DIR IOMUX_MODE(MX31_PIN_USBOTG_DIR, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_NXT__USBOTG_NXT IOMUX_MODE(MX31_PIN_USBOTG_NXT, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_STP__USBOTG_STP IOMUX_MODE(MX31_PIN_USBOTG_STP, IOMUX_CONFIG_FUNC)
/*XXX: The SS0, SS1, SS2, SS3 lines of spi3 are multiplexed by cspi2_ss0, cspi2_ss1, cspi1_ss0
* cspi1_ss1*/
diff --git a/arch/arm/plat-mxc/include/mach/irqs.h b/arch/arm/plat-mxc/include/mach/irqs.h
index c02b8fc2d821..518a36504b88 100644
--- a/arch/arm/plat-mxc/include/mach/irqs.h
+++ b/arch/arm/plat-mxc/include/mach/irqs.h
@@ -45,7 +45,7 @@
#define NR_IRQS (MXC_IPU_IRQ_START + MX3_IPU_IRQS)
-extern void imx_irq_set_priority(unsigned char irq, unsigned char prio);
+extern int imx_irq_set_priority(unsigned char irq, unsigned char prio);
/* all normal IRQs can be FIQs */
#define FIQ_START 0
diff --git a/arch/arm/plat-mxc/include/mach/mx21.h b/arch/arm/plat-mxc/include/mach/mx21.h
index e8c4cf56c24e..8b070a041a99 100644
--- a/arch/arm/plat-mxc/include/mach/mx21.h
+++ b/arch/arm/plat-mxc/include/mach/mx21.h
@@ -54,9 +54,6 @@
#define IRAM_BASE_ADDR 0xFFFFE800 /* internal ram */
-/* this CPU supports up to 192 GPIOs (don't forget the baseboard!) */
-#define ARCH_NR_GPIOS (6*32 + 16)
-
/* fixed interrupt numbers */
#define MXC_INT_USBCTRL 58
#define MXC_INT_USBCTRL 58
diff --git a/arch/arm/plat-mxc/irq.c b/arch/arm/plat-mxc/irq.c
index 6e7578a3514b..0fb68a531f55 100644
--- a/arch/arm/plat-mxc/irq.c
+++ b/arch/arm/plat-mxc/irq.c
@@ -50,23 +50,27 @@
#define IIM_PROD_REV_SH 3
#define IIM_PROD_REV_LEN 5
-#ifdef CONFIG_MXC_IRQ_PRIOR
-void imx_irq_set_priority(unsigned char irq, unsigned char prio)
+int imx_irq_set_priority(unsigned char irq, unsigned char prio)
{
+#ifdef CONFIG_MXC_IRQ_PRIOR
unsigned int temp;
unsigned int mask = 0x0F << irq % 8 * 4;
- if (irq > 63)
- return;
+ if (irq >= MXC_INTERNAL_IRQS)
+ return -EINVAL;;
temp = __raw_readl(AVIC_NIPRIORITY(irq / 8));
temp &= ~mask;
temp |= prio & mask;
__raw_writel(temp, AVIC_NIPRIORITY(irq / 8));
+
+ return 0;
+#else
+ return -ENOSYS;
+#endif
}
EXPORT_SYMBOL(imx_irq_set_priority);
-#endif
#ifdef CONFIG_FIQ
int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
diff --git a/arch/arm/plat-mxc/time.c b/arch/arm/plat-mxc/time.c
index ef1b3cd85bd3..dab3357196fb 100644
--- a/arch/arm/plat-mxc/time.c
+++ b/arch/arm/plat-mxc/time.c
@@ -36,7 +36,7 @@ static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
/* clock source */
-static cycle_t mxc_get_cycles(void)
+static cycle_t mxc_get_cycles(struct clocksource *cs)
{
return __raw_readl(TIMER_BASE + MXC_TCN);
}
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 2e0614552ac8..29efc279287a 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -239,6 +239,13 @@ void recalculate_root_clocks(void)
}
}
+/**
+ * clk_init_one - initialize any fields in the struct clk before clk init
+ * @clk: struct clk * to initialize
+ *
+ * Initialize any struct clk fields needed before normal clk initialization
+ * can run. No return value.
+ */
void clk_init_one(struct clk *clk)
{
INIT_LIST_HEAD(&clk->children);
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
index d1797147732f..433021f3d7cc 100644
--- a/arch/arm/plat-omap/common.c
+++ b/arch/arm/plat-omap/common.c
@@ -185,7 +185,7 @@ console_initcall(omap_add_serial_console);
#include <linux/clocksource.h>
-static cycle_t omap_32k_read(void)
+static cycle_t omap_32k_read(struct clocksource *cs)
{
return omap_readl(TIMER_32K_SYNCHRONIZED);
}
@@ -207,7 +207,7 @@ unsigned long long sched_clock(void)
{
unsigned long long ret;
- ret = (unsigned long long)omap_32k_read();
+ ret = (unsigned long long)omap_32k_read(&clocksource_32k);
ret = (ret * clocksource_32k.mult_orig) >> clocksource_32k.shift;
return ret;
}
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 21cc0142b97a..7fc8c045ad5d 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -760,19 +760,12 @@ void omap_free_dma(int lch)
{
unsigned long flags;
- spin_lock_irqsave(&dma_chan_lock, flags);
if (dma_chan[lch].dev_id == -1) {
pr_err("omap_dma: trying to free unallocated DMA channel %d\n",
lch);
- spin_unlock_irqrestore(&dma_chan_lock, flags);
return;
}
- dma_chan[lch].dev_id = -1;
- dma_chan[lch].next_lch = -1;
- dma_chan[lch].callback = NULL;
- spin_unlock_irqrestore(&dma_chan_lock, flags);
-
if (cpu_class_is_omap1()) {
/* Disable all DMA interrupts for the channel. */
dma_write(0, CICR(lch));
@@ -798,6 +791,12 @@ void omap_free_dma(int lch)
dma_write(0, CCR(lch));
omap_clear_dma(lch);
}
+
+ spin_lock_irqsave(&dma_chan_lock, flags);
+ dma_chan[lch].dev_id = -1;
+ dma_chan[lch].next_lch = -1;
+ dma_chan[lch].callback = NULL;
+ spin_unlock_irqrestore(&dma_chan_lock, flags);
}
EXPORT_SYMBOL(omap_free_dma);
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index bfd47570cc91..55bb99631292 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -238,7 +238,7 @@ static struct omap_dm_timer omap3_dm_timers[] = {
{ .phys_base = 0x49040000, .irq = INT_24XX_GPTIMER9 },
{ .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
{ .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
- { .phys_base = 0x48304000, .irq = INT_24XX_GPTIMER12 },
+ { .phys_base = 0x48304000, .irq = INT_34XX_GPT12_IRQ },
};
static const char *omap3_dm_source_names[] __initdata = {
@@ -321,11 +321,9 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer)
l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */
/*
- * Enable wake-up only for GPT1 on OMAP2 CPUs.
- * FIXME: All timers should have wake-up enabled and clear
- * PRCM status.
+ * Enable wake-up on OMAP2 CPUs.
*/
- if (cpu_class_is_omap2() && (timer == &dm_timers[0]))
+ if (cpu_class_is_omap2())
l |= 1 << 2;
omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
@@ -511,7 +509,7 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
#ifdef CONFIG_ARCH_OMAP1
-void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
+int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
{
int n = (timer - dm_timers) << 1;
u32 l;
@@ -519,23 +517,31 @@ void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
l |= source << n;
omap_writel(l, MOD_CONF_CTRL_1);
+
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
#else
-void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
+int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
{
+ int ret = -EINVAL;
+
if (source < 0 || source >= 3)
- return;
+ return -EINVAL;
clk_disable(timer->fclk);
- clk_set_parent(timer->fclk, dm_source_clocks[source]);
+ ret = clk_set_parent(timer->fclk, dm_source_clocks[source]);
clk_enable(timer->fclk);
- /* When the functional clock disappears, too quick writes seem to
- * cause an abort. */
+ /*
+ * When the functional clock disappears, too quick writes seem
+ * to cause an abort. XXX Is this still necessary?
+ */
__delay(150000);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index d3fa41e3d8c5..17d7afe42b83 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -758,8 +758,12 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
/* Workaround for clearing DSP GPIO interrupts to allow retention */
#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+ reg = bank->base + OMAP24XX_GPIO_IRQSTATUS2;
if (cpu_is_omap24xx() || cpu_is_omap34xx())
- __raw_writel(gpio_mask, bank->base + OMAP24XX_GPIO_IRQSTATUS2);
+ __raw_writel(gpio_mask, reg);
+
+ /* Flush posted write for the irq status to avoid spurious interrupts */
+ __raw_readl(reg);
#endif
}
@@ -921,13 +925,10 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
case METHOD_MPUIO:
case METHOD_GPIO_1610:
spin_lock_irqsave(&bank->lock, flags);
- if (enable) {
+ if (enable)
bank->suspend_wakeup |= (1 << gpio);
- enable_irq_wake(bank->irq);
- } else {
- disable_irq_wake(bank->irq);
+ else
bank->suspend_wakeup &= ~(1 << gpio);
- }
spin_unlock_irqrestore(&bank->lock, flags);
return 0;
#endif
@@ -940,13 +941,10 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
return -EINVAL;
}
spin_lock_irqsave(&bank->lock, flags);
- if (enable) {
+ if (enable)
bank->suspend_wakeup |= (1 << gpio);
- enable_irq_wake(bank->irq);
- } else {
- disable_irq_wake(bank->irq);
+ else
bank->suspend_wakeup &= ~(1 << gpio);
- }
spin_unlock_irqrestore(&bank->lock, flags);
return 0;
#endif
diff --git a/arch/arm/plat-omap/include/mach/dmtimer.h b/arch/arm/plat-omap/include/mach/dmtimer.h
index 6dc703138210..20f1054c0a80 100644
--- a/arch/arm/plat-omap/include/mach/dmtimer.h
+++ b/arch/arm/plat-omap/include/mach/dmtimer.h
@@ -64,7 +64,7 @@ void omap_dm_timer_trigger(struct omap_dm_timer *timer);
void omap_dm_timer_start(struct omap_dm_timer *timer);
void omap_dm_timer_stop(struct omap_dm_timer *timer);
-void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source);
+int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source);
void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value);
void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value);
void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match);
diff --git a/arch/arm/plat-omap/include/mach/eac.h b/arch/arm/plat-omap/include/mach/eac.h
deleted file mode 100644
index 9e62cf030270..000000000000
--- a/arch/arm/plat-omap/include/mach/eac.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach2/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 <mach/io.h>
-#include <mach/hardware.h>
-#include <asm/irq.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/arch/arm/plat-omap/include/mach/gpioexpander.h b/arch/arm/plat-omap/include/mach/gpioexpander.h
deleted file mode 100644
index 90444a0d6b1a..000000000000
--- a/arch/arm/plat-omap/include/mach/gpioexpander.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/gpioexpander.h
- *
- *
- * Copyright (C) 2004 Texas Instruments, Inc.
- *
- * 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_OMAP_GPIOEXPANDER_H
-#define __ASM_ARCH_OMAP_GPIOEXPANDER_H
-
-/* Function Prototypes for GPIO Expander functions */
-
-#ifdef CONFIG_GPIOEXPANDER_OMAP
-int read_gpio_expa(u8 *, int);
-int write_gpio_expa(u8 , int);
-#else
-static inline int read_gpio_expa(u8 *val, int addr)
-{
- return 0;
-}
-static inline int write_gpio_expa(u8 val, int addr)
-{
- return 0;
-}
-#endif
-
-#endif /* __ASM_ARCH_OMAP_GPIOEXPANDER_H */
diff --git a/arch/arm/plat-omap/include/mach/irda.h b/arch/arm/plat-omap/include/mach/irda.h
index 8372a00d8e0b..40f60339d1c6 100644
--- a/arch/arm/plat-omap/include/mach/irda.h
+++ b/arch/arm/plat-omap/include/mach/irda.h
@@ -21,10 +21,6 @@ struct omap_irda_config {
int transceiver_cap;
int (*transceiver_mode)(struct device *dev, int mode);
int (*select_irda)(struct device *dev, int state);
- /* Very specific to the needs of some platforms (h3,h4)
- * having calls which can sleep in irda_set_speed.
- */
- struct delayed_work gpio_expa;
int rx_channel;
int tx_channel;
unsigned long dest_start;
diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h
index 4435bd434e17..81d5b36534b3 100644
--- a/arch/arm/plat-omap/include/mach/mmc.h
+++ b/arch/arm/plat-omap/include/mach/mmc.h
@@ -79,7 +79,6 @@ struct omap_mmc_platform_data {
/* use the internal clock */
unsigned internal_clock:1;
- s16 power_pin;
int switch_pin; /* gpio (card detect) */
int gpio_wp; /* gpio (write protect) */
diff --git a/arch/arm/plat-omap/include/mach/timer-gp.h b/arch/arm/plat-omap/include/mach/timer-gp.h
new file mode 100644
index 000000000000..c88d346b59d9
--- /dev/null
+++ b/arch/arm/plat-omap/include/mach/timer-gp.h
@@ -0,0 +1,17 @@
+/*
+ * OMAP2/3 GPTIMER support.headers
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * 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 __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_TIMER_GP_H
+#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_TIMER_GP_H
+
+int __init omap2_gp_clockevent_set_gptimer(u8 id);
+
+#endif
+
diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c
index 0abfbaa59871..538ba7541d3f 100644
--- a/arch/arm/plat-omap/mailbox.c
+++ b/arch/arm/plat-omap/mailbox.c
@@ -147,24 +147,40 @@ static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void *arg)
return ret;
}
+struct omap_msg_tx_data {
+ mbox_msg_t msg;
+ void *arg;
+};
+
+static void omap_msg_tx_end_io(struct request *rq, int error)
+{
+ kfree(rq->special);
+ __blk_put_request(rq->q, rq);
+}
+
int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void* arg)
{
+ struct omap_msg_tx_data *tx_data;
struct request *rq;
struct request_queue *q = mbox->txq->queue;
- int ret = 0;
+
+ tx_data = kmalloc(sizeof(*tx_data), GFP_ATOMIC);
+ if (unlikely(!tx_data))
+ return -ENOMEM;
rq = blk_get_request(q, WRITE, GFP_ATOMIC);
if (unlikely(!rq)) {
- ret = -ENOMEM;
- goto fail;
+ kfree(tx_data);
+ return -ENOMEM;
}
- rq->data = (void *)msg;
- blk_insert_request(q, rq, 0, arg);
+ tx_data->msg = msg;
+ tx_data->arg = arg;
+ rq->end_io = omap_msg_tx_end_io;
+ blk_insert_request(q, rq, 0, tx_data);
schedule_work(&mbox->txq->work);
- fail:
- return ret;
+ return 0;
}
EXPORT_SYMBOL(omap_mbox_msg_send);
@@ -178,6 +194,8 @@ static void mbox_tx_work(struct work_struct *work)
struct request_queue *q = mbox->txq->queue;
while (1) {
+ struct omap_msg_tx_data *tx_data;
+
spin_lock(q->queue_lock);
rq = elv_next_request(q);
spin_unlock(q->queue_lock);
@@ -185,15 +203,16 @@ static void mbox_tx_work(struct work_struct *work)
if (!rq)
break;
- ret = __mbox_msg_send(mbox, (mbox_msg_t) rq->data, rq->special);
+ tx_data = rq->special;
+
+ ret = __mbox_msg_send(mbox, tx_data->msg, tx_data->arg);
if (ret) {
enable_mbox_irq(mbox, IRQ_TX);
return;
}
spin_lock(q->queue_lock);
- if (__blk_end_request(rq, 0, 0))
- BUG();
+ __blk_end_request_all(rq, 0);
spin_unlock(q->queue_lock);
}
}
@@ -223,11 +242,8 @@ static void mbox_rx_work(struct work_struct *work)
if (!rq)
break;
- msg = (mbox_msg_t) rq->data;
-
- if (blk_end_request(rq, 0, 0))
- BUG();
-
+ msg = (mbox_msg_t)rq->special;
+ blk_end_request_all(rq, 0);
mbox->rxq->callback((void *)msg);
}
}
@@ -264,7 +280,6 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox)
goto nomem;
msg = mbox_fifo_read(mbox);
- rq->data = (void *)msg;
if (unlikely(mbox_seq_test(mbox, msg))) {
pr_info("mbox: Illegal seq bit!(%08x)\n", msg);
@@ -272,7 +287,7 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox)
mbox->err_notify();
}
- blk_insert_request(q, rq, 0, NULL);
+ blk_insert_request(q, rq, 0, (void *)msg);
if (mbox->ops->type == OMAP_MBOX_TYPE1)
break;
}
@@ -335,10 +350,9 @@ omap_mbox_read(struct device *dev, struct device_attribute *attr, char *buf)
if (!rq)
break;
- *p = (mbox_msg_t) rq->data;
+ *p = (mbox_msg_t)rq->special;
- if (blk_end_request(rq, 0, 0))
- BUG();
+ blk_end_request_all(rq, 0);
if (unlikely(mbox_seq_test(mbox, *p))) {
pr_info("mbox: Illegal seq bit!(%08x) ignored\n", *p);
diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c
index 6fa2923e6dca..de8a001fc3a9 100644
--- a/arch/arm/plat-orion/time.c
+++ b/arch/arm/plat-orion/time.c
@@ -16,7 +16,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <asm/mach/time.h>
-#include <mach/hardware.h>
+#include <mach/bridge-regs.h>
/*
* Number of timer ticks per jiffy.
@@ -41,7 +41,7 @@ static u32 ticks_per_jiffy;
/*
* Clocksource handling.
*/
-static cycle_t orion_clksrc_read(void)
+static cycle_t orion_clksrc_read(struct clocksource *cs)
{
return 0xffffffff - readl(TIMER0_VAL);
}
diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile
index 8f2c4c7fbd48..0264bfb0ca4f 100644
--- a/arch/arm/plat-pxa/Makefile
+++ b/arch/arm/plat-pxa/Makefile
@@ -7,3 +7,5 @@ obj-y := dma.o
obj-$(CONFIG_GENERIC_GPIO) += gpio.o
obj-$(CONFIG_PXA3xx) += mfp.o
obj-$(CONFIG_ARCH_MMP) += mfp.o
+
+obj-$(CONFIG_HAVE_PWM) += pwm.o
diff --git a/arch/arm/plat-pxa/gpio.c b/arch/arm/plat-pxa/gpio.c
index af819bf21b63..abc79d44acaa 100644
--- a/arch/arm/plat-pxa/gpio.c
+++ b/arch/arm/plat-pxa/gpio.c
@@ -121,6 +121,8 @@ static int __init pxa_init_gpio_chip(int gpio_end)
return -ENOMEM;
}
+ memset(chips, 0, nbanks * sizeof(struct pxa_gpio_chip));
+
for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
struct gpio_chip *c = &chips[i].chip;
@@ -143,6 +145,21 @@ static int __init pxa_init_gpio_chip(int gpio_end)
return 0;
}
+/* Update only those GRERx and GFERx edge detection register bits if those
+ * bits are set in c->irq_mask
+ */
+static inline void update_edge_detect(struct pxa_gpio_chip *c)
+{
+ uint32_t grer, gfer;
+
+ grer = __raw_readl(c->regbase + GRER_OFFSET) & ~c->irq_mask;
+ gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~c->irq_mask;
+ grer |= c->irq_edge_rise & c->irq_mask;
+ gfer |= c->irq_edge_fall & c->irq_mask;
+ __raw_writel(grer, c->regbase + GRER_OFFSET);
+ __raw_writel(gfer, c->regbase + GFER_OFFSET);
+}
+
static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
{
struct pxa_gpio_chip *c;
@@ -181,8 +198,7 @@ static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
else
c->irq_edge_fall &= ~mask;
- __raw_writel(c->irq_edge_rise & c->irq_mask, c->regbase + GRER_OFFSET);
- __raw_writel(c->irq_edge_fall & c->irq_mask, c->regbase + GFER_OFFSET);
+ update_edge_detect(c);
pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, irq, gpio,
((type & IRQ_TYPE_EDGE_RISING) ? " rising" : ""),
@@ -244,8 +260,7 @@ static void pxa_unmask_muxed_gpio(unsigned int irq)
struct pxa_gpio_chip *c = gpio_to_chip(gpio);
c->irq_mask |= GPIO_bit(gpio);
- __raw_writel(c->irq_edge_rise & c->irq_mask, c->regbase + GRER_OFFSET);
- __raw_writel(c->irq_edge_fall & c->irq_mask, c->regbase + GFER_OFFSET);
+ update_edge_detect(c);
}
static struct irq_chip pxa_muxed_gpio_chip = {
diff --git a/arch/arm/mach-pxa/include/mach/i2c.h b/arch/arm/plat-pxa/include/plat/i2c.h
index 1a9f65e6ec0f..1a9f65e6ec0f 100644
--- a/arch/arm/mach-pxa/include/mach/i2c.h
+++ b/arch/arm/plat-pxa/include/plat/i2c.h
diff --git a/arch/arm/mach-pxa/pwm.c b/arch/arm/plat-pxa/pwm.c
index fcdd374437a8..a9eabdcfa163 100644
--- a/arch/arm/mach-pxa/pwm.c
+++ b/arch/arm/plat-pxa/pwm.c
@@ -21,6 +21,19 @@
#include <asm/div64.h>
+#define HAS_SECONDARY_PWM 0x10
+#define PWM_ID_BASE(d) ((d) & 0xf)
+
+static const struct platform_device_id pwm_id_table[] = {
+ /* PWM has_secondary_pwm? */
+ { "pxa25x-pwm", 0 },
+ { "pxa27x-pwm", 0 | HAS_SECONDARY_PWM },
+ { "pxa168-pwm", 1 },
+ { "pxa910-pwm", 1 },
+ { },
+};
+MODULE_DEVICE_TABLE(platform, pwm_id_table);
+
/* PWM registers and bits definitions */
#define PWMCR (0x00)
#define PWMDCR (0x04)
@@ -31,7 +44,8 @@
struct pwm_device {
struct list_head node;
- struct platform_device *pdev;
+ struct pwm_device *secondary;
+ struct platform_device *pdev;
const char *label;
struct clk *clk;
@@ -159,17 +173,17 @@ static inline void __add_pwm(struct pwm_device *pwm)
mutex_unlock(&pwm_lock);
}
-static struct pwm_device *pwm_probe(struct platform_device *pdev,
- unsigned int pwm_id, struct pwm_device *parent_pwm)
+static int __devinit pwm_probe(struct platform_device *pdev)
{
- struct pwm_device *pwm;
+ struct platform_device_id *id = platform_get_device_id(pdev);
+ struct pwm_device *pwm, *secondary = NULL;
struct resource *r;
int ret = 0;
pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
if (pwm == NULL) {
dev_err(&pdev->dev, "failed to allocate memory\n");
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
}
pwm->clk = clk_get(&pdev->dev, NULL);
@@ -180,16 +194,9 @@ static struct pwm_device *pwm_probe(struct platform_device *pdev,
pwm->clk_enabled = 0;
pwm->use_count = 0;
- pwm->pwm_id = pwm_id;
+ pwm->pwm_id = PWM_ID_BASE(id->driver_data) + pdev->id;
pwm->pdev = pdev;
- if (parent_pwm != NULL) {
- /* registers for the second PWM has offset of 0x10 */
- pwm->mmio_base = parent_pwm->mmio_base + 0x10;
- __add_pwm(pwm);
- return pwm;
- }
-
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (r == NULL) {
dev_err(&pdev->dev, "no memory resource defined\n");
@@ -211,9 +218,27 @@ static struct pwm_device *pwm_probe(struct platform_device *pdev,
goto err_free_mem;
}
+ if (id->driver_data & HAS_SECONDARY_PWM) {
+ secondary = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
+ if (secondary == NULL) {
+ ret = -ENOMEM;
+ goto err_free_mem;
+ }
+
+ *secondary = *pwm;
+ pwm->secondary = secondary;
+
+ /* registers for the second PWM has offset of 0x10 */
+ secondary->mmio_base = pwm->mmio_base + 0x10;
+ secondary->pwm_id = pdev->id + 2;
+ }
+
__add_pwm(pwm);
+ if (secondary)
+ __add_pwm(secondary);
+
platform_set_drvdata(pdev, pwm);
- return pwm;
+ return 0;
err_free_mem:
release_mem_region(r->start, r->end - r->start + 1);
@@ -221,32 +246,7 @@ err_free_clk:
clk_put(pwm->clk);
err_free:
kfree(pwm);
- return ERR_PTR(ret);
-}
-
-static int __devinit pxa25x_pwm_probe(struct platform_device *pdev)
-{
- struct pwm_device *pwm = pwm_probe(pdev, pdev->id, NULL);
-
- if (IS_ERR(pwm))
- return PTR_ERR(pwm);
-
- return 0;
-}
-
-static int __devinit pxa27x_pwm_probe(struct platform_device *pdev)
-{
- struct pwm_device *pwm;
-
- pwm = pwm_probe(pdev, pdev->id, NULL);
- if (IS_ERR(pwm))
- return PTR_ERR(pwm);
-
- pwm = pwm_probe(pdev, pdev->id + 2, pwm);
- if (IS_ERR(pwm))
- return PTR_ERR(pwm);
-
- return 0;
+ return ret;
}
static int __devexit pwm_remove(struct platform_device *pdev)
@@ -259,6 +259,12 @@ static int __devexit pwm_remove(struct platform_device *pdev)
return -ENODEV;
mutex_lock(&pwm_lock);
+
+ if (pwm->secondary) {
+ list_del(&pwm->secondary->node);
+ kfree(pwm->secondary);
+ }
+
list_del(&pwm->node);
mutex_unlock(&pwm_lock);
@@ -272,46 +278,25 @@ static int __devexit pwm_remove(struct platform_device *pdev)
return 0;
}
-static struct platform_driver pxa25x_pwm_driver = {
+static struct platform_driver pwm_driver = {
.driver = {
.name = "pxa25x-pwm",
+ .owner = THIS_MODULE,
},
- .probe = pxa25x_pwm_probe,
- .remove = __devexit_p(pwm_remove),
-};
-
-static struct platform_driver pxa27x_pwm_driver = {
- .driver = {
- .name = "pxa27x-pwm",
- },
- .probe = pxa27x_pwm_probe,
+ .probe = pwm_probe,
.remove = __devexit_p(pwm_remove),
+ .id_table = pwm_id_table,
};
static int __init pwm_init(void)
{
- int ret = 0;
-
- ret = platform_driver_register(&pxa25x_pwm_driver);
- if (ret) {
- printk(KERN_ERR "failed to register pxa25x_pwm_driver\n");
- return ret;
- }
-
- ret = platform_driver_register(&pxa27x_pwm_driver);
- if (ret) {
- printk(KERN_ERR "failed to register pxa27x_pwm_driver\n");
- return ret;
- }
-
- return ret;
+ return platform_driver_register(&pwm_driver);
}
arch_initcall(pwm_init);
static void __exit pwm_exit(void)
{
- platform_driver_unregister(&pxa25x_pwm_driver);
- platform_driver_unregister(&pxa27x_pwm_driver);
+ platform_driver_unregister(&pwm_driver);
}
module_exit(pwm_exit);
diff --git a/arch/arm/plat-s3c/Kconfig b/arch/arm/plat-s3c/Kconfig
index de9383814e5e..a4c5027421d3 100644
--- a/arch/arm/plat-s3c/Kconfig
+++ b/arch/arm/plat-s3c/Kconfig
@@ -71,6 +71,15 @@ config S3C2410_PM_DEBUG
Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
for more information.
+config S3C_PM_DEBUG_LED_SMDK
+ bool "SMDK LED suspend/resume debugging"
+ depends on PM && (MACH_SMDK6410)
+ help
+ Say Y here to enable the use of the SMDK LEDs on the baseboard
+ for debugging of the state of the suspend and resume process.
+
+ Note, this currently only works for S3C64XX based SMDK boards.
+
config S3C2410_PM_CHECK
bool "S3C2410 PM Suspend Memory CRC"
depends on PM && CRC32
@@ -172,4 +181,9 @@ config S3C_DEV_FB
help
Compile in platform device definition for framebuffer
+config S3C_DEV_USB_HOST
+ bool
+ help
+ Compile in platform device definition for USB host.
+
endif
diff --git a/arch/arm/plat-s3c/Makefile b/arch/arm/plat-s3c/Makefile
index 8d7815d25a51..bfc8f537db18 100644
--- a/arch/arm/plat-s3c/Makefile
+++ b/arch/arm/plat-s3c/Makefile
@@ -21,6 +21,7 @@ obj-y += gpio-config.o
# PM support
obj-$(CONFIG_PM) += pm.o
+obj-$(CONFIG_PM) += pm-gpio.o
obj-$(CONFIG_S3C2410_PM_CHECK) += pm-check.o
# devices
@@ -30,3 +31,4 @@ obj-$(CONFIG_S3C_DEV_HSMMC1) += dev-hsmmc1.o
obj-y += dev-i2c0.o
obj-$(CONFIG_S3C_DEV_I2C1) += dev-i2c1.o
obj-$(CONFIG_S3C_DEV_FB) += dev-fb.o
+obj-$(CONFIG_S3C_DEV_USB_HOST) += dev-usb.o
diff --git a/arch/arm/plat-s3c/dev-usb.c b/arch/arm/plat-s3c/dev-usb.c
new file mode 100644
index 000000000000..2ee85abed6d9
--- /dev/null
+++ b/arch/arm/plat-s3c/dev-usb.c
@@ -0,0 +1,50 @@
+/* linux/arch/arm/plat-s3c/dev-usb.c
+ *
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
+ *
+ * S3C series device definition for USB host
+ *
+ * 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/string.h>
+#include <linux/platform_device.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/devs.h>
+
+
+static struct resource s3c_usb_resource[] = {
+ [0] = {
+ .start = S3C_PA_USBHOST,
+ .end = S3C_PA_USBHOST + 0x100 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_USBH,
+ .end = IRQ_USBH,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static u64 s3c_device_usb_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_usb = {
+ .name = "s3c2410-ohci",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_usb_resource),
+ .resource = s3c_usb_resource,
+ .dev = {
+ .dma_mask = &s3c_device_usb_dmamask,
+ .coherent_dma_mask = 0xffffffffUL
+ }
+};
+
+EXPORT_SYMBOL(s3c_device_usb);
diff --git a/arch/arm/plat-s3c/gpio-config.c b/arch/arm/plat-s3c/gpio-config.c
index 7642b975a998..08044dec9731 100644
--- a/arch/arm/plat-s3c/gpio-config.c
+++ b/arch/arm/plat-s3c/gpio-config.c
@@ -13,6 +13,7 @@
*/
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/io.h>
@@ -38,6 +39,7 @@ int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
return ret;
}
+EXPORT_SYMBOL(s3c_gpio_cfgpin);
int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
{
@@ -56,6 +58,7 @@ int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
return ret;
}
+EXPORT_SYMBOL(s3c_gpio_setpull);
#ifdef CONFIG_S3C_GPIO_CFG_S3C24XX
int s3c_gpio_setcfg_s3c24xx_banka(struct s3c_gpio_chip *chip,
diff --git a/arch/arm/plat-s3c/gpio.c b/arch/arm/plat-s3c/gpio.c
index d71dd6d9ce5c..260fdc6ad685 100644
--- a/arch/arm/plat-s3c/gpio.c
+++ b/arch/arm/plat-s3c/gpio.c
@@ -16,7 +16,7 @@
#include <linux/io.h>
#include <linux/gpio.h>
-#include <plat/gpio-core.h>
+#include <mach/gpio-core.h>
#ifdef CONFIG_S3C_GPIO_TRACK
struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
@@ -140,6 +140,15 @@ __init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
if (!gc->get)
gc->get = s3c_gpiolib_get;
+#ifdef CONFIG_PM
+ if (chip->pm != NULL) {
+ if (!chip->pm->save || !chip->pm->resume)
+ printk(KERN_ERR "gpio: %s has missing PM functions\n",
+ gc->label);
+ } else
+ printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
+#endif
+
/* gpiochip_add() prints own failure message on error. */
ret = gpiochip_add(gc);
if (ret >= 0)
diff --git a/arch/arm/plat-s3c/include/plat/cpu.h b/arch/arm/plat-s3c/include/plat/cpu.h
index e62ae0fcfe56..be541cbba070 100644
--- a/arch/arm/plat-s3c/include/plat/cpu.h
+++ b/arch/arm/plat-s3c/include/plat/cpu.h
@@ -69,3 +69,6 @@ extern struct sysdev_class s3c2412_sysclass;
extern struct sysdev_class s3c2440_sysclass;
extern struct sysdev_class s3c2442_sysclass;
extern struct sysdev_class s3c2443_sysclass;
+extern struct sysdev_class s3c6410_sysclass;
+extern struct sysdev_class s3c64xx_sysclass;
+
diff --git a/arch/arm/plat-s3c/include/plat/devs.h b/arch/arm/plat-s3c/include/plat/devs.h
index 6b1b5231511c..26f0cec3ac04 100644
--- a/arch/arm/plat-s3c/include/plat/devs.h
+++ b/arch/arm/plat-s3c/include/plat/devs.h
@@ -34,6 +34,7 @@ extern struct platform_device s3c_device_iis;
extern struct platform_device s3c_device_rtc;
extern struct platform_device s3c_device_adc;
extern struct platform_device s3c_device_sdi;
+extern struct platform_device s3c_device_hwmon;
extern struct platform_device s3c_device_hsmmc0;
extern struct platform_device s3c_device_hsmmc1;
extern struct platform_device s3c_device_hsmmc2;
diff --git a/arch/arm/plat-s3c/include/plat/gpio-core.h b/arch/arm/plat-s3c/include/plat/gpio-core.h
index 2fc60a580ac8..32af612767aa 100644
--- a/arch/arm/plat-s3c/include/plat/gpio-core.h
+++ b/arch/arm/plat-s3c/include/plat/gpio-core.h
@@ -20,6 +20,18 @@
* specific code.
*/
+struct s3c_gpio_chip;
+
+/**
+ * struct s3c_gpio_pm - power management (suspend/resume) information
+ * @save: Routine to save the state of the GPIO block
+ * @resume: Routine to resume the GPIO block.
+ */
+struct s3c_gpio_pm {
+ void (*save)(struct s3c_gpio_chip *chip);
+ void (*resume)(struct s3c_gpio_chip *chip);
+};
+
struct s3c_gpio_cfg;
/**
@@ -27,6 +39,7 @@ struct s3c_gpio_cfg;
* @chip: The chip structure to be exported via gpiolib.
* @base: The base pointer to the gpio configuration registers.
* @config: special function and pull-resistor control information.
+ * @pm_save: Save information for suspend/resume support.
*
* This wrapper provides the necessary information for the Samsung
* specific gpios being registered with gpiolib.
@@ -34,7 +47,11 @@ struct s3c_gpio_cfg;
struct s3c_gpio_chip {
struct gpio_chip chip;
struct s3c_gpio_cfg *config;
+ struct s3c_gpio_pm *pm;
void __iomem *base;
+#ifdef CONFIG_PM
+ u32 pm_save[4];
+#endif
};
static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc)
@@ -75,3 +92,16 @@ static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int chip)
static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { }
#endif
+
+#ifdef CONFIG_PM
+extern struct s3c_gpio_pm s3c_gpio_pm_1bit;
+extern struct s3c_gpio_pm s3c_gpio_pm_2bit;
+extern struct s3c_gpio_pm s3c_gpio_pm_4bit;
+#define __gpio_pm(x) x
+#else
+#define s3c_gpio_pm_1bit NULL
+#define s3c_gpio_pm_2bit NULL
+#define s3c_gpio_pm_4bit NULL
+#define __gpio_pm(x) NULL
+
+#endif /* CONFIG_PM */
diff --git a/arch/arm/plat-s3c/include/plat/pm.h b/arch/arm/plat-s3c/include/plat/pm.h
index 3779775133a9..7a797192fcf3 100644
--- a/arch/arm/plat-s3c/include/plat/pm.h
+++ b/arch/arm/plat-s3c/include/plat/pm.h
@@ -44,6 +44,8 @@ extern void (*pm_cpu_sleep)(void);
extern unsigned long s3c_pm_flags;
+extern unsigned char pm_uart_udivslot; /* true to save UART UDIVSLOT */
+
/* from sleep.S */
extern int s3c_cpu_save(unsigned long *saveblk);
@@ -88,6 +90,7 @@ struct pm_uart_save {
u32 ufcon;
u32 umcon;
u32 ubrdiv;
+ u32 udivslot;
};
/* helper functions to save/restore lists of registers. */
@@ -124,6 +127,18 @@ extern void s3c_pm_dbg(const char *msg, ...);
#define S3C_PMDBG(fmt...) printk(KERN_DEBUG fmt)
#endif
+#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
+/**
+ * s3c_pm_debug_smdkled() - Debug PM suspend/resume via SMDK Board LEDs
+ * @set: set bits for the state of the LEDs
+ * @clear: clear bits for the state of the LEDs.
+ */
+extern void s3c_pm_debug_smdkled(u32 set, u32 clear);
+
+#else
+static inline void s3c_pm_debug_smdkled(u32 set, u32 clear) { }
+#endif /* CONFIG_S3C_PM_DEBUG_LED_SMDK */
+
/* suspend memory checking */
#ifdef CONFIG_S3C2410_PM_CHECK
diff --git a/arch/arm/plat-s3c/include/plat/regs-serial.h b/arch/arm/plat-s3c/include/plat/regs-serial.h
index 487d7d2a7e1d..66af75a5cdd1 100644
--- a/arch/arm/plat-s3c/include/plat/regs-serial.h
+++ b/arch/arm/plat-s3c/include/plat/regs-serial.h
@@ -189,6 +189,11 @@
#define S3C2443_DIVSLOT (0x2C)
+/* S3C64XX interrupt registers. */
+#define S3C64XX_UINTP 0x30
+#define S3C64XX_UINTSP 0x34
+#define S3C64XX_UINTM 0x38
+
#ifndef __ASSEMBLY__
/* struct s3c24xx_uart_clksrc
diff --git a/arch/arm/plat-s3c/pm-gpio.c b/arch/arm/plat-s3c/pm-gpio.c
new file mode 100644
index 000000000000..cfd326a8b693
--- /dev/null
+++ b/arch/arm/plat-s3c/pm-gpio.c
@@ -0,0 +1,380 @@
+
+/* linux/arch/arm/plat-s3c/pm-gpio.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
+ *
+ * S3C series GPIO PM 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/kernel.h>
+#include <linux/sysdev.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <mach/gpio-core.h>
+#include <plat/pm.h>
+
+/* PM GPIO helpers */
+
+#define OFFS_CON (0x00)
+#define OFFS_DAT (0x04)
+#define OFFS_UP (0x08)
+
+static void s3c_gpio_pm_1bit_save(struct s3c_gpio_chip *chip)
+{
+ chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
+ chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
+}
+
+static void s3c_gpio_pm_1bit_resume(struct s3c_gpio_chip *chip)
+{
+ void __iomem *base = chip->base;
+ u32 old_gpcon = __raw_readl(base + OFFS_CON);
+ u32 old_gpdat = __raw_readl(base + OFFS_DAT);
+ u32 gps_gpcon = chip->pm_save[0];
+ u32 gps_gpdat = chip->pm_save[1];
+ u32 gpcon;
+
+ /* GPACON only has one bit per control / data and no PULLUPs.
+ * GPACON[x] = 0 => Output, 1 => SFN */
+
+ /* first set all SFN bits to SFN */
+
+ gpcon = old_gpcon | gps_gpcon;
+ __raw_writel(gpcon, base + OFFS_CON);
+
+ /* now set all the other bits */
+
+ __raw_writel(gps_gpdat, base + OFFS_DAT);
+ __raw_writel(gps_gpcon, base + OFFS_CON);
+
+ S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
+ chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
+}
+
+struct s3c_gpio_pm s3c_gpio_pm_1bit = {
+ .save = s3c_gpio_pm_1bit_save,
+ .resume = s3c_gpio_pm_1bit_resume,
+};
+
+static void s3c_gpio_pm_2bit_save(struct s3c_gpio_chip *chip)
+{
+ chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
+ chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
+ chip->pm_save[2] = __raw_readl(chip->base + OFFS_UP);
+}
+
+/* Test whether the given masked+shifted bits of an GPIO configuration
+ * are one of the SFN (special function) modes. */
+
+static inline int is_sfn(unsigned long con)
+{
+ return con >= 2;
+}
+
+/* Test if the given masked+shifted GPIO configuration is an input */
+
+static inline int is_in(unsigned long con)
+{
+ return con == 0;
+}
+
+/* Test if the given masked+shifted GPIO configuration is an output */
+
+static inline int is_out(unsigned long con)
+{
+ return con == 1;
+}
+
+/**
+ * s3c_gpio_pm_2bit_resume() - restore the given GPIO bank
+ * @chip: The chip information to resume.
+ *
+ * Restore one of the GPIO banks that was saved during suspend. This is
+ * not as simple as once thought, due to the possibility of glitches
+ * from the order that the CON and DAT registers are set in.
+ *
+ * The three states the pin can be are {IN,OUT,SFN} which gives us 9
+ * combinations of changes to check. Three of these, if the pin stays
+ * in the same configuration can be discounted. This leaves us with
+ * the following:
+ *
+ * { IN => OUT } Change DAT first
+ * { IN => SFN } Change CON first
+ * { OUT => SFN } Change CON first, so new data will not glitch
+ * { OUT => IN } Change CON first, so new data will not glitch
+ * { SFN => IN } Change CON first
+ * { SFN => OUT } Change DAT first, so new data will not glitch [1]
+ *
+ * We do not currently deal with the UP registers as these control
+ * weak resistors, so a small delay in change should not need to bring
+ * these into the calculations.
+ *
+ * [1] this assumes that writing to a pin DAT whilst in SFN will set the
+ * state for when it is next output.
+ */
+static void s3c_gpio_pm_2bit_resume(struct s3c_gpio_chip *chip)
+{
+ void __iomem *base = chip->base;
+ u32 old_gpcon = __raw_readl(base + OFFS_CON);
+ u32 old_gpdat = __raw_readl(base + OFFS_DAT);
+ u32 gps_gpcon = chip->pm_save[0];
+ u32 gps_gpdat = chip->pm_save[1];
+ u32 gpcon, old, new, mask;
+ u32 change_mask = 0x0;
+ int nr;
+
+ /* restore GPIO pull-up settings */
+ __raw_writel(chip->pm_save[2], base + OFFS_UP);
+
+ /* Create a change_mask of all the items that need to have
+ * their CON value changed before their DAT value, so that
+ * we minimise the work between the two settings.
+ */
+
+ for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) {
+ old = (old_gpcon & mask) >> nr;
+ new = (gps_gpcon & mask) >> nr;
+
+ /* If there is no change, then skip */
+
+ if (old == new)
+ continue;
+
+ /* If both are special function, then skip */
+
+ if (is_sfn(old) && is_sfn(new))
+ continue;
+
+ /* Change is IN => OUT, do not change now */
+
+ if (is_in(old) && is_out(new))
+ continue;
+
+ /* Change is SFN => OUT, do not change now */
+
+ if (is_sfn(old) && is_out(new))
+ continue;
+
+ /* We should now be at the case of IN=>SFN,
+ * OUT=>SFN, OUT=>IN, SFN=>IN. */
+
+ change_mask |= mask;
+ }
+
+
+ /* Write the new CON settings */
+
+ gpcon = old_gpcon & ~change_mask;
+ gpcon |= gps_gpcon & change_mask;
+
+ __raw_writel(gpcon, base + OFFS_CON);
+
+ /* Now change any items that require DAT,CON */
+
+ __raw_writel(gps_gpdat, base + OFFS_DAT);
+ __raw_writel(gps_gpcon, base + OFFS_CON);
+
+ S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
+ chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
+}
+
+struct s3c_gpio_pm s3c_gpio_pm_2bit = {
+ .save = s3c_gpio_pm_2bit_save,
+ .resume = s3c_gpio_pm_2bit_resume,
+};
+
+#ifdef CONFIG_ARCH_S3C64XX
+static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip)
+{
+ chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
+ chip->pm_save[2] = __raw_readl(chip->base + OFFS_DAT);
+ chip->pm_save[3] = __raw_readl(chip->base + OFFS_UP);
+
+ if (chip->chip.ngpio > 8)
+ chip->pm_save[0] = __raw_readl(chip->base - 4);
+}
+
+static u32 s3c_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
+{
+ u32 old, new, mask;
+ u32 change_mask = 0x0;
+ int nr;
+
+ for (nr = 0, mask = 0x0f; nr < 16; nr += 4, mask <<= 4) {
+ old = (old_gpcon & mask) >> nr;
+ new = (gps_gpcon & mask) >> nr;
+
+ /* If there is no change, then skip */
+
+ if (old == new)
+ continue;
+
+ /* If both are special function, then skip */
+
+ if (is_sfn(old) && is_sfn(new))
+ continue;
+
+ /* Change is IN => OUT, do not change now */
+
+ if (is_in(old) && is_out(new))
+ continue;
+
+ /* Change is SFN => OUT, do not change now */
+
+ if (is_sfn(old) && is_out(new))
+ continue;
+
+ /* We should now be at the case of IN=>SFN,
+ * OUT=>SFN, OUT=>IN, SFN=>IN. */
+
+ change_mask |= mask;
+ }
+
+ return change_mask;
+}
+
+static void s3c_gpio_pm_4bit_con(struct s3c_gpio_chip *chip, int index)
+{
+ void __iomem *con = chip->base + (index * 4);
+ u32 old_gpcon = __raw_readl(con);
+ u32 gps_gpcon = chip->pm_save[index + 1];
+ u32 gpcon, mask;
+
+ mask = s3c_gpio_pm_4bit_mask(old_gpcon, gps_gpcon);
+
+ gpcon = old_gpcon & ~mask;
+ gpcon |= gps_gpcon & mask;
+
+ __raw_writel(gpcon, con);
+}
+
+static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
+{
+ void __iomem *base = chip->base;
+ u32 old_gpcon[2];
+ u32 old_gpdat = __raw_readl(base + OFFS_DAT);
+ u32 gps_gpdat = chip->pm_save[2];
+
+ /* First, modify the CON settings */
+
+ old_gpcon[0] = 0;
+ old_gpcon[1] = __raw_readl(base + OFFS_CON);
+
+ s3c_gpio_pm_4bit_con(chip, 0);
+ if (chip->chip.ngpio > 8) {
+ old_gpcon[0] = __raw_readl(base - 4);
+ s3c_gpio_pm_4bit_con(chip, -1);
+ }
+
+ /* Now change the configurations that require DAT,CON */
+
+ __raw_writel(chip->pm_save[2], base + OFFS_DAT);
+ __raw_writel(chip->pm_save[1], base + OFFS_CON);
+ if (chip->chip.ngpio > 8)
+ __raw_writel(chip->pm_save[0], base - 4);
+
+ __raw_writel(chip->pm_save[2], base + OFFS_DAT);
+ __raw_writel(chip->pm_save[3], base + OFFS_UP);
+
+ if (chip->chip.ngpio > 8) {
+ S3C_PMDBG("%s: CON4 %08x,%08x => %08x,%08x, DAT %08x => %08x\n",
+ chip->chip.label, old_gpcon[0], old_gpcon[1],
+ __raw_readl(base - 4),
+ __raw_readl(base + OFFS_CON),
+ old_gpdat, gps_gpdat);
+ } else
+ S3C_PMDBG("%s: CON4 %08x => %08x, DAT %08x => %08x\n",
+ chip->chip.label, old_gpcon[1],
+ __raw_readl(base + OFFS_CON),
+ old_gpdat, gps_gpdat);
+}
+
+struct s3c_gpio_pm s3c_gpio_pm_4bit = {
+ .save = s3c_gpio_pm_4bit_save,
+ .resume = s3c_gpio_pm_4bit_resume,
+};
+#endif /* CONFIG_ARCH_S3C64XX */
+
+/**
+ * s3c_pm_save_gpio() - save gpio chip data for suspend
+ * @ourchip: The chip for suspend.
+ */
+static void s3c_pm_save_gpio(struct s3c_gpio_chip *ourchip)
+{
+ struct s3c_gpio_pm *pm = ourchip->pm;
+
+ if (pm == NULL || pm->save == NULL)
+ S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
+ else
+ pm->save(ourchip);
+}
+
+/**
+ * s3c_pm_save_gpios() - Save the state of the GPIO banks.
+ *
+ * For all the GPIO banks, save the state of each one ready for going
+ * into a suspend mode.
+ */
+void s3c_pm_save_gpios(void)
+{
+ struct s3c_gpio_chip *ourchip;
+ unsigned int gpio_nr;
+
+ for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
+ ourchip = s3c_gpiolib_getchip(gpio_nr);
+ if (!ourchip)
+ continue;
+
+ s3c_pm_save_gpio(ourchip);
+
+ S3C_PMDBG("%s: save %08x,%08x,%08x,%08x\n",
+ ourchip->chip.label,
+ ourchip->pm_save[0],
+ ourchip->pm_save[1],
+ ourchip->pm_save[2],
+ ourchip->pm_save[3]);
+
+ gpio_nr += ourchip->chip.ngpio;
+ gpio_nr += CONFIG_S3C_GPIO_SPACE;
+ }
+}
+
+/**
+ * s3c_pm_resume_gpio() - restore gpio chip data after suspend
+ * @ourchip: The suspended chip.
+ */
+static void s3c_pm_resume_gpio(struct s3c_gpio_chip *ourchip)
+{
+ struct s3c_gpio_pm *pm = ourchip->pm;
+
+ if (pm == NULL || pm->resume == NULL)
+ S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
+ else
+ pm->resume(ourchip);
+}
+
+void s3c_pm_restore_gpios(void)
+{
+ struct s3c_gpio_chip *ourchip;
+ unsigned int gpio_nr;
+
+ for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
+ ourchip = s3c_gpiolib_getchip(gpio_nr);
+ if (!ourchip)
+ continue;
+
+ s3c_pm_resume_gpio(ourchip);
+
+ gpio_nr += ourchip->chip.ngpio;
+ gpio_nr += CONFIG_S3C_GPIO_SPACE;
+ }
+}
diff --git a/arch/arm/plat-s3c/pm.c b/arch/arm/plat-s3c/pm.c
index 061182ca66e3..8d97db2c7a0d 100644
--- a/arch/arm/plat-s3c/pm.c
+++ b/arch/arm/plat-s3c/pm.c
@@ -21,11 +21,10 @@
#include <asm/cacheflush.h>
#include <mach/hardware.h>
+#include <mach/map.h>
#include <plat/regs-serial.h>
#include <mach/regs-clock.h>
-#include <mach/regs-gpio.h>
-#include <mach/regs-mem.h>
#include <mach/regs-irq.h>
#include <asm/irq.h>
@@ -70,6 +69,8 @@ static inline void s3c_pm_debug_init(void)
/* Save the UART configurations if we are configured for debug. */
+unsigned char pm_uart_udivslot;
+
#ifdef CONFIG_S3C2410_PM_DEBUG
struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS];
@@ -83,6 +84,12 @@ static void s3c_pm_save_uart(unsigned int uart, struct pm_uart_save *save)
save->ufcon = __raw_readl(regs + S3C2410_UFCON);
save->umcon = __raw_readl(regs + S3C2410_UMCON);
save->ubrdiv = __raw_readl(regs + S3C2410_UBRDIV);
+
+ if (pm_uart_udivslot)
+ save->udivslot = __raw_readl(regs + S3C2443_DIVSLOT);
+
+ S3C_PMDBG("UART[%d]: ULCON=%04x, UCON=%04x, UFCON=%04x, UBRDIV=%04x\n",
+ uart, save->ulcon, save->ucon, save->ufcon, save->ubrdiv);
}
static void s3c_pm_save_uarts(void)
@@ -98,11 +105,16 @@ static void s3c_pm_restore_uart(unsigned int uart, struct pm_uart_save *save)
{
void __iomem *regs = S3C_VA_UARTx(uart);
+ s3c_pm_arch_update_uart(regs, save);
+
__raw_writel(save->ulcon, regs + S3C2410_ULCON);
__raw_writel(save->ucon, regs + S3C2410_UCON);
__raw_writel(save->ufcon, regs + S3C2410_UFCON);
__raw_writel(save->umcon, regs + S3C2410_UMCON);
__raw_writel(save->ubrdiv, regs + S3C2410_UBRDIV);
+
+ if (pm_uart_udivslot)
+ __raw_writel(save->udivslot, regs + S3C2443_DIVSLOT);
}
static void s3c_pm_restore_uarts(void)
@@ -313,6 +325,9 @@ static int s3c_pm_enter(suspend_state_t state)
S3C_PMDBG("%s: post sleep, preparing to return\n", __func__);
+ /* LEDs should now be 1110 */
+ s3c_pm_debug_smdkled(1 << 1, 0);
+
s3c_pm_check_restore();
/* ok, let's return from sleep */
diff --git a/arch/arm/plat-s3c24xx/adc.c b/arch/arm/plat-s3c24xx/adc.c
index 9a5c767e0a42..91adfa71c172 100644
--- a/arch/arm/plat-s3c24xx/adc.c
+++ b/arch/arm/plat-s3c24xx/adc.c
@@ -100,7 +100,7 @@ static void s3c_adc_dbgshow(struct adc_device *adc)
readl(adc->regs + S3C2410_ADCDLY));
}
-void s3c_adc_try(struct adc_device *adc)
+static void s3c_adc_try(struct adc_device *adc)
{
struct s3c_adc_client *next = adc->ts_pend;
@@ -190,6 +190,23 @@ EXPORT_SYMBOL_GPL(s3c_adc_register);
void s3c_adc_release(struct s3c_adc_client *client)
{
/* We should really check that nothing is in progress. */
+ if (adc_dev->cur == client)
+ adc_dev->cur = NULL;
+ if (adc_dev->ts_pend == client)
+ adc_dev->ts_pend = NULL;
+ else {
+ struct list_head *p, *n;
+ struct s3c_adc_client *tmp;
+
+ list_for_each_safe(p, n, &adc_pending) {
+ tmp = list_entry(p, struct s3c_adc_client, pend);
+ if (tmp == client)
+ list_del(&tmp->pend);
+ }
+ }
+
+ if (adc_dev->cur == NULL)
+ s3c_adc_try(adc_dev);
kfree(client);
}
EXPORT_SYMBOL_GPL(s3c_adc_release);
diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c
index 16ac01d9b8ab..4eb378c89a39 100644
--- a/arch/arm/plat-s3c24xx/devs.c
+++ b/arch/arm/plat-s3c24xx/devs.c
@@ -136,36 +136,6 @@ struct platform_device *s3c24xx_uart_src[4] = {
struct platform_device *s3c24xx_uart_devs[4] = {
};
-/* USB Host Controller */
-
-static struct resource s3c_usb_resource[] = {
- [0] = {
- .start = S3C24XX_PA_USBHOST,
- .end = S3C24XX_PA_USBHOST + S3C24XX_SZ_USBHOST - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_USBH,
- .end = IRQ_USBH,
- .flags = IORESOURCE_IRQ,
- }
-};
-
-static u64 s3c_device_usb_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_usb = {
- .name = "s3c2410-ohci",
- .id = -1,
- .num_resources = ARRAY_SIZE(s3c_usb_resource),
- .resource = s3c_usb_resource,
- .dev = {
- .dma_mask = &s3c_device_usb_dmamask,
- .coherent_dma_mask = 0xffffffffUL
- }
-};
-
-EXPORT_SYMBOL(s3c_device_usb);
-
/* LCD Controller */
static struct resource s3c_lcd_resource[] = {
diff --git a/arch/arm/plat-s3c24xx/gpiolib.c b/arch/arm/plat-s3c24xx/gpiolib.c
index 94a341aaa4e4..4bac12dc0733 100644
--- a/arch/arm/plat-s3c24xx/gpiolib.c
+++ b/arch/arm/plat-s3c24xx/gpiolib.c
@@ -19,9 +19,10 @@
#include <linux/io.h>
#include <linux/gpio.h>
-#include <plat/gpio-core.h>
+#include <mach/gpio-core.h>
#include <mach/hardware.h>
#include <asm/irq.h>
+#include <plat/pm.h>
#include <mach/regs-gpio.h>
@@ -78,6 +79,7 @@ static int s3c24xx_gpiolib_bankg_toirq(struct gpio_chip *chip, unsigned offset)
struct s3c_gpio_chip s3c24xx_gpios[] = {
[0] = {
.base = S3C24XX_GPIO_BASE(S3C2410_GPA0),
+ .pm = __gpio_pm(&s3c_gpio_pm_1bit),
.chip = {
.base = S3C2410_GPA0,
.owner = THIS_MODULE,
@@ -89,6 +91,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
},
[1] = {
.base = S3C24XX_GPIO_BASE(S3C2410_GPB0),
+ .pm = __gpio_pm(&s3c_gpio_pm_2bit),
.chip = {
.base = S3C2410_GPB0,
.owner = THIS_MODULE,
@@ -98,6 +101,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
},
[2] = {
.base = S3C24XX_GPIO_BASE(S3C2410_GPC0),
+ .pm = __gpio_pm(&s3c_gpio_pm_2bit),
.chip = {
.base = S3C2410_GPC0,
.owner = THIS_MODULE,
@@ -107,6 +111,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
},
[3] = {
.base = S3C24XX_GPIO_BASE(S3C2410_GPD0),
+ .pm = __gpio_pm(&s3c_gpio_pm_2bit),
.chip = {
.base = S3C2410_GPD0,
.owner = THIS_MODULE,
@@ -116,6 +121,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
},
[4] = {
.base = S3C24XX_GPIO_BASE(S3C2410_GPE0),
+ .pm = __gpio_pm(&s3c_gpio_pm_2bit),
.chip = {
.base = S3C2410_GPE0,
.label = "GPIOE",
@@ -125,6 +131,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
},
[5] = {
.base = S3C24XX_GPIO_BASE(S3C2410_GPF0),
+ .pm = __gpio_pm(&s3c_gpio_pm_2bit),
.chip = {
.base = S3C2410_GPF0,
.owner = THIS_MODULE,
@@ -135,6 +142,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
},
[6] = {
.base = S3C24XX_GPIO_BASE(S3C2410_GPG0),
+ .pm = __gpio_pm(&s3c_gpio_pm_2bit),
.chip = {
.base = S3C2410_GPG0,
.owner = THIS_MODULE,
diff --git a/arch/arm/plat-s3c24xx/include/plat/map.h b/arch/arm/plat-s3c24xx/include/plat/map.h
index eed8f78e7593..c4d133436fc7 100644
--- a/arch/arm/plat-s3c24xx/include/plat/map.h
+++ b/arch/arm/plat-s3c24xx/include/plat/map.h
@@ -58,7 +58,6 @@
#define S3C24XX_SZ_SPI SZ_1M
#define S3C24XX_SZ_SDI SZ_1M
#define S3C24XX_SZ_NAND SZ_1M
-#define S3C24XX_SZ_USBHOST SZ_1M
/* GPIO ports */
diff --git a/arch/arm/plat-s3c24xx/include/plat/pm-core.h b/arch/arm/plat-s3c24xx/include/plat/pm-core.h
index c75882113e04..fb45dd9adca5 100644
--- a/arch/arm/plat-s3c24xx/include/plat/pm-core.h
+++ b/arch/arm/plat-s3c24xx/include/plat/pm-core.h
@@ -57,3 +57,8 @@ static inline void s3c_pm_arch_show_resume_irqs(void)
s3c_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
s3c_irqwake_eintmask);
}
+
+static inline void s3c_pm_arch_update_uart(void __iomem *regs,
+ struct pm_uart_save *save)
+{
+}
diff --git a/arch/arm/plat-s3c24xx/pm.c b/arch/arm/plat-s3c24xx/pm.c
index 062a29339a91..5135c40a1b90 100644
--- a/arch/arm/plat-s3c24xx/pm.c
+++ b/arch/arm/plat-s3c24xx/pm.c
@@ -75,43 +75,10 @@ static struct sleep_save core_save[] = {
SAVE_ITEM(S3C2410_CLKSLOW),
};
-static struct gpio_sleep {
- void __iomem *base;
- unsigned int gpcon;
- unsigned int gpdat;
- unsigned int gpup;
-} gpio_save[] = {
- [0] = {
- .base = S3C2410_GPACON,
- },
- [1] = {
- .base = S3C2410_GPBCON,
- },
- [2] = {
- .base = S3C2410_GPCCON,
- },
- [3] = {
- .base = S3C2410_GPDCON,
- },
- [4] = {
- .base = S3C2410_GPECON,
- },
- [5] = {
- .base = S3C2410_GPFCON,
- },
- [6] = {
- .base = S3C2410_GPGCON,
- },
- [7] = {
- .base = S3C2410_GPHCON,
- },
-};
-
static struct sleep_save misc_save[] = {
SAVE_ITEM(S3C2410_DCLKCON),
};
-
/* s3c_pm_check_resume_pin
*
* check to see if the pin is configured correctly for sleep mode, and
@@ -165,186 +132,6 @@ void s3c_pm_configure_extint(void)
}
}
-/* offsets for CON/DAT/UP registers */
-
-#define OFFS_CON (S3C2410_GPACON - S3C2410_GPACON)
-#define OFFS_DAT (S3C2410_GPADAT - S3C2410_GPACON)
-#define OFFS_UP (S3C2410_GPBUP - S3C2410_GPBCON)
-
-/* s3c_pm_save_gpios()
- *
- * Save the state of the GPIOs
- */
-
-void s3c_pm_save_gpios(void)
-{
- struct gpio_sleep *gps = gpio_save;
- unsigned int gpio;
-
- for (gpio = 0; gpio < ARRAY_SIZE(gpio_save); gpio++, gps++) {
- void __iomem *base = gps->base;
-
- gps->gpcon = __raw_readl(base + OFFS_CON);
- gps->gpdat = __raw_readl(base + OFFS_DAT);
-
- if (gpio > 0)
- gps->gpup = __raw_readl(base + OFFS_UP);
-
- }
-}
-
-/* Test whether the given masked+shifted bits of an GPIO configuration
- * are one of the SFN (special function) modes. */
-
-static inline int is_sfn(unsigned long con)
-{
- return (con == 2 || con == 3);
-}
-
-/* Test if the given masked+shifted GPIO configuration is an input */
-
-static inline int is_in(unsigned long con)
-{
- return con == 0;
-}
-
-/* Test if the given masked+shifted GPIO configuration is an output */
-
-static inline int is_out(unsigned long con)
-{
- return con == 1;
-}
-
-/**
- * s3c2410_pm_restore_gpio() - restore the given GPIO bank
- * @index: The number of the GPIO bank being resumed.
- * @gps: The sleep confgiuration for the bank.
- *
- * Restore one of the GPIO banks that was saved during suspend. This is
- * not as simple as once thought, due to the possibility of glitches
- * from the order that the CON and DAT registers are set in.
- *
- * The three states the pin can be are {IN,OUT,SFN} which gives us 9
- * combinations of changes to check. Three of these, if the pin stays
- * in the same configuration can be discounted. This leaves us with
- * the following:
- *
- * { IN => OUT } Change DAT first
- * { IN => SFN } Change CON first
- * { OUT => SFN } Change CON first, so new data will not glitch
- * { OUT => IN } Change CON first, so new data will not glitch
- * { SFN => IN } Change CON first
- * { SFN => OUT } Change DAT first, so new data will not glitch [1]
- *
- * We do not currently deal with the UP registers as these control
- * weak resistors, so a small delay in change should not need to bring
- * these into the calculations.
- *
- * [1] this assumes that writing to a pin DAT whilst in SFN will set the
- * state for when it is next output.
- */
-
-static void s3c2410_pm_restore_gpio(int index, struct gpio_sleep *gps)
-{
- void __iomem *base = gps->base;
- unsigned long gps_gpcon = gps->gpcon;
- unsigned long gps_gpdat = gps->gpdat;
- unsigned long old_gpcon;
- unsigned long old_gpdat;
- unsigned long old_gpup = 0x0;
- unsigned long gpcon;
- int nr;
-
- old_gpcon = __raw_readl(base + OFFS_CON);
- old_gpdat = __raw_readl(base + OFFS_DAT);
-
- if (base == S3C2410_GPACON) {
- /* GPACON only has one bit per control / data and no PULLUPs.
- * GPACON[x] = 0 => Output, 1 => SFN */
-
- /* first set all SFN bits to SFN */
-
- gpcon = old_gpcon | gps->gpcon;
- __raw_writel(gpcon, base + OFFS_CON);
-
- /* now set all the other bits */
-
- __raw_writel(gps_gpdat, base + OFFS_DAT);
- __raw_writel(gps_gpcon, base + OFFS_CON);
- } else {
- unsigned long old, new, mask;
- unsigned long change_mask = 0x0;
-
- old_gpup = __raw_readl(base + OFFS_UP);
-
- /* Create a change_mask of all the items that need to have
- * their CON value changed before their DAT value, so that
- * we minimise the work between the two settings.
- */
-
- for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) {
- old = (old_gpcon & mask) >> nr;
- new = (gps_gpcon & mask) >> nr;
-
- /* If there is no change, then skip */
-
- if (old == new)
- continue;
-
- /* If both are special function, then skip */
-
- if (is_sfn(old) && is_sfn(new))
- continue;
-
- /* Change is IN => OUT, do not change now */
-
- if (is_in(old) && is_out(new))
- continue;
-
- /* Change is SFN => OUT, do not change now */
-
- if (is_sfn(old) && is_out(new))
- continue;
-
- /* We should now be at the case of IN=>SFN,
- * OUT=>SFN, OUT=>IN, SFN=>IN. */
-
- change_mask |= mask;
- }
-
- /* Write the new CON settings */
-
- gpcon = old_gpcon & ~change_mask;
- gpcon |= gps_gpcon & change_mask;
-
- __raw_writel(gpcon, base + OFFS_CON);
-
- /* Now change any items that require DAT,CON */
-
- __raw_writel(gps_gpdat, base + OFFS_DAT);
- __raw_writel(gps_gpcon, base + OFFS_CON);
- __raw_writel(gps->gpup, base + OFFS_UP);
- }
-
- S3C_PMDBG("GPIO[%d] CON %08lx => %08lx, DAT %08lx => %08lx\n",
- index, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
-}
-
-
-/** s3c2410_pm_restore_gpios()
- *
- * Restore the state of the GPIOs
- */
-
-void s3c_pm_restore_gpios(void)
-{
- struct gpio_sleep *gps = gpio_save;
- int gpio;
-
- for (gpio = 0; gpio < ARRAY_SIZE(gpio_save); gpio++, gps++) {
- s3c2410_pm_restore_gpio(gpio, gps);
- }
-}
void s3c_pm_restore_core(void)
{
diff --git a/arch/arm/plat-s3c64xx/Kconfig b/arch/arm/plat-s3c64xx/Kconfig
index 54375a00a7d2..ad48fd73e04d 100644
--- a/arch/arm/plat-s3c64xx/Kconfig
+++ b/arch/arm/plat-s3c64xx/Kconfig
@@ -19,6 +19,7 @@ config PLAT_S3C64XX
select S3C_GPIO_PULL_UPDOWN
select S3C_GPIO_CFG_S3C24XX
select S3C_GPIO_CFG_S3C64XX
+ select USB_ARCH_HAS_OHCI
help
Base platform code for any Samsung S3C64XX device
diff --git a/arch/arm/plat-s3c64xx/Makefile b/arch/arm/plat-s3c64xx/Makefile
index 2e6d79bf8f33..12ac7a50ab74 100644
--- a/arch/arm/plat-s3c64xx/Makefile
+++ b/arch/arm/plat-s3c64xx/Makefile
@@ -24,6 +24,12 @@ obj-y += gpiolib.o
obj-$(CONFIG_CPU_S3C6400_INIT) += s3c6400-init.o
obj-$(CONFIG_CPU_S3C6400_CLOCK) += s3c6400-clock.o
+# PM support
+
+obj-$(CONFIG_PM) += pm.o
+obj-$(CONFIG_PM) += sleep.o
+obj-$(CONFIG_PM) += irq-pm.o
+
# Device setup
obj-$(CONFIG_S3C64XX_SETUP_I2C0) += setup-i2c0.o
diff --git a/arch/arm/plat-s3c64xx/cpu.c b/arch/arm/plat-s3c64xx/cpu.c
index 91f49a3a665d..f9fdaab32ab4 100644
--- a/arch/arm/plat-s3c64xx/cpu.c
+++ b/arch/arm/plat-s3c64xx/cpu.c
@@ -16,6 +16,7 @@
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
+#include <linux/sysdev.h>
#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <linux/io.h>
@@ -104,6 +105,16 @@ static struct map_desc s3c_iodesc[] __initdata = {
},
};
+
+struct sysdev_class s3c64xx_sysclass = {
+ .name = "s3c64xx-core",
+};
+
+static struct sys_device s3c64xx_sysdev = {
+ .cls = &s3c64xx_sysclass,
+};
+
+
/* read cpu identification code */
void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
@@ -117,3 +128,11 @@ void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
idcode = __raw_readl(S3C_VA_SYS + 0x118);
s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
}
+
+static __init int s3c64xx_sysdev_init(void)
+{
+ sysdev_class_register(&s3c64xx_sysclass);
+ return sysdev_register(&s3c64xx_sysdev);
+}
+
+core_initcall(s3c64xx_sysdev_init);
diff --git a/arch/arm/plat-s3c64xx/gpiolib.c b/arch/arm/plat-s3c64xx/gpiolib.c
index ee9188add8fb..ccb82e854962 100644
--- a/arch/arm/plat-s3c64xx/gpiolib.c
+++ b/arch/arm/plat-s3c64xx/gpiolib.c
@@ -385,12 +385,19 @@ static __init void s3c64xx_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
{
chip->chip.direction_input = s3c64xx_gpiolib_4bit_input;
chip->chip.direction_output = s3c64xx_gpiolib_4bit_output;
+ chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
}
static __init void s3c64xx_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
{
chip->chip.direction_input = s3c64xx_gpiolib_4bit2_input;
chip->chip.direction_output = s3c64xx_gpiolib_4bit2_output;
+ chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
+}
+
+static __init void s3c64xx_gpiolib_add_2bit(struct s3c_gpio_chip *chip)
+{
+ chip->pm = __gpio_pm(&s3c_gpio_pm_2bit);
}
static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips,
@@ -412,7 +419,8 @@ static __init int s3c64xx_gpiolib_init(void)
s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
s3c64xx_gpiolib_add_4bit2);
- s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit), NULL);
+ s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit),
+ s3c64xx_gpiolib_add_2bit);
return 0;
}
diff --git a/arch/arm/plat-s3c64xx/include/plat/irqs.h b/arch/arm/plat-s3c64xx/include/plat/irqs.h
index f865bf4d709e..743a70094d04 100644
--- a/arch/arm/plat-s3c64xx/include/plat/irqs.h
+++ b/arch/arm/plat-s3c64xx/include/plat/irqs.h
@@ -157,6 +157,7 @@
#define S3C_EINT(x) ((x) + S3C_IRQ_EINT_BASE)
#define IRQ_EINT(x) S3C_EINT(x)
+#define IRQ_EINT_BIT(x) ((x) - S3C_EINT(0))
/* Next the external interrupt groups. These are similar to the IRQ_EINT(x)
* that they are sourced from the GPIO pins but with a different scheme for
diff --git a/arch/arm/plat-s3c64xx/include/plat/pm-core.h b/arch/arm/plat-s3c64xx/include/plat/pm-core.h
new file mode 100644
index 000000000000..d347de3ba0dc
--- /dev/null
+++ b/arch/arm/plat-s3c64xx/include/plat/pm-core.h
@@ -0,0 +1,98 @@
+/* linux/arch/arm/plat-s3c64xx/include/plat/pm-core.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX - PM core support for arch/arm/plat-s3c/pm.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 <plat/regs-gpio.h>
+
+static inline void s3c_pm_debug_init_uart(void)
+{
+ u32 tmp = __raw_readl(S3C_PCLK_GATE);
+
+ /* As a note, since the S3C64XX UARTs generally have multiple
+ * clock sources, we simply enable PCLK at the moment and hope
+ * that the resume settings for the UART are suitable for the
+ * use with PCLK.
+ */
+
+ tmp |= S3C_CLKCON_PCLK_UART0;
+ tmp |= S3C_CLKCON_PCLK_UART1;
+ tmp |= S3C_CLKCON_PCLK_UART2;
+ tmp |= S3C_CLKCON_PCLK_UART3;
+
+ __raw_writel(tmp, S3C_PCLK_GATE);
+ udelay(10);
+}
+
+static inline void s3c_pm_arch_prepare_irqs(void)
+{
+ /* VIC should have already been taken care of */
+
+ /* clear any pending EINT0 interrupts */
+ __raw_writel(__raw_readl(S3C64XX_EINT0PEND), S3C64XX_EINT0PEND);
+}
+
+static inline void s3c_pm_arch_stop_clocks(void)
+{
+}
+
+static inline void s3c_pm_arch_show_resume_irqs(void)
+{
+}
+
+/* make these defines, we currently do not have any need to change
+ * the IRQ wake controls depending on the CPU we are running on */
+
+#define s3c_irqwake_eintallow ((1 << 28) - 1)
+#define s3c_irqwake_intallow (0)
+
+static inline void s3c_pm_arch_update_uart(void __iomem *regs,
+ struct pm_uart_save *save)
+{
+ u32 ucon = __raw_readl(regs + S3C2410_UCON);
+ u32 ucon_clk = ucon & S3C6400_UCON_CLKMASK;
+ u32 save_clk = save->ucon & S3C6400_UCON_CLKMASK;
+ u32 new_ucon;
+ u32 delta;
+
+ /* S3C64XX UART blocks only support level interrupts, so ensure that
+ * when we restore unused UART blocks we force the level interrupt
+ * settigs. */
+ save->ucon |= S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL;
+
+ /* We have a constraint on changing the clock type of the UART
+ * between UCLKx and PCLK, so ensure that when we restore UCON
+ * that the CLK field is correctly modified if the bootloader
+ * has changed anything.
+ */
+ if (ucon_clk != save_clk) {
+ new_ucon = save->ucon;
+ delta = ucon_clk ^ save_clk;
+
+ /* change from UCLKx => wrong PCLK,
+ * either UCLK can be tested for by a bit-test
+ * with UCLK0 */
+ if (ucon_clk & S3C6400_UCON_UCLK0 &&
+ !(save_clk & S3C6400_UCON_UCLK0) &&
+ delta & S3C6400_UCON_PCLK2) {
+ new_ucon &= ~S3C6400_UCON_UCLK0;
+ } else if (delta == S3C6400_UCON_PCLK2) {
+ /* as an precaution, don't change from
+ * PCLK2 => PCLK or vice-versa */
+ new_ucon ^= S3C6400_UCON_PCLK2;
+ }
+
+ S3C_PMDBG("ucon change %04x => %04x (save=%04x)\n",
+ ucon, new_ucon, save->ucon);
+ save->ucon = new_ucon;
+ }
+}
diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-clock.h b/arch/arm/plat-s3c64xx/include/plat/regs-clock.h
index b1082c163247..52836d41e333 100644
--- a/arch/arm/plat-s3c64xx/include/plat/regs-clock.h
+++ b/arch/arm/plat-s3c64xx/include/plat/regs-clock.h
@@ -32,6 +32,7 @@
#define S3C_HCLK_GATE S3C_CLKREG(0x30)
#define S3C_PCLK_GATE S3C_CLKREG(0x34)
#define S3C_SCLK_GATE S3C_CLKREG(0x38)
+#define S3C_MEM0_GATE S3C_CLKREG(0x3C)
/* CLKDIV0 */
#define S3C6400_CLKDIV0_MFC_MASK (0xf << 28)
diff --git a/arch/arm/plat-s3c64xx/irq-eint.c b/arch/arm/plat-s3c64xx/irq-eint.c
index 47e5155bb13e..f81b7b818ba0 100644
--- a/arch/arm/plat-s3c64xx/irq-eint.c
+++ b/arch/arm/plat-s3c64xx/irq-eint.c
@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/interrupt.h>
+#include <linux/sysdev.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/io.h>
@@ -26,6 +27,7 @@
#include <mach/map.h>
#include <plat/cpu.h>
+#include <plat/pm.h>
#define eint_offset(irq) ((irq) - IRQ_EINT(0))
#define eint_irq_to_bit(irq) (1 << eint_offset(irq))
@@ -134,6 +136,7 @@ static struct irq_chip s3c_irq_eint = {
.mask_ack = s3c_irq_eint_maskack,
.ack = s3c_irq_eint_ack,
.set_type = s3c_irq_eint_set_type,
+ .set_wake = s3c_irqext_wake,
};
/* s3c_irq_demux_eint
diff --git a/arch/arm/plat-s3c64xx/irq-pm.c b/arch/arm/plat-s3c64xx/irq-pm.c
new file mode 100644
index 000000000000..ca523b5d4c17
--- /dev/null
+++ b/arch/arm/plat-s3c64xx/irq-pm.c
@@ -0,0 +1,111 @@
+/* arch/arm/plat-s3c64xx/irq-pm.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX - Interrupt handling Power Management
+ *
+ * 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/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/serial_core.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <mach/map.h>
+
+#include <plat/regs-serial.h>
+#include <plat/regs-timer.h>
+#include <plat/regs-gpio.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
+
+/* We handled all the IRQ types in this code, to save having to make several
+ * small files to handle each different type separately. Having the EINT_GRP
+ * code here shouldn't be as much bloat as the IRQ table space needed when
+ * they are enabled. The added benefit is we ensure that these registers are
+ * in the same state as we suspended.
+ */
+
+static struct sleep_save irq_save[] = {
+ SAVE_ITEM(S3C64XX_PRIORITY),
+ SAVE_ITEM(S3C64XX_EINT0CON0),
+ SAVE_ITEM(S3C64XX_EINT0CON1),
+ SAVE_ITEM(S3C64XX_EINT0FLTCON0),
+ SAVE_ITEM(S3C64XX_EINT0FLTCON1),
+ SAVE_ITEM(S3C64XX_EINT0FLTCON2),
+ SAVE_ITEM(S3C64XX_EINT0FLTCON3),
+ SAVE_ITEM(S3C64XX_EINT0MASK),
+ SAVE_ITEM(S3C64XX_TINT_CSTAT),
+};
+
+static struct irq_grp_save {
+ u32 fltcon;
+ u32 con;
+ u32 mask;
+} eint_grp_save[5];
+
+static u32 irq_uart_mask[CONFIG_SERIAL_SAMSUNG_UARTS];
+
+static int s3c64xx_irq_pm_suspend(struct sys_device *dev, pm_message_t state)
+{
+ struct irq_grp_save *grp = eint_grp_save;
+ int i;
+
+ S3C_PMDBG("%s: suspending IRQs\n", __func__);
+
+ s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
+
+ for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
+ irq_uart_mask[i] = __raw_readl(S3C_VA_UARTx(i) + S3C64XX_UINTM);
+
+ for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
+ grp->con = __raw_readl(S3C64XX_EINT12CON + (i * 4));
+ grp->mask = __raw_readl(S3C64XX_EINT12MASK + (i * 4));
+ grp->fltcon = __raw_readl(S3C64XX_EINT12FLTCON + (i * 4));
+ }
+
+ return 0;
+}
+
+static int s3c64xx_irq_pm_resume(struct sys_device *dev)
+{
+ struct irq_grp_save *grp = eint_grp_save;
+ int i;
+
+ S3C_PMDBG("%s: resuming IRQs\n", __func__);
+
+ s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
+
+ for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
+ __raw_writel(irq_uart_mask[i], S3C_VA_UARTx(i) + S3C64XX_UINTM);
+
+ for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
+ __raw_writel(grp->con, S3C64XX_EINT12CON + (i * 4));
+ __raw_writel(grp->mask, S3C64XX_EINT12MASK + (i * 4));
+ __raw_writel(grp->fltcon, S3C64XX_EINT12FLTCON + (i * 4));
+ }
+
+ S3C_PMDBG("%s: IRQ configuration restored\n", __func__);
+ return 0;
+}
+
+static struct sysdev_driver s3c64xx_irq_driver = {
+ .suspend = s3c64xx_irq_pm_suspend,
+ .resume = s3c64xx_irq_pm_resume,
+};
+
+static int __init s3c64xx_irq_pm_init(void)
+{
+ return sysdev_driver_register(&s3c64xx_sysclass, &s3c64xx_irq_driver);
+}
+
+arch_initcall(s3c64xx_irq_pm_init);
+
diff --git a/arch/arm/plat-s3c64xx/irq.c b/arch/arm/plat-s3c64xx/irq.c
index f22edf7c2d2d..8dc5b6da9789 100644
--- a/arch/arm/plat-s3c64xx/irq.c
+++ b/arch/arm/plat-s3c64xx/irq.c
@@ -14,12 +14,14 @@
#include <linux/kernel.h>
#include <linux/interrupt.h>
+#include <linux/serial_core.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <asm/hardware/vic.h>
#include <mach/map.h>
+#include <plat/regs-serial.h>
#include <plat/regs-timer.h>
#include <plat/cpu.h>
@@ -135,9 +137,6 @@ static inline unsigned int s3c_irq_uart_bit(unsigned int irq)
}
/* UART interrupt registers, not worth adding to seperate include header */
-#define S3C64XX_UINTP 0x30
-#define S3C64XX_UINTSP 0x34
-#define S3C64XX_UINTM 0x38
static void s3c_irq_uart_mask(unsigned int irq)
{
@@ -233,8 +232,8 @@ void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid)
printk(KERN_DEBUG "%s: initialising interrupts\n", __func__);
/* initialise the pair of VICs */
- vic_init(S3C_VA_VIC0, S3C_VIC0_BASE, vic0_valid);
- vic_init(S3C_VA_VIC1, S3C_VIC1_BASE, vic1_valid);
+ vic_init(S3C_VA_VIC0, S3C_VIC0_BASE, vic0_valid, 0);
+ vic_init(S3C_VA_VIC1, S3C_VIC1_BASE, vic1_valid, 0);
/* add the timer sub-irqs */
diff --git a/arch/arm/plat-s3c64xx/pm.c b/arch/arm/plat-s3c64xx/pm.c
new file mode 100644
index 000000000000..07a6516a4f3c
--- /dev/null
+++ b/arch/arm/plat-s3c64xx/pm.c
@@ -0,0 +1,175 @@
+/* linux/arch/arm/plat-s3c64xx/pm.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX CPU PM support.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/suspend.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+
+#include <mach/map.h>
+
+#include <plat/pm.h>
+#include <plat/regs-sys.h>
+#include <plat/regs-gpio.h>
+#include <plat/regs-clock.h>
+#include <plat/regs-syscon-power.h>
+#include <plat/regs-gpio-memport.h>
+
+#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
+#include <plat/gpio-bank-n.h>
+
+void s3c_pm_debug_smdkled(u32 set, u32 clear)
+{
+ unsigned long flags;
+ u32 reg;
+
+ local_irq_save(flags);
+ reg = __raw_readl(S3C64XX_GPNCON);
+ reg &= ~(S3C64XX_GPN_CONMASK(12) | S3C64XX_GPN_CONMASK(13) |
+ S3C64XX_GPN_CONMASK(14) | S3C64XX_GPN_CONMASK(15));
+ reg |= S3C64XX_GPN_OUTPUT(12) | S3C64XX_GPN_OUTPUT(13) |
+ S3C64XX_GPN_OUTPUT(14) | S3C64XX_GPN_OUTPUT(15);
+ __raw_writel(reg, S3C64XX_GPNCON);
+
+ reg = __raw_readl(S3C64XX_GPNDAT);
+ reg &= ~(clear << 12);
+ reg |= set << 12;
+ __raw_writel(reg, S3C64XX_GPNDAT);
+
+ local_irq_restore(flags);
+}
+#endif
+
+static struct sleep_save core_save[] = {
+ SAVE_ITEM(S3C_APLL_LOCK),
+ SAVE_ITEM(S3C_MPLL_LOCK),
+ SAVE_ITEM(S3C_EPLL_LOCK),
+ SAVE_ITEM(S3C_CLK_SRC),
+ SAVE_ITEM(S3C_CLK_DIV0),
+ SAVE_ITEM(S3C_CLK_DIV1),
+ SAVE_ITEM(S3C_CLK_DIV2),
+ SAVE_ITEM(S3C_CLK_OUT),
+ SAVE_ITEM(S3C_HCLK_GATE),
+ SAVE_ITEM(S3C_PCLK_GATE),
+ SAVE_ITEM(S3C_SCLK_GATE),
+ SAVE_ITEM(S3C_MEM0_GATE),
+
+ SAVE_ITEM(S3C_EPLL_CON1),
+ SAVE_ITEM(S3C_EPLL_CON0),
+
+ SAVE_ITEM(S3C64XX_MEM0DRVCON),
+ SAVE_ITEM(S3C64XX_MEM1DRVCON),
+
+#ifndef CONFIG_CPU_FREQ
+ SAVE_ITEM(S3C_APLL_CON),
+ SAVE_ITEM(S3C_MPLL_CON),
+#endif
+};
+
+static struct sleep_save misc_save[] = {
+ SAVE_ITEM(S3C64XX_AHB_CON0),
+ SAVE_ITEM(S3C64XX_AHB_CON1),
+ SAVE_ITEM(S3C64XX_AHB_CON2),
+
+ SAVE_ITEM(S3C64XX_SPCON),
+
+ SAVE_ITEM(S3C64XX_MEM0CONSTOP),
+ SAVE_ITEM(S3C64XX_MEM1CONSTOP),
+ SAVE_ITEM(S3C64XX_MEM0CONSLP0),
+ SAVE_ITEM(S3C64XX_MEM0CONSLP1),
+ SAVE_ITEM(S3C64XX_MEM1CONSLP),
+};
+
+void s3c_pm_configure_extint(void)
+{
+ __raw_writel(s3c_irqwake_eintmask, S3C64XX_EINT_MASK);
+}
+
+void s3c_pm_restore_core(void)
+{
+ __raw_writel(0, S3C64XX_EINT_MASK);
+
+ s3c_pm_debug_smdkled(1 << 2, 0);
+
+ s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
+ s3c_pm_do_restore(misc_save, ARRAY_SIZE(misc_save));
+}
+
+void s3c_pm_save_core(void)
+{
+ s3c_pm_do_save(misc_save, ARRAY_SIZE(misc_save));
+ s3c_pm_do_save(core_save, ARRAY_SIZE(core_save));
+}
+
+/* since both s3c6400 and s3c6410 share the same sleep pm calls, we
+ * put the per-cpu code in here until any new cpu comes along and changes
+ * this.
+ */
+
+#include <plat/regs-gpio.h>
+
+static void s3c64xx_cpu_suspend(void)
+{
+ unsigned long tmp;
+
+ /* set our standby method to sleep */
+
+ tmp = __raw_readl(S3C64XX_PWR_CFG);
+ tmp &= ~S3C64XX_PWRCFG_CFG_WFI_MASK;
+ tmp |= S3C64XX_PWRCFG_CFG_WFI_SLEEP;
+ __raw_writel(tmp, S3C64XX_PWR_CFG);
+
+ /* clear any old wakeup */
+
+ __raw_writel(__raw_readl(S3C64XX_WAKEUP_STAT),
+ S3C64XX_WAKEUP_STAT);
+
+ /* set the LED state to 0110 over sleep */
+ s3c_pm_debug_smdkled(3 << 1, 0xf);
+
+ /* issue the standby signal into the pm unit. Note, we
+ * issue a write-buffer drain just in case */
+
+ tmp = 0;
+
+ asm("b 1f\n\t"
+ ".align 5\n\t"
+ "1:\n\t"
+ "mcr p15, 0, %0, c7, c10, 5\n\t"
+ "mcr p15, 0, %0, c7, c10, 4\n\t"
+ "mcr p15, 0, %0, c7, c0, 4" :: "r" (tmp));
+
+ /* we should never get past here */
+
+ panic("sleep resumed to originator?");
+}
+
+static void s3c64xx_pm_prepare(void)
+{
+ /* store address of resume. */
+ __raw_writel(virt_to_phys(s3c_cpu_resume), S3C64XX_INFORM0);
+
+ /* ensure previous wakeup state is cleared before sleeping */
+ __raw_writel(__raw_readl(S3C64XX_WAKEUP_STAT), S3C64XX_WAKEUP_STAT);
+}
+
+static int s3c64xx_pm_init(void)
+{
+ pm_cpu_prep = s3c64xx_pm_prepare;
+ pm_cpu_sleep = s3c64xx_cpu_suspend;
+ pm_uart_udivslot = 1;
+ return 0;
+}
+
+arch_initcall(s3c64xx_pm_init);
diff --git a/arch/arm/plat-s3c64xx/sleep.S b/arch/arm/plat-s3c64xx/sleep.S
new file mode 100644
index 000000000000..8e71fe90a373
--- /dev/null
+++ b/arch/arm/plat-s3c64xx/sleep.S
@@ -0,0 +1,144 @@
+/* linux/0arch/arm/plat-s3c64xx/sleep.S
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX CPU sleep 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/linkage.h>
+#include <asm/assembler.h>
+#include <mach/map.h>
+
+#undef S3C64XX_VA_GPIO
+#define S3C64XX_VA_GPIO (0x0)
+
+#include <plat/regs-gpio.h>
+#include <plat/gpio-bank-n.h>
+
+#define LL_UART (S3C_PA_UART + (0x400 * CONFIG_S3C_LOWLEVEL_UART_PORT))
+
+ .text
+
+ /* s3c_cpu_save
+ *
+ * Save enough processor state to allow the restart of the pm.c
+ * code after resume.
+ *
+ * entry:
+ * r0 = pointer to the save block
+ */
+
+ENTRY(s3c_cpu_save)
+ stmfd sp!, { r4 - r12, lr }
+
+ mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
+ mrc p15, 0, r5, c3, c0, 0 @ Domain ID
+ mrc p15, 0, r6, c2, c0, 0 @ Translation Table BASE0
+ mrc p15, 0, r7, c2, c0, 1 @ Translation Table BASE1
+ mrc p15, 0, r8, c2, c0, 2 @ Translation Table Control
+ mrc p15, 0, r9, c1, c0, 0 @ Control register
+ mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register
+ mrc p15, 0, r11, c1, c0, 2 @ Co-processor access controls
+
+ stmia r0, { r4 - r13 } @ Save CP registers and SP
+
+ @@ save our state to ram
+ bl s3c_pm_cb_flushcache
+
+ @@ call final suspend code
+ ldr r0, =pm_cpu_sleep
+ ldr pc, [r0]
+
+ @@ return to the caller, after the MMU is turned on.
+ @@ restore the last bits of the stack and return.
+resume_with_mmu:
+ ldmfd sp!, { r4 - r12, pc } @ return, from sp from s3c_cpu_save
+
+ .data
+
+ /* the next bit is code, but it requires easy access to the
+ * s3c_sleep_save_phys data before the MMU is switched on, so
+ * we store the code that needs this variable in the .data where
+ * the value can be written to (the .text segment is RO).
+ */
+
+ .global s3c_sleep_save_phys
+s3c_sleep_save_phys:
+ .word 0
+
+ /* Sleep magic, the word before the resume entry point so that the
+ * bootloader can check for a resumeable image. */
+
+ .word 0x2bedf00d
+
+ /* s3c_cpu_reusme
+ *
+ * This is the entry point, stored by whatever method the bootloader
+ * requires to get the kernel runnign again. This code expects to be
+ * entered with no caches live and the MMU disabled. It will then
+ * restore the MMU and other basic CP registers saved and restart
+ * the kernel C code to finish the resume code.
+ */
+
+ENTRY(s3c_cpu_resume)
+ msr cpsr_c, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
+ ldr r2, =LL_UART /* for debug */
+
+#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
+ /* Initialise the GPIO state if we are debugging via the SMDK LEDs,
+ * as the uboot version supplied resets these to inputs during the
+ * resume checks.
+ */
+
+ ldr r3, =S3C64XX_PA_GPIO
+ ldr r0, [ r3, #S3C64XX_GPNCON ]
+ bic r0, r0, #(S3C64XX_GPN_CONMASK(12) | S3C64XX_GPN_CONMASK(13) | \
+ S3C64XX_GPN_CONMASK(14) | S3C64XX_GPN_CONMASK(15))
+ orr r0, r0, #(S3C64XX_GPN_OUTPUT(12) | S3C64XX_GPN_OUTPUT(13) | \
+ S3C64XX_GPN_OUTPUT(14) | S3C64XX_GPN_OUTPUT(15))
+ str r0, [ r3, #S3C64XX_GPNCON ]
+
+ ldr r0, [ r3, #S3C64XX_GPNDAT ]
+ bic r0, r0, #0xf << 12 @ GPN12..15
+ orr r0, r0, #1 << 15 @ GPN15
+ str r0, [ r3, #S3C64XX_GPNDAT ]
+#endif
+
+ /* __v6_setup from arch/arm/mm/proc-v6.S, ensure that the caches
+ * are thoroughly cleaned just in case the bootloader didn't do it
+ * for us. */
+ mov r0, #0
+ mcr p15, 0, r0, c7, c14, 0 @ clean+invalidate D cache
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
+ mcr p15, 0, r0, c7, c15, 0 @ clean+invalidate cache
+ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
+ @@mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs
+ @@mcr p15, 0, r0, c7, c7, 0 @ Invalidate I + D caches
+
+ ldr r0, s3c_sleep_save_phys
+ ldmia r0, { r4 - r13 }
+
+ mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID
+ mcr p15, 0, r5, c3, c0, 0 @ Domain ID
+ mcr p15, 0, r6, c2, c0, 0 @ Translation Table BASE0
+ mcr p15, 0, r7, c2, c0, 1 @ Translation Table BASE1
+ mcr p15, 0, r8, c2, c0, 2 @ Translation Table Control
+ mcr p15, 0, r10, c1, c0, 1 @ Auxiliary control register
+
+ mov r0, #0 @ restore copro access controls
+ mcr p15, 0, r11, c1, c0, 2 @ Co-processor access controls
+ mcr p15, 0, r0, c7, c5, 4
+
+ ldr r2, =resume_with_mmu
+ mcr p15, 0, r9, c1, c0, 0 /* turn mmu back on */
+ nop
+ mov pc, r2 /* jump back */
+
+ .end
diff --git a/arch/arm/plat-stmp3xxx/Kconfig b/arch/arm/plat-stmp3xxx/Kconfig
new file mode 100644
index 000000000000..2cf37c35951b
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/Kconfig
@@ -0,0 +1,37 @@
+if ARCH_STMP3XXX
+
+menu "Freescale STMP3xxx implementations"
+
+choice
+ prompt "Select STMP3xxx chip family"
+
+config ARCH_STMP37XX
+ bool "Freescale SMTP37xx"
+ select CPU_ARM926T
+ ---help---
+ STMP37xx refers to 3700 through 3769 chips
+
+config ARCH_STMP378X
+ bool "Freescale STMP378x"
+ select CPU_ARM926T
+ ---help---
+ STMP378x refers to 3780 through 3789 chips
+
+endchoice
+
+choice
+ prompt "Select STMP3xxx board type"
+
+config MACH_STMP37XX
+ depends on ARCH_STMP37XX
+ bool "Freescale STMP37xx development board"
+
+config MACH_STMP378X
+ depends on ARCH_STMP378X
+ bool "Freescale STMP378x development board"
+
+endchoice
+
+endmenu
+
+endif
diff --git a/arch/arm/plat-stmp3xxx/Makefile b/arch/arm/plat-stmp3xxx/Makefile
new file mode 100644
index 000000000000..b63480066d6b
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the linux kernel.
+#
+# Object file lists.
+obj-y += core.o timer.o irq.o dma.o clock.o pinmux.o
diff --git a/arch/arm/plat-stmp3xxx/clock.c b/arch/arm/plat-stmp3xxx/clock.c
new file mode 100644
index 000000000000..9a1d46b470cd
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/clock.c
@@ -0,0 +1,1112 @@
+/*
+ * Clock manipulation routines for Freescale STMP37XX/STMP378X
+ *
+ * Author: Vitaly Wool <vital@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <asm/mach-types.h>
+#include <asm/clkdev.h>
+#include <mach/regs-clkctrl.h>
+
+#include "clock.h"
+
+static DEFINE_SPINLOCK(clocks_lock);
+
+static struct clk osc_24M;
+static struct clk pll_clk;
+static struct clk cpu_clk;
+static struct clk hclk;
+
+static int propagate_rate(struct clk *);
+
+static inline int clk_is_busy(struct clk *clk)
+{
+ return __raw_readl(clk->busy_reg) & (1 << clk->busy_bit);
+}
+
+static inline int clk_good(struct clk *clk)
+{
+ return clk && !IS_ERR(clk) && clk->ops;
+}
+
+static int std_clk_enable(struct clk *clk)
+{
+ if (clk->enable_reg) {
+ u32 clk_reg = __raw_readl(clk->enable_reg);
+ if (clk->enable_negate)
+ clk_reg &= ~(1 << clk->enable_shift);
+ else
+ clk_reg |= (1 << clk->enable_shift);
+ __raw_writel(clk_reg, clk->enable_reg);
+ if (clk->enable_wait)
+ udelay(clk->enable_wait);
+ return 0;
+ } else
+ return -EINVAL;
+}
+
+static int std_clk_disable(struct clk *clk)
+{
+ if (clk->enable_reg) {
+ u32 clk_reg = __raw_readl(clk->enable_reg);
+ if (clk->enable_negate)
+ clk_reg |= (1 << clk->enable_shift);
+ else
+ clk_reg &= ~(1 << clk->enable_shift);
+ __raw_writel(clk_reg, clk->enable_reg);
+ return 0;
+ } else
+ return -EINVAL;
+}
+
+static int io_set_rate(struct clk *clk, u32 rate)
+{
+ u32 reg_frac, clkctrl_frac;
+ int i, ret = 0, mask = 0x1f;
+
+ clkctrl_frac = (clk->parent->rate * 18 + rate - 1) / rate;
+
+ if (clkctrl_frac < 18 || clkctrl_frac > 35) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ reg_frac = __raw_readl(clk->scale_reg);
+ reg_frac &= ~(mask << clk->scale_shift);
+ __raw_writel(reg_frac | (clkctrl_frac << clk->scale_shift),
+ clk->scale_reg);
+ if (clk->busy_reg) {
+ for (i = 10000; i; i--)
+ if (!clk_is_busy(clk))
+ break;
+ if (!i)
+ ret = -ETIMEDOUT;
+ else
+ ret = 0;
+ }
+out:
+ return ret;
+}
+
+static long io_get_rate(struct clk *clk)
+{
+ long rate = clk->parent->rate * 18;
+ int mask = 0x1f;
+
+ rate /= (__raw_readl(clk->scale_reg) >> clk->scale_shift) & mask;
+ clk->rate = rate;
+
+ return rate;
+}
+
+static long per_get_rate(struct clk *clk)
+{
+ long rate = clk->parent->rate;
+ long div;
+ const int mask = 0xff;
+
+ if (clk->enable_reg &&
+ !(__raw_readl(clk->enable_reg) & clk->enable_shift))
+ clk->rate = 0;
+ else {
+ div = (__raw_readl(clk->scale_reg) >> clk->scale_shift) & mask;
+ if (div)
+ rate /= div;
+ clk->rate = rate;
+ }
+
+ return clk->rate;
+}
+
+static int per_set_rate(struct clk *clk, u32 rate)
+{
+ int ret = -EINVAL;
+ int div = (clk->parent->rate + rate - 1) / rate;
+ u32 reg_frac;
+ const int mask = 0xff;
+ int try = 10;
+ int i = -1;
+
+ if (div == 0 || div > mask)
+ goto out;
+
+ reg_frac = __raw_readl(clk->scale_reg);
+ reg_frac &= ~(mask << clk->scale_shift);
+
+ while (try--) {
+ __raw_writel(reg_frac | (div << clk->scale_shift),
+ clk->scale_reg);
+
+ if (clk->busy_reg) {
+ for (i = 10000; i; i--)
+ if (!clk_is_busy(clk))
+ break;
+ }
+ if (i)
+ break;
+ }
+
+ if (!i)
+ ret = -ETIMEDOUT;
+ else
+ ret = 0;
+
+out:
+ if (ret != 0)
+ printk(KERN_ERR "%s: error %d\n", __func__, ret);
+ return ret;
+}
+
+static long lcdif_get_rate(struct clk *clk)
+{
+ long rate = clk->parent->rate;
+ long div;
+ const int mask = 0xff;
+
+ div = (__raw_readl(clk->scale_reg) >> clk->scale_shift) & mask;
+ if (div) {
+ rate /= div;
+ div = (HW_CLKCTRL_FRAC_RD() & BM_CLKCTRL_FRAC_PIXFRAC) >>
+ BP_CLKCTRL_FRAC_PIXFRAC;
+ rate /= div;
+ }
+ clk->rate = rate;
+
+ return rate;
+}
+
+static int lcdif_set_rate(struct clk *clk, u32 rate)
+{
+ int ret = 0;
+ /*
+ * On 3700, we can get most timings exact by modifying ref_pix
+ * and the divider, but keeping the phase timings at 1 (2
+ * phases per cycle).
+ *
+ * ref_pix can be between 480e6*18/35=246.9MHz and 480e6*18/18=480MHz,
+ * which is between 18/(18*480e6)=2.084ns and 35/(18*480e6)=4.050ns.
+ *
+ * ns_cycle >= 2*18e3/(18*480) = 25/6
+ * ns_cycle <= 2*35e3/(18*480) = 875/108
+ *
+ * Multiply the ns_cycle by 'div' to lengthen it until it fits the
+ * bounds. This is the divider we'll use after ref_pix.
+ *
+ * 6 * ns_cycle >= 25 * div
+ * 108 * ns_cycle <= 875 * div
+ */
+ u32 ns_cycle = 1000000 / rate;
+ u32 div, reg_val;
+ u32 lowest_result = (u32) -1;
+ u32 lowest_div = 0, lowest_fracdiv = 0;
+
+ for (div = 1; div < 256; ++div) {
+ u32 fracdiv;
+ u32 ps_result;
+ int lower_bound = 6 * ns_cycle >= 25 * div;
+ int upper_bound = 108 * ns_cycle <= 875 * div;
+ if (!lower_bound)
+ break;
+ if (!upper_bound)
+ continue;
+ /*
+ * Found a matching div. Calculate fractional divider needed,
+ * rounded up.
+ */
+ fracdiv = ((clk->parent->rate / 1000 * 18 / 2) *
+ ns_cycle + 1000 * div - 1) /
+ (1000 * div);
+ if (fracdiv < 18 || fracdiv > 35) {
+ ret = -EINVAL;
+ goto out;
+ }
+ /* Calculate the actual cycle time this results in */
+ ps_result = 6250 * div * fracdiv / 27;
+
+ /* Use the fastest result that doesn't break ns_cycle */
+ if (ps_result <= lowest_result) {
+ lowest_result = ps_result;
+ lowest_div = div;
+ lowest_fracdiv = fracdiv;
+ }
+ }
+
+ if (div >= 256 || lowest_result == (u32) -1) {
+ ret = -EINVAL;
+ goto out;
+ }
+ pr_debug("Programming PFD=%u,DIV=%u ref_pix=%uMHz "
+ "PIXCLK=%uMHz cycle=%u.%03uns\n",
+ lowest_fracdiv, lowest_div,
+ 480*18/lowest_fracdiv, 480*18/lowest_fracdiv/lowest_div,
+ lowest_result / 1000, lowest_result % 1000);
+
+ /* Program ref_pix phase fractional divider */
+ HW_CLKCTRL_FRAC_WR((HW_CLKCTRL_FRAC_RD() & ~BM_CLKCTRL_FRAC_PIXFRAC) |
+ BF_CLKCTRL_FRAC_PIXFRAC(lowest_fracdiv));
+ /* Ungate PFD */
+ HW_CLKCTRL_FRAC_CLR(BM_CLKCTRL_FRAC_CLKGATEPIX);
+
+ /* Program pix divider */
+ reg_val = __raw_readl(clk->scale_reg);
+ reg_val &= ~(BM_CLKCTRL_PIX_DIV | BM_CLKCTRL_PIX_CLKGATE);
+ reg_val |= BF_CLKCTRL_PIX_DIV(lowest_div);
+ __raw_writel(reg_val, clk->scale_reg);
+
+ /* Wait for divider update */
+ if (clk->busy_reg) {
+ int i;
+ for (i = 10000; i; i--)
+ if (!clk_is_busy(clk))
+ break;
+ if (!i) {
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+ }
+
+ /* Switch to ref_pix source */
+ HW_CLKCTRL_CLKSEQ_CLR(BM_CLKCTRL_CLKSEQ_BYPASS_PIX);
+
+out:
+ return ret;
+}
+
+
+static int cpu_set_rate(struct clk *clk, u32 rate)
+{
+ if (rate < 24000)
+ return -EINVAL;
+ else if (rate == 24000) {
+ /* switch to the 24M source */
+ clk_set_parent(clk, &osc_24M);
+ } else {
+ int i;
+ u32 clkctrl_cpu = 1;
+ u32 c = clkctrl_cpu;
+ u32 clkctrl_frac = 1;
+ u32 val;
+ for ( ; c < 0x40; c++) {
+ u32 f = (pll_clk.rate*18/c + rate/2) / rate;
+ int s1, s2;
+
+ if (f < 18 || f > 35)
+ continue;
+ s1 = pll_clk.rate*18/clkctrl_frac/clkctrl_cpu - rate;
+ s2 = pll_clk.rate*18/c/f - rate;
+ pr_debug("%s: s1 %d, s2 %d\n", __func__, s1, s2);
+ if (abs(s1) > abs(s2)) {
+ clkctrl_cpu = c;
+ clkctrl_frac = f;
+ }
+ if (s2 == 0)
+ break;
+ };
+ pr_debug("%s: clkctrl_cpu %d, clkctrl_frac %d\n", __func__,
+ clkctrl_cpu, clkctrl_frac);
+ if (c == 0x40) {
+ int d = pll_clk.rate*18/clkctrl_frac/clkctrl_cpu -
+ rate;
+ if (abs(d) > 100 ||
+ clkctrl_frac < 18 || clkctrl_frac > 35)
+ return -EINVAL;
+ }
+
+ /* 4.6.2 */
+ val = __raw_readl(clk->scale_reg);
+ val &= ~(0x3f << clk->scale_shift);
+ val |= clkctrl_frac;
+ clk_set_parent(clk, &osc_24M);
+ udelay(10);
+ __raw_writel(val, clk->scale_reg);
+ /* ungate */
+ __raw_writel(1<<7, clk->scale_reg + 8);
+ /* write clkctrl_cpu */
+ clk->saved_div = clkctrl_cpu;
+ HW_CLKCTRL_CPU_WR((HW_CLKCTRL_CPU_RD() & ~0x3f) | clkctrl_cpu);
+ for (i = 10000; i; i--)
+ if (!clk_is_busy(clk))
+ break;
+ if (!i) {
+ printk(KERN_ERR "couldn't set up CPU divisor\n");
+ return -ETIMEDOUT;
+ }
+ clk_set_parent(clk, &pll_clk);
+ clk->saved_div = 0;
+ udelay(10);
+ }
+ return 0;
+}
+
+static long cpu_get_rate(struct clk *clk)
+{
+ long rate = clk->parent->rate * 18;
+
+ rate /= (__raw_readl(clk->scale_reg) >> clk->scale_shift) & 0x3f;
+ rate /= HW_CLKCTRL_CPU_RD() & 0x3f;
+ rate = ((rate + 9) / 10) * 10;
+ clk->rate = rate;
+
+ return rate;
+}
+
+static long cpu_round_rate(struct clk *clk, u32 rate)
+{
+ unsigned long r = 0;
+
+ if (rate <= 24000)
+ r = 24000;
+ else {
+ u32 clkctrl_cpu = 1;
+ u32 clkctrl_frac;
+ do {
+ clkctrl_frac =
+ (pll_clk.rate*18 / clkctrl_cpu + rate/2) / rate;
+ if (clkctrl_frac > 35)
+ continue;
+ if (pll_clk.rate*18 / clkctrl_frac / clkctrl_cpu/10 ==
+ rate / 10)
+ break;
+ } while (pll_clk.rate / 2 >= clkctrl_cpu++ * rate);
+ if (pll_clk.rate / 2 < (clkctrl_cpu - 1) * rate)
+ clkctrl_cpu--;
+ pr_debug("%s: clkctrl_cpu %d, clkctrl_frac %d\n", __func__,
+ clkctrl_cpu, clkctrl_frac);
+ if (clkctrl_frac < 18)
+ clkctrl_frac = 18;
+ if (clkctrl_frac > 35)
+ clkctrl_frac = 35;
+
+ r = pll_clk.rate * 18;
+ r /= clkctrl_frac;
+ r /= clkctrl_cpu;
+ r = 10 * ((r + 9) / 10);
+ }
+ return r;
+}
+
+static long emi_get_rate(struct clk *clk)
+{
+ long rate = clk->parent->rate * 18;
+
+ rate /= (__raw_readl(clk->scale_reg) >> clk->scale_shift) & 0x3f;
+ rate /= HW_CLKCTRL_EMI_RD() & 0x3f;
+ clk->rate = rate;
+
+ return rate;
+}
+
+static int clkseq_set_parent(struct clk *clk, struct clk *parent)
+{
+ int ret = -EINVAL;
+ int shift = 8;
+
+ /* bypass? */
+ if (parent == &osc_24M)
+ shift = 4;
+
+ if (clk->bypass_reg) {
+ u32 hbus_mask = BM_CLKCTRL_HBUS_DIV_FRAC_EN |
+ BM_CLKCTRL_HBUS_DIV;
+
+ if (clk == &cpu_clk && shift == 4) {
+ u32 hbus_val = HW_CLKCTRL_HBUS_RD();
+ u32 cpu_val = HW_CLKCTRL_CPU_RD();
+ hbus_val &= ~hbus_mask;
+ hbus_val |= 1;
+ clk->saved_div = cpu_val & BM_CLKCTRL_CPU_DIV_CPU;
+ cpu_val &= ~BM_CLKCTRL_CPU_DIV_CPU;
+ cpu_val |= 1;
+ __raw_writel(1 << clk->bypass_shift,
+ clk->bypass_reg + shift);
+ if (machine_is_stmp378x()) {
+ HW_CLKCTRL_HBUS_WR(hbus_val);
+ HW_CLKCTRL_CPU_WR(cpu_val);
+ hclk.rate = 0;
+ }
+ } else if (clk == &cpu_clk && shift == 8) {
+ u32 hbus_val = HW_CLKCTRL_HBUS_RD();
+ u32 cpu_val = HW_CLKCTRL_CPU_RD();
+ hbus_val &= ~hbus_mask;
+ hbus_val |= 2;
+ cpu_val &= ~BM_CLKCTRL_CPU_DIV_CPU;
+ if (clk->saved_div)
+ cpu_val |= clk->saved_div;
+ else
+ cpu_val |= 2;
+ if (machine_is_stmp378x()) {
+ HW_CLKCTRL_HBUS_WR(hbus_val);
+ HW_CLKCTRL_CPU_WR(cpu_val);
+ hclk.rate = 0;
+ }
+ __raw_writel(1 << clk->bypass_shift,
+ clk->bypass_reg + shift);
+ } else
+ __raw_writel(1 << clk->bypass_shift,
+ clk->bypass_reg + shift);
+
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static int hbus_set_rate(struct clk *clk, u32 rate)
+{
+ u8 div = 0;
+ int is_frac = 0;
+ u32 clkctrl_hbus;
+ struct clk *parent = clk->parent;
+
+ pr_debug("%s: rate %d, parent rate %d\n", __func__, rate,
+ parent->rate);
+
+ if (rate > parent->rate)
+ return -EINVAL;
+
+ if (((parent->rate + rate/2) / rate) * rate != parent->rate &&
+ parent->rate / rate < 32) {
+ pr_debug("%s: switching to fractional mode\n", __func__);
+ is_frac = 1;
+ }
+
+ if (is_frac)
+ div = (32 * rate + parent->rate / 2) / parent->rate;
+ else
+ div = (parent->rate + rate - 1) / rate;
+ pr_debug("%s: div calculated is %d\n", __func__, div);
+ if (!div || div > 0x1f)
+ return -EINVAL;
+
+ clk_set_parent(&cpu_clk, &osc_24M);
+ udelay(10);
+ clkctrl_hbus = __raw_readl(clk->scale_reg);
+ clkctrl_hbus &= ~0x3f;
+ clkctrl_hbus |= div;
+ clkctrl_hbus |= (is_frac << 5);
+
+ __raw_writel(clkctrl_hbus, clk->scale_reg);
+ if (clk->busy_reg) {
+ int i;
+ for (i = 10000; i; i--)
+ if (!clk_is_busy(clk))
+ break;
+ if (!i) {
+ printk(KERN_ERR "couldn't set up CPU divisor\n");
+ return -ETIMEDOUT;
+ }
+ }
+ clk_set_parent(&cpu_clk, &pll_clk);
+ __raw_writel(clkctrl_hbus, clk->scale_reg);
+ udelay(10);
+ return 0;
+}
+
+static long hbus_get_rate(struct clk *clk)
+{
+ long rate = clk->parent->rate;
+
+ if (__raw_readl(clk->scale_reg) & 0x20) {
+ rate *= __raw_readl(clk->scale_reg) & 0x1f;
+ rate /= 32;
+ } else
+ rate /= __raw_readl(clk->scale_reg) & 0x1f;
+ clk->rate = rate;
+
+ return rate;
+}
+
+static int xbus_set_rate(struct clk *clk, u32 rate)
+{
+ u16 div = 0;
+ u32 clkctrl_xbus;
+
+ pr_debug("%s: rate %d, parent rate %d\n", __func__, rate,
+ clk->parent->rate);
+
+ div = (clk->parent->rate + rate - 1) / rate;
+ pr_debug("%s: div calculated is %d\n", __func__, div);
+ if (!div || div > 0x3ff)
+ return -EINVAL;
+
+ clkctrl_xbus = __raw_readl(clk->scale_reg);
+ clkctrl_xbus &= ~0x3ff;
+ clkctrl_xbus |= div;
+ __raw_writel(clkctrl_xbus, clk->scale_reg);
+ if (clk->busy_reg) {
+ int i;
+ for (i = 10000; i; i--)
+ if (!clk_is_busy(clk))
+ break;
+ if (!i) {
+ printk(KERN_ERR "couldn't set up xbus divisor\n");
+ return -ETIMEDOUT;
+ }
+ }
+ return 0;
+}
+
+static long xbus_get_rate(struct clk *clk)
+{
+ long rate = clk->parent->rate;
+
+ rate /= __raw_readl(clk->scale_reg) & 0x3ff;
+ clk->rate = rate;
+
+ return rate;
+}
+
+
+/* Clock ops */
+
+static struct clk_ops std_ops = {
+ .enable = std_clk_enable,
+ .disable = std_clk_disable,
+ .get_rate = per_get_rate,
+ .set_rate = per_set_rate,
+ .set_parent = clkseq_set_parent,
+};
+
+static struct clk_ops min_ops = {
+ .enable = std_clk_enable,
+ .disable = std_clk_disable,
+};
+
+static struct clk_ops cpu_ops = {
+ .enable = std_clk_enable,
+ .disable = std_clk_disable,
+ .get_rate = cpu_get_rate,
+ .set_rate = cpu_set_rate,
+ .round_rate = cpu_round_rate,
+ .set_parent = clkseq_set_parent,
+};
+
+static struct clk_ops io_ops = {
+ .enable = std_clk_enable,
+ .disable = std_clk_disable,
+ .get_rate = io_get_rate,
+ .set_rate = io_set_rate,
+};
+
+static struct clk_ops hbus_ops = {
+ .get_rate = hbus_get_rate,
+ .set_rate = hbus_set_rate,
+};
+
+static struct clk_ops xbus_ops = {
+ .get_rate = xbus_get_rate,
+ .set_rate = xbus_set_rate,
+};
+
+static struct clk_ops lcdif_ops = {
+ .enable = std_clk_enable,
+ .disable = std_clk_disable,
+ .get_rate = lcdif_get_rate,
+ .set_rate = lcdif_set_rate,
+ .set_parent = clkseq_set_parent,
+};
+
+static struct clk_ops emi_ops = {
+ .get_rate = emi_get_rate,
+};
+
+/* List of on-chip clocks */
+
+static struct clk osc_24M = {
+ .flags = FIXED_RATE | ENABLED,
+ .rate = 24000,
+};
+
+static struct clk pll_clk = {
+ .parent = &osc_24M,
+ .enable_reg = HW_CLKCTRL_PLLCTRL0_ADDR,
+ .enable_shift = 16,
+ .enable_wait = 10,
+ .flags = FIXED_RATE | ENABLED,
+ .rate = 480000,
+ .ops = &min_ops,
+};
+
+static struct clk cpu_clk = {
+ .parent = &pll_clk,
+ .scale_reg = HW_CLKCTRL_FRAC_ADDR,
+ .scale_shift = 0,
+ .bypass_reg = HW_CLKCTRL_CLKSEQ_ADDR,
+ .bypass_shift = 7,
+ .busy_reg = HW_CLKCTRL_CPU_ADDR,
+ .busy_bit = 28,
+ .flags = RATE_PROPAGATES | ENABLED,
+ .ops = &cpu_ops,
+};
+
+static struct clk io_clk = {
+ .parent = &pll_clk,
+ .enable_reg = HW_CLKCTRL_FRAC_ADDR,
+ .enable_shift = 31,
+ .enable_negate = 1,
+ .scale_reg = HW_CLKCTRL_FRAC_ADDR,
+ .scale_shift = 24,
+ .flags = RATE_PROPAGATES | ENABLED,
+ .ops = &io_ops,
+};
+
+static struct clk hclk = {
+ .parent = &cpu_clk,
+ .scale_reg = HW_CLKCTRL_HBUS_ADDR,
+ .bypass_reg = HW_CLKCTRL_CLKSEQ_ADDR,
+ .bypass_shift = 7,
+ .busy_reg = HW_CLKCTRL_HBUS_ADDR,
+ .busy_bit = 29,
+ .flags = RATE_PROPAGATES | ENABLED,
+ .ops = &hbus_ops,
+};
+
+static struct clk xclk = {
+ .parent = &osc_24M,
+ .scale_reg = HW_CLKCTRL_XBUS_ADDR,
+ .busy_reg = HW_CLKCTRL_XBUS_ADDR,
+ .busy_bit = 31,
+ .flags = RATE_PROPAGATES | ENABLED,
+ .ops = &xbus_ops,
+};
+
+static struct clk uart_clk = {
+ .parent = &xclk,
+ .enable_reg = HW_CLKCTRL_XTAL_ADDR,
+ .enable_shift = 31,
+ .enable_negate = 1,
+ .flags = ENABLED,
+ .ops = &min_ops,
+};
+
+static struct clk audio_clk = {
+ .parent = &xclk,
+ .enable_reg = HW_CLKCTRL_XTAL_ADDR,
+ .enable_shift = 30,
+ .enable_negate = 1,
+ .ops = &min_ops,
+};
+
+static struct clk pwm_clk = {
+ .parent = &xclk,
+ .enable_reg = HW_CLKCTRL_XTAL_ADDR,
+ .enable_shift = 29,
+ .enable_negate = 1,
+ .ops = &min_ops,
+};
+
+static struct clk dri_clk = {
+ .parent = &xclk,
+ .enable_reg = HW_CLKCTRL_XTAL_ADDR,
+ .enable_shift = 28,
+ .enable_negate = 1,
+ .ops = &min_ops,
+};
+
+static struct clk digctl_clk = {
+ .parent = &xclk,
+ .enable_reg = HW_CLKCTRL_XTAL_ADDR,
+ .enable_shift = 27,
+ .enable_negate = 1,
+ .ops = &min_ops,
+};
+
+static struct clk timer_clk = {
+ .parent = &xclk,
+ .enable_reg = HW_CLKCTRL_XTAL_ADDR,
+ .enable_shift = 26,
+ .enable_negate = 1,
+ .flags = ENABLED,
+ .ops = &min_ops,
+};
+
+static struct clk lcdif_clk = {
+ .parent = &pll_clk,
+ .scale_reg = HW_CLKCTRL_PIX_ADDR,
+ .busy_reg = HW_CLKCTRL_PIX_ADDR,
+ .busy_bit = 29,
+ .enable_reg = HW_CLKCTRL_PIX_ADDR,
+ .enable_shift = 31,
+ .enable_negate = 1,
+ .bypass_reg = HW_CLKCTRL_CLKSEQ_ADDR,
+ .bypass_shift = 1,
+ .flags = NEEDS_SET_PARENT,
+ .ops = &lcdif_ops,
+};
+
+static struct clk ssp_clk = {
+ .parent = &io_clk,
+ .scale_reg = HW_CLKCTRL_SSP_ADDR,
+ .busy_reg = HW_CLKCTRL_SSP_ADDR,
+ .busy_bit = 29,
+ .enable_reg = HW_CLKCTRL_SSP_ADDR,
+ .enable_shift = 31,
+ .bypass_reg = HW_CLKCTRL_CLKSEQ_ADDR,
+ .bypass_shift = 5,
+ .enable_negate = 1,
+ .flags = NEEDS_SET_PARENT,
+ .ops = &std_ops,
+};
+
+static struct clk gpmi_clk = {
+ .parent = &io_clk,
+ .scale_reg = HW_CLKCTRL_GPMI_ADDR,
+ .busy_reg = HW_CLKCTRL_GPMI_ADDR,
+ .busy_bit = 29,
+ .enable_reg = HW_CLKCTRL_GPMI_ADDR,
+ .enable_shift = 31,
+ .enable_negate = 1,
+ .bypass_reg = HW_CLKCTRL_CLKSEQ_ADDR,
+ .bypass_shift = 4,
+ .flags = NEEDS_SET_PARENT,
+ .ops = &std_ops,
+};
+
+static struct clk spdif_clk = {
+ .parent = &pll_clk,
+ .enable_reg = HW_CLKCTRL_SPDIF_ADDR,
+ .enable_shift = 31,
+ .enable_negate = 1,
+ .ops = &min_ops,
+};
+
+static struct clk emi_clk = {
+ .parent = &pll_clk,
+ .enable_reg = HW_CLKCTRL_EMI_ADDR,
+ .enable_shift = 31,
+ .enable_negate = 1,
+ .scale_reg = HW_CLKCTRL_FRAC_ADDR,
+ .scale_shift = 8,
+ .busy_reg = HW_CLKCTRL_EMI_ADDR,
+ .busy_bit = 28,
+ .bypass_reg = HW_CLKCTRL_CLKSEQ_ADDR,
+ .bypass_shift = 6,
+ .flags = ENABLED,
+ .ops = &emi_ops,
+};
+
+static struct clk ir_clk = {
+ .parent = &io_clk,
+ .enable_reg = HW_CLKCTRL_IR_ADDR,
+ .enable_shift = 31,
+ .enable_negate = 1,
+ .bypass_reg = HW_CLKCTRL_CLKSEQ_ADDR,
+ .bypass_shift = 3,
+ .ops = &min_ops,
+};
+
+static struct clk saif_clk = {
+ .parent = &pll_clk,
+ .scale_reg = HW_CLKCTRL_SAIF_ADDR,
+ .busy_reg = HW_CLKCTRL_SAIF_ADDR,
+ .busy_bit = 29,
+ .enable_reg = HW_CLKCTRL_SAIF_ADDR,
+ .enable_shift = 31,
+ .enable_negate = 1,
+ .bypass_reg = HW_CLKCTRL_CLKSEQ_ADDR,
+ .bypass_shift = 0,
+ .ops = &std_ops,
+};
+
+static struct clk usb_clk = {
+ .parent = &pll_clk,
+ .enable_reg = HW_CLKCTRL_PLLCTRL0_ADDR,
+ .enable_shift = 18,
+ .enable_negate = 1,
+ .ops = &min_ops,
+};
+
+/* list of all the clocks */
+static __initdata struct clk_lookup onchip_clks[] = {
+ {
+ .con_id = "osc_24M",
+ .clk = &osc_24M,
+ }, {
+ .con_id = "pll",
+ .clk = &pll_clk,
+ }, {
+ .con_id = "cpu",
+ .clk = &cpu_clk,
+ }, {
+ .con_id = "hclk",
+ .clk = &hclk,
+ }, {
+ .con_id = "xclk",
+ .clk = &xclk,
+ }, {
+ .con_id = "io",
+ .clk = &io_clk,
+ }, {
+ .con_id = "uart",
+ .clk = &uart_clk,
+ }, {
+ .con_id = "audio",
+ .clk = &audio_clk,
+ }, {
+ .con_id = "pwm",
+ .clk = &pwm_clk,
+ }, {
+ .con_id = "dri",
+ .clk = &dri_clk,
+ }, {
+ .con_id = "digctl",
+ .clk = &digctl_clk,
+ }, {
+ .con_id = "timer",
+ .clk = &timer_clk,
+ }, {
+ .con_id = "lcdif",
+ .clk = &lcdif_clk,
+ }, {
+ .con_id = "ssp",
+ .clk = &ssp_clk,
+ }, {
+ .con_id = "gpmi",
+ .clk = &gpmi_clk,
+ }, {
+ .con_id = "spdif",
+ .clk = &spdif_clk,
+ }, {
+ .con_id = "emi",
+ .clk = &emi_clk,
+ }, {
+ .con_id = "ir",
+ .clk = &ir_clk,
+ }, {
+ .con_id = "saif",
+ .clk = &saif_clk,
+ }, {
+ .con_id = "usb",
+ .clk = &usb_clk,
+ },
+};
+
+static int __init propagate_rate(struct clk *clk)
+{
+ struct clk_lookup *cl;
+
+ for (cl = onchip_clks; cl < onchip_clks + ARRAY_SIZE(onchip_clks);
+ cl++) {
+ if (unlikely(!clk_good(cl->clk)))
+ continue;
+ if (cl->clk->parent == clk && cl->clk->ops->get_rate) {
+ cl->clk->ops->get_rate(cl->clk);
+ if (cl->clk->flags & RATE_PROPAGATES)
+ propagate_rate(cl->clk);
+ }
+ }
+
+ return 0;
+}
+
+/* Exported API */
+unsigned long clk_get_rate(struct clk *clk)
+{
+ if (unlikely(!clk_good(clk)))
+ return 0;
+
+ if (clk->rate != 0)
+ return clk->rate;
+
+ if (clk->ops->get_rate != NULL)
+ return clk->ops->get_rate(clk);
+
+ return clk_get_rate(clk->parent);
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ if (unlikely(!clk_good(clk)))
+ return 0;
+
+ if (clk->ops->round_rate)
+ return clk->ops->round_rate(clk, rate);
+
+ return 0;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+static inline int close_enough(long rate1, long rate2)
+{
+ return rate1 && !((rate2 - rate1) * 1000 / rate1);
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ int ret = -EINVAL;
+
+ if (unlikely(!clk_good(clk)))
+ goto out;
+
+ if (clk->flags & FIXED_RATE || !clk->ops->set_rate)
+ goto out;
+
+ else if (!close_enough(clk->rate, rate)) {
+ ret = clk->ops->set_rate(clk, rate);
+ if (ret < 0)
+ goto out;
+ clk->rate = rate;
+ if (clk->flags & RATE_PROPAGATES)
+ propagate_rate(clk);
+ } else
+ ret = 0;
+
+out:
+ return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_enable(struct clk *clk)
+{
+ unsigned long clocks_flags;
+
+ if (unlikely(!clk_good(clk)))
+ return -EINVAL;
+
+ if (clk->parent)
+ clk_enable(clk->parent);
+
+ spin_lock_irqsave(&clocks_lock, clocks_flags);
+
+ clk->usage++;
+ if (clk->ops && clk->ops->enable)
+ clk->ops->enable(clk);
+
+ spin_unlock_irqrestore(&clocks_lock, clocks_flags);
+ return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+static void local_clk_disable(struct clk *clk)
+{
+ if (unlikely(!clk_good(clk)))
+ return;
+
+ if (clk->usage == 0 && clk->ops->disable)
+ clk->ops->disable(clk);
+
+ if (clk->parent)
+ local_clk_disable(clk->parent);
+}
+
+void clk_disable(struct clk *clk)
+{
+ unsigned long clocks_flags;
+
+ if (unlikely(!clk_good(clk)))
+ return;
+
+ spin_lock_irqsave(&clocks_lock, clocks_flags);
+
+ if ((--clk->usage) == 0 && clk->ops->disable)
+ clk->ops->disable(clk);
+
+ spin_unlock_irqrestore(&clocks_lock, clocks_flags);
+ if (clk->parent)
+ clk_disable(clk->parent);
+}
+EXPORT_SYMBOL(clk_disable);
+
+/* Some additional API */
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ int ret = -ENODEV;
+ unsigned long clocks_flags;
+
+ if (unlikely(!clk_good(clk)))
+ goto out;
+
+ if (!clk->ops->set_parent)
+ goto out;
+
+ spin_lock_irqsave(&clocks_lock, clocks_flags);
+
+ ret = clk->ops->set_parent(clk, parent);
+ if (!ret) {
+ /* disable if usage count is 0 */
+ local_clk_disable(parent);
+
+ parent->usage += clk->usage;
+ clk->parent->usage -= clk->usage;
+
+ /* disable if new usage count is 0 */
+ local_clk_disable(clk->parent);
+
+ clk->parent = parent;
+ }
+ spin_unlock_irqrestore(&clocks_lock, clocks_flags);
+
+out:
+ return ret;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+ if (unlikely(!clk_good(clk)))
+ return NULL;
+ return clk->parent;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
+static int __init clk_init(void)
+{
+ struct clk_lookup *cl;
+ struct clk_ops *ops;
+
+ spin_lock_init(&clocks_lock);
+
+ for (cl = onchip_clks; cl < onchip_clks + ARRAY_SIZE(onchip_clks);
+ cl++) {
+ if (cl->clk->flags & ENABLED)
+ clk_enable(cl->clk);
+ else
+ local_clk_disable(cl->clk);
+
+ ops = cl->clk->ops;
+
+ if ((cl->clk->flags & NEEDS_INITIALIZATION) &&
+ ops && ops->set_rate)
+ ops->set_rate(cl->clk, cl->clk->rate);
+
+ if (cl->clk->flags & FIXED_RATE) {
+ if (cl->clk->flags & RATE_PROPAGATES)
+ propagate_rate(cl->clk);
+ } else {
+ if (ops && ops->get_rate)
+ ops->get_rate(cl->clk);
+ }
+
+ if (cl->clk->flags & NEEDS_SET_PARENT) {
+ if (ops && ops->set_parent)
+ ops->set_parent(cl->clk, cl->clk->parent);
+ }
+
+ clkdev_add(cl);
+ }
+ return 0;
+}
+
+arch_initcall(clk_init);
diff --git a/arch/arm/plat-stmp3xxx/clock.h b/arch/arm/plat-stmp3xxx/clock.h
new file mode 100644
index 000000000000..a6611e1a3510
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/clock.h
@@ -0,0 +1,61 @@
+/*
+ * Clock control driver for Freescale STMP37XX/STMP378X - internal header file
+ *
+ * Author: Vitaly Wool <vital@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ARCH_ARM_STMX3XXX_CLOCK_H__
+#define __ARCH_ARM_STMX3XXX_CLOCK_H__
+
+#ifndef __ASSEMBLER__
+
+struct clk_ops {
+ int (*enable) (struct clk *);
+ int (*disable) (struct clk *);
+ long (*get_rate) (struct clk *);
+ long (*round_rate) (struct clk *, u32);
+ int (*set_rate) (struct clk *, u32);
+ int (*set_parent) (struct clk *, struct clk *);
+};
+
+struct clk {
+ struct clk *parent;
+ u32 rate;
+ u32 flags;
+ u8 scale_shift;
+ u8 enable_shift;
+ u8 bypass_shift;
+ u8 busy_bit;
+ s8 usage;
+ int enable_wait;
+ int enable_negate;
+ u32 saved_div;
+ void __iomem *enable_reg;
+ void __iomem *scale_reg;
+ void __iomem *bypass_reg;
+ void __iomem *busy_reg;
+ struct clk_ops *ops;
+};
+
+#endif /* __ASSEMBLER__ */
+
+/* Flags */
+#define RATE_PROPAGATES (1<<0)
+#define NEEDS_INITIALIZATION (1<<1)
+#define PARENT_SET_RATE (1<<2)
+#define FIXED_RATE (1<<3)
+#define ENABLED (1<<4)
+#define NEEDS_SET_PARENT (1<<5)
+
+#endif
diff --git a/arch/arm/plat-stmp3xxx/core.c b/arch/arm/plat-stmp3xxx/core.c
new file mode 100644
index 000000000000..6e2fef1639b0
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/core.c
@@ -0,0 +1,127 @@
+/*
+ * Freescale STMP37XX/STMP378X core routines
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <mach/stmp3xxx.h>
+#include <mach/dma.h>
+#include <mach/regs-clkctrl.h>
+
+static int __stmp3xxx_reset_block(void __iomem *hwreg, int just_enable)
+{
+ u32 c;
+ int timeout;
+
+ /* the process of software reset of IP block is done
+ in several steps:
+
+ - clear SFTRST and wait for block is enabled;
+ - clear clock gating (CLKGATE bit);
+ - set the SFTRST again and wait for block is in reset;
+ - clear SFTRST and wait for reset completion.
+ */
+ c = __raw_readl(hwreg);
+ c &= ~(1<<31); /* clear SFTRST */
+ __raw_writel(c, hwreg);
+ for (timeout = 1000000; timeout > 0; timeout--)
+ /* still in SFTRST state ? */
+ if ((__raw_readl(hwreg) & (1<<31)) == 0)
+ break;
+ if (timeout <= 0) {
+ printk(KERN_ERR"%s(%p): timeout when enabling\n",
+ __func__, hwreg);
+ return -ETIME;
+ }
+
+ c = __raw_readl(hwreg);
+ c &= ~(1<<30); /* clear CLKGATE */
+ __raw_writel(c, hwreg);
+
+ if (!just_enable) {
+ c = __raw_readl(hwreg);
+ c |= (1<<31); /* now again set SFTRST */
+ __raw_writel(c, hwreg);
+ for (timeout = 1000000; timeout > 0; timeout--)
+ /* poll until CLKGATE set */
+ if (__raw_readl(hwreg) & (1<<30))
+ break;
+ if (timeout <= 0) {
+ printk(KERN_ERR"%s(%p): timeout when resetting\n",
+ __func__, hwreg);
+ return -ETIME;
+ }
+
+ c = __raw_readl(hwreg);
+ c &= ~(1<<31); /* clear SFTRST */
+ __raw_writel(c, hwreg);
+ for (timeout = 1000000; timeout > 0; timeout--)
+ /* still in SFTRST state ? */
+ if ((__raw_readl(hwreg) & (1<<31)) == 0)
+ break;
+ if (timeout <= 0) {
+ printk(KERN_ERR"%s(%p): timeout when enabling "
+ "after reset\n", __func__, hwreg);
+ return -ETIME;
+ }
+
+ c = __raw_readl(hwreg);
+ c &= ~(1<<30); /* clear CLKGATE */
+ __raw_writel(c, hwreg);
+ }
+ for (timeout = 1000000; timeout > 0; timeout--)
+ /* still in SFTRST state ? */
+ if ((__raw_readl(hwreg) & (1<<30)) == 0)
+ break;
+
+ if (timeout <= 0) {
+ printk(KERN_ERR"%s(%p): timeout when unclockgating\n",
+ __func__, hwreg);
+ return -ETIME;
+ }
+
+ return 0;
+}
+
+int stmp3xxx_reset_block(void __iomem *hwreg, int just_enable)
+{
+ int try = 10;
+ int r;
+
+ while (try--) {
+ r = __stmp3xxx_reset_block(hwreg, just_enable);
+ if (!r)
+ break;
+ pr_debug("%s: try %d failed\n", __func__, 10 - try);
+ }
+ return r;
+}
+EXPORT_SYMBOL(stmp3xxx_reset_block);
+
+struct platform_device stmp3xxx_dbguart = {
+ .name = "stmp3xxx-dbguart",
+ .id = -1,
+};
+
+void __init stmp3xxx_init(void)
+{
+ /* Turn off auto-slow and other tricks */
+ HW_CLKCTRL_HBUS_CLR(0x07f00000U);
+
+ stmp3xxx_dma_init();
+}
diff --git a/arch/arm/plat-stmp3xxx/dma.c b/arch/arm/plat-stmp3xxx/dma.c
new file mode 100644
index 000000000000..cf42de05e568
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/dma.c
@@ -0,0 +1,462 @@
+/*
+ * DMA helper routines for Freescale STMP37XX/STMP378X
+ *
+ * Author: dmitry pervushin <dpervushin@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/dmapool.h>
+#include <linux/sysdev.h>
+#include <linux/cpufreq.h>
+
+#include <asm/page.h>
+
+#include <mach/dma.h>
+#include <mach/regs-apbx.h>
+#include <mach/regs-apbh.h>
+
+static const size_t pool_item_size = sizeof(struct stmp3xxx_dma_command);
+static const size_t pool_alignment = 8;
+static struct stmp3xxx_dma_user {
+ void *pool;
+ int inuse;
+ const char *name;
+} channels[MAX_DMA_CHANNELS];
+
+static inline int dmach(int ch)
+{
+ return ch % 16;
+}
+
+static inline int dmabus(int ch)
+{
+ return ch / 16;
+}
+
+#define IS_VALID_CHANNEL(ch) ((ch) >= 0 && (ch) < MAX_DMA_CHANNELS)
+#define IS_USED(ch) (channels[ch].inuse)
+
+int stmp3xxx_dma_request(int ch, struct device *dev, const char *name)
+{
+ struct stmp3xxx_dma_user *user;
+ int err = 0;
+
+ user = channels + ch;
+ if (!IS_VALID_CHANNEL(ch)) {
+ err = -ENODEV;
+ goto out;
+ }
+ if (IS_USED(ch)) {
+ err = -EBUSY;
+ goto out;
+ }
+ /* Create a pool to allocate dma commands from */
+ user->pool = dma_pool_create(name, dev, pool_item_size,
+ pool_alignment, PAGE_SIZE);
+ if (user->pool == NULL) {
+ err = -ENOMEM;
+ goto out;
+ }
+ user->name = name;
+ user->inuse++;
+out:
+ return err;
+}
+EXPORT_SYMBOL(stmp3xxx_dma_request);
+
+int stmp3xxx_dma_release(int ch)
+{
+ struct stmp3xxx_dma_user *user = channels + ch;
+ int err = 0;
+
+ if (!IS_VALID_CHANNEL(ch)) {
+ err = -ENODEV;
+ goto out;
+ }
+ if (!IS_USED(ch)) {
+ err = -EBUSY;
+ goto out;
+ }
+ BUG_ON(user->pool == NULL);
+ dma_pool_destroy(user->pool);
+ user->inuse--;
+out:
+ return err;
+}
+EXPORT_SYMBOL(stmp3xxx_dma_release);
+
+int stmp3xxx_dma_read_semaphore(int channel)
+{
+ int sem = -1;
+
+ switch (dmabus(channel)) {
+ case STMP3XXX_BUS_APBH:
+ sem =
+ (HW_APBH_CHn_SEMA_RD(dmach(channel)) &
+ BM_APBH_CHn_SEMA_PHORE) >> BP_APBH_CHn_SEMA_PHORE;
+ break;
+
+ case STMP3XXX_BUS_APBX:
+ sem =
+ (HW_APBX_CHn_SEMA_RD(dmach(channel)) &
+ BM_APBX_CHn_SEMA_PHORE) >> BP_APBX_CHn_SEMA_PHORE;
+ break;
+ default:
+ BUG();
+ }
+ return sem;
+}
+EXPORT_SYMBOL(stmp3xxx_dma_read_semaphore);
+
+int stmp3xxx_dma_allocate_command(int channel,
+ struct stmp3xxx_dma_descriptor *descriptor)
+{
+ struct stmp3xxx_dma_user *user = channels + channel;
+ int err = 0;
+
+ if (!IS_VALID_CHANNEL(channel)) {
+ err = -ENODEV;
+ goto out;
+ }
+ if (!IS_USED(channel)) {
+ err = -EBUSY;
+ goto out;
+ }
+ if (descriptor == NULL) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* Allocate memory for a command from the buffer */
+ descriptor->command =
+ dma_pool_alloc(user->pool, GFP_KERNEL, &descriptor->handle);
+
+ /* Check it worked */
+ if (!descriptor->command) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ memset(descriptor->command, 0, pool_item_size);
+out:
+ WARN_ON(err);
+ return err;
+}
+EXPORT_SYMBOL(stmp3xxx_dma_allocate_command);
+
+int stmp3xxx_dma_free_command(int channel,
+ struct stmp3xxx_dma_descriptor *descriptor)
+{
+ int err = 0;
+
+ if (!IS_VALID_CHANNEL(channel)) {
+ err = -ENODEV;
+ goto out;
+ }
+ if (!IS_USED(channel)) {
+ err = -EBUSY;
+ goto out;
+ }
+
+ /* Return the command memory to the pool */
+ dma_pool_free(channels[channel].pool, descriptor->command,
+ descriptor->handle);
+
+ /* Initialise descriptor so we're not tempted to use it */
+ descriptor->command = NULL;
+ descriptor->handle = 0;
+ descriptor->virtual_buf_ptr = NULL;
+ descriptor->next_descr = NULL;
+
+ WARN_ON(err);
+out:
+ return err;
+}
+EXPORT_SYMBOL(stmp3xxx_dma_free_command);
+
+void stmp3xxx_dma_go(int channel,
+ struct stmp3xxx_dma_descriptor *head, u32 semaphore)
+{
+ int ch = dmach(channel);
+
+ switch (dmabus(channel)) {
+ case STMP3XXX_BUS_APBH:
+ /* Set next command */
+ HW_APBH_CHn_NXTCMDAR_WR(ch, head->handle);
+ /* Set counting semaphore (kicks off transfer). Assumes
+ peripheral has been set up correctly */
+ HW_APBH_CHn_SEMA_WR(ch, semaphore);
+ break;
+
+ case STMP3XXX_BUS_APBX:
+ /* Set next command */
+ HW_APBX_CHn_NXTCMDAR_WR(ch, head->handle);
+ /* Set counting semaphore (kicks off transfer). Assumes
+ peripheral has been set up correctly */
+ HW_APBX_CHn_SEMA_WR(ch, semaphore);
+ break;
+ }
+}
+EXPORT_SYMBOL(stmp3xxx_dma_go);
+
+int stmp3xxx_dma_running(int channel)
+{
+ switch (dmabus(channel)) {
+ case STMP3XXX_BUS_APBH:
+ return HW_APBH_CHn_SEMA_RD(dmach(channel)) &
+ BM_APBH_CHn_SEMA_PHORE;
+
+ case STMP3XXX_BUS_APBX:
+ return HW_APBX_CHn_SEMA_RD(dmach(channel)) &
+ BM_APBX_CHn_SEMA_PHORE;
+
+ default:
+ BUG();
+ return 0;
+ }
+}
+EXPORT_SYMBOL(stmp3xxx_dma_running);
+
+/*
+ * Circular dma chain management
+ */
+void stmp3xxx_dma_free_chain(struct stmp37xx_circ_dma_chain *chain)
+{
+ int i;
+
+ for (i = 0; i < chain->total_count; i++)
+ stmp3xxx_dma_free_command(
+ STMP3xxx_DMA(chain->channel, chain->bus),
+ &chain->chain[i]);
+}
+EXPORT_SYMBOL(stmp3xxx_dma_free_chain);
+
+int stmp3xxx_dma_make_chain(int ch, struct stmp37xx_circ_dma_chain *chain,
+ struct stmp3xxx_dma_descriptor descriptors[],
+ unsigned items)
+{
+ int i;
+ int err = 0;
+
+ if (items == 0)
+ return err;
+
+ for (i = 0; i < items; i++) {
+ err = stmp3xxx_dma_allocate_command(ch, &descriptors[i]);
+ if (err) {
+ WARN_ON(err);
+ /*
+ * Couldn't allocate the whole chain.
+ * deallocate what has been allocated
+ */
+ if (i) {
+ do {
+ stmp3xxx_dma_free_command(ch,
+ &descriptors
+ [i]);
+ } while (i-- >= 0);
+ }
+ return err;
+ }
+
+ /* link them! */
+ if (i > 0) {
+ descriptors[i - 1].next_descr = &descriptors[i];
+ descriptors[i - 1].command->next =
+ descriptors[i].handle;
+ }
+ }
+
+ /* make list circular */
+ descriptors[items - 1].next_descr = &descriptors[0];
+ descriptors[items - 1].command->next = descriptors[0].handle;
+
+ chain->total_count = items;
+ chain->chain = descriptors;
+ chain->free_index = 0;
+ chain->active_index = 0;
+ chain->cooked_index = 0;
+ chain->free_count = items;
+ chain->active_count = 0;
+ chain->cooked_count = 0;
+ chain->bus = dmabus(ch);
+ chain->channel = dmach(ch);
+ return err;
+}
+EXPORT_SYMBOL(stmp3xxx_dma_make_chain);
+
+void stmp37xx_circ_clear_chain(struct stmp37xx_circ_dma_chain *chain)
+{
+ BUG_ON(stmp3xxx_dma_running(STMP3xxx_DMA(chain->channel, chain->bus)) >
+ 0);
+ chain->free_index = 0;
+ chain->active_index = 0;
+ chain->cooked_index = 0;
+ chain->free_count = chain->total_count;
+ chain->active_count = 0;
+ chain->cooked_count = 0;
+}
+EXPORT_SYMBOL(stmp37xx_circ_clear_chain);
+
+void stmp37xx_circ_advance_free(struct stmp37xx_circ_dma_chain *chain,
+ unsigned count)
+{
+ BUG_ON(chain->cooked_count < count);
+
+ chain->cooked_count -= count;
+ chain->cooked_index += count;
+ chain->cooked_index %= chain->total_count;
+ chain->free_count += count;
+}
+EXPORT_SYMBOL(stmp37xx_circ_advance_free);
+
+void stmp37xx_circ_advance_active(struct stmp37xx_circ_dma_chain *chain,
+ unsigned count)
+{
+ BUG_ON(chain->free_count < count);
+
+ chain->free_count -= count;
+ chain->free_index += count;
+ chain->free_index %= chain->total_count;
+ chain->active_count += count;
+
+ switch (chain->bus) {
+ case STMP3XXX_BUS_APBH:
+ /* Set counting semaphore (kicks off transfer). Assumes
+ peripheral has been set up correctly */
+ HW_APBH_CHn_SEMA_CLR(chain->channel,
+ BM_APBH_CHn_SEMA_INCREMENT_SEMA);
+ HW_APBH_CHn_SEMA_SET(chain->channel,
+ BF_APBH_CHn_SEMA_INCREMENT_SEMA(count));
+ break;
+
+ case STMP3XXX_BUS_APBX:
+ /* Set counting semaphore (kicks off transfer). Assumes
+ peripheral has been set up correctly */
+ HW_APBX_CHn_SEMA_CLR(chain->channel,
+ BM_APBX_CHn_SEMA_INCREMENT_SEMA);
+ HW_APBX_CHn_SEMA_SET(chain->channel,
+ BF_APBX_CHn_SEMA_INCREMENT_SEMA(count));
+ break;
+
+ default:
+ BUG();
+ }
+}
+EXPORT_SYMBOL(stmp37xx_circ_advance_active);
+
+unsigned stmp37xx_circ_advance_cooked(struct stmp37xx_circ_dma_chain *chain)
+{
+ unsigned cooked;
+
+ cooked = chain->active_count -
+ stmp3xxx_dma_read_semaphore(STMP3xxx_DMA(chain->channel, chain->bus));
+
+ chain->active_count -= cooked;
+ chain->active_index += cooked;
+ chain->active_index %= chain->total_count;
+
+ chain->cooked_count += cooked;
+
+ return cooked;
+}
+EXPORT_SYMBOL(stmp37xx_circ_advance_cooked);
+
+void stmp3xxx_dma_set_alt_target(int channel, int function)
+{
+#if defined(CONFIG_ARCH_STMP37XX)
+ unsigned bits = 4;
+#elif defined(CONFIG_ARCH_STMP378X)
+ unsigned bits = 2;
+#else
+#error wrong arch
+#endif
+ int shift = dmach(channel) * bits;
+ unsigned mask = (1<<bits) - 1;
+
+ BUG_ON(function < 0 || function >= (1<<bits));
+ pr_debug("%s: channel = %d, using mask %x, "
+ "shift = %d\n", __func__, channel, mask, shift);
+
+ switch (dmabus(channel)) {
+ case STMP3XXX_BUS_APBH:
+ HW_APBH_DEVSEL_CLR(mask<<shift);
+ HW_APBH_DEVSEL_SET(function<<shift);
+ break;
+ case STMP3XXX_BUS_APBX:
+ HW_APBX_DEVSEL_CLR(mask<<shift);
+ HW_APBX_DEVSEL_SET(function<<shift);
+ break;
+ default:
+ BUG();
+ }
+}
+EXPORT_SYMBOL(stmp3xxx_dma_set_alt_target);
+
+void stmp3xxx_dma_suspend(void)
+{
+ HW_APBH_CTRL0_SET(BM_APBH_CTRL0_CLKGATE);
+ HW_APBX_CTRL0_SET(BM_APBX_CTRL0_CLKGATE);
+}
+
+void stmp3xxx_dma_resume(void)
+{
+ HW_APBH_CTRL0_CLR(BM_APBH_CTRL0_CLKGATE | BM_APBH_CTRL0_SFTRST);
+ HW_APBX_CTRL0_CLR(BM_APBX_CTRL0_CLKGATE | BM_APBX_CTRL0_SFTRST);
+}
+
+#ifdef CONFIG_CPU_FREQ
+
+struct dma_notifier_block {
+ struct notifier_block nb;
+ void *data;
+};
+
+static int dma_cpufreq_notifier(struct notifier_block *self,
+ unsigned long phase, void *p)
+{
+ switch (phase) {
+ case CPUFREQ_POSTCHANGE:
+ stmp3xxx_dma_resume();
+ break;
+
+ case CPUFREQ_PRECHANGE:
+ stmp3xxx_dma_suspend();
+ break;
+
+ default:
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct dma_notifier_block dma_cpufreq_nb = {
+ .nb = {
+ .notifier_call = dma_cpufreq_notifier,
+ },
+};
+#endif /* CONFIG_CPU_FREQ */
+
+void __init stmp3xxx_dma_init(void)
+{
+ HW_APBH_CTRL0_CLR(BM_APBH_CTRL0_CLKGATE | BM_APBH_CTRL0_SFTRST);
+ HW_APBX_CTRL0_CLR(BM_APBX_CTRL0_CLKGATE | BM_APBX_CTRL0_SFTRST);
+#ifdef CONFIG_CPU_FREQ
+ cpufreq_register_notifier(&dma_cpufreq_nb.nb,
+ CPUFREQ_TRANSITION_NOTIFIER);
+#endif /* CONFIG_CPU_FREQ */
+
+}
diff --git a/arch/arm/plat-stmp3xxx/include/mach/clkdev.h b/arch/arm/plat-stmp3xxx/include/mach/clkdev.h
new file mode 100644
index 000000000000..f9c39772d7c5
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/include/mach/clkdev.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_MACH_CLKDEV_H
+#define __ASM_MACH_CLKDEV_H
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff --git a/arch/arm/plat-stmp3xxx/include/mach/cputype.h b/arch/arm/plat-stmp3xxx/include/mach/cputype.h
new file mode 100644
index 000000000000..b4e205b95f2c
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/include/mach/cputype.h
@@ -0,0 +1,33 @@
+/*
+ * Freescale STMP37XX/STMP378X CPU type detection
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_PLAT_CPU_H
+#define __ASM_PLAT_CPU_H
+
+#ifdef CONFIG_ARCH_STMP37XX
+#define cpu_is_stmp37xx() (1)
+#else
+#define cpu_is_stmp37xx() (0)
+#endif
+
+#ifdef CONFIG_ARCH_STMP378X
+#define cpu_is_stmp378x() (1)
+#else
+#define cpu_is_stmp378x() (0)
+#endif
+
+#endif /* __ASM_PLAT_CPU_H */
diff --git a/arch/arm/plat-stmp3xxx/include/mach/debug-macro.S b/arch/arm/plat-stmp3xxx/include/mach/debug-macro.S
new file mode 100644
index 000000000000..fb3b969bf0a2
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/include/mach/debug-macro.S
@@ -0,0 +1,42 @@
+/*
+ * Debugging macro include header
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+ .macro addruart,rx
+ mrc p15, 0, \rx, c1, c0
+ tst \rx, #1 @ MMU enabled?
+ moveq \rx, #0x80000000 @ physical base address
+ addeq \rx, \rx, #0x00070000
+ movne \rx, #0xf0000000 @ virtual base
+ addne \rx, \rx, #0x00070000
+ .endm
+
+ .macro senduart,rd,rx
+ strb \rd, [\rx, #0] @ data register at 0
+ .endm
+
+ .macro waituart,rd,rx
+1001: ldr \rd, [\rx, #0x18] @ UARTFLG
+ tst \rd, #1 << 5 @ UARTFLGUTXFF - 1 when full
+ bne 1001b
+ .endm
+
+ .macro busyuart,rd,rx
+1001: ldr \rd, [\rx, #0x18] @ UARTFLG
+ tst \rd, #1 << 3 @ UARTFLGUBUSY - 1 when busy
+ bne 1001b
+ .endm
diff --git a/arch/arm/plat-stmp3xxx/include/mach/dma.h b/arch/arm/plat-stmp3xxx/include/mach/dma.h
new file mode 100644
index 000000000000..1e305b2bfe73
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/include/mach/dma.h
@@ -0,0 +1,155 @@
+/*
+ * Freescale STMP37XX/STMP378X DMA helper interface
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_PLAT_STMP3XXX_DMA_H
+#define __ASM_PLAT_STMP3XXX_DMA_H
+
+#include <linux/platform_device.h>
+#include <linux/dmapool.h>
+
+#if !defined(MAX_PIO_WORDS)
+#define MAX_PIO_WORDS (15)
+#endif
+
+#define STMP3XXX_BUS_APBH 0
+#define STMP3XXX_BUS_APBX 1
+#define STMP3XXX_DMA_MAX_CHANNEL 16
+
+
+#define STMP3xxx_DMA(channel, bus) ((bus) * 16 + (channel))
+
+#define MAX_DMA_ADDRESS 0xffffffff
+
+#define MAX_DMA_CHANNELS 32
+
+struct stmp3xxx_dma_command {
+ u32 next;
+ u32 cmd;
+ union {
+ u32 buf_ptr;
+ u32 alternate;
+ };
+ u32 pio_words[MAX_PIO_WORDS];
+};
+
+struct stmp3xxx_dma_descriptor {
+ struct stmp3xxx_dma_command *command;
+ dma_addr_t handle;
+
+ /* The virtual address of the buffer pointer */
+ void *virtual_buf_ptr;
+ /* The next descriptor in a the DMA chain (optional) */
+ struct stmp3xxx_dma_descriptor *next_descr;
+};
+
+struct stmp37xx_circ_dma_chain {
+ unsigned total_count;
+ struct stmp3xxx_dma_descriptor *chain;
+
+ unsigned free_index;
+ unsigned free_count;
+ unsigned active_index;
+ unsigned active_count;
+ unsigned cooked_index;
+ unsigned cooked_count;
+
+ int bus;
+ unsigned channel;
+};
+
+static inline struct stmp3xxx_dma_descriptor
+ *stmp3xxx_dma_circ_get_free_head(struct stmp37xx_circ_dma_chain *chain)
+{
+ return &(chain->chain[chain->free_index]);
+}
+
+static inline struct stmp3xxx_dma_descriptor
+ *stmp3xxx_dma_circ_get_cooked_head(struct stmp37xx_circ_dma_chain *chain)
+{
+ return &(chain->chain[chain->cooked_index]);
+}
+
+int stmp3xxx_dma_request(int ch, struct device *dev, const char *name);
+int stmp3xxx_dma_release(int ch);
+int stmp3xxx_dma_allocate_command(int ch,
+ struct stmp3xxx_dma_descriptor *descriptor);
+int stmp3xxx_dma_free_command(int ch,
+ struct stmp3xxx_dma_descriptor *descriptor);
+void stmp3xxx_dma_continue(int channel, u32 semaphore);
+void stmp3xxx_dma_go(int ch, struct stmp3xxx_dma_descriptor *head,
+ u32 semaphore);
+int stmp3xxx_dma_running(int ch);
+int stmp3xxx_dma_make_chain(int ch, struct stmp37xx_circ_dma_chain *chain,
+ struct stmp3xxx_dma_descriptor descriptors[],
+ unsigned items);
+void stmp3xxx_dma_free_chain(struct stmp37xx_circ_dma_chain *chain);
+void stmp37xx_circ_clear_chain(struct stmp37xx_circ_dma_chain *chain);
+void stmp37xx_circ_advance_free(struct stmp37xx_circ_dma_chain *chain,
+ unsigned count);
+void stmp37xx_circ_advance_active(struct stmp37xx_circ_dma_chain *chain,
+ unsigned count);
+unsigned stmp37xx_circ_advance_cooked(struct stmp37xx_circ_dma_chain *chain);
+int stmp3xxx_dma_read_semaphore(int ch);
+void stmp3xxx_dma_init(void);
+void stmp3xxx_dma_set_alt_target(int ch, int target);
+void stmp3xxx_dma_suspend(void);
+void stmp3xxx_dma_resume(void);
+
+/*
+ * STMP37xx and STMP378x have different DMA control
+ * registers layout
+ */
+
+void stmp3xxx_arch_dma_freeze(int ch);
+void stmp3xxx_arch_dma_unfreeze(int ch);
+void stmp3xxx_arch_dma_reset_channel(int ch);
+void stmp3xxx_arch_dma_enable_interrupt(int ch);
+void stmp3xxx_arch_dma_clear_interrupt(int ch);
+int stmp3xxx_arch_dma_is_interrupt(int ch);
+
+static inline void stmp3xxx_dma_reset_channel(int ch)
+{
+ stmp3xxx_arch_dma_reset_channel(ch);
+}
+
+
+static inline void stmp3xxx_dma_freeze(int ch)
+{
+ stmp3xxx_arch_dma_freeze(ch);
+}
+
+static inline void stmp3xxx_dma_unfreeze(int ch)
+{
+ stmp3xxx_arch_dma_unfreeze(ch);
+}
+
+static inline void stmp3xxx_dma_enable_interrupt(int ch)
+{
+ stmp3xxx_arch_dma_enable_interrupt(ch);
+}
+
+static inline void stmp3xxx_dma_clear_interrupt(int ch)
+{
+ stmp3xxx_arch_dma_clear_interrupt(ch);
+}
+
+static inline int stmp3xxx_dma_is_interrupt(int ch)
+{
+ return stmp3xxx_arch_dma_is_interrupt(ch);
+}
+
+#endif /* __ASM_PLAT_STMP3XXX_DMA_H */
diff --git a/arch/arm/plat-stmp3xxx/include/mach/gpio.h b/arch/arm/plat-stmp3xxx/include/mach/gpio.h
new file mode 100644
index 000000000000..a8b579256170
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/include/mach/gpio.h
@@ -0,0 +1,28 @@
+/*
+ * Freescale STMP37XX/STMP378X GPIO interface
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_PLAT_GPIO_H
+#define __ASM_PLAT_GPIO_H
+
+#define ARCH_NR_GPIOS (32 * 3)
+#define gpio_to_irq(gpio) __gpio_to_irq(gpio)
+#define gpio_get_value(gpio) __gpio_get_value(gpio)
+#define gpio_set_value(gpio, value) __gpio_set_value(gpio, value)
+
+#include <asm-generic/gpio.h>
+
+#endif /* __ASM_PLAT_GPIO_H */
diff --git a/arch/arm/plat-stmp3xxx/include/mach/hardware.h b/arch/arm/plat-stmp3xxx/include/mach/hardware.h
new file mode 100644
index 000000000000..47b8978405bc
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/include/mach/hardware.h
@@ -0,0 +1,32 @@
+/*
+ * This file contains the hardware definitions of the Freescale STMP3XXX
+ *
+ * Copyright (C) 2005 Sigmatel Inc
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+/*
+ * Where in virtual memory the IO devices (timers, system controllers
+ * and so on)
+ */
+#define IO_BASE 0xF0000000 /* VA of IO */
+#define IO_SIZE 0x00100000 /* How much? */
+#define IO_START 0x80000000 /* PA of IO */
+
+/* macro to get at IO space when running virtually */
+#define IO_ADDRESS(x) (((x) & 0x000fffff) | IO_BASE)
+
+#endif
diff --git a/arch/arm/plat-stmp3xxx/include/mach/io.h b/arch/arm/plat-stmp3xxx/include/mach/io.h
new file mode 100644
index 000000000000..d08b1b7f3d1c
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/include/mach/io.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2005 Sigmatel Inc
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a) __typesafe_io(a)
+#define __mem_pci(a) (a)
+#define __mem_isa(a) (a)
+
+#endif
diff --git a/arch/arm/plat-stmp3xxx/include/mach/memory.h b/arch/arm/plat-stmp3xxx/include/mach/memory.h
new file mode 100644
index 000000000000..7b875a07a1a7
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/include/mach/memory.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET UL(0x40000000)
+
+#endif
diff --git a/arch/arm/plat-stmp3xxx/include/mach/pinmux.h b/arch/arm/plat-stmp3xxx/include/mach/pinmux.h
new file mode 100644
index 000000000000..526c068d7c44
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/include/mach/pinmux.h
@@ -0,0 +1,158 @@
+/*
+ * Freescale STMP37XX/STMP378X Pin Multiplexing
+ *
+ * Author: Vladislav Buzov <vbuzov@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __PINMUX_H
+#define __PINMUX_H
+
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/gpio.h>
+#include <asm-generic/gpio.h>
+
+/* Pin definitions */
+#include "pins.h"
+#include <mach/pins.h>
+
+/*
+ * Each pin may be routed up to four different HW interfaces
+ * including GPIO
+ */
+enum pin_fun {
+ PIN_FUN1 = 0,
+ PIN_FUN2,
+ PIN_FUN3,
+ PIN_GPIO,
+};
+
+/*
+ * Each pin may have different output drive strength in range from
+ * 4mA to 20mA. The most common case is 4, 8 and 12 mA strengths.
+ */
+enum pin_strength {
+ PIN_4MA = 0,
+ PIN_8MA,
+ PIN_12MA,
+ PIN_16MA,
+ PIN_20MA,
+};
+
+/*
+ * Each pin can be programmed for 1.8V or 3.3V
+ */
+enum pin_voltage {
+ PIN_1_8V = 0,
+ PIN_3_3V,
+};
+
+/*
+ * Structure to define a group of pins and their parameters
+ */
+struct pin_desc {
+ unsigned id;
+ enum pin_fun fun;
+ enum pin_strength strength;
+ enum pin_voltage voltage;
+ unsigned pullup:1;
+};
+
+struct pin_group {
+ struct pin_desc *pins;
+ int nr_pins;
+};
+
+/* Set pin drive strength */
+void stmp3xxx_pin_strength(unsigned id, enum pin_strength strength,
+ const char *label);
+
+/* Set pin voltage */
+void stmp3xxx_pin_voltage(unsigned id, enum pin_voltage voltage,
+ const char *label);
+
+/* Enable pull-up resistor for a pin */
+void stmp3xxx_pin_pullup(unsigned id, int enable, const char *label);
+
+/*
+ * Request a pin ownership, only one module (identified by @label)
+ * may own a pin.
+ */
+int stmp3xxx_request_pin(unsigned id, enum pin_fun fun, const char *label);
+
+/* Release pin */
+void stmp3xxx_release_pin(unsigned id, const char *label);
+
+void stmp3xxx_set_pin_type(unsigned id, enum pin_fun fun);
+
+/*
+ * Each bank is associated with a number of registers to control
+ * pin function, drive strength, voltage and pull-up reigster. The
+ * number of registers of a given type depends on the number of bits
+ * describin particular pin.
+ */
+#define HW_MUXSEL_NUM 2 /* registers per bank */
+#define HW_MUXSEL_PIN_LEN 2 /* bits per pin */
+#define HW_MUXSEL_PIN_NUM 16 /* pins per register */
+#define HW_MUXSEL_PINFUN_MASK 0x3 /* pin function mask */
+#define HW_MUXSEL_PINFUN_NUM 4 /* four options for a pin */
+
+#define HW_DRIVE_NUM 4 /* registers per bank */
+#define HW_DRIVE_PIN_LEN 4 /* bits per pin */
+#define HW_DRIVE_PIN_NUM 8 /* pins per register */
+#define HW_DRIVE_PINDRV_MASK 0x3 /* pin strength mask - 2 bits */
+#define HW_DRIVE_PINDRV_NUM 5 /* five possible strength values */
+#define HW_DRIVE_PINV_MASK 0x4 /* pin voltage mask - 1 bit */
+
+
+struct stmp3xxx_pinmux_bank {
+ struct gpio_chip chip;
+
+ /* Pins allocation map */
+ unsigned long pin_map;
+
+ /* Pin owner names */
+ const char *pin_labels[32];
+
+ /* Bank registers */
+ void __iomem *hw_muxsel[HW_MUXSEL_NUM];
+ void __iomem *hw_drive[HW_DRIVE_NUM];
+ void __iomem *hw_pull;
+
+ void __iomem *pin2irq,
+ *irqlevel,
+ *irqpolarity,
+ *irqen,
+ *irqstat;
+
+ /* HW MUXSEL register function bit values */
+ u8 functions[HW_MUXSEL_PINFUN_NUM];
+
+ /*
+ * HW DRIVE register strength bit values:
+ * 0xff - requested strength is not supported for this bank
+ */
+ u8 strengths[HW_DRIVE_PINDRV_NUM];
+
+ /* GPIO things */
+ void __iomem *hw_gpio_read,
+ *hw_gpio_set,
+ *hw_gpio_clr,
+ *hw_gpio_doe;
+ int irq, virq;
+};
+
+int __init stmp3xxx_pinmux_init(int virtual_irq_start);
+
+#endif /* __PINMUX_H */
diff --git a/arch/arm/plat-stmp3xxx/include/mach/pins.h b/arch/arm/plat-stmp3xxx/include/mach/pins.h
new file mode 100644
index 000000000000..c573318e1caa
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/include/mach/pins.h
@@ -0,0 +1,30 @@
+/*
+ * Freescale STMP37XX/STMP378X Pin multiplexing interface definitions
+ *
+ * Author: Vladislav Buzov <vbuzov@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_PLAT_PINS_H
+#define __ASM_PLAT_PINS_H
+
+#define STMP3XXX_PINID(bank, pin) (bank * 32 + pin)
+#define STMP3XXX_PINID_TO_BANK(pinid) (pinid / 32)
+#define STMP3XXX_PINID_TO_PINNUM(pinid) (pinid % 32)
+
+/*
+ * Special invalid pin identificator to show a pin doesn't exist
+ */
+#define PINID_NO_PIN STMP3XXX_PINID(0xFF, 0xFF)
+
+#endif /* __ASM_PLAT_PINS_H */
diff --git a/arch/arm/plat-stmp3xxx/include/mach/platform.h b/arch/arm/plat-stmp3xxx/include/mach/platform.h
new file mode 100644
index 000000000000..525c41379bbe
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/include/mach/platform.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_PLAT_PLATFORM_H
+#define __ASM_PLAT_PLATFORM_H
+
+#include <asm/sizes.h>
+
+/* Virtual address where registers are mapped */
+#define STMP3XXX_REGS_PHBASE 0x80000000
+#ifdef __ASSEMBLER__
+#define STMP3XXX_REGS_BASE 0xF0000000
+#else
+#define STMP3XXX_REGS_BASE (void __iomem *)0xF0000000
+#endif
+#define STMP3XXX_REGS_SIZE SZ_1M
+
+/* Virtual address where OCRAM is mapped */
+#define STMP3XXX_OCRAM_PHBASE 0x00000000
+#ifdef __ASSEMBLER__
+#define STMP3XXX_OCRAM_BASE 0xf1000000
+#else
+#define STMP3XXX_OCRAM_BASE (void __iomem *)0xf1000000
+#endif
+#define STMP3XXX_OCRAM_SIZE (32 * SZ_1K)
+
+#ifdef CONFIG_ARCH_STMP37XX
+#define IRQ_PRIORITY_REG_RD HW_ICOLL_PRIORITYn_RD
+#define IRQ_PRIORITY_REG_WR HW_ICOLL_PRIORITYn_WR
+#endif
+
+#ifdef CONFIG_ARCH_STMP378X
+#define IRQ_PRIORITY_REG_RD HW_ICOLL_INTERRUPTn_RD
+#define IRQ_PRIORITY_REG_WR HW_ICOLL_INTERRUPTn_WR
+#endif
+
+#endif /* __ASM_ARCH_PLATFORM_H */
diff --git a/arch/arm/plat-stmp3xxx/include/mach/stmp3xxx.h b/arch/arm/plat-stmp3xxx/include/mach/stmp3xxx.h
new file mode 100644
index 000000000000..78cf1be75519
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/include/mach/stmp3xxx.h
@@ -0,0 +1,34 @@
+/*
+ * Freescale STMP37XX/STMP378X core structure and function declarations
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_PLAT_STMP3XXX_H
+#define __ASM_PLAT_STMP3XXX_H
+
+#include <linux/irq.h>
+
+extern struct sys_timer stmp3xxx_timer;
+
+void stmp3xxx_init_irq(struct irq_chip *chip);
+void stmp3xxx_init(void);
+int stmp3xxx_reset_block(void __iomem *hwreg, int just_enable);
+extern struct platform_device stmp3xxx_dbguart;
+
+struct pin_group;
+void stmp3xxx_release_pin_group(struct pin_group *pin_group, const char *label);
+int stmp3xxx_request_pin_group(struct pin_group *pin_group, const char *label);
+
+#endif /* __ASM_PLAT_STMP3XXX_H */
diff --git a/arch/arm/plat-stmp3xxx/include/mach/stmp3xxx_regs.h b/arch/arm/plat-stmp3xxx/include/mach/stmp3xxx_regs.h
new file mode 100644
index 000000000000..47797b2b36af
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/include/mach/stmp3xxx_regs.h
@@ -0,0 +1,195 @@
+/*
+ * Freescale STMP37XX/STMP378X SoC register access interfaces
+ *
+ * The SoC registers may be accessed via:
+ *
+ * - single 32 bit address, or
+ * - four 32 bit addresses - general purpose, set, clear and toggle bits
+ *
+ * Multiple IP blocks (e.g. SSP, UART) provide identical register sets per
+ * each module
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_PLAT_STMP3XXX_REGS_H
+#define __ASM_PLAT_STMP3XXX_REGS_H
+
+#ifndef __ASSEMBLER__
+#include <linux/io.h>
+#endif
+
+#include "platform.h"
+
+#define REGS_BASE STMP3XXX_REGS_BASE
+
+#define HW_STMP3xxx_SET 0x04
+#define HW_STMP3xxx_CLR 0x08
+#define HW_STMP3xxx_TOG 0x0c
+
+#ifndef __ASSEMBLER__
+#define HW_REGISTER_FUNCS(id, base, offset, regset, rd, wr) \
+ static const u32 id##_OFFSET = offset; \
+ static inline u32 id##_RD_NB(const void __iomem *regbase) { \
+ if (!rd) \
+ printk(KERN_ERR"%s: cannot READ at %p+%x\n", \
+ #id, regbase, offset); \
+ return __raw_readl(regbase + offset); \
+ } \
+ static inline void id##_WR_NB(void __iomem *regbase, u32 v) { \
+ if (!wr) \
+ printk(KERN_ERR"%s: cannot WRITE at %p+%x\n", \
+ #id, regbase, offset); \
+ __raw_writel(v, regbase + offset); \
+ } \
+ static inline void id##_SET_NB(void __iomem *regbase, u32 v) { \
+ if (!wr) \
+ printk(KERN_ERR"%s: cannot SET at %p+%x\n", \
+ #id, regbase, offset); \
+ if (regset) \
+ __raw_writel(v, regbase + \
+ offset + HW_STMP3xxx_SET); \
+ else \
+ __raw_writel(v | __raw_readl(regbase + offset), \
+ regbase + offset); \
+ } \
+ static inline void id##_CLR_NB(void __iomem *regbase, u32 v) { \
+ if (!wr) \
+ printk(KERN_ERR"%s: cannot CLR at %p+%x\n", \
+ #id, regbase, offset); \
+ if (regset) \
+ __raw_writel(v, regbase + \
+ offset + HW_STMP3xxx_CLR); \
+ else \
+ __raw_writel( \
+ ~v & __raw_readl(regbase + offset), \
+ regbase + offset); \
+ } \
+ static inline void id##_TOG_NB(void __iomem *regbase, u32 v) { \
+ if (!wr) \
+ printk(KERN_ERR"%s: cannot TOG at %p+%x\n", \
+ #id, regbase, offset); \
+ if (regset) \
+ __raw_writel(v, regbase + \
+ offset + HW_STMP3xxx_TOG); \
+ else \
+ __raw_writel(v ^ __raw_readl(regbase + offset), \
+ regbase + offset); \
+ } \
+ static inline u32 id##_RD(void) { return id##_RD_NB(base); } \
+ static inline void id##_WR(u32 v) { id##_WR_NB(base, v); } \
+ static inline void id##_SET(u32 v) { id##_SET_NB(base, v); } \
+ static inline void id##_CLR(u32 v) { id##_CLR_NB(base, v); } \
+ static inline void id##_TOG(u32 v) { id##_TOG_NB(base, v); }
+
+#define HW_REGISTER_FUNCS_INDEXED(id, base, offset, regset, rd, wr, step)\
+ static inline u32 id##_OFFSET(int i) { \
+ return offset + i * step; \
+ } \
+ static inline u32 id##_RD_NB(const void __iomem *regbase, int i) {\
+ if (!rd) \
+ printk(KERN_ERR"%s(%d): can't READ at %p+%x\n", \
+ #id, i, regbase, offset + i * step); \
+ return __raw_readl(regbase + offset + i * step); \
+ } \
+ static inline void id##_WR_NB(void __iomem *regbase, int i, u32 v) {\
+ if (!wr) \
+ printk(KERN_ERR"%s(%d): can't WRITE at %p+%x\n",\
+ #id, i, regbase, offset + i * step); \
+ __raw_writel(v, regbase + offset + i * step); \
+ } \
+ static inline void id##_SET_NB(void __iomem *regbase, int i, u32 v) {\
+ if (!wr) \
+ printk(KERN_ERR"%s(%d): can't SET at %p+%x\n", \
+ #id, i, regbase, offset + i * step); \
+ if (regset) \
+ __raw_writel(v, regbase + offset + \
+ i * step + HW_STMP3xxx_SET); \
+ else \
+ __raw_writel(v | __raw_readl(regbase + \
+ offset + i * step), \
+ regbase + offset + i * step); \
+ } \
+ static inline void id##_CLR_NB(void __iomem *regbase, int i, u32 v) {\
+ if (!wr) \
+ printk(KERN_ERR"%s(%d): cannot CLR at %p+%x\n", \
+ #id, i, regbase, offset + i * step); \
+ if (regset) \
+ __raw_writel(v, regbase + offset + \
+ i * step + HW_STMP3xxx_CLR); \
+ else \
+ __raw_writel(~v & __raw_readl(regbase + \
+ offset + i * step), \
+ regbase + offset + i * step); \
+ } \
+ static inline void id##_TOG_NB(void __iomem *regbase, int i, u32 v) {\
+ if (!wr) \
+ printk(KERN_ERR"%s(%d): cannot TOG at %p+%x\n", \
+ #id, i, regbase, offset + i * step); \
+ if (regset) \
+ __raw_writel(v, regbase + offset + \
+ i * step + HW_STMP3xxx_TOG); \
+ else \
+ __raw_writel(v ^ __raw_readl(regbase + offset \
+ + i * step), \
+ regbase + offset + i * step); \
+ } \
+ static inline u32 id##_RD(int i) \
+ { \
+ return id##_RD_NB(base, i); \
+ } \
+ static inline void id##_WR(int i, u32 v) \
+ { \
+ id##_WR_NB(base, i, v); \
+ } \
+ static inline void id##_SET(int i, u32 v) \
+ { \
+ id##_SET_NB(base, i, v); \
+ } \
+ static inline void id##_CLR(int i, u32 v) \
+ { \
+ id##_CLR_NB(base, i, v); \
+ } \
+ static inline void id##_TOG(int i, u32 v) \
+ { \
+ id##_TOG_NB(base, i, v); \
+ }
+
+#define HW_REGISTER_WO(id, base, offset)\
+ HW_REGISTER_FUNCS(id, base, offset, 1, 0, 1)
+#define HW_REGISTER_RO(id, base, offset)\
+ HW_REGISTER_FUNCS(id, base, offset, 1, 1, 0)
+#define HW_REGISTER(id, base, offset) \
+ HW_REGISTER_FUNCS(id, base, offset, 1, 1, 1)
+#define HW_REGISTER_0(id, base, offset) \
+ HW_REGISTER_FUNCS(id, base, offset, 0, 1, 1)
+#define HW_REGISTER_INDEXED(id, base, offset, step) \
+ HW_REGISTER_FUNCS_INDEXED(id, base, offset, 1, 1, 1, step)
+#define HW_REGISTER_RO_INDEXED(id, base, offset, step) \
+ HW_REGISTER_FUNCS_INDEXED(id, base, offset, 1, 1, 0, step)
+#define HW_REGISTER_0_INDEXED(id, base, offset, step) \
+ HW_REGISTER_FUNCS_INDEXED(id, base, offset, 0, 1, 1, step)
+#else /* __ASSEMBLER__ */
+#define HW_REGISTER_FUNCS(id, base, offset, regset, rd, wr)
+#define HW_REGISTER_FUNCS_INDEXED(id, base, offset, regset, rd, wr, step)
+#define HW_REGISTER_WO(id, base, offset)
+#define HW_REGISTER_RO(id, base, offset)
+#define HW_REGISTER(id, base, offset)
+#define HW_REGISTER_0(id, base, offset)
+#define HW_REGISTER_INDEXED(id, base, offset, step)
+#define HW_REGISTER_RO_INDEXED(id, base, offset, step)
+#define HW_REGISTER_0_INDEXED(id, base, offset, step)
+#endif /* __ASSEMBLER__ */
+
+#endif /* __ASM_PLAT_STMP3XXX_REGS_H */
diff --git a/arch/arm/plat-stmp3xxx/include/mach/system.h b/arch/arm/plat-stmp3xxx/include/mach/system.h
new file mode 100644
index 000000000000..dac48d267148
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/include/mach/system.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2005 Sigmatel Inc
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+#include <asm/proc-fns.h>
+#include <mach/regs-clkctrl.h>
+#include <mach/regs-power.h>
+
+static inline void arch_idle(void)
+{
+ /*
+ * This should do all the clock switching
+ * and wait for interrupt tricks
+ */
+
+ cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+ /* Set BATTCHRG to default value */
+ HW_POWER_CHARGE_WR(0x00010000);
+
+ /* Set MINPWR to default value */
+ HW_POWER_MINPWR_WR(0);
+
+ /* Reset digital side of chip (but not power or RTC) */
+ HW_CLKCTRL_RESET_WR(BM_CLKCTRL_RESET_DIG);
+
+ /* Should not return */
+}
+
+#endif
diff --git a/arch/arm/plat-stmp3xxx/include/mach/timex.h b/arch/arm/plat-stmp3xxx/include/mach/timex.h
new file mode 100644
index 000000000000..3373985d7a8e
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/include/mach/timex.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 1999 ARM Limited
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*
+ * System time clock is sourced from the 32k clock
+ */
+#define CLOCK_TICK_RATE (32768)
diff --git a/arch/arm/plat-stmp3xxx/include/mach/uncompress.h b/arch/arm/plat-stmp3xxx/include/mach/uncompress.h
new file mode 100644
index 000000000000..f79f5ee56cd4
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/include/mach/uncompress.h
@@ -0,0 +1,53 @@
+/*
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_PLAT_UNCOMPRESS_H
+#define __ASM_PLAT_UNCOMPRESS_H
+
+/*
+ * Register includes are for when the MMU enabled; we need to define our
+ * own stuff here for pre-MMU use
+ */
+#define UARTDBG_BASE 0x80070000
+#define UART(c) (((volatile unsigned *)UARTDBG_BASE)[c])
+
+/*
+ * This does not append a newline
+ */
+static void putc(char c)
+{
+ /* Wait for TX fifo empty */
+ while ((UART(6) & (1<<7)) == 0)
+ continue;
+
+ /* Write byte */
+ UART(0) = c;
+
+ /* Wait for last bit to exit the UART */
+ while (UART(6) & (1<<3))
+ continue;
+}
+
+static void flush(void)
+{
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+
+#define arch_decomp_wdog()
+
+#endif /* __ASM_PLAT_UNCOMPRESS_H */
diff --git a/arch/arm/plat-stmp3xxx/include/mach/vmalloc.h b/arch/arm/plat-stmp3xxx/include/mach/vmalloc.h
new file mode 100644
index 000000000000..541b880c1863
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/include/mach/vmalloc.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#define VMALLOC_END (0xF0000000)
diff --git a/arch/arm/plat-stmp3xxx/irq.c b/arch/arm/plat-stmp3xxx/irq.c
new file mode 100644
index 000000000000..cb3659096681
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/irq.c
@@ -0,0 +1,59 @@
+/*
+ * Freescale STMP37XX/STMP378X common interrupt handling code
+ *
+ * Author: Vladislav Buzov <vbuzov@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/sysdev.h>
+
+#include <mach/stmp3xxx.h>
+#include <mach/regs-icoll.h>
+
+void __init stmp3xxx_init_irq(struct irq_chip *chip)
+{
+ unsigned int i;
+
+ /* Reset the interrupt controller */
+ HW_ICOLL_CTRL_CLR(BM_ICOLL_CTRL_CLKGATE);
+ udelay(10);
+ HW_ICOLL_CTRL_CLR(BM_ICOLL_CTRL_SFTRST);
+ udelay(10);
+ HW_ICOLL_CTRL_SET(BM_ICOLL_CTRL_SFTRST);
+ while (!(HW_ICOLL_CTRL_RD() & BM_ICOLL_CTRL_CLKGATE))
+ continue;
+ HW_ICOLL_CTRL_CLR(BM_ICOLL_CTRL_SFTRST | BM_ICOLL_CTRL_CLKGATE);
+
+ /* Disable all interrupts initially */
+ for (i = 0; i < NR_REAL_IRQS; i++) {
+ chip->mask(i);
+ set_irq_chip(i, chip);
+ set_irq_handler(i, handle_level_irq);
+ set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+ }
+
+ /* Ensure vector is cleared */
+ HW_ICOLL_LEVELACK_WR(1);
+ HW_ICOLL_LEVELACK_WR(2);
+ HW_ICOLL_LEVELACK_WR(4);
+ HW_ICOLL_LEVELACK_WR(8);
+
+ HW_ICOLL_VECTOR_WR(0);
+ /* Barrier */
+ (void) HW_ICOLL_STAT_RD();
+}
+
diff --git a/arch/arm/plat-stmp3xxx/pinmux.c b/arch/arm/plat-stmp3xxx/pinmux.c
new file mode 100644
index 000000000000..9b28cc83f31c
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/pinmux.c
@@ -0,0 +1,545 @@
+/*
+ * Freescale STMP378X/STMP378X Pin Multiplexing
+ *
+ * Author: Vladislav Buzov <vbuzov@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/sysdev.h>
+#include <linux/string.h>
+#include <linux/bitops.h>
+#include <linux/sysdev.h>
+#include <linux/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-pinctrl.h>
+#include <mach/pins.h>
+#include <mach/pinmux.h>
+
+#define NR_BANKS ARRAY_SIZE(pinmux_banks)
+static struct stmp3xxx_pinmux_bank pinmux_banks[] = {
+ [0] = {
+ .hw_muxsel = {
+ HW_PINCTRL_MUXSEL0_ADDR,
+ HW_PINCTRL_MUXSEL1_ADDR
+ },
+ .hw_drive = {
+ HW_PINCTRL_DRIVE0_ADDR,
+ HW_PINCTRL_DRIVE1_ADDR,
+ HW_PINCTRL_DRIVE2_ADDR,
+ HW_PINCTRL_DRIVE3_ADDR
+ },
+ .hw_pull = HW_PINCTRL_PULL0_ADDR,
+ .functions = { 0x0, 0x1, 0x2, 0x3 },
+ .strengths = { 0x0, 0x1, 0x2, 0x3, 0xff },
+
+ .hw_gpio_read = HW_PINCTRL_DIN0_ADDR,
+ .hw_gpio_set = HW_PINCTRL_DOUT0_ADDR + HW_STMP3xxx_SET,
+ .hw_gpio_clr = HW_PINCTRL_DOUT0_ADDR + HW_STMP3xxx_CLR,
+ .hw_gpio_doe = HW_PINCTRL_DOE0_ADDR,
+ .irq = IRQ_GPIO0,
+
+ .pin2irq = HW_PINCTRL_PIN2IRQ0_ADDR,
+ .irqstat = HW_PINCTRL_IRQSTAT0_ADDR,
+ .irqlevel = HW_PINCTRL_IRQLEVEL0_ADDR,
+ .irqpolarity = HW_PINCTRL_IRQPOL0_ADDR,
+ .irqen = HW_PINCTRL_IRQEN0_ADDR,
+ },
+ [1] = {
+ .hw_muxsel = {
+ HW_PINCTRL_MUXSEL2_ADDR,
+ HW_PINCTRL_MUXSEL3_ADDR
+ },
+ .hw_drive = {
+ HW_PINCTRL_DRIVE4_ADDR,
+ HW_PINCTRL_DRIVE5_ADDR,
+ HW_PINCTRL_DRIVE6_ADDR,
+ HW_PINCTRL_DRIVE7_ADDR
+ },
+ .hw_pull = HW_PINCTRL_PULL1_ADDR,
+ .functions = { 0x0, 0x1, 0x2, 0x3 },
+ .strengths = { 0x0, 0x1, 0x2, 0x3, 0xff },
+
+ .hw_gpio_read = HW_PINCTRL_DIN1_ADDR,
+ .hw_gpio_set = HW_PINCTRL_DOUT1_ADDR + HW_STMP3xxx_SET,
+ .hw_gpio_clr = HW_PINCTRL_DOUT1_ADDR + HW_STMP3xxx_CLR,
+ .hw_gpio_doe = HW_PINCTRL_DOE1_ADDR,
+ .irq = IRQ_GPIO1,
+
+ .pin2irq = HW_PINCTRL_PIN2IRQ1_ADDR,
+ .irqstat = HW_PINCTRL_IRQSTAT1_ADDR,
+ .irqlevel = HW_PINCTRL_IRQLEVEL1_ADDR,
+ .irqpolarity = HW_PINCTRL_IRQPOL1_ADDR,
+ .irqen = HW_PINCTRL_IRQEN1_ADDR,
+ },
+ [2] = {
+ .hw_muxsel = {
+ HW_PINCTRL_MUXSEL4_ADDR,
+ HW_PINCTRL_MUXSEL5_ADDR,
+ },
+ .hw_drive = {
+ HW_PINCTRL_DRIVE8_ADDR,
+ HW_PINCTRL_DRIVE9_ADDR,
+ HW_PINCTRL_DRIVE10_ADDR,
+ HW_PINCTRL_DRIVE11_ADDR,
+ },
+ .hw_pull = HW_PINCTRL_PULL2_ADDR,
+ .functions = { 0x0, 0x1, 0x2, 0x3 },
+ .strengths = { 0x0, 0x1, 0x2, 0x1, 0x2 },
+
+ .hw_gpio_read = HW_PINCTRL_DIN2_ADDR,
+ .hw_gpio_set = HW_PINCTRL_DOUT2_ADDR + HW_STMP3xxx_SET,
+ .hw_gpio_clr = HW_PINCTRL_DOUT2_ADDR + HW_STMP3xxx_CLR,
+ .hw_gpio_doe = HW_PINCTRL_DOE2_ADDR,
+ .irq = IRQ_GPIO2,
+
+ .pin2irq = HW_PINCTRL_PIN2IRQ2_ADDR,
+ .irqstat = HW_PINCTRL_IRQSTAT2_ADDR,
+ .irqlevel = HW_PINCTRL_IRQLEVEL2_ADDR,
+ .irqpolarity = HW_PINCTRL_IRQPOL2_ADDR,
+ .irqen = HW_PINCTRL_IRQEN2_ADDR,
+ },
+ [3] = {
+ .hw_muxsel = {
+ HW_PINCTRL_MUXSEL6_ADDR,
+ HW_PINCTRL_MUXSEL7_ADDR,
+ },
+ .hw_drive = {
+ HW_PINCTRL_DRIVE12_ADDR,
+ HW_PINCTRL_DRIVE13_ADDR,
+ HW_PINCTRL_DRIVE14_ADDR,
+ NULL,
+ },
+ .hw_pull = HW_PINCTRL_PULL3_ADDR,
+ .functions = {0x0, 0x1, 0x2, 0x3},
+ .strengths = {0x0, 0x1, 0x2, 0x3, 0xff},
+ },
+};
+
+static inline struct stmp3xxx_pinmux_bank *
+stmp3xxx_pinmux_bank(unsigned id, unsigned *bank, unsigned *pin)
+{
+ unsigned b, p;
+
+ b = STMP3XXX_PINID_TO_BANK(id);
+ p = STMP3XXX_PINID_TO_PINNUM(id);
+ BUG_ON(b >= NR_BANKS);
+ if (bank)
+ *bank = b;
+ if (pin)
+ *pin = p;
+ return &pinmux_banks[b];
+}
+
+/* Check if requested pin is owned by caller */
+static int stmp3xxx_check_pin(unsigned id, const char *label)
+{
+ unsigned pin;
+ struct stmp3xxx_pinmux_bank *pm = stmp3xxx_pinmux_bank(id, NULL, &pin);
+
+ if (!test_bit(pin, &pm->pin_map)) {
+ printk(KERN_WARNING
+ "%s: Accessing free pin %x, caller %s\n",
+ __func__, id, label);
+
+ return -EINVAL;
+ }
+
+ if (label && pm->pin_labels[pin] &&
+ strcmp(label, pm->pin_labels[pin])) {
+ printk(KERN_WARNING
+ "%s: Wrong pin owner %x, caller %s owner %s\n",
+ __func__, id, label, pm->pin_labels[pin]);
+
+ return -EINVAL;
+ }
+ return 0;
+}
+
+void stmp3xxx_pin_strength(unsigned id, enum pin_strength strength,
+ const char *label)
+{
+ struct stmp3xxx_pinmux_bank *pbank;
+ void __iomem *hwdrive;
+ u32 shift, val;
+ u32 bank, pin;
+
+ pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
+ pr_debug("%s: label %s bank %d pin %d strength %d\n", __func__, label,
+ bank, pin, strength);
+
+ hwdrive = pbank->hw_drive[pin / HW_DRIVE_PIN_NUM];
+ shift = (pin % HW_DRIVE_PIN_NUM) * HW_DRIVE_PIN_LEN;
+ val = pbank->strengths[strength];
+ if (val == 0xff) {
+ printk(KERN_WARNING
+ "%s: strength is not supported for bank %d, caller %s",
+ __func__, bank, label);
+ return;
+ }
+
+ if (stmp3xxx_check_pin(id, label))
+ return;
+
+ pr_debug("%s: writing 0x%x to 0x%p register\n", __func__,
+ val << shift, hwdrive);
+ __raw_writel(HW_DRIVE_PINDRV_MASK << shift, hwdrive + HW_STMP3xxx_CLR);
+ __raw_writel(val << shift, hwdrive + HW_STMP3xxx_SET);
+}
+
+void stmp3xxx_pin_voltage(unsigned id, enum pin_voltage voltage,
+ const char *label)
+{
+ struct stmp3xxx_pinmux_bank *pbank;
+ void __iomem *hwdrive;
+ u32 shift;
+ u32 bank, pin;
+
+ pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
+ pr_debug("%s: label %s bank %d pin %d voltage %d\n", __func__, label,
+ bank, pin, voltage);
+
+ hwdrive = pbank->hw_drive[pin / HW_DRIVE_PIN_NUM];
+ shift = (pin % HW_DRIVE_PIN_NUM) * HW_DRIVE_PIN_LEN;
+
+ if (stmp3xxx_check_pin(id, label))
+ return;
+
+ pr_debug("%s: changing 0x%x bit in 0x%p register\n",
+ __func__, HW_DRIVE_PINV_MASK << shift, hwdrive);
+ if (voltage == PIN_1_8V)
+ __raw_writel(HW_DRIVE_PINV_MASK << shift,
+ hwdrive + HW_STMP3xxx_CLR);
+ else
+ __raw_writel(HW_DRIVE_PINV_MASK << shift,
+ hwdrive + HW_STMP3xxx_SET);
+}
+
+void stmp3xxx_pin_pullup(unsigned id, int enable, const char *label)
+{
+ struct stmp3xxx_pinmux_bank *pbank;
+ void __iomem *hwpull;
+ u32 bank, pin;
+
+ pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
+ pr_debug("%s: label %s bank %d pin %d enable %d\n", __func__, label,
+ bank, pin, enable);
+
+ hwpull = pbank->hw_pull;
+
+ if (stmp3xxx_check_pin(id, label))
+ return;
+
+ pr_debug("%s: changing 0x%x bit in 0x%p register\n",
+ __func__, 1 << pin, hwpull);
+ __raw_writel(1 << pin,
+ hwpull + (enable ? HW_STMP3xxx_SET : HW_STMP3xxx_CLR));
+}
+
+int stmp3xxx_request_pin(unsigned id, enum pin_fun fun, const char *label)
+{
+ struct stmp3xxx_pinmux_bank *pbank;
+ u32 bank, pin;
+ int ret = 0;
+
+ pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
+ pr_debug("%s: label %s bank %d pin %d fun %d\n", __func__, label,
+ bank, pin, fun);
+
+ if (test_bit(pin, &pbank->pin_map)) {
+ printk(KERN_WARNING
+ "%s: CONFLICT DETECTED pin %d:%d caller %s owner %s\n",
+ __func__, bank, pin, label, pbank->pin_labels[pin]);
+ return -EBUSY;
+ }
+
+ set_bit(pin, &pbank->pin_map);
+ pbank->pin_labels[pin] = label;
+
+ stmp3xxx_set_pin_type(id, fun);
+
+ return ret;
+}
+
+void stmp3xxx_set_pin_type(unsigned id, enum pin_fun fun)
+{
+ struct stmp3xxx_pinmux_bank *pbank;
+ void __iomem *hwmux;
+ u32 shift, val;
+ u32 bank, pin;
+
+ pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
+
+ hwmux = pbank->hw_muxsel[pin / HW_MUXSEL_PIN_NUM];
+ shift = (pin % HW_MUXSEL_PIN_NUM) * HW_MUXSEL_PIN_LEN;
+
+ val = pbank->functions[fun];
+ shift = (pin % HW_MUXSEL_PIN_NUM) * HW_MUXSEL_PIN_LEN;
+ pr_debug("%s: writing 0x%x to 0x%p register\n",
+ __func__, val << shift, hwmux);
+ __raw_writel(HW_MUXSEL_PINFUN_MASK << shift, hwmux + HW_STMP3xxx_CLR);
+ __raw_writel(val << shift, hwmux + HW_STMP3xxx_SET);
+}
+
+void stmp3xxx_release_pin(unsigned id, const char *label)
+{
+ struct stmp3xxx_pinmux_bank *pbank;
+ u32 bank, pin;
+
+ pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
+ pr_debug("%s: label %s bank %d pin %d\n", __func__, label, bank, pin);
+
+ if (stmp3xxx_check_pin(id, label))
+ return;
+
+ clear_bit(pin, &pbank->pin_map);
+ pbank->pin_labels[pin] = NULL;
+}
+
+int stmp3xxx_request_pin_group(struct pin_group *pin_group, const char *label)
+{
+ struct pin_desc *pin;
+ int p;
+ int err = 0;
+
+ /* Allocate and configure pins */
+ for (p = 0; p < pin_group->nr_pins; p++) {
+ pr_debug("%s: #%d\n", __func__, p);
+ pin = &pin_group->pins[p];
+
+ err = stmp3xxx_request_pin(pin->id, pin->fun, label);
+ if (err)
+ goto out_err;
+
+ stmp3xxx_pin_strength(pin->id, pin->strength, label);
+ stmp3xxx_pin_voltage(pin->id, pin->voltage, label);
+ stmp3xxx_pin_pullup(pin->id, pin->pullup, label);
+ }
+
+ return 0;
+
+out_err:
+ /* Release allocated pins in case of error */
+ while (--p >= 0) {
+ pr_debug("%s: releasing #%d\n", __func__, p);
+ stmp3xxx_release_pin(pin_group->pins[p].id, label);
+ }
+ return err;
+}
+EXPORT_SYMBOL(stmp3xxx_request_pin_group);
+
+void stmp3xxx_release_pin_group(struct pin_group *pin_group, const char *label)
+{
+ struct pin_desc *pin;
+ int p;
+
+ for (p = 0; p < pin_group->nr_pins; p++) {
+ pin = &pin_group->pins[p];
+ stmp3xxx_release_pin(pin->id, label);
+ }
+}
+EXPORT_SYMBOL(stmp3xxx_release_pin_group);
+
+static int stmp3xxx_irq_to_gpio(int irq,
+ struct stmp3xxx_pinmux_bank **bank, unsigned *gpio)
+{
+ struct stmp3xxx_pinmux_bank *pm;
+
+ for (pm = pinmux_banks; pm < pinmux_banks + NR_BANKS; pm++)
+ if (pm->virq <= irq && irq < pm->virq + 32) {
+ *bank = pm;
+ *gpio = irq - pm->virq;
+ return 0;
+ }
+ return -ENOENT;
+}
+
+static int stmp3xxx_set_irqtype(unsigned irq, unsigned type)
+{
+ struct stmp3xxx_pinmux_bank *pm;
+ unsigned gpio;
+ int l, p;
+
+ stmp3xxx_irq_to_gpio(irq, &pm, &gpio);
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ l = 0; p = 1; break;
+ case IRQ_TYPE_EDGE_FALLING:
+ l = 0; p = 0; break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ l = 1; p = 1; break;
+ case IRQ_TYPE_LEVEL_LOW:
+ l = 1; p = 0; break;
+ default:
+ pr_debug("%s: Incorrect GPIO interrupt type 0x%x\n",
+ __func__, type);
+ return -ENXIO;
+ }
+ __raw_writel(1 << gpio,
+ pm->irqlevel + (l ? HW_STMP3xxx_SET : HW_STMP3xxx_CLR));
+ __raw_writel(1 << gpio,
+ pm->irqpolarity + (p ? HW_STMP3xxx_SET : HW_STMP3xxx_CLR));
+ return 0;
+}
+
+static void stmp3xxx_pin_ack_irq(unsigned irq)
+{
+ u32 stat;
+ struct stmp3xxx_pinmux_bank *pm;
+ unsigned gpio;
+
+ stmp3xxx_irq_to_gpio(irq, &pm, &gpio);
+ stat = __raw_readl(pm->irqstat) & (1<<gpio);
+ __raw_writel(stat, pm->irqstat + HW_STMP3xxx_CLR);
+}
+
+static void stmp3xxx_pin_mask_irq(unsigned irq)
+{
+ struct stmp3xxx_pinmux_bank *pm;
+ unsigned gpio;
+
+ stmp3xxx_irq_to_gpio(irq, &pm, &gpio);
+ __raw_writel(1 << gpio, pm->irqen + HW_STMP3xxx_CLR);
+ __raw_writel(1 << gpio, pm->pin2irq + HW_STMP3xxx_CLR);
+}
+
+static void stmp3xxx_pin_unmask_irq(unsigned irq)
+{
+ struct stmp3xxx_pinmux_bank *pm;
+ unsigned gpio;
+
+ stmp3xxx_irq_to_gpio(irq, &pm, &gpio);
+ __raw_writel(1 << gpio, pm->irqen + HW_STMP3xxx_SET);
+ __raw_writel(1 << gpio, pm->pin2irq + HW_STMP3xxx_SET);
+}
+
+static inline
+struct stmp3xxx_pinmux_bank *to_pinmux_bank(struct gpio_chip *chip)
+{
+ return container_of(chip, struct stmp3xxx_pinmux_bank, chip);
+}
+
+static int stmp3xxx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip);
+ return pm->virq + offset;
+}
+
+static int stmp3xxx_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip);
+ unsigned v;
+
+ v = __raw_readl(pm->hw_gpio_read) & (1 << offset);
+ return v ? 1 : 0;
+}
+
+static void stmp3xxx_gpio_set(struct gpio_chip *chip, unsigned offset, int v)
+{
+ struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip);
+
+ __raw_writel(1 << offset, v ? pm->hw_gpio_set : pm->hw_gpio_clr);
+}
+
+static int stmp3xxx_gpio_output(struct gpio_chip *chip, unsigned offset, int v)
+{
+ struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip);
+
+ __raw_writel(1 << offset, pm->hw_gpio_doe + HW_STMP3xxx_SET);
+ stmp3xxx_gpio_set(chip, offset, v);
+ return 0;
+}
+
+static int stmp3xxx_gpio_input(struct gpio_chip *chip, unsigned offset)
+{
+ struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip);
+
+ __raw_writel(1 << offset, pm->hw_gpio_doe + HW_STMP3xxx_CLR);
+ return 0;
+}
+
+static int stmp3xxx_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ return stmp3xxx_request_pin(chip->base + offset, PIN_GPIO, "gpio");
+}
+
+static void stmp3xxx_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+ stmp3xxx_release_pin(chip->base + offset, "gpio");
+}
+
+static void stmp3xxx_gpio_irq(u32 irq, struct irq_desc *desc)
+{
+ struct stmp3xxx_pinmux_bank *pm = get_irq_data(irq);
+ int gpio_irq = pm->virq;
+ u32 stat = __raw_readl(pm->irqstat);
+
+ while (stat) {
+ if (stat & 1)
+ irq_desc[gpio_irq].handle_irq(gpio_irq,
+ &irq_desc[gpio_irq]);
+ gpio_irq++;
+ stat >>= 1;
+ }
+}
+
+static struct irq_chip gpio_irq_chip = {
+ .ack = stmp3xxx_pin_ack_irq,
+ .mask = stmp3xxx_pin_mask_irq,
+ .unmask = stmp3xxx_pin_unmask_irq,
+ .set_type = stmp3xxx_set_irqtype,
+};
+
+int __init stmp3xxx_pinmux_init(int virtual_irq_start)
+{
+ int b, r = 0;
+ struct stmp3xxx_pinmux_bank *pm;
+ int virq;
+
+ for (b = 0; b < 3; b++) {
+ /* only banks 0,1,2 are allowed to GPIO */
+ pm = pinmux_banks + b;
+ pm->chip.base = 32 * b;
+ pm->chip.ngpio = 32;
+ pm->chip.owner = THIS_MODULE;
+ pm->chip.can_sleep = 1;
+ pm->chip.exported = 1;
+ pm->chip.to_irq = stmp3xxx_gpio_to_irq;
+ pm->chip.direction_input = stmp3xxx_gpio_input;
+ pm->chip.direction_output = stmp3xxx_gpio_output;
+ pm->chip.get = stmp3xxx_gpio_get;
+ pm->chip.set = stmp3xxx_gpio_set;
+ pm->chip.request = stmp3xxx_gpio_request;
+ pm->chip.free = stmp3xxx_gpio_free;
+ pm->virq = virtual_irq_start + b * 32;
+
+ for (virq = pm->virq; virq < pm->virq; virq++) {
+ gpio_irq_chip.mask(virq);
+ set_irq_chip(virq, &gpio_irq_chip);
+ set_irq_handler(virq, handle_level_irq);
+ set_irq_flags(virq, IRQF_VALID);
+ }
+ r = gpiochip_add(&pm->chip);
+ if (r < 0)
+ break;
+ set_irq_chained_handler(pm->irq, stmp3xxx_gpio_irq);
+ set_irq_data(pm->irq, pm);
+ }
+ return r;
+}
+
+MODULE_AUTHOR("Vladislav Buzov");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-stmp3xxx/timer.c b/arch/arm/plat-stmp3xxx/timer.c
new file mode 100644
index 000000000000..7d872f0aee70
--- /dev/null
+++ b/arch/arm/plat-stmp3xxx/timer.c
@@ -0,0 +1,172 @@
+/*
+ * System timer for Freescale STMP37XX/STMP378X
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/mach/time.h>
+#include <mach/stmp3xxx.h>
+#include <mach/regs-timrot.h>
+
+static irqreturn_t
+stmp3xxx_timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *c = dev_id;
+
+ if (HW_TIMROT_TIMCTRLn_RD(0) & (1<<15)) {
+ HW_TIMROT_TIMCTRLn_CLR(0, (1<<15));
+ c->event_handler(c);
+ } else if (HW_TIMROT_TIMCTRLn_RD(1) & (1<<15)) {
+ HW_TIMROT_TIMCTRLn_CLR(1, (1<<15));
+ HW_TIMROT_TIMCTRLn_CLR(1, BM_TIMROT_TIMCTRLn_IRQ_EN);
+ HW_TIMROT_TIMCOUNTn_WR(1, 0xFFFF);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static cycle_t stmp3xxx_clock_read(struct clocksource *cs)
+{
+ return ~((HW_TIMROT_TIMCOUNTn_RD(1) & 0xFFFF0000) >> 16);
+}
+
+static int
+stmp3xxx_timrot_set_next_event(unsigned long delta,
+ struct clock_event_device *dev)
+{
+ HW_TIMROT_TIMCOUNTn_WR(0, delta); /* reload */
+ return 0;
+}
+
+static void
+stmp3xxx_timrot_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *dev)
+{
+}
+
+static struct clock_event_device ckevt_timrot = {
+ .name = "timrot",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .shift = 32,
+ .set_next_event = stmp3xxx_timrot_set_next_event,
+ .set_mode = stmp3xxx_timrot_set_mode,
+};
+
+static struct clocksource cksrc_stmp3xxx = {
+ .name = "cksrc_stmp3xxx",
+ .rating = 250,
+ .read = stmp3xxx_clock_read,
+ .mask = CLOCKSOURCE_MASK(16),
+ .shift = 10,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static struct irqaction stmp3xxx_timer_irq = {
+ .name = "stmp3xxx_timer",
+ .flags = IRQF_DISABLED | IRQF_TIMER,
+ .handler = stmp3xxx_timer_interrupt,
+ .dev_id = &ckevt_timrot,
+};
+
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ */
+static void __init stmp3xxx_init_timer(void)
+{
+ cksrc_stmp3xxx.mult = clocksource_hz2mult(CLOCK_TICK_RATE,
+ cksrc_stmp3xxx.shift);
+ ckevt_timrot.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
+ ckevt_timrot.shift);
+ ckevt_timrot.min_delta_ns = clockevent_delta2ns(2, &ckevt_timrot);
+ ckevt_timrot.max_delta_ns = clockevent_delta2ns(0xFFF, &ckevt_timrot);
+ ckevt_timrot.cpumask = cpumask_of(0);
+
+ HW_TIMROT_ROTCTRL_CLR(BM_TIMROT_ROTCTRL_SFTRST |
+ BM_TIMROT_ROTCTRL_CLKGATE);
+ HW_TIMROT_TIMCOUNTn_WR(0, 0);
+ HW_TIMROT_TIMCOUNTn_WR(1, 0);
+
+ HW_TIMROT_TIMCTRLn_WR(0,
+ (BF_TIMROT_TIMCTRLn_SELECT(8) | /* 32 kHz */
+ BF_TIMROT_TIMCTRLn_PRESCALE(0) |
+ BM_TIMROT_TIMCTRLn_RELOAD |
+ BM_TIMROT_TIMCTRLn_UPDATE |
+ BM_TIMROT_TIMCTRLn_IRQ_EN));
+ HW_TIMROT_TIMCTRLn_WR(1,
+ (BF_TIMROT_TIMCTRLn_SELECT(8) | /* 32 kHz */
+ BF_TIMROT_TIMCTRLn_PRESCALE(0) |
+ BM_TIMROT_TIMCTRLn_RELOAD |
+ BM_TIMROT_TIMCTRLn_UPDATE));
+
+ HW_TIMROT_TIMCOUNTn_WR(0, CLOCK_TICK_RATE / HZ - 1);
+ HW_TIMROT_TIMCOUNTn_WR(1, 0xFFFF); /* reload */
+
+ setup_irq(IRQ_TIMER0, &stmp3xxx_timer_irq);
+
+ clocksource_register(&cksrc_stmp3xxx);
+ clockevents_register_device(&ckevt_timrot);
+}
+
+#ifdef CONFIG_PM
+
+void stmp3xxx_suspend_timer(void)
+{
+ HW_TIMROT_TIMCTRLn_CLR(0, BM_TIMROT_TIMCTRLn_IRQ_EN);
+ HW_TIMROT_TIMCTRLn_CLR(0, (1<<15));
+ HW_TIMROT_ROTCTRL_SET(BM_TIMROT_ROTCTRL_CLKGATE);
+}
+
+void stmp3xxx_resume_timer(void)
+{
+ HW_TIMROT_ROTCTRL_CLR(BM_TIMROT_ROTCTRL_SFTRST |
+ BM_TIMROT_ROTCTRL_CLKGATE);
+
+
+ HW_TIMROT_TIMCTRLn_WR(0,
+ (BF_TIMROT_TIMCTRLn_SELECT(8) | /* 32 kHz */
+ BF_TIMROT_TIMCTRLn_PRESCALE(0) |
+ BM_TIMROT_TIMCTRLn_UPDATE |
+ BM_TIMROT_TIMCTRLn_IRQ_EN));
+ HW_TIMROT_TIMCTRLn_WR(1,
+ (BF_TIMROT_TIMCTRLn_SELECT(8) | /* 32 kHz */
+ BF_TIMROT_TIMCTRLn_PRESCALE(0) |
+ BM_TIMROT_TIMCTRLn_RELOAD |
+ BM_TIMROT_TIMCTRLn_UPDATE));
+
+ HW_TIMROT_TIMCOUNTn_WR(0, CLOCK_TICK_RATE / HZ - 1);
+ HW_TIMROT_TIMCOUNTn_WR(1, 0xFFFF); /* reload */
+}
+
+#else
+
+#define stmp3xxx_suspend_timer NULL
+#define stmp3xxx_resume_timer NULL
+
+#endif /* CONFIG_PM */
+
+struct sys_timer stmp3xxx_timer = {
+ .init = stmp3xxx_init_timer,
+ .suspend = stmp3xxx_suspend_timer,
+ .resume = stmp3xxx_resume_timer,
+};
diff --git a/arch/avr32/Makefile b/arch/avr32/Makefile
index 0b97e14f73f6..c21a3290d542 100644
--- a/arch/avr32/Makefile
+++ b/arch/avr32/Makefile
@@ -43,8 +43,6 @@ core-y += arch/avr32/mm/
drivers-$(CONFIG_OPROFILE) += arch/avr32/oprofile/
libs-y += arch/avr32/lib/
-CLEAN_FILES += include/asm-avr32/.arch include/asm-avr32/arch
-
BOOT_TARGETS := vmlinux.elf vmlinux.bin uImage uImage.srec
.PHONY: $(BOOT_TARGETS) install
diff --git a/arch/avr32/boards/merisc/setup.c b/arch/avr32/boards/merisc/setup.c
index 20b300cf105a..623b077594fc 100644
--- a/arch/avr32/boards/merisc/setup.c
+++ b/arch/avr32/boards/merisc/setup.c
@@ -94,9 +94,10 @@ static struct spi_board_info __initdata spi0_board_info[] = {
static struct mci_platform_data __initdata mci0_data = {
.slot[0] = {
- .bus_width = 4,
- .detect_pin = GPIO_PIN_PE(19),
- .wp_pin = GPIO_PIN_PE(20),
+ .bus_width = 4,
+ .detect_pin = GPIO_PIN_PE(19),
+ .wp_pin = GPIO_PIN_PE(20),
+ .detect_is_active_high = true,
},
};
diff --git a/arch/avr32/kernel/time.c b/arch/avr32/kernel/time.c
index 0ff46bf873b0..f27aa3b259fa 100644
--- a/arch/avr32/kernel/time.c
+++ b/arch/avr32/kernel/time.c
@@ -18,7 +18,7 @@
#include <mach/pm.h>
-static cycle_t read_cycle_count(void)
+static cycle_t read_cycle_count(struct clocksource *cs)
{
return (cycle_t)sysreg_read(COUNT);
}
diff --git a/arch/blackfin/kernel/time-ts.c b/arch/blackfin/kernel/time-ts.c
index 0ed2badfd746..27646121280a 100644
--- a/arch/blackfin/kernel/time-ts.c
+++ b/arch/blackfin/kernel/time-ts.c
@@ -58,16 +58,11 @@ static inline unsigned long long cycles_2_ns(cycle_t cyc)
return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
}
-static cycle_t read_cycles(void)
+static cycle_t read_cycles(struct clocksource *cs)
{
return __bfin_cycles_off + (get_cycles() << __bfin_cycles_mod);
}
-unsigned long long sched_clock(void)
-{
- return cycles_2_ns(read_cycles());
-}
-
static struct clocksource clocksource_bfin = {
.name = "bfin_cycles",
.rating = 350,
@@ -77,6 +72,11 @@ static struct clocksource clocksource_bfin = {
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
+unsigned long long sched_clock(void)
+{
+ return cycles_2_ns(read_cycles(&clocksource_bfin));
+}
+
static int __init bfin_clocksource_init(void)
{
set_cyc2ns_scale(get_cclk() / 1000);
diff --git a/arch/cris/Makefile b/arch/cris/Makefile
index 3662cfb7b61d..71e17d3eeddb 100644
--- a/arch/cris/Makefile
+++ b/arch/cris/Makefile
@@ -70,7 +70,7 @@ SRC_ARCH = $(srctree)/arch/cris
# cris object files path
OBJ_ARCH = $(objtree)/arch/cris
-boot := arch/cris/$(SARCH)/boot
+boot := arch/cris/boot
MACHINE := arch/cris/$(SARCH)
all: zImage
@@ -81,15 +81,15 @@ zImage Image: vmlinux
archprepare:
archclean:
- $(Q)if [ -e arch/cris/$(SARCH)/boot ]; then \
- $(MAKE) $(clean)=arch/cris/$(SARCH)/boot; \
+ $(Q)if [ -e arch/cris/boot ]; then \
+ $(MAKE) $(clean)=arch/cris/boot; \
fi
CLEAN_FILES += \
- $(MACHINE)/boot/zImage \
- $(MACHINE)/boot/compressed/decompress.bin \
- $(MACHINE)/boot/compressed/piggy.gz \
- $(MACHINE)/boot/rescue/rescue.bin
+ $(boot)/zImage \
+ $(boot)/compressed/decompress.bin \
+ $(boot)/compressed/piggy.gz \
+ $(boot)/rescue/rescue.bin
# MRPROPER_FILES +=
diff --git a/arch/cris/arch-v10/boot/compressed/README b/arch/cris/arch-v10/boot/compressed/README
deleted file mode 100644
index 48b3db9924b9..000000000000
--- a/arch/cris/arch-v10/boot/compressed/README
+++ /dev/null
@@ -1,25 +0,0 @@
-Creation of the self-extracting compressed kernel image (vmlinuz)
------------------------------------------------------------------
-$Id: README,v 1.1 2001/12/17 13:59:27 bjornw Exp $
-
-This can be slightly confusing because it's a process with many steps.
-
-The kernel object built by the arch/etrax100/Makefile, vmlinux, is split
-by that makefile into text and data binary files, vmlinux.text and
-vmlinux.data.
-
-Those files together with a ROM filesystem can be catted together and
-burned into a flash or executed directly at the DRAM origin.
-
-They can also be catted together and compressed with gzip, which is what
-happens in this makefile. Together they make up piggy.img.
-
-The decompressor is built into the file decompress.o. It is turned into
-the binary file decompress.bin, which is catted together with piggy.img
-into the file vmlinuz. It can be executed in an arbitrary place in flash.
-
-Be careful - it assumes some things about free locations in DRAM. It
-assumes the DRAM starts at 0x40000000 and that it is at least 8 MB,
-so it puts its code at 0x40700000, and initial stack at 0x40800000.
-
--Bjorn
diff --git a/arch/cris/arch-v10/boot/compressed/misc.c b/arch/cris/arch-v10/boot/compressed/misc.c
deleted file mode 100644
index a4db1507d3b1..000000000000
--- a/arch/cris/arch-v10/boot/compressed/misc.c
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * misc.c
- *
- * This is a collection of several routines from gzip-1.0.3
- * adapted for Linux.
- *
- * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
- * puts by Nick Holloway 1993, better puts by Martin Mares 1995
- * adaptation for Linux/CRIS Axis Communications AB, 1999
- *
- */
-
-/* where the piggybacked kernel image expects itself to live.
- * it is the same address we use when we network load an uncompressed
- * image into DRAM, and it is the address the kernel is linked to live
- * at by vmlinux.lds.S
- */
-
-#define KERNEL_LOAD_ADR 0x40004000
-
-
-#include <linux/types.h>
-#include <arch/svinto.h>
-
-/*
- * gzip declarations
- */
-
-#define OF(args) args
-#define STATIC static
-
-void *memset(void *s, int c, size_t n);
-void *memcpy(void *__dest, __const void *__src, size_t __n);
-
-#define memzero(s, n) memset((s), 0, (n))
-
-typedef unsigned char uch;
-typedef unsigned short ush;
-typedef unsigned long ulg;
-
-#define WSIZE 0x8000 /* Window size must be at least 32k, */
- /* and a power of two */
-
-static uch *inbuf; /* input buffer */
-static uch window[WSIZE]; /* Sliding window buffer */
-
-unsigned inptr = 0; /* index of next byte to be processed in inbuf
- * After decompression it will contain the
- * compressed size, and head.S will read it.
- */
-
-static unsigned outcnt = 0; /* bytes in output buffer */
-
-/* gzip flag byte */
-#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
-#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
-#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
-#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
-#define COMMENT 0x10 /* bit 4 set: file comment present */
-#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
-#define RESERVED 0xC0 /* bit 6,7: reserved */
-
-#define get_byte() (inbuf[inptr++])
-
-/* Diagnostic functions */
-#ifdef DEBUG
-# define Assert(cond, msg) do { \
- if (!(cond)) \
- error(msg); \
- } while (0)
-# define Trace(x) fprintf x
-# define Tracev(x) do { \
- if (verbose) \
- fprintf x; \
- } while (0)
-# define Tracevv(x) do { \
- if (verbose > 1) \
- fprintf x; \
- } while (0)
-# define Tracec(c, x) do { \
- if (verbose && (c)) \
- fprintf x; \
- } while (0)
-# define Tracecv(c, x) do { \
- if (verbose > 1 && (c)) \
- fprintf x; \
- } while (0)
-#else
-# define Assert(cond, msg)
-# define Trace(x)
-# define Tracev(x)
-# define Tracevv(x)
-# define Tracec(c, x)
-# define Tracecv(c, x)
-#endif
-
-static void flush_window(void);
-static void error(char *m);
-
-extern char *input_data; /* lives in head.S */
-
-static long bytes_out = 0;
-static uch *output_data;
-static unsigned long output_ptr = 0;
-static void puts(const char *);
-
-/* the "heap" is put directly after the BSS ends, at end */
-
-extern int _end;
-static long free_mem_ptr = (long)&_end;
-static long free_mem_end_ptr;
-
-#include "../../../../../lib/inflate.c"
-
-/* decompressor info and error messages to serial console */
-
-static void
-puts(const char *s)
-{
-#ifndef CONFIG_ETRAX_DEBUG_PORT_NULL
- while (*s) {
-#ifdef CONFIG_ETRAX_DEBUG_PORT0
- while (!(*R_SERIAL0_STATUS & (1 << 5))) ;
- *R_SERIAL0_TR_DATA = *s++;
-#endif
-#ifdef CONFIG_ETRAX_DEBUG_PORT1
- while (!(*R_SERIAL1_STATUS & (1 << 5))) ;
- *R_SERIAL1_TR_DATA = *s++;
-#endif
-#ifdef CONFIG_ETRAX_DEBUG_PORT2
- while (!(*R_SERIAL2_STATUS & (1 << 5))) ;
- *R_SERIAL2_TR_DATA = *s++;
-#endif
-#ifdef CONFIG_ETRAX_DEBUG_PORT3
- while (!(*R_SERIAL3_STATUS & (1 << 5))) ;
- *R_SERIAL3_TR_DATA = *s++;
-#endif
- }
-#endif
-}
-
-void *memset(void *s, int c, size_t n)
-{
- int i;
- char *ss = (char *)s;
-
- for (i = 0; i < n; i++)
- ss[i] = c;
-
- return s;
-}
-
-void *memcpy(void *__dest, __const void *__src, size_t __n)
-{
- int i;
- char *d = (char *)__dest, *s = (char *)__src;
-
- for (i = 0; i < __n; i++)
- d[i] = s[i];
-
- return __dest;
-}
-
-/* ===========================================================================
- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
- * (Used for the decompressed data only.)
- */
-
-static void flush_window(void)
-{
- ulg c = crc; /* temporary variable */
- unsigned n;
- uch *in, *out, ch;
-
- in = window;
- out = &output_data[output_ptr];
- for (n = 0; n < outcnt; n++) {
- ch = *out = *in;
- out++;
- in++;
- c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
- }
- crc = c;
- bytes_out += (ulg)outcnt;
- output_ptr += (ulg)outcnt;
- outcnt = 0;
-}
-
-static void error(char *x)
-{
- puts("\n\n");
- puts(x);
- puts("\n\n -- System halted\n");
-
- while (1); /* Halt */
-}
-
-void setup_normal_output_buffer(void)
-{
- output_data = (char *)KERNEL_LOAD_ADR;
-}
-
-void decompress_kernel(void)
-{
- char revision;
-
- /* input_data is set in head.S */
- inbuf = input_data;
-
-#ifdef CONFIG_ETRAX_DEBUG_PORT0
- *R_SERIAL0_XOFF = 0;
- *R_SERIAL0_BAUD = 0x99;
- *R_SERIAL0_TR_CTRL = 0x40;
-#endif
-#ifdef CONFIG_ETRAX_DEBUG_PORT1
- *R_SERIAL1_XOFF = 0;
- *R_SERIAL1_BAUD = 0x99;
- *R_SERIAL1_TR_CTRL = 0x40;
-#endif
-#ifdef CONFIG_ETRAX_DEBUG_PORT2
- *R_GEN_CONFIG = 0x08;
- *R_SERIAL2_XOFF = 0;
- *R_SERIAL2_BAUD = 0x99;
- *R_SERIAL2_TR_CTRL = 0x40;
-#endif
-#ifdef CONFIG_ETRAX_DEBUG_PORT3
- *R_GEN_CONFIG = 0x100;
- *R_SERIAL3_XOFF = 0;
- *R_SERIAL3_BAUD = 0x99;
- *R_SERIAL3_TR_CTRL = 0x40;
-#endif
-
- setup_normal_output_buffer();
-
- makecrc();
-
- __asm__ volatile ("move $vr,%0" : "=rm" (revision));
- if (revision < 10) {
- puts("You need an ETRAX 100LX to run linux 2.6\n");
- while (1);
- }
-
- puts("Uncompressing Linux...\n");
- gunzip();
- puts("Done. Now booting the kernel.\n");
-}
diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S
index 72f5cd319b97..2c18d08cd913 100644
--- a/arch/cris/arch-v10/kernel/entry.S
+++ b/arch/cris/arch-v10/kernel/entry.S
@@ -536,10 +536,10 @@ multiple_interrupt:
movem $r13, [$sp]
push $r10 ; push orig_r10
clear.d [$sp=$sp-4] ; frametype == 0, normal frame
-
+
move.d $sp, $r10
jsr do_multiple_IRQ
-
+
jump ret_from_intr
do_sigtrap:
@@ -585,7 +585,7 @@ _ugdb_handle_breakpoint:
pop $r0 ; Restore r0.
ba do_sigtrap ; SIGTRAP the offending process.
pop $dccr ; Restore dccr in delay slot.
-
+
.global kernel_execve
kernel_execve:
move.d __NR_execve, $r9
@@ -929,6 +929,14 @@ sys_call_table:
.long sys_fallocate
.long sys_timerfd_settime /* 325 */
.long sys_timerfd_gettime
+ .long sys_signalfd4
+ .long sys_eventfd2
+ .long sys_epoll_create1
+ .long sys_dup3 /* 330 */
+ .long sys_pipe2
+ .long sys_inotify_init1
+ .long sys_preadv
+ .long sys_pwritev
/*
* NOTE!! This doesn't have to be exact - we just have
diff --git a/arch/cris/arch-v32/boot/Makefile b/arch/cris/arch-v32/boot/Makefile
deleted file mode 100644
index 99896ad60b30..000000000000
--- a/arch/cris/arch-v32/boot/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# arch/cris/arch-v32/boot/Makefile
-#
-
-OBJCOPYFLAGS = -O binary -R .note -R .comment
-
-subdir- := compressed rescue
-targets := Image
-
-$(obj)/Image: vmlinux FORCE
- $(call if_changed,objcopy)
- @echo ' Kernel: $@ is ready'
-
-$(obj)/compressed/vmlinux: $(obj)/Image FORCE
- $(Q)$(MAKE) $(build)=$(obj)/compressed $@
- $(Q)$(MAKE) $(build)=$(obj)/rescue $(obj)/rescue/rescue.bin
-
-$(obj)/zImage: $(obj)/compressed/vmlinux
- @cp $< $@
- @echo ' Kernel: $@ is ready'
diff --git a/arch/cris/arch-v32/boot/compressed/Makefile b/arch/cris/arch-v32/boot/compressed/Makefile
deleted file mode 100644
index e176b8b69d92..000000000000
--- a/arch/cris/arch-v32/boot/compressed/Makefile
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# arch/cris/arch-v32/boot/compressed/Makefile
-#
-
-asflags-y += -I$(srctree)/include/asm/mach/ -I$(srctree)/include/asm/arch
-ccflags-y += -O2 -I$(srctree)/include/asm/mach/ -I$(srctree)/include/asm/arch
-ldflags-y += -T$(srctree)/$(src)/decompress.lds
-OBJECTS = $(obj)/head.o $(obj)/misc.o
-OBJCOPYFLAGS = -O binary --remove-section=.bss
-
-quiet_cmd_image = BUILD $@
-cmd_image = cat $(obj)/decompress.bin $(obj)/piggy.gz > $@
-
-targets := vmlinux piggy.gz decompress.o decompress.bin
-
-$(obj)/decompress.o: $(OBJECTS) FORCE
- $(call if_changed,ld)
-
-$(obj)/decompress.bin: $(obj)/decompress.o FORCE
- $(call if_changed,objcopy)
-
-$(obj)/vmlinux: $(obj)/piggy.gz $(obj)/decompress.bin FORCE
- $(call if_changed,image)
-
-$(obj)/piggy.gz: $(obj)/../Image FORCE
- $(call if_changed,gzip)
diff --git a/arch/cris/arch-v32/boot/rescue/Makefile b/arch/cris/arch-v32/boot/rescue/Makefile
deleted file mode 100644
index 566aac663a38..000000000000
--- a/arch/cris/arch-v32/boot/rescue/Makefile
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# Makefile for rescue (bootstrap) code
-#
-
-CC = gcc-cris -mlinux -march=v32 $(LINUXINCLUDE)
-ccflags-y += -O2 -I $(srctree)/include/asm/arch/mach/ \
- -I $(srctree)/include/asm/arch
-asflags-y += -I $(srctree)/include/asm/arch/mach/ -I $(srctree)/include/asm/arch
-LD = gcc-cris -mlinux -march=v32 -nostdlib
-ldflags-y += -T $(srctree)/$(src)/rescue.lds
-LDPOSTFLAGS = -lgcc
-OBJCOPYFLAGS = -O binary --remove-section=.bss
-obj-$(CONFIG_ETRAX_AXISFLASHMAP) = head.o
-OBJECT := $(obj)/head.o
-
-targets := rescue.o rescue.bin
-
-quiet_cmd_ldlibgcc = LD $@
-cmd_ldlibgcc = $(LD) $(LDFLAGS) $(filter-out FORCE,$^) $(LDPOSTFLAGS) -o $@
-
-$(obj)/rescue.o: $(OBJECTS) FORCE
- $(call if_changed,ldlibgcc)
-
-$(obj)/rescue.bin: $(obj)/rescue.o FORCE
- $(call if_changed,objcopy)
- cp -p $(obj)/rescue.bin $(objtree)
diff --git a/arch/cris/arch-v32/drivers/mach-a3/gpio.c b/arch/cris/arch-v32/drivers/mach-a3/gpio.c
index 7a87bc0ae2e8..97357cfd17bb 100644
--- a/arch/cris/arch-v32/drivers/mach-a3/gpio.c
+++ b/arch/cris/arch-v32/drivers/mach-a3/gpio.c
@@ -681,7 +681,7 @@ static int virtual_gpio_ioctl(struct file *file, unsigned int cmd,
shadow |= ~readl(dir_oe[priv->minor]) |
(arg & changeable_bits[priv->minor]);
i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
- spin_lock_irqrestore(&gpio_lock, flags);
+ spin_unlock_irqrestore(&gpio_lock, flags);
break;
case IO_CLRBITS:
spin_lock_irqsave(&gpio_lock, flags);
@@ -690,7 +690,7 @@ static int virtual_gpio_ioctl(struct file *file, unsigned int cmd,
shadow |= ~readl(dir_oe[priv->minor]) &
~(arg & changeable_bits[priv->minor]);
i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
- spin_lock_irqrestore(&gpio_lock, flags);
+ spin_unlock_irqrestore(&gpio_lock, flags);
break;
case IO_HIGHALARM:
/* Set alarm when bits with 1 in arg go high. */
diff --git a/arch/cris/arch-v32/kernel/Makefile b/arch/cris/arch-v32/kernel/Makefile
index 993d987b0078..40358355d0cb 100644
--- a/arch/cris/arch-v32/kernel/Makefile
+++ b/arch/cris/arch-v32/kernel/Makefile
@@ -9,8 +9,6 @@ obj-y := entry.o traps.o irq.o debugport.o \
process.o ptrace.o setup.o signal.o traps.o time.o \
cache.o cacheflush.o
-obj-$(CONFIG_ETRAXFS_SIM) += vcs_hook.o
-
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_ETRAX_KGDB) += kgdb.o kgdb_asm.o
obj-$(CONFIG_ETRAX_FAST_TIMER) += fasttimer.o
diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S
index 5e674c8f7c51..435b9671bd4b 100644
--- a/arch/cris/arch-v32/kernel/entry.S
+++ b/arch/cris/arch-v32/kernel/entry.S
@@ -852,6 +852,14 @@ sys_call_table:
.long sys_fallocate
.long sys_timerfd_settime /* 325 */
.long sys_timerfd_gettime
+ .long sys_signalfd4
+ .long sys_eventfd2
+ .long sys_epoll_create1
+ .long sys_dup3 /* 330 */
+ .long sys_pipe2
+ .long sys_inotify_init1
+ .long sys_preadv
+ .long sys_pwritev
/*
* NOTE!! This doesn't have to be exact - we just have
diff --git a/arch/cris/arch-v32/kernel/irq.c b/arch/cris/arch-v32/kernel/irq.c
index df3925cb1c7f..d70b445f4a8f 100644
--- a/arch/cris/arch-v32/kernel/irq.c
+++ b/arch/cris/arch-v32/kernel/irq.c
@@ -325,12 +325,14 @@ static void end_crisv32_irq(unsigned int irq)
{
}
-void set_affinity_crisv32_irq(unsigned int irq, const struct cpumask *dest)
+int set_affinity_crisv32_irq(unsigned int irq, const struct cpumask *dest)
{
unsigned long flags;
spin_lock_irqsave(&irq_lock, flags);
irq_allocations[irq - FIRST_IRQ].mask = *dest;
spin_unlock_irqrestore(&irq_lock, flags);
+
+ return 0;
}
static struct irq_chip crisv32_irq_type = {
diff --git a/arch/cris/arch-v10/boot/.gitignore b/arch/cris/boot/.gitignore
index 171a0853caf8..171a0853caf8 100644
--- a/arch/cris/arch-v10/boot/.gitignore
+++ b/arch/cris/boot/.gitignore
diff --git a/arch/cris/arch-v10/boot/Makefile b/arch/cris/boot/Makefile
index 217203014433..144f3afa0119 100644
--- a/arch/cris/arch-v10/boot/Makefile
+++ b/arch/cris/boot/Makefile
@@ -1,8 +1,12 @@
#
-# arch/cris/arch-v10/boot/Makefile
+# arch/cris/boot/Makefile
#
-OBJCOPYFLAGS = -O binary --remove-section=.bss
+objcopyflags-$(CONFIG_ETRAX_ARCH_V10) += -R .note -R .comment
+objcopyflags-$(CONFIG_ETRAX_ARCH_V32) += --remove-section=.bss
+
+OBJCOPYFLAGS = -O binary $(objcopyflags-y)
+
subdir- := compressed rescue
targets := Image
diff --git a/arch/cris/arch-v10/boot/compressed/Makefile b/arch/cris/boot/compressed/Makefile
index 6fe0ffaf3be6..8fe9338c1775 100644
--- a/arch/cris/arch-v10/boot/compressed/Makefile
+++ b/arch/cris/boot/compressed/Makefile
@@ -1,11 +1,23 @@
#
-# arch/cris/arch-v10/boot/compressed/Makefile
+# arch/cris/boot/compressed/Makefile
#
asflags-y += $(LINUXINCLUDE)
ccflags-y += -O2 $(LINUXINCLUDE)
-ldflags-y += -T $(srctree)/$(src)/decompress.lds
-OBJECTS = $(obj)/head.o $(obj)/misc.o
+
+# asflags-$(CONFIG_ETRAX_ARCH_V32) += -I$(srctree)/include/asm/mach \
+# -I$(srctree)/include/asm/arch
+# ccflags-$(CONFIG_ETRAX_ARCH_V32) += -O2 -I$(srctree)/include/asm/mach
+# -I$(srctree)/include/asm/arch
+
+arch-$(CONFIG_ETRAX_ARCH_V10) = v10
+arch-$(CONFIG_ETRAX_ARCH_V32) = v32
+
+ldflags-y += -T $(srctree)/$(src)/decompress_$(arch-y).lds
+
+OBJECTS-$(CONFIG_ETRAX_ARCH_V32) = $(obj)/head_v32.o
+OBJECTS-$(CONFIG_ETRAX_ARCH_V10) = $(obj)/head_v10.o
+OBJECTS= $(OBJECTS-y) $(obj)/misc.o
OBJCOPYFLAGS = -O binary --remove-section=.bss
quiet_cmd_image = BUILD $@
@@ -24,4 +36,3 @@ $(obj)/vmlinux: $(obj)/piggy.gz $(obj)/decompress.bin FORCE
$(obj)/piggy.gz: $(obj)/../Image FORCE
$(call if_changed,gzip)
-
diff --git a/arch/cris/arch-v32/boot/compressed/README b/arch/cris/boot/compressed/README
index 182c5d75784b..182c5d75784b 100644
--- a/arch/cris/arch-v32/boot/compressed/README
+++ b/arch/cris/boot/compressed/README
diff --git a/arch/cris/arch-v10/boot/compressed/decompress.lds b/arch/cris/boot/compressed/decompress_v10.lds
index e80f4594d543..e80f4594d543 100644
--- a/arch/cris/arch-v10/boot/compressed/decompress.lds
+++ b/arch/cris/boot/compressed/decompress_v10.lds
diff --git a/arch/cris/arch-v32/boot/compressed/decompress.lds b/arch/cris/boot/compressed/decompress_v32.lds
index 3c837feca3ac..3c837feca3ac 100644
--- a/arch/cris/arch-v32/boot/compressed/decompress.lds
+++ b/arch/cris/boot/compressed/decompress_v32.lds
diff --git a/arch/cris/arch-v10/boot/compressed/head.S b/arch/cris/boot/compressed/head_v10.S
index 0bb4dcc29254..9edb8ade7e1f 100644
--- a/arch/cris/arch-v10/boot/compressed/head.S
+++ b/arch/cris/boot/compressed/head_v10.S
@@ -30,7 +30,7 @@
beq dram_init_finished
nop
-#include "../../lib/dram_init.S"
+#include "../../arch-v10/lib/dram_init.S"
dram_init_finished:
@@ -123,4 +123,4 @@ _cmd_line_magic:
.dword 0
_cmd_line_addr:
.dword 0
-#include "../../lib/hw_settings.S"
+#include "../../arch-v10/lib/hw_settings.S"
diff --git a/arch/cris/arch-v32/boot/compressed/head.S b/arch/cris/boot/compressed/head_v32.S
index a4a65c5c669e..f483005f3d48 100644
--- a/arch/cris/arch-v32/boot/compressed/head.S
+++ b/arch/cris/boot/compressed/head_v32.S
@@ -17,7 +17,7 @@
.globl input_data
.text
-_start:
+start:
di
;; Start clocks for used blocks.
@@ -29,9 +29,9 @@ _start:
nop
#if defined CONFIG_ETRAXFS
-#include "../../mach-fs/dram_init.S"
+#include "../../arch-v32/mach-fs/dram_init.S"
#elif defined CONFIG_CRIS_MACH_ARTPEC3
-#include "../../mach-a3/dram_init.S"
+#include "../../arch-v32/mach-a3/dram_init.S"
#else
#error Only ETRAXFS and ARTPEC-3 supported!
#endif
@@ -137,9 +137,9 @@ _boot_source:
.dword 0
#if defined CONFIG_ETRAXFS
-#include "../../mach-fs/hw_settings.S"
+#include "../../arch-v32/mach-fs/hw_settings.S"
#elif defined CONFIG_CRIS_MACH_ARTPEC3
-#include "../../mach-a3/hw_settings.S"
+#include "../../arch-v32/mach-a3/hw_settings.S"
#else
#error Only ETRAXFS and ARTPEC-3 supported!
#endif
diff --git a/arch/cris/arch-v32/boot/compressed/misc.c b/arch/cris/boot/compressed/misc.c
index 3595e16e82bc..47bc190ba6d4 100644
--- a/arch/cris/arch-v32/boot/compressed/misc.c
+++ b/arch/cris/boot/compressed/misc.c
@@ -18,8 +18,9 @@
#define KERNEL_LOAD_ADR 0x40004000
-
#include <linux/types.h>
+
+#ifdef CONFIG_ETRAX_ARCH_V32
#include <hwregs/reg_rdwr.h>
#include <hwregs/reg_map.h>
#include <hwregs/ser_defs.h>
@@ -27,6 +28,9 @@
#ifdef CONFIG_CRIS_MACH_ARTPEC3
#include <hwregs/clkgen_defs.h>
#endif
+#else
+#include <arch/svinto.h>
+#endif
/*
* gzip declarations
@@ -35,12 +39,10 @@
#define OF(args) args
#define STATIC static
-void* memset(void* s, int c, size_t n);
-void* memcpy(void* __dest, __const void* __src,
- size_t __n);
-
-#define memzero(s, n) memset ((s), 0, (n))
+void *memset(void *s, int c, size_t n);
+void *memcpy(void *__dest, __const void *__src, size_t __n);
+#define memzero(s, n) memset((s), 0, (n))
typedef unsigned char uch;
typedef unsigned short ush;
@@ -68,27 +70,43 @@ static unsigned outcnt = 0; /* bytes in output buffer */
#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
#define RESERVED 0xC0 /* bit 6,7: reserved */
-#define get_byte() inbuf[inptr++]
+#define get_byte() (inbuf[inptr++])
/* Diagnostic functions */
#ifdef DEBUG
-# define Assert(cond,msg) {if(!(cond)) error(msg);}
+# define Assert(cond, msg) do { \
+ if (!(cond)) \
+ error(msg); \
+ } while (0)
# define Trace(x) fprintf x
-# define Tracev(x) {if (verbose) fprintf x ;}
-# define Tracevv(x) {if (verbose>1) fprintf x ;}
-# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
-# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+# define Tracev(x) do { \
+ if (verbose) \
+ fprintf x; \
+ } while (0)
+# define Tracevv(x) do { \
+ if (verbose > 1) \
+ fprintf x; \
+ } while (0)
+# define Tracec(c, x) do { \
+ if (verbose && (c)) \
+ fprintf x; \
+ } while (0)
+# define Tracecv(c, x) do { \
+ if (verbose > 1 && (c)) \
+ fprintf x; \
+ } while (0)
#else
-# define Assert(cond,msg)
+# define Assert(cond, msg)
# define Trace(x)
# define Tracev(x)
# define Tracevv(x)
-# define Tracec(c,x)
-# define Tracecv(c,x)
+# define Tracec(c, x)
+# define Tracecv(c, x)
#endif
static void flush_window(void);
static void error(char *m);
+static void puts(const char *);
extern char *input_data; /* lives in head.S */
@@ -96,10 +114,6 @@ static long bytes_out;
static uch *output_data;
static unsigned long output_ptr;
-static void error(char *m);
-
-static void puts(const char *);
-
/* the "heap" is put directly after the BSS ends, at end */
extern int _end;
@@ -110,8 +124,8 @@ static long free_mem_end_ptr;
/* decompressor info and error messages to serial console */
-static inline void
-serout(const char *s, reg_scope_instances regi_ser)
+#ifdef CONFIG_ETRAX_ARCH_V32
+static inline void serout(const char *s, reg_scope_instances regi_ser)
{
reg_ser_rs_stat_din rs;
reg_ser_rw_dout dout = {.data = *s};
@@ -123,23 +137,47 @@ serout(const char *s, reg_scope_instances regi_ser)
REG_WR(ser, regi_ser, rw_dout, dout);
}
+#endif
-static void
-puts(const char *s)
+static void puts(const char *s)
{
#ifndef CONFIG_ETRAX_DEBUG_PORT_NULL
while (*s) {
#ifdef CONFIG_ETRAX_DEBUG_PORT0
+#ifdef CONFIG_ETRAX_ARCH_V32
serout(s, regi_ser0);
+#else
+ while (!(*R_SERIAL0_STATUS & (1 << 5)))
+ ;
+ *R_SERIAL0_TR_DATA = *s++;
+#endif
#endif
#ifdef CONFIG_ETRAX_DEBUG_PORT1
+#ifdef CONFIG_ETRAX_ARCH_V32
serout(s, regi_ser1);
+#else
+ while (!(*R_SERIAL1_STATUS & (1 << 5)))
+ ;
+ *R_SERIAL1_TR_DATA = *s++;
+#endif
#endif
#ifdef CONFIG_ETRAX_DEBUG_PORT2
+#ifdef CONFIG_ETRAX_ARCH_V32
serout(s, regi_ser2);
+#else
+ while (!(*R_SERIAL2_STATUS & (1 << 5)))
+ ;
+ *R_SERIAL2_TR_DATA = *s++;
+#endif
#endif
#ifdef CONFIG_ETRAX_DEBUG_PORT3
+#ifdef CONFIG_ETRAX_ARCH_V32
serout(s, regi_ser3);
+#else
+ while (!(*R_SERIAL3_STATUS & (1 << 5)))
+ ;
+ *R_SERIAL3_TR_DATA = *s++;
+#endif
#endif
*s++;
}
@@ -147,8 +185,7 @@ puts(const char *s)
#endif
}
-void*
-memset(void* s, int c, size_t n)
+void *memset(void *s, int c, size_t n)
{
int i;
char *ss = (char*)s;
@@ -158,14 +195,13 @@ memset(void* s, int c, size_t n)
return s;
}
-void*
-memcpy(void* __dest, __const void* __src,
- size_t __n)
+void *memcpy(void *__dest, __const void *__src, size_t __n)
{
int i;
char *d = (char *)__dest, *s = (char *)__src;
- for (i=0;i<__n;i++) d[i] = s[i];
+ for (i = 0; i < __n; i++)
+ d[i] = s[i];
return __dest;
}
@@ -175,43 +211,42 @@ memcpy(void* __dest, __const void* __src,
* (Used for the decompressed data only.)
*/
-static void
-flush_window()
+static void flush_window(void)
{
- ulg c = crc; /* temporary variable */
- unsigned n;
- uch *in, *out, ch;
-
- in = window;
- out = &output_data[output_ptr];
- for (n = 0; n < outcnt; n++) {
- ch = *out++ = *in++;
- c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
- }
- crc = c;
- bytes_out += (ulg)outcnt;
- output_ptr += (ulg)outcnt;
- outcnt = 0;
+ ulg c = crc; /* temporary variable */
+ unsigned n;
+ uch *in, *out, ch;
+
+ in = window;
+ out = &output_data[output_ptr];
+ for (n = 0; n < outcnt; n++) {
+ ch = *out = *in;
+ out++;
+ in++;
+ c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+ }
+ crc = c;
+ bytes_out += (ulg)outcnt;
+ output_ptr += (ulg)outcnt;
+ outcnt = 0;
}
-static void
-error(char *x)
+static void error(char *x)
{
- puts("\r\n\n");
+ puts("\n\n");
puts(x);
- puts("\r\n\n -- System halted\n");
+ puts("\n\n -- System halted\n");
while(1); /* Halt */
}
-void
-setup_normal_output_buffer(void)
+void setup_normal_output_buffer(void)
{
output_data = (char *)KERNEL_LOAD_ADR;
}
-static inline void
-serial_setup(reg_scope_instances regi_ser)
+#ifdef CONFIG_ETRAX_ARCH_V32
+static inline void serial_setup(reg_scope_instances regi_ser)
{
reg_ser_rw_xoff xoff;
reg_ser_rw_tr_ctrl tr_ctrl;
@@ -252,12 +287,16 @@ serial_setup(reg_scope_instances regi_ser)
REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl);
REG_WR(ser, regi_ser, rw_rec_baud_div, rec_baud);
}
+#endif
-void
-decompress_kernel(void)
+void decompress_kernel(void)
{
char revision;
+ char compile_rev;
+#ifdef CONFIG_ETRAX_ARCH_V32
+ /* Need at least a CRISv32 to run. */
+ compile_rev = 32;
#if defined(CONFIG_ETRAX_DEBUG_PORT1) || \
defined(CONFIG_ETRAX_DEBUG_PORT2) || \
defined(CONFIG_ETRAX_DEBUG_PORT3)
@@ -277,6 +316,7 @@ decompress_kernel(void)
hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
#endif
+
#ifdef CONFIG_ETRAX_DEBUG_PORT0
serial_setup(regi_ser0);
#endif
@@ -300,19 +340,52 @@ decompress_kernel(void)
/* input_data is set in head.S */
inbuf = input_data;
+#else /* CRISv10 */
+ /* Need at least a crisv10 to run. */
+ compile_rev = 10;
+
+ /* input_data is set in head.S */
+ inbuf = input_data;
+
+#ifdef CONFIG_ETRAX_DEBUG_PORT0
+ *R_SERIAL0_XOFF = 0;
+ *R_SERIAL0_BAUD = 0x99;
+ *R_SERIAL0_TR_CTRL = 0x40;
+#endif
+#ifdef CONFIG_ETRAX_DEBUG_PORT1
+ *R_SERIAL1_XOFF = 0;
+ *R_SERIAL1_BAUD = 0x99;
+ *R_SERIAL1_TR_CTRL = 0x40;
+#endif
+#ifdef CONFIG_ETRAX_DEBUG_PORT2
+ *R_GEN_CONFIG = 0x08;
+ *R_SERIAL2_XOFF = 0;
+ *R_SERIAL2_BAUD = 0x99;
+ *R_SERIAL2_TR_CTRL = 0x40;
+#endif
+#ifdef CONFIG_ETRAX_DEBUG_PORT3
+ *R_GEN_CONFIG = 0x100;
+ *R_SERIAL3_XOFF = 0;
+ *R_SERIAL3_BAUD = 0x99;
+ *R_SERIAL3_TR_CTRL = 0x40;
+#endif
+#endif
setup_normal_output_buffer();
makecrc();
__asm__ volatile ("move $vr,%0" : "=rm" (revision));
- if (revision < 32)
- {
- puts("You need an ETRAX FS to run Linux 2.6/crisv32.\r\n");
+ if (revision < compile_rev) {
+#ifdef CONFIG_ETRAX_ARCH_V32
+ puts("You need an ETRAX FS to run Linux 2.6/crisv32\n");
+#else
+ puts("You need an ETRAX 100LX to run linux 2.6\n");
+#endif
while(1);
}
- puts("Uncompressing Linux...\r\n");
+ puts("Uncompressing Linux...\n");
gunzip();
- puts("Done. Now booting the kernel.\r\n");
+ puts("Done. Now booting the kernel\n");
}
diff --git a/arch/cris/arch-v10/boot/rescue/Makefile b/arch/cris/boot/rescue/Makefile
index 82ab59b968e5..52bd0bd1dd22 100644
--- a/arch/cris/arch-v10/boot/rescue/Makefile
+++ b/arch/cris/boot/rescue/Makefile
@@ -2,16 +2,26 @@
# Makefile for rescue (bootstrap) code
#
-ccflags-y += -O2 $(LINUXINCLUDE)
+# CC = gcc-cris -mlinux -march=v32 $(LINUXINCLUDE)
+# ccflags-$(CONFIG_ETRAX_ARCH_V32) += -I$(srctree)/include/asm/arch/mach/ \
+# -I$(srctree)/include/asm/arch
+# asflags-y += -I $(srctree)/include/asm/arch/mach/ -I $(srctree)/include/asm/arch
+# LD = gcc-cris -mlinux -march=v32 -nostdlib
+
asflags-y += $(LINUXINCLUDE)
-ldflags-y += -T $(srctree)/$(src)/rescue.lds
+ccflags-y += -O2 $(LINUXINCLUDE)
+arch-$(CONFIG_ETRAX_ARCH_V10) = v10
+arch-$(CONFIG_ETRAX_ARCH_V32) = v32
+
+ldflags-y += -T $(srctree)/$(src)/rescue_$(arch-y).lds
OBJCOPYFLAGS = -O binary --remove-section=.bss
-obj-$(CONFIG_ETRAX_AXISFLASHMAP) = head.o
-OBJECT := $(obj)/head.o
+obj-$(CONFIG_ETRAX_ARCH_V32) = $(obj)/head_v32.o
+obj-$(CONFIG_ETRAX_ARCH_V10) = $(obj)/head_v10.o
+OBJECTS := $(obj-y)
targets := rescue.o rescue.bin
-$(obj)/rescue.o: $(OBJECT) FORCE
+$(obj)/rescue.o: $(OBJECTS) FORCE
$(call if_changed,ld)
$(obj)/rescue.bin: $(obj)/rescue.o FORCE
@@ -26,6 +36,7 @@ $(obj)/testrescue.bin: $(obj)/testrescue.o
dd if=testrescue_tmp.bin of=$(obj)/testrescue.bin bs=1 count=784
rm tr.bin tmp2423 testrescue_tmp.bin
+
$(obj)/kimagerescue.bin: $(obj)/kimagerescue.o
$(OBJCOPY) $(OBJCOPYFLAGS) $(obj)/kimagerescue.o ktr.bin
# Pad it to 784 bytes, that's what the rescue loader expects
@@ -33,3 +44,4 @@ $(obj)/kimagerescue.bin: $(obj)/kimagerescue.o
cat ktr.bin tmp2423 >kimagerescue_tmp.bin
dd if=kimagerescue_tmp.bin of=$(obj)/kimagerescue.bin bs=1 count=784
rm ktr.bin tmp2423 kimagerescue_tmp.bin
+
diff --git a/arch/cris/arch-v10/boot/rescue/head.S b/arch/cris/boot/rescue/head_v10.S
index fb503d1eeea4..2fafe247a25b 100644
--- a/arch/cris/arch-v10/boot/rescue/head.S
+++ b/arch/cris/boot/rescue/head_v10.S
@@ -155,7 +155,7 @@ no_newjump:
#endif
;; We need to setup the bus registers before we start using the DRAM
-#include "../../lib/dram_init.S"
+#include "../../../arch-v10/lib/dram_init.S"
;; we now should go through the checksum-table and check the listed
;; partitions for errors.
diff --git a/arch/cris/arch-v32/boot/rescue/head.S b/arch/cris/boot/rescue/head_v32.S
index 5f846b7700a3..5f846b7700a3 100644
--- a/arch/cris/arch-v32/boot/rescue/head.S
+++ b/arch/cris/boot/rescue/head_v32.S
diff --git a/arch/cris/arch-v10/boot/rescue/kimagerescue.S b/arch/cris/boot/rescue/kimagerescue.S
index 6f7b3e61260b..6f7b3e61260b 100644
--- a/arch/cris/arch-v10/boot/rescue/kimagerescue.S
+++ b/arch/cris/boot/rescue/kimagerescue.S
diff --git a/arch/cris/arch-v10/boot/rescue/rescue.lds b/arch/cris/boot/rescue/rescue_v10.lds
index 0b52a9490db6..0b52a9490db6 100644
--- a/arch/cris/arch-v10/boot/rescue/rescue.lds
+++ b/arch/cris/boot/rescue/rescue_v10.lds
diff --git a/arch/cris/arch-v32/boot/rescue/rescue.lds b/arch/cris/boot/rescue/rescue_v32.lds
index 8ac646bc1a2b..8ac646bc1a2b 100644
--- a/arch/cris/arch-v32/boot/rescue/rescue.lds
+++ b/arch/cris/boot/rescue/rescue_v32.lds
diff --git a/arch/cris/arch-v10/boot/rescue/testrescue.S b/arch/cris/boot/rescue/testrescue.S
index fc7ec674eca5..fc7ec674eca5 100644
--- a/arch/cris/arch-v10/boot/rescue/testrescue.S
+++ b/arch/cris/boot/rescue/testrescue.S
diff --git a/arch/cris/arch-v10/boot/tools/build.c b/arch/cris/boot/tools/build.c
index c8adef364160..c8adef364160 100644
--- a/arch/cris/arch-v10/boot/tools/build.c
+++ b/arch/cris/boot/tools/build.c
diff --git a/arch/cris/include/asm/unistd.h b/arch/cris/include/asm/unistd.h
index 235d076379d5..c17079388bb9 100644
--- a/arch/cris/include/asm/unistd.h
+++ b/arch/cris/include/asm/unistd.h
@@ -281,7 +281,7 @@
#define __NR_mbind 274
#define __NR_get_mempolicy 275
#define __NR_set_mempolicy 276
-#define __NR_mq_open 277
+#define __NR_mq_open 277
#define __NR_mq_unlink (__NR_mq_open+1)
#define __NR_mq_timedsend (__NR_mq_open+2)
#define __NR_mq_timedreceive (__NR_mq_open+3)
@@ -331,10 +331,18 @@
#define __NR_fallocate 324
#define __NR_timerfd_settime 325
#define __NR_timerfd_gettime 326
+#define __NR_signalfd4 327
+#define __NR_eventfd2 328
+#define __NR_epoll_create1 329
+#define __NR_dup3 330
+#define __NR_pipe2 331
+#define __NR_inotify_init1 332
+#define __NR_preadv 333
+#define __NR_pwritev 334
#ifdef __KERNEL__
-#define NR_syscalls 327
+#define NR_syscalls 335
#include <arch/unistd.h>
diff --git a/arch/frv/include/asm/bug.h b/arch/frv/include/asm/bug.h
index 6b1b44d71028..2e054508a2f6 100644
--- a/arch/frv/include/asm/bug.h
+++ b/arch/frv/include/asm/bug.h
@@ -30,7 +30,7 @@ extern void __debug_bug_printk(const char *file, unsigned line);
do { \
__debug_bug_trap(signr); \
asm volatile("nop"); \
-} while(0)
+} while(1)
#define HAVE_ARCH_BUG
#define BUG() \
@@ -46,7 +46,8 @@ do { \
#define HAVE_ARCH_KGDB_BAD_PAGE
#define kgdb_bad_page(page) do { kgdb_raise(SIGABRT); } while(0)
#endif
-#endif
+
+#endif /* CONFIG_BUG */
#include <asm-generic/bug.h>
diff --git a/arch/frv/include/asm/gdb-stub.h b/arch/frv/include/asm/gdb-stub.h
index 24f9738670bd..2da716407ff2 100644
--- a/arch/frv/include/asm/gdb-stub.h
+++ b/arch/frv/include/asm/gdb-stub.h
@@ -90,7 +90,6 @@ extern void gdbstub_do_rx(void);
extern asmlinkage void __debug_stub_init_break(void);
extern asmlinkage void __break_hijack_kernel_event(void);
extern asmlinkage void __break_hijack_kernel_event_breaks_here(void);
-extern asmlinkage void start_kernel(void);
extern asmlinkage void gdbstub_rx_handler(void);
extern asmlinkage void gdbstub_rx_irq(void);
diff --git a/arch/frv/include/asm/init.h b/arch/frv/include/asm/init.h
deleted file mode 100644
index 8b15838de216..000000000000
--- a/arch/frv/include/asm/init.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _ASM_INIT_H
-#define _ASM_INIT_H
-
-#define __init __attribute__ ((__section__ (".text.init")))
-#define __initdata __attribute__ ((__section__ (".data.init")))
-/* For assembly routines */
-#define __INIT .section ".text.init",#alloc,#execinstr
-#define __FINIT .previous
-#define __INITDATA .section ".data.init",#alloc,#write
-
-#endif
-
diff --git a/arch/frv/include/asm/unistd.h b/arch/frv/include/asm/unistd.h
index edcfaf5f0414..96d78d5d2c41 100644
--- a/arch/frv/include/asm/unistd.h
+++ b/arch/frv/include/asm/unistd.h
@@ -339,10 +339,12 @@
#define __NR_dup3 330
#define __NR_pipe2 331
#define __NR_inotify_init1 332
+#define __NR_preadv 333
+#define __NR_pwritev 334
#ifdef __KERNEL__
-#define NR_syscalls 333
+#define NR_syscalls 335
#define __ARCH_WANT_IPC_PARSE_VERSION
/* #define __ARCH_WANT_OLD_READDIR */
diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S
index 99060ab507ee..1da523b3298e 100644
--- a/arch/frv/kernel/entry.S
+++ b/arch/frv/kernel/entry.S
@@ -1525,5 +1525,7 @@ sys_call_table:
.long sys_dup3 /* 330 */
.long sys_pipe2
.long sys_inotify_init1
+ .long sys_preadv
+ .long sys_pwritev
syscall_table_size = (. - sys_call_table)
diff --git a/arch/frv/kernel/head-mmu-fr451.S b/arch/frv/kernel/head-mmu-fr451.S
index c8f210d84ff5..98f87d586e59 100644
--- a/arch/frv/kernel/head-mmu-fr451.S
+++ b/arch/frv/kernel/head-mmu-fr451.S
@@ -9,6 +9,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/init.h>
#include <linux/threads.h>
#include <linux/linkage.h>
#include <asm/ptrace.h>
@@ -31,7 +32,7 @@
#define __400_LCR 0xfe000100
#define __400_LSBR 0xfe000c00
- .section .text.init,"ax"
+ __INIT
.balign 4
###############################################################################
diff --git a/arch/frv/kernel/head-uc-fr401.S b/arch/frv/kernel/head-uc-fr401.S
index ee282be20fff..438643cfa38e 100644
--- a/arch/frv/kernel/head-uc-fr401.S
+++ b/arch/frv/kernel/head-uc-fr401.S
@@ -9,6 +9,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/init.h>
#include <linux/threads.h>
#include <linux/linkage.h>
#include <asm/ptrace.h>
@@ -30,7 +31,7 @@
#define __400_LCR 0xfe000100
#define __400_LSBR 0xfe000c00
- .section .text.init,"ax"
+ __INIT
.balign 4
###############################################################################
diff --git a/arch/frv/kernel/head-uc-fr451.S b/arch/frv/kernel/head-uc-fr451.S
index b10d9c8295d2..b2a76c4a1786 100644
--- a/arch/frv/kernel/head-uc-fr451.S
+++ b/arch/frv/kernel/head-uc-fr451.S
@@ -9,6 +9,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/init.h>
#include <linux/threads.h>
#include <linux/linkage.h>
#include <asm/ptrace.h>
@@ -30,7 +31,7 @@
#define __400_LCR 0xfe000100
#define __400_LSBR 0xfe000c00
- .section .text.init,"ax"
+ __INIT
.balign 4
###############################################################################
diff --git a/arch/frv/kernel/head-uc-fr555.S b/arch/frv/kernel/head-uc-fr555.S
index 39937c19b460..5497aaf34f77 100644
--- a/arch/frv/kernel/head-uc-fr555.S
+++ b/arch/frv/kernel/head-uc-fr555.S
@@ -9,6 +9,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/init.h>
#include <linux/threads.h>
#include <linux/linkage.h>
#include <asm/ptrace.h>
@@ -29,7 +30,7 @@
#define __551_LCR 0xfeff1100
#define __551_LSBR 0xfeff1c00
- .section .text.init,"ax"
+ __INIT
.balign 4
###############################################################################
diff --git a/arch/frv/kernel/head.S b/arch/frv/kernel/head.S
index fecf751c5cae..b825ef3f2d54 100644
--- a/arch/frv/kernel/head.S
+++ b/arch/frv/kernel/head.S
@@ -9,6 +9,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/init.h>
#include <linux/threads.h>
#include <linux/linkage.h>
#include <asm/thread_info.h>
@@ -27,7 +28,7 @@
# command line string
#
###############################################################################
- .section .text.head,"ax"
+ __HEAD
.balign 4
.globl _boot, __head_reference
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index 0669e1382383..55e4fab7c0bc 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -46,7 +46,6 @@
#include <asm/io.h>
#ifdef CONFIG_BLK_DEV_INITRD
-#include <linux/blk.h>
#include <asm/pgtable.h>
#endif
diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S
index b95c4eace62f..22d9787406ed 100644
--- a/arch/frv/kernel/vmlinux.lds.S
+++ b/arch/frv/kernel/vmlinux.lds.S
@@ -26,7 +26,7 @@ SECTIONS
_sinittext = .;
.init.text : {
- *(.text.head)
+ HEAD_TEXT
#ifndef CONFIG_DEBUG_INFO
INIT_TEXT
EXIT_TEXT
diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c
index 0f41c3a72da5..c0dcec65c6b7 100644
--- a/arch/frv/mb93090-mb00/pci-vdk.c
+++ b/arch/frv/mb93090-mb00/pci-vdk.c
@@ -31,6 +31,29 @@ struct pci_bus *__nongpreldata pci_root_bus;
struct pci_ops *__nongpreldata pci_root_ops;
/*
+ * The accessible PCI window does not cover the entire CPU address space, but
+ * there are devices we want to access outside of that window, so we need to
+ * insert specific PCI bus resources instead of using the platform-level bus
+ * resources directly for the PCI root bus.
+ *
+ * These are configured and inserted by pcibios_init() and are attached to the
+ * root bus by pcibios_fixup_bus().
+ */
+static struct resource pci_ioport_resource = {
+ .name = "PCI IO",
+ .start = 0,
+ .end = IO_SPACE_LIMIT,
+ .flags = IORESOURCE_IO,
+};
+
+static struct resource pci_iomem_resource = {
+ .name = "PCI mem",
+ .start = 0,
+ .end = -1,
+ .flags = IORESOURCE_MEM,
+};
+
+/*
* Functions for accessing PCI configuration space
*/
@@ -304,6 +327,12 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
#if 0
printk("### PCIBIOS_FIXUP_BUS(%d)\n",bus->number);
#endif
+
+ if (bus->number == 0) {
+ bus->resource[0] = &pci_ioport_resource;
+ bus->resource[1] = &pci_iomem_resource;
+ }
+
pci_read_bridge_bases(bus);
if (bus->number == 0) {
@@ -350,28 +379,36 @@ int __init pcibios_init(void)
/* enable PCI arbitration */
__reg_MB86943_pci_arbiter = MB86943_PCIARB_EN;
- ioport_resource.start = (__reg_MB86943_sl_pci_io_base << 9) & 0xfffffc00;
- ioport_resource.end = (__reg_MB86943_sl_pci_io_range << 9) | 0x3ff;
- ioport_resource.end += ioport_resource.start;
+ pci_ioport_resource.start = (__reg_MB86943_sl_pci_io_base << 9) & 0xfffffc00;
+ pci_ioport_resource.end = (__reg_MB86943_sl_pci_io_range << 9) | 0x3ff;
+ pci_ioport_resource.end += pci_ioport_resource.start;
printk("PCI IO window: %08llx-%08llx\n",
- (unsigned long long) ioport_resource.start,
- (unsigned long long) ioport_resource.end);
+ (unsigned long long) pci_ioport_resource.start,
+ (unsigned long long) pci_ioport_resource.end);
- iomem_resource.start = (__reg_MB86943_sl_pci_mem_base << 9) & 0xfffffc00;
+ pci_iomem_resource.start = (__reg_MB86943_sl_pci_mem_base << 9) & 0xfffffc00;
+ pci_iomem_resource.end = (__reg_MB86943_sl_pci_mem_range << 9) | 0x3ff;
+ pci_iomem_resource.end += pci_iomem_resource.start;
- /* Reserve somewhere to write to flush posted writes. */
- iomem_resource.start += 0x400;
-
- iomem_resource.end = (__reg_MB86943_sl_pci_mem_range << 9) | 0x3ff;
- iomem_resource.end += iomem_resource.start;
+ /* Reserve somewhere to write to flush posted writes. This is used by
+ * __flush_PCI_writes() from asm/io.h to force the write FIFO in the
+ * CPU-PCI bridge to flush as this doesn't happen automatically when a
+ * read is performed on the MB93090 development kit motherboard.
+ */
+ pci_iomem_resource.start += 0x400;
printk("PCI MEM window: %08llx-%08llx\n",
- (unsigned long long) iomem_resource.start,
- (unsigned long long) iomem_resource.end);
+ (unsigned long long) pci_iomem_resource.start,
+ (unsigned long long) pci_iomem_resource.end);
printk("PCI DMA memory: %08lx-%08lx\n",
dma_coherent_mem_start, dma_coherent_mem_end);
+ if (insert_resource(&iomem_resource, &pci_iomem_resource) < 0)
+ panic("Unable to insert PCI IOMEM resource\n");
+ if (insert_resource(&ioport_resource, &pci_ioport_resource) < 0)
+ panic("Unable to insert PCI IOPORT resource\n");
+
if (!pci_probe)
return -ENXIO;
diff --git a/include/asm-h8300/timer.h b/arch/h8300/include/asm/timer.h
index def80464d38f..def80464d38f 100644
--- a/include/asm-h8300/timer.h
+++ b/arch/h8300/include/asm/timer.h
diff --git a/arch/ia64/hp/sim/hpsim_irq.c b/arch/ia64/hp/sim/hpsim_irq.c
index cc0a3182db3c..acb5047ab573 100644
--- a/arch/ia64/hp/sim/hpsim_irq.c
+++ b/arch/ia64/hp/sim/hpsim_irq.c
@@ -21,9 +21,10 @@ hpsim_irq_noop (unsigned int irq)
{
}
-static void
+static int
hpsim_set_affinity_noop(unsigned int a, const struct cpumask *b)
{
+ return 0;
}
static struct hw_interrupt_type irq_type_hp_sim = {
diff --git a/arch/ia64/include/asm/idle.h b/arch/ia64/include/asm/idle.h
new file mode 100644
index 000000000000..b7685015a8ba
--- /dev/null
+++ b/arch/ia64/include/asm/idle.h
@@ -0,0 +1,7 @@
+#ifndef _ASM_IA64_IDLE_H
+#define _ASM_IA64_IDLE_H
+
+static inline void enter_idle(void) { }
+static inline void exit_idle(void) { }
+
+#endif /* _ASM_IA64_IDLE_H */
diff --git a/arch/ia64/include/asm/iommu.h b/arch/ia64/include/asm/iommu.h
index 0490794fe4aa..37d41ca5645a 100644
--- a/arch/ia64/include/asm/iommu.h
+++ b/arch/ia64/include/asm/iommu.h
@@ -9,6 +9,7 @@ extern void pci_iommu_shutdown(void);
extern void no_iommu_init(void);
extern int force_iommu, no_iommu;
extern int iommu_detected;
+extern int iommu_pass_through;
extern void iommu_dma_init(void);
extern void machvec_init(const char *name);
diff --git a/arch/ia64/include/asm/kvm_host.h b/arch/ia64/include/asm/kvm_host.h
index 4542651e6acb..589536fa799d 100644
--- a/arch/ia64/include/asm/kvm_host.h
+++ b/arch/ia64/include/asm/kvm_host.h
@@ -371,6 +371,7 @@ struct kvm_vcpu_arch {
int last_run_cpu;
int vmm_tr_slot;
int vm_tr_slot;
+ int sn_rtc_tr_slot;
#define KVM_MP_STATE_RUNNABLE 0
#define KVM_MP_STATE_UNINITIALIZED 1
@@ -465,6 +466,7 @@ struct kvm_arch {
unsigned long vmm_init_rr;
int online_vcpus;
+ int is_sn2;
struct kvm_ioapic *vioapic;
struct kvm_vm_stat stat;
@@ -578,6 +580,8 @@ struct kvm_vmm_info{
kvm_vmm_entry *vmm_entry;
kvm_tramp_entry *tramp_entry;
unsigned long vmm_ivt;
+ unsigned long patch_mov_ar;
+ unsigned long patch_mov_ar_sn2;
};
int kvm_highest_pending_irq(struct kvm_vcpu *vcpu);
@@ -585,7 +589,6 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu);
int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run);
void kvm_sal_emul(struct kvm_vcpu *vcpu);
-static inline void kvm_inject_nmi(struct kvm_vcpu *vcpu) {}
#endif /* __ASSEMBLY__*/
#endif
diff --git a/arch/ia64/include/asm/paravirt_privop.h b/arch/ia64/include/asm/paravirt_privop.h
index 3d2951130b5f..8f6cb11c9fae 100644
--- a/arch/ia64/include/asm/paravirt_privop.h
+++ b/arch/ia64/include/asm/paravirt_privop.h
@@ -445,7 +445,6 @@ paravirt_set_rr0_to_rr4(unsigned long val0, unsigned long val1,
register unsigned long ia64_intri_res asm ("r8"); \
register unsigned long __reg asm ("r8") = (reg); \
\
- BUILD_BUG_ON(!__builtin_constant_p(reg)); \
asm volatile (paravirt_alt_bundle(__PARAVIRT_BR, \
PARAVIRT_TYPE(GETREG) \
+ (reg)) \
@@ -464,7 +463,6 @@ paravirt_set_rr0_to_rr4(unsigned long val0, unsigned long val1,
register unsigned long ia64_clobber1 asm ("r8"); \
register unsigned long ia64_clobber2 asm ("r9"); \
\
- BUILD_BUG_ON(!__builtin_constant_p(reg)); \
asm volatile (paravirt_alt_bundle(__PARAVIRT_BR, \
PARAVIRT_TYPE(SETREG) \
+ (reg)) \
diff --git a/arch/ia64/include/asm/pgtable.h b/arch/ia64/include/asm/pgtable.h
index 7a9bff47564f..0a9cc73d35c7 100644
--- a/arch/ia64/include/asm/pgtable.h
+++ b/arch/ia64/include/asm/pgtable.h
@@ -146,6 +146,8 @@
#define PAGE_GATE __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_X_RX)
#define PAGE_KERNEL __pgprot(__DIRTY_BITS | _PAGE_PL_0 | _PAGE_AR_RWX)
#define PAGE_KERNELRX __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_RX)
+#define PAGE_KERNEL_UC __pgprot(__DIRTY_BITS | _PAGE_PL_0 | _PAGE_AR_RWX | \
+ _PAGE_MA_UC)
# ifndef __ASSEMBLY__
diff --git a/arch/ia64/include/asm/smp.h b/arch/ia64/include/asm/smp.h
index 598408336251..d217d1d4e051 100644
--- a/arch/ia64/include/asm/smp.h
+++ b/arch/ia64/include/asm/smp.h
@@ -58,7 +58,7 @@ extern struct smp_boot_data {
extern char no_int_routing __devinitdata;
extern cpumask_t cpu_core_map[NR_CPUS];
-DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
+DECLARE_PER_CPU_SHARED_ALIGNED(cpumask_t, cpu_sibling_map);
extern int smp_num_siblings;
extern void __iomem *ipi_base_addr;
extern unsigned char smp_int_redirect;
diff --git a/arch/ia64/include/asm/xen/events.h b/arch/ia64/include/asm/xen/events.h
index 73248781fba8..b8370c8b6198 100644
--- a/arch/ia64/include/asm/xen/events.h
+++ b/arch/ia64/include/asm/xen/events.h
@@ -36,14 +36,9 @@ static inline int xen_irqs_disabled(struct pt_regs *regs)
return !(ia64_psr(regs)->i);
}
-static inline void xen_do_IRQ(int irq, struct pt_regs *regs)
+static inline void handle_irq(int irq, struct pt_regs *regs)
{
- struct pt_regs *old_regs;
- old_regs = set_irq_regs(regs);
- irq_enter();
__do_IRQ(irq);
- irq_exit();
- set_irq_regs(old_regs);
}
#define irq_ctx_init(cpu) do { } while (0)
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 5510317db37b..baec6f00f7f3 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -636,7 +636,7 @@ void __init acpi_numa_arch_fixup(void)
* success: return IRQ number (>=0)
* failure: return < 0
*/
-int acpi_register_gsi(u32 gsi, int triggering, int polarity)
+int acpi_register_gsi(struct device *dev, u32 gsi, int triggering, int polarity)
{
if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM)
return gsi;
@@ -678,7 +678,8 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table)
fadt = (struct acpi_table_fadt *)fadt_header;
- acpi_register_gsi(fadt->sci_interrupt, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW);
+ acpi_register_gsi(NULL, fadt->sci_interrupt, ACPI_LEVEL_SENSITIVE,
+ ACPI_ACTIVE_LOW);
return 0;
}
diff --git a/arch/ia64/kernel/cyclone.c b/arch/ia64/kernel/cyclone.c
index 790ef0d87e12..71e35864d2e2 100644
--- a/arch/ia64/kernel/cyclone.c
+++ b/arch/ia64/kernel/cyclone.c
@@ -21,7 +21,7 @@ void __init cyclone_setup(void)
static void __iomem *cyclone_mc;
-static cycle_t read_cyclone(void)
+static cycle_t read_cyclone(struct clocksource *cs)
{
return (cycle_t)readq((void __iomem *)cyclone_mc);
}
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index 166e0d839fa0..f92cef47bf86 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -329,7 +329,7 @@ unmask_irq (unsigned int irq)
}
-static void
+static int
iosapic_set_affinity(unsigned int irq, const struct cpumask *mask)
{
#ifdef CONFIG_SMP
@@ -343,15 +343,15 @@ iosapic_set_affinity(unsigned int irq, const struct cpumask *mask)
cpu = cpumask_first_and(cpu_online_mask, mask);
if (cpu >= nr_cpu_ids)
- return;
+ return -1;
if (irq_prepare_move(irq, cpu))
- return;
+ return -1;
dest = cpu_physical_id(cpu);
if (!iosapic_intr_info[irq].count)
- return; /* not an IOSAPIC interrupt */
+ return -1; /* not an IOSAPIC interrupt */
set_irq_affinity_info(irq, dest, redir);
@@ -376,7 +376,9 @@ iosapic_set_affinity(unsigned int irq, const struct cpumask *mask)
iosapic_write(iosapic, IOSAPIC_RTE_HIGH(rte_index), high32);
iosapic_write(iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
}
+
#endif
+ return 0;
}
/*
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index acc4d19ae62a..b448197728be 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -610,6 +610,9 @@ static struct irqaction ipi_irqaction = {
.name = "IPI"
};
+/*
+ * KVM uses this interrupt to force a cpu out of guest mode
+ */
static struct irqaction resched_irqaction = {
.handler = dummy_handler,
.flags = IRQF_DISABLED,
diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c
index 2b15e233f7fe..0f8ade9331ba 100644
--- a/arch/ia64/kernel/msi_ia64.c
+++ b/arch/ia64/kernel/msi_ia64.c
@@ -12,7 +12,7 @@
static struct irq_chip ia64_msi_chip;
#ifdef CONFIG_SMP
-static void ia64_set_msi_irq_affinity(unsigned int irq,
+static int ia64_set_msi_irq_affinity(unsigned int irq,
const cpumask_t *cpu_mask)
{
struct msi_msg msg;
@@ -20,10 +20,10 @@ static void ia64_set_msi_irq_affinity(unsigned int irq,
int cpu = first_cpu(*cpu_mask);
if (!cpu_online(cpu))
- return;
+ return -1;
if (irq_prepare_move(irq, cpu))
- return;
+ return -1;
read_msi_msg(irq, &msg);
@@ -39,6 +39,8 @@ static void ia64_set_msi_irq_affinity(unsigned int irq,
write_msi_msg(irq, &msg);
cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu));
+
+ return 0;
}
#endif /* CONFIG_SMP */
@@ -130,17 +132,17 @@ void arch_teardown_msi_irq(unsigned int irq)
#ifdef CONFIG_DMAR
#ifdef CONFIG_SMP
-static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
{
struct irq_cfg *cfg = irq_cfg + irq;
struct msi_msg msg;
int cpu = cpumask_first(mask);
if (!cpu_online(cpu))
- return;
+ return -1;
if (irq_prepare_move(irq, cpu))
- return;
+ return -1;
dmar_msi_read(irq, &msg);
@@ -151,6 +153,8 @@ static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
dmar_msi_write(irq, &msg);
cpumask_copy(irq_desc[irq].affinity, mask);
+
+ return 0;
}
#endif /* CONFIG_SMP */
diff --git a/arch/ia64/kernel/pci-dma.c b/arch/ia64/kernel/pci-dma.c
index eb987386f691..ecdde25d0d18 100644
--- a/arch/ia64/kernel/pci-dma.c
+++ b/arch/ia64/kernel/pci-dma.c
@@ -32,6 +32,8 @@ int force_iommu __read_mostly = 1;
int force_iommu __read_mostly;
#endif
+int iommu_pass_through;
+
/* Dummy device used for NULL arguments (normally ISA). Better would
be probably a smaller DMA mask, but this is bug-to-bug compatible
to i386. */
diff --git a/arch/ia64/kernel/pci-swiotlb.c b/arch/ia64/kernel/pci-swiotlb.c
index 573f02c39a00..223abb134105 100644
--- a/arch/ia64/kernel/pci-swiotlb.c
+++ b/arch/ia64/kernel/pci-swiotlb.c
@@ -16,7 +16,7 @@ EXPORT_SYMBOL(swiotlb);
static void *ia64_swiotlb_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp)
{
- if (dev->coherent_dma_mask != DMA_64BIT_MASK)
+ if (dev->coherent_dma_mask != DMA_BIT_MASK(64))
gfp |= GFP_DMA;
return swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
}
@@ -46,7 +46,7 @@ void __init swiotlb_dma_init(void)
void __init pci_swiotlb_init(void)
{
- if (!iommu_detected) {
+ if (!iommu_detected || iommu_pass_through) {
#ifdef CONFIG_IA64_GENERIC
swiotlb = 1;
printk(KERN_INFO "PCI-DMA: Re-initialize machine vector.\n");
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
index 2ea4199d9c57..5230eaafd83f 100644
--- a/arch/ia64/kernel/smp.c
+++ b/arch/ia64/kernel/smp.c
@@ -225,6 +225,7 @@ smp_send_reschedule (int cpu)
{
platform_send_ipi(cpu, IA64_IPI_RESCHEDULE, IA64_IPI_DM_INT, 0);
}
+EXPORT_SYMBOL_GPL(smp_send_reschedule);
/*
* Called with preemption disabled.
@@ -300,15 +301,12 @@ smp_flush_tlb_mm (struct mm_struct *mm)
return;
}
+ smp_call_function_mask(mm->cpu_vm_mask,
+ (void (*)(void *))local_finish_flush_tlb_mm, mm, 1);
+ local_irq_disable();
+ local_finish_flush_tlb_mm(mm);
+ local_irq_enable();
preempt_enable();
- /*
- * We could optimize this further by using mm->cpu_vm_mask to track which CPUs
- * have been running in the address space. It's not clear that this is worth the
- * trouble though: to avoid races, we have to raise the IPI on the target CPU
- * anyhow, and once a CPU is interrupted, the cost of local_flush_tlb_all() is
- * rather trivial.
- */
- on_each_cpu((void (*)(void *))local_finish_flush_tlb_mm, mm, 1);
}
void arch_send_call_function_single_ipi(int cpu)
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 641c8b61c4f1..604c1a35db33 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -33,7 +33,7 @@
#include "fsyscall_gtod_data.h"
-static cycle_t itc_get_cycles(void);
+static cycle_t itc_get_cycles(struct clocksource *cs);
struct fsyscall_gtod_data_t fsyscall_gtod_data = {
.lock = SEQLOCK_UNLOCKED,
@@ -383,7 +383,7 @@ ia64_init_itm (void)
}
}
-static cycle_t itc_get_cycles(void)
+static cycle_t itc_get_cycles(struct clocksource *cs)
{
u64 lcycle, now, ret;
diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig
index 0a2d6b86075a..64d520937874 100644
--- a/arch/ia64/kvm/Kconfig
+++ b/arch/ia64/kvm/Kconfig
@@ -23,7 +23,7 @@ if VIRTUALIZATION
config KVM
tristate "Kernel-based Virtual Machine (KVM) support"
- depends on HAVE_KVM && EXPERIMENTAL
+ depends on HAVE_KVM && MODULES && EXPERIMENTAL
# for device assignment:
depends on PCI
select PREEMPT_NOTIFIERS
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 28af6a731bb8..80c57b0a21c4 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -41,6 +41,9 @@
#include <asm/div64.h>
#include <asm/tlb.h>
#include <asm/elf.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/clksupport.h>
+#include <asm/sn/shub_mmr.h>
#include "misc.h"
#include "vti.h"
@@ -65,6 +68,16 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
{ NULL }
};
+static unsigned long kvm_get_itc(struct kvm_vcpu *vcpu)
+{
+#if defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_GENERIC)
+ if (vcpu->kvm->arch.is_sn2)
+ return rtc_time();
+ else
+#endif
+ return ia64_getreg(_IA64_REG_AR_ITC);
+}
+
static void kvm_flush_icache(unsigned long start, unsigned long len)
{
int l;
@@ -119,8 +132,7 @@ void kvm_arch_hardware_enable(void *garbage)
unsigned long saved_psr;
int slot;
- pte = pte_val(mk_pte_phys(__pa(kvm_vmm_base),
- PAGE_KERNEL));
+ pte = pte_val(mk_pte_phys(__pa(kvm_vmm_base), PAGE_KERNEL));
local_irq_save(saved_psr);
slot = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT);
local_irq_restore(saved_psr);
@@ -283,6 +295,18 @@ static int handle_sal_call(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
}
+static int __apic_accept_irq(struct kvm_vcpu *vcpu, uint64_t vector)
+{
+ struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
+
+ if (!test_and_set_bit(vector, &vpd->irr[0])) {
+ vcpu->arch.irq_new_pending = 1;
+ kvm_vcpu_kick(vcpu);
+ return 1;
+ }
+ return 0;
+}
+
/*
* offset: address offset to IPI space.
* value: deliver value.
@@ -292,20 +316,20 @@ static void vcpu_deliver_ipi(struct kvm_vcpu *vcpu, uint64_t dm,
{
switch (dm) {
case SAPIC_FIXED:
- kvm_apic_set_irq(vcpu, vector, 0);
break;
case SAPIC_NMI:
- kvm_apic_set_irq(vcpu, 2, 0);
+ vector = 2;
break;
case SAPIC_EXTINT:
- kvm_apic_set_irq(vcpu, 0, 0);
+ vector = 0;
break;
case SAPIC_INIT:
case SAPIC_PMI:
default:
printk(KERN_ERR"kvm: Unimplemented Deliver reserved IPI!\n");
- break;
+ return;
}
+ __apic_accept_irq(vcpu, vector);
}
static struct kvm_vcpu *lid_to_vcpu(struct kvm *kvm, unsigned long id,
@@ -413,6 +437,23 @@ static int handle_switch_rr6(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
return 1;
}
+static int kvm_sn2_setup_mappings(struct kvm_vcpu *vcpu)
+{
+ unsigned long pte, rtc_phys_addr, map_addr;
+ int slot;
+
+ map_addr = KVM_VMM_BASE + (1UL << KVM_VMM_SHIFT);
+ rtc_phys_addr = LOCAL_MMR_OFFSET | SH_RTC;
+ pte = pte_val(mk_pte_phys(rtc_phys_addr, PAGE_KERNEL_UC));
+ slot = ia64_itr_entry(0x3, map_addr, pte, PAGE_SHIFT);
+ vcpu->arch.sn_rtc_tr_slot = slot;
+ if (slot < 0) {
+ printk(KERN_ERR "Mayday mayday! RTC mapping failed!\n");
+ slot = 0;
+ }
+ return slot;
+}
+
int kvm_emulate_halt(struct kvm_vcpu *vcpu)
{
@@ -426,7 +467,7 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu)
if (irqchip_in_kernel(vcpu->kvm)) {
- vcpu_now_itc = ia64_getreg(_IA64_REG_AR_ITC) + vcpu->arch.itc_offset;
+ vcpu_now_itc = kvm_get_itc(vcpu) + vcpu->arch.itc_offset;
if (time_after(vcpu_now_itc, vpd->itm)) {
vcpu->arch.timer_check = 1;
@@ -447,10 +488,10 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu)
hrtimer_cancel(p_ht);
vcpu->arch.ht_active = 0;
- if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests))
+ if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests) ||
+ kvm_cpu_has_pending_timer(vcpu))
if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED)
- vcpu->arch.mp_state =
- KVM_MP_STATE_RUNNABLE;
+ vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE)
return -EINTR;
@@ -551,22 +592,35 @@ static int kvm_insert_vmm_mapping(struct kvm_vcpu *vcpu)
if (r < 0)
goto out;
vcpu->arch.vm_tr_slot = r;
+
+#if defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_GENERIC)
+ if (kvm->arch.is_sn2) {
+ r = kvm_sn2_setup_mappings(vcpu);
+ if (r < 0)
+ goto out;
+ }
+#endif
+
r = 0;
out:
return r;
-
}
static void kvm_purge_vmm_mapping(struct kvm_vcpu *vcpu)
{
-
+ struct kvm *kvm = vcpu->kvm;
ia64_ptr_entry(0x3, vcpu->arch.vmm_tr_slot);
ia64_ptr_entry(0x3, vcpu->arch.vm_tr_slot);
-
+#if defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_GENERIC)
+ if (kvm->arch.is_sn2)
+ ia64_ptr_entry(0x3, vcpu->arch.sn_rtc_tr_slot);
+#endif
}
static int kvm_vcpu_pre_transition(struct kvm_vcpu *vcpu)
{
+ unsigned long psr;
+ int r;
int cpu = smp_processor_id();
if (vcpu->arch.last_run_cpu != cpu ||
@@ -578,62 +632,60 @@ static int kvm_vcpu_pre_transition(struct kvm_vcpu *vcpu)
vcpu->arch.host_rr6 = ia64_get_rr(RR6);
vti_set_rr6(vcpu->arch.vmm_rr);
- return kvm_insert_vmm_mapping(vcpu);
+ local_irq_save(psr);
+ r = kvm_insert_vmm_mapping(vcpu);
+ local_irq_restore(psr);
+ return r;
}
+
static void kvm_vcpu_post_transition(struct kvm_vcpu *vcpu)
{
kvm_purge_vmm_mapping(vcpu);
vti_set_rr6(vcpu->arch.host_rr6);
}
-static int vti_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
union context *host_ctx, *guest_ctx;
int r;
- /*Get host and guest context with guest address space.*/
- host_ctx = kvm_get_host_context(vcpu);
- guest_ctx = kvm_get_guest_context(vcpu);
-
- r = kvm_vcpu_pre_transition(vcpu);
- if (r < 0)
- goto out;
- kvm_vmm_info->tramp_entry(host_ctx, guest_ctx);
- kvm_vcpu_post_transition(vcpu);
- r = 0;
-out:
- return r;
-}
-
-static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
-{
- int r;
+ /*
+ * down_read() may sleep and return with interrupts enabled
+ */
+ down_read(&vcpu->kvm->slots_lock);
again:
- preempt_disable();
- local_irq_disable();
-
if (signal_pending(current)) {
- local_irq_enable();
- preempt_enable();
r = -EINTR;
kvm_run->exit_reason = KVM_EXIT_INTR;
goto out;
}
- vcpu->guest_mode = 1;
+ preempt_disable();
+ local_irq_disable();
+
+ /*Get host and guest context with guest address space.*/
+ host_ctx = kvm_get_host_context(vcpu);
+ guest_ctx = kvm_get_guest_context(vcpu);
+
+ clear_bit(KVM_REQ_KICK, &vcpu->requests);
+
+ r = kvm_vcpu_pre_transition(vcpu);
+ if (r < 0)
+ goto vcpu_run_fail;
+
+ up_read(&vcpu->kvm->slots_lock);
kvm_guest_enter();
- down_read(&vcpu->kvm->slots_lock);
- r = vti_vcpu_run(vcpu, kvm_run);
- if (r < 0) {
- local_irq_enable();
- preempt_enable();
- kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
- goto out;
- }
+
+ /*
+ * Transition to the guest
+ */
+ kvm_vmm_info->tramp_entry(host_ctx, guest_ctx);
+
+ kvm_vcpu_post_transition(vcpu);
vcpu->arch.launched = 1;
- vcpu->guest_mode = 0;
+ set_bit(KVM_REQ_KICK, &vcpu->requests);
local_irq_enable();
/*
@@ -644,9 +696,10 @@ again:
*/
barrier();
kvm_guest_exit();
- up_read(&vcpu->kvm->slots_lock);
preempt_enable();
+ down_read(&vcpu->kvm->slots_lock);
+
r = kvm_handle_exit(kvm_run, vcpu);
if (r > 0) {
@@ -655,12 +708,20 @@ again:
}
out:
+ up_read(&vcpu->kvm->slots_lock);
if (r > 0) {
kvm_resched(vcpu);
+ down_read(&vcpu->kvm->slots_lock);
goto again;
}
return r;
+
+vcpu_run_fail:
+ local_irq_enable();
+ preempt_enable();
+ kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
+ goto out;
}
static void kvm_set_mmio_data(struct kvm_vcpu *vcpu)
@@ -786,6 +847,9 @@ struct kvm *kvm_arch_create_vm(void)
if (IS_ERR(kvm))
return ERR_PTR(-ENOMEM);
+
+ kvm->arch.is_sn2 = ia64_platform_is("sn2");
+
kvm_init_vm(kvm);
kvm->arch.online_vcpus = 0;
@@ -882,7 +946,7 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
RESTORE_REGS(saved_gp);
vcpu->arch.irq_new_pending = 1;
- vcpu->arch.itc_offset = regs->saved_itc - ia64_getreg(_IA64_REG_AR_ITC);
+ vcpu->arch.itc_offset = regs->saved_itc - kvm_get_itc(vcpu);
set_bit(KVM_REQ_RESUME, &vcpu->requests);
vcpu_put(vcpu);
@@ -1041,10 +1105,6 @@ static void kvm_free_vmm_area(void)
}
}
-static void vti_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
-{
-}
-
static int vti_init_vpd(struct kvm_vcpu *vcpu)
{
int i;
@@ -1163,7 +1223,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
regs->cr_iip = PALE_RESET_ENTRY;
/*Initialize itc offset for vcpus*/
- itc_offset = 0UL - ia64_getreg(_IA64_REG_AR_ITC);
+ itc_offset = 0UL - kvm_get_itc(vcpu);
for (i = 0; i < kvm->arch.online_vcpus; i++) {
v = (struct kvm_vcpu *)((char *)vcpu +
sizeof(struct kvm_vcpu_data) * i);
@@ -1235,6 +1295,7 @@ static int vti_vcpu_setup(struct kvm_vcpu *vcpu, int id)
local_irq_save(psr);
r = kvm_insert_vmm_mapping(vcpu);
+ local_irq_restore(psr);
if (r)
goto fail;
r = kvm_vcpu_init(vcpu, vcpu->kvm, id);
@@ -1252,13 +1313,11 @@ static int vti_vcpu_setup(struct kvm_vcpu *vcpu, int id)
goto uninit;
kvm_purge_vmm_mapping(vcpu);
- local_irq_restore(psr);
return 0;
uninit:
kvm_vcpu_uninit(vcpu);
fail:
- local_irq_restore(psr);
return r;
}
@@ -1289,7 +1348,6 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
vcpu->kvm = kvm;
cpu = get_cpu();
- vti_vcpu_load(vcpu, cpu);
r = vti_vcpu_setup(vcpu, id);
put_cpu();
@@ -1425,7 +1483,7 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
}
for (i = 0; i < 4; i++)
regs->insvc[i] = vcpu->arch.insvc[i];
- regs->saved_itc = vcpu->arch.itc_offset + ia64_getreg(_IA64_REG_AR_ITC);
+ regs->saved_itc = vcpu->arch.itc_offset + kvm_get_itc(vcpu);
SAVE_REGS(xtp);
SAVE_REGS(metaphysical_rr0);
SAVE_REGS(metaphysical_rr4);
@@ -1572,6 +1630,7 @@ int kvm_arch_set_memory_region(struct kvm *kvm,
void kvm_arch_flush_shadow(struct kvm *kvm)
{
+ kvm_flush_remote_tlbs(kvm);
}
long kvm_arch_dev_ioctl(struct file *filp,
@@ -1614,8 +1673,37 @@ out:
return 0;
}
+
+/*
+ * On SN2, the ITC isn't stable, so copy in fast path code to use the
+ * SN2 RTC, replacing the ITC based default verion.
+ */
+static void kvm_patch_vmm(struct kvm_vmm_info *vmm_info,
+ struct module *module)
+{
+ unsigned long new_ar, new_ar_sn2;
+ unsigned long module_base;
+
+ if (!ia64_platform_is("sn2"))
+ return;
+
+ module_base = (unsigned long)module->module_core;
+
+ new_ar = kvm_vmm_base + vmm_info->patch_mov_ar - module_base;
+ new_ar_sn2 = kvm_vmm_base + vmm_info->patch_mov_ar_sn2 - module_base;
+
+ printk(KERN_INFO "kvm: Patching ITC emulation to use SGI SN2 RTC "
+ "as source\n");
+
+ /*
+ * Copy the SN2 version of mov_ar into place. They are both
+ * the same size, so 6 bundles is sufficient (6 * 0x10).
+ */
+ memcpy((void *)new_ar, (void *)new_ar_sn2, 0x60);
+}
+
static int kvm_relocate_vmm(struct kvm_vmm_info *vmm_info,
- struct module *module)
+ struct module *module)
{
unsigned long module_base;
unsigned long vmm_size;
@@ -1637,6 +1725,7 @@ static int kvm_relocate_vmm(struct kvm_vmm_info *vmm_info,
return -EFAULT;
memcpy((void *)kvm_vmm_base, (void *)module_base, vmm_size);
+ kvm_patch_vmm(vmm_info, module);
kvm_flush_icache(kvm_vmm_base, vmm_size);
/*Recalculate kvm_vmm_info based on new VMM*/
@@ -1790,38 +1879,24 @@ void kvm_arch_hardware_unsetup(void)
{
}
-static void vcpu_kick_intr(void *info)
-{
-#ifdef DEBUG
- struct kvm_vcpu *vcpu = (struct kvm_vcpu *)info;
- printk(KERN_DEBUG"vcpu_kick_intr %p \n", vcpu);
-#endif
-}
-
void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
{
- int ipi_pcpu = vcpu->cpu;
- int cpu = get_cpu();
+ int me;
+ int cpu = vcpu->cpu;
if (waitqueue_active(&vcpu->wq))
wake_up_interruptible(&vcpu->wq);
- if (vcpu->guest_mode && cpu != ipi_pcpu)
- smp_call_function_single(ipi_pcpu, vcpu_kick_intr, vcpu, 0);
+ me = get_cpu();
+ if (cpu != me && (unsigned) cpu < nr_cpu_ids && cpu_online(cpu))
+ if (!test_and_set_bit(KVM_REQ_KICK, &vcpu->requests))
+ smp_send_reschedule(cpu);
put_cpu();
}
-int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig)
+int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq)
{
-
- struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
-
- if (!test_and_set_bit(vec, &vpd->irr[0])) {
- vcpu->arch.irq_new_pending = 1;
- kvm_vcpu_kick(vcpu);
- return 1;
- }
- return 0;
+ return __apic_accept_irq(vcpu, irq->vector);
}
int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest)
@@ -1834,20 +1909,18 @@ int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda)
return 0;
}
-struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
- unsigned long bitmap)
+int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2)
{
- struct kvm_vcpu *lvcpu = kvm->vcpus[0];
- int i;
-
- for (i = 1; i < kvm->arch.online_vcpus; i++) {
- if (!kvm->vcpus[i])
- continue;
- if (lvcpu->arch.xtp > kvm->vcpus[i]->arch.xtp)
- lvcpu = kvm->vcpus[i];
- }
+ return vcpu1->arch.xtp - vcpu2->arch.xtp;
+}
- return lvcpu;
+int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
+ int short_hand, int dest, int dest_mode)
+{
+ struct kvm_lapic *target = vcpu->arch.apic;
+ return (dest_mode == 0) ?
+ kvm_apic_match_physical_addr(target, dest) :
+ kvm_apic_match_logical_addr(target, dest);
}
static int find_highest_bits(int *dat)
@@ -1886,6 +1959,12 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu)
return 0;
}
+int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu)
+{
+ /* do real check here */
+ return 1;
+}
+
int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
{
return vcpu->arch.timer_fired;
@@ -1916,6 +1995,7 @@ static int vcpu_reset(struct kvm_vcpu *vcpu)
long psr;
local_irq_save(psr);
r = kvm_insert_vmm_mapping(vcpu);
+ local_irq_restore(psr);
if (r)
goto fail;
@@ -1928,7 +2008,6 @@ static int vcpu_reset(struct kvm_vcpu *vcpu)
kvm_purge_vmm_mapping(vcpu);
r = 0;
fail:
- local_irq_restore(psr);
return r;
}
diff --git a/arch/ia64/kvm/kvm_fw.c b/arch/ia64/kvm/kvm_fw.c
index a8ae52ed5635..e4b82319881d 100644
--- a/arch/ia64/kvm/kvm_fw.c
+++ b/arch/ia64/kvm/kvm_fw.c
@@ -21,6 +21,9 @@
#include <linux/kvm_host.h>
#include <linux/smp.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/clksupport.h>
+#include <asm/sn/shub_mmr.h>
#include "vti.h"
#include "misc.h"
@@ -188,12 +191,35 @@ static struct ia64_pal_retval pal_freq_base(struct kvm_vcpu *vcpu)
return result;
}
-static struct ia64_pal_retval pal_freq_ratios(struct kvm_vcpu *vcpu)
+/*
+ * On the SGI SN2, the ITC isn't stable. Emulation backed by the SN2
+ * RTC is used instead. This function patches the ratios from SAL
+ * to match the RTC before providing them to the guest.
+ */
+static void sn2_patch_itc_freq_ratios(struct ia64_pal_retval *result)
{
+ struct pal_freq_ratio *ratio;
+ unsigned long sal_freq, sal_drift, factor;
+
+ result->status = ia64_sal_freq_base(SAL_FREQ_BASE_PLATFORM,
+ &sal_freq, &sal_drift);
+ ratio = (struct pal_freq_ratio *)&result->v2;
+ factor = ((sal_freq * 3) + (sn_rtc_cycles_per_second / 2)) /
+ sn_rtc_cycles_per_second;
+
+ ratio->num = 3;
+ ratio->den = factor;
+}
+static struct ia64_pal_retval pal_freq_ratios(struct kvm_vcpu *vcpu)
+{
struct ia64_pal_retval result;
PAL_CALL(result, PAL_FREQ_RATIOS, 0, 0, 0);
+
+ if (vcpu->kvm->arch.is_sn2)
+ sn2_patch_itc_freq_ratios(&result);
+
return result;
}
diff --git a/arch/ia64/kvm/lapic.h b/arch/ia64/kvm/lapic.h
index 6d6cbcb14893..ee541cebcd78 100644
--- a/arch/ia64/kvm/lapic.h
+++ b/arch/ia64/kvm/lapic.h
@@ -20,6 +20,10 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu);
int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
-int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig);
+int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
+ int short_hand, int dest, int dest_mode);
+int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2);
+int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq);
+#define kvm_apic_present(x) (true)
#endif
diff --git a/arch/ia64/kvm/optvfault.S b/arch/ia64/kvm/optvfault.S
index 32254ce9a1bd..f793be3effff 100644
--- a/arch/ia64/kvm/optvfault.S
+++ b/arch/ia64/kvm/optvfault.S
@@ -11,6 +11,7 @@
#include <asm/asmmacro.h>
#include <asm/processor.h>
+#include <asm/kvm_host.h>
#include "vti.h"
#include "asm-offsets.h"
@@ -140,6 +141,35 @@ GLOBAL_ENTRY(kvm_asm_mov_from_ar)
;;
END(kvm_asm_mov_from_ar)
+/*
+ * Special SGI SN2 optimized version of mov_from_ar using the SN2 RTC
+ * clock as it's source for emulating the ITC. This version will be
+ * copied on top of the original version if the host is determined to
+ * be an SN2.
+ */
+GLOBAL_ENTRY(kvm_asm_mov_from_ar_sn2)
+ add r18=VMM_VCPU_ITC_OFS_OFFSET, r21
+ movl r19 = (KVM_VMM_BASE+(1<<KVM_VMM_SHIFT))
+
+ add r16=VMM_VCPU_LAST_ITC_OFFSET,r21
+ extr.u r17=r25,6,7
+ mov r24=b0
+ ;;
+ ld8 r18=[r18]
+ ld8 r19=[r19]
+ addl r20=@gprel(asm_mov_to_reg),gp
+ ;;
+ add r19=r19,r18
+ shladd r17=r17,4,r20
+ ;;
+ adds r30=kvm_resume_to_guest-asm_mov_to_reg,r20
+ st8 [r16] = r19
+ mov b0=r17
+ br.sptk.few b0
+ ;;
+END(kvm_asm_mov_from_ar_sn2)
+
+
// mov r1=rr[r3]
GLOBAL_ENTRY(kvm_asm_mov_from_rr)
diff --git a/arch/ia64/kvm/process.c b/arch/ia64/kvm/process.c
index b1dc80952d91..a8f84da04b49 100644
--- a/arch/ia64/kvm/process.c
+++ b/arch/ia64/kvm/process.c
@@ -652,20 +652,25 @@ void kvm_ia64_handle_break(unsigned long ifa, struct kvm_pt_regs *regs,
unsigned long isr, unsigned long iim)
{
struct kvm_vcpu *v = current_vcpu;
+ long psr;
if (ia64_psr(regs)->cpl == 0) {
/* Allow hypercalls only when cpl = 0. */
if (iim == DOMN_PAL_REQUEST) {
+ local_irq_save(psr);
set_pal_call_data(v);
vmm_transition(v);
get_pal_call_result(v);
vcpu_increment_iip(v);
+ local_irq_restore(psr);
return;
} else if (iim == DOMN_SAL_REQUEST) {
+ local_irq_save(psr);
set_sal_call_data(v);
vmm_transition(v);
get_sal_call_result(v);
vcpu_increment_iip(v);
+ local_irq_restore(psr);
return;
}
}
diff --git a/arch/ia64/kvm/vcpu.c b/arch/ia64/kvm/vcpu.c
index a18ee17b9192..a2c6c15e4761 100644
--- a/arch/ia64/kvm/vcpu.c
+++ b/arch/ia64/kvm/vcpu.c
@@ -788,13 +788,29 @@ void vcpu_set_fpreg(struct kvm_vcpu *vcpu, unsigned long reg,
setfpreg(reg, val, regs); /* FIXME: handle NATs later*/
}
+/*
+ * The Altix RTC is mapped specially here for the vmm module
+ */
+#define SN_RTC_BASE (u64 *)(KVM_VMM_BASE+(1UL<<KVM_VMM_SHIFT))
+static long kvm_get_itc(struct kvm_vcpu *vcpu)
+{
+#if defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_GENERIC)
+ struct kvm *kvm = (struct kvm *)KVM_VM_BASE;
+
+ if (kvm->arch.is_sn2)
+ return (*SN_RTC_BASE);
+ else
+#endif
+ return ia64_getreg(_IA64_REG_AR_ITC);
+}
+
/************************************************************************
* lsapic timer
***********************************************************************/
u64 vcpu_get_itc(struct kvm_vcpu *vcpu)
{
unsigned long guest_itc;
- guest_itc = VMX(vcpu, itc_offset) + ia64_getreg(_IA64_REG_AR_ITC);
+ guest_itc = VMX(vcpu, itc_offset) + kvm_get_itc(vcpu);
if (guest_itc >= VMX(vcpu, last_itc)) {
VMX(vcpu, last_itc) = guest_itc;
@@ -809,7 +825,7 @@ static void vcpu_set_itc(struct kvm_vcpu *vcpu, u64 val)
struct kvm_vcpu *v;
struct kvm *kvm;
int i;
- long itc_offset = val - ia64_getreg(_IA64_REG_AR_ITC);
+ long itc_offset = val - kvm_get_itc(vcpu);
unsigned long vitv = VCPU(vcpu, itv);
kvm = (struct kvm *)KVM_VM_BASE;
diff --git a/arch/ia64/kvm/vmm.c b/arch/ia64/kvm/vmm.c
index 9eee5c04bacc..f4b4c899bb6c 100644
--- a/arch/ia64/kvm/vmm.c
+++ b/arch/ia64/kvm/vmm.c
@@ -30,15 +30,19 @@ MODULE_AUTHOR("Intel");
MODULE_LICENSE("GPL");
extern char kvm_ia64_ivt;
+extern char kvm_asm_mov_from_ar;
+extern char kvm_asm_mov_from_ar_sn2;
extern fpswa_interface_t *vmm_fpswa_interface;
long vmm_sanity = 1;
struct kvm_vmm_info vmm_info = {
- .module = THIS_MODULE,
- .vmm_entry = vmm_entry,
- .tramp_entry = vmm_trampoline,
- .vmm_ivt = (unsigned long)&kvm_ia64_ivt,
+ .module = THIS_MODULE,
+ .vmm_entry = vmm_entry,
+ .tramp_entry = vmm_trampoline,
+ .vmm_ivt = (unsigned long)&kvm_ia64_ivt,
+ .patch_mov_ar = (unsigned long)&kvm_asm_mov_from_ar,
+ .patch_mov_ar_sn2 = (unsigned long)&kvm_asm_mov_from_ar_sn2,
};
static int __init kvm_vmm_init(void)
diff --git a/arch/ia64/kvm/vmm_ivt.S b/arch/ia64/kvm/vmm_ivt.S
index 3ef1a017a318..40920c630649 100644
--- a/arch/ia64/kvm/vmm_ivt.S
+++ b/arch/ia64/kvm/vmm_ivt.S
@@ -95,7 +95,7 @@ GLOBAL_ENTRY(kvm_vmm_panic)
;;
srlz.i // guarantee that interruption collection is on
;;
- //(p15) ssm psr.i // restore psr.i
+ (p15) ssm psr.i // restore psr.
addl r14=@gprel(ia64_leave_hypervisor),gp
;;
KVM_SAVE_REST
@@ -249,7 +249,7 @@ ENTRY(kvm_break_fault)
;;
srlz.i // guarantee that interruption collection is on
;;
- //(p15)ssm psr.i // restore psr.i
+ (p15)ssm psr.i // restore psr.i
addl r14=@gprel(ia64_leave_hypervisor),gp
;;
KVM_SAVE_REST
@@ -439,7 +439,7 @@ kvm_dispatch_vexirq:
;;
srlz.i // guarantee that interruption collection is on
;;
- //(p15) ssm psr.i // restore psr.i
+ (p15) ssm psr.i // restore psr.i
adds r3=8,r2 // set up second base pointer
;;
KVM_SAVE_REST
@@ -819,7 +819,7 @@ ENTRY(kvm_dtlb_miss_dispatch)
;;
srlz.i // guarantee that interruption collection is on
;;
- //(p15) ssm psr.i // restore psr.i
+ (p15) ssm psr.i // restore psr.i
addl r14=@gprel(ia64_leave_hypervisor_prepare),gp
;;
KVM_SAVE_REST
@@ -842,7 +842,7 @@ ENTRY(kvm_itlb_miss_dispatch)
;;
srlz.i // guarantee that interruption collection is on
;;
- //(p15) ssm psr.i // restore psr.i
+ (p15) ssm psr.i // restore psr.i
addl r14=@gprel(ia64_leave_hypervisor),gp
;;
KVM_SAVE_REST
@@ -871,7 +871,7 @@ ENTRY(kvm_dispatch_reflection)
;;
srlz.i // guarantee that interruption collection is on
;;
- //(p15) ssm psr.i // restore psr.i
+ (p15) ssm psr.i // restore psr.i
addl r14=@gprel(ia64_leave_hypervisor),gp
;;
KVM_SAVE_REST
@@ -898,7 +898,7 @@ ENTRY(kvm_dispatch_virtualization_fault)
;;
srlz.i // guarantee that interruption collection is on
;;
- //(p15) ssm psr.i // restore psr.i
+ (p15) ssm psr.i // restore psr.i
addl r14=@gprel(ia64_leave_hypervisor_prepare),gp
;;
KVM_SAVE_REST
@@ -920,7 +920,7 @@ ENTRY(kvm_dispatch_interrupt)
;;
srlz.i
;;
- //(p15) ssm psr.i
+ (p15) ssm psr.i
addl r14=@gprel(ia64_leave_hypervisor),gp
;;
KVM_SAVE_REST
@@ -1333,7 +1333,7 @@ hostret = r24
;;
(p7) srlz.i
;;
-//(p6) ssm psr.i
+(p6) ssm psr.i
;;
mov rp=rpsave
mov ar.pfs=pfssave
diff --git a/arch/ia64/kvm/vtlb.c b/arch/ia64/kvm/vtlb.c
index 2c2501f13159..4290a429bf7c 100644
--- a/arch/ia64/kvm/vtlb.c
+++ b/arch/ia64/kvm/vtlb.c
@@ -254,7 +254,8 @@ u64 guest_vhpt_lookup(u64 iha, u64 *pte)
"(p7) st8 [%2]=r9;;"
"ssm psr.ic;;"
"srlz.d;;"
- /* "ssm psr.i;;" Once interrupts in vmm open, need fix*/
+ "ssm psr.i;;"
+ "srlz.d;;"
: "=r"(ret) : "r"(iha), "r"(pte):"memory");
return ret;
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index 66fd705e82c0..764f26abac05 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -227,7 +227,7 @@ finish_up:
return new_irq_info;
}
-static void sn_set_affinity_irq(unsigned int irq, const struct cpumask *mask)
+static int sn_set_affinity_irq(unsigned int irq, const struct cpumask *mask)
{
struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
nasid_t nasid;
@@ -239,6 +239,8 @@ static void sn_set_affinity_irq(unsigned int irq, const struct cpumask *mask)
list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
sn_irq_lh[irq], list)
(void)sn_retarget_vector(sn_irq_info, nasid, slice);
+
+ return 0;
}
#ifdef CONFIG_SMP
diff --git a/arch/ia64/sn/kernel/msi_sn.c b/arch/ia64/sn/kernel/msi_sn.c
index 81e428943d73..fbbfb9701201 100644
--- a/arch/ia64/sn/kernel/msi_sn.c
+++ b/arch/ia64/sn/kernel/msi_sn.c
@@ -151,7 +151,7 @@ int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry)
}
#ifdef CONFIG_SMP
-static void sn_set_msi_irq_affinity(unsigned int irq,
+static int sn_set_msi_irq_affinity(unsigned int irq,
const struct cpumask *cpu_mask)
{
struct msi_msg msg;
@@ -168,7 +168,7 @@ static void sn_set_msi_irq_affinity(unsigned int irq,
cpu = cpumask_first(cpu_mask);
sn_irq_info = sn_msi_info[irq].sn_irq_info;
if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
- return;
+ return -1;
/*
* Release XIO resources for the old MSI PCI address
@@ -189,7 +189,7 @@ static void sn_set_msi_irq_affinity(unsigned int irq,
new_irq_info = sn_retarget_vector(sn_irq_info, nasid, slice);
sn_msi_info[irq].sn_irq_info = new_irq_info;
if (new_irq_info == NULL)
- return;
+ return -1;
/*
* Map the xio address into bus space
@@ -206,6 +206,8 @@ static void sn_set_msi_irq_affinity(unsigned int irq,
write_msi_msg(irq, &msg);
cpumask_copy(irq_desc[irq].affinity, cpu_mask);
+
+ return 0;
}
#endif /* CONFIG_SMP */
diff --git a/arch/ia64/sn/kernel/sn2/timer.c b/arch/ia64/sn/kernel/sn2/timer.c
index cf67fc562054..21d6f09e3447 100644
--- a/arch/ia64/sn/kernel/sn2/timer.c
+++ b/arch/ia64/sn/kernel/sn2/timer.c
@@ -23,7 +23,7 @@
extern unsigned long sn_rtc_cycles_per_second;
-static cycle_t read_sn2(void)
+static cycle_t read_sn2(struct clocksource *cs)
{
return (cycle_t)readq(RTC_COUNTER_ADDR);
}
diff --git a/arch/ia64/xen/xensetup.S b/arch/ia64/xen/xensetup.S
index 28fed1fcc079..aff8346ea193 100644
--- a/arch/ia64/xen/xensetup.S
+++ b/arch/ia64/xen/xensetup.S
@@ -54,8 +54,6 @@ END(startup_xen)
#define isBP p3 // are we the Bootstrap Processor?
- .text
-
GLOBAL_ENTRY(xen_setup_hook)
mov r8=XEN_PV_DOMAIN_ASM
(isBP) movl r9=xen_domain_type;;
diff --git a/arch/m32r/boot/compressed/Makefile b/arch/m32r/boot/compressed/Makefile
index d908e1d3c07f..560484ae35ec 100644
--- a/arch/m32r/boot/compressed/Makefile
+++ b/arch/m32r/boot/compressed/Makefile
@@ -6,7 +6,6 @@
targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o \
piggy.o vmlinux.lds
-EXTRA_AFLAGS := -traditional
OBJECTS = $(obj)/head.o $(obj)/misc.o
diff --git a/include/asm-m32r/Kbuild b/arch/m32r/include/asm/Kbuild
index c68e1680da01..c68e1680da01 100644
--- a/include/asm-m32r/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
diff --git a/include/asm-m32r/addrspace.h b/arch/m32r/include/asm/addrspace.h
index 81782c122da4..81782c122da4 100644
--- a/include/asm-m32r/addrspace.h
+++ b/arch/m32r/include/asm/addrspace.h
diff --git a/include/asm-m32r/assembler.h b/arch/m32r/include/asm/assembler.h
index 26351539b5ff..728799fc70aa 100644
--- a/include/asm-m32r/assembler.h
+++ b/arch/m32r/include/asm/assembler.h
@@ -9,14 +9,15 @@
* This file contains M32R architecture specific macro definitions.
*/
+#include <linux/stringify.h>
+
+#undef __STR
-#ifndef __STR
#ifdef __ASSEMBLY__
#define __STR(x) x
#else
-#define __STR(x) #x
+#define __STR(x) __stringify(x)
#endif
-#endif /* __STR */
#ifdef CONFIG_SMP
#define M32R_LOCK __STR(lock)
diff --git a/include/asm-m32r/atomic.h b/arch/m32r/include/asm/atomic.h
index 2eed30f84080..2eed30f84080 100644
--- a/include/asm-m32r/atomic.h
+++ b/arch/m32r/include/asm/atomic.h
diff --git a/include/asm-m32r/auxvec.h b/arch/m32r/include/asm/auxvec.h
index f76dcc860fae..f76dcc860fae 100644
--- a/include/asm-m32r/auxvec.h
+++ b/arch/m32r/include/asm/auxvec.h
diff --git a/include/asm-m32r/bitops.h b/arch/m32r/include/asm/bitops.h
index aaddf0d57603..aaddf0d57603 100644
--- a/include/asm-m32r/bitops.h
+++ b/arch/m32r/include/asm/bitops.h
diff --git a/include/asm-m32r/bug.h b/arch/m32r/include/asm/bug.h
index 4cc0462c15b8..4cc0462c15b8 100644
--- a/include/asm-m32r/bug.h
+++ b/arch/m32r/include/asm/bug.h
diff --git a/include/asm-m32r/bugs.h b/arch/m32r/include/asm/bugs.h
index f77214eff136..f77214eff136 100644
--- a/include/asm-m32r/bugs.h
+++ b/arch/m32r/include/asm/bugs.h
diff --git a/include/asm-m32r/byteorder.h b/arch/m32r/include/asm/byteorder.h
index 21855d8b028b..21855d8b028b 100644
--- a/include/asm-m32r/byteorder.h
+++ b/arch/m32r/include/asm/byteorder.h
diff --git a/include/asm-m32r/cache.h b/arch/m32r/include/asm/cache.h
index 40b3ee98193d..40b3ee98193d 100644
--- a/include/asm-m32r/cache.h
+++ b/arch/m32r/include/asm/cache.h
diff --git a/include/asm-m32r/cachectl.h b/arch/m32r/include/asm/cachectl.h
index 2aab8f6fff41..2aab8f6fff41 100644
--- a/include/asm-m32r/cachectl.h
+++ b/arch/m32r/include/asm/cachectl.h
diff --git a/include/asm-m32r/cacheflush.h b/arch/m32r/include/asm/cacheflush.h
index 78587c958146..78587c958146 100644
--- a/include/asm-m32r/cacheflush.h
+++ b/arch/m32r/include/asm/cacheflush.h
diff --git a/include/asm-m32r/checksum.h b/arch/m32r/include/asm/checksum.h
index a7a7c4f44abe..a7a7c4f44abe 100644
--- a/include/asm-m32r/checksum.h
+++ b/arch/m32r/include/asm/checksum.h
diff --git a/include/asm-m32r/cputime.h b/arch/m32r/include/asm/cputime.h
index 0a47550df2b7..0a47550df2b7 100644
--- a/include/asm-m32r/cputime.h
+++ b/arch/m32r/include/asm/cputime.h
diff --git a/include/asm-m32r/current.h b/arch/m32r/include/asm/current.h
index 7859d864f2c2..7859d864f2c2 100644
--- a/include/asm-m32r/current.h
+++ b/arch/m32r/include/asm/current.h
diff --git a/include/asm-m32r/delay.h b/arch/m32r/include/asm/delay.h
index 9dd9e999ea69..9dd9e999ea69 100644
--- a/include/asm-m32r/delay.h
+++ b/arch/m32r/include/asm/delay.h
diff --git a/include/asm-m32r/device.h b/arch/m32r/include/asm/device.h
index d8f9872b0e2d..d8f9872b0e2d 100644
--- a/include/asm-m32r/device.h
+++ b/arch/m32r/include/asm/device.h
diff --git a/include/asm-m32r/div64.h b/arch/m32r/include/asm/div64.h
index 6cd978cefb28..6cd978cefb28 100644
--- a/include/asm-m32r/div64.h
+++ b/arch/m32r/include/asm/div64.h
diff --git a/include/asm-m32r/dma.h b/arch/m32r/include/asm/dma.h
index 52f6a22dd232..52f6a22dd232 100644
--- a/include/asm-m32r/dma.h
+++ b/arch/m32r/include/asm/dma.h
diff --git a/include/asm-m32r/elf.h b/arch/m32r/include/asm/elf.h
index 0cc34c94bf2b..0cc34c94bf2b 100644
--- a/include/asm-m32r/elf.h
+++ b/arch/m32r/include/asm/elf.h
diff --git a/include/asm-m32r/emergency-restart.h b/arch/m32r/include/asm/emergency-restart.h
index 108d8c48e42e..108d8c48e42e 100644
--- a/include/asm-m32r/emergency-restart.h
+++ b/arch/m32r/include/asm/emergency-restart.h
diff --git a/include/asm-m32r/errno.h b/arch/m32r/include/asm/errno.h
index 777149262aad..777149262aad 100644
--- a/include/asm-m32r/errno.h
+++ b/arch/m32r/include/asm/errno.h
diff --git a/include/asm-m32r/fb.h b/arch/m32r/include/asm/fb.h
index d92e99cd8c8a..d92e99cd8c8a 100644
--- a/include/asm-m32r/fb.h
+++ b/arch/m32r/include/asm/fb.h
diff --git a/include/asm-m32r/fcntl.h b/arch/m32r/include/asm/fcntl.h
index 46ab12db5739..46ab12db5739 100644
--- a/include/asm-m32r/fcntl.h
+++ b/arch/m32r/include/asm/fcntl.h
diff --git a/include/asm-m32r/flat.h b/arch/m32r/include/asm/flat.h
index d851cf0c4aa5..d851cf0c4aa5 100644
--- a/include/asm-m32r/flat.h
+++ b/arch/m32r/include/asm/flat.h
diff --git a/include/asm-m32r/ftrace.h b/arch/m32r/include/asm/ftrace.h
index 40a8c178f10d..40a8c178f10d 100644
--- a/include/asm-m32r/ftrace.h
+++ b/arch/m32r/include/asm/ftrace.h
diff --git a/include/asm-m32r/futex.h b/arch/m32r/include/asm/futex.h
index 6a332a9f099c..6a332a9f099c 100644
--- a/include/asm-m32r/futex.h
+++ b/arch/m32r/include/asm/futex.h
diff --git a/include/asm-m32r/hardirq.h b/arch/m32r/include/asm/hardirq.h
index cb8aa762f235..cb8aa762f235 100644
--- a/include/asm-m32r/hardirq.h
+++ b/arch/m32r/include/asm/hardirq.h
diff --git a/include/asm-m32r/hw_irq.h b/arch/m32r/include/asm/hw_irq.h
index 7138537cda03..7138537cda03 100644
--- a/include/asm-m32r/hw_irq.h
+++ b/arch/m32r/include/asm/hw_irq.h
diff --git a/include/asm-m32r/io.h b/arch/m32r/include/asm/io.h
index d06933bd6318..d06933bd6318 100644
--- a/include/asm-m32r/io.h
+++ b/arch/m32r/include/asm/io.h
diff --git a/include/asm-m32r/ioctl.h b/arch/m32r/include/asm/ioctl.h
index b279fe06dfe5..b279fe06dfe5 100644
--- a/include/asm-m32r/ioctl.h
+++ b/arch/m32r/include/asm/ioctl.h
diff --git a/include/asm-m32r/ioctls.h b/arch/m32r/include/asm/ioctls.h
index b9f54bb5d7cf..b9f54bb5d7cf 100644
--- a/include/asm-m32r/ioctls.h
+++ b/arch/m32r/include/asm/ioctls.h
diff --git a/include/asm-m32r/ipcbuf.h b/arch/m32r/include/asm/ipcbuf.h
index 8d2d7c8ffdb0..8d2d7c8ffdb0 100644
--- a/include/asm-m32r/ipcbuf.h
+++ b/arch/m32r/include/asm/ipcbuf.h
diff --git a/include/asm-m32r/irq.h b/arch/m32r/include/asm/irq.h
index 242028b4d86a..242028b4d86a 100644
--- a/include/asm-m32r/irq.h
+++ b/arch/m32r/include/asm/irq.h
diff --git a/include/asm-m32r/irq_regs.h b/arch/m32r/include/asm/irq_regs.h
index 3dd9c0b70270..3dd9c0b70270 100644
--- a/include/asm-m32r/irq_regs.h
+++ b/arch/m32r/include/asm/irq_regs.h
diff --git a/include/asm-m32r/kdebug.h b/arch/m32r/include/asm/kdebug.h
index 6ece1b037665..6ece1b037665 100644
--- a/include/asm-m32r/kdebug.h
+++ b/arch/m32r/include/asm/kdebug.h
diff --git a/include/asm-m32r/kmap_types.h b/arch/m32r/include/asm/kmap_types.h
index fa94dc6410ea..fa94dc6410ea 100644
--- a/include/asm-m32r/kmap_types.h
+++ b/arch/m32r/include/asm/kmap_types.h
diff --git a/include/asm-m32r/linkage.h b/arch/m32r/include/asm/linkage.h
index a9fb151cf648..a9fb151cf648 100644
--- a/include/asm-m32r/linkage.h
+++ b/arch/m32r/include/asm/linkage.h
diff --git a/include/asm-m32r/local.h b/arch/m32r/include/asm/local.h
index 22256d138630..22256d138630 100644
--- a/include/asm-m32r/local.h
+++ b/arch/m32r/include/asm/local.h
diff --git a/include/asm-m32r/m32102.h b/arch/m32r/include/asm/m32102.h
index 52807f8db166..52807f8db166 100644
--- a/include/asm-m32r/m32102.h
+++ b/arch/m32r/include/asm/m32102.h
diff --git a/include/asm-m32r/m32104ut/m32104ut_pld.h b/arch/m32r/include/asm/m32104ut/m32104ut_pld.h
index 2dc89d68b6d9..2dc89d68b6d9 100644
--- a/include/asm-m32r/m32104ut/m32104ut_pld.h
+++ b/arch/m32r/include/asm/m32104ut/m32104ut_pld.h
diff --git a/include/asm-m32r/m32700ut/m32700ut_lan.h b/arch/m32r/include/asm/m32700ut/m32700ut_lan.h
index aae810a4fb2c..aae810a4fb2c 100644
--- a/include/asm-m32r/m32700ut/m32700ut_lan.h
+++ b/arch/m32r/include/asm/m32700ut/m32700ut_lan.h
diff --git a/include/asm-m32r/m32700ut/m32700ut_lcd.h b/arch/m32r/include/asm/m32700ut/m32700ut_lcd.h
index 4c2489079788..4c2489079788 100644
--- a/include/asm-m32r/m32700ut/m32700ut_lcd.h
+++ b/arch/m32r/include/asm/m32700ut/m32700ut_lcd.h
diff --git a/include/asm-m32r/m32700ut/m32700ut_pld.h b/arch/m32r/include/asm/m32700ut/m32700ut_pld.h
index 57623beb44cb..57623beb44cb 100644
--- a/include/asm-m32r/m32700ut/m32700ut_pld.h
+++ b/arch/m32r/include/asm/m32700ut/m32700ut_pld.h
diff --git a/include/asm-m32r/m32r.h b/arch/m32r/include/asm/m32r.h
index 214b44b40757..214b44b40757 100644
--- a/include/asm-m32r/m32r.h
+++ b/arch/m32r/include/asm/m32r.h
diff --git a/include/asm-m32r/m32r_mp_fpga.h b/arch/m32r/include/asm/m32r_mp_fpga.h
index 976d2b995919..976d2b995919 100644
--- a/include/asm-m32r/m32r_mp_fpga.h
+++ b/arch/m32r/include/asm/m32r_mp_fpga.h
diff --git a/include/asm-m32r/mappi2/mappi2_pld.h b/arch/m32r/include/asm/mappi2/mappi2_pld.h
index 2624c9db7255..2624c9db7255 100644
--- a/include/asm-m32r/mappi2/mappi2_pld.h
+++ b/arch/m32r/include/asm/mappi2/mappi2_pld.h
diff --git a/include/asm-m32r/mappi3/mappi3_pld.h b/arch/m32r/include/asm/mappi3/mappi3_pld.h
index 451c40ee70af..451c40ee70af 100644
--- a/include/asm-m32r/mappi3/mappi3_pld.h
+++ b/arch/m32r/include/asm/mappi3/mappi3_pld.h
diff --git a/include/asm-m32r/mc146818rtc.h b/arch/m32r/include/asm/mc146818rtc.h
index aa1b7bf84f51..aa1b7bf84f51 100644
--- a/include/asm-m32r/mc146818rtc.h
+++ b/arch/m32r/include/asm/mc146818rtc.h
diff --git a/include/asm-m32r/mman.h b/arch/m32r/include/asm/mman.h
index 516a8973b130..516a8973b130 100644
--- a/include/asm-m32r/mman.h
+++ b/arch/m32r/include/asm/mman.h
diff --git a/include/asm-m32r/mmu.h b/arch/m32r/include/asm/mmu.h
index 150cb92bb666..150cb92bb666 100644
--- a/include/asm-m32r/mmu.h
+++ b/arch/m32r/include/asm/mmu.h
diff --git a/include/asm-m32r/mmu_context.h b/arch/m32r/include/asm/mmu_context.h
index 91909e5dd9d0..91909e5dd9d0 100644
--- a/include/asm-m32r/mmu_context.h
+++ b/arch/m32r/include/asm/mmu_context.h
diff --git a/include/asm-m32r/mmzone.h b/arch/m32r/include/asm/mmzone.h
index 9f3b5accda88..9f3b5accda88 100644
--- a/include/asm-m32r/mmzone.h
+++ b/arch/m32r/include/asm/mmzone.h
diff --git a/include/asm-m32r/module.h b/arch/m32r/include/asm/module.h
index eb73ee011215..eb73ee011215 100644
--- a/include/asm-m32r/module.h
+++ b/arch/m32r/include/asm/module.h
diff --git a/include/asm-m32r/msgbuf.h b/arch/m32r/include/asm/msgbuf.h
index 0d5a877b813e..0d5a877b813e 100644
--- a/include/asm-m32r/msgbuf.h
+++ b/arch/m32r/include/asm/msgbuf.h
diff --git a/include/asm-m32r/mutex.h b/arch/m32r/include/asm/mutex.h
index 458c1f7fbc18..458c1f7fbc18 100644
--- a/include/asm-m32r/mutex.h
+++ b/arch/m32r/include/asm/mutex.h
diff --git a/include/asm-m32r/opsput/opsput_lan.h b/arch/m32r/include/asm/opsput/opsput_lan.h
index a5f18dd1ab20..a5f18dd1ab20 100644
--- a/include/asm-m32r/opsput/opsput_lan.h
+++ b/arch/m32r/include/asm/opsput/opsput_lan.h
diff --git a/include/asm-m32r/opsput/opsput_lcd.h b/arch/m32r/include/asm/opsput/opsput_lcd.h
index 369c9f0832a6..369c9f0832a6 100644
--- a/include/asm-m32r/opsput/opsput_lcd.h
+++ b/arch/m32r/include/asm/opsput/opsput_lcd.h
diff --git a/include/asm-m32r/opsput/opsput_pld.h b/arch/m32r/include/asm/opsput/opsput_pld.h
index 3f11ea1aac2d..3f11ea1aac2d 100644
--- a/include/asm-m32r/opsput/opsput_pld.h
+++ b/arch/m32r/include/asm/opsput/opsput_pld.h
diff --git a/include/asm-m32r/page.h b/arch/m32r/include/asm/page.h
index c9333089fe11..c9333089fe11 100644
--- a/include/asm-m32r/page.h
+++ b/arch/m32r/include/asm/page.h
diff --git a/include/asm-m32r/param.h b/arch/m32r/include/asm/param.h
index 94c770196048..94c770196048 100644
--- a/include/asm-m32r/param.h
+++ b/arch/m32r/include/asm/param.h
diff --git a/include/asm-m32r/pci.h b/arch/m32r/include/asm/pci.h
index fe785d167db6..fe785d167db6 100644
--- a/include/asm-m32r/pci.h
+++ b/arch/m32r/include/asm/pci.h
diff --git a/include/asm-m32r/percpu.h b/arch/m32r/include/asm/percpu.h
index e3169301fe66..e3169301fe66 100644
--- a/include/asm-m32r/percpu.h
+++ b/arch/m32r/include/asm/percpu.h
diff --git a/include/asm-m32r/pgalloc.h b/arch/m32r/include/asm/pgalloc.h
index f11a2b909cdb..f11a2b909cdb 100644
--- a/include/asm-m32r/pgalloc.h
+++ b/arch/m32r/include/asm/pgalloc.h
diff --git a/include/asm-m32r/pgtable-2level.h b/arch/m32r/include/asm/pgtable-2level.h
index bca3475f9595..bca3475f9595 100644
--- a/include/asm-m32r/pgtable-2level.h
+++ b/arch/m32r/include/asm/pgtable-2level.h
diff --git a/include/asm-m32r/pgtable.h b/arch/m32r/include/asm/pgtable.h
index e6359c566b50..e6359c566b50 100644
--- a/include/asm-m32r/pgtable.h
+++ b/arch/m32r/include/asm/pgtable.h
diff --git a/include/asm-m32r/poll.h b/arch/m32r/include/asm/poll.h
index c98509d3149e..c98509d3149e 100644
--- a/include/asm-m32r/poll.h
+++ b/arch/m32r/include/asm/poll.h
diff --git a/include/asm-m32r/posix_types.h b/arch/m32r/include/asm/posix_types.h
index b309c5858637..b309c5858637 100644
--- a/include/asm-m32r/posix_types.h
+++ b/arch/m32r/include/asm/posix_types.h
diff --git a/include/asm-m32r/processor.h b/arch/m32r/include/asm/processor.h
index 1a997fc148a2..1a997fc148a2 100644
--- a/include/asm-m32r/processor.h
+++ b/arch/m32r/include/asm/processor.h
diff --git a/include/asm-m32r/ptrace.h b/arch/m32r/include/asm/ptrace.h
index a0755b982028..a0755b982028 100644
--- a/include/asm-m32r/ptrace.h
+++ b/arch/m32r/include/asm/ptrace.h
diff --git a/include/asm-m32r/resource.h b/arch/m32r/include/asm/resource.h
index b1ce766e37a0..b1ce766e37a0 100644
--- a/include/asm-m32r/resource.h
+++ b/arch/m32r/include/asm/resource.h
diff --git a/include/asm-m32r/rtc.h b/arch/m32r/include/asm/rtc.h
index 0340633f3f4d..0340633f3f4d 100644
--- a/include/asm-m32r/rtc.h
+++ b/arch/m32r/include/asm/rtc.h
diff --git a/include/asm-m32r/s1d13806.h b/arch/m32r/include/asm/s1d13806.h
index 248d36a82d79..248d36a82d79 100644
--- a/include/asm-m32r/s1d13806.h
+++ b/arch/m32r/include/asm/s1d13806.h
diff --git a/include/asm-m32r/scatterlist.h b/arch/m32r/include/asm/scatterlist.h
index 1ed372c73d0b..1ed372c73d0b 100644
--- a/include/asm-m32r/scatterlist.h
+++ b/arch/m32r/include/asm/scatterlist.h
diff --git a/include/asm-m32r/sections.h b/arch/m32r/include/asm/sections.h
index 5e5d21c4908a..5e5d21c4908a 100644
--- a/include/asm-m32r/sections.h
+++ b/arch/m32r/include/asm/sections.h
diff --git a/include/asm-m32r/segment.h b/arch/m32r/include/asm/segment.h
index 42b11aeb3249..42b11aeb3249 100644
--- a/include/asm-m32r/segment.h
+++ b/arch/m32r/include/asm/segment.h
diff --git a/include/asm-m32r/sembuf.h b/arch/m32r/include/asm/sembuf.h
index c9873d6890e2..c9873d6890e2 100644
--- a/include/asm-m32r/sembuf.h
+++ b/arch/m32r/include/asm/sembuf.h
diff --git a/include/asm-m32r/serial.h b/arch/m32r/include/asm/serial.h
index 5ac244c72f15..5ac244c72f15 100644
--- a/include/asm-m32r/serial.h
+++ b/arch/m32r/include/asm/serial.h
diff --git a/include/asm-m32r/setup.h b/arch/m32r/include/asm/setup.h
index c637ab992394..c637ab992394 100644
--- a/include/asm-m32r/setup.h
+++ b/arch/m32r/include/asm/setup.h
diff --git a/include/asm-m32r/shmbuf.h b/arch/m32r/include/asm/shmbuf.h
index b0cdf0aa7d65..b0cdf0aa7d65 100644
--- a/include/asm-m32r/shmbuf.h
+++ b/arch/m32r/include/asm/shmbuf.h
diff --git a/include/asm-m32r/shmparam.h b/arch/m32r/include/asm/shmparam.h
index 35986d81a528..35986d81a528 100644
--- a/include/asm-m32r/shmparam.h
+++ b/arch/m32r/include/asm/shmparam.h
diff --git a/include/asm-m32r/sigcontext.h b/arch/m32r/include/asm/sigcontext.h
index da4a9c36d09b..da4a9c36d09b 100644
--- a/include/asm-m32r/sigcontext.h
+++ b/arch/m32r/include/asm/sigcontext.h
diff --git a/include/asm-m32r/siginfo.h b/arch/m32r/include/asm/siginfo.h
index 7d9cd9ebfd0e..7d9cd9ebfd0e 100644
--- a/include/asm-m32r/siginfo.h
+++ b/arch/m32r/include/asm/siginfo.h
diff --git a/include/asm-m32r/signal.h b/arch/m32r/include/asm/signal.h
index 1a607066bc64..1a607066bc64 100644
--- a/include/asm-m32r/signal.h
+++ b/arch/m32r/include/asm/signal.h
diff --git a/include/asm-m32r/smp.h b/arch/m32r/include/asm/smp.h
index b96a6d2ffbc3..b96a6d2ffbc3 100644
--- a/include/asm-m32r/smp.h
+++ b/arch/m32r/include/asm/smp.h
diff --git a/include/asm-m32r/socket.h b/arch/m32r/include/asm/socket.h
index be7ed589af5c..be7ed589af5c 100644
--- a/include/asm-m32r/socket.h
+++ b/arch/m32r/include/asm/socket.h
diff --git a/include/asm-m32r/sockios.h b/arch/m32r/include/asm/sockios.h
index 6c1fb9b43bdb..6c1fb9b43bdb 100644
--- a/include/asm-m32r/sockios.h
+++ b/arch/m32r/include/asm/sockios.h
diff --git a/include/asm-m32r/spinlock.h b/arch/m32r/include/asm/spinlock.h
index dded923883b2..dded923883b2 100644
--- a/include/asm-m32r/spinlock.h
+++ b/arch/m32r/include/asm/spinlock.h
diff --git a/include/asm-m32r/spinlock_types.h b/arch/m32r/include/asm/spinlock_types.h
index 83f52105c0e4..83f52105c0e4 100644
--- a/include/asm-m32r/spinlock_types.h
+++ b/arch/m32r/include/asm/spinlock_types.h
diff --git a/include/asm-m32r/stat.h b/arch/m32r/include/asm/stat.h
index da4518f82d6d..da4518f82d6d 100644
--- a/include/asm-m32r/stat.h
+++ b/arch/m32r/include/asm/stat.h
diff --git a/include/asm-m32r/statfs.h b/arch/m32r/include/asm/statfs.h
index 6eb4c6007e6b..6eb4c6007e6b 100644
--- a/include/asm-m32r/statfs.h
+++ b/arch/m32r/include/asm/statfs.h
diff --git a/include/asm-m32r/string.h b/arch/m32r/include/asm/string.h
index e61e2b0bfc1f..e61e2b0bfc1f 100644
--- a/include/asm-m32r/string.h
+++ b/arch/m32r/include/asm/string.h
diff --git a/include/asm-m32r/swab.h b/arch/m32r/include/asm/swab.h
index 54dab001d6d1..54dab001d6d1 100644
--- a/include/asm-m32r/swab.h
+++ b/arch/m32r/include/asm/swab.h
diff --git a/include/asm-m32r/syscall.h b/arch/m32r/include/asm/syscall.h
index 25f316f2b78d..25f316f2b78d 100644
--- a/include/asm-m32r/syscall.h
+++ b/arch/m32r/include/asm/syscall.h
diff --git a/include/asm-m32r/system.h b/arch/m32r/include/asm/system.h
index c980f5ba8de7..c980f5ba8de7 100644
--- a/include/asm-m32r/system.h
+++ b/arch/m32r/include/asm/system.h
diff --git a/include/asm-m32r/termbits.h b/arch/m32r/include/asm/termbits.h
index bc104008b55b..bc104008b55b 100644
--- a/include/asm-m32r/termbits.h
+++ b/arch/m32r/include/asm/termbits.h
diff --git a/include/asm-m32r/termios.h b/arch/m32r/include/asm/termios.h
index 93ce79fd342a..93ce79fd342a 100644
--- a/include/asm-m32r/termios.h
+++ b/arch/m32r/include/asm/termios.h
diff --git a/include/asm-m32r/thread_info.h b/arch/m32r/include/asm/thread_info.h
index 8589d462df27..8589d462df27 100644
--- a/include/asm-m32r/thread_info.h
+++ b/arch/m32r/include/asm/thread_info.h
diff --git a/include/asm-m32r/timex.h b/arch/m32r/include/asm/timex.h
index bb9fe4feb12d..bb9fe4feb12d 100644
--- a/include/asm-m32r/timex.h
+++ b/arch/m32r/include/asm/timex.h
diff --git a/include/asm-m32r/tlb.h b/arch/m32r/include/asm/tlb.h
index c7ebd8d48f3b..c7ebd8d48f3b 100644
--- a/include/asm-m32r/tlb.h
+++ b/arch/m32r/include/asm/tlb.h
diff --git a/include/asm-m32r/tlbflush.h b/arch/m32r/include/asm/tlbflush.h
index 0ef95307784e..0ef95307784e 100644
--- a/include/asm-m32r/tlbflush.h
+++ b/arch/m32r/include/asm/tlbflush.h
diff --git a/include/asm-m32r/topology.h b/arch/m32r/include/asm/topology.h
index d607eb32bd7e..d607eb32bd7e 100644
--- a/include/asm-m32r/topology.h
+++ b/arch/m32r/include/asm/topology.h
diff --git a/include/asm-m32r/types.h b/arch/m32r/include/asm/types.h
index bc9f7fff0ac3..bc9f7fff0ac3 100644
--- a/include/asm-m32r/types.h
+++ b/arch/m32r/include/asm/types.h
diff --git a/include/asm-m32r/uaccess.h b/arch/m32r/include/asm/uaccess.h
index 1c7047bea200..1c7047bea200 100644
--- a/include/asm-m32r/uaccess.h
+++ b/arch/m32r/include/asm/uaccess.h
diff --git a/include/asm-m32r/ucontext.h b/arch/m32r/include/asm/ucontext.h
index 09324741eec3..09324741eec3 100644
--- a/include/asm-m32r/ucontext.h
+++ b/arch/m32r/include/asm/ucontext.h
diff --git a/include/asm-m32r/unaligned.h b/arch/m32r/include/asm/unaligned.h
index 377eb20d1ec6..377eb20d1ec6 100644
--- a/include/asm-m32r/unaligned.h
+++ b/arch/m32r/include/asm/unaligned.h
diff --git a/include/asm-m32r/unistd.h b/arch/m32r/include/asm/unistd.h
index cf701c933249..cf701c933249 100644
--- a/include/asm-m32r/unistd.h
+++ b/arch/m32r/include/asm/unistd.h
diff --git a/include/asm-m32r/user.h b/arch/m32r/include/asm/user.h
index 03b3c11c2aff..03b3c11c2aff 100644
--- a/include/asm-m32r/user.h
+++ b/arch/m32r/include/asm/user.h
diff --git a/include/asm-m32r/vga.h b/arch/m32r/include/asm/vga.h
index a1b63061c06f..a1b63061c06f 100644
--- a/include/asm-m32r/vga.h
+++ b/arch/m32r/include/asm/vga.h
diff --git a/include/asm-m32r/xor.h b/arch/m32r/include/asm/xor.h
index 6d525259df3e..6d525259df3e 100644
--- a/include/asm-m32r/xor.h
+++ b/arch/m32r/include/asm/xor.h
diff --git a/arch/m32r/kernel/Makefile b/arch/m32r/kernel/Makefile
index 09200d4886e3..b1a4b6036591 100644
--- a/arch/m32r/kernel/Makefile
+++ b/arch/m32r/kernel/Makefile
@@ -9,5 +9,3 @@ obj-y := process.o entry.o traps.o align.o irq.o setup.o time.o \
obj-$(CONFIG_SMP) += smp.o smpboot.o
obj-$(CONFIG_MODULES) += module.o
-
-EXTRA_AFLAGS := -traditional
diff --git a/arch/m32r/kernel/head.S b/arch/m32r/kernel/head.S
index 90916067b9c1..0a7194439eb1 100644
--- a/arch/m32r/kernel/head.S
+++ b/arch/m32r/kernel/head.S
@@ -23,7 +23,7 @@ __INITDATA
/*
* References to members of the boot_cpu_data structure.
*/
-.section .text.head, "ax"
+__HEAD
.global start_kernel
.global __bss_start
.global _end
diff --git a/arch/m32r/kernel/vmlinux.lds.S b/arch/m32r/kernel/vmlinux.lds.S
index 9db05df20c0e..4179adf6c624 100644
--- a/arch/m32r/kernel/vmlinux.lds.S
+++ b/arch/m32r/kernel/vmlinux.lds.S
@@ -27,7 +27,7 @@ SECTIONS
_text = .; /* Text and read-only data */
.boot : { *(.boot) } = 0
.text : {
- *(.text.head)
+ HEAD_TEXT
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig
index 23597beb66c1..0f69fa5ddf26 100644
--- a/arch/m68k/configs/amiga_defconfig
+++ b/arch/m68k/configs/amiga_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc7
-# Tue Dec 2 20:27:42 2008
+# Linux kernel version: 2.6.30-rc3
+# Wed Apr 22 20:47:52 2009
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -29,14 +29,24 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
# CONFIG_SYSFS_DEPRECATED_V2 is not set
CONFIG_RELAY=y
CONFIG_NAMESPACES=y
@@ -44,23 +54,27 @@ CONFIG_NAMESPACES=y
# CONFIG_IPC_NS is not set
# CONFIG_USER_NS is not set
# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -68,15 +82,16 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -84,11 +99,8 @@ 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=y
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -104,7 +116,6 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
# CONFIG_FREEZER is not set
#
@@ -140,12 +151,13 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
#
# General setup
@@ -157,7 +169,7 @@ CONFIG_BINFMT_AOUT=m
CONFIG_BINFMT_MISC=m
CONFIG_ZORRO=y
CONFIG_AMIGA_PCMCIA=y
-# CONFIG_HEARTBEAT is not set
+CONFIG_HEARTBEAT=y
CONFIG_PROC_HARDWARE=y
CONFIG_ISA=y
CONFIG_GENERIC_ISA_DMA=y
@@ -184,7 +196,10 @@ CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# 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 is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
CONFIG_NET_IPIP=m
CONFIG_NET_IPGRE=m
# CONFIG_ARPD is not set
@@ -258,6 +273,7 @@ CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
@@ -266,6 +282,7 @@ CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
@@ -276,6 +293,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -354,25 +372,20 @@ CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
CONFIG_IP6_NF_MATCH_MH=m
CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_RAW=m
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=m
-# CONFIG_IP_DCCP_CCID3_DEBUG is not set
-CONFIG_IP_DCCP_CCID3_RTO=100
-CONFIG_IP_DCCP_TFRC_LIB=m
+# CONFIG_IP_DCCP_CCID3 is not set
CONFIG_IP_SCTP=m
# CONFIG_SCTP_DBG_MSG is not set
# CONFIG_SCTP_DBG_OBJCNT is not set
@@ -394,8 +407,10 @@ CONFIG_ATALK=m
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
CONFIG_NET_CLS_ROUTE=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -406,8 +421,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -453,15 +468,20 @@ CONFIG_CDROM_PKTCDVD_BUFFERS=8
CONFIG_ATA_OVER_ETH=m
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
#
# Please see Documentation/ide/ide.txt for help/info on IDE drives
#
+CONFIG_IDE_ATAPI=y
# CONFIG_BLK_DEV_IDE_SATA is not set
CONFIG_IDE_GD=y
CONFIG_IDE_GD_ATA=y
@@ -469,7 +489,6 @@ CONFIG_IDE_GD_ATA=y
CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -478,7 +497,6 @@ CONFIG_IDE_PROC_FS=y
#
# CONFIG_BLK_DEV_PLATFORM is not set
CONFIG_BLK_DEV_GAYLE=y
-CONFIG_BLK_DEV_IDEDOUBLER=y
CONFIG_BLK_DEV_BUDDHA=y
# CONFIG_BLK_DEV_IDEDMA is not set
@@ -530,6 +548,8 @@ CONFIG_ISCSI_TCP=m
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_IN2000 is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DTC3280 is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GENERIC_NCR5380 is not set
@@ -547,6 +567,7 @@ CONFIG_GVP11_SCSI=y
CONFIG_SCSI_A4000T=y
CONFIG_SCSI_ZORRO7XX=y
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_MD_LINEAR=m
@@ -554,7 +575,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
# CONFIG_MD_RAID10 is not set
CONFIG_MD_RAID456=m
-CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_RAID6_PQ=m
# CONFIG_MD_MULTIPATH is not set
# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=m
@@ -567,6 +588,7 @@ CONFIG_DM_MULTIPATH=m
# CONFIG_DM_DELAY is not set
CONFIG_DM_UEVENT=y
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_DUMMY=m
# CONFIG_BONDING is not set
CONFIG_MACVLAN=m
@@ -577,14 +599,16 @@ CONFIG_VETH=m
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
-CONFIG_ARIADNE=m
-CONFIG_A2065=m
-CONFIG_HYDRA=m
-CONFIG_ZORRO8390=m
-CONFIG_APNE=m
+CONFIG_ARIADNE=y
+CONFIG_A2065=y
+CONFIG_HYDRA=y
+CONFIG_ZORRO8390=y
+CONFIG_APNE=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_ETHOC is not set
# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_DNET is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
# CONFIG_HP100 is not set
@@ -609,7 +633,10 @@ CONFIG_APNE=m
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_PLIP is not set
CONFIG_PPP=m
@@ -719,7 +746,7 @@ CONFIG_HW_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
# CONFIG_DEVKMEM is not set
# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_A2232=m
+CONFIG_A2232=y
#
# Serial drivers
@@ -730,6 +757,7 @@ CONFIG_A2232=m
# Non-8250 serial port support
#
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
CONFIG_PRINTER=m
@@ -821,6 +849,7 @@ CONFIG_FB_FM2=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -856,7 +885,6 @@ CONFIG_HIDRAW=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -867,14 +895,13 @@ CONFIG_HID_COMPAT=y
# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
#
CONFIG_AMIGA_BUILTIN_SERIAL=y
CONFIG_MULTIFACE_III_TTY=m
-# CONFIG_SERIAL_CONSOLE is not set
+CONFIG_SERIAL_CONSOLE=y
#
# File systems
@@ -883,6 +910,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
@@ -909,13 +937,15 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
-# CONFIG_OCFS2_COMPAT_JBD is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_QUOTA_TREE=m
# CONFIG_QFMT_V1 is not set
# CONFIG_QFMT_V2 is not set
CONFIG_QUOTACTL=y
@@ -924,6 +954,11 @@ CONFIG_AUTOFS4_FS=m
CONFIG_FUSE_FS=m
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
@@ -935,8 +970,8 @@ CONFIG_UDF_NLS=y
#
# DOS/FAT/NT Filesystems
#
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=m
CONFIG_FAT_DEFAULT_CODEPAGE=437
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
@@ -954,10 +989,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
CONFIG_AFFS_FS=m
CONFIG_HFS_FS=m
@@ -966,6 +998,9 @@ CONFIG_HFSPLUS_FS=m
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
# CONFIG_VXFS_FS is not set
CONFIG_MINIX_FS=y
# CONFIG_OMFS_FS is not set
@@ -976,23 +1011,24 @@ CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
# CONFIG_UFS_DEBUG is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
-CONFIG_NFS_FS=m
+CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
CONFIG_NFS_V4=y
+# CONFIG_ROOT_NFS is not set
CONFIG_NFSD=m
CONFIG_NFSD_V3=y
# CONFIG_NFSD_V3_ACL is not set
# CONFIG_NFSD_V4 is not set
-CONFIG_LOCKD=m
+CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=m
-CONFIG_SUNRPC_GSS=m
-# CONFIG_SUNRPC_REGISTER_V4 is not set
-CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
CONFIG_SMB_NLS_DEFAULT=y
@@ -1067,11 +1103,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-
-#
-# Tracers
-#
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -1092,13 +1123,21 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_AUTHENC=m
CONFIG_CRYPTO_TEST=m
@@ -1113,7 +1152,7 @@ CONFIG_CRYPTO_SEQIV=m
#
# Block modes
#
-CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_CTR=m
CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_ECB=m
@@ -1132,7 +1171,7 @@ CONFIG_CRYPTO_XCBC=m
#
CONFIG_CRYPTO_CRC32C=m
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD128=m
CONFIG_CRYPTO_RMD160=m
@@ -1154,7 +1193,7 @@ CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SALSA20=m
@@ -1168,6 +1207,7 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
# Compression
#
CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
#
@@ -1175,11 +1215,13 @@ CONFIG_CRYPTO_LZO=m
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
@@ -1191,10 +1233,13 @@ CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
CONFIG_LZO_COMPRESS=m
CONFIG_LZO_DECOMPRESS=m
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
CONFIG_TEXTSEARCH_FSM=m
-CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig
index 935108d115a0..5fff58196b3e 100644
--- a/arch/m68k/configs/apollo_defconfig
+++ b/arch/m68k/configs/apollo_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc7
-# Tue Dec 2 20:27:43 2008
+# Linux kernel version: 2.6.30-rc3
+# Wed Apr 22 20:47:54 2009
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -29,14 +29,24 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
# CONFIG_SYSFS_DEPRECATED_V2 is not set
CONFIG_RELAY=y
CONFIG_NAMESPACES=y
@@ -44,23 +54,27 @@ CONFIG_NAMESPACES=y
# CONFIG_IPC_NS is not set
# CONFIG_USER_NS is not set
# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -68,15 +82,16 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -84,11 +99,8 @@ 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=y
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -104,7 +116,6 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
# CONFIG_FREEZER is not set
#
@@ -140,12 +151,13 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
#
# General setup
@@ -256,6 +268,7 @@ CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
@@ -264,6 +277,7 @@ CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
@@ -274,6 +288,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -352,25 +367,20 @@ CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
CONFIG_IP6_NF_MATCH_MH=m
CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_RAW=m
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=m
-# CONFIG_IP_DCCP_CCID3_DEBUG is not set
-CONFIG_IP_DCCP_CCID3_RTO=100
-CONFIG_IP_DCCP_TFRC_LIB=m
+# CONFIG_IP_DCCP_CCID3 is not set
CONFIG_IP_SCTP=m
# CONFIG_SCTP_DBG_MSG is not set
# CONFIG_SCTP_DBG_OBJCNT is not set
@@ -392,8 +402,10 @@ CONFIG_ATALK=m
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
CONFIG_NET_CLS_ROUTE=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -404,8 +416,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -441,9 +453,13 @@ CONFIG_CDROM_PKTCDVD_BUFFERS=8
CONFIG_ATA_OVER_ETH=m
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -491,8 +507,11 @@ CONFIG_SCSI_SRP_ATTRS=m
CONFIG_SCSI_SRP_TGT_ATTRS=y
CONFIG_SCSI_LOWLEVEL=y
CONFIG_ISCSI_TCP=m
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_MD_LINEAR=m
@@ -500,7 +519,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
# CONFIG_MD_RAID10 is not set
CONFIG_MD_RAID456=m
-CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_RAID6_PQ=m
# CONFIG_MD_MULTIPATH is not set
# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=m
@@ -513,6 +532,7 @@ CONFIG_DM_MULTIPATH=m
# CONFIG_DM_DELAY is not set
CONFIG_DM_UEVENT=y
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_DUMMY=m
# CONFIG_BONDING is not set
CONFIG_MACVLAN=m
@@ -522,6 +542,8 @@ CONFIG_VETH=m
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET 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
@@ -538,7 +560,10 @@ CONFIG_NET_ETHERNET=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
CONFIG_PPP=m
# CONFIG_PPP_MULTILINK is not set
@@ -596,7 +621,6 @@ CONFIG_MOUSE_PS2=m
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
@@ -636,6 +660,7 @@ CONFIG_VT_HW_CONSOLE_BINDING=y
# Non-8250 serial port support
#
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -718,6 +743,7 @@ CONFIG_FB_APOLLO=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -749,7 +775,6 @@ CONFIG_HIDRAW=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -757,9 +782,9 @@ CONFIG_HID_COMPAT=y
# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
@@ -774,6 +799,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
@@ -800,13 +826,15 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
-# CONFIG_OCFS2_COMPAT_JBD is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_QUOTA_TREE=m
# CONFIG_QFMT_V1 is not set
# CONFIG_QFMT_V2 is not set
CONFIG_QUOTACTL=y
@@ -815,6 +843,11 @@ CONFIG_AUTOFS4_FS=m
CONFIG_FUSE_FS=m
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
@@ -845,10 +878,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
CONFIG_AFFS_FS=m
CONFIG_HFS_FS=m
@@ -857,6 +887,9 @@ CONFIG_HFSPLUS_FS=m
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
# CONFIG_VXFS_FS is not set
CONFIG_MINIX_FS=y
# CONFIG_OMFS_FS is not set
@@ -867,6 +900,7 @@ CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
# CONFIG_UFS_DEBUG is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -883,7 +917,6 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -958,11 +991,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-
-#
-# Tracers
-#
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -983,13 +1011,21 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_AUTHENC=m
CONFIG_CRYPTO_TEST=m
@@ -1059,6 +1095,7 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
# Compression
#
CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
#
@@ -1066,11 +1103,13 @@ CONFIG_CRYPTO_LZO=m
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
@@ -1082,10 +1121,13 @@ CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
CONFIG_LZO_COMPRESS=m
CONFIG_LZO_DECOMPRESS=m
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
CONFIG_TEXTSEARCH_FSM=m
-CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig
index a594a1d47b62..d92a90e03ecb 100644
--- a/arch/m68k/configs/atari_defconfig
+++ b/arch/m68k/configs/atari_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc7
-# Tue Dec 2 20:27:44 2008
+# Linux kernel version: 2.6.30-rc3
+# Wed Apr 22 20:47:56 2009
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -29,14 +29,24 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
# CONFIG_SYSFS_DEPRECATED_V2 is not set
CONFIG_RELAY=y
CONFIG_NAMESPACES=y
@@ -44,23 +54,27 @@ CONFIG_NAMESPACES=y
# CONFIG_IPC_NS is not set
# CONFIG_USER_NS is not set
# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -68,15 +82,16 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -84,11 +99,8 @@ 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=y
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -104,7 +116,6 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
# CONFIG_FREEZER is not set
#
@@ -140,12 +151,13 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
#
# General setup
@@ -180,7 +192,10 @@ CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# 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 is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
CONFIG_NET_IPIP=m
CONFIG_NET_IPGRE=m
# CONFIG_ARPD is not set
@@ -254,6 +269,7 @@ CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
@@ -262,6 +278,7 @@ CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
@@ -272,6 +289,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -350,25 +368,20 @@ CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
CONFIG_IP6_NF_MATCH_MH=m
CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_RAW=m
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=m
-# CONFIG_IP_DCCP_CCID3_DEBUG is not set
-CONFIG_IP_DCCP_CCID3_RTO=100
-CONFIG_IP_DCCP_TFRC_LIB=m
+# CONFIG_IP_DCCP_CCID3 is not set
CONFIG_IP_SCTP=m
# CONFIG_SCTP_DBG_MSG is not set
# CONFIG_SCTP_DBG_OBJCNT is not set
@@ -390,8 +403,10 @@ CONFIG_ATALK=m
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
CONFIG_NET_CLS_ROUTE=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -402,8 +417,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -445,15 +460,20 @@ CONFIG_CDROM_PKTCDVD_BUFFERS=8
CONFIG_ATA_OVER_ETH=m
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
#
# Please see Documentation/ide/ide.txt for help/info on IDE drives
#
+CONFIG_IDE_ATAPI=y
# CONFIG_BLK_DEV_IDE_SATA is not set
CONFIG_IDE_GD=y
CONFIG_IDE_GD_ATA=y
@@ -461,7 +481,6 @@ CONFIG_IDE_GD_ATA=y
CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -516,11 +535,14 @@ CONFIG_SCSI_SRP_ATTRS=m
CONFIG_SCSI_SRP_TGT_ATTRS=y
CONFIG_SCSI_LOWLEVEL=y
CONFIG_ISCSI_TCP=m
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DEBUG is not set
CONFIG_ATARI_SCSI=y
# CONFIG_ATARI_SCSI_TOSHIBA_DELAY is not set
# CONFIG_ATARI_SCSI_RESET_BOOT is not set
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_MD_LINEAR=m
@@ -528,7 +550,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
# CONFIG_MD_RAID10 is not set
CONFIG_MD_RAID456=m
-CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_RAID6_PQ=m
# CONFIG_MD_MULTIPATH is not set
# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=m
@@ -541,6 +563,7 @@ CONFIG_DM_MULTIPATH=m
# CONFIG_DM_DELAY is not set
CONFIG_DM_UEVENT=y
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_DUMMY=m
# CONFIG_BONDING is not set
CONFIG_MACVLAN=m
@@ -550,7 +573,9 @@ CONFIG_VETH=m
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
-CONFIG_ATARILANCE=m
+CONFIG_ATARILANCE=y
+# CONFIG_ETHOC is not set
+# CONFIG_DNET 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
@@ -568,7 +593,10 @@ CONFIG_ATARILANCE=m
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_PLIP is not set
CONFIG_PPP=m
@@ -625,11 +653,10 @@ CONFIG_INPUT_KEYBOARD=y
CONFIG_ATARI_KBD_CORE=y
CONFIG_KEYBOARD_ATARI=y
CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2=m
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
@@ -649,7 +676,7 @@ CONFIG_INPUT_M68K_BEEP=m
CONFIG_SERIO=y
# CONFIG_SERIO_SERPORT is not set
# CONFIG_SERIO_PARKBD is not set
-CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_LIBPS2=m
# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
@@ -673,6 +700,7 @@ CONFIG_VT_HW_CONSOLE_BINDING=y
# Non-8250 serial port support
#
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
CONFIG_PRINTER=m
@@ -760,6 +788,7 @@ CONFIG_FB_ATARI=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -794,7 +823,6 @@ CONFIG_HIDRAW=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -805,14 +833,14 @@ CONFIG_HID_COMPAT=y
# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
#
-CONFIG_ATARI_MFPSER=m
-CONFIG_ATARI_MIDI=m
+CONFIG_ATARI_MFPSER=y
+CONFIG_ATARI_MIDI=y
CONFIG_ATARI_DSP56K=m
+CONFIG_SERIAL_CONSOLE=y
#
# File systems
@@ -821,6 +849,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
@@ -847,13 +876,15 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
-# CONFIG_OCFS2_COMPAT_JBD is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_QUOTA_TREE=m
# CONFIG_QFMT_V1 is not set
# CONFIG_QFMT_V2 is not set
CONFIG_QUOTACTL=y
@@ -862,6 +893,11 @@ CONFIG_AUTOFS4_FS=m
CONFIG_FUSE_FS=m
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
@@ -892,10 +928,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
CONFIG_AFFS_FS=m
CONFIG_HFS_FS=m
@@ -904,6 +937,9 @@ CONFIG_HFSPLUS_FS=m
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
# CONFIG_VXFS_FS is not set
CONFIG_MINIX_FS=y
# CONFIG_OMFS_FS is not set
@@ -914,22 +950,24 @@ CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
# CONFIG_UFS_DEBUG is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
-CONFIG_NFS_FS=m
+CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFS_V4 is not set
+CONFIG_NFS_V4=y
+# CONFIG_ROOT_NFS is not set
CONFIG_NFSD=m
CONFIG_NFSD_V3=y
# CONFIG_NFSD_V3_ACL is not set
# CONFIG_NFSD_V4 is not set
-CONFIG_LOCKD=m
+CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=m
-# CONFIG_SUNRPC_REGISTER_V4 is not set
-# CONFIG_RPCSEC_GSS_KRB5 is not set
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
CONFIG_SMB_NLS_DEFAULT=y
@@ -1004,11 +1042,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-
-#
-# Tracers
-#
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -1029,13 +1062,21 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_AUTHENC=m
CONFIG_CRYPTO_TEST=m
@@ -1050,7 +1091,7 @@ CONFIG_CRYPTO_SEQIV=m
#
# Block modes
#
-CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_CTR=m
CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_ECB=m
@@ -1069,7 +1110,7 @@ CONFIG_CRYPTO_XCBC=m
#
CONFIG_CRYPTO_CRC32C=m
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD128=m
CONFIG_CRYPTO_RMD160=m
@@ -1091,7 +1132,7 @@ CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SALSA20=m
@@ -1105,6 +1146,7 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
# Compression
#
CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
#
@@ -1112,11 +1154,13 @@ CONFIG_CRYPTO_LZO=m
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=y
CONFIG_CRC_T10DIF=y
@@ -1128,10 +1172,13 @@ CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
CONFIG_LZO_COMPRESS=m
CONFIG_LZO_DECOMPRESS=m
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
CONFIG_TEXTSEARCH_FSM=m
-CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig
index d3d9814a91de..6e6b1aa66682 100644
--- a/arch/m68k/configs/bvme6000_defconfig
+++ b/arch/m68k/configs/bvme6000_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc7
-# Tue Dec 2 20:27:45 2008
+# Linux kernel version: 2.6.30-rc3
+# Wed Apr 22 20:47:59 2009
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -29,14 +29,24 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
# CONFIG_SYSFS_DEPRECATED_V2 is not set
CONFIG_RELAY=y
CONFIG_NAMESPACES=y
@@ -44,23 +54,27 @@ CONFIG_NAMESPACES=y
# CONFIG_IPC_NS is not set
# CONFIG_USER_NS is not set
# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -68,15 +82,16 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -84,11 +99,8 @@ 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=y
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -104,7 +116,6 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
# CONFIG_FREEZER is not set
#
@@ -143,12 +154,13 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
#
# General setup
@@ -258,6 +270,7 @@ CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
@@ -266,6 +279,7 @@ CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
@@ -276,6 +290,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -354,25 +369,20 @@ CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
CONFIG_IP6_NF_MATCH_MH=m
CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_RAW=m
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=m
-# CONFIG_IP_DCCP_CCID3_DEBUG is not set
-CONFIG_IP_DCCP_CCID3_RTO=100
-CONFIG_IP_DCCP_TFRC_LIB=m
+# CONFIG_IP_DCCP_CCID3 is not set
CONFIG_IP_SCTP=m
# CONFIG_SCTP_DBG_MSG is not set
# CONFIG_SCTP_DBG_OBJCNT is not set
@@ -394,8 +404,10 @@ CONFIG_ATALK=m
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
CONFIG_NET_CLS_ROUTE=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -406,8 +418,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -443,9 +455,13 @@ CONFIG_CDROM_PKTCDVD_BUFFERS=8
CONFIG_ATA_OVER_ETH=m
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -493,10 +509,13 @@ CONFIG_SCSI_SRP_ATTRS=m
CONFIG_SCSI_SRP_TGT_ATTRS=y
CONFIG_SCSI_LOWLEVEL=y
CONFIG_ISCSI_TCP=m
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
CONFIG_53C700_BE_BUS=y
# CONFIG_SCSI_DEBUG is not set
CONFIG_BVME6000_SCSI=y
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_MD_LINEAR=m
@@ -504,7 +523,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
# CONFIG_MD_RAID10 is not set
CONFIG_MD_RAID456=m
-CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_RAID6_PQ=m
# CONFIG_MD_MULTIPATH is not set
# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=m
@@ -517,6 +536,7 @@ CONFIG_DM_MULTIPATH=m
# CONFIG_DM_DELAY is not set
CONFIG_DM_UEVENT=y
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_DUMMY=m
# CONFIG_BONDING is not set
CONFIG_MACVLAN=m
@@ -527,6 +547,8 @@ CONFIG_VETH=m
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
CONFIG_BVME6000_NET=y
+# CONFIG_ETHOC is not set
+# CONFIG_DNET 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
@@ -543,7 +565,10 @@ CONFIG_BVME6000_NET=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
CONFIG_PPP=m
# CONFIG_PPP_MULTILINK is not set
@@ -601,7 +626,6 @@ CONFIG_MOUSE_PS2=m
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
@@ -641,6 +665,7 @@ CONFIG_VT_HW_CONSOLE_BINDING=y
# Non-8250 serial port support
#
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -717,7 +742,6 @@ CONFIG_HIDRAW=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -725,9 +749,9 @@ CONFIG_HID_COMPAT=y
# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
@@ -742,6 +766,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
@@ -768,13 +793,15 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
-# CONFIG_OCFS2_COMPAT_JBD is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_QUOTA_TREE=m
# CONFIG_QFMT_V1 is not set
# CONFIG_QFMT_V2 is not set
CONFIG_QUOTACTL=y
@@ -783,6 +810,11 @@ CONFIG_AUTOFS4_FS=m
CONFIG_FUSE_FS=m
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
@@ -813,10 +845,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
CONFIG_AFFS_FS=m
CONFIG_HFS_FS=m
@@ -825,6 +854,9 @@ CONFIG_HFSPLUS_FS=m
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
# CONFIG_VXFS_FS is not set
CONFIG_MINIX_FS=y
# CONFIG_OMFS_FS is not set
@@ -835,6 +867,7 @@ CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
# CONFIG_UFS_DEBUG is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -851,7 +884,6 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -927,11 +959,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-
-#
-# Tracers
-#
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -952,13 +979,21 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_AUTHENC=m
CONFIG_CRYPTO_TEST=m
@@ -1028,6 +1063,7 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
# Compression
#
CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
#
@@ -1035,11 +1071,13 @@ CONFIG_CRYPTO_LZO=m
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
CONFIG_BITREVERSE=m
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
@@ -1051,10 +1089,13 @@ CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
CONFIG_LZO_COMPRESS=m
CONFIG_LZO_DECOMPRESS=m
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
CONFIG_TEXTSEARCH_FSM=m
-CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig
index 5556ef088d04..bc0565f63a15 100644
--- a/arch/m68k/configs/hp300_defconfig
+++ b/arch/m68k/configs/hp300_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc7
-# Tue Dec 2 20:27:46 2008
+# Linux kernel version: 2.6.30-rc3
+# Wed Apr 22 20:48:01 2009
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -29,14 +29,24 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
# CONFIG_SYSFS_DEPRECATED_V2 is not set
CONFIG_RELAY=y
CONFIG_NAMESPACES=y
@@ -44,23 +54,27 @@ CONFIG_NAMESPACES=y
# CONFIG_IPC_NS is not set
# CONFIG_USER_NS is not set
# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -68,15 +82,16 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -84,11 +99,8 @@ 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=y
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -104,7 +116,6 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
# CONFIG_FREEZER is not set
#
@@ -141,12 +152,13 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
#
# General setup
@@ -257,6 +269,7 @@ CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
@@ -265,6 +278,7 @@ CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
@@ -275,6 +289,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -353,25 +368,20 @@ CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
CONFIG_IP6_NF_MATCH_MH=m
CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_RAW=m
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=m
-# CONFIG_IP_DCCP_CCID3_DEBUG is not set
-CONFIG_IP_DCCP_CCID3_RTO=100
-CONFIG_IP_DCCP_TFRC_LIB=m
+# CONFIG_IP_DCCP_CCID3 is not set
CONFIG_IP_SCTP=m
# CONFIG_SCTP_DBG_MSG is not set
# CONFIG_SCTP_DBG_OBJCNT is not set
@@ -393,8 +403,10 @@ CONFIG_ATALK=m
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
CONFIG_NET_CLS_ROUTE=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -405,8 +417,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -442,9 +454,13 @@ CONFIG_CDROM_PKTCDVD_BUFFERS=8
CONFIG_ATA_OVER_ETH=m
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -492,8 +508,11 @@ CONFIG_SCSI_SRP_ATTRS=m
CONFIG_SCSI_SRP_TGT_ATTRS=y
CONFIG_SCSI_LOWLEVEL=y
CONFIG_ISCSI_TCP=m
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_MD_LINEAR=m
@@ -501,7 +520,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
# CONFIG_MD_RAID10 is not set
CONFIG_MD_RAID456=m
-CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_RAID6_PQ=m
# CONFIG_MD_MULTIPATH is not set
# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=m
@@ -514,6 +533,7 @@ CONFIG_DM_MULTIPATH=m
# CONFIG_DM_DELAY is not set
CONFIG_DM_UEVENT=y
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_DUMMY=m
# CONFIG_BONDING is not set
CONFIG_MACVLAN=m
@@ -524,6 +544,8 @@ CONFIG_VETH=m
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
CONFIG_HPLANCE=y
+# CONFIG_ETHOC is not set
+# CONFIG_DNET 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
@@ -540,7 +562,10 @@ CONFIG_HPLANCE=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
CONFIG_PPP=m
# CONFIG_PPP_MULTILINK is not set
@@ -600,7 +625,6 @@ CONFIG_MOUSE_PS2=m
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
@@ -646,6 +670,7 @@ CONFIG_VT_HW_CONSOLE_BINDING=y
# Non-8250 serial port support
#
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -728,6 +753,7 @@ CONFIG_FB_HP300=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -759,7 +785,6 @@ CONFIG_HIDRAW=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -767,9 +792,9 @@ CONFIG_HID_COMPAT=y
# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
@@ -782,6 +807,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
@@ -808,13 +834,15 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
-# CONFIG_OCFS2_COMPAT_JBD is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_QUOTA_TREE=m
# CONFIG_QFMT_V1 is not set
# CONFIG_QFMT_V2 is not set
CONFIG_QUOTACTL=y
@@ -823,6 +851,11 @@ CONFIG_AUTOFS4_FS=m
CONFIG_FUSE_FS=m
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
@@ -853,10 +886,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
CONFIG_AFFS_FS=m
CONFIG_HFS_FS=m
@@ -865,6 +895,9 @@ CONFIG_HFSPLUS_FS=m
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
# CONFIG_VXFS_FS is not set
CONFIG_MINIX_FS=y
# CONFIG_OMFS_FS is not set
@@ -875,6 +908,7 @@ CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
# CONFIG_UFS_DEBUG is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -891,7 +925,6 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -966,11 +999,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-
-#
-# Tracers
-#
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -991,13 +1019,21 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_AUTHENC=m
CONFIG_CRYPTO_TEST=m
@@ -1067,6 +1103,7 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
# Compression
#
CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
#
@@ -1074,11 +1111,13 @@ CONFIG_CRYPTO_LZO=m
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
@@ -1090,10 +1129,13 @@ CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
CONFIG_LZO_COMPRESS=m
CONFIG_LZO_DECOMPRESS=m
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
CONFIG_TEXTSEARCH_FSM=m
-CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
index c6de25724a25..9991b64fea57 100644
--- a/arch/m68k/configs/mac_defconfig
+++ b/arch/m68k/configs/mac_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc7
-# Tue Dec 2 20:27:47 2008
+# Linux kernel version: 2.6.30-rc3
+# Wed Apr 22 20:48:03 2009
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -29,14 +29,24 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
# CONFIG_SYSFS_DEPRECATED_V2 is not set
CONFIG_RELAY=y
CONFIG_NAMESPACES=y
@@ -44,23 +54,27 @@ CONFIG_NAMESPACES=y
# CONFIG_IPC_NS is not set
# CONFIG_USER_NS is not set
# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -68,15 +82,16 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -84,11 +99,8 @@ 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=y
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -104,7 +116,6 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
# CONFIG_FREEZER is not set
#
@@ -142,12 +153,13 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
#
# General setup
@@ -255,6 +267,7 @@ CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
@@ -263,6 +276,7 @@ CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
@@ -273,6 +287,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -351,25 +366,20 @@ CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
CONFIG_IP6_NF_MATCH_MH=m
CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_RAW=m
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=m
-# CONFIG_IP_DCCP_CCID3_DEBUG is not set
-CONFIG_IP_DCCP_CCID3_RTO=100
-CONFIG_IP_DCCP_TFRC_LIB=m
+# CONFIG_IP_DCCP_CCID3 is not set
CONFIG_IP_SCTP=m
# CONFIG_SCTP_DBG_MSG is not set
# CONFIG_SCTP_DBG_OBJCNT is not set
@@ -394,8 +404,10 @@ CONFIG_IPDDP_DECAP=y
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
CONFIG_NET_CLS_ROUTE=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -406,8 +418,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -429,6 +441,7 @@ CONFIG_CONNECTOR=m
# CONFIG_MTD is not set
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_SWIM=y
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_CRYPTOLOOP=m
@@ -443,15 +456,20 @@ CONFIG_CDROM_PKTCDVD_BUFFERS=8
CONFIG_ATA_OVER_ETH=m
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
#
# Please see Documentation/ide/ide.txt for help/info on IDE drives
#
+CONFIG_IDE_ATAPI=y
# CONFIG_BLK_DEV_IDE_SATA is not set
CONFIG_IDE_GD=y
CONFIG_IDE_GD_ATA=y
@@ -459,7 +477,6 @@ CONFIG_IDE_GD_ATA=y
CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -514,10 +531,13 @@ CONFIG_SCSI_SRP_ATTRS=m
CONFIG_SCSI_SRP_TGT_ATTRS=y
CONFIG_SCSI_LOWLEVEL=y
CONFIG_ISCSI_TCP=m
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DEBUG is not set
CONFIG_MAC_SCSI=y
CONFIG_SCSI_MAC_ESP=y
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_MD_LINEAR=m
@@ -525,7 +545,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
# CONFIG_MD_RAID10 is not set
CONFIG_MD_RAID456=m
-CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_RAID6_PQ=m
# CONFIG_MD_MULTIPATH is not set
# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=m
@@ -547,6 +567,7 @@ CONFIG_ADB_CUDA=y
CONFIG_INPUT_ADBHID=y
CONFIG_MAC_EMUMOUSEBTN=y
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_DUMMY=m
# CONFIG_BONDING is not set
CONFIG_MACVLAN=m
@@ -561,6 +582,8 @@ CONFIG_MAC89x0=m
CONFIG_MACSONIC=m
CONFIG_MACMACE=y
# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET 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
@@ -577,7 +600,10 @@ CONFIG_MACMACE=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
CONFIG_PPP=m
# CONFIG_PPP_MULTILINK is not set
@@ -635,7 +661,6 @@ CONFIG_MOUSE_PS2=m
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
@@ -677,6 +702,7 @@ CONFIG_VT_HW_CONSOLE_BINDING=y
# Non-8250 serial port support
#
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -760,6 +786,7 @@ CONFIG_FB_MAC=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -793,7 +820,6 @@ CONFIG_HIDRAW=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -801,9 +827,9 @@ CONFIG_HID_COMPAT=y
# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
@@ -819,6 +845,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
@@ -845,13 +872,15 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
-# CONFIG_OCFS2_COMPAT_JBD is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_QUOTA_TREE=m
# CONFIG_QFMT_V1 is not set
# CONFIG_QFMT_V2 is not set
CONFIG_QUOTACTL=y
@@ -860,6 +889,11 @@ CONFIG_AUTOFS4_FS=m
CONFIG_FUSE_FS=m
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
@@ -890,10 +924,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
CONFIG_AFFS_FS=m
CONFIG_HFS_FS=y
@@ -902,6 +933,9 @@ CONFIG_HFSPLUS_FS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
# CONFIG_VXFS_FS is not set
CONFIG_MINIX_FS=y
# CONFIG_OMFS_FS is not set
@@ -912,6 +946,7 @@ CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
# CONFIG_UFS_DEBUG is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
@@ -927,7 +962,6 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
CONFIG_SUNRPC_GSS=m
-# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=m
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -1003,11 +1037,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-
-#
-# Tracers
-#
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -1028,13 +1057,21 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
-CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_AUTHENC=m
CONFIG_CRYPTO_TEST=m
@@ -1104,6 +1141,7 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
# Compression
#
CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
#
@@ -1111,11 +1149,13 @@ CONFIG_CRYPTO_LZO=m
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
@@ -1127,10 +1167,13 @@ CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
CONFIG_LZO_COMPRESS=m
CONFIG_LZO_DECOMPRESS=m
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
CONFIG_TEXTSEARCH_FSM=m
-CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig
index 70693588031e..69c43e2d8b45 100644
--- a/arch/m68k/configs/multi_defconfig
+++ b/arch/m68k/configs/multi_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc7
-# Tue Dec 2 20:27:48 2008
+# Linux kernel version: 2.6.30-rc3
+# Wed Apr 22 20:48:06 2009
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -29,14 +29,24 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
# CONFIG_SYSFS_DEPRECATED_V2 is not set
CONFIG_RELAY=y
CONFIG_NAMESPACES=y
@@ -44,23 +54,27 @@ CONFIG_NAMESPACES=y
# CONFIG_IPC_NS is not set
# CONFIG_USER_NS is not set
# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -68,15 +82,16 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -84,11 +99,8 @@ 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=y
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -104,7 +116,6 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
# CONFIG_FREEZER is not set
#
@@ -146,12 +157,13 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
#
# General setup
@@ -268,6 +280,7 @@ CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
@@ -276,6 +289,7 @@ CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
@@ -286,6 +300,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -364,25 +379,20 @@ CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
CONFIG_IP6_NF_MATCH_MH=m
CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_RAW=m
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=m
-# CONFIG_IP_DCCP_CCID3_DEBUG is not set
-CONFIG_IP_DCCP_CCID3_RTO=100
-CONFIG_IP_DCCP_TFRC_LIB=m
+# CONFIG_IP_DCCP_CCID3 is not set
CONFIG_IP_SCTP=m
# CONFIG_SCTP_DBG_MSG is not set
# CONFIG_SCTP_DBG_OBJCNT is not set
@@ -408,8 +418,10 @@ CONFIG_IPDDP_DECAP=y
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
CONFIG_NET_CLS_ROUTE=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -420,8 +432,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -454,6 +466,7 @@ CONFIG_PARPORT_NOT_PC=y
CONFIG_BLK_DEV=y
CONFIG_AMIGA_FLOPPY=y
CONFIG_ATARI_FLOPPY=y
+CONFIG_BLK_DEV_SWIM=y
CONFIG_AMIGA_Z2RAM=y
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
@@ -469,15 +482,20 @@ CONFIG_CDROM_PKTCDVD_BUFFERS=8
CONFIG_ATA_OVER_ETH=m
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
#
# Please see Documentation/ide/ide.txt for help/info on IDE drives
#
+CONFIG_IDE_ATAPI=y
# CONFIG_BLK_DEV_IDE_SATA is not set
CONFIG_IDE_GD=y
CONFIG_IDE_GD_ATA=y
@@ -485,7 +503,6 @@ CONFIG_IDE_GD_ATA=y
CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -494,7 +511,6 @@ CONFIG_IDE_PROC_FS=y
#
# CONFIG_BLK_DEV_PLATFORM is not set
CONFIG_BLK_DEV_GAYLE=y
-CONFIG_BLK_DEV_IDEDOUBLER=y
CONFIG_BLK_DEV_BUDDHA=y
CONFIG_BLK_DEV_FALCON_IDE=y
CONFIG_BLK_DEV_MAC_IDE=y
@@ -549,6 +565,8 @@ CONFIG_ISCSI_TCP=m
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_IN2000 is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DTC3280 is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GENERIC_NCR5380 is not set
@@ -575,6 +593,7 @@ CONFIG_MVME16x_SCSI=y
CONFIG_BVME6000_SCSI=y
CONFIG_SUN3X_ESP=y
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_MD_LINEAR=m
@@ -582,7 +601,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
# CONFIG_MD_RAID10 is not set
CONFIG_MD_RAID456=m
-CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_RAID6_PQ=m
# CONFIG_MD_MULTIPATH is not set
# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=m
@@ -604,6 +623,7 @@ CONFIG_ADB_CUDA=y
CONFIG_INPUT_ADBHID=y
CONFIG_MAC_EMUMOUSEBTN=y
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_DUMMY=m
# CONFIG_BONDING is not set
CONFIG_MACVLAN=m
@@ -614,24 +634,26 @@ CONFIG_VETH=m
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
-CONFIG_ARIADNE=m
-CONFIG_A2065=m
-CONFIG_HYDRA=m
-CONFIG_ZORRO8390=m
-CONFIG_APNE=m
+CONFIG_ARIADNE=y
+CONFIG_A2065=y
+CONFIG_HYDRA=y
+CONFIG_ZORRO8390=y
+CONFIG_APNE=y
CONFIG_MAC8390=y
-CONFIG_MAC89x0=m
-CONFIG_MACSONIC=m
+CONFIG_MAC89x0=y
+CONFIG_MACSONIC=y
CONFIG_MACMACE=y
CONFIG_MVME147_NET=y
CONFIG_MVME16x_NET=y
CONFIG_BVME6000_NET=y
-CONFIG_ATARILANCE=m
+CONFIG_ATARILANCE=y
CONFIG_SUN3LANCE=y
CONFIG_HPLANCE=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_ETHOC is not set
# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_DNET is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
# CONFIG_HP100 is not set
@@ -657,7 +679,10 @@ CONFIG_NE2000=m
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_PLIP is not set
CONFIG_PPP=m
@@ -717,11 +742,10 @@ CONFIG_KEYBOARD_ATARI=y
CONFIG_KEYBOARD_HIL_OLD=y
CONFIG_KEYBOARD_HIL=y
CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2=m
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
@@ -732,7 +756,7 @@ CONFIG_MOUSE_SERIAL=m
CONFIG_MOUSE_AMIGA=m
CONFIG_MOUSE_ATARI=m
# CONFIG_MOUSE_VSXXXAA is not set
-CONFIG_MOUSE_HIL=m
+CONFIG_MOUSE_HIL=y
CONFIG_INPUT_JOYSTICK=y
# CONFIG_JOYSTICK_ANALOG is not set
# CONFIG_JOYSTICK_A3D is not set
@@ -763,18 +787,18 @@ CONFIG_JOYSTICK_AMIGA=m
CONFIG_INPUT_MISC=y
CONFIG_INPUT_M68K_BEEP=m
# CONFIG_INPUT_UINPUT is not set
-CONFIG_HP_SDC_RTC=m
+CONFIG_HP_SDC_RTC=y
#
# Hardware I/O ports
#
CONFIG_SERIO=y
# CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIO_Q40KBD=m
+CONFIG_SERIO_Q40KBD=y
# CONFIG_SERIO_PARKBD is not set
CONFIG_HP_SDC=y
CONFIG_HIL_MLC=y
-CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_LIBPS2=m
# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
@@ -788,7 +812,7 @@ CONFIG_HW_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
# CONFIG_DEVKMEM is not set
# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_A2232=m
+CONFIG_A2232=y
#
# Serial drivers
@@ -799,6 +823,7 @@ CONFIG_A2232=m
# Non-8250 serial port support
#
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
CONFIG_PRINTER=m
@@ -807,7 +832,7 @@ CONFIG_PRINTER=m
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
CONFIG_NVRAM=y
-CONFIG_GEN_RTC=m
+CONFIG_GEN_RTC=y
CONFIG_GEN_RTC_X=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
@@ -898,6 +923,7 @@ CONFIG_FB_HP300=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -937,7 +963,6 @@ CONFIG_HIDRAW=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -948,13 +973,12 @@ CONFIG_HID_COMPAT=y
# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
#
-CONFIG_ATARI_MFPSER=m
-CONFIG_ATARI_MIDI=m
+CONFIG_ATARI_MFPSER=y
+CONFIG_ATARI_MIDI=y
CONFIG_ATARI_DSP56K=m
CONFIG_AMIGA_BUILTIN_SERIAL=y
CONFIG_MULTIFACE_III_TTY=m
@@ -974,6 +998,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
@@ -1000,13 +1025,15 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
-# CONFIG_OCFS2_COMPAT_JBD is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_QUOTA_TREE=m
# CONFIG_QFMT_V1 is not set
# CONFIG_QFMT_V2 is not set
CONFIG_QUOTACTL=y
@@ -1015,6 +1042,11 @@ CONFIG_AUTOFS4_FS=m
CONFIG_FUSE_FS=m
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
@@ -1045,10 +1077,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
CONFIG_AFFS_FS=m
CONFIG_HFS_FS=y
@@ -1057,6 +1086,9 @@ CONFIG_HFSPLUS_FS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
# CONFIG_VXFS_FS is not set
CONFIG_MINIX_FS=y
# CONFIG_OMFS_FS is not set
@@ -1067,6 +1099,7 @@ CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
# CONFIG_UFS_DEBUG is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -1083,7 +1116,6 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -1163,11 +1195,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-
-#
-# Tracers
-#
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -1188,13 +1215,21 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_AUTHENC=m
CONFIG_CRYPTO_TEST=m
@@ -1264,6 +1299,7 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
# Compression
#
CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
#
@@ -1271,11 +1307,13 @@ CONFIG_CRYPTO_LZO=m
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=y
CONFIG_CRC_T10DIF=y
@@ -1287,10 +1325,13 @@ CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
CONFIG_LZO_COMPRESS=m
CONFIG_LZO_DECOMPRESS=m
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
CONFIG_TEXTSEARCH_FSM=m
-CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig
index 52d42715bd0b..7dceb5d71223 100644
--- a/arch/m68k/configs/mvme147_defconfig
+++ b/arch/m68k/configs/mvme147_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc7
-# Tue Dec 2 20:27:50 2008
+# Linux kernel version: 2.6.30-rc3
+# Wed Apr 22 20:48:08 2009
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -29,14 +29,24 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
# CONFIG_SYSFS_DEPRECATED_V2 is not set
CONFIG_RELAY=y
CONFIG_NAMESPACES=y
@@ -44,23 +54,27 @@ CONFIG_NAMESPACES=y
# CONFIG_IPC_NS is not set
# CONFIG_USER_NS is not set
# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -68,15 +82,16 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -84,11 +99,8 @@ 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=y
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -104,7 +116,6 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
# CONFIG_FREEZER is not set
#
@@ -143,12 +154,13 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
#
# General setup
@@ -258,6 +270,7 @@ CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
@@ -266,6 +279,7 @@ CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
@@ -276,6 +290,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -354,25 +369,20 @@ CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
CONFIG_IP6_NF_MATCH_MH=m
CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_RAW=m
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=m
-# CONFIG_IP_DCCP_CCID3_DEBUG is not set
-CONFIG_IP_DCCP_CCID3_RTO=100
-CONFIG_IP_DCCP_TFRC_LIB=m
+# CONFIG_IP_DCCP_CCID3 is not set
CONFIG_IP_SCTP=m
# CONFIG_SCTP_DBG_MSG is not set
# CONFIG_SCTP_DBG_OBJCNT is not set
@@ -394,8 +404,10 @@ CONFIG_ATALK=m
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
CONFIG_NET_CLS_ROUTE=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -406,8 +418,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -443,9 +455,13 @@ CONFIG_CDROM_PKTCDVD_BUFFERS=8
CONFIG_ATA_OVER_ETH=m
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -493,9 +509,12 @@ CONFIG_SCSI_SRP_ATTRS=m
CONFIG_SCSI_SRP_TGT_ATTRS=y
CONFIG_SCSI_LOWLEVEL=y
CONFIG_ISCSI_TCP=m
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DEBUG is not set
CONFIG_MVME147_SCSI=y
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_MD_LINEAR=m
@@ -503,7 +522,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
# CONFIG_MD_RAID10 is not set
CONFIG_MD_RAID456=m
-CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_RAID6_PQ=m
# CONFIG_MD_MULTIPATH is not set
# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=m
@@ -516,6 +535,7 @@ CONFIG_DM_MULTIPATH=m
# CONFIG_DM_DELAY is not set
CONFIG_DM_UEVENT=y
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_DUMMY=m
# CONFIG_BONDING is not set
CONFIG_MACVLAN=m
@@ -526,6 +546,8 @@ CONFIG_VETH=m
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
CONFIG_MVME147_NET=y
+# CONFIG_ETHOC is not set
+# CONFIG_DNET 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
@@ -542,7 +564,10 @@ CONFIG_MVME147_NET=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
CONFIG_PPP=m
# CONFIG_PPP_MULTILINK is not set
@@ -600,7 +625,6 @@ CONFIG_MOUSE_PS2=m
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
@@ -640,6 +664,7 @@ CONFIG_VT_HW_CONSOLE_BINDING=y
# Non-8250 serial port support
#
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -716,7 +741,6 @@ CONFIG_HIDRAW=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -724,9 +748,9 @@ CONFIG_HID_COMPAT=y
# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
@@ -741,6 +765,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
@@ -767,13 +792,15 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
-# CONFIG_OCFS2_COMPAT_JBD is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_QUOTA_TREE=m
# CONFIG_QFMT_V1 is not set
# CONFIG_QFMT_V2 is not set
CONFIG_QUOTACTL=y
@@ -782,6 +809,11 @@ CONFIG_AUTOFS4_FS=m
CONFIG_FUSE_FS=m
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
@@ -812,10 +844,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
CONFIG_AFFS_FS=m
CONFIG_HFS_FS=m
@@ -824,6 +853,9 @@ CONFIG_HFSPLUS_FS=m
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
# CONFIG_VXFS_FS is not set
CONFIG_MINIX_FS=y
# CONFIG_OMFS_FS is not set
@@ -834,6 +866,7 @@ CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
# CONFIG_UFS_DEBUG is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -850,7 +883,6 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -926,11 +958,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-
-#
-# Tracers
-#
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -951,13 +978,21 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_AUTHENC=m
CONFIG_CRYPTO_TEST=m
@@ -1027,6 +1062,7 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
# Compression
#
CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
#
@@ -1034,11 +1070,13 @@ CONFIG_CRYPTO_LZO=m
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
@@ -1050,10 +1088,13 @@ CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
CONFIG_LZO_COMPRESS=m
CONFIG_LZO_DECOMPRESS=m
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
CONFIG_TEXTSEARCH_FSM=m
-CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig
index 3403ed2eda79..890594fcacb3 100644
--- a/arch/m68k/configs/mvme16x_defconfig
+++ b/arch/m68k/configs/mvme16x_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc7
-# Tue Dec 2 20:27:51 2008
+# Linux kernel version: 2.6.30-rc3
+# Wed Apr 22 20:48:10 2009
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -29,14 +29,24 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
# CONFIG_SYSFS_DEPRECATED_V2 is not set
CONFIG_RELAY=y
CONFIG_NAMESPACES=y
@@ -44,23 +54,27 @@ CONFIG_NAMESPACES=y
# CONFIG_IPC_NS is not set
# CONFIG_USER_NS is not set
# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -68,15 +82,16 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -84,11 +99,8 @@ 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=y
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -104,7 +116,6 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
# CONFIG_FREEZER is not set
#
@@ -143,12 +154,13 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
#
# General setup
@@ -258,6 +270,7 @@ CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
@@ -266,6 +279,7 @@ CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
@@ -276,6 +290,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -354,25 +369,20 @@ CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
CONFIG_IP6_NF_MATCH_MH=m
CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_RAW=m
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=m
-# CONFIG_IP_DCCP_CCID3_DEBUG is not set
-CONFIG_IP_DCCP_CCID3_RTO=100
-CONFIG_IP_DCCP_TFRC_LIB=m
+# CONFIG_IP_DCCP_CCID3 is not set
CONFIG_IP_SCTP=m
# CONFIG_SCTP_DBG_MSG is not set
# CONFIG_SCTP_DBG_OBJCNT is not set
@@ -394,8 +404,10 @@ CONFIG_ATALK=m
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
CONFIG_NET_CLS_ROUTE=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -406,8 +418,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -443,9 +455,13 @@ CONFIG_CDROM_PKTCDVD_BUFFERS=8
CONFIG_ATA_OVER_ETH=m
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -493,10 +509,13 @@ CONFIG_SCSI_SRP_ATTRS=m
CONFIG_SCSI_SRP_TGT_ATTRS=y
CONFIG_SCSI_LOWLEVEL=y
CONFIG_ISCSI_TCP=m
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
CONFIG_53C700_BE_BUS=y
# CONFIG_SCSI_DEBUG is not set
CONFIG_MVME16x_SCSI=y
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_MD_LINEAR=m
@@ -504,7 +523,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
# CONFIG_MD_RAID10 is not set
CONFIG_MD_RAID456=m
-CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_RAID6_PQ=m
# CONFIG_MD_MULTIPATH is not set
# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=m
@@ -517,6 +536,7 @@ CONFIG_DM_MULTIPATH=m
# CONFIG_DM_DELAY is not set
CONFIG_DM_UEVENT=y
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_DUMMY=m
# CONFIG_BONDING is not set
CONFIG_MACVLAN=m
@@ -527,6 +547,8 @@ CONFIG_VETH=m
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
CONFIG_MVME16x_NET=y
+# CONFIG_ETHOC is not set
+# CONFIG_DNET 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
@@ -543,7 +565,10 @@ CONFIG_MVME16x_NET=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
CONFIG_PPP=m
# CONFIG_PPP_MULTILINK is not set
@@ -601,7 +626,6 @@ CONFIG_MOUSE_PS2=m
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
@@ -641,6 +665,7 @@ CONFIG_VT_HW_CONSOLE_BINDING=y
# Non-8250 serial port support
#
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -717,7 +742,6 @@ CONFIG_HIDRAW=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -725,9 +749,9 @@ CONFIG_HID_COMPAT=y
# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
@@ -743,6 +767,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
@@ -769,13 +794,15 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
-# CONFIG_OCFS2_COMPAT_JBD is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_QUOTA_TREE=m
# CONFIG_QFMT_V1 is not set
# CONFIG_QFMT_V2 is not set
CONFIG_QUOTACTL=y
@@ -784,6 +811,11 @@ CONFIG_AUTOFS4_FS=m
CONFIG_FUSE_FS=m
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
@@ -814,10 +846,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
CONFIG_AFFS_FS=m
CONFIG_HFS_FS=m
@@ -826,6 +855,9 @@ CONFIG_HFSPLUS_FS=m
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
# CONFIG_VXFS_FS is not set
CONFIG_MINIX_FS=y
# CONFIG_OMFS_FS is not set
@@ -836,6 +868,7 @@ CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
# CONFIG_UFS_DEBUG is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -852,7 +885,6 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -928,11 +960,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-
-#
-# Tracers
-#
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -953,13 +980,21 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_AUTHENC=m
CONFIG_CRYPTO_TEST=m
@@ -1029,6 +1064,7 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
# Compression
#
CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
#
@@ -1036,11 +1072,13 @@ CONFIG_CRYPTO_LZO=m
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
@@ -1052,10 +1090,13 @@ CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
CONFIG_LZO_COMPRESS=m
CONFIG_LZO_DECOMPRESS=m
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
CONFIG_TEXTSEARCH_FSM=m
-CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig
index 3459c594194b..7cf58c27ff84 100644
--- a/arch/m68k/configs/q40_defconfig
+++ b/arch/m68k/configs/q40_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc7
-# Tue Dec 2 20:27:52 2008
+# Linux kernel version: 2.6.30-rc3
+# Wed Apr 22 20:48:13 2009
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -29,14 +29,24 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
# CONFIG_SYSFS_DEPRECATED_V2 is not set
CONFIG_RELAY=y
CONFIG_NAMESPACES=y
@@ -44,23 +54,27 @@ CONFIG_NAMESPACES=y
# CONFIG_IPC_NS is not set
# CONFIG_USER_NS is not set
# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -68,15 +82,16 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -84,11 +99,8 @@ 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=y
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -104,7 +116,6 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
# CONFIG_FREEZER is not set
#
@@ -140,12 +151,13 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
#
# General setup
@@ -255,6 +267,7 @@ CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
@@ -263,6 +276,7 @@ CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
@@ -273,6 +287,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -351,25 +366,20 @@ CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
CONFIG_IP6_NF_MATCH_MH=m
CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_RAW=m
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=m
-# CONFIG_IP_DCCP_CCID3_DEBUG is not set
-CONFIG_IP_DCCP_CCID3_RTO=100
-CONFIG_IP_DCCP_TFRC_LIB=m
+# CONFIG_IP_DCCP_CCID3 is not set
CONFIG_IP_SCTP=m
# CONFIG_SCTP_DBG_MSG is not set
# CONFIG_SCTP_DBG_OBJCNT is not set
@@ -391,8 +401,10 @@ CONFIG_ATALK=m
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
CONFIG_NET_CLS_ROUTE=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -403,8 +415,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -441,15 +453,20 @@ CONFIG_CDROM_PKTCDVD_BUFFERS=8
CONFIG_ATA_OVER_ETH=m
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
#
# Please see Documentation/ide/ide.txt for help/info on IDE drives
#
+CONFIG_IDE_ATAPI=y
# CONFIG_BLK_DEV_IDE_SATA is not set
CONFIG_IDE_GD=y
CONFIG_IDE_GD_ATA=y
@@ -457,7 +474,6 @@ CONFIG_IDE_GD_ATA=y
CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -516,6 +532,8 @@ CONFIG_ISCSI_TCP=m
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_IN2000 is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DTC3280 is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GENERIC_NCR5380 is not set
@@ -527,6 +545,7 @@ CONFIG_ISCSI_TCP=m
# CONFIG_SCSI_T128 is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_MD_LINEAR=m
@@ -534,7 +553,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
# CONFIG_MD_RAID10 is not set
CONFIG_MD_RAID456=m
-CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_RAID6_PQ=m
# CONFIG_MD_MULTIPATH is not set
# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=m
@@ -547,6 +566,7 @@ CONFIG_DM_MULTIPATH=m
# CONFIG_DM_DELAY is not set
CONFIG_DM_UEVENT=y
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_DUMMY=m
# CONFIG_BONDING is not set
CONFIG_MACVLAN=m
@@ -559,7 +579,9 @@ CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_ETHOC is not set
# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_DNET is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
# CONFIG_HP100 is not set
@@ -584,7 +606,10 @@ CONFIG_NE2000=m
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
CONFIG_PPP=m
# CONFIG_PPP_MULTILINK is not set
@@ -642,7 +667,6 @@ CONFIG_MOUSE_PS2=m
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
@@ -688,6 +712,7 @@ CONFIG_VT_HW_CONSOLE_BINDING=y
# Non-8250 serial port support
#
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -771,6 +796,7 @@ CONFIG_FB_Q40=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -805,7 +831,6 @@ CONFIG_HIDRAW=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -813,9 +838,9 @@ CONFIG_HID_COMPAT=y
# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
@@ -828,6 +853,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
@@ -854,13 +880,15 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
-# CONFIG_OCFS2_COMPAT_JBD is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_QUOTA_TREE=m
# CONFIG_QFMT_V1 is not set
# CONFIG_QFMT_V2 is not set
CONFIG_QUOTACTL=y
@@ -869,6 +897,11 @@ CONFIG_AUTOFS4_FS=m
CONFIG_FUSE_FS=m
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
@@ -899,10 +932,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
CONFIG_AFFS_FS=m
CONFIG_HFS_FS=m
@@ -911,6 +941,9 @@ CONFIG_HFSPLUS_FS=m
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
# CONFIG_VXFS_FS is not set
CONFIG_MINIX_FS=y
# CONFIG_OMFS_FS is not set
@@ -921,6 +954,7 @@ CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
# CONFIG_UFS_DEBUG is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -936,7 +970,6 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -1011,11 +1044,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-
-#
-# Tracers
-#
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -1036,13 +1064,21 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_AUTHENC=m
CONFIG_CRYPTO_TEST=m
@@ -1112,6 +1148,7 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
# Compression
#
CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
#
@@ -1119,11 +1156,13 @@ CONFIG_CRYPTO_LZO=m
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
@@ -1135,10 +1174,13 @@ CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
CONFIG_LZO_COMPRESS=m
CONFIG_LZO_DECOMPRESS=m
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
CONFIG_TEXTSEARCH_FSM=m
-CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig
index f404917429fa..f27c1a47bacf 100644
--- a/arch/m68k/configs/sun3_defconfig
+++ b/arch/m68k/configs/sun3_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc7
-# Tue Dec 2 20:27:53 2008
+# Linux kernel version: 2.6.30-rc3
+# Wed Apr 22 20:48:16 2009
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -29,14 +29,24 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
# CONFIG_SYSFS_DEPRECATED_V2 is not set
CONFIG_RELAY=y
CONFIG_NAMESPACES=y
@@ -44,23 +54,27 @@ CONFIG_NAMESPACES=y
# CONFIG_IPC_NS is not set
# CONFIG_USER_NS is not set
# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -68,15 +82,16 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -84,11 +99,8 @@ 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=y
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -104,7 +116,6 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
# CONFIG_FREEZER is not set
#
@@ -138,12 +149,13 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
#
# General setup
@@ -253,6 +265,7 @@ CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
@@ -261,6 +274,7 @@ CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
@@ -271,6 +285,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -349,25 +364,20 @@ CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
CONFIG_IP6_NF_MATCH_MH=m
CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_RAW=m
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=m
-# CONFIG_IP_DCCP_CCID3_DEBUG is not set
-CONFIG_IP_DCCP_CCID3_RTO=100
-CONFIG_IP_DCCP_TFRC_LIB=m
+# CONFIG_IP_DCCP_CCID3 is not set
CONFIG_IP_SCTP=m
# CONFIG_SCTP_DBG_MSG is not set
# CONFIG_SCTP_DBG_OBJCNT is not set
@@ -389,8 +399,10 @@ CONFIG_ATALK=m
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
CONFIG_NET_CLS_ROUTE=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -401,8 +413,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -438,9 +450,13 @@ CONFIG_CDROM_PKTCDVD_BUFFERS=8
CONFIG_ATA_OVER_ETH=m
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -488,9 +504,12 @@ CONFIG_SCSI_SRP_ATTRS=m
CONFIG_SCSI_SRP_TGT_ATTRS=y
CONFIG_SCSI_LOWLEVEL=y
CONFIG_ISCSI_TCP=m
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DEBUG is not set
CONFIG_SUN3_SCSI=y
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_MD_LINEAR=m
@@ -498,7 +517,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
# CONFIG_MD_RAID10 is not set
CONFIG_MD_RAID456=m
-CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_RAID6_PQ=m
# CONFIG_MD_MULTIPATH is not set
# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=m
@@ -511,6 +530,7 @@ CONFIG_DM_MULTIPATH=m
# CONFIG_DM_DELAY is not set
CONFIG_DM_UEVENT=y
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_DUMMY=m
# CONFIG_BONDING is not set
CONFIG_MACVLAN=m
@@ -522,6 +542,8 @@ CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
CONFIG_SUN3LANCE=y
CONFIG_SUN3_82586=y
+# CONFIG_ETHOC is not set
+# CONFIG_DNET 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
@@ -537,7 +559,10 @@ CONFIG_SUN3_82586=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
CONFIG_PPP=m
# CONFIG_PPP_MULTILINK is not set
@@ -595,7 +620,6 @@ CONFIG_MOUSE_PS2=m
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
@@ -635,6 +659,7 @@ CONFIG_VT_HW_CONSOLE_BINDING=y
# Non-8250 serial port support
#
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -710,6 +735,7 @@ CONFIG_FB=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -741,16 +767,15 @@ CONFIG_HIDRAW=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
@@ -763,6 +788,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
@@ -789,13 +815,15 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
-# CONFIG_OCFS2_COMPAT_JBD is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_QUOTA_TREE=m
# CONFIG_QFMT_V1 is not set
# CONFIG_QFMT_V2 is not set
CONFIG_QUOTACTL=y
@@ -804,6 +832,11 @@ CONFIG_AUTOFS4_FS=m
CONFIG_FUSE_FS=m
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
@@ -834,10 +867,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
CONFIG_AFFS_FS=m
CONFIG_HFS_FS=m
@@ -846,6 +876,9 @@ CONFIG_HFSPLUS_FS=m
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
# CONFIG_VXFS_FS is not set
CONFIG_MINIX_FS=y
# CONFIG_OMFS_FS is not set
@@ -856,6 +889,7 @@ CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
# CONFIG_UFS_DEBUG is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -872,7 +906,6 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -948,11 +981,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-
-#
-# Tracers
-#
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -973,13 +1001,21 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_AUTHENC=m
CONFIG_CRYPTO_TEST=m
@@ -1049,6 +1085,7 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
# Compression
#
CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
#
@@ -1056,11 +1093,13 @@ CONFIG_CRYPTO_LZO=m
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
@@ -1072,9 +1111,12 @@ CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
CONFIG_LZO_COMPRESS=m
CONFIG_LZO_DECOMPRESS=m
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
CONFIG_TEXTSEARCH_FSM=m
-CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
+CONFIG_NLATTR=y
diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig
index 4d8a1e84e39f..c40edb919fda 100644
--- a/arch/m68k/configs/sun3x_defconfig
+++ b/arch/m68k/configs/sun3x_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc7
-# Tue Dec 2 20:27:54 2008
+# Linux kernel version: 2.6.30-rc3
+# Wed Apr 22 20:48:20 2009
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -29,14 +29,24 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
# CONFIG_SYSFS_DEPRECATED_V2 is not set
CONFIG_RELAY=y
CONFIG_NAMESPACES=y
@@ -44,23 +54,27 @@ CONFIG_NAMESPACES=y
# CONFIG_IPC_NS is not set
# CONFIG_USER_NS is not set
# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -68,15 +82,16 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -84,11 +99,8 @@ 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=y
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -104,7 +116,6 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
# CONFIG_FREEZER is not set
#
@@ -140,12 +151,13 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
#
# General setup
@@ -255,6 +267,7 @@ CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
@@ -263,6 +276,7 @@ CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
@@ -273,6 +287,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -351,25 +366,20 @@ CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
CONFIG_IP6_NF_MATCH_MH=m
CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_RAW=m
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=m
-# CONFIG_IP_DCCP_CCID3_DEBUG is not set
-CONFIG_IP_DCCP_CCID3_RTO=100
-CONFIG_IP_DCCP_TFRC_LIB=m
+# CONFIG_IP_DCCP_CCID3 is not set
CONFIG_IP_SCTP=m
# CONFIG_SCTP_DBG_MSG is not set
# CONFIG_SCTP_DBG_OBJCNT is not set
@@ -391,8 +401,10 @@ CONFIG_ATALK=m
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
CONFIG_NET_CLS_ROUTE=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -403,8 +415,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -440,9 +452,13 @@ CONFIG_CDROM_PKTCDVD_BUFFERS=8
CONFIG_ATA_OVER_ETH=m
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -490,9 +506,12 @@ CONFIG_SCSI_SRP_ATTRS=m
CONFIG_SCSI_SRP_TGT_ATTRS=y
CONFIG_SCSI_LOWLEVEL=y
CONFIG_ISCSI_TCP=m
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DEBUG is not set
CONFIG_SUN3X_ESP=y
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_MD_LINEAR=m
@@ -500,7 +519,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
# CONFIG_MD_RAID10 is not set
CONFIG_MD_RAID456=m
-CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_RAID6_PQ=m
# CONFIG_MD_MULTIPATH is not set
# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=m
@@ -513,6 +532,7 @@ CONFIG_DM_MULTIPATH=m
# CONFIG_DM_DELAY is not set
CONFIG_DM_UEVENT=y
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_DUMMY=m
# CONFIG_BONDING is not set
CONFIG_MACVLAN=m
@@ -523,6 +543,8 @@ CONFIG_VETH=m
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
CONFIG_SUN3LANCE=y
+# CONFIG_ETHOC is not set
+# CONFIG_DNET 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
@@ -539,7 +561,10 @@ CONFIG_SUN3LANCE=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
CONFIG_PPP=m
# CONFIG_PPP_MULTILINK is not set
@@ -597,7 +622,6 @@ CONFIG_MOUSE_PS2=m
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
@@ -637,6 +661,7 @@ CONFIG_VT_HW_CONSOLE_BINDING=y
# Non-8250 serial port support
#
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -718,6 +743,7 @@ CONFIG_FB=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -749,7 +775,6 @@ CONFIG_HIDRAW=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -757,9 +782,9 @@ CONFIG_HID_COMPAT=y
# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
@@ -772,6 +797,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
@@ -798,13 +824,15 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
-# CONFIG_OCFS2_COMPAT_JBD is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_QUOTA_TREE=m
# CONFIG_QFMT_V1 is not set
# CONFIG_QFMT_V2 is not set
CONFIG_QUOTACTL=y
@@ -813,6 +841,11 @@ CONFIG_AUTOFS4_FS=m
CONFIG_FUSE_FS=m
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
@@ -843,10 +876,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
CONFIG_AFFS_FS=m
CONFIG_HFS_FS=m
@@ -855,6 +885,9 @@ CONFIG_HFSPLUS_FS=m
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
# CONFIG_VXFS_FS is not set
CONFIG_MINIX_FS=y
# CONFIG_OMFS_FS is not set
@@ -865,6 +898,7 @@ CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
# CONFIG_UFS_DEBUG is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -881,7 +915,6 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -957,11 +990,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-
-#
-# Tracers
-#
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -982,13 +1010,21 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_AUTHENC=m
CONFIG_CRYPTO_TEST=m
@@ -1058,6 +1094,7 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
# Compression
#
CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
#
@@ -1065,11 +1102,13 @@ CONFIG_CRYPTO_LZO=m
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
@@ -1081,10 +1120,13 @@ CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
CONFIG_LZO_COMPRESS=m
CONFIG_LZO_DECOMPRESS=m
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
CONFIG_TEXTSEARCH_FSM=m
-CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/m68k/include/asm/checksum.h b/arch/m68k/include/asm/checksum.h
index 1cf544767453..87cabc334249 100644
--- a/arch/m68k/include/asm/checksum.h
+++ b/arch/m68k/include/asm/checksum.h
@@ -1,5 +1,159 @@
-#ifdef __uClinux__
-#include "checksum_no.h"
+#ifndef _M68K_CHECKSUM_H
+#define _M68K_CHECKSUM_H
+
+#include <linux/in6.h>
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+__wsum csum_partial(const void *buff, int len, __wsum sum);
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+extern __wsum csum_partial_copy_from_user(const void __user *src,
+ void *dst,
+ int len, __wsum sum,
+ int *csum_err);
+
+extern __wsum csum_partial_copy_nocheck(const void *src,
+ void *dst, int len,
+ __wsum sum);
+
+
+#ifdef CONFIG_MMU
+/*
+ * This is a version of ip_compute_csum() optimized for IP headers,
+ * which always checksum on 4 octet boundaries.
+ *
+ */
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+ unsigned int sum = 0;
+ unsigned long tmp;
+
+ __asm__ ("subqw #1,%2\n"
+ "1:\t"
+ "movel %1@+,%3\n\t"
+ "addxl %3,%0\n\t"
+ "dbra %2,1b\n\t"
+ "movel %0,%3\n\t"
+ "swap %3\n\t"
+ "addxw %3,%0\n\t"
+ "clrw %3\n\t"
+ "addxw %3,%0\n\t"
+ : "=d" (sum), "=&a" (iph), "=&d" (ihl), "=&d" (tmp)
+ : "0" (sum), "1" (iph), "2" (ihl)
+ : "memory");
+ return (__force __sum16)~sum;
+}
#else
-#include "checksum_mm.h"
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl);
#endif
+
+/*
+ * Fold a partial checksum
+ */
+
+static inline __sum16 csum_fold(__wsum sum)
+{
+ unsigned int tmp = (__force u32)sum;
+#ifdef CONFIG_COLDFIRE
+ tmp = (tmp & 0xffff) + (tmp >> 16);
+ tmp = (tmp & 0xffff) + (tmp >> 16);
+ return (__force __sum16)~tmp;
+#else
+ __asm__("swap %1\n\t"
+ "addw %1, %0\n\t"
+ "clrw %1\n\t"
+ "addxw %1, %0"
+ : "=&d" (sum), "=&d" (tmp)
+ : "0" (sum), "1" (tmp));
+ return (__force __sum16)~sum;
+#endif
+}
+
+
+static inline __wsum
+csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
+ unsigned short proto, __wsum sum)
+{
+ __asm__ ("addl %2,%0\n\t"
+ "addxl %3,%0\n\t"
+ "addxl %4,%0\n\t"
+ "clrl %1\n\t"
+ "addxl %1,%0"
+ : "=&d" (sum), "=d" (saddr)
+ : "g" (daddr), "1" (saddr), "d" (len + proto),
+ "0" (sum));
+ return sum;
+}
+
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline __sum16
+csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
+ unsigned short proto, __wsum sum)
+{
+ return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+
+static inline __sum16 ip_compute_csum(const void *buff, int len)
+{
+ return csum_fold (csum_partial(buff, len, 0));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+static __inline__ __sum16
+csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,
+ __u32 len, unsigned short proto, __wsum sum)
+{
+ register unsigned long tmp;
+ __asm__("addl %2@,%0\n\t"
+ "movel %2@(4),%1\n\t"
+ "addxl %1,%0\n\t"
+ "movel %2@(8),%1\n\t"
+ "addxl %1,%0\n\t"
+ "movel %2@(12),%1\n\t"
+ "addxl %1,%0\n\t"
+ "movel %3@,%1\n\t"
+ "addxl %1,%0\n\t"
+ "movel %3@(4),%1\n\t"
+ "addxl %1,%0\n\t"
+ "movel %3@(8),%1\n\t"
+ "addxl %1,%0\n\t"
+ "movel %3@(12),%1\n\t"
+ "addxl %1,%0\n\t"
+ "addxl %4,%0\n\t"
+ "clrl %1\n\t"
+ "addxl %1,%0"
+ : "=&d" (sum), "=&d" (tmp)
+ : "a" (saddr), "a" (daddr), "d" (len + proto),
+ "0" (sum));
+
+ return csum_fold(sum);
+}
+
+#endif /* _M68K_CHECKSUM_H */
diff --git a/arch/m68k/include/asm/checksum_mm.h b/arch/m68k/include/asm/checksum_mm.h
deleted file mode 100644
index 494f9aec37ea..000000000000
--- a/arch/m68k/include/asm/checksum_mm.h
+++ /dev/null
@@ -1,148 +0,0 @@
-#ifndef _M68K_CHECKSUM_H
-#define _M68K_CHECKSUM_H
-
-#include <linux/in6.h>
-
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-__wsum csum_partial(const void *buff, int len, __wsum sum);
-
-/*
- * the same as csum_partial, but copies from src while it
- * checksums
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
-extern __wsum csum_partial_copy_from_user(const void __user *src,
- void *dst,
- int len, __wsum sum,
- int *csum_err);
-
-extern __wsum csum_partial_copy_nocheck(const void *src,
- void *dst, int len,
- __wsum sum);
-
-/*
- * This is a version of ip_compute_csum() optimized for IP headers,
- * which always checksum on 4 octet boundaries.
- *
- */
-static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
-{
- unsigned int sum = 0;
- unsigned long tmp;
-
- __asm__ ("subqw #1,%2\n"
- "1:\t"
- "movel %1@+,%3\n\t"
- "addxl %3,%0\n\t"
- "dbra %2,1b\n\t"
- "movel %0,%3\n\t"
- "swap %3\n\t"
- "addxw %3,%0\n\t"
- "clrw %3\n\t"
- "addxw %3,%0\n\t"
- : "=d" (sum), "=&a" (iph), "=&d" (ihl), "=&d" (tmp)
- : "0" (sum), "1" (iph), "2" (ihl)
- : "memory");
- return (__force __sum16)~sum;
-}
-
-/*
- * Fold a partial checksum
- */
-
-static inline __sum16 csum_fold(__wsum sum)
-{
- unsigned int tmp = (__force u32)sum;
- __asm__("swap %1\n\t"
- "addw %1, %0\n\t"
- "clrw %1\n\t"
- "addxw %1, %0"
- : "=&d" (sum), "=&d" (tmp)
- : "0" (sum), "1" (tmp));
- return (__force __sum16)~sum;
-}
-
-
-static inline __wsum
-csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
- unsigned short proto, __wsum sum)
-{
- __asm__ ("addl %2,%0\n\t"
- "addxl %3,%0\n\t"
- "addxl %4,%0\n\t"
- "clrl %1\n\t"
- "addxl %1,%0"
- : "=&d" (sum), "=d" (saddr)
- : "g" (daddr), "1" (saddr), "d" (len + proto),
- "0" (sum));
- return sum;
-}
-
-
-/*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
- */
-static inline __sum16
-csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
- unsigned short proto, __wsum sum)
-{
- return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
-}
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-
-static inline __sum16 ip_compute_csum(const void *buff, int len)
-{
- return csum_fold (csum_partial(buff, len, 0));
-}
-
-#define _HAVE_ARCH_IPV6_CSUM
-static __inline__ __sum16
-csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,
- __u32 len, unsigned short proto, __wsum sum)
-{
- register unsigned long tmp;
- __asm__("addl %2@,%0\n\t"
- "movel %2@(4),%1\n\t"
- "addxl %1,%0\n\t"
- "movel %2@(8),%1\n\t"
- "addxl %1,%0\n\t"
- "movel %2@(12),%1\n\t"
- "addxl %1,%0\n\t"
- "movel %3@,%1\n\t"
- "addxl %1,%0\n\t"
- "movel %3@(4),%1\n\t"
- "addxl %1,%0\n\t"
- "movel %3@(8),%1\n\t"
- "addxl %1,%0\n\t"
- "movel %3@(12),%1\n\t"
- "addxl %1,%0\n\t"
- "addxl %4,%0\n\t"
- "clrl %1\n\t"
- "addxl %1,%0"
- : "=&d" (sum), "=&d" (tmp)
- : "a" (saddr), "a" (daddr), "d" (len + proto),
- "0" (sum));
-
- return csum_fold(sum);
-}
-
-#endif /* _M68K_CHECKSUM_H */
diff --git a/arch/m68k/include/asm/checksum_no.h b/arch/m68k/include/asm/checksum_no.h
deleted file mode 100644
index 81883482ffb1..000000000000
--- a/arch/m68k/include/asm/checksum_no.h
+++ /dev/null
@@ -1,132 +0,0 @@
-#ifndef _M68K_CHECKSUM_H
-#define _M68K_CHECKSUM_H
-
-#include <linux/in6.h>
-
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-__wsum csum_partial(const void *buff, int len, __wsum sum);
-
-/*
- * the same as csum_partial, but copies from src while it
- * checksums
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
-__wsum csum_partial_copy_nocheck(const void *src, void *dst,
- int len, __wsum sum);
-
-
-/*
- * the same as csum_partial_copy, but copies from user space.
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
-extern __wsum csum_partial_copy_from_user(const void __user *src,
- void *dst, int len, __wsum sum, int *csum_err);
-
-__sum16 ip_fast_csum(const void *iph, unsigned int ihl);
-
-/*
- * Fold a partial checksum
- */
-
-static inline __sum16 csum_fold(__wsum sum)
-{
- unsigned int tmp = (__force u32)sum;
-#ifdef CONFIG_COLDFIRE
- tmp = (tmp & 0xffff) + (tmp >> 16);
- tmp = (tmp & 0xffff) + (tmp >> 16);
- return (__force __sum16)~tmp;
-#else
- __asm__("swap %1\n\t"
- "addw %1, %0\n\t"
- "clrw %1\n\t"
- "addxw %1, %0"
- : "=&d" (sum), "=&d" (tmp)
- : "0" (sum), "1" (sum));
- return (__force __sum16)~sum;
-#endif
-}
-
-
-/*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
- */
-
-static inline __wsum
-csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
- unsigned short proto, __wsum sum)
-{
- __asm__ ("addl %1,%0\n\t"
- "addxl %4,%0\n\t"
- "addxl %5,%0\n\t"
- "clrl %1\n\t"
- "addxl %1,%0"
- : "=&d" (sum), "=&d" (saddr)
- : "0" (daddr), "1" (saddr), "d" (len + proto),
- "d"(sum));
- return sum;
-}
-
-static inline __sum16
-csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
- unsigned short proto, __wsum sum)
-{
- return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
-}
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-
-extern __sum16 ip_compute_csum(const void *buff, int len);
-
-#define _HAVE_ARCH_IPV6_CSUM
-static __inline__ __sum16
-csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,
- __u32 len, unsigned short proto, __wsum sum)
-{
- register unsigned long tmp;
- __asm__("addl %2@,%0\n\t"
- "movel %2@(4),%1\n\t"
- "addxl %1,%0\n\t"
- "movel %2@(8),%1\n\t"
- "addxl %1,%0\n\t"
- "movel %2@(12),%1\n\t"
- "addxl %1,%0\n\t"
- "movel %3@,%1\n\t"
- "addxl %1,%0\n\t"
- "movel %3@(4),%1\n\t"
- "addxl %1,%0\n\t"
- "movel %3@(8),%1\n\t"
- "addxl %1,%0\n\t"
- "movel %3@(12),%1\n\t"
- "addxl %1,%0\n\t"
- "addxl %4,%0\n\t"
- "clrl %1\n\t"
- "addxl %1,%0"
- : "=&d" (sum), "=&d" (tmp)
- : "a" (saddr), "a" (daddr), "d" (len + proto),
- "0" (sum));
-
- return csum_fold(sum);
-}
-
-#endif /* _M68K_CHECKSUM_H */
diff --git a/arch/m68k/include/asm/dma.h b/arch/m68k/include/asm/dma.h
index b82e660cf1c2..1f1fcdf5e49e 100644
--- a/arch/m68k/include/asm/dma.h
+++ b/arch/m68k/include/asm/dma.h
@@ -1,5 +1,492 @@
-#ifdef __uClinux__
-#include "dma_no.h"
+#ifndef _M68K_DMA_H
+#define _M68K_DMA_H 1
+
+#ifdef CONFIG_COLDFIRE
+/*
+ * ColdFire DMA Model:
+ * ColdFire DMA supports two forms of DMA: Single and Dual address. Single
+ * address mode emits a source address, and expects that the device will either
+ * pick up the data (DMA READ) or source data (DMA WRITE). This implies that
+ * the device will place data on the correct byte(s) of the data bus, as the
+ * memory transactions are always 32 bits. This implies that only 32 bit
+ * devices will find single mode transfers useful. Dual address DMA mode
+ * performs two cycles: source read and destination write. ColdFire will
+ * align the data so that the device will always get the correct bytes, thus
+ * is useful for 8 and 16 bit devices. This is the mode that is supported
+ * below.
+ *
+ * AUG/22/2000 : added support for 32-bit Dual-Address-Mode (K) 2000
+ * Oliver Kamphenkel (O.Kamphenkel@tu-bs.de)
+ *
+ * AUG/25/2000 : addad support for 8, 16 and 32-bit Single-Address-Mode (K)2000
+ * Oliver Kamphenkel (O.Kamphenkel@tu-bs.de)
+ *
+ * APR/18/2002 : added proper support for MCF5272 DMA controller.
+ * Arthur Shipkowski (art@videon-central.com)
+ */
+
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfdma.h>
+
+/*
+ * Set number of channels of DMA on ColdFire for different implementations.
+ */
+#if defined(CONFIG_M5249) || defined(CONFIG_M5307) || defined(CONFIG_M5407) || \
+ defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#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
-#include "dma_mm.h"
+#define MAX_M68K_DMA_CHANNELS 2
#endif
+
+extern unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS];
+extern unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
+
+#if !defined(CONFIG_M5272)
+#define DMA_MODE_WRITE_BIT 0x01 /* Memory/IO to IO/Memory select */
+#define DMA_MODE_WORD_BIT 0x02 /* 8 or 16 bit transfers */
+#define DMA_MODE_LONG_BIT 0x04 /* or 32 bit transfers */
+#define DMA_MODE_SINGLE_BIT 0x08 /* single-address-mode */
+
+/* I/O to memory, 8 bits, mode */
+#define DMA_MODE_READ 0
+/* memory to I/O, 8 bits, mode */
+#define DMA_MODE_WRITE 1
+/* I/O to memory, 16 bits, mode */
+#define DMA_MODE_READ_WORD 2
+/* memory to I/O, 16 bits, mode */
+#define DMA_MODE_WRITE_WORD 3
+/* I/O to memory, 32 bits, mode */
+#define DMA_MODE_READ_LONG 4
+/* memory to I/O, 32 bits, mode */
+#define DMA_MODE_WRITE_LONG 5
+/* I/O to memory, 8 bits, single-address-mode */
+#define DMA_MODE_READ_SINGLE 8
+/* memory to I/O, 8 bits, single-address-mode */
+#define DMA_MODE_WRITE_SINGLE 9
+/* I/O to memory, 16 bits, single-address-mode */
+#define DMA_MODE_READ_WORD_SINGLE 10
+/* memory to I/O, 16 bits, single-address-mode */
+#define DMA_MODE_WRITE_WORD_SINGLE 11
+/* I/O to memory, 32 bits, single-address-mode */
+#define DMA_MODE_READ_LONG_SINGLE 12
+/* memory to I/O, 32 bits, single-address-mode */
+#define DMA_MODE_WRITE_LONG_SINGLE 13
+
+#else /* CONFIG_M5272 is defined */
+
+/* Source static-address mode */
+#define DMA_MODE_SRC_SA_BIT 0x01
+/* Two bits to select between all four modes */
+#define DMA_MODE_SSIZE_MASK 0x06
+/* Offset to shift bits in */
+#define DMA_MODE_SSIZE_OFF 0x01
+/* Destination static-address mode */
+#define DMA_MODE_DES_SA_BIT 0x10
+/* Two bits to select between all four modes */
+#define DMA_MODE_DSIZE_MASK 0x60
+/* Offset to shift bits in */
+#define DMA_MODE_DSIZE_OFF 0x05
+/* Size modifiers */
+#define DMA_MODE_SIZE_LONG 0x00
+#define DMA_MODE_SIZE_BYTE 0x01
+#define DMA_MODE_SIZE_WORD 0x02
+#define DMA_MODE_SIZE_LINE 0x03
+
+/*
+ * Aliases to help speed quick ports; these may be suboptimal, however. They
+ * do not include the SINGLE mode modifiers since the MCF5272 does not have a
+ * mode where the device is in control of its addressing.
+ */
+
+/* I/O to memory, 8 bits, mode */
+#define DMA_MODE_READ ((DMA_MODE_SIZE_BYTE << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_BYTE << DMA_MODE_SSIZE_OFF) | DMA_SRC_SA_BIT)
+/* memory to I/O, 8 bits, mode */
+#define DMA_MODE_WRITE ((DMA_MODE_SIZE_BYTE << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_BYTE << DMA_MODE_SSIZE_OFF) | DMA_DES_SA_BIT)
+/* I/O to memory, 16 bits, mode */
+#define DMA_MODE_READ_WORD ((DMA_MODE_SIZE_WORD << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_WORD << DMA_MODE_SSIZE_OFF) | DMA_SRC_SA_BIT)
+/* memory to I/O, 16 bits, mode */
+#define DMA_MODE_WRITE_WORD ((DMA_MODE_SIZE_WORD << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_WORD << DMA_MODE_SSIZE_OFF) | DMA_DES_SA_BIT)
+/* I/O to memory, 32 bits, mode */
+#define DMA_MODE_READ_LONG ((DMA_MODE_SIZE_LONG << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_LONG << DMA_MODE_SSIZE_OFF) | DMA_SRC_SA_BIT)
+/* memory to I/O, 32 bits, mode */
+#define DMA_MODE_WRITE_LONG ((DMA_MODE_SIZE_LONG << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_LONG << DMA_MODE_SSIZE_OFF) | DMA_DES_SA_BIT)
+
+#endif /* !defined(CONFIG_M5272) */
+
+#if !defined(CONFIG_M5272)
+/* enable/disable a specific DMA channel */
+static __inline__ void enable_dma(unsigned int dmanr)
+{
+ volatile unsigned short *dmawp;
+
+#ifdef DMA_DEBUG
+ printk("enable_dma(dmanr=%d)\n", dmanr);
+#endif
+
+ dmawp = (unsigned short *) dma_base_addr[dmanr];
+ dmawp[MCFDMA_DCR] |= MCFDMA_DCR_EEXT;
+}
+
+static __inline__ void disable_dma(unsigned int dmanr)
+{
+ volatile unsigned short *dmawp;
+ volatile unsigned char *dmapb;
+
+#ifdef DMA_DEBUG
+ printk("disable_dma(dmanr=%d)\n", dmanr);
+#endif
+
+ dmawp = (unsigned short *) dma_base_addr[dmanr];
+ dmapb = (unsigned char *) dma_base_addr[dmanr];
+
+ /* Turn off external requests, and stop any DMA in progress */
+ dmawp[MCFDMA_DCR] &= ~MCFDMA_DCR_EEXT;
+ dmapb[MCFDMA_DSR] = MCFDMA_DSR_DONE;
+}
+
+/*
+ * Clear the 'DMA Pointer Flip Flop'.
+ * Write 0 for LSB/MSB, 1 for MSB/LSB access.
+ * Use this once to initialize the FF to a known state.
+ * After that, keep track of it. :-)
+ * --- In order to do that, the DMA routines below should ---
+ * --- only be used while interrupts are disabled! ---
+ *
+ * This is a NOP for ColdFire. Provide a stub for compatibility.
+ */
+static __inline__ void clear_dma_ff(unsigned int dmanr)
+{
+}
+
+/* set mode (above) for a specific DMA channel */
+static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
+{
+
+ volatile unsigned char *dmabp;
+ volatile unsigned short *dmawp;
+
+#ifdef DMA_DEBUG
+ printk("set_dma_mode(dmanr=%d,mode=%d)\n", dmanr, mode);
+#endif
+
+ dmabp = (unsigned char *) dma_base_addr[dmanr];
+ dmawp = (unsigned short *) dma_base_addr[dmanr];
+
+ // Clear config errors
+ dmabp[MCFDMA_DSR] = MCFDMA_DSR_DONE;
+
+ // Set command register
+ dmawp[MCFDMA_DCR] =
+ MCFDMA_DCR_INT | // Enable completion irq
+ MCFDMA_DCR_CS | // Force one xfer per request
+ MCFDMA_DCR_AA | // Enable auto alignment
+ // single-address-mode
+ ((mode & DMA_MODE_SINGLE_BIT) ? MCFDMA_DCR_SAA : 0) |
+ // sets s_rw (-> r/w) high if Memory to I/0
+ ((mode & DMA_MODE_WRITE_BIT) ? MCFDMA_DCR_S_RW : 0) |
+ // Memory to I/O or I/O to Memory
+ ((mode & DMA_MODE_WRITE_BIT) ? MCFDMA_DCR_SINC : MCFDMA_DCR_DINC) |
+ // 32 bit, 16 bit or 8 bit transfers
+ ((mode & DMA_MODE_WORD_BIT) ? MCFDMA_DCR_SSIZE_WORD :
+ ((mode & DMA_MODE_LONG_BIT) ? MCFDMA_DCR_SSIZE_LONG :
+ MCFDMA_DCR_SSIZE_BYTE)) |
+ ((mode & DMA_MODE_WORD_BIT) ? MCFDMA_DCR_DSIZE_WORD :
+ ((mode & DMA_MODE_LONG_BIT) ? MCFDMA_DCR_DSIZE_LONG :
+ MCFDMA_DCR_DSIZE_BYTE));
+
+#ifdef DEBUG_DMA
+ printk("%s(%d): dmanr=%d DSR[%x]=%x DCR[%x]=%x\n", __FILE__, __LINE__,
+ dmanr, (int) &dmabp[MCFDMA_DSR], dmabp[MCFDMA_DSR],
+ (int) &dmawp[MCFDMA_DCR], dmawp[MCFDMA_DCR]);
+#endif
+}
+
+/* Set transfer address for specific DMA channel */
+static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
+{
+ volatile unsigned short *dmawp;
+ volatile unsigned int *dmalp;
+
+#ifdef DMA_DEBUG
+ printk("set_dma_addr(dmanr=%d,a=%x)\n", dmanr, a);
+#endif
+
+ dmawp = (unsigned short *) dma_base_addr[dmanr];
+ dmalp = (unsigned int *) dma_base_addr[dmanr];
+
+ // Determine which address registers are used for memory/device accesses
+ if (dmawp[MCFDMA_DCR] & MCFDMA_DCR_SINC) {
+ // Source incrementing, must be memory
+ dmalp[MCFDMA_SAR] = a;
+ // Set dest address, must be device
+ dmalp[MCFDMA_DAR] = dma_device_address[dmanr];
+ } else {
+ // Destination incrementing, must be memory
+ dmalp[MCFDMA_DAR] = a;
+ // Set source address, must be device
+ dmalp[MCFDMA_SAR] = dma_device_address[dmanr];
+ }
+
+#ifdef DEBUG_DMA
+ printk("%s(%d): dmanr=%d DCR[%x]=%x SAR[%x]=%08x DAR[%x]=%08x\n",
+ __FILE__, __LINE__, dmanr, (int) &dmawp[MCFDMA_DCR], dmawp[MCFDMA_DCR],
+ (int) &dmalp[MCFDMA_SAR], dmalp[MCFDMA_SAR],
+ (int) &dmalp[MCFDMA_DAR], dmalp[MCFDMA_DAR]);
+#endif
+}
+
+/*
+ * Specific for Coldfire - sets device address.
+ * Should be called after the mode set call, and before set DMA address.
+ */
+static __inline__ void set_dma_device_addr(unsigned int dmanr, unsigned int a)
+{
+#ifdef DMA_DEBUG
+ printk("set_dma_device_addr(dmanr=%d,a=%x)\n", dmanr, a);
+#endif
+
+ dma_device_address[dmanr] = a;
+}
+
+/*
+ * NOTE 2: "count" represents _bytes_.
+ */
+static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
+{
+ volatile unsigned short *dmawp;
+
+#ifdef DMA_DEBUG
+ printk("set_dma_count(dmanr=%d,count=%d)\n", dmanr, count);
+#endif
+
+ dmawp = (unsigned short *) dma_base_addr[dmanr];
+ dmawp[MCFDMA_BCR] = (unsigned short)count;
+}
+
+/*
+ * Get DMA residue count. After a DMA transfer, this
+ * should return zero. Reading this while a DMA transfer is
+ * still in progress will return unpredictable results.
+ * Otherwise, it returns the number of _bytes_ left to transfer.
+ */
+static __inline__ int get_dma_residue(unsigned int dmanr)
+{
+ volatile unsigned short *dmawp;
+ unsigned short count;
+
+#ifdef DMA_DEBUG
+ printk("get_dma_residue(dmanr=%d)\n", dmanr);
+#endif
+
+ dmawp = (unsigned short *) dma_base_addr[dmanr];
+ count = dmawp[MCFDMA_BCR];
+ return((int) count);
+}
+#else /* CONFIG_M5272 is defined */
+
+/*
+ * The MCF5272 DMA controller is very different than the controller defined above
+ * in terms of register mapping. For instance, with the exception of the 16-bit
+ * interrupt register (IRQ#85, for reference), all of the registers are 32-bit.
+ *
+ * The big difference, however, is the lack of device-requested DMA. All modes
+ * are dual address transfer, and there is no 'device' setup or direction bit.
+ * You can DMA between a device and memory, between memory and memory, or even between
+ * two devices directly, with any combination of incrementing and non-incrementing
+ * addresses you choose. This puts a crimp in distinguishing between the 'device
+ * address' set up by set_dma_device_addr.
+ *
+ * Therefore, there are two options. One is to use set_dma_addr and set_dma_device_addr,
+ * which will act exactly as above in -- it will look to see if the source is set to
+ * autoincrement, and if so it will make the source use the set_dma_addr value and the
+ * destination the set_dma_device_addr value. Otherwise the source will be set to the
+ * set_dma_device_addr value and the destination will get the set_dma_addr value.
+ *
+ * The other is to use the provided set_dma_src_addr and set_dma_dest_addr functions
+ * and make it explicit. Depending on what you're doing, one of these two should work
+ * for you, but don't mix them in the same transfer setup.
+ */
+
+/* enable/disable a specific DMA channel */
+static __inline__ void enable_dma(unsigned int dmanr)
+{
+ volatile unsigned int *dmalp;
+
+#ifdef DMA_DEBUG
+ printk("enable_dma(dmanr=%d)\n", dmanr);
+#endif
+
+ dmalp = (unsigned int *) dma_base_addr[dmanr];
+ dmalp[MCFDMA_DMR] |= MCFDMA_DMR_EN;
+}
+
+static __inline__ void disable_dma(unsigned int dmanr)
+{
+ volatile unsigned int *dmalp;
+
+#ifdef DMA_DEBUG
+ printk("disable_dma(dmanr=%d)\n", dmanr);
+#endif
+
+ dmalp = (unsigned int *) dma_base_addr[dmanr];
+
+ /* Turn off external requests, and stop any DMA in progress */
+ dmalp[MCFDMA_DMR] &= ~MCFDMA_DMR_EN;
+ dmalp[MCFDMA_DMR] |= MCFDMA_DMR_RESET;
+}
+
+/*
+ * Clear the 'DMA Pointer Flip Flop'.
+ * Write 0 for LSB/MSB, 1 for MSB/LSB access.
+ * Use this once to initialize the FF to a known state.
+ * After that, keep track of it. :-)
+ * --- In order to do that, the DMA routines below should ---
+ * --- only be used while interrupts are disabled! ---
+ *
+ * This is a NOP for ColdFire. Provide a stub for compatibility.
+ */
+static __inline__ void clear_dma_ff(unsigned int dmanr)
+{
+}
+
+/* set mode (above) for a specific DMA channel */
+static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
+{
+
+ volatile unsigned int *dmalp;
+ volatile unsigned short *dmawp;
+
+#ifdef DMA_DEBUG
+ printk("set_dma_mode(dmanr=%d,mode=%d)\n", dmanr, mode);
+#endif
+ dmalp = (unsigned int *) dma_base_addr[dmanr];
+ dmawp = (unsigned short *) dma_base_addr[dmanr];
+
+ // Clear config errors
+ dmalp[MCFDMA_DMR] |= MCFDMA_DMR_RESET;
+
+ // Set command register
+ dmalp[MCFDMA_DMR] =
+ MCFDMA_DMR_RQM_DUAL | // Mandatory Request Mode setting
+ MCFDMA_DMR_DSTT_SD | // Set up addressing types; set to supervisor-data.
+ MCFDMA_DMR_SRCT_SD | // Set up addressing types; set to supervisor-data.
+ // source static-address-mode
+ ((mode & DMA_MODE_SRC_SA_BIT) ? MCFDMA_DMR_SRCM_SA : MCFDMA_DMR_SRCM_IA) |
+ // dest static-address-mode
+ ((mode & DMA_MODE_DES_SA_BIT) ? MCFDMA_DMR_DSTM_SA : MCFDMA_DMR_DSTM_IA) |
+ // burst, 32 bit, 16 bit or 8 bit transfers are separately configurable on the MCF5272
+ (((mode & DMA_MODE_SSIZE_MASK) >> DMA_MODE_SSIZE_OFF) << MCFDMA_DMR_DSTS_OFF) |
+ (((mode & DMA_MODE_SSIZE_MASK) >> DMA_MODE_SSIZE_OFF) << MCFDMA_DMR_SRCS_OFF);
+
+ dmawp[MCFDMA_DIR] |= MCFDMA_DIR_ASCEN; /* Enable completion interrupts */
+
+#ifdef DEBUG_DMA
+ printk("%s(%d): dmanr=%d DMR[%x]=%x DIR[%x]=%x\n", __FILE__, __LINE__,
+ dmanr, (int) &dmalp[MCFDMA_DMR], dmabp[MCFDMA_DMR],
+ (int) &dmawp[MCFDMA_DIR], dmawp[MCFDMA_DIR]);
+#endif
+}
+
+/* Set transfer address for specific DMA channel */
+static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
+{
+ volatile unsigned int *dmalp;
+
+#ifdef DMA_DEBUG
+ printk("set_dma_addr(dmanr=%d,a=%x)\n", dmanr, a);
+#endif
+
+ dmalp = (unsigned int *) dma_base_addr[dmanr];
+
+ // Determine which address registers are used for memory/device accesses
+ if (dmalp[MCFDMA_DMR] & MCFDMA_DMR_SRCM) {
+ // Source incrementing, must be memory
+ dmalp[MCFDMA_DSAR] = a;
+ // Set dest address, must be device
+ dmalp[MCFDMA_DDAR] = dma_device_address[dmanr];
+ } else {
+ // Destination incrementing, must be memory
+ dmalp[MCFDMA_DDAR] = a;
+ // Set source address, must be device
+ dmalp[MCFDMA_DSAR] = dma_device_address[dmanr];
+ }
+
+#ifdef DEBUG_DMA
+ printk("%s(%d): dmanr=%d DMR[%x]=%x SAR[%x]=%08x DAR[%x]=%08x\n",
+ __FILE__, __LINE__, dmanr, (int) &dmawp[MCFDMA_DMR], dmawp[MCFDMA_DMR],
+ (int) &dmalp[MCFDMA_DSAR], dmalp[MCFDMA_DSAR],
+ (int) &dmalp[MCFDMA_DDAR], dmalp[MCFDMA_DDAR]);
+#endif
+}
+
+/*
+ * Specific for Coldfire - sets device address.
+ * Should be called after the mode set call, and before set DMA address.
+ */
+static __inline__ void set_dma_device_addr(unsigned int dmanr, unsigned int a)
+{
+#ifdef DMA_DEBUG
+ printk("set_dma_device_addr(dmanr=%d,a=%x)\n", dmanr, a);
+#endif
+
+ dma_device_address[dmanr] = a;
+}
+
+/*
+ * NOTE 2: "count" represents _bytes_.
+ *
+ * NOTE 3: While a 32-bit register, "count" is only a maximum 24-bit value.
+ */
+static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
+{
+ volatile unsigned int *dmalp;
+
+#ifdef DMA_DEBUG
+ printk("set_dma_count(dmanr=%d,count=%d)\n", dmanr, count);
+#endif
+
+ dmalp = (unsigned int *) dma_base_addr[dmanr];
+ dmalp[MCFDMA_DBCR] = count;
+}
+
+/*
+ * Get DMA residue count. After a DMA transfer, this
+ * should return zero. Reading this while a DMA transfer is
+ * still in progress will return unpredictable results.
+ * Otherwise, it returns the number of _bytes_ left to transfer.
+ */
+static __inline__ int get_dma_residue(unsigned int dmanr)
+{
+ volatile unsigned int *dmalp;
+ unsigned int count;
+
+#ifdef DMA_DEBUG
+ printk("get_dma_residue(dmanr=%d)\n", dmanr);
+#endif
+
+ dmalp = (unsigned int *) dma_base_addr[dmanr];
+ count = dmalp[MCFDMA_DBCR];
+ return(count);
+}
+
+#endif /* !defined(CONFIG_M5272) */
+#endif /* CONFIG_COLDFIRE */
+
+
+/* it's useless on the m68k, but unfortunately needed by the new
+ bootmem allocator (but this should do it for this) */
+#define MAX_DMA_ADDRESS PAGE_OFFSET
+
+#define MAX_DMA_CHANNELS 8
+
+extern int request_dma(unsigned int dmanr, const char * device_id); /* reserve a DMA channel */
+extern void free_dma(unsigned int dmanr); /* release it again */
+
+#define isa_dma_bridge_buggy (0)
+
+#endif /* _M68K_DMA_H */
diff --git a/arch/m68k/include/asm/dma_mm.h b/arch/m68k/include/asm/dma_mm.h
deleted file mode 100644
index 4240fbc946f8..000000000000
--- a/arch/m68k/include/asm/dma_mm.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _M68K_DMA_H
-#define _M68K_DMA_H 1
-
-
-/* it's useless on the m68k, but unfortunately needed by the new
- bootmem allocator (but this should do it for this) */
-#define MAX_DMA_ADDRESS PAGE_OFFSET
-
-#define MAX_DMA_CHANNELS 8
-
-extern int request_dma(unsigned int dmanr, const char * device_id); /* reserve a DMA channel */
-extern void free_dma(unsigned int dmanr); /* release it again */
-
-#define isa_dma_bridge_buggy (0)
-
-#endif /* _M68K_DMA_H */
diff --git a/arch/m68k/include/asm/dma_no.h b/arch/m68k/include/asm/dma_no.h
deleted file mode 100644
index 939a02056217..000000000000
--- a/arch/m68k/include/asm/dma_no.h
+++ /dev/null
@@ -1,494 +0,0 @@
-#ifndef _M68K_DMA_H
-#define _M68K_DMA_H 1
-
-//#define DMA_DEBUG 1
-
-
-#ifdef CONFIG_COLDFIRE
-/*
- * ColdFire DMA Model:
- * ColdFire DMA supports two forms of DMA: Single and Dual address. Single
- * address mode emits a source address, and expects that the device will either
- * pick up the data (DMA READ) or source data (DMA WRITE). This implies that
- * the device will place data on the correct byte(s) of the data bus, as the
- * memory transactions are always 32 bits. This implies that only 32 bit
- * devices will find single mode transfers useful. Dual address DMA mode
- * performs two cycles: source read and destination write. ColdFire will
- * align the data so that the device will always get the correct bytes, thus
- * is useful for 8 and 16 bit devices. This is the mode that is supported
- * below.
- *
- * AUG/22/2000 : added support for 32-bit Dual-Address-Mode (K) 2000
- * Oliver Kamphenkel (O.Kamphenkel@tu-bs.de)
- *
- * AUG/25/2000 : addad support for 8, 16 and 32-bit Single-Address-Mode (K)2000
- * Oliver Kamphenkel (O.Kamphenkel@tu-bs.de)
- *
- * APR/18/2002 : added proper support for MCF5272 DMA controller.
- * Arthur Shipkowski (art@videon-central.com)
- */
-
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfdma.h>
-
-/*
- * Set number of channels of DMA on ColdFire for different implementations.
- */
-#if defined(CONFIG_M5249) || defined(CONFIG_M5307) || defined(CONFIG_M5407) || \
- defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
-#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
-
-extern unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS];
-extern unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
-
-#if !defined(CONFIG_M5272)
-#define DMA_MODE_WRITE_BIT 0x01 /* Memory/IO to IO/Memory select */
-#define DMA_MODE_WORD_BIT 0x02 /* 8 or 16 bit transfers */
-#define DMA_MODE_LONG_BIT 0x04 /* or 32 bit transfers */
-#define DMA_MODE_SINGLE_BIT 0x08 /* single-address-mode */
-
-/* I/O to memory, 8 bits, mode */
-#define DMA_MODE_READ 0
-/* memory to I/O, 8 bits, mode */
-#define DMA_MODE_WRITE 1
-/* I/O to memory, 16 bits, mode */
-#define DMA_MODE_READ_WORD 2
-/* memory to I/O, 16 bits, mode */
-#define DMA_MODE_WRITE_WORD 3
-/* I/O to memory, 32 bits, mode */
-#define DMA_MODE_READ_LONG 4
-/* memory to I/O, 32 bits, mode */
-#define DMA_MODE_WRITE_LONG 5
-/* I/O to memory, 8 bits, single-address-mode */
-#define DMA_MODE_READ_SINGLE 8
-/* memory to I/O, 8 bits, single-address-mode */
-#define DMA_MODE_WRITE_SINGLE 9
-/* I/O to memory, 16 bits, single-address-mode */
-#define DMA_MODE_READ_WORD_SINGLE 10
-/* memory to I/O, 16 bits, single-address-mode */
-#define DMA_MODE_WRITE_WORD_SINGLE 11
-/* I/O to memory, 32 bits, single-address-mode */
-#define DMA_MODE_READ_LONG_SINGLE 12
-/* memory to I/O, 32 bits, single-address-mode */
-#define DMA_MODE_WRITE_LONG_SINGLE 13
-
-#else /* CONFIG_M5272 is defined */
-
-/* Source static-address mode */
-#define DMA_MODE_SRC_SA_BIT 0x01
-/* Two bits to select between all four modes */
-#define DMA_MODE_SSIZE_MASK 0x06
-/* Offset to shift bits in */
-#define DMA_MODE_SSIZE_OFF 0x01
-/* Destination static-address mode */
-#define DMA_MODE_DES_SA_BIT 0x10
-/* Two bits to select between all four modes */
-#define DMA_MODE_DSIZE_MASK 0x60
-/* Offset to shift bits in */
-#define DMA_MODE_DSIZE_OFF 0x05
-/* Size modifiers */
-#define DMA_MODE_SIZE_LONG 0x00
-#define DMA_MODE_SIZE_BYTE 0x01
-#define DMA_MODE_SIZE_WORD 0x02
-#define DMA_MODE_SIZE_LINE 0x03
-
-/*
- * Aliases to help speed quick ports; these may be suboptimal, however. They
- * do not include the SINGLE mode modifiers since the MCF5272 does not have a
- * mode where the device is in control of its addressing.
- */
-
-/* I/O to memory, 8 bits, mode */
-#define DMA_MODE_READ ((DMA_MODE_SIZE_BYTE << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_BYTE << DMA_MODE_SSIZE_OFF) | DMA_SRC_SA_BIT)
-/* memory to I/O, 8 bits, mode */
-#define DMA_MODE_WRITE ((DMA_MODE_SIZE_BYTE << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_BYTE << DMA_MODE_SSIZE_OFF) | DMA_DES_SA_BIT)
-/* I/O to memory, 16 bits, mode */
-#define DMA_MODE_READ_WORD ((DMA_MODE_SIZE_WORD << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_WORD << DMA_MODE_SSIZE_OFF) | DMA_SRC_SA_BIT)
-/* memory to I/O, 16 bits, mode */
-#define DMA_MODE_WRITE_WORD ((DMA_MODE_SIZE_WORD << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_WORD << DMA_MODE_SSIZE_OFF) | DMA_DES_SA_BIT)
-/* I/O to memory, 32 bits, mode */
-#define DMA_MODE_READ_LONG ((DMA_MODE_SIZE_LONG << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_LONG << DMA_MODE_SSIZE_OFF) | DMA_SRC_SA_BIT)
-/* memory to I/O, 32 bits, mode */
-#define DMA_MODE_WRITE_LONG ((DMA_MODE_SIZE_LONG << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_LONG << DMA_MODE_SSIZE_OFF) | DMA_DES_SA_BIT)
-
-#endif /* !defined(CONFIG_M5272) */
-
-#if !defined(CONFIG_M5272)
-/* enable/disable a specific DMA channel */
-static __inline__ void enable_dma(unsigned int dmanr)
-{
- volatile unsigned short *dmawp;
-
-#ifdef DMA_DEBUG
- printk("enable_dma(dmanr=%d)\n", dmanr);
-#endif
-
- dmawp = (unsigned short *) dma_base_addr[dmanr];
- dmawp[MCFDMA_DCR] |= MCFDMA_DCR_EEXT;
-}
-
-static __inline__ void disable_dma(unsigned int dmanr)
-{
- volatile unsigned short *dmawp;
- volatile unsigned char *dmapb;
-
-#ifdef DMA_DEBUG
- printk("disable_dma(dmanr=%d)\n", dmanr);
-#endif
-
- dmawp = (unsigned short *) dma_base_addr[dmanr];
- dmapb = (unsigned char *) dma_base_addr[dmanr];
-
- /* Turn off external requests, and stop any DMA in progress */
- dmawp[MCFDMA_DCR] &= ~MCFDMA_DCR_EEXT;
- dmapb[MCFDMA_DSR] = MCFDMA_DSR_DONE;
-}
-
-/*
- * Clear the 'DMA Pointer Flip Flop'.
- * Write 0 for LSB/MSB, 1 for MSB/LSB access.
- * Use this once to initialize the FF to a known state.
- * After that, keep track of it. :-)
- * --- In order to do that, the DMA routines below should ---
- * --- only be used while interrupts are disabled! ---
- *
- * This is a NOP for ColdFire. Provide a stub for compatibility.
- */
-static __inline__ void clear_dma_ff(unsigned int dmanr)
-{
-}
-
-/* set mode (above) for a specific DMA channel */
-static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
-{
-
- volatile unsigned char *dmabp;
- volatile unsigned short *dmawp;
-
-#ifdef DMA_DEBUG
- printk("set_dma_mode(dmanr=%d,mode=%d)\n", dmanr, mode);
-#endif
-
- dmabp = (unsigned char *) dma_base_addr[dmanr];
- dmawp = (unsigned short *) dma_base_addr[dmanr];
-
- // Clear config errors
- dmabp[MCFDMA_DSR] = MCFDMA_DSR_DONE;
-
- // Set command register
- dmawp[MCFDMA_DCR] =
- MCFDMA_DCR_INT | // Enable completion irq
- MCFDMA_DCR_CS | // Force one xfer per request
- MCFDMA_DCR_AA | // Enable auto alignment
- // single-address-mode
- ((mode & DMA_MODE_SINGLE_BIT) ? MCFDMA_DCR_SAA : 0) |
- // sets s_rw (-> r/w) high if Memory to I/0
- ((mode & DMA_MODE_WRITE_BIT) ? MCFDMA_DCR_S_RW : 0) |
- // Memory to I/O or I/O to Memory
- ((mode & DMA_MODE_WRITE_BIT) ? MCFDMA_DCR_SINC : MCFDMA_DCR_DINC) |
- // 32 bit, 16 bit or 8 bit transfers
- ((mode & DMA_MODE_WORD_BIT) ? MCFDMA_DCR_SSIZE_WORD :
- ((mode & DMA_MODE_LONG_BIT) ? MCFDMA_DCR_SSIZE_LONG :
- MCFDMA_DCR_SSIZE_BYTE)) |
- ((mode & DMA_MODE_WORD_BIT) ? MCFDMA_DCR_DSIZE_WORD :
- ((mode & DMA_MODE_LONG_BIT) ? MCFDMA_DCR_DSIZE_LONG :
- MCFDMA_DCR_DSIZE_BYTE));
-
-#ifdef DEBUG_DMA
- printk("%s(%d): dmanr=%d DSR[%x]=%x DCR[%x]=%x\n", __FILE__, __LINE__,
- dmanr, (int) &dmabp[MCFDMA_DSR], dmabp[MCFDMA_DSR],
- (int) &dmawp[MCFDMA_DCR], dmawp[MCFDMA_DCR]);
-#endif
-}
-
-/* Set transfer address for specific DMA channel */
-static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
-{
- volatile unsigned short *dmawp;
- volatile unsigned int *dmalp;
-
-#ifdef DMA_DEBUG
- printk("set_dma_addr(dmanr=%d,a=%x)\n", dmanr, a);
-#endif
-
- dmawp = (unsigned short *) dma_base_addr[dmanr];
- dmalp = (unsigned int *) dma_base_addr[dmanr];
-
- // Determine which address registers are used for memory/device accesses
- if (dmawp[MCFDMA_DCR] & MCFDMA_DCR_SINC) {
- // Source incrementing, must be memory
- dmalp[MCFDMA_SAR] = a;
- // Set dest address, must be device
- dmalp[MCFDMA_DAR] = dma_device_address[dmanr];
- } else {
- // Destination incrementing, must be memory
- dmalp[MCFDMA_DAR] = a;
- // Set source address, must be device
- dmalp[MCFDMA_SAR] = dma_device_address[dmanr];
- }
-
-#ifdef DEBUG_DMA
- printk("%s(%d): dmanr=%d DCR[%x]=%x SAR[%x]=%08x DAR[%x]=%08x\n",
- __FILE__, __LINE__, dmanr, (int) &dmawp[MCFDMA_DCR], dmawp[MCFDMA_DCR],
- (int) &dmalp[MCFDMA_SAR], dmalp[MCFDMA_SAR],
- (int) &dmalp[MCFDMA_DAR], dmalp[MCFDMA_DAR]);
-#endif
-}
-
-/*
- * Specific for Coldfire - sets device address.
- * Should be called after the mode set call, and before set DMA address.
- */
-static __inline__ void set_dma_device_addr(unsigned int dmanr, unsigned int a)
-{
-#ifdef DMA_DEBUG
- printk("set_dma_device_addr(dmanr=%d,a=%x)\n", dmanr, a);
-#endif
-
- dma_device_address[dmanr] = a;
-}
-
-/*
- * NOTE 2: "count" represents _bytes_.
- */
-static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
-{
- volatile unsigned short *dmawp;
-
-#ifdef DMA_DEBUG
- printk("set_dma_count(dmanr=%d,count=%d)\n", dmanr, count);
-#endif
-
- dmawp = (unsigned short *) dma_base_addr[dmanr];
- dmawp[MCFDMA_BCR] = (unsigned short)count;
-}
-
-/*
- * Get DMA residue count. After a DMA transfer, this
- * should return zero. Reading this while a DMA transfer is
- * still in progress will return unpredictable results.
- * Otherwise, it returns the number of _bytes_ left to transfer.
- */
-static __inline__ int get_dma_residue(unsigned int dmanr)
-{
- volatile unsigned short *dmawp;
- unsigned short count;
-
-#ifdef DMA_DEBUG
- printk("get_dma_residue(dmanr=%d)\n", dmanr);
-#endif
-
- dmawp = (unsigned short *) dma_base_addr[dmanr];
- count = dmawp[MCFDMA_BCR];
- return((int) count);
-}
-#else /* CONFIG_M5272 is defined */
-
-/*
- * The MCF5272 DMA controller is very different than the controller defined above
- * in terms of register mapping. For instance, with the exception of the 16-bit
- * interrupt register (IRQ#85, for reference), all of the registers are 32-bit.
- *
- * The big difference, however, is the lack of device-requested DMA. All modes
- * are dual address transfer, and there is no 'device' setup or direction bit.
- * You can DMA between a device and memory, between memory and memory, or even between
- * two devices directly, with any combination of incrementing and non-incrementing
- * addresses you choose. This puts a crimp in distinguishing between the 'device
- * address' set up by set_dma_device_addr.
- *
- * Therefore, there are two options. One is to use set_dma_addr and set_dma_device_addr,
- * which will act exactly as above in -- it will look to see if the source is set to
- * autoincrement, and if so it will make the source use the set_dma_addr value and the
- * destination the set_dma_device_addr value. Otherwise the source will be set to the
- * set_dma_device_addr value and the destination will get the set_dma_addr value.
- *
- * The other is to use the provided set_dma_src_addr and set_dma_dest_addr functions
- * and make it explicit. Depending on what you're doing, one of these two should work
- * for you, but don't mix them in the same transfer setup.
- */
-
-/* enable/disable a specific DMA channel */
-static __inline__ void enable_dma(unsigned int dmanr)
-{
- volatile unsigned int *dmalp;
-
-#ifdef DMA_DEBUG
- printk("enable_dma(dmanr=%d)\n", dmanr);
-#endif
-
- dmalp = (unsigned int *) dma_base_addr[dmanr];
- dmalp[MCFDMA_DMR] |= MCFDMA_DMR_EN;
-}
-
-static __inline__ void disable_dma(unsigned int dmanr)
-{
- volatile unsigned int *dmalp;
-
-#ifdef DMA_DEBUG
- printk("disable_dma(dmanr=%d)\n", dmanr);
-#endif
-
- dmalp = (unsigned int *) dma_base_addr[dmanr];
-
- /* Turn off external requests, and stop any DMA in progress */
- dmalp[MCFDMA_DMR] &= ~MCFDMA_DMR_EN;
- dmalp[MCFDMA_DMR] |= MCFDMA_DMR_RESET;
-}
-
-/*
- * Clear the 'DMA Pointer Flip Flop'.
- * Write 0 for LSB/MSB, 1 for MSB/LSB access.
- * Use this once to initialize the FF to a known state.
- * After that, keep track of it. :-)
- * --- In order to do that, the DMA routines below should ---
- * --- only be used while interrupts are disabled! ---
- *
- * This is a NOP for ColdFire. Provide a stub for compatibility.
- */
-static __inline__ void clear_dma_ff(unsigned int dmanr)
-{
-}
-
-/* set mode (above) for a specific DMA channel */
-static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
-{
-
- volatile unsigned int *dmalp;
- volatile unsigned short *dmawp;
-
-#ifdef DMA_DEBUG
- printk("set_dma_mode(dmanr=%d,mode=%d)\n", dmanr, mode);
-#endif
- dmalp = (unsigned int *) dma_base_addr[dmanr];
- dmawp = (unsigned short *) dma_base_addr[dmanr];
-
- // Clear config errors
- dmalp[MCFDMA_DMR] |= MCFDMA_DMR_RESET;
-
- // Set command register
- dmalp[MCFDMA_DMR] =
- MCFDMA_DMR_RQM_DUAL | // Mandatory Request Mode setting
- MCFDMA_DMR_DSTT_SD | // Set up addressing types; set to supervisor-data.
- MCFDMA_DMR_SRCT_SD | // Set up addressing types; set to supervisor-data.
- // source static-address-mode
- ((mode & DMA_MODE_SRC_SA_BIT) ? MCFDMA_DMR_SRCM_SA : MCFDMA_DMR_SRCM_IA) |
- // dest static-address-mode
- ((mode & DMA_MODE_DES_SA_BIT) ? MCFDMA_DMR_DSTM_SA : MCFDMA_DMR_DSTM_IA) |
- // burst, 32 bit, 16 bit or 8 bit transfers are separately configurable on the MCF5272
- (((mode & DMA_MODE_SSIZE_MASK) >> DMA_MODE_SSIZE_OFF) << MCFDMA_DMR_DSTS_OFF) |
- (((mode & DMA_MODE_SSIZE_MASK) >> DMA_MODE_SSIZE_OFF) << MCFDMA_DMR_SRCS_OFF);
-
- dmawp[MCFDMA_DIR] |= MCFDMA_DIR_ASCEN; /* Enable completion interrupts */
-
-#ifdef DEBUG_DMA
- printk("%s(%d): dmanr=%d DMR[%x]=%x DIR[%x]=%x\n", __FILE__, __LINE__,
- dmanr, (int) &dmalp[MCFDMA_DMR], dmabp[MCFDMA_DMR],
- (int) &dmawp[MCFDMA_DIR], dmawp[MCFDMA_DIR]);
-#endif
-}
-
-/* Set transfer address for specific DMA channel */
-static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
-{
- volatile unsigned int *dmalp;
-
-#ifdef DMA_DEBUG
- printk("set_dma_addr(dmanr=%d,a=%x)\n", dmanr, a);
-#endif
-
- dmalp = (unsigned int *) dma_base_addr[dmanr];
-
- // Determine which address registers are used for memory/device accesses
- if (dmalp[MCFDMA_DMR] & MCFDMA_DMR_SRCM) {
- // Source incrementing, must be memory
- dmalp[MCFDMA_DSAR] = a;
- // Set dest address, must be device
- dmalp[MCFDMA_DDAR] = dma_device_address[dmanr];
- } else {
- // Destination incrementing, must be memory
- dmalp[MCFDMA_DDAR] = a;
- // Set source address, must be device
- dmalp[MCFDMA_DSAR] = dma_device_address[dmanr];
- }
-
-#ifdef DEBUG_DMA
- printk("%s(%d): dmanr=%d DMR[%x]=%x SAR[%x]=%08x DAR[%x]=%08x\n",
- __FILE__, __LINE__, dmanr, (int) &dmawp[MCFDMA_DMR], dmawp[MCFDMA_DMR],
- (int) &dmalp[MCFDMA_DSAR], dmalp[MCFDMA_DSAR],
- (int) &dmalp[MCFDMA_DDAR], dmalp[MCFDMA_DDAR]);
-#endif
-}
-
-/*
- * Specific for Coldfire - sets device address.
- * Should be called after the mode set call, and before set DMA address.
- */
-static __inline__ void set_dma_device_addr(unsigned int dmanr, unsigned int a)
-{
-#ifdef DMA_DEBUG
- printk("set_dma_device_addr(dmanr=%d,a=%x)\n", dmanr, a);
-#endif
-
- dma_device_address[dmanr] = a;
-}
-
-/*
- * NOTE 2: "count" represents _bytes_.
- *
- * NOTE 3: While a 32-bit register, "count" is only a maximum 24-bit value.
- */
-static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
-{
- volatile unsigned int *dmalp;
-
-#ifdef DMA_DEBUG
- printk("set_dma_count(dmanr=%d,count=%d)\n", dmanr, count);
-#endif
-
- dmalp = (unsigned int *) dma_base_addr[dmanr];
- dmalp[MCFDMA_DBCR] = count;
-}
-
-/*
- * Get DMA residue count. After a DMA transfer, this
- * should return zero. Reading this while a DMA transfer is
- * still in progress will return unpredictable results.
- * Otherwise, it returns the number of _bytes_ left to transfer.
- */
-static __inline__ int get_dma_residue(unsigned int dmanr)
-{
- volatile unsigned int *dmalp;
- unsigned int count;
-
-#ifdef DMA_DEBUG
- printk("get_dma_residue(dmanr=%d)\n", dmanr);
-#endif
-
- dmalp = (unsigned int *) dma_base_addr[dmanr];
- count = dmalp[MCFDMA_DBCR];
- return(count);
-}
-
-#endif /* !defined(CONFIG_M5272) */
-#endif /* CONFIG_COLDFIRE */
-
-#define MAX_DMA_CHANNELS 8
-
-/* Don't define MAX_DMA_ADDRESS; it's useless on the m68k/coldfire and any
- occurrence should be flagged as an error. */
-/* under 2.4 it is actually needed by the new bootmem allocator */
-#define MAX_DMA_ADDRESS PAGE_OFFSET
-
-/* These are in kernel/dma.c: */
-extern int request_dma(unsigned int dmanr, const char *device_id); /* reserve a DMA channel */
-extern void free_dma(unsigned int dmanr); /* release it again */
-
-#endif /* _M68K_DMA_H */
diff --git a/arch/m68k/include/asm/hardirq.h b/arch/m68k/include/asm/hardirq.h
index 56d0d5db231c..7167ed209823 100644
--- a/arch/m68k/include/asm/hardirq.h
+++ b/arch/m68k/include/asm/hardirq.h
@@ -1,5 +1,18 @@
-#ifdef __uClinux__
-#include "hardirq_no.h"
-#else
-#include "hardirq_mm.h"
+#ifndef __M68K_HARDIRQ_H
+#define __M68K_HARDIRQ_H
+
+#include <linux/threads.h>
+#include <linux/cache.h>
+
+/* entry.S is sensitive to the offsets of these fields */
+typedef struct {
+ unsigned int __softirq_pending;
+} ____cacheline_aligned irq_cpustat_t;
+
+#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+
+#define HARDIRQ_BITS 8
+
+void ack_bad_irq(unsigned int irq);
+
#endif
diff --git a/arch/m68k/include/asm/hardirq_mm.h b/arch/m68k/include/asm/hardirq_mm.h
deleted file mode 100644
index 394ee946015c..000000000000
--- a/arch/m68k/include/asm/hardirq_mm.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __M68K_HARDIRQ_H
-#define __M68K_HARDIRQ_H
-
-#include <linux/threads.h>
-#include <linux/cache.h>
-
-/* entry.S is sensitive to the offsets of these fields */
-typedef struct {
- unsigned int __softirq_pending;
-} ____cacheline_aligned irq_cpustat_t;
-
-#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
-
-#define HARDIRQ_BITS 8
-
-#endif
diff --git a/arch/m68k/include/asm/hardirq_no.h b/arch/m68k/include/asm/hardirq_no.h
deleted file mode 100644
index bfad28149a49..000000000000
--- a/arch/m68k/include/asm/hardirq_no.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef __M68K_HARDIRQ_H
-#define __M68K_HARDIRQ_H
-
-#include <linux/cache.h>
-#include <linux/threads.h>
-#include <asm/irq.h>
-
-typedef struct {
- unsigned int __softirq_pending;
-} ____cacheline_aligned irq_cpustat_t;
-
-#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
-
-#define HARDIRQ_BITS 8
-
-/*
- * The hardirq mask has to be large enough to have
- * space for potentially all IRQ sources in the system
- * nesting on a single CPU:
- */
-#if (1 << HARDIRQ_BITS) < NR_IRQS
-# error HARDIRQ_BITS is too low!
-#endif
-
-void ack_bad_irq(unsigned int irq);
-
-#endif /* __M68K_HARDIRQ_H */
diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h
index d031416595b2..cc0614a6deeb 100644
--- a/arch/m68k/include/asm/irq.h
+++ b/arch/m68k/include/asm/irq.h
@@ -1,5 +1,134 @@
-#ifdef __uClinux__
-#include "irq_no.h"
+#ifndef _M68K_IRQ_H_
+#define _M68K_IRQ_H_
+
+#include <linux/linkage.h>
+#include <linux/hardirq.h>
+#include <linux/irqreturn.h>
+#include <linux/spinlock_types.h>
+
+/*
+ * This should be the same as the max(NUM_X_SOURCES) for all the
+ * different m68k hosts compiled into the kernel.
+ * Currently the Atari has 72 and the Amiga 24, but if both are
+ * supported in the kernel it is better to make room for 72.
+ */
+#if defined(CONFIG_COLDFIRE)
+#define NR_IRQS 256
+#elif defined(CONFIG_VME) || defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
+#define NR_IRQS 200
+#elif defined(CONFIG_ATARI) || defined(CONFIG_MAC)
+#define NR_IRQS 72
+#elif defined(CONFIG_Q40)
+#define NR_IRQS 43
+#elif defined(CONFIG_AMIGA) || !defined(CONFIG_MMU)
+#define NR_IRQS 32
+#elif defined(CONFIG_APOLLO)
+#define NR_IRQS 24
+#elif defined(CONFIG_HP300)
+#define NR_IRQS 8
#else
-#include "irq_mm.h"
+#define NR_IRQS 0
#endif
+
+/*
+ * The hardirq mask has to be large enough to have
+ * space for potentially all IRQ sources in the system
+ * nesting on a single CPU:
+ */
+#if (1 << HARDIRQ_BITS) < NR_IRQS
+# error HARDIRQ_BITS is too low!
+#endif
+
+#ifdef CONFIG_MMU
+
+/*
+ * Interrupt source definitions
+ * General interrupt sources are the level 1-7.
+ * Adding an interrupt service routine for one of these sources
+ * results in the addition of that routine to a chain of routines.
+ * Each one is called in succession. Each individual interrupt
+ * service routine should determine if the device associated with
+ * that routine requires service.
+ */
+
+#define IRQ_SPURIOUS 0
+
+#define IRQ_AUTO_1 1 /* level 1 interrupt */
+#define IRQ_AUTO_2 2 /* level 2 interrupt */
+#define IRQ_AUTO_3 3 /* level 3 interrupt */
+#define IRQ_AUTO_4 4 /* level 4 interrupt */
+#define IRQ_AUTO_5 5 /* level 5 interrupt */
+#define IRQ_AUTO_6 6 /* level 6 interrupt */
+#define IRQ_AUTO_7 7 /* level 7 interrupt (non-maskable) */
+
+#define IRQ_USER 8
+
+extern unsigned int irq_canonicalize(unsigned int irq);
+
+struct pt_regs;
+
+/*
+ * various flags for request_irq() - the Amiga now uses the standard
+ * mechanism like all other architectures - IRQF_DISABLED and
+ * IRQF_SHARED are your friends.
+ */
+#ifndef MACH_AMIGA_ONLY
+#define IRQ_FLG_LOCK (0x0001) /* handler is not replaceable */
+#define IRQ_FLG_REPLACE (0x0002) /* replace existing handler */
+#define IRQ_FLG_FAST (0x0004)
+#define IRQ_FLG_SLOW (0x0008)
+#define IRQ_FLG_STD (0x8000) /* internally used */
+#endif
+
+/*
+ * This structure is used to chain together the ISRs for a particular
+ * interrupt source (if it supports chaining).
+ */
+typedef struct irq_node {
+ irqreturn_t (*handler)(int, void *);
+ void *dev_id;
+ struct irq_node *next;
+ unsigned long flags;
+ const char *devname;
+} irq_node_t;
+
+/*
+ * This structure has only 4 elements for speed reasons
+ */
+struct irq_handler {
+ int (*handler)(int, void *);
+ unsigned long flags;
+ void *dev_id;
+ const char *devname;
+};
+
+struct irq_controller {
+ const char *name;
+ spinlock_t lock;
+ int (*startup)(unsigned int irq);
+ void (*shutdown)(unsigned int irq);
+ void (*enable)(unsigned int irq);
+ void (*disable)(unsigned int irq);
+};
+
+extern int m68k_irq_startup(unsigned int);
+extern void m68k_irq_shutdown(unsigned int);
+
+/*
+ * This function returns a new irq_node_t
+ */
+extern irq_node_t *new_irq_node(void);
+
+extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *));
+extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
+ void (*handler)(unsigned int, struct pt_regs *));
+extern void m68k_setup_irq_controller(struct irq_controller *, unsigned int, unsigned int);
+
+asmlinkage void m68k_handle_int(unsigned int);
+asmlinkage void __m68k_handle_int(unsigned int, struct pt_regs *);
+
+#else
+#define irq_canonicalize(irq) (irq)
+#endif /* CONFIG_MMU */
+
+#endif /* _M68K_IRQ_H_ */
diff --git a/arch/m68k/include/asm/irq_mm.h b/arch/m68k/include/asm/irq_mm.h
deleted file mode 100644
index 0cab42cad79e..000000000000
--- a/arch/m68k/include/asm/irq_mm.h
+++ /dev/null
@@ -1,126 +0,0 @@
-#ifndef _M68K_IRQ_H_
-#define _M68K_IRQ_H_
-
-#include <linux/linkage.h>
-#include <linux/hardirq.h>
-#include <linux/irqreturn.h>
-#include <linux/spinlock_types.h>
-
-/*
- * This should be the same as the max(NUM_X_SOURCES) for all the
- * different m68k hosts compiled into the kernel.
- * Currently the Atari has 72 and the Amiga 24, but if both are
- * supported in the kernel it is better to make room for 72.
- */
-#if defined(CONFIG_VME) || defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
-#define NR_IRQS 200
-#elif defined(CONFIG_ATARI) || defined(CONFIG_MAC)
-#define NR_IRQS 72
-#elif defined(CONFIG_Q40)
-#define NR_IRQS 43
-#elif defined(CONFIG_AMIGA)
-#define NR_IRQS 32
-#elif defined(CONFIG_APOLLO)
-#define NR_IRQS 24
-#elif defined(CONFIG_HP300)
-#define NR_IRQS 8
-#else
-#define NR_IRQS 0
-#endif
-
-/*
- * The hardirq mask has to be large enough to have
- * space for potentially all IRQ sources in the system
- * nesting on a single CPU:
- */
-#if (1 << HARDIRQ_BITS) < NR_IRQS
-# error HARDIRQ_BITS is too low!
-#endif
-
-/*
- * Interrupt source definitions
- * General interrupt sources are the level 1-7.
- * Adding an interrupt service routine for one of these sources
- * results in the addition of that routine to a chain of routines.
- * Each one is called in succession. Each individual interrupt
- * service routine should determine if the device associated with
- * that routine requires service.
- */
-
-#define IRQ_SPURIOUS 0
-
-#define IRQ_AUTO_1 1 /* level 1 interrupt */
-#define IRQ_AUTO_2 2 /* level 2 interrupt */
-#define IRQ_AUTO_3 3 /* level 3 interrupt */
-#define IRQ_AUTO_4 4 /* level 4 interrupt */
-#define IRQ_AUTO_5 5 /* level 5 interrupt */
-#define IRQ_AUTO_6 6 /* level 6 interrupt */
-#define IRQ_AUTO_7 7 /* level 7 interrupt (non-maskable) */
-
-#define IRQ_USER 8
-
-extern unsigned int irq_canonicalize(unsigned int irq);
-
-struct pt_regs;
-
-/*
- * various flags for request_irq() - the Amiga now uses the standard
- * mechanism like all other architectures - IRQF_DISABLED and
- * IRQF_SHARED are your friends.
- */
-#ifndef MACH_AMIGA_ONLY
-#define IRQ_FLG_LOCK (0x0001) /* handler is not replaceable */
-#define IRQ_FLG_REPLACE (0x0002) /* replace existing handler */
-#define IRQ_FLG_FAST (0x0004)
-#define IRQ_FLG_SLOW (0x0008)
-#define IRQ_FLG_STD (0x8000) /* internally used */
-#endif
-
-/*
- * This structure is used to chain together the ISRs for a particular
- * interrupt source (if it supports chaining).
- */
-typedef struct irq_node {
- irqreturn_t (*handler)(int, void *);
- void *dev_id;
- struct irq_node *next;
- unsigned long flags;
- const char *devname;
-} irq_node_t;
-
-/*
- * This structure has only 4 elements for speed reasons
- */
-struct irq_handler {
- int (*handler)(int, void *);
- unsigned long flags;
- void *dev_id;
- const char *devname;
-};
-
-struct irq_controller {
- const char *name;
- spinlock_t lock;
- int (*startup)(unsigned int irq);
- void (*shutdown)(unsigned int irq);
- void (*enable)(unsigned int irq);
- void (*disable)(unsigned int irq);
-};
-
-extern int m68k_irq_startup(unsigned int);
-extern void m68k_irq_shutdown(unsigned int);
-
-/*
- * This function returns a new irq_node_t
- */
-extern irq_node_t *new_irq_node(void);
-
-extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *));
-extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
- void (*handler)(unsigned int, struct pt_regs *));
-extern void m68k_setup_irq_controller(struct irq_controller *, unsigned int, unsigned int);
-
-asmlinkage void m68k_handle_int(unsigned int);
-asmlinkage void __m68k_handle_int(unsigned int, struct pt_regs *);
-
-#endif /* _M68K_IRQ_H_ */
diff --git a/arch/m68k/include/asm/irq_no.h b/arch/m68k/include/asm/irq_no.h
deleted file mode 100644
index 9373c31ac87d..000000000000
--- a/arch/m68k/include/asm/irq_no.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef _M68KNOMMU_IRQ_H_
-#define _M68KNOMMU_IRQ_H_
-
-#ifdef CONFIG_COLDFIRE
-/*
- * On the ColdFire we keep track of all vectors. That way drivers
- * can register whatever vector number they wish, and we can deal
- * with it.
- */
-#define SYS_IRQS 256
-#define NR_IRQS SYS_IRQS
-
-#else
-
-/*
- * # of m68k interrupts
- */
-#define SYS_IRQS 8
-#define NR_IRQS (24 + SYS_IRQS)
-
-#endif /* CONFIG_COLDFIRE */
-
-
-#define irq_canonicalize(irq) (irq)
-
-#endif /* _M68KNOMMU_IRQ_H_ */
diff --git a/arch/m68k/include/asm/m520xsim.h b/arch/m68k/include/asm/m520xsim.h
index 49d016e6391a..7d76b8747e35 100644
--- a/arch/m68k/include/asm/m520xsim.h
+++ b/arch/m68k/include/asm/m520xsim.h
@@ -11,9 +11,8 @@
#define m520xsim_h
/****************************************************************************/
-
/*
- * Define the 5282 SIM register set addresses.
+ * Define the 520x SIM register set addresses.
*/
#define MCFICM_INTC0 0x48000 /* Base for Interrupt Ctrl 0 */
#define MCFINTC_IPRH 0x00 /* Interrupt pending 32-63 */
@@ -22,8 +21,22 @@
#define MCFINTC_IMRL 0x0c /* Interrupt mask 1-31 */
#define MCFINTC_INTFRCH 0x10 /* Interrupt force 32-63 */
#define MCFINTC_INTFRCL 0x14 /* Interrupt force 1-31 */
+#define MCFINTC_SIMR 0x1c /* Set interrupt mask 0-63 */
+#define MCFINTC_CIMR 0x1d /* Clear interrupt mask 0-63 */
#define MCFINTC_ICR0 0x40 /* Base ICR register */
+/*
+ * The common interrupt controller code just wants to know the absolute
+ * address to the SIMR and CIMR registers (not offsets into IPSBAR).
+ * The 520x family only has a single INTC unit.
+ */
+#define MCFINTC0_SIMR (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_SIMR)
+#define MCFINTC0_CIMR (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_CIMR)
+#define MCFINTC0_ICR0 (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0)
+#define MCFINTC1_SIMR (0)
+#define MCFINTC1_CIMR (0)
+#define MCFINTC1_ICR0 (0)
+
#define MCFINT_VECBASE 64
#define MCFINT_UART0 26 /* Interrupt number for UART0 */
#define MCFINT_UART1 27 /* Interrupt number for UART1 */
@@ -55,9 +68,14 @@
#define MCF_GPIO_PAR_FECI2C_PAR_SDA_URXD2 (0x02)
#define MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2 (0x04)
-#define ICR_INTRCONF 0x05
-#define MCFPIT_IMR MCFINTC_IMRL
-#define MCFPIT_IMR_IBIT (1 << MCFINT_PIT1)
+/*
+ * Reset Controll Unit.
+ */
+#define MCF_RCR 0xFC0A0000
+#define MCF_RSR 0xFC0A0001
+
+#define MCF_RCR_SWRESET 0x80 /* Software reset bit */
+#define MCF_RCR_FRCSTOUT 0x40 /* Force external reset */
/****************************************************************************/
#endif /* m520xsim_h */
diff --git a/arch/m68k/include/asm/m523xsim.h b/arch/m68k/include/asm/m523xsim.h
index bf397313e93f..55183b5df1b8 100644
--- a/arch/m68k/include/asm/m523xsim.h
+++ b/arch/m68k/include/asm/m523xsim.h
@@ -41,5 +41,14 @@
#define MCFSIM_DACR1 0x50 /* SDRAM base address 1 */
#define MCFSIM_DMR1 0x54 /* SDRAM address mask 1 */
+/*
+ * Reset Controll Unit (relative to IPSBAR).
+ */
+#define MCF_RCR 0x110000
+#define MCF_RSR 0x110001
+
+#define MCF_RCR_SWRESET 0x80 /* Software reset bit */
+#define MCF_RCR_FRCSTOUT 0x40 /* Force external reset */
+
/****************************************************************************/
#endif /* m523xsim_h */
diff --git a/arch/m68k/include/asm/m527xsim.h b/arch/m68k/include/asm/m527xsim.h
index 1f63ab3fb3e6..95f4f8ee8f7c 100644
--- a/arch/m68k/include/asm/m527xsim.h
+++ b/arch/m68k/include/asm/m527xsim.h
@@ -70,5 +70,14 @@
#define UART2_ENABLE_MASK 0x3f00
#endif
+/*
+ * Reset Controll Unit (relative to IPSBAR).
+ */
+#define MCF_RCR 0x110000
+#define MCF_RSR 0x110001
+
+#define MCF_RCR_SWRESET 0x80 /* Software reset bit */
+#define MCF_RCR_FRCSTOUT 0x40 /* Force external reset */
+
/****************************************************************************/
#endif /* m527xsim_h */
diff --git a/arch/m68k/include/asm/m528xsim.h b/arch/m68k/include/asm/m528xsim.h
index 28bf783a5d6d..d79c49f8134a 100644
--- a/arch/m68k/include/asm/m528xsim.h
+++ b/arch/m68k/include/asm/m528xsim.h
@@ -56,6 +56,14 @@
#define MCF5282_INTC0_ICR17 (volatile u8 *) (MCF_IPSBAR + 0x0C51)
+/*
+ * Reset Control Unit (relative to IPSBAR).
+ */
+#define MCF_RCR 0x110000
+#define MCF_RSR 0x110001
+
+#define MCF_RCR_SWRESET 0x80 /* Software reset bit */
+#define MCF_RCR_FRCSTOUT 0x40 /* Force external reset */
/*********************************************************************
*
diff --git a/arch/m68k/include/asm/m532xsim.h b/arch/m68k/include/asm/m532xsim.h
index ce603451b55e..d563b6bcc738 100644
--- a/arch/m68k/include/asm/m532xsim.h
+++ b/arch/m68k/include/asm/m532xsim.h
@@ -56,49 +56,18 @@
#define MCFSIM_DMA3ICR MCFSIM_ICR9 /* DMA 3 ICR */
-#define MCFSIM_IMR_MASKALL 0xFFFFFFFF /* All SIM intr sources */
-
-#define MCFSIM_IMR_SIMR0 0xFC04801C
-#define MCFSIM_IMR_SIMR1 0xFC04C01C
-#define MCFSIM_IMR_CIMR0 0xFC04801D
-#define MCFSIM_IMR_CIMR1 0xFC04C01D
+#define MCFINTC0_SIMR 0xFC04801C
+#define MCFINTC0_CIMR 0xFC04801D
+#define MCFINTC0_ICR0 0xFC048040
+#define MCFINTC1_SIMR 0xFC04C01C
+#define MCFINTC1_CIMR 0xFC04C01D
+#define MCFINTC1_ICR0 0xFC04C040
#define MCFSIM_ICR_TIMER1 (0xFC048040+32)
#define MCFSIM_ICR_TIMER2 (0xFC048040+33)
/*
- * Macro to set IMR register. It is 32 bits on the 5307.
- */
-#define mcf_getimr() \
- *((volatile unsigned long *) (MCF_MBAR + MCFSIM_IMR))
-
-#define mcf_setimr(imr) \
- *((volatile unsigned long *) (MCF_MBAR + MCFSIM_IMR)) = (imr);
-
-#define mcf_getipr() \
- *((volatile unsigned long *) (MCF_MBAR + MCFSIM_IPR))
-
-#define mcf_getiprl() \
- *((volatile unsigned long *) (MCF_MBAR + MCFSIM_IPRL))
-
-#define mcf_getiprh() \
- *((volatile unsigned long *) (MCF_MBAR + MCFSIM_IPRH))
-
-
-#define mcf_enable_irq0(irq) \
- *((volatile unsigned char*) (MCFSIM_IMR_CIMR0)) = (irq);
-
-#define mcf_enable_irq1(irq) \
- *((volatile unsigned char*) (MCFSIM_IMR_CIMR1)) = (irq);
-
-#define mcf_disable_irq0(irq) \
- *((volatile unsigned char*) (MCFSIM_IMR_SIMR0)) = (irq);
-
-#define mcf_disable_irq1(irq) \
- *((volatile unsigned char*) (MCFSIM_IMR_SIMR1)) = (irq);
-
-/*
* Define the Cache register flags.
*/
#define CACR_EC (1<<31)
@@ -127,6 +96,18 @@
/*********************************************************************
*
+ * Reset Controller Module
+ *
+ *********************************************************************/
+
+#define MCF_RCR 0xFC0A0000
+#define MCF_RSR 0xFC0A0001
+
+#define MCF_RCR_SWRESET 0x80 /* Software reset bit */
+#define MCF_RCR_FRCSTOUT 0x40 /* Force external reset */
+
+/*********************************************************************
+ *
* Inter-IC (I2C) Module
*
*********************************************************************/
diff --git a/arch/m68k/include/asm/mcfsim.h b/arch/m68k/include/asm/mcfsim.h
index da3f2ceff3a4..b90425fb50fe 100644
--- a/arch/m68k/include/asm/mcfsim.h
+++ b/arch/m68k/include/asm/mcfsim.h
@@ -101,20 +101,6 @@
#endif
-/*
- * PIT interrupt settings, if not found in mXXXXsim.h file.
- */
-#ifndef ICR_INTRCONF
-#define ICR_INTRCONF 0x2b /* PIT1 level 5, priority 3 */
-#endif
-#ifndef MCFPIT_IMR
-#define MCFPIT_IMR MCFINTC_IMRH
-#endif
-#ifndef MCFPIT_IMR_IBIT
-#define MCFPIT_IMR_IBIT (1 << (MCFINT_PIT1 - 32))
-#endif
-
-
#ifndef __ASSEMBLY__
/*
* Definition for the interrupt auto-vectoring support.
diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h
index fc3f2c22f2b8..74fd674b15ad 100644
--- a/arch/m68k/include/asm/processor.h
+++ b/arch/m68k/include/asm/processor.h
@@ -1,5 +1,170 @@
-#ifdef __uClinux__
-#include "processor_no.h"
+/*
+ * include/asm-m68k/processor.h
+ *
+ * Copyright (C) 1995 Hamish Macdonald
+ */
+
+#ifndef __ASM_M68K_PROCESSOR_H
+#define __ASM_M68K_PROCESSOR_H
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+
+#include <linux/thread_info.h>
+#include <asm/segment.h>
+#include <asm/fpu.h>
+#include <asm/ptrace.h>
+
+static inline unsigned long rdusp(void)
+{
+#ifdef CONFIG_COLDFIRE
+ extern unsigned int sw_usp;
+ return sw_usp;
#else
-#include "processor_mm.h"
+ unsigned long usp;
+ __asm__ __volatile__("move %/usp,%0" : "=a" (usp));
+ return usp;
+#endif
+}
+
+static inline void wrusp(unsigned long usp)
+{
+#ifdef CONFIG_COLDFIRE
+ extern unsigned int sw_usp;
+ sw_usp = usp;
+#else
+ __asm__ __volatile__("move %0,%/usp" : : "a" (usp));
+#endif
+}
+
+/*
+ * User space process size: 3.75GB. This is hardcoded into a few places,
+ * so don't change it unless you know what you are doing.
+ */
+#ifndef CONFIG_SUN3
+#define TASK_SIZE (0xF0000000UL)
+#else
+#define TASK_SIZE (0x0E000000UL)
+#endif
+
+#ifdef __KERNEL__
+#define STACK_TOP TASK_SIZE
+#define STACK_TOP_MAX STACK_TOP
+#endif
+
+/* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#ifdef CONFIG_MMU
+#ifndef CONFIG_SUN3
+#define TASK_UNMAPPED_BASE 0xC0000000UL
+#else
+#define TASK_UNMAPPED_BASE 0x0A000000UL
+#endif
+#define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr)
+#else
+#define TASK_UNMAPPED_BASE 0
+#endif
+
+struct thread_struct {
+ unsigned long ksp; /* kernel stack pointer */
+ unsigned long usp; /* user stack pointer */
+ unsigned short sr; /* saved status register */
+ unsigned short fs; /* saved fs (sfc, dfc) */
+ unsigned long crp[2]; /* cpu root pointer */
+ unsigned long esp0; /* points to SR of stack frame */
+ unsigned long faddr; /* info about last fault */
+ int signo, code;
+ unsigned long fp[8*3];
+ unsigned long fpcntl[3]; /* fp control regs */
+ unsigned char fpstate[FPSTATESIZE]; /* floating point state */
+ struct thread_info info;
+};
+
+#define INIT_THREAD { \
+ .ksp = sizeof(init_stack) + (unsigned long) init_stack, \
+ .sr = PS_S, \
+ .fs = __KERNEL_DS, \
+ .info = INIT_THREAD_INFO(init_task), \
+}
+
+#ifdef CONFIG_MMU
+/*
+ * Do necessary setup to start up a newly executed thread.
+ */
+static inline void start_thread(struct pt_regs * regs, unsigned long pc,
+ unsigned long usp)
+{
+ /* reads from user space */
+ set_fs(USER_DS);
+
+ regs->pc = pc;
+ regs->sr &= ~0x2000;
+ wrusp(usp);
+}
+
+#else
+
+/*
+ * Coldfire stacks need to be re-aligned on trap exit, conventional
+ * 68k can handle this case cleanly.
+ */
+#ifdef CONFIG_COLDFIRE
+#define reformat(_regs) do { (_regs)->format = 0x4; } while(0)
+#else
+#define reformat(_regs) do { } while (0)
+#endif
+
+#define start_thread(_regs, _pc, _usp) \
+do { \
+ set_fs(USER_DS); /* reads from user space */ \
+ (_regs)->pc = (_pc); \
+ ((struct switch_stack *)(_regs))[-1].a6 = 0; \
+ reformat(_regs); \
+ if (current->mm) \
+ (_regs)->d5 = current->mm->start_data; \
+ (_regs)->sr &= ~0x2000; \
+ wrusp(_usp); \
+} while(0)
+
+#endif
+
+/* Forward declaration, a strange C thing */
+struct task_struct;
+
+/* Free all resources held by a thread. */
+static inline void release_thread(struct task_struct *dead_task)
+{
+}
+
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk) do { } while (0)
+
+extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+
+/*
+ * Free current thread data structures etc..
+ */
+static inline void exit_thread(void)
+{
+}
+
+extern unsigned long thread_saved_pc(struct task_struct *tsk);
+
+unsigned long get_wchan(struct task_struct *p);
+
+#define KSTK_EIP(tsk) \
+ ({ \
+ unsigned long eip = 0; \
+ if ((tsk)->thread.esp0 > PAGE_SIZE && \
+ (virt_addr_valid((tsk)->thread.esp0))) \
+ eip = ((struct pt_regs *) (tsk)->thread.esp0)->pc; \
+ eip; })
+#define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp)
+
+#define cpu_relax() barrier()
+
#endif
diff --git a/arch/m68k/include/asm/processor_mm.h b/arch/m68k/include/asm/processor_mm.h
deleted file mode 100644
index 1f61ef53f0e0..000000000000
--- a/arch/m68k/include/asm/processor_mm.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * include/asm-m68k/processor.h
- *
- * Copyright (C) 1995 Hamish Macdonald
- */
-
-#ifndef __ASM_M68K_PROCESSOR_H
-#define __ASM_M68K_PROCESSOR_H
-
-/*
- * Default implementation of macro that returns current
- * instruction pointer ("program counter").
- */
-#define current_text_addr() ({ __label__ _l; _l: &&_l;})
-
-#include <linux/thread_info.h>
-#include <asm/segment.h>
-#include <asm/fpu.h>
-#include <asm/ptrace.h>
-
-static inline unsigned long rdusp(void)
-{
- unsigned long usp;
-
- __asm__ __volatile__("move %/usp,%0" : "=a" (usp));
- return usp;
-}
-
-static inline void wrusp(unsigned long usp)
-{
- __asm__ __volatile__("move %0,%/usp" : : "a" (usp));
-}
-
-/*
- * User space process size: 3.75GB. This is hardcoded into a few places,
- * so don't change it unless you know what you are doing.
- */
-#ifndef CONFIG_SUN3
-#define TASK_SIZE (0xF0000000UL)
-#else
-#define TASK_SIZE (0x0E000000UL)
-#endif
-
-#ifdef __KERNEL__
-#define STACK_TOP TASK_SIZE
-#define STACK_TOP_MAX STACK_TOP
-#endif
-
-/* This decides where the kernel will search for a free chunk of vm
- * space during mmap's.
- */
-#ifndef CONFIG_SUN3
-#define TASK_UNMAPPED_BASE 0xC0000000UL
-#else
-#define TASK_UNMAPPED_BASE 0x0A000000UL
-#endif
-#define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr)
-
-struct thread_struct {
- unsigned long ksp; /* kernel stack pointer */
- unsigned long usp; /* user stack pointer */
- unsigned short sr; /* saved status register */
- unsigned short fs; /* saved fs (sfc, dfc) */
- unsigned long crp[2]; /* cpu root pointer */
- unsigned long esp0; /* points to SR of stack frame */
- unsigned long faddr; /* info about last fault */
- int signo, code;
- unsigned long fp[8*3];
- unsigned long fpcntl[3]; /* fp control regs */
- unsigned char fpstate[FPSTATESIZE]; /* floating point state */
- struct thread_info info;
-};
-
-#define INIT_THREAD { \
- .ksp = sizeof(init_stack) + (unsigned long) init_stack, \
- .sr = PS_S, \
- .fs = __KERNEL_DS, \
- .info = INIT_THREAD_INFO(init_task), \
-}
-
-/*
- * Do necessary setup to start up a newly executed thread.
- */
-static inline void start_thread(struct pt_regs * regs, unsigned long pc,
- unsigned long usp)
-{
- /* reads from user space */
- set_fs(USER_DS);
-
- regs->pc = pc;
- regs->sr &= ~0x2000;
- wrusp(usp);
-}
-
-/* Forward declaration, a strange C thing */
-struct task_struct;
-
-/* Free all resources held by a thread. */
-static inline void release_thread(struct task_struct *dead_task)
-{
-}
-
-/* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk) do { } while (0)
-
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
-/*
- * Free current thread data structures etc..
- */
-static inline void exit_thread(void)
-{
-}
-
-extern unsigned long thread_saved_pc(struct task_struct *tsk);
-
-unsigned long get_wchan(struct task_struct *p);
-
-#define KSTK_EIP(tsk) \
- ({ \
- unsigned long eip = 0; \
- if ((tsk)->thread.esp0 > PAGE_SIZE && \
- (virt_addr_valid((tsk)->thread.esp0))) \
- eip = ((struct pt_regs *) (tsk)->thread.esp0)->pc; \
- eip; })
-#define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp)
-
-#define cpu_relax() barrier()
-
-#endif
diff --git a/arch/m68k/include/asm/processor_no.h b/arch/m68k/include/asm/processor_no.h
deleted file mode 100644
index 91cba18acdd3..000000000000
--- a/arch/m68k/include/asm/processor_no.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * include/asm-m68knommu/processor.h
- *
- * Copyright (C) 1995 Hamish Macdonald
- */
-
-#ifndef __ASM_M68K_PROCESSOR_H
-#define __ASM_M68K_PROCESSOR_H
-
-/*
- * Default implementation of macro that returns current
- * instruction pointer ("program counter").
- */
-#define current_text_addr() ({ __label__ _l; _l: &&_l;})
-
-#include <linux/compiler.h>
-#include <linux/threads.h>
-#include <asm/types.h>
-#include <asm/segment.h>
-#include <asm/fpu.h>
-#include <asm/ptrace.h>
-#include <asm/current.h>
-
-static inline unsigned long rdusp(void)
-{
-#ifdef CONFIG_COLDFIRE
- extern unsigned int sw_usp;
- return(sw_usp);
-#else
- unsigned long usp;
- __asm__ __volatile__("move %/usp,%0" : "=a" (usp));
- return usp;
-#endif
-}
-
-static inline void wrusp(unsigned long usp)
-{
-#ifdef CONFIG_COLDFIRE
- extern unsigned int sw_usp;
- sw_usp = usp;
-#else
- __asm__ __volatile__("move %0,%/usp" : : "a" (usp));
-#endif
-}
-
-/*
- * User space process size: 3.75GB. This is hardcoded into a few places,
- * so don't change it unless you know what you are doing.
- */
-#define TASK_SIZE (0xF0000000UL)
-
-/*
- * This decides where the kernel will search for a free chunk of vm
- * space during mmap's. We won't be using it
- */
-#define TASK_UNMAPPED_BASE 0
-
-/*
- * if you change this structure, you must change the code and offsets
- * in m68k/machasm.S
- */
-
-struct thread_struct {
- unsigned long ksp; /* kernel stack pointer */
- unsigned long usp; /* user stack pointer */
- unsigned short sr; /* saved status register */
- unsigned short fs; /* saved fs (sfc, dfc) */
- unsigned long crp[2]; /* cpu root pointer */
- unsigned long esp0; /* points to SR of stack frame */
- unsigned long fp[8*3];
- unsigned long fpcntl[3]; /* fp control regs */
- unsigned char fpstate[FPSTATESIZE]; /* floating point state */
-};
-
-#define INIT_THREAD { \
- sizeof(init_stack) + (unsigned long) init_stack, 0, \
- PS_S, __KERNEL_DS, \
- {0, 0}, 0, {0,}, {0, 0, 0}, {0,}, \
-}
-
-/*
- * Coldfire stacks need to be re-aligned on trap exit, conventional
- * 68k can handle this case cleanly.
- */
-#if defined(CONFIG_COLDFIRE)
-#define reformat(_regs) do { (_regs)->format = 0x4; } while(0)
-#else
-#define reformat(_regs) do { } while (0)
-#endif
-
-/*
- * Do necessary setup to start up a newly executed thread.
- *
- * pass the data segment into user programs if it exists,
- * it can't hurt anything as far as I can tell
- */
-#define start_thread(_regs, _pc, _usp) \
-do { \
- set_fs(USER_DS); /* reads from user space */ \
- (_regs)->pc = (_pc); \
- ((struct switch_stack *)(_regs))[-1].a6 = 0; \
- reformat(_regs); \
- if (current->mm) \
- (_regs)->d5 = current->mm->start_data; \
- (_regs)->sr &= ~0x2000; \
- wrusp(_usp); \
-} while(0)
-
-/* Forward declaration, a strange C thing */
-struct task_struct;
-
-/* Free all resources held by a thread. */
-static inline void release_thread(struct task_struct *dead_task)
-{
-}
-
-/* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk) do { } while (0)
-
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
-/*
- * Free current thread data structures etc..
- */
-static inline void exit_thread(void)
-{
-}
-
-unsigned long thread_saved_pc(struct task_struct *tsk);
-unsigned long get_wchan(struct task_struct *p);
-
-#define KSTK_EIP(tsk) \
- ({ \
- unsigned long eip = 0; \
- if ((tsk)->thread.esp0 > PAGE_SIZE && \
- (virt_addr_valid((tsk)->thread.esp0))) \
- eip = ((struct pt_regs *) (tsk)->thread.esp0)->pc; \
- eip; })
-#define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp)
-
-#define cpu_relax() barrier()
-
-#endif
diff --git a/arch/m68k/include/asm/system_no.h b/arch/m68k/include/asm/system_no.h
index 4496c0aa8379..3c0718d74398 100644
--- a/arch/m68k/include/asm/system_no.h
+++ b/arch/m68k/include/asm/system_no.h
@@ -203,113 +203,6 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
#include <asm-generic/cmpxchg.h>
#endif
-#if defined( CONFIG_M68328 ) || defined( CONFIG_M68EZ328 ) || \
- defined (CONFIG_M68360) || defined( CONFIG_M68VZ328 )
-#define HARD_RESET_NOW() ({ \
- local_irq_disable(); \
- asm(" \
- moveal #0x10c00000, %a0; \
- moveb #0, 0xFFFFF300; \
- moveal 0(%a0), %sp; \
- moveal 4(%a0), %a0; \
- jmp (%a0); \
- "); \
-})
-#endif
-
-#ifdef CONFIG_COLDFIRE
-#if defined(CONFIG_M5272) && defined(CONFIG_NETtel)
-/*
- * Need to account for broken early mask of 5272 silicon. So don't
- * jump through the original start address. Jump strait into the
- * known start of the FLASH code.
- */
-#define HARD_RESET_NOW() ({ \
- asm(" \
- movew #0x2700, %sr; \
- jmp 0xf0000400; \
- "); \
-})
-#elif defined(CONFIG_NETtel) || \
- defined(CONFIG_SECUREEDGEMP3) || defined(CONFIG_CLEOPATRA)
-#define HARD_RESET_NOW() ({ \
- asm(" \
- movew #0x2700, %sr; \
- moveal #0x10000044, %a0; \
- movel #0xffffffff, (%a0); \
- moveal #0x10000001, %a0; \
- moveb #0x00, (%a0); \
- moveal #0xf0000004, %a0; \
- moveal (%a0), %a0; \
- jmp (%a0); \
- "); \
-})
-#elif defined(CONFIG_M5272)
-/*
- * Retrieve the boot address in flash using CSBR0 and CSOR0
- * find the reset vector at flash_address + 4 (e.g. 0x400)
- * remap it in the flash's current location (e.g. 0xf0000400)
- * and jump there.
- */
-#define HARD_RESET_NOW() ({ \
- asm(" \
- movew #0x2700, %%sr; \
- move.l %0+0x40,%%d0; \
- and.l %0+0x44,%%d0; \
- andi.l #0xfffff000,%%d0; \
- mov.l %%d0,%%a0; \
- or.l 4(%%a0),%%d0; \
- mov.l %%d0,%%a0; \
- jmp (%%a0);" \
- : /* No output */ \
- : "o" (*(char *)MCF_MBAR) ); \
-})
-#elif defined(CONFIG_M528x)
-/*
- * The MCF528x has a bit (SOFTRST) in memory (Reset Control Register RCR),
- * that when set, resets the MCF528x.
- */
-#define HARD_RESET_NOW() \
-({ \
- unsigned char volatile *reset; \
- asm("move.w #0x2700, %sr"); \
- reset = ((volatile unsigned char *)(MCF_IPSBAR + 0x110000)); \
- while(1) \
- *reset |= (0x01 << 7);\
-})
-#elif defined(CONFIG_M523x)
-#define HARD_RESET_NOW() ({ \
- asm(" \
- movew #0x2700, %sr; \
- movel #0x01000000, %sp; \
- moveal #0x40110000, %a0; \
- moveb #0x80, (%a0); \
- "); \
-})
-#elif defined(CONFIG_M520x)
- /*
- * The MCF5208 has a bit (SOFTRST) in memory (Reset Control Register
- * RCR), that when set, resets the MCF5208.
- */
-#define HARD_RESET_NOW() \
-({ \
- unsigned char volatile *reset; \
- asm("move.w #0x2700, %sr"); \
- reset = ((volatile unsigned char *)(MCF_IPSBAR + 0xA0000)); \
- while(1) \
- *reset |= 0x80; \
-})
-#else
-#define HARD_RESET_NOW() ({ \
- asm(" \
- movew #0x2700, %sr; \
- moveal #0x4, %a0; \
- moveal (%a0), %a0; \
- jmp (%a0); \
- "); \
-})
-#endif
-#endif
#define arch_align_stack(x) (x)
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h
index 3c19027331fa..aa29a8640f74 100644
--- a/arch/m68k/include/asm/unistd.h
+++ b/arch/m68k/include/asm/unistd.h
@@ -332,10 +332,12 @@
#define __NR_dup3 326
#define __NR_pipe2 327
#define __NR_inotify_init1 328
+#define __NR_preadv 329
+#define __NR_pwritev 330
#ifdef __KERNEL__
-#define NR_syscalls 329
+#define NR_syscalls 331
#define __ARCH_WANT_IPC_PARSE_VERSION
#define __ARCH_WANT_OLD_READDIR
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 5c332f2b9b83..8744f60c07a9 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -753,4 +753,6 @@ sys_call_table:
.long sys_dup3
.long sys_pipe2
.long sys_inotify_init1
+ .long sys_preadv
+ .long sys_pwritev /* 330 */
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S
index f513f530de91..86edb5fbcfc3 100644
--- a/arch/m68k/kernel/head.S
+++ b/arch/m68k/kernel/head.S
@@ -577,7 +577,7 @@ func_define putn,1
#endif
.endm
-.section ".text.head","ax"
+__HEAD
ENTRY(_stext)
/*
* Version numbers of the bootinfo interface
diff --git a/arch/m68k/kernel/sun3-head.S b/arch/m68k/kernel/sun3-head.S
index aad01592dbbc..43036bf4aeed 100644
--- a/arch/m68k/kernel/sun3-head.S
+++ b/arch/m68k/kernel/sun3-head.S
@@ -1,4 +1,5 @@
#include <linux/linkage.h>
+#include <linux/init.h>
#include <asm/entry.h>
#include <asm/page.h>
@@ -29,7 +30,7 @@ kernel_pmd_table: .skip 0x2000
.globl kernel_pg_dir
.equ kernel_pg_dir,kernel_pmd_table
- .section .text.head
+ __HEAD
ENTRY(_stext)
ENTRY(_start)
diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds
index f846d4e3e5e1..01d212bb05a6 100644
--- a/arch/m68k/kernel/vmlinux-std.lds
+++ b/arch/m68k/kernel/vmlinux-std.lds
@@ -12,7 +12,7 @@ SECTIONS
. = 0x1000;
_text = .; /* Text and read-only data */
.text : {
- *(.text.head)
+ HEAD_TEXT
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds
index d9368c0709ba..c192f773db96 100644
--- a/arch/m68k/kernel/vmlinux-sun3.lds
+++ b/arch/m68k/kernel/vmlinux-sun3.lds
@@ -12,7 +12,7 @@ SECTIONS
. = 0xE002000;
_text = .; /* Text and read-only data */
.text : {
- *(.text.head)
+ HEAD_TEXT
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index 4beb59dfc6ec..534376299a99 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -16,6 +16,7 @@ config MMU
config NO_DMA
bool
+ depends on !COLDFIRE
default y
config FPU
diff --git a/arch/m68knommu/configs/m5208evb_defconfig b/arch/m68knommu/configs/m5208evb_defconfig
index 6fae33a05e2a..854a4f333b2f 100644
--- a/arch/m68knommu/configs/m5208evb_defconfig
+++ b/arch/m68knommu/configs/m5208evb_defconfig
@@ -1,6 +1,6 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26-rc1
+# Linux kernel version: 2.6.30-rc2
#
CONFIG_M68K=y
# CONFIG_MMU is not set
@@ -15,9 +15,10 @@ CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_TIME_LOW_RES=y
+CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_NO_IOPORT=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -33,53 +34,55 @@ CONFIG_LOCALVERSION_AUTO=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES 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_UID16 is not set
-# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
# CONFIG_KALLSYMS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-# CONFIG_COMPAT_BRK is not set
CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_SIGNALFD is not set
# CONFIG_TIMERFD is not set
# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
# CONFIG_VM_EVENT_COUNTERS is not set
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
-# CONFIG_HAVE_OPROFILE is not set
-# CONFIG_HAVE_KPROBES is not set
-# CONFIG_HAVE_KRETPROBES is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-CONFIG_SLABINFO=y
-CONFIG_TINY_SHMEM=y
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT 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 is not set
+# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -93,7 +96,7 @@ CONFIG_IOSCHED_NOOP=y
# CONFIG_DEFAULT_CFQ is not set
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
-CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Processor type and features
@@ -145,44 +148,39 @@ CONFIG_RAM16BIT=y
# CONFIG_ROM is not set
CONFIG_RAMKERNEL=y
# CONFIG_ROMKERNEL is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
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_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_VIRT_TO_BUS=y
+# CONFIG_UNEVICTABLE_LRU is not set
CONFIG_ISA_DMA_API=y
#
-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
-#
-# CONFIG_PCI is not set
-# CONFIG_ARCH_SUPPORTS_MSI is not set
-
-#
# Executable file formats
#
CONFIG_BINFMT_FLAT=y
# CONFIG_BINFMT_ZFLAT is not set
# CONFIG_BINFMT_SHARED_FLAT is not set
-# CONFIG_BINFMT_AOUT is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
# Power management options
#
# CONFIG_PM is not set
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -223,6 +221,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -232,7 +231,9 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -243,14 +244,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# 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_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -289,10 +284,8 @@ CONFIG_MTD_BLOCK=y
#
# RAM/ROM/Flash chip drivers
#
-CONFIG_MTD_CFI=y
+# CONFIG_MTD_CFI is not set
# 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
@@ -303,10 +296,6 @@ 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=y
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
CONFIG_MTD_RAM=y
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
@@ -315,7 +304,6 @@ CONFIG_MTD_RAM=y
# Mapping drivers for chip access
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
CONFIG_MTD_UCLINUX=y
# CONFIG_MTD_PLATRAM is not set
@@ -337,6 +325,11 @@ CONFIG_MTD_UCLINUX=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -351,6 +344,7 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
# CONFIG_MISC_DEVICES is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -364,7 +358,7 @@ CONFIG_HAVE_IDE=y
# CONFIG_SCSI_NETLINK is not set
# CONFIG_MD is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -374,10 +368,15 @@ CONFIG_NETDEVICES=y
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
CONFIG_FEC=y
# CONFIG_FEC2 is not set
@@ -389,8 +388,10 @@ CONFIG_FEC=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -415,7 +416,7 @@ CONFIG_FEC=y
# Character devices
#
# CONFIG_VT is not set
-# CONFIG_DEVKMEM is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -428,7 +429,6 @@ CONFIG_FEC=y
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_COLDFIRE is not set
CONFIG_SERIAL_MCF=y
CONFIG_SERIAL_MCF_BAUDRATE=115200
CONFIG_SERIAL_MCF_CONSOLE=y
@@ -447,19 +447,23 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -470,11 +474,12 @@ CONFIG_SSB_POSSIBLE=y
#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
#
# Multimedia drivers
#
-# CONFIG_DAB is not set
+CONFIG_DAB=y
#
# Graphics support
@@ -488,10 +493,6 @@ CONFIG_SSB_POSSIBLE=y
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
@@ -499,7 +500,10 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_NEW_LEDS is not set
# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
@@ -507,11 +511,13 @@ CONFIG_SSB_POSSIBLE=y
CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_FILE_LOCKING is not set
# CONFIG_XFS_FS is not set
+# CONFIG_BTRFS_FS is not set
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY is not set
# CONFIG_QUOTA is not set
@@ -520,6 +526,11 @@ CONFIG_EXT2_FS=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -540,10 +551,7 @@ CONFIG_PROC_SYSCTL=y
# CONFIG_SYSFS is not set
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -553,13 +561,20 @@ CONFIG_PROC_SYSCTL=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
CONFIG_ROMFS_FS=y
+# CONFIG_ROMFS_BACKED_BY_BLOCK is not set
+CONFIG_ROMFS_BACKED_BY_MTD=y
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_MTD=y
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
# CONFIG_NETWORK_FILESYSTEMS is not set
#
@@ -581,10 +596,14 @@ CONFIG_FRAME_WARN=1024
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
# CONFIG_SAMPLES is not set
CONFIG_FULLDEBUG=y
# CONFIG_HIGHPROFILE is not set
-# CONFIG_BOOTPARAM is not set
+CONFIG_BOOTPARAM=y
+CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
# CONFIG_NO_KERNEL_MSG is not set
# CONFIG_BDM_DISABLE is not set
@@ -592,19 +611,23 @@ CONFIG_FULLDEBUG=y
# Security options
#
# CONFIG_KEYS is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
# CONFIG_LIBCRC32C is not set
CONFIG_HAS_IOMEM=y
CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/m68knommu/configs/m5249evb_defconfig b/arch/m68knommu/configs/m5249evb_defconfig
index cc6458333d67..2efba32e33a0 100644
--- a/arch/m68knommu/configs/m5249evb_defconfig
+++ b/arch/m68knommu/configs/m5249evb_defconfig
@@ -1,6 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26-rc1
+# Linux kernel version: 2.6.30-rc2
+# Wed Apr 22 17:32:41 2009
#
CONFIG_M68K=y
# CONFIG_MMU is not set
@@ -15,9 +16,10 @@ CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_TIME_LOW_RES=y
+# CONFIG_GENERIC_CLOCKEVENTS is not set
CONFIG_NO_IOPORT=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -29,11 +31,23 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
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_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
@@ -41,44 +55,37 @@ CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
-# CONFIG_UID16 is not set
-# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
# CONFIG_KALLSYMS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-# CONFIG_COMPAT_BRK is not set
CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_SIGNALFD is not set
# CONFIG_TIMERFD is not set
# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
# CONFIG_VM_EVENT_COUNTERS is not set
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
-# CONFIG_HAVE_OPROFILE is not set
-# CONFIG_HAVE_KPROBES is not set
-# CONFIG_HAVE_KRETPROBES is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-CONFIG_SLABINFO=y
-CONFIG_TINY_SHMEM=y
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT 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 is not set
+# CONFIG_MODULES 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
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -92,7 +99,7 @@ CONFIG_IOSCHED_NOOP=y
# CONFIG_DEFAULT_CFQ is not set
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
-CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Processor type and features
@@ -144,45 +151,103 @@ CONFIG_RAMAUTOBIT=y
# CONFIG_ROM is not set
CONFIG_RAMKERNEL=y
# CONFIG_ROMKERNEL is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_VIRT_TO_BUS=y
+# CONFIG_UNEVICTABLE_LRU is not set
CONFIG_ISA_DMA_API=y
#
-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
-#
-# CONFIG_PCI is not set
-# CONFIG_ARCH_SUPPORTS_MSI is not set
-
-#
# Executable file formats
#
CONFIG_BINFMT_FLAT=y
# CONFIG_BINFMT_ZFLAT is not set
# CONFIG_BINFMT_SHARED_FLAT is not set
-# CONFIG_BINFMT_AOUT is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
# Power management options
#
# CONFIG_PM is not set
-
-#
-# Networking
-#
-# CONFIG_NET is not set
+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 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 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_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
#
# Device Drivers
@@ -194,6 +259,7 @@ CONFIG_BINFMT_FLAT=y
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=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
@@ -259,6 +325,11 @@ CONFIG_MTD_UCLINUX=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -266,14 +337,15 @@ CONFIG_MTD_UCLINUX=y
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_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
-CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
-# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_MISC_DEVICES is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -285,6 +357,56 @@ CONFIG_HAVE_IDE=y
# CONFIG_SCSI_DMA is not set
# CONFIG_SCSI_NETLINK is not set
# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
+# 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 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_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
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# 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_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
# CONFIG_PHONE is not set
#
@@ -302,7 +424,7 @@ CONFIG_HAVE_IDE=y
# Character devices
#
# CONFIG_VT is not set
-# CONFIG_DEVKMEM is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -315,7 +437,6 @@ CONFIG_HAVE_IDE=y
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_COLDFIRE is not set
CONFIG_SERIAL_MCF=y
CONFIG_SERIAL_MCF_BAUDRATE=19200
CONFIG_SERIAL_MCF_CONSOLE=y
@@ -323,7 +444,8 @@ CONFIG_SERIAL_MCF_CONSOLE=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
-# CONFIG_HW_RANDOM is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
# CONFIG_GEN_RTC is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
@@ -334,19 +456,23 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -356,11 +482,13 @@ CONFIG_SSB_POSSIBLE=y
# Multimedia core support
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
#
# Multimedia drivers
#
-# CONFIG_DAB is not set
+CONFIG_DAB=y
#
# Graphics support
@@ -374,10 +502,6 @@ CONFIG_SSB_POSSIBLE=y
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
@@ -385,7 +509,10 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_NEW_LEDS is not set
# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
@@ -393,19 +520,28 @@ CONFIG_SSB_POSSIBLE=y
CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_FILE_LOCKING is not set
# CONFIG_XFS_FS is not set
-# CONFIG_DNOTIFY is not set
-# CONFIG_INOTIFY is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -427,10 +563,7 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -440,13 +573,21 @@ CONFIG_SYSFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
CONFIG_ROMFS_FS=y
+# CONFIG_ROMFS_BACKED_BY_BLOCK is not set
+CONFIG_ROMFS_BACKED_BY_MTD=y
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_MTD=y
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
#
# Partition Types
@@ -454,6 +595,7 @@ CONFIG_ROMFS_FS=y
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
+# CONFIG_DLM is not set
#
# Kernel hacking
@@ -468,10 +610,14 @@ CONFIG_FRAME_WARN=1024
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
# CONFIG_SAMPLES is not set
# CONFIG_FULLDEBUG is not set
# CONFIG_HIGHPROFILE is not set
-# CONFIG_BOOTPARAM is not set
+CONFIG_BOOTPARAM=y
+CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
# CONFIG_NO_KERNEL_MSG is not set
# CONFIG_BDM_DISABLE is not set
@@ -480,18 +626,22 @@ CONFIG_FRAME_WARN=1024
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T 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
+CONFIG_NLATTR=y
diff --git a/arch/arm/configs/pcm037_defconfig b/arch/m68knommu/configs/m5272c3_defconfig
index 6e37c77c4760..f37852a34218 100644
--- a/arch/arm/configs/pcm037_defconfig
+++ b/arch/m68knommu/configs/m5272c3_defconfig
@@ -1,30 +1,25 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26-rc6
-# Wed Jun 25 11:52:42 2008
+# Linux kernel version: 2.6.30-rc2
+# Wed Apr 22 17:17:30 2009
#
-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_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_ARCH_SUPPORTS_AOUT=y
-CONFIG_ZONE_DMA=y
-CONFIG_ARCH_MTD_XIP=y
-CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_TIME_LOW_RES=y
+# CONFIG_GENERIC_CLOCKEVENTS is not set
+CONFIG_NO_IOPORT=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -32,248 +27,166 @@ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
-CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_SYSVIPC is not set
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_GROUP_SCHED=y
-CONFIG_FAIR_GROUP_SCHED=y
-# CONFIG_RT_GROUP_SCHED is not set
-CONFIG_USER_SCHED=y
-# CONFIG_CGROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
-CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
-CONFIG_SHMEM=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
-CONFIG_HAVE_OPROFILE=y
-# CONFIG_KPROBES is not set
-CONFIG_HAVE_KPROBES=y
-CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_DMA_ATTRS is not set
-CONFIG_PROC_PAGE_MONITOR=y
-CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_BASE_SMALL=0
-CONFIG_MODULES=y
-# CONFIG_MODULE_FORCE_LOAD is not set
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
+# CONFIG_MODULES 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
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
#
CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
# 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"
-CONFIG_CLASSIC_RCU=y
-
-#
-# 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=y
-# CONFIG_ARCH_ORION5X 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 is not set
-# CONFIG_ARCH_MSM7X00A is not set
-
-#
-# Boot options
-#
-
-#
-# Power management
-#
-
-#
-# Freescale MXC Implementations
-#
-CONFIG_ARCH_MX3=y
-
-#
-# MX3 Options
-#
-# CONFIG_MACH_MX31ADS is not set
-CONFIG_MACH_PCM037=y
-
-#
-# Processor Type
-#
-CONFIG_CPU_32=y
-CONFIG_CPU_V6=y
-# CONFIG_CPU_32v6K is not set
-CONFIG_CPU_32v6=y
-CONFIG_CPU_ABRT_EV6=y
-CONFIG_CPU_PABRT_NOIFAR=y
-CONFIG_CPU_CACHE_V6=y
-CONFIG_CPU_CACHE_VIPT=y
-CONFIG_CPU_COPY_V6=y
-CONFIG_CPU_TLB_V6=y
-CONFIG_CPU_HAS_ASID=y
-CONFIG_CPU_CP15=y
-CONFIG_CPU_CP15_MMU=y
-
-#
-# Processor Features
-#
-CONFIG_ARM_THUMB=y
-# CONFIG_CPU_ICACHE_DISABLE is not set
-# CONFIG_CPU_DCACHE_DISABLE is not set
-# CONFIG_CPU_BPREDICT_DISABLE is not set
-# CONFIG_OUTER_CACHE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+# CONFIG_FREEZER is not set
+
+#
+# Processor type and features
+#
+# CONFIG_M68328 is not set
+# CONFIG_M68EZ328 is not set
+# CONFIG_M68VZ328 is not set
+# CONFIG_M68360 is not set
+# CONFIG_M5206 is not set
+# CONFIG_M5206e is not set
+# CONFIG_M520x is not set
+# CONFIG_M523x is not set
+# CONFIG_M5249 is not set
+# CONFIG_M5271 is not set
+CONFIG_M5272=y
+# CONFIG_M5275 is not set
+# CONFIG_M528x is not set
+# CONFIG_M5307 is not set
+# CONFIG_M532x is not set
+# CONFIG_M5407 is not set
+CONFIG_COLDFIRE=y
+CONFIG_CLOCK_SET=y
+CONFIG_CLOCK_FREQ=66666666
+CONFIG_CLOCK_DIV=1
+
+#
+# Platform
+#
+# CONFIG_UC5272 is not set
+CONFIG_M5272C3=y
+# CONFIG_COBRA5272 is not set
+# CONFIG_CANCam is not set
+# CONFIG_SCALES is not set
+# CONFIG_NETtel is not set
+# CONFIG_CPU16B is not set
+# CONFIG_MOD5272 is not set
+CONFIG_FREESCALE=y
+CONFIG_4KSTACKS=y
+CONFIG_HZ=100
#
-# Bus support
+# RAM configuration
#
-# CONFIG_PCI_SYSCALL is not set
-# CONFIG_ARCH_SUPPORTS_MSI is not set
-# CONFIG_PCCARD is not set
+CONFIG_RAMBASE=0x00000000
+CONFIG_RAMSIZE=0x00800000
+CONFIG_VECTORBASE=0x00000000
+CONFIG_KERNELBASE=0x00020000
+CONFIG_RAMAUTOBIT=y
+# CONFIG_RAM8BIT is not set
+# CONFIG_RAM16BIT is not set
+# CONFIG_RAM32BIT is not set
#
-# Kernel Features
+# ROM configuration
#
-CONFIG_TICK_ONESHOT=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
-CONFIG_PREEMPT=y
-CONFIG_HZ=100
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+# CONFIG_ROM is not set
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_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="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw ip=off"
-# CONFIG_XIP_KERNEL is not set
-# CONFIG_KEXEC is not set
+# CONFIG_UNEVICTABLE_LRU is not set
#
-# Floating point emulation
+# Executable file formats
#
-
-#
-# At least one emulation must be selected
-#
-CONFIG_VFP=y
-
-#
-# Userspace binary formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_FLAT=y
+# CONFIG_BINFMT_ZFLAT is not set
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
# Power management options
#
# CONFIG_PM is not set
-CONFIG_ARCH_SUSPEND_POSSIBLE=y
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -287,10 +200,7 @@ 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 is not set
-# CONFIG_IP_PNP_RARP is not set
+# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_ARPD is not set
@@ -317,6 +227,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -326,7 +237,9 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -337,14 +250,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# 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_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -355,10 +262,8 @@ 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=m
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
CONFIG_MTD=y
@@ -366,8 +271,7 @@ CONFIG_MTD=y
# 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
+# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_AR7_PARTS is not set
#
@@ -386,13 +290,8 @@ CONFIG_MTD_BLOCK=y
#
# RAM/ROM/Flash chip drivers
#
-CONFIG_MTD_CFI=y
+# CONFIG_MTD_CFI is not set
# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-# CONFIG_MTD_CFI_NOSWAP is not set
-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
CONFIG_MTD_MAP_BANK_WIDTH_1=y
CONFIG_MTD_MAP_BANK_WIDTH_2=y
CONFIG_MTD_MAP_BANK_WIDTH_4=y
@@ -403,10 +302,7 @@ 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_RAM is not set
+CONFIG_MTD_RAM=y
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
@@ -414,11 +310,7 @@ CONFIG_MTD_CFI_I2=y
# Mapping drivers for chip access
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x0
-CONFIG_MTD_PHYSMAP_LEN=0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
-# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_UCLINUX=y
# CONFIG_MTD_PLATRAM is not set
#
@@ -439,11 +331,26 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
# CONFIG_PARPORT is not set
-# CONFIG_BLK_DEV is not set
+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_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
# CONFIG_MISC_DEVICES is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -455,48 +362,30 @@ CONFIG_HAVE_IDE=y
# 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_COMPAT_NET_DEV_OPS=y
# 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=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=y
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_ICPLUS_PHY is not set
-# CONFIG_REALTEK_PHY is not set
-# CONFIG_NATIONAL_PHY is not set
-# CONFIG_STE10XP is not set
-# CONFIG_LSI_ET1011C_PHY is not set
-# CONFIG_FIXED_PHY is not set
-# CONFIG_MDIO_BITBANG is not set
+# CONFIG_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_SMSC911X=y
+# CONFIG_MII is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
+CONFIG_FEC=y
+# CONFIG_FEC2 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -505,7 +394,10 @@ CONFIG_SMSC911X=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -513,6 +405,7 @@ CONFIG_SMSC911X=y
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
#
# Input device support
@@ -540,51 +433,44 @@ CONFIG_DEVKMEM=y
#
# Non-8250 serial port support
#
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MCF=y
+CONFIG_SERIAL_MCF_BAUDRATE=19200
+CONFIG_SERIAL_MCF_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_NVRAM is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_GEN_RTC 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
# CONFIG_SPI is not set
-CONFIG_HAVE_GPIO_LIB=y
-
-#
-# GPIO Support
-#
-
-#
-# I2C GPIO expanders:
-#
-
-#
-# SPI GPIO expanders:
-#
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
-# CONFIG_MFD_ASIC3 is not set
-# CONFIG_HTC_EGPIO is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -600,7 +486,7 @@ CONFIG_SSB_POSSIBLE=y
#
# Multimedia drivers
#
-# CONFIG_DAB is not set
+CONFIG_DAB=y
#
# Graphics support
@@ -614,38 +500,45 @@ CONFIG_SSB_POSSIBLE=y
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
-CONFIG_RTC_LIB=y
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
#
-# CONFIG_EXT2_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_FILE_LOCKING is not set
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
# CONFIG_DNOTIFY is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
+# CONFIG_INOTIFY is not set
# CONFIG_QUOTA is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -664,14 +557,10 @@ CONFIG_INOTIFY_USER=y
CONFIG_PROC_FS=y
CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -679,42 +568,23 @@ CONFIG_TMPFS=y
# 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_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_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_ROMFS_BACKED_BY_BLOCK is not set
+CONFIG_ROMFS_BACKED_BY_MTD=y
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_MTD=y
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-CONFIG_NETWORK_FILESYSTEMS=y
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=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
+# CONFIG_NILFS2_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
#
# Partition Types
@@ -728,8 +598,8 @@ CONFIG_MSDOS_PARTITION=y
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
CONFIG_FRAME_WARN=1024
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
@@ -737,33 +607,39 @@ CONFIG_FRAME_WARN=1024
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
# CONFIG_SAMPLES is not set
-# CONFIG_DEBUG_USER is not set
+# CONFIG_FULLDEBUG is not set
+# CONFIG_HIGHPROFILE is not set
+CONFIG_BOOTPARAM=y
+CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
+# CONFIG_NO_KERNEL_MSG is not set
+# CONFIG_BDM_DISABLE is not set
#
# Security options
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T 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
+CONFIG_NLATTR=y
diff --git a/arch/m68knommu/configs/m5275evb_defconfig b/arch/m68knommu/configs/m5275evb_defconfig
index 0d1256f5addb..dc5c621d419c 100644
--- a/arch/m68knommu/configs/m5275evb_defconfig
+++ b/arch/m68knommu/configs/m5275evb_defconfig
@@ -1,6 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26-rc1
+# Linux kernel version: 2.6.30-rc2
+# Wed Apr 22 23:29:01 2009
#
CONFIG_M68K=y
# CONFIG_MMU is not set
@@ -15,9 +16,10 @@ CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_TIME_LOW_RES=y
+CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_NO_IOPORT=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -33,10 +35,19 @@ CONFIG_LOCALVERSION_AUTO=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
@@ -44,44 +55,37 @@ CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
-# CONFIG_UID16 is not set
-# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
# CONFIG_KALLSYMS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-# CONFIG_COMPAT_BRK is not set
CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_SIGNALFD is not set
# CONFIG_TIMERFD is not set
# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
# CONFIG_VM_EVENT_COUNTERS is not set
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
-# CONFIG_HAVE_OPROFILE is not set
-# CONFIG_HAVE_KPROBES is not set
-# CONFIG_HAVE_KRETPROBES is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-CONFIG_SLABINFO=y
-CONFIG_TINY_SHMEM=y
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT 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 is not set
+# CONFIG_MODULES 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
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -95,7 +99,7 @@ CONFIG_IOSCHED_NOOP=y
# CONFIG_DEFAULT_CFQ is not set
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
-CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Processor type and features
@@ -148,44 +152,39 @@ CONFIG_RAMAUTOBIT=y
# CONFIG_ROM is not set
CONFIG_RAMKERNEL=y
# CONFIG_ROMKERNEL is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
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_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_VIRT_TO_BUS=y
+# CONFIG_UNEVICTABLE_LRU is not set
CONFIG_ISA_DMA_API=y
#
-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
-#
-# CONFIG_PCI is not set
-# CONFIG_ARCH_SUPPORTS_MSI is not set
-
-#
# Executable file formats
#
CONFIG_BINFMT_FLAT=y
# CONFIG_BINFMT_ZFLAT is not set
# CONFIG_BINFMT_SHARED_FLAT is not set
-# CONFIG_BINFMT_AOUT is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
# Power management options
#
# CONFIG_PM is not set
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -226,6 +225,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -235,7 +235,9 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -246,14 +248,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# 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_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -333,6 +329,11 @@ CONFIG_MTD_UCLINUX=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -347,6 +348,7 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
# CONFIG_MISC_DEVICES is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -360,7 +362,7 @@ CONFIG_HAVE_IDE=y
# CONFIG_SCSI_NETLINK is not set
# CONFIG_MD is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -370,10 +372,15 @@ CONFIG_NETDEVICES=y
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
CONFIG_FEC=y
CONFIG_FEC2=y
@@ -385,8 +392,10 @@ CONFIG_FEC2=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
CONFIG_PPP=y
# CONFIG_PPP_MULTILINK is not set
@@ -421,7 +430,7 @@ CONFIG_SLHC=y
# Character devices
#
# CONFIG_VT is not set
-# CONFIG_DEVKMEM is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -434,7 +443,6 @@ CONFIG_SLHC=y
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_COLDFIRE is not set
CONFIG_SERIAL_MCF=y
CONFIG_SERIAL_MCF_BAUDRATE=19200
CONFIG_SERIAL_MCF_CONSOLE=y
@@ -442,7 +450,8 @@ CONFIG_SERIAL_MCF_CONSOLE=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
-# CONFIG_HW_RANDOM is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
# CONFIG_GEN_RTC is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
@@ -453,19 +462,23 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -476,6 +489,7 @@ CONFIG_SSB_POSSIBLE=y
#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
#
# Multimedia drivers
@@ -494,10 +508,6 @@ CONFIG_DAB=y
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
@@ -505,7 +515,10 @@ CONFIG_DAB=y
# CONFIG_NEW_LEDS is not set
# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
@@ -513,12 +526,14 @@ CONFIG_DAB=y
CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_FILE_LOCKING is not set
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY is not set
# CONFIG_QUOTA is not set
@@ -527,6 +542,11 @@ CONFIG_EXT2_FS=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -548,10 +568,7 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -561,21 +578,21 @@ CONFIG_SYSFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
CONFIG_ROMFS_FS=y
+# CONFIG_ROMFS_BACKED_BY_BLOCK is not set
+CONFIG_ROMFS_BACKED_BY_MTD=y
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_MTD=y
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-CONFIG_NETWORK_FILESYSTEMS=y
-# CONFIG_NFS_FS is not set
-# CONFIG_NFSD 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
+# CONFIG_NILFS2_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
#
# Partition Types
@@ -598,10 +615,14 @@ CONFIG_FRAME_WARN=1024
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
# CONFIG_SAMPLES is not set
# CONFIG_FULLDEBUG is not set
# CONFIG_HIGHPROFILE is not set
-# CONFIG_BOOTPARAM is not set
+CONFIG_BOOTPARAM=y
+CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
# CONFIG_NO_KERNEL_MSG is not set
# CONFIG_BDM_DISABLE is not set
@@ -610,18 +631,22 @@ CONFIG_FRAME_WARN=1024
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T 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
+CONFIG_NLATTR=y
diff --git a/arch/m68knommu/configs/m5307c3_defconfig b/arch/m68knommu/configs/m5307c3_defconfig
index fe2acdfa4d76..3a3f6733ae43 100644
--- a/arch/m68knommu/configs/m5307c3_defconfig
+++ b/arch/m68knommu/configs/m5307c3_defconfig
@@ -1,6 +1,6 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26-rc1
+# Linux kernel version: 2.6.30-rc2
#
CONFIG_M68K=y
# CONFIG_MMU is not set
@@ -15,9 +15,10 @@ CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_TIME_LOW_RES=y
+# CONFIG_GENERIC_CLOCKEVENTS is not set
CONFIG_NO_IOPORT=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -33,10 +34,21 @@ CONFIG_LOCALVERSION_AUTO=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_USER_SCHED is not set
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
@@ -44,44 +56,37 @@ CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
-# CONFIG_UID16 is not set
-# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
# CONFIG_KALLSYMS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-# CONFIG_COMPAT_BRK is not set
CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_SIGNALFD is not set
# CONFIG_TIMERFD is not set
# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
# CONFIG_VM_EVENT_COUNTERS is not set
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
-# CONFIG_HAVE_OPROFILE is not set
-# CONFIG_HAVE_KPROBES is not set
-# CONFIG_HAVE_KRETPROBES is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-CONFIG_SLABINFO=y
-CONFIG_TINY_SHMEM=y
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT 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 is not set
+# CONFIG_MODULES 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
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -95,7 +100,7 @@ CONFIG_IOSCHED_NOOP=y
# CONFIG_DEFAULT_CFQ is not set
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
-CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Processor type and features
@@ -127,12 +132,11 @@ CONFIG_CLOCK_DIV=2
#
# CONFIG_ARN5307 is not set
CONFIG_M5307C3=y
-# CONFIG_eLIA is not set
# CONFIG_SECUREEDGEMP3 is not set
# CONFIG_CLEOPATRA is not set
# CONFIG_NETtel is not set
CONFIG_FREESCALE=y
-# CONFIG_4KSTACKS is not set
+CONFIG_4KSTACKS=y
CONFIG_HZ=100
#
@@ -153,45 +157,36 @@ CONFIG_RAMAUTOBIT=y
# CONFIG_ROM is not set
CONFIG_RAMKERNEL=y
# CONFIG_ROMKERNEL is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_VIRT_TO_BUS=y
+# CONFIG_UNEVICTABLE_LRU is not set
CONFIG_ISA_DMA_API=y
#
-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
-#
-# CONFIG_PCI is not set
-# CONFIG_COMEMPCI is not set
-# CONFIG_ARCH_SUPPORTS_MSI is not set
-
-#
# Executable file formats
#
CONFIG_BINFMT_FLAT=y
# CONFIG_BINFMT_ZFLAT is not set
# CONFIG_BINFMT_SHARED_FLAT is not set
-# CONFIG_BINFMT_AOUT is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
# Power management options
#
# CONFIG_PM is not set
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -232,6 +227,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -241,7 +237,9 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -252,14 +250,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# 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_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -274,7 +266,79 @@ CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
-# CONFIG_MTD 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
+# CONFIG_MTD_AR7_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
+# CONFIG_MTD_OOPS 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=y
+# 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_UCLINUX=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
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR 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
@@ -286,6 +350,7 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
# CONFIG_MISC_DEVICES is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -299,7 +364,7 @@ CONFIG_HAVE_IDE=y
# CONFIG_SCSI_NETLINK is not set
# CONFIG_MD is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -309,10 +374,15 @@ CONFIG_NETDEVICES=y
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -322,8 +392,10 @@ CONFIG_NET_ETHERNET=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
CONFIG_PPP=y
# CONFIG_PPP_MULTILINK is not set
@@ -381,7 +453,7 @@ CONFIG_INPUT=y
# Character devices
#
# CONFIG_VT is not set
-# CONFIG_DEVKMEM is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -394,13 +466,12 @@ CONFIG_INPUT=y
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_COLDFIRE is not set
CONFIG_SERIAL_MCF=y
CONFIG_SERIAL_MCF_BAUDRATE=19200
CONFIG_SERIAL_MCF_CONSOLE=y
CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_GEN_RTC is not set
@@ -413,19 +484,23 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -436,6 +511,7 @@ CONFIG_SSB_POSSIBLE=y
#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
#
# Multimedia drivers
@@ -454,10 +530,6 @@ CONFIG_DAB=y
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
# CONFIG_HID_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
@@ -466,7 +538,10 @@ CONFIG_DAB=y
# CONFIG_NEW_LEDS is not set
# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
@@ -474,12 +549,14 @@ CONFIG_DAB=y
CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY is not set
# CONFIG_QUOTA is not set
@@ -488,6 +565,11 @@ CONFIG_EXT2_FS=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -509,10 +591,7 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -520,14 +599,22 @@ CONFIG_SYSFS=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_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
CONFIG_ROMFS_FS=y
+# CONFIG_ROMFS_BACKED_BY_BLOCK is not set
+CONFIG_ROMFS_BACKED_BY_MTD=y
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_MTD=y
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
# CONFIG_NETWORK_FILESYSTEMS is not set
#
@@ -551,10 +638,14 @@ CONFIG_FRAME_WARN=1024
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
# CONFIG_SAMPLES is not set
CONFIG_FULLDEBUG=y
# CONFIG_HIGHPROFILE is not set
-# CONFIG_BOOTPARAM is not set
+CONFIG_BOOTPARAM=y
+CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
# CONFIG_NO_KERNEL_MSG is not set
# CONFIG_BDM_DISABLE is not set
@@ -563,18 +654,22 @@ CONFIG_FULLDEBUG=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T 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
+CONFIG_NLATTR=y
diff --git a/arch/m68knommu/configs/m5407c3_defconfig b/arch/m68knommu/configs/m5407c3_defconfig
index 1118936d20e3..97b6cde2fc19 100644
--- a/arch/m68knommu/configs/m5407c3_defconfig
+++ b/arch/m68knommu/configs/m5407c3_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26-rc1
-# Wed May 7 10:25:16 2008
+# Linux kernel version: 2.6.30-rc2
+# Thu Apr 23 09:21:40 2009
#
CONFIG_M68K=y
# CONFIG_MMU is not set
@@ -16,9 +16,10 @@ CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_TIME_LOW_RES=y
+# CONFIG_GENERIC_CLOCKEVENTS is not set
CONFIG_NO_IOPORT=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -34,10 +35,19 @@ CONFIG_LOCALVERSION_AUTO=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
@@ -45,44 +55,43 @@ CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
-# CONFIG_UID16 is not set
-# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
# CONFIG_KALLSYMS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-# CONFIG_COMPAT_BRK is not set
CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_SIGNALFD is not set
# CONFIG_TIMERFD is not set
# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
# CONFIG_VM_EVENT_COUNTERS is not set
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
-# CONFIG_HAVE_OPROFILE is not set
-# CONFIG_HAVE_KPROBES is not set
-# CONFIG_HAVE_KRETPROBES is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
-CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS 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
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -96,7 +105,7 @@ CONFIG_IOSCHED_NOOP=y
# CONFIG_DEFAULT_CFQ is not set
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
-CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Processor type and features
@@ -149,45 +158,36 @@ CONFIG_RAMAUTOBIT=y
# CONFIG_ROM is not set
CONFIG_RAMKERNEL=y
# CONFIG_ROMKERNEL is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_VIRT_TO_BUS=y
+# CONFIG_UNEVICTABLE_LRU is not set
CONFIG_ISA_DMA_API=y
#
-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
-#
-# CONFIG_PCI is not set
-# CONFIG_COMEMPCI is not set
-# CONFIG_ARCH_SUPPORTS_MSI is not set
-
-#
# Executable file formats
#
CONFIG_BINFMT_FLAT=y
# CONFIG_BINFMT_ZFLAT is not set
# CONFIG_BINFMT_SHARED_FLAT is not set
-# CONFIG_BINFMT_AOUT is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
# Power management options
#
# CONFIG_PM is not set
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -228,6 +228,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -237,7 +238,9 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -248,14 +251,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# 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_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -274,6 +271,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_AR7_PARTS is not set
@@ -335,6 +333,11 @@ CONFIG_MTD_UCLINUX=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -349,6 +352,7 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
# CONFIG_MISC_DEVICES is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -362,7 +366,7 @@ CONFIG_HAVE_IDE=y
# CONFIG_SCSI_NETLINK is not set
# CONFIG_MD is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -372,10 +376,15 @@ CONFIG_NETDEVICES=y
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -385,8 +394,10 @@ CONFIG_NET_ETHERNET=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
CONFIG_PPP=y
# CONFIG_PPP_MULTILINK is not set
@@ -409,39 +420,22 @@ CONFIG_SLHC=y
#
# 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_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
+# CONFIG_INPUT is not set
#
# Hardware I/O ports
#
-# CONFIG_SERIO is not set
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
#
# Character devices
#
# CONFIG_VT is not set
-# CONFIG_DEVKMEM is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -454,7 +448,6 @@ CONFIG_INPUT=y
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_COLDFIRE is not set
CONFIG_SERIAL_MCF=y
CONFIG_SERIAL_MCF_BAUDRATE=19200
CONFIG_SERIAL_MCF_CONSOLE=y
@@ -473,19 +466,23 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -496,6 +493,7 @@ CONFIG_SSB_POSSIBLE=y
#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
#
# Multimedia drivers
@@ -514,19 +512,17 @@ CONFIG_DAB=y
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
-# CONFIG_HID_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
@@ -534,12 +530,14 @@ CONFIG_DAB=y
CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_FILE_LOCKING is not set
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY is not set
# CONFIG_QUOTA is not set
@@ -548,6 +546,11 @@ CONFIG_EXT2_FS=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -569,10 +572,7 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -582,13 +582,20 @@ CONFIG_SYSFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
CONFIG_ROMFS_FS=y
+# CONFIG_ROMFS_BACKED_BY_BLOCK is not set
+CONFIG_ROMFS_BACKED_BY_MTD=y
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_MTD=y
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
# CONFIG_NETWORK_FILESYSTEMS is not set
#
@@ -611,11 +618,17 @@ CONFIG_FRAME_WARN=1024
# 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_SLUB_STATS is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
# CONFIG_SAMPLES is not set
# CONFIG_FULLDEBUG is not set
# CONFIG_HIGHPROFILE is not set
-# CONFIG_BOOTPARAM is not set
+CONFIG_BOOTPARAM=y
+CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
# CONFIG_NO_KERNEL_MSG is not set
# CONFIG_BDM_DISABLE is not set
@@ -624,18 +637,22 @@ CONFIG_FRAME_WARN=1024
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T 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
+CONFIG_NLATTR=y
diff --git a/arch/m68knommu/kernel/asm-offsets.c b/arch/m68knommu/kernel/asm-offsets.c
index c785d07c02cc..f500dd6935d6 100644
--- a/arch/m68knommu/kernel/asm-offsets.c
+++ b/arch/m68knommu/kernel/asm-offsets.c
@@ -30,9 +30,6 @@ int main(void)
DEFINE(TASK_MM, offsetof(struct task_struct, mm));
DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
- /* offsets into the kernel_stat struct */
- DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
-
/* offsets into the irq_cpustat_t struct */
DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
@@ -69,9 +66,6 @@ int main(void)
DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4);
#endif
- /* offsets into the kernel_stat struct */
- DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
-
/* signal defines */
DEFINE(SIGSEGV, SIGSEGV);
DEFINE(SEGV_MAPERR, SEGV_MAPERR);
diff --git a/arch/m68knommu/kernel/dma.c b/arch/m68knommu/kernel/dma.c
index 936125806638..aaf38bbbb6cd 100644
--- a/arch/m68knommu/kernel/dma.c
+++ b/arch/m68knommu/kernel/dma.c
@@ -7,10 +7,9 @@
#include <linux/types.h>
#include <linux/mm.h>
-#include <linux/string.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
-#include <asm/io.h>
+#include <asm/cacheflush.h>
void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp)
@@ -36,7 +35,39 @@ void dma_free_coherent(struct device *dev, size_t size,
free_pages((unsigned long)vaddr, get_order(size));
}
-void dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle, size_t size, enum dma_data_direction dir)
+void dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
+ size_t size, enum dma_data_direction dir)
{
+ switch (dir) {
+ case DMA_TO_DEVICE:
+ flush_dcache_range(handle, size);
+ break;
+ case DMA_FROM_DEVICE:
+ /* Should be clear already */
+ break;
+ default:
+ if (printk_ratelimit())
+ printk("dma_sync_single_for_device: unsupported dir %u\n", dir);
+ break;
+ }
+}
+
+EXPORT_SYMBOL(dma_sync_single_for_device);
+dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size,
+ enum dma_data_direction dir)
+{
+ dma_addr_t handle = virt_to_phys(addr);
+ flush_dcache_range(handle, size);
+ return handle;
}
+EXPORT_SYMBOL(dma_map_single);
+dma_addr_t dma_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size,
+ enum dma_data_direction dir)
+{
+ dma_addr_t handle = page_to_phys(page) + offset;
+ dma_sync_single_for_device(dev, handle, size, dir);
+ return handle;
+}
+EXPORT_SYMBOL(dma_map_page);
diff --git a/arch/m68knommu/kernel/entry.S b/arch/m68knommu/kernel/entry.S
index f4782d2dce8f..f56faa5c9cd9 100644
--- a/arch/m68knommu/kernel/entry.S
+++ b/arch/m68knommu/kernel/entry.S
@@ -26,7 +26,6 @@
#include <linux/sys.h>
#include <linux/linkage.h>
-#include <asm/thread_info.h>
#include <asm/errno.h>
#include <asm/setup.h>
#include <asm/segment.h>
diff --git a/arch/m68knommu/kernel/irq.c b/arch/m68knommu/kernel/irq.c
index 56e0f4c55a67..3e56f60882b5 100644
--- a/arch/m68knommu/kernel/irq.c
+++ b/arch/m68knommu/kernel/irq.c
@@ -34,27 +34,6 @@ void ack_bad_irq(unsigned int irq)
printk(KERN_ERR "IRQ: unexpected irq=%d\n", irq);
}
-static struct irq_chip m_irq_chip = {
- .name = "M68K-INTC",
- .enable = enable_vector,
- .disable = disable_vector,
- .ack = ack_vector,
-};
-
-void __init init_IRQ(void)
-{
- int irq;
-
- init_vectors();
-
- for (irq = 0; (irq < NR_IRQS); irq++) {
- irq_desc[irq].status = IRQ_DISABLED;
- irq_desc[irq].action = NULL;
- irq_desc[irq].depth = 1;
- irq_desc[irq].chip = &m_irq_chip;
- }
-}
-
int show_interrupts(struct seq_file *p, void *v)
{
struct irqaction *ap;
diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68knommu/kernel/syscalltable.S
index 1017e76f3711..c0b8782832fd 100644
--- a/arch/m68knommu/kernel/syscalltable.S
+++ b/arch/m68knommu/kernel/syscalltable.S
@@ -347,6 +347,8 @@ ENTRY(sys_call_table)
.long sys_dup3
.long sys_pipe2
.long sys_inotify_init1
+ .long sys_preadv
+ .long sys_pwritev /* 330 */
.rept NR_syscalls-(.-sys_call_table)/4
.long sys_ni_syscall
diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S
index 69ba9b10767a..b7fe505e358d 100644
--- a/arch/m68knommu/kernel/vmlinux.lds.S
+++ b/arch/m68knommu/kernel/vmlinux.lds.S
@@ -147,6 +147,8 @@ SECTIONS {
. = ALIGN(4);
_sdata = . ;
DATA_DATA
+ . = ALIGN(32);
+ *(.data.cacheline_aligned)
. = ALIGN(8192) ;
*(.data.init_task)
_edata = . ;
diff --git a/arch/m68knommu/lib/checksum.c b/arch/m68knommu/lib/checksum.c
index 269d83bfbbe1..8bf012aec81c 100644
--- a/arch/m68knommu/lib/checksum.c
+++ b/arch/m68knommu/lib/checksum.c
@@ -127,15 +127,6 @@ __wsum csum_partial(const void *buff, int len, __wsum sum)
EXPORT_SYMBOL(csum_partial);
/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-__sum16 ip_compute_csum(const void *buff, int len)
-{
- return (__force __sum16)~do_csum(buff,len);
-}
-
-/*
* copy from fs while checksumming, otherwise like csum_partial
*/
diff --git a/arch/m68knommu/platform/5206/config.c b/arch/m68knommu/platform/5206/config.c
index 53a5920c2b71..f6f79874e9af 100644
--- a/arch/m68knommu/platform/5206/config.c
+++ b/arch/m68knommu/platform/5206/config.c
@@ -12,7 +12,6 @@
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/init.h>
-#include <linux/interrupt.h>
#include <linux/io.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
@@ -21,10 +20,6 @@
/***************************************************************************/
-void coldfire_reset(void);
-
-/***************************************************************************/
-
static struct mcf_platform_uart m5206_uart_platform[] = {
{
.mapbase = MCF_MBAR + MCFUART_BASE1,
@@ -109,10 +104,21 @@ void mcf_settimericr(unsigned int timer, unsigned int level)
/***************************************************************************/
+void m5206_cpu_reset(void)
+{
+ local_irq_disable();
+ /* Set watchdog to soft reset, and enabled */
+ __raw_writeb(0xc0, MCF_MBAR + MCFSIM_SYPCR);
+ for (;;)
+ /* wait for watchdog to timeout */;
+}
+
+/***************************************************************************/
+
void __init config_BSP(char *commandp, int size)
{
mcf_setimr(MCFSIM_IMR_MASKALL);
- mach_reset = coldfire_reset;
+ mach_reset = m5206_cpu_reset;
}
/***************************************************************************/
diff --git a/arch/m68knommu/platform/5206e/config.c b/arch/m68knommu/platform/5206e/config.c
index db902540bf2c..65887799db81 100644
--- a/arch/m68knommu/platform/5206e/config.c
+++ b/arch/m68knommu/platform/5206e/config.c
@@ -11,7 +11,6 @@
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/init.h>
-#include <linux/interrupt.h>
#include <linux/io.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
@@ -21,10 +20,6 @@
/***************************************************************************/
-void coldfire_reset(void);
-
-/***************************************************************************/
-
static struct mcf_platform_uart m5206e_uart_platform[] = {
{
.mapbase = MCF_MBAR + MCFUART_BASE1,
@@ -109,6 +104,17 @@ void mcf_settimericr(unsigned int timer, unsigned int level)
/***************************************************************************/
+void m5206e_cpu_reset(void)
+{
+ local_irq_disable();
+ /* Set watchdog to soft reset, and enabled */
+ __raw_writeb(0xc0, MCF_MBAR + MCFSIM_SYPCR);
+ for (;;)
+ /* wait for watchdog to timeout */;
+}
+
+/***************************************************************************/
+
void __init config_BSP(char *commandp, int size)
{
mcf_setimr(MCFSIM_IMR_MASKALL);
@@ -119,7 +125,7 @@ void __init config_BSP(char *commandp, int size)
commandp[size-1] = 0;
#endif /* CONFIG_NETtel */
- mach_reset = coldfire_reset;
+ mach_reset = m5206e_cpu_reset;
}
/***************************************************************************/
diff --git a/arch/m68knommu/platform/520x/config.c b/arch/m68knommu/platform/520x/config.c
index 855fc6a79d72..92614de42cd3 100644
--- a/arch/m68knommu/platform/520x/config.c
+++ b/arch/m68knommu/platform/520x/config.c
@@ -14,7 +14,6 @@
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/init.h>
-#include <linux/interrupt.h>
#include <linux/io.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
@@ -23,10 +22,6 @@
/***************************************************************************/
-void coldfire_reset(void);
-
-/***************************************************************************/
-
static struct mcf_platform_uart m520x_uart_platform[] = {
{
.mapbase = MCF_MBAR + MCFUART_BASE1,
@@ -86,20 +81,11 @@ static struct platform_device *m520x_devices[] __initdata = {
/***************************************************************************/
-#define INTC0 (MCF_MBAR + MCFICM_INTC0)
-
static void __init m520x_uart_init_line(int line, int irq)
{
- u32 imr;
u16 par;
u8 par2;
- writeb(0x03, INTC0 + MCFINTC_ICR0 + MCFINT_UART0 + line);
-
- imr = readl(INTC0 + MCFINTC_IMRL);
- imr &= ~((1 << (irq - MCFINT_VECBASE)) | 1);
- writel(imr, INTC0 + MCFINTC_IMRL);
-
switch (line) {
case 0:
par = readw(MCF_IPSBAR + MCF_GPIO_PAR_UART);
@@ -136,18 +122,8 @@ static void __init m520x_uarts_init(void)
static void __init m520x_fec_init(void)
{
- u32 imr;
u8 v;
- /* Unmask FEC interrupts at ColdFire interrupt controller */
- writeb(0x4, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0 + 36);
- writeb(0x4, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0 + 40);
- writeb(0x4, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0 + 42);
-
- imr = readl(MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH);
- imr &= ~0x0001FFF0;
- writel(imr, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH);
-
/* Set multi-function pins to ethernet mode */
v = readb(MCF_IPSBAR + MCF_GPIO_PAR_FEC);
writeb(v | 0xf0, MCF_IPSBAR + MCF_GPIO_PAR_FEC);
@@ -158,20 +134,17 @@ static void __init m520x_fec_init(void)
/***************************************************************************/
-/*
- * Program the vector to be an auto-vectored.
- */
-
-void mcf_autovector(unsigned int vec)
+static void m520x_cpu_reset(void)
{
- /* Everything is auto-vectored on the 520x devices */
+ local_irq_disable();
+ __raw_writeb(MCF_RCR_SWRESET, MCF_RCR);
}
/***************************************************************************/
void __init config_BSP(char *commandp, int size)
{
- mach_reset = coldfire_reset;
+ mach_reset = m520x_cpu_reset;
m520x_uarts_init();
m520x_fec_init();
}
diff --git a/arch/m68knommu/platform/523x/config.c b/arch/m68knommu/platform/523x/config.c
index 74133f27b30c..00f08d2e43b0 100644
--- a/arch/m68knommu/platform/523x/config.c
+++ b/arch/m68knommu/platform/523x/config.c
@@ -15,7 +15,6 @@
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/init.h>
-#include <linux/interrupt.h>
#include <linux/io.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
@@ -24,10 +23,6 @@
/***************************************************************************/
-void coldfire_reset(void);
-
-/***************************************************************************/
-
static struct mcf_platform_uart m523x_uart_platform[] = {
{
.mapbase = MCF_MBAR + MCFUART_BASE1,
@@ -87,73 +82,17 @@ static struct platform_device *m523x_devices[] __initdata = {
/***************************************************************************/
-#define INTC0 (MCF_MBAR + MCFICM_INTC0)
-
-static void __init m523x_uart_init_line(int line, int irq)
-{
- u32 imr;
-
- if ((line < 0) || (line > 2))
- return;
-
- writeb(0x30+line, (INTC0 + MCFINTC_ICR0 + MCFINT_UART0 + line));
-
- imr = readl(INTC0 + MCFINTC_IMRL);
- imr &= ~((1 << (irq - MCFINT_VECBASE)) | 1);
- writel(imr, INTC0 + MCFINTC_IMRL);
-}
-
-static void __init m523x_uarts_init(void)
-{
- const int nrlines = ARRAY_SIZE(m523x_uart_platform);
- int line;
-
- for (line = 0; (line < nrlines); line++)
- m523x_uart_init_line(line, m523x_uart_platform[line].irq);
-}
-
-/***************************************************************************/
-
-static void __init m523x_fec_init(void)
-{
- u32 imr;
-
- /* Unmask FEC interrupts at ColdFire interrupt controller */
- writeb(0x28, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0 + 23);
- writeb(0x27, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0 + 27);
- writeb(0x26, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0 + 29);
-
- imr = readl(MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH);
- imr &= ~0xf;
- writel(imr, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH);
- imr = readl(MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL);
- imr &= ~0xff800001;
- writel(imr, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL);
-}
-
-/***************************************************************************/
-
-void mcf_disableall(void)
-{
- *((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH)) = 0xffffffff;
- *((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL)) = 0xffffffff;
-}
-
-/***************************************************************************/
-
-void mcf_autovector(unsigned int vec)
+static void m523x_cpu_reset(void)
{
- /* Everything is auto-vectored on the 523x */
+ local_irq_disable();
+ __raw_writeb(MCF_RCR_SWRESET, MCF_IPSBAR + MCF_RCR);
}
/***************************************************************************/
void __init config_BSP(char *commandp, int size)
{
- mcf_disableall();
- mach_reset = coldfire_reset;
- m523x_uarts_init();
- m523x_fec_init();
+ mach_reset = m523x_cpu_reset;
}
/***************************************************************************/
diff --git a/arch/m68knommu/platform/5249/config.c b/arch/m68knommu/platform/5249/config.c
index 9eab19d01eb1..93d998825925 100644
--- a/arch/m68knommu/platform/5249/config.c
+++ b/arch/m68knommu/platform/5249/config.c
@@ -11,7 +11,6 @@
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/init.h>
-#include <linux/interrupt.h>
#include <linux/io.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
@@ -20,10 +19,6 @@
/***************************************************************************/
-void coldfire_reset(void);
-
-/***************************************************************************/
-
static struct mcf_platform_uart m5249_uart_platform[] = {
{
.mapbase = MCF_MBAR + MCFUART_BASE1,
@@ -106,10 +101,21 @@ void mcf_settimericr(unsigned int timer, unsigned int level)
/***************************************************************************/
+void m5249_cpu_reset(void)
+{
+ local_irq_disable();
+ /* Set watchdog to soft reset, and enabled */
+ __raw_writeb(0xc0, MCF_MBAR + MCFSIM_SYPCR);
+ for (;;)
+ /* wait for watchdog to timeout */;
+}
+
+/***************************************************************************/
+
void __init config_BSP(char *commandp, int size)
{
mcf_setimr(MCFSIM_IMR_MASKALL);
- mach_reset = coldfire_reset;
+ mach_reset = m5249_cpu_reset;
}
/***************************************************************************/
diff --git a/arch/m68knommu/platform/5272/config.c b/arch/m68knommu/platform/5272/config.c
index e049245f4092..5f95fcde05fd 100644
--- a/arch/m68knommu/platform/5272/config.c
+++ b/arch/m68knommu/platform/5272/config.c
@@ -12,7 +12,6 @@
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/init.h>
-#include <linux/interrupt.h>
#include <linux/io.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
@@ -21,8 +20,6 @@
/***************************************************************************/
-void coldfire_reset(void);
-
extern unsigned int mcf_timervector;
extern unsigned int mcf_profilevector;
extern unsigned int mcf_timerlevel;
@@ -170,6 +167,19 @@ void mcf_settimericr(int timer, int level)
/***************************************************************************/
+static void m5272_cpu_reset(void)
+{
+ local_irq_disable();
+ /* Set watchdog to reset, and enabled */
+ __raw_writew(0, MCF_MBAR + MCFSIM_WIRR);
+ __raw_writew(1, MCF_MBAR + MCFSIM_WRRR);
+ __raw_writew(0, MCF_MBAR + MCFSIM_WCR);
+ for (;;)
+ /* wait for watchdog to timeout */;
+}
+
+/***************************************************************************/
+
void __init config_BSP(char *commandp, int size)
{
#if defined (CONFIG_MOD5272)
@@ -194,7 +204,7 @@ void __init config_BSP(char *commandp, int size)
mcf_timervector = 69;
mcf_profilevector = 70;
- mach_reset = coldfire_reset;
+ mach_reset = m5272_cpu_reset;
}
/***************************************************************************/
diff --git a/arch/m68knommu/platform/527x/config.c b/arch/m68knommu/platform/527x/config.c
index 49343fb157b0..fa51be172830 100644
--- a/arch/m68knommu/platform/527x/config.c
+++ b/arch/m68knommu/platform/527x/config.c
@@ -15,7 +15,6 @@
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/init.h>
-#include <linux/interrupt.h>
#include <linux/io.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
@@ -24,10 +23,6 @@
/***************************************************************************/
-void coldfire_reset(void);
-
-/***************************************************************************/
-
static struct mcf_platform_uart m527x_uart_platform[] = {
{
.mapbase = MCF_MBAR + MCFUART_BASE1,
@@ -121,23 +116,13 @@ static struct platform_device *m527x_devices[] __initdata = {
/***************************************************************************/
-#define INTC0 (MCF_MBAR + MCFICM_INTC0)
-
static void __init m527x_uart_init_line(int line, int irq)
{
u16 sepmask;
- u32 imr;
if ((line < 0) || (line > 2))
return;
- /* level 6, line based priority */
- writeb(0x30+line, INTC0 + MCFINTC_ICR0 + MCFINT_UART0 + line);
-
- imr = readl(INTC0 + MCFINTC_IMRL);
- imr &= ~((1 << (irq - MCFINT_VECBASE)) | 1);
- writel(imr, INTC0 + MCFINTC_IMRL);
-
/*
* External Pin Mask Setting & Enable External Pin for Interface
*/
@@ -162,41 +147,23 @@ static void __init m527x_uarts_init(void)
/***************************************************************************/
-static void __init m527x_fec_irq_init(int nr)
-{
- unsigned long base;
- u32 imr;
-
- base = MCF_IPSBAR + (nr ? MCFICM_INTC1 : MCFICM_INTC0);
-
- writeb(0x28, base + MCFINTC_ICR0 + 23);
- writeb(0x27, base + MCFINTC_ICR0 + 27);
- writeb(0x26, base + MCFINTC_ICR0 + 29);
-
- imr = readl(base + MCFINTC_IMRH);
- imr &= ~0xf;
- writel(imr, base + MCFINTC_IMRH);
- imr = readl(base + MCFINTC_IMRL);
- imr &= ~0xff800001;
- writel(imr, base + MCFINTC_IMRL);
-}
-
static void __init m527x_fec_init(void)
{
u16 par;
u8 v;
- m527x_fec_irq_init(0);
-
/* Set multi-function pins to ethernet mode for fec0 */
+#if defined(CONFIG_M5271)
+ v = readb(MCF_IPSBAR + 0x100047);
+ writeb(v | 0xf0, MCF_IPSBAR + 0x100047);
+#else
par = readw(MCF_IPSBAR + 0x100082);
writew(par | 0xf00, MCF_IPSBAR + 0x100082);
v = readb(MCF_IPSBAR + 0x100078);
writeb(v | 0xc0, MCF_IPSBAR + 0x100078);
+#endif
#ifdef CONFIG_FEC2
- m527x_fec_irq_init(1);
-
/* Set multi-function pins to ethernet mode for fec1 */
par = readw(MCF_IPSBAR + 0x100082);
writew(par | 0xa0, MCF_IPSBAR + 0x100082);
@@ -207,25 +174,17 @@ static void __init m527x_fec_init(void)
/***************************************************************************/
-void mcf_disableall(void)
-{
- *((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH)) = 0xffffffff;
- *((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL)) = 0xffffffff;
-}
-
-/***************************************************************************/
-
-void mcf_autovector(unsigned int vec)
+static void m527x_cpu_reset(void)
{
- /* Everything is auto-vectored on the 5272 */
+ local_irq_disable();
+ __raw_writeb(MCF_RCR_SWRESET, MCF_IPSBAR + MCF_RCR);
}
/***************************************************************************/
void __init config_BSP(char *commandp, int size)
{
- mcf_disableall();
- mach_reset = coldfire_reset;
+ mach_reset = m527x_cpu_reset;
m527x_uarts_init();
m527x_fec_init();
}
diff --git a/arch/m68knommu/platform/528x/config.c b/arch/m68knommu/platform/528x/config.c
index bee526f4d1af..6e608d1836f1 100644
--- a/arch/m68knommu/platform/528x/config.c
+++ b/arch/m68knommu/platform/528x/config.c
@@ -3,8 +3,8 @@
/*
* linux/arch/m68knommu/platform/528x/config.c
*
- * Sub-architcture dependant initialization code for the Motorola
- * 5280 and 5282 CPUs.
+ * Sub-architcture dependant initialization code for the Freescale
+ * 5280, 5281 and 5282 CPUs.
*
* Copyright (C) 1999-2003, Greg Ungerer (gerg@snapgear.com)
* Copyright (C) 2001-2003, SnapGear Inc. (www.snapgear.com)
@@ -15,24 +15,13 @@
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/init.h>
-#include <linux/interrupt.h>
#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/flash.h>
#include <linux/io.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
#include <asm/mcfuart.h>
-#ifdef CONFIG_MTD_PARTITIONS
-#include <linux/mtd/partitions.h>
-#endif
-
-/***************************************************************************/
-
-void coldfire_reset(void);
-
/***************************************************************************/
static struct mcf_platform_uart m528x_uart_platform[] = {
@@ -95,23 +84,13 @@ static struct platform_device *m528x_devices[] __initdata = {
/***************************************************************************/
-#define INTC0 (MCF_MBAR + MCFICM_INTC0)
-
static void __init m528x_uart_init_line(int line, int irq)
{
u8 port;
- u32 imr;
if ((line < 0) || (line > 2))
return;
- /* level 6, line based priority */
- writeb(0x30+line, INTC0 + MCFINTC_ICR0 + MCFINT_UART0 + line);
-
- imr = readl(INTC0 + MCFINTC_IMRL);
- imr &= ~((1 << (irq - MCFINT_VECBASE)) | 1);
- writel(imr, INTC0 + MCFINTC_IMRL);
-
/* make sure PUAPAR is set for UART0 and UART1 */
if (line < 2) {
port = readb(MCF_MBAR + MCF5282_GPIO_PUAPAR);
@@ -133,21 +112,8 @@ static void __init m528x_uarts_init(void)
static void __init m528x_fec_init(void)
{
- u32 imr;
u16 v16;
- /* Unmask FEC interrupts at ColdFire interrupt controller */
- writeb(0x28, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0 + 23);
- writeb(0x27, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0 + 27);
- writeb(0x26, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0 + 29);
-
- imr = readl(MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH);
- imr &= ~0xf;
- writel(imr, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH);
- imr = readl(MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL);
- imr &= ~0xff800001;
- writel(imr, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL);
-
/* Set multi-function pins to ethernet mode for fec0 */
v16 = readw(MCF_IPSBAR + 0x100056);
writew(v16 | 0xf00, MCF_IPSBAR + 0x100056);
@@ -156,17 +122,10 @@ static void __init m528x_fec_init(void)
/***************************************************************************/
-void mcf_disableall(void)
-{
- *((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH)) = 0xffffffff;
- *((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL)) = 0xffffffff;
-}
-
-/***************************************************************************/
-
-void mcf_autovector(unsigned int vec)
+static void m528x_cpu_reset(void)
{
- /* Everything is auto-vectored on the 5272 */
+ local_irq_disable();
+ __raw_writeb(MCF_RCR_SWRESET, MCF_IPSBAR + MCF_RCR);
}
/***************************************************************************/
@@ -200,8 +159,6 @@ void wildfiremod_halt(void)
void __init config_BSP(char *commandp, int size)
{
- mcf_disableall();
-
#ifdef CONFIG_WILDFIRE
mach_halt = wildfire_halt;
#endif
@@ -214,6 +171,7 @@ void __init config_BSP(char *commandp, int size)
static int __init init_BSP(void)
{
+ mach_reset = m528x_cpu_reset;
m528x_uarts_init();
m528x_fec_init();
platform_add_devices(m528x_devices, ARRAY_SIZE(m528x_devices));
diff --git a/arch/m68knommu/platform/5307/config.c b/arch/m68knommu/platform/5307/config.c
index 44803bf70a6e..39da9e9ff674 100644
--- a/arch/m68knommu/platform/5307/config.c
+++ b/arch/m68knommu/platform/5307/config.c
@@ -12,7 +12,6 @@
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/init.h>
-#include <linux/interrupt.h>
#include <linux/io.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
@@ -22,8 +21,6 @@
/***************************************************************************/
-void coldfire_reset(void);
-
extern unsigned int mcf_timervector;
extern unsigned int mcf_profilevector;
extern unsigned int mcf_timerlevel;
@@ -119,6 +116,17 @@ void mcf_settimericr(unsigned int timer, unsigned int level)
/***************************************************************************/
+void m5307_cpu_reset(void)
+{
+ local_irq_disable();
+ /* Set watchdog to soft reset, and enabled */
+ __raw_writeb(0xc0, MCF_MBAR + MCFSIM_SYPCR);
+ for (;;)
+ /* wait for watchdog to timeout */;
+}
+
+/***************************************************************************/
+
void __init config_BSP(char *commandp, int size)
{
mcf_setimr(MCFSIM_IMR_MASKALL);
@@ -134,7 +142,7 @@ void __init config_BSP(char *commandp, int size)
mcf_timerlevel = 6;
#endif
- mach_reset = coldfire_reset;
+ mach_reset = m5307_cpu_reset;
#ifdef CONFIG_BDM_DISABLE
/*
diff --git a/arch/m68knommu/platform/532x/config.c b/arch/m68knommu/platform/532x/config.c
index 591f2f801134..47e4573c328e 100644
--- a/arch/m68knommu/platform/532x/config.c
+++ b/arch/m68knommu/platform/532x/config.c
@@ -20,7 +20,6 @@
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/init.h>
-#include <linux/interrupt.h>
#include <linux/io.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
@@ -31,8 +30,6 @@
/***************************************************************************/
-void coldfire_reset(void);
-
extern unsigned int mcf_timervector;
extern unsigned int mcf_profilevector;
extern unsigned int mcf_timerlevel;
@@ -100,18 +97,11 @@ static struct platform_device *m532x_devices[] __initdata = {
static void __init m532x_uart_init_line(int line, int irq)
{
if (line == 0) {
- MCF_INTC0_ICR26 = 0x3;
- MCF_INTC0_CIMR = 26;
/* GPIO initialization */
MCF_GPIO_PAR_UART |= 0x000F;
} else if (line == 1) {
- MCF_INTC0_ICR27 = 0x3;
- MCF_INTC0_CIMR = 27;
/* GPIO initialization */
MCF_GPIO_PAR_UART |= 0x0FF0;
- } else if (line == 2) {
- MCF_INTC0_ICR28 = 0x3;
- MCF_INTC0_CIMR = 28;
}
}
@@ -127,14 +117,6 @@ static void __init m532x_uarts_init(void)
static void __init m532x_fec_init(void)
{
- /* Unmask FEC interrupts at ColdFire interrupt controller */
- MCF_INTC0_ICR36 = 0x2;
- MCF_INTC0_ICR40 = 0x2;
- MCF_INTC0_ICR42 = 0x2;
-
- MCF_INTC0_IMRH &= ~(MCF_INTC_IMRH_INT_MASK36 |
- MCF_INTC_IMRH_INT_MASK40 | MCF_INTC_IMRH_INT_MASK42);
-
/* Set multi-function pins to ethernet mode for fec0 */
MCF_GPIO_PAR_FECI2C |= (MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC |
MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO);
@@ -146,28 +128,20 @@ static void __init m532x_fec_init(void)
void mcf_settimericr(unsigned int timer, unsigned int level)
{
- volatile unsigned char *icrp;
- unsigned int icr;
- unsigned char irq;
-
- if (timer <= 2) {
- switch (timer) {
- case 2: irq = 33; icr = MCFSIM_ICR_TIMER2; break;
- default: irq = 32; icr = MCFSIM_ICR_TIMER1; break;
- }
-
- icrp = (volatile unsigned char *) (icr);
- *icrp = level;
- mcf_enable_irq0(irq);
- }
}
/***************************************************************************/
-void __init config_BSP(char *commandp, int size)
+static void m532x_cpu_reset(void)
{
- mcf_setimr(MCFSIM_IMR_MASKALL);
+ local_irq_disable();
+ __raw_writeb(MCF_RCR_SWRESET, MCF_RCR);
+}
+
+/***************************************************************************/
+void __init config_BSP(char *commandp, int size)
+{
#if !defined(CONFIG_BOOTPARAM)
/* Copy command line from FLASH to local buffer... */
memcpy(commandp, (char *) 0x4000, 4);
@@ -181,7 +155,7 @@ void __init config_BSP(char *commandp, int size)
mcf_timervector = 64+32;
mcf_profilevector = 64+33;
- mach_reset = coldfire_reset;
+ mach_reset = m532x_cpu_reset;
#ifdef CONFIG_BDM_DISABLE
/*
diff --git a/arch/m68knommu/platform/5407/config.c b/arch/m68knommu/platform/5407/config.c
index 0ee8c1a200c8..b41d942bf8d0 100644
--- a/arch/m68knommu/platform/5407/config.c
+++ b/arch/m68knommu/platform/5407/config.c
@@ -12,7 +12,6 @@
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/init.h>
-#include <linux/interrupt.h>
#include <linux/io.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
@@ -21,8 +20,6 @@
/***************************************************************************/
-void coldfire_reset(void);
-
extern unsigned int mcf_timervector;
extern unsigned int mcf_profilevector;
extern unsigned int mcf_timerlevel;
@@ -110,6 +107,17 @@ void mcf_settimericr(unsigned int timer, unsigned int level)
/***************************************************************************/
+void m5407_cpu_reset(void)
+{
+ local_irq_disable();
+ /* set watchdog to soft reset, and enabled */
+ __raw_writeb(0xc0, MCF_MBAR + MCFSIM_SYPCR);
+ for (;;)
+ /* wait for watchdog to timeout */;
+}
+
+/***************************************************************************/
+
void __init config_BSP(char *commandp, int size)
{
mcf_setimr(MCFSIM_IMR_MASKALL);
@@ -121,7 +129,7 @@ void __init config_BSP(char *commandp, int size)
mcf_timerlevel = 6;
#endif
- mach_reset = coldfire_reset;
+ mach_reset = m5407_cpu_reset;
}
/***************************************************************************/
diff --git a/arch/m68knommu/platform/68328/ints.c b/arch/m68knommu/platform/68328/ints.c
index 72e56d554f4f..dab623389a01 100644
--- a/arch/m68knommu/platform/68328/ints.c
+++ b/arch/m68knommu/platform/68328/ints.c
@@ -73,34 +73,6 @@ extern e_vector *_ramvec;
/* The number of spurious interrupts */
volatile unsigned int num_spurious;
-/*
- * This function should be called during kernel startup to initialize
- * the machine vector table.
- */
-void __init init_vectors(void)
-{
- int i;
-
- /* set up the vectors */
- for (i = 72; i < 256; ++i)
- _ramvec[i] = (e_vector) bad_interrupt;
-
- _ramvec[32] = system_call;
-
- _ramvec[65] = (e_vector) inthandler1;
- _ramvec[66] = (e_vector) inthandler2;
- _ramvec[67] = (e_vector) inthandler3;
- _ramvec[68] = (e_vector) inthandler4;
- _ramvec[69] = (e_vector) inthandler5;
- _ramvec[70] = (e_vector) inthandler6;
- _ramvec[71] = (e_vector) inthandler7;
-
- IVR = 0x40; /* Set DragonBall IVR (interrupt base) to 64 */
-
- /* turn off all interrupts */
- IMR = ~0;
-}
-
/* The 68k family did not have a good way to determine the source
* of interrupts until later in the family. The EC000 core does
* not provide the vector number on the stack, we vector everything
@@ -163,18 +135,54 @@ void process_int(int vec, struct pt_regs *fp)
}
}
-void enable_vector(unsigned int irq)
+static void intc_irq_unmask(unsigned int irq)
{
IMR &= ~(1<<irq);
}
-void disable_vector(unsigned int irq)
+static void intc_irq_mask(unsigned int irq)
{
IMR |= (1<<irq);
}
-void ack_vector(unsigned int irq)
+static struct irq_chip intc_irq_chip = {
+ .name = "M68K-INTC",
+ .mask = intc_irq_mask,
+ .unmask = intc_irq_unmask,
+};
+
+/*
+ * This function should be called during kernel startup to initialize
+ * the machine vector table.
+ */
+void __init init_IRQ(void)
{
- /* Nothing needed */
+ int i;
+
+ /* set up the vectors */
+ for (i = 72; i < 256; ++i)
+ _ramvec[i] = (e_vector) bad_interrupt;
+
+ _ramvec[32] = system_call;
+
+ _ramvec[65] = (e_vector) inthandler1;
+ _ramvec[66] = (e_vector) inthandler2;
+ _ramvec[67] = (e_vector) inthandler3;
+ _ramvec[68] = (e_vector) inthandler4;
+ _ramvec[69] = (e_vector) inthandler5;
+ _ramvec[70] = (e_vector) inthandler6;
+ _ramvec[71] = (e_vector) inthandler7;
+
+ IVR = 0x40; /* Set DragonBall IVR (interrupt base) to 64 */
+
+ /* turn off all interrupts */
+ IMR = ~0;
+
+ for (i = 0; (i < NR_IRQS); i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = NULL;
+ irq_desc[i].depth = 1;
+ irq_desc[i].chip = &intc_irq_chip;
+ }
}
diff --git a/arch/m68knommu/platform/68328/timers.c b/arch/m68knommu/platform/68328/timers.c
index 6bafefa546e5..309f725995bf 100644
--- a/arch/m68knommu/platform/68328/timers.c
+++ b/arch/m68knommu/platform/68328/timers.c
@@ -75,7 +75,7 @@ static struct irqaction m68328_timer_irq = {
/***************************************************************************/
-static cycle_t m68328_read_clk(void)
+static cycle_t m68328_read_clk(struct clocksource *cs)
{
unsigned long flags;
u32 cycles;
diff --git a/arch/m68knommu/platform/68360/ints.c b/arch/m68knommu/platform/68360/ints.c
index c36781157e09..1143f77caca4 100644
--- a/arch/m68knommu/platform/68360/ints.c
+++ b/arch/m68knommu/platform/68360/ints.c
@@ -37,11 +37,33 @@ extern void *_ramvec[];
/* The number of spurious interrupts */
volatile unsigned int num_spurious;
+static void intc_irq_unmask(unsigned int irq)
+{
+ pquicc->intr_cimr |= (1 << irq);
+}
+
+static void intc_irq_mask(unsigned int irq)
+{
+ pquicc->intr_cimr &= ~(1 << irq);
+}
+
+static void intc_irq_ack(unsigned int irq)
+{
+ pquicc->intr_cisr = (1 << irq);
+}
+
+static struct irq_chip intc_irq_chip = {
+ .name = "M68K-INTC",
+ .mask = intc_irq_mask,
+ .unmask = intc_irq_unmask,
+ .ack = intc_irq_ack,
+};
+
/*
* This function should be called during kernel startup to initialize
* the vector table.
*/
-void init_vectors(void)
+void init_IRQ(void)
{
int i;
int vba = (CPM_VECTOR_BASE<<4);
@@ -109,20 +131,12 @@ void init_vectors(void)
/* turn off all CPM interrupts */
pquicc->intr_cimr = 0x00000000;
-}
-
-void enable_vector(unsigned int irq)
-{
- pquicc->intr_cimr |= (1 << irq);
-}
-void disable_vector(unsigned int irq)
-{
- pquicc->intr_cimr &= ~(1 << irq);
-}
-
-void ack_vector(unsigned int irq)
-{
- pquicc->intr_cisr = (1 << irq);
+ for (i = 0; (i < NR_IRQS); i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = NULL;
+ irq_desc[i].depth = 1;
+ irq_desc[i].chip = &intc_irq_chip;
+ }
}
diff --git a/arch/m68knommu/platform/coldfire/Makefile b/arch/m68knommu/platform/coldfire/Makefile
index 1bcb9372353f..85be019f378b 100644
--- a/arch/m68knommu/platform/coldfire/Makefile
+++ b/arch/m68knommu/platform/coldfire/Makefile
@@ -15,16 +15,16 @@
asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
obj-$(CONFIG_COLDFIRE) += clk.o dma.o entry.o vectors.o
-obj-$(CONFIG_M5206) += timers.o
-obj-$(CONFIG_M5206e) += timers.o
-obj-$(CONFIG_M520x) += pit.o
-obj-$(CONFIG_M523x) += pit.o dma_timer.o
-obj-$(CONFIG_M5249) += timers.o
-obj-$(CONFIG_M527x) += pit.o
-obj-$(CONFIG_M5272) += timers.o
-obj-$(CONFIG_M528x) += pit.o
-obj-$(CONFIG_M5307) += timers.o
-obj-$(CONFIG_M532x) += timers.o
-obj-$(CONFIG_M5407) += timers.o
+obj-$(CONFIG_M5206) += timers.o intc.o
+obj-$(CONFIG_M5206e) += timers.o intc.o
+obj-$(CONFIG_M520x) += pit.o intc-simr.o
+obj-$(CONFIG_M523x) += pit.o dma_timer.o intc-2.o
+obj-$(CONFIG_M5249) += timers.o intc.o
+obj-$(CONFIG_M527x) += pit.o intc-2.o
+obj-$(CONFIG_M5272) += timers.o intc.o
+obj-$(CONFIG_M528x) += pit.o intc-2.o
+obj-$(CONFIG_M5307) += timers.o intc.o
+obj-$(CONFIG_M532x) += timers.o intc-simr.o
+obj-$(CONFIG_M5407) += timers.o intc.o
extra-y := head.o
diff --git a/arch/m68knommu/platform/coldfire/dma_timer.c b/arch/m68knommu/platform/coldfire/dma_timer.c
index 772578b1084f..a5f562823d7a 100644
--- a/arch/m68knommu/platform/coldfire/dma_timer.c
+++ b/arch/m68knommu/platform/coldfire/dma_timer.c
@@ -34,7 +34,7 @@
#define DMA_DTMR_CLK_DIV_16 (2 << 1)
#define DMA_DTMR_ENABLE (1 << 0)
-static cycle_t cf_dt_get_cycles(void)
+static cycle_t cf_dt_get_cycles(struct clocksource *cs)
{
return __raw_readl(DTCN0);
}
diff --git a/arch/m68knommu/platform/coldfire/intc-2.c b/arch/m68knommu/platform/coldfire/intc-2.c
new file mode 100644
index 000000000000..5598c8b8661f
--- /dev/null
+++ b/arch/m68knommu/platform/coldfire/intc-2.c
@@ -0,0 +1,93 @@
+/*
+ * intc-1.c
+ *
+ * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/traps.h>
+
+/*
+ * Each vector needs a unique priority and level asscoiated with it.
+ * We don't really care so much what they are, we don't rely on the
+ * tranditional priority interrupt scheme of the m68k/ColdFire.
+ */
+static u8 intc_intpri = 0x36;
+
+static void intc_irq_mask(unsigned int irq)
+{
+ if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + 128)) {
+ unsigned long imraddr;
+ u32 val, imrbit;
+
+ irq -= MCFINT_VECBASE;
+ imraddr = MCF_IPSBAR;
+ imraddr += (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
+ imraddr += (irq & 0x20) ? MCFINTC_IMRH : MCFINTC_IMRL;
+ imrbit = 0x1 << (irq & 0x1f);
+
+ val = __raw_readl(imraddr);
+ __raw_writel(val | imrbit, imraddr);
+ }
+}
+
+static void intc_irq_unmask(unsigned int irq)
+{
+ if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + 128)) {
+ unsigned long intaddr, imraddr, icraddr;
+ u32 val, imrbit;
+
+ irq -= MCFINT_VECBASE;
+ intaddr = MCF_IPSBAR;
+ intaddr += (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
+ imraddr = intaddr + ((irq & 0x20) ? MCFINTC_IMRH : MCFINTC_IMRL);
+ icraddr = intaddr + MCFINTC_ICR0 + (irq & 0x3f);
+ imrbit = 0x1 << (irq & 0x1f);
+
+ /* Don't set the "maskall" bit! */
+ if ((irq & 0x20) == 0)
+ imrbit |= 0x1;
+
+ if (__raw_readb(icraddr) == 0)
+ __raw_writeb(intc_intpri--, icraddr);
+
+ val = __raw_readl(imraddr);
+ __raw_writel(val & ~imrbit, imraddr);
+ }
+}
+
+static struct irq_chip intc_irq_chip = {
+ .name = "CF-INTC",
+ .mask = intc_irq_mask,
+ .unmask = intc_irq_unmask,
+};
+
+void __init init_IRQ(void)
+{
+ int irq;
+
+ init_vectors();
+
+ /* Mask all interrupt sources */
+ __raw_writel(0x1, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL);
+ __raw_writel(0x1, MCF_IPSBAR + MCFICM_INTC1 + MCFINTC_IMRL);
+
+ for (irq = 0; (irq < NR_IRQS); irq++) {
+ irq_desc[irq].status = IRQ_DISABLED;
+ irq_desc[irq].action = NULL;
+ irq_desc[irq].depth = 1;
+ irq_desc[irq].chip = &intc_irq_chip;
+ }
+}
+
diff --git a/arch/m68knommu/platform/coldfire/intc-simr.c b/arch/m68knommu/platform/coldfire/intc-simr.c
new file mode 100644
index 000000000000..1b01e79c2f63
--- /dev/null
+++ b/arch/m68knommu/platform/coldfire/intc-simr.c
@@ -0,0 +1,78 @@
+/*
+ * intc-simr.c
+ *
+ * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/traps.h>
+
+static void intc_irq_mask(unsigned int irq)
+{
+ if (irq >= MCFINT_VECBASE) {
+ if (irq < MCFINT_VECBASE + 64)
+ __raw_writeb(irq - MCFINT_VECBASE, MCFINTC0_SIMR);
+ else if ((irq < MCFINT_VECBASE + 128) && MCFINTC1_SIMR)
+ __raw_writeb(irq - MCFINT_VECBASE - 64, MCFINTC1_SIMR);
+ }
+}
+
+static void intc_irq_unmask(unsigned int irq)
+{
+ if (irq >= MCFINT_VECBASE) {
+ if (irq < MCFINT_VECBASE + 64)
+ __raw_writeb(irq - MCFINT_VECBASE, MCFINTC0_CIMR);
+ else if ((irq < MCFINT_VECBASE + 128) && MCFINTC1_CIMR)
+ __raw_writeb(irq - MCFINT_VECBASE - 64, MCFINTC1_CIMR);
+ }
+}
+
+static int intc_irq_set_type(unsigned int irq, unsigned int type)
+{
+ if (irq >= MCFINT_VECBASE) {
+ if (irq < MCFINT_VECBASE + 64)
+ __raw_writeb(5, MCFINTC0_ICR0 + irq - MCFINT_VECBASE);
+ else if ((irq < MCFINT_VECBASE) && MCFINTC1_ICR0)
+ __raw_writeb(5, MCFINTC1_ICR0 + irq - MCFINT_VECBASE - 64);
+ }
+ return 0;
+}
+
+static struct irq_chip intc_irq_chip = {
+ .name = "CF-INTC",
+ .mask = intc_irq_mask,
+ .unmask = intc_irq_unmask,
+ .set_type = intc_irq_set_type,
+};
+
+void __init init_IRQ(void)
+{
+ int irq;
+
+ init_vectors();
+
+ /* Mask all interrupt sources */
+ __raw_writeb(0xff, MCFINTC0_SIMR);
+ if (MCFINTC1_SIMR)
+ __raw_writeb(0xff, MCFINTC1_SIMR);
+
+ for (irq = 0; (irq < NR_IRQS); irq++) {
+ irq_desc[irq].status = IRQ_DISABLED;
+ irq_desc[irq].action = NULL;
+ irq_desc[irq].depth = 1;
+ irq_desc[irq].chip = &intc_irq_chip;
+ intc_irq_set_type(irq, 0);
+ }
+}
+
diff --git a/arch/m68knommu/platform/coldfire/intc.c b/arch/m68knommu/platform/coldfire/intc.c
new file mode 100644
index 000000000000..c81ab6e5cf26
--- /dev/null
+++ b/arch/m68knommu/platform/coldfire/intc.c
@@ -0,0 +1,55 @@
+/*
+ * intc.c
+ *
+ * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <asm/traps.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+
+static void intc_irq_mask(unsigned int irq)
+{
+}
+
+static void intc_irq_unmask(unsigned int irq)
+{
+}
+
+static int intc_irq_set_type(unsigned int irq, unsigned int type)
+{
+ return 0;
+}
+
+static struct irq_chip intc_irq_chip = {
+ .name = "CF-INTC",
+ .mask = intc_irq_mask,
+ .unmask = intc_irq_unmask,
+ .set_type = intc_irq_set_type,
+};
+
+void __init init_IRQ(void)
+{
+ int irq;
+
+ init_vectors();
+
+ for (irq = 0; (irq < NR_IRQS); irq++) {
+ irq_desc[irq].status = IRQ_DISABLED;
+ irq_desc[irq].action = NULL;
+ irq_desc[irq].depth = 1;
+ irq_desc[irq].chip = &intc_irq_chip;
+ intc_irq_set_type(irq, 0);
+ }
+}
+
diff --git a/arch/m68knommu/platform/coldfire/pit.c b/arch/m68knommu/platform/coldfire/pit.c
index 2a12e7fa9748..d8720ee34510 100644
--- a/arch/m68knommu/platform/coldfire/pit.c
+++ b/arch/m68knommu/platform/coldfire/pit.c
@@ -32,7 +32,6 @@
*/
#define FREQ ((MCF_CLK / 2) / 64)
#define TA(a) (MCF_IPSBAR + MCFPIT_BASE1 + (a))
-#define INTC0 (MCF_IPSBAR + MCFICM_INTC0)
#define PIT_CYCLES_PER_JIFFY (FREQ / HZ)
static u32 pit_cnt;
@@ -125,7 +124,7 @@ static struct irqaction pit_irq = {
/***************************************************************************/
-static cycle_t pit_read_clk(void)
+static cycle_t pit_read_clk(struct clocksource *cs)
{
unsigned long flags;
u32 cycles;
@@ -154,8 +153,6 @@ static struct clocksource pit_clk = {
void hw_timer_init(void)
{
- u32 imr;
-
cf_pit_clockevent.cpumask = cpumask_of(smp_processor_id());
cf_pit_clockevent.mult = div_sc(FREQ, NSEC_PER_SEC, 32);
cf_pit_clockevent.max_delta_ns =
@@ -166,11 +163,6 @@ void hw_timer_init(void)
setup_irq(MCFINT_VECBASE + MCFINT_PIT1, &pit_irq);
- __raw_writeb(ICR_INTRCONF, INTC0 + MCFINTC_ICR0 + MCFINT_PIT1);
- imr = __raw_readl(INTC0 + MCFPIT_IMR);
- imr &= ~MCFPIT_IMR_IBIT;
- __raw_writel(imr, INTC0 + MCFPIT_IMR);
-
pit_clk.mult = clocksource_hz2mult(FREQ, pit_clk.shift);
clocksource_register(&pit_clk);
}
diff --git a/arch/m68knommu/platform/coldfire/timers.c b/arch/m68knommu/platform/coldfire/timers.c
index 454f25493491..1ba8a3731653 100644
--- a/arch/m68knommu/platform/coldfire/timers.c
+++ b/arch/m68knommu/platform/coldfire/timers.c
@@ -78,7 +78,7 @@ static struct irqaction mcftmr_timer_irq = {
/***************************************************************************/
-static cycle_t mcftmr_read_clk(void)
+static cycle_t mcftmr_read_clk(struct clocksource *cs)
{
unsigned long flags;
u32 cycles;
diff --git a/arch/m68knommu/platform/coldfire/vectors.c b/arch/m68knommu/platform/coldfire/vectors.c
index 6cf894620234..a21d3f870b7a 100644
--- a/arch/m68knommu/platform/coldfire/vectors.c
+++ b/arch/m68knommu/platform/coldfire/vectors.c
@@ -1,7 +1,7 @@
/***************************************************************************/
/*
- * linux/arch/m68knommu/platform/5307/vectors.c
+ * linux/arch/m68knommu/platform/coldfire/vectors.c
*
* Copyright (C) 1999-2007, Greg Ungerer <gerg@snapgear.com>
*/
@@ -15,7 +15,6 @@
#include <asm/machdep.h>
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
-#include <asm/mcfdma.h>
#include <asm/mcfwdebug.h>
/***************************************************************************/
@@ -79,27 +78,3 @@ void __init init_vectors(void)
}
/***************************************************************************/
-
-void enable_vector(unsigned int irq)
-{
- /* Currently no action on ColdFire */
-}
-
-void disable_vector(unsigned int irq)
-{
- /* Currently no action on ColdFire */
-}
-
-void ack_vector(unsigned int irq)
-{
- /* Currently no action on ColdFire */
-}
-
-/***************************************************************************/
-
-void coldfire_reset(void)
-{
- HARD_RESET_NOW();
-}
-
-/***************************************************************************/
diff --git a/arch/microblaze/Makefile b/arch/microblaze/Makefile
index 0dcbb9832974..aaadfa701da3 100644
--- a/arch/microblaze/Makefile
+++ b/arch/microblaze/Makefile
@@ -26,21 +26,19 @@ ifeq (,$(findstring spartan2,$(CONFIG_XILINX_MICROBLAZE0_FAMILY)))
endif
CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_DIV) += -mno-xl-soft-div
CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_BARREL) += -mxl-barrel-shift
-CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_PCMP) += -mxl-pattern-compare
+CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR) += -mxl-pattern-compare
CPUFLAGS-1 += $(call cc-option,-mcpu=v$(CPU_VER))
# The various CONFIG_XILINX cpu features options are integers 0/1/2...
# rather than bools y/n
-CFLAGS += $(CPUFLAGS-1)
-CFLAGS += $(CPUFLAGS-2)
# r31 holds current when in kernel mode
-CFLAGS += -ffixed-r31
+CFLAGS_KERNEL += -ffixed-r31 $(CPUFLAGS-1) $(CPUFLAGS-2)
LDFLAGS_BLOB := --format binary --oformat elf32-microblaze
-LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
+LIBGCC := $(shell $(CC) $(CFLAGS_KERNEL) -print-libgcc-file-name)
head-y := arch/microblaze/kernel/head.o
libs-y += arch/microblaze/lib/ $(LIBGCC)
diff --git a/arch/microblaze/include/asm/auxvec.h b/arch/microblaze/include/asm/auxvec.h
index e69de29bb2d1..8b137891791f 100644
--- a/arch/microblaze/include/asm/auxvec.h
+++ b/arch/microblaze/include/asm/auxvec.h
@@ -0,0 +1 @@
+
diff --git a/arch/microblaze/include/asm/cache.h b/arch/microblaze/include/asm/cache.h
index c4c64b43c074..c209c47509d5 100644
--- a/arch/microblaze/include/asm/cache.h
+++ b/arch/microblaze/include/asm/cache.h
@@ -37,9 +37,4 @@ void _invalidate_dcache(unsigned int addr);
#define __disable_dcache() _disable_dcache()
#define __invalidate_dcache(addr) _invalidate_dcache(addr)
-/* FIXME - I don't think this is right */
-#ifdef CONFIG_XILINX_UNCACHED_SHADOW
-#define UNCACHED_SHADOW_MASK (CONFIG_XILINX_ERAM_SIZE)
-#endif
-
#endif /* _ASM_MICROBLAZE_CACHE_H */
diff --git a/arch/microblaze/include/asm/cputable.h b/arch/microblaze/include/asm/cputable.h
index e69de29bb2d1..8b137891791f 100644
--- a/arch/microblaze/include/asm/cputable.h
+++ b/arch/microblaze/include/asm/cputable.h
@@ -0,0 +1 @@
+
diff --git a/arch/microblaze/include/asm/entry.h b/arch/microblaze/include/asm/entry.h
index 7f57e42ee467..e4c3aef884df 100644
--- a/arch/microblaze/include/asm/entry.h
+++ b/arch/microblaze/include/asm/entry.h
@@ -29,7 +29,9 @@ DECLARE_PER_CPU(unsigned int, KM); /* Kernel/user mode */
DECLARE_PER_CPU(unsigned int, ENTRY_SP); /* Saved SP on kernel entry */
DECLARE_PER_CPU(unsigned int, R11_SAVE); /* Temp variable for entry */
DECLARE_PER_CPU(unsigned int, CURRENT_SAVE); /* Saved current pointer */
-DECLARE_PER_CPU(unsigned int, SYSCALL_SAVE); /* Saved syscall number */
# endif /* __ASSEMBLY__ */
+/* noMMU hasn't any space for args */
+# define STATE_SAVE_ARG_SPACE (0)
+
#endif /* _ASM_MICROBLAZE_ENTRY_H */
diff --git a/arch/microblaze/include/asm/exceptions.h b/arch/microblaze/include/asm/exceptions.h
index 4cdd2159f470..24ca540e77c0 100644
--- a/arch/microblaze/include/asm/exceptions.h
+++ b/arch/microblaze/include/asm/exceptions.h
@@ -61,6 +61,9 @@
asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
int fsr, int addr);
+void die(const char *str, struct pt_regs *fp, long err);
+void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr);
+
#if defined(CONFIG_XMON)
extern void xmon(struct pt_regs *regs);
extern int xmon_bpt(struct pt_regs *regs);
diff --git a/arch/microblaze/include/asm/ftrace.h b/arch/microblaze/include/asm/ftrace.h
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/arch/microblaze/include/asm/ftrace.h
@@ -0,0 +1 @@
+
diff --git a/arch/microblaze/include/asm/hw_irq.h b/arch/microblaze/include/asm/hw_irq.h
index e69de29bb2d1..8b137891791f 100644
--- a/arch/microblaze/include/asm/hw_irq.h
+++ b/arch/microblaze/include/asm/hw_irq.h
@@ -0,0 +1 @@
+
diff --git a/arch/microblaze/include/asm/io.h b/arch/microblaze/include/asm/io.h
index cfab0342588d..8b5853ee6b5c 100644
--- a/arch/microblaze/include/asm/io.h
+++ b/arch/microblaze/include/asm/io.h
@@ -12,7 +12,6 @@
#include <asm/byteorder.h>
#include <asm/page.h>
#include <linux/types.h>
-#include <asm/page.h>
#define IO_SPACE_LIMIT (0xFFFFFFFF)
diff --git a/arch/microblaze/include/asm/of_platform.h b/arch/microblaze/include/asm/of_platform.h
index 187c0eedaece..37491276c6ca 100644
--- a/arch/microblaze/include/asm/of_platform.h
+++ b/arch/microblaze/include/asm/of_platform.h
@@ -36,16 +36,6 @@ static const struct of_device_id of_default_bus_ids[] = {
{},
};
-/* Platform drivers register/unregister */
-static inline int of_register_platform_driver(struct of_platform_driver *drv)
-{
- return of_register_driver(drv, &of_platform_bus_type);
-}
-static inline void of_unregister_platform_driver(struct of_platform_driver *drv)
-{
- of_unregister_driver(drv);
-}
-
/* Platform devices and busses creation */
extern struct of_device *of_platform_device_create(struct device_node *np,
const char *bus_id,
diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h
index d8e15434ba21..9329029d2614 100644
--- a/arch/microblaze/include/asm/processor.h
+++ b/arch/microblaze/include/asm/processor.h
@@ -15,6 +15,8 @@
#include <asm/setup.h>
#include <asm/registers.h>
#include <asm/segment.h>
+#include <asm/entry.h>
+#include <asm/current.h>
# ifndef __ASSEMBLY__
/* from kernel/cpu/mb.c */
@@ -26,6 +28,12 @@ extern const struct seq_operations cpuinfo_op;
# endif /* __ASSEMBLY__ */
+#define task_pt_regs(tsk) \
+ (((struct pt_regs *)(THREAD_SIZE + task_stack_page(tsk))) - 1)
+
+/* Do necessary setup to start up a newly executed thread. */
+void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp);
+
/*
* User space process size: memory size
*
@@ -55,16 +63,6 @@ struct task_struct;
struct thread_struct { };
# define INIT_THREAD { }
-/* Do necessary setup to start up a newly executed thread. */
-static inline void start_thread(struct pt_regs *regs,
- unsigned long pc,
- unsigned long usp)
-{
- regs->pc = pc;
- regs->r1 = usp;
- regs->kernel_mode = 0;
-}
-
/* Free all resources held by a thread. */
static inline void release_thread(struct task_struct *dead_task)
{
@@ -84,9 +82,6 @@ extern unsigned long get_wchan(struct task_struct *p);
*/
extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-# define task_pt_regs(tsk) \
- (((struct pt_regs *)(THREAD_SIZE + task_stack_page(tsk))) - 1)
-
# define KSTK_EIP(tsk) (0)
# define KSTK_ESP(tsk) (0)
diff --git a/arch/microblaze/include/asm/ptrace.h b/arch/microblaze/include/asm/ptrace.h
index f1f03486428a..55015bce5e47 100644
--- a/arch/microblaze/include/asm/ptrace.h
+++ b/arch/microblaze/include/asm/ptrace.h
@@ -52,10 +52,10 @@ struct pt_regs {
microblaze_reg_t ear;
microblaze_reg_t esr;
microblaze_reg_t fsr;
- int kernel_mode;
+ int pt_mode;
};
-#define kernel_mode(regs) ((regs)->kernel_mode)
+#define kernel_mode(regs) ((regs)->pt_mode)
#define user_mode(regs) (!kernel_mode(regs))
#define instruction_pointer(regs) ((regs)->pc)
diff --git a/arch/microblaze/include/asm/socket.h b/arch/microblaze/include/asm/socket.h
index f919b6b540ac..825936860314 100644
--- a/arch/microblaze/include/asm/socket.h
+++ b/arch/microblaze/include/asm/socket.h
@@ -63,4 +63,7 @@
#define SO_MARK 36
+#define SO_TIMESTAMPING 37
+#define SCM_TIMESTAMPING SO_TIMESTAMPING
+
#endif /* _ASM_MICROBLAZE_SOCKET_H */
diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h
index d9d3903fde3f..b5e2f5fa5c53 100644
--- a/arch/microblaze/include/asm/unistd.h
+++ b/arch/microblaze/include/asm/unistd.h
@@ -378,8 +378,10 @@
#define __NR_sendmsg 360 /* new */
#define __NR_recvmsg 361 /* new */
#define __NR_accept04 362 /* new */
+#define __NR_preadv 363 /* new */
+#define __NR_pwritev 364 /* new */
-#define __NR_syscalls 363
+#define __NR_syscalls 365
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
diff --git a/arch/microblaze/include/asm/user.h b/arch/microblaze/include/asm/user.h
index e69de29bb2d1..8b137891791f 100644
--- a/arch/microblaze/include/asm/user.h
+++ b/arch/microblaze/include/asm/user.h
@@ -0,0 +1 @@
+
diff --git a/arch/microblaze/include/asm/vga.h b/arch/microblaze/include/asm/vga.h
index e69de29bb2d1..8b137891791f 100644
--- a/arch/microblaze/include/asm/vga.h
+++ b/arch/microblaze/include/asm/vga.h
@@ -0,0 +1 @@
+
diff --git a/arch/microblaze/kernel/asm-offsets.c b/arch/microblaze/kernel/asm-offsets.c
index 38e1a2e8ad0c..aabd9e9423a6 100644
--- a/arch/microblaze/kernel/asm-offsets.c
+++ b/arch/microblaze/kernel/asm-offsets.c
@@ -57,7 +57,7 @@ int main(int argc, char *argv[])
DEFINE(PT_R29, offsetof(struct pt_regs, r29));
DEFINE(PT_R30, offsetof(struct pt_regs, r30));
DEFINE(PT_R31, offsetof(struct pt_regs, r31));
- DEFINE(PT_MODE, offsetof(struct pt_regs, kernel_mode));
+ DEFINE(PT_MODE, offsetof(struct pt_regs, pt_mode));
BLANK();
/* Magic offsets for PTRACE PEEK/POKE etc */
diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c
index be9fecca4f91..af866a450125 100644
--- a/arch/microblaze/kernel/cpu/cache.c
+++ b/arch/microblaze/kernel/cpu/cache.c
@@ -100,7 +100,6 @@ void _enable_dcache(void)
void _disable_dcache(void)
{
- if (cpuinfo.use_dcache) {
#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
__asm__ __volatile__ (" \
msrclr r0, %0; \
@@ -119,12 +118,10 @@ void _disable_dcache(void)
: "i" (MSR_DCE) \
: "memory", "r12");
#endif
- }
}
void _invalidate_dcache(unsigned int addr)
{
- if (cpuinfo.use_dcache)
__asm__ __volatile__ (" \
wdc %0, r0" \
: \
diff --git a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
index cf7424a6bb87..153f57c57b6d 100644
--- a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
+++ b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
@@ -30,6 +30,13 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
int temp; /* for saving temp value */
get_pvr(&pvr);
+ CI(ver_code, VERSION);
+ if (!ci->ver_code) {
+ printk(KERN_ERR "ERROR: MB has broken PVR regs "
+ "-> use DTS setting\n");
+ return;
+ }
+
temp = PVR_USE_BARREL(pvr) | PVR_USE_MSR_INSTR(pvr) |\
PVR_USE_PCMP_INSTR(pvr) | PVR_USE_DIV(pvr);
if (ci->use_instr != temp)
@@ -60,8 +67,6 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
CI(mmu, USE_MMU);
- CI(ver_code, VERSION);
-
CI(use_icache, USE_ICACHE);
CI(icache_tagbits, ICACHE_ADDR_TAG_BITS);
CI(icache_write, ICACHE_ALLOW_WR);
diff --git a/arch/microblaze/kernel/cpu/cpuinfo-static.c b/arch/microblaze/kernel/cpu/cpuinfo-static.c
index cfe44effdb77..450ca6bb828d 100644
--- a/arch/microblaze/kernel/cpu/cpuinfo-static.c
+++ b/arch/microblaze/kernel/cpu/cpuinfo-static.c
@@ -14,8 +14,8 @@
#include <asm/cpuinfo.h>
#include <asm/pvr.h>
-const static char family_string[] = CONFIG_XILINX_MICROBLAZE0_FAMILY;
-const static char cpu_ver_string[] = CONFIG_XILINX_MICROBLAZE0_HW_VER;
+static const char family_string[] = CONFIG_XILINX_MICROBLAZE0_FAMILY;
+static const char cpu_ver_string[] = CONFIG_XILINX_MICROBLAZE0_HW_VER;
#define err_printk(x) \
early_printk("ERROR: Microblaze " x "- different for kernel and DTS\n");
diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c
index 4a740dfcf6da..a10bea119b94 100644
--- a/arch/microblaze/kernel/cpu/cpuinfo.c
+++ b/arch/microblaze/kernel/cpu/cpuinfo.c
@@ -71,7 +71,7 @@ void __init setup_cpuinfo(void)
__func__);
set_cpuinfo_static(&cpuinfo, cpu);
break;
-/* FIXME I found weird behavior with MB 7.00.a/b
+/* FIXME I found weird behavior with MB 7.00.a/b 7.10.a
* please do not use FULL PVR with MMU */
case 1:
printk(KERN_INFO "%s: Using full CPU PVR support\n",
diff --git a/arch/microblaze/kernel/cpu/mb.c b/arch/microblaze/kernel/cpu/mb.c
index 3b6212bdc8dc..4dcfccdbc364 100644
--- a/arch/microblaze/kernel/cpu/mb.c
+++ b/arch/microblaze/kernel/cpu/mb.c
@@ -115,8 +115,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
cpuinfo.hw_debug ? "yes" : "no");
count += seq_printf(m,
- "PVR-USR1:\t%x\n"
- "PVR-USR2:\t%x\n",
+ "PVR-USR1:\t%02x\n"
+ "PVR-USR2:\t%08x\n",
cpuinfo.pvr_user1,
cpuinfo.pvr_user2);
diff --git a/arch/microblaze/kernel/early_printk.c b/arch/microblaze/kernel/early_printk.c
index 62cc78993f44..4b0f0fdb9ca0 100644
--- a/arch/microblaze/kernel/early_printk.c
+++ b/arch/microblaze/kernel/early_printk.c
@@ -36,7 +36,7 @@ static void early_printk_putc(char c)
unsigned retries = 10000;
/* read status bit - 0x8 offset */
- while (retries-- && (in_be32(base_addr + 8) & (1 << 3)))
+ while (--retries && (in_be32(base_addr + 8) & (1 << 3)))
;
/* Only attempt the iowrite if we didn't timeout */
diff --git a/arch/microblaze/kernel/of_device.c b/arch/microblaze/kernel/of_device.c
index 717edf4ad0b4..9a0f7632c47c 100644
--- a/arch/microblaze/kernel/of_device.c
+++ b/arch/microblaze/kernel/of_device.c
@@ -13,7 +13,6 @@ 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;
@@ -25,9 +24,8 @@ void of_device_make_bus_id(struct of_device *dev)
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);
+ dev_set_name(&dev->dev, "%llx.%s",
+ (unsigned long long)addr, node->name);
return;
}
}
@@ -37,7 +35,7 @@ void of_device_make_bus_id(struct of_device *dev)
* counter (and pray...)
*/
magic = atomic_add_return(1, &bus_no_reg_magic);
- snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1);
+ dev_set_name(&dev->dev, "%s.%d", node->name, magic - 1);
}
EXPORT_SYMBOL(of_device_make_bus_id);
@@ -58,7 +56,7 @@ struct of_device *of_device_alloc(struct device_node *np,
dev->dev.archdata.of_node = np;
if (bus_id)
- strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
+ dev_set_name(&dev->dev, bus_id);
else
of_device_make_bus_id(dev);
diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c
index 60e9ed7d3132..07d4fa339eda 100644
--- a/arch/microblaze/kernel/process.c
+++ b/arch/microblaze/kernel/process.c
@@ -18,7 +18,7 @@
void show_regs(struct pt_regs *regs)
{
- printk(KERN_INFO " Registers dump: mode=%X\r\n", regs->kernel_mode);
+ printk(KERN_INFO " Registers dump: mode=%X\r\n", regs->pt_mode);
printk(KERN_INFO " r1=%08lX, r2=%08lX, r3=%08lX, r4=%08lX\n",
regs->r1, regs->r2, regs->r3, regs->r4);
printk(KERN_INFO " r5=%08lX, r6=%08lX, r7=%08lX, r8=%08lX\n",
@@ -37,8 +37,6 @@ void show_regs(struct pt_regs *regs)
regs->r29, regs->r30, regs->r31, regs->pc);
printk(KERN_INFO " msr=%08lX, ear=%08lX, esr=%08lX, fsr=%08lX\n",
regs->msr, regs->ear, regs->esr, regs->fsr);
- while (1)
- ;
}
void (*pm_idle)(void);
@@ -115,8 +113,7 @@ void flush_thread(void)
{
}
-/* FIXME - here will be a proposed change -> remove nr parameter */
-int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+int copy_thread(unsigned long clone_flags, unsigned long usp,
unsigned long unused,
struct task_struct *p, struct pt_regs *regs)
{
@@ -164,7 +161,6 @@ static void kernel_thread_helper(int (*fn)(void *), void *arg)
int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
{
struct pt_regs regs;
- int ret;
memset(&regs, 0, sizeof(regs));
/* store them in non-volatile registers */
@@ -172,12 +168,10 @@ int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
regs.r6 = (unsigned long)arg;
local_save_flags(regs.msr);
regs.pc = (unsigned long)kernel_thread_helper;
- regs.kernel_mode = 1;
+ regs.pt_mode = 1;
- ret = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
+ return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
&regs, 0, NULL, NULL);
-
- return ret;
}
unsigned long get_wchan(struct task_struct *p)
@@ -185,3 +179,12 @@ unsigned long get_wchan(struct task_struct *p)
/* TBD (used by procfs) */
return 0;
}
+
+/* Set up a thread for executing a new program */
+void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp)
+{
+ set_fs(USER_DS);
+ regs->pc = pc;
+ regs->r1 = usp;
+ regs->pt_mode = 0;
+}
diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
index 475b1fac5cfd..34c48718061a 100644
--- a/arch/microblaze/kernel/prom.c
+++ b/arch/microblaze/kernel/prom.c
@@ -39,7 +39,6 @@
#include <asm/system.h>
#include <asm/mmu.h>
#include <asm/pgtable.h>
-#include <linux/pci.h>
#include <asm/sections.h>
#include <asm/pci-bridge.h>
diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c
index 3171e39e3220..b86aa623e36d 100644
--- a/arch/microblaze/kernel/ptrace.c
+++ b/arch/microblaze/kernel/ptrace.c
@@ -32,7 +32,6 @@
#include <linux/signal.h>
#include <linux/errno.h>
-#include <linux/ptrace.h>
#include <asm/processor.h>
#include <linux/uaccess.h>
#include <asm/asm-offsets.h>
diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c
index ff347b98863a..40d36931e363 100644
--- a/arch/microblaze/kernel/signal.c
+++ b/arch/microblaze/kernel/signal.c
@@ -37,7 +37,6 @@
#include <linux/uaccess.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
-#include <linux/signal.h>
#include <linux/syscalls.h>
#include <asm/cacheflush.h>
#include <asm/syscalls.h>
@@ -179,7 +178,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *rval_p)
asmlinkage int sys_sigreturn(struct pt_regs *regs)
{
- struct sigframe *frame = (struct sigframe *)regs->r1;
+ struct sigframe *frame =
+ (struct sigframe *)(regs->r1 + STATE_SAVE_ARG_SPACE);
+
sigset_t set;
int rval;
@@ -210,7 +211,9 @@ badframe:
asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
{
- struct rt_sigframe *frame = (struct rt_sigframe *)regs->r1;
+ struct rt_sigframe *frame =
+ (struct rt_sigframe *)(regs->r1 + STATE_SAVE_ARG_SPACE);
+
sigset_t set;
stack_t st;
int rval;
@@ -337,7 +340,8 @@ static void setup_frame(int sig, struct k_sigaction *ka,
goto give_sigsegv;
/* Set up registers for signal handler */
- regs->r1 = (unsigned long) frame;
+ regs->r1 = (unsigned long) frame - STATE_SAVE_ARG_SPACE;
+
/* Signal handler args: */
regs->r5 = signal; /* Arg 0: signum */
regs->r6 = (unsigned long) &frame->sc; /* arg 1: sigcontext */
@@ -415,7 +419,8 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
goto give_sigsegv;
/* Set up registers for signal handler */
- regs->r1 = (unsigned long) frame;
+ regs->r1 = (unsigned long) frame - STATE_SAVE_ARG_SPACE;
+
/* Signal handler args: */
regs->r5 = signal; /* arg 0: signum */
regs->r6 = (unsigned long) &frame->info; /* arg 1: siginfo */
diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c
index d90b548fb1bb..31905ff590b7 100644
--- a/arch/microblaze/kernel/sys_microblaze.c
+++ b/arch/microblaze/kernel/sys_microblaze.c
@@ -29,9 +29,7 @@
#include <linux/module.h>
#include <linux/err.h>
#include <linux/fs.h>
-#include <linux/ipc.h>
#include <linux/semaphore.h>
-#include <linux/syscalls.h>
#include <linux/uaccess.h>
#include <linux/unistd.h>
@@ -133,7 +131,7 @@ sys_ipc(uint call, int first, int second, int third, void *ptr, long fifth)
ret = sys_shmctl(first, second, (struct shmid_ds *) ptr);
break;
}
- return -EINVAL;
+ return ret;
}
asmlinkage int sys_vfork(struct pt_regs *regs)
diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S
index 529b0dbf4fe9..3bb42ec924c2 100644
--- a/arch/microblaze/kernel/syscall_table.S
+++ b/arch/microblaze/kernel/syscall_table.S
@@ -363,3 +363,5 @@ ENTRY(sys_call_table)
.long sys_sendmsg /* 360 */
.long sys_recvmsg
.long sys_ni_syscall
+ .long sys_ni_syscall
+ .long sys_ni_syscall
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c
index 05a497eefd78..bdfa2f9f0c81 100644
--- a/arch/microblaze/kernel/timer.c
+++ b/arch/microblaze/kernel/timer.c
@@ -176,7 +176,7 @@ static __init void microblaze_clockevent_init(void)
clockevents_register_device(&clockevent_microblaze_timer);
}
-static cycle_t microblaze_read(void)
+static cycle_t microblaze_read(struct clocksource *cs)
{
/* reading actual value of timer 1 */
return (cycle_t) (in_be32(TIMER_BASE + TCR1));
diff --git a/arch/microblaze/kernel/traps.c b/arch/microblaze/kernel/traps.c
index fbdc533c61e3..293ef486013a 100644
--- a/arch/microblaze/kernel/traps.c
+++ b/arch/microblaze/kernel/traps.c
@@ -34,7 +34,7 @@ static int kstack_depth_to_print = 24;
static int __init kstack_setup(char *s)
{
- kstack_depth_to_print = strict_strtoul(s, 0, 0);
+ kstack_depth_to_print = strict_strtoul(s, 0, NULL);
return 1;
}
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 998e5db8cc0f..db97aa101f5f 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -617,6 +617,8 @@ config CAVIUM_OCTEON_REFERENCE_BOARD
select SYS_HAS_EARLY_PRINTK
select SYS_HAS_CPU_CAVIUM_OCTEON
select SWAP_IO_SPACE
+ select HW_HAS_PCI
+ select ARCH_SUPPORTS_MSI
help
This option supports all of the Octeon reference boards from Cavium
Networks. It builds a kernel that dynamically determines the Octeon
diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
index d6903c3f3d51..7c0528b0e34c 100644
--- a/arch/mips/cavium-octeon/Makefile
+++ b/arch/mips/cavium-octeon/Makefile
@@ -14,5 +14,9 @@ obj-y += dma-octeon.o flash_setup.o
obj-y += octeon-memcpy.o
obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_PCI) += pci-common.o
+obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_PCI) += pcie.o
+obj-$(CONFIG_PCI_MSI) += msi.o
EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c
index 01b1ef94b361..627c162a6159 100644
--- a/arch/mips/cavium-octeon/dma-octeon.c
+++ b/arch/mips/cavium-octeon/dma-octeon.c
@@ -13,20 +13,327 @@
*/
#include <linux/types.h>
#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/scatterlist.h>
+
+#include <linux/cache.h>
+#include <linux/io.h>
+
+#include <asm/octeon/octeon.h>
+#include <asm/octeon/cvmx-npi-defs.h>
+#include <asm/octeon/cvmx-pci-defs.h>
#include <dma-coherence.h>
+#ifdef CONFIG_PCI
+#include "pci-common.h"
+#endif
+
+#define BAR2_PCI_ADDRESS 0x8000000000ul
+
+struct bar1_index_state {
+ int16_t ref_count; /* Number of PCI mappings using this index */
+ uint16_t address_bits; /* Upper bits of physical address. This is
+ shifted 22 bits */
+};
+
+#ifdef CONFIG_PCI
+static DEFINE_SPINLOCK(bar1_lock);
+static struct bar1_index_state bar1_state[32];
+#endif
+
dma_addr_t octeon_map_dma_mem(struct device *dev, void *ptr, size_t size)
{
+#ifndef CONFIG_PCI
/* Without PCI/PCIe this function can be called for Octeon internal
devices such as USB. These devices all support 64bit addressing */
mb();
return virt_to_phys(ptr);
+#else
+ unsigned long flags;
+ uint64_t dma_mask;
+ int64_t start_index;
+ dma_addr_t result = -1;
+ uint64_t physical = virt_to_phys(ptr);
+ int64_t index;
+
+ mb();
+ /*
+ * Use the DMA masks to determine the allowed memory
+ * region. For us it doesn't limit the actual memory, just the
+ * address visible over PCI. Devices with limits need to use
+ * lower indexed Bar1 entries.
+ */
+ if (dev) {
+ dma_mask = dev->coherent_dma_mask;
+ if (dev->dma_mask)
+ dma_mask = *dev->dma_mask;
+ } else {
+ dma_mask = 0xfffffffful;
+ }
+
+ /*
+ * Platform devices, such as the internal USB, skip all
+ * translation and use Octeon physical addresses directly.
+ */
+ if (!dev || dev->bus == &platform_bus_type)
+ return physical;
+
+ switch (octeon_dma_bar_type) {
+ case OCTEON_DMA_BAR_TYPE_PCIE:
+ if (unlikely(physical < (16ul << 10)))
+ panic("dma_map_single: Not allowed to map first 16KB."
+ " It interferes with BAR0 special area\n");
+ else if ((physical + size >= (256ul << 20)) &&
+ (physical < (512ul << 20)))
+ panic("dma_map_single: Not allowed to map bootbus\n");
+ else if ((physical + size >= 0x400000000ull) &&
+ physical < 0x410000000ull)
+ panic("dma_map_single: "
+ "Attempt to map illegal memory address 0x%llx\n",
+ physical);
+ else if (physical >= 0x420000000ull)
+ panic("dma_map_single: "
+ "Attempt to map illegal memory address 0x%llx\n",
+ physical);
+ else if ((physical + size >=
+ (4ull<<30) - (OCTEON_PCI_BAR1_HOLE_SIZE<<20))
+ && physical < (4ull<<30))
+ pr_warning("dma_map_single: Warning: "
+ "Mapping memory address that might "
+ "conflict with devices 0x%llx-0x%llx\n",
+ physical, physical+size-1);
+ /* The 2nd 256MB is mapped at 256<<20 instead of 0x410000000 */
+ if ((physical >= 0x410000000ull) && physical < 0x420000000ull)
+ result = physical - 0x400000000ull;
+ else
+ result = physical;
+ if (((result+size-1) & dma_mask) != result+size-1)
+ panic("dma_map_single: Attempt to map address "
+ "0x%llx-0x%llx, which can't be accessed "
+ "according to the dma mask 0x%llx\n",
+ physical, physical+size-1, dma_mask);
+ goto done;
+
+ case OCTEON_DMA_BAR_TYPE_BIG:
+#ifdef CONFIG_64BIT
+ /* If the device supports 64bit addressing, then use BAR2 */
+ if (dma_mask > BAR2_PCI_ADDRESS) {
+ result = physical + BAR2_PCI_ADDRESS;
+ goto done;
+ }
+#endif
+ if (unlikely(physical < (4ul << 10))) {
+ panic("dma_map_single: Not allowed to map first 4KB. "
+ "It interferes with BAR0 special area\n");
+ } else if (physical < (256ul << 20)) {
+ if (unlikely(physical + size > (256ul << 20)))
+ panic("dma_map_single: Requested memory spans "
+ "Bar0 0:256MB and bootbus\n");
+ result = physical;
+ goto done;
+ } else if (unlikely(physical < (512ul << 20))) {
+ panic("dma_map_single: Not allowed to map bootbus\n");
+ } else if (physical < (2ul << 30)) {
+ if (unlikely(physical + size > (2ul << 30)))
+ panic("dma_map_single: Requested memory spans "
+ "Bar0 512MB:2GB and BAR1\n");
+ result = physical;
+ goto done;
+ } else if (physical < (2ul << 30) + (128 << 20)) {
+ /* Fall through */
+ } else if (physical <
+ (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20)) {
+ if (unlikely
+ (physical + size >
+ (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20)))
+ panic("dma_map_single: Requested memory "
+ "extends past Bar1 (4GB-%luMB)\n",
+ OCTEON_PCI_BAR1_HOLE_SIZE);
+ result = physical;
+ goto done;
+ } else if ((physical >= 0x410000000ull) &&
+ (physical < 0x420000000ull)) {
+ if (unlikely(physical + size > 0x420000000ull))
+ panic("dma_map_single: Requested memory spans "
+ "non existant memory\n");
+ /* BAR0 fixed mapping 256MB:512MB ->
+ * 16GB+256MB:16GB+512MB */
+ result = physical - 0x400000000ull;
+ goto done;
+ } else {
+ /* Continued below switch statement */
+ }
+ break;
+
+ case OCTEON_DMA_BAR_TYPE_SMALL:
+#ifdef CONFIG_64BIT
+ /* If the device supports 64bit addressing, then use BAR2 */
+ if (dma_mask > BAR2_PCI_ADDRESS) {
+ result = physical + BAR2_PCI_ADDRESS;
+ goto done;
+ }
+#endif
+ /* Continued below switch statement */
+ break;
+
+ default:
+ panic("dma_map_single: Invalid octeon_dma_bar_type\n");
+ }
+
+ /* Don't allow mapping to span multiple Bar entries. The hardware guys
+ won't guarantee that DMA across boards work */
+ if (unlikely((physical >> 22) != ((physical + size - 1) >> 22)))
+ panic("dma_map_single: "
+ "Requested memory spans more than one Bar1 entry\n");
+
+ if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG)
+ start_index = 31;
+ else if (unlikely(dma_mask < (1ul << 27)))
+ start_index = (dma_mask >> 22);
+ else
+ start_index = 31;
+
+ /* Only one processor can access the Bar register at once */
+ spin_lock_irqsave(&bar1_lock, flags);
+
+ /* Look through Bar1 for existing mapping that will work */
+ for (index = start_index; index >= 0; index--) {
+ if ((bar1_state[index].address_bits == physical >> 22) &&
+ (bar1_state[index].ref_count)) {
+ /* An existing mapping will work, use it */
+ bar1_state[index].ref_count++;
+ if (unlikely(bar1_state[index].ref_count < 0))
+ panic("dma_map_single: "
+ "Bar1[%d] reference count overflowed\n",
+ (int) index);
+ result = (index << 22) | (physical & ((1 << 22) - 1));
+ /* Large BAR1 is offset at 2GB */
+ if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG)
+ result += 2ul << 30;
+ goto done_unlock;
+ }
+ }
+
+ /* No existing mappings, look for a free entry */
+ for (index = start_index; index >= 0; index--) {
+ if (unlikely(bar1_state[index].ref_count == 0)) {
+ union cvmx_pci_bar1_indexx bar1_index;
+ /* We have a free entry, use it */
+ bar1_state[index].ref_count = 1;
+ bar1_state[index].address_bits = physical >> 22;
+ bar1_index.u32 = 0;
+ /* Address bits[35:22] sent to L2C */
+ bar1_index.s.addr_idx = physical >> 22;
+ /* Don't put PCI accesses in L2. */
+ bar1_index.s.ca = 1;
+ /* Endian Swap Mode */
+ bar1_index.s.end_swp = 1;
+ /* Set '1' when the selected address range is valid. */
+ bar1_index.s.addr_v = 1;
+ octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index),
+ bar1_index.u32);
+ /* An existing mapping will work, use it */
+ result = (index << 22) | (physical & ((1 << 22) - 1));
+ /* Large BAR1 is offset at 2GB */
+ if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG)
+ result += 2ul << 30;
+ goto done_unlock;
+ }
+ }
+
+ pr_err("dma_map_single: "
+ "Can't find empty BAR1 index for physical mapping 0x%llx\n",
+ (unsigned long long) physical);
+
+done_unlock:
+ spin_unlock_irqrestore(&bar1_lock, flags);
+done:
+ pr_debug("dma_map_single 0x%llx->0x%llx\n", physical, result);
+ return result;
+#endif
}
void octeon_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
{
- /* Without PCI/PCIe this function can be called for Octeon internal
- * devices such as USB. These devices all support 64bit addressing */
+#ifndef CONFIG_PCI
+ /*
+ * Without PCI/PCIe this function can be called for Octeon internal
+ * devices such as USB. These devices all support 64bit addressing.
+ */
+ return;
+#else
+ unsigned long flags;
+ uint64_t index;
+
+ /*
+ * Platform devices, such as the internal USB, skip all
+ * translation and use Octeon physical addresses directly.
+ */
+ if (dev->bus == &platform_bus_type)
+ return;
+
+ switch (octeon_dma_bar_type) {
+ case OCTEON_DMA_BAR_TYPE_PCIE:
+ /* Nothing to do, all mappings are static */
+ goto done;
+
+ case OCTEON_DMA_BAR_TYPE_BIG:
+#ifdef CONFIG_64BIT
+ /* Nothing to do for addresses using BAR2 */
+ if (dma_addr >= BAR2_PCI_ADDRESS)
+ goto done;
+#endif
+ if (unlikely(dma_addr < (4ul << 10)))
+ panic("dma_unmap_single: Unexpect DMA address 0x%llx\n",
+ dma_addr);
+ else if (dma_addr < (2ul << 30))
+ /* Nothing to do for addresses using BAR0 */
+ goto done;
+ else if (dma_addr < (2ul << 30) + (128ul << 20))
+ /* Need to unmap, fall through */
+ index = (dma_addr - (2ul << 30)) >> 22;
+ else if (dma_addr <
+ (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20))
+ goto done; /* Nothing to do for the rest of BAR1 */
+ else
+ panic("dma_unmap_single: Unexpect DMA address 0x%llx\n",
+ dma_addr);
+ /* Continued below switch statement */
+ break;
+
+ case OCTEON_DMA_BAR_TYPE_SMALL:
+#ifdef CONFIG_64BIT
+ /* Nothing to do for addresses using BAR2 */
+ if (dma_addr >= BAR2_PCI_ADDRESS)
+ goto done;
+#endif
+ index = dma_addr >> 22;
+ /* Continued below switch statement */
+ break;
+
+ default:
+ panic("dma_unmap_single: Invalid octeon_dma_bar_type\n");
+ }
+
+ if (unlikely(index > 31))
+ panic("dma_unmap_single: "
+ "Attempt to unmap an invalid address (0x%llx)\n",
+ dma_addr);
+
+ spin_lock_irqsave(&bar1_lock, flags);
+ bar1_state[index].ref_count--;
+ if (bar1_state[index].ref_count == 0)
+ octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index), 0);
+ else if (unlikely(bar1_state[index].ref_count < 0))
+ panic("dma_unmap_single: Bar1[%u] reference count < 0\n",
+ (int) index);
+ spin_unlock_irqrestore(&bar1_lock, flags);
+done:
+ pr_debug("dma_unmap_single 0x%llx\n", dma_addr);
return;
+#endif
}
diff --git a/arch/mips/cavium-octeon/executive/Makefile b/arch/mips/cavium-octeon/executive/Makefile
index 80d6cb26766b..2fd66db6939e 100644
--- a/arch/mips/cavium-octeon/executive/Makefile
+++ b/arch/mips/cavium-octeon/executive/Makefile
@@ -11,3 +11,4 @@
obj-y += cvmx-bootmem.o cvmx-l2c.o cvmx-sysinfo.o octeon-model.o
+obj-$(CONFIG_PCI) += cvmx-helper-errata.o cvmx-helper-jtag.o
diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-errata.c b/arch/mips/cavium-octeon/executive/cvmx-helper-errata.c
new file mode 100644
index 000000000000..8fb82057cd80
--- /dev/null
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-errata.c
@@ -0,0 +1,70 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/**
+ *
+ * Fixes and workaround for Octeon chip errata. This file
+ * contains functions called by cvmx-helper to workaround known
+ * chip errata. For the most part, code doesn't need to call
+ * these functions directly.
+ *
+ */
+#include <asm/octeon/octeon.h>
+
+#include <asm/octeon/cvmx-helper-jtag.h>
+
+/**
+ * Due to errata G-720, the 2nd order CDR circuit on CN52XX pass
+ * 1 doesn't work properly. The following code disables 2nd order
+ * CDR for the specified QLM.
+ *
+ * @qlm: QLM to disable 2nd order CDR for.
+ */
+void __cvmx_helper_errata_qlm_disable_2nd_order_cdr(int qlm)
+{
+ int lane;
+ cvmx_helper_qlm_jtag_init();
+ /* We need to load all four lanes of the QLM, a total of 1072 bits */
+ for (lane = 0; lane < 4; lane++) {
+ /*
+ * Each lane has 268 bits. We need to set
+ * cfg_cdr_incx<67:64> = 3 and cfg_cdr_secord<77> =
+ * 1. All other bits are zero. Bits go in LSB first,
+ * so start off with the zeros for bits <63:0>.
+ */
+ cvmx_helper_qlm_jtag_shift_zeros(qlm, 63 - 0 + 1);
+ /* cfg_cdr_incx<67:64>=3 */
+ cvmx_helper_qlm_jtag_shift(qlm, 67 - 64 + 1, 3);
+ /* Zeros for bits <76:68> */
+ cvmx_helper_qlm_jtag_shift_zeros(qlm, 76 - 68 + 1);
+ /* cfg_cdr_secord<77>=1 */
+ cvmx_helper_qlm_jtag_shift(qlm, 77 - 77 + 1, 1);
+ /* Zeros for bits <267:78> */
+ cvmx_helper_qlm_jtag_shift_zeros(qlm, 267 - 78 + 1);
+ }
+ cvmx_helper_qlm_jtag_update(qlm);
+}
diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-jtag.c b/arch/mips/cavium-octeon/executive/cvmx-helper-jtag.c
new file mode 100644
index 000000000000..c1c54890bae0
--- /dev/null
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-jtag.c
@@ -0,0 +1,144 @@
+
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/**
+ *
+ * Helper utilities for qlm_jtag.
+ *
+ */
+
+#include <asm/octeon/octeon.h>
+#include <asm/octeon/cvmx-helper-jtag.h>
+
+
+/**
+ * Initialize the internal QLM JTAG logic to allow programming
+ * of the JTAG chain by the cvmx_helper_qlm_jtag_*() functions.
+ * These functions should only be used at the direction of Cavium
+ * Networks. Programming incorrect values into the JTAG chain
+ * can cause chip damage.
+ */
+void cvmx_helper_qlm_jtag_init(void)
+{
+ union cvmx_ciu_qlm_jtgc jtgc;
+ uint32_t clock_div = 0;
+ uint32_t divisor = cvmx_sysinfo_get()->cpu_clock_hz / (25 * 1000000);
+ divisor = (divisor - 1) >> 2;
+ /* Convert the divisor into a power of 2 shift */
+ while (divisor) {
+ clock_div++;
+ divisor = divisor >> 1;
+ }
+
+ /*
+ * Clock divider for QLM JTAG operations. eclk is divided by
+ * 2^(CLK_DIV + 2)
+ */
+ jtgc.u64 = 0;
+ jtgc.s.clk_div = clock_div;
+ jtgc.s.mux_sel = 0;
+ if (OCTEON_IS_MODEL(OCTEON_CN52XX))
+ jtgc.s.bypass = 0x3;
+ else
+ jtgc.s.bypass = 0xf;
+ cvmx_write_csr(CVMX_CIU_QLM_JTGC, jtgc.u64);
+ cvmx_read_csr(CVMX_CIU_QLM_JTGC);
+}
+
+/**
+ * Write up to 32bits into the QLM jtag chain. Bits are shifted
+ * into the MSB and out the LSB, so you should shift in the low
+ * order bits followed by the high order bits. The JTAG chain is
+ * 4 * 268 bits long, or 1072.
+ *
+ * @qlm: QLM to shift value into
+ * @bits: Number of bits to shift in (1-32).
+ * @data: Data to shift in. Bit 0 enters the chain first, followed by
+ * bit 1, etc.
+ *
+ * Returns The low order bits of the JTAG chain that shifted out of the
+ * circle.
+ */
+uint32_t cvmx_helper_qlm_jtag_shift(int qlm, int bits, uint32_t data)
+{
+ union cvmx_ciu_qlm_jtgd jtgd;
+ jtgd.u64 = 0;
+ jtgd.s.shift = 1;
+ jtgd.s.shft_cnt = bits - 1;
+ jtgd.s.shft_reg = data;
+ if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X))
+ jtgd.s.select = 1 << qlm;
+ cvmx_write_csr(CVMX_CIU_QLM_JTGD, jtgd.u64);
+ do {
+ jtgd.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGD);
+ } while (jtgd.s.shift);
+ return jtgd.s.shft_reg >> (32 - bits);
+}
+
+/**
+ * Shift long sequences of zeros into the QLM JTAG chain. It is
+ * common to need to shift more than 32 bits of zeros into the
+ * chain. This function is a convience wrapper around
+ * cvmx_helper_qlm_jtag_shift() to shift more than 32 bits of
+ * zeros at a time.
+ *
+ * @qlm: QLM to shift zeros into
+ * @bits:
+ */
+void cvmx_helper_qlm_jtag_shift_zeros(int qlm, int bits)
+{
+ while (bits > 0) {
+ int n = bits;
+ if (n > 32)
+ n = 32;
+ cvmx_helper_qlm_jtag_shift(qlm, n, 0);
+ bits -= n;
+ }
+}
+
+/**
+ * Program the QLM JTAG chain into all lanes of the QLM. You must
+ * have already shifted in 268*4, or 1072 bits into the JTAG
+ * chain. Updating invalid values can possibly cause chip damage.
+ *
+ * @qlm: QLM to program
+ */
+void cvmx_helper_qlm_jtag_update(int qlm)
+{
+ union cvmx_ciu_qlm_jtgd jtgd;
+
+ /* Update the new data */
+ jtgd.u64 = 0;
+ jtgd.s.update = 1;
+ if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X))
+ jtgd.s.select = 1 << qlm;
+ cvmx_write_csr(CVMX_CIU_QLM_JTGD, jtgd.u64);
+ do {
+ jtgd.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGD);
+ } while (jtgd.s.update);
+}
diff --git a/arch/mips/cavium-octeon/msi.c b/arch/mips/cavium-octeon/msi.c
new file mode 100644
index 000000000000..964b03b75a8f
--- /dev/null
+++ b/arch/mips/cavium-octeon/msi.c
@@ -0,0 +1,288 @@
+/*
+ * 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-2007 Cavium Networks
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/msi.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+
+#include <asm/octeon/octeon.h>
+#include <asm/octeon/cvmx-npi-defs.h>
+#include <asm/octeon/cvmx-pci-defs.h>
+#include <asm/octeon/cvmx-npei-defs.h>
+#include <asm/octeon/cvmx-pexp-defs.h>
+
+#include "pci-common.h"
+
+/*
+ * Each bit in msi_free_irq_bitmask represents a MSI interrupt that is
+ * in use.
+ */
+static uint64_t msi_free_irq_bitmask;
+
+/*
+ * Each bit in msi_multiple_irq_bitmask tells that the device using
+ * this bit in msi_free_irq_bitmask is also using the next bit. This
+ * is used so we can disable all of the MSI interrupts when a device
+ * uses multiple.
+ */
+static uint64_t msi_multiple_irq_bitmask;
+
+/*
+ * This lock controls updates to msi_free_irq_bitmask and
+ * msi_multiple_irq_bitmask.
+ */
+static DEFINE_SPINLOCK(msi_free_irq_bitmask_lock);
+
+
+/**
+ * Called when a driver request MSI interrupts instead of the
+ * legacy INT A-D. This routine will allocate multiple interrupts
+ * for MSI devices that support them. A device can override this by
+ * programming the MSI control bits [6:4] before calling
+ * pci_enable_msi().
+ *
+ * @param dev Device requesting MSI interrupts
+ * @param desc MSI descriptor
+ *
+ * Returns 0 on success.
+ */
+int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
+{
+ struct msi_msg msg;
+ uint16_t control;
+ int configured_private_bits;
+ int request_private_bits;
+ int irq;
+ int irq_step;
+ uint64_t search_mask;
+
+ /*
+ * Read the MSI config to figure out how many IRQs this device
+ * wants. Most devices only want 1, which will give
+ * configured_private_bits and request_private_bits equal 0.
+ */
+ pci_read_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS,
+ &control);
+
+ /*
+ * If the number of private bits has been configured then use
+ * that value instead of the requested number. This gives the
+ * driver the chance to override the number of interrupts
+ * before calling pci_enable_msi().
+ */
+ configured_private_bits = (control & PCI_MSI_FLAGS_QSIZE) >> 4;
+ if (configured_private_bits == 0) {
+ /* Nothing is configured, so use the hardware requested size */
+ request_private_bits = (control & PCI_MSI_FLAGS_QMASK) >> 1;
+ } else {
+ /*
+ * Use the number of configured bits, assuming the
+ * driver wanted to override the hardware request
+ * value.
+ */
+ request_private_bits = configured_private_bits;
+ }
+
+ /*
+ * The PCI 2.3 spec mandates that there are at most 32
+ * interrupts. If this device asks for more, only give it one.
+ */
+ if (request_private_bits > 5)
+ request_private_bits = 0;
+
+try_only_one:
+ /*
+ * The IRQs have to be aligned on a power of two based on the
+ * number being requested.
+ */
+ irq_step = 1 << request_private_bits;
+
+ /* Mask with one bit for each IRQ */
+ search_mask = (1 << irq_step) - 1;
+
+ /*
+ * We're going to search msi_free_irq_bitmask_lock for zero
+ * bits. This represents an MSI interrupt number that isn't in
+ * use.
+ */
+ spin_lock(&msi_free_irq_bitmask_lock);
+ for (irq = 0; irq < 64; irq += irq_step) {
+ if ((msi_free_irq_bitmask & (search_mask << irq)) == 0) {
+ msi_free_irq_bitmask |= search_mask << irq;
+ msi_multiple_irq_bitmask |= (search_mask >> 1) << irq;
+ break;
+ }
+ }
+ spin_unlock(&msi_free_irq_bitmask_lock);
+
+ /* Make sure the search for available interrupts didn't fail */
+ if (irq >= 64) {
+ if (request_private_bits) {
+ pr_err("arch_setup_msi_irq: Unable to find %d free "
+ "interrupts, trying just one",
+ 1 << request_private_bits);
+ request_private_bits = 0;
+ goto try_only_one;
+ } else
+ panic("arch_setup_msi_irq: Unable to find a free MSI "
+ "interrupt");
+ }
+
+ /* MSI interrupts start at logical IRQ OCTEON_IRQ_MSI_BIT0 */
+ irq += OCTEON_IRQ_MSI_BIT0;
+
+ switch (octeon_dma_bar_type) {
+ case OCTEON_DMA_BAR_TYPE_SMALL:
+ /* When not using big bar, Bar 0 is based at 128MB */
+ msg.address_lo =
+ ((128ul << 20) + CVMX_PCI_MSI_RCV) & 0xffffffff;
+ msg.address_hi = ((128ul << 20) + CVMX_PCI_MSI_RCV) >> 32;
+ case OCTEON_DMA_BAR_TYPE_BIG:
+ /* When using big bar, Bar 0 is based at 0 */
+ msg.address_lo = (0 + CVMX_PCI_MSI_RCV) & 0xffffffff;
+ msg.address_hi = (0 + CVMX_PCI_MSI_RCV) >> 32;
+ break;
+ case OCTEON_DMA_BAR_TYPE_PCIE:
+ /* When using PCIe, Bar 0 is based at 0 */
+ /* FIXME CVMX_NPEI_MSI_RCV* other than 0? */
+ msg.address_lo = (0 + CVMX_NPEI_PCIE_MSI_RCV) & 0xffffffff;
+ msg.address_hi = (0 + CVMX_NPEI_PCIE_MSI_RCV) >> 32;
+ break;
+ default:
+ panic("arch_setup_msi_irq: Invalid octeon_dma_bar_type\n");
+ }
+ msg.data = irq - OCTEON_IRQ_MSI_BIT0;
+
+ /* Update the number of IRQs the device has available to it */
+ control &= ~PCI_MSI_FLAGS_QSIZE;
+ control |= request_private_bits << 4;
+ pci_write_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS,
+ control);
+
+ set_irq_msi(irq, desc);
+ write_msi_msg(irq, &msg);
+ return 0;
+}
+
+
+/**
+ * Called when a device no longer needs its MSI interrupts. All
+ * MSI interrupts for the device are freed.
+ *
+ * @irq: The devices first irq number. There may be multple in sequence.
+ */
+void arch_teardown_msi_irq(unsigned int irq)
+{
+ int number_irqs;
+ uint64_t bitmask;
+
+ if ((irq < OCTEON_IRQ_MSI_BIT0) || (irq > OCTEON_IRQ_MSI_BIT63))
+ panic("arch_teardown_msi_irq: Attempted to teardown illegal "
+ "MSI interrupt (%d)", irq);
+ irq -= OCTEON_IRQ_MSI_BIT0;
+
+ /*
+ * Count the number of IRQs we need to free by looking at the
+ * msi_multiple_irq_bitmask. Each bit set means that the next
+ * IRQ is also owned by this device.
+ */
+ number_irqs = 0;
+ while ((irq+number_irqs < 64) &&
+ (msi_multiple_irq_bitmask & (1ull << (irq + number_irqs))))
+ number_irqs++;
+ number_irqs++;
+ /* Mask with one bit for each IRQ */
+ bitmask = (1 << number_irqs) - 1;
+ /* Shift the mask to the correct bit location */
+ bitmask <<= irq;
+ if ((msi_free_irq_bitmask & bitmask) != bitmask)
+ panic("arch_teardown_msi_irq: Attempted to teardown MSI "
+ "interrupt (%d) not in use", irq);
+
+ /* Checks are done, update the in use bitmask */
+ spin_lock(&msi_free_irq_bitmask_lock);
+ msi_free_irq_bitmask &= ~bitmask;
+ msi_multiple_irq_bitmask &= ~bitmask;
+ spin_unlock(&msi_free_irq_bitmask_lock);
+}
+
+
+/**
+ * Called by the interrupt handling code when an MSI interrupt
+ * occurs.
+ *
+ * @param cpl
+ * @param dev_id
+ *
+ * @return
+ */
+static irqreturn_t octeon_msi_interrupt(int cpl, void *dev_id)
+{
+ uint64_t msi_bits;
+ int irq;
+
+ if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_PCIE)
+ msi_bits = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_RCV0);
+ else
+ msi_bits = cvmx_read_csr(CVMX_NPI_NPI_MSI_RCV);
+ irq = fls64(msi_bits);
+ if (irq) {
+ irq += OCTEON_IRQ_MSI_BIT0 - 1;
+ if (irq_desc[irq].action) {
+ do_IRQ(irq);
+ return IRQ_HANDLED;
+ } else {
+ pr_err("Spurious MSI interrupt %d\n", irq);
+ if (octeon_has_feature(OCTEON_FEATURE_PCIE)) {
+ /* These chips have PCIe */
+ cvmx_write_csr(CVMX_PEXP_NPEI_MSI_RCV0,
+ 1ull << (irq -
+ OCTEON_IRQ_MSI_BIT0));
+ } else {
+ /* These chips have PCI */
+ cvmx_write_csr(CVMX_NPI_NPI_MSI_RCV,
+ 1ull << (irq -
+ OCTEON_IRQ_MSI_BIT0));
+ }
+ }
+ }
+ return IRQ_NONE;
+}
+
+
+/**
+ * Initializes the MSI interrupt handling code
+ *
+ * @return
+ */
+int octeon_msi_initialize(void)
+{
+ int r;
+ if (octeon_has_feature(OCTEON_FEATURE_PCIE)) {
+ r = request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt,
+ IRQF_SHARED,
+ "MSI[0:63]", octeon_msi_interrupt);
+ } else if (octeon_is_pci_host()) {
+ r = request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt,
+ IRQF_SHARED,
+ "MSI[0:15]", octeon_msi_interrupt);
+ r += request_irq(OCTEON_IRQ_PCI_MSI1, octeon_msi_interrupt,
+ IRQF_SHARED,
+ "MSI[16:31]", octeon_msi_interrupt);
+ r += request_irq(OCTEON_IRQ_PCI_MSI2, octeon_msi_interrupt,
+ IRQF_SHARED,
+ "MSI[32:47]", octeon_msi_interrupt);
+ r += request_irq(OCTEON_IRQ_PCI_MSI3, octeon_msi_interrupt,
+ IRQF_SHARED,
+ "MSI[48:63]", octeon_msi_interrupt);
+ }
+ return 0;
+}
+
+subsys_initcall(octeon_msi_initialize);
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
index 1c19af8daa62..8dfa009e0070 100644
--- a/arch/mips/cavium-octeon/octeon-irq.c
+++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -10,6 +10,8 @@
#include <linux/hardirq.h>
#include <asm/octeon/octeon.h>
+#include <asm/octeon/cvmx-pexp-defs.h>
+#include <asm/octeon/cvmx-npi-defs.h>
DEFINE_RWLOCK(octeon_irq_ciu0_rwlock);
DEFINE_RWLOCK(octeon_irq_ciu1_rwlock);
@@ -177,7 +179,7 @@ static void octeon_irq_ciu0_disable(unsigned int irq)
}
#ifdef CONFIG_SMP
-static void octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask *dest)
+static int octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask *dest)
{
int cpu;
int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */
@@ -199,6 +201,8 @@ static void octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask
*/
cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2));
write_unlock(&octeon_irq_ciu0_rwlock);
+
+ return 0;
}
#endif
@@ -292,7 +296,7 @@ static void octeon_irq_ciu1_disable(unsigned int irq)
}
#ifdef CONFIG_SMP
-static void octeon_irq_ciu1_set_affinity(unsigned int irq, const struct cpumask *dest)
+static int octeon_irq_ciu1_set_affinity(unsigned int irq, const struct cpumask *dest)
{
int cpu;
int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */
@@ -315,6 +319,8 @@ static void octeon_irq_ciu1_set_affinity(unsigned int irq, const struct cpumask
*/
cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1));
write_unlock(&octeon_irq_ciu1_rwlock);
+
+ return 0;
}
#endif
diff --git a/arch/mips/cavium-octeon/pci-common.c b/arch/mips/cavium-octeon/pci-common.c
new file mode 100644
index 000000000000..cd029f88da7f
--- /dev/null
+++ b/arch/mips/cavium-octeon/pci-common.c
@@ -0,0 +1,137 @@
+/*
+ * 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-2007 Cavium Networks
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include "pci-common.h"
+
+typeof(pcibios_map_irq) *octeon_pcibios_map_irq;
+enum octeon_dma_bar_type octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_INVALID;
+
+/**
+ * Map a PCI device to the appropriate interrupt line
+ *
+ * @param dev The Linux PCI device structure for the device to map
+ * @param slot The slot number for this device on __BUS 0__. Linux
+ * enumerates through all the bridges and figures out the
+ * slot on Bus 0 where this device eventually hooks to.
+ * @param pin The PCI interrupt pin read from the device, then swizzled
+ * as it goes through each bridge.
+ * @return Interrupt number for the device
+ */
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+ if (octeon_pcibios_map_irq)
+ return octeon_pcibios_map_irq(dev, slot, pin);
+ else
+ panic("octeon_pcibios_map_irq doesn't point to a "
+ "pcibios_map_irq() function");
+}
+
+
+/**
+ * Called to perform platform specific PCI setup
+ *
+ * @param dev
+ * @return
+ */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ uint16_t config;
+ uint32_t dconfig;
+ int pos;
+ /*
+ * Force the Cache line setting to 64 bytes. The standard
+ * Linux bus scan doesn't seem to set it. Octeon really has
+ * 128 byte lines, but Intel bridges get really upset if you
+ * try and set values above 64 bytes. Value is specified in
+ * 32bit words.
+ */
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 64 / 4);
+ /* Set latency timers for all devices */
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 48);
+
+ /* Enable reporting System errors and parity errors on all devices */
+ /* Enable parity checking and error reporting */
+ pci_read_config_word(dev, PCI_COMMAND, &config);
+ config |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
+ pci_write_config_word(dev, PCI_COMMAND, config);
+
+ if (dev->subordinate) {
+ /* Set latency timers on sub bridges */
+ pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 48);
+ /* More bridge error detection */
+ pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &config);
+ config |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR;
+ pci_write_config_word(dev, PCI_BRIDGE_CONTROL, config);
+ }
+
+ /* Enable the PCIe normal error reporting */
+ pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+ if (pos) {
+ /* Update Device Control */
+ pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &config);
+ /* Correctable Error Reporting */
+ config |= PCI_EXP_DEVCTL_CERE;
+ /* Non-Fatal Error Reporting */
+ config |= PCI_EXP_DEVCTL_NFERE;
+ /* Fatal Error Reporting */
+ config |= PCI_EXP_DEVCTL_FERE;
+ /* Unsupported Request */
+ config |= PCI_EXP_DEVCTL_URRE;
+ pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, config);
+ }
+
+ /* Find the Advanced Error Reporting capability */
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+ if (pos) {
+ /* Clear Uncorrectable Error Status */
+ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS,
+ &dconfig);
+ pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS,
+ dconfig);
+ /* Enable reporting of all uncorrectable errors */
+ /* Uncorrectable Error Mask - turned on bits disable errors */
+ pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, 0);
+ /*
+ * Leave severity at HW default. This only controls if
+ * errors are reported as uncorrectable or
+ * correctable, not if the error is reported.
+ */
+ /* PCI_ERR_UNCOR_SEVER - Uncorrectable Error Severity */
+ /* Clear Correctable Error Status */
+ pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &dconfig);
+ pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, dconfig);
+ /* Enable reporting of all correctable errors */
+ /* Correctable Error Mask - turned on bits disable errors */
+ pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, 0);
+ /* Advanced Error Capabilities */
+ pci_read_config_dword(dev, pos + PCI_ERR_CAP, &dconfig);
+ /* ECRC Generation Enable */
+ if (config & PCI_ERR_CAP_ECRC_GENC)
+ config |= PCI_ERR_CAP_ECRC_GENE;
+ /* ECRC Check Enable */
+ if (config & PCI_ERR_CAP_ECRC_CHKC)
+ config |= PCI_ERR_CAP_ECRC_CHKE;
+ pci_write_config_dword(dev, pos + PCI_ERR_CAP, dconfig);
+ /* PCI_ERR_HEADER_LOG - Header Log Register (16 bytes) */
+ /* Report all errors to the root complex */
+ pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND,
+ PCI_ERR_ROOT_CMD_COR_EN |
+ PCI_ERR_ROOT_CMD_NONFATAL_EN |
+ PCI_ERR_ROOT_CMD_FATAL_EN);
+ /* Clear the Root status register */
+ pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &dconfig);
+ pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, dconfig);
+ }
+
+ return 0;
+}
diff --git a/arch/mips/cavium-octeon/pci-common.h b/arch/mips/cavium-octeon/pci-common.h
new file mode 100644
index 000000000000..74ae79991e45
--- /dev/null
+++ b/arch/mips/cavium-octeon/pci-common.h
@@ -0,0 +1,39 @@
+/*
+ * 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-2007 Cavium Networks
+ */
+#ifndef __OCTEON_PCI_COMMON_H__
+#define __OCTEON_PCI_COMMON_H__
+
+#include <linux/pci.h>
+
+/* Some PCI cards require delays when accessing config space. */
+#define PCI_CONFIG_SPACE_DELAY 10000
+
+/* pcibios_map_irq() is defined inside pci-common.c. All it does is call the
+ Octeon specific version pointed to by this variable. This function needs to
+ change for PCI or PCIe based hosts */
+extern typeof(pcibios_map_irq) *octeon_pcibios_map_irq;
+
+/* The following defines are only used when octeon_dma_bar_type =
+ OCTEON_DMA_BAR_TYPE_BIG */
+#define OCTEON_PCI_BAR1_HOLE_BITS 5
+#define OCTEON_PCI_BAR1_HOLE_SIZE (1ul<<(OCTEON_PCI_BAR1_HOLE_BITS+3))
+
+enum octeon_dma_bar_type {
+ OCTEON_DMA_BAR_TYPE_INVALID,
+ OCTEON_DMA_BAR_TYPE_SMALL,
+ OCTEON_DMA_BAR_TYPE_BIG,
+ OCTEON_DMA_BAR_TYPE_PCIE
+};
+
+/**
+ * This is a variable to tell the DMA mapping system in dma-octeon.c
+ * how to map PCI DMA addresses.
+ */
+extern enum octeon_dma_bar_type octeon_dma_bar_type;
+
+#endif
diff --git a/arch/mips/cavium-octeon/pci.c b/arch/mips/cavium-octeon/pci.c
new file mode 100644
index 000000000000..67c0ff5e92f1
--- /dev/null
+++ b/arch/mips/cavium-octeon/pci.c
@@ -0,0 +1,568 @@
+/*
+ * 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-2007 Cavium Networks
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+
+#include <asm/time.h>
+
+#include <asm/octeon/octeon.h>
+#include <asm/octeon/cvmx-npi-defs.h>
+#include <asm/octeon/cvmx-pci-defs.h>
+
+#include "pci-common.h"
+
+#define USE_OCTEON_INTERNAL_ARBITER
+
+/*
+ * Octeon's PCI controller uses did=3, subdid=2 for PCI IO
+ * addresses. Use PCI endian swapping 1 so no address swapping is
+ * necessary. The Linux io routines will endian swap the data.
+ */
+#define OCTEON_PCI_IOSPACE_BASE 0x80011a0400000000ull
+#define OCTEON_PCI_IOSPACE_SIZE (1ull<<32)
+
+/* Octeon't PCI controller uses did=3, subdid=3 for PCI memory. */
+#define OCTEON_PCI_MEMSPACE_OFFSET (0x00011b0000000000ull)
+
+/**
+ * This is the bit decoding used for the Octeon PCI controller addresses
+ */
+union octeon_pci_address {
+ uint64_t u64;
+ struct {
+ uint64_t upper:2;
+ uint64_t reserved:13;
+ uint64_t io:1;
+ uint64_t did:5;
+ uint64_t subdid:3;
+ uint64_t reserved2:4;
+ uint64_t endian_swap:2;
+ uint64_t reserved3:10;
+ uint64_t bus:8;
+ uint64_t dev:5;
+ uint64_t func:3;
+ uint64_t reg:8;
+ } s;
+};
+
+/**
+ * Return the mapping of PCI device number to IRQ line. Each
+ * character in the return string represents the interrupt
+ * line for the device at that position. Device 1 maps to the
+ * first character, etc. The characters A-D are used for PCI
+ * interrupts.
+ *
+ * Returns PCI interrupt mapping
+ */
+const char *octeon_get_pci_interrupts(void)
+{
+ /*
+ * Returning an empty string causes the interrupts to be
+ * routed based on the PCI specification. From the PCI spec:
+ *
+ * INTA# of Device Number 0 is connected to IRQW on the system
+ * board. (Device Number has no significance regarding being
+ * located on the system board or in a connector.) INTA# of
+ * Device Number 1 is connected to IRQX on the system
+ * board. INTA# of Device Number 2 is connected to IRQY on the
+ * system board. INTA# of Device Number 3 is connected to IRQZ
+ * on the system board. The table below describes how each
+ * agent's INTx# lines are connected to the system board
+ * interrupt lines. The following equation can be used to
+ * determine to which INTx# signal on the system board a given
+ * device's INTx# line(s) is connected.
+ *
+ * MB = (D + I) MOD 4 MB = System board Interrupt (IRQW = 0,
+ * IRQX = 1, IRQY = 2, and IRQZ = 3) D = Device Number I =
+ * Interrupt Number (INTA# = 0, INTB# = 1, INTC# = 2, and
+ * INTD# = 3)
+ */
+ switch (octeon_bootinfo->board_type) {
+ case CVMX_BOARD_TYPE_NAO38:
+ /* This is really the NAC38 */
+ return "AAAAADABAAAAAAAAAAAAAAAAAAAAAAAA";
+ case CVMX_BOARD_TYPE_THUNDER:
+ return "";
+ case CVMX_BOARD_TYPE_EBH3000:
+ return "";
+ case CVMX_BOARD_TYPE_EBH3100:
+ case CVMX_BOARD_TYPE_CN3010_EVB_HS5:
+ case CVMX_BOARD_TYPE_CN3005_EVB_HS5:
+ return "AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
+ case CVMX_BOARD_TYPE_BBGW_REF:
+ return "AABCD";
+ default:
+ return "";
+ }
+}
+
+/**
+ * Map a PCI device to the appropriate interrupt line
+ *
+ * @dev: The Linux PCI device structure for the device to map
+ * @slot: The slot number for this device on __BUS 0__. Linux
+ * enumerates through all the bridges and figures out the
+ * slot on Bus 0 where this device eventually hooks to.
+ * @pin: The PCI interrupt pin read from the device, then swizzled
+ * as it goes through each bridge.
+ * Returns Interrupt number for the device
+ */
+int __init octeon_pci_pcibios_map_irq(const struct pci_dev *dev,
+ u8 slot, u8 pin)
+{
+ int irq_num;
+ const char *interrupts;
+ int dev_num;
+
+ /* Get the board specific interrupt mapping */
+ interrupts = octeon_get_pci_interrupts();
+
+ dev_num = dev->devfn >> 3;
+ if (dev_num < strlen(interrupts))
+ irq_num = ((interrupts[dev_num] - 'A' + pin - 1) & 3) +
+ OCTEON_IRQ_PCI_INT0;
+ else
+ irq_num = ((slot + pin - 3) & 3) + OCTEON_IRQ_PCI_INT0;
+ return irq_num;
+}
+
+
+/**
+ * Read a value from configuration space
+ *
+ */
+static int octeon_read_config(struct pci_bus *bus, unsigned int devfn,
+ int reg, int size, u32 *val)
+{
+ union octeon_pci_address pci_addr;
+
+ pci_addr.u64 = 0;
+ pci_addr.s.upper = 2;
+ pci_addr.s.io = 1;
+ pci_addr.s.did = 3;
+ pci_addr.s.subdid = 1;
+ pci_addr.s.endian_swap = 1;
+ pci_addr.s.bus = bus->number;
+ pci_addr.s.dev = devfn >> 3;
+ pci_addr.s.func = devfn & 0x7;
+ pci_addr.s.reg = reg;
+
+#if PCI_CONFIG_SPACE_DELAY
+ udelay(PCI_CONFIG_SPACE_DELAY);
+#endif
+ switch (size) {
+ case 4:
+ *val = le32_to_cpu(cvmx_read64_uint32(pci_addr.u64));
+ return PCIBIOS_SUCCESSFUL;
+ case 2:
+ *val = le16_to_cpu(cvmx_read64_uint16(pci_addr.u64));
+ return PCIBIOS_SUCCESSFUL;
+ case 1:
+ *val = cvmx_read64_uint8(pci_addr.u64);
+ return PCIBIOS_SUCCESSFUL;
+ }
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+}
+
+
+/**
+ * Write a value to PCI configuration space
+ *
+ * @bus:
+ * @devfn:
+ * @reg:
+ * @size:
+ * @val:
+ * Returns
+ */
+static int octeon_write_config(struct pci_bus *bus, unsigned int devfn,
+ int reg, int size, u32 val)
+{
+ union octeon_pci_address pci_addr;
+
+ pci_addr.u64 = 0;
+ pci_addr.s.upper = 2;
+ pci_addr.s.io = 1;
+ pci_addr.s.did = 3;
+ pci_addr.s.subdid = 1;
+ pci_addr.s.endian_swap = 1;
+ pci_addr.s.bus = bus->number;
+ pci_addr.s.dev = devfn >> 3;
+ pci_addr.s.func = devfn & 0x7;
+ pci_addr.s.reg = reg;
+
+#if PCI_CONFIG_SPACE_DELAY
+ udelay(PCI_CONFIG_SPACE_DELAY);
+#endif
+ switch (size) {
+ case 4:
+ cvmx_write64_uint32(pci_addr.u64, cpu_to_le32(val));
+ return PCIBIOS_SUCCESSFUL;
+ case 2:
+ cvmx_write64_uint16(pci_addr.u64, cpu_to_le16(val));
+ return PCIBIOS_SUCCESSFUL;
+ case 1:
+ cvmx_write64_uint8(pci_addr.u64, val);
+ return PCIBIOS_SUCCESSFUL;
+ }
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+}
+
+
+static struct pci_ops octeon_pci_ops = {
+ octeon_read_config,
+ octeon_write_config,
+};
+
+static struct resource octeon_pci_mem_resource = {
+ .start = 0,
+ .end = 0,
+ .name = "Octeon PCI MEM",
+ .flags = IORESOURCE_MEM,
+};
+
+/*
+ * PCI ports must be above 16KB so the ISA bus filtering in the PCI-X to PCI
+ * bridge
+ */
+static struct resource octeon_pci_io_resource = {
+ .start = 0x4000,
+ .end = OCTEON_PCI_IOSPACE_SIZE - 1,
+ .name = "Octeon PCI IO",
+ .flags = IORESOURCE_IO,
+};
+
+static struct pci_controller octeon_pci_controller = {
+ .pci_ops = &octeon_pci_ops,
+ .mem_resource = &octeon_pci_mem_resource,
+ .mem_offset = OCTEON_PCI_MEMSPACE_OFFSET,
+ .io_resource = &octeon_pci_io_resource,
+ .io_offset = 0,
+ .io_map_base = OCTEON_PCI_IOSPACE_BASE,
+};
+
+
+/**
+ * Low level initialize the Octeon PCI controller
+ *
+ * Returns
+ */
+static void octeon_pci_initialize(void)
+{
+ union cvmx_pci_cfg01 cfg01;
+ union cvmx_npi_ctl_status ctl_status;
+ union cvmx_pci_ctl_status_2 ctl_status_2;
+ union cvmx_pci_cfg19 cfg19;
+ union cvmx_pci_cfg16 cfg16;
+ union cvmx_pci_cfg22 cfg22;
+ union cvmx_pci_cfg56 cfg56;
+
+ /* Reset the PCI Bus */
+ cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x1);
+ cvmx_read_csr(CVMX_CIU_SOFT_PRST);
+
+ udelay(2000); /* Hold PCI reset for 2 ms */
+
+ ctl_status.u64 = 0; /* cvmx_read_csr(CVMX_NPI_CTL_STATUS); */
+ ctl_status.s.max_word = 1;
+ ctl_status.s.timer = 1;
+ cvmx_write_csr(CVMX_NPI_CTL_STATUS, ctl_status.u64);
+
+ /* Deassert PCI reset and advertize PCX Host Mode Device Capability
+ (64b) */
+ cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x4);
+ cvmx_read_csr(CVMX_CIU_SOFT_PRST);
+
+ udelay(2000); /* Wait 2 ms after deasserting PCI reset */
+
+ ctl_status_2.u32 = 0;
+ ctl_status_2.s.tsr_hwm = 1; /* Initializes to 0. Must be set
+ before any PCI reads. */
+ ctl_status_2.s.bar2pres = 1; /* Enable BAR2 */
+ ctl_status_2.s.bar2_enb = 1;
+ ctl_status_2.s.bar2_cax = 1; /* Don't use L2 */
+ ctl_status_2.s.bar2_esx = 1;
+ ctl_status_2.s.pmo_amod = 1; /* Round robin priority */
+ if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG) {
+ /* BAR1 hole */
+ ctl_status_2.s.bb1_hole = OCTEON_PCI_BAR1_HOLE_BITS;
+ ctl_status_2.s.bb1_siz = 1; /* BAR1 is 2GB */
+ ctl_status_2.s.bb_ca = 1; /* Don't use L2 with big bars */
+ ctl_status_2.s.bb_es = 1; /* Big bar in byte swap mode */
+ ctl_status_2.s.bb1 = 1; /* BAR1 is big */
+ ctl_status_2.s.bb0 = 1; /* BAR0 is big */
+ }
+
+ octeon_npi_write32(CVMX_NPI_PCI_CTL_STATUS_2, ctl_status_2.u32);
+ udelay(2000); /* Wait 2 ms before doing PCI reads */
+
+ ctl_status_2.u32 = octeon_npi_read32(CVMX_NPI_PCI_CTL_STATUS_2);
+ pr_notice("PCI Status: %s %s-bit\n",
+ ctl_status_2.s.ap_pcix ? "PCI-X" : "PCI",
+ ctl_status_2.s.ap_64ad ? "64" : "32");
+
+ if (OCTEON_IS_MODEL(OCTEON_CN58XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) {
+ union cvmx_pci_cnt_reg cnt_reg_start;
+ union cvmx_pci_cnt_reg cnt_reg_end;
+ unsigned long cycles, pci_clock;
+
+ cnt_reg_start.u64 = cvmx_read_csr(CVMX_NPI_PCI_CNT_REG);
+ cycles = read_c0_cvmcount();
+ udelay(1000);
+ cnt_reg_end.u64 = cvmx_read_csr(CVMX_NPI_PCI_CNT_REG);
+ cycles = read_c0_cvmcount() - cycles;
+ pci_clock = (cnt_reg_end.s.pcicnt - cnt_reg_start.s.pcicnt) /
+ (cycles / (mips_hpt_frequency / 1000000));
+ pr_notice("PCI Clock: %lu MHz\n", pci_clock);
+ }
+
+ /*
+ * TDOMC must be set to one in PCI mode. TDOMC should be set to 4
+ * in PCI-X mode to allow four oustanding splits. Otherwise,
+ * should not change from its reset value. Don't write PCI_CFG19
+ * in PCI mode (0x82000001 reset value), write it to 0x82000004
+ * after PCI-X mode is known. MRBCI,MDWE,MDRE -> must be zero.
+ * MRBCM -> must be one.
+ */
+ if (ctl_status_2.s.ap_pcix) {
+ cfg19.u32 = 0;
+ /*
+ * Target Delayed/Split request outstanding maximum
+ * count. [1..31] and 0=32. NOTE: If the user
+ * programs these bits beyond the Designed Maximum
+ * outstanding count, then the designed maximum table
+ * depth will be used instead. No additional
+ * Deferred/Split transactions will be accepted if
+ * this outstanding maximum count is
+ * reached. Furthermore, no additional deferred/split
+ * transactions will be accepted if the I/O delay/ I/O
+ * Split Request outstanding maximum is reached.
+ */
+ cfg19.s.tdomc = 4;
+ /*
+ * Master Deferred Read Request Outstanding Max Count
+ * (PCI only). CR4C[26:24] Max SAC cycles MAX DAC
+ * cycles 000 8 4 001 1 0 010 2 1 011 3 1 100 4 2 101
+ * 5 2 110 6 3 111 7 3 For example, if these bits are
+ * programmed to 100, the core can support 2 DAC
+ * cycles, 4 SAC cycles or a combination of 1 DAC and
+ * 2 SAC cycles. NOTE: For the PCI-X maximum
+ * outstanding split transactions, refer to
+ * CRE0[22:20].
+ */
+ cfg19.s.mdrrmc = 2;
+ /*
+ * Master Request (Memory Read) Byte Count/Byte Enable
+ * select. 0 = Byte Enables valid. In PCI mode, a
+ * burst transaction cannot be performed using Memory
+ * Read command=4?h6. 1 = DWORD Byte Count valid
+ * (default). In PCI Mode, the memory read byte
+ * enables are automatically generated by the
+ * core. Note: N3 Master Request transaction sizes are
+ * always determined through the
+ * am_attr[<35:32>|<7:0>] field.
+ */
+ cfg19.s.mrbcm = 1;
+ octeon_npi_write32(CVMX_NPI_PCI_CFG19, cfg19.u32);
+ }
+
+
+ cfg01.u32 = 0;
+ cfg01.s.msae = 1; /* Memory Space Access Enable */
+ cfg01.s.me = 1; /* Master Enable */
+ cfg01.s.pee = 1; /* PERR# Enable */
+ cfg01.s.see = 1; /* System Error Enable */
+ cfg01.s.fbbe = 1; /* Fast Back to Back Transaction Enable */
+
+ octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+
+#ifdef USE_OCTEON_INTERNAL_ARBITER
+ /*
+ * When OCTEON is a PCI host, most systems will use OCTEON's
+ * internal arbiter, so must enable it before any PCI/PCI-X
+ * traffic can occur.
+ */
+ {
+ union cvmx_npi_pci_int_arb_cfg pci_int_arb_cfg;
+
+ pci_int_arb_cfg.u64 = 0;
+ pci_int_arb_cfg.s.en = 1; /* Internal arbiter enable */
+ cvmx_write_csr(CVMX_NPI_PCI_INT_ARB_CFG, pci_int_arb_cfg.u64);
+ }
+#endif /* USE_OCTEON_INTERNAL_ARBITER */
+
+ /*
+ * Preferrably written to 1 to set MLTD. [RDSATI,TRTAE,
+ * TWTAE,TMAE,DPPMR -> must be zero. TILT -> must not be set to
+ * 1..7.
+ */
+ cfg16.u32 = 0;
+ cfg16.s.mltd = 1; /* Master Latency Timer Disable */
+ octeon_npi_write32(CVMX_NPI_PCI_CFG16, cfg16.u32);
+
+ /*
+ * Should be written to 0x4ff00. MTTV -> must be zero.
+ * FLUSH -> must be 1. MRV -> should be 0xFF.
+ */
+ cfg22.u32 = 0;
+ /* Master Retry Value [1..255] and 0=infinite */
+ cfg22.s.mrv = 0xff;
+ /*
+ * AM_DO_FLUSH_I control NOTE: This bit MUST BE ONE for proper
+ * N3K operation.
+ */
+ cfg22.s.flush = 1;
+ octeon_npi_write32(CVMX_NPI_PCI_CFG22, cfg22.u32);
+
+ /*
+ * MOST Indicates the maximum number of outstanding splits (in -1
+ * notation) when OCTEON is in PCI-X mode. PCI-X performance is
+ * affected by the MOST selection. Should generally be written
+ * with one of 0x3be807, 0x2be807, 0x1be807, or 0x0be807,
+ * depending on the desired MOST of 3, 2, 1, or 0, respectively.
+ */
+ cfg56.u32 = 0;
+ cfg56.s.pxcid = 7; /* RO - PCI-X Capability ID */
+ cfg56.s.ncp = 0xe8; /* RO - Next Capability Pointer */
+ cfg56.s.dpere = 1; /* Data Parity Error Recovery Enable */
+ cfg56.s.roe = 1; /* Relaxed Ordering Enable */
+ cfg56.s.mmbc = 1; /* Maximum Memory Byte Count
+ [0=512B,1=1024B,2=2048B,3=4096B] */
+ cfg56.s.most = 3; /* Maximum outstanding Split transactions [0=1
+ .. 7=32] */
+
+ octeon_npi_write32(CVMX_NPI_PCI_CFG56, cfg56.u32);
+
+ /*
+ * Affects PCI performance when OCTEON services reads to its
+ * BAR1/BAR2. Refer to Section 10.6.1. The recommended values are
+ * 0x22, 0x33, and 0x33 for PCI_READ_CMD_6, PCI_READ_CMD_C, and
+ * PCI_READ_CMD_E, respectively. Unfortunately due to errata DDR-700,
+ * these values need to be changed so they won't possibly prefetch off
+ * of the end of memory if PCI is DMAing a buffer at the end of
+ * memory. Note that these values differ from their reset values.
+ */
+ octeon_npi_write32(CVMX_NPI_PCI_READ_CMD_6, 0x21);
+ octeon_npi_write32(CVMX_NPI_PCI_READ_CMD_C, 0x31);
+ octeon_npi_write32(CVMX_NPI_PCI_READ_CMD_E, 0x31);
+}
+
+
+/**
+ * Initialize the Octeon PCI controller
+ *
+ * Returns
+ */
+static int __init octeon_pci_setup(void)
+{
+ union cvmx_npi_mem_access_subidx mem_access;
+ int index;
+
+ /* Only these chips have PCI */
+ if (octeon_has_feature(OCTEON_FEATURE_PCIE))
+ return 0;
+
+ /* Point pcibios_map_irq() to the PCI version of it */
+ octeon_pcibios_map_irq = octeon_pci_pcibios_map_irq;
+
+ /* Only use the big bars on chips that support it */
+ if (OCTEON_IS_MODEL(OCTEON_CN31XX) ||
+ OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2) ||
+ OCTEON_IS_MODEL(OCTEON_CN38XX_PASS1))
+ octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_SMALL;
+ else
+ octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_BIG;
+
+ /* PCI I/O and PCI MEM values */
+ set_io_port_base(OCTEON_PCI_IOSPACE_BASE);
+ ioport_resource.start = 0;
+ ioport_resource.end = OCTEON_PCI_IOSPACE_SIZE - 1;
+ if (!octeon_is_pci_host()) {
+ pr_notice("Not in host mode, PCI Controller not initialized\n");
+ return 0;
+ }
+
+ pr_notice("%s Octeon big bar support\n",
+ (octeon_dma_bar_type ==
+ OCTEON_DMA_BAR_TYPE_BIG) ? "Enabling" : "Disabling");
+
+ octeon_pci_initialize();
+
+ mem_access.u64 = 0;
+ mem_access.s.esr = 1; /* Endian-Swap on read. */
+ mem_access.s.esw = 1; /* Endian-Swap on write. */
+ mem_access.s.nsr = 0; /* No-Snoop on read. */
+ mem_access.s.nsw = 0; /* No-Snoop on write. */
+ mem_access.s.ror = 0; /* Relax Read on read. */
+ mem_access.s.row = 0; /* Relax Order on write. */
+ mem_access.s.ba = 0; /* PCI Address bits [63:36]. */
+ cvmx_write_csr(CVMX_NPI_MEM_ACCESS_SUBID3, mem_access.u64);
+
+ /*
+ * Remap the Octeon BAR 2 above all 32 bit devices
+ * (0x8000000000ul). This is done here so it is remapped
+ * before the readl()'s below. We don't want BAR2 overlapping
+ * with BAR0/BAR1 during these reads.
+ */
+ octeon_npi_write32(CVMX_NPI_PCI_CFG08, 0);
+ octeon_npi_write32(CVMX_NPI_PCI_CFG09, 0x80);
+
+ /* Disable the BAR1 movable mappings */
+ for (index = 0; index < 32; index++)
+ octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index), 0);
+
+ if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG) {
+ /* Remap the Octeon BAR 0 to 0-2GB */
+ octeon_npi_write32(CVMX_NPI_PCI_CFG04, 0);
+ octeon_npi_write32(CVMX_NPI_PCI_CFG05, 0);
+
+ /*
+ * Remap the Octeon BAR 1 to map 2GB-4GB (minus the
+ * BAR 1 hole).
+ */
+ octeon_npi_write32(CVMX_NPI_PCI_CFG06, 2ul << 30);
+ octeon_npi_write32(CVMX_NPI_PCI_CFG07, 0);
+
+ /* Devices go after BAR1 */
+ octeon_pci_mem_resource.start =
+ OCTEON_PCI_MEMSPACE_OFFSET + (4ul << 30) -
+ (OCTEON_PCI_BAR1_HOLE_SIZE << 20);
+ octeon_pci_mem_resource.end =
+ octeon_pci_mem_resource.start + (1ul << 30);
+ } else {
+ /* Remap the Octeon BAR 0 to map 128MB-(128MB+4KB) */
+ octeon_npi_write32(CVMX_NPI_PCI_CFG04, 128ul << 20);
+ octeon_npi_write32(CVMX_NPI_PCI_CFG05, 0);
+
+ /* Remap the Octeon BAR 1 to map 0-128MB */
+ octeon_npi_write32(CVMX_NPI_PCI_CFG06, 0);
+ octeon_npi_write32(CVMX_NPI_PCI_CFG07, 0);
+
+ /* Devices go after BAR0 */
+ octeon_pci_mem_resource.start =
+ OCTEON_PCI_MEMSPACE_OFFSET + (128ul << 20) +
+ (4ul << 10);
+ octeon_pci_mem_resource.end =
+ octeon_pci_mem_resource.start + (1ul << 30);
+ }
+
+ register_pci_controller(&octeon_pci_controller);
+
+ /*
+ * Clear any errors that might be pending from before the bus
+ * was setup properly.
+ */
+ cvmx_write_csr(CVMX_NPI_PCI_INT_SUM2, -1);
+ return 0;
+}
+
+arch_initcall(octeon_pci_setup);
diff --git a/arch/mips/cavium-octeon/pcie.c b/arch/mips/cavium-octeon/pcie.c
new file mode 100644
index 000000000000..49d14081b3b5
--- /dev/null
+++ b/arch/mips/cavium-octeon/pcie.c
@@ -0,0 +1,1370 @@
+/*
+ * 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, 2008 Cavium Networks
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+
+#include <asm/octeon/octeon.h>
+#include <asm/octeon/cvmx-npei-defs.h>
+#include <asm/octeon/cvmx-pciercx-defs.h>
+#include <asm/octeon/cvmx-pescx-defs.h>
+#include <asm/octeon/cvmx-pexp-defs.h>
+#include <asm/octeon/cvmx-helper-errata.h>
+
+#include "pci-common.h"
+
+union cvmx_pcie_address {
+ uint64_t u64;
+ struct {
+ uint64_t upper:2; /* Normally 2 for XKPHYS */
+ uint64_t reserved_49_61:13; /* Must be zero */
+ uint64_t io:1; /* 1 for IO space access */
+ uint64_t did:5; /* PCIe DID = 3 */
+ uint64_t subdid:3; /* PCIe SubDID = 1 */
+ uint64_t reserved_36_39:4; /* Must be zero */
+ uint64_t es:2; /* Endian swap = 1 */
+ uint64_t port:2; /* PCIe port 0,1 */
+ uint64_t reserved_29_31:3; /* Must be zero */
+ /*
+ * Selects the type of the configuration request (0 = type 0,
+ * 1 = type 1).
+ */
+ uint64_t ty:1;
+ /* Target bus number sent in the ID in the request. */
+ uint64_t bus:8;
+ /*
+ * Target device number sent in the ID in the
+ * request. Note that Dev must be zero for type 0
+ * configuration requests.
+ */
+ uint64_t dev:5;
+ /* Target function number sent in the ID in the request. */
+ uint64_t func:3;
+ /*
+ * Selects a register in the configuration space of
+ * the target.
+ */
+ uint64_t reg:12;
+ } config;
+ struct {
+ uint64_t upper:2; /* Normally 2 for XKPHYS */
+ uint64_t reserved_49_61:13; /* Must be zero */
+ uint64_t io:1; /* 1 for IO space access */
+ uint64_t did:5; /* PCIe DID = 3 */
+ uint64_t subdid:3; /* PCIe SubDID = 2 */
+ uint64_t reserved_36_39:4; /* Must be zero */
+ uint64_t es:2; /* Endian swap = 1 */
+ uint64_t port:2; /* PCIe port 0,1 */
+ uint64_t address:32; /* PCIe IO address */
+ } io;
+ struct {
+ uint64_t upper:2; /* Normally 2 for XKPHYS */
+ uint64_t reserved_49_61:13; /* Must be zero */
+ uint64_t io:1; /* 1 for IO space access */
+ uint64_t did:5; /* PCIe DID = 3 */
+ uint64_t subdid:3; /* PCIe SubDID = 3-6 */
+ uint64_t reserved_36_39:4; /* Must be zero */
+ uint64_t address:36; /* PCIe Mem address */
+ } mem;
+};
+
+/**
+ * Return the Core virtual base address for PCIe IO access. IOs are
+ * read/written as an offset from this address.
+ *
+ * @pcie_port: PCIe port the IO is for
+ *
+ * Returns 64bit Octeon IO base address for read/write
+ */
+static inline uint64_t cvmx_pcie_get_io_base_address(int pcie_port)
+{
+ union cvmx_pcie_address pcie_addr;
+ pcie_addr.u64 = 0;
+ pcie_addr.io.upper = 0;
+ pcie_addr.io.io = 1;
+ pcie_addr.io.did = 3;
+ pcie_addr.io.subdid = 2;
+ pcie_addr.io.es = 1;
+ pcie_addr.io.port = pcie_port;
+ return pcie_addr.u64;
+}
+
+/**
+ * Size of the IO address region returned at address
+ * cvmx_pcie_get_io_base_address()
+ *
+ * @pcie_port: PCIe port the IO is for
+ *
+ * Returns Size of the IO window
+ */
+static inline uint64_t cvmx_pcie_get_io_size(int pcie_port)
+{
+ return 1ull << 32;
+}
+
+/**
+ * Return the Core virtual base address for PCIe MEM access. Memory is
+ * read/written as an offset from this address.
+ *
+ * @pcie_port: PCIe port the IO is for
+ *
+ * Returns 64bit Octeon IO base address for read/write
+ */
+static inline uint64_t cvmx_pcie_get_mem_base_address(int pcie_port)
+{
+ union cvmx_pcie_address pcie_addr;
+ pcie_addr.u64 = 0;
+ pcie_addr.mem.upper = 0;
+ pcie_addr.mem.io = 1;
+ pcie_addr.mem.did = 3;
+ pcie_addr.mem.subdid = 3 + pcie_port;
+ return pcie_addr.u64;
+}
+
+/**
+ * Size of the Mem address region returned at address
+ * cvmx_pcie_get_mem_base_address()
+ *
+ * @pcie_port: PCIe port the IO is for
+ *
+ * Returns Size of the Mem window
+ */
+static inline uint64_t cvmx_pcie_get_mem_size(int pcie_port)
+{
+ return 1ull << 36;
+}
+
+/**
+ * Read a PCIe config space register indirectly. This is used for
+ * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???.
+ *
+ * @pcie_port: PCIe port to read from
+ * @cfg_offset: Address to read
+ *
+ * Returns Value read
+ */
+static uint32_t cvmx_pcie_cfgx_read(int pcie_port, uint32_t cfg_offset)
+{
+ union cvmx_pescx_cfg_rd pescx_cfg_rd;
+ pescx_cfg_rd.u64 = 0;
+ pescx_cfg_rd.s.addr = cfg_offset;
+ cvmx_write_csr(CVMX_PESCX_CFG_RD(pcie_port), pescx_cfg_rd.u64);
+ pescx_cfg_rd.u64 = cvmx_read_csr(CVMX_PESCX_CFG_RD(pcie_port));
+ return pescx_cfg_rd.s.data;
+}
+
+/**
+ * Write a PCIe config space register indirectly. This is used for
+ * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???.
+ *
+ * @pcie_port: PCIe port to write to
+ * @cfg_offset: Address to write
+ * @val: Value to write
+ */
+static void cvmx_pcie_cfgx_write(int pcie_port, uint32_t cfg_offset,
+ uint32_t val)
+{
+ union cvmx_pescx_cfg_wr pescx_cfg_wr;
+ pescx_cfg_wr.u64 = 0;
+ pescx_cfg_wr.s.addr = cfg_offset;
+ pescx_cfg_wr.s.data = val;
+ cvmx_write_csr(CVMX_PESCX_CFG_WR(pcie_port), pescx_cfg_wr.u64);
+}
+
+/**
+ * Build a PCIe config space request address for a device
+ *
+ * @pcie_port: PCIe port to access
+ * @bus: Sub bus
+ * @dev: Device ID
+ * @fn: Device sub function
+ * @reg: Register to access
+ *
+ * Returns 64bit Octeon IO address
+ */
+static inline uint64_t __cvmx_pcie_build_config_addr(int pcie_port, int bus,
+ int dev, int fn, int reg)
+{
+ union cvmx_pcie_address pcie_addr;
+ union cvmx_pciercx_cfg006 pciercx_cfg006;
+
+ pciercx_cfg006.u32 =
+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG006(pcie_port));
+ if ((bus <= pciercx_cfg006.s.pbnum) && (dev != 0))
+ return 0;
+
+ pcie_addr.u64 = 0;
+ pcie_addr.config.upper = 2;
+ pcie_addr.config.io = 1;
+ pcie_addr.config.did = 3;
+ pcie_addr.config.subdid = 1;
+ pcie_addr.config.es = 1;
+ pcie_addr.config.port = pcie_port;
+ pcie_addr.config.ty = (bus > pciercx_cfg006.s.pbnum);
+ pcie_addr.config.bus = bus;
+ pcie_addr.config.dev = dev;
+ pcie_addr.config.func = fn;
+ pcie_addr.config.reg = reg;
+ return pcie_addr.u64;
+}
+
+/**
+ * Read 8bits from a Device's config space
+ *
+ * @pcie_port: PCIe port the device is on
+ * @bus: Sub bus
+ * @dev: Device ID
+ * @fn: Device sub function
+ * @reg: Register to access
+ *
+ * Returns Result of the read
+ */
+static uint8_t cvmx_pcie_config_read8(int pcie_port, int bus, int dev,
+ int fn, int reg)
+{
+ uint64_t address =
+ __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg);
+ if (address)
+ return cvmx_read64_uint8(address);
+ else
+ return 0xff;
+}
+
+/**
+ * Read 16bits from a Device's config space
+ *
+ * @pcie_port: PCIe port the device is on
+ * @bus: Sub bus
+ * @dev: Device ID
+ * @fn: Device sub function
+ * @reg: Register to access
+ *
+ * Returns Result of the read
+ */
+static uint16_t cvmx_pcie_config_read16(int pcie_port, int bus, int dev,
+ int fn, int reg)
+{
+ uint64_t address =
+ __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg);
+ if (address)
+ return le16_to_cpu(cvmx_read64_uint16(address));
+ else
+ return 0xffff;
+}
+
+/**
+ * Read 32bits from a Device's config space
+ *
+ * @pcie_port: PCIe port the device is on
+ * @bus: Sub bus
+ * @dev: Device ID
+ * @fn: Device sub function
+ * @reg: Register to access
+ *
+ * Returns Result of the read
+ */
+static uint32_t cvmx_pcie_config_read32(int pcie_port, int bus, int dev,
+ int fn, int reg)
+{
+ uint64_t address =
+ __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg);
+ if (address)
+ return le32_to_cpu(cvmx_read64_uint32(address));
+ else
+ return 0xffffffff;
+}
+
+/**
+ * Write 8bits to a Device's config space
+ *
+ * @pcie_port: PCIe port the device is on
+ * @bus: Sub bus
+ * @dev: Device ID
+ * @fn: Device sub function
+ * @reg: Register to access
+ * @val: Value to write
+ */
+static void cvmx_pcie_config_write8(int pcie_port, int bus, int dev, int fn,
+ int reg, uint8_t val)
+{
+ uint64_t address =
+ __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg);
+ if (address)
+ cvmx_write64_uint8(address, val);
+}
+
+/**
+ * Write 16bits to a Device's config space
+ *
+ * @pcie_port: PCIe port the device is on
+ * @bus: Sub bus
+ * @dev: Device ID
+ * @fn: Device sub function
+ * @reg: Register to access
+ * @val: Value to write
+ */
+static void cvmx_pcie_config_write16(int pcie_port, int bus, int dev, int fn,
+ int reg, uint16_t val)
+{
+ uint64_t address =
+ __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg);
+ if (address)
+ cvmx_write64_uint16(address, cpu_to_le16(val));
+}
+
+/**
+ * Write 32bits to a Device's config space
+ *
+ * @pcie_port: PCIe port the device is on
+ * @bus: Sub bus
+ * @dev: Device ID
+ * @fn: Device sub function
+ * @reg: Register to access
+ * @val: Value to write
+ */
+static void cvmx_pcie_config_write32(int pcie_port, int bus, int dev, int fn,
+ int reg, uint32_t val)
+{
+ uint64_t address =
+ __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg);
+ if (address)
+ cvmx_write64_uint32(address, cpu_to_le32(val));
+}
+
+/**
+ * Initialize the RC config space CSRs
+ *
+ * @pcie_port: PCIe port to initialize
+ */
+static void __cvmx_pcie_rc_initialize_config_space(int pcie_port)
+{
+ union cvmx_pciercx_cfg030 pciercx_cfg030;
+ union cvmx_npei_ctl_status2 npei_ctl_status2;
+ union cvmx_pciercx_cfg070 pciercx_cfg070;
+ union cvmx_pciercx_cfg001 pciercx_cfg001;
+ union cvmx_pciercx_cfg032 pciercx_cfg032;
+ union cvmx_pciercx_cfg006 pciercx_cfg006;
+ union cvmx_pciercx_cfg008 pciercx_cfg008;
+ union cvmx_pciercx_cfg009 pciercx_cfg009;
+ union cvmx_pciercx_cfg010 pciercx_cfg010;
+ union cvmx_pciercx_cfg011 pciercx_cfg011;
+ union cvmx_pciercx_cfg035 pciercx_cfg035;
+ union cvmx_pciercx_cfg075 pciercx_cfg075;
+ union cvmx_pciercx_cfg034 pciercx_cfg034;
+
+ /* Max Payload Size (PCIE*_CFG030[MPS]) */
+ /* Max Read Request Size (PCIE*_CFG030[MRRS]) */
+ /* Relaxed-order, no-snoop enables (PCIE*_CFG030[RO_EN,NS_EN] */
+ /* Error Message Enables (PCIE*_CFG030[CE_EN,NFE_EN,FE_EN,UR_EN]) */
+ pciercx_cfg030.u32 =
+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG030(pcie_port));
+ /*
+ * Max payload size = 128 bytes for best Octeon DMA
+ * performance.
+ */
+ pciercx_cfg030.s.mps = 0;
+ /*
+ * Max read request size = 128 bytes for best Octeon DMA
+ * performance.
+ */
+ pciercx_cfg030.s.mrrs = 0;
+ /* Enable relaxed ordering. */
+ pciercx_cfg030.s.ro_en = 1;
+ /* Enable no snoop. */
+ pciercx_cfg030.s.ns_en = 1;
+ /* Correctable error reporting enable. */
+ pciercx_cfg030.s.ce_en = 1;
+ /* Non-fatal error reporting enable. */
+ pciercx_cfg030.s.nfe_en = 1;
+ /* Fatal error reporting enable. */
+ pciercx_cfg030.s.fe_en = 1;
+ /* Unsupported request reporting enable. */
+ pciercx_cfg030.s.ur_en = 1;
+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG030(pcie_port),
+ pciercx_cfg030.u32);
+
+ /*
+ * Max Payload Size (NPEI_CTL_STATUS2[MPS]) must match
+ * PCIE*_CFG030[MPS]
+ *
+ * Max Read Request Size (NPEI_CTL_STATUS2[MRRS]) must not
+ * exceed PCIE*_CFG030[MRRS].
+ */
+ npei_ctl_status2.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS2);
+ /* Max payload size = 128 bytes for best Octeon DMA performance */
+ npei_ctl_status2.s.mps = 0;
+ /* Max read request size = 128 bytes for best Octeon DMA performance */
+ npei_ctl_status2.s.mrrs = 0;
+ cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS2, npei_ctl_status2.u64);
+
+ /* ECRC Generation (PCIE*_CFG070[GE,CE]) */
+ pciercx_cfg070.u32 =
+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG070(pcie_port));
+ pciercx_cfg070.s.ge = 1; /* ECRC generation enable. */
+ pciercx_cfg070.s.ce = 1; /* ECRC check enable. */
+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG070(pcie_port),
+ pciercx_cfg070.u32);
+
+ /*
+ * Access Enables (PCIE*_CFG001[MSAE,ME]) ME and MSAE should
+ * always be set.
+ *
+ * Interrupt Disable (PCIE*_CFG001[I_DIS]) System Error
+ * Message Enable (PCIE*_CFG001[SEE])
+ */
+ pciercx_cfg001.u32 =
+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG001(pcie_port));
+ pciercx_cfg001.s.msae = 1; /* Memory space enable. */
+ pciercx_cfg001.s.me = 1; /* Bus master enable. */
+ pciercx_cfg001.s.i_dis = 1; /* INTx assertion disable. */
+ pciercx_cfg001.s.see = 1; /* SERR# enable */
+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG001(pcie_port),
+ pciercx_cfg001.u32);
+
+ /* Advanced Error Recovery Message Enables */
+ /* (PCIE*_CFG066,PCIE*_CFG067,PCIE*_CFG069) */
+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG066(pcie_port), 0);
+ /* Use CVMX_PCIERCX_CFG067 hardware default */
+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG069(pcie_port), 0);
+
+ /* Active State Power Management (PCIE*_CFG032[ASLPC]) */
+ pciercx_cfg032.u32 =
+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port));
+ pciercx_cfg032.s.aslpc = 0; /* Active state Link PM control. */
+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG032(pcie_port),
+ pciercx_cfg032.u32);
+
+ /* Entrance Latencies (PCIE*_CFG451[L0EL,L1EL]) */
+
+ /*
+ * Link Width Mode (PCIERCn_CFG452[LME]) - Set during
+ * cvmx_pcie_rc_initialize_link()
+ *
+ * Primary Bus Number (PCIERCn_CFG006[PBNUM])
+ *
+ * We set the primary bus number to 1 so IDT bridges are
+ * happy. They don't like zero.
+ */
+ pciercx_cfg006.u32 = 0;
+ pciercx_cfg006.s.pbnum = 1;
+ pciercx_cfg006.s.sbnum = 1;
+ pciercx_cfg006.s.subbnum = 1;
+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG006(pcie_port),
+ pciercx_cfg006.u32);
+
+ /*
+ * Memory-mapped I/O BAR (PCIERCn_CFG008)
+ * Most applications should disable the memory-mapped I/O BAR by
+ * setting PCIERCn_CFG008[ML_ADDR] < PCIERCn_CFG008[MB_ADDR]
+ */
+ pciercx_cfg008.u32 = 0;
+ pciercx_cfg008.s.mb_addr = 0x100;
+ pciercx_cfg008.s.ml_addr = 0;
+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG008(pcie_port),
+ pciercx_cfg008.u32);
+
+ /*
+ * Prefetchable BAR (PCIERCn_CFG009,PCIERCn_CFG010,PCIERCn_CFG011)
+ * Most applications should disable the prefetchable BAR by setting
+ * PCIERCn_CFG011[UMEM_LIMIT],PCIERCn_CFG009[LMEM_LIMIT] <
+ * PCIERCn_CFG010[UMEM_BASE],PCIERCn_CFG009[LMEM_BASE]
+ */
+ pciercx_cfg009.u32 =
+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG009(pcie_port));
+ pciercx_cfg010.u32 =
+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG010(pcie_port));
+ pciercx_cfg011.u32 =
+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG011(pcie_port));
+ pciercx_cfg009.s.lmem_base = 0x100;
+ pciercx_cfg009.s.lmem_limit = 0;
+ pciercx_cfg010.s.umem_base = 0x100;
+ pciercx_cfg011.s.umem_limit = 0;
+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG009(pcie_port),
+ pciercx_cfg009.u32);
+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG010(pcie_port),
+ pciercx_cfg010.u32);
+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG011(pcie_port),
+ pciercx_cfg011.u32);
+
+ /*
+ * System Error Interrupt Enables (PCIERCn_CFG035[SECEE,SEFEE,SENFEE])
+ * PME Interrupt Enables (PCIERCn_CFG035[PMEIE])
+ */
+ pciercx_cfg035.u32 =
+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG035(pcie_port));
+ /* System error on correctable error enable. */
+ pciercx_cfg035.s.secee = 1;
+ /* System error on fatal error enable. */
+ pciercx_cfg035.s.sefee = 1;
+ /* System error on non-fatal error enable. */
+ pciercx_cfg035.s.senfee = 1;
+ /* PME interrupt enable. */
+ pciercx_cfg035.s.pmeie = 1;
+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG035(pcie_port),
+ pciercx_cfg035.u32);
+
+ /*
+ * Advanced Error Recovery Interrupt Enables
+ * (PCIERCn_CFG075[CERE,NFERE,FERE])
+ */
+ pciercx_cfg075.u32 =
+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG075(pcie_port));
+ /* Correctable error reporting enable. */
+ pciercx_cfg075.s.cere = 1;
+ /* Non-fatal error reporting enable. */
+ pciercx_cfg075.s.nfere = 1;
+ /* Fatal error reporting enable. */
+ pciercx_cfg075.s.fere = 1;
+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG075(pcie_port),
+ pciercx_cfg075.u32);
+
+ /* HP Interrupt Enables (PCIERCn_CFG034[HPINT_EN],
+ * PCIERCn_CFG034[DLLS_EN,CCINT_EN])
+ */
+ pciercx_cfg034.u32 =
+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG034(pcie_port));
+ /* Hot-plug interrupt enable. */
+ pciercx_cfg034.s.hpint_en = 1;
+ /* Data Link Layer state changed enable */
+ pciercx_cfg034.s.dlls_en = 1;
+ /* Command completed interrupt enable. */
+ pciercx_cfg034.s.ccint_en = 1;
+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG034(pcie_port),
+ pciercx_cfg034.u32);
+}
+
+/**
+ * Initialize a host mode PCIe link. This function takes a PCIe
+ * port from reset to a link up state. Software can then begin
+ * configuring the rest of the link.
+ *
+ * @pcie_port: PCIe port to initialize
+ *
+ * Returns Zero on success
+ */
+static int __cvmx_pcie_rc_initialize_link(int pcie_port)
+{
+ uint64_t start_cycle;
+ union cvmx_pescx_ctl_status pescx_ctl_status;
+ union cvmx_pciercx_cfg452 pciercx_cfg452;
+ union cvmx_pciercx_cfg032 pciercx_cfg032;
+ union cvmx_pciercx_cfg448 pciercx_cfg448;
+
+ /* Set the lane width */
+ pciercx_cfg452.u32 =
+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG452(pcie_port));
+ pescx_ctl_status.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS(pcie_port));
+ if (pescx_ctl_status.s.qlm_cfg == 0) {
+ /* We're in 8 lane (56XX) or 4 lane (54XX) mode */
+ pciercx_cfg452.s.lme = 0xf;
+ } else {
+ /* We're in 4 lane (56XX) or 2 lane (52XX) mode */
+ pciercx_cfg452.s.lme = 0x7;
+ }
+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG452(pcie_port),
+ pciercx_cfg452.u32);
+
+ /*
+ * CN52XX pass 1.x has an errata where length mismatches on UR
+ * responses can cause bus errors on 64bit memory
+ * reads. Turning off length error checking fixes this.
+ */
+ if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) {
+ union cvmx_pciercx_cfg455 pciercx_cfg455;
+ pciercx_cfg455.u32 =
+ cvmx_pcie_cfgx_read(pcie_port,
+ CVMX_PCIERCX_CFG455(pcie_port));
+ pciercx_cfg455.s.m_cpl_len_err = 1;
+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG455(pcie_port),
+ pciercx_cfg455.u32);
+ }
+
+ /* Lane swap needs to be manually enabled for CN52XX */
+ if (OCTEON_IS_MODEL(OCTEON_CN52XX) && (pcie_port == 1)) {
+ pescx_ctl_status.s.lane_swp = 1;
+ cvmx_write_csr(CVMX_PESCX_CTL_STATUS(pcie_port),
+ pescx_ctl_status.u64);
+ }
+
+ /* Bring up the link */
+ pescx_ctl_status.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS(pcie_port));
+ pescx_ctl_status.s.lnk_enb = 1;
+ cvmx_write_csr(CVMX_PESCX_CTL_STATUS(pcie_port), pescx_ctl_status.u64);
+
+ /*
+ * CN52XX pass 1.0: Due to a bug in 2nd order CDR, it needs to
+ * be disabled.
+ */
+ if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0))
+ __cvmx_helper_errata_qlm_disable_2nd_order_cdr(0);
+
+ /* Wait for the link to come up */
+ cvmx_dprintf("PCIe: Waiting for port %d link\n", pcie_port);
+ start_cycle = cvmx_get_cycle();
+ do {
+ if (cvmx_get_cycle() - start_cycle >
+ 2 * cvmx_sysinfo_get()->cpu_clock_hz) {
+ cvmx_dprintf("PCIe: Port %d link timeout\n",
+ pcie_port);
+ return -1;
+ }
+ cvmx_wait(10000);
+ pciercx_cfg032.u32 =
+ cvmx_pcie_cfgx_read(pcie_port,
+ CVMX_PCIERCX_CFG032(pcie_port));
+ } while (pciercx_cfg032.s.dlla == 0);
+
+ /* Display the link status */
+ cvmx_dprintf("PCIe: Port %d link active, %d lanes\n", pcie_port,
+ pciercx_cfg032.s.nlw);
+
+ /*
+ * Update the Replay Time Limit. Empirically, some PCIe
+ * devices take a little longer to respond than expected under
+ * load. As a workaround for this we configure the Replay Time
+ * Limit to the value expected for a 512 byte MPS instead of
+ * our actual 256 byte MPS. The numbers below are directly
+ * from the PCIe spec table 3-4.
+ */
+ pciercx_cfg448.u32 =
+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG448(pcie_port));
+ switch (pciercx_cfg032.s.nlw) {
+ case 1: /* 1 lane */
+ pciercx_cfg448.s.rtl = 1677;
+ break;
+ case 2: /* 2 lanes */
+ pciercx_cfg448.s.rtl = 867;
+ break;
+ case 4: /* 4 lanes */
+ pciercx_cfg448.s.rtl = 462;
+ break;
+ case 8: /* 8 lanes */
+ pciercx_cfg448.s.rtl = 258;
+ break;
+ }
+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG448(pcie_port),
+ pciercx_cfg448.u32);
+
+ return 0;
+}
+
+/**
+ * Initialize a PCIe port for use in host(RC) mode. It doesn't
+ * enumerate the bus.
+ *
+ * @pcie_port: PCIe port to initialize
+ *
+ * Returns Zero on success
+ */
+static int cvmx_pcie_rc_initialize(int pcie_port)
+{
+ int i;
+ union cvmx_ciu_soft_prst ciu_soft_prst;
+ union cvmx_pescx_bist_status pescx_bist_status;
+ union cvmx_pescx_bist_status2 pescx_bist_status2;
+ union cvmx_npei_ctl_status npei_ctl_status;
+ union cvmx_npei_mem_access_ctl npei_mem_access_ctl;
+ union cvmx_npei_mem_access_subidx mem_access_subid;
+ union cvmx_npei_dbg_data npei_dbg_data;
+ union cvmx_pescx_ctl_status2 pescx_ctl_status2;
+
+ /*
+ * Make sure we aren't trying to setup a target mode interface
+ * in host mode.
+ */
+ npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS);
+ if ((pcie_port == 0) && !npei_ctl_status.s.host_mode) {
+ cvmx_dprintf("PCIe: ERROR: cvmx_pcie_rc_initialize() called "
+ "on port0, but port0 is not in host mode\n");
+ return -1;
+ }
+
+ /*
+ * Make sure a CN52XX isn't trying to bring up port 1 when it
+ * is disabled.
+ */
+ if (OCTEON_IS_MODEL(OCTEON_CN52XX)) {
+ npei_dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA);
+ if ((pcie_port == 1) && npei_dbg_data.cn52xx.qlm0_link_width) {
+ cvmx_dprintf("PCIe: ERROR: cvmx_pcie_rc_initialize() "
+ "called on port1, but port1 is "
+ "disabled\n");
+ return -1;
+ }
+ }
+
+ /*
+ * PCIe switch arbitration mode. '0' == fixed priority NPEI,
+ * PCIe0, then PCIe1. '1' == round robin.
+ */
+ npei_ctl_status.s.arb = 1;
+ /* Allow up to 0x20 config retries */
+ npei_ctl_status.s.cfg_rtry = 0x20;
+ /*
+ * CN52XX pass1.x has an errata where P0_NTAGS and P1_NTAGS
+ * don't reset.
+ */
+ if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) {
+ npei_ctl_status.s.p0_ntags = 0x20;
+ npei_ctl_status.s.p1_ntags = 0x20;
+ }
+ cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS, npei_ctl_status.u64);
+
+ /* Bring the PCIe out of reset */
+ if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_EBH5200) {
+ /*
+ * The EBH5200 board swapped the PCIe reset lines on
+ * the board. As a workaround for this bug, we bring
+ * both PCIe ports out of reset at the same time
+ * instead of on separate calls. So for port 0, we
+ * bring both out of reset and do nothing on port 1.
+ */
+ if (pcie_port == 0) {
+ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST);
+ /*
+ * After a chip reset the PCIe will also be in
+ * reset. If it isn't, most likely someone is
+ * trying to init it again without a proper
+ * PCIe reset.
+ */
+ if (ciu_soft_prst.s.soft_prst == 0) {
+ /* Reset the ports */
+ ciu_soft_prst.s.soft_prst = 1;
+ cvmx_write_csr(CVMX_CIU_SOFT_PRST,
+ ciu_soft_prst.u64);
+ ciu_soft_prst.u64 =
+ cvmx_read_csr(CVMX_CIU_SOFT_PRST1);
+ ciu_soft_prst.s.soft_prst = 1;
+ cvmx_write_csr(CVMX_CIU_SOFT_PRST1,
+ ciu_soft_prst.u64);
+ /* Wait until pcie resets the ports. */
+ udelay(2000);
+ }
+ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1);
+ ciu_soft_prst.s.soft_prst = 0;
+ cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64);
+ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST);
+ ciu_soft_prst.s.soft_prst = 0;
+ cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64);
+ }
+ } else {
+ /*
+ * The normal case: The PCIe ports are completely
+ * separate and can be brought out of reset
+ * independently.
+ */
+ if (pcie_port)
+ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1);
+ else
+ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST);
+ /*
+ * After a chip reset the PCIe will also be in
+ * reset. If it isn't, most likely someone is trying
+ * to init it again without a proper PCIe reset.
+ */
+ if (ciu_soft_prst.s.soft_prst == 0) {
+ /* Reset the port */
+ ciu_soft_prst.s.soft_prst = 1;
+ if (pcie_port)
+ cvmx_write_csr(CVMX_CIU_SOFT_PRST1,
+ ciu_soft_prst.u64);
+ else
+ cvmx_write_csr(CVMX_CIU_SOFT_PRST,
+ ciu_soft_prst.u64);
+ /* Wait until pcie resets the ports. */
+ udelay(2000);
+ }
+ if (pcie_port) {
+ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1);
+ ciu_soft_prst.s.soft_prst = 0;
+ cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64);
+ } else {
+ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST);
+ ciu_soft_prst.s.soft_prst = 0;
+ cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64);
+ }
+ }
+
+ /*
+ * Wait for PCIe reset to complete. Due to errata PCIE-700, we
+ * don't poll PESCX_CTL_STATUS2[PCIERST], but simply wait a
+ * fixed number of cycles.
+ */
+ cvmx_wait(400000);
+
+ /* PESCX_BIST_STATUS2[PCLK_RUN] was missing on pass 1 of CN56XX and
+ CN52XX, so we only probe it on newer chips */
+ if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)
+ && !OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) {
+ /* Clear PCLK_RUN so we can check if the clock is running */
+ pescx_ctl_status2.u64 =
+ cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port));
+ pescx_ctl_status2.s.pclk_run = 1;
+ cvmx_write_csr(CVMX_PESCX_CTL_STATUS2(pcie_port),
+ pescx_ctl_status2.u64);
+ /*
+ * Now that we cleared PCLK_RUN, wait for it to be set
+ * again telling us the clock is running.
+ */
+ if (CVMX_WAIT_FOR_FIELD64(CVMX_PESCX_CTL_STATUS2(pcie_port),
+ union cvmx_pescx_ctl_status2,
+ pclk_run, ==, 1, 10000)) {
+ cvmx_dprintf("PCIe: Port %d isn't clocked, skipping.\n",
+ pcie_port);
+ return -1;
+ }
+ }
+
+ /*
+ * Check and make sure PCIe came out of reset. If it doesn't
+ * the board probably hasn't wired the clocks up and the
+ * interface should be skipped.
+ */
+ pescx_ctl_status2.u64 =
+ cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port));
+ if (pescx_ctl_status2.s.pcierst) {
+ cvmx_dprintf("PCIe: Port %d stuck in reset, skipping.\n",
+ pcie_port);
+ return -1;
+ }
+
+ /*
+ * Check BIST2 status. If any bits are set skip this interface. This
+ * is an attempt to catch PCIE-813 on pass 1 parts.
+ */
+ pescx_bist_status2.u64 =
+ cvmx_read_csr(CVMX_PESCX_BIST_STATUS2(pcie_port));
+ if (pescx_bist_status2.u64) {
+ cvmx_dprintf("PCIe: Port %d BIST2 failed. Most likely this "
+ "port isn't hooked up, skipping.\n",
+ pcie_port);
+ return -1;
+ }
+
+ /* Check BIST status */
+ pescx_bist_status.u64 =
+ cvmx_read_csr(CVMX_PESCX_BIST_STATUS(pcie_port));
+ if (pescx_bist_status.u64)
+ cvmx_dprintf("PCIe: BIST FAILED for port %d (0x%016llx)\n",
+ pcie_port, CAST64(pescx_bist_status.u64));
+
+ /* Initialize the config space CSRs */
+ __cvmx_pcie_rc_initialize_config_space(pcie_port);
+
+ /* Bring the link up */
+ if (__cvmx_pcie_rc_initialize_link(pcie_port)) {
+ cvmx_dprintf
+ ("PCIe: ERROR: cvmx_pcie_rc_initialize_link() failed\n");
+ return -1;
+ }
+
+ /* Store merge control (NPEI_MEM_ACCESS_CTL[TIMER,MAX_WORD]) */
+ npei_mem_access_ctl.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL);
+ /* Allow 16 words to combine */
+ npei_mem_access_ctl.s.max_word = 0;
+ /* Wait up to 127 cycles for more data */
+ npei_mem_access_ctl.s.timer = 127;
+ cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL, npei_mem_access_ctl.u64);
+
+ /* Setup Mem access SubDIDs */
+ mem_access_subid.u64 = 0;
+ /* Port the request is sent to. */
+ mem_access_subid.s.port = pcie_port;
+ /* Due to an errata on pass 1 chips, no merging is allowed. */
+ mem_access_subid.s.nmerge = 1;
+ /* Endian-swap for Reads. */
+ mem_access_subid.s.esr = 1;
+ /* Endian-swap for Writes. */
+ mem_access_subid.s.esw = 1;
+ /* No Snoop for Reads. */
+ mem_access_subid.s.nsr = 1;
+ /* No Snoop for Writes. */
+ mem_access_subid.s.nsw = 1;
+ /* Disable Relaxed Ordering for Reads. */
+ mem_access_subid.s.ror = 0;
+ /* Disable Relaxed Ordering for Writes. */
+ mem_access_subid.s.row = 0;
+ /* PCIe Adddress Bits <63:34>. */
+ mem_access_subid.s.ba = 0;
+
+ /*
+ * Setup mem access 12-15 for port 0, 16-19 for port 1,
+ * supplying 36 bits of address space.
+ */
+ for (i = 12 + pcie_port * 4; i < 16 + pcie_port * 4; i++) {
+ cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_SUBIDX(i),
+ mem_access_subid.u64);
+ /* Set each SUBID to extend the addressable range */
+ mem_access_subid.s.ba += 1;
+ }
+
+ /*
+ * Disable the peer to peer forwarding register. This must be
+ * setup by the OS after it enumerates the bus and assigns
+ * addresses to the PCIe busses.
+ */
+ for (i = 0; i < 4; i++) {
+ cvmx_write_csr(CVMX_PESCX_P2P_BARX_START(i, pcie_port), -1);
+ cvmx_write_csr(CVMX_PESCX_P2P_BARX_END(i, pcie_port), -1);
+ }
+
+ /* Set Octeon's BAR0 to decode 0-16KB. It overlaps with Bar2 */
+ cvmx_write_csr(CVMX_PESCX_P2N_BAR0_START(pcie_port), 0);
+
+ /*
+ * Disable Octeon's BAR1. It isn't needed in RC mode since
+ * BAR2 maps all of memory. BAR2 also maps 256MB-512MB into
+ * the 2nd 256MB of memory.
+ */
+ cvmx_write_csr(CVMX_PESCX_P2N_BAR1_START(pcie_port), -1);
+
+ /*
+ * Set Octeon's BAR2 to decode 0-2^39. Bar0 and Bar1 take
+ * precedence where they overlap. It also overlaps with the
+ * device addresses, so make sure the peer to peer forwarding
+ * is set right.
+ */
+ cvmx_write_csr(CVMX_PESCX_P2N_BAR2_START(pcie_port), 0);
+
+ /*
+ * Setup BAR2 attributes
+ *
+ * Relaxed Ordering (NPEI_CTL_PORTn[PTLP_RO,CTLP_RO, WAIT_COM])
+ * - PTLP_RO,CTLP_RO should normally be set (except for debug).
+ * - WAIT_COM=0 will likely work for all applications.
+ *
+ * Load completion relaxed ordering (NPEI_CTL_PORTn[WAITL_COM]).
+ */
+ if (pcie_port) {
+ union cvmx_npei_ctl_port1 npei_ctl_port;
+ npei_ctl_port.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_PORT1);
+ npei_ctl_port.s.bar2_enb = 1;
+ npei_ctl_port.s.bar2_esx = 1;
+ npei_ctl_port.s.bar2_cax = 0;
+ npei_ctl_port.s.ptlp_ro = 1;
+ npei_ctl_port.s.ctlp_ro = 1;
+ npei_ctl_port.s.wait_com = 0;
+ npei_ctl_port.s.waitl_com = 0;
+ cvmx_write_csr(CVMX_PEXP_NPEI_CTL_PORT1, npei_ctl_port.u64);
+ } else {
+ union cvmx_npei_ctl_port0 npei_ctl_port;
+ npei_ctl_port.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_PORT0);
+ npei_ctl_port.s.bar2_enb = 1;
+ npei_ctl_port.s.bar2_esx = 1;
+ npei_ctl_port.s.bar2_cax = 0;
+ npei_ctl_port.s.ptlp_ro = 1;
+ npei_ctl_port.s.ctlp_ro = 1;
+ npei_ctl_port.s.wait_com = 0;
+ npei_ctl_port.s.waitl_com = 0;
+ cvmx_write_csr(CVMX_PEXP_NPEI_CTL_PORT0, npei_ctl_port.u64);
+ }
+ return 0;
+}
+
+
+/* Above was cvmx-pcie.c, below original pcie.c */
+
+
+/**
+ * Map a PCI device to the appropriate interrupt line
+ *
+ * @param dev The Linux PCI device structure for the device to map
+ * @param slot The slot number for this device on __BUS 0__. Linux
+ * enumerates through all the bridges and figures out the
+ * slot on Bus 0 where this device eventually hooks to.
+ * @param pin The PCI interrupt pin read from the device, then swizzled
+ * as it goes through each bridge.
+ * @return Interrupt number for the device
+ */
+int __init octeon_pcie_pcibios_map_irq(const struct pci_dev *dev,
+ u8 slot, u8 pin)
+{
+ /*
+ * The EBH5600 board with the PCI to PCIe bridge mistakenly
+ * wires the first slot for both device id 2 and interrupt
+ * A. According to the PCI spec, device id 2 should be C. The
+ * following kludge attempts to fix this.
+ */
+ if (strstr(octeon_board_type_string(), "EBH5600") &&
+ dev->bus && dev->bus->parent) {
+ /*
+ * Iterate all the way up the device chain and find
+ * the root bus.
+ */
+ while (dev->bus && dev->bus->parent)
+ dev = to_pci_dev(dev->bus->bridge);
+ /* If the root bus is number 0 and the PEX 8114 is the
+ * root, assume we are behind the miswired bus. We
+ * need to correct the swizzle level by two. Yuck.
+ */
+ if ((dev->bus->number == 0) &&
+ (dev->vendor == 0x10b5) && (dev->device == 0x8114)) {
+ /*
+ * The pin field is one based, not zero. We
+ * need to swizzle it by minus two.
+ */
+ pin = ((pin - 3) & 3) + 1;
+ }
+ }
+ /*
+ * The -1 is because pin starts with one, not zero. It might
+ * be that this equation needs to include the slot number, but
+ * I don't have hardware to check that against.
+ */
+ return pin - 1 + OCTEON_IRQ_PCI_INT0;
+}
+
+/**
+ * Read a value from configuration space
+ *
+ * @param bus
+ * @param devfn
+ * @param reg
+ * @param size
+ * @param val
+ * @return
+ */
+static inline int octeon_pcie_read_config(int pcie_port, struct pci_bus *bus,
+ unsigned int devfn, int reg, int size,
+ u32 *val)
+{
+ union octeon_cvmemctl cvmmemctl;
+ union octeon_cvmemctl cvmmemctl_save;
+ int bus_number = bus->number;
+
+ /*
+ * We need to force the bus number to be zero on the root
+ * bus. Linux numbers the 2nd root bus to start after all
+ * buses on root 0.
+ */
+ if (bus->parent == NULL)
+ bus_number = 0;
+
+ /*
+ * PCIe only has a single device connected to Octeon. It is
+ * always device ID 0. Don't bother doing reads for other
+ * device IDs on the first segment.
+ */
+ if ((bus_number == 0) && (devfn >> 3 != 0))
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+
+ /*
+ * The following is a workaround for the CN57XX, CN56XX,
+ * CN55XX, and CN54XX errata with PCIe config reads from non
+ * existent devices. These chips will hang the PCIe link if a
+ * config read is performed that causes a UR response.
+ */
+ if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1) ||
+ OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_1)) {
+ /*
+ * For our EBH5600 board, port 0 has a bridge with two
+ * PCI-X slots. We need a new special checks to make
+ * sure we only probe valid stuff. The PCIe->PCI-X
+ * bridge only respondes to device ID 0, function
+ * 0-1
+ */
+ if ((bus_number == 0) && (devfn >= 2))
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+ /*
+ * The PCI-X slots are device ID 2,3. Choose one of
+ * the below "if" blocks based on what is plugged into
+ * the board.
+ */
+#if 1
+ /* Use this option if you aren't using either slot */
+ if (bus_number == 1)
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+#elif 0
+ /*
+ * Use this option if you are using the first slot but
+ * not the second.
+ */
+ if ((bus_number == 1) && (devfn >> 3 != 2))
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+#elif 0
+ /*
+ * Use this option if you are using the second slot
+ * but not the first.
+ */
+ if ((bus_number == 1) && (devfn >> 3 != 3))
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+#elif 0
+ /* Use this opion if you are using both slots */
+ if ((bus_number == 1) &&
+ !((devfn == (2 << 3)) || (devfn == (3 << 3))))
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+#endif
+
+ /*
+ * Shorten the DID timeout so bus errors for PCIe
+ * config reads from non existent devices happen
+ * faster. This allows us to continue booting even if
+ * the above "if" checks are wrong. Once one of these
+ * errors happens, the PCIe port is dead.
+ */
+ cvmmemctl_save.u64 = __read_64bit_c0_register($11, 7);
+ cvmmemctl.u64 = cvmmemctl_save.u64;
+ cvmmemctl.s.didtto = 2;
+ __write_64bit_c0_register($11, 7, cvmmemctl.u64);
+ }
+
+ switch (size) {
+ case 4:
+ *val = cvmx_pcie_config_read32(pcie_port, bus_number,
+ devfn >> 3, devfn & 0x7, reg);
+ break;
+ case 2:
+ *val = cvmx_pcie_config_read16(pcie_port, bus_number,
+ devfn >> 3, devfn & 0x7, reg);
+ break;
+ case 1:
+ *val = cvmx_pcie_config_read8(pcie_port, bus_number, devfn >> 3,
+ devfn & 0x7, reg);
+ break;
+ default:
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+ }
+
+ if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1) ||
+ OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_1))
+ __write_64bit_c0_register($11, 7, cvmmemctl_save.u64);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int octeon_pcie0_read_config(struct pci_bus *bus, unsigned int devfn,
+ int reg, int size, u32 *val)
+{
+ return octeon_pcie_read_config(0, bus, devfn, reg, size, val);
+}
+
+static int octeon_pcie1_read_config(struct pci_bus *bus, unsigned int devfn,
+ int reg, int size, u32 *val)
+{
+ return octeon_pcie_read_config(1, bus, devfn, reg, size, val);
+}
+
+
+
+/**
+ * Write a value to PCI configuration space
+ *
+ * @param bus
+ * @param devfn
+ * @param reg
+ * @param size
+ * @param val
+ * @return
+ */
+static inline int octeon_pcie_write_config(int pcie_port, struct pci_bus *bus,
+ unsigned int devfn, int reg,
+ int size, u32 val)
+{
+ int bus_number = bus->number;
+ /*
+ * We need to force the bus number to be zero on the root
+ * bus. Linux numbers the 2nd root bus to start after all
+ * busses on root 0.
+ */
+ if (bus->parent == NULL)
+ bus_number = 0;
+
+ switch (size) {
+ case 4:
+ cvmx_pcie_config_write32(pcie_port, bus_number, devfn >> 3,
+ devfn & 0x7, reg, val);
+ return PCIBIOS_SUCCESSFUL;
+ case 2:
+ cvmx_pcie_config_write16(pcie_port, bus_number, devfn >> 3,
+ devfn & 0x7, reg, val);
+ return PCIBIOS_SUCCESSFUL;
+ case 1:
+ cvmx_pcie_config_write8(pcie_port, bus_number, devfn >> 3,
+ devfn & 0x7, reg, val);
+ return PCIBIOS_SUCCESSFUL;
+ }
+#if PCI_CONFIG_SPACE_DELAY
+ udelay(PCI_CONFIG_SPACE_DELAY);
+#endif
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+}
+
+static int octeon_pcie0_write_config(struct pci_bus *bus, unsigned int devfn,
+ int reg, int size, u32 val)
+{
+ return octeon_pcie_write_config(0, bus, devfn, reg, size, val);
+}
+
+static int octeon_pcie1_write_config(struct pci_bus *bus, unsigned int devfn,
+ int reg, int size, u32 val)
+{
+ return octeon_pcie_write_config(1, bus, devfn, reg, size, val);
+}
+
+static struct pci_ops octeon_pcie0_ops = {
+ octeon_pcie0_read_config,
+ octeon_pcie0_write_config,
+};
+
+static struct resource octeon_pcie0_mem_resource = {
+ .name = "Octeon PCIe0 MEM",
+ .flags = IORESOURCE_MEM,
+};
+
+static struct resource octeon_pcie0_io_resource = {
+ .name = "Octeon PCIe0 IO",
+ .flags = IORESOURCE_IO,
+};
+
+static struct pci_controller octeon_pcie0_controller = {
+ .pci_ops = &octeon_pcie0_ops,
+ .mem_resource = &octeon_pcie0_mem_resource,
+ .io_resource = &octeon_pcie0_io_resource,
+};
+
+static struct pci_ops octeon_pcie1_ops = {
+ octeon_pcie1_read_config,
+ octeon_pcie1_write_config,
+};
+
+static struct resource octeon_pcie1_mem_resource = {
+ .name = "Octeon PCIe1 MEM",
+ .flags = IORESOURCE_MEM,
+};
+
+static struct resource octeon_pcie1_io_resource = {
+ .name = "Octeon PCIe1 IO",
+ .flags = IORESOURCE_IO,
+};
+
+static struct pci_controller octeon_pcie1_controller = {
+ .pci_ops = &octeon_pcie1_ops,
+ .mem_resource = &octeon_pcie1_mem_resource,
+ .io_resource = &octeon_pcie1_io_resource,
+};
+
+
+/**
+ * Initialize the Octeon PCIe controllers
+ *
+ * @return
+ */
+static int __init octeon_pcie_setup(void)
+{
+ union cvmx_npei_ctl_status npei_ctl_status;
+ int result;
+
+ /* These chips don't have PCIe */
+ if (!octeon_has_feature(OCTEON_FEATURE_PCIE))
+ return 0;
+
+ /* Point pcibios_map_irq() to the PCIe version of it */
+ octeon_pcibios_map_irq = octeon_pcie_pcibios_map_irq;
+
+ /* Use the PCIe based DMA mappings */
+ octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_PCIE;
+
+ /*
+ * PCIe I/O range. It is based on port 0 but includes up until
+ * port 1's end.
+ */
+ set_io_port_base(CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address(0)));
+ ioport_resource.start = 0;
+ ioport_resource.end =
+ cvmx_pcie_get_io_base_address(1) -
+ cvmx_pcie_get_io_base_address(0) + cvmx_pcie_get_io_size(1) - 1;
+
+ npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS);
+ if (npei_ctl_status.s.host_mode) {
+ pr_notice("PCIe: Initializing port 0\n");
+ result = cvmx_pcie_rc_initialize(0);
+ if (result == 0) {
+ /* Memory offsets are physical addresses */
+ octeon_pcie0_controller.mem_offset =
+ cvmx_pcie_get_mem_base_address(0);
+ /* IO offsets are Mips virtual addresses */
+ octeon_pcie0_controller.io_map_base =
+ CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address
+ (0));
+ octeon_pcie0_controller.io_offset = 0;
+ /*
+ * To keep things similar to PCI, we start
+ * device addresses at the same place as PCI
+ * uisng big bar support. This normally
+ * translates to 4GB-256MB, which is the same
+ * as most x86 PCs.
+ */
+ octeon_pcie0_controller.mem_resource->start =
+ cvmx_pcie_get_mem_base_address(0) +
+ (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20);
+ octeon_pcie0_controller.mem_resource->end =
+ cvmx_pcie_get_mem_base_address(0) +
+ cvmx_pcie_get_mem_size(0) - 1;
+ /*
+ * Ports must be above 16KB for the ISA bus
+ * filtering in the PCI-X to PCI bridge.
+ */
+ octeon_pcie0_controller.io_resource->start = 4 << 10;
+ octeon_pcie0_controller.io_resource->end =
+ cvmx_pcie_get_io_size(0) - 1;
+ register_pci_controller(&octeon_pcie0_controller);
+ }
+ } else {
+ pr_notice("PCIe: Port 0 in endpoint mode, skipping.\n");
+ }
+
+ /* Skip the 2nd port on CN52XX if port 0 is in 4 lane mode */
+ if (OCTEON_IS_MODEL(OCTEON_CN52XX)) {
+ union cvmx_npei_dbg_data npei_dbg_data;
+ npei_dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA);
+ if (npei_dbg_data.cn52xx.qlm0_link_width)
+ return 0;
+ }
+
+ pr_notice("PCIe: Initializing port 1\n");
+ result = cvmx_pcie_rc_initialize(1);
+ if (result == 0) {
+ /* Memory offsets are physical addresses */
+ octeon_pcie1_controller.mem_offset =
+ cvmx_pcie_get_mem_base_address(1);
+ /* IO offsets are Mips virtual addresses */
+ octeon_pcie1_controller.io_map_base =
+ CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address(1));
+ octeon_pcie1_controller.io_offset =
+ cvmx_pcie_get_io_base_address(1) -
+ cvmx_pcie_get_io_base_address(0);
+ /*
+ * To keep things similar to PCI, we start device
+ * addresses at the same place as PCI uisng big bar
+ * support. This normally translates to 4GB-256MB,
+ * which is the same as most x86 PCs.
+ */
+ octeon_pcie1_controller.mem_resource->start =
+ cvmx_pcie_get_mem_base_address(1) + (4ul << 30) -
+ (OCTEON_PCI_BAR1_HOLE_SIZE << 20);
+ octeon_pcie1_controller.mem_resource->end =
+ cvmx_pcie_get_mem_base_address(1) +
+ cvmx_pcie_get_mem_size(1) - 1;
+ /*
+ * Ports must be above 16KB for the ISA bus filtering
+ * in the PCI-X to PCI bridge.
+ */
+ octeon_pcie1_controller.io_resource->start =
+ cvmx_pcie_get_io_base_address(1) -
+ cvmx_pcie_get_io_base_address(0);
+ octeon_pcie1_controller.io_resource->end =
+ octeon_pcie1_controller.io_resource->start +
+ cvmx_pcie_get_io_size(1) - 1;
+ register_pci_controller(&octeon_pcie1_controller);
+ }
+ return 0;
+}
+
+arch_initcall(octeon_pcie_setup);
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
index 783da855a2e3..d6d35b2e5fe8 100644
--- a/arch/mips/configs/bigsur_defconfig
+++ b/arch/mips/configs/bigsur_defconfig
@@ -963,7 +963,7 @@ CONFIG_EEPROM_LEGACY=y
CONFIG_SENSORS_PCF8574=y
# CONFIG_PCF8575 is not set
CONFIG_SENSORS_PCF8591=y
-CONFIG_SENSORS_MAX6875=y
+CONFIG_EEPROM_MAX6875=y
# CONFIG_SENSORS_TSL2550 is not set
CONFIG_I2C_DEBUG_CORE=y
CONFIG_I2C_DEBUG_ALGO=y
diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig
index 8426d3b9501c..fadb351d249b 100644
--- a/arch/mips/configs/mtx1_defconfig
+++ b/arch/mips/configs/mtx1_defconfig
@@ -1849,7 +1849,7 @@ CONFIG_EEPROM_LEGACY=m
CONFIG_SENSORS_PCF8574=m
CONFIG_SENSORS_PCA9539=m
CONFIG_SENSORS_PCF8591=m
-CONFIG_SENSORS_MAX6875=m
+CONFIG_EEPROM_MAX6875=m
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h
index 3214ade02d10..4f1eed107b08 100644
--- a/arch/mips/include/asm/irq.h
+++ b/arch/mips/include/asm/irq.h
@@ -49,7 +49,7 @@ static inline void smtc_im_ack_irq(unsigned int irq)
#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
#include <linux/cpumask.h>
-extern void plat_set_irq_affinity(unsigned int irq,
+extern int plat_set_irq_affinity(unsigned int irq,
const struct cpumask *affinity);
extern void smtc_forward_irq(unsigned int irq);
diff --git a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
index f30fce92aabb..17d579471ec4 100644
--- a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
+++ b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
@@ -30,12 +30,14 @@ static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
return octeon_map_dma_mem(dev, page_address(page), PAGE_SIZE);
}
-static inline unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
+ dma_addr_t dma_addr)
{
return dma_addr;
}
-static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
+static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
+ size_t size, enum dma_data_direction direction)
{
octeon_unmap_dma_mem(dev, dma_addr);
}
diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h
index 36c611b6c597..8da98073e952 100644
--- a/arch/mips/include/asm/mach-generic/dma-coherence.h
+++ b/arch/mips/include/asm/mach-generic/dma-coherence.h
@@ -23,12 +23,14 @@ static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
return page_to_phys(page);
}
-static inline unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
+ dma_addr_t dma_addr)
{
return dma_addr;
}
-static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
+static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
+ size_t size, enum dma_data_direction direction)
{
}
diff --git a/arch/mips/include/asm/mach-ip27/dma-coherence.h b/arch/mips/include/asm/mach-ip27/dma-coherence.h
index 4c21bfca10c3..d3d04018a858 100644
--- a/arch/mips/include/asm/mach-ip27/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ip27/dma-coherence.h
@@ -33,12 +33,14 @@ static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page)
return pa;
}
-static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+static unsigned long plat_dma_addr_to_phys(struct device *dev,
+ dma_addr_t dma_addr)
{
return dma_addr & ~(0xffUL << 56);
}
-static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
+static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
+ size_t size, enum dma_data_direction direction)
{
}
diff --git a/arch/mips/include/asm/mach-ip32/dma-coherence.h b/arch/mips/include/asm/mach-ip32/dma-coherence.h
index 7ae40f4b1c80..37855955b313 100644
--- a/arch/mips/include/asm/mach-ip32/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ip32/dma-coherence.h
@@ -50,7 +50,8 @@ static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page)
}
/* This is almost certainly wrong but it's what dma-ip32.c used to use */
-static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+static unsigned long plat_dma_addr_to_phys(struct device *dev,
+ dma_addr_t dma_addr)
{
unsigned long addr = dma_addr & RAM_OFFSET_MASK;
@@ -60,7 +61,8 @@ static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
return addr;
}
-static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
+static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
+ size_t size, enum dma_data_direction direction)
{
}
diff --git a/arch/mips/include/asm/mach-jazz/dma-coherence.h b/arch/mips/include/asm/mach-jazz/dma-coherence.h
index 1c7cd27efa7b..f93aee59454a 100644
--- a/arch/mips/include/asm/mach-jazz/dma-coherence.h
+++ b/arch/mips/include/asm/mach-jazz/dma-coherence.h
@@ -22,12 +22,14 @@ static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page)
return vdma_alloc(page_to_phys(page), PAGE_SIZE);
}
-static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+static unsigned long plat_dma_addr_to_phys(struct device *dev,
+ dma_addr_t dma_addr)
{
return vdma_log2phys(dma_addr);
}
-static void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
+static void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
+ size_t size, enum dma_data_direction direction)
{
vdma_free(dma_addr);
}
diff --git a/arch/mips/include/asm/mach-lemote/dma-coherence.h b/arch/mips/include/asm/mach-lemote/dma-coherence.h
index 38fad7dfe7da..c8de5e750777 100644
--- a/arch/mips/include/asm/mach-lemote/dma-coherence.h
+++ b/arch/mips/include/asm/mach-lemote/dma-coherence.h
@@ -25,12 +25,14 @@ static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
return page_to_phys(page) | 0x80000000;
}
-static inline unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
+ dma_addr_t dma_addr)
{
return dma_addr & 0x7fffffff;
}
-static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
+static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
+ size_t size, enum dma_data_direction direction)
{
}
diff --git a/arch/mips/include/asm/octeon/cvmx-helper-errata.h b/arch/mips/include/asm/octeon/cvmx-helper-errata.h
new file mode 100644
index 000000000000..5fc99189ff58
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-helper-errata.h
@@ -0,0 +1,33 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_HELPER_ERRATA_H__
+#define __CVMX_HELPER_ERRATA_H__
+
+extern void __cvmx_helper_errata_qlm_disable_2nd_order_cdr(int qlm);
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-helper-jtag.h b/arch/mips/include/asm/octeon/cvmx-helper-jtag.h
new file mode 100644
index 000000000000..29f016ddb895
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-helper-jtag.h
@@ -0,0 +1,43 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/**
+ * @file
+ *
+ * Helper utilities for qlm_jtag.
+ *
+ */
+
+#ifndef __CVMX_HELPER_JTAG_H__
+#define __CVMX_HELPER_JTAG_H__
+
+extern void cvmx_helper_qlm_jtag_init(void);
+extern uint32_t cvmx_helper_qlm_jtag_shift(int qlm, int bits, uint32_t data);
+extern void cvmx_helper_qlm_jtag_shift_zeros(int qlm, int bits);
+extern void cvmx_helper_qlm_jtag_update(int qlm);
+
+#endif /* __CVMX_HELPER_JTAG_H__ */
diff --git a/arch/mips/include/asm/octeon/cvmx-npei-defs.h b/arch/mips/include/asm/octeon/cvmx-npei-defs.h
new file mode 100644
index 000000000000..4b347bb8ce80
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-npei-defs.h
@@ -0,0 +1,2560 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_NPEI_DEFS_H__
+#define __CVMX_NPEI_DEFS_H__
+
+#define CVMX_NPEI_BAR1_INDEXX(offset) \
+ (0x0000000000000000ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_BIST_STATUS \
+ (0x0000000000000580ull)
+#define CVMX_NPEI_BIST_STATUS2 \
+ (0x0000000000000680ull)
+#define CVMX_NPEI_CTL_PORT0 \
+ (0x0000000000000250ull)
+#define CVMX_NPEI_CTL_PORT1 \
+ (0x0000000000000260ull)
+#define CVMX_NPEI_CTL_STATUS \
+ (0x0000000000000570ull)
+#define CVMX_NPEI_CTL_STATUS2 \
+ (0x0000000000003C00ull)
+#define CVMX_NPEI_DATA_OUT_CNT \
+ (0x00000000000005F0ull)
+#define CVMX_NPEI_DBG_DATA \
+ (0x0000000000000510ull)
+#define CVMX_NPEI_DBG_SELECT \
+ (0x0000000000000500ull)
+#define CVMX_NPEI_DMA0_INT_LEVEL \
+ (0x00000000000005C0ull)
+#define CVMX_NPEI_DMA1_INT_LEVEL \
+ (0x00000000000005D0ull)
+#define CVMX_NPEI_DMAX_COUNTS(offset) \
+ (0x0000000000000450ull + (((offset) & 7) * 16))
+#define CVMX_NPEI_DMAX_DBELL(offset) \
+ (0x00000000000003B0ull + (((offset) & 7) * 16))
+#define CVMX_NPEI_DMAX_IBUFF_SADDR(offset) \
+ (0x0000000000000400ull + (((offset) & 7) * 16))
+#define CVMX_NPEI_DMAX_NADDR(offset) \
+ (0x00000000000004A0ull + (((offset) & 7) * 16))
+#define CVMX_NPEI_DMA_CNTS \
+ (0x00000000000005E0ull)
+#define CVMX_NPEI_DMA_CONTROL \
+ (0x00000000000003A0ull)
+#define CVMX_NPEI_INT_A_ENB \
+ (0x0000000000000560ull)
+#define CVMX_NPEI_INT_A_ENB2 \
+ (0x0000000000003CE0ull)
+#define CVMX_NPEI_INT_A_SUM \
+ (0x0000000000000550ull)
+#define CVMX_NPEI_INT_ENB \
+ (0x0000000000000540ull)
+#define CVMX_NPEI_INT_ENB2 \
+ (0x0000000000003CD0ull)
+#define CVMX_NPEI_INT_INFO \
+ (0x0000000000000590ull)
+#define CVMX_NPEI_INT_SUM \
+ (0x0000000000000530ull)
+#define CVMX_NPEI_INT_SUM2 \
+ (0x0000000000003CC0ull)
+#define CVMX_NPEI_LAST_WIN_RDATA0 \
+ (0x0000000000000600ull)
+#define CVMX_NPEI_LAST_WIN_RDATA1 \
+ (0x0000000000000610ull)
+#define CVMX_NPEI_MEM_ACCESS_CTL \
+ (0x00000000000004F0ull)
+#define CVMX_NPEI_MEM_ACCESS_SUBIDX(offset) \
+ (0x0000000000000340ull + (((offset) & 31) * 16) - 16 * 12)
+#define CVMX_NPEI_MSI_ENB0 \
+ (0x0000000000003C50ull)
+#define CVMX_NPEI_MSI_ENB1 \
+ (0x0000000000003C60ull)
+#define CVMX_NPEI_MSI_ENB2 \
+ (0x0000000000003C70ull)
+#define CVMX_NPEI_MSI_ENB3 \
+ (0x0000000000003C80ull)
+#define CVMX_NPEI_MSI_RCV0 \
+ (0x0000000000003C10ull)
+#define CVMX_NPEI_MSI_RCV1 \
+ (0x0000000000003C20ull)
+#define CVMX_NPEI_MSI_RCV2 \
+ (0x0000000000003C30ull)
+#define CVMX_NPEI_MSI_RCV3 \
+ (0x0000000000003C40ull)
+#define CVMX_NPEI_MSI_RD_MAP \
+ (0x0000000000003CA0ull)
+#define CVMX_NPEI_MSI_W1C_ENB0 \
+ (0x0000000000003CF0ull)
+#define CVMX_NPEI_MSI_W1C_ENB1 \
+ (0x0000000000003D00ull)
+#define CVMX_NPEI_MSI_W1C_ENB2 \
+ (0x0000000000003D10ull)
+#define CVMX_NPEI_MSI_W1C_ENB3 \
+ (0x0000000000003D20ull)
+#define CVMX_NPEI_MSI_W1S_ENB0 \
+ (0x0000000000003D30ull)
+#define CVMX_NPEI_MSI_W1S_ENB1 \
+ (0x0000000000003D40ull)
+#define CVMX_NPEI_MSI_W1S_ENB2 \
+ (0x0000000000003D50ull)
+#define CVMX_NPEI_MSI_W1S_ENB3 \
+ (0x0000000000003D60ull)
+#define CVMX_NPEI_MSI_WR_MAP \
+ (0x0000000000003C90ull)
+#define CVMX_NPEI_PCIE_CREDIT_CNT \
+ (0x0000000000003D70ull)
+#define CVMX_NPEI_PCIE_MSI_RCV \
+ (0x0000000000003CB0ull)
+#define CVMX_NPEI_PCIE_MSI_RCV_B1 \
+ (0x0000000000000650ull)
+#define CVMX_NPEI_PCIE_MSI_RCV_B2 \
+ (0x0000000000000660ull)
+#define CVMX_NPEI_PCIE_MSI_RCV_B3 \
+ (0x0000000000000670ull)
+#define CVMX_NPEI_PKTX_CNTS(offset) \
+ (0x0000000000002400ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_PKTX_INSTR_BADDR(offset) \
+ (0x0000000000002800ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_PKTX_INSTR_BAOFF_DBELL(offset) \
+ (0x0000000000002C00ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_PKTX_INSTR_FIFO_RSIZE(offset) \
+ (0x0000000000003000ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_PKTX_INSTR_HEADER(offset) \
+ (0x0000000000003400ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_PKTX_IN_BP(offset) \
+ (0x0000000000003800ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_PKTX_SLIST_BADDR(offset) \
+ (0x0000000000001400ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_PKTX_SLIST_BAOFF_DBELL(offset) \
+ (0x0000000000001800ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_PKTX_SLIST_FIFO_RSIZE(offset) \
+ (0x0000000000001C00ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_PKT_CNT_INT \
+ (0x0000000000001110ull)
+#define CVMX_NPEI_PKT_CNT_INT_ENB \
+ (0x0000000000001130ull)
+#define CVMX_NPEI_PKT_DATA_OUT_ES \
+ (0x00000000000010B0ull)
+#define CVMX_NPEI_PKT_DATA_OUT_NS \
+ (0x00000000000010A0ull)
+#define CVMX_NPEI_PKT_DATA_OUT_ROR \
+ (0x0000000000001090ull)
+#define CVMX_NPEI_PKT_DPADDR \
+ (0x0000000000001080ull)
+#define CVMX_NPEI_PKT_INPUT_CONTROL \
+ (0x0000000000001150ull)
+#define CVMX_NPEI_PKT_INSTR_ENB \
+ (0x0000000000001000ull)
+#define CVMX_NPEI_PKT_INSTR_RD_SIZE \
+ (0x0000000000001190ull)
+#define CVMX_NPEI_PKT_INSTR_SIZE \
+ (0x0000000000001020ull)
+#define CVMX_NPEI_PKT_INT_LEVELS \
+ (0x0000000000001100ull)
+#define CVMX_NPEI_PKT_IN_BP \
+ (0x00000000000006B0ull)
+#define CVMX_NPEI_PKT_IN_DONEX_CNTS(offset) \
+ (0x0000000000002000ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_PKT_IN_INSTR_COUNTS \
+ (0x00000000000006A0ull)
+#define CVMX_NPEI_PKT_IN_PCIE_PORT \
+ (0x00000000000011A0ull)
+#define CVMX_NPEI_PKT_IPTR \
+ (0x0000000000001070ull)
+#define CVMX_NPEI_PKT_OUTPUT_WMARK \
+ (0x0000000000001160ull)
+#define CVMX_NPEI_PKT_OUT_BMODE \
+ (0x00000000000010D0ull)
+#define CVMX_NPEI_PKT_OUT_ENB \
+ (0x0000000000001010ull)
+#define CVMX_NPEI_PKT_PCIE_PORT \
+ (0x00000000000010E0ull)
+#define CVMX_NPEI_PKT_PORT_IN_RST \
+ (0x0000000000000690ull)
+#define CVMX_NPEI_PKT_SLIST_ES \
+ (0x0000000000001050ull)
+#define CVMX_NPEI_PKT_SLIST_ID_SIZE \
+ (0x0000000000001180ull)
+#define CVMX_NPEI_PKT_SLIST_NS \
+ (0x0000000000001040ull)
+#define CVMX_NPEI_PKT_SLIST_ROR \
+ (0x0000000000001030ull)
+#define CVMX_NPEI_PKT_TIME_INT \
+ (0x0000000000001120ull)
+#define CVMX_NPEI_PKT_TIME_INT_ENB \
+ (0x0000000000001140ull)
+#define CVMX_NPEI_RSL_INT_BLOCKS \
+ (0x0000000000000520ull)
+#define CVMX_NPEI_SCRATCH_1 \
+ (0x0000000000000270ull)
+#define CVMX_NPEI_STATE1 \
+ (0x0000000000000620ull)
+#define CVMX_NPEI_STATE2 \
+ (0x0000000000000630ull)
+#define CVMX_NPEI_STATE3 \
+ (0x0000000000000640ull)
+#define CVMX_NPEI_WINDOW_CTL \
+ (0x0000000000000380ull)
+#define CVMX_NPEI_WIN_RD_ADDR \
+ (0x0000000000000210ull)
+#define CVMX_NPEI_WIN_RD_DATA \
+ (0x0000000000000240ull)
+#define CVMX_NPEI_WIN_WR_ADDR \
+ (0x0000000000000200ull)
+#define CVMX_NPEI_WIN_WR_DATA \
+ (0x0000000000000220ull)
+#define CVMX_NPEI_WIN_WR_MASK \
+ (0x0000000000000230ull)
+
+union cvmx_npei_bar1_indexx {
+ uint32_t u32;
+ struct cvmx_npei_bar1_indexx_s {
+ uint32_t reserved_18_31:14;
+ uint32_t addr_idx:14;
+ uint32_t ca:1;
+ uint32_t end_swp:2;
+ uint32_t addr_v:1;
+ } s;
+ struct cvmx_npei_bar1_indexx_s cn52xx;
+ struct cvmx_npei_bar1_indexx_s cn52xxp1;
+ struct cvmx_npei_bar1_indexx_s cn56xx;
+ struct cvmx_npei_bar1_indexx_s cn56xxp1;
+};
+
+union cvmx_npei_bist_status {
+ uint64_t u64;
+ struct cvmx_npei_bist_status_s {
+ uint64_t pkt_rdf:1;
+ uint64_t pkt_pmem:1;
+ uint64_t pkt_p1:1;
+ uint64_t reserved_60_60:1;
+ uint64_t pcr_gim:1;
+ uint64_t pkt_pif:1;
+ uint64_t pcsr_int:1;
+ uint64_t pcsr_im:1;
+ uint64_t pcsr_cnt:1;
+ uint64_t pcsr_id:1;
+ uint64_t pcsr_sl:1;
+ uint64_t reserved_50_52:3;
+ uint64_t pkt_ind:1;
+ uint64_t pkt_slm:1;
+ uint64_t reserved_36_47:12;
+ uint64_t d0_pst:1;
+ uint64_t d1_pst:1;
+ uint64_t d2_pst:1;
+ uint64_t d3_pst:1;
+ uint64_t reserved_31_31:1;
+ uint64_t n2p0_c:1;
+ uint64_t n2p0_o:1;
+ uint64_t n2p1_c:1;
+ uint64_t n2p1_o:1;
+ uint64_t cpl_p0:1;
+ uint64_t cpl_p1:1;
+ uint64_t p2n1_po:1;
+ uint64_t p2n1_no:1;
+ uint64_t p2n1_co:1;
+ uint64_t p2n0_po:1;
+ uint64_t p2n0_no:1;
+ uint64_t p2n0_co:1;
+ uint64_t p2n0_c0:1;
+ uint64_t p2n0_c1:1;
+ uint64_t p2n0_n:1;
+ uint64_t p2n0_p0:1;
+ uint64_t p2n0_p1:1;
+ uint64_t p2n1_c0:1;
+ uint64_t p2n1_c1:1;
+ uint64_t p2n1_n:1;
+ uint64_t p2n1_p0:1;
+ uint64_t p2n1_p1:1;
+ uint64_t csm0:1;
+ uint64_t csm1:1;
+ uint64_t dif0:1;
+ uint64_t dif1:1;
+ uint64_t dif2:1;
+ uint64_t dif3:1;
+ uint64_t reserved_2_2:1;
+ uint64_t msi:1;
+ uint64_t ncb_cmd:1;
+ } s;
+ struct cvmx_npei_bist_status_cn52xx {
+ uint64_t pkt_rdf:1;
+ uint64_t pkt_pmem:1;
+ uint64_t pkt_p1:1;
+ uint64_t reserved_60_60:1;
+ uint64_t pcr_gim:1;
+ uint64_t pkt_pif:1;
+ uint64_t pcsr_int:1;
+ uint64_t pcsr_im:1;
+ uint64_t pcsr_cnt:1;
+ uint64_t pcsr_id:1;
+ uint64_t pcsr_sl:1;
+ uint64_t pkt_imem:1;
+ uint64_t pkt_pfm:1;
+ uint64_t pkt_pof:1;
+ uint64_t reserved_48_49:2;
+ uint64_t pkt_pop0:1;
+ uint64_t pkt_pop1:1;
+ uint64_t d0_mem:1;
+ uint64_t d1_mem:1;
+ uint64_t d2_mem:1;
+ uint64_t d3_mem:1;
+ uint64_t d4_mem:1;
+ uint64_t ds_mem:1;
+ uint64_t reserved_36_39:4;
+ uint64_t d0_pst:1;
+ uint64_t d1_pst:1;
+ uint64_t d2_pst:1;
+ uint64_t d3_pst:1;
+ uint64_t d4_pst:1;
+ uint64_t n2p0_c:1;
+ uint64_t n2p0_o:1;
+ uint64_t n2p1_c:1;
+ uint64_t n2p1_o:1;
+ uint64_t cpl_p0:1;
+ uint64_t cpl_p1:1;
+ uint64_t p2n1_po:1;
+ uint64_t p2n1_no:1;
+ uint64_t p2n1_co:1;
+ uint64_t p2n0_po:1;
+ uint64_t p2n0_no:1;
+ uint64_t p2n0_co:1;
+ uint64_t p2n0_c0:1;
+ uint64_t p2n0_c1:1;
+ uint64_t p2n0_n:1;
+ uint64_t p2n0_p0:1;
+ uint64_t p2n0_p1:1;
+ uint64_t p2n1_c0:1;
+ uint64_t p2n1_c1:1;
+ uint64_t p2n1_n:1;
+ uint64_t p2n1_p0:1;
+ uint64_t p2n1_p1:1;
+ uint64_t csm0:1;
+ uint64_t csm1:1;
+ uint64_t dif0:1;
+ uint64_t dif1:1;
+ uint64_t dif2:1;
+ uint64_t dif3:1;
+ uint64_t dif4:1;
+ uint64_t msi:1;
+ uint64_t ncb_cmd:1;
+ } cn52xx;
+ struct cvmx_npei_bist_status_cn52xxp1 {
+ uint64_t reserved_46_63:18;
+ uint64_t d0_mem0:1;
+ uint64_t d1_mem1:1;
+ uint64_t d2_mem2:1;
+ uint64_t d3_mem3:1;
+ uint64_t dr0_mem:1;
+ uint64_t d0_mem:1;
+ uint64_t d1_mem:1;
+ uint64_t d2_mem:1;
+ uint64_t d3_mem:1;
+ uint64_t dr1_mem:1;
+ uint64_t d0_pst:1;
+ uint64_t d1_pst:1;
+ uint64_t d2_pst:1;
+ uint64_t d3_pst:1;
+ uint64_t dr2_mem:1;
+ uint64_t n2p0_c:1;
+ uint64_t n2p0_o:1;
+ uint64_t n2p1_c:1;
+ uint64_t n2p1_o:1;
+ uint64_t cpl_p0:1;
+ uint64_t cpl_p1:1;
+ uint64_t p2n1_po:1;
+ uint64_t p2n1_no:1;
+ uint64_t p2n1_co:1;
+ uint64_t p2n0_po:1;
+ uint64_t p2n0_no:1;
+ uint64_t p2n0_co:1;
+ uint64_t p2n0_c0:1;
+ uint64_t p2n0_c1:1;
+ uint64_t p2n0_n:1;
+ uint64_t p2n0_p0:1;
+ uint64_t p2n0_p1:1;
+ uint64_t p2n1_c0:1;
+ uint64_t p2n1_c1:1;
+ uint64_t p2n1_n:1;
+ uint64_t p2n1_p0:1;
+ uint64_t p2n1_p1:1;
+ uint64_t csm0:1;
+ uint64_t csm1:1;
+ uint64_t dif0:1;
+ uint64_t dif1:1;
+ uint64_t dif2:1;
+ uint64_t dif3:1;
+ uint64_t dr3_mem:1;
+ uint64_t msi:1;
+ uint64_t ncb_cmd:1;
+ } cn52xxp1;
+ struct cvmx_npei_bist_status_cn56xx {
+ uint64_t pkt_rdf:1;
+ uint64_t reserved_60_62:3;
+ uint64_t pcr_gim:1;
+ uint64_t pkt_pif:1;
+ uint64_t pcsr_int:1;
+ uint64_t pcsr_im:1;
+ uint64_t pcsr_cnt:1;
+ uint64_t pcsr_id:1;
+ uint64_t pcsr_sl:1;
+ uint64_t pkt_imem:1;
+ uint64_t pkt_pfm:1;
+ uint64_t pkt_pof:1;
+ uint64_t reserved_48_49:2;
+ uint64_t pkt_pop0:1;
+ uint64_t pkt_pop1:1;
+ uint64_t d0_mem:1;
+ uint64_t d1_mem:1;
+ uint64_t d2_mem:1;
+ uint64_t d3_mem:1;
+ uint64_t d4_mem:1;
+ uint64_t ds_mem:1;
+ uint64_t reserved_36_39:4;
+ uint64_t d0_pst:1;
+ uint64_t d1_pst:1;
+ uint64_t d2_pst:1;
+ uint64_t d3_pst:1;
+ uint64_t d4_pst:1;
+ uint64_t n2p0_c:1;
+ uint64_t n2p0_o:1;
+ uint64_t n2p1_c:1;
+ uint64_t n2p1_o:1;
+ uint64_t cpl_p0:1;
+ uint64_t cpl_p1:1;
+ uint64_t p2n1_po:1;
+ uint64_t p2n1_no:1;
+ uint64_t p2n1_co:1;
+ uint64_t p2n0_po:1;
+ uint64_t p2n0_no:1;
+ uint64_t p2n0_co:1;
+ uint64_t p2n0_c0:1;
+ uint64_t p2n0_c1:1;
+ uint64_t p2n0_n:1;
+ uint64_t p2n0_p0:1;
+ uint64_t p2n0_p1:1;
+ uint64_t p2n1_c0:1;
+ uint64_t p2n1_c1:1;
+ uint64_t p2n1_n:1;
+ uint64_t p2n1_p0:1;
+ uint64_t p2n1_p1:1;
+ uint64_t csm0:1;
+ uint64_t csm1:1;
+ uint64_t dif0:1;
+ uint64_t dif1:1;
+ uint64_t dif2:1;
+ uint64_t dif3:1;
+ uint64_t dif4:1;
+ uint64_t msi:1;
+ uint64_t ncb_cmd:1;
+ } cn56xx;
+ struct cvmx_npei_bist_status_cn56xxp1 {
+ uint64_t reserved_58_63:6;
+ uint64_t pcsr_int:1;
+ uint64_t pcsr_im:1;
+ uint64_t pcsr_cnt:1;
+ uint64_t pcsr_id:1;
+ uint64_t pcsr_sl:1;
+ uint64_t pkt_pout:1;
+ uint64_t pkt_imem:1;
+ uint64_t pkt_cntm:1;
+ uint64_t pkt_ind:1;
+ uint64_t pkt_slm:1;
+ uint64_t pkt_odf:1;
+ uint64_t pkt_oif:1;
+ uint64_t pkt_out:1;
+ uint64_t pkt_i0:1;
+ uint64_t pkt_i1:1;
+ uint64_t pkt_s0:1;
+ uint64_t pkt_s1:1;
+ uint64_t d0_mem:1;
+ uint64_t d1_mem:1;
+ uint64_t d2_mem:1;
+ uint64_t d3_mem:1;
+ uint64_t d4_mem:1;
+ uint64_t d0_pst:1;
+ uint64_t d1_pst:1;
+ uint64_t d2_pst:1;
+ uint64_t d3_pst:1;
+ uint64_t d4_pst:1;
+ uint64_t n2p0_c:1;
+ uint64_t n2p0_o:1;
+ uint64_t n2p1_c:1;
+ uint64_t n2p1_o:1;
+ uint64_t cpl_p0:1;
+ uint64_t cpl_p1:1;
+ uint64_t p2n1_po:1;
+ uint64_t p2n1_no:1;
+ uint64_t p2n1_co:1;
+ uint64_t p2n0_po:1;
+ uint64_t p2n0_no:1;
+ uint64_t p2n0_co:1;
+ uint64_t p2n0_c0:1;
+ uint64_t p2n0_c1:1;
+ uint64_t p2n0_n:1;
+ uint64_t p2n0_p0:1;
+ uint64_t p2n0_p1:1;
+ uint64_t p2n1_c0:1;
+ uint64_t p2n1_c1:1;
+ uint64_t p2n1_n:1;
+ uint64_t p2n1_p0:1;
+ uint64_t p2n1_p1:1;
+ uint64_t csm0:1;
+ uint64_t csm1:1;
+ uint64_t dif0:1;
+ uint64_t dif1:1;
+ uint64_t dif2:1;
+ uint64_t dif3:1;
+ uint64_t dif4:1;
+ uint64_t msi:1;
+ uint64_t ncb_cmd:1;
+ } cn56xxp1;
+};
+
+union cvmx_npei_bist_status2 {
+ uint64_t u64;
+ struct cvmx_npei_bist_status2_s {
+ uint64_t reserved_5_63:59;
+ uint64_t psc_p0:1;
+ uint64_t psc_p1:1;
+ uint64_t pkt_gd:1;
+ uint64_t pkt_gl:1;
+ uint64_t pkt_blk:1;
+ } s;
+ struct cvmx_npei_bist_status2_s cn52xx;
+ struct cvmx_npei_bist_status2_s cn56xx;
+};
+
+union cvmx_npei_ctl_port0 {
+ uint64_t u64;
+ struct cvmx_npei_ctl_port0_s {
+ uint64_t reserved_21_63:43;
+ uint64_t waitl_com:1;
+ uint64_t intd:1;
+ uint64_t intc:1;
+ uint64_t intb:1;
+ uint64_t inta:1;
+ uint64_t intd_map:2;
+ uint64_t intc_map:2;
+ uint64_t intb_map:2;
+ uint64_t inta_map:2;
+ uint64_t ctlp_ro:1;
+ uint64_t reserved_6_6:1;
+ uint64_t ptlp_ro:1;
+ uint64_t bar2_enb:1;
+ uint64_t bar2_esx:2;
+ uint64_t bar2_cax:1;
+ uint64_t wait_com:1;
+ } s;
+ struct cvmx_npei_ctl_port0_s cn52xx;
+ struct cvmx_npei_ctl_port0_s cn52xxp1;
+ struct cvmx_npei_ctl_port0_s cn56xx;
+ struct cvmx_npei_ctl_port0_s cn56xxp1;
+};
+
+union cvmx_npei_ctl_port1 {
+ uint64_t u64;
+ struct cvmx_npei_ctl_port1_s {
+ uint64_t reserved_21_63:43;
+ uint64_t waitl_com:1;
+ uint64_t intd:1;
+ uint64_t intc:1;
+ uint64_t intb:1;
+ uint64_t inta:1;
+ uint64_t intd_map:2;
+ uint64_t intc_map:2;
+ uint64_t intb_map:2;
+ uint64_t inta_map:2;
+ uint64_t ctlp_ro:1;
+ uint64_t reserved_6_6:1;
+ uint64_t ptlp_ro:1;
+ uint64_t bar2_enb:1;
+ uint64_t bar2_esx:2;
+ uint64_t bar2_cax:1;
+ uint64_t wait_com:1;
+ } s;
+ struct cvmx_npei_ctl_port1_s cn52xx;
+ struct cvmx_npei_ctl_port1_s cn52xxp1;
+ struct cvmx_npei_ctl_port1_s cn56xx;
+ struct cvmx_npei_ctl_port1_s cn56xxp1;
+};
+
+union cvmx_npei_ctl_status {
+ uint64_t u64;
+ struct cvmx_npei_ctl_status_s {
+ uint64_t reserved_44_63:20;
+ uint64_t p1_ntags:6;
+ uint64_t p0_ntags:6;
+ uint64_t cfg_rtry:16;
+ uint64_t ring_en:1;
+ uint64_t lnk_rst:1;
+ uint64_t arb:1;
+ uint64_t pkt_bp:4;
+ uint64_t host_mode:1;
+ uint64_t chip_rev:8;
+ } s;
+ struct cvmx_npei_ctl_status_s cn52xx;
+ struct cvmx_npei_ctl_status_cn52xxp1 {
+ uint64_t reserved_44_63:20;
+ uint64_t p1_ntags:6;
+ uint64_t p0_ntags:6;
+ uint64_t cfg_rtry:16;
+ uint64_t reserved_15_15:1;
+ uint64_t lnk_rst:1;
+ uint64_t arb:1;
+ uint64_t reserved_9_12:4;
+ uint64_t host_mode:1;
+ uint64_t chip_rev:8;
+ } cn52xxp1;
+ struct cvmx_npei_ctl_status_s cn56xx;
+ struct cvmx_npei_ctl_status_cn56xxp1 {
+ uint64_t reserved_16_63:48;
+ uint64_t ring_en:1;
+ uint64_t lnk_rst:1;
+ uint64_t arb:1;
+ uint64_t pkt_bp:4;
+ uint64_t host_mode:1;
+ uint64_t chip_rev:8;
+ } cn56xxp1;
+};
+
+union cvmx_npei_ctl_status2 {
+ uint64_t u64;
+ struct cvmx_npei_ctl_status2_s {
+ uint64_t reserved_16_63:48;
+ uint64_t mps:1;
+ uint64_t mrrs:3;
+ uint64_t c1_w_flt:1;
+ uint64_t c0_w_flt:1;
+ uint64_t c1_b1_s:3;
+ uint64_t c0_b1_s:3;
+ uint64_t c1_wi_d:1;
+ uint64_t c1_b0_d:1;
+ uint64_t c0_wi_d:1;
+ uint64_t c0_b0_d:1;
+ } s;
+ struct cvmx_npei_ctl_status2_s cn52xx;
+ struct cvmx_npei_ctl_status2_s cn52xxp1;
+ struct cvmx_npei_ctl_status2_s cn56xx;
+ struct cvmx_npei_ctl_status2_s cn56xxp1;
+};
+
+union cvmx_npei_data_out_cnt {
+ uint64_t u64;
+ struct cvmx_npei_data_out_cnt_s {
+ uint64_t reserved_44_63:20;
+ uint64_t p1_ucnt:16;
+ uint64_t p1_fcnt:6;
+ uint64_t p0_ucnt:16;
+ uint64_t p0_fcnt:6;
+ } s;
+ struct cvmx_npei_data_out_cnt_s cn52xx;
+ struct cvmx_npei_data_out_cnt_s cn52xxp1;
+ struct cvmx_npei_data_out_cnt_s cn56xx;
+ struct cvmx_npei_data_out_cnt_s cn56xxp1;
+};
+
+union cvmx_npei_dbg_data {
+ uint64_t u64;
+ struct cvmx_npei_dbg_data_s {
+ uint64_t reserved_28_63:36;
+ uint64_t qlm0_rev_lanes:1;
+ uint64_t reserved_25_26:2;
+ uint64_t qlm1_spd:2;
+ uint64_t c_mul:5;
+ uint64_t dsel_ext:1;
+ uint64_t data:17;
+ } s;
+ struct cvmx_npei_dbg_data_cn52xx {
+ uint64_t reserved_29_63:35;
+ uint64_t qlm0_link_width:1;
+ uint64_t qlm0_rev_lanes:1;
+ uint64_t qlm1_mode:2;
+ uint64_t qlm1_spd:2;
+ uint64_t c_mul:5;
+ uint64_t dsel_ext:1;
+ uint64_t data:17;
+ } cn52xx;
+ struct cvmx_npei_dbg_data_cn52xx cn52xxp1;
+ struct cvmx_npei_dbg_data_cn56xx {
+ uint64_t reserved_29_63:35;
+ uint64_t qlm2_rev_lanes:1;
+ uint64_t qlm0_rev_lanes:1;
+ uint64_t qlm3_spd:2;
+ uint64_t qlm1_spd:2;
+ uint64_t c_mul:5;
+ uint64_t dsel_ext:1;
+ uint64_t data:17;
+ } cn56xx;
+ struct cvmx_npei_dbg_data_cn56xx cn56xxp1;
+};
+
+union cvmx_npei_dbg_select {
+ uint64_t u64;
+ struct cvmx_npei_dbg_select_s {
+ uint64_t reserved_16_63:48;
+ uint64_t dbg_sel:16;
+ } s;
+ struct cvmx_npei_dbg_select_s cn52xx;
+ struct cvmx_npei_dbg_select_s cn52xxp1;
+ struct cvmx_npei_dbg_select_s cn56xx;
+ struct cvmx_npei_dbg_select_s cn56xxp1;
+};
+
+union cvmx_npei_dmax_counts {
+ uint64_t u64;
+ struct cvmx_npei_dmax_counts_s {
+ uint64_t reserved_39_63:25;
+ uint64_t fcnt:7;
+ uint64_t dbell:32;
+ } s;
+ struct cvmx_npei_dmax_counts_s cn52xx;
+ struct cvmx_npei_dmax_counts_s cn52xxp1;
+ struct cvmx_npei_dmax_counts_s cn56xx;
+ struct cvmx_npei_dmax_counts_s cn56xxp1;
+};
+
+union cvmx_npei_dmax_dbell {
+ uint32_t u32;
+ struct cvmx_npei_dmax_dbell_s {
+ uint32_t reserved_16_31:16;
+ uint32_t dbell:16;
+ } s;
+ struct cvmx_npei_dmax_dbell_s cn52xx;
+ struct cvmx_npei_dmax_dbell_s cn52xxp1;
+ struct cvmx_npei_dmax_dbell_s cn56xx;
+ struct cvmx_npei_dmax_dbell_s cn56xxp1;
+};
+
+union cvmx_npei_dmax_ibuff_saddr {
+ uint64_t u64;
+ struct cvmx_npei_dmax_ibuff_saddr_s {
+ uint64_t reserved_37_63:27;
+ uint64_t idle:1;
+ uint64_t saddr:29;
+ uint64_t reserved_0_6:7;
+ } s;
+ struct cvmx_npei_dmax_ibuff_saddr_cn52xx {
+ uint64_t reserved_36_63:28;
+ uint64_t saddr:29;
+ uint64_t reserved_0_6:7;
+ } cn52xx;
+ struct cvmx_npei_dmax_ibuff_saddr_cn52xx cn52xxp1;
+ struct cvmx_npei_dmax_ibuff_saddr_s cn56xx;
+ struct cvmx_npei_dmax_ibuff_saddr_cn52xx cn56xxp1;
+};
+
+union cvmx_npei_dmax_naddr {
+ uint64_t u64;
+ struct cvmx_npei_dmax_naddr_s {
+ uint64_t reserved_36_63:28;
+ uint64_t addr:36;
+ } s;
+ struct cvmx_npei_dmax_naddr_s cn52xx;
+ struct cvmx_npei_dmax_naddr_s cn52xxp1;
+ struct cvmx_npei_dmax_naddr_s cn56xx;
+ struct cvmx_npei_dmax_naddr_s cn56xxp1;
+};
+
+union cvmx_npei_dma0_int_level {
+ uint64_t u64;
+ struct cvmx_npei_dma0_int_level_s {
+ uint64_t time:32;
+ uint64_t cnt:32;
+ } s;
+ struct cvmx_npei_dma0_int_level_s cn52xx;
+ struct cvmx_npei_dma0_int_level_s cn52xxp1;
+ struct cvmx_npei_dma0_int_level_s cn56xx;
+ struct cvmx_npei_dma0_int_level_s cn56xxp1;
+};
+
+union cvmx_npei_dma1_int_level {
+ uint64_t u64;
+ struct cvmx_npei_dma1_int_level_s {
+ uint64_t time:32;
+ uint64_t cnt:32;
+ } s;
+ struct cvmx_npei_dma1_int_level_s cn52xx;
+ struct cvmx_npei_dma1_int_level_s cn52xxp1;
+ struct cvmx_npei_dma1_int_level_s cn56xx;
+ struct cvmx_npei_dma1_int_level_s cn56xxp1;
+};
+
+union cvmx_npei_dma_cnts {
+ uint64_t u64;
+ struct cvmx_npei_dma_cnts_s {
+ uint64_t dma1:32;
+ uint64_t dma0:32;
+ } s;
+ struct cvmx_npei_dma_cnts_s cn52xx;
+ struct cvmx_npei_dma_cnts_s cn52xxp1;
+ struct cvmx_npei_dma_cnts_s cn56xx;
+ struct cvmx_npei_dma_cnts_s cn56xxp1;
+};
+
+union cvmx_npei_dma_control {
+ uint64_t u64;
+ struct cvmx_npei_dma_control_s {
+ uint64_t reserved_39_63:25;
+ uint64_t dma4_enb:1;
+ uint64_t dma3_enb:1;
+ uint64_t dma2_enb:1;
+ uint64_t dma1_enb:1;
+ uint64_t dma0_enb:1;
+ uint64_t b0_lend:1;
+ uint64_t dwb_denb:1;
+ uint64_t dwb_ichk:9;
+ uint64_t fpa_que:3;
+ uint64_t o_add1:1;
+ uint64_t o_ro:1;
+ uint64_t o_ns:1;
+ uint64_t o_es:2;
+ uint64_t o_mode:1;
+ uint64_t csize:14;
+ } s;
+ struct cvmx_npei_dma_control_s cn52xx;
+ struct cvmx_npei_dma_control_cn52xxp1 {
+ uint64_t reserved_38_63:26;
+ uint64_t dma3_enb:1;
+ uint64_t dma2_enb:1;
+ uint64_t dma1_enb:1;
+ uint64_t dma0_enb:1;
+ uint64_t b0_lend:1;
+ uint64_t dwb_denb:1;
+ uint64_t dwb_ichk:9;
+ uint64_t fpa_que:3;
+ uint64_t o_add1:1;
+ uint64_t o_ro:1;
+ uint64_t o_ns:1;
+ uint64_t o_es:2;
+ uint64_t o_mode:1;
+ uint64_t csize:14;
+ } cn52xxp1;
+ struct cvmx_npei_dma_control_s cn56xx;
+ struct cvmx_npei_dma_control_s cn56xxp1;
+};
+
+union cvmx_npei_int_a_enb {
+ uint64_t u64;
+ struct cvmx_npei_int_a_enb_s {
+ uint64_t reserved_10_63:54;
+ uint64_t pout_err:1;
+ uint64_t pin_bp:1;
+ uint64_t p1_rdlk:1;
+ uint64_t p0_rdlk:1;
+ uint64_t pgl_err:1;
+ uint64_t pdi_err:1;
+ uint64_t pop_err:1;
+ uint64_t pins_err:1;
+ uint64_t dma1_cpl:1;
+ uint64_t dma0_cpl:1;
+ } s;
+ struct cvmx_npei_int_a_enb_cn52xx {
+ uint64_t reserved_8_63:56;
+ uint64_t p1_rdlk:1;
+ uint64_t p0_rdlk:1;
+ uint64_t pgl_err:1;
+ uint64_t pdi_err:1;
+ uint64_t pop_err:1;
+ uint64_t pins_err:1;
+ uint64_t dma1_cpl:1;
+ uint64_t dma0_cpl:1;
+ } cn52xx;
+ struct cvmx_npei_int_a_enb_cn52xxp1 {
+ uint64_t reserved_2_63:62;
+ uint64_t dma1_cpl:1;
+ uint64_t dma0_cpl:1;
+ } cn52xxp1;
+ struct cvmx_npei_int_a_enb_s cn56xx;
+};
+
+union cvmx_npei_int_a_enb2 {
+ uint64_t u64;
+ struct cvmx_npei_int_a_enb2_s {
+ uint64_t reserved_10_63:54;
+ uint64_t pout_err:1;
+ uint64_t pin_bp:1;
+ uint64_t p1_rdlk:1;
+ uint64_t p0_rdlk:1;
+ uint64_t pgl_err:1;
+ uint64_t pdi_err:1;
+ uint64_t pop_err:1;
+ uint64_t pins_err:1;
+ uint64_t dma1_cpl:1;
+ uint64_t dma0_cpl:1;
+ } s;
+ struct cvmx_npei_int_a_enb2_cn52xx {
+ uint64_t reserved_8_63:56;
+ uint64_t p1_rdlk:1;
+ uint64_t p0_rdlk:1;
+ uint64_t pgl_err:1;
+ uint64_t pdi_err:1;
+ uint64_t pop_err:1;
+ uint64_t pins_err:1;
+ uint64_t reserved_0_1:2;
+ } cn52xx;
+ struct cvmx_npei_int_a_enb2_cn52xxp1 {
+ uint64_t reserved_2_63:62;
+ uint64_t dma1_cpl:1;
+ uint64_t dma0_cpl:1;
+ } cn52xxp1;
+ struct cvmx_npei_int_a_enb2_s cn56xx;
+};
+
+union cvmx_npei_int_a_sum {
+ uint64_t u64;
+ struct cvmx_npei_int_a_sum_s {
+ uint64_t reserved_10_63:54;
+ uint64_t pout_err:1;
+ uint64_t pin_bp:1;
+ uint64_t p1_rdlk:1;
+ uint64_t p0_rdlk:1;
+ uint64_t pgl_err:1;
+ uint64_t pdi_err:1;
+ uint64_t pop_err:1;
+ uint64_t pins_err:1;
+ uint64_t dma1_cpl:1;
+ uint64_t dma0_cpl:1;
+ } s;
+ struct cvmx_npei_int_a_sum_cn52xx {
+ uint64_t reserved_8_63:56;
+ uint64_t p1_rdlk:1;
+ uint64_t p0_rdlk:1;
+ uint64_t pgl_err:1;
+ uint64_t pdi_err:1;
+ uint64_t pop_err:1;
+ uint64_t pins_err:1;
+ uint64_t dma1_cpl:1;
+ uint64_t dma0_cpl:1;
+ } cn52xx;
+ struct cvmx_npei_int_a_sum_cn52xxp1 {
+ uint64_t reserved_2_63:62;
+ uint64_t dma1_cpl:1;
+ uint64_t dma0_cpl:1;
+ } cn52xxp1;
+ struct cvmx_npei_int_a_sum_s cn56xx;
+};
+
+union cvmx_npei_int_enb {
+ uint64_t u64;
+ struct cvmx_npei_int_enb_s {
+ uint64_t mio_inta:1;
+ uint64_t reserved_62_62:1;
+ uint64_t int_a:1;
+ uint64_t c1_ldwn:1;
+ uint64_t c0_ldwn:1;
+ uint64_t c1_exc:1;
+ uint64_t c0_exc:1;
+ uint64_t c1_up_wf:1;
+ uint64_t c0_up_wf:1;
+ uint64_t c1_un_wf:1;
+ uint64_t c0_un_wf:1;
+ uint64_t c1_un_bx:1;
+ uint64_t c1_un_wi:1;
+ uint64_t c1_un_b2:1;
+ uint64_t c1_un_b1:1;
+ uint64_t c1_un_b0:1;
+ uint64_t c1_up_bx:1;
+ uint64_t c1_up_wi:1;
+ uint64_t c1_up_b2:1;
+ uint64_t c1_up_b1:1;
+ uint64_t c1_up_b0:1;
+ uint64_t c0_un_bx:1;
+ uint64_t c0_un_wi:1;
+ uint64_t c0_un_b2:1;
+ uint64_t c0_un_b1:1;
+ uint64_t c0_un_b0:1;
+ uint64_t c0_up_bx:1;
+ uint64_t c0_up_wi:1;
+ uint64_t c0_up_b2:1;
+ uint64_t c0_up_b1:1;
+ uint64_t c0_up_b0:1;
+ uint64_t c1_hpint:1;
+ uint64_t c1_pmei:1;
+ uint64_t c1_wake:1;
+ uint64_t crs1_dr:1;
+ uint64_t c1_se:1;
+ uint64_t crs1_er:1;
+ uint64_t c1_aeri:1;
+ uint64_t c0_hpint:1;
+ uint64_t c0_pmei:1;
+ uint64_t c0_wake:1;
+ uint64_t crs0_dr:1;
+ uint64_t c0_se:1;
+ uint64_t crs0_er:1;
+ uint64_t c0_aeri:1;
+ uint64_t ptime:1;
+ uint64_t pcnt:1;
+ uint64_t pidbof:1;
+ uint64_t psldbof:1;
+ uint64_t dtime1:1;
+ uint64_t dtime0:1;
+ uint64_t dcnt1:1;
+ uint64_t dcnt0:1;
+ uint64_t dma1fi:1;
+ uint64_t dma0fi:1;
+ uint64_t dma4dbo:1;
+ uint64_t dma3dbo:1;
+ uint64_t dma2dbo:1;
+ uint64_t dma1dbo:1;
+ uint64_t dma0dbo:1;
+ uint64_t iob2big:1;
+ uint64_t bar0_to:1;
+ uint64_t rml_wto:1;
+ uint64_t rml_rto:1;
+ } s;
+ struct cvmx_npei_int_enb_s cn52xx;
+ struct cvmx_npei_int_enb_cn52xxp1 {
+ uint64_t mio_inta:1;
+ uint64_t reserved_62_62:1;
+ uint64_t int_a:1;
+ uint64_t c1_ldwn:1;
+ uint64_t c0_ldwn:1;
+ uint64_t c1_exc:1;
+ uint64_t c0_exc:1;
+ uint64_t c1_up_wf:1;
+ uint64_t c0_up_wf:1;
+ uint64_t c1_un_wf:1;
+ uint64_t c0_un_wf:1;
+ uint64_t c1_un_bx:1;
+ uint64_t c1_un_wi:1;
+ uint64_t c1_un_b2:1;
+ uint64_t c1_un_b1:1;
+ uint64_t c1_un_b0:1;
+ uint64_t c1_up_bx:1;
+ uint64_t c1_up_wi:1;
+ uint64_t c1_up_b2:1;
+ uint64_t c1_up_b1:1;
+ uint64_t c1_up_b0:1;
+ uint64_t c0_un_bx:1;
+ uint64_t c0_un_wi:1;
+ uint64_t c0_un_b2:1;
+ uint64_t c0_un_b1:1;
+ uint64_t c0_un_b0:1;
+ uint64_t c0_up_bx:1;
+ uint64_t c0_up_wi:1;
+ uint64_t c0_up_b2:1;
+ uint64_t c0_up_b1:1;
+ uint64_t c0_up_b0:1;
+ uint64_t c1_hpint:1;
+ uint64_t c1_pmei:1;
+ uint64_t c1_wake:1;
+ uint64_t crs1_dr:1;
+ uint64_t c1_se:1;
+ uint64_t crs1_er:1;
+ uint64_t c1_aeri:1;
+ uint64_t c0_hpint:1;
+ uint64_t c0_pmei:1;
+ uint64_t c0_wake:1;
+ uint64_t crs0_dr:1;
+ uint64_t c0_se:1;
+ uint64_t crs0_er:1;
+ uint64_t c0_aeri:1;
+ uint64_t ptime:1;
+ uint64_t pcnt:1;
+ uint64_t pidbof:1;
+ uint64_t psldbof:1;
+ uint64_t dtime1:1;
+ uint64_t dtime0:1;
+ uint64_t dcnt1:1;
+ uint64_t dcnt0:1;
+ uint64_t dma1fi:1;
+ uint64_t dma0fi:1;
+ uint64_t reserved_8_8:1;
+ uint64_t dma3dbo:1;
+ uint64_t dma2dbo:1;
+ uint64_t dma1dbo:1;
+ uint64_t dma0dbo:1;
+ uint64_t iob2big:1;
+ uint64_t bar0_to:1;
+ uint64_t rml_wto:1;
+ uint64_t rml_rto:1;
+ } cn52xxp1;
+ struct cvmx_npei_int_enb_s cn56xx;
+ struct cvmx_npei_int_enb_cn56xxp1 {
+ uint64_t mio_inta:1;
+ uint64_t reserved_61_62:2;
+ uint64_t c1_ldwn:1;
+ uint64_t c0_ldwn:1;
+ uint64_t c1_exc:1;
+ uint64_t c0_exc:1;
+ uint64_t c1_up_wf:1;
+ uint64_t c0_up_wf:1;
+ uint64_t c1_un_wf:1;
+ uint64_t c0_un_wf:1;
+ uint64_t c1_un_bx:1;
+ uint64_t c1_un_wi:1;
+ uint64_t c1_un_b2:1;
+ uint64_t c1_un_b1:1;
+ uint64_t c1_un_b0:1;
+ uint64_t c1_up_bx:1;
+ uint64_t c1_up_wi:1;
+ uint64_t c1_up_b2:1;
+ uint64_t c1_up_b1:1;
+ uint64_t c1_up_b0:1;
+ uint64_t c0_un_bx:1;
+ uint64_t c0_un_wi:1;
+ uint64_t c0_un_b2:1;
+ uint64_t c0_un_b1:1;
+ uint64_t c0_un_b0:1;
+ uint64_t c0_up_bx:1;
+ uint64_t c0_up_wi:1;
+ uint64_t c0_up_b2:1;
+ uint64_t c0_up_b1:1;
+ uint64_t c0_up_b0:1;
+ uint64_t c1_hpint:1;
+ uint64_t c1_pmei:1;
+ uint64_t c1_wake:1;
+ uint64_t reserved_29_29:1;
+ uint64_t c1_se:1;
+ uint64_t reserved_27_27:1;
+ uint64_t c1_aeri:1;
+ uint64_t c0_hpint:1;
+ uint64_t c0_pmei:1;
+ uint64_t c0_wake:1;
+ uint64_t reserved_22_22:1;
+ uint64_t c0_se:1;
+ uint64_t reserved_20_20:1;
+ uint64_t c0_aeri:1;
+ uint64_t ptime:1;
+ uint64_t pcnt:1;
+ uint64_t pidbof:1;
+ uint64_t psldbof:1;
+ uint64_t dtime1:1;
+ uint64_t dtime0:1;
+ uint64_t dcnt1:1;
+ uint64_t dcnt0:1;
+ uint64_t dma1fi:1;
+ uint64_t dma0fi:1;
+ uint64_t dma4dbo:1;
+ uint64_t dma3dbo:1;
+ uint64_t dma2dbo:1;
+ uint64_t dma1dbo:1;
+ uint64_t dma0dbo:1;
+ uint64_t iob2big:1;
+ uint64_t bar0_to:1;
+ uint64_t rml_wto:1;
+ uint64_t rml_rto:1;
+ } cn56xxp1;
+};
+
+union cvmx_npei_int_enb2 {
+ uint64_t u64;
+ struct cvmx_npei_int_enb2_s {
+ uint64_t reserved_62_63:2;
+ uint64_t int_a:1;
+ uint64_t c1_ldwn:1;
+ uint64_t c0_ldwn:1;
+ uint64_t c1_exc:1;
+ uint64_t c0_exc:1;
+ uint64_t c1_up_wf:1;
+ uint64_t c0_up_wf:1;
+ uint64_t c1_un_wf:1;
+ uint64_t c0_un_wf:1;
+ uint64_t c1_un_bx:1;
+ uint64_t c1_un_wi:1;
+ uint64_t c1_un_b2:1;
+ uint64_t c1_un_b1:1;
+ uint64_t c1_un_b0:1;
+ uint64_t c1_up_bx:1;
+ uint64_t c1_up_wi:1;
+ uint64_t c1_up_b2:1;
+ uint64_t c1_up_b1:1;
+ uint64_t c1_up_b0:1;
+ uint64_t c0_un_bx:1;
+ uint64_t c0_un_wi:1;
+ uint64_t c0_un_b2:1;
+ uint64_t c0_un_b1:1;
+ uint64_t c0_un_b0:1;
+ uint64_t c0_up_bx:1;
+ uint64_t c0_up_wi:1;
+ uint64_t c0_up_b2:1;
+ uint64_t c0_up_b1:1;
+ uint64_t c0_up_b0:1;
+ uint64_t c1_hpint:1;
+ uint64_t c1_pmei:1;
+ uint64_t c1_wake:1;
+ uint64_t crs1_dr:1;
+ uint64_t c1_se:1;
+ uint64_t crs1_er:1;
+ uint64_t c1_aeri:1;
+ uint64_t c0_hpint:1;
+ uint64_t c0_pmei:1;
+ uint64_t c0_wake:1;
+ uint64_t crs0_dr:1;
+ uint64_t c0_se:1;
+ uint64_t crs0_er:1;
+ uint64_t c0_aeri:1;
+ uint64_t ptime:1;
+ uint64_t pcnt:1;
+ uint64_t pidbof:1;
+ uint64_t psldbof:1;
+ uint64_t dtime1:1;
+ uint64_t dtime0:1;
+ uint64_t dcnt1:1;
+ uint64_t dcnt0:1;
+ uint64_t dma1fi:1;
+ uint64_t dma0fi:1;
+ uint64_t dma4dbo:1;
+ uint64_t dma3dbo:1;
+ uint64_t dma2dbo:1;
+ uint64_t dma1dbo:1;
+ uint64_t dma0dbo:1;
+ uint64_t iob2big:1;
+ uint64_t bar0_to:1;
+ uint64_t rml_wto:1;
+ uint64_t rml_rto:1;
+ } s;
+ struct cvmx_npei_int_enb2_s cn52xx;
+ struct cvmx_npei_int_enb2_cn52xxp1 {
+ uint64_t reserved_62_63:2;
+ uint64_t int_a:1;
+ uint64_t c1_ldwn:1;
+ uint64_t c0_ldwn:1;
+ uint64_t c1_exc:1;
+ uint64_t c0_exc:1;
+ uint64_t c1_up_wf:1;
+ uint64_t c0_up_wf:1;
+ uint64_t c1_un_wf:1;
+ uint64_t c0_un_wf:1;
+ uint64_t c1_un_bx:1;
+ uint64_t c1_un_wi:1;
+ uint64_t c1_un_b2:1;
+ uint64_t c1_un_b1:1;
+ uint64_t c1_un_b0:1;
+ uint64_t c1_up_bx:1;
+ uint64_t c1_up_wi:1;
+ uint64_t c1_up_b2:1;
+ uint64_t c1_up_b1:1;
+ uint64_t c1_up_b0:1;
+ uint64_t c0_un_bx:1;
+ uint64_t c0_un_wi:1;
+ uint64_t c0_un_b2:1;
+ uint64_t c0_un_b1:1;
+ uint64_t c0_un_b0:1;
+ uint64_t c0_up_bx:1;
+ uint64_t c0_up_wi:1;
+ uint64_t c0_up_b2:1;
+ uint64_t c0_up_b1:1;
+ uint64_t c0_up_b0:1;
+ uint64_t c1_hpint:1;
+ uint64_t c1_pmei:1;
+ uint64_t c1_wake:1;
+ uint64_t crs1_dr:1;
+ uint64_t c1_se:1;
+ uint64_t crs1_er:1;
+ uint64_t c1_aeri:1;
+ uint64_t c0_hpint:1;
+ uint64_t c0_pmei:1;
+ uint64_t c0_wake:1;
+ uint64_t crs0_dr:1;
+ uint64_t c0_se:1;
+ uint64_t crs0_er:1;
+ uint64_t c0_aeri:1;
+ uint64_t ptime:1;
+ uint64_t pcnt:1;
+ uint64_t pidbof:1;
+ uint64_t psldbof:1;
+ uint64_t dtime1:1;
+ uint64_t dtime0:1;
+ uint64_t dcnt1:1;
+ uint64_t dcnt0:1;
+ uint64_t dma1fi:1;
+ uint64_t dma0fi:1;
+ uint64_t reserved_8_8:1;
+ uint64_t dma3dbo:1;
+ uint64_t dma2dbo:1;
+ uint64_t dma1dbo:1;
+ uint64_t dma0dbo:1;
+ uint64_t iob2big:1;
+ uint64_t bar0_to:1;
+ uint64_t rml_wto:1;
+ uint64_t rml_rto:1;
+ } cn52xxp1;
+ struct cvmx_npei_int_enb2_s cn56xx;
+ struct cvmx_npei_int_enb2_cn56xxp1 {
+ uint64_t reserved_61_63:3;
+ uint64_t c1_ldwn:1;
+ uint64_t c0_ldwn:1;
+ uint64_t c1_exc:1;
+ uint64_t c0_exc:1;
+ uint64_t c1_up_wf:1;
+ uint64_t c0_up_wf:1;
+ uint64_t c1_un_wf:1;
+ uint64_t c0_un_wf:1;
+ uint64_t c1_un_bx:1;
+ uint64_t c1_un_wi:1;
+ uint64_t c1_un_b2:1;
+ uint64_t c1_un_b1:1;
+ uint64_t c1_un_b0:1;
+ uint64_t c1_up_bx:1;
+ uint64_t c1_up_wi:1;
+ uint64_t c1_up_b2:1;
+ uint64_t c1_up_b1:1;
+ uint64_t c1_up_b0:1;
+ uint64_t c0_un_bx:1;
+ uint64_t c0_un_wi:1;
+ uint64_t c0_un_b2:1;
+ uint64_t c0_un_b1:1;
+ uint64_t c0_un_b0:1;
+ uint64_t c0_up_bx:1;
+ uint64_t c0_up_wi:1;
+ uint64_t c0_up_b2:1;
+ uint64_t c0_up_b1:1;
+ uint64_t c0_up_b0:1;
+ uint64_t c1_hpint:1;
+ uint64_t c1_pmei:1;
+ uint64_t c1_wake:1;
+ uint64_t reserved_29_29:1;
+ uint64_t c1_se:1;
+ uint64_t reserved_27_27:1;
+ uint64_t c1_aeri:1;
+ uint64_t c0_hpint:1;
+ uint64_t c0_pmei:1;
+ uint64_t c0_wake:1;
+ uint64_t reserved_22_22:1;
+ uint64_t c0_se:1;
+ uint64_t reserved_20_20:1;
+ uint64_t c0_aeri:1;
+ uint64_t ptime:1;
+ uint64_t pcnt:1;
+ uint64_t pidbof:1;
+ uint64_t psldbof:1;
+ uint64_t dtime1:1;
+ uint64_t dtime0:1;
+ uint64_t dcnt1:1;
+ uint64_t dcnt0:1;
+ uint64_t dma1fi:1;
+ uint64_t dma0fi:1;
+ uint64_t dma4dbo:1;
+ uint64_t dma3dbo:1;
+ uint64_t dma2dbo:1;
+ uint64_t dma1dbo:1;
+ uint64_t dma0dbo:1;
+ uint64_t iob2big:1;
+ uint64_t bar0_to:1;
+ uint64_t rml_wto:1;
+ uint64_t rml_rto:1;
+ } cn56xxp1;
+};
+
+union cvmx_npei_int_info {
+ uint64_t u64;
+ struct cvmx_npei_int_info_s {
+ uint64_t reserved_12_63:52;
+ uint64_t pidbof:6;
+ uint64_t psldbof:6;
+ } s;
+ struct cvmx_npei_int_info_s cn52xx;
+ struct cvmx_npei_int_info_s cn56xx;
+ struct cvmx_npei_int_info_s cn56xxp1;
+};
+
+union cvmx_npei_int_sum {
+ uint64_t u64;
+ struct cvmx_npei_int_sum_s {
+ uint64_t mio_inta:1;
+ uint64_t reserved_62_62:1;
+ uint64_t int_a:1;
+ uint64_t c1_ldwn:1;
+ uint64_t c0_ldwn:1;
+ uint64_t c1_exc:1;
+ uint64_t c0_exc:1;
+ uint64_t c1_up_wf:1;
+ uint64_t c0_up_wf:1;
+ uint64_t c1_un_wf:1;
+ uint64_t c0_un_wf:1;
+ uint64_t c1_un_bx:1;
+ uint64_t c1_un_wi:1;
+ uint64_t c1_un_b2:1;
+ uint64_t c1_un_b1:1;
+ uint64_t c1_un_b0:1;
+ uint64_t c1_up_bx:1;
+ uint64_t c1_up_wi:1;
+ uint64_t c1_up_b2:1;
+ uint64_t c1_up_b1:1;
+ uint64_t c1_up_b0:1;
+ uint64_t c0_un_bx:1;
+ uint64_t c0_un_wi:1;
+ uint64_t c0_un_b2:1;
+ uint64_t c0_un_b1:1;
+ uint64_t c0_un_b0:1;
+ uint64_t c0_up_bx:1;
+ uint64_t c0_up_wi:1;
+ uint64_t c0_up_b2:1;
+ uint64_t c0_up_b1:1;
+ uint64_t c0_up_b0:1;
+ uint64_t c1_hpint:1;
+ uint64_t c1_pmei:1;
+ uint64_t c1_wake:1;
+ uint64_t crs1_dr:1;
+ uint64_t c1_se:1;
+ uint64_t crs1_er:1;
+ uint64_t c1_aeri:1;
+ uint64_t c0_hpint:1;
+ uint64_t c0_pmei:1;
+ uint64_t c0_wake:1;
+ uint64_t crs0_dr:1;
+ uint64_t c0_se:1;
+ uint64_t crs0_er:1;
+ uint64_t c0_aeri:1;
+ uint64_t ptime:1;
+ uint64_t pcnt:1;
+ uint64_t pidbof:1;
+ uint64_t psldbof:1;
+ uint64_t dtime1:1;
+ uint64_t dtime0:1;
+ uint64_t dcnt1:1;
+ uint64_t dcnt0:1;
+ uint64_t dma1fi:1;
+ uint64_t dma0fi:1;
+ uint64_t dma4dbo:1;
+ uint64_t dma3dbo:1;
+ uint64_t dma2dbo:1;
+ uint64_t dma1dbo:1;
+ uint64_t dma0dbo:1;
+ uint64_t iob2big:1;
+ uint64_t bar0_to:1;
+ uint64_t rml_wto:1;
+ uint64_t rml_rto:1;
+ } s;
+ struct cvmx_npei_int_sum_s cn52xx;
+ struct cvmx_npei_int_sum_cn52xxp1 {
+ uint64_t mio_inta:1;
+ uint64_t reserved_62_62:1;
+ uint64_t int_a:1;
+ uint64_t c1_ldwn:1;
+ uint64_t c0_ldwn:1;
+ uint64_t c1_exc:1;
+ uint64_t c0_exc:1;
+ uint64_t c1_up_wf:1;
+ uint64_t c0_up_wf:1;
+ uint64_t c1_un_wf:1;
+ uint64_t c0_un_wf:1;
+ uint64_t c1_un_bx:1;
+ uint64_t c1_un_wi:1;
+ uint64_t c1_un_b2:1;
+ uint64_t c1_un_b1:1;
+ uint64_t c1_un_b0:1;
+ uint64_t c1_up_bx:1;
+ uint64_t c1_up_wi:1;
+ uint64_t c1_up_b2:1;
+ uint64_t c1_up_b1:1;
+ uint64_t c1_up_b0:1;
+ uint64_t c0_un_bx:1;
+ uint64_t c0_un_wi:1;
+ uint64_t c0_un_b2:1;
+ uint64_t c0_un_b1:1;
+ uint64_t c0_un_b0:1;
+ uint64_t c0_up_bx:1;
+ uint64_t c0_up_wi:1;
+ uint64_t c0_up_b2:1;
+ uint64_t c0_up_b1:1;
+ uint64_t c0_up_b0:1;
+ uint64_t c1_hpint:1;
+ uint64_t c1_pmei:1;
+ uint64_t c1_wake:1;
+ uint64_t crs1_dr:1;
+ uint64_t c1_se:1;
+ uint64_t crs1_er:1;
+ uint64_t c1_aeri:1;
+ uint64_t c0_hpint:1;
+ uint64_t c0_pmei:1;
+ uint64_t c0_wake:1;
+ uint64_t crs0_dr:1;
+ uint64_t c0_se:1;
+ uint64_t crs0_er:1;
+ uint64_t c0_aeri:1;
+ uint64_t reserved_15_18:4;
+ uint64_t dtime1:1;
+ uint64_t dtime0:1;
+ uint64_t dcnt1:1;
+ uint64_t dcnt0:1;
+ uint64_t dma1fi:1;
+ uint64_t dma0fi:1;
+ uint64_t reserved_8_8:1;
+ uint64_t dma3dbo:1;
+ uint64_t dma2dbo:1;
+ uint64_t dma1dbo:1;
+ uint64_t dma0dbo:1;
+ uint64_t iob2big:1;
+ uint64_t bar0_to:1;
+ uint64_t rml_wto:1;
+ uint64_t rml_rto:1;
+ } cn52xxp1;
+ struct cvmx_npei_int_sum_s cn56xx;
+ struct cvmx_npei_int_sum_cn56xxp1 {
+ uint64_t mio_inta:1;
+ uint64_t reserved_61_62:2;
+ uint64_t c1_ldwn:1;
+ uint64_t c0_ldwn:1;
+ uint64_t c1_exc:1;
+ uint64_t c0_exc:1;
+ uint64_t c1_up_wf:1;
+ uint64_t c0_up_wf:1;
+ uint64_t c1_un_wf:1;
+ uint64_t c0_un_wf:1;
+ uint64_t c1_un_bx:1;
+ uint64_t c1_un_wi:1;
+ uint64_t c1_un_b2:1;
+ uint64_t c1_un_b1:1;
+ uint64_t c1_un_b0:1;
+ uint64_t c1_up_bx:1;
+ uint64_t c1_up_wi:1;
+ uint64_t c1_up_b2:1;
+ uint64_t c1_up_b1:1;
+ uint64_t c1_up_b0:1;
+ uint64_t c0_un_bx:1;
+ uint64_t c0_un_wi:1;
+ uint64_t c0_un_b2:1;
+ uint64_t c0_un_b1:1;
+ uint64_t c0_un_b0:1;
+ uint64_t c0_up_bx:1;
+ uint64_t c0_up_wi:1;
+ uint64_t c0_up_b2:1;
+ uint64_t c0_up_b1:1;
+ uint64_t c0_up_b0:1;
+ uint64_t c1_hpint:1;
+ uint64_t c1_pmei:1;
+ uint64_t c1_wake:1;
+ uint64_t reserved_29_29:1;
+ uint64_t c1_se:1;
+ uint64_t reserved_27_27:1;
+ uint64_t c1_aeri:1;
+ uint64_t c0_hpint:1;
+ uint64_t c0_pmei:1;
+ uint64_t c0_wake:1;
+ uint64_t reserved_22_22:1;
+ uint64_t c0_se:1;
+ uint64_t reserved_20_20:1;
+ uint64_t c0_aeri:1;
+ uint64_t ptime:1;
+ uint64_t pcnt:1;
+ uint64_t pidbof:1;
+ uint64_t psldbof:1;
+ uint64_t dtime1:1;
+ uint64_t dtime0:1;
+ uint64_t dcnt1:1;
+ uint64_t dcnt0:1;
+ uint64_t dma1fi:1;
+ uint64_t dma0fi:1;
+ uint64_t dma4dbo:1;
+ uint64_t dma3dbo:1;
+ uint64_t dma2dbo:1;
+ uint64_t dma1dbo:1;
+ uint64_t dma0dbo:1;
+ uint64_t iob2big:1;
+ uint64_t bar0_to:1;
+ uint64_t rml_wto:1;
+ uint64_t rml_rto:1;
+ } cn56xxp1;
+};
+
+union cvmx_npei_int_sum2 {
+ uint64_t u64;
+ struct cvmx_npei_int_sum2_s {
+ uint64_t mio_inta:1;
+ uint64_t reserved_62_62:1;
+ uint64_t int_a:1;
+ uint64_t c1_ldwn:1;
+ uint64_t c0_ldwn:1;
+ uint64_t c1_exc:1;
+ uint64_t c0_exc:1;
+ uint64_t c1_up_wf:1;
+ uint64_t c0_up_wf:1;
+ uint64_t c1_un_wf:1;
+ uint64_t c0_un_wf:1;
+ uint64_t c1_un_bx:1;
+ uint64_t c1_un_wi:1;
+ uint64_t c1_un_b2:1;
+ uint64_t c1_un_b1:1;
+ uint64_t c1_un_b0:1;
+ uint64_t c1_up_bx:1;
+ uint64_t c1_up_wi:1;
+ uint64_t c1_up_b2:1;
+ uint64_t c1_up_b1:1;
+ uint64_t c1_up_b0:1;
+ uint64_t c0_un_bx:1;
+ uint64_t c0_un_wi:1;
+ uint64_t c0_un_b2:1;
+ uint64_t c0_un_b1:1;
+ uint64_t c0_un_b0:1;
+ uint64_t c0_up_bx:1;
+ uint64_t c0_up_wi:1;
+ uint64_t c0_up_b2:1;
+ uint64_t c0_up_b1:1;
+ uint64_t c0_up_b0:1;
+ uint64_t c1_hpint:1;
+ uint64_t c1_pmei:1;
+ uint64_t c1_wake:1;
+ uint64_t crs1_dr:1;
+ uint64_t c1_se:1;
+ uint64_t crs1_er:1;
+ uint64_t c1_aeri:1;
+ uint64_t c0_hpint:1;
+ uint64_t c0_pmei:1;
+ uint64_t c0_wake:1;
+ uint64_t crs0_dr:1;
+ uint64_t c0_se:1;
+ uint64_t crs0_er:1;
+ uint64_t c0_aeri:1;
+ uint64_t reserved_15_18:4;
+ uint64_t dtime1:1;
+ uint64_t dtime0:1;
+ uint64_t dcnt1:1;
+ uint64_t dcnt0:1;
+ uint64_t dma1fi:1;
+ uint64_t dma0fi:1;
+ uint64_t reserved_8_8:1;
+ uint64_t dma3dbo:1;
+ uint64_t dma2dbo:1;
+ uint64_t dma1dbo:1;
+ uint64_t dma0dbo:1;
+ uint64_t iob2big:1;
+ uint64_t bar0_to:1;
+ uint64_t rml_wto:1;
+ uint64_t rml_rto:1;
+ } s;
+ struct cvmx_npei_int_sum2_s cn52xx;
+ struct cvmx_npei_int_sum2_s cn52xxp1;
+ struct cvmx_npei_int_sum2_s cn56xx;
+};
+
+union cvmx_npei_last_win_rdata0 {
+ uint64_t u64;
+ struct cvmx_npei_last_win_rdata0_s {
+ uint64_t data:64;
+ } s;
+ struct cvmx_npei_last_win_rdata0_s cn52xx;
+ struct cvmx_npei_last_win_rdata0_s cn52xxp1;
+ struct cvmx_npei_last_win_rdata0_s cn56xx;
+ struct cvmx_npei_last_win_rdata0_s cn56xxp1;
+};
+
+union cvmx_npei_last_win_rdata1 {
+ uint64_t u64;
+ struct cvmx_npei_last_win_rdata1_s {
+ uint64_t data:64;
+ } s;
+ struct cvmx_npei_last_win_rdata1_s cn52xx;
+ struct cvmx_npei_last_win_rdata1_s cn52xxp1;
+ struct cvmx_npei_last_win_rdata1_s cn56xx;
+ struct cvmx_npei_last_win_rdata1_s cn56xxp1;
+};
+
+union cvmx_npei_mem_access_ctl {
+ uint64_t u64;
+ struct cvmx_npei_mem_access_ctl_s {
+ uint64_t reserved_14_63:50;
+ uint64_t max_word:4;
+ uint64_t timer:10;
+ } s;
+ struct cvmx_npei_mem_access_ctl_s cn52xx;
+ struct cvmx_npei_mem_access_ctl_s cn52xxp1;
+ struct cvmx_npei_mem_access_ctl_s cn56xx;
+ struct cvmx_npei_mem_access_ctl_s cn56xxp1;
+};
+
+union cvmx_npei_mem_access_subidx {
+ uint64_t u64;
+ struct cvmx_npei_mem_access_subidx_s {
+ uint64_t reserved_42_63:22;
+ uint64_t zero:1;
+ uint64_t port:2;
+ uint64_t nmerge:1;
+ uint64_t esr:2;
+ uint64_t esw:2;
+ uint64_t nsr:1;
+ uint64_t nsw:1;
+ uint64_t ror:1;
+ uint64_t row:1;
+ uint64_t ba:30;
+ } s;
+ struct cvmx_npei_mem_access_subidx_s cn52xx;
+ struct cvmx_npei_mem_access_subidx_s cn52xxp1;
+ struct cvmx_npei_mem_access_subidx_s cn56xx;
+ struct cvmx_npei_mem_access_subidx_s cn56xxp1;
+};
+
+union cvmx_npei_msi_enb0 {
+ uint64_t u64;
+ struct cvmx_npei_msi_enb0_s {
+ uint64_t enb:64;
+ } s;
+ struct cvmx_npei_msi_enb0_s cn52xx;
+ struct cvmx_npei_msi_enb0_s cn52xxp1;
+ struct cvmx_npei_msi_enb0_s cn56xx;
+ struct cvmx_npei_msi_enb0_s cn56xxp1;
+};
+
+union cvmx_npei_msi_enb1 {
+ uint64_t u64;
+ struct cvmx_npei_msi_enb1_s {
+ uint64_t enb:64;
+ } s;
+ struct cvmx_npei_msi_enb1_s cn52xx;
+ struct cvmx_npei_msi_enb1_s cn52xxp1;
+ struct cvmx_npei_msi_enb1_s cn56xx;
+ struct cvmx_npei_msi_enb1_s cn56xxp1;
+};
+
+union cvmx_npei_msi_enb2 {
+ uint64_t u64;
+ struct cvmx_npei_msi_enb2_s {
+ uint64_t enb:64;
+ } s;
+ struct cvmx_npei_msi_enb2_s cn52xx;
+ struct cvmx_npei_msi_enb2_s cn52xxp1;
+ struct cvmx_npei_msi_enb2_s cn56xx;
+ struct cvmx_npei_msi_enb2_s cn56xxp1;
+};
+
+union cvmx_npei_msi_enb3 {
+ uint64_t u64;
+ struct cvmx_npei_msi_enb3_s {
+ uint64_t enb:64;
+ } s;
+ struct cvmx_npei_msi_enb3_s cn52xx;
+ struct cvmx_npei_msi_enb3_s cn52xxp1;
+ struct cvmx_npei_msi_enb3_s cn56xx;
+ struct cvmx_npei_msi_enb3_s cn56xxp1;
+};
+
+union cvmx_npei_msi_rcv0 {
+ uint64_t u64;
+ struct cvmx_npei_msi_rcv0_s {
+ uint64_t intr:64;
+ } s;
+ struct cvmx_npei_msi_rcv0_s cn52xx;
+ struct cvmx_npei_msi_rcv0_s cn52xxp1;
+ struct cvmx_npei_msi_rcv0_s cn56xx;
+ struct cvmx_npei_msi_rcv0_s cn56xxp1;
+};
+
+union cvmx_npei_msi_rcv1 {
+ uint64_t u64;
+ struct cvmx_npei_msi_rcv1_s {
+ uint64_t intr:64;
+ } s;
+ struct cvmx_npei_msi_rcv1_s cn52xx;
+ struct cvmx_npei_msi_rcv1_s cn52xxp1;
+ struct cvmx_npei_msi_rcv1_s cn56xx;
+ struct cvmx_npei_msi_rcv1_s cn56xxp1;
+};
+
+union cvmx_npei_msi_rcv2 {
+ uint64_t u64;
+ struct cvmx_npei_msi_rcv2_s {
+ uint64_t intr:64;
+ } s;
+ struct cvmx_npei_msi_rcv2_s cn52xx;
+ struct cvmx_npei_msi_rcv2_s cn52xxp1;
+ struct cvmx_npei_msi_rcv2_s cn56xx;
+ struct cvmx_npei_msi_rcv2_s cn56xxp1;
+};
+
+union cvmx_npei_msi_rcv3 {
+ uint64_t u64;
+ struct cvmx_npei_msi_rcv3_s {
+ uint64_t intr:64;
+ } s;
+ struct cvmx_npei_msi_rcv3_s cn52xx;
+ struct cvmx_npei_msi_rcv3_s cn52xxp1;
+ struct cvmx_npei_msi_rcv3_s cn56xx;
+ struct cvmx_npei_msi_rcv3_s cn56xxp1;
+};
+
+union cvmx_npei_msi_rd_map {
+ uint64_t u64;
+ struct cvmx_npei_msi_rd_map_s {
+ uint64_t reserved_16_63:48;
+ uint64_t rd_int:8;
+ uint64_t msi_int:8;
+ } s;
+ struct cvmx_npei_msi_rd_map_s cn52xx;
+ struct cvmx_npei_msi_rd_map_s cn52xxp1;
+ struct cvmx_npei_msi_rd_map_s cn56xx;
+ struct cvmx_npei_msi_rd_map_s cn56xxp1;
+};
+
+union cvmx_npei_msi_w1c_enb0 {
+ uint64_t u64;
+ struct cvmx_npei_msi_w1c_enb0_s {
+ uint64_t clr:64;
+ } s;
+ struct cvmx_npei_msi_w1c_enb0_s cn52xx;
+ struct cvmx_npei_msi_w1c_enb0_s cn56xx;
+};
+
+union cvmx_npei_msi_w1c_enb1 {
+ uint64_t u64;
+ struct cvmx_npei_msi_w1c_enb1_s {
+ uint64_t clr:64;
+ } s;
+ struct cvmx_npei_msi_w1c_enb1_s cn52xx;
+ struct cvmx_npei_msi_w1c_enb1_s cn56xx;
+};
+
+union cvmx_npei_msi_w1c_enb2 {
+ uint64_t u64;
+ struct cvmx_npei_msi_w1c_enb2_s {
+ uint64_t clr:64;
+ } s;
+ struct cvmx_npei_msi_w1c_enb2_s cn52xx;
+ struct cvmx_npei_msi_w1c_enb2_s cn56xx;
+};
+
+union cvmx_npei_msi_w1c_enb3 {
+ uint64_t u64;
+ struct cvmx_npei_msi_w1c_enb3_s {
+ uint64_t clr:64;
+ } s;
+ struct cvmx_npei_msi_w1c_enb3_s cn52xx;
+ struct cvmx_npei_msi_w1c_enb3_s cn56xx;
+};
+
+union cvmx_npei_msi_w1s_enb0 {
+ uint64_t u64;
+ struct cvmx_npei_msi_w1s_enb0_s {
+ uint64_t set:64;
+ } s;
+ struct cvmx_npei_msi_w1s_enb0_s cn52xx;
+ struct cvmx_npei_msi_w1s_enb0_s cn56xx;
+};
+
+union cvmx_npei_msi_w1s_enb1 {
+ uint64_t u64;
+ struct cvmx_npei_msi_w1s_enb1_s {
+ uint64_t set:64;
+ } s;
+ struct cvmx_npei_msi_w1s_enb1_s cn52xx;
+ struct cvmx_npei_msi_w1s_enb1_s cn56xx;
+};
+
+union cvmx_npei_msi_w1s_enb2 {
+ uint64_t u64;
+ struct cvmx_npei_msi_w1s_enb2_s {
+ uint64_t set:64;
+ } s;
+ struct cvmx_npei_msi_w1s_enb2_s cn52xx;
+ struct cvmx_npei_msi_w1s_enb2_s cn56xx;
+};
+
+union cvmx_npei_msi_w1s_enb3 {
+ uint64_t u64;
+ struct cvmx_npei_msi_w1s_enb3_s {
+ uint64_t set:64;
+ } s;
+ struct cvmx_npei_msi_w1s_enb3_s cn52xx;
+ struct cvmx_npei_msi_w1s_enb3_s cn56xx;
+};
+
+union cvmx_npei_msi_wr_map {
+ uint64_t u64;
+ struct cvmx_npei_msi_wr_map_s {
+ uint64_t reserved_16_63:48;
+ uint64_t ciu_int:8;
+ uint64_t msi_int:8;
+ } s;
+ struct cvmx_npei_msi_wr_map_s cn52xx;
+ struct cvmx_npei_msi_wr_map_s cn52xxp1;
+ struct cvmx_npei_msi_wr_map_s cn56xx;
+ struct cvmx_npei_msi_wr_map_s cn56xxp1;
+};
+
+union cvmx_npei_pcie_credit_cnt {
+ uint64_t u64;
+ struct cvmx_npei_pcie_credit_cnt_s {
+ uint64_t reserved_48_63:16;
+ uint64_t p1_ccnt:8;
+ uint64_t p1_ncnt:8;
+ uint64_t p1_pcnt:8;
+ uint64_t p0_ccnt:8;
+ uint64_t p0_ncnt:8;
+ uint64_t p0_pcnt:8;
+ } s;
+ struct cvmx_npei_pcie_credit_cnt_s cn52xx;
+ struct cvmx_npei_pcie_credit_cnt_s cn56xx;
+};
+
+union cvmx_npei_pcie_msi_rcv {
+ uint64_t u64;
+ struct cvmx_npei_pcie_msi_rcv_s {
+ uint64_t reserved_8_63:56;
+ uint64_t intr:8;
+ } s;
+ struct cvmx_npei_pcie_msi_rcv_s cn52xx;
+ struct cvmx_npei_pcie_msi_rcv_s cn52xxp1;
+ struct cvmx_npei_pcie_msi_rcv_s cn56xx;
+ struct cvmx_npei_pcie_msi_rcv_s cn56xxp1;
+};
+
+union cvmx_npei_pcie_msi_rcv_b1 {
+ uint64_t u64;
+ struct cvmx_npei_pcie_msi_rcv_b1_s {
+ uint64_t reserved_16_63:48;
+ uint64_t intr:8;
+ uint64_t reserved_0_7:8;
+ } s;
+ struct cvmx_npei_pcie_msi_rcv_b1_s cn52xx;
+ struct cvmx_npei_pcie_msi_rcv_b1_s cn52xxp1;
+ struct cvmx_npei_pcie_msi_rcv_b1_s cn56xx;
+ struct cvmx_npei_pcie_msi_rcv_b1_s cn56xxp1;
+};
+
+union cvmx_npei_pcie_msi_rcv_b2 {
+ uint64_t u64;
+ struct cvmx_npei_pcie_msi_rcv_b2_s {
+ uint64_t reserved_24_63:40;
+ uint64_t intr:8;
+ uint64_t reserved_0_15:16;
+ } s;
+ struct cvmx_npei_pcie_msi_rcv_b2_s cn52xx;
+ struct cvmx_npei_pcie_msi_rcv_b2_s cn52xxp1;
+ struct cvmx_npei_pcie_msi_rcv_b2_s cn56xx;
+ struct cvmx_npei_pcie_msi_rcv_b2_s cn56xxp1;
+};
+
+union cvmx_npei_pcie_msi_rcv_b3 {
+ uint64_t u64;
+ struct cvmx_npei_pcie_msi_rcv_b3_s {
+ uint64_t reserved_32_63:32;
+ uint64_t intr:8;
+ uint64_t reserved_0_23:24;
+ } s;
+ struct cvmx_npei_pcie_msi_rcv_b3_s cn52xx;
+ struct cvmx_npei_pcie_msi_rcv_b3_s cn52xxp1;
+ struct cvmx_npei_pcie_msi_rcv_b3_s cn56xx;
+ struct cvmx_npei_pcie_msi_rcv_b3_s cn56xxp1;
+};
+
+union cvmx_npei_pktx_cnts {
+ uint64_t u64;
+ struct cvmx_npei_pktx_cnts_s {
+ uint64_t reserved_54_63:10;
+ uint64_t timer:22;
+ uint64_t cnt:32;
+ } s;
+ struct cvmx_npei_pktx_cnts_s cn52xx;
+ struct cvmx_npei_pktx_cnts_s cn56xx;
+ struct cvmx_npei_pktx_cnts_s cn56xxp1;
+};
+
+union cvmx_npei_pktx_in_bp {
+ uint64_t u64;
+ struct cvmx_npei_pktx_in_bp_s {
+ uint64_t wmark:32;
+ uint64_t cnt:32;
+ } s;
+ struct cvmx_npei_pktx_in_bp_s cn52xx;
+ struct cvmx_npei_pktx_in_bp_s cn56xx;
+ struct cvmx_npei_pktx_in_bp_s cn56xxp1;
+};
+
+union cvmx_npei_pktx_instr_baddr {
+ uint64_t u64;
+ struct cvmx_npei_pktx_instr_baddr_s {
+ uint64_t addr:61;
+ uint64_t reserved_0_2:3;
+ } s;
+ struct cvmx_npei_pktx_instr_baddr_s cn52xx;
+ struct cvmx_npei_pktx_instr_baddr_s cn56xx;
+ struct cvmx_npei_pktx_instr_baddr_s cn56xxp1;
+};
+
+union cvmx_npei_pktx_instr_baoff_dbell {
+ uint64_t u64;
+ struct cvmx_npei_pktx_instr_baoff_dbell_s {
+ uint64_t aoff:32;
+ uint64_t dbell:32;
+ } s;
+ struct cvmx_npei_pktx_instr_baoff_dbell_s cn52xx;
+ struct cvmx_npei_pktx_instr_baoff_dbell_s cn56xx;
+ struct cvmx_npei_pktx_instr_baoff_dbell_s cn56xxp1;
+};
+
+union cvmx_npei_pktx_instr_fifo_rsize {
+ uint64_t u64;
+ struct cvmx_npei_pktx_instr_fifo_rsize_s {
+ uint64_t max:9;
+ uint64_t rrp:9;
+ uint64_t wrp:9;
+ uint64_t fcnt:5;
+ uint64_t rsize:32;
+ } s;
+ struct cvmx_npei_pktx_instr_fifo_rsize_s cn52xx;
+ struct cvmx_npei_pktx_instr_fifo_rsize_s cn56xx;
+ struct cvmx_npei_pktx_instr_fifo_rsize_s cn56xxp1;
+};
+
+union cvmx_npei_pktx_instr_header {
+ uint64_t u64;
+ struct cvmx_npei_pktx_instr_header_s {
+ uint64_t reserved_44_63:20;
+ uint64_t pbp:1;
+ uint64_t rsv_f:5;
+ uint64_t rparmode:2;
+ uint64_t rsv_e:1;
+ uint64_t rskp_len:7;
+ uint64_t rsv_d:6;
+ uint64_t use_ihdr:1;
+ uint64_t rsv_c:5;
+ uint64_t par_mode:2;
+ uint64_t rsv_b:1;
+ uint64_t skp_len:7;
+ uint64_t rsv_a:6;
+ } s;
+ struct cvmx_npei_pktx_instr_header_s cn52xx;
+ struct cvmx_npei_pktx_instr_header_s cn56xx;
+ struct cvmx_npei_pktx_instr_header_s cn56xxp1;
+};
+
+union cvmx_npei_pktx_slist_baddr {
+ uint64_t u64;
+ struct cvmx_npei_pktx_slist_baddr_s {
+ uint64_t addr:60;
+ uint64_t reserved_0_3:4;
+ } s;
+ struct cvmx_npei_pktx_slist_baddr_s cn52xx;
+ struct cvmx_npei_pktx_slist_baddr_s cn56xx;
+ struct cvmx_npei_pktx_slist_baddr_s cn56xxp1;
+};
+
+union cvmx_npei_pktx_slist_baoff_dbell {
+ uint64_t u64;
+ struct cvmx_npei_pktx_slist_baoff_dbell_s {
+ uint64_t aoff:32;
+ uint64_t dbell:32;
+ } s;
+ struct cvmx_npei_pktx_slist_baoff_dbell_s cn52xx;
+ struct cvmx_npei_pktx_slist_baoff_dbell_s cn56xx;
+ struct cvmx_npei_pktx_slist_baoff_dbell_s cn56xxp1;
+};
+
+union cvmx_npei_pktx_slist_fifo_rsize {
+ uint64_t u64;
+ struct cvmx_npei_pktx_slist_fifo_rsize_s {
+ uint64_t reserved_32_63:32;
+ uint64_t rsize:32;
+ } s;
+ struct cvmx_npei_pktx_slist_fifo_rsize_s cn52xx;
+ struct cvmx_npei_pktx_slist_fifo_rsize_s cn56xx;
+ struct cvmx_npei_pktx_slist_fifo_rsize_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_cnt_int {
+ uint64_t u64;
+ struct cvmx_npei_pkt_cnt_int_s {
+ uint64_t reserved_32_63:32;
+ uint64_t port:32;
+ } s;
+ struct cvmx_npei_pkt_cnt_int_s cn52xx;
+ struct cvmx_npei_pkt_cnt_int_s cn56xx;
+ struct cvmx_npei_pkt_cnt_int_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_cnt_int_enb {
+ uint64_t u64;
+ struct cvmx_npei_pkt_cnt_int_enb_s {
+ uint64_t reserved_32_63:32;
+ uint64_t port:32;
+ } s;
+ struct cvmx_npei_pkt_cnt_int_enb_s cn52xx;
+ struct cvmx_npei_pkt_cnt_int_enb_s cn56xx;
+ struct cvmx_npei_pkt_cnt_int_enb_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_data_out_es {
+ uint64_t u64;
+ struct cvmx_npei_pkt_data_out_es_s {
+ uint64_t es:64;
+ } s;
+ struct cvmx_npei_pkt_data_out_es_s cn52xx;
+ struct cvmx_npei_pkt_data_out_es_s cn56xx;
+ struct cvmx_npei_pkt_data_out_es_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_data_out_ns {
+ uint64_t u64;
+ struct cvmx_npei_pkt_data_out_ns_s {
+ uint64_t reserved_32_63:32;
+ uint64_t nsr:32;
+ } s;
+ struct cvmx_npei_pkt_data_out_ns_s cn52xx;
+ struct cvmx_npei_pkt_data_out_ns_s cn56xx;
+ struct cvmx_npei_pkt_data_out_ns_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_data_out_ror {
+ uint64_t u64;
+ struct cvmx_npei_pkt_data_out_ror_s {
+ uint64_t reserved_32_63:32;
+ uint64_t ror:32;
+ } s;
+ struct cvmx_npei_pkt_data_out_ror_s cn52xx;
+ struct cvmx_npei_pkt_data_out_ror_s cn56xx;
+ struct cvmx_npei_pkt_data_out_ror_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_dpaddr {
+ uint64_t u64;
+ struct cvmx_npei_pkt_dpaddr_s {
+ uint64_t reserved_32_63:32;
+ uint64_t dptr:32;
+ } s;
+ struct cvmx_npei_pkt_dpaddr_s cn52xx;
+ struct cvmx_npei_pkt_dpaddr_s cn56xx;
+ struct cvmx_npei_pkt_dpaddr_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_in_bp {
+ uint64_t u64;
+ struct cvmx_npei_pkt_in_bp_s {
+ uint64_t reserved_32_63:32;
+ uint64_t bp:32;
+ } s;
+ struct cvmx_npei_pkt_in_bp_s cn56xx;
+};
+
+union cvmx_npei_pkt_in_donex_cnts {
+ uint64_t u64;
+ struct cvmx_npei_pkt_in_donex_cnts_s {
+ uint64_t reserved_32_63:32;
+ uint64_t cnt:32;
+ } s;
+ struct cvmx_npei_pkt_in_donex_cnts_s cn52xx;
+ struct cvmx_npei_pkt_in_donex_cnts_s cn56xx;
+ struct cvmx_npei_pkt_in_donex_cnts_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_in_instr_counts {
+ uint64_t u64;
+ struct cvmx_npei_pkt_in_instr_counts_s {
+ uint64_t wr_cnt:32;
+ uint64_t rd_cnt:32;
+ } s;
+ struct cvmx_npei_pkt_in_instr_counts_s cn52xx;
+ struct cvmx_npei_pkt_in_instr_counts_s cn56xx;
+};
+
+union cvmx_npei_pkt_in_pcie_port {
+ uint64_t u64;
+ struct cvmx_npei_pkt_in_pcie_port_s {
+ uint64_t pp:64;
+ } s;
+ struct cvmx_npei_pkt_in_pcie_port_s cn52xx;
+ struct cvmx_npei_pkt_in_pcie_port_s cn56xx;
+};
+
+union cvmx_npei_pkt_input_control {
+ uint64_t u64;
+ struct cvmx_npei_pkt_input_control_s {
+ uint64_t reserved_23_63:41;
+ uint64_t pkt_rr:1;
+ uint64_t pbp_dhi:13;
+ uint64_t d_nsr:1;
+ uint64_t d_esr:2;
+ uint64_t d_ror:1;
+ uint64_t use_csr:1;
+ uint64_t nsr:1;
+ uint64_t esr:2;
+ uint64_t ror:1;
+ } s;
+ struct cvmx_npei_pkt_input_control_s cn52xx;
+ struct cvmx_npei_pkt_input_control_s cn56xx;
+ struct cvmx_npei_pkt_input_control_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_instr_enb {
+ uint64_t u64;
+ struct cvmx_npei_pkt_instr_enb_s {
+ uint64_t reserved_32_63:32;
+ uint64_t enb:32;
+ } s;
+ struct cvmx_npei_pkt_instr_enb_s cn52xx;
+ struct cvmx_npei_pkt_instr_enb_s cn56xx;
+ struct cvmx_npei_pkt_instr_enb_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_instr_rd_size {
+ uint64_t u64;
+ struct cvmx_npei_pkt_instr_rd_size_s {
+ uint64_t rdsize:64;
+ } s;
+ struct cvmx_npei_pkt_instr_rd_size_s cn52xx;
+ struct cvmx_npei_pkt_instr_rd_size_s cn56xx;
+};
+
+union cvmx_npei_pkt_instr_size {
+ uint64_t u64;
+ struct cvmx_npei_pkt_instr_size_s {
+ uint64_t reserved_32_63:32;
+ uint64_t is_64b:32;
+ } s;
+ struct cvmx_npei_pkt_instr_size_s cn52xx;
+ struct cvmx_npei_pkt_instr_size_s cn56xx;
+ struct cvmx_npei_pkt_instr_size_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_int_levels {
+ uint64_t u64;
+ struct cvmx_npei_pkt_int_levels_s {
+ uint64_t reserved_54_63:10;
+ uint64_t time:22;
+ uint64_t cnt:32;
+ } s;
+ struct cvmx_npei_pkt_int_levels_s cn52xx;
+ struct cvmx_npei_pkt_int_levels_s cn56xx;
+ struct cvmx_npei_pkt_int_levels_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_iptr {
+ uint64_t u64;
+ struct cvmx_npei_pkt_iptr_s {
+ uint64_t reserved_32_63:32;
+ uint64_t iptr:32;
+ } s;
+ struct cvmx_npei_pkt_iptr_s cn52xx;
+ struct cvmx_npei_pkt_iptr_s cn56xx;
+ struct cvmx_npei_pkt_iptr_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_out_bmode {
+ uint64_t u64;
+ struct cvmx_npei_pkt_out_bmode_s {
+ uint64_t reserved_32_63:32;
+ uint64_t bmode:32;
+ } s;
+ struct cvmx_npei_pkt_out_bmode_s cn52xx;
+ struct cvmx_npei_pkt_out_bmode_s cn56xx;
+ struct cvmx_npei_pkt_out_bmode_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_out_enb {
+ uint64_t u64;
+ struct cvmx_npei_pkt_out_enb_s {
+ uint64_t reserved_32_63:32;
+ uint64_t enb:32;
+ } s;
+ struct cvmx_npei_pkt_out_enb_s cn52xx;
+ struct cvmx_npei_pkt_out_enb_s cn56xx;
+ struct cvmx_npei_pkt_out_enb_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_output_wmark {
+ uint64_t u64;
+ struct cvmx_npei_pkt_output_wmark_s {
+ uint64_t reserved_32_63:32;
+ uint64_t wmark:32;
+ } s;
+ struct cvmx_npei_pkt_output_wmark_s cn52xx;
+ struct cvmx_npei_pkt_output_wmark_s cn56xx;
+};
+
+union cvmx_npei_pkt_pcie_port {
+ uint64_t u64;
+ struct cvmx_npei_pkt_pcie_port_s {
+ uint64_t pp:64;
+ } s;
+ struct cvmx_npei_pkt_pcie_port_s cn52xx;
+ struct cvmx_npei_pkt_pcie_port_s cn56xx;
+ struct cvmx_npei_pkt_pcie_port_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_port_in_rst {
+ uint64_t u64;
+ struct cvmx_npei_pkt_port_in_rst_s {
+ uint64_t in_rst:32;
+ uint64_t out_rst:32;
+ } s;
+ struct cvmx_npei_pkt_port_in_rst_s cn52xx;
+ struct cvmx_npei_pkt_port_in_rst_s cn56xx;
+};
+
+union cvmx_npei_pkt_slist_es {
+ uint64_t u64;
+ struct cvmx_npei_pkt_slist_es_s {
+ uint64_t es:64;
+ } s;
+ struct cvmx_npei_pkt_slist_es_s cn52xx;
+ struct cvmx_npei_pkt_slist_es_s cn56xx;
+ struct cvmx_npei_pkt_slist_es_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_slist_id_size {
+ uint64_t u64;
+ struct cvmx_npei_pkt_slist_id_size_s {
+ uint64_t reserved_23_63:41;
+ uint64_t isize:7;
+ uint64_t bsize:16;
+ } s;
+ struct cvmx_npei_pkt_slist_id_size_s cn52xx;
+ struct cvmx_npei_pkt_slist_id_size_s cn56xx;
+ struct cvmx_npei_pkt_slist_id_size_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_slist_ns {
+ uint64_t u64;
+ struct cvmx_npei_pkt_slist_ns_s {
+ uint64_t reserved_32_63:32;
+ uint64_t nsr:32;
+ } s;
+ struct cvmx_npei_pkt_slist_ns_s cn52xx;
+ struct cvmx_npei_pkt_slist_ns_s cn56xx;
+ struct cvmx_npei_pkt_slist_ns_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_slist_ror {
+ uint64_t u64;
+ struct cvmx_npei_pkt_slist_ror_s {
+ uint64_t reserved_32_63:32;
+ uint64_t ror:32;
+ } s;
+ struct cvmx_npei_pkt_slist_ror_s cn52xx;
+ struct cvmx_npei_pkt_slist_ror_s cn56xx;
+ struct cvmx_npei_pkt_slist_ror_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_time_int {
+ uint64_t u64;
+ struct cvmx_npei_pkt_time_int_s {
+ uint64_t reserved_32_63:32;
+ uint64_t port:32;
+ } s;
+ struct cvmx_npei_pkt_time_int_s cn52xx;
+ struct cvmx_npei_pkt_time_int_s cn56xx;
+ struct cvmx_npei_pkt_time_int_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_time_int_enb {
+ uint64_t u64;
+ struct cvmx_npei_pkt_time_int_enb_s {
+ uint64_t reserved_32_63:32;
+ uint64_t port:32;
+ } s;
+ struct cvmx_npei_pkt_time_int_enb_s cn52xx;
+ struct cvmx_npei_pkt_time_int_enb_s cn56xx;
+ struct cvmx_npei_pkt_time_int_enb_s cn56xxp1;
+};
+
+union cvmx_npei_rsl_int_blocks {
+ uint64_t u64;
+ struct cvmx_npei_rsl_int_blocks_s {
+ uint64_t reserved_31_63:33;
+ uint64_t iob:1;
+ uint64_t lmc1:1;
+ uint64_t agl:1;
+ uint64_t reserved_24_27:4;
+ uint64_t asxpcs1:1;
+ uint64_t asxpcs0:1;
+ uint64_t reserved_21_21:1;
+ uint64_t pip:1;
+ uint64_t reserved_18_19:2;
+ uint64_t lmc0:1;
+ uint64_t l2c:1;
+ uint64_t usb1:1;
+ uint64_t rad:1;
+ uint64_t usb:1;
+ uint64_t pow:1;
+ uint64_t tim:1;
+ uint64_t pko:1;
+ uint64_t ipd:1;
+ uint64_t reserved_8_8:1;
+ uint64_t zip:1;
+ uint64_t reserved_6_6:1;
+ uint64_t fpa:1;
+ uint64_t key:1;
+ uint64_t npei:1;
+ uint64_t gmx1:1;
+ uint64_t gmx0:1;
+ uint64_t mio:1;
+ } s;
+ struct cvmx_npei_rsl_int_blocks_s cn52xx;
+ struct cvmx_npei_rsl_int_blocks_s cn52xxp1;
+ struct cvmx_npei_rsl_int_blocks_cn56xx {
+ uint64_t reserved_31_63:33;
+ uint64_t iob:1;
+ uint64_t lmc1:1;
+ uint64_t agl:1;
+ uint64_t reserved_24_27:4;
+ uint64_t asxpcs1:1;
+ uint64_t asxpcs0:1;
+ uint64_t reserved_21_21:1;
+ uint64_t pip:1;
+ uint64_t reserved_18_19:2;
+ uint64_t lmc0:1;
+ uint64_t l2c:1;
+ uint64_t reserved_15_15:1;
+ uint64_t rad:1;
+ uint64_t usb:1;
+ uint64_t pow:1;
+ uint64_t tim:1;
+ uint64_t pko:1;
+ uint64_t ipd:1;
+ uint64_t reserved_8_8:1;
+ uint64_t zip:1;
+ uint64_t reserved_6_6:1;
+ uint64_t fpa:1;
+ uint64_t key:1;
+ uint64_t npei:1;
+ uint64_t gmx1:1;
+ uint64_t gmx0:1;
+ uint64_t mio:1;
+ } cn56xx;
+ struct cvmx_npei_rsl_int_blocks_cn56xx cn56xxp1;
+};
+
+union cvmx_npei_scratch_1 {
+ uint64_t u64;
+ struct cvmx_npei_scratch_1_s {
+ uint64_t data:64;
+ } s;
+ struct cvmx_npei_scratch_1_s cn52xx;
+ struct cvmx_npei_scratch_1_s cn52xxp1;
+ struct cvmx_npei_scratch_1_s cn56xx;
+ struct cvmx_npei_scratch_1_s cn56xxp1;
+};
+
+union cvmx_npei_state1 {
+ uint64_t u64;
+ struct cvmx_npei_state1_s {
+ uint64_t cpl1:12;
+ uint64_t cpl0:12;
+ uint64_t arb:1;
+ uint64_t csr:39;
+ } s;
+ struct cvmx_npei_state1_s cn52xx;
+ struct cvmx_npei_state1_s cn52xxp1;
+ struct cvmx_npei_state1_s cn56xx;
+ struct cvmx_npei_state1_s cn56xxp1;
+};
+
+union cvmx_npei_state2 {
+ uint64_t u64;
+ struct cvmx_npei_state2_s {
+ uint64_t reserved_48_63:16;
+ uint64_t npei:1;
+ uint64_t rac:1;
+ uint64_t csm1:15;
+ uint64_t csm0:15;
+ uint64_t nnp0:8;
+ uint64_t nnd:8;
+ } s;
+ struct cvmx_npei_state2_s cn52xx;
+ struct cvmx_npei_state2_s cn52xxp1;
+ struct cvmx_npei_state2_s cn56xx;
+ struct cvmx_npei_state2_s cn56xxp1;
+};
+
+union cvmx_npei_state3 {
+ uint64_t u64;
+ struct cvmx_npei_state3_s {
+ uint64_t reserved_56_63:8;
+ uint64_t psm1:15;
+ uint64_t psm0:15;
+ uint64_t nsm1:13;
+ uint64_t nsm0:13;
+ } s;
+ struct cvmx_npei_state3_s cn52xx;
+ struct cvmx_npei_state3_s cn52xxp1;
+ struct cvmx_npei_state3_s cn56xx;
+ struct cvmx_npei_state3_s cn56xxp1;
+};
+
+union cvmx_npei_win_rd_addr {
+ uint64_t u64;
+ struct cvmx_npei_win_rd_addr_s {
+ uint64_t reserved_51_63:13;
+ uint64_t ld_cmd:2;
+ uint64_t iobit:1;
+ uint64_t rd_addr:48;
+ } s;
+ struct cvmx_npei_win_rd_addr_s cn52xx;
+ struct cvmx_npei_win_rd_addr_s cn52xxp1;
+ struct cvmx_npei_win_rd_addr_s cn56xx;
+ struct cvmx_npei_win_rd_addr_s cn56xxp1;
+};
+
+union cvmx_npei_win_rd_data {
+ uint64_t u64;
+ struct cvmx_npei_win_rd_data_s {
+ uint64_t rd_data:64;
+ } s;
+ struct cvmx_npei_win_rd_data_s cn52xx;
+ struct cvmx_npei_win_rd_data_s cn52xxp1;
+ struct cvmx_npei_win_rd_data_s cn56xx;
+ struct cvmx_npei_win_rd_data_s cn56xxp1;
+};
+
+union cvmx_npei_win_wr_addr {
+ uint64_t u64;
+ struct cvmx_npei_win_wr_addr_s {
+ uint64_t reserved_49_63:15;
+ uint64_t iobit:1;
+ uint64_t wr_addr:46;
+ uint64_t reserved_0_1:2;
+ } s;
+ struct cvmx_npei_win_wr_addr_s cn52xx;
+ struct cvmx_npei_win_wr_addr_s cn52xxp1;
+ struct cvmx_npei_win_wr_addr_s cn56xx;
+ struct cvmx_npei_win_wr_addr_s cn56xxp1;
+};
+
+union cvmx_npei_win_wr_data {
+ uint64_t u64;
+ struct cvmx_npei_win_wr_data_s {
+ uint64_t wr_data:64;
+ } s;
+ struct cvmx_npei_win_wr_data_s cn52xx;
+ struct cvmx_npei_win_wr_data_s cn52xxp1;
+ struct cvmx_npei_win_wr_data_s cn56xx;
+ struct cvmx_npei_win_wr_data_s cn56xxp1;
+};
+
+union cvmx_npei_win_wr_mask {
+ uint64_t u64;
+ struct cvmx_npei_win_wr_mask_s {
+ uint64_t reserved_8_63:56;
+ uint64_t wr_mask:8;
+ } s;
+ struct cvmx_npei_win_wr_mask_s cn52xx;
+ struct cvmx_npei_win_wr_mask_s cn52xxp1;
+ struct cvmx_npei_win_wr_mask_s cn56xx;
+ struct cvmx_npei_win_wr_mask_s cn56xxp1;
+};
+
+union cvmx_npei_window_ctl {
+ uint64_t u64;
+ struct cvmx_npei_window_ctl_s {
+ uint64_t reserved_32_63:32;
+ uint64_t time:32;
+ } s;
+ struct cvmx_npei_window_ctl_s cn52xx;
+ struct cvmx_npei_window_ctl_s cn52xxp1;
+ struct cvmx_npei_window_ctl_s cn56xx;
+ struct cvmx_npei_window_ctl_s cn56xxp1;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-npi-defs.h b/arch/mips/include/asm/octeon/cvmx-npi-defs.h
new file mode 100644
index 000000000000..4e03cd8561e3
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-npi-defs.h
@@ -0,0 +1,1735 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_NPI_DEFS_H__
+#define __CVMX_NPI_DEFS_H__
+
+#define CVMX_NPI_BASE_ADDR_INPUT0 \
+ CVMX_ADD_IO_SEG(0x00011F0000000070ull)
+#define CVMX_NPI_BASE_ADDR_INPUT1 \
+ CVMX_ADD_IO_SEG(0x00011F0000000080ull)
+#define CVMX_NPI_BASE_ADDR_INPUT2 \
+ CVMX_ADD_IO_SEG(0x00011F0000000090ull)
+#define CVMX_NPI_BASE_ADDR_INPUT3 \
+ CVMX_ADD_IO_SEG(0x00011F00000000A0ull)
+#define CVMX_NPI_BASE_ADDR_INPUTX(offset) \
+ CVMX_ADD_IO_SEG(0x00011F0000000070ull + (((offset) & 3) * 16))
+#define CVMX_NPI_BASE_ADDR_OUTPUT0 \
+ CVMX_ADD_IO_SEG(0x00011F00000000B8ull)
+#define CVMX_NPI_BASE_ADDR_OUTPUT1 \
+ CVMX_ADD_IO_SEG(0x00011F00000000C0ull)
+#define CVMX_NPI_BASE_ADDR_OUTPUT2 \
+ CVMX_ADD_IO_SEG(0x00011F00000000C8ull)
+#define CVMX_NPI_BASE_ADDR_OUTPUT3 \
+ CVMX_ADD_IO_SEG(0x00011F00000000D0ull)
+#define CVMX_NPI_BASE_ADDR_OUTPUTX(offset) \
+ CVMX_ADD_IO_SEG(0x00011F00000000B8ull + (((offset) & 3) * 8))
+#define CVMX_NPI_BIST_STATUS \
+ CVMX_ADD_IO_SEG(0x00011F00000003F8ull)
+#define CVMX_NPI_BUFF_SIZE_OUTPUT0 \
+ CVMX_ADD_IO_SEG(0x00011F00000000E0ull)
+#define CVMX_NPI_BUFF_SIZE_OUTPUT1 \
+ CVMX_ADD_IO_SEG(0x00011F00000000E8ull)
+#define CVMX_NPI_BUFF_SIZE_OUTPUT2 \
+ CVMX_ADD_IO_SEG(0x00011F00000000F0ull)
+#define CVMX_NPI_BUFF_SIZE_OUTPUT3 \
+ CVMX_ADD_IO_SEG(0x00011F00000000F8ull)
+#define CVMX_NPI_BUFF_SIZE_OUTPUTX(offset) \
+ CVMX_ADD_IO_SEG(0x00011F00000000E0ull + (((offset) & 3) * 8))
+#define CVMX_NPI_COMP_CTL \
+ CVMX_ADD_IO_SEG(0x00011F0000000218ull)
+#define CVMX_NPI_CTL_STATUS \
+ CVMX_ADD_IO_SEG(0x00011F0000000010ull)
+#define CVMX_NPI_DBG_SELECT \
+ CVMX_ADD_IO_SEG(0x00011F0000000008ull)
+#define CVMX_NPI_DMA_CONTROL \
+ CVMX_ADD_IO_SEG(0x00011F0000000128ull)
+#define CVMX_NPI_DMA_HIGHP_COUNTS \
+ CVMX_ADD_IO_SEG(0x00011F0000000148ull)
+#define CVMX_NPI_DMA_HIGHP_NADDR \
+ CVMX_ADD_IO_SEG(0x00011F0000000158ull)
+#define CVMX_NPI_DMA_LOWP_COUNTS \
+ CVMX_ADD_IO_SEG(0x00011F0000000140ull)
+#define CVMX_NPI_DMA_LOWP_NADDR \
+ CVMX_ADD_IO_SEG(0x00011F0000000150ull)
+#define CVMX_NPI_HIGHP_DBELL \
+ CVMX_ADD_IO_SEG(0x00011F0000000120ull)
+#define CVMX_NPI_HIGHP_IBUFF_SADDR \
+ CVMX_ADD_IO_SEG(0x00011F0000000110ull)
+#define CVMX_NPI_INPUT_CONTROL \
+ CVMX_ADD_IO_SEG(0x00011F0000000138ull)
+#define CVMX_NPI_INT_ENB \
+ CVMX_ADD_IO_SEG(0x00011F0000000020ull)
+#define CVMX_NPI_INT_SUM \
+ CVMX_ADD_IO_SEG(0x00011F0000000018ull)
+#define CVMX_NPI_LOWP_DBELL \
+ CVMX_ADD_IO_SEG(0x00011F0000000118ull)
+#define CVMX_NPI_LOWP_IBUFF_SADDR \
+ CVMX_ADD_IO_SEG(0x00011F0000000108ull)
+#define CVMX_NPI_MEM_ACCESS_SUBID3 \
+ CVMX_ADD_IO_SEG(0x00011F0000000028ull)
+#define CVMX_NPI_MEM_ACCESS_SUBID4 \
+ CVMX_ADD_IO_SEG(0x00011F0000000030ull)
+#define CVMX_NPI_MEM_ACCESS_SUBID5 \
+ CVMX_ADD_IO_SEG(0x00011F0000000038ull)
+#define CVMX_NPI_MEM_ACCESS_SUBID6 \
+ CVMX_ADD_IO_SEG(0x00011F0000000040ull)
+#define CVMX_NPI_MEM_ACCESS_SUBIDX(offset) \
+ CVMX_ADD_IO_SEG(0x00011F0000000028ull + (((offset) & 7) * 8) - 8 * 3)
+#define CVMX_NPI_MSI_RCV \
+ (0x0000000000000190ull)
+#define CVMX_NPI_NPI_MSI_RCV \
+ CVMX_ADD_IO_SEG(0x00011F0000001190ull)
+#define CVMX_NPI_NUM_DESC_OUTPUT0 \
+ CVMX_ADD_IO_SEG(0x00011F0000000050ull)
+#define CVMX_NPI_NUM_DESC_OUTPUT1 \
+ CVMX_ADD_IO_SEG(0x00011F0000000058ull)
+#define CVMX_NPI_NUM_DESC_OUTPUT2 \
+ CVMX_ADD_IO_SEG(0x00011F0000000060ull)
+#define CVMX_NPI_NUM_DESC_OUTPUT3 \
+ CVMX_ADD_IO_SEG(0x00011F0000000068ull)
+#define CVMX_NPI_NUM_DESC_OUTPUTX(offset) \
+ CVMX_ADD_IO_SEG(0x00011F0000000050ull + (((offset) & 3) * 8))
+#define CVMX_NPI_OUTPUT_CONTROL \
+ CVMX_ADD_IO_SEG(0x00011F0000000100ull)
+#define CVMX_NPI_P0_DBPAIR_ADDR \
+ CVMX_ADD_IO_SEG(0x00011F0000000180ull)
+#define CVMX_NPI_P0_INSTR_ADDR \
+ CVMX_ADD_IO_SEG(0x00011F00000001C0ull)
+#define CVMX_NPI_P0_INSTR_CNTS \
+ CVMX_ADD_IO_SEG(0x00011F00000001A0ull)
+#define CVMX_NPI_P0_PAIR_CNTS \
+ CVMX_ADD_IO_SEG(0x00011F0000000160ull)
+#define CVMX_NPI_P1_DBPAIR_ADDR \
+ CVMX_ADD_IO_SEG(0x00011F0000000188ull)
+#define CVMX_NPI_P1_INSTR_ADDR \
+ CVMX_ADD_IO_SEG(0x00011F00000001C8ull)
+#define CVMX_NPI_P1_INSTR_CNTS \
+ CVMX_ADD_IO_SEG(0x00011F00000001A8ull)
+#define CVMX_NPI_P1_PAIR_CNTS \
+ CVMX_ADD_IO_SEG(0x00011F0000000168ull)
+#define CVMX_NPI_P2_DBPAIR_ADDR \
+ CVMX_ADD_IO_SEG(0x00011F0000000190ull)
+#define CVMX_NPI_P2_INSTR_ADDR \
+ CVMX_ADD_IO_SEG(0x00011F00000001D0ull)
+#define CVMX_NPI_P2_INSTR_CNTS \
+ CVMX_ADD_IO_SEG(0x00011F00000001B0ull)
+#define CVMX_NPI_P2_PAIR_CNTS \
+ CVMX_ADD_IO_SEG(0x00011F0000000170ull)
+#define CVMX_NPI_P3_DBPAIR_ADDR \
+ CVMX_ADD_IO_SEG(0x00011F0000000198ull)
+#define CVMX_NPI_P3_INSTR_ADDR \
+ CVMX_ADD_IO_SEG(0x00011F00000001D8ull)
+#define CVMX_NPI_P3_INSTR_CNTS \
+ CVMX_ADD_IO_SEG(0x00011F00000001B8ull)
+#define CVMX_NPI_P3_PAIR_CNTS \
+ CVMX_ADD_IO_SEG(0x00011F0000000178ull)
+#define CVMX_NPI_PCI_BAR1_INDEXX(offset) \
+ CVMX_ADD_IO_SEG(0x00011F0000001100ull + (((offset) & 31) * 4))
+#define CVMX_NPI_PCI_BIST_REG \
+ CVMX_ADD_IO_SEG(0x00011F00000011C0ull)
+#define CVMX_NPI_PCI_BURST_SIZE \
+ CVMX_ADD_IO_SEG(0x00011F00000000D8ull)
+#define CVMX_NPI_PCI_CFG00 \
+ CVMX_ADD_IO_SEG(0x00011F0000001800ull)
+#define CVMX_NPI_PCI_CFG01 \
+ CVMX_ADD_IO_SEG(0x00011F0000001804ull)
+#define CVMX_NPI_PCI_CFG02 \
+ CVMX_ADD_IO_SEG(0x00011F0000001808ull)
+#define CVMX_NPI_PCI_CFG03 \
+ CVMX_ADD_IO_SEG(0x00011F000000180Cull)
+#define CVMX_NPI_PCI_CFG04 \
+ CVMX_ADD_IO_SEG(0x00011F0000001810ull)
+#define CVMX_NPI_PCI_CFG05 \
+ CVMX_ADD_IO_SEG(0x00011F0000001814ull)
+#define CVMX_NPI_PCI_CFG06 \
+ CVMX_ADD_IO_SEG(0x00011F0000001818ull)
+#define CVMX_NPI_PCI_CFG07 \
+ CVMX_ADD_IO_SEG(0x00011F000000181Cull)
+#define CVMX_NPI_PCI_CFG08 \
+ CVMX_ADD_IO_SEG(0x00011F0000001820ull)
+#define CVMX_NPI_PCI_CFG09 \
+ CVMX_ADD_IO_SEG(0x00011F0000001824ull)
+#define CVMX_NPI_PCI_CFG10 \
+ CVMX_ADD_IO_SEG(0x00011F0000001828ull)
+#define CVMX_NPI_PCI_CFG11 \
+ CVMX_ADD_IO_SEG(0x00011F000000182Cull)
+#define CVMX_NPI_PCI_CFG12 \
+ CVMX_ADD_IO_SEG(0x00011F0000001830ull)
+#define CVMX_NPI_PCI_CFG13 \
+ CVMX_ADD_IO_SEG(0x00011F0000001834ull)
+#define CVMX_NPI_PCI_CFG15 \
+ CVMX_ADD_IO_SEG(0x00011F000000183Cull)
+#define CVMX_NPI_PCI_CFG16 \
+ CVMX_ADD_IO_SEG(0x00011F0000001840ull)
+#define CVMX_NPI_PCI_CFG17 \
+ CVMX_ADD_IO_SEG(0x00011F0000001844ull)
+#define CVMX_NPI_PCI_CFG18 \
+ CVMX_ADD_IO_SEG(0x00011F0000001848ull)
+#define CVMX_NPI_PCI_CFG19 \
+ CVMX_ADD_IO_SEG(0x00011F000000184Cull)
+#define CVMX_NPI_PCI_CFG20 \
+ CVMX_ADD_IO_SEG(0x00011F0000001850ull)
+#define CVMX_NPI_PCI_CFG21 \
+ CVMX_ADD_IO_SEG(0x00011F0000001854ull)
+#define CVMX_NPI_PCI_CFG22 \
+ CVMX_ADD_IO_SEG(0x00011F0000001858ull)
+#define CVMX_NPI_PCI_CFG56 \
+ CVMX_ADD_IO_SEG(0x00011F00000018E0ull)
+#define CVMX_NPI_PCI_CFG57 \
+ CVMX_ADD_IO_SEG(0x00011F00000018E4ull)
+#define CVMX_NPI_PCI_CFG58 \
+ CVMX_ADD_IO_SEG(0x00011F00000018E8ull)
+#define CVMX_NPI_PCI_CFG59 \
+ CVMX_ADD_IO_SEG(0x00011F00000018ECull)
+#define CVMX_NPI_PCI_CFG60 \
+ CVMX_ADD_IO_SEG(0x00011F00000018F0ull)
+#define CVMX_NPI_PCI_CFG61 \
+ CVMX_ADD_IO_SEG(0x00011F00000018F4ull)
+#define CVMX_NPI_PCI_CFG62 \
+ CVMX_ADD_IO_SEG(0x00011F00000018F8ull)
+#define CVMX_NPI_PCI_CFG63 \
+ CVMX_ADD_IO_SEG(0x00011F00000018FCull)
+#define CVMX_NPI_PCI_CNT_REG \
+ CVMX_ADD_IO_SEG(0x00011F00000011B8ull)
+#define CVMX_NPI_PCI_CTL_STATUS_2 \
+ CVMX_ADD_IO_SEG(0x00011F000000118Cull)
+#define CVMX_NPI_PCI_INT_ARB_CFG \
+ CVMX_ADD_IO_SEG(0x00011F0000000130ull)
+#define CVMX_NPI_PCI_INT_ENB2 \
+ CVMX_ADD_IO_SEG(0x00011F00000011A0ull)
+#define CVMX_NPI_PCI_INT_SUM2 \
+ CVMX_ADD_IO_SEG(0x00011F0000001198ull)
+#define CVMX_NPI_PCI_READ_CMD \
+ CVMX_ADD_IO_SEG(0x00011F0000000048ull)
+#define CVMX_NPI_PCI_READ_CMD_6 \
+ CVMX_ADD_IO_SEG(0x00011F0000001180ull)
+#define CVMX_NPI_PCI_READ_CMD_C \
+ CVMX_ADD_IO_SEG(0x00011F0000001184ull)
+#define CVMX_NPI_PCI_READ_CMD_E \
+ CVMX_ADD_IO_SEG(0x00011F0000001188ull)
+#define CVMX_NPI_PCI_SCM_REG \
+ CVMX_ADD_IO_SEG(0x00011F00000011A8ull)
+#define CVMX_NPI_PCI_TSR_REG \
+ CVMX_ADD_IO_SEG(0x00011F00000011B0ull)
+#define CVMX_NPI_PORT32_INSTR_HDR \
+ CVMX_ADD_IO_SEG(0x00011F00000001F8ull)
+#define CVMX_NPI_PORT33_INSTR_HDR \
+ CVMX_ADD_IO_SEG(0x00011F0000000200ull)
+#define CVMX_NPI_PORT34_INSTR_HDR \
+ CVMX_ADD_IO_SEG(0x00011F0000000208ull)
+#define CVMX_NPI_PORT35_INSTR_HDR \
+ CVMX_ADD_IO_SEG(0x00011F0000000210ull)
+#define CVMX_NPI_PORT_BP_CONTROL \
+ CVMX_ADD_IO_SEG(0x00011F00000001F0ull)
+#define CVMX_NPI_PX_DBPAIR_ADDR(offset) \
+ CVMX_ADD_IO_SEG(0x00011F0000000180ull + (((offset) & 3) * 8))
+#define CVMX_NPI_PX_INSTR_ADDR(offset) \
+ CVMX_ADD_IO_SEG(0x00011F00000001C0ull + (((offset) & 3) * 8))
+#define CVMX_NPI_PX_INSTR_CNTS(offset) \
+ CVMX_ADD_IO_SEG(0x00011F00000001A0ull + (((offset) & 3) * 8))
+#define CVMX_NPI_PX_PAIR_CNTS(offset) \
+ CVMX_ADD_IO_SEG(0x00011F0000000160ull + (((offset) & 3) * 8))
+#define CVMX_NPI_RSL_INT_BLOCKS \
+ CVMX_ADD_IO_SEG(0x00011F0000000000ull)
+#define CVMX_NPI_SIZE_INPUT0 \
+ CVMX_ADD_IO_SEG(0x00011F0000000078ull)
+#define CVMX_NPI_SIZE_INPUT1 \
+ CVMX_ADD_IO_SEG(0x00011F0000000088ull)
+#define CVMX_NPI_SIZE_INPUT2 \
+ CVMX_ADD_IO_SEG(0x00011F0000000098ull)
+#define CVMX_NPI_SIZE_INPUT3 \
+ CVMX_ADD_IO_SEG(0x00011F00000000A8ull)
+#define CVMX_NPI_SIZE_INPUTX(offset) \
+ CVMX_ADD_IO_SEG(0x00011F0000000078ull + (((offset) & 3) * 16))
+#define CVMX_NPI_WIN_READ_TO \
+ CVMX_ADD_IO_SEG(0x00011F00000001E0ull)
+
+union cvmx_npi_base_addr_inputx {
+ uint64_t u64;
+ struct cvmx_npi_base_addr_inputx_s {
+ uint64_t baddr:61;
+ uint64_t reserved_0_2:3;
+ } s;
+ struct cvmx_npi_base_addr_inputx_s cn30xx;
+ struct cvmx_npi_base_addr_inputx_s cn31xx;
+ struct cvmx_npi_base_addr_inputx_s cn38xx;
+ struct cvmx_npi_base_addr_inputx_s cn38xxp2;
+ struct cvmx_npi_base_addr_inputx_s cn50xx;
+ struct cvmx_npi_base_addr_inputx_s cn58xx;
+ struct cvmx_npi_base_addr_inputx_s cn58xxp1;
+};
+
+union cvmx_npi_base_addr_outputx {
+ uint64_t u64;
+ struct cvmx_npi_base_addr_outputx_s {
+ uint64_t baddr:61;
+ uint64_t reserved_0_2:3;
+ } s;
+ struct cvmx_npi_base_addr_outputx_s cn30xx;
+ struct cvmx_npi_base_addr_outputx_s cn31xx;
+ struct cvmx_npi_base_addr_outputx_s cn38xx;
+ struct cvmx_npi_base_addr_outputx_s cn38xxp2;
+ struct cvmx_npi_base_addr_outputx_s cn50xx;
+ struct cvmx_npi_base_addr_outputx_s cn58xx;
+ struct cvmx_npi_base_addr_outputx_s cn58xxp1;
+};
+
+union cvmx_npi_bist_status {
+ uint64_t u64;
+ struct cvmx_npi_bist_status_s {
+ uint64_t reserved_20_63:44;
+ uint64_t csr_bs:1;
+ uint64_t dif_bs:1;
+ uint64_t rdp_bs:1;
+ uint64_t pcnc_bs:1;
+ uint64_t pcn_bs:1;
+ uint64_t rdn_bs:1;
+ uint64_t pcac_bs:1;
+ uint64_t pcad_bs:1;
+ uint64_t rdnl_bs:1;
+ uint64_t pgf_bs:1;
+ uint64_t pig_bs:1;
+ uint64_t pof0_bs:1;
+ uint64_t pof1_bs:1;
+ uint64_t pof2_bs:1;
+ uint64_t pof3_bs:1;
+ uint64_t pos_bs:1;
+ uint64_t nus_bs:1;
+ uint64_t dob_bs:1;
+ uint64_t pdf_bs:1;
+ uint64_t dpi_bs:1;
+ } s;
+ struct cvmx_npi_bist_status_cn30xx {
+ uint64_t reserved_20_63:44;
+ uint64_t csr_bs:1;
+ uint64_t dif_bs:1;
+ uint64_t rdp_bs:1;
+ uint64_t pcnc_bs:1;
+ uint64_t pcn_bs:1;
+ uint64_t rdn_bs:1;
+ uint64_t pcac_bs:1;
+ uint64_t pcad_bs:1;
+ uint64_t rdnl_bs:1;
+ uint64_t pgf_bs:1;
+ uint64_t pig_bs:1;
+ uint64_t pof0_bs:1;
+ uint64_t reserved_5_7:3;
+ uint64_t pos_bs:1;
+ uint64_t nus_bs:1;
+ uint64_t dob_bs:1;
+ uint64_t pdf_bs:1;
+ uint64_t dpi_bs:1;
+ } cn30xx;
+ struct cvmx_npi_bist_status_s cn31xx;
+ struct cvmx_npi_bist_status_s cn38xx;
+ struct cvmx_npi_bist_status_s cn38xxp2;
+ struct cvmx_npi_bist_status_cn50xx {
+ uint64_t reserved_20_63:44;
+ uint64_t csr_bs:1;
+ uint64_t dif_bs:1;
+ uint64_t rdp_bs:1;
+ uint64_t pcnc_bs:1;
+ uint64_t pcn_bs:1;
+ uint64_t rdn_bs:1;
+ uint64_t pcac_bs:1;
+ uint64_t pcad_bs:1;
+ uint64_t rdnl_bs:1;
+ uint64_t pgf_bs:1;
+ uint64_t pig_bs:1;
+ uint64_t pof0_bs:1;
+ uint64_t pof1_bs:1;
+ uint64_t reserved_5_6:2;
+ uint64_t pos_bs:1;
+ uint64_t nus_bs:1;
+ uint64_t dob_bs:1;
+ uint64_t pdf_bs:1;
+ uint64_t dpi_bs:1;
+ } cn50xx;
+ struct cvmx_npi_bist_status_s cn58xx;
+ struct cvmx_npi_bist_status_s cn58xxp1;
+};
+
+union cvmx_npi_buff_size_outputx {
+ uint64_t u64;
+ struct cvmx_npi_buff_size_outputx_s {
+ uint64_t reserved_23_63:41;
+ uint64_t isize:7;
+ uint64_t bsize:16;
+ } s;
+ struct cvmx_npi_buff_size_outputx_s cn30xx;
+ struct cvmx_npi_buff_size_outputx_s cn31xx;
+ struct cvmx_npi_buff_size_outputx_s cn38xx;
+ struct cvmx_npi_buff_size_outputx_s cn38xxp2;
+ struct cvmx_npi_buff_size_outputx_s cn50xx;
+ struct cvmx_npi_buff_size_outputx_s cn58xx;
+ struct cvmx_npi_buff_size_outputx_s cn58xxp1;
+};
+
+union cvmx_npi_comp_ctl {
+ uint64_t u64;
+ struct cvmx_npi_comp_ctl_s {
+ uint64_t reserved_10_63:54;
+ uint64_t pctl:5;
+ uint64_t nctl:5;
+ } s;
+ struct cvmx_npi_comp_ctl_s cn50xx;
+ struct cvmx_npi_comp_ctl_s cn58xx;
+ struct cvmx_npi_comp_ctl_s cn58xxp1;
+};
+
+union cvmx_npi_ctl_status {
+ uint64_t u64;
+ struct cvmx_npi_ctl_status_s {
+ uint64_t reserved_63_63:1;
+ uint64_t chip_rev:8;
+ uint64_t dis_pniw:1;
+ uint64_t out3_enb:1;
+ uint64_t out2_enb:1;
+ uint64_t out1_enb:1;
+ uint64_t out0_enb:1;
+ uint64_t ins3_enb:1;
+ uint64_t ins2_enb:1;
+ uint64_t ins1_enb:1;
+ uint64_t ins0_enb:1;
+ uint64_t ins3_64b:1;
+ uint64_t ins2_64b:1;
+ uint64_t ins1_64b:1;
+ uint64_t ins0_64b:1;
+ uint64_t pci_wdis:1;
+ uint64_t wait_com:1;
+ uint64_t reserved_37_39:3;
+ uint64_t max_word:5;
+ uint64_t reserved_10_31:22;
+ uint64_t timer:10;
+ } s;
+ struct cvmx_npi_ctl_status_cn30xx {
+ uint64_t reserved_63_63:1;
+ uint64_t chip_rev:8;
+ uint64_t dis_pniw:1;
+ uint64_t reserved_51_53:3;
+ uint64_t out0_enb:1;
+ uint64_t reserved_47_49:3;
+ uint64_t ins0_enb:1;
+ uint64_t reserved_43_45:3;
+ uint64_t ins0_64b:1;
+ uint64_t pci_wdis:1;
+ uint64_t wait_com:1;
+ uint64_t reserved_37_39:3;
+ uint64_t max_word:5;
+ uint64_t reserved_10_31:22;
+ uint64_t timer:10;
+ } cn30xx;
+ struct cvmx_npi_ctl_status_cn31xx {
+ uint64_t reserved_63_63:1;
+ uint64_t chip_rev:8;
+ uint64_t dis_pniw:1;
+ uint64_t reserved_52_53:2;
+ uint64_t out1_enb:1;
+ uint64_t out0_enb:1;
+ uint64_t reserved_48_49:2;
+ uint64_t ins1_enb:1;
+ uint64_t ins0_enb:1;
+ uint64_t reserved_44_45:2;
+ uint64_t ins1_64b:1;
+ uint64_t ins0_64b:1;
+ uint64_t pci_wdis:1;
+ uint64_t wait_com:1;
+ uint64_t reserved_37_39:3;
+ uint64_t max_word:5;
+ uint64_t reserved_10_31:22;
+ uint64_t timer:10;
+ } cn31xx;
+ struct cvmx_npi_ctl_status_s cn38xx;
+ struct cvmx_npi_ctl_status_s cn38xxp2;
+ struct cvmx_npi_ctl_status_cn31xx cn50xx;
+ struct cvmx_npi_ctl_status_s cn58xx;
+ struct cvmx_npi_ctl_status_s cn58xxp1;
+};
+
+union cvmx_npi_dbg_select {
+ uint64_t u64;
+ struct cvmx_npi_dbg_select_s {
+ uint64_t reserved_16_63:48;
+ uint64_t dbg_sel:16;
+ } s;
+ struct cvmx_npi_dbg_select_s cn30xx;
+ struct cvmx_npi_dbg_select_s cn31xx;
+ struct cvmx_npi_dbg_select_s cn38xx;
+ struct cvmx_npi_dbg_select_s cn38xxp2;
+ struct cvmx_npi_dbg_select_s cn50xx;
+ struct cvmx_npi_dbg_select_s cn58xx;
+ struct cvmx_npi_dbg_select_s cn58xxp1;
+};
+
+union cvmx_npi_dma_control {
+ uint64_t u64;
+ struct cvmx_npi_dma_control_s {
+ uint64_t reserved_36_63:28;
+ uint64_t b0_lend:1;
+ uint64_t dwb_denb:1;
+ uint64_t dwb_ichk:9;
+ uint64_t fpa_que:3;
+ uint64_t o_add1:1;
+ uint64_t o_ro:1;
+ uint64_t o_ns:1;
+ uint64_t o_es:2;
+ uint64_t o_mode:1;
+ uint64_t hp_enb:1;
+ uint64_t lp_enb:1;
+ uint64_t csize:14;
+ } s;
+ struct cvmx_npi_dma_control_s cn30xx;
+ struct cvmx_npi_dma_control_s cn31xx;
+ struct cvmx_npi_dma_control_s cn38xx;
+ struct cvmx_npi_dma_control_s cn38xxp2;
+ struct cvmx_npi_dma_control_s cn50xx;
+ struct cvmx_npi_dma_control_s cn58xx;
+ struct cvmx_npi_dma_control_s cn58xxp1;
+};
+
+union cvmx_npi_dma_highp_counts {
+ uint64_t u64;
+ struct cvmx_npi_dma_highp_counts_s {
+ uint64_t reserved_39_63:25;
+ uint64_t fcnt:7;
+ uint64_t dbell:32;
+ } s;
+ struct cvmx_npi_dma_highp_counts_s cn30xx;
+ struct cvmx_npi_dma_highp_counts_s cn31xx;
+ struct cvmx_npi_dma_highp_counts_s cn38xx;
+ struct cvmx_npi_dma_highp_counts_s cn38xxp2;
+ struct cvmx_npi_dma_highp_counts_s cn50xx;
+ struct cvmx_npi_dma_highp_counts_s cn58xx;
+ struct cvmx_npi_dma_highp_counts_s cn58xxp1;
+};
+
+union cvmx_npi_dma_highp_naddr {
+ uint64_t u64;
+ struct cvmx_npi_dma_highp_naddr_s {
+ uint64_t reserved_40_63:24;
+ uint64_t state:4;
+ uint64_t addr:36;
+ } s;
+ struct cvmx_npi_dma_highp_naddr_s cn30xx;
+ struct cvmx_npi_dma_highp_naddr_s cn31xx;
+ struct cvmx_npi_dma_highp_naddr_s cn38xx;
+ struct cvmx_npi_dma_highp_naddr_s cn38xxp2;
+ struct cvmx_npi_dma_highp_naddr_s cn50xx;
+ struct cvmx_npi_dma_highp_naddr_s cn58xx;
+ struct cvmx_npi_dma_highp_naddr_s cn58xxp1;
+};
+
+union cvmx_npi_dma_lowp_counts {
+ uint64_t u64;
+ struct cvmx_npi_dma_lowp_counts_s {
+ uint64_t reserved_39_63:25;
+ uint64_t fcnt:7;
+ uint64_t dbell:32;
+ } s;
+ struct cvmx_npi_dma_lowp_counts_s cn30xx;
+ struct cvmx_npi_dma_lowp_counts_s cn31xx;
+ struct cvmx_npi_dma_lowp_counts_s cn38xx;
+ struct cvmx_npi_dma_lowp_counts_s cn38xxp2;
+ struct cvmx_npi_dma_lowp_counts_s cn50xx;
+ struct cvmx_npi_dma_lowp_counts_s cn58xx;
+ struct cvmx_npi_dma_lowp_counts_s cn58xxp1;
+};
+
+union cvmx_npi_dma_lowp_naddr {
+ uint64_t u64;
+ struct cvmx_npi_dma_lowp_naddr_s {
+ uint64_t reserved_40_63:24;
+ uint64_t state:4;
+ uint64_t addr:36;
+ } s;
+ struct cvmx_npi_dma_lowp_naddr_s cn30xx;
+ struct cvmx_npi_dma_lowp_naddr_s cn31xx;
+ struct cvmx_npi_dma_lowp_naddr_s cn38xx;
+ struct cvmx_npi_dma_lowp_naddr_s cn38xxp2;
+ struct cvmx_npi_dma_lowp_naddr_s cn50xx;
+ struct cvmx_npi_dma_lowp_naddr_s cn58xx;
+ struct cvmx_npi_dma_lowp_naddr_s cn58xxp1;
+};
+
+union cvmx_npi_highp_dbell {
+ uint64_t u64;
+ struct cvmx_npi_highp_dbell_s {
+ uint64_t reserved_16_63:48;
+ uint64_t dbell:16;
+ } s;
+ struct cvmx_npi_highp_dbell_s cn30xx;
+ struct cvmx_npi_highp_dbell_s cn31xx;
+ struct cvmx_npi_highp_dbell_s cn38xx;
+ struct cvmx_npi_highp_dbell_s cn38xxp2;
+ struct cvmx_npi_highp_dbell_s cn50xx;
+ struct cvmx_npi_highp_dbell_s cn58xx;
+ struct cvmx_npi_highp_dbell_s cn58xxp1;
+};
+
+union cvmx_npi_highp_ibuff_saddr {
+ uint64_t u64;
+ struct cvmx_npi_highp_ibuff_saddr_s {
+ uint64_t reserved_36_63:28;
+ uint64_t saddr:36;
+ } s;
+ struct cvmx_npi_highp_ibuff_saddr_s cn30xx;
+ struct cvmx_npi_highp_ibuff_saddr_s cn31xx;
+ struct cvmx_npi_highp_ibuff_saddr_s cn38xx;
+ struct cvmx_npi_highp_ibuff_saddr_s cn38xxp2;
+ struct cvmx_npi_highp_ibuff_saddr_s cn50xx;
+ struct cvmx_npi_highp_ibuff_saddr_s cn58xx;
+ struct cvmx_npi_highp_ibuff_saddr_s cn58xxp1;
+};
+
+union cvmx_npi_input_control {
+ uint64_t u64;
+ struct cvmx_npi_input_control_s {
+ uint64_t reserved_23_63:41;
+ uint64_t pkt_rr:1;
+ uint64_t pbp_dhi:13;
+ uint64_t d_nsr:1;
+ uint64_t d_esr:2;
+ uint64_t d_ror:1;
+ uint64_t use_csr:1;
+ uint64_t nsr:1;
+ uint64_t esr:2;
+ uint64_t ror:1;
+ } s;
+ struct cvmx_npi_input_control_cn30xx {
+ uint64_t reserved_22_63:42;
+ uint64_t pbp_dhi:13;
+ uint64_t d_nsr:1;
+ uint64_t d_esr:2;
+ uint64_t d_ror:1;
+ uint64_t use_csr:1;
+ uint64_t nsr:1;
+ uint64_t esr:2;
+ uint64_t ror:1;
+ } cn30xx;
+ struct cvmx_npi_input_control_cn30xx cn31xx;
+ struct cvmx_npi_input_control_s cn38xx;
+ struct cvmx_npi_input_control_cn30xx cn38xxp2;
+ struct cvmx_npi_input_control_s cn50xx;
+ struct cvmx_npi_input_control_s cn58xx;
+ struct cvmx_npi_input_control_s cn58xxp1;
+};
+
+union cvmx_npi_int_enb {
+ uint64_t u64;
+ struct cvmx_npi_int_enb_s {
+ uint64_t reserved_62_63:2;
+ uint64_t q1_a_f:1;
+ uint64_t q1_s_e:1;
+ uint64_t pdf_p_f:1;
+ uint64_t pdf_p_e:1;
+ uint64_t pcf_p_f:1;
+ uint64_t pcf_p_e:1;
+ uint64_t rdx_s_e:1;
+ uint64_t rwx_s_e:1;
+ uint64_t pnc_a_f:1;
+ uint64_t pnc_s_e:1;
+ uint64_t com_a_f:1;
+ uint64_t com_s_e:1;
+ uint64_t q3_a_f:1;
+ uint64_t q3_s_e:1;
+ uint64_t q2_a_f:1;
+ uint64_t q2_s_e:1;
+ uint64_t pcr_a_f:1;
+ uint64_t pcr_s_e:1;
+ uint64_t fcr_a_f:1;
+ uint64_t fcr_s_e:1;
+ uint64_t iobdma:1;
+ uint64_t p_dperr:1;
+ uint64_t win_rto:1;
+ uint64_t i3_pperr:1;
+ uint64_t i2_pperr:1;
+ uint64_t i1_pperr:1;
+ uint64_t i0_pperr:1;
+ uint64_t p3_ptout:1;
+ uint64_t p2_ptout:1;
+ uint64_t p1_ptout:1;
+ uint64_t p0_ptout:1;
+ uint64_t p3_pperr:1;
+ uint64_t p2_pperr:1;
+ uint64_t p1_pperr:1;
+ uint64_t p0_pperr:1;
+ uint64_t g3_rtout:1;
+ uint64_t g2_rtout:1;
+ uint64_t g1_rtout:1;
+ uint64_t g0_rtout:1;
+ uint64_t p3_perr:1;
+ uint64_t p2_perr:1;
+ uint64_t p1_perr:1;
+ uint64_t p0_perr:1;
+ uint64_t p3_rtout:1;
+ uint64_t p2_rtout:1;
+ uint64_t p1_rtout:1;
+ uint64_t p0_rtout:1;
+ uint64_t i3_overf:1;
+ uint64_t i2_overf:1;
+ uint64_t i1_overf:1;
+ uint64_t i0_overf:1;
+ uint64_t i3_rtout:1;
+ uint64_t i2_rtout:1;
+ uint64_t i1_rtout:1;
+ uint64_t i0_rtout:1;
+ uint64_t po3_2sml:1;
+ uint64_t po2_2sml:1;
+ uint64_t po1_2sml:1;
+ uint64_t po0_2sml:1;
+ uint64_t pci_rsl:1;
+ uint64_t rml_wto:1;
+ uint64_t rml_rto:1;
+ } s;
+ struct cvmx_npi_int_enb_cn30xx {
+ uint64_t reserved_62_63:2;
+ uint64_t q1_a_f:1;
+ uint64_t q1_s_e:1;
+ uint64_t pdf_p_f:1;
+ uint64_t pdf_p_e:1;
+ uint64_t pcf_p_f:1;
+ uint64_t pcf_p_e:1;
+ uint64_t rdx_s_e:1;
+ uint64_t rwx_s_e:1;
+ uint64_t pnc_a_f:1;
+ uint64_t pnc_s_e:1;
+ uint64_t com_a_f:1;
+ uint64_t com_s_e:1;
+ uint64_t q3_a_f:1;
+ uint64_t q3_s_e:1;
+ uint64_t q2_a_f:1;
+ uint64_t q2_s_e:1;
+ uint64_t pcr_a_f:1;
+ uint64_t pcr_s_e:1;
+ uint64_t fcr_a_f:1;
+ uint64_t fcr_s_e:1;
+ uint64_t iobdma:1;
+ uint64_t p_dperr:1;
+ uint64_t win_rto:1;
+ uint64_t reserved_36_38:3;
+ uint64_t i0_pperr:1;
+ uint64_t reserved_32_34:3;
+ uint64_t p0_ptout:1;
+ uint64_t reserved_28_30:3;
+ uint64_t p0_pperr:1;
+ uint64_t reserved_24_26:3;
+ uint64_t g0_rtout:1;
+ uint64_t reserved_20_22:3;
+ uint64_t p0_perr:1;
+ uint64_t reserved_16_18:3;
+ uint64_t p0_rtout:1;
+ uint64_t reserved_12_14:3;
+ uint64_t i0_overf:1;
+ uint64_t reserved_8_10:3;
+ uint64_t i0_rtout:1;
+ uint64_t reserved_4_6:3;
+ uint64_t po0_2sml:1;
+ uint64_t pci_rsl:1;
+ uint64_t rml_wto:1;
+ uint64_t rml_rto:1;
+ } cn30xx;
+ struct cvmx_npi_int_enb_cn31xx {
+ uint64_t reserved_62_63:2;
+ uint64_t q1_a_f:1;
+ uint64_t q1_s_e:1;
+ uint64_t pdf_p_f:1;
+ uint64_t pdf_p_e:1;
+ uint64_t pcf_p_f:1;
+ uint64_t pcf_p_e:1;
+ uint64_t rdx_s_e:1;
+ uint64_t rwx_s_e:1;
+ uint64_t pnc_a_f:1;
+ uint64_t pnc_s_e:1;
+ uint64_t com_a_f:1;
+ uint64_t com_s_e:1;
+ uint64_t q3_a_f:1;
+ uint64_t q3_s_e:1;
+ uint64_t q2_a_f:1;
+ uint64_t q2_s_e:1;
+ uint64_t pcr_a_f:1;
+ uint64_t pcr_s_e:1;
+ uint64_t fcr_a_f:1;
+ uint64_t fcr_s_e:1;
+ uint64_t iobdma:1;
+ uint64_t p_dperr:1;
+ uint64_t win_rto:1;
+ uint64_t reserved_37_38:2;
+ uint64_t i1_pperr:1;
+ uint64_t i0_pperr:1;
+ uint64_t reserved_33_34:2;
+ uint64_t p1_ptout:1;
+ uint64_t p0_ptout:1;
+ uint64_t reserved_29_30:2;
+ uint64_t p1_pperr:1;
+ uint64_t p0_pperr:1;
+ uint64_t reserved_25_26:2;
+ uint64_t g1_rtout:1;
+ uint64_t g0_rtout:1;
+ uint64_t reserved_21_22:2;
+ uint64_t p1_perr:1;
+ uint64_t p0_perr:1;
+ uint64_t reserved_17_18:2;
+ uint64_t p1_rtout:1;
+ uint64_t p0_rtout:1;
+ uint64_t reserved_13_14:2;
+ uint64_t i1_overf:1;
+ uint64_t i0_overf:1;
+ uint64_t reserved_9_10:2;
+ uint64_t i1_rtout:1;
+ uint64_t i0_rtout:1;
+ uint64_t reserved_5_6:2;
+ uint64_t po1_2sml:1;
+ uint64_t po0_2sml:1;
+ uint64_t pci_rsl:1;
+ uint64_t rml_wto:1;
+ uint64_t rml_rto:1;
+ } cn31xx;
+ struct cvmx_npi_int_enb_s cn38xx;
+ struct cvmx_npi_int_enb_cn38xxp2 {
+ uint64_t reserved_42_63:22;
+ uint64_t iobdma:1;
+ uint64_t p_dperr:1;
+ uint64_t win_rto:1;
+ uint64_t i3_pperr:1;
+ uint64_t i2_pperr:1;
+ uint64_t i1_pperr:1;
+ uint64_t i0_pperr:1;
+ uint64_t p3_ptout:1;
+ uint64_t p2_ptout:1;
+ uint64_t p1_ptout:1;
+ uint64_t p0_ptout:1;
+ uint64_t p3_pperr:1;
+ uint64_t p2_pperr:1;
+ uint64_t p1_pperr:1;
+ uint64_t p0_pperr:1;
+ uint64_t g3_rtout:1;
+ uint64_t g2_rtout:1;
+ uint64_t g1_rtout:1;
+ uint64_t g0_rtout:1;
+ uint64_t p3_perr:1;
+ uint64_t p2_perr:1;
+ uint64_t p1_perr:1;
+ uint64_t p0_perr:1;
+ uint64_t p3_rtout:1;
+ uint64_t p2_rtout:1;
+ uint64_t p1_rtout:1;
+ uint64_t p0_rtout:1;
+ uint64_t i3_overf:1;
+ uint64_t i2_overf:1;
+ uint64_t i1_overf:1;
+ uint64_t i0_overf:1;
+ uint64_t i3_rtout:1;
+ uint64_t i2_rtout:1;
+ uint64_t i1_rtout:1;
+ uint64_t i0_rtout:1;
+ uint64_t po3_2sml:1;
+ uint64_t po2_2sml:1;
+ uint64_t po1_2sml:1;
+ uint64_t po0_2sml:1;
+ uint64_t pci_rsl:1;
+ uint64_t rml_wto:1;
+ uint64_t rml_rto:1;
+ } cn38xxp2;
+ struct cvmx_npi_int_enb_cn31xx cn50xx;
+ struct cvmx_npi_int_enb_s cn58xx;
+ struct cvmx_npi_int_enb_s cn58xxp1;
+};
+
+union cvmx_npi_int_sum {
+ uint64_t u64;
+ struct cvmx_npi_int_sum_s {
+ uint64_t reserved_62_63:2;
+ uint64_t q1_a_f:1;
+ uint64_t q1_s_e:1;
+ uint64_t pdf_p_f:1;
+ uint64_t pdf_p_e:1;
+ uint64_t pcf_p_f:1;
+ uint64_t pcf_p_e:1;
+ uint64_t rdx_s_e:1;
+ uint64_t rwx_s_e:1;
+ uint64_t pnc_a_f:1;
+ uint64_t pnc_s_e:1;
+ uint64_t com_a_f:1;
+ uint64_t com_s_e:1;
+ uint64_t q3_a_f:1;
+ uint64_t q3_s_e:1;
+ uint64_t q2_a_f:1;
+ uint64_t q2_s_e:1;
+ uint64_t pcr_a_f:1;
+ uint64_t pcr_s_e:1;
+ uint64_t fcr_a_f:1;
+ uint64_t fcr_s_e:1;
+ uint64_t iobdma:1;
+ uint64_t p_dperr:1;
+ uint64_t win_rto:1;
+ uint64_t i3_pperr:1;
+ uint64_t i2_pperr:1;
+ uint64_t i1_pperr:1;
+ uint64_t i0_pperr:1;
+ uint64_t p3_ptout:1;
+ uint64_t p2_ptout:1;
+ uint64_t p1_ptout:1;
+ uint64_t p0_ptout:1;
+ uint64_t p3_pperr:1;
+ uint64_t p2_pperr:1;
+ uint64_t p1_pperr:1;
+ uint64_t p0_pperr:1;
+ uint64_t g3_rtout:1;
+ uint64_t g2_rtout:1;
+ uint64_t g1_rtout:1;
+ uint64_t g0_rtout:1;
+ uint64_t p3_perr:1;
+ uint64_t p2_perr:1;
+ uint64_t p1_perr:1;
+ uint64_t p0_perr:1;
+ uint64_t p3_rtout:1;
+ uint64_t p2_rtout:1;
+ uint64_t p1_rtout:1;
+ uint64_t p0_rtout:1;
+ uint64_t i3_overf:1;
+ uint64_t i2_overf:1;
+ uint64_t i1_overf:1;
+ uint64_t i0_overf:1;
+ uint64_t i3_rtout:1;
+ uint64_t i2_rtout:1;
+ uint64_t i1_rtout:1;
+ uint64_t i0_rtout:1;
+ uint64_t po3_2sml:1;
+ uint64_t po2_2sml:1;
+ uint64_t po1_2sml:1;
+ uint64_t po0_2sml:1;
+ uint64_t pci_rsl:1;
+ uint64_t rml_wto:1;
+ uint64_t rml_rto:1;
+ } s;
+ struct cvmx_npi_int_sum_cn30xx {
+ uint64_t reserved_62_63:2;
+ uint64_t q1_a_f:1;
+ uint64_t q1_s_e:1;
+ uint64_t pdf_p_f:1;
+ uint64_t pdf_p_e:1;
+ uint64_t pcf_p_f:1;
+ uint64_t pcf_p_e:1;
+ uint64_t rdx_s_e:1;
+ uint64_t rwx_s_e:1;
+ uint64_t pnc_a_f:1;
+ uint64_t pnc_s_e:1;
+ uint64_t com_a_f:1;
+ uint64_t com_s_e:1;
+ uint64_t q3_a_f:1;
+ uint64_t q3_s_e:1;
+ uint64_t q2_a_f:1;
+ uint64_t q2_s_e:1;
+ uint64_t pcr_a_f:1;
+ uint64_t pcr_s_e:1;
+ uint64_t fcr_a_f:1;
+ uint64_t fcr_s_e:1;
+ uint64_t iobdma:1;
+ uint64_t p_dperr:1;
+ uint64_t win_rto:1;
+ uint64_t reserved_36_38:3;
+ uint64_t i0_pperr:1;
+ uint64_t reserved_32_34:3;
+ uint64_t p0_ptout:1;
+ uint64_t reserved_28_30:3;
+ uint64_t p0_pperr:1;
+ uint64_t reserved_24_26:3;
+ uint64_t g0_rtout:1;
+ uint64_t reserved_20_22:3;
+ uint64_t p0_perr:1;
+ uint64_t reserved_16_18:3;
+ uint64_t p0_rtout:1;
+ uint64_t reserved_12_14:3;
+ uint64_t i0_overf:1;
+ uint64_t reserved_8_10:3;
+ uint64_t i0_rtout:1;
+ uint64_t reserved_4_6:3;
+ uint64_t po0_2sml:1;
+ uint64_t pci_rsl:1;
+ uint64_t rml_wto:1;
+ uint64_t rml_rto:1;
+ } cn30xx;
+ struct cvmx_npi_int_sum_cn31xx {
+ uint64_t reserved_62_63:2;
+ uint64_t q1_a_f:1;
+ uint64_t q1_s_e:1;
+ uint64_t pdf_p_f:1;
+ uint64_t pdf_p_e:1;
+ uint64_t pcf_p_f:1;
+ uint64_t pcf_p_e:1;
+ uint64_t rdx_s_e:1;
+ uint64_t rwx_s_e:1;
+ uint64_t pnc_a_f:1;
+ uint64_t pnc_s_e:1;
+ uint64_t com_a_f:1;
+ uint64_t com_s_e:1;
+ uint64_t q3_a_f:1;
+ uint64_t q3_s_e:1;
+ uint64_t q2_a_f:1;
+ uint64_t q2_s_e:1;
+ uint64_t pcr_a_f:1;
+ uint64_t pcr_s_e:1;
+ uint64_t fcr_a_f:1;
+ uint64_t fcr_s_e:1;
+ uint64_t iobdma:1;
+ uint64_t p_dperr:1;
+ uint64_t win_rto:1;
+ uint64_t reserved_37_38:2;
+ uint64_t i1_pperr:1;
+ uint64_t i0_pperr:1;
+ uint64_t reserved_33_34:2;
+ uint64_t p1_ptout:1;
+ uint64_t p0_ptout:1;
+ uint64_t reserved_29_30:2;
+ uint64_t p1_pperr:1;
+ uint64_t p0_pperr:1;
+ uint64_t reserved_25_26:2;
+ uint64_t g1_rtout:1;
+ uint64_t g0_rtout:1;
+ uint64_t reserved_21_22:2;
+ uint64_t p1_perr:1;
+ uint64_t p0_perr:1;
+ uint64_t reserved_17_18:2;
+ uint64_t p1_rtout:1;
+ uint64_t p0_rtout:1;
+ uint64_t reserved_13_14:2;
+ uint64_t i1_overf:1;
+ uint64_t i0_overf:1;
+ uint64_t reserved_9_10:2;
+ uint64_t i1_rtout:1;
+ uint64_t i0_rtout:1;
+ uint64_t reserved_5_6:2;
+ uint64_t po1_2sml:1;
+ uint64_t po0_2sml:1;
+ uint64_t pci_rsl:1;
+ uint64_t rml_wto:1;
+ uint64_t rml_rto:1;
+ } cn31xx;
+ struct cvmx_npi_int_sum_s cn38xx;
+ struct cvmx_npi_int_sum_cn38xxp2 {
+ uint64_t reserved_42_63:22;
+ uint64_t iobdma:1;
+ uint64_t p_dperr:1;
+ uint64_t win_rto:1;
+ uint64_t i3_pperr:1;
+ uint64_t i2_pperr:1;
+ uint64_t i1_pperr:1;
+ uint64_t i0_pperr:1;
+ uint64_t p3_ptout:1;
+ uint64_t p2_ptout:1;
+ uint64_t p1_ptout:1;
+ uint64_t p0_ptout:1;
+ uint64_t p3_pperr:1;
+ uint64_t p2_pperr:1;
+ uint64_t p1_pperr:1;
+ uint64_t p0_pperr:1;
+ uint64_t g3_rtout:1;
+ uint64_t g2_rtout:1;
+ uint64_t g1_rtout:1;
+ uint64_t g0_rtout:1;
+ uint64_t p3_perr:1;
+ uint64_t p2_perr:1;
+ uint64_t p1_perr:1;
+ uint64_t p0_perr:1;
+ uint64_t p3_rtout:1;
+ uint64_t p2_rtout:1;
+ uint64_t p1_rtout:1;
+ uint64_t p0_rtout:1;
+ uint64_t i3_overf:1;
+ uint64_t i2_overf:1;
+ uint64_t i1_overf:1;
+ uint64_t i0_overf:1;
+ uint64_t i3_rtout:1;
+ uint64_t i2_rtout:1;
+ uint64_t i1_rtout:1;
+ uint64_t i0_rtout:1;
+ uint64_t po3_2sml:1;
+ uint64_t po2_2sml:1;
+ uint64_t po1_2sml:1;
+ uint64_t po0_2sml:1;
+ uint64_t pci_rsl:1;
+ uint64_t rml_wto:1;
+ uint64_t rml_rto:1;
+ } cn38xxp2;
+ struct cvmx_npi_int_sum_cn31xx cn50xx;
+ struct cvmx_npi_int_sum_s cn58xx;
+ struct cvmx_npi_int_sum_s cn58xxp1;
+};
+
+union cvmx_npi_lowp_dbell {
+ uint64_t u64;
+ struct cvmx_npi_lowp_dbell_s {
+ uint64_t reserved_16_63:48;
+ uint64_t dbell:16;
+ } s;
+ struct cvmx_npi_lowp_dbell_s cn30xx;
+ struct cvmx_npi_lowp_dbell_s cn31xx;
+ struct cvmx_npi_lowp_dbell_s cn38xx;
+ struct cvmx_npi_lowp_dbell_s cn38xxp2;
+ struct cvmx_npi_lowp_dbell_s cn50xx;
+ struct cvmx_npi_lowp_dbell_s cn58xx;
+ struct cvmx_npi_lowp_dbell_s cn58xxp1;
+};
+
+union cvmx_npi_lowp_ibuff_saddr {
+ uint64_t u64;
+ struct cvmx_npi_lowp_ibuff_saddr_s {
+ uint64_t reserved_36_63:28;
+ uint64_t saddr:36;
+ } s;
+ struct cvmx_npi_lowp_ibuff_saddr_s cn30xx;
+ struct cvmx_npi_lowp_ibuff_saddr_s cn31xx;
+ struct cvmx_npi_lowp_ibuff_saddr_s cn38xx;
+ struct cvmx_npi_lowp_ibuff_saddr_s cn38xxp2;
+ struct cvmx_npi_lowp_ibuff_saddr_s cn50xx;
+ struct cvmx_npi_lowp_ibuff_saddr_s cn58xx;
+ struct cvmx_npi_lowp_ibuff_saddr_s cn58xxp1;
+};
+
+union cvmx_npi_mem_access_subidx {
+ uint64_t u64;
+ struct cvmx_npi_mem_access_subidx_s {
+ uint64_t reserved_38_63:26;
+ uint64_t shortl:1;
+ uint64_t nmerge:1;
+ uint64_t esr:2;
+ uint64_t esw:2;
+ uint64_t nsr:1;
+ uint64_t nsw:1;
+ uint64_t ror:1;
+ uint64_t row:1;
+ uint64_t ba:28;
+ } s;
+ struct cvmx_npi_mem_access_subidx_s cn30xx;
+ struct cvmx_npi_mem_access_subidx_cn31xx {
+ uint64_t reserved_36_63:28;
+ uint64_t esr:2;
+ uint64_t esw:2;
+ uint64_t nsr:1;
+ uint64_t nsw:1;
+ uint64_t ror:1;
+ uint64_t row:1;
+ uint64_t ba:28;
+ } cn31xx;
+ struct cvmx_npi_mem_access_subidx_s cn38xx;
+ struct cvmx_npi_mem_access_subidx_cn31xx cn38xxp2;
+ struct cvmx_npi_mem_access_subidx_s cn50xx;
+ struct cvmx_npi_mem_access_subidx_s cn58xx;
+ struct cvmx_npi_mem_access_subidx_s cn58xxp1;
+};
+
+union cvmx_npi_msi_rcv {
+ uint64_t u64;
+ struct cvmx_npi_msi_rcv_s {
+ uint64_t int_vec:64;
+ } s;
+ struct cvmx_npi_msi_rcv_s cn30xx;
+ struct cvmx_npi_msi_rcv_s cn31xx;
+ struct cvmx_npi_msi_rcv_s cn38xx;
+ struct cvmx_npi_msi_rcv_s cn38xxp2;
+ struct cvmx_npi_msi_rcv_s cn50xx;
+ struct cvmx_npi_msi_rcv_s cn58xx;
+ struct cvmx_npi_msi_rcv_s cn58xxp1;
+};
+
+union cvmx_npi_num_desc_outputx {
+ uint64_t u64;
+ struct cvmx_npi_num_desc_outputx_s {
+ uint64_t reserved_32_63:32;
+ uint64_t size:32;
+ } s;
+ struct cvmx_npi_num_desc_outputx_s cn30xx;
+ struct cvmx_npi_num_desc_outputx_s cn31xx;
+ struct cvmx_npi_num_desc_outputx_s cn38xx;
+ struct cvmx_npi_num_desc_outputx_s cn38xxp2;
+ struct cvmx_npi_num_desc_outputx_s cn50xx;
+ struct cvmx_npi_num_desc_outputx_s cn58xx;
+ struct cvmx_npi_num_desc_outputx_s cn58xxp1;
+};
+
+union cvmx_npi_output_control {
+ uint64_t u64;
+ struct cvmx_npi_output_control_s {
+ uint64_t reserved_49_63:15;
+ uint64_t pkt_rr:1;
+ uint64_t p3_bmode:1;
+ uint64_t p2_bmode:1;
+ uint64_t p1_bmode:1;
+ uint64_t p0_bmode:1;
+ uint64_t o3_es:2;
+ uint64_t o3_ns:1;
+ uint64_t o3_ro:1;
+ uint64_t o2_es:2;
+ uint64_t o2_ns:1;
+ uint64_t o2_ro:1;
+ uint64_t o1_es:2;
+ uint64_t o1_ns:1;
+ uint64_t o1_ro:1;
+ uint64_t o0_es:2;
+ uint64_t o0_ns:1;
+ uint64_t o0_ro:1;
+ uint64_t o3_csrm:1;
+ uint64_t o2_csrm:1;
+ uint64_t o1_csrm:1;
+ uint64_t o0_csrm:1;
+ uint64_t reserved_20_23:4;
+ uint64_t iptr_o3:1;
+ uint64_t iptr_o2:1;
+ uint64_t iptr_o1:1;
+ uint64_t iptr_o0:1;
+ uint64_t esr_sl3:2;
+ uint64_t nsr_sl3:1;
+ uint64_t ror_sl3:1;
+ uint64_t esr_sl2:2;
+ uint64_t nsr_sl2:1;
+ uint64_t ror_sl2:1;
+ uint64_t esr_sl1:2;
+ uint64_t nsr_sl1:1;
+ uint64_t ror_sl1:1;
+ uint64_t esr_sl0:2;
+ uint64_t nsr_sl0:1;
+ uint64_t ror_sl0:1;
+ } s;
+ struct cvmx_npi_output_control_cn30xx {
+ uint64_t reserved_45_63:19;
+ uint64_t p0_bmode:1;
+ uint64_t reserved_32_43:12;
+ uint64_t o0_es:2;
+ uint64_t o0_ns:1;
+ uint64_t o0_ro:1;
+ uint64_t reserved_25_27:3;
+ uint64_t o0_csrm:1;
+ uint64_t reserved_17_23:7;
+ uint64_t iptr_o0:1;
+ uint64_t reserved_4_15:12;
+ uint64_t esr_sl0:2;
+ uint64_t nsr_sl0:1;
+ uint64_t ror_sl0:1;
+ } cn30xx;
+ struct cvmx_npi_output_control_cn31xx {
+ uint64_t reserved_46_63:18;
+ uint64_t p1_bmode:1;
+ uint64_t p0_bmode:1;
+ uint64_t reserved_36_43:8;
+ uint64_t o1_es:2;
+ uint64_t o1_ns:1;
+ uint64_t o1_ro:1;
+ uint64_t o0_es:2;
+ uint64_t o0_ns:1;
+ uint64_t o0_ro:1;
+ uint64_t reserved_26_27:2;
+ uint64_t o1_csrm:1;
+ uint64_t o0_csrm:1;
+ uint64_t reserved_18_23:6;
+ uint64_t iptr_o1:1;
+ uint64_t iptr_o0:1;
+ uint64_t reserved_8_15:8;
+ uint64_t esr_sl1:2;
+ uint64_t nsr_sl1:1;
+ uint64_t ror_sl1:1;
+ uint64_t esr_sl0:2;
+ uint64_t nsr_sl0:1;
+ uint64_t ror_sl0:1;
+ } cn31xx;
+ struct cvmx_npi_output_control_s cn38xx;
+ struct cvmx_npi_output_control_cn38xxp2 {
+ uint64_t reserved_48_63:16;
+ uint64_t p3_bmode:1;
+ uint64_t p2_bmode:1;
+ uint64_t p1_bmode:1;
+ uint64_t p0_bmode:1;
+ uint64_t o3_es:2;
+ uint64_t o3_ns:1;
+ uint64_t o3_ro:1;
+ uint64_t o2_es:2;
+ uint64_t o2_ns:1;
+ uint64_t o2_ro:1;
+ uint64_t o1_es:2;
+ uint64_t o1_ns:1;
+ uint64_t o1_ro:1;
+ uint64_t o0_es:2;
+ uint64_t o0_ns:1;
+ uint64_t o0_ro:1;
+ uint64_t o3_csrm:1;
+ uint64_t o2_csrm:1;
+ uint64_t o1_csrm:1;
+ uint64_t o0_csrm:1;
+ uint64_t reserved_20_23:4;
+ uint64_t iptr_o3:1;
+ uint64_t iptr_o2:1;
+ uint64_t iptr_o1:1;
+ uint64_t iptr_o0:1;
+ uint64_t esr_sl3:2;
+ uint64_t nsr_sl3:1;
+ uint64_t ror_sl3:1;
+ uint64_t esr_sl2:2;
+ uint64_t nsr_sl2:1;
+ uint64_t ror_sl2:1;
+ uint64_t esr_sl1:2;
+ uint64_t nsr_sl1:1;
+ uint64_t ror_sl1:1;
+ uint64_t esr_sl0:2;
+ uint64_t nsr_sl0:1;
+ uint64_t ror_sl0:1;
+ } cn38xxp2;
+ struct cvmx_npi_output_control_cn50xx {
+ uint64_t reserved_49_63:15;
+ uint64_t pkt_rr:1;
+ uint64_t reserved_46_47:2;
+ uint64_t p1_bmode:1;
+ uint64_t p0_bmode:1;
+ uint64_t reserved_36_43:8;
+ uint64_t o1_es:2;
+ uint64_t o1_ns:1;
+ uint64_t o1_ro:1;
+ uint64_t o0_es:2;
+ uint64_t o0_ns:1;
+ uint64_t o0_ro:1;
+ uint64_t reserved_26_27:2;
+ uint64_t o1_csrm:1;
+ uint64_t o0_csrm:1;
+ uint64_t reserved_18_23:6;
+ uint64_t iptr_o1:1;
+ uint64_t iptr_o0:1;
+ uint64_t reserved_8_15:8;
+ uint64_t esr_sl1:2;
+ uint64_t nsr_sl1:1;
+ uint64_t ror_sl1:1;
+ uint64_t esr_sl0:2;
+ uint64_t nsr_sl0:1;
+ uint64_t ror_sl0:1;
+ } cn50xx;
+ struct cvmx_npi_output_control_s cn58xx;
+ struct cvmx_npi_output_control_s cn58xxp1;
+};
+
+union cvmx_npi_px_dbpair_addr {
+ uint64_t u64;
+ struct cvmx_npi_px_dbpair_addr_s {
+ uint64_t reserved_63_63:1;
+ uint64_t state:2;
+ uint64_t naddr:61;
+ } s;
+ struct cvmx_npi_px_dbpair_addr_s cn30xx;
+ struct cvmx_npi_px_dbpair_addr_s cn31xx;
+ struct cvmx_npi_px_dbpair_addr_s cn38xx;
+ struct cvmx_npi_px_dbpair_addr_s cn38xxp2;
+ struct cvmx_npi_px_dbpair_addr_s cn50xx;
+ struct cvmx_npi_px_dbpair_addr_s cn58xx;
+ struct cvmx_npi_px_dbpair_addr_s cn58xxp1;
+};
+
+union cvmx_npi_px_instr_addr {
+ uint64_t u64;
+ struct cvmx_npi_px_instr_addr_s {
+ uint64_t state:3;
+ uint64_t naddr:61;
+ } s;
+ struct cvmx_npi_px_instr_addr_s cn30xx;
+ struct cvmx_npi_px_instr_addr_s cn31xx;
+ struct cvmx_npi_px_instr_addr_s cn38xx;
+ struct cvmx_npi_px_instr_addr_s cn38xxp2;
+ struct cvmx_npi_px_instr_addr_s cn50xx;
+ struct cvmx_npi_px_instr_addr_s cn58xx;
+ struct cvmx_npi_px_instr_addr_s cn58xxp1;
+};
+
+union cvmx_npi_px_instr_cnts {
+ uint64_t u64;
+ struct cvmx_npi_px_instr_cnts_s {
+ uint64_t reserved_38_63:26;
+ uint64_t fcnt:6;
+ uint64_t avail:32;
+ } s;
+ struct cvmx_npi_px_instr_cnts_s cn30xx;
+ struct cvmx_npi_px_instr_cnts_s cn31xx;
+ struct cvmx_npi_px_instr_cnts_s cn38xx;
+ struct cvmx_npi_px_instr_cnts_s cn38xxp2;
+ struct cvmx_npi_px_instr_cnts_s cn50xx;
+ struct cvmx_npi_px_instr_cnts_s cn58xx;
+ struct cvmx_npi_px_instr_cnts_s cn58xxp1;
+};
+
+union cvmx_npi_px_pair_cnts {
+ uint64_t u64;
+ struct cvmx_npi_px_pair_cnts_s {
+ uint64_t reserved_37_63:27;
+ uint64_t fcnt:5;
+ uint64_t avail:32;
+ } s;
+ struct cvmx_npi_px_pair_cnts_s cn30xx;
+ struct cvmx_npi_px_pair_cnts_s cn31xx;
+ struct cvmx_npi_px_pair_cnts_s cn38xx;
+ struct cvmx_npi_px_pair_cnts_s cn38xxp2;
+ struct cvmx_npi_px_pair_cnts_s cn50xx;
+ struct cvmx_npi_px_pair_cnts_s cn58xx;
+ struct cvmx_npi_px_pair_cnts_s cn58xxp1;
+};
+
+union cvmx_npi_pci_burst_size {
+ uint64_t u64;
+ struct cvmx_npi_pci_burst_size_s {
+ uint64_t reserved_14_63:50;
+ uint64_t wr_brst:7;
+ uint64_t rd_brst:7;
+ } s;
+ struct cvmx_npi_pci_burst_size_s cn30xx;
+ struct cvmx_npi_pci_burst_size_s cn31xx;
+ struct cvmx_npi_pci_burst_size_s cn38xx;
+ struct cvmx_npi_pci_burst_size_s cn38xxp2;
+ struct cvmx_npi_pci_burst_size_s cn50xx;
+ struct cvmx_npi_pci_burst_size_s cn58xx;
+ struct cvmx_npi_pci_burst_size_s cn58xxp1;
+};
+
+union cvmx_npi_pci_int_arb_cfg {
+ uint64_t u64;
+ struct cvmx_npi_pci_int_arb_cfg_s {
+ uint64_t reserved_13_63:51;
+ uint64_t hostmode:1;
+ uint64_t pci_ovr:4;
+ uint64_t reserved_5_7:3;
+ uint64_t en:1;
+ uint64_t park_mod:1;
+ uint64_t park_dev:3;
+ } s;
+ struct cvmx_npi_pci_int_arb_cfg_cn30xx {
+ uint64_t reserved_5_63:59;
+ uint64_t en:1;
+ uint64_t park_mod:1;
+ uint64_t park_dev:3;
+ } cn30xx;
+ struct cvmx_npi_pci_int_arb_cfg_cn30xx cn31xx;
+ struct cvmx_npi_pci_int_arb_cfg_cn30xx cn38xx;
+ struct cvmx_npi_pci_int_arb_cfg_cn30xx cn38xxp2;
+ struct cvmx_npi_pci_int_arb_cfg_s cn50xx;
+ struct cvmx_npi_pci_int_arb_cfg_s cn58xx;
+ struct cvmx_npi_pci_int_arb_cfg_s cn58xxp1;
+};
+
+union cvmx_npi_pci_read_cmd {
+ uint64_t u64;
+ struct cvmx_npi_pci_read_cmd_s {
+ uint64_t reserved_11_63:53;
+ uint64_t cmd_size:11;
+ } s;
+ struct cvmx_npi_pci_read_cmd_s cn30xx;
+ struct cvmx_npi_pci_read_cmd_s cn31xx;
+ struct cvmx_npi_pci_read_cmd_s cn38xx;
+ struct cvmx_npi_pci_read_cmd_s cn38xxp2;
+ struct cvmx_npi_pci_read_cmd_s cn50xx;
+ struct cvmx_npi_pci_read_cmd_s cn58xx;
+ struct cvmx_npi_pci_read_cmd_s cn58xxp1;
+};
+
+union cvmx_npi_port32_instr_hdr {
+ uint64_t u64;
+ struct cvmx_npi_port32_instr_hdr_s {
+ uint64_t reserved_44_63:20;
+ uint64_t pbp:1;
+ uint64_t rsv_f:5;
+ uint64_t rparmode:2;
+ uint64_t rsv_e:1;
+ uint64_t rskp_len:7;
+ uint64_t rsv_d:6;
+ uint64_t use_ihdr:1;
+ uint64_t rsv_c:5;
+ uint64_t par_mode:2;
+ uint64_t rsv_b:1;
+ uint64_t skp_len:7;
+ uint64_t rsv_a:6;
+ } s;
+ struct cvmx_npi_port32_instr_hdr_s cn30xx;
+ struct cvmx_npi_port32_instr_hdr_s cn31xx;
+ struct cvmx_npi_port32_instr_hdr_s cn38xx;
+ struct cvmx_npi_port32_instr_hdr_s cn38xxp2;
+ struct cvmx_npi_port32_instr_hdr_s cn50xx;
+ struct cvmx_npi_port32_instr_hdr_s cn58xx;
+ struct cvmx_npi_port32_instr_hdr_s cn58xxp1;
+};
+
+union cvmx_npi_port33_instr_hdr {
+ uint64_t u64;
+ struct cvmx_npi_port33_instr_hdr_s {
+ uint64_t reserved_44_63:20;
+ uint64_t pbp:1;
+ uint64_t rsv_f:5;
+ uint64_t rparmode:2;
+ uint64_t rsv_e:1;
+ uint64_t rskp_len:7;
+ uint64_t rsv_d:6;
+ uint64_t use_ihdr:1;
+ uint64_t rsv_c:5;
+ uint64_t par_mode:2;
+ uint64_t rsv_b:1;
+ uint64_t skp_len:7;
+ uint64_t rsv_a:6;
+ } s;
+ struct cvmx_npi_port33_instr_hdr_s cn31xx;
+ struct cvmx_npi_port33_instr_hdr_s cn38xx;
+ struct cvmx_npi_port33_instr_hdr_s cn38xxp2;
+ struct cvmx_npi_port33_instr_hdr_s cn50xx;
+ struct cvmx_npi_port33_instr_hdr_s cn58xx;
+ struct cvmx_npi_port33_instr_hdr_s cn58xxp1;
+};
+
+union cvmx_npi_port34_instr_hdr {
+ uint64_t u64;
+ struct cvmx_npi_port34_instr_hdr_s {
+ uint64_t reserved_44_63:20;
+ uint64_t pbp:1;
+ uint64_t rsv_f:5;
+ uint64_t rparmode:2;
+ uint64_t rsv_e:1;
+ uint64_t rskp_len:7;
+ uint64_t rsv_d:6;
+ uint64_t use_ihdr:1;
+ uint64_t rsv_c:5;
+ uint64_t par_mode:2;
+ uint64_t rsv_b:1;
+ uint64_t skp_len:7;
+ uint64_t rsv_a:6;
+ } s;
+ struct cvmx_npi_port34_instr_hdr_s cn38xx;
+ struct cvmx_npi_port34_instr_hdr_s cn38xxp2;
+ struct cvmx_npi_port34_instr_hdr_s cn58xx;
+ struct cvmx_npi_port34_instr_hdr_s cn58xxp1;
+};
+
+union cvmx_npi_port35_instr_hdr {
+ uint64_t u64;
+ struct cvmx_npi_port35_instr_hdr_s {
+ uint64_t reserved_44_63:20;
+ uint64_t pbp:1;
+ uint64_t rsv_f:5;
+ uint64_t rparmode:2;
+ uint64_t rsv_e:1;
+ uint64_t rskp_len:7;
+ uint64_t rsv_d:6;
+ uint64_t use_ihdr:1;
+ uint64_t rsv_c:5;
+ uint64_t par_mode:2;
+ uint64_t rsv_b:1;
+ uint64_t skp_len:7;
+ uint64_t rsv_a:6;
+ } s;
+ struct cvmx_npi_port35_instr_hdr_s cn38xx;
+ struct cvmx_npi_port35_instr_hdr_s cn38xxp2;
+ struct cvmx_npi_port35_instr_hdr_s cn58xx;
+ struct cvmx_npi_port35_instr_hdr_s cn58xxp1;
+};
+
+union cvmx_npi_port_bp_control {
+ uint64_t u64;
+ struct cvmx_npi_port_bp_control_s {
+ uint64_t reserved_8_63:56;
+ uint64_t bp_on:4;
+ uint64_t enb:4;
+ } s;
+ struct cvmx_npi_port_bp_control_s cn30xx;
+ struct cvmx_npi_port_bp_control_s cn31xx;
+ struct cvmx_npi_port_bp_control_s cn38xx;
+ struct cvmx_npi_port_bp_control_s cn38xxp2;
+ struct cvmx_npi_port_bp_control_s cn50xx;
+ struct cvmx_npi_port_bp_control_s cn58xx;
+ struct cvmx_npi_port_bp_control_s cn58xxp1;
+};
+
+union cvmx_npi_rsl_int_blocks {
+ uint64_t u64;
+ struct cvmx_npi_rsl_int_blocks_s {
+ uint64_t reserved_32_63:32;
+ uint64_t rint_31:1;
+ uint64_t iob:1;
+ uint64_t reserved_28_29:2;
+ uint64_t rint_27:1;
+ uint64_t rint_26:1;
+ uint64_t rint_25:1;
+ uint64_t rint_24:1;
+ uint64_t asx1:1;
+ uint64_t asx0:1;
+ uint64_t rint_21:1;
+ uint64_t pip:1;
+ uint64_t spx1:1;
+ uint64_t spx0:1;
+ uint64_t lmc:1;
+ uint64_t l2c:1;
+ uint64_t rint_15:1;
+ uint64_t reserved_13_14:2;
+ uint64_t pow:1;
+ uint64_t tim:1;
+ uint64_t pko:1;
+ uint64_t ipd:1;
+ uint64_t rint_8:1;
+ uint64_t zip:1;
+ uint64_t dfa:1;
+ uint64_t fpa:1;
+ uint64_t key:1;
+ uint64_t npi:1;
+ uint64_t gmx1:1;
+ uint64_t gmx0:1;
+ uint64_t mio:1;
+ } s;
+ struct cvmx_npi_rsl_int_blocks_cn30xx {
+ uint64_t reserved_32_63:32;
+ uint64_t rint_31:1;
+ uint64_t iob:1;
+ uint64_t rint_29:1;
+ uint64_t rint_28:1;
+ uint64_t rint_27:1;
+ uint64_t rint_26:1;
+ uint64_t rint_25:1;
+ uint64_t rint_24:1;
+ uint64_t asx1:1;
+ uint64_t asx0:1;
+ uint64_t rint_21:1;
+ uint64_t pip:1;
+ uint64_t spx1:1;
+ uint64_t spx0:1;
+ uint64_t lmc:1;
+ uint64_t l2c:1;
+ uint64_t rint_15:1;
+ uint64_t rint_14:1;
+ uint64_t usb:1;
+ uint64_t pow:1;
+ uint64_t tim:1;
+ uint64_t pko:1;
+ uint64_t ipd:1;
+ uint64_t rint_8:1;
+ uint64_t zip:1;
+ uint64_t dfa:1;
+ uint64_t fpa:1;
+ uint64_t key:1;
+ uint64_t npi:1;
+ uint64_t gmx1:1;
+ uint64_t gmx0:1;
+ uint64_t mio:1;
+ } cn30xx;
+ struct cvmx_npi_rsl_int_blocks_cn30xx cn31xx;
+ struct cvmx_npi_rsl_int_blocks_cn38xx {
+ uint64_t reserved_32_63:32;
+ uint64_t rint_31:1;
+ uint64_t iob:1;
+ uint64_t rint_29:1;
+ uint64_t rint_28:1;
+ uint64_t rint_27:1;
+ uint64_t rint_26:1;
+ uint64_t rint_25:1;
+ uint64_t rint_24:1;
+ uint64_t asx1:1;
+ uint64_t asx0:1;
+ uint64_t rint_21:1;
+ uint64_t pip:1;
+ uint64_t spx1:1;
+ uint64_t spx0:1;
+ uint64_t lmc:1;
+ uint64_t l2c:1;
+ uint64_t rint_15:1;
+ uint64_t rint_14:1;
+ uint64_t rint_13:1;
+ uint64_t pow:1;
+ uint64_t tim:1;
+ uint64_t pko:1;
+ uint64_t ipd:1;
+ uint64_t rint_8:1;
+ uint64_t zip:1;
+ uint64_t dfa:1;
+ uint64_t fpa:1;
+ uint64_t key:1;
+ uint64_t npi:1;
+ uint64_t gmx1:1;
+ uint64_t gmx0:1;
+ uint64_t mio:1;
+ } cn38xx;
+ struct cvmx_npi_rsl_int_blocks_cn38xx cn38xxp2;
+ struct cvmx_npi_rsl_int_blocks_cn50xx {
+ uint64_t reserved_31_63:33;
+ uint64_t iob:1;
+ uint64_t lmc1:1;
+ uint64_t agl:1;
+ uint64_t reserved_24_27:4;
+ uint64_t asx1:1;
+ uint64_t asx0:1;
+ uint64_t reserved_21_21:1;
+ uint64_t pip:1;
+ uint64_t spx1:1;
+ uint64_t spx0:1;
+ uint64_t lmc:1;
+ uint64_t l2c:1;
+ uint64_t reserved_15_15:1;
+ uint64_t rad:1;
+ uint64_t usb:1;
+ uint64_t pow:1;
+ uint64_t tim:1;
+ uint64_t pko:1;
+ uint64_t ipd:1;
+ uint64_t reserved_8_8:1;
+ uint64_t zip:1;
+ uint64_t dfa:1;
+ uint64_t fpa:1;
+ uint64_t key:1;
+ uint64_t npi:1;
+ uint64_t gmx1:1;
+ uint64_t gmx0:1;
+ uint64_t mio:1;
+ } cn50xx;
+ struct cvmx_npi_rsl_int_blocks_cn38xx cn58xx;
+ struct cvmx_npi_rsl_int_blocks_cn38xx cn58xxp1;
+};
+
+union cvmx_npi_size_inputx {
+ uint64_t u64;
+ struct cvmx_npi_size_inputx_s {
+ uint64_t reserved_32_63:32;
+ uint64_t size:32;
+ } s;
+ struct cvmx_npi_size_inputx_s cn30xx;
+ struct cvmx_npi_size_inputx_s cn31xx;
+ struct cvmx_npi_size_inputx_s cn38xx;
+ struct cvmx_npi_size_inputx_s cn38xxp2;
+ struct cvmx_npi_size_inputx_s cn50xx;
+ struct cvmx_npi_size_inputx_s cn58xx;
+ struct cvmx_npi_size_inputx_s cn58xxp1;
+};
+
+union cvmx_npi_win_read_to {
+ uint64_t u64;
+ struct cvmx_npi_win_read_to_s {
+ uint64_t reserved_32_63:32;
+ uint64_t time:32;
+ } s;
+ struct cvmx_npi_win_read_to_s cn30xx;
+ struct cvmx_npi_win_read_to_s cn31xx;
+ struct cvmx_npi_win_read_to_s cn38xx;
+ struct cvmx_npi_win_read_to_s cn38xxp2;
+ struct cvmx_npi_win_read_to_s cn50xx;
+ struct cvmx_npi_win_read_to_s cn58xx;
+ struct cvmx_npi_win_read_to_s cn58xxp1;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-pci-defs.h b/arch/mips/include/asm/octeon/cvmx-pci-defs.h
new file mode 100644
index 000000000000..90f8d6535753
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-pci-defs.h
@@ -0,0 +1,1645 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_PCI_DEFS_H__
+#define __CVMX_PCI_DEFS_H__
+
+#define CVMX_PCI_BAR1_INDEXX(offset) \
+ (0x0000000000000100ull + (((offset) & 31) * 4))
+#define CVMX_PCI_BIST_REG \
+ (0x00000000000001C0ull)
+#define CVMX_PCI_CFG00 \
+ (0x0000000000000000ull)
+#define CVMX_PCI_CFG01 \
+ (0x0000000000000004ull)
+#define CVMX_PCI_CFG02 \
+ (0x0000000000000008ull)
+#define CVMX_PCI_CFG03 \
+ (0x000000000000000Cull)
+#define CVMX_PCI_CFG04 \
+ (0x0000000000000010ull)
+#define CVMX_PCI_CFG05 \
+ (0x0000000000000014ull)
+#define CVMX_PCI_CFG06 \
+ (0x0000000000000018ull)
+#define CVMX_PCI_CFG07 \
+ (0x000000000000001Cull)
+#define CVMX_PCI_CFG08 \
+ (0x0000000000000020ull)
+#define CVMX_PCI_CFG09 \
+ (0x0000000000000024ull)
+#define CVMX_PCI_CFG10 \
+ (0x0000000000000028ull)
+#define CVMX_PCI_CFG11 \
+ (0x000000000000002Cull)
+#define CVMX_PCI_CFG12 \
+ (0x0000000000000030ull)
+#define CVMX_PCI_CFG13 \
+ (0x0000000000000034ull)
+#define CVMX_PCI_CFG15 \
+ (0x000000000000003Cull)
+#define CVMX_PCI_CFG16 \
+ (0x0000000000000040ull)
+#define CVMX_PCI_CFG17 \
+ (0x0000000000000044ull)
+#define CVMX_PCI_CFG18 \
+ (0x0000000000000048ull)
+#define CVMX_PCI_CFG19 \
+ (0x000000000000004Cull)
+#define CVMX_PCI_CFG20 \
+ (0x0000000000000050ull)
+#define CVMX_PCI_CFG21 \
+ (0x0000000000000054ull)
+#define CVMX_PCI_CFG22 \
+ (0x0000000000000058ull)
+#define CVMX_PCI_CFG56 \
+ (0x00000000000000E0ull)
+#define CVMX_PCI_CFG57 \
+ (0x00000000000000E4ull)
+#define CVMX_PCI_CFG58 \
+ (0x00000000000000E8ull)
+#define CVMX_PCI_CFG59 \
+ (0x00000000000000ECull)
+#define CVMX_PCI_CFG60 \
+ (0x00000000000000F0ull)
+#define CVMX_PCI_CFG61 \
+ (0x00000000000000F4ull)
+#define CVMX_PCI_CFG62 \
+ (0x00000000000000F8ull)
+#define CVMX_PCI_CFG63 \
+ (0x00000000000000FCull)
+#define CVMX_PCI_CNT_REG \
+ (0x00000000000001B8ull)
+#define CVMX_PCI_CTL_STATUS_2 \
+ (0x000000000000018Cull)
+#define CVMX_PCI_DBELL_0 \
+ (0x0000000000000080ull)
+#define CVMX_PCI_DBELL_1 \
+ (0x0000000000000088ull)
+#define CVMX_PCI_DBELL_2 \
+ (0x0000000000000090ull)
+#define CVMX_PCI_DBELL_3 \
+ (0x0000000000000098ull)
+#define CVMX_PCI_DBELL_X(offset) \
+ (0x0000000000000080ull + (((offset) & 3) * 8))
+#define CVMX_PCI_DMA_CNT0 \
+ (0x00000000000000A0ull)
+#define CVMX_PCI_DMA_CNT1 \
+ (0x00000000000000A8ull)
+#define CVMX_PCI_DMA_CNTX(offset) \
+ (0x00000000000000A0ull + (((offset) & 1) * 8))
+#define CVMX_PCI_DMA_INT_LEV0 \
+ (0x00000000000000A4ull)
+#define CVMX_PCI_DMA_INT_LEV1 \
+ (0x00000000000000ACull)
+#define CVMX_PCI_DMA_INT_LEVX(offset) \
+ (0x00000000000000A4ull + (((offset) & 1) * 8))
+#define CVMX_PCI_DMA_TIME0 \
+ (0x00000000000000B0ull)
+#define CVMX_PCI_DMA_TIME1 \
+ (0x00000000000000B4ull)
+#define CVMX_PCI_DMA_TIMEX(offset) \
+ (0x00000000000000B0ull + (((offset) & 1) * 4))
+#define CVMX_PCI_INSTR_COUNT0 \
+ (0x0000000000000084ull)
+#define CVMX_PCI_INSTR_COUNT1 \
+ (0x000000000000008Cull)
+#define CVMX_PCI_INSTR_COUNT2 \
+ (0x0000000000000094ull)
+#define CVMX_PCI_INSTR_COUNT3 \
+ (0x000000000000009Cull)
+#define CVMX_PCI_INSTR_COUNTX(offset) \
+ (0x0000000000000084ull + (((offset) & 3) * 8))
+#define CVMX_PCI_INT_ENB \
+ (0x0000000000000038ull)
+#define CVMX_PCI_INT_ENB2 \
+ (0x00000000000001A0ull)
+#define CVMX_PCI_INT_SUM \
+ (0x0000000000000030ull)
+#define CVMX_PCI_INT_SUM2 \
+ (0x0000000000000198ull)
+#define CVMX_PCI_MSI_RCV \
+ (0x00000000000000F0ull)
+#define CVMX_PCI_PKTS_SENT0 \
+ (0x0000000000000040ull)
+#define CVMX_PCI_PKTS_SENT1 \
+ (0x0000000000000050ull)
+#define CVMX_PCI_PKTS_SENT2 \
+ (0x0000000000000060ull)
+#define CVMX_PCI_PKTS_SENT3 \
+ (0x0000000000000070ull)
+#define CVMX_PCI_PKTS_SENTX(offset) \
+ (0x0000000000000040ull + (((offset) & 3) * 16))
+#define CVMX_PCI_PKTS_SENT_INT_LEV0 \
+ (0x0000000000000048ull)
+#define CVMX_PCI_PKTS_SENT_INT_LEV1 \
+ (0x0000000000000058ull)
+#define CVMX_PCI_PKTS_SENT_INT_LEV2 \
+ (0x0000000000000068ull)
+#define CVMX_PCI_PKTS_SENT_INT_LEV3 \
+ (0x0000000000000078ull)
+#define CVMX_PCI_PKTS_SENT_INT_LEVX(offset) \
+ (0x0000000000000048ull + (((offset) & 3) * 16))
+#define CVMX_PCI_PKTS_SENT_TIME0 \
+ (0x000000000000004Cull)
+#define CVMX_PCI_PKTS_SENT_TIME1 \
+ (0x000000000000005Cull)
+#define CVMX_PCI_PKTS_SENT_TIME2 \
+ (0x000000000000006Cull)
+#define CVMX_PCI_PKTS_SENT_TIME3 \
+ (0x000000000000007Cull)
+#define CVMX_PCI_PKTS_SENT_TIMEX(offset) \
+ (0x000000000000004Cull + (((offset) & 3) * 16))
+#define CVMX_PCI_PKT_CREDITS0 \
+ (0x0000000000000044ull)
+#define CVMX_PCI_PKT_CREDITS1 \
+ (0x0000000000000054ull)
+#define CVMX_PCI_PKT_CREDITS2 \
+ (0x0000000000000064ull)
+#define CVMX_PCI_PKT_CREDITS3 \
+ (0x0000000000000074ull)
+#define CVMX_PCI_PKT_CREDITSX(offset) \
+ (0x0000000000000044ull + (((offset) & 3) * 16))
+#define CVMX_PCI_READ_CMD_6 \
+ (0x0000000000000180ull)
+#define CVMX_PCI_READ_CMD_C \
+ (0x0000000000000184ull)
+#define CVMX_PCI_READ_CMD_E \
+ (0x0000000000000188ull)
+#define CVMX_PCI_READ_TIMEOUT \
+ CVMX_ADD_IO_SEG(0x00011F00000000B0ull)
+#define CVMX_PCI_SCM_REG \
+ (0x00000000000001A8ull)
+#define CVMX_PCI_TSR_REG \
+ (0x00000000000001B0ull)
+#define CVMX_PCI_WIN_RD_ADDR \
+ (0x0000000000000008ull)
+#define CVMX_PCI_WIN_RD_DATA \
+ (0x0000000000000020ull)
+#define CVMX_PCI_WIN_WR_ADDR \
+ (0x0000000000000000ull)
+#define CVMX_PCI_WIN_WR_DATA \
+ (0x0000000000000010ull)
+#define CVMX_PCI_WIN_WR_MASK \
+ (0x0000000000000018ull)
+
+union cvmx_pci_bar1_indexx {
+ uint32_t u32;
+ struct cvmx_pci_bar1_indexx_s {
+ uint32_t reserved_18_31:14;
+ uint32_t addr_idx:14;
+ uint32_t ca:1;
+ uint32_t end_swp:2;
+ uint32_t addr_v:1;
+ } s;
+ struct cvmx_pci_bar1_indexx_s cn30xx;
+ struct cvmx_pci_bar1_indexx_s cn31xx;
+ struct cvmx_pci_bar1_indexx_s cn38xx;
+ struct cvmx_pci_bar1_indexx_s cn38xxp2;
+ struct cvmx_pci_bar1_indexx_s cn50xx;
+ struct cvmx_pci_bar1_indexx_s cn58xx;
+ struct cvmx_pci_bar1_indexx_s cn58xxp1;
+};
+
+union cvmx_pci_bist_reg {
+ uint64_t u64;
+ struct cvmx_pci_bist_reg_s {
+ uint64_t reserved_10_63:54;
+ uint64_t rsp_bs:1;
+ uint64_t dma0_bs:1;
+ uint64_t cmd0_bs:1;
+ uint64_t cmd_bs:1;
+ uint64_t csr2p_bs:1;
+ uint64_t csrr_bs:1;
+ uint64_t rsp2p_bs:1;
+ uint64_t csr2n_bs:1;
+ uint64_t dat2n_bs:1;
+ uint64_t dbg2n_bs:1;
+ } s;
+ struct cvmx_pci_bist_reg_s cn50xx;
+};
+
+union cvmx_pci_cfg00 {
+ uint32_t u32;
+ struct cvmx_pci_cfg00_s {
+ uint32_t devid:16;
+ uint32_t vendid:16;
+ } s;
+ struct cvmx_pci_cfg00_s cn30xx;
+ struct cvmx_pci_cfg00_s cn31xx;
+ struct cvmx_pci_cfg00_s cn38xx;
+ struct cvmx_pci_cfg00_s cn38xxp2;
+ struct cvmx_pci_cfg00_s cn50xx;
+ struct cvmx_pci_cfg00_s cn58xx;
+ struct cvmx_pci_cfg00_s cn58xxp1;
+};
+
+union cvmx_pci_cfg01 {
+ uint32_t u32;
+ struct cvmx_pci_cfg01_s {
+ uint32_t dpe:1;
+ uint32_t sse:1;
+ uint32_t rma:1;
+ uint32_t rta:1;
+ uint32_t sta:1;
+ uint32_t devt:2;
+ uint32_t mdpe:1;
+ uint32_t fbb:1;
+ uint32_t reserved_22_22:1;
+ uint32_t m66:1;
+ uint32_t cle:1;
+ uint32_t i_stat:1;
+ uint32_t reserved_11_18:8;
+ uint32_t i_dis:1;
+ uint32_t fbbe:1;
+ uint32_t see:1;
+ uint32_t ads:1;
+ uint32_t pee:1;
+ uint32_t vps:1;
+ uint32_t mwice:1;
+ uint32_t scse:1;
+ uint32_t me:1;
+ uint32_t msae:1;
+ uint32_t isae:1;
+ } s;
+ struct cvmx_pci_cfg01_s cn30xx;
+ struct cvmx_pci_cfg01_s cn31xx;
+ struct cvmx_pci_cfg01_s cn38xx;
+ struct cvmx_pci_cfg01_s cn38xxp2;
+ struct cvmx_pci_cfg01_s cn50xx;
+ struct cvmx_pci_cfg01_s cn58xx;
+ struct cvmx_pci_cfg01_s cn58xxp1;
+};
+
+union cvmx_pci_cfg02 {
+ uint32_t u32;
+ struct cvmx_pci_cfg02_s {
+ uint32_t cc:24;
+ uint32_t rid:8;
+ } s;
+ struct cvmx_pci_cfg02_s cn30xx;
+ struct cvmx_pci_cfg02_s cn31xx;
+ struct cvmx_pci_cfg02_s cn38xx;
+ struct cvmx_pci_cfg02_s cn38xxp2;
+ struct cvmx_pci_cfg02_s cn50xx;
+ struct cvmx_pci_cfg02_s cn58xx;
+ struct cvmx_pci_cfg02_s cn58xxp1;
+};
+
+union cvmx_pci_cfg03 {
+ uint32_t u32;
+ struct cvmx_pci_cfg03_s {
+ uint32_t bcap:1;
+ uint32_t brb:1;
+ uint32_t reserved_28_29:2;
+ uint32_t bcod:4;
+ uint32_t ht:8;
+ uint32_t lt:8;
+ uint32_t cls:8;
+ } s;
+ struct cvmx_pci_cfg03_s cn30xx;
+ struct cvmx_pci_cfg03_s cn31xx;
+ struct cvmx_pci_cfg03_s cn38xx;
+ struct cvmx_pci_cfg03_s cn38xxp2;
+ struct cvmx_pci_cfg03_s cn50xx;
+ struct cvmx_pci_cfg03_s cn58xx;
+ struct cvmx_pci_cfg03_s cn58xxp1;
+};
+
+union cvmx_pci_cfg04 {
+ uint32_t u32;
+ struct cvmx_pci_cfg04_s {
+ uint32_t lbase:20;
+ uint32_t lbasez:8;
+ uint32_t pf:1;
+ uint32_t typ:2;
+ uint32_t mspc:1;
+ } s;
+ struct cvmx_pci_cfg04_s cn30xx;
+ struct cvmx_pci_cfg04_s cn31xx;
+ struct cvmx_pci_cfg04_s cn38xx;
+ struct cvmx_pci_cfg04_s cn38xxp2;
+ struct cvmx_pci_cfg04_s cn50xx;
+ struct cvmx_pci_cfg04_s cn58xx;
+ struct cvmx_pci_cfg04_s cn58xxp1;
+};
+
+union cvmx_pci_cfg05 {
+ uint32_t u32;
+ struct cvmx_pci_cfg05_s {
+ uint32_t hbase:32;
+ } s;
+ struct cvmx_pci_cfg05_s cn30xx;
+ struct cvmx_pci_cfg05_s cn31xx;
+ struct cvmx_pci_cfg05_s cn38xx;
+ struct cvmx_pci_cfg05_s cn38xxp2;
+ struct cvmx_pci_cfg05_s cn50xx;
+ struct cvmx_pci_cfg05_s cn58xx;
+ struct cvmx_pci_cfg05_s cn58xxp1;
+};
+
+union cvmx_pci_cfg06 {
+ uint32_t u32;
+ struct cvmx_pci_cfg06_s {
+ uint32_t lbase:5;
+ uint32_t lbasez:23;
+ uint32_t pf:1;
+ uint32_t typ:2;
+ uint32_t mspc:1;
+ } s;
+ struct cvmx_pci_cfg06_s cn30xx;
+ struct cvmx_pci_cfg06_s cn31xx;
+ struct cvmx_pci_cfg06_s cn38xx;
+ struct cvmx_pci_cfg06_s cn38xxp2;
+ struct cvmx_pci_cfg06_s cn50xx;
+ struct cvmx_pci_cfg06_s cn58xx;
+ struct cvmx_pci_cfg06_s cn58xxp1;
+};
+
+union cvmx_pci_cfg07 {
+ uint32_t u32;
+ struct cvmx_pci_cfg07_s {
+ uint32_t hbase:32;
+ } s;
+ struct cvmx_pci_cfg07_s cn30xx;
+ struct cvmx_pci_cfg07_s cn31xx;
+ struct cvmx_pci_cfg07_s cn38xx;
+ struct cvmx_pci_cfg07_s cn38xxp2;
+ struct cvmx_pci_cfg07_s cn50xx;
+ struct cvmx_pci_cfg07_s cn58xx;
+ struct cvmx_pci_cfg07_s cn58xxp1;
+};
+
+union cvmx_pci_cfg08 {
+ uint32_t u32;
+ struct cvmx_pci_cfg08_s {
+ uint32_t lbasez:28;
+ uint32_t pf:1;
+ uint32_t typ:2;
+ uint32_t mspc:1;
+ } s;
+ struct cvmx_pci_cfg08_s cn30xx;
+ struct cvmx_pci_cfg08_s cn31xx;
+ struct cvmx_pci_cfg08_s cn38xx;
+ struct cvmx_pci_cfg08_s cn38xxp2;
+ struct cvmx_pci_cfg08_s cn50xx;
+ struct cvmx_pci_cfg08_s cn58xx;
+ struct cvmx_pci_cfg08_s cn58xxp1;
+};
+
+union cvmx_pci_cfg09 {
+ uint32_t u32;
+ struct cvmx_pci_cfg09_s {
+ uint32_t hbase:25;
+ uint32_t hbasez:7;
+ } s;
+ struct cvmx_pci_cfg09_s cn30xx;
+ struct cvmx_pci_cfg09_s cn31xx;
+ struct cvmx_pci_cfg09_s cn38xx;
+ struct cvmx_pci_cfg09_s cn38xxp2;
+ struct cvmx_pci_cfg09_s cn50xx;
+ struct cvmx_pci_cfg09_s cn58xx;
+ struct cvmx_pci_cfg09_s cn58xxp1;
+};
+
+union cvmx_pci_cfg10 {
+ uint32_t u32;
+ struct cvmx_pci_cfg10_s {
+ uint32_t cisp:32;
+ } s;
+ struct cvmx_pci_cfg10_s cn30xx;
+ struct cvmx_pci_cfg10_s cn31xx;
+ struct cvmx_pci_cfg10_s cn38xx;
+ struct cvmx_pci_cfg10_s cn38xxp2;
+ struct cvmx_pci_cfg10_s cn50xx;
+ struct cvmx_pci_cfg10_s cn58xx;
+ struct cvmx_pci_cfg10_s cn58xxp1;
+};
+
+union cvmx_pci_cfg11 {
+ uint32_t u32;
+ struct cvmx_pci_cfg11_s {
+ uint32_t ssid:16;
+ uint32_t ssvid:16;
+ } s;
+ struct cvmx_pci_cfg11_s cn30xx;
+ struct cvmx_pci_cfg11_s cn31xx;
+ struct cvmx_pci_cfg11_s cn38xx;
+ struct cvmx_pci_cfg11_s cn38xxp2;
+ struct cvmx_pci_cfg11_s cn50xx;
+ struct cvmx_pci_cfg11_s cn58xx;
+ struct cvmx_pci_cfg11_s cn58xxp1;
+};
+
+union cvmx_pci_cfg12 {
+ uint32_t u32;
+ struct cvmx_pci_cfg12_s {
+ uint32_t erbar:16;
+ uint32_t erbarz:5;
+ uint32_t reserved_1_10:10;
+ uint32_t erbar_en:1;
+ } s;
+ struct cvmx_pci_cfg12_s cn30xx;
+ struct cvmx_pci_cfg12_s cn31xx;
+ struct cvmx_pci_cfg12_s cn38xx;
+ struct cvmx_pci_cfg12_s cn38xxp2;
+ struct cvmx_pci_cfg12_s cn50xx;
+ struct cvmx_pci_cfg12_s cn58xx;
+ struct cvmx_pci_cfg12_s cn58xxp1;
+};
+
+union cvmx_pci_cfg13 {
+ uint32_t u32;
+ struct cvmx_pci_cfg13_s {
+ uint32_t reserved_8_31:24;
+ uint32_t cp:8;
+ } s;
+ struct cvmx_pci_cfg13_s cn30xx;
+ struct cvmx_pci_cfg13_s cn31xx;
+ struct cvmx_pci_cfg13_s cn38xx;
+ struct cvmx_pci_cfg13_s cn38xxp2;
+ struct cvmx_pci_cfg13_s cn50xx;
+ struct cvmx_pci_cfg13_s cn58xx;
+ struct cvmx_pci_cfg13_s cn58xxp1;
+};
+
+union cvmx_pci_cfg15 {
+ uint32_t u32;
+ struct cvmx_pci_cfg15_s {
+ uint32_t ml:8;
+ uint32_t mg:8;
+ uint32_t inta:8;
+ uint32_t il:8;
+ } s;
+ struct cvmx_pci_cfg15_s cn30xx;
+ struct cvmx_pci_cfg15_s cn31xx;
+ struct cvmx_pci_cfg15_s cn38xx;
+ struct cvmx_pci_cfg15_s cn38xxp2;
+ struct cvmx_pci_cfg15_s cn50xx;
+ struct cvmx_pci_cfg15_s cn58xx;
+ struct cvmx_pci_cfg15_s cn58xxp1;
+};
+
+union cvmx_pci_cfg16 {
+ uint32_t u32;
+ struct cvmx_pci_cfg16_s {
+ uint32_t trdnpr:1;
+ uint32_t trdard:1;
+ uint32_t rdsati:1;
+ uint32_t trdrs:1;
+ uint32_t trtae:1;
+ uint32_t twsei:1;
+ uint32_t twsen:1;
+ uint32_t twtae:1;
+ uint32_t tmae:1;
+ uint32_t tslte:3;
+ uint32_t tilt:4;
+ uint32_t pbe:12;
+ uint32_t dppmr:1;
+ uint32_t reserved_2_2:1;
+ uint32_t tswc:1;
+ uint32_t mltd:1;
+ } s;
+ struct cvmx_pci_cfg16_s cn30xx;
+ struct cvmx_pci_cfg16_s cn31xx;
+ struct cvmx_pci_cfg16_s cn38xx;
+ struct cvmx_pci_cfg16_s cn38xxp2;
+ struct cvmx_pci_cfg16_s cn50xx;
+ struct cvmx_pci_cfg16_s cn58xx;
+ struct cvmx_pci_cfg16_s cn58xxp1;
+};
+
+union cvmx_pci_cfg17 {
+ uint32_t u32;
+ struct cvmx_pci_cfg17_s {
+ uint32_t tscme:32;
+ } s;
+ struct cvmx_pci_cfg17_s cn30xx;
+ struct cvmx_pci_cfg17_s cn31xx;
+ struct cvmx_pci_cfg17_s cn38xx;
+ struct cvmx_pci_cfg17_s cn38xxp2;
+ struct cvmx_pci_cfg17_s cn50xx;
+ struct cvmx_pci_cfg17_s cn58xx;
+ struct cvmx_pci_cfg17_s cn58xxp1;
+};
+
+union cvmx_pci_cfg18 {
+ uint32_t u32;
+ struct cvmx_pci_cfg18_s {
+ uint32_t tdsrps:32;
+ } s;
+ struct cvmx_pci_cfg18_s cn30xx;
+ struct cvmx_pci_cfg18_s cn31xx;
+ struct cvmx_pci_cfg18_s cn38xx;
+ struct cvmx_pci_cfg18_s cn38xxp2;
+ struct cvmx_pci_cfg18_s cn50xx;
+ struct cvmx_pci_cfg18_s cn58xx;
+ struct cvmx_pci_cfg18_s cn58xxp1;
+};
+
+union cvmx_pci_cfg19 {
+ uint32_t u32;
+ struct cvmx_pci_cfg19_s {
+ uint32_t mrbcm:1;
+ uint32_t mrbci:1;
+ uint32_t mdwe:1;
+ uint32_t mdre:1;
+ uint32_t mdrimc:1;
+ uint32_t mdrrmc:3;
+ uint32_t tmes:8;
+ uint32_t teci:1;
+ uint32_t tmei:1;
+ uint32_t tmse:1;
+ uint32_t tmdpes:1;
+ uint32_t tmapes:1;
+ uint32_t reserved_9_10:2;
+ uint32_t tibcd:1;
+ uint32_t tibde:1;
+ uint32_t reserved_6_6:1;
+ uint32_t tidomc:1;
+ uint32_t tdomc:5;
+ } s;
+ struct cvmx_pci_cfg19_s cn30xx;
+ struct cvmx_pci_cfg19_s cn31xx;
+ struct cvmx_pci_cfg19_s cn38xx;
+ struct cvmx_pci_cfg19_s cn38xxp2;
+ struct cvmx_pci_cfg19_s cn50xx;
+ struct cvmx_pci_cfg19_s cn58xx;
+ struct cvmx_pci_cfg19_s cn58xxp1;
+};
+
+union cvmx_pci_cfg20 {
+ uint32_t u32;
+ struct cvmx_pci_cfg20_s {
+ uint32_t mdsp:32;
+ } s;
+ struct cvmx_pci_cfg20_s cn30xx;
+ struct cvmx_pci_cfg20_s cn31xx;
+ struct cvmx_pci_cfg20_s cn38xx;
+ struct cvmx_pci_cfg20_s cn38xxp2;
+ struct cvmx_pci_cfg20_s cn50xx;
+ struct cvmx_pci_cfg20_s cn58xx;
+ struct cvmx_pci_cfg20_s cn58xxp1;
+};
+
+union cvmx_pci_cfg21 {
+ uint32_t u32;
+ struct cvmx_pci_cfg21_s {
+ uint32_t scmre:32;
+ } s;
+ struct cvmx_pci_cfg21_s cn30xx;
+ struct cvmx_pci_cfg21_s cn31xx;
+ struct cvmx_pci_cfg21_s cn38xx;
+ struct cvmx_pci_cfg21_s cn38xxp2;
+ struct cvmx_pci_cfg21_s cn50xx;
+ struct cvmx_pci_cfg21_s cn58xx;
+ struct cvmx_pci_cfg21_s cn58xxp1;
+};
+
+union cvmx_pci_cfg22 {
+ uint32_t u32;
+ struct cvmx_pci_cfg22_s {
+ uint32_t mac:7;
+ uint32_t reserved_19_24:6;
+ uint32_t flush:1;
+ uint32_t mra:1;
+ uint32_t mtta:1;
+ uint32_t mrv:8;
+ uint32_t mttv:8;
+ } s;
+ struct cvmx_pci_cfg22_s cn30xx;
+ struct cvmx_pci_cfg22_s cn31xx;
+ struct cvmx_pci_cfg22_s cn38xx;
+ struct cvmx_pci_cfg22_s cn38xxp2;
+ struct cvmx_pci_cfg22_s cn50xx;
+ struct cvmx_pci_cfg22_s cn58xx;
+ struct cvmx_pci_cfg22_s cn58xxp1;
+};
+
+union cvmx_pci_cfg56 {
+ uint32_t u32;
+ struct cvmx_pci_cfg56_s {
+ uint32_t reserved_23_31:9;
+ uint32_t most:3;
+ uint32_t mmbc:2;
+ uint32_t roe:1;
+ uint32_t dpere:1;
+ uint32_t ncp:8;
+ uint32_t pxcid:8;
+ } s;
+ struct cvmx_pci_cfg56_s cn30xx;
+ struct cvmx_pci_cfg56_s cn31xx;
+ struct cvmx_pci_cfg56_s cn38xx;
+ struct cvmx_pci_cfg56_s cn38xxp2;
+ struct cvmx_pci_cfg56_s cn50xx;
+ struct cvmx_pci_cfg56_s cn58xx;
+ struct cvmx_pci_cfg56_s cn58xxp1;
+};
+
+union cvmx_pci_cfg57 {
+ uint32_t u32;
+ struct cvmx_pci_cfg57_s {
+ uint32_t reserved_30_31:2;
+ uint32_t scemr:1;
+ uint32_t mcrsd:3;
+ uint32_t mostd:3;
+ uint32_t mmrbcd:2;
+ uint32_t dc:1;
+ uint32_t usc:1;
+ uint32_t scd:1;
+ uint32_t m133:1;
+ uint32_t w64:1;
+ uint32_t bn:8;
+ uint32_t dn:5;
+ uint32_t fn:3;
+ } s;
+ struct cvmx_pci_cfg57_s cn30xx;
+ struct cvmx_pci_cfg57_s cn31xx;
+ struct cvmx_pci_cfg57_s cn38xx;
+ struct cvmx_pci_cfg57_s cn38xxp2;
+ struct cvmx_pci_cfg57_s cn50xx;
+ struct cvmx_pci_cfg57_s cn58xx;
+ struct cvmx_pci_cfg57_s cn58xxp1;
+};
+
+union cvmx_pci_cfg58 {
+ uint32_t u32;
+ struct cvmx_pci_cfg58_s {
+ uint32_t pmes:5;
+ uint32_t d2s:1;
+ uint32_t d1s:1;
+ uint32_t auxc:3;
+ uint32_t dsi:1;
+ uint32_t reserved_20_20:1;
+ uint32_t pmec:1;
+ uint32_t pcimiv:3;
+ uint32_t ncp:8;
+ uint32_t pmcid:8;
+ } s;
+ struct cvmx_pci_cfg58_s cn30xx;
+ struct cvmx_pci_cfg58_s cn31xx;
+ struct cvmx_pci_cfg58_s cn38xx;
+ struct cvmx_pci_cfg58_s cn38xxp2;
+ struct cvmx_pci_cfg58_s cn50xx;
+ struct cvmx_pci_cfg58_s cn58xx;
+ struct cvmx_pci_cfg58_s cn58xxp1;
+};
+
+union cvmx_pci_cfg59 {
+ uint32_t u32;
+ struct cvmx_pci_cfg59_s {
+ uint32_t pmdia:8;
+ uint32_t bpccen:1;
+ uint32_t bd3h:1;
+ uint32_t reserved_16_21:6;
+ uint32_t pmess:1;
+ uint32_t pmedsia:2;
+ uint32_t pmds:4;
+ uint32_t pmeens:1;
+ uint32_t reserved_2_7:6;
+ uint32_t ps:2;
+ } s;
+ struct cvmx_pci_cfg59_s cn30xx;
+ struct cvmx_pci_cfg59_s cn31xx;
+ struct cvmx_pci_cfg59_s cn38xx;
+ struct cvmx_pci_cfg59_s cn38xxp2;
+ struct cvmx_pci_cfg59_s cn50xx;
+ struct cvmx_pci_cfg59_s cn58xx;
+ struct cvmx_pci_cfg59_s cn58xxp1;
+};
+
+union cvmx_pci_cfg60 {
+ uint32_t u32;
+ struct cvmx_pci_cfg60_s {
+ uint32_t reserved_24_31:8;
+ uint32_t m64:1;
+ uint32_t mme:3;
+ uint32_t mmc:3;
+ uint32_t msien:1;
+ uint32_t ncp:8;
+ uint32_t msicid:8;
+ } s;
+ struct cvmx_pci_cfg60_s cn30xx;
+ struct cvmx_pci_cfg60_s cn31xx;
+ struct cvmx_pci_cfg60_s cn38xx;
+ struct cvmx_pci_cfg60_s cn38xxp2;
+ struct cvmx_pci_cfg60_s cn50xx;
+ struct cvmx_pci_cfg60_s cn58xx;
+ struct cvmx_pci_cfg60_s cn58xxp1;
+};
+
+union cvmx_pci_cfg61 {
+ uint32_t u32;
+ struct cvmx_pci_cfg61_s {
+ uint32_t msi31t2:30;
+ uint32_t reserved_0_1:2;
+ } s;
+ struct cvmx_pci_cfg61_s cn30xx;
+ struct cvmx_pci_cfg61_s cn31xx;
+ struct cvmx_pci_cfg61_s cn38xx;
+ struct cvmx_pci_cfg61_s cn38xxp2;
+ struct cvmx_pci_cfg61_s cn50xx;
+ struct cvmx_pci_cfg61_s cn58xx;
+ struct cvmx_pci_cfg61_s cn58xxp1;
+};
+
+union cvmx_pci_cfg62 {
+ uint32_t u32;
+ struct cvmx_pci_cfg62_s {
+ uint32_t msi:32;
+ } s;
+ struct cvmx_pci_cfg62_s cn30xx;
+ struct cvmx_pci_cfg62_s cn31xx;
+ struct cvmx_pci_cfg62_s cn38xx;
+ struct cvmx_pci_cfg62_s cn38xxp2;
+ struct cvmx_pci_cfg62_s cn50xx;
+ struct cvmx_pci_cfg62_s cn58xx;
+ struct cvmx_pci_cfg62_s cn58xxp1;
+};
+
+union cvmx_pci_cfg63 {
+ uint32_t u32;
+ struct cvmx_pci_cfg63_s {
+ uint32_t reserved_16_31:16;
+ uint32_t msimd:16;
+ } s;
+ struct cvmx_pci_cfg63_s cn30xx;
+ struct cvmx_pci_cfg63_s cn31xx;
+ struct cvmx_pci_cfg63_s cn38xx;
+ struct cvmx_pci_cfg63_s cn38xxp2;
+ struct cvmx_pci_cfg63_s cn50xx;
+ struct cvmx_pci_cfg63_s cn58xx;
+ struct cvmx_pci_cfg63_s cn58xxp1;
+};
+
+union cvmx_pci_cnt_reg {
+ uint64_t u64;
+ struct cvmx_pci_cnt_reg_s {
+ uint64_t reserved_38_63:26;
+ uint64_t hm_pcix:1;
+ uint64_t hm_speed:2;
+ uint64_t ap_pcix:1;
+ uint64_t ap_speed:2;
+ uint64_t pcicnt:32;
+ } s;
+ struct cvmx_pci_cnt_reg_s cn50xx;
+ struct cvmx_pci_cnt_reg_s cn58xx;
+ struct cvmx_pci_cnt_reg_s cn58xxp1;
+};
+
+union cvmx_pci_ctl_status_2 {
+ uint32_t u32;
+ struct cvmx_pci_ctl_status_2_s {
+ uint32_t reserved_29_31:3;
+ uint32_t bb1_hole:3;
+ uint32_t bb1_siz:1;
+ uint32_t bb_ca:1;
+ uint32_t bb_es:2;
+ uint32_t bb1:1;
+ uint32_t bb0:1;
+ uint32_t erst_n:1;
+ uint32_t bar2pres:1;
+ uint32_t scmtyp:1;
+ uint32_t scm:1;
+ uint32_t en_wfilt:1;
+ uint32_t reserved_14_14:1;
+ uint32_t ap_pcix:1;
+ uint32_t ap_64ad:1;
+ uint32_t b12_bist:1;
+ uint32_t pmo_amod:1;
+ uint32_t pmo_fpc:3;
+ uint32_t tsr_hwm:3;
+ uint32_t bar2_enb:1;
+ uint32_t bar2_esx:2;
+ uint32_t bar2_cax:1;
+ } s;
+ struct cvmx_pci_ctl_status_2_s cn30xx;
+ struct cvmx_pci_ctl_status_2_cn31xx {
+ uint32_t reserved_20_31:12;
+ uint32_t erst_n:1;
+ uint32_t bar2pres:1;
+ uint32_t scmtyp:1;
+ uint32_t scm:1;
+ uint32_t en_wfilt:1;
+ uint32_t reserved_14_14:1;
+ uint32_t ap_pcix:1;
+ uint32_t ap_64ad:1;
+ uint32_t b12_bist:1;
+ uint32_t pmo_amod:1;
+ uint32_t pmo_fpc:3;
+ uint32_t tsr_hwm:3;
+ uint32_t bar2_enb:1;
+ uint32_t bar2_esx:2;
+ uint32_t bar2_cax:1;
+ } cn31xx;
+ struct cvmx_pci_ctl_status_2_s cn38xx;
+ struct cvmx_pci_ctl_status_2_cn31xx cn38xxp2;
+ struct cvmx_pci_ctl_status_2_s cn50xx;
+ struct cvmx_pci_ctl_status_2_s cn58xx;
+ struct cvmx_pci_ctl_status_2_s cn58xxp1;
+};
+
+union cvmx_pci_dbellx {
+ uint32_t u32;
+ struct cvmx_pci_dbellx_s {
+ uint32_t reserved_16_31:16;
+ uint32_t inc_val:16;
+ } s;
+ struct cvmx_pci_dbellx_s cn30xx;
+ struct cvmx_pci_dbellx_s cn31xx;
+ struct cvmx_pci_dbellx_s cn38xx;
+ struct cvmx_pci_dbellx_s cn38xxp2;
+ struct cvmx_pci_dbellx_s cn50xx;
+ struct cvmx_pci_dbellx_s cn58xx;
+ struct cvmx_pci_dbellx_s cn58xxp1;
+};
+
+union cvmx_pci_dma_cntx {
+ uint32_t u32;
+ struct cvmx_pci_dma_cntx_s {
+ uint32_t dma_cnt:32;
+ } s;
+ struct cvmx_pci_dma_cntx_s cn30xx;
+ struct cvmx_pci_dma_cntx_s cn31xx;
+ struct cvmx_pci_dma_cntx_s cn38xx;
+ struct cvmx_pci_dma_cntx_s cn38xxp2;
+ struct cvmx_pci_dma_cntx_s cn50xx;
+ struct cvmx_pci_dma_cntx_s cn58xx;
+ struct cvmx_pci_dma_cntx_s cn58xxp1;
+};
+
+union cvmx_pci_dma_int_levx {
+ uint32_t u32;
+ struct cvmx_pci_dma_int_levx_s {
+ uint32_t pkt_cnt:32;
+ } s;
+ struct cvmx_pci_dma_int_levx_s cn30xx;
+ struct cvmx_pci_dma_int_levx_s cn31xx;
+ struct cvmx_pci_dma_int_levx_s cn38xx;
+ struct cvmx_pci_dma_int_levx_s cn38xxp2;
+ struct cvmx_pci_dma_int_levx_s cn50xx;
+ struct cvmx_pci_dma_int_levx_s cn58xx;
+ struct cvmx_pci_dma_int_levx_s cn58xxp1;
+};
+
+union cvmx_pci_dma_timex {
+ uint32_t u32;
+ struct cvmx_pci_dma_timex_s {
+ uint32_t dma_time:32;
+ } s;
+ struct cvmx_pci_dma_timex_s cn30xx;
+ struct cvmx_pci_dma_timex_s cn31xx;
+ struct cvmx_pci_dma_timex_s cn38xx;
+ struct cvmx_pci_dma_timex_s cn38xxp2;
+ struct cvmx_pci_dma_timex_s cn50xx;
+ struct cvmx_pci_dma_timex_s cn58xx;
+ struct cvmx_pci_dma_timex_s cn58xxp1;
+};
+
+union cvmx_pci_instr_countx {
+ uint32_t u32;
+ struct cvmx_pci_instr_countx_s {
+ uint32_t icnt:32;
+ } s;
+ struct cvmx_pci_instr_countx_s cn30xx;
+ struct cvmx_pci_instr_countx_s cn31xx;
+ struct cvmx_pci_instr_countx_s cn38xx;
+ struct cvmx_pci_instr_countx_s cn38xxp2;
+ struct cvmx_pci_instr_countx_s cn50xx;
+ struct cvmx_pci_instr_countx_s cn58xx;
+ struct cvmx_pci_instr_countx_s cn58xxp1;
+};
+
+union cvmx_pci_int_enb {
+ uint64_t u64;
+ struct cvmx_pci_int_enb_s {
+ uint64_t reserved_34_63:30;
+ uint64_t ill_rd:1;
+ uint64_t ill_wr:1;
+ uint64_t win_wr:1;
+ uint64_t dma1_fi:1;
+ uint64_t dma0_fi:1;
+ uint64_t idtime1:1;
+ uint64_t idtime0:1;
+ uint64_t idcnt1:1;
+ uint64_t idcnt0:1;
+ uint64_t iptime3:1;
+ uint64_t iptime2:1;
+ uint64_t iptime1:1;
+ uint64_t iptime0:1;
+ uint64_t ipcnt3:1;
+ uint64_t ipcnt2:1;
+ uint64_t ipcnt1:1;
+ uint64_t ipcnt0:1;
+ uint64_t irsl_int:1;
+ uint64_t ill_rrd:1;
+ uint64_t ill_rwr:1;
+ uint64_t idperr:1;
+ uint64_t iaperr:1;
+ uint64_t iserr:1;
+ uint64_t itsr_abt:1;
+ uint64_t imsc_msg:1;
+ uint64_t imsi_mabt:1;
+ uint64_t imsi_tabt:1;
+ uint64_t imsi_per:1;
+ uint64_t imr_tto:1;
+ uint64_t imr_abt:1;
+ uint64_t itr_abt:1;
+ uint64_t imr_wtto:1;
+ uint64_t imr_wabt:1;
+ uint64_t itr_wabt:1;
+ } s;
+ struct cvmx_pci_int_enb_cn30xx {
+ uint64_t reserved_34_63:30;
+ uint64_t ill_rd:1;
+ uint64_t ill_wr:1;
+ uint64_t win_wr:1;
+ uint64_t dma1_fi:1;
+ uint64_t dma0_fi:1;
+ uint64_t idtime1:1;
+ uint64_t idtime0:1;
+ uint64_t idcnt1:1;
+ uint64_t idcnt0:1;
+ uint64_t reserved_22_24:3;
+ uint64_t iptime0:1;
+ uint64_t reserved_18_20:3;
+ uint64_t ipcnt0:1;
+ uint64_t irsl_int:1;
+ uint64_t ill_rrd:1;
+ uint64_t ill_rwr:1;
+ uint64_t idperr:1;
+ uint64_t iaperr:1;
+ uint64_t iserr:1;
+ uint64_t itsr_abt:1;
+ uint64_t imsc_msg:1;
+ uint64_t imsi_mabt:1;
+ uint64_t imsi_tabt:1;
+ uint64_t imsi_per:1;
+ uint64_t imr_tto:1;
+ uint64_t imr_abt:1;
+ uint64_t itr_abt:1;
+ uint64_t imr_wtto:1;
+ uint64_t imr_wabt:1;
+ uint64_t itr_wabt:1;
+ } cn30xx;
+ struct cvmx_pci_int_enb_cn31xx {
+ uint64_t reserved_34_63:30;
+ uint64_t ill_rd:1;
+ uint64_t ill_wr:1;
+ uint64_t win_wr:1;
+ uint64_t dma1_fi:1;
+ uint64_t dma0_fi:1;
+ uint64_t idtime1:1;
+ uint64_t idtime0:1;
+ uint64_t idcnt1:1;
+ uint64_t idcnt0:1;
+ uint64_t reserved_23_24:2;
+ uint64_t iptime1:1;
+ uint64_t iptime0:1;
+ uint64_t reserved_19_20:2;
+ uint64_t ipcnt1:1;
+ uint64_t ipcnt0:1;
+ uint64_t irsl_int:1;
+ uint64_t ill_rrd:1;
+ uint64_t ill_rwr:1;
+ uint64_t idperr:1;
+ uint64_t iaperr:1;
+ uint64_t iserr:1;
+ uint64_t itsr_abt:1;
+ uint64_t imsc_msg:1;
+ uint64_t imsi_mabt:1;
+ uint64_t imsi_tabt:1;
+ uint64_t imsi_per:1;
+ uint64_t imr_tto:1;
+ uint64_t imr_abt:1;
+ uint64_t itr_abt:1;
+ uint64_t imr_wtto:1;
+ uint64_t imr_wabt:1;
+ uint64_t itr_wabt:1;
+ } cn31xx;
+ struct cvmx_pci_int_enb_s cn38xx;
+ struct cvmx_pci_int_enb_s cn38xxp2;
+ struct cvmx_pci_int_enb_cn31xx cn50xx;
+ struct cvmx_pci_int_enb_s cn58xx;
+ struct cvmx_pci_int_enb_s cn58xxp1;
+};
+
+union cvmx_pci_int_enb2 {
+ uint64_t u64;
+ struct cvmx_pci_int_enb2_s {
+ uint64_t reserved_34_63:30;
+ uint64_t ill_rd:1;
+ uint64_t ill_wr:1;
+ uint64_t win_wr:1;
+ uint64_t dma1_fi:1;
+ uint64_t dma0_fi:1;
+ uint64_t rdtime1:1;
+ uint64_t rdtime0:1;
+ uint64_t rdcnt1:1;
+ uint64_t rdcnt0:1;
+ uint64_t rptime3:1;
+ uint64_t rptime2:1;
+ uint64_t rptime1:1;
+ uint64_t rptime0:1;
+ uint64_t rpcnt3:1;
+ uint64_t rpcnt2:1;
+ uint64_t rpcnt1:1;
+ uint64_t rpcnt0:1;
+ uint64_t rrsl_int:1;
+ uint64_t ill_rrd:1;
+ uint64_t ill_rwr:1;
+ uint64_t rdperr:1;
+ uint64_t raperr:1;
+ uint64_t rserr:1;
+ uint64_t rtsr_abt:1;
+ uint64_t rmsc_msg:1;
+ uint64_t rmsi_mabt:1;
+ uint64_t rmsi_tabt:1;
+ uint64_t rmsi_per:1;
+ uint64_t rmr_tto:1;
+ uint64_t rmr_abt:1;
+ uint64_t rtr_abt:1;
+ uint64_t rmr_wtto:1;
+ uint64_t rmr_wabt:1;
+ uint64_t rtr_wabt:1;
+ } s;
+ struct cvmx_pci_int_enb2_cn30xx {
+ uint64_t reserved_34_63:30;
+ uint64_t ill_rd:1;
+ uint64_t ill_wr:1;
+ uint64_t win_wr:1;
+ uint64_t dma1_fi:1;
+ uint64_t dma0_fi:1;
+ uint64_t rdtime1:1;
+ uint64_t rdtime0:1;
+ uint64_t rdcnt1:1;
+ uint64_t rdcnt0:1;
+ uint64_t reserved_22_24:3;
+ uint64_t rptime0:1;
+ uint64_t reserved_18_20:3;
+ uint64_t rpcnt0:1;
+ uint64_t rrsl_int:1;
+ uint64_t ill_rrd:1;
+ uint64_t ill_rwr:1;
+ uint64_t rdperr:1;
+ uint64_t raperr:1;
+ uint64_t rserr:1;
+ uint64_t rtsr_abt:1;
+ uint64_t rmsc_msg:1;
+ uint64_t rmsi_mabt:1;
+ uint64_t rmsi_tabt:1;
+ uint64_t rmsi_per:1;
+ uint64_t rmr_tto:1;
+ uint64_t rmr_abt:1;
+ uint64_t rtr_abt:1;
+ uint64_t rmr_wtto:1;
+ uint64_t rmr_wabt:1;
+ uint64_t rtr_wabt:1;
+ } cn30xx;
+ struct cvmx_pci_int_enb2_cn31xx {
+ uint64_t reserved_34_63:30;
+ uint64_t ill_rd:1;
+ uint64_t ill_wr:1;
+ uint64_t win_wr:1;
+ uint64_t dma1_fi:1;
+ uint64_t dma0_fi:1;
+ uint64_t rdtime1:1;
+ uint64_t rdtime0:1;
+ uint64_t rdcnt1:1;
+ uint64_t rdcnt0:1;
+ uint64_t reserved_23_24:2;
+ uint64_t rptime1:1;
+ uint64_t rptime0:1;
+ uint64_t reserved_19_20:2;
+ uint64_t rpcnt1:1;
+ uint64_t rpcnt0:1;
+ uint64_t rrsl_int:1;
+ uint64_t ill_rrd:1;
+ uint64_t ill_rwr:1;
+ uint64_t rdperr:1;
+ uint64_t raperr:1;
+ uint64_t rserr:1;
+ uint64_t rtsr_abt:1;
+ uint64_t rmsc_msg:1;
+ uint64_t rmsi_mabt:1;
+ uint64_t rmsi_tabt:1;
+ uint64_t rmsi_per:1;
+ uint64_t rmr_tto:1;
+ uint64_t rmr_abt:1;
+ uint64_t rtr_abt:1;
+ uint64_t rmr_wtto:1;
+ uint64_t rmr_wabt:1;
+ uint64_t rtr_wabt:1;
+ } cn31xx;
+ struct cvmx_pci_int_enb2_s cn38xx;
+ struct cvmx_pci_int_enb2_s cn38xxp2;
+ struct cvmx_pci_int_enb2_cn31xx cn50xx;
+ struct cvmx_pci_int_enb2_s cn58xx;
+ struct cvmx_pci_int_enb2_s cn58xxp1;
+};
+
+union cvmx_pci_int_sum {
+ uint64_t u64;
+ struct cvmx_pci_int_sum_s {
+ uint64_t reserved_34_63:30;
+ uint64_t ill_rd:1;
+ uint64_t ill_wr:1;
+ uint64_t win_wr:1;
+ uint64_t dma1_fi:1;
+ uint64_t dma0_fi:1;
+ uint64_t dtime1:1;
+ uint64_t dtime0:1;
+ uint64_t dcnt1:1;
+ uint64_t dcnt0:1;
+ uint64_t ptime3:1;
+ uint64_t ptime2:1;
+ uint64_t ptime1:1;
+ uint64_t ptime0:1;
+ uint64_t pcnt3:1;
+ uint64_t pcnt2:1;
+ uint64_t pcnt1:1;
+ uint64_t pcnt0:1;
+ uint64_t rsl_int:1;
+ uint64_t ill_rrd:1;
+ uint64_t ill_rwr:1;
+ uint64_t dperr:1;
+ uint64_t aperr:1;
+ uint64_t serr:1;
+ uint64_t tsr_abt:1;
+ uint64_t msc_msg:1;
+ uint64_t msi_mabt:1;
+ uint64_t msi_tabt:1;
+ uint64_t msi_per:1;
+ uint64_t mr_tto:1;
+ uint64_t mr_abt:1;
+ uint64_t tr_abt:1;
+ uint64_t mr_wtto:1;
+ uint64_t mr_wabt:1;
+ uint64_t tr_wabt:1;
+ } s;
+ struct cvmx_pci_int_sum_cn30xx {
+ uint64_t reserved_34_63:30;
+ uint64_t ill_rd:1;
+ uint64_t ill_wr:1;
+ uint64_t win_wr:1;
+ uint64_t dma1_fi:1;
+ uint64_t dma0_fi:1;
+ uint64_t dtime1:1;
+ uint64_t dtime0:1;
+ uint64_t dcnt1:1;
+ uint64_t dcnt0:1;
+ uint64_t reserved_22_24:3;
+ uint64_t ptime0:1;
+ uint64_t reserved_18_20:3;
+ uint64_t pcnt0:1;
+ uint64_t rsl_int:1;
+ uint64_t ill_rrd:1;
+ uint64_t ill_rwr:1;
+ uint64_t dperr:1;
+ uint64_t aperr:1;
+ uint64_t serr:1;
+ uint64_t tsr_abt:1;
+ uint64_t msc_msg:1;
+ uint64_t msi_mabt:1;
+ uint64_t msi_tabt:1;
+ uint64_t msi_per:1;
+ uint64_t mr_tto:1;
+ uint64_t mr_abt:1;
+ uint64_t tr_abt:1;
+ uint64_t mr_wtto:1;
+ uint64_t mr_wabt:1;
+ uint64_t tr_wabt:1;
+ } cn30xx;
+ struct cvmx_pci_int_sum_cn31xx {
+ uint64_t reserved_34_63:30;
+ uint64_t ill_rd:1;
+ uint64_t ill_wr:1;
+ uint64_t win_wr:1;
+ uint64_t dma1_fi:1;
+ uint64_t dma0_fi:1;
+ uint64_t dtime1:1;
+ uint64_t dtime0:1;
+ uint64_t dcnt1:1;
+ uint64_t dcnt0:1;
+ uint64_t reserved_23_24:2;
+ uint64_t ptime1:1;
+ uint64_t ptime0:1;
+ uint64_t reserved_19_20:2;
+ uint64_t pcnt1:1;
+ uint64_t pcnt0:1;
+ uint64_t rsl_int:1;
+ uint64_t ill_rrd:1;
+ uint64_t ill_rwr:1;
+ uint64_t dperr:1;
+ uint64_t aperr:1;
+ uint64_t serr:1;
+ uint64_t tsr_abt:1;
+ uint64_t msc_msg:1;
+ uint64_t msi_mabt:1;
+ uint64_t msi_tabt:1;
+ uint64_t msi_per:1;
+ uint64_t mr_tto:1;
+ uint64_t mr_abt:1;
+ uint64_t tr_abt:1;
+ uint64_t mr_wtto:1;
+ uint64_t mr_wabt:1;
+ uint64_t tr_wabt:1;
+ } cn31xx;
+ struct cvmx_pci_int_sum_s cn38xx;
+ struct cvmx_pci_int_sum_s cn38xxp2;
+ struct cvmx_pci_int_sum_cn31xx cn50xx;
+ struct cvmx_pci_int_sum_s cn58xx;
+ struct cvmx_pci_int_sum_s cn58xxp1;
+};
+
+union cvmx_pci_int_sum2 {
+ uint64_t u64;
+ struct cvmx_pci_int_sum2_s {
+ uint64_t reserved_34_63:30;
+ uint64_t ill_rd:1;
+ uint64_t ill_wr:1;
+ uint64_t win_wr:1;
+ uint64_t dma1_fi:1;
+ uint64_t dma0_fi:1;
+ uint64_t dtime1:1;
+ uint64_t dtime0:1;
+ uint64_t dcnt1:1;
+ uint64_t dcnt0:1;
+ uint64_t ptime3:1;
+ uint64_t ptime2:1;
+ uint64_t ptime1:1;
+ uint64_t ptime0:1;
+ uint64_t pcnt3:1;
+ uint64_t pcnt2:1;
+ uint64_t pcnt1:1;
+ uint64_t pcnt0:1;
+ uint64_t rsl_int:1;
+ uint64_t ill_rrd:1;
+ uint64_t ill_rwr:1;
+ uint64_t dperr:1;
+ uint64_t aperr:1;
+ uint64_t serr:1;
+ uint64_t tsr_abt:1;
+ uint64_t msc_msg:1;
+ uint64_t msi_mabt:1;
+ uint64_t msi_tabt:1;
+ uint64_t msi_per:1;
+ uint64_t mr_tto:1;
+ uint64_t mr_abt:1;
+ uint64_t tr_abt:1;
+ uint64_t mr_wtto:1;
+ uint64_t mr_wabt:1;
+ uint64_t tr_wabt:1;
+ } s;
+ struct cvmx_pci_int_sum2_cn30xx {
+ uint64_t reserved_34_63:30;
+ uint64_t ill_rd:1;
+ uint64_t ill_wr:1;
+ uint64_t win_wr:1;
+ uint64_t dma1_fi:1;
+ uint64_t dma0_fi:1;
+ uint64_t dtime1:1;
+ uint64_t dtime0:1;
+ uint64_t dcnt1:1;
+ uint64_t dcnt0:1;
+ uint64_t reserved_22_24:3;
+ uint64_t ptime0:1;
+ uint64_t reserved_18_20:3;
+ uint64_t pcnt0:1;
+ uint64_t rsl_int:1;
+ uint64_t ill_rrd:1;
+ uint64_t ill_rwr:1;
+ uint64_t dperr:1;
+ uint64_t aperr:1;
+ uint64_t serr:1;
+ uint64_t tsr_abt:1;
+ uint64_t msc_msg:1;
+ uint64_t msi_mabt:1;
+ uint64_t msi_tabt:1;
+ uint64_t msi_per:1;
+ uint64_t mr_tto:1;
+ uint64_t mr_abt:1;
+ uint64_t tr_abt:1;
+ uint64_t mr_wtto:1;
+ uint64_t mr_wabt:1;
+ uint64_t tr_wabt:1;
+ } cn30xx;
+ struct cvmx_pci_int_sum2_cn31xx {
+ uint64_t reserved_34_63:30;
+ uint64_t ill_rd:1;
+ uint64_t ill_wr:1;
+ uint64_t win_wr:1;
+ uint64_t dma1_fi:1;
+ uint64_t dma0_fi:1;
+ uint64_t dtime1:1;
+ uint64_t dtime0:1;
+ uint64_t dcnt1:1;
+ uint64_t dcnt0:1;
+ uint64_t reserved_23_24:2;
+ uint64_t ptime1:1;
+ uint64_t ptime0:1;
+ uint64_t reserved_19_20:2;
+ uint64_t pcnt1:1;
+ uint64_t pcnt0:1;
+ uint64_t rsl_int:1;
+ uint64_t ill_rrd:1;
+ uint64_t ill_rwr:1;
+ uint64_t dperr:1;
+ uint64_t aperr:1;
+ uint64_t serr:1;
+ uint64_t tsr_abt:1;
+ uint64_t msc_msg:1;
+ uint64_t msi_mabt:1;
+ uint64_t msi_tabt:1;
+ uint64_t msi_per:1;
+ uint64_t mr_tto:1;
+ uint64_t mr_abt:1;
+ uint64_t tr_abt:1;
+ uint64_t mr_wtto:1;
+ uint64_t mr_wabt:1;
+ uint64_t tr_wabt:1;
+ } cn31xx;
+ struct cvmx_pci_int_sum2_s cn38xx;
+ struct cvmx_pci_int_sum2_s cn38xxp2;
+ struct cvmx_pci_int_sum2_cn31xx cn50xx;
+ struct cvmx_pci_int_sum2_s cn58xx;
+ struct cvmx_pci_int_sum2_s cn58xxp1;
+};
+
+union cvmx_pci_msi_rcv {
+ uint32_t u32;
+ struct cvmx_pci_msi_rcv_s {
+ uint32_t reserved_6_31:26;
+ uint32_t intr:6;
+ } s;
+ struct cvmx_pci_msi_rcv_s cn30xx;
+ struct cvmx_pci_msi_rcv_s cn31xx;
+ struct cvmx_pci_msi_rcv_s cn38xx;
+ struct cvmx_pci_msi_rcv_s cn38xxp2;
+ struct cvmx_pci_msi_rcv_s cn50xx;
+ struct cvmx_pci_msi_rcv_s cn58xx;
+ struct cvmx_pci_msi_rcv_s cn58xxp1;
+};
+
+union cvmx_pci_pkt_creditsx {
+ uint32_t u32;
+ struct cvmx_pci_pkt_creditsx_s {
+ uint32_t pkt_cnt:16;
+ uint32_t ptr_cnt:16;
+ } s;
+ struct cvmx_pci_pkt_creditsx_s cn30xx;
+ struct cvmx_pci_pkt_creditsx_s cn31xx;
+ struct cvmx_pci_pkt_creditsx_s cn38xx;
+ struct cvmx_pci_pkt_creditsx_s cn38xxp2;
+ struct cvmx_pci_pkt_creditsx_s cn50xx;
+ struct cvmx_pci_pkt_creditsx_s cn58xx;
+ struct cvmx_pci_pkt_creditsx_s cn58xxp1;
+};
+
+union cvmx_pci_pkts_sentx {
+ uint32_t u32;
+ struct cvmx_pci_pkts_sentx_s {
+ uint32_t pkt_cnt:32;
+ } s;
+ struct cvmx_pci_pkts_sentx_s cn30xx;
+ struct cvmx_pci_pkts_sentx_s cn31xx;
+ struct cvmx_pci_pkts_sentx_s cn38xx;
+ struct cvmx_pci_pkts_sentx_s cn38xxp2;
+ struct cvmx_pci_pkts_sentx_s cn50xx;
+ struct cvmx_pci_pkts_sentx_s cn58xx;
+ struct cvmx_pci_pkts_sentx_s cn58xxp1;
+};
+
+union cvmx_pci_pkts_sent_int_levx {
+ uint32_t u32;
+ struct cvmx_pci_pkts_sent_int_levx_s {
+ uint32_t pkt_cnt:32;
+ } s;
+ struct cvmx_pci_pkts_sent_int_levx_s cn30xx;
+ struct cvmx_pci_pkts_sent_int_levx_s cn31xx;
+ struct cvmx_pci_pkts_sent_int_levx_s cn38xx;
+ struct cvmx_pci_pkts_sent_int_levx_s cn38xxp2;
+ struct cvmx_pci_pkts_sent_int_levx_s cn50xx;
+ struct cvmx_pci_pkts_sent_int_levx_s cn58xx;
+ struct cvmx_pci_pkts_sent_int_levx_s cn58xxp1;
+};
+
+union cvmx_pci_pkts_sent_timex {
+ uint32_t u32;
+ struct cvmx_pci_pkts_sent_timex_s {
+ uint32_t pkt_time:32;
+ } s;
+ struct cvmx_pci_pkts_sent_timex_s cn30xx;
+ struct cvmx_pci_pkts_sent_timex_s cn31xx;
+ struct cvmx_pci_pkts_sent_timex_s cn38xx;
+ struct cvmx_pci_pkts_sent_timex_s cn38xxp2;
+ struct cvmx_pci_pkts_sent_timex_s cn50xx;
+ struct cvmx_pci_pkts_sent_timex_s cn58xx;
+ struct cvmx_pci_pkts_sent_timex_s cn58xxp1;
+};
+
+union cvmx_pci_read_cmd_6 {
+ uint32_t u32;
+ struct cvmx_pci_read_cmd_6_s {
+ uint32_t reserved_9_31:23;
+ uint32_t min_data:6;
+ uint32_t prefetch:3;
+ } s;
+ struct cvmx_pci_read_cmd_6_s cn30xx;
+ struct cvmx_pci_read_cmd_6_s cn31xx;
+ struct cvmx_pci_read_cmd_6_s cn38xx;
+ struct cvmx_pci_read_cmd_6_s cn38xxp2;
+ struct cvmx_pci_read_cmd_6_s cn50xx;
+ struct cvmx_pci_read_cmd_6_s cn58xx;
+ struct cvmx_pci_read_cmd_6_s cn58xxp1;
+};
+
+union cvmx_pci_read_cmd_c {
+ uint32_t u32;
+ struct cvmx_pci_read_cmd_c_s {
+ uint32_t reserved_9_31:23;
+ uint32_t min_data:6;
+ uint32_t prefetch:3;
+ } s;
+ struct cvmx_pci_read_cmd_c_s cn30xx;
+ struct cvmx_pci_read_cmd_c_s cn31xx;
+ struct cvmx_pci_read_cmd_c_s cn38xx;
+ struct cvmx_pci_read_cmd_c_s cn38xxp2;
+ struct cvmx_pci_read_cmd_c_s cn50xx;
+ struct cvmx_pci_read_cmd_c_s cn58xx;
+ struct cvmx_pci_read_cmd_c_s cn58xxp1;
+};
+
+union cvmx_pci_read_cmd_e {
+ uint32_t u32;
+ struct cvmx_pci_read_cmd_e_s {
+ uint32_t reserved_9_31:23;
+ uint32_t min_data:6;
+ uint32_t prefetch:3;
+ } s;
+ struct cvmx_pci_read_cmd_e_s cn30xx;
+ struct cvmx_pci_read_cmd_e_s cn31xx;
+ struct cvmx_pci_read_cmd_e_s cn38xx;
+ struct cvmx_pci_read_cmd_e_s cn38xxp2;
+ struct cvmx_pci_read_cmd_e_s cn50xx;
+ struct cvmx_pci_read_cmd_e_s cn58xx;
+ struct cvmx_pci_read_cmd_e_s cn58xxp1;
+};
+
+union cvmx_pci_read_timeout {
+ uint64_t u64;
+ struct cvmx_pci_read_timeout_s {
+ uint64_t reserved_32_63:32;
+ uint64_t enb:1;
+ uint64_t cnt:31;
+ } s;
+ struct cvmx_pci_read_timeout_s cn30xx;
+ struct cvmx_pci_read_timeout_s cn31xx;
+ struct cvmx_pci_read_timeout_s cn38xx;
+ struct cvmx_pci_read_timeout_s cn38xxp2;
+ struct cvmx_pci_read_timeout_s cn50xx;
+ struct cvmx_pci_read_timeout_s cn58xx;
+ struct cvmx_pci_read_timeout_s cn58xxp1;
+};
+
+union cvmx_pci_scm_reg {
+ uint64_t u64;
+ struct cvmx_pci_scm_reg_s {
+ uint64_t reserved_32_63:32;
+ uint64_t scm:32;
+ } s;
+ struct cvmx_pci_scm_reg_s cn30xx;
+ struct cvmx_pci_scm_reg_s cn31xx;
+ struct cvmx_pci_scm_reg_s cn38xx;
+ struct cvmx_pci_scm_reg_s cn38xxp2;
+ struct cvmx_pci_scm_reg_s cn50xx;
+ struct cvmx_pci_scm_reg_s cn58xx;
+ struct cvmx_pci_scm_reg_s cn58xxp1;
+};
+
+union cvmx_pci_tsr_reg {
+ uint64_t u64;
+ struct cvmx_pci_tsr_reg_s {
+ uint64_t reserved_36_63:28;
+ uint64_t tsr:36;
+ } s;
+ struct cvmx_pci_tsr_reg_s cn30xx;
+ struct cvmx_pci_tsr_reg_s cn31xx;
+ struct cvmx_pci_tsr_reg_s cn38xx;
+ struct cvmx_pci_tsr_reg_s cn38xxp2;
+ struct cvmx_pci_tsr_reg_s cn50xx;
+ struct cvmx_pci_tsr_reg_s cn58xx;
+ struct cvmx_pci_tsr_reg_s cn58xxp1;
+};
+
+union cvmx_pci_win_rd_addr {
+ uint64_t u64;
+ struct cvmx_pci_win_rd_addr_s {
+ uint64_t reserved_49_63:15;
+ uint64_t iobit:1;
+ uint64_t reserved_0_47:48;
+ } s;
+ struct cvmx_pci_win_rd_addr_cn30xx {
+ uint64_t reserved_49_63:15;
+ uint64_t iobit:1;
+ uint64_t rd_addr:46;
+ uint64_t reserved_0_1:2;
+ } cn30xx;
+ struct cvmx_pci_win_rd_addr_cn30xx cn31xx;
+ struct cvmx_pci_win_rd_addr_cn38xx {
+ uint64_t reserved_49_63:15;
+ uint64_t iobit:1;
+ uint64_t rd_addr:45;
+ uint64_t reserved_0_2:3;
+ } cn38xx;
+ struct cvmx_pci_win_rd_addr_cn38xx cn38xxp2;
+ struct cvmx_pci_win_rd_addr_cn30xx cn50xx;
+ struct cvmx_pci_win_rd_addr_cn38xx cn58xx;
+ struct cvmx_pci_win_rd_addr_cn38xx cn58xxp1;
+};
+
+union cvmx_pci_win_rd_data {
+ uint64_t u64;
+ struct cvmx_pci_win_rd_data_s {
+ uint64_t rd_data:64;
+ } s;
+ struct cvmx_pci_win_rd_data_s cn30xx;
+ struct cvmx_pci_win_rd_data_s cn31xx;
+ struct cvmx_pci_win_rd_data_s cn38xx;
+ struct cvmx_pci_win_rd_data_s cn38xxp2;
+ struct cvmx_pci_win_rd_data_s cn50xx;
+ struct cvmx_pci_win_rd_data_s cn58xx;
+ struct cvmx_pci_win_rd_data_s cn58xxp1;
+};
+
+union cvmx_pci_win_wr_addr {
+ uint64_t u64;
+ struct cvmx_pci_win_wr_addr_s {
+ uint64_t reserved_49_63:15;
+ uint64_t iobit:1;
+ uint64_t wr_addr:45;
+ uint64_t reserved_0_2:3;
+ } s;
+ struct cvmx_pci_win_wr_addr_s cn30xx;
+ struct cvmx_pci_win_wr_addr_s cn31xx;
+ struct cvmx_pci_win_wr_addr_s cn38xx;
+ struct cvmx_pci_win_wr_addr_s cn38xxp2;
+ struct cvmx_pci_win_wr_addr_s cn50xx;
+ struct cvmx_pci_win_wr_addr_s cn58xx;
+ struct cvmx_pci_win_wr_addr_s cn58xxp1;
+};
+
+union cvmx_pci_win_wr_data {
+ uint64_t u64;
+ struct cvmx_pci_win_wr_data_s {
+ uint64_t wr_data:64;
+ } s;
+ struct cvmx_pci_win_wr_data_s cn30xx;
+ struct cvmx_pci_win_wr_data_s cn31xx;
+ struct cvmx_pci_win_wr_data_s cn38xx;
+ struct cvmx_pci_win_wr_data_s cn38xxp2;
+ struct cvmx_pci_win_wr_data_s cn50xx;
+ struct cvmx_pci_win_wr_data_s cn58xx;
+ struct cvmx_pci_win_wr_data_s cn58xxp1;
+};
+
+union cvmx_pci_win_wr_mask {
+ uint64_t u64;
+ struct cvmx_pci_win_wr_mask_s {
+ uint64_t reserved_8_63:56;
+ uint64_t wr_mask:8;
+ } s;
+ struct cvmx_pci_win_wr_mask_s cn30xx;
+ struct cvmx_pci_win_wr_mask_s cn31xx;
+ struct cvmx_pci_win_wr_mask_s cn38xx;
+ struct cvmx_pci_win_wr_mask_s cn38xxp2;
+ struct cvmx_pci_win_wr_mask_s cn50xx;
+ struct cvmx_pci_win_wr_mask_s cn58xx;
+ struct cvmx_pci_win_wr_mask_s cn58xxp1;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-pcieep-defs.h b/arch/mips/include/asm/octeon/cvmx-pcieep-defs.h
new file mode 100644
index 000000000000..d553f8e88df6
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-pcieep-defs.h
@@ -0,0 +1,1365 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_PCIEEP_DEFS_H__
+#define __CVMX_PCIEEP_DEFS_H__
+
+#define CVMX_PCIEEP_CFG000 \
+ (0x0000000000000000ull)
+#define CVMX_PCIEEP_CFG001 \
+ (0x0000000000000004ull)
+#define CVMX_PCIEEP_CFG002 \
+ (0x0000000000000008ull)
+#define CVMX_PCIEEP_CFG003 \
+ (0x000000000000000Cull)
+#define CVMX_PCIEEP_CFG004 \
+ (0x0000000000000010ull)
+#define CVMX_PCIEEP_CFG004_MASK \
+ (0x0000000080000010ull)
+#define CVMX_PCIEEP_CFG005 \
+ (0x0000000000000014ull)
+#define CVMX_PCIEEP_CFG005_MASK \
+ (0x0000000080000014ull)
+#define CVMX_PCIEEP_CFG006 \
+ (0x0000000000000018ull)
+#define CVMX_PCIEEP_CFG006_MASK \
+ (0x0000000080000018ull)
+#define CVMX_PCIEEP_CFG007 \
+ (0x000000000000001Cull)
+#define CVMX_PCIEEP_CFG007_MASK \
+ (0x000000008000001Cull)
+#define CVMX_PCIEEP_CFG008 \
+ (0x0000000000000020ull)
+#define CVMX_PCIEEP_CFG008_MASK \
+ (0x0000000080000020ull)
+#define CVMX_PCIEEP_CFG009 \
+ (0x0000000000000024ull)
+#define CVMX_PCIEEP_CFG009_MASK \
+ (0x0000000080000024ull)
+#define CVMX_PCIEEP_CFG010 \
+ (0x0000000000000028ull)
+#define CVMX_PCIEEP_CFG011 \
+ (0x000000000000002Cull)
+#define CVMX_PCIEEP_CFG012 \
+ (0x0000000000000030ull)
+#define CVMX_PCIEEP_CFG012_MASK \
+ (0x0000000080000030ull)
+#define CVMX_PCIEEP_CFG013 \
+ (0x0000000000000034ull)
+#define CVMX_PCIEEP_CFG015 \
+ (0x000000000000003Cull)
+#define CVMX_PCIEEP_CFG016 \
+ (0x0000000000000040ull)
+#define CVMX_PCIEEP_CFG017 \
+ (0x0000000000000044ull)
+#define CVMX_PCIEEP_CFG020 \
+ (0x0000000000000050ull)
+#define CVMX_PCIEEP_CFG021 \
+ (0x0000000000000054ull)
+#define CVMX_PCIEEP_CFG022 \
+ (0x0000000000000058ull)
+#define CVMX_PCIEEP_CFG023 \
+ (0x000000000000005Cull)
+#define CVMX_PCIEEP_CFG028 \
+ (0x0000000000000070ull)
+#define CVMX_PCIEEP_CFG029 \
+ (0x0000000000000074ull)
+#define CVMX_PCIEEP_CFG030 \
+ (0x0000000000000078ull)
+#define CVMX_PCIEEP_CFG031 \
+ (0x000000000000007Cull)
+#define CVMX_PCIEEP_CFG032 \
+ (0x0000000000000080ull)
+#define CVMX_PCIEEP_CFG033 \
+ (0x0000000000000084ull)
+#define CVMX_PCIEEP_CFG034 \
+ (0x0000000000000088ull)
+#define CVMX_PCIEEP_CFG037 \
+ (0x0000000000000094ull)
+#define CVMX_PCIEEP_CFG038 \
+ (0x0000000000000098ull)
+#define CVMX_PCIEEP_CFG039 \
+ (0x000000000000009Cull)
+#define CVMX_PCIEEP_CFG040 \
+ (0x00000000000000A0ull)
+#define CVMX_PCIEEP_CFG041 \
+ (0x00000000000000A4ull)
+#define CVMX_PCIEEP_CFG042 \
+ (0x00000000000000A8ull)
+#define CVMX_PCIEEP_CFG064 \
+ (0x0000000000000100ull)
+#define CVMX_PCIEEP_CFG065 \
+ (0x0000000000000104ull)
+#define CVMX_PCIEEP_CFG066 \
+ (0x0000000000000108ull)
+#define CVMX_PCIEEP_CFG067 \
+ (0x000000000000010Cull)
+#define CVMX_PCIEEP_CFG068 \
+ (0x0000000000000110ull)
+#define CVMX_PCIEEP_CFG069 \
+ (0x0000000000000114ull)
+#define CVMX_PCIEEP_CFG070 \
+ (0x0000000000000118ull)
+#define CVMX_PCIEEP_CFG071 \
+ (0x000000000000011Cull)
+#define CVMX_PCIEEP_CFG072 \
+ (0x0000000000000120ull)
+#define CVMX_PCIEEP_CFG073 \
+ (0x0000000000000124ull)
+#define CVMX_PCIEEP_CFG074 \
+ (0x0000000000000128ull)
+#define CVMX_PCIEEP_CFG448 \
+ (0x0000000000000700ull)
+#define CVMX_PCIEEP_CFG449 \
+ (0x0000000000000704ull)
+#define CVMX_PCIEEP_CFG450 \
+ (0x0000000000000708ull)
+#define CVMX_PCIEEP_CFG451 \
+ (0x000000000000070Cull)
+#define CVMX_PCIEEP_CFG452 \
+ (0x0000000000000710ull)
+#define CVMX_PCIEEP_CFG453 \
+ (0x0000000000000714ull)
+#define CVMX_PCIEEP_CFG454 \
+ (0x0000000000000718ull)
+#define CVMX_PCIEEP_CFG455 \
+ (0x000000000000071Cull)
+#define CVMX_PCIEEP_CFG456 \
+ (0x0000000000000720ull)
+#define CVMX_PCIEEP_CFG458 \
+ (0x0000000000000728ull)
+#define CVMX_PCIEEP_CFG459 \
+ (0x000000000000072Cull)
+#define CVMX_PCIEEP_CFG460 \
+ (0x0000000000000730ull)
+#define CVMX_PCIEEP_CFG461 \
+ (0x0000000000000734ull)
+#define CVMX_PCIEEP_CFG462 \
+ (0x0000000000000738ull)
+#define CVMX_PCIEEP_CFG463 \
+ (0x000000000000073Cull)
+#define CVMX_PCIEEP_CFG464 \
+ (0x0000000000000740ull)
+#define CVMX_PCIEEP_CFG465 \
+ (0x0000000000000744ull)
+#define CVMX_PCIEEP_CFG466 \
+ (0x0000000000000748ull)
+#define CVMX_PCIEEP_CFG467 \
+ (0x000000000000074Cull)
+#define CVMX_PCIEEP_CFG468 \
+ (0x0000000000000750ull)
+#define CVMX_PCIEEP_CFG490 \
+ (0x00000000000007A8ull)
+#define CVMX_PCIEEP_CFG491 \
+ (0x00000000000007ACull)
+#define CVMX_PCIEEP_CFG492 \
+ (0x00000000000007B0ull)
+#define CVMX_PCIEEP_CFG516 \
+ (0x0000000000000810ull)
+#define CVMX_PCIEEP_CFG517 \
+ (0x0000000000000814ull)
+
+union cvmx_pcieep_cfg000 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg000_s {
+ uint32_t devid:16;
+ uint32_t vendid:16;
+ } s;
+ struct cvmx_pcieep_cfg000_s cn52xx;
+ struct cvmx_pcieep_cfg000_s cn52xxp1;
+ struct cvmx_pcieep_cfg000_s cn56xx;
+ struct cvmx_pcieep_cfg000_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg001 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg001_s {
+ uint32_t dpe:1;
+ uint32_t sse:1;
+ uint32_t rma:1;
+ uint32_t rta:1;
+ uint32_t sta:1;
+ uint32_t devt:2;
+ uint32_t mdpe:1;
+ uint32_t fbb:1;
+ uint32_t reserved_22_22:1;
+ uint32_t m66:1;
+ uint32_t cl:1;
+ uint32_t i_stat:1;
+ uint32_t reserved_11_18:8;
+ uint32_t i_dis:1;
+ uint32_t fbbe:1;
+ uint32_t see:1;
+ uint32_t ids_wcc:1;
+ uint32_t per:1;
+ uint32_t vps:1;
+ uint32_t mwice:1;
+ uint32_t scse:1;
+ uint32_t me:1;
+ uint32_t msae:1;
+ uint32_t isae:1;
+ } s;
+ struct cvmx_pcieep_cfg001_s cn52xx;
+ struct cvmx_pcieep_cfg001_s cn52xxp1;
+ struct cvmx_pcieep_cfg001_s cn56xx;
+ struct cvmx_pcieep_cfg001_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg002 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg002_s {
+ uint32_t bcc:8;
+ uint32_t sc:8;
+ uint32_t pi:8;
+ uint32_t rid:8;
+ } s;
+ struct cvmx_pcieep_cfg002_s cn52xx;
+ struct cvmx_pcieep_cfg002_s cn52xxp1;
+ struct cvmx_pcieep_cfg002_s cn56xx;
+ struct cvmx_pcieep_cfg002_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg003 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg003_s {
+ uint32_t bist:8;
+ uint32_t mfd:1;
+ uint32_t chf:7;
+ uint32_t lt:8;
+ uint32_t cls:8;
+ } s;
+ struct cvmx_pcieep_cfg003_s cn52xx;
+ struct cvmx_pcieep_cfg003_s cn52xxp1;
+ struct cvmx_pcieep_cfg003_s cn56xx;
+ struct cvmx_pcieep_cfg003_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg004 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg004_s {
+ uint32_t lbab:18;
+ uint32_t reserved_4_13:10;
+ uint32_t pf:1;
+ uint32_t typ:2;
+ uint32_t mspc:1;
+ } s;
+ struct cvmx_pcieep_cfg004_s cn52xx;
+ struct cvmx_pcieep_cfg004_s cn52xxp1;
+ struct cvmx_pcieep_cfg004_s cn56xx;
+ struct cvmx_pcieep_cfg004_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg004_mask {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg004_mask_s {
+ uint32_t lmask:31;
+ uint32_t enb:1;
+ } s;
+ struct cvmx_pcieep_cfg004_mask_s cn52xx;
+ struct cvmx_pcieep_cfg004_mask_s cn52xxp1;
+ struct cvmx_pcieep_cfg004_mask_s cn56xx;
+ struct cvmx_pcieep_cfg004_mask_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg005 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg005_s {
+ uint32_t ubab:32;
+ } s;
+ struct cvmx_pcieep_cfg005_s cn52xx;
+ struct cvmx_pcieep_cfg005_s cn52xxp1;
+ struct cvmx_pcieep_cfg005_s cn56xx;
+ struct cvmx_pcieep_cfg005_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg005_mask {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg005_mask_s {
+ uint32_t umask:32;
+ } s;
+ struct cvmx_pcieep_cfg005_mask_s cn52xx;
+ struct cvmx_pcieep_cfg005_mask_s cn52xxp1;
+ struct cvmx_pcieep_cfg005_mask_s cn56xx;
+ struct cvmx_pcieep_cfg005_mask_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg006 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg006_s {
+ uint32_t lbab:6;
+ uint32_t reserved_4_25:22;
+ uint32_t pf:1;
+ uint32_t typ:2;
+ uint32_t mspc:1;
+ } s;
+ struct cvmx_pcieep_cfg006_s cn52xx;
+ struct cvmx_pcieep_cfg006_s cn52xxp1;
+ struct cvmx_pcieep_cfg006_s cn56xx;
+ struct cvmx_pcieep_cfg006_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg006_mask {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg006_mask_s {
+ uint32_t lmask:31;
+ uint32_t enb:1;
+ } s;
+ struct cvmx_pcieep_cfg006_mask_s cn52xx;
+ struct cvmx_pcieep_cfg006_mask_s cn52xxp1;
+ struct cvmx_pcieep_cfg006_mask_s cn56xx;
+ struct cvmx_pcieep_cfg006_mask_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg007 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg007_s {
+ uint32_t ubab:32;
+ } s;
+ struct cvmx_pcieep_cfg007_s cn52xx;
+ struct cvmx_pcieep_cfg007_s cn52xxp1;
+ struct cvmx_pcieep_cfg007_s cn56xx;
+ struct cvmx_pcieep_cfg007_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg007_mask {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg007_mask_s {
+ uint32_t umask:32;
+ } s;
+ struct cvmx_pcieep_cfg007_mask_s cn52xx;
+ struct cvmx_pcieep_cfg007_mask_s cn52xxp1;
+ struct cvmx_pcieep_cfg007_mask_s cn56xx;
+ struct cvmx_pcieep_cfg007_mask_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg008 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg008_s {
+ uint32_t reserved_4_31:28;
+ uint32_t pf:1;
+ uint32_t typ:2;
+ uint32_t mspc:1;
+ } s;
+ struct cvmx_pcieep_cfg008_s cn52xx;
+ struct cvmx_pcieep_cfg008_s cn52xxp1;
+ struct cvmx_pcieep_cfg008_s cn56xx;
+ struct cvmx_pcieep_cfg008_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg008_mask {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg008_mask_s {
+ uint32_t lmask:31;
+ uint32_t enb:1;
+ } s;
+ struct cvmx_pcieep_cfg008_mask_s cn52xx;
+ struct cvmx_pcieep_cfg008_mask_s cn52xxp1;
+ struct cvmx_pcieep_cfg008_mask_s cn56xx;
+ struct cvmx_pcieep_cfg008_mask_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg009 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg009_s {
+ uint32_t ubab:25;
+ uint32_t reserved_0_6:7;
+ } s;
+ struct cvmx_pcieep_cfg009_s cn52xx;
+ struct cvmx_pcieep_cfg009_s cn52xxp1;
+ struct cvmx_pcieep_cfg009_s cn56xx;
+ struct cvmx_pcieep_cfg009_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg009_mask {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg009_mask_s {
+ uint32_t umask:32;
+ } s;
+ struct cvmx_pcieep_cfg009_mask_s cn52xx;
+ struct cvmx_pcieep_cfg009_mask_s cn52xxp1;
+ struct cvmx_pcieep_cfg009_mask_s cn56xx;
+ struct cvmx_pcieep_cfg009_mask_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg010 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg010_s {
+ uint32_t cisp:32;
+ } s;
+ struct cvmx_pcieep_cfg010_s cn52xx;
+ struct cvmx_pcieep_cfg010_s cn52xxp1;
+ struct cvmx_pcieep_cfg010_s cn56xx;
+ struct cvmx_pcieep_cfg010_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg011 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg011_s {
+ uint32_t ssid:16;
+ uint32_t ssvid:16;
+ } s;
+ struct cvmx_pcieep_cfg011_s cn52xx;
+ struct cvmx_pcieep_cfg011_s cn52xxp1;
+ struct cvmx_pcieep_cfg011_s cn56xx;
+ struct cvmx_pcieep_cfg011_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg012 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg012_s {
+ uint32_t eraddr:16;
+ uint32_t reserved_1_15:15;
+ uint32_t er_en:1;
+ } s;
+ struct cvmx_pcieep_cfg012_s cn52xx;
+ struct cvmx_pcieep_cfg012_s cn52xxp1;
+ struct cvmx_pcieep_cfg012_s cn56xx;
+ struct cvmx_pcieep_cfg012_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg012_mask {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg012_mask_s {
+ uint32_t mask:31;
+ uint32_t enb:1;
+ } s;
+ struct cvmx_pcieep_cfg012_mask_s cn52xx;
+ struct cvmx_pcieep_cfg012_mask_s cn52xxp1;
+ struct cvmx_pcieep_cfg012_mask_s cn56xx;
+ struct cvmx_pcieep_cfg012_mask_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg013 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg013_s {
+ uint32_t reserved_8_31:24;
+ uint32_t cp:8;
+ } s;
+ struct cvmx_pcieep_cfg013_s cn52xx;
+ struct cvmx_pcieep_cfg013_s cn52xxp1;
+ struct cvmx_pcieep_cfg013_s cn56xx;
+ struct cvmx_pcieep_cfg013_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg015 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg015_s {
+ uint32_t ml:8;
+ uint32_t mg:8;
+ uint32_t inta:8;
+ uint32_t il:8;
+ } s;
+ struct cvmx_pcieep_cfg015_s cn52xx;
+ struct cvmx_pcieep_cfg015_s cn52xxp1;
+ struct cvmx_pcieep_cfg015_s cn56xx;
+ struct cvmx_pcieep_cfg015_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg016 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg016_s {
+ uint32_t pmes:5;
+ uint32_t d2s:1;
+ uint32_t d1s:1;
+ uint32_t auxc:3;
+ uint32_t dsi:1;
+ uint32_t reserved_20_20:1;
+ uint32_t pme_clock:1;
+ uint32_t pmsv:3;
+ uint32_t ncp:8;
+ uint32_t pmcid:8;
+ } s;
+ struct cvmx_pcieep_cfg016_s cn52xx;
+ struct cvmx_pcieep_cfg016_s cn52xxp1;
+ struct cvmx_pcieep_cfg016_s cn56xx;
+ struct cvmx_pcieep_cfg016_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg017 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg017_s {
+ uint32_t pmdia:8;
+ uint32_t bpccee:1;
+ uint32_t bd3h:1;
+ uint32_t reserved_16_21:6;
+ uint32_t pmess:1;
+ uint32_t pmedsia:2;
+ uint32_t pmds:4;
+ uint32_t pmeens:1;
+ uint32_t reserved_4_7:4;
+ uint32_t nsr:1;
+ uint32_t reserved_2_2:1;
+ uint32_t ps:2;
+ } s;
+ struct cvmx_pcieep_cfg017_s cn52xx;
+ struct cvmx_pcieep_cfg017_s cn52xxp1;
+ struct cvmx_pcieep_cfg017_s cn56xx;
+ struct cvmx_pcieep_cfg017_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg020 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg020_s {
+ uint32_t reserved_24_31:8;
+ uint32_t m64:1;
+ uint32_t mme:3;
+ uint32_t mmc:3;
+ uint32_t msien:1;
+ uint32_t ncp:8;
+ uint32_t msicid:8;
+ } s;
+ struct cvmx_pcieep_cfg020_s cn52xx;
+ struct cvmx_pcieep_cfg020_s cn52xxp1;
+ struct cvmx_pcieep_cfg020_s cn56xx;
+ struct cvmx_pcieep_cfg020_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg021 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg021_s {
+ uint32_t lmsi:30;
+ uint32_t reserved_0_1:2;
+ } s;
+ struct cvmx_pcieep_cfg021_s cn52xx;
+ struct cvmx_pcieep_cfg021_s cn52xxp1;
+ struct cvmx_pcieep_cfg021_s cn56xx;
+ struct cvmx_pcieep_cfg021_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg022 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg022_s {
+ uint32_t umsi:32;
+ } s;
+ struct cvmx_pcieep_cfg022_s cn52xx;
+ struct cvmx_pcieep_cfg022_s cn52xxp1;
+ struct cvmx_pcieep_cfg022_s cn56xx;
+ struct cvmx_pcieep_cfg022_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg023 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg023_s {
+ uint32_t reserved_16_31:16;
+ uint32_t msimd:16;
+ } s;
+ struct cvmx_pcieep_cfg023_s cn52xx;
+ struct cvmx_pcieep_cfg023_s cn52xxp1;
+ struct cvmx_pcieep_cfg023_s cn56xx;
+ struct cvmx_pcieep_cfg023_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg028 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg028_s {
+ uint32_t reserved_30_31:2;
+ uint32_t imn:5;
+ uint32_t si:1;
+ uint32_t dpt:4;
+ uint32_t pciecv:4;
+ uint32_t ncp:8;
+ uint32_t pcieid:8;
+ } s;
+ struct cvmx_pcieep_cfg028_s cn52xx;
+ struct cvmx_pcieep_cfg028_s cn52xxp1;
+ struct cvmx_pcieep_cfg028_s cn56xx;
+ struct cvmx_pcieep_cfg028_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg029 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg029_s {
+ uint32_t reserved_28_31:4;
+ uint32_t cspls:2;
+ uint32_t csplv:8;
+ uint32_t reserved_16_17:2;
+ uint32_t rber:1;
+ uint32_t reserved_12_14:3;
+ uint32_t el1al:3;
+ uint32_t el0al:3;
+ uint32_t etfs:1;
+ uint32_t pfs:2;
+ uint32_t mpss:3;
+ } s;
+ struct cvmx_pcieep_cfg029_s cn52xx;
+ struct cvmx_pcieep_cfg029_s cn52xxp1;
+ struct cvmx_pcieep_cfg029_s cn56xx;
+ struct cvmx_pcieep_cfg029_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg030 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg030_s {
+ uint32_t reserved_22_31:10;
+ uint32_t tp:1;
+ uint32_t ap_d:1;
+ uint32_t ur_d:1;
+ uint32_t fe_d:1;
+ uint32_t nfe_d:1;
+ uint32_t ce_d:1;
+ uint32_t reserved_15_15:1;
+ uint32_t mrrs:3;
+ uint32_t ns_en:1;
+ uint32_t ap_en:1;
+ uint32_t pf_en:1;
+ uint32_t etf_en:1;
+ uint32_t mps:3;
+ uint32_t ro_en:1;
+ uint32_t ur_en:1;
+ uint32_t fe_en:1;
+ uint32_t nfe_en:1;
+ uint32_t ce_en:1;
+ } s;
+ struct cvmx_pcieep_cfg030_s cn52xx;
+ struct cvmx_pcieep_cfg030_s cn52xxp1;
+ struct cvmx_pcieep_cfg030_s cn56xx;
+ struct cvmx_pcieep_cfg030_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg031 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg031_s {
+ uint32_t pnum:8;
+ uint32_t reserved_22_23:2;
+ uint32_t lbnc:1;
+ uint32_t dllarc:1;
+ uint32_t sderc:1;
+ uint32_t cpm:1;
+ uint32_t l1el:3;
+ uint32_t l0el:3;
+ uint32_t aslpms:2;
+ uint32_t mlw:6;
+ uint32_t mls:4;
+ } s;
+ struct cvmx_pcieep_cfg031_s cn52xx;
+ struct cvmx_pcieep_cfg031_s cn52xxp1;
+ struct cvmx_pcieep_cfg031_s cn56xx;
+ struct cvmx_pcieep_cfg031_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg032 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg032_s {
+ uint32_t reserved_30_31:2;
+ uint32_t dlla:1;
+ uint32_t scc:1;
+ uint32_t lt:1;
+ uint32_t reserved_26_26:1;
+ uint32_t nlw:6;
+ uint32_t ls:4;
+ uint32_t reserved_10_15:6;
+ uint32_t hawd:1;
+ uint32_t ecpm:1;
+ uint32_t es:1;
+ uint32_t ccc:1;
+ uint32_t rl:1;
+ uint32_t ld:1;
+ uint32_t rcb:1;
+ uint32_t reserved_2_2:1;
+ uint32_t aslpc:2;
+ } s;
+ struct cvmx_pcieep_cfg032_s cn52xx;
+ struct cvmx_pcieep_cfg032_s cn52xxp1;
+ struct cvmx_pcieep_cfg032_s cn56xx;
+ struct cvmx_pcieep_cfg032_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg033 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg033_s {
+ uint32_t ps_num:13;
+ uint32_t nccs:1;
+ uint32_t emip:1;
+ uint32_t sp_ls:2;
+ uint32_t sp_lv:8;
+ uint32_t hp_c:1;
+ uint32_t hp_s:1;
+ uint32_t pip:1;
+ uint32_t aip:1;
+ uint32_t mrlsp:1;
+ uint32_t pcp:1;
+ uint32_t abp:1;
+ } s;
+ struct cvmx_pcieep_cfg033_s cn52xx;
+ struct cvmx_pcieep_cfg033_s cn52xxp1;
+ struct cvmx_pcieep_cfg033_s cn56xx;
+ struct cvmx_pcieep_cfg033_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg034 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg034_s {
+ uint32_t reserved_25_31:7;
+ uint32_t dlls_c:1;
+ uint32_t emis:1;
+ uint32_t pds:1;
+ uint32_t mrlss:1;
+ uint32_t ccint_d:1;
+ uint32_t pd_c:1;
+ uint32_t mrls_c:1;
+ uint32_t pf_d:1;
+ uint32_t abp_d:1;
+ uint32_t reserved_13_15:3;
+ uint32_t dlls_en:1;
+ uint32_t emic:1;
+ uint32_t pcc:1;
+ uint32_t pic:2;
+ uint32_t aic:2;
+ uint32_t hpint_en:1;
+ uint32_t ccint_en:1;
+ uint32_t pd_en:1;
+ uint32_t mrls_en:1;
+ uint32_t pf_en:1;
+ uint32_t abp_en:1;
+ } s;
+ struct cvmx_pcieep_cfg034_s cn52xx;
+ struct cvmx_pcieep_cfg034_s cn52xxp1;
+ struct cvmx_pcieep_cfg034_s cn56xx;
+ struct cvmx_pcieep_cfg034_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg037 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg037_s {
+ uint32_t reserved_5_31:27;
+ uint32_t ctds:1;
+ uint32_t ctrs:4;
+ } s;
+ struct cvmx_pcieep_cfg037_s cn52xx;
+ struct cvmx_pcieep_cfg037_s cn52xxp1;
+ struct cvmx_pcieep_cfg037_s cn56xx;
+ struct cvmx_pcieep_cfg037_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg038 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg038_s {
+ uint32_t reserved_5_31:27;
+ uint32_t ctd:1;
+ uint32_t ctv:4;
+ } s;
+ struct cvmx_pcieep_cfg038_s cn52xx;
+ struct cvmx_pcieep_cfg038_s cn52xxp1;
+ struct cvmx_pcieep_cfg038_s cn56xx;
+ struct cvmx_pcieep_cfg038_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg039 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg039_s {
+ uint32_t reserved_0_31:32;
+ } s;
+ struct cvmx_pcieep_cfg039_s cn52xx;
+ struct cvmx_pcieep_cfg039_s cn52xxp1;
+ struct cvmx_pcieep_cfg039_s cn56xx;
+ struct cvmx_pcieep_cfg039_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg040 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg040_s {
+ uint32_t reserved_0_31:32;
+ } s;
+ struct cvmx_pcieep_cfg040_s cn52xx;
+ struct cvmx_pcieep_cfg040_s cn52xxp1;
+ struct cvmx_pcieep_cfg040_s cn56xx;
+ struct cvmx_pcieep_cfg040_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg041 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg041_s {
+ uint32_t reserved_0_31:32;
+ } s;
+ struct cvmx_pcieep_cfg041_s cn52xx;
+ struct cvmx_pcieep_cfg041_s cn52xxp1;
+ struct cvmx_pcieep_cfg041_s cn56xx;
+ struct cvmx_pcieep_cfg041_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg042 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg042_s {
+ uint32_t reserved_0_31:32;
+ } s;
+ struct cvmx_pcieep_cfg042_s cn52xx;
+ struct cvmx_pcieep_cfg042_s cn52xxp1;
+ struct cvmx_pcieep_cfg042_s cn56xx;
+ struct cvmx_pcieep_cfg042_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg064 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg064_s {
+ uint32_t nco:12;
+ uint32_t cv:4;
+ uint32_t pcieec:16;
+ } s;
+ struct cvmx_pcieep_cfg064_s cn52xx;
+ struct cvmx_pcieep_cfg064_s cn52xxp1;
+ struct cvmx_pcieep_cfg064_s cn56xx;
+ struct cvmx_pcieep_cfg064_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg065 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg065_s {
+ uint32_t reserved_21_31:11;
+ uint32_t ures:1;
+ uint32_t ecrces:1;
+ uint32_t mtlps:1;
+ uint32_t ros:1;
+ uint32_t ucs:1;
+ uint32_t cas:1;
+ uint32_t cts:1;
+ uint32_t fcpes:1;
+ uint32_t ptlps:1;
+ uint32_t reserved_6_11:6;
+ uint32_t sdes:1;
+ uint32_t dlpes:1;
+ uint32_t reserved_0_3:4;
+ } s;
+ struct cvmx_pcieep_cfg065_s cn52xx;
+ struct cvmx_pcieep_cfg065_s cn52xxp1;
+ struct cvmx_pcieep_cfg065_s cn56xx;
+ struct cvmx_pcieep_cfg065_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg066 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg066_s {
+ uint32_t reserved_21_31:11;
+ uint32_t urem:1;
+ uint32_t ecrcem:1;
+ uint32_t mtlpm:1;
+ uint32_t rom:1;
+ uint32_t ucm:1;
+ uint32_t cam:1;
+ uint32_t ctm:1;
+ uint32_t fcpem:1;
+ uint32_t ptlpm:1;
+ uint32_t reserved_6_11:6;
+ uint32_t sdem:1;
+ uint32_t dlpem:1;
+ uint32_t reserved_0_3:4;
+ } s;
+ struct cvmx_pcieep_cfg066_s cn52xx;
+ struct cvmx_pcieep_cfg066_s cn52xxp1;
+ struct cvmx_pcieep_cfg066_s cn56xx;
+ struct cvmx_pcieep_cfg066_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg067 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg067_s {
+ uint32_t reserved_21_31:11;
+ uint32_t ures:1;
+ uint32_t ecrces:1;
+ uint32_t mtlps:1;
+ uint32_t ros:1;
+ uint32_t ucs:1;
+ uint32_t cas:1;
+ uint32_t cts:1;
+ uint32_t fcpes:1;
+ uint32_t ptlps:1;
+ uint32_t reserved_6_11:6;
+ uint32_t sdes:1;
+ uint32_t dlpes:1;
+ uint32_t reserved_0_3:4;
+ } s;
+ struct cvmx_pcieep_cfg067_s cn52xx;
+ struct cvmx_pcieep_cfg067_s cn52xxp1;
+ struct cvmx_pcieep_cfg067_s cn56xx;
+ struct cvmx_pcieep_cfg067_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg068 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg068_s {
+ uint32_t reserved_14_31:18;
+ uint32_t anfes:1;
+ uint32_t rtts:1;
+ uint32_t reserved_9_11:3;
+ uint32_t rnrs:1;
+ uint32_t bdllps:1;
+ uint32_t btlps:1;
+ uint32_t reserved_1_5:5;
+ uint32_t res:1;
+ } s;
+ struct cvmx_pcieep_cfg068_s cn52xx;
+ struct cvmx_pcieep_cfg068_s cn52xxp1;
+ struct cvmx_pcieep_cfg068_s cn56xx;
+ struct cvmx_pcieep_cfg068_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg069 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg069_s {
+ uint32_t reserved_14_31:18;
+ uint32_t anfem:1;
+ uint32_t rttm:1;
+ uint32_t reserved_9_11:3;
+ uint32_t rnrm:1;
+ uint32_t bdllpm:1;
+ uint32_t btlpm:1;
+ uint32_t reserved_1_5:5;
+ uint32_t rem:1;
+ } s;
+ struct cvmx_pcieep_cfg069_s cn52xx;
+ struct cvmx_pcieep_cfg069_s cn52xxp1;
+ struct cvmx_pcieep_cfg069_s cn56xx;
+ struct cvmx_pcieep_cfg069_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg070 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg070_s {
+ uint32_t reserved_9_31:23;
+ uint32_t ce:1;
+ uint32_t cc:1;
+ uint32_t ge:1;
+ uint32_t gc:1;
+ uint32_t fep:5;
+ } s;
+ struct cvmx_pcieep_cfg070_s cn52xx;
+ struct cvmx_pcieep_cfg070_s cn52xxp1;
+ struct cvmx_pcieep_cfg070_s cn56xx;
+ struct cvmx_pcieep_cfg070_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg071 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg071_s {
+ uint32_t dword1:32;
+ } s;
+ struct cvmx_pcieep_cfg071_s cn52xx;
+ struct cvmx_pcieep_cfg071_s cn52xxp1;
+ struct cvmx_pcieep_cfg071_s cn56xx;
+ struct cvmx_pcieep_cfg071_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg072 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg072_s {
+ uint32_t dword2:32;
+ } s;
+ struct cvmx_pcieep_cfg072_s cn52xx;
+ struct cvmx_pcieep_cfg072_s cn52xxp1;
+ struct cvmx_pcieep_cfg072_s cn56xx;
+ struct cvmx_pcieep_cfg072_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg073 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg073_s {
+ uint32_t dword3:32;
+ } s;
+ struct cvmx_pcieep_cfg073_s cn52xx;
+ struct cvmx_pcieep_cfg073_s cn52xxp1;
+ struct cvmx_pcieep_cfg073_s cn56xx;
+ struct cvmx_pcieep_cfg073_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg074 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg074_s {
+ uint32_t dword4:32;
+ } s;
+ struct cvmx_pcieep_cfg074_s cn52xx;
+ struct cvmx_pcieep_cfg074_s cn52xxp1;
+ struct cvmx_pcieep_cfg074_s cn56xx;
+ struct cvmx_pcieep_cfg074_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg448 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg448_s {
+ uint32_t rtl:16;
+ uint32_t rtltl:16;
+ } s;
+ struct cvmx_pcieep_cfg448_s cn52xx;
+ struct cvmx_pcieep_cfg448_s cn52xxp1;
+ struct cvmx_pcieep_cfg448_s cn56xx;
+ struct cvmx_pcieep_cfg448_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg449 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg449_s {
+ uint32_t omr:32;
+ } s;
+ struct cvmx_pcieep_cfg449_s cn52xx;
+ struct cvmx_pcieep_cfg449_s cn52xxp1;
+ struct cvmx_pcieep_cfg449_s cn56xx;
+ struct cvmx_pcieep_cfg449_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg450 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg450_s {
+ uint32_t lpec:8;
+ uint32_t reserved_22_23:2;
+ uint32_t link_state:6;
+ uint32_t force_link:1;
+ uint32_t reserved_8_14:7;
+ uint32_t link_num:8;
+ } s;
+ struct cvmx_pcieep_cfg450_s cn52xx;
+ struct cvmx_pcieep_cfg450_s cn52xxp1;
+ struct cvmx_pcieep_cfg450_s cn56xx;
+ struct cvmx_pcieep_cfg450_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg451 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg451_s {
+ uint32_t reserved_30_31:2;
+ uint32_t l1el:3;
+ uint32_t l0el:3;
+ uint32_t n_fts_cc:8;
+ uint32_t n_fts:8;
+ uint32_t ack_freq:8;
+ } s;
+ struct cvmx_pcieep_cfg451_s cn52xx;
+ struct cvmx_pcieep_cfg451_s cn52xxp1;
+ struct cvmx_pcieep_cfg451_s cn56xx;
+ struct cvmx_pcieep_cfg451_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg452 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg452_s {
+ uint32_t reserved_26_31:6;
+ uint32_t eccrc:1;
+ uint32_t reserved_22_24:3;
+ uint32_t lme:6;
+ uint32_t reserved_8_15:8;
+ uint32_t flm:1;
+ uint32_t reserved_6_6:1;
+ uint32_t dllle:1;
+ uint32_t reserved_4_4:1;
+ uint32_t ra:1;
+ uint32_t le:1;
+ uint32_t sd:1;
+ uint32_t omr:1;
+ } s;
+ struct cvmx_pcieep_cfg452_s cn52xx;
+ struct cvmx_pcieep_cfg452_s cn52xxp1;
+ struct cvmx_pcieep_cfg452_s cn56xx;
+ struct cvmx_pcieep_cfg452_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg453 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg453_s {
+ uint32_t dlld:1;
+ uint32_t reserved_26_30:5;
+ uint32_t ack_nak:1;
+ uint32_t fcd:1;
+ uint32_t ilst:24;
+ } s;
+ struct cvmx_pcieep_cfg453_s cn52xx;
+ struct cvmx_pcieep_cfg453_s cn52xxp1;
+ struct cvmx_pcieep_cfg453_s cn56xx;
+ struct cvmx_pcieep_cfg453_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg454 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg454_s {
+ uint32_t reserved_29_31:3;
+ uint32_t tmfcwt:5;
+ uint32_t tmanlt:5;
+ uint32_t tmrt:5;
+ uint32_t reserved_11_13:3;
+ uint32_t nskps:3;
+ uint32_t reserved_4_7:4;
+ uint32_t ntss:4;
+ } s;
+ struct cvmx_pcieep_cfg454_s cn52xx;
+ struct cvmx_pcieep_cfg454_s cn52xxp1;
+ struct cvmx_pcieep_cfg454_s cn56xx;
+ struct cvmx_pcieep_cfg454_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg455 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg455_s {
+ uint32_t m_cfg0_filt:1;
+ uint32_t m_io_filt:1;
+ uint32_t msg_ctrl:1;
+ uint32_t m_cpl_ecrc_filt:1;
+ uint32_t m_ecrc_filt:1;
+ uint32_t m_cpl_len_err:1;
+ uint32_t m_cpl_attr_err:1;
+ uint32_t m_cpl_tc_err:1;
+ uint32_t m_cpl_fun_err:1;
+ uint32_t m_cpl_rid_err:1;
+ uint32_t m_cpl_tag_err:1;
+ uint32_t m_lk_filt:1;
+ uint32_t m_cfg1_filt:1;
+ uint32_t m_bar_match:1;
+ uint32_t m_pois_filt:1;
+ uint32_t m_fun:1;
+ uint32_t dfcwt:1;
+ uint32_t reserved_11_14:4;
+ uint32_t skpiv:11;
+ } s;
+ struct cvmx_pcieep_cfg455_s cn52xx;
+ struct cvmx_pcieep_cfg455_s cn52xxp1;
+ struct cvmx_pcieep_cfg455_s cn56xx;
+ struct cvmx_pcieep_cfg455_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg456 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg456_s {
+ uint32_t reserved_2_31:30;
+ uint32_t m_vend1_drp:1;
+ uint32_t m_vend0_drp:1;
+ } s;
+ struct cvmx_pcieep_cfg456_s cn52xx;
+ struct cvmx_pcieep_cfg456_s cn52xxp1;
+ struct cvmx_pcieep_cfg456_s cn56xx;
+ struct cvmx_pcieep_cfg456_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg458 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg458_s {
+ uint32_t dbg_info_l32:32;
+ } s;
+ struct cvmx_pcieep_cfg458_s cn52xx;
+ struct cvmx_pcieep_cfg458_s cn52xxp1;
+ struct cvmx_pcieep_cfg458_s cn56xx;
+ struct cvmx_pcieep_cfg458_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg459 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg459_s {
+ uint32_t dbg_info_u32:32;
+ } s;
+ struct cvmx_pcieep_cfg459_s cn52xx;
+ struct cvmx_pcieep_cfg459_s cn52xxp1;
+ struct cvmx_pcieep_cfg459_s cn56xx;
+ struct cvmx_pcieep_cfg459_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg460 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg460_s {
+ uint32_t reserved_20_31:12;
+ uint32_t tphfcc:8;
+ uint32_t tpdfcc:12;
+ } s;
+ struct cvmx_pcieep_cfg460_s cn52xx;
+ struct cvmx_pcieep_cfg460_s cn52xxp1;
+ struct cvmx_pcieep_cfg460_s cn56xx;
+ struct cvmx_pcieep_cfg460_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg461 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg461_s {
+ uint32_t reserved_20_31:12;
+ uint32_t tchfcc:8;
+ uint32_t tcdfcc:12;
+ } s;
+ struct cvmx_pcieep_cfg461_s cn52xx;
+ struct cvmx_pcieep_cfg461_s cn52xxp1;
+ struct cvmx_pcieep_cfg461_s cn56xx;
+ struct cvmx_pcieep_cfg461_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg462 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg462_s {
+ uint32_t reserved_20_31:12;
+ uint32_t tchfcc:8;
+ uint32_t tcdfcc:12;
+ } s;
+ struct cvmx_pcieep_cfg462_s cn52xx;
+ struct cvmx_pcieep_cfg462_s cn52xxp1;
+ struct cvmx_pcieep_cfg462_s cn56xx;
+ struct cvmx_pcieep_cfg462_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg463 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg463_s {
+ uint32_t reserved_3_31:29;
+ uint32_t rqne:1;
+ uint32_t trbne:1;
+ uint32_t rtlpfccnr:1;
+ } s;
+ struct cvmx_pcieep_cfg463_s cn52xx;
+ struct cvmx_pcieep_cfg463_s cn52xxp1;
+ struct cvmx_pcieep_cfg463_s cn56xx;
+ struct cvmx_pcieep_cfg463_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg464 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg464_s {
+ uint32_t wrr_vc3:8;
+ uint32_t wrr_vc2:8;
+ uint32_t wrr_vc1:8;
+ uint32_t wrr_vc0:8;
+ } s;
+ struct cvmx_pcieep_cfg464_s cn52xx;
+ struct cvmx_pcieep_cfg464_s cn52xxp1;
+ struct cvmx_pcieep_cfg464_s cn56xx;
+ struct cvmx_pcieep_cfg464_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg465 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg465_s {
+ uint32_t wrr_vc7:8;
+ uint32_t wrr_vc6:8;
+ uint32_t wrr_vc5:8;
+ uint32_t wrr_vc4:8;
+ } s;
+ struct cvmx_pcieep_cfg465_s cn52xx;
+ struct cvmx_pcieep_cfg465_s cn52xxp1;
+ struct cvmx_pcieep_cfg465_s cn56xx;
+ struct cvmx_pcieep_cfg465_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg466 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg466_s {
+ uint32_t rx_queue_order:1;
+ uint32_t type_ordering:1;
+ uint32_t reserved_24_29:6;
+ uint32_t queue_mode:3;
+ uint32_t reserved_20_20:1;
+ uint32_t header_credits:8;
+ uint32_t data_credits:12;
+ } s;
+ struct cvmx_pcieep_cfg466_s cn52xx;
+ struct cvmx_pcieep_cfg466_s cn52xxp1;
+ struct cvmx_pcieep_cfg466_s cn56xx;
+ struct cvmx_pcieep_cfg466_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg467 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg467_s {
+ uint32_t reserved_24_31:8;
+ uint32_t queue_mode:3;
+ uint32_t reserved_20_20:1;
+ uint32_t header_credits:8;
+ uint32_t data_credits:12;
+ } s;
+ struct cvmx_pcieep_cfg467_s cn52xx;
+ struct cvmx_pcieep_cfg467_s cn52xxp1;
+ struct cvmx_pcieep_cfg467_s cn56xx;
+ struct cvmx_pcieep_cfg467_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg468 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg468_s {
+ uint32_t reserved_24_31:8;
+ uint32_t queue_mode:3;
+ uint32_t reserved_20_20:1;
+ uint32_t header_credits:8;
+ uint32_t data_credits:12;
+ } s;
+ struct cvmx_pcieep_cfg468_s cn52xx;
+ struct cvmx_pcieep_cfg468_s cn52xxp1;
+ struct cvmx_pcieep_cfg468_s cn56xx;
+ struct cvmx_pcieep_cfg468_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg490 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg490_s {
+ uint32_t reserved_26_31:6;
+ uint32_t header_depth:10;
+ uint32_t reserved_14_15:2;
+ uint32_t data_depth:14;
+ } s;
+ struct cvmx_pcieep_cfg490_s cn52xx;
+ struct cvmx_pcieep_cfg490_s cn52xxp1;
+ struct cvmx_pcieep_cfg490_s cn56xx;
+ struct cvmx_pcieep_cfg490_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg491 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg491_s {
+ uint32_t reserved_26_31:6;
+ uint32_t header_depth:10;
+ uint32_t reserved_14_15:2;
+ uint32_t data_depth:14;
+ } s;
+ struct cvmx_pcieep_cfg491_s cn52xx;
+ struct cvmx_pcieep_cfg491_s cn52xxp1;
+ struct cvmx_pcieep_cfg491_s cn56xx;
+ struct cvmx_pcieep_cfg491_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg492 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg492_s {
+ uint32_t reserved_26_31:6;
+ uint32_t header_depth:10;
+ uint32_t reserved_14_15:2;
+ uint32_t data_depth:14;
+ } s;
+ struct cvmx_pcieep_cfg492_s cn52xx;
+ struct cvmx_pcieep_cfg492_s cn52xxp1;
+ struct cvmx_pcieep_cfg492_s cn56xx;
+ struct cvmx_pcieep_cfg492_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg516 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg516_s {
+ uint32_t phy_stat:32;
+ } s;
+ struct cvmx_pcieep_cfg516_s cn52xx;
+ struct cvmx_pcieep_cfg516_s cn52xxp1;
+ struct cvmx_pcieep_cfg516_s cn56xx;
+ struct cvmx_pcieep_cfg516_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg517 {
+ uint32_t u32;
+ struct cvmx_pcieep_cfg517_s {
+ uint32_t phy_ctrl:32;
+ } s;
+ struct cvmx_pcieep_cfg517_s cn52xx;
+ struct cvmx_pcieep_cfg517_s cn52xxp1;
+ struct cvmx_pcieep_cfg517_s cn56xx;
+ struct cvmx_pcieep_cfg517_s cn56xxp1;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-pciercx-defs.h b/arch/mips/include/asm/octeon/cvmx-pciercx-defs.h
new file mode 100644
index 000000000000..75574c918942
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-pciercx-defs.h
@@ -0,0 +1,1397 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_PCIERCX_DEFS_H__
+#define __CVMX_PCIERCX_DEFS_H__
+
+#define CVMX_PCIERCX_CFG000(offset) \
+ (0x0000000000000000ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG001(offset) \
+ (0x0000000000000004ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG002(offset) \
+ (0x0000000000000008ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG003(offset) \
+ (0x000000000000000Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG004(offset) \
+ (0x0000000000000010ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG005(offset) \
+ (0x0000000000000014ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG006(offset) \
+ (0x0000000000000018ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG007(offset) \
+ (0x000000000000001Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG008(offset) \
+ (0x0000000000000020ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG009(offset) \
+ (0x0000000000000024ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG010(offset) \
+ (0x0000000000000028ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG011(offset) \
+ (0x000000000000002Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG012(offset) \
+ (0x0000000000000030ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG013(offset) \
+ (0x0000000000000034ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG014(offset) \
+ (0x0000000000000038ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG015(offset) \
+ (0x000000000000003Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG016(offset) \
+ (0x0000000000000040ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG017(offset) \
+ (0x0000000000000044ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG020(offset) \
+ (0x0000000000000050ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG021(offset) \
+ (0x0000000000000054ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG022(offset) \
+ (0x0000000000000058ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG023(offset) \
+ (0x000000000000005Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG028(offset) \
+ (0x0000000000000070ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG029(offset) \
+ (0x0000000000000074ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG030(offset) \
+ (0x0000000000000078ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG031(offset) \
+ (0x000000000000007Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG032(offset) \
+ (0x0000000000000080ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG033(offset) \
+ (0x0000000000000084ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG034(offset) \
+ (0x0000000000000088ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG035(offset) \
+ (0x000000000000008Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG036(offset) \
+ (0x0000000000000090ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG037(offset) \
+ (0x0000000000000094ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG038(offset) \
+ (0x0000000000000098ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG039(offset) \
+ (0x000000000000009Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG040(offset) \
+ (0x00000000000000A0ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG041(offset) \
+ (0x00000000000000A4ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG042(offset) \
+ (0x00000000000000A8ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG064(offset) \
+ (0x0000000000000100ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG065(offset) \
+ (0x0000000000000104ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG066(offset) \
+ (0x0000000000000108ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG067(offset) \
+ (0x000000000000010Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG068(offset) \
+ (0x0000000000000110ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG069(offset) \
+ (0x0000000000000114ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG070(offset) \
+ (0x0000000000000118ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG071(offset) \
+ (0x000000000000011Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG072(offset) \
+ (0x0000000000000120ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG073(offset) \
+ (0x0000000000000124ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG074(offset) \
+ (0x0000000000000128ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG075(offset) \
+ (0x000000000000012Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG076(offset) \
+ (0x0000000000000130ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG077(offset) \
+ (0x0000000000000134ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG448(offset) \
+ (0x0000000000000700ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG449(offset) \
+ (0x0000000000000704ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG450(offset) \
+ (0x0000000000000708ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG451(offset) \
+ (0x000000000000070Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG452(offset) \
+ (0x0000000000000710ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG453(offset) \
+ (0x0000000000000714ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG454(offset) \
+ (0x0000000000000718ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG455(offset) \
+ (0x000000000000071Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG456(offset) \
+ (0x0000000000000720ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG458(offset) \
+ (0x0000000000000728ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG459(offset) \
+ (0x000000000000072Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG460(offset) \
+ (0x0000000000000730ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG461(offset) \
+ (0x0000000000000734ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG462(offset) \
+ (0x0000000000000738ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG463(offset) \
+ (0x000000000000073Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG464(offset) \
+ (0x0000000000000740ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG465(offset) \
+ (0x0000000000000744ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG466(offset) \
+ (0x0000000000000748ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG467(offset) \
+ (0x000000000000074Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG468(offset) \
+ (0x0000000000000750ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG490(offset) \
+ (0x00000000000007A8ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG491(offset) \
+ (0x00000000000007ACull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG492(offset) \
+ (0x00000000000007B0ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG516(offset) \
+ (0x0000000000000810ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG517(offset) \
+ (0x0000000000000814ull + (((offset) & 1) * 0))
+
+union cvmx_pciercx_cfg000 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg000_s {
+ uint32_t devid:16;
+ uint32_t vendid:16;
+ } s;
+ struct cvmx_pciercx_cfg000_s cn52xx;
+ struct cvmx_pciercx_cfg000_s cn52xxp1;
+ struct cvmx_pciercx_cfg000_s cn56xx;
+ struct cvmx_pciercx_cfg000_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg001 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg001_s {
+ uint32_t dpe:1;
+ uint32_t sse:1;
+ uint32_t rma:1;
+ uint32_t rta:1;
+ uint32_t sta:1;
+ uint32_t devt:2;
+ uint32_t mdpe:1;
+ uint32_t fbb:1;
+ uint32_t reserved_22_22:1;
+ uint32_t m66:1;
+ uint32_t cl:1;
+ uint32_t i_stat:1;
+ uint32_t reserved_11_18:8;
+ uint32_t i_dis:1;
+ uint32_t fbbe:1;
+ uint32_t see:1;
+ uint32_t ids_wcc:1;
+ uint32_t per:1;
+ uint32_t vps:1;
+ uint32_t mwice:1;
+ uint32_t scse:1;
+ uint32_t me:1;
+ uint32_t msae:1;
+ uint32_t isae:1;
+ } s;
+ struct cvmx_pciercx_cfg001_s cn52xx;
+ struct cvmx_pciercx_cfg001_s cn52xxp1;
+ struct cvmx_pciercx_cfg001_s cn56xx;
+ struct cvmx_pciercx_cfg001_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg002 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg002_s {
+ uint32_t bcc:8;
+ uint32_t sc:8;
+ uint32_t pi:8;
+ uint32_t rid:8;
+ } s;
+ struct cvmx_pciercx_cfg002_s cn52xx;
+ struct cvmx_pciercx_cfg002_s cn52xxp1;
+ struct cvmx_pciercx_cfg002_s cn56xx;
+ struct cvmx_pciercx_cfg002_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg003 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg003_s {
+ uint32_t bist:8;
+ uint32_t mfd:1;
+ uint32_t chf:7;
+ uint32_t lt:8;
+ uint32_t cls:8;
+ } s;
+ struct cvmx_pciercx_cfg003_s cn52xx;
+ struct cvmx_pciercx_cfg003_s cn52xxp1;
+ struct cvmx_pciercx_cfg003_s cn56xx;
+ struct cvmx_pciercx_cfg003_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg004 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg004_s {
+ uint32_t reserved_0_31:32;
+ } s;
+ struct cvmx_pciercx_cfg004_s cn52xx;
+ struct cvmx_pciercx_cfg004_s cn52xxp1;
+ struct cvmx_pciercx_cfg004_s cn56xx;
+ struct cvmx_pciercx_cfg004_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg005 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg005_s {
+ uint32_t reserved_0_31:32;
+ } s;
+ struct cvmx_pciercx_cfg005_s cn52xx;
+ struct cvmx_pciercx_cfg005_s cn52xxp1;
+ struct cvmx_pciercx_cfg005_s cn56xx;
+ struct cvmx_pciercx_cfg005_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg006 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg006_s {
+ uint32_t slt:8;
+ uint32_t subbnum:8;
+ uint32_t sbnum:8;
+ uint32_t pbnum:8;
+ } s;
+ struct cvmx_pciercx_cfg006_s cn52xx;
+ struct cvmx_pciercx_cfg006_s cn52xxp1;
+ struct cvmx_pciercx_cfg006_s cn56xx;
+ struct cvmx_pciercx_cfg006_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg007 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg007_s {
+ uint32_t dpe:1;
+ uint32_t sse:1;
+ uint32_t rma:1;
+ uint32_t rta:1;
+ uint32_t sta:1;
+ uint32_t devt:2;
+ uint32_t mdpe:1;
+ uint32_t fbb:1;
+ uint32_t reserved_22_22:1;
+ uint32_t m66:1;
+ uint32_t reserved_16_20:5;
+ uint32_t lio_limi:4;
+ uint32_t reserved_9_11:3;
+ uint32_t io32b:1;
+ uint32_t lio_base:4;
+ uint32_t reserved_1_3:3;
+ uint32_t io32a:1;
+ } s;
+ struct cvmx_pciercx_cfg007_s cn52xx;
+ struct cvmx_pciercx_cfg007_s cn52xxp1;
+ struct cvmx_pciercx_cfg007_s cn56xx;
+ struct cvmx_pciercx_cfg007_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg008 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg008_s {
+ uint32_t ml_addr:12;
+ uint32_t reserved_16_19:4;
+ uint32_t mb_addr:12;
+ uint32_t reserved_0_3:4;
+ } s;
+ struct cvmx_pciercx_cfg008_s cn52xx;
+ struct cvmx_pciercx_cfg008_s cn52xxp1;
+ struct cvmx_pciercx_cfg008_s cn56xx;
+ struct cvmx_pciercx_cfg008_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg009 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg009_s {
+ uint32_t lmem_limit:12;
+ uint32_t reserved_17_19:3;
+ uint32_t mem64b:1;
+ uint32_t lmem_base:12;
+ uint32_t reserved_1_3:3;
+ uint32_t mem64a:1;
+ } s;
+ struct cvmx_pciercx_cfg009_s cn52xx;
+ struct cvmx_pciercx_cfg009_s cn52xxp1;
+ struct cvmx_pciercx_cfg009_s cn56xx;
+ struct cvmx_pciercx_cfg009_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg010 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg010_s {
+ uint32_t umem_base:32;
+ } s;
+ struct cvmx_pciercx_cfg010_s cn52xx;
+ struct cvmx_pciercx_cfg010_s cn52xxp1;
+ struct cvmx_pciercx_cfg010_s cn56xx;
+ struct cvmx_pciercx_cfg010_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg011 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg011_s {
+ uint32_t umem_limit:32;
+ } s;
+ struct cvmx_pciercx_cfg011_s cn52xx;
+ struct cvmx_pciercx_cfg011_s cn52xxp1;
+ struct cvmx_pciercx_cfg011_s cn56xx;
+ struct cvmx_pciercx_cfg011_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg012 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg012_s {
+ uint32_t uio_limit:16;
+ uint32_t uio_base:16;
+ } s;
+ struct cvmx_pciercx_cfg012_s cn52xx;
+ struct cvmx_pciercx_cfg012_s cn52xxp1;
+ struct cvmx_pciercx_cfg012_s cn56xx;
+ struct cvmx_pciercx_cfg012_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg013 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg013_s {
+ uint32_t reserved_8_31:24;
+ uint32_t cp:8;
+ } s;
+ struct cvmx_pciercx_cfg013_s cn52xx;
+ struct cvmx_pciercx_cfg013_s cn52xxp1;
+ struct cvmx_pciercx_cfg013_s cn56xx;
+ struct cvmx_pciercx_cfg013_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg014 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg014_s {
+ uint32_t reserved_0_31:32;
+ } s;
+ struct cvmx_pciercx_cfg014_s cn52xx;
+ struct cvmx_pciercx_cfg014_s cn52xxp1;
+ struct cvmx_pciercx_cfg014_s cn56xx;
+ struct cvmx_pciercx_cfg014_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg015 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg015_s {
+ uint32_t reserved_28_31:4;
+ uint32_t dtsees:1;
+ uint32_t dts:1;
+ uint32_t sdt:1;
+ uint32_t pdt:1;
+ uint32_t fbbe:1;
+ uint32_t sbrst:1;
+ uint32_t mam:1;
+ uint32_t vga16d:1;
+ uint32_t vgae:1;
+ uint32_t isae:1;
+ uint32_t see:1;
+ uint32_t pere:1;
+ uint32_t inta:8;
+ uint32_t il:8;
+ } s;
+ struct cvmx_pciercx_cfg015_s cn52xx;
+ struct cvmx_pciercx_cfg015_s cn52xxp1;
+ struct cvmx_pciercx_cfg015_s cn56xx;
+ struct cvmx_pciercx_cfg015_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg016 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg016_s {
+ uint32_t pmes:5;
+ uint32_t d2s:1;
+ uint32_t d1s:1;
+ uint32_t auxc:3;
+ uint32_t dsi:1;
+ uint32_t reserved_20_20:1;
+ uint32_t pme_clock:1;
+ uint32_t pmsv:3;
+ uint32_t ncp:8;
+ uint32_t pmcid:8;
+ } s;
+ struct cvmx_pciercx_cfg016_s cn52xx;
+ struct cvmx_pciercx_cfg016_s cn52xxp1;
+ struct cvmx_pciercx_cfg016_s cn56xx;
+ struct cvmx_pciercx_cfg016_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg017 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg017_s {
+ uint32_t pmdia:8;
+ uint32_t bpccee:1;
+ uint32_t bd3h:1;
+ uint32_t reserved_16_21:6;
+ uint32_t pmess:1;
+ uint32_t pmedsia:2;
+ uint32_t pmds:4;
+ uint32_t pmeens:1;
+ uint32_t reserved_4_7:4;
+ uint32_t nsr:1;
+ uint32_t reserved_2_2:1;
+ uint32_t ps:2;
+ } s;
+ struct cvmx_pciercx_cfg017_s cn52xx;
+ struct cvmx_pciercx_cfg017_s cn52xxp1;
+ struct cvmx_pciercx_cfg017_s cn56xx;
+ struct cvmx_pciercx_cfg017_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg020 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg020_s {
+ uint32_t reserved_24_31:8;
+ uint32_t m64:1;
+ uint32_t mme:3;
+ uint32_t mmc:3;
+ uint32_t msien:1;
+ uint32_t ncp:8;
+ uint32_t msicid:8;
+ } s;
+ struct cvmx_pciercx_cfg020_s cn52xx;
+ struct cvmx_pciercx_cfg020_s cn52xxp1;
+ struct cvmx_pciercx_cfg020_s cn56xx;
+ struct cvmx_pciercx_cfg020_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg021 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg021_s {
+ uint32_t lmsi:30;
+ uint32_t reserved_0_1:2;
+ } s;
+ struct cvmx_pciercx_cfg021_s cn52xx;
+ struct cvmx_pciercx_cfg021_s cn52xxp1;
+ struct cvmx_pciercx_cfg021_s cn56xx;
+ struct cvmx_pciercx_cfg021_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg022 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg022_s {
+ uint32_t umsi:32;
+ } s;
+ struct cvmx_pciercx_cfg022_s cn52xx;
+ struct cvmx_pciercx_cfg022_s cn52xxp1;
+ struct cvmx_pciercx_cfg022_s cn56xx;
+ struct cvmx_pciercx_cfg022_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg023 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg023_s {
+ uint32_t reserved_16_31:16;
+ uint32_t msimd:16;
+ } s;
+ struct cvmx_pciercx_cfg023_s cn52xx;
+ struct cvmx_pciercx_cfg023_s cn52xxp1;
+ struct cvmx_pciercx_cfg023_s cn56xx;
+ struct cvmx_pciercx_cfg023_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg028 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg028_s {
+ uint32_t reserved_30_31:2;
+ uint32_t imn:5;
+ uint32_t si:1;
+ uint32_t dpt:4;
+ uint32_t pciecv:4;
+ uint32_t ncp:8;
+ uint32_t pcieid:8;
+ } s;
+ struct cvmx_pciercx_cfg028_s cn52xx;
+ struct cvmx_pciercx_cfg028_s cn52xxp1;
+ struct cvmx_pciercx_cfg028_s cn56xx;
+ struct cvmx_pciercx_cfg028_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg029 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg029_s {
+ uint32_t reserved_28_31:4;
+ uint32_t cspls:2;
+ uint32_t csplv:8;
+ uint32_t reserved_16_17:2;
+ uint32_t rber:1;
+ uint32_t reserved_12_14:3;
+ uint32_t el1al:3;
+ uint32_t el0al:3;
+ uint32_t etfs:1;
+ uint32_t pfs:2;
+ uint32_t mpss:3;
+ } s;
+ struct cvmx_pciercx_cfg029_s cn52xx;
+ struct cvmx_pciercx_cfg029_s cn52xxp1;
+ struct cvmx_pciercx_cfg029_s cn56xx;
+ struct cvmx_pciercx_cfg029_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg030 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg030_s {
+ uint32_t reserved_22_31:10;
+ uint32_t tp:1;
+ uint32_t ap_d:1;
+ uint32_t ur_d:1;
+ uint32_t fe_d:1;
+ uint32_t nfe_d:1;
+ uint32_t ce_d:1;
+ uint32_t reserved_15_15:1;
+ uint32_t mrrs:3;
+ uint32_t ns_en:1;
+ uint32_t ap_en:1;
+ uint32_t pf_en:1;
+ uint32_t etf_en:1;
+ uint32_t mps:3;
+ uint32_t ro_en:1;
+ uint32_t ur_en:1;
+ uint32_t fe_en:1;
+ uint32_t nfe_en:1;
+ uint32_t ce_en:1;
+ } s;
+ struct cvmx_pciercx_cfg030_s cn52xx;
+ struct cvmx_pciercx_cfg030_s cn52xxp1;
+ struct cvmx_pciercx_cfg030_s cn56xx;
+ struct cvmx_pciercx_cfg030_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg031 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg031_s {
+ uint32_t pnum:8;
+ uint32_t reserved_22_23:2;
+ uint32_t lbnc:1;
+ uint32_t dllarc:1;
+ uint32_t sderc:1;
+ uint32_t cpm:1;
+ uint32_t l1el:3;
+ uint32_t l0el:3;
+ uint32_t aslpms:2;
+ uint32_t mlw:6;
+ uint32_t mls:4;
+ } s;
+ struct cvmx_pciercx_cfg031_s cn52xx;
+ struct cvmx_pciercx_cfg031_s cn52xxp1;
+ struct cvmx_pciercx_cfg031_s cn56xx;
+ struct cvmx_pciercx_cfg031_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg032 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg032_s {
+ uint32_t lab:1;
+ uint32_t lbm:1;
+ uint32_t dlla:1;
+ uint32_t scc:1;
+ uint32_t lt:1;
+ uint32_t reserved_26_26:1;
+ uint32_t nlw:6;
+ uint32_t ls:4;
+ uint32_t reserved_12_15:4;
+ uint32_t lab_int_enb:1;
+ uint32_t lbm_int_enb:1;
+ uint32_t hawd:1;
+ uint32_t ecpm:1;
+ uint32_t es:1;
+ uint32_t ccc:1;
+ uint32_t rl:1;
+ uint32_t ld:1;
+ uint32_t rcb:1;
+ uint32_t reserved_2_2:1;
+ uint32_t aslpc:2;
+ } s;
+ struct cvmx_pciercx_cfg032_s cn52xx;
+ struct cvmx_pciercx_cfg032_s cn52xxp1;
+ struct cvmx_pciercx_cfg032_s cn56xx;
+ struct cvmx_pciercx_cfg032_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg033 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg033_s {
+ uint32_t ps_num:13;
+ uint32_t nccs:1;
+ uint32_t emip:1;
+ uint32_t sp_ls:2;
+ uint32_t sp_lv:8;
+ uint32_t hp_c:1;
+ uint32_t hp_s:1;
+ uint32_t pip:1;
+ uint32_t aip:1;
+ uint32_t mrlsp:1;
+ uint32_t pcp:1;
+ uint32_t abp:1;
+ } s;
+ struct cvmx_pciercx_cfg033_s cn52xx;
+ struct cvmx_pciercx_cfg033_s cn52xxp1;
+ struct cvmx_pciercx_cfg033_s cn56xx;
+ struct cvmx_pciercx_cfg033_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg034 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg034_s {
+ uint32_t reserved_25_31:7;
+ uint32_t dlls_c:1;
+ uint32_t emis:1;
+ uint32_t pds:1;
+ uint32_t mrlss:1;
+ uint32_t ccint_d:1;
+ uint32_t pd_c:1;
+ uint32_t mrls_c:1;
+ uint32_t pf_d:1;
+ uint32_t abp_d:1;
+ uint32_t reserved_13_15:3;
+ uint32_t dlls_en:1;
+ uint32_t emic:1;
+ uint32_t pcc:1;
+ uint32_t pic:2;
+ uint32_t aic:2;
+ uint32_t hpint_en:1;
+ uint32_t ccint_en:1;
+ uint32_t pd_en:1;
+ uint32_t mrls_en:1;
+ uint32_t pf_en:1;
+ uint32_t abp_en:1;
+ } s;
+ struct cvmx_pciercx_cfg034_s cn52xx;
+ struct cvmx_pciercx_cfg034_s cn52xxp1;
+ struct cvmx_pciercx_cfg034_s cn56xx;
+ struct cvmx_pciercx_cfg034_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg035 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg035_s {
+ uint32_t reserved_17_31:15;
+ uint32_t crssv:1;
+ uint32_t reserved_5_15:11;
+ uint32_t crssve:1;
+ uint32_t pmeie:1;
+ uint32_t sefee:1;
+ uint32_t senfee:1;
+ uint32_t secee:1;
+ } s;
+ struct cvmx_pciercx_cfg035_s cn52xx;
+ struct cvmx_pciercx_cfg035_s cn52xxp1;
+ struct cvmx_pciercx_cfg035_s cn56xx;
+ struct cvmx_pciercx_cfg035_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg036 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg036_s {
+ uint32_t reserved_18_31:14;
+ uint32_t pme_pend:1;
+ uint32_t pme_stat:1;
+ uint32_t pme_rid:16;
+ } s;
+ struct cvmx_pciercx_cfg036_s cn52xx;
+ struct cvmx_pciercx_cfg036_s cn52xxp1;
+ struct cvmx_pciercx_cfg036_s cn56xx;
+ struct cvmx_pciercx_cfg036_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg037 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg037_s {
+ uint32_t reserved_5_31:27;
+ uint32_t ctds:1;
+ uint32_t ctrs:4;
+ } s;
+ struct cvmx_pciercx_cfg037_s cn52xx;
+ struct cvmx_pciercx_cfg037_s cn52xxp1;
+ struct cvmx_pciercx_cfg037_s cn56xx;
+ struct cvmx_pciercx_cfg037_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg038 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg038_s {
+ uint32_t reserved_5_31:27;
+ uint32_t ctd:1;
+ uint32_t ctv:4;
+ } s;
+ struct cvmx_pciercx_cfg038_s cn52xx;
+ struct cvmx_pciercx_cfg038_s cn52xxp1;
+ struct cvmx_pciercx_cfg038_s cn56xx;
+ struct cvmx_pciercx_cfg038_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg039 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg039_s {
+ uint32_t reserved_0_31:32;
+ } s;
+ struct cvmx_pciercx_cfg039_s cn52xx;
+ struct cvmx_pciercx_cfg039_s cn52xxp1;
+ struct cvmx_pciercx_cfg039_s cn56xx;
+ struct cvmx_pciercx_cfg039_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg040 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg040_s {
+ uint32_t reserved_0_31:32;
+ } s;
+ struct cvmx_pciercx_cfg040_s cn52xx;
+ struct cvmx_pciercx_cfg040_s cn52xxp1;
+ struct cvmx_pciercx_cfg040_s cn56xx;
+ struct cvmx_pciercx_cfg040_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg041 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg041_s {
+ uint32_t reserved_0_31:32;
+ } s;
+ struct cvmx_pciercx_cfg041_s cn52xx;
+ struct cvmx_pciercx_cfg041_s cn52xxp1;
+ struct cvmx_pciercx_cfg041_s cn56xx;
+ struct cvmx_pciercx_cfg041_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg042 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg042_s {
+ uint32_t reserved_0_31:32;
+ } s;
+ struct cvmx_pciercx_cfg042_s cn52xx;
+ struct cvmx_pciercx_cfg042_s cn52xxp1;
+ struct cvmx_pciercx_cfg042_s cn56xx;
+ struct cvmx_pciercx_cfg042_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg064 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg064_s {
+ uint32_t nco:12;
+ uint32_t cv:4;
+ uint32_t pcieec:16;
+ } s;
+ struct cvmx_pciercx_cfg064_s cn52xx;
+ struct cvmx_pciercx_cfg064_s cn52xxp1;
+ struct cvmx_pciercx_cfg064_s cn56xx;
+ struct cvmx_pciercx_cfg064_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg065 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg065_s {
+ uint32_t reserved_21_31:11;
+ uint32_t ures:1;
+ uint32_t ecrces:1;
+ uint32_t mtlps:1;
+ uint32_t ros:1;
+ uint32_t ucs:1;
+ uint32_t cas:1;
+ uint32_t cts:1;
+ uint32_t fcpes:1;
+ uint32_t ptlps:1;
+ uint32_t reserved_6_11:6;
+ uint32_t sdes:1;
+ uint32_t dlpes:1;
+ uint32_t reserved_0_3:4;
+ } s;
+ struct cvmx_pciercx_cfg065_s cn52xx;
+ struct cvmx_pciercx_cfg065_s cn52xxp1;
+ struct cvmx_pciercx_cfg065_s cn56xx;
+ struct cvmx_pciercx_cfg065_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg066 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg066_s {
+ uint32_t reserved_21_31:11;
+ uint32_t urem:1;
+ uint32_t ecrcem:1;
+ uint32_t mtlpm:1;
+ uint32_t rom:1;
+ uint32_t ucm:1;
+ uint32_t cam:1;
+ uint32_t ctm:1;
+ uint32_t fcpem:1;
+ uint32_t ptlpm:1;
+ uint32_t reserved_6_11:6;
+ uint32_t sdem:1;
+ uint32_t dlpem:1;
+ uint32_t reserved_0_3:4;
+ } s;
+ struct cvmx_pciercx_cfg066_s cn52xx;
+ struct cvmx_pciercx_cfg066_s cn52xxp1;
+ struct cvmx_pciercx_cfg066_s cn56xx;
+ struct cvmx_pciercx_cfg066_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg067 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg067_s {
+ uint32_t reserved_21_31:11;
+ uint32_t ures:1;
+ uint32_t ecrces:1;
+ uint32_t mtlps:1;
+ uint32_t ros:1;
+ uint32_t ucs:1;
+ uint32_t cas:1;
+ uint32_t cts:1;
+ uint32_t fcpes:1;
+ uint32_t ptlps:1;
+ uint32_t reserved_6_11:6;
+ uint32_t sdes:1;
+ uint32_t dlpes:1;
+ uint32_t reserved_0_3:4;
+ } s;
+ struct cvmx_pciercx_cfg067_s cn52xx;
+ struct cvmx_pciercx_cfg067_s cn52xxp1;
+ struct cvmx_pciercx_cfg067_s cn56xx;
+ struct cvmx_pciercx_cfg067_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg068 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg068_s {
+ uint32_t reserved_14_31:18;
+ uint32_t anfes:1;
+ uint32_t rtts:1;
+ uint32_t reserved_9_11:3;
+ uint32_t rnrs:1;
+ uint32_t bdllps:1;
+ uint32_t btlps:1;
+ uint32_t reserved_1_5:5;
+ uint32_t res:1;
+ } s;
+ struct cvmx_pciercx_cfg068_s cn52xx;
+ struct cvmx_pciercx_cfg068_s cn52xxp1;
+ struct cvmx_pciercx_cfg068_s cn56xx;
+ struct cvmx_pciercx_cfg068_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg069 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg069_s {
+ uint32_t reserved_14_31:18;
+ uint32_t anfem:1;
+ uint32_t rttm:1;
+ uint32_t reserved_9_11:3;
+ uint32_t rnrm:1;
+ uint32_t bdllpm:1;
+ uint32_t btlpm:1;
+ uint32_t reserved_1_5:5;
+ uint32_t rem:1;
+ } s;
+ struct cvmx_pciercx_cfg069_s cn52xx;
+ struct cvmx_pciercx_cfg069_s cn52xxp1;
+ struct cvmx_pciercx_cfg069_s cn56xx;
+ struct cvmx_pciercx_cfg069_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg070 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg070_s {
+ uint32_t reserved_9_31:23;
+ uint32_t ce:1;
+ uint32_t cc:1;
+ uint32_t ge:1;
+ uint32_t gc:1;
+ uint32_t fep:5;
+ } s;
+ struct cvmx_pciercx_cfg070_s cn52xx;
+ struct cvmx_pciercx_cfg070_s cn52xxp1;
+ struct cvmx_pciercx_cfg070_s cn56xx;
+ struct cvmx_pciercx_cfg070_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg071 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg071_s {
+ uint32_t dword1:32;
+ } s;
+ struct cvmx_pciercx_cfg071_s cn52xx;
+ struct cvmx_pciercx_cfg071_s cn52xxp1;
+ struct cvmx_pciercx_cfg071_s cn56xx;
+ struct cvmx_pciercx_cfg071_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg072 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg072_s {
+ uint32_t dword2:32;
+ } s;
+ struct cvmx_pciercx_cfg072_s cn52xx;
+ struct cvmx_pciercx_cfg072_s cn52xxp1;
+ struct cvmx_pciercx_cfg072_s cn56xx;
+ struct cvmx_pciercx_cfg072_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg073 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg073_s {
+ uint32_t dword3:32;
+ } s;
+ struct cvmx_pciercx_cfg073_s cn52xx;
+ struct cvmx_pciercx_cfg073_s cn52xxp1;
+ struct cvmx_pciercx_cfg073_s cn56xx;
+ struct cvmx_pciercx_cfg073_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg074 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg074_s {
+ uint32_t dword4:32;
+ } s;
+ struct cvmx_pciercx_cfg074_s cn52xx;
+ struct cvmx_pciercx_cfg074_s cn52xxp1;
+ struct cvmx_pciercx_cfg074_s cn56xx;
+ struct cvmx_pciercx_cfg074_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg075 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg075_s {
+ uint32_t reserved_3_31:29;
+ uint32_t fere:1;
+ uint32_t nfere:1;
+ uint32_t cere:1;
+ } s;
+ struct cvmx_pciercx_cfg075_s cn52xx;
+ struct cvmx_pciercx_cfg075_s cn52xxp1;
+ struct cvmx_pciercx_cfg075_s cn56xx;
+ struct cvmx_pciercx_cfg075_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg076 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg076_s {
+ uint32_t aeimn:5;
+ uint32_t reserved_7_26:20;
+ uint32_t femr:1;
+ uint32_t nfemr:1;
+ uint32_t fuf:1;
+ uint32_t multi_efnfr:1;
+ uint32_t efnfr:1;
+ uint32_t multi_ecr:1;
+ uint32_t ecr:1;
+ } s;
+ struct cvmx_pciercx_cfg076_s cn52xx;
+ struct cvmx_pciercx_cfg076_s cn52xxp1;
+ struct cvmx_pciercx_cfg076_s cn56xx;
+ struct cvmx_pciercx_cfg076_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg077 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg077_s {
+ uint32_t efnfsi:16;
+ uint32_t ecsi:16;
+ } s;
+ struct cvmx_pciercx_cfg077_s cn52xx;
+ struct cvmx_pciercx_cfg077_s cn52xxp1;
+ struct cvmx_pciercx_cfg077_s cn56xx;
+ struct cvmx_pciercx_cfg077_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg448 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg448_s {
+ uint32_t rtl:16;
+ uint32_t rtltl:16;
+ } s;
+ struct cvmx_pciercx_cfg448_s cn52xx;
+ struct cvmx_pciercx_cfg448_s cn52xxp1;
+ struct cvmx_pciercx_cfg448_s cn56xx;
+ struct cvmx_pciercx_cfg448_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg449 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg449_s {
+ uint32_t omr:32;
+ } s;
+ struct cvmx_pciercx_cfg449_s cn52xx;
+ struct cvmx_pciercx_cfg449_s cn52xxp1;
+ struct cvmx_pciercx_cfg449_s cn56xx;
+ struct cvmx_pciercx_cfg449_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg450 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg450_s {
+ uint32_t lpec:8;
+ uint32_t reserved_22_23:2;
+ uint32_t link_state:6;
+ uint32_t force_link:1;
+ uint32_t reserved_8_14:7;
+ uint32_t link_num:8;
+ } s;
+ struct cvmx_pciercx_cfg450_s cn52xx;
+ struct cvmx_pciercx_cfg450_s cn52xxp1;
+ struct cvmx_pciercx_cfg450_s cn56xx;
+ struct cvmx_pciercx_cfg450_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg451 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg451_s {
+ uint32_t reserved_30_31:2;
+ uint32_t l1el:3;
+ uint32_t l0el:3;
+ uint32_t n_fts_cc:8;
+ uint32_t n_fts:8;
+ uint32_t ack_freq:8;
+ } s;
+ struct cvmx_pciercx_cfg451_s cn52xx;
+ struct cvmx_pciercx_cfg451_s cn52xxp1;
+ struct cvmx_pciercx_cfg451_s cn56xx;
+ struct cvmx_pciercx_cfg451_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg452 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg452_s {
+ uint32_t reserved_26_31:6;
+ uint32_t eccrc:1;
+ uint32_t reserved_22_24:3;
+ uint32_t lme:6;
+ uint32_t reserved_8_15:8;
+ uint32_t flm:1;
+ uint32_t reserved_6_6:1;
+ uint32_t dllle:1;
+ uint32_t reserved_4_4:1;
+ uint32_t ra:1;
+ uint32_t le:1;
+ uint32_t sd:1;
+ uint32_t omr:1;
+ } s;
+ struct cvmx_pciercx_cfg452_s cn52xx;
+ struct cvmx_pciercx_cfg452_s cn52xxp1;
+ struct cvmx_pciercx_cfg452_s cn56xx;
+ struct cvmx_pciercx_cfg452_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg453 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg453_s {
+ uint32_t dlld:1;
+ uint32_t reserved_26_30:5;
+ uint32_t ack_nak:1;
+ uint32_t fcd:1;
+ uint32_t ilst:24;
+ } s;
+ struct cvmx_pciercx_cfg453_s cn52xx;
+ struct cvmx_pciercx_cfg453_s cn52xxp1;
+ struct cvmx_pciercx_cfg453_s cn56xx;
+ struct cvmx_pciercx_cfg453_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg454 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg454_s {
+ uint32_t reserved_29_31:3;
+ uint32_t tmfcwt:5;
+ uint32_t tmanlt:5;
+ uint32_t tmrt:5;
+ uint32_t reserved_11_13:3;
+ uint32_t nskps:3;
+ uint32_t reserved_4_7:4;
+ uint32_t ntss:4;
+ } s;
+ struct cvmx_pciercx_cfg454_s cn52xx;
+ struct cvmx_pciercx_cfg454_s cn52xxp1;
+ struct cvmx_pciercx_cfg454_s cn56xx;
+ struct cvmx_pciercx_cfg454_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg455 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg455_s {
+ uint32_t m_cfg0_filt:1;
+ uint32_t m_io_filt:1;
+ uint32_t msg_ctrl:1;
+ uint32_t m_cpl_ecrc_filt:1;
+ uint32_t m_ecrc_filt:1;
+ uint32_t m_cpl_len_err:1;
+ uint32_t m_cpl_attr_err:1;
+ uint32_t m_cpl_tc_err:1;
+ uint32_t m_cpl_fun_err:1;
+ uint32_t m_cpl_rid_err:1;
+ uint32_t m_cpl_tag_err:1;
+ uint32_t m_lk_filt:1;
+ uint32_t m_cfg1_filt:1;
+ uint32_t m_bar_match:1;
+ uint32_t m_pois_filt:1;
+ uint32_t m_fun:1;
+ uint32_t dfcwt:1;
+ uint32_t reserved_11_14:4;
+ uint32_t skpiv:11;
+ } s;
+ struct cvmx_pciercx_cfg455_s cn52xx;
+ struct cvmx_pciercx_cfg455_s cn52xxp1;
+ struct cvmx_pciercx_cfg455_s cn56xx;
+ struct cvmx_pciercx_cfg455_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg456 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg456_s {
+ uint32_t reserved_2_31:30;
+ uint32_t m_vend1_drp:1;
+ uint32_t m_vend0_drp:1;
+ } s;
+ struct cvmx_pciercx_cfg456_s cn52xx;
+ struct cvmx_pciercx_cfg456_s cn52xxp1;
+ struct cvmx_pciercx_cfg456_s cn56xx;
+ struct cvmx_pciercx_cfg456_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg458 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg458_s {
+ uint32_t dbg_info_l32:32;
+ } s;
+ struct cvmx_pciercx_cfg458_s cn52xx;
+ struct cvmx_pciercx_cfg458_s cn52xxp1;
+ struct cvmx_pciercx_cfg458_s cn56xx;
+ struct cvmx_pciercx_cfg458_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg459 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg459_s {
+ uint32_t dbg_info_u32:32;
+ } s;
+ struct cvmx_pciercx_cfg459_s cn52xx;
+ struct cvmx_pciercx_cfg459_s cn52xxp1;
+ struct cvmx_pciercx_cfg459_s cn56xx;
+ struct cvmx_pciercx_cfg459_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg460 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg460_s {
+ uint32_t reserved_20_31:12;
+ uint32_t tphfcc:8;
+ uint32_t tpdfcc:12;
+ } s;
+ struct cvmx_pciercx_cfg460_s cn52xx;
+ struct cvmx_pciercx_cfg460_s cn52xxp1;
+ struct cvmx_pciercx_cfg460_s cn56xx;
+ struct cvmx_pciercx_cfg460_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg461 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg461_s {
+ uint32_t reserved_20_31:12;
+ uint32_t tchfcc:8;
+ uint32_t tcdfcc:12;
+ } s;
+ struct cvmx_pciercx_cfg461_s cn52xx;
+ struct cvmx_pciercx_cfg461_s cn52xxp1;
+ struct cvmx_pciercx_cfg461_s cn56xx;
+ struct cvmx_pciercx_cfg461_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg462 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg462_s {
+ uint32_t reserved_20_31:12;
+ uint32_t tchfcc:8;
+ uint32_t tcdfcc:12;
+ } s;
+ struct cvmx_pciercx_cfg462_s cn52xx;
+ struct cvmx_pciercx_cfg462_s cn52xxp1;
+ struct cvmx_pciercx_cfg462_s cn56xx;
+ struct cvmx_pciercx_cfg462_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg463 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg463_s {
+ uint32_t reserved_3_31:29;
+ uint32_t rqne:1;
+ uint32_t trbne:1;
+ uint32_t rtlpfccnr:1;
+ } s;
+ struct cvmx_pciercx_cfg463_s cn52xx;
+ struct cvmx_pciercx_cfg463_s cn52xxp1;
+ struct cvmx_pciercx_cfg463_s cn56xx;
+ struct cvmx_pciercx_cfg463_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg464 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg464_s {
+ uint32_t wrr_vc3:8;
+ uint32_t wrr_vc2:8;
+ uint32_t wrr_vc1:8;
+ uint32_t wrr_vc0:8;
+ } s;
+ struct cvmx_pciercx_cfg464_s cn52xx;
+ struct cvmx_pciercx_cfg464_s cn52xxp1;
+ struct cvmx_pciercx_cfg464_s cn56xx;
+ struct cvmx_pciercx_cfg464_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg465 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg465_s {
+ uint32_t wrr_vc7:8;
+ uint32_t wrr_vc6:8;
+ uint32_t wrr_vc5:8;
+ uint32_t wrr_vc4:8;
+ } s;
+ struct cvmx_pciercx_cfg465_s cn52xx;
+ struct cvmx_pciercx_cfg465_s cn52xxp1;
+ struct cvmx_pciercx_cfg465_s cn56xx;
+ struct cvmx_pciercx_cfg465_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg466 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg466_s {
+ uint32_t rx_queue_order:1;
+ uint32_t type_ordering:1;
+ uint32_t reserved_24_29:6;
+ uint32_t queue_mode:3;
+ uint32_t reserved_20_20:1;
+ uint32_t header_credits:8;
+ uint32_t data_credits:12;
+ } s;
+ struct cvmx_pciercx_cfg466_s cn52xx;
+ struct cvmx_pciercx_cfg466_s cn52xxp1;
+ struct cvmx_pciercx_cfg466_s cn56xx;
+ struct cvmx_pciercx_cfg466_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg467 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg467_s {
+ uint32_t reserved_24_31:8;
+ uint32_t queue_mode:3;
+ uint32_t reserved_20_20:1;
+ uint32_t header_credits:8;
+ uint32_t data_credits:12;
+ } s;
+ struct cvmx_pciercx_cfg467_s cn52xx;
+ struct cvmx_pciercx_cfg467_s cn52xxp1;
+ struct cvmx_pciercx_cfg467_s cn56xx;
+ struct cvmx_pciercx_cfg467_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg468 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg468_s {
+ uint32_t reserved_24_31:8;
+ uint32_t queue_mode:3;
+ uint32_t reserved_20_20:1;
+ uint32_t header_credits:8;
+ uint32_t data_credits:12;
+ } s;
+ struct cvmx_pciercx_cfg468_s cn52xx;
+ struct cvmx_pciercx_cfg468_s cn52xxp1;
+ struct cvmx_pciercx_cfg468_s cn56xx;
+ struct cvmx_pciercx_cfg468_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg490 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg490_s {
+ uint32_t reserved_26_31:6;
+ uint32_t header_depth:10;
+ uint32_t reserved_14_15:2;
+ uint32_t data_depth:14;
+ } s;
+ struct cvmx_pciercx_cfg490_s cn52xx;
+ struct cvmx_pciercx_cfg490_s cn52xxp1;
+ struct cvmx_pciercx_cfg490_s cn56xx;
+ struct cvmx_pciercx_cfg490_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg491 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg491_s {
+ uint32_t reserved_26_31:6;
+ uint32_t header_depth:10;
+ uint32_t reserved_14_15:2;
+ uint32_t data_depth:14;
+ } s;
+ struct cvmx_pciercx_cfg491_s cn52xx;
+ struct cvmx_pciercx_cfg491_s cn52xxp1;
+ struct cvmx_pciercx_cfg491_s cn56xx;
+ struct cvmx_pciercx_cfg491_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg492 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg492_s {
+ uint32_t reserved_26_31:6;
+ uint32_t header_depth:10;
+ uint32_t reserved_14_15:2;
+ uint32_t data_depth:14;
+ } s;
+ struct cvmx_pciercx_cfg492_s cn52xx;
+ struct cvmx_pciercx_cfg492_s cn52xxp1;
+ struct cvmx_pciercx_cfg492_s cn56xx;
+ struct cvmx_pciercx_cfg492_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg516 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg516_s {
+ uint32_t phy_stat:32;
+ } s;
+ struct cvmx_pciercx_cfg516_s cn52xx;
+ struct cvmx_pciercx_cfg516_s cn52xxp1;
+ struct cvmx_pciercx_cfg516_s cn56xx;
+ struct cvmx_pciercx_cfg516_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg517 {
+ uint32_t u32;
+ struct cvmx_pciercx_cfg517_s {
+ uint32_t phy_ctrl:32;
+ } s;
+ struct cvmx_pciercx_cfg517_s cn52xx;
+ struct cvmx_pciercx_cfg517_s cn52xxp1;
+ struct cvmx_pciercx_cfg517_s cn56xx;
+ struct cvmx_pciercx_cfg517_s cn56xxp1;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-pescx-defs.h b/arch/mips/include/asm/octeon/cvmx-pescx-defs.h
new file mode 100644
index 000000000000..f40cfaf84454
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-pescx-defs.h
@@ -0,0 +1,410 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_PESCX_DEFS_H__
+#define __CVMX_PESCX_DEFS_H__
+
+#define CVMX_PESCX_BIST_STATUS(block_id) \
+ CVMX_ADD_IO_SEG(0x00011800C8000018ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_BIST_STATUS2(block_id) \
+ CVMX_ADD_IO_SEG(0x00011800C8000418ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_CFG_RD(block_id) \
+ CVMX_ADD_IO_SEG(0x00011800C8000030ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_CFG_WR(block_id) \
+ CVMX_ADD_IO_SEG(0x00011800C8000028ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_CPL_LUT_VALID(block_id) \
+ CVMX_ADD_IO_SEG(0x00011800C8000098ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_CTL_STATUS(block_id) \
+ CVMX_ADD_IO_SEG(0x00011800C8000000ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_CTL_STATUS2(block_id) \
+ CVMX_ADD_IO_SEG(0x00011800C8000400ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_DBG_INFO(block_id) \
+ CVMX_ADD_IO_SEG(0x00011800C8000008ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_DBG_INFO_EN(block_id) \
+ CVMX_ADD_IO_SEG(0x00011800C80000A0ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_DIAG_STATUS(block_id) \
+ CVMX_ADD_IO_SEG(0x00011800C8000020ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_P2N_BAR0_START(block_id) \
+ CVMX_ADD_IO_SEG(0x00011800C8000080ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_P2N_BAR1_START(block_id) \
+ CVMX_ADD_IO_SEG(0x00011800C8000088ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_P2N_BAR2_START(block_id) \
+ CVMX_ADD_IO_SEG(0x00011800C8000090ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_P2P_BARX_END(offset, block_id) \
+ CVMX_ADD_IO_SEG(0x00011800C8000048ull + (((offset) & 3) * 16) + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_P2P_BARX_START(offset, block_id) \
+ CVMX_ADD_IO_SEG(0x00011800C8000040ull + (((offset) & 3) * 16) + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_TLP_CREDITS(block_id) \
+ CVMX_ADD_IO_SEG(0x00011800C8000038ull + (((block_id) & 1) * 0x8000000ull))
+
+union cvmx_pescx_bist_status {
+ uint64_t u64;
+ struct cvmx_pescx_bist_status_s {
+ uint64_t reserved_13_63:51;
+ uint64_t rqdata5:1;
+ uint64_t ctlp_or:1;
+ uint64_t ntlp_or:1;
+ uint64_t ptlp_or:1;
+ uint64_t retry:1;
+ uint64_t rqdata0:1;
+ uint64_t rqdata1:1;
+ uint64_t rqdata2:1;
+ uint64_t rqdata3:1;
+ uint64_t rqdata4:1;
+ uint64_t rqhdr1:1;
+ uint64_t rqhdr0:1;
+ uint64_t sot:1;
+ } s;
+ struct cvmx_pescx_bist_status_s cn52xx;
+ struct cvmx_pescx_bist_status_cn52xxp1 {
+ uint64_t reserved_12_63:52;
+ uint64_t ctlp_or:1;
+ uint64_t ntlp_or:1;
+ uint64_t ptlp_or:1;
+ uint64_t retry:1;
+ uint64_t rqdata0:1;
+ uint64_t rqdata1:1;
+ uint64_t rqdata2:1;
+ uint64_t rqdata3:1;
+ uint64_t rqdata4:1;
+ uint64_t rqhdr1:1;
+ uint64_t rqhdr0:1;
+ uint64_t sot:1;
+ } cn52xxp1;
+ struct cvmx_pescx_bist_status_s cn56xx;
+ struct cvmx_pescx_bist_status_cn52xxp1 cn56xxp1;
+};
+
+union cvmx_pescx_bist_status2 {
+ uint64_t u64;
+ struct cvmx_pescx_bist_status2_s {
+ uint64_t reserved_14_63:50;
+ uint64_t cto_p2e:1;
+ uint64_t e2p_cpl:1;
+ uint64_t e2p_n:1;
+ uint64_t e2p_p:1;
+ uint64_t e2p_rsl:1;
+ uint64_t dbg_p2e:1;
+ uint64_t peai_p2e:1;
+ uint64_t rsl_p2e:1;
+ uint64_t pef_tpf1:1;
+ uint64_t pef_tpf0:1;
+ uint64_t pef_tnf:1;
+ uint64_t pef_tcf1:1;
+ uint64_t pef_tc0:1;
+ uint64_t ppf:1;
+ } s;
+ struct cvmx_pescx_bist_status2_s cn52xx;
+ struct cvmx_pescx_bist_status2_s cn52xxp1;
+ struct cvmx_pescx_bist_status2_s cn56xx;
+ struct cvmx_pescx_bist_status2_s cn56xxp1;
+};
+
+union cvmx_pescx_cfg_rd {
+ uint64_t u64;
+ struct cvmx_pescx_cfg_rd_s {
+ uint64_t data:32;
+ uint64_t addr:32;
+ } s;
+ struct cvmx_pescx_cfg_rd_s cn52xx;
+ struct cvmx_pescx_cfg_rd_s cn52xxp1;
+ struct cvmx_pescx_cfg_rd_s cn56xx;
+ struct cvmx_pescx_cfg_rd_s cn56xxp1;
+};
+
+union cvmx_pescx_cfg_wr {
+ uint64_t u64;
+ struct cvmx_pescx_cfg_wr_s {
+ uint64_t data:32;
+ uint64_t addr:32;
+ } s;
+ struct cvmx_pescx_cfg_wr_s cn52xx;
+ struct cvmx_pescx_cfg_wr_s cn52xxp1;
+ struct cvmx_pescx_cfg_wr_s cn56xx;
+ struct cvmx_pescx_cfg_wr_s cn56xxp1;
+};
+
+union cvmx_pescx_cpl_lut_valid {
+ uint64_t u64;
+ struct cvmx_pescx_cpl_lut_valid_s {
+ uint64_t reserved_32_63:32;
+ uint64_t tag:32;
+ } s;
+ struct cvmx_pescx_cpl_lut_valid_s cn52xx;
+ struct cvmx_pescx_cpl_lut_valid_s cn52xxp1;
+ struct cvmx_pescx_cpl_lut_valid_s cn56xx;
+ struct cvmx_pescx_cpl_lut_valid_s cn56xxp1;
+};
+
+union cvmx_pescx_ctl_status {
+ uint64_t u64;
+ struct cvmx_pescx_ctl_status_s {
+ uint64_t reserved_28_63:36;
+ uint64_t dnum:5;
+ uint64_t pbus:8;
+ uint64_t qlm_cfg:2;
+ uint64_t lane_swp:1;
+ uint64_t pm_xtoff:1;
+ uint64_t pm_xpme:1;
+ uint64_t ob_p_cmd:1;
+ uint64_t reserved_7_8:2;
+ uint64_t nf_ecrc:1;
+ uint64_t dly_one:1;
+ uint64_t lnk_enb:1;
+ uint64_t ro_ctlp:1;
+ uint64_t reserved_2_2:1;
+ uint64_t inv_ecrc:1;
+ uint64_t inv_lcrc:1;
+ } s;
+ struct cvmx_pescx_ctl_status_s cn52xx;
+ struct cvmx_pescx_ctl_status_s cn52xxp1;
+ struct cvmx_pescx_ctl_status_cn56xx {
+ uint64_t reserved_28_63:36;
+ uint64_t dnum:5;
+ uint64_t pbus:8;
+ uint64_t qlm_cfg:2;
+ uint64_t reserved_12_12:1;
+ uint64_t pm_xtoff:1;
+ uint64_t pm_xpme:1;
+ uint64_t ob_p_cmd:1;
+ uint64_t reserved_7_8:2;
+ uint64_t nf_ecrc:1;
+ uint64_t dly_one:1;
+ uint64_t lnk_enb:1;
+ uint64_t ro_ctlp:1;
+ uint64_t reserved_2_2:1;
+ uint64_t inv_ecrc:1;
+ uint64_t inv_lcrc:1;
+ } cn56xx;
+ struct cvmx_pescx_ctl_status_cn56xx cn56xxp1;
+};
+
+union cvmx_pescx_ctl_status2 {
+ uint64_t u64;
+ struct cvmx_pescx_ctl_status2_s {
+ uint64_t reserved_2_63:62;
+ uint64_t pclk_run:1;
+ uint64_t pcierst:1;
+ } s;
+ struct cvmx_pescx_ctl_status2_s cn52xx;
+ struct cvmx_pescx_ctl_status2_cn52xxp1 {
+ uint64_t reserved_1_63:63;
+ uint64_t pcierst:1;
+ } cn52xxp1;
+ struct cvmx_pescx_ctl_status2_s cn56xx;
+ struct cvmx_pescx_ctl_status2_cn52xxp1 cn56xxp1;
+};
+
+union cvmx_pescx_dbg_info {
+ uint64_t u64;
+ struct cvmx_pescx_dbg_info_s {
+ uint64_t reserved_31_63:33;
+ uint64_t ecrc_e:1;
+ uint64_t rawwpp:1;
+ uint64_t racpp:1;
+ uint64_t ramtlp:1;
+ uint64_t rarwdns:1;
+ uint64_t caar:1;
+ uint64_t racca:1;
+ uint64_t racur:1;
+ uint64_t rauc:1;
+ uint64_t rqo:1;
+ uint64_t fcuv:1;
+ uint64_t rpe:1;
+ uint64_t fcpvwt:1;
+ uint64_t dpeoosd:1;
+ uint64_t rtwdle:1;
+ uint64_t rdwdle:1;
+ uint64_t mre:1;
+ uint64_t rte:1;
+ uint64_t acto:1;
+ uint64_t rvdm:1;
+ uint64_t rumep:1;
+ uint64_t rptamrc:1;
+ uint64_t rpmerc:1;
+ uint64_t rfemrc:1;
+ uint64_t rnfemrc:1;
+ uint64_t rcemrc:1;
+ uint64_t rpoison:1;
+ uint64_t recrce:1;
+ uint64_t rtlplle:1;
+ uint64_t rtlpmal:1;
+ uint64_t spoison:1;
+ } s;
+ struct cvmx_pescx_dbg_info_s cn52xx;
+ struct cvmx_pescx_dbg_info_s cn52xxp1;
+ struct cvmx_pescx_dbg_info_s cn56xx;
+ struct cvmx_pescx_dbg_info_s cn56xxp1;
+};
+
+union cvmx_pescx_dbg_info_en {
+ uint64_t u64;
+ struct cvmx_pescx_dbg_info_en_s {
+ uint64_t reserved_31_63:33;
+ uint64_t ecrc_e:1;
+ uint64_t rawwpp:1;
+ uint64_t racpp:1;
+ uint64_t ramtlp:1;
+ uint64_t rarwdns:1;
+ uint64_t caar:1;
+ uint64_t racca:1;
+ uint64_t racur:1;
+ uint64_t rauc:1;
+ uint64_t rqo:1;
+ uint64_t fcuv:1;
+ uint64_t rpe:1;
+ uint64_t fcpvwt:1;
+ uint64_t dpeoosd:1;
+ uint64_t rtwdle:1;
+ uint64_t rdwdle:1;
+ uint64_t mre:1;
+ uint64_t rte:1;
+ uint64_t acto:1;
+ uint64_t rvdm:1;
+ uint64_t rumep:1;
+ uint64_t rptamrc:1;
+ uint64_t rpmerc:1;
+ uint64_t rfemrc:1;
+ uint64_t rnfemrc:1;
+ uint64_t rcemrc:1;
+ uint64_t rpoison:1;
+ uint64_t recrce:1;
+ uint64_t rtlplle:1;
+ uint64_t rtlpmal:1;
+ uint64_t spoison:1;
+ } s;
+ struct cvmx_pescx_dbg_info_en_s cn52xx;
+ struct cvmx_pescx_dbg_info_en_s cn52xxp1;
+ struct cvmx_pescx_dbg_info_en_s cn56xx;
+ struct cvmx_pescx_dbg_info_en_s cn56xxp1;
+};
+
+union cvmx_pescx_diag_status {
+ uint64_t u64;
+ struct cvmx_pescx_diag_status_s {
+ uint64_t reserved_4_63:60;
+ uint64_t pm_dst:1;
+ uint64_t pm_stat:1;
+ uint64_t pm_en:1;
+ uint64_t aux_en:1;
+ } s;
+ struct cvmx_pescx_diag_status_s cn52xx;
+ struct cvmx_pescx_diag_status_s cn52xxp1;
+ struct cvmx_pescx_diag_status_s cn56xx;
+ struct cvmx_pescx_diag_status_s cn56xxp1;
+};
+
+union cvmx_pescx_p2n_bar0_start {
+ uint64_t u64;
+ struct cvmx_pescx_p2n_bar0_start_s {
+ uint64_t addr:50;
+ uint64_t reserved_0_13:14;
+ } s;
+ struct cvmx_pescx_p2n_bar0_start_s cn52xx;
+ struct cvmx_pescx_p2n_bar0_start_s cn52xxp1;
+ struct cvmx_pescx_p2n_bar0_start_s cn56xx;
+ struct cvmx_pescx_p2n_bar0_start_s cn56xxp1;
+};
+
+union cvmx_pescx_p2n_bar1_start {
+ uint64_t u64;
+ struct cvmx_pescx_p2n_bar1_start_s {
+ uint64_t addr:38;
+ uint64_t reserved_0_25:26;
+ } s;
+ struct cvmx_pescx_p2n_bar1_start_s cn52xx;
+ struct cvmx_pescx_p2n_bar1_start_s cn52xxp1;
+ struct cvmx_pescx_p2n_bar1_start_s cn56xx;
+ struct cvmx_pescx_p2n_bar1_start_s cn56xxp1;
+};
+
+union cvmx_pescx_p2n_bar2_start {
+ uint64_t u64;
+ struct cvmx_pescx_p2n_bar2_start_s {
+ uint64_t addr:25;
+ uint64_t reserved_0_38:39;
+ } s;
+ struct cvmx_pescx_p2n_bar2_start_s cn52xx;
+ struct cvmx_pescx_p2n_bar2_start_s cn52xxp1;
+ struct cvmx_pescx_p2n_bar2_start_s cn56xx;
+ struct cvmx_pescx_p2n_bar2_start_s cn56xxp1;
+};
+
+union cvmx_pescx_p2p_barx_end {
+ uint64_t u64;
+ struct cvmx_pescx_p2p_barx_end_s {
+ uint64_t addr:52;
+ uint64_t reserved_0_11:12;
+ } s;
+ struct cvmx_pescx_p2p_barx_end_s cn52xx;
+ struct cvmx_pescx_p2p_barx_end_s cn52xxp1;
+ struct cvmx_pescx_p2p_barx_end_s cn56xx;
+ struct cvmx_pescx_p2p_barx_end_s cn56xxp1;
+};
+
+union cvmx_pescx_p2p_barx_start {
+ uint64_t u64;
+ struct cvmx_pescx_p2p_barx_start_s {
+ uint64_t addr:52;
+ uint64_t reserved_0_11:12;
+ } s;
+ struct cvmx_pescx_p2p_barx_start_s cn52xx;
+ struct cvmx_pescx_p2p_barx_start_s cn52xxp1;
+ struct cvmx_pescx_p2p_barx_start_s cn56xx;
+ struct cvmx_pescx_p2p_barx_start_s cn56xxp1;
+};
+
+union cvmx_pescx_tlp_credits {
+ uint64_t u64;
+ struct cvmx_pescx_tlp_credits_s {
+ uint64_t reserved_0_63:64;
+ } s;
+ struct cvmx_pescx_tlp_credits_cn52xx {
+ uint64_t reserved_56_63:8;
+ uint64_t peai_ppf:8;
+ uint64_t pesc_cpl:8;
+ uint64_t pesc_np:8;
+ uint64_t pesc_p:8;
+ uint64_t npei_cpl:8;
+ uint64_t npei_np:8;
+ uint64_t npei_p:8;
+ } cn52xx;
+ struct cvmx_pescx_tlp_credits_cn52xxp1 {
+ uint64_t reserved_38_63:26;
+ uint64_t peai_ppf:8;
+ uint64_t pesc_cpl:5;
+ uint64_t pesc_np:5;
+ uint64_t pesc_p:5;
+ uint64_t npei_cpl:5;
+ uint64_t npei_np:5;
+ uint64_t npei_p:5;
+ } cn52xxp1;
+ struct cvmx_pescx_tlp_credits_cn52xx cn56xx;
+ struct cvmx_pescx_tlp_credits_cn52xxp1 cn56xxp1;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-pexp-defs.h b/arch/mips/include/asm/octeon/cvmx-pexp-defs.h
new file mode 100644
index 000000000000..5ea5dc571b54
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-pexp-defs.h
@@ -0,0 +1,229 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/**
+ * cvmx-pexp-defs.h
+ *
+ * Configuration and status register (CSR) definitions for
+ * OCTEON PEXP.
+ *
+ */
+#ifndef __CVMX_PEXP_DEFS_H__
+#define __CVMX_PEXP_DEFS_H__
+
+#define CVMX_PEXP_NPEI_BAR1_INDEXX(offset) \
+ CVMX_ADD_IO_SEG(0x00011F0000008000ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_BIST_STATUS \
+ CVMX_ADD_IO_SEG(0x00011F0000008580ull)
+#define CVMX_PEXP_NPEI_BIST_STATUS2 \
+ CVMX_ADD_IO_SEG(0x00011F0000008680ull)
+#define CVMX_PEXP_NPEI_CTL_PORT0 \
+ CVMX_ADD_IO_SEG(0x00011F0000008250ull)
+#define CVMX_PEXP_NPEI_CTL_PORT1 \
+ CVMX_ADD_IO_SEG(0x00011F0000008260ull)
+#define CVMX_PEXP_NPEI_CTL_STATUS \
+ CVMX_ADD_IO_SEG(0x00011F0000008570ull)
+#define CVMX_PEXP_NPEI_CTL_STATUS2 \
+ CVMX_ADD_IO_SEG(0x00011F000000BC00ull)
+#define CVMX_PEXP_NPEI_DATA_OUT_CNT \
+ CVMX_ADD_IO_SEG(0x00011F00000085F0ull)
+#define CVMX_PEXP_NPEI_DBG_DATA \
+ CVMX_ADD_IO_SEG(0x00011F0000008510ull)
+#define CVMX_PEXP_NPEI_DBG_SELECT \
+ CVMX_ADD_IO_SEG(0x00011F0000008500ull)
+#define CVMX_PEXP_NPEI_DMA0_INT_LEVEL \
+ CVMX_ADD_IO_SEG(0x00011F00000085C0ull)
+#define CVMX_PEXP_NPEI_DMA1_INT_LEVEL \
+ CVMX_ADD_IO_SEG(0x00011F00000085D0ull)
+#define CVMX_PEXP_NPEI_DMAX_COUNTS(offset) \
+ CVMX_ADD_IO_SEG(0x00011F0000008450ull + (((offset) & 7) * 16))
+#define CVMX_PEXP_NPEI_DMAX_DBELL(offset) \
+ CVMX_ADD_IO_SEG(0x00011F00000083B0ull + (((offset) & 7) * 16))
+#define CVMX_PEXP_NPEI_DMAX_IBUFF_SADDR(offset) \
+ CVMX_ADD_IO_SEG(0x00011F0000008400ull + (((offset) & 7) * 16))
+#define CVMX_PEXP_NPEI_DMAX_NADDR(offset) \
+ CVMX_ADD_IO_SEG(0x00011F00000084A0ull + (((offset) & 7) * 16))
+#define CVMX_PEXP_NPEI_DMA_CNTS \
+ CVMX_ADD_IO_SEG(0x00011F00000085E0ull)
+#define CVMX_PEXP_NPEI_DMA_CONTROL \
+ CVMX_ADD_IO_SEG(0x00011F00000083A0ull)
+#define CVMX_PEXP_NPEI_INT_A_ENB \
+ CVMX_ADD_IO_SEG(0x00011F0000008560ull)
+#define CVMX_PEXP_NPEI_INT_A_ENB2 \
+ CVMX_ADD_IO_SEG(0x00011F000000BCE0ull)
+#define CVMX_PEXP_NPEI_INT_A_SUM \
+ CVMX_ADD_IO_SEG(0x00011F0000008550ull)
+#define CVMX_PEXP_NPEI_INT_ENB \
+ CVMX_ADD_IO_SEG(0x00011F0000008540ull)
+#define CVMX_PEXP_NPEI_INT_ENB2 \
+ CVMX_ADD_IO_SEG(0x00011F000000BCD0ull)
+#define CVMX_PEXP_NPEI_INT_INFO \
+ CVMX_ADD_IO_SEG(0x00011F0000008590ull)
+#define CVMX_PEXP_NPEI_INT_SUM \
+ CVMX_ADD_IO_SEG(0x00011F0000008530ull)
+#define CVMX_PEXP_NPEI_INT_SUM2 \
+ CVMX_ADD_IO_SEG(0x00011F000000BCC0ull)
+#define CVMX_PEXP_NPEI_LAST_WIN_RDATA0 \
+ CVMX_ADD_IO_SEG(0x00011F0000008600ull)
+#define CVMX_PEXP_NPEI_LAST_WIN_RDATA1 \
+ CVMX_ADD_IO_SEG(0x00011F0000008610ull)
+#define CVMX_PEXP_NPEI_MEM_ACCESS_CTL \
+ CVMX_ADD_IO_SEG(0x00011F00000084F0ull)
+#define CVMX_PEXP_NPEI_MEM_ACCESS_SUBIDX(offset) \
+ CVMX_ADD_IO_SEG(0x00011F0000008280ull + (((offset) & 31) * 16) - 16 * 12)
+#define CVMX_PEXP_NPEI_MSI_ENB0 \
+ CVMX_ADD_IO_SEG(0x00011F000000BC50ull)
+#define CVMX_PEXP_NPEI_MSI_ENB1 \
+ CVMX_ADD_IO_SEG(0x00011F000000BC60ull)
+#define CVMX_PEXP_NPEI_MSI_ENB2 \
+ CVMX_ADD_IO_SEG(0x00011F000000BC70ull)
+#define CVMX_PEXP_NPEI_MSI_ENB3 \
+ CVMX_ADD_IO_SEG(0x00011F000000BC80ull)
+#define CVMX_PEXP_NPEI_MSI_RCV0 \
+ CVMX_ADD_IO_SEG(0x00011F000000BC10ull)
+#define CVMX_PEXP_NPEI_MSI_RCV1 \
+ CVMX_ADD_IO_SEG(0x00011F000000BC20ull)
+#define CVMX_PEXP_NPEI_MSI_RCV2 \
+ CVMX_ADD_IO_SEG(0x00011F000000BC30ull)
+#define CVMX_PEXP_NPEI_MSI_RCV3 \
+ CVMX_ADD_IO_SEG(0x00011F000000BC40ull)
+#define CVMX_PEXP_NPEI_MSI_RD_MAP \
+ CVMX_ADD_IO_SEG(0x00011F000000BCA0ull)
+#define CVMX_PEXP_NPEI_MSI_W1C_ENB0 \
+ CVMX_ADD_IO_SEG(0x00011F000000BCF0ull)
+#define CVMX_PEXP_NPEI_MSI_W1C_ENB1 \
+ CVMX_ADD_IO_SEG(0x00011F000000BD00ull)
+#define CVMX_PEXP_NPEI_MSI_W1C_ENB2 \
+ CVMX_ADD_IO_SEG(0x00011F000000BD10ull)
+#define CVMX_PEXP_NPEI_MSI_W1C_ENB3 \
+ CVMX_ADD_IO_SEG(0x00011F000000BD20ull)
+#define CVMX_PEXP_NPEI_MSI_W1S_ENB0 \
+ CVMX_ADD_IO_SEG(0x00011F000000BD30ull)
+#define CVMX_PEXP_NPEI_MSI_W1S_ENB1 \
+ CVMX_ADD_IO_SEG(0x00011F000000BD40ull)
+#define CVMX_PEXP_NPEI_MSI_W1S_ENB2 \
+ CVMX_ADD_IO_SEG(0x00011F000000BD50ull)
+#define CVMX_PEXP_NPEI_MSI_W1S_ENB3 \
+ CVMX_ADD_IO_SEG(0x00011F000000BD60ull)
+#define CVMX_PEXP_NPEI_MSI_WR_MAP \
+ CVMX_ADD_IO_SEG(0x00011F000000BC90ull)
+#define CVMX_PEXP_NPEI_PCIE_CREDIT_CNT \
+ CVMX_ADD_IO_SEG(0x00011F000000BD70ull)
+#define CVMX_PEXP_NPEI_PCIE_MSI_RCV \
+ CVMX_ADD_IO_SEG(0x00011F000000BCB0ull)
+#define CVMX_PEXP_NPEI_PCIE_MSI_RCV_B1 \
+ CVMX_ADD_IO_SEG(0x00011F0000008650ull)
+#define CVMX_PEXP_NPEI_PCIE_MSI_RCV_B2 \
+ CVMX_ADD_IO_SEG(0x00011F0000008660ull)
+#define CVMX_PEXP_NPEI_PCIE_MSI_RCV_B3 \
+ CVMX_ADD_IO_SEG(0x00011F0000008670ull)
+#define CVMX_PEXP_NPEI_PKTX_CNTS(offset) \
+ CVMX_ADD_IO_SEG(0x00011F000000A400ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_PKTX_INSTR_BADDR(offset) \
+ CVMX_ADD_IO_SEG(0x00011F000000A800ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_PKTX_INSTR_BAOFF_DBELL(offset) \
+ CVMX_ADD_IO_SEG(0x00011F000000AC00ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_PKTX_INSTR_FIFO_RSIZE(offset) \
+ CVMX_ADD_IO_SEG(0x00011F000000B000ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_PKTX_INSTR_HEADER(offset) \
+ CVMX_ADD_IO_SEG(0x00011F000000B400ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_PKTX_IN_BP(offset) \
+ CVMX_ADD_IO_SEG(0x00011F000000B800ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_PKTX_SLIST_BADDR(offset) \
+ CVMX_ADD_IO_SEG(0x00011F0000009400ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_PKTX_SLIST_BAOFF_DBELL(offset) \
+ CVMX_ADD_IO_SEG(0x00011F0000009800ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_PKTX_SLIST_FIFO_RSIZE(offset) \
+ CVMX_ADD_IO_SEG(0x00011F0000009C00ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_PKT_CNT_INT \
+ CVMX_ADD_IO_SEG(0x00011F0000009110ull)
+#define CVMX_PEXP_NPEI_PKT_CNT_INT_ENB \
+ CVMX_ADD_IO_SEG(0x00011F0000009130ull)
+#define CVMX_PEXP_NPEI_PKT_DATA_OUT_ES \
+ CVMX_ADD_IO_SEG(0x00011F00000090B0ull)
+#define CVMX_PEXP_NPEI_PKT_DATA_OUT_NS \
+ CVMX_ADD_IO_SEG(0x00011F00000090A0ull)
+#define CVMX_PEXP_NPEI_PKT_DATA_OUT_ROR \
+ CVMX_ADD_IO_SEG(0x00011F0000009090ull)
+#define CVMX_PEXP_NPEI_PKT_DPADDR \
+ CVMX_ADD_IO_SEG(0x00011F0000009080ull)
+#define CVMX_PEXP_NPEI_PKT_INPUT_CONTROL \
+ CVMX_ADD_IO_SEG(0x00011F0000009150ull)
+#define CVMX_PEXP_NPEI_PKT_INSTR_ENB \
+ CVMX_ADD_IO_SEG(0x00011F0000009000ull)
+#define CVMX_PEXP_NPEI_PKT_INSTR_RD_SIZE \
+ CVMX_ADD_IO_SEG(0x00011F0000009190ull)
+#define CVMX_PEXP_NPEI_PKT_INSTR_SIZE \
+ CVMX_ADD_IO_SEG(0x00011F0000009020ull)
+#define CVMX_PEXP_NPEI_PKT_INT_LEVELS \
+ CVMX_ADD_IO_SEG(0x00011F0000009100ull)
+#define CVMX_PEXP_NPEI_PKT_IN_BP \
+ CVMX_ADD_IO_SEG(0x00011F00000086B0ull)
+#define CVMX_PEXP_NPEI_PKT_IN_DONEX_CNTS(offset) \
+ CVMX_ADD_IO_SEG(0x00011F000000A000ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_PKT_IN_INSTR_COUNTS \
+ CVMX_ADD_IO_SEG(0x00011F00000086A0ull)
+#define CVMX_PEXP_NPEI_PKT_IN_PCIE_PORT \
+ CVMX_ADD_IO_SEG(0x00011F00000091A0ull)
+#define CVMX_PEXP_NPEI_PKT_IPTR \
+ CVMX_ADD_IO_SEG(0x00011F0000009070ull)
+#define CVMX_PEXP_NPEI_PKT_OUTPUT_WMARK \
+ CVMX_ADD_IO_SEG(0x00011F0000009160ull)
+#define CVMX_PEXP_NPEI_PKT_OUT_BMODE \
+ CVMX_ADD_IO_SEG(0x00011F00000090D0ull)
+#define CVMX_PEXP_NPEI_PKT_OUT_ENB \
+ CVMX_ADD_IO_SEG(0x00011F0000009010ull)
+#define CVMX_PEXP_NPEI_PKT_PCIE_PORT \
+ CVMX_ADD_IO_SEG(0x00011F00000090E0ull)
+#define CVMX_PEXP_NPEI_PKT_PORT_IN_RST \
+ CVMX_ADD_IO_SEG(0x00011F0000008690ull)
+#define CVMX_PEXP_NPEI_PKT_SLIST_ES \
+ CVMX_ADD_IO_SEG(0x00011F0000009050ull)
+#define CVMX_PEXP_NPEI_PKT_SLIST_ID_SIZE \
+ CVMX_ADD_IO_SEG(0x00011F0000009180ull)
+#define CVMX_PEXP_NPEI_PKT_SLIST_NS \
+ CVMX_ADD_IO_SEG(0x00011F0000009040ull)
+#define CVMX_PEXP_NPEI_PKT_SLIST_ROR \
+ CVMX_ADD_IO_SEG(0x00011F0000009030ull)
+#define CVMX_PEXP_NPEI_PKT_TIME_INT \
+ CVMX_ADD_IO_SEG(0x00011F0000009120ull)
+#define CVMX_PEXP_NPEI_PKT_TIME_INT_ENB \
+ CVMX_ADD_IO_SEG(0x00011F0000009140ull)
+#define CVMX_PEXP_NPEI_RSL_INT_BLOCKS \
+ CVMX_ADD_IO_SEG(0x00011F0000008520ull)
+#define CVMX_PEXP_NPEI_SCRATCH_1 \
+ CVMX_ADD_IO_SEG(0x00011F0000008270ull)
+#define CVMX_PEXP_NPEI_STATE1 \
+ CVMX_ADD_IO_SEG(0x00011F0000008620ull)
+#define CVMX_PEXP_NPEI_STATE2 \
+ CVMX_ADD_IO_SEG(0x00011F0000008630ull)
+#define CVMX_PEXP_NPEI_STATE3 \
+ CVMX_ADD_IO_SEG(0x00011F0000008640ull)
+#define CVMX_PEXP_NPEI_WINDOW_CTL \
+ CVMX_ADD_IO_SEG(0x00011F0000008380ull)
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx.h b/arch/mips/include/asm/octeon/cvmx.h
index 03fddfa3e928..e31e3fe14f8a 100644
--- a/arch/mips/include/asm/octeon/cvmx.h
+++ b/arch/mips/include/asm/octeon/cvmx.h
@@ -376,6 +376,18 @@ static inline uint64_t cvmx_get_cycle(void)
}
/**
+ * Wait for the specified number of cycle
+ *
+ */
+static inline void cvmx_wait(uint64_t cycles)
+{
+ uint64_t done = cvmx_get_cycle() + cycles;
+
+ while (cvmx_get_cycle() < done)
+ ; /* Spin */
+}
+
+/**
* Reads a chip global cycle counter. This counts CPU cycles since
* chip reset. The counter is 64 bit.
* This register does not exist on CN38XX pass 1 silicion
diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h
index edc676084cda..cac9b1a206fc 100644
--- a/arch/mips/include/asm/octeon/octeon.h
+++ b/arch/mips/include/asm/octeon/octeon.h
@@ -245,4 +245,6 @@ static inline uint32_t octeon_npi_read32(uint64_t address)
return cvmx_read64_uint32(address ^ 4);
}
+extern struct cvmx_bootinfo *octeon_bootinfo;
+
#endif /* __ASM_OCTEON_OCTEON_H */
diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h
index 4c140db36786..387bf59f1e37 100644
--- a/arch/mips/include/asm/r4kcache.h
+++ b/arch/mips/include/asm/r4kcache.h
@@ -399,6 +399,7 @@ __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64)
__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
diff --git a/arch/mips/include/asm/txx9/dmac.h b/arch/mips/include/asm/txx9/dmac.h
new file mode 100644
index 000000000000..5e9151fccbb4
--- /dev/null
+++ b/arch/mips/include/asm/txx9/dmac.h
@@ -0,0 +1,51 @@
+/*
+ * TXx9 SoC DMA Controller
+ *
+ * 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_TXX9_DMAC_H
+#define __ASM_TXX9_DMAC_H
+
+#include <linux/dmaengine.h>
+
+#define TXX9_DMA_MAX_NR_CHANNELS 4
+
+/**
+ * struct txx9dmac_platform_data - Controller configuration parameters
+ * @memcpy_chan: Channel used for DMA_MEMCPY
+ * @have_64bit_regs: DMAC have 64 bit registers
+ */
+struct txx9dmac_platform_data {
+ int memcpy_chan;
+ bool have_64bit_regs;
+};
+
+/**
+ * struct txx9dmac_chan_platform_data - Channel configuration parameters
+ * @dmac_dev: A platform device for DMAC
+ */
+struct txx9dmac_chan_platform_data {
+ struct platform_device *dmac_dev;
+};
+
+/**
+ * struct txx9dmac_slave - Controller-specific information about a slave
+ * @tx_reg: physical address of data register used for
+ * memory-to-peripheral transfers
+ * @rx_reg: physical address of data register used for
+ * peripheral-to-memory transfers
+ * @reg_width: peripheral register width
+ */
+struct txx9dmac_slave {
+ u64 tx_reg;
+ u64 rx_reg;
+ unsigned int reg_width;
+};
+
+void txx9_dmac_init(int id, unsigned long baseaddr, int irq,
+ const struct txx9dmac_platform_data *pdata);
+
+#endif /* __ASM_TXX9_DMAC_H */
diff --git a/arch/mips/include/asm/txx9/tx4927.h b/arch/mips/include/asm/txx9/tx4927.h
index 7d813f1cb98d..d92ae07000d3 100644
--- a/arch/mips/include/asm/txx9/tx4927.h
+++ b/arch/mips/include/asm/txx9/tx4927.h
@@ -41,6 +41,7 @@
#define TX4927_SDRAMC_REG (TX4927_REG_BASE + 0x8000)
#define TX4927_EBUSC_REG (TX4927_REG_BASE + 0x9000)
+#define TX4927_DMA_REG (TX4927_REG_BASE + 0xb000)
#define TX4927_PCIC_REG (TX4927_REG_BASE + 0xd000)
#define TX4927_CCFG_REG (TX4927_REG_BASE + 0xe000)
#define TX4927_IRC_REG (TX4927_REG_BASE + 0xf600)
@@ -265,5 +266,6 @@ int tx4927_pciclk66_setup(void);
void tx4927_setup_pcierr_irq(void);
void tx4927_irq_init(void);
void tx4927_mtd_init(int ch);
+void tx4927_dmac_init(int memcpy_chan);
#endif /* __ASM_TXX9_TX4927_H */
diff --git a/arch/mips/include/asm/txx9/tx4938.h b/arch/mips/include/asm/txx9/tx4938.h
index cd8bc2021755..0758a0c411b1 100644
--- a/arch/mips/include/asm/txx9/tx4938.h
+++ b/arch/mips/include/asm/txx9/tx4938.h
@@ -305,5 +305,6 @@ struct tx4938ide_platform_info {
};
void tx4938_ata_init(unsigned int irq, unsigned int shift, int tune);
+void tx4938_dmac_init(int memcpy_chan0, int memcpy_chan1);
#endif
diff --git a/arch/mips/include/asm/txx9/tx4939.h b/arch/mips/include/asm/txx9/tx4939.h
index f02c50b3abfb..1be9798a26b5 100644
--- a/arch/mips/include/asm/txx9/tx4939.h
+++ b/arch/mips/include/asm/txx9/tx4939.h
@@ -544,5 +544,6 @@ void tx4939_ata_init(void);
void tx4939_rtc_init(void);
void tx4939_ndfmc_init(unsigned int hold, unsigned int spw,
unsigned char ch_mask, unsigned char wide_mask);
+void tx4939_dmac_init(int memcpy_chan0, int memcpy_chan1);
#endif /* __ASM_TXX9_TX4939_H */
diff --git a/arch/mips/kernel/cevt-txx9.c b/arch/mips/kernel/cevt-txx9.c
index eccf7d6096bd..0037f21baf0d 100644
--- a/arch/mips/kernel/cevt-txx9.c
+++ b/arch/mips/kernel/cevt-txx9.c
@@ -20,22 +20,29 @@
#define TIMER_CCD 0 /* 1/2 */
#define TIMER_CLK(imclk) ((imclk) / (2 << TIMER_CCD))
-static struct txx9_tmr_reg __iomem *txx9_cs_tmrptr;
+struct txx9_clocksource {
+ struct clocksource cs;
+ struct txx9_tmr_reg __iomem *tmrptr;
+};
-static cycle_t txx9_cs_read(void)
+static cycle_t txx9_cs_read(struct clocksource *cs)
{
- return __raw_readl(&txx9_cs_tmrptr->trr);
+ struct txx9_clocksource *txx9_cs =
+ container_of(cs, struct txx9_clocksource, cs);
+ 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,
+static struct txx9_clocksource txx9_clocksource = {
+ .cs = {
+ .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,
@@ -43,8 +50,8 @@ void __init txx9_clocksource_init(unsigned long baseaddr,
{
struct txx9_tmr_reg __iomem *tmrptr;
- clocksource_set_clock(&txx9_clocksource, TIMER_CLK(imbusclk));
- clocksource_register(&txx9_clocksource);
+ clocksource_set_clock(&txx9_clocksource.cs, TIMER_CLK(imbusclk));
+ clocksource_register(&txx9_clocksource.cs);
tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
__raw_writel(TCR_BASE, &tmrptr->tcr);
@@ -53,10 +60,13 @@ void __init txx9_clocksource_init(unsigned long baseaddr,
__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;
+ txx9_clocksource.tmrptr = tmrptr;
}
-static struct txx9_tmr_reg __iomem *txx9_tmrptr;
+struct txx9_clock_event_device {
+ struct clock_event_device cd;
+ struct txx9_tmr_reg __iomem *tmrptr;
+};
static void txx9tmr_stop_and_clear(struct txx9_tmr_reg __iomem *tmrptr)
{
@@ -69,7 +79,9 @@ static void txx9tmr_stop_and_clear(struct txx9_tmr_reg __iomem *tmrptr)
static void txx9tmr_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
{
- struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr;
+ struct txx9_clock_event_device *txx9_cd =
+ container_of(evt, struct txx9_clock_event_device, cd);
+ struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
txx9tmr_stop_and_clear(tmrptr);
switch (mode) {
@@ -99,7 +111,9 @@ static void txx9tmr_set_mode(enum clock_event_mode mode,
static int txx9tmr_set_next_event(unsigned long delta,
struct clock_event_device *evt)
{
- struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr;
+ struct txx9_clock_event_device *txx9_cd =
+ container_of(evt, struct txx9_clock_event_device, cd);
+ struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
txx9tmr_stop_and_clear(tmrptr);
/* start timer */
@@ -108,18 +122,22 @@ static int txx9tmr_set_next_event(unsigned long delta,
return 0;
}
-static struct clock_event_device txx9tmr_clock_event_device = {
- .name = "TXx9",
- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
- .rating = 200,
- .set_mode = txx9tmr_set_mode,
- .set_next_event = txx9tmr_set_next_event,
+static struct txx9_clock_event_device txx9_clock_event_device = {
+ .cd = {
+ .name = "TXx9",
+ .features = CLOCK_EVT_FEAT_PERIODIC |
+ CLOCK_EVT_FEAT_ONESHOT,
+ .rating = 200,
+ .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;
+ struct txx9_clock_event_device *txx9_cd = dev_id;
+ struct clock_event_device *cd = &txx9_cd->cd;
+ struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
__raw_writel(0, &tmrptr->tisr); /* ack interrupt */
cd->event_handler(cd);
@@ -130,19 +148,20 @@ static struct irqaction txx9tmr_irq = {
.handler = txx9tmr_interrupt,
.flags = IRQF_DISABLED | IRQF_PERCPU,
.name = "txx9tmr",
+ .dev_id = &txx9_clock_event_device,
};
void __init txx9_clockevent_init(unsigned long baseaddr, int irq,
unsigned int imbusclk)
{
- struct clock_event_device *cd = &txx9tmr_clock_event_device;
+ struct clock_event_device *cd = &txx9_clock_event_device.cd;
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;
+ txx9_clock_event_device.tmrptr = tmrptr;
clockevent_set_clock(cd, TIMER_CLK(imbusclk));
cd->max_delta_ns =
diff --git a/arch/mips/kernel/csrc-bcm1480.c b/arch/mips/kernel/csrc-bcm1480.c
index 868745e7184b..51489f8a825e 100644
--- a/arch/mips/kernel/csrc-bcm1480.c
+++ b/arch/mips/kernel/csrc-bcm1480.c
@@ -28,7 +28,7 @@
#include <asm/sibyte/sb1250.h>
-static cycle_t bcm1480_hpt_read(void)
+static cycle_t bcm1480_hpt_read(struct clocksource *cs)
{
return (cycle_t) __raw_readq(IOADDR(A_SCD_ZBBUS_CYCLE_COUNT));
}
diff --git a/arch/mips/kernel/csrc-ioasic.c b/arch/mips/kernel/csrc-ioasic.c
index 1d5f63cf8997..b551f48d3a07 100644
--- a/arch/mips/kernel/csrc-ioasic.c
+++ b/arch/mips/kernel/csrc-ioasic.c
@@ -25,7 +25,7 @@
#include <asm/dec/ioasic.h>
#include <asm/dec/ioasic_addrs.h>
-static cycle_t dec_ioasic_hpt_read(void)
+static cycle_t dec_ioasic_hpt_read(struct clocksource *cs)
{
return ioasic_read(IO_REG_FCTR);
}
@@ -47,13 +47,13 @@ void __init dec_ioasic_clocksource_init(void)
while (!ds1287_timer_state())
;
- start = dec_ioasic_hpt_read();
+ start = dec_ioasic_hpt_read(&clocksource_dec);
while (i--)
while (!ds1287_timer_state())
;
- end = dec_ioasic_hpt_read();
+ end = dec_ioasic_hpt_read(&clocksource_dec);
freq = (end - start) * 10;
printk(KERN_INFO "I/O ASIC clock frequency %dHz\n", freq);
diff --git a/arch/mips/kernel/csrc-r4k.c b/arch/mips/kernel/csrc-r4k.c
index f1a2893931ed..e95a3cd48eea 100644
--- a/arch/mips/kernel/csrc-r4k.c
+++ b/arch/mips/kernel/csrc-r4k.c
@@ -10,7 +10,7 @@
#include <asm/time.h>
-static cycle_t c0_hpt_read(void)
+static cycle_t c0_hpt_read(struct clocksource *cs)
{
return read_c0_count();
}
diff --git a/arch/mips/kernel/csrc-sb1250.c b/arch/mips/kernel/csrc-sb1250.c
index 92212bbb8e45..d14d3d1907fa 100644
--- a/arch/mips/kernel/csrc-sb1250.c
+++ b/arch/mips/kernel/csrc-sb1250.c
@@ -33,7 +33,7 @@
* The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over
* again.
*/
-static cycle_t sb1250_hpt_read(void)
+static cycle_t sb1250_hpt_read(struct clocksource *cs)
{
unsigned int count;
diff --git a/arch/mips/kernel/i8253.c b/arch/mips/kernel/i8253.c
index 689719e34f08..ed20e7fe65e3 100644
--- a/arch/mips/kernel/i8253.c
+++ b/arch/mips/kernel/i8253.c
@@ -128,7 +128,7 @@ void __init setup_pit_timer(void)
* to just read by itself. So use jiffies to emulate a free
* running counter:
*/
-static cycle_t pit_read(void)
+static cycle_t pit_read(struct clocksource *cs)
{
unsigned long flags;
int count;
diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c
index 87deb8f6c458..3f43c2e3aa5a 100644
--- a/arch/mips/kernel/irq-gic.c
+++ b/arch/mips/kernel/irq-gic.c
@@ -155,7 +155,7 @@ static void gic_unmask_irq(unsigned int irq)
static DEFINE_SPINLOCK(gic_lock);
-static void gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
+static int gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
{
cpumask_t tmp = CPU_MASK_NONE;
unsigned long flags;
@@ -166,7 +166,7 @@ static void gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
cpumask_and(&tmp, cpumask, cpu_online_mask);
if (cpus_empty(tmp))
- return;
+ return -1;
/* Assumption : cpumask refers to a single CPU */
spin_lock_irqsave(&gic_lock, flags);
@@ -190,6 +190,7 @@ static void gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
cpumask_copy(irq_desc[irq].affinity, cpumask);
spin_unlock_irqrestore(&gic_lock, flags);
+ return 0;
}
#endif
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 58d9075e86fe..e9ffb5a1a0a1 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -100,6 +100,12 @@ static inline void r4k_blast_dcache_page_dc32(unsigned long addr)
blast_dcache32_page(addr);
}
+static inline void r4k_blast_dcache_page_dc64(unsigned long addr)
+{
+ R4600_HIT_CACHEOP_WAR_IMPL;
+ blast_dcache64_page(addr);
+}
+
static void __cpuinit r4k_blast_dcache_page_setup(void)
{
unsigned long dc_lsize = cpu_dcache_line_size();
@@ -110,6 +116,8 @@ static void __cpuinit r4k_blast_dcache_page_setup(void)
r4k_blast_dcache_page = blast_dcache16_page;
else if (dc_lsize == 32)
r4k_blast_dcache_page = r4k_blast_dcache_page_dc32;
+ else if (dc_lsize == 64)
+ r4k_blast_dcache_page = r4k_blast_dcache_page_dc64;
}
static void (* r4k_blast_dcache_page_indexed)(unsigned long addr);
@@ -124,6 +132,8 @@ static void __cpuinit r4k_blast_dcache_page_indexed_setup(void)
r4k_blast_dcache_page_indexed = blast_dcache16_page_indexed;
else if (dc_lsize == 32)
r4k_blast_dcache_page_indexed = blast_dcache32_page_indexed;
+ else if (dc_lsize == 64)
+ r4k_blast_dcache_page_indexed = blast_dcache64_page_indexed;
}
static void (* r4k_blast_dcache)(void);
@@ -138,6 +148,8 @@ static void __cpuinit r4k_blast_dcache_setup(void)
r4k_blast_dcache = blast_dcache16;
else if (dc_lsize == 32)
r4k_blast_dcache = blast_dcache32;
+ else if (dc_lsize == 64)
+ r4k_blast_dcache = blast_dcache64;
}
/* force code alignment (used for TX49XX_ICACHE_INDEX_INV_WAR) */
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index bed56f1ac837..d835130ad609 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -20,9 +20,10 @@
#include <dma-coherence.h>
-static inline unsigned long dma_addr_to_virt(dma_addr_t dma_addr)
+static inline unsigned long dma_addr_to_virt(struct device *dev,
+ dma_addr_t dma_addr)
{
- unsigned long addr = plat_dma_addr_to_phys(dma_addr);
+ unsigned long addr = plat_dma_addr_to_phys(dev, dma_addr);
return (unsigned long)phys_to_virt(addr);
}
@@ -111,7 +112,7 @@ EXPORT_SYMBOL(dma_alloc_coherent);
void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle)
{
- plat_unmap_dma_mem(dev, dma_handle);
+ plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL);
free_pages((unsigned long) vaddr, get_order(size));
}
@@ -122,7 +123,7 @@ void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
{
unsigned long addr = (unsigned long) vaddr;
- plat_unmap_dma_mem(dev, dma_handle);
+ plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL);
if (!plat_device_is_coherent(dev))
addr = CAC_ADDR(addr);
@@ -170,10 +171,10 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction direction)
{
if (cpu_is_noncoherent_r10000(dev))
- __dma_sync(dma_addr_to_virt(dma_addr), size,
+ __dma_sync(dma_addr_to_virt(dev, dma_addr), size,
direction);
- plat_unmap_dma_mem(dev, dma_addr);
+ plat_unmap_dma_mem(dev, dma_addr, size, direction);
}
EXPORT_SYMBOL(dma_unmap_single);
@@ -249,7 +250,7 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
if (addr)
__dma_sync(addr, sg->length, direction);
}
- plat_unmap_dma_mem(dev, sg->dma_address);
+ plat_unmap_dma_mem(dev, sg->dma_address, sg->length, direction);
}
}
@@ -263,7 +264,7 @@ void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
if (cpu_is_noncoherent_r10000(dev)) {
unsigned long addr;
- addr = dma_addr_to_virt(dma_handle);
+ addr = dma_addr_to_virt(dev, dma_handle);
__dma_sync(addr, size, direction);
}
}
@@ -279,7 +280,7 @@ void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
if (!plat_device_is_coherent(dev)) {
unsigned long addr;
- addr = dma_addr_to_virt(dma_handle);
+ addr = dma_addr_to_virt(dev, dma_handle);
__dma_sync(addr, size, direction);
}
}
@@ -294,7 +295,7 @@ void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
if (cpu_is_noncoherent_r10000(dev)) {
unsigned long addr;
- addr = dma_addr_to_virt(dma_handle);
+ addr = dma_addr_to_virt(dev, dma_handle);
__dma_sync(addr + offset, size, direction);
}
}
@@ -310,7 +311,7 @@ void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
if (!plat_device_is_coherent(dev)) {
unsigned long addr;
- addr = dma_addr_to_virt(dma_handle);
+ addr = dma_addr_to_virt(dev, dma_handle);
__dma_sync(addr + offset, size, direction);
}
}
diff --git a/arch/mips/mti-malta/malta-smtc.c b/arch/mips/mti-malta/malta-smtc.c
index 5ba31888fefb..499ffe5475df 100644
--- a/arch/mips/mti-malta/malta-smtc.c
+++ b/arch/mips/mti-malta/malta-smtc.c
@@ -114,7 +114,7 @@ struct plat_smp_ops msmtc_smp_ops = {
*/
-void plat_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
+int plat_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
{
cpumask_t tmask;
int cpu = 0;
@@ -156,5 +156,7 @@ void plat_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
/* Do any generic SMTC IRQ affinity setup */
smtc_set_irq_affinity(irq, tmask);
+
+ return 0;
}
#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
diff --git a/arch/mips/nxp/pnx8550/common/time.c b/arch/mips/nxp/pnx8550/common/time.c
index cf293b279098..8df43e9e4d90 100644
--- a/arch/mips/nxp/pnx8550/common/time.c
+++ b/arch/mips/nxp/pnx8550/common/time.c
@@ -35,7 +35,7 @@
static unsigned long cpj;
-static cycle_t hpt_read(void)
+static cycle_t hpt_read(struct clocksource *cs)
{
return read_c0_count2();
}
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c
index f024057a35f8..f10a7cd64f7e 100644
--- a/arch/mips/sgi-ip27/ip27-timer.c
+++ b/arch/mips/sgi-ip27/ip27-timer.c
@@ -159,7 +159,7 @@ static void __init hub_rt_clock_event_global_init(void)
setup_irq(irq, &hub_rt_irqaction);
}
-static cycle_t hub_rt_read(void)
+static cycle_t hub_rt_read(struct clocksource *cs)
{
return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT);
}
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c
index 352352b3cb2f..4f256a131bf6 100644
--- a/arch/mips/sibyte/bcm1480/irq.c
+++ b/arch/mips/sibyte/bcm1480/irq.c
@@ -50,7 +50,7 @@ static void enable_bcm1480_irq(unsigned int irq);
static void disable_bcm1480_irq(unsigned int irq);
static void ack_bcm1480_irq(unsigned int irq);
#ifdef CONFIG_SMP
-static void bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask);
+static int bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask);
#endif
#ifdef CONFIG_PCI
@@ -109,7 +109,7 @@ void bcm1480_unmask_irq(int cpu, int irq)
}
#ifdef CONFIG_SMP
-static void bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask)
{
int i = 0, old_cpu, cpu, int_on, k;
u64 cur_ints;
@@ -119,7 +119,7 @@ static void bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask)
if (cpumask_weight(mask) != 1) {
printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
- return;
+ return -1;
}
i = cpumask_first(mask);
@@ -155,6 +155,8 @@ static void bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask)
}
spin_unlock(&bcm1480_imr_lock);
spin_unlock_irqrestore(&desc->lock, flags);
+
+ return 0;
}
#endif
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index c08ff582da6f..e389507f1f96 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -50,7 +50,7 @@ static void enable_sb1250_irq(unsigned int irq);
static void disable_sb1250_irq(unsigned int irq);
static void ack_sb1250_irq(unsigned int irq);
#ifdef CONFIG_SMP
-static void sb1250_set_affinity(unsigned int irq, const struct cpumask *mask);
+static int sb1250_set_affinity(unsigned int irq, const struct cpumask *mask);
#endif
#ifdef CONFIG_SIBYTE_HAS_LDT
@@ -103,7 +103,7 @@ void sb1250_unmask_irq(int cpu, int irq)
}
#ifdef CONFIG_SMP
-static void sb1250_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int sb1250_set_affinity(unsigned int irq, const struct cpumask *mask)
{
int i = 0, old_cpu, cpu, int_on;
u64 cur_ints;
@@ -114,7 +114,7 @@ static void sb1250_set_affinity(unsigned int irq, const struct cpumask *mask)
if (cpumask_weight(mask) > 1) {
printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
- return;
+ return -1;
}
/* Convert logical CPU to physical CPU */
@@ -146,6 +146,8 @@ static void sb1250_set_affinity(unsigned int irq, const struct cpumask *mask)
}
spin_unlock(&sb1250_imr_lock);
spin_unlock_irqrestore(&desc->lock, flags);
+
+ return 0;
}
#endif
diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c
index 8a266c6a3f58..369d8637217d 100644
--- a/arch/mips/txx9/generic/setup.c
+++ b/arch/mips/txx9/generic/setup.c
@@ -33,6 +33,7 @@
#include <asm/txx9/pci.h>
#include <asm/txx9tmr.h>
#include <asm/txx9/ndfmc.h>
+#include <asm/txx9/dmac.h>
#ifdef CONFIG_CPU_TX49XX
#include <asm/txx9/tx4938.h>
#endif
@@ -821,3 +822,57 @@ void __init txx9_iocled_init(unsigned long baseaddr,
{
}
#endif /* CONFIG_LEDS_GPIO */
+
+void __init txx9_dmac_init(int id, unsigned long baseaddr, int irq,
+ const struct txx9dmac_platform_data *pdata)
+{
+#if defined(CONFIG_TXX9_DMAC) || defined(CONFIG_TXX9_DMAC_MODULE)
+ struct resource res[] = {
+ {
+ .start = baseaddr,
+ .end = baseaddr + 0x800 - 1,
+ .flags = IORESOURCE_MEM,
+#ifndef CONFIG_MACH_TX49XX
+ }, {
+ .start = irq,
+ .flags = IORESOURCE_IRQ,
+#endif
+ }
+ };
+#ifdef CONFIG_MACH_TX49XX
+ struct resource chan_res[] = {
+ {
+ .flags = IORESOURCE_IRQ,
+ }
+ };
+#endif
+ struct platform_device *pdev = platform_device_alloc("txx9dmac", id);
+ struct txx9dmac_chan_platform_data cpdata;
+ int i;
+
+ if (!pdev ||
+ platform_device_add_resources(pdev, res, ARRAY_SIZE(res)) ||
+ platform_device_add_data(pdev, pdata, sizeof(*pdata)) ||
+ platform_device_add(pdev)) {
+ platform_device_put(pdev);
+ return;
+ }
+ memset(&cpdata, 0, sizeof(cpdata));
+ cpdata.dmac_dev = pdev;
+ for (i = 0; i < TXX9_DMA_MAX_NR_CHANNELS; i++) {
+#ifdef CONFIG_MACH_TX49XX
+ chan_res[0].start = irq + i;
+#endif
+ pdev = platform_device_alloc("txx9dmac-chan",
+ id * TXX9_DMA_MAX_NR_CHANNELS + i);
+ if (!pdev ||
+#ifdef CONFIG_MACH_TX49XX
+ platform_device_add_resources(pdev, chan_res,
+ ARRAY_SIZE(chan_res)) ||
+#endif
+ platform_device_add_data(pdev, &cpdata, sizeof(cpdata)) ||
+ platform_device_add(pdev))
+ platform_device_put(pdev);
+ }
+#endif
+}
diff --git a/arch/mips/txx9/generic/setup_tx4927.c b/arch/mips/txx9/generic/setup_tx4927.c
index 914e93c62639..778078adea3b 100644
--- a/arch/mips/txx9/generic/setup_tx4927.c
+++ b/arch/mips/txx9/generic/setup_tx4927.c
@@ -22,6 +22,7 @@
#include <asm/txx9tmr.h>
#include <asm/txx9pio.h>
#include <asm/txx9/generic.h>
+#include <asm/txx9/dmac.h>
#include <asm/txx9/tx4927.h>
static void __init tx4927_wdr_init(void)
@@ -253,6 +254,17 @@ void __init tx4927_mtd_init(int ch)
txx9_physmap_flash_init(ch, start, size, &pdata);
}
+void __init tx4927_dmac_init(int memcpy_chan)
+{
+ struct txx9dmac_platform_data plat_data = {
+ .memcpy_chan = memcpy_chan,
+ .have_64bit_regs = true,
+ };
+
+ txx9_dmac_init(0, TX4927_DMA_REG & 0xfffffffffULL,
+ TXX9_IRQ_BASE + TX4927_IR_DMA(0), &plat_data);
+}
+
static void __init tx4927_stop_unused_modules(void)
{
__u64 pcfg, rst = 0, ckd = 0;
diff --git a/arch/mips/txx9/generic/setup_tx4938.c b/arch/mips/txx9/generic/setup_tx4938.c
index f0844f891f0b..5d2cbbfd5d4a 100644
--- a/arch/mips/txx9/generic/setup_tx4938.c
+++ b/arch/mips/txx9/generic/setup_tx4938.c
@@ -24,6 +24,7 @@
#include <asm/txx9pio.h>
#include <asm/txx9/generic.h>
#include <asm/txx9/ndfmc.h>
+#include <asm/txx9/dmac.h>
#include <asm/txx9/tx4938.h>
static void __init tx4938_wdr_init(void)
@@ -239,11 +240,6 @@ void __init tx4938_setup(void)
for (i = 0; i < TX4938_NR_TMR; i++)
txx9_tmr_init(TX4938_TMR_REG(i) & 0xfffffffffULL);
- /* DMA */
- for (i = 0; i < 2; i++)
- ____raw_writeq(TX4938_DMA_MCR_MSTEN,
- (void __iomem *)(TX4938_DMA_REG(i) + 0x50));
-
/* PIO */
txx9_gpio_init(TX4938_PIO_REG & 0xfffffffffULL, 0, TX4938_NUM_PIO);
__raw_writel(0, &tx4938_pioptr->maskcpu);
@@ -403,6 +399,21 @@ void __init tx4938_ndfmc_init(unsigned int hold, unsigned int spw)
txx9_ndfmc_init(baseaddr, &plat_data);
}
+void __init tx4938_dmac_init(int memcpy_chan0, int memcpy_chan1)
+{
+ struct txx9dmac_platform_data plat_data = {
+ .have_64bit_regs = true,
+ };
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ plat_data.memcpy_chan = i ? memcpy_chan1 : memcpy_chan0;
+ txx9_dmac_init(i, TX4938_DMA_REG(i) & 0xfffffffffULL,
+ TXX9_IRQ_BASE + TX4938_IR_DMA(i, 0),
+ &plat_data);
+ }
+}
+
static void __init tx4938_stop_unused_modules(void)
{
__u64 pcfg, rst = 0, ckd = 0;
diff --git a/arch/mips/txx9/generic/setup_tx4939.c b/arch/mips/txx9/generic/setup_tx4939.c
index 7a25b573e9b0..6ed53a75010a 100644
--- a/arch/mips/txx9/generic/setup_tx4939.c
+++ b/arch/mips/txx9/generic/setup_tx4939.c
@@ -28,6 +28,7 @@
#include <asm/txx9tmr.h>
#include <asm/txx9/generic.h>
#include <asm/txx9/ndfmc.h>
+#include <asm/txx9/dmac.h>
#include <asm/txx9/tx4939.h>
static void __init tx4939_wdr_init(void)
@@ -259,11 +260,6 @@ void __init tx4939_setup(void)
for (i = 0; i < TX4939_NR_TMR; i++)
txx9_tmr_init(TX4939_TMR_REG(i) & 0xfffffffffULL);
- /* DMA */
- for (i = 0; i < 2; i++)
- ____raw_writeq(TX4938_DMA_MCR_MSTEN,
- (void __iomem *)(TX4939_DMA_REG(i) + 0x50));
-
/* set PCIC1 reset (required to prevent hangup on BIST) */
txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_PCI1RST);
pcfg = ____raw_readq(&tx4939_ccfgptr->pcfg);
@@ -474,6 +470,21 @@ void __init tx4939_ndfmc_init(unsigned int hold, unsigned int spw,
txx9_ndfmc_init(TX4939_NDFMC_REG & 0xfffffffffULL, &plat_data);
}
+void __init tx4939_dmac_init(int memcpy_chan0, int memcpy_chan1)
+{
+ struct txx9dmac_platform_data plat_data = {
+ .have_64bit_regs = true,
+ };
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ plat_data.memcpy_chan = i ? memcpy_chan1 : memcpy_chan0;
+ txx9_dmac_init(i, TX4939_DMA_REG(i) & 0xfffffffffULL,
+ TXX9_IRQ_BASE + TX4939_IR_DMA(i, 0),
+ &plat_data);
+ }
+}
+
static void __init tx4939_stop_unused_modules(void)
{
__u64 pcfg, rst = 0, ckd = 0;
diff --git a/arch/mips/txx9/rbtx4927/setup.c b/arch/mips/txx9/rbtx4927/setup.c
index 01129a9d50fa..332cdbc7fcef 100644
--- a/arch/mips/txx9/rbtx4927/setup.c
+++ b/arch/mips/txx9/rbtx4927/setup.c
@@ -337,6 +337,10 @@ static void __init rbtx4927_device_init(void)
rbtx4927_ne_init();
tx4927_wdt_init();
rbtx4927_mtd_init();
+ if (TX4927_REV_PCODE() == 0x4927)
+ tx4927_dmac_init(2);
+ else
+ tx4938_dmac_init(0, 2);
txx9_iocled_init(RBTX4927_LED_ADDR - IO_BASE, -1, 3, 1, "green", NULL);
rbtx4927_gpioled_init();
}
diff --git a/arch/mips/txx9/rbtx4938/setup.c b/arch/mips/txx9/rbtx4938/setup.c
index 65d13df8878a..37c5e3d20287 100644
--- a/arch/mips/txx9/rbtx4938/setup.c
+++ b/arch/mips/txx9/rbtx4938/setup.c
@@ -355,6 +355,7 @@ static void __init rbtx4938_device_init(void)
/* TC58DVM82A1FT: tDH=10ns, tWP=tRP=tREADID=35ns */
tx4938_ndfmc_init(10, 35);
tx4938_ata_init(RBTX4938_IRQ_IOC_ATA, 0, 1);
+ tx4938_dmac_init(0, 2);
txx9_iocled_init(RBTX4938_LED_ADDR - IO_BASE, -1, 8, 1, "green", NULL);
}
diff --git a/arch/mips/txx9/rbtx4939/setup.c b/arch/mips/txx9/rbtx4939/setup.c
index 011e1e332f47..d5ef662e992b 100644
--- a/arch/mips/txx9/rbtx4939/setup.c
+++ b/arch/mips/txx9/rbtx4939/setup.c
@@ -498,6 +498,7 @@ static void __init rbtx4939_device_init(void)
tx4939_wdt_init();
tx4939_ata_init();
tx4939_rtc_init();
+ tx4939_dmac_init(0, 2);
}
static void __init rbtx4939_setup(void)
diff --git a/arch/mn10300/configs/asb2303_defconfig b/arch/mn10300/configs/asb2303_defconfig
index 3aa8906b3dea..3acce23708b0 100644
--- a/arch/mn10300/configs/asb2303_defconfig
+++ b/arch/mn10300/configs/asb2303_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.25-rc2
-# Tue Feb 19 18:52:24 2008
+# Linux kernel version: 2.6.30-rc2
+# Sat Apr 18 11:13:22 2009
#
CONFIG_MN10300=y
CONFIG_AM33=y
@@ -18,7 +18,6 @@ CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_BUG=y
CONFIG_QUICKLIST=y
CONFIG_ARCH_HAS_ILOG2_U32=y
-# CONFIG_ARCH_SUPPORTS_AOUT is not set
CONFIG_GENERIC_HARDIRQS=y
# CONFIG_HOTPLUG_CPU is not set
CONFIG_HZ=1000
@@ -40,52 +39,58 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
-# CONFIG_USER_SCHED is not set
-# CONFIG_CGROUP_SCHED is not set
-# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
# CONFIG_KALLSYMS is not set
+CONFIG_STRIP_ASM_SYMS=y
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
# CONFIG_MARKERS is not set
-CONFIG_OPROFILE=y
-# CONFIG_HAVE_OPROFILE is not set
-# CONFIG_HAVE_KPROBES is not set
-# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
# CONFIG_BLOCK is not set
-CONFIG_CLASSIC_RCU=y
-# CONFIG_PREEMPT_RCU is not set
+# CONFIG_FREEZER is not set
#
# Matsushita MN10300 system setup
@@ -107,7 +112,6 @@ CONFIG_INTERRUPT_VECTOR_BASE=0x90000000
CONFIG_KERNEL_TEXT_ADDRESS=0x90001000
CONFIG_KERNEL_ZIMAGE_BASE_ADDRESS=0x90700000
CONFIG_PREEMPT=y
-CONFIG_PREEMPT_BKL=y
CONFIG_MN10300_CURRENT_IN_E2=y
CONFIG_MN10300_USING_JTAG=y
CONFIG_MN10300_RTC=y
@@ -135,13 +139,15 @@ CONFIG_FLATMEM_MANUAL=y
# 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_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=1
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
#
# Power management options
@@ -152,11 +158,9 @@ CONFIG_VIRT_TO_BUS=y
# Executable formats
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -194,8 +198,6 @@ 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
@@ -203,6 +205,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -212,7 +215,9 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -223,14 +228,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# 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_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -255,6 +254,7 @@ CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
#
# User Modules And Translation Layers
@@ -297,9 +297,7 @@ CONFIG_MTD_CFI_UTIL=y
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x8000000
-CONFIG_MTD_PHYSMAP_LEN=0x0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
# CONFIG_MTD_PLATRAM is not set
#
@@ -319,14 +317,23 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
# CONFIG_PARPORT is not set
CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
-# CONFIG_HAVE_IDE is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
#
# SCSI device support
@@ -334,7 +341,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_SCSI_DMA is not set
# CONFIG_SCSI_NETLINK is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -345,10 +352,15 @@ CONFIG_NETDEVICES=y
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
CONFIG_SMC91X=y
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -358,6 +370,10 @@ CONFIG_SMC91X=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -382,6 +398,7 @@ CONFIG_SMC91X=y
# Character devices
#
# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -403,6 +420,7 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -411,34 +429,43 @@ CONFIG_RTC=y
# CONFIG_R3964 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
# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
# CONFIG_DAB is not set
#
@@ -453,21 +480,17 @@ CONFIG_SSB_POSSIBLE=y
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
-
-#
-# Userspace I/O
-#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
@@ -481,20 +504,23 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+# CONFIG_PROC_PAGE_MONITOR is not set
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -506,19 +532,17 @@ CONFIG_JFFS2_ZLIB=y
# CONFIG_JFFS2_LZO is not set
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_ROMFS_FS is not set
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_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
@@ -535,12 +559,16 @@ CONFIG_SUNRPC=y
# CONFIG_PRINTK_TIME is not set
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
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 is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
# CONFIG_SAMPLES is not set
#
@@ -548,26 +576,26 @@ CONFIG_MAGIC_SYSRQ=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T 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
-
-#
-# Profiling support
-#
+CONFIG_NLATTR=y
diff --git a/arch/mn10300/include/asm/bug.h b/arch/mn10300/include/asm/bug.h
index 4fcf3384e259..aa6a38886391 100644
--- a/arch/mn10300/include/asm/bug.h
+++ b/arch/mn10300/include/asm/bug.h
@@ -11,10 +11,12 @@
#ifndef _ASM_BUG_H
#define _ASM_BUG_H
+#ifdef CONFIG_BUG
+
/*
* Tell the user there is some problem.
*/
-#define _debug_bug_trap() \
+#define BUG() \
do { \
asm volatile( \
" syscall 15 \n" \
@@ -25,11 +27,11 @@ do { \
: \
: "i"(__FILE__), "i"(__LINE__) \
); \
-} while (0)
-
-#define BUG() _debug_bug_trap()
+} while (1)
#define HAVE_ARCH_BUG
+#endif /* CONFIG_BUG */
+
#include <asm-generic/bug.h>
#endif /* _ASM_BUG_H */
diff --git a/arch/mn10300/include/asm/gdb-stub.h b/arch/mn10300/include/asm/gdb-stub.h
index e5a6368559af..556cce992548 100644
--- a/arch/mn10300/include/asm/gdb-stub.h
+++ b/arch/mn10300/include/asm/gdb-stub.h
@@ -109,7 +109,6 @@ extern asmlinkage int gdbstub_intercept(struct pt_regs *, enum exception_code);
extern asmlinkage void gdbstub_exception(struct pt_regs *, enum exception_code);
extern asmlinkage void __gdbstub_bug_trap(void);
extern asmlinkage void __gdbstub_pause(void);
-extern asmlinkage void start_kernel(void);
#ifndef CONFIG_MN10300_CACHE_DISABLED
extern asmlinkage void gdbstub_purge_cache(void);
diff --git a/arch/mn10300/include/asm/unistd.h b/arch/mn10300/include/asm/unistd.h
index 543a4f98695d..fef5b434dadc 100644
--- a/arch/mn10300/include/asm/unistd.h
+++ b/arch/mn10300/include/asm/unistd.h
@@ -344,6 +344,8 @@
#define __NR_dup3 331
#define __NR_pipe2 332
#define __NR_inotify_init1 333
+#define __NR_preadv 334
+#define __NR_pwritev 335
#ifdef __KERNEL__
diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S
index 34ab5a293153..3dc3e462f92a 100644
--- a/arch/mn10300/kernel/entry.S
+++ b/arch/mn10300/kernel/entry.S
@@ -723,6 +723,8 @@ ENTRY(sys_call_table)
.long sys_dup3
.long sys_pipe2
.long sys_inotify_init1
+ .long sys_preadv
+ .long sys_pwritev /* 335 */
nr_syscalls=(.-sys_call_table)/4
diff --git a/arch/mn10300/kernel/head.S b/arch/mn10300/kernel/head.S
index 8a8309fbe3c4..14f27f3bfaf4 100644
--- a/arch/mn10300/kernel/head.S
+++ b/arch/mn10300/kernel/head.S
@@ -9,6 +9,7 @@
* 2 of the Licence, or (at your option) any later version.
*/
+#include <linux/init.h>
#include <linux/threads.h>
#include <linux/linkage.h>
#include <linux/serial_reg.h>
@@ -19,7 +20,7 @@
#include <asm/param.h>
#include <unit/serial.h>
- .section .text.head,"ax"
+ __HEAD
###############################################################################
#
diff --git a/arch/mn10300/kernel/setup.c b/arch/mn10300/kernel/setup.c
index 71414e19fd16..79890edfd67a 100644
--- a/arch/mn10300/kernel/setup.c
+++ b/arch/mn10300/kernel/setup.c
@@ -136,10 +136,6 @@ void __init setup_arch(char **cmdline_p)
data_resource.start = virt_to_bus(&_etext);
data_resource.end = virt_to_bus(&_edata)-1;
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
-
start_pfn = (CONFIG_KERNEL_RAM_BASE_ADDRESS >> PAGE_SHIFT);
kstart_pfn = PFN_UP(__pa(&_text));
free_pfn = PFN_UP(__pa(&_end));
diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
index b8259668f7dc..24de6b90f401 100644
--- a/arch/mn10300/kernel/vmlinux.lds.S
+++ b/arch/mn10300/kernel/vmlinux.lds.S
@@ -27,10 +27,7 @@ SECTIONS
_stext = .;
_text = .; /* Text and read-only data */
.text : {
- *(
- .text.head
- .text
- )
+ HEAD_TEXT
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
index 4ea4229d765c..8007f1e65729 100644
--- a/arch/parisc/kernel/irq.c
+++ b/arch/parisc/kernel/irq.c
@@ -130,15 +130,17 @@ int cpu_check_affinity(unsigned int irq, const struct cpumask *dest)
return cpu_dest;
}
-static void cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest)
+static int cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest)
{
int cpu_dest;
cpu_dest = cpu_check_affinity(irq, dest);
if (cpu_dest < 0)
- return;
+ return -1;
cpumask_copy(&irq_desc[irq].affinity, dest);
+
+ return 0;
}
#endif
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 5b50e1ac6179..a0d1146a0578 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -181,6 +181,10 @@ config SYS_SUPPORTS_APM_EMULATION
default y if PMAC_APM_EMU
bool
+config DTC
+ bool
+ default y
+
config DEFAULT_UIMAGE
bool
help
@@ -462,7 +466,7 @@ config PPC_64K_PAGES
config PPC_256K_PAGES
bool "256k page size" if 44x
- depends on !STDBINUTILS && (!SHMEM || BROKEN)
+ depends on !STDBINUTILS
help
Make the page size 256k.
diff --git a/arch/powerpc/boot/4xx.c b/arch/powerpc/boot/4xx.c
index 5c878436f348..325b310573b9 100644
--- a/arch/powerpc/boot/4xx.c
+++ b/arch/powerpc/boot/4xx.c
@@ -158,21 +158,33 @@ void ibm440spe_fixup_memsize(void)
#define DDR_GET_VAL(val, mask, shift) (((val) >> (shift)) & (mask))
-void ibm4xx_denali_fixup_memsize(void)
+/*
+ * Some U-Boot versions set the number of chipselects to two
+ * for Sequoia/Rainier boards while they only have one chipselect
+ * hardwired. Hardcode the number of chipselects to one
+ * for sequioa/rainer board models or read the actual value
+ * from the memory controller register DDR0_10 otherwise.
+ */
+static inline u32 ibm4xx_denali_get_cs(void)
{
- u32 val, max_cs, max_col, max_row;
- u32 cs, col, row, bank, dpath;
- unsigned long memsize;
+ void *devp;
+ char model[64];
+ u32 val, cs;
- val = SDRAM0_READ(DDR0_02);
- if (!DDR_GET_VAL(val, DDR_START, DDR_START_SHIFT))
- fatal("DDR controller is not initialized\n");
+ devp = finddevice("/");
+ if (!devp)
+ goto read_cs;
- /* get maximum cs col and row values */
- max_cs = DDR_GET_VAL(val, DDR_MAX_CS_REG, DDR_MAX_CS_REG_SHIFT);
- max_col = DDR_GET_VAL(val, DDR_MAX_COL_REG, DDR_MAX_COL_REG_SHIFT);
- max_row = DDR_GET_VAL(val, DDR_MAX_ROW_REG, DDR_MAX_ROW_REG_SHIFT);
+ if (getprop(devp, "model", model, sizeof(model)) <= 0)
+ goto read_cs;
+ model[sizeof(model)-1] = 0;
+
+ if (!strcmp(model, "amcc,sequoia") ||
+ !strcmp(model, "amcc,rainier"))
+ return 1;
+
+read_cs:
/* get CS value */
val = SDRAM0_READ(DDR0_10);
@@ -183,7 +195,25 @@ void ibm4xx_denali_fixup_memsize(void)
cs++;
val = val >> 1;
}
+ return cs;
+}
+
+void ibm4xx_denali_fixup_memsize(void)
+{
+ u32 val, max_cs, max_col, max_row;
+ u32 cs, col, row, bank, dpath;
+ unsigned long memsize;
+
+ val = SDRAM0_READ(DDR0_02);
+ if (!DDR_GET_VAL(val, DDR_START, DDR_START_SHIFT))
+ fatal("DDR controller is not initialized\n");
+ /* get maximum cs col and row values */
+ max_cs = DDR_GET_VAL(val, DDR_MAX_CS_REG, DDR_MAX_CS_REG_SHIFT);
+ max_col = DDR_GET_VAL(val, DDR_MAX_COL_REG, DDR_MAX_COL_REG_SHIFT);
+ max_row = DDR_GET_VAL(val, DDR_MAX_ROW_REG, DDR_MAX_ROW_REG_SHIFT);
+
+ cs = ibm4xx_denali_get_cs();
if (!cs)
fatal("No memory installed\n");
if (cs > max_cs)
@@ -193,9 +223,9 @@ void ibm4xx_denali_fixup_memsize(void)
val = SDRAM0_READ(DDR0_14);
if (DDR_GET_VAL(val, DDR_REDUC, DDR_REDUC_SHIFT))
- dpath = 8; /* 64 bits */
- else
dpath = 4; /* 32 bits */
+ else
+ dpath = 8; /* 64 bits */
/* get address pins (rows) */
val = SDRAM0_READ(DDR0_42);
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 4458abb67c51..8da2bf963b57 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -33,7 +33,7 @@ ifeq ($(call cc-option-yn, -fstack-protector),y)
BOOTCFLAGS += -fno-stack-protector
endif
-BOOTCFLAGS += -I$(obj) -I$(srctree)/$(obj) -I$(srctree)/$(src)/libfdt
+BOOTCFLAGS += -I$(obj) -I$(srctree)/$(obj)
DTS_FLAGS ?= -p 1024
@@ -53,9 +53,14 @@ zliblinuxheader := zlib.h zconf.h zutil.h
$(addprefix $(obj)/,$(zlib) cuboot-c2k.o gunzip_util.o main.o prpmc2800.o): \
$(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
-src-libfdt := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
+libfdt := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
+libfdtheader := fdt.h libfdt.h libfdt_internal.h
+
+$(addprefix $(obj)/,$(libfdt) libfdt-wrapper.o simpleboot.o): \
+ $(addprefix $(obj)/,$(libfdtheader))
+
src-wlib := string.S crt0.S crtsavres.S stdio.c main.c \
- $(addprefix libfdt/,$(src-libfdt)) libfdt-wrapper.c \
+ $(libfdt) libfdt-wrapper.c \
ns16550.c serial.c simple_alloc.c div64.S util.S \
gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
@@ -96,6 +101,12 @@ $(addprefix $(obj)/,$(zlibheader)): $(obj)/%: $(srctree)/lib/zlib_inflate/%
$(addprefix $(obj)/,$(zliblinuxheader)): $(obj)/%: $(srctree)/include/linux/%
$(call cmd,copy_zliblinuxheader)
+quiet_cmd_copy_libfdt = COPY $@
+ cmd_copy_libfdt = cp $< $@
+
+$(addprefix $(obj)/,$(libfdt) $(libfdtheader)): $(obj)/%: $(srctree)/scripts/dtc/libfdt/%
+ $(call cmd,copy_libfdt)
+
$(obj)/empty.c:
@touch $@
@@ -103,6 +114,7 @@ $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds: $(obj)/%: $(srct
@cp $< $@
clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \
+ $(libfdt) $(libfdtheader) \
empty.c zImage.coff.lds zImage.ps3.lds zImage.lds
quiet_cmd_bootcc = BOOTCC $@
@@ -114,6 +126,8 @@ quiet_cmd_bootas = BOOTAS $@
quiet_cmd_bootar = BOOTAR $@
cmd_bootar = $(CROSS32AR) -cr $@.$$$$ $(filter-out FORCE,$^); mv $@.$$$$ $@
+$(obj-libfdt): $(obj)/%.o: $(srctree)/scripts/dtc/libfdt/%.c FORCE
+ $(call if_changed_dep,bootcc)
$(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c FORCE
$(Q)mkdir -p $(dir $@)
$(call if_changed_dep,bootcc)
@@ -124,7 +138,7 @@ $(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S FORCE
$(obj)/wrapper.a: $(obj-wlib) FORCE
$(call if_changed,bootar)
-hostprogs-y := addnote addRamDisk hack-coff mktree dtc
+hostprogs-y := addnote addRamDisk hack-coff mktree
targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a)
extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
@@ -133,47 +147,10 @@ extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
dtstree := $(srctree)/$(src)/dts
wrapper :=$(srctree)/$(src)/wrapper
-wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree dtc) \
+wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \
$(wrapper) FORCE
#############
-# Bits for building dtc
-# DTC_GENPARSER := 1 # Uncomment to rebuild flex/bison output
-
-dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o srcpos.o checks.o
-dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o
-dtc-objs := $(addprefix dtc-src/, $(dtc-objs))
-
-# prerequisites on generated files needs to be explicit
-$(obj)/dtc-src/dtc-parser.tab.o: $(obj)/dtc-src/dtc-parser.tab.c $(obj)/dtc-src/dtc-parser.tab.h
-$(obj)/dtc-src/dtc-lexer.lex.o: $(obj)/dtc-src/dtc-lexer.lex.c $(obj)/dtc-src/dtc-parser.tab.h
-
-HOSTCFLAGS += -I$(src)/dtc-src/ -I$(src)/libfdt/
-
-targets += dtc-src/dtc-parser.tab.c
-targets += dtc-src/dtc-lexer.lex.c
-
-clean-files += dtc-src/dtc-parser.tab.h
-
-ifdef DTC_GENPARSER
-BISON = bison
-FLEX = flex
-
-quiet_cmd_bison = BISON $@
- cmd_bison = $(BISON) -o$@ -d $<; cp $@ $@_shipped
-quiet_cmd_flex = FLEX $@
- cmd_flex = $(FLEX) -o$@ $<; cp $@ $@_shipped
-
-$(obj)/dtc-src/dtc-parser.tab.c: $(src)/dtc-src/dtc-parser.y FORCE
- $(call if_changed,bison)
-
-$(obj)/dtc-src/dtc-parser.tab.h: $(obj)/dtc-src/dtc-parser.tab.c
-
-$(obj)/dtc-src/dtc-lexer.lex.c: $(src)/dtc-src/dtc-lexer.l FORCE
- $(call if_changed,flex)
-endif
-
-#############
# Bits for building various flavours of zImage
ifneq ($(CROSS32_COMPILE),)
@@ -347,8 +324,10 @@ $(obj)/treeImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
$(call if_changed,wrap,treeboot-$*,,$(obj)/$*.dtb)
# Rule to build device tree blobs
-$(obj)/%.dtb: $(dtstree)/%.dts $(obj)/dtc
- $(obj)/dtc -O dtb -o $(obj)/$*.dtb -b 0 $(DTS_FLAGS) $(dtstree)/$*.dts
+DTC = $(objtree)/scripts/dtc/dtc
+
+$(obj)/%.dtb: $(dtstree)/%.dts
+ $(DTC) -O dtb -o $(obj)/$*.dtb -b 0 $(DTS_FLAGS) $(dtstree)/$*.dts
# If there isn't a platform selected then just strip the vmlinux.
ifeq (,$(image-y))
diff --git a/arch/powerpc/boot/dts/gef_ppc9a.dts b/arch/powerpc/boot/dts/gef_ppc9a.dts
index d47ad0718759..910944edd886 100644
--- a/arch/powerpc/boot/dts/gef_ppc9a.dts
+++ b/arch/powerpc/boot/dts/gef_ppc9a.dts
@@ -161,11 +161,24 @@
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>;
+ device_type = "soc";
compatible = "fsl,mpc8641-soc", "simple-bus";
ranges = <0x0 0xfef00000 0x00100000>;
- reg = <0xfef00000 0x100000>; // CCSRBAR 1M
bus-frequency = <33333333>;
+ mcm-law@0 {
+ compatible = "fsl,mcm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <10>;
+ };
+
+ mcm@1000 {
+ compatible = "fsl,mpc8641-mcm", "fsl,mcm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
i2c1: i2c@3000 {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/powerpc/boot/dts/gef_sbc310.dts b/arch/powerpc/boot/dts/gef_sbc310.dts
index 1569117e5ddc..0f4c9ec2c3a6 100644
--- a/arch/powerpc/boot/dts/gef_sbc310.dts
+++ b/arch/powerpc/boot/dts/gef_sbc310.dts
@@ -163,9 +163,21 @@
device_type = "soc";
compatible = "simple-bus";
ranges = <0x0 0xfef00000 0x00100000>;
- reg = <0xfef00000 0x100000>; // CCSRBAR 1M
bus-frequency = <33333333>;
+ mcm-law@0 {
+ compatible = "fsl,mcm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <10>;
+ };
+
+ mcm@1000 {
+ compatible = "fsl,mpc8641-mcm", "fsl,mcm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
i2c1: i2c@3000 {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/powerpc/boot/dts/gef_sbc610.dts b/arch/powerpc/boot/dts/gef_sbc610.dts
index 6582dbd36da7..217f8aa66725 100644
--- a/arch/powerpc/boot/dts/gef_sbc610.dts
+++ b/arch/powerpc/boot/dts/gef_sbc610.dts
@@ -128,9 +128,21 @@
device_type = "soc";
compatible = "simple-bus";
ranges = <0x0 0xfef00000 0x00100000>;
- reg = <0xfef00000 0x100000>; // CCSRBAR 1M
bus-frequency = <33333333>;
+ mcm-law@0 {
+ compatible = "fsl,mcm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <10>;
+ };
+
+ mcm@1000 {
+ compatible = "fsl,mpc8641-mcm", "fsl,mcm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
i2c1: i2c@3000 {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/powerpc/boot/dts/ksi8560.dts b/arch/powerpc/boot/dts/ksi8560.dts
index c9cfd374bffb..bdb7fc0fa332 100644
--- a/arch/powerpc/boot/dts/ksi8560.dts
+++ b/arch/powerpc/boot/dts/ksi8560.dts
@@ -56,6 +56,19 @@
ranges = <0x00000000 0xfdf00000 0x00100000>;
bus-frequency = <0>; /* Fixed by bootwrapper */
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <8>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8560-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,mpc8540-memory-controller";
reg = <0x2000 0x1000>;
diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts
index c63e3566479e..d13cb11ce623 100644
--- a/arch/powerpc/boot/dts/lite5200b.dts
+++ b/arch/powerpc/boot/dts/lite5200b.dts
@@ -293,4 +293,43 @@
0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
};
+
+ localbus {
+ compatible = "fsl,mpc5200b-lpb","fsl,mpc5200-lpb","simple-bus";
+
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ ranges = <0 0 0xfe000000 0x02000000>;
+
+ flash@0,0 {
+ compatible = "cfi-flash";
+ reg = <0 0 0x02000000>;
+ bank-width = <1>;
+ #size-cells = <1>;
+ #address-cells = <1>;
+
+ partition@0 {
+ label = "kernel";
+ reg = <0x00000000 0x00200000>;
+ };
+ partition@200000 {
+ label = "rootfs";
+ reg = <0x00200000 0x01d00000>;
+ };
+ partition@1f00000 {
+ label = "u-boot";
+ reg = <0x01f00000 0x00060000>;
+ };
+ partition@1f60000 {
+ label = "u-boot-env";
+ reg = <0x01f60000 0x00020000>;
+ };
+ partition@1f80000 {
+ label = "dtb";
+ reg = <0x01f80000 0x00080000>;
+ };
+ };
+ };
+
};
diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts
index 57c595bf1071..436c9c671dd9 100644
--- a/arch/powerpc/boot/dts/mpc832x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc832x_mds.dts
@@ -249,6 +249,8 @@
reg = <0xe0100000 0x480>;
brg-frequency = <0>;
bus-frequency = <198000000>;
+ fsl,qe-num-riscs = <1>;
+ fsl,qe-num-snums = <28>;
muram@10000 {
#address-cells = <1>;
@@ -369,7 +371,6 @@
};
pci0: pci@e0008500 {
- cell-index = <1>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
/* IDSEL 0x11 AD17 */
diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts
index 4319bd70a580..9a0952f74b81 100644
--- a/arch/powerpc/boot/dts/mpc832x_rdb.dts
+++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts
@@ -221,6 +221,8 @@
reg = <0xe0100000 0x480>;
brg-frequency = <0>;
bus-frequency = <198000000>;
+ fsl,qe-num-riscs = <1>;
+ fsl,qe-num-snums = <28>;
muram@10000 {
#address-cells = <1>;
@@ -327,7 +329,6 @@
};
pci0: pci@e0008500 {
- cell-index = <1>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
/* IDSEL 0x10 AD16 (USB) */
diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
index 1ae38f0ddef8..e3eeaeda9187 100644
--- a/arch/powerpc/boot/dts/mpc8349emitx.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
@@ -278,7 +278,6 @@
};
pci0: pci@e0008500 {
- cell-index = <1>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
/* IDSEL 0x10 - SATA */
@@ -301,7 +300,6 @@
};
pci1: pci@e0008600 {
- cell-index = <2>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
/* IDSEL 0x0E - MiniPCI Slot */
diff --git a/arch/powerpc/boot/dts/mpc8349emitxgp.dts b/arch/powerpc/boot/dts/mpc8349emitxgp.dts
index 662abe1fb804..eb732115f016 100644
--- a/arch/powerpc/boot/dts/mpc8349emitxgp.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitxgp.dts
@@ -227,7 +227,6 @@
};
pci0: pci@e0008600 {
- cell-index = <2>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
/* IDSEL 0x0F - PCI Slot */
diff --git a/arch/powerpc/boot/dts/mpc834x_mds.dts b/arch/powerpc/boot/dts/mpc834x_mds.dts
index d9f0a2325fa4..a2553a6f9009 100644
--- a/arch/powerpc/boot/dts/mpc834x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc834x_mds.dts
@@ -286,7 +286,6 @@
};
pci0: pci@e0008500 {
- cell-index = <1>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
@@ -348,7 +347,6 @@
};
pci1: pci@e0008600 {
- cell-index = <2>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts
index 6e34f170fa62..39ff4c829caf 100644
--- a/arch/powerpc/boot/dts/mpc836x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc836x_mds.dts
@@ -289,6 +289,8 @@
reg = <0xe0100000 0x480>;
brg-frequency = <0>;
bus-frequency = <396000000>;
+ fsl,qe-num-riscs = <2>;
+ fsl,qe-num-snums = <28>;
muram@10000 {
#address-cells = <1>;
@@ -410,7 +412,6 @@
};
pci0: pci@e0008500 {
- cell-index = <1>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
diff --git a/arch/powerpc/boot/dts/mpc836x_rdk.dts b/arch/powerpc/boot/dts/mpc836x_rdk.dts
index 37b789510d68..6315d6fcc58a 100644
--- a/arch/powerpc/boot/dts/mpc836x_rdk.dts
+++ b/arch/powerpc/boot/dts/mpc836x_rdk.dts
@@ -198,6 +198,8 @@
clock-frequency = <0>;
bus-frequency = <0>;
brg-frequency = <0>;
+ fsl,qe-num-riscs = <2>;
+ fsl,qe-num-snums = <28>;
muram@10000 {
#address-cells = <1>;
diff --git a/arch/powerpc/boot/dts/mpc8377_mds.dts b/arch/powerpc/boot/dts/mpc8377_mds.dts
index 963708017e6c..67bb372c9451 100644
--- a/arch/powerpc/boot/dts/mpc8377_mds.dts
+++ b/arch/powerpc/boot/dts/mpc8377_mds.dts
@@ -383,7 +383,6 @@
};
pci0: pci@e0008500 {
- cell-index = <0>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
diff --git a/arch/powerpc/boot/dts/mpc8378_mds.dts b/arch/powerpc/boot/dts/mpc8378_mds.dts
index 651ff2f9db2d..a955a577db81 100644
--- a/arch/powerpc/boot/dts/mpc8378_mds.dts
+++ b/arch/powerpc/boot/dts/mpc8378_mds.dts
@@ -367,7 +367,6 @@
};
pci0: pci@e0008500 {
- cell-index = <0>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
diff --git a/arch/powerpc/boot/dts/mpc8379_mds.dts b/arch/powerpc/boot/dts/mpc8379_mds.dts
index d6f208b8297a..d266ddbfc28d 100644
--- a/arch/powerpc/boot/dts/mpc8379_mds.dts
+++ b/arch/powerpc/boot/dts/mpc8379_mds.dts
@@ -397,7 +397,6 @@
};
pci0: pci@e0008500 {
- cell-index = <0>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
diff --git a/arch/powerpc/boot/dts/mpc8536ds.dts b/arch/powerpc/boot/dts/mpc8536ds.dts
index b31c5041350b..e781ad2f1f8a 100644
--- a/arch/powerpc/boot/dts/mpc8536ds.dts
+++ b/arch/powerpc/boot/dts/mpc8536ds.dts
@@ -51,9 +51,21 @@
device_type = "soc";
compatible = "simple-bus";
ranges = <0x0 0xffe00000 0x100000>;
- reg = <0xffe00000 0x1000>;
bus-frequency = <0>; // Filled out by uboot.
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <12>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8536-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,mpc8536-memory-controller";
reg = <0x2000 0x1000>;
@@ -321,7 +333,6 @@
};
pci0: pci@ffe08000 {
- cell-index = <0>;
compatible = "fsl,mpc8540-pci";
device_type = "pci";
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
@@ -346,7 +357,6 @@
};
pci1: pcie@ffe09000 {
- cell-index = <1>;
compatible = "fsl,mpc8548-pcie";
device_type = "pci";
#interrupt-cells = <1>;
@@ -383,7 +393,6 @@
};
pci2: pcie@ffe0a000 {
- cell-index = <2>;
compatible = "fsl,mpc8548-pcie";
device_type = "pci";
#interrupt-cells = <1>;
@@ -420,7 +429,6 @@
};
pci3: pcie@ffe0b000 {
- cell-index = <3>;
compatible = "fsl,mpc8548-pcie";
device_type = "pci";
#interrupt-cells = <1>;
diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts
index ddd67be10b03..9dc292962a9a 100644
--- a/arch/powerpc/boot/dts/mpc8540ads.dts
+++ b/arch/powerpc/boot/dts/mpc8540ads.dts
@@ -55,9 +55,21 @@
device_type = "soc";
compatible = "simple-bus";
ranges = <0x0 0xe0000000 0x100000>;
- reg = <0xe0000000 0x100000>; // CCSRBAR 1M
bus-frequency = <0>;
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <8>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8540-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,8540-memory-controller";
reg = <0x2000 0x1000>;
@@ -258,7 +270,6 @@
};
pci0: pci@e0008000 {
- cell-index = <0>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts
index e45097f44fbd..9a3ad311aedf 100644
--- a/arch/powerpc/boot/dts/mpc8541cds.dts
+++ b/arch/powerpc/boot/dts/mpc8541cds.dts
@@ -55,9 +55,21 @@
device_type = "soc";
compatible = "simple-bus";
ranges = <0x0 0xe0000000 0x100000>;
- reg = <0xe0000000 0x1000>; // CCSRBAR 1M
bus-frequency = <0>;
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <8>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8541-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,8541-memory-controller";
reg = <0x2000 0x1000>;
@@ -272,7 +284,6 @@
};
pci0: pci@e0008000 {
- cell-index = <0>;
interrupt-map-mask = <0x1f800 0x0 0x0 0x7>;
interrupt-map = <
@@ -344,7 +355,6 @@
};
pci1: pci@e0009000 {
- cell-index = <1>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
diff --git a/arch/powerpc/boot/dts/mpc8544ds.dts b/arch/powerpc/boot/dts/mpc8544ds.dts
index 7c6932be0197..98e94b465662 100644
--- a/arch/powerpc/boot/dts/mpc8544ds.dts
+++ b/arch/powerpc/boot/dts/mpc8544ds.dts
@@ -57,9 +57,21 @@
compatible = "simple-bus";
ranges = <0x0 0xe0000000 0x100000>;
- reg = <0xe0000000 0x1000>; // CCSRBAR 1M
bus-frequency = <0>; // Filled out by uboot.
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <10>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8544-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,8544-memory-controller";
reg = <0x2000 0x1000>;
@@ -274,7 +286,6 @@
};
pci0: pci@e0008000 {
- cell-index = <0>;
compatible = "fsl,mpc8540-pci";
device_type = "pci";
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
@@ -306,7 +317,6 @@
};
pci1: pcie@e0009000 {
- cell-index = <1>;
compatible = "fsl,mpc8548-pcie";
device_type = "pci";
#interrupt-cells = <1>;
@@ -343,7 +353,6 @@
};
pci2: pcie@e000a000 {
- cell-index = <2>;
compatible = "fsl,mpc8548-pcie";
device_type = "pci";
#interrupt-cells = <1>;
@@ -380,7 +389,6 @@
};
pci3: pcie@e000b000 {
- cell-index = <3>;
compatible = "fsl,mpc8548-pcie";
device_type = "pci";
#interrupt-cells = <1>;
diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts
index 804e90353293..475be1433fe1 100644
--- a/arch/powerpc/boot/dts/mpc8548cds.dts
+++ b/arch/powerpc/boot/dts/mpc8548cds.dts
@@ -60,9 +60,21 @@
device_type = "soc";
compatible = "simple-bus";
ranges = <0x0 0xe0000000 0x100000>;
- reg = <0xe0000000 0x1000>; // CCSRBAR
bus-frequency = <0>;
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <10>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8548-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,8548-memory-controller";
reg = <0x2000 0x1000>;
@@ -328,7 +340,6 @@
};
pci0: pci@e0008000 {
- cell-index = <0>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
/* IDSEL 0x4 (PCIX Slot 2) */
@@ -478,7 +489,6 @@
};
pci1: pci@e0009000 {
- cell-index = <1>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
@@ -503,7 +513,6 @@
};
pci2: pcie@e000a000 {
- cell-index = <2>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
diff --git a/arch/powerpc/boot/dts/mpc8555cds.dts b/arch/powerpc/boot/dts/mpc8555cds.dts
index 9484f0729b10..065b2f093de2 100644
--- a/arch/powerpc/boot/dts/mpc8555cds.dts
+++ b/arch/powerpc/boot/dts/mpc8555cds.dts
@@ -55,9 +55,21 @@
device_type = "soc";
compatible = "simple-bus";
ranges = <0x0 0xe0000000 0x100000>;
- reg = <0xe0000000 0x1000>; // CCSRBAR 1M
bus-frequency = <0>;
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <8>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8555-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,8555-memory-controller";
reg = <0x2000 0x1000>;
@@ -272,7 +284,6 @@
};
pci0: pci@e0008000 {
- cell-index = <0>;
interrupt-map-mask = <0x1f800 0x0 0x0 0x7>;
interrupt-map = <
@@ -344,7 +355,6 @@
};
pci1: pci@e0009000 {
- cell-index = <1>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
diff --git a/arch/powerpc/boot/dts/mpc8560ads.dts b/arch/powerpc/boot/dts/mpc8560ads.dts
index cc2acf87d02f..a5bb1ec70a5a 100644
--- a/arch/powerpc/boot/dts/mpc8560ads.dts
+++ b/arch/powerpc/boot/dts/mpc8560ads.dts
@@ -55,9 +55,21 @@
device_type = "soc";
compatible = "simple-bus";
ranges = <0x0 0xe0000000 0x100000>;
- reg = <0xe0000000 0x200>;
bus-frequency = <330000000>;
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <8>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8560-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,8540-memory-controller";
reg = <0x2000 0x1000>;
@@ -291,7 +303,6 @@
};
pci0: pci@e0008000 {
- cell-index = <0>;
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts
index 9d52e3b25047..038913deb2e9 100644
--- a/arch/powerpc/boot/dts/mpc8568mds.dts
+++ b/arch/powerpc/boot/dts/mpc8568mds.dts
@@ -26,6 +26,7 @@
serial1 = &serial1;
pci0 = &pci0;
pci1 = &pci1;
+ rapidio0 = &rio0;
};
cpus {
@@ -62,9 +63,21 @@
device_type = "soc";
compatible = "simple-bus";
ranges = <0x0 0xe0000000 0x100000>;
- reg = <0xe0000000 0x1000>;
bus-frequency = <0>;
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <10>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8568-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,8568-memory-controller";
reg = <0x2000 0x1000>;
@@ -349,6 +362,8 @@
reg = <0xe0080000 0x480>;
brg-frequency = <0>;
bus-frequency = <396000000>;
+ fsl,qe-num-riscs = <2>;
+ fsl,qe-num-snums = <28>;
muram@10000 {
#address-cells = <1>;
@@ -459,7 +474,6 @@
};
pci0: pci@e0008000 {
- cell-index = <0>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
/* IDSEL 0x12 AD18 */
@@ -490,7 +504,6 @@
/* PCI Express */
pci1: pcie@e000a000 {
- cell-index = <2>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
@@ -526,4 +539,20 @@
0x0 0x800000>;
};
};
+
+ rio0: rapidio@e00c00000 {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ compatible = "fsl,mpc8568-rapidio", "fsl,rapidio-delta";
+ reg = <0xe00c0000 0x20000>;
+ ranges = <0x0 0x0 0xc0000000 0x0 0x20000000>;
+ interrupts = <48 2 /* error */
+ 49 2 /* bell_outb */
+ 50 2 /* bell_inb */
+ 53 2 /* msg1_tx */
+ 54 2 /* msg1_rx */
+ 55 2 /* msg2_tx */
+ 56 2 /* msg2_rx */>;
+ interrupt-parent = <&mpic>;
+ };
};
diff --git a/arch/powerpc/boot/dts/mpc8569mds.dts b/arch/powerpc/boot/dts/mpc8569mds.dts
new file mode 100644
index 000000000000..23a102ea9143
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8569mds.dts
@@ -0,0 +1,567 @@
+/*
+ * MPC8569E MDS Device Tree Source
+ *
+ * Copyright (C) 2009 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.
+ */
+
+/dts-v1/;
+
+/ {
+ model = "MPC8569EMDS";
+ compatible = "fsl,MPC8569EMDS";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ aliases {
+ serial0 = &serial0;
+ serial1 = &serial1;
+ ethernet0 = &enet0;
+ ethernet1 = &enet1;
+ ethernet2 = &enet2;
+ ethernet3 = &enet3;
+ pci1 = &pci1;
+ rapidio0 = &rio0;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PowerPC,8569@0 {
+ device_type = "cpu";
+ reg = <0x0>;
+ d-cache-line-size = <32>; // 32 bytes
+ i-cache-line-size = <32>; // 32 bytes
+ d-cache-size = <0x8000>; // L1, 32K
+ i-cache-size = <0x8000>; // L1, 32K
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+ next-level-cache = <&L2>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ };
+
+ localbus@e0005000 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8569-elbc", "fsl,elbc", "simple-bus";
+ reg = <0xe0005000 0x1000>;
+ interrupts = <19 2>;
+ interrupt-parent = <&mpic>;
+
+ ranges = <0x0 0x0 0xfe000000 0x02000000
+ 0x1 0x0 0xf8000000 0x00008000
+ 0x2 0x0 0xf0000000 0x04000000
+ 0x3 0x0 0xfc000000 0x00008000
+ 0x4 0x0 0xf8008000 0x00008000
+ 0x5 0x0 0xf8010000 0x00008000>;
+
+ nor@0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "cfi-flash";
+ reg = <0x0 0x0 0x02000000>;
+ bank-width = <2>;
+ device-width = <1>;
+ };
+
+ bcsr@1,0 {
+ compatible = "fsl,mpc8569mds-bcsr";
+ reg = <1 0 0x8000>;
+ };
+
+ nand@3,0 {
+ compatible = "fsl,mpc8569-fcm-nand",
+ "fsl,elbc-fcm-nand";
+ reg = <3 0 0x8000>;
+ };
+
+ pib@4,0 {
+ compatible = "fsl,mpc8569mds-pib";
+ reg = <4 0 0x8000>;
+ };
+
+ pib@5,0 {
+ compatible = "fsl,mpc8569mds-pib";
+ reg = <5 0 0x8000>;
+ };
+ };
+
+ soc@e0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "fsl,mpc8569-immr", "simple-bus";
+ ranges = <0x0 0xe0000000 0x100000>;
+ bus-frequency = <0>;
+
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <10>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8569-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ memory-controller@2000 {
+ compatible = "fsl,mpc8569-memory-controller";
+ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <18 2>;
+ };
+
+ i2c@3000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+ reg = <0x3000 0x100>;
+ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+
+ rtc@68 {
+ compatible = "dallas,ds1374";
+ reg = <0x68>;
+ };
+ };
+
+ i2c@3100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <1>;
+ compatible = "fsl-i2c";
+ reg = <0x3100 0x100>;
+ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+
+ serial0: serial@4500 {
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x4500 0x100>;
+ clock-frequency = <0>;
+ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ serial1: serial@4600 {
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x4600 0x100>;
+ clock-frequency = <0>;
+ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ L2: l2-cache-controller@20000 {
+ compatible = "fsl,mpc8569-l2-cache-controller";
+ reg = <0x20000 0x1000>;
+ cache-line-size = <32>; // 32 bytes
+ cache-size = <0x80000>; // L2, 512K
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ };
+
+ dma@21300 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8569-dma", "fsl,eloplus-dma";
+ reg = <0x21300 0x4>;
+ ranges = <0x0 0x21100 0x200>;
+ cell-index = <0>;
+ dma-channel@0 {
+ compatible = "fsl,mpc8569-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x0 0x80>;
+ cell-index = <0>;
+ interrupt-parent = <&mpic>;
+ interrupts = <20 2>;
+ };
+ dma-channel@80 {
+ compatible = "fsl,mpc8569-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x80 0x80>;
+ cell-index = <1>;
+ interrupt-parent = <&mpic>;
+ interrupts = <21 2>;
+ };
+ dma-channel@100 {
+ compatible = "fsl,mpc8569-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x100 0x80>;
+ cell-index = <2>;
+ interrupt-parent = <&mpic>;
+ interrupts = <22 2>;
+ };
+ dma-channel@180 {
+ compatible = "fsl,mpc8569-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x180 0x80>;
+ cell-index = <3>;
+ interrupt-parent = <&mpic>;
+ interrupts = <23 2>;
+ };
+ };
+
+ sdhci@2e000 {
+ compatible = "fsl,mpc8569-esdhc", "fsl,esdhc";
+ reg = <0x2e000 0x1000>;
+ interrupts = <72 0x8>;
+ interrupt-parent = <&mpic>;
+ /* Filled in by U-Boot */
+ clock-frequency = <0>;
+ status = "disabled";
+ };
+
+ crypto@30000 {
+ compatible = "fsl,sec3.1", "fsl,sec3.0", "fsl,sec2.4",
+ "fsl,sec2.2", "fsl,sec2.1", "fsl,sec2.0";
+ reg = <0x30000 0x10000>;
+ interrupts = <45 2 58 2>;
+ interrupt-parent = <&mpic>;
+ fsl,num-channels = <4>;
+ fsl,channel-fifo-len = <24>;
+ fsl,exec-units-mask = <0xbfe>;
+ fsl,descriptor-types-mask = <0x3ab0ebf>;
+ };
+
+ mpic: pic@40000 {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ reg = <0x40000 0x40000>;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ };
+
+ global-utilities@e0000 {
+ compatible = "fsl,mpc8569-guts";
+ reg = <0xe0000 0x1000>;
+ fsl,has-rstcr;
+ };
+
+ par_io@e0100 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xe0100 0x100>;
+ ranges = <0x0 0xe0100 0x100>;
+ device_type = "par_io";
+ num-ports = <7>;
+
+ qe_pio_e: gpio-controller@80 {
+ #gpio-cells = <2>;
+ compatible = "fsl,mpc8569-qe-pario-bank",
+ "fsl,mpc8323-qe-pario-bank";
+ reg = <0x80 0x18>;
+ gpio-controller;
+ };
+
+ pio1: ucc_pin@01 {
+ pio-map = <
+ /* port pin dir open_drain assignment has_irq */
+ 0x2 0x1f 0x1 0x0 0x1 0x0 /* QE_MUX_MDC */
+ 0x2 0x1e 0x3 0x0 0x2 0x0 /* QE_MUX_MDIO */
+ 0x2 0x0b 0x2 0x0 0x1 0x0 /* CLK12*/
+ 0x0 0x0 0x1 0x0 0x3 0x0 /* ENET1_TXD0_SER1_TXD0 */
+ 0x0 0x1 0x1 0x0 0x3 0x0 /* ENET1_TXD1_SER1_TXD1 */
+ 0x0 0x2 0x1 0x0 0x1 0x0 /* ENET1_TXD2_SER1_TXD2 */
+ 0x0 0x3 0x1 0x0 0x2 0x0 /* ENET1_TXD3_SER1_TXD3 */
+ 0x0 0x6 0x2 0x0 0x3 0x0 /* ENET1_RXD0_SER1_RXD0 */
+ 0x0 0x7 0x2 0x0 0x1 0x0 /* ENET1_RXD1_SER1_RXD1 */
+ 0x0 0x8 0x2 0x0 0x2 0x0 /* ENET1_RXD2_SER1_RXD2 */
+ 0x0 0x9 0x2 0x0 0x2 0x0 /* ENET1_RXD3_SER1_RXD3 */
+ 0x0 0x4 0x1 0x0 0x2 0x0 /* ENET1_TX_EN_SER1_RTS_B */
+ 0x0 0xc 0x2 0x0 0x3 0x0 /* ENET1_RX_DV_SER1_CTS_B */
+ 0x2 0x8 0x2 0x0 0x1 0x0 /* ENET1_GRXCLK */
+ 0x2 0x14 0x1 0x0 0x2 0x0>; /* ENET1_GTXCLK */
+ };
+
+ pio2: ucc_pin@02 {
+ pio-map = <
+ /* port pin dir open_drain assignment has_irq */
+ 0x2 0x1f 0x1 0x0 0x1 0x0 /* QE_MUX_MDC */
+ 0x2 0x1e 0x3 0x0 0x2 0x0 /* QE_MUX_MDIO */
+ 0x2 0x10 0x2 0x0 0x3 0x0 /* CLK17 */
+ 0x0 0xe 0x1 0x0 0x2 0x0 /* ENET2_TXD0_SER2_TXD0 */
+ 0x0 0xf 0x1 0x0 0x2 0x0 /* ENET2_TXD1_SER2_TXD1 */
+ 0x0 0x10 0x1 0x0 0x1 0x0 /* ENET2_TXD2_SER2_TXD2 */
+ 0x0 0x11 0x1 0x0 0x1 0x0 /* ENET2_TXD3_SER2_TXD3 */
+ 0x0 0x14 0x2 0x0 0x2 0x0 /* ENET2_RXD0_SER2_RXD0 */
+ 0x0 0x15 0x2 0x0 0x1 0x0 /* ENET2_RXD1_SER2_RXD1 */
+ 0x0 0x16 0x2 0x0 0x1 0x0 /* ENET2_RXD2_SER2_RXD2 */
+ 0x0 0x17 0x2 0x0 0x1 0x0 /* ENET2_RXD3_SER2_RXD3 */
+ 0x0 0x12 0x1 0x0 0x2 0x0 /* ENET2_TX_EN_SER2_RTS_B */
+ 0x0 0x1a 0x2 0x0 0x3 0x0 /* ENET2_RX_DV_SER2_CTS_B */
+ 0x2 0x3 0x2 0x0 0x1 0x0 /* ENET2_GRXCLK */
+ 0x2 0x2 0x1 0x0 0x2 0x0>; /* ENET2_GTXCLK */
+ };
+
+ pio3: ucc_pin@03 {
+ pio-map = <
+ /* port pin dir open_drain assignment has_irq */
+ 0x2 0x1f 0x1 0x0 0x1 0x0 /* QE_MUX_MDC */
+ 0x2 0x1e 0x3 0x0 0x2 0x0 /* QE_MUX_MDIO */
+ 0x2 0x0b 0x2 0x0 0x1 0x0 /* CLK12*/
+ 0x0 0x1d 0x1 0x0 0x2 0x0 /* ENET3_TXD0_SER3_TXD0 */
+ 0x0 0x1e 0x1 0x0 0x3 0x0 /* ENET3_TXD1_SER3_TXD1 */
+ 0x0 0x1f 0x1 0x0 0x2 0x0 /* ENET3_TXD2_SER3_TXD2 */
+ 0x1 0x0 0x1 0x0 0x3 0x0 /* ENET3_TXD3_SER3_TXD3 */
+ 0x1 0x3 0x2 0x0 0x3 0x0 /* ENET3_RXD0_SER3_RXD0 */
+ 0x1 0x4 0x2 0x0 0x1 0x0 /* ENET3_RXD1_SER3_RXD1 */
+ 0x1 0x5 0x2 0x0 0x2 0x0 /* ENET3_RXD2_SER3_RXD2 */
+ 0x1 0x6 0x2 0x0 0x3 0x0 /* ENET3_RXD3_SER3_RXD3 */
+ 0x1 0x1 0x1 0x0 0x1 0x0 /* ENET3_TX_EN_SER3_RTS_B */
+ 0x1 0x9 0x2 0x0 0x3 0x0 /* ENET3_RX_DV_SER3_CTS_B */
+ 0x2 0x9 0x2 0x0 0x2 0x0 /* ENET3_GRXCLK */
+ 0x2 0x19 0x1 0x0 0x2 0x0>; /* ENET3_GTXCLK */
+ };
+
+ pio4: ucc_pin@04 {
+ pio-map = <
+ /* port pin dir open_drain assignment has_irq */
+ 0x2 0x1f 0x1 0x0 0x1 0x0 /* QE_MUX_MDC */
+ 0x2 0x1e 0x3 0x0 0x2 0x0 /* QE_MUX_MDIO */
+ 0x2 0x10 0x2 0x0 0x3 0x0 /* CLK17 */
+ 0x1 0xc 0x1 0x0 0x2 0x0 /* ENET4_TXD0_SER4_TXD0 */
+ 0x1 0xd 0x1 0x0 0x2 0x0 /* ENET4_TXD1_SER4_TXD1 */
+ 0x1 0xe 0x1 0x0 0x1 0x0 /* ENET4_TXD2_SER4_TXD2 */
+ 0x1 0xf 0x1 0x0 0x2 0x0 /* ENET4_TXD3_SER4_TXD3 */
+ 0x1 0x12 0x2 0x0 0x2 0x0 /* ENET4_RXD0_SER4_RXD0 */
+ 0x1 0x13 0x2 0x0 0x1 0x0 /* ENET4_RXD1_SER4_RXD1 */
+ 0x1 0x14 0x2 0x0 0x1 0x0 /* ENET4_RXD2_SER4_RXD2 */
+ 0x1 0x15 0x2 0x0 0x2 0x0 /* ENET4_RXD3_SER4_RXD3 */
+ 0x1 0x10 0x1 0x0 0x2 0x0 /* ENET4_TX_EN_SER4_RTS_B */
+ 0x1 0x18 0x2 0x0 0x3 0x0 /* ENET4_RX_DV_SER4_CTS_B */
+ 0x2 0x11 0x2 0x0 0x2 0x0 /* ENET4_GRXCLK */
+ 0x2 0x18 0x1 0x0 0x2 0x0>; /* ENET4_GTXCLK */
+ };
+ };
+ };
+
+ qe@e0080000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "qe";
+ compatible = "fsl,qe";
+ ranges = <0x0 0xe0080000 0x40000>;
+ reg = <0xe0080000 0x480>;
+ brg-frequency = <0>;
+ bus-frequency = <0>;
+ fsl,qe-num-riscs = <4>;
+ fsl,qe-num-snums = <46>;
+
+ qeic: interrupt-controller@80 {
+ interrupt-controller;
+ compatible = "fsl,qe-ic";
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ reg = <0x80 0x80>;
+ interrupts = <46 2 46 2>; //high:30 low:30
+ interrupt-parent = <&mpic>;
+ };
+
+ spi@4c0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc8569-qe-spi", "fsl,spi";
+ reg = <0x4c0 0x40>;
+ cell-index = <0>;
+ interrupts = <2>;
+ interrupt-parent = <&qeic>;
+ gpios = <&qe_pio_e 30 0>;
+ mode = "cpu-qe";
+
+ serial-flash@0 {
+ compatible = "stm,m25p40";
+ reg = <0>;
+ spi-max-frequency = <25000000>;
+ };
+ };
+
+ spi@500 {
+ cell-index = <1>;
+ compatible = "fsl,spi";
+ reg = <0x500 0x40>;
+ interrupts = <1>;
+ interrupt-parent = <&qeic>;
+ mode = "cpu";
+ };
+
+ enet0: ucc@2000 {
+ device_type = "network";
+ compatible = "ucc_geth";
+ cell-index = <1>;
+ reg = <0x2000 0x200>;
+ interrupts = <32>;
+ interrupt-parent = <&qeic>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ rx-clock-name = "none";
+ tx-clock-name = "clk12";
+ pio-handle = <&pio1>;
+ phy-handle = <&qe_phy0>;
+ phy-connection-type = "rgmii-id";
+ };
+
+ mdio@2120 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x2120 0x18>;
+ compatible = "fsl,ucc-mdio";
+
+ qe_phy0: ethernet-phy@07 {
+ interrupt-parent = <&mpic>;
+ interrupts = <1 1>;
+ reg = <0x7>;
+ device_type = "ethernet-phy";
+ };
+ qe_phy1: ethernet-phy@01 {
+ interrupt-parent = <&mpic>;
+ interrupts = <2 1>;
+ reg = <0x1>;
+ device_type = "ethernet-phy";
+ };
+ qe_phy2: ethernet-phy@02 {
+ interrupt-parent = <&mpic>;
+ interrupts = <3 1>;
+ reg = <0x2>;
+ device_type = "ethernet-phy";
+ };
+ qe_phy3: ethernet-phy@03 {
+ interrupt-parent = <&mpic>;
+ interrupts = <4 1>;
+ reg = <0x3>;
+ device_type = "ethernet-phy";
+ };
+ };
+
+ enet2: ucc@2200 {
+ device_type = "network";
+ compatible = "ucc_geth";
+ cell-index = <3>;
+ reg = <0x2200 0x200>;
+ interrupts = <34>;
+ interrupt-parent = <&qeic>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ rx-clock-name = "none";
+ tx-clock-name = "clk12";
+ pio-handle = <&pio3>;
+ phy-handle = <&qe_phy2>;
+ phy-connection-type = "rgmii-id";
+ };
+
+ enet1: ucc@3000 {
+ device_type = "network";
+ compatible = "ucc_geth";
+ cell-index = <2>;
+ reg = <0x3000 0x200>;
+ interrupts = <33>;
+ interrupt-parent = <&qeic>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ rx-clock-name = "none";
+ tx-clock-name = "clk17";
+ pio-handle = <&pio2>;
+ phy-handle = <&qe_phy1>;
+ phy-connection-type = "rgmii-id";
+ };
+
+ enet3: ucc@3200 {
+ device_type = "network";
+ compatible = "ucc_geth";
+ cell-index = <4>;
+ reg = <0x3200 0x200>;
+ interrupts = <35>;
+ interrupt-parent = <&qeic>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ rx-clock-name = "none";
+ tx-clock-name = "clk17";
+ pio-handle = <&pio4>;
+ phy-handle = <&qe_phy3>;
+ phy-connection-type = "rgmii-id";
+ };
+
+ muram@10000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,qe-muram", "fsl,cpm-muram";
+ ranges = <0x0 0x10000 0x20000>;
+
+ data-only@0 {
+ compatible = "fsl,qe-muram-data",
+ "fsl,cpm-muram-data";
+ reg = <0x0 0x20000>;
+ };
+ };
+
+ };
+
+ /* PCI Express */
+ pci1: pcie@e000a000 {
+ compatible = "fsl,mpc8548-pcie";
+ device_type = "pci";
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ reg = <0xe000a000 0x1000>;
+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x0 (PEX) */
+ 00000 0x0 0x0 0x1 &mpic 0x0 0x1
+ 00000 0x0 0x0 0x2 &mpic 0x1 0x1
+ 00000 0x0 0x0 0x3 &mpic 0x2 0x1
+ 00000 0x0 0x0 0x4 &mpic 0x3 0x1>;
+
+ interrupt-parent = <&mpic>;
+ interrupts = <26 2>;
+ bus-range = <0 255>;
+ ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000
+ 0x1000000 0x0 0x00000000 0xe2800000 0x0 0x00800000>;
+ clock-frequency = <33333333>;
+ pcie@0 {
+ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ ranges = <0x2000000 0x0 0xa0000000
+ 0x2000000 0x0 0xa0000000
+ 0x0 0x10000000
+
+ 0x1000000 0x0 0x0
+ 0x1000000 0x0 0x0
+ 0x0 0x800000>;
+ };
+ };
+
+ rio0: rapidio@e00c00000 {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ compatible = "fsl,mpc8569-rapidio", "fsl,rapidio-delta";
+ reg = <0xe00c0000 0x20000>;
+ ranges = <0x0 0x0 0xc0000000 0x0 0x20000000>;
+ interrupts = <48 2 /* error */
+ 49 2 /* bell_outb */
+ 50 2 /* bell_inb */
+ 53 2 /* msg1_tx */
+ 54 2 /* msg1_rx */
+ 55 2 /* msg2_tx */
+ 56 2 /* msg2_rx */>;
+ interrupt-parent = <&mpic>;
+ };
+};
diff --git a/arch/powerpc/boot/dts/mpc8572ds.dts b/arch/powerpc/boot/dts/mpc8572ds.dts
index 6e79a4169088..cafc1285c140 100644
--- a/arch/powerpc/boot/dts/mpc8572ds.dts
+++ b/arch/powerpc/boot/dts/mpc8572ds.dts
@@ -182,9 +182,21 @@
device_type = "soc";
compatible = "simple-bus";
ranges = <0x0 0 0xffe00000 0x100000>;
- reg = <0 0xffe00000 0 0x1000>; // CCSRBAR & soc regs, remove once parse code for immrbase fixed
bus-frequency = <0>; // Filled out by uboot.
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <12>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8572-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,mpc8572-memory-controller";
reg = <0x2000 0x1000>;
@@ -514,7 +526,6 @@
};
pci0: pcie@ffe08000 {
- cell-index = <0>;
compatible = "fsl,mpc8548-pcie";
device_type = "pci";
#interrupt-cells = <1>;
@@ -724,7 +735,6 @@
};
pci1: pcie@ffe09000 {
- cell-index = <1>;
compatible = "fsl,mpc8548-pcie";
device_type = "pci";
#interrupt-cells = <1>;
@@ -761,7 +771,6 @@
};
pci2: pcie@ffe0a000 {
- cell-index = <2>;
compatible = "fsl,mpc8548-pcie";
device_type = "pci";
#interrupt-cells = <1>;
diff --git a/arch/powerpc/boot/dts/mpc8572ds_36b.dts b/arch/powerpc/boot/dts/mpc8572ds_36b.dts
index dbd81a764742..11979659c577 100644
--- a/arch/powerpc/boot/dts/mpc8572ds_36b.dts
+++ b/arch/powerpc/boot/dts/mpc8572ds_36b.dts
@@ -182,9 +182,21 @@
device_type = "soc";
compatible = "simple-bus";
ranges = <0x0 0xf 0xffe00000 0x100000>;
- reg = <0xf 0xffe00000 0 0x1000>; // CCSRBAR & soc regs, remove once parse code for immrbase fixed
bus-frequency = <0>; // Filled out by uboot.
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <12>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8572-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,mpc8572-memory-controller";
reg = <0x2000 0x1000>;
@@ -514,7 +526,6 @@
};
pci0: pcie@fffe08000 {
- cell-index = <0>;
compatible = "fsl,mpc8548-pcie";
device_type = "pci";
#interrupt-cells = <1>;
@@ -724,7 +735,6 @@
};
pci1: pcie@fffe09000 {
- cell-index = <1>;
compatible = "fsl,mpc8548-pcie";
device_type = "pci";
#interrupt-cells = <1>;
@@ -761,7 +771,6 @@
};
pci2: pcie@fffe0a000 {
- cell-index = <2>;
compatible = "fsl,mpc8548-pcie";
device_type = "pci";
#interrupt-cells = <1>;
diff --git a/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts b/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts
index 2bc0c7189653..5bd1011fde96 100644
--- a/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts
+++ b/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts
@@ -59,9 +59,21 @@
device_type = "soc";
compatible = "simple-bus";
ranges = <0x0 0xffe00000 0x100000>;
- reg = <0xffe00000 0x1000>; // CCSRBAR & soc regs, remove once parse code for immrbase fixed
bus-frequency = <0>; // Filled out by uboot.
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <12>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8572-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,mpc8572-memory-controller";
reg = <0x2000 0x1000>;
@@ -238,7 +250,6 @@
};
pci0: pcie@ffe08000 {
- cell-index = <0>;
compatible = "fsl,mpc8548-pcie";
device_type = "pci";
#interrupt-cells = <1>;
@@ -448,7 +459,6 @@
};
pci1: pcie@ffe09000 {
- cell-index = <1>;
compatible = "fsl,mpc8548-pcie";
device_type = "pci";
#interrupt-cells = <1>;
diff --git a/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts b/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts
index 159cb3a875f0..0efc3456e297 100644
--- a/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts
+++ b/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts
@@ -58,7 +58,6 @@
device_type = "soc";
compatible = "simple-bus";
ranges = <0x0 0xffe00000 0x100000>;
- reg = <0xffe00000 0x1000>; // CCSRBAR & soc regs, remove once parse code for immrbase fixed
bus-frequency = <0>; // Filled out by uboot.
L2: l2-cache-controller@20000 {
@@ -196,7 +195,6 @@
};
pci2: pcie@ffe0a000 {
- cell-index = <2>;
compatible = "fsl,mpc8548-pcie";
device_type = "pci";
#interrupt-cells = <1>;
diff --git a/arch/powerpc/boot/dts/mpc8610_hpcd.dts b/arch/powerpc/boot/dts/mpc8610_hpcd.dts
index 1bd3ebe11437..cfc2c60d1f5f 100644
--- a/arch/powerpc/boot/dts/mpc8610_hpcd.dts
+++ b/arch/powerpc/boot/dts/mpc8610_hpcd.dts
@@ -112,9 +112,21 @@
device_type = "soc";
compatible = "fsl,mpc8610-immr", "simple-bus";
ranges = <0x0 0xe0000000 0x00100000>;
- reg = <0xe0000000 0x1000>;
bus-frequency = <0>;
+ mcm-law@0 {
+ compatible = "fsl,mcm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <10>;
+ };
+
+ mcm@1000 {
+ compatible = "fsl,mpc8610-mcm", "fsl,mcm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
i2c@3000 {
#address-cells = <1>;
#size-cells = <0>;
@@ -316,7 +328,6 @@
};
pci0: pci@e0008000 {
- cell-index = <0>;
compatible = "fsl,mpc8610-pci";
device_type = "pci";
#interrupt-cells = <1>;
@@ -346,7 +357,6 @@
};
pci1: pcie@e000a000 {
- cell-index = <1>;
compatible = "fsl,mpc8641-pcie";
device_type = "pci";
#interrupt-cells = <1>;
diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
index d72beb192460..848320e4d3c4 100644
--- a/arch/powerpc/boot/dts/mpc8641_hpcn.dts
+++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
@@ -114,9 +114,21 @@
device_type = "soc";
compatible = "simple-bus";
ranges = <0x00000000 0xffe00000 0x00100000>;
- reg = <0xffe00000 0x00001000>; // CCSRBAR
bus-frequency = <0>;
+ mcm-law@0 {
+ compatible = "fsl,mcm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <10>;
+ };
+
+ mcm@1000 {
+ compatible = "fsl,mpc8641-mcm", "fsl,mcm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
i2c@3000 {
#address-cells = <1>;
#size-cells = <0>;
@@ -357,7 +369,6 @@
};
pci0: pcie@ffe08000 {
- cell-index = <0>;
compatible = "fsl,mpc8641-pcie";
device_type = "pci";
#interrupt-cells = <1>;
@@ -566,7 +577,6 @@
};
pci1: pcie@ffe09000 {
- cell-index = <1>;
compatible = "fsl,mpc8641-pcie";
device_type = "pci";
#interrupt-cells = <1>;
diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn_36b.dts b/arch/powerpc/boot/dts/mpc8641_hpcn_36b.dts
new file mode 100644
index 000000000000..65893b9f963d
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8641_hpcn_36b.dts
@@ -0,0 +1,609 @@
+/*
+ * MPC8641 HPCN Device Tree Source
+ *
+ * Copyright 2008-2009 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.
+ */
+
+/dts-v1/;
+
+/ {
+ model = "MPC8641HPCN";
+ compatible = "fsl,mpc8641hpcn";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ aliases {
+ ethernet0 = &enet0;
+ ethernet1 = &enet1;
+ ethernet2 = &enet2;
+ ethernet3 = &enet3;
+ serial0 = &serial0;
+ serial1 = &serial1;
+ pci0 = &pci0;
+ pci1 = &pci1;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PowerPC,8641@0 {
+ device_type = "cpu";
+ reg = <0>;
+ d-cache-line-size = <32>; // 32 bytes
+ i-cache-line-size = <32>; // 32 bytes
+ d-cache-size = <32768>; // L1, 32K
+ i-cache-size = <32768>; // L1, 32K
+ timebase-frequency = <0>; // 33 MHz, from uboot
+ bus-frequency = <0>; // From uboot
+ clock-frequency = <0>; // From uboot
+ };
+ PowerPC,8641@1 {
+ device_type = "cpu";
+ reg = <1>;
+ d-cache-line-size = <32>; // 32 bytes
+ i-cache-line-size = <32>; // 32 bytes
+ d-cache-size = <32768>; // L1, 32K
+ i-cache-size = <32768>; // L1, 32K
+ timebase-frequency = <0>; // 33 MHz, from uboot
+ bus-frequency = <0>; // From uboot
+ clock-frequency = <0>; // From uboot
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x00000000 0x0 0x40000000>; // 1G at 0x0
+ };
+
+ localbus@fffe05000 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8641-localbus", "simple-bus";
+ reg = <0x0f 0xffe05000 0x0 0x1000>;
+ interrupts = <19 2>;
+ interrupt-parent = <&mpic>;
+
+ ranges = <0 0 0xf 0xef800000 0x00800000
+ 2 0 0xf 0xffdf8000 0x00008000
+ 3 0 0xf 0xffdf0000 0x00008000>;
+
+ flash@0,0 {
+ compatible = "cfi-flash";
+ reg = <0 0 0x00800000>;
+ bank-width = <2>;
+ device-width = <2>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ partition@0 {
+ label = "kernel";
+ reg = <0x00000000 0x00300000>;
+ };
+ partition@300000 {
+ label = "firmware b";
+ reg = <0x00300000 0x00100000>;
+ read-only;
+ };
+ partition@400000 {
+ label = "fs";
+ reg = <0x00400000 0x00300000>;
+ };
+ partition@700000 {
+ label = "firmware a";
+ reg = <0x00700000 0x00100000>;
+ read-only;
+ };
+ };
+ };
+
+ soc8641@fffe00000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "simple-bus";
+ ranges = <0x00000000 0x0f 0xffe00000 0x00100000>;
+ bus-frequency = <0>;
+
+ mcm-law@0 {
+ compatible = "fsl,mcm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <10>;
+ };
+
+ mcm@1000 {
+ compatible = "fsl,mpc8641-mcm", "fsl,mcm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ i2c@3000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+ reg = <0x3000 0x100>;
+ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+
+ i2c@3100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <1>;
+ compatible = "fsl-i2c";
+ reg = <0x3100 0x100>;
+ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+
+ dma@21300 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8641-dma", "fsl,eloplus-dma";
+ reg = <0x21300 0x4>;
+ ranges = <0x0 0x21100 0x200>;
+ cell-index = <0>;
+ dma-channel@0 {
+ compatible = "fsl,mpc8641-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x0 0x80>;
+ cell-index = <0>;
+ interrupt-parent = <&mpic>;
+ interrupts = <20 2>;
+ };
+ dma-channel@80 {
+ compatible = "fsl,mpc8641-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x80 0x80>;
+ cell-index = <1>;
+ interrupt-parent = <&mpic>;
+ interrupts = <21 2>;
+ };
+ dma-channel@100 {
+ compatible = "fsl,mpc8641-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x100 0x80>;
+ cell-index = <2>;
+ interrupt-parent = <&mpic>;
+ interrupts = <22 2>;
+ };
+ dma-channel@180 {
+ compatible = "fsl,mpc8641-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x180 0x80>;
+ cell-index = <3>;
+ interrupt-parent = <&mpic>;
+ interrupts = <23 2>;
+ };
+ };
+
+ enet0: ethernet@24000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ cell-index = <0>;
+ device_type = "network";
+ model = "TSEC";
+ compatible = "gianfar";
+ reg = <0x24000 0x1000>;
+ ranges = <0x0 0x24000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <29 2 30 2 34 2>;
+ interrupt-parent = <&mpic>;
+ tbi-handle = <&tbi0>;
+ phy-handle = <&phy0>;
+ phy-connection-type = "rgmii-id";
+
+ mdio@520 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,gianfar-mdio";
+ reg = <0x520 0x20>;
+
+ phy0: ethernet-phy@0 {
+ interrupt-parent = <&mpic>;
+ interrupts = <10 1>;
+ reg = <0>;
+ device_type = "ethernet-phy";
+ };
+ phy1: ethernet-phy@1 {
+ interrupt-parent = <&mpic>;
+ interrupts = <10 1>;
+ reg = <1>;
+ device_type = "ethernet-phy";
+ };
+ phy2: ethernet-phy@2 {
+ interrupt-parent = <&mpic>;
+ interrupts = <10 1>;
+ reg = <2>;
+ device_type = "ethernet-phy";
+ };
+ phy3: ethernet-phy@3 {
+ interrupt-parent = <&mpic>;
+ interrupts = <10 1>;
+ reg = <3>;
+ device_type = "ethernet-phy";
+ };
+ tbi0: tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+ };
+
+ enet1: ethernet@25000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ cell-index = <1>;
+ device_type = "network";
+ model = "TSEC";
+ compatible = "gianfar";
+ reg = <0x25000 0x1000>;
+ ranges = <0x0 0x25000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <35 2 36 2 40 2>;
+ interrupt-parent = <&mpic>;
+ tbi-handle = <&tbi1>;
+ phy-handle = <&phy1>;
+ phy-connection-type = "rgmii-id";
+
+ mdio@520 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,gianfar-tbi";
+ reg = <0x520 0x20>;
+
+ tbi1: tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+ };
+
+ enet2: ethernet@26000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ cell-index = <2>;
+ device_type = "network";
+ model = "TSEC";
+ compatible = "gianfar";
+ reg = <0x26000 0x1000>;
+ ranges = <0x0 0x26000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <31 2 32 2 33 2>;
+ interrupt-parent = <&mpic>;
+ tbi-handle = <&tbi2>;
+ phy-handle = <&phy2>;
+ phy-connection-type = "rgmii-id";
+
+ mdio@520 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,gianfar-tbi";
+ reg = <0x520 0x20>;
+
+ tbi2: tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+ };
+
+ enet3: ethernet@27000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ cell-index = <3>;
+ device_type = "network";
+ model = "TSEC";
+ compatible = "gianfar";
+ reg = <0x27000 0x1000>;
+ ranges = <0x0 0x27000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <37 2 38 2 39 2>;
+ interrupt-parent = <&mpic>;
+ tbi-handle = <&tbi3>;
+ phy-handle = <&phy3>;
+ phy-connection-type = "rgmii-id";
+
+ mdio@520 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,gianfar-tbi";
+ reg = <0x520 0x20>;
+
+ tbi3: tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+ };
+
+ serial0: serial@4500 {
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x4500 0x100>;
+ clock-frequency = <0>;
+ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ serial1: serial@4600 {
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x4600 0x100>;
+ clock-frequency = <0>;
+ interrupts = <28 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ mpic: pic@40000 {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ reg = <0x40000 0x40000>;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ };
+
+ global-utilities@e0000 {
+ compatible = "fsl,mpc8641-guts";
+ reg = <0xe0000 0x1000>;
+ fsl,has-rstcr;
+ };
+ };
+
+ pci0: pcie@fffe08000 {
+ cell-index = <0>;
+ compatible = "fsl,mpc8641-pcie";
+ device_type = "pci";
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ reg = <0x0f 0xffe08000 0x0 0x1000>;
+ bus-range = <0x0 0xff>;
+ ranges = <0x02000000 0x0 0xc0000000 0x0c 0x00000000 0x0 0x20000000
+ 0x01000000 0x0 0x00000000 0x0f 0xffc00000 0x0 0x00010000>;
+ clock-frequency = <33333333>;
+ interrupt-parent = <&mpic>;
+ interrupts = <24 2>;
+ interrupt-map-mask = <0xff00 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x11 func 0 - PCI slot 1 */
+ 0x8800 0 0 1 &mpic 2 1
+ 0x8800 0 0 2 &mpic 3 1
+ 0x8800 0 0 3 &mpic 4 1
+ 0x8800 0 0 4 &mpic 1 1
+
+ /* IDSEL 0x11 func 1 - PCI slot 1 */
+ 0x8900 0 0 1 &mpic 2 1
+ 0x8900 0 0 2 &mpic 3 1
+ 0x8900 0 0 3 &mpic 4 1
+ 0x8900 0 0 4 &mpic 1 1
+
+ /* IDSEL 0x11 func 2 - PCI slot 1 */
+ 0x8a00 0 0 1 &mpic 2 1
+ 0x8a00 0 0 2 &mpic 3 1
+ 0x8a00 0 0 3 &mpic 4 1
+ 0x8a00 0 0 4 &mpic 1 1
+
+ /* IDSEL 0x11 func 3 - PCI slot 1 */
+ 0x8b00 0 0 1 &mpic 2 1
+ 0x8b00 0 0 2 &mpic 3 1
+ 0x8b00 0 0 3 &mpic 4 1
+ 0x8b00 0 0 4 &mpic 1 1
+
+ /* IDSEL 0x11 func 4 - PCI slot 1 */
+ 0x8c00 0 0 1 &mpic 2 1
+ 0x8c00 0 0 2 &mpic 3 1
+ 0x8c00 0 0 3 &mpic 4 1
+ 0x8c00 0 0 4 &mpic 1 1
+
+ /* IDSEL 0x11 func 5 - PCI slot 1 */
+ 0x8d00 0 0 1 &mpic 2 1
+ 0x8d00 0 0 2 &mpic 3 1
+ 0x8d00 0 0 3 &mpic 4 1
+ 0x8d00 0 0 4 &mpic 1 1
+
+ /* IDSEL 0x11 func 6 - PCI slot 1 */
+ 0x8e00 0 0 1 &mpic 2 1
+ 0x8e00 0 0 2 &mpic 3 1
+ 0x8e00 0 0 3 &mpic 4 1
+ 0x8e00 0 0 4 &mpic 1 1
+
+ /* IDSEL 0x11 func 7 - PCI slot 1 */
+ 0x8f00 0 0 1 &mpic 2 1
+ 0x8f00 0 0 2 &mpic 3 1
+ 0x8f00 0 0 3 &mpic 4 1
+ 0x8f00 0 0 4 &mpic 1 1
+
+ /* IDSEL 0x12 func 0 - PCI slot 2 */
+ 0x9000 0 0 1 &mpic 3 1
+ 0x9000 0 0 2 &mpic 4 1
+ 0x9000 0 0 3 &mpic 1 1
+ 0x9000 0 0 4 &mpic 2 1
+
+ /* IDSEL 0x12 func 1 - PCI slot 2 */
+ 0x9100 0 0 1 &mpic 3 1
+ 0x9100 0 0 2 &mpic 4 1
+ 0x9100 0 0 3 &mpic 1 1
+ 0x9100 0 0 4 &mpic 2 1
+
+ /* IDSEL 0x12 func 2 - PCI slot 2 */
+ 0x9200 0 0 1 &mpic 3 1
+ 0x9200 0 0 2 &mpic 4 1
+ 0x9200 0 0 3 &mpic 1 1
+ 0x9200 0 0 4 &mpic 2 1
+
+ /* IDSEL 0x12 func 3 - PCI slot 2 */
+ 0x9300 0 0 1 &mpic 3 1
+ 0x9300 0 0 2 &mpic 4 1
+ 0x9300 0 0 3 &mpic 1 1
+ 0x9300 0 0 4 &mpic 2 1
+
+ /* IDSEL 0x12 func 4 - PCI slot 2 */
+ 0x9400 0 0 1 &mpic 3 1
+ 0x9400 0 0 2 &mpic 4 1
+ 0x9400 0 0 3 &mpic 1 1
+ 0x9400 0 0 4 &mpic 2 1
+
+ /* IDSEL 0x12 func 5 - PCI slot 2 */
+ 0x9500 0 0 1 &mpic 3 1
+ 0x9500 0 0 2 &mpic 4 1
+ 0x9500 0 0 3 &mpic 1 1
+ 0x9500 0 0 4 &mpic 2 1
+
+ /* IDSEL 0x12 func 6 - PCI slot 2 */
+ 0x9600 0 0 1 &mpic 3 1
+ 0x9600 0 0 2 &mpic 4 1
+ 0x9600 0 0 3 &mpic 1 1
+ 0x9600 0 0 4 &mpic 2 1
+
+ /* IDSEL 0x12 func 7 - PCI slot 2 */
+ 0x9700 0 0 1 &mpic 3 1
+ 0x9700 0 0 2 &mpic 4 1
+ 0x9700 0 0 3 &mpic 1 1
+ 0x9700 0 0 4 &mpic 2 1
+
+ // IDSEL 0x1c USB
+ 0xe000 0 0 1 &i8259 12 2
+ 0xe100 0 0 2 &i8259 9 2
+ 0xe200 0 0 3 &i8259 10 2
+ 0xe300 0 0 4 &i8259 11 2
+
+ // IDSEL 0x1d Audio
+ 0xe800 0 0 1 &i8259 6 2
+
+ // IDSEL 0x1e Legacy
+ 0xf000 0 0 1 &i8259 7 2
+ 0xf100 0 0 1 &i8259 7 2
+
+ // IDSEL 0x1f IDE/SATA
+ 0xf800 0 0 1 &i8259 14 2
+ 0xf900 0 0 1 &i8259 5 2
+ >;
+
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ ranges = <0x02000000 0x0 0xc0000000
+ 0x02000000 0x0 0xc0000000
+ 0x0 0x20000000
+
+ 0x01000000 0x0 0x00000000
+ 0x01000000 0x0 0x00000000
+ 0x0 0x00010000>;
+ uli1575@0 {
+ reg = <0 0 0 0 0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ ranges = <0x02000000 0x0 0xc0000000
+ 0x02000000 0x0 0xc0000000
+ 0x0 0x20000000
+ 0x01000000 0x0 0x00000000
+ 0x01000000 0x0 0x00000000
+ 0x0 0x00010000>;
+ isa@1e {
+ device_type = "isa";
+ #interrupt-cells = <2>;
+ #size-cells = <1>;
+ #address-cells = <2>;
+ reg = <0xf000 0 0 0 0>;
+ ranges = <1 0 0x01000000 0 0
+ 0x00001000>;
+ interrupt-parent = <&i8259>;
+
+ i8259: interrupt-controller@20 {
+ reg = <1 0x20 2
+ 1 0xa0 2
+ 1 0x4d0 2>;
+ interrupt-controller;
+ device_type = "interrupt-controller";
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ compatible = "chrp,iic";
+ interrupts = <9 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ i8042@60 {
+ #size-cells = <0>;
+ #address-cells = <1>;
+ reg = <1 0x60 1 1 0x64 1>;
+ interrupts = <1 3 12 3>;
+ interrupt-parent =
+ <&i8259>;
+
+ keyboard@0 {
+ reg = <0>;
+ compatible = "pnpPNP,303";
+ };
+
+ mouse@1 {
+ reg = <1>;
+ compatible = "pnpPNP,f03";
+ };
+ };
+
+ rtc@70 {
+ compatible =
+ "pnpPNP,b00";
+ reg = <1 0x70 2>;
+ };
+
+ gpio@400 {
+ reg = <1 0x400 0x80>;
+ };
+ };
+ };
+ };
+
+ };
+
+ pci1: pcie@fffe09000 {
+ cell-index = <1>;
+ compatible = "fsl,mpc8641-pcie";
+ device_type = "pci";
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ reg = <0x0f 0xffe09000 0x0 0x1000>;
+ bus-range = <0x0 0xff>;
+ ranges = <0x02000000 0x0 0xc0000000 0x0c 0x20000000 0x0 0x20000000
+ 0x01000000 0x0 0x00000000 0x0f 0xffc10000 0x0 0x00010000>;
+ clock-frequency = <33333333>;
+ interrupt-parent = <&mpic>;
+ interrupts = <25 2>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0x0000 0 0 1 &mpic 4 1
+ 0x0000 0 0 2 &mpic 5 1
+ 0x0000 0 0 3 &mpic 6 1
+ 0x0000 0 0 4 &mpic 7 1
+ >;
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ ranges = <0x02000000 0x0 0xc0000000
+ 0x02000000 0x0 0xc0000000
+ 0x0 0x20000000
+
+ 0x01000000 0x0 0x00000000
+ 0x01000000 0x0 0x00000000
+ 0x0 0x00010000>;
+ };
+ };
+};
diff --git a/arch/powerpc/boot/dts/sbc8349.dts b/arch/powerpc/boot/dts/sbc8349.dts
index a36dbbc48694..5fb6f6684b0e 100644
--- a/arch/powerpc/boot/dts/sbc8349.dts
+++ b/arch/powerpc/boot/dts/sbc8349.dts
@@ -278,7 +278,6 @@
};
pci0: pci@e0008500 {
- cell-index = <1>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
diff --git a/arch/powerpc/boot/dts/sbc8548.dts b/arch/powerpc/boot/dts/sbc8548.dts
index b1f1416ac998..9eefe00ed253 100644
--- a/arch/powerpc/boot/dts/sbc8548.dts
+++ b/arch/powerpc/boot/dts/sbc8548.dts
@@ -151,10 +151,22 @@
#size-cells = <1>;
device_type = "soc";
ranges = <0x00000000 0xe0000000 0x00100000>;
- reg = <0xe0000000 0x00001000>; // CCSRBAR
bus-frequency = <0>;
compatible = "simple-bus";
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <10>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8548-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,mpc8548-memory-controller";
reg = <0x2000 0x1000>;
@@ -350,7 +362,6 @@
};
pci0: pci@e0008000 {
- cell-index = <0>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
/* IDSEL 0x01 (PCI-X slot) @66MHz */
@@ -380,7 +391,6 @@
};
pci2: pcie@e000a000 {
- cell-index = <2>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
diff --git a/arch/powerpc/boot/dts/sbc8560.dts b/arch/powerpc/boot/dts/sbc8560.dts
index c4564b81e473..239d57a55cf4 100644
--- a/arch/powerpc/boot/dts/sbc8560.dts
+++ b/arch/powerpc/boot/dts/sbc8560.dts
@@ -57,9 +57,21 @@
#size-cells = <1>;
device_type = "soc";
ranges = <0x0 0xff700000 0x00100000>;
- reg = <0xff700000 0x00100000>;
clock-frequency = <0>;
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <8>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8560-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,mpc8560-memory-controller";
reg = <0x2000 0x1000>;
@@ -296,7 +308,6 @@
};
pci0: pci@ff708000 {
- cell-index = <0>;
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
diff --git a/arch/powerpc/boot/dts/sbc8641d.dts b/arch/powerpc/boot/dts/sbc8641d.dts
index e3e914e78caa..ee5538feb455 100644
--- a/arch/powerpc/boot/dts/sbc8641d.dts
+++ b/arch/powerpc/boot/dts/sbc8641d.dts
@@ -126,9 +126,21 @@
device_type = "soc";
compatible = "simple-bus";
ranges = <0x00000000 0xf8000000 0x00100000>;
- reg = <0xf8000000 0x00001000>; // CCSRBAR
bus-frequency = <0>;
+ mcm-law@0 {
+ compatible = "fsl,mcm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <10>;
+ };
+
+ mcm@1000 {
+ compatible = "fsl,mpc8641-mcm", "fsl,mcm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
i2c@3000 {
#address-cells = <1>;
#size-cells = <0>;
@@ -371,7 +383,6 @@
};
pci0: pcie@f8008000 {
- cell-index = <0>;
compatible = "fsl,mpc8641-pcie";
device_type = "pci";
#interrupt-cells = <1>;
@@ -410,7 +421,6 @@
};
pci1: pcie@f8009000 {
- cell-index = <1>;
compatible = "fsl,mpc8641-pcie";
device_type = "pci";
#interrupt-cells = <1>;
diff --git a/arch/powerpc/boot/dts/socrates.dts b/arch/powerpc/boot/dts/socrates.dts
index 7a6ae75a1e57..feb4ef6bd144 100644
--- a/arch/powerpc/boot/dts/socrates.dts
+++ b/arch/powerpc/boot/dts/socrates.dts
@@ -55,10 +55,22 @@
device_type = "soc";
ranges = <0x00000000 0xe0000000 0x00100000>;
- reg = <0xe0000000 0x00001000>; // CCSRBAR 1M
bus-frequency = <0>; // Filled in by U-Boot
compatible = "fsl,mpc8544-immr", "simple-bus";
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <10>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8544-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,mpc8544-memory-controller";
reg = <0x2000 0x1000>;
@@ -314,7 +326,6 @@
};
pci0: pci@e0008000 {
- cell-index = <0>;
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
diff --git a/arch/powerpc/boot/dts/stx_gp3_8560.dts b/arch/powerpc/boot/dts/stx_gp3_8560.dts
index ea6b15152de3..b670d03fbcd9 100644
--- a/arch/powerpc/boot/dts/stx_gp3_8560.dts
+++ b/arch/powerpc/boot/dts/stx_gp3_8560.dts
@@ -52,10 +52,22 @@
#size-cells = <1>;
device_type = "soc";
ranges = <0 0xfdf00000 0x100000>;
- reg = <0xfdf00000 0x1000>;
bus-frequency = <0>;
compatible = "fsl,mpc8560-immr", "simple-bus";
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <8>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8560-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,mpc8540-memory-controller";
reg = <0x2000 0x1000>;
@@ -251,7 +263,6 @@
};
pci0: pci@fdf08000 {
- cell-index = <0>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
diff --git a/arch/powerpc/boot/dts/tqm8540.dts b/arch/powerpc/boot/dts/tqm8540.dts
index 231bae756637..71347537b83e 100644
--- a/arch/powerpc/boot/dts/tqm8540.dts
+++ b/arch/powerpc/boot/dts/tqm8540.dts
@@ -54,10 +54,22 @@
#size-cells = <1>;
device_type = "soc";
ranges = <0x0 0xe0000000 0x100000>;
- reg = <0xe0000000 0x200>;
bus-frequency = <0>;
compatible = "fsl,mpc8540-immr", "simple-bus";
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <8>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8540-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,mpc8540-memory-controller";
reg = <0x2000 0x1000>;
@@ -84,9 +96,9 @@
interrupt-parent = <&mpic>;
dfsrr;
- dtt@50 {
+ dtt@48 {
compatible = "national,lm75";
- reg = <0x50>;
+ reg = <0x48>;
};
rtc@68 {
@@ -266,7 +278,6 @@
};
pci0: pci@e0008000 {
- cell-index = <0>;
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
diff --git a/arch/powerpc/boot/dts/tqm8541.dts b/arch/powerpc/boot/dts/tqm8541.dts
index 4356a1f08295..b30f63753d41 100644
--- a/arch/powerpc/boot/dts/tqm8541.dts
+++ b/arch/powerpc/boot/dts/tqm8541.dts
@@ -53,10 +53,22 @@
#size-cells = <1>;
device_type = "soc";
ranges = <0x0 0xe0000000 0x100000>;
- reg = <0xe0000000 0x200>;
bus-frequency = <0>;
compatible = "fsl,mpc8541-immr", "simple-bus";
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <8>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8541-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,mpc8540-memory-controller";
reg = <0x2000 0x1000>;
@@ -83,9 +95,9 @@
interrupt-parent = <&mpic>;
dfsrr;
- dtt@50 {
+ dtt@48 {
compatible = "national,lm75";
- reg = <0x50>;
+ reg = <0x48>;
};
rtc@68 {
@@ -288,7 +300,6 @@
};
pci0: pci@e0008000 {
- cell-index = <0>;
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
diff --git a/arch/powerpc/boot/dts/tqm8548-bigflash.dts b/arch/powerpc/boot/dts/tqm8548-bigflash.dts
index 19aa72301c83..61f25e15fd66 100644
--- a/arch/powerpc/boot/dts/tqm8548-bigflash.dts
+++ b/arch/powerpc/boot/dts/tqm8548-bigflash.dts
@@ -55,10 +55,22 @@
#size-cells = <1>;
device_type = "soc";
ranges = <0x0 0xa0000000 0x100000>;
- reg = <0xa0000000 0x1000>; // CCSRBAR
bus-frequency = <0>;
compatible = "fsl,mpc8548-immr", "simple-bus";
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <10>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8548-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,mpc8548-memory-controller";
reg = <0x2000 0x1000>;
@@ -85,9 +97,9 @@
interrupt-parent = <&mpic>;
dfsrr;
- dtt@50 {
+ dtt@48 {
compatible = "national,lm75";
- reg = <0x50>;
+ reg = <0x48>;
};
rtc@68 {
@@ -247,7 +259,7 @@
interrupts = <31 2 32 2 33 2>;
interrupt-parent = <&mpic>;
tbi-handle = <&tbi2>;
- phy-handle = <&phy3>;
+ phy-handle = <&phy4>;
mdio@520 {
#address-cells = <1>;
@@ -275,7 +287,7 @@
interrupts = <37 2 38 2 39 2>;
interrupt-parent = <&mpic>;
tbi-handle = <&tbi3>;
- phy-handle = <&phy4>;
+ phy-handle = <&phy5>;
mdio@520 {
#address-cells = <1>;
@@ -419,7 +431,6 @@
};
pci0: pci@a0008000 {
- cell-index = <0>;
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
@@ -441,7 +452,6 @@
};
pci1: pcie@a000a000 {
- cell-index = <2>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
/* IDSEL 0x0 (PEX) */
diff --git a/arch/powerpc/boot/dts/tqm8548.dts b/arch/powerpc/boot/dts/tqm8548.dts
index 49145a04fc6c..025759c7c955 100644
--- a/arch/powerpc/boot/dts/tqm8548.dts
+++ b/arch/powerpc/boot/dts/tqm8548.dts
@@ -55,10 +55,22 @@
#size-cells = <1>;
device_type = "soc";
ranges = <0x0 0xe0000000 0x100000>;
- reg = <0xe0000000 0x1000>; // CCSRBAR
bus-frequency = <0>;
compatible = "fsl,mpc8548-immr", "simple-bus";
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <10>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8548-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,mpc8548-memory-controller";
reg = <0x2000 0x1000>;
@@ -85,9 +97,9 @@
interrupt-parent = <&mpic>;
dfsrr;
- dtt@50 {
+ dtt@48 {
compatible = "national,lm75";
- reg = <0x50>;
+ reg = <0x48>;
};
rtc@68 {
@@ -247,7 +259,7 @@
interrupts = <31 2 32 2 33 2>;
interrupt-parent = <&mpic>;
tbi-handle = <&tbi2>;
- phy-handle = <&phy3>;
+ phy-handle = <&phy4>;
mdio@520 {
#address-cells = <1>;
@@ -275,7 +287,7 @@
interrupts = <37 2 38 2 39 2>;
interrupt-parent = <&mpic>;
tbi-handle = <&tbi3>;
- phy-handle = <&phy4>;
+ phy-handle = <&phy5>;
mdio@520 {
#address-cells = <1>;
@@ -419,7 +431,6 @@
};
pci0: pci@e0008000 {
- cell-index = <0>;
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
@@ -441,7 +452,6 @@
};
pci1: pcie@e000a000 {
- cell-index = <2>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
/* IDSEL 0x0 (PEX) */
diff --git a/arch/powerpc/boot/dts/tqm8555.dts b/arch/powerpc/boot/dts/tqm8555.dts
index 06d366ebbda3..95e287381836 100644
--- a/arch/powerpc/boot/dts/tqm8555.dts
+++ b/arch/powerpc/boot/dts/tqm8555.dts
@@ -53,10 +53,22 @@
#size-cells = <1>;
device_type = "soc";
ranges = <0x0 0xe0000000 0x100000>;
- reg = <0xe0000000 0x200>;
bus-frequency = <0>;
compatible = "fsl,mpc8555-immr", "simple-bus";
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <8>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8555-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,mpc8540-memory-controller";
reg = <0x2000 0x1000>;
@@ -83,9 +95,9 @@
interrupt-parent = <&mpic>;
dfsrr;
- dtt@50 {
+ dtt@48 {
compatible = "national,lm75";
- reg = <0x50>;
+ reg = <0x48>;
};
rtc@68 {
@@ -288,7 +300,6 @@
};
pci0: pci@e0008000 {
- cell-index = <0>;
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
diff --git a/arch/powerpc/boot/dts/tqm8560.dts b/arch/powerpc/boot/dts/tqm8560.dts
index feff915e0492..ff70580a8f4c 100644
--- a/arch/powerpc/boot/dts/tqm8560.dts
+++ b/arch/powerpc/boot/dts/tqm8560.dts
@@ -55,10 +55,22 @@
#size-cells = <1>;
device_type = "soc";
ranges = <0x0 0xe0000000 0x100000>;
- reg = <0xe0000000 0x200>;
bus-frequency = <0>;
compatible = "fsl,mpc8560-immr", "simple-bus";
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <8>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,mpc8560-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ };
+
memory-controller@2000 {
compatible = "fsl,mpc8540-memory-controller";
reg = <0x2000 0x1000>;
@@ -85,9 +97,9 @@
interrupt-parent = <&mpic>;
dfsrr;
- dtt@50 {
+ dtt@48 {
compatible = "national,lm75";
- reg = <0x50>;
+ reg = <0x48>;
};
rtc@68 {
@@ -359,7 +371,6 @@
};
pci0: pci@e0008000 {
- cell-index = <0>;
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
diff --git a/arch/powerpc/boot/simpleboot.c b/arch/powerpc/boot/simpleboot.c
index c58a0dada992..21cd48074ec8 100644
--- a/arch/powerpc/boot/simpleboot.c
+++ b/arch/powerpc/boot/simpleboot.c
@@ -19,7 +19,7 @@
#include "types.h"
#include "io.h"
#include "stdio.h"
-#include "libfdt/libfdt.h"
+#include <libfdt.h>
BSS_STACK(4*1024);
diff --git a/arch/powerpc/configs/40x/acadia_defconfig b/arch/powerpc/configs/40x/acadia_defconfig
index a32ec8d323a0..173a5bb77ca1 100644
--- a/arch/powerpc/configs/40x/acadia_defconfig
+++ b/arch/powerpc/configs/40x/acadia_defconfig
@@ -252,7 +252,7 @@ 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_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
diff --git a/arch/powerpc/configs/40x/ep405_defconfig b/arch/powerpc/configs/40x/ep405_defconfig
index 4e9d85f39da0..e9b8495cde0c 100644
--- a/arch/powerpc/configs/40x/ep405_defconfig
+++ b/arch/powerpc/configs/40x/ep405_defconfig
@@ -254,7 +254,7 @@ 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_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
diff --git a/arch/powerpc/configs/40x/kilauea_defconfig b/arch/powerpc/configs/40x/kilauea_defconfig
index 9917a09bad3a..cc3e7b785ac4 100644
--- a/arch/powerpc/configs/40x/kilauea_defconfig
+++ b/arch/powerpc/configs/40x/kilauea_defconfig
@@ -252,7 +252,7 @@ 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_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
diff --git a/arch/powerpc/configs/40x/makalu_defconfig b/arch/powerpc/configs/40x/makalu_defconfig
index 58bf2ac2e0dd..50c7cc174568 100644
--- a/arch/powerpc/configs/40x/makalu_defconfig
+++ b/arch/powerpc/configs/40x/makalu_defconfig
@@ -252,7 +252,7 @@ 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_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
diff --git a/arch/powerpc/configs/40x/virtex_defconfig b/arch/powerpc/configs/40x/virtex_defconfig
index f5698f962e58..416e79ac0711 100644
--- a/arch/powerpc/configs/40x/virtex_defconfig
+++ b/arch/powerpc/configs/40x/virtex_defconfig
@@ -258,7 +258,7 @@ 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_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
diff --git a/arch/powerpc/configs/44x/arches_defconfig b/arch/powerpc/configs/44x/arches_defconfig
index 1d72b0ac3f25..f7fd32c09424 100644
--- a/arch/powerpc/configs/44x/arches_defconfig
+++ b/arch/powerpc/configs/44x/arches_defconfig
@@ -258,7 +258,7 @@ 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_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
diff --git a/arch/powerpc/configs/44x/bamboo_defconfig b/arch/powerpc/configs/44x/bamboo_defconfig
index 959bdc43a491..e57f1e4c1795 100644
--- a/arch/powerpc/configs/44x/bamboo_defconfig
+++ b/arch/powerpc/configs/44x/bamboo_defconfig
@@ -262,7 +262,7 @@ 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_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
diff --git a/arch/powerpc/configs/44x/canyonlands_defconfig b/arch/powerpc/configs/44x/canyonlands_defconfig
index f9a08ee49b96..5e85412eb9fa 100644
--- a/arch/powerpc/configs/44x/canyonlands_defconfig
+++ b/arch/powerpc/configs/44x/canyonlands_defconfig
@@ -262,7 +262,7 @@ 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_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
@@ -716,7 +716,7 @@ CONFIG_SSB_POSSIBLE=y
#
# Multimedia drivers
#
-CONFIG_DAB=y
+# CONFIG_DAB is not set
# CONFIG_USB_DABUSB is not set
#
@@ -725,7 +725,7 @@ CONFIG_DAB=y
# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_VGASTATE is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
# CONFIG_FB is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
diff --git a/arch/powerpc/configs/44x/ebony_defconfig b/arch/powerpc/configs/44x/ebony_defconfig
index be64aa644d15..b652f7dcab5a 100644
--- a/arch/powerpc/configs/44x/ebony_defconfig
+++ b/arch/powerpc/configs/44x/ebony_defconfig
@@ -261,7 +261,7 @@ 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_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
diff --git a/arch/powerpc/configs/44x/katmai_defconfig b/arch/powerpc/configs/44x/katmai_defconfig
index f67250b24ec5..c23a4ef13e45 100644
--- a/arch/powerpc/configs/44x/katmai_defconfig
+++ b/arch/powerpc/configs/44x/katmai_defconfig
@@ -256,7 +256,7 @@ 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_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
diff --git a/arch/powerpc/configs/44x/rainier_defconfig b/arch/powerpc/configs/44x/rainier_defconfig
index 9348c12bd7a6..b25fad1343dc 100644
--- a/arch/powerpc/configs/44x/rainier_defconfig
+++ b/arch/powerpc/configs/44x/rainier_defconfig
@@ -260,7 +260,7 @@ 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_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
diff --git a/arch/powerpc/configs/44x/redwood_defconfig b/arch/powerpc/configs/44x/redwood_defconfig
index e665433762ba..ed31d4f17b5a 100644
--- a/arch/powerpc/configs/44x/redwood_defconfig
+++ b/arch/powerpc/configs/44x/redwood_defconfig
@@ -265,7 +265,7 @@ CONFIG_PCIEAER=y
# CONFIG_PCIEASPM is not set
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
diff --git a/arch/powerpc/configs/44x/sam440ep_defconfig b/arch/powerpc/configs/44x/sam440ep_defconfig
index 70d5c3fa3283..e14e89a5e06b 100644
--- a/arch/powerpc/configs/44x/sam440ep_defconfig
+++ b/arch/powerpc/configs/44x/sam440ep_defconfig
@@ -262,7 +262,7 @@ 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_LEGACY is not set
# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
diff --git a/arch/powerpc/configs/44x/sequoia_defconfig b/arch/powerpc/configs/44x/sequoia_defconfig
index a921fe3c3711..cb98da046d3d 100644
--- a/arch/powerpc/configs/44x/sequoia_defconfig
+++ b/arch/powerpc/configs/44x/sequoia_defconfig
@@ -262,7 +262,7 @@ 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_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
diff --git a/arch/powerpc/configs/44x/taishan_defconfig b/arch/powerpc/configs/44x/taishan_defconfig
index 826700872d26..ef32cc4f82eb 100644
--- a/arch/powerpc/configs/44x/taishan_defconfig
+++ b/arch/powerpc/configs/44x/taishan_defconfig
@@ -260,7 +260,7 @@ 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_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
diff --git a/arch/powerpc/configs/44x/virtex5_defconfig b/arch/powerpc/configs/44x/virtex5_defconfig
index 1bf0a63614b1..2518b8568c70 100644
--- a/arch/powerpc/configs/44x/virtex5_defconfig
+++ b/arch/powerpc/configs/44x/virtex5_defconfig
@@ -263,7 +263,7 @@ 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_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
diff --git a/arch/powerpc/configs/52xx/cm5200_defconfig b/arch/powerpc/configs/52xx/cm5200_defconfig
index 1239c6132b4a..3838b77b8116 100644
--- a/arch/powerpc/configs/52xx/cm5200_defconfig
+++ b/arch/powerpc/configs/52xx/cm5200_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc2
-# Mon Jan 26 21:41:58 2009
+# Linux kernel version: 2.6.30-rc2
+# Sat Apr 18 00:47:44 2009
#
# CONFIG_PPC64 is not set
@@ -14,6 +14,7 @@ CONFIG_6xx=y
# CONFIG_40x is not set
# CONFIG_44x is not set
# CONFIG_E200 is not set
+CONFIG_PPC_BOOK3S=y
CONFIG_PPC_FPU=y
# CONFIG_ALTIVEC is not set
CONFIG_PPC_STD_MMU=y
@@ -54,6 +55,7 @@ CONFIG_GENERIC_BUG=y
CONFIG_DEFAULT_UIMAGE=y
# CONFIG_PPC_DCR_NATIVE is not set
# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -94,19 +96,22 @@ CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
CONFIG_EMBEDDED=y
# CONFIG_SYSCTL_SYSCALL is not set
# CONFIG_KALLSYMS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -115,10 +120,12 @@ CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -126,6 +133,7 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -133,7 +141,6 @@ CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -154,8 +161,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
# Platform support
#
-CONFIG_PPC_MULTIPLATFORM=y
-CONFIG_CLASSIC32=y
# CONFIG_PPC_CHRP is not set
# CONFIG_MPC5121_ADS is not set
# CONFIG_MPC5121_GENERIC is not set
@@ -163,6 +168,7 @@ CONFIG_PPC_MPC52xx=y
CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_PPC_EFIKA is not set
# CONFIG_PPC_LITE5200 is not set
+# CONFIG_PPC_MEDIA5200 is not set
# CONFIG_PPC_MPC5200_BUGFIX is not set
# CONFIG_PPC_MPC5200_GPIO is not set
# CONFIG_PPC_PMAC is not set
@@ -173,6 +179,8 @@ CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_86xx is not set
# CONFIG_EMBEDDED6xx is not set
+# CONFIG_AMIGAONE is not set
+CONFIG_PPC_OF_BOOT_TRAMPOLINE=y
# CONFIG_IPIC is not set
# CONFIG_MPIC is not set
# CONFIG_MPIC_WEIRD is not set
@@ -232,9 +240,12 @@ CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_PPC_4K_PAGES=y
# CONFIG_PPC_16K_PAGES is not set
# CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -275,7 +286,6 @@ CONFIG_NET=y
#
# Networking options
#
-CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -331,6 +341,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
# CONFIG_DCB is not set
@@ -343,7 +354,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
@@ -440,7 +450,6 @@ CONFIG_MTD_PHYSMAP_OF=y
# LPDDR flash memory drivers
#
# CONFIG_MTD_LPDDR is not set
-# CONFIG_MTD_QINFO_PROBE is not set
#
# UBI - Unsorted block images
@@ -505,10 +514,12 @@ CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_SRP_ATTRS is not set
# CONFIG_SCSI_LOWLEVEL is not set
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
# CONFIG_ATA is not set
# CONFIG_MD is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -537,6 +548,8 @@ CONFIG_LXT_PHY=y
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET 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
@@ -555,7 +568,6 @@ CONFIG_FEC_MPC52xx_MDIO=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
#
# Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -657,7 +669,6 @@ CONFIG_I2C_MPC=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -786,11 +797,11 @@ CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
#
#
-# see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -831,7 +842,6 @@ CONFIG_USB_STORAGE=y
# 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
@@ -846,6 +856,7 @@ CONFIG_USB_STORAGE=y
#
# OTG and related infrastructure
#
+# CONFIG_NOP_USB_XCEIV is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -853,6 +864,7 @@ CONFIG_USB_STORAGE=y
# CONFIG_EDAC is not set
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
@@ -863,6 +875,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -885,6 +898,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -941,6 +959,7 @@ CONFIG_CRAMFS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -953,7 +972,6 @@ CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1024,6 +1042,7 @@ CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
# CONFIG_DLM is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
@@ -1039,11 +1058,12 @@ CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
+CONFIG_DECOMPRESS_GZIP=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
#
# Kernel hacking
@@ -1061,6 +1081,9 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1089,9 +1112,12 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -1099,17 +1125,19 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_CODE_PATCHING_SELFTEST is not set
# CONFIG_FTR_FIXUP_SELFTEST is not set
# CONFIG_MSI_BITMAP_SELFTEST is not set
@@ -1140,10 +1168,12 @@ CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_AUTHENC is not set
@@ -1211,6 +1241,7 @@ CONFIG_CRYPTO_DES=y
# Compression
#
# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
#
diff --git a/arch/powerpc/configs/52xx/lite5200b_defconfig b/arch/powerpc/configs/52xx/lite5200b_defconfig
index b7b880562906..29b0f34488f5 100644
--- a/arch/powerpc/configs/52xx/lite5200b_defconfig
+++ b/arch/powerpc/configs/52xx/lite5200b_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc2
-# Mon Jan 26 21:41:14 2009
+# Linux kernel version: 2.6.30-rc2
+# Sat Apr 18 00:48:04 2009
#
# CONFIG_PPC64 is not set
@@ -14,6 +14,7 @@ CONFIG_6xx=y
# CONFIG_40x is not set
# CONFIG_44x is not set
# CONFIG_E200 is not set
+CONFIG_PPC_BOOK3S=y
CONFIG_PPC_FPU=y
# CONFIG_ALTIVEC is not set
CONFIG_PPC_STD_MMU=y
@@ -55,6 +56,7 @@ CONFIG_DEFAULT_UIMAGE=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
# CONFIG_PPC_DCR_NATIVE is not set
# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -95,19 +97,22 @@ CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
CONFIG_EMBEDDED=y
# CONFIG_SYSCTL_SYSCALL is not set
# CONFIG_KALLSYMS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -117,10 +122,12 @@ CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_PCI_QUIRKS=y
CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -128,6 +135,7 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -140,7 +148,6 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -161,8 +168,6 @@ CONFIG_FREEZER=y
#
# Platform support
#
-CONFIG_PPC_MULTIPLATFORM=y
-CONFIG_CLASSIC32=y
# CONFIG_PPC_CHRP is not set
# CONFIG_MPC5121_ADS is not set
# CONFIG_MPC5121_GENERIC is not set
@@ -170,6 +175,7 @@ CONFIG_PPC_MPC52xx=y
CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_PPC_EFIKA is not set
CONFIG_PPC_LITE5200=y
+# CONFIG_PPC_MEDIA5200 is not set
# CONFIG_PPC_MPC5200_BUGFIX is not set
# CONFIG_PPC_MPC5200_GPIO is not set
# CONFIG_PPC_PMAC is not set
@@ -180,6 +186,8 @@ CONFIG_PPC_LITE5200=y
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_86xx is not set
# CONFIG_EMBEDDED6xx is not set
+# CONFIG_AMIGAONE is not set
+CONFIG_PPC_OF_BOOT_TRAMPOLINE=y
# CONFIG_IPIC is not set
# CONFIG_MPIC is not set
# CONFIG_MPIC_WEIRD is not set
@@ -241,9 +249,12 @@ CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_PPC_4K_PAGES=y
# CONFIG_PPC_16K_PAGES is not set
# CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -272,6 +283,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -294,7 +306,6 @@ CONFIG_NET=y
#
# Networking options
#
-CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -350,6 +361,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
# CONFIG_DCB is not set
@@ -362,7 +374,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
@@ -412,6 +423,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_ISL29003 is not set
# CONFIG_C2PORT is not set
#
@@ -477,9 +489,11 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
@@ -502,6 +516,7 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
@@ -578,6 +593,7 @@ CONFIG_PATA_MPC52xx=y
# CONFIG_I2O is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -611,6 +627,8 @@ CONFIG_NET_ETHERNET=y
# CONFIG_SUNGEM is not set
# CONFIG_CASSINI is not set
# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -632,6 +650,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_E1000E is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -642,10 +661,10 @@ CONFIG_NETDEV_1000=y
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
-# CONFIG_MV643XX_ETH is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
@@ -655,6 +674,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
@@ -664,6 +684,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_BNX2X is not set
# CONFIG_QLGE is not set
# CONFIG_SFC is not set
+# CONFIG_BE2NET is not set
# CONFIG_TR is not set
#
@@ -671,7 +692,6 @@ CONFIG_CHELSIO_T3_DEPENDS=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
#
# Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -795,7 +815,6 @@ CONFIG_I2C_MPC=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -876,7 +895,7 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
#
# CONFIG_USB_GADGET is not set
@@ -892,6 +911,7 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_EDAC is not set
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
@@ -902,6 +922,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -924,6 +945,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -966,6 +992,7 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -978,7 +1005,6 @@ CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -994,6 +1020,7 @@ CONFIG_RPCSEC_GSS_KRB5=y
CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
# CONFIG_DLM is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
@@ -1007,11 +1034,13 @@ CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
# CONFIG_LIBCRC32C is not set
-CONFIG_PLIST=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
#
# Kernel hacking
@@ -1029,6 +1058,9 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1057,9 +1089,12 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -1067,17 +1102,19 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_CODE_PATCHING_SELFTEST is not set
# CONFIG_FTR_FIXUP_SELFTEST is not set
# CONFIG_MSI_BITMAP_SELFTEST is not set
@@ -1108,10 +1145,12 @@ CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_AUTHENC is not set
# CONFIG_CRYPTO_TEST is not set
@@ -1180,6 +1219,7 @@ CONFIG_CRYPTO_DES=y
# Compression
#
# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
#
diff --git a/arch/powerpc/configs/52xx/motionpro_defconfig b/arch/powerpc/configs/52xx/motionpro_defconfig
index fb10f22fd0d2..07b6b266ea95 100644
--- a/arch/powerpc/configs/52xx/motionpro_defconfig
+++ b/arch/powerpc/configs/52xx/motionpro_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc2
-# Mon Jan 26 21:42:29 2009
+# Linux kernel version: 2.6.30-rc2
+# Sat Apr 18 00:48:22 2009
#
# CONFIG_PPC64 is not set
@@ -14,6 +14,7 @@ CONFIG_6xx=y
# CONFIG_40x is not set
# CONFIG_44x is not set
# CONFIG_E200 is not set
+CONFIG_PPC_BOOK3S=y
CONFIG_PPC_FPU=y
# CONFIG_ALTIVEC is not set
CONFIG_PPC_STD_MMU=y
@@ -54,6 +55,7 @@ CONFIG_GENERIC_BUG=y
CONFIG_DEFAULT_UIMAGE=y
# CONFIG_PPC_DCR_NATIVE is not set
# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -94,19 +96,22 @@ CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
CONFIG_EMBEDDED=y
# CONFIG_SYSCTL_SYSCALL is not set
# CONFIG_KALLSYMS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -115,10 +120,12 @@ CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -126,6 +133,7 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -133,7 +141,6 @@ CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -154,8 +161,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
# Platform support
#
-CONFIG_PPC_MULTIPLATFORM=y
-CONFIG_CLASSIC32=y
# CONFIG_PPC_CHRP is not set
# CONFIG_MPC5121_ADS is not set
# CONFIG_MPC5121_GENERIC is not set
@@ -163,6 +168,7 @@ CONFIG_PPC_MPC52xx=y
CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_PPC_EFIKA is not set
# CONFIG_PPC_LITE5200 is not set
+# CONFIG_PPC_MEDIA5200 is not set
# CONFIG_PPC_MPC5200_BUGFIX is not set
# CONFIG_PPC_MPC5200_GPIO is not set
# CONFIG_PPC_PMAC is not set
@@ -173,6 +179,8 @@ CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_86xx is not set
# CONFIG_EMBEDDED6xx is not set
+# CONFIG_AMIGAONE is not set
+CONFIG_PPC_OF_BOOT_TRAMPOLINE=y
# CONFIG_IPIC is not set
# CONFIG_MPIC is not set
# CONFIG_MPIC_WEIRD is not set
@@ -233,9 +241,12 @@ CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_PPC_4K_PAGES=y
# CONFIG_PPC_16K_PAGES is not set
# CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -276,7 +287,6 @@ CONFIG_NET=y
#
# Networking options
#
-CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -332,6 +342,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
# CONFIG_DCB is not set
@@ -344,7 +355,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
@@ -441,7 +451,6 @@ CONFIG_MTD_ROM=y
# LPDDR flash memory drivers
#
# CONFIG_MTD_LPDDR is not set
-# CONFIG_MTD_QINFO_PROBE is not set
#
# UBI - Unsorted block images
@@ -466,6 +475,7 @@ CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_MISC_DEVICES=y
# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
# CONFIG_C2PORT is not set
#
@@ -516,8 +526,10 @@ CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
@@ -528,6 +540,7 @@ CONFIG_PATA_MPC52xx=y
# CONFIG_MD is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -556,6 +569,8 @@ CONFIG_ICPLUS_PHY=y
CONFIG_MDIO_BITBANG=y
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
+# CONFIG_ETHOC is not set
+# CONFIG_DNET 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
@@ -574,7 +589,6 @@ CONFIG_FEC_MPC52xx_MDIO=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
#
# Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -665,7 +679,6 @@ CONFIG_I2C_MPC=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -696,6 +709,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_F71882FG is not set
# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
@@ -710,11 +724,14 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 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_PCF8591 is not set
# CONFIG_SENSORS_DME1737 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
@@ -800,7 +817,9 @@ CONFIG_LEDS_CLASS=y
#
# LED drivers
#
+# CONFIG_LEDS_LP5521 is not set
# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_BD2802 is not set
#
# LED Triggers
@@ -810,6 +829,10 @@ CONFIG_LEDS_TRIGGER_TIMER=y
# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
# CONFIG_ACCESSIBILITY is not set
# CONFIG_EDAC is not set
CONFIG_RTC_LIB=y
@@ -866,8 +889,9 @@ CONFIG_RTC_DRV_DS1307=y
#
# on-CPU RTC drivers
#
-# CONFIG_RTC_DRV_PPC is not set
+# CONFIG_RTC_DRV_GENERIC is not set
# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
@@ -878,6 +902,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -900,6 +925,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -956,6 +986,7 @@ CONFIG_CRAMFS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -968,7 +999,6 @@ CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1039,6 +1069,7 @@ CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
# CONFIG_DLM is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
@@ -1054,11 +1085,12 @@ CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
+CONFIG_DECOMPRESS_GZIP=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
#
# Kernel hacking
@@ -1076,6 +1108,9 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1104,9 +1139,12 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -1114,17 +1152,19 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_CODE_PATCHING_SELFTEST is not set
# CONFIG_FTR_FIXUP_SELFTEST is not set
# CONFIG_MSI_BITMAP_SELFTEST is not set
@@ -1155,10 +1195,12 @@ CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_AUTHENC is not set
@@ -1226,6 +1268,7 @@ CONFIG_CRYPTO_DES=y
# Compression
#
# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
#
diff --git a/arch/powerpc/configs/52xx/pcm030_defconfig b/arch/powerpc/configs/52xx/pcm030_defconfig
index 00944c09a0ae..afb1a3d1ef0a 100644
--- a/arch/powerpc/configs/52xx/pcm030_defconfig
+++ b/arch/powerpc/configs/52xx/pcm030_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc2
-# Mon Jan 26 21:41:33 2009
+# Linux kernel version: 2.6.30-rc2
+# Sat Apr 18 00:48:42 2009
#
# CONFIG_PPC64 is not set
@@ -14,6 +14,7 @@ CONFIG_6xx=y
# CONFIG_40x is not set
# CONFIG_44x is not set
# CONFIG_E200 is not set
+CONFIG_PPC_BOOK3S=y
CONFIG_PPC_FPU=y
# CONFIG_ALTIVEC is not set
CONFIG_PPC_STD_MMU=y
@@ -54,6 +55,7 @@ CONFIG_GENERIC_BUG=y
CONFIG_DEFAULT_UIMAGE=y
# CONFIG_PPC_DCR_NATIVE is not set
# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -69,6 +71,7 @@ CONFIG_LOCALVERSION="trunk"
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
@@ -97,18 +100,18 @@ CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
CONFIG_EMBEDDED=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -117,10 +120,12 @@ CONFIG_SHMEM=y
CONFIG_AIO=y
# CONFIG_VM_EVENT_COUNTERS is not set
CONFIG_PCI_QUIRKS=y
+CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -129,6 +134,7 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -141,7 +147,6 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -162,8 +167,6 @@ CONFIG_DEFAULT_IOSCHED="noop"
#
# Platform support
#
-CONFIG_PPC_MULTIPLATFORM=y
-CONFIG_CLASSIC32=y
# CONFIG_PPC_CHRP is not set
# CONFIG_MPC5121_ADS is not set
# CONFIG_MPC5121_GENERIC is not set
@@ -171,6 +174,7 @@ CONFIG_PPC_MPC52xx=y
CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_PPC_EFIKA is not set
# CONFIG_PPC_LITE5200 is not set
+# CONFIG_PPC_MEDIA5200 is not set
# CONFIG_PPC_MPC5200_BUGFIX is not set
# CONFIG_PPC_MPC5200_GPIO is not set
# CONFIG_PPC_PMAC is not set
@@ -181,6 +185,8 @@ CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_86xx is not set
# CONFIG_EMBEDDED6xx is not set
+# CONFIG_AMIGAONE is not set
+CONFIG_PPC_OF_BOOT_TRAMPOLINE=y
# CONFIG_IPIC is not set
# CONFIG_MPIC is not set
# CONFIG_MPIC_WEIRD is not set
@@ -242,9 +248,12 @@ CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_PPC_4K_PAGES=y
# CONFIG_PPC_16K_PAGES is not set
# CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -268,6 +277,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -290,7 +300,6 @@ CONFIG_NET=y
#
# Networking options
#
-CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -340,6 +349,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
# CONFIG_DCB is not set
@@ -352,7 +362,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
@@ -451,7 +460,6 @@ CONFIG_MTD_PHYSMAP=y
# LPDDR flash memory drivers
#
# CONFIG_MTD_LPDDR is not set
-# CONFIG_MTD_QINFO_PROBE is not set
#
# UBI - Unsorted block images
@@ -504,6 +512,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
# CONFIG_SCSI_LOWLEVEL is not set
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_ATA=m
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
@@ -580,6 +589,7 @@ CONFIG_PATA_MPC52xx=m
# CONFIG_I2O is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -613,6 +623,8 @@ CONFIG_MII=y
# CONFIG_SUNGEM is not set
# CONFIG_CASSINI is not set
# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -636,7 +648,6 @@ CONFIG_FEC_MPC52xx_MDIO=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
#
# Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -702,6 +713,7 @@ CONFIG_UNIX98_PTYS=y
# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
# CONFIG_NVRAM is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -767,7 +779,6 @@ CONFIG_I2C_MPC=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -889,11 +900,11 @@ CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
#
#
-# see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
#
CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -934,7 +945,6 @@ CONFIG_USB_STORAGE=m
# 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
@@ -949,6 +959,7 @@ CONFIG_USB_STORAGE=m
#
# OTG and related infrastructure
#
+# CONFIG_NOP_USB_XCEIV is not set
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1007,8 +1018,9 @@ CONFIG_RTC_DRV_PCF8563=m
#
# on-CPU RTC drivers
#
-# CONFIG_RTC_DRV_PPC is not set
+# CONFIG_RTC_DRV_GENERIC is not set
# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
@@ -1019,6 +1031,7 @@ CONFIG_EXT2_FS=m
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=m
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -1040,6 +1053,11 @@ CONFIG_FILE_LOCKING=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -1096,6 +1114,7 @@ CONFIG_JFFS2_RTIME=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -1107,7 +1126,6 @@ CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1162,6 +1180,7 @@ CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
# CONFIG_DLM is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
@@ -1177,11 +1196,11 @@ CONFIG_CRC32=y
# 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
CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
#
# Kernel hacking
@@ -1200,13 +1219,25 @@ CONFIG_FRAME_WARN=1024
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_PRINT_STACK_DEPTH=64
diff --git a/arch/powerpc/configs/52xx/tqm5200_defconfig b/arch/powerpc/configs/52xx/tqm5200_defconfig
index 65237ad6f07e..8585c7c12861 100644
--- a/arch/powerpc/configs/52xx/tqm5200_defconfig
+++ b/arch/powerpc/configs/52xx/tqm5200_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc2
-# Mon Jan 26 21:42:58 2009
+# Linux kernel version: 2.6.30-rc2
+# Sat Apr 18 00:48:57 2009
#
# CONFIG_PPC64 is not set
@@ -14,6 +14,7 @@ CONFIG_6xx=y
# CONFIG_40x is not set
# CONFIG_44x is not set
# CONFIG_E200 is not set
+CONFIG_PPC_BOOK3S=y
CONFIG_PPC_FPU=y
# CONFIG_ALTIVEC is not set
CONFIG_PPC_STD_MMU=y
@@ -54,6 +55,7 @@ CONFIG_GENERIC_BUG=y
CONFIG_DEFAULT_UIMAGE=y
# CONFIG_PPC_DCR_NATIVE is not set
# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -94,19 +96,22 @@ CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
CONFIG_EMBEDDED=y
# CONFIG_SYSCTL_SYSCALL is not set
# CONFIG_KALLSYMS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -115,10 +120,12 @@ CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -126,6 +133,7 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -138,7 +146,6 @@ CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -159,8 +166,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
# Platform support
#
-CONFIG_PPC_MULTIPLATFORM=y
-CONFIG_CLASSIC32=y
# CONFIG_PPC_CHRP is not set
# CONFIG_MPC5121_ADS is not set
# CONFIG_MPC5121_GENERIC is not set
@@ -168,6 +173,7 @@ CONFIG_PPC_MPC52xx=y
CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_PPC_EFIKA is not set
# CONFIG_PPC_LITE5200 is not set
+# CONFIG_PPC_MEDIA5200 is not set
CONFIG_PPC_MPC5200_BUGFIX=y
# CONFIG_PPC_MPC5200_GPIO is not set
# CONFIG_PPC_PMAC is not set
@@ -178,6 +184,8 @@ CONFIG_PPC_MPC5200_BUGFIX=y
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_86xx is not set
# CONFIG_EMBEDDED6xx is not set
+# CONFIG_AMIGAONE is not set
+CONFIG_PPC_OF_BOOT_TRAMPOLINE=y
# CONFIG_IPIC is not set
# CONFIG_MPIC is not set
# CONFIG_MPIC_WEIRD is not set
@@ -238,9 +246,12 @@ CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_PPC_4K_PAGES=y
# CONFIG_PPC_16K_PAGES is not set
# CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -281,7 +292,6 @@ CONFIG_NET=y
#
# Networking options
#
-CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -337,6 +347,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
# CONFIG_DCB is not set
@@ -349,7 +360,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
@@ -447,7 +457,6 @@ CONFIG_MTD_PHYSMAP_OF=y
# LPDDR flash memory drivers
#
# CONFIG_MTD_LPDDR is not set
-# CONFIG_MTD_QINFO_PROBE is not set
#
# UBI - Unsorted block images
@@ -514,8 +523,10 @@ CONFIG_SCSI_WAIT_SCAN=m
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
@@ -527,6 +538,7 @@ CONFIG_PATA_PLATFORM=y
# CONFIG_MD is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -555,6 +567,8 @@ CONFIG_LXT_PHY=y
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET 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
@@ -573,7 +587,6 @@ CONFIG_FEC_MPC52xx_MDIO=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
#
# Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -675,7 +688,6 @@ CONFIG_I2C_MPC=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -706,6 +718,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_F71882FG is not set
# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
@@ -720,11 +733,14 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 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_PCF8591 is not set
# CONFIG_SENSORS_DME1737 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
@@ -857,11 +873,11 @@ CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
#
#
-# see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -902,7 +918,6 @@ CONFIG_USB_STORAGE=y
# 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
@@ -917,6 +932,7 @@ CONFIG_USB_STORAGE=y
#
# OTG and related infrastructure
#
+# CONFIG_NOP_USB_XCEIV is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -976,8 +992,9 @@ CONFIG_RTC_DRV_DS1307=y
#
# on-CPU RTC drivers
#
-# CONFIG_RTC_DRV_PPC is not set
+# CONFIG_RTC_DRV_GENERIC is not set
# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
@@ -988,6 +1005,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -1010,6 +1028,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -1066,6 +1089,7 @@ CONFIG_CRAMFS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -1078,7 +1102,6 @@ CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1149,6 +1172,7 @@ CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
# CONFIG_DLM is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
@@ -1164,11 +1188,12 @@ CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
+CONFIG_DECOMPRESS_GZIP=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
#
# Kernel hacking
@@ -1186,6 +1211,9 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1214,9 +1242,12 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -1224,17 +1255,19 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_CODE_PATCHING_SELFTEST is not set
# CONFIG_FTR_FIXUP_SELFTEST is not set
# CONFIG_MSI_BITMAP_SELFTEST is not set
@@ -1265,10 +1298,12 @@ CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_AUTHENC is not set
# CONFIG_CRYPTO_TEST is not set
@@ -1337,6 +1372,7 @@ CONFIG_CRYPTO_DES=y
# Compression
#
# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
#
diff --git a/arch/powerpc/configs/85xx/mpc8536_ds_defconfig b/arch/powerpc/configs/85xx/mpc8536_ds_defconfig
deleted file mode 100644
index e31b6a4732ed..000000000000
--- a/arch/powerpc/configs/85xx/mpc8536_ds_defconfig
+++ /dev/null
@@ -1,1802 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc2
-# Mon Jan 26 15:36:04 2009
-#
-# CONFIG_PPC64 is not set
-
-#
-# Processor support
-#
-# CONFIG_6xx is not set
-CONFIG_PPC_85xx=y
-# CONFIG_PPC_8xx is not set
-# CONFIG_40x is not set
-# CONFIG_44x is not set
-# CONFIG_E200 is not set
-CONFIG_E500=y
-# CONFIG_PPC_E500MC is not set
-CONFIG_BOOKE=y
-CONFIG_FSL_BOOKE=y
-CONFIG_FSL_EMB_PERFMON=y
-# CONFIG_PHYS_64BIT is not set
-CONFIG_SPE=y
-CONFIG_PPC_MMU_NOHASH=y
-# CONFIG_PPC_MM_SLICES is not set
-# CONFIG_SMP is not set
-CONFIG_PPC32=y
-CONFIG_WORD_SIZE=32
-# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
-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_HAVE_SETUP_PER_CPU_AREA is not set
-CONFIG_IRQ_PER_CPU=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_HAVE_LATENCYTOP_SUPPORT=y
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_ARCH_HAS_ILOG2_U32=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
-CONFIG_PPC=y
-CONFIG_EARLY_PRINTK=y
-CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_OMIT_FRAME_POINTER=y
-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
-CONFIG_PPC_OF=y
-CONFIG_OF=y
-CONFIG_PPC_UDBG_16550=y
-# CONFIG_GENERIC_TBSYNC is not set
-CONFIG_AUDIT_ARCH=y
-CONFIG_GENERIC_BUG=y
-CONFIG_DEFAULT_UIMAGE=y
-# CONFIG_PPC_DCR_NATIVE is not set
-# CONFIG_PPC_DCR_MMIO is not set
-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=y
-CONFIG_BSD_PROCESS_ACCT=y
-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
-# CONFIG_TASKSTATS is not set
-CONFIG_AUDIT=y
-# CONFIG_AUDITSYSCALL is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_GROUP_SCHED=y
-# CONFIG_FAIR_GROUP_SCHED is not set
-# CONFIG_RT_GROUP_SCHED is not set
-CONFIG_USER_SCHED=y
-# CONFIG_CGROUP_SCHED is not set
-# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-# CONFIG_RELAY is not set
-# CONFIG_NAMESPACES 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_STRIP_GENERATED=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
-CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
-CONFIG_SHMEM=y
-CONFIG_AIO=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_PCI_QUIRKS=y
-CONFIG_SLUB_DEBUG=y
-# CONFIG_SLAB is not set
-CONFIG_SLUB=y
-# CONFIG_SLOB is not set
-# CONFIG_PROFILING is not set
-CONFIG_HAVE_OPROFILE=y
-# CONFIG_KPROBES is not set
-CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
-CONFIG_HAVE_IOREMAP_PROT=y
-CONFIG_HAVE_KPROBES=y
-CONFIG_HAVE_KRETPROBES=y
-CONFIG_HAVE_ARCH_TRACEHOOK=y
-# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
-CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
-CONFIG_BASE_SMALL=0
-CONFIG_MODULES=y
-# CONFIG_MODULE_FORCE_LOAD is not set
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_BLOCK=y
-CONFIG_LBD=y
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_BLK_DEV_INTEGRITY is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
-# CONFIG_DEFAULT_DEADLINE is not set
-CONFIG_DEFAULT_CFQ=y
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
-# CONFIG_FREEZER is not set
-
-#
-# Platform support
-#
-# CONFIG_PPC_CELL is not set
-# CONFIG_PPC_CELL_NATIVE is not set
-# CONFIG_PQ2ADS is not set
-CONFIG_MPC85xx=y
-# CONFIG_MPC8540_ADS is not set
-# CONFIG_MPC8560_ADS is not set
-# CONFIG_MPC85xx_CDS is not set
-# CONFIG_MPC85xx_MDS is not set
-CONFIG_MPC8536_DS=y
-# CONFIG_MPC85xx_DS is not set
-# CONFIG_KSI8560 is not set
-# CONFIG_STX_GP3 is not set
-# CONFIG_TQM8540 is not set
-# CONFIG_TQM8541 is not set
-# CONFIG_TQM8548 is not set
-# CONFIG_TQM8555 is not set
-# CONFIG_TQM8560 is not set
-# CONFIG_SBC8548 is not set
-# CONFIG_SBC8560 is not set
-# CONFIG_IPIC is not set
-CONFIG_MPIC=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
-# CONFIG_PPC_RTAS is not set
-# CONFIG_MMIO_NVRAM is not set
-# 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_QUICC_ENGINE is not set
-# CONFIG_CPM2 is not set
-# CONFIG_FSL_ULI1575 is not set
-# CONFIG_MPC8xxx_GPIO is not set
-# CONFIG_SIMPLE_GPIO is not set
-
-#
-# Kernel options
-#
-CONFIG_HIGHMEM=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=y
-# CONFIG_HZ_300 is not set
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
-CONFIG_SCHED_HRTICK=y
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-CONFIG_BINFMT_ELF=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-# CONFIG_HAVE_AOUT is not set
-CONFIG_BINFMT_MISC=m
-CONFIG_MATH_EMULATION=y
-# CONFIG_IOMMU_HELPER is not set
-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
-CONFIG_ARCH_HAS_WALK_MEMORY=y
-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_ARCH_POPULATES_NODE_MAP=y
-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_PAGEFLAGS_EXTENDED=y
-CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_MIGRATION=y
-# CONFIG_PHYS_ADDR_T_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
-CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
-CONFIG_PPC_4K_PAGES=y
-# CONFIG_PPC_16K_PAGES is not set
-# CONFIG_PPC_64K_PAGES is not set
-CONFIG_FORCE_MAX_ZONEORDER=11
-CONFIG_PROC_DEVICETREE=y
-# CONFIG_CMDLINE_BOOL is not set
-CONFIG_EXTRA_TARGETS=""
-# CONFIG_PM is not set
-CONFIG_SECCOMP=y
-CONFIG_ISA_DMA_API=y
-
-#
-# Bus options
-#
-CONFIG_ZONE_DMA=y
-CONFIG_PPC_INDIRECT_PCI=y
-CONFIG_FSL_SOC=y
-CONFIG_FSL_PCI=y
-CONFIG_PPC_PCI_CHOICE=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_SYSCALL=y
-# CONFIG_PCIEPORTBUS is not set
-CONFIG_ARCH_SUPPORTS_MSI=y
-# CONFIG_PCI_MSI is not set
-# CONFIG_PCI_LEGACY is not set
-# CONFIG_PCI_DEBUG is not set
-# CONFIG_PCI_STUB is not set
-# CONFIG_PCCARD is not set
-# CONFIG_HOTPLUG_PCI is not set
-# CONFIG_HAS_RAPIDIO is not set
-
-#
-# Advanced setup
-#
-# CONFIG_ADVANCED_OPTIONS is not set
-
-#
-# Default settings for advanced configuration options are used
-#
-CONFIG_LOWMEM_SIZE=0x30000000
-CONFIG_PAGE_OFFSET=0xc0000000
-CONFIG_KERNEL_START=0xc0000000
-CONFIG_PHYSICAL_START=0x00000000
-CONFIG_PHYSICAL_ALIGN=0x10000000
-CONFIG_TASK_SIZE=0xc0000000
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_COMPAT_NET_DEV_OPS=y
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-# CONFIG_XFRM_SUB_POLICY is not set
-# CONFIG_XFRM_MIGRATE is not set
-# CONFIG_XFRM_STATISTICS 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=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_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_NET_IPIP=y
-CONFIG_NET_IPGRE=y
-CONFIG_NET_IPGRE_BROADCAST=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-CONFIG_ARPD=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=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
-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 is not set
-# CONFIG_INET6_ESP is not set
-# CONFIG_INET6_IPCOMP is not set
-# CONFIG_IPV6_MIP6 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_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
-CONFIG_IPV6_SIT=y
-CONFIG_IPV6_NDISC_NODETYPE=y
-# CONFIG_IPV6_TUNNEL is not set
-# CONFIG_IPV6_MULTIPLE_TABLES is not set
-# CONFIG_IPV6_MROUTE is not set
-# CONFIG_NETWORK_SECMARK is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_IP_DCCP is not set
-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
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_NET_DSA is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_SCHED is not set
-# CONFIG_DCB is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_CAN is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
-CONFIG_FIB_RULES=y
-CONFIG_WIRELESS=y
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_OLD_REGULATORY=y
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_WIMAX is not set
-# CONFIG_RFKILL is not set
-# CONFIG_NET_9P is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
-CONFIG_FIRMWARE_IN_KERNEL=y
-CONFIG_EXTRA_FIRMWARE=""
-# CONFIG_DEBUG_DRIVER is not set
-# CONFIG_DEBUG_DEVRES is not set
-# CONFIG_SYS_HYPERVISOR is not set
-# CONFIG_CONNECTOR is not set
-# CONFIG_MTD is not set
-CONFIG_OF_DEVICE=y
-CONFIG_OF_I2C=y
-# CONFIG_PARPORT is not set
-CONFIG_BLK_DEV=y
-# CONFIG_BLK_DEV_FD is not set
-# 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=y
-# 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=524288
-# CONFIG_BLK_DEV_XIP is not set
-# CONFIG_CDROM_PKTCDVD is not set
-# CONFIG_ATA_OVER_ETH is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_MISC_DEVICES=y
-# CONFIG_PHANTOM is not set
-# CONFIG_EEPROM_93CX6 is not set
-# CONFIG_SGI_IOC4 is not set
-# CONFIG_TIFM_CORE is not set
-# CONFIG_ICS932S401 is not set
-# CONFIG_ENCLOSURE_SERVICES is not set
-# CONFIG_HP_ILO is not set
-# CONFIG_C2PORT is not set
-CONFIG_HAVE_IDE=y
-# CONFIG_IDE 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=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-CONFIG_CHR_DEV_SG=y
-# CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_SCSI_CONSTANTS is not set
-CONFIG_SCSI_LOGGING=y
-# 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_LIBSAS is not set
-# CONFIG_SCSI_SRP_ATTRS is not set
-CONFIG_SCSI_LOWLEVEL=y
-# CONFIG_ISCSI_TCP is not set
-# CONFIG_SCSI_CXGB3_ISCSI is not set
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_AIC94XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_ARCMSR is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_LIBFC is not set
-# CONFIG_FCOE is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
-# CONFIG_SCSI_STEX is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR 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_SCSI_DH is not set
-CONFIG_ATA=y
-# CONFIG_ATA_NONSTANDARD is not set
-CONFIG_SATA_PMP=y
-# CONFIG_SATA_AHCI is not set
-CONFIG_SATA_SIL24=y
-CONFIG_SATA_FSL=y
-CONFIG_ATA_SFF=y
-# CONFIG_SATA_SVW is not set
-# CONFIG_ATA_PIIX is not set
-# CONFIG_SATA_MV is not set
-# 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=y
-# CONFIG_SATA_SIS is not set
-# CONFIG_SATA_ULI is not set
-# CONFIG_SATA_VIA is not set
-# CONFIG_SATA_VITESSE is not set
-# CONFIG_SATA_INIC162X is not set
-# CONFIG_PATA_ALI is not set
-# CONFIG_PATA_AMD is not set
-# CONFIG_PATA_ARTOP is not set
-# CONFIG_PATA_ATIIXP is not set
-# CONFIG_PATA_CMD640_PCI is not set
-# CONFIG_PATA_CMD64X is not set
-# CONFIG_PATA_CS5520 is not set
-# CONFIG_PATA_CS5530 is not set
-# CONFIG_PATA_CYPRESS is not set
-# CONFIG_PATA_EFAR is not set
-# CONFIG_ATA_GENERIC is not set
-# CONFIG_PATA_HPT366 is not set
-# CONFIG_PATA_HPT37X is not set
-# CONFIG_PATA_HPT3X2N is not set
-# CONFIG_PATA_HPT3X3 is not set
-# CONFIG_PATA_IT821X is not set
-# CONFIG_PATA_IT8213 is not set
-# CONFIG_PATA_JMICRON is not set
-# CONFIG_PATA_TRIFLEX is not set
-# CONFIG_PATA_MARVELL is not set
-# CONFIG_PATA_MPIIX is not set
-# CONFIG_PATA_OLDPIIX is not set
-# CONFIG_PATA_NETCELL is not set
-# CONFIG_PATA_NINJA32 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
-# CONFIG_PATA_RADISYS is not set
-# CONFIG_PATA_RZ1000 is not set
-# CONFIG_PATA_SC1200 is not set
-# CONFIG_PATA_SERVERWORKS is not set
-# CONFIG_PATA_PDC2027X is not set
-# CONFIG_PATA_SIL680 is not set
-# CONFIG_PATA_SIS is not set
-# CONFIG_PATA_VIA is not set
-# CONFIG_PATA_WINBOND is not set
-# CONFIG_PATA_PLATFORM is not set
-# CONFIG_PATA_SCH is not set
-# CONFIG_MD is not set
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# Enable only one of the two stacks, unless you know what you are doing
-#
-# CONFIG_FIREWIRE is not set
-# CONFIG_IEEE1394 is not set
-# CONFIG_I2O is not set
-# CONFIG_MACINTOSH_DRIVERS is not set
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=y
-# 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_ARCNET is not set
-CONFIG_PHYLIB=y
-
-#
-# MII PHY device drivers
-#
-# CONFIG_MARVELL_PHY is not set
-# CONFIG_DAVICOM_PHY is not set
-# CONFIG_QSEMI_PHY is not set
-# CONFIG_LXT_PHY is not set
-# CONFIG_CICADA_PHY is not set
-CONFIG_VITESSE_PHY=y
-# CONFIG_SMSC_PHY is not set
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_ICPLUS_PHY is not set
-# CONFIG_REALTEK_PHY is not set
-# CONFIG_NATIONAL_PHY is not set
-# CONFIG_STE10XP is not set
-# CONFIG_LSI_ET1011C_PHY is not set
-# CONFIG_FIXED_PHY is not set
-# CONFIG_MDIO_BITBANG is not set
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# 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_ZMII is not set
-# CONFIG_IBM_NEW_EMAC_RGMII is not set
-# CONFIG_IBM_NEW_EMAC_TAH is not set
-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
-# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
-# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
-# CONFIG_NET_PCI is not set
-# CONFIG_B44 is not set
-# CONFIG_ATL2 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_IP1000 is not set
-# CONFIG_IGB is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-CONFIG_SKGE=y
-# CONFIG_SKGE_DEBUG is not set
-CONFIG_SKY2=y
-# CONFIG_SKY2_DEBUG is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_GIANFAR=y
-# CONFIG_QLA3XXX is not set
-# CONFIG_ATL1 is not set
-# CONFIG_ATL1E is not set
-# CONFIG_JME is not set
-CONFIG_NETDEV_10000=y
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3_DEPENDS=y
-# CONFIG_CHELSIO_T3 is not set
-# CONFIG_ENIC is not set
-# CONFIG_IXGBE is not set
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-# CONFIG_NETXEN_NIC is not set
-# CONFIG_NIU is not set
-# CONFIG_MLX4_EN is not set
-# CONFIG_MLX4_CORE is not set
-# CONFIG_TEHUTI is not set
-# CONFIG_BNX2X is not set
-# CONFIG_QLGE is not set
-# CONFIG_SFC is not set
-# CONFIG_TR is not set
-
-#
-# Wireless LAN
-#
-# CONFIG_WLAN_PRE80211 is not set
-# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
-
-#
-# Enable WiMAX (Networking options) to see the WiMAX drivers
-#
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET is not set
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_NET_FC is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_ISDN is not set
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-CONFIG_INPUT_FF_MEMLESS=m
-# CONFIG_INPUT_POLLDEV is not set
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# 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=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
-# CONFIG_SERIO_XILINX_XPS_PS2 is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_CONSOLE_TRANSLATIONS=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_VT_HW_CONSOLE_BINDING is not set
-CONFIG_DEVKMEM=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_NOZOMI is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=2
-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_8250_DETECT_IRQ=y
-CONFIG_SERIAL_8250_RSA=y
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_SERIAL_UARTLITE is not set
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-# CONFIG_SERIAL_OF_PLATFORM is not set
-CONFIG_UNIX98_PTYS=y
-# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_HVC_UDBG is not set
-# CONFIG_IPMI_HANDLER is not set
-CONFIG_HW_RANDOM=y
-# CONFIG_NVRAM is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_TCG_TPM is not set
-CONFIG_DEVPORT=y
-CONFIG_I2C=y
-CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_CHARDEV is not set
-CONFIG_I2C_HELPER_AUTO=y
-
-#
-# I2C Hardware Bus support
-#
-
-#
-# PC SMBus host controller drivers
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_ISCH is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-
-#
-# I2C system bus drivers (mostly embedded / system-on-chip)
-#
-CONFIG_I2C_MPC=y
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_SIMTEC is not set
-
-#
-# External I2C/SMBus adapter drivers
-#
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_TINY_USB is not set
-
-#
-# Graphics adapter I2C/DDC channel drivers
-#
-# CONFIG_I2C_VOODOO3 is not set
-
-#
-# Other I2C/SMBus bus drivers
-#
-# CONFIG_I2C_PCA_PLATFORM is not set
-# CONFIG_I2C_STUB is not set
-
-#
-# Miscellaneous I2C Chip support
-#
-# CONFIG_DS1682 is not set
-# CONFIG_EEPROM_AT24 is not set
-CONFIG_EEPROM_LEGACY=y
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-# CONFIG_SPI is not set
-CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
-# CONFIG_W1 is not set
-# CONFIG_POWER_SUPPLY is not set
-# CONFIG_HWMON is not set
-CONFIG_THERMAL=y
-# CONFIG_WATCHDOG is not set
-CONFIG_SSB_POSSIBLE=y
-
-#
-# Sonics Silicon Backplane
-#
-# CONFIG_SSB is not set
-
-#
-# Multifunction device drivers
-#
-# CONFIG_MFD_CORE is not set
-# CONFIG_MFD_SM501 is not set
-# CONFIG_HTC_PASIC3 is not set
-# CONFIG_TWL4030_CORE is not set
-# CONFIG_MFD_TMIO is not set
-# CONFIG_PMIC_DA903X is not set
-# CONFIG_MFD_WM8400 is not set
-# CONFIG_MFD_WM8350_I2C is not set
-# CONFIG_MFD_PCF50633 is not set
-# CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-CONFIG_DVB_CORE=m
-CONFIG_VIDEO_MEDIA=m
-
-#
-# Multimedia drivers
-#
-# CONFIG_MEDIA_ATTACH is not set
-CONFIG_MEDIA_TUNER=m
-# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
-CONFIG_MEDIA_TUNER_SIMPLE=m
-CONFIG_MEDIA_TUNER_TDA8290=m
-CONFIG_MEDIA_TUNER_TDA9887=m
-CONFIG_MEDIA_TUNER_TEA5761=m
-CONFIG_MEDIA_TUNER_TEA5767=m
-CONFIG_MEDIA_TUNER_MT20XX=m
-CONFIG_MEDIA_TUNER_XC2028=m
-CONFIG_MEDIA_TUNER_XC5000=m
-# CONFIG_DVB_DYNAMIC_MINORS is not set
-CONFIG_DVB_CAPTURE_DRIVERS=y
-
-#
-# Supported SAA7146 based PCI Adapters
-#
-# CONFIG_TTPCI_EEPROM is not set
-# CONFIG_DVB_BUDGET_CORE is not set
-
-#
-# Supported USB Adapters
-#
-# CONFIG_DVB_USB is not set
-# CONFIG_DVB_TTUSB_BUDGET is not set
-# CONFIG_DVB_TTUSB_DEC is not set
-# CONFIG_DVB_SIANO_SMS1XXX is not set
-
-#
-# Supported FlexCopII (B2C2) Adapters
-#
-# CONFIG_DVB_B2C2_FLEXCOP is not set
-
-#
-# Supported BT878 Adapters
-#
-
-#
-# Supported Pluto2 Adapters
-#
-# CONFIG_DVB_PLUTO2 is not set
-
-#
-# Supported SDMC DM1105 Adapters
-#
-# CONFIG_DVB_DM1105 is not set
-
-#
-# Supported DVB Frontends
-#
-
-#
-# Customise DVB Frontends
-#
-# CONFIG_DVB_FE_CUSTOMISE is not set
-
-#
-# Multistandard (satellite) frontends
-#
-# CONFIG_DVB_STB0899 is not set
-# CONFIG_DVB_STB6100 is not set
-
-#
-# DVB-S (satellite) frontends
-#
-# CONFIG_DVB_CX24110 is not set
-# CONFIG_DVB_CX24123 is not set
-# CONFIG_DVB_MT312 is not set
-# CONFIG_DVB_S5H1420 is not set
-# CONFIG_DVB_STV0288 is not set
-# CONFIG_DVB_STB6000 is not set
-# CONFIG_DVB_STV0299 is not set
-# CONFIG_DVB_TDA8083 is not set
-# CONFIG_DVB_TDA10086 is not set
-# CONFIG_DVB_TDA8261 is not set
-# CONFIG_DVB_VES1X93 is not set
-# CONFIG_DVB_TUNER_ITD1000 is not set
-# CONFIG_DVB_TUNER_CX24113 is not set
-# CONFIG_DVB_TDA826X is not set
-# CONFIG_DVB_TUA6100 is not set
-# CONFIG_DVB_CX24116 is not set
-# CONFIG_DVB_SI21XX is not set
-
-#
-# DVB-T (terrestrial) frontends
-#
-# CONFIG_DVB_SP8870 is not set
-# CONFIG_DVB_SP887X is not set
-# CONFIG_DVB_CX22700 is not set
-# CONFIG_DVB_CX22702 is not set
-# CONFIG_DVB_DRX397XD is not set
-# CONFIG_DVB_L64781 is not set
-# CONFIG_DVB_TDA1004X is not set
-# CONFIG_DVB_NXT6000 is not set
-# CONFIG_DVB_MT352 is not set
-# CONFIG_DVB_ZL10353 is not set
-# CONFIG_DVB_DIB3000MB is not set
-# CONFIG_DVB_DIB3000MC is not set
-# CONFIG_DVB_DIB7000M is not set
-# CONFIG_DVB_DIB7000P is not set
-# CONFIG_DVB_TDA10048 is not set
-
-#
-# DVB-C (cable) frontends
-#
-# CONFIG_DVB_VES1820 is not set
-# CONFIG_DVB_TDA10021 is not set
-# CONFIG_DVB_TDA10023 is not set
-# CONFIG_DVB_STV0297 is not set
-
-#
-# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
-#
-# CONFIG_DVB_NXT200X is not set
-# CONFIG_DVB_OR51211 is not set
-# CONFIG_DVB_OR51132 is not set
-# CONFIG_DVB_BCM3510 is not set
-# CONFIG_DVB_LGDT330X is not set
-# CONFIG_DVB_LGDT3304 is not set
-# CONFIG_DVB_S5H1409 is not set
-# CONFIG_DVB_AU8522 is not set
-# CONFIG_DVB_S5H1411 is not set
-
-#
-# ISDB-T (terrestrial) frontends
-#
-# CONFIG_DVB_S921 is not set
-
-#
-# Digital terrestrial only tuners/PLL
-#
-# CONFIG_DVB_PLL is not set
-# CONFIG_DVB_TUNER_DIB0070 is not set
-
-#
-# SEC control devices for DVB-S
-#
-# CONFIG_DVB_LNBP21 is not set
-# CONFIG_DVB_ISL6405 is not set
-# CONFIG_DVB_ISL6421 is not set
-# CONFIG_DVB_LGS8GL5 is not set
-
-#
-# Tools to develop new frontends
-#
-# CONFIG_DVB_DUMMY_FE is not set
-# CONFIG_DVB_AF9013 is not set
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
-
-#
-# Graphics support
-#
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_VGASTATE is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=y
-# CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Console display driver support
-#
-CONFIG_VGA_CONSOLE=y
-# CONFIG_VGACON_SOFT_SCROLLBACK is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_SOUND=y
-# CONFIG_SOUND_OSS_CORE is not set
-CONFIG_SND=y
-CONFIG_SND_TIMER=y
-CONFIG_SND_PCM=y
-# CONFIG_SND_SEQUENCER is not set
-# CONFIG_SND_MIXER_OSS is not set
-# CONFIG_SND_PCM_OSS is not set
-# CONFIG_SND_HRTIMER is not set
-# 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
-CONFIG_SND_VMASTER=y
-CONFIG_SND_AC97_CODEC=y
-CONFIG_SND_DRIVERS=y
-# 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
-# CONFIG_SND_AC97_POWER_SAVE is not set
-CONFIG_SND_PCI=y
-# CONFIG_SND_AD1889 is not set
-# CONFIG_SND_ALS300 is not set
-# CONFIG_SND_ALS4000 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_AW2 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_OXYGEN is not set
-# CONFIG_SND_CS4281 is not set
-# CONFIG_SND_CS46XX is not set
-# CONFIG_SND_CS5530 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_HIFIER is not set
-# CONFIG_SND_ICE1712 is not set
-# CONFIG_SND_ICE1724 is not set
-CONFIG_SND_INTEL8X0=y
-# 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_VIRTUOSO is not set
-# CONFIG_SND_VX222 is not set
-# CONFIG_SND_YMFPCI is not set
-CONFIG_SND_PPC=y
-CONFIG_SND_USB=y
-# CONFIG_SND_USB_AUDIO is not set
-# CONFIG_SND_USB_USX2Y is not set
-# CONFIG_SND_USB_CAIAQ is not set
-# CONFIG_SND_SOC is not set
-# CONFIG_SOUND_PRIME is not set
-CONFIG_AC97_BUS=y
-CONFIG_HID_SUPPORT=y
-CONFIG_HID=y
-# CONFIG_HID_DEBUG is not set
-# CONFIG_HIDRAW is not set
-
-#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-# CONFIG_HID_PID is not set
-# CONFIG_USB_HIDDEV is not set
-
-#
-# Special HID drivers
-#
-CONFIG_HID_COMPAT=y
-CONFIG_HID_A4TECH=y
-CONFIG_HID_APPLE=y
-CONFIG_HID_BELKIN=y
-CONFIG_HID_CHERRY=y
-CONFIG_HID_CHICONY=y
-CONFIG_HID_CYPRESS=y
-CONFIG_HID_EZKEY=y
-CONFIG_HID_GYRATION=y
-CONFIG_HID_LOGITECH=y
-# CONFIG_LOGITECH_FF is not set
-# CONFIG_LOGIRUMBLEPAD2_FF is not set
-CONFIG_HID_MICROSOFT=y
-CONFIG_HID_MONTEREY=y
-# CONFIG_HID_NTRIG is not set
-CONFIG_HID_PANTHERLORD=y
-# CONFIG_PANTHERLORD_FF is not set
-CONFIG_HID_PETALYNX=y
-CONFIG_HID_SAMSUNG=y
-CONFIG_HID_SONY=y
-CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
-# CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
-CONFIG_USB_SUPPORT=y
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
-
-#
-# Miscellaneous USB options
-#
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_DEVICE_CLASS=y
-# CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_OTG is not set
-# CONFIG_USB_OTG_WHITELIST is not set
-# CONFIG_USB_OTG_BLACKLIST_HUB is not set
-CONFIG_USB_MON=y
-# CONFIG_USB_WUSB is not set
-# CONFIG_USB_WUSB_CBAF is not set
-
-#
-# USB Host Controller Drivers
-#
-# CONFIG_USB_C67X00_HCD is not set
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_ROOT_HUB_TT=y
-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
-CONFIG_USB_EHCI_FSL=y
-CONFIG_USB_EHCI_HCD_PPC_OF=y
-# CONFIG_USB_OXU210HP_HCD is not set
-# CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_ISP1760_HCD is not set
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
-CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
-CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
-CONFIG_USB_OHCI_HCD_PCI=y
-CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
-CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
-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
-# CONFIG_USB_WHCI_HCD is not set
-# CONFIG_USB_HWA_HCD is not set
-
-#
-# USB Device Class drivers
-#
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
-# CONFIG_USB_WDM is not set
-# CONFIG_USB_TMC is not set
-
-#
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
-#
-
-#
-# see USB_STORAGE Help for more information
-#
-CONFIG_USB_STORAGE=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_ISD200 is not set
-# CONFIG_USB_STORAGE_USBAT is not set
-# CONFIG_USB_STORAGE_SDDR09 is not set
-# CONFIG_USB_STORAGE_SDDR55 is not set
-# CONFIG_USB_STORAGE_JUMPSHOT is not set
-# CONFIG_USB_STORAGE_ALAUDA is not set
-# CONFIG_USB_STORAGE_ONETOUCH is not set
-# CONFIG_USB_STORAGE_KARMA is not set
-# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
-# CONFIG_USB_LIBUSUAL is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_MICROTEK is not set
-
-#
-# USB port drivers
-#
-# CONFIG_USB_SERIAL is not set
-
-#
-# USB Miscellaneous drivers
-#
-# CONFIG_USB_EMI62 is not set
-# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_SEVSEG is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_LEGOTOWER is not set
-# CONFIG_USB_LCD is not set
-# CONFIG_USB_BERRY_CHARGE is not set
-# CONFIG_USB_LED is not set
-# CONFIG_USB_CYPRESS_CY7C63 is not set
-# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
-# CONFIG_USB_IDMOUSE is not set
-# CONFIG_USB_FTDI_ELAN is not set
-# CONFIG_USB_APPLEDISPLAY is not set
-# CONFIG_USB_SISUSBVGA is not set
-# CONFIG_USB_LD is not set
-# CONFIG_USB_TRANCEVIBRATOR is not set
-# CONFIG_USB_IOWARRIOR is not set
-# CONFIG_USB_TEST is not set
-# CONFIG_USB_ISIGHTFW is not set
-# CONFIG_USB_VST is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# OTG and related infrastructure
-#
-# CONFIG_UWB is not set
-# CONFIG_MMC is not set
-# CONFIG_MEMSTICK is not set
-# CONFIG_NEW_LEDS is not set
-# CONFIG_ACCESSIBILITY is not set
-# CONFIG_INFINIBAND is not set
-# CONFIG_EDAC is not set
-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_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
-# CONFIG_RTC_DRV_S35390A is not set
-# CONFIG_RTC_DRV_FM3130 is not set
-# CONFIG_RTC_DRV_RX8581 is not set
-
-#
-# SPI RTC drivers
-#
-
-#
-# Platform RTC drivers
-#
-CONFIG_RTC_DRV_CMOS=y
-# CONFIG_RTC_DRV_DS1286 is not set
-# CONFIG_RTC_DRV_DS1511 is not set
-# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_DS1742 is not set
-# CONFIG_RTC_DRV_STK17TA8 is not set
-# CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_M48T35 is not set
-# CONFIG_RTC_DRV_M48T59 is not set
-# CONFIG_RTC_DRV_BQ4802 is not set
-# CONFIG_RTC_DRV_V3020 is not set
-
-#
-# on-CPU RTC drivers
-#
-# CONFIG_RTC_DRV_PPC is not set
-CONFIG_DMADEVICES=y
-
-#
-# DMA Devices
-#
-CONFIG_FSL_DMA=y
-CONFIG_DMA_ENGINE=y
-
-#
-# DMA Clients
-#
-# CONFIG_NET_DMA is not set
-# CONFIG_DMATEST is not set
-# CONFIG_UIO is not set
-# CONFIG_STAGING 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=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4_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_FILE_LOCKING=y
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_BTRFS_FS is not set
-CONFIG_DNOTIFY=y
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_FUSE_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=m
-CONFIG_UDF_NLS=y
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
-CONFIG_NTFS_FS=y
-# CONFIG_NTFS_DEBUG is not set
-# CONFIG_NTFS_RW is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_PROC_PAGE_MONITOR=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_POSIX_ACL is not set
-# CONFIG_HUGETLB_PAGE is not set
-# CONFIG_CONFIGFS_FS is not set
-CONFIG_MISC_FILESYSTEMS=y
-CONFIG_ADFS_FS=m
-# CONFIG_ADFS_FS_RW is not set
-CONFIG_AFFS_FS=m
-CONFIG_HFS_FS=m
-CONFIG_HFSPLUS_FS=m
-CONFIG_BEFS_FS=m
-# CONFIG_BEFS_DEBUG is not set
-CONFIG_BFS_FS=m
-CONFIG_EFS_FS=m
-CONFIG_CRAMFS=y
-# CONFIG_SQUASHFS is not set
-CONFIG_VXFS_FS=m
-# CONFIG_MINIX_FS is not set
-# CONFIG_OMFS_FS is not set
-CONFIG_HPFS_FS=m
-CONFIG_QNX4FS_FS=m
-# CONFIG_ROMFS_FS is not set
-CONFIG_SYSV_FS=m
-CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
-# CONFIG_UFS_DEBUG is not set
-CONFIG_NETWORK_FILESYSTEMS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_V4 is not set
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 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=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=y
-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
-CONFIG_NLS=y
-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=m
-# CONFIG_DLM is not set
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-CONFIG_GENERIC_FIND_LAST_BIT=y
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
-CONFIG_CRC_T10DIF=y
-CONFIG_CRC_ITU_T=m
-CONFIG_CRC32=y
-# CONFIG_CRC7 is not set
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
-CONFIG_HAS_DMA=y
-CONFIG_HAVE_LMB=y
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_WARN_DEPRECATED=y
-CONFIG_ENABLE_MUST_CHECK=y
-CONFIG_FRAME_WARN=1024
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-CONFIG_DEBUG_FS=y
-# CONFIG_HEADERS_CHECK is not set
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SHIRQ is not set
-CONFIG_DETECT_SOFTLOCKUP=y
-# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
-CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
-CONFIG_SCHED_DEBUG=y
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_OBJECTS is not set
-# CONFIG_SLUB_DEBUG_ON is not set
-# CONFIG_SLUB_STATS is not set
-# CONFIG_DEBUG_RT_MUTEXES is not set
-# CONFIG_RT_MUTEX_TESTER is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_MUTEXES 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_HIGHMEM is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_VM is not set
-# CONFIG_DEBUG_WRITECOUNT is not set
-# CONFIG_DEBUG_MEMORY_INIT is not set
-# CONFIG_DEBUG_LIST is not set
-# CONFIG_DEBUG_SG is not set
-# CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
-# CONFIG_RCU_TORTURE_TEST is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_BACKTRACE_SELF_TEST is not set
-# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
-# CONFIG_FAULT_INJECTION is not set
-# CONFIG_LATENCYTOP is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_HAVE_FUNCTION_TRACER=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
-# CONFIG_SAMPLES is not set
-CONFIG_HAVE_ARCH_KGDB=y
-# CONFIG_KGDB is not set
-CONFIG_PRINT_STACK_DEPTH=64
-# CONFIG_DEBUG_STACKOVERFLOW is not set
-# CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
-# CONFIG_CODE_PATCHING_SELFTEST is not set
-# CONFIG_FTR_FIXUP_SELFTEST is not set
-# CONFIG_MSI_BITMAP_SELFTEST is not set
-# CONFIG_XMON is not set
-# CONFIG_IRQSTACKS is not set
-# CONFIG_VIRQ_DEBUG is not set
-# CONFIG_BDI_SWITCH is not set
-# CONFIG_PPC_EARLY_DEBUG is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-# CONFIG_SECURITYFS is not set
-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
-CONFIG_CRYPTO=y
-
-#
-# Crypto core or helper
-#
-# CONFIG_CRYPTO_FIPS is not set
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_ALGAPI2=y
-CONFIG_CRYPTO_AEAD=y
-CONFIG_CRYPTO_AEAD2=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_BLKCIPHER2=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_HASH2=y
-CONFIG_CRYPTO_RNG2=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_MANAGER2=y
-# CONFIG_CRYPTO_GF128MUL is not set
-# CONFIG_CRYPTO_NULL is not set
-# CONFIG_CRYPTO_CRYPTD is not set
-CONFIG_CRYPTO_AUTHENC=y
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Authenticated Encryption with Associated Data
-#
-# CONFIG_CRYPTO_CCM is not set
-# CONFIG_CRYPTO_GCM is not set
-# CONFIG_CRYPTO_SEQIV is not set
-
-#
-# Block modes
-#
-CONFIG_CRYPTO_CBC=y
-# CONFIG_CRYPTO_CTR is not set
-# CONFIG_CRYPTO_CTS is not set
-# CONFIG_CRYPTO_ECB is not set
-# CONFIG_CRYPTO_LRW is not set
-CONFIG_CRYPTO_PCBC=m
-# CONFIG_CRYPTO_XTS is not set
-
-#
-# Hash modes
-#
-CONFIG_CRYPTO_HMAC=y
-# CONFIG_CRYPTO_XCBC is not set
-
-#
-# Digest
-#
-CONFIG_CRYPTO_CRC32C=m
-# CONFIG_CRYPTO_MD4 is not set
-CONFIG_CRYPTO_MD5=y
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_RMD128 is not set
-# CONFIG_CRYPTO_RMD160 is not set
-# CONFIG_CRYPTO_RMD256 is not set
-# CONFIG_CRYPTO_RMD320 is not set
-CONFIG_CRYPTO_SHA1=m
-# CONFIG_CRYPTO_SHA256 is not set
-# CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_WP512 is not set
-
-#
-# Ciphers
-#
-# CONFIG_CRYPTO_AES is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-# CONFIG_CRYPTO_ARC4 is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_CAMELLIA is not set
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
-CONFIG_CRYPTO_DES=y
-# CONFIG_CRYPTO_FCRYPT is not set
-# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_SALSA20 is not set
-# CONFIG_CRYPTO_SEED is not set
-# CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_TEA is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-
-#
-# Compression
-#
-# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_LZO is not set
-
-#
-# Random Number Generation
-#
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_HW=y
-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
-CONFIG_CRYPTO_DEV_TALITOS=y
-# CONFIG_PPC_CLOCK is not set
-# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/configs/85xx/mpc8544_ds_defconfig b/arch/powerpc/configs/85xx/mpc8544_ds_defconfig
deleted file mode 100644
index f6fa0b761cb3..000000000000
--- a/arch/powerpc/configs/85xx/mpc8544_ds_defconfig
+++ /dev/null
@@ -1,1802 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc2
-# Mon Jan 26 15:36:07 2009
-#
-# CONFIG_PPC64 is not set
-
-#
-# Processor support
-#
-# CONFIG_6xx is not set
-CONFIG_PPC_85xx=y
-# CONFIG_PPC_8xx is not set
-# CONFIG_40x is not set
-# CONFIG_44x is not set
-# CONFIG_E200 is not set
-CONFIG_E500=y
-# CONFIG_PPC_E500MC is not set
-CONFIG_BOOKE=y
-CONFIG_FSL_BOOKE=y
-CONFIG_FSL_EMB_PERFMON=y
-# CONFIG_PHYS_64BIT is not set
-CONFIG_SPE=y
-CONFIG_PPC_MMU_NOHASH=y
-# CONFIG_PPC_MM_SLICES is not set
-# CONFIG_SMP is not set
-CONFIG_PPC32=y
-CONFIG_WORD_SIZE=32
-# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
-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_HAVE_SETUP_PER_CPU_AREA is not set
-CONFIG_IRQ_PER_CPU=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_HAVE_LATENCYTOP_SUPPORT=y
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_ARCH_HAS_ILOG2_U32=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
-CONFIG_PPC=y
-CONFIG_EARLY_PRINTK=y
-CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_OMIT_FRAME_POINTER=y
-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
-CONFIG_PPC_OF=y
-CONFIG_OF=y
-CONFIG_PPC_UDBG_16550=y
-# CONFIG_GENERIC_TBSYNC is not set
-CONFIG_AUDIT_ARCH=y
-CONFIG_GENERIC_BUG=y
-CONFIG_DEFAULT_UIMAGE=y
-# CONFIG_PPC_DCR_NATIVE is not set
-# CONFIG_PPC_DCR_MMIO is not set
-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=y
-CONFIG_BSD_PROCESS_ACCT=y
-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
-# CONFIG_TASKSTATS is not set
-CONFIG_AUDIT=y
-# CONFIG_AUDITSYSCALL is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_GROUP_SCHED=y
-# CONFIG_FAIR_GROUP_SCHED is not set
-# CONFIG_RT_GROUP_SCHED is not set
-CONFIG_USER_SCHED=y
-# CONFIG_CGROUP_SCHED is not set
-# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-# CONFIG_RELAY is not set
-# CONFIG_NAMESPACES 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_STRIP_GENERATED=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
-CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
-CONFIG_SHMEM=y
-CONFIG_AIO=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_PCI_QUIRKS=y
-CONFIG_SLUB_DEBUG=y
-# CONFIG_SLAB is not set
-CONFIG_SLUB=y
-# CONFIG_SLOB is not set
-# CONFIG_PROFILING is not set
-CONFIG_HAVE_OPROFILE=y
-# CONFIG_KPROBES is not set
-CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
-CONFIG_HAVE_IOREMAP_PROT=y
-CONFIG_HAVE_KPROBES=y
-CONFIG_HAVE_KRETPROBES=y
-CONFIG_HAVE_ARCH_TRACEHOOK=y
-# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
-CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
-CONFIG_BASE_SMALL=0
-CONFIG_MODULES=y
-# CONFIG_MODULE_FORCE_LOAD is not set
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_BLOCK=y
-CONFIG_LBD=y
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_BLK_DEV_INTEGRITY is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
-# CONFIG_DEFAULT_DEADLINE is not set
-CONFIG_DEFAULT_CFQ=y
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
-# CONFIG_FREEZER is not set
-
-#
-# Platform support
-#
-# CONFIG_PPC_CELL is not set
-# CONFIG_PPC_CELL_NATIVE is not set
-# CONFIG_PQ2ADS is not set
-CONFIG_MPC85xx=y
-# CONFIG_MPC8540_ADS is not set
-# CONFIG_MPC8560_ADS is not set
-# CONFIG_MPC85xx_CDS is not set
-# CONFIG_MPC85xx_MDS is not set
-# CONFIG_MPC8536_DS is not set
-CONFIG_MPC85xx_DS=y
-# CONFIG_KSI8560 is not set
-# CONFIG_STX_GP3 is not set
-# CONFIG_TQM8540 is not set
-# CONFIG_TQM8541 is not set
-# CONFIG_TQM8548 is not set
-# CONFIG_TQM8555 is not set
-# CONFIG_TQM8560 is not set
-# CONFIG_SBC8548 is not set
-# CONFIG_SBC8560 is not set
-# CONFIG_IPIC is not set
-CONFIG_MPIC=y
-# CONFIG_MPIC_WEIRD is not set
-CONFIG_PPC_I8259=y
-# CONFIG_PPC_RTAS is not set
-# CONFIG_MMIO_NVRAM is not set
-# 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_QUICC_ENGINE is not set
-# CONFIG_CPM2 is not set
-CONFIG_FSL_ULI1575=y
-# CONFIG_MPC8xxx_GPIO is not set
-# CONFIG_SIMPLE_GPIO is not set
-
-#
-# Kernel options
-#
-CONFIG_HIGHMEM=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=y
-# CONFIG_HZ_300 is not set
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
-CONFIG_SCHED_HRTICK=y
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-CONFIG_BINFMT_ELF=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-# CONFIG_HAVE_AOUT is not set
-CONFIG_BINFMT_MISC=m
-CONFIG_MATH_EMULATION=y
-# CONFIG_IOMMU_HELPER is not set
-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
-CONFIG_ARCH_HAS_WALK_MEMORY=y
-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_ARCH_POPULATES_NODE_MAP=y
-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_PAGEFLAGS_EXTENDED=y
-CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_MIGRATION=y
-# CONFIG_PHYS_ADDR_T_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
-CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
-CONFIG_PPC_4K_PAGES=y
-# CONFIG_PPC_16K_PAGES is not set
-# CONFIG_PPC_64K_PAGES is not set
-CONFIG_FORCE_MAX_ZONEORDER=11
-CONFIG_PROC_DEVICETREE=y
-# CONFIG_CMDLINE_BOOL is not set
-CONFIG_EXTRA_TARGETS=""
-# CONFIG_PM is not set
-CONFIG_SECCOMP=y
-CONFIG_ISA_DMA_API=y
-
-#
-# Bus options
-#
-CONFIG_ZONE_DMA=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PPC_INDIRECT_PCI=y
-CONFIG_FSL_SOC=y
-CONFIG_FSL_PCI=y
-CONFIG_PPC_PCI_CHOICE=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_SYSCALL=y
-# CONFIG_PCIEPORTBUS is not set
-CONFIG_ARCH_SUPPORTS_MSI=y
-# CONFIG_PCI_MSI is not set
-# CONFIG_PCI_LEGACY is not set
-# CONFIG_PCI_DEBUG is not set
-# CONFIG_PCI_STUB is not set
-# CONFIG_PCCARD is not set
-# CONFIG_HOTPLUG_PCI is not set
-# CONFIG_HAS_RAPIDIO is not set
-
-#
-# Advanced setup
-#
-# CONFIG_ADVANCED_OPTIONS is not set
-
-#
-# Default settings for advanced configuration options are used
-#
-CONFIG_LOWMEM_SIZE=0x30000000
-CONFIG_PAGE_OFFSET=0xc0000000
-CONFIG_KERNEL_START=0xc0000000
-CONFIG_PHYSICAL_START=0x00000000
-CONFIG_PHYSICAL_ALIGN=0x10000000
-CONFIG_TASK_SIZE=0xc0000000
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_COMPAT_NET_DEV_OPS=y
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-# CONFIG_XFRM_SUB_POLICY is not set
-# CONFIG_XFRM_MIGRATE is not set
-# CONFIG_XFRM_STATISTICS 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=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_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_NET_IPIP=y
-CONFIG_NET_IPGRE=y
-CONFIG_NET_IPGRE_BROADCAST=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-CONFIG_ARPD=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=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
-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 is not set
-# CONFIG_INET6_ESP is not set
-# CONFIG_INET6_IPCOMP is not set
-# CONFIG_IPV6_MIP6 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_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
-CONFIG_IPV6_SIT=y
-CONFIG_IPV6_NDISC_NODETYPE=y
-# CONFIG_IPV6_TUNNEL is not set
-# CONFIG_IPV6_MULTIPLE_TABLES is not set
-# CONFIG_IPV6_MROUTE is not set
-# CONFIG_NETWORK_SECMARK is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_IP_DCCP is not set
-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
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_NET_DSA is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_SCHED is not set
-# CONFIG_DCB is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_CAN is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
-CONFIG_FIB_RULES=y
-CONFIG_WIRELESS=y
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_OLD_REGULATORY=y
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_WIMAX is not set
-# CONFIG_RFKILL is not set
-# CONFIG_NET_9P is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
-CONFIG_FIRMWARE_IN_KERNEL=y
-CONFIG_EXTRA_FIRMWARE=""
-# CONFIG_DEBUG_DRIVER is not set
-# CONFIG_DEBUG_DEVRES is not set
-# CONFIG_SYS_HYPERVISOR is not set
-# CONFIG_CONNECTOR is not set
-# CONFIG_MTD is not set
-CONFIG_OF_DEVICE=y
-CONFIG_OF_I2C=y
-# CONFIG_PARPORT is not set
-CONFIG_BLK_DEV=y
-# CONFIG_BLK_DEV_FD is not set
-# 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=y
-# 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=131072
-# CONFIG_BLK_DEV_XIP is not set
-# CONFIG_CDROM_PKTCDVD is not set
-# CONFIG_ATA_OVER_ETH is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_MISC_DEVICES=y
-# CONFIG_PHANTOM is not set
-# CONFIG_EEPROM_93CX6 is not set
-# CONFIG_SGI_IOC4 is not set
-# CONFIG_TIFM_CORE is not set
-# CONFIG_ICS932S401 is not set
-# CONFIG_ENCLOSURE_SERVICES is not set
-# CONFIG_HP_ILO is not set
-# CONFIG_C2PORT is not set
-CONFIG_HAVE_IDE=y
-# CONFIG_IDE 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=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-CONFIG_CHR_DEV_SG=y
-# CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_SCSI_CONSTANTS is not set
-CONFIG_SCSI_LOGGING=y
-# 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_LIBSAS is not set
-# CONFIG_SCSI_SRP_ATTRS is not set
-CONFIG_SCSI_LOWLEVEL=y
-# CONFIG_ISCSI_TCP is not set
-# CONFIG_SCSI_CXGB3_ISCSI is not set
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_AIC94XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_ARCMSR is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_LIBFC is not set
-# CONFIG_FCOE is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
-# CONFIG_SCSI_STEX is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR 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_SCSI_DH is not set
-CONFIG_ATA=y
-# CONFIG_ATA_NONSTANDARD is not set
-CONFIG_SATA_PMP=y
-CONFIG_SATA_AHCI=y
-# CONFIG_SATA_SIL24 is not set
-# CONFIG_SATA_FSL is not set
-CONFIG_ATA_SFF=y
-# CONFIG_SATA_SVW is not set
-# CONFIG_ATA_PIIX is not set
-# CONFIG_SATA_MV is not set
-# 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_SIS is not set
-# CONFIG_SATA_ULI is not set
-# CONFIG_SATA_VIA is not set
-# CONFIG_SATA_VITESSE is not set
-# CONFIG_SATA_INIC162X is not set
-CONFIG_PATA_ALI=y
-# CONFIG_PATA_AMD is not set
-# CONFIG_PATA_ARTOP is not set
-# CONFIG_PATA_ATIIXP is not set
-# CONFIG_PATA_CMD640_PCI is not set
-# CONFIG_PATA_CMD64X is not set
-# CONFIG_PATA_CS5520 is not set
-# CONFIG_PATA_CS5530 is not set
-# CONFIG_PATA_CYPRESS is not set
-# CONFIG_PATA_EFAR is not set
-# CONFIG_ATA_GENERIC is not set
-# CONFIG_PATA_HPT366 is not set
-# CONFIG_PATA_HPT37X is not set
-# CONFIG_PATA_HPT3X2N is not set
-# CONFIG_PATA_HPT3X3 is not set
-# CONFIG_PATA_IT821X is not set
-# CONFIG_PATA_IT8213 is not set
-# CONFIG_PATA_JMICRON is not set
-# CONFIG_PATA_TRIFLEX is not set
-# CONFIG_PATA_MARVELL is not set
-# CONFIG_PATA_MPIIX is not set
-# CONFIG_PATA_OLDPIIX is not set
-# CONFIG_PATA_NETCELL is not set
-# CONFIG_PATA_NINJA32 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
-# CONFIG_PATA_RADISYS is not set
-# CONFIG_PATA_RZ1000 is not set
-# CONFIG_PATA_SC1200 is not set
-# CONFIG_PATA_SERVERWORKS is not set
-# CONFIG_PATA_PDC2027X is not set
-# CONFIG_PATA_SIL680 is not set
-# CONFIG_PATA_SIS is not set
-# CONFIG_PATA_VIA is not set
-# CONFIG_PATA_WINBOND is not set
-# CONFIG_PATA_PLATFORM is not set
-# CONFIG_PATA_SCH is not set
-# CONFIG_MD is not set
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# Enable only one of the two stacks, unless you know what you are doing
-#
-# CONFIG_FIREWIRE is not set
-# CONFIG_IEEE1394 is not set
-# CONFIG_I2O is not set
-# CONFIG_MACINTOSH_DRIVERS is not set
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=y
-# 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_ARCNET is not set
-CONFIG_PHYLIB=y
-
-#
-# MII PHY device drivers
-#
-# CONFIG_MARVELL_PHY is not set
-# CONFIG_DAVICOM_PHY is not set
-# CONFIG_QSEMI_PHY is not set
-# CONFIG_LXT_PHY is not set
-# CONFIG_CICADA_PHY is not set
-CONFIG_VITESSE_PHY=y
-# CONFIG_SMSC_PHY is not set
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_ICPLUS_PHY is not set
-# CONFIG_REALTEK_PHY is not set
-# CONFIG_NATIONAL_PHY is not set
-# CONFIG_STE10XP is not set
-# CONFIG_LSI_ET1011C_PHY is not set
-# CONFIG_FIXED_PHY is not set
-# CONFIG_MDIO_BITBANG is not set
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# 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_ZMII is not set
-# CONFIG_IBM_NEW_EMAC_RGMII is not set
-# CONFIG_IBM_NEW_EMAC_TAH is not set
-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
-# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
-# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
-# CONFIG_NET_PCI is not set
-# CONFIG_B44 is not set
-# CONFIG_ATL2 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_IP1000 is not set
-# CONFIG_IGB is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_GIANFAR=y
-# CONFIG_QLA3XXX is not set
-# CONFIG_ATL1 is not set
-# CONFIG_ATL1E is not set
-# CONFIG_JME is not set
-CONFIG_NETDEV_10000=y
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3_DEPENDS=y
-# CONFIG_CHELSIO_T3 is not set
-# CONFIG_ENIC is not set
-# CONFIG_IXGBE is not set
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-# CONFIG_NETXEN_NIC is not set
-# CONFIG_NIU is not set
-# CONFIG_MLX4_EN is not set
-# CONFIG_MLX4_CORE is not set
-# CONFIG_TEHUTI is not set
-# CONFIG_BNX2X is not set
-# CONFIG_QLGE is not set
-# CONFIG_SFC is not set
-# CONFIG_TR is not set
-
-#
-# Wireless LAN
-#
-# CONFIG_WLAN_PRE80211 is not set
-# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
-
-#
-# Enable WiMAX (Networking options) to see the WiMAX drivers
-#
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET is not set
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_NET_FC is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_ISDN is not set
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-CONFIG_INPUT_FF_MEMLESS=m
-# CONFIG_INPUT_POLLDEV is not set
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# 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=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
-# CONFIG_SERIO_XILINX_XPS_PS2 is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_CONSOLE_TRANSLATIONS=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_VT_HW_CONSOLE_BINDING is not set
-CONFIG_DEVKMEM=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_NOZOMI is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=2
-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_8250_DETECT_IRQ=y
-CONFIG_SERIAL_8250_RSA=y
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_SERIAL_UARTLITE is not set
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-# CONFIG_SERIAL_OF_PLATFORM is not set
-CONFIG_UNIX98_PTYS=y
-# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_HVC_UDBG is not set
-# CONFIG_IPMI_HANDLER is not set
-CONFIG_HW_RANDOM=y
-CONFIG_NVRAM=y
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_TCG_TPM is not set
-CONFIG_DEVPORT=y
-CONFIG_I2C=y
-CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_CHARDEV is not set
-CONFIG_I2C_HELPER_AUTO=y
-
-#
-# I2C Hardware Bus support
-#
-
-#
-# PC SMBus host controller drivers
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_ISCH is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-
-#
-# I2C system bus drivers (mostly embedded / system-on-chip)
-#
-CONFIG_I2C_MPC=y
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_SIMTEC is not set
-
-#
-# External I2C/SMBus adapter drivers
-#
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_TINY_USB is not set
-
-#
-# Graphics adapter I2C/DDC channel drivers
-#
-# CONFIG_I2C_VOODOO3 is not set
-
-#
-# Other I2C/SMBus bus drivers
-#
-# CONFIG_I2C_PCA_PLATFORM is not set
-# CONFIG_I2C_STUB is not set
-
-#
-# Miscellaneous I2C Chip support
-#
-# CONFIG_DS1682 is not set
-# CONFIG_EEPROM_AT24 is not set
-CONFIG_EEPROM_LEGACY=y
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-# CONFIG_SPI is not set
-CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
-# CONFIG_W1 is not set
-# CONFIG_POWER_SUPPLY is not set
-# CONFIG_HWMON is not set
-# CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
-# CONFIG_WATCHDOG is not set
-CONFIG_SSB_POSSIBLE=y
-
-#
-# Sonics Silicon Backplane
-#
-# CONFIG_SSB is not set
-
-#
-# Multifunction device drivers
-#
-# CONFIG_MFD_CORE is not set
-# CONFIG_MFD_SM501 is not set
-# CONFIG_HTC_PASIC3 is not set
-# CONFIG_TWL4030_CORE is not set
-# CONFIG_MFD_TMIO is not set
-# CONFIG_PMIC_DA903X is not set
-# CONFIG_MFD_WM8400 is not set
-# CONFIG_MFD_WM8350_I2C is not set
-# CONFIG_MFD_PCF50633 is not set
-# CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-CONFIG_DVB_CORE=m
-CONFIG_VIDEO_MEDIA=m
-
-#
-# Multimedia drivers
-#
-# CONFIG_MEDIA_ATTACH is not set
-CONFIG_MEDIA_TUNER=m
-# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
-CONFIG_MEDIA_TUNER_SIMPLE=m
-CONFIG_MEDIA_TUNER_TDA8290=m
-CONFIG_MEDIA_TUNER_TDA9887=m
-CONFIG_MEDIA_TUNER_TEA5761=m
-CONFIG_MEDIA_TUNER_TEA5767=m
-CONFIG_MEDIA_TUNER_MT20XX=m
-CONFIG_MEDIA_TUNER_XC2028=m
-CONFIG_MEDIA_TUNER_XC5000=m
-# CONFIG_DVB_DYNAMIC_MINORS is not set
-CONFIG_DVB_CAPTURE_DRIVERS=y
-
-#
-# Supported SAA7146 based PCI Adapters
-#
-# CONFIG_TTPCI_EEPROM is not set
-# CONFIG_DVB_BUDGET_CORE is not set
-
-#
-# Supported USB Adapters
-#
-# CONFIG_DVB_USB is not set
-# CONFIG_DVB_TTUSB_BUDGET is not set
-# CONFIG_DVB_TTUSB_DEC is not set
-# CONFIG_DVB_SIANO_SMS1XXX is not set
-
-#
-# Supported FlexCopII (B2C2) Adapters
-#
-# CONFIG_DVB_B2C2_FLEXCOP is not set
-
-#
-# Supported BT878 Adapters
-#
-
-#
-# Supported Pluto2 Adapters
-#
-# CONFIG_DVB_PLUTO2 is not set
-
-#
-# Supported SDMC DM1105 Adapters
-#
-# CONFIG_DVB_DM1105 is not set
-
-#
-# Supported DVB Frontends
-#
-
-#
-# Customise DVB Frontends
-#
-# CONFIG_DVB_FE_CUSTOMISE is not set
-
-#
-# Multistandard (satellite) frontends
-#
-# CONFIG_DVB_STB0899 is not set
-# CONFIG_DVB_STB6100 is not set
-
-#
-# DVB-S (satellite) frontends
-#
-# CONFIG_DVB_CX24110 is not set
-# CONFIG_DVB_CX24123 is not set
-# CONFIG_DVB_MT312 is not set
-# CONFIG_DVB_S5H1420 is not set
-# CONFIG_DVB_STV0288 is not set
-# CONFIG_DVB_STB6000 is not set
-# CONFIG_DVB_STV0299 is not set
-# CONFIG_DVB_TDA8083 is not set
-# CONFIG_DVB_TDA10086 is not set
-# CONFIG_DVB_TDA8261 is not set
-# CONFIG_DVB_VES1X93 is not set
-# CONFIG_DVB_TUNER_ITD1000 is not set
-# CONFIG_DVB_TUNER_CX24113 is not set
-# CONFIG_DVB_TDA826X is not set
-# CONFIG_DVB_TUA6100 is not set
-# CONFIG_DVB_CX24116 is not set
-# CONFIG_DVB_SI21XX is not set
-
-#
-# DVB-T (terrestrial) frontends
-#
-# CONFIG_DVB_SP8870 is not set
-# CONFIG_DVB_SP887X is not set
-# CONFIG_DVB_CX22700 is not set
-# CONFIG_DVB_CX22702 is not set
-# CONFIG_DVB_DRX397XD is not set
-# CONFIG_DVB_L64781 is not set
-# CONFIG_DVB_TDA1004X is not set
-# CONFIG_DVB_NXT6000 is not set
-# CONFIG_DVB_MT352 is not set
-# CONFIG_DVB_ZL10353 is not set
-# CONFIG_DVB_DIB3000MB is not set
-# CONFIG_DVB_DIB3000MC is not set
-# CONFIG_DVB_DIB7000M is not set
-# CONFIG_DVB_DIB7000P is not set
-# CONFIG_DVB_TDA10048 is not set
-
-#
-# DVB-C (cable) frontends
-#
-# CONFIG_DVB_VES1820 is not set
-# CONFIG_DVB_TDA10021 is not set
-# CONFIG_DVB_TDA10023 is not set
-# CONFIG_DVB_STV0297 is not set
-
-#
-# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
-#
-# CONFIG_DVB_NXT200X is not set
-# CONFIG_DVB_OR51211 is not set
-# CONFIG_DVB_OR51132 is not set
-# CONFIG_DVB_BCM3510 is not set
-# CONFIG_DVB_LGDT330X is not set
-# CONFIG_DVB_LGDT3304 is not set
-# CONFIG_DVB_S5H1409 is not set
-# CONFIG_DVB_AU8522 is not set
-# CONFIG_DVB_S5H1411 is not set
-
-#
-# ISDB-T (terrestrial) frontends
-#
-# CONFIG_DVB_S921 is not set
-
-#
-# Digital terrestrial only tuners/PLL
-#
-# CONFIG_DVB_PLL is not set
-# CONFIG_DVB_TUNER_DIB0070 is not set
-
-#
-# SEC control devices for DVB-S
-#
-# CONFIG_DVB_LNBP21 is not set
-# CONFIG_DVB_ISL6405 is not set
-# CONFIG_DVB_ISL6421 is not set
-# CONFIG_DVB_LGS8GL5 is not set
-
-#
-# Tools to develop new frontends
-#
-# CONFIG_DVB_DUMMY_FE is not set
-# CONFIG_DVB_AF9013 is not set
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
-
-#
-# Graphics support
-#
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_VGASTATE is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=y
-# CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Console display driver support
-#
-CONFIG_VGA_CONSOLE=y
-# CONFIG_VGACON_SOFT_SCROLLBACK is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_SOUND=y
-CONFIG_SOUND_OSS_CORE=y
-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_HRTIMER is not set
-# CONFIG_SND_DYNAMIC_MINORS is not set
-# CONFIG_SND_SUPPORT_OLD_API is not set
-CONFIG_SND_VERBOSE_PROCFS=y
-# CONFIG_SND_VERBOSE_PRINTK is not set
-# CONFIG_SND_DEBUG is not set
-CONFIG_SND_VMASTER=y
-CONFIG_SND_AC97_CODEC=y
-CONFIG_SND_DRIVERS=y
-# 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
-# CONFIG_SND_AC97_POWER_SAVE is not set
-CONFIG_SND_PCI=y
-# CONFIG_SND_AD1889 is not set
-# CONFIG_SND_ALS300 is not set
-# CONFIG_SND_ALS4000 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_AW2 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_OXYGEN is not set
-# CONFIG_SND_CS4281 is not set
-# CONFIG_SND_CS46XX is not set
-# CONFIG_SND_CS5530 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_HIFIER is not set
-# CONFIG_SND_ICE1712 is not set
-# CONFIG_SND_ICE1724 is not set
-CONFIG_SND_INTEL8X0=y
-# 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_VIRTUOSO is not set
-# CONFIG_SND_VX222 is not set
-# CONFIG_SND_YMFPCI is not set
-CONFIG_SND_PPC=y
-CONFIG_SND_USB=y
-# CONFIG_SND_USB_AUDIO is not set
-# CONFIG_SND_USB_USX2Y is not set
-# CONFIG_SND_USB_CAIAQ is not set
-# CONFIG_SND_SOC is not set
-# CONFIG_SOUND_PRIME is not set
-CONFIG_AC97_BUS=y
-CONFIG_HID_SUPPORT=y
-CONFIG_HID=y
-# CONFIG_HID_DEBUG is not set
-# CONFIG_HIDRAW is not set
-
-#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-# CONFIG_HID_PID is not set
-# CONFIG_USB_HIDDEV is not set
-
-#
-# Special HID drivers
-#
-CONFIG_HID_COMPAT=y
-CONFIG_HID_A4TECH=y
-CONFIG_HID_APPLE=y
-CONFIG_HID_BELKIN=y
-CONFIG_HID_CHERRY=y
-CONFIG_HID_CHICONY=y
-CONFIG_HID_CYPRESS=y
-CONFIG_HID_EZKEY=y
-CONFIG_HID_GYRATION=y
-CONFIG_HID_LOGITECH=y
-# CONFIG_LOGITECH_FF is not set
-# CONFIG_LOGIRUMBLEPAD2_FF is not set
-CONFIG_HID_MICROSOFT=y
-CONFIG_HID_MONTEREY=y
-# CONFIG_HID_NTRIG is not set
-CONFIG_HID_PANTHERLORD=y
-# CONFIG_PANTHERLORD_FF is not set
-CONFIG_HID_PETALYNX=y
-CONFIG_HID_SAMSUNG=y
-CONFIG_HID_SONY=y
-CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
-# CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
-CONFIG_USB_SUPPORT=y
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
-
-#
-# Miscellaneous USB options
-#
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_DEVICE_CLASS=y
-# CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_OTG is not set
-# CONFIG_USB_OTG_WHITELIST is not set
-# CONFIG_USB_OTG_BLACKLIST_HUB is not set
-CONFIG_USB_MON=y
-# CONFIG_USB_WUSB is not set
-# CONFIG_USB_WUSB_CBAF is not set
-
-#
-# USB Host Controller Drivers
-#
-# CONFIG_USB_C67X00_HCD is not set
-CONFIG_USB_EHCI_HCD=y
-# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
-# CONFIG_USB_EHCI_FSL is not set
-CONFIG_USB_EHCI_HCD_PPC_OF=y
-# CONFIG_USB_OXU210HP_HCD is not set
-# CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_ISP1760_HCD is not set
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
-CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
-CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
-CONFIG_USB_OHCI_HCD_PCI=y
-CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
-CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
-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
-# CONFIG_USB_WHCI_HCD is not set
-# CONFIG_USB_HWA_HCD is not set
-
-#
-# USB Device Class drivers
-#
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
-# CONFIG_USB_WDM is not set
-# CONFIG_USB_TMC is not set
-
-#
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
-#
-
-#
-# see USB_STORAGE Help for more information
-#
-CONFIG_USB_STORAGE=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_ISD200 is not set
-# CONFIG_USB_STORAGE_USBAT is not set
-# CONFIG_USB_STORAGE_SDDR09 is not set
-# CONFIG_USB_STORAGE_SDDR55 is not set
-# CONFIG_USB_STORAGE_JUMPSHOT is not set
-# CONFIG_USB_STORAGE_ALAUDA is not set
-# CONFIG_USB_STORAGE_ONETOUCH is not set
-# CONFIG_USB_STORAGE_KARMA is not set
-# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
-# CONFIG_USB_LIBUSUAL is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_MICROTEK is not set
-
-#
-# USB port drivers
-#
-# CONFIG_USB_SERIAL is not set
-
-#
-# USB Miscellaneous drivers
-#
-# CONFIG_USB_EMI62 is not set
-# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_SEVSEG is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_LEGOTOWER is not set
-# CONFIG_USB_LCD is not set
-# CONFIG_USB_BERRY_CHARGE is not set
-# CONFIG_USB_LED is not set
-# CONFIG_USB_CYPRESS_CY7C63 is not set
-# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
-# CONFIG_USB_IDMOUSE is not set
-# CONFIG_USB_FTDI_ELAN is not set
-# CONFIG_USB_APPLEDISPLAY is not set
-# CONFIG_USB_SISUSBVGA is not set
-# CONFIG_USB_LD is not set
-# CONFIG_USB_TRANCEVIBRATOR is not set
-# CONFIG_USB_IOWARRIOR is not set
-# CONFIG_USB_TEST is not set
-# CONFIG_USB_ISIGHTFW is not set
-# CONFIG_USB_VST is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# OTG and related infrastructure
-#
-# CONFIG_UWB is not set
-# CONFIG_MMC is not set
-# CONFIG_MEMSTICK is not set
-# CONFIG_NEW_LEDS is not set
-# CONFIG_ACCESSIBILITY is not set
-# CONFIG_INFINIBAND is not set
-# CONFIG_EDAC is not set
-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_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
-# CONFIG_RTC_DRV_S35390A is not set
-# CONFIG_RTC_DRV_FM3130 is not set
-# CONFIG_RTC_DRV_RX8581 is not set
-
-#
-# SPI RTC drivers
-#
-
-#
-# Platform RTC drivers
-#
-CONFIG_RTC_DRV_CMOS=y
-# CONFIG_RTC_DRV_DS1286 is not set
-# CONFIG_RTC_DRV_DS1511 is not set
-# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_DS1742 is not set
-# CONFIG_RTC_DRV_STK17TA8 is not set
-# CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_M48T35 is not set
-# CONFIG_RTC_DRV_M48T59 is not set
-# CONFIG_RTC_DRV_BQ4802 is not set
-# CONFIG_RTC_DRV_V3020 is not set
-
-#
-# on-CPU RTC drivers
-#
-# CONFIG_RTC_DRV_PPC is not set
-CONFIG_DMADEVICES=y
-
-#
-# DMA Devices
-#
-CONFIG_FSL_DMA=y
-CONFIG_DMA_ENGINE=y
-
-#
-# DMA Clients
-#
-# CONFIG_NET_DMA is not set
-# CONFIG_DMATEST is not set
-# CONFIG_UIO is not set
-# CONFIG_STAGING 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=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4_FS is not set
-CONFIG_JBD=y
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_BTRFS_FS is not set
-CONFIG_DNOTIFY=y
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_FUSE_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=m
-CONFIG_UDF_NLS=y
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
-CONFIG_NTFS_FS=y
-# CONFIG_NTFS_DEBUG is not set
-# CONFIG_NTFS_RW is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_PROC_PAGE_MONITOR=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_POSIX_ACL is not set
-# CONFIG_HUGETLB_PAGE is not set
-# CONFIG_CONFIGFS_FS is not set
-CONFIG_MISC_FILESYSTEMS=y
-CONFIG_ADFS_FS=m
-# CONFIG_ADFS_FS_RW is not set
-CONFIG_AFFS_FS=m
-CONFIG_HFS_FS=m
-CONFIG_HFSPLUS_FS=m
-CONFIG_BEFS_FS=m
-# CONFIG_BEFS_DEBUG is not set
-CONFIG_BFS_FS=m
-CONFIG_EFS_FS=m
-CONFIG_CRAMFS=y
-# CONFIG_SQUASHFS is not set
-CONFIG_VXFS_FS=m
-# CONFIG_MINIX_FS is not set
-# CONFIG_OMFS_FS is not set
-CONFIG_HPFS_FS=m
-CONFIG_QNX4FS_FS=m
-# CONFIG_ROMFS_FS is not set
-CONFIG_SYSV_FS=m
-CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
-# CONFIG_UFS_DEBUG is not set
-CONFIG_NETWORK_FILESYSTEMS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_V4 is not set
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 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=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=y
-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
-CONFIG_NLS=y
-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=m
-# CONFIG_DLM is not set
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-CONFIG_GENERIC_FIND_LAST_BIT=y
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
-CONFIG_CRC_T10DIF=y
-CONFIG_CRC_ITU_T=m
-CONFIG_CRC32=y
-# CONFIG_CRC7 is not set
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
-CONFIG_HAS_DMA=y
-CONFIG_HAVE_LMB=y
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_WARN_DEPRECATED=y
-CONFIG_ENABLE_MUST_CHECK=y
-CONFIG_FRAME_WARN=1024
-# 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_DETECT_SOFTLOCKUP=y
-# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
-CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
-CONFIG_SCHED_DEBUG=y
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_OBJECTS is not set
-# CONFIG_SLUB_DEBUG_ON is not set
-# CONFIG_SLUB_STATS is not set
-# CONFIG_DEBUG_RT_MUTEXES is not set
-# CONFIG_RT_MUTEX_TESTER is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_MUTEXES 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_HIGHMEM is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_VM is not set
-# CONFIG_DEBUG_WRITECOUNT is not set
-# CONFIG_DEBUG_MEMORY_INIT is not set
-# CONFIG_DEBUG_LIST is not set
-# CONFIG_DEBUG_SG is not set
-# CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
-# CONFIG_RCU_TORTURE_TEST is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_BACKTRACE_SELF_TEST is not set
-# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
-# CONFIG_FAULT_INJECTION is not set
-# CONFIG_LATENCYTOP is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_HAVE_FUNCTION_TRACER=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
-# CONFIG_SAMPLES is not set
-CONFIG_HAVE_ARCH_KGDB=y
-# CONFIG_KGDB is not set
-CONFIG_PRINT_STACK_DEPTH=64
-# CONFIG_DEBUG_STACKOVERFLOW is not set
-# CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
-# CONFIG_CODE_PATCHING_SELFTEST is not set
-# CONFIG_FTR_FIXUP_SELFTEST is not set
-# CONFIG_MSI_BITMAP_SELFTEST is not set
-# CONFIG_XMON is not set
-# CONFIG_IRQSTACKS is not set
-# CONFIG_BDI_SWITCH is not set
-# CONFIG_PPC_EARLY_DEBUG is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-# CONFIG_SECURITYFS is not set
-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
-CONFIG_CRYPTO=y
-
-#
-# Crypto core or helper
-#
-# CONFIG_CRYPTO_FIPS is not set
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_ALGAPI2=y
-CONFIG_CRYPTO_AEAD=y
-CONFIG_CRYPTO_AEAD2=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_BLKCIPHER2=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_HASH2=y
-CONFIG_CRYPTO_RNG2=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_MANAGER2=y
-# CONFIG_CRYPTO_GF128MUL is not set
-# CONFIG_CRYPTO_NULL is not set
-# CONFIG_CRYPTO_CRYPTD is not set
-CONFIG_CRYPTO_AUTHENC=y
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Authenticated Encryption with Associated Data
-#
-# CONFIG_CRYPTO_CCM is not set
-# CONFIG_CRYPTO_GCM is not set
-# CONFIG_CRYPTO_SEQIV is not set
-
-#
-# Block modes
-#
-CONFIG_CRYPTO_CBC=y
-# CONFIG_CRYPTO_CTR is not set
-# CONFIG_CRYPTO_CTS is not set
-# CONFIG_CRYPTO_ECB is not set
-# CONFIG_CRYPTO_LRW is not set
-CONFIG_CRYPTO_PCBC=m
-# CONFIG_CRYPTO_XTS is not set
-
-#
-# Hash modes
-#
-CONFIG_CRYPTO_HMAC=y
-# CONFIG_CRYPTO_XCBC is not set
-
-#
-# Digest
-#
-CONFIG_CRYPTO_CRC32C=m
-# CONFIG_CRYPTO_MD4 is not set
-CONFIG_CRYPTO_MD5=y
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_RMD128 is not set
-# CONFIG_CRYPTO_RMD160 is not set
-# CONFIG_CRYPTO_RMD256 is not set
-# CONFIG_CRYPTO_RMD320 is not set
-CONFIG_CRYPTO_SHA1=m
-# CONFIG_CRYPTO_SHA256 is not set
-# CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_WP512 is not set
-
-#
-# Ciphers
-#
-# CONFIG_CRYPTO_AES is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-# CONFIG_CRYPTO_ARC4 is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_CAMELLIA is not set
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
-CONFIG_CRYPTO_DES=y
-# CONFIG_CRYPTO_FCRYPT is not set
-# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_SALSA20 is not set
-# CONFIG_CRYPTO_SEED is not set
-# CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_TEA is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-
-#
-# Compression
-#
-# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_LZO is not set
-
-#
-# Random Number Generation
-#
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_HW=y
-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
-CONFIG_CRYPTO_DEV_TALITOS=y
-# CONFIG_PPC_CLOCK is not set
-# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/configs/85xx/mpc8568mds_defconfig b/arch/powerpc/configs/85xx/mpc8568mds_defconfig
deleted file mode 100644
index 186c1010a135..000000000000
--- a/arch/powerpc/configs/85xx/mpc8568mds_defconfig
+++ /dev/null
@@ -1,1309 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc2
-# Mon Jan 26 15:36:10 2009
-#
-# CONFIG_PPC64 is not set
-
-#
-# Processor support
-#
-# CONFIG_6xx is not set
-CONFIG_PPC_85xx=y
-# CONFIG_PPC_8xx is not set
-# CONFIG_40x is not set
-# CONFIG_44x is not set
-# CONFIG_E200 is not set
-CONFIG_E500=y
-# CONFIG_PPC_E500MC is not set
-CONFIG_BOOKE=y
-CONFIG_FSL_BOOKE=y
-CONFIG_FSL_EMB_PERFMON=y
-# CONFIG_PHYS_64BIT is not set
-CONFIG_SPE=y
-CONFIG_PPC_MMU_NOHASH=y
-# CONFIG_PPC_MM_SLICES is not set
-# CONFIG_SMP is not set
-CONFIG_PPC32=y
-CONFIG_WORD_SIZE=32
-# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
-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_HAVE_SETUP_PER_CPU_AREA is not set
-CONFIG_IRQ_PER_CPU=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_HAVE_LATENCYTOP_SUPPORT=y
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_ARCH_HAS_ILOG2_U32=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
-CONFIG_PPC=y
-CONFIG_EARLY_PRINTK=y
-CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_OMIT_FRAME_POINTER=y
-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
-CONFIG_PPC_OF=y
-CONFIG_OF=y
-CONFIG_PPC_UDBG_16550=y
-# CONFIG_GENERIC_TBSYNC is not set
-CONFIG_AUDIT_ARCH=y
-CONFIG_GENERIC_BUG=y
-CONFIG_DEFAULT_UIMAGE=y
-# CONFIG_PPC_DCR_NATIVE is not set
-# CONFIG_PPC_DCR_MMIO is not set
-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_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_GROUP_SCHED=y
-# CONFIG_FAIR_GROUP_SCHED is not set
-# CONFIG_RT_GROUP_SCHED is not set
-CONFIG_USER_SCHED=y
-# CONFIG_CGROUP_SCHED is not set
-# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-# CONFIG_RELAY is not set
-# CONFIG_NAMESPACES 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 is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
-# CONFIG_EPOLL is not set
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
-CONFIG_SHMEM=y
-CONFIG_AIO=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_PCI_QUIRKS=y
-CONFIG_SLUB_DEBUG=y
-# CONFIG_SLAB is not set
-CONFIG_SLUB=y
-# CONFIG_SLOB is not set
-# CONFIG_PROFILING is not set
-CONFIG_HAVE_OPROFILE=y
-CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
-CONFIG_HAVE_IOREMAP_PROT=y
-CONFIG_HAVE_KPROBES=y
-CONFIG_HAVE_KRETPROBES=y
-CONFIG_HAVE_ARCH_TRACEHOOK=y
-# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
-CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
-CONFIG_BASE_SMALL=0
-CONFIG_MODULES=y
-# CONFIG_MODULE_FORCE_LOAD is not set
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_BLK_DEV_INTEGRITY is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
-# CONFIG_FREEZER is not set
-
-#
-# Platform support
-#
-# CONFIG_PPC_CELL is not set
-# CONFIG_PPC_CELL_NATIVE is not set
-# CONFIG_PQ2ADS is not set
-CONFIG_MPC85xx=y
-# CONFIG_MPC8540_ADS is not set
-# CONFIG_MPC8560_ADS is not set
-# CONFIG_MPC85xx_CDS is not set
-CONFIG_MPC85xx_MDS=y
-# CONFIG_MPC8536_DS is not set
-# CONFIG_MPC85xx_DS is not set
-# CONFIG_KSI8560 is not set
-# CONFIG_STX_GP3 is not set
-# CONFIG_TQM8540 is not set
-# CONFIG_TQM8541 is not set
-# CONFIG_TQM8548 is not set
-# CONFIG_TQM8555 is not set
-# CONFIG_TQM8560 is not set
-# CONFIG_SBC8548 is not set
-# CONFIG_SBC8560 is not set
-# CONFIG_IPIC is not set
-CONFIG_MPIC=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
-# CONFIG_PPC_RTAS is not set
-# CONFIG_MMIO_NVRAM is not set
-# 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_QUICC_ENGINE=y
-# CONFIG_QE_GPIO is not set
-# CONFIG_CPM2 is not set
-# CONFIG_FSL_ULI1575 is not set
-# CONFIG_MPC8xxx_GPIO is not set
-# CONFIG_SIMPLE_GPIO is not set
-
-#
-# Kernel options
-#
-# CONFIG_HIGHMEM is not set
-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
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
-CONFIG_SCHED_HRTICK=y
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-CONFIG_BINFMT_ELF=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-# CONFIG_HAVE_AOUT is not set
-# CONFIG_BINFMT_MISC is not set
-CONFIG_MATH_EMULATION=y
-# CONFIG_IOMMU_HELPER is not set
-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
-CONFIG_ARCH_HAS_WALK_MEMORY=y
-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_ARCH_POPULATES_NODE_MAP=y
-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_PAGEFLAGS_EXTENDED=y
-CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_MIGRATION=y
-# CONFIG_PHYS_ADDR_T_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
-CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
-CONFIG_PPC_4K_PAGES=y
-# CONFIG_PPC_16K_PAGES is not set
-# CONFIG_PPC_64K_PAGES is not set
-CONFIG_FORCE_MAX_ZONEORDER=11
-CONFIG_PROC_DEVICETREE=y
-# CONFIG_CMDLINE_BOOL is not set
-CONFIG_EXTRA_TARGETS=""
-# CONFIG_PM is not set
-CONFIG_SECCOMP=y
-CONFIG_ISA_DMA_API=y
-
-#
-# Bus options
-#
-CONFIG_ZONE_DMA=y
-CONFIG_PPC_INDIRECT_PCI=y
-CONFIG_FSL_SOC=y
-CONFIG_FSL_PCI=y
-CONFIG_PPC_PCI_CHOICE=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_SYSCALL=y
-# CONFIG_PCIEPORTBUS is not set
-CONFIG_ARCH_SUPPORTS_MSI=y
-# CONFIG_PCI_MSI is not set
-# CONFIG_PCI_LEGACY is not set
-# CONFIG_PCI_DEBUG is not set
-# CONFIG_PCI_STUB is not set
-# CONFIG_PCCARD is not set
-# CONFIG_HOTPLUG_PCI is not set
-# CONFIG_HAS_RAPIDIO is not set
-
-#
-# Advanced setup
-#
-# CONFIG_ADVANCED_OPTIONS is not set
-
-#
-# Default settings for advanced configuration options are used
-#
-CONFIG_LOWMEM_SIZE=0x30000000
-CONFIG_PAGE_OFFSET=0xc0000000
-CONFIG_KERNEL_START=0xc0000000
-CONFIG_PHYSICAL_START=0x00000000
-CONFIG_PHYSICAL_ALIGN=0x10000000
-CONFIG_TASK_SIZE=0xc0000000
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_COMPAT_NET_DEV_OPS=y
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
-# CONFIG_XFRM_SUB_POLICY is not set
-# CONFIG_XFRM_MIGRATE is not set
-# CONFIG_XFRM_STATISTICS is not set
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=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=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
-# CONFIG_INET_LRO is not set
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETWORK_SECMARK is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_IP_DCCP is not set
-# CONFIG_IP_SCTP is not set
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_NET_DSA is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_SCHED is not set
-# CONFIG_DCB is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_CAN is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
-CONFIG_WIRELESS=y
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_OLD_REGULATORY=y
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_WIMAX is not set
-# CONFIG_RFKILL is not set
-# CONFIG_NET_9P is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-# CONFIG_DEBUG_DRIVER is not set
-# CONFIG_DEBUG_DEVRES is not set
-# CONFIG_SYS_HYPERVISOR is not set
-# CONFIG_CONNECTOR is not set
-# CONFIG_MTD is not set
-CONFIG_OF_DEVICE=y
-CONFIG_OF_I2C=y
-# CONFIG_PARPORT is not set
-CONFIG_BLK_DEV=y
-# CONFIG_BLK_DEV_FD is not set
-# 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_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=32768
-# CONFIG_BLK_DEV_XIP is not set
-# CONFIG_CDROM_PKTCDVD is not set
-# CONFIG_ATA_OVER_ETH is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_MISC_DEVICES=y
-# CONFIG_PHANTOM is not set
-# CONFIG_EEPROM_93CX6 is not set
-# CONFIG_SGI_IOC4 is not set
-# CONFIG_TIFM_CORE is not set
-# CONFIG_ICS932S401 is not set
-# CONFIG_ENCLOSURE_SERVICES is not set
-# CONFIG_HP_ILO is not set
-# CONFIG_C2PORT is not set
-CONFIG_HAVE_IDE=y
-# CONFIG_IDE 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=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-# CONFIG_BLK_DEV_SD is not set
-# 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_LIBSAS is not set
-# CONFIG_SCSI_SRP_ATTRS is not set
-CONFIG_SCSI_LOWLEVEL=y
-# CONFIG_ISCSI_TCP is not set
-# CONFIG_SCSI_CXGB3_ISCSI is not set
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_AIC94XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_ARCMSR is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_LIBFC is not set
-# CONFIG_FCOE is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
-# CONFIG_SCSI_STEX is not set
-# CONFIG_SCSI_SYM53C8XX_2 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_SCSI_DH is not set
-# CONFIG_ATA is not set
-# CONFIG_MD is not set
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# Enable only one of the two stacks, unless you know what you are doing
-#
-# CONFIG_FIREWIRE is not set
-# CONFIG_IEEE1394 is not set
-# CONFIG_I2O is not set
-# CONFIG_MACINTOSH_DRIVERS is not set
-CONFIG_NETDEVICES=y
-# 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_ARCNET is not set
-CONFIG_PHYLIB=y
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=y
-# CONFIG_DAVICOM_PHY is not set
-# CONFIG_QSEMI_PHY is not set
-# CONFIG_LXT_PHY is not set
-# CONFIG_CICADA_PHY is not set
-# CONFIG_VITESSE_PHY is not set
-# CONFIG_SMSC_PHY is not set
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_ICPLUS_PHY is not set
-# CONFIG_REALTEK_PHY is not set
-# CONFIG_NATIONAL_PHY is not set
-# CONFIG_STE10XP is not set
-# CONFIG_LSI_ET1011C_PHY is not set
-# CONFIG_FIXED_PHY is not set
-# CONFIG_MDIO_BITBANG is not set
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# 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_ZMII is not set
-# CONFIG_IBM_NEW_EMAC_RGMII is not set
-# CONFIG_IBM_NEW_EMAC_TAH is not set
-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
-# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
-# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
-# CONFIG_NET_PCI is not set
-# CONFIG_B44 is not set
-# CONFIG_ATL2 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_IP1000 is not set
-# CONFIG_IGB is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_GIANFAR=y
-# CONFIG_UCC_GETH is not set
-# CONFIG_QLA3XXX is not set
-# CONFIG_ATL1 is not set
-# CONFIG_ATL1E is not set
-# CONFIG_JME is not set
-CONFIG_NETDEV_10000=y
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3_DEPENDS=y
-# CONFIG_CHELSIO_T3 is not set
-# CONFIG_ENIC is not set
-# CONFIG_IXGBE is not set
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-# CONFIG_NETXEN_NIC is not set
-# CONFIG_NIU is not set
-# CONFIG_MLX4_EN is not set
-# CONFIG_MLX4_CORE is not set
-# CONFIG_TEHUTI is not set
-# CONFIG_BNX2X is not set
-# CONFIG_QLGE is not set
-# CONFIG_SFC is not set
-# CONFIG_TR is not set
-
-#
-# Wireless LAN
-#
-# CONFIG_WLAN_PRE80211 is not set
-# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
-
-#
-# Enable WiMAX (Networking options) to see the WiMAX drivers
-#
-# 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_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_ISDN is not set
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-# CONFIG_INPUT_POLLDEV is not set
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# 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 is not set
-CONFIG_DEVKMEM=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_NOZOMI is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_SERIAL_UARTLITE is not set
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-# CONFIG_SERIAL_OF_PLATFORM is not set
-# CONFIG_SERIAL_QE is not set
-CONFIG_UNIX98_PTYS=y
-# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_HVC_UDBG is not set
-# CONFIG_IPMI_HANDLER is not set
-CONFIG_HW_RANDOM=y
-# CONFIG_NVRAM is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_TCG_TPM is not set
-CONFIG_DEVPORT=y
-CONFIG_I2C=y
-CONFIG_I2C_BOARDINFO=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_HELPER_AUTO=y
-
-#
-# I2C Hardware Bus support
-#
-
-#
-# PC SMBus host controller drivers
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_ISCH is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-
-#
-# I2C system bus drivers (mostly embedded / system-on-chip)
-#
-CONFIG_I2C_MPC=y
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_SIMTEC is not set
-
-#
-# External I2C/SMBus adapter drivers
-#
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_TAOS_EVM is not set
-
-#
-# Graphics adapter I2C/DDC channel drivers
-#
-# CONFIG_I2C_VOODOO3 is not set
-
-#
-# Other I2C/SMBus bus drivers
-#
-# CONFIG_I2C_PCA_PLATFORM is not set
-# CONFIG_I2C_STUB is not set
-
-#
-# Miscellaneous I2C Chip support
-#
-# CONFIG_DS1682 is not set
-# CONFIG_EEPROM_AT24 is not set
-# CONFIG_EEPROM_LEGACY is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-# CONFIG_SPI is not set
-CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
-# CONFIG_W1 is not set
-# CONFIG_POWER_SUPPLY is not set
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_AD7414 is not set
-# CONFIG_SENSORS_AD7418 is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1029 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ADT7462 is not set
-# CONFIG_SENSORS_ADT7470 is not set
-# CONFIG_SENSORS_ADT7473 is not set
-# CONFIG_SENSORS_ADT7475 is not set
-# CONFIG_SENSORS_ATXP1 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_I5K_AMB is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_F71882FG is not set
-# CONFIG_SENSORS_F75375S is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_LM93 is not set
-# CONFIG_SENSORS_LTC4245 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_MAX6650 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_SIS5595 is not set
-# CONFIG_SENSORS_DME1737 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47M192 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_ADS7828 is not set
-# CONFIG_SENSORS_THMC50 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_SENSORS_VT8231 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83791D is not set
-# CONFIG_SENSORS_W83792D is not set
-# CONFIG_SENSORS_W83793 is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83L786NG is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
-# CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_ALIM7101_WDT is not set
-# CONFIG_BOOKE_WDT is not set
-
-#
-# PCI-based Watchdog Cards
-#
-# CONFIG_PCIPCWATCHDOG is not set
-# CONFIG_WDTPCI is not set
-CONFIG_SSB_POSSIBLE=y
-
-#
-# Sonics Silicon Backplane
-#
-# CONFIG_SSB is not set
-
-#
-# Multifunction device drivers
-#
-# CONFIG_MFD_CORE is not set
-# CONFIG_MFD_SM501 is not set
-# CONFIG_HTC_PASIC3 is not set
-# CONFIG_TWL4030_CORE is not set
-# CONFIG_MFD_TMIO is not set
-# CONFIG_PMIC_DA903X is not set
-# CONFIG_MFD_WM8400 is not set
-# CONFIG_MFD_WM8350_I2C is not set
-# CONFIG_MFD_PCF50633 is not set
-# CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-
-#
-# 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_SOUND is not set
-CONFIG_HID_SUPPORT=y
-CONFIG_HID=y
-# CONFIG_HID_DEBUG is not set
-# CONFIG_HIDRAW is not set
-# CONFIG_HID_PID is not set
-
-#
-# Special HID drivers
-#
-CONFIG_HID_COMPAT=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
-# CONFIG_USB_OTG_WHITELIST is not set
-# CONFIG_USB_OTG_BLACKLIST_HUB is not set
-
-#
-# Enable Host or Gadget support to see Inventra options
-#
-
-#
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# OTG and related infrastructure
-#
-# CONFIG_UWB is not set
-# CONFIG_MMC is not set
-# CONFIG_MEMSTICK is not set
-# CONFIG_NEW_LEDS is not set
-# CONFIG_ACCESSIBILITY is not set
-# CONFIG_INFINIBAND is not set
-# CONFIG_EDAC is not set
-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_DS1374=y
-# 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
-# CONFIG_RTC_DRV_S35390A is not set
-# CONFIG_RTC_DRV_FM3130 is not set
-# CONFIG_RTC_DRV_RX8581 is not set
-
-#
-# SPI RTC drivers
-#
-
-#
-# Platform RTC drivers
-#
-# CONFIG_RTC_DRV_CMOS is not set
-# CONFIG_RTC_DRV_DS1286 is not set
-# CONFIG_RTC_DRV_DS1511 is not set
-# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_DS1742 is not set
-# CONFIG_RTC_DRV_STK17TA8 is not set
-# CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_M48T35 is not set
-# CONFIG_RTC_DRV_M48T59 is not set
-# CONFIG_RTC_DRV_BQ4802 is not set
-# CONFIG_RTC_DRV_V3020 is not set
-
-#
-# on-CPU RTC drivers
-#
-# CONFIG_RTC_DRV_PPC is not set
-# CONFIG_DMADEVICES is not set
-# CONFIG_UIO is not set
-# CONFIG_STAGING 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=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4_FS is not set
-CONFIG_JBD=y
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
-# CONFIG_XFS_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_BTRFS_FS is not set
-CONFIG_DNOTIFY=y
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS 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_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_PROC_PAGE_MONITOR=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_POSIX_ACL is not set
-# CONFIG_HUGETLB_PAGE is not set
-# CONFIG_CONFIGFS_FS is not set
-CONFIG_MISC_FILESYSTEMS=y
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_SQUASHFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_OMFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-CONFIG_NETWORK_FILESYSTEMS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-# CONFIG_NFSD is not set
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 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=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 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
-# CONFIG_NLS is not set
-# CONFIG_DLM is not set
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-CONFIG_GENERIC_FIND_LAST_BIT=y
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
-# CONFIG_CRC_T10DIF is not set
-# CONFIG_CRC_ITU_T 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
-CONFIG_HAVE_LMB=y
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_WARN_DEPRECATED=y
-CONFIG_ENABLE_MUST_CHECK=y
-CONFIG_FRAME_WARN=1024
-# 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_DETECT_SOFTLOCKUP=y
-# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
-CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
-CONFIG_SCHED_DEBUG=y
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_OBJECTS is not set
-# CONFIG_SLUB_DEBUG_ON is not set
-# CONFIG_SLUB_STATS is not set
-# CONFIG_DEBUG_RT_MUTEXES is not set
-# CONFIG_RT_MUTEX_TESTER is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_MUTEXES 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_VM is not set
-# CONFIG_DEBUG_WRITECOUNT is not set
-# CONFIG_DEBUG_MEMORY_INIT is not set
-# CONFIG_DEBUG_LIST is not set
-# CONFIG_DEBUG_SG is not set
-# CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
-# CONFIG_RCU_TORTURE_TEST is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_BACKTRACE_SELF_TEST is not set
-# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
-# CONFIG_FAULT_INJECTION is not set
-# CONFIG_LATENCYTOP is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_HAVE_FUNCTION_TRACER=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
-# CONFIG_SAMPLES is not set
-CONFIG_HAVE_ARCH_KGDB=y
-# CONFIG_KGDB is not set
-CONFIG_PRINT_STACK_DEPTH=64
-# CONFIG_DEBUG_STACKOVERFLOW is not set
-# CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
-# CONFIG_CODE_PATCHING_SELFTEST is not set
-# CONFIG_FTR_FIXUP_SELFTEST is not set
-# CONFIG_MSI_BITMAP_SELFTEST is not set
-# CONFIG_XMON is not set
-# CONFIG_IRQSTACKS is not set
-# CONFIG_BDI_SWITCH is not set
-CONFIG_PPC_EARLY_DEBUG=y
-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
-# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
-# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
-# CONFIG_PPC_EARLY_DEBUG_44x is not set
-# CONFIG_PPC_EARLY_DEBUG_40x is not set
-# CONFIG_PPC_EARLY_DEBUG_CPM is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-# CONFIG_SECURITYFS is not set
-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
-CONFIG_CRYPTO=y
-
-#
-# Crypto core or helper
-#
-# CONFIG_CRYPTO_FIPS is not set
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_ALGAPI2=y
-CONFIG_CRYPTO_AEAD2=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_BLKCIPHER2=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_HASH2=y
-CONFIG_CRYPTO_RNG2=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_MANAGER2=y
-# CONFIG_CRYPTO_GF128MUL is not set
-# CONFIG_CRYPTO_NULL is not set
-# CONFIG_CRYPTO_CRYPTD is not set
-# CONFIG_CRYPTO_AUTHENC is not set
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Authenticated Encryption with Associated Data
-#
-# CONFIG_CRYPTO_CCM is not set
-# CONFIG_CRYPTO_GCM is not set
-# CONFIG_CRYPTO_SEQIV is not set
-
-#
-# Block modes
-#
-CONFIG_CRYPTO_CBC=y
-# CONFIG_CRYPTO_CTR is not set
-# CONFIG_CRYPTO_CTS is not set
-CONFIG_CRYPTO_ECB=m
-# CONFIG_CRYPTO_LRW is not set
-CONFIG_CRYPTO_PCBC=m
-# CONFIG_CRYPTO_XTS is not set
-
-#
-# Hash modes
-#
-# CONFIG_CRYPTO_HMAC is not set
-# CONFIG_CRYPTO_XCBC is not set
-
-#
-# Digest
-#
-# CONFIG_CRYPTO_CRC32C is not set
-# CONFIG_CRYPTO_MD4 is not set
-CONFIG_CRYPTO_MD5=y
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_RMD128 is not set
-# CONFIG_CRYPTO_RMD160 is not set
-# CONFIG_CRYPTO_RMD256 is not set
-# CONFIG_CRYPTO_RMD320 is not set
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-# CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_WP512 is not set
-
-#
-# Ciphers
-#
-# CONFIG_CRYPTO_AES is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-# CONFIG_CRYPTO_ARC4 is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_CAMELLIA is not set
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
-CONFIG_CRYPTO_DES=y
-# CONFIG_CRYPTO_FCRYPT is not set
-# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_SALSA20 is not set
-# CONFIG_CRYPTO_SEED is not set
-# CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_TEA is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-
-#
-# Compression
-#
-# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_LZO is not set
-
-#
-# Random Number Generation
-#
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_HW=y
-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
-# CONFIG_CRYPTO_DEV_TALITOS is not set
-# CONFIG_PPC_CLOCK is not set
-CONFIG_PPC_LIB_RHEAP=y
-# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/configs/85xx/tqm8548_defconfig b/arch/powerpc/configs/85xx/tqm8548_defconfig
index 0bc45975911a..43030fea2eee 100644
--- a/arch/powerpc/configs/85xx/tqm8548_defconfig
+++ b/arch/powerpc/configs/85xx/tqm8548_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc2
-# Mon Jan 26 15:36:20 2009
+# Linux kernel version: 2.6.29-rc7
+# Mon Mar 16 09:03:28 2009
#
# CONFIG_PPC64 is not set
@@ -22,6 +22,7 @@ CONFIG_FSL_EMB_PERFMON=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
CONFIG_PPC_MMU_NOHASH=y
+CONFIG_PPC_BOOK3E_MMU=y
# CONFIG_PPC_MM_SLICES is not set
# CONFIG_SMP is not set
CONFIG_PPC32=y
@@ -75,6 +76,15 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
CONFIG_GROUP_SCHED=y
@@ -152,11 +162,6 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -202,7 +207,7 @@ CONFIG_MPIC=y
#
# Kernel options
#
-# CONFIG_HIGHMEM is not set
+CONFIG_HIGHMEM=y
CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
@@ -244,6 +249,7 @@ CONFIG_UNEVICTABLE_LRU=y
CONFIG_PPC_4K_PAGES=y
# CONFIG_PPC_16K_PAGES is not set
# CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -259,6 +265,7 @@ CONFIG_ZONE_DMA=y
CONFIG_PPC_INDIRECT_PCI=y
CONFIG_FSL_SOC=y
CONFIG_FSL_PCI=y
+CONFIG_FSL_LBC=y
CONFIG_PPC_PCI_CHOICE=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
@@ -284,10 +291,11 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# Default settings for advanced configuration options are used
#
CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_LOWMEM_CAM_NUM=3
CONFIG_PAGE_OFFSET=0xc0000000
CONFIG_KERNEL_START=0xc0000000
CONFIG_PHYSICAL_START=0x00000000
-CONFIG_PHYSICAL_ALIGN=0x10000000
+CONFIG_PHYSICAL_ALIGN=0x04000000
CONFIG_TASK_SIZE=0xc0000000
CONFIG_NET=y
@@ -363,12 +371,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
-CONFIG_WIRELESS=y
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_OLD_REGULATORY=y
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+# CONFIG_WIRELESS is not set
# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -471,27 +474,18 @@ CONFIG_MTD_NAND_IDS=y
# CONFIG_MTD_NAND_NANDSIM is not set
# CONFIG_MTD_NAND_PLATFORM is not set
# CONFIG_MTD_NAND_FSL_ELBC is not set
-# CONFIG_MTD_NAND_FSL_UPM is not set
+CONFIG_MTD_NAND_FSL_UPM=y
# CONFIG_MTD_ONENAND is not set
#
# LPDDR flash memory drivers
#
# CONFIG_MTD_LPDDR is not set
-# CONFIG_MTD_QINFO_PROBE is not set
#
# UBI - Unsorted block images
#
-CONFIG_MTD_UBI=m
-CONFIG_MTD_UBI_WL_THRESHOLD=4096
-CONFIG_MTD_UBI_BEB_RESERVE=1
-# CONFIG_MTD_UBI_GLUEBI is not set
-
-#
-# UBI debugging options
-#
-# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_MTD_UBI is not set
CONFIG_OF_DEVICE=y
CONFIG_OF_I2C=y
# CONFIG_PARPORT is not set
@@ -515,69 +509,21 @@ CONFIG_BLK_DEV_RAM_SIZE=32768
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
-CONFIG_IDE=y
-
-#
-# Please see Documentation/ide/ide.txt for help/info on IDE drives
-#
-CONFIG_IDE_TIMINGS=y
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_IDE_GD=y
-CONFIG_IDE_GD_ATA=y
-# CONFIG_IDE_GD_ATAPI is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-CONFIG_IDE_PROC_FS=y
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_PLATFORM is not set
-CONFIG_BLK_DEV_IDEDMA_SFF=y
-
-#
-# PCI IDE chipsets support
-#
-CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_IDEPCI_PCIBUS_ORDER=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
-CONFIG_BLK_DEV_GENERIC=y
-# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-# CONFIG_BLK_DEV_CMD64X is not set
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_JMICRON is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-# CONFIG_BLK_DEV_IT8172 is not set
-# CONFIG_BLK_DEV_IT8213 is not set
-# CONFIG_BLK_DEV_IT821X is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-CONFIG_BLK_DEV_VIA82CXXX=y
-# CONFIG_BLK_DEV_TC86C001 is not set
-CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDE is not set
#
# SCSI device support
@@ -650,7 +596,7 @@ CONFIG_MII=y
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
-CONFIG_E1000=y
+# CONFIG_E1000 is not set
# CONFIG_E1000E is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
@@ -668,6 +614,7 @@ CONFIG_GIANFAR=y
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
@@ -835,8 +782,6 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_EEPROM_AT24 is not set
-# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -975,26 +920,7 @@ CONFIG_HID=y
# Special HID drivers
#
CONFIG_HID_COMPAT=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
-# CONFIG_USB_OTG_WHITELIST is not set
-# CONFIG_USB_OTG_BLACKLIST_HUB is not set
-
-#
-# Enable Host or Gadget support to see Inventra options
-#
-
-#
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# OTG and related infrastructure
-#
+# CONFIG_USB_SUPPORT is not set
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1064,16 +990,9 @@ CONFIG_RTC_DRV_DS1307=y
#
# 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_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
# CONFIG_EXT4_FS is not set
-CONFIG_JBD=y
-CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
@@ -1122,8 +1041,17 @@ CONFIG_MISC_FILESYSTEMS=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_UBIFS_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_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
@@ -1184,6 +1112,8 @@ CONFIG_GENERIC_FIND_LAST_BIT=y
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
@@ -1219,6 +1149,7 @@ 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_HIGHMEM is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_VM is not set
@@ -1236,6 +1167,7 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
diff --git a/arch/powerpc/configs/mpc5200_defconfig b/arch/powerpc/configs/mpc5200_defconfig
index af0cd55605d0..aaa4416660e9 100644
--- a/arch/powerpc/configs/mpc5200_defconfig
+++ b/arch/powerpc/configs/mpc5200_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc3
-# Fri Feb 6 09:48:53 2009
+# Linux kernel version: 2.6.30-rc2
+# Mon Apr 20 11:06:25 2009
#
# CONFIG_PPC64 is not set
@@ -14,6 +14,7 @@ CONFIG_6xx=y
# CONFIG_40x is not set
# CONFIG_44x is not set
# CONFIG_E200 is not set
+CONFIG_PPC_BOOK3S=y
CONFIG_PPC_FPU=y
# CONFIG_ALTIVEC is not set
CONFIG_PPC_STD_MMU=y
@@ -39,6 +40,7 @@ CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_GPIO=y
# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
@@ -55,6 +57,7 @@ CONFIG_DEFAULT_UIMAGE=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
# CONFIG_PPC_DCR_NATIVE is not set
# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -91,19 +94,22 @@ CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
CONFIG_EMBEDDED=y
# CONFIG_SYSCTL_SYSCALL is not set
# CONFIG_KALLSYMS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -113,10 +119,12 @@ CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_PCI_QUIRKS=y
CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -124,6 +132,7 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -136,7 +145,6 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -157,8 +165,6 @@ CONFIG_FREEZER=y
#
# Platform support
#
-CONFIG_PPC_MULTIPLATFORM=y
-CONFIG_CLASSIC32=y
# CONFIG_PPC_CHRP is not set
# CONFIG_MPC5121_ADS is not set
# CONFIG_MPC5121_GENERIC is not set
@@ -166,8 +172,9 @@ CONFIG_PPC_MPC52xx=y
CONFIG_PPC_MPC5200_SIMPLE=y
CONFIG_PPC_EFIKA=y
CONFIG_PPC_LITE5200=y
+CONFIG_PPC_MEDIA5200=y
CONFIG_PPC_MPC5200_BUGFIX=y
-# CONFIG_PPC_MPC5200_GPIO is not set
+CONFIG_PPC_MPC5200_GPIO=y
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
@@ -176,7 +183,9 @@ CONFIG_PPC_MPC5200_BUGFIX=y
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_86xx is not set
# CONFIG_EMBEDDED6xx is not set
+# CONFIG_AMIGAONE is not set
CONFIG_PPC_NATIVE=y
+CONFIG_PPC_OF_BOOT_TRAMPOLINE=y
# CONFIG_UDBG_RTAS_CONSOLE is not set
# CONFIG_IPIC is not set
# CONFIG_MPIC is not set
@@ -241,9 +250,12 @@ CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_PPC_4K_PAGES=y
# CONFIG_PPC_16K_PAGES is not set
# CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -272,6 +284,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -294,7 +307,6 @@ CONFIG_NET=y
#
# Networking options
#
-CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -350,6 +362,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
# CONFIG_DCB is not set
@@ -362,7 +375,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
@@ -388,12 +400,9 @@ CONFIG_MTD=y
CONFIG_MTD_CONCAT=y
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_TESTS is not set
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
-# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
-# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
-# CONFIG_MTD_OF_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
# CONFIG_MTD_AR7_PARTS is not set
#
@@ -447,6 +456,8 @@ CONFIG_MTD_PHYSMAP_OF=y
# Self-contained MTD device drivers
#
# CONFIG_MTD_PMC551 is not set
+# 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
@@ -465,14 +476,23 @@ CONFIG_MTD_PHYSMAP_OF=y
# LPDDR flash memory drivers
#
# CONFIG_MTD_LPDDR is not set
-# CONFIG_MTD_QINFO_PROBE is not set
#
# UBI - Unsorted block images
#
-# CONFIG_MTD_UBI is not set
+CONFIG_MTD_UBI=m
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
CONFIG_OF_DEVICE=y
+CONFIG_OF_GPIO=y
CONFIG_OF_I2C=y
+CONFIG_OF_SPI=y
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_FD is not set
@@ -500,12 +520,14 @@ CONFIG_MISC_DEVICES=y
# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_ISL29003 is not set
# CONFIG_C2PORT is not set
#
# EEPROM support
#
CONFIG_EEPROM_AT24=y
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_EEPROM_LEGACY is not set
# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
@@ -564,9 +586,11 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
@@ -589,6 +613,7 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
@@ -666,6 +691,7 @@ CONFIG_PATA_PLATFORM=y
# CONFIG_I2O is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -699,6 +725,9 @@ CONFIG_NET_ETHERNET=y
# CONFIG_SUNGEM is not set
# CONFIG_CASSINI is not set
# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -722,7 +751,6 @@ CONFIG_FEC_MPC52xx_MDIO=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
#
# Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -802,6 +830,7 @@ CONFIG_DEVKMEM=y
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_MAX3100 is not set
# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
@@ -854,6 +883,7 @@ CONFIG_I2C_ALGOBIT=y
#
# I2C system bus drivers (mostly embedded / system-on-chip)
#
+# CONFIG_I2C_GPIO is not set
CONFIG_I2C_MPC=y
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_SIMTEC is not set
@@ -883,22 +913,63 @@ CONFIG_I2C_MPC=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
-# CONFIG_SPI is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_MPC52xx_PSC=m
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=m
+# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+# CONFIG_GPIO_BT8XX is not set
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_AD7414 is not set
# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
@@ -915,10 +986,12 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_F71882FG is not set
# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A 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
@@ -929,11 +1002,16 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_MAX1111 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_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_DME1737 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
@@ -952,6 +1030,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83L786NG is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
@@ -989,6 +1068,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
@@ -1084,9 +1164,13 @@ CONFIG_FB_RADEON_BACKLIGHT=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LCD_CLASS_DEVICE=m
+# CONFIG_LCD_LTV350QV is not set
# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_TDO24M is not set
+# CONFIG_LCD_VGG2432A4 is not set
# CONFIG_LCD_PLATFORM is not set
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_BACKLIGHT_GENERIC=y
@@ -1127,15 +1211,17 @@ CONFIG_USB_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
# CONFIG_HID_APPLE is not set
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
# CONFIG_HID_CHICONY is not set
CONFIG_HID_CYPRESS=y
+# CONFIG_DRAGONRISE_FF is not set
CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_KENSINGTON is not set
# CONFIG_HID_LOGITECH is not set
# CONFIG_HID_MICROSOFT is not set
# CONFIG_HID_MONTEREY is not set
@@ -1204,11 +1290,11 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
#
#
-# see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -1250,7 +1336,6 @@ CONFIG_USB_STORAGE=y
# 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
@@ -1265,6 +1350,8 @@ CONFIG_USB_STORAGE=y
#
# OTG and related infrastructure
#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1317,6 +1404,13 @@ CONFIG_RTC_DRV_DS1307=y
#
# SPI RTC drivers
#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
#
# Platform RTC drivers
@@ -1336,8 +1430,9 @@ CONFIG_RTC_DRV_DS1307=y
#
# on-CPU RTC drivers
#
-# CONFIG_RTC_DRV_PPC is not set
+# CONFIG_RTC_DRV_GENERIC is not set
# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
@@ -1348,6 +1443,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -1370,6 +1466,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -1416,6 +1517,12 @@ CONFIG_JFFS2_ZLIB=y
# CONFIG_JFFS2_LZO is not set
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=m
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
CONFIG_CRAMFS=y
# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
@@ -1426,6 +1533,7 @@ CONFIG_CRAMFS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -1438,7 +1546,6 @@ CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1493,6 +1600,7 @@ CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
# CONFIG_DLM is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
@@ -1500,7 +1608,7 @@ CONFIG_NLS_ISO8859_1=y
CONFIG_BITREVERSE=y
CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
+CONFIG_CRC16=m
# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
@@ -1508,11 +1616,14 @@ CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=m
+CONFIG_DECOMPRESS_GZIP=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
#
# Kernel hacking
@@ -1530,6 +1641,9 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1558,9 +1672,12 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -1568,17 +1685,19 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_CODE_PATCHING_SELFTEST is not set
# CONFIG_FTR_FIXUP_SELFTEST is not set
# CONFIG_MSI_BITMAP_SELFTEST is not set
@@ -1609,10 +1728,12 @@ CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_AUTHENC is not set
# CONFIG_CRYPTO_TEST is not set
@@ -1680,8 +1801,9 @@ CONFIG_CRYPTO_DES=y
#
# Compression
#
-# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=m
#
# Random Number Generation
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig
index fb08819d7cc4..c162724fed4f 100644
--- a/arch/powerpc/configs/mpc85xx_defconfig
+++ b/arch/powerpc/configs/mpc85xx_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc2
-# Mon Jan 26 15:35:37 2009
+# Linux kernel version: 2.6.30-rc2
+# Tue Apr 21 15:40:23 2009
#
# CONFIG_PPC64 is not set
@@ -22,6 +22,7 @@ CONFIG_FSL_EMB_PERFMON=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
CONFIG_PPC_MMU_NOHASH=y
+CONFIG_PPC_BOOK3E_MMU=y
# CONFIG_PPC_MM_SLICES is not set
# CONFIG_SMP is not set
CONFIG_PPC32=y
@@ -59,6 +60,7 @@ CONFIG_GENERIC_BUG=y
CONFIG_DEFAULT_UIMAGE=y
# CONFIG_PPC_DCR_NATIVE is not set
# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -73,11 +75,21 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
CONFIG_AUDIT=y
# CONFIG_AUDITSYSCALL is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
@@ -93,22 +105,24 @@ CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_STRIP_GENERATED=y
CONFIG_KALLSYMS_EXTRA_PASS=y
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -118,10 +132,12 @@ CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_PCI_QUIRKS=y
CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -130,6 +146,7 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -142,7 +159,6 @@ CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
CONFIG_LBD=y
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -158,11 +174,6 @@ CONFIG_IOSCHED_CFQ=y
CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -178,8 +189,9 @@ CONFIG_MPC85xx_CDS=y
CONFIG_MPC85xx_MDS=y
CONFIG_MPC8536_DS=y
CONFIG_MPC85xx_DS=y
+CONFIG_SOCRATES=y
CONFIG_KSI8560=y
-# CONFIG_STX_GP3 is not set
+CONFIG_STX_GP3=y
CONFIG_TQM8540=y
CONFIG_TQM8541=y
CONFIG_TQM8548=y
@@ -200,11 +212,11 @@ CONFIG_PPC_I8259=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
CONFIG_QUICC_ENGINE=y
-# CONFIG_QE_GPIO is not set
+CONFIG_QE_GPIO=y
CONFIG_CPM2=y
CONFIG_FSL_ULI1575=y
CONFIG_CPM=y
-# CONFIG_MPC8xxx_GPIO is not set
+CONFIG_MPC8xxx_GPIO=y
# CONFIG_SIMPLE_GPIO is not set
#
@@ -249,9 +261,12 @@ CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_PPC_4K_PAGES=y
# CONFIG_PPC_16K_PAGES is not set
# CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -278,6 +293,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -291,17 +307,17 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# Default settings for advanced configuration options are used
#
CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_LOWMEM_CAM_NUM=3
CONFIG_PAGE_OFFSET=0xc0000000
CONFIG_KERNEL_START=0xc0000000
CONFIG_PHYSICAL_START=0x00000000
-CONFIG_PHYSICAL_ALIGN=0x10000000
+CONFIG_PHYSICAL_ALIGN=0x04000000
CONFIG_TASK_SIZE=0xc0000000
CONFIG_NET=y
#
# Networking options
#
-CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -389,6 +405,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
# CONFIG_DCB is not set
@@ -401,7 +418,6 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
CONFIG_FIB_RULES=y
CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
@@ -456,13 +472,20 @@ CONFIG_BLK_DEV_RAM_SIZE=131072
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_ISL29003 is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+CONFIG_EEPROM_LEGACY=y
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -521,9 +544,11 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
@@ -546,6 +571,7 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
@@ -622,6 +648,7 @@ CONFIG_PATA_ALI=y
# CONFIG_I2O is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_DUMMY=y
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -634,11 +661,11 @@ CONFIG_PHYLIB=y
#
# MII PHY device drivers
#
-# CONFIG_MARVELL_PHY is not set
-# CONFIG_DAVICOM_PHY is not set
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
# CONFIG_QSEMI_PHY is not set
# CONFIG_LXT_PHY is not set
-# CONFIG_CICADA_PHY is not set
+CONFIG_CICADA_PHY=y
CONFIG_VITESSE_PHY=y
# CONFIG_SMSC_PHY is not set
# CONFIG_BROADCOM_PHY is not set
@@ -647,7 +674,7 @@ CONFIG_VITESSE_PHY=y
# CONFIG_NATIONAL_PHY is not set
# CONFIG_STE10XP is not set
# CONFIG_LSI_ET1011C_PHY is not set
-# CONFIG_FIXED_PHY is not set
+CONFIG_FIXED_PHY=y
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
@@ -655,6 +682,8 @@ CONFIG_MII=y
# CONFIG_SUNGEM is not set
# CONFIG_CASSINI is not set
# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -667,7 +696,10 @@ CONFIG_MII=y
# CONFIG_NET_PCI is not set
# CONFIG_B44 is not set
# CONFIG_ATL2 is not set
-# CONFIG_FS_ENET is not set
+CONFIG_FS_ENET=y
+CONFIG_FS_ENET_HAS_SCC=y
+CONFIG_FS_ENET_HAS_FCC=y
+# CONFIG_FS_ENET_MDIO_FCC is not set
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
@@ -675,6 +707,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_E1000E is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -685,11 +718,15 @@ CONFIG_NETDEV_1000=y
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
+CONFIG_FSL_PQ_MDIO=y
CONFIG_GIANFAR=y
-# CONFIG_UCC_GETH is not set
+CONFIG_UCC_GETH=y
+# CONFIG_UGETH_MAGIC_PACKET is not set
+# CONFIG_UGETH_TX_ON_DEMAND is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
@@ -699,6 +736,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
@@ -708,6 +746,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_BNX2X is not set
# CONFIG_QLGE is not set
# CONFIG_SFC is not set
+# CONFIG_BE2NET is not set
# CONFIG_TR is not set
#
@@ -715,7 +754,6 @@ CONFIG_CHELSIO_T3_DEPENDS=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
#
# Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -813,14 +851,15 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_CPM is not set
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
-# CONFIG_SERIAL_QE is not set
+CONFIG_SERIAL_QE=m
CONFIG_UNIX98_PTYS=y
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
-# CONFIG_HW_RANDOM is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
CONFIG_NVRAM=y
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -857,7 +896,7 @@ CONFIG_I2C_HELPER_AUTO=y
#
# I2C system bus drivers (mostly embedded / system-on-chip)
#
-# CONFIG_I2C_CPM is not set
+CONFIG_I2C_CPM=m
# CONFIG_I2C_GPIO is not set
CONFIG_I2C_MPC=y
# CONFIG_I2C_OCORES is not set
@@ -885,12 +924,9 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_EEPROM_AT24 is not set
-CONFIG_EEPROM_LEGACY=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -969,7 +1005,7 @@ CONFIG_VIDEO_MEDIA=m
#
# CONFIG_MEDIA_ATTACH is not set
CONFIG_MEDIA_TUNER=m
-# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
CONFIG_MEDIA_TUNER_SIMPLE=m
CONFIG_MEDIA_TUNER_TDA8290=m
CONFIG_MEDIA_TUNER_TDA9887=m
@@ -978,6 +1014,7 @@ CONFIG_MEDIA_TUNER_TEA5767=m
CONFIG_MEDIA_TUNER_MT20XX=m
CONFIG_MEDIA_TUNER_XC2028=m
CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MC44S803=m
# CONFIG_DVB_DYNAMIC_MINORS is not set
CONFIG_DVB_CAPTURE_DRIVERS=y
@@ -1017,103 +1054,7 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
#
# Supported DVB Frontends
#
-
-#
-# Customise DVB Frontends
-#
# CONFIG_DVB_FE_CUSTOMISE is not set
-
-#
-# Multistandard (satellite) frontends
-#
-# CONFIG_DVB_STB0899 is not set
-# CONFIG_DVB_STB6100 is not set
-
-#
-# DVB-S (satellite) frontends
-#
-# CONFIG_DVB_CX24110 is not set
-# CONFIG_DVB_CX24123 is not set
-# CONFIG_DVB_MT312 is not set
-# CONFIG_DVB_S5H1420 is not set
-# CONFIG_DVB_STV0288 is not set
-# CONFIG_DVB_STB6000 is not set
-# CONFIG_DVB_STV0299 is not set
-# CONFIG_DVB_TDA8083 is not set
-# CONFIG_DVB_TDA10086 is not set
-# CONFIG_DVB_TDA8261 is not set
-# CONFIG_DVB_VES1X93 is not set
-# CONFIG_DVB_TUNER_ITD1000 is not set
-# CONFIG_DVB_TUNER_CX24113 is not set
-# CONFIG_DVB_TDA826X is not set
-# CONFIG_DVB_TUA6100 is not set
-# CONFIG_DVB_CX24116 is not set
-# CONFIG_DVB_SI21XX is not set
-
-#
-# DVB-T (terrestrial) frontends
-#
-# CONFIG_DVB_SP8870 is not set
-# CONFIG_DVB_SP887X is not set
-# CONFIG_DVB_CX22700 is not set
-# CONFIG_DVB_CX22702 is not set
-# CONFIG_DVB_DRX397XD is not set
-# CONFIG_DVB_L64781 is not set
-# CONFIG_DVB_TDA1004X is not set
-# CONFIG_DVB_NXT6000 is not set
-# CONFIG_DVB_MT352 is not set
-# CONFIG_DVB_ZL10353 is not set
-# CONFIG_DVB_DIB3000MB is not set
-# CONFIG_DVB_DIB3000MC is not set
-# CONFIG_DVB_DIB7000M is not set
-# CONFIG_DVB_DIB7000P is not set
-# CONFIG_DVB_TDA10048 is not set
-
-#
-# DVB-C (cable) frontends
-#
-# CONFIG_DVB_VES1820 is not set
-# CONFIG_DVB_TDA10021 is not set
-# CONFIG_DVB_TDA10023 is not set
-# CONFIG_DVB_STV0297 is not set
-
-#
-# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
-#
-# CONFIG_DVB_NXT200X is not set
-# CONFIG_DVB_OR51211 is not set
-# CONFIG_DVB_OR51132 is not set
-# CONFIG_DVB_BCM3510 is not set
-# CONFIG_DVB_LGDT330X is not set
-# CONFIG_DVB_LGDT3304 is not set
-# CONFIG_DVB_S5H1409 is not set
-# CONFIG_DVB_AU8522 is not set
-# CONFIG_DVB_S5H1411 is not set
-
-#
-# ISDB-T (terrestrial) frontends
-#
-# CONFIG_DVB_S921 is not set
-
-#
-# Digital terrestrial only tuners/PLL
-#
-# CONFIG_DVB_PLL is not set
-# CONFIG_DVB_TUNER_DIB0070 is not set
-
-#
-# SEC control devices for DVB-S
-#
-# CONFIG_DVB_LNBP21 is not set
-# CONFIG_DVB_ISL6405 is not set
-# CONFIG_DVB_ISL6421 is not set
-# CONFIG_DVB_LGS8GL5 is not set
-
-#
-# Tools to develop new frontends
-#
-# CONFIG_DVB_DUMMY_FE is not set
-# CONFIG_DVB_AF9013 is not set
CONFIG_DAB=y
# CONFIG_USB_DABUSB is not set
@@ -1193,6 +1134,8 @@ CONFIG_SND_PCI=y
# CONFIG_SND_INDIGO is not set
# CONFIG_SND_INDIGOIO is not set
# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_INDIGOIOX is not set
+# CONFIG_SND_INDIGODJX is not set
# CONFIG_SND_EMU10K1 is not set
# CONFIG_SND_EMU10K1X is not set
# CONFIG_SND_ENS1370 is not set
@@ -1247,15 +1190,17 @@ CONFIG_USB_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
+# CONFIG_DRAGONRISE_FF is not set
CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
CONFIG_HID_LOGITECH=y
# CONFIG_LOGITECH_FF is not set
# CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -1314,6 +1259,7 @@ CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_FHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
# CONFIG_USB_WHCI_HCD is not set
@@ -1329,11 +1275,11 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
#
#
-# see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -1375,7 +1321,6 @@ CONFIG_USB_STORAGE=y
# 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
@@ -1392,6 +1337,7 @@ CONFIG_USB_STORAGE=y
# OTG and related infrastructure
#
# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1406,6 +1352,8 @@ CONFIG_EDAC=y
# CONFIG_EDAC_DEBUG is not set
CONFIG_EDAC_MM_EDAC=y
CONFIG_EDAC_MPC85XX=y
+# CONFIG_EDAC_AMD8131 is not set
+# CONFIG_EDAC_AMD8111 is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
@@ -1460,7 +1408,7 @@ CONFIG_RTC_DRV_CMOS=y
#
# on-CPU RTC drivers
#
-# CONFIG_RTC_DRV_PPC is not set
+# CONFIG_RTC_DRV_GENERIC is not set
CONFIG_DMADEVICES=y
#
@@ -1473,7 +1421,9 @@ CONFIG_DMA_ENGINE=y
# DMA Clients
#
# CONFIG_NET_DMA is not set
+# CONFIG_ASYNC_TX_DMA is not set
# CONFIG_DMATEST is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
@@ -1484,6 +1434,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -1508,6 +1459,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=m
@@ -1562,6 +1518,7 @@ CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
# CONFIG_UFS_DEBUG is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -1577,7 +1534,6 @@ CONFIG_EXPORTFS=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1648,6 +1604,10 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_KOI8_U is not set
CONFIG_NLS_UTF8=m
# CONFIG_DLM is not set
+CONFIG_UCC_SLOW=y
+CONFIG_UCC_FAST=y
+CONFIG_UCC=y
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
@@ -1662,11 +1622,12 @@ CONFIG_CRC32=y
# CONFIG_CRC7 is not set
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
-CONFIG_PLIST=y
+CONFIG_DECOMPRESS_GZIP=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
#
# Kernel hacking
@@ -1684,6 +1645,9 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1714,9 +1678,12 @@ CONFIG_DEBUG_INFO=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -1724,17 +1691,20 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_CODE_PATCHING_SELFTEST is not set
# CONFIG_FTR_FIXUP_SELFTEST is not set
# CONFIG_MSI_BITMAP_SELFTEST is not set
@@ -1759,18 +1729,21 @@ CONFIG_CRYPTO=y
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
# CONFIG_CRYPTO_CRYPTD is not set
-# CONFIG_CRYPTO_AUTHENC is not set
+CONFIG_CRYPTO_AUTHENC=y
# CONFIG_CRYPTO_TEST is not set
#
@@ -1837,6 +1810,7 @@ CONFIG_CRYPTO_DES=y
# Compression
#
# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
#
@@ -1845,7 +1819,7 @@ CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
-# CONFIG_CRYPTO_DEV_TALITOS is not set
+CONFIG_CRYPTO_DEV_TALITOS=y
CONFIG_PPC_CLOCK=y
CONFIG_PPC_LIB_RHEAP=y
# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/configs/85xx/mpc8572_ds_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig
index 813223ae174d..1aa1c508d600 100644
--- a/arch/powerpc/configs/85xx/mpc8572_ds_defconfig
+++ b/arch/powerpc/configs/mpc85xx_smp_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc2
-# Mon Jan 26 15:36:12 2009
+# Linux kernel version: 2.6.30-rc2
+# Tue Apr 21 15:41:18 2009
#
# CONFIG_PPC64 is not set
@@ -22,9 +22,10 @@ CONFIG_FSL_EMB_PERFMON=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
CONFIG_PPC_MMU_NOHASH=y
+CONFIG_PPC_BOOK3E_MMU=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_SMP=y
-CONFIG_NR_CPUS=2
+CONFIG_NR_CPUS=8
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
@@ -44,6 +45,7 @@ CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_GPIO=y
# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
@@ -59,6 +61,7 @@ CONFIG_GENERIC_BUG=y
CONFIG_DEFAULT_UIMAGE=y
# CONFIG_PPC_DCR_NATIVE is not set
# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -73,11 +76,21 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
CONFIG_AUDIT=y
# CONFIG_AUDITSYSCALL is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
@@ -93,22 +106,24 @@ CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_STRIP_GENERATED=y
CONFIG_KALLSYMS_EXTRA_PASS=y
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -118,10 +133,12 @@ CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_PCI_QUIRKS=y
CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -130,6 +147,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -143,7 +162,6 @@ CONFIG_MODVERSIONS=y
CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
CONFIG_LBD=y
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -159,11 +177,6 @@ CONFIG_IOSCHED_CFQ=y
CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -173,21 +186,23 @@ CONFIG_CLASSIC_RCU=y
# CONFIG_PPC_CELL_NATIVE is not set
# CONFIG_PQ2ADS is not set
CONFIG_MPC85xx=y
-# CONFIG_MPC8540_ADS is not set
-# CONFIG_MPC8560_ADS is not set
-# CONFIG_MPC85xx_CDS is not set
-# CONFIG_MPC85xx_MDS is not set
-# CONFIG_MPC8536_DS is not set
+CONFIG_MPC8540_ADS=y
+CONFIG_MPC8560_ADS=y
+CONFIG_MPC85xx_CDS=y
+CONFIG_MPC85xx_MDS=y
+CONFIG_MPC8536_DS=y
CONFIG_MPC85xx_DS=y
-# CONFIG_KSI8560 is not set
-# CONFIG_STX_GP3 is not set
-# CONFIG_TQM8540 is not set
-# CONFIG_TQM8541 is not set
-# CONFIG_TQM8548 is not set
-# CONFIG_TQM8555 is not set
-# CONFIG_TQM8560 is not set
-# CONFIG_SBC8548 is not set
+CONFIG_SOCRATES=y
+CONFIG_KSI8560=y
+CONFIG_STX_GP3=y
+CONFIG_TQM8540=y
+CONFIG_TQM8541=y
+CONFIG_TQM8548=y
+CONFIG_TQM8555=y
+CONFIG_TQM8560=y
+CONFIG_SBC8548=y
# CONFIG_SBC8560 is not set
+CONFIG_TQM85xx=y
# CONFIG_IPIC is not set
CONFIG_MPIC=y
# CONFIG_MPIC_WEIRD is not set
@@ -199,10 +214,12 @@ CONFIG_PPC_I8259=y
# CONFIG_PPC_INDIRECT_IO is not set
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
-# CONFIG_QUICC_ENGINE is not set
-# CONFIG_CPM2 is not set
+CONFIG_QUICC_ENGINE=y
+CONFIG_QE_GPIO=y
+CONFIG_CPM2=y
CONFIG_FSL_ULI1575=y
-# CONFIG_MPC8xxx_GPIO is not set
+CONFIG_CPM=y
+CONFIG_MPC8xxx_GPIO=y
# CONFIG_SIMPLE_GPIO is not set
#
@@ -248,9 +265,12 @@ CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_PPC_4K_PAGES=y
# CONFIG_PPC_16K_PAGES is not set
# CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -277,6 +297,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -290,17 +311,17 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# Default settings for advanced configuration options are used
#
CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_LOWMEM_CAM_NUM=3
CONFIG_PAGE_OFFSET=0xc0000000
CONFIG_KERNEL_START=0xc0000000
CONFIG_PHYSICAL_START=0x00000000
-CONFIG_PHYSICAL_ALIGN=0x10000000
+CONFIG_PHYSICAL_ALIGN=0x04000000
CONFIG_TASK_SIZE=0xc0000000
CONFIG_NET=y
#
# Networking options
#
-CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -388,6 +409,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
# CONFIG_DCB is not set
@@ -400,7 +422,6 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
CONFIG_FIB_RULES=y
CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
@@ -431,6 +452,7 @@ CONFIG_EXTRA_FIRMWARE=""
# CONFIG_CONNECTOR is not set
# CONFIG_MTD is not set
CONFIG_OF_DEVICE=y
+CONFIG_OF_GPIO=y
CONFIG_OF_I2C=y
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
@@ -454,13 +476,20 @@ CONFIG_BLK_DEV_RAM_SIZE=131072
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_ISL29003 is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+CONFIG_EEPROM_LEGACY=y
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -519,9 +548,11 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
@@ -544,12 +575,13 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
CONFIG_SATA_AHCI=y
# CONFIG_SATA_SIL24 is not set
-# CONFIG_SATA_FSL is not set
+CONFIG_SATA_FSL=y
CONFIG_ATA_SFF=y
# CONFIG_SATA_SVW is not set
# CONFIG_ATA_PIIX is not set
@@ -620,6 +652,7 @@ CONFIG_PATA_ALI=y
# CONFIG_I2O is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_DUMMY=y
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -632,11 +665,11 @@ CONFIG_PHYLIB=y
#
# MII PHY device drivers
#
-# CONFIG_MARVELL_PHY is not set
-# CONFIG_DAVICOM_PHY is not set
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
# CONFIG_QSEMI_PHY is not set
# CONFIG_LXT_PHY is not set
-# CONFIG_CICADA_PHY is not set
+CONFIG_CICADA_PHY=y
CONFIG_VITESSE_PHY=y
# CONFIG_SMSC_PHY is not set
# CONFIG_BROADCOM_PHY is not set
@@ -645,7 +678,7 @@ CONFIG_VITESSE_PHY=y
# CONFIG_NATIONAL_PHY is not set
# CONFIG_STE10XP is not set
# CONFIG_LSI_ET1011C_PHY is not set
-# CONFIG_FIXED_PHY is not set
+CONFIG_FIXED_PHY=y
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
@@ -653,6 +686,8 @@ CONFIG_MII=y
# CONFIG_SUNGEM is not set
# CONFIG_CASSINI is not set
# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -665,6 +700,10 @@ CONFIG_MII=y
# CONFIG_NET_PCI is not set
# CONFIG_B44 is not set
# CONFIG_ATL2 is not set
+CONFIG_FS_ENET=y
+CONFIG_FS_ENET_HAS_SCC=y
+CONFIG_FS_ENET_HAS_FCC=y
+# CONFIG_FS_ENET_MDIO_FCC is not set
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
@@ -672,6 +711,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_E1000E is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -682,10 +722,15 @@ CONFIG_NETDEV_1000=y
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
+CONFIG_FSL_PQ_MDIO=y
CONFIG_GIANFAR=y
+CONFIG_UCC_GETH=y
+# CONFIG_UGETH_MAGIC_PACKET is not set
+# CONFIG_UGETH_TX_ON_DEMAND is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
@@ -695,6 +740,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
@@ -704,6 +750,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_BNX2X is not set
# CONFIG_QLGE is not set
# CONFIG_SFC is not set
+# CONFIG_BE2NET is not set
# CONFIG_TR is not set
#
@@ -711,7 +758,6 @@ CONFIG_CHELSIO_T3_DEPENDS=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
#
# Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -806,8 +852,10 @@ CONFIG_SERIAL_8250_RSA=y
# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_CPM is not set
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_SERIAL_QE=m
CONFIG_UNIX98_PTYS=y
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
@@ -815,6 +863,7 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
CONFIG_NVRAM=y
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -851,6 +900,8 @@ CONFIG_I2C_HELPER_AUTO=y
#
# I2C system bus drivers (mostly embedded / system-on-chip)
#
+CONFIG_I2C_CPM=m
+# CONFIG_I2C_GPIO is not set
CONFIG_I2C_MPC=y
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_SIMTEC is not set
@@ -877,12 +928,9 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_EEPROM_AT24 is not set
-CONFIG_EEPROM_LEGACY=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -891,7 +939,31 @@ CONFIG_EEPROM_LEGACY=y
# CONFIG_I2C_DEBUG_CHIP is not set
# CONFIG_SPI is not set
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+# CONFIG_GPIO_BT8XX is not set
+
+#
+# SPI GPIO expanders:
+#
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
@@ -911,6 +983,8 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_UCB1400_CORE is not set
+# CONFIG_TPS65010 is not set
# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
@@ -935,7 +1009,7 @@ CONFIG_VIDEO_MEDIA=m
#
# CONFIG_MEDIA_ATTACH is not set
CONFIG_MEDIA_TUNER=m
-# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
CONFIG_MEDIA_TUNER_SIMPLE=m
CONFIG_MEDIA_TUNER_TDA8290=m
CONFIG_MEDIA_TUNER_TDA9887=m
@@ -944,6 +1018,7 @@ CONFIG_MEDIA_TUNER_TEA5767=m
CONFIG_MEDIA_TUNER_MT20XX=m
CONFIG_MEDIA_TUNER_XC2028=m
CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MC44S803=m
# CONFIG_DVB_DYNAMIC_MINORS is not set
CONFIG_DVB_CAPTURE_DRIVERS=y
@@ -983,103 +1058,7 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
#
# Supported DVB Frontends
#
-
-#
-# Customise DVB Frontends
-#
# CONFIG_DVB_FE_CUSTOMISE is not set
-
-#
-# Multistandard (satellite) frontends
-#
-# CONFIG_DVB_STB0899 is not set
-# CONFIG_DVB_STB6100 is not set
-
-#
-# DVB-S (satellite) frontends
-#
-# CONFIG_DVB_CX24110 is not set
-# CONFIG_DVB_CX24123 is not set
-# CONFIG_DVB_MT312 is not set
-# CONFIG_DVB_S5H1420 is not set
-# CONFIG_DVB_STV0288 is not set
-# CONFIG_DVB_STB6000 is not set
-# CONFIG_DVB_STV0299 is not set
-# CONFIG_DVB_TDA8083 is not set
-# CONFIG_DVB_TDA10086 is not set
-# CONFIG_DVB_TDA8261 is not set
-# CONFIG_DVB_VES1X93 is not set
-# CONFIG_DVB_TUNER_ITD1000 is not set
-# CONFIG_DVB_TUNER_CX24113 is not set
-# CONFIG_DVB_TDA826X is not set
-# CONFIG_DVB_TUA6100 is not set
-# CONFIG_DVB_CX24116 is not set
-# CONFIG_DVB_SI21XX is not set
-
-#
-# DVB-T (terrestrial) frontends
-#
-# CONFIG_DVB_SP8870 is not set
-# CONFIG_DVB_SP887X is not set
-# CONFIG_DVB_CX22700 is not set
-# CONFIG_DVB_CX22702 is not set
-# CONFIG_DVB_DRX397XD is not set
-# CONFIG_DVB_L64781 is not set
-# CONFIG_DVB_TDA1004X is not set
-# CONFIG_DVB_NXT6000 is not set
-# CONFIG_DVB_MT352 is not set
-# CONFIG_DVB_ZL10353 is not set
-# CONFIG_DVB_DIB3000MB is not set
-# CONFIG_DVB_DIB3000MC is not set
-# CONFIG_DVB_DIB7000M is not set
-# CONFIG_DVB_DIB7000P is not set
-# CONFIG_DVB_TDA10048 is not set
-
-#
-# DVB-C (cable) frontends
-#
-# CONFIG_DVB_VES1820 is not set
-# CONFIG_DVB_TDA10021 is not set
-# CONFIG_DVB_TDA10023 is not set
-# CONFIG_DVB_STV0297 is not set
-
-#
-# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
-#
-# CONFIG_DVB_NXT200X is not set
-# CONFIG_DVB_OR51211 is not set
-# CONFIG_DVB_OR51132 is not set
-# CONFIG_DVB_BCM3510 is not set
-# CONFIG_DVB_LGDT330X is not set
-# CONFIG_DVB_LGDT3304 is not set
-# CONFIG_DVB_S5H1409 is not set
-# CONFIG_DVB_AU8522 is not set
-# CONFIG_DVB_S5H1411 is not set
-
-#
-# ISDB-T (terrestrial) frontends
-#
-# CONFIG_DVB_S921 is not set
-
-#
-# Digital terrestrial only tuners/PLL
-#
-# CONFIG_DVB_PLL is not set
-# CONFIG_DVB_TUNER_DIB0070 is not set
-
-#
-# SEC control devices for DVB-S
-#
-# CONFIG_DVB_LNBP21 is not set
-# CONFIG_DVB_ISL6405 is not set
-# CONFIG_DVB_ISL6421 is not set
-# CONFIG_DVB_LGS8GL5 is not set
-
-#
-# Tools to develop new frontends
-#
-# CONFIG_DVB_DUMMY_FE is not set
-# CONFIG_DVB_AF9013 is not set
CONFIG_DAB=y
# CONFIG_USB_DABUSB is not set
@@ -1159,6 +1138,8 @@ CONFIG_SND_PCI=y
# CONFIG_SND_INDIGO is not set
# CONFIG_SND_INDIGOIO is not set
# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_INDIGOIOX is not set
+# CONFIG_SND_INDIGODJX is not set
# CONFIG_SND_EMU10K1 is not set
# CONFIG_SND_EMU10K1X is not set
# CONFIG_SND_ENS1370 is not set
@@ -1213,15 +1194,17 @@ CONFIG_USB_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
+# CONFIG_DRAGONRISE_FF is not set
CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
CONFIG_HID_LOGITECH=y
# CONFIG_LOGITECH_FF is not set
# CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -1264,9 +1247,9 @@ CONFIG_USB_MON=y
#
# CONFIG_USB_C67X00_HCD is not set
CONFIG_USB_EHCI_HCD=y
-# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
-# CONFIG_USB_EHCI_FSL is not set
+CONFIG_USB_EHCI_FSL=y
CONFIG_USB_EHCI_HCD_PPC_OF=y
# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
@@ -1280,10 +1263,12 @@ CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_FHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
# CONFIG_USB_WHCI_HCD is not set
# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
#
# USB Device Class drivers
@@ -1294,11 +1279,11 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
#
#
-# see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -1340,7 +1325,6 @@ CONFIG_USB_STORAGE=y
# 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
@@ -1356,13 +1340,24 @@ CONFIG_USB_STORAGE=y
#
# OTG and related infrastructure
#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
# CONFIG_ACCESSIBILITY is not set
# CONFIG_INFINIBAND is not set
-# CONFIG_EDAC is not set
+CONFIG_EDAC=y
+
+#
+# Reporting subsystems
+#
+# CONFIG_EDAC_DEBUG is not set
+CONFIG_EDAC_MM_EDAC=y
+CONFIG_EDAC_MPC85XX=y
+# CONFIG_EDAC_AMD8131 is not set
+# CONFIG_EDAC_AMD8111 is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
@@ -1417,8 +1412,22 @@ CONFIG_RTC_DRV_CMOS=y
#
# on-CPU RTC drivers
#
-# CONFIG_RTC_DRV_PPC is not set
-# CONFIG_DMADEVICES is not set
+# CONFIG_RTC_DRV_GENERIC is not set
+CONFIG_DMADEVICES=y
+
+#
+# DMA Devices
+#
+CONFIG_FSL_DMA=y
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+# CONFIG_NET_DMA is not set
+# CONFIG_ASYNC_TX_DMA is not set
+# CONFIG_DMATEST is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
@@ -1429,11 +1438,13 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
# CONFIG_EXT4_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
@@ -1452,6 +1463,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=m
@@ -1506,6 +1522,7 @@ CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
# CONFIG_UFS_DEBUG is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -1521,7 +1538,6 @@ CONFIG_EXPORTFS=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1592,6 +1608,10 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_KOI8_U is not set
CONFIG_NLS_UTF8=m
# CONFIG_DLM is not set
+CONFIG_UCC_SLOW=y
+CONFIG_UCC_FAST=y
+CONFIG_UCC=y
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
@@ -1606,11 +1626,12 @@ CONFIG_CRC32=y
# CONFIG_CRC7 is not set
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
-CONFIG_PLIST=y
+CONFIG_DECOMPRESS_GZIP=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
#
# Kernel hacking
@@ -1621,13 +1642,16 @@ CONFIG_ENABLE_MUST_CHECK=y
CONFIG_FRAME_WARN=1024
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1658,9 +1682,12 @@ CONFIG_DEBUG_INFO=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -1668,22 +1695,26 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_CODE_PATCHING_SELFTEST is not set
# CONFIG_FTR_FIXUP_SELFTEST is not set
# CONFIG_MSI_BITMAP_SELFTEST is not set
# CONFIG_XMON is not set
# CONFIG_IRQSTACKS is not set
+CONFIG_VIRQ_DEBUG=y
# CONFIG_BDI_SWITCH is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1709,10 +1740,12 @@ CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_AUTHENC=y
# CONFIG_CRYPTO_TEST is not set
@@ -1781,6 +1814,7 @@ CONFIG_CRYPTO_DES=y
# Compression
#
# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
#
@@ -1790,5 +1824,6 @@ CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
CONFIG_CRYPTO_DEV_TALITOS=y
-# CONFIG_PPC_CLOCK is not set
+CONFIG_PPC_CLOCK=y
+CONFIG_PPC_LIB_RHEAP=y
# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig
index 7d044dfd9236..12dc7c409616 100644
--- a/arch/powerpc/configs/ppc6xx_defconfig
+++ b/arch/powerpc/configs/ppc6xx_defconfig
@@ -1808,7 +1808,7 @@ CONFIG_PCF8575=m
CONFIG_SENSORS_PCA9539=m
CONFIG_SENSORS_PCF8591=m
# CONFIG_TPS65010 is not set
-CONFIG_SENSORS_MAX6875=m
+CONFIG_EEPROM_MAX6875=m
CONFIG_SENSORS_TSL2550=m
CONFIG_MCU_MPC8349EMITX=m
# CONFIG_I2C_DEBUG_CORE is not set
diff --git a/arch/powerpc/include/asm/cpm1.h b/arch/powerpc/include/asm/cpm1.h
index 2ff798744c1d..7685ffde8821 100644
--- a/arch/powerpc/include/asm/cpm1.h
+++ b/arch/powerpc/include/asm/cpm1.h
@@ -598,8 +598,6 @@ typedef struct risc_timer_pram {
#define CICR_IEN ((uint)0x00000080) /* Int. enable */
#define CICR_SPS ((uint)0x00000001) /* SCC Spread */
-#define IMAP_ADDR (get_immrbase())
-
#define CPM_PIN_INPUT 0
#define CPM_PIN_OUTPUT 1
#define CPM_PIN_PRIMARY 0
diff --git a/arch/powerpc/include/asm/cpm2.h b/arch/powerpc/include/asm/cpm2.h
index 0f5e8ff59a85..990ff191da8b 100644
--- a/arch/powerpc/include/asm/cpm2.h
+++ b/arch/powerpc/include/asm/cpm2.h
@@ -14,10 +14,6 @@
#include <asm/cpm.h>
#include <sysdev/fsl_soc.h>
-#ifdef CONFIG_PPC_85xx
-#define CPM_MAP_ADDR (get_immrbase() + 0x80000)
-#endif
-
/* CPM Command register.
*/
#define CPM_CR_RST ((uint)0x80000000)
diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h
index 1a856b15226e..d6b4a12cdeff 100644
--- a/arch/powerpc/include/asm/elf.h
+++ b/arch/powerpc/include/asm/elf.h
@@ -258,7 +258,9 @@ do { \
# define elf_read_implies_exec(ex, exec_stk) (test_thread_flag(TIF_32BIT) ? \
(exec_stk != EXSTACK_DISABLE_X) : 0)
#else
-# define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+# define SET_PERSONALITY(ex) \
+ set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
+# define elf_read_implies_exec(ex, exec_stk) (exec_stk != EXSTACK_DISABLE_X)
#endif /* __powerpc64__ */
extern int dcache_bsize;
diff --git a/arch/powerpc/include/asm/futex.h b/arch/powerpc/include/asm/futex.h
index 6d406c5c5de4..9696cc36d2dc 100644
--- a/arch/powerpc/include/asm/futex.h
+++ b/arch/powerpc/include/asm/futex.h
@@ -27,7 +27,7 @@
PPC_LONG "1b,4b,2b,4b\n" \
".previous" \
: "=&r" (oldval), "=&r" (ret) \
- : "b" (uaddr), "i" (-EFAULT), "1" (oparg) \
+ : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
: "cr0", "memory")
static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
@@ -47,19 +47,19 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
switch (op) {
case FUTEX_OP_SET:
- __futex_atomic_op("", ret, oldval, uaddr, oparg);
+ __futex_atomic_op("mr %1,%4\n", ret, oldval, uaddr, oparg);
break;
case FUTEX_OP_ADD:
- __futex_atomic_op("add %1,%0,%1\n", ret, oldval, uaddr, oparg);
+ __futex_atomic_op("add %1,%0,%4\n", ret, oldval, uaddr, oparg);
break;
case FUTEX_OP_OR:
- __futex_atomic_op("or %1,%0,%1\n", ret, oldval, uaddr, oparg);
+ __futex_atomic_op("or %1,%0,%4\n", ret, oldval, uaddr, oparg);
break;
case FUTEX_OP_ANDN:
- __futex_atomic_op("andc %1,%0,%1\n", ret, oldval, uaddr, oparg);
+ __futex_atomic_op("andc %1,%0,%4\n", ret, oldval, uaddr, oparg);
break;
case FUTEX_OP_XOR:
- __futex_atomic_op("xor %1,%0,%1\n", ret, oldval, uaddr, oparg);
+ __futex_atomic_op("xor %1,%0,%4\n", ret, oldval, uaddr, oparg);
break;
default:
ret = -ENOSYS;
diff --git a/arch/powerpc/include/asm/mpc86xx.h b/arch/powerpc/include/asm/mpc86xx.h
deleted file mode 100644
index 15f650f987e7..000000000000
--- a/arch/powerpc/include/asm/mpc86xx.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * MPC86xx definitions
- *
- * Author: Jeff Brown
- *
- * Copyright 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 as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#ifdef __KERNEL__
-#ifndef __ASM_POWERPC_MPC86xx_H__
-#define __ASM_POWERPC_MPC86xx_H__
-
-#include <asm/mmu.h>
-
-#ifdef CONFIG_PPC_86xx
-
-#define CPU0_BOOT_RELEASE 0x01000000
-#define CPU1_BOOT_RELEASE 0x02000000
-#define CPU_ALL_RELEASED (CPU0_BOOT_RELEASE | CPU1_BOOT_RELEASE)
-#define MCM_PORT_CONFIG_OFFSET 0x1010
-
-/* Offset from CCSRBAR */
-#define MPC86xx_MCM_OFFSET (0x00000)
-#define MPC86xx_MCM_SIZE (0x02000)
-
-#endif /* CONFIG_PPC_86xx */
-#endif /* __ASM_POWERPC_MPC86xx_H__ */
-#endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/of_platform.h b/arch/powerpc/include/asm/of_platform.h
index 53b46507ffde..d4aaa3489440 100644
--- a/arch/powerpc/include/asm/of_platform.h
+++ b/arch/powerpc/include/asm/of_platform.h
@@ -11,16 +11,6 @@
*
*/
-/* Platform drivers register/unregister */
-static inline int of_register_platform_driver(struct of_platform_driver *drv)
-{
- return of_register_driver(drv, &of_platform_bus_type);
-}
-static inline void of_unregister_platform_driver(struct of_platform_driver *drv)
-{
- of_unregister_driver(drv);
-}
-
/* Platform devices and busses creation */
extern struct of_device *of_platform_device_create(struct device_node *np,
const char *bus_id,
diff --git a/arch/powerpc/include/asm/parport.h b/arch/powerpc/include/asm/parport.h
index 414c50e2e881..94942d60ddfd 100644
--- a/arch/powerpc/include/asm/parport.h
+++ b/arch/powerpc/include/asm/parport.h
@@ -29,7 +29,7 @@ static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
prop = of_get_property(np, "interrupts", NULL);
if (!prop)
continue;
- if (parport_pc_probe_port(io1, io2, prop[0], autodma, NULL) != NULL)
+ if (parport_pc_probe_port(io1, io2, prop[0], autodma, NULL, 0) != NULL)
count++;
}
return count;
diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h
index 84007afabdb5..9861258f6a4c 100644
--- a/arch/powerpc/include/asm/pci-bridge.h
+++ b/arch/powerpc/include/asm/pci-bridge.h
@@ -140,10 +140,12 @@ struct pci_controller {
struct resource io_resource;
struct resource mem_resources[3];
int global_number; /* PCI domain number */
+
+ resource_size_t dma_window_base_cur;
+ resource_size_t dma_window_size;
+
#ifdef CONFIG_PPC64
unsigned long buid;
- unsigned long dma_window_base_cur;
- unsigned long dma_window_size;
void *private_data;
#endif /* CONFIG_PPC64 */
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index f4a4db8d5555..640ccbbc0977 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -43,7 +43,7 @@
#define PPC_INST_STSWI 0x7c0005aa
#define PPC_INST_STSWX 0x7c00052a
-#define PPC_INST_TLBILX 0x7c000626
+#define PPC_INST_TLBILX 0x7c000024
#define PPC_INST_WAIT 0x7c00007c
/* macros to insert fields into opcodes */
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index f59a66684aed..384d90c9c272 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -4,6 +4,7 @@
#ifndef _ASM_POWERPC_PPC_ASM_H
#define _ASM_POWERPC_PPC_ASM_H
+#include <linux/init.h>
#include <linux/stringify.h>
#include <asm/asm-compat.h>
#include <asm/processor.h>
@@ -189,7 +190,7 @@ name: \
GLUE(.,name):
#define _INIT_GLOBAL(name) \
- .section ".text.init.refok"; \
+ __REF; \
.align 2 ; \
.globl name; \
.globl GLUE(.,name); \
@@ -229,7 +230,7 @@ name: \
GLUE(.,name):
#define _INIT_STATIC(name) \
- .section ".text.init.refok"; \
+ __REF; \
.align 2 ; \
.section ".opd","aw"; \
name: \
diff --git a/arch/powerpc/include/asm/qe.h b/arch/powerpc/include/asm/qe.h
index 2701753d9937..e0faf332c9c9 100644
--- a/arch/powerpc/include/asm/qe.h
+++ b/arch/powerpc/include/asm/qe.h
@@ -22,7 +22,7 @@
#include <asm/cpm.h>
#include <asm/immap_qe.h>
-#define QE_NUM_OF_SNUM 28
+#define QE_NUM_OF_SNUM 256 /* There are 256 serial number in QE */
#define QE_NUM_OF_BRGS 16
#define QE_NUM_OF_PORTS 1024
@@ -152,6 +152,9 @@ unsigned int qe_get_brg_clk(void);
int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier);
int qe_get_snum(void);
void qe_put_snum(u8 snum);
+unsigned int qe_get_num_of_risc(void);
+unsigned int qe_get_num_of_snums(void);
+
/* we actually use cpm_muram implementation, define this for convenience */
#define qe_muram_init cpm_muram_init
#define qe_muram_alloc cpm_muram_alloc
@@ -231,12 +234,16 @@ struct qe_bd {
#define QE_ALIGNMENT_OF_PRAM 64
/* RISC allocation */
-enum qe_risc_allocation {
- QE_RISC_ALLOCATION_RISC1 = 1, /* RISC 1 */
- QE_RISC_ALLOCATION_RISC2 = 2, /* RISC 2 */
- QE_RISC_ALLOCATION_RISC1_AND_RISC2 = 3 /* Dynamically choose
- RISC 1 or RISC 2 */
-};
+#define QE_RISC_ALLOCATION_RISC1 0x1 /* RISC 1 */
+#define QE_RISC_ALLOCATION_RISC2 0x2 /* RISC 2 */
+#define QE_RISC_ALLOCATION_RISC3 0x4 /* RISC 3 */
+#define QE_RISC_ALLOCATION_RISC4 0x8 /* RISC 4 */
+#define QE_RISC_ALLOCATION_RISC1_AND_RISC2 (QE_RISC_ALLOCATION_RISC1 | \
+ QE_RISC_ALLOCATION_RISC2)
+#define QE_RISC_ALLOCATION_FOUR_RISCS (QE_RISC_ALLOCATION_RISC1 | \
+ QE_RISC_ALLOCATION_RISC2 | \
+ QE_RISC_ALLOCATION_RISC3 | \
+ QE_RISC_ALLOCATION_RISC4)
/* QE extended filtering Table Lookup Key Size */
enum qe_fltr_tbl_lookup_key_size {
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index cd1b687544f3..f9c40f869c6e 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -382,7 +382,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
.icache_bsize = 128,
.dcache_bsize = 128,
.machine_check = machine_check_generic,
- .oprofile_cpu_type = "ppc64/compat-power5+",
+ .oprofile_cpu_type = "ppc64/ibm-compat-v1",
+ .oprofile_type = PPC_OPROFILE_POWER4,
.platform = "power5+",
},
{ /* Power6 */
@@ -416,7 +417,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
.icache_bsize = 128,
.dcache_bsize = 128,
.machine_check = machine_check_generic,
- .oprofile_cpu_type = "ppc64/compat-power6",
+ .oprofile_cpu_type = "ppc64/ibm-compat-v1",
+ .oprofile_type = PPC_OPROFILE_POWER4,
.platform = "power6",
},
{ /* 2.06-compliant processor, i.e. Power7 "architected" mode */
@@ -429,7 +431,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
.icache_bsize = 128,
.dcache_bsize = 128,
.machine_check = machine_check_generic,
- .oprofile_cpu_type = "ppc64/compat-power7",
+ .oprofile_type = PPC_OPROFILE_POWER4,
+ .oprofile_cpu_type = "ppc64/ibm-compat-v1",
.platform = "power7",
},
{ /* Power7 */
@@ -1833,8 +1836,10 @@ static void __init setup_cpu_spec(unsigned long offset, struct cpu_spec *s)
* and, in that case, keep the current value for
* oprofile_cpu_type.
*/
- if (old.oprofile_cpu_type == NULL)
- t->oprofile_cpu_type = s->oprofile_cpu_type;
+ if (old.oprofile_cpu_type == NULL) {
+ t->oprofile_cpu_type = old.oprofile_cpu_type;
+ t->oprofile_type = old.oprofile_type;
+ }
}
*PTRRELOC(&cur_cpu_spec) = &the_cpu_spec;
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index 54e68c11ae15..c01467f952d3 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -21,6 +21,7 @@
*
*/
+#include <linux/init.h>
#include <asm/reg.h>
#include <asm/page.h>
#include <asm/mmu.h>
@@ -50,7 +51,7 @@
mtspr SPRN_DBAT##n##L,RB; \
1:
- .section .text.head, "ax"
+ __HEAD
.stabs "arch/powerpc/kernel/",N_SO,0,0,0f
.stabs "head_32.S",N_SO,0,0,0f
0:
diff --git a/arch/powerpc/kernel/head_40x.S b/arch/powerpc/kernel/head_40x.S
index 56d8e5d90c5b..0c96911d4299 100644
--- a/arch/powerpc/kernel/head_40x.S
+++ b/arch/powerpc/kernel/head_40x.S
@@ -31,6 +31,7 @@
*
*/
+#include <linux/init.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/mmu.h>
@@ -52,7 +53,7 @@
*
* This is all going to change RSN when we add bi_recs....... -- Dan
*/
- .section .text.head, "ax"
+ __HEAD
_ENTRY(_stext);
_ENTRY(_start);
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
index b56fecc93a16..18d8a1677c4d 100644
--- a/arch/powerpc/kernel/head_44x.S
+++ b/arch/powerpc/kernel/head_44x.S
@@ -28,6 +28,7 @@
* option) any later version.
*/
+#include <linux/init.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/mmu.h>
@@ -50,7 +51,7 @@
* r7 - End of kernel command line string
*
*/
- .section .text.head, "ax"
+ __HEAD
_ENTRY(_stext);
_ENTRY(_start);
/*
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 3c9452d4308b..52ff8c53b93c 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -19,6 +19,7 @@
*
*/
+#include <linux/init.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/mmu.h>
@@ -38,7 +39,7 @@
#else
#define DO_8xx_CPU6(val, reg)
#endif
- .section .text.head, "ax"
+ __HEAD
_ENTRY(_stext);
_ENTRY(_start);
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 4c22620d009b..5bdcc06d294c 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -30,6 +30,7 @@
* option) any later version.
*/
+#include <linux/init.h>
#include <linux/threads.h>
#include <asm/processor.h>
#include <asm/page.h>
@@ -53,7 +54,7 @@
* r7 - End of kernel command line string
*
*/
- .section .text.head, "ax"
+ __HEAD
_ENTRY(_stext);
_ENTRY(_start);
/*
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index 8f0856f312da..8362620c9e6f 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -971,7 +971,7 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
struct device_node *p;
const u32 *intspec, *tmp, *addr;
u32 intsize, intlen;
- int res;
+ int res = -EINVAL;
DBG("of_irq_map_one: dev=%s, index=%d\n", device->full_name, index);
@@ -995,21 +995,20 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
/* Get size of interrupt specifier */
tmp = of_get_property(p, "#interrupt-cells", NULL);
- if (tmp == NULL) {
- of_node_put(p);
- return -EINVAL;
- }
+ if (tmp == NULL)
+ goto out;
intsize = *tmp;
DBG(" intsize=%d intlen=%d\n", intsize, intlen);
/* Check index */
if ((index + 1) * intsize > intlen)
- return -EINVAL;
+ goto out;
/* Get new specifier and map it */
res = of_irq_map_raw(p, intspec + index * intsize, intsize,
addr, out_irq);
+out:
of_node_put(p);
return res;
}
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 926ea864e34f..48571ac56fb7 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -77,7 +77,7 @@
#include <linux/clockchips.h>
#include <linux/clocksource.h>
-static cycle_t rtc_read(void);
+static cycle_t rtc_read(struct clocksource *);
static struct clocksource clocksource_rtc = {
.name = "rtc",
.rating = 400,
@@ -88,7 +88,7 @@ static struct clocksource clocksource_rtc = {
.read = rtc_read,
};
-static cycle_t timebase_read(void);
+static cycle_t timebase_read(struct clocksource *);
static struct clocksource clocksource_timebase = {
.name = "timebase",
.rating = 400,
@@ -766,12 +766,12 @@ unsigned long read_persistent_clock(void)
}
/* clocksource code */
-static cycle_t rtc_read(void)
+static cycle_t rtc_read(struct clocksource *cs)
{
return (cycle_t)get_rtc();
}
-static cycle_t timebase_read(void)
+static cycle_t timebase_read(struct clocksource *cs)
{
return (cycle_t)get_tb();
}
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index b9ef1644a722..a047a6cfca4d 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -52,9 +52,10 @@ SECTIONS
/* Text and gots */
.text : AT(ADDR(.text) - LOAD_OFFSET) {
ALIGN_FUNCTION();
- *(.text.head)
+ HEAD_TEXT
_text = .;
- *(.text .fixup .text.init.refok .exit.text.refok __ftr_alt_*)
+ /* careful! __ftr_alt_* sections need to be close to .text */
+ *(.text .fixup __ftr_alt_* .ref.text)
SCHED_TEXT
LOCK_TEXT
KPROBES_TEXT
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 9057335fdc61..2cf915e51e7e 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -41,6 +41,12 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *v)
return !!(v->arch.pending_exceptions);
}
+int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu)
+{
+ /* do real check here */
+ return 1;
+}
+
int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
{
return !(v->arch.msr & MSR_WE);
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index db556d25c3a7..1ade7eb6ae00 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -753,7 +753,7 @@ void __init early_init_mmu(void)
}
#ifdef CONFIG_SMP
-void __init early_init_mmu_secondary(void)
+void __cpuinit early_init_mmu_secondary(void)
{
/* Initialize hash table for that CPU */
if (!firmware_has_feature(FW_FEATURE_LPAR))
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c
index 7af72970faed..ad2eb4d34dd4 100644
--- a/arch/powerpc/mm/tlb_nohash.c
+++ b/arch/powerpc/mm/tlb_nohash.c
@@ -125,7 +125,6 @@ static void do_flush_tlb_page_ipi(void *param)
void flush_tlb_mm(struct mm_struct *mm)
{
- cpumask_t cpu_mask;
unsigned int pid;
preempt_disable();
diff --git a/arch/powerpc/mm/tlb_nohash_low.S b/arch/powerpc/mm/tlb_nohash_low.S
index 788b87c36f77..3037911279b1 100644
--- a/arch/powerpc/mm/tlb_nohash_low.S
+++ b/arch/powerpc/mm/tlb_nohash_low.S
@@ -191,6 +191,6 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_USE_TLBILX)
isync
1: wrtee r10
blr
-#elif
+#else
#error Unsupported processor type !
#endif
diff --git a/arch/powerpc/oprofile/op_model_fsl_emb.c b/arch/powerpc/oprofile/op_model_fsl_emb.c
index 91596f6ba1f4..62312abffa28 100644
--- a/arch/powerpc/oprofile/op_model_fsl_emb.c
+++ b/arch/powerpc/oprofile/op_model_fsl_emb.c
@@ -228,20 +228,6 @@ static void pmc_stop_ctrs(void)
mtpmr(PMRN_PMGC0, pmgc0);
}
-static void dump_pmcs(void)
-{
- printk("pmgc0: %x\n", mfpmr(PMRN_PMGC0));
- printk("pmc\t\tpmlca\t\tpmlcb\n");
- printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC0),
- mfpmr(PMRN_PMLCA0), mfpmr(PMRN_PMLCB0));
- printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC1),
- mfpmr(PMRN_PMLCA1), mfpmr(PMRN_PMLCB1));
- printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC2),
- mfpmr(PMRN_PMLCA2), mfpmr(PMRN_PMLCB2));
- printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC3),
- mfpmr(PMRN_PMLCA3), mfpmr(PMRN_PMLCB3));
-}
-
static int fsl_emb_cpu_setup(struct op_counter_config *ctr)
{
int i;
diff --git a/arch/powerpc/platforms/82xx/pq2ads.h b/arch/powerpc/platforms/82xx/pq2ads.h
index 984db42cc8e7..6cf0f97486e2 100644
--- a/arch/powerpc/platforms/82xx/pq2ads.h
+++ b/arch/powerpc/platforms/82xx/pq2ads.h
@@ -24,10 +24,6 @@
#include <linux/seq_file.h>
-/* Backword-compatibility stuff for the drivers */
-#define CPM_MAP_ADDR ((uint)0xf0000000)
-#define CPM_IRQ_OFFSET 0
-
/* The ADS8260 has 16, 32-bit wide control/status registers, accessed
* only on word boundaries.
* Not all are used (yet), or are interesting to us (yet).
@@ -44,14 +40,5 @@
#define BCSR3_FETHIEN2 ((uint)0x10000000) /* 0 == enable*/
#define BCSR3_FETH2_RST ((uint)0x80000000) /* 0 == reset */
-/* cpm serial driver works with constants below */
-
-#define SIU_INT_SMC1 ((uint)0x04+CPM_IRQ_OFFSET)
-#define SIU_INT_SMC2 ((uint)0x05+CPM_IRQ_OFFSET)
-#define SIU_INT_SCC1 ((uint)0x28+CPM_IRQ_OFFSET)
-#define SIU_INT_SCC2 ((uint)0x29+CPM_IRQ_OFFSET)
-#define SIU_INT_SCC3 ((uint)0x2a+CPM_IRQ_OFFSET)
-#define SIU_INT_SCC4 ((uint)0x2b+CPM_IRQ_OFFSET)
-
#endif /* __MACH_ADS8260_DEFS */
#endif /* __KERNEL__ */
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index 7f066adc068c..43d385cedcd7 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -34,6 +34,7 @@ config MPC85xx_MDS
bool "Freescale MPC85xx MDS"
select DEFAULT_UIMAGE
select PHYLIB
+ select HAS_RAPIDIO
help
This option enables support for the MPC85xx MDS board
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 7dd029034aec..b2c0a4319973 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -206,23 +206,24 @@ static void __init mpc85xx_mds_setup_arch(void)
}
if (bcsr_regs) {
+ if (machine_is(mpc8568_mds)) {
#define BCSR_UCC1_GETH_EN (0x1 << 7)
#define BCSR_UCC2_GETH_EN (0x1 << 7)
#define BCSR_UCC1_MODE_MSK (0x3 << 4)
#define BCSR_UCC2_MODE_MSK (0x3 << 0)
- /* Turn off UCC1 & UCC2 */
- clrbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN);
- clrbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN);
+ /* Turn off UCC1 & UCC2 */
+ clrbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN);
+ clrbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN);
- /* Mode is RGMII, all bits clear */
- clrbits8(&bcsr_regs[11], BCSR_UCC1_MODE_MSK |
- BCSR_UCC2_MODE_MSK);
-
- /* Turn UCC1 & UCC2 on */
- setbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN);
- setbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN);
+ /* Mode is RGMII, all bits clear */
+ clrbits8(&bcsr_regs[11], BCSR_UCC1_MODE_MSK |
+ BCSR_UCC2_MODE_MSK);
+ /* Turn UCC1 & UCC2 on */
+ setbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN);
+ setbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN);
+ }
iounmap(bcsr_regs);
}
#endif /* CONFIG_QUICC_ENGINE */
@@ -257,7 +258,8 @@ static int __init board_fixups(void)
return 0;
}
-machine_arch_initcall(mpc85xx_mds, board_fixups);
+machine_arch_initcall(mpc8568_mds, board_fixups);
+machine_arch_initcall(mpc8569_mds, board_fixups);
static struct of_device_id mpc85xx_ids[] = {
{ .type = "soc", },
@@ -276,7 +278,8 @@ static int __init mpc85xx_publish_devices(void)
return 0;
}
-machine_device_initcall(mpc85xx_mds, mpc85xx_publish_devices);
+machine_device_initcall(mpc8568_mds, mpc85xx_publish_devices);
+machine_device_initcall(mpc8569_mds, mpc85xx_publish_devices);
static void __init mpc85xx_mds_pic_init(void)
{
@@ -321,8 +324,8 @@ static int __init mpc85xx_mds_probe(void)
return of_flat_dt_is_compatible(root, "MPC85xxMDS");
}
-define_machine(mpc85xx_mds) {
- .name = "MPC85xx MDS",
+define_machine(mpc8568_mds) {
+ .name = "MPC8568 MDS",
.probe = mpc85xx_mds_probe,
.setup_arch = mpc85xx_mds_setup_arch,
.init_IRQ = mpc85xx_mds_pic_init,
@@ -334,3 +337,24 @@ define_machine(mpc85xx_mds) {
.pcibios_fixup_bus = fsl_pcibios_fixup_bus,
#endif
};
+
+static int __init mpc8569_mds_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ return of_flat_dt_is_compatible(root, "fsl,MPC8569EMDS");
+}
+
+define_machine(mpc8569_mds) {
+ .name = "MPC8569 MDS",
+ .probe = mpc8569_mds_probe,
+ .setup_arch = mpc85xx_mds_setup_arch,
+ .init_IRQ = mpc85xx_mds_pic_init,
+ .get_irq = mpic_get_irq,
+ .restart = fsl_rstcr_restart,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+#ifdef CONFIG_PCI
+ .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
+#endif
+};
diff --git a/arch/powerpc/platforms/86xx/gef_ppc9a.c b/arch/powerpc/platforms/86xx/gef_ppc9a.c
index d79104669cdc..2efa052975e6 100644
--- a/arch/powerpc/platforms/86xx/gef_ppc9a.c
+++ b/arch/powerpc/platforms/86xx/gef_ppc9a.c
@@ -28,7 +28,6 @@
#include <asm/time.h>
#include <asm/machdep.h>
#include <asm/pci-bridge.h>
-#include <asm/mpc86xx.h>
#include <asm/prom.h>
#include <mm/mmu_decl.h>
#include <asm/udbg.h>
diff --git a/arch/powerpc/platforms/86xx/gef_sbc310.c b/arch/powerpc/platforms/86xx/gef_sbc310.c
index af14f852d747..90754e752bd8 100644
--- a/arch/powerpc/platforms/86xx/gef_sbc310.c
+++ b/arch/powerpc/platforms/86xx/gef_sbc310.c
@@ -28,7 +28,6 @@
#include <asm/time.h>
#include <asm/machdep.h>
#include <asm/pci-bridge.h>
-#include <asm/mpc86xx.h>
#include <asm/prom.h>
#include <mm/mmu_decl.h>
#include <asm/udbg.h>
diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c
index ea2360639652..72b31a6010a0 100644
--- a/arch/powerpc/platforms/86xx/gef_sbc610.c
+++ b/arch/powerpc/platforms/86xx/gef_sbc610.c
@@ -28,7 +28,6 @@
#include <asm/time.h>
#include <asm/machdep.h>
#include <asm/pci-bridge.h>
-#include <asm/mpc86xx.h>
#include <asm/prom.h>
#include <mm/mmu_decl.h>
#include <asm/udbg.h>
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index 3f49a6f893a3..51eec0cd5519 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -28,7 +28,6 @@
#include <asm/time.h>
#include <asm/machdep.h>
#include <asm/pci-bridge.h>
-#include <asm/mpc86xx.h>
#include <asm/prom.h>
#include <mm/mmu_decl.h>
#include <asm/udbg.h>
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index c4ec49b5f7f8..7e9e83c04a8a 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -24,7 +24,6 @@
#include <asm/time.h>
#include <asm/machdep.h>
#include <asm/pci-bridge.h>
-#include <asm/mpc86xx.h>
#include <asm/prom.h>
#include <mm/mmu_decl.h>
#include <asm/udbg.h>
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_smp.c b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
index 014e26cda08d..d84bbb508ee7 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_smp.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
@@ -20,7 +20,6 @@
#include <asm/pgtable.h>
#include <asm/pci-bridge.h>
#include <asm/mpic.h>
-#include <asm/mpc86xx.h>
#include <asm/cacheflush.h>
#include <sysdev/fsl_soc.h>
@@ -30,6 +29,11 @@
extern void __secondary_start_mpc86xx(void);
extern unsigned long __secondary_hold_acknowledge;
+#define MCM_PORT_CONFIG_OFFSET 0x10
+
+/* Offset from CCSRBAR */
+#define MPC86xx_MCM_OFFSET (0x1000)
+#define MPC86xx_MCM_SIZE (0x1000)
static void __init
smp_86xx_release_core(int nr)
@@ -48,6 +52,8 @@ smp_86xx_release_core(int nr)
pcr = in_be32(mcm_vaddr + (MCM_PORT_CONFIG_OFFSET >> 2));
pcr |= 1 << (nr + 24);
out_be32(mcm_vaddr + (MCM_PORT_CONFIG_OFFSET >> 2), pcr);
+
+ iounmap(mcm_vaddr);
}
diff --git a/arch/powerpc/platforms/86xx/sbc8641d.c b/arch/powerpc/platforms/86xx/sbc8641d.c
index 2886a36fc085..51c8f331b671 100644
--- a/arch/powerpc/platforms/86xx/sbc8641d.c
+++ b/arch/powerpc/platforms/86xx/sbc8641d.c
@@ -25,7 +25,6 @@
#include <asm/time.h>
#include <asm/machdep.h>
#include <asm/pci-bridge.h>
-#include <asm/mpc86xx.h>
#include <asm/prom.h>
#include <mm/mmu_decl.h>
#include <asm/udbg.h>
diff --git a/arch/powerpc/platforms/8xx/mpc885ads.h b/arch/powerpc/platforms/8xx/mpc885ads.h
index a5076668bad6..19412f76fa3b 100644
--- a/arch/powerpc/platforms/8xx/mpc885ads.h
+++ b/arch/powerpc/platforms/8xx/mpc885ads.h
@@ -17,10 +17,6 @@
#include <sysdev/fsl_soc.h>
-#define MPC8xx_CPM_OFFSET (0x9c0)
-#define CPM_MAP_ADDR (get_immrbase() + MPC8xx_CPM_OFFSET)
-#define CPM_IRQ_OFFSET 16 // for compability with cpm_uart driver
-
/* Bits of interest in the BCSRs.
*/
#define BCSR1_ETHEN ((uint)0x20000000)
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 40e24c39ad06..50f17bdd3c16 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -13,7 +13,6 @@ config PPC_CELL_COMMON
config PPC_CELL_NATIVE
bool
select PPC_CELL_COMMON
- select PPC_OF_PLATFORM_PCI
select MPIC
select IBM_NEW_EMAC_EMAC4
select IBM_NEW_EMAC_RGMII
@@ -25,6 +24,8 @@ config PPC_IBM_CELL_BLADE
bool "IBM Cell Blade"
depends on PPC64 && PPC_BOOK3S
select PPC_CELL_NATIVE
+ select PPC_OF_PLATFORM_PCI
+ select PCI
select MMIO_NVRAM
select PPC_UDBG_16550
select UDBG_RTAS_CONSOLE
@@ -33,6 +34,8 @@ config PPC_CELLEB
bool "Toshiba's Cell Reference Set 'Celleb' Architecture"
depends on PPC64 && PPC_BOOK3S
select PPC_CELL_NATIVE
+ select PPC_OF_PLATFORM_PCI
+ select PCI
select HAS_TXX9_SERIAL
select PPC_UDBG_BEAT
select USB_OHCI_BIG_ENDIAN_MMIO
diff --git a/arch/powerpc/platforms/fsl_uli1575.c b/arch/powerpc/platforms/fsl_uli1575.c
index 1db6b9e037fc..df83dc972531 100644
--- a/arch/powerpc/platforms/fsl_uli1575.c
+++ b/arch/powerpc/platforms/fsl_uli1575.c
@@ -51,13 +51,19 @@ u8 uli_pirq_to_irq[8] = {
ULI_8259_NONE, /* PIRQH */
};
+static inline bool is_quirk_valid(void)
+{
+ return (machine_is(mpc86xx_hpcn) ||
+ machine_is(mpc8544_ds) ||
+ machine_is(mpc8572_ds));
+}
+
/* Bridge */
static void __devinit early_uli5249(struct pci_dev *dev)
{
unsigned char temp;
- if (!machine_is(mpc86xx_hpcn) && !machine_is(mpc8544_ds) &&
- !machine_is(mpc8572_ds))
+ if (!is_quirk_valid())
return;
pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_IO |
@@ -80,8 +86,7 @@ static void __devinit quirk_uli1575(struct pci_dev *dev)
{
int i;
- if (!machine_is(mpc86xx_hpcn) && !machine_is(mpc8544_ds) &&
- !machine_is(mpc8572_ds))
+ if (!is_quirk_valid())
return;
/*
@@ -149,8 +154,7 @@ static void __devinit quirk_final_uli1575(struct pci_dev *dev)
* IRQ 14: Edge
* IRQ 15: Edge
*/
- if (!machine_is(mpc86xx_hpcn) && !machine_is(mpc8544_ds) &&
- !machine_is(mpc8572_ds))
+ if (!is_quirk_valid())
return;
outb(0xfa, 0x4d0);
@@ -176,8 +180,7 @@ static void __devinit quirk_uli5288(struct pci_dev *dev)
unsigned char c;
unsigned int d;
- if (!machine_is(mpc86xx_hpcn) && !machine_is(mpc8544_ds) &&
- !machine_is(mpc8572_ds))
+ if (!is_quirk_valid())
return;
/* read/write lock */
@@ -201,8 +204,7 @@ static void __devinit quirk_uli5229(struct pci_dev *dev)
{
unsigned short temp;
- if (!machine_is(mpc86xx_hpcn) && !machine_is(mpc8544_ds) &&
- !machine_is(mpc8572_ds))
+ if (!is_quirk_valid())
return;
pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE |
@@ -270,16 +272,10 @@ static void __devinit hpcd_quirk_uli1575(struct pci_dev *dev)
static void __devinit hpcd_quirk_uli5288(struct pci_dev *dev)
{
unsigned char c;
- unsigned short temp;
if (!machine_is(mpc86xx_hpcd))
return;
- /* Interrupt Disable, Needed when SATA disabled */
- pci_read_config_word(dev, PCI_COMMAND, &temp);
- temp |= 1<<10;
- pci_write_config_word(dev, PCI_COMMAND, temp);
-
pci_read_config_byte(dev, 0x83, &c);
c |= 0x80;
pci_write_config_byte(dev, 0x83, c);
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
index c64fb5bfb37e..153051eb6d93 100644
--- a/arch/powerpc/platforms/pasemi/setup.c
+++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -44,10 +44,6 @@
#include "pasemi.h"
-#if !defined(CONFIG_SMP)
-static void smp_send_stop(void) {}
-#endif
-
/* SDC reset register, must be pre-mapped at reset time */
static void __iomem *reset_reg;
diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c
index 86e392b1b049..cf1cd0f8c18f 100644
--- a/arch/powerpc/platforms/ps3/os-area.c
+++ b/arch/powerpc/platforms/ps3/os-area.c
@@ -578,7 +578,7 @@ static void os_area_db_init(struct os_area_db *db)
*
*/
-static void update_flash_db(void)
+static void __maybe_unused update_flash_db(void)
{
int result;
int file;
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index 66181821322a..1a7b5ae0c83e 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -45,10 +45,6 @@
DEFINE_MUTEX(ps3_gpu_mutex);
EXPORT_SYMBOL_GPL(ps3_gpu_mutex);
-#if !defined(CONFIG_SMP)
-static void smp_send_stop(void) {}
-#endif
-
static union ps3_firmware_version ps3_firmware_version;
void ps3_get_firmware_version(union ps3_firmware_version *v)
diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c
index fafcaa0e81ef..ab69925d579b 100644
--- a/arch/powerpc/platforms/pseries/dtl.c
+++ b/arch/powerpc/platforms/pseries/dtl.c
@@ -25,6 +25,7 @@
#include <asm/smp.h>
#include <asm/system.h>
#include <asm/uaccess.h>
+#include <asm/firmware.h>
#include "plpar_wrappers.h"
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index 380420f8c400..9a2a6e32f00f 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -182,6 +182,8 @@ static void eeh_report_reset(struct pci_dev *dev, void *userdata)
if (!driver)
return;
+ dev->error_state = pci_channel_io_normal;
+
eeh_enable_irq(dev);
if (!driver->err_handler ||
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 80b513449f4c..be3581a8c294 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -333,7 +333,7 @@ static void xics_eoi_lpar(unsigned int virq)
lpar_xirr_info_set((0xff << 24) | irq);
}
-static void xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
+static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
{
unsigned int irq;
int status;
@@ -342,14 +342,14 @@ static void xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
irq = (unsigned int)irq_map[virq].hwirq;
if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
- return;
+ return -1;
status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
if (status) {
printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
__func__, irq, status);
- return;
+ return -1;
}
/*
@@ -363,7 +363,7 @@ static void xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
printk(KERN_WARNING
"%s: No online cpus in the mask %s for irq %d\n",
__func__, cpulist, virq);
- return;
+ return -1;
}
status = rtas_call(ibm_set_xive, 3, 1, NULL,
@@ -372,8 +372,10 @@ static void xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
if (status) {
printk(KERN_ERR "%s: ibm,set-xive irq=%u returns %d\n",
__func__, irq, status);
- return;
+ return -1;
}
+
+ return 0;
}
static struct irq_chip xics_pic_direct = {
diff --git a/arch/powerpc/sysdev/cpm2.c b/arch/powerpc/sysdev/cpm2.c
index fd969f0e3121..eb5927212fab 100644
--- a/arch/powerpc/sysdev/cpm2.c
+++ b/arch/powerpc/sysdev/cpm2.c
@@ -61,7 +61,7 @@ EXPORT_SYMBOL(cpm2_immr);
void __init cpm2_reset(void)
{
#ifdef CONFIG_PPC_85xx
- cpm2_immr = ioremap(CPM_MAP_ADDR, CPM_MAP_SIZE);
+ cpm2_immr = ioremap(get_immrbase() + 0x80000, CPM_MAP_SIZE);
#else
cpm2_immr = ioremap(get_immrbase(), CPM_MAP_SIZE);
#endif
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 78021d8afc53..94d8b3feb1ea 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -152,6 +152,10 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
out_be32(&pci->piw[2].piwbar,0x00000000);
out_be32(&pci->piw[2].piwar, PIWAR_2G);
+ /* Save the base address and size covered by inbound window mappings */
+ hose->dma_window_base_cur = 0x00000000;
+ hose->dma_window_size = 0x80000000;
+
iounmap(pci);
}
@@ -281,6 +285,8 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8543, quirk_fsl_pcie_header);
DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8547E, quirk_fsl_pcie_header);
DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8545E, quirk_fsl_pcie_header);
DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8545, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8569E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8569, quirk_fsl_pcie_header);
DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8568E, quirk_fsl_pcie_header);
DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8568, quirk_fsl_pcie_header);
DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8567E, quirk_fsl_pcie_header);
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index a0fa4ebb39c6..abdb124e1e2f 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -18,6 +18,7 @@
#include <linux/types.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
+#include <linux/device.h>
#include <linux/rio.h>
#include <linux/rio_drv.h>
#include <linux/of_platform.h>
@@ -159,6 +160,7 @@ struct rio_msg_rx_ring {
};
struct rio_priv {
+ struct device *dev;
void __iomem *regs_win;
struct rio_atmu_regs __iomem *atmu_regs;
struct rio_atmu_regs __iomem *maint_atmu_regs;
@@ -484,13 +486,13 @@ int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entr
for (i = 0; i < priv->msg_tx_ring.size; i++) {
priv->msg_tx_ring.virt_buffer[i] =
- dma_alloc_coherent(NULL, RIO_MSG_BUFFER_SIZE,
+ dma_alloc_coherent(priv->dev, RIO_MSG_BUFFER_SIZE,
&priv->msg_tx_ring.phys_buffer[i], GFP_KERNEL);
if (!priv->msg_tx_ring.virt_buffer[i]) {
rc = -ENOMEM;
for (j = 0; j < priv->msg_tx_ring.size; j++)
if (priv->msg_tx_ring.virt_buffer[j])
- dma_free_coherent(NULL,
+ dma_free_coherent(priv->dev,
RIO_MSG_BUFFER_SIZE,
priv->msg_tx_ring.
virt_buffer[j],
@@ -501,7 +503,7 @@ int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entr
}
/* Initialize outbound message descriptor ring */
- priv->msg_tx_ring.virt = dma_alloc_coherent(NULL,
+ priv->msg_tx_ring.virt = dma_alloc_coherent(priv->dev,
priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
&priv->msg_tx_ring.phys, GFP_KERNEL);
if (!priv->msg_tx_ring.virt) {
@@ -549,12 +551,13 @@ int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entr
return rc;
out_irq:
- dma_free_coherent(NULL, priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
+ dma_free_coherent(priv->dev,
+ priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
priv->msg_tx_ring.virt, priv->msg_tx_ring.phys);
out_dma:
for (i = 0; i < priv->msg_tx_ring.size; i++)
- dma_free_coherent(NULL, RIO_MSG_BUFFER_SIZE,
+ dma_free_coherent(priv->dev, RIO_MSG_BUFFER_SIZE,
priv->msg_tx_ring.virt_buffer[i],
priv->msg_tx_ring.phys_buffer[i]);
@@ -576,7 +579,8 @@ void rio_close_outb_mbox(struct rio_mport *mport, int mbox)
out_be32(&priv->msg_regs->omr, 0);
/* Free ring */
- dma_free_coherent(NULL, priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
+ dma_free_coherent(priv->dev,
+ priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
priv->msg_tx_ring.virt, priv->msg_tx_ring.phys);
/* Free interrupt */
@@ -654,7 +658,7 @@ int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entri
priv->msg_rx_ring.virt_buffer[i] = NULL;
/* Initialize inbound message ring */
- priv->msg_rx_ring.virt = dma_alloc_coherent(NULL,
+ priv->msg_rx_ring.virt = dma_alloc_coherent(priv->dev,
priv->msg_rx_ring.size * RIO_MAX_MSG_SIZE,
&priv->msg_rx_ring.phys, GFP_KERNEL);
if (!priv->msg_rx_ring.virt) {
@@ -673,7 +677,7 @@ int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entri
rc = request_irq(IRQ_RIO_RX(mport), fsl_rio_rx_handler, 0,
"msg_rx", (void *)mport);
if (rc < 0) {
- dma_free_coherent(NULL, RIO_MSG_BUFFER_SIZE,
+ dma_free_coherent(priv->dev, RIO_MSG_BUFFER_SIZE,
priv->msg_tx_ring.virt_buffer[i],
priv->msg_tx_ring.phys_buffer[i]);
goto out;
@@ -713,7 +717,7 @@ void rio_close_inb_mbox(struct rio_mport *mport, int mbox)
out_be32(&priv->msg_regs->imr, 0);
/* Free ring */
- dma_free_coherent(NULL, priv->msg_rx_ring.size * RIO_MAX_MSG_SIZE,
+ dma_free_coherent(priv->dev, priv->msg_rx_ring.size * RIO_MAX_MSG_SIZE,
priv->msg_rx_ring.virt, priv->msg_rx_ring.phys);
/* Free interrupt */
@@ -890,7 +894,7 @@ static int fsl_rio_doorbell_init(struct rio_mport *mport)
}
/* Initialize inbound doorbells */
- priv->dbell_ring.virt = dma_alloc_coherent(NULL, 512 *
+ priv->dbell_ring.virt = dma_alloc_coherent(priv->dev, 512 *
DOORBELL_MESSAGE_SIZE, &priv->dbell_ring.phys, GFP_KERNEL);
if (!priv->dbell_ring.virt) {
printk(KERN_ERR "RIO: unable allocate inbound doorbell ring\n");
@@ -911,7 +915,7 @@ static int fsl_rio_doorbell_init(struct rio_mport *mport)
"dbell_rx", (void *)mport);
if (rc < 0) {
iounmap(priv->dbell_win);
- dma_free_coherent(NULL, 512 * DOORBELL_MESSAGE_SIZE,
+ dma_free_coherent(priv->dev, 512 * DOORBELL_MESSAGE_SIZE,
priv->dbell_ring.virt, priv->dbell_ring.phys);
printk(KERN_ERR
"MPC85xx RIO: unable to request inbound doorbell irq");
@@ -1087,6 +1091,8 @@ int fsl_rio_setup(struct of_device *dev)
rio_init_mbox_res(&port->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0);
strcpy(port->name, "RIO0 mport");
+ priv->dev = &dev->dev;
+
port->ops = ops;
port->host_deviceid = fsl_rio_get_hdid(port->id);
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index afe8dbc964aa..bd1b74dad739 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -425,16 +425,10 @@ static int __init setup_rstcr(void)
struct device_node *np;
np = of_find_node_by_name(NULL, "global-utilities");
if ((np && of_get_property(np, "fsl,has-rstcr", NULL))) {
- const u32 *prop = of_get_property(np, "reg", NULL);
- if (prop) {
- /* map reset control register
- * 0xE00B0 is offset of reset control register
- */
- rstcr = ioremap(get_immrbase() + *prop + 0xB0, 0xff);
- if (!rstcr)
- printk (KERN_EMERG "Error: reset control "
- "register not mapped!\n");
- }
+ rstcr = of_iomap(np, 0) + 0xb0;
+ if (!rstcr)
+ printk (KERN_EMERG "Error: reset control register "
+ "not mapped!\n");
} else
printk (KERN_INFO "rstcr compatible register does not exist!\n");
if (np)
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 21b956701596..f4cbd15cf22f 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -807,7 +807,7 @@ static void mpic_end_ipi(unsigned int irq)
#endif /* CONFIG_SMP */
-void mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
+int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
{
struct mpic *mpic = mpic_from_irq(irq);
unsigned int src = mpic_irq_to_hw(irq);
@@ -824,6 +824,8 @@ void mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION),
mpic_physmask(cpus_addr(tmp)[0]));
}
+
+ return 0;
}
static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
diff --git a/arch/powerpc/sysdev/mpic.h b/arch/powerpc/sysdev/mpic.h
index 3cef2af10f42..eff433c322a0 100644
--- a/arch/powerpc/sysdev/mpic.h
+++ b/arch/powerpc/sysdev/mpic.h
@@ -36,6 +36,6 @@ static inline int mpic_pasemi_msi_init(struct mpic *mpic)
extern int mpic_set_irq_type(unsigned int virq, unsigned int flow_type);
extern void mpic_set_vector(unsigned int virq, unsigned int vector);
-extern void mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask);
+extern int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask);
#endif /* _POWERPC_SYSDEV_MPIC_H */
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index 01bce3784b0a..b28b0e512d67 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -61,6 +61,7 @@ struct qe_immap __iomem *qe_immr;
EXPORT_SYMBOL(qe_immr);
static struct qe_snum snums[QE_NUM_OF_SNUM]; /* Dynamically allocated SNUMs */
+static unsigned int qe_num_of_snum;
static phys_addr_t qebase = -1;
@@ -264,10 +265,14 @@ static void qe_snums_init(void)
0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
- 0xD8, 0xD9, 0xE8, 0xE9,
+ 0xD8, 0xD9, 0xE8, 0xE9, 0x08, 0x09, 0x18, 0x19,
+ 0x28, 0x29, 0x38, 0x39, 0x48, 0x49, 0x58, 0x59,
+ 0x68, 0x69, 0x78, 0x79, 0x80, 0x81,
};
- for (i = 0; i < QE_NUM_OF_SNUM; i++) {
+ qe_num_of_snum = qe_get_num_of_snums();
+
+ for (i = 0; i < qe_num_of_snum; i++) {
snums[i].num = snum_init[i];
snums[i].state = QE_SNUM_STATE_FREE;
}
@@ -280,7 +285,7 @@ int qe_get_snum(void)
int i;
spin_lock_irqsave(&qe_lock, flags);
- for (i = 0; i < QE_NUM_OF_SNUM; i++) {
+ for (i = 0; i < qe_num_of_snum; i++) {
if (snums[i].state == QE_SNUM_STATE_FREE) {
snums[i].state = QE_SNUM_STATE_USED;
snum = snums[i].num;
@@ -297,7 +302,7 @@ void qe_put_snum(u8 snum)
{
int i;
- for (i = 0; i < QE_NUM_OF_SNUM; i++) {
+ for (i = 0; i < qe_num_of_snum; i++) {
if (snums[i].num == snum) {
snums[i].state = QE_SNUM_STATE_FREE;
break;
@@ -575,3 +580,65 @@ struct qe_firmware_info *qe_get_firmware_info(void)
}
EXPORT_SYMBOL(qe_get_firmware_info);
+unsigned int qe_get_num_of_risc(void)
+{
+ struct device_node *qe;
+ int size;
+ unsigned int num_of_risc = 0;
+ const u32 *prop;
+
+ qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
+ if (!qe) {
+ /* Older devices trees did not have an "fsl,qe"
+ * compatible property, so we need to look for
+ * the QE node by name.
+ */
+ qe = of_find_node_by_type(NULL, "qe");
+ if (!qe)
+ return num_of_risc;
+ }
+
+ prop = of_get_property(qe, "fsl,qe-num-riscs", &size);
+ if (prop && size == sizeof(*prop))
+ num_of_risc = *prop;
+
+ of_node_put(qe);
+
+ return num_of_risc;
+}
+EXPORT_SYMBOL(qe_get_num_of_risc);
+
+unsigned int qe_get_num_of_snums(void)
+{
+ struct device_node *qe;
+ int size;
+ unsigned int num_of_snums;
+ const u32 *prop;
+
+ num_of_snums = 28; /* The default number of snum for threads is 28 */
+ qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
+ if (!qe) {
+ /* Older devices trees did not have an "fsl,qe"
+ * compatible property, so we need to look for
+ * the QE node by name.
+ */
+ qe = of_find_node_by_type(NULL, "qe");
+ if (!qe)
+ return num_of_snums;
+ }
+
+ prop = of_get_property(qe, "fsl,qe-num-snums", &size);
+ if (prop && size == sizeof(*prop)) {
+ num_of_snums = *prop;
+ if ((num_of_snums < 28) || (num_of_snums > QE_NUM_OF_SNUM)) {
+ /* No QE ever has fewer than 28 SNUMs */
+ pr_err("QE: number of snum is invalid\n");
+ return -EINVAL;
+ }
+ }
+
+ of_node_put(qe);
+
+ return num_of_snums;
+}
+EXPORT_SYMBOL(qe_get_num_of_snums);
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 2eca5fe0e75b..1094787e97e5 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -567,6 +567,24 @@ bool "s390 guest support for KVM (EXPERIMENTAL)"
the KVM hypervisor. This will add detection for KVM as well as a
virtio transport. If KVM is detected, the virtio console will be
the default console.
+
+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.
+
endmenu
source "net/Kconfig"
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index 27b70d8a359c..1dfc7100c7ee 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -98,7 +98,7 @@ static DECLARE_WORK(appldata_work, appldata_work_fn);
/*
* Ops list
*/
-static DEFINE_SPINLOCK(appldata_ops_lock);
+static DEFINE_MUTEX(appldata_ops_mutex);
static LIST_HEAD(appldata_ops_list);
@@ -129,14 +129,14 @@ static void appldata_work_fn(struct work_struct *work)
i = 0;
get_online_cpus();
- spin_lock(&appldata_ops_lock);
+ mutex_lock(&appldata_ops_mutex);
list_for_each(lh, &appldata_ops_list) {
ops = list_entry(lh, struct appldata_ops, list);
if (ops->active == 1) {
ops->callback(ops->data);
}
}
- spin_unlock(&appldata_ops_lock);
+ mutex_unlock(&appldata_ops_mutex);
put_online_cpus();
}
@@ -176,7 +176,7 @@ static void __appldata_mod_vtimer_wrap(void *p) {
struct vtimer_list *timer;
u64 expires;
} *args = p;
- mod_virt_timer(args->timer, args->expires);
+ mod_virt_timer_periodic(args->timer, args->expires);
}
#define APPLDATA_ADD_TIMER 0
@@ -338,7 +338,7 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp,
struct list_head *lh;
found = 0;
- spin_lock(&appldata_ops_lock);
+ mutex_lock(&appldata_ops_mutex);
list_for_each(lh, &appldata_ops_list) {
tmp_ops = list_entry(lh, struct appldata_ops, list);
if (&tmp_ops->ctl_table[2] == ctl) {
@@ -346,15 +346,15 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp,
}
}
if (!found) {
- spin_unlock(&appldata_ops_lock);
+ mutex_unlock(&appldata_ops_mutex);
return -ENODEV;
}
ops = ctl->data;
if (!try_module_get(ops->owner)) { // protect this function
- spin_unlock(&appldata_ops_lock);
+ mutex_unlock(&appldata_ops_mutex);
return -ENODEV;
}
- spin_unlock(&appldata_ops_lock);
+ mutex_unlock(&appldata_ops_mutex);
if (!*lenp || *ppos) {
*lenp = 0;
@@ -378,11 +378,11 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp,
return -EFAULT;
}
- spin_lock(&appldata_ops_lock);
+ mutex_lock(&appldata_ops_mutex);
if ((buf[0] == '1') && (ops->active == 0)) {
// protect work queue callback
if (!try_module_get(ops->owner)) {
- spin_unlock(&appldata_ops_lock);
+ mutex_unlock(&appldata_ops_mutex);
module_put(ops->owner);
return -ENODEV;
}
@@ -407,7 +407,7 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp,
"failed with rc=%d\n", ops->name, rc);
module_put(ops->owner);
}
- spin_unlock(&appldata_ops_lock);
+ mutex_unlock(&appldata_ops_mutex);
out:
*lenp = len;
*ppos += len;
@@ -433,9 +433,9 @@ int appldata_register_ops(struct appldata_ops *ops)
if (!ops->ctl_table)
return -ENOMEM;
- spin_lock(&appldata_ops_lock);
+ mutex_lock(&appldata_ops_mutex);
list_add(&ops->list, &appldata_ops_list);
- spin_unlock(&appldata_ops_lock);
+ mutex_unlock(&appldata_ops_mutex);
ops->ctl_table[0].procname = appldata_proc_name;
ops->ctl_table[0].maxlen = 0;
@@ -452,9 +452,9 @@ int appldata_register_ops(struct appldata_ops *ops)
goto out;
return 0;
out:
- spin_lock(&appldata_ops_lock);
+ mutex_lock(&appldata_ops_mutex);
list_del(&ops->list);
- spin_unlock(&appldata_ops_lock);
+ mutex_unlock(&appldata_ops_mutex);
kfree(ops->ctl_table);
return -ENOMEM;
}
@@ -466,9 +466,9 @@ out:
*/
void appldata_unregister_ops(struct appldata_ops *ops)
{
- spin_lock(&appldata_ops_lock);
+ mutex_lock(&appldata_ops_mutex);
list_del(&ops->list);
- spin_unlock(&appldata_ops_lock);
+ mutex_unlock(&appldata_ops_mutex);
unregister_sysctl_table(ops->sysctl_header);
kfree(ops->ctl_table);
}
diff --git a/arch/s390/appldata/appldata_mem.c b/arch/s390/appldata/appldata_mem.c
index 3ed56b7d1b2f..4188cbe63a54 100644
--- a/arch/s390/appldata/appldata_mem.c
+++ b/arch/s390/appldata/appldata_mem.c
@@ -78,7 +78,7 @@ static void appldata_get_mem_data(void *data)
{
/*
* don't put large structures on the stack, we are
- * serialized through the appldata_ops_lock and can use static
+ * serialized through the appldata_ops_mutex and can use static
*/
static struct sysinfo val;
unsigned long ev[NR_VM_EVENT_ITEMS];
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 31e809c77790..d401d56c255f 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.29-rc4
-# Wed Feb 11 10:07:16 2009
+# Linux kernel version: 2.6.30-rc3
+# Thu Apr 23 09:29:52 2009
#
CONFIG_SCHED_MC=y
CONFIG_MMU=y
@@ -22,6 +22,7 @@ CONFIG_NO_DMA=y
CONFIG_GENERIC_LOCKBREAK=y
CONFIG_PGSTE=y
CONFIG_VIRT_CPU_ACCOUNTING=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_S390=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -37,6 +38,7 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
CONFIG_AUDIT=y
@@ -77,21 +79,24 @@ CONFIG_IPC_NS=y
# CONFIG_NET_NS is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=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
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-# CONFIG_COMPAT_BRK is not set
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -99,10 +104,12 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_KPROBES=y
CONFIG_HAVE_SYSCALL_WRAPPERS=y
@@ -111,6 +118,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_HAVE_DEFAULT_NO_SPIN_MUTEXES=y
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -124,7 +133,6 @@ CONFIG_MODVERSIONS=y
CONFIG_INIT_ALL_POSSIBLE=y
CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
-# CONFIG_BLK_DEV_IO_TRACE is not set
CONFIG_BLK_DEV_BSG=y
# CONFIG_BLK_DEV_INTEGRITY is not set
CONFIG_BLOCK_COMPAT=y
@@ -211,11 +219,12 @@ CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
#
# I/O subsystem configuration
#
-CONFIG_MACHCHK_WARNING=y
CONFIG_QDIO=y
CONFIG_CHSC_SCH=m
@@ -247,12 +256,12 @@ CONFIG_S390_HYPFS_FS=y
CONFIG_KEXEC=y
# CONFIG_ZFCPDUMP is not set
CONFIG_S390_GUEST=y
+CONFIG_SECCOMP=y
CONFIG_NET=y
#
# Networking options
#
-CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -374,6 +383,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
CONFIG_NET_SCHED=y
#
@@ -438,7 +448,6 @@ CONFIG_CAN_BCM=m
CONFIG_CAN_VCAN=m
# CONFIG_CAN_DEBUG_DEVICES is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -537,6 +546,7 @@ CONFIG_SCSI_FC_ATTRS=y
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DEBUG is not set
CONFIG_ZFCP=y
CONFIG_SCSI_DH=m
@@ -544,6 +554,10 @@ CONFIG_SCSI_DH_RDAC=m
CONFIG_SCSI_DH_HP_SW=m
CONFIG_SCSI_DH_EMC=m
CONFIG_SCSI_DH_ALUA=m
+CONFIG_SCSI_OSD_INITIATOR=m
+CONFIG_SCSI_OSD_ULD=m
+CONFIG_SCSI_OSD_DPRINT_SENSE=1
+# CONFIG_SCSI_OSD_DEBUG is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=y
CONFIG_MD_AUTODETECT=y
@@ -564,6 +578,7 @@ CONFIG_DM_MULTIPATH=m
# CONFIG_DM_DELAY is not set
# CONFIG_DM_UEVENT is not set
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_IFB is not set
CONFIG_DUMMY=m
CONFIG_BONDING=m
@@ -667,6 +682,7 @@ CONFIG_S390_VMUR=m
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
CONFIG_ACCESSIBILITY=y
+# CONFIG_AUXDISPLAY is not set
# CONFIG_STAGING is not set
#
@@ -676,6 +692,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -701,6 +718,11 @@ CONFIG_INOTIFY_USER=y
CONFIG_GENERIC_ACL=y
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -744,6 +766,8 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_EXOFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -758,7 +782,6 @@ CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -806,6 +829,7 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
+# CONFIG_DETECT_HUNG_TASK is not set
# CONFIG_SCHED_DEBUG is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -830,7 +854,6 @@ CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
# CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_FRAME_POINTER is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_KPROBES_SANITY_TEST is not set
@@ -840,7 +863,9 @@ CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -850,14 +875,17 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
CONFIG_SAMPLES=y
# CONFIG_SAMPLE_KOBJECT is not set
# CONFIG_SAMPLE_KPROBES is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
#
# Security options
@@ -882,10 +910,12 @@ CONFIG_CRYPTO_HASH=m
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG=m
CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_GF128MUL=m
# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_AUTHENC=m
# CONFIG_CRYPTO_TEST is not set
@@ -954,6 +984,7 @@ CONFIG_CRYPTO_SEED=m
# Compression
#
# CONFIG_CRYPTO_DEFLATE is not set
+CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
#
@@ -969,6 +1000,7 @@ CONFIG_CRYPTO_SHA512_S390=m
# CONFIG_CRYPTO_DES_S390 is not set
# CONFIG_CRYPTO_AES_S390 is not set
CONFIG_S390_PRNG=m
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
@@ -982,9 +1014,14 @@ CONFIG_CRC_T10DIF=y
CONFIG_CRC32=m
CONFIG_CRC7=m
CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
CONFIG_LZO_COMPRESS=m
CONFIG_LZO_DECOMPRESS=m
-CONFIG_PLIST=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_NLATTR=y
CONFIG_HAVE_KVM=y
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=m
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h
index de065b32381a..01a08020bc0e 100644
--- a/arch/s390/include/asm/compat.h
+++ b/arch/s390/include/asm/compat.h
@@ -5,6 +5,7 @@
*/
#include <linux/types.h>
#include <linux/sched.h>
+#include <linux/thread_info.h>
#define PSW32_MASK_PER 0x40000000UL
#define PSW32_MASK_DAT 0x04000000UL
@@ -163,12 +164,28 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
return (u32)(unsigned long)uptr;
}
+#ifdef CONFIG_COMPAT
+
+static inline int is_compat_task(void)
+{
+ return test_thread_flag(TIF_31BIT);
+}
+
+#else
+
+static inline int is_compat_task(void)
+{
+ return 0;
+}
+
+#endif
+
static inline void __user *compat_alloc_user_space(long len)
{
unsigned long stack;
stack = KSTK_ESP(current);
- if (test_thread_flag(TIF_31BIT))
+ if (is_compat_task())
stack &= 0x7fffffffUL;
return (void __user *) (stack - len);
}
diff --git a/arch/s390/include/asm/cpu.h b/arch/s390/include/asm/cpu.h
deleted file mode 100644
index d60a2eefb17b..000000000000
--- a/arch/s390/include/asm/cpu.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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 long long idle_count;
- unsigned long long idle_enter;
- unsigned long long idle_time;
-};
-
-DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
-
-void vtime_start_cpu(void);
-
-static inline void s390_idle_check(void)
-{
- if ((&__get_cpu_var(s390_idle))->idle_enter != 0ULL)
- vtime_start_cpu();
-}
-
-#endif /* _ASM_S390_CPU_H_ */
diff --git a/arch/s390/include/asm/cpuid.h b/arch/s390/include/asm/cpuid.h
new file mode 100644
index 000000000000..07836a2e5222
--- /dev/null
+++ b/arch/s390/include/asm/cpuid.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright IBM Corp. 2000,2009
+ * Author(s): Hartmut Penner <hp@de.ibm.com>,
+ * Martin Schwidefsky <schwidefsky@de.ibm.com>
+ * Christian Ehrhardt <ehrhardt@de.ibm.com>
+ */
+
+#ifndef _ASM_S390_CPUID_H_
+#define _ASM_S390_CPUID_H_
+
+/*
+ * CPU type and hardware bug flags. Kept separately for each CPU.
+ * Members of this structure are referenced in head.S, so think twice
+ * before touching them. [mj]
+ */
+
+typedef struct
+{
+ unsigned int version : 8;
+ unsigned int ident : 24;
+ unsigned int machine : 16;
+ unsigned int unused : 16;
+} __attribute__ ((packed)) cpuid_t;
+
+#endif /* _ASM_S390_CPUID_H_ */
diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h
index 95b0f7db3c69..ec917d42ee6d 100644
--- a/arch/s390/include/asm/cputime.h
+++ b/arch/s390/include/asm/cputime.h
@@ -9,6 +9,9 @@
#ifndef _S390_CPUTIME_H
#define _S390_CPUTIME_H
+#include <linux/types.h>
+#include <linux/percpu.h>
+#include <linux/spinlock.h>
#include <asm/div64.h>
/* We want to use full resolution of the CPU timer: 2**-12 micro-seconds. */
@@ -174,4 +177,24 @@ cputime64_to_clock_t(cputime64_t cputime)
return __div(cputime, 4096000000ULL / USER_HZ);
}
+struct s390_idle_data {
+ spinlock_t lock;
+ unsigned long long idle_count;
+ unsigned long long idle_enter;
+ unsigned long long idle_time;
+};
+
+DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
+
+void vtime_start_cpu(void);
+cputime64_t s390_get_idle_time(int cpu);
+
+#define arch_idle_time(cpu) s390_get_idle_time(cpu)
+
+static inline void s390_idle_check(void)
+{
+ if ((&__get_cpu_var(s390_idle))->idle_enter != 0ULL)
+ vtime_start_cpu();
+}
+
#endif /* _S390_CPUTIME_H */
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index c6e674f5fca9..54ea39f96ecd 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -15,6 +15,7 @@
#define ASM_KVM_HOST_H
#include <linux/kvm_host.h>
#include <asm/debug.h>
+#include <asm/cpuid.h>
#define KVM_MAX_VCPUS 64
#define KVM_MEMORY_SLOTS 32
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h
index b349f1c7fdfa..713fe9fb1fcc 100644
--- a/arch/s390/include/asm/lowcore.h
+++ b/arch/s390/include/asm/lowcore.h
@@ -30,6 +30,7 @@
#define __LC_SUBCHANNEL_NR 0x00ba
#define __LC_IO_INT_PARM 0x00bc
#define __LC_IO_INT_WORD 0x00c0
+#define __LC_STFL_FAC_LIST 0x00c8
#define __LC_MCCK_CODE 0x00e8
#define __LC_DUMP_REIPL 0x0e00
@@ -66,6 +67,7 @@
#define __LC_USER_EXEC_ASCE 0x02ac
#define __LC_CPUID 0x02b0
#define __LC_INT_CLOCK 0x02c8
+#define __LC_MACHINE_FLAGS 0x02d8
#define __LC_IRB 0x0300
#define __LC_PFAULT_INTPARM 0x0080
#define __LC_CPU_TIMER_SAVE_AREA 0x00d8
@@ -110,6 +112,7 @@
#define __LC_CPUID 0x0320
#define __LC_INT_CLOCK 0x0340
#define __LC_VDSO_PER_CPU 0x0350
+#define __LC_MACHINE_FLAGS 0x0358
#define __LC_IRB 0x0380
#define __LC_PASTE 0x03c0
#define __LC_PFAULT_INTPARM 0x11b8
@@ -127,9 +130,9 @@
#ifndef __ASSEMBLY__
-#include <asm/processor.h>
+#include <asm/cpuid.h>
+#include <asm/ptrace.h>
#include <linux/types.h>
-#include <asm/sigp.h>
void restart_int_handler(void);
void ext_int_handler(void);
@@ -277,7 +280,8 @@ struct _lowcore
__u32 ext_call_fast; /* 0x02c4 */
__u64 int_clock; /* 0x02c8 */
__u64 clock_comparator; /* 0x02d0 */
- __u8 pad_0x02d8[0x0300-0x02d8]; /* 0x02d8 */
+ __u32 machine_flags; /* 0x02d8 */
+ __u8 pad_0x02dc[0x0300-0x02dc]; /* 0x02dc */
/* Interrupt response block */
__u8 irb[64]; /* 0x0300 */
@@ -381,7 +385,8 @@ struct _lowcore
__u64 int_clock; /* 0x0340 */
__u64 clock_comparator; /* 0x0348 */
__u64 vdso_per_cpu_data; /* 0x0350 */
- __u8 pad_0x0358[0x0380-0x0358]; /* 0x0358 */
+ __u64 machine_flags; /* 0x0358 */
+ __u8 pad_0x0360[0x0380-0x0360]; /* 0x0360 */
/* Interrupt response block. */
__u8 irb[64]; /* 0x0380 */
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 61862b3ac794..c139fa7b8e89 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -14,7 +14,10 @@
#define __ASM_S390_PROCESSOR_H
#include <linux/linkage.h>
+#include <asm/cpuid.h>
+#include <asm/page.h>
#include <asm/ptrace.h>
+#include <asm/setup.h>
#ifdef __KERNEL__
/*
@@ -23,20 +26,6 @@
*/
#define current_text_addr() ({ void *pc; asm("basr %0,0" : "=a" (pc)); pc; })
-/*
- * CPU type and hardware bug flags. Kept separately for each CPU.
- * Members of this structure are referenced in head.S, so think twice
- * before touching them. [mj]
- */
-
-typedef struct
-{
- unsigned int version : 8;
- unsigned int ident : 24;
- unsigned int machine : 16;
- unsigned int unused : 16;
-} __attribute__ ((packed)) cpuid_t;
-
static inline void get_cpu_id(cpuid_t *ptr)
{
asm volatile("stidp 0(%1)" : "=m" (*ptr) : "a" (ptr));
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index f1b051630c50..539263fc9ab9 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -313,8 +313,6 @@ typedef struct
#ifdef __KERNEL__
-#include <asm/setup.h>
-#include <asm/page.h>
/*
* The pt_regs struct defines the way the registers are stored on
diff --git a/arch/s390/include/asm/seccomp.h b/arch/s390/include/asm/seccomp.h
new file mode 100644
index 000000000000..781a9cf9b002
--- /dev/null
+++ b/arch/s390/include/asm/seccomp.h
@@ -0,0 +1,16 @@
+#ifndef _ASM_S390_SECCOMP_H
+#define _ASM_S390_SECCOMP_H
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_sigreturn
+
+#define __NR_seccomp_read_32 __NR_read
+#define __NR_seccomp_write_32 __NR_write
+#define __NR_seccomp_exit_32 __NR_exit
+#define __NR_seccomp_sigreturn_32 __NR_sigreturn
+
+#endif /* _ASM_S390_SECCOMP_H */
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h
index e8bd6ac22c99..38b0fc221ed7 100644
--- a/arch/s390/include/asm/setup.h
+++ b/arch/s390/include/asm/setup.h
@@ -14,6 +14,7 @@
#ifdef __KERNEL__
+#include <asm/lowcore.h>
#include <asm/types.h>
#define PARMAREA 0x10400
@@ -63,7 +64,6 @@ extern unsigned int s390_noexec;
/*
* Machine features detected in head.S
*/
-extern unsigned long machine_flags;
#define MACHINE_FLAG_VM (1UL << 0)
#define MACHINE_FLAG_IEEE (1UL << 1)
@@ -77,28 +77,28 @@ extern unsigned long machine_flags;
#define MACHINE_FLAG_HPAGE (1UL << 10)
#define MACHINE_FLAG_PFMF (1UL << 11)
-#define MACHINE_IS_VM (machine_flags & MACHINE_FLAG_VM)
-#define MACHINE_IS_KVM (machine_flags & MACHINE_FLAG_KVM)
-#define MACHINE_HAS_DIAG9C (machine_flags & MACHINE_FLAG_DIAG9C)
+#define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM)
+#define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM)
+#define MACHINE_HAS_DIAG9C (S390_lowcore.machine_flags & MACHINE_FLAG_DIAG9C)
#ifndef __s390x__
-#define MACHINE_HAS_IEEE (machine_flags & MACHINE_FLAG_IEEE)
-#define MACHINE_HAS_CSP (machine_flags & MACHINE_FLAG_CSP)
+#define MACHINE_HAS_IEEE (S390_lowcore.machine_flags & MACHINE_FLAG_IEEE)
+#define MACHINE_HAS_CSP (S390_lowcore.machine_flags & MACHINE_FLAG_CSP)
#define MACHINE_HAS_IDTE (0)
#define MACHINE_HAS_DIAG44 (1)
-#define MACHINE_HAS_MVPG (machine_flags & MACHINE_FLAG_MVPG)
+#define MACHINE_HAS_MVPG (S390_lowcore.machine_flags & MACHINE_FLAG_MVPG)
#define MACHINE_HAS_MVCOS (0)
#define MACHINE_HAS_HPAGE (0)
#define MACHINE_HAS_PFMF (0)
#else /* __s390x__ */
#define MACHINE_HAS_IEEE (1)
#define MACHINE_HAS_CSP (1)
-#define MACHINE_HAS_IDTE (machine_flags & MACHINE_FLAG_IDTE)
-#define MACHINE_HAS_DIAG44 (machine_flags & MACHINE_FLAG_DIAG44)
+#define MACHINE_HAS_IDTE (S390_lowcore.machine_flags & MACHINE_FLAG_IDTE)
+#define MACHINE_HAS_DIAG44 (S390_lowcore.machine_flags & MACHINE_FLAG_DIAG44)
#define MACHINE_HAS_MVPG (1)
-#define MACHINE_HAS_MVCOS (machine_flags & MACHINE_FLAG_MVCOS)
-#define MACHINE_HAS_HPAGE (machine_flags & MACHINE_FLAG_HPAGE)
-#define MACHINE_HAS_PFMF (machine_flags & MACHINE_FLAG_PFMF)
+#define MACHINE_HAS_MVCOS (S390_lowcore.machine_flags & MACHINE_FLAG_MVCOS)
+#define MACHINE_HAS_HPAGE (S390_lowcore.machine_flags & MACHINE_FLAG_HPAGE)
+#define MACHINE_HAS_PFMF (S390_lowcore.machine_flags & MACHINE_FLAG_PFMF)
#endif /* __s390x__ */
#define ZFCPDUMP_HSA_SIZE (32UL<<20)
diff --git a/arch/s390/include/asm/spinlock.h b/arch/s390/include/asm/spinlock.h
index f3861b09ebb0..c9af0d19c7ab 100644
--- a/arch/s390/include/asm/spinlock.h
+++ b/arch/s390/include/asm/spinlock.h
@@ -122,8 +122,10 @@ static inline void __raw_spin_unlock(raw_spinlock_t *lp)
#define __raw_write_can_lock(x) ((x)->lock == 0)
extern void _raw_read_lock_wait(raw_rwlock_t *lp);
+extern void _raw_read_lock_wait_flags(raw_rwlock_t *lp, unsigned long flags);
extern int _raw_read_trylock_retry(raw_rwlock_t *lp);
extern void _raw_write_lock_wait(raw_rwlock_t *lp);
+extern void _raw_write_lock_wait_flags(raw_rwlock_t *lp, unsigned long flags);
extern int _raw_write_trylock_retry(raw_rwlock_t *lp);
static inline void __raw_read_lock(raw_rwlock_t *rw)
@@ -134,6 +136,14 @@ static inline void __raw_read_lock(raw_rwlock_t *rw)
_raw_read_lock_wait(rw);
}
+static inline void __raw_read_lock_flags(raw_rwlock_t *rw, unsigned long flags)
+{
+ unsigned int old;
+ old = rw->lock & 0x7fffffffU;
+ if (_raw_compare_and_swap(&rw->lock, old, old + 1) != old)
+ _raw_read_lock_wait_flags(rw, flags);
+}
+
static inline void __raw_read_unlock(raw_rwlock_t *rw)
{
unsigned int old, cmp;
@@ -151,6 +161,12 @@ static inline void __raw_write_lock(raw_rwlock_t *rw)
_raw_write_lock_wait(rw);
}
+static inline void __raw_write_lock_flags(raw_rwlock_t *rw, unsigned long flags)
+{
+ if (unlikely(_raw_compare_and_swap(&rw->lock, 0, 0x80000000) != 0))
+ _raw_write_lock_wait_flags(rw, flags);
+}
+
static inline void __raw_write_unlock(raw_rwlock_t *rw)
{
_raw_compare_and_swap(&rw->lock, 0x80000000, 0);
@@ -172,9 +188,6 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw)
return _raw_write_trylock_retry(rw);
}
-#define __raw_read_lock_flags(lock, flags) __raw_read_lock(lock)
-#define __raw_write_lock_flags(lock, flags) __raw_write_lock(lock)
-
#define _raw_read_relax(lock) cpu_relax()
#define _raw_write_relax(lock) cpu_relax()
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h
index c544aa524535..2f86653dda69 100644
--- a/arch/s390/include/asm/thread_info.h
+++ b/arch/s390/include/asm/thread_info.h
@@ -31,8 +31,9 @@
#define ASYNC_SIZE (PAGE_SIZE << ASYNC_ORDER)
#ifndef __ASSEMBLY__
-#include <asm/processor.h>
#include <asm/lowcore.h>
+#include <asm/page.h>
+#include <asm/processor.h>
/*
* low level task data that entry.S needs immediate access to
@@ -82,14 +83,15 @@ static inline struct thread_info *current_thread_info(void)
/*
* thread information flags bit numbers
*/
-#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
#define TIF_SIGPENDING 2 /* signal pending */
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_RESTART_SVC 4 /* restart svc with new svc number */
-#define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */
#define TIF_SINGLE_STEP 6 /* deliver sigtrap on return to user */
#define TIF_MCCK_PENDING 7 /* machine check handling is pending */
+#define TIF_SYSCALL_TRACE 8 /* syscall trace active */
+#define TIF_SYSCALL_AUDIT 9 /* syscall auditing active */
+#define TIF_SECCOMP 10 /* secure computing */
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling
TIF_NEED_RESCHED */
@@ -98,15 +100,16 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_RESTORE_SIGMASK 20 /* restore signal mask in do_signal() */
#define TIF_FREEZE 21 /* thread is freezing for suspend */
-#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_RESTART_SVC (1<<TIF_RESTART_SVC)
-#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
#define _TIF_SINGLE_STEP (1<<TIF_SINGLE_STEP)
#define _TIF_MCCK_PENDING (1<<TIF_MCCK_PENDING)
+#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
+#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
+#define _TIF_SECCOMP (1<<TIF_SECCOMP)
#define _TIF_USEDFPU (1<<TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_31BIT (1<<TIF_31BIT)
diff --git a/arch/s390/include/asm/timer.h b/arch/s390/include/asm/timer.h
index e4bcab739c19..814243cafdfe 100644
--- a/arch/s390/include/asm/timer.h
+++ b/arch/s390/include/asm/timer.h
@@ -41,6 +41,7 @@ extern void init_virt_timer(struct vtimer_list *timer);
extern void add_virt_timer(void *new);
extern void add_virt_timer_periodic(void *new);
extern int mod_virt_timer(struct vtimer_list *timer, __u64 expires);
+extern int mod_virt_timer_periodic(struct vtimer_list *timer, __u64 expires);
extern int del_virt_timer(struct vtimer_list *timer);
extern void init_cpu_vtimer(void);
diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h
index d744c3d62de5..cc21e3e20fd7 100644
--- a/arch/s390/include/asm/timex.h
+++ b/arch/s390/include/asm/timex.h
@@ -11,6 +11,9 @@
#ifndef _ASM_S390_TIMEX_H
#define _ASM_S390_TIMEX_H
+/* The value of the TOD clock for 1.1.1970. */
+#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
+
/* Inline functions for clock register access. */
static inline int set_clock(__u64 time)
{
@@ -85,4 +88,6 @@ int get_sync_clock(unsigned long long *clock);
void init_cpu_timer(void);
unsigned long long monotonic_clock(void);
+extern u64 sched_clock_base_cc;
+
#endif
diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h
index c8ad350d1444..f0f19e6ace6c 100644
--- a/arch/s390/include/asm/unistd.h
+++ b/arch/s390/include/asm/unistd.h
@@ -265,7 +265,9 @@
#define __NR_pipe2 325
#define __NR_dup3 326
#define __NR_epoll_create1 327
-#define NR_syscalls 328
+#define __NR_preadv 328
+#define __NR_pwritev 329
+#define NR_syscalls 330
/*
* There are some system calls that are not present on 64 bit, some
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 228e3105ded7..0657de7944fe 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -22,7 +22,7 @@ CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o \
processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o \
- vdso.o vtime.o sysinfo.o nmi.o
+ vdso.o vtime.o sysinfo.o nmi.o sclp.o
obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o)
obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index 67a60016babb..fa9905ce7d0b 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -27,6 +27,8 @@ int main(void)
DEFINE(__TI_flags, offsetof(struct thread_info, flags));
DEFINE(__TI_cpu, offsetof(struct thread_info, cpu));
DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count));
+ DEFINE(__TI_user_timer, offsetof(struct thread_info, user_timer));
+ DEFINE(__TI_system_timer, offsetof(struct thread_info, system_timer));
BLANK();
DEFINE(__PT_ARGS, offsetof(struct pt_regs, args));
DEFINE(__PT_PSW, offsetof(struct pt_regs, psw));
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 6cc87d8c8682..002c70d3cb75 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -702,20 +702,12 @@ asmlinkage long sys32_fstatat64(unsigned int dfd, char __user *filename,
struct stat64_emu31 __user* statbuf, int flag)
{
struct kstat stat;
- int error = -EINVAL;
-
- if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
- goto out;
-
- if (flag & AT_SYMLINK_NOFOLLOW)
- error = vfs_lstat_fd(dfd, filename, &stat);
- else
- error = vfs_stat_fd(dfd, filename, &stat);
+ int error;
- if (!error)
- error = cp_stat64(statbuf, &stat);
-out:
- return error;
+ error = vfs_fstatat(dfd, filename, &stat, flag);
+ if (error)
+ return error;
+ return cp_stat64(statbuf, &stat);
}
/*
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 87cf5a79a351..fb38af6316bb 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1805,3 +1805,21 @@ compat_sys_keyctl_wrapper:
llgfr %r5,%r5 # u32
llgfr %r6,%r6 # u32
jg compat_sys_keyctl # branch to system call
+
+ .globl compat_sys_preadv_wrapper
+compat_sys_preadv_wrapper:
+ llgfr %r2,%r2 # unsigned long
+ llgtr %r3,%r3 # compat_iovec *
+ llgfr %r4,%r4 # unsigned long
+ llgfr %r5,%r5 # u32
+ llgfr %r6,%r6 # u32
+ jg compat_sys_preadv # branch to system call
+
+ .globl compat_sys_pwritev_wrapper
+compat_sys_pwritev_wrapper:
+ llgfr %r2,%r2 # unsigned long
+ llgtr %r3,%r3 # compat_iovec *
+ llgfr %r4,%r4 # unsigned long
+ llgfr %r5,%r5 # u32
+ llgfr %r6,%r6 # u32
+ jg compat_sys_pwritev # branch to system call
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 4d221c81c849..cf09948faad6 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -34,8 +34,25 @@
char kernel_nss_name[NSS_NAME_SIZE + 1];
+static unsigned long machine_flags;
+
static void __init setup_boot_command_line(void);
+/*
+ * Get the TOD clock running.
+ */
+static void __init reset_tod_clock(void)
+{
+ u64 time;
+
+ if (store_clock(&time) == 0)
+ return;
+ /* TOD clock not running. Set the clock to Unix Epoch. */
+ if (set_clock(TOD_UNIX_EPOCH) != 0 || store_clock(&time) != 0)
+ disabled_wait(0);
+
+ sched_clock_base_cc = TOD_UNIX_EPOCH;
+}
#ifdef CONFIG_SHARED_KERNEL
int __init savesys_ipl_nss(char *cmd, const int cmdlen);
@@ -370,6 +387,7 @@ static void __init setup_boot_command_line(void)
*/
void __init startup_init(void)
{
+ reset_tod_clock();
ipl_save_parameters();
rescue_initrd();
clear_bss_section();
@@ -391,5 +409,6 @@ void __init startup_init(void)
setup_hpage();
sclp_facilities_detect();
detect_memory_layout(memory_chunk);
+ S390_lowcore.machine_flags = machine_flags;
lockdep_on();
}
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 1268aa2991bf..db25cdc21e12 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -53,6 +53,7 @@ _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
_TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
_TIF_MCCK_PENDING)
+_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | _TIF_SECCOMP>>8)
STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
STACK_SIZE = 1 << STACK_SHIFT
@@ -265,7 +266,7 @@ sysc_do_restart:
sth %r7,SP_SVCNR(%r15)
sll %r7,2 # svc number *4
l %r8,BASED(.Lsysc_table)
- tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
+ tm __TI_flags+2(%r9),_TIF_SYSCALL
l %r8,0(%r7,%r8) # get system call addr.
bnz BASED(sysc_tracesys)
basr %r14,%r8 # call sys_xxxx
@@ -405,7 +406,7 @@ sysc_tracego:
basr %r14,%r8 # call sys_xxx
st %r2,SP_R2(%r15) # store return value
sysc_tracenogo:
- tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
+ tm __TI_flags+2(%r9),_TIF_SYSCALL
bz BASED(sysc_return)
l %r1,BASED(.Ltrace_exit)
la %r2,SP_PTREGS(%r15) # load pt_regs
@@ -837,16 +838,29 @@ mcck_return:
__CPUINIT
.globl restart_int_handler
restart_int_handler:
+ basr %r1,0
+restart_base:
+ spt restart_vtime-restart_base(%r1)
+ stck __LC_LAST_UPDATE_CLOCK
+ mvc __LC_LAST_UPDATE_TIMER(8),restart_vtime-restart_base(%r1)
+ mvc __LC_EXIT_TIMER(8),restart_vtime-restart_base(%r1)
l %r15,__LC_SAVE_AREA+60 # load ksp
lctl %c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs
lam %a0,%a15,__LC_AREGS_SAVE_AREA
lm %r6,%r15,__SF_GPRS(%r15) # load registers from clone
+ l %r1,__LC_THREAD_INFO
+ mvc __LC_USER_TIMER(8),__TI_user_timer(%r1)
+ mvc __LC_SYSTEM_TIMER(8),__TI_system_timer(%r1)
+ xc __LC_STEAL_TIMER(8),__LC_STEAL_TIMER
stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on
basr %r14,0
l %r14,restart_addr-.(%r14)
br %r14 # branch to start_secondary
restart_addr:
.long start_secondary
+ .align 8
+restart_vtime:
+ .long 0x7fffffff,0xffffffff
.previous
#else
/*
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index c6fbde13971a..3cec9b504f5f 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -56,6 +56,7 @@ _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
_TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
_TIF_MCCK_PENDING)
+_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | _TIF_SECCOMP>>8)
#define BASED(name) name-system_call(%r13)
@@ -260,7 +261,7 @@ sysc_do_restart:
larl %r10,sys_call_table_emu # use 31 bit emulation system calls
sysc_noemu:
#endif
- tm __TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
+ tm __TI_flags+6(%r9),_TIF_SYSCALL
lgf %r8,0(%r7,%r10) # load address of system call routine
jnz sysc_tracesys
basr %r14,%r8 # call sys_xxxx
@@ -391,7 +392,7 @@ sysc_tracego:
basr %r14,%r8 # call sys_xxx
stg %r2,SP_R2(%r15) # store return value
sysc_tracenogo:
- tm __TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
+ tm __TI_flags+6(%r9),_TIF_SYSCALL
jz sysc_return
la %r2,SP_PTREGS(%r15) # load pt_regs
larl %r14,sysc_return # return point is sysc_return
@@ -831,14 +832,27 @@ mcck_return:
__CPUINIT
.globl restart_int_handler
restart_int_handler:
+ basr %r1,0
+restart_base:
+ spt restart_vtime-restart_base(%r1)
+ stck __LC_LAST_UPDATE_CLOCK
+ mvc __LC_LAST_UPDATE_TIMER(8),restart_vtime-restart_base(%r1)
+ mvc __LC_EXIT_TIMER(8),restart_vtime-restart_base(%r1)
lg %r15,__LC_SAVE_AREA+120 # load ksp
lghi %r10,__LC_CREGS_SAVE_AREA
lctlg %c0,%c15,0(%r10) # get new ctl regs
lghi %r10,__LC_AREGS_SAVE_AREA
lam %a0,%a15,0(%r10)
lmg %r6,%r15,__SF_GPRS(%r15) # load registers from clone
+ lg %r1,__LC_THREAD_INFO
+ mvc __LC_USER_TIMER(8),__TI_user_timer(%r1)
+ mvc __LC_SYSTEM_TIMER(8),__TI_system_timer(%r1)
+ xc __LC_STEAL_TIMER(8),__LC_STEAL_TIMER
stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on
jg start_secondary
+ .align 8
+restart_vtime:
+ .long 0x7fffffff,0xffffffff
.previous
#else
/*
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index 1046c2c9f8d1..ec6882348520 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -1,7 +1,5 @@
/*
- * arch/s390/kernel/head.S
- *
- * Copyright (C) IBM Corp. 1999,2006
+ * Copyright IBM Corp. 1999,2009
*
* Author(s): Hartmut Penner <hp@de.ibm.com>
* Martin Schwidefsky <schwidefsky@de.ibm.com>
@@ -23,6 +21,7 @@
*
*/
+#include <linux/init.h>
#include <asm/setup.h>
#include <asm/lowcore.h>
#include <asm/asm-offsets.h>
@@ -35,7 +34,7 @@
#define ARCH_OFFSET 0
#endif
-.section ".text.head","ax"
+__HEAD
#ifndef CONFIG_IPL
.org 0
.long 0x00080000,0x80000000+startup # Just a restart PSW
@@ -63,7 +62,7 @@
.org 0x100
#
# subroutine for loading from tape
-# Paramters:
+# Parameters:
# R1 = device number
# R2 = load address
.Lloader:
@@ -471,34 +470,74 @@ startup:basr %r13,0 # get base
.LPG0:
xc 0x200(256),0x200 # partially clear lowcore
xc 0x300(256),0x300
-
+ l %r1,5f-.LPG0(%r13)
+ stck 0(%r1)
+ spt 6f-.LPG0(%r13)
+ mvc __LC_LAST_UPDATE_CLOCK(8),0(%r1)
+ mvc __LC_LAST_UPDATE_TIMER(8),6f-.LPG0(%r13)
+ mvc __LC_EXIT_TIMER(8),5f-.LPG0(%r13)
#ifndef CONFIG_MARCH_G5
- # check processor version against MARCH_{G5,Z900,Z990,Z9_109,Z10}
- stidp __LC_CPUID # store cpuid
- lhi %r0,(3f-2f) / 2
- la %r1,2f-.LPG0(%r13)
-0: clc __LC_CPUID+4(2),0(%r1)
- jne 3f
- lpsw 1f-.LPG0(13) # machine type not good enough, crash
+ # check capabilities against MARCH_{G5,Z900,Z990,Z9_109,Z10}
+ xc __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST
+ stfl __LC_STFL_FAC_LIST # store facility list
+ tm __LC_STFL_FAC_LIST,0x01 # stfle available ?
+ jz 0f
+ la %r0,0
+ .insn s,0xb2b00000,__LC_STFL_FAC_LIST # store facility list extended
+0: l %r0,__LC_STFL_FAC_LIST
+ n %r0,2f+8-.LPG0(%r13)
+ cl %r0,2f+8-.LPG0(%r13)
+ jne 1f
+ l %r0,__LC_STFL_FAC_LIST+4
+ n %r0,2f+12-.LPG0(%r13)
+ cl %r0,2f+12-.LPG0(%r13)
+ je 3f
+1: l %r15,.Lstack-.LPG0(%r13)
+ ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union+THREAD_SIZE
+ ahi %r15,-96
+ la %r2,.Lals_string-.LPG0(%r13)
+ l %r3,.Lsclp_print-.LPG0(%r13)
+ basr %r14,%r3
+ lpsw 2f-.LPG0(%r13) # machine type not good enough, crash
+.Lals_string:
+ .asciz "The Linux kernel requires more recent processor hardware"
+.Lsclp_print:
+ .long _sclp_print_early
+.Lstack:
+ .long init_thread_union
.align 16
-1: .long 0x000a0000,0x00000000
-2:
+2: .long 0x000a0000,0x8badcccc
+#if defined(CONFIG_64BIT)
#if defined(CONFIG_MARCH_Z10)
- .short 0x9672, 0x2064, 0x2066, 0x2084, 0x2086, 0x2094, 0x2096
+ .long 0xc100efe3, 0xf0680000
#elif defined(CONFIG_MARCH_Z9_109)
- .short 0x9672, 0x2064, 0x2066, 0x2084, 0x2086
+ .long 0xc100efc3, 0x00000000
#elif defined(CONFIG_MARCH_Z990)
- .short 0x9672, 0x2064, 0x2066
+ .long 0xc0002000, 0x00000000
#elif defined(CONFIG_MARCH_Z900)
- .short 0x9672
+ .long 0xc0000000, 0x00000000
+#endif
+#else
+#if defined(CONFIG_MARCH_Z10)
+ .long 0x8100c880, 0x00000000
+#elif defined(CONFIG_MARCH_Z9_109)
+ .long 0x8100c880, 0x00000000
+#elif defined(CONFIG_MARCH_Z990)
+ .long 0x80002000, 0x00000000
+#elif defined(CONFIG_MARCH_Z900)
+ .long 0x80000000, 0x00000000
#endif
-3: la %r1,2(%r1)
- brct %r0,0b
+#endif
+3:
#endif
- l %r13,0f-.LPG0(%r13)
+ l %r13,4f-.LPG0(%r13)
b 0(%r13)
-0: .long startup_continue
+ .align 4
+4: .long startup_continue
+5: .long sched_clock_base_cc
+ .align 8
+6: .long 0x7fffffff,0xffffffff
#
# params at 10400 (setup.h)
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 6f3711a0eaaa..b8bf4b140065 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -23,6 +23,7 @@
#include <asm/ebcdic.h>
#include <asm/reset.h>
#include <asm/sclp.h>
+#include <asm/sigp.h>
#include <asm/checksum.h>
#define IPL_PARM_BLOCK_VERSION 0
diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c
index 4bfdc421d7e9..015e27da40eb 100644
--- a/arch/s390/kernel/nmi.c
+++ b/arch/s390/kernel/nmi.c
@@ -10,12 +10,13 @@
#include <linux/init.h>
#include <linux/errno.h>
+#include <linux/hardirq.h>
#include <linux/time.h>
#include <linux/module.h>
#include <asm/lowcore.h>
#include <asm/smp.h>
#include <asm/etr.h>
-#include <asm/cpu.h>
+#include <asm/cputime.h>
#include <asm/nmi.h>
#include <asm/crw.h>
@@ -253,7 +254,7 @@ void notrace s390_do_machine_check(struct pt_regs *regs)
struct mci *mci;
int umode;
- lockdep_off();
+ nmi_enter();
s390_idle_check();
mci = (struct mci *) &S390_lowcore.mcck_interruption_code;
@@ -363,7 +364,7 @@ void notrace s390_do_machine_check(struct pt_regs *regs)
mcck->warning = 1;
set_thread_flag(TIF_MCCK_PENDING);
}
- lockdep_on();
+ nmi_exit();
}
static int __init machine_check_init(void)
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index a3acd8e60aff..355f7a30c3f1 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -32,6 +32,7 @@
#include <linux/elfcore.h>
#include <linux/kernel_stat.h>
#include <linux/syscalls.h>
+#include <asm/compat.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/system.h>
@@ -204,7 +205,7 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
save_fp_regs(&p->thread.fp_regs);
/* Set a new TLS ? */
if (clone_flags & CLONE_SETTLS) {
- if (test_thread_flag(TIF_31BIT)) {
+ if (is_compat_task()) {
p->thread.acrs[0] = (unsigned int) regs->gprs[6];
} else {
p->thread.acrs[0] = (unsigned int)(regs->gprs[6] >> 32);
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 75c496f4f16d..b6fc1ae2ffcb 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -36,7 +36,8 @@
#include <linux/elf.h>
#include <linux/regset.h>
#include <linux/tracehook.h>
-
+#include <linux/seccomp.h>
+#include <asm/compat.h>
#include <asm/segment.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -69,7 +70,7 @@ FixPerRegisters(struct task_struct *task)
if (per_info->single_step) {
per_info->control_regs.bits.starting_addr = 0;
#ifdef CONFIG_COMPAT
- if (test_thread_flag(TIF_31BIT))
+ if (is_compat_task())
per_info->control_regs.bits.ending_addr = 0x7fffffffUL;
else
#endif
@@ -482,8 +483,7 @@ static int peek_user_compat(struct task_struct *child,
{
__u32 tmp;
- if (!test_thread_flag(TIF_31BIT) ||
- (addr & 3) || addr > sizeof(struct user) - 3)
+ if (!is_compat_task() || (addr & 3) || addr > sizeof(struct user) - 3)
return -EIO;
tmp = __peek_user_compat(child, addr);
@@ -584,8 +584,7 @@ static int __poke_user_compat(struct task_struct *child,
static int poke_user_compat(struct task_struct *child,
addr_t addr, addr_t data)
{
- if (!test_thread_flag(TIF_31BIT) ||
- (addr & 3) || addr > sizeof(struct user32) - 3)
+ if (!is_compat_task() || (addr & 3) || addr > sizeof(struct user32) - 3)
return -EIO;
return __poke_user_compat(child, addr, data);
@@ -642,6 +641,9 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
{
long ret;
+ /* Do the secure computing check first. */
+ secure_computing(regs->gprs[2]);
+
/*
* The sysc_tracesys code in entry.S stored the system
* call number to gprs[2].
@@ -660,7 +662,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
}
if (unlikely(current->audit_context))
- audit_syscall_entry(test_thread_flag(TIF_31BIT) ?
+ audit_syscall_entry(is_compat_task() ?
AUDIT_ARCH_S390 : AUDIT_ARCH_S390X,
regs->gprs[2], regs->orig_gpr2,
regs->gprs[3], regs->gprs[4],
diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c
index a0d2d55d7fb3..6b0686d78fc7 100644
--- a/arch/s390/kernel/s390_ext.c
+++ b/arch/s390/kernel/s390_ext.c
@@ -13,7 +13,7 @@
#include <linux/errno.h>
#include <linux/kernel_stat.h>
#include <linux/interrupt.h>
-#include <asm/cpu.h>
+#include <asm/cputime.h>
#include <asm/lowcore.h>
#include <asm/s390_ext.h>
#include <asm/irq_regs.h>
diff --git a/arch/s390/kernel/sclp.S b/arch/s390/kernel/sclp.S
new file mode 100644
index 000000000000..20639dfe0c42
--- /dev/null
+++ b/arch/s390/kernel/sclp.S
@@ -0,0 +1,327 @@
+/*
+ * Mini SCLP driver.
+ *
+ * Copyright IBM Corp. 2004,2009
+ *
+ * Author(s): Peter Oberparleiter <Peter.Oberparleiter@de.ibm.com>,
+ * Heiko Carstens <heiko.carstens@de.ibm.com>,
+ *
+ */
+
+LC_EXT_NEW_PSW = 0x58 # addr of ext int handler
+LC_EXT_INT_PARAM = 0x80 # addr of ext int parameter
+LC_EXT_INT_CODE = 0x86 # addr of ext int code
+
+#
+# Subroutine which waits synchronously until either an external interruption
+# or a timeout occurs.
+#
+# Parameters:
+# R2 = 0 for no timeout, non-zero for timeout in (approximated) seconds
+#
+# Returns:
+# R2 = 0 on interrupt, 2 on timeout
+# R3 = external interruption parameter if R2=0
+#
+
+.section ".init.text","ax"
+
+_sclp_wait_int:
+ stm %r6,%r15,24(%r15) # save registers
+ basr %r13,0 # get base register
+.LbaseS1:
+ ahi %r15,-96 # create stack frame
+ la %r8,LC_EXT_NEW_PSW # register int handler
+ mvc .LoldpswS1-.LbaseS1(8,%r13),0(%r8)
+ mvc 0(8,%r8),.LextpswS1-.LbaseS1(%r13)
+ lhi %r6,0x0200 # cr mask for ext int (cr0.54)
+ ltr %r2,%r2
+ jz .LsetctS1
+ ahi %r6,0x0800 # cr mask for clock int (cr0.52)
+ stck .LtimeS1-.LbaseS1(%r13) # initiate timeout
+ al %r2,.LtimeS1-.LbaseS1(%r13)
+ st %r2,.LtimeS1-.LbaseS1(%r13)
+ sckc .LtimeS1-.LbaseS1(%r13)
+
+.LsetctS1:
+ stctl %c0,%c0,.LctlS1-.LbaseS1(%r13) # enable required interrupts
+ l %r0,.LctlS1-.LbaseS1(%r13)
+ lhi %r1,~(0x200 | 0x800) # clear old values
+ nr %r1,%r0
+ or %r1,%r6 # set new value
+ st %r1,.LctlS1-.LbaseS1(%r13)
+ lctl %c0,%c0,.LctlS1-.LbaseS1(%r13)
+ st %r0,.LctlS1-.LbaseS1(%r13)
+ lhi %r2,2 # return code for timeout
+.LloopS1:
+ lpsw .LwaitpswS1-.LbaseS1(%r13) # wait until interrupt
+.LwaitS1:
+ lh %r7,LC_EXT_INT_CODE
+ chi %r7,0x1004 # timeout?
+ je .LtimeoutS1
+ chi %r7,0x2401 # service int?
+ jne .LloopS1
+ sr %r2,%r2
+ l %r3,LC_EXT_INT_PARAM
+.LtimeoutS1:
+ lctl %c0,%c0,.LctlS1-.LbaseS1(%r13) # restore interrupt setting
+ # restore old handler
+ mvc 0(8,%r8),.LoldpswS1-.LbaseS1(%r13)
+ lm %r6,%r15,120(%r15) # restore registers
+ br %r14 # return to caller
+
+ .align 8
+.LoldpswS1:
+ .long 0, 0 # old ext int PSW
+.LextpswS1:
+ .long 0x00080000, 0x80000000+.LwaitS1 # PSW to handle ext int
+.LwaitpswS1:
+ .long 0x010a0000, 0x00000000+.LloopS1 # PSW to wait for ext int
+.LtimeS1:
+ .quad 0 # current time
+.LctlS1:
+ .long 0 # CT0 contents
+
+#
+# Subroutine to synchronously issue a service call.
+#
+# Parameters:
+# R2 = command word
+# R3 = sccb address
+#
+# Returns:
+# R2 = 0 on success, 1 on failure
+# R3 = sccb response code if R2 = 0
+#
+
+_sclp_servc:
+ stm %r6,%r15,24(%r15) # save registers
+ ahi %r15,-96 # create stack frame
+ lr %r6,%r2 # save command word
+ lr %r7,%r3 # save sccb address
+.LretryS2:
+ lhi %r2,1 # error return code
+ .insn rre,0xb2200000,%r6,%r7 # servc
+ brc 1,.LendS2 # exit if not operational
+ brc 8,.LnotbusyS2 # go on if not busy
+ sr %r2,%r2 # wait until no longer busy
+ bras %r14,_sclp_wait_int
+ j .LretryS2 # retry
+.LnotbusyS2:
+ sr %r2,%r2 # wait until result
+ bras %r14,_sclp_wait_int
+ sr %r2,%r2
+ lh %r3,6(%r7)
+.LendS2:
+ lm %r6,%r15,120(%r15) # restore registers
+ br %r14
+
+#
+# Subroutine to set up the SCLP interface.
+#
+# Parameters:
+# R2 = 0 to activate, non-zero to deactivate
+#
+# Returns:
+# R2 = 0 on success, non-zero on failure
+#
+
+_sclp_setup:
+ stm %r6,%r15,24(%r15) # save registers
+ ahi %r15,-96 # create stack frame
+ basr %r13,0 # get base register
+.LbaseS3:
+ l %r6,.LsccbS0-.LbaseS3(%r13) # prepare init mask sccb
+ mvc 0(.LinitendS3-.LinitsccbS3,%r6),.LinitsccbS3-.LbaseS3(%r13)
+ ltr %r2,%r2 # initialization?
+ jz .LdoinitS3 # go ahead
+ # clear masks
+ xc .LinitmaskS3-.LinitsccbS3(8,%r6),.LinitmaskS3-.LinitsccbS3(%r6)
+.LdoinitS3:
+ l %r2,.LwritemaskS3-.LbaseS3(%r13)# get command word
+ lr %r3,%r6 # get sccb address
+ bras %r14,_sclp_servc # issue service call
+ ltr %r2,%r2 # servc successful?
+ jnz .LerrorS3
+ chi %r3,0x20 # write mask successful?
+ jne .LerrorS3
+ # check masks
+ la %r2,.LinitmaskS3-.LinitsccbS3(%r6)
+ l %r1,0(%r2) # receive mask ok?
+ n %r1,12(%r2)
+ cl %r1,0(%r2)
+ jne .LerrorS3
+ l %r1,4(%r2) # send mask ok?
+ n %r1,8(%r2)
+ cl %r1,4(%r2)
+ sr %r2,%r2
+ je .LendS3
+.LerrorS3:
+ lhi %r2,1 # error return code
+.LendS3:
+ lm %r6,%r15,120(%r15) # restore registers
+ br %r14
+.LwritemaskS3:
+ .long 0x00780005 # SCLP command for write mask
+.LinitsccbS3:
+ .word .LinitendS3-.LinitsccbS3
+ .byte 0,0,0,0
+ .word 0
+ .word 0
+ .word 4
+.LinitmaskS3:
+ .long 0x80000000
+ .long 0x40000000
+ .long 0
+ .long 0
+.LinitendS3:
+
+#
+# Subroutine which prints a given text to the SCLP console.
+#
+# Parameters:
+# R2 = address of nil-terminated ASCII text
+#
+# Returns:
+# R2 = 0 on success, 1 on failure
+#
+
+_sclp_print:
+ stm %r6,%r15,24(%r15) # save registers
+ ahi %r15,-96 # create stack frame
+ basr %r13,0 # get base register
+.LbaseS4:
+ l %r8,.LsccbS0-.LbaseS4(%r13) # prepare write data sccb
+ mvc 0(.LmtoS4-.LwritesccbS4,%r8),.LwritesccbS4-.LbaseS4(%r13)
+ la %r7,.LmtoS4-.LwritesccbS4(%r8) # current mto addr
+ sr %r0,%r0
+ l %r10,.Lascebc-.LbaseS4(%r13) # address of translation table
+.LinitmtoS4:
+ # initialize mto
+ mvc 0(.LmtoendS4-.LmtoS4,%r7),.LmtoS4-.LbaseS4(%r13)
+ lhi %r6,.LmtoendS4-.LmtoS4 # current mto length
+.LloopS4:
+ ic %r0,0(%r2) # get character
+ ahi %r2,1
+ ltr %r0,%r0 # end of string?
+ jz .LfinalizemtoS4
+ chi %r0,0x15 # end of line (NL)?
+ jz .LfinalizemtoS4
+ stc %r0,0(%r6,%r7) # copy to mto
+ la %r11,0(%r6,%r7)
+ tr 0(1,%r11),0(%r10) # translate to EBCDIC
+ ahi %r6,1
+ j .LloopS4
+.LfinalizemtoS4:
+ sth %r6,0(%r7) # update mto length
+ lh %r9,.LmdbS4-.LwritesccbS4(%r8) # update mdb length
+ ar %r9,%r6
+ sth %r9,.LmdbS4-.LwritesccbS4(%r8)
+ lh %r9,.LevbufS4-.LwritesccbS4(%r8)# update evbuf length
+ ar %r9,%r6
+ sth %r9,.LevbufS4-.LwritesccbS4(%r8)
+ lh %r9,0(%r8) # update sccb length
+ ar %r9,%r6
+ sth %r9,0(%r8)
+ ar %r7,%r6 # update current mto adress
+ ltr %r0,%r0 # more characters?
+ jnz .LinitmtoS4
+ l %r2,.LwritedataS4-.LbaseS4(%r13)# write data
+ lr %r3,%r8
+ bras %r14,_sclp_servc
+ ltr %r2,%r2 # servc successful?
+ jnz .LendS4
+ chi %r3,0x20 # write data successful?
+ je .LendS4
+ lhi %r2,1 # error return code
+.LendS4:
+ lm %r6,%r15,120(%r15) # restore registers
+ br %r14
+
+#
+# Function which prints a given text to the SCLP console.
+#
+# Parameters:
+# R2 = address of nil-terminated ASCII text
+#
+# Returns:
+# R2 = 0 on success, 1 on failure
+#
+
+ .globl _sclp_print_early
+_sclp_print_early:
+ stm %r6,%r15,24(%r15) # save registers
+ ahi %r15,-96 # create stack frame
+ lr %r10,%r2 # save string pointer
+ lhi %r2,0
+ bras %r14,_sclp_setup # enable console
+ ltr %r2,%r2
+ jnz .LendS5
+ lr %r2,%r10
+ bras %r14,_sclp_print # print string
+ ltr %r2,%r2
+ jnz .LendS5
+ lhi %r2,1
+ bras %r14,_sclp_setup # disable console
+.LendS5:
+ lm %r6,%r15,120(%r15) # restore registers
+ br %r14
+
+.LwritedataS4:
+ .long 0x00760005 # SCLP command for write data
+.LwritesccbS4:
+ # sccb
+ .word .LmtoS4-.LwritesccbS4
+ .byte 0
+ .byte 0,0,0
+ .word 0
+
+ # evbuf
+.LevbufS4:
+ .word .LmtoS4-.LevbufS4
+ .byte 0x02
+ .byte 0
+ .word 0
+
+.LmdbS4:
+ # mdb
+ .word .LmtoS4-.LmdbS4
+ .word 1
+ .long 0xd4c4c240
+ .long 1
+
+ # go
+.LgoS4:
+ .word .LmtoS4-.LgoS4
+ .word 1
+ .long 0
+ .byte 0,0,0,0,0,0,0,0
+ .byte 0,0,0
+ .byte 0
+ .byte 0,0,0,0,0,0,0
+ .byte 0
+ .word 0
+ .byte 0,0,0,0,0,0,0,0,0,0
+ .byte 0,0,0,0,0,0,0,0
+ .byte 0,0,0,0,0,0,0,0
+
+.LmtoS4:
+ .word .LmtoendS4-.LmtoS4
+ .word 4
+ .word 0x1000
+ .byte 0
+ .byte 0,0,0
+.LmtoendS4:
+
+ # Global constants
+.LsccbS0:
+ .long _sclp_work_area
+.Lascebc:
+ .long _ascebc
+.previous
+
+.section ".init.data","a"
+ .balign 4096
+_sclp_work_area:
+ .fill 4096
+.previous
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 06201b93cbbf..7402b6a39ead 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -82,9 +82,6 @@ EXPORT_SYMBOL(console_devno);
unsigned int console_irq = -1;
EXPORT_SYMBOL(console_irq);
-unsigned long machine_flags;
-EXPORT_SYMBOL(machine_flags);
-
unsigned long elf_hwcap = 0;
char elf_platform[ELF_PLATFORM_SIZE];
@@ -426,6 +423,7 @@ setup_lowcore(void)
__alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE;
lc->current_task = (unsigned long) init_thread_union.thread_info.task;
lc->thread_info = (unsigned long) &init_thread_union;
+ lc->machine_flags = S390_lowcore.machine_flags;
#ifndef CONFIG_64BIT
if (MACHINE_HAS_IEEE) {
lc->extended_save_area_addr = (__u32)
@@ -436,6 +434,14 @@ setup_lowcore(void)
#else
lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0];
#endif
+ lc->sync_enter_timer = S390_lowcore.sync_enter_timer;
+ lc->async_enter_timer = S390_lowcore.async_enter_timer;
+ lc->exit_timer = S390_lowcore.exit_timer;
+ lc->user_timer = S390_lowcore.user_timer;
+ lc->system_timer = S390_lowcore.system_timer;
+ lc->steal_timer = S390_lowcore.steal_timer;
+ lc->last_update_timer = S390_lowcore.last_update_timer;
+ lc->last_update_clock = S390_lowcore.last_update_clock;
set_prefix((u32)(unsigned long) lc);
lowcore_ptr[0] = lc;
}
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 3cf74c3ccb69..062bd64e65fa 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -26,6 +26,7 @@
#include <linux/binfmts.h>
#include <linux/tracehook.h>
#include <linux/syscalls.h>
+#include <linux/compat.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
#include <asm/lowcore.h>
@@ -482,7 +483,7 @@ void do_signal(struct pt_regs *regs)
/* Whee! Actually deliver the signal. */
int ret;
#ifdef CONFIG_COMPAT
- if (test_thread_flag(TIF_31BIT)) {
+ if (is_compat_task()) {
ret = handle_signal32(signr, &ka, &info, oldset, regs);
}
else
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 006ed5016eb4..0af302ceac2d 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -47,7 +47,7 @@
#include <asm/timer.h>
#include <asm/lowcore.h>
#include <asm/sclp.h>
-#include <asm/cpu.h>
+#include <asm/cputime.h>
#include <asm/vdso.h>
#include "entry.h"
@@ -571,6 +571,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
cpu_lowcore->current_task = (unsigned long) idle;
cpu_lowcore->cpu_nr = cpu;
cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce;
+ cpu_lowcore->machine_flags = S390_lowcore.machine_flags;
eieio();
while (signal_processor(cpu, sigp_restart) == sigp_busy)
@@ -590,7 +591,8 @@ static int __init setup_possible_cpus(char *s)
int pcpus, cpu;
pcpus = simple_strtoul(s, NULL, 0);
- for (cpu = 0; cpu < pcpus && cpu < nr_cpu_ids; cpu++)
+ init_cpu_possible(cpumask_of(0));
+ for (cpu = 1; cpu < pcpus && cpu < nr_cpu_ids; cpu++)
set_cpu_possible(cpu, true);
return 0;
}
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index fe5b25a988ab..2c7739fe70b1 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -336,3 +336,5 @@ SYSCALL(sys_inotify_init1,sys_inotify_init1,sys_inotify_init1_wrapper)
SYSCALL(sys_pipe2,sys_pipe2,sys_pipe2_wrapper) /* 325 */
SYSCALL(sys_dup3,sys_dup3,sys_dup3_wrapper)
SYSCALL(sys_epoll_create1,sys_epoll_create1,sys_epoll_create1_wrapper)
+SYSCALL(sys_preadv,sys_preadv,compat_sys_preadv_wrapper)
+SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev_wrapper)
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index f72d41068dc2..ef596d020573 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -52,9 +52,6 @@
#define USECS_PER_JIFFY ((unsigned long) 1000000/HZ)
#define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12)
-/* The value of the TOD clock for 1.1.1970. */
-#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
-
/*
* Create a small time difference between the timer interrupts
* on the different cpus to avoid lock contention.
@@ -63,9 +60,10 @@
#define TICK_SIZE tick
+u64 sched_clock_base_cc = -1; /* Force to data section. */
+
static ext_int_info_t ext_int_info_cc;
static ext_int_info_t ext_int_etr_cc;
-static u64 sched_clock_base_cc;
static DEFINE_PER_CPU(struct clock_event_device, comparators);
@@ -195,25 +193,15 @@ static void timing_alert_interrupt(__u16 code)
static void etr_reset(void);
static void stp_reset(void);
-/*
- * Get the TOD clock running.
- */
-static u64 __init reset_tod_clock(void)
+unsigned long read_persistent_clock(void)
{
- u64 time;
-
- etr_reset();
- stp_reset();
- if (store_clock(&time) == 0)
- return time;
- /* TOD clock not running. Set the clock to Unix Epoch. */
- if (set_clock(TOD_UNIX_EPOCH) != 0 || store_clock(&time) != 0)
- panic("TOD clock not operational.");
+ struct timespec ts;
- return TOD_UNIX_EPOCH;
+ tod_to_timeval(get_clock() - TOD_UNIX_EPOCH, &ts);
+ return ts.tv_sec;
}
-static cycle_t read_tod_clock(void)
+static cycle_t read_tod_clock(struct clocksource *cs)
{
return get_clock();
}
@@ -265,12 +253,13 @@ void update_vsyscall_tz(void)
*/
void __init time_init(void)
{
- sched_clock_base_cc = reset_tod_clock();
+ struct timespec ts;
+ unsigned long flags;
+ cycle_t now;
- /* set xtime */
- tod_to_timeval(sched_clock_base_cc - TOD_UNIX_EPOCH, &xtime);
- set_normalized_timespec(&wall_to_monotonic,
- -xtime.tv_sec, -xtime.tv_nsec);
+ /* Reset time synchronization interfaces. */
+ etr_reset();
+ stp_reset();
/* request the clock comparator external interrupt */
if (register_early_external_interrupt(0x1004,
@@ -278,17 +267,38 @@ void __init time_init(void)
&ext_int_info_cc) != 0)
panic("Couldn't request external interrupt 0x1004");
- if (clocksource_register(&clocksource_tod) != 0)
- panic("Could not register TOD clock source");
-
/* request the timing alert external interrupt */
if (register_early_external_interrupt(0x1406,
timing_alert_interrupt,
&ext_int_etr_cc) != 0)
panic("Couldn't request external interrupt 0x1406");
+ if (clocksource_register(&clocksource_tod) != 0)
+ panic("Could not register TOD clock source");
+
+ /*
+ * The TOD clock is an accurate clock. The xtime should be
+ * initialized in a way that the difference between TOD and
+ * xtime is reasonably small. Too bad that timekeeping_init
+ * sets xtime.tv_nsec to zero. In addition the clock source
+ * change from the jiffies clock source to the TOD clock
+ * source add another error of up to 1/HZ second. The same
+ * function sets wall_to_monotonic to a value that is too
+ * small for /proc/uptime to be accurate.
+ * Reset xtime and wall_to_monotonic to sane values.
+ */
+ write_seqlock_irqsave(&xtime_lock, flags);
+ now = get_clock();
+ tod_to_timeval(now - TOD_UNIX_EPOCH, &xtime);
+ clocksource_tod.cycle_last = now;
+ clocksource_tod.raw_time = xtime;
+ tod_to_timeval(sched_clock_base_cc - TOD_UNIX_EPOCH, &ts);
+ set_normalized_timespec(&wall_to_monotonic, -ts.tv_sec, -ts.tv_nsec);
+ write_sequnlock_irqrestore(&xtime_lock, flags);
+
/* Enable TOD clock interrupts on the boot cpu. */
init_cpu_timer();
+
/* Enable cpu timer interrupts on the boot cpu. */
vtime_init();
}
@@ -1423,6 +1433,7 @@ static void *stp_page;
static void stp_work_fn(struct work_struct *work);
static DEFINE_MUTEX(stp_work_mutex);
static DECLARE_WORK(stp_work, stp_work_fn);
+static struct timer_list stp_timer;
static int __init early_parse_stp(char *p)
{
@@ -1454,10 +1465,16 @@ static void __init stp_reset(void)
}
}
+static void stp_timeout(unsigned long dummy)
+{
+ queue_work(time_sync_wq, &stp_work);
+}
+
static int __init stp_init(void)
{
if (!test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags))
return 0;
+ setup_timer(&stp_timer, stp_timeout, 0UL);
time_init_wq();
if (!stp_online)
return 0;
@@ -1565,6 +1582,7 @@ static void stp_work_fn(struct work_struct *work)
if (!stp_online) {
chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000);
+ del_timer_sync(&stp_timer);
goto out_unlock;
}
@@ -1586,6 +1604,13 @@ static void stp_work_fn(struct work_struct *work)
stop_machine(stp_sync_clock, &stp_sync, &cpu_online_map);
put_online_cpus();
+ if (!check_sync_clock())
+ /*
+ * There is a usable clock but the synchonization failed.
+ * Retry after a second.
+ */
+ mod_timer(&stp_timer, jiffies + HZ);
+
out_unlock:
mutex_unlock(&stp_work_mutex);
}
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c
index 89b2e7f1b7a9..75b2d83085ce 100644
--- a/arch/s390/kernel/vdso.c
+++ b/arch/s390/kernel/vdso.c
@@ -22,7 +22,7 @@
#include <linux/elf.h>
#include <linux/security.h>
#include <linux/bootmem.h>
-
+#include <linux/compat.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/processor.h>
@@ -53,8 +53,16 @@ unsigned int __read_mostly vdso_enabled = 1;
static int __init vdso_setup(char *s)
{
- vdso_enabled = simple_strtoul(s, NULL, 0);
- return 1;
+ int rc;
+
+ rc = 0;
+ if (strncmp(s, "on", 3) == 0)
+ vdso_enabled = 1;
+ else if (strncmp(s, "off", 4) == 0)
+ vdso_enabled = 0;
+ else
+ rc = strict_strtoul(s, 0, &vdso_enabled);
+ return !rc;
}
__setup("vdso=", vdso_setup);
@@ -203,7 +211,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
vdso_pagelist = vdso64_pagelist;
vdso_pages = vdso64_pages;
#ifdef CONFIG_COMPAT
- if (test_thread_flag(TIF_31BIT)) {
+ if (is_compat_task()) {
vdso_pagelist = vdso32_pagelist;
vdso_pages = vdso32_pages;
}
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 7a2063eb88f0..89399b8756c2 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -29,8 +29,8 @@ SECTIONS
. = 0x00000000;
.text : {
_text = .; /* Text and read-only data */
- *(.text.head)
- TEXT_TEXT
+ HEAD_TEXT
+ TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
KPROBES_TEXT
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index ecf0304e61c1..c8eb7255332b 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -23,7 +23,7 @@
#include <asm/s390_ext.h>
#include <asm/timer.h>
#include <asm/irq_regs.h>
-#include <asm/cpu.h>
+#include <asm/cputime.h>
static ext_int_info_t ext_int_info_timer;
@@ -134,6 +134,8 @@ void vtime_start_cpu(void)
/* Account time spent with enabled wait psw loaded as idle time. */
idle_time = S390_lowcore.int_clock - idle->idle_enter;
account_idle_time(idle_time);
+ S390_lowcore.steal_timer +=
+ idle->idle_enter - S390_lowcore.last_update_clock;
S390_lowcore.last_update_clock = S390_lowcore.int_clock;
/* Account system time spent going idle. */
@@ -238,6 +240,22 @@ void vtime_stop_cpu(void)
}
}
+cputime64_t s390_get_idle_time(int cpu)
+{
+ struct s390_idle_data *idle;
+ unsigned long long now, idle_time, idle_enter;
+
+ idle = &per_cpu(s390_idle, cpu);
+ spin_lock(&idle->lock);
+ now = get_clock();
+ idle_time = 0;
+ idle_enter = idle->idle_enter;
+ if (idle_enter != 0ULL && idle_enter < now)
+ idle_time = now - idle_enter;
+ spin_unlock(&idle->lock);
+ return idle_time;
+}
+
/*
* Sorted add to a list. List is linear searched until first bigger
* element is found.
@@ -425,17 +443,7 @@ void add_virt_timer_periodic(void *new)
}
EXPORT_SYMBOL(add_virt_timer_periodic);
-/*
- * If we change a pending timer the function must be called on the CPU
- * where the timer is running on, e.g. by smp_call_function_single()
- *
- * The original mod_timer adds the timer if it is not pending. For
- * compatibility we do the same. The timer will be added on the current
- * CPU as a oneshot timer.
- *
- * returns whether it has modified a pending timer (1) or not (0)
- */
-int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
+int __mod_vtimer(struct vtimer_list *timer, __u64 expires, int periodic)
{
struct vtimer_queue *vq;
unsigned long flags;
@@ -444,39 +452,35 @@ int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
BUG_ON(!timer->function);
BUG_ON(!expires || expires > VTIMER_MAX_SLICE);
- /*
- * This is a common optimization triggered by the
- * networking code - if the timer is re-modified
- * to be the same thing then just return:
- */
if (timer->expires == expires && vtimer_pending(timer))
return 1;
cpu = get_cpu();
vq = &per_cpu(virt_cpu_timer, cpu);
- /* check if we run on the right CPU */
- BUG_ON(timer->cpu != cpu);
-
/* disable interrupts before test if timer is pending */
spin_lock_irqsave(&vq->lock, flags);
/* if timer isn't pending add it on the current CPU */
if (!vtimer_pending(timer)) {
spin_unlock_irqrestore(&vq->lock, flags);
- /* we do not activate an interval timer with mod_virt_timer */
- timer->interval = 0;
+
+ if (periodic)
+ timer->interval = expires;
+ else
+ timer->interval = 0;
timer->expires = expires;
timer->cpu = cpu;
internal_add_vtimer(timer);
return 0;
}
+ /* check if we run on the right CPU */
+ BUG_ON(timer->cpu != cpu);
+
list_del_init(&timer->entry);
timer->expires = expires;
-
- /* also change the interval if we have an interval timer */
- if (timer->interval)
+ if (periodic)
timer->interval = expires;
/* the timer can't expire anymore so we can release the lock */
@@ -484,9 +488,32 @@ int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
internal_add_vtimer(timer);
return 1;
}
+
+/*
+ * If we change a pending timer the function must be called on the CPU
+ * where the timer is running on.
+ *
+ * returns whether it has modified a pending timer (1) or not (0)
+ */
+int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
+{
+ return __mod_vtimer(timer, expires, 0);
+}
EXPORT_SYMBOL(mod_virt_timer);
/*
+ * If we change a pending timer the function must be called on the CPU
+ * where the timer is running on.
+ *
+ * returns whether it has modified a pending timer (1) or not (0)
+ */
+int mod_virt_timer_periodic(struct vtimer_list *timer, __u64 expires)
+{
+ return __mod_vtimer(timer, expires, 1);
+}
+EXPORT_SYMBOL(mod_virt_timer_periodic);
+
+/*
* delete a virtual timer
*
* returns whether the deleted timer was pending (1) or not (0)
@@ -516,16 +543,8 @@ EXPORT_SYMBOL(del_virt_timer);
*/
void init_cpu_vtimer(void)
{
- struct thread_info *ti = current_thread_info();
struct vtimer_queue *vq;
- S390_lowcore.user_timer = ti->user_timer;
- S390_lowcore.system_timer = ti->system_timer;
-
- /* kick the virtual timer */
- asm volatile ("STCK %0" : "=m" (S390_lowcore.last_update_clock));
- asm volatile ("STPT %0" : "=m" (S390_lowcore.last_update_timer));
-
/* initialize per cpu vtimer structure */
vq = &__get_cpu_var(virt_cpu_timer);
INIT_LIST_HEAD(&vq->list);
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 0189356fe209..4ed4c3a11485 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -318,6 +318,12 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu)
return rc;
}
+int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu)
+{
+ /* do real check here */
+ return 1;
+}
+
int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
{
return 0;
diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c
index e41f4008afc5..f7e0d30250b7 100644
--- a/arch/s390/lib/spinlock.c
+++ b/arch/s390/lib/spinlock.c
@@ -124,6 +124,27 @@ void _raw_read_lock_wait(raw_rwlock_t *rw)
}
EXPORT_SYMBOL(_raw_read_lock_wait);
+void _raw_read_lock_wait_flags(raw_rwlock_t *rw, unsigned long flags)
+{
+ unsigned int old;
+ int count = spin_retry;
+
+ local_irq_restore(flags);
+ while (1) {
+ if (count-- <= 0) {
+ _raw_yield();
+ count = spin_retry;
+ }
+ if (!__raw_read_can_lock(rw))
+ continue;
+ old = rw->lock & 0x7fffffffU;
+ local_irq_disable();
+ if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old)
+ return;
+ }
+}
+EXPORT_SYMBOL(_raw_read_lock_wait_flags);
+
int _raw_read_trylock_retry(raw_rwlock_t *rw)
{
unsigned int old;
@@ -157,6 +178,25 @@ void _raw_write_lock_wait(raw_rwlock_t *rw)
}
EXPORT_SYMBOL(_raw_write_lock_wait);
+void _raw_write_lock_wait_flags(raw_rwlock_t *rw, unsigned long flags)
+{
+ int count = spin_retry;
+
+ local_irq_restore(flags);
+ while (1) {
+ if (count-- <= 0) {
+ _raw_yield();
+ count = spin_retry;
+ }
+ if (!__raw_write_can_lock(rw))
+ continue;
+ local_irq_disable();
+ if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
+ return;
+ }
+}
+EXPORT_SYMBOL(_raw_write_lock_wait_flags);
+
int _raw_write_trylock_retry(raw_rwlock_t *rw)
{
int count = spin_retry;
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 833e8366c351..220a152c836c 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -19,6 +19,7 @@
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
+#include <linux/compat.h>
#include <linux/smp.h>
#include <linux/kdebug.h>
#include <linux/smp_lock.h>
@@ -239,7 +240,7 @@ static int signal_return(struct mm_struct *mm, struct pt_regs *regs,
up_read(&mm->mmap_sem);
clear_tsk_thread_flag(current, TIF_SINGLE_STEP);
#ifdef CONFIG_COMPAT
- compat = test_tsk_thread_flag(current, TIF_31BIT);
+ compat = is_compat_task();
if (compat && instruction == 0x0a77)
sys32_sigreturn();
else if (compat && instruction == 0x0aad)
diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c
index e008d236cc15..f4558ccf02b9 100644
--- a/arch/s390/mm/mmap.c
+++ b/arch/s390/mm/mmap.c
@@ -28,6 +28,7 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <asm/pgalloc.h>
+#include <asm/compat.h>
/*
* Top of mmap area (just below the process stack).
@@ -55,7 +56,7 @@ static inline int mmap_is_legacy(void)
/*
* Force standard allocation for 64 bit programs.
*/
- if (!test_thread_flag(TIF_31BIT))
+ if (!is_compat_task())
return 1;
#endif
return sysctl_legacy_va_layout ||
@@ -91,7 +92,7 @@ EXPORT_SYMBOL_GPL(arch_pick_mmap_layout);
int s390_mmap_check(unsigned long addr, unsigned long len)
{
- if (!test_thread_flag(TIF_31BIT) &&
+ if (!is_compat_task() &&
len >= TASK_SIZE && TASK_SIZE < (1UL << 53))
return crst_table_upgrade(current->mm, 1UL << 53);
return 0;
@@ -108,8 +109,7 @@ s390_get_unmapped_area(struct file *filp, unsigned long addr,
area = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
if (!(area & ~PAGE_MASK))
return area;
- if (area == -ENOMEM &&
- !test_thread_flag(TIF_31BIT) && TASK_SIZE < (1UL << 53)) {
+ if (area == -ENOMEM && !is_compat_task() && TASK_SIZE < (1UL << 53)) {
/* Upgrade the page table to 4 levels and retry. */
rc = crst_table_upgrade(mm, 1UL << 53);
if (rc)
@@ -131,8 +131,7 @@ s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr,
area = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags);
if (!(area & ~PAGE_MASK))
return area;
- if (area == -ENOMEM &&
- !test_thread_flag(TIF_31BIT) && TASK_SIZE < (1UL << 53)) {
+ if (area == -ENOMEM && !is_compat_task() && TASK_SIZE < (1UL << 53)) {
/* Upgrade the page table to 4 levels and retry. */
rc = crst_table_upgrade(mm, 1UL << 53);
if (rc)
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 5e4babecf934..a9dee13ddd8b 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -14,6 +14,8 @@ config SUPERH
select HAVE_GENERIC_DMA_COHERENT
select HAVE_IOREMAP_PROT if MMU
select HAVE_ARCH_TRACEHOOK
+ select HAVE_DMA_API_DEBUG
+ select RTC_LIB
help
The SuperH is a RISC processor targeted for use in embedded systems
and consumer electronics; it was also used in the Sega Dreamcast
@@ -21,7 +23,7 @@ config SUPERH
<http://www.linux-sh.org/>.
config SUPERH32
- def_bool !SUPERH64
+ def_bool ARCH = "sh"
select HAVE_KPROBES
select HAVE_KRETPROBES
select HAVE_FUNCTION_TRACER
@@ -31,7 +33,7 @@ config SUPERH32
select ARCH_HIBERNATION_POSSIBLE if MMU
config SUPERH64
- def_bool y if CPU_SH5
+ def_bool ARCH = "sh64"
config ARCH_DEFCONFIG
string
@@ -73,14 +75,18 @@ config GENERIC_IOMAP
bool
config GENERIC_TIME
- def_bool n
+ def_bool y
config GENERIC_CLOCKEVENTS
- def_bool n
+ def_bool y
config GENERIC_CLOCKEVENTS_BROADCAST
bool
+config GENERIC_CMOS_UPDATE
+ def_bool y
+ depends on SH_SH03 || SH_DREAMCAST
+
config GENERIC_LOCKBREAK
def_bool y
depends on SMP && PREEMPT
@@ -111,6 +117,12 @@ config SYS_SUPPORTS_PCI
config SYS_SUPPORTS_CMT
bool
+config SYS_SUPPORTS_MTU2
+ bool
+
+config SYS_SUPPORTS_TMU
+ bool
+
config STACKTRACE_SUPPORT
def_bool y
@@ -156,6 +168,7 @@ config CPU_SH3
bool
select CPU_HAS_INTEVT
select CPU_HAS_SR_RB
+ select SYS_SUPPORTS_TMU
config CPU_SH4
bool
@@ -163,6 +176,7 @@ config CPU_SH4
select CPU_HAS_SR_RB
select CPU_HAS_PTEA if !CPU_SH4A || CPU_SHX2
select CPU_HAS_FPU if !CPU_SH4AL_DSP
+ select SYS_SUPPORTS_TMU
config CPU_SH4A
bool
@@ -176,6 +190,7 @@ config CPU_SH4AL_DSP
config CPU_SH5
bool
select CPU_HAS_FPU
+ select SYS_SUPPORTS_TMU
config CPU_SHX2
bool
@@ -187,6 +202,8 @@ config ARCH_SHMOBILE
bool
select ARCH_SUSPEND_POSSIBLE
+if SUPERH32
+
choice
prompt "Processor sub-type selection"
@@ -207,27 +224,32 @@ config CPU_SUBTYPE_SH7201
bool "Support SH7201 processor"
select CPU_SH2A
select CPU_HAS_FPU
+ select SYS_SUPPORTS_MTU2
config CPU_SUBTYPE_SH7203
bool "Support SH7203 processor"
select CPU_SH2A
select CPU_HAS_FPU
select SYS_SUPPORTS_CMT
+ select SYS_SUPPORTS_MTU2
config CPU_SUBTYPE_SH7206
bool "Support SH7206 processor"
select CPU_SH2A
select SYS_SUPPORTS_CMT
+ select SYS_SUPPORTS_MTU2
config CPU_SUBTYPE_SH7263
bool "Support SH7263 processor"
select CPU_SH2A
select CPU_HAS_FPU
select SYS_SUPPORTS_CMT
+ select SYS_SUPPORTS_MTU2
config CPU_SUBTYPE_MXG
bool "Support MX-G processor"
select CPU_SH2A
+ select SYS_SUPPORTS_MTU2
help
Select MX-G if running on an R8A03022BG part.
@@ -344,6 +366,16 @@ config CPU_SUBTYPE_SH7723
help
Select SH7723 if you have an SH-MobileR2 CPU.
+config CPU_SUBTYPE_SH7724
+ bool "Support SH7724 processor"
+ select CPU_SH4A
+ select CPU_SHX2
+ select ARCH_SHMOBILE
+ select ARCH_SPARSEMEM_ENABLE
+ select SYS_SUPPORTS_CMT
+ help
+ Select SH7724 if you have an SH-MobileR2R CPU.
+
config CPU_SUBTYPE_SH7763
bool "Support SH7763 processor"
select CPU_SH4A
@@ -408,6 +440,15 @@ config CPU_SUBTYPE_SH7366
select SYS_SUPPORTS_NUMA
select SYS_SUPPORTS_CMT
+endchoice
+
+endif
+
+if SUPERH64
+
+choice
+ prompt "Processor sub-type selection"
+
# SH-5 Processor Support
config CPU_SUBTYPE_SH5_101
@@ -420,6 +461,8 @@ config CPU_SUBTYPE_SH5_103
endchoice
+endif
+
source "arch/sh/mm/Kconfig"
source "arch/sh/Kconfig.cpu"
@@ -432,33 +475,29 @@ config SH_TMU
bool "TMU timer support"
depends on CPU_SH3 || CPU_SH4
default y
- select GENERIC_TIME
- select GENERIC_CLOCKEVENTS
help
This enables the use of the TMU as the system timer.
-config SH_CMT
- bool "CMT timer support"
- depends on SYS_SUPPORTS_CMT && CPU_SH2
+config SH_TIMER_TMU
+ bool "TMU timer driver"
+ depends on !SH_TMU && SYS_SUPPORTS_TMU
default y
help
- This enables the use of the CMT as the system timer.
+ This enables the build of the TMU timer driver.
-#
-# Support for the new-style CMT driver. This will replace SH_CMT
-# once its other dependencies are merged.
-#
config SH_TIMER_CMT
- bool "CMT clockevents driver"
- depends on SYS_SUPPORTS_CMT && !SH_CMT
- select GENERIC_CLOCKEVENTS
+ bool "CMT timer driver"
+ depends on SYS_SUPPORTS_CMT
+ default y
+ help
+ This enables build of the CMT timer driver.
-config SH_MTU2
- bool "MTU2 timer support"
- depends on CPU_SH2A
+config SH_TIMER_MTU2
+ bool "MTU2 timer driver"
+ depends on SYS_SUPPORTS_MTU2
default y
help
- This enables the use of the MTU2 as the system timer.
+ This enables build of the MTU2 timer driver.
config SH_TIMER_IRQ
int
@@ -481,6 +520,7 @@ config SH_PCLK_FREQ
CPU_SUBTYPE_SH7203 || CPU_SUBTYPE_SH7206 || \
CPU_SUBTYPE_SH7263 || CPU_SUBTYPE_MXG || \
CPU_SUBTYPE_SH7786
+ default "41666666" if CPU_SUBTYPE_SH7724
default "60000000" if CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_SH7751R
default "66000000" if CPU_SUBTYPE_SH4_202
default "50000000"
@@ -654,22 +694,37 @@ endmenu
menu "Boot options"
config ZERO_PAGE_OFFSET
- hex "Zero page offset"
- default "0x00004000" if SH_SH03
- default "0x00010000" if PAGE_SIZE_64KB
+ hex
+ default "0x00010000" if PAGE_SIZE_64KB || SH_RTS7751R2D || \
+ SH_7751_SOLUTION_ENGINE
+ default "0x00004000" if PAGE_SIZE_16KB || SH_SH03
default "0x00002000" if PAGE_SIZE_8KB
default "0x00001000"
help
This sets the default offset of zero page.
config BOOT_LINK_OFFSET
- hex "Link address offset for booting"
+ hex
+ default "0x00210000" if SH_SHMIN
+ default "0x00400000" if SH_CAYMAN
+ default "0x00810000" if SH_7780_SOLUTION_ENGINE
+ default "0x009e0000" if SH_TITAN
+ default "0x01800000" if SH_SDK7780
+ default "0x02000000" if SH_EDOSK7760
default "0x00800000"
help
This option allows you to set the link address offset of the zImage.
This can be useful if you are on a board which has a small amount of
memory.
+config ENTRY_OFFSET
+ hex
+ default "0x00001000" if PAGE_SIZE_4KB
+ default "0x00002000" if PAGE_SIZE_8KB
+ default "0x00004000" if PAGE_SIZE_16KB
+ default "0x00010000" if PAGE_SIZE_64KB
+ default "0x00000000"
+
config UBC_WAKEUP
bool "Wakeup UBC on startup"
depends on CPU_SH4 && !CPU_SH4A
diff --git a/arch/sh/Kconfig.cpu b/arch/sh/Kconfig.cpu
index c7d704381a6d..9eb1712372d8 100644
--- a/arch/sh/Kconfig.cpu
+++ b/arch/sh/Kconfig.cpu
@@ -76,11 +76,6 @@ config SPECULATIVE_EXECUTION
If unsure, say N.
-config SH64_USER_MISALIGNED_FIXUP
- def_bool y
- prompt "Fixup misaligned loads/stores occurring in user mode"
- depends on SUPERH64
-
config SH64_ID2815_WORKAROUND
bool "Include workaround for SH5-101 cut2 silicon defect ID2815"
depends on CPU_SUBTYPE_SH5_101
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
index 0d62681f72a0..8179cc9be9a4 100644
--- a/arch/sh/Kconfig.debug
+++ b/arch/sh/Kconfig.debug
@@ -38,10 +38,10 @@ config EARLY_SCIF_CONSOLE_PORT
default "0xffe00000" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7763 || \
CPU_SUBTYPE_SH7722 || CPU_SUBTYPE_SH7366 || \
CPU_SUBTYPE_SH7343
- default "0xffe80000" if CPU_SH4
default "0xffea0000" if CPU_SUBTYPE_SH7785
default "0xfffe8000" if CPU_SUBTYPE_SH7203
default "0xfffe9800" if CPU_SUBTYPE_SH7206 || CPU_SUBTYPE_SH7263
+ default "0xffe80000" if CPU_SH4
default "0x00000000"
config EARLY_PRINTK
@@ -92,7 +92,7 @@ config 4KSTACKS
config IRQSTACKS
bool "Use separate kernel stacks when processing interrupts"
- depends on DEBUG_KERNEL && SUPERH32
+ depends on DEBUG_KERNEL && SUPERH32 && BROKEN
help
If you say Y here the kernel will use separate kernel stacks
for handling hard and soft interrupts. This can help avoid
@@ -122,27 +122,8 @@ config SH_NO_BSS_INIT
For all other cases, say N. If this option seems perplexing, or
you aren't sure, say N.
-config MORE_COMPILE_OPTIONS
- bool "Add any additional compile options"
- help
- If you want to add additional CFLAGS to the kernel build, enable this
- option and then enter what you would like to add in the next question.
- Note however that -g is already appended with the selection of KGDB.
-
-config COMPILE_OPTIONS
- string "Additional compile arguments"
- depends on MORE_COMPILE_OPTIONS
-
config SH64_SR_WATCH
bool "Debug: set SR.WATCH to enable hardware watchpoints and trace"
depends on SUPERH64
-config POOR_MANS_STRACE
- bool "Debug: enable rudimentary strace facility"
- depends on SUPERH64
- help
- This option allows system calls to be traced to the console. It also
- aids in detecting kernel stack underflow. It is useful for debugging
- early-userland problems (e.g. init incurring fatal exceptions.)
-
endmenu
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index bece1f7535f2..a47fbd260ba4 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -70,9 +70,6 @@ cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -ml
cflags-y += $(call cc-option,-mno-fdpic)
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 .note.gnu.build-id -R .comment \
-R .stab -R .stabstr -S
@@ -94,25 +91,35 @@ KBUILD_IMAGE := $(defaultimage-y)
#
ifdef CONFIG_SUPERH32
UTS_MACHINE := sh
+BITS := 32
LDFLAGS_vmlinux += -e _stext
else
UTS_MACHINE := sh64
+BITS := 64
LDFLAGS_vmlinux += --defsym phys_stext=_stext-$(CONFIG_PAGE_OFFSET) \
--defsym phys_stext_shmedia=phys_stext+1 \
-e phys_stext_shmedia
endif
+ifneq ($(SUBARCH),$(ARCH))
+ ifeq ($(CROSS_COMPILE),)
+ CROSS_COMPILE := $(call cc-cross-prefix, $(UTS_MACHINE)-linux- $(UTS_MACHINE)-linux-gnu- $(UTS_MACHINE)-unknown-linux-gnu-)
+ endif
+endif
+
ifdef CONFIG_CPU_LITTLE_ENDIAN
-LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64'
+ld-bfd := elf32-$(UTS_MACHINE)-linux
+LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64' --oformat $(ld-bfd)
LDFLAGS += -EL
else
-LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64+4'
+ld-bfd := elf32-$(UTS_MACHINE)big-linux
+LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64+4' --oformat $(ld-bfd)
LDFLAGS += -EB
endif
-head-y := arch/sh/kernel/init_task.o
-head-$(CONFIG_SUPERH32) += arch/sh/kernel/head_32.o
-head-$(CONFIG_SUPERH64) += arch/sh/kernel/head_64.o
+export ld-bfd BITS
+
+head-y := arch/sh/kernel/init_task.o arch/sh/kernel/head_$(BITS).o
core-y += arch/sh/kernel/ arch/sh/mm/ arch/sh/boards/
core-$(CONFIG_SH_FPU_EMU) += arch/sh/math-emu/
@@ -193,7 +200,7 @@ zImage uImage uImage.srec vmlinux.srec: vmlinux
compressed: zImage
-archprepare: maketools arch/sh/lib64/syscalltab.h
+archprepare: maketools
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
@@ -205,34 +212,4 @@ define archhelp
@echo ' uImage.srec - Create an S-record for U-Boot'
endef
-define filechk_gen-syscalltab
- (set -e; \
- echo "/*"; \
- echo " * DO NOT MODIFY."; \
- echo " *"; \
- echo " * This file was generated by arch/sh/Makefile"; \
- echo " * Any changes will be reverted at build time."; \
- echo " */"; \
- echo ""; \
- echo "#ifndef __SYSCALLTAB_H"; \
- echo "#define __SYSCALLTAB_H"; \
- echo ""; \
- echo "#include <linux/kernel.h>"; \
- echo ""; \
- echo "struct syscall_info {"; \
- echo " const char *name;"; \
- echo "} syscall_info_table[] = {"; \
- sed -e '/^.*\.long /!d;s// { "/;s/\(\([^/]*\)\/\)\{1\}.*/\2/; \
- s/[ \t]*$$//g;s/$$/" },/;s/\("\)sys_/\1/g'; \
- echo "};"; \
- echo ""; \
- echo "#define NUM_SYSCALL_INFO_ENTRIES ARRAY_SIZE(syscall_info_table)";\
- echo ""; \
- echo "#endif /* __SYSCALLTAB_H */" )
-endef
-
-arch/sh/lib64/syscalltab.h: arch/sh/kernel/syscalls_64.S
- $(call filechk,gen-syscalltab)
-
-CLEAN_FILES += arch/sh/lib64/syscalltab.h \
- include/asm-sh/machtypes.h
+CLEAN_FILES += include/asm-sh/machtypes.h
diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig
index dcc1af8a2cfe..99e2d47f79f5 100644
--- a/arch/sh/boards/Kconfig
+++ b/arch/sh/boards/Kconfig
@@ -121,7 +121,7 @@ config SH_RTS7751R2D
bool "RTS7751R2D"
depends on CPU_SUBTYPE_SH7751R
select SYS_SUPPORTS_PCI
- select IO_TRAPPED
+ select IO_TRAPPED if MMU
help
Select RTS7751R2D if configuring for a Renesas Technology
Sales SH-Graphics board.
@@ -145,13 +145,13 @@ config SH_HIGHLANDER
bool "Highlander"
depends on CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785
select SYS_SUPPORTS_PCI
- select IO_TRAPPED
+ select IO_TRAPPED if MMU
config SH_SH7785LCR
bool "SH7785LCR"
depends on CPU_SUBTYPE_SH7785
select SYS_SUPPORTS_PCI
- select IO_TRAPPED
+ select IO_TRAPPED if MMU
config SH_SH7785LCR_29BIT_PHYSMAPS
bool "SH7785LCR 29bit physmaps"
diff --git a/arch/sh/boards/board-ap325rxa.c b/arch/sh/boards/board-ap325rxa.c
index 912458f666eb..39e46919df14 100644
--- a/arch/sh/boards/board-ap325rxa.c
+++ b/arch/sh/boards/board-ap325rxa.c
@@ -349,6 +349,7 @@ static int ov7725_power(struct device *dev, int mode)
static struct ov772x_camera_info ov7725_info = {
.buswidth = SOCAM_DATAWIDTH_8,
.flags = OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP,
+ .edgectrl = OV772X_AUTO_EDGECTRL(0xf, 0),
.link = {
.power = ov7725_power,
},
diff --git a/arch/sh/boards/board-urquell.c b/arch/sh/boards/board-urquell.c
index 8367d1d789c3..beb88c4da2c1 100644
--- a/arch/sh/boards/board-urquell.c
+++ b/arch/sh/boards/board-urquell.c
@@ -2,6 +2,8 @@
* Renesas Technology Corp. SH7786 Urquell Support.
*
* Copyright (C) 2008 Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on board-sh7785lcr.c
* Copyright (C) 2008 Yoshihiro Shimoda
*
* This file is subject to the terms and conditions of the GNU General Public
@@ -21,6 +23,32 @@
#include <asm/heartbeat.h>
#include <asm/sizes.h>
+/*
+ * bit 1234 5678
+ *----------------------------
+ * SW1 0101 0010 -> Pck 33MHz version
+ * (1101 0010) Pck 66MHz version
+ * SW2 0x1x xxxx -> little endian
+ * 29bit mode
+ * SW47 0001 1000 -> CS0 : on-board flash
+ * CS1 : SRAM, registers, LAN, PCMCIA
+ * 38400 bps for SCIF1
+ *
+ * Address
+ * 0x00000000 - 0x04000000 (CS0) Nor Flash
+ * 0x04000000 - 0x04200000 (CS1) SRAM
+ * 0x05000000 - 0x05800000 (CS1) on board register
+ * 0x05800000 - 0x06000000 (CS1) LAN91C111
+ * 0x06000000 - 0x06400000 (CS1) PCMCIA
+ * 0x08000000 - 0x10000000 (CS2-CS3) DDR3
+ * 0x10000000 - 0x14000000 (CS4) PCIe
+ * 0x14000000 - 0x14800000 (CS5) Core0 LRAM/URAM
+ * 0x14800000 - 0x15000000 (CS5) Core1 LRAM/URAM
+ * 0x18000000 - 0x1C000000 (CS6) ATA/NAND-Flash
+ * 0x1C000000 - (CS7) SH7786 Control register
+ */
+
+/* HeartBeat */
static struct resource heartbeat_resources[] = {
[0] = {
.start = BOARDREG(SLEDR),
@@ -43,6 +71,7 @@ static struct platform_device heartbeat_device = {
.resource = heartbeat_resources,
};
+/* LAN91C111 */
static struct smc91x_platdata smc91x_info = {
.flags = SMC91X_USE_16BIT | SMC91X_NOWAIT,
};
@@ -69,6 +98,7 @@ static struct platform_device smc91x_eth_device = {
},
};
+/* Nor Flash */
static struct mtd_partition nor_flash_partitions[] = {
{
.name = "loader",
diff --git a/arch/sh/boards/mach-cayman/Makefile b/arch/sh/boards/mach-cayman/Makefile
index cafe1ac3b29c..00fa3eaecb1b 100644
--- a/arch/sh/boards/mach-cayman/Makefile
+++ b/arch/sh/boards/mach-cayman/Makefile
@@ -1,4 +1,4 @@
#
# Makefile for the Hitachi Cayman specific parts of the kernel
#
-obj-y := setup.o irq.o
+obj-y := setup.o irq.o panic.o
diff --git a/arch/sh/boards/mach-cayman/irq.c b/arch/sh/boards/mach-cayman/irq.c
index da62ad516994..33f770856319 100644
--- a/arch/sh/boards/mach-cayman/irq.c
+++ b/arch/sh/boards/mach-cayman/irq.c
@@ -142,26 +142,11 @@ int cayman_irq_demux(int evt)
return irq;
}
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
-int cayman_irq_describe(char* p, int irq)
-{
- if (irq < NR_INTC_IRQS) {
- return intc_irq_describe(p, irq);
- } else if (irq < NR_INTC_IRQS + 8) {
- return sprintf(p, "(SMSC %d)", irq - NR_INTC_IRQS);
- } else if ((irq >= NR_INTC_IRQS + 24) && (irq < NR_INTC_IRQS + 32)) {
- return sprintf(p, "(PCI2 %d)", irq - (NR_INTC_IRQS + 24));
- }
-
- return 0;
-}
-#endif
-
void init_cayman_irq(void)
{
int i;
- epld_virt = onchip_remap(EPLD_BASE, 1024, "EPLD");
+ epld_virt = (unsigned long)ioremap_nocache(EPLD_BASE, 1024);
if (!epld_virt) {
printk(KERN_ERR "Cayman IRQ: Unable to remap EPLD\n");
return;
diff --git a/arch/sh/boards/mach-cayman/panic.c b/arch/sh/boards/mach-cayman/panic.c
new file mode 100644
index 000000000000..d1e67306d07c
--- /dev/null
+++ b/arch/sh/boards/mach-cayman/panic.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2003 Richard Curnow, SuperH UK Limited
+ *
+ * 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/kernel.h>
+#include <linux/io.h>
+#include <cpu/registers.h>
+
+/* THIS IS A PHYSICAL ADDRESS */
+#define HDSP2534_ADDR (0x04002100)
+
+static void poor_mans_delay(void)
+{
+ int i;
+
+ for (i = 0; i < 2500000; i++)
+ cpu_relax();
+}
+
+static void show_value(unsigned long x)
+{
+ int i;
+ unsigned nibble;
+ for (i = 0; i < 8; i++) {
+ nibble = ((x >> (i * 4)) & 0xf);
+
+ __raw_writeb(nibble + ((nibble > 9) ? 55 : 48),
+ HDSP2534_ADDR + 0xe0 + ((7 - i) << 2));
+ }
+}
+
+void
+panic_handler(unsigned long panicPC, unsigned long panicSSR,
+ unsigned long panicEXPEVT)
+{
+ while (1) {
+ /* This piece of code displays the PC on the LED display */
+ show_value(panicPC);
+ poor_mans_delay();
+ show_value(panicSSR);
+ poor_mans_delay();
+ show_value(panicEXPEVT);
+ poor_mans_delay();
+ }
+}
diff --git a/arch/sh/boards/mach-cayman/setup.c b/arch/sh/boards/mach-cayman/setup.c
index e7f9cc5f2ff1..7e8216ac31bd 100644
--- a/arch/sh/boards/mach-cayman/setup.c
+++ b/arch/sh/boards/mach-cayman/setup.c
@@ -102,7 +102,7 @@ static int __init smsc_superio_setup(void)
{
unsigned char devid, devrev;
- smsc_superio_virt = onchip_remap(SMSC_SUPERIO_BASE, 1024, "SMSC SuperIO");
+ smsc_superio_virt = (unsigned long)ioremap_nocache(SMSC_SUPERIO_BASE, 1024);
if (!smsc_superio_virt) {
panic("Unable to remap SMSC SuperIO\n");
}
diff --git a/arch/sh/boards/mach-dreamcast/setup.c b/arch/sh/boards/mach-dreamcast/setup.c
index d1bee4884cd6..ebe99227d4e6 100644
--- a/arch/sh/boards/mach-dreamcast/setup.c
+++ b/arch/sh/boards/mach-dreamcast/setup.c
@@ -30,7 +30,6 @@
extern struct irq_chip systemasic_int;
extern void aica_time_init(void);
-extern int gapspci_init(void);
extern int systemasic_irq_demux(int);
static void __init dreamcast_setup(char **cmdline_p)
@@ -51,11 +50,6 @@ static void __init dreamcast_setup(char **cmdline_p)
handle_level_irq);
board_time_init = aica_time_init;
-
-#ifdef CONFIG_PCI
- if (gapspci_init() < 0)
- printk(KERN_WARNING "GAPSPCI was not detected.\n");
-#endif
}
static struct sh_machine_vector mv_dreamcast __initmv = {
diff --git a/arch/sh/boards/mach-r2d/setup.c b/arch/sh/boards/mach-r2d/setup.c
index c585be00956e..a625ecb93e47 100644
--- a/arch/sh/boards/mach-r2d/setup.c
+++ b/arch/sh/boards/mach-r2d/setup.c
@@ -10,6 +10,9 @@
*/
#include <linux/init.h>
#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
#include <linux/ata_platform.h>
#include <linux/sm501.h>
#include <linux/sm501-regs.h>
@@ -181,6 +184,50 @@ static struct platform_device sm501_device = {
.resource = sm501_resources,
};
+static struct mtd_partition r2d_partitions[] = {
+ {
+ .name = "U-Boot",
+ .offset = 0x00000000,
+ .size = 0x00040000,
+ .mask_flags = MTD_WRITEABLE,
+ }, {
+ .name = "Environment",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = 0x00040000,
+ .mask_flags = MTD_WRITEABLE,
+ }, {
+ .name = "Kernel",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = 0x001c0000,
+ }, {
+ .name = "Flash_FS",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = MTDPART_SIZ_FULL,
+ }
+};
+
+static struct physmap_flash_data flash_data = {
+ .width = 2,
+ .nr_parts = ARRAY_SIZE(r2d_partitions),
+ .parts = r2d_partitions,
+};
+
+static struct resource flash_resource = {
+ .start = 0x00000000,
+ .end = 0x02000000,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device flash_device = {
+ .name = "physmap-flash",
+ .id = -1,
+ .resource = &flash_resource,
+ .num_resources = 1,
+ .dev = {
+ .platform_data = &flash_data,
+ },
+};
+
static struct platform_device *rts7751r2d_devices[] __initdata = {
&sm501_device,
&heartbeat_device,
@@ -203,6 +250,9 @@ static int __init rts7751r2d_devices_setup(void)
if (register_trapped_io(&cf_trapped_io) == 0)
platform_device_register(&cf_ide_device);
+ if (mach_is_r2d_plus())
+ platform_device_register(&flash_device);
+
spi_register_board_info(spi_bus, ARRAY_SIZE(spi_bus));
return platform_add_devices(rts7751r2d_devices,
diff --git a/arch/sh/boards/mach-se/7751/Makefile b/arch/sh/boards/mach-se/7751/Makefile
index dbc29f3a9de5..e6f4341bfe6e 100644
--- a/arch/sh/boards/mach-se/7751/Makefile
+++ b/arch/sh/boards/mach-se/7751/Makefile
@@ -3,5 +3,3 @@
#
obj-y := setup.o io.o irq.o
-
-obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/sh/boards/mach-se/7751/io.c b/arch/sh/boards/mach-se/7751/io.c
index 6287ae570319..6e75bd4459e5 100644
--- a/arch/sh/boards/mach-se/7751/io.c
+++ b/arch/sh/boards/mach-se/7751/io.c
@@ -34,8 +34,6 @@ unsigned char sh7751se_inb(unsigned long port)
{
if (PXSEG(port))
return *(volatile unsigned char *)port;
- else if (is_pci_ioaddr(port))
- return *(volatile unsigned char *)pci_ioaddr(port);
else
return (*port2adr(port)) & 0xff;
}
@@ -46,8 +44,6 @@ unsigned char sh7751se_inb_p(unsigned long port)
if (PXSEG(port))
v = *(volatile unsigned char *)port;
- else if (is_pci_ioaddr(port))
- v = *(volatile unsigned char *)pci_ioaddr(port);
else
v = (*port2adr(port)) & 0xff;
ctrl_delay();
@@ -58,8 +54,6 @@ unsigned short sh7751se_inw(unsigned long port)
{
if (PXSEG(port))
return *(volatile unsigned short *)port;
- else if (is_pci_ioaddr(port))
- return *(volatile unsigned short *)pci_ioaddr(port);
else if (port >= 0x2000)
return *port2adr(port);
else
@@ -71,8 +65,6 @@ unsigned int sh7751se_inl(unsigned long port)
{
if (PXSEG(port))
return *(volatile unsigned long *)port;
- else if (is_pci_ioaddr(port))
- return *(volatile unsigned int *)pci_ioaddr(port);
else if (port >= 0x2000)
return *port2adr(port);
else
@@ -85,8 +77,6 @@ void sh7751se_outb(unsigned char value, unsigned long port)
if (PXSEG(port))
*(volatile unsigned char *)port = value;
- else if (is_pci_ioaddr(port))
- *((unsigned char*)pci_ioaddr(port)) = value;
else
*(port2adr(port)) = value;
}
@@ -95,8 +85,6 @@ void sh7751se_outb_p(unsigned char value, unsigned long port)
{
if (PXSEG(port))
*(volatile unsigned char *)port = value;
- else if (is_pci_ioaddr(port))
- *((unsigned char*)pci_ioaddr(port)) = value;
else
*(port2adr(port)) = value;
ctrl_delay();
@@ -106,8 +94,6 @@ void sh7751se_outw(unsigned short value, unsigned long port)
{
if (PXSEG(port))
*(volatile unsigned short *)port = value;
- else if (is_pci_ioaddr(port))
- *((unsigned short *)pci_ioaddr(port)) = value;
else if (port >= 0x2000)
*port2adr(port) = value;
else
@@ -118,8 +104,6 @@ void sh7751se_outl(unsigned int value, unsigned long port)
{
if (PXSEG(port))
*(volatile unsigned long *)port = value;
- else if (is_pci_ioaddr(port))
- *((unsigned long*)pci_ioaddr(port)) = value;
else
maybebadio(port);
}
diff --git a/arch/sh/boards/mach-se/7751/pci.c b/arch/sh/boards/mach-se/7751/pci.c
deleted file mode 100644
index 203b2923fe7f..000000000000
--- a/arch/sh/boards/mach-se/7751/pci.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * linux/arch/sh/boards/se/7751/pci.c
- *
- * Author: Ian DaSilva (idasilva@mvista.com)
- *
- * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * PCI initialization for the Hitachi SH7751 Solution Engine board (MS7751SE01)
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-
-#include <asm/io.h>
-#include "../../../drivers/pci/pci-sh7751.h"
-
-#define PCIMCR_MRSET_OFF 0xBFFFFFFF
-#define PCIMCR_RFSH_OFF 0xFFFFFFFB
-
-/*
- * Only long word accesses of the PCIC's internal local registers and the
- * configuration registers from the CPU is supported.
- */
-#define PCIC_WRITE(x,v) writel((v), PCI_REG(x))
-#define PCIC_READ(x) readl(PCI_REG(x))
-
-/*
- * Description: This function sets up and initializes the pcic, sets
- * up the BARS, maps the DRAM into the address space etc, etc.
- */
-int __init pcibios_init_platform(void)
-{
- unsigned long bcr1, wcr1, wcr2, wcr3, mcr;
- unsigned short bcr2;
-
- /*
- * Initialize the slave bus controller on the pcic. The values used
- * here should not be hardcoded, but they should be taken from the bsc
- * on the processor, to make this function as generic as possible.
- * (i.e. Another sbc may usr different SDRAM timing settings -- in order
- * for the pcic to work, its settings need to be exactly the same.)
- */
- bcr1 = (*(volatile unsigned long*)(SH7751_BCR1));
- bcr2 = (*(volatile unsigned short*)(SH7751_BCR2));
- wcr1 = (*(volatile unsigned long*)(SH7751_WCR1));
- wcr2 = (*(volatile unsigned long*)(SH7751_WCR2));
- wcr3 = (*(volatile unsigned long*)(SH7751_WCR3));
- mcr = (*(volatile unsigned long*)(SH7751_MCR));
-
- bcr1 = bcr1 | 0x00080000; /* Enable Bit 19, BREQEN */
- (*(volatile unsigned long*)(SH7751_BCR1)) = bcr1;
-
- bcr1 = bcr1 | 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */
- PCIC_WRITE(SH7751_PCIBCR1, bcr1); /* PCIC BCR1 */
- PCIC_WRITE(SH7751_PCIBCR2, bcr2); /* PCIC BCR2 */
- PCIC_WRITE(SH7751_PCIWCR1, wcr1); /* PCIC WCR1 */
- PCIC_WRITE(SH7751_PCIWCR2, wcr2); /* PCIC WCR2 */
- PCIC_WRITE(SH7751_PCIWCR3, wcr3); /* PCIC WCR3 */
- mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
- PCIC_WRITE(SH7751_PCIMCR, mcr); /* PCIC MCR */
-
-
- /* Enable all interrupts, so we know what to fix */
- PCIC_WRITE(SH7751_PCIINTM, 0x0000c3ff);
- PCIC_WRITE(SH7751_PCIAINTM, 0x0000380f);
-
- /* Set up standard PCI config registers */
- PCIC_WRITE(SH7751_PCICONF1, 0xF39000C7); /* Bus Master, Mem & I/O access */
- PCIC_WRITE(SH7751_PCICONF2, 0x00000000); /* PCI Class code & Revision ID */
- PCIC_WRITE(SH7751_PCICONF4, 0xab000001); /* PCI I/O address (local regs) */
- PCIC_WRITE(SH7751_PCICONF5, 0x0c000000); /* PCI MEM address (local RAM) */
- PCIC_WRITE(SH7751_PCICONF6, 0xd0000000); /* PCI MEM address (unused) */
- PCIC_WRITE(SH7751_PCICONF11, 0x35051054); /* PCI Subsystem ID & Vendor ID */
- PCIC_WRITE(SH7751_PCILSR0, 0x03f00000); /* MEM (full 64M exposed) */
- PCIC_WRITE(SH7751_PCILSR1, 0x00000000); /* MEM (unused) */
- PCIC_WRITE(SH7751_PCILAR0, 0x0c000000); /* MEM (direct map from PCI) */
- PCIC_WRITE(SH7751_PCILAR1, 0x00000000); /* MEM (unused) */
-
- /* Now turn it on... */
- PCIC_WRITE(SH7751_PCICR, 0xa5000001);
-
- /*
- * Set PCIMBR and PCIIOBR here, assuming a single window
- * (16M MEM, 256K IO) is enough. If a larger space is
- * needed, the readx/writex and inx/outx functions will
- * have to do more (e.g. setting registers for each call).
- */
-
- /*
- * Set the MBR so PCI address is one-to-one with window,
- * meaning all calls go straight through... use BUG_ON to
- * catch erroneous assumption.
- */
- BUG_ON(PCIBIOS_MIN_MEM != SH7751_PCI_MEMORY_BASE);
-
- PCIC_WRITE(SH7751_PCIMBR, PCIBIOS_MIN_MEM);
-
- /* Set IOBR for window containing area specified in pci.h */
- PCIC_WRITE(SH7751_PCIIOBR, (PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK));
-
- /* All done, may as well say so... */
- printk("SH7751 PCI: Finished initialization of the PCI controller\n");
-
- return 1;
-}
-
-int __init pcibios_map_platform_irq(u8 slot, u8 pin)
-{
- switch (slot) {
- case 0: return 13;
- case 1: return 13; /* AMD Ethernet controller */
- case 2: return -1;
- case 3: return -1;
- case 4: return -1;
- default:
- printk("PCI: Bad IRQ mapping request for slot %d\n", slot);
- return -1;
- }
-}
-
-static struct resource sh7751_io_resource = {
- .name = "SH7751 IO",
- .start = SH7751_PCI_IO_BASE,
- .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
- .flags = IORESOURCE_IO
-};
-
-static struct resource sh7751_mem_resource = {
- .name = "SH7751 mem",
- .start = SH7751_PCI_MEMORY_BASE,
- .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
- .flags = IORESOURCE_MEM
-};
-
-extern struct pci_ops sh7751_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
- { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
- { NULL, NULL, NULL, 0, 0 },
-};
-
diff --git a/arch/sh/boards/mach-se/7780/irq.c b/arch/sh/boards/mach-se/7780/irq.c
index 66ad292c9fc3..b8d43b638fcf 100644
--- a/arch/sh/boards/mach-se/7780/irq.c
+++ b/arch/sh/boards/mach-se/7780/irq.c
@@ -12,10 +12,13 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
-#include <asm/irq.h>
-#include <asm/io.h>
+#include <linux/irq.h>
+#include <linux/io.h>
#include <mach-se/mach/se7780.h>
+#define INTC_BASE 0xffd00000
+#define INTC_ICR1 (INTC_BASE+0x1c)
+
/*
* Initialize IRQ setting
*/
@@ -43,4 +46,24 @@ void __init init_se7780_IRQ(void)
ctrl_outw((IRQPIN_PCCPW << IRQPOS_PCCPW), FPGA_INTSEL3);
plat_irq_setup_pins(IRQ_MODE_IRQ); /* install handlers for IRQ0-7 */
+
+ /* ICR1: detect low level(for 2ndcut) */
+ ctrl_outl(0xAAAA0000, INTC_ICR1);
+
+ /*
+ * FPGA PCISEL register initialize
+ *
+ * CPU || SLOT1 | SLOT2 | S-ATA | USB
+ * -------------------------------------
+ * INTA || INTA | INTD | -- | INTB
+ * -------------------------------------
+ * INTB || INTB | INTA | -- | INTC
+ * -------------------------------------
+ * INTC || INTC | INTB | INTA | --
+ * -------------------------------------
+ * INTD || INTD | INTC | -- | INTA
+ * -------------------------------------
+ */
+ ctrl_outw(0x0013, FPGA_PCI_INTSEL1);
+ ctrl_outw(0xE402, FPGA_PCI_INTSEL2);
}
diff --git a/arch/sh/boards/mach-sh03/rtc.c b/arch/sh/boards/mach-sh03/rtc.c
index 0a9266bb51c5..a8b9f844ab5b 100644
--- a/arch/sh/boards/mach-sh03/rtc.c
+++ b/arch/sh/boards/mach-sh03/rtc.c
@@ -35,13 +35,13 @@
#define RTC_BUSY 1
#define RTC_STOP 2
-extern spinlock_t rtc_lock;
+static DEFINE_SPINLOCK(sh03_rtc_lock);
unsigned long get_cmos_time(void)
{
unsigned int year, mon, day, hour, min, sec;
- spin_lock(&rtc_lock);
+ spin_lock(&sh03_rtc_lock);
again:
do {
sec = (ctrl_inb(RTC_SEC1) & 0xf) + (ctrl_inb(RTC_SEC10) & 0x7) * 10;
@@ -73,7 +73,7 @@ unsigned long get_cmos_time(void)
goto again;
}
- spin_unlock(&rtc_lock);
+ spin_unlock(&sh03_rtc_lock);
return mktime(year, mon, day, hour, min, sec);
}
@@ -91,7 +91,7 @@ static int set_rtc_mmss(unsigned long nowtime)
int i;
/* gets recalled with irq locally disabled */
- spin_lock(&rtc_lock);
+ spin_lock(&sh03_rtc_lock);
for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
if (!(ctrl_inb(RTC_CTL) & RTC_BUSY))
break;
@@ -113,7 +113,7 @@ static int set_rtc_mmss(unsigned long nowtime)
cmos_minutes, real_minutes);
retval = -1;
}
- spin_unlock(&rtc_lock);
+ spin_unlock(&sh03_rtc_lock);
return retval;
}
diff --git a/arch/sh/boards/mach-snapgear/io.c b/arch/sh/boards/mach-snapgear/io.c
index 0f4824264557..476650e42dbc 100644
--- a/arch/sh/boards/mach-snapgear/io.c
+++ b/arch/sh/boards/mach-snapgear/io.c
@@ -36,8 +36,6 @@ unsigned char snapgear_inb(unsigned long port)
{
if (PXSEG(port))
return *(volatile unsigned char *)port;
- else if (is_pci_ioaddr(port))
- return *(volatile unsigned char *)pci_ioaddr(port);
else
return (*port2adr(port)) & 0xff;
}
@@ -48,8 +46,6 @@ unsigned char snapgear_inb_p(unsigned long port)
if (PXSEG(port))
v = *(volatile unsigned char *)port;
- else if (is_pci_ioaddr(port))
- v = *(volatile unsigned char *)pci_ioaddr(port);
else
v = (*port2adr(port))&0xff;
ctrl_delay();
@@ -60,8 +56,6 @@ unsigned short snapgear_inw(unsigned long port)
{
if (PXSEG(port))
return *(volatile unsigned short *)port;
- else if (is_pci_ioaddr(port))
- return *(volatile unsigned short *)pci_ioaddr(port);
else if (port >= 0x2000)
return *port2adr(port);
else
@@ -73,8 +67,6 @@ unsigned int snapgear_inl(unsigned long port)
{
if (PXSEG(port))
return *(volatile unsigned long *)port;
- else if (is_pci_ioaddr(port))
- return *(volatile unsigned int *)pci_ioaddr(port);
else if (port >= 0x2000)
return *port2adr(port);
else
@@ -87,8 +79,6 @@ void snapgear_outb(unsigned char value, unsigned long port)
if (PXSEG(port))
*(volatile unsigned char *)port = value;
- else if (is_pci_ioaddr(port))
- *((unsigned char*)pci_ioaddr(port)) = value;
else
*(port2adr(port)) = value;
}
@@ -97,8 +87,6 @@ void snapgear_outb_p(unsigned char value, unsigned long port)
{
if (PXSEG(port))
*(volatile unsigned char *)port = value;
- else if (is_pci_ioaddr(port))
- *((unsigned char*)pci_ioaddr(port)) = value;
else
*(port2adr(port)) = value;
ctrl_delay();
@@ -108,8 +96,6 @@ void snapgear_outw(unsigned short value, unsigned long port)
{
if (PXSEG(port))
*(volatile unsigned short *)port = value;
- else if (is_pci_ioaddr(port))
- *((unsigned short *)pci_ioaddr(port)) = value;
else if (port >= 0x2000)
*port2adr(port) = value;
else
@@ -120,8 +106,6 @@ void snapgear_outl(unsigned int value, unsigned long port)
{
if (PXSEG(port))
*(volatile unsigned long *)port = value;
- else if (is_pci_ioaddr(port))
- *((unsigned long*)pci_ioaddr(port)) = value;
else
maybebadio(port);
}
diff --git a/arch/sh/boards/mach-systemh/io.c b/arch/sh/boards/mach-systemh/io.c
index dec3db0ee933..15577ff1f715 100644
--- a/arch/sh/boards/mach-systemh/io.c
+++ b/arch/sh/boards/mach-systemh/io.c
@@ -35,8 +35,6 @@ unsigned char sh7751systemh_inb(unsigned long port)
{
if (PXSEG(port))
return *(volatile unsigned char *)port;
- else if (is_pci_ioaddr(port))
- return *(volatile unsigned char *)pci_ioaddr(port);
else if (port <= 0x3F1)
return *(volatile unsigned char *)ETHER_IOMAP(port);
else
@@ -49,8 +47,6 @@ unsigned char sh7751systemh_inb_p(unsigned long port)
if (PXSEG(port))
v = *(volatile unsigned char *)port;
- else if (is_pci_ioaddr(port))
- v = *(volatile unsigned char *)pci_ioaddr(port);
else if (port <= 0x3F1)
v = *(volatile unsigned char *)ETHER_IOMAP(port);
else
@@ -63,8 +59,6 @@ unsigned short sh7751systemh_inw(unsigned long port)
{
if (PXSEG(port))
return *(volatile unsigned short *)port;
- else if (is_pci_ioaddr(port))
- return *(volatile unsigned short *)pci_ioaddr(port);
else if (port >= 0x2000)
return *port2adr(port);
else if (port <= 0x3F1)
@@ -78,8 +72,6 @@ unsigned int sh7751systemh_inl(unsigned long port)
{
if (PXSEG(port))
return *(volatile unsigned long *)port;
- else if (is_pci_ioaddr(port))
- return *(volatile unsigned int *)pci_ioaddr(port);
else if (port >= 0x2000)
return *port2adr(port);
else if (port <= 0x3F1)
@@ -94,8 +86,6 @@ void sh7751systemh_outb(unsigned char value, unsigned long port)
if (PXSEG(port))
*(volatile unsigned char *)port = value;
- else if (is_pci_ioaddr(port))
- *((unsigned char*)pci_ioaddr(port)) = value;
else if (port <= 0x3F1)
*(volatile unsigned char *)ETHER_IOMAP(port) = value;
else
@@ -106,8 +96,6 @@ void sh7751systemh_outb_p(unsigned char value, unsigned long port)
{
if (PXSEG(port))
*(volatile unsigned char *)port = value;
- else if (is_pci_ioaddr(port))
- *((unsigned char*)pci_ioaddr(port)) = value;
else if (port <= 0x3F1)
*(volatile unsigned char *)ETHER_IOMAP(port) = value;
else
@@ -119,8 +107,6 @@ void sh7751systemh_outw(unsigned short value, unsigned long port)
{
if (PXSEG(port))
*(volatile unsigned short *)port = value;
- else if (is_pci_ioaddr(port))
- *((unsigned short *)pci_ioaddr(port)) = value;
else if (port >= 0x2000)
*port2adr(port) = value;
else if (port <= 0x3F1)
@@ -133,8 +119,6 @@ void sh7751systemh_outl(unsigned int value, unsigned long port)
{
if (PXSEG(port))
*(volatile unsigned long *)port = value;
- else if (is_pci_ioaddr(port))
- *((unsigned long*)pci_ioaddr(port)) = value;
else
maybebadio(port);
}
diff --git a/arch/sh/boards/mach-titan/io.c b/arch/sh/boards/mach-titan/io.c
index 4badad4c6f30..0130e9826aca 100644
--- a/arch/sh/boards/mach-titan/io.c
+++ b/arch/sh/boards/mach-titan/io.c
@@ -17,8 +17,6 @@ u8 titan_inb(unsigned long port)
{
if (PXSEG(port))
return ctrl_inb(port);
- else if (is_pci_ioaddr(port))
- return ctrl_inb(pci_ioaddr(port));
return ctrl_inw(port2adr(port)) & 0xff;
}
@@ -28,8 +26,6 @@ u8 titan_inb_p(unsigned long port)
if (PXSEG(port))
v = ctrl_inb(port);
- else if (is_pci_ioaddr(port))
- v = ctrl_inb(pci_ioaddr(port));
else
v = ctrl_inw(port2adr(port)) & 0xff;
ctrl_delay();
@@ -40,8 +36,6 @@ u16 titan_inw(unsigned long port)
{
if (PXSEG(port))
return ctrl_inw(port);
- else if (is_pci_ioaddr(port))
- return ctrl_inw(pci_ioaddr(port));
else if (port >= 0x2000)
return ctrl_inw(port2adr(port));
else
@@ -53,8 +47,6 @@ u32 titan_inl(unsigned long port)
{
if (PXSEG(port))
return ctrl_inl(port);
- else if (is_pci_ioaddr(port))
- return ctrl_inl(pci_ioaddr(port));
else if (port >= 0x2000)
return ctrl_inw(port2adr(port));
else
@@ -66,8 +58,6 @@ void titan_outb(u8 value, unsigned long port)
{
if (PXSEG(port))
ctrl_outb(value, port);
- else if (is_pci_ioaddr(port))
- ctrl_outb(value, pci_ioaddr(port));
else
ctrl_outw(value, port2adr(port));
}
@@ -76,8 +66,6 @@ void titan_outb_p(u8 value, unsigned long port)
{
if (PXSEG(port))
ctrl_outb(value, port);
- else if (is_pci_ioaddr(port))
- ctrl_outb(value, pci_ioaddr(port));
else
ctrl_outw(value, port2adr(port));
ctrl_delay();
@@ -87,8 +75,6 @@ void titan_outw(u16 value, unsigned long port)
{
if (PXSEG(port))
ctrl_outw(value, port);
- else if (is_pci_ioaddr(port))
- ctrl_outw(value, pci_ioaddr(port));
else if (port >= 0x2000)
ctrl_outw(value, port2adr(port));
else
@@ -99,8 +85,6 @@ void titan_outl(u32 value, unsigned long port)
{
if (PXSEG(port))
ctrl_outl(value, port);
- else if (is_pci_ioaddr(port))
- ctrl_outl(value, pci_ioaddr(port));
else
maybebadio(port);
}
@@ -117,10 +101,8 @@ void titan_outsl(unsigned long port, const void *src, unsigned long count)
void __iomem *titan_ioport_map(unsigned long port, unsigned int size)
{
- if (PXSEG(port) || is_pci_memaddr(port))
+ if (PXSEG(port))
return (void __iomem *)port;
- else if (is_pci_ioaddr(port))
- return (void __iomem *)pci_ioaddr(port);
return (void __iomem *)port2adr(port);
}
diff --git a/arch/sh/boot/Makefile b/arch/sh/boot/Makefile
index 95483d161258..78efb04c28f3 100644
--- a/arch/sh/boot/Makefile
+++ b/arch/sh/boot/Makefile
@@ -20,9 +20,6 @@ CONFIG_BOOT_LINK_OFFSET ?= 0x00800000
CONFIG_ZERO_PAGE_OFFSET ?= 0x00001000
CONFIG_ENTRY_OFFSET ?= 0x00001000
-export CONFIG_PAGE_OFFSET CONFIG_MEMORY_START CONFIG_BOOT_LINK_OFFSET \
- CONFIG_ZERO_PAGE_OFFSET CONFIG_ENTRY_OFFSET
-
targets := zImage vmlinux.srec uImage uImage.srec
subdir- := compressed
@@ -43,6 +40,9 @@ KERNEL_MEMORY := $(shell /bin/bash -c 'printf "0x%08x" \
$$[$(CONFIG_MEMORY_START)]')
endif
+export CONFIG_PAGE_OFFSET CONFIG_MEMORY_START CONFIG_BOOT_LINK_OFFSET \
+ CONFIG_ZERO_PAGE_OFFSET CONFIG_ENTRY_OFFSET KERNEL_MEMORY
+
KERNEL_LOAD := $(shell /bin/bash -c 'printf "0x%08x" \
$$[$(CONFIG_PAGE_OFFSET) + \
$(KERNEL_MEMORY) + \
diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile
index efb01dc3c8c3..9531bf1b7c2f 100644
--- a/arch/sh/boot/compressed/Makefile
+++ b/arch/sh/boot/compressed/Makefile
@@ -1,5 +1,47 @@
-ifeq ($(CONFIG_SUPERH32),y)
-include ${srctree}/arch/sh/boot/compressed/Makefile_32
-else
-include ${srctree}/arch/sh/boot/compressed/Makefile_64
+#
+# linux/arch/sh/boot/compressed/Makefile
+#
+# create a compressed vmlinux image from the original vmlinux
+#
+
+targets := vmlinux vmlinux.bin vmlinux.bin.gz \
+ head_$(BITS).o misc_$(BITS).o piggy.o
+
+OBJECTS = $(obj)/head_$(BITS).o $(obj)/misc_$(BITS).o $(obj)/cache.o
+
+ifdef CONFIG_SH_STANDARD_BIOS
+OBJECTS += $(obj)/../../kernel/sh_bios.o
endif
+
+#
+# IMAGE_OFFSET is the load offset of the compression loader
+#
+IMAGE_OFFSET := $(shell /bin/bash -c 'printf "0x%08x" \
+ $$[$(CONFIG_PAGE_OFFSET) + \
+ $(KERNEL_MEMORY) + \
+ $(CONFIG_BOOT_LINK_OFFSET)]')
+
+LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
+
+ifeq ($(CONFIG_FUNCTION_TRACER),y)
+ORIG_CFLAGS := $(KBUILD_CFLAGS)
+KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
+endif
+
+LDFLAGS_vmlinux := --oformat $(ld-bfd) -Ttext $(IMAGE_OFFSET) -e startup \
+ -T $(obj)/../../kernel/vmlinux.lds
+
+$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE
+ $(call if_changed,ld)
+ @:
+
+$(obj)/vmlinux.bin: vmlinux FORCE
+ $(call if_changed,objcopy)
+
+$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
+ $(call if_changed,gzip)
+
+OBJCOPYFLAGS += -R .empty_zero_page
+
+$(obj)/piggy.o: $(obj)/piggy.S $(obj)/vmlinux.bin.gz FORCE
+ $(call if_changed,as_o_S)
diff --git a/arch/sh/boot/compressed/Makefile_32 b/arch/sh/boot/compressed/Makefile_32
deleted file mode 100644
index b96a055b053e..000000000000
--- a/arch/sh/boot/compressed/Makefile_32
+++ /dev/null
@@ -1,46 +0,0 @@
-#
-# linux/arch/sh/boot/compressed/Makefile
-#
-# create a compressed vmlinux image from the original vmlinux
-#
-
-targets := vmlinux vmlinux.bin vmlinux.bin.gz \
- head_32.o misc_32.o piggy.o
-
-OBJECTS = $(obj)/head_32.o $(obj)/misc_32.o
-
-ifdef CONFIG_SH_STANDARD_BIOS
-OBJECTS += $(obj)/../../kernel/sh_bios.o
-endif
-
-#
-# IMAGE_OFFSET is the load offset of the compression loader
-#
-IMAGE_OFFSET := $(shell /bin/bash -c 'printf "0x%08x" \
- $$[$(CONFIG_PAGE_OFFSET) + \
- $(CONFIG_MEMORY_START) + \
- $(CONFIG_BOOT_LINK_OFFSET)]')
-
-LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
-
-ifeq ($(CONFIG_FUNCTION_TRACER),y)
-ORIG_CFLAGS := $(KBUILD_CFLAGS)
-KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
-endif
-
-LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup -T $(obj)/../../kernel/vmlinux.lds
-
-$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE
- $(call if_changed,ld)
- @:
-
-$(obj)/vmlinux.bin: vmlinux FORCE
- $(call if_changed,objcopy)
-
-$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
- $(call if_changed,gzip)
-
-OBJCOPYFLAGS += -R .empty_zero_page
-
-$(obj)/piggy.o: $(obj)/piggy.S $(obj)/vmlinux.bin.gz FORCE
- $(call if_changed,as_o_S)
diff --git a/arch/sh/boot/compressed/Makefile_64 b/arch/sh/boot/compressed/Makefile_64
deleted file mode 100644
index 658d4f915556..000000000000
--- a/arch/sh/boot/compressed/Makefile_64
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# arch/sh/boot/compressed/Makefile_64
-#
-# create a compressed vmlinux image from the original vmlinux
-#
-# Copyright (C) 2002 Stuart Menefy
-# Copyright (C) 2004 Paul Mundt
-#
-# 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.
-#
-
-targets := vmlinux vmlinux.bin vmlinux.bin.gz \
- head_64.o misc_64.o cache.o piggy.o
-
-OBJECTS := $(obj)/vmlinux_64.lds $(obj)/head_64.o $(obj)/misc_64.o \
- $(obj)/cache.o
-
-#
-# ZIMAGE_OFFSET is the load offset of the compression loader
-# (4M for the kernel plus 64K for this loader)
-#
-ZIMAGE_OFFSET := $(shell /bin/bash -c 'printf "0x%08x" \
- $$[$(CONFIG_PAGE_OFFSET)+0x400000+0x10000]')
-
-LDFLAGS_vmlinux := -Ttext $(ZIMAGE_OFFSET) -e startup \
- -T $(obj)/../../kernel/vmlinux.lds
-
-$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
- $(call if_changed,ld)
- @:
-
-$(obj)/vmlinux.bin: vmlinux FORCE
- $(call if_changed,objcopy)
-
-$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
- $(call if_changed,gzip)
-
-OBJCOPYFLAGS += -R .empty_zero_page
-
-$(obj)/piggy.o: $(obj)/piggy.S $(obj)/vmlinux.bin.gz FORCE
- $(call if_changed,as_o_S)
diff --git a/arch/sh/boot/compressed/head_64.S b/arch/sh/boot/compressed/head_64.S
index 622eac3cf556..9993113c6713 100644
--- a/arch/sh/boot/compressed/head_64.S
+++ b/arch/sh/boot/compressed/head_64.S
@@ -14,6 +14,7 @@
* Copyright (C) 2002 Stuart Menefy (stuart.menefy@st.com)
*/
#include <asm/cache.h>
+#include <asm/tlb.h>
#include <cpu/mmu_context.h>
#include <cpu/registers.h>
@@ -33,11 +34,7 @@
#define ICCR0_INIT_VAL ICCR0_ON | ICCR0_ICI /* ICE + ICI */
#define ICCR1_INIT_VAL ICCR1_NOLOCK /* No locking */
-#if 1
#define OCCR0_INIT_VAL OCCR0_ON | OCCR0_OCI | OCCR0_WB /* OCE + OCI + WB */
-#else
-#define OCCR0_INIT_VAL OCCR0_OFF
-#endif
#define OCCR1_INIT_VAL OCCR1_NOLOCK /* No locking */
.text
diff --git a/arch/sh/boot/compressed/vmlinux_64.lds b/arch/sh/boot/compressed/vmlinux_64.lds
deleted file mode 100644
index 59c2ef4aeda5..000000000000
--- a/arch/sh/boot/compressed/vmlinux_64.lds
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * ld script to make compressed SuperH/shmedia Linux kernel+decompression
- * bootstrap
- * Modified by Stuart Menefy from arch/sh/vmlinux.lds.S written by Niibe Yutaka
- */
-
-
-#ifdef CONFIG_LITTLE_ENDIAN
-/* OUTPUT_FORMAT("elf32-sh64l-linux", "elf32-sh64l-linux", "elf32-sh64l-linux") */
-#define NOP 0x6ff0fff0
-#else
-/* OUTPUT_FORMAT("elf32-sh64", "elf32-sh64", "elf32-sh64") */
-#define NOP 0xf0fff06f
-#endif
-
-OUTPUT_FORMAT("elf32-sh64-linux")
-OUTPUT_ARCH(sh)
-ENTRY(_start)
-
-#define ALIGNED_GAP(section, align) (((ADDR(section)+SIZEOF(section)+(align)-1) & ~((align)-1))-ADDR(section))
-#define FOLLOWING(section, align) AT (LOADADDR(section) + ALIGNED_GAP(section,align))
-
-SECTIONS
-{
- _text = .; /* Text and read-only data */
-
- .text : {
- *(.text)
- *(.text64)
- *(.text..SHmedia32)
- *(.fixup)
- *(.gnu.warning)
- } = NOP
- . = ALIGN(4);
- .rodata : { *(.rodata) }
-
- /* There is no 'real' reason for eight byte alignment, four would work
- * as well, but gdb downloads much (*4) faster with this.
- */
- . = ALIGN(8);
- .image : { *(.image) }
- . = ALIGN(4);
- _etext = .; /* End of text section */
-
- .data : /* Data */
- FOLLOWING(.image, 4)
- {
- _data = .;
- *(.data)
- }
- _data_image = LOADADDR(.data);/* Address of data section in ROM */
-
- _edata = .; /* End of data section */
-
- .stack : { stack = .; _stack = .; }
-
- . = ALIGN(4);
- __bss_start = .; /* BSS */
- .bss : {
- *(.bss)
- }
- . = ALIGN(4);
- _end = . ;
-}
diff --git a/arch/sh/configs/ap325rxa_defconfig b/arch/sh/configs/ap325rxa_defconfig
index c8d982a8a2e6..022f70e0ea03 100644
--- a/arch/sh/configs/ap325rxa_defconfig
+++ b/arch/sh/configs/ap325rxa_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 17:46:53 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 12:42:06 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -74,6 +75,7 @@ CONFIG_EMBEDDED=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
# CONFIG_KALLSYMS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -92,12 +94,15 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -110,7 +115,6 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -159,6 +163,7 @@ CONFIG_ARCH_SHMOBILE=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
CONFIG_CPU_SUBTYPE_SH7723=y
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -168,8 +173,6 @@ CONFIG_CPU_SUBTYPE_SH7723=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -573,6 +576,7 @@ CONFIG_SCSI_WAIT_SCAN=m
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
# CONFIG_SCSI_OSD_INITIATOR is not set
@@ -695,6 +699,7 @@ CONFIG_DEVKMEM=y
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_MAX3100 is not set
CONFIG_SERIAL_SH_SCI=y
CONFIG_SERIAL_SH_SCI_NR_UARTS=6
CONFIG_SERIAL_SH_SCI_CONSOLE=y
@@ -1030,6 +1035,7 @@ CONFIG_EXT2_FS_POSIX_ACL=y
CONFIG_EXT2_FS_SECURITY=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
@@ -1052,6 +1058,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -1100,6 +1111,7 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -1191,10 +1203,24 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -1303,6 +1329,7 @@ CONFIG_CRYPTO_CBC=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/cayman_defconfig b/arch/sh/configs/cayman_defconfig
index fa5fc1e1e980..40301f86a45c 100644
--- a/arch/sh/configs/cayman_defconfig
+++ b/arch/sh/configs/cayman_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 17:49:14 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:42:53 2009
#
CONFIG_SUPERH=y
# CONFIG_SUPERH32 is not set
@@ -40,6 +40,7 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
# CONFIG_SYSVIPC is not set
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
@@ -70,6 +71,7 @@ CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -89,10 +91,13 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -105,7 +110,6 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -127,39 +131,6 @@ CONFIG_DEFAULT_IOSCHED="cfq"
# System type
#
CONFIG_CPU_SH5=y
-# CONFIG_CPU_SUBTYPE_SH7619 is not set
-# CONFIG_CPU_SUBTYPE_SH7201 is not set
-# CONFIG_CPU_SUBTYPE_SH7203 is not set
-# CONFIG_CPU_SUBTYPE_SH7206 is not set
-# CONFIG_CPU_SUBTYPE_SH7263 is not set
-# CONFIG_CPU_SUBTYPE_MXG is not set
-# CONFIG_CPU_SUBTYPE_SH7705 is not set
-# CONFIG_CPU_SUBTYPE_SH7706 is not set
-# CONFIG_CPU_SUBTYPE_SH7707 is not set
-# CONFIG_CPU_SUBTYPE_SH7708 is not set
-# 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_SH7721 is not set
-# CONFIG_CPU_SUBTYPE_SH7750 is not set
-# CONFIG_CPU_SUBTYPE_SH7091 is not set
-# CONFIG_CPU_SUBTYPE_SH7750R is not set
-# CONFIG_CPU_SUBTYPE_SH7750S is not set
-# CONFIG_CPU_SUBTYPE_SH7751 is not set
-# CONFIG_CPU_SUBTYPE_SH7751R is not set
-# CONFIG_CPU_SUBTYPE_SH7760 is not set
-# CONFIG_CPU_SUBTYPE_SH4_202 is not set
-# CONFIG_CPU_SUBTYPE_SH7723 is not set
-# CONFIG_CPU_SUBTYPE_SH7763 is not set
-# CONFIG_CPU_SUBTYPE_SH7770 is not set
-# CONFIG_CPU_SUBTYPE_SH7780 is not set
-# CONFIG_CPU_SUBTYPE_SH7785 is not set
-# CONFIG_CPU_SUBTYPE_SH7786 is not set
-# CONFIG_CPU_SUBTYPE_SHX3 is not set
-# CONFIG_CPU_SUBTYPE_SH7343 is not set
-# CONFIG_CPU_SUBTYPE_SH7722 is not set
-# CONFIG_CPU_SUBTYPE_SH7366 is not set
CONFIG_CPU_SUBTYPE_SH5_101=y
# CONFIG_CPU_SUBTYPE_SH5_103 is not set
@@ -279,8 +250,6 @@ CONFIG_BOOT_LINK_OFFSET=0x00800000
#
CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
@@ -492,6 +461,7 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -568,6 +538,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_E1000E is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -591,6 +562,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
@@ -779,6 +751,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_F71882FG is not set
# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
@@ -1042,7 +1015,6 @@ CONFIG_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1082,6 +1054,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -1105,6 +1078,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -1146,8 +1124,13 @@ CONFIG_MINIX_FS=y
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -1208,6 +1191,9 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
CONFIG_SCHEDSTATS=y
# CONFIG_TIMER_STATS is not set
@@ -1241,15 +1227,21 @@ CONFIG_FRAME_POINTER=y
# CONFIG_LATENCYTOP is not set
# CONFIG_SYSCTL_SYSCALL_CHECK is not set
# CONFIG_PAGE_POISONING is not set
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_DEBUG_BOOTMEM is not set
@@ -1354,6 +1346,7 @@ CONFIG_CRYPTO=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/dreamcast_defconfig b/arch/sh/configs/dreamcast_defconfig
index 5c1123640142..1f3cc98330bf 100644
--- a/arch/sh/configs/dreamcast_defconfig
+++ b/arch/sh/configs/dreamcast_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 17:51:48 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 12:44:27 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -71,6 +72,7 @@ CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -90,6 +92,7 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
# CONFIG_OPROFILE is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
@@ -98,6 +101,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -110,7 +115,6 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -156,6 +160,7 @@ CONFIG_CPU_SUBTYPE_SH7091=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -165,8 +170,6 @@ CONFIG_CPU_SUBTYPE_SH7091=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -271,7 +274,7 @@ CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_SH_DMA_API=y
CONFIG_SH_DMA=y
CONFIG_SH_DMA_IRQ_MULTI=y
-CONFIG_NR_ONCHIP_DMA_CHANNELS=6
+CONFIG_NR_ONCHIP_DMA_CHANNELS=4
CONFIG_NR_DMA_CHANNELS_BOOL=y
CONFIG_NR_DMA_CHANNELS=9
# CONFIG_PVR2_DMA is not set
@@ -320,7 +323,6 @@ CONFIG_CMDLINE="console=ttySC1,115200 panic=3"
CONFIG_MAPLE=y
CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
@@ -602,6 +604,7 @@ CONFIG_INPUT_MOUSE=y
# CONFIG_MOUSE_APPLETOUCH is not set
# CONFIG_MOUSE_BCM5974 is not set
# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_MAPLE is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
@@ -812,7 +815,6 @@ CONFIG_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
@@ -867,6 +869,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -910,6 +917,7 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
@@ -947,10 +955,24 @@ CONFIG_FRAME_WARN=1024
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -1051,6 +1073,7 @@ CONFIG_CRYPTO=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/edosk7705_defconfig b/arch/sh/configs/edosk7705_defconfig
index f4c34b039312..d7092457ddc7 100644
--- a/arch/sh/configs/edosk7705_defconfig
+++ b/arch/sh/configs/edosk7705_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 17:54:02 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 12:45:04 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -56,6 +57,7 @@ CONFIG_EMBEDDED=y
# CONFIG_UID16 is not set
# CONFIG_SYSCTL_SYSCALL is not set
# CONFIG_KALLSYMS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_HOTPLUG is not set
# CONFIG_PRINTK is not set
# CONFIG_BUG is not set
@@ -74,12 +76,15 @@ CONFIG_SHMEM=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_BASE_SMALL=1
# CONFIG_MODULES is not set
@@ -114,6 +119,7 @@ CONFIG_CPU_SUBTYPE_SH7705=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -123,8 +129,6 @@ CONFIG_CPU_SUBTYPE_SH7705=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -382,6 +386,10 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+
+#
# Pseudo filesystems
#
# CONFIG_PROC_FS is not set
@@ -409,10 +417,22 @@ CONFIG_FRAME_WARN=1024
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -426,6 +446,7 @@ CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/edosk7760_defconfig b/arch/sh/configs/edosk7760_defconfig
index 7825c2699f18..a822b1d8c116 100644
--- a/arch/sh/configs/edosk7760_defconfig
+++ b/arch/sh/configs/edosk7760_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 17:54:57 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 12:45:25 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -40,6 +41,7 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
@@ -67,7 +69,6 @@ CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
@@ -77,6 +78,7 @@ CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -96,6 +98,7 @@ CONFIG_COMPAT_BRK=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -103,6 +106,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -115,7 +120,6 @@ CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -161,6 +165,7 @@ CONFIG_CPU_SH4=y
CONFIG_CPU_SUBTYPE_SH7760=y
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -170,8 +175,6 @@ CONFIG_CPU_SUBTYPE_SH7760=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -815,6 +818,7 @@ CONFIG_EXT2_FS_XATTR=y
# CONFIG_EXT2_FS_SECURITY is not set
CONFIG_EXT2_FS_XIP=y
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -839,6 +843,11 @@ CONFIG_INOTIFY_USER=y
CONFIG_GENERIC_ACL=y
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -883,6 +892,7 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
@@ -964,6 +974,9 @@ CONFIG_DEBUG_SHIRQ=y
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
# CONFIG_SCHED_DEBUG is not set
# CONFIG_SCHEDSTATS is not set
CONFIG_TIMER_STATS=y
@@ -1001,6 +1014,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -1010,9 +1024,14 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
@@ -1126,6 +1145,7 @@ CONFIG_CRYPTO_DES=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/espt_defconfig b/arch/sh/configs/espt_defconfig
index ebb4c37abaa6..c5b50077913d 100644
--- a/arch/sh/configs/espt_defconfig
+++ b/arch/sh/configs/espt_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 17:58:18 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 12:46:26 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -78,6 +79,7 @@ CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -106,6 +108,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -117,7 +121,6 @@ CONFIG_MODULES=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -164,6 +167,7 @@ CONFIG_CPU_SH4A=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
CONFIG_CPU_SUBTYPE_SH7763=y
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -173,8 +177,6 @@ CONFIG_CPU_SUBTYPE_SH7763=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -548,6 +550,7 @@ CONFIG_SCSI_WAIT_SCAN=m
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
# CONFIG_SCSI_OSD_INITIATOR is not set
@@ -919,6 +922,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -943,6 +947,11 @@ CONFIG_AUTOFS4_FS=y
CONFIG_GENERIC_ACL=y
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -985,8 +994,13 @@ CONFIG_CRAMFS=y
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
@@ -1075,11 +1089,25 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_RING_BUFFER=y
CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -1179,6 +1207,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
+CONFIG_BINARY_PRINTF=y
#
# Library routines
diff --git a/arch/sh/configs/hp6xx_defconfig b/arch/sh/configs/hp6xx_defconfig
index 82b113af08d3..8e13027eecc3 100644
--- a/arch/sh/configs/hp6xx_defconfig
+++ b/arch/sh/configs/hp6xx_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:01:05 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 12:47:15 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -67,6 +68,7 @@ CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -85,12 +87,15 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -98,7 +103,6 @@ CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -144,6 +148,7 @@ CONFIG_CPU_SUBTYPE_SH7709=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -153,8 +158,6 @@ CONFIG_CPU_SUBTYPE_SH7709=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -385,6 +388,7 @@ CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
# CONFIG_SCSI_DH is not set
@@ -431,6 +435,7 @@ CONFIG_KEYBOARD_HP6XX=y
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_AD7879 is not set
# CONFIG_TOUCHSCREEN_FUJITSU is not set
# CONFIG_TOUCHSCREEN_GUNZE is not set
# CONFIG_TOUCHSCREEN_ELO is not set
@@ -674,6 +679,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -719,6 +729,7 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
#
# Partition Types
@@ -786,10 +797,23 @@ CONFIG_FRAME_WARN=1024
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -898,6 +922,7 @@ CONFIG_CRYPTO_MD5=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/landisk_defconfig b/arch/sh/configs/landisk_defconfig
index b6fa4a7599d0..7f549aef0dfd 100644
--- a/arch/sh/configs/landisk_defconfig
+++ b/arch/sh/configs/landisk_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:02:54 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 12:47:48 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -69,6 +70,7 @@ CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_EXTRA_PASS=y
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -88,6 +90,7 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -95,6 +98,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -107,7 +112,6 @@ CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -153,6 +157,7 @@ CONFIG_CPU_SUBTYPE_SH7751R=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -162,8 +167,6 @@ CONFIG_CPU_SUBTYPE_SH7751R=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -292,8 +295,6 @@ CONFIG_BOOT_LINK_OFFSET=0x00800000
#
CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
@@ -602,6 +603,7 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -706,6 +708,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_E1000E is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -729,6 +732,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
@@ -922,6 +926,7 @@ CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
# CONFIG_SOC_CAMERA is not set
CONFIG_V4L_USB_DRIVERS=y
# CONFIG_USB_VIDEO_CLASS is not set
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
# CONFIG_USB_GSPCA is not set
# CONFIG_VIDEO_HDPVR is not set
CONFIG_VIDEO_USBVIDEO=m
@@ -994,15 +999,17 @@ CONFIG_USB_HID=m
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=m
CONFIG_HID_APPLE=m
CONFIG_HID_BELKIN=m
CONFIG_HID_CHERRY=m
CONFIG_HID_CHICONY=m
CONFIG_HID_CYPRESS=m
+# CONFIG_DRAGONRISE_FF is not set
CONFIG_HID_EZKEY=m
+# CONFIG_HID_KYE is not set
CONFIG_HID_GYRATION=m
+# CONFIG_HID_KENSINGTON is not set
CONFIG_HID_LOGITECH=m
# CONFIG_LOGITECH_FF is not set
# CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -1197,6 +1204,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -1222,6 +1230,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=m
@@ -1270,10 +1283,15 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
# CONFIG_SYSV_FS is not set
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
# CONFIG_UFS_DEBUG is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
@@ -1364,10 +1382,23 @@ CONFIG_FRAME_WARN=1024
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_SH_STANDARD_BIOS=y
@@ -1469,6 +1500,7 @@ CONFIG_CRYPTO=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/lboxre2_defconfig b/arch/sh/configs/lboxre2_defconfig
index 92c515c4199f..a7db539f2800 100644
--- a/arch/sh/configs/lboxre2_defconfig
+++ b/arch/sh/configs/lboxre2_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:06:51 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 12:48:54 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -69,6 +70,7 @@ CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_EXTRA_PASS=y
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -88,6 +90,7 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -95,6 +98,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -107,7 +112,6 @@ CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -153,6 +157,7 @@ CONFIG_CPU_SUBTYPE_SH7751R=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -162,8 +167,6 @@ CONFIG_CPU_SUBTYPE_SH7751R=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -293,8 +296,6 @@ CONFIG_CMDLINE="console=ttySC1,115200 root=/dev/sda1"
#
CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
@@ -542,6 +543,7 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -702,6 +704,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_E1000E is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -725,6 +728,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
@@ -931,7 +935,6 @@ CONFIG_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1007,6 +1010,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -1029,6 +1033,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -1073,8 +1082,13 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
@@ -1151,10 +1165,23 @@ CONFIG_FRAME_WARN=1024
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_SH_STANDARD_BIOS=y
@@ -1256,6 +1283,7 @@ CONFIG_CRYPTO=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/magicpanelr2_defconfig b/arch/sh/configs/magicpanelr2_defconfig
index 26586c2d64ca..58bec61506fa 100644
--- a/arch/sh/configs/magicpanelr2_defconfig
+++ b/arch/sh/configs/magicpanelr2_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:07:39 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 12:49:32 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -39,6 +40,7 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
# CONFIG_TASKSTATS is not set
@@ -66,7 +68,6 @@ CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
@@ -76,6 +77,7 @@ CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -94,6 +96,7 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -101,6 +104,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -113,7 +118,6 @@ CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -159,6 +163,7 @@ CONFIG_CPU_SUBTYPE_SH7720=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -168,8 +173,6 @@ CONFIG_CPU_SUBTYPE_SH7720=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -813,6 +816,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
@@ -831,6 +835,11 @@ CONFIG_FILE_LOCKING=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -884,6 +893,7 @@ CONFIG_JFFS2_RTIME=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -965,6 +975,7 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_DETECT_HUNG_TASK is not set
# CONFIG_SCHED_DEBUG is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1000,6 +1011,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -1008,9 +1020,14 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
# CONFIG_IRQSOFF_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
@@ -1035,6 +1052,7 @@ CONFIG_DUMP_CODE=y
# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/microdev_defconfig b/arch/sh/configs/microdev_defconfig
index 75178355d69a..2886fc84bc1c 100644
--- a/arch/sh/configs/microdev_defconfig
+++ b/arch/sh/configs/microdev_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:11:13 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 12:50:51 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -65,7 +66,6 @@ CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
@@ -74,6 +74,7 @@ CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -92,12 +93,15 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -105,7 +109,6 @@ CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -151,6 +154,7 @@ CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
CONFIG_CPU_SUBTYPE_SH4_202=y
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -160,8 +164,6 @@ CONFIG_CPU_SUBTYPE_SH4_202=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -647,6 +649,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -669,6 +672,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -715,6 +723,7 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -802,10 +811,24 @@ CONFIG_FRAME_WARN=1024
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -914,6 +937,7 @@ CONFIG_CRYPTO_DES=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/migor_defconfig b/arch/sh/configs/migor_defconfig
index a8720f9c6047..8ecceb4bf27e 100644
--- a/arch/sh/configs/migor_defconfig
+++ b/arch/sh/configs/migor_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:14:03 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 12:51:34 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -67,7 +68,6 @@ CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
@@ -76,6 +76,7 @@ CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -104,6 +105,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -115,7 +118,6 @@ CONFIG_MODULES=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -165,6 +167,7 @@ CONFIG_ARCH_SHMOBILE=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -174,8 +177,6 @@ CONFIG_ARCH_SHMOBILE=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
CONFIG_CPU_SUBTYPE_SH7722=y
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -577,6 +578,7 @@ CONFIG_SCSI_WAIT_SCAN=m
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
# CONFIG_SCSI_OSD_INITIATOR is not set
@@ -873,7 +875,6 @@ CONFIG_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
@@ -1012,6 +1013,11 @@ CONFIG_FILE_LOCKING=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -1056,6 +1062,7 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
@@ -1105,11 +1112,25 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_RING_BUFFER=y
CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -1218,6 +1239,7 @@ CONFIG_CRYPTO_WORKQUEUE=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
+CONFIG_BINARY_PRINTF=y
#
# Library routines
diff --git a/arch/sh/configs/polaris_defconfig b/arch/sh/configs/polaris_defconfig
index df2d177d5346..2b9507286182 100644
--- a/arch/sh/configs/polaris_defconfig
+++ b/arch/sh/configs/polaris_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:16:48 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 12:52:19 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -40,6 +41,7 @@ CONFIG_LOCALVERSION=""
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
# CONFIG_TASKSTATS is not set
@@ -76,6 +78,7 @@ CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -94,6 +97,7 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -101,6 +105,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -113,7 +119,6 @@ CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -159,6 +164,7 @@ CONFIG_CPU_SUBTYPE_SH7709=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -168,8 +174,6 @@ CONFIG_CPU_SUBTYPE_SH7709=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -778,6 +782,11 @@ CONFIG_FILE_LOCKING=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -831,6 +840,7 @@ CONFIG_JFFS2_RTIME=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -874,6 +884,9 @@ CONFIG_DEBUG_SHIRQ=y
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
# CONFIG_SCHED_DEBUG is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -914,6 +927,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -923,9 +937,14 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
@@ -950,6 +969,7 @@ CONFIG_DUMP_CODE=y
# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/r7780mp_defconfig b/arch/sh/configs/r7780mp_defconfig
index 7def4df46ddb..943da63a3852 100644
--- a/arch/sh/configs/r7780mp_defconfig
+++ b/arch/sh/configs/r7780mp_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:20:17 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 12:53:28 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -78,6 +79,7 @@ CONFIG_UID16=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -107,6 +109,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_BASE_SMALL=0
@@ -118,7 +122,6 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -165,6 +168,7 @@ CONFIG_CPU_SH4A=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
CONFIG_CPU_SUBTYPE_SH7780=y
@@ -174,8 +178,6 @@ CONFIG_CPU_SUBTYPE_SH7780=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -258,7 +260,7 @@ CONFIG_SH_R7780MP=y
#
CONFIG_SH_TMU=y
CONFIG_SH_TIMER_IRQ=28
-CONFIG_SH_PCLK_FREQ=32000000
+CONFIG_SH_PCLK_FREQ=33333333
# CONFIG_NO_HZ is not set
# CONFIG_HIGH_RES_TIMERS is not set
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -313,8 +315,6 @@ CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda1"
#
CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
@@ -536,6 +536,7 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -696,6 +697,7 @@ CONFIG_E1000=m
# CONFIG_E1000E is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -719,6 +721,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
@@ -920,6 +923,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_F71882FG is not set
# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
@@ -1027,7 +1031,6 @@ CONFIG_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1120,6 +1123,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -1143,6 +1147,11 @@ CONFIG_INOTIFY_USER=y
CONFIG_FUSE_FS=m
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -1191,6 +1200,7 @@ CONFIG_MINIX_FS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -1279,6 +1289,9 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1316,6 +1329,7 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_RING_BUFFER=y
CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -1325,11 +1339,16 @@ CONFIG_TRACING=y
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
@@ -1449,6 +1468,7 @@ CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_BINARY_PRINTF=y
#
# Library routines
diff --git a/arch/sh/configs/r7785rp_defconfig b/arch/sh/configs/r7785rp_defconfig
index cb134ffc2118..82658f672398 100644
--- a/arch/sh/configs/r7785rp_defconfig
+++ b/arch/sh/configs/r7785rp_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:24:35 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 12:55:10 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -43,6 +44,7 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
@@ -78,6 +80,7 @@ CONFIG_UID16=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -108,6 +111,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -120,7 +125,6 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -168,6 +172,7 @@ CONFIG_CPU_SHX2=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -177,8 +182,6 @@ CONFIG_CPU_SUBTYPE_SH7785=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -266,7 +269,7 @@ CONFIG_SH_R7785RP=y
#
CONFIG_SH_TMU=y
CONFIG_SH_TIMER_IRQ=28
-CONFIG_SH_PCLK_FREQ=50000000
+CONFIG_SH_PCLK_FREQ=33333333
CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
@@ -337,8 +340,6 @@ CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda1"
#
CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCI_LEGACY is not set
@@ -561,6 +562,7 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -698,6 +700,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_E1000E is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -721,6 +724,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
@@ -948,6 +952,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_F71882FG is not set
# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
@@ -970,6 +975,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_DME1737 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
@@ -1109,7 +1115,6 @@ CONFIG_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1202,6 +1207,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -1225,6 +1231,11 @@ CONFIG_INOTIFY_USER=y
CONFIG_FUSE_FS=m
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -1273,6 +1284,7 @@ CONFIG_MINIX_FS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -1359,6 +1371,7 @@ CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_DETECT_HUNG_TASK is not set
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1401,6 +1414,7 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_RING_BUFFER=y
CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -1410,11 +1424,16 @@ CONFIG_TRACING=y
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
@@ -1534,6 +1553,7 @@ CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_BINARY_PRINTF=y
#
# Library routines
diff --git a/arch/sh/configs/rsk7201_defconfig b/arch/sh/configs/rsk7201_defconfig
index a037c744b798..fa4395768d19 100644
--- a/arch/sh/configs/rsk7201_defconfig
+++ b/arch/sh/configs/rsk7201_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:29:08 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 12:56:29 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -65,7 +66,6 @@ CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
@@ -74,6 +74,7 @@ CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -100,6 +101,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_RT_MUTEXES=y
CONFIG_BASE_SMALL=0
@@ -110,7 +113,6 @@ CONFIG_MODULES=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -157,6 +159,7 @@ CONFIG_CPU_SUBTYPE_SH7201=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -166,8 +169,6 @@ CONFIG_CPU_SUBTYPE_SH7201=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -603,6 +604,11 @@ CONFIG_EXT2_FS=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -651,8 +657,13 @@ CONFIG_JFFS2_RTIME=y
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
#
# Partition Types
@@ -686,11 +697,24 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_RING_BUFFER=y
CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -705,6 +729,7 @@ CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
+CONFIG_BINARY_PRINTF=y
#
# Library routines
diff --git a/arch/sh/configs/rsk7203_defconfig b/arch/sh/configs/rsk7203_defconfig
index 9ae28e88426c..e3a65f819f0a 100644
--- a/arch/sh/configs/rsk7203_defconfig
+++ b/arch/sh/configs/rsk7203_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:30:34 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 12:57:06 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -39,6 +40,7 @@ CONFIG_LOCALVERSION=""
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
@@ -70,7 +72,6 @@ CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
@@ -80,6 +81,7 @@ CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -106,6 +108,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_RT_MUTEXES=y
CONFIG_BASE_SMALL=0
@@ -116,7 +120,6 @@ CONFIG_MODULES=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -163,6 +166,7 @@ CONFIG_CPU_SUBTYPE_SH7203=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -172,8 +176,6 @@ CONFIG_CPU_SUBTYPE_SH7203=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -750,15 +752,17 @@ CONFIG_USB_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
+# CONFIG_DRAGONRISE_FF is not set
CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
CONFIG_HID_LOGITECH=y
# CONFIG_LOGITECH_FF is not set
# CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -874,6 +878,7 @@ CONFIG_LEDS_CLASS=y
# LED drivers
#
CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_GPIO_PLATFORM=y
#
# LED Triggers
@@ -882,6 +887,7 @@ CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+# CONFIG_LEDS_TRIGGER_GPIO is not set
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
#
@@ -951,6 +957,11 @@ CONFIG_FILE_LOCKING=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -989,8 +1000,13 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
@@ -1033,6 +1049,9 @@ CONFIG_DEBUG_SHIRQ=y
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1076,6 +1095,7 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_RING_BUFFER=y
CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -1083,11 +1103,16 @@ CONFIG_TRACING=y
# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
@@ -1111,6 +1136,7 @@ CONFIG_DUMP_CODE=y
# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
+CONFIG_BINARY_PRINTF=y
#
# Library routines
diff --git a/arch/sh/configs/rts7751r2d1_defconfig b/arch/sh/configs/rts7751r2d1_defconfig
index c0f741af6da8..a4a59f6205ab 100644
--- a/arch/sh/configs/rts7751r2d1_defconfig
+++ b/arch/sh/configs/rts7751r2d1_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:33:25 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 12:58:13 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -70,6 +71,7 @@ CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -99,6 +101,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -110,7 +114,6 @@ CONFIG_MODULES=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -156,6 +159,7 @@ CONFIG_CPU_SUBTYPE_SH7751R=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -165,8 +169,6 @@ CONFIG_CPU_SUBTYPE_SH7751R=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -302,8 +304,6 @@ CONFIG_CMDLINE="console=tty0 console=ttySC0,115200 root=/dev/sda1 earlyprintk=se
#
CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
@@ -513,6 +513,7 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -672,6 +673,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_E1000E is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -695,6 +697,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
@@ -793,6 +796,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_MAX3100 is not set
CONFIG_SERIAL_SH_SCI=y
CONFIG_SERIAL_SH_SCI_NR_UARTS=1
CONFIG_SERIAL_SH_SCI_CONSOLE=y
@@ -1079,15 +1083,17 @@ CONFIG_USB_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
+# CONFIG_DRAGONRISE_FF is not set
CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
CONFIG_HID_LOGITECH=y
# CONFIG_LOGITECH_FF is not set
# CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -1291,6 +1297,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -1337,6 +1348,7 @@ CONFIG_MINIX_FS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
@@ -1417,11 +1429,25 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_RING_BUFFER=y
CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -1524,6 +1550,7 @@ CONFIG_CRYPTO=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_BINARY_PRINTF=y
#
# Library routines
diff --git a/arch/sh/configs/rts7751r2dplus_defconfig b/arch/sh/configs/rts7751r2dplus_defconfig
index 8feef629e49c..a860435b8847 100644
--- a/arch/sh/configs/rts7751r2dplus_defconfig
+++ b/arch/sh/configs/rts7751r2dplus_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:34:12 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 12:59:01 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -70,6 +71,7 @@ CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -99,6 +101,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -110,7 +114,6 @@ CONFIG_MODULES=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -156,6 +159,7 @@ CONFIG_CPU_SUBTYPE_SH7751R=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -165,8 +169,6 @@ CONFIG_CPU_SUBTYPE_SH7751R=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -302,8 +304,6 @@ CONFIG_CMDLINE="console=tty0 console=ttySC0,115200 root=/dev/sda1 earlyprintk=se
#
CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
@@ -424,7 +424,92 @@ CONFIG_FIRMWARE_IN_KERNEL=y
CONFIG_EXTRA_FIRMWARE=""
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLKDEVS is not set
+# CONFIG_MTD_BLOCK is not set
+# 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
+# CONFIG_MTD_OOPS 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 is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# 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=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# 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 is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR 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_CISS_DA is not set
@@ -513,6 +598,7 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -672,6 +758,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_E1000E is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -695,6 +782,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
@@ -793,6 +881,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_MAX3100 is not set
CONFIG_SERIAL_SH_SCI=y
CONFIG_SERIAL_SH_SCI_NR_UARTS=1
CONFIG_SERIAL_SH_SCI_CONSOLE=y
@@ -1079,15 +1168,17 @@ CONFIG_USB_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
+# CONFIG_DRAGONRISE_FF is not set
CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
CONFIG_HID_LOGITECH=y
# CONFIG_LOGITECH_FF is not set
# CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -1291,6 +1382,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -1337,6 +1433,7 @@ CONFIG_MINIX_FS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
@@ -1417,11 +1514,25 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_RING_BUFFER=y
CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -1524,6 +1635,7 @@ CONFIG_CRYPTO=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_BINARY_PRINTF=y
#
# Library routines
diff --git a/arch/sh/configs/sdk7780_defconfig b/arch/sh/configs/sdk7780_defconfig
index 739e2299ae80..a629b79a1844 100644
--- a/arch/sh/configs/sdk7780_defconfig
+++ b/arch/sh/configs/sdk7780_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:34:43 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 12:59:32 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -41,6 +42,7 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
@@ -73,6 +75,7 @@ CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -93,6 +96,7 @@ CONFIG_COMPAT_BRK=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -100,6 +104,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -112,7 +118,6 @@ CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
CONFIG_LBD=y
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -159,6 +164,7 @@ CONFIG_CPU_SH4A=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
CONFIG_CPU_SUBTYPE_SH7780=y
@@ -168,8 +174,6 @@ CONFIG_CPU_SUBTYPE_SH7780=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -310,8 +314,6 @@ CONFIG_CMDLINE="mem=128M console=tty0 console=ttySC0,115200 ip=bootp root=/dev/n
#
CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCI_LEGACY is not set
@@ -646,6 +648,7 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -1091,15 +1094,17 @@ CONFIG_USB_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
+# CONFIG_DRAGONRISE_FF is not set
CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
CONFIG_HID_LOGITECH=y
# CONFIG_LOGITECH_FF is not set
# CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -1257,6 +1262,7 @@ CONFIG_EXT2_FS_POSIX_ACL=y
# CONFIG_EXT2_FS_SECURITY is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
# CONFIG_EXT3_FS_SECURITY is not set
@@ -1281,6 +1287,11 @@ CONFIG_AUTOFS4_FS=y
CONFIG_GENERIC_ACL=y
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
@@ -1331,6 +1342,7 @@ CONFIG_MINIX_FS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -1418,6 +1430,9 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
# CONFIG_SCHED_DEBUG is not set
# CONFIG_SCHEDSTATS is not set
CONFIG_TIMER_STATS=y
@@ -1455,6 +1470,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -1464,9 +1480,14 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
@@ -1580,6 +1601,7 @@ CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/se7206_defconfig b/arch/sh/configs/se7206_defconfig
index d30e0a7ad9f1..5caf85a3312d 100644
--- a/arch/sh/configs/se7206_defconfig
+++ b/arch/sh/configs/se7206_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:39:37 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:01:02 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -40,6 +41,7 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
@@ -63,6 +65,7 @@ CONFIG_CGROUP_DEBUG=y
CONFIG_CGROUP_NS=y
# CONFIG_CGROUP_FREEZER is not set
CONFIG_CGROUP_DEVICE=y
+# CONFIG_CPUSETS is not set
CONFIG_CGROUP_CPUACCT=y
CONFIG_RESOURCE_COUNTERS=y
CONFIG_CGROUP_MEM_RES_CTLR=y
@@ -80,7 +83,6 @@ CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
@@ -90,6 +92,7 @@ CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -116,6 +119,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_RT_MUTEXES=y
CONFIG_BASE_SMALL=0
@@ -127,7 +132,6 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -174,6 +178,7 @@ CONFIG_CPU_SUBTYPE_SH7206=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -183,8 +188,6 @@ CONFIG_CPU_SUBTYPE_SH7206=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -746,6 +749,11 @@ CONFIG_FILE_LOCKING=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -785,8 +793,13 @@ CONFIG_CRAMFS=y
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -831,6 +844,9 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -869,6 +885,7 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_RING_BUFFER=y
CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -876,11 +893,16 @@ CONFIG_TRACING=y
# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
@@ -991,6 +1013,7 @@ CONFIG_CRYPTO_LZO=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
+CONFIG_BINARY_PRINTF=y
#
# Library routines
diff --git a/arch/sh/configs/se7343_defconfig b/arch/sh/configs/se7343_defconfig
index fbb72d029e68..004d531716dc 100644
--- a/arch/sh/configs/se7343_defconfig
+++ b/arch/sh/configs/se7343_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:42:00 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:01:44 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -40,6 +41,7 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
@@ -73,6 +75,7 @@ CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -91,6 +94,7 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -98,6 +102,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_BASE_SMALL=0
@@ -109,7 +115,6 @@ CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -158,6 +163,7 @@ CONFIG_ARCH_SHMOBILE=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -167,8 +173,6 @@ CONFIG_ARCH_SHMOBILE=y
CONFIG_CPU_SUBTYPE_SH7343=y
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -769,6 +773,7 @@ CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
# CONFIG_SOC_CAMERA is not set
CONFIG_V4L_USB_DRIVERS=y
# CONFIG_USB_VIDEO_CLASS is not set
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
CONFIG_USB_GSPCA=m
# CONFIG_USB_M5602 is not set
# CONFIG_USB_STV06XX is not set
@@ -800,6 +805,7 @@ CONFIG_USB_GSPCA=m
# CONFIG_VIDEO_PVRUSB2 is not set
# CONFIG_VIDEO_HDPVR is not set
# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_CX231XX is not set
# CONFIG_VIDEO_USBVISION is not set
# CONFIG_USB_VICAM is not set
# CONFIG_USB_IBMCAM is not set
@@ -813,6 +819,7 @@ CONFIG_USB_GSPCA=m
# CONFIG_USB_STV680 is not set
# CONFIG_USB_ZC0301 is not set
# CONFIG_USB_PWC is not set
+CONFIG_USB_PWC_INPUT_EVDEV=y
# CONFIG_USB_ZR364XX is not set
# CONFIG_USB_STKWEBCAM is not set
# CONFIG_USB_S2255 is not set
@@ -914,15 +921,17 @@ CONFIG_USB_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
+# CONFIG_DRAGONRISE_FF is not set
CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
CONFIG_HID_LOGITECH=y
# CONFIG_LOGITECH_FF is not set
# CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -1050,6 +1059,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -1071,6 +1081,11 @@ CONFIG_FILE_LOCKING=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -1125,6 +1140,7 @@ CONFIG_CRAMFS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -1174,10 +1190,23 @@ CONFIG_FRAME_WARN=1024
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -1279,6 +1308,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/se7619_defconfig b/arch/sh/configs/se7619_defconfig
index 125304e80f57..edbece52afc1 100644
--- a/arch/sh/configs/se7619_defconfig
+++ b/arch/sh/configs/se7619_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:44:53 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:02:32 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -61,6 +62,7 @@ CONFIG_EMBEDDED=y
# CONFIG_UID16 is not set
# CONFIG_SYSCTL_SYSCALL is not set
# CONFIG_KALLSYMS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -78,11 +80,14 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_BASE_SMALL=1
@@ -134,6 +139,7 @@ CONFIG_CPU_SUBTYPE_SH7619=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -143,8 +149,6 @@ CONFIG_CPU_SUBTYPE_SH7619=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -513,7 +517,6 @@ CONFIG_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
@@ -564,6 +567,11 @@ CONFIG_FILE_LOCKING=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -601,8 +609,13 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
#
# Partition Types
@@ -630,10 +643,21 @@ CONFIG_FRAME_WARN=1024
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -647,6 +671,7 @@ CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/se7705_defconfig b/arch/sh/configs/se7705_defconfig
index 0308abf52384..bae161c66835 100644
--- a/arch/sh/configs/se7705_defconfig
+++ b/arch/sh/configs/se7705_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:45:56 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:02:52 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -62,7 +63,6 @@ CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
@@ -70,6 +70,7 @@ CONFIG_EMBEDDED=y
CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
# CONFIG_KALLSYMS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -88,12 +89,15 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -150,6 +154,7 @@ CONFIG_CPU_SUBTYPE_SH7705=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -159,8 +164,6 @@ CONFIG_CPU_SUBTYPE_SH7705=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -698,7 +701,6 @@ CONFIG_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
@@ -752,6 +754,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -804,6 +811,7 @@ CONFIG_JFFS2_RTIME=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
@@ -847,10 +855,23 @@ CONFIG_FRAME_WARN=1024
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -949,6 +970,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/se7712_defconfig b/arch/sh/configs/se7712_defconfig
index a8c24b703489..330043f3c316 100644
--- a/arch/sh/configs/se7712_defconfig
+++ b/arch/sh/configs/se7712_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:48:18 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:03:27 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -38,6 +39,7 @@ CONFIG_LOCALVERSION=""
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
@@ -69,6 +71,7 @@ CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
# CONFIG_BUG is not set
@@ -87,6 +90,7 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -94,6 +98,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -105,7 +111,6 @@ CONFIG_MODULES=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -151,6 +156,7 @@ CONFIG_CPU_SUBTYPE_SH7712=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -160,8 +166,6 @@ CONFIG_CPU_SUBTYPE_SH7712=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -585,6 +589,7 @@ CONFIG_SCSI_WAIT_SCAN=m
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
# CONFIG_SCSI_OSD_INITIATOR is not set
@@ -812,6 +817,7 @@ CONFIG_EXT2_FS_POSIX_ACL=y
CONFIG_EXT2_FS_SECURITY=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -833,6 +839,11 @@ CONFIG_FILE_LOCKING=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -887,6 +898,7 @@ CONFIG_CRAMFS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
@@ -927,6 +939,7 @@ CONFIG_FRAME_WARN=1024
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_DETECT_HUNG_TASK is not set
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -961,6 +974,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -969,9 +983,14 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
# CONFIG_IRQSOFF_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
@@ -1090,6 +1109,7 @@ CONFIG_CRYPTO_DEFLATE=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/se7721_defconfig b/arch/sh/configs/se7721_defconfig
index 4b79c2567dc8..56478918440d 100644
--- a/arch/sh/configs/se7721_defconfig
+++ b/arch/sh/configs/se7721_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:51:44 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:04:19 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -38,6 +39,7 @@ CONFIG_LOCALVERSION=""
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
@@ -73,6 +75,7 @@ CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
# CONFIG_BUG is not set
@@ -91,6 +94,7 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -98,6 +102,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -109,7 +115,6 @@ CONFIG_MODULES=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -155,6 +160,7 @@ CONFIG_CPU_SUBTYPE_SH7721=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -164,8 +170,6 @@ CONFIG_CPU_SUBTYPE_SH7721=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -776,15 +780,17 @@ CONFIG_USB_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
+# CONFIG_DRAGONRISE_FF is not set
CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
CONFIG_HID_LOGITECH=y
# CONFIG_LOGITECH_FF is not set
# CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -943,6 +949,7 @@ CONFIG_EXT2_FS_POSIX_ACL=y
CONFIG_EXT2_FS_SECURITY=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -964,6 +971,11 @@ CONFIG_FILE_LOCKING=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -1021,6 +1033,7 @@ CONFIG_CRAMFS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
# CONFIG_NETWORK_FILESYSTEMS is not set
#
@@ -1085,6 +1098,7 @@ CONFIG_FRAME_WARN=1024
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_DETECT_HUNG_TASK is not set
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1119,6 +1133,7 @@ CONFIG_FRAME_POINTER=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -1127,9 +1142,14 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
# CONFIG_IRQSOFF_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
@@ -1248,6 +1268,7 @@ CONFIG_CRYPTO_DEFLATE=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/se7722_defconfig b/arch/sh/configs/se7722_defconfig
index 82bdaac45fb5..726fdbdb2807 100644
--- a/arch/sh/configs/se7722_defconfig
+++ b/arch/sh/configs/se7722_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:55:10 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:05:29 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -69,7 +70,6 @@ CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
@@ -78,6 +78,7 @@ CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -97,6 +98,7 @@ CONFIG_COMPAT_BRK=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
# CONFIG_OPROFILE is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
@@ -105,6 +107,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -117,7 +121,6 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -167,6 +170,7 @@ CONFIG_ARCH_SHMOBILE=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -176,8 +180,6 @@ CONFIG_ARCH_SHMOBILE=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
CONFIG_CPU_SUBTYPE_SH7722=y
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -486,6 +488,7 @@ CONFIG_SCSI_WAIT_SCAN=m
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
# CONFIG_SCSI_OSD_INITIATOR is not set
@@ -692,7 +695,6 @@ CONFIG_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
@@ -766,6 +768,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -789,6 +792,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -832,6 +840,7 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
@@ -872,11 +881,25 @@ CONFIG_DEBUG_FS=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_SH_STANDARD_BIOS=y
@@ -977,6 +1000,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/se7750_defconfig b/arch/sh/configs/se7750_defconfig
index ceef6d9138ee..ed1a1230f636 100644
--- a/arch/sh/configs/se7750_defconfig
+++ b/arch/sh/configs/se7750_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:57:31 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:06:02 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -70,6 +71,7 @@ CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -88,6 +90,7 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -95,6 +98,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -106,7 +111,6 @@ CONFIG_MODULES=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -152,6 +156,7 @@ CONFIG_CPU_SUBTYPE_SH7750=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -161,8 +166,6 @@ CONFIG_CPU_SUBTYPE_SH7750=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -553,6 +556,7 @@ CONFIG_SCSI_WAIT_SCAN=m
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
# CONFIG_SCSI_OSD_INITIATOR is not set
@@ -775,6 +779,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -829,6 +838,7 @@ CONFIG_JFFS2_RTIME=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
@@ -886,10 +896,23 @@ CONFIG_FRAME_WARN=1024
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -989,6 +1012,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/se7751_defconfig b/arch/sh/configs/se7751_defconfig
index 67fc26b3a7d0..55f3b788e0cb 100644
--- a/arch/sh/configs/se7751_defconfig
+++ b/arch/sh/configs/se7751_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 18:59:59 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:06:44 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -65,7 +66,6 @@ CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
@@ -74,6 +74,7 @@ CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -92,6 +93,7 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -99,6 +101,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -110,7 +114,6 @@ CONFIG_MODULES=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -156,6 +159,7 @@ CONFIG_CPU_SUBTYPE_SH7751=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -165,8 +169,6 @@ CONFIG_CPU_SUBTYPE_SH7751=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -742,6 +744,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -796,6 +803,7 @@ CONFIG_JFFS2_RTIME=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
@@ -833,10 +841,23 @@ CONFIG_FRAME_WARN=1024
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -936,6 +957,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/se7780_defconfig b/arch/sh/configs/se7780_defconfig
index ebce23cc2ad8..c4f0af32efa9 100644
--- a/arch/sh/configs/se7780_defconfig
+++ b/arch/sh/configs/se7780_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 19:02:05 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:07:14 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -67,6 +68,7 @@ CONFIG_EMBEDDED=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
# CONFIG_KALLSYMS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -86,12 +88,15 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -103,7 +108,6 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
#
@@ -149,6 +153,7 @@ CONFIG_CPU_SH4A=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
CONFIG_CPU_SUBTYPE_SH7780=y
@@ -158,8 +163,6 @@ CONFIG_CPU_SUBTYPE_SH7780=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -285,8 +288,6 @@ CONFIG_CMDLINE="console=ttySC0.115200 root=/dev/sda1"
#
CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
@@ -558,6 +559,7 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -957,15 +959,17 @@ CONFIG_USB_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
+# CONFIG_DRAGONRISE_FF is not set
CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
CONFIG_HID_LOGITECH=y
# CONFIG_LOGITECH_FF is not set
# CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -1122,6 +1126,10 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -1245,11 +1253,24 @@ CONFIG_DEBUG_FS=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -1345,6 +1366,7 @@ CONFIG_CRYPTO=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/sh03_defconfig b/arch/sh/configs/sh03_defconfig
index 6fcdb090cf32..f9c6e51dc0b0 100644
--- a/arch/sh/configs/sh03_defconfig
+++ b/arch/sh/configs/sh03_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 19:04:59 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:07:56 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -41,6 +42,7 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
@@ -67,7 +69,6 @@ CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
@@ -76,6 +77,7 @@ CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -105,6 +107,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -117,7 +121,6 @@ CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -163,6 +166,7 @@ CONFIG_CPU_SUBTYPE_SH7751=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -172,8 +176,6 @@ CONFIG_CPU_SUBTYPE_SH7751=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -300,8 +302,6 @@ CONFIG_CMDLINE="console=ttySC1,115200 mem=64M root=/dev/nfs"
#
CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
@@ -562,6 +562,7 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -656,6 +657,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_E1000E is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -679,6 +681,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
@@ -887,7 +890,6 @@ CONFIG_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
@@ -929,6 +931,7 @@ CONFIG_EXT2_FS_XATTR=y
# CONFIG_EXT2_FS_SECURITY is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
# CONFIG_EXT3_FS_SECURITY is not set
@@ -952,6 +955,11 @@ CONFIG_AUTOFS4_FS=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=m
@@ -1001,6 +1009,7 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -1112,11 +1121,26 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_RING_BUFFER=y
CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_SH_STANDARD_BIOS=y
@@ -1228,6 +1252,7 @@ CONFIG_CRYPTO_DEFLATE=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_BINARY_PRINTF=y
#
# Library routines
diff --git a/arch/sh/configs/sh7710voipgw_defconfig b/arch/sh/configs/sh7710voipgw_defconfig
index 1ab37c01da6e..48b58098cf84 100644
--- a/arch/sh/configs/sh7710voipgw_defconfig
+++ b/arch/sh/configs/sh7710voipgw_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 19:09:01 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:09:16 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -39,6 +40,7 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
@@ -72,6 +74,7 @@ CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -90,6 +93,7 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -97,6 +101,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_BASE_SMALL=0
@@ -108,7 +114,6 @@ CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -154,6 +159,7 @@ CONFIG_CPU_SUBTYPE_SH7710=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -163,8 +169,6 @@ CONFIG_CPU_SUBTYPE_SH7710=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -728,7 +732,6 @@ CONFIG_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
@@ -780,6 +783,11 @@ CONFIG_FILE_LOCKING=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -834,6 +842,7 @@ CONFIG_JFFS2_RTIME=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
@@ -871,11 +880,24 @@ CONFIG_DEBUG_FS=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -975,6 +997,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/sh7724_generic_defconfig b/arch/sh/configs/sh7724_generic_defconfig
new file mode 100644
index 000000000000..ec8f18c7684c
--- /dev/null
+++ b/arch/sh/configs/sh7724_generic_defconfig
@@ -0,0 +1,707 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:09:47 2009
+#
+CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
+CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GENERIC_IRQ_PROBE=y
+# CONFIG_GENERIC_GPIO is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_CMT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_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_ARCH_HAS_DEFAULT_IDLE=y
+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 is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+
+#
+# RCU Subsystem
+#
+# CONFIG_CLASSIC_RCU is not set
+CONFIG_TREE_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CGROUP_NS is not set
+# CONFIG_CGROUP_FREEZER is not set
+# CONFIG_CGROUP_DEVICE is not set
+# CONFIG_CPUSETS is not set
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_RESOURCE_COUNTERS is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+# CONFIG_UID16 is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+# CONFIG_MODULES is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_FREEZER=y
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+CONFIG_CPU_SHX2=y
+CONFIG_ARCH_SHMOBILE=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
+# CONFIG_CPU_SUBTYPE_SH7203 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7263 is not set
+# CONFIG_CPU_SUBTYPE_MXG is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# 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_SH7721 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+# CONFIG_CPU_SUBTYPE_SH7723 is not set
+CONFIG_CPU_SUBTYPE_SH7724=y
+# CONFIG_CPU_SUBTYPE_SH7763 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SH7786 is not set
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+# CONFIG_CPU_SUBTYPE_SH7366 is not set
+
+#
+# Memory management options
+#
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_29BIT=y
+# CONFIG_X2TLB is not set
+CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_ENTRY_OFFSET=0x00001000
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_STATIC=y
+
+#
+# Memory hotplug is currently incompatible with Software Suspend
+#
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+
+#
+# Cache configuration
+#
+CONFIG_CACHE_WRITEBACK=y
+# CONFIG_CACHE_WRITETHROUGH is not set
+# CONFIG_CACHE_OFF is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
+# CONFIG_SH_STORE_QUEUES is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_PTEA=y
+CONFIG_CPU_HAS_FPU=y
+
+#
+# Board support
+#
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_CMT=y
+CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_PCLK_FREQ=41666666
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+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_POWERSAVE is not set
+# 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 is not set
+# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+CONFIG_SH_CPU_FREQ=y
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_HEARTBEAT is not set
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# 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_SCHED_HRTICK=y
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+CONFIG_KEXEC_JUMP=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_GUSA=y
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_STD_PARTITION=""
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# 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_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=6
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 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
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_SH_MOBILE=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_REGULATOR is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# 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_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_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_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_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
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SH=y
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_UIO=y
+# CONFIG_UIO_PDRV is not set
+CONFIG_UIO_PDRV_GENIRQ=y
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE 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 is not set
+# CONFIG_SYSFS is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC32 is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/sh7763rdp_defconfig b/arch/sh/configs/sh7763rdp_defconfig
index c79bb84ec305..f77bc7998d2f 100644
--- a/arch/sh/configs/sh7763rdp_defconfig
+++ b/arch/sh/configs/sh7763rdp_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 19:10:57 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:10:12 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -78,6 +79,7 @@ CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -106,6 +108,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -117,7 +121,6 @@ CONFIG_MODULES=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -164,6 +167,7 @@ CONFIG_CPU_SH4A=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
CONFIG_CPU_SUBTYPE_SH7763=y
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -173,8 +177,6 @@ CONFIG_CPU_SUBTYPE_SH7763=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -555,6 +557,7 @@ CONFIG_SCSI_WAIT_SCAN=m
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
# CONFIG_SCSI_OSD_INITIATOR is not set
@@ -941,6 +944,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -965,6 +969,11 @@ CONFIG_AUTOFS4_FS=y
CONFIG_GENERIC_ACL=y
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -1012,6 +1021,7 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
@@ -1100,11 +1110,25 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_RING_BUFFER=y
CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -1204,6 +1228,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
+CONFIG_BINARY_PRINTF=y
#
# Library routines
diff --git a/arch/sh/configs/sh7785lcr_32bit_defconfig b/arch/sh/configs/sh7785lcr_32bit_defconfig
index a6cf4505741c..1c55b800d124 100644
--- a/arch/sh/configs/sh7785lcr_32bit_defconfig
+++ b/arch/sh/configs/sh7785lcr_32bit_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 19:12:18 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:10:53 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -79,6 +80,7 @@ CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -98,6 +100,7 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
# CONFIG_OPROFILE is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
@@ -106,6 +109,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -118,7 +123,6 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -166,6 +170,7 @@ CONFIG_CPU_SHX2=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -175,8 +180,6 @@ CONFIG_CPU_SUBTYPE_SH7785=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -310,8 +313,6 @@ CONFIG_BOOT_LINK_OFFSET=0x00800000
#
CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
@@ -672,6 +673,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_E1000E is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -1009,15 +1011,17 @@ CONFIG_USB_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
+# CONFIG_DRAGONRISE_FF is not set
CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
CONFIG_HID_LOGITECH=y
# CONFIG_LOGITECH_FF is not set
# CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -1218,6 +1222,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -1240,6 +1245,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -1289,6 +1299,7 @@ CONFIG_MINIX_FS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -1377,6 +1388,9 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1413,6 +1427,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -1422,9 +1437,14 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
@@ -1542,6 +1562,7 @@ CONFIG_CRYPTO_DES=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/sh7785lcr_defconfig b/arch/sh/configs/sh7785lcr_defconfig
index 8a42bbef1f50..4385fe97a780 100644
--- a/arch/sh/configs/sh7785lcr_defconfig
+++ b/arch/sh/configs/sh7785lcr_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 19:15:58 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:11:48 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -79,6 +80,7 @@ CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -98,6 +100,7 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
# CONFIG_OPROFILE is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
@@ -106,6 +109,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -118,7 +123,6 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -166,6 +170,7 @@ CONFIG_CPU_SHX2=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -175,8 +180,6 @@ CONFIG_CPU_SUBTYPE_SH7785=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -186,38 +189,31 @@ CONFIG_MMU=y
CONFIG_PAGE_OFFSET=0x80000000
CONFIG_MEMORY_START=0x08000000
CONFIG_MEMORY_SIZE=0x08000000
-# CONFIG_29BIT is not set
-CONFIG_32BIT=y
-CONFIG_PMB_ENABLE=y
-# CONFIG_PMB is not set
-CONFIG_PMB_FIXED=y
+CONFIG_29BIT=y
+# CONFIG_PMB_ENABLE 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=2
+CONFIG_MAX_ACTIVE_REGIONS=1
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_8KB is not set
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
CONFIG_ENTRY_OFFSET=0x00001000
CONFIG_SELECT_MEMORY_MODEL=y
-# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
-CONFIG_SPARSEMEM_MANUAL=y
-CONFIG_SPARSEMEM=y
-CONFIG_HAVE_MEMORY_PRESENT=y
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
-# CONFIG_MEMORY_HOTPLUG is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_MIGRATION=y
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -249,6 +245,7 @@ CONFIG_CPU_HAS_FPU=y
#
# CONFIG_SH_HIGHLANDER is not set
CONFIG_SH_SH7785LCR=y
+CONFIG_SH_SH7785LCR_29BIT_PHYSMAPS=y
#
# Timer and clock configuration
@@ -310,8 +307,6 @@ CONFIG_BOOT_LINK_OFFSET=0x00800000
#
CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
@@ -672,6 +667,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_E1000E is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -1009,15 +1005,17 @@ CONFIG_USB_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
+# CONFIG_DRAGONRISE_FF is not set
CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
CONFIG_HID_LOGITECH=y
# CONFIG_LOGITECH_FF is not set
# CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -1218,6 +1216,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -1240,6 +1239,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -1289,6 +1293,7 @@ CONFIG_MINIX_FS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -1377,6 +1382,9 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1413,6 +1421,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -1422,9 +1431,14 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
@@ -1542,6 +1556,7 @@ CONFIG_CRYPTO_DES=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/shmin_defconfig b/arch/sh/configs/shmin_defconfig
index d695e9061874..4e120256ec63 100644
--- a/arch/sh/configs/shmin_defconfig
+++ b/arch/sh/configs/shmin_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 19:19:03 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:12:41 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -63,6 +64,7 @@ CONFIG_EMBEDDED=y
# CONFIG_UID16 is not set
# CONFIG_SYSCTL_SYSCALL is not set
# CONFIG_KALLSYMS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
# CONFIG_BUG is not set
@@ -81,12 +83,15 @@ CONFIG_COMPAT_BRK=y
# CONFIG_SLUB is not set
CONFIG_SLOB=y
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_BASE_SMALL=1
# CONFIG_MODULES is not set
@@ -137,6 +142,7 @@ CONFIG_CPU_SUBTYPE_SH7706=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -146,8 +152,6 @@ CONFIG_CPU_SUBTYPE_SH7706=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -675,6 +679,11 @@ CONFIG_FILE_LOCKING=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -718,6 +727,7 @@ CONFIG_CRAMFS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -762,10 +772,22 @@ CONFIG_FRAME_WARN=1024
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_SH_STANDARD_BIOS=y
@@ -864,6 +886,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/shx3_defconfig b/arch/sh/configs/shx3_defconfig
index e3651f574399..c088144925fa 100644
--- a/arch/sh/configs/shx3_defconfig
+++ b/arch/sh/configs/shx3_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 19:20:54 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:13:12 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -42,6 +43,7 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
@@ -96,6 +98,7 @@ CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -126,6 +129,8 @@ CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_USE_GENERIC_SMP_HELPERS=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_RT_MUTEXES=y
CONFIG_BASE_SMALL=0
@@ -138,7 +143,6 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -186,6 +190,7 @@ CONFIG_CPU_SHX3=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -195,8 +200,6 @@ CONFIG_CPU_SUBTYPE_SHX3=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -553,6 +556,7 @@ CONFIG_SCSI_WAIT_SCAN=m
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
# CONFIG_SCSI_OSD_INITIATOR is not set
@@ -646,6 +650,7 @@ CONFIG_DEVKMEM=y
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_MAX3100 is not set
CONFIG_SERIAL_SH_SCI=y
CONFIG_SERIAL_SH_SCI_NR_UARTS=2
CONFIG_SERIAL_SH_SCI_CONSOLE=y
@@ -985,6 +990,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -1008,6 +1014,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -1051,6 +1062,7 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
@@ -1085,6 +1097,9 @@ CONFIG_DEBUG_SHIRQ=y
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1124,6 +1139,7 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_RING_BUFFER=y
CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -1133,11 +1149,16 @@ CONFIG_TRACING=y
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
@@ -1245,6 +1266,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
+CONFIG_BINARY_PRINTF=y
#
# Library routines
diff --git a/arch/sh/configs/snapgear_defconfig b/arch/sh/configs/snapgear_defconfig
index 6960f60bf52e..54a7a3c41f34 100644
--- a/arch/sh/configs/snapgear_defconfig
+++ b/arch/sh/configs/snapgear_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 19:21:39 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:14:00 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -64,7 +65,6 @@ CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
@@ -73,6 +73,7 @@ CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -92,12 +93,15 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -105,7 +109,6 @@ CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -151,6 +154,7 @@ CONFIG_CPU_SUBTYPE_SH7751R=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -160,8 +164,6 @@ CONFIG_CPU_SUBTYPE_SH7751R=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -295,8 +297,6 @@ CONFIG_BOOT_LINK_OFFSET=0x00800000
#
CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
@@ -763,6 +763,11 @@ CONFIG_FILE_LOCKING=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -805,8 +810,13 @@ CONFIG_CRAMFS=y
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
@@ -844,10 +854,23 @@ CONFIG_FRAME_WARN=1024
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -862,6 +885,7 @@ CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/systemh_defconfig b/arch/sh/configs/systemh_defconfig
index 7ea639bc5936..dbe7e546f0bb 100644
--- a/arch/sh/configs/systemh_defconfig
+++ b/arch/sh/configs/systemh_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 19:23:31 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:14:33 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -61,7 +62,6 @@ CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
@@ -70,6 +70,7 @@ CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -88,6 +89,7 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -95,6 +97,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -107,7 +111,6 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -153,6 +156,7 @@ CONFIG_CPU_SUBTYPE_SH7751R=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -162,8 +166,6 @@ CONFIG_CPU_SUBTYPE_SH7751R=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -506,6 +508,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -547,8 +554,13 @@ CONFIG_CRAMFS=y
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
#
# Partition Types
@@ -577,10 +589,24 @@ CONFIG_FRAME_WARN=1024
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -595,6 +621,7 @@ CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/titan_defconfig b/arch/sh/configs/titan_defconfig
index bbeb4c6ebb95..8ca94ef74278 100644
--- a/arch/sh/configs/titan_defconfig
+++ b/arch/sh/configs/titan_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 19:24:55 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:14:55 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -40,6 +41,7 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
@@ -66,7 +68,6 @@ CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
@@ -76,6 +77,7 @@ CONFIG_UID16=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -95,6 +97,7 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -102,6 +105,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -114,7 +119,6 @@ CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -160,6 +164,7 @@ CONFIG_CPU_SUBTYPE_SH7751R=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -169,8 +174,6 @@ CONFIG_CPU_SUBTYPE_SH7751R=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -305,8 +308,6 @@ CONFIG_CMDLINE="console=ttySC1,38400N81 root=/dev/nfs ip=:::::eth1:autoconf rw"
#
CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
@@ -789,6 +790,7 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -906,6 +908,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_E1000E is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -929,6 +932,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
@@ -1182,7 +1186,6 @@ CONFIG_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1393,6 +1396,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
@@ -1419,6 +1423,11 @@ CONFIG_INOTIFY_USER=y
CONFIG_FUSE_FS=m
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=m
@@ -1467,8 +1476,13 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -1576,6 +1590,7 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_DETECT_HUNG_TASK is not set
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1610,6 +1625,7 @@ CONFIG_SCHED_DEBUG=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -1618,9 +1634,14 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
# CONFIG_IRQSOFF_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
@@ -1741,6 +1762,7 @@ CONFIG_CRYPTO_DEFLATE=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/ul2_defconfig b/arch/sh/configs/ul2_defconfig
index 34f5192a3241..bfb4d9806892 100644
--- a/arch/sh/configs/ul2_defconfig
+++ b/arch/sh/configs/ul2_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 19:30:27 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 13:17:05 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -69,7 +70,6 @@ CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
@@ -78,6 +78,7 @@ CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -97,6 +98,7 @@ CONFIG_COMPAT_BRK=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
# CONFIG_OPROFILE is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
@@ -105,6 +107,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -117,7 +121,6 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -167,6 +170,7 @@ CONFIG_ARCH_SHMOBILE=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -176,8 +180,6 @@ CONFIG_ARCH_SHMOBILE=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
CONFIG_CPU_SUBTYPE_SH7366=y
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -584,6 +586,7 @@ CONFIG_SCSI_WAIT_SCAN=m
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
# CONFIG_SCSI_OSD_INITIATOR is not set
@@ -936,6 +939,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -958,6 +962,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -1005,6 +1014,7 @@ CONFIG_CRAMFS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
@@ -1095,10 +1105,24 @@ CONFIG_FRAME_WARN=1024
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -1208,6 +1232,7 @@ CONFIG_CRYPTO_ARC4=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/configs/urquell_defconfig b/arch/sh/configs/urquell_defconfig
index d174b1a4d802..512664fed66c 100644
--- a/arch/sh/configs/urquell_defconfig
+++ b/arch/sh/configs/urquell_defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr 2 19:33:39 2009
+# Linux kernel version: 2.6.30-rc3
+# Mon Apr 27 14:02:55 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
@@ -76,6 +77,7 @@ CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
@@ -94,6 +96,7 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
# CONFIG_OPROFILE is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
@@ -102,6 +105,8 @@ CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -114,7 +119,6 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -162,6 +166,7 @@ CONFIG_CPU_SHX3=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -171,8 +176,6 @@ CONFIG_CPU_SUBTYPE_SH7786=y
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
# CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -900,15 +903,17 @@ CONFIG_USB_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
+# CONFIG_DRAGONRISE_FF is not set
CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
CONFIG_HID_LOGITECH=y
# CONFIG_LOGITECH_FF is not set
# CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -1046,6 +1051,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
@@ -1068,6 +1074,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -1117,6 +1128,7 @@ CONFIG_MINIX_FS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -1209,10 +1221,24 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
@@ -1322,6 +1348,7 @@ CONFIG_CRYPTO_DES=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig
index 666713ac5fcf..63e9dd30b41c 100644
--- a/arch/sh/drivers/dma/Kconfig
+++ b/arch/sh/drivers/dma/Kconfig
@@ -16,7 +16,8 @@ config SH_DMA_IRQ_MULTI
CPU_SUBTYPE_SH7750S || CPU_SUBTYPE_SH7750R || \
CPU_SUBTYPE_SH7751R || CPU_SUBTYPE_SH7091 || \
CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7764 || \
- CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785
+ CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785 || \
+ CPU_SUBTYPE_SH7760
config NR_ONCHIP_DMA_CHANNELS
int
diff --git a/arch/sh/drivers/pci/Kconfig b/arch/sh/drivers/pci/Kconfig
index 7e816ededed7..e8db585a6638 100644
--- a/arch/sh/drivers/pci/Kconfig
+++ b/arch/sh/drivers/pci/Kconfig
@@ -17,21 +17,3 @@ config SH_PCIDMA_NONCOHERENT
code will not have to flush the CPU's caches. If you have a PCI host
bridge integrated with your SH CPU, refer carefully to the chip specs
to see if you can say 'N' here. Otherwise, leave it as 'Y'.
-
-# This is also board-specific
-config PCI_AUTO
- bool
- depends on PCI
- default y
-
-config PCI_AUTO_UPDATE_RESOURCES
- bool
- depends on PCI_AUTO
- default y if !SH_DREAMCAST
- help
- Selecting this option will cause the PCI auto code to leave your
- BAR values alone. Otherwise they will be updated automatically. If
- for some reason, you have a board that simply refuses to work
- with its resources updated beyond what they are when the device
- is powered up, set this to N. Everyone else will want this as Y.
-
diff --git a/arch/sh/drivers/pci/Makefile b/arch/sh/drivers/pci/Makefile
index 847e90894d1b..d2ffc477549a 100644
--- a/arch/sh/drivers/pci/Makefile
+++ b/arch/sh/drivers/pci/Makefile
@@ -1,9 +1,7 @@
#
# Makefile for the PCI specific kernel interface routines under Linux.
#
-
obj-y += pci.o
-obj-$(CONFIG_PCI_AUTO) += pci-auto.o
obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci-sh7751.o ops-sh4.o
obj-$(CONFIG_CPU_SUBTYPE_SH7751R) += pci-sh7751.o ops-sh4.o
@@ -12,15 +10,17 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7780) += pci-sh7780.o ops-sh4.o
obj-$(CONFIG_CPU_SUBTYPE_SH7785) += pci-sh7780.o ops-sh4.o
obj-$(CONFIG_CPU_SH5) += pci-sh5.o ops-sh5.o
-obj-$(CONFIG_SH_DREAMCAST) += ops-dreamcast.o fixups-dreamcast.o
-obj-$(CONFIG_SH_SECUREEDGE5410) += ops-snapgear.o
-obj-$(CONFIG_SH_RTS7751R2D) += ops-rts7751r2d.o fixups-rts7751r2d.o
-obj-$(CONFIG_SH_SH03) += ops-sh03.o fixups-sh03.o
-obj-$(CONFIG_SH_HIGHLANDER) += ops-r7780rp.o fixups-r7780rp.o
-obj-$(CONFIG_SH_SDK7780) += ops-sdk7780.o fixups-sdk7780.o
-obj-$(CONFIG_SH_TITAN) += ops-titan.o
-obj-$(CONFIG_SH_LANDISK) += ops-landisk.o
-obj-$(CONFIG_SH_LBOX_RE2) += ops-lboxre2.o fixups-lboxre2.o
-obj-$(CONFIG_SH_7780_SOLUTION_ENGINE) += ops-se7780.o fixups-se7780.o
-obj-$(CONFIG_SH_CAYMAN) += ops-cayman.o
-obj-$(CONFIG_SH_SH7785LCR) += ops-sh7785lcr.o fixups-sh7785lcr.o
+obj-$(CONFIG_SH_DREAMCAST) += ops-dreamcast.o fixups-dreamcast.o \
+ pci-dreamcast.o
+obj-$(CONFIG_SH_SECUREEDGE5410) += fixups-snapgear.o
+obj-$(CONFIG_SH_7751_SOLUTION_ENGINE) += fixups-se7751.o
+obj-$(CONFIG_SH_RTS7751R2D) += fixups-rts7751r2d.o
+obj-$(CONFIG_SH_SH03) += fixups-sh03.o
+obj-$(CONFIG_SH_HIGHLANDER) += fixups-r7780rp.o
+obj-$(CONFIG_SH_SH7785LCR) += fixups-r7780rp.o
+obj-$(CONFIG_SH_SDK7780) += fixups-sdk7780.o
+obj-$(CONFIG_SH_7780_SOLUTION_ENGINE) += fixups-sdk7780.o
+obj-$(CONFIG_SH_TITAN) += fixups-titan.o
+obj-$(CONFIG_SH_LANDISK) += fixups-landisk.o
+obj-$(CONFIG_SH_LBOX_RE2) += fixups-rts7751r2d.o
+obj-$(CONFIG_SH_CAYMAN) += fixups-cayman.o
diff --git a/arch/sh/drivers/pci/ops-cayman.c b/arch/sh/drivers/pci/fixups-cayman.c
index 38ef76207af6..b68b61d22c6c 100644
--- a/arch/sh/drivers/pci/ops-cayman.c
+++ b/arch/sh/drivers/pci/fixups-cayman.c
@@ -75,15 +75,3 @@ int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
return result;
}
-
-struct pci_channel board_pci_channels[] = {
- { &sh5_pci_ops, NULL, NULL, 0, 0xff },
- { NULL, NULL, NULL, 0, 0 },
-};
-EXPORT_SYMBOL(board_pci_channels);
-
-int __init pcibios_init_platform(void)
-{
- return sh5pci_init(__pa(memory_start),
- __pa(memory_end) - __pa(memory_start));
-}
diff --git a/arch/sh/drivers/pci/fixups-dreamcast.c b/arch/sh/drivers/pci/fixups-dreamcast.c
index 2bf85cf091e1..ed7f489936f1 100644
--- a/arch/sh/drivers/pci/fixups-dreamcast.c
+++ b/arch/sh/drivers/pci/fixups-dreamcast.c
@@ -30,7 +30,7 @@
static void __init gapspci_fixup_resources(struct pci_dev *dev)
{
- struct pci_channel *p = board_pci_channels;
+ struct pci_channel *p = dev->sysdata;
printk(KERN_NOTICE "PCI: Fixing up device %s\n", pci_name(dev));
@@ -41,6 +41,13 @@ static void __init gapspci_fixup_resources(struct pci_dev *dev)
*/
dev->resource[1].start = p->io_resource->start + 0x100;
dev->resource[1].end = dev->resource[1].start + 0x200 - 1;
+
+ /*
+ * This is not a normal BAR, prevent any attempts to move
+ * the BAR, as this will result in a bus lock.
+ */
+ dev->resource[1].flags |= IORESOURCE_PCI_FIXED;
+
/*
* Redirect dma memory allocations to special memory window.
*/
diff --git a/arch/sh/drivers/pci/ops-landisk.c b/arch/sh/drivers/pci/fixups-landisk.c
index bff09ecf3419..bb1a6bb5149e 100644
--- a/arch/sh/drivers/pci/ops-landisk.c
+++ b/arch/sh/drivers/pci/fixups-landisk.c
@@ -15,39 +15,6 @@
#include <linux/pci.h>
#include "pci-sh4.h"
-static struct resource sh7751_io_resource = {
- .name = "SH7751 IO",
- .start = SH7751_PCI_IO_BASE,
- .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
- .flags = IORESOURCE_IO
-};
-
-static struct resource sh7751_mem_resource = {
- .name = "SH7751 mem",
- .start = SH7751_PCI_MEMORY_BASE,
- .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
- .flags = IORESOURCE_MEM
-};
-
-struct pci_channel board_pci_channels[] = {
- {&sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0x3ff},
- {NULL, NULL, NULL, 0, 0},
-};
-
-static struct sh4_pci_address_map sh7751_pci_map = {
- .window0 = {
- .base = SH7751_CS3_BASE_ADDR,
- .size = (64 << 20), /* 64MB */
- },
-
- .flags = SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
- return sh7751_pcic_init(&sh7751_pci_map);
-}
-
int pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
{
/*
diff --git a/arch/sh/drivers/pci/fixups-lboxre2.c b/arch/sh/drivers/pci/fixups-lboxre2.c
deleted file mode 100644
index 1c1d41255ec0..000000000000
--- a/arch/sh/drivers/pci/fixups-lboxre2.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * arch/sh/drivers/pci/fixups-lboxre2.c
- *
- * L-BOX RE2 PCI fixups
- *
- * Copyright (C) 2007 Nobuhiro Iwamatsu
- *
- * 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 "pci-sh4.h"
-
-#define PCIMCR_MRSET_OFF 0xBFFFFFFF
-#define PCIMCR_RFSH_OFF 0xFFFFFFFB
-
-int pci_fixup_pcic(void)
-{
- unsigned long bcr1, mcr;
-
- bcr1 = ctrl_inl(SH7751_BCR1);
- bcr1 |= 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */
- pci_write_reg(bcr1, SH4_PCIBCR1);
-
- /* Enable all interrupts, so we known what to fix */
- pci_write_reg(0x0000c3ff, SH4_PCIINTM);
- pci_write_reg(0x0000380f, SH4_PCIAINTM);
- pci_write_reg(0xfb900047, SH7751_PCICONF1);
- pci_write_reg(0xab000001, SH7751_PCICONF4);
-
- mcr = ctrl_inl(SH7751_MCR);
- mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
- pci_write_reg(mcr, SH4_PCIMCR);
-
- pci_write_reg(0x0c000000, SH7751_PCICONF5);
- pci_write_reg(0xd0000000, SH7751_PCICONF6);
- pci_write_reg(0x0c000000, SH4_PCILAR0);
- pci_write_reg(0x00000000, SH4_PCILAR1);
-
- return 0;
-}
diff --git a/arch/sh/drivers/pci/fixups-r7780rp.c b/arch/sh/drivers/pci/fixups-r7780rp.c
index 3e321df65d22..15ca65cb667e 100644
--- a/arch/sh/drivers/pci/fixups-r7780rp.c
+++ b/arch/sh/drivers/pci/fixups-r7780rp.c
@@ -11,35 +11,26 @@
* for more details.
*/
#include <linux/pci.h>
+#include <linux/io.h>
#include "pci-sh4.h"
-#include <asm/io.h>
-int pci_fixup_pcic(void)
-{
- pci_write_reg(0x000043ff, SH4_PCIINTM);
- pci_write_reg(0x0000380f, SH4_PCIAINTM);
-
- pci_write_reg(0xfbb00047, SH7780_PCICMD);
- pci_write_reg(0x00000000, SH7780_PCIIBAR);
-
- pci_write_reg(0x00011912, SH7780_PCISVID);
- pci_write_reg(0x08000000, SH7780_PCICSCR0);
- pci_write_reg(0x0000001b, SH7780_PCICSAR0);
- pci_write_reg(0xfd000000, SH7780_PCICSCR1);
- pci_write_reg(0x0000000f, SH7780_PCICSAR1);
-
- pci_write_reg(0xfd000000, SH7780_PCIMBR0);
- pci_write_reg(0x00fc0000, SH7780_PCIMBMR0);
+static char irq_tab[] __initdata = {
+ 65, 66, 67, 68,
+};
-#ifdef CONFIG_32BIT
- pci_write_reg(0xc0000000, SH7780_PCIMBR2);
- pci_write_reg(0x20000000 - SH7780_PCI_IO_SIZE, SH7780_PCIMBMR2);
-#endif
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+ return irq_tab[slot];
+}
- /* Set IOBR for windows containing area specified in pci.h */
- pci_write_reg((PCIBIOS_MIN_IO & ~(SH7780_PCI_IO_SIZE - 1)),
- SH7780_PCIIOBR);
- pci_write_reg(((SH7780_PCI_IO_SIZE-1) & (7<<18)), SH7780_PCIIOBMR);
+int pci_fixup_pcic(struct pci_channel *chan)
+{
+ pci_write_reg(chan, 0x000043ff, SH4_PCIINTM);
+ pci_write_reg(chan, 0x00000000, SH7780_PCIIBAR);
+ pci_write_reg(chan, 0x08000000, SH7780_PCICSCR0);
+ pci_write_reg(chan, 0x0000001b, SH7780_PCICSAR0);
+ pci_write_reg(chan, 0xfd000000, SH7780_PCICSCR1);
+ pci_write_reg(chan, 0x0000000f, SH7780_PCICSAR1);
return 0;
}
diff --git a/arch/sh/drivers/pci/fixups-rts7751r2d.c b/arch/sh/drivers/pci/fixups-rts7751r2d.c
index 904bce8768d3..052b354236dc 100644
--- a/arch/sh/drivers/pci/fixups-rts7751r2d.c
+++ b/arch/sh/drivers/pci/fixups-rts7751r2d.c
@@ -1,43 +1,67 @@
/*
* arch/sh/drivers/pci/fixups-rts7751r2d.c
*
- * RTS7751R2D PCI fixups
+ * RTS7751R2D / LBOXRE2 PCI fixups
*
* Copyright (C) 2003 Lineo uSolutions, Inc.
* Copyright (C) 2004 Paul Mundt
+ * Copyright (C) 2007 Nobuhiro Iwamatsu
*
* 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/pci.h>
+#include <mach/lboxre2.h>
+#include <mach/r2d.h>
#include "pci-sh4.h"
+#include <asm/machtypes.h>
#define PCIMCR_MRSET_OFF 0xBFFFFFFF
#define PCIMCR_RFSH_OFF 0xFFFFFFFB
-int pci_fixup_pcic(void)
+static u8 rts7751r2d_irq_tab[] __initdata = {
+ IRQ_PCI_INTA,
+ IRQ_PCI_INTB,
+ IRQ_PCI_INTC,
+ IRQ_PCI_INTD,
+};
+
+static char lboxre2_irq_tab[] __initdata = {
+ IRQ_ETH0, IRQ_ETH1, IRQ_INTA, IRQ_INTD,
+};
+
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+ if (mach_is_lboxre2())
+ return lboxre2_irq_tab[slot];
+ else
+ return rts7751r2d_irq_tab[slot];
+}
+
+int pci_fixup_pcic(struct pci_channel *chan)
{
unsigned long bcr1, mcr;
bcr1 = ctrl_inl(SH7751_BCR1);
bcr1 |= 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */
- pci_write_reg(bcr1, SH4_PCIBCR1);
+ pci_write_reg(chan, bcr1, SH4_PCIBCR1);
/* Enable all interrupts, so we known what to fix */
- pci_write_reg(0x0000c3ff, SH4_PCIINTM);
- pci_write_reg(0x0000380f, SH4_PCIAINTM);
+ pci_write_reg(chan, 0x0000c3ff, SH4_PCIINTM);
+ pci_write_reg(chan, 0x0000380f, SH4_PCIAINTM);
- pci_write_reg(0xfb900047, SH7751_PCICONF1);
- pci_write_reg(0xab000001, SH7751_PCICONF4);
+ pci_write_reg(chan, 0xfb900047, SH7751_PCICONF1);
+ pci_write_reg(chan, 0xab000001, SH7751_PCICONF4);
mcr = ctrl_inl(SH7751_MCR);
mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
- pci_write_reg(mcr, SH4_PCIMCR);
+ pci_write_reg(chan, mcr, SH4_PCIMCR);
- pci_write_reg(0x0c000000, SH7751_PCICONF5);
- pci_write_reg(0xd0000000, SH7751_PCICONF6);
- pci_write_reg(0x0c000000, SH4_PCILAR0);
- pci_write_reg(0x00000000, SH4_PCILAR1);
+ pci_write_reg(chan, 0x0c000000, SH7751_PCICONF5);
+ pci_write_reg(chan, 0xd0000000, SH7751_PCICONF6);
+ pci_write_reg(chan, 0x0c000000, SH4_PCILAR0);
+ pci_write_reg(chan, 0x00000000, SH4_PCILAR1);
return 0;
}
diff --git a/arch/sh/drivers/pci/fixups-sdk7780.c b/arch/sh/drivers/pci/fixups-sdk7780.c
index 2f8863099dd1..250b0edd7365 100644
--- a/arch/sh/drivers/pci/fixups-sdk7780.c
+++ b/arch/sh/drivers/pci/fixups-sdk7780.c
@@ -5,55 +5,48 @@
*
* Copyright (C) 2003 Lineo uSolutions, Inc.
* Copyright (C) 2004 - 2006 Paul Mundt
+ * Copyright (C) 2006 Nobuhiro Iwamatsu
*
* 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/pci.h>
+#include <linux/io.h>
#include "pci-sh4.h"
-#include <asm/io.h>
-int pci_fixup_pcic(void)
+/* IDSEL [16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31] */
+static char sdk7780_irq_tab[4][16] __initdata = {
+ /* INTA */
+ { 65, 68, 67, 68, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ /* INTB */
+ { 66, 65, -1, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ /* INTC */
+ { 67, 66, -1, 66, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ /* INTD */
+ { 68, 67, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+};
+
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+ return sdk7780_irq_tab[pin-1][slot];
+}
+int pci_fixup_pcic(struct pci_channel *chan)
{
- ctrl_outl(0x00000001, SH7780_PCI_VCR2);
-
/* Enable all interrupts, so we know what to fix */
- pci_write_reg(0x0000C3FF, SH7780_PCIIMR);
- pci_write_reg(0x0000380F, SH7780_PCIAINTM);
+ pci_write_reg(chan, 0x0000C3FF, SH7780_PCIIMR);
/* Set up standard PCI config registers */
- pci_write_reg(0xFB00, SH7780_PCISTATUS);
- pci_write_reg(0x0047, SH7780_PCICMD);
- pci_write_reg(0x00, SH7780_PCIPIF);
- pci_write_reg(0x00, SH7780_PCISUB);
- pci_write_reg(0x06, SH7780_PCIBCC);
- pci_write_reg(0x1912, SH7780_PCISVID);
- pci_write_reg(0x0001, SH7780_PCISID);
-
- pci_write_reg(0x08000000, SH7780_PCIMBAR0); /* PCI */
- pci_write_reg(0x08000000, SH7780_PCILAR0); /* SHwy */
- pci_write_reg(0x07F00001, SH7780_PCILSR); /* size 128M w/ MBAR */
-
- pci_write_reg(0x00000000, SH7780_PCIMBAR1);
- pci_write_reg(0x00000000, SH7780_PCILAR1);
- pci_write_reg(0x00000000, SH7780_PCILSR1);
-
- pci_write_reg(0xAB000801, SH7780_PCIIBAR);
-
- /*
- * Set the MBR so PCI address is one-to-one with window,
- * meaning all calls go straight through... use ifdef to
- * catch erroneous assumption.
- */
- pci_write_reg(0xFD000000 , SH7780_PCIMBR0);
- pci_write_reg(0x00FC0000 , SH7780_PCIMBMR0); /* 16M */
+ pci_write_reg(chan, 0x08000000, SH7780_PCIMBAR0); /* PCI */
+ pci_write_reg(chan, 0x08000000, SH4_PCILAR0); /* SHwy */
+ pci_write_reg(chan, 0x07F00001, SH4_PCILSR0); /* size 128M w/ MBAR */
- /* Set IOBR for window containing area specified in pci.h */
- pci_write_reg(PCIBIOS_MIN_IO & ~(SH7780_PCI_IO_SIZE-1), SH7780_PCIIOBR);
- pci_write_reg((SH7780_PCI_IO_SIZE-1) & (7 << 18), SH7780_PCIIOBMR);
+ pci_write_reg(chan, 0x00000000, SH7780_PCIMBAR1);
+ pci_write_reg(chan, 0x00000000, SH4_PCILAR1);
+ pci_write_reg(chan, 0x00000000, SH4_PCILSR1);
- pci_write_reg(0xA5000C01, SH7780_PCICR);
+ pci_write_reg(chan, 0xAB000801, SH7780_PCIIBAR);
+ pci_write_reg(chan, 0xA5000C01, SH4_PCICR);
return 0;
}
diff --git a/arch/sh/drivers/pci/fixups-se7751.c b/arch/sh/drivers/pci/fixups-se7751.c
new file mode 100644
index 000000000000..475fa9f0fe2c
--- /dev/null
+++ b/arch/sh/drivers/pci/fixups-se7751.c
@@ -0,0 +1,111 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include "pci-sh4.h"
+
+int __init pcibios_map_platform_irq(u8 slot, u8 pin)
+{
+ switch (slot) {
+ case 0: return 13;
+ case 1: return 13; /* AMD Ethernet controller */
+ case 2: return -1;
+ case 3: return -1;
+ case 4: return -1;
+ default:
+ printk("PCI: Bad IRQ mapping request for slot %d\n", slot);
+ return -1;
+ }
+}
+
+#define PCIMCR_MRSET_OFF 0xBFFFFFFF
+#define PCIMCR_RFSH_OFF 0xFFFFFFFB
+
+/*
+ * Only long word accesses of the PCIC's internal local registers and the
+ * configuration registers from the CPU is supported.
+ */
+#define PCIC_WRITE(x,v) writel((v), PCI_REG(x))
+#define PCIC_READ(x) readl(PCI_REG(x))
+
+/*
+ * Description: This function sets up and initializes the pcic, sets
+ * up the BARS, maps the DRAM into the address space etc, etc.
+ */
+int pci_fixup_pcic(struct pci_channel *chan)
+{
+ unsigned long bcr1, wcr1, wcr2, wcr3, mcr;
+ unsigned short bcr2;
+
+ /*
+ * Initialize the slave bus controller on the pcic. The values used
+ * here should not be hardcoded, but they should be taken from the bsc
+ * on the processor, to make this function as generic as possible.
+ * (i.e. Another sbc may usr different SDRAM timing settings -- in order
+ * for the pcic to work, its settings need to be exactly the same.)
+ */
+ bcr1 = (*(volatile unsigned long*)(SH7751_BCR1));
+ bcr2 = (*(volatile unsigned short*)(SH7751_BCR2));
+ wcr1 = (*(volatile unsigned long*)(SH7751_WCR1));
+ wcr2 = (*(volatile unsigned long*)(SH7751_WCR2));
+ wcr3 = (*(volatile unsigned long*)(SH7751_WCR3));
+ mcr = (*(volatile unsigned long*)(SH7751_MCR));
+
+ bcr1 = bcr1 | 0x00080000; /* Enable Bit 19, BREQEN */
+ (*(volatile unsigned long*)(SH7751_BCR1)) = bcr1;
+
+ bcr1 = bcr1 | 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */
+ PCIC_WRITE(SH7751_PCIBCR1, bcr1); /* PCIC BCR1 */
+ PCIC_WRITE(SH7751_PCIBCR2, bcr2); /* PCIC BCR2 */
+ PCIC_WRITE(SH7751_PCIWCR1, wcr1); /* PCIC WCR1 */
+ PCIC_WRITE(SH7751_PCIWCR2, wcr2); /* PCIC WCR2 */
+ PCIC_WRITE(SH7751_PCIWCR3, wcr3); /* PCIC WCR3 */
+ mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
+ PCIC_WRITE(SH7751_PCIMCR, mcr); /* PCIC MCR */
+
+
+ /* Enable all interrupts, so we know what to fix */
+ PCIC_WRITE(SH7751_PCIINTM, 0x0000c3ff);
+ PCIC_WRITE(SH7751_PCIAINTM, 0x0000380f);
+
+ /* Set up standard PCI config registers */
+ PCIC_WRITE(SH7751_PCICONF1, 0xF39000C7); /* Bus Master, Mem & I/O access */
+ PCIC_WRITE(SH7751_PCICONF2, 0x00000000); /* PCI Class code & Revision ID */
+ PCIC_WRITE(SH7751_PCICONF4, 0xab000001); /* PCI I/O address (local regs) */
+ PCIC_WRITE(SH7751_PCICONF5, 0x0c000000); /* PCI MEM address (local RAM) */
+ PCIC_WRITE(SH7751_PCICONF6, 0xd0000000); /* PCI MEM address (unused) */
+ PCIC_WRITE(SH7751_PCICONF11, 0x35051054); /* PCI Subsystem ID & Vendor ID */
+ PCIC_WRITE(SH7751_PCILSR0, 0x03f00000); /* MEM (full 64M exposed) */
+ PCIC_WRITE(SH7751_PCILSR1, 0x00000000); /* MEM (unused) */
+ PCIC_WRITE(SH7751_PCILAR0, 0x0c000000); /* MEM (direct map from PCI) */
+ PCIC_WRITE(SH7751_PCILAR1, 0x00000000); /* MEM (unused) */
+
+ /* Now turn it on... */
+ PCIC_WRITE(SH7751_PCICR, 0xa5000001);
+
+ /*
+ * Set PCIMBR and PCIIOBR here, assuming a single window
+ * (16M MEM, 256K IO) is enough. If a larger space is
+ * needed, the readx/writex and inx/outx functions will
+ * have to do more (e.g. setting registers for each call).
+ */
+
+ /*
+ * Set the MBR so PCI address is one-to-one with window,
+ * meaning all calls go straight through... use BUG_ON to
+ * catch erroneous assumption.
+ */
+ BUG_ON(chan->mem_resource->start != SH7751_PCI_MEMORY_BASE);
+
+ PCIC_WRITE(SH7751_PCIMBR, chan->mem_resource->start);
+
+ /* Set IOBR for window containing area specified in pci.h */
+ PCIC_WRITE(SH7751_PCIIOBR, (chan->io_resource->start & SH7751_PCIIOBR_MASK));
+
+ /* All done, may as well say so... */
+ printk("SH7751 PCI: Finished initialization of the PCI controller\n");
+
+ return 1;
+}
diff --git a/arch/sh/drivers/pci/fixups-se7780.c b/arch/sh/drivers/pci/fixups-se7780.c
deleted file mode 100644
index 880cea1c0d89..000000000000
--- a/arch/sh/drivers/pci/fixups-se7780.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * arch/sh/drivers/pci/fixups-se7780.c
- *
- * HITACHI UL Solution Engine 7780 PCI fixups
- *
- * Copyright (C) 2003 Lineo uSolutions, Inc.
- * Copyright (C) 2004 - 2006 Paul Mundt
- * Copyright (C) 2006 Nobuhiro Iwamatsu
- *
- * 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/pci.h>
-#include "pci-sh4.h"
-#include <asm/io.h>
-
-int pci_fixup_pcic(void)
-{
- ctrl_outl(0x00000001, SH7780_PCI_VCR2);
-
- /* Enable all interrupts, so we know what to fix */
- pci_write_reg(0x0000C3FF, SH7780_PCIIMR);
- pci_write_reg(0x0000380F, SH7780_PCIAINTM);
-
- /* Set up standard PCI config registers */
- ctrl_outw(0xFB00, PCI_REG(SH7780_PCISTATUS));
- ctrl_outw(0x0047, PCI_REG(SH7780_PCICMD));
- ctrl_outb( 0x00, PCI_REG(SH7780_PCIPIF));
- ctrl_outb( 0x00, PCI_REG(SH7780_PCISUB));
- ctrl_outb( 0x06, PCI_REG(SH7780_PCIBCC));
- ctrl_outw(0x1912, PCI_REG(SH7780_PCISVID));
- ctrl_outw(0x0001, PCI_REG(SH7780_PCISID));
-
- pci_write_reg(0x08000000, SH7780_PCIMBAR0); /* PCI */
- pci_write_reg(0x08000000, SH7780_PCILAR0); /* SHwy */
- pci_write_reg(0x07F00001, SH7780_PCILSR); /* size 128M w/ MBAR */
-
- pci_write_reg(0x00000000, SH7780_PCIMBAR1);
- pci_write_reg(0x00000000, SH7780_PCILAR1);
- pci_write_reg(0x00000000, SH7780_PCILSR1);
-
- pci_write_reg(0xAB000801, SH7780_PCIIBAR);
-
- /*
- * Set the MBR so PCI address is one-to-one with window,
- * meaning all calls go straight through... use ifdef to
- * catch erroneous assumption.
- */
- pci_write_reg(0xFD000000 , SH7780_PCIMBR0);
- pci_write_reg(0x00FC0000 , SH7780_PCIMBMR0); /* 16M */
-
- /* Set IOBR for window containing area specified in pci.h */
- pci_write_reg(PCIBIOS_MIN_IO & ~(SH7780_PCI_IO_SIZE-1), SH7780_PCIIOBR);
- pci_write_reg((SH7780_PCI_IO_SIZE-1) & (7 << 18), SH7780_PCIIOBMR);
-
- pci_write_reg(0xA5000C01, SH7780_PCICR);
-
- return 0;
-}
diff --git a/arch/sh/drivers/pci/fixups-sh7785lcr.c b/arch/sh/drivers/pci/fixups-sh7785lcr.c
deleted file mode 100644
index 4949e601387a..000000000000
--- a/arch/sh/drivers/pci/fixups-sh7785lcr.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * arch/sh/drivers/pci/fixups-sh7785lcr.c
- *
- * R0P7785LC0011RL PCI fixups
- * Copyright (C) 2008 Yoshihiro Shimoda
- *
- * Based on arch/sh/drivers/pci/fixups-r7780rp.c
- * Copyright (C) 2003 Lineo uSolutions, Inc.
- * Copyright (C) 2004 - 2006 Paul Mundt
- *
- * 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/pci.h>
-#include "pci-sh4.h"
-
-int pci_fixup_pcic(void)
-{
- pci_write_reg(0x000043ff, SH4_PCIINTM);
- pci_write_reg(0x0000380f, SH4_PCIAINTM);
-
- pci_write_reg(0xfbb00047, SH7780_PCICMD);
- pci_write_reg(0x00000000, SH7780_PCIIBAR);
-
- pci_write_reg(0x00011912, SH7780_PCISVID);
- pci_write_reg(0x08000000, SH7780_PCICSCR0);
- pci_write_reg(0x0000001b, SH7780_PCICSAR0);
- pci_write_reg(0xfd000000, SH7780_PCICSCR1);
- pci_write_reg(0x0000000f, SH7780_PCICSAR1);
-
- pci_write_reg(0xfd000000, SH7780_PCIMBR0);
- pci_write_reg(0x00fc0000, SH7780_PCIMBMR0);
-
-#ifdef CONFIG_32BIT
- pci_write_reg(0xc0000000, SH7780_PCIMBR2);
- pci_write_reg(0x20000000 - SH7780_PCI_IO_SIZE, SH7780_PCIMBMR2);
-#endif
-
- /* Set IOBR for windows containing area specified in pci.h */
- pci_write_reg((PCIBIOS_MIN_IO & ~(SH7780_PCI_IO_SIZE - 1)),
- SH7780_PCIIOBR);
- pci_write_reg(((SH7780_PCI_IO_SIZE - 1) & (7 << 18)), SH7780_PCIIOBMR);
-
- return 0;
-}
diff --git a/arch/sh/drivers/pci/fixups-snapgear.c b/arch/sh/drivers/pci/fixups-snapgear.c
new file mode 100644
index 000000000000..5a39ecc1adb8
--- /dev/null
+++ b/arch/sh/drivers/pci/fixups-snapgear.c
@@ -0,0 +1,38 @@
+/*
+ * arch/sh/drivers/pci/ops-snapgear.c
+ *
+ * Author: David McCullough <davidm@snapgear.com>
+ *
+ * Ported to new API by Paul Mundt <lethal@linux-sh.org>
+ *
+ * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * PCI initialization for the SnapGear boards
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include "pci-sh4.h"
+
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+ int irq = -1;
+
+ switch (slot) {
+ case 8: /* the PCI bridge */ break;
+ case 11: irq = 8; break; /* USB */
+ case 12: irq = 11; break; /* PCMCIA */
+ case 13: irq = 5; break; /* eth0 */
+ case 14: irq = 8; break; /* eth1 */
+ case 15: irq = 11; break; /* safenet (unused) */
+ }
+
+ printk("PCI: Mapping SnapGear IRQ for slot %d, pin %c to irq %d\n",
+ slot, pin - 1 + 'A', irq);
+
+ return irq;
+}
diff --git a/arch/sh/drivers/pci/ops-titan.c b/arch/sh/drivers/pci/fixups-titan.c
index a8f7801a34af..3a79fa8254a6 100644
--- a/arch/sh/drivers/pci/ops-titan.c
+++ b/arch/sh/drivers/pci/fixups-titan.c
@@ -36,42 +36,3 @@ int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
return irq;
}
-
-static struct resource sh7751_io_resource = {
- .name = "SH7751_IO",
- .start = SH7751_PCI_IO_BASE,
- .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
- .flags = IORESOURCE_IO
-};
-
-static struct resource sh7751_mem_resource = {
- .name = "SH7751_mem",
- .start = SH7751_PCI_MEMORY_BASE,
- .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
- .flags = IORESOURCE_MEM
-};
-
-struct pci_channel board_pci_channels[] = {
- { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
- { NULL, NULL, NULL, 0, 0 },
-};
-EXPORT_SYMBOL(board_pci_channels);
-
-static struct sh4_pci_address_map sh7751_pci_map = {
- .window0 = {
- .base = SH7751_CS2_BASE_ADDR,
- .size = SH7751_MEM_REGION_SIZE*2, /* cs2 and cs3 */
- },
-
- .window1 = {
- .base = SH7751_CS2_BASE_ADDR,
- .size = SH7751_MEM_REGION_SIZE*2,
- },
-
- .flags = SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
- return sh7751_pcic_init(&sh7751_pci_map);
-}
diff --git a/arch/sh/drivers/pci/ops-dreamcast.c b/arch/sh/drivers/pci/ops-dreamcast.c
index f5d2a2aa6f3f..e83d0d3aabe2 100644
--- a/arch/sh/drivers/pci/ops-dreamcast.c
+++ b/arch/sh/drivers/pci/ops-dreamcast.c
@@ -1,15 +1,9 @@
/*
- * arch/sh/drivers/pci/ops-dreamcast.c
- *
* PCI operations for the Sega Dreamcast
*
* Copyright (C) 2001, 2002 M. R. Brown
* Copyright (C) 2002, 2003 Paul Mundt
*
- * This file originally bore the message (with enclosed-$):
- * Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp
- * Dreamcast PCI: Supports SEGA Broadband Adaptor only.
- *
* 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.
@@ -23,34 +17,10 @@
#include <linux/irq.h>
#include <linux/pci.h>
#include <linux/module.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
+#include <linux/io.h>
+#include <linux/irq.h>
#include <mach/pci.h>
-static struct resource gapspci_io_resource = {
- .name = "GAPSPCI IO",
- .start = GAPSPCI_BBA_CONFIG,
- .end = GAPSPCI_BBA_CONFIG + GAPSPCI_BBA_CONFIG_SIZE - 1,
- .flags = IORESOURCE_IO,
-};
-
-static struct resource gapspci_mem_resource = {
- .name = "GAPSPCI mem",
- .start = GAPSPCI_DMA_BASE,
- .end = GAPSPCI_DMA_BASE + GAPSPCI_DMA_SIZE - 1,
- .flags = IORESOURCE_MEM,
-};
-
-static struct pci_ops gapspci_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
- { &gapspci_pci_ops, &gapspci_io_resource,
- &gapspci_mem_resource, 0, 1 },
- { 0, }
-};
-EXPORT_SYMBOL(board_pci_channels);
-
/*
* The !gapspci_config_access case really shouldn't happen, ever, unless
* someone implicitly messes around with the last devfn value.. otherwise we
@@ -85,10 +55,10 @@ static int gapspci_read(struct pci_bus *bus, unsigned int devfn, int where, int
return PCIBIOS_DEVICE_NOT_FOUND;
switch (size) {
- case 1: *val = inb(GAPSPCI_BBA_CONFIG+where); break;
- case 2: *val = inw(GAPSPCI_BBA_CONFIG+where); break;
- case 4: *val = inl(GAPSPCI_BBA_CONFIG+where); break;
- }
+ case 1: *val = inb(GAPSPCI_BBA_CONFIG+where); break;
+ case 2: *val = inw(GAPSPCI_BBA_CONFIG+where); break;
+ case 4: *val = inl(GAPSPCI_BBA_CONFIG+where); break;
+ }
return PCIBIOS_SUCCESSFUL;
}
@@ -99,72 +69,15 @@ static int gapspci_write(struct pci_bus *bus, unsigned int devfn, int where, int
return PCIBIOS_DEVICE_NOT_FOUND;
switch (size) {
- case 1: outb(( u8)val, GAPSPCI_BBA_CONFIG+where); break;
- case 2: outw((u16)val, GAPSPCI_BBA_CONFIG+where); break;
- case 4: outl((u32)val, GAPSPCI_BBA_CONFIG+where); break;
+ case 1: outb(( u8)val, GAPSPCI_BBA_CONFIG+where); break;
+ case 2: outw((u16)val, GAPSPCI_BBA_CONFIG+where); break;
+ case 4: outl((u32)val, GAPSPCI_BBA_CONFIG+where); break;
}
return PCIBIOS_SUCCESSFUL;
}
-static struct pci_ops gapspci_pci_ops = {
+struct pci_ops gapspci_pci_ops = {
.read = gapspci_read,
.write = gapspci_write,
};
-
-/*
- * gapspci init
- */
-
-int __init gapspci_init(void)
-{
- char idbuf[16];
- int i;
-
- /*
- * FIXME: All of this wants documenting to some degree,
- * even some basic register definitions would be nice.
- *
- * I haven't seen anything this ugly since.. maple.
- */
-
- for (i=0; i<16; i++)
- idbuf[i] = inb(GAPSPCI_REGS+i);
-
- if (strncmp(idbuf, "GAPSPCI_BRIDGE_2", 16))
- return -ENODEV;
-
- outl(0x5a14a501, GAPSPCI_REGS+0x18);
-
- for (i=0; i<1000000; i++)
- ;
-
- if (inl(GAPSPCI_REGS+0x18) != 1)
- return -EINVAL;
-
- outl(0x01000000, GAPSPCI_REGS+0x20);
- outl(0x01000000, GAPSPCI_REGS+0x24);
-
- outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28);
- outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c);
-
- outl(1, GAPSPCI_REGS+0x14);
- outl(1, GAPSPCI_REGS+0x34);
-
- /* Setting Broadband Adapter */
- outw(0xf900, GAPSPCI_BBA_CONFIG+0x06);
- outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30);
- outb(0x00, GAPSPCI_BBA_CONFIG+0x3c);
- outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d);
- outw(0x0006, GAPSPCI_BBA_CONFIG+0x04);
- outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10);
- outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14);
-
- return 0;
-}
-
-/* Haven't done anything here as yet */
-char * __devinit pcibios_setup(char *str)
-{
- return str;
-}
diff --git a/arch/sh/drivers/pci/ops-lboxre2.c b/arch/sh/drivers/pci/ops-lboxre2.c
deleted file mode 100644
index 86c0b6fb7375..000000000000
--- a/arch/sh/drivers/pci/ops-lboxre2.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * linux/arch/sh/drivers/pci/ops-lboxre2.c
- *
- * Copyright (C) 2007 Nobuhiro Iwamatsu
- *
- * PCI initialization for the NTT COMWARE L-BOX RE2
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/io.h>
-#include <mach/lboxre2.h>
-#include "pci-sh4.h"
-
-static char lboxre2_irq_tab[] __initdata = {
- IRQ_ETH0, IRQ_ETH1, IRQ_INTA, IRQ_INTD,
-};
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
- return lboxre2_irq_tab[slot];
-}
-
-static struct resource sh7751_io_resource = {
- .name = "SH7751_IO",
- .start = SH7751_PCI_IO_BASE ,
- .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
- .flags = IORESOURCE_IO
-};
-
-static struct resource sh7751_mem_resource = {
- .name = "SH7751_mem",
- .start = SH7751_PCI_MEMORY_BASE,
- .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
- .flags = IORESOURCE_MEM
-};
-
-extern struct pci_ops sh7751_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
- { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
- { NULL, NULL, NULL, 0, 0 },
-};
-
-EXPORT_SYMBOL(board_pci_channels);
-
-static struct sh4_pci_address_map sh7751_pci_map = {
- .window0 = {
- .base = SH7751_CS3_BASE_ADDR,
- .size = 0x04000000,
- },
- .window1 = {
- .base = 0x00000000, /* Unused */
- .size = 0x00000000, /* Unused */
- },
- .flags = SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
- return sh7751_pcic_init(&sh7751_pci_map);
-}
diff --git a/arch/sh/drivers/pci/ops-r7780rp.c b/arch/sh/drivers/pci/ops-r7780rp.c
deleted file mode 100644
index 8555238e63eb..000000000000
--- a/arch/sh/drivers/pci/ops-r7780rp.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Author: Ian DaSilva (idasilva@mvista.com)
- *
- * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * PCI initialization for the Renesas SH7780 Highlander R7780RP-1 board
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <mach/highlander.h>
-#include <asm/io.h>
-#include "pci-sh4.h"
-
-static char irq_tab[] __initdata = {
- 65, 66, 67, 68,
-};
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
- return irq_tab[slot];
-}
-
-static struct resource sh7780_io_resource = {
- .name = "SH7780_IO",
- .start = SH7780_PCI_IO_BASE,
- .end = SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1,
- .flags = IORESOURCE_IO
-};
-
-static struct resource sh7780_mem_resource = {
- .name = "SH7780_mem",
- .start = SH7780_PCI_MEMORY_BASE,
- .end = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
- .flags = IORESOURCE_MEM
-};
-
-extern struct pci_ops sh7780_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
- { &sh4_pci_ops, &sh7780_io_resource, &sh7780_mem_resource, 0, 0xff },
- { NULL, NULL, NULL, 0, 0 },
-};
-EXPORT_SYMBOL(board_pci_channels);
-
-static struct sh4_pci_address_map sh7780_pci_map = {
- .window0 = {
- .base = SH7780_CS2_BASE_ADDR,
- .size = 0x04000000,
- },
-
- .window1 = {
- .base = SH7780_CS3_BASE_ADDR,
- .size = 0x04000000,
- },
-
- .flags = SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
- return sh7780_pcic_init(&sh7780_pci_map);
-}
diff --git a/arch/sh/drivers/pci/ops-rts7751r2d.c b/arch/sh/drivers/pci/ops-rts7751r2d.c
deleted file mode 100644
index d6ca74b25d5f..000000000000
--- a/arch/sh/drivers/pci/ops-rts7751r2d.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * linux/arch/sh/drivers/pci/ops-rts7751r2d.c
- *
- * Author: Ian DaSilva (idasilva@mvista.com)
- *
- * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * PCI initialization for the Renesas SH7751R RTS7751R2D board
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/io.h>
-#include <mach/r2d.h>
-#include "pci-sh4.h"
-
-static u8 rts7751r2d_irq_tab[] __initdata = {
- IRQ_PCI_INTA,
- IRQ_PCI_INTB,
- IRQ_PCI_INTC,
- IRQ_PCI_INTD,
-};
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
- return rts7751r2d_irq_tab[slot];
-}
-
-static struct resource sh7751_io_resource = {
- .name = "SH7751_IO",
- .start = 0x4000,
- .end = SH7751_PCI_IO_SIZE - 1,
- .flags = IORESOURCE_IO
-};
-
-static struct resource sh7751_mem_resource = {
- .name = "SH7751_mem",
- .start = SH7751_PCI_MEMORY_BASE,
- .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
- .flags = IORESOURCE_MEM
-};
-
-extern struct pci_ops sh7751_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
- { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
- { NULL, NULL, NULL, 0, 0 },
-};
-EXPORT_SYMBOL(board_pci_channels);
-
-static struct sh4_pci_address_map sh7751_pci_map = {
- .window0 = {
- .base = SH7751_CS3_BASE_ADDR,
- .size = 0x04000000,
- },
-
- .window1 = {
- .base = 0x00000000, /* Unused */
- .size = 0x00000000, /* Unused */
- },
-
- .flags = SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
- __set_io_port_base(SH7751_PCI_IO_BASE);
- return sh7751_pcic_init(&sh7751_pci_map);
-}
-
diff --git a/arch/sh/drivers/pci/ops-sdk7780.c b/arch/sh/drivers/pci/ops-sdk7780.c
deleted file mode 100644
index 4dcc64184b23..000000000000
--- a/arch/sh/drivers/pci/ops-sdk7780.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * linux/arch/sh/drivers/pci/ops-sdk7780.c
- *
- * Copyright (C) 2006 Nobuhiro Iwamatsu
- *
- * PCI initialization for the SDK7780SE03
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <mach/sdk7780.h>
-#include <asm/io.h>
-#include "pci-sh4.h"
-
-/* IDSEL [16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31] */
-static char sdk7780_irq_tab[4][16] __initdata = {
- /* INTA */
- { 65, 68, 67, 68, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- /* INTB */
- { 66, 65, -1, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- /* INTC */
- { 67, 66, -1, 66, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- /* INTD */
- { 68, 67, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
-};
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
- return sdk7780_irq_tab[pin-1][slot];
-}
-
-static struct resource sdk7780_io_resource = {
- .name = "SH7780_IO",
- .start = SH7780_PCI_IO_BASE,
- .end = SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1,
- .flags = IORESOURCE_IO
-};
-
-static struct resource sdk7780_mem_resource = {
- .name = "SH7780_mem",
- .start = SH7780_PCI_MEMORY_BASE,
- .end = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
- .flags = IORESOURCE_MEM
-};
-
-struct pci_channel board_pci_channels[] = {
- { &sh4_pci_ops, &sdk7780_io_resource, &sdk7780_mem_resource, 0, 0xff },
- { NULL, NULL, NULL, 0, 0 },
-};
-EXPORT_SYMBOL(board_pci_channels);
-
-static struct sh4_pci_address_map sdk7780_pci_map = {
- .window0 = {
- .base = SH7780_CS2_BASE_ADDR,
- .size = 0x04000000,
- },
- .window1 = {
- .base = SH7780_CS3_BASE_ADDR,
- .size = 0x04000000,
- },
- .flags = SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
- printk(KERN_INFO "SH7780 PCI: Finished initializing PCI controller\n");
- return sh7780_pcic_init(&sdk7780_pci_map);
-}
diff --git a/arch/sh/drivers/pci/ops-se7780.c b/arch/sh/drivers/pci/ops-se7780.c
deleted file mode 100644
index 3145c62484d6..000000000000
--- a/arch/sh/drivers/pci/ops-se7780.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * linux/arch/sh/drivers/pci/ops-se7780.c
- *
- * Copyright (C) 2006 Nobuhiro Iwamatsu
- *
- * PCI initialization for the Hitachi UL Solution Engine 7780SE03
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <mach-se/mach/se7780.h>
-#include <asm/io.h>
-#include "pci-sh4.h"
-
-/*
- * IDSEL = AD16 PCI slot
- * IDSEL = AD17 PCI slot
- * IDSEL = AD18 Serial ATA Controller (Silicon Image SiL3512A)
- * IDSEL = AD19 USB Host Controller (NEC uPD7210100A)
- */
-
-/* IDSEL [16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31] */
-static char se7780_irq_tab[4][16] __initdata = {
- /* INTA */
- { 65, 68, 67, 68, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- /* INTB */
- { 66, 65, -1, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- /* INTC */
- { 67, 66, -1, 66, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- /* INTD */
- { 68, 67, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
-};
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
- return se7780_irq_tab[pin-1][slot];
-}
-
-static struct resource se7780_io_resource = {
- .name = "SH7780_IO",
- .start = SH7780_PCI_IO_BASE,
- .end = SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1,
- .flags = IORESOURCE_IO
-};
-
-static struct resource se7780_mem_resource = {
- .name = "SH7780_mem",
- .start = SH7780_PCI_MEMORY_BASE,
- .end = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
- .flags = IORESOURCE_MEM
-};
-
-extern struct pci_ops se7780_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
- { &sh4_pci_ops, &se7780_io_resource, &se7780_mem_resource, 0, 0xff },
- { NULL, NULL, NULL, 0, 0 },
-};
-EXPORT_SYMBOL(board_pci_channels);
-
-static struct sh4_pci_address_map se7780_pci_map = {
- .window0 = {
- .base = SH7780_CS2_BASE_ADDR,
- .size = 0x04000000,
- },
- .flags = SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
- printk("SH7780 PCI: Finished initialization of the PCI controller\n");
-
- /*
- * FPGA PCISEL register initialize
- *
- * CPU || SLOT1 | SLOT2 | S-ATA | USB
- * -------------------------------------
- * INTA || INTA | INTD | -- | INTB
- * -------------------------------------
- * INTB || INTB | INTA | -- | INTC
- * -------------------------------------
- * INTC || INTC | INTB | INTA | --
- * -------------------------------------
- * INTD || INTD | INTC | -- | INTA
- * -------------------------------------
- */
- ctrl_outw(0x0013, FPGA_PCI_INTSEL1);
- ctrl_outw(0xE402, FPGA_PCI_INTSEL2);
-
- return sh7780_pcic_init(&se7780_pci_map);
-}
diff --git a/arch/sh/drivers/pci/ops-sh03.c b/arch/sh/drivers/pci/ops-sh03.c
deleted file mode 100644
index e1703ff5a4d2..000000000000
--- a/arch/sh/drivers/pci/ops-sh03.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * linux/arch/sh/drivers/pci/ops-sh03.c
- *
- * PCI initialization for the Interface CTP/PCI-SH03 board
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-#include "pci-sh7751.h"
-
-/*
- * Description: This function sets up and initializes the pcic, sets
- * up the BARS, maps the DRAM into the address space etc, etc.
- */
-int __init pcibios_init_platform(void)
-{
- __set_io_port_base(SH7751_PCI_IO_BASE);
- return 1;
-}
-
-static struct resource sh7751_io_resource = {
- .name = "SH03 IO",
- .start = SH7751_PCI_IO_BASE,
- .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
- .flags = IORESOURCE_IO
-};
-
-static struct resource sh7751_mem_resource = {
- .name = "SH03 mem",
- .start = SH7751_PCI_MEMORY_BASE,
- .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
- .flags = IORESOURCE_MEM
-};
-
-extern struct pci_ops sh4_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
- { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
- { NULL, NULL, NULL, 0, 0 },
-};
-
diff --git a/arch/sh/drivers/pci/ops-sh4.c b/arch/sh/drivers/pci/ops-sh4.c
index 710a3b0306e5..78bebebdc99c 100644
--- a/arch/sh/drivers/pci/ops-sh4.c
+++ b/arch/sh/drivers/pci/ops-sh4.c
@@ -1,22 +1,22 @@
/*
* Generic SH-4 / SH-4A PCIC operations (SH7751, SH7780).
*
- * Copyright (C) 2002 - 2006 Paul Mundt
+ * Copyright (C) 2002 - 2009 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License v2. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/pci.h>
+#include <linux/io.h>
#include <asm/addrspace.h>
-#include <asm/io.h>
#include "pci-sh4.h"
/*
* Direct access to PCI hardware...
*/
#define CONFIG_CMD(bus, devfn, where) \
- P1SEGADDR((bus->number << 16) | (devfn << 8) | (where & ~3))
+ (P1SEG | (bus->number << 16) | (devfn << 8) | (where & ~3))
static DEFINE_SPINLOCK(sh4_pci_lock);
@@ -26,6 +26,7 @@ static DEFINE_SPINLOCK(sh4_pci_lock);
static int sh4_pci_read(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val)
{
+ struct pci_channel *chan = bus->sysdata;
unsigned long flags;
u32 data;
@@ -34,8 +35,8 @@ static int sh4_pci_read(struct pci_bus *bus, unsigned int devfn,
* so we must do byte alignment by hand
*/
spin_lock_irqsave(&sh4_pci_lock, flags);
- pci_write_reg(CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
- data = pci_read_reg(SH4_PCIPDR);
+ pci_write_reg(chan, CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
+ data = pci_read_reg(chan, SH4_PCIPDR);
spin_unlock_irqrestore(&sh4_pci_lock, flags);
switch (size) {
@@ -63,13 +64,14 @@ static int sh4_pci_read(struct pci_bus *bus, unsigned int devfn,
static int sh4_pci_write(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 val)
{
+ struct pci_channel *chan = bus->sysdata;
unsigned long flags;
int shift;
u32 data;
spin_lock_irqsave(&sh4_pci_lock, flags);
- pci_write_reg(CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
- data = pci_read_reg(SH4_PCIPDR);
+ pci_write_reg(chan, CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
+ data = pci_read_reg(chan, SH4_PCIPDR);
spin_unlock_irqrestore(&sh4_pci_lock, flags);
switch (size) {
@@ -90,7 +92,7 @@ static int sh4_pci_write(struct pci_bus *bus, unsigned int devfn,
return PCIBIOS_FUNC_NOT_SUPPORTED;
}
- pci_write_reg(data, SH4_PCIPDR);
+ pci_write_reg(chan, data, SH4_PCIPDR);
return PCIBIOS_SUCCESSFUL;
}
@@ -104,66 +106,31 @@ struct pci_ops sh4_pci_ops = {
* Not really related to pci_ops, but it's common and not worth shoving
* somewhere else for now..
*/
-static unsigned int pci_probe = PCI_PROBE_CONF1;
-
-int __init sh4_pci_check_direct(void)
+int __init sh4_pci_check_direct(struct pci_channel *chan)
{
/*
* Check if configuration works.
*/
- if (pci_probe & PCI_PROBE_CONF1) {
- unsigned int tmp = pci_read_reg(SH4_PCIPAR);
-
- pci_write_reg(P1SEG, SH4_PCIPAR);
+ unsigned int tmp = pci_read_reg(chan, SH4_PCIPAR);
- if (pci_read_reg(SH4_PCIPAR) == P1SEG) {
- pci_write_reg(tmp, SH4_PCIPAR);
- printk(KERN_INFO "PCI: Using configuration type 1\n");
- request_region(PCI_REG(SH4_PCIPAR), 8, "PCI conf1");
+ pci_write_reg(chan, P1SEG, SH4_PCIPAR);
- return 0;
- }
-
- pci_write_reg(tmp, SH4_PCIPAR);
+ if (pci_read_reg(chan, SH4_PCIPAR) == P1SEG) {
+ pci_write_reg(chan, tmp, SH4_PCIPAR);
+ printk(KERN_INFO "PCI: Using configuration type 1\n");
+ request_region(chan->reg_base + SH4_PCIPAR, 8,
+ "PCI conf1");
+ return 0;
}
- pr_debug("PCI: pci_check_direct failed\n");
- return -EINVAL;
-}
+ pci_write_reg(chan, tmp, SH4_PCIPAR);
-/* Handle generic fixups */
-static void __init pci_fixup_ide_bases(struct pci_dev *d)
-{
- int i;
+ printk(KERN_ERR "PCI: %s failed\n", __func__);
- /*
- * PCI IDE controllers use non-standard I/O port decoding, respect it.
- */
- if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
- return;
- pr_debug("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);
-
-char * __devinit pcibios_setup(char *str)
-{
- if (!strcmp(str, "off")) {
- pci_probe = 0;
- return NULL;
- }
-
- return str;
+ return -EINVAL;
}
-int __attribute__((weak)) pci_fixup_pcic(void)
+int __attribute__((weak)) pci_fixup_pcic(struct pci_channel *chan)
{
/* Nothing to do. */
return 0;
diff --git a/arch/sh/drivers/pci/ops-sh5.c b/arch/sh/drivers/pci/ops-sh5.c
index 729e38a6fe07..4ce95a001b80 100644
--- a/arch/sh/drivers/pci/ops-sh5.c
+++ b/arch/sh/drivers/pci/ops-sh5.c
@@ -22,31 +22,6 @@
#include <asm/io.h>
#include "pci-sh5.h"
-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);
-
-char * __devinit pcibios_setup(char *str)
-{
- return str;
-}
-
static int sh5pci_read(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *val)
{
diff --git a/arch/sh/drivers/pci/ops-sh7785lcr.c b/arch/sh/drivers/pci/ops-sh7785lcr.c
deleted file mode 100644
index e8b7446a7c2b..000000000000
--- a/arch/sh/drivers/pci/ops-sh7785lcr.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Author: Ian DaSilva (idasilva@mvista.com)
- *
- * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * PCI initialization for the Renesas R0P7785LC0011RL board
- * Based on arch/sh/drivers/pci/ops-r7780rp.c
- *
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include "pci-sh4.h"
-
-static char irq_tab[] __initdata = {
- 65, 66, 67, 68,
-};
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
- return irq_tab[slot];
-}
-
-static struct resource sh7785_io_resource = {
- .name = "SH7785_IO",
- .start = SH7780_PCI_IO_BASE,
- .end = SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1,
- .flags = IORESOURCE_IO
-};
-
-static struct resource sh7785_mem_resource = {
- .name = "SH7785_mem",
- .start = SH7780_PCI_MEMORY_BASE,
- .end = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
- .flags = IORESOURCE_MEM
-};
-
-struct pci_channel board_pci_channels[] = {
- { &sh4_pci_ops, &sh7785_io_resource, &sh7785_mem_resource, 0, 0xff },
- { NULL, NULL, NULL, 0, 0 },
-};
-EXPORT_SYMBOL(board_pci_channels);
-
-static struct sh4_pci_address_map sh7785_pci_map = {
- .window0 = {
- .base = SH7780_CS0_BASE_ADDR,
- .size = 0x20000000,
- },
-
- .flags = SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
- return sh7780_pcic_init(&sh7785_pci_map);
-}
diff --git a/arch/sh/drivers/pci/ops-snapgear.c b/arch/sh/drivers/pci/ops-snapgear.c
deleted file mode 100644
index 53dd893d4e54..000000000000
--- a/arch/sh/drivers/pci/ops-snapgear.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * arch/sh/drivers/pci/ops-snapgear.c
- *
- * Author: David McCullough <davidm@snapgear.com>
- *
- * Ported to new API by Paul Mundt <lethal@linux-sh.org>
- *
- * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * PCI initialization for the SnapGear boards
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include "pci-sh4.h"
-
-#define SNAPGEAR_PCI_IO 0x4000
-#define SNAPGEAR_PCI_MEM 0xfd000000
-
-/* PCI: default LOCAL memory window sizes (seen from PCI bus) */
-#define SNAPGEAR_LSR0_SIZE (64*(1<<20)) //64MB
-#define SNAPGEAR_LSR1_SIZE (64*(1<<20)) //64MB
-
-static struct resource sh7751_io_resource = {
- .name = "SH7751 IO",
- .start = SNAPGEAR_PCI_IO,
- .end = SNAPGEAR_PCI_IO + (64*1024) - 1, /* 64KiB I/O */
- .flags = IORESOURCE_IO,
-};
-
-static struct resource sh7751_mem_resource = {
- .name = "SH7751 mem",
- .start = SNAPGEAR_PCI_MEM,
- .end = SNAPGEAR_PCI_MEM + (64*1024*1024) - 1, /* 64MiB mem */
- .flags = IORESOURCE_MEM,
-};
-
-struct pci_channel board_pci_channels[] = {
- { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
- { 0, }
-};
-
-static struct sh4_pci_address_map sh7751_pci_map = {
- .window0 = {
- .base = SH7751_CS2_BASE_ADDR,
- .size = SNAPGEAR_LSR0_SIZE,
- },
-
- .window1 = {
- .base = SH7751_CS2_BASE_ADDR,
- .size = SNAPGEAR_LSR1_SIZE,
- },
-
- .flags = SH4_PCIC_NO_RESET,
-};
-
-/*
- * Initialize the SnapGear PCI interface
- * Setup hardware to be Central Funtion
- * Copy the BSR regs to the PCI interface
- * Setup PCI windows into local RAM
- */
-int __init pcibios_init_platform(void)
-{
- return sh7751_pcic_init(&sh7751_pci_map);
-}
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
- int irq = -1;
-
- switch (slot) {
- case 8: /* the PCI bridge */ break;
- case 11: irq = 8; break; /* USB */
- case 12: irq = 11; break; /* PCMCIA */
- case 13: irq = 5; break; /* eth0 */
- case 14: irq = 8; break; /* eth1 */
- case 15: irq = 11; break; /* safenet (unused) */
- }
-
- printk("PCI: Mapping SnapGear IRQ for slot %d, pin %c to irq %d\n",
- slot, pin - 1 + 'A', irq);
-
- return irq;
-}
-
-void __init pcibios_fixup(void)
-{
- /* Nothing to fixup .. */
-}
diff --git a/arch/sh/drivers/pci/pci-auto.c b/arch/sh/drivers/pci/pci-auto.c
deleted file mode 100644
index cf48b12ee58c..000000000000
--- a/arch/sh/drivers/pci/pci-auto.c
+++ /dev/null
@@ -1,545 +0,0 @@
-/*
- * PCI autoconfiguration library
- *
- * Author: Matt Porter <mporter@mvista.com>
- *
- * Copyright 2000, 2001 MontaVista Software Inc.
- * Copyright 2001 Bradley D. LaRonde <brad@ltc.com>
- * Copyright 2003 Paul Mundt <lethal@linux-sh.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-/*
- * Modified for MIPS by Jun Sun, jsun@mvista.com
- *
- * . Simplify the interface between pci_auto and the rest: a single function.
- * . Assign resources from low address to upper address.
- * . change most int to u32.
- *
- * Further modified to include it as mips generic code, ppopov@mvista.com.
- *
- * 2001-10-26 Bradley D. LaRonde <brad@ltc.com>
- * - Add a top_bus argument to the "early config" functions so that
- * they can set a fake parent bus pointer to convince the underlying
- * pci ops to use type 1 configuration for sub busses.
- * - Set bridge base and limit registers correctly.
- * - Align io and memory base properly before and after bridge setup.
- * - Don't fall through to pci_setup_bars for bridge.
- * - Reformat the debug output to look more like lspci's output.
- *
- * Cloned for SuperH by M. R. Brown, mrbrown@0xd6.org
- *
- * 2003-08-05 Paul Mundt <lethal@linux-sh.org>
- * - Don't update the BAR values on systems that already have valid addresses
- * and don't want these updated for whatever reason, by way of a new config
- * option check. However, we still read in the old BAR values so that they
- * can still be reported through the debug output.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-
-#define DEBUG
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-/*
- * These functions are used early on before PCI scanning is done
- * and all of the pci_dev and pci_bus structures have been created.
- */
-static struct pci_dev *fake_pci_dev(struct pci_channel *hose,
- int top_bus, int busnr, int devfn)
-{
- static struct pci_dev dev;
- static struct pci_bus bus;
-
- dev.bus = &bus;
- dev.sysdata = hose;
- dev.devfn = devfn;
- bus.number = busnr;
- bus.ops = hose->pci_ops;
-
- if(busnr != top_bus)
- /* Fake a parent bus structure. */
- bus.parent = &bus;
- else
- bus.parent = NULL;
-
- return &dev;
-}
-
-#define EARLY_PCI_OP(rw, size, type) \
-static int early_##rw##_config_##size(struct pci_channel *hose, \
- int top_bus, int bus, int devfn, int offset, type value) \
-{ \
- return pci_##rw##_config_##size( \
- fake_pci_dev(hose, top_bus, bus, devfn), \
- offset, value); \
-}
-
-EARLY_PCI_OP(read, byte, u8 *)
-EARLY_PCI_OP(read, word, u16 *)
-EARLY_PCI_OP(read, dword, u32 *)
-EARLY_PCI_OP(write, byte, u8)
-EARLY_PCI_OP(write, word, u16)
-EARLY_PCI_OP(write, dword, u32)
-
-static struct resource *io_resource_inuse;
-static struct resource *mem_resource_inuse;
-
-static u32 pciauto_lower_iospc;
-static u32 pciauto_upper_iospc;
-
-static u32 pciauto_lower_memspc;
-static u32 pciauto_upper_memspc;
-
-static void __init
-pciauto_setup_bars(struct pci_channel *hose,
- int top_bus,
- int current_bus,
- int pci_devfn,
- int bar_limit)
-{
- u32 bar_response, bar_size, bar_value;
- u32 bar, addr_mask, bar_nr = 0;
- u32 * upper_limit;
- u32 * lower_limit;
- int found_mem64 = 0;
-
- for (bar = PCI_BASE_ADDRESS_0; bar <= bar_limit; bar+=4) {
- u32 bar_addr;
-
- /* Read the old BAR value */
- early_read_config_dword(hose, top_bus,
- current_bus,
- pci_devfn,
- bar,
- &bar_addr);
-
- /* Tickle the BAR and get the response */
- early_write_config_dword(hose, top_bus,
- current_bus,
- pci_devfn,
- bar,
- 0xffffffff);
-
- early_read_config_dword(hose, top_bus,
- current_bus,
- pci_devfn,
- bar,
- &bar_response);
-
- /*
- * Write the old BAR value back out, only update the BAR
- * if we implicitly want resources to be updated, which
- * is done by the generic code further down. -- PFM.
- */
- early_write_config_dword(hose, top_bus,
- current_bus,
- pci_devfn,
- bar,
- bar_addr);
-
- /* If BAR is not implemented go to the next BAR */
- if (!bar_response)
- continue;
-
- /*
- * Workaround for a BAR that doesn't use its upper word,
- * like the ALi 1535D+ PCI DC-97 Controller Modem (M5457).
- * bdl <brad@ltc.com>
- */
- if (!(bar_response & 0xffff0000))
- bar_response |= 0xffff0000;
-
-retry:
- /* Check the BAR type and set our address mask */
- if (bar_response & PCI_BASE_ADDRESS_SPACE) {
- addr_mask = PCI_BASE_ADDRESS_IO_MASK;
- upper_limit = &pciauto_upper_iospc;
- lower_limit = &pciauto_lower_iospc;
- DBG(" I/O");
- } else {
- if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
- PCI_BASE_ADDRESS_MEM_TYPE_64)
- found_mem64 = 1;
-
- addr_mask = PCI_BASE_ADDRESS_MEM_MASK;
- upper_limit = &pciauto_upper_memspc;
- lower_limit = &pciauto_lower_memspc;
- DBG(" Mem");
- }
-
-
- /* Calculate requested size */
- bar_size = ~(bar_response & addr_mask) + 1;
-
- /* Allocate a base address */
- bar_value = ((*lower_limit - 1) & ~(bar_size - 1)) + bar_size;
-
- if ((bar_value + bar_size) > *upper_limit) {
- if (bar_response & PCI_BASE_ADDRESS_SPACE) {
- if (io_resource_inuse->child) {
- io_resource_inuse =
- io_resource_inuse->child;
- pciauto_lower_iospc =
- io_resource_inuse->start;
- pciauto_upper_iospc =
- io_resource_inuse->end + 1;
- goto retry;
- }
-
- } else {
- if (mem_resource_inuse->child) {
- mem_resource_inuse =
- mem_resource_inuse->child;
- pciauto_lower_memspc =
- mem_resource_inuse->start;
- pciauto_upper_memspc =
- mem_resource_inuse->end + 1;
- goto retry;
- }
- }
- DBG(" unavailable -- skipping, value %x size %x\n",
- bar_value, bar_size);
- continue;
- }
-
- if (bar_value < *lower_limit || (bar_value + bar_size) >= *upper_limit) {
- DBG(" unavailable -- skipping, value %x size %x\n",
- bar_value, bar_size);
- continue;
- }
-
-#ifdef CONFIG_PCI_AUTO_UPDATE_RESOURCES
- /* Write it out and update our limit */
- early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
- bar, bar_value);
-#endif
-
- *lower_limit = bar_value + bar_size;
-
- /*
- * If we are a 64-bit decoder then increment to the
- * upper 32 bits of the bar and force it to locate
- * in the lower 4GB of memory.
- */
- if (found_mem64) {
- bar += 4;
- early_write_config_dword(hose, top_bus,
- current_bus,
- pci_devfn,
- bar,
- 0x00000000);
- }
-
- DBG(" at 0x%.8x [size=0x%x]\n", bar_value, bar_size);
-
- bar_nr++;
- }
-
-}
-
-static void __init
-pciauto_prescan_setup_bridge(struct pci_channel *hose,
- int top_bus,
- int current_bus,
- int pci_devfn,
- int sub_bus)
-{
- /* Configure bus number registers */
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_PRIMARY_BUS, current_bus);
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_SECONDARY_BUS, sub_bus + 1);
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_SUBORDINATE_BUS, 0xff);
-
- /* Align memory and I/O to 1MB and 4KB boundaries. */
- pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1))
- & ~(0x100000 - 1);
- pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1))
- & ~(0x1000 - 1);
-
- /* Set base (lower limit) of address range behind bridge. */
- early_write_config_word(hose, top_bus, current_bus, pci_devfn,
- PCI_MEMORY_BASE, pciauto_lower_memspc >> 16);
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_IO_BASE, (pciauto_lower_iospc & 0x0000f000) >> 8);
- early_write_config_word(hose, top_bus, current_bus, pci_devfn,
- PCI_IO_BASE_UPPER16, pciauto_lower_iospc >> 16);
-
- /* We don't support prefetchable memory for now, so disable */
- early_write_config_word(hose, top_bus, current_bus, pci_devfn,
- PCI_PREF_MEMORY_BASE, 0);
- early_write_config_word(hose, top_bus, current_bus, pci_devfn,
- PCI_PREF_MEMORY_LIMIT, 0);
-}
-
-static void __init
-pciauto_postscan_setup_bridge(struct pci_channel *hose,
- int top_bus,
- int current_bus,
- int pci_devfn,
- int sub_bus)
-{
- u32 temp;
-
- /*
- * [jsun] we always bump up baselines a little, so that if there
- * nothing behind P2P bridge, we don't wind up overlapping IO/MEM
- * spaces.
- */
- pciauto_lower_memspc += 1;
- pciauto_lower_iospc += 1;
-
- /* Configure bus number registers */
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_SUBORDINATE_BUS, sub_bus);
-
- /* Set upper limit of address range behind bridge. */
- early_write_config_word(hose, top_bus, current_bus, pci_devfn,
- PCI_MEMORY_LIMIT, pciauto_lower_memspc >> 16);
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_IO_LIMIT, (pciauto_lower_iospc & 0x0000f000) >> 8);
- early_write_config_word(hose, top_bus, current_bus, pci_devfn,
- PCI_IO_LIMIT_UPPER16, pciauto_lower_iospc >> 16);
-
- /* Align memory and I/O to 1MB and 4KB boundaries. */
- pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1))
- & ~(0x100000 - 1);
- pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1))
- & ~(0x1000 - 1);
-
- /* Enable memory and I/O accesses, enable bus master */
- early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_COMMAND, &temp);
- early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_COMMAND, temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY
- | PCI_COMMAND_MASTER);
-}
-
-static void __init
-pciauto_prescan_setup_cardbus_bridge(struct pci_channel *hose,
- int top_bus,
- int current_bus,
- int pci_devfn,
- int sub_bus)
-{
- /* Configure bus number registers */
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_PRIMARY_BUS, current_bus);
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_SECONDARY_BUS, sub_bus + 1);
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_SUBORDINATE_BUS, 0xff);
-
- /* Align memory and I/O to 4KB and 4 byte boundaries. */
- pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1))
- & ~(0x1000 - 1);
- pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1))
- & ~(0x4 - 1);
-
- early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_CB_MEMORY_BASE_0, pciauto_lower_memspc);
- early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_CB_IO_BASE_0, pciauto_lower_iospc);
-}
-
-static void __init
-pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
- int top_bus,
- int current_bus,
- int pci_devfn,
- int sub_bus)
-{
- u32 temp;
-
- /*
- * [jsun] we always bump up baselines a little, so that if there
- * nothing behind P2P bridge, we don't wind up overlapping IO/MEM
- * spaces.
- */
- pciauto_lower_memspc += 1;
- pciauto_lower_iospc += 1;
-
- /*
- * Configure subordinate bus number. The PCI subsystem
- * bus scan will renumber buses (reserving three additional
- * for this PCI<->CardBus bridge for the case where a CardBus
- * adapter contains a P2P or CB2CB bridge.
- */
-
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_SUBORDINATE_BUS, sub_bus);
-
- /*
- * Reserve an additional 4MB for mem space and 16KB for
- * I/O space. This should cover any additional space
- * requirement of unusual CardBus devices with
- * additional bridges that can consume more address space.
- *
- * Although pcmcia-cs currently will reprogram bridge
- * windows, the goal is to add an option to leave them
- * alone and use the bridge window ranges as the regions
- * that are searched for free resources upon hot-insertion
- * of a device. This will allow a PCI<->CardBus bridge
- * configured by this routine to happily live behind a
- * P2P bridge in a system.
- */
- /* Align memory and I/O to 4KB and 4 byte boundaries. */
- pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1))
- & ~(0x1000 - 1);
- pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1))
- & ~(0x4 - 1);
- /* Set up memory and I/O filter limits, assume 32-bit I/O space */
- early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_CB_MEMORY_LIMIT_0, pciauto_lower_memspc - 1);
- early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_CB_IO_LIMIT_0, pciauto_lower_iospc - 1);
-
- /* Enable memory and I/O accesses, enable bus master */
- early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_COMMAND, &temp);
- early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_COMMAND, temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
- PCI_COMMAND_MASTER);
-}
-
-#define PCIAUTO_IDE_MODE_MASK 0x05
-
-static int __init
-pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
-{
- int sub_bus;
- u32 pci_devfn, pci_class, cmdstat, found_multi=0;
- unsigned short vid, did;
- unsigned char header_type;
- int devfn_start = 0;
- int devfn_stop = 0xff;
-
- sub_bus = current_bus;
-
- if (hose->first_devfn)
- devfn_start = hose->first_devfn;
- if (hose->last_devfn)
- devfn_stop = hose->last_devfn;
-
- for (pci_devfn=devfn_start; pci_devfn<devfn_stop; pci_devfn++) {
-
- if (PCI_FUNC(pci_devfn) && !found_multi)
- continue;
-
- early_read_config_word(hose, top_bus, current_bus, pci_devfn,
- PCI_VENDOR_ID, &vid);
-
- if (vid == 0xffff) continue;
-
- early_read_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_HEADER_TYPE, &header_type);
-
- if (!PCI_FUNC(pci_devfn))
- found_multi = header_type & 0x80;
-
- early_read_config_word(hose, top_bus, current_bus, pci_devfn,
- PCI_DEVICE_ID, &did);
-
- early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_CLASS_REVISION, &pci_class);
-
- DBG("%.2x:%.2x.%x Class %.4x: %.4x:%.4x",
- current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn),
- pci_class >> 16, vid, did);
- if (pci_class & 0xff)
- DBG(" (rev %.2x)", pci_class & 0xff);
- DBG("\n");
-
- if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) {
- DBG(" Bridge: primary=%.2x, secondary=%.2x\n",
- current_bus, sub_bus + 1);
- pciauto_prescan_setup_bridge(hose, top_bus, current_bus,
- pci_devfn, sub_bus);
- DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n",
- sub_bus + 1,
- pciauto_lower_iospc, pciauto_lower_memspc);
- sub_bus = pciauto_bus_scan(hose, top_bus, sub_bus+1);
- DBG("Back to bus %.2x\n", current_bus);
- pciauto_postscan_setup_bridge(hose, top_bus, current_bus,
- pci_devfn, sub_bus);
- continue;
- } else if ((pci_class >> 16) == PCI_CLASS_BRIDGE_CARDBUS) {
- DBG(" CARDBUS Bridge: primary=%.2x, secondary=%.2x\n",
- current_bus, sub_bus + 1);
- DBG("PCI Autoconfig: Found CardBus bridge, device %d function %d\n", PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn));
- /* Place CardBus Socket/ExCA registers */
- pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_0);
-
- pciauto_prescan_setup_cardbus_bridge(hose, top_bus,
- current_bus, pci_devfn, sub_bus);
-
- DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n",
- sub_bus + 1,
- pciauto_lower_iospc, pciauto_lower_memspc);
- sub_bus = pciauto_bus_scan(hose, top_bus, sub_bus+1);
- DBG("Back to bus %.2x, sub_bus is %x\n", current_bus, sub_bus);
- pciauto_postscan_setup_cardbus_bridge(hose, top_bus,
- current_bus, pci_devfn, sub_bus);
- continue;
- } else if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) {
-
- unsigned char prg_iface;
-
- early_read_config_byte(hose, top_bus, current_bus,
- pci_devfn, PCI_CLASS_PROG, &prg_iface);
- if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) {
- DBG("Skipping legacy mode IDE controller\n");
- continue;
- }
- }
-
- /*
- * Found a peripheral, enable some standard
- * settings
- */
- early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_COMMAND, &cmdstat);
- early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_COMMAND, cmdstat | PCI_COMMAND_IO |
- PCI_COMMAND_MEMORY |
- PCI_COMMAND_MASTER);
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_LATENCY_TIMER, 0x80);
-
- /* Allocate PCI I/O and/or memory space */
- pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_5);
- }
- return sub_bus;
-}
-
-int __init
-pciauto_assign_resources(int busno, struct pci_channel *hose)
-{
- /* setup resource limits */
- io_resource_inuse = hose->io_resource;
- mem_resource_inuse = hose->mem_resource;
-
- pciauto_lower_iospc = io_resource_inuse->start;
- pciauto_upper_iospc = io_resource_inuse->end + 1;
- pciauto_lower_memspc = mem_resource_inuse->start;
- pciauto_upper_memspc = mem_resource_inuse->end + 1;
- DBG("Autoconfig PCI channel 0x%p\n", hose);
- DBG("Scanning bus %.2x, I/O 0x%.8x:0x%.8x, Mem 0x%.8x:0x%.8x\n",
- busno, pciauto_lower_iospc, pciauto_upper_iospc,
- pciauto_lower_memspc, pciauto_upper_memspc);
-
- return pciauto_bus_scan(hose, busno, busno);
-}
diff --git a/arch/sh/drivers/pci/pci-dreamcast.c b/arch/sh/drivers/pci/pci-dreamcast.c
new file mode 100644
index 000000000000..210f9d4af141
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-dreamcast.c
@@ -0,0 +1,102 @@
+/*
+ * PCI support for the Sega Dreamcast
+ *
+ * Copyright (C) 2001, 2002 M. R. Brown
+ * Copyright (C) 2002, 2003 Paul Mundt
+ *
+ * This file originally bore the message (with enclosed-$):
+ * Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp
+ * Dreamcast PCI: Supports SEGA Broadband Adaptor only.
+ *
+ * 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/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <mach/pci.h>
+
+static struct resource gapspci_io_resource = {
+ .name = "GAPSPCI IO",
+ .start = GAPSPCI_BBA_CONFIG,
+ .end = GAPSPCI_BBA_CONFIG + GAPSPCI_BBA_CONFIG_SIZE - 1,
+ .flags = IORESOURCE_IO,
+};
+
+static struct resource gapspci_mem_resource = {
+ .name = "GAPSPCI mem",
+ .start = GAPSPCI_DMA_BASE,
+ .end = GAPSPCI_DMA_BASE + GAPSPCI_DMA_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct pci_channel dreamcast_pci_controller = {
+ .pci_ops = &gapspci_pci_ops,
+ .io_resource = &gapspci_io_resource,
+ .io_offset = 0x00000000,
+ .mem_resource = &gapspci_mem_resource,
+ .mem_offset = 0x00000000,
+};
+
+/*
+ * gapspci init
+ */
+
+static int __init gapspci_init(void)
+{
+ char idbuf[16];
+ int i;
+
+ /*
+ * FIXME: All of this wants documenting to some degree,
+ * even some basic register definitions would be nice.
+ *
+ * I haven't seen anything this ugly since.. maple.
+ */
+
+ for (i=0; i<16; i++)
+ idbuf[i] = inb(GAPSPCI_REGS+i);
+
+ if (strncmp(idbuf, "GAPSPCI_BRIDGE_2", 16))
+ return -ENODEV;
+
+ outl(0x5a14a501, GAPSPCI_REGS+0x18);
+
+ for (i=0; i<1000000; i++)
+ cpu_relax();
+
+ if (inl(GAPSPCI_REGS+0x18) != 1)
+ return -EINVAL;
+
+ outl(0x01000000, GAPSPCI_REGS+0x20);
+ outl(0x01000000, GAPSPCI_REGS+0x24);
+
+ outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28);
+ outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c);
+
+ outl(1, GAPSPCI_REGS+0x14);
+ outl(1, GAPSPCI_REGS+0x34);
+
+ /* Setting Broadband Adapter */
+ outw(0xf900, GAPSPCI_BBA_CONFIG+0x06);
+ outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30);
+ outb(0x00, GAPSPCI_BBA_CONFIG+0x3c);
+ outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d);
+ outw(0x0006, GAPSPCI_BBA_CONFIG+0x04);
+ outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10);
+ outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14);
+
+ register_pci_controller(&dreamcast_pci_controller);
+
+ return 0;
+}
+arch_initcall(gapspci_init);
diff --git a/arch/sh/drivers/pci/pci-sh4.h b/arch/sh/drivers/pci/pci-sh4.h
index a83dcf70c13b..3d5296cde622 100644
--- a/arch/sh/drivers/pci/pci-sh4.h
+++ b/arch/sh/drivers/pci/pci-sh4.h
@@ -149,13 +149,10 @@
#define SH4_PCIPDTR_PB0 0x000000001 /* Port 0 Enable */
#define SH4_PCIPDR 0x220 /* Port IO Data Register */
-/* Flags */
-#define SH4_PCIC_NO_RESET 0x0001
-
/* arch/sh/kernel/drivers/pci/ops-sh4.c */
extern struct pci_ops sh4_pci_ops;
-int sh4_pci_check_direct(void);
-int pci_fixup_pcic(void);
+int sh4_pci_check_direct(struct pci_channel *chan);
+int pci_fixup_pcic(struct pci_channel *chan);
struct sh4_pci_address_space {
unsigned long base;
@@ -165,16 +162,18 @@ struct sh4_pci_address_space {
struct sh4_pci_address_map {
struct sh4_pci_address_space window0;
struct sh4_pci_address_space window1;
- unsigned long flags;
};
-static inline void pci_write_reg(unsigned long val, unsigned long reg)
+static inline void pci_write_reg(struct pci_channel *chan,
+ unsigned long val, unsigned long reg)
{
- ctrl_outl(val, PCI_REG(reg));
+ ctrl_outl(val, chan->reg_base + reg);
}
-static inline unsigned long pci_read_reg(unsigned long reg)
+static inline unsigned long pci_read_reg(struct pci_channel *chan,
+ unsigned long reg)
{
- return ctrl_inl(PCI_REG(reg));
+ return ctrl_inl(chan->reg_base + reg);
}
+
#endif /* __PCI_SH4_H */
diff --git a/arch/sh/drivers/pci/pci-sh5.c b/arch/sh/drivers/pci/pci-sh5.c
index 7a97438762c8..873ed2b44055 100644
--- a/arch/sh/drivers/pci/pci-sh5.c
+++ b/arch/sh/drivers/pci/pci-sh5.c
@@ -89,8 +89,21 @@ static irqreturn_t pcish5_serr_irq(int irq, void *dev_id)
return IRQ_NONE;
}
-int __init sh5pci_init(unsigned long memStart, unsigned long memSize)
+static struct resource sh5_io_resource = { /* place holder */ };
+static struct resource sh5_mem_resource = { /* place holder */ };
+
+static struct pci_channel sh5pci_controller = {
+ .pci_ops = &sh5_pci_ops,
+ .mem_resource = &sh5_mem_resource,
+ .mem_offset = 0x00000000,
+ .io_resource = &sh5_io_resource,
+ .io_offset = 0x00000000,
+};
+
+static int __init sh5pci_init(void)
{
+ unsigned long memStart = __pa(memory_start);
+ unsigned long memSize = __pa(memory_end) - memStart;
u32 lsr0;
u32 uval;
@@ -106,12 +119,12 @@ int __init sh5pci_init(unsigned long memStart, unsigned long memSize)
return -EINVAL;
}
- pcicr_virt = onchip_remap(SH5PCI_ICR_BASE, 1024, "PCICR");
+ pcicr_virt = (unsigned long)ioremap_nocache(SH5PCI_ICR_BASE, 1024);
if (!pcicr_virt) {
panic("Unable to remap PCICR\n");
}
- PCI_IO_AREA = onchip_remap(SH5PCI_IO_BASE, 0x10000, "PCIIO");
+ PCI_IO_AREA = (unsigned long)ioremap_nocache(SH5PCI_IO_BASE, 0x10000);
if (!PCI_IO_AREA) {
panic("Unable to remap PCIIO\n");
}
@@ -197,32 +210,14 @@ int __init sh5pci_init(unsigned long memStart, unsigned long memSize)
SH5PCI_WRITE(AINTM, ~0);
SH5PCI_WRITE(PINTM, ~0);
- return 0;
-}
+ sh5_io_resource.start = PCI_IO_AREA;
+ sh5_io_resource.end = PCI_IO_AREA + 0x10000;
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
-{
- struct pci_dev *dev = bus->self;
- int i;
-
- if (dev) {
- for (i= 0; i < 3; i++) {
- bus->resource[i] =
- &dev->resource[PCI_BRIDGE_RESOURCES+i];
- bus->resource[i]->name = bus->name;
- }
- bus->resource[0]->flags |= IORESOURCE_IO;
- bus->resource[1]->flags |= IORESOURCE_MEM;
-
- /* For now, propagate host limits to the bus;
- * we'll adjust them later. */
- bus->resource[0]->end = 64*1024 - 1 ;
- bus->resource[1]->end = PCIBIOS_MIN_MEM+(256*1024*1024)-1;
- bus->resource[0]->start = PCIBIOS_MIN_IO;
- bus->resource[1]->start = PCIBIOS_MIN_MEM;
-
- /* Turn off downstream PF memory address range by default */
- bus->resource[2]->start = 1024*1024;
- bus->resource[2]->end = bus->resource[2]->start - 1;
- }
+ sh5_mem_resource.start = memStart;
+ sh5_mem_resource.end = memStart + memSize;
+
+ register_pci_controller(&sh5pci_controller);
+
+ return 0;
}
+arch_initcall(sh5pci_init);
diff --git a/arch/sh/drivers/pci/pci-sh5.h b/arch/sh/drivers/pci/pci-sh5.h
index 7cff3fc04d30..f277628221f3 100644
--- a/arch/sh/drivers/pci/pci-sh5.h
+++ b/arch/sh/drivers/pci/pci-sh5.h
@@ -107,7 +107,4 @@ extern unsigned long pcicr_virt;
extern struct pci_ops sh5_pci_ops;
-/* arch/sh/drivers/pci/pci-sh5.c */
-int sh5pci_init(unsigned long memStart, unsigned long memSize);
-
#endif /* __PCI_SH5_H */
diff --git a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c
index 3065eb184f01..c4fa0bb13976 100644
--- a/arch/sh/drivers/pci/pci-sh7751.c
+++ b/arch/sh/drivers/pci/pci-sh7751.c
@@ -1,88 +1,99 @@
/*
- * Low-Level PCI Support for the SH7751
+ * Low-Level PCI Support for the SH7751
*
- * Dustin McIntire (dustin@sensoria.com)
- * Derived from arch/i386/kernel/pci-*.c which bore the message:
- * (c) 1999--2000 Martin Mares <mj@ucw.cz>
+ * Copyright (C) 2003 - 2009 Paul Mundt
+ * Copyright (C) 2001 Dustin McIntire
*
- * Ported to the new API by Paul Mundt <lethal@linux-sh.org>
- * With cleanup by Paul van Gool <pvangool@mimotech.com>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
+ * With cleanup by Paul van Gool <pvangool@mimotech.com>, 2003.
*
+ * 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.
*/
-#undef DEBUG
-
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/types.h>
#include <linux/errno.h>
-#include <linux/delay.h>
+#include <linux/io.h>
#include "pci-sh4.h"
#include <asm/addrspace.h>
-#include <asm/io.h>
-/*
- * Initialization. Try all known PCI access methods. Note that we support
- * using both PCI BIOS and direct access: in such cases, we use I/O ports
- * to access config space.
- *
- * Note that the platform specific initialization (BSC registers, and memory
- * space mapping) will be called via the platform defined function
- * pcibios_init_platform().
- */
-static int __init sh7751_pci_init(void)
+static int __init __area_sdram_check(struct pci_channel *chan,
+ unsigned int area)
{
- unsigned int id;
- int ret;
-
- pr_debug("PCI: Starting intialization.\n");
+ unsigned long word;
- /* check for SH7751/SH7751R hardware */
- id = pci_read_reg(SH7751_PCICONF0);
- if (id != ((SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID) &&
- id != ((SH7751R_DEVICE_ID << 16) | SH7751_VENDOR_ID)) {
- pr_debug("PCI: This is not an SH7751(R) (%x)\n", id);
- return -ENODEV;
- }
-
- if ((ret = sh4_pci_check_direct()) != 0)
- return ret;
-
- return pcibios_init_platform();
-}
-subsys_initcall(sh7751_pci_init);
-
-static int __init __area_sdram_check(unsigned int area)
-{
- u32 word;
-
- word = ctrl_inl(SH7751_BCR1);
+ word = __raw_readl(SH7751_BCR1);
/* check BCR for SDRAM in area */
if (((word >> area) & 1) == 0) {
- printk("PCI: Area %d is not configured for SDRAM. BCR1=0x%x\n",
+ printk("PCI: Area %d is not configured for SDRAM. BCR1=0x%lx\n",
area, word);
return 0;
}
- pci_write_reg(word, SH4_PCIBCR1);
+ pci_write_reg(chan, word, SH4_PCIBCR1);
- word = (u16)ctrl_inw(SH7751_BCR2);
+ word = __raw_readw(SH7751_BCR2);
/* check BCR2 for 32bit SDRAM interface*/
if (((word >> (area << 1)) & 0x3) != 0x3) {
- printk("PCI: Area %d is not 32 bit SDRAM. BCR2=0x%x\n",
+ printk("PCI: Area %d is not 32 bit SDRAM. BCR2=0x%lx\n",
area, word);
return 0;
}
- pci_write_reg(word, SH4_PCIBCR2);
+ pci_write_reg(chan, word, SH4_PCIBCR2);
return 1;
}
-int __init sh7751_pcic_init(struct sh4_pci_address_map *map)
+static struct resource sh7751_io_resource = {
+ .name = "SH7751_IO",
+ .start = SH7751_PCI_IO_BASE,
+ .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
+ .flags = IORESOURCE_IO
+};
+
+static struct resource sh7751_mem_resource = {
+ .name = "SH7785_mem",
+ .start = SH7751_PCI_MEMORY_BASE,
+ .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
+ .flags = IORESOURCE_MEM
+};
+
+static struct pci_channel sh7751_pci_controller = {
+ .pci_ops = &sh4_pci_ops,
+ .mem_resource = &sh7751_mem_resource,
+ .mem_offset = 0x00000000,
+ .io_resource = &sh7751_io_resource,
+ .io_offset = 0x00000000,
+};
+
+static struct sh4_pci_address_map sh7751_pci_map = {
+ .window0 = {
+ .base = SH7751_CS3_BASE_ADDR,
+ .size = 0x04000000,
+ },
+};
+
+static int __init sh7751_pci_init(void)
{
- u32 reg;
- u32 word;
+ struct pci_channel *chan = &sh7751_pci_controller;
+ unsigned int id;
+ u32 word, reg;
+ int ret;
+
+ printk(KERN_NOTICE "PCI: Starting intialization.\n");
+
+ chan->reg_base = 0xfe200000;
+
+ /* check for SH7751/SH7751R hardware */
+ id = pci_read_reg(chan, SH7751_PCICONF0);
+ if (id != ((SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID) &&
+ id != ((SH7751R_DEVICE_ID << 16) | SH7751_VENDOR_ID)) {
+ pr_debug("PCI: This is not an SH7751(R) (%x)\n", id);
+ return -ENODEV;
+ }
+
+ if ((ret = sh4_pci_check_direct(chan)) != 0)
+ return ret;
/* Set the BCR's to enable PCI access */
reg = ctrl_inl(SH7751_BCR1);
@@ -90,25 +101,10 @@ int __init sh7751_pcic_init(struct sh4_pci_address_map *map)
ctrl_outl(reg, SH7751_BCR1);
/* Turn the clocks back on (not done in reset)*/
- pci_write_reg(0, SH4_PCICLKR);
+ pci_write_reg(chan, 0, SH4_PCICLKR);
/* Clear Powerdown IRQ's (not done in reset) */
word = SH4_PCIPINT_D3 | SH4_PCIPINT_D0;
- pci_write_reg(word, SH4_PCIPINT);
-
- /*
- * This code is unused for some boards as it is done in the
- * bootloader and doing it here means the MAC addresses loaded
- * by the bootloader get lost.
- */
- if (!(map->flags & SH4_PCIC_NO_RESET)) {
- /* toggle PCI reset pin */
- word = SH4_PCICR_PREFIX | SH4_PCICR_PRST;
- pci_write_reg(word, SH4_PCICR);
- /* Wait for a long time... not 1 sec. but long enough */
- mdelay(100);
- word = SH4_PCICR_PREFIX;
- pci_write_reg(word, SH4_PCICR);
- }
+ pci_write_reg(chan, word, SH4_PCIPINT);
/* set the command/status bits to:
* Wait Cycle Control + Parity Enable + Bus Master +
@@ -116,89 +112,77 @@ int __init sh7751_pcic_init(struct sh4_pci_address_map *map)
*/
word = SH7751_PCICONF1_WCC | SH7751_PCICONF1_PER |
SH7751_PCICONF1_BUM | SH7751_PCICONF1_MES;
- pci_write_reg(word, SH7751_PCICONF1);
+ pci_write_reg(chan, word, SH7751_PCICONF1);
/* define this host as the host bridge */
word = PCI_BASE_CLASS_BRIDGE << 24;
- pci_write_reg(word, SH7751_PCICONF2);
+ pci_write_reg(chan, word, SH7751_PCICONF2);
/* Set IO and Mem windows to local address
* Make PCI and local address the same for easy 1 to 1 mapping
- * Window0 = map->window0.size @ non-cached area base = SDRAM
- * Window1 = map->window1.size @ cached area base = SDRAM
*/
- word = map->window0.size - 1;
- pci_write_reg(word, SH4_PCILSR0);
- word = map->window1.size - 1;
- pci_write_reg(word, SH4_PCILSR1);
+ word = sh7751_pci_map.window0.size - 1;
+ pci_write_reg(chan, word, SH4_PCILSR0);
/* Set the values on window 0 PCI config registers */
- word = P2SEGADDR(map->window0.base);
- pci_write_reg(word, SH4_PCILAR0);
- pci_write_reg(word, SH7751_PCICONF5);
- /* Set the values on window 1 PCI config registers */
- word = PHYSADDR(map->window1.base);
- pci_write_reg(word, SH4_PCILAR1);
- pci_write_reg(word, SH7751_PCICONF6);
+ word = P2SEGADDR(sh7751_pci_map.window0.base);
+ pci_write_reg(chan, word, SH4_PCILAR0);
+ pci_write_reg(chan, word, SH7751_PCICONF5);
/* Set the local 16MB PCI memory space window to
* the lowest PCI mapped address
*/
- word = PCIBIOS_MIN_MEM & SH4_PCIMBR_MASK;
+ word = chan->mem_resource->start & SH4_PCIMBR_MASK;
pr_debug("PCI: Setting upper bits of Memory window to 0x%x\n", word);
- pci_write_reg(word , SH4_PCIMBR);
-
- /* Map IO space into PCI IO window
- * The IO window is 64K-PCIBIOS_MIN_IO in size
- * IO addresses will be translated to the
- * PCI IO window base address
- */
- pr_debug("PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n",
- PCIBIOS_MIN_IO, (64 << 10),
- SH7751_PCI_IO_BASE + PCIBIOS_MIN_IO);
+ pci_write_reg(chan, word , SH4_PCIMBR);
/* Make sure the MSB's of IO window are set to access PCI space
* correctly */
- word = PCIBIOS_MIN_IO & SH4_PCIIOBR_MASK;
+ word = chan->io_resource->start & SH4_PCIIOBR_MASK;
pr_debug("PCI: Setting upper bits of IO window to 0x%x\n", word);
- pci_write_reg(word, SH4_PCIIOBR);
+ pci_write_reg(chan, word, SH4_PCIIOBR);
/* Set PCI WCRx, BCRx's, copy from BSC locations */
/* check BCR for SDRAM in specified area */
- switch (map->window0.base) {
- case SH7751_CS0_BASE_ADDR: word = __area_sdram_check(0); break;
- case SH7751_CS1_BASE_ADDR: word = __area_sdram_check(1); break;
- case SH7751_CS2_BASE_ADDR: word = __area_sdram_check(2); break;
- case SH7751_CS3_BASE_ADDR: word = __area_sdram_check(3); break;
- case SH7751_CS4_BASE_ADDR: word = __area_sdram_check(4); break;
- case SH7751_CS5_BASE_ADDR: word = __area_sdram_check(5); break;
- case SH7751_CS6_BASE_ADDR: word = __area_sdram_check(6); break;
+ switch (sh7751_pci_map.window0.base) {
+ case SH7751_CS0_BASE_ADDR: word = __area_sdram_check(chan, 0); break;
+ case SH7751_CS1_BASE_ADDR: word = __area_sdram_check(chan, 1); break;
+ case SH7751_CS2_BASE_ADDR: word = __area_sdram_check(chan, 2); break;
+ case SH7751_CS3_BASE_ADDR: word = __area_sdram_check(chan, 3); break;
+ case SH7751_CS4_BASE_ADDR: word = __area_sdram_check(chan, 4); break;
+ case SH7751_CS5_BASE_ADDR: word = __area_sdram_check(chan, 5); break;
+ case SH7751_CS6_BASE_ADDR: word = __area_sdram_check(chan, 6); break;
}
if (!word)
- return 0;
+ return -1;
/* configure the wait control registers */
word = ctrl_inl(SH7751_WCR1);
- pci_write_reg(word, SH4_PCIWCR1);
+ pci_write_reg(chan, word, SH4_PCIWCR1);
word = ctrl_inl(SH7751_WCR2);
- pci_write_reg(word, SH4_PCIWCR2);
+ pci_write_reg(chan, word, SH4_PCIWCR2);
word = ctrl_inl(SH7751_WCR3);
- pci_write_reg(word, SH4_PCIWCR3);
+ pci_write_reg(chan, word, SH4_PCIWCR3);
word = ctrl_inl(SH7751_MCR);
- pci_write_reg(word, SH4_PCIMCR);
+ pci_write_reg(chan, word, SH4_PCIMCR);
/* NOTE: I'm ignoring the PCI error IRQs for now..
* TODO: add support for the internal error interrupts and
* DMA interrupts...
*/
- pci_fixup_pcic();
+ pci_fixup_pcic(chan);
/* SH7751 init done, set central function init complete */
/* use round robin mode to stop a device starving/overruning */
word = SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_ARBM;
- pci_write_reg(word, SH4_PCICR);
+ pci_write_reg(chan, word, SH4_PCICR);
- return 1;
+ __set_io_port_base(SH7751_PCI_IO_BASE);
+
+ register_pci_controller(chan);
+
+ return 0;
}
+arch_initcall(sh7751_pci_init);
diff --git a/arch/sh/drivers/pci/pci-sh7751.h b/arch/sh/drivers/pci/pci-sh7751.h
index 68e3cb5e6bec..4983a4d20355 100644
--- a/arch/sh/drivers/pci/pci-sh7751.h
+++ b/arch/sh/drivers/pci/pci-sh7751.h
@@ -26,7 +26,6 @@
#define SH7751_PCI_IO_SIZE 0x40000 /* Size of IO window */
#define SH7751_PCIREG_BASE 0xFE200000 /* PCI regs base address */
-#define PCI_REG(n) (SH7751_PCIREG_BASE+ n)
#define SH7751_PCICONF0 0x0 /* PCI Config Reg 0 */
#define SH7751_PCICONF0_DEVID 0xFFFF0000 /* Device ID */
@@ -58,7 +57,7 @@
#define SH7751_PCICONF2_SCC 0x00FF0000 /* Sub-Class Code */
#define SH7751_PCICONF2_RLPI 0x0000FF00 /* Programming Interface */
#define SH7751_PCICONF2_REV 0x000000FF /* Revision ID */
-#define SH7751_PCICONF3 0xC /* PCI Config Reg 3 */
+#define SH7751_PCICONF3 0xC /* PCI Config Reg 3 */
#define SH7751_PCICONF3_BIST7 0x80000000 /* Bist Supported */
#define SH7751_PCICONF3_BIST6 0x40000000 /* Bist Executing */
#define SH7751_PCICONF3_BIST3_0 0x0F000000 /* Bist Passed */
@@ -73,12 +72,12 @@
#define SH7751_PCICONF5_BASE 0xFFFFFFF0 /* Mem Space Base Addr */
#define SH7751_PCICONF5_LAP 0x00000008 /* Prefetch Enabled */
#define SH7751_PCICONF5_LAT 0x00000006 /* Local Memory type */
- #define SH7751_PCICONF5_ASI 0x00000001 /* Address Space Type */
+ #define SH7751_PCICONF5_ASI 0x00000001 /* Address Space Type */
#define SH7751_PCICONF6 0x18 /* PCI Config Reg 6 */
#define SH7751_PCICONF6_BASE 0xFFFFFFF0 /* Mem Space Base Addr */
#define SH7751_PCICONF6_LAP 0x00000008 /* Prefetch Enabled */
#define SH7751_PCICONF6_LAT 0x00000006 /* Local Memory type */
- #define SH7751_PCICONF6_ASI 0x00000001 /* Address Space Type */
+ #define SH7751_PCICONF6_ASI 0x00000001 /* Address Space Type */
/* PCICONF7 - PCICONF10 are undefined */
#define SH7751_PCICONF11 0x2C /* PCI Config Reg 11 */
#define SH7751_PCICONF11_SSID 0xFFFF0000 /* Subsystem ID */
@@ -127,9 +126,4 @@
#define SH7751_CS5_BASE_ADDR (SH7751_CS4_BASE_ADDR + SH7751_MEM_REGION_SIZE)
#define SH7751_CS6_BASE_ADDR (SH7751_CS5_BASE_ADDR + SH7751_MEM_REGION_SIZE)
-struct sh4_pci_address_map;
-
-/* arch/sh/drivers/pci/pci-sh7751.c */
-int sh7751_pcic_init(struct sh4_pci_address_map *map);
-
#endif /* _PCI_SH7751_H_ */
diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c
index bae6a2cf047d..ae13ff925c61 100644
--- a/arch/sh/drivers/pci/pci-sh7780.c
+++ b/arch/sh/drivers/pci/pci-sh7780.c
@@ -1,19 +1,12 @@
/*
- * Low-Level PCI Support for the SH7780
+ * Low-Level PCI Support for the SH7780
*
- * Dustin McIntire (dustin@sensoria.com)
- * Derived from arch/i386/kernel/pci-*.c which bore the message:
- * (c) 1999--2000 Martin Mares <mj@ucw.cz>
- *
- * Ported to the new API by Paul Mundt <lethal@linux-sh.org>
- * With cleanup by Paul van Gool <pvangool@mimotech.com>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
+ * Copyright (C) 2005 - 2009 Paul Mundt
*
+ * 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.
*/
-#undef DEBUG
-
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -22,135 +15,137 @@
#include <linux/delay.h>
#include "pci-sh4.h"
-#define INTC_BASE 0xffd00000
-#define INTC_ICR0 (INTC_BASE+0x0)
-#define INTC_ICR1 (INTC_BASE+0x1c)
-#define INTC_INTPRI (INTC_BASE+0x10)
-#define INTC_INTREQ (INTC_BASE+0x24)
-#define INTC_INTMSK0 (INTC_BASE+0x44)
-#define INTC_INTMSK1 (INTC_BASE+0x48)
-#define INTC_INTMSK2 (INTC_BASE+0x40080)
-#define INTC_INTMSKCLR0 (INTC_BASE+0x64)
-#define INTC_INTMSKCLR1 (INTC_BASE+0x68)
-#define INTC_INTMSKCLR2 (INTC_BASE+0x40084)
-#define INTC_INT2MSKR (INTC_BASE+0x40038)
-#define INTC_INT2MSKCR (INTC_BASE+0x4003c)
+extern u8 pci_cache_line_size;
+
+static struct resource sh7785_io_resource = {
+ .name = "SH7785_IO",
+ .start = SH7780_PCI_IO_BASE,
+ .end = SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1,
+ .flags = IORESOURCE_IO
+};
+
+static struct resource sh7785_mem_resource = {
+ .name = "SH7785_mem",
+ .start = SH7780_PCI_MEMORY_BASE,
+ .end = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
+ .flags = IORESOURCE_MEM
+};
+
+static struct pci_channel sh7780_pci_controller = {
+ .pci_ops = &sh4_pci_ops,
+ .mem_resource = &sh7785_mem_resource,
+ .mem_offset = 0x00000000,
+ .io_resource = &sh7785_io_resource,
+ .io_offset = 0x00000000,
+};
+
+static struct sh4_pci_address_map sh7780_pci_map = {
+ .window0 = {
+#if defined(CONFIG_32BIT)
+ .base = SH7780_32BIT_DDR_BASE_ADDR,
+ .size = 0x40000000,
+#else
+ .base = SH7780_CS0_BASE_ADDR,
+ .size = 0x20000000,
+#endif
+ },
+};
-/*
- * Initialization. Try all known PCI access methods. Note that we support
- * using both PCI BIOS and direct access: in such cases, we use I/O ports
- * to access config space.
- *
- * Note that the platform specific initialization (BSC registers, and memory
- * space mapping) will be called via the platform defined function
- * pcibios_init_platform().
- */
static int __init sh7780_pci_init(void)
{
+ struct pci_channel *chan = &sh7780_pci_controller;
unsigned int id;
- int ret, match = 0;
-
- pr_debug("PCI: Starting intialization.\n");
-
- ctrl_outl(0x00000001, SH7780_PCI_VCR2); /* Enable PCIC */
-
- /* check for SH7780/SH7780R hardware */
- id = pci_read_reg(SH7780_PCIVID);
- if ((id & 0xffff) == SH7780_VENDOR_ID) {
- switch ((id >> 16) & 0xffff) {
- case SH7763_DEVICE_ID:
- case SH7780_DEVICE_ID:
- case SH7781_DEVICE_ID:
- case SH7785_DEVICE_ID:
- match = 1;
- break;
- }
- }
+ const char *type = NULL;
+ int ret;
+ u32 word;
- if (unlikely(!match)) {
- printk(KERN_ERR "PCI: This is not an SH7780 (%x)\n", id);
+ printk(KERN_NOTICE "PCI: Starting intialization.\n");
+
+ chan->reg_base = 0xfe040000;
+
+ /* Enable CPU access to the PCIC registers. */
+ __raw_writel(PCIECR_ENBL, PCIECR);
+
+ id = __raw_readw(chan->reg_base + SH7780_PCIVID);
+ if (id != SH7780_VENDOR_ID) {
+ printk(KERN_ERR "PCI: Unknown vendor ID 0x%04x.\n", id);
return -ENODEV;
}
- /* Setup the INTC */
- if (mach_is_7780se()) {
- /* ICR0: IRL=use separately */
- ctrl_outl(0x00C00020, INTC_ICR0);
- /* ICR1: detect low level(for 2ndcut) */
- ctrl_outl(0xAAAA0000, INTC_ICR1);
- /* INTPRI: priority=3(all) */
- ctrl_outl(0x33333333, INTC_INTPRI);
+ id = __raw_readw(chan->reg_base + SH7780_PCIDID);
+ type = (id == SH7763_DEVICE_ID) ? "SH7763" :
+ (id == SH7780_DEVICE_ID) ? "SH7780" :
+ (id == SH7781_DEVICE_ID) ? "SH7781" :
+ (id == SH7785_DEVICE_ID) ? "SH7785" :
+ NULL;
+ if (unlikely(!type)) {
+ printk(KERN_ERR "PCI: Found an unsupported Renesas host "
+ "controller, device id 0x%04x.\n", id);
+ return -EINVAL;
}
- if ((ret = sh4_pci_check_direct()) != 0)
- return ret;
+ printk(KERN_NOTICE "PCI: Found a Renesas %s host "
+ "controller, revision %d.\n", type,
+ __raw_readb(chan->reg_base + SH7780_PCIRID));
- return pcibios_init_platform();
-}
-core_initcall(sh7780_pci_init);
-
-int __init sh7780_pcic_init(struct sh4_pci_address_map *map)
-{
- u32 word;
+ if ((ret = sh4_pci_check_direct(chan)) != 0)
+ return ret;
/*
- * This code is unused for some boards as it is done in the
- * bootloader and doing it here means the MAC addresses loaded
- * by the bootloader get lost.
- */
- if (!(map->flags & SH4_PCIC_NO_RESET)) {
- /* toggle PCI reset pin */
- word = SH4_PCICR_PREFIX | SH4_PCICR_PRST;
- pci_write_reg(word, SH4_PCICR);
- /* Wait for a long time... not 1 sec. but long enough */
- mdelay(100);
- word = SH4_PCICR_PREFIX;
- pci_write_reg(word, SH4_PCICR);
- }
-
- /* set the command/status bits to:
- * Wait Cycle Control + Parity Enable + Bus Master +
- * Mem space enable
+ * Set the class and sub-class codes.
*/
- pci_write_reg(0x00000046, SH7780_PCICMD);
+ __raw_writeb(PCI_CLASS_BRIDGE_HOST >> 8,
+ chan->reg_base + SH7780_PCIBCC);
+ __raw_writeb(PCI_CLASS_BRIDGE_HOST & 0xff,
+ chan->reg_base + SH7780_PCISUB);
- /* define this host as the host bridge */
- word = PCI_BASE_CLASS_BRIDGE << 24;
- pci_write_reg(word, SH7780_PCIRID);
+ pci_cache_line_size = pci_read_reg(chan, SH7780_PCICLS) / 4;
- /* Set IO and Mem windows to local address
+ /*
+ * Set IO and Mem windows to local address
* Make PCI and local address the same for easy 1 to 1 mapping
*/
- pci_write_reg(map->window0.size - 0xfffff, SH4_PCILSR0);
- pci_write_reg(map->window1.size - 0xfffff, SH4_PCILSR1);
+ pci_write_reg(chan, sh7780_pci_map.window0.size - 0xfffff, SH4_PCILSR0);
/* Set the values on window 0 PCI config registers */
- pci_write_reg(map->window0.base, SH4_PCILAR0);
- pci_write_reg(map->window0.base, SH7780_PCIMBAR0);
- /* Set the values on window 1 PCI config registers */
- pci_write_reg(map->window1.base, SH4_PCILAR1);
- pci_write_reg(map->window1.base, SH7780_PCIMBAR1);
-
- /* Map IO space into PCI IO window
- * The IO window is 64K-PCIBIOS_MIN_IO in size
- * IO addresses will be translated to the
- * PCI IO window base address
- */
- pr_debug("PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n",
- PCIBIOS_MIN_IO, (64 << 10),
- SH7780_PCI_IO_BASE + PCIBIOS_MIN_IO);
+ pci_write_reg(chan, sh7780_pci_map.window0.base, SH4_PCILAR0);
+ pci_write_reg(chan, sh7780_pci_map.window0.base, SH7780_PCIMBAR0);
- /* NOTE: I'm ignoring the PCI error IRQs for now..
- * TODO: add support for the internal error interrupts and
- * DMA interrupts...
- */
+ pci_write_reg(chan, 0x0000380f, SH4_PCIAINTM);
+
+ /* Set up standard PCI config registers */
+ __raw_writew(0xFB00, chan->reg_base + SH7780_PCISTATUS);
+ __raw_writew(0x0047, chan->reg_base + SH7780_PCICMD);
+ __raw_writew(0x1912, chan->reg_base + SH7780_PCISVID);
+ __raw_writew(0x0001, chan->reg_base + SH7780_PCISID);
+
+ __raw_writeb(0x00, chan->reg_base + SH7780_PCIPIF);
/* Apply any last-minute PCIC fixups */
- pci_fixup_pcic();
+ pci_fixup_pcic(chan);
+
+ pci_write_reg(chan, 0xfd000000, SH7780_PCIMBR0);
+ pci_write_reg(chan, 0x00fc0000, SH7780_PCIMBMR0);
+
+#ifdef CONFIG_32BIT
+ pci_write_reg(chan, 0xc0000000, SH7780_PCIMBR2);
+ pci_write_reg(chan, 0x20000000 - SH7780_PCI_IO_SIZE, SH7780_PCIMBMR2);
+#endif
+
+ /* Set IOBR for windows containing area specified in pci.h */
+ pci_write_reg(chan, chan->io_resource->start & ~(SH7780_PCI_IO_SIZE-1),
+ SH7780_PCIIOBR);
+ pci_write_reg(chan, ((SH7780_PCI_IO_SIZE-1) & (7<<18)),
+ SH7780_PCIIOBMR);
/* SH7780 init done, set central function init complete */
/* use round robin mode to stop a device starving/overruning */
word = SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_FTO;
- pci_write_reg(word, SH4_PCICR);
+ pci_write_reg(chan, word, SH4_PCICR);
+
+ __set_io_port_base(SH7780_PCI_IO_BASE);
+
+ register_pci_controller(chan);
- return 1;
+ return 0;
}
+arch_initcall(sh7780_pci_init);
diff --git a/arch/sh/drivers/pci/pci-sh7780.h b/arch/sh/drivers/pci/pci-sh7780.h
index 97b2c98f05c4..4a52478c97cf 100644
--- a/arch/sh/drivers/pci/pci-sh7780.h
+++ b/arch/sh/drivers/pci/pci-sh7780.h
@@ -20,9 +20,8 @@
#define SH7785_DEVICE_ID 0x0007
/* SH7780 Control Registers */
-#define SH7780_PCI_VCR0 0xFE000000
-#define SH7780_PCI_VCR1 0xFE000004
-#define SH7780_PCI_VCR2 0xFE000008
+#define PCIECR 0xFE000008
+#define PCIECR_ENBL 0x01
/* SH7780 Specific Values */
#define SH7780_PCI_CONFIG_BASE 0xFD000000 /* Config space base addr */
@@ -35,7 +34,6 @@
#define SH7780_PCI_IO_SIZE 0x00400000 /* Size of IO window */
#define SH7780_PCIREG_BASE 0xFE040000 /* PCI regs base address */
-#define PCI_REG(n) (SH7780_PCIREG_BASE+n)
/* SH7780 PCI Config Registers */
#define SH7780_PCIVID 0x000 /* Vendor ID */
@@ -67,11 +65,6 @@
#define SH7780_PCIPMCSR_BSE 0x046
#define SH7780_PCICDD 0x047
-#define SH7780_PCICR 0x100 /* PCI Control Register */
-#define SH7780_PCILSR 0x104 /* PCI Local Space Register0 */
-#define SH7780_PCILSR1 0x108 /* PCI Local Space Register1 */
-#define SH7780_PCILAR0 0x10C /* PCI Local Address Register1 */
-#define SH7780_PCILAR1 0x110 /* PCI Local Address Register1 */
#define SH7780_PCIIR 0x114 /* PCI Interrupt Register */
#define SH7780_PCIIMR 0x118 /* PCI Interrupt Mask Register */
#define SH7780_PCIAIR 0x11C /* Error Address Register */
@@ -104,9 +97,6 @@
#define SH7780_CS5_BASE_ADDR (SH7780_CS4_BASE_ADDR + SH7780_MEM_REGION_SIZE)
#define SH7780_CS6_BASE_ADDR (SH7780_CS5_BASE_ADDR + SH7780_MEM_REGION_SIZE)
-struct sh4_pci_address_map;
-
-/* arch/sh/drivers/pci/pci-sh7780.c */
-int sh7780_pcic_init(struct sh4_pci_address_map *map);
+#define SH7780_32BIT_DDR_BASE_ADDR 0x40000000
#endif /* _PCI_SH7780_H_ */
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index e36c7b870861..54d77cbb8b39 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -1,64 +1,156 @@
/*
- * arch/sh/drivers/pci/pci.c
+ * New-style PCI core.
*
- * Copyright (c) 2002 M. R. Brown <mrbrown@linux-sh.org>
- * Copyright (c) 2004 - 2006 Paul Mundt <lethal@linux-sh.org>
+ * Copyright (c) 2004 - 2009 Paul Mundt
+ * Copyright (c) 2002 M. R. Brown
*
- * These functions are collected here to reduce duplication of common
- * code amongst the many platform-specific PCI support code files.
- *
- * These routines require the following board-specific routines:
- * void pcibios_fixup_irqs();
- *
- * See include/asm-sh/pci.h for more information.
+ * Modelled after arch/mips/pci/pci.c:
+ * Copyright (C) 2003, 04 Ralf Baechle (ralf@linux-mips.org)
*
* 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/kernel.h>
+#include <linux/mm.h>
#include <linux/pci.h>
#include <linux/init.h>
-#include <asm/io.h>
+#include <linux/types.h>
+#include <linux/dma-debug.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
-static int __init pcibios_init(void)
+unsigned long PCIBIOS_MIN_IO = 0x0000;
+unsigned long PCIBIOS_MIN_MEM = 0;
+
+/*
+ * The PCI controller list.
+ */
+static struct pci_channel *hose_head, **hose_tail = &hose_head;
+
+static int pci_initialized;
+
+static void __devinit pcibios_scanbus(struct pci_channel *hose)
{
- struct pci_channel *p;
+ static int next_busno;
struct pci_bus *bus;
- int busno;
-#ifdef CONFIG_PCI_AUTO
- /* assign resources */
- busno = 0;
- for (p = board_pci_channels; p->pci_ops != NULL; p++)
- busno = pciauto_assign_resources(busno, p) + 1;
-#endif
+ bus = pci_scan_bus(next_busno, hose->pci_ops, hose);
+ if (bus) {
+ next_busno = bus->subordinate + 1;
+ /* Don't allow 8-bit bus number overflow inside the hose -
+ reserve some space for bridges. */
+ if (next_busno > 224)
+ next_busno = 0;
+
+ pci_bus_size_bridges(bus);
+ pci_bus_assign_resources(bus);
+ pci_enable_bridges(bus);
+ }
+}
+
+static DEFINE_MUTEX(pci_scan_mutex);
+
+void __devinit register_pci_controller(struct pci_channel *hose)
+{
+ if (request_resource(&iomem_resource, hose->mem_resource) < 0)
+ goto out;
+ if (request_resource(&ioport_resource, hose->io_resource) < 0) {
+ release_resource(hose->mem_resource);
+ goto out;
+ }
+
+ *hose_tail = hose;
+ hose_tail = &hose->next;
- /* scan the buses */
- busno = 0;
- for (p = board_pci_channels; p->pci_ops != NULL; p++) {
- bus = pci_scan_bus(busno, p->pci_ops, p);
- busno = bus->subordinate + 1;
+ /*
+ * Do not panic here but later - this might hapen before console init.
+ */
+ if (!hose->io_map_base) {
+ printk(KERN_WARNING
+ "registering PCI controller with io_map_base unset\n");
+ }
+
+ /*
+ * Scan the bus if it is register after the PCI subsystem
+ * initialization.
+ */
+ if (pci_initialized) {
+ mutex_lock(&pci_scan_mutex);
+ pcibios_scanbus(hose);
+ mutex_unlock(&pci_scan_mutex);
}
+ return;
+
+out:
+ printk(KERN_WARNING
+ "Skipping PCI bus scan due to resource conflict\n");
+}
+
+static int __init pcibios_init(void)
+{
+ struct pci_channel *hose;
+
+ /* Scan all of the recorded PCI controllers. */
+ for (hose = hose_head; hose; hose = hose->next)
+ pcibios_scanbus(hose);
+
pci_fixup_irqs(pci_common_swizzle, pcibios_map_platform_irq);
+ dma_debug_add_bus(&pci_bus_type);
+
+ pci_initialized = 1;
+
return 0;
}
subsys_initcall(pcibios_init);
+static void pcibios_fixup_device_resources(struct pci_dev *dev,
+ struct pci_bus *bus)
+{
+ /* Update device resources. */
+ struct pci_channel *hose = bus->sysdata;
+ unsigned long offset = 0;
+ int i;
+
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ if (!dev->resource[i].start)
+ continue;
+ if (dev->resource[i].flags & IORESOURCE_PCI_FIXED)
+ continue;
+ if (dev->resource[i].flags & IORESOURCE_IO)
+ offset = hose->io_offset;
+ else if (dev->resource[i].flags & IORESOURCE_MEM)
+ offset = hose->mem_offset;
+
+ dev->resource[i].start += offset;
+ dev->resource[i].end += offset;
+ }
+}
+
/*
* Called after each bus is probed, but before its children
* are examined.
*/
-void __devinit __weak pcibios_fixup_bus(struct pci_bus *bus)
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
{
- pci_read_bridge_bases(bus);
-}
+ struct pci_dev *dev = bus->self;
+ struct list_head *ln;
+ struct pci_channel *chan = bus->sysdata;
-void pcibios_align_resource(void *data, struct resource *res,
- resource_size_t size, resource_size_t align)
- __attribute__ ((weak));
+ if (!dev) {
+ bus->resource[0] = chan->io_resource;
+ bus->resource[1] = chan->mem_resource;
+ }
+
+ for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
+ dev = pci_dev_b(ln);
+
+ if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
+ pcibios_fixup_device_resources(dev, bus);
+ }
+}
/*
* We need to avoid collisions with `mirrored' VGA ports
@@ -69,14 +161,58 @@ void pcibios_align_resource(void *data, struct resource *res,
void pcibios_align_resource(void *data, struct resource *res,
resource_size_t size, resource_size_t align)
{
+ struct pci_dev *dev = data;
+ struct pci_channel *chan = dev->sysdata;
+ resource_size_t start = res->start;
+
if (res->flags & IORESOURCE_IO) {
- resource_size_t start = res->start;
+ if (start < PCIBIOS_MIN_IO + chan->io_resource->start)
+ start = PCIBIOS_MIN_IO + chan->io_resource->start;
+ /*
+ * Put everything into 0x00-0xff region modulo 0x400.
+ */
if (start & 0x300) {
start = (start + 0x3ff) & ~0x3ff;
res->start = start;
}
+ } else if (res->flags & IORESOURCE_MEM) {
+ if (start < PCIBIOS_MIN_MEM + chan->mem_resource->start)
+ start = PCIBIOS_MIN_MEM + chan->mem_resource->start;
}
+
+ res->start = start;
+}
+
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
+{
+ struct pci_channel *hose = dev->sysdata;
+ unsigned long offset = 0;
+
+ if (res->flags & IORESOURCE_IO)
+ offset = hose->io_offset;
+ else if (res->flags & IORESOURCE_MEM)
+ offset = hose->mem_offset;
+
+ region->start = res->start - offset;
+ region->end = res->end - offset;
+}
+
+void __devinit
+pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region)
+{
+ struct pci_channel *hose = dev->sysdata;
+ unsigned long offset = 0;
+
+ if (res->flags & IORESOURCE_IO)
+ offset = hose->io_offset;
+ else if (res->flags & IORESOURCE_MEM)
+ offset = hose->mem_offset;
+
+ res->start = region->start + offset;
+ res->end = region->end + offset;
}
int pcibios_enable_device(struct pci_dev *dev, int mask)
@@ -87,13 +223,21 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
pci_read_config_word(dev, PCI_COMMAND, &cmd);
old_cmd = cmd;
- for(idx=0; idx<6; idx++) {
- if (!(mask & (1 << idx)))
+ for (idx=0; idx < PCI_NUM_RESOURCES; idx++) {
+ /* Only set up the requested stuff */
+ if (!(mask & (1<<idx)))
continue;
+
r = &dev->resource[idx];
+ if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
+ continue;
+ if ((idx == PCI_ROM_RESOURCE) &&
+ (!(r->flags & IORESOURCE_ROM_ENABLE)))
+ continue;
if (!r->start && r->end) {
- printk(KERN_ERR "PCI: Device %s not available because "
- "of resource collisions\n", pci_name(dev));
+ printk(KERN_ERR "PCI: Device %s not available "
+ "because of resource collisions\n",
+ pci_name(dev));
return -EINVAL;
}
if (r->flags & IORESOURCE_IO)
@@ -101,10 +245,8 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
if (r->flags & IORESOURCE_MEM)
cmd |= PCI_COMMAND_MEMORY;
}
- if (dev->resource[PCI_ROM_RESOURCE].start)
- cmd |= PCI_COMMAND_MEMORY;
if (cmd != old_cmd) {
- printk(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n",
+ printk("PCI: Enabling device %s (%04x -> %04x)\n",
pci_name(dev), old_cmd, cmd);
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
@@ -137,6 +279,43 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
}
+char * __devinit pcibios_setup(char *str)
+{
+ return str;
+}
+
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state, int write_combine)
+{
+ /*
+ * I/O space can be accessed via normal processor loads and stores on
+ * this platform but for now we elect not to do this and portable
+ * drivers should not do this anyway.
+ */
+ if (mmap_state == pci_mmap_io)
+ return -EINVAL;
+
+ /*
+ * Ignore write-combine; for now only return uncached mappings.
+ */
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+}
+
+static void __iomem *ioport_map_pci(struct pci_dev *dev,
+ unsigned long port, unsigned int nr)
+{
+ struct pci_channel *chan = dev->sysdata;
+
+ if (!chan->io_map_base)
+ chan->io_map_base = generic_io_base;
+
+ return (void __iomem *)(chan->io_map_base + port);
+}
+
void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
{
resource_size_t start = pci_resource_start(dev, bar);
@@ -148,20 +327,24 @@ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
if (maxlen && len > maxlen)
len = maxlen;
+ if (flags & IORESOURCE_IO)
+ return ioport_map_pci(dev, start, len);
+
/*
* Presently the IORESOURCE_MEM case is a bit special, most
* SH7751 style PCI controllers have PCI memory at a fixed
- * location in the address space where no remapping is desired
- * (typically at 0xfd000000, but is_pci_memaddr() will know
- * best). With the IORESOURCE_MEM case more care has to be taken
+ * location in the address space where no remapping is desired.
+ * With the IORESOURCE_MEM case more care has to be taken
* to inhibit page table mapping for legacy cores, but this is
* punted off to __ioremap().
* -- PFM.
*/
- if (flags & IORESOURCE_IO)
- return ioport_map(start, len);
- if (flags & IORESOURCE_MEM)
- return ioremap(start, len);
+ if (flags & IORESOURCE_MEM) {
+ if (flags & IORESOURCE_CACHEABLE)
+ return ioremap(start, len);
+
+ return ioremap_nocache(start, len);
+ }
return NULL;
}
@@ -172,3 +355,10 @@ void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
iounmap(addr);
}
EXPORT_SYMBOL(pci_iounmap);
+
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+EXPORT_SYMBOL(pcibios_bus_to_resource);
+EXPORT_SYMBOL(PCIBIOS_MIN_IO);
+EXPORT_SYMBOL(PCIBIOS_MIN_MEM);
+#endif
diff --git a/arch/sh/include/asm/cacheflush.h b/arch/sh/include/asm/cacheflush.h
index 09acbc32d6c7..4c5462daa74c 100644
--- a/arch/sh/include/asm/cacheflush.h
+++ b/arch/sh/include/asm/cacheflush.h
@@ -75,7 +75,5 @@ extern void copy_from_user_page(struct vm_area_struct *vma,
#define flush_cache_vmap(start, end) flush_cache_all()
#define flush_cache_vunmap(start, end) flush_cache_all()
-#define HAVE_ARCH_UNMAPPED_AREA
-
#endif /* __KERNEL__ */
#endif /* __ASM_SH_CACHEFLUSH_H */
diff --git a/arch/sh/include/asm/clock.h b/arch/sh/include/asm/clock.h
index 2f6c9627bc1f..b1f29199e4bd 100644
--- a/arch/sh/include/asm/clock.h
+++ b/arch/sh/include/asm/clock.h
@@ -1,7 +1,6 @@
#ifndef __ASM_SH_CLOCK_H
#define __ASM_SH_CLOCK_H
-#include <linux/kref.h>
#include <linux/list.h>
#include <linux/seq_file.h>
#include <linux/clk.h>
@@ -28,7 +27,7 @@ struct clk {
struct clk *parent;
struct clk_ops *ops;
- struct kref kref;
+ int usecount;
unsigned long rate;
unsigned long flags;
@@ -37,6 +36,7 @@ struct clk {
#define CLK_ALWAYS_ENABLED (1 << 0)
#define CLK_RATE_PROPAGATES (1 << 1)
+#define CLK_NEEDS_INIT (1 << 2)
/* Should be defined by processor-specific code */
void arch_init_clk_ops(struct clk_ops **, int type);
diff --git a/arch/sh/include/asm/device.h b/arch/sh/include/asm/device.h
index efd511d0803a..8688a88303ee 100644
--- a/arch/sh/include/asm/device.h
+++ b/arch/sh/include/asm/device.h
@@ -10,3 +10,5 @@ struct platform_device;
int platform_resource_setup_memory(struct platform_device *pdev,
char *name, unsigned long memsize);
+void plat_early_device_setup(void);
+
diff --git a/arch/sh/include/asm/dma-mapping.h b/arch/sh/include/asm/dma-mapping.h
index 627315ecdb52..ea9d4f41c9d2 100644
--- a/arch/sh/include/asm/dma-mapping.h
+++ b/arch/sh/include/asm/dma-mapping.h
@@ -3,6 +3,7 @@
#include <linux/mm.h>
#include <linux/scatterlist.h>
+#include <linux/dma-debug.h>
#include <asm/cacheflush.h>
#include <asm/io.h>
#include <asm-generic/dma-coherent.h>
@@ -38,16 +39,26 @@ static inline dma_addr_t dma_map_single(struct device *dev,
void *ptr, size_t size,
enum dma_data_direction dir)
{
+ dma_addr_t addr = virt_to_phys(ptr);
+
#if defined(CONFIG_PCI) && !defined(CONFIG_SH_PCIDMA_NONCOHERENT)
if (dev->bus == &pci_bus_type)
- return virt_to_phys(ptr);
+ return addr;
#endif
dma_cache_sync(dev, ptr, size, dir);
- return virt_to_phys(ptr);
+ debug_dma_map_page(dev, virt_to_page(ptr),
+ (unsigned long)ptr & ~PAGE_MASK, size,
+ dir, addr, true);
+
+ return addr;
}
-#define dma_unmap_single(dev, addr, size, dir) do { } while (0)
+static inline void dma_unmap_single(struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir)
+{
+ debug_dma_unmap_page(dev, addr, size, dir, true);
+}
static inline int dma_map_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir)
@@ -59,12 +70,19 @@ static inline int dma_map_sg(struct device *dev, struct scatterlist *sg,
dma_cache_sync(dev, sg_virt(&sg[i]), sg[i].length, dir);
#endif
sg[i].dma_address = sg_phys(&sg[i]);
+ sg[i].dma_length = sg[i].length;
}
+ debug_dma_map_sg(dev, sg, nents, i, dir);
+
return nents;
}
-#define dma_unmap_sg(dev, sg, nents, dir) do { } while (0)
+static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir)
+{
+ debug_dma_unmap_sg(dev, sg, nents, dir);
+}
static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
@@ -111,6 +129,7 @@ static inline void dma_sync_sg(struct device *dev, struct scatterlist *sg,
dma_cache_sync(dev, sg_virt(&sg[i]), sg[i].length, dir);
#endif
sg[i].dma_address = sg_phys(&sg[i]);
+ sg[i].dma_length = sg[i].length;
}
}
@@ -119,6 +138,7 @@ static inline void dma_sync_single_for_cpu(struct device *dev,
enum dma_data_direction dir)
{
dma_sync_single(dev, dma_handle, size, dir);
+ debug_dma_sync_single_for_cpu(dev, dma_handle, size, dir);
}
static inline void dma_sync_single_for_device(struct device *dev,
@@ -127,6 +147,7 @@ static inline void dma_sync_single_for_device(struct device *dev,
enum dma_data_direction dir)
{
dma_sync_single(dev, dma_handle, size, dir);
+ debug_dma_sync_single_for_device(dev, dma_handle, size, dir);
}
static inline void dma_sync_single_range_for_cpu(struct device *dev,
@@ -136,6 +157,8 @@ static inline void dma_sync_single_range_for_cpu(struct device *dev,
enum dma_data_direction direction)
{
dma_sync_single_for_cpu(dev, dma_handle+offset, size, direction);
+ debug_dma_sync_single_range_for_cpu(dev, dma_handle,
+ offset, size, direction);
}
static inline void dma_sync_single_range_for_device(struct device *dev,
@@ -145,6 +168,8 @@ static inline void dma_sync_single_range_for_device(struct device *dev,
enum dma_data_direction direction)
{
dma_sync_single_for_device(dev, dma_handle+offset, size, direction);
+ debug_dma_sync_single_range_for_device(dev, dma_handle,
+ offset, size, direction);
}
@@ -153,6 +178,7 @@ static inline void dma_sync_sg_for_cpu(struct device *dev,
enum dma_data_direction dir)
{
dma_sync_sg(dev, sg, nelems, dir);
+ debug_dma_sync_sg_for_cpu(dev, sg, nelems, dir);
}
static inline void dma_sync_sg_for_device(struct device *dev,
@@ -160,9 +186,9 @@ static inline void dma_sync_sg_for_device(struct device *dev,
enum dma_data_direction dir)
{
dma_sync_sg(dev, sg, nelems, dir);
+ debug_dma_sync_sg_for_device(dev, sg, nelems, dir);
}
-
static inline int dma_get_cache_alignment(void)
{
/*
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index 0454f8d68059..25348141674b 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -123,10 +123,15 @@ static inline void __raw_reads##bwlq(volatile void __iomem *mem, \
__BUILD_MEMORY_STRING(b, u8)
__BUILD_MEMORY_STRING(w, u16)
-__BUILD_MEMORY_STRING(q, u64)
+#ifdef CONFIG_SUPERH32
void __raw_writesl(void __iomem *addr, const void *data, int longlen);
void __raw_readsl(const void __iomem *addr, void *data, int longlen);
+#else
+__BUILD_MEMORY_STRING(l, u32)
+#endif
+
+__BUILD_MEMORY_STRING(q, u64)
#define writesb __raw_writesb
#define writesw __raw_writesw
@@ -224,17 +229,6 @@ void __iomem *__ioremap(unsigned long offset, unsigned long size,
unsigned long flags);
void __iounmap(void __iomem *addr);
-/* arch/sh/mm/ioremap_64.c */
-unsigned long onchip_remap(unsigned long addr, unsigned long size,
- const char *name);
-extern void onchip_unmap(unsigned long vaddr);
-#else
-#define __ioremap(offset, size, flags) ((void __iomem *)(offset))
-#define __iounmap(addr) do { } while (0)
-#define onchip_remap(addr, size, name) (addr)
-#define onchip_unmap(addr) do { } while (0)
-#endif /* CONFIG_MMU */
-
static inline void __iomem *
__ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags)
{
@@ -268,6 +262,10 @@ __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags)
return __ioremap(offset, size, flags);
}
+#else
+#define __ioremap_mode(offset, size, flags) ((void __iomem *)(offset))
+#define __iounmap(addr) do { } while (0)
+#endif /* CONFIG_MMU */
#define ioremap(offset, size) \
__ioremap_mode((offset), (size), 0)
diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h
index 613644a758e8..036c3311233c 100644
--- a/arch/sh/include/asm/kprobes.h
+++ b/arch/sh/include/asm/kprobes.h
@@ -6,7 +6,7 @@
#include <linux/types.h>
#include <linux/ptrace.h>
-typedef u16 kprobe_opcode_t;
+typedef insn_size_t kprobe_opcode_t;
#define BREAKPOINT_INSTRUCTION 0xc33a
#define MAX_INSN_SIZE 16
diff --git a/arch/sh/include/asm/pci.h b/arch/sh/include/asm/pci.h
index df1d383e18a5..5b2e0fcdfc22 100644
--- a/arch/sh/include/asm/pci.h
+++ b/arch/sh/include/asm/pci.h
@@ -17,54 +17,29 @@
* external) PCI controllers.
*/
struct pci_channel {
- struct pci_ops *pci_ops;
- struct resource *io_resource;
- struct resource *mem_resource;
- int first_devfn;
- int last_devfn;
-};
+ struct pci_channel *next;
-/*
- * Each board initializes this array and terminates it with a NULL entry.
- */
-extern struct pci_channel board_pci_channels[];
+ struct pci_ops *pci_ops;
+ struct resource *io_resource;
+ struct resource *mem_resource;
-#define PCIBIOS_MIN_IO board_pci_channels->io_resource->start
-#define PCIBIOS_MIN_MEM board_pci_channels->mem_resource->start
+ unsigned long io_offset;
+ unsigned long mem_offset;
-/*
- * I/O routine helpers
- */
-#if defined(CONFIG_CPU_SUBTYPE_SH7780) || defined(CONFIG_CPU_SUBTYPE_SH7785)
-#define PCI_IO_AREA 0xFE400000
-#define PCI_IO_SIZE 0x00400000
-#elif defined(CONFIG_CPU_SH5)
-extern unsigned long PCI_IO_AREA;
-#define PCI_IO_SIZE 0x00010000
-#else
-#define PCI_IO_AREA 0xFE240000
-#define PCI_IO_SIZE 0x00040000
-#endif
+ unsigned long reg_base;
-#define PCI_MEM_SIZE 0x01000000
+ unsigned long io_map_base;
+};
-#define SH4_PCIIOBR_MASK 0xFFFC0000
-#define pci_ioaddr(addr) (PCI_IO_AREA + (addr & ~SH4_PCIIOBR_MASK))
+extern void register_pci_controller(struct pci_channel *hose);
-#if defined(CONFIG_PCI)
-#define is_pci_ioaddr(port) \
- (((port) >= PCIBIOS_MIN_IO) && \
- ((port) < (PCIBIOS_MIN_IO + PCI_IO_SIZE)))
-#define is_pci_memaddr(port) \
- (((port) >= PCIBIOS_MIN_MEM) && \
- ((port) < (PCIBIOS_MIN_MEM + PCI_MEM_SIZE)))
-#else
-#define is_pci_ioaddr(port) (0)
-#define is_pci_memaddr(port) (0)
-#endif
+extern unsigned long PCIBIOS_MIN_IO, PCIBIOS_MIN_MEM;
struct pci_dev;
+#define HAVE_PCI_MMAP
+extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state, int write_combine);
extern void pcibios_set_master(struct pci_dev *dev);
static inline void pcibios_penalize_isa_irq(int irq, int active)
@@ -123,22 +98,51 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
}
#endif
+#ifdef CONFIG_SUPERH32
+/*
+ * If we're on an SH7751 or SH7780 PCI controller, PCI memory is mapped
+ * at the end of the address space in a special non-translatable area.
+ */
+#define PCI_MEM_FIXED_START 0xfd000000
+#define PCI_MEM_FIXED_END (PCI_MEM_FIXED_START + 0x01000000)
+
+#define is_pci_memory_fixed_range(s, e) \
+ ((s) >= PCI_MEM_FIXED_START && (e) < PCI_MEM_FIXED_END)
+#else
+#define is_pci_memory_fixed_range(s, e) (0)
+#endif
+
/* Board-specific fixup routines. */
-void pcibios_fixup(void);
-int pcibios_init_platform(void);
int pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin);
-#ifdef CONFIG_PCI_AUTO
-int pciauto_assign_resources(int busno, struct pci_channel *hose);
-#endif
+extern void pcibios_resource_to_bus(struct pci_dev *dev,
+ struct pci_bus_region *region, struct resource *res);
-#endif /* __KERNEL__ */
+extern void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region);
+
+static inline struct resource *
+pcibios_select_root(struct pci_dev *pdev, struct resource *res)
+{
+ struct resource *root = NULL;
-/* generic pci stuff */
-#include <asm-generic/pci.h>
+ if (res->flags & IORESOURCE_IO)
+ root = &ioport_resource;
+ if (res->flags & IORESOURCE_MEM)
+ root = &iomem_resource;
+
+ return root;
+}
+
+/* Chances are this interrupt is wired PC-style ... */
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+ return channel ? 15 : 14;
+}
/* generic DMA-mapping stuff */
#include <asm-generic/pci-dma-compat.h>
+#endif /* __KERNEL__ */
#endif /* __ASM_SH_PCI_H */
diff --git a/arch/sh/include/asm/pgtable.h b/arch/sh/include/asm/pgtable.h
index b517ae08b9c0..2a011b18090b 100644
--- a/arch/sh/include/asm/pgtable.h
+++ b/arch/sh/include/asm/pgtable.h
@@ -154,6 +154,10 @@ extern void kmap_coherent_init(void);
#define kmap_coherent_init() do { } while (0)
#endif
+/* arch/sh/mm/mmap.c */
+#define HAVE_ARCH_UNMAPPED_AREA
+#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
+
#include <asm-generic/pgtable.h>
#endif /* __ASM_SH_PGTABLE_H */
diff --git a/arch/sh/include/asm/processor.h b/arch/sh/include/asm/processor.h
index 1fd58b421438..005c962c8b1c 100644
--- a/arch/sh/include/asm/processor.h
+++ b/arch/sh/include/asm/processor.h
@@ -32,7 +32,7 @@ enum cpu_type {
/* SH-4A types */
CPU_SH7763, CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785, CPU_SH7786,
- CPU_SH7723, CPU_SHX3,
+ CPU_SH7723, CPU_SH7724, CPU_SHX3,
/* SH4AL-DSP types */
CPU_SH7343, CPU_SH7722, CPU_SH7366,
diff --git a/arch/sh/include/asm/ptrace.h b/arch/sh/include/asm/ptrace.h
index d3f6caa936b0..1dc12cb44a2d 100644
--- a/arch/sh/include/asm/ptrace.h
+++ b/arch/sh/include/asm/ptrace.h
@@ -9,7 +9,7 @@
struct pt_regs {
unsigned long long pc;
unsigned long long sr;
- unsigned long long syscall_nr;
+ long long syscall_nr;
unsigned long long regs[63];
unsigned long long tregs[8];
unsigned long long pad[2];
@@ -102,6 +102,11 @@ struct pt_dspregs {
#define PTRACE_GETDSPREGS 55 /* DSP registers */
#define PTRACE_SETDSPREGS 56
+#define PT_TEXT_END_ADDR 240
+#define PT_TEXT_ADDR 244 /* &(struct user)->start_code */
+#define PT_DATA_ADDR 248 /* &(struct user)->start_data */
+#define PT_TEXT_LEN 252
+
#ifdef __KERNEL__
#include <asm/addrspace.h>
diff --git a/arch/sh/include/asm/rtc.h b/arch/sh/include/asm/rtc.h
index f7b010d48af7..52b0c2dba979 100644
--- a/arch/sh/include/asm/rtc.h
+++ b/arch/sh/include/asm/rtc.h
@@ -6,6 +6,17 @@ extern void (*board_time_init)(void);
extern void (*rtc_sh_get_time)(struct timespec *);
extern int (*rtc_sh_set_time)(const time_t);
+/* some dummy definitions */
+#define RTC_BATT_BAD 0x100 /* battery bad */
+#define RTC_SQWE 0x08 /* enable square-wave output */
+#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */
+#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */
+#define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */
+
+struct rtc_time;
+unsigned int get_rtc_time(struct rtc_time *);
+int set_rtc_time(struct rtc_time *);
+
#define RTC_CAP_4_DIGIT_YEAR (1 << 0)
struct sh_rtc_platform_info {
diff --git a/arch/sh/include/asm/scatterlist.h b/arch/sh/include/asm/scatterlist.h
index 2084d0373693..c693d268a413 100644
--- a/arch/sh/include/asm/scatterlist.h
+++ b/arch/sh/include/asm/scatterlist.h
@@ -5,12 +5,13 @@
struct scatterlist {
#ifdef CONFIG_DEBUG_SG
- unsigned long sg_magic;
+ unsigned long sg_magic;
#endif
- unsigned long page_link;
- unsigned int offset;/* for highmem, page offset */
- dma_addr_t dma_address;
- unsigned int length;
+ unsigned long page_link;
+ unsigned int offset; /* for highmem, page offset */
+ unsigned int length;
+ dma_addr_t dma_address;
+ unsigned int dma_length;
};
#define ISA_DMA_THRESHOLD PHYS_ADDR_MASK
diff --git a/arch/sh/include/asm/swab.h b/arch/sh/include/asm/swab.h
index e69315935107..0e08fe54ad71 100644
--- a/arch/sh/include/asm/swab.h
+++ b/arch/sh/include/asm/swab.h
@@ -14,15 +14,15 @@ static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
{
__asm__(
#ifdef __SH5__
- "byterev %0, %0\n\t"
+ "byterev %1, %0\n\t"
"shari %0, 32, %0"
#else
- "swap.b %0, %0\n\t"
+ "swap.b %1, %0\n\t"
"swap.w %0, %0\n\t"
"swap.b %0, %0"
#endif
: "=r" (x)
- : "0" (x));
+ : "r" (x));
return x;
}
@@ -32,13 +32,13 @@ static inline __attribute_const__ __u16 __arch_swab16(__u16 x)
{
__asm__(
#ifdef __SH5__
- "byterev %0, %0\n\t"
+ "byterev %1, %0\n\t"
"shari %0, 32, %0"
#else
- "swap.b %0, %0"
+ "swap.b %1, %0"
#endif
: "=r" (x)
- : "0" (x));
+ : "r" (x));
return x;
}
diff --git a/arch/sh/include/asm/system_32.h b/arch/sh/include/asm/system_32.h
index 240b31e1142c..6c68a51f1cc5 100644
--- a/arch/sh/include/asm/system_32.h
+++ b/arch/sh/include/asm/system_32.h
@@ -198,7 +198,7 @@ do { \
})
#endif
-int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs,
+int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
struct mem_access *ma);
asmlinkage void do_address_error(struct pt_regs *regs,
diff --git a/arch/sh/include/asm/timer.h b/arch/sh/include/asm/timer.h
index 4c3b66e30af2..6c0851188c00 100644
--- a/arch/sh/include/asm/timer.h
+++ b/arch/sh/include/asm/timer.h
@@ -9,9 +9,6 @@ struct sys_timer_ops {
int (*init)(void);
int (*start)(void);
int (*stop)(void);
-#ifndef CONFIG_GENERIC_TIME
- unsigned long (*get_offset)(void);
-#endif
};
struct sys_timer {
@@ -21,24 +18,12 @@ struct sys_timer {
struct sys_timer_ops *ops;
};
-#define TICK_SIZE (tick_nsec / 1000)
-
-extern struct sys_timer tmu_timer, cmt_timer, mtu2_timer;
+extern struct sys_timer tmu_timer;
extern struct sys_timer *sys_timer;
-#ifndef CONFIG_GENERIC_TIME
-static inline unsigned long get_timer_offset(void)
-{
- return sys_timer->ops->get_offset();
-}
-#endif
-
/* arch/sh/kernel/timers/timer.c */
struct sys_timer *get_sys_timer(void);
-/* arch/sh/kernel/time.c */
-void handle_timer_tick(void);
-
extern struct clocksource clocksource_sh;
#endif /* __ASM_SH_TIMER_H */
diff --git a/arch/sh/include/asm/topology.h b/arch/sh/include/asm/topology.h
index a3f239545897..8489a0905a87 100644
--- a/arch/sh/include/asm/topology.h
+++ b/arch/sh/include/asm/topology.h
@@ -37,8 +37,11 @@
#define pcibus_to_node(bus) ((void)(bus), -1)
#define pcibus_to_cpumask(bus) (pcibus_to_node(bus) == -1 ? \
CPU_MASK_ALL : \
- node_to_cpumask(pcibus_to_node(bus)) \
- )
+ node_to_cpumask(pcibus_to_node(bus)))
+#define cpumask_of_pcibus(bus) (pcibus_to_node(bus) == -1 ? \
+ CPU_MASK_ALL_PTR : \
+ cpumask_of_node(pcibus_to_node(bus)))
+
#endif
#include <asm-generic/topology.h>
diff --git a/arch/sh/include/asm/types.h b/arch/sh/include/asm/types.h
index beea4e6f8dfd..b13caca62a76 100644
--- a/arch/sh/include/asm/types.h
+++ b/arch/sh/include/asm/types.h
@@ -23,9 +23,9 @@ typedef unsigned short umode_t;
typedef u32 dma_addr_t;
#ifdef CONFIG_SUPERH32
-typedef u16 opcode_t;
+typedef u16 insn_size_t;
#else
-typedef u32 opcode_t;
+typedef u32 insn_size_t;
#endif
#endif /* __ASSEMBLY__ */
diff --git a/arch/sh/include/asm/ubc.h b/arch/sh/include/asm/ubc.h
index a7b9028bbfbb..4ca4b7717371 100644
--- a/arch/sh/include/asm/ubc.h
+++ b/arch/sh/include/asm/ubc.h
@@ -42,12 +42,23 @@
#define BRCR_CMFA (1 << 15)
#define BRCR_CMFB (1 << 14)
+
+#if defined CONFIG_CPU_SH2A
+#define BRCR_CMFCA (1 << 15)
+#define BRCR_CMFCB (1 << 14)
+#define BRCR_CMFDA (1 << 13)
+#define BRCR_CMFDB (1 << 12)
+#define BRCR_PCBB (1 << 6) /* 1: after execution */
+#define BRCR_PCBA (1 << 5) /* 1: after execution */
+#define BRCR_PCTE 0
+#else
#define BRCR_PCTE (1 << 11)
#define BRCR_PCBA (1 << 10) /* 1: after execution */
#define BRCR_DBEB (1 << 7)
#define BRCR_PCBB (1 << 6)
#define BRCR_SEQ (1 << 3)
#define BRCR_UBDE (1 << 0)
+#endif
#ifndef __ASSEMBLY__
/* arch/sh/kernel/cpu/ubc.S */
diff --git a/arch/sh/include/asm/unistd_32.h b/arch/sh/include/asm/unistd_32.h
index d52c000cf924..2efb819e2db3 100644
--- a/arch/sh/include/asm/unistd_32.h
+++ b/arch/sh/include/asm/unistd_32.h
@@ -341,8 +341,10 @@
#define __NR_dup3 330
#define __NR_pipe2 331
#define __NR_inotify_init1 332
+#define __NR_preadv 333
+#define __NR_pwritev 334
-#define NR_syscalls 333
+#define NR_syscalls 335
#ifdef __KERNEL__
diff --git a/arch/sh/include/asm/unistd_64.h b/arch/sh/include/asm/unistd_64.h
index 7c54e91753c1..6eb9d2934c0f 100644
--- a/arch/sh/include/asm/unistd_64.h
+++ b/arch/sh/include/asm/unistd_64.h
@@ -381,10 +381,12 @@
#define __NR_dup3 358
#define __NR_pipe2 359
#define __NR_inotify_init1 360
+#define __NR_preadv 361
+#define __NR_pwritev 362
#ifdef __KERNEL__
-#define NR_syscalls 361
+#define NR_syscalls 363
#define __ARCH_WANT_IPC_PARSE_VERSION
#define __ARCH_WANT_OLD_READDIR
diff --git a/arch/sh/include/cpu-sh2a/cpu/ubc.h b/arch/sh/include/cpu-sh2a/cpu/ubc.h
index 8ce2fc1cf625..1192e1c761a7 100644
--- a/arch/sh/include/cpu-sh2a/cpu/ubc.h
+++ b/arch/sh/include/cpu-sh2a/cpu/ubc.h
@@ -1 +1,28 @@
-#include <cpu-sh2/cpu/ubc.h>
+/*
+ * SH-2A UBC definitions
+ *
+ * Copyright (C) 2008 Kieran Bingham
+ *
+ * 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_CPU_SH2A_UBC_H
+#define __ASM_CPU_SH2A_UBC_H
+
+#define UBC_BARA 0xfffc0400
+#define UBC_BAMRA 0xfffc0404
+#define UBC_BBRA 0xfffc04a0 /* 16 bit access */
+#define UBC_BDRA 0xfffc0408
+#define UBC_BDMRA 0xfffc040c
+
+#define UBC_BARB 0xfffc0410
+#define UBC_BAMRB 0xfffc0414
+#define UBC_BBRB 0xfffc04b0 /* 16 bit access */
+#define UBC_BDRB 0xfffc0418
+#define UBC_BDMRB 0xfffc041c
+
+#define UBC_BRCR 0xfffc04c0
+
+#endif /* __ASM_CPU_SH2A_UBC_H */
diff --git a/arch/sh/include/cpu-sh4/cpu/freq.h b/arch/sh/include/cpu-sh4/cpu/freq.h
index 749d1c434337..ccf1d999db6d 100644
--- a/arch/sh/include/cpu-sh4/cpu/freq.h
+++ b/arch/sh/include/cpu-sh4/cpu/freq.h
@@ -25,6 +25,24 @@
#elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \
defined(CONFIG_CPU_SUBTYPE_SH7780)
#define FRQCR 0xffc80000
+#elif defined(CONFIG_CPU_SUBTYPE_SH7724)
+#define FRQCRA 0xa4150000
+#define FRQCRB 0xa4150004
+#define VCLKCR 0xa4150048
+
+#define FCLKACR 0xa4150008
+#define FCLKBCR 0xa415000c
+#define FRQCR FRQCRA
+#define SCLKACR FCLKACR
+#define SCLKBCR FCLKBCR
+#define FCLKACR 0xa4150008
+#define FCLKBCR 0xa415000c
+#define IrDACLKCR 0xa4150018
+
+#define MSTPCR0 0xa4150030
+#define MSTPCR1 0xa4150034
+#define MSTPCR2 0xa4150038
+
#elif defined(CONFIG_CPU_SUBTYPE_SH7785)
#define FRQCR0 0xffc80000
#define FRQCR1 0xffc80004
diff --git a/arch/sh/include/cpu-sh4/cpu/sh7724.h b/arch/sh/include/cpu-sh4/cpu/sh7724.h
new file mode 100644
index 000000000000..34605c9e354d
--- /dev/null
+++ b/arch/sh/include/cpu-sh4/cpu/sh7724.h
@@ -0,0 +1,255 @@
+#ifndef __ASM_SH7724_H__
+#define __ASM_SH7724_H__
+
+enum {
+ /* PTA */
+ GPIO_PTA7, GPIO_PTA6, GPIO_PTA5, GPIO_PTA4,
+ GPIO_PTA3, GPIO_PTA2, GPIO_PTA1, GPIO_PTA0,
+
+ /* PTB */
+ GPIO_PTB7, GPIO_PTB6, GPIO_PTB5, GPIO_PTB4,
+ GPIO_PTB3, GPIO_PTB2, GPIO_PTB1, GPIO_PTB0,
+
+ /* PTC */
+ GPIO_PTC7, GPIO_PTC6, GPIO_PTC5, GPIO_PTC4,
+ GPIO_PTC3, GPIO_PTC2, GPIO_PTC1, GPIO_PTC0,
+
+ /* PTD */
+ GPIO_PTD7, GPIO_PTD6, GPIO_PTD5, GPIO_PTD4,
+ GPIO_PTD3, GPIO_PTD2, GPIO_PTD1, GPIO_PTD0,
+
+ /* PTE */
+ GPIO_PTE7, GPIO_PTE6, GPIO_PTE5, GPIO_PTE4,
+ GPIO_PTE3, GPIO_PTE2, GPIO_PTE1, GPIO_PTE0,
+
+ /* PTF */
+ GPIO_PTF7, GPIO_PTF6, GPIO_PTF5, GPIO_PTF4,
+ GPIO_PTF3, GPIO_PTF2, GPIO_PTF1, GPIO_PTF0,
+
+ /* PTG */
+ GPIO_PTG5, GPIO_PTG4,
+ GPIO_PTG3, GPIO_PTG2, GPIO_PTG1, GPIO_PTG0,
+
+ /* PTH */
+ GPIO_PTH7, GPIO_PTH6, GPIO_PTH5, GPIO_PTH4,
+ GPIO_PTH3, GPIO_PTH2, GPIO_PTH1, GPIO_PTH0,
+
+ /* PTJ */
+ GPIO_PTJ7, GPIO_PTJ6, GPIO_PTJ5,
+ GPIO_PTJ3, GPIO_PTJ2, GPIO_PTJ1, GPIO_PTJ0,
+
+ /* PTK */
+ GPIO_PTK7, GPIO_PTK6, GPIO_PTK5, GPIO_PTK4,
+ GPIO_PTK3, GPIO_PTK2, GPIO_PTK1, GPIO_PTK0,
+
+ /* PTL */
+ GPIO_PTL7, GPIO_PTL6, GPIO_PTL5, GPIO_PTL4,
+ GPIO_PTL3, GPIO_PTL2, GPIO_PTL1, GPIO_PTL0,
+
+ /* PTM */
+ GPIO_PTM7, GPIO_PTM6, GPIO_PTM5, GPIO_PTM4,
+ GPIO_PTM3, GPIO_PTM2, GPIO_PTM1, GPIO_PTM0,
+
+ /* PTN */
+ GPIO_PTN7, GPIO_PTN6, GPIO_PTN5, GPIO_PTN4,
+ GPIO_PTN3, GPIO_PTN2, GPIO_PTN1, GPIO_PTN0,
+
+ /* PTQ */
+ GPIO_PTQ7, GPIO_PTQ6, GPIO_PTQ5, GPIO_PTQ4,
+ GPIO_PTQ3, GPIO_PTQ2, GPIO_PTQ1, GPIO_PTQ0,
+
+ /* PTR */
+ GPIO_PTR7, GPIO_PTR6, GPIO_PTR5, GPIO_PTR4,
+ GPIO_PTR3, GPIO_PTR2, GPIO_PTR1, GPIO_PTR0,
+
+ /* PTS */
+ GPIO_PTS6, GPIO_PTS5, GPIO_PTS4,
+ GPIO_PTS3, GPIO_PTS2, GPIO_PTS1, GPIO_PTS0,
+
+ /* PTT */
+ GPIO_PTT7, GPIO_PTT6, GPIO_PTT5, GPIO_PTT4,
+ GPIO_PTT3, GPIO_PTT2, GPIO_PTT1, GPIO_PTT0,
+
+ /* PTU */
+ GPIO_PTU7, GPIO_PTU6, GPIO_PTU5, GPIO_PTU4,
+ GPIO_PTU3, GPIO_PTU2, GPIO_PTU1, GPIO_PTU0,
+
+ /* PTV */
+ GPIO_PTV7, GPIO_PTV6, GPIO_PTV5, GPIO_PTV4,
+ GPIO_PTV3, GPIO_PTV2, GPIO_PTV1, GPIO_PTV0,
+
+ /* PTW */
+ GPIO_PTW7, GPIO_PTW6, GPIO_PTW5, GPIO_PTW4,
+ GPIO_PTW3, GPIO_PTW2, GPIO_PTW1, GPIO_PTW0,
+
+ /* PTX */
+ GPIO_PTX7, GPIO_PTX6, GPIO_PTX5, GPIO_PTX4,
+ GPIO_PTX3, GPIO_PTX2, GPIO_PTX1, GPIO_PTX0,
+
+ /* PTY */
+ GPIO_PTY7, GPIO_PTY6, GPIO_PTY5, GPIO_PTY4,
+ GPIO_PTY3, GPIO_PTY2, GPIO_PTY1, GPIO_PTY0,
+
+ /* PTZ */
+ GPIO_PTZ7, GPIO_PTZ6, GPIO_PTZ5, GPIO_PTZ4,
+ GPIO_PTZ3, GPIO_PTZ2, GPIO_PTZ1, GPIO_PTZ0,
+
+ /* BSC (PTA/PTB/PTJ/PTQ/PTR/PTT) */
+ GPIO_FN_D31, GPIO_FN_D30, GPIO_FN_D29, GPIO_FN_D28,
+ GPIO_FN_D27, GPIO_FN_D26, GPIO_FN_D25, GPIO_FN_D24,
+ GPIO_FN_D23, GPIO_FN_D22, GPIO_FN_D21, GPIO_FN_D20,
+ GPIO_FN_D19, GPIO_FN_D18, GPIO_FN_D17, GPIO_FN_D16,
+ GPIO_FN_D15, GPIO_FN_D14, GPIO_FN_D13, GPIO_FN_D12,
+ GPIO_FN_D11, GPIO_FN_D10, GPIO_FN_D9, GPIO_FN_D8,
+ GPIO_FN_D7, GPIO_FN_D6, GPIO_FN_D5, GPIO_FN_D4,
+ GPIO_FN_D3, GPIO_FN_D2, GPIO_FN_D1, GPIO_FN_D0,
+ GPIO_FN_A25, GPIO_FN_A24, GPIO_FN_A23, GPIO_FN_A22,
+ GPIO_FN_CS6B_CE1B, GPIO_FN_CS6A_CE2B,
+ GPIO_FN_CS5B_CE1A, GPIO_FN_CS5A_CE2A,
+ GPIO_FN_WE3_ICIOWR, GPIO_FN_WE2_ICIORD,
+ GPIO_FN_IOIS16, GPIO_FN_WAIT,
+ GPIO_FN_BS,
+
+ /* KEYSC (PTA/PTB)*/
+ GPIO_FN_KEYOUT5_IN5, GPIO_FN_KEYOUT4_IN6, GPIO_FN_KEYIN4,
+ GPIO_FN_KEYIN3, GPIO_FN_KEYIN2, GPIO_FN_KEYIN1, GPIO_FN_KEYIN0,
+ GPIO_FN_KEYOUT3, GPIO_FN_KEYOUT2, GPIO_FN_KEYOUT1, GPIO_FN_KEYOUT0,
+
+ /* ATAPI (PTA/PTB/PTK/PTR/PTS/PTW) */
+ GPIO_FN_IDED15, GPIO_FN_IDED14, GPIO_FN_IDED13, GPIO_FN_IDED12,
+ GPIO_FN_IDED11, GPIO_FN_IDED10, GPIO_FN_IDED9, GPIO_FN_IDED8,
+ GPIO_FN_IDED7, GPIO_FN_IDED6, GPIO_FN_IDED5, GPIO_FN_IDED4,
+ GPIO_FN_IDED3, GPIO_FN_IDED2, GPIO_FN_IDED1, GPIO_FN_IDED0,
+ GPIO_FN_IDEA2, GPIO_FN_IDEA1, GPIO_FN_IDEA0, GPIO_FN_IDEIOWR,
+ GPIO_FN_IODREQ, GPIO_FN_IDECS0, GPIO_FN_IDECS1, GPIO_FN_IDEIORD,
+ GPIO_FN_DIRECTION, GPIO_FN_EXBUF_ENB, GPIO_FN_IDERST, GPIO_FN_IODACK,
+ GPIO_FN_IDEINT, GPIO_FN_IDEIORDY,
+
+ /* TPU (PTB/PTR/PTS) */
+ GPIO_FN_TPUTO3, GPIO_FN_TPUTO2, GPIO_FN_TPUTO1, GPIO_FN_TPUTO0,
+ GPIO_FN_TPUTI3, GPIO_FN_TPUTI2,
+
+ /* LCDC (PTC/PTD/PTE/PTF/PTM/PTR) */
+ GPIO_FN_LCDD23, GPIO_FN_LCDD22, GPIO_FN_LCDD21, GPIO_FN_LCDD20,
+ GPIO_FN_LCDD19, GPIO_FN_LCDD18, GPIO_FN_LCDD17, GPIO_FN_LCDD16,
+ GPIO_FN_LCDD15, GPIO_FN_LCDD14, GPIO_FN_LCDD13, GPIO_FN_LCDD12,
+ GPIO_FN_LCDD11, GPIO_FN_LCDD10, GPIO_FN_LCDD9, GPIO_FN_LCDD8,
+ GPIO_FN_LCDD7, GPIO_FN_LCDD6, GPIO_FN_LCDD5, GPIO_FN_LCDD4,
+ GPIO_FN_LCDD3, GPIO_FN_LCDD2, GPIO_FN_LCDD1, GPIO_FN_LCDD0,
+ GPIO_FN_LCDVSYN, GPIO_FN_LCDDISP, GPIO_FN_LCDRS, GPIO_FN_LCDHSYN,
+ GPIO_FN_LCDCS, GPIO_FN_LCDDON, GPIO_FN_LCDDCK, GPIO_FN_LCDWR,
+ GPIO_FN_LCDVEPWC, GPIO_FN_LCDVCPWC, GPIO_FN_LCDRD, GPIO_FN_LCDLCLK,
+
+ /* SCIF0 (PTF/PTM) */
+ GPIO_FN_SCIF0_TXD, GPIO_FN_SCIF0_RXD, GPIO_FN_SCIF0_SCK,
+
+ /* SCIF1 (PTL) */
+ GPIO_FN_SCIF1_SCK, GPIO_FN_SCIF1_RXD, GPIO_FN_SCIF1_TXD,
+
+ /* SCIF2 (PTE/PTF/PTN) with LCDC, VOU */
+ GPIO_FN_SCIF2_L_TXD, GPIO_FN_SCIF2_L_SCK, GPIO_FN_SCIF2_L_RXD,
+ GPIO_FN_SCIF2_V_TXD, GPIO_FN_SCIF2_V_SCK, GPIO_FN_SCIF2_V_RXD,
+
+ /* SCIF3 (PTL/PTN/PTZ) with VOU, IRQ */
+ GPIO_FN_SCIF3_V_SCK, GPIO_FN_SCIF3_V_RXD, GPIO_FN_SCIF3_V_TXD,
+ GPIO_FN_SCIF3_V_CTS, GPIO_FN_SCIF3_V_RTS,
+ GPIO_FN_SCIF3_I_SCK, GPIO_FN_SCIF3_I_RXD, GPIO_FN_SCIF3_I_TXD,
+ GPIO_FN_SCIF3_I_CTS, GPIO_FN_SCIF3_I_RTS,
+
+ /* SCIF4 (PTE) */
+ GPIO_FN_SCIF4_SCK, GPIO_FN_SCIF4_RXD, GPIO_FN_SCIF4_TXD,
+
+ /* SCIF5 (PTS) */
+ GPIO_FN_SCIF5_SCK, GPIO_FN_SCIF5_RXD, GPIO_FN_SCIF5_TXD,
+
+ /* FSI (PTE/PTU/PTV) */
+ GPIO_FN_FSIMCKB, GPIO_FN_FSIMCKA, GPIO_FN_FSIOASD,
+ GPIO_FN_FSIIABCK, GPIO_FN_FSIIALRCK, GPIO_FN_FSIOABCK,
+ GPIO_FN_FSIOALRCK, GPIO_FN_CLKAUDIOAO, GPIO_FN_FSIIBSD,
+ GPIO_FN_FSIOBSD, GPIO_FN_FSIIBBCK, GPIO_FN_FSIIBLRCK,
+ GPIO_FN_FSIOBBCK, GPIO_FN_FSIOBLRCK, GPIO_FN_CLKAUDIOBO,
+ GPIO_FN_FSIIASD,
+
+ /* AUD (PTG) */
+ GPIO_FN_AUDCK, GPIO_FN_AUDSYNC, GPIO_FN_AUDATA3,
+ GPIO_FN_AUDATA2, GPIO_FN_AUDATA1, GPIO_FN_AUDATA0,
+
+ /* VIO (PTS) (common?) */
+ GPIO_FN_VIO_CKO,
+
+ /* VIO0 (PTH/PTK) */
+ GPIO_FN_VIO0_D15, GPIO_FN_VIO0_D14, GPIO_FN_VIO0_D13, GPIO_FN_VIO0_D12,
+ GPIO_FN_VIO0_D11, GPIO_FN_VIO0_D10, GPIO_FN_VIO0_D9, GPIO_FN_VIO0_D8,
+ GPIO_FN_VIO0_D7, GPIO_FN_VIO0_D6, GPIO_FN_VIO0_D5, GPIO_FN_VIO0_D4,
+ GPIO_FN_VIO0_D3, GPIO_FN_VIO0_D2, GPIO_FN_VIO0_D1, GPIO_FN_VIO0_D0,
+ GPIO_FN_VIO0_VD, GPIO_FN_VIO0_CLK,
+ GPIO_FN_VIO0_FLD, GPIO_FN_VIO0_HD,
+
+ /* VIO1 (PTK/PTS) */
+ GPIO_FN_VIO1_D7, GPIO_FN_VIO1_D6, GPIO_FN_VIO1_D5, GPIO_FN_VIO1_D4,
+ GPIO_FN_VIO1_D3, GPIO_FN_VIO1_D2, GPIO_FN_VIO1_D1, GPIO_FN_VIO1_D0,
+ GPIO_FN_VIO1_FLD, GPIO_FN_VIO1_HD, GPIO_FN_VIO1_VD, GPIO_FN_VIO1_CLK,
+
+ /* Eth (PTL/PTN/PTX) */
+ GPIO_FN_RMII_RXD0, GPIO_FN_RMII_RXD1,
+ GPIO_FN_RMII_TXD0, GPIO_FN_RMII_TXD1,
+ GPIO_FN_RMII_REF_CLK, GPIO_FN_RMII_TX_EN,
+ GPIO_FN_RMII_RX_ER, GPIO_FN_RMII_CRS_DV,
+ GPIO_FN_LNKSTA, GPIO_FN_MDIO,
+ GPIO_FN_MDC,
+
+ /* System (PTJ) */
+ GPIO_FN_PDSTATUS, GPIO_FN_STATUS2, GPIO_FN_STATUS0,
+
+ /* VOU (PTL/PTM/PTN*/
+ GPIO_FN_DV_D15, GPIO_FN_DV_D14, GPIO_FN_DV_D13, GPIO_FN_DV_D12,
+ GPIO_FN_DV_D11, GPIO_FN_DV_D10, GPIO_FN_DV_D9, GPIO_FN_DV_D8,
+ GPIO_FN_DV_D7, GPIO_FN_DV_D6, GPIO_FN_DV_D5, GPIO_FN_DV_D4,
+ GPIO_FN_DV_D3, GPIO_FN_DV_D2, GPIO_FN_DV_D1, GPIO_FN_DV_D0,
+ GPIO_FN_DV_CLKI, GPIO_FN_DV_CLK, GPIO_FN_DV_VSYNC, GPIO_FN_DV_HSYNC,
+
+ /* MSIOF0 (PTL/PTM) */
+ GPIO_FN_MSIOF0_RXD, GPIO_FN_MSIOF0_TXD,
+ GPIO_FN_MSIOF0_MCK, GPIO_FN_MSIOF0_TSCK,
+ GPIO_FN_MSIOF0_SS1, GPIO_FN_MSIOF0_SS2,
+ GPIO_FN_MSIOF0_TSYNC, GPIO_FN_MSIOF0_RSCK,
+ GPIO_FN_MSIOF0_RSYNC,
+
+ /* MSIOF1 (PTV) */
+ GPIO_FN_MSIOF1_RXD, GPIO_FN_MSIOF1_TXD,
+ GPIO_FN_MSIOF1_MCK, GPIO_FN_MSIOF1_TSCK,
+ GPIO_FN_MSIOF1_SS1, GPIO_FN_MSIOF1_SS2,
+ GPIO_FN_MSIOF1_TSYNC, GPIO_FN_MSIOF1_RSCK,
+ GPIO_FN_MSIOF1_RSYNC,
+
+ /* DMAC (PTU/PTX) */
+ GPIO_FN_DMAC_DACK0, GPIO_FN_DMAC_DREQ0,
+ GPIO_FN_DMAC_DACK1, GPIO_FN_DMAC_DREQ1,
+
+ /* SDHI0 (PTY) */
+ GPIO_FN_SDHI0CD, GPIO_FN_SDHI0WP, GPIO_FN_SDHI0CMD, GPIO_FN_SDHI0CLK,
+ GPIO_FN_SDHI0D3, GPIO_FN_SDHI0D2, GPIO_FN_SDHI0D1, GPIO_FN_SDHI0D0,
+
+ /* SDHI1 (PTW) */
+ GPIO_FN_SDHI1CD, GPIO_FN_SDHI1WP, GPIO_FN_SDHI1CMD, GPIO_FN_SDHI1CLK,
+ GPIO_FN_SDHI1D3, GPIO_FN_SDHI1D2, GPIO_FN_SDHI1D1, GPIO_FN_SDHI1D0,
+
+ /* MMC (PTW/PTX)*/
+ GPIO_FN_MMC_D7, GPIO_FN_MMC_D6, GPIO_FN_MMC_D5, GPIO_FN_MMC_D4,
+ GPIO_FN_MMC_D3, GPIO_FN_MMC_D2, GPIO_FN_MMC_D1, GPIO_FN_MMC_D0,
+ GPIO_FN_MMC_CLK, GPIO_FN_MMC_CMD,
+
+ /* IrDA (PTX) */
+ GPIO_FN_IRDA_OUT, GPIO_FN_IRDA_IN,
+
+ /* TSIF (PTX) */
+ GPIO_FN_TSIF_TS0_SDAT, GPIO_FN_TSIF_TS0_SCK,
+ GPIO_FN_TSIF_TS0_SDEN, GPIO_FN_TSIF_TS0_SPSYNC,
+
+ /* IRQ (PTZ) */
+ GPIO_FN_INTC_IRQ7, GPIO_FN_INTC_IRQ6, GPIO_FN_INTC_IRQ5,
+ GPIO_FN_INTC_IRQ4, GPIO_FN_INTC_IRQ3, GPIO_FN_INTC_IRQ2,
+ GPIO_FN_INTC_IRQ1, GPIO_FN_INTC_IRQ0,
+};
+
+#endif /* __ASM_SH7724_H__ */
diff --git a/arch/sh/include/cpu-sh5/cpu/irq.h b/arch/sh/include/cpu-sh5/cpu/irq.h
index f0f0756e6e84..0ccf257a72d1 100644
--- a/arch/sh/include/cpu-sh5/cpu/irq.h
+++ b/arch/sh/include/cpu-sh5/cpu/irq.h
@@ -111,7 +111,6 @@
#define TOP_PRIORITY 15
extern int intc_evt_to_irq[(0xE20/0x20)+1];
-int intc_irq_describe(char* p, int irq);
extern int platform_int_priority[NR_INTC_IRQS];
#endif /* __ASM_SH_CPU_SH5_IRQ_H */
diff --git a/arch/sh/include/mach-common/mach/sh7785lcr.h b/arch/sh/include/mach-common/mach/sh7785lcr.h
index 1ce27d5c7491..90011d435f30 100644
--- a/arch/sh/include/mach-common/mach/sh7785lcr.h
+++ b/arch/sh/include/mach-common/mach/sh7785lcr.h
@@ -9,11 +9,11 @@
* -----------------------------+---------------+---------------
* 0x00000000 - 0x03ffffff(CS0) | NOR Flash | NOR Flash
* 0x04000000 - 0x05ffffff(CS1) | PLD | PLD
- * 0x06000000 - 0x07ffffff(CS1) | reserved | I2C
+ * 0x06000000 - 0x07ffffff(CS1) | I2C | I2C
* 0x08000000 - 0x0bffffff(CS2) | USB | DDR SDRAM
* 0x0c000000 - 0x0fffffff(CS3) | SD | DDR SDRAM
* 0x10000000 - 0x13ffffff(CS4) | SM107 | SM107
- * 0x14000000 - 0x17ffffff(CS5) | I2C | USB
+ * 0x14000000 - 0x17ffffff(CS5) | reserved | USB
* 0x18000000 - 0x1bffffff(CS6) | reserved | SD
* 0x40000000 - 0x5fffffff | DDR SDRAM | (cannot use)
*
@@ -32,6 +32,9 @@
#define PLD_VERSR (PLD_BASE_ADDR + 0x0c)
#define PLD_MMSR (PLD_BASE_ADDR + 0x0e)
+#define PCA9564_ADDR 0x06000000 /* I2C */
+#define PCA9564_SIZE 0x00000100
+
#define SM107_MEM_ADDR 0x10000000
#define SM107_MEM_SIZE 0x00e00000
#define SM107_REG_ADDR 0x13e00000
@@ -40,16 +43,13 @@
#if defined(CONFIG_SH_SH7785LCR_29BIT_PHYSMAPS)
#define R8A66597_ADDR 0x14000000 /* USB */
#define CG200_ADDR 0x18000000 /* SD */
-#define PCA9564_ADDR 0x06000000 /* I2C */
#else
#define R8A66597_ADDR 0x08000000
#define CG200_ADDR 0x0c000000
-#define PCA9564_ADDR 0x14000000
#endif
#define R8A66597_SIZE 0x00000100
#define CG200_SIZE 0x00010000
-#define PCA9564_SIZE 0x00000100
#endif /* __ASM_SH_RENESAS_SH7785LCR_H */
diff --git a/arch/sh/include/mach-dreamcast/mach/pci.h b/arch/sh/include/mach-dreamcast/mach/pci.h
index 75fc9009e092..0314d975e626 100644
--- a/arch/sh/include/mach-dreamcast/mach/pci.h
+++ b/arch/sh/include/mach-dreamcast/mach/pci.h
@@ -21,5 +21,7 @@
#define GAPSPCI_IRQ HW_EVENT_EXTERNAL
+extern struct pci_ops gapspci_pci_ops;
+
#endif /* __ASM_SH_DREAMCAST_PCI_H */
diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32
index 82a3a150c00d..aee08afe5ff7 100644
--- a/arch/sh/kernel/Makefile_32
+++ b/arch/sh/kernel/Makefile_32
@@ -11,7 +11,7 @@ endif
obj-y := debugtraps.o idle.o io.o io_generic.o irq.o \
machvec.o process_32.o ptrace_32.o setup.o signal_32.o \
- sys_sh.o sys_sh32.o syscalls_32.o time_32.o topology.o \
+ sys_sh.o sys_sh32.o syscalls_32.o time.o topology.o \
traps.o traps_32.o
obj-y += cpu/ timers/
@@ -32,4 +32,6 @@ obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
obj-$(CONFIG_DUMP_CODE) += disassemble.o
obj-$(CONFIG_HIBERNATION) += swsusp.o
+obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += localtimer.o
+
EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/kernel/Makefile_64 b/arch/sh/kernel/Makefile_64
index fe425d7f6871..c845a0d61979 100644
--- a/arch/sh/kernel/Makefile_64
+++ b/arch/sh/kernel/Makefile_64
@@ -2,19 +2,18 @@ extra-y := head_64.o init_task.o vmlinux.lds
obj-y := debugtraps.o idle.o io.o io_generic.o irq.o machvec.o process_64.o \
ptrace_64.o setup.o signal_64.o sys_sh.o sys_sh64.o \
- syscalls_64.o time_64.o topology.o traps.o traps_64.o
+ syscalls_64.o time.o topology.o traps.o traps_64.o
obj-y += cpu/ timers/
-obj-$(CONFIG_VSYSCALL) += vsyscall/
obj-$(CONFIG_SMP) += smp.o
-obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o
obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o
obj-$(CONFIG_MODULES) += sh_ksyms_64.o module.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
-obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_IO_TRAPPED) += io_trapped.o
obj-$(CONFIG_GENERIC_GPIO) += gpio.o
+obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += localtimer.o
+
EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c
index 1dc896483b59..133dbe403341 100644
--- a/arch/sh/kernel/cpu/clock.c
+++ b/arch/sh/kernel/cpu/clock.c
@@ -19,7 +19,6 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/list.h>
-#include <linux/kref.h>
#include <linux/kobject.h>
#include <linux/sysdev.h>
#include <linux/seq_file.h>
@@ -90,7 +89,7 @@ static void propagate_rate(struct clk *clk)
}
}
-static int __clk_enable(struct clk *clk)
+static void __clk_init(struct clk *clk)
{
/*
* See if this is the first time we're enabling the clock, some
@@ -99,17 +98,34 @@ static int __clk_enable(struct clk *clk)
* changes and the clock needs to hunt for the proper set of
* divisors to use before it can effectively recalc.
*/
- if (unlikely(atomic_read(&clk->kref.refcount) == 1))
+
+ if (clk->flags & CLK_NEEDS_INIT) {
if (clk->ops && clk->ops->init)
clk->ops->init(clk);
- kref_get(&clk->kref);
+ clk->flags &= ~CLK_NEEDS_INIT;
+ }
+}
+
+static int __clk_enable(struct clk *clk)
+{
+ if (!clk)
+ return -EINVAL;
+ clk->usecount++;
+
+ /* nothing to do if always enabled */
if (clk->flags & CLK_ALWAYS_ENABLED)
return 0;
- if (likely(clk->ops && clk->ops->enable))
- clk->ops->enable(clk);
+ if (clk->usecount == 1) {
+ __clk_init(clk);
+
+ __clk_enable(clk->parent);
+
+ if (clk->ops && clk->ops->enable)
+ clk->ops->enable(clk);
+ }
return 0;
}
@@ -119,11 +135,6 @@ int clk_enable(struct clk *clk)
unsigned long flags;
int ret;
- if (!clk)
- return -EINVAL;
-
- clk_enable(clk->parent);
-
spin_lock_irqsave(&clock_lock, flags);
ret = __clk_enable(clk);
spin_unlock_irqrestore(&clock_lock, flags);
@@ -132,21 +143,23 @@ int clk_enable(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_enable);
-static void clk_kref_release(struct kref *kref)
-{
- /* Nothing to do */
-}
-
static void __clk_disable(struct clk *clk)
{
- int count = kref_put(&clk->kref, clk_kref_release);
+ if (!clk)
+ return;
+
+ clk->usecount--;
+
+ WARN_ON(clk->usecount < 0);
if (clk->flags & CLK_ALWAYS_ENABLED)
return;
- if (!count) { /* count reaches zero, disable the clock */
+ if (clk->usecount == 0) {
if (likely(clk->ops && clk->ops->disable))
clk->ops->disable(clk);
+
+ __clk_disable(clk->parent);
}
}
@@ -154,14 +167,9 @@ void clk_disable(struct clk *clk)
{
unsigned long flags;
- if (!clk)
- return;
-
spin_lock_irqsave(&clock_lock, flags);
__clk_disable(clk);
spin_unlock_irqrestore(&clock_lock, flags);
-
- clk_disable(clk->parent);
}
EXPORT_SYMBOL_GPL(clk_disable);
@@ -170,14 +178,14 @@ int clk_register(struct clk *clk)
mutex_lock(&clock_list_sem);
list_add(&clk->node, &clock_list);
- kref_init(&clk->kref);
+ clk->usecount = 0;
+ clk->flags |= CLK_NEEDS_INIT;
mutex_unlock(&clock_list_sem);
if (clk->flags & CLK_ALWAYS_ENABLED) {
+ __clk_init(clk);
pr_debug( "Clock '%s' is ALWAYS_ENABLED\n", clk->name);
- if (clk->ops && clk->ops->init)
- clk->ops->init(clk);
if (clk->ops && clk->ops->enable)
clk->ops->enable(clk);
pr_debug( "Enabled.");
@@ -353,7 +361,7 @@ static int show_clocks(char *buf, char **start, off_t off,
p += sprintf(p, "%-12s\t: %ld.%02ldMHz\t%s\n", clk->name,
rate / 1000000, (rate % 1000000) / 10000,
((clk->flags & CLK_ALWAYS_ENABLED) ||
- (atomic_read(&clk->kref.refcount) != 1)) ?
+ clk->usecount > 0) ?
"enabled" : "disabled");
}
diff --git a/arch/sh/kernel/cpu/irq/imask.c b/arch/sh/kernel/cpu/irq/imask.c
index 301b505c4278..f43753b54e1d 100644
--- a/arch/sh/kernel/cpu/irq/imask.c
+++ b/arch/sh/kernel/cpu/irq/imask.c
@@ -39,7 +39,7 @@ static unsigned int startup_imask_irq(unsigned int irq)
return 0; /* never anything pending */
}
-static struct hw_interrupt_type imask_irq_type = {
+static struct irq_chip imask_irq_type = {
.typename = "SR.IMASK",
.startup = startup_imask_irq,
.shutdown = shutdown_imask_irq,
diff --git a/arch/sh/kernel/cpu/irq/intc-sh5.c b/arch/sh/kernel/cpu/irq/intc-sh5.c
index 726f0335da76..a619eaf6e6b4 100644
--- a/arch/sh/kernel/cpu/irq/intc-sh5.c
+++ b/arch/sh/kernel/cpu/irq/intc-sh5.c
@@ -84,7 +84,7 @@ static void disable_intc_irq(unsigned int irq);
static void mask_and_ack_intc(unsigned int);
static void end_intc_irq(unsigned int irq);
-static struct hw_interrupt_type intc_irq_type = {
+static struct irq_chip intc_irq_type = {
.typename = "INTC",
.startup = startup_intc_irq,
.shutdown = shutdown_intc_irq,
@@ -160,35 +160,13 @@ void make_intc_irq(unsigned int irq)
disable_intc_irq(irq);
}
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
-static int IRQ_to_vectorN[NR_INTC_IRQS] = {
- 0x12, 0x15, 0x18, 0x1B, 0x40, 0x41, 0x42, 0x43, /* 0- 7 */
- -1, -1, -1, -1, 0x50, 0x51, 0x52, 0x53, /* 8-15 */
- 0x54, 0x55, 0x32, 0x33, 0x34, 0x35, 0x36, -1, /* 16-23 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 24-31 */
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x38, /* 32-39 */
- 0x39, 0x3A, 0x3B, -1, -1, -1, -1, -1, /* 40-47 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 48-55 */
- -1, -1, -1, -1, -1, -1, -1, 0x2B, /* 56-63 */
-
-};
-
-int intc_irq_describe(char* p, int irq)
-{
- if (irq < NR_INTC_IRQS)
- return sprintf(p, "(0x%3x)", IRQ_to_vectorN[irq]*0x20);
- else
- return 0;
-}
-#endif
-
void __init plat_irq_setup(void)
{
unsigned long long __dummy0, __dummy1=~0x00000000100000f0;
unsigned long reg;
int i;
- intc_virt = onchip_remap(INTC_BASE, 1024, "INTC");
+ intc_virt = (unsigned long)ioremap_nocache(INTC_BASE, 1024);
if (!intc_virt) {
panic("Unable to remap INTC\n");
}
diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
index 0e32d8e448ca..94ac27fc2237 100644
--- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c
+++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
@@ -12,6 +12,8 @@
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
enum {
UNUSED = 0,
@@ -109,9 +111,75 @@ static struct platform_device eth_device = {
.resource = eth_resources,
};
+static struct sh_timer_config cmt0_platform_data = {
+ .name = "CMT0",
+ .channel_offset = 0x02,
+ .timer_bit = 0,
+ .clk = "module_clk",
+ .clockevent_rating = 125,
+ .clocksource_rating = 0, /* disabled due to code generation issues */
+};
+
+static struct resource cmt0_resources[] = {
+ [0] = {
+ .name = "CMT0",
+ .start = 0xf84a0072,
+ .end = 0xf84a0077,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 86,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device cmt0_device = {
+ .name = "sh_cmt",
+ .id = 0,
+ .dev = {
+ .platform_data = &cmt0_platform_data,
+ },
+ .resource = cmt0_resources,
+ .num_resources = ARRAY_SIZE(cmt0_resources),
+};
+
+static struct sh_timer_config cmt1_platform_data = {
+ .name = "CMT1",
+ .channel_offset = 0x08,
+ .timer_bit = 1,
+ .clk = "module_clk",
+ .clockevent_rating = 125,
+ .clocksource_rating = 0, /* disabled due to code generation issues */
+};
+
+static struct resource cmt1_resources[] = {
+ [0] = {
+ .name = "CMT1",
+ .start = 0xf84a0078,
+ .end = 0xf84a007d,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 87,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device cmt1_device = {
+ .name = "sh_cmt",
+ .id = 1,
+ .dev = {
+ .platform_data = &cmt1_platform_data,
+ },
+ .resource = cmt1_resources,
+ .num_resources = ARRAY_SIZE(cmt1_resources),
+};
+
static struct platform_device *sh7619_devices[] __initdata = {
&sci_device,
&eth_device,
+ &cmt0_device,
+ &cmt1_device,
};
static int __init sh7619_devices_setup(void)
@@ -125,3 +193,19 @@ void __init plat_irq_setup(void)
{
register_intc_controller(&intc_desc);
}
+
+static struct platform_device *sh7619_early_devices[] __initdata = {
+ &cmt0_device,
+ &cmt1_device,
+};
+
+#define STBCR3 0xf80a0000
+
+void __init plat_early_device_setup(void)
+{
+ /* enable CMT clock */
+ __raw_writeb(__raw_readb(STBCR3) & ~0x10, STBCR3);
+
+ early_platform_add_devices(sh7619_early_devices,
+ ARRAY_SIZE(sh7619_early_devices));
+}
diff --git a/arch/sh/kernel/cpu/sh2a/setup-mxg.c b/arch/sh/kernel/cpu/sh2a/setup-mxg.c
index 844293723cfc..a452d9649069 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-mxg.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-mxg.c
@@ -11,6 +11,7 @@
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
enum {
UNUSED = 0,
@@ -24,7 +25,7 @@ enum {
SCIF0, SCIF1,
- MTU2_GROUP1, MTU2_GROUP2, MTU2_GROUP3, MTU2_GROUP4, MTU2_GROUP5
+ MTU2_GROUP1, MTU2_GROUP2, MTU2_GROUP3, MTU2_GROUP4, MTU2_GROUP5,
MTU2_TGI3B, MTU2_TGI3C,
/* interrupt groups */
@@ -113,6 +114,99 @@ static struct intc_mask_reg mask_registers[] __initdata = {
static DECLARE_INTC_DESC(intc_desc, "mxg", vectors, groups,
mask_registers, prio_registers, NULL);
+static struct sh_timer_config mtu2_0_platform_data = {
+ .name = "MTU2_0",
+ .channel_offset = -0x80,
+ .timer_bit = 0,
+ .clk = "module_clk",
+ .clockevent_rating = 200,
+};
+
+static struct resource mtu2_0_resources[] = {
+ [0] = {
+ .name = "MTU2_0",
+ .start = 0xff801300,
+ .end = 0xff801326,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 228,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mtu2_0_device = {
+ .name = "sh_mtu2",
+ .id = 0,
+ .dev = {
+ .platform_data = &mtu2_0_platform_data,
+ },
+ .resource = mtu2_0_resources,
+ .num_resources = ARRAY_SIZE(mtu2_0_resources),
+};
+
+static struct sh_timer_config mtu2_1_platform_data = {
+ .name = "MTU2_1",
+ .channel_offset = -0x100,
+ .timer_bit = 1,
+ .clk = "module_clk",
+ .clockevent_rating = 200,
+};
+
+static struct resource mtu2_1_resources[] = {
+ [0] = {
+ .name = "MTU2_1",
+ .start = 0xff801380,
+ .end = 0xff801390,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 234,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mtu2_1_device = {
+ .name = "sh_mtu2",
+ .id = 1,
+ .dev = {
+ .platform_data = &mtu2_1_platform_data,
+ },
+ .resource = mtu2_1_resources,
+ .num_resources = ARRAY_SIZE(mtu2_1_resources),
+};
+
+static struct sh_timer_config mtu2_2_platform_data = {
+ .name = "MTU2_2",
+ .channel_offset = 0x80,
+ .timer_bit = 2,
+ .clk = "module_clk",
+ .clockevent_rating = 200,
+};
+
+static struct resource mtu2_2_resources[] = {
+ [0] = {
+ .name = "MTU2_2",
+ .start = 0xff801000,
+ .end = 0xff80100a,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 240,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mtu2_2_device = {
+ .name = "sh_mtu2",
+ .id = 2,
+ .dev = {
+ .platform_data = &mtu2_2_platform_data,
+ },
+ .resource = mtu2_2_resources,
+ .num_resources = ARRAY_SIZE(mtu2_2_resources),
+};
+
static struct plat_sci_port sci_platform_data[] = {
{
.mapbase = 0xff804000,
@@ -134,6 +228,9 @@ static struct platform_device sci_device = {
static struct platform_device *mxg_devices[] __initdata = {
&sci_device,
+ &mtu2_0_device,
+ &mtu2_1_device,
+ &mtu2_2_device,
};
static int __init mxg_devices_setup(void)
@@ -147,3 +244,15 @@ void __init plat_irq_setup(void)
{
register_intc_controller(&intc_desc);
}
+
+static struct platform_device *mxg_early_devices[] __initdata = {
+ &mtu2_0_device,
+ &mtu2_1_device,
+ &mtu2_2_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(mxg_early_devices,
+ ARRAY_SIZE(mxg_early_devices));
+}
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c
index 00f42f9e3f5c..772358b7685e 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c
@@ -12,6 +12,8 @@
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
enum {
UNUSED = 0,
@@ -249,9 +251,105 @@ static struct platform_device rtc_device = {
.resource = rtc_resources,
};
+static struct sh_timer_config mtu2_0_platform_data = {
+ .name = "MTU2_0",
+ .channel_offset = -0x80,
+ .timer_bit = 0,
+ .clk = "module_clk",
+ .clockevent_rating = 200,
+};
+
+static struct resource mtu2_0_resources[] = {
+ [0] = {
+ .name = "MTU2_0",
+ .start = 0xfffe4300,
+ .end = 0xfffe4326,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 108,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mtu2_0_device = {
+ .name = "sh_mtu2",
+ .id = 0,
+ .dev = {
+ .platform_data = &mtu2_0_platform_data,
+ },
+ .resource = mtu2_0_resources,
+ .num_resources = ARRAY_SIZE(mtu2_0_resources),
+};
+
+static struct sh_timer_config mtu2_1_platform_data = {
+ .name = "MTU2_1",
+ .channel_offset = -0x100,
+ .timer_bit = 1,
+ .clk = "module_clk",
+ .clockevent_rating = 200,
+};
+
+static struct resource mtu2_1_resources[] = {
+ [0] = {
+ .name = "MTU2_1",
+ .start = 0xfffe4380,
+ .end = 0xfffe4390,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 116,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mtu2_1_device = {
+ .name = "sh_mtu2",
+ .id = 1,
+ .dev = {
+ .platform_data = &mtu2_1_platform_data,
+ },
+ .resource = mtu2_1_resources,
+ .num_resources = ARRAY_SIZE(mtu2_1_resources),
+};
+
+static struct sh_timer_config mtu2_2_platform_data = {
+ .name = "MTU2_2",
+ .channel_offset = 0x80,
+ .timer_bit = 2,
+ .clk = "module_clk",
+ .clockevent_rating = 200,
+};
+
+static struct resource mtu2_2_resources[] = {
+ [0] = {
+ .name = "MTU2_2",
+ .start = 0xfffe4000,
+ .end = 0xfffe400a,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 124,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mtu2_2_device = {
+ .name = "sh_mtu2",
+ .id = 2,
+ .dev = {
+ .platform_data = &mtu2_2_platform_data,
+ },
+ .resource = mtu2_2_resources,
+ .num_resources = ARRAY_SIZE(mtu2_2_resources),
+};
+
static struct platform_device *sh7201_devices[] __initdata = {
&sci_device,
&rtc_device,
+ &mtu2_0_device,
+ &mtu2_1_device,
+ &mtu2_2_device,
};
static int __init sh7201_devices_setup(void)
@@ -265,3 +363,20 @@ void __init plat_irq_setup(void)
{
register_intc_controller(&intc_desc);
}
+
+static struct platform_device *sh7201_early_devices[] __initdata = {
+ &mtu2_0_device,
+ &mtu2_1_device,
+ &mtu2_2_device,
+};
+
+#define STBCR3 0xfffe0408
+
+void __init plat_early_device_setup(void)
+{
+ /* enable MTU2 clock */
+ __raw_writeb(__raw_readb(STBCR3) & ~0x20, STBCR3);
+
+ early_platform_add_devices(sh7201_early_devices,
+ ARRAY_SIZE(sh7201_early_devices));
+}
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
index 820dfb2e8656..d7493418ba60 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
@@ -11,6 +11,8 @@
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
enum {
UNUSED = 0,
@@ -205,6 +207,132 @@ static struct platform_device sci_device = {
},
};
+static struct sh_timer_config cmt0_platform_data = {
+ .name = "CMT0",
+ .channel_offset = 0x02,
+ .timer_bit = 0,
+ .clk = "module_clk",
+ .clockevent_rating = 125,
+ .clocksource_rating = 0, /* disabled due to code generation issues */
+};
+
+static struct resource cmt0_resources[] = {
+ [0] = {
+ .name = "CMT0",
+ .start = 0xfffec002,
+ .end = 0xfffec007,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 142,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device cmt0_device = {
+ .name = "sh_cmt",
+ .id = 0,
+ .dev = {
+ .platform_data = &cmt0_platform_data,
+ },
+ .resource = cmt0_resources,
+ .num_resources = ARRAY_SIZE(cmt0_resources),
+};
+
+static struct sh_timer_config cmt1_platform_data = {
+ .name = "CMT1",
+ .channel_offset = 0x08,
+ .timer_bit = 1,
+ .clk = "module_clk",
+ .clockevent_rating = 125,
+ .clocksource_rating = 0, /* disabled due to code generation issues */
+};
+
+static struct resource cmt1_resources[] = {
+ [0] = {
+ .name = "CMT1",
+ .start = 0xfffec008,
+ .end = 0xfffec00d,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 143,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device cmt1_device = {
+ .name = "sh_cmt",
+ .id = 1,
+ .dev = {
+ .platform_data = &cmt1_platform_data,
+ },
+ .resource = cmt1_resources,
+ .num_resources = ARRAY_SIZE(cmt1_resources),
+};
+
+static struct sh_timer_config mtu2_0_platform_data = {
+ .name = "MTU2_0",
+ .channel_offset = -0x80,
+ .timer_bit = 0,
+ .clk = "module_clk",
+ .clockevent_rating = 200,
+};
+
+static struct resource mtu2_0_resources[] = {
+ [0] = {
+ .name = "MTU2_0",
+ .start = 0xfffe4300,
+ .end = 0xfffe4326,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 146,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mtu2_0_device = {
+ .name = "sh_mtu2",
+ .id = 0,
+ .dev = {
+ .platform_data = &mtu2_0_platform_data,
+ },
+ .resource = mtu2_0_resources,
+ .num_resources = ARRAY_SIZE(mtu2_0_resources),
+};
+
+static struct sh_timer_config mtu2_1_platform_data = {
+ .name = "MTU2_1",
+ .channel_offset = -0x100,
+ .timer_bit = 1,
+ .clk = "module_clk",
+ .clockevent_rating = 200,
+};
+
+static struct resource mtu2_1_resources[] = {
+ [0] = {
+ .name = "MTU2_1",
+ .start = 0xfffe4380,
+ .end = 0xfffe4390,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 153,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mtu2_1_device = {
+ .name = "sh_mtu2",
+ .id = 1,
+ .dev = {
+ .platform_data = &mtu2_1_platform_data,
+ },
+ .resource = mtu2_1_resources,
+ .num_resources = ARRAY_SIZE(mtu2_1_resources),
+};
+
static struct resource rtc_resources[] = {
[0] = {
.start = 0xffff2000,
@@ -227,6 +355,10 @@ static struct platform_device rtc_device = {
static struct platform_device *sh7203_devices[] __initdata = {
&sci_device,
+ &cmt0_device,
+ &cmt1_device,
+ &mtu2_0_device,
+ &mtu2_1_device,
&rtc_device,
};
@@ -241,3 +373,25 @@ void __init plat_irq_setup(void)
{
register_intc_controller(&intc_desc);
}
+
+static struct platform_device *sh7203_early_devices[] __initdata = {
+ &cmt0_device,
+ &cmt1_device,
+ &mtu2_0_device,
+ &mtu2_1_device,
+};
+
+#define STBCR3 0xfffe0408
+#define STBCR4 0xfffe040c
+
+void __init plat_early_device_setup(void)
+{
+ /* enable CMT clock */
+ __raw_writeb(__raw_readb(STBCR4) & ~0x04, STBCR4);
+
+ /* enable MTU2 clock */
+ __raw_writeb(__raw_readb(STBCR3) & ~0x20, STBCR3);
+
+ early_platform_add_devices(sh7203_early_devices,
+ ARRAY_SIZE(sh7203_early_devices));
+}
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
index c46a8355726d..2fc6bff5c5fb 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
@@ -12,6 +12,8 @@
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
enum {
UNUSED = 0,
@@ -165,8 +167,170 @@ static struct platform_device sci_device = {
},
};
+static struct sh_timer_config cmt0_platform_data = {
+ .name = "CMT0",
+ .channel_offset = 0x02,
+ .timer_bit = 0,
+ .clk = "module_clk",
+ .clockevent_rating = 125,
+ .clocksource_rating = 0, /* disabled due to code generation issues */
+};
+
+static struct resource cmt0_resources[] = {
+ [0] = {
+ .name = "CMT0",
+ .start = 0xfffec002,
+ .end = 0xfffec007,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 140,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device cmt0_device = {
+ .name = "sh_cmt",
+ .id = 0,
+ .dev = {
+ .platform_data = &cmt0_platform_data,
+ },
+ .resource = cmt0_resources,
+ .num_resources = ARRAY_SIZE(cmt0_resources),
+};
+
+static struct sh_timer_config cmt1_platform_data = {
+ .name = "CMT1",
+ .channel_offset = 0x08,
+ .timer_bit = 1,
+ .clk = "module_clk",
+ .clockevent_rating = 125,
+ .clocksource_rating = 0, /* disabled due to code generation issues */
+};
+
+static struct resource cmt1_resources[] = {
+ [0] = {
+ .name = "CMT1",
+ .start = 0xfffec008,
+ .end = 0xfffec00d,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 144,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device cmt1_device = {
+ .name = "sh_cmt",
+ .id = 1,
+ .dev = {
+ .platform_data = &cmt1_platform_data,
+ },
+ .resource = cmt1_resources,
+ .num_resources = ARRAY_SIZE(cmt1_resources),
+};
+
+static struct sh_timer_config mtu2_0_platform_data = {
+ .name = "MTU2_0",
+ .channel_offset = -0x80,
+ .timer_bit = 0,
+ .clk = "module_clk",
+ .clockevent_rating = 200,
+};
+
+static struct resource mtu2_0_resources[] = {
+ [0] = {
+ .name = "MTU2_0",
+ .start = 0xfffe4300,
+ .end = 0xfffe4326,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 156,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mtu2_0_device = {
+ .name = "sh_mtu2",
+ .id = 0,
+ .dev = {
+ .platform_data = &mtu2_0_platform_data,
+ },
+ .resource = mtu2_0_resources,
+ .num_resources = ARRAY_SIZE(mtu2_0_resources),
+};
+
+static struct sh_timer_config mtu2_1_platform_data = {
+ .name = "MTU2_1",
+ .channel_offset = -0x100,
+ .timer_bit = 1,
+ .clk = "module_clk",
+ .clockevent_rating = 200,
+};
+
+static struct resource mtu2_1_resources[] = {
+ [0] = {
+ .name = "MTU2_1",
+ .start = 0xfffe4380,
+ .end = 0xfffe4390,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 164,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mtu2_1_device = {
+ .name = "sh_mtu2",
+ .id = 1,
+ .dev = {
+ .platform_data = &mtu2_1_platform_data,
+ },
+ .resource = mtu2_1_resources,
+ .num_resources = ARRAY_SIZE(mtu2_1_resources),
+};
+
+static struct sh_timer_config mtu2_2_platform_data = {
+ .name = "MTU2_2",
+ .channel_offset = 0x80,
+ .timer_bit = 2,
+ .clk = "module_clk",
+ .clockevent_rating = 200,
+};
+
+static struct resource mtu2_2_resources[] = {
+ [0] = {
+ .name = "MTU2_2",
+ .start = 0xfffe4000,
+ .end = 0xfffe400a,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 180,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mtu2_2_device = {
+ .name = "sh_mtu2",
+ .id = 2,
+ .dev = {
+ .platform_data = &mtu2_2_platform_data,
+ },
+ .resource = mtu2_2_resources,
+ .num_resources = ARRAY_SIZE(mtu2_2_resources),
+};
+
static struct platform_device *sh7206_devices[] __initdata = {
&sci_device,
+ &cmt0_device,
+ &cmt1_device,
+ &mtu2_0_device,
+ &mtu2_1_device,
+ &mtu2_2_device,
};
static int __init sh7206_devices_setup(void)
@@ -180,3 +344,26 @@ void __init plat_irq_setup(void)
{
register_intc_controller(&intc_desc);
}
+
+static struct platform_device *sh7206_early_devices[] __initdata = {
+ &cmt0_device,
+ &cmt1_device,
+ &mtu2_0_device,
+ &mtu2_1_device,
+ &mtu2_2_device,
+};
+
+#define STBCR3 0xfffe0408
+#define STBCR4 0xfffe040c
+
+void __init plat_early_device_setup(void)
+{
+ /* enable CMT clock */
+ __raw_writeb(__raw_readb(STBCR4) & ~0x04, STBCR4);
+
+ /* enable MTU2 clock */
+ __raw_writeb(__raw_readb(STBCR3) & ~0x20, STBCR3);
+
+ early_platform_add_devices(sh7206_early_devices,
+ ARRAY_SIZE(sh7206_early_devices));
+}
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index 91e3677ae09d..973ff831c8a8 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -156,6 +156,12 @@ int __init detect_cpu_and_cache_system(void)
break;
}
break;
+ case 0x300b:
+ boot_cpu_data.type = CPU_SH7724;
+ boot_cpu_data.icache.ways = 4;
+ boot_cpu_data.dcache.ways = 4;
+ boot_cpu_data.flags |= CPU_HAS_LLSC | CPU_HAS_FPU;
+ break;
case 0x4000: /* 1st cut */
case 0x4001: /* 2nd cut */
boot_cpu_data.type = CPU_SHX3;
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
index a1c80d909cd6..09da0c187d4c 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
@@ -12,6 +12,7 @@
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/io.h>
+#include <linux/sh_timer.h>
#include <linux/serial_sci.h>
static struct resource rtc_resources[] = {
@@ -60,9 +61,177 @@ static struct platform_device sci_device = {
},
};
+static struct sh_timer_config tmu0_platform_data = {
+ .name = "TMU0",
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clk = "module_clk",
+ .clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+ [0] = {
+ .name = "TMU0",
+ .start = 0xffd80008,
+ .end = 0xffd80013,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 16,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu0_device = {
+ .name = "sh_tmu",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu0_platform_data,
+ },
+ .resource = tmu0_resources,
+ .num_resources = ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+ .name = "TMU1",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clk = "module_clk",
+ .clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+ [0] = {
+ .name = "TMU1",
+ .start = 0xffd80014,
+ .end = 0xffd8001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 17,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu1_device = {
+ .name = "sh_tmu",
+ .id = 1,
+ .dev = {
+ .platform_data = &tmu1_platform_data,
+ },
+ .resource = tmu1_resources,
+ .num_resources = ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+ .name = "TMU2",
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+ .clk = "module_clk",
+};
+
+static struct resource tmu2_resources[] = {
+ [0] = {
+ .name = "TMU2",
+ .start = 0xffd80020,
+ .end = 0xffd8002f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 18,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu2_device = {
+ .name = "sh_tmu",
+ .id = 2,
+ .dev = {
+ .platform_data = &tmu2_platform_data,
+ },
+ .resource = tmu2_resources,
+ .num_resources = ARRAY_SIZE(tmu2_resources),
+};
+
+/* SH7750R, SH7751 and SH7751R all have two extra timer channels */
+#if defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751R)
+
+static struct sh_timer_config tmu3_platform_data = {
+ .name = "TMU3",
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clk = "module_clk",
+};
+
+static struct resource tmu3_resources[] = {
+ [0] = {
+ .name = "TMU3",
+ .start = 0xfe100008,
+ .end = 0xfe100013,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 72,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu3_device = {
+ .name = "sh_tmu",
+ .id = 3,
+ .dev = {
+ .platform_data = &tmu3_platform_data,
+ },
+ .resource = tmu3_resources,
+ .num_resources = ARRAY_SIZE(tmu3_resources),
+};
+
+static struct sh_timer_config tmu4_platform_data = {
+ .name = "TMU4",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clk = "module_clk",
+};
+
+static struct resource tmu4_resources[] = {
+ [0] = {
+ .name = "TMU4",
+ .start = 0xfe100014,
+ .end = 0xfe10001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 76,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu4_device = {
+ .name = "sh_tmu",
+ .id = 4,
+ .dev = {
+ .platform_data = &tmu4_platform_data,
+ },
+ .resource = tmu4_resources,
+ .num_resources = ARRAY_SIZE(tmu4_resources),
+};
+
+#endif
+
static struct platform_device *sh7750_devices[] __initdata = {
&rtc_device,
&sci_device,
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+#if defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751R)
+ &tmu3_device,
+ &tmu4_device,
+#endif
};
static int __init sh7750_devices_setup(void)
@@ -72,6 +241,24 @@ static int __init sh7750_devices_setup(void)
}
__initcall(sh7750_devices_setup);
+static struct platform_device *sh7750_early_devices[] __initdata = {
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+#if defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751R)
+ &tmu3_device,
+ &tmu4_device,
+#endif
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7750_early_devices,
+ ARRAY_SIZE(sh7750_early_devices));
+}
+
enum {
UNUSED = 0,
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
index d9bdc931ac09..cd097335758f 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
@@ -10,6 +10,7 @@
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/serial.h>
+#include <linux/sh_timer.h>
#include <linux/serial_sci.h>
#include <linux/io.h>
@@ -18,10 +19,7 @@ enum {
/* interrupt sources */
IRL0, IRL1, IRL2, IRL3,
- HUDI, GPIOI,
- DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3,
- DMAC_DMTE4, DMAC_DMTE5, DMAC_DMTE6, DMAC_DMTE7,
- DMAC_DMAE,
+ HUDI, GPIOI, DMAC,
IRQ4, IRQ5, IRQ6, IRQ7,
HCAN20, HCAN21,
SSI0, SSI1,
@@ -36,21 +34,20 @@ enum {
HSPI,
MMCIF0, MMCIF1, MMCIF2, MMCIF3,
MFI, ADC, CMT,
- TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
- WDT,
- REF_RCMI, REF_ROVI,
+ TMU0, TMU1, TMU2,
+ WDT, REF,
/* interrupt groups */
- DMAC, DMABRG, SCIF0, SCIF1, SCIF2, SIM, MMCIF, TMU2, REF,
+ DMABRG, SCIF0, SCIF1, SCIF2, SIM, MMCIF,
};
static struct intc_vect vectors[] __initdata = {
INTC_VECT(HUDI, 0x600), INTC_VECT(GPIOI, 0x620),
- INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
- INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
- INTC_VECT(DMAC_DMTE4, 0x780), INTC_VECT(DMAC_DMTE5, 0x7a0),
- INTC_VECT(DMAC_DMTE6, 0x7c0), INTC_VECT(DMAC_DMTE7, 0x7e0),
- INTC_VECT(DMAC_DMAE, 0x6c0),
+ INTC_VECT(DMAC, 0x640), INTC_VECT(DMAC, 0x660),
+ INTC_VECT(DMAC, 0x680), INTC_VECT(DMAC, 0x6a0),
+ INTC_VECT(DMAC, 0x780), INTC_VECT(DMAC, 0x7a0),
+ INTC_VECT(DMAC, 0x7c0), INTC_VECT(DMAC, 0x7e0),
+ INTC_VECT(DMAC, 0x6c0),
INTC_VECT(IRQ4, 0x800), INTC_VECT(IRQ5, 0x820),
INTC_VECT(IRQ6, 0x840), INTC_VECT(IRQ6, 0x860),
INTC_VECT(HCAN20, 0x900), INTC_VECT(HCAN21, 0x920),
@@ -74,23 +71,18 @@ static struct intc_vect vectors[] __initdata = {
INTC_VECT(MFI, 0xe80), /* 0xf80 according to data sheet */
INTC_VECT(ADC, 0xf80), INTC_VECT(CMT, 0xfa0),
INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
- INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
+ INTC_VECT(TMU2, 0x440), INTC_VECT(TMU2, 0x460),
INTC_VECT(WDT, 0x560),
- INTC_VECT(REF_RCMI, 0x580), INTC_VECT(REF_ROVI, 0x5a0),
+ INTC_VECT(REF, 0x580), INTC_VECT(REF, 0x5a0),
};
static struct intc_group groups[] __initdata = {
- INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
- DMAC_DMTE3, DMAC_DMTE4, DMAC_DMTE5,
- DMAC_DMTE6, DMAC_DMTE7, DMAC_DMAE),
INTC_GROUP(DMABRG, DMABRG0, DMABRG1, DMABRG2),
INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI),
INTC_GROUP(SCIF1, SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI),
INTC_GROUP(SCIF2, SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI),
INTC_GROUP(SIM, SIM_ERI, SIM_RXI, SIM_TXI, SIM_TEI),
INTC_GROUP(MMCIF, MMCIF0, MMCIF1, MMCIF2, MMCIF3),
- INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
- INTC_GROUP(REF, REF_RCMI, REF_ROVI),
};
static struct intc_mask_reg mask_registers[] __initdata = {
@@ -168,8 +160,104 @@ static struct platform_device sci_device = {
},
};
+static struct sh_timer_config tmu0_platform_data = {
+ .name = "TMU0",
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clk = "module_clk",
+ .clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+ [0] = {
+ .name = "TMU0",
+ .start = 0xffd80008,
+ .end = 0xffd80013,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 16,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu0_device = {
+ .name = "sh_tmu",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu0_platform_data,
+ },
+ .resource = tmu0_resources,
+ .num_resources = ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+ .name = "TMU1",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clk = "module_clk",
+ .clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+ [0] = {
+ .name = "TMU1",
+ .start = 0xffd80014,
+ .end = 0xffd8001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 17,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu1_device = {
+ .name = "sh_tmu",
+ .id = 1,
+ .dev = {
+ .platform_data = &tmu1_platform_data,
+ },
+ .resource = tmu1_resources,
+ .num_resources = ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+ .name = "TMU2",
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+ .clk = "module_clk",
+};
+
+static struct resource tmu2_resources[] = {
+ [0] = {
+ .name = "TMU2",
+ .start = 0xffd80020,
+ .end = 0xffd8002f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 18,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu2_device = {
+ .name = "sh_tmu",
+ .id = 2,
+ .dev = {
+ .platform_data = &tmu2_platform_data,
+ },
+ .resource = tmu2_resources,
+ .num_resources = ARRAY_SIZE(tmu2_resources),
+};
+
+
static struct platform_device *sh7760_devices[] __initdata = {
&sci_device,
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
};
static int __init sh7760_devices_setup(void)
@@ -179,6 +267,18 @@ static int __init sh7760_devices_setup(void)
}
__initcall(sh7760_devices_setup);
+static struct platform_device *sh7760_early_devices[] __initdata = {
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7760_early_devices,
+ ARRAY_SIZE(sh7760_early_devices));
+}
+
#define INTC_ICR 0xffd00000UL
#define INTC_ICR_IRLM (1 << 7)
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
index 1a92361feeb9..afd6fba47849 100644
--- a/arch/sh/kernel/cpu/sh4a/Makefile
+++ b/arch/sh/kernel/cpu/sh4a/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7786) += setup-sh7786.o
obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o
obj-$(CONFIG_CPU_SUBTYPE_SH7722) += setup-sh7722.o
obj-$(CONFIG_CPU_SUBTYPE_SH7723) += setup-sh7723.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7724) += setup-sh7724.o
obj-$(CONFIG_CPU_SUBTYPE_SH7366) += setup-sh7366.o
obj-$(CONFIG_CPU_SUBTYPE_SHX3) += setup-shx3.o
@@ -26,12 +27,14 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7786) := clock-sh7786.o
clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7722.o
clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o
clock-$(CONFIG_CPU_SUBTYPE_SH7723) := clock-sh7722.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7724) := clock-sh7722.o
clock-$(CONFIG_CPU_SUBTYPE_SH7366) := clock-sh7722.o
clock-$(CONFIG_CPU_SUBTYPE_SHX3) := clock-shx3.o
# Pinmux setup
pinmux-$(CONFIG_CPU_SUBTYPE_SH7722) := pinmux-sh7722.o
pinmux-$(CONFIG_CPU_SUBTYPE_SH7723) := pinmux-sh7723.o
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7724) := pinmux-sh7724.o
pinmux-$(CONFIG_CPU_SUBTYPE_SH7785) := pinmux-sh7785.o
pinmux-$(CONFIG_CPU_SUBTYPE_SH7786) := pinmux-sh7786.o
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
index 0e174af21874..1ccdfc561fef 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
@@ -130,6 +130,12 @@ static void adjust_clocks(int originate, int *l, unsigned long v[],
* is quite simple..
*/
+#if defined(CONFIG_CPU_SUBTYPE_SH7724)
+#define STCPLL(frqcr) ((((frqcr >> 24) & 0x3f) + 1) * 2)
+#else
+#define STCPLL(frqcr) (((frqcr >> 24) & 0x1f) + 1)
+#endif
+
/*
* Instead of having two separate multipliers/divisors set, like this:
*
@@ -139,13 +145,17 @@ static void adjust_clocks(int originate, int *l, unsigned long v[],
* I created the divisors2 array, which is used to calculate rate like
* rate = parent * 2 / divisors2[ divisor ];
*/
+#if defined(CONFIG_CPU_SUBTYPE_SH7724)
+static int divisors2[] = { 4, 1, 8, 12, 16, 24, 32, 1, 48, 64, 72, 96, 1, 144 };
+#else
static int divisors2[] = { 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40 };
+#endif
static void master_clk_recalc(struct clk *clk)
{
unsigned frqcr = ctrl_inl(FRQCR);
- clk->rate = CONFIG_SH_PCLK_FREQ * (((frqcr >> 24) & 0x1f) + 1);
+ clk->rate = CONFIG_SH_PCLK_FREQ * STCPLL(frqcr);
}
static void master_clk_init(struct clk *clk)
@@ -161,13 +171,30 @@ static void module_clk_recalc(struct clk *clk)
{
unsigned long frqcr = ctrl_inl(FRQCR);
- clk->rate = clk->parent->rate / (((frqcr >> 24) & 0x1f) + 1);
+ clk->rate = clk->parent->rate / STCPLL(frqcr);
}
+#if defined(CONFIG_CPU_SUBTYPE_SH7724)
+#define MASTERDIVS { 12, 16, 24, 30, 32, 36, 48 }
+#define STCMASK 0x3f
+#define DIVCALC(div) (div/2-1)
+#define FRQCRKICK 0x80000000
+#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
+#define MASTERDIVS { 6, 8, 12, 16 }
+#define STCMASK 0x1f
+#define DIVCALC(div) (div-1)
+#define FRQCRKICK 0x00000000
+#else
+#define MASTERDIVS { 2, 3, 4, 6, 8, 16 }
+#define STCMASK 0x1f
+#define DIVCALC(div) (div-1)
+#define FRQCRKICK 0x00000000
+#endif
+
static int master_clk_setrate(struct clk *clk, unsigned long rate, int id)
{
int div = rate / clk->rate;
- int master_divs[] = { 2, 3, 4, 6, 8, 16 };
+ int master_divs[] = MASTERDIVS;
int index;
unsigned long frqcr;
@@ -180,8 +207,9 @@ static int master_clk_setrate(struct clk *clk, unsigned long rate, int id)
div = master_divs[index - 1];
frqcr = ctrl_inl(FRQCR);
- frqcr &= ~(0xF << 24);
- frqcr |= ( (div-1) << 24);
+ frqcr &= ~(STCMASK << 24);
+ frqcr |= (DIVCALC(div) << 24);
+ frqcr |= FRQCRKICK;
ctrl_outl(frqcr, FRQCR);
return 0;
@@ -377,6 +405,7 @@ static int sh7722_frqcr_set_rate(struct clk *clk, unsigned long rate,
/* clear FRQCR bits */
frqcr &= ~(ctx.mask << ctx.shift);
frqcr |= div << ctx.shift;
+ frqcr |= FRQCRKICK;
/* ...and perform actual change */
ctrl_outl(frqcr, FRQCR);
@@ -542,8 +571,8 @@ static struct clk sh7722_r_clock = {
.flags = CLK_RATE_PROPAGATES,
};
-#ifndef CONFIG_CPU_SUBTYPE_SH7343
-
+#if !defined(CONFIG_CPU_SUBTYPE_SH7343) &&\
+ !defined(CONFIG_CPU_SUBTYPE_SH7724)
/*
* these three clocks - SIU A, SIU B, IrDA - share the same clk_ops
* methods of clk_ops determine which register they should access by
@@ -560,15 +589,16 @@ static struct clk sh7722_siu_b_clock = {
.arch_flags = SCLKBCR,
.ops = &sh7722_siu_clk_ops,
};
+#endif /* CONFIG_CPU_SUBTYPE_SH7343, SH7724 */
-#if defined(CONFIG_CPU_SUBTYPE_SH7722)
+#if defined(CONFIG_CPU_SUBTYPE_SH7722) ||\
+ defined(CONFIG_CPU_SUBTYPE_SH7724)
static struct clk sh7722_irda_clock = {
.name = "irda_clk",
.arch_flags = IrDACLKCR,
.ops = &sh7722_siu_clk_ops,
};
#endif
-#endif /* CONFIG_CPU_SUBTYPE_SH7343 */
static struct clk sh7722_video_clock = {
.name = "video_clk",
@@ -715,6 +745,61 @@ static struct clk sh7722_mstpcr_clocks[] = {
MSTPCR("vpu0", "bus_clk", 2, 1),
MSTPCR("lcdc0", "bus_clk", 2, 0),
#endif
+#if defined(CONFIG_CPU_SUBTYPE_SH7724)
+ /* See Datasheet : Overview -> Block Diagram */
+ MSTPCR("tlb0", "cpu_clk", 0, 31),
+ MSTPCR("ic0", "cpu_clk", 0, 30),
+ MSTPCR("oc0", "cpu_clk", 0, 29),
+ MSTPCR("rs0", "bus_clk", 0, 28),
+ MSTPCR("ilmem0", "cpu_clk", 0, 27),
+ MSTPCR("l2c0", "sh_clk", 0, 26),
+ MSTPCR("fpu0", "cpu_clk", 0, 24),
+ MSTPCR("intc0", "peripheral_clk", 0, 22),
+ MSTPCR("dmac0", "bus_clk", 0, 21),
+ MSTPCR("sh0", "sh_clk", 0, 20),
+ MSTPCR("hudi0", "peripheral_clk", 0, 19),
+ MSTPCR("ubc0", "cpu_clk", 0, 17),
+ MSTPCR("tmu0", "peripheral_clk", 0, 15),
+ MSTPCR("cmt0", "r_clk", 0, 14),
+ MSTPCR("rwdt0", "r_clk", 0, 13),
+ MSTPCR("dmac1", "bus_clk", 0, 12),
+ MSTPCR("tmu1", "peripheral_clk", 0, 10),
+ MSTPCR("scif0", "peripheral_clk", 0, 9),
+ MSTPCR("scif1", "peripheral_clk", 0, 8),
+ MSTPCR("scif2", "peripheral_clk", 0, 7),
+ MSTPCR("scif3", "bus_clk", 0, 6),
+ MSTPCR("scif4", "bus_clk", 0, 5),
+ MSTPCR("scif5", "bus_clk", 0, 4),
+ MSTPCR("msiof0", "bus_clk", 0, 2),
+ MSTPCR("msiof1", "bus_clk", 0, 1),
+ MSTPCR("keysc0", "r_clk", 1, 12),
+ MSTPCR("rtc0", "r_clk", 1, 11),
+ MSTPCR("i2c0", "peripheral_clk", 1, 9),
+ MSTPCR("i2c1", "peripheral_clk", 1, 8),
+ MSTPCR("mmc0", "bus_clk", 2, 29),
+ MSTPCR("eth0", "bus_clk", 2, 28),
+ MSTPCR("atapi0", "bus_clk", 2, 26),
+ MSTPCR("tpu0", "bus_clk", 2, 25),
+ MSTPCR("irda0", "peripheral_clk", 2, 24),
+ MSTPCR("tsif0", "bus_clk", 2, 22),
+ MSTPCR("usb1", "bus_clk", 2, 21),
+ MSTPCR("usb0", "bus_clk", 2, 20),
+ MSTPCR("2dg0", "bus_clk", 2, 19),
+ MSTPCR("sdhi0", "bus_clk", 2, 18),
+ MSTPCR("sdhi1", "bus_clk", 2, 17),
+ MSTPCR("veu1", "bus_clk", 2, 15),
+ MSTPCR("ceu1", "bus_clk", 2, 13),
+ MSTPCR("beu1", "bus_clk", 2, 12),
+ MSTPCR("2ddmac0", "sh_clk", 2, 10),
+ MSTPCR("spu0", "bus_clk", 2, 9),
+ MSTPCR("jpu0", "bus_clk", 2, 6),
+ MSTPCR("vou0", "bus_clk", 2, 5),
+ MSTPCR("beu0", "bus_clk", 2, 4),
+ MSTPCR("ceu0", "bus_clk", 2, 3),
+ MSTPCR("veu0", "bus_clk", 2, 2),
+ MSTPCR("vpu0", "bus_clk", 2, 1),
+ MSTPCR("lcdc0", "bus_clk", 2, 0),
+#endif
#if defined(CONFIG_CPU_SUBTYPE_SH7343)
MSTPCR("uram0", "umem_clk", 0, 28),
MSTPCR("xymem0", "bus_clk", 0, 26),
@@ -786,12 +871,15 @@ static struct clk *sh7722_clocks[] = {
&sh7722_sh_clock,
&sh7722_peripheral_clock,
&sh7722_sdram_clock,
-#ifndef CONFIG_CPU_SUBTYPE_SH7343
+#if !defined(CONFIG_CPU_SUBTYPE_SH7343) &&\
+ !defined(CONFIG_CPU_SUBTYPE_SH7724)
&sh7722_siu_a_clock,
&sh7722_siu_b_clock,
-#if defined(CONFIG_CPU_SUBTYPE_SH7722)
- &sh7722_irda_clock,
#endif
+/* 7724 should support FSI clock */
+#if defined(CONFIG_CPU_SUBTYPE_SH7722) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7724)
+ &sh7722_irda_clock,
#endif
&sh7722_video_clock,
};
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7724.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7724.c
new file mode 100644
index 000000000000..1af0f9586379
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/pinmux-sh7724.c
@@ -0,0 +1,2230 @@
+/*
+ * SH7724 Pinmux
+ *
+ * Copyright (C) 2009 Renesas Solutions Corp.
+ *
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on SH7723 Pinmux
+ * Copyright (C) 2008 Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <cpu/sh7724.h>
+
+enum {
+ PINMUX_RESERVED = 0,
+
+ PINMUX_DATA_BEGIN,
+ PTA7_DATA, PTA6_DATA, PTA5_DATA, PTA4_DATA,
+ PTA3_DATA, PTA2_DATA, PTA1_DATA, PTA0_DATA,
+ PTB7_DATA, PTB6_DATA, PTB5_DATA, PTB4_DATA,
+ PTB3_DATA, PTB2_DATA, PTB1_DATA, PTB0_DATA,
+ PTC7_DATA, PTC6_DATA, PTC5_DATA, PTC4_DATA,
+ PTC3_DATA, PTC2_DATA, PTC1_DATA, PTC0_DATA,
+ PTD7_DATA, PTD6_DATA, PTD5_DATA, PTD4_DATA,
+ PTD3_DATA, PTD2_DATA, PTD1_DATA, PTD0_DATA,
+ PTE7_DATA, PTE6_DATA, PTE5_DATA, PTE4_DATA,
+ PTE3_DATA, PTE2_DATA, PTE1_DATA, PTE0_DATA,
+ PTF7_DATA, PTF6_DATA, PTF5_DATA, PTF4_DATA,
+ PTF3_DATA, PTF2_DATA, PTF1_DATA, PTF0_DATA,
+ PTG5_DATA, PTG4_DATA,
+ PTG3_DATA, PTG2_DATA, PTG1_DATA, PTG0_DATA,
+ PTH7_DATA, PTH6_DATA, PTH5_DATA, PTH4_DATA,
+ PTH3_DATA, PTH2_DATA, PTH1_DATA, PTH0_DATA,
+ PTJ7_DATA, PTJ6_DATA, PTJ5_DATA,
+ PTJ3_DATA, PTJ2_DATA, PTJ1_DATA, PTJ0_DATA,
+ PTK7_DATA, PTK6_DATA, PTK5_DATA, PTK4_DATA,
+ PTK3_DATA, PTK2_DATA, PTK1_DATA, PTK0_DATA,
+ PTL7_DATA, PTL6_DATA, PTL5_DATA, PTL4_DATA,
+ PTL3_DATA, PTL2_DATA, PTL1_DATA, PTL0_DATA,
+ PTM7_DATA, PTM6_DATA, PTM5_DATA, PTM4_DATA,
+ PTM3_DATA, PTM2_DATA, PTM1_DATA, PTM0_DATA,
+ PTN7_DATA, PTN6_DATA, PTN5_DATA, PTN4_DATA,
+ PTN3_DATA, PTN2_DATA, PTN1_DATA, PTN0_DATA,
+ PTQ7_DATA, PTQ6_DATA, PTQ5_DATA, PTQ4_DATA,
+ PTQ3_DATA, PTQ2_DATA, PTQ1_DATA, PTQ0_DATA,
+ PTR7_DATA, PTR6_DATA, PTR5_DATA, PTR4_DATA,
+ PTR3_DATA, PTR2_DATA, PTR1_DATA, PTR0_DATA,
+ PTS6_DATA, PTS5_DATA, PTS4_DATA,
+ PTS3_DATA, PTS2_DATA, PTS1_DATA, PTS0_DATA,
+ PTT7_DATA, PTT6_DATA, PTT5_DATA, PTT4_DATA,
+ PTT3_DATA, PTT2_DATA, PTT1_DATA, PTT0_DATA,
+ PTU7_DATA, PTU6_DATA, PTU5_DATA, PTU4_DATA,
+ PTU3_DATA, PTU2_DATA, PTU1_DATA, PTU0_DATA,
+ PTV7_DATA, PTV6_DATA, PTV5_DATA, PTV4_DATA,
+ PTV3_DATA, PTV2_DATA, PTV1_DATA, PTV0_DATA,
+ PTW7_DATA, PTW6_DATA, PTW5_DATA, PTW4_DATA,
+ PTW3_DATA, PTW2_DATA, PTW1_DATA, PTW0_DATA,
+ PTX7_DATA, PTX6_DATA, PTX5_DATA, PTX4_DATA,
+ PTX3_DATA, PTX2_DATA, PTX1_DATA, PTX0_DATA,
+ PTY7_DATA, PTY6_DATA, PTY5_DATA, PTY4_DATA,
+ PTY3_DATA, PTY2_DATA, PTY1_DATA, PTY0_DATA,
+ PTZ7_DATA, PTZ6_DATA, PTZ5_DATA, PTZ4_DATA,
+ PTZ3_DATA, PTZ2_DATA, PTZ1_DATA, PTZ0_DATA,
+ PINMUX_DATA_END,
+
+ PINMUX_INPUT_BEGIN,
+ PTA7_IN, PTA6_IN, PTA5_IN, PTA4_IN,
+ PTA3_IN, PTA2_IN, PTA1_IN, PTA0_IN,
+ PTB7_IN, PTB6_IN, PTB5_IN, PTB4_IN,
+ PTB3_IN, PTB2_IN, PTB1_IN, PTB0_IN,
+ PTC7_IN, PTC6_IN, PTC5_IN, PTC4_IN,
+ PTC3_IN, PTC2_IN, PTC1_IN, PTC0_IN,
+ PTD7_IN, PTD6_IN, PTD5_IN, PTD4_IN,
+ PTD3_IN, PTD2_IN, PTD1_IN, PTD0_IN,
+ PTE7_IN, PTE6_IN, PTE5_IN, PTE4_IN,
+ PTE3_IN, PTE2_IN, PTE1_IN, PTE0_IN,
+ PTF7_IN, PTF6_IN, PTF5_IN, PTF4_IN,
+ PTF3_IN, PTF2_IN, PTF1_IN, PTF0_IN,
+ PTH7_IN, PTH6_IN, PTH5_IN, PTH4_IN,
+ PTH3_IN, PTH2_IN, PTH1_IN, PTH0_IN,
+ PTJ3_IN, PTJ2_IN, PTJ1_IN, PTJ0_IN,
+ PTK7_IN, PTK6_IN, PTK5_IN, PTK4_IN,
+ PTK3_IN, PTK2_IN, PTK1_IN, PTK0_IN,
+ PTL7_IN, PTL6_IN, PTL5_IN, PTL4_IN,
+ PTL3_IN, PTL2_IN, PTL1_IN, PTL0_IN,
+ PTM7_IN, PTM6_IN, PTM5_IN, PTM4_IN,
+ PTM3_IN, PTM2_IN, PTM1_IN, PTM0_IN,
+ PTN7_IN, PTN6_IN, PTN5_IN, PTN4_IN,
+ PTN3_IN, PTN2_IN, PTN1_IN, PTN0_IN,
+ PTQ7_IN, PTQ6_IN, PTQ5_IN, PTQ4_IN,
+ PTQ3_IN, PTQ2_IN, PTQ1_IN, PTQ0_IN,
+ PTR7_IN, PTR6_IN, PTR5_IN, PTR4_IN,
+ PTR3_IN, PTR2_IN, PTR1_IN, PTR0_IN,
+ PTS6_IN, PTS5_IN, PTS4_IN,
+ PTS3_IN, PTS2_IN, PTS1_IN, PTS0_IN,
+ PTT7_IN, PTT6_IN, PTT5_IN, PTT4_IN,
+ PTT3_IN, PTT2_IN, PTT1_IN, PTT0_IN,
+ PTU7_IN, PTU6_IN, PTU5_IN, PTU4_IN,
+ PTU3_IN, PTU2_IN, PTU1_IN, PTU0_IN,
+ PTV7_IN, PTV6_IN, PTV5_IN, PTV4_IN,
+ PTV3_IN, PTV2_IN, PTV1_IN, PTV0_IN,
+ PTW7_IN, PTW6_IN, PTW5_IN, PTW4_IN,
+ PTW3_IN, PTW2_IN, PTW1_IN, PTW0_IN,
+ PTX7_IN, PTX6_IN, PTX5_IN, PTX4_IN,
+ PTX3_IN, PTX2_IN, PTX1_IN, PTX0_IN,
+ PTY7_IN, PTY6_IN, PTY5_IN, PTY4_IN,
+ PTY3_IN, PTY2_IN, PTY1_IN, PTY0_IN,
+ PTZ7_IN, PTZ6_IN, PTZ5_IN, PTZ4_IN,
+ PTZ3_IN, PTZ2_IN, PTZ1_IN, PTZ0_IN,
+ PINMUX_INPUT_END,
+
+ PINMUX_INPUT_PULLUP_BEGIN,
+ PTA7_IN_PU, PTA6_IN_PU, PTA5_IN_PU, PTA4_IN_PU,
+ PTA3_IN_PU, PTA2_IN_PU, PTA1_IN_PU, PTA0_IN_PU,
+ PTB7_IN_PU, PTB6_IN_PU, PTB5_IN_PU, PTB4_IN_PU,
+ PTB3_IN_PU, PTB2_IN_PU, PTB1_IN_PU, PTB0_IN_PU,
+ PTC7_IN_PU, PTC6_IN_PU, PTC5_IN_PU, PTC4_IN_PU,
+ PTC3_IN_PU, PTC2_IN_PU, PTC1_IN_PU, PTC0_IN_PU,
+ PTD7_IN_PU, PTD6_IN_PU, PTD5_IN_PU, PTD4_IN_PU,
+ PTD3_IN_PU, PTD2_IN_PU, PTD1_IN_PU, PTD0_IN_PU,
+ PTE7_IN_PU, PTE6_IN_PU, PTE5_IN_PU, PTE4_IN_PU,
+ PTE3_IN_PU, PTE2_IN_PU, PTE1_IN_PU, PTE0_IN_PU,
+ PTF7_IN_PU, PTF6_IN_PU, PTF5_IN_PU, PTF4_IN_PU,
+ PTF3_IN_PU, PTF2_IN_PU, PTF1_IN_PU, PTF0_IN_PU,
+ PTH7_IN_PU, PTH6_IN_PU, PTH5_IN_PU, PTH4_IN_PU,
+ PTH3_IN_PU, PTH2_IN_PU, PTH1_IN_PU, PTH0_IN_PU,
+ PTJ3_IN_PU, PTJ2_IN_PU, PTJ1_IN_PU, PTJ0_IN_PU,
+ PTK7_IN_PU, PTK6_IN_PU, PTK5_IN_PU, PTK4_IN_PU,
+ PTK3_IN_PU, PTK2_IN_PU, PTK1_IN_PU, PTK0_IN_PU,
+ PTL7_IN_PU, PTL6_IN_PU, PTL5_IN_PU, PTL4_IN_PU,
+ PTL3_IN_PU, PTL2_IN_PU, PTL1_IN_PU, PTL0_IN_PU,
+ PTM7_IN_PU, PTM6_IN_PU, PTM5_IN_PU, PTM4_IN_PU,
+ PTM3_IN_PU, PTM2_IN_PU, PTM1_IN_PU, PTM0_IN_PU,
+ PTN7_IN_PU, PTN6_IN_PU, PTN5_IN_PU, PTN4_IN_PU,
+ PTN3_IN_PU, PTN2_IN_PU, PTN1_IN_PU, PTN0_IN_PU,
+ PTQ7_IN_PU, PTQ6_IN_PU, PTQ5_IN_PU, PTQ4_IN_PU,
+ PTQ3_IN_PU, PTQ2_IN_PU, PTQ1_IN_PU, PTQ0_IN_PU,
+ PTR7_IN_PU, PTR6_IN_PU, PTR5_IN_PU, PTR4_IN_PU,
+ PTR3_IN_PU, PTR2_IN_PU, PTR1_IN_PU, PTR0_IN_PU,
+ PTS6_IN_PU, PTS5_IN_PU, PTS4_IN_PU,
+ PTS3_IN_PU, PTS2_IN_PU, PTS1_IN_PU, PTS0_IN_PU,
+ PTT7_IN_PU, PTT6_IN_PU, PTT5_IN_PU, PTT4_IN_PU,
+ PTT3_IN_PU, PTT2_IN_PU, PTT1_IN_PU, PTT0_IN_PU,
+ PTU7_IN_PU, PTU6_IN_PU, PTU5_IN_PU, PTU4_IN_PU,
+ PTU3_IN_PU, PTU2_IN_PU, PTU1_IN_PU, PTU0_IN_PU,
+ PTV7_IN_PU, PTV6_IN_PU, PTV5_IN_PU, PTV4_IN_PU,
+ PTV3_IN_PU, PTV2_IN_PU, PTV1_IN_PU, PTV0_IN_PU,
+ PTW7_IN_PU, PTW6_IN_PU, PTW5_IN_PU, PTW4_IN_PU,
+ PTW3_IN_PU, PTW2_IN_PU, PTW1_IN_PU, PTW0_IN_PU,
+ PTX7_IN_PU, PTX6_IN_PU, PTX5_IN_PU, PTX4_IN_PU,
+ PTX3_IN_PU, PTX2_IN_PU, PTX1_IN_PU, PTX0_IN_PU,
+ PTY7_IN_PU, PTY6_IN_PU, PTY5_IN_PU, PTY4_IN_PU,
+ PTY3_IN_PU, PTY2_IN_PU, PTY1_IN_PU, PTY0_IN_PU,
+ PTZ7_IN_PU, PTZ6_IN_PU, PTZ5_IN_PU, PTZ4_IN_PU,
+ PTZ3_IN_PU, PTZ2_IN_PU, PTZ1_IN_PU, PTZ0_IN_PU,
+ PINMUX_INPUT_PULLUP_END,
+
+ PINMUX_OUTPUT_BEGIN,
+ PTA7_OUT, PTA6_OUT, PTA5_OUT, PTA4_OUT,
+ PTA3_OUT, PTA2_OUT, PTA1_OUT, PTA0_OUT,
+ PTB7_OUT, PTB6_OUT, PTB5_OUT, PTB4_OUT,
+ PTB3_OUT, PTB2_OUT, PTB1_OUT, PTB0_OUT,
+ PTC7_OUT, PTC6_OUT, PTC5_OUT, PTC4_OUT,
+ PTC3_OUT, PTC2_OUT, PTC1_OUT, PTC0_OUT,
+ PTD7_OUT, PTD6_OUT, PTD5_OUT, PTD4_OUT,
+ PTD3_OUT, PTD2_OUT, PTD1_OUT, PTD0_OUT,
+ PTE7_OUT, PTE6_OUT, PTE5_OUT, PTE4_OUT,
+ PTE3_OUT, PTE2_OUT, PTE1_OUT, PTE0_OUT,
+ PTF7_OUT, PTF6_OUT, PTF5_OUT, PTF4_OUT,
+ PTF3_OUT, PTF2_OUT, PTF1_OUT, PTF0_OUT,
+ PTG5_OUT, PTG4_OUT,
+ PTG3_OUT, PTG2_OUT, PTG1_OUT, PTG0_OUT,
+ PTH7_OUT, PTH6_OUT, PTH5_OUT, PTH4_OUT,
+ PTH3_OUT, PTH2_OUT, PTH1_OUT, PTH0_OUT,
+ PTJ7_OUT, PTJ6_OUT, PTJ5_OUT,
+ PTJ3_OUT, PTJ2_OUT, PTJ1_OUT, PTJ0_OUT,
+ PTK7_OUT, PTK6_OUT, PTK5_OUT, PTK4_OUT,
+ PTK3_OUT, PTK2_OUT, PTK1_OUT, PTK0_OUT,
+ PTL7_OUT, PTL6_OUT, PTL5_OUT, PTL4_OUT,
+ PTL3_OUT, PTL2_OUT, PTL1_OUT, PTL0_OUT,
+ PTM7_OUT, PTM6_OUT, PTM5_OUT, PTM4_OUT,
+ PTM3_OUT, PTM2_OUT, PTM1_OUT, PTM0_OUT,
+ PTN7_OUT, PTN6_OUT, PTN5_OUT, PTN4_OUT,
+ PTN3_OUT, PTN2_OUT, PTN1_OUT, PTN0_OUT,
+ PTQ7_OUT, PTQ6_OUT, PTQ5_OUT, PTQ4_OUT,
+ PTQ3_OUT, PTQ2_OUT, PTQ1_OUT, PTQ0_OUT,
+ PTR7_OUT, PTR6_OUT, PTR5_OUT, PTR4_OUT,
+ PTR1_OUT, PTR0_OUT,
+ PTS6_OUT, PTS5_OUT, PTS4_OUT,
+ PTS3_OUT, PTS2_OUT, PTS1_OUT, PTS0_OUT,
+ PTT7_OUT, PTT6_OUT, PTT5_OUT, PTT4_OUT,
+ PTT3_OUT, PTT2_OUT, PTT1_OUT, PTT0_OUT,
+ PTU7_OUT, PTU6_OUT, PTU5_OUT, PTU4_OUT,
+ PTU3_OUT, PTU2_OUT, PTU1_OUT, PTU0_OUT,
+ PTV7_OUT, PTV6_OUT, PTV5_OUT, PTV4_OUT,
+ PTV3_OUT, PTV2_OUT, PTV1_OUT, PTV0_OUT,
+ PTW7_OUT, PTW6_OUT, PTW5_OUT, PTW4_OUT,
+ PTW3_OUT, PTW2_OUT, PTW1_OUT, PTW0_OUT,
+ PTX7_OUT, PTX6_OUT, PTX5_OUT, PTX4_OUT,
+ PTX3_OUT, PTX2_OUT, PTX1_OUT, PTX0_OUT,
+ PTY7_OUT, PTY6_OUT, PTY5_OUT, PTY4_OUT,
+ PTY3_OUT, PTY2_OUT, PTY1_OUT, PTY0_OUT,
+ PTZ7_OUT, PTZ6_OUT, PTZ5_OUT, PTZ4_OUT,
+ PTZ3_OUT, PTZ2_OUT, PTZ1_OUT, PTZ0_OUT,
+ PINMUX_OUTPUT_END,
+
+ PINMUX_FUNCTION_BEGIN,
+ PTA7_FN, PTA6_FN, PTA5_FN, PTA4_FN,
+ PTA3_FN, PTA2_FN, PTA1_FN, PTA0_FN,
+ PTB7_FN, PTB6_FN, PTB5_FN, PTB4_FN,
+ PTB3_FN, PTB2_FN, PTB1_FN, PTB0_FN,
+ PTC7_FN, PTC6_FN, PTC5_FN, PTC4_FN,
+ PTC3_FN, PTC2_FN, PTC1_FN, PTC0_FN,
+ PTD7_FN, PTD6_FN, PTD5_FN, PTD4_FN,
+ PTD3_FN, PTD2_FN, PTD1_FN, PTD0_FN,
+ PTE7_FN, PTE6_FN, PTE5_FN, PTE4_FN,
+ PTE3_FN, PTE2_FN, PTE1_FN, PTE0_FN,
+ PTF7_FN, PTF6_FN, PTF5_FN, PTF4_FN,
+ PTF3_FN, PTF2_FN, PTF1_FN, PTF0_FN,
+ PTG5_FN, PTG4_FN,
+ PTG3_FN, PTG2_FN, PTG1_FN, PTG0_FN,
+ PTH7_FN, PTH6_FN, PTH5_FN, PTH4_FN,
+ PTH3_FN, PTH2_FN, PTH1_FN, PTH0_FN,
+ PTJ7_FN, PTJ6_FN, PTJ5_FN,
+ PTJ3_FN, PTJ2_FN, PTJ1_FN, PTJ0_FN,
+ PTK7_FN, PTK6_FN, PTK5_FN, PTK4_FN,
+ PTK3_FN, PTK2_FN, PTK1_FN, PTK0_FN,
+ PTL7_FN, PTL6_FN, PTL5_FN, PTL4_FN,
+ PTL3_FN, PTL2_FN, PTL1_FN, PTL0_FN,
+ PTM7_FN, PTM6_FN, PTM5_FN, PTM4_FN,
+ PTM3_FN, PTM2_FN, PTM1_FN, PTM0_FN,
+ PTN7_FN, PTN6_FN, PTN5_FN, PTN4_FN,
+ PTN3_FN, PTN2_FN, PTN1_FN, PTN0_FN,
+ PTQ7_FN, PTQ6_FN, PTQ5_FN, PTQ4_FN,
+ PTQ3_FN, PTQ2_FN, PTQ1_FN, PTQ0_FN,
+ PTR7_FN, PTR6_FN, PTR5_FN, PTR4_FN,
+ PTR3_FN, PTR2_FN, PTR1_FN, PTR0_FN,
+ PTS6_FN, PTS5_FN, PTS4_FN,
+ PTS3_FN, PTS2_FN, PTS1_FN, PTS0_FN,
+ PTT7_FN, PTT6_FN, PTT5_FN, PTT4_FN,
+ PTT3_FN, PTT2_FN, PTT1_FN, PTT0_FN,
+ PTU7_FN, PTU6_FN, PTU5_FN, PTU4_FN,
+ PTU3_FN, PTU2_FN, PTU1_FN, PTU0_FN,
+ PTV7_FN, PTV6_FN, PTV5_FN, PTV4_FN,
+ PTV3_FN, PTV2_FN, PTV1_FN, PTV0_FN,
+ PTW7_FN, PTW6_FN, PTW5_FN, PTW4_FN,
+ PTW3_FN, PTW2_FN, PTW1_FN, PTW0_FN,
+ PTX7_FN, PTX6_FN, PTX5_FN, PTX4_FN,
+ PTX3_FN, PTX2_FN, PTX1_FN, PTX0_FN,
+ PTY7_FN, PTY6_FN, PTY5_FN, PTY4_FN,
+ PTY3_FN, PTY2_FN, PTY1_FN, PTY0_FN,
+ PTZ7_FN, PTZ6_FN, PTZ5_FN, PTZ4_FN,
+ PTZ3_FN, PTZ2_FN, PTZ1_FN, PTZ0_FN,
+
+
+ PSA15_0, PSA15_1,
+ PSA14_0, PSA14_1,
+ PSA13_0, PSA13_1,
+ PSA12_0, PSA12_1,
+ PSA10_0, PSA10_1,
+ PSA9_0, PSA9_1,
+ PSA8_0, PSA8_1,
+ PSA7_0, PSA7_1,
+ PSA6_0, PSA6_1,
+ PSA5_0, PSA5_1,
+ PSA3_0, PSA3_1,
+ PSA2_0, PSA2_1,
+ PSA1_0, PSA1_1,
+ PSA0_0, PSA0_1,
+
+ PSB14_0, PSB14_1,
+ PSB13_0, PSB13_1,
+ PSB12_0, PSB12_1,
+ PSB11_0, PSB11_1,
+ PSB10_0, PSB10_1,
+ PSB9_0, PSB9_1,
+ PSB8_0, PSB8_1,
+ PSB7_0, PSB7_1,
+ PSB6_0, PSB6_1,
+ PSB5_0, PSB5_1,
+ PSB4_0, PSB4_1,
+ PSB3_0, PSB3_1,
+ PSB2_0, PSB2_1,
+ PSB1_0, PSB1_1,
+ PSB0_0, PSB0_1,
+
+ PSC15_0, PSC15_1,
+ PSC14_0, PSC14_1,
+ PSC13_0, PSC13_1,
+ PSC12_0, PSC12_1,
+ PSC11_0, PSC11_1,
+ PSC10_0, PSC10_1,
+ PSC9_0, PSC9_1,
+ PSC8_0, PSC8_1,
+ PSC7_0, PSC7_1,
+ PSC6_0, PSC6_1,
+ PSC5_0, PSC5_1,
+ PSC4_0, PSC4_1,
+ PSC2_0, PSC2_1,
+ PSC1_0, PSC1_1,
+ PSC0_0, PSC0_1,
+
+ PSD15_0, PSD15_1,
+ PSD14_0, PSD14_1,
+ PSD13_0, PSD13_1,
+ PSD12_0, PSD12_1,
+ PSD11_0, PSD11_1,
+ PSD10_0, PSD10_1,
+ PSD9_0, PSD9_1,
+ PSD8_0, PSD8_1,
+ PSD7_0, PSD7_1,
+ PSD6_0, PSD6_1,
+ PSD5_0, PSD5_1,
+ PSD4_0, PSD4_1,
+ PSD3_0, PSD3_1,
+ PSD2_0, PSD2_1,
+ PSD1_0, PSD1_1,
+ PSD0_0, PSD0_1,
+
+ PSE15_0, PSE15_1,
+ PSE14_0, PSE14_1,
+ PSE13_0, PSE13_1,
+ PSE12_0, PSE12_1,
+ PSE11_0, PSE11_1,
+ PSE10_0, PSE10_1,
+ PSE9_0, PSE9_1,
+ PSE8_0, PSE8_1,
+ PSE7_0, PSE7_1,
+ PSE6_0, PSE6_1,
+ PSE5_0, PSE5_1,
+ PSE4_0, PSE4_1,
+ PSE3_0, PSE3_1,
+ PSE2_0, PSE2_1,
+ PSE1_0, PSE1_1,
+ PSE0_0, PSE0_1,
+ PINMUX_FUNCTION_END,
+
+ PINMUX_MARK_BEGIN,
+ /*PTA*/
+ D23_MARK, KEYOUT2_MARK, IDED15_MARK,
+ D22_MARK, KEYOUT1_MARK, IDED14_MARK,
+ D21_MARK, KEYOUT0_MARK, IDED13_MARK,
+ D20_MARK, KEYIN4_MARK, IDED12_MARK,
+ D19_MARK, KEYIN3_MARK, IDED11_MARK,
+ D18_MARK, KEYIN2_MARK, IDED10_MARK,
+ D17_MARK, KEYIN1_MARK, IDED9_MARK,
+ D16_MARK, KEYIN0_MARK, IDED8_MARK,
+
+ /*PTB*/
+ D31_MARK, TPUTO1_MARK, IDEA1_MARK,
+ D30_MARK, TPUTO0_MARK, IDEA0_MARK,
+ D29_MARK, IODREQ_MARK,
+ D28_MARK, IDECS0_MARK,
+ D27_MARK, IDECS1_MARK,
+ D26_MARK, KEYOUT5_IN5_MARK, IDEIORD_MARK,
+ D25_MARK, KEYOUT4_IN6_MARK, IDEIOWR_MARK,
+ D24_MARK, KEYOUT3_MARK, IDEINT_MARK,
+
+ /*PTC*/
+ LCDD7_MARK,
+ LCDD6_MARK,
+ LCDD5_MARK,
+ LCDD4_MARK,
+ LCDD3_MARK,
+ LCDD2_MARK,
+ LCDD1_MARK,
+ LCDD0_MARK,
+
+ /*PTD*/
+ LCDD15_MARK,
+ LCDD14_MARK,
+ LCDD13_MARK,
+ LCDD12_MARK,
+ LCDD11_MARK,
+ LCDD10_MARK,
+ LCDD9_MARK,
+ LCDD8_MARK,
+
+ /*PTE*/
+ FSIMCKB_MARK,
+ FSIMCKA_MARK,
+ LCDD21_MARK, SCIF2_L_TXD_MARK,
+ LCDD20_MARK, SCIF4_SCK_MARK,
+ LCDD19_MARK, SCIF4_RXD_MARK,
+ LCDD18_MARK, SCIF4_TXD_MARK,
+ LCDD17_MARK,
+ LCDD16_MARK,
+
+ /*PTF*/
+ LCDVSYN_MARK,
+ LCDDISP_MARK, LCDRS_MARK,
+ LCDHSYN_MARK, LCDCS_MARK,
+ LCDDON_MARK,
+ LCDDCK_MARK, LCDWR_MARK,
+ LCDVEPWC_MARK, SCIF0_TXD_MARK,
+ LCDD23_MARK, SCIF2_L_SCK_MARK,
+ LCDD22_MARK, SCIF2_L_RXD_MARK,
+
+ /*PTG*/
+ AUDCK_MARK,
+ AUDSYNC_MARK,
+ AUDATA3_MARK,
+ AUDATA2_MARK,
+ AUDATA1_MARK,
+ AUDATA0_MARK,
+
+ /*PTH*/
+ VIO0_VD_MARK,
+ VIO0_CLK_MARK,
+ VIO0_D7_MARK,
+ VIO0_D6_MARK,
+ VIO0_D5_MARK,
+ VIO0_D4_MARK,
+ VIO0_D3_MARK,
+ VIO0_D2_MARK,
+
+ /*PTJ*/
+ PDSTATUS_MARK,
+ STATUS2_MARK,
+ STATUS0_MARK,
+ A25_MARK, BS_MARK,
+ A24_MARK,
+ A23_MARK,
+ A22_MARK,
+
+ /*PTK*/
+ VIO1_D5_MARK, VIO0_D13_MARK, IDED5_MARK,
+ VIO1_D4_MARK, VIO0_D12_MARK, IDED4_MARK,
+ VIO1_D3_MARK, VIO0_D11_MARK, IDED3_MARK,
+ VIO1_D2_MARK, VIO0_D10_MARK, IDED2_MARK,
+ VIO1_D1_MARK, VIO0_D9_MARK, IDED1_MARK,
+ VIO1_D0_MARK, VIO0_D8_MARK, IDED0_MARK,
+ VIO0_FLD_MARK,
+ VIO0_HD_MARK,
+
+ /*PTL*/
+ DV_D5_MARK, SCIF3_V_SCK_MARK, RMII_RXD0_MARK,
+ DV_D4_MARK, SCIF3_V_RXD_MARK, RMII_RXD1_MARK,
+ DV_D3_MARK, SCIF3_V_TXD_MARK, RMII_REF_CLK_MARK,
+ DV_D2_MARK, SCIF1_SCK_MARK, RMII_TX_EN_MARK,
+ DV_D1_MARK, SCIF1_RXD_MARK, RMII_TXD0_MARK,
+ DV_D0_MARK, SCIF1_TXD_MARK, RMII_TXD1_MARK,
+ DV_D15_MARK,
+ DV_D14_MARK, MSIOF0_MCK_MARK,
+
+ /*PTM*/
+ DV_D13_MARK, MSIOF0_TSCK_MARK,
+ DV_D12_MARK, MSIOF0_RXD_MARK,
+ DV_D11_MARK, MSIOF0_TXD_MARK,
+ DV_D10_MARK, MSIOF0_TSYNC_MARK,
+ DV_D9_MARK, MSIOF0_SS1_MARK, MSIOF0_RSCK_MARK,
+ DV_D8_MARK, MSIOF0_SS2_MARK, MSIOF0_RSYNC_MARK,
+ LCDVCPWC_MARK, SCIF0_RXD_MARK,
+ LCDRD_MARK, SCIF0_SCK_MARK,
+
+ /*PTN*/
+ VIO0_D1_MARK,
+ VIO0_D0_MARK,
+ DV_CLKI_MARK,
+ DV_CLK_MARK, SCIF2_V_SCK_MARK,
+ DV_VSYNC_MARK, SCIF2_V_RXD_MARK,
+ DV_HSYNC_MARK, SCIF2_V_TXD_MARK,
+ DV_D7_MARK, SCIF3_V_CTS_MARK, RMII_RX_ER_MARK,
+ DV_D6_MARK, SCIF3_V_RTS_MARK, RMII_CRS_DV_MARK,
+
+ /*PTQ*/
+ D7_MARK,
+ D6_MARK,
+ D5_MARK,
+ D4_MARK,
+ D3_MARK,
+ D2_MARK,
+ D1_MARK,
+ D0_MARK,
+
+ /*PTR*/
+ CS6B_CE1B_MARK,
+ CS6A_CE2B_MARK,
+ CS5B_CE1A_MARK,
+ CS5A_CE2A_MARK,
+ IOIS16_MARK, LCDLCLK_MARK,
+ WAIT_MARK,
+ WE3_ICIOWR_MARK, TPUTO3_MARK, TPUTI3_MARK,
+ WE2_ICIORD_MARK, TPUTO2_MARK, IDEA2_MARK,
+
+ /*PTS*/
+ VIO_CKO_MARK,
+ VIO1_FLD_MARK, TPUTI2_MARK, IDEIORDY_MARK,
+ VIO1_HD_MARK, SCIF5_SCK_MARK,
+ VIO1_VD_MARK, SCIF5_RXD_MARK,
+ VIO1_CLK_MARK, SCIF5_TXD_MARK,
+ VIO1_D7_MARK, VIO0_D15_MARK, IDED7_MARK,
+ VIO1_D6_MARK, VIO0_D14_MARK, IDED6_MARK,
+
+ /*PTT*/
+ D15_MARK,
+ D14_MARK,
+ D13_MARK,
+ D12_MARK,
+ D11_MARK,
+ D10_MARK,
+ D9_MARK,
+ D8_MARK,
+
+ /*PTU*/
+ DMAC_DACK0_MARK,
+ DMAC_DREQ0_MARK,
+ FSIOASD_MARK,
+ FSIIABCK_MARK,
+ FSIIALRCK_MARK,
+ FSIOABCK_MARK,
+ FSIOALRCK_MARK,
+ CLKAUDIOAO_MARK,
+
+ /*PTV*/
+ FSIIBSD_MARK, MSIOF1_SS2_MARK, MSIOF1_RSYNC_MARK,
+ FSIOBSD_MARK, MSIOF1_SS1_MARK, MSIOF1_RSCK_MARK,
+ FSIIBBCK_MARK, MSIOF1_RXD_MARK,
+ FSIIBLRCK_MARK, MSIOF1_TSYNC_MARK,
+ FSIOBBCK_MARK, MSIOF1_TSCK_MARK,
+ FSIOBLRCK_MARK, MSIOF1_TXD_MARK,
+ CLKAUDIOBO_MARK, MSIOF1_MCK_MARK,
+ FSIIASD_MARK,
+
+ /*PTW*/
+ MMC_D7_MARK, SDHI1CD_MARK, IODACK_MARK,
+ MMC_D6_MARK, SDHI1WP_MARK, IDERST_MARK,
+ MMC_D5_MARK, SDHI1D3_MARK, EXBUF_ENB_MARK,
+ MMC_D4_MARK, SDHI1D2_MARK, DIRECTION_MARK,
+ MMC_D3_MARK, SDHI1D1_MARK,
+ MMC_D2_MARK, SDHI1D0_MARK,
+ MMC_D1_MARK, SDHI1CMD_MARK,
+ MMC_D0_MARK, SDHI1CLK_MARK,
+
+ /*PTX*/
+ DMAC_DACK1_MARK, IRDA_OUT_MARK,
+ DMAC_DREQ1_MARK, IRDA_IN_MARK,
+ TSIF_TS0_SDAT_MARK, LNKSTA_MARK,
+ TSIF_TS0_SCK_MARK, MDIO_MARK,
+ TSIF_TS0_SDEN_MARK, MDC_MARK,
+ TSIF_TS0_SPSYNC_MARK,
+ MMC_CLK_MARK,
+ MMC_CMD_MARK,
+
+ /*PTY*/
+ SDHI0CD_MARK,
+ SDHI0WP_MARK,
+ SDHI0D3_MARK,
+ SDHI0D2_MARK,
+ SDHI0D1_MARK,
+ SDHI0D0_MARK,
+ SDHI0CMD_MARK,
+ SDHI0CLK_MARK,
+
+ /*PTZ*/
+ INTC_IRQ7_MARK, SCIF3_I_CTS_MARK,
+ INTC_IRQ6_MARK, SCIF3_I_RTS_MARK,
+ INTC_IRQ5_MARK, SCIF3_I_SCK_MARK,
+ INTC_IRQ4_MARK, SCIF3_I_RXD_MARK,
+ INTC_IRQ3_MARK, SCIF3_I_TXD_MARK,
+ INTC_IRQ2_MARK,
+ INTC_IRQ1_MARK,
+ INTC_IRQ0_MARK,
+ PINMUX_MARK_END,
+};
+
+static pinmux_enum_t pinmux_data[] = {
+ /* PTA GPIO */
+ PINMUX_DATA(PTA7_DATA, PTA7_IN, PTA7_OUT, PTA7_IN_PU),
+ PINMUX_DATA(PTA6_DATA, PTA6_IN, PTA6_OUT, PTA6_IN_PU),
+ PINMUX_DATA(PTA5_DATA, PTA5_IN, PTA5_OUT, PTA5_IN_PU),
+ PINMUX_DATA(PTA4_DATA, PTA4_IN, PTA4_OUT, PTA4_IN_PU),
+ PINMUX_DATA(PTA3_DATA, PTA3_IN, PTA3_OUT, PTA3_IN_PU),
+ PINMUX_DATA(PTA2_DATA, PTA2_IN, PTA2_OUT, PTA2_IN_PU),
+ PINMUX_DATA(PTA1_DATA, PTA1_IN, PTA1_OUT, PTA1_IN_PU),
+ PINMUX_DATA(PTA0_DATA, PTA0_IN, PTA0_OUT, PTA0_IN_PU),
+
+ /* PTB GPIO */
+ PINMUX_DATA(PTB7_DATA, PTB7_IN, PTB7_OUT, PTB7_IN_PU),
+ PINMUX_DATA(PTB6_DATA, PTB6_IN, PTB6_OUT, PTB6_IN_PU),
+ PINMUX_DATA(PTB5_DATA, PTB5_IN, PTB5_OUT, PTB5_IN_PU),
+ PINMUX_DATA(PTB4_DATA, PTB4_IN, PTB4_OUT, PTB4_IN_PU),
+ PINMUX_DATA(PTB3_DATA, PTB3_IN, PTB3_OUT, PTB3_IN_PU),
+ PINMUX_DATA(PTB2_DATA, PTB2_IN, PTB2_OUT, PTB2_IN_PU),
+ PINMUX_DATA(PTB1_DATA, PTB1_IN, PTB1_OUT, PTB1_IN_PU),
+ PINMUX_DATA(PTB0_DATA, PTB0_IN, PTB0_OUT, PTB0_IN_PU),
+
+ /* PTC GPIO */
+ PINMUX_DATA(PTC7_DATA, PTC7_IN, PTC7_OUT, PTC7_IN_PU),
+ PINMUX_DATA(PTC6_DATA, PTC6_IN, PTC6_OUT, PTC6_IN_PU),
+ PINMUX_DATA(PTC5_DATA, PTC5_IN, PTC5_OUT, PTC5_IN_PU),
+ PINMUX_DATA(PTC4_DATA, PTC4_IN, PTC4_OUT, PTC4_IN_PU),
+ PINMUX_DATA(PTC3_DATA, PTC3_IN, PTC3_OUT, PTC3_IN_PU),
+ PINMUX_DATA(PTC2_DATA, PTC2_IN, PTC2_OUT, PTC2_IN_PU),
+ PINMUX_DATA(PTC1_DATA, PTC1_IN, PTC1_OUT, PTC1_IN_PU),
+ PINMUX_DATA(PTC0_DATA, PTC0_IN, PTC0_OUT, PTC0_IN_PU),
+
+ /* PTD GPIO */
+ PINMUX_DATA(PTD7_DATA, PTD7_IN, PTD7_OUT, PTD7_IN_PU),
+ PINMUX_DATA(PTD6_DATA, PTD6_IN, PTD6_OUT, PTD6_IN_PU),
+ PINMUX_DATA(PTD5_DATA, PTD5_IN, PTD5_OUT, PTD5_IN_PU),
+ PINMUX_DATA(PTD4_DATA, PTD4_IN, PTD4_OUT, PTD4_IN_PU),
+ PINMUX_DATA(PTD3_DATA, PTD3_IN, PTD3_OUT, PTD3_IN_PU),
+ PINMUX_DATA(PTD2_DATA, PTD2_IN, PTD2_OUT, PTD2_IN_PU),
+ PINMUX_DATA(PTD1_DATA, PTD1_IN, PTD1_OUT, PTD1_IN_PU),
+ PINMUX_DATA(PTD0_DATA, PTD0_IN, PTD0_OUT, PTD0_IN_PU),
+
+ /* PTE GPIO */
+ PINMUX_DATA(PTE7_DATA, PTE7_IN, PTE7_OUT, PTE7_IN_PU),
+ PINMUX_DATA(PTE6_DATA, PTE6_IN, PTE6_OUT, PTE6_IN_PU),
+ PINMUX_DATA(PTE5_DATA, PTE5_IN, PTE5_OUT, PTE5_IN_PU),
+ PINMUX_DATA(PTE4_DATA, PTE4_IN, PTE4_OUT, PTE4_IN_PU),
+ PINMUX_DATA(PTE3_DATA, PTE3_IN, PTE3_OUT, PTE3_IN_PU),
+ PINMUX_DATA(PTE2_DATA, PTE2_IN, PTE2_OUT, PTE2_IN_PU),
+ PINMUX_DATA(PTE1_DATA, PTE1_IN, PTE1_OUT, PTE1_IN_PU),
+ PINMUX_DATA(PTE0_DATA, PTE0_IN, PTE0_OUT, PTE0_IN_PU),
+
+ /* PTF GPIO */
+ PINMUX_DATA(PTF7_DATA, PTF7_IN, PTF7_OUT, PTF7_IN_PU),
+ PINMUX_DATA(PTF6_DATA, PTF6_IN, PTF6_OUT, PTF6_IN_PU),
+ PINMUX_DATA(PTF5_DATA, PTF5_IN, PTF5_OUT, PTF5_IN_PU),
+ PINMUX_DATA(PTF4_DATA, PTF4_IN, PTF4_OUT, PTF4_IN_PU),
+ PINMUX_DATA(PTF3_DATA, PTF3_IN, PTF3_OUT, PTF3_IN_PU),
+ PINMUX_DATA(PTF2_DATA, PTF2_IN, PTF2_OUT, PTF2_IN_PU),
+ PINMUX_DATA(PTF1_DATA, PTF1_IN, PTF1_OUT, PTF1_IN_PU),
+ PINMUX_DATA(PTF0_DATA, PTF0_IN, PTF0_OUT, PTF0_IN_PU),
+
+ /* PTG GPIO */
+ PINMUX_DATA(PTG5_DATA, PTG5_OUT),
+ PINMUX_DATA(PTG4_DATA, PTG4_OUT),
+ PINMUX_DATA(PTG3_DATA, PTG3_OUT),
+ PINMUX_DATA(PTG2_DATA, PTG2_OUT),
+ PINMUX_DATA(PTG1_DATA, PTG1_OUT),
+ PINMUX_DATA(PTG0_DATA, PTG0_OUT),
+
+ /* PTH GPIO */
+ PINMUX_DATA(PTH7_DATA, PTH7_IN, PTH7_OUT, PTH7_IN_PU),
+ PINMUX_DATA(PTH6_DATA, PTH6_IN, PTH6_OUT, PTH6_IN_PU),
+ PINMUX_DATA(PTH5_DATA, PTH5_IN, PTH5_OUT, PTH5_IN_PU),
+ PINMUX_DATA(PTH4_DATA, PTH4_IN, PTH4_OUT, PTH4_IN_PU),
+ PINMUX_DATA(PTH3_DATA, PTH3_IN, PTH3_OUT, PTH3_IN_PU),
+ PINMUX_DATA(PTH2_DATA, PTH2_IN, PTH2_OUT, PTH2_IN_PU),
+ PINMUX_DATA(PTH1_DATA, PTH1_IN, PTH1_OUT, PTH1_IN_PU),
+ PINMUX_DATA(PTH0_DATA, PTH0_IN, PTH0_OUT, PTH0_IN_PU),
+
+ /* PTJ GPIO */
+ PINMUX_DATA(PTJ7_DATA, PTJ7_OUT),
+ PINMUX_DATA(PTJ6_DATA, PTJ6_OUT),
+ PINMUX_DATA(PTJ5_DATA, PTJ5_OUT),
+ PINMUX_DATA(PTJ3_DATA, PTJ3_IN, PTJ3_OUT, PTJ3_IN_PU),
+ PINMUX_DATA(PTJ2_DATA, PTJ2_IN, PTJ2_OUT, PTJ2_IN_PU),
+ PINMUX_DATA(PTJ1_DATA, PTJ1_IN, PTJ1_OUT, PTJ1_IN_PU),
+ PINMUX_DATA(PTJ0_DATA, PTJ0_IN, PTJ0_OUT, PTJ0_IN_PU),
+
+ /* PTK GPIO */
+ PINMUX_DATA(PTK7_DATA, PTK7_IN, PTK7_OUT, PTK7_IN_PU),
+ PINMUX_DATA(PTK6_DATA, PTK6_IN, PTK6_OUT, PTK6_IN_PU),
+ PINMUX_DATA(PTK5_DATA, PTK5_IN, PTK5_OUT, PTK5_IN_PU),
+ PINMUX_DATA(PTK4_DATA, PTK4_IN, PTK4_OUT, PTK4_IN_PU),
+ PINMUX_DATA(PTK3_DATA, PTK3_IN, PTK3_OUT, PTK3_IN_PU),
+ PINMUX_DATA(PTK2_DATA, PTK2_IN, PTK2_OUT, PTK2_IN_PU),
+ PINMUX_DATA(PTK1_DATA, PTK1_IN, PTK1_OUT, PTK1_IN_PU),
+ PINMUX_DATA(PTK0_DATA, PTK0_IN, PTK0_OUT, PTK0_IN_PU),
+
+ /* PTL GPIO */
+ PINMUX_DATA(PTL7_DATA, PTL7_IN, PTL7_OUT, PTL7_IN_PU),
+ PINMUX_DATA(PTL6_DATA, PTL6_IN, PTL6_OUT, PTL6_IN_PU),
+ PINMUX_DATA(PTL5_DATA, PTL5_IN, PTL5_OUT, PTL5_IN_PU),
+ PINMUX_DATA(PTL4_DATA, PTL4_IN, PTL4_OUT, PTL4_IN_PU),
+ PINMUX_DATA(PTL3_DATA, PTL3_IN, PTL3_OUT, PTL3_IN_PU),
+ PINMUX_DATA(PTL2_DATA, PTL2_IN, PTL2_OUT, PTL2_IN_PU),
+ PINMUX_DATA(PTL1_DATA, PTL1_IN, PTL1_OUT, PTL1_IN_PU),
+ PINMUX_DATA(PTL0_DATA, PTL0_IN, PTL0_OUT, PTL0_IN_PU),
+
+ /* PTM GPIO */
+ PINMUX_DATA(PTM7_DATA, PTM7_IN, PTM7_OUT, PTM7_IN_PU),
+ PINMUX_DATA(PTM6_DATA, PTM6_IN, PTM6_OUT, PTM6_IN_PU),
+ PINMUX_DATA(PTM5_DATA, PTM5_IN, PTM5_OUT, PTM5_IN_PU),
+ PINMUX_DATA(PTM4_DATA, PTM4_IN, PTM4_OUT, PTM4_IN_PU),
+ PINMUX_DATA(PTM3_DATA, PTM3_IN, PTM3_OUT, PTM3_IN_PU),
+ PINMUX_DATA(PTM2_DATA, PTM2_IN, PTM2_OUT, PTM2_IN_PU),
+ PINMUX_DATA(PTM1_DATA, PTM1_IN, PTM1_OUT, PTM1_IN_PU),
+ PINMUX_DATA(PTM0_DATA, PTM0_IN, PTM0_OUT, PTM0_IN_PU),
+
+ /* PTN GPIO */
+ PINMUX_DATA(PTN7_DATA, PTN7_IN, PTN7_OUT, PTN7_IN_PU),
+ PINMUX_DATA(PTN6_DATA, PTN6_IN, PTN6_OUT, PTN6_IN_PU),
+ PINMUX_DATA(PTN5_DATA, PTN5_IN, PTN5_OUT, PTN5_IN_PU),
+ PINMUX_DATA(PTN4_DATA, PTN4_IN, PTN4_OUT, PTN4_IN_PU),
+ PINMUX_DATA(PTN3_DATA, PTN3_IN, PTN3_OUT, PTN3_IN_PU),
+ PINMUX_DATA(PTN2_DATA, PTN2_IN, PTN2_OUT, PTN2_IN_PU),
+ PINMUX_DATA(PTN1_DATA, PTN1_IN, PTN1_OUT, PTN1_IN_PU),
+ PINMUX_DATA(PTN0_DATA, PTN0_IN, PTN0_OUT, PTN0_IN_PU),
+
+ /* PTQ GPIO */
+ PINMUX_DATA(PTQ7_DATA, PTQ7_IN, PTQ7_OUT, PTQ7_IN_PU),
+ PINMUX_DATA(PTQ6_DATA, PTQ6_IN, PTQ6_OUT, PTQ6_IN_PU),
+ PINMUX_DATA(PTQ5_DATA, PTQ5_IN, PTQ5_OUT, PTQ5_IN_PU),
+ PINMUX_DATA(PTQ4_DATA, PTQ4_IN, PTQ4_OUT, PTQ4_IN_PU),
+ PINMUX_DATA(PTQ3_DATA, PTQ3_IN, PTQ3_OUT, PTQ3_IN_PU),
+ PINMUX_DATA(PTQ2_DATA, PTQ2_IN, PTQ2_OUT, PTQ2_IN_PU),
+ PINMUX_DATA(PTQ1_DATA, PTQ1_IN, PTQ1_OUT, PTQ1_IN_PU),
+ PINMUX_DATA(PTQ0_DATA, PTQ0_IN, PTQ0_OUT, PTQ0_IN_PU),
+
+ /* PTR GPIO */
+ PINMUX_DATA(PTR7_DATA, PTR7_IN, PTR7_OUT, PTR7_IN_PU),
+ PINMUX_DATA(PTR6_DATA, PTR6_IN, PTR6_OUT, PTR6_IN_PU),
+ PINMUX_DATA(PTR5_DATA, PTR5_IN, PTR5_OUT, PTR5_IN_PU),
+ PINMUX_DATA(PTR4_DATA, PTR4_IN, PTR4_OUT, PTR4_IN_PU),
+ PINMUX_DATA(PTR3_DATA, PTR3_IN, PTR3_IN_PU),
+ PINMUX_DATA(PTR2_DATA, PTR2_IN, PTR2_IN_PU),
+ PINMUX_DATA(PTR1_DATA, PTR1_IN, PTR1_OUT, PTR1_IN_PU),
+ PINMUX_DATA(PTR0_DATA, PTR0_IN, PTR0_OUT, PTR0_IN_PU),
+
+ /* PTS GPIO */
+ PINMUX_DATA(PTS6_DATA, PTS6_IN, PTS6_OUT, PTS6_IN_PU),
+ PINMUX_DATA(PTS5_DATA, PTS5_IN, PTS5_OUT, PTS5_IN_PU),
+ PINMUX_DATA(PTS4_DATA, PTS4_IN, PTS4_OUT, PTS4_IN_PU),
+ PINMUX_DATA(PTS3_DATA, PTS3_IN, PTS3_OUT, PTS3_IN_PU),
+ PINMUX_DATA(PTS2_DATA, PTS2_IN, PTS2_OUT, PTS2_IN_PU),
+ PINMUX_DATA(PTS1_DATA, PTS1_IN, PTS1_OUT, PTS1_IN_PU),
+ PINMUX_DATA(PTS0_DATA, PTS0_IN, PTS0_OUT, PTS0_IN_PU),
+
+ /* PTT GPIO */
+ PINMUX_DATA(PTT7_DATA, PTT7_IN, PTT7_OUT, PTT7_IN_PU),
+ PINMUX_DATA(PTT6_DATA, PTT6_IN, PTT6_OUT, PTT6_IN_PU),
+ PINMUX_DATA(PTT5_DATA, PTT5_IN, PTT5_OUT, PTT5_IN_PU),
+ PINMUX_DATA(PTT4_DATA, PTT4_IN, PTT4_OUT, PTT4_IN_PU),
+ PINMUX_DATA(PTT3_DATA, PTT3_IN, PTT3_OUT, PTT3_IN_PU),
+ PINMUX_DATA(PTT2_DATA, PTT2_IN, PTT2_OUT, PTT2_IN_PU),
+ PINMUX_DATA(PTT1_DATA, PTT1_IN, PTT1_OUT, PTT1_IN_PU),
+ PINMUX_DATA(PTT0_DATA, PTT0_IN, PTT0_OUT, PTT0_IN_PU),
+
+ /* PTU GPIO */
+ PINMUX_DATA(PTU7_DATA, PTU7_IN, PTU7_OUT, PTU7_IN_PU),
+ PINMUX_DATA(PTU6_DATA, PTU6_IN, PTU6_OUT, PTU6_IN_PU),
+ PINMUX_DATA(PTU5_DATA, PTU5_IN, PTU5_OUT, PTU5_IN_PU),
+ PINMUX_DATA(PTU4_DATA, PTU4_IN, PTU4_OUT, PTU4_IN_PU),
+ PINMUX_DATA(PTU3_DATA, PTU3_IN, PTU3_OUT, PTU3_IN_PU),
+ PINMUX_DATA(PTU2_DATA, PTU2_IN, PTU2_OUT, PTU2_IN_PU),
+ PINMUX_DATA(PTU1_DATA, PTU1_IN, PTU1_OUT, PTU1_IN_PU),
+ PINMUX_DATA(PTU0_DATA, PTU0_IN, PTU0_OUT, PTU0_IN_PU),
+
+ /* PTV GPIO */
+ PINMUX_DATA(PTV7_DATA, PTV7_IN, PTV7_OUT, PTV7_IN_PU),
+ PINMUX_DATA(PTV6_DATA, PTV6_IN, PTV6_OUT, PTV6_IN_PU),
+ PINMUX_DATA(PTV5_DATA, PTV5_IN, PTV5_OUT, PTV5_IN_PU),
+ PINMUX_DATA(PTV4_DATA, PTV4_IN, PTV4_OUT, PTV4_IN_PU),
+ PINMUX_DATA(PTV3_DATA, PTV3_IN, PTV3_OUT, PTV3_IN_PU),
+ PINMUX_DATA(PTV2_DATA, PTV2_IN, PTV2_OUT, PTV2_IN_PU),
+ PINMUX_DATA(PTV1_DATA, PTV1_IN, PTV1_OUT, PTV1_IN_PU),
+ PINMUX_DATA(PTV0_DATA, PTV0_IN, PTV0_OUT, PTV0_IN_PU),
+
+ /* PTW GPIO */
+ PINMUX_DATA(PTW7_DATA, PTW7_IN, PTW7_OUT, PTW7_IN_PU),
+ PINMUX_DATA(PTW6_DATA, PTW6_IN, PTW6_OUT, PTW6_IN_PU),
+ PINMUX_DATA(PTW5_DATA, PTW5_IN, PTW5_OUT, PTW5_IN_PU),
+ PINMUX_DATA(PTW4_DATA, PTW4_IN, PTW4_OUT, PTW4_IN_PU),
+ PINMUX_DATA(PTW3_DATA, PTW3_IN, PTW3_OUT, PTW3_IN_PU),
+ PINMUX_DATA(PTW2_DATA, PTW2_IN, PTW2_OUT, PTW2_IN_PU),
+ PINMUX_DATA(PTW1_DATA, PTW1_IN, PTW1_OUT, PTW1_IN_PU),
+ PINMUX_DATA(PTW0_DATA, PTW0_IN, PTW0_OUT, PTW0_IN_PU),
+
+ /* PTX GPIO */
+ PINMUX_DATA(PTX7_DATA, PTX7_IN, PTX7_OUT, PTX7_IN_PU),
+ PINMUX_DATA(PTX6_DATA, PTX6_IN, PTX6_OUT, PTX6_IN_PU),
+ PINMUX_DATA(PTX5_DATA, PTX5_IN, PTX5_OUT, PTX5_IN_PU),
+ PINMUX_DATA(PTX4_DATA, PTX4_IN, PTX4_OUT, PTX4_IN_PU),
+ PINMUX_DATA(PTX3_DATA, PTX3_IN, PTX3_OUT, PTX3_IN_PU),
+ PINMUX_DATA(PTX2_DATA, PTX2_IN, PTX2_OUT, PTX2_IN_PU),
+ PINMUX_DATA(PTX1_DATA, PTX1_IN, PTX1_OUT, PTX1_IN_PU),
+ PINMUX_DATA(PTX0_DATA, PTX0_IN, PTX0_OUT, PTX0_IN_PU),
+
+ /* PTY GPIO */
+ PINMUX_DATA(PTY7_DATA, PTY7_IN, PTY7_OUT, PTY7_IN_PU),
+ PINMUX_DATA(PTY6_DATA, PTY6_IN, PTY6_OUT, PTY6_IN_PU),
+ PINMUX_DATA(PTY5_DATA, PTY5_IN, PTY5_OUT, PTY5_IN_PU),
+ PINMUX_DATA(PTY4_DATA, PTY4_IN, PTY4_OUT, PTY4_IN_PU),
+ PINMUX_DATA(PTY3_DATA, PTY3_IN, PTY3_OUT, PTY3_IN_PU),
+ PINMUX_DATA(PTY2_DATA, PTY2_IN, PTY2_OUT, PTY2_IN_PU),
+ PINMUX_DATA(PTY1_DATA, PTY1_IN, PTY1_OUT, PTY1_IN_PU),
+ PINMUX_DATA(PTY0_DATA, PTY0_IN, PTY0_OUT, PTY0_IN_PU),
+
+ /* PTZ GPIO */
+ PINMUX_DATA(PTZ7_DATA, PTZ7_IN, PTZ7_OUT, PTZ7_IN_PU),
+ PINMUX_DATA(PTZ6_DATA, PTZ6_IN, PTZ6_OUT, PTZ6_IN_PU),
+ PINMUX_DATA(PTZ5_DATA, PTZ5_IN, PTZ5_OUT, PTZ5_IN_PU),
+ PINMUX_DATA(PTZ4_DATA, PTZ4_IN, PTZ4_OUT, PTZ4_IN_PU),
+ PINMUX_DATA(PTZ3_DATA, PTZ3_IN, PTZ3_OUT, PTZ3_IN_PU),
+ PINMUX_DATA(PTZ2_DATA, PTZ2_IN, PTZ2_OUT, PTZ2_IN_PU),
+ PINMUX_DATA(PTZ1_DATA, PTZ1_IN, PTZ1_OUT, PTZ1_IN_PU),
+ PINMUX_DATA(PTZ0_DATA, PTZ0_IN, PTZ0_OUT, PTZ0_IN_PU),
+
+ /* PTA FN */
+ PINMUX_DATA(D23_MARK, PSA15_0, PSA14_0, PTA7_FN),
+ PINMUX_DATA(D22_MARK, PSA15_0, PSA14_0, PTA6_FN),
+ PINMUX_DATA(D21_MARK, PSA15_0, PSA14_0, PTA5_FN),
+ PINMUX_DATA(D20_MARK, PSA15_0, PSA14_0, PTA4_FN),
+ PINMUX_DATA(D19_MARK, PSA15_0, PSA14_0, PTA3_FN),
+ PINMUX_DATA(D18_MARK, PSA15_0, PSA14_0, PTA2_FN),
+ PINMUX_DATA(D17_MARK, PSA15_0, PSA14_0, PTA1_FN),
+ PINMUX_DATA(D16_MARK, PSA15_0, PSA14_0, PTA0_FN),
+
+ PINMUX_DATA(KEYOUT2_MARK, PSA15_0, PSA14_1, PTA7_FN),
+ PINMUX_DATA(KEYOUT1_MARK, PSA15_0, PSA14_1, PTA6_FN),
+ PINMUX_DATA(KEYOUT0_MARK, PSA15_0, PSA14_1, PTA5_FN),
+ PINMUX_DATA(KEYIN4_MARK, PSA15_0, PSA14_1, PTA4_FN),
+ PINMUX_DATA(KEYIN3_MARK, PSA15_0, PSA14_1, PTA3_FN),
+ PINMUX_DATA(KEYIN2_MARK, PSA15_0, PSA14_1, PTA2_FN),
+ PINMUX_DATA(KEYIN1_MARK, PSA15_0, PSA14_1, PTA1_FN),
+ PINMUX_DATA(KEYIN0_MARK, PSA15_0, PSA14_1, PTA0_FN),
+
+ PINMUX_DATA(IDED15_MARK, PSA15_1, PSA14_0, PTA7_FN),
+ PINMUX_DATA(IDED14_MARK, PSA15_1, PSA14_0, PTA6_FN),
+ PINMUX_DATA(IDED13_MARK, PSA15_1, PSA14_0, PTA5_FN),
+ PINMUX_DATA(IDED12_MARK, PSA15_1, PSA14_0, PTA4_FN),
+ PINMUX_DATA(IDED11_MARK, PSA15_1, PSA14_0, PTA3_FN),
+ PINMUX_DATA(IDED10_MARK, PSA15_1, PSA14_0, PTA2_FN),
+ PINMUX_DATA(IDED9_MARK, PSA15_1, PSA14_0, PTA1_FN),
+ PINMUX_DATA(IDED8_MARK, PSA15_1, PSA14_0, PTA0_FN),
+
+ /* PTB FN */
+ PINMUX_DATA(D31_MARK, PSE15_0, PSE14_0, PTB7_FN),
+ PINMUX_DATA(D30_MARK, PSE15_0, PSE14_0, PTB6_FN),
+ PINMUX_DATA(D29_MARK, PSE11_0, PTB5_FN),
+ PINMUX_DATA(D28_MARK, PSE11_0, PTB4_FN),
+ PINMUX_DATA(D27_MARK, PSE11_0, PTB3_FN),
+ PINMUX_DATA(D26_MARK, PSA15_0, PSA14_0, PTB2_FN),
+ PINMUX_DATA(D25_MARK, PSA15_0, PSA14_0, PTB1_FN),
+ PINMUX_DATA(D24_MARK, PSA15_0, PSA14_0, PTB0_FN),
+
+ PINMUX_DATA(IDEA1_MARK, PSE15_1, PSE14_0, PTB7_FN),
+ PINMUX_DATA(IDEA0_MARK, PSE15_1, PSE14_0, PTB6_FN),
+ PINMUX_DATA(IODREQ_MARK, PSE11_1, PTB5_FN),
+ PINMUX_DATA(IDECS0_MARK, PSE11_1, PTB4_FN),
+ PINMUX_DATA(IDECS1_MARK, PSE11_1, PTB3_FN),
+ PINMUX_DATA(IDEIORD_MARK, PSA15_1, PSA14_0, PTB2_FN),
+ PINMUX_DATA(IDEIOWR_MARK, PSA15_1, PSA14_0, PTB1_FN),
+ PINMUX_DATA(IDEINT_MARK, PSA15_1, PSA14_0, PTB0_FN),
+
+ PINMUX_DATA(TPUTO1_MARK, PSE15_0, PSE14_1, PTB7_FN),
+ PINMUX_DATA(TPUTO0_MARK, PSE15_0, PSE14_1, PTB6_FN),
+
+ PINMUX_DATA(KEYOUT5_IN5_MARK, PSA15_0, PSA14_1, PTB2_FN),
+ PINMUX_DATA(KEYOUT4_IN6_MARK, PSA15_0, PSA14_1, PTB1_FN),
+ PINMUX_DATA(KEYOUT3_MARK, PSA15_0, PSA14_1, PTB0_FN),
+
+ /* PTC FN */
+ PINMUX_DATA(LCDD7_MARK, PSD5_0, PTC7_FN),
+ PINMUX_DATA(LCDD6_MARK, PSD5_0, PTC6_FN),
+ PINMUX_DATA(LCDD5_MARK, PSD5_0, PTC5_FN),
+ PINMUX_DATA(LCDD4_MARK, PSD5_0, PTC4_FN),
+ PINMUX_DATA(LCDD3_MARK, PSD5_0, PTC3_FN),
+ PINMUX_DATA(LCDD2_MARK, PSD5_0, PTC2_FN),
+ PINMUX_DATA(LCDD1_MARK, PSD5_0, PTC1_FN),
+ PINMUX_DATA(LCDD0_MARK, PSD5_0, PTC0_FN),
+
+ /* PTD FN */
+ PINMUX_DATA(LCDD15_MARK, PSD5_0, PTD7_FN),
+ PINMUX_DATA(LCDD14_MARK, PSD5_0, PTD6_FN),
+ PINMUX_DATA(LCDD13_MARK, PSD5_0, PTD5_FN),
+ PINMUX_DATA(LCDD12_MARK, PSD5_0, PTD4_FN),
+ PINMUX_DATA(LCDD11_MARK, PSD5_0, PTD3_FN),
+ PINMUX_DATA(LCDD10_MARK, PSD5_0, PTD2_FN),
+ PINMUX_DATA(LCDD9_MARK, PSD5_0, PTD1_FN),
+ PINMUX_DATA(LCDD8_MARK, PSD5_0, PTD0_FN),
+
+ /* PTE FN */
+ PINMUX_DATA(FSIMCKB_MARK, PTE7_FN),
+ PINMUX_DATA(FSIMCKA_MARK, PTE6_FN),
+
+ PINMUX_DATA(LCDD21_MARK, PSC5_0, PSC4_0, PTE5_FN),
+ PINMUX_DATA(LCDD20_MARK, PSD3_0, PSD2_0, PTE4_FN),
+ PINMUX_DATA(LCDD19_MARK, PSA3_0, PSA2_0, PTE3_FN),
+ PINMUX_DATA(LCDD18_MARK, PSA3_0, PSA2_0, PTE2_FN),
+ PINMUX_DATA(LCDD17_MARK, PSD5_0, PTE1_FN),
+ PINMUX_DATA(LCDD16_MARK, PSD5_0, PTE0_FN),
+
+ PINMUX_DATA(SCIF2_L_TXD_MARK, PSC5_0, PSC4_1, PTE5_FN),
+ PINMUX_DATA(SCIF4_SCK_MARK, PSD3_0, PSD2_1, PTE4_FN),
+ PINMUX_DATA(SCIF4_RXD_MARK, PSA3_0, PSA2_1, PTE3_FN),
+ PINMUX_DATA(SCIF4_TXD_MARK, PSA3_0, PSA2_1, PTE2_FN),
+
+ /* PTF FN */
+ PINMUX_DATA(LCDVSYN_MARK, PSD8_0, PTF7_FN),
+ PINMUX_DATA(LCDDISP_MARK, PSD10_0, PSD9_0, PTF6_FN),
+ PINMUX_DATA(LCDHSYN_MARK, PSD10_0, PSD9_0, PTF5_FN),
+ PINMUX_DATA(LCDDON_MARK, PSD8_0, PTF4_FN),
+ PINMUX_DATA(LCDDCK_MARK, PSD10_0, PSD9_0, PTF3_FN),
+ PINMUX_DATA(LCDVEPWC_MARK, PSA6_0, PTF2_FN),
+ PINMUX_DATA(LCDD23_MARK, PSC7_0, PSC6_0, PTF1_FN),
+ PINMUX_DATA(LCDD22_MARK, PSC5_0, PSC4_0, PTF0_FN),
+
+ PINMUX_DATA(LCDRS_MARK, PSD10_0, PSD9_1, PTF6_FN),
+ PINMUX_DATA(LCDCS_MARK, PSD10_0, PSD9_1, PTF5_FN),
+ PINMUX_DATA(LCDWR_MARK, PSD10_0, PSD9_1, PTF3_FN),
+
+ PINMUX_DATA(SCIF0_TXD_MARK, PSA6_1, PTF2_FN),
+ PINMUX_DATA(SCIF2_L_SCK_MARK, PSC7_0, PSC6_1, PTF1_FN),
+ PINMUX_DATA(SCIF2_L_RXD_MARK, PSC5_0, PSC4_1, PTF0_FN),
+
+ /* PTG FN */
+ PINMUX_DATA(AUDCK_MARK, PTG5_FN),
+ PINMUX_DATA(AUDSYNC_MARK, PTG4_FN),
+ PINMUX_DATA(AUDATA3_MARK, PTG3_FN),
+ PINMUX_DATA(AUDATA2_MARK, PTG2_FN),
+ PINMUX_DATA(AUDATA1_MARK, PTG1_FN),
+ PINMUX_DATA(AUDATA0_MARK, PTG0_FN),
+
+ /* PTH FN */
+ PINMUX_DATA(VIO0_VD_MARK, PTH7_FN),
+ PINMUX_DATA(VIO0_CLK_MARK, PTH6_FN),
+ PINMUX_DATA(VIO0_D7_MARK, PTH5_FN),
+ PINMUX_DATA(VIO0_D6_MARK, PTH4_FN),
+ PINMUX_DATA(VIO0_D5_MARK, PTH3_FN),
+ PINMUX_DATA(VIO0_D4_MARK, PTH2_FN),
+ PINMUX_DATA(VIO0_D3_MARK, PTH1_FN),
+ PINMUX_DATA(VIO0_D2_MARK, PTH0_FN),
+
+ /* PTJ FN */
+ PINMUX_DATA(PDSTATUS_MARK, PTJ7_FN),
+ PINMUX_DATA(STATUS2_MARK, PTJ6_FN),
+ PINMUX_DATA(STATUS0_MARK, PTJ5_FN),
+ PINMUX_DATA(A25_MARK, PSA8_0, PTJ3_FN),
+ PINMUX_DATA(BS_MARK, PSA8_1, PTJ3_FN),
+ PINMUX_DATA(A24_MARK, PTJ2_FN),
+ PINMUX_DATA(A23_MARK, PTJ1_FN),
+ PINMUX_DATA(A22_MARK, PTJ0_FN),
+
+ /* PTK FN */
+ PINMUX_DATA(VIO1_D5_MARK, PSB7_0, PSB6_0, PTK7_FN),
+ PINMUX_DATA(VIO1_D4_MARK, PSB7_0, PSB6_0, PTK6_FN),
+ PINMUX_DATA(VIO1_D3_MARK, PSB7_0, PSB6_0, PTK5_FN),
+ PINMUX_DATA(VIO1_D2_MARK, PSB7_0, PSB6_0, PTK4_FN),
+ PINMUX_DATA(VIO1_D1_MARK, PSB7_0, PSB6_0, PTK3_FN),
+ PINMUX_DATA(VIO1_D0_MARK, PSB7_0, PSB6_0, PTK2_FN),
+
+ PINMUX_DATA(VIO0_D13_MARK, PSB7_0, PSB6_1, PTK7_FN),
+ PINMUX_DATA(VIO0_D12_MARK, PSB7_0, PSB6_1, PTK6_FN),
+ PINMUX_DATA(VIO0_D11_MARK, PSB7_0, PSB6_1, PTK5_FN),
+ PINMUX_DATA(VIO0_D10_MARK, PSB7_0, PSB6_1, PTK4_FN),
+ PINMUX_DATA(VIO0_D9_MARK, PSB7_0, PSB6_1, PTK3_FN),
+ PINMUX_DATA(VIO0_D8_MARK, PSB7_0, PSB6_1, PTK2_FN),
+
+ PINMUX_DATA(IDED5_MARK, PSB7_1, PSB6_0, PTK7_FN),
+ PINMUX_DATA(IDED4_MARK, PSB7_1, PSB6_0, PTK6_FN),
+ PINMUX_DATA(IDED3_MARK, PSB7_1, PSB6_0, PTK5_FN),
+ PINMUX_DATA(IDED2_MARK, PSB7_1, PSB6_0, PTK4_FN),
+ PINMUX_DATA(IDED1_MARK, PSB7_1, PSB6_0, PTK3_FN),
+ PINMUX_DATA(IDED0_MARK, PSB7_1, PSB6_0, PTK2_FN),
+
+ PINMUX_DATA(VIO0_FLD_MARK, PTK1_FN),
+ PINMUX_DATA(VIO0_HD_MARK, PTK0_FN),
+
+ /* PTL FN */
+ PINMUX_DATA(DV_D5_MARK, PSB9_0, PSB8_0, PTL7_FN),
+ PINMUX_DATA(DV_D4_MARK, PSB9_0, PSB8_0, PTL6_FN),
+ PINMUX_DATA(DV_D3_MARK, PSE7_0, PSE6_0, PTL5_FN),
+ PINMUX_DATA(DV_D2_MARK, PSC9_0, PSC8_0, PTL4_FN),
+ PINMUX_DATA(DV_D1_MARK, PSC9_0, PSC8_0, PTL3_FN),
+ PINMUX_DATA(DV_D0_MARK, PSC9_0, PSC8_0, PTL2_FN),
+ PINMUX_DATA(DV_D15_MARK, PSD4_0, PTL1_FN),
+ PINMUX_DATA(DV_D14_MARK, PSE5_0, PSE4_0, PTL0_FN),
+
+ PINMUX_DATA(SCIF3_V_SCK_MARK, PSB9_0, PSB8_1, PTL7_FN),
+ PINMUX_DATA(SCIF3_V_RXD_MARK, PSB9_0, PSB8_1, PTL6_FN),
+ PINMUX_DATA(SCIF3_V_TXD_MARK, PSE7_0, PSE6_1, PTL5_FN),
+ PINMUX_DATA(SCIF1_SCK_MARK, PSC9_0, PSC8_1, PTL4_FN),
+ PINMUX_DATA(SCIF1_RXD_MARK, PSC9_0, PSC8_1, PTL3_FN),
+ PINMUX_DATA(SCIF1_TXD_MARK, PSC9_0, PSC8_1, PTL2_FN),
+
+ PINMUX_DATA(RMII_RXD0_MARK, PSB9_1, PSB8_0, PTL7_FN),
+ PINMUX_DATA(RMII_RXD1_MARK, PSB9_1, PSB8_0, PTL6_FN),
+ PINMUX_DATA(RMII_REF_CLK_MARK, PSE7_1, PSE6_0, PTL5_FN),
+ PINMUX_DATA(RMII_TX_EN_MARK, PSC9_1, PSC8_0, PTL4_FN),
+ PINMUX_DATA(RMII_TXD0_MARK, PSC9_1, PSC8_0, PTL3_FN),
+ PINMUX_DATA(RMII_TXD1_MARK, PSC9_1, PSC8_0, PTL2_FN),
+
+ PINMUX_DATA(MSIOF0_MCK_MARK, PSE5_0, PSE4_1, PTL0_FN),
+
+ /* PTM FN */
+ PINMUX_DATA(DV_D13_MARK, PSC13_0, PSC12_0, PTM7_FN),
+ PINMUX_DATA(DV_D12_MARK, PSC13_0, PSC12_0, PTM6_FN),
+ PINMUX_DATA(DV_D11_MARK, PSC13_0, PSC12_0, PTM5_FN),
+ PINMUX_DATA(DV_D10_MARK, PSC13_0, PSC12_0, PTM4_FN),
+ PINMUX_DATA(DV_D9_MARK, PSC11_0, PSC10_0, PTM3_FN),
+ PINMUX_DATA(DV_D8_MARK, PSC11_0, PSC10_0, PTM2_FN),
+
+ PINMUX_DATA(MSIOF0_TSCK_MARK, PSC13_0, PSC12_1, PTM7_FN),
+ PINMUX_DATA(MSIOF0_RXD_MARK, PSC13_0, PSC12_1, PTM6_FN),
+ PINMUX_DATA(MSIOF0_TXD_MARK, PSC13_0, PSC12_1, PTM5_FN),
+ PINMUX_DATA(MSIOF0_TSYNC_MARK, PSC13_0, PSC12_1, PTM4_FN),
+ PINMUX_DATA(MSIOF0_SS1_MARK, PSC11_0, PSC10_1, PTM3_FN),
+ PINMUX_DATA(MSIOF0_RSCK_MARK, PSC11_1, PSC10_0, PTM3_FN),
+ PINMUX_DATA(MSIOF0_SS2_MARK, PSC11_0, PSC10_1, PTM2_FN),
+ PINMUX_DATA(MSIOF0_RSYNC_MARK, PSC11_1, PSC10_0, PTM2_FN),
+
+ PINMUX_DATA(LCDVCPWC_MARK, PSA6_0, PTM1_FN),
+ PINMUX_DATA(LCDRD_MARK, PSA7_0, PTM0_FN),
+
+ PINMUX_DATA(SCIF0_RXD_MARK, PSA6_1, PTM1_FN),
+ PINMUX_DATA(SCIF0_SCK_MARK, PSA7_1, PTM0_FN),
+
+ /* PTN FN */
+ PINMUX_DATA(VIO0_D1_MARK, PTN7_FN),
+ PINMUX_DATA(VIO0_D0_MARK, PTN6_FN),
+
+ PINMUX_DATA(DV_CLKI_MARK, PSD11_0, PTN5_FN),
+ PINMUX_DATA(DV_CLK_MARK, PSD13_0, PSD12_0, PTN4_FN),
+ PINMUX_DATA(DV_VSYNC_MARK, PSD15_0, PSD14_0, PTN3_FN),
+ PINMUX_DATA(DV_HSYNC_MARK, PSB5_0, PSB4_0, PTN2_FN),
+ PINMUX_DATA(DV_D7_MARK, PSB3_0, PSB2_0, PTN1_FN),
+ PINMUX_DATA(DV_D6_MARK, PSB1_0, PSB0_0, PTN0_FN),
+
+ PINMUX_DATA(SCIF2_V_SCK_MARK, PSD13_0, PSD12_1, PTN4_FN),
+ PINMUX_DATA(SCIF2_V_RXD_MARK, PSD15_0, PSD14_1, PTN3_FN),
+ PINMUX_DATA(SCIF2_V_TXD_MARK, PSB5_0, PSB4_1, PTN2_FN),
+ PINMUX_DATA(SCIF3_V_CTS_MARK, PSB3_0, PSB2_1, PTN1_FN),
+ PINMUX_DATA(SCIF3_V_RTS_MARK, PSB1_0, PSB0_1, PTN0_FN),
+
+ PINMUX_DATA(RMII_RX_ER_MARK, PSB3_1, PSB2_0, PTN1_FN),
+ PINMUX_DATA(RMII_CRS_DV_MARK, PSB1_1, PSB0_0, PTN0_FN),
+
+ /* PTQ FN */
+ PINMUX_DATA(D7_MARK, PTQ7_FN),
+ PINMUX_DATA(D6_MARK, PTQ6_FN),
+ PINMUX_DATA(D5_MARK, PTQ5_FN),
+ PINMUX_DATA(D4_MARK, PTQ4_FN),
+ PINMUX_DATA(D3_MARK, PTQ3_FN),
+ PINMUX_DATA(D2_MARK, PTQ2_FN),
+ PINMUX_DATA(D1_MARK, PTQ1_FN),
+ PINMUX_DATA(D0_MARK, PTQ0_FN),
+
+ /* PTR FN */
+ PINMUX_DATA(CS6B_CE1B_MARK, PTR7_FN),
+ PINMUX_DATA(CS6A_CE2B_MARK, PTR6_FN),
+ PINMUX_DATA(CS5B_CE1A_MARK, PTR5_FN),
+ PINMUX_DATA(CS5A_CE2A_MARK, PTR4_FN),
+ PINMUX_DATA(IOIS16_MARK, PSA5_0, PTR3_FN),
+ PINMUX_DATA(WAIT_MARK, PTR2_FN),
+ PINMUX_DATA(WE3_ICIOWR_MARK, PSA1_0, PSA0_0, PTR1_FN),
+ PINMUX_DATA(WE2_ICIORD_MARK, PSD1_0, PSD0_0, PTR0_FN),
+
+ PINMUX_DATA(LCDLCLK_MARK, PSA5_1, PTR3_FN),
+
+ PINMUX_DATA(IDEA2_MARK, PSD1_1, PSD0_0, PTR0_FN),
+
+ PINMUX_DATA(TPUTO3_MARK, PSA1_0, PSA0_1, PTR1_FN),
+ PINMUX_DATA(TPUTI3_MARK, PSA1_1, PSA0_0, PTR1_FN),
+ PINMUX_DATA(TPUTO2_MARK, PSD1_0, PSD0_1, PTR0_FN),
+
+ /* PTS FN */
+ PINMUX_DATA(VIO_CKO_MARK, PTS6_FN),
+
+ PINMUX_DATA(TPUTI2_MARK, PSE9_0, PSE8_1, PTS5_FN),
+
+ PINMUX_DATA(IDEIORDY_MARK, PSE9_1, PSE8_0, PTS5_FN),
+
+ PINMUX_DATA(VIO1_FLD_MARK, PSE9_0, PSE8_0, PTS5_FN),
+ PINMUX_DATA(VIO1_HD_MARK, PSA10_0, PTS4_FN),
+ PINMUX_DATA(VIO1_VD_MARK, PSA9_0, PTS3_FN),
+ PINMUX_DATA(VIO1_CLK_MARK, PSA9_0, PTS2_FN),
+ PINMUX_DATA(VIO1_D7_MARK, PSB7_0, PSB6_0, PTS1_FN),
+ PINMUX_DATA(VIO1_D6_MARK, PSB7_0, PSB6_0, PTS0_FN),
+
+ PINMUX_DATA(SCIF5_SCK_MARK, PSA10_1, PTS4_FN),
+ PINMUX_DATA(SCIF5_RXD_MARK, PSA9_1, PTS3_FN),
+ PINMUX_DATA(SCIF5_TXD_MARK, PSA9_1, PTS2_FN),
+
+ PINMUX_DATA(VIO0_D15_MARK, PSB7_0, PSB6_1, PTS1_FN),
+ PINMUX_DATA(VIO0_D14_MARK, PSB7_0, PSB6_1, PTS0_FN),
+
+ PINMUX_DATA(IDED7_MARK, PSB7_1, PSB6_0, PTS1_FN),
+ PINMUX_DATA(IDED6_MARK, PSB7_1, PSB6_0, PTS0_FN),
+
+ /* PTT FN */
+ PINMUX_DATA(D15_MARK, PTT7_FN),
+ PINMUX_DATA(D14_MARK, PTT6_FN),
+ PINMUX_DATA(D13_MARK, PTT5_FN),
+ PINMUX_DATA(D12_MARK, PTT4_FN),
+ PINMUX_DATA(D11_MARK, PTT3_FN),
+ PINMUX_DATA(D10_MARK, PTT2_FN),
+ PINMUX_DATA(D9_MARK, PTT1_FN),
+ PINMUX_DATA(D8_MARK, PTT0_FN),
+
+ /* PTU FN */
+ PINMUX_DATA(DMAC_DACK0_MARK, PTU7_FN),
+ PINMUX_DATA(DMAC_DREQ0_MARK, PTU6_FN),
+
+ PINMUX_DATA(FSIOASD_MARK, PSE1_0, PTU5_FN),
+ PINMUX_DATA(FSIIABCK_MARK, PSE1_0, PTU4_FN),
+ PINMUX_DATA(FSIIALRCK_MARK, PSE1_0, PTU3_FN),
+ PINMUX_DATA(FSIOABCK_MARK, PSE1_0, PTU2_FN),
+ PINMUX_DATA(FSIOALRCK_MARK, PSE1_0, PTU1_FN),
+ PINMUX_DATA(CLKAUDIOAO_MARK, PSE0_0, PTU0_FN),
+
+ /* PTV FN */
+ PINMUX_DATA(FSIIBSD_MARK, PSD7_0, PSD6_0, PTV7_FN),
+ PINMUX_DATA(FSIOBSD_MARK, PSD7_0, PSD6_0, PTV6_FN),
+ PINMUX_DATA(FSIIBBCK_MARK, PSC15_0, PSC14_0, PTV5_FN),
+ PINMUX_DATA(FSIIBLRCK_MARK, PSC15_0, PSC14_0, PTV4_FN),
+ PINMUX_DATA(FSIOBBCK_MARK, PSC15_0, PSC14_0, PTV3_FN),
+ PINMUX_DATA(FSIOBLRCK_MARK, PSC15_0, PSC14_0, PTV2_FN),
+ PINMUX_DATA(CLKAUDIOBO_MARK, PSE3_0, PSE2_0, PTV1_FN),
+ PINMUX_DATA(FSIIASD_MARK, PSE10_0, PTV0_FN),
+
+ PINMUX_DATA(MSIOF1_SS2_MARK, PSD7_0, PSD6_1, PTV7_FN),
+ PINMUX_DATA(MSIOF1_RSYNC_MARK, PSD7_1, PSD6_0, PTV7_FN),
+ PINMUX_DATA(MSIOF1_SS1_MARK, PSD7_0, PSD6_1, PTV6_FN),
+ PINMUX_DATA(MSIOF1_RSCK_MARK, PSD7_1, PSD6_0, PTV6_FN),
+ PINMUX_DATA(MSIOF1_RXD_MARK, PSC15_0, PSC14_1, PTV5_FN),
+ PINMUX_DATA(MSIOF1_TSYNC_MARK, PSC15_0, PSC14_1, PTV4_FN),
+ PINMUX_DATA(MSIOF1_TSCK_MARK, PSC15_0, PSC14_1, PTV3_FN),
+ PINMUX_DATA(MSIOF1_TXD_MARK, PSC15_0, PSC14_1, PTV2_FN),
+ PINMUX_DATA(MSIOF1_MCK_MARK, PSE3_0, PSE2_1, PTV1_FN),
+
+ /* PTW FN */
+ PINMUX_DATA(MMC_D7_MARK, PSE13_0, PSE12_0, PTW7_FN),
+ PINMUX_DATA(MMC_D6_MARK, PSE13_0, PSE12_0, PTW6_FN),
+ PINMUX_DATA(MMC_D5_MARK, PSE13_0, PSE12_0, PTW5_FN),
+ PINMUX_DATA(MMC_D4_MARK, PSE13_0, PSE12_0, PTW4_FN),
+ PINMUX_DATA(MMC_D3_MARK, PSA13_0, PTW3_FN),
+ PINMUX_DATA(MMC_D2_MARK, PSA13_0, PTW2_FN),
+ PINMUX_DATA(MMC_D1_MARK, PSA13_0, PTW1_FN),
+ PINMUX_DATA(MMC_D0_MARK, PSA13_0, PTW0_FN),
+
+ PINMUX_DATA(SDHI1CD_MARK, PSE13_0, PSE12_1, PTW7_FN),
+ PINMUX_DATA(SDHI1WP_MARK, PSE13_0, PSE12_1, PTW6_FN),
+ PINMUX_DATA(SDHI1D3_MARK, PSE13_0, PSE12_1, PTW5_FN),
+ PINMUX_DATA(SDHI1D2_MARK, PSE13_0, PSE12_1, PTW4_FN),
+ PINMUX_DATA(SDHI1D1_MARK, PSA13_1, PTW3_FN),
+ PINMUX_DATA(SDHI1D0_MARK, PSA13_1, PTW2_FN),
+ PINMUX_DATA(SDHI1CMD_MARK, PSA13_1, PTW1_FN),
+ PINMUX_DATA(SDHI1CLK_MARK, PSA13_1, PTW0_FN),
+
+ PINMUX_DATA(IODACK_MARK, PSE13_1, PSE12_0, PTW7_FN),
+ PINMUX_DATA(IDERST_MARK, PSE13_1, PSE12_0, PTW6_FN),
+ PINMUX_DATA(EXBUF_ENB_MARK, PSE13_1, PSE12_0, PTW5_FN),
+ PINMUX_DATA(DIRECTION_MARK, PSE13_1, PSE12_0, PTW4_FN),
+
+ /* PTX FN */
+ PINMUX_DATA(DMAC_DACK1_MARK, PSA12_0, PTX7_FN),
+ PINMUX_DATA(DMAC_DREQ1_MARK, PSA12_0, PTX6_FN),
+
+ PINMUX_DATA(IRDA_OUT_MARK, PSA12_1, PTX7_FN),
+ PINMUX_DATA(IRDA_IN_MARK, PSA12_1, PTX6_FN),
+
+ PINMUX_DATA(TSIF_TS0_SDAT_MARK, PSC0_0, PTX5_FN),
+ PINMUX_DATA(TSIF_TS0_SCK_MARK, PSC1_0, PTX4_FN),
+ PINMUX_DATA(TSIF_TS0_SDEN_MARK, PSC2_0, PTX3_FN),
+ PINMUX_DATA(TSIF_TS0_SPSYNC_MARK, PTX2_FN),
+
+ PINMUX_DATA(LNKSTA_MARK, PSC0_1, PTX5_FN),
+ PINMUX_DATA(MDIO_MARK, PSC1_1, PTX4_FN),
+ PINMUX_DATA(MDC_MARK, PSC2_1, PTX3_FN),
+
+ PINMUX_DATA(MMC_CLK_MARK, PTX1_FN),
+ PINMUX_DATA(MMC_CMD_MARK, PTX0_FN),
+
+ /* PTY FN */
+ PINMUX_DATA(SDHI0CD_MARK, PTY7_FN),
+ PINMUX_DATA(SDHI0WP_MARK, PTY6_FN),
+ PINMUX_DATA(SDHI0D3_MARK, PTY5_FN),
+ PINMUX_DATA(SDHI0D2_MARK, PTY4_FN),
+ PINMUX_DATA(SDHI0D1_MARK, PTY3_FN),
+ PINMUX_DATA(SDHI0D0_MARK, PTY2_FN),
+ PINMUX_DATA(SDHI0CMD_MARK, PTY1_FN),
+ PINMUX_DATA(SDHI0CLK_MARK, PTY0_FN),
+
+ /* PTZ FN */
+ PINMUX_DATA(INTC_IRQ7_MARK, PSB10_0, PTZ7_FN),
+ PINMUX_DATA(INTC_IRQ6_MARK, PSB11_0, PTZ6_FN),
+ PINMUX_DATA(INTC_IRQ5_MARK, PSB12_0, PTZ5_FN),
+ PINMUX_DATA(INTC_IRQ4_MARK, PSB13_0, PTZ4_FN),
+ PINMUX_DATA(INTC_IRQ3_MARK, PSB14_0, PTZ3_FN),
+ PINMUX_DATA(INTC_IRQ2_MARK, PTZ2_FN),
+ PINMUX_DATA(INTC_IRQ1_MARK, PTZ1_FN),
+ PINMUX_DATA(INTC_IRQ0_MARK, PTZ0_FN),
+
+ PINMUX_DATA(SCIF3_I_CTS_MARK, PSB10_1, PTZ7_FN),
+ PINMUX_DATA(SCIF3_I_RTS_MARK, PSB11_1, PTZ6_FN),
+ PINMUX_DATA(SCIF3_I_SCK_MARK, PSB12_1, PTZ5_FN),
+ PINMUX_DATA(SCIF3_I_RXD_MARK, PSB13_1, PTZ4_FN),
+ PINMUX_DATA(SCIF3_I_TXD_MARK, PSB14_1, PTZ3_FN),
+};
+
+static struct pinmux_gpio pinmux_gpios[] = {
+ /* PTA */
+ PINMUX_GPIO(GPIO_PTA7, PTA7_DATA),
+ PINMUX_GPIO(GPIO_PTA6, PTA6_DATA),
+ PINMUX_GPIO(GPIO_PTA5, PTA5_DATA),
+ PINMUX_GPIO(GPIO_PTA4, PTA4_DATA),
+ PINMUX_GPIO(GPIO_PTA3, PTA3_DATA),
+ PINMUX_GPIO(GPIO_PTA2, PTA2_DATA),
+ PINMUX_GPIO(GPIO_PTA1, PTA1_DATA),
+ PINMUX_GPIO(GPIO_PTA0, PTA0_DATA),
+
+ /* PTB */
+ PINMUX_GPIO(GPIO_PTB7, PTB7_DATA),
+ PINMUX_GPIO(GPIO_PTB6, PTB6_DATA),
+ PINMUX_GPIO(GPIO_PTB5, PTB5_DATA),
+ PINMUX_GPIO(GPIO_PTB4, PTB4_DATA),
+ PINMUX_GPIO(GPIO_PTB3, PTB3_DATA),
+ PINMUX_GPIO(GPIO_PTB2, PTB2_DATA),
+ PINMUX_GPIO(GPIO_PTB1, PTB1_DATA),
+ PINMUX_GPIO(GPIO_PTB0, PTB0_DATA),
+
+ /* PTC */
+ PINMUX_GPIO(GPIO_PTC7, PTC7_DATA),
+ PINMUX_GPIO(GPIO_PTC6, PTC6_DATA),
+ PINMUX_GPIO(GPIO_PTC5, PTC5_DATA),
+ PINMUX_GPIO(GPIO_PTC4, PTC4_DATA),
+ PINMUX_GPIO(GPIO_PTC3, PTC3_DATA),
+ PINMUX_GPIO(GPIO_PTC2, PTC2_DATA),
+ PINMUX_GPIO(GPIO_PTC1, PTC1_DATA),
+ PINMUX_GPIO(GPIO_PTC0, PTC0_DATA),
+
+ /* PTD */
+ PINMUX_GPIO(GPIO_PTD7, PTD7_DATA),
+ PINMUX_GPIO(GPIO_PTD6, PTD6_DATA),
+ PINMUX_GPIO(GPIO_PTD5, PTD5_DATA),
+ PINMUX_GPIO(GPIO_PTD4, PTD4_DATA),
+ PINMUX_GPIO(GPIO_PTD3, PTD3_DATA),
+ PINMUX_GPIO(GPIO_PTD2, PTD2_DATA),
+ PINMUX_GPIO(GPIO_PTD1, PTD1_DATA),
+ PINMUX_GPIO(GPIO_PTD0, PTD0_DATA),
+
+ /* PTE */
+ PINMUX_GPIO(GPIO_PTE7, PTE7_DATA),
+ PINMUX_GPIO(GPIO_PTE6, PTE6_DATA),
+ PINMUX_GPIO(GPIO_PTE5, PTE5_DATA),
+ PINMUX_GPIO(GPIO_PTE4, PTE4_DATA),
+ PINMUX_GPIO(GPIO_PTE3, PTE3_DATA),
+ PINMUX_GPIO(GPIO_PTE2, PTE2_DATA),
+ PINMUX_GPIO(GPIO_PTE1, PTE1_DATA),
+ PINMUX_GPIO(GPIO_PTE0, PTE0_DATA),
+
+ /* PTF */
+ PINMUX_GPIO(GPIO_PTF7, PTF7_DATA),
+ PINMUX_GPIO(GPIO_PTF6, PTF6_DATA),
+ PINMUX_GPIO(GPIO_PTF5, PTF5_DATA),
+ PINMUX_GPIO(GPIO_PTF4, PTF4_DATA),
+ PINMUX_GPIO(GPIO_PTF3, PTF3_DATA),
+ PINMUX_GPIO(GPIO_PTF2, PTF2_DATA),
+ PINMUX_GPIO(GPIO_PTF1, PTF1_DATA),
+ PINMUX_GPIO(GPIO_PTF0, PTF0_DATA),
+
+ /* PTG */
+ PINMUX_GPIO(GPIO_PTG5, PTG5_DATA),
+ PINMUX_GPIO(GPIO_PTG4, PTG4_DATA),
+ PINMUX_GPIO(GPIO_PTG3, PTG3_DATA),
+ PINMUX_GPIO(GPIO_PTG2, PTG2_DATA),
+ PINMUX_GPIO(GPIO_PTG1, PTG1_DATA),
+ PINMUX_GPIO(GPIO_PTG0, PTG0_DATA),
+
+ /* PTH */
+ PINMUX_GPIO(GPIO_PTH7, PTH7_DATA),
+ PINMUX_GPIO(GPIO_PTH6, PTH6_DATA),
+ PINMUX_GPIO(GPIO_PTH5, PTH5_DATA),
+ PINMUX_GPIO(GPIO_PTH4, PTH4_DATA),
+ PINMUX_GPIO(GPIO_PTH3, PTH3_DATA),
+ PINMUX_GPIO(GPIO_PTH2, PTH2_DATA),
+ PINMUX_GPIO(GPIO_PTH1, PTH1_DATA),
+ PINMUX_GPIO(GPIO_PTH0, PTH0_DATA),
+
+ /* PTJ */
+ PINMUX_GPIO(GPIO_PTJ7, PTJ7_DATA),
+ PINMUX_GPIO(GPIO_PTJ6, PTJ6_DATA),
+ PINMUX_GPIO(GPIO_PTJ5, PTJ5_DATA),
+ PINMUX_GPIO(GPIO_PTJ3, PTJ3_DATA),
+ PINMUX_GPIO(GPIO_PTJ2, PTJ2_DATA),
+ PINMUX_GPIO(GPIO_PTJ1, PTJ1_DATA),
+ PINMUX_GPIO(GPIO_PTJ0, PTJ0_DATA),
+
+ /* PTK */
+ PINMUX_GPIO(GPIO_PTK7, PTK7_DATA),
+ PINMUX_GPIO(GPIO_PTK6, PTK6_DATA),
+ PINMUX_GPIO(GPIO_PTK5, PTK5_DATA),
+ PINMUX_GPIO(GPIO_PTK4, PTK4_DATA),
+ PINMUX_GPIO(GPIO_PTK3, PTK3_DATA),
+ PINMUX_GPIO(GPIO_PTK2, PTK2_DATA),
+ PINMUX_GPIO(GPIO_PTK1, PTK1_DATA),
+ PINMUX_GPIO(GPIO_PTK0, PTK0_DATA),
+
+ /* PTL */
+ PINMUX_GPIO(GPIO_PTL7, PTL7_DATA),
+ PINMUX_GPIO(GPIO_PTL6, PTL6_DATA),
+ PINMUX_GPIO(GPIO_PTL5, PTL5_DATA),
+ PINMUX_GPIO(GPIO_PTL4, PTL4_DATA),
+ PINMUX_GPIO(GPIO_PTL3, PTL3_DATA),
+ PINMUX_GPIO(GPIO_PTL2, PTL2_DATA),
+ PINMUX_GPIO(GPIO_PTL1, PTL1_DATA),
+ PINMUX_GPIO(GPIO_PTL0, PTL0_DATA),
+
+ /* PTM */
+ PINMUX_GPIO(GPIO_PTM7, PTM7_DATA),
+ PINMUX_GPIO(GPIO_PTM6, PTM6_DATA),
+ PINMUX_GPIO(GPIO_PTM5, PTM5_DATA),
+ PINMUX_GPIO(GPIO_PTM4, PTM4_DATA),
+ PINMUX_GPIO(GPIO_PTM3, PTM3_DATA),
+ PINMUX_GPIO(GPIO_PTM2, PTM2_DATA),
+ PINMUX_GPIO(GPIO_PTM1, PTM1_DATA),
+ PINMUX_GPIO(GPIO_PTM0, PTM0_DATA),
+
+ /* PTN */
+ PINMUX_GPIO(GPIO_PTN7, PTN7_DATA),
+ PINMUX_GPIO(GPIO_PTN6, PTN6_DATA),
+ PINMUX_GPIO(GPIO_PTN5, PTN5_DATA),
+ PINMUX_GPIO(GPIO_PTN4, PTN4_DATA),
+ PINMUX_GPIO(GPIO_PTN3, PTN3_DATA),
+ PINMUX_GPIO(GPIO_PTN2, PTN2_DATA),
+ PINMUX_GPIO(GPIO_PTN1, PTN1_DATA),
+ PINMUX_GPIO(GPIO_PTN0, PTN0_DATA),
+
+ /* PTQ */
+ PINMUX_GPIO(GPIO_PTQ7, PTQ7_DATA),
+ PINMUX_GPIO(GPIO_PTQ6, PTQ6_DATA),
+ PINMUX_GPIO(GPIO_PTQ5, PTQ5_DATA),
+ PINMUX_GPIO(GPIO_PTQ4, PTQ4_DATA),
+ PINMUX_GPIO(GPIO_PTQ3, PTQ3_DATA),
+ PINMUX_GPIO(GPIO_PTQ2, PTQ2_DATA),
+ PINMUX_GPIO(GPIO_PTQ1, PTQ1_DATA),
+ PINMUX_GPIO(GPIO_PTQ0, PTQ0_DATA),
+
+ /* PTR */
+ PINMUX_GPIO(GPIO_PTR7, PTR7_DATA),
+ PINMUX_GPIO(GPIO_PTR6, PTR6_DATA),
+ PINMUX_GPIO(GPIO_PTR5, PTR5_DATA),
+ PINMUX_GPIO(GPIO_PTR4, PTR4_DATA),
+ PINMUX_GPIO(GPIO_PTR3, PTR3_DATA),
+ PINMUX_GPIO(GPIO_PTR2, PTR2_DATA),
+ PINMUX_GPIO(GPIO_PTR1, PTR1_DATA),
+ PINMUX_GPIO(GPIO_PTR0, PTR0_DATA),
+
+ /* PTS */
+ PINMUX_GPIO(GPIO_PTS6, PTS6_DATA),
+ PINMUX_GPIO(GPIO_PTS5, PTS5_DATA),
+ PINMUX_GPIO(GPIO_PTS4, PTS4_DATA),
+ PINMUX_GPIO(GPIO_PTS3, PTS3_DATA),
+ PINMUX_GPIO(GPIO_PTS2, PTS2_DATA),
+ PINMUX_GPIO(GPIO_PTS1, PTS1_DATA),
+ PINMUX_GPIO(GPIO_PTS0, PTS0_DATA),
+
+ /* PTT */
+ PINMUX_GPIO(GPIO_PTT7, PTT7_DATA),
+ PINMUX_GPIO(GPIO_PTT6, PTT6_DATA),
+ PINMUX_GPIO(GPIO_PTT5, PTT5_DATA),
+ PINMUX_GPIO(GPIO_PTT4, PTT4_DATA),
+ PINMUX_GPIO(GPIO_PTT3, PTT3_DATA),
+ PINMUX_GPIO(GPIO_PTT2, PTT2_DATA),
+ PINMUX_GPIO(GPIO_PTT1, PTT1_DATA),
+ PINMUX_GPIO(GPIO_PTT0, PTT0_DATA),
+
+ /* PTU */
+ PINMUX_GPIO(GPIO_PTU7, PTU7_DATA),
+ PINMUX_GPIO(GPIO_PTU6, PTU6_DATA),
+ PINMUX_GPIO(GPIO_PTU5, PTU5_DATA),
+ PINMUX_GPIO(GPIO_PTU4, PTU4_DATA),
+ PINMUX_GPIO(GPIO_PTU3, PTU3_DATA),
+ PINMUX_GPIO(GPIO_PTU2, PTU2_DATA),
+ PINMUX_GPIO(GPIO_PTU1, PTU1_DATA),
+ PINMUX_GPIO(GPIO_PTU0, PTU0_DATA),
+
+ /* PTV */
+ PINMUX_GPIO(GPIO_PTV7, PTV7_DATA),
+ PINMUX_GPIO(GPIO_PTV6, PTV6_DATA),
+ PINMUX_GPIO(GPIO_PTV5, PTV5_DATA),
+ PINMUX_GPIO(GPIO_PTV4, PTV4_DATA),
+ PINMUX_GPIO(GPIO_PTV3, PTV3_DATA),
+ PINMUX_GPIO(GPIO_PTV2, PTV2_DATA),
+ PINMUX_GPIO(GPIO_PTV1, PTV1_DATA),
+ PINMUX_GPIO(GPIO_PTV0, PTV0_DATA),
+
+ /* PTW */
+ PINMUX_GPIO(GPIO_PTW7, PTW7_DATA),
+ PINMUX_GPIO(GPIO_PTW6, PTW6_DATA),
+ PINMUX_GPIO(GPIO_PTW5, PTW5_DATA),
+ PINMUX_GPIO(GPIO_PTW4, PTW4_DATA),
+ PINMUX_GPIO(GPIO_PTW3, PTW3_DATA),
+ PINMUX_GPIO(GPIO_PTW2, PTW2_DATA),
+ PINMUX_GPIO(GPIO_PTW1, PTW1_DATA),
+ PINMUX_GPIO(GPIO_PTW0, PTW0_DATA),
+
+ /* PTX */
+ PINMUX_GPIO(GPIO_PTX7, PTX7_DATA),
+ PINMUX_GPIO(GPIO_PTX6, PTX6_DATA),
+ PINMUX_GPIO(GPIO_PTX5, PTX5_DATA),
+ PINMUX_GPIO(GPIO_PTX4, PTX4_DATA),
+ PINMUX_GPIO(GPIO_PTX3, PTX3_DATA),
+ PINMUX_GPIO(GPIO_PTX2, PTX2_DATA),
+ PINMUX_GPIO(GPIO_PTX1, PTX1_DATA),
+ PINMUX_GPIO(GPIO_PTX0, PTX0_DATA),
+
+ /* PTY */
+ PINMUX_GPIO(GPIO_PTY7, PTY7_DATA),
+ PINMUX_GPIO(GPIO_PTY6, PTY6_DATA),
+ PINMUX_GPIO(GPIO_PTY5, PTY5_DATA),
+ PINMUX_GPIO(GPIO_PTY4, PTY4_DATA),
+ PINMUX_GPIO(GPIO_PTY3, PTY3_DATA),
+ PINMUX_GPIO(GPIO_PTY2, PTY2_DATA),
+ PINMUX_GPIO(GPIO_PTY1, PTY1_DATA),
+ PINMUX_GPIO(GPIO_PTY0, PTY0_DATA),
+
+ /* PTZ */
+ PINMUX_GPIO(GPIO_PTZ7, PTZ7_DATA),
+ PINMUX_GPIO(GPIO_PTZ6, PTZ6_DATA),
+ PINMUX_GPIO(GPIO_PTZ5, PTZ5_DATA),
+ PINMUX_GPIO(GPIO_PTZ4, PTZ4_DATA),
+ PINMUX_GPIO(GPIO_PTZ3, PTZ3_DATA),
+ PINMUX_GPIO(GPIO_PTZ2, PTZ2_DATA),
+ PINMUX_GPIO(GPIO_PTZ1, PTZ1_DATA),
+ PINMUX_GPIO(GPIO_PTZ0, PTZ0_DATA),
+
+ /* BSC */
+ PINMUX_GPIO(GPIO_FN_D31, D31_MARK),
+ PINMUX_GPIO(GPIO_FN_D30, D30_MARK),
+ PINMUX_GPIO(GPIO_FN_D29, D29_MARK),
+ PINMUX_GPIO(GPIO_FN_D28, D28_MARK),
+ PINMUX_GPIO(GPIO_FN_D27, D27_MARK),
+ PINMUX_GPIO(GPIO_FN_D26, D26_MARK),
+ PINMUX_GPIO(GPIO_FN_D25, D25_MARK),
+ PINMUX_GPIO(GPIO_FN_D24, D24_MARK),
+ PINMUX_GPIO(GPIO_FN_D23, D23_MARK),
+ PINMUX_GPIO(GPIO_FN_D22, D22_MARK),
+ PINMUX_GPIO(GPIO_FN_D21, D21_MARK),
+ PINMUX_GPIO(GPIO_FN_D20, D20_MARK),
+ PINMUX_GPIO(GPIO_FN_D19, D19_MARK),
+ PINMUX_GPIO(GPIO_FN_D18, D18_MARK),
+ PINMUX_GPIO(GPIO_FN_D17, D17_MARK),
+ PINMUX_GPIO(GPIO_FN_D16, D16_MARK),
+ PINMUX_GPIO(GPIO_FN_D15, D15_MARK),
+ PINMUX_GPIO(GPIO_FN_D14, D14_MARK),
+ PINMUX_GPIO(GPIO_FN_D13, D13_MARK),
+ PINMUX_GPIO(GPIO_FN_D12, D12_MARK),
+ PINMUX_GPIO(GPIO_FN_D11, D11_MARK),
+ PINMUX_GPIO(GPIO_FN_D10, D10_MARK),
+ PINMUX_GPIO(GPIO_FN_D9, D9_MARK),
+ PINMUX_GPIO(GPIO_FN_D8, D8_MARK),
+ PINMUX_GPIO(GPIO_FN_D7, D7_MARK),
+ PINMUX_GPIO(GPIO_FN_D6, D6_MARK),
+ PINMUX_GPIO(GPIO_FN_D5, D5_MARK),
+ PINMUX_GPIO(GPIO_FN_D4, D4_MARK),
+ PINMUX_GPIO(GPIO_FN_D3, D3_MARK),
+ PINMUX_GPIO(GPIO_FN_D2, D2_MARK),
+ PINMUX_GPIO(GPIO_FN_D1, D1_MARK),
+ PINMUX_GPIO(GPIO_FN_D0, D0_MARK),
+ PINMUX_GPIO(GPIO_FN_A25, A25_MARK),
+ PINMUX_GPIO(GPIO_FN_A24, A24_MARK),
+ PINMUX_GPIO(GPIO_FN_A23, A23_MARK),
+ PINMUX_GPIO(GPIO_FN_A22, A22_MARK),
+ PINMUX_GPIO(GPIO_FN_CS6B_CE1B, CS6B_CE1B_MARK),
+ PINMUX_GPIO(GPIO_FN_CS6A_CE2B, CS6A_CE2B_MARK),
+ PINMUX_GPIO(GPIO_FN_CS5B_CE1A, CS5B_CE1A_MARK),
+ PINMUX_GPIO(GPIO_FN_CS5A_CE2A, CS5A_CE2A_MARK),
+ PINMUX_GPIO(GPIO_FN_WE3_ICIOWR, WE3_ICIOWR_MARK),
+ PINMUX_GPIO(GPIO_FN_WE2_ICIORD, WE2_ICIORD_MARK),
+ PINMUX_GPIO(GPIO_FN_IOIS16, IOIS16_MARK),
+ PINMUX_GPIO(GPIO_FN_WAIT, WAIT_MARK),
+ PINMUX_GPIO(GPIO_FN_BS, BS_MARK),
+
+ /* KEYSC */
+ PINMUX_GPIO(GPIO_FN_KEYOUT5_IN5, KEYOUT5_IN5_MARK),
+ PINMUX_GPIO(GPIO_FN_KEYOUT4_IN6, KEYOUT4_IN6_MARK),
+ PINMUX_GPIO(GPIO_FN_KEYIN4, KEYIN4_MARK),
+ PINMUX_GPIO(GPIO_FN_KEYIN3, KEYIN3_MARK),
+ PINMUX_GPIO(GPIO_FN_KEYIN2, KEYIN2_MARK),
+ PINMUX_GPIO(GPIO_FN_KEYIN1, KEYIN1_MARK),
+ PINMUX_GPIO(GPIO_FN_KEYIN0, KEYIN0_MARK),
+ PINMUX_GPIO(GPIO_FN_KEYOUT3, KEYOUT3_MARK),
+ PINMUX_GPIO(GPIO_FN_KEYOUT2, KEYOUT2_MARK),
+ PINMUX_GPIO(GPIO_FN_KEYOUT1, KEYOUT1_MARK),
+ PINMUX_GPIO(GPIO_FN_KEYOUT0, KEYOUT0_MARK),
+
+ /* ATAPI */
+ PINMUX_GPIO(GPIO_FN_IDED15, IDED15_MARK),
+ PINMUX_GPIO(GPIO_FN_IDED14, IDED14_MARK),
+ PINMUX_GPIO(GPIO_FN_IDED13, IDED13_MARK),
+ PINMUX_GPIO(GPIO_FN_IDED12, IDED12_MARK),
+ PINMUX_GPIO(GPIO_FN_IDED11, IDED11_MARK),
+ PINMUX_GPIO(GPIO_FN_IDED10, IDED10_MARK),
+ PINMUX_GPIO(GPIO_FN_IDED9, IDED9_MARK),
+ PINMUX_GPIO(GPIO_FN_IDED8, IDED8_MARK),
+ PINMUX_GPIO(GPIO_FN_IDED7, IDED7_MARK),
+ PINMUX_GPIO(GPIO_FN_IDED6, IDED6_MARK),
+ PINMUX_GPIO(GPIO_FN_IDED5, IDED5_MARK),
+ PINMUX_GPIO(GPIO_FN_IDED4, IDED4_MARK),
+ PINMUX_GPIO(GPIO_FN_IDED3, IDED3_MARK),
+ PINMUX_GPIO(GPIO_FN_IDED2, IDED2_MARK),
+ PINMUX_GPIO(GPIO_FN_IDED1, IDED1_MARK),
+ PINMUX_GPIO(GPIO_FN_IDED0, IDED0_MARK),
+ PINMUX_GPIO(GPIO_FN_IDEA2, IDEA2_MARK),
+ PINMUX_GPIO(GPIO_FN_IDEA1, IDEA1_MARK),
+ PINMUX_GPIO(GPIO_FN_IDEA0, IDEA0_MARK),
+ PINMUX_GPIO(GPIO_FN_IDEIOWR, IDEIOWR_MARK),
+ PINMUX_GPIO(GPIO_FN_IODREQ, IODREQ_MARK),
+ PINMUX_GPIO(GPIO_FN_IDECS0, IDECS0_MARK),
+ PINMUX_GPIO(GPIO_FN_IDECS1, IDECS1_MARK),
+ PINMUX_GPIO(GPIO_FN_IDEIORD, IDEIORD_MARK),
+ PINMUX_GPIO(GPIO_FN_DIRECTION, DIRECTION_MARK),
+ PINMUX_GPIO(GPIO_FN_EXBUF_ENB, EXBUF_ENB_MARK),
+ PINMUX_GPIO(GPIO_FN_IDERST, IDERST_MARK),
+ PINMUX_GPIO(GPIO_FN_IODACK, IODACK_MARK),
+ PINMUX_GPIO(GPIO_FN_IDEINT, IDEINT_MARK),
+ PINMUX_GPIO(GPIO_FN_IDEIORDY, IDEIORDY_MARK),
+
+ /* TPU */
+ PINMUX_GPIO(GPIO_FN_TPUTO3, TPUTO3_MARK),
+ PINMUX_GPIO(GPIO_FN_TPUTO2, TPUTO2_MARK),
+ PINMUX_GPIO(GPIO_FN_TPUTO1, TPUTO1_MARK),
+ PINMUX_GPIO(GPIO_FN_TPUTO0, TPUTO0_MARK),
+ PINMUX_GPIO(GPIO_FN_TPUTI3, TPUTI3_MARK),
+ PINMUX_GPIO(GPIO_FN_TPUTI2, TPUTI2_MARK),
+
+ /* LCDC */
+ PINMUX_GPIO(GPIO_FN_LCDD23, LCDD23_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD22, LCDD22_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD21, LCDD21_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD20, LCDD20_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD19, LCDD19_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD18, LCDD18_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD17, LCDD17_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD16, LCDD16_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD15, LCDD15_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD14, LCDD14_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD13, LCDD13_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD12, LCDD12_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD11, LCDD11_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD10, LCDD10_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD9, LCDD9_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD8, LCDD8_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD7, LCDD7_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD6, LCDD6_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD5, LCDD5_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD4, LCDD4_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD3, LCDD3_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD2, LCDD2_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD1, LCDD1_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDD0, LCDD0_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDVSYN, LCDVSYN_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDDISP, LCDDISP_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDRS, LCDRS_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDHSYN, LCDHSYN_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDCS, LCDCS_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDDON, LCDDON_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDDCK, LCDDCK_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDWR, LCDWR_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDVEPWC, LCDVEPWC_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDVCPWC, LCDVCPWC_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDRD, LCDRD_MARK),
+ PINMUX_GPIO(GPIO_FN_LCDLCLK, LCDLCLK_MARK),
+
+ /* SCIF0 */
+ PINMUX_GPIO(GPIO_FN_SCIF0_TXD, SCIF0_TXD_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF0_RXD, SCIF0_RXD_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF0_SCK, SCIF0_SCK_MARK),
+
+ /* SCIF1 */
+ PINMUX_GPIO(GPIO_FN_SCIF1_SCK, SCIF1_SCK_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF1_RXD, SCIF1_RXD_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF1_TXD, SCIF1_TXD_MARK),
+
+ /* SCIF2 */
+ PINMUX_GPIO(GPIO_FN_SCIF2_L_TXD, SCIF2_L_TXD_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF2_L_SCK, SCIF2_L_SCK_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF2_L_RXD, SCIF2_L_RXD_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF2_V_TXD, SCIF2_V_TXD_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF2_V_SCK, SCIF2_V_SCK_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF2_V_RXD, SCIF2_V_RXD_MARK),
+
+ /* SCIF3 */
+ PINMUX_GPIO(GPIO_FN_SCIF3_V_SCK, SCIF3_V_SCK_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF3_V_RXD, SCIF3_V_RXD_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF3_V_TXD, SCIF3_V_TXD_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF3_V_CTS, SCIF3_V_CTS_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF3_V_RTS, SCIF3_V_RTS_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF3_I_SCK, SCIF3_I_SCK_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF3_I_RXD, SCIF3_I_RXD_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF3_I_TXD, SCIF3_I_TXD_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF3_I_CTS, SCIF3_I_CTS_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF3_I_RTS, SCIF3_I_RTS_MARK),
+
+ /* SCIF4 */
+ PINMUX_GPIO(GPIO_FN_SCIF4_SCK, SCIF4_SCK_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF4_RXD, SCIF4_RXD_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF4_TXD, SCIF4_TXD_MARK),
+
+ /* SCIF5 */
+ PINMUX_GPIO(GPIO_FN_SCIF5_SCK, SCIF5_SCK_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF5_RXD, SCIF5_RXD_MARK),
+ PINMUX_GPIO(GPIO_FN_SCIF5_TXD, SCIF5_TXD_MARK),
+
+ /* FSI */
+ PINMUX_GPIO(GPIO_FN_FSIMCKB, FSIMCKB_MARK),
+ PINMUX_GPIO(GPIO_FN_FSIMCKA, FSIMCKA_MARK),
+ PINMUX_GPIO(GPIO_FN_FSIOASD, FSIOASD_MARK),
+ PINMUX_GPIO(GPIO_FN_FSIIABCK, FSIIABCK_MARK),
+ PINMUX_GPIO(GPIO_FN_FSIIALRCK, FSIIALRCK_MARK),
+ PINMUX_GPIO(GPIO_FN_FSIOABCK, FSIOABCK_MARK),
+ PINMUX_GPIO(GPIO_FN_FSIOALRCK, FSIOALRCK_MARK),
+ PINMUX_GPIO(GPIO_FN_CLKAUDIOAO, CLKAUDIOAO_MARK),
+ PINMUX_GPIO(GPIO_FN_FSIIBSD, FSIIBSD_MARK),
+ PINMUX_GPIO(GPIO_FN_FSIOBSD, FSIOBSD_MARK),
+ PINMUX_GPIO(GPIO_FN_FSIIBBCK, FSIIBBCK_MARK),
+ PINMUX_GPIO(GPIO_FN_FSIIBLRCK, FSIIBLRCK_MARK),
+ PINMUX_GPIO(GPIO_FN_FSIOBBCK, FSIOBBCK_MARK),
+ PINMUX_GPIO(GPIO_FN_FSIOBLRCK, FSIOBLRCK_MARK),
+ PINMUX_GPIO(GPIO_FN_CLKAUDIOBO, CLKAUDIOBO_MARK),
+ PINMUX_GPIO(GPIO_FN_FSIIASD, FSIIASD_MARK),
+
+ /* AUD */
+ PINMUX_GPIO(GPIO_FN_AUDCK, AUDCK_MARK),
+ PINMUX_GPIO(GPIO_FN_AUDSYNC, AUDSYNC_MARK),
+ PINMUX_GPIO(GPIO_FN_AUDATA3, AUDATA3_MARK),
+ PINMUX_GPIO(GPIO_FN_AUDATA2, AUDATA2_MARK),
+ PINMUX_GPIO(GPIO_FN_AUDATA1, AUDATA1_MARK),
+ PINMUX_GPIO(GPIO_FN_AUDATA0, AUDATA0_MARK),
+
+ /* VIO */
+ PINMUX_GPIO(GPIO_FN_VIO_CKO, VIO_CKO_MARK),
+
+ /* VIO0 */
+ PINMUX_GPIO(GPIO_FN_VIO0_D15, VIO0_D15_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO0_D14, VIO0_D14_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO0_D13, VIO0_D13_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO0_D12, VIO0_D12_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO0_D11, VIO0_D11_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO0_D10, VIO0_D10_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO0_D9, VIO0_D9_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO0_D8, VIO0_D8_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO0_D7, VIO0_D7_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO0_D6, VIO0_D6_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO0_D5, VIO0_D5_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO0_D4, VIO0_D4_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO0_D3, VIO0_D3_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO0_D2, VIO0_D2_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO0_D1, VIO0_D1_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO0_D0, VIO0_D0_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO0_VD, VIO0_VD_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO0_CLK, VIO0_CLK_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO0_FLD, VIO0_FLD_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO0_HD, VIO0_HD_MARK),
+
+ /* VIO1 */
+ PINMUX_GPIO(GPIO_FN_VIO1_D7, VIO1_D7_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO1_D6, VIO1_D6_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO1_D5, VIO1_D5_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO1_D4, VIO1_D4_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO1_D3, VIO1_D3_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO1_D2, VIO1_D2_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO1_D1, VIO1_D1_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO1_D0, VIO1_D0_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO1_FLD, VIO1_FLD_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO1_HD, VIO1_HD_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO1_VD, VIO1_VD_MARK),
+ PINMUX_GPIO(GPIO_FN_VIO1_CLK, VIO1_CLK_MARK),
+
+ /* Eth */
+ PINMUX_GPIO(GPIO_FN_RMII_RXD0, RMII_RXD0_MARK),
+ PINMUX_GPIO(GPIO_FN_RMII_RXD1, RMII_RXD1_MARK),
+ PINMUX_GPIO(GPIO_FN_RMII_TXD0, RMII_TXD0_MARK),
+ PINMUX_GPIO(GPIO_FN_RMII_TXD1, RMII_TXD1_MARK),
+ PINMUX_GPIO(GPIO_FN_RMII_REF_CLK, RMII_REF_CLK_MARK),
+ PINMUX_GPIO(GPIO_FN_RMII_TX_EN, RMII_TX_EN_MARK),
+ PINMUX_GPIO(GPIO_FN_RMII_RX_ER, RMII_RX_ER_MARK),
+ PINMUX_GPIO(GPIO_FN_RMII_CRS_DV, RMII_CRS_DV_MARK),
+ PINMUX_GPIO(GPIO_FN_LNKSTA, LNKSTA_MARK),
+ PINMUX_GPIO(GPIO_FN_MDIO, MDIO_MARK),
+ PINMUX_GPIO(GPIO_FN_MDC, MDC_MARK),
+
+ /* System */
+ PINMUX_GPIO(GPIO_FN_PDSTATUS, PDSTATUS_MARK),
+ PINMUX_GPIO(GPIO_FN_STATUS2, STATUS2_MARK),
+ PINMUX_GPIO(GPIO_FN_STATUS0, STATUS0_MARK),
+
+ /* VOU */
+ PINMUX_GPIO(GPIO_FN_DV_D15, DV_D15_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_D14, DV_D14_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_D13, DV_D13_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_D12, DV_D12_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_D11, DV_D11_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_D10, DV_D10_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_D9, DV_D9_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_D8, DV_D8_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_D7, DV_D7_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_D6, DV_D6_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_D5, DV_D5_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_D4, DV_D4_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_D3, DV_D3_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_D2, DV_D2_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_D1, DV_D1_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_D0, DV_D0_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_CLKI, DV_CLKI_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_CLK, DV_CLK_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_VSYNC, DV_VSYNC_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_HSYNC, DV_HSYNC_MARK),
+
+ /* MSIOF0 */
+ PINMUX_GPIO(GPIO_FN_MSIOF0_RXD, MSIOF0_RXD_MARK),
+ PINMUX_GPIO(GPIO_FN_MSIOF0_TXD, MSIOF0_TXD_MARK),
+ PINMUX_GPIO(GPIO_FN_MSIOF0_MCK, MSIOF0_MCK_MARK),
+ PINMUX_GPIO(GPIO_FN_MSIOF0_TSCK, MSIOF0_TSCK_MARK),
+ PINMUX_GPIO(GPIO_FN_MSIOF0_SS1, MSIOF0_SS1_MARK),
+ PINMUX_GPIO(GPIO_FN_MSIOF0_SS2, MSIOF0_SS2_MARK),
+ PINMUX_GPIO(GPIO_FN_MSIOF0_TSYNC, MSIOF0_TSYNC_MARK),
+ PINMUX_GPIO(GPIO_FN_MSIOF0_RSCK, MSIOF0_RSCK_MARK),
+ PINMUX_GPIO(GPIO_FN_MSIOF0_RSYNC, MSIOF0_RSYNC_MARK),
+
+ /* MSIOF1 */
+ PINMUX_GPIO(GPIO_FN_MSIOF1_RXD, MSIOF1_RXD_MARK),
+ PINMUX_GPIO(GPIO_FN_MSIOF1_TXD, MSIOF1_TXD_MARK),
+ PINMUX_GPIO(GPIO_FN_MSIOF1_MCK, MSIOF1_MCK_MARK),
+ PINMUX_GPIO(GPIO_FN_MSIOF1_TSCK, MSIOF1_TSCK_MARK),
+ PINMUX_GPIO(GPIO_FN_MSIOF1_SS1, MSIOF1_SS1_MARK),
+ PINMUX_GPIO(GPIO_FN_MSIOF1_SS2, MSIOF1_SS2_MARK),
+ PINMUX_GPIO(GPIO_FN_MSIOF1_TSYNC, MSIOF1_TSYNC_MARK),
+ PINMUX_GPIO(GPIO_FN_MSIOF1_RSCK, MSIOF1_RSCK_MARK),
+ PINMUX_GPIO(GPIO_FN_MSIOF1_RSYNC, MSIOF1_RSYNC_MARK),
+
+ /* DMAC */
+ PINMUX_GPIO(GPIO_FN_DMAC_DACK0, DMAC_DACK0_MARK),
+ PINMUX_GPIO(GPIO_FN_DMAC_DREQ0, DMAC_DREQ0_MARK),
+ PINMUX_GPIO(GPIO_FN_DMAC_DACK1, DMAC_DACK1_MARK),
+ PINMUX_GPIO(GPIO_FN_DMAC_DREQ1, DMAC_DREQ1_MARK),
+
+ /* SDHI0 */
+ PINMUX_GPIO(GPIO_FN_SDHI0CD, SDHI0CD_MARK),
+ PINMUX_GPIO(GPIO_FN_SDHI0WP, SDHI0WP_MARK),
+ PINMUX_GPIO(GPIO_FN_SDHI0CMD, SDHI0CMD_MARK),
+ PINMUX_GPIO(GPIO_FN_SDHI0CLK, SDHI0CLK_MARK),
+ PINMUX_GPIO(GPIO_FN_SDHI0D3, SDHI0D3_MARK),
+ PINMUX_GPIO(GPIO_FN_SDHI0D2, SDHI0D2_MARK),
+ PINMUX_GPIO(GPIO_FN_SDHI0D1, SDHI0D1_MARK),
+ PINMUX_GPIO(GPIO_FN_SDHI0D0, SDHI0D0_MARK),
+
+ /* SDHI1 */
+ PINMUX_GPIO(GPIO_FN_SDHI1CD, SDHI1CD_MARK),
+ PINMUX_GPIO(GPIO_FN_SDHI1WP, SDHI1WP_MARK),
+ PINMUX_GPIO(GPIO_FN_SDHI1CMD, SDHI1CMD_MARK),
+ PINMUX_GPIO(GPIO_FN_SDHI1CLK, SDHI1CLK_MARK),
+ PINMUX_GPIO(GPIO_FN_SDHI1D3, SDHI1D3_MARK),
+ PINMUX_GPIO(GPIO_FN_SDHI1D2, SDHI1D2_MARK),
+ PINMUX_GPIO(GPIO_FN_SDHI1D1, SDHI1D1_MARK),
+ PINMUX_GPIO(GPIO_FN_SDHI1D0, SDHI1D0_MARK),
+
+ /* MMC */
+ PINMUX_GPIO(GPIO_FN_MMC_D7, MMC_D7_MARK),
+ PINMUX_GPIO(GPIO_FN_MMC_D6, MMC_D6_MARK),
+ PINMUX_GPIO(GPIO_FN_MMC_D5, MMC_D5_MARK),
+ PINMUX_GPIO(GPIO_FN_MMC_D4, MMC_D4_MARK),
+ PINMUX_GPIO(GPIO_FN_MMC_D3, MMC_D3_MARK),
+ PINMUX_GPIO(GPIO_FN_MMC_D2, MMC_D2_MARK),
+ PINMUX_GPIO(GPIO_FN_MMC_D1, MMC_D1_MARK),
+ PINMUX_GPIO(GPIO_FN_MMC_D0, MMC_D0_MARK),
+ PINMUX_GPIO(GPIO_FN_MMC_CLK, MMC_CLK_MARK),
+ PINMUX_GPIO(GPIO_FN_MMC_CMD, MMC_CMD_MARK),
+
+ /* IrDA */
+ PINMUX_GPIO(GPIO_FN_IRDA_OUT, IRDA_OUT_MARK),
+ PINMUX_GPIO(GPIO_FN_IRDA_IN, IRDA_IN_MARK),
+
+ /* TSIF */
+ PINMUX_GPIO(GPIO_FN_TSIF_TS0_SDAT, TSIF_TS0_SDAT_MARK),
+ PINMUX_GPIO(GPIO_FN_TSIF_TS0_SCK, TSIF_TS0_SCK_MARK),
+ PINMUX_GPIO(GPIO_FN_TSIF_TS0_SDEN, TSIF_TS0_SDEN_MARK),
+ PINMUX_GPIO(GPIO_FN_TSIF_TS0_SPSYNC, TSIF_TS0_SPSYNC_MARK),
+
+ /* IRQ */
+ PINMUX_GPIO(GPIO_FN_INTC_IRQ7, INTC_IRQ7_MARK),
+ PINMUX_GPIO(GPIO_FN_INTC_IRQ6, INTC_IRQ6_MARK),
+ PINMUX_GPIO(GPIO_FN_INTC_IRQ5, INTC_IRQ5_MARK),
+ PINMUX_GPIO(GPIO_FN_INTC_IRQ4, INTC_IRQ4_MARK),
+ PINMUX_GPIO(GPIO_FN_INTC_IRQ3, INTC_IRQ3_MARK),
+ PINMUX_GPIO(GPIO_FN_INTC_IRQ2, INTC_IRQ2_MARK),
+ PINMUX_GPIO(GPIO_FN_INTC_IRQ1, INTC_IRQ1_MARK),
+ PINMUX_GPIO(GPIO_FN_INTC_IRQ0, INTC_IRQ0_MARK),
+ };
+
+static struct pinmux_cfg_reg pinmux_config_regs[] = {
+ { PINMUX_CFG_REG("PACR", 0xa4050100, 16, 2) {
+ PTA7_FN, PTA7_OUT, PTA7_IN_PU, PTA7_IN,
+ PTA6_FN, PTA6_OUT, PTA6_IN_PU, PTA6_IN,
+ PTA5_FN, PTA5_OUT, PTA5_IN_PU, PTA5_IN,
+ PTA4_FN, PTA4_OUT, PTA4_IN_PU, PTA4_IN,
+ PTA3_FN, PTA3_OUT, PTA3_IN_PU, PTA3_IN,
+ PTA2_FN, PTA2_OUT, PTA2_IN_PU, PTA2_IN,
+ PTA1_FN, PTA1_OUT, PTA1_IN_PU, PTA1_IN,
+ PTA0_FN, PTA0_OUT, PTA0_IN_PU, PTA0_IN }
+ },
+ { PINMUX_CFG_REG("PBCR", 0xa4050102, 16, 2) {
+ PTB7_FN, PTB7_OUT, PTB7_IN_PU, PTB7_IN,
+ PTB6_FN, PTB6_OUT, PTB6_IN_PU, PTB6_IN,
+ PTB5_FN, PTB5_OUT, PTB5_IN_PU, PTB5_IN,
+ PTB4_FN, PTB4_OUT, PTB4_IN_PU, PTB4_IN,
+ PTB3_FN, PTB3_OUT, PTB3_IN_PU, PTB3_IN,
+ PTB2_FN, PTB2_OUT, PTB2_IN_PU, PTB2_IN,
+ PTB1_FN, PTB1_OUT, PTB1_IN_PU, PTB1_IN,
+ PTB0_FN, PTB0_OUT, PTB0_IN_PU, PTB0_IN }
+ },
+ { PINMUX_CFG_REG("PCCR", 0xa4050104, 16, 2) {
+ PTC7_FN, PTC7_OUT, PTC7_IN_PU, PTC7_IN,
+ PTC6_FN, PTC6_OUT, PTC6_IN_PU, PTC6_IN,
+ PTC5_FN, PTC5_OUT, PTC5_IN_PU, PTC5_IN,
+ PTC4_FN, PTC4_OUT, PTC4_IN_PU, PTC4_IN,
+ PTC3_FN, PTC3_OUT, PTC3_IN_PU, PTC3_IN,
+ PTC2_FN, PTC2_OUT, PTC2_IN_PU, PTC2_IN,
+ PTC1_FN, PTC1_OUT, PTC1_IN_PU, PTC1_IN,
+ PTC0_FN, PTC0_OUT, PTC0_IN_PU, PTC0_IN }
+ },
+ { PINMUX_CFG_REG("PDCR", 0xa4050106, 16, 2) {
+ PTD7_FN, PTD7_OUT, PTD7_IN_PU, PTD7_IN,
+ PTD6_FN, PTD6_OUT, PTD6_IN_PU, PTD6_IN,
+ PTD5_FN, PTD5_OUT, PTD5_IN_PU, PTD5_IN,
+ PTD4_FN, PTD4_OUT, PTD4_IN_PU, PTD4_IN,
+ PTD3_FN, PTD3_OUT, PTD3_IN_PU, PTD3_IN,
+ PTD2_FN, PTD2_OUT, PTD2_IN_PU, PTD2_IN,
+ PTD1_FN, PTD1_OUT, PTD1_IN_PU, PTD1_IN,
+ PTD0_FN, PTD0_OUT, PTD0_IN_PU, PTD0_IN }
+ },
+ { PINMUX_CFG_REG("PECR", 0xa4050108, 16, 2) {
+ PTE7_FN, PTE7_OUT, PTE7_IN_PU, PTE7_IN,
+ PTE6_FN, PTE6_OUT, PTE6_IN_PU, PTE6_IN,
+ PTE5_FN, PTE5_OUT, PTE5_IN_PU, PTE5_IN,
+ PTE4_FN, PTE4_OUT, PTE4_IN_PU, PTE4_IN,
+ PTE3_FN, PTE3_OUT, PTE3_IN_PU, PTE3_IN,
+ PTE2_FN, PTE2_OUT, PTE2_IN_PU, PTE2_IN,
+ PTE1_FN, PTE1_OUT, PTE1_IN_PU, PTE1_IN,
+ PTE0_FN, PTE0_OUT, PTE0_IN_PU, PTE0_IN }
+ },
+ { PINMUX_CFG_REG("PFCR", 0xa405010a, 16, 2) {
+ PTF7_FN, PTF7_OUT, PTF7_IN_PU, PTF7_IN,
+ PTF6_FN, PTF6_OUT, PTF6_IN_PU, PTF6_IN,
+ PTF5_FN, PTF5_OUT, PTF5_IN_PU, PTF5_IN,
+ PTF4_FN, PTF4_OUT, PTF4_IN_PU, PTF4_IN,
+ PTF3_FN, PTF3_OUT, PTF3_IN_PU, PTF3_IN,
+ PTF2_FN, PTF2_OUT, PTF2_IN_PU, PTF2_IN,
+ PTF1_FN, PTF1_OUT, PTF1_IN_PU, PTF1_IN,
+ PTF0_FN, PTF0_OUT, PTF0_IN_PU, PTF0_IN }
+ },
+ { PINMUX_CFG_REG("PGCR", 0xa405010c, 16, 2) {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ PTG5_FN, PTG5_OUT, 0, 0,
+ PTG4_FN, PTG4_OUT, 0, 0,
+ PTG3_FN, PTG3_OUT, 0, 0,
+ PTG2_FN, PTG2_OUT, 0, 0,
+ PTG1_FN, PTG1_OUT, 0, 0,
+ PTG0_FN, PTG0_OUT, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PHCR", 0xa405010e, 16, 2) {
+ PTH7_FN, PTH7_OUT, PTH7_IN_PU, PTH7_IN,
+ PTH6_FN, PTH6_OUT, PTH6_IN_PU, PTH6_IN,
+ PTH5_FN, PTH5_OUT, PTH5_IN_PU, PTH5_IN,
+ PTH4_FN, PTH4_OUT, PTH4_IN_PU, PTH4_IN,
+ PTH3_FN, PTH3_OUT, PTH3_IN_PU, PTH3_IN,
+ PTH2_FN, PTH2_OUT, PTH2_IN_PU, PTH2_IN,
+ PTH1_FN, PTH1_OUT, PTH1_IN_PU, PTH1_IN,
+ PTH0_FN, PTH0_OUT, PTH0_IN_PU, PTH0_IN }
+ },
+ { PINMUX_CFG_REG("PJCR", 0xa4050110, 16, 2) {
+ PTJ7_FN, PTJ7_OUT, 0, 0,
+ PTJ6_FN, PTJ6_OUT, 0, 0,
+ PTJ5_FN, PTJ5_OUT, 0, 0,
+ 0, 0, 0, 0,
+ PTJ3_FN, PTJ3_OUT, PTJ3_IN_PU, PTJ3_IN,
+ PTJ2_FN, PTJ2_OUT, PTJ2_IN_PU, PTJ2_IN,
+ PTJ1_FN, PTJ1_OUT, PTJ1_IN_PU, PTJ1_IN,
+ PTJ0_FN, PTJ0_OUT, PTJ0_IN_PU, PTJ0_IN }
+ },
+ { PINMUX_CFG_REG("PKCR", 0xa4050112, 16, 2) {
+ PTK7_FN, PTK7_OUT, PTK7_IN_PU, PTK7_IN,
+ PTK6_FN, PTK6_OUT, PTK6_IN_PU, PTK6_IN,
+ PTK5_FN, PTK5_OUT, PTK5_IN_PU, PTK5_IN,
+ PTK4_FN, PTK4_OUT, PTK4_IN_PU, PTK4_IN,
+ PTK3_FN, PTK3_OUT, PTK3_IN_PU, PTK3_IN,
+ PTK2_FN, PTK2_OUT, PTK2_IN_PU, PTK2_IN,
+ PTK1_FN, PTK1_OUT, PTK1_IN_PU, PTK1_IN,
+ PTK0_FN, PTK0_OUT, PTK0_IN_PU, PTK0_IN }
+ },
+ { PINMUX_CFG_REG("PLCR", 0xa4050114, 16, 2) {
+ PTL7_FN, PTL7_OUT, PTL7_IN_PU, PTL7_IN,
+ PTL6_FN, PTL6_OUT, PTL6_IN_PU, PTL6_IN,
+ PTL5_FN, PTL5_OUT, PTL5_IN_PU, PTL5_IN,
+ PTL4_FN, PTL4_OUT, PTL4_IN_PU, PTL4_IN,
+ PTL3_FN, PTL3_OUT, PTL3_IN_PU, PTL3_IN,
+ PTL2_FN, PTL2_OUT, PTL2_IN_PU, PTL2_IN,
+ PTL1_FN, PTL1_OUT, PTL1_IN_PU, PTL1_IN,
+ PTL0_FN, PTL0_OUT, PTL0_IN_PU, PTL0_IN }
+ },
+ { PINMUX_CFG_REG("PMCR", 0xa4050116, 16, 2) {
+ PTM7_FN, PTM7_OUT, PTM7_IN_PU, PTM7_IN,
+ PTM6_FN, PTM6_OUT, PTM6_IN_PU, PTM6_IN,
+ PTM5_FN, PTM5_OUT, PTM5_IN_PU, PTM5_IN,
+ PTM4_FN, PTM4_OUT, PTM4_IN_PU, PTM4_IN,
+ PTM3_FN, PTM3_OUT, PTM3_IN_PU, PTM3_IN,
+ PTM2_FN, PTM2_OUT, PTM2_IN_PU, PTM2_IN,
+ PTM1_FN, PTM1_OUT, PTM1_IN_PU, PTM1_IN,
+ PTM0_FN, PTM0_OUT, PTM0_IN_PU, PTM0_IN }
+ },
+ { PINMUX_CFG_REG("PNCR", 0xa4050118, 16, 2) {
+ PTN7_FN, PTN7_OUT, PTN7_IN_PU, PTN7_IN,
+ PTN6_FN, PTN6_OUT, PTN6_IN_PU, PTN6_IN,
+ PTN5_FN, PTN5_OUT, PTN5_IN_PU, PTN5_IN,
+ PTN4_FN, PTN4_OUT, PTN4_IN_PU, PTN4_IN,
+ PTN3_FN, PTN3_OUT, PTN3_IN_PU, PTN3_IN,
+ PTN2_FN, PTN2_OUT, PTN2_IN_PU, PTN2_IN,
+ PTN1_FN, PTN1_OUT, PTN1_IN_PU, PTN1_IN,
+ PTN0_FN, PTN0_OUT, PTN0_IN_PU, PTN0_IN }
+ },
+ { PINMUX_CFG_REG("PQCR", 0xa405011a, 16, 2) {
+ PTQ7_FN, PTQ7_OUT, PTQ7_IN_PU, PTQ7_IN,
+ PTQ6_FN, PTQ6_OUT, PTQ6_IN_PU, PTQ6_IN,
+ PTQ5_FN, PTQ5_OUT, PTQ5_IN_PU, PTQ5_IN,
+ PTQ4_FN, PTQ4_OUT, PTQ4_IN_PU, PTQ4_IN,
+ PTQ3_FN, PTQ3_OUT, PTQ3_IN_PU, PTQ3_IN,
+ PTQ2_FN, PTQ2_OUT, PTQ2_IN_PU, PTQ2_IN,
+ PTQ1_FN, PTQ1_OUT, PTQ1_IN_PU, PTQ1_IN,
+ PTQ0_FN, PTQ0_OUT, PTQ0_IN_PU, PTQ0_IN }
+ },
+ { PINMUX_CFG_REG("PRCR", 0xa405011c, 16, 2) {
+ PTR7_FN, PTR7_OUT, PTR7_IN_PU, PTR7_IN,
+ PTR6_FN, PTR6_OUT, PTR6_IN_PU, PTR6_IN,
+ PTR5_FN, PTR5_OUT, PTR5_IN_PU, PTR5_IN,
+ PTR4_FN, PTR4_OUT, PTR4_IN_PU, PTR4_IN,
+ PTR3_FN, 0, PTR3_IN_PU, PTR3_IN,
+ PTR2_FN, 0, PTR2_IN_PU, PTR2_IN,
+ PTR1_FN, PTR1_OUT, PTR1_IN_PU, PTR1_IN,
+ PTR0_FN, PTR0_OUT, PTR0_IN_PU, PTR0_IN }
+ },
+ { PINMUX_CFG_REG("PSCR", 0xa405011e, 16, 2) {
+ 0, 0, 0, 0,
+ PTS6_FN, PTS6_OUT, PTS6_IN_PU, PTS6_IN,
+ PTS5_FN, PTS5_OUT, PTS5_IN_PU, PTS5_IN,
+ PTS4_FN, PTS4_OUT, PTS4_IN_PU, PTS4_IN,
+ PTS3_FN, PTS3_OUT, PTS3_IN_PU, PTS3_IN,
+ PTS2_FN, PTS2_OUT, PTS2_IN_PU, PTS2_IN,
+ PTS1_FN, PTS1_OUT, PTS1_IN_PU, PTS1_IN,
+ PTS0_FN, PTS0_OUT, PTS0_IN_PU, PTS0_IN }
+ },
+ { PINMUX_CFG_REG("PTCR", 0xa4050140, 16, 2) {
+ PTT7_FN, PTT7_OUT, PTT7_IN_PU, PTT7_IN,
+ PTT6_FN, PTT6_OUT, PTT6_IN_PU, PTT6_IN,
+ PTT5_FN, PTT5_OUT, PTT5_IN_PU, PTT5_IN,
+ PTT4_FN, PTT4_OUT, PTT4_IN_PU, PTT4_IN,
+ PTT3_FN, PTT3_OUT, PTT3_IN_PU, PTT3_IN,
+ PTT2_FN, PTT2_OUT, PTT2_IN_PU, PTT2_IN,
+ PTT1_FN, PTT1_OUT, PTT1_IN_PU, PTT1_IN,
+ PTT0_FN, PTT0_OUT, PTT0_IN_PU, PTT0_IN }
+ },
+ { PINMUX_CFG_REG("PUCR", 0xa4050142, 16, 2) {
+ PTU7_FN, PTU7_OUT, PTU7_IN_PU, PTU7_IN,
+ PTU6_FN, PTU6_OUT, PTU6_IN_PU, PTU6_IN,
+ PTU5_FN, PTU5_OUT, PTU5_IN_PU, PTU5_IN,
+ PTU4_FN, PTU4_OUT, PTU4_IN_PU, PTU4_IN,
+ PTU3_FN, PTU3_OUT, PTU3_IN_PU, PTU3_IN,
+ PTU2_FN, PTU2_OUT, PTU2_IN_PU, PTU2_IN,
+ PTU1_FN, PTU1_OUT, PTU1_IN_PU, PTU1_IN,
+ PTU0_FN, PTU0_OUT, PTU0_IN_PU, PTU0_IN }
+ },
+ { PINMUX_CFG_REG("PVCR", 0xa4050144, 16, 2) {
+ PTV7_FN, PTV7_OUT, PTV7_IN_PU, PTV7_IN,
+ PTV6_FN, PTV6_OUT, PTV6_IN_PU, PTV6_IN,
+ PTV5_FN, PTV5_OUT, PTV5_IN_PU, PTV5_IN,
+ PTV4_FN, PTV4_OUT, PTV4_IN_PU, PTV4_IN,
+ PTV3_FN, PTV3_OUT, PTV3_IN_PU, PTV3_IN,
+ PTV2_FN, PTV2_OUT, PTV2_IN_PU, PTV2_IN,
+ PTV1_FN, PTV1_OUT, PTV1_IN_PU, PTV1_IN,
+ PTV0_FN, PTV0_OUT, PTV0_IN_PU, PTV0_IN }
+ },
+ { PINMUX_CFG_REG("PWCR", 0xa4050146, 16, 2) {
+ PTW7_FN, PTW7_OUT, PTW7_IN_PU, PTW7_IN,
+ PTW6_FN, PTW6_OUT, PTW6_IN_PU, PTW6_IN,
+ PTW5_FN, PTW5_OUT, PTW5_IN_PU, PTW5_IN,
+ PTW4_FN, PTW4_OUT, PTW4_IN_PU, PTW4_IN,
+ PTW3_FN, PTW3_OUT, PTW3_IN_PU, PTW3_IN,
+ PTW2_FN, PTW2_OUT, PTW2_IN_PU, PTW2_IN,
+ PTW1_FN, PTW1_OUT, PTW1_IN_PU, PTW1_IN,
+ PTW0_FN, PTW0_OUT, PTW0_IN_PU, PTW0_IN }
+ },
+ { PINMUX_CFG_REG("PXCR", 0xa4050148, 16, 2) {
+ PTX7_FN, PTX7_OUT, PTX7_IN_PU, PTX7_IN,
+ PTX6_FN, PTX6_OUT, PTX6_IN_PU, PTX6_IN,
+ PTX5_FN, PTX5_OUT, PTX5_IN_PU, PTX5_IN,
+ PTX4_FN, PTX4_OUT, PTX4_IN_PU, PTX4_IN,
+ PTX3_FN, PTX3_OUT, PTX3_IN_PU, PTX3_IN,
+ PTX2_FN, PTX2_OUT, PTX2_IN_PU, PTX2_IN,
+ PTX1_FN, PTX1_OUT, PTX1_IN_PU, PTX1_IN,
+ PTX0_FN, PTX0_OUT, PTX0_IN_PU, PTX0_IN }
+ },
+ { PINMUX_CFG_REG("PYCR", 0xa405014a, 16, 2) {
+ PTY7_FN, PTY7_OUT, PTY7_IN_PU, PTY7_IN,
+ PTY6_FN, PTY6_OUT, PTY6_IN_PU, PTY6_IN,
+ PTY5_FN, PTY5_OUT, PTY5_IN_PU, PTY5_IN,
+ PTY4_FN, PTY4_OUT, PTY4_IN_PU, PTY4_IN,
+ PTY3_FN, PTY3_OUT, PTY3_IN_PU, PTY3_IN,
+ PTY2_FN, PTY2_OUT, PTY2_IN_PU, PTY2_IN,
+ PTY1_FN, PTY1_OUT, PTY1_IN_PU, PTY1_IN,
+ PTY0_FN, PTY0_OUT, PTY0_IN_PU, PTY0_IN }
+ },
+ { PINMUX_CFG_REG("PZCR", 0xa405014c, 16, 2) {
+ PTZ7_FN, PTZ7_OUT, PTZ7_IN_PU, PTZ7_IN,
+ PTZ6_FN, PTZ6_OUT, PTZ6_IN_PU, PTZ6_IN,
+ PTZ5_FN, PTZ5_OUT, PTZ5_IN_PU, PTZ5_IN,
+ PTZ4_FN, PTZ4_OUT, PTZ4_IN_PU, PTZ4_IN,
+ PTZ3_FN, PTZ3_OUT, PTZ3_IN_PU, PTZ3_IN,
+ PTZ2_FN, PTZ2_OUT, PTZ2_IN_PU, PTZ2_IN,
+ PTZ1_FN, PTZ1_OUT, PTZ1_IN_PU, PTZ1_IN,
+ PTZ0_FN, PTZ0_OUT, PTZ0_IN_PU, PTZ0_IN }
+ },
+ { PINMUX_CFG_REG("PSELA", 0xa405014e, 16, 1) {
+ PSA15_0, PSA15_1,
+ PSA14_0, PSA14_1,
+ PSA13_0, PSA13_1,
+ PSA12_0, PSA12_1,
+ 0, 0,
+ PSA10_0, PSA10_1,
+ PSA9_0, PSA9_1,
+ PSA8_0, PSA8_1,
+ PSA7_0, PSA7_1,
+ PSA6_0, PSA6_1,
+ PSA5_0, PSA5_1,
+ 0, 0,
+ PSA3_0, PSA3_1,
+ PSA2_0, PSA2_1,
+ PSA1_0, PSA1_1,
+ PSA0_0, PSA0_1}
+ },
+ { PINMUX_CFG_REG("PSELB", 0xa4050150, 16, 1) {
+ 0, 0,
+ PSB14_0, PSB14_1,
+ PSB13_0, PSB13_1,
+ PSB12_0, PSB12_1,
+ PSB11_0, PSB11_1,
+ PSB10_0, PSB10_1,
+ PSB9_0, PSB9_1,
+ PSB8_0, PSB8_1,
+ PSB7_0, PSB7_1,
+ PSB6_0, PSB6_1,
+ PSB5_0, PSB5_1,
+ PSB4_0, PSB4_1,
+ PSB3_0, PSB3_1,
+ PSB2_0, PSB2_1,
+ PSB1_0, PSB1_1,
+ PSB0_0, PSB0_1}
+ },
+ { PINMUX_CFG_REG("PSELC", 0xa4050152, 16, 1) {
+ PSC15_0, PSC15_1,
+ PSC14_0, PSC14_1,
+ PSC13_0, PSC13_1,
+ PSC12_0, PSC12_1,
+ PSC11_0, PSC11_1,
+ PSC10_0, PSC10_1,
+ PSC9_0, PSC9_1,
+ PSC8_0, PSC8_1,
+ PSC7_0, PSC7_1,
+ PSC6_0, PSC6_1,
+ PSC5_0, PSC5_1,
+ PSC4_0, PSC4_1,
+ 0, 0,
+ PSC2_0, PSC2_1,
+ PSC1_0, PSC1_1,
+ PSC0_0, PSC0_1}
+ },
+ { PINMUX_CFG_REG("PSELD", 0xa4050154, 16, 1) {
+ PSD15_0, PSD15_1,
+ PSD14_0, PSD14_1,
+ PSD13_0, PSD13_1,
+ PSD12_0, PSD12_1,
+ PSD11_0, PSD11_1,
+ PSD10_0, PSD10_1,
+ PSD9_0, PSD9_1,
+ PSD8_0, PSD8_1,
+ PSD7_0, PSD7_1,
+ PSD6_0, PSD6_1,
+ PSD5_0, PSD5_1,
+ PSD4_0, PSD4_1,
+ PSD3_0, PSD3_1,
+ PSD2_0, PSD2_1,
+ PSD1_0, PSD1_1,
+ PSD0_0, PSD0_1}
+ },
+ { PINMUX_CFG_REG("PSELE", 0xa4050156, 16, 1) {
+ PSE15_0, PSE15_1,
+ PSE14_0, PSE14_1,
+ PSE13_0, PSE13_1,
+ PSE12_0, PSE12_1,
+ PSE11_0, PSE11_1,
+ PSE10_0, PSE10_1,
+ PSE9_0, PSE9_1,
+ PSE8_0, PSE8_1,
+ PSE7_0, PSE7_1,
+ PSE6_0, PSE6_1,
+ PSE5_0, PSE5_1,
+ PSE4_0, PSE4_1,
+ PSE3_0, PSE3_1,
+ PSE2_0, PSE2_1,
+ PSE1_0, PSE1_1,
+ PSE0_0, PSE0_1}
+ },
+ {}
+};
+
+static struct pinmux_data_reg pinmux_data_regs[] = {
+ { PINMUX_DATA_REG("PADR", 0xa4050120, 8) {
+ PTA7_DATA, PTA6_DATA, PTA5_DATA, PTA4_DATA,
+ PTA3_DATA, PTA2_DATA, PTA1_DATA, PTA0_DATA }
+ },
+ { PINMUX_DATA_REG("PBDR", 0xa4050122, 8) {
+ PTB7_DATA, PTB6_DATA, PTB5_DATA, PTB4_DATA,
+ PTB3_DATA, PTB2_DATA, PTB1_DATA, PTB0_DATA }
+ },
+ { PINMUX_DATA_REG("PCDR", 0xa4050124, 8) {
+ PTC7_DATA, PTC6_DATA, PTC5_DATA, PTC4_DATA,
+ PTC3_DATA, PTC2_DATA, PTC1_DATA, PTC0_DATA }
+ },
+ { PINMUX_DATA_REG("PDDR", 0xa4050126, 8) {
+ PTD7_DATA, PTD6_DATA, PTD5_DATA, PTD4_DATA,
+ PTD3_DATA, PTD2_DATA, PTD1_DATA, PTD0_DATA }
+ },
+ { PINMUX_DATA_REG("PEDR", 0xa4050128, 8) {
+ PTE7_DATA, PTE6_DATA, PTE5_DATA, PTE4_DATA,
+ PTE3_DATA, PTE2_DATA, PTE1_DATA, PTE0_DATA }
+ },
+ { PINMUX_DATA_REG("PFDR", 0xa405012a, 8) {
+ PTF7_DATA, PTF6_DATA, PTF5_DATA, PTF4_DATA,
+ PTF3_DATA, PTF2_DATA, PTF1_DATA, PTF0_DATA }
+ },
+ { PINMUX_DATA_REG("PGDR", 0xa405012c, 8) {
+ 0, 0, PTG5_DATA, PTG4_DATA,
+ PTG3_DATA, PTG2_DATA, PTG1_DATA, PTG0_DATA }
+ },
+ { PINMUX_DATA_REG("PHDR", 0xa405012e, 8) {
+ PTH7_DATA, PTH6_DATA, PTH5_DATA, PTH4_DATA,
+ PTH3_DATA, PTH2_DATA, PTH1_DATA, PTH0_DATA }
+ },
+ { PINMUX_DATA_REG("PJDR", 0xa4050130, 8) {
+ PTJ7_DATA, PTJ6_DATA, PTJ5_DATA, 0,
+ PTJ3_DATA, PTJ2_DATA, PTJ1_DATA, PTJ0_DATA }
+ },
+ { PINMUX_DATA_REG("PKDR", 0xa4050132, 8) {
+ PTK7_DATA, PTK6_DATA, PTK5_DATA, PTK4_DATA,
+ PTK3_DATA, PTK2_DATA, PTK1_DATA, PTK0_DATA }
+ },
+ { PINMUX_DATA_REG("PLDR", 0xa4050134, 8) {
+ PTL7_DATA, PTL6_DATA, PTL5_DATA, PTL4_DATA,
+ PTL3_DATA, PTL2_DATA, PTL1_DATA, PTL0_DATA }
+ },
+ { PINMUX_DATA_REG("PMDR", 0xa4050136, 8) {
+ PTM7_DATA, PTM6_DATA, PTM5_DATA, PTM4_DATA,
+ PTM3_DATA, PTM2_DATA, PTM1_DATA, PTM0_DATA }
+ },
+ { PINMUX_DATA_REG("PNDR", 0xa4050138, 8) {
+ PTN7_DATA, PTN6_DATA, PTN5_DATA, PTN4_DATA,
+ PTN3_DATA, PTN2_DATA, PTN1_DATA, PTN0_DATA }
+ },
+ { PINMUX_DATA_REG("PQDR", 0xa405013a, 8) {
+ PTQ7_DATA, PTQ6_DATA, PTQ5_DATA, PTQ4_DATA,
+ PTQ3_DATA, PTQ2_DATA, PTQ1_DATA, PTQ0_DATA }
+ },
+ { PINMUX_DATA_REG("PRDR", 0xa405013c, 8) {
+ PTR7_DATA, PTR6_DATA, PTR5_DATA, PTR4_DATA,
+ PTR3_DATA, PTR2_DATA, PTR1_DATA, PTR0_DATA }
+ },
+ { PINMUX_DATA_REG("PSDR", 0xa405013e, 8) {
+ 0, PTS6_DATA, PTS5_DATA, PTS4_DATA,
+ PTS3_DATA, PTS2_DATA, PTS1_DATA, PTS0_DATA }
+ },
+ { PINMUX_DATA_REG("PTDR", 0xa4050160, 8) {
+ PTT7_DATA, PTT6_DATA, PTT5_DATA, PTT4_DATA,
+ PTT3_DATA, PTT2_DATA, PTT1_DATA, PTT0_DATA }
+ },
+ { PINMUX_DATA_REG("PUDR", 0xa4050162, 8) {
+ PTU7_DATA, PTU6_DATA, PTU5_DATA, PTU4_DATA,
+ PTU3_DATA, PTU2_DATA, PTU1_DATA, PTU0_DATA }
+ },
+ { PINMUX_DATA_REG("PVDR", 0xa4050164, 8) {
+ PTV7_DATA, PTV6_DATA, PTV5_DATA, PTV4_DATA,
+ PTV3_DATA, PTV2_DATA, PTV1_DATA, PTV0_DATA }
+ },
+ { PINMUX_DATA_REG("PWDR", 0xa4050166, 8) {
+ PTW7_DATA, PTW6_DATA, PTW5_DATA, PTW4_DATA,
+ PTW3_DATA, PTW2_DATA, PTW1_DATA, PTW0_DATA }
+ },
+ { PINMUX_DATA_REG("PXDR", 0xa4050168, 8) {
+ PTX7_DATA, PTX6_DATA, PTX5_DATA, PTX4_DATA,
+ PTX3_DATA, PTX2_DATA, PTX1_DATA, PTX0_DATA }
+ },
+ { PINMUX_DATA_REG("PYDR", 0xa405016a, 8) {
+ PTY7_DATA, PTY6_DATA, PTY5_DATA, PTY4_DATA,
+ PTY3_DATA, PTY2_DATA, PTY1_DATA, PTY0_DATA }
+ },
+ { PINMUX_DATA_REG("PZDR", 0xa405016c, 8) {
+ PTZ7_DATA, PTZ6_DATA, PTZ5_DATA, PTZ4_DATA,
+ PTZ3_DATA, PTZ2_DATA, PTZ1_DATA, PTZ0_DATA }
+ },
+ { },
+};
+
+static struct pinmux_info sh7724_pinmux_info = {
+ .name = "sh7724_pfc",
+ .reserved_id = PINMUX_RESERVED,
+ .data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
+ .input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
+ .input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
+ .output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
+ .mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
+ .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
+
+ .first_gpio = GPIO_PTA7,
+ .last_gpio = GPIO_FN_INTC_IRQ0,
+
+ .gpios = pinmux_gpios,
+ .cfg_regs = pinmux_config_regs,
+ .data_regs = pinmux_data_regs,
+
+ .gpio_data = pinmux_data,
+ .gpio_data_size = ARRAY_SIZE(pinmux_data),
+};
+
+static int __init plat_pinmux_setup(void)
+{
+ return register_pinmux(&sh7724_pinmux_info);
+}
+arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
index c1549382c87c..b9c361e8cc82 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
@@ -12,7 +12,7 @@
#include <linux/serial.h>
#include <linux/serial_sci.h>
#include <linux/uio_driver.h>
-#include <linux/sh_cmt.h>
+#include <linux/sh_timer.h>
#include <asm/clock.h>
static struct resource iic0_resources[] = {
@@ -141,7 +141,7 @@ static struct platform_device jpu_device = {
.num_resources = ARRAY_SIZE(jpu_resources),
};
-static struct sh_cmt_config cmt_platform_data = {
+static struct sh_timer_config cmt_platform_data = {
.name = "CMT",
.channel_offset = 0x60,
.timer_bit = 5,
@@ -179,21 +179,25 @@ static struct plat_sci_port sci_platform_data[] = {
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 80, 80, 80, 80 },
+ .clk = "scif0",
}, {
.mapbase = 0xffe10000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 81, 81, 81, 81 },
+ .clk = "scif1",
}, {
.mapbase = 0xffe20000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 82, 82, 82, 82 },
+ .clk = "scif2",
}, {
.mapbase = 0xffe30000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 83, 83, 83, 83 },
+ .clk = "scif3",
}, {
.flags = 0,
}
@@ -234,6 +238,16 @@ static int __init sh7343_devices_setup(void)
}
__initcall(sh7343_devices_setup);
+static struct platform_device *sh7343_early_devices[] __initdata = {
+ &cmt_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7343_early_devices,
+ ARRAY_SIZE(sh7343_early_devices));
+}
+
enum {
UNUSED = 0,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
index 93ecf8ed5c6c..d4a994be4a7d 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
@@ -14,7 +14,7 @@
#include <linux/serial.h>
#include <linux/serial_sci.h>
#include <linux/uio_driver.h>
-#include <linux/sh_cmt.h>
+#include <linux/sh_timer.h>
#include <asm/clock.h>
static struct resource iic_resources[] = {
@@ -148,7 +148,7 @@ static struct platform_device veu1_device = {
.num_resources = ARRAY_SIZE(veu1_resources),
};
-static struct sh_cmt_config cmt_platform_data = {
+static struct sh_timer_config cmt_platform_data = {
.name = "CMT",
.channel_offset = 0x60,
.timer_bit = 5,
@@ -186,6 +186,7 @@ static struct plat_sci_port sci_platform_data[] = {
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 80, 80, 80, 80 },
+ .clk = "scif0",
}, {
.flags = 0,
}
@@ -226,6 +227,16 @@ static int __init sh7366_devices_setup(void)
}
__initcall(sh7366_devices_setup);
+static struct platform_device *sh7366_early_devices[] __initdata = {
+ &cmt_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7366_early_devices,
+ ARRAY_SIZE(sh7366_early_devices));
+}
+
enum {
UNUSED=0,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index 0e5d204bc792..5d6247fecd63 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -13,7 +13,7 @@
#include <linux/serial_sci.h>
#include <linux/mm.h>
#include <linux/uio_driver.h>
-#include <linux/sh_cmt.h>
+#include <linux/sh_timer.h>
#include <asm/clock.h>
#include <asm/mmzone.h>
@@ -177,13 +177,13 @@ static struct platform_device jpu_device = {
.num_resources = ARRAY_SIZE(jpu_resources),
};
-static struct sh_cmt_config cmt_platform_data = {
+static struct sh_timer_config cmt_platform_data = {
.name = "CMT",
.channel_offset = 0x60,
.timer_bit = 5,
.clk = "cmt0",
.clockevent_rating = 125,
- .clocksource_rating = 200,
+ .clocksource_rating = 125,
};
static struct resource cmt_resources[] = {
@@ -209,24 +209,119 @@ static struct platform_device cmt_device = {
.num_resources = ARRAY_SIZE(cmt_resources),
};
+static struct sh_timer_config tmu0_platform_data = {
+ .name = "TMU0",
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clk = "tmu0",
+ .clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+ [0] = {
+ .name = "TMU0",
+ .start = 0xffd80008,
+ .end = 0xffd80013,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 16,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu0_device = {
+ .name = "sh_tmu",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu0_platform_data,
+ },
+ .resource = tmu0_resources,
+ .num_resources = ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+ .name = "TMU1",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clk = "tmu0",
+ .clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+ [0] = {
+ .name = "TMU1",
+ .start = 0xffd80014,
+ .end = 0xffd8001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 17,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu1_device = {
+ .name = "sh_tmu",
+ .id = 1,
+ .dev = {
+ .platform_data = &tmu1_platform_data,
+ },
+ .resource = tmu1_resources,
+ .num_resources = ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+ .name = "TMU2",
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+ .clk = "tmu0",
+};
+
+static struct resource tmu2_resources[] = {
+ [0] = {
+ .name = "TMU2",
+ .start = 0xffd80020,
+ .end = 0xffd8002b,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 18,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu2_device = {
+ .name = "sh_tmu",
+ .id = 2,
+ .dev = {
+ .platform_data = &tmu2_platform_data,
+ },
+ .resource = tmu2_resources,
+ .num_resources = ARRAY_SIZE(tmu2_resources),
+};
+
static struct plat_sci_port sci_platform_data[] = {
{
.mapbase = 0xffe00000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 80, 80, 80, 80 },
+ .clk = "scif0",
},
{
.mapbase = 0xffe10000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 81, 81, 81, 81 },
+ .clk = "scif1",
},
{
.mapbase = 0xffe20000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 82, 82, 82, 82 },
+ .clk = "scif2",
},
{
.flags = 0,
@@ -243,6 +338,9 @@ static struct platform_device sci_device = {
static struct platform_device *sh7722_devices[] __initdata = {
&cmt_device,
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
&rtc_device,
&usbf_device,
&iic_device,
@@ -256,7 +354,6 @@ static int __init sh7722_devices_setup(void)
{
clk_always_enable("uram0"); /* URAM */
clk_always_enable("xymem0"); /* XYMEM */
- clk_always_enable("rtc0"); /* RTC */
clk_always_enable("veu0"); /* VEU */
clk_always_enable("vpu0"); /* VPU */
clk_always_enable("jpu0"); /* JPU */
@@ -270,6 +367,19 @@ static int __init sh7722_devices_setup(void)
}
__initcall(sh7722_devices_setup);
+static struct platform_device *sh7722_early_devices[] __initdata = {
+ &cmt_device,
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7722_early_devices,
+ ARRAY_SIZE(sh7722_early_devices));
+}
+
enum {
UNUSED=0,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
index 5338dacbcfba..1429fc5e4286 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
@@ -13,7 +13,7 @@
#include <linux/mm.h>
#include <linux/serial_sci.h>
#include <linux/uio_driver.h>
-#include <linux/sh_cmt.h>
+#include <linux/sh_timer.h>
#include <asm/clock.h>
#include <asm/mmzone.h>
@@ -101,13 +101,13 @@ static struct platform_device veu1_device = {
.num_resources = ARRAY_SIZE(veu1_resources),
};
-static struct sh_cmt_config cmt_platform_data = {
+static struct sh_timer_config cmt_platform_data = {
.name = "CMT",
.channel_offset = 0x60,
.timer_bit = 5,
.clk = "cmt0",
.clockevent_rating = 125,
- .clocksource_rating = 200,
+ .clocksource_rating = 125,
};
static struct resource cmt_resources[] = {
@@ -133,37 +133,225 @@ static struct platform_device cmt_device = {
.num_resources = ARRAY_SIZE(cmt_resources),
};
+static struct sh_timer_config tmu0_platform_data = {
+ .name = "TMU0",
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clk = "tmu0",
+ .clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+ [0] = {
+ .name = "TMU0",
+ .start = 0xffd80008,
+ .end = 0xffd80013,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 16,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu0_device = {
+ .name = "sh_tmu",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu0_platform_data,
+ },
+ .resource = tmu0_resources,
+ .num_resources = ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+ .name = "TMU1",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clk = "tmu0",
+ .clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+ [0] = {
+ .name = "TMU1",
+ .start = 0xffd80014,
+ .end = 0xffd8001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 17,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu1_device = {
+ .name = "sh_tmu",
+ .id = 1,
+ .dev = {
+ .platform_data = &tmu1_platform_data,
+ },
+ .resource = tmu1_resources,
+ .num_resources = ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+ .name = "TMU2",
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+ .clk = "tmu0",
+};
+
+static struct resource tmu2_resources[] = {
+ [0] = {
+ .name = "TMU2",
+ .start = 0xffd80020,
+ .end = 0xffd8002b,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 18,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu2_device = {
+ .name = "sh_tmu",
+ .id = 2,
+ .dev = {
+ .platform_data = &tmu2_platform_data,
+ },
+ .resource = tmu2_resources,
+ .num_resources = ARRAY_SIZE(tmu2_resources),
+};
+
+static struct sh_timer_config tmu3_platform_data = {
+ .name = "TMU3",
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clk = "tmu1",
+};
+
+static struct resource tmu3_resources[] = {
+ [0] = {
+ .name = "TMU3",
+ .start = 0xffd90008,
+ .end = 0xffd90013,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 57,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu3_device = {
+ .name = "sh_tmu",
+ .id = 3,
+ .dev = {
+ .platform_data = &tmu3_platform_data,
+ },
+ .resource = tmu3_resources,
+ .num_resources = ARRAY_SIZE(tmu3_resources),
+};
+
+static struct sh_timer_config tmu4_platform_data = {
+ .name = "TMU4",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clk = "tmu1",
+};
+
+static struct resource tmu4_resources[] = {
+ [0] = {
+ .name = "TMU4",
+ .start = 0xffd90014,
+ .end = 0xffd9001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 58,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu4_device = {
+ .name = "sh_tmu",
+ .id = 4,
+ .dev = {
+ .platform_data = &tmu4_platform_data,
+ },
+ .resource = tmu4_resources,
+ .num_resources = ARRAY_SIZE(tmu4_resources),
+};
+
+static struct sh_timer_config tmu5_platform_data = {
+ .name = "TMU5",
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+ .clk = "tmu1",
+};
+
+static struct resource tmu5_resources[] = {
+ [0] = {
+ .name = "TMU5",
+ .start = 0xffd90020,
+ .end = 0xffd9002b,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 57,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu5_device = {
+ .name = "sh_tmu",
+ .id = 5,
+ .dev = {
+ .platform_data = &tmu5_platform_data,
+ },
+ .resource = tmu5_resources,
+ .num_resources = ARRAY_SIZE(tmu5_resources),
+};
+
static struct plat_sci_port sci_platform_data[] = {
{
.mapbase = 0xffe00000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 80, 80, 80, 80 },
+ .clk = "scif0",
},{
.mapbase = 0xffe10000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 81, 81, 81, 81 },
+ .clk = "scif1",
},{
.mapbase = 0xffe20000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 82, 82, 82, 82 },
+ .clk = "scif2",
},{
.mapbase = 0xa4e30000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIFA,
.irqs = { 56, 56, 56, 56 },
+ .clk = "scif3",
},{
.mapbase = 0xa4e40000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIFA,
.irqs = { 88, 88, 88, 88 },
+ .clk = "scif4",
},{
.mapbase = 0xa4e50000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIFA,
.irqs = { 109, 109, 109, 109 },
+ .clk = "scif5",
}, {
.flags = 0,
}
@@ -255,6 +443,12 @@ static struct platform_device iic_device = {
static struct platform_device *sh7723_devices[] __initdata = {
&cmt_device,
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+ &tmu3_device,
+ &tmu4_device,
+ &tmu5_device,
&sci_device,
&rtc_device,
&iic_device,
@@ -267,7 +461,6 @@ static struct platform_device *sh7723_devices[] __initdata = {
static int __init sh7723_devices_setup(void)
{
clk_always_enable("meram0"); /* MERAM */
- clk_always_enable("rtc0"); /* RTC */
clk_always_enable("veu1"); /* VEU2H1 */
clk_always_enable("veu0"); /* VEU2H0 */
clk_always_enable("vpu0"); /* VPU */
@@ -281,6 +474,22 @@ static int __init sh7723_devices_setup(void)
}
__initcall(sh7723_devices_setup);
+static struct platform_device *sh7723_early_devices[] __initdata = {
+ &cmt_device,
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+ &tmu3_device,
+ &tmu4_device,
+ &tmu5_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7723_early_devices,
+ ARRAY_SIZE(sh7723_early_devices));
+}
+
enum {
UNUSED=0,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
new file mode 100644
index 000000000000..a3039ce1a6a5
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
@@ -0,0 +1,562 @@
+/*
+ * SH7724 Setup
+ *
+ * Copyright (C) 2009 Renesas Solutions Corp.
+ *
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on SH7723 Setup
+ * Copyright (C) 2008 Paul Mundt
+ *
+ * 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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/mm.h>
+#include <linux/serial_sci.h>
+#include <linux/uio_driver.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
+#include <asm/clock.h>
+#include <asm/mmzone.h>
+
+/* Serial */
+static struct plat_sci_port sci_platform_data[] = {
+ {
+ .mapbase = 0xffe00000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 80, 80, 80, 80 },
+ .clk = "scif0",
+ }, {
+ .mapbase = 0xffe10000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 81, 81, 81, 81 },
+ .clk = "scif1",
+ }, {
+ .mapbase = 0xffe20000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 82, 82, 82, 82 },
+ .clk = "scif2",
+ }, {
+ .mapbase = 0xa4e30000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIFA,
+ .irqs = { 56, 56, 56, 56 },
+ .clk = "scif3",
+ }, {
+ .mapbase = 0xa4e40000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIFA,
+ .irqs = { 88, 88, 88, 88 },
+ .clk = "scif4",
+ }, {
+ .mapbase = 0xa4e50000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIFA,
+ .irqs = { 109, 109, 109, 109 },
+ .clk = "scif5",
+ }, {
+ .flags = 0,
+ }
+};
+
+static struct platform_device sci_device = {
+ .name = "sh-sci",
+ .id = -1,
+ .dev = {
+ .platform_data = sci_platform_data,
+ },
+};
+
+/* RTC */
+static struct resource rtc_resources[] = {
+ [0] = {
+ .start = 0xa465fec0,
+ .end = 0xa465fec0 + 0x58 - 1,
+ .flags = IORESOURCE_IO,
+ },
+ [1] = {
+ /* Period IRQ */
+ .start = 69,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ /* Carry IRQ */
+ .start = 70,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ /* Alarm IRQ */
+ .start = 68,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device rtc_device = {
+ .name = "sh-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+ .resource = rtc_resources,
+};
+
+/* I2C0 */
+static struct resource iic0_resources[] = {
+ [0] = {
+ .name = "IIC0",
+ .start = 0x04470000,
+ .end = 0x04470018 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 96,
+ .end = 99,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device iic0_device = {
+ .name = "i2c-sh_mobile",
+ .id = 0, /* "i2c0" clock */
+ .num_resources = ARRAY_SIZE(iic0_resources),
+ .resource = iic0_resources,
+};
+
+/* I2C1 */
+static struct resource iic1_resources[] = {
+ [0] = {
+ .name = "IIC1",
+ .start = 0x04750000,
+ .end = 0x04750018 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 92,
+ .end = 95,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device iic1_device = {
+ .name = "i2c-sh_mobile",
+ .id = 1, /* "i2c1" clock */
+ .num_resources = ARRAY_SIZE(iic1_resources),
+ .resource = iic1_resources,
+};
+
+/* VPU */
+static struct uio_info vpu_platform_data = {
+ .name = "VPU5F",
+ .version = "0",
+ .irq = 60,
+};
+
+static struct resource vpu_resources[] = {
+ [0] = {
+ .name = "VPU",
+ .start = 0xfe900000,
+ .end = 0xfe902807,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* place holder for contiguous memory */
+ },
+};
+
+static struct platform_device vpu_device = {
+ .name = "uio_pdrv_genirq",
+ .id = 0,
+ .dev = {
+ .platform_data = &vpu_platform_data,
+ },
+ .resource = vpu_resources,
+ .num_resources = ARRAY_SIZE(vpu_resources),
+};
+
+/* VEU0 */
+static struct uio_info veu0_platform_data = {
+ .name = "VEU3F0",
+ .version = "0",
+ .irq = 83,
+};
+
+static struct resource veu0_resources[] = {
+ [0] = {
+ .name = "VEU3F0",
+ .start = 0xfe920000,
+ .end = 0xfe9200cb - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* place holder for contiguous memory */
+ },
+};
+
+static struct platform_device veu0_device = {
+ .name = "uio_pdrv_genirq",
+ .id = 1,
+ .dev = {
+ .platform_data = &veu0_platform_data,
+ },
+ .resource = veu0_resources,
+ .num_resources = ARRAY_SIZE(veu0_resources),
+};
+
+/* VEU1 */
+static struct uio_info veu1_platform_data = {
+ .name = "VEU3F1",
+ .version = "0",
+ .irq = 54,
+};
+
+static struct resource veu1_resources[] = {
+ [0] = {
+ .name = "VEU3F1",
+ .start = 0xfe924000,
+ .end = 0xfe9240cb - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* place holder for contiguous memory */
+ },
+};
+
+static struct platform_device veu1_device = {
+ .name = "uio_pdrv_genirq",
+ .id = 2,
+ .dev = {
+ .platform_data = &veu1_platform_data,
+ },
+ .resource = veu1_resources,
+ .num_resources = ARRAY_SIZE(veu1_resources),
+};
+
+static struct sh_timer_config cmt_platform_data = {
+ .name = "CMT",
+ .channel_offset = 0x60,
+ .timer_bit = 5,
+ .clk = "cmt0",
+ .clockevent_rating = 125,
+ .clocksource_rating = 200,
+};
+
+static struct resource cmt_resources[] = {
+ [0] = {
+ .name = "CMT",
+ .start = 0x044a0060,
+ .end = 0x044a006b,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 104,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device cmt_device = {
+ .name = "sh_cmt",
+ .id = 0,
+ .dev = {
+ .platform_data = &cmt_platform_data,
+ },
+ .resource = cmt_resources,
+ .num_resources = ARRAY_SIZE(cmt_resources),
+};
+
+static struct platform_device *sh7724_devices[] __initdata = {
+ &cmt_device,
+ &sci_device,
+ &rtc_device,
+ &iic0_device,
+ &iic1_device,
+ &vpu_device,
+ &veu0_device,
+ &veu1_device,
+};
+
+static int __init sh7724_devices_setup(void)
+{
+ clk_always_enable("vpu0"); /* VPU */
+ clk_always_enable("veu1"); /* VEU3F1 */
+ clk_always_enable("veu0"); /* VEU3F0 */
+
+ platform_resource_setup_memory(&vpu_device, "vpu", 2 << 20);
+ platform_resource_setup_memory(&veu0_device, "veu0", 2 << 20);
+ platform_resource_setup_memory(&veu1_device, "veu1", 2 << 20);
+
+ return platform_add_devices(sh7724_devices,
+ ARRAY_SIZE(sh7724_devices));
+}
+device_initcall(sh7724_devices_setup);
+
+static struct platform_device *sh7724_early_devices[] __initdata = {
+ &cmt_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7724_early_devices,
+ ARRAY_SIZE(sh7724_early_devices));
+}
+
+enum {
+ UNUSED = 0,
+
+ /* interrupt sources */
+ IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
+ HUDI,
+ DMAC1A_DEI0, DMAC1A_DEI1, DMAC1A_DEI2, DMAC1A_DEI3,
+ _2DG_TRI, _2DG_INI, _2DG_CEI, _2DG_BRK,
+ DMAC0A_DEI0, DMAC0A_DEI1, DMAC0A_DEI2, DMAC0A_DEI3,
+ VIO_CEU20I, VIO_BEU20I, VIO_VEU3F1, VIO_VOUI,
+ SCIFA_SCIFA0,
+ VPU_VPUI,
+ TPU_TPUI,
+ CEU21I,
+ BEU21I,
+ USB_USI0,
+ ATAPI,
+ RTC_ATI, RTC_PRI, RTC_CUI,
+ DMAC1B_DEI4, DMAC1B_DEI5, DMAC1B_DADERR,
+ DMAC0B_DEI4, DMAC0B_DEI5, DMAC0B_DADERR,
+ KEYSC_KEYI,
+ SCIF_SCIF0, SCIF_SCIF1, SCIF_SCIF2,
+ VEU3F0I,
+ MSIOF_MSIOFI0, MSIOF_MSIOFI1,
+ SPU_SPUI0, SPU_SPUI1,
+ SCIFA_SCIFA1,
+/* ICB_ICBI, */
+ ETHI,
+ I2C1_ALI, I2C1_TACKI, I2C1_WAITI, I2C1_DTEI,
+ I2C0_ALI, I2C0_TACKI, I2C0_WAITI, I2C0_DTEI,
+ SDHI0_SDHII0, SDHI0_SDHII1, SDHI0_SDHII2,
+ CMT_CMTI,
+ TSIF_TSIFI,
+/* ICB_LMBI, */
+ FSI_FSI,
+ SCIFA_SCIFA2,
+ TMU0_TUNI0, TMU0_TUNI1, TMU0_TUNI2,
+ IRDA_IRDAI,
+ SDHI1_SDHII0, SDHI1_SDHII1, SDHI1_SDHII2,
+ JPU_JPUI,
+ MMC_MMCI0, MMC_MMCI1, MMC_MMCI2,
+ LCDC_LCDCI,
+ TMU1_TUNI0, TMU1_TUNI1, TMU1_TUNI2,
+
+ /* interrupt groups */
+ DMAC1A, _2DG, DMAC0A, VIO, RTC,
+ DMAC1B, DMAC0B, I2C0, I2C1, SDHI0, SDHI1, SPU, MMC,
+};
+
+static struct intc_vect vectors[] __initdata = {
+ INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620),
+ INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660),
+ INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0),
+ INTC_VECT(IRQ6, 0x6c0), INTC_VECT(IRQ7, 0x6e0),
+
+ INTC_VECT(DMAC1A_DEI0, 0x700),
+ INTC_VECT(DMAC1A_DEI1, 0x720),
+ INTC_VECT(DMAC1A_DEI2, 0x740),
+ INTC_VECT(DMAC1A_DEI3, 0x760),
+
+ INTC_VECT(_2DG_TRI, 0x780),
+ INTC_VECT(_2DG_INI, 0x7A0),
+ INTC_VECT(_2DG_CEI, 0x7C0),
+ INTC_VECT(_2DG_BRK, 0x7E0),
+
+ INTC_VECT(DMAC0A_DEI0, 0x800),
+ INTC_VECT(DMAC0A_DEI1, 0x820),
+ INTC_VECT(DMAC0A_DEI2, 0x840),
+ INTC_VECT(DMAC0A_DEI3, 0x860),
+
+ INTC_VECT(VIO_CEU20I, 0x880),
+ INTC_VECT(VIO_BEU20I, 0x8A0),
+ INTC_VECT(VIO_VEU3F1, 0x8C0),
+ INTC_VECT(VIO_VOUI, 0x8E0),
+
+ INTC_VECT(SCIFA_SCIFA0, 0x900),
+ INTC_VECT(VPU_VPUI, 0x980),
+ INTC_VECT(TPU_TPUI, 0x9A0),
+ INTC_VECT(CEU21I, 0x9E0),
+ INTC_VECT(BEU21I, 0xA00),
+ INTC_VECT(USB_USI0, 0xA20),
+ INTC_VECT(ATAPI, 0xA60),
+
+ INTC_VECT(RTC_ATI, 0xA80),
+ INTC_VECT(RTC_PRI, 0xAA0),
+ INTC_VECT(RTC_CUI, 0xAC0),
+
+ INTC_VECT(DMAC1B_DEI4, 0xB00),
+ INTC_VECT(DMAC1B_DEI5, 0xB20),
+ INTC_VECT(DMAC1B_DADERR, 0xB40),
+
+ INTC_VECT(DMAC0B_DEI4, 0xB80),
+ INTC_VECT(DMAC0B_DEI5, 0xBA0),
+ INTC_VECT(DMAC0B_DADERR, 0xBC0),
+
+ INTC_VECT(KEYSC_KEYI, 0xBE0),
+ INTC_VECT(SCIF_SCIF0, 0xC00),
+ INTC_VECT(SCIF_SCIF1, 0xC20),
+ INTC_VECT(SCIF_SCIF2, 0xC40),
+ INTC_VECT(VEU3F0I, 0xC60),
+ INTC_VECT(MSIOF_MSIOFI0, 0xC80),
+ INTC_VECT(MSIOF_MSIOFI1, 0xCA0),
+ INTC_VECT(SPU_SPUI0, 0xCC0),
+ INTC_VECT(SPU_SPUI1, 0xCE0),
+ INTC_VECT(SCIFA_SCIFA1, 0xD00),
+
+/* INTC_VECT(ICB_ICBI, 0xD20), */
+ INTC_VECT(ETHI, 0xD60),
+
+ INTC_VECT(I2C1_ALI, 0xD80),
+ INTC_VECT(I2C1_TACKI, 0xDA0),
+ INTC_VECT(I2C1_WAITI, 0xDC0),
+ INTC_VECT(I2C1_DTEI, 0xDE0),
+
+ INTC_VECT(I2C0_ALI, 0xE00),
+ INTC_VECT(I2C0_TACKI, 0xE20),
+ INTC_VECT(I2C0_WAITI, 0xE40),
+ INTC_VECT(I2C0_DTEI, 0xE60),
+
+ INTC_VECT(SDHI0_SDHII0, 0xE80),
+ INTC_VECT(SDHI0_SDHII1, 0xEA0),
+ INTC_VECT(SDHI0_SDHII2, 0xEC0),
+
+ INTC_VECT(CMT_CMTI, 0xF00),
+ INTC_VECT(TSIF_TSIFI, 0xF20),
+/* INTC_VECT(ICB_LMBI, 0xF60), */
+ INTC_VECT(FSI_FSI, 0xF80),
+ INTC_VECT(SCIFA_SCIFA2, 0xFA0),
+
+ INTC_VECT(TMU0_TUNI0, 0x400),
+ INTC_VECT(TMU0_TUNI1, 0x420),
+ INTC_VECT(TMU0_TUNI2, 0x440),
+
+ INTC_VECT(IRDA_IRDAI, 0x480),
+
+ INTC_VECT(SDHI1_SDHII0, 0x4E0),
+ INTC_VECT(SDHI1_SDHII1, 0x500),
+ INTC_VECT(SDHI1_SDHII2, 0x520),
+
+ INTC_VECT(JPU_JPUI, 0x560),
+
+ INTC_VECT(MMC_MMCI0, 0x580),
+ INTC_VECT(MMC_MMCI1, 0x5A0),
+ INTC_VECT(MMC_MMCI2, 0x5C0),
+
+ INTC_VECT(LCDC_LCDCI, 0xF40),
+
+ INTC_VECT(TMU1_TUNI0, 0x920),
+ INTC_VECT(TMU1_TUNI1, 0x940),
+ INTC_VECT(TMU1_TUNI2, 0x960),
+};
+
+static struct intc_group groups[] __initdata = {
+ INTC_GROUP(DMAC1A, DMAC1A_DEI0, DMAC1A_DEI1, DMAC1A_DEI2, DMAC1A_DEI3),
+ INTC_GROUP(_2DG, _2DG_TRI, _2DG_INI, _2DG_CEI, _2DG_BRK),
+ INTC_GROUP(DMAC0A, DMAC0A_DEI0, DMAC0A_DEI1, DMAC0A_DEI2, DMAC0A_DEI3),
+ INTC_GROUP(VIO, VIO_CEU20I, VIO_BEU20I, VIO_VEU3F1, VIO_VOUI),
+ INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
+ INTC_GROUP(DMAC1B, DMAC1B_DEI4, DMAC1B_DEI5, DMAC1B_DADERR),
+ INTC_GROUP(DMAC0B, DMAC0B_DEI4, DMAC0B_DEI5, DMAC0B_DADERR),
+ INTC_GROUP(I2C0, I2C0_ALI, I2C0_TACKI, I2C0_WAITI, I2C0_DTEI),
+ INTC_GROUP(I2C1, I2C1_ALI, I2C1_TACKI, I2C1_WAITI, I2C1_DTEI),
+ INTC_GROUP(SDHI0, SDHI0_SDHII0, SDHI0_SDHII1, SDHI0_SDHII2),
+ INTC_GROUP(SDHI1, SDHI1_SDHII0, SDHI1_SDHII1, SDHI1_SDHII2),
+ INTC_GROUP(SPU, SPU_SPUI0, SPU_SPUI1),
+ INTC_GROUP(MMC, MMC_MMCI0, MMC_MMCI1, MMC_MMCI2),
+};
+
+/* FIXMEEEEEEEEEEEEEEEEEEE !!!!! */
+/* very bad manual !! */
+static struct intc_mask_reg mask_registers[] __initdata = {
+ { 0xa4080080, 0xa40800c0, 8, /* IMR0 / IMCR0 */
+ { 0, TMU1_TUNI2, TMU1_TUNI1, TMU1_TUNI0,
+ /*SDHII3?*/0, SDHI1_SDHII2, SDHI1_SDHII1, SDHI1_SDHII0 } },
+ { 0xa4080084, 0xa40800c4, 8, /* IMR1 / IMCR1 */
+ { VIO_VOUI, VIO_VEU3F1, VIO_BEU20I, VIO_CEU20I,
+ DMAC0A_DEI3, DMAC0A_DEI2, DMAC0A_DEI1, DMAC0A_DEI0 } },
+ { 0xa4080088, 0xa40800c8, 8, /* IMR2 / IMCR2 */
+ { 0, 0, 0, VPU_VPUI, ATAPI, ETHI, 0, /*SCIFA3*/SCIFA_SCIFA0 } },
+ { 0xa408008c, 0xa40800cc, 8, /* IMR3 / IMCR3 */
+ { DMAC1A_DEI3, DMAC1A_DEI2, DMAC1A_DEI1, DMAC1A_DEI0,
+ SPU_SPUI1, SPU_SPUI0, BEU21I, IRDA_IRDAI } },
+ { 0xa4080090, 0xa40800d0, 8, /* IMR4 / IMCR4 */
+ { 0, TMU0_TUNI2, TMU0_TUNI1, TMU0_TUNI0,
+ JPU_JPUI, 0, 0, LCDC_LCDCI } },
+ { 0xa4080094, 0xa40800d4, 8, /* IMR5 / IMCR5 */
+ { KEYSC_KEYI, DMAC0B_DADERR, DMAC0B_DEI5, DMAC0B_DEI4,
+ VEU3F0I, SCIF_SCIF2, SCIF_SCIF1, SCIF_SCIF0 } },
+ { 0xa4080098, 0xa40800d8, 8, /* IMR6 / IMCR6 */
+ { 0, 0, /*ICB_ICBI*/0, /*SCIFA4*/SCIFA_SCIFA1,
+ CEU21I, 0, MSIOF_MSIOFI1, MSIOF_MSIOFI0 } },
+ { 0xa408009c, 0xa40800dc, 8, /* IMR7 / IMCR7 */
+ { I2C0_DTEI, I2C0_WAITI, I2C0_TACKI, I2C0_ALI,
+ I2C1_DTEI, I2C1_WAITI, I2C1_TACKI, I2C1_ALI } },
+ { 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */
+ { /*SDHII3*/0, SDHI0_SDHII2, SDHI0_SDHII1, SDHI0_SDHII0,
+ 0, 0, /*SCIFA5*/SCIFA_SCIFA2, FSI_FSI } },
+ { 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */
+ { 0, 0, 0, CMT_CMTI, 0, /*USB1*/0, USB_USI0, 0 } },
+ { 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */
+ { 0, DMAC1B_DADERR, DMAC1B_DEI5, DMAC1B_DEI4,
+ 0, RTC_ATI, RTC_PRI, RTC_CUI } },
+ { 0xa40800ac, 0xa40800ec, 8, /* IMR11 / IMCR11 */
+ { _2DG_BRK, _2DG_CEI, _2DG_INI, _2DG_TRI,
+ 0, TPU_TPUI, /*ICB_LMBI*/0, TSIF_TSIFI } },
+ { 0xa40800b0, 0xa40800f0, 8, /* IMR12 / IMCR12 */
+ { 0, 0, 0, 0, 0, 0, 0, 0/*2DDMAC*/ } },
+ { 0xa4140044, 0xa4140064, 8, /* INTMSK00 / INTMSKCLR00 */
+ { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_prio_reg prio_registers[] __initdata = {
+ { 0xa4080000, 0, 16, 4, /* IPRA */ { TMU0_TUNI0, TMU0_TUNI1,
+ TMU0_TUNI2, IRDA_IRDAI } },
+ { 0xa4080004, 0, 16, 4, /* IPRB */ { JPU_JPUI, LCDC_LCDCI,
+ DMAC1A, BEU21I } },
+ { 0xa4080008, 0, 16, 4, /* IPRC */ { TMU1_TUNI0, TMU1_TUNI1,
+ TMU1_TUNI2, SPU } },
+ { 0xa408000c, 0, 16, 4, /* IPRD */ { 0, MMC, 0, ATAPI } },
+ { 0xa4080010, 0, 16, 4, /* IPRE */
+ { DMAC0A, /*BEU?VEU?*/VIO, /*SCIFA3*/SCIFA_SCIFA0, /*VPU5F*/
+ VPU_VPUI } },
+ { 0xa4080014, 0, 16, 4, /* IPRF */ { KEYSC_KEYI, DMAC0B,
+ USB_USI0, CMT_CMTI } },
+ { 0xa4080018, 0, 16, 4, /* IPRG */ { SCIF_SCIF0, SCIF_SCIF1,
+ SCIF_SCIF2, VEU3F0I } },
+ { 0xa408001c, 0, 16, 4, /* IPRH */ { MSIOF_MSIOFI0, MSIOF_MSIOFI1,
+ I2C1, I2C0 } },
+ { 0xa4080020, 0, 16, 4, /* IPRI */ { /*SCIFA4*/SCIFA_SCIFA1, /*ICB*/0,
+ TSIF_TSIFI, _2DG/*ICB?*/ } },
+ { 0xa4080024, 0, 16, 4, /* IPRJ */ { CEU21I, ETHI, FSI_FSI, SDHI1 } },
+ { 0xa4080028, 0, 16, 4, /* IPRK */ { RTC, DMAC1B, /*ICB?*/0, SDHI0 } },
+ { 0xa408002c, 0, 16, 4, /* IPRL */ { /*SCIFA5*/SCIFA_SCIFA2, 0,
+ TPU_TPUI, /*2DDMAC*/0 } },
+ { 0xa4140010, 0, 32, 4, /* INTPRI00 */
+ { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_sense_reg sense_registers[] __initdata = {
+ { 0xa414001c, 16, 2, /* ICR1 */
+ { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_mask_reg ack_registers[] __initdata = {
+ { 0xa4140024, 0, 8, /* INTREQ00 */
+ { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_desc, "sh7724", vectors, groups,
+ mask_registers, prio_registers, sense_registers,
+ ack_registers);
+
+void __init plat_irq_setup(void)
+{
+ register_intc_controller(&intc_desc);
+}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
index 6f7227cd65bf..f1df02095062 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
@@ -12,6 +12,189 @@
#include <linux/serial.h>
#include <linux/io.h>
#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+
+static struct sh_timer_config tmu0_platform_data = {
+ .name = "TMU0",
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clk = "module_clk",
+ .clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+ [0] = {
+ .name = "TMU0",
+ .start = 0xffd80008,
+ .end = 0xffd80013,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 28,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu0_device = {
+ .name = "sh_tmu",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu0_platform_data,
+ },
+ .resource = tmu0_resources,
+ .num_resources = ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+ .name = "TMU1",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clk = "module_clk",
+ .clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+ [0] = {
+ .name = "TMU1",
+ .start = 0xffd80014,
+ .end = 0xffd8001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 29,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu1_device = {
+ .name = "sh_tmu",
+ .id = 1,
+ .dev = {
+ .platform_data = &tmu1_platform_data,
+ },
+ .resource = tmu1_resources,
+ .num_resources = ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+ .name = "TMU2",
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+ .clk = "module_clk",
+};
+
+static struct resource tmu2_resources[] = {
+ [0] = {
+ .name = "TMU2",
+ .start = 0xffd80020,
+ .end = 0xffd8002f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 30,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu2_device = {
+ .name = "sh_tmu",
+ .id = 2,
+ .dev = {
+ .platform_data = &tmu2_platform_data,
+ },
+ .resource = tmu2_resources,
+ .num_resources = ARRAY_SIZE(tmu2_resources),
+};
+
+static struct sh_timer_config tmu3_platform_data = {
+ .name = "TMU3",
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clk = "module_clk",
+};
+
+static struct resource tmu3_resources[] = {
+ [0] = {
+ .name = "TMU3",
+ .start = 0xffdc0008,
+ .end = 0xffdc0013,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 96,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu3_device = {
+ .name = "sh_tmu",
+ .id = 3,
+ .dev = {
+ .platform_data = &tmu3_platform_data,
+ },
+ .resource = tmu3_resources,
+ .num_resources = ARRAY_SIZE(tmu3_resources),
+};
+
+static struct sh_timer_config tmu4_platform_data = {
+ .name = "TMU4",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clk = "module_clk",
+};
+
+static struct resource tmu4_resources[] = {
+ [0] = {
+ .name = "TMU4",
+ .start = 0xffdc0014,
+ .end = 0xffdc001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 97,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu4_device = {
+ .name = "sh_tmu",
+ .id = 4,
+ .dev = {
+ .platform_data = &tmu4_platform_data,
+ },
+ .resource = tmu4_resources,
+ .num_resources = ARRAY_SIZE(tmu4_resources),
+};
+
+static struct sh_timer_config tmu5_platform_data = {
+ .name = "TMU5",
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+ .clk = "module_clk",
+};
+
+static struct resource tmu5_resources[] = {
+ [0] = {
+ .name = "TMU5",
+ .start = 0xffdc0020,
+ .end = 0xffdc002b,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 98,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu5_device = {
+ .name = "sh_tmu",
+ .id = 5,
+ .dev = {
+ .platform_data = &tmu5_platform_data,
+ },
+ .resource = tmu5_resources,
+ .num_resources = ARRAY_SIZE(tmu5_resources),
+};
static struct resource rtc_resources[] = {
[0] = {
@@ -58,6 +241,12 @@ static struct platform_device sci_device = {
};
static struct platform_device *sh7780_devices[] __initdata = {
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+ &tmu3_device,
+ &tmu4_device,
+ &tmu5_device,
&rtc_device,
&sci_device,
};
@@ -69,6 +258,21 @@ static int __init sh7780_devices_setup(void)
}
__initcall(sh7780_devices_setup);
+static struct platform_device *sh7780_early_devices[] __initdata = {
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+ &tmu3_device,
+ &tmu4_device,
+ &tmu5_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7780_early_devices,
+ ARRAY_SIZE(sh7780_early_devices));
+}
+
enum {
UNUSED = 0,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
index d80802a49dbd..dc5d3e507a21 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
@@ -13,8 +13,191 @@
#include <linux/serial_sci.h>
#include <linux/io.h>
#include <linux/mm.h>
+#include <linux/sh_timer.h>
#include <asm/mmzone.h>
+static struct sh_timer_config tmu0_platform_data = {
+ .name = "TMU0",
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clk = "module_clk",
+ .clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+ [0] = {
+ .name = "TMU0",
+ .start = 0xffd80008,
+ .end = 0xffd80013,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 28,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu0_device = {
+ .name = "sh_tmu",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu0_platform_data,
+ },
+ .resource = tmu0_resources,
+ .num_resources = ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+ .name = "TMU1",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clk = "module_clk",
+ .clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+ [0] = {
+ .name = "TMU1",
+ .start = 0xffd80014,
+ .end = 0xffd8001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 29,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu1_device = {
+ .name = "sh_tmu",
+ .id = 1,
+ .dev = {
+ .platform_data = &tmu1_platform_data,
+ },
+ .resource = tmu1_resources,
+ .num_resources = ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+ .name = "TMU2",
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+ .clk = "module_clk",
+};
+
+static struct resource tmu2_resources[] = {
+ [0] = {
+ .name = "TMU2",
+ .start = 0xffd80020,
+ .end = 0xffd8002f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 30,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu2_device = {
+ .name = "sh_tmu",
+ .id = 2,
+ .dev = {
+ .platform_data = &tmu2_platform_data,
+ },
+ .resource = tmu2_resources,
+ .num_resources = ARRAY_SIZE(tmu2_resources),
+};
+
+static struct sh_timer_config tmu3_platform_data = {
+ .name = "TMU3",
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clk = "module_clk",
+};
+
+static struct resource tmu3_resources[] = {
+ [0] = {
+ .name = "TMU3",
+ .start = 0xffdc0008,
+ .end = 0xffdc0013,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 96,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu3_device = {
+ .name = "sh_tmu",
+ .id = 3,
+ .dev = {
+ .platform_data = &tmu3_platform_data,
+ },
+ .resource = tmu3_resources,
+ .num_resources = ARRAY_SIZE(tmu3_resources),
+};
+
+static struct sh_timer_config tmu4_platform_data = {
+ .name = "TMU4",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clk = "module_clk",
+};
+
+static struct resource tmu4_resources[] = {
+ [0] = {
+ .name = "TMU4",
+ .start = 0xffdc0014,
+ .end = 0xffdc001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 97,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu4_device = {
+ .name = "sh_tmu",
+ .id = 4,
+ .dev = {
+ .platform_data = &tmu4_platform_data,
+ },
+ .resource = tmu4_resources,
+ .num_resources = ARRAY_SIZE(tmu4_resources),
+};
+
+static struct sh_timer_config tmu5_platform_data = {
+ .name = "TMU5",
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+ .clk = "module_clk",
+};
+
+static struct resource tmu5_resources[] = {
+ [0] = {
+ .name = "TMU5",
+ .start = 0xffdc0020,
+ .end = 0xffdc002b,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 98,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu5_device = {
+ .name = "sh_tmu",
+ .id = 5,
+ .dev = {
+ .platform_data = &tmu5_platform_data,
+ },
+ .resource = tmu5_resources,
+ .num_resources = ARRAY_SIZE(tmu5_resources),
+};
+
static struct plat_sci_port sci_platform_data[] = {
{
.mapbase = 0xffea0000,
@@ -60,6 +243,12 @@ static struct platform_device sci_device = {
};
static struct platform_device *sh7785_devices[] __initdata = {
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+ &tmu3_device,
+ &tmu4_device,
+ &tmu5_device,
&sci_device,
};
@@ -70,6 +259,21 @@ static int __init sh7785_devices_setup(void)
}
__initcall(sh7785_devices_setup);
+static struct platform_device *sh7785_early_devices[] __initdata = {
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+ &tmu3_device,
+ &tmu4_device,
+ &tmu5_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7785_early_devices,
+ ARRAY_SIZE(sh7785_early_devices));
+}
+
enum {
UNUSED = 0,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
index 5a47e1cf442e..2c464bf5a899 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2009 Renesas Solutions Corp.
* Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ * Paul Mundt <paul.mundt@renesas.com>
*
* Based on SH7785 Setup
*
@@ -19,6 +20,7 @@
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/dma-mapping.h>
+#include <linux/sh_timer.h>
#include <asm/mmzone.h>
static struct plat_sci_port sci_platform_data[] = {
@@ -69,6 +71,368 @@ static struct platform_device sci_device = {
},
};
+static struct sh_timer_config tmu0_platform_data = {
+ .name = "TMU0",
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clk = "module_clk",
+ .clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+ [0] = {
+ .name = "TMU0",
+ .start = 0xffd80008,
+ .end = 0xffd80013,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 16,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu0_device = {
+ .name = "sh_tmu",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu0_platform_data,
+ },
+ .resource = tmu0_resources,
+ .num_resources = ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+ .name = "TMU1",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clk = "module_clk",
+ .clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+ [0] = {
+ .name = "TMU1",
+ .start = 0xffd80014,
+ .end = 0xffd8001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 17,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu1_device = {
+ .name = "sh_tmu",
+ .id = 1,
+ .dev = {
+ .platform_data = &tmu1_platform_data,
+ },
+ .resource = tmu1_resources,
+ .num_resources = ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+ .name = "TMU2",
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+ .clk = "module_clk",
+};
+
+static struct resource tmu2_resources[] = {
+ [0] = {
+ .name = "TMU2",
+ .start = 0xffd80020,
+ .end = 0xffd8002f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 18,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu2_device = {
+ .name = "sh_tmu",
+ .id = 2,
+ .dev = {
+ .platform_data = &tmu2_platform_data,
+ },
+ .resource = tmu2_resources,
+ .num_resources = ARRAY_SIZE(tmu2_resources),
+};
+
+static struct sh_timer_config tmu3_platform_data = {
+ .name = "TMU3",
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clk = "module_clk",
+};
+
+static struct resource tmu3_resources[] = {
+ [0] = {
+ .name = "TMU3",
+ .start = 0xffda0008,
+ .end = 0xffda0013,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 20,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu3_device = {
+ .name = "sh_tmu",
+ .id = 3,
+ .dev = {
+ .platform_data = &tmu3_platform_data,
+ },
+ .resource = tmu3_resources,
+ .num_resources = ARRAY_SIZE(tmu3_resources),
+};
+
+static struct sh_timer_config tmu4_platform_data = {
+ .name = "TMU4",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clk = "module_clk",
+};
+
+static struct resource tmu4_resources[] = {
+ [0] = {
+ .name = "TMU4",
+ .start = 0xffda0014,
+ .end = 0xffda001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 21,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu4_device = {
+ .name = "sh_tmu",
+ .id = 4,
+ .dev = {
+ .platform_data = &tmu4_platform_data,
+ },
+ .resource = tmu4_resources,
+ .num_resources = ARRAY_SIZE(tmu4_resources),
+};
+
+static struct sh_timer_config tmu5_platform_data = {
+ .name = "TMU5",
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+ .clk = "module_clk",
+};
+
+static struct resource tmu5_resources[] = {
+ [0] = {
+ .name = "TMU5",
+ .start = 0xffda0020,
+ .end = 0xffda002b,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 22,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu5_device = {
+ .name = "sh_tmu",
+ .id = 5,
+ .dev = {
+ .platform_data = &tmu5_platform_data,
+ },
+ .resource = tmu5_resources,
+ .num_resources = ARRAY_SIZE(tmu5_resources),
+};
+
+static struct sh_timer_config tmu6_platform_data = {
+ .name = "TMU6",
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clk = "module_clk",
+};
+
+static struct resource tmu6_resources[] = {
+ [0] = {
+ .name = "TMU6",
+ .start = 0xffdc0008,
+ .end = 0xffdc0013,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 45,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu6_device = {
+ .name = "sh_tmu",
+ .id = 6,
+ .dev = {
+ .platform_data = &tmu6_platform_data,
+ },
+ .resource = tmu6_resources,
+ .num_resources = ARRAY_SIZE(tmu6_resources),
+};
+
+static struct sh_timer_config tmu7_platform_data = {
+ .name = "TMU7",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clk = "module_clk",
+};
+
+static struct resource tmu7_resources[] = {
+ [0] = {
+ .name = "TMU7",
+ .start = 0xffdc0014,
+ .end = 0xffdc001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 45,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu7_device = {
+ .name = "sh_tmu",
+ .id = 7,
+ .dev = {
+ .platform_data = &tmu7_platform_data,
+ },
+ .resource = tmu7_resources,
+ .num_resources = ARRAY_SIZE(tmu7_resources),
+};
+
+static struct sh_timer_config tmu8_platform_data = {
+ .name = "TMU8",
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+ .clk = "module_clk",
+};
+
+static struct resource tmu8_resources[] = {
+ [0] = {
+ .name = "TMU8",
+ .start = 0xffdc0020,
+ .end = 0xffdc002b,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 45,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu8_device = {
+ .name = "sh_tmu",
+ .id = 8,
+ .dev = {
+ .platform_data = &tmu8_platform_data,
+ },
+ .resource = tmu8_resources,
+ .num_resources = ARRAY_SIZE(tmu8_resources),
+};
+
+static struct sh_timer_config tmu9_platform_data = {
+ .name = "TMU9",
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clk = "module_clk",
+};
+
+static struct resource tmu9_resources[] = {
+ [0] = {
+ .name = "TMU9",
+ .start = 0xffde0008,
+ .end = 0xffde0013,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 46,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu9_device = {
+ .name = "sh_tmu",
+ .id = 9,
+ .dev = {
+ .platform_data = &tmu9_platform_data,
+ },
+ .resource = tmu9_resources,
+ .num_resources = ARRAY_SIZE(tmu9_resources),
+};
+
+static struct sh_timer_config tmu10_platform_data = {
+ .name = "TMU10",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clk = "module_clk",
+};
+
+static struct resource tmu10_resources[] = {
+ [0] = {
+ .name = "TMU10",
+ .start = 0xffde0014,
+ .end = 0xffde001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 46,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu10_device = {
+ .name = "sh_tmu",
+ .id = 10,
+ .dev = {
+ .platform_data = &tmu10_platform_data,
+ },
+ .resource = tmu10_resources,
+ .num_resources = ARRAY_SIZE(tmu10_resources),
+};
+
+static struct sh_timer_config tmu11_platform_data = {
+ .name = "TMU11",
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+ .clk = "module_clk",
+};
+
+static struct resource tmu11_resources[] = {
+ [0] = {
+ .name = "TMU11",
+ .start = 0xffde0020,
+ .end = 0xffde002b,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 46,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu11_device = {
+ .name = "sh_tmu",
+ .id = 11,
+ .dev = {
+ .platform_data = &tmu11_platform_data,
+ },
+ .resource = tmu11_resources,
+ .num_resources = ARRAY_SIZE(tmu11_resources),
+};
+
static struct resource usb_ohci_resources[] = {
[0] = {
.start = 0xffe70400,
@@ -94,6 +458,21 @@ static struct platform_device usb_ohci_device = {
.resource = usb_ohci_resources,
};
+static struct platform_device *sh7786_early_devices[] __initdata = {
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+ &tmu3_device,
+ &tmu4_device,
+ &tmu5_device,
+ &tmu6_device,
+ &tmu7_device,
+ &tmu8_device,
+ &tmu9_device,
+ &tmu10_device,
+ &tmu11_device,
+};
+
static struct platform_device *sh7786_devices[] __initdata = {
&sci_device,
&usb_ohci_device,
@@ -143,25 +522,39 @@ static void __init sh7786_usb_setup(void)
* Set the PHY and PLL enable bit
*/
__raw_writel(PHY_ENB | PLL_ENB, USBPCTL1);
- while (i-- &&
- ((__raw_readl(USBST) & ACT_PLL_STATUS) != ACT_PLL_STATUS))
+ while (i--) {
+ if (ACT_PLL_STATUS == (__raw_readl(USBST) & ACT_PLL_STATUS)) {
+ /* Set the PHY RST bit */
+ __raw_writel(PHY_ENB | PLL_ENB | PHY_RST, USBPCTL1);
+ printk(KERN_INFO "sh7786 usb setup done\n");
+ break;
+ }
cpu_relax();
-
- if (i) {
- /* Set the PHY RST bit */
- __raw_writel(PHY_ENB | PLL_ENB | PHY_RST, USBPCTL1);
- printk(KERN_INFO "sh7786 usb setup done\n");
}
}
static int __init sh7786_devices_setup(void)
{
+ int ret;
+
sh7786_usb_setup();
+
+ ret = platform_add_devices(sh7786_early_devices,
+ ARRAY_SIZE(sh7786_early_devices));
+ if (unlikely(ret != 0))
+ return ret;
+
return platform_add_devices(sh7786_devices,
ARRAY_SIZE(sh7786_devices));
}
device_initcall(sh7786_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7786_early_devices,
+ ARRAY_SIZE(sh7786_early_devices));
+}
+
enum {
UNUSED = 0,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-shx3.c b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
index bd35f32534b9..9d5185b42f13 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-shx3.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
@@ -1,7 +1,7 @@
/*
- * SH-X3 Setup
+ * SH-X3 Prototype Setup
*
- * Copyright (C) 2007 Paul Mundt
+ * Copyright (C) 2007 - 2009 Paul Mundt
*
* 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
@@ -12,6 +12,7 @@
#include <linux/serial.h>
#include <linux/serial_sci.h>
#include <linux/io.h>
+#include <linux/sh_timer.h>
#include <asm/mmzone.h>
static struct plat_sci_port sci_platform_data[] = {
@@ -48,17 +49,221 @@ static struct platform_device sci_device = {
},
};
+static struct sh_timer_config tmu0_platform_data = {
+ .name = "TMU0",
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clk = "module_clk",
+ .clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+ [0] = {
+ .name = "TMU0",
+ .start = 0xffc10008,
+ .end = 0xffc10013,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 16,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu0_device = {
+ .name = "sh_tmu",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu0_platform_data,
+ },
+ .resource = tmu0_resources,
+ .num_resources = ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+ .name = "TMU1",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clk = "module_clk",
+ .clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+ [0] = {
+ .name = "TMU1",
+ .start = 0xffc10014,
+ .end = 0xffc1001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 17,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu1_device = {
+ .name = "sh_tmu",
+ .id = 1,
+ .dev = {
+ .platform_data = &tmu1_platform_data,
+ },
+ .resource = tmu1_resources,
+ .num_resources = ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+ .name = "TMU2",
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+ .clk = "module_clk",
+};
+
+static struct resource tmu2_resources[] = {
+ [0] = {
+ .name = "TMU2",
+ .start = 0xffc10020,
+ .end = 0xffc1002f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 18,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu2_device = {
+ .name = "sh_tmu",
+ .id = 2,
+ .dev = {
+ .platform_data = &tmu2_platform_data,
+ },
+ .resource = tmu2_resources,
+ .num_resources = ARRAY_SIZE(tmu2_resources),
+};
+
+static struct sh_timer_config tmu3_platform_data = {
+ .name = "TMU3",
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clk = "module_clk",
+};
+
+static struct resource tmu3_resources[] = {
+ [0] = {
+ .name = "TMU3",
+ .start = 0xffc20008,
+ .end = 0xffc20013,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 19,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu3_device = {
+ .name = "sh_tmu",
+ .id = 3,
+ .dev = {
+ .platform_data = &tmu3_platform_data,
+ },
+ .resource = tmu3_resources,
+ .num_resources = ARRAY_SIZE(tmu3_resources),
+};
+
+static struct sh_timer_config tmu4_platform_data = {
+ .name = "TMU4",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clk = "module_clk",
+};
+
+static struct resource tmu4_resources[] = {
+ [0] = {
+ .name = "TMU4",
+ .start = 0xffc20014,
+ .end = 0xffc2001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 20,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu4_device = {
+ .name = "sh_tmu",
+ .id = 4,
+ .dev = {
+ .platform_data = &tmu4_platform_data,
+ },
+ .resource = tmu4_resources,
+ .num_resources = ARRAY_SIZE(tmu4_resources),
+};
+
+static struct sh_timer_config tmu5_platform_data = {
+ .name = "TMU5",
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+ .clk = "module_clk",
+};
+
+static struct resource tmu5_resources[] = {
+ [0] = {
+ .name = "TMU5",
+ .start = 0xffc20020,
+ .end = 0xffc2002b,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 21,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu5_device = {
+ .name = "sh_tmu",
+ .id = 5,
+ .dev = {
+ .platform_data = &tmu5_platform_data,
+ },
+ .resource = tmu5_resources,
+ .num_resources = ARRAY_SIZE(tmu5_resources),
+};
+
+static struct platform_device *shx3_early_devices[] __initdata = {
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+ &tmu3_device,
+ &tmu4_device,
+ &tmu5_device,
+};
+
static struct platform_device *shx3_devices[] __initdata = {
&sci_device,
};
static int __init shx3_devices_setup(void)
{
+ int ret;
+
+ ret = platform_add_devices(shx3_early_devices,
+ ARRAY_SIZE(shx3_early_devices));
+ if (unlikely(ret != 0))
+ return ret;
+
return platform_add_devices(shx3_devices,
ARRAY_SIZE(shx3_devices));
}
__initcall(shx3_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(shx3_early_devices,
+ ARRAY_SIZE(shx3_early_devices));
+}
+
enum {
UNUSED = 0,
diff --git a/arch/sh/kernel/cpu/sh5/Makefile b/arch/sh/kernel/cpu/sh5/Makefile
index ce4602ea23a8..a184a31e686e 100644
--- a/arch/sh/kernel/cpu/sh5/Makefile
+++ b/arch/sh/kernel/cpu/sh5/Makefile
@@ -6,6 +6,9 @@ obj-y := entry.o probe.o switchto.o
obj-$(CONFIG_SH_FPU) += fpu.o
obj-$(CONFIG_KALLSYMS) += unwind.o
+# CPU subtype setup
+obj-$(CONFIG_CPU_SH5) += setup-sh5.o
+
# Primary on-chip clocks (common)
clock-$(CONFIG_CPU_SH5) := clock-sh5.o
diff --git a/arch/sh/kernel/cpu/sh5/clock-sh5.c b/arch/sh/kernel/cpu/sh5/clock-sh5.c
index 52c49248833a..5486324880e1 100644
--- a/arch/sh/kernel/cpu/sh5/clock-sh5.c
+++ b/arch/sh/kernel/cpu/sh5/clock-sh5.c
@@ -71,7 +71,7 @@ static struct clk_ops *sh5_clk_ops[] = {
void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
{
- cprc_base = onchip_remap(CPRC_BASE, 1024, "CPRC");
+ cprc_base = (unsigned long)ioremap_nocache(CPRC_BASE, 1024);
BUG_ON(!cprc_base);
if (idx < ARRAY_SIZE(sh5_clk_ops))
diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S
index e640c63d5811..b0aacf675258 100644
--- a/arch/sh/kernel/cpu/sh5/entry.S
+++ b/arch/sh/kernel/cpu/sh5/entry.S
@@ -10,6 +10,7 @@
* for more details.
*/
#include <linux/errno.h>
+#include <linux/init.h>
#include <linux/sys.h>
#include <cpu/registers.h>
#include <asm/processor.h>
@@ -811,27 +812,6 @@ no_underflow:
! exceptions
add SP, ZERO, r14
-#ifdef CONFIG_POOR_MANS_STRACE
- /* We've pushed all the registers now, so only r2-r4 hold anything
- * useful. Move them into callee save registers */
- or r2, ZERO, r28
- or r3, ZERO, r29
- or r4, ZERO, r30
-
- /* Preserve r2 as the event code */
- movi evt_debug, r3
- ori r3, 1, r3
- ptabs r3, tr0
-
- or SP, ZERO, r6
- getcon TRA, r5
- blink tr0, LINK
-
- or r28, ZERO, r2
- or r29, ZERO, r3
- or r30, ZERO, r4
-#endif
-
/* For syscall and debug race condition, get TRA now */
getcon TRA, r5
@@ -886,11 +866,6 @@ no_underflow:
*/
.global ret_from_irq
ret_from_irq:
-#ifdef CONFIG_POOR_MANS_STRACE
- pta evt_debug_ret_from_irq, tr0
- ori SP, 0, r2
- blink tr0, LINK
-#endif
ld.q SP, FRAME_S(FSSR), r6
shlri r6, 30, r6
andi r6, 1, r6
@@ -904,12 +879,6 @@ ret_from_irq:
ret_from_exception:
preempt_stop()
-#ifdef CONFIG_POOR_MANS_STRACE
- pta evt_debug_ret_from_exc, tr0
- ori SP, 0, r2
- blink tr0, LINK
-#endif
-
ld.q SP, FRAME_S(FSSR), r6
shlri r6, 30, r6
andi r6, 1, r6
@@ -1235,18 +1204,6 @@ syscall_bad:
.global syscall_ret
syscall_ret:
st.q SP, FRAME_R(9), r2 /* Expecting SP back to BASIC frame */
-
-#ifdef CONFIG_POOR_MANS_STRACE
- /* nothing useful in registers at this point */
-
- movi evt_debug2, r5
- ori r5, 1, r5
- ptabs r5, tr0
- ld.q SP, FRAME_R(9), r2
- or SP, ZERO, r3
- blink tr0, LINK
-#endif
-
ld.q SP, FRAME_S(FSPC), r2
addi r2, 4, r2 /* Move PC, being pre-execution event */
st.q SP, FRAME_S(FSPC), r2
@@ -1267,25 +1224,12 @@ ret_from_fork:
ptabs r5, tr0
blink tr0, LINK
-#ifdef CONFIG_POOR_MANS_STRACE
- /* nothing useful in registers at this point */
-
- movi evt_debug2, r5
- ori r5, 1, r5
- ptabs r5, tr0
- ld.q SP, FRAME_R(9), r2
- or SP, ZERO, r3
- blink tr0, LINK
-#endif
-
ld.q SP, FRAME_S(FSPC), r2
addi r2, 4, r2 /* Move PC, being pre-execution event */
st.q SP, FRAME_S(FSPC), r2
pta ret_from_syscall, tr0
blink tr0, ZERO
-
-
syscall_allowed:
/* Use LINK to deflect the exit point, default is syscall_ret */
pta syscall_ret, tr0
@@ -1409,8 +1353,8 @@ peek_real_address_q:
r2(out) : result quadword
This is provided as a cheapskate way of manipulating device
- registers for debugging (to avoid the need to onchip_remap the debug
- module, and to avoid the need to onchip_remap the watchpoint
+ registers for debugging (to avoid the need to ioremap the debug
+ module, and to avoid the need to ioremap the watchpoint
controller in a way that identity maps sufficient bits to avoid the
SH5-101 cut2 silicon defect).
@@ -1458,8 +1402,8 @@ poke_real_address_q:
r3 : quadword value to write.
This is provided as a cheapskate way of manipulating device
- registers for debugging (to avoid the need to onchip_remap the debug
- module, and to avoid the need to onchip_remap the watchpoint
+ registers for debugging (to avoid the need to ioremap the debug
+ module, and to avoid the need to ioremap the watchpoint
controller in a way that identity maps sufficient bits to avoid the
SH5-101 cut2 silicon defect).
@@ -2058,10 +2002,10 @@ asm_uaccess_end:
/*
- * --- .text.init Section
+ * --- .init.text Section
*/
- .section .text.init, "ax"
+ __INIT
/*
* void trap_init (void)
diff --git a/arch/sh/kernel/cpu/sh5/setup-sh5.c b/arch/sh/kernel/cpu/sh5/setup-sh5.c
new file mode 100644
index 000000000000..678d69bdebba
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh5/setup-sh5.c
@@ -0,0 +1,195 @@
+/*
+ * SH5-101/SH5-103 CPU Setup
+ *
+ * Copyright (C) 2009 Paul Mundt
+ *
+ * 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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/serial_sci.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/sh_timer.h>
+#include <asm/addrspace.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+ {
+ .mapbase = PHYS_PERIPHERAL_BLOCK + 0x01030000,
+ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+ .type = PORT_SCIF,
+ .irqs = { 39, 40, 42, 0 },
+ }, {
+ .flags = 0,
+ }
+};
+
+static struct platform_device sci_device = {
+ .name = "sh-sci",
+ .id = -1,
+ .dev = {
+ .platform_data = sci_platform_data,
+ },
+};
+
+static struct resource rtc_resources[] = {
+ [0] = {
+ .start = PHYS_PERIPHERAL_BLOCK + 0x01040000,
+ .end = PHYS_PERIPHERAL_BLOCK + 0x01040000 + 0x58 - 1,
+ .flags = IORESOURCE_IO,
+ },
+ [1] = {
+ /* Period IRQ */
+ .start = IRQ_PRI,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ /* Carry IRQ */
+ .start = IRQ_CUI,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ /* Alarm IRQ */
+ .start = IRQ_ATI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device rtc_device = {
+ .name = "sh-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+ .resource = rtc_resources,
+};
+
+#define TMU_BLOCK_OFF 0x01020000
+#define TMU_BASE PHYS_PERIPHERAL_BLOCK + TMU_BLOCK_OFF
+#define TMU0_BASE (TMU_BASE + 0x8 + (0xc * 0x0))
+#define TMU1_BASE (TMU_BASE + 0x8 + (0xc * 0x1))
+#define TMU2_BASE (TMU_BASE + 0x8 + (0xc * 0x2))
+
+static struct sh_timer_config tmu0_platform_data = {
+ .name = "TMU0",
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clk = "module_clk",
+ .clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+ [0] = {
+ .name = "TMU0",
+ .start = TMU0_BASE,
+ .end = TMU0_BASE + 0xc - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_TUNI0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu0_device = {
+ .name = "sh_tmu",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu0_platform_data,
+ },
+ .resource = tmu0_resources,
+ .num_resources = ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+ .name = "TMU1",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clk = "module_clk",
+ .clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+ [0] = {
+ .name = "TMU1",
+ .start = TMU1_BASE,
+ .end = TMU1_BASE + 0xc - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_TUNI1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu1_device = {
+ .name = "sh_tmu",
+ .id = 1,
+ .dev = {
+ .platform_data = &tmu1_platform_data,
+ },
+ .resource = tmu1_resources,
+ .num_resources = ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+ .name = "TMU2",
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+ .clk = "module_clk",
+};
+
+static struct resource tmu2_resources[] = {
+ [0] = {
+ .name = "TMU2",
+ .start = TMU2_BASE,
+ .end = TMU2_BASE + 0xc - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_TUNI2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu2_device = {
+ .name = "sh_tmu",
+ .id = 2,
+ .dev = {
+ .platform_data = &tmu2_platform_data,
+ },
+ .resource = tmu2_resources,
+ .num_resources = ARRAY_SIZE(tmu2_resources),
+};
+
+static struct platform_device *sh5_early_devices[] __initdata = {
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+};
+
+static struct platform_device *sh5_devices[] __initdata = {
+ &sci_device,
+ &rtc_device,
+};
+
+static int __init sh5_devices_setup(void)
+{
+ int ret;
+
+ ret = platform_add_devices(sh5_early_devices,
+ ARRAY_SIZE(sh5_early_devices));
+ if (unlikely(ret != 0))
+ return ret;
+
+ return platform_add_devices(sh5_devices,
+ ARRAY_SIZE(sh5_devices));
+}
+__initcall(sh5_devices_setup);
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh5_early_devices,
+ ARRAY_SIZE(sh5_early_devices));
+}
diff --git a/arch/sh/kernel/head_32.S b/arch/sh/kernel/head_32.S
index 788605ff7088..a78be74b8d3e 100644
--- a/arch/sh/kernel/head_32.S
+++ b/arch/sh/kernel/head_32.S
@@ -10,6 +10,7 @@
*
* Head.S contains the SH exception handlers and startup code.
*/
+#include <linux/init.h>
#include <linux/linkage.h>
#include <asm/thread_info.h>
@@ -40,7 +41,7 @@ ENTRY(empty_zero_page)
1:
.skip PAGE_SIZE - empty_zero_page - 1b
- .section .text.head, "ax"
+ __HEAD
/*
* Condition at the entry of _stext:
diff --git a/arch/sh/kernel/head_64.S b/arch/sh/kernel/head_64.S
index 7ccfb995a398..3ea765844c74 100644
--- a/arch/sh/kernel/head_64.S
+++ b/arch/sh/kernel/head_64.S
@@ -8,6 +8,9 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
+
+#include <linux/init.h>
+
#include <asm/page.h>
#include <asm/cache.h>
#include <asm/tlb.h>
@@ -110,7 +113,7 @@ empty_bad_pte_table:
fpu_in_use: .quad 0
- .section .text.head, "ax"
+ __HEAD
.balign L1_CACHE_BYTES
/*
* Condition at the entry of __stext:
diff --git a/arch/sh/kernel/io.c b/arch/sh/kernel/io.c
index 29cf4588fc05..4f85fffaa557 100644
--- a/arch/sh/kernel/io.c
+++ b/arch/sh/kernel/io.c
@@ -12,6 +12,7 @@
* for more details.
*/
#include <linux/module.h>
+#include <linux/pci.h>
#include <asm/machvec.h>
#include <asm/io.h>
diff --git a/arch/sh/kernel/io_trapped.c b/arch/sh/kernel/io_trapped.c
index c22853b059ef..77dfecb64373 100644
--- a/arch/sh/kernel/io_trapped.c
+++ b/arch/sh/kernel/io_trapped.c
@@ -267,7 +267,7 @@ static struct mem_access trapped_io_access = {
int handle_trapped_io(struct pt_regs *regs, unsigned long address)
{
mm_segment_t oldfs;
- opcode_t instruction;
+ insn_size_t instruction;
int tmp;
if (!lookup_tiop(address))
diff --git a/arch/sh/kernel/kgdb.c b/arch/sh/kernel/kgdb.c
index 7c747e7d71b8..305aad742aec 100644
--- a/arch/sh/kernel/kgdb.c
+++ b/arch/sh/kernel/kgdb.c
@@ -47,7 +47,7 @@ char in_nmi = 0; /* Set during NMI to prevent re-entry */
/* Calculate the new address for after a step */
static short *get_step_address(struct pt_regs *linux_regs)
{
- opcode_t op = __raw_readw(linux_regs->pc);
+ insn_size_t op = __raw_readw(linux_regs->pc);
long addr;
/* BT */
@@ -134,7 +134,7 @@ static short *get_step_address(struct pt_regs *linux_regs)
*/
static unsigned long stepped_address;
-static opcode_t stepped_opcode;
+static insn_size_t stepped_opcode;
static void do_single_step(struct pt_regs *linux_regs)
{
diff --git a/arch/sh/kernel/timers/timer-broadcast.c b/arch/sh/kernel/localtimer.c
index 96e8eaea1e62..96e8eaea1e62 100644
--- a/arch/sh/kernel/timers/timer-broadcast.c
+++ b/arch/sh/kernel/localtimer.c
diff --git a/arch/sh/kernel/module.c b/arch/sh/kernel/module.c
index c43081039dd5..c19b0f7d2cc1 100644
--- a/arch/sh/kernel/module.c
+++ b/arch/sh/kernel/module.c
@@ -90,7 +90,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
* SHmedia, the LSB of the symbol needs to be asserted
* for the CPU to be in SHmedia mode when it starts executing
* the branch target. */
- relocation |= (sym->st_other & 4);
+ relocation |= !!(sym->st_other & 4);
#endif
switch (ELF32_R_TYPE(rel[i].r_info)) {
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c
index 6d94725d22f2..9289ede29c7b 100644
--- a/arch/sh/kernel/process_32.c
+++ b/arch/sh/kernel/process_32.c
@@ -251,7 +251,8 @@ static void ubc_set_tracing(int asid, unsigned long pc)
if (current_cpu_data.type == CPU_SH7729 ||
current_cpu_data.type == CPU_SH7710 ||
- current_cpu_data.type == CPU_SH7712) {
+ current_cpu_data.type == CPU_SH7712 ||
+ current_cpu_data.type == CPU_SH7203){
ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA);
ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR);
} else {
@@ -407,6 +408,7 @@ asmlinkage void break_point_trap(void)
#else
ctrl_outw(0, UBC_BBRA);
ctrl_outw(0, UBC_BBRB);
+ ctrl_outl(0, UBC_BRCR);
#endif
current->thread.ubc_pc = 0;
ubc_usercnt -= 1;
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c
index f7b22dd83b0c..3392e835a374 100644
--- a/arch/sh/kernel/ptrace_32.c
+++ b/arch/sh/kernel/ptrace_32.c
@@ -334,6 +334,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
[(addr - (long)&dummy->fpu) >> 2];
} else if (addr == (long) &dummy->u_fpvalid)
tmp = !!tsk_used_math(child);
+ else if (addr == PT_TEXT_ADDR)
+ tmp = child->mm->start_code;
+ else if (addr == PT_DATA_ADDR)
+ tmp = child->mm->start_data;
+ else if (addr == PT_TEXT_END_ADDR)
+ tmp = child->mm->end_code;
+ else if (addr == PT_TEXT_LEN)
+ tmp = child->mm->end_code - child->mm->start_code;
else
tmp = 0;
ret = put_user(tmp, datap);
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 04a6004fccc4..00086b234278 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -29,6 +29,7 @@
#include <linux/mmzone.h>
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/platform_device.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/page.h>
@@ -155,7 +156,7 @@ static void __init reserve_crashkernel(void)
&crash_size, &crash_base);
if (ret == 0 && crash_size) {
if (crash_base <= 0) {
- vp = alloc_bootmem_nopanic(crash_size);
+ vp = alloc_bootmem_nopanic(crash_size);
if (!vp) {
printk(KERN_INFO "crashkernel allocation "
"failed\n");
@@ -184,7 +185,6 @@ static inline void __init reserve_crashkernel(void)
{}
#endif
-#ifndef CONFIG_GENERIC_CALIBRATE_DELAY
void __cpuinit calibrate_delay(void)
{
struct clk *clk = clk_get(NULL, "cpu_clk");
@@ -200,7 +200,6 @@ void __cpuinit calibrate_delay(void)
(loops_per_jiffy/(5000/HZ)) % 100,
loops_per_jiffy);
}
-#endif
void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
unsigned long end_pfn)
@@ -328,6 +327,10 @@ static int __init parse_elfcorehdr(char *arg)
early_param("elfcorehdr", parse_elfcorehdr);
#endif
+void __init __attribute__ ((weak)) plat_early_device_setup(void)
+{
+}
+
void __init setup_arch(char **cmdline_p)
{
enable_mmu();
@@ -381,6 +384,8 @@ void __init setup_arch(char **cmdline_p)
parse_early_param();
+ plat_early_device_setup();
+
sh_mv_setup();
/*
@@ -435,7 +440,8 @@ static const char *cpu_name[] = {
[CPU_SH7722] = "SH7722", [CPU_SHX3] = "SH-X3",
[CPU_SH5_101] = "SH5-101", [CPU_SH5_103] = "SH5-103",
[CPU_MXG] = "MX-G", [CPU_SH7723] = "SH7723",
- [CPU_SH7366] = "SH7366", [CPU_SH_NONE] = "Unknown"
+ [CPU_SH7366] = "SH7366", [CPU_SH7724] = "SH7724",
+ [CPU_SH_NONE] = "Unknown"
};
const char *get_cpu_subtype(struct sh_cpuinfo *c)
diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c
index 528de2955c81..2d868c60aa6e 100644
--- a/arch/sh/kernel/sh_ksyms_32.c
+++ b/arch/sh/kernel/sh_ksyms_32.c
@@ -19,13 +19,12 @@
#include <asm/ftrace.h>
extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
-extern struct hw_interrupt_type no_irq_type;
/* platform dependent support */
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(irq_desc);
-EXPORT_SYMBOL(no_irq_type);
+EXPORT_SYMBOL(no_irq_chip);
EXPORT_SYMBOL(strlen);
diff --git a/arch/sh/kernel/sh_ksyms_64.c b/arch/sh/kernel/sh_ksyms_64.c
index 0d74d6b8774e..8f54ef0cfbca 100644
--- a/arch/sh/kernel/sh_ksyms_64.c
+++ b/arch/sh/kernel/sh_ksyms_64.c
@@ -76,5 +76,7 @@ EXPORT_SYMBOL(strcpy);
#define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name)
DECLARE_EXPORT(__sdivsi3);
+DECLARE_EXPORT(__sdivsi3_1);
+DECLARE_EXPORT(__sdivsi3_2);
DECLARE_EXPORT(__udivsi3);
DECLARE_EXPORT(__div_table);
diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c
index 58dfc02c7af1..e3a7e36639ef 100644
--- a/arch/sh/kernel/sys_sh.c
+++ b/arch/sh/kernel/sys_sh.c
@@ -63,6 +63,15 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff)
{
+ /*
+ * The shift for mmap2 is constant, regardless of PAGE_SIZE
+ * setting.
+ */
+ if (pgoff & ((1 << (PAGE_SHIFT - 12)) - 1))
+ return -EINVAL;
+
+ pgoff >>= PAGE_SHIFT - 12;
+
return do_mmap2(addr, len, prot, flags, fd, pgoff);
}
diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S
index e67c1733e1b9..05202edd8e21 100644
--- a/arch/sh/kernel/syscalls_32.S
+++ b/arch/sh/kernel/syscalls_32.S
@@ -349,3 +349,5 @@ ENTRY(sys_call_table)
.long sys_dup3 /* 330 */
.long sys_pipe2
.long sys_inotify_init1
+ .long sys_preadv
+ .long sys_writev
diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S
index 557cb91f5caf..a083609f9284 100644
--- a/arch/sh/kernel/syscalls_64.S
+++ b/arch/sh/kernel/syscalls_64.S
@@ -387,3 +387,5 @@ sys_call_table:
.long sys_dup3
.long sys_pipe2
.long sys_inotify_init1 /* 360 */
+ .long sys_preadv
+ .long sys_pwritev
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
new file mode 100644
index 000000000000..a77838f539f8
--- /dev/null
+++ b/arch/sh/kernel/time.c
@@ -0,0 +1,150 @@
+/*
+ * arch/sh/kernel/time.c
+ *
+ * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ * Copyright (C) 2002 - 2009 Paul Mundt
+ * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/profile.h>
+#include <linux/timex.h>
+#include <linux/sched.h>
+#include <linux/clockchips.h>
+#include <linux/platform_device.h>
+#include <linux/smp.h>
+#include <linux/rtc.h>
+#include <asm/clock.h>
+#include <asm/rtc.h>
+#include <asm/timer.h>
+
+struct sys_timer *sys_timer;
+
+/* Dummy RTC ops */
+static void null_rtc_get_time(struct timespec *tv)
+{
+ tv->tv_sec = mktime(2000, 1, 1, 0, 0, 0);
+ tv->tv_nsec = 0;
+}
+
+static int null_rtc_set_time(const time_t secs)
+{
+ return 0;
+}
+
+void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time;
+int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time;
+
+#ifdef CONFIG_GENERIC_CMOS_UPDATE
+unsigned long read_persistent_clock(void)
+{
+ struct timespec tv;
+ rtc_sh_get_time(&tv);
+ return tv.tv_sec;
+}
+
+int update_persistent_clock(struct timespec now)
+{
+ return rtc_sh_set_time(now.tv_sec);
+}
+#endif
+
+unsigned int get_rtc_time(struct rtc_time *tm)
+{
+ if (rtc_sh_get_time != null_rtc_get_time) {
+ struct timespec tv;
+
+ rtc_sh_get_time(&tv);
+ rtc_time_to_tm(tv.tv_sec, tm);
+ }
+
+ return RTC_24H;
+}
+EXPORT_SYMBOL(get_rtc_time);
+
+int set_rtc_time(struct rtc_time *tm)
+{
+ unsigned long secs;
+
+ rtc_tm_to_time(tm, &secs);
+ return rtc_sh_set_time(secs);
+}
+EXPORT_SYMBOL(set_rtc_time);
+
+static int __init rtc_generic_init(void)
+{
+ struct platform_device *pdev;
+
+ if (rtc_sh_get_time == null_rtc_get_time)
+ return -ENODEV;
+
+ pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+
+ return 0;
+}
+module_init(rtc_generic_init);
+
+void (*board_time_init)(void);
+
+struct clocksource clocksource_sh = {
+ .name = "SuperH",
+};
+
+unsigned long long sched_clock(void)
+{
+ unsigned long long cycles;
+
+ /* jiffies based sched_clock if no clocksource is installed */
+ if (!clocksource_sh.rating)
+ return (jiffies_64 - INITIAL_JIFFIES) * (NSEC_PER_SEC / HZ);
+
+ cycles = clocksource_sh.read(&clocksource_sh);
+ return cyc2ns(&clocksource_sh, cycles);
+}
+
+static void __init sh_late_time_init(void)
+{
+ /*
+ * Make sure all compiled-in early timers register themselves.
+ * Run probe() for one "earlytimer" device.
+ */
+ early_platform_driver_register_all("earlytimer");
+ if (early_platform_driver_probe("earlytimer", 1, 0))
+ return;
+
+ /*
+ * Find the timer to use as the system timer, it will be
+ * initialized for us.
+ */
+ sys_timer = get_sys_timer();
+ if (unlikely(!sys_timer))
+ panic("System timer missing.\n");
+
+ printk(KERN_INFO "Using %s for system timer\n", sys_timer->name);
+}
+
+void __init time_init(void)
+{
+ if (board_time_init)
+ board_time_init();
+
+ clk_init();
+
+ rtc_sh_get_time(&xtime);
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+ local_timer_setup(smp_processor_id());
+#endif
+
+ late_time_init = sh_late_time_init;
+}
diff --git a/arch/sh/kernel/time_32.c b/arch/sh/kernel/time_32.c
deleted file mode 100644
index c34e1e0f9b02..000000000000
--- a/arch/sh/kernel/time_32.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * arch/sh/kernel/time_32.c
- *
- * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
- * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
- * Copyright (C) 2002 - 2008 Paul Mundt
- * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
- *
- * Some code taken from i386 version.
- * Copyright (C) 1991, 1992, 1995 Linus Torvalds
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/profile.h>
-#include <linux/timex.h>
-#include <linux/sched.h>
-#include <linux/clockchips.h>
-#include <linux/mc146818rtc.h> /* for rtc_lock */
-#include <linux/smp.h>
-#include <asm/clock.h>
-#include <asm/rtc.h>
-#include <asm/timer.h>
-#include <asm/kgdb.h>
-
-struct sys_timer *sys_timer;
-
-/* Move this somewhere more sensible.. */
-DEFINE_SPINLOCK(rtc_lock);
-EXPORT_SYMBOL(rtc_lock);
-
-/* Dummy RTC ops */
-static void null_rtc_get_time(struct timespec *tv)
-{
- tv->tv_sec = mktime(2000, 1, 1, 0, 0, 0);
- tv->tv_nsec = 0;
-}
-
-static int null_rtc_set_time(const time_t secs)
-{
- return 0;
-}
-
-void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time;
-int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time;
-
-#ifndef CONFIG_GENERIC_TIME
-void do_gettimeofday(struct timeval *tv)
-{
- unsigned long flags;
- unsigned long seq;
- unsigned long usec, sec;
-
- do {
- /*
- * Turn off IRQs when grabbing xtime_lock, so that
- * the sys_timer get_offset code doesn't have to handle it.
- */
- seq = read_seqbegin_irqsave(&xtime_lock, flags);
- usec = get_timer_offset();
- sec = xtime.tv_sec;
- usec += xtime.tv_nsec / NSEC_PER_USEC;
- } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
-
- while (usec >= 1000000) {
- usec -= 1000000;
- sec++;
- }
-
- tv->tv_sec = sec;
- tv->tv_usec = usec;
-}
-EXPORT_SYMBOL(do_gettimeofday);
-
-int do_settimeofday(struct timespec *tv)
-{
- time_t wtm_sec, sec = tv->tv_sec;
- long wtm_nsec, nsec = tv->tv_nsec;
-
- if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
- return -EINVAL;
-
- write_seqlock_irq(&xtime_lock);
- /*
- * This is revolting. We need to set "xtime" correctly. However, the
- * value in this location is the value at the most recent update of
- * wall time. Discover what correction gettimeofday() would have
- * made, and then undo it!
- */
- nsec -= get_timer_offset() * NSEC_PER_USEC;
-
- wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
- wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
- set_normalized_timespec(&xtime, sec, nsec);
- set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
- ntp_clear();
- write_sequnlock_irq(&xtime_lock);
- clock_was_set();
-
- return 0;
-}
-EXPORT_SYMBOL(do_settimeofday);
-#endif /* !CONFIG_GENERIC_TIME */
-
-/* last time the RTC clock got updated */
-static long last_rtc_update;
-
-/*
- * handle_timer_tick() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
- */
-void handle_timer_tick(void)
-{
- if (current->pid)
- profile_tick(CPU_PROFILING);
-
- /*
- * 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
- * the irq version of write_lock because as just said we have irq
- * locally disabled. -arca
- */
- write_seqlock(&xtime_lock);
- do_timer(1);
-
- /*
- * If we have an externally synchronized Linux clock, then update
- * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
- * called as close as possible to 500 ms before the new second starts.
- */
- if (ntp_synced() &&
- xtime.tv_sec > last_rtc_update + 660 &&
- (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
- (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
- if (rtc_sh_set_time(xtime.tv_sec) == 0)
- last_rtc_update = xtime.tv_sec;
- else
- /* do it again in 60s */
- last_rtc_update = xtime.tv_sec - 600;
- }
- write_sequnlock(&xtime_lock);
-
-#ifndef CONFIG_SMP
- update_process_times(user_mode(get_irq_regs()));
-#endif
-}
-
-#ifdef CONFIG_PM
-int timer_suspend(struct sys_device *dev, pm_message_t state)
-{
- struct sys_timer *sys_timer = container_of(dev, struct sys_timer, dev);
-
- sys_timer->ops->stop();
-
- return 0;
-}
-
-int timer_resume(struct sys_device *dev)
-{
- struct sys_timer *sys_timer = container_of(dev, struct sys_timer, dev);
-
- sys_timer->ops->start();
-
- return 0;
-}
-#else
-#define timer_suspend NULL
-#define timer_resume NULL
-#endif
-
-static struct sysdev_class timer_sysclass = {
- .name = "timer",
- .suspend = timer_suspend,
- .resume = timer_resume,
-};
-
-static int __init timer_init_sysfs(void)
-{
- int ret;
-
- if (!sys_timer)
- return 0;
-
- ret = sysdev_class_register(&timer_sysclass);
- if (ret != 0)
- return ret;
-
- sys_timer->dev.cls = &timer_sysclass;
- return sysdev_register(&sys_timer->dev);
-}
-device_initcall(timer_init_sysfs);
-
-void (*board_time_init)(void);
-
-struct clocksource clocksource_sh = {
- .name = "SuperH",
-};
-
-#ifdef CONFIG_GENERIC_TIME
-unsigned long long sched_clock(void)
-{
- unsigned long long cycles;
-
- /* jiffies based sched_clock if no clocksource is installed */
- if (!clocksource_sh.rating)
- return (unsigned long long)jiffies * (NSEC_PER_SEC / HZ);
-
- cycles = clocksource_sh.read();
- return cyc2ns(&clocksource_sh, cycles);
-}
-#endif
-
-void __init time_init(void)
-{
- if (board_time_init)
- board_time_init();
-
- clk_init();
-
- rtc_sh_get_time(&xtime);
- set_normalized_timespec(&wall_to_monotonic,
- -xtime.tv_sec, -xtime.tv_nsec);
-
-#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
- local_timer_setup(smp_processor_id());
-#endif
-
- /*
- * Find the timer to use as the system timer, it will be
- * initialized for us.
- */
- sys_timer = get_sys_timer();
- if (unlikely(!sys_timer))
- panic("System timer missing.\n");
-
- printk(KERN_INFO "Using %s for system timer\n", sys_timer->name);
-}
diff --git a/arch/sh/kernel/time_64.c b/arch/sh/kernel/time_64.c
deleted file mode 100644
index 988c77c37231..000000000000
--- a/arch/sh/kernel/time_64.c
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * arch/sh/kernel/time_64.c
- *
- * Copyright (C) 2000, 2001 Paolo Alberelli
- * Copyright (C) 2003 - 2007 Paul Mundt
- * Copyright (C) 2003 Richard Curnow
- *
- * Original TMU/RTC code taken from sh version.
- * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
- * Some code taken from i386 version.
- * Copyright (C) 1991, 1992, 1995 Linus Torvalds
- *
- * 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/errno.h>
-#include <linux/rwsem.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/profile.h>
-#include <linux/smp.h>
-#include <linux/module.h>
-#include <linux/bcd.h>
-#include <linux/timex.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <cpu/registers.h> /* required by inline __asm__ stmt. */
-#include <cpu/irq.h>
-#include <asm/addrspace.h>
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-#include <asm/delay.h>
-#include <asm/clock.h>
-
-#define TMU_TOCR_INIT 0x00
-#define TMU0_TCR_INIT 0x0020
-#define TMU_TSTR_INIT 1
-#define TMU_TSTR_OFF 0
-
-/* Real Time Clock */
-#define RTC_BLOCK_OFF 0x01040000
-#define RTC_BASE PHYS_PERIPHERAL_BLOCK + RTC_BLOCK_OFF
-#define RTC_RCR1_CIE 0x10 /* Carry Interrupt Enable */
-#define RTC_RCR1 (rtc_base + 0x38)
-
-/* Time Management Unit */
-#define TMU_BLOCK_OFF 0x01020000
-#define TMU_BASE PHYS_PERIPHERAL_BLOCK + TMU_BLOCK_OFF
-#define TMU0_BASE tmu_base + 0x8 + (0xc * 0x0)
-#define TMU1_BASE tmu_base + 0x8 + (0xc * 0x1)
-#define TMU2_BASE tmu_base + 0x8 + (0xc * 0x2)
-
-#define TMU_TOCR tmu_base+0x0 /* Byte access */
-#define TMU_TSTR tmu_base+0x4 /* Byte access */
-
-#define TMU0_TCOR TMU0_BASE+0x0 /* Long access */
-#define TMU0_TCNT TMU0_BASE+0x4 /* Long access */
-#define TMU0_TCR TMU0_BASE+0x8 /* Word access */
-
-#define TICK_SIZE (tick_nsec / 1000)
-
-static unsigned long tmu_base, rtc_base;
-unsigned long cprc_base;
-
-/* Variables to allow interpolation of time of day to resolution better than a
- * jiffy. */
-
-/* This is effectively protected by xtime_lock */
-static unsigned long ctc_last_interrupt;
-static unsigned long long usecs_per_jiffy = 1000000/HZ; /* Approximation */
-
-#define CTC_JIFFY_SCALE_SHIFT 40
-
-/* 2**CTC_JIFFY_SCALE_SHIFT / ctc_ticks_per_jiffy */
-static unsigned long long scaled_recip_ctc_ticks_per_jiffy;
-
-/* Estimate number of microseconds that have elapsed since the last timer tick,
- by scaling the delta that has occurred in the CTC register.
-
- WARNING WARNING WARNING : This algorithm relies on the CTC decrementing at
- the CPU clock rate. If the CPU sleeps, the CTC stops counting. Bear this
- in mind if enabling SLEEP_WORKS in process.c. In that case, this algorithm
- probably needs to use TMU.TCNT0 instead. This will work even if the CPU is
- sleeping, though will be coarser.
-
- FIXME : What if usecs_per_tick is moving around too much, e.g. if an adjtime
- is running or if the freq or tick arguments of adjtimex are modified after
- we have calibrated the scaling factor? This will result in either a jump at
- the end of a tick period, or a wrap backwards at the start of the next one,
- if the application is reading the time of day often enough. I think we
- ought to do better than this. For this reason, usecs_per_jiffy is left
- separated out in the calculation below. This allows some future hook into
- the adjtime-related stuff in kernel/timer.c to remove this hazard.
-
-*/
-
-static unsigned long usecs_since_tick(void)
-{
- unsigned long long current_ctc;
- long ctc_ticks_since_interrupt;
- unsigned long long ull_ctc_ticks_since_interrupt;
- unsigned long result;
-
- unsigned long long mul1_out;
- unsigned long long mul1_out_high;
- unsigned long long mul2_out_low, mul2_out_high;
-
- /* Read CTC register */
- asm ("getcon cr62, %0" : "=r" (current_ctc));
- /* Note, the CTC counts down on each CPU clock, not up.
- Note(2), use long type to get correct wraparound arithmetic when
- the counter crosses zero. */
- ctc_ticks_since_interrupt = (long) ctc_last_interrupt - (long) current_ctc;
- ull_ctc_ticks_since_interrupt = (unsigned long long) ctc_ticks_since_interrupt;
-
- /* Inline assembly to do 32x32x32->64 multiplier */
- asm volatile ("mulu.l %1, %2, %0" :
- "=r" (mul1_out) :
- "r" (ull_ctc_ticks_since_interrupt), "r" (usecs_per_jiffy));
-
- mul1_out_high = mul1_out >> 32;
-
- asm volatile ("mulu.l %1, %2, %0" :
- "=r" (mul2_out_low) :
- "r" (mul1_out), "r" (scaled_recip_ctc_ticks_per_jiffy));
-
-#if 1
- asm volatile ("mulu.l %1, %2, %0" :
- "=r" (mul2_out_high) :
- "r" (mul1_out_high), "r" (scaled_recip_ctc_ticks_per_jiffy));
-#endif
-
- result = (unsigned long) (((mul2_out_high << 32) + mul2_out_low) >> CTC_JIFFY_SCALE_SHIFT);
-
- return result;
-}
-
-void do_gettimeofday(struct timeval *tv)
-{
- unsigned long flags;
- unsigned long seq;
- unsigned long usec, sec;
-
- do {
- seq = read_seqbegin_irqsave(&xtime_lock, flags);
- usec = usecs_since_tick();
- sec = xtime.tv_sec;
- usec += xtime.tv_nsec / 1000;
- } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
-
- while (usec >= 1000000) {
- usec -= 1000000;
- sec++;
- }
-
- tv->tv_sec = sec;
- tv->tv_usec = usec;
-}
-EXPORT_SYMBOL(do_gettimeofday);
-
-int do_settimeofday(struct timespec *tv)
-{
- time_t wtm_sec, sec = tv->tv_sec;
- long wtm_nsec, nsec = tv->tv_nsec;
-
- if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
- return -EINVAL;
-
- write_seqlock_irq(&xtime_lock);
- /*
- * This is revolting. We need to set "xtime" correctly. However, the
- * value in this location is the value at the most recent update of
- * wall time. Discover what correction gettimeofday() would have
- * made, and then undo it!
- */
- nsec -= 1000 * usecs_since_tick();
-
- wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
- wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
- set_normalized_timespec(&xtime, sec, nsec);
- set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
- ntp_clear();
- write_sequnlock_irq(&xtime_lock);
- clock_was_set();
-
- return 0;
-}
-EXPORT_SYMBOL(do_settimeofday);
-
-/* Dummy RTC ops */
-static void null_rtc_get_time(struct timespec *tv)
-{
- tv->tv_sec = mktime(2000, 1, 1, 0, 0, 0);
- tv->tv_nsec = 0;
-}
-
-static int null_rtc_set_time(const time_t secs)
-{
- return 0;
-}
-
-void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time;
-int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time;
-
-/* last time the RTC clock got updated */
-static long last_rtc_update;
-
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
- */
-static inline void do_timer_interrupt(void)
-{
- unsigned long long current_ctc;
-
- if (current->pid)
- profile_tick(CPU_PROFILING);
-
- /*
- * 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
- * the irq version of write_lock because as just said we have irq
- * locally disabled. -arca
- */
- write_seqlock(&xtime_lock);
- asm ("getcon cr62, %0" : "=r" (current_ctc));
- ctc_last_interrupt = (unsigned long) current_ctc;
-
- do_timer(1);
-
- /*
- * If we have an externally synchronized Linux clock, then update
- * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
- * called as close as possible to 500 ms before the new second starts.
- */
- if (ntp_synced() &&
- xtime.tv_sec > last_rtc_update + 660 &&
- (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
- (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
- if (rtc_sh_set_time(xtime.tv_sec) == 0)
- last_rtc_update = xtime.tv_sec;
- else
- /* do it again in 60 s */
- last_rtc_update = xtime.tv_sec - 600;
- }
- write_sequnlock(&xtime_lock);
-
-#ifndef CONFIG_SMP
- update_process_times(user_mode(get_irq_regs()));
-#endif
-}
-
-/*
- * This is the same as the above, except we _also_ save the current
- * Time Stamp Counter value at the time of the timer interrupt, so that
- * we later on can estimate the time of day more exactly.
- */
-static irqreturn_t timer_interrupt(int irq, void *dev_id)
-{
- unsigned long timer_status;
-
- /* Clear UNF bit */
- timer_status = ctrl_inw(TMU0_TCR);
- timer_status &= ~0x100;
- ctrl_outw(timer_status, TMU0_TCR);
-
- do_timer_interrupt();
-
- return IRQ_HANDLED;
-}
-
-static struct irqaction irq0 = {
- .handler = timer_interrupt,
- .flags = IRQF_DISABLED,
- .name = "timer",
-};
-
-void __init time_init(void)
-{
- unsigned long interval;
- struct clk *clk;
-
- tmu_base = onchip_remap(TMU_BASE, 1024, "TMU");
- if (!tmu_base) {
- panic("Unable to remap TMU\n");
- }
-
- rtc_base = onchip_remap(RTC_BASE, 1024, "RTC");
- if (!rtc_base) {
- panic("Unable to remap RTC\n");
- }
-
- clk = clk_get(NULL, "cpu_clk");
- scaled_recip_ctc_ticks_per_jiffy = ((1ULL << CTC_JIFFY_SCALE_SHIFT) /
- (unsigned long long)(clk_get_rate(clk) / HZ));
-
- rtc_sh_get_time(&xtime);
-
- setup_irq(TIMER_IRQ, &irq0);
-
- clk = clk_get(NULL, "module_clk");
- interval = (clk_get_rate(clk)/(HZ*4));
-
- printk("Interval = %ld\n", interval);
-
- /* Start TMU0 */
- ctrl_outb(TMU_TSTR_OFF, TMU_TSTR);
- ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
- ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);
- ctrl_outl(interval, TMU0_TCOR);
- ctrl_outl(interval, TMU0_TCNT);
- ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
-}
-
-static struct resource rtc_resources[] = {
- [0] = {
- /* RTC base, filled in by rtc_init */
- .flags = IORESOURCE_IO,
- },
- [1] = {
- /* Period IRQ */
- .start = IRQ_PRI,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- /* Carry IRQ */
- .start = IRQ_CUI,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- /* Alarm IRQ */
- .start = IRQ_ATI,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device rtc_device = {
- .name = "sh-rtc",
- .id = -1,
- .num_resources = ARRAY_SIZE(rtc_resources),
- .resource = rtc_resources,
-};
-
-static int __init rtc_init(void)
-{
- rtc_resources[0].start = rtc_base;
- rtc_resources[0].end = rtc_resources[0].start + 0x58 - 1;
-
- return platform_device_register(&rtc_device);
-}
-device_initcall(rtc_init);
diff --git a/arch/sh/kernel/timers/Makefile b/arch/sh/kernel/timers/Makefile
index 0b7f8577193f..8bceba59e76f 100644
--- a/arch/sh/kernel/timers/Makefile
+++ b/arch/sh/kernel/timers/Makefile
@@ -5,7 +5,3 @@
obj-y := timer.o
obj-$(CONFIG_SH_TMU) += timer-tmu.o
-obj-$(CONFIG_SH_MTU2) += timer-mtu2.o
-obj-$(CONFIG_SH_CMT) += timer-cmt.o
-
-obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += timer-broadcast.o
diff --git a/arch/sh/kernel/timers/timer-cmt.c b/arch/sh/kernel/timers/timer-cmt.c
deleted file mode 100644
index 9aa348658ae3..000000000000
--- a/arch/sh/kernel/timers/timer-cmt.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * arch/sh/kernel/timers/timer-cmt.c - CMT Timer Support
- *
- * Copyright (C) 2005 Yoshinori Sato
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/seqlock.h>
-#include <asm/timer.h>
-#include <asm/rtc.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/clock.h>
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7619)
-#define CMT_CMSTR 0xf84a0070
-#define CMT_CMCSR_0 0xf84a0072
-#define CMT_CMCNT_0 0xf84a0074
-#define CMT_CMCOR_0 0xf84a0076
-#define CMT_CMCSR_1 0xf84a0078
-#define CMT_CMCNT_1 0xf84a007a
-#define CMT_CMCOR_1 0xf84a007c
-
-#define STBCR3 0xf80a0000
-#define cmt_clock_enable() do { ctrl_outb(ctrl_inb(STBCR3) & ~0x10, STBCR3); } while(0)
-#define CMT_CMCSR_INIT 0x0040
-#define CMT_CMCSR_CALIB 0x0000
-#elif defined(CONFIG_CPU_SUBTYPE_SH7203) || \
- defined(CONFIG_CPU_SUBTYPE_SH7206) || \
- defined(CONFIG_CPU_SUBTYPE_SH7263)
-#define CMT_CMSTR 0xfffec000
-#define CMT_CMCSR_0 0xfffec002
-#define CMT_CMCNT_0 0xfffec004
-#define CMT_CMCOR_0 0xfffec006
-
-#define STBCR4 0xfffe040c
-#define cmt_clock_enable() do { ctrl_outb(ctrl_inb(STBCR4) & ~0x04, STBCR4); } while(0)
-#define CMT_CMCSR_INIT 0x0040
-#define CMT_CMCSR_CALIB 0x0000
-#else
-#error "Unknown CPU SUBTYPE"
-#endif
-
-static unsigned long cmt_timer_get_offset(void)
-{
- int count;
- static unsigned short count_p = 0xffff; /* for the first call after boot */
- static unsigned long jiffies_p = 0;
-
- /*
- * cache volatile jiffies temporarily; we have IRQs turned off.
- */
- unsigned long jiffies_t;
-
- /* timer count may underflow right here */
- count = ctrl_inw(CMT_CMCOR_0);
- count -= ctrl_inw(CMT_CMCNT_0);
-
- jiffies_t = jiffies;
-
- /*
- * avoiding timer inconsistencies (they are rare, but they happen)...
- * there is one kind of problem that must be avoided here:
- * 1. the timer counter underflows
- */
-
- if (jiffies_t == jiffies_p) {
- if (count > count_p) {
- /* the nutcase */
- if (ctrl_inw(CMT_CMCSR_0) & 0x80) { /* Check CMF bit */
- count -= LATCH;
- } else {
- printk("%s (): hardware timer problem?\n",
- __func__);
- }
- }
- } else
- jiffies_p = jiffies_t;
-
- count_p = count;
-
- count = ((LATCH-1) - count) * TICK_SIZE;
- count = (count + LATCH/2) / LATCH;
-
- return count;
-}
-
-static irqreturn_t cmt_timer_interrupt(int irq, void *dev_id)
-{
- unsigned long timer_status;
-
- /* Clear CMF bit */
- timer_status = ctrl_inw(CMT_CMCSR_0);
- timer_status &= ~0x80;
- ctrl_outw(timer_status, CMT_CMCSR_0);
-
- handle_timer_tick();
-
- return IRQ_HANDLED;
-}
-
-static struct irqaction cmt_irq = {
- .name = "timer",
- .handler = cmt_timer_interrupt,
- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-};
-
-static void cmt_clk_init(struct clk *clk)
-{
- u8 divisor = CMT_CMCSR_INIT & 0x3;
- ctrl_inw(CMT_CMCSR_0);
- ctrl_outw(CMT_CMCSR_INIT, CMT_CMCSR_0);
- clk->parent = clk_get(NULL, "module_clk");
- clk->rate = clk->parent->rate / (8 << (divisor << 1));
-}
-
-static void cmt_clk_recalc(struct clk *clk)
-{
- u8 divisor = ctrl_inw(CMT_CMCSR_0) & 0x3;
- clk->rate = clk->parent->rate / (8 << (divisor << 1));
-}
-
-static struct clk_ops cmt_clk_ops = {
- .init = cmt_clk_init,
- .recalc = cmt_clk_recalc,
-};
-
-static struct clk cmt0_clk = {
- .name = "cmt0_clk",
- .ops = &cmt_clk_ops,
-};
-
-static int cmt_timer_start(void)
-{
- ctrl_outw(ctrl_inw(CMT_CMSTR) | 0x01, CMT_CMSTR);
- return 0;
-}
-
-static int cmt_timer_stop(void)
-{
- ctrl_outw(ctrl_inw(CMT_CMSTR) & ~0x01, CMT_CMSTR);
- return 0;
-}
-
-static int cmt_timer_init(void)
-{
- unsigned long interval;
-
- cmt_clock_enable();
-
- setup_irq(CONFIG_SH_TIMER_IRQ, &cmt_irq);
-
- cmt0_clk.parent = clk_get(NULL, "module_clk");
-
- cmt_timer_stop();
-
- interval = cmt0_clk.parent->rate / 8 / HZ;
- printk(KERN_INFO "Interval = %ld\n", interval);
-
- ctrl_outw(interval, CMT_CMCOR_0);
-
- clk_register(&cmt0_clk);
- clk_enable(&cmt0_clk);
-
- cmt_timer_start();
-
- return 0;
-}
-
-static struct sys_timer_ops cmt_timer_ops = {
- .init = cmt_timer_init,
- .start = cmt_timer_start,
- .stop = cmt_timer_stop,
-#ifndef CONFIG_GENERIC_TIME
- .get_offset = cmt_timer_get_offset,
-#endif
-};
-
-struct sys_timer cmt_timer = {
- .name = "cmt",
- .ops = &cmt_timer_ops,
-};
diff --git a/arch/sh/kernel/timers/timer-mtu2.c b/arch/sh/kernel/timers/timer-mtu2.c
deleted file mode 100644
index 9b0ef0126479..000000000000
--- a/arch/sh/kernel/timers/timer-mtu2.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * arch/sh/kernel/timers/timer-mtu2.c - MTU2 Timer Support
- *
- * Copyright (C) 2005 Paul Mundt
- *
- * Based off of arch/sh/kernel/timers/timer-tmu.c
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/seqlock.h>
-#include <asm/timer.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/clock.h>
-
-/*
- * We use channel 1 for our lowly system timer. Channel 2 would be the other
- * likely candidate, but we leave it alone as it has higher divisors that
- * would be of more use to other more interesting applications.
- *
- * TODO: Presently we only implement a 16-bit single-channel system timer.
- * However, we can implement channel cascade if we go the overflow route and
- * get away with using 2 MTU2 channels as a 32-bit timer.
- */
-#define MTU2_TSTR 0xfffe4280
-#define MTU2_TCR_1 0xfffe4380
-#define MTU2_TMDR_1 0xfffe4381
-#define MTU2_TIOR_1 0xfffe4382
-#define MTU2_TIER_1 0xfffe4384
-#define MTU2_TSR_1 0xfffe4385
-#define MTU2_TCNT_1 0xfffe4386 /* 16-bit counter */
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7201) || \
- defined(CONFIG_CPU_SUBTYPE_SH7203)
-#define MTU2_TGRA_1 0xfffe4388
-#else
-#define MTU2_TGRA_1 0xfffe438a
-#endif
-
-#define STBCR3 0xfffe0408
-
-#define MTU2_TSTR_CST1 (1 << 1) /* Counter Start 1 */
-
-#define MTU2_TSR_TGFA (1 << 0) /* GRA compare match */
-
-#define MTU2_TIER_TGIEA (1 << 0) /* GRA compare match interrupt enable */
-
-#define MTU2_TCR_INIT 0x22
-
-#define MTU2_TCR_CALIB 0x00
-
-static unsigned long mtu2_timer_get_offset(void)
-{
- int count;
- static int count_p = 0x7fff; /* for the first call after boot */
- static unsigned long jiffies_p = 0;
-
- /*
- * cache volatile jiffies temporarily; we have IRQs turned off.
- */
- unsigned long jiffies_t;
-
- /* timer count may underflow right here */
- count = ctrl_inw(MTU2_TCNT_1); /* read the latched count */
-
- jiffies_t = jiffies;
-
- /*
- * avoiding timer inconsistencies (they are rare, but they happen)...
- * there is one kind of problem that must be avoided here:
- * 1. the timer counter underflows
- */
-
- if (jiffies_t == jiffies_p) {
- if (count > count_p) {
- if (ctrl_inb(MTU2_TSR_1) & MTU2_TSR_TGFA) {
- count -= LATCH;
- } else {
- printk("%s (): hardware timer problem?\n",
- __func__);
- }
- }
- } else
- jiffies_p = jiffies_t;
-
- count_p = count;
-
- count = ((LATCH-1) - count) * TICK_SIZE;
- count = (count + LATCH/2) / LATCH;
-
- return count;
-}
-
-static irqreturn_t mtu2_timer_interrupt(int irq, void *dev_id)
-{
- unsigned long timer_status;
-
- /* Clear TGFA bit */
- timer_status = ctrl_inb(MTU2_TSR_1);
- timer_status &= ~MTU2_TSR_TGFA;
- ctrl_outb(timer_status, MTU2_TSR_1);
-
- /* Do timer tick */
- handle_timer_tick();
-
- return IRQ_HANDLED;
-}
-
-static struct irqaction mtu2_irq = {
- .name = "timer",
- .handler = mtu2_timer_interrupt,
- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-};
-
-static unsigned int divisors[] = { 1, 4, 16, 64, 1, 1, 256 };
-
-static void mtu2_clk_init(struct clk *clk)
-{
- u8 idx = MTU2_TCR_INIT & 0x7;
-
- clk->rate = clk->parent->rate / divisors[idx];
- /* Start TCNT counting */
- ctrl_outb(ctrl_inb(MTU2_TSTR) | MTU2_TSTR_CST1, MTU2_TSTR);
-
-}
-
-static void mtu2_clk_recalc(struct clk *clk)
-{
- u8 idx = ctrl_inb(MTU2_TCR_1) & 0x7;
- clk->rate = clk->parent->rate / divisors[idx];
-}
-
-static struct clk_ops mtu2_clk_ops = {
- .init = mtu2_clk_init,
- .recalc = mtu2_clk_recalc,
-};
-
-static struct clk mtu2_clk1 = {
- .name = "mtu2_clk1",
- .ops = &mtu2_clk_ops,
-};
-
-static int mtu2_timer_start(void)
-{
- ctrl_outb(ctrl_inb(MTU2_TSTR) | MTU2_TSTR_CST1, MTU2_TSTR);
- return 0;
-}
-
-static int mtu2_timer_stop(void)
-{
- ctrl_outb(ctrl_inb(MTU2_TSTR) & ~MTU2_TSTR_CST1, MTU2_TSTR);
- return 0;
-}
-
-static int mtu2_timer_init(void)
-{
- unsigned long interval;
-
- setup_irq(CONFIG_SH_TIMER_IRQ, &mtu2_irq);
-
- mtu2_clk1.parent = clk_get(NULL, "module_clk");
-
- ctrl_outb(ctrl_inb(STBCR3) & (~0x20), STBCR3);
-
- /* Normal operation */
- ctrl_outb(0, MTU2_TMDR_1);
- ctrl_outb(MTU2_TCR_INIT, MTU2_TCR_1);
- ctrl_outb(0x01, MTU2_TIOR_1);
-
- /* Enable underflow interrupt */
- ctrl_outb(ctrl_inb(MTU2_TIER_1) | MTU2_TIER_TGIEA, MTU2_TIER_1);
-
- interval = CONFIG_SH_PCLK_FREQ / 16 / HZ;
- printk(KERN_INFO "Interval = %ld\n", interval);
-
- ctrl_outw(interval, MTU2_TGRA_1);
- ctrl_outw(0, MTU2_TCNT_1);
-
- clk_register(&mtu2_clk1);
- clk_enable(&mtu2_clk1);
-
- return 0;
-}
-
-struct sys_timer_ops mtu2_timer_ops = {
- .init = mtu2_timer_init,
- .start = mtu2_timer_start,
- .stop = mtu2_timer_stop,
-#ifndef CONFIG_GENERIC_TIME
- .get_offset = mtu2_timer_get_offset,
-#endif
-};
-
-struct sys_timer mtu2_timer = {
- .name = "mtu2",
- .ops = &mtu2_timer_ops,
-};
diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c
index c5d3396f5960..fe8d8930ccb6 100644
--- a/arch/sh/kernel/timers/timer-tmu.c
+++ b/arch/sh/kernel/timers/timer-tmu.c
@@ -81,7 +81,7 @@ static int tmu_timer_stop(void)
*/
static int tmus_are_scaled;
-static cycle_t tmu_timer_read(void)
+static cycle_t tmu_timer_read(struct clocksource *cs)
{
return ((cycle_t)(~_tmu_read(TMU1)))<<tmus_are_scaled;
}
diff --git a/arch/sh/kernel/timers/timer.c b/arch/sh/kernel/timers/timer.c
index 4e7e747d1b69..920891acb779 100644
--- a/arch/sh/kernel/timers/timer.c
+++ b/arch/sh/kernel/timers/timer.c
@@ -17,12 +17,6 @@ static struct sys_timer *sys_timers[] = {
#ifdef CONFIG_SH_TMU
&tmu_timer,
#endif
-#ifdef CONFIG_SH_MTU2
- &mtu2_timer,
-#endif
-#ifdef CONFIG_SH_CMT
- &cmt_timer,
-#endif
NULL,
};
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index 438f1ebcc453..46348ed07cc3 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -22,11 +22,11 @@ static void handle_BUG(struct pt_regs *regs)
int is_valid_bugaddr(unsigned long addr)
{
- unsigned short opcode;
+ insn_size_t opcode;
if (addr < PAGE_OFFSET)
return 0;
- if (probe_kernel_address((u16 *)addr, opcode))
+ if (probe_kernel_address((insn_size_t *)addr, opcode))
return 0;
return opcode == TRAPA_BUG_OPCODE;
@@ -66,7 +66,7 @@ BUILD_TRAP_HANDLER(bug)
#ifdef CONFIG_BUG
if (__kernel_text_address(instruction_pointer(regs))) {
- opcode_t insn = *(opcode_t *)instruction_pointer(regs);
+ insn_size_t insn = *(insn_size_t *)instruction_pointer(regs);
if (insn == TRAPA_BUG_OPCODE)
handle_BUG(regs);
}
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c
index 30ca9c51e52d..2b772776fcda 100644
--- a/arch/sh/kernel/traps_32.c
+++ b/arch/sh/kernel/traps_32.c
@@ -34,6 +34,7 @@
# define TRAP_ILLEGAL_SLOT_INST 6
# define TRAP_ADDRESS_ERROR 9
# ifdef CONFIG_CPU_SH2A
+# define TRAP_UBC 12
# define TRAP_FPU_ERROR 13
# define TRAP_DIVZERO_ERROR 17
# define TRAP_DIVOVF_ERROR 18
@@ -176,7 +177,7 @@ static struct mem_access user_mem_access = {
* (if that instruction is in a branch delay slot)
* - return 0 if emulation okay, -EFAULT on existential error
*/
-static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs,
+static int handle_unaligned_ins(insn_size_t instruction, struct pt_regs *regs,
struct mem_access *ma)
{
int ret, index, count;
@@ -321,10 +322,10 @@ static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs,
* - fetches the instruction from PC+2
*/
static inline int handle_delayslot(struct pt_regs *regs,
- opcode_t old_instruction,
+ insn_size_t old_instruction,
struct mem_access *ma)
{
- opcode_t instruction;
+ insn_size_t instruction;
void __user *addr = (void __user *)(regs->pc +
instruction_size(old_instruction));
@@ -364,7 +365,7 @@ static inline int handle_delayslot(struct pt_regs *regs,
static int handle_unaligned_notify_count = 10;
-int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs,
+int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
struct mem_access *ma)
{
u_int rm;
@@ -522,7 +523,7 @@ asmlinkage void do_address_error(struct pt_regs *regs,
unsigned long error_code = 0;
mm_segment_t oldfs;
siginfo_t info;
- opcode_t instruction;
+ insn_size_t instruction;
int tmp;
/* Intentional ifdef */
@@ -849,6 +850,10 @@ void __init trap_init(void)
#endif
#endif
+#ifdef TRAP_UBC
+ set_exception_table_vec(TRAP_UBC, break_point_trap);
+#endif
+
/* Setup VBR for boot cpu */
per_cpu_trap_init();
}
diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c
index a85831cbf18b..267e5ebbb475 100644
--- a/arch/sh/kernel/traps_64.c
+++ b/arch/sh/kernel/traps_64.c
@@ -370,7 +370,6 @@ static int generate_and_check_address(struct pt_regs *regs,
return -1;
}
-#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
/* Check accessible. For misaligned access in the kernel, assume the
address is always accessible (and if not, just fault when the
load/store gets done.) */
@@ -380,18 +379,13 @@ static int generate_and_check_address(struct pt_regs *regs,
}
/* Do access_ok check later - it depends on whether it's a load or a store. */
}
-#endif
*address = addr;
return 0;
}
-/* Default value as for sh */
-#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
static int user_mode_unaligned_fixup_count = 10;
static int user_mode_unaligned_fixup_enable = 1;
-#endif
-
static int kernel_mode_unaligned_fixup_count = 32;
static void misaligned_kernel_word_load(__u64 address, int do_sign_extend, __u64 *result)
@@ -440,7 +434,6 @@ static int misaligned_load(struct pt_regs *regs,
}
destreg = (opcode >> 4) & 0x3f;
-#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
if (user_mode(regs)) {
__u64 buffer;
@@ -470,9 +463,7 @@ static int misaligned_load(struct pt_regs *regs,
width_shift, (unsigned long) regs->pc);
break;
}
- } else
-#endif
- {
+ } else {
/* kernel mode - we can take short cuts since if we fault, it's a genuine bug */
__u64 lo, hi;
@@ -519,7 +510,6 @@ static int misaligned_store(struct pt_regs *regs,
}
srcreg = (opcode >> 4) & 0x3f;
-#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
if (user_mode(regs)) {
__u64 buffer;
@@ -546,9 +536,7 @@ static int misaligned_store(struct pt_regs *regs,
if (__copy_user((void *)(int)address, &buffer, (1 << width_shift)) > 0) {
return -1; /* fault */
}
- } else
-#endif
- {
+ } else {
/* kernel mode - we can take short cuts since if we fault, it's a genuine bug */
__u64 val = regs->regs[srcreg];
@@ -576,7 +564,6 @@ static int misaligned_store(struct pt_regs *regs,
}
-#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
/* Never need to fix up misaligned FPU accesses within the kernel since that's a real
error. */
static int misaligned_fpu_load(struct pt_regs *regs,
@@ -727,7 +714,6 @@ static int misaligned_fpu_store(struct pt_regs *regs,
return -1;
}
}
-#endif
static int misaligned_fixup(struct pt_regs *regs)
{
@@ -735,12 +721,8 @@ static int misaligned_fixup(struct pt_regs *regs)
int error;
int major, minor;
-#if !defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
- /* Never fixup user mode misaligned accesses without this option enabled. */
- return -1;
-#else
- if (!user_mode_unaligned_fixup_enable) return -1;
-#endif
+ if (!user_mode_unaligned_fixup_enable)
+ return -1;
error = read_opcode(regs->pc, &opcode, user_mode(regs));
if (error < 0) {
@@ -749,15 +731,12 @@ static int misaligned_fixup(struct pt_regs *regs)
major = (opcode >> 26) & 0x3f;
minor = (opcode >> 16) & 0xf;
-#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
if (user_mode(regs) && (user_mode_unaligned_fixup_count > 0)) {
--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, task_pid_nr(current), (__u32)regs->pc, opcode);
- } else
-#endif
- if (!user_mode(regs) && (kernel_mode_unaligned_fixup_count > 0)) {
+ } else if (!user_mode(regs) && (kernel_mode_unaligned_fixup_count > 0)) {
--kernel_mode_unaligned_fixup_count;
if (in_interrupt()) {
printk("Fixing up unaligned kernelspace access in interrupt pc=0x%08x ins=0x%08lx\n",
@@ -830,7 +809,6 @@ static int misaligned_fixup(struct pt_regs *regs)
}
break;
-#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
case (0x94>>2): /* FLD.S */
error = misaligned_fpu_load(regs, opcode, 1, 2, 0);
break;
@@ -881,7 +859,6 @@ static int misaligned_fixup(struct pt_regs *regs)
break;
}
break;
-#endif
default:
/* Fault */
@@ -907,7 +884,6 @@ static ctl_table unaligned_table[] = {
.mode = 0644,
.proc_handler = &proc_dointvec
},
-#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
{
.ctl_name = CTL_UNNUMBERED,
.procname = "user_reports",
@@ -923,7 +899,6 @@ static ctl_table unaligned_table[] = {
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec},
-#endif
{}
};
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index d7d4991f32af..f53c76acaede 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -1,5 +1,178 @@
-#ifdef CONFIG_SUPERH32
-# include "vmlinux_32.lds.S"
+/*
+ * ld script to make SuperH Linux kernel
+ * Written by Niibe Yutaka and Paul Mundt
+ */
+#ifdef CONFIG_SUPERH64
+#define LOAD_OFFSET CONFIG_PAGE_OFFSET
+OUTPUT_ARCH(sh:sh5)
#else
-# include "vmlinux_64.lds.S"
+#define LOAD_OFFSET 0
+OUTPUT_ARCH(sh)
#endif
+
+#include <asm/thread_info.h>
+#include <asm/cache.h>
+#include <asm-generic/vmlinux.lds.h>
+
+ENTRY(_start)
+SECTIONS
+{
+#ifdef CONFIG_PMB_FIXED
+ . = CONFIG_PAGE_OFFSET + (CONFIG_MEMORY_START & 0x1fffffff) +
+ CONFIG_ZERO_PAGE_OFFSET;
+#elif defined(CONFIG_32BIT)
+ . = CONFIG_PAGE_OFFSET + CONFIG_ZERO_PAGE_OFFSET;
+#else
+ . = CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET;
+#endif
+
+ _text = .; /* Text and read-only data */
+
+ .empty_zero_page : AT(ADDR(.empty_zero_page) - LOAD_OFFSET) {
+ *(.empty_zero_page)
+ } = 0
+
+ .text : AT(ADDR(.text) - LOAD_OFFSET) {
+ HEAD_TEXT
+ TEXT_TEXT
+
+#ifdef CONFIG_SUPERH64
+ *(.text64)
+ *(.text..SHmedia32)
+#endif
+
+ SCHED_TEXT
+ LOCK_TEXT
+ KPROBES_TEXT
+ IRQENTRY_TEXT
+ *(.fixup)
+ *(.gnu.warning)
+ _etext = .; /* End of text section */
+ } = 0x0009
+
+ . = ALIGN(16); /* Exception table */
+ __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
+ __start___ex_table = .;
+ *(__ex_table)
+ __stop___ex_table = .;
+ }
+
+ NOTES
+ RO_DATA(PAGE_SIZE)
+
+ /*
+ * Code which must be executed uncached and the associated data
+ */
+ . = ALIGN(PAGE_SIZE);
+ .uncached : AT(ADDR(.uncached) - LOAD_OFFSET) {
+ __uncached_start = .;
+ *(.uncached.text)
+ *(.uncached.data)
+ __uncached_end = .;
+ }
+
+ . = ALIGN(THREAD_SIZE);
+ .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */
+ *(.data.init_task)
+
+ . = ALIGN(L1_CACHE_BYTES);
+ *(.data.cacheline_aligned)
+
+ . = ALIGN(L1_CACHE_BYTES);
+ *(.data.read_mostly)
+
+ . = ALIGN(PAGE_SIZE);
+ *(.data.page_aligned)
+
+ __nosave_begin = .;
+ *(.data.nosave)
+ . = ALIGN(PAGE_SIZE);
+ __nosave_end = .;
+
+ DATA_DATA
+ CONSTRUCTORS
+ }
+
+ _edata = .; /* End of data section */
+
+ . = ALIGN(PAGE_SIZE); /* Init code and data */
+ .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
+ __init_begin = .;
+ _sinittext = .;
+ INIT_TEXT
+ _einittext = .;
+ }
+
+ .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { INIT_DATA }
+
+ . = ALIGN(16);
+ .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
+ __setup_start = .;
+ *(.init.setup)
+ __setup_end = .;
+ }
+
+ .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
+ __initcall_start = .;
+ INITCALLS
+ __initcall_end = .;
+ }
+
+ .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
+ __con_initcall_start = .;
+ *(.con_initcall.init)
+ __con_initcall_end = .;
+ }
+
+ SECURITY_INIT
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ . = ALIGN(PAGE_SIZE);
+ .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
+ __initramfs_start = .;
+ *(.init.ramfs)
+ __initramfs_end = .;
+ }
+#endif
+
+ . = ALIGN(4);
+ .machvec.init : AT(ADDR(.machvec.init) - LOAD_OFFSET) {
+ __machvec_start = .;
+ *(.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 : AT(ADDR(.exit.text) - LOAD_OFFSET) { EXIT_TEXT }
+ .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { EXIT_DATA }
+
+ . = ALIGN(PAGE_SIZE);
+ .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
+ __init_end = .;
+ __bss_start = .; /* BSS */
+ *(.bss.page_aligned)
+ *(.bss)
+ *(COMMON)
+ . = 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)
+ }
+
+ STABS_DEBUG
+ DWARF_DEBUG
+}
diff --git a/arch/sh/kernel/vmlinux_32.lds.S b/arch/sh/kernel/vmlinux_32.lds.S
deleted file mode 100644
index d0b2a715cd14..000000000000
--- a/arch/sh/kernel/vmlinux_32.lds.S
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * ld script to make SuperH Linux kernel
- * Written by Niibe Yutaka
- */
-#include <asm/thread_info.h>
-#include <asm/cache.h>
-#include <asm-generic/vmlinux.lds.h>
-
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
-OUTPUT_FORMAT("elf32-sh-linux", "elf32-sh-linux", "elf32-sh-linux")
-#else
-OUTPUT_FORMAT("elf32-shbig-linux", "elf32-shbig-linux", "elf32-shbig-linux")
-#endif
-OUTPUT_ARCH(sh)
-ENTRY(_start)
-SECTIONS
-{
-#ifdef CONFIG_PMB_FIXED
- . = CONFIG_PAGE_OFFSET + (CONFIG_MEMORY_START & 0x1fffffff) +
- CONFIG_ZERO_PAGE_OFFSET;
-#elif defined(CONFIG_32BIT)
- . = CONFIG_PAGE_OFFSET + CONFIG_ZERO_PAGE_OFFSET;
-#else
- . = CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET;
-#endif
-
- _text = .; /* Text and read-only data */
-
- .empty_zero_page : {
- *(.empty_zero_page)
- } = 0
-
- .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 = .;
-
- _etext = .; /* End of text section */
-
- NOTES
- RO_DATA(PAGE_SIZE)
-
- /*
- * Code which must be executed uncached and the associated data
- */
- . = ALIGN(PAGE_SIZE);
- __uncached_start = .;
- .uncached.text : { *(.uncached.text) }
- .uncached.data : { *(.uncached.data) }
- __uncached_end = .;
-
- . = ALIGN(THREAD_SIZE);
- .data : { /* Data */
- *(.data.init_task)
-
- . = ALIGN(L1_CACHE_BYTES);
- *(.data.cacheline_aligned)
-
- . = ALIGN(L1_CACHE_BYTES);
- *(.data.read_mostly)
-
- . = ALIGN(PAGE_SIZE);
- *(.data.page_aligned)
-
- __nosave_begin = .;
- *(.data.nosave)
- . = ALIGN(PAGE_SIZE);
- __nosave_end = .;
-
- DATA_DATA
- CONSTRUCTORS
- }
-
- _edata = .; /* End of data section */
-
- . = 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
-
-#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 = .;
-
- 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 = . ;
- }
-
- /*
- * 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)
- }
-
- STABS_DEBUG
- DWARF_DEBUG
-}
diff --git a/arch/sh/kernel/vmlinux_64.lds.S b/arch/sh/kernel/vmlinux_64.lds.S
deleted file mode 100644
index 33fa46451406..000000000000
--- a/arch/sh/kernel/vmlinux_64.lds.S
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * ld script to make SH64 Linux kernel
- *
- * Copyright (C) 2000, 2001 Paolo Alberelli
- *
- * benedict.gaster@superh.com: 2nd May 2002
- * Add definition of empty_zero_page to be the first page of kernel image.
- *
- * benedict.gaster@superh.com: 3rd May 2002
- * Added support for ramdisk, removing statically linked romfs at the
- * same time.
- *
- * lethal@linux-sh.org: 9th May 2003
- * Kill off GLOBAL_NAME() usage and other CDC-isms.
- *
- * lethal@linux-sh.org: 19th May 2003
- * Remove support for ancient toolchains.
- *
- * 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 <asm/page.h>
-#include <asm/cache.h>
-#include <asm/thread_info.h>
-
-#define LOAD_OFFSET CONFIG_PAGE_OFFSET
-#include <asm-generic/vmlinux.lds.h>
-
-OUTPUT_ARCH(sh:sh5)
-
-#define C_PHYS(x) AT (ADDR(x) - LOAD_OFFSET)
-
-ENTRY(__start)
-SECTIONS
-{
- . = CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START + PAGE_SIZE;
- _text = .; /* Text and read-only data */
-
- .empty_zero_page : C_PHYS(.empty_zero_page) {
- *(.empty_zero_page)
- } = 0
-
- .text : C_PHYS(.text) {
- *(.text.head)
- TEXT_TEXT
- *(.text64)
- *(.text..SHmedia32)
- SCHED_TEXT
- LOCK_TEXT
- KPROBES_TEXT
- *(.fixup)
- *(.gnu.warning)
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
- } = 0x6ff0fff0
-#else
- } = 0xf0fff06f
-#endif
-
- /* We likely want __ex_table to be Cache Line aligned */
- . = ALIGN(L1_CACHE_BYTES); /* Exception table */
- __start___ex_table = .;
- __ex_table : C_PHYS(__ex_table) { *(__ex_table) }
- __stop___ex_table = .;
-
- _etext = .; /* End of text section */
-
- NOTES
- RO_DATA(PAGE_SIZE)
-
- . = ALIGN(THREAD_SIZE);
- .data : C_PHYS(.data) { /* Data */
- *(.data.init_task)
-
- . = ALIGN(L1_CACHE_BYTES);
- *(.data.cacheline_aligned)
-
- . = ALIGN(L1_CACHE_BYTES);
- *(.data.read_mostly)
-
- . = ALIGN(PAGE_SIZE);
- *(.data.page_aligned)
-
- __nosave_begin = .;
- *(.data.nosave)
- . = ALIGN(PAGE_SIZE);
- __nosave_end = .;
-
- DATA_DATA
- CONSTRUCTORS
- }
-
- _edata = .; /* End of data section */
-
- . = ALIGN(PAGE_SIZE); /* Init code and data */
- __init_begin = .;
- _sinittext = .;
- .init.text : C_PHYS(.init.text) { INIT_TEXT }
- _einittext = .;
- .init.data : C_PHYS(.init.data) { INIT_DATA }
- . = ALIGN(L1_CACHE_BYTES); /* Better if Cache Line aligned */
- __setup_start = .;
- .init.setup : C_PHYS(.init.setup) { *(.init.setup) }
- __setup_end = .;
- __initcall_start = .;
- .initcall.init : C_PHYS(.initcall.init) {
- INITCALLS
- }
- __initcall_end = .;
- __con_initcall_start = .;
- .con_initcall.init : C_PHYS(.con_initcall.init) {
- *(.con_initcall.init)
- }
- __con_initcall_end = .;
-
- SECURITY_INIT
-
-#ifdef CONFIG_BLK_DEV_INITRD
- . = ALIGN(PAGE_SIZE);
- __initramfs_start = .;
- .init.ramfs : C_PHYS(.init.ramfs) { *(.init.ramfs) }
- __initramfs_end = .;
-#endif
-
- . = ALIGN(8);
- __machvec_start = .;
- .machvec.init : C_PHYS(.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 : C_PHYS(.exit.text) { EXIT_TEXT }
- .exit.data : C_PHYS(.exit.data) { EXIT_DATA }
-
- . = ALIGN(PAGE_SIZE);
- .bss : C_PHYS(.bss) {
- __init_end = .;
- __bss_start = .; /* BSS */
- *(.bss.page_aligned)
- *(.bss)
- *(COMMON)
- . = 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)
- }
-
- STABS_DEBUG
- DWARF_DEBUG
-}
diff --git a/arch/sh/lib64/.gitignore b/arch/sh/lib64/.gitignore
deleted file mode 100644
index 3508c2cb23c4..000000000000
--- a/arch/sh/lib64/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-syscalltab.h
diff --git a/arch/sh/lib64/dbg.c b/arch/sh/lib64/dbg.c
index 2fb8eaf6de60..6152a6a6d9c6 100644
--- a/arch/sh/lib64/dbg.c
+++ b/arch/sh/lib64/dbg.c
@@ -135,140 +135,6 @@ void print_itlb(void)
(" =============================================================\n");
}
-/* ======================================================================= */
-
-#ifdef CONFIG_POOR_MANS_STRACE
-
-#include "syscalltab.h"
-
-struct ring_node {
- int evt;
- int ret_addr;
- int event;
- int tra;
- int pid;
- unsigned long sp;
- unsigned long pc;
-};
-
-static struct ring_node event_ring[16];
-static int event_ptr = 0;
-
-struct stored_syscall_data {
- int pid;
- int syscall_number;
-};
-
-#define N_STORED_SYSCALLS 16
-
-static struct stored_syscall_data stored_syscalls[N_STORED_SYSCALLS];
-static int syscall_next=0;
-static int syscall_next_print=0;
-
-void evt_debug(int evt, int ret_addr, int event, int tra, struct pt_regs *regs)
-{
- int syscallno = tra & 0xff;
- unsigned long sp;
- unsigned long stack_bottom;
- int pid;
- struct ring_node *rr;
-
- pid = current->pid;
- stack_bottom = (unsigned long) task_stack_page(current);
- asm volatile("ori r15, 0, %0" : "=r" (sp));
- rr = event_ring + event_ptr;
- rr->evt = evt;
- rr->ret_addr = ret_addr;
- rr->event = event;
- rr->tra = tra;
- rr->pid = pid;
- rr->sp = sp;
- rr->pc = regs->pc;
-
- if (sp < stack_bottom + 3092) {
- int i, j;
- printk("evt_debug : stack underflow report\n");
- for (j=0, i = event_ptr; j<16; j++) {
- rr = event_ring + i;
- printk("evt=%08x event=%08x tra=%08x pid=%5d sp=%08lx pc=%08lx\n",
- rr->evt, rr->event, rr->tra, rr->pid, rr->sp, rr->pc);
- i--;
- i &= 15;
- }
- panic("STACK UNDERFLOW\n");
- }
-
- event_ptr = (event_ptr + 1) & 15;
-
- if ((event == 2) && (evt == 0x160)) {
- if (syscallno < NUM_SYSCALL_INFO_ENTRIES) {
- /* Store the syscall information to print later. We
- * can't print this now - currently we're running with
- * SR.BL=1, so we can't take a tlbmiss (which could occur
- * in the console drivers under printk).
- *
- * Just overwrite old entries on ring overflow - this
- * is only for last-hope debugging. */
- stored_syscalls[syscall_next].pid = current->pid;
- stored_syscalls[syscall_next].syscall_number = syscallno;
- syscall_next++;
- syscall_next &= (N_STORED_SYSCALLS - 1);
- }
- }
-}
-
-static void drain_syscalls(void) {
- while (syscall_next_print != syscall_next) {
- printk("Task %d: %s()\n",
- stored_syscalls[syscall_next_print].pid,
- syscall_info_table[stored_syscalls[syscall_next_print].syscall_number].name);
- syscall_next_print++;
- syscall_next_print &= (N_STORED_SYSCALLS - 1);
- }
-}
-
-void evt_debug2(unsigned int ret)
-{
- drain_syscalls();
- printk("Task %d: syscall returns %08x\n", current->pid, ret);
-}
-
-void evt_debug_ret_from_irq(struct pt_regs *regs)
-{
- int pid;
- struct ring_node *rr;
-
- pid = current->pid;
- rr = event_ring + event_ptr;
- rr->evt = 0xffff;
- rr->ret_addr = 0;
- rr->event = 0;
- rr->tra = 0;
- rr->pid = pid;
- rr->pc = regs->pc;
- event_ptr = (event_ptr + 1) & 15;
-}
-
-void evt_debug_ret_from_exc(struct pt_regs *regs)
-{
- int pid;
- struct ring_node *rr;
-
- pid = current->pid;
- rr = event_ring + event_ptr;
- rr->evt = 0xfffe;
- rr->ret_addr = 0;
- rr->event = 0;
- rr->tra = 0;
- rr->pid = pid;
- rr->pc = regs->pc;
- event_ptr = (event_ptr + 1) & 15;
-}
-
-#endif /* CONFIG_POOR_MANS_STRACE */
-
-/* ======================================================================= */
-
void show_excp_regs(char *from, int trapnr, int signr, struct pt_regs *regs)
{
@@ -380,51 +246,3 @@ void show_excp_regs(char *from, int trapnr, int signr, struct pt_regs *regs)
print_dtlb();
print_itlb();
}
-
-/* ======================================================================= */
-
-/*
-** Depending on <base> scan the MMU, Data or Instruction side
-** looking for a valid mapping matching Eaddr & asid.
-** Return -1 if not found or the TLB id entry otherwise.
-** Note: it works only for 4k pages!
-*/
-static unsigned long
-lookup_mmu_side(unsigned long base, unsigned long Eaddr, unsigned long asid)
-{
- regType_t pteH;
- unsigned long epn;
- int count;
-
- epn = Eaddr & 0xfffff000;
-
- for (count = 0; count < MAX_TLBs; count++, base += TLB_STEP) {
- pteH = getConfigReg(base);
- if (GET_VALID(pteH))
- if ((unsigned long) GET_EPN(pteH) == epn)
- if ((unsigned long) GET_ASID(pteH) == asid)
- break;
- }
- return ((unsigned long) ((count < MAX_TLBs) ? base : -1));
-}
-
-unsigned long lookup_dtlb(unsigned long Eaddr)
-{
- unsigned long asid = get_asid();
- return (lookup_mmu_side((u64) DTLB_BASE, Eaddr, asid));
-}
-
-unsigned long lookup_itlb(unsigned long Eaddr)
-{
- unsigned long asid = get_asid();
- return (lookup_mmu_side((u64) ITLB_BASE, Eaddr, asid));
-}
-
-void print_page(struct page *page)
-{
- printk(" page[%p] -> index 0x%lx, count 0x%x, flags 0x%lx\n",
- page, page->index, page_count(page), page->flags);
- printk(" address_space = %p, pages =%ld\n", page->mapping,
- page->mapping->nrpages);
-
-}
diff --git a/arch/sh/lib64/panic.c b/arch/sh/lib64/panic.c
index da32ba7b5fcc..38c954e04f6a 100644
--- a/arch/sh/lib64/panic.c
+++ b/arch/sh/lib64/panic.c
@@ -6,53 +6,10 @@
* for more details.
*/
-#include <linux/kernel.h>
-#include <asm/io.h>
-#include <cpu/registers.h>
-
-/* THIS IS A PHYSICAL ADDRESS */
-#define HDSP2534_ADDR (0x04002100)
-
-#ifdef CONFIG_SH_CAYMAN
-
-static void poor_mans_delay(void)
-{
- int i;
- for (i = 0; i < 2500000; i++) {
- } /* poor man's delay */
-}
-
-static void show_value(unsigned long x)
-{
- int i;
- unsigned nibble;
- for (i = 0; i < 8; i++) {
- nibble = ((x >> (i * 4)) & 0xf);
-
- ctrl_outb(nibble + ((nibble > 9) ? 55 : 48),
- HDSP2534_ADDR + 0xe0 + ((7 - i) << 2));
- }
-}
-
-#endif
-
void
panic_handler(unsigned long panicPC, unsigned long panicSSR,
unsigned long panicEXPEVT)
{
-#ifdef CONFIG_SH_CAYMAN
- while (1) {
- /* This piece of code displays the PC on the LED display */
- show_value(panicPC);
- poor_mans_delay();
- show_value(panicSSR);
- poor_mans_delay();
- show_value(panicEXPEVT);
- poor_mans_delay();
- }
-#endif
-
/* Never return from the panic handler */
for (;;) ;
-
}
diff --git a/arch/sh/lib64/sdivsi3.S b/arch/sh/lib64/sdivsi3.S
index 6a800c6a4904..1963bbd42288 100644
--- a/arch/sh/lib64/sdivsi3.S
+++ b/arch/sh/lib64/sdivsi3.S
@@ -1,4 +1,6 @@
.global __sdivsi3
+ .global __sdivsi3_1
+ .global __sdivsi3_2
.section .text..SHmedia32,"ax"
.align 2
@@ -6,13 +8,15 @@
/* clobbered: r1,r18,r19,r20,r21,r25,tr0 */
/* result in r0 */
__sdivsi3:
+__sdivsi3_1:
ptb __div_table,tr0
+ gettr tr0,r20
+__sdivsi3_2:
nsb r5, r1
shlld r5, r1, r25 /* normalize; [-2 ..1, 1..2) in s2.62 */
shari r25, 58, r21 /* extract 5(6) bit index (s2.4 with hole -1..1) */
/* bubble */
- gettr tr0,r20
ldx.ub r20, r21, r19 /* u0.8 */
shari r25, 32, r25 /* normalize to s2.30 */
shlli r21, 1, r21
diff --git a/arch/sh/lib64/udelay.c b/arch/sh/lib64/udelay.c
index d76bd801194f..f215b063da70 100644
--- a/arch/sh/lib64/udelay.c
+++ b/arch/sh/lib64/udelay.c
@@ -33,7 +33,7 @@ void __delay(unsigned long loops)
:"0"(loops));
}
-inline void __const_udelay(unsigned long xloops)
+void __const_udelay(unsigned long xloops)
{
__delay(xloops * (HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy));
}
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index d4079cab2d58..b900d2cd18f7 100644
--- a/arch/sh/mm/Kconfig
+++ b/arch/sh/mm/Kconfig
@@ -201,14 +201,6 @@ config PAGE_SIZE_64KB
endchoice
-config ENTRY_OFFSET
- hex
- default "0x00001000" if PAGE_SIZE_4KB
- default "0x00002000" if PAGE_SIZE_8KB
- default "0x00004000" if PAGE_SIZE_16KB
- default "0x00010000" if PAGE_SIZE_64KB
- default "0x00000000"
-
choice
prompt "HugeTLB page size"
depends on HUGETLB_PAGE && (CPU_SH4 || CPU_SH5) && MMU
diff --git a/arch/sh/mm/cache-sh5.c b/arch/sh/mm/cache-sh5.c
index 9e277ec7d536..86762092508c 100644
--- a/arch/sh/mm/cache-sh5.c
+++ b/arch/sh/mm/cache-sh5.c
@@ -60,7 +60,7 @@ static inline void sh64_teardown_dtlb_cache_slot(void)
static inline void sh64_icache_inv_all(void)
{
unsigned long long addr, flag, data;
- unsigned int flags;
+ unsigned long flags;
addr = ICCR0;
flag = ICCR0_ICI;
@@ -172,7 +172,7 @@ static void sh64_icache_inv_user_page_range(struct mm_struct *mm,
unsigned long eaddr;
unsigned long after_last_page_start;
unsigned long mm_asid, current_asid;
- unsigned long long flags = 0ULL;
+ unsigned long flags = 0;
mm_asid = cpu_asid(smp_processor_id(), mm);
current_asid = get_asid();
@@ -236,7 +236,7 @@ static void sh64_icache_inv_user_small_range(struct mm_struct *mm,
unsigned long long eaddr = start;
unsigned long long eaddr_end = start + len;
unsigned long current_asid, mm_asid;
- unsigned long long flags;
+ unsigned long flags;
unsigned long long epage_start;
/*
@@ -342,7 +342,7 @@ static void inline sh64_dcache_purge_sets(int sets_to_purge_base, int n_sets)
* alloco is a NOP if the cache is write-through.
*/
if (test_bit(SH_CACHE_MODE_WT, &(cpu_data->dcache.flags)))
- ctrl_inb(eaddr);
+ __raw_readb((unsigned long)eaddr);
}
}
diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c
index edcd5fbf9651..e098ec158ddb 100644
--- a/arch/sh/mm/consistent.c
+++ b/arch/sh/mm/consistent.c
@@ -10,11 +10,22 @@
* for more details.
*/
#include <linux/mm.h>
+#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
+#include <linux/dma-debug.h>
+#include <linux/io.h>
#include <asm/cacheflush.h>
#include <asm/addrspace.h>
-#include <asm/io.h>
+
+#define PREALLOC_DMA_DEBUG_ENTRIES 4096
+
+static int __init dma_init(void)
+{
+ dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
+ return 0;
+}
+fs_initcall(dma_init);
void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp)
@@ -45,6 +56,9 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
split_page(pfn_to_page(virt_to_phys(ret) >> PAGE_SHIFT), order);
*dma_handle = virt_to_phys(ret);
+
+ debug_dma_alloc_coherent(dev, size, *dma_handle, ret_nocache);
+
return ret_nocache;
}
EXPORT_SYMBOL(dma_alloc_coherent);
@@ -56,12 +70,15 @@ void dma_free_coherent(struct device *dev, size_t size,
unsigned long pfn = dma_handle >> PAGE_SHIFT;
int k;
- if (!dma_release_from_coherent(dev, order, vaddr)) {
- WARN_ON(irqs_disabled()); /* for portability */
- for (k = 0; k < (1 << order); k++)
- __free_pages(pfn_to_page(pfn + k), 0);
- iounmap(vaddr);
- }
+ WARN_ON(irqs_disabled()); /* for portability */
+
+ if (dma_release_from_coherent(dev, order, vaddr))
+ return;
+
+ debug_dma_free_coherent(dev, size, vaddr, dma_handle);
+ for (k = 0; k < (1 << order); k++)
+ __free_pages(pfn_to_page(pfn + k), 0);
+ iounmap(vaddr);
}
EXPORT_SYMBOL(dma_free_coherent);
diff --git a/arch/sh/mm/ioremap_32.c b/arch/sh/mm/ioremap_32.c
index 60cc486d2c2c..da2f4186f2cd 100644
--- a/arch/sh/mm/ioremap_32.c
+++ b/arch/sh/mm/ioremap_32.c
@@ -46,17 +46,15 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
return NULL;
/*
- * If we're on an SH7751 or SH7780 PCI controller, PCI memory is
- * mapped at the end of the address space (typically 0xfd000000)
- * in a non-translatable area, so mapping through page tables for
- * this area is not only pointless, but also fundamentally
- * broken. Just return the physical address instead.
+ * If we're in the fixed PCI memory range, mapping through page
+ * tables is not only pointless, but also fundamentally broken.
+ * Just return the physical address instead.
*
* For boards that map a small PCI memory aperture somewhere in
* P1/P2 space, ioremap() will already do the right thing,
* and we'll never get this far.
*/
- if (is_pci_memaddr(phys_addr) && is_pci_memaddr(last_addr))
+ if (is_pci_memory_fixed_range(phys_addr, size))
return (void __iomem *)phys_addr;
#if !defined(CONFIG_PMB_FIXED)
@@ -121,7 +119,9 @@ void __iounmap(void __iomem *addr)
unsigned long seg = PXSEG(vaddr);
struct vm_struct *p;
- if (seg < P3SEG || vaddr >= P3_ADDR_MAX || is_pci_memaddr(vaddr))
+ if (seg < P3SEG || vaddr >= P3_ADDR_MAX)
+ return;
+ if (is_pci_memory_fixed_range(vaddr, 0))
return;
#ifdef CONFIG_PMB
diff --git a/arch/sh/mm/ioremap_64.c b/arch/sh/mm/ioremap_64.c
index 31e1bb5effbe..2331229f8126 100644
--- a/arch/sh/mm/ioremap_64.c
+++ b/arch/sh/mm/ioremap_64.c
@@ -27,88 +27,17 @@
#include <asm/tlbflush.h>
#include <asm/mmu.h>
-static void shmedia_mapioaddr(unsigned long, unsigned long);
-static unsigned long shmedia_ioremap(struct resource *, u32, int);
-
-/*
- * Generic mapping function (not visible outside):
- */
-
-/*
- * Remap an arbitrary physical address space into the kernel virtual
- * address space. Needed when the kernel wants to access high addresses
- * directly.
- *
- * NOTE! We need to allow non-page-aligned mappings too: we will obviously
- * have to convert them into an offset in a page-aligned mapping, but the
- * caller shouldn't need to know that small detail.
- */
-void *__ioremap(unsigned long phys_addr, unsigned long size,
- unsigned long flags)
-{
- void * addr;
- struct vm_struct * area;
- unsigned long offset, last_addr;
- pgprot_t pgprot;
-
- /* Don't allow wraparound or zero size */
- last_addr = phys_addr + size - 1;
- if (!size || last_addr < phys_addr)
- return NULL;
-
- pgprot = __pgprot(_PAGE_PRESENT | _PAGE_READ |
- _PAGE_WRITE | _PAGE_DIRTY |
- _PAGE_ACCESSED | _PAGE_SHARED | flags);
-
- /*
- * Mappings have to be page-aligned
- */
- offset = phys_addr & ~PAGE_MASK;
- phys_addr &= PAGE_MASK;
- size = PAGE_ALIGN(last_addr + 1) - phys_addr;
-
- /*
- * Ok, go for it..
- */
- area = get_vm_area(size, VM_IOREMAP);
- if (!area)
- return NULL;
- pr_debug("Get vm_area returns %p addr %p\n", area, area->addr);
- area->phys_addr = phys_addr;
- addr = area->addr;
- if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
- phys_addr, pgprot)) {
- vunmap(addr);
- return NULL;
- }
- return (void *) (offset + (char *)addr);
-}
-EXPORT_SYMBOL(__ioremap);
-
-void __iounmap(void *addr)
-{
- struct vm_struct *area;
-
- vfree((void *) (PAGE_MASK & (unsigned long) addr));
- area = remove_vm_area((void *) (PAGE_MASK & (unsigned long) addr));
- if (!area) {
- printk(KERN_ERR "iounmap: bad address %p\n", addr);
- return;
- }
-
- kfree(area);
-}
-EXPORT_SYMBOL(__iounmap);
-
static struct resource shmedia_iomap = {
.name = "shmedia_iomap",
.start = IOBASE_VADDR + PAGE_SIZE,
.end = IOBASE_END - 1,
};
-static void shmedia_mapioaddr(unsigned long pa, unsigned long va);
+static void shmedia_mapioaddr(unsigned long pa, unsigned long va,
+ unsigned long flags);
static void shmedia_unmapioaddr(unsigned long vaddr);
-static unsigned long shmedia_ioremap(struct resource *res, u32 pa, int sz);
+static void __iomem *shmedia_ioremap(struct resource *res, u32 pa,
+ int sz, unsigned long flags);
/*
* We have the same problem as the SPARC, so lets have the same comment:
@@ -130,18 +59,18 @@ static struct xresource xresv[XNRES];
static struct xresource *xres_alloc(void)
{
- struct xresource *xrp;
- int n;
-
- xrp = xresv;
- for (n = 0; n < XNRES; n++) {
- if (xrp->xflag == 0) {
- xrp->xflag = 1;
- return xrp;
- }
- xrp++;
- }
- return NULL;
+ struct xresource *xrp;
+ int n;
+
+ xrp = xresv;
+ for (n = 0; n < XNRES; n++) {
+ if (xrp->xflag == 0) {
+ xrp->xflag = 1;
+ return xrp;
+ }
+ xrp++;
+ }
+ return NULL;
}
static void xres_free(struct xresource *xrp)
@@ -161,76 +90,71 @@ static struct resource *shmedia_find_resource(struct resource *root,
return NULL;
}
-static unsigned long shmedia_alloc_io(unsigned long phys, unsigned long size,
- const char *name)
+static void __iomem *shmedia_alloc_io(unsigned long phys, unsigned long size,
+ const char *name, unsigned long flags)
{
- static int printed_full = 0;
- struct xresource *xres;
- struct resource *res;
- char *tack;
- int tlen;
-
- if (name == NULL) name = "???";
-
- if ((xres = xres_alloc()) != 0) {
- tack = xres->xname;
- res = &xres->xres;
- } else {
- if (!printed_full) {
- printk("%s: done with statics, switching to kmalloc\n",
- __func__);
- printed_full = 1;
- }
- tlen = strlen(name);
- tack = kmalloc(sizeof (struct resource) + tlen + 1, GFP_KERNEL);
- if (!tack)
- return -ENOMEM;
- memset(tack, 0, sizeof(struct resource));
- res = (struct resource *) tack;
- tack += sizeof (struct resource);
- }
-
- strncpy(tack, name, XNMLN);
- tack[XNMLN] = 0;
- res->name = tack;
-
- return shmedia_ioremap(res, phys, size);
+ static int printed_full;
+ struct xresource *xres;
+ struct resource *res;
+ char *tack;
+ int tlen;
+
+ if (name == NULL)
+ name = "???";
+
+ xres = xres_alloc();
+ if (xres != 0) {
+ tack = xres->xname;
+ res = &xres->xres;
+ } else {
+ if (!printed_full) {
+ printk(KERN_NOTICE "%s: done with statics, "
+ "switching to kmalloc\n", __func__);
+ printed_full = 1;
+ }
+ tlen = strlen(name);
+ tack = kmalloc(sizeof(struct resource) + tlen + 1, GFP_KERNEL);
+ if (!tack)
+ return NULL;
+ memset(tack, 0, sizeof(struct resource));
+ res = (struct resource *) tack;
+ tack += sizeof(struct resource);
+ }
+
+ strncpy(tack, name, XNMLN);
+ tack[XNMLN] = 0;
+ res->name = tack;
+
+ return shmedia_ioremap(res, phys, size, flags);
}
-static unsigned long shmedia_ioremap(struct resource *res, u32 pa, int sz)
+static void __iomem *shmedia_ioremap(struct resource *res, u32 pa, int sz,
+ unsigned long flags)
{
- unsigned long offset = ((unsigned long) pa) & (~PAGE_MASK);
+ unsigned long offset = ((unsigned long) pa) & (~PAGE_MASK);
unsigned long round_sz = (offset + sz + PAGE_SIZE-1) & PAGE_MASK;
- unsigned long va;
- unsigned int psz;
+ unsigned long va;
+ unsigned int psz;
- if (allocate_resource(&shmedia_iomap, res, round_sz,
+ if (allocate_resource(&shmedia_iomap, res, round_sz,
shmedia_iomap.start, shmedia_iomap.end,
PAGE_SIZE, NULL, NULL) != 0) {
- panic("alloc_io_res(%s): cannot occupy\n",
- (res->name != NULL)? res->name: "???");
- }
+ panic("alloc_io_res(%s): cannot occupy\n",
+ (res->name != NULL) ? res->name : "???");
+ }
- va = res->start;
- pa &= PAGE_MASK;
+ va = res->start;
+ pa &= PAGE_MASK;
psz = (res->end - res->start + (PAGE_SIZE - 1)) / PAGE_SIZE;
- /* log at boot time ... */
- printk("mapioaddr: %6s [%2d page%s] va 0x%08lx pa 0x%08x\n",
- ((res->name != NULL) ? res->name : "???"),
- psz, psz == 1 ? " " : "s", va, pa);
-
- for (psz = res->end - res->start + 1; psz != 0; psz -= PAGE_SIZE) {
- shmedia_mapioaddr(pa, va);
- va += PAGE_SIZE;
- pa += PAGE_SIZE;
- }
-
- res->start += offset;
- res->end = res->start + sz - 1; /* not strictly necessary.. */
+ for (psz = res->end - res->start + 1; psz != 0; psz -= PAGE_SIZE) {
+ shmedia_mapioaddr(pa, va, flags);
+ va += PAGE_SIZE;
+ pa += PAGE_SIZE;
+ }
- return res->start;
+ return (void __iomem *)(unsigned long)(res->start + offset);
}
static void shmedia_free_io(struct resource *res)
@@ -249,14 +173,12 @@ static void shmedia_free_io(struct resource *res)
static __init_refok void *sh64_get_page(void)
{
- extern int after_bootmem;
void *page;
- if (after_bootmem) {
- page = (void *)get_zeroed_page(GFP_ATOMIC);
- } else {
+ if (after_bootmem)
+ page = (void *)get_zeroed_page(GFP_KERNEL);
+ else
page = alloc_bootmem_pages(PAGE_SIZE);
- }
if (!page || ((unsigned long)page & ~PAGE_MASK))
panic("sh64_get_page: Out of memory already?\n");
@@ -264,17 +186,20 @@ static __init_refok void *sh64_get_page(void)
return page;
}
-static void shmedia_mapioaddr(unsigned long pa, unsigned long va)
+static void shmedia_mapioaddr(unsigned long pa, unsigned long va,
+ unsigned long flags)
{
pgd_t *pgdp;
pud_t *pudp;
pmd_t *pmdp;
pte_t *ptep, pte;
pgprot_t prot;
- unsigned long flags = 1; /* 1 = CB0-1 device */
pr_debug("shmedia_mapiopage pa %08lx va %08lx\n", pa, va);
+ if (!flags)
+ flags = 1; /* 1 = CB0-1 device */
+
pgdp = pgd_offset_k(va);
if (pgd_none(*pgdp) || !pgd_present(*pgdp)) {
pudp = (pud_t *)sh64_get_page();
@@ -288,7 +213,7 @@ static void shmedia_mapioaddr(unsigned long pa, unsigned long va)
}
pmdp = pmd_offset(pudp, va);
- if (pmd_none(*pmdp) || !pmd_present(*pmdp) ) {
+ if (pmd_none(*pmdp) || !pmd_present(*pmdp)) {
ptep = (pte_t *)sh64_get_page();
set_pmd(pmdp, __pmd((unsigned long)ptep + _PAGE_TABLE));
}
@@ -336,17 +261,19 @@ static void shmedia_unmapioaddr(unsigned long vaddr)
pte_clear(&init_mm, vaddr, ptep);
}
-unsigned long onchip_remap(unsigned long phys, unsigned long size, const char *name)
+void __iomem *__ioremap(unsigned long offset, unsigned long size,
+ unsigned long flags)
{
- if (size < PAGE_SIZE)
- size = PAGE_SIZE;
+ char name[14];
- return shmedia_alloc_io(phys, size, name);
+ sprintf(name, "phys_%08x", (u32)offset);
+ return shmedia_alloc_io(offset, size, name, flags);
}
-EXPORT_SYMBOL(onchip_remap);
+EXPORT_SYMBOL(__ioremap);
-void onchip_unmap(unsigned long vaddr)
+void __iounmap(void __iomem *virtual)
{
+ unsigned long vaddr = (unsigned long)virtual & PAGE_MASK;
struct resource *res;
unsigned int psz;
@@ -357,10 +284,7 @@ void onchip_unmap(unsigned long vaddr)
return;
}
- psz = (res->end - res->start + (PAGE_SIZE - 1)) / PAGE_SIZE;
-
- printk(KERN_DEBUG "unmapioaddr: %6s [%2d page%s] freed\n",
- res->name, psz, psz == 1 ? " " : "s");
+ psz = (res->end - res->start + (PAGE_SIZE - 1)) / PAGE_SIZE;
shmedia_free_io(res);
@@ -371,9 +295,8 @@ void onchip_unmap(unsigned long vaddr)
kfree(res);
}
}
-EXPORT_SYMBOL(onchip_unmap);
+EXPORT_SYMBOL(__iounmap);
-#ifdef CONFIG_PROC_FS
static int
ioremap_proc_info(char *buf, char **start, off_t fpos, int length, int *eof,
void *data)
@@ -385,7 +308,10 @@ ioremap_proc_info(char *buf, char **start, off_t fpos, int length, int *eof,
for (r = ((struct resource *)data)->child; r != NULL; r = r->sibling) {
if (p + 32 >= e) /* Better than nothing */
break;
- if ((nm = r->name) == 0) nm = "???";
+ nm = r->name;
+ if (nm == NULL)
+ nm = "???";
+
p += sprintf(p, "%08lx-%08lx: %s\n",
(unsigned long)r->start,
(unsigned long)r->end, nm);
@@ -393,14 +319,11 @@ ioremap_proc_info(char *buf, char **start, off_t fpos, int length, int *eof,
return p-buf;
}
-#endif /* CONFIG_PROC_FS */
static int __init register_proc_onchip(void)
{
-#ifdef CONFIG_PROC_FS
- create_proc_read_entry("io_map",0,0, ioremap_proc_info, &shmedia_iomap);
-#endif
+ create_proc_read_entry("io_map", 0, 0, ioremap_proc_info,
+ &shmedia_iomap);
return 0;
}
-
-__initcall(register_proc_onchip);
+late_initcall(register_proc_onchip);
diff --git a/arch/sh/mm/mmap.c b/arch/sh/mm/mmap.c
index 931f4d003fa0..1b5fdfb4e0c2 100644
--- a/arch/sh/mm/mmap.c
+++ b/arch/sh/mm/mmap.c
@@ -1,7 +1,7 @@
/*
* arch/sh/mm/mmap.c
*
- * Copyright (C) 2008 Paul Mundt
+ * Copyright (C) 2008 - 2009 Paul Mundt
*
* 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
@@ -21,9 +21,26 @@ EXPORT_SYMBOL(shm_align_mask);
/*
* To avoid cache aliases, we map the shared page with same color.
*/
-#define COLOUR_ALIGN(addr, pgoff) \
- ((((addr) + shm_align_mask) & ~shm_align_mask) + \
- (((pgoff) << PAGE_SHIFT) & shm_align_mask))
+static inline unsigned long COLOUR_ALIGN(unsigned long addr,
+ unsigned long pgoff)
+{
+ unsigned long base = (addr + shm_align_mask) & ~shm_align_mask;
+ unsigned long off = (pgoff << PAGE_SHIFT) & shm_align_mask;
+
+ return base + off;
+}
+
+static inline unsigned long COLOUR_ALIGN_DOWN(unsigned long addr,
+ unsigned long pgoff)
+{
+ unsigned long base = addr & ~shm_align_mask;
+ unsigned long off = (pgoff << PAGE_SHIFT) & shm_align_mask;
+
+ if (base + off <= addr)
+ return base + off;
+
+ return base - off;
+}
unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
unsigned long len, unsigned long pgoff, unsigned long flags)
@@ -103,6 +120,117 @@ full_search:
addr = COLOUR_ALIGN(addr, pgoff);
}
}
+
+unsigned long
+arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
+ const unsigned long len, const unsigned long pgoff,
+ const unsigned long flags)
+{
+ struct vm_area_struct *vma;
+ struct mm_struct *mm = current->mm;
+ unsigned long addr = addr0;
+ int do_colour_align;
+
+ if (flags & MAP_FIXED) {
+ /* We do not accept a shared mapping if it would violate
+ * cache aliasing constraints.
+ */
+ if ((flags & MAP_SHARED) &&
+ ((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask))
+ return -EINVAL;
+ return addr;
+ }
+
+ if (unlikely(len > TASK_SIZE))
+ return -ENOMEM;
+
+ do_colour_align = 0;
+ if (filp || (flags & MAP_SHARED))
+ do_colour_align = 1;
+
+ /* requesting a specific address */
+ if (addr) {
+ if (do_colour_align)
+ addr = COLOUR_ALIGN(addr, pgoff);
+ else
+ addr = PAGE_ALIGN(addr);
+
+ vma = find_vma(mm, addr);
+ if (TASK_SIZE - len >= addr &&
+ (!vma || addr + len <= vma->vm_start))
+ return addr;
+ }
+
+ /* check if free_area_cache is useful for us */
+ if (len <= mm->cached_hole_size) {
+ mm->cached_hole_size = 0;
+ mm->free_area_cache = mm->mmap_base;
+ }
+
+ /* either no address requested or can't fit in requested address hole */
+ addr = mm->free_area_cache;
+ if (do_colour_align) {
+ unsigned long base = COLOUR_ALIGN_DOWN(addr-len, pgoff);
+
+ addr = base + len;
+ }
+
+ /* make sure it can fit in the remaining address space */
+ if (likely(addr > len)) {
+ vma = find_vma(mm, addr-len);
+ if (!vma || addr <= vma->vm_start) {
+ /* remember the address as a hint for next time */
+ return (mm->free_area_cache = addr-len);
+ }
+ }
+
+ if (unlikely(mm->mmap_base < len))
+ goto bottomup;
+
+ addr = mm->mmap_base-len;
+ if (do_colour_align)
+ addr = COLOUR_ALIGN_DOWN(addr, pgoff);
+
+ do {
+ /*
+ * Lookup failure means no vma is above this address,
+ * else if new region fits below vma->vm_start,
+ * return with success:
+ */
+ vma = find_vma(mm, addr);
+ if (likely(!vma || addr+len <= vma->vm_start)) {
+ /* remember the address as a hint for next time */
+ return (mm->free_area_cache = addr);
+ }
+
+ /* remember the largest hole we saw so far */
+ if (addr + mm->cached_hole_size < vma->vm_start)
+ mm->cached_hole_size = vma->vm_start - addr;
+
+ /* try just below the current vma->vm_start */
+ addr = vma->vm_start-len;
+ if (do_colour_align)
+ addr = COLOUR_ALIGN_DOWN(addr, pgoff);
+ } while (likely(len < vma->vm_start));
+
+bottomup:
+ /*
+ * A failed mmap() very likely causes application failure,
+ * so fall back to the bottom-up function here. This scenario
+ * can happen with large stack limits and large mmap()
+ * allocations.
+ */
+ mm->cached_hole_size = ~0UL;
+ mm->free_area_cache = TASK_UNMAPPED_BASE;
+ addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
+ /*
+ * Restore the topdown base:
+ */
+ mm->free_area_cache = mm->mmap_base;
+ mm->cached_hole_size = ~0UL;
+
+ return addr;
+}
#endif /* CONFIG_MMU */
/*
diff --git a/arch/sh/oprofile/common.c b/arch/sh/oprofile/common.c
index 1b9d4304b3bf..44f4e31c6d63 100644
--- a/arch/sh/oprofile/common.c
+++ b/arch/sh/oprofile/common.c
@@ -109,6 +109,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
case CPU_SH7785:
case CPU_SH7786:
case CPU_SH7723:
+ case CPU_SH7724:
case CPU_SHX3:
lmodel = &op_model_sh4a_ops;
break;
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index cc12cd48bbc5..2185cf946d68 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -93,6 +93,9 @@ config AUDIT_ARCH
config HAVE_SETUP_PER_CPU_AREA
def_bool y if SPARC64
+config HAVE_DYNAMIC_PER_CPU_AREA
+ def_bool y if SPARC64
+
config GENERIC_HARDIRQS_NO__DO_IRQ
bool
def_bool y if SPARC64
diff --git a/arch/sparc/configs/sparc32_defconfig b/arch/sparc/configs/sparc32_defconfig
index 09ab46e4c59d..8bcd27af724b 100644
--- a/arch/sparc/configs/sparc32_defconfig
+++ b/arch/sparc/configs/sparc32_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28
-# Thu Jan 8 16:45:44 2009
+# Linux kernel version: 2.6.30-rc2
+# Fri Apr 17 04:04:46 2009
#
# CONFIG_64BIT is not set
CONFIG_SPARC=y
@@ -30,17 +30,27 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -49,24 +59,28 @@ CONFIG_NAMESPACES=y
# CONFIG_IPC_NS is not set
# CONFIG_USER_NS is not set
# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -75,12 +89,15 @@ CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_PCI_QUIRKS=y
+CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -93,7 +110,6 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -109,11 +125,6 @@ CONFIG_IOSCHED_CFQ=y
CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -144,6 +155,8 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_SUN_PM=y
# CONFIG_SPARC_LED is not set
CONFIG_SERIAL_CONSOLE=y
@@ -159,6 +172,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
# CONFIG_PCCARD is not set
CONFIG_SUN_OPENPROMFS=m
CONFIG_SPARC32_PCI=y
@@ -175,8 +189,6 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NET_NS is not set
-CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -251,6 +263,7 @@ CONFIG_IPV6_TUNNEL=m
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
# CONFIG_DCB is not set
@@ -263,7 +276,6 @@ CONFIG_NET_PKTGEN=m
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
@@ -313,12 +325,16 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -375,8 +391,10 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -398,6 +416,7 @@ CONFIG_SCSI_QLOGICPTI=m
CONFIG_SCSI_SUNESP=y
# CONFIG_SCSI_SRP is not set
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
# CONFIG_ATA is not set
# CONFIG_MD is not set
# CONFIG_FUSION is not set
@@ -413,6 +432,7 @@ CONFIG_SCSI_SUNESP=y
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_DUMMY=m
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -430,6 +450,8 @@ CONFIG_SUNQE=m
# CONFIG_SUNGEM is not set
# CONFIG_CASSINI is not set
# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -448,6 +470,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_E1000 is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_MYRI_SBUS is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
@@ -462,6 +485,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
@@ -471,6 +495,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
@@ -480,6 +505,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_BNX2X is not set
# CONFIG_QLGE is not set
# CONFIG_SFC is not set
+# CONFIG_BE2NET is not set
# CONFIG_TR is not set
#
@@ -487,7 +513,6 @@ CONFIG_CHELSIO_T3_DEPENDS=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
#
# Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -537,7 +562,6 @@ CONFIG_MOUSE_PS2=m
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
@@ -597,6 +621,7 @@ CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=m
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_RAW_DRIVER is not set
@@ -688,7 +713,6 @@ CONFIG_HID=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
@@ -700,7 +724,7 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
#
# CONFIG_USB_GADGET is not set
@@ -750,6 +774,7 @@ CONFIG_RTC_DRV_M48T59=y
# on-CPU RTC drivers
#
# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
@@ -777,6 +802,7 @@ CONFIG_FS_POSIX_ACL=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -786,6 +812,11 @@ CONFIG_AUTOFS4_FS=m
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=m
@@ -820,14 +851,20 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
CONFIG_ROMFS_FS=m
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
@@ -838,7 +875,6 @@ CONFIG_LOCKD=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=m
-# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=m
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -911,6 +947,9 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
# CONFIG_SCHED_DEBUG is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -939,15 +978,7 @@ CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_SYSCTL_SYSCALL_CHECK is not set
-
-#
-# Tracers
-#
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_PAGE_POISONING is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_KGDB=y
@@ -979,10 +1010,12 @@ CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_AUTHENC=y
# CONFIG_CRYPTO_TEST is not set
@@ -1052,6 +1085,7 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
# Compression
#
CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
#
@@ -1059,6 +1093,7 @@ CONFIG_CRYPTO_DEFLATE=y
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
#
# Library routines
@@ -1074,7 +1109,10 @@ CONFIG_CRC32=y
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/sparc/configs/sparc64_defconfig b/arch/sparc/configs/sparc64_defconfig
index ade49941def2..b5d63bd8716e 100644
--- a/arch/sparc/configs/sparc64_defconfig
+++ b/arch/sparc/configs/sparc64_defconfig
@@ -1,13 +1,14 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28
-# Fri Jan 2 18:14:26 2009
+# Linux kernel version: 2.6.30-rc2
+# Fri Apr 17 02:03:07 2009
#
+CONFIG_64BIT=y
CONFIG_SPARC=y
+# CONFIG_SPARC32 is not set
CONFIG_SPARC64=y
CONFIG_ARCH_DEFCONFIG="arch/sparc/configs/sparc64_defconfig"
CONFIG_BITS=64
-CONFIG_64BIT=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_CLOCKEVENTS=y
@@ -22,6 +23,7 @@ CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_MMU=y
CONFIG_ARCH_NO_VIRT_TO_BUS=y
CONFIG_OF=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -36,17 +38,27 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=18
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_RELAY=y
@@ -55,24 +67,28 @@ CONFIG_NAMESPACES=y
# CONFIG_IPC_NS is not set
# CONFIG_USER_NS is not set
# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-# CONFIG_COMPAT_BRK is not set
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -82,6 +98,7 @@ CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_PCI_QUIRKS=y
CONFIG_SLUB_DEBUG=y
+# CONFIG_COMPAT_BRK is not set
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
@@ -91,15 +108,16 @@ CONFIG_TRACEPOINTS=y
CONFIG_OPROFILE=m
CONFIG_HAVE_OPROFILE=y
CONFIG_KPROBES=y
+CONFIG_HAVE_SYSCALL_WRAPPERS=y
CONFIG_KRETPROBES=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_USE_GENERIC_SMP_HELPERS=y
+# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -107,10 +125,8 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_KMOD=y
CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
-CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_BLK_DEV_BSG=y
# CONFIG_BLK_DEV_INTEGRITY is not set
CONFIG_BLOCK_COMPAT=y
@@ -127,11 +143,6 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -185,11 +196,12 @@ CONFIG_SPARSEMEM_VMEMMAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-CONFIG_RESOURCES_64BIT=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=1
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_SCHED_SMT=y
CONFIG_SCHED_MC=y
# CONFIG_PREEMPT_NONE is not set
@@ -210,6 +222,8 @@ CONFIG_ARCH_SUPPORTS_MSI=y
CONFIG_PCI_MSI=y
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
# CONFIG_PCCARD is not set
CONFIG_SUN_OPENPROMFS=m
CONFIG_SPARC64_PCI=y
@@ -229,8 +243,6 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NET_NS is not set
-CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -292,25 +304,7 @@ CONFIG_IPV6_TUNNEL=m
# CONFIG_IPV6_MROUTE is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-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=m
-# CONFIG_IP_DCCP_CCID3_DEBUG is not set
-CONFIG_IP_DCCP_CCID3_RTO=100
-CONFIG_IP_DCCP_TFRC_LIB=m
-
-#
-# DCCP Kernel Hacking
-#
-# CONFIG_IP_DCCP_DEBUG is not set
-# CONFIG_NET_DCCPPROBE 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
@@ -326,6 +320,7 @@ CONFIG_VLAN_8021Q=m
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
# CONFIG_DCB is not set
@@ -334,18 +329,19 @@ CONFIG_VLAN_8021Q=m
#
CONFIG_NET_PKTGEN=m
CONFIG_NET_TCPPROBE=m
+# CONFIG_NET_DROP_MONITOR is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -389,19 +385,27 @@ CONFIG_SUNVDC=m
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_ISL29003 is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
#
# Please see Documentation/ide/ide.txt for help/info on IDE drives
#
+CONFIG_IDE_XFER_MODE=y
CONFIG_IDE_TIMINGS=y
CONFIG_IDE_ATAPI=y
# CONFIG_BLK_DEV_IDE_SATA is not set
@@ -439,6 +443,7 @@ CONFIG_BLK_DEV_ALI15X3=y
# CONFIG_BLK_DEV_JMICRON is not set
# CONFIG_BLK_DEV_SC1200 is not set
# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8172 is not set
# CONFIG_BLK_DEV_IT8213 is not set
# CONFIG_BLK_DEV_IT821X is not set
# CONFIG_BLK_DEV_NS87415 is not set
@@ -506,8 +511,10 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -528,6 +535,7 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_SUNESP is not set
# CONFIG_SCSI_SRP is not set
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
# CONFIG_ATA is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
@@ -536,7 +544,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
CONFIG_MD_RAID10=m
CONFIG_MD_RAID456=m
-# CONFIG_MD_RAID5_RESHAPE is not set
+CONFIG_MD_RAID6_PQ=m
CONFIG_MD_MULTIPATH=m
# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=m
@@ -561,6 +569,7 @@ CONFIG_DM_ZERO=m
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -589,14 +598,16 @@ CONFIG_PHYLIB=m
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=m
-# CONFIG_SUNLANCE is not set
-# CONFIG_HAPPYMEAL is not set
+CONFIG_SUNLANCE=m
+CONFIG_HAPPYMEAL=m
# CONFIG_SUNBMAC is not set
# CONFIG_SUNQE is not set
-# CONFIG_SUNGEM is not set
-CONFIG_CASSINI=m
+CONFIG_SUNGEM=m
+# CONFIG_CASSINI is not set
CONFIG_SUNVNET=m
# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -631,9 +642,10 @@ CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
CONFIG_E1000=m
-# CONFIG_E1000E is not set
+CONFIG_E1000E=m
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_MYRI_SBUS is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
@@ -648,6 +660,7 @@ CONFIG_BNX2=m
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
@@ -657,6 +670,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
CONFIG_NIU=m
@@ -666,6 +680,7 @@ CONFIG_NIU=m
# CONFIG_BNX2X is not set
# CONFIG_QLGE is not set
# CONFIG_SFC is not set
+# CONFIG_BE2NET is not set
# CONFIG_TR is not set
#
@@ -673,7 +688,10 @@ CONFIG_NIU=m
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
#
# USB Network Adapters
@@ -738,7 +756,6 @@ CONFIG_MOUSE_PS2=y
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
@@ -805,6 +822,7 @@ CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=m
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
CONFIG_HW_RANDOM_N2RNG=m
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -867,12 +885,9 @@ CONFIG_I2C_ALGOBIT=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_EEPROM_AT24 is not set
-# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -897,12 +912,14 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_F71882FG is not set
# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
@@ -917,10 +934,14 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 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_PCF8591 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_DME1737 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
@@ -957,10 +978,12 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
#
@@ -1053,6 +1076,7 @@ CONFIG_FB_ATY_GX=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -1141,6 +1165,8 @@ CONFIG_SND_ALI5451=m
# CONFIG_SND_INDIGO is not set
# CONFIG_SND_INDIGOIO is not set
# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_INDIGOIOX is not set
+# CONFIG_SND_INDIGODJX is not set
# CONFIG_SND_EMU10K1 is not set
# CONFIG_SND_EMU10K1X is not set
# CONFIG_SND_ENS1370 is not set
@@ -1197,28 +1223,31 @@ CONFIG_USB_HIDDEV=y
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
+# CONFIG_DRAGONRISE_FF is not set
CONFIG_HID_EZKEY=y
+CONFIG_HID_KYE=y
CONFIG_HID_GYRATION=y
+CONFIG_HID_KENSINGTON=y
CONFIG_HID_LOGITECH=y
# CONFIG_LOGITECH_FF is not set
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+CONFIG_HID_TOPSEED=y
# CONFIG_THRUSTMASTER_FF is not set
# CONFIG_ZEROPLUS_FF is not set
CONFIG_USB_SUPPORT=y
@@ -1247,6 +1276,7 @@ CONFIG_USB_DEVICEFS=y
CONFIG_USB_EHCI_HCD=m
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
@@ -1268,18 +1298,17 @@ CONFIG_USB_UHCI_HCD=m
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
#
#
-# see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
#
CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_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
@@ -1315,7 +1344,6 @@ CONFIG_USB_STORAGE=m
# 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
@@ -1327,6 +1355,11 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_NOP_USB_XCEIV is not set
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1390,6 +1423,7 @@ CONFIG_RTC_DRV_BQ4802=y
CONFIG_RTC_DRV_SUN4V=y
CONFIG_RTC_DRV_STARFIRE=y
# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
@@ -1412,6 +1446,7 @@ CONFIG_EXT2_FS_POSIX_ACL=y
CONFIG_EXT2_FS_SECURITY=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
@@ -1426,6 +1461,7 @@ CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -1435,6 +1471,11 @@ CONFIG_INOTIFY_USER=y
# CONFIG_FUSE_FS is not set
#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
@@ -1460,10 +1501,7 @@ CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_ECRYPT_FS is not set
@@ -1473,6 +1511,7 @@ CONFIG_HUGETLB_PAGE=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1481,6 +1520,7 @@ CONFIG_HUGETLB_PAGE=y
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
@@ -1555,6 +1595,9 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
# CONFIG_SCHED_DEBUG is not set
CONFIG_SCHEDSTATS=y
# CONFIG_TIMER_STATS is not set
@@ -1590,10 +1633,12 @@ CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_NOP_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_RING_BUFFER=y
CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
@@ -1602,18 +1647,21 @@ CONFIG_TRACING=y
# CONFIG_IRQSOFF_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+CONFIG_BLK_DEV_IO_TRACE=y
# CONFIG_FTRACE_STARTUP_TEST is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_DYNAMIC_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_DCFLUSH is not set
# CONFIG_STACK_DEBUG is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
#
# Security options
@@ -1642,10 +1690,12 @@ CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_AUTHENC=y
CONFIG_CRYPTO_TEST=m
@@ -1715,6 +1765,7 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
# Compression
#
CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
#
@@ -1723,11 +1774,13 @@ CONFIG_CRYPTO_DEFLATE=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_BINARY_PRINTF=y
#
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
# CONFIG_CRC_T10DIF is not set
@@ -1737,8 +1790,11 @@ CONFIG_CRC32=y
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
diff --git a/arch/sparc/include/asm/atomic_32.h b/arch/sparc/include/asm/atomic_32.h
index ce465975a6a5..bb91b1248cd1 100644
--- a/arch/sparc/include/asm/atomic_32.h
+++ b/arch/sparc/include/asm/atomic_32.h
@@ -15,6 +15,8 @@
#ifdef __KERNEL__
+#include <asm/system.h>
+
#define ATOMIC_INIT(i) { (i) }
extern int __atomic_add_return(int, atomic_t *);
diff --git a/arch/sparc/include/asm/cpudata_64.h b/arch/sparc/include/asm/cpudata_64.h
index a11b89ee9ef8..926397d345ff 100644
--- a/arch/sparc/include/asm/cpudata_64.h
+++ b/arch/sparc/include/asm/cpudata_64.h
@@ -6,9 +6,6 @@
#ifndef _SPARC64_CPUDATA_H
#define _SPARC64_CPUDATA_H
-#include <asm/hypervisor.h>
-#include <asm/asi.h>
-
#ifndef __ASSEMBLY__
#include <linux/percpu.h>
@@ -38,202 +35,10 @@ DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data);
#define cpu_data(__cpu) per_cpu(__cpu_data, (__cpu))
#define local_cpu_data() __get_cpu_var(__cpu_data)
-/* Trap handling code needs to get at a few critical values upon
- * trap entry and to process TSB misses. These cannot be in the
- * per_cpu() area as we really need to lock them into the TLB and
- * thus make them part of the main kernel image. As a result we
- * try to make this as small as possible.
- *
- * This is padded out and aligned to 64-bytes to avoid false sharing
- * on SMP.
- */
-
-/* If you modify the size of this structure, please update
- * TRAP_BLOCK_SZ_SHIFT below.
- */
-struct thread_info;
-struct trap_per_cpu {
-/* D-cache line 1: Basic thread information, cpu and device mondo queues */
- struct thread_info *thread;
- unsigned long pgd_paddr;
- unsigned long cpu_mondo_pa;
- unsigned long dev_mondo_pa;
-
-/* D-cache line 2: Error Mondo Queue and kernel buffer pointers */
- unsigned long resum_mondo_pa;
- unsigned long resum_kernel_buf_pa;
- unsigned long nonresum_mondo_pa;
- unsigned long nonresum_kernel_buf_pa;
-
-/* Dcache lines 3, 4, 5, and 6: Hypervisor Fault Status */
- struct hv_fault_status fault_info;
-
-/* Dcache line 7: Physical addresses of CPU send mondo block and CPU list. */
- unsigned long cpu_mondo_block_pa;
- unsigned long cpu_list_pa;
- unsigned long tsb_huge;
- unsigned long tsb_huge_temp;
-
-/* Dcache line 8: IRQ work list, and keep trap_block a power-of-2 in size. */
- unsigned long irq_worklist_pa;
- unsigned int cpu_mondo_qmask;
- unsigned int dev_mondo_qmask;
- unsigned int resum_qmask;
- unsigned int nonresum_qmask;
- void *hdesc;
-} __attribute__((aligned(64)));
-extern struct trap_per_cpu trap_block[NR_CPUS];
-extern void init_cur_cpu_trap(struct thread_info *);
-extern void setup_tba(void);
-extern int ncpus_probed;
extern const struct seq_operations cpuinfo_op;
-extern unsigned long real_hard_smp_processor_id(void);
-
-struct cpuid_patch_entry {
- unsigned int addr;
- unsigned int cheetah_safari[4];
- unsigned int cheetah_jbus[4];
- unsigned int starfire[4];
- unsigned int sun4v[4];
-};
-extern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end;
-
-struct sun4v_1insn_patch_entry {
- unsigned int addr;
- unsigned int insn;
-};
-extern struct sun4v_1insn_patch_entry __sun4v_1insn_patch,
- __sun4v_1insn_patch_end;
-
-struct sun4v_2insn_patch_entry {
- unsigned int addr;
- unsigned int insns[2];
-};
-extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch,
- __sun4v_2insn_patch_end;
-
#endif /* !(__ASSEMBLY__) */
-#define TRAP_PER_CPU_THREAD 0x00
-#define TRAP_PER_CPU_PGD_PADDR 0x08
-#define TRAP_PER_CPU_CPU_MONDO_PA 0x10
-#define TRAP_PER_CPU_DEV_MONDO_PA 0x18
-#define TRAP_PER_CPU_RESUM_MONDO_PA 0x20
-#define TRAP_PER_CPU_RESUM_KBUF_PA 0x28
-#define TRAP_PER_CPU_NONRESUM_MONDO_PA 0x30
-#define TRAP_PER_CPU_NONRESUM_KBUF_PA 0x38
-#define TRAP_PER_CPU_FAULT_INFO 0x40
-#define TRAP_PER_CPU_CPU_MONDO_BLOCK_PA 0xc0
-#define TRAP_PER_CPU_CPU_LIST_PA 0xc8
-#define TRAP_PER_CPU_TSB_HUGE 0xd0
-#define TRAP_PER_CPU_TSB_HUGE_TEMP 0xd8
-#define TRAP_PER_CPU_IRQ_WORKLIST_PA 0xe0
-#define TRAP_PER_CPU_CPU_MONDO_QMASK 0xe8
-#define TRAP_PER_CPU_DEV_MONDO_QMASK 0xec
-#define TRAP_PER_CPU_RESUM_QMASK 0xf0
-#define TRAP_PER_CPU_NONRESUM_QMASK 0xf4
-
-#define TRAP_BLOCK_SZ_SHIFT 8
-
-#include <asm/scratchpad.h>
-
-#define __GET_CPUID(REG) \
- /* Spitfire implementation (default). */ \
-661: ldxa [%g0] ASI_UPA_CONFIG, REG; \
- srlx REG, 17, REG; \
- and REG, 0x1f, REG; \
- nop; \
- .section .cpuid_patch, "ax"; \
- /* Instruction location. */ \
- .word 661b; \
- /* Cheetah Safari implementation. */ \
- ldxa [%g0] ASI_SAFARI_CONFIG, REG; \
- srlx REG, 17, REG; \
- and REG, 0x3ff, REG; \
- nop; \
- /* Cheetah JBUS implementation. */ \
- ldxa [%g0] ASI_JBUS_CONFIG, REG; \
- srlx REG, 17, REG; \
- and REG, 0x1f, REG; \
- nop; \
- /* Starfire implementation. */ \
- sethi %hi(0x1fff40000d0 >> 9), REG; \
- sllx REG, 9, REG; \
- or REG, 0xd0, REG; \
- lduwa [REG] ASI_PHYS_BYPASS_EC_E, REG;\
- /* sun4v implementation. */ \
- mov SCRATCHPAD_CPUID, REG; \
- ldxa [REG] ASI_SCRATCHPAD, REG; \
- nop; \
- nop; \
- .previous;
-
-#ifdef CONFIG_SMP
-
-#define TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
- __GET_CPUID(TMP) \
- sethi %hi(trap_block), DEST; \
- sllx TMP, TRAP_BLOCK_SZ_SHIFT, TMP; \
- or DEST, %lo(trap_block), DEST; \
- add DEST, TMP, DEST; \
-
-/* Clobbers TMP, current address space PGD phys address into DEST. */
-#define TRAP_LOAD_PGD_PHYS(DEST, TMP) \
- TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
- ldx [DEST + TRAP_PER_CPU_PGD_PADDR], DEST;
-
-/* Clobbers TMP, loads local processor's IRQ work area into DEST. */
-#define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP) \
- TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
- add DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST;
-
-/* Clobbers TMP, loads DEST with current thread info pointer. */
-#define TRAP_LOAD_THREAD_REG(DEST, TMP) \
- TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
- ldx [DEST + TRAP_PER_CPU_THREAD], DEST;
-
-/* Given the current thread info pointer in THR, load the per-cpu
- * area base of the current processor into DEST. REG1, REG2, and REG3 are
- * clobbered.
- *
- * You absolutely cannot use DEST as a temporary in this code. The
- * reason is that traps can happen during execution, and return from
- * trap will load the fully resolved DEST per-cpu base. This can corrupt
- * the calculations done by the macro mid-stream.
- */
-#define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3) \
- lduh [THR + TI_CPU], REG1; \
- sethi %hi(__per_cpu_shift), REG3; \
- sethi %hi(__per_cpu_base), REG2; \
- ldx [REG3 + %lo(__per_cpu_shift)], REG3; \
- ldx [REG2 + %lo(__per_cpu_base)], REG2; \
- sllx REG1, REG3, REG3; \
- add REG3, REG2, DEST;
-
-#else
-
-#define TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
- sethi %hi(trap_block), DEST; \
- or DEST, %lo(trap_block), DEST; \
-
-/* Uniprocessor versions, we know the cpuid is zero. */
-#define TRAP_LOAD_PGD_PHYS(DEST, TMP) \
- TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
- ldx [DEST + TRAP_PER_CPU_PGD_PADDR], DEST;
-
-/* Clobbers TMP, loads local processor's IRQ work area into DEST. */
-#define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP) \
- TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
- add DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST;
-
-#define TRAP_LOAD_THREAD_REG(DEST, TMP) \
- TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
- ldx [DEST + TRAP_PER_CPU_THREAD], DEST;
-
-/* No per-cpu areas on uniprocessor, so no need to load DEST. */
-#define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3)
-
-#endif /* !(CONFIG_SMP) */
+#include <asm/trap_block.h>
#endif /* _SPARC64_CPUDATA_H */
diff --git a/arch/sparc/include/asm/mdesc.h b/arch/sparc/include/asm/mdesc.h
index 1acc7272e537..9faa046713fb 100644
--- a/arch/sparc/include/asm/mdesc.h
+++ b/arch/sparc/include/asm/mdesc.h
@@ -71,7 +71,8 @@ struct mdesc_notifier_client {
extern void mdesc_register_notifier(struct mdesc_notifier_client *client);
-extern void mdesc_fill_in_cpu_data(cpumask_t mask);
+extern void mdesc_fill_in_cpu_data(cpumask_t *mask);
+extern void mdesc_populate_present_mask(cpumask_t *mask);
extern void sun4v_mdesc_init(void);
diff --git a/arch/sparc/include/asm/parport.h b/arch/sparc/include/asm/parport.h
index dff3f0253aa8..ff9ead640c4a 100644
--- a/arch/sparc/include/asm/parport.h
+++ b/arch/sparc/include/asm/parport.h
@@ -117,7 +117,7 @@ static int __devinit ecpp_probe(struct of_device *op, const struct of_device_id
if (!strcmp(parent->name, "dma")) {
p = parport_pc_probe_port(base, base + 0x400,
op->irqs[0], PARPORT_DMA_NOFIFO,
- op->dev.parent->parent);
+ op->dev.parent->parent, 0);
if (!p)
return -ENOMEM;
dev_set_drvdata(&op->dev, p);
@@ -168,7 +168,8 @@ static int __devinit ecpp_probe(struct of_device *op, const struct of_device_id
p = parport_pc_probe_port(base, base + 0x400,
op->irqs[0],
slot,
- op->dev.parent);
+ op->dev.parent,
+ 0);
err = -ENOMEM;
if (!p)
goto out_disable_irq;
diff --git a/arch/sparc/include/asm/percpu_64.h b/arch/sparc/include/asm/percpu_64.h
index bee64593023e..007aafb4ae97 100644
--- a/arch/sparc/include/asm/percpu_64.h
+++ b/arch/sparc/include/asm/percpu_64.h
@@ -7,20 +7,16 @@ register unsigned long __local_per_cpu_offset asm("g5");
#ifdef CONFIG_SMP
-extern void real_setup_per_cpu_areas(void);
+#include <asm/trap_block.h>
-extern unsigned long __per_cpu_base;
-extern unsigned long __per_cpu_shift;
#define __per_cpu_offset(__cpu) \
- (__per_cpu_base + ((unsigned long)(__cpu) << __per_cpu_shift))
+ (trap_block[(__cpu)].__per_cpu_base)
#define per_cpu_offset(x) (__per_cpu_offset(x))
#define __my_cpu_offset __local_per_cpu_offset
#else /* ! SMP */
-#define real_setup_per_cpu_areas() do { } while (0)
-
#endif /* SMP */
#include <asm-generic/percpu.h>
diff --git a/arch/sparc/include/asm/prom.h b/arch/sparc/include/asm/prom.h
index 900d44714f8d..be8d7aaeb60d 100644
--- a/arch/sparc/include/asm/prom.h
+++ b/arch/sparc/include/asm/prom.h
@@ -86,6 +86,8 @@ extern int of_node_to_nid(struct device_node *dp);
#endif
extern void prom_build_devicetree(void);
+extern void of_populate_present_mask(void);
+extern void of_fill_in_cpu_data(void);
/* Dummy ref counting routines - to be implemented later */
static inline struct device_node *of_node_get(struct device_node *node)
diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h
index 639ac805448a..65865726b283 100644
--- a/arch/sparc/include/asm/thread_info_64.h
+++ b/arch/sparc/include/asm/thread_info_64.h
@@ -102,8 +102,8 @@ struct thread_info {
#define TI_KERN_CNTD1 0x00000488
#define TI_PCR 0x00000490
#define TI_RESTART_BLOCK 0x00000498
-#define TI_KUNA_REGS 0x000004c0
-#define TI_KUNA_INSN 0x000004c8
+#define TI_KUNA_REGS 0x000004c8
+#define TI_KUNA_INSN 0x000004d0
#define TI_FPREGS 0x00000500
/* We embed this in the uppermost byte of thread_info->flags */
diff --git a/arch/sparc/include/asm/trap_block.h b/arch/sparc/include/asm/trap_block.h
new file mode 100644
index 000000000000..7e26b2db6211
--- /dev/null
+++ b/arch/sparc/include/asm/trap_block.h
@@ -0,0 +1,207 @@
+#ifndef _SPARC_TRAP_BLOCK_H
+#define _SPARC_TRAP_BLOCK_H
+
+#include <asm/hypervisor.h>
+#include <asm/asi.h>
+
+#ifndef __ASSEMBLY__
+
+/* Trap handling code needs to get at a few critical values upon
+ * trap entry and to process TSB misses. These cannot be in the
+ * per_cpu() area as we really need to lock them into the TLB and
+ * thus make them part of the main kernel image. As a result we
+ * try to make this as small as possible.
+ *
+ * This is padded out and aligned to 64-bytes to avoid false sharing
+ * on SMP.
+ */
+
+/* If you modify the size of this structure, please update
+ * TRAP_BLOCK_SZ_SHIFT below.
+ */
+struct thread_info;
+struct trap_per_cpu {
+/* D-cache line 1: Basic thread information, cpu and device mondo queues */
+ struct thread_info *thread;
+ unsigned long pgd_paddr;
+ unsigned long cpu_mondo_pa;
+ unsigned long dev_mondo_pa;
+
+/* D-cache line 2: Error Mondo Queue and kernel buffer pointers */
+ unsigned long resum_mondo_pa;
+ unsigned long resum_kernel_buf_pa;
+ unsigned long nonresum_mondo_pa;
+ unsigned long nonresum_kernel_buf_pa;
+
+/* Dcache lines 3, 4, 5, and 6: Hypervisor Fault Status */
+ struct hv_fault_status fault_info;
+
+/* Dcache line 7: Physical addresses of CPU send mondo block and CPU list. */
+ unsigned long cpu_mondo_block_pa;
+ unsigned long cpu_list_pa;
+ unsigned long tsb_huge;
+ unsigned long tsb_huge_temp;
+
+/* Dcache line 8: IRQ work list, and keep trap_block a power-of-2 in size. */
+ unsigned long irq_worklist_pa;
+ unsigned int cpu_mondo_qmask;
+ unsigned int dev_mondo_qmask;
+ unsigned int resum_qmask;
+ unsigned int nonresum_qmask;
+ unsigned long __per_cpu_base;
+} __attribute__((aligned(64)));
+extern struct trap_per_cpu trap_block[NR_CPUS];
+extern void init_cur_cpu_trap(struct thread_info *);
+extern void setup_tba(void);
+extern int ncpus_probed;
+
+extern unsigned long real_hard_smp_processor_id(void);
+
+struct cpuid_patch_entry {
+ unsigned int addr;
+ unsigned int cheetah_safari[4];
+ unsigned int cheetah_jbus[4];
+ unsigned int starfire[4];
+ unsigned int sun4v[4];
+};
+extern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end;
+
+struct sun4v_1insn_patch_entry {
+ unsigned int addr;
+ unsigned int insn;
+};
+extern struct sun4v_1insn_patch_entry __sun4v_1insn_patch,
+ __sun4v_1insn_patch_end;
+
+struct sun4v_2insn_patch_entry {
+ unsigned int addr;
+ unsigned int insns[2];
+};
+extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch,
+ __sun4v_2insn_patch_end;
+
+
+#endif /* !(__ASSEMBLY__) */
+
+#define TRAP_PER_CPU_THREAD 0x00
+#define TRAP_PER_CPU_PGD_PADDR 0x08
+#define TRAP_PER_CPU_CPU_MONDO_PA 0x10
+#define TRAP_PER_CPU_DEV_MONDO_PA 0x18
+#define TRAP_PER_CPU_RESUM_MONDO_PA 0x20
+#define TRAP_PER_CPU_RESUM_KBUF_PA 0x28
+#define TRAP_PER_CPU_NONRESUM_MONDO_PA 0x30
+#define TRAP_PER_CPU_NONRESUM_KBUF_PA 0x38
+#define TRAP_PER_CPU_FAULT_INFO 0x40
+#define TRAP_PER_CPU_CPU_MONDO_BLOCK_PA 0xc0
+#define TRAP_PER_CPU_CPU_LIST_PA 0xc8
+#define TRAP_PER_CPU_TSB_HUGE 0xd0
+#define TRAP_PER_CPU_TSB_HUGE_TEMP 0xd8
+#define TRAP_PER_CPU_IRQ_WORKLIST_PA 0xe0
+#define TRAP_PER_CPU_CPU_MONDO_QMASK 0xe8
+#define TRAP_PER_CPU_DEV_MONDO_QMASK 0xec
+#define TRAP_PER_CPU_RESUM_QMASK 0xf0
+#define TRAP_PER_CPU_NONRESUM_QMASK 0xf4
+#define TRAP_PER_CPU_PER_CPU_BASE 0xf8
+
+#define TRAP_BLOCK_SZ_SHIFT 8
+
+#include <asm/scratchpad.h>
+
+#define __GET_CPUID(REG) \
+ /* Spitfire implementation (default). */ \
+661: ldxa [%g0] ASI_UPA_CONFIG, REG; \
+ srlx REG, 17, REG; \
+ and REG, 0x1f, REG; \
+ nop; \
+ .section .cpuid_patch, "ax"; \
+ /* Instruction location. */ \
+ .word 661b; \
+ /* Cheetah Safari implementation. */ \
+ ldxa [%g0] ASI_SAFARI_CONFIG, REG; \
+ srlx REG, 17, REG; \
+ and REG, 0x3ff, REG; \
+ nop; \
+ /* Cheetah JBUS implementation. */ \
+ ldxa [%g0] ASI_JBUS_CONFIG, REG; \
+ srlx REG, 17, REG; \
+ and REG, 0x1f, REG; \
+ nop; \
+ /* Starfire implementation. */ \
+ sethi %hi(0x1fff40000d0 >> 9), REG; \
+ sllx REG, 9, REG; \
+ or REG, 0xd0, REG; \
+ lduwa [REG] ASI_PHYS_BYPASS_EC_E, REG;\
+ /* sun4v implementation. */ \
+ mov SCRATCHPAD_CPUID, REG; \
+ ldxa [REG] ASI_SCRATCHPAD, REG; \
+ nop; \
+ nop; \
+ .previous;
+
+#ifdef CONFIG_SMP
+
+#define TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
+ __GET_CPUID(TMP) \
+ sethi %hi(trap_block), DEST; \
+ sllx TMP, TRAP_BLOCK_SZ_SHIFT, TMP; \
+ or DEST, %lo(trap_block), DEST; \
+ add DEST, TMP, DEST; \
+
+/* Clobbers TMP, current address space PGD phys address into DEST. */
+#define TRAP_LOAD_PGD_PHYS(DEST, TMP) \
+ TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
+ ldx [DEST + TRAP_PER_CPU_PGD_PADDR], DEST;
+
+/* Clobbers TMP, loads local processor's IRQ work area into DEST. */
+#define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP) \
+ TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
+ add DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST;
+
+/* Clobbers TMP, loads DEST with current thread info pointer. */
+#define TRAP_LOAD_THREAD_REG(DEST, TMP) \
+ TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
+ ldx [DEST + TRAP_PER_CPU_THREAD], DEST;
+
+/* Given the current thread info pointer in THR, load the per-cpu
+ * area base of the current processor into DEST. REG1, REG2, and REG3 are
+ * clobbered.
+ *
+ * You absolutely cannot use DEST as a temporary in this code. The
+ * reason is that traps can happen during execution, and return from
+ * trap will load the fully resolved DEST per-cpu base. This can corrupt
+ * the calculations done by the macro mid-stream.
+ */
+#define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3) \
+ lduh [THR + TI_CPU], REG1; \
+ sethi %hi(trap_block), REG2; \
+ sllx REG1, TRAP_BLOCK_SZ_SHIFT, REG1; \
+ or REG2, %lo(trap_block), REG2; \
+ add REG2, REG1, REG2; \
+ ldx [REG2 + TRAP_PER_CPU_PER_CPU_BASE], DEST;
+
+#else
+
+#define TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
+ sethi %hi(trap_block), DEST; \
+ or DEST, %lo(trap_block), DEST; \
+
+/* Uniprocessor versions, we know the cpuid is zero. */
+#define TRAP_LOAD_PGD_PHYS(DEST, TMP) \
+ TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
+ ldx [DEST + TRAP_PER_CPU_PGD_PADDR], DEST;
+
+/* Clobbers TMP, loads local processor's IRQ work area into DEST. */
+#define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP) \
+ TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
+ add DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST;
+
+#define TRAP_LOAD_THREAD_REG(DEST, TMP) \
+ TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
+ ldx [DEST + TRAP_PER_CPU_THREAD], DEST;
+
+/* No per-cpu areas on uniprocessor, so no need to load DEST. */
+#define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3)
+
+#endif /* !(CONFIG_SMP) */
+
+#endif /* _SPARC_TRAP_BLOCK_H */
diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c
index 90350f838f05..4a700f4b79ce 100644
--- a/arch/sparc/kernel/ds.c
+++ b/arch/sparc/kernel/ds.c
@@ -544,7 +544,8 @@ static int __cpuinit dr_cpu_configure(struct ds_info *dp,
resp_len, ncpus, mask,
DR_CPU_STAT_CONFIGURED);
- mdesc_fill_in_cpu_data(*mask);
+ mdesc_populate_present_mask(mask);
+ mdesc_fill_in_cpu_data(mask);
for_each_cpu_mask(cpu, *mask) {
int err;
diff --git a/arch/sparc/kernel/head_32.S b/arch/sparc/kernel/head_32.S
index f0b4b516304f..6b4d8acc4c83 100644
--- a/arch/sparc/kernel/head_32.S
+++ b/arch/sparc/kernel/head_32.S
@@ -72,7 +72,7 @@ sun4e_notsup:
.align 4
/* The Sparc trap table, bootloader gives us control at _start. */
- .section .text.head,"ax"
+ __HEAD
.globl start, _stext, _start, __stext
.globl trapbase
_start: /* danger danger */
@@ -735,7 +735,7 @@ go_to_highmem:
nop
/* The code above should be at beginning and we have to take care about
- * short jumps, as branching to .text.init section from .text is usually
+ * short jumps, as branching to .init.text section from .text is usually
* impossible */
__INIT
/* Acquire boot time privileged register values, this will help debugging.
diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S
index 3a1b7bf03cff..f8f21050448b 100644
--- a/arch/sparc/kernel/head_64.S
+++ b/arch/sparc/kernel/head_64.S
@@ -467,7 +467,7 @@ jump_to_sun4u_init:
jmpl %g2 + %g0, %g0
nop
- .section .text.init.refok
+ __REF
sun4u_init:
BRANCH_IF_SUN4V(g1, sun4v_init)
@@ -641,28 +641,6 @@ tlb_fixup_done:
/* Not reached... */
1:
- /* If we boot on a non-zero cpu, all of the per-cpu
- * variable references we make before setting up the
- * per-cpu areas will use a bogus offset. Put a
- * compensating factor into __per_cpu_base to handle
- * this cleanly.
- *
- * What the per-cpu code calculates is:
- *
- * __per_cpu_base + (cpu << __per_cpu_shift)
- *
- * These two variables are zero initially, so to
- * make it all cancel out to zero we need to put
- * "0 - (cpu << 0)" into __per_cpu_base so that the
- * above formula evaluates to zero.
- *
- * We cannot even perform a printk() until this stuff
- * is setup as that calls cpu_clock() which uses
- * per-cpu variables.
- */
- sub %g0, %o0, %o1
- sethi %hi(__per_cpu_base), %o2
- stx %o1, [%o2 + %lo(__per_cpu_base)]
#else
mov 0, %o0
#endif
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c
index 5deabe921a47..e5e78f9cfc95 100644
--- a/arch/sparc/kernel/irq_64.c
+++ b/arch/sparc/kernel/irq_64.c
@@ -318,10 +318,12 @@ static void sun4u_irq_enable(unsigned int virt_irq)
}
}
-static void sun4u_set_affinity(unsigned int virt_irq,
+static int sun4u_set_affinity(unsigned int virt_irq,
const struct cpumask *mask)
{
sun4u_irq_enable(virt_irq);
+
+ return 0;
}
/* Don't do anything. The desc->status check for IRQ_DISABLED in
@@ -377,7 +379,7 @@ static void sun4v_irq_enable(unsigned int virt_irq)
ino, err);
}
-static void sun4v_set_affinity(unsigned int virt_irq,
+static int sun4v_set_affinity(unsigned int virt_irq,
const struct cpumask *mask)
{
unsigned int ino = virt_irq_table[virt_irq].dev_ino;
@@ -388,6 +390,8 @@ static void sun4v_set_affinity(unsigned int virt_irq,
if (err != HV_EOK)
printk(KERN_ERR "sun4v_intr_settarget(%x,%lu): "
"err(%d)\n", ino, cpuid, err);
+
+ return 0;
}
static void sun4v_irq_disable(unsigned int virt_irq)
@@ -445,7 +449,7 @@ static void sun4v_virq_enable(unsigned int virt_irq)
dev_handle, dev_ino, err);
}
-static void sun4v_virt_set_affinity(unsigned int virt_irq,
+static int sun4v_virt_set_affinity(unsigned int virt_irq,
const struct cpumask *mask)
{
unsigned long cpuid, dev_handle, dev_ino;
@@ -461,6 +465,8 @@ static void sun4v_virt_set_affinity(unsigned int virt_irq,
printk(KERN_ERR "sun4v_vintr_set_target(%lx,%lx,%lu): "
"err(%d)\n",
dev_handle, dev_ino, cpuid, err);
+
+ return 0;
}
static void sun4v_virq_disable(unsigned int virt_irq)
diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c
index 6ce5d2598a09..adf5f273868a 100644
--- a/arch/sparc/kernel/ldc.c
+++ b/arch/sparc/kernel/ldc.c
@@ -1183,8 +1183,7 @@ out_free_txq:
free_queue(lp->tx_num_entries, lp->tx_base);
out_free_mssbuf:
- if (mssbuf)
- kfree(mssbuf);
+ kfree(mssbuf);
out_free_iommu:
ldc_iommu_release(lp);
@@ -1217,8 +1216,7 @@ void ldc_free(struct ldc_channel *lp)
hlist_del(&lp->list);
- if (lp->mssbuf)
- kfree(lp->mssbuf);
+ kfree(lp->mssbuf);
ldc_iommu_release(lp);
diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c
index f0e6ed23a468..938da19dc065 100644
--- a/arch/sparc/kernel/mdesc.c
+++ b/arch/sparc/kernel/mdesc.c
@@ -574,7 +574,7 @@ static void __init report_platform_properties(void)
mdesc_release(hp);
}
-static void __devinit fill_in_one_cache(cpuinfo_sparc *c,
+static void __cpuinit fill_in_one_cache(cpuinfo_sparc *c,
struct mdesc_handle *hp,
u64 mp)
{
@@ -619,8 +619,7 @@ static void __devinit fill_in_one_cache(cpuinfo_sparc *c,
}
}
-static void __devinit mark_core_ids(struct mdesc_handle *hp, u64 mp,
- int core_id)
+static void __cpuinit mark_core_ids(struct mdesc_handle *hp, u64 mp, int core_id)
{
u64 a;
@@ -653,7 +652,7 @@ static void __devinit mark_core_ids(struct mdesc_handle *hp, u64 mp,
}
}
-static void __devinit set_core_ids(struct mdesc_handle *hp)
+static void __cpuinit set_core_ids(struct mdesc_handle *hp)
{
int idx;
u64 mp;
@@ -678,8 +677,7 @@ static void __devinit set_core_ids(struct mdesc_handle *hp)
}
}
-static void __devinit mark_proc_ids(struct mdesc_handle *hp, u64 mp,
- int proc_id)
+static void __cpuinit mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id)
{
u64 a;
@@ -698,8 +696,7 @@ static void __devinit mark_proc_ids(struct mdesc_handle *hp, u64 mp,
}
}
-static void __devinit __set_proc_ids(struct mdesc_handle *hp,
- const char *exec_unit_name)
+static void __cpuinit __set_proc_ids(struct mdesc_handle *hp, const char *exec_unit_name)
{
int idx;
u64 mp;
@@ -720,13 +717,13 @@ static void __devinit __set_proc_ids(struct mdesc_handle *hp,
}
}
-static void __devinit set_proc_ids(struct mdesc_handle *hp)
+static void __cpuinit set_proc_ids(struct mdesc_handle *hp)
{
__set_proc_ids(hp, "exec_unit");
__set_proc_ids(hp, "exec-unit");
}
-static void __devinit get_one_mondo_bits(const u64 *p, unsigned int *mask,
+static void __cpuinit get_one_mondo_bits(const u64 *p, unsigned int *mask,
unsigned char def)
{
u64 val;
@@ -745,7 +742,7 @@ use_default:
*mask = ((1U << def) * 64U) - 1U;
}
-static void __devinit get_mondo_data(struct mdesc_handle *hp, u64 mp,
+static void __cpuinit get_mondo_data(struct mdesc_handle *hp, u64 mp,
struct trap_per_cpu *tb)
{
const u64 *val;
@@ -763,23 +760,15 @@ static void __devinit get_mondo_data(struct mdesc_handle *hp, u64 mp,
get_one_mondo_bits(val, &tb->nonresum_qmask, 2);
}
-void __cpuinit mdesc_fill_in_cpu_data(cpumask_t mask)
+static void * __cpuinit mdesc_iterate_over_cpus(void *(*func)(struct mdesc_handle *, u64, int, void *), void *arg, cpumask_t *mask)
{
struct mdesc_handle *hp = mdesc_grab();
+ void *ret = NULL;
u64 mp;
- ncpus_probed = 0;
mdesc_for_each_node_by_name(hp, mp, "cpu") {
const u64 *id = mdesc_get_property(hp, mp, "id", NULL);
- const u64 *cfreq = mdesc_get_property(hp, mp, "clock-frequency", NULL);
- struct trap_per_cpu *tb;
- cpuinfo_sparc *c;
- int cpuid;
- u64 a;
-
- ncpus_probed++;
-
- cpuid = *id;
+ int cpuid = *id;
#ifdef CONFIG_SMP
if (cpuid >= NR_CPUS) {
@@ -788,62 +777,104 @@ void __cpuinit mdesc_fill_in_cpu_data(cpumask_t mask)
cpuid, NR_CPUS);
continue;
}
- if (!cpu_isset(cpuid, mask))
+ if (!cpu_isset(cpuid, *mask))
continue;
-#else
- /* On uniprocessor we only want the values for the
- * real physical cpu the kernel booted onto, however
- * cpu_data() only has one entry at index 0.
- */
- if (cpuid != real_hard_smp_processor_id())
- continue;
- cpuid = 0;
#endif
- c = &cpu_data(cpuid);
- c->clock_tick = *cfreq;
+ ret = func(hp, mp, cpuid, arg);
+ if (ret)
+ goto out;
+ }
+out:
+ mdesc_release(hp);
+ return ret;
+}
- tb = &trap_block[cpuid];
- get_mondo_data(hp, mp, tb);
+static void * __cpuinit record_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg)
+{
+ ncpus_probed++;
+#ifdef CONFIG_SMP
+ set_cpu_present(cpuid, true);
+#endif
+ return NULL;
+}
- mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
- u64 j, t = mdesc_arc_target(hp, a);
- const char *t_name;
+void __cpuinit mdesc_populate_present_mask(cpumask_t *mask)
+{
+ if (tlb_type != hypervisor)
+ return;
- t_name = mdesc_node_name(hp, t);
- if (!strcmp(t_name, "cache")) {
- fill_in_one_cache(c, hp, t);
- continue;
- }
+ ncpus_probed = 0;
+ mdesc_iterate_over_cpus(record_one_cpu, NULL, mask);
+}
- mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_FWD) {
- u64 n = mdesc_arc_target(hp, j);
- const char *n_name;
+static void * __cpuinit fill_in_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg)
+{
+ const u64 *cfreq = mdesc_get_property(hp, mp, "clock-frequency", NULL);
+ struct trap_per_cpu *tb;
+ cpuinfo_sparc *c;
+ u64 a;
- n_name = mdesc_node_name(hp, n);
- if (!strcmp(n_name, "cache"))
- fill_in_one_cache(c, hp, n);
- }
+#ifndef CONFIG_SMP
+ /* On uniprocessor we only want the values for the
+ * real physical cpu the kernel booted onto, however
+ * cpu_data() only has one entry at index 0.
+ */
+ if (cpuid != real_hard_smp_processor_id())
+ return NULL;
+ cpuid = 0;
+#endif
+
+ c = &cpu_data(cpuid);
+ c->clock_tick = *cfreq;
+
+ tb = &trap_block[cpuid];
+ get_mondo_data(hp, mp, tb);
+
+ mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
+ u64 j, t = mdesc_arc_target(hp, a);
+ const char *t_name;
+
+ t_name = mdesc_node_name(hp, t);
+ if (!strcmp(t_name, "cache")) {
+ fill_in_one_cache(c, hp, t);
+ continue;
}
-#ifdef CONFIG_SMP
- cpu_set(cpuid, cpu_present_map);
-#endif
+ mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_FWD) {
+ u64 n = mdesc_arc_target(hp, j);
+ const char *n_name;
- c->core_id = 0;
- c->proc_id = -1;
+ n_name = mdesc_node_name(hp, n);
+ if (!strcmp(n_name, "cache"))
+ fill_in_one_cache(c, hp, n);
+ }
}
+ c->core_id = 0;
+ c->proc_id = -1;
+
+ return NULL;
+}
+
+void __cpuinit mdesc_fill_in_cpu_data(cpumask_t *mask)
+{
+ struct mdesc_handle *hp;
+
+ mdesc_iterate_over_cpus(fill_in_one_cpu, NULL, mask);
+
#ifdef CONFIG_SMP
sparc64_multi_core = 1;
#endif
+ hp = mdesc_grab();
+
set_core_ids(hp);
set_proc_ids(hp);
- smp_fill_in_sib_core_maps();
-
mdesc_release(hp);
+
+ smp_fill_in_sib_core_maps();
}
static ssize_t mdesc_read(struct file *file, char __user *buf,
@@ -887,7 +918,6 @@ void __init sun4v_mdesc_init(void)
{
struct mdesc_handle *hp;
unsigned long len, real_len, status;
- cpumask_t mask;
(void) sun4v_mach_desc(0UL, 0UL, &len);
@@ -911,7 +941,4 @@ void __init sun4v_mdesc_init(void)
cur_mdesc = hp;
report_platform_properties();
-
- cpus_setall(mask);
- mdesc_fill_in_cpu_data(mask);
}
diff --git a/arch/sparc/kernel/of_device_32.c b/arch/sparc/kernel/of_device_32.c
index 0a83bd737654..c8f14c1dc521 100644
--- a/arch/sparc/kernel/of_device_32.c
+++ b/arch/sparc/kernel/of_device_32.c
@@ -246,8 +246,25 @@ static unsigned long of_bus_pci_get_flags(const u32 *addr, unsigned long flags)
static int of_bus_sbus_match(struct device_node *np)
{
- return !strcmp(np->name, "sbus") ||
- !strcmp(np->name, "sbi");
+ struct device_node *dp = np;
+
+ while (dp) {
+ if (!strcmp(dp->name, "sbus") ||
+ !strcmp(dp->name, "sbi"))
+ return 1;
+
+ /* Have a look at use_1to1_mapping(). We're trying
+ * to match SBUS if that's the top-level bus and we
+ * don't have some intervening real bus that provides
+ * ranges based translations.
+ */
+ if (of_find_property(dp, "ranges", NULL) != NULL)
+ break;
+
+ dp = dp->parent;
+ }
+
+ return 0;
}
static void of_bus_sbus_count_cells(struct device_node *child,
diff --git a/arch/sparc/kernel/of_device_64.c b/arch/sparc/kernel/of_device_64.c
index 27381f1baffc..5ac287ac03de 100644
--- a/arch/sparc/kernel/of_device_64.c
+++ b/arch/sparc/kernel/of_device_64.c
@@ -300,8 +300,25 @@ static unsigned long of_bus_pci_get_flags(const u32 *addr, unsigned long flags)
static int of_bus_sbus_match(struct device_node *np)
{
- return !strcmp(np->name, "sbus") ||
- !strcmp(np->name, "sbi");
+ struct device_node *dp = np;
+
+ while (dp) {
+ if (!strcmp(dp->name, "sbus") ||
+ !strcmp(dp->name, "sbi"))
+ return 1;
+
+ /* Have a look at use_1to1_mapping(). We're trying
+ * to match SBUS if that's the top-level bus and we
+ * don't have some intervening real bus that provides
+ * ranges based translations.
+ */
+ if (of_find_property(dp, "ranges", NULL) != NULL)
+ break;
+
+ dp = dp->parent;
+ }
+
+ return 0;
}
static void of_bus_sbus_count_cells(struct device_node *child,
diff --git a/arch/sparc/kernel/prom.h b/arch/sparc/kernel/prom.h
index bb0f0fda6cab..453397fe5e14 100644
--- a/arch/sparc/kernel/prom.h
+++ b/arch/sparc/kernel/prom.h
@@ -22,7 +22,6 @@ static inline int is_root_node(const struct device_node *dp)
extern char *build_path_component(struct device_node *dp);
extern void of_console_init(void);
-extern void of_fill_in_cpu_data(void);
extern unsigned int prom_early_allocated;
diff --git a/arch/sparc/kernel/prom_64.c b/arch/sparc/kernel/prom_64.c
index ca55c7012f77..f65d62385cb4 100644
--- a/arch/sparc/kernel/prom_64.c
+++ b/arch/sparc/kernel/prom_64.c
@@ -374,75 +374,26 @@ static const char *get_mid_prop(void)
return (tlb_type == spitfire ? "upa-portid" : "portid");
}
-struct device_node *of_find_node_by_cpuid(int cpuid)
-{
- struct device_node *dp;
- const char *mid_prop = get_mid_prop();
-
- for_each_node_by_type(dp, "cpu") {
- int id = of_getintprop_default(dp, mid_prop, -1);
- const char *this_mid_prop = mid_prop;
-
- if (id < 0) {
- this_mid_prop = "cpuid";
- id = of_getintprop_default(dp, this_mid_prop, -1);
- }
-
- if (id < 0) {
- prom_printf("OF: Serious problem, cpu lacks "
- "%s property", this_mid_prop);
- prom_halt();
- }
- if (cpuid == id)
- return dp;
- }
- return NULL;
-}
-
-void __init of_fill_in_cpu_data(void)
+static void *of_iterate_over_cpus(void *(*func)(struct device_node *, int, void *), void *arg)
{
struct device_node *dp;
const char *mid_prop;
- if (tlb_type == hypervisor)
- return;
-
mid_prop = get_mid_prop();
- ncpus_probed = 0;
for_each_node_by_type(dp, "cpu") {
int cpuid = of_getintprop_default(dp, mid_prop, -1);
const char *this_mid_prop = mid_prop;
- struct device_node *portid_parent;
- int portid = -1;
+ void *ret;
- portid_parent = NULL;
if (cpuid < 0) {
this_mid_prop = "cpuid";
cpuid = of_getintprop_default(dp, this_mid_prop, -1);
- if (cpuid >= 0) {
- int limit = 2;
-
- portid_parent = dp;
- while (limit--) {
- portid_parent = portid_parent->parent;
- if (!portid_parent)
- break;
- portid = of_getintprop_default(portid_parent,
- "portid", -1);
- if (portid >= 0)
- break;
- }
- }
}
-
if (cpuid < 0) {
prom_printf("OF: Serious problem, cpu lacks "
"%s property", this_mid_prop);
prom_halt();
}
-
- ncpus_probed++;
-
#ifdef CONFIG_SMP
if (cpuid >= NR_CPUS) {
printk(KERN_WARNING "Ignoring CPU %d which is "
@@ -450,79 +401,144 @@ void __init of_fill_in_cpu_data(void)
cpuid, NR_CPUS);
continue;
}
-#else
- /* On uniprocessor we only want the values for the
- * real physical cpu the kernel booted onto, however
- * cpu_data() only has one entry at index 0.
- */
- if (cpuid != real_hard_smp_processor_id())
- continue;
- cpuid = 0;
#endif
+ ret = func(dp, cpuid, arg);
+ if (ret)
+ return ret;
+ }
+ return NULL;
+}
- cpu_data(cpuid).clock_tick =
- of_getintprop_default(dp, "clock-frequency", 0);
-
- if (portid_parent) {
- cpu_data(cpuid).dcache_size =
- of_getintprop_default(dp, "l1-dcache-size",
- 16 * 1024);
- cpu_data(cpuid).dcache_line_size =
- of_getintprop_default(dp, "l1-dcache-line-size",
- 32);
- cpu_data(cpuid).icache_size =
- of_getintprop_default(dp, "l1-icache-size",
- 8 * 1024);
- cpu_data(cpuid).icache_line_size =
- of_getintprop_default(dp, "l1-icache-line-size",
- 32);
- cpu_data(cpuid).ecache_size =
- of_getintprop_default(dp, "l2-cache-size", 0);
- cpu_data(cpuid).ecache_line_size =
- of_getintprop_default(dp, "l2-cache-line-size", 0);
- if (!cpu_data(cpuid).ecache_size ||
- !cpu_data(cpuid).ecache_line_size) {
- cpu_data(cpuid).ecache_size =
- of_getintprop_default(portid_parent,
- "l2-cache-size",
- (4 * 1024 * 1024));
- cpu_data(cpuid).ecache_line_size =
- of_getintprop_default(portid_parent,
- "l2-cache-line-size", 64);
- }
-
- cpu_data(cpuid).core_id = portid + 1;
- cpu_data(cpuid).proc_id = portid;
+static void *check_cpu_node(struct device_node *dp, int cpuid, void *arg)
+{
+ int id = (int) (long) arg;
+
+ if (id == cpuid)
+ return dp;
+ return NULL;
+}
+
+struct device_node *of_find_node_by_cpuid(int cpuid)
+{
+ return of_iterate_over_cpus(check_cpu_node, (void *) (long) cpuid);
+}
+
+static void *record_one_cpu(struct device_node *dp, int cpuid, void *arg)
+{
+ ncpus_probed++;
#ifdef CONFIG_SMP
- sparc64_multi_core = 1;
+ set_cpu_present(cpuid, true);
+ set_cpu_possible(cpuid, true);
#endif
- } else {
- cpu_data(cpuid).dcache_size =
- of_getintprop_default(dp, "dcache-size", 16 * 1024);
- cpu_data(cpuid).dcache_line_size =
- of_getintprop_default(dp, "dcache-line-size", 32);
+ return NULL;
+}
+
+void __init of_populate_present_mask(void)
+{
+ if (tlb_type == hypervisor)
+ return;
+
+ ncpus_probed = 0;
+ of_iterate_over_cpus(record_one_cpu, NULL);
+}
- cpu_data(cpuid).icache_size =
- of_getintprop_default(dp, "icache-size", 16 * 1024);
- cpu_data(cpuid).icache_line_size =
- of_getintprop_default(dp, "icache-line-size", 32);
+static void *fill_in_one_cpu(struct device_node *dp, int cpuid, void *arg)
+{
+ struct device_node *portid_parent = NULL;
+ int portid = -1;
+
+ if (of_find_property(dp, "cpuid", NULL)) {
+ int limit = 2;
+
+ portid_parent = dp;
+ while (limit--) {
+ portid_parent = portid_parent->parent;
+ if (!portid_parent)
+ break;
+ portid = of_getintprop_default(portid_parent,
+ "portid", -1);
+ if (portid >= 0)
+ break;
+ }
+ }
+#ifndef CONFIG_SMP
+ /* On uniprocessor we only want the values for the
+ * real physical cpu the kernel booted onto, however
+ * cpu_data() only has one entry at index 0.
+ */
+ if (cpuid != real_hard_smp_processor_id())
+ return NULL;
+ cpuid = 0;
+#endif
+
+ cpu_data(cpuid).clock_tick =
+ of_getintprop_default(dp, "clock-frequency", 0);
+
+ if (portid_parent) {
+ cpu_data(cpuid).dcache_size =
+ of_getintprop_default(dp, "l1-dcache-size",
+ 16 * 1024);
+ cpu_data(cpuid).dcache_line_size =
+ of_getintprop_default(dp, "l1-dcache-line-size",
+ 32);
+ cpu_data(cpuid).icache_size =
+ of_getintprop_default(dp, "l1-icache-size",
+ 8 * 1024);
+ cpu_data(cpuid).icache_line_size =
+ of_getintprop_default(dp, "l1-icache-line-size",
+ 32);
+ cpu_data(cpuid).ecache_size =
+ of_getintprop_default(dp, "l2-cache-size", 0);
+ cpu_data(cpuid).ecache_line_size =
+ of_getintprop_default(dp, "l2-cache-line-size", 0);
+ if (!cpu_data(cpuid).ecache_size ||
+ !cpu_data(cpuid).ecache_line_size) {
cpu_data(cpuid).ecache_size =
- of_getintprop_default(dp, "ecache-size",
+ of_getintprop_default(portid_parent,
+ "l2-cache-size",
(4 * 1024 * 1024));
cpu_data(cpuid).ecache_line_size =
- of_getintprop_default(dp, "ecache-line-size", 64);
-
- cpu_data(cpuid).core_id = 0;
- cpu_data(cpuid).proc_id = -1;
+ of_getintprop_default(portid_parent,
+ "l2-cache-line-size", 64);
}
+ cpu_data(cpuid).core_id = portid + 1;
+ cpu_data(cpuid).proc_id = portid;
#ifdef CONFIG_SMP
- set_cpu_present(cpuid, true);
- set_cpu_possible(cpuid, true);
+ sparc64_multi_core = 1;
#endif
+ } else {
+ cpu_data(cpuid).dcache_size =
+ of_getintprop_default(dp, "dcache-size", 16 * 1024);
+ cpu_data(cpuid).dcache_line_size =
+ of_getintprop_default(dp, "dcache-line-size", 32);
+
+ cpu_data(cpuid).icache_size =
+ of_getintprop_default(dp, "icache-size", 16 * 1024);
+ cpu_data(cpuid).icache_line_size =
+ of_getintprop_default(dp, "icache-line-size", 32);
+
+ cpu_data(cpuid).ecache_size =
+ of_getintprop_default(dp, "ecache-size",
+ (4 * 1024 * 1024));
+ cpu_data(cpuid).ecache_line_size =
+ of_getintprop_default(dp, "ecache-line-size", 64);
+
+ cpu_data(cpuid).core_id = 0;
+ cpu_data(cpuid).proc_id = -1;
}
+ return NULL;
+}
+
+void __init of_fill_in_cpu_data(void)
+{
+ if (tlb_type == hypervisor)
+ return;
+
+ of_iterate_over_cpus(fill_in_one_cpu, NULL);
+
smp_fill_in_sib_core_maps();
}
diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c
index ff7b591c8946..0fb5789d43c8 100644
--- a/arch/sparc/kernel/prom_common.c
+++ b/arch/sparc/kernel/prom_common.c
@@ -313,6 +313,4 @@ void __init prom_build_devicetree(void)
printk("PROM: Built device tree with %u bytes of memory.\n",
prom_early_allocated);
-
- of_fill_in_cpu_data();
}
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index 708e12a26b05..1de47d2169c8 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -20,7 +20,8 @@
#include <linux/cache.h>
#include <linux/jiffies.h>
#include <linux/profile.h>
-#include <linux/lmb.h>
+#include <linux/bootmem.h>
+#include <linux/vmalloc.h>
#include <linux/cpu.h>
#include <asm/head.h>
@@ -118,9 +119,9 @@ void __cpuinit smp_callin(void)
while (!cpu_isset(cpuid, smp_commenced_mask))
rmb();
- ipi_call_lock();
+ ipi_call_lock_irq();
cpu_set(cpuid, cpu_online_map);
- ipi_call_unlock();
+ ipi_call_unlock_irq();
/* idle thread is expected to have preempt disabled */
preempt_disable();
@@ -278,7 +279,7 @@ static unsigned long kimage_addr_to_ra(void *p)
return kern_base + (val - KERNBASE);
}
-static void __cpuinit ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg)
+static void __cpuinit ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg, void **descrp)
{
extern unsigned long sparc64_ttable_tl0;
extern unsigned long kern_locked_tte_data;
@@ -298,12 +299,12 @@ static void __cpuinit ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread
"hvtramp_descr.\n");
return;
}
+ *descrp = hdesc;
hdesc->cpu = cpu;
hdesc->num_mappings = num_kernel_image_mappings;
tb = &trap_block[cpu];
- tb->hdesc = hdesc;
hdesc->fault_info_va = (unsigned long) &tb->fault_info;
hdesc->fault_info_pa = kimage_addr_to_ra(&tb->fault_info);
@@ -341,12 +342,12 @@ static struct thread_info *cpu_new_thread = NULL;
static int __cpuinit smp_boot_one_cpu(unsigned int cpu)
{
- struct trap_per_cpu *tb = &trap_block[cpu];
unsigned long entry =
(unsigned long)(&sparc64_cpu_startup);
unsigned long cookie =
(unsigned long)(&cpu_new_thread);
struct task_struct *p;
+ void *descr = NULL;
int timeout, ret;
p = fork_idle(cpu);
@@ -359,7 +360,8 @@ static int __cpuinit smp_boot_one_cpu(unsigned int cpu)
#if defined(CONFIG_SUN_LDOMS) && defined(CONFIG_HOTPLUG_CPU)
if (ldom_domaining_enabled)
ldom_startcpu_cpuid(cpu,
- (unsigned long) cpu_new_thread);
+ (unsigned long) cpu_new_thread,
+ &descr);
else
#endif
prom_startcpu_cpuid(cpu, entry, cookie);
@@ -383,10 +385,7 @@ static int __cpuinit smp_boot_one_cpu(unsigned int cpu)
}
cpu_new_thread = NULL;
- if (tb->hdesc) {
- kfree(tb->hdesc);
- tb->hdesc = NULL;
- }
+ kfree(descr);
return ret;
}
@@ -1373,36 +1372,171 @@ void smp_send_stop(void)
{
}
-unsigned long __per_cpu_base __read_mostly;
-unsigned long __per_cpu_shift __read_mostly;
+/**
+ * pcpu_alloc_bootmem - NUMA friendly alloc_bootmem wrapper for percpu
+ * @cpu: cpu to allocate for
+ * @size: size allocation in bytes
+ * @align: alignment
+ *
+ * Allocate @size bytes aligned at @align for cpu @cpu. This wrapper
+ * does the right thing for NUMA regardless of the current
+ * configuration.
+ *
+ * RETURNS:
+ * Pointer to the allocated area on success, NULL on failure.
+ */
+static void * __init pcpu_alloc_bootmem(unsigned int cpu, unsigned long size,
+ unsigned long align)
+{
+ const unsigned long goal = __pa(MAX_DMA_ADDRESS);
+#ifdef CONFIG_NEED_MULTIPLE_NODES
+ int node = cpu_to_node(cpu);
+ void *ptr;
+
+ if (!node_online(node) || !NODE_DATA(node)) {
+ ptr = __alloc_bootmem(size, align, goal);
+ pr_info("cpu %d has no node %d or node-local memory\n",
+ cpu, node);
+ pr_debug("per cpu data for cpu%d %lu bytes at %016lx\n",
+ cpu, size, __pa(ptr));
+ } else {
+ ptr = __alloc_bootmem_node(NODE_DATA(node),
+ size, align, goal);
+ pr_debug("per cpu data for cpu%d %lu bytes on node%d at "
+ "%016lx\n", cpu, size, node, __pa(ptr));
+ }
+ return ptr;
+#else
+ return __alloc_bootmem(size, align, goal);
+#endif
+}
-EXPORT_SYMBOL(__per_cpu_base);
-EXPORT_SYMBOL(__per_cpu_shift);
+static size_t pcpur_size __initdata;
+static void **pcpur_ptrs __initdata;
-void __init real_setup_per_cpu_areas(void)
+static struct page * __init pcpur_get_page(unsigned int cpu, int pageno)
{
- unsigned long paddr, goal, size, i;
- char *ptr;
+ size_t off = (size_t)pageno << PAGE_SHIFT;
- /* Copy section for each CPU (we discard the original) */
- goal = PERCPU_ENOUGH_ROOM;
+ if (off >= pcpur_size)
+ return NULL;
- __per_cpu_shift = PAGE_SHIFT;
- for (size = PAGE_SIZE; size < goal; size <<= 1UL)
- __per_cpu_shift++;
+ return virt_to_page(pcpur_ptrs[cpu] + off);
+}
+
+#define PCPU_CHUNK_SIZE (4UL * 1024UL * 1024UL)
+
+static void __init pcpu_map_range(unsigned long start, unsigned long end,
+ struct page *page)
+{
+ unsigned long pfn = page_to_pfn(page);
+ unsigned long pte_base;
+
+ BUG_ON((pfn<<PAGE_SHIFT)&(PCPU_CHUNK_SIZE - 1UL));
+
+ 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);
+
+ while (start < end) {
+ pgd_t *pgd = pgd_offset_k(start);
+ unsigned long this_end;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ pud = pud_offset(pgd, start);
+ if (pud_none(*pud)) {
+ pmd_t *new;
+
+ new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
+ pud_populate(&init_mm, pud, new);
+ }
+
+ pmd = pmd_offset(pud, start);
+ if (!pmd_present(*pmd)) {
+ pte_t *new;
+
+ new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
+ pmd_populate_kernel(&init_mm, pmd, new);
+ }
- paddr = lmb_alloc(size * NR_CPUS, PAGE_SIZE);
- if (!paddr) {
- prom_printf("Cannot allocate per-cpu memory.\n");
- prom_halt();
+ pte = pte_offset_kernel(pmd, start);
+ this_end = (start + PMD_SIZE) & PMD_MASK;
+ if (this_end > end)
+ this_end = end;
+
+ while (start < this_end) {
+ unsigned long paddr = pfn << PAGE_SHIFT;
+
+ pte_val(*pte) = (paddr | pte_base);
+
+ start += PAGE_SIZE;
+ pte++;
+ pfn++;
+ }
+ }
+}
+
+void __init setup_per_cpu_areas(void)
+{
+ size_t dyn_size, static_size = __per_cpu_end - __per_cpu_start;
+ static struct vm_struct vm;
+ unsigned long delta, cpu;
+ size_t pcpu_unit_size;
+ size_t ptrs_size;
+
+ pcpur_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE +
+ PERCPU_DYNAMIC_RESERVE);
+ dyn_size = pcpur_size - static_size - PERCPU_MODULE_RESERVE;
+
+
+ ptrs_size = PFN_ALIGN(num_possible_cpus() * sizeof(pcpur_ptrs[0]));
+ pcpur_ptrs = alloc_bootmem(ptrs_size);
+
+ for_each_possible_cpu(cpu) {
+ pcpur_ptrs[cpu] = pcpu_alloc_bootmem(cpu, PCPU_CHUNK_SIZE,
+ PCPU_CHUNK_SIZE);
+
+ free_bootmem(__pa(pcpur_ptrs[cpu] + pcpur_size),
+ PCPU_CHUNK_SIZE - pcpur_size);
+
+ memcpy(pcpur_ptrs[cpu], __per_cpu_load, static_size);
}
- ptr = __va(paddr);
- __per_cpu_base = ptr - __per_cpu_start;
+ /* allocate address and map */
+ vm.flags = VM_ALLOC;
+ vm.size = num_possible_cpus() * PCPU_CHUNK_SIZE;
+ vm_area_register_early(&vm, PCPU_CHUNK_SIZE);
+
+ for_each_possible_cpu(cpu) {
+ unsigned long start = (unsigned long) vm.addr;
+ unsigned long end;
+
+ start += cpu * PCPU_CHUNK_SIZE;
+ end = start + PCPU_CHUNK_SIZE;
+ pcpu_map_range(start, end, virt_to_page(pcpur_ptrs[cpu]));
+ }
- for (i = 0; i < NR_CPUS; i++, ptr += size)
- memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
+ pcpu_unit_size = pcpu_setup_first_chunk(pcpur_get_page, static_size,
+ PERCPU_MODULE_RESERVE, dyn_size,
+ PCPU_CHUNK_SIZE, vm.addr, NULL);
+
+ free_bootmem(__pa(pcpur_ptrs), ptrs_size);
+
+ delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start;
+ for_each_possible_cpu(cpu) {
+ __per_cpu_offset(cpu) = delta + cpu * pcpu_unit_size;
+ }
/* Setup %g5 for the boot cpu. */
__local_per_cpu_offset = __per_cpu_offset(smp_processor_id());
+
+ of_fill_in_cpu_data();
+ if (tlb_type == hypervisor)
+ mdesc_fill_in_cpu_data(CPU_MASK_ALL_PTR);
}
diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c
index e800503879e4..f5000a460c05 100644
--- a/arch/sparc/kernel/sys_sparc32.c
+++ b/arch/sparc/kernel/sys_sparc32.c
@@ -206,21 +206,12 @@ asmlinkage long compat_sys_fstatat64(unsigned int dfd, char __user *filename,
struct compat_stat64 __user * statbuf, int flag)
{
struct kstat stat;
- int error = -EINVAL;
-
- if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
- goto out;
-
- if (flag & AT_SYMLINK_NOFOLLOW)
- error = vfs_lstat_fd(dfd, filename, &stat);
- else
- error = vfs_stat_fd(dfd, filename, &stat);
-
- if (!error)
- error = cp_compat_stat64(&stat, statbuf);
+ int error;
-out:
- return error;
+ error = vfs_fstatat(dfd, filename, &stat, flag);
+ if (error)
+ return error;
+ return cp_compat_stat64(&stat, statbuf);
}
asmlinkage long compat_sys_sysfs(int option, u32 arg1, u32 arg2)
diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c
index db310aa00183..5c12e79b4bdf 100644
--- a/arch/sparc/kernel/time_64.c
+++ b/arch/sparc/kernel/time_64.c
@@ -814,6 +814,11 @@ void udelay(unsigned long usecs)
}
EXPORT_SYMBOL(udelay);
+static cycle_t clocksource_tick_read(struct clocksource *cs)
+{
+ return tick_ops->get_tick();
+}
+
void __init time_init(void)
{
unsigned long freq = sparc64_init_timers();
@@ -827,7 +832,7 @@ void __init time_init(void)
clocksource_tick.mult =
clocksource_hz2mult(freq,
clocksource_tick.shift);
- clocksource_tick.read = tick_ops->get_tick;
+ clocksource_tick.read = clocksource_tick_read;
printk("clocksource: mult[%x] shift[%d]\n",
clocksource_tick.mult, clocksource_tick.shift);
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c
index d809c4ebb48f..10f7bb9fc140 100644
--- a/arch/sparc/kernel/traps_64.c
+++ b/arch/sparc/kernel/traps_64.c
@@ -2509,6 +2509,7 @@ void do_getpsr(struct pt_regs *regs)
}
struct trap_per_cpu trap_block[NR_CPUS];
+EXPORT_SYMBOL(trap_block);
/* This can get invoked before sched_init() so play it super safe
* and use hard_smp_processor_id().
@@ -2530,84 +2531,97 @@ extern void tsb_config_offsets_are_bolixed_dave(void);
void __init trap_init(void)
{
/* Compile time sanity check. */
- if (TI_TASK != offsetof(struct thread_info, task) ||
- TI_FLAGS != offsetof(struct thread_info, flags) ||
- TI_CPU != offsetof(struct thread_info, cpu) ||
- TI_FPSAVED != offsetof(struct thread_info, fpsaved) ||
- TI_KSP != offsetof(struct thread_info, ksp) ||
- TI_FAULT_ADDR != offsetof(struct thread_info, fault_address) ||
- TI_KREGS != offsetof(struct thread_info, kregs) ||
- TI_UTRAPS != offsetof(struct thread_info, utraps) ||
- TI_EXEC_DOMAIN != offsetof(struct thread_info, exec_domain) ||
- TI_REG_WINDOW != offsetof(struct thread_info, reg_window) ||
- TI_RWIN_SPTRS != offsetof(struct thread_info, rwbuf_stkptrs) ||
- TI_GSR != offsetof(struct thread_info, gsr) ||
- TI_XFSR != offsetof(struct thread_info, xfsr) ||
- TI_USER_CNTD0 != offsetof(struct thread_info, user_cntd0) ||
- TI_USER_CNTD1 != offsetof(struct thread_info, user_cntd1) ||
- TI_KERN_CNTD0 != offsetof(struct thread_info, kernel_cntd0) ||
- TI_KERN_CNTD1 != offsetof(struct thread_info, kernel_cntd1) ||
- TI_PCR != offsetof(struct thread_info, pcr_reg) ||
- TI_PRE_COUNT != offsetof(struct thread_info, preempt_count) ||
- TI_NEW_CHILD != offsetof(struct thread_info, new_child) ||
- TI_SYS_NOERROR != offsetof(struct thread_info, syscall_noerror) ||
- TI_RESTART_BLOCK != offsetof(struct thread_info, restart_block) ||
- TI_KUNA_REGS != offsetof(struct thread_info, kern_una_regs) ||
- TI_KUNA_INSN != offsetof(struct thread_info, kern_una_insn) ||
- TI_FPREGS != offsetof(struct thread_info, fpregs) ||
- (TI_FPREGS & (64 - 1)))
- thread_info_offsets_are_bolixed_dave();
-
- if (TRAP_PER_CPU_THREAD != offsetof(struct trap_per_cpu, thread) ||
- (TRAP_PER_CPU_PGD_PADDR !=
- offsetof(struct trap_per_cpu, pgd_paddr)) ||
- (TRAP_PER_CPU_CPU_MONDO_PA !=
- offsetof(struct trap_per_cpu, cpu_mondo_pa)) ||
- (TRAP_PER_CPU_DEV_MONDO_PA !=
- offsetof(struct trap_per_cpu, dev_mondo_pa)) ||
- (TRAP_PER_CPU_RESUM_MONDO_PA !=
- offsetof(struct trap_per_cpu, resum_mondo_pa)) ||
- (TRAP_PER_CPU_RESUM_KBUF_PA !=
- offsetof(struct trap_per_cpu, resum_kernel_buf_pa)) ||
- (TRAP_PER_CPU_NONRESUM_MONDO_PA !=
- offsetof(struct trap_per_cpu, nonresum_mondo_pa)) ||
- (TRAP_PER_CPU_NONRESUM_KBUF_PA !=
- offsetof(struct trap_per_cpu, nonresum_kernel_buf_pa)) ||
- (TRAP_PER_CPU_FAULT_INFO !=
- offsetof(struct trap_per_cpu, fault_info)) ||
- (TRAP_PER_CPU_CPU_MONDO_BLOCK_PA !=
- offsetof(struct trap_per_cpu, cpu_mondo_block_pa)) ||
- (TRAP_PER_CPU_CPU_LIST_PA !=
- offsetof(struct trap_per_cpu, cpu_list_pa)) ||
- (TRAP_PER_CPU_TSB_HUGE !=
- offsetof(struct trap_per_cpu, tsb_huge)) ||
- (TRAP_PER_CPU_TSB_HUGE_TEMP !=
- offsetof(struct trap_per_cpu, tsb_huge_temp)) ||
- (TRAP_PER_CPU_IRQ_WORKLIST_PA !=
- offsetof(struct trap_per_cpu, irq_worklist_pa)) ||
- (TRAP_PER_CPU_CPU_MONDO_QMASK !=
- offsetof(struct trap_per_cpu, cpu_mondo_qmask)) ||
- (TRAP_PER_CPU_DEV_MONDO_QMASK !=
- offsetof(struct trap_per_cpu, dev_mondo_qmask)) ||
- (TRAP_PER_CPU_RESUM_QMASK !=
- offsetof(struct trap_per_cpu, resum_qmask)) ||
- (TRAP_PER_CPU_NONRESUM_QMASK !=
- offsetof(struct trap_per_cpu, nonresum_qmask)))
- trap_per_cpu_offsets_are_bolixed_dave();
-
- if ((TSB_CONFIG_TSB !=
- offsetof(struct tsb_config, tsb)) ||
- (TSB_CONFIG_RSS_LIMIT !=
- offsetof(struct tsb_config, tsb_rss_limit)) ||
- (TSB_CONFIG_NENTRIES !=
- offsetof(struct tsb_config, tsb_nentries)) ||
- (TSB_CONFIG_REG_VAL !=
- offsetof(struct tsb_config, tsb_reg_val)) ||
- (TSB_CONFIG_MAP_VADDR !=
- offsetof(struct tsb_config, tsb_map_vaddr)) ||
- (TSB_CONFIG_MAP_PTE !=
- offsetof(struct tsb_config, tsb_map_pte)))
- tsb_config_offsets_are_bolixed_dave();
+ BUILD_BUG_ON(TI_TASK != offsetof(struct thread_info, task) ||
+ TI_FLAGS != offsetof(struct thread_info, flags) ||
+ TI_CPU != offsetof(struct thread_info, cpu) ||
+ TI_FPSAVED != offsetof(struct thread_info, fpsaved) ||
+ TI_KSP != offsetof(struct thread_info, ksp) ||
+ TI_FAULT_ADDR != offsetof(struct thread_info,
+ fault_address) ||
+ TI_KREGS != offsetof(struct thread_info, kregs) ||
+ TI_UTRAPS != offsetof(struct thread_info, utraps) ||
+ TI_EXEC_DOMAIN != offsetof(struct thread_info,
+ exec_domain) ||
+ TI_REG_WINDOW != offsetof(struct thread_info,
+ reg_window) ||
+ TI_RWIN_SPTRS != offsetof(struct thread_info,
+ rwbuf_stkptrs) ||
+ TI_GSR != offsetof(struct thread_info, gsr) ||
+ TI_XFSR != offsetof(struct thread_info, xfsr) ||
+ TI_USER_CNTD0 != offsetof(struct thread_info,
+ user_cntd0) ||
+ TI_USER_CNTD1 != offsetof(struct thread_info,
+ user_cntd1) ||
+ TI_KERN_CNTD0 != offsetof(struct thread_info,
+ kernel_cntd0) ||
+ TI_KERN_CNTD1 != offsetof(struct thread_info,
+ kernel_cntd1) ||
+ TI_PCR != offsetof(struct thread_info, pcr_reg) ||
+ TI_PRE_COUNT != offsetof(struct thread_info,
+ preempt_count) ||
+ TI_NEW_CHILD != offsetof(struct thread_info, new_child) ||
+ TI_SYS_NOERROR != offsetof(struct thread_info,
+ syscall_noerror) ||
+ TI_RESTART_BLOCK != offsetof(struct thread_info,
+ restart_block) ||
+ TI_KUNA_REGS != offsetof(struct thread_info,
+ kern_una_regs) ||
+ TI_KUNA_INSN != offsetof(struct thread_info,
+ kern_una_insn) ||
+ TI_FPREGS != offsetof(struct thread_info, fpregs) ||
+ (TI_FPREGS & (64 - 1)));
+
+ BUILD_BUG_ON(TRAP_PER_CPU_THREAD != offsetof(struct trap_per_cpu,
+ thread) ||
+ (TRAP_PER_CPU_PGD_PADDR !=
+ offsetof(struct trap_per_cpu, pgd_paddr)) ||
+ (TRAP_PER_CPU_CPU_MONDO_PA !=
+ offsetof(struct trap_per_cpu, cpu_mondo_pa)) ||
+ (TRAP_PER_CPU_DEV_MONDO_PA !=
+ offsetof(struct trap_per_cpu, dev_mondo_pa)) ||
+ (TRAP_PER_CPU_RESUM_MONDO_PA !=
+ offsetof(struct trap_per_cpu, resum_mondo_pa)) ||
+ (TRAP_PER_CPU_RESUM_KBUF_PA !=
+ offsetof(struct trap_per_cpu, resum_kernel_buf_pa)) ||
+ (TRAP_PER_CPU_NONRESUM_MONDO_PA !=
+ offsetof(struct trap_per_cpu, nonresum_mondo_pa)) ||
+ (TRAP_PER_CPU_NONRESUM_KBUF_PA !=
+ offsetof(struct trap_per_cpu, nonresum_kernel_buf_pa)) ||
+ (TRAP_PER_CPU_FAULT_INFO !=
+ offsetof(struct trap_per_cpu, fault_info)) ||
+ (TRAP_PER_CPU_CPU_MONDO_BLOCK_PA !=
+ offsetof(struct trap_per_cpu, cpu_mondo_block_pa)) ||
+ (TRAP_PER_CPU_CPU_LIST_PA !=
+ offsetof(struct trap_per_cpu, cpu_list_pa)) ||
+ (TRAP_PER_CPU_TSB_HUGE !=
+ offsetof(struct trap_per_cpu, tsb_huge)) ||
+ (TRAP_PER_CPU_TSB_HUGE_TEMP !=
+ offsetof(struct trap_per_cpu, tsb_huge_temp)) ||
+ (TRAP_PER_CPU_IRQ_WORKLIST_PA !=
+ offsetof(struct trap_per_cpu, irq_worklist_pa)) ||
+ (TRAP_PER_CPU_CPU_MONDO_QMASK !=
+ offsetof(struct trap_per_cpu, cpu_mondo_qmask)) ||
+ (TRAP_PER_CPU_DEV_MONDO_QMASK !=
+ offsetof(struct trap_per_cpu, dev_mondo_qmask)) ||
+ (TRAP_PER_CPU_RESUM_QMASK !=
+ offsetof(struct trap_per_cpu, resum_qmask)) ||
+ (TRAP_PER_CPU_NONRESUM_QMASK !=
+ offsetof(struct trap_per_cpu, nonresum_qmask)) ||
+ (TRAP_PER_CPU_PER_CPU_BASE !=
+ offsetof(struct trap_per_cpu, __per_cpu_base)));
+
+ BUILD_BUG_ON((TSB_CONFIG_TSB !=
+ offsetof(struct tsb_config, tsb)) ||
+ (TSB_CONFIG_RSS_LIMIT !=
+ offsetof(struct tsb_config, tsb_rss_limit)) ||
+ (TSB_CONFIG_NENTRIES !=
+ offsetof(struct tsb_config, tsb_nentries)) ||
+ (TSB_CONFIG_REG_VAL !=
+ offsetof(struct tsb_config, tsb_reg_val)) ||
+ (TSB_CONFIG_MAP_VADDR !=
+ offsetof(struct tsb_config, tsb_map_vaddr)) ||
+ (TSB_CONFIG_MAP_PTE !=
+ offsetof(struct tsb_config, tsb_map_pte)));
/* Attach to the address space of init_task. On SMP we
* do this in smp.c:smp_callin for other cpus.
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 76267085b13b..fcbbd000ec08 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -41,7 +41,7 @@ SECTIONS
.text TEXTSTART :
{
_text = .;
- *(.text.head)
+ HEAD_TEXT
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
diff --git a/arch/sparc/mm/init_32.c b/arch/sparc/mm/init_32.c
index cbb282dab5a7..26bb3919ff1f 100644
--- a/arch/sparc/mm/init_32.c
+++ b/arch/sparc/mm/init_32.c
@@ -358,6 +358,7 @@ void __init paging_init(void)
protection_map[15] = PAGE_SHARED;
btfixup();
prom_build_devicetree();
+ of_fill_in_cpu_data();
device_scan();
}
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index f26a352c08a0..b5a5932def77 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -1679,11 +1679,6 @@ pgd_t swapper_pg_dir[2048];
static void sun4u_pgprot_init(void);
static void sun4v_pgprot_init(void);
-/* Dummy function */
-void __init setup_per_cpu_areas(void)
-{
-}
-
void __init paging_init(void)
{
unsigned long end_pfn, shift, phys_base;
@@ -1799,16 +1794,13 @@ void __init paging_init(void)
if (tlb_type == hypervisor)
sun4v_ktsb_register();
- /* We must setup the per-cpu areas before we pull in the
- * PROM and the MDESC. The code there fills in cpu and
- * other information into per-cpu data structures.
- */
- real_setup_per_cpu_areas();
-
prom_build_devicetree();
+ of_populate_present_mask();
- if (tlb_type == hypervisor)
+ if (tlb_type == hypervisor) {
sun4v_mdesc_init();
+ mdesc_populate_present_mask(CPU_MASK_ALL_PTR);
+ }
/* Once the OF device tree and MDESC have been setup, we know
* the list of possible cpus. Therefore we can allocate the
diff --git a/arch/um/Kconfig.rest b/arch/um/Kconfig.rest
index 7b5cea75a6c4..0ccad0ff6d6e 100644
--- a/arch/um/Kconfig.rest
+++ b/arch/um/Kconfig.rest
@@ -36,7 +36,7 @@ source "drivers/leds/Kconfig"
#This is just to shut up some Kconfig warnings, so no prompt.
config INPUT
- bool
+ tristate
default n
source "arch/um/Kconfig.debug"
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index f934225fd8ef..433012764a37 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -451,23 +451,6 @@ static void do_ubd_request(struct request_queue * q);
/* Only changed by ubd_init, which is an initcall. */
static int thread_fd = -1;
-
-static void ubd_end_request(struct request *req, int bytes, int error)
-{
- blk_end_request(req, error, bytes);
-}
-
-/* Callable only from interrupt context - otherwise you need to do
- * spin_lock_irq()/spin_lock_irqsave() */
-static inline void ubd_finish(struct request *req, int bytes)
-{
- if(bytes < 0){
- ubd_end_request(req, 0, -EIO);
- return;
- }
- ubd_end_request(req, bytes, 0);
-}
-
static LIST_HEAD(restart);
/* XXX - move this inside ubd_intr. */
@@ -475,7 +458,6 @@ static LIST_HEAD(restart);
static void ubd_handler(void)
{
struct io_thread_req *req;
- struct request *rq;
struct ubd *ubd;
struct list_head *list, *next_ele;
unsigned long flags;
@@ -492,10 +474,7 @@ static void ubd_handler(void)
return;
}
- rq = req->req;
- rq->nr_sectors -= req->length >> 9;
- if(rq->nr_sectors == 0)
- ubd_finish(rq, rq->hard_nr_sectors << 9);
+ blk_end_request(req->req, 0, req->length);
kfree(req);
}
reactivate_fd(thread_fd, UBD_IRQ);
@@ -1243,7 +1222,8 @@ static void do_ubd_request(struct request_queue *q)
{
struct io_thread_req *io_req;
struct request *req;
- int n, last_sectors;
+ sector_t sector;
+ int n;
while(1){
struct ubd *dev = q->queuedata;
@@ -1259,11 +1239,10 @@ static void do_ubd_request(struct request_queue *q)
}
req = dev->request;
- last_sectors = 0;
+ sector = req->sector;
while(dev->start_sg < dev->end_sg){
struct scatterlist *sg = &dev->sg[dev->start_sg];
- req->sector += last_sectors;
io_req = kmalloc(sizeof(struct io_thread_req),
GFP_ATOMIC);
if(io_req == NULL){
@@ -1272,10 +1251,10 @@ static void do_ubd_request(struct request_queue *q)
return;
}
prepare_request(req, io_req,
- (unsigned long long) req->sector << 9,
+ (unsigned long long)sector << 9,
sg->offset, sg->length, sg_page(sg));
- last_sectors = sg->length >> 9;
+ sector += sg->length >> 9;
n = os_write_file(thread_fd, &io_req,
sizeof(struct io_thread_req *));
if(n != sizeof(struct io_thread_req *)){
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index b13a87a3ec95..c8b9c469fcd7 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -65,7 +65,7 @@ static irqreturn_t um_timer(int irq, void *dev)
return IRQ_HANDLED;
}
-static cycle_t itimer_read(void)
+static cycle_t itimer_read(struct clocksource *cs)
{
return os_nsecs() / 1000;
}
diff --git a/arch/x86/Kbuild b/arch/x86/Kbuild
new file mode 100644
index 000000000000..ad8ec356fb36
--- /dev/null
+++ b/arch/x86/Kbuild
@@ -0,0 +1,16 @@
+
+obj-$(CONFIG_KVM) += kvm/
+
+# Xen paravirtualization support
+obj-$(CONFIG_XEN) += xen/
+
+# lguest paravirtualization support
+obj-$(CONFIG_LGUEST_GUEST) += lguest/
+
+obj-y += kernel/
+obj-y += mm/
+
+obj-y += crypto/
+obj-y += vdso/
+obj-$(CONFIG_IA32_EMULATION) += ia32/
+
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index bc25b9f5e4cd..b0af3a6b362a 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -47,6 +47,11 @@ config X86
select HAVE_KERNEL_BZIP2
select HAVE_KERNEL_LZMA
+config OUTPUT_FORMAT
+ string
+ default "elf32-i386" if X86_32
+ default "elf64-x86-64" if X86_64
+
config ARCH_DEFCONFIG
string
default "arch/x86/configs/i386_defconfig" if X86_32
@@ -274,14 +279,9 @@ config SPARSE_IRQ
If you don't know what to do here, say N.
-config NUMA_MIGRATE_IRQ_DESC
- bool "Move irq desc when changing irq smp_affinity"
+config NUMA_IRQ_DESC
+ def_bool y
depends on SPARSE_IRQ && NUMA
- default n
- ---help---
- This enables moving irq_desc to cpu/node that irq will use handled.
-
- If you don't know what to do here, say N.
config X86_MPPARSE
bool "Enable MPS table" if ACPI
@@ -353,7 +353,8 @@ config X86_UV
bool "SGI Ultraviolet"
depends on X86_64
depends on X86_EXTENDED_PLATFORM
- select X86_X2APIC
+ depends on NUMA
+ depends on X86_X2APIC
---help---
This option is needed in order to support SGI Ultraviolet systems.
If you don't have one of these, you should say N here.
@@ -663,6 +664,7 @@ config MAXSMP
config NR_CPUS
int "Maximum number of CPUs" if SMP && !MAXSMP
+ range 2 8 if SMP && X86_32 && !X86_BIGSMP
range 2 512 if SMP && !MAXSMP
default "1" if !SMP
default "4096" if MAXSMP
@@ -1191,6 +1193,11 @@ config ARCH_MEMORY_PROBE
def_bool X86_64
depends on MEMORY_HOTPLUG
+config ILLEGAL_POINTER_VALUE
+ hex
+ default 0 if X86_32
+ default 0xdead000000000000 if X86_64
+
source "mm/Kconfig"
config HIGHPTE
@@ -1450,17 +1457,20 @@ config KEXEC_JUMP
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"
+ default "0x400000" if EMBEDDED
+ default "0x1000000"
---help---
This gives the physical address where the kernel is loaded.
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.
+ run from there. Otherwise, bzImage will run from the either
+ the above physical address or where it has been loaded by
+ the boot loader, whichever is higher.
+
+ For embedded machines with very small memory (less than
+ about 24 MB) this may need to be adjusted downward from the
+ default value of 0x1000000 (16 MB).
In normal kdump cases one does not have to set/change this option
as now bzImage can be compiled as a completely relocatable image
@@ -1511,8 +1521,8 @@ config RELOCATABLE
config PHYSICAL_ALIGN
hex
prompt "Alignment value to which kernel should be aligned" if X86_32
- default "0x100000" if X86_32
- default "0x200000" if X86_64
+ default "0x200000" if X86_64 || X86_PAE
+ default "0x400000"
range 0x2000 0x400000
---help---
This value puts the alignment restrictions on physical address
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index d8359e73317f..ca1aa3eca9bc 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -161,12 +161,20 @@ config IOMMU_DEBUG
config IOMMU_LEAK
bool "IOMMU leak tracing"
- depends on DEBUG_KERNEL
- depends on IOMMU_DEBUG
+ depends on IOMMU_DEBUG && DMA_API_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 X86_DS_SELFTEST
+ bool "DS selftest"
+ default y
+ depends on DEBUG_KERNEL
+ depends on X86_DS
+ ---help---
+ Perform Debug Store selftests at boot time.
+ If in doubt, say "N".
+
config HAVE_MMIOTRACE_SUPPORT
def_bool y
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index f05d8c91d9e5..edbd0ca62067 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -7,8 +7,6 @@ else
KBUILD_DEFCONFIG := $(ARCH)_defconfig
endif
-core-$(CONFIG_KVM) += arch/x86/kvm/
-
# 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
@@ -118,21 +116,8 @@ head-y += arch/x86/kernel/init_task.o
libs-y += arch/x86/lib/
-# Sub architecture files that needs linking first
-core-y += $(fcore-y)
-
-# Xen paravirtualization support
-core-$(CONFIG_XEN) += arch/x86/xen/
-
-# lguest paravirtualization support
-core-$(CONFIG_LGUEST_GUEST) += arch/x86/lguest/
-
-core-y += arch/x86/kernel/
-core-y += arch/x86/mm/
-
-core-y += arch/x86/crypto/
-core-y += arch/x86/vdso/
-core-$(CONFIG_IA32_EMULATION) += arch/x86/ia32/
+# See arch/x86/Kbuild for content of core part of the kernel
+core-y += arch/x86/
# drivers-y are linked after core-y
drivers-$(CONFIG_MATH_EMULATION) += arch/x86/math-emu/
@@ -153,7 +138,7 @@ endif
boot := arch/x86/boot
-BOOT_TARGETS = bzlilo bzdisk fdimage fdimage144 fdimage288 isoimage install
+BOOT_TARGETS = bzlilo bzdisk fdimage fdimage144 fdimage288 isoimage
PHONY += bzImage $(BOOT_TARGETS)
@@ -171,6 +156,10 @@ bzImage: vmlinux
$(BOOT_TARGETS): vmlinux
$(Q)$(MAKE) $(build)=$(boot) $@
+PHONY += install
+install:
+ $(Q)$(MAKE) $(build)=$(boot) $@
+
PHONY += vdso_install
vdso_install:
$(Q)$(MAKE) $(build)=arch/x86/vdso $@
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index 6633b6e7505a..658bc525cac7 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -26,9 +26,10 @@ targets := vmlinux.bin setup.bin setup.elf bzImage
targets += fdimage fdimage144 fdimage288 image.iso mtools.conf
subdir- := compressed
-setup-y += a20.o cmdline.o copy.o cpu.o cpucheck.o edd.o
+setup-y += a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o edd.o
setup-y += header.o main.o mca.o memory.o pm.o pmjump.o
-setup-y += printf.o string.o tty.o video.o video-mode.o version.o
+setup-y += printf.o regs.o string.o tty.o video.o video-mode.o
+setup-y += version.o
setup-$(CONFIG_X86_APM_BOOT) += apm.o
# The link order of the video-*.o modules can matter. In particular,
diff --git a/arch/x86/boot/a20.c b/arch/x86/boot/a20.c
index 7c19ce8c2442..64a31a6d751a 100644
--- a/arch/x86/boot/a20.c
+++ b/arch/x86/boot/a20.c
@@ -2,7 +2,7 @@
*
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright 2007-2008 rPath, Inc. - All Rights Reserved
- * Copyright 2009 Intel Corporation
+ * Copyright 2009 Intel Corporation; author H. Peter Anvin
*
* This file is part of the Linux kernel, and is made available under
* the terms of the GNU General Public License version 2.
@@ -90,8 +90,11 @@ static int a20_test_long(void)
static void enable_a20_bios(void)
{
- asm volatile("pushfl; int $0x15; popfl"
- : : "a" ((u16)0x2401));
+ struct biosregs ireg;
+
+ initregs(&ireg);
+ ireg.ax = 0x2401;
+ intcall(0x15, &ireg, NULL);
}
static void enable_a20_kbc(void)
diff --git a/arch/x86/boot/apm.c b/arch/x86/boot/apm.c
index 7aa6033001f9..ee274834ea8b 100644
--- a/arch/x86/boot/apm.c
+++ b/arch/x86/boot/apm.c
@@ -2,6 +2,7 @@
*
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright 2007 rPath, Inc. - All Rights Reserved
+ * Copyright 2009 Intel Corporation; author H. Peter Anvin
*
* Original APM BIOS checking by Stephen Rothwell, May 1994
* (sfr@canb.auug.org.au)
@@ -19,75 +20,56 @@
int query_apm_bios(void)
{
- u16 ax, bx, cx, dx, di;
- u32 ebx, esi;
- u8 err;
+ struct biosregs ireg, oreg;
/* APM BIOS installation check */
- ax = 0x5300;
- bx = cx = 0;
- asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0"
- : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx)
- : : "esi", "edi");
+ initregs(&ireg);
+ ireg.ah = 0x53;
+ intcall(0x15, &ireg, &oreg);
- if (err)
+ if (oreg.flags & X86_EFLAGS_CF)
return -1; /* No APM BIOS */
- if (bx != 0x504d) /* "PM" signature */
+ if (oreg.bx != 0x504d) /* "PM" signature */
return -1;
- if (!(cx & 0x02)) /* 32 bits supported? */
+ if (!(oreg.cx & 0x02)) /* 32 bits supported? */
return -1;
/* Disconnect first, just in case */
- ax = 0x5304;
- bx = 0;
- asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp"
- : "+a" (ax), "+b" (bx)
- : : "ecx", "edx", "esi", "edi");
-
- /* Paranoia */
- ebx = esi = 0;
- cx = dx = di = 0;
+ ireg.al = 0x04;
+ intcall(0x15, &ireg, NULL);
/* 32-bit connect */
- asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %6"
- : "=a" (ax), "+b" (ebx), "+c" (cx), "+d" (dx),
- "+S" (esi), "+D" (di), "=m" (err)
- : "a" (0x5303));
-
- boot_params.apm_bios_info.cseg = ax;
- boot_params.apm_bios_info.offset = ebx;
- boot_params.apm_bios_info.cseg_16 = cx;
- boot_params.apm_bios_info.dseg = dx;
- boot_params.apm_bios_info.cseg_len = (u16)esi;
- boot_params.apm_bios_info.cseg_16_len = esi >> 16;
- boot_params.apm_bios_info.dseg_len = di;
-
- if (err)
+ ireg.al = 0x03;
+ intcall(0x15, &ireg, &oreg);
+
+ boot_params.apm_bios_info.cseg = oreg.ax;
+ boot_params.apm_bios_info.offset = oreg.ebx;
+ boot_params.apm_bios_info.cseg_16 = oreg.cx;
+ boot_params.apm_bios_info.dseg = oreg.dx;
+ boot_params.apm_bios_info.cseg_len = oreg.si;
+ boot_params.apm_bios_info.cseg_16_len = oreg.hsi;
+ boot_params.apm_bios_info.dseg_len = oreg.di;
+
+ if (oreg.flags & X86_EFLAGS_CF)
return -1;
/* Redo the installation check as the 32-bit connect;
some BIOSes return different flags this way... */
- ax = 0x5300;
- bx = cx = 0;
- asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0"
- : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx)
- : : "esi", "edi");
+ ireg.al = 0x00;
+ intcall(0x15, &ireg, &oreg);
- if (err || bx != 0x504d) {
+ if ((oreg.eflags & X86_EFLAGS_CF) || oreg.bx != 0x504d) {
/* Failure with 32-bit connect, try to disconect and ignore */
- ax = 0x5304;
- bx = 0;
- asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp"
- : "+a" (ax), "+b" (bx)
- : : "ecx", "edx", "esi", "edi");
+ ireg.al = 0x04;
+ intcall(0x15, &ireg, NULL);
return -1;
}
- boot_params.apm_bios_info.version = ax;
- boot_params.apm_bios_info.flags = cx;
+ boot_params.apm_bios_info.version = oreg.ax;
+ boot_params.apm_bios_info.flags = oreg.cx;
return 0;
}
diff --git a/arch/x86/boot/bioscall.S b/arch/x86/boot/bioscall.S
new file mode 100644
index 000000000000..507793739ea5
--- /dev/null
+++ b/arch/x86/boot/bioscall.S
@@ -0,0 +1,82 @@
+/* -----------------------------------------------------------------------
+ *
+ * Copyright 2009 Intel Corporation; author H. Peter Anvin
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2 or (at your
+ * option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * "Glove box" for BIOS calls. Avoids the constant problems with BIOSes
+ * touching registers they shouldn't be.
+ */
+
+ .code16
+ .text
+ .globl intcall
+ .type intcall, @function
+intcall:
+ /* Self-modify the INT instruction. Ugly, but works. */
+ cmpb %al, 3f
+ je 1f
+ movb %al, 3f
+ jmp 1f /* Synchronize pipeline */
+1:
+ /* Save state */
+ pushfl
+ pushw %fs
+ pushw %gs
+ pushal
+
+ /* Copy input state to stack frame */
+ subw $44, %sp
+ movw %dx, %si
+ movw %sp, %di
+ movw $11, %cx
+ rep; movsd
+
+ /* Pop full state from the stack */
+ popal
+ popw %gs
+ popw %fs
+ popw %es
+ popw %ds
+ popfl
+
+ /* Actual INT */
+ .byte 0xcd /* INT opcode */
+3: .byte 0
+
+ /* Push full state to the stack */
+ pushfl
+ pushw %ds
+ pushw %es
+ pushw %fs
+ pushw %gs
+ pushal
+
+ /* Re-establish C environment invariants */
+ cld
+ movzwl %sp, %esp
+ movw %cs, %ax
+ movw %ax, %ds
+ movw %ax, %es
+
+ /* Copy output state from stack frame */
+ movw 68(%esp), %di /* Original %cx == 3rd argument */
+ andw %di, %di
+ jz 4f
+ movw %sp, %si
+ movw $11, %cx
+ rep; movsd
+4: addw $44, %sp
+
+ /* Restore state and return */
+ popal
+ popw %gs
+ popw %fs
+ popfl
+ retl
+ .size intcall, .-intcall
diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
index 7b2692e897e5..98239d2658f2 100644
--- a/arch/x86/boot/boot.h
+++ b/arch/x86/boot/boot.h
@@ -2,6 +2,7 @@
*
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright 2007 rPath, Inc. - All Rights Reserved
+ * Copyright 2009 Intel Corporation; author H. Peter Anvin
*
* This file is part of the Linux kernel, and is made available under
* the terms of the GNU General Public License version 2.
@@ -26,6 +27,7 @@
#include <asm/setup.h>
#include "bitops.h"
#include <asm/cpufeature.h>
+#include <asm/processor-flags.h>
/* Useful macros */
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
@@ -241,6 +243,49 @@ int enable_a20(void);
/* apm.c */
int query_apm_bios(void);
+/* bioscall.c */
+struct biosregs {
+ union {
+ struct {
+ u32 edi;
+ u32 esi;
+ u32 ebp;
+ u32 _esp;
+ u32 ebx;
+ u32 edx;
+ u32 ecx;
+ u32 eax;
+ u32 _fsgs;
+ u32 _dses;
+ u32 eflags;
+ };
+ struct {
+ u16 di, hdi;
+ u16 si, hsi;
+ u16 bp, hbp;
+ u16 _sp, _hsp;
+ u16 bx, hbx;
+ u16 dx, hdx;
+ u16 cx, hcx;
+ u16 ax, hax;
+ u16 gs, fs;
+ u16 es, ds;
+ u16 flags, hflags;
+ };
+ struct {
+ u8 dil, dih, edi2, edi3;
+ u8 sil, sih, esi2, esi3;
+ u8 bpl, bph, ebp2, ebp3;
+ u8 _spl, _sph, _esp2, _esp3;
+ u8 bl, bh, ebx2, ebx3;
+ u8 dl, dh, edx2, edx3;
+ u8 cl, ch, ecx2, ecx3;
+ u8 al, ah, eax2, eax3;
+ };
+ };
+};
+void intcall(u8 int_no, const struct biosregs *ireg, struct biosregs *oreg);
+
/* cmdline.c */
int cmdline_find_option(const char *option, char *buffer, int bufsize);
int cmdline_find_option_bool(const char *option);
@@ -279,6 +324,9 @@ int sprintf(char *buf, const char *fmt, ...);
int vsprintf(char *buf, const char *fmt, va_list args);
int printf(const char *fmt, ...);
+/* regs.c */
+void initregs(struct biosregs *regs);
+
/* string.c */
int strcmp(const char *str1, const char *str2);
size_t strnlen(const char *s, size_t maxlen);
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 65551c9f8571..0f4b5e2abd3f 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -19,7 +19,7 @@ KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
LDFLAGS := -m elf_$(UTS_MACHINE)
LDFLAGS_vmlinux := -T
-$(obj)/vmlinux: $(src)/vmlinux_$(BITS).lds $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/piggy.o FORCE
+$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/piggy.o FORCE
$(call if_changed,ld)
@:
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index 3a8a866fb2e2..2d7cd0f2bc7d 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -39,11 +39,11 @@ ENTRY(startup_32)
cli
movl $(__BOOT_DS),%eax
- movl %eax,%ds
- movl %eax,%es
- movl %eax,%fs
- movl %eax,%gs
- movl %eax,%ss
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %fs
+ movl %eax, %gs
+ movl %eax, %ss
1:
/* Calculate the delta between where we were compiled to run
@@ -64,12 +64,18 @@ ENTRY(startup_32)
*/
#ifdef CONFIG_RELOCATABLE
- movl %ebp, %ebx
- addl $(CONFIG_PHYSICAL_ALIGN - 1), %ebx
- andl $(~(CONFIG_PHYSICAL_ALIGN - 1)), %ebx
+ movl $LOAD_PHYSICAL_ADDR, %eax
+ movl %ebp, %ebx
+ cmpl %ebx, %eax
+ jbe 1f
+ movl %eax, %ebx
+1:
+ addl $(LOAD_PHYSICAL_ALIGN - 1), %ebx
+ andl $(~(LOAD_PHYSICAL_ALIGN - 1)), %ebx
#else
movl $LOAD_PHYSICAL_ADDR, %ebx
#endif
+ movl %ebx, %edi /* Save kernel target address */
/* Replace the compressed data size with the uncompressed size */
subl input_len(%ebp), %ebx
@@ -84,27 +90,30 @@ ENTRY(startup_32)
addl $4095, %ebx
andl $~4095, %ebx
-/* Copy the compressed kernel to the end of our buffer
+/*
+ * Set up the stack
+ */
+ leal boot_stack_end(%ebx), %esp
+ pushl %edi /* Saved kernel target address */
+
+/*
+ * Copy the compressed kernel to the end of our buffer
* where decompression in place becomes safe.
*/
pushl %esi
- leal _end(%ebp), %esi
- leal _end(%ebx), %edi
- movl $(_end - startup_32), %ecx
+ leal (_bss-4)(%ebp), %esi
+ leal (_bss-4)(%ebx), %edi
+ movl $(_bss - startup_32), %ecx
+ shrl $2, %ecx
std
- rep
- movsb
+ rep; movsl
cld
popl %esi
-/* Compute the kernel start address.
+/*
+ * %ebp -> kernel target address
*/
-#ifdef CONFIG_RELOCATABLE
- addl $(CONFIG_PHYSICAL_ALIGN - 1), %ebp
- andl $(~(CONFIG_PHYSICAL_ALIGN - 1)), %ebp
-#else
- movl $LOAD_PHYSICAL_ADDR, %ebp
-#endif
+ popl %ebp
/*
* Jump to the relocated address.
@@ -117,20 +126,14 @@ ENDPROC(startup_32)
relocated:
/*
- * Clear BSS
- */
- xorl %eax,%eax
- leal _edata(%ebx),%edi
- leal _end(%ebx), %ecx
- subl %edi,%ecx
- cld
- rep
- stosb
-
-/*
- * Setup the stack for the decompressor
+ * Clear BSS - note: stack is currently empty
*/
- leal boot_stack_end(%ebx), %esp
+ xorl %eax, %eax
+ leal _bss(%ebx), %edi
+ leal (_ebss+3)(%ebx), %ecx
+ subl %edi, %ecx
+ shrl $2, %ecx
+ rep; stosl
/*
* Do the decompression, and jump to the new kernel..
@@ -178,12 +181,12 @@ relocated:
/*
* Jump to the decompressed kernel.
*/
- xorl %ebx,%ebx
+ xorl %ebx, %ebx
jmp *%ebp
-.bss
/* Stack and heap for uncompression */
-.balign 4
+ .bss
+ .balign 4
boot_heap:
.fill BOOT_HEAP_SIZE, 1, 0
boot_stack:
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index ed4a82948002..201af02e127d 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -7,11 +7,6 @@
/*
* head.S contains the 32-bit startup code.
*
- * NOTE!!! Startup happens at absolute address 0x00001000, which is also where
- * the page directory will exist. The startup code will be overwritten by
- * the page directory. [According to comments etc elsewhere on a compressed
- * kernel it will end up at 0x1000 + 1Mb I hope so as I assume this. - AC]
- *
* Page 0 is deliberately kept safe, since System Management Mode code in
* laptops may need to access the BIOS data stored there. This is also
* useful for future device drivers that either access the BIOS via VM86
@@ -27,7 +22,6 @@
#include <linux/linkage.h>
#include <asm/segment.h>
#include <asm/pgtable_types.h>
-#include <asm/page_types.h>
#include <asm/boot.h>
#include <asm/msr.h>
#include <asm/processor-flags.h>
@@ -77,13 +71,17 @@ ENTRY(startup_32)
* contains the address where we should move the kernel image temporarily
* for safe in-place decompression.
*/
-
#ifdef CONFIG_RELOCATABLE
+ movl $LOAD_PHYSICAL_ADDR, %eax
movl %ebp, %ebx
- addl $(PMD_PAGE_SIZE -1), %ebx
- andl $PMD_PAGE_MASK, %ebx
+ addl $(LOAD_PHYSICAL_ALIGN - 1), %ebx
+ andl $~(LOAD_PHYSICAL_ALIGN - 1), %ebx
+ cmpl %ebx, %eax
+ jbe 1f
+ movl %eax, %ebx
+1:
#else
- movl $CONFIG_PHYSICAL_START, %ebx
+ movl $LOAD_PHYSICAL_ADDR, %ebx
#endif
/* Replace the compressed data size with the uncompressed size */
@@ -215,19 +213,23 @@ ENTRY(startup_64)
*
* If it is a relocatable kernel then decompress and run the kernel
* from load address aligned to 2MB addr, otherwise decompress and
- * run the kernel from CONFIG_PHYSICAL_START
+ * run the kernel from LOAD_PHYSICAL_ADDR
*/
/* Start with the delta to where the kernel will run at. */
#ifdef CONFIG_RELOCATABLE
leaq startup_32(%rip) /* - $startup_32 */, %rbp
- addq $(PMD_PAGE_SIZE - 1), %rbp
- andq $PMD_PAGE_MASK, %rbp
- movq %rbp, %rbx
+ movq $LOAD_PHYSICAL_ADDR, %rax
+ addq $(LOAD_PHYSICAL_ALIGN - 1), %rbp
+ andq $~(LOAD_PHYSICAL_ALIGN - 1), %rbp
+ cmpq %rbp, %rax
+ jbe 1f
+ movq %rax, %rbp
+1:
#else
- movq $CONFIG_PHYSICAL_START, %rbp
- movq %rbp, %rbx
+ movq $LOAD_PHYSICAL_ADDR, %rbp
#endif
+ movq %rbp, %rbx
/* Replace the compressed data size with the uncompressed size */
movl input_len(%rip), %eax
@@ -266,13 +268,13 @@ relocated:
/*
* Clear BSS
*/
- xorq %rax, %rax
- leaq _edata(%rbx), %rdi
- leaq _end_before_pgt(%rbx), %rcx
+ xorl %eax, %eax
+ leaq _edata(%rip), %rdi
+ leaq _end_before_pgt(%rip), %rcx
subq %rdi, %rcx
+ shrq $3, %rcx
cld
- rep
- stosb
+ rep stosq
/* Setup the stack */
leaq boot_stack_end(%rip), %rsp
diff --git a/arch/x86/boot/compressed/vmlinux_64.lds b/arch/x86/boot/compressed/vmlinux.lds.S
index bef1ac891bce..27c168dcc407 100644
--- a/arch/x86/boot/compressed/vmlinux_64.lds
+++ b/arch/x86/boot/compressed/vmlinux.lds.S
@@ -1,6 +1,15 @@
-OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
+OUTPUT_FORMAT(CONFIG_OUTPUT_FORMAT, CONFIG_OUTPUT_FORMAT, CONFIG_OUTPUT_FORMAT)
+
+#undef i386
+
+#ifdef CONFIG_X86_64
OUTPUT_ARCH(i386:x86-64)
ENTRY(startup_64)
+#else
+OUTPUT_ARCH(i386)
+ENTRY(startup_32)
+#endif
+
SECTIONS
{
/* Be careful parts of head_64.S assume startup_32 is at
@@ -33,16 +42,19 @@ SECTIONS
*(.data.*)
_edata = . ;
}
+ . = ALIGN(32);
.bss : {
_bss = . ;
*(.bss)
*(.bss.*)
*(COMMON)
+#ifdef CONFIG_X86_64
. = ALIGN(8);
_end_before_pgt = . ;
. = ALIGN(4096);
pgtable = . ;
. = . + 4096 * 6;
+#endif
_ebss = .;
}
}
diff --git a/arch/x86/boot/compressed/vmlinux_32.lds b/arch/x86/boot/compressed/vmlinux_32.lds
deleted file mode 100644
index bb3c48379c40..000000000000
--- a/arch/x86/boot/compressed/vmlinux_32.lds
+++ /dev/null
@@ -1,43 +0,0 @@
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH(i386)
-ENTRY(startup_32)
-SECTIONS
-{
- /* Be careful parts of head_32.S assume startup_32 is at
- * address 0.
- */
- . = 0;
- .text.head : {
- _head = . ;
- *(.text.head)
- _ehead = . ;
- }
- .rodata.compressed : {
- *(.rodata.compressed)
- }
- .text : {
- _text = .; /* Text */
- *(.text)
- *(.text.*)
- _etext = . ;
- }
- .rodata : {
- _rodata = . ;
- *(.rodata) /* read-only data */
- *(.rodata.*)
- _erodata = . ;
- }
- .data : {
- _data = . ;
- *(.data)
- *(.data.*)
- _edata = . ;
- }
- .bss : {
- _bss = . ;
- *(.bss)
- *(.bss.*)
- *(COMMON)
- _end = . ;
- }
-}
diff --git a/arch/x86/boot/edd.c b/arch/x86/boot/edd.c
index 1aae8f3e5ca1..c501a5b466f8 100644
--- a/arch/x86/boot/edd.c
+++ b/arch/x86/boot/edd.c
@@ -2,6 +2,7 @@
*
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright 2007 rPath, Inc. - All Rights Reserved
+ * Copyright 2009 Intel Corporation; author H. Peter Anvin
*
* This file is part of the Linux kernel, and is made available under
* the terms of the GNU General Public License version 2.
@@ -22,17 +23,17 @@
*/
static int read_mbr(u8 devno, void *buf)
{
- u16 ax, bx, cx, dx;
+ struct biosregs ireg, oreg;
- ax = 0x0201; /* Legacy Read, one sector */
- cx = 0x0001; /* Sector 0-0-1 */
- dx = devno;
- bx = (size_t)buf;
- asm volatile("pushfl; stc; int $0x13; setc %%al; popfl"
- : "+a" (ax), "+c" (cx), "+d" (dx), "+b" (bx)
- : : "esi", "edi", "memory");
+ initregs(&ireg);
+ ireg.ax = 0x0201; /* Legacy Read, one sector */
+ ireg.cx = 0x0001; /* Sector 0-0-1 */
+ ireg.dl = devno;
+ ireg.bx = (size_t)buf;
- return -(u8)ax; /* 0 or -1 */
+ intcall(0x13, &ireg, &oreg);
+
+ return -(oreg.eflags & X86_EFLAGS_CF); /* 0 or -1 */
}
static u32 read_mbr_sig(u8 devno, struct edd_info *ei, u32 *mbrsig)
@@ -72,56 +73,46 @@ static u32 read_mbr_sig(u8 devno, struct edd_info *ei, u32 *mbrsig)
static int get_edd_info(u8 devno, struct edd_info *ei)
{
- u16 ax, bx, cx, dx, di;
+ struct biosregs ireg, oreg;
memset(ei, 0, sizeof *ei);
/* Check Extensions Present */
- ax = 0x4100;
- bx = EDDMAGIC1;
- dx = devno;
- asm("pushfl; stc; int $0x13; setc %%al; popfl"
- : "+a" (ax), "+b" (bx), "=c" (cx), "+d" (dx)
- : : "esi", "edi");
+ initregs(&ireg);
+ ireg.ah = 0x41;
+ ireg.bx = EDDMAGIC1;
+ ireg.dl = devno;
+ intcall(0x13, &ireg, &oreg);
- if ((u8)ax)
+ if (oreg.eflags & X86_EFLAGS_CF)
return -1; /* No extended information */
- if (bx != EDDMAGIC2)
+ if (oreg.bx != EDDMAGIC2)
return -1;
ei->device = devno;
- ei->version = ax >> 8; /* EDD version number */
- ei->interface_support = cx; /* EDD functionality subsets */
+ ei->version = oreg.ah; /* EDD version number */
+ ei->interface_support = oreg.cx; /* EDD functionality subsets */
/* Extended Get Device Parameters */
ei->params.length = sizeof(ei->params);
- ax = 0x4800;
- dx = devno;
- asm("pushfl; int $0x13; popfl"
- : "+a" (ax), "+d" (dx), "=m" (ei->params)
- : "S" (&ei->params)
- : "ebx", "ecx", "edi");
+ ireg.ah = 0x48;
+ ireg.si = (size_t)&ei->params;
+ intcall(0x13, &ireg, &oreg);
/* Get legacy CHS parameters */
/* Ralf Brown recommends setting ES:DI to 0:0 */
- ax = 0x0800;
- dx = devno;
- di = 0;
- asm("pushw %%es; "
- "movw %%di,%%es; "
- "pushfl; stc; int $0x13; setc %%al; popfl; "
- "popw %%es"
- : "+a" (ax), "=b" (bx), "=c" (cx), "+d" (dx), "+D" (di)
- : : "esi");
-
- if ((u8)ax == 0) {
- ei->legacy_max_cylinder = (cx >> 8) + ((cx & 0xc0) << 2);
- ei->legacy_max_head = dx >> 8;
- ei->legacy_sectors_per_track = cx & 0x3f;
+ ireg.ah = 0x08;
+ ireg.es = 0;
+ intcall(0x13, &ireg, &oreg);
+
+ if (!(oreg.eflags & X86_EFLAGS_CF)) {
+ ei->legacy_max_cylinder = oreg.ch + ((oreg.cl & 0xc0) << 2);
+ ei->legacy_max_head = oreg.dh;
+ ei->legacy_sectors_per_track = oreg.cl & 0x3f;
}
return 0;
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index 5d84d1c74e4c..0b6e882bef9f 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -192,7 +192,7 @@ ramdisk_max: .long 0x7fffffff
# but leave it at 2 GB to avoid
# possible bootloader bugs.
-kernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment
+kernel_alignment: .long LOAD_PHYSICAL_ALIGN #physical addr alignment
#required for protected mode
#kernel
#ifdef CONFIG_RELOCATABLE
@@ -221,7 +221,7 @@ setup_data: .quad 0 # 64-bit physical pointer to
# End of setup header #####################################################
- .section ".inittext", "ax"
+ .section ".entrytext", "ax"
start_of_setup:
#ifdef SAFE_RESET_DISK_CONTROLLER
# Reset the disk controller.
diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c
index 58f0415d3ae0..140172b895bd 100644
--- a/arch/x86/boot/main.c
+++ b/arch/x86/boot/main.c
@@ -2,6 +2,7 @@
*
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright 2007 rPath, Inc. - All Rights Reserved
+ * Copyright 2009 Intel Corporation; author H. Peter Anvin
*
* This file is part of the Linux kernel, and is made available under
* the terms of the GNU General Public License version 2.
@@ -61,11 +62,10 @@ static void copy_boot_params(void)
*/
static void keyboard_set_repeat(void)
{
- u16 ax = 0x0305;
- u16 bx = 0;
- asm volatile("int $0x16"
- : "+a" (ax), "+b" (bx)
- : : "ecx", "edx", "esi", "edi");
+ struct biosregs ireg;
+ initregs(&ireg);
+ ireg.ax = 0x0305;
+ intcall(0x16, &ireg, NULL);
}
/*
@@ -73,18 +73,22 @@ static void keyboard_set_repeat(void)
*/
static void query_ist(void)
{
+ struct biosregs ireg, oreg;
+
/* Some older BIOSes apparently crash on this call, so filter
it from machines too old to have SpeedStep at all. */
if (cpu.level < 6)
return;
- asm("int $0x15"
- : "=a" (boot_params.ist_info.signature),
- "=b" (boot_params.ist_info.command),
- "=c" (boot_params.ist_info.event),
- "=d" (boot_params.ist_info.perf_level)
- : "a" (0x0000e980), /* IST Support */
- "d" (0x47534943)); /* Request value */
+ initregs(&ireg);
+ ireg.ax = 0xe980; /* IST Support */
+ ireg.edx = 0x47534943; /* Request value */
+ intcall(0x15, &ireg, &oreg);
+
+ boot_params.ist_info.signature = oreg.eax;
+ boot_params.ist_info.command = oreg.ebx;
+ boot_params.ist_info.event = oreg.ecx;
+ boot_params.ist_info.perf_level = oreg.edx;
}
/*
@@ -93,13 +97,12 @@ static void query_ist(void)
static void set_bios_mode(void)
{
#ifdef CONFIG_X86_64
- u32 eax, ebx;
+ struct biosregs ireg;
- eax = 0xec00;
- ebx = 2;
- asm volatile("int $0x15"
- : "+a" (eax), "+b" (ebx)
- : : "ecx", "edx", "esi", "edi");
+ initregs(&ireg);
+ ireg.ax = 0xec00;
+ ireg.bx = 2;
+ intcall(0x15, &ireg, NULL);
#endif
}
diff --git a/arch/x86/boot/mca.c b/arch/x86/boot/mca.c
index 911eaae5d696..a95a531148ef 100644
--- a/arch/x86/boot/mca.c
+++ b/arch/x86/boot/mca.c
@@ -2,6 +2,7 @@
*
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright 2007 rPath, Inc. - All Rights Reserved
+ * Copyright 2009 Intel Corporation; author H. Peter Anvin
*
* This file is part of the Linux kernel, and is made available under
* the terms of the GNU General Public License version 2.
@@ -16,26 +17,22 @@
int query_mca(void)
{
- u8 err;
- u16 es, bx, len;
-
- asm("pushw %%es ; "
- "int $0x15 ; "
- "setc %0 ; "
- "movw %%es, %1 ; "
- "popw %%es"
- : "=acd" (err), "=acdSD" (es), "=b" (bx)
- : "a" (0xc000));
-
- if (err)
+ struct biosregs ireg, oreg;
+ u16 len;
+
+ initregs(&ireg);
+ ireg.ah = 0xc0;
+ intcall(0x15, &ireg, &oreg);
+
+ if (oreg.eflags & X86_EFLAGS_CF)
return -1; /* No MCA present */
- set_fs(es);
- len = rdfs16(bx);
+ set_fs(oreg.es);
+ len = rdfs16(oreg.bx);
if (len > sizeof(boot_params.sys_desc_table))
len = sizeof(boot_params.sys_desc_table);
- copy_from_fs(&boot_params.sys_desc_table, bx, len);
+ copy_from_fs(&boot_params.sys_desc_table, oreg.bx, len);
return 0;
}
diff --git a/arch/x86/boot/memory.c b/arch/x86/boot/memory.c
index 5054c2ddd1a0..d989de810cac 100644
--- a/arch/x86/boot/memory.c
+++ b/arch/x86/boot/memory.c
@@ -25,12 +25,16 @@ struct e820_ext_entry {
static int detect_memory_e820(void)
{
int count = 0;
- u32 next = 0;
- u32 size, id, edi;
- u8 err;
+ struct biosregs ireg, oreg;
struct e820entry *desc = boot_params.e820_map;
static struct e820_ext_entry buf; /* static so it is zeroed */
+ initregs(&ireg);
+ ireg.ax = 0xe820;
+ ireg.cx = sizeof buf;
+ ireg.edx = SMAP;
+ ireg.di = (size_t)&buf;
+
/*
* Set this here so that if the BIOS doesn't change this field
* but still doesn't change %ecx, we're still okay...
@@ -38,22 +42,13 @@ static int detect_memory_e820(void)
buf.ext_flags = 1;
do {
- size = sizeof buf;
-
- /* Important: %edx and %esi are clobbered by some BIOSes,
- so they must be either used for the error output
- or explicitly marked clobbered. Given that, assume there
- is something out there clobbering %ebp and %edi, too. */
- asm("pushl %%ebp; int $0x15; popl %%ebp; setc %0"
- : "=d" (err), "+b" (next), "=a" (id), "+c" (size),
- "=D" (edi), "+m" (buf)
- : "D" (&buf), "d" (SMAP), "a" (0xe820)
- : "esi");
+ intcall(0x15, &ireg, &oreg);
+ ireg.ebx = oreg.ebx; /* for next iteration... */
/* BIOSes which terminate the chain with CF = 1 as opposed
to %ebx = 0 don't always report the SMAP signature on
the final, failing, probe. */
- if (err)
+ if (oreg.eflags & X86_EFLAGS_CF)
break;
/* Some BIOSes stop returning SMAP in the middle of
@@ -61,7 +56,7 @@ static int detect_memory_e820(void)
screwed up the map at that point, we might have a
partial map, the full map, or complete garbage, so
just return failure. */
- if (id != SMAP) {
+ if (oreg.eax != SMAP) {
count = 0;
break;
}
@@ -69,58 +64,62 @@ static int detect_memory_e820(void)
/* ACPI 3.0 added the extended flags support. If bit 0
in the extended flags is zero, we're supposed to simply
ignore the entry -- a backwards incompatible change! */
- if (size > 20 && !(buf.ext_flags & 1))
+ if (oreg.cx > 20 && !(buf.ext_flags & 1))
continue;
*desc++ = buf.std;
count++;
- } while (next && count < ARRAY_SIZE(boot_params.e820_map));
+ } while (ireg.ebx && count < ARRAY_SIZE(boot_params.e820_map));
return boot_params.e820_entries = count;
}
static int detect_memory_e801(void)
{
- u16 ax, bx, cx, dx;
- u8 err;
+ struct biosregs ireg, oreg;
- bx = cx = dx = 0;
- ax = 0xe801;
- asm("stc; int $0x15; setc %0"
- : "=m" (err), "+a" (ax), "+b" (bx), "+c" (cx), "+d" (dx));
+ initregs(&ireg);
+ ireg.ax = 0xe801;
+ intcall(0x15, &ireg, &oreg);
- if (err)
+ if (oreg.eflags & X86_EFLAGS_CF)
return -1;
/* Do we really need to do this? */
- if (cx || dx) {
- ax = cx;
- bx = dx;
+ if (oreg.cx || oreg.dx) {
+ oreg.ax = oreg.cx;
+ oreg.bx = oreg.dx;
}
- if (ax > 15*1024)
+ if (oreg.ax > 15*1024) {
return -1; /* Bogus! */
-
- /* This ignores memory above 16MB if we have a memory hole
- there. If someone actually finds a machine with a memory
- hole at 16MB and no support for 0E820h they should probably
- generate a fake e820 map. */
- boot_params.alt_mem_k = (ax == 15*1024) ? (dx << 6)+ax : ax;
+ } else if (oreg.ax == 15*1024) {
+ boot_params.alt_mem_k = (oreg.dx << 6) + oreg.ax;
+ } else {
+ /*
+ * This ignores memory above 16MB if we have a memory
+ * hole there. If someone actually finds a machine
+ * with a memory hole at 16MB and no support for
+ * 0E820h they should probably generate a fake e820
+ * map.
+ */
+ boot_params.alt_mem_k = oreg.ax;
+ }
return 0;
}
static int detect_memory_88(void)
{
- u16 ax;
- u8 err;
+ struct biosregs ireg, oreg;
- ax = 0x8800;
- asm("stc; int $0x15; setc %0" : "=bcdm" (err), "+a" (ax));
+ initregs(&ireg);
+ ireg.ah = 0x88;
+ intcall(0x15, &ireg, &oreg);
- boot_params.screen_info.ext_mem_k = ax;
+ boot_params.screen_info.ext_mem_k = oreg.ax;
- return -err;
+ return -(oreg.eflags & X86_EFLAGS_CF); /* 0 or -1 */
}
int detect_memory(void)
diff --git a/arch/x86/boot/regs.c b/arch/x86/boot/regs.c
new file mode 100644
index 000000000000..958019b1cfa5
--- /dev/null
+++ b/arch/x86/boot/regs.c
@@ -0,0 +1,29 @@
+/* -----------------------------------------------------------------------
+ *
+ * Copyright 2009 Intel Corporation; author H. Peter Anvin
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2 or (at your
+ * option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * Simple helper function for initializing a register set.
+ *
+ * Note that this sets EFLAGS_CF in the input register set; this
+ * makes it easier to catch functions which do nothing but don't
+ * explicitly set CF.
+ */
+
+#include "boot.h"
+
+void initregs(struct biosregs *reg)
+{
+ memset(reg, 0, sizeof *reg);
+ reg->eflags |= X86_EFLAGS_CF;
+ reg->ds = ds();
+ reg->es = ds();
+ reg->fs = fs();
+ reg->gs = gs();
+}
diff --git a/arch/x86/boot/setup.ld b/arch/x86/boot/setup.ld
index bb8dc2de7969..0f6ec455a2b1 100644
--- a/arch/x86/boot/setup.ld
+++ b/arch/x86/boot/setup.ld
@@ -15,8 +15,11 @@ SECTIONS
. = 497;
.header : { *(.header) }
+ .entrytext : { *(.entrytext) }
.inittext : { *(.inittext) }
.initdata : { *(.initdata) }
+ __end_init = .;
+
.text : { *(.text) }
.text32 : { *(.text32) }
@@ -52,4 +55,7 @@ SECTIONS
. = ASSERT(_end <= 0x8000, "Setup too big!");
. = ASSERT(hdr == 0x1f1, "The setup header has the wrong offset!");
+ /* Necessary for the very-old-loader check to work... */
+ . = ASSERT(__end_init <= 5*512, "init sections too big!");
+
}
diff --git a/arch/x86/boot/tty.c b/arch/x86/boot/tty.c
index 7e8e8b25f5f6..01ec69c901c7 100644
--- a/arch/x86/boot/tty.c
+++ b/arch/x86/boot/tty.c
@@ -2,6 +2,7 @@
*
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright 2007 rPath, Inc. - All Rights Reserved
+ * Copyright 2009 Intel Corporation; author H. Peter Anvin
*
* This file is part of the Linux kernel, and is made available under
* the terms of the GNU General Public License version 2.
@@ -22,24 +23,23 @@
void __attribute__((section(".inittext"))) putchar(int ch)
{
- unsigned char c = ch;
+ struct biosregs ireg;
- if (c == '\n')
+ if (ch == '\n')
putchar('\r'); /* \n -> \r\n */
- /* int $0x10 is known to have bugs involving touching registers
- it shouldn't. Be extra conservative... */
- asm volatile("pushal; pushw %%ds; int $0x10; popw %%ds; popal"
- : : "b" (0x0007), "c" (0x0001), "a" (0x0e00|ch));
+ initregs(&ireg);
+ ireg.bx = 0x0007;
+ ireg.cx = 0x0001;
+ ireg.ah = 0x0e;
+ ireg.al = ch;
+ intcall(0x10, &ireg, NULL);
}
void __attribute__((section(".inittext"))) puts(const char *str)
{
- int n = 0;
- while (*str) {
+ while (*str)
putchar(*str++);
- n++;
- }
}
/*
@@ -49,14 +49,13 @@ void __attribute__((section(".inittext"))) puts(const char *str)
static u8 gettime(void)
{
- u16 ax = 0x0200;
- u16 cx, dx;
+ struct biosregs ireg, oreg;
- asm volatile("int $0x1a"
- : "+a" (ax), "=c" (cx), "=d" (dx)
- : : "ebx", "esi", "edi");
+ initregs(&ireg);
+ ireg.ah = 0x02;
+ intcall(0x1a, &ireg, &oreg);
- return dx >> 8;
+ return oreg.dh;
}
/*
@@ -64,19 +63,24 @@ static u8 gettime(void)
*/
int getchar(void)
{
- u16 ax = 0;
- asm volatile("int $0x16" : "+a" (ax));
+ struct biosregs ireg, oreg;
+
+ initregs(&ireg);
+ /* ireg.ah = 0x00; */
+ intcall(0x16, &ireg, &oreg);
- return ax & 0xff;
+ return oreg.al;
}
static int kbd_pending(void)
{
- u8 pending;
- asm volatile("int $0x16; setnz %0"
- : "=qm" (pending)
- : "a" (0x0100));
- return pending;
+ struct biosregs ireg, oreg;
+
+ initregs(&ireg);
+ ireg.ah = 0x01;
+ intcall(0x16, &ireg, &oreg);
+
+ return !(oreg.eflags & X86_EFLAGS_ZF);
}
void kbd_flush(void)
diff --git a/arch/x86/boot/video-bios.c b/arch/x86/boot/video-bios.c
index 3fa979c9c363..d660be492363 100644
--- a/arch/x86/boot/video-bios.c
+++ b/arch/x86/boot/video-bios.c
@@ -2,6 +2,7 @@
*
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright 2007 rPath, Inc. - All Rights Reserved
+ * Copyright 2009 Intel Corporation; author H. Peter Anvin
*
* This file is part of the Linux kernel, and is made available under
* the terms of the GNU General Public License version 2.
@@ -29,21 +30,21 @@ static int bios_set_mode(struct mode_info *mi)
static int set_bios_mode(u8 mode)
{
- u16 ax;
+ struct biosregs ireg, oreg;
u8 new_mode;
- ax = mode; /* AH=0x00 Set Video Mode */
- asm volatile(INT10
- : "+a" (ax)
- : : "ebx", "ecx", "edx", "esi", "edi");
+ initregs(&ireg);
+ ireg.al = mode; /* AH=0x00 Set Video Mode */
+ intcall(0x10, &ireg, NULL);
- ax = 0x0f00; /* Get Current Video Mode */
- asm volatile(INT10
- : "+a" (ax)
- : : "ebx", "ecx", "edx", "esi", "edi");
+
+ ireg.ah = 0x0f; /* Get Current Video Mode */
+ intcall(0x10, &ireg, &oreg);
do_restore = 1; /* Assume video contents were lost */
- new_mode = ax & 0x7f; /* Not all BIOSes are clean with the top bit */
+
+ /* Not all BIOSes are clean with the top bit */
+ new_mode = ireg.al & 0x7f;
if (new_mode == mode)
return 0; /* Mode change OK */
@@ -53,10 +54,8 @@ static int set_bios_mode(u8 mode)
/* Mode setting failed, but we didn't end up where we
started. That's bad. Try to revert to the original
video mode. */
- ax = boot_params.screen_info.orig_video_mode;
- asm volatile(INT10
- : "+a" (ax)
- : : "ebx", "ecx", "edx", "esi", "edi");
+ ireg.ax = boot_params.screen_info.orig_video_mode;
+ intcall(0x10, &ireg, NULL);
}
#endif
return -1;
diff --git a/arch/x86/boot/video-vesa.c b/arch/x86/boot/video-vesa.c
index 4a58c8ce3f69..c700147d6ffb 100644
--- a/arch/x86/boot/video-vesa.c
+++ b/arch/x86/boot/video-vesa.c
@@ -2,6 +2,7 @@
*
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright 2007 rPath, Inc. - All Rights Reserved
+ * Copyright 2009 Intel Corporation; author H. Peter Anvin
*
* This file is part of the Linux kernel, and is made available under
* the terms of the GNU General Public License version 2.
@@ -31,7 +32,7 @@ static inline void vesa_store_mode_params_graphics(void) {}
static int vesa_probe(void)
{
#if defined(CONFIG_VIDEO_VESA) || defined(CONFIG_FIRMWARE_EDID)
- u16 ax, cx, di;
+ struct biosregs ireg, oreg;
u16 mode;
addr_t mode_ptr;
struct mode_info *mi;
@@ -39,13 +40,12 @@ static int vesa_probe(void)
video_vesa.modes = GET_HEAP(struct mode_info, 0);
- ax = 0x4f00;
- di = (size_t)&vginfo;
- asm(INT10
- : "+a" (ax), "+D" (di), "=m" (vginfo)
- : : "ebx", "ecx", "edx", "esi");
+ initregs(&ireg);
+ ireg.ax = 0x4f00;
+ ireg.di = (size_t)&vginfo;
+ intcall(0x10, &ireg, &oreg);
- if (ax != 0x004f ||
+ if (ireg.ax != 0x004f ||
vginfo.signature != VESA_MAGIC ||
vginfo.version < 0x0102)
return 0; /* Not present */
@@ -65,14 +65,12 @@ static int vesa_probe(void)
memset(&vminfo, 0, sizeof vminfo); /* Just in case... */
- ax = 0x4f01;
- cx = mode;
- di = (size_t)&vminfo;
- asm(INT10
- : "+a" (ax), "+c" (cx), "+D" (di), "=m" (vminfo)
- : : "ebx", "edx", "esi");
+ ireg.ax = 0x4f01;
+ ireg.cx = mode;
+ ireg.di = (size_t)&vminfo;
+ intcall(0x10, &ireg, &oreg);
- if (ax != 0x004f)
+ if (ireg.ax != 0x004f)
continue;
if ((vminfo.mode_attr & 0x15) == 0x05) {
@@ -111,20 +109,19 @@ static int vesa_probe(void)
static int vesa_set_mode(struct mode_info *mode)
{
- u16 ax, bx, cx, di;
+ struct biosregs ireg, oreg;
int is_graphic;
u16 vesa_mode = mode->mode - VIDEO_FIRST_VESA;
memset(&vminfo, 0, sizeof vminfo); /* Just in case... */
- ax = 0x4f01;
- cx = vesa_mode;
- di = (size_t)&vminfo;
- asm(INT10
- : "+a" (ax), "+c" (cx), "+D" (di), "=m" (vminfo)
- : : "ebx", "edx", "esi");
+ initregs(&ireg);
+ ireg.ax = 0x4f01;
+ ireg.cx = vesa_mode;
+ ireg.di = (size_t)&vminfo;
+ intcall(0x10, &ireg, &oreg);
- if (ax != 0x004f)
+ if (oreg.ax != 0x004f)
return -1;
if ((vminfo.mode_attr & 0x15) == 0x05) {
@@ -141,14 +138,12 @@ static int vesa_set_mode(struct mode_info *mode)
}
- ax = 0x4f02;
- bx = vesa_mode;
- di = 0;
- asm volatile(INT10
- : "+a" (ax), "+b" (bx), "+D" (di)
- : : "ecx", "edx", "esi");
+ initregs(&ireg);
+ ireg.ax = 0x4f02;
+ ireg.bx = vesa_mode;
+ intcall(0x10, &ireg, &oreg);
- if (ax != 0x004f)
+ if (oreg.ax != 0x004f)
return -1;
graphic_mode = is_graphic;
@@ -171,50 +166,45 @@ static int vesa_set_mode(struct mode_info *mode)
/* Switch DAC to 8-bit mode */
static void vesa_dac_set_8bits(void)
{
+ struct biosregs ireg, oreg;
u8 dac_size = 6;
/* If possible, switch the DAC to 8-bit mode */
if (vginfo.capabilities & 1) {
- u16 ax, bx;
-
- ax = 0x4f08;
- bx = 0x0800;
- asm volatile(INT10
- : "+a" (ax), "+b" (bx)
- : : "ecx", "edx", "esi", "edi");
-
- if (ax == 0x004f)
- dac_size = bx >> 8;
+ initregs(&ireg);
+ ireg.ax = 0x4f08;
+ ireg.bh = 0x08;
+ intcall(0x10, &ireg, &oreg);
+ if (oreg.ax == 0x004f)
+ dac_size = oreg.bh;
}
/* Set the color sizes to the DAC size, and offsets to 0 */
- boot_params.screen_info.red_size = dac_size;
+ boot_params.screen_info.red_size = dac_size;
boot_params.screen_info.green_size = dac_size;
- boot_params.screen_info.blue_size = dac_size;
- boot_params.screen_info.rsvd_size = dac_size;
+ boot_params.screen_info.blue_size = dac_size;
+ boot_params.screen_info.rsvd_size = dac_size;
- boot_params.screen_info.red_pos = 0;
- boot_params.screen_info.green_pos = 0;
- boot_params.screen_info.blue_pos = 0;
- boot_params.screen_info.rsvd_pos = 0;
+ boot_params.screen_info.red_pos = 0;
+ boot_params.screen_info.green_pos = 0;
+ boot_params.screen_info.blue_pos = 0;
+ boot_params.screen_info.rsvd_pos = 0;
}
/* Save the VESA protected mode info */
static void vesa_store_pm_info(void)
{
- u16 ax, bx, di, es;
+ struct biosregs ireg, oreg;
- ax = 0x4f0a;
- bx = di = 0;
- asm("pushw %%es; "INT10"; movw %%es,%0; popw %%es"
- : "=d" (es), "+a" (ax), "+b" (bx), "+D" (di)
- : : "ecx", "esi");
+ initregs(&ireg);
+ ireg.ax = 0x4f0a;
+ intcall(0x10, &ireg, &oreg);
- if (ax != 0x004f)
+ if (oreg.ax != 0x004f)
return;
- boot_params.screen_info.vesapm_seg = es;
- boot_params.screen_info.vesapm_off = di;
+ boot_params.screen_info.vesapm_seg = oreg.es;
+ boot_params.screen_info.vesapm_off = oreg.di;
}
/*
@@ -252,7 +242,7 @@ static void vesa_store_mode_params_graphics(void)
void vesa_store_edid(void)
{
#ifdef CONFIG_FIRMWARE_EDID
- u16 ax, bx, cx, dx, di;
+ struct biosregs ireg, oreg;
/* Apparently used as a nonsense token... */
memset(&boot_params.edid_info, 0x13, sizeof boot_params.edid_info);
@@ -260,33 +250,26 @@ void vesa_store_edid(void)
if (vginfo.version < 0x0200)
return; /* EDID requires VBE 2.0+ */
- ax = 0x4f15; /* VBE DDC */
- bx = 0x0000; /* Report DDC capabilities */
- cx = 0; /* Controller 0 */
- di = 0; /* ES:DI must be 0 by spec */
-
- /* Note: The VBE DDC spec is different from the main VESA spec;
- we genuinely have to assume all registers are destroyed here. */
-
- asm("pushw %%es; movw %2,%%es; "INT10"; popw %%es"
- : "+a" (ax), "+b" (bx), "+c" (cx), "+D" (di)
- : : "esi", "edx");
+ initregs(&ireg);
+ ireg.ax = 0x4f15; /* VBE DDC */
+ /* ireg.bx = 0x0000; */ /* Report DDC capabilities */
+ /* ireg.cx = 0; */ /* Controller 0 */
+ ireg.es = 0; /* ES:DI must be 0 by spec */
+ intcall(0x10, &ireg, &oreg);
- if (ax != 0x004f)
+ if (oreg.ax != 0x004f)
return; /* No EDID */
/* BH = time in seconds to transfer EDD information */
/* BL = DDC level supported */
- ax = 0x4f15; /* VBE DDC */
- bx = 0x0001; /* Read EDID */
- cx = 0; /* Controller 0 */
- dx = 0; /* EDID block number */
- di =(size_t) &boot_params.edid_info; /* (ES:)Pointer to block */
- asm(INT10
- : "+a" (ax), "+b" (bx), "+d" (dx), "=m" (boot_params.edid_info),
- "+c" (cx), "+D" (di)
- : : "esi");
+ ireg.ax = 0x4f15; /* VBE DDC */
+ ireg.bx = 0x0001; /* Read EDID */
+ /* ireg.cx = 0; */ /* Controller 0 */
+ /* ireg.dx = 0; */ /* EDID block number */
+ ireg.es = ds();
+ ireg.di =(size_t)&boot_params.edid_info; /* (ES:)Pointer to block */
+ intcall(0x10, &ireg, &oreg);
#endif /* CONFIG_FIRMWARE_EDID */
}
diff --git a/arch/x86/boot/video-vga.c b/arch/x86/boot/video-vga.c
index 9e0587a37768..8f8d827e254d 100644
--- a/arch/x86/boot/video-vga.c
+++ b/arch/x86/boot/video-vga.c
@@ -2,6 +2,7 @@
*
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright 2007 rPath, Inc. - All Rights Reserved
+ * Copyright 2009 Intel Corporation; author H. Peter Anvin
*
* This file is part of the Linux kernel, and is made available under
* the terms of the GNU General Public License version 2.
@@ -39,30 +40,30 @@ static __videocard video_vga;
/* Set basic 80x25 mode */
static u8 vga_set_basic_mode(void)
{
+ struct biosregs ireg, oreg;
u16 ax;
u8 rows;
u8 mode;
+ initregs(&ireg);
+
#ifdef CONFIG_VIDEO_400_HACK
if (adapter >= ADAPTER_VGA) {
- asm volatile(INT10
- : : "a" (0x1202), "b" (0x0030)
- : "ecx", "edx", "esi", "edi");
+ ireg.ax = 0x1202;
+ ireg.bx = 0x0030;
+ intcall(0x10, &ireg, NULL);
}
#endif
ax = 0x0f00;
- asm volatile(INT10
- : "+a" (ax)
- : : "ebx", "ecx", "edx", "esi", "edi");
-
- mode = (u8)ax;
+ intcall(0x10, &ireg, &oreg);
+ mode = oreg.al;
set_fs(0);
rows = rdfs8(0x484); /* rows minus one */
#ifndef CONFIG_VIDEO_400_HACK
- if ((ax == 0x5003 || ax == 0x5007) &&
+ if ((oreg.ax == 0x5003 || oreg.ax == 0x5007) &&
(rows == 0 || rows == 24))
return mode;
#endif
@@ -71,10 +72,8 @@ static u8 vga_set_basic_mode(void)
mode = 3;
/* Set the mode */
- ax = mode;
- asm volatile(INT10
- : "+a" (ax)
- : : "ebx", "ecx", "edx", "esi", "edi");
+ ireg.ax = mode; /* AH=0: set mode */
+ intcall(0x10, &ireg, NULL);
do_restore = 1;
return mode;
}
@@ -82,43 +81,69 @@ static u8 vga_set_basic_mode(void)
static void vga_set_8font(void)
{
/* Set 8x8 font - 80x43 on EGA, 80x50 on VGA */
+ struct biosregs ireg;
+
+ initregs(&ireg);
/* Set 8x8 font */
- asm volatile(INT10 : : "a" (0x1112), "b" (0));
+ ireg.ax = 0x1112;
+ /* ireg.bl = 0; */
+ intcall(0x10, &ireg, NULL);
/* Use alternate print screen */
- asm volatile(INT10 : : "a" (0x1200), "b" (0x20));
+ ireg.ax = 0x1200;
+ ireg.bl = 0x20;
+ intcall(0x10, &ireg, NULL);
/* Turn off cursor emulation */
- asm volatile(INT10 : : "a" (0x1201), "b" (0x34));
+ ireg.ax = 0x1201;
+ ireg.bl = 0x34;
+ intcall(0x10, &ireg, NULL);
/* Cursor is scan lines 6-7 */
- asm volatile(INT10 : : "a" (0x0100), "c" (0x0607));
+ ireg.ax = 0x0100;
+ ireg.cx = 0x0607;
+ intcall(0x10, &ireg, NULL);
}
static void vga_set_14font(void)
{
/* Set 9x14 font - 80x28 on VGA */
+ struct biosregs ireg;
+
+ initregs(&ireg);
/* Set 9x14 font */
- asm volatile(INT10 : : "a" (0x1111), "b" (0));
+ ireg.ax = 0x1111;
+ /* ireg.bl = 0; */
+ intcall(0x10, &ireg, NULL);
/* Turn off cursor emulation */
- asm volatile(INT10 : : "a" (0x1201), "b" (0x34));
+ ireg.ax = 0x1201;
+ ireg.bl = 0x34;
+ intcall(0x10, &ireg, NULL);
/* Cursor is scan lines 11-12 */
- asm volatile(INT10 : : "a" (0x0100), "c" (0x0b0c));
+ ireg.ax = 0x0100;
+ ireg.cx = 0x0b0c;
+ intcall(0x10, &ireg, NULL);
}
static void vga_set_80x43(void)
{
/* Set 80x43 mode on VGA (not EGA) */
+ struct biosregs ireg;
+
+ initregs(&ireg);
/* Set 350 scans */
- asm volatile(INT10 : : "a" (0x1201), "b" (0x30));
+ ireg.ax = 0x1201;
+ ireg.bl = 0x30;
+ intcall(0x10, &ireg, NULL);
/* Reset video mode */
- asm volatile(INT10 : : "a" (0x0003));
+ ireg.ax = 0x0003;
+ intcall(0x10, &ireg, NULL);
vga_set_8font();
}
@@ -225,8 +250,6 @@ static int vga_set_mode(struct mode_info *mode)
*/
static int vga_probe(void)
{
- u16 ega_bx;
-
static const char *card_name[] = {
"CGA/MDA/HGC", "EGA", "VGA"
};
@@ -240,26 +263,26 @@ static int vga_probe(void)
sizeof(ega_modes)/sizeof(struct mode_info),
sizeof(vga_modes)/sizeof(struct mode_info),
};
- u8 vga_flag;
- asm(INT10
- : "=b" (ega_bx)
- : "a" (0x1200), "b" (0x10) /* Check EGA/VGA */
- : "ecx", "edx", "esi", "edi");
+ struct biosregs ireg, oreg;
+
+ initregs(&ireg);
+
+ ireg.ax = 0x1200;
+ ireg.bl = 0x10; /* Check EGA/VGA */
+ intcall(0x10, &ireg, &oreg);
#ifndef _WAKEUP
- boot_params.screen_info.orig_video_ega_bx = ega_bx;
+ boot_params.screen_info.orig_video_ega_bx = oreg.bx;
#endif
/* If we have MDA/CGA/HGC then BL will be unchanged at 0x10 */
- if ((u8)ega_bx != 0x10) {
+ if (oreg.bl != 0x10) {
/* EGA/VGA */
- asm(INT10
- : "=a" (vga_flag)
- : "a" (0x1a00)
- : "ebx", "ecx", "edx", "esi", "edi");
+ ireg.ax = 0x1a00;
+ intcall(0x10, &ireg, &oreg);
- if (vga_flag == 0x1a) {
+ if (oreg.al == 0x1a) {
adapter = ADAPTER_VGA;
#ifndef _WAKEUP
boot_params.screen_info.orig_video_isVGA = 1;
diff --git a/arch/x86/boot/video.c b/arch/x86/boot/video.c
index 3bef2c1febe9..bad728b76fc2 100644
--- a/arch/x86/boot/video.c
+++ b/arch/x86/boot/video.c
@@ -2,6 +2,7 @@
*
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright 2007 rPath, Inc. - All Rights Reserved
+ * Copyright 2009 Intel Corporation; author H. Peter Anvin
*
* This file is part of the Linux kernel, and is made available under
* the terms of the GNU General Public License version 2.
@@ -18,33 +19,29 @@
static void store_cursor_position(void)
{
- u16 curpos;
- u16 ax, bx;
+ struct biosregs ireg, oreg;
- ax = 0x0300;
- bx = 0;
- asm(INT10
- : "=d" (curpos), "+a" (ax), "+b" (bx)
- : : "ecx", "esi", "edi");
+ initregs(&ireg);
+ ireg.ah = 0x03;
+ intcall(0x10, &ireg, &oreg);
- boot_params.screen_info.orig_x = curpos;
- boot_params.screen_info.orig_y = curpos >> 8;
+ boot_params.screen_info.orig_x = oreg.dl;
+ boot_params.screen_info.orig_y = oreg.dh;
}
static void store_video_mode(void)
{
- u16 ax, page;
+ struct biosregs ireg, oreg;
/* N.B.: the saving of the video page here is a bit silly,
since we pretty much assume page 0 everywhere. */
- ax = 0x0f00;
- asm(INT10
- : "+a" (ax), "=b" (page)
- : : "ecx", "edx", "esi", "edi");
+ initregs(&ireg);
+ ireg.ah = 0x0f;
+ intcall(0x10, &ireg, &oreg);
/* Not all BIOSes are clean with respect to the top bit */
- boot_params.screen_info.orig_video_mode = ax & 0x7f;
- boot_params.screen_info.orig_video_page = page >> 8;
+ boot_params.screen_info.orig_video_mode = oreg.al & 0x7f;
+ boot_params.screen_info.orig_video_page = oreg.bh;
}
/*
@@ -257,7 +254,7 @@ static void restore_screen(void)
int y;
addr_t dst = 0;
u16 *src = saved.data;
- u16 ax, bx, dx;
+ struct biosregs ireg;
if (graphic_mode)
return; /* Can't restore onto a graphic mode */
@@ -296,12 +293,11 @@ static void restore_screen(void)
}
/* Restore cursor position */
- ax = 0x0200; /* Set cursor position */
- bx = 0; /* Page number (<< 8) */
- dx = (saved.cury << 8)+saved.curx;
- asm volatile(INT10
- : "+a" (ax), "+b" (bx), "+d" (dx)
- : : "ecx", "esi", "edi");
+ initregs(&ireg);
+ ireg.ah = 0x02; /* Set cursor position */
+ ireg.dh = saved.cury;
+ ireg.dl = saved.curx;
+ intcall(0x10, &ireg, NULL);
}
#else
#define save_screen() ((void)0)
diff --git a/arch/x86/boot/video.h b/arch/x86/boot/video.h
index ee63f5d14461..5bb174a997fc 100644
--- a/arch/x86/boot/video.h
+++ b/arch/x86/boot/video.h
@@ -112,20 +112,6 @@ extern int force_x, force_y; /* Don't query the BIOS for cols/rows */
extern int do_restore; /* Restore screen contents */
extern int graphic_mode; /* Graphics mode with linear frame buffer */
-/*
- * int $0x10 is notorious for touching registers it shouldn't.
- * gcc doesn't like %ebp being clobbered, so define it as a push/pop
- * sequence here.
- *
- * A number of systems, including the original PC can clobber %bp in
- * certain circumstances, like when scrolling. There exists at least
- * one Trident video card which could clobber DS under a set of
- * circumstances that we are unlikely to encounter (scrolling when
- * using an extended graphics mode of more than 800x600 pixels), but
- * it's cheap insurance to deal with that here.
- */
-#define INT10 "pushl %%ebp; pushw %%ds; int $0x10; popw %%ds; popl %%ebp"
-
/* Accessing VGA indexed registers */
static inline u8 in_idx(u16 port, u8 index)
{
diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig
index 9fe5d212ab4c..27b8ce0f5908 100644
--- a/arch/x86/configs/x86_64_defconfig
+++ b/arch/x86/configs/x86_64_defconfig
@@ -195,7 +195,6 @@ CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_SMP=y
CONFIG_SPARSE_IRQ=y
-# CONFIG_NUMA_MIGRATE_IRQ_DESC is not set
CONFIG_X86_FIND_SMP_CONFIG=y
CONFIG_X86_MPPARSE=y
# CONFIG_X86_ELAN is not set
diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile
index ebe7deedd5b4..cfb0010fa940 100644
--- a/arch/x86/crypto/Makefile
+++ b/arch/x86/crypto/Makefile
@@ -2,6 +2,8 @@
# Arch-specific CryptoAPI modules.
#
+obj-$(CONFIG_CRYPTO_FPU) += fpu.o
+
obj-$(CONFIG_CRYPTO_AES_586) += aes-i586.o
obj-$(CONFIG_CRYPTO_TWOFISH_586) += twofish-i586.o
obj-$(CONFIG_CRYPTO_SALSA20_586) += salsa20-i586.o
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c
index 02af0af65497..4e663398f77f 100644
--- a/arch/x86/crypto/aesni-intel_glue.c
+++ b/arch/x86/crypto/aesni-intel_glue.c
@@ -21,6 +21,22 @@
#include <asm/i387.h>
#include <asm/aes.h>
+#if defined(CONFIG_CRYPTO_CTR) || defined(CONFIG_CRYPTO_CTR_MODULE)
+#define HAS_CTR
+#endif
+
+#if defined(CONFIG_CRYPTO_LRW) || defined(CONFIG_CRYPTO_LRW_MODULE)
+#define HAS_LRW
+#endif
+
+#if defined(CONFIG_CRYPTO_PCBC) || defined(CONFIG_CRYPTO_PCBC_MODULE)
+#define HAS_PCBC
+#endif
+
+#if defined(CONFIG_CRYPTO_XTS) || defined(CONFIG_CRYPTO_XTS_MODULE)
+#define HAS_XTS
+#endif
+
struct async_aes_ctx {
struct cryptd_ablkcipher *cryptd_tfm;
};
@@ -137,6 +153,41 @@ static struct crypto_alg aesni_alg = {
}
};
+static void __aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+ struct crypto_aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(tfm));
+
+ aesni_enc(ctx, dst, src);
+}
+
+static void __aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+ struct crypto_aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(tfm));
+
+ aesni_dec(ctx, dst, src);
+}
+
+static struct crypto_alg __aesni_alg = {
+ .cra_name = "__aes-aesni",
+ .cra_driver_name = "__driver-aes-aesni",
+ .cra_priority = 0,
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypto_aes_ctx)+AESNI_ALIGN-1,
+ .cra_alignmask = 0,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(__aesni_alg.cra_list),
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = AES_MIN_KEY_SIZE,
+ .cia_max_keysize = AES_MAX_KEY_SIZE,
+ .cia_setkey = aes_set_key,
+ .cia_encrypt = __aes_encrypt,
+ .cia_decrypt = __aes_decrypt
+ }
+ }
+};
+
static int ecb_encrypt(struct blkcipher_desc *desc,
struct scatterlist *dst, struct scatterlist *src,
unsigned int nbytes)
@@ -277,8 +328,16 @@ static int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key,
unsigned int key_len)
{
struct async_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+ struct crypto_ablkcipher *child = &ctx->cryptd_tfm->base;
+ int err;
- return crypto_ablkcipher_setkey(&ctx->cryptd_tfm->base, key, key_len);
+ crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+ crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(tfm)
+ & CRYPTO_TFM_REQ_MASK);
+ err = crypto_ablkcipher_setkey(child, key, key_len);
+ crypto_ablkcipher_set_flags(tfm, crypto_ablkcipher_get_flags(child)
+ & CRYPTO_TFM_RES_MASK);
+ return err;
}
static int ablk_encrypt(struct ablkcipher_request *req)
@@ -411,6 +470,163 @@ static struct crypto_alg ablk_cbc_alg = {
},
};
+#ifdef HAS_CTR
+static int ablk_ctr_init(struct crypto_tfm *tfm)
+{
+ struct cryptd_ablkcipher *cryptd_tfm;
+
+ cryptd_tfm = cryptd_alloc_ablkcipher("fpu(ctr(__driver-aes-aesni))",
+ 0, 0);
+ if (IS_ERR(cryptd_tfm))
+ return PTR_ERR(cryptd_tfm);
+ ablk_init_common(tfm, cryptd_tfm);
+ return 0;
+}
+
+static struct crypto_alg ablk_ctr_alg = {
+ .cra_name = "ctr(aes)",
+ .cra_driver_name = "ctr-aes-aesni",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct async_aes_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(ablk_ctr_alg.cra_list),
+ .cra_init = ablk_ctr_init,
+ .cra_exit = ablk_exit,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = ablk_set_key,
+ .encrypt = ablk_encrypt,
+ .decrypt = ablk_decrypt,
+ .geniv = "chainiv",
+ },
+ },
+};
+#endif
+
+#ifdef HAS_LRW
+static int ablk_lrw_init(struct crypto_tfm *tfm)
+{
+ struct cryptd_ablkcipher *cryptd_tfm;
+
+ cryptd_tfm = cryptd_alloc_ablkcipher("fpu(lrw(__driver-aes-aesni))",
+ 0, 0);
+ if (IS_ERR(cryptd_tfm))
+ return PTR_ERR(cryptd_tfm);
+ ablk_init_common(tfm, cryptd_tfm);
+ return 0;
+}
+
+static struct crypto_alg ablk_lrw_alg = {
+ .cra_name = "lrw(aes)",
+ .cra_driver_name = "lrw-aes-aesni",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct async_aes_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(ablk_lrw_alg.cra_list),
+ .cra_init = ablk_lrw_init,
+ .cra_exit = ablk_exit,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE + AES_BLOCK_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE + AES_BLOCK_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = ablk_set_key,
+ .encrypt = ablk_encrypt,
+ .decrypt = ablk_decrypt,
+ },
+ },
+};
+#endif
+
+#ifdef HAS_PCBC
+static int ablk_pcbc_init(struct crypto_tfm *tfm)
+{
+ struct cryptd_ablkcipher *cryptd_tfm;
+
+ cryptd_tfm = cryptd_alloc_ablkcipher("fpu(pcbc(__driver-aes-aesni))",
+ 0, 0);
+ if (IS_ERR(cryptd_tfm))
+ return PTR_ERR(cryptd_tfm);
+ ablk_init_common(tfm, cryptd_tfm);
+ return 0;
+}
+
+static struct crypto_alg ablk_pcbc_alg = {
+ .cra_name = "pcbc(aes)",
+ .cra_driver_name = "pcbc-aes-aesni",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct async_aes_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(ablk_pcbc_alg.cra_list),
+ .cra_init = ablk_pcbc_init,
+ .cra_exit = ablk_exit,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = ablk_set_key,
+ .encrypt = ablk_encrypt,
+ .decrypt = ablk_decrypt,
+ },
+ },
+};
+#endif
+
+#ifdef HAS_XTS
+static int ablk_xts_init(struct crypto_tfm *tfm)
+{
+ struct cryptd_ablkcipher *cryptd_tfm;
+
+ cryptd_tfm = cryptd_alloc_ablkcipher("fpu(xts(__driver-aes-aesni))",
+ 0, 0);
+ if (IS_ERR(cryptd_tfm))
+ return PTR_ERR(cryptd_tfm);
+ ablk_init_common(tfm, cryptd_tfm);
+ return 0;
+}
+
+static struct crypto_alg ablk_xts_alg = {
+ .cra_name = "xts(aes)",
+ .cra_driver_name = "xts-aes-aesni",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct async_aes_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(ablk_xts_alg.cra_list),
+ .cra_init = ablk_xts_init,
+ .cra_exit = ablk_exit,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = 2 * AES_MIN_KEY_SIZE,
+ .max_keysize = 2 * AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = ablk_set_key,
+ .encrypt = ablk_encrypt,
+ .decrypt = ablk_decrypt,
+ },
+ },
+};
+#endif
+
static int __init aesni_init(void)
{
int err;
@@ -421,6 +637,8 @@ static int __init aesni_init(void)
}
if ((err = crypto_register_alg(&aesni_alg)))
goto aes_err;
+ if ((err = crypto_register_alg(&__aesni_alg)))
+ goto __aes_err;
if ((err = crypto_register_alg(&blk_ecb_alg)))
goto blk_ecb_err;
if ((err = crypto_register_alg(&blk_cbc_alg)))
@@ -429,9 +647,41 @@ static int __init aesni_init(void)
goto ablk_ecb_err;
if ((err = crypto_register_alg(&ablk_cbc_alg)))
goto ablk_cbc_err;
+#ifdef HAS_CTR
+ if ((err = crypto_register_alg(&ablk_ctr_alg)))
+ goto ablk_ctr_err;
+#endif
+#ifdef HAS_LRW
+ if ((err = crypto_register_alg(&ablk_lrw_alg)))
+ goto ablk_lrw_err;
+#endif
+#ifdef HAS_PCBC
+ if ((err = crypto_register_alg(&ablk_pcbc_alg)))
+ goto ablk_pcbc_err;
+#endif
+#ifdef HAS_XTS
+ if ((err = crypto_register_alg(&ablk_xts_alg)))
+ goto ablk_xts_err;
+#endif
return err;
+#ifdef HAS_XTS
+ablk_xts_err:
+#endif
+#ifdef HAS_PCBC
+ crypto_unregister_alg(&ablk_pcbc_alg);
+ablk_pcbc_err:
+#endif
+#ifdef HAS_LRW
+ crypto_unregister_alg(&ablk_lrw_alg);
+ablk_lrw_err:
+#endif
+#ifdef HAS_CTR
+ crypto_unregister_alg(&ablk_ctr_alg);
+ablk_ctr_err:
+#endif
+ crypto_unregister_alg(&ablk_cbc_alg);
ablk_cbc_err:
crypto_unregister_alg(&ablk_ecb_alg);
ablk_ecb_err:
@@ -439,6 +689,8 @@ ablk_ecb_err:
blk_cbc_err:
crypto_unregister_alg(&blk_ecb_alg);
blk_ecb_err:
+ crypto_unregister_alg(&__aesni_alg);
+__aes_err:
crypto_unregister_alg(&aesni_alg);
aes_err:
return err;
@@ -446,10 +698,23 @@ aes_err:
static void __exit aesni_exit(void)
{
+#ifdef HAS_XTS
+ crypto_unregister_alg(&ablk_xts_alg);
+#endif
+#ifdef HAS_PCBC
+ crypto_unregister_alg(&ablk_pcbc_alg);
+#endif
+#ifdef HAS_LRW
+ crypto_unregister_alg(&ablk_lrw_alg);
+#endif
+#ifdef HAS_CTR
+ crypto_unregister_alg(&ablk_ctr_alg);
+#endif
crypto_unregister_alg(&ablk_cbc_alg);
crypto_unregister_alg(&ablk_ecb_alg);
crypto_unregister_alg(&blk_cbc_alg);
crypto_unregister_alg(&blk_ecb_alg);
+ crypto_unregister_alg(&__aesni_alg);
crypto_unregister_alg(&aesni_alg);
}
diff --git a/arch/x86/crypto/fpu.c b/arch/x86/crypto/fpu.c
new file mode 100644
index 000000000000..5f9781a3815f
--- /dev/null
+++ b/arch/x86/crypto/fpu.c
@@ -0,0 +1,166 @@
+/*
+ * FPU: Wrapper for blkcipher touching fpu
+ *
+ * Copyright (c) Intel Corp.
+ * Author: Huang Ying <ying.huang@intel.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 <crypto/algapi.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/i387.h>
+
+struct crypto_fpu_ctx {
+ struct crypto_blkcipher *child;
+};
+
+static int crypto_fpu_setkey(struct crypto_tfm *parent, const u8 *key,
+ unsigned int keylen)
+{
+ struct crypto_fpu_ctx *ctx = crypto_tfm_ctx(parent);
+ struct crypto_blkcipher *child = ctx->child;
+ int err;
+
+ crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+ crypto_blkcipher_set_flags(child, crypto_tfm_get_flags(parent) &
+ CRYPTO_TFM_REQ_MASK);
+ err = crypto_blkcipher_setkey(child, key, keylen);
+ crypto_tfm_set_flags(parent, crypto_blkcipher_get_flags(child) &
+ CRYPTO_TFM_RES_MASK);
+ return err;
+}
+
+static int crypto_fpu_encrypt(struct blkcipher_desc *desc_in,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ int err;
+ struct crypto_fpu_ctx *ctx = crypto_blkcipher_ctx(desc_in->tfm);
+ struct crypto_blkcipher *child = ctx->child;
+ struct blkcipher_desc desc = {
+ .tfm = child,
+ .info = desc_in->info,
+ .flags = desc_in->flags,
+ };
+
+ kernel_fpu_begin();
+ err = crypto_blkcipher_crt(desc.tfm)->encrypt(&desc, dst, src, nbytes);
+ kernel_fpu_end();
+ return err;
+}
+
+static int crypto_fpu_decrypt(struct blkcipher_desc *desc_in,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ int err;
+ struct crypto_fpu_ctx *ctx = crypto_blkcipher_ctx(desc_in->tfm);
+ struct crypto_blkcipher *child = ctx->child;
+ struct blkcipher_desc desc = {
+ .tfm = child,
+ .info = desc_in->info,
+ .flags = desc_in->flags,
+ };
+
+ kernel_fpu_begin();
+ err = crypto_blkcipher_crt(desc.tfm)->decrypt(&desc, dst, src, nbytes);
+ kernel_fpu_end();
+ return err;
+}
+
+static int crypto_fpu_init_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
+ struct crypto_spawn *spawn = crypto_instance_ctx(inst);
+ struct crypto_fpu_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_blkcipher *cipher;
+
+ cipher = crypto_spawn_blkcipher(spawn);
+ if (IS_ERR(cipher))
+ return PTR_ERR(cipher);
+
+ ctx->child = cipher;
+ return 0;
+}
+
+static void crypto_fpu_exit_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_fpu_ctx *ctx = crypto_tfm_ctx(tfm);
+ crypto_free_blkcipher(ctx->child);
+}
+
+static struct crypto_instance *crypto_fpu_alloc(struct rtattr **tb)
+{
+ struct crypto_instance *inst;
+ struct crypto_alg *alg;
+ int err;
+
+ err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+ if (err)
+ return ERR_PTR(err);
+
+ alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_BLKCIPHER,
+ CRYPTO_ALG_TYPE_MASK);
+ if (IS_ERR(alg))
+ return ERR_CAST(alg);
+
+ inst = crypto_alloc_instance("fpu", alg);
+ if (IS_ERR(inst))
+ goto out_put_alg;
+
+ inst->alg.cra_flags = alg->cra_flags;
+ inst->alg.cra_priority = alg->cra_priority;
+ inst->alg.cra_blocksize = alg->cra_blocksize;
+ inst->alg.cra_alignmask = alg->cra_alignmask;
+ inst->alg.cra_type = alg->cra_type;
+ inst->alg.cra_blkcipher.ivsize = alg->cra_blkcipher.ivsize;
+ inst->alg.cra_blkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
+ inst->alg.cra_blkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
+ inst->alg.cra_ctxsize = sizeof(struct crypto_fpu_ctx);
+ inst->alg.cra_init = crypto_fpu_init_tfm;
+ inst->alg.cra_exit = crypto_fpu_exit_tfm;
+ inst->alg.cra_blkcipher.setkey = crypto_fpu_setkey;
+ inst->alg.cra_blkcipher.encrypt = crypto_fpu_encrypt;
+ inst->alg.cra_blkcipher.decrypt = crypto_fpu_decrypt;
+
+out_put_alg:
+ crypto_mod_put(alg);
+ return inst;
+}
+
+static void crypto_fpu_free(struct crypto_instance *inst)
+{
+ crypto_drop_spawn(crypto_instance_ctx(inst));
+ kfree(inst);
+}
+
+static struct crypto_template crypto_fpu_tmpl = {
+ .name = "fpu",
+ .alloc = crypto_fpu_alloc,
+ .free = crypto_fpu_free,
+ .module = THIS_MODULE,
+};
+
+static int __init crypto_fpu_module_init(void)
+{
+ return crypto_register_template(&crypto_fpu_tmpl);
+}
+
+static void __exit crypto_fpu_module_exit(void)
+{
+ crypto_unregister_template(&crypto_fpu_tmpl);
+}
+
+module_init(crypto_fpu_module_init);
+module_exit(crypto_fpu_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("FPU block cipher wrapper");
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index a505202086e8..dcef387ddc36 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -830,4 +830,5 @@ ia32_sys_call_table:
.quad sys_inotify_init1
.quad compat_sys_preadv
.quad compat_sys_pwritev
+ .quad compat_sys_rt_tgsigqueueinfo /* 335 */
ia32_syscall_end:
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c
index efac92fd1efb..085a8c35f149 100644
--- a/arch/x86/ia32/sys_ia32.c
+++ b/arch/x86/ia32/sys_ia32.c
@@ -129,21 +129,12 @@ asmlinkage long sys32_fstatat(unsigned int dfd, char __user *filename,
struct stat64 __user *statbuf, int flag)
{
struct kstat stat;
- int error = -EINVAL;
+ int error;
- if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
- goto out;
-
- if (flag & AT_SYMLINK_NOFOLLOW)
- error = vfs_lstat_fd(dfd, filename, &stat);
- else
- error = vfs_stat_fd(dfd, filename, &stat);
-
- if (!error)
- error = cp_stat64(statbuf, &stat);
-
-out:
- return error;
+ error = vfs_fstatat(dfd, filename, &stat, flag);
+ if (error)
+ return error;
+ return cp_stat64(statbuf, &stat);
}
/*
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index f6aa18eadf71..1a37bcdc8606 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -3,6 +3,7 @@
#include <linux/types.h>
#include <linux/stddef.h>
+#include <linux/stringify.h>
#include <asm/asm.h>
/*
@@ -74,6 +75,22 @@ static inline void alternatives_smp_switch(int smp) {}
const unsigned char *const *find_nop_table(void);
+/* alternative assembly primitive: */
+#define ALTERNATIVE(oldinstr, newinstr, feature) \
+ \
+ "661:\n\t" oldinstr "\n662:\n" \
+ ".section .altinstructions,\"a\"\n" \
+ _ASM_ALIGN "\n" \
+ _ASM_PTR "661b\n" /* label */ \
+ _ASM_PTR "663f\n" /* new instruction */ \
+ " .byte " __stringify(feature) "\n" /* feature bit */ \
+ " .byte 662b-661b\n" /* sourcelen */ \
+ " .byte 664f-663f\n" /* replacementlen */ \
+ ".previous\n" \
+ ".section .altinstr_replacement, \"ax\"\n" \
+ "663:\n\t" newinstr "\n664:\n" /* replacement */ \
+ ".previous"
+
/*
* Alternative instructions for different CPU types or capabilities.
*
@@ -87,18 +104,7 @@ const unsigned char *const *find_nop_table(void);
* without volatile and memory clobber.
*/
#define alternative(oldinstr, newinstr, feature) \
- asm volatile ("661:\n\t" oldinstr "\n662:\n" \
- ".section .altinstructions,\"a\"\n" \
- _ASM_ALIGN "\n" \
- _ASM_PTR "661b\n" /* label */ \
- _ASM_PTR "663f\n" /* new instruction */ \
- " .byte %c0\n" /* feature bit */ \
- " .byte 662b-661b\n" /* sourcelen */ \
- " .byte 664f-663f\n" /* replacementlen */ \
- ".previous\n" \
- ".section .altinstr_replacement,\"ax\"\n" \
- "663:\n\t" newinstr "\n664:\n" /* replacement */ \
- ".previous" :: "i" (feature) : "memory")
+ asm volatile (ALTERNATIVE(oldinstr, newinstr, feature) : : : "memory")
/*
* Alternative inline assembly with input.
@@ -109,35 +115,16 @@ const unsigned char *const *find_nop_table(void);
* Best is to use constraints that are fixed size (like (%1) ... "r")
* If you use variable sized constraints like "m" or "g" in the
* replacement make sure to pad to the worst case length.
+ * Leaving an unused argument 0 to keep API compatibility.
*/
#define alternative_input(oldinstr, newinstr, feature, input...) \
- asm volatile ("661:\n\t" oldinstr "\n662:\n" \
- ".section .altinstructions,\"a\"\n" \
- _ASM_ALIGN "\n" \
- _ASM_PTR "661b\n" /* label */ \
- _ASM_PTR "663f\n" /* new instruction */ \
- " .byte %c0\n" /* feature bit */ \
- " .byte 662b-661b\n" /* sourcelen */ \
- " .byte 664f-663f\n" /* replacementlen */ \
- ".previous\n" \
- ".section .altinstr_replacement,\"ax\"\n" \
- "663:\n\t" newinstr "\n664:\n" /* replacement */ \
- ".previous" :: "i" (feature), ##input)
+ asm volatile (ALTERNATIVE(oldinstr, newinstr, feature) \
+ : : "i" (0), ## input)
/* Like alternative_input, but with a single output argument */
#define alternative_io(oldinstr, newinstr, feature, output, input...) \
- asm volatile ("661:\n\t" oldinstr "\n662:\n" \
- ".section .altinstructions,\"a\"\n" \
- _ASM_ALIGN "\n" \
- _ASM_PTR "661b\n" /* label */ \
- _ASM_PTR "663f\n" /* new instruction */ \
- " .byte %c[feat]\n" /* feature bit */ \
- " .byte 662b-661b\n" /* sourcelen */ \
- " .byte 664f-663f\n" /* replacementlen */ \
- ".previous\n" \
- ".section .altinstr_replacement,\"ax\"\n" \
- "663:\n\t" newinstr "\n664:\n" /* replacement */ \
- ".previous" : output : [feat] "i" (feature), ##input)
+ asm volatile (ALTERNATIVE(oldinstr, newinstr, feature) \
+ : output : "i" (0), ## input)
/*
* use this macro(s) if you need more than one output parameter
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 42f2f8377422..229d0be184a2 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -107,8 +107,7 @@ extern u32 native_safe_apic_wait_icr_idle(void);
extern void native_apic_icr_write(u32 low, u32 id);
extern u64 native_apic_icr_read(void);
-#define EIM_8BIT_APIC_ID 0
-#define EIM_32BIT_APIC_ID 1
+extern int x2apic_mode;
#ifdef CONFIG_X86_X2APIC
/*
@@ -166,10 +165,9 @@ static inline u64 native_x2apic_icr_read(void)
return val;
}
-extern int x2apic, x2apic_phys;
+extern int x2apic_phys;
extern void check_x2apic(void);
extern void enable_x2apic(void);
-extern void enable_IR_x2apic(void);
extern void x2apic_icr_write(u32 low, u32 id);
static inline int x2apic_enabled(void)
{
@@ -183,6 +181,8 @@ static inline int x2apic_enabled(void)
return 1;
return 0;
}
+
+#define x2apic_supported() (cpu_has_x2apic)
#else
static inline void check_x2apic(void)
{
@@ -190,28 +190,20 @@ static inline void check_x2apic(void)
static inline void enable_x2apic(void)
{
}
-static inline void enable_IR_x2apic(void)
-{
-}
static inline int x2apic_enabled(void)
{
return 0;
}
-#define x2apic 0
-
+#define x2apic_preenabled 0
+#define x2apic_supported() 0
#endif
-extern int get_physical_broadcast(void);
+extern void enable_IR_x2apic(void);
-#ifdef CONFIG_X86_X2APIC
-static inline void ack_x2APIC_irq(void)
-{
- /* Docs say use 0 for future compatibility */
- native_apic_msr_write(APIC_EOI, 0);
-}
-#endif
+extern int get_physical_broadcast(void);
+extern void apic_disable(void);
extern int lapic_get_maxlvt(void);
extern void clear_local_APIC(void);
extern void connect_bsp_APIC(void);
@@ -252,7 +244,7 @@ static inline void lapic_shutdown(void) { }
#define local_apic_timer_c2_ok 1
static inline void init_apic_mappings(void) { }
static inline void disable_local_APIC(void) { }
-
+static inline void apic_disable(void) { }
#endif /* !CONFIG_X86_LOCAL_APIC */
#ifdef CONFIG_X86_64
@@ -478,6 +470,9 @@ static inline unsigned int read_apic_id(void)
extern void default_setup_apic_routing(void);
#ifdef CONFIG_X86_32
+
+extern struct apic apic_default;
+
/*
* Set up the logical destination ID.
*
diff --git a/arch/x86/include/asm/boot.h b/arch/x86/include/asm/boot.h
index 6ba23dd9fc92..641debb17af2 100644
--- a/arch/x86/include/asm/boot.h
+++ b/arch/x86/include/asm/boot.h
@@ -8,10 +8,19 @@
#ifdef __KERNEL__
+#include <asm/page_types.h>
+
+/* Permitted physical alignment of the kernel */
+#if defined(CONFIG_X86_64) && CONFIG_PHYSICAL_ALIGN < PMD_PAGE_SIZE
+#define LOAD_PHYSICAL_ALIGN PMD_PAGE_SIZE
+#else
+#define LOAD_PHYSICAL_ALIGN CONFIG_PHYSICAL_ALIGN
+#endif
+
/* Physical address where kernel should be loaded. */
#define LOAD_PHYSICAL_ADDR ((CONFIG_PHYSICAL_START \
- + (CONFIG_PHYSICAL_ALIGN - 1)) \
- & ~(CONFIG_PHYSICAL_ALIGN - 1))
+ + (LOAD_PHYSICAL_ALIGN - 1)) \
+ & ~(LOAD_PHYSICAL_ALIGN - 1))
#ifdef CONFIG_KERNEL_BZIP2
#define BOOT_HEAP_SIZE 0x400000
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index bb83b1c397aa..dd68bf5c1e32 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -22,7 +22,7 @@
#define X86_FEATURE_TSC (0*32+ 4) /* Time Stamp Counter */
#define X86_FEATURE_MSR (0*32+ 5) /* Model-Specific Registers */
#define X86_FEATURE_PAE (0*32+ 6) /* Physical Address Extensions */
-#define X86_FEATURE_MCE (0*32+ 7) /* Machine Check Architecture */
+#define X86_FEATURE_MCE (0*32+ 7) /* Machine Check Exception */
#define X86_FEATURE_CX8 (0*32+ 8) /* CMPXCHG8 instruction */
#define X86_FEATURE_APIC (0*32+ 9) /* Onboard APIC */
#define X86_FEATURE_SEP (0*32+11) /* SYSENTER/SYSEXIT */
@@ -115,6 +115,8 @@
#define X86_FEATURE_XMM4_1 (4*32+19) /* "sse4_1" SSE-4.1 */
#define X86_FEATURE_XMM4_2 (4*32+20) /* "sse4_2" SSE-4.2 */
#define X86_FEATURE_X2APIC (4*32+21) /* x2APIC */
+#define X86_FEATURE_MOVBE (4*32+22) /* MOVBE instruction */
+#define X86_FEATURE_POPCNT (4*32+23) /* POPCNT instruction */
#define X86_FEATURE_AES (4*32+25) /* AES instructions */
#define X86_FEATURE_XSAVE (4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
#define X86_FEATURE_OSXSAVE (4*32+27) /* "" XSAVE enabled in the OS */
diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h
index 5623c50d67b2..c45f415ce315 100644
--- a/arch/x86/include/asm/desc.h
+++ b/arch/x86/include/asm/desc.h
@@ -37,7 +37,7 @@ extern gate_desc idt_table[];
struct gdt_page {
struct desc_struct gdt[GDT_ENTRIES];
} __attribute__((aligned(PAGE_SIZE)));
-DECLARE_PER_CPU(struct gdt_page, gdt_page);
+DECLARE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page);
static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
{
diff --git a/arch/x86/include/asm/ds.h b/arch/x86/include/asm/ds.h
index a8f672ba100c..70dac199b093 100644
--- a/arch/x86/include/asm/ds.h
+++ b/arch/x86/include/asm/ds.h
@@ -15,8 +15,8 @@
* - buffer allocation (memory accounting)
*
*
- * Copyright (C) 2007-2008 Intel Corporation.
- * Markus Metzger <markus.t.metzger@intel.com>, 2007-2008
+ * Copyright (C) 2007-2009 Intel Corporation.
+ * Markus Metzger <markus.t.metzger@intel.com>, 2007-2009
*/
#ifndef _ASM_X86_DS_H
@@ -83,8 +83,10 @@ enum ds_feature {
* The interrupt threshold is independent from the overflow callback
* to allow users to use their own overflow interrupt handling mechanism.
*
- * task: the task to request recording for;
- * NULL for per-cpu recording on the current cpu
+ * The function might sleep.
+ *
+ * task: the task to request recording for
+ * cpu: the cpu to request recording for
* base: the base pointer for the (non-pageable) buffer;
* size: the size of the provided buffer in bytes
* ovfl: pointer to a function to be called on buffer overflow;
@@ -93,19 +95,28 @@ enum ds_feature {
* -1 if no interrupt threshold is requested.
* flags: a bit-mask of the above flags
*/
-extern struct bts_tracer *ds_request_bts(struct task_struct *task,
- void *base, size_t size,
- bts_ovfl_callback_t ovfl,
- size_t th, unsigned int flags);
-extern struct pebs_tracer *ds_request_pebs(struct task_struct *task,
- void *base, size_t size,
- pebs_ovfl_callback_t ovfl,
- size_t th, unsigned int flags);
+extern struct bts_tracer *ds_request_bts_task(struct task_struct *task,
+ void *base, size_t size,
+ bts_ovfl_callback_t ovfl,
+ size_t th, unsigned int flags);
+extern struct bts_tracer *ds_request_bts_cpu(int cpu, void *base, size_t size,
+ bts_ovfl_callback_t ovfl,
+ size_t th, unsigned int flags);
+extern struct pebs_tracer *ds_request_pebs_task(struct task_struct *task,
+ void *base, size_t size,
+ pebs_ovfl_callback_t ovfl,
+ size_t th, unsigned int flags);
+extern struct pebs_tracer *ds_request_pebs_cpu(int cpu,
+ void *base, size_t size,
+ pebs_ovfl_callback_t ovfl,
+ size_t th, unsigned int flags);
/*
* Release BTS or PEBS resources
* Suspend and resume BTS or PEBS tracing
*
+ * Must be called with irq's enabled.
+ *
* tracer: the tracer handle returned from ds_request_~()
*/
extern void ds_release_bts(struct bts_tracer *tracer);
@@ -115,6 +126,28 @@ extern void ds_release_pebs(struct pebs_tracer *tracer);
extern void ds_suspend_pebs(struct pebs_tracer *tracer);
extern void ds_resume_pebs(struct pebs_tracer *tracer);
+/*
+ * Release BTS or PEBS resources
+ * Suspend and resume BTS or PEBS tracing
+ *
+ * Cpu tracers must call this on the traced cpu.
+ * Task tracers must call ds_release_~_noirq() for themselves.
+ *
+ * May be called with irq's disabled.
+ *
+ * Returns 0 if successful;
+ * -EPERM if the cpu tracer does not trace the current cpu.
+ * -EPERM if the task tracer does not trace itself.
+ *
+ * tracer: the tracer handle returned from ds_request_~()
+ */
+extern int ds_release_bts_noirq(struct bts_tracer *tracer);
+extern int ds_suspend_bts_noirq(struct bts_tracer *tracer);
+extern int ds_resume_bts_noirq(struct bts_tracer *tracer);
+extern int ds_release_pebs_noirq(struct pebs_tracer *tracer);
+extern int ds_suspend_pebs_noirq(struct pebs_tracer *tracer);
+extern int ds_resume_pebs_noirq(struct pebs_tracer *tracer);
+
/*
* The raw DS buffer state as it is used for BTS and PEBS recording.
@@ -170,9 +203,9 @@ struct bts_struct {
} lbr;
/* BTS_TASK_ARRIVES or BTS_TASK_DEPARTS */
struct {
- __u64 jiffies;
+ __u64 clock;
pid_t pid;
- } timestamp;
+ } event;
} variant;
};
@@ -201,8 +234,12 @@ struct bts_trace {
struct pebs_trace {
struct ds_trace ds;
- /* the PEBS reset value */
- unsigned long long reset_value;
+ /* the number of valid counters in the below array */
+ unsigned int counters;
+
+#define MAX_PEBS_COUNTERS 4
+ /* the counter reset value */
+ unsigned long long counter_reset[MAX_PEBS_COUNTERS];
};
@@ -237,9 +274,11 @@ extern int ds_reset_pebs(struct pebs_tracer *tracer);
* Returns 0 on success; -Eerrno on error
*
* tracer: the tracer handle returned from ds_request_pebs()
+ * counter: the index of the counter
* value: the new counter reset value
*/
-extern int ds_set_pebs_reset(struct pebs_tracer *tracer, u64 value);
+extern int ds_set_pebs_reset(struct pebs_tracer *tracer,
+ unsigned int counter, u64 value);
/*
* Initialization
@@ -252,21 +291,12 @@ extern void __cpuinit ds_init_intel(struct cpuinfo_x86 *);
*/
extern void ds_switch_to(struct task_struct *prev, struct task_struct *next);
-/*
- * Task clone/init and cleanup work
- */
-extern void ds_copy_thread(struct task_struct *tsk, struct task_struct *father);
-extern void ds_exit_thread(struct task_struct *tsk);
-
#else /* CONFIG_X86_DS */
struct cpuinfo_x86;
static inline void __cpuinit ds_init_intel(struct cpuinfo_x86 *ignored) {}
static inline void ds_switch_to(struct task_struct *prev,
struct task_struct *next) {}
-static inline void ds_copy_thread(struct task_struct *tsk,
- struct task_struct *father) {}
-static inline void ds_exit_thread(struct task_struct *tsk) {}
#endif /* CONFIG_X86_DS */
#endif /* _ASM_X86_DS_H */
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h
index 039db6aa8e02..37555e52f980 100644
--- a/arch/x86/include/asm/hardirq.h
+++ b/arch/x86/include/asm/hardirq.h
@@ -26,7 +26,7 @@ typedef struct {
#endif
} ____cacheline_aligned irq_cpustat_t;
-DECLARE_PER_CPU(irq_cpustat_t, irq_stat);
+DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
/* We can have at most NR_VECTORS irqs routed to a cpu at a time */
#define MAX_HARDIRQS_PER_CPU NR_VECTORS
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index b762ea49bd70..be9ae4111c94 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -78,7 +78,11 @@ extern void eisa_set_level_irq(unsigned int irq);
/* SMP */
extern void smp_apic_timer_interrupt(struct pt_regs *);
extern void smp_spurious_interrupt(struct pt_regs *);
+extern void smp_generic_interrupt(struct pt_regs *);
extern void smp_error_interrupt(struct pt_regs *);
+#ifdef CONFIG_X86_IO_APIC
+extern asmlinkage void smp_irq_move_cleanup_interrupt(void);
+#endif
#ifdef CONFIG_SMP
extern void smp_reschedule_interrupt(struct pt_regs *);
extern void smp_call_function_interrupt(struct pt_regs *);
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h
index 71c9e5183982..63d185087d91 100644
--- a/arch/x86/include/asm/i387.h
+++ b/arch/x86/include/asm/i387.h
@@ -67,7 +67,7 @@ static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
".previous\n"
_ASM_EXTABLE(1b, 3b)
: [err] "=r" (err)
-#if 0 /* See comment in __save_init_fpu() below. */
+#if 0 /* See comment in fxsave() below. */
: [fx] "r" (fx), "m" (*fx), "0" (0));
#else
: [fx] "cdaSDb" (fx), "m" (*fx), "0" (0));
@@ -75,14 +75,6 @@ static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
return err;
}
-static inline int restore_fpu_checking(struct task_struct *tsk)
-{
- if (task_thread_info(tsk)->status & TS_XSAVE)
- return xrstor_checking(&tsk->thread.xstate->xsave);
- else
- return fxrstor_checking(&tsk->thread.xstate->fxsave);
-}
-
/* AMD CPUs don't save/restore FDP/FIP/FOP unless an exception
is pending. Clear the x87 state here by setting it to fixed
values. The kernel data segment can be sometimes 0 and sometimes
@@ -120,7 +112,7 @@ static inline int fxsave_user(struct i387_fxsave_struct __user *fx)
".previous\n"
_ASM_EXTABLE(1b, 3b)
: [err] "=r" (err), "=m" (*fx)
-#if 0 /* See comment in __fxsave_clear() below. */
+#if 0 /* See comment in fxsave() below. */
: [fx] "r" (fx), "0" (0));
#else
: [fx] "cdaSDb" (fx), "0" (0));
@@ -185,12 +177,9 @@ static inline void tolerant_fwait(void)
asm volatile("fnclex ; fwait");
}
-static inline void restore_fpu(struct task_struct *tsk)
+/* perform fxrstor iff the processor has extended states, otherwise frstor */
+static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
{
- if (task_thread_info(tsk)->status & TS_XSAVE) {
- xrstor_checking(&tsk->thread.xstate->xsave);
- return;
- }
/*
* The "nop" is needed to make the instructions the same
* length.
@@ -199,7 +188,9 @@ static inline void restore_fpu(struct task_struct *tsk)
"nop ; frstor %1",
"fxrstor %1",
X86_FEATURE_FXSR,
- "m" (tsk->thread.xstate->fxsave));
+ "m" (*fx));
+
+ return 0;
}
/* We need a safe address that is cheap to find and that is already
@@ -262,6 +253,14 @@ end:
#endif /* CONFIG_X86_64 */
+static inline int restore_fpu_checking(struct task_struct *tsk)
+{
+ if (task_thread_info(tsk)->status & TS_XSAVE)
+ return xrstor_checking(&tsk->thread.xstate->xsave);
+ else
+ return fxrstor_checking(&tsk->thread.xstate->fxsave);
+}
+
/*
* Signal frame handlers...
*/
diff --git a/arch/x86/include/asm/i8259.h b/arch/x86/include/asm/i8259.h
index 1a99e6c092af..58d7091eeb1f 100644
--- a/arch/x86/include/asm/i8259.h
+++ b/arch/x86/include/asm/i8259.h
@@ -60,8 +60,4 @@ extern struct irq_chip i8259A_chip;
extern void mask_8259A(void);
extern void unmask_8259A(void);
-#ifdef CONFIG_X86_32
-extern void init_ISA_irqs(void);
-#endif
-
#endif /* _ASM_X86_I8259_H */
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 9d826e436010..27bd2fdd00ae 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -154,22 +154,18 @@ extern int timer_through_8259;
extern int io_apic_get_unique_id(int ioapic, int apic_id);
extern int io_apic_get_version(int ioapic);
extern int io_apic_get_redir_entries(int ioapic);
-extern int io_apic_set_pci_routing(int ioapic, int pin, int irq,
- int edge_level, int active_high_low);
+extern int io_apic_set_pci_routing(struct device *dev, int ioapic, int pin,
+ int irq, int edge_level, int active_high_low);
#endif /* CONFIG_ACPI */
extern int (*ioapic_renumber_irq)(int ioapic, int irq);
extern void ioapic_init_mappings(void);
-#ifdef CONFIG_X86_64
extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries);
extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
-extern void reinit_intr_remapped_IO_APIC(int intr_remapping,
- struct IO_APIC_route_entry **ioapic_entries);
-#endif
extern void probe_nr_irqs_gsi(void);
diff --git a/arch/x86/include/asm/iomap.h b/arch/x86/include/asm/iomap.h
index 86af26091d6c..0e9fe1d9d971 100644
--- a/arch/x86/include/asm/iomap.h
+++ b/arch/x86/include/asm/iomap.h
@@ -1,3 +1,6 @@
+#ifndef _ASM_X86_IOMAP_H
+#define _ASM_X86_IOMAP_H
+
/*
* Copyright © 2008 Ingo Molnar
*
@@ -31,3 +34,5 @@ iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot);
void
iounmap_atomic(void *kvaddr, enum km_type type);
+
+#endif /* _ASM_X86_IOMAP_H */
diff --git a/arch/x86/include/asm/iommu.h b/arch/x86/include/asm/iommu.h
index af326a2975b5..fd6d21bbee6c 100644
--- a/arch/x86/include/asm/iommu.h
+++ b/arch/x86/include/asm/iommu.h
@@ -6,6 +6,7 @@ extern void no_iommu_init(void);
extern struct dma_map_ops nommu_dma_ops;
extern int force_iommu, no_iommu;
extern int iommu_detected;
+extern int iommu_pass_through;
/* 10 seconds */
#define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000)
diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h
index 0396760fccb8..f275e2244505 100644
--- a/arch/x86/include/asm/irq_remapping.h
+++ b/arch/x86/include/asm/irq_remapping.h
@@ -1,6 +1,6 @@
#ifndef _ASM_X86_IRQ_REMAPPING_H
#define _ASM_X86_IRQ_REMAPPING_H
-#define IRTE_DEST(dest) ((x2apic) ? dest : dest << 8)
+#define IRTE_DEST(dest) ((x2apic_mode) ? dest : dest << 8)
#endif /* _ASM_X86_IRQ_REMAPPING_H */
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h
index 3cbd79bbb47c..910b5a3d6751 100644
--- a/arch/x86/include/asm/irq_vectors.h
+++ b/arch/x86/include/asm/irq_vectors.h
@@ -34,6 +34,7 @@
#ifdef CONFIG_X86_32
# define SYSCALL_VECTOR 0x80
+# define IA32_SYSCALL_VECTOR 0x80
#else
# define IA32_SYSCALL_VECTOR 0x80
#endif
diff --git a/arch/x86/include/asm/k8.h b/arch/x86/include/asm/k8.h
index 54c8cc53b24d..c2d1f3b58e5f 100644
--- a/arch/x86/include/asm/k8.h
+++ b/arch/x86/include/asm/k8.h
@@ -12,4 +12,17 @@ extern int cache_k8_northbridges(void);
extern void k8_flush_garts(void);
extern int k8_scan_nodes(unsigned long start, unsigned long end);
+#ifdef CONFIG_K8_NB
+static inline struct pci_dev *node_to_k8_nb_misc(int node)
+{
+ return (node < num_k8_northbridges) ? k8_northbridges[node] : NULL;
+}
+#else
+static inline struct pci_dev *node_to_k8_nb_misc(int node)
+{
+ return NULL;
+}
+#endif
+
+
#endif /* _ASM_X86_K8_H */
diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h
index dc3f6cf11704..125be8b19568 100644
--- a/arch/x86/include/asm/kvm.h
+++ b/arch/x86/include/asm/kvm.h
@@ -16,6 +16,7 @@
#define __KVM_HAVE_MSI
#define __KVM_HAVE_USER_NMI
#define __KVM_HAVE_GUEST_DEBUG
+#define __KVM_HAVE_MSIX
/* Architectural interrupt line count. */
#define KVM_NR_INTERRUPTS 256
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index f0faf58044ff..5322ee67caaa 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -185,6 +185,7 @@ union kvm_mmu_page_role {
unsigned access:3;
unsigned invalid:1;
unsigned cr4_pge:1;
+ unsigned nxe:1;
};
};
@@ -212,7 +213,6 @@ struct kvm_mmu_page {
int multimapped; /* More than one parent_pte? */
int root_count; /* Currently serving as active root */
bool unsync;
- bool global;
unsigned int unsync_children;
union {
u64 *parent_pte; /* !multimapped */
@@ -261,11 +261,11 @@ struct kvm_mmu {
union kvm_mmu_page_role base_role;
u64 *pae_root;
+ u64 rsvd_bits_mask[2][4];
};
struct kvm_vcpu_arch {
u64 host_tsc;
- int interrupt_window_open;
unsigned long irq_summary; /* bit vector: 1 per word in irq_pending */
DECLARE_BITMAP(irq_pending, KVM_NR_INTERRUPTS);
/*
@@ -286,6 +286,7 @@ struct kvm_vcpu_arch {
u64 shadow_efer;
u64 apic_base;
struct kvm_lapic *apic; /* kernel irqchip context */
+ int32_t apic_arb_prio;
int mp_state;
int sipi_vector;
u64 ia32_misc_enable_msr;
@@ -358,7 +359,6 @@ struct kvm_vcpu_arch {
bool nmi_pending;
bool nmi_injected;
- bool nmi_window_open;
struct mtrr_state_type mtrr_state;
u32 pat;
@@ -392,15 +392,15 @@ struct kvm_arch{
*/
struct list_head active_mmu_pages;
struct list_head assigned_dev_head;
- struct list_head oos_global_pages;
struct iommu_domain *iommu_domain;
+#define KVM_IOMMU_CACHE_COHERENCY 0x1
+ int iommu_flags;
struct kvm_pic *vpic;
struct kvm_ioapic *vioapic;
struct kvm_pit *vpit;
struct hlist_head irq_ack_notifier_list;
int vapics_in_nmi_mode;
- int round_robin_prev_vcpu;
unsigned int tss_addr;
struct page *apic_access_page;
@@ -423,7 +423,6 @@ struct kvm_vm_stat {
u32 mmu_recycled;
u32 mmu_cache_miss;
u32 mmu_unsync;
- u32 mmu_unsync_global;
u32 remote_tlb_flush;
u32 lpages;
};
@@ -443,7 +442,6 @@ struct kvm_vcpu_stat {
u32 halt_exits;
u32 halt_wakeup;
u32 request_irq_exits;
- u32 request_nmi_exits;
u32 irq_exits;
u32 host_state_reload;
u32 efer_reload;
@@ -513,18 +511,19 @@ struct kvm_x86_ops {
void (*skip_emulated_instruction)(struct kvm_vcpu *vcpu);
void (*patch_hypercall)(struct kvm_vcpu *vcpu,
unsigned char *hypercall_addr);
- int (*get_irq)(struct kvm_vcpu *vcpu);
void (*set_irq)(struct kvm_vcpu *vcpu, int vec);
+ void (*set_nmi)(struct kvm_vcpu *vcpu);
void (*queue_exception)(struct kvm_vcpu *vcpu, unsigned nr,
bool has_error_code, u32 error_code);
- bool (*exception_injected)(struct kvm_vcpu *vcpu);
- void (*inject_pending_irq)(struct kvm_vcpu *vcpu);
- void (*inject_pending_vectors)(struct kvm_vcpu *vcpu,
- struct kvm_run *run);
-
+ int (*interrupt_allowed)(struct kvm_vcpu *vcpu);
+ int (*nmi_allowed)(struct kvm_vcpu *vcpu);
+ void (*enable_nmi_window)(struct kvm_vcpu *vcpu);
+ void (*enable_irq_window)(struct kvm_vcpu *vcpu);
+ void (*update_cr8_intercept)(struct kvm_vcpu *vcpu, int tpr, int irr);
+ void (*drop_interrupt_shadow)(struct kvm_vcpu *vcpu);
int (*set_tss_addr)(struct kvm *kvm, unsigned int addr);
int (*get_tdp_level)(void);
- int (*get_mt_mask_shift)(void);
+ u64 (*get_mt_mask)(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio);
};
extern struct kvm_x86_ops *kvm_x86_ops;
@@ -538,7 +537,7 @@ int kvm_mmu_setup(struct kvm_vcpu *vcpu);
void kvm_mmu_set_nonpresent_ptes(u64 trap_pte, u64 notrap_pte);
void kvm_mmu_set_base_ptes(u64 base_pte);
void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
- u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 mt_mask);
+ u64 dirty_mask, u64 nx_mask, u64 x_mask);
int kvm_mmu_reset_context(struct kvm_vcpu *vcpu);
void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot);
@@ -552,6 +551,7 @@ int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
const void *val, int bytes);
int kvm_pv_mmu_op(struct kvm_vcpu *vcpu, unsigned long bytes,
gpa_t addr, unsigned long *ret);
+u8 kvm_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn);
extern bool tdp_enabled;
@@ -563,6 +563,7 @@ enum emulation_result {
#define EMULTYPE_NO_DECODE (1 << 0)
#define EMULTYPE_TRAP_UD (1 << 1)
+#define EMULTYPE_SKIP (1 << 2)
int emulate_instruction(struct kvm_vcpu *vcpu, struct kvm_run *run,
unsigned long cr2, u16 error_code, int emulation_type);
void kvm_report_emulation_failure(struct kvm_vcpu *cvpu, const char *context);
@@ -638,7 +639,6 @@ void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu);
int kvm_mmu_load(struct kvm_vcpu *vcpu);
void kvm_mmu_unload(struct kvm_vcpu *vcpu);
void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu);
-void kvm_mmu_sync_global(struct kvm_vcpu *vcpu);
int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
@@ -769,6 +769,7 @@ enum {
#define HF_GIF_MASK (1 << 0)
#define HF_HIF_MASK (1 << 1)
#define HF_VINTR_MASK (1 << 2)
+#define HF_NMI_MASK (1 << 3)
/*
* Hardware virtualization extension instructions may fault if a
@@ -791,5 +792,6 @@ asmlinkage void kvm_handle_fault_on_reboot(void);
#define KVM_ARCH_WANT_MMU_NOTIFIER
int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
int kvm_age_hva(struct kvm *kvm, unsigned long hva);
+int cpuid_maxphyaddr(struct kvm_vcpu *vcpu);
#endif /* _ASM_X86_KVM_HOST_H */
diff --git a/arch/x86/include/asm/lguest_hcall.h b/arch/x86/include/asm/lguest_hcall.h
index 0f4ee7148afe..faae1996487b 100644
--- a/arch/x86/include/asm/lguest_hcall.h
+++ b/arch/x86/include/asm/lguest_hcall.h
@@ -5,7 +5,6 @@
#define LHCALL_FLUSH_ASYNC 0
#define LHCALL_LGUEST_INIT 1
#define LHCALL_SHUTDOWN 2
-#define LHCALL_LOAD_GDT 3
#define LHCALL_NEW_PGTABLE 4
#define LHCALL_FLUSH_TLB 5
#define LHCALL_LOAD_IDT_ENTRY 6
@@ -17,6 +16,7 @@
#define LHCALL_SET_PMD 15
#define LHCALL_LOAD_TLS 16
#define LHCALL_NOTIFY 17
+#define LHCALL_LOAD_GDT_ENTRY 18
#define LGUEST_TRAP_ENTRY 0x1F
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 563933e06a35..4f8c199584e7 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -137,6 +137,7 @@ DECLARE_PER_CPU(mce_banks_t, mce_poll_banks);
enum mcp_flags {
MCP_TIMESTAMP = (1 << 0), /* log time stamp */
MCP_UC = (1 << 1), /* log uncorrected errors */
+ MCP_DONTLOG = (1 << 2), /* only clear, don't log */
};
extern void machine_check_poll(enum mcp_flags flags, mce_banks_t *b);
diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h
index 642fc7fc8cdc..3ea1f531f532 100644
--- a/arch/x86/include/asm/mpspec.h
+++ b/arch/x86/include/asm/mpspec.h
@@ -72,7 +72,9 @@ extern void mp_register_ioapic(int id, u32 address, u32 gsi_base);
extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
u32 gsi);
extern void mp_config_acpi_legacy_irqs(void);
-extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
+struct device;
+extern int mp_register_gsi(struct device *dev, u32 gsi, int edge_level,
+ int active_high_low);
extern int acpi_probe_gsi(void);
#ifdef CONFIG_X86_IO_APIC
extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
diff --git a/arch/x86/include/asm/page_32_types.h b/arch/x86/include/asm/page_32_types.h
index 0f915ae649a7..6f1b7331313f 100644
--- a/arch/x86/include/asm/page_32_types.h
+++ b/arch/x86/include/asm/page_32_types.h
@@ -54,10 +54,6 @@ extern unsigned int __VMALLOC_RESERVE;
extern int sysctl_legacy_va_layout;
extern void find_low_pfn_range(void);
-extern unsigned long init_memory_mapping(unsigned long start,
- unsigned long end);
-extern void initmem_init(unsigned long, unsigned long);
-extern void free_initmem(void);
extern void setup_bootmem_allocator(void);
#endif /* !__ASSEMBLY__ */
diff --git a/arch/x86/include/asm/page_64_types.h b/arch/x86/include/asm/page_64_types.h
index d38c91b70248..3f587188ae68 100644
--- a/arch/x86/include/asm/page_64_types.h
+++ b/arch/x86/include/asm/page_64_types.h
@@ -71,12 +71,6 @@ extern unsigned long __phys_addr(unsigned long);
#define vmemmap ((struct page *)VMEMMAP_START)
-extern unsigned long init_memory_mapping(unsigned long start,
- unsigned long end);
-
-extern void initmem_init(unsigned long start_pfn, unsigned long end_pfn);
-extern void free_initmem(void);
-
extern void init_extra_mapping_uc(unsigned long phys, unsigned long size);
extern void init_extra_mapping_wb(unsigned long phys, unsigned long size);
diff --git a/arch/x86/include/asm/page_types.h b/arch/x86/include/asm/page_types.h
index 826ad37006ab..6473f5ccff85 100644
--- a/arch/x86/include/asm/page_types.h
+++ b/arch/x86/include/asm/page_types.h
@@ -46,6 +46,12 @@ extern int devmem_is_allowed(unsigned long pagenr);
extern unsigned long max_low_pfn_mapped;
extern unsigned long max_pfn_mapped;
+extern unsigned long init_memory_mapping(unsigned long start,
+ unsigned long end);
+
+extern void initmem_init(unsigned long start_pfn, unsigned long end_pfn);
+extern void free_initmem(void);
+
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_X86_PAGE_DEFS_H */
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index 378e3691c08c..1fe583783792 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -56,6 +56,7 @@ struct desc_ptr;
struct tss_struct;
struct mm_struct;
struct desc_struct;
+struct task_struct;
/*
* Wrapper type for pointers to code which uses the non-standard
@@ -203,7 +204,8 @@ struct pv_cpu_ops {
void (*swapgs)(void);
- struct pv_lazy_ops lazy_mode;
+ void (*start_context_switch)(struct task_struct *prev);
+ void (*end_context_switch)(struct task_struct *next);
};
struct pv_irq_ops {
@@ -1399,25 +1401,23 @@ enum paravirt_lazy_mode {
};
enum paravirt_lazy_mode paravirt_get_lazy_mode(void);
-void paravirt_enter_lazy_cpu(void);
-void paravirt_leave_lazy_cpu(void);
+void paravirt_start_context_switch(struct task_struct *prev);
+void paravirt_end_context_switch(struct task_struct *next);
+
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)
+#define __HAVE_ARCH_START_CONTEXT_SWITCH
+static inline void arch_start_context_switch(struct task_struct *prev)
{
- PVOP_VCALL0(pv_cpu_ops.lazy_mode.enter);
+ PVOP_VCALL1(pv_cpu_ops.start_context_switch, prev);
}
-static inline void arch_leave_lazy_cpu_mode(void)
+static inline void arch_end_context_switch(struct task_struct *next)
{
- PVOP_VCALL0(pv_cpu_ops.lazy_mode.leave);
+ PVOP_VCALL1(pv_cpu_ops.end_context_switch, next);
}
-void arch_flush_lazy_cpu_mode(void);
-
#define __HAVE_ARCH_ENTER_LAZY_MMU_MODE
static inline void arch_enter_lazy_mmu_mode(void)
{
diff --git a/arch/x86/include/asm/pat.h b/arch/x86/include/asm/pat.h
index 2cd07b9422f4..7af14e512f97 100644
--- a/arch/x86/include/asm/pat.h
+++ b/arch/x86/include/asm/pat.h
@@ -18,9 +18,5 @@ extern int free_memtype(u64 start, u64 end);
extern int kernel_map_sync_memtype(u64 base, unsigned long size,
unsigned long flag);
-extern void map_devmem(unsigned long pfn, unsigned long size,
- struct pgprot vma_prot);
-extern void unmap_devmem(unsigned long pfn, unsigned long size,
- struct pgprot vma_prot);
#endif /* _ASM_X86_PAT_H */
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index b51a1e8b0baf..927958d13c19 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -130,6 +130,7 @@ extern void pci_iommu_alloc(void);
/* generic pci stuff */
#include <asm-generic/pci.h>
+#define PCIBIOS_MAX_MEM_32 0xffffffff
#ifdef CONFIG_NUMA
/* Returns the node based on pci bus */
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index 29d96d168bc0..18ef7ebf2631 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -81,6 +81,8 @@ static inline void __init paravirt_pagetable_setup_done(pgd_t *base)
#define pte_val(x) native_pte_val(x)
#define __pte(x) native_make_pte(x)
+#define arch_end_context_switch(prev) do {} while(0)
+
#endif /* CONFIG_PARAVIRT */
/*
@@ -503,6 +505,8 @@ static inline int pgd_none(pgd_t pgd)
#ifndef __ASSEMBLY__
+extern int direct_gbpages;
+
/* local pte updates need not use xchg for locking */
static inline pte_t native_local_ptep_get_and_clear(pte_t *ptep)
{
diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h
index 6b87bc6d5018..abde308fdb0f 100644
--- a/arch/x86/include/asm/pgtable_64.h
+++ b/arch/x86/include/asm/pgtable_64.h
@@ -25,10 +25,6 @@ extern pgd_t init_level4_pgt[];
extern void paging_init(void);
-#endif /* !__ASSEMBLY__ */
-
-#ifndef __ASSEMBLY__
-
#define pte_ERROR(e) \
printk("%s:%d: bad pte %p(%016lx).\n", \
__FILE__, __LINE__, &(e), pte_val(e))
@@ -135,8 +131,6 @@ static inline int pgd_large(pgd_t pgd) { return 0; }
#define update_mmu_cache(vma, address, pte) do { } while (0)
-extern int direct_gbpages;
-
/* Encode and de-code a swap entry */
#if _PAGE_BIT_FILE < _PAGE_BIT_PROTNONE
#define SWP_TYPE_BITS (_PAGE_BIT_FILE - _PAGE_BIT_PRESENT - 1)
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index b8238dc8786d..4d258ad76a0f 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -273,7 +273,6 @@ typedef struct page *pgtable_t;
extern pteval_t __supported_pte_mask;
extern int nx_enabled;
-extern void set_nx(void);
#define pgprot_writecombine pgprot_writecombine
extern pgprot_t pgprot_writecombine(pgprot_t prot);
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index fcf4d92e7e04..0b2fab0051e0 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -138,7 +138,7 @@ extern struct tss_struct doublefault_tss;
extern __u32 cleared_cpu_caps[NCAPINTS];
#ifdef CONFIG_SMP
-DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
+DECLARE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
#define cpu_data(cpu) per_cpu(cpu_info, cpu)
#define current_cpu_data __get_cpu_var(cpu_info)
#else
@@ -270,7 +270,7 @@ struct tss_struct {
} ____cacheline_aligned;
-DECLARE_PER_CPU(struct tss_struct, init_tss);
+DECLARE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss);
/*
* Save the original ist values for checking stack pointers during debugging
@@ -393,7 +393,7 @@ union irq_stack_union {
};
};
-DECLARE_PER_CPU(union irq_stack_union, irq_stack_union);
+DECLARE_PER_CPU_FIRST(union irq_stack_union, irq_stack_union);
DECLARE_INIT_PER_CPU(irq_stack_union);
DECLARE_PER_CPU(char *, irq_stack_ptr);
@@ -460,14 +460,8 @@ struct thread_struct {
unsigned io_bitmap_max;
/* MSR_IA32_DEBUGCTLMSR value to switch in if TIF_DEBUGCTLMSR is set. */
unsigned long debugctlmsr;
-#ifdef CONFIG_X86_DS
-/* Debug Store context; see include/asm-x86/ds.h; goes into MSR_IA32_DS_AREA */
+ /* Debug Store context; see asm/ds.h */
struct ds_context *ds_ctx;
-#endif /* CONFIG_X86_DS */
-#ifdef CONFIG_X86_PTRACE_BTS
-/* the signal to send on a bts buffer overflow */
- unsigned int bts_ovfl_signal;
-#endif /* CONFIG_X86_PTRACE_BTS */
};
static inline unsigned long native_get_debugreg(int regno)
@@ -795,6 +789,21 @@ static inline unsigned long get_debugctlmsr(void)
return debugctlmsr;
}
+static inline unsigned long get_debugctlmsr_on_cpu(int cpu)
+{
+ u64 debugctlmsr = 0;
+ u32 val1, val2;
+
+#ifndef CONFIG_X86_DEBUGCTLMSR
+ if (boot_cpu_data.x86 < 6)
+ return 0;
+#endif
+ rdmsr_on_cpu(cpu, MSR_IA32_DEBUGCTLMSR, &val1, &val2);
+ debugctlmsr = val1 | ((u64)val2 << 32);
+
+ return debugctlmsr;
+}
+
static inline void update_debugctlmsr(unsigned long debugctlmsr)
{
#ifndef CONFIG_X86_DEBUGCTLMSR
@@ -804,6 +813,18 @@ static inline void update_debugctlmsr(unsigned long debugctlmsr)
wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr);
}
+static inline void update_debugctlmsr_on_cpu(int cpu,
+ unsigned long debugctlmsr)
+{
+#ifndef CONFIG_X86_DEBUGCTLMSR
+ if (boot_cpu_data.x86 < 6)
+ return;
+#endif
+ wrmsr_on_cpu(cpu, MSR_IA32_DEBUGCTLMSR,
+ (u32)((u64)debugctlmsr),
+ (u32)((u64)debugctlmsr >> 32));
+}
+
/*
* from system description table in BIOS. Mostly for MCA use, but
* others may find it useful:
diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h
index e304b66abeea..5cdd19f20b5b 100644
--- a/arch/x86/include/asm/ptrace.h
+++ b/arch/x86/include/asm/ptrace.h
@@ -235,12 +235,11 @@ extern int do_get_thread_area(struct task_struct *p, int idx,
extern int do_set_thread_area(struct task_struct *p, int idx,
struct user_desc __user *info, int can_allocate);
-extern void x86_ptrace_untrace(struct task_struct *);
-extern void x86_ptrace_fork(struct task_struct *child,
- unsigned long clone_flags);
+#ifdef CONFIG_X86_PTRACE_BTS
+extern void ptrace_bts_untrace(struct task_struct *tsk);
-#define arch_ptrace_untrace(tsk) x86_ptrace_untrace(tsk)
-#define arch_ptrace_fork(child, flags) x86_ptrace_fork(child, flags)
+#define arch_ptrace_untrace(tsk) ptrace_bts_untrace(tsk)
+#endif /* CONFIG_X86_PTRACE_BTS */
#endif /* __KERNEL__ */
diff --git a/arch/x86/include/asm/required-features.h b/arch/x86/include/asm/required-features.h
index d5cd6c586881..64cf2d24fad1 100644
--- a/arch/x86/include/asm/required-features.h
+++ b/arch/x86/include/asm/required-features.h
@@ -48,9 +48,15 @@
#endif
#ifdef CONFIG_X86_64
+#ifdef CONFIG_PARAVIRT
+/* Paravirtualized systems may not have PSE or PGE available */
#define NEED_PSE 0
+#define NEED_PGE 0
+#else
+#define NEED_PSE (1<<(X86_FEATURE_PSE) & 31)
+#define NEED_PGE (1<<(X86_FEATURE_PGE) & 31)
+#endif
#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))
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
index bdc2ada05ae0..4093d1ed6db2 100644
--- a/arch/x86/include/asm/setup.h
+++ b/arch/x86/include/asm/setup.h
@@ -33,7 +33,6 @@ struct x86_quirks {
int (*setup_ioapic_ids)(void);
};
-extern void x86_quirk_pre_intr_init(void);
extern void x86_quirk_intr_init(void);
extern void x86_quirk_trap_init(void);
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index 82ada75f3ebf..85574b7c1bc1 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -225,6 +225,7 @@ struct __attribute__ ((__packed__)) vmcb {
#define SVM_EVTINJ_VALID_ERR (1 << 11)
#define SVM_EXITINTINFO_VEC_MASK SVM_EVTINJ_VEC_MASK
+#define SVM_EXITINTINFO_TYPE_MASK SVM_EVTINJ_TYPE_MASK
#define SVM_EXITINTINFO_TYPE_INTR SVM_EVTINJ_TYPE_INTR
#define SVM_EXITINTINFO_TYPE_NMI SVM_EVTINJ_TYPE_NMI
diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h
index 7043408f6904..372b76edd63f 100644
--- a/arch/x86/include/asm/syscalls.h
+++ b/arch/x86/include/asm/syscalls.h
@@ -1,7 +1,7 @@
/*
* syscalls.h - Linux syscall interfaces (arch-specific)
*
- * Copyright (c) 2008 Jaswinder Singh
+ * Copyright (c) 2008 Jaswinder Singh Rajput
*
* This file is released under the GPLv2.
* See the file COPYING for more details.
@@ -12,50 +12,55 @@
#include <linux/compiler.h>
#include <linux/linkage.h>
-#include <linux/types.h>
#include <linux/signal.h>
+#include <linux/types.h>
/* Common in X86_32 and X86_64 */
/* kernel/ioport.c */
asmlinkage long sys_ioperm(unsigned long, unsigned long, int);
+/* kernel/process.c */
+int sys_fork(struct pt_regs *);
+int sys_vfork(struct pt_regs *);
+
/* kernel/ldt.c */
asmlinkage int sys_modify_ldt(int, void __user *, unsigned long);
+/* kernel/signal.c */
+long sys_rt_sigreturn(struct pt_regs *);
+
/* kernel/tls.c */
asmlinkage int sys_set_thread_area(struct user_desc __user *);
asmlinkage int sys_get_thread_area(struct user_desc __user *);
/* X86_32 only */
#ifdef CONFIG_X86_32
+/* kernel/ioport.c */
+long sys_iopl(struct pt_regs *);
+
/* kernel/process_32.c */
-int sys_fork(struct pt_regs *);
int sys_clone(struct pt_regs *);
-int sys_vfork(struct pt_regs *);
int sys_execve(struct pt_regs *);
-/* kernel/signal_32.c */
+/* kernel/signal.c */
asmlinkage int sys_sigsuspend(int, int, old_sigset_t);
asmlinkage int sys_sigaction(int, const struct old_sigaction __user *,
struct old_sigaction __user *);
int sys_sigaltstack(struct pt_regs *);
unsigned long sys_sigreturn(struct pt_regs *);
-long sys_rt_sigreturn(struct pt_regs *);
-
-/* kernel/ioport.c */
-long sys_iopl(struct pt_regs *);
/* kernel/sys_i386_32.c */
+struct mmap_arg_struct;
+struct sel_arg_struct;
+struct oldold_utsname;
+struct old_utsname;
+
asmlinkage long sys_mmap2(unsigned long, unsigned long, unsigned long,
unsigned long, unsigned long, unsigned long);
-struct mmap_arg_struct;
asmlinkage int old_mmap(struct mmap_arg_struct __user *);
-struct sel_arg_struct;
asmlinkage int old_select(struct sel_arg_struct __user *);
asmlinkage int sys_ipc(uint, int, int, int, void __user *, long);
-struct old_utsname;
asmlinkage int sys_uname(struct old_utsname __user *);
-struct oldold_utsname;
asmlinkage int sys_olduname(struct oldold_utsname __user *);
/* kernel/vm86_32.c */
@@ -65,29 +70,27 @@ int sys_vm86(struct pt_regs *);
#else /* CONFIG_X86_32 */
/* X86_64 only */
+/* kernel/ioport.c */
+asmlinkage long sys_iopl(unsigned int, struct pt_regs *);
+
/* kernel/process_64.c */
-asmlinkage long sys_fork(struct pt_regs *);
asmlinkage long sys_clone(unsigned long, unsigned long,
void __user *, void __user *,
struct pt_regs *);
-asmlinkage long sys_vfork(struct pt_regs *);
asmlinkage long sys_execve(char __user *, char __user * __user *,
char __user * __user *,
struct pt_regs *);
long sys_arch_prctl(int, unsigned long);
-/* kernel/ioport.c */
-asmlinkage long sys_iopl(unsigned int, struct pt_regs *);
-
-/* kernel/signal_64.c */
+/* kernel/signal.c */
asmlinkage long sys_sigaltstack(const stack_t __user *, stack_t __user *,
struct pt_regs *);
-long sys_rt_sigreturn(struct pt_regs *);
/* kernel/sys_x86_64.c */
+struct new_utsname;
+
asmlinkage long sys_mmap(unsigned long, unsigned long, unsigned long,
unsigned long, unsigned long, unsigned long);
-struct new_utsname;
asmlinkage long sys_uname(struct new_utsname __user *);
#endif /* CONFIG_X86_32 */
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index 8820a73ae090..602c769fc98c 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -94,7 +94,8 @@ struct thread_info {
#define TIF_FORCED_TF 24 /* true if TF in eflags artificially */
#define TIF_DEBUGCTLMSR 25 /* uses thread_struct.debugctlmsr */
#define TIF_DS_AREA_MSR 26 /* uses thread_struct.ds_area_msr */
-#define TIF_SYSCALL_FTRACE 27 /* for ftrace syscall instrumentation */
+#define TIF_LAZY_MMU_UPDATES 27 /* task is updating the mmu lazily */
+#define TIF_SYSCALL_FTRACE 28 /* for ftrace syscall instrumentation */
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
@@ -116,6 +117,7 @@ struct thread_info {
#define _TIF_FORCED_TF (1 << TIF_FORCED_TF)
#define _TIF_DEBUGCTLMSR (1 << TIF_DEBUGCTLMSR)
#define _TIF_DS_AREA_MSR (1 << TIF_DS_AREA_MSR)
+#define _TIF_LAZY_MMU_UPDATES (1 << TIF_LAZY_MMU_UPDATES)
#define _TIF_SYSCALL_FTRACE (1 << TIF_SYSCALL_FTRACE)
/* work to do in syscall_trace_enter() */
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
index d3539f998f88..a5ecc9c33e92 100644
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -17,7 +17,7 @@
static inline void __native_flush_tlb(void)
{
- write_cr3(read_cr3());
+ native_write_cr3(native_read_cr3());
}
static inline void __native_flush_tlb_global(void)
@@ -32,11 +32,11 @@ static inline void __native_flush_tlb_global(void)
*/
raw_local_irq_save(flags);
- cr4 = read_cr4();
+ cr4 = native_read_cr4();
/* clear PGE */
- write_cr4(cr4 & ~X86_CR4_PGE);
+ native_write_cr4(cr4 & ~X86_CR4_PGE);
/* write old PGE again and flush TLBs */
- write_cr4(cr4);
+ native_write_cr4(cr4);
raw_local_irq_restore(flags);
}
@@ -152,7 +152,7 @@ struct tlb_state {
struct mm_struct *active_mm;
int state;
};
-DECLARE_PER_CPU(struct tlb_state, cpu_tlbstate);
+DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate);
static inline void reset_lazy_tlbstate(void)
{
diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h
index 892b119dba6f..f44b49abca49 100644
--- a/arch/x86/include/asm/topology.h
+++ b/arch/x86/include/asm/topology.h
@@ -200,7 +200,7 @@ static inline void arch_fix_phys_package_id(int num, u32 slot)
}
struct pci_bus;
-void set_pci_bus_resources_arch_default(struct pci_bus *b);
+void x86_pci_root_bus_res_quirks(struct pci_bus *b);
#ifdef CONFIG_SMP
#define mc_capable() (cpumask_weight(cpu_core_mask(0)) != nr_cpu_ids)
diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h
index 0d5342515b86..cbfdc26b1460 100644
--- a/arch/x86/include/asm/traps.h
+++ b/arch/x86/include/asm/traps.h
@@ -2,6 +2,7 @@
#define _ASM_X86_TRAPS_H
#include <asm/debugreg.h>
+#include <asm/siginfo.h> /* TRAP_TRACE, ... */
#ifdef CONFIG_X86_32
#define dotraplinkage
@@ -74,7 +75,6 @@ static inline int get_si_code(unsigned long condition)
}
extern int panic_on_unrecovered_nmi;
-extern int kstack_depth_to_print;
void math_error(void __user *);
void math_emulate(struct math_emu_info *);
diff --git a/arch/x86/include/asm/unistd_32.h b/arch/x86/include/asm/unistd_32.h
index 6e72d74cf8dc..708dae61262d 100644
--- a/arch/x86/include/asm/unistd_32.h
+++ b/arch/x86/include/asm/unistd_32.h
@@ -340,6 +340,7 @@
#define __NR_inotify_init1 332
#define __NR_preadv 333
#define __NR_pwritev 334
+#define __NR_rt_tgsigqueueinfo 335
#ifdef __KERNEL__
diff --git a/arch/x86/include/asm/unistd_64.h b/arch/x86/include/asm/unistd_64.h
index f81829462325..4e2b05404400 100644
--- a/arch/x86/include/asm/unistd_64.h
+++ b/arch/x86/include/asm/unistd_64.h
@@ -657,6 +657,8 @@ __SYSCALL(__NR_inotify_init1, sys_inotify_init1)
__SYSCALL(__NR_preadv, sys_preadv)
#define __NR_pwritev 296
__SYSCALL(__NR_pwritev, sys_pwritev)
+#define __NR_rt_tgsigqueueinfo 297
+__SYSCALL(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo)
#ifndef __NO_STUBS
diff --git a/arch/x86/include/asm/uv/uv_mmrs.h b/arch/x86/include/asm/uv/uv_mmrs.h
index db68ac8a5ac2..2cae46c7c8a2 100644
--- a/arch/x86/include/asm/uv/uv_mmrs.h
+++ b/arch/x86/include/asm/uv/uv_mmrs.h
@@ -17,6 +17,11 @@
/* ========================================================================= */
/* UVH_BAU_DATA_CONFIG */
/* ========================================================================= */
+#define UVH_LB_BAU_MISC_CONTROL 0x320170UL
+#define UV_ENABLE_INTD_SOFT_ACK_MODE_SHIFT 15
+#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHIFT 16
+#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD 0x000000000bUL
+/* 1011 timebase 7 (168millisec) * 3 ticks -> 500ms */
#define UVH_BAU_DATA_CONFIG 0x61680UL
#define UVH_BAU_DATA_CONFIG_32 0x0438
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h
index 1a918dde46b5..018a0a400799 100644
--- a/arch/x86/include/asm/xen/page.h
+++ b/arch/x86/include/asm/xen/page.h
@@ -124,7 +124,8 @@ static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
/* VIRT <-> MACHINE conversion */
#define virt_to_machine(v) (phys_to_machine(XPADDR(__pa(v))))
-#define virt_to_mfn(v) (pfn_to_mfn(PFN_DOWN(__pa(v))))
+#define virt_to_pfn(v) (PFN_DOWN(__pa(v)))
+#define virt_to_mfn(v) (pfn_to_mfn(virt_to_pfn(v)))
#define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT))
static inline unsigned long pte_mfn(pte_t pte)
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 145cce75cda7..68a4ff609767 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -28,7 +28,7 @@ CFLAGS_paravirt.o := $(nostackp)
obj-y := process_$(BITS).o signal.o entry_$(BITS).o
obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
obj-y += time_$(BITS).o ioport.o ldt.o dumpstack.o
-obj-y += setup.o i8259.o irqinit_$(BITS).o
+obj-y += setup.o i8259.o irqinit.o
obj-$(CONFIG_X86_VISWS) += visws_quirks.o
obj-$(CONFIG_X86_32) += probe_roms_32.o
obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o
@@ -44,6 +44,7 @@ obj-y += process.o
obj-y += i387.o xsave.o
obj-y += ptrace.o
obj-$(CONFIG_X86_DS) += ds.o
+obj-$(CONFIG_X86_DS_SELFTEST) += ds_selftest.o
obj-$(CONFIG_X86_32) += tls.o
obj-$(CONFIG_IA32_EMULATION) += tls.o
obj-y += step.o
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 723989d7f802..6ee96b5530f1 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -522,7 +522,7 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
* success: return IRQ number (>=0)
* failure: return < 0
*/
-int acpi_register_gsi(u32 gsi, int triggering, int polarity)
+int acpi_register_gsi(struct device *dev, u32 gsi, int triggering, int polarity)
{
unsigned int irq;
unsigned int plat_gsi = gsi;
@@ -539,7 +539,7 @@ int acpi_register_gsi(u32 gsi, int triggering, int polarity)
#ifdef CONFIG_X86_IO_APIC
if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) {
- plat_gsi = mp_register_gsi(gsi, triggering, polarity);
+ plat_gsi = mp_register_gsi(dev, gsi, triggering, polarity);
}
#endif
acpi_gsi_to_irq(plat_gsi, &irq);
@@ -1158,7 +1158,7 @@ void __init mp_config_acpi_legacy_irqs(void)
}
}
-int mp_register_gsi(u32 gsi, int triggering, int polarity)
+int mp_register_gsi(struct device *dev, u32 gsi, int triggering, int polarity)
{
int ioapic;
int ioapic_pin;
@@ -1253,7 +1253,7 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
}
}
#endif
- io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
+ io_apic_set_pci_routing(dev, ioapic, ioapic_pin, gsi,
triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
return gsi;
diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
index bbbe4bbb6f34..b866b876446e 100644
--- a/arch/x86/kernel/acpi/cstate.c
+++ b/arch/x86/kernel/acpi/cstate.c
@@ -53,6 +53,12 @@ struct cstate_entry {
};
static struct cstate_entry *cpu_cstate_entry; /* per CPU ptr */
+/* Used for the cross-CPU calls */
+struct acpi_processor_cx_cross_cpu {
+ struct acpi_processor_cx *cx;
+ long retval;
+};
+
static short mwait_supported[ACPI_PROCESSOR_MAX_POWER];
#define MWAIT_SUBSTATE_MASK (0xf)
@@ -67,10 +73,10 @@ static short mwait_supported[ACPI_PROCESSOR_MAX_POWER];
#define NATIVE_CSTATE_BEYOND_HALT (2)
-static long acpi_processor_ffh_cstate_probe_cpu(void *_cx)
+static void acpi_processor_ffh_cstate_probe_cpu(void *_cxcc)
{
- struct acpi_processor_cx *cx = _cx;
- long retval;
+ struct acpi_processor_cx_cross_cpu *cxcc = _cxcc;
+ struct acpi_processor_cx *cx = cxcc->cx;
unsigned int eax, ebx, ecx, edx;
unsigned int edx_part;
unsigned int cstate_type; /* C-state type and not ACPI C-state type */
@@ -84,16 +90,16 @@ static long acpi_processor_ffh_cstate_probe_cpu(void *_cx)
edx_part = edx >> (cstate_type * MWAIT_SUBSTATE_SIZE);
num_cstate_subtype = edx_part & MWAIT_SUBSTATE_MASK;
- retval = 0;
+ cxcc->retval = 0;
if (num_cstate_subtype < (cx->address & MWAIT_SUBSTATE_MASK)) {
- retval = -1;
+ cxcc->retval = -1;
goto out;
}
/* mwait ecx extensions INTERRUPT_BREAK should be supported for C2/C3 */
if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) ||
!(ecx & CPUID5_ECX_INTERRUPT_BREAK)) {
- retval = -1;
+ cxcc->retval = -1;
goto out;
}
@@ -107,7 +113,7 @@ static long acpi_processor_ffh_cstate_probe_cpu(void *_cx)
ACPI_CX_DESC_LEN, "ACPI FFH INTEL MWAIT 0x%x",
cx->address);
out:
- return retval;
+ return;
}
int acpi_processor_ffh_cstate_probe(unsigned int cpu,
@@ -115,6 +121,7 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu,
{
struct cstate_entry *percpu_entry;
struct cpuinfo_x86 *c = &cpu_data(cpu);
+ struct acpi_processor_cx_cross_cpu cxcc = { .cx = cx, };
long retval;
if (!cpu_cstate_entry || c->cpuid_level < CPUID_MWAIT_LEAF)
@@ -127,13 +134,18 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu,
percpu_entry->states[cx->index].eax = 0;
percpu_entry->states[cx->index].ecx = 0;
- /* Make sure we are running on right CPU */
+ /* Run acpi_processor_ffh_cstate_probe_cpu() on the target CPU */
- retval = work_on_cpu(cpu, acpi_processor_ffh_cstate_probe_cpu, cx);
+ retval = smp_call_function_single(cpu,
+ acpi_processor_ffh_cstate_probe_cpu, &cxcc, 1);
if (retval == 0) {
- /* Use the hint in CST */
- percpu_entry->states[cx->index].eax = cx->address;
- percpu_entry->states[cx->index].ecx = MWAIT_ECX_INTERRUPT_BREAK;
+ retval = cxcc.retval;
+ if (retval == 0) {
+ /* Use the hint in CST */
+ percpu_entry->states[cx->index].eax = cx->address;
+ percpu_entry->states[cx->index].ecx =
+ MWAIT_ECX_INTERRUPT_BREAK;
+ }
}
return retval;
}
diff --git a/arch/x86/kernel/acpi/realmode/Makefile b/arch/x86/kernel/acpi/realmode/Makefile
index 1c31cc0e9def..167bc16ce0e5 100644
--- a/arch/x86/kernel/acpi/realmode/Makefile
+++ b/arch/x86/kernel/acpi/realmode/Makefile
@@ -9,7 +9,7 @@
always := wakeup.bin
targets := wakeup.elf wakeup.lds
-wakeup-y += wakeup.o wakemain.o video-mode.o copy.o
+wakeup-y += wakeup.o wakemain.o video-mode.o copy.o bioscall.o regs.o
# The link order of the video-*.o modules can matter. In particular,
# video-vga.o *must* be listed first, followed by video-vesa.o.
diff --git a/arch/x86/kernel/acpi/realmode/bioscall.S b/arch/x86/kernel/acpi/realmode/bioscall.S
new file mode 100644
index 000000000000..f51eb0bb56ce
--- /dev/null
+++ b/arch/x86/kernel/acpi/realmode/bioscall.S
@@ -0,0 +1 @@
+#include "../../../boot/bioscall.S"
diff --git a/arch/x86/kernel/acpi/realmode/regs.c b/arch/x86/kernel/acpi/realmode/regs.c
new file mode 100644
index 000000000000..6206033ba202
--- /dev/null
+++ b/arch/x86/kernel/acpi/realmode/regs.c
@@ -0,0 +1 @@
+#include "../../../boot/regs.c"
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index 7c243a2c5115..ca93638ba430 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -104,7 +104,7 @@ int acpi_save_state_mem(void)
initial_gs = per_cpu_offset(smp_processor_id());
#endif
initial_code = (unsigned long)wakeup_long64;
- saved_magic = 0x123456789abcdef0;
+ saved_magic = 0x123456789abcdef0L;
#endif /* CONFIG_64BIT */
return 0;
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index 42c33cebf00f..8c0be0902dac 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -49,10 +49,10 @@
#define IVHD_DEV_EXT_SELECT 0x46
#define IVHD_DEV_EXT_SELECT_RANGE 0x47
-#define IVHD_FLAG_HT_TUN_EN 0x00
-#define IVHD_FLAG_PASSPW_EN 0x01
-#define IVHD_FLAG_RESPASSPW_EN 0x02
-#define IVHD_FLAG_ISOC_EN 0x03
+#define IVHD_FLAG_HT_TUN_EN_MASK 0x01
+#define IVHD_FLAG_PASSPW_EN_MASK 0x02
+#define IVHD_FLAG_RESPASSPW_EN_MASK 0x04
+#define IVHD_FLAG_ISOC_EN_MASK 0x08
#define IVMD_FLAG_EXCL_RANGE 0x08
#define IVMD_FLAG_UNITY_MAP 0x01
@@ -569,19 +569,19 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu,
* First set the recommended feature enable bits from ACPI
* into the IOMMU control registers
*/
- h->flags & IVHD_FLAG_HT_TUN_EN ?
+ h->flags & IVHD_FLAG_HT_TUN_EN_MASK ?
iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) :
iommu_feature_disable(iommu, CONTROL_HT_TUN_EN);
- h->flags & IVHD_FLAG_PASSPW_EN ?
+ h->flags & IVHD_FLAG_PASSPW_EN_MASK ?
iommu_feature_enable(iommu, CONTROL_PASSPW_EN) :
iommu_feature_disable(iommu, CONTROL_PASSPW_EN);
- h->flags & IVHD_FLAG_RESPASSPW_EN ?
+ h->flags & IVHD_FLAG_RESPASSPW_EN_MASK ?
iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) :
iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN);
- h->flags & IVHD_FLAG_ISOC_EN ?
+ h->flags & IVHD_FLAG_ISOC_EN_MASK ?
iommu_feature_enable(iommu, CONTROL_ISOC_EN) :
iommu_feature_disable(iommu, CONTROL_ISOC_EN);
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index f2870920f246..e258bedce7cb 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -98,6 +98,29 @@ early_param("lapic", parse_lapic);
/* Local APIC was disabled by the BIOS and enabled by the kernel */
static int enabled_via_apicbase;
+/*
+ * Handle interrupt mode configuration register (IMCR).
+ * This register controls whether the interrupt signals
+ * that reach the BSP come from the master PIC or from the
+ * local APIC. Before entering Symmetric I/O Mode, either
+ * the BIOS or the operating system must switch out of
+ * PIC Mode by changing the IMCR.
+ */
+static inline void imcr_pic_to_apic(void)
+{
+ /* select IMCR register */
+ outb(0x70, 0x22);
+ /* NMI and 8259 INTR go through APIC */
+ outb(0x01, 0x23);
+}
+
+static inline void imcr_apic_to_pic(void)
+{
+ /* select IMCR register */
+ outb(0x70, 0x22);
+ /* NMI and 8259 INTR go directly to BSP */
+ outb(0x00, 0x23);
+}
#endif
#ifdef CONFIG_X86_64
@@ -111,13 +134,19 @@ static __init int setup_apicpmtimer(char *s)
__setup("apicpmtimer", setup_apicpmtimer);
#endif
+int x2apic_mode;
#ifdef CONFIG_X86_X2APIC
-int x2apic;
/* x2apic enabled before OS handover */
static int x2apic_preenabled;
static int disable_x2apic;
static __init int setup_nox2apic(char *str)
{
+ if (x2apic_enabled()) {
+ pr_warning("Bios already enabled x2apic, "
+ "can't enforce nox2apic");
+ return 0;
+ }
+
disable_x2apic = 1;
setup_clear_cpu_cap(X86_FEATURE_X2APIC);
return 0;
@@ -209,6 +238,24 @@ static int modern_apic(void)
return lapic_get_version() >= 0x14;
}
+/*
+ * bare function to substitute write operation
+ * and it's _that_ fast :)
+ */
+void native_apic_write_dummy(u32 reg, u32 v)
+{
+ WARN_ON_ONCE((cpu_has_apic || !disable_apic));
+}
+
+/*
+ * right after this call apic->write doesn't do anything
+ * note that there is no restore operation it works one way
+ */
+void apic_disable(void)
+{
+ apic->write = native_apic_write_dummy;
+}
+
void native_apic_wait_icr_idle(void)
{
while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
@@ -815,7 +862,7 @@ void clear_local_APIC(void)
u32 v;
/* APIC hasn't been mapped yet */
- if (!x2apic && !apic_phys)
+ if (!x2apic_mode && !apic_phys)
return;
maxlvt = lapic_get_maxlvt();
@@ -1287,7 +1334,7 @@ void check_x2apic(void)
{
if (x2apic_enabled()) {
pr_info("x2apic enabled by BIOS, switching to x2apic ops\n");
- x2apic_preenabled = x2apic = 1;
+ x2apic_preenabled = x2apic_mode = 1;
}
}
@@ -1295,7 +1342,7 @@ void enable_x2apic(void)
{
int msr, msr2;
- if (!x2apic)
+ if (!x2apic_mode)
return;
rdmsr(MSR_IA32_APICBASE, msr, msr2);
@@ -1304,6 +1351,7 @@ void enable_x2apic(void)
wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0);
}
}
+#endif /* CONFIG_X86_X2APIC */
void __init enable_IR_x2apic(void)
{
@@ -1312,32 +1360,21 @@ void __init enable_IR_x2apic(void)
unsigned long flags;
struct IO_APIC_route_entry **ioapic_entries = NULL;
- if (!cpu_has_x2apic)
- return;
-
- if (!x2apic_preenabled && disable_x2apic) {
- pr_info("Skipped enabling x2apic and Interrupt-remapping "
- "because of nox2apic\n");
- return;
+ ret = dmar_table_init();
+ if (ret) {
+ pr_debug("dmar_table_init() failed with %d:\n", ret);
+ goto ir_failed;
}
- if (x2apic_preenabled && disable_x2apic)
- panic("Bios already enabled x2apic, can't enforce nox2apic");
-
- if (!x2apic_preenabled && skip_ioapic_setup) {
- pr_info("Skipped enabling x2apic and Interrupt-remapping "
- "because of skipping io-apic setup\n");
- return;
+ if (!intr_remapping_supported()) {
+ pr_debug("intr-remapping not supported\n");
+ goto ir_failed;
}
- ret = dmar_table_init();
- if (ret) {
- pr_info("dmar_table_init() failed with %d:\n", ret);
- if (x2apic_preenabled)
- panic("x2apic enabled by bios. But IR enabling failed");
- else
- pr_info("Not enabling x2apic,Intr-remapping\n");
+ if (!x2apic_preenabled && skip_ioapic_setup) {
+ pr_info("Skipped enabling intr-remap because of skipping "
+ "io-apic setup\n");
return;
}
@@ -1357,19 +1394,16 @@ void __init enable_IR_x2apic(void)
mask_IO_APIC_setup(ioapic_entries);
mask_8259A();
- ret = enable_intr_remapping(EIM_32BIT_APIC_ID);
-
- if (ret && x2apic_preenabled) {
- local_irq_restore(flags);
- panic("x2apic enabled by bios. But IR enabling failed");
- }
-
+ ret = enable_intr_remapping(x2apic_supported());
if (ret)
goto end_restore;
- if (!x2apic) {
- x2apic = 1;
+ pr_info("Enabled Interrupt-remapping\n");
+
+ if (x2apic_supported() && !x2apic_mode) {
+ x2apic_mode = 1;
enable_x2apic();
+ pr_info("Enabled x2apic\n");
}
end_restore:
@@ -1378,37 +1412,34 @@ end_restore:
* IR enabling failed
*/
restore_IO_APIC_setup(ioapic_entries);
- else
- reinit_intr_remapped_IO_APIC(x2apic_preenabled, ioapic_entries);
unmask_8259A();
local_irq_restore(flags);
end:
- if (!ret) {
- if (!x2apic_preenabled)
- pr_info("Enabled x2apic and interrupt-remapping\n");
- else
- pr_info("Enabled Interrupt-remapping\n");
- } else
- pr_err("Failed to enable Interrupt-remapping and x2apic\n");
if (ioapic_entries)
free_ioapic_entries(ioapic_entries);
+
+ if (!ret)
+ return;
+
+ir_failed:
+ if (x2apic_preenabled)
+ panic("x2apic enabled by bios. But IR enabling failed");
+ else if (cpu_has_x2apic)
+ pr_info("Not enabling x2apic,Intr-remapping\n");
#else
if (!cpu_has_x2apic)
return;
if (x2apic_preenabled)
panic("x2apic enabled prior OS handover,"
- " enable CONFIG_INTR_REMAP");
-
- pr_info("Enable CONFIG_INTR_REMAP for enabling intr-remapping "
- " and x2apic\n");
+ " enable CONFIG_X86_X2APIC, CONFIG_INTR_REMAP");
#endif
return;
}
-#endif /* CONFIG_X86_X2APIC */
+
#ifdef CONFIG_X86_64
/*
@@ -1539,7 +1570,7 @@ void __init early_init_lapic_mapping(void)
*/
void __init init_apic_mappings(void)
{
- if (x2apic) {
+ if (x2apic_mode) {
boot_cpu_physical_apicid = read_apic_id();
return;
}
@@ -1565,6 +1596,12 @@ void __init init_apic_mappings(void)
*/
if (boot_cpu_physical_apicid == -1U)
boot_cpu_physical_apicid = read_apic_id();
+
+ /* lets check if we may to NOP'ify apic operations */
+ if (!cpu_has_apic) {
+ pr_info("APIC: disable apic facility\n");
+ apic_disable();
+ }
}
/*
@@ -1733,8 +1770,7 @@ void __init connect_bsp_APIC(void)
*/
apic_printk(APIC_VERBOSE, "leaving PIC mode, "
"enabling APIC mode.\n");
- outb(0x70, 0x22);
- outb(0x01, 0x23);
+ imcr_pic_to_apic();
}
#endif
if (apic->enable_apic_mode)
@@ -1762,8 +1798,7 @@ void disconnect_bsp_APIC(int virt_wire_setup)
*/
apic_printk(APIC_VERBOSE, "disabling APIC mode, "
"entering PIC mode.\n");
- outb(0x70, 0x22);
- outb(0x00, 0x23);
+ imcr_apic_to_pic();
return;
}
#endif
@@ -1969,10 +2004,10 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state)
local_irq_save(flags);
disable_local_APIC();
-#ifdef CONFIG_INTR_REMAP
+
if (intr_remapping_enabled)
disable_intr_remapping();
-#endif
+
local_irq_restore(flags);
return 0;
}
@@ -1982,8 +2017,6 @@ static int lapic_resume(struct sys_device *dev)
unsigned int l, h;
unsigned long flags;
int maxlvt;
-
-#ifdef CONFIG_INTR_REMAP
int ret;
struct IO_APIC_route_entry **ioapic_entries = NULL;
@@ -1991,7 +2024,7 @@ static int lapic_resume(struct sys_device *dev)
return 0;
local_irq_save(flags);
- if (x2apic) {
+ if (intr_remapping_enabled) {
ioapic_entries = alloc_ioapic_entries();
if (!ioapic_entries) {
WARN(1, "Alloc ioapic_entries in lapic resume failed.");
@@ -2007,17 +2040,10 @@ static int lapic_resume(struct sys_device *dev)
mask_IO_APIC_setup(ioapic_entries);
mask_8259A();
- enable_x2apic();
}
-#else
- if (!apic_pm_state.active)
- return 0;
- local_irq_save(flags);
- if (x2apic)
+ if (x2apic_mode)
enable_x2apic();
-#endif
-
else {
/*
* Make sure the APICBASE points to the right address
@@ -2055,20 +2081,15 @@ static int lapic_resume(struct sys_device *dev)
apic_write(APIC_ESR, 0);
apic_read(APIC_ESR);
-#ifdef CONFIG_INTR_REMAP
- if (intr_remapping_enabled)
- reenable_intr_remapping(EIM_32BIT_APIC_ID);
-
- if (x2apic) {
+ if (intr_remapping_enabled) {
+ reenable_intr_remapping(x2apic_mode);
unmask_8259A();
restore_IO_APIC_setup(ioapic_entries);
free_ioapic_entries(ioapic_entries);
}
-#endif
local_irq_restore(flags);
-
return 0;
}
@@ -2117,31 +2138,14 @@ static void apic_pm_activate(void) { }
#endif /* CONFIG_PM */
#ifdef CONFIG_X86_64
-/*
- * apic_is_clustered_box() -- Check if we can expect good TSC
- *
- * Thus far, the major user of this is IBM's Summit2 series:
- *
- * Clustered boxes may have unsynced TSC problems if they are
- * multi-chassis. Use available data to take a good guess.
- * If in doubt, go HPET.
- */
-__cpuinit int apic_is_clustered_box(void)
+
+static int __cpuinit apic_cluster_num(void)
{
int i, clusters, zeros;
unsigned id;
u16 *bios_cpu_apicid;
DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS);
- /*
- * there is not this kind of box with AMD CPU yet.
- * Some AMD box with quadcore cpu and 8 sockets apicid
- * will be [4, 0x23] or [8, 0x27] could be thought to
- * vsmp box still need checking...
- */
- if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && !is_vsmp_box())
- return 0;
-
bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid);
bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
@@ -2177,18 +2181,67 @@ __cpuinit int apic_is_clustered_box(void)
++zeros;
}
- /* ScaleMP vSMPowered boxes have one cluster per board and TSCs are
- * not guaranteed to be synced between boards
- */
- if (is_vsmp_box() && clusters > 1)
+ return clusters;
+}
+
+static int __cpuinitdata multi_checked;
+static int __cpuinitdata multi;
+
+static int __cpuinit set_multi(const struct dmi_system_id *d)
+{
+ if (multi)
+ return 0;
+ pr_info("APIC: %s detected, Multi Chassis\n", d->ident);
+ multi = 1;
+ return 0;
+}
+
+static const __cpuinitconst struct dmi_system_id multi_dmi_table[] = {
+ {
+ .callback = set_multi,
+ .ident = "IBM System Summit2",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Summit2"),
+ },
+ },
+ {}
+};
+
+static void __cpuinit dmi_check_multi(void)
+{
+ if (multi_checked)
+ return;
+
+ dmi_check_system(multi_dmi_table);
+ multi_checked = 1;
+}
+
+/*
+ * apic_is_clustered_box() -- Check if we can expect good TSC
+ *
+ * Thus far, the major user of this is IBM's Summit2 series:
+ * Clustered boxes may have unsynced TSC problems if they are
+ * multi-chassis.
+ * Use DMI to check them
+ */
+__cpuinit int apic_is_clustered_box(void)
+{
+ dmi_check_multi();
+ if (multi)
return 1;
+ if (!is_vsmp_box())
+ return 0;
+
/*
- * If clusters > 2, then should be multi-chassis.
- * May have to revisit this when multi-core + hyperthreaded CPUs come
- * out, but AFAIK this will work even for them.
+ * ScaleMP vSMPowered boxes have one cluster per board and TSCs are
+ * not guaranteed to be synced between boards
*/
- return (clusters > 2);
+ if (apic_cluster_num() > 1)
+ return 1;
+
+ return 0;
}
#endif
diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c
index 1c11b819f245..8e07c1418661 100644
--- a/arch/x86/kernel/apic/es7000_32.c
+++ b/arch/x86/kernel/apic/es7000_32.c
@@ -145,7 +145,7 @@ es7000_rename_gsi(int ioapic, int gsi)
return gsi;
}
-static int wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip)
+static int __cpuinit wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip)
{
unsigned long vect = 0, psaival = 0;
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index a2789e42e162..ed641eb1631f 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -59,6 +59,7 @@
#include <asm/setup.h>
#include <asm/irq_remapping.h>
#include <asm/hpet.h>
+#include <asm/hw_irq.h>
#include <asm/uv/uv_hub.h>
#include <asm/uv/uv_irq.h>
@@ -129,12 +130,9 @@ struct irq_pin_list {
struct irq_pin_list *next;
};
-static struct irq_pin_list *get_one_free_irq_2_pin(int cpu)
+static struct irq_pin_list *get_one_free_irq_2_pin(int node)
{
struct irq_pin_list *pin;
- int node;
-
- node = cpu_to_node(cpu);
pin = kzalloc_node(sizeof(*pin), GFP_ATOMIC, node);
@@ -148,9 +146,6 @@ struct irq_cfg {
unsigned move_cleanup_count;
u8 vector;
u8 move_in_progress : 1;
-#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
- u8 move_desc_pending : 1;
-#endif
};
/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
@@ -212,12 +207,9 @@ static struct irq_cfg *irq_cfg(unsigned int irq)
return cfg;
}
-static struct irq_cfg *get_one_free_irq_cfg(int cpu)
+static struct irq_cfg *get_one_free_irq_cfg(int node)
{
struct irq_cfg *cfg;
- int node;
-
- node = cpu_to_node(cpu);
cfg = kzalloc_node(sizeof(*cfg), GFP_ATOMIC, node);
if (cfg) {
@@ -238,13 +230,13 @@ static struct irq_cfg *get_one_free_irq_cfg(int cpu)
return cfg;
}
-int arch_init_chip_data(struct irq_desc *desc, int cpu)
+int arch_init_chip_data(struct irq_desc *desc, int node)
{
struct irq_cfg *cfg;
cfg = desc->chip_data;
if (!cfg) {
- desc->chip_data = get_one_free_irq_cfg(cpu);
+ desc->chip_data = get_one_free_irq_cfg(node);
if (!desc->chip_data) {
printk(KERN_ERR "can not alloc irq_cfg\n");
BUG_ON(1);
@@ -254,10 +246,9 @@ int arch_init_chip_data(struct irq_desc *desc, int cpu)
return 0;
}
-#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
-
+/* for move_irq_desc */
static void
-init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int cpu)
+init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int node)
{
struct irq_pin_list *old_entry, *head, *tail, *entry;
@@ -266,7 +257,7 @@ init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int cpu)
if (!old_entry)
return;
- entry = get_one_free_irq_2_pin(cpu);
+ entry = get_one_free_irq_2_pin(node);
if (!entry)
return;
@@ -276,7 +267,7 @@ init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int cpu)
tail = entry;
old_entry = old_entry->next;
while (old_entry) {
- entry = get_one_free_irq_2_pin(cpu);
+ entry = get_one_free_irq_2_pin(node);
if (!entry) {
entry = head;
while (entry) {
@@ -316,12 +307,12 @@ static void free_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg)
}
void arch_init_copy_chip_data(struct irq_desc *old_desc,
- struct irq_desc *desc, int cpu)
+ struct irq_desc *desc, int node)
{
struct irq_cfg *cfg;
struct irq_cfg *old_cfg;
- cfg = get_one_free_irq_cfg(cpu);
+ cfg = get_one_free_irq_cfg(node);
if (!cfg)
return;
@@ -332,7 +323,7 @@ void arch_init_copy_chip_data(struct irq_desc *old_desc,
memcpy(cfg, old_cfg, sizeof(struct irq_cfg));
- init_copy_irq_2_pin(old_cfg, cfg, cpu);
+ init_copy_irq_2_pin(old_cfg, cfg, node);
}
static void free_irq_cfg(struct irq_cfg *old_cfg)
@@ -356,19 +347,7 @@ void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)
old_desc->chip_data = NULL;
}
}
-
-static void
-set_extra_move_desc(struct irq_desc *desc, const struct cpumask *mask)
-{
- struct irq_cfg *cfg = desc->chip_data;
-
- if (!cfg->move_in_progress) {
- /* it means that domain is not changed */
- if (!cpumask_intersects(desc->affinity, mask))
- cfg->move_desc_pending = 1;
- }
-}
-#endif
+/* end for move_irq_desc */
#else
static struct irq_cfg *irq_cfg(unsigned int irq)
@@ -378,13 +357,6 @@ static struct irq_cfg *irq_cfg(unsigned int irq)
#endif
-#ifndef CONFIG_NUMA_MIGRATE_IRQ_DESC
-static inline void
-set_extra_move_desc(struct irq_desc *desc, const struct cpumask *mask)
-{
-}
-#endif
-
struct io_apic {
unsigned int index;
unsigned int unused[3];
@@ -518,132 +490,18 @@ static void ioapic_mask_entry(int apic, int pin)
spin_unlock_irqrestore(&ioapic_lock, flags);
}
-#ifdef CONFIG_SMP
-static void send_cleanup_vector(struct irq_cfg *cfg)
-{
- cpumask_var_t cleanup_mask;
-
- if (unlikely(!alloc_cpumask_var(&cleanup_mask, GFP_ATOMIC))) {
- unsigned int i;
- cfg->move_cleanup_count = 0;
- for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
- cfg->move_cleanup_count++;
- for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
- apic->send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR);
- } else {
- cpumask_and(cleanup_mask, cfg->old_domain, cpu_online_mask);
- cfg->move_cleanup_count = cpumask_weight(cleanup_mask);
- apic->send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
- free_cpumask_var(cleanup_mask);
- }
- cfg->move_in_progress = 0;
-}
-
-static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg)
-{
- int apic, pin;
- struct irq_pin_list *entry;
- u8 vector = cfg->vector;
-
- entry = cfg->irq_2_pin;
- for (;;) {
- unsigned int reg;
-
- if (!entry)
- break;
-
- apic = entry->apic;
- pin = entry->pin;
- /*
- * With interrupt-remapping, destination information comes
- * from interrupt-remapping table entry.
- */
- if (!irq_remapped(irq))
- io_apic_write(apic, 0x11 + pin*2, dest);
- reg = io_apic_read(apic, 0x10 + pin*2);
- reg &= ~IO_APIC_REDIR_VECTOR_MASK;
- reg |= vector;
- io_apic_modify(apic, 0x10 + pin*2, reg);
- if (!entry->next)
- break;
- entry = entry->next;
- }
-}
-
-static int
-assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask);
-
-/*
- * Either sets desc->affinity to a valid value, and returns
- * ->cpu_mask_to_apicid of that, or returns BAD_APICID and
- * leaves desc->affinity untouched.
- */
-static unsigned int
-set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask)
-{
- struct irq_cfg *cfg;
- unsigned int irq;
-
- if (!cpumask_intersects(mask, cpu_online_mask))
- return BAD_APICID;
-
- irq = desc->irq;
- cfg = desc->chip_data;
- if (assign_irq_vector(irq, cfg, mask))
- return BAD_APICID;
-
- /* check that before desc->addinity get updated */
- set_extra_move_desc(desc, mask);
-
- cpumask_copy(desc->affinity, mask);
-
- return apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain);
-}
-
-static void
-set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
-{
- struct irq_cfg *cfg;
- unsigned long flags;
- unsigned int dest;
- unsigned int irq;
-
- irq = desc->irq;
- cfg = desc->chip_data;
-
- spin_lock_irqsave(&ioapic_lock, flags);
- dest = set_desc_affinity(desc, mask);
- if (dest != BAD_APICID) {
- /* Only the high 8 bits are valid. */
- dest = SET_APIC_LOGICAL_ID(dest);
- __target_IO_APIC_irq(irq, dest, cfg);
- }
- spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-
-static void
-set_ioapic_affinity_irq(unsigned int irq, const struct cpumask *mask)
-{
- struct irq_desc *desc;
-
- desc = irq_to_desc(irq);
-
- set_ioapic_affinity_irq_desc(desc, mask);
-}
-#endif /* CONFIG_SMP */
-
/*
* The common case is 1:1 IRQ<->pin mappings. Sometimes there are
* shared ISA-space IRQs, so we have to support them. We are super
* fast in the common case, and fast for shared ISA-space IRQs.
*/
-static void add_pin_to_irq_cpu(struct irq_cfg *cfg, int cpu, int apic, int pin)
+static void add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)
{
struct irq_pin_list *entry;
entry = cfg->irq_2_pin;
if (!entry) {
- entry = get_one_free_irq_2_pin(cpu);
+ entry = get_one_free_irq_2_pin(node);
if (!entry) {
printk(KERN_ERR "can not alloc irq_2_pin to add %d - %d\n",
apic, pin);
@@ -663,7 +521,7 @@ static void add_pin_to_irq_cpu(struct irq_cfg *cfg, int cpu, int apic, int pin)
entry = entry->next;
}
- entry->next = get_one_free_irq_2_pin(cpu);
+ entry->next = get_one_free_irq_2_pin(node);
entry = entry->next;
entry->apic = apic;
entry->pin = pin;
@@ -672,7 +530,7 @@ static void add_pin_to_irq_cpu(struct irq_cfg *cfg, int cpu, int apic, int pin)
/*
* Reroute an IRQ to a different pin.
*/
-static void __init replace_pin_at_irq_cpu(struct irq_cfg *cfg, int cpu,
+static void __init replace_pin_at_irq_node(struct irq_cfg *cfg, int node,
int oldapic, int oldpin,
int newapic, int newpin)
{
@@ -692,7 +550,7 @@ static void __init replace_pin_at_irq_cpu(struct irq_cfg *cfg, int cpu,
/* why? call replace before add? */
if (!replaced)
- add_pin_to_irq_cpu(cfg, cpu, newapic, newpin);
+ add_pin_to_irq_node(cfg, node, newapic, newpin);
}
static inline void io_apic_modify_irq(struct irq_cfg *cfg,
@@ -850,7 +708,6 @@ static int __init ioapic_pirq_setup(char *str)
__setup("pirq=", ioapic_pirq_setup);
#endif /* CONFIG_X86_32 */
-#ifdef CONFIG_INTR_REMAP
struct IO_APIC_route_entry **alloc_ioapic_entries(void)
{
int apic;
@@ -948,20 +805,6 @@ int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries)
return 0;
}
-void reinit_intr_remapped_IO_APIC(int intr_remapping,
- struct IO_APIC_route_entry **ioapic_entries)
-
-{
- /*
- * for now plain restore of previous settings.
- * TBD: In the case of OS enabling interrupt-remapping,
- * IO-APIC RTE's need to be setup to point to interrupt-remapping
- * table entries. for now, do a plain restore, and wait for
- * the setup_IO_APIC_irqs() to do proper initialization.
- */
- restore_IO_APIC_setup(ioapic_entries);
-}
-
void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries)
{
int apic;
@@ -971,7 +814,6 @@ void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries)
kfree(ioapic_entries);
}
-#endif
/*
* Find the IRQ entry number of a certain pin.
@@ -1634,7 +1476,7 @@ static void __init setup_IO_APIC_irqs(void)
int notcon = 0;
struct irq_desc *desc;
struct irq_cfg *cfg;
- int cpu = boot_cpu_id;
+ int node = cpu_to_node(boot_cpu_id);
apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
@@ -1669,13 +1511,13 @@ static void __init setup_IO_APIC_irqs(void)
apic->multi_timer_check(apic_id, irq))
continue;
- desc = irq_to_desc_alloc_cpu(irq, cpu);
+ desc = irq_to_desc_alloc_node(irq, node);
if (!desc) {
printk(KERN_INFO "can not get irq_desc for %d\n", irq);
continue;
}
cfg = desc->chip_data;
- add_pin_to_irq_cpu(cfg, cpu, apic_id, pin);
+ add_pin_to_irq_node(cfg, node, apic_id, pin);
setup_IO_APIC_irq(apic_id, pin, irq, desc,
irq_trigger(idx), irq_polarity(idx));
@@ -2360,6 +2202,118 @@ static int ioapic_retrigger_irq(unsigned int irq)
*/
#ifdef CONFIG_SMP
+static void send_cleanup_vector(struct irq_cfg *cfg)
+{
+ cpumask_var_t cleanup_mask;
+
+ if (unlikely(!alloc_cpumask_var(&cleanup_mask, GFP_ATOMIC))) {
+ unsigned int i;
+ cfg->move_cleanup_count = 0;
+ for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
+ cfg->move_cleanup_count++;
+ for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
+ apic->send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR);
+ } else {
+ cpumask_and(cleanup_mask, cfg->old_domain, cpu_online_mask);
+ cfg->move_cleanup_count = cpumask_weight(cleanup_mask);
+ apic->send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+ free_cpumask_var(cleanup_mask);
+ }
+ cfg->move_in_progress = 0;
+}
+
+static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg)
+{
+ int apic, pin;
+ struct irq_pin_list *entry;
+ u8 vector = cfg->vector;
+
+ entry = cfg->irq_2_pin;
+ for (;;) {
+ unsigned int reg;
+
+ if (!entry)
+ break;
+
+ apic = entry->apic;
+ pin = entry->pin;
+ /*
+ * With interrupt-remapping, destination information comes
+ * from interrupt-remapping table entry.
+ */
+ if (!irq_remapped(irq))
+ io_apic_write(apic, 0x11 + pin*2, dest);
+ reg = io_apic_read(apic, 0x10 + pin*2);
+ reg &= ~IO_APIC_REDIR_VECTOR_MASK;
+ reg |= vector;
+ io_apic_modify(apic, 0x10 + pin*2, reg);
+ if (!entry->next)
+ break;
+ entry = entry->next;
+ }
+}
+
+static int
+assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask);
+
+/*
+ * Either sets desc->affinity to a valid value, and returns
+ * ->cpu_mask_to_apicid of that, or returns BAD_APICID and
+ * leaves desc->affinity untouched.
+ */
+static unsigned int
+set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask)
+{
+ struct irq_cfg *cfg;
+ unsigned int irq;
+
+ if (!cpumask_intersects(mask, cpu_online_mask))
+ return BAD_APICID;
+
+ irq = desc->irq;
+ cfg = desc->chip_data;
+ if (assign_irq_vector(irq, cfg, mask))
+ return BAD_APICID;
+
+ cpumask_copy(desc->affinity, mask);
+
+ return apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain);
+}
+
+static int
+set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
+{
+ struct irq_cfg *cfg;
+ unsigned long flags;
+ unsigned int dest;
+ unsigned int irq;
+ int ret = -1;
+
+ irq = desc->irq;
+ cfg = desc->chip_data;
+
+ spin_lock_irqsave(&ioapic_lock, flags);
+ dest = set_desc_affinity(desc, mask);
+ if (dest != BAD_APICID) {
+ /* Only the high 8 bits are valid. */
+ dest = SET_APIC_LOGICAL_ID(dest);
+ __target_IO_APIC_irq(irq, dest, cfg);
+ ret = 0;
+ }
+ spin_unlock_irqrestore(&ioapic_lock, flags);
+
+ return ret;
+}
+
+static int
+set_ioapic_affinity_irq(unsigned int irq, const struct cpumask *mask)
+{
+ struct irq_desc *desc;
+
+ desc = irq_to_desc(irq);
+
+ return set_ioapic_affinity_irq_desc(desc, mask);
+}
#ifdef CONFIG_INTR_REMAP
@@ -2374,26 +2328,25 @@ static int ioapic_retrigger_irq(unsigned int irq)
* Real vector that is used for interrupting cpu will be coming from
* the interrupt-remapping table entry.
*/
-static void
+static int
migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
{
struct irq_cfg *cfg;
struct irte irte;
unsigned int dest;
unsigned int irq;
+ int ret = -1;
if (!cpumask_intersects(mask, cpu_online_mask))
- return;
+ return ret;
irq = desc->irq;
if (get_irte(irq, &irte))
- return;
+ return ret;
cfg = desc->chip_data;
if (assign_irq_vector(irq, cfg, mask))
- return;
-
- set_extra_move_desc(desc, mask);
+ return ret;
dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask);
@@ -2409,27 +2362,30 @@ migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
send_cleanup_vector(cfg);
cpumask_copy(desc->affinity, mask);
+
+ return 0;
}
/*
* Migrates the IRQ destination in the process context.
*/
-static void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
+static int set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
const struct cpumask *mask)
{
- migrate_ioapic_irq_desc(desc, mask);
+ return migrate_ioapic_irq_desc(desc, mask);
}
-static void set_ir_ioapic_affinity_irq(unsigned int irq,
+static int set_ir_ioapic_affinity_irq(unsigned int irq,
const struct cpumask *mask)
{
struct irq_desc *desc = irq_to_desc(irq);
- set_ir_ioapic_affinity_irq_desc(desc, mask);
+ return set_ir_ioapic_affinity_irq_desc(desc, mask);
}
#else
-static inline void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
+static inline int set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
const struct cpumask *mask)
{
+ return 0;
}
#endif
@@ -2491,86 +2447,19 @@ static void irq_complete_move(struct irq_desc **descp)
struct irq_cfg *cfg = desc->chip_data;
unsigned vector, me;
- if (likely(!cfg->move_in_progress)) {
-#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
- if (likely(!cfg->move_desc_pending))
- return;
-
- /* domain has not changed, but affinity did */
- me = smp_processor_id();
- if (cpumask_test_cpu(me, desc->affinity)) {
- *descp = desc = move_irq_desc(desc, me);
- /* get the new one */
- cfg = desc->chip_data;
- cfg->move_desc_pending = 0;
- }
-#endif
+ if (likely(!cfg->move_in_progress))
return;
- }
vector = ~get_irq_regs()->orig_ax;
me = smp_processor_id();
- if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) {
-#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
- *descp = desc = move_irq_desc(desc, me);
- /* get the new one */
- cfg = desc->chip_data;
-#endif
+ if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
send_cleanup_vector(cfg);
- }
}
#else
static inline void irq_complete_move(struct irq_desc **descp) {}
#endif
-static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
-{
- int apic, pin;
- struct irq_pin_list *entry;
-
- entry = cfg->irq_2_pin;
- for (;;) {
-
- if (!entry)
- break;
-
- apic = entry->apic;
- pin = entry->pin;
- io_apic_eoi(apic, pin);
- entry = entry->next;
- }
-}
-
-static void
-eoi_ioapic_irq(struct irq_desc *desc)
-{
- struct irq_cfg *cfg;
- unsigned long flags;
- unsigned int irq;
-
- irq = desc->irq;
- cfg = desc->chip_data;
-
- spin_lock_irqsave(&ioapic_lock, flags);
- __eoi_ioapic_irq(irq, cfg);
- spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-
-#ifdef CONFIG_X86_X2APIC
-static void ack_x2apic_level(unsigned int irq)
-{
- struct irq_desc *desc = irq_to_desc(irq);
- ack_x2APIC_irq();
- eoi_ioapic_irq(desc);
-}
-
-static void ack_x2apic_edge(unsigned int irq)
-{
- ack_x2APIC_irq();
-}
-#endif
-
static void ack_apic_edge(unsigned int irq)
{
struct irq_desc *desc = irq_to_desc(irq);
@@ -2634,9 +2523,6 @@ static void ack_apic_level(unsigned int irq)
*/
ack_APIC_irq();
- if (irq_remapped(irq))
- eoi_ioapic_irq(desc);
-
/* Now we can move and renable the irq */
if (unlikely(do_unmask_irq)) {
/* Only migrate the irq if the ack has been received.
@@ -2683,22 +2569,50 @@ static void ack_apic_level(unsigned int irq)
}
#ifdef CONFIG_INTR_REMAP
+static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
+{
+ int apic, pin;
+ struct irq_pin_list *entry;
+
+ entry = cfg->irq_2_pin;
+ for (;;) {
+
+ if (!entry)
+ break;
+
+ apic = entry->apic;
+ pin = entry->pin;
+ io_apic_eoi(apic, pin);
+ entry = entry->next;
+ }
+}
+
+static void
+eoi_ioapic_irq(struct irq_desc *desc)
+{
+ struct irq_cfg *cfg;
+ unsigned long flags;
+ unsigned int irq;
+
+ irq = desc->irq;
+ cfg = desc->chip_data;
+
+ spin_lock_irqsave(&ioapic_lock, flags);
+ __eoi_ioapic_irq(irq, cfg);
+ spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
static void ir_ack_apic_edge(unsigned int irq)
{
-#ifdef CONFIG_X86_X2APIC
- if (x2apic_enabled())
- return ack_x2apic_edge(irq);
-#endif
- return ack_apic_edge(irq);
+ ack_APIC_irq();
}
static void ir_ack_apic_level(unsigned int irq)
{
-#ifdef CONFIG_X86_X2APIC
- if (x2apic_enabled())
- return ack_x2apic_level(irq);
-#endif
- return ack_apic_level(irq);
+ struct irq_desc *desc = irq_to_desc(irq);
+
+ ack_APIC_irq();
+ eoi_ioapic_irq(desc);
}
#endif /* CONFIG_INTR_REMAP */
@@ -2903,7 +2817,7 @@ static inline void __init check_timer(void)
{
struct irq_desc *desc = irq_to_desc(0);
struct irq_cfg *cfg = desc->chip_data;
- int cpu = boot_cpu_id;
+ int node = cpu_to_node(boot_cpu_id);
int apic1, pin1, apic2, pin2;
unsigned long flags;
int no_pin1 = 0;
@@ -2969,7 +2883,7 @@ static inline void __init check_timer(void)
* Ok, does IRQ0 through the IOAPIC work?
*/
if (no_pin1) {
- add_pin_to_irq_cpu(cfg, cpu, apic1, pin1);
+ add_pin_to_irq_node(cfg, node, apic1, pin1);
setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
} else {
/* for edge trigger, setup_IO_APIC_irq already
@@ -3006,7 +2920,7 @@ static inline void __init check_timer(void)
/*
* legacy devices should be connected to IO APIC #0
*/
- replace_pin_at_irq_cpu(cfg, cpu, apic1, pin1, apic2, pin2);
+ replace_pin_at_irq_node(cfg, node, apic1, pin1, apic2, pin2);
setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
enable_8259A_irq(0);
if (timer_irq_works()) {
@@ -3218,14 +3132,13 @@ static int nr_irqs_gsi = NR_IRQS_LEGACY;
/*
* Dynamic irq allocate and deallocation
*/
-unsigned int create_irq_nr(unsigned int irq_want)
+unsigned int create_irq_nr(unsigned int irq_want, int node)
{
/* Allocate an unused irq */
unsigned int irq;
unsigned int new;
unsigned long flags;
struct irq_cfg *cfg_new = NULL;
- int cpu = boot_cpu_id;
struct irq_desc *desc_new = NULL;
irq = 0;
@@ -3234,7 +3147,7 @@ unsigned int create_irq_nr(unsigned int irq_want)
spin_lock_irqsave(&vector_lock, flags);
for (new = irq_want; new < nr_irqs; new++) {
- desc_new = irq_to_desc_alloc_cpu(new, cpu);
+ desc_new = irq_to_desc_alloc_node(new, node);
if (!desc_new) {
printk(KERN_INFO "can not get irq_desc for %d\n", new);
continue;
@@ -3243,6 +3156,9 @@ unsigned int create_irq_nr(unsigned int irq_want)
if (cfg_new->vector != 0)
continue;
+
+ desc_new = move_irq_desc(desc_new, node);
+
if (__assign_irq_vector(new, cfg_new, apic->target_cpus()) == 0)
irq = new;
break;
@@ -3260,11 +3176,12 @@ unsigned int create_irq_nr(unsigned int irq_want)
int create_irq(void)
{
+ int node = cpu_to_node(boot_cpu_id);
unsigned int irq_want;
int irq;
irq_want = nr_irqs_gsi;
- irq = create_irq_nr(irq_want);
+ irq = create_irq_nr(irq_want, node);
if (irq == 0)
irq = -1;
@@ -3366,7 +3283,7 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms
}
#ifdef CONFIG_SMP
-static void set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
+static int set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
{
struct irq_desc *desc = irq_to_desc(irq);
struct irq_cfg *cfg;
@@ -3375,7 +3292,7 @@ static void set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
dest = set_desc_affinity(desc, mask);
if (dest == BAD_APICID)
- return;
+ return -1;
cfg = desc->chip_data;
@@ -3387,13 +3304,15 @@ static void set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
msg.address_lo |= MSI_ADDR_DEST_ID(dest);
write_msi_msg_desc(desc, &msg);
+
+ return 0;
}
#ifdef CONFIG_INTR_REMAP
/*
* Migrate the MSI irq to another cpumask. This migration is
* done in the process context using interrupt-remapping hardware.
*/
-static void
+static int
ir_set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
{
struct irq_desc *desc = irq_to_desc(irq);
@@ -3402,11 +3321,11 @@ ir_set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
struct irte irte;
if (get_irte(irq, &irte))
- return;
+ return -1;
dest = set_desc_affinity(desc, mask);
if (dest == BAD_APICID)
- return;
+ return -1;
irte.vector = cfg->vector;
irte.dest_id = IRTE_DEST(dest);
@@ -3423,6 +3342,8 @@ ir_set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
*/
if (cfg->move_in_progress)
send_cleanup_vector(cfg);
+
+ return 0;
}
#endif
@@ -3518,15 +3439,17 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
unsigned int irq_want;
struct intel_iommu *iommu = NULL;
int index = 0;
+ int node;
/* x86 doesn't support multiple MSI yet */
if (type == PCI_CAP_ID_MSI && nvec > 1)
return 1;
+ node = dev_to_node(&dev->dev);
irq_want = nr_irqs_gsi;
sub_handle = 0;
list_for_each_entry(msidesc, &dev->msi_list, list) {
- irq = create_irq_nr(irq_want);
+ irq = create_irq_nr(irq_want, node);
if (irq == 0)
return -1;
irq_want = irq + 1;
@@ -3576,7 +3499,7 @@ void arch_teardown_msi_irq(unsigned int irq)
#if defined (CONFIG_DMAR) || defined (CONFIG_INTR_REMAP)
#ifdef CONFIG_SMP
-static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
{
struct irq_desc *desc = irq_to_desc(irq);
struct irq_cfg *cfg;
@@ -3585,7 +3508,7 @@ static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
dest = set_desc_affinity(desc, mask);
if (dest == BAD_APICID)
- return;
+ return -1;
cfg = desc->chip_data;
@@ -3597,6 +3520,8 @@ static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
msg.address_lo |= MSI_ADDR_DEST_ID(dest);
dmar_msi_write(irq, &msg);
+
+ return 0;
}
#endif /* CONFIG_SMP */
@@ -3630,7 +3555,7 @@ int arch_setup_dmar_msi(unsigned int irq)
#ifdef CONFIG_HPET_TIMER
#ifdef CONFIG_SMP
-static void hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
{
struct irq_desc *desc = irq_to_desc(irq);
struct irq_cfg *cfg;
@@ -3639,7 +3564,7 @@ static void hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
dest = set_desc_affinity(desc, mask);
if (dest == BAD_APICID)
- return;
+ return -1;
cfg = desc->chip_data;
@@ -3651,6 +3576,8 @@ static void hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
msg.address_lo |= MSI_ADDR_DEST_ID(dest);
hpet_msi_write(irq, &msg);
+
+ return 0;
}
#endif /* CONFIG_SMP */
@@ -3670,12 +3597,14 @@ int arch_setup_hpet_msi(unsigned int irq)
{
int ret;
struct msi_msg msg;
+ struct irq_desc *desc = irq_to_desc(irq);
ret = msi_compose_msg(NULL, irq, &msg);
if (ret < 0)
return ret;
hpet_msi_write(irq, &msg);
+ desc->status |= IRQ_MOVE_PCNTXT;
set_irq_chip_and_handler_name(irq, &hpet_msi_type, handle_edge_irq,
"edge");
@@ -3705,7 +3634,7 @@ static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
write_ht_irq_msg(irq, &msg);
}
-static void set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask)
+static int set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask)
{
struct irq_desc *desc = irq_to_desc(irq);
struct irq_cfg *cfg;
@@ -3713,11 +3642,13 @@ static void set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask)
dest = set_desc_affinity(desc, mask);
if (dest == BAD_APICID)
- return;
+ return -1;
cfg = desc->chip_data;
target_ht_irq(irq, dest, cfg->vector);
+
+ return 0;
}
#endif
@@ -3792,6 +3723,8 @@ int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
unsigned long flags;
int err;
+ BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
+
cfg = irq_cfg(irq);
err = assign_irq_vector(irq, cfg, eligible_cpu);
@@ -3805,15 +3738,13 @@ int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
mmr_value = 0;
entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
- BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
-
- entry->vector = cfg->vector;
- entry->delivery_mode = apic->irq_delivery_mode;
- entry->dest_mode = apic->irq_dest_mode;
- entry->polarity = 0;
- entry->trigger = 0;
- entry->mask = 0;
- entry->dest = apic->cpu_mask_to_apicid(eligible_cpu);
+ entry->vector = cfg->vector;
+ entry->delivery_mode = apic->irq_delivery_mode;
+ entry->dest_mode = apic->irq_dest_mode;
+ entry->polarity = 0;
+ entry->trigger = 0;
+ entry->mask = 0;
+ entry->dest = apic->cpu_mask_to_apicid(eligible_cpu);
mmr_pnode = uv_blade_to_pnode(mmr_blade);
uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
@@ -3831,10 +3762,10 @@ void arch_disable_uv_irq(int mmr_blade, unsigned long mmr_offset)
struct uv_IO_APIC_route_entry *entry;
int mmr_pnode;
+ BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
+
mmr_value = 0;
entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
- BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
-
entry->mask = 1;
mmr_pnode = uv_blade_to_pnode(mmr_blade);
@@ -3992,11 +3923,12 @@ int __init io_apic_get_version(int ioapic)
}
#endif
-int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity)
+int io_apic_set_pci_routing(struct device *dev, int ioapic, int pin, int irq,
+ int triggering, int polarity)
{
struct irq_desc *desc;
struct irq_cfg *cfg;
- int cpu = boot_cpu_id;
+ int node;
if (!IO_APIC_IRQ(irq)) {
apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
@@ -4004,7 +3936,12 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int p
return -EINVAL;
}
- desc = irq_to_desc_alloc_cpu(irq, cpu);
+ if (dev)
+ node = dev_to_node(dev);
+ else
+ node = cpu_to_node(boot_cpu_id);
+
+ desc = irq_to_desc_alloc_node(irq, node);
if (!desc) {
printk(KERN_INFO "can not get irq_desc %d\n", irq);
return 0;
@@ -4015,7 +3952,7 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int p
*/
if (irq >= NR_IRQS_LEGACY) {
cfg = desc->chip_data;
- add_pin_to_irq_cpu(cfg, cpu, ioapic, pin);
+ add_pin_to_irq_node(cfg, node, ioapic, pin);
}
setup_IO_APIC_irq(ioapic, pin, irq, desc, triggering, polarity);
diff --git a/arch/x86/kernel/apic/nmi.c b/arch/x86/kernel/apic/nmi.c
index d6bd62407152..a691302dc3ff 100644
--- a/arch/x86/kernel/apic/nmi.c
+++ b/arch/x86/kernel/apic/nmi.c
@@ -104,7 +104,7 @@ static __init void nmi_cpu_busy(void *data)
}
#endif
-static void report_broken_nmi(int cpu, int *prev_nmi_count)
+static void report_broken_nmi(int cpu, unsigned int *prev_nmi_count)
{
printk(KERN_CONT "\n");
@@ -138,7 +138,7 @@ int __init check_nmi_watchdog(void)
if (!prev_nmi_count)
goto error;
- alloc_cpumask_var(&backtrace_mask, GFP_KERNEL);
+ alloc_cpumask_var(&backtrace_mask, GFP_KERNEL|__GFP_ZERO);
printk(KERN_INFO "Testing NMI watchdog ... ");
#ifdef CONFIG_SMP
@@ -414,7 +414,8 @@ nmi_watchdog_tick(struct pt_regs *regs, unsigned reason)
touched = 1;
}
- if (cpumask_test_cpu(cpu, backtrace_mask)) {
+ /* We can be called before check_nmi_watchdog, hence NULL check. */
+ if (backtrace_mask != NULL && cpumask_test_cpu(cpu, backtrace_mask)) {
static DEFINE_SPINLOCK(lock); /* Serialise the printks */
spin_lock(&lock);
diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c
index 01eda2ac65e4..440a8bccd91a 100644
--- a/arch/x86/kernel/apic/probe_32.c
+++ b/arch/x86/kernel/apic/probe_32.c
@@ -160,7 +160,6 @@ extern struct apic apic_summit;
extern struct apic apic_bigsmp;
extern struct apic apic_es7000;
extern struct apic apic_es7000_cluster;
-extern struct apic apic_default;
struct apic *apic = &apic_default;
EXPORT_SYMBOL_GPL(apic);
diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c
index 1783652bb0e5..bc3e880f9b82 100644
--- a/arch/x86/kernel/apic/probe_64.c
+++ b/arch/x86/kernel/apic/probe_64.c
@@ -50,7 +50,7 @@ static struct apic *apic_probe[] __initdata = {
void __init default_setup_apic_routing(void)
{
#ifdef CONFIG_X86_X2APIC
- if (x2apic && (apic != &apic_x2apic_phys &&
+ if (x2apic_mode && (apic != &apic_x2apic_phys &&
#ifdef CONFIG_X86_UV
apic != &apic_x2apic_uv_x &&
#endif
diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c
index 9cfe1f415d81..344eee4ac0a4 100644
--- a/arch/x86/kernel/apic/summit_32.c
+++ b/arch/x86/kernel/apic/summit_32.c
@@ -173,13 +173,6 @@ static inline int is_WPEG(struct rio_detail *rio){
rio->type == LookOutAWPEG || rio->type == LookOutBWPEG);
}
-
-/* In clustered mode, the high nibble of APIC ID is a cluster number.
- * The low nibble is a 4-bit bitmap. */
-#define XAPIC_DEST_CPUS_SHIFT 4
-#define XAPIC_DEST_CPUS_MASK ((1u << XAPIC_DEST_CPUS_SHIFT) - 1)
-#define XAPIC_DEST_CLUSTER_MASK (XAPIC_DEST_CPUS_MASK << XAPIC_DEST_CPUS_SHIFT)
-
#define SUMMIT_APIC_DFR_VALUE (APIC_DFR_CLUSTER)
static const struct cpumask *summit_target_cpus(void)
diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c
index 4a903e2f0d17..8e4cbb255c38 100644
--- a/arch/x86/kernel/apic/x2apic_cluster.c
+++ b/arch/x86/kernel/apic/x2apic_cluster.c
@@ -10,7 +10,7 @@
#include <asm/apic.h>
#include <asm/ipi.h>
-DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid);
+static DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid);
static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index 1248318436e8..780a733a5e7a 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -19,6 +19,7 @@
#include <linux/timer.h>
#include <linux/cpu.h>
#include <linux/init.h>
+#include <linux/io.h>
#include <asm/uv/uv_mmrs.h>
#include <asm/uv/uv_hub.h>
@@ -34,6 +35,17 @@ DEFINE_PER_CPU(int, x2apic_extra_bits);
static enum uv_system_type uv_system_type;
+static int early_get_nodeid(void)
+{
+ union uvh_node_id_u node_id;
+ unsigned long *mmr;
+
+ mmr = early_ioremap(UV_LOCAL_MMR_BASE | UVH_NODE_ID, sizeof(*mmr));
+ node_id.v = *mmr;
+ early_iounmap(mmr, sizeof(*mmr));
+ return node_id.s.node_id;
+}
+
static int uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{
if (!strcmp(oem_id, "SGI")) {
@@ -42,6 +54,8 @@ static int uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
else if (!strcmp(oem_table_id, "UVX"))
uv_system_type = UV_X2APIC;
else if (!strcmp(oem_table_id, "UVH")) {
+ __get_cpu_var(x2apic_extra_bits) =
+ early_get_nodeid() << (UV_APIC_PNODE_SHIFT - 1);
uv_system_type = UV_NON_UNIQUE_APIC;
return 1;
}
@@ -91,7 +105,7 @@ static void uv_vector_allocation_domain(int cpu, struct cpumask *retmask)
cpumask_set_cpu(cpu, retmask);
}
-static int uv_wakeup_secondary(int phys_apicid, unsigned long start_rip)
+static int __cpuinit uv_wakeup_secondary(int phys_apicid, unsigned long start_rip)
{
#ifdef CONFIG_SMP
unsigned long val;
@@ -549,7 +563,8 @@ void __init uv_system_init(void)
unsigned long gnode_upper, lowmem_redir_base, lowmem_redir_size;
int bytes, nid, cpu, lcpu, pnode, blade, i, j, m_val, n_val;
int max_pnode = 0;
- unsigned long mmr_base, present;
+ unsigned long mmr_base, present, paddr;
+ unsigned short pnode_mask;
map_low_mmrs();
@@ -568,15 +583,18 @@ void __init uv_system_init(void)
bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades();
uv_blade_info = kmalloc(bytes, GFP_KERNEL);
+ BUG_ON(!uv_blade_info);
get_lowmem_redirect(&lowmem_redir_base, &lowmem_redir_size);
bytes = sizeof(uv_node_to_blade[0]) * num_possible_nodes();
uv_node_to_blade = kmalloc(bytes, GFP_KERNEL);
+ BUG_ON(!uv_node_to_blade);
memset(uv_node_to_blade, 255, bytes);
bytes = sizeof(uv_cpu_to_blade[0]) * num_possible_cpus();
uv_cpu_to_blade = kmalloc(bytes, GFP_KERNEL);
+ BUG_ON(!uv_cpu_to_blade);
memset(uv_cpu_to_blade, 255, bytes);
blade = 0;
@@ -592,6 +610,7 @@ void __init uv_system_init(void)
}
}
+ pnode_mask = (1 << n_val) - 1;
node_id.v = uv_read_local_mmr(UVH_NODE_ID);
gnode_upper = (((unsigned long)node_id.s.node_id) &
~((1 << n_val) - 1)) << m_val;
@@ -615,7 +634,7 @@ void __init uv_system_init(void)
uv_cpu_hub_info(cpu)->numa_blade_id = blade;
uv_cpu_hub_info(cpu)->blade_processor_id = lcpu;
uv_cpu_hub_info(cpu)->pnode = pnode;
- uv_cpu_hub_info(cpu)->pnode_mask = (1 << n_val) - 1;
+ uv_cpu_hub_info(cpu)->pnode_mask = pnode_mask;
uv_cpu_hub_info(cpu)->gpa_mask = (1 << (m_val + n_val)) - 1;
uv_cpu_hub_info(cpu)->gnode_upper = gnode_upper;
uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base;
@@ -631,6 +650,17 @@ void __init uv_system_init(void)
lcpu, blade);
}
+ /* Add blade/pnode info for nodes without cpus */
+ for_each_online_node(nid) {
+ if (uv_node_to_blade[nid] >= 0)
+ continue;
+ paddr = node_start_pfn(nid) << PAGE_SHIFT;
+ paddr = uv_soc_phys_ram_to_gpa(paddr);
+ pnode = (paddr >> m_val) & pnode_mask;
+ blade = boot_pnode_to_blade(pnode);
+ uv_node_to_blade[nid] = blade;
+ }
+
map_gru_high(max_pnode);
map_mmr_high(max_pnode);
map_config_high(max_pnode);
diff --git a/arch/x86/kernel/bios_uv.c b/arch/x86/kernel/bios_uv.c
index f63882728d91..63a88e1f987d 100644
--- a/arch/x86/kernel/bios_uv.c
+++ b/arch/x86/kernel/bios_uv.c
@@ -182,7 +182,8 @@ void uv_bios_init(void)
memcpy(&uv_systab, tab, sizeof(struct uv_systab));
iounmap(tab);
- printk(KERN_INFO "EFI UV System Table Revision %d\n", tab->revision);
+ printk(KERN_INFO "EFI UV System Table Revision %d\n",
+ uv_systab.revision);
}
#else /* !CONFIG_EFI */
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index c4f667896c28..c1caefc82e62 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1203,6 +1203,8 @@ void __cpuinit cpu_init(void)
load_TR_desc();
load_LDT(&init_mm.context);
+ t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
+
#ifdef CONFIG_DOUBLEFAULT
/* Set up doublefault TSS pointer in the GDT */
__set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
index 3e3cd3db7a0c..208ecf6643df 100644
--- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -65,14 +65,18 @@ enum {
struct acpi_cpufreq_data {
struct acpi_processor_performance *acpi_data;
struct cpufreq_frequency_table *freq_table;
- unsigned int max_freq;
unsigned int resume;
unsigned int cpu_feature;
- u64 saved_aperf, saved_mperf;
};
static DEFINE_PER_CPU(struct acpi_cpufreq_data *, drv_data);
+struct acpi_msr_data {
+ u64 saved_aperf, saved_mperf;
+};
+
+static DEFINE_PER_CPU(struct acpi_msr_data, msr_data);
+
DEFINE_TRACE(power_mark);
/* acpi_perf_data is a pointer to percpu data. */
@@ -204,7 +208,13 @@ static void drv_read(struct drv_cmd *cmd)
static void drv_write(struct drv_cmd *cmd)
{
+ int this_cpu;
+
+ this_cpu = get_cpu();
+ if (cpumask_test_cpu(this_cpu, cmd->mask))
+ do_drv_write(cmd);
smp_call_function_many(cmd->mask, do_drv_write, cmd, 1);
+ put_cpu();
}
static u32 get_cur_val(const struct cpumask *mask)
@@ -277,15 +287,15 @@ static unsigned int get_measured_perf(struct cpufreq_policy *policy,
unsigned int perf_percent;
unsigned int retval;
- if (smp_call_function_single(cpu, read_measured_perf_ctrs, &cur, 1))
+ if (smp_call_function_single(cpu, read_measured_perf_ctrs, &readin, 1))
return 0;
cur.aperf.whole = readin.aperf.whole -
- per_cpu(drv_data, cpu)->saved_aperf;
+ per_cpu(msr_data, cpu).saved_aperf;
cur.mperf.whole = readin.mperf.whole -
- per_cpu(drv_data, cpu)->saved_mperf;
- per_cpu(drv_data, cpu)->saved_aperf = readin.aperf.whole;
- per_cpu(drv_data, cpu)->saved_mperf = readin.mperf.whole;
+ per_cpu(msr_data, cpu).saved_mperf;
+ per_cpu(msr_data, cpu).saved_aperf = readin.aperf.whole;
+ per_cpu(msr_data, cpu).saved_mperf = readin.mperf.whole;
#ifdef __i386__
/*
@@ -329,7 +339,7 @@ static unsigned int get_measured_perf(struct cpufreq_policy *policy,
#endif
- retval = per_cpu(drv_data, policy->cpu)->max_freq * perf_percent / 100;
+ retval = (policy->cpuinfo.max_freq * perf_percent) / 100;
return retval;
}
@@ -682,16 +692,11 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
/* Check for high latency (>20uS) from buggy BIOSes, like on T42 */
if (perf->control_register.space_id == ACPI_ADR_SPACE_FIXED_HARDWARE &&
policy->cpuinfo.transition_latency > 20 * 1000) {
- static int print_once;
policy->cpuinfo.transition_latency = 20 * 1000;
- if (!print_once) {
- print_once = 1;
- printk(KERN_INFO "Capping off P-state tranision latency"
- " at 20 uS\n");
- }
+ printk_once(KERN_INFO "Capping off P-state tranision"
+ " latency at 20 uS\n");
}
- data->max_freq = perf->states[0].core_frequency * 1000;
/* table init */
for (i = 0; i < perf->state_count; i++) {
if (i > 0 && perf->states[i].core_frequency >=
@@ -710,6 +715,9 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
if (result)
goto err_freqfree;
+ if (perf->states[0].core_frequency * 1000 != policy->cpuinfo.max_freq)
+ printk(KERN_WARNING FW_WARN "P-state 0 is not max freq\n");
+
switch (perf->control_register.space_id) {
case ACPI_ADR_SPACE_SYSTEM_IO:
/* Current speed is unknown and not detectable by IO port */
diff --git a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
index 6ac55bd341ae..869615193720 100644
--- a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
+++ b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
@@ -168,6 +168,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
case 0x0E: /* Core */
case 0x0F: /* Core Duo */
case 0x16: /* Celeron Core */
+ case 0x1C: /* Atom */
p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
return speedstep_get_frequency(SPEEDSTEP_CPU_PCORE);
case 0x0D: /* Pentium M (Dothan) */
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k7.c b/arch/x86/kernel/cpu/cpufreq/powernow-k7.c
index 3c28ccd49742..a8363e5be4ef 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k7.c
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k7.c
@@ -168,10 +168,12 @@ static int check_powernow(void)
return 1;
}
+#ifdef CONFIG_X86_POWERNOW_K7_ACPI
static void invalidate_entry(unsigned int entry)
{
powernow_table[entry].frequency = CPUFREQ_ENTRY_INVALID;
}
+#endif
static int get_ranges(unsigned char *pst)
{
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
index 4709ead2db52..e9c6f7736b1c 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
@@ -510,19 +510,10 @@ static int core_voltage_post_transition(struct powernow_k8_data *data,
return 0;
}
-static int check_supported_cpu(unsigned int cpu)
+static long check_supported_cpu(void *unused)
{
- cpumask_t oldmask;
u32 eax, ebx, ecx, edx;
- unsigned int rc = 0;
-
- oldmask = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
-
- if (smp_processor_id() != cpu) {
- printk(KERN_ERR PFX "limiting to cpu %u failed\n", cpu);
- goto out;
- }
+ unsigned int rc = -ENODEV;
if (current_cpu_data.x86_vendor != X86_VENDOR_AMD)
goto out;
@@ -562,10 +553,9 @@ static int check_supported_cpu(unsigned int cpu)
goto out;
}
- rc = 1;
+ rc = 0;
out:
- set_cpus_allowed_ptr(current, &oldmask);
return rc;
}
@@ -1121,11 +1111,16 @@ static int transition_frequency_pstate(struct powernow_k8_data *data,
return res;
}
-/* Driver entry point to switch to the target frequency */
-static int powernowk8_target(struct cpufreq_policy *pol,
- unsigned targfreq, unsigned relation)
+struct target_data {
+ struct cpufreq_policy *pol;
+ unsigned targfreq;
+ unsigned relation;
+};
+
+static long powernowk8_target_on_cpu(void *_tdata)
{
- cpumask_t oldmask;
+ struct target_data *tdata = _tdata;
+ struct cpufreq_policy *pol = tdata->pol;
struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
u32 checkfid;
u32 checkvid;
@@ -1138,22 +1133,13 @@ static int powernowk8_target(struct cpufreq_policy *pol,
checkfid = data->currfid;
checkvid = data->currvid;
- /* only run on specific CPU from here on */
- oldmask = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(pol->cpu));
-
- if (smp_processor_id() != pol->cpu) {
- printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
- goto err_out;
- }
-
if (pending_bit_stuck()) {
printk(KERN_ERR PFX "failing targ, change pending bit set\n");
goto err_out;
}
dprintk("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n",
- pol->cpu, targfreq, pol->min, pol->max, relation);
+ pol->cpu, tdata->targfreq, pol->min, pol->max, tdata->relation);
if (query_current_values_with_pending_wait(data))
goto err_out;
@@ -1173,7 +1159,8 @@ static int powernowk8_target(struct cpufreq_policy *pol,
}
if (cpufreq_frequency_table_target(pol, data->powernow_table,
- targfreq, relation, &newstate))
+ tdata->targfreq, tdata->relation,
+ &newstate))
goto err_out;
mutex_lock(&fidvid_mutex);
@@ -1200,10 +1187,19 @@ static int powernowk8_target(struct cpufreq_policy *pol,
ret = 0;
err_out:
- set_cpus_allowed_ptr(current, &oldmask);
return ret;
}
+/* Driver entry point to switch to the target frequency */
+static int powernowk8_target(struct cpufreq_policy *pol,
+ unsigned targfreq, unsigned relation)
+{
+ struct target_data tdata = { .pol = pol,
+ .targfreq = targfreq,
+ .relation = relation };
+ return work_on_cpu(pol->cpu, powernowk8_target_on_cpu, &tdata);
+}
+
/* Driver entry point to verify the policy and range of frequencies */
static int powernowk8_verify(struct cpufreq_policy *pol)
{
@@ -1215,19 +1211,42 @@ static int powernowk8_verify(struct cpufreq_policy *pol)
return cpufreq_frequency_table_verify(pol, data->powernow_table);
}
+static long __cpuinit powernowk8_cpu_init_on_cpu(void *_data)
+{
+ struct powernow_k8_data *data = _data;
+
+ if (smp_processor_id() != data->cpu) {
+ printk(KERN_ERR PFX "limiting to cpu %u failed\n", data->cpu);
+ return -EIO;
+ }
+
+ if (pending_bit_stuck()) {
+ printk(KERN_ERR PFX "failing init, change pending bit set\n");
+ return -ENODEV;
+ }
+
+ if (query_current_values_with_pending_wait(data))
+ return -ENODEV;
+
+ if (cpu_family == CPU_OPTERON)
+ fidvid_msr_init();
+
+ return 0;
+}
+
/* per CPU init entry point to the driver */
static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
{
struct powernow_k8_data *data;
- cpumask_t oldmask;
int rc;
static int print_once;
if (!cpu_online(pol->cpu))
return -ENODEV;
- if (!check_supported_cpu(pol->cpu))
- return -ENODEV;
+ rc = work_on_cpu(pol->cpu, check_supported_cpu, NULL);
+ if (rc != 0)
+ return rc;
data = kzalloc(sizeof(struct powernow_k8_data), GFP_KERNEL);
if (!data) {
@@ -1278,27 +1297,9 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
pol->cpuinfo.transition_latency = get_transition_latency(data);
/* only run on specific CPU from here on */
- oldmask = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(pol->cpu));
-
- if (smp_processor_id() != pol->cpu) {
- printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
- goto err_out_unmask;
- }
-
- if (pending_bit_stuck()) {
- printk(KERN_ERR PFX "failing init, change pending bit set\n");
- goto err_out_unmask;
- }
-
- if (query_current_values_with_pending_wait(data))
- goto err_out_unmask;
-
- if (cpu_family == CPU_OPTERON)
- fidvid_msr_init();
-
- /* run on any CPU again */
- set_cpus_allowed_ptr(current, &oldmask);
+ rc = work_on_cpu(data->cpu, powernowk8_cpu_init_on_cpu, data);
+ if (rc != 0)
+ goto err_out_exit_acpi;
if (cpu_family == CPU_HW_PSTATE)
cpumask_copy(pol->cpus, cpumask_of(pol->cpu));
@@ -1335,8 +1336,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
return 0;
-err_out_unmask:
- set_cpus_allowed_ptr(current, &oldmask);
+err_out_exit_acpi:
powernow_k8_cpu_exit_acpi(data);
err_out:
@@ -1361,12 +1361,20 @@ static int __devexit powernowk8_cpu_exit(struct cpufreq_policy *pol)
return 0;
}
+static void query_values_on_cpu(void *_err)
+{
+ int *err = _err;
+ struct powernow_k8_data *data = __get_cpu_var(powernow_data);
+
+ *err = query_current_values_with_pending_wait(data);
+}
+
static unsigned int powernowk8_get(unsigned int cpu)
{
struct powernow_k8_data *data;
- cpumask_t oldmask = current->cpus_allowed;
unsigned int khz = 0;
unsigned int first;
+ int err;
first = cpumask_first(cpu_core_mask(cpu));
data = per_cpu(powernow_data, first);
@@ -1374,15 +1382,8 @@ static unsigned int powernowk8_get(unsigned int cpu)
if (!data)
return -EINVAL;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
- if (smp_processor_id() != cpu) {
- printk(KERN_ERR PFX
- "limiting to CPU %d failed in powernowk8_get\n", cpu);
- set_cpus_allowed_ptr(current, &oldmask);
- return 0;
- }
-
- if (query_current_values_with_pending_wait(data))
+ smp_call_function_single(first, query_values_on_cpu, &err, true);
+ if (err)
goto out;
if (cpu_family == CPU_HW_PSTATE)
@@ -1393,7 +1394,6 @@ static unsigned int powernowk8_get(unsigned int cpu)
out:
- set_cpus_allowed_ptr(current, &oldmask);
return khz;
}
@@ -1419,7 +1419,7 @@ static int __cpuinit powernowk8_init(void)
unsigned int i, supported_cpus = 0;
for_each_online_cpu(i) {
- if (check_supported_cpu(i))
+ if (work_on_cpu(i, check_supported_cpu, NULL) == 0)
supported_cpus++;
}
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
index c9f1fdc02830..c9727f62a820 100644
--- a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -323,14 +323,8 @@ static unsigned int get_cur_freq(unsigned int cpu)
{
unsigned l, h;
unsigned clock_freq;
- cpumask_t saved_mask;
- saved_mask = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
- if (smp_processor_id() != cpu)
- return 0;
-
- rdmsr(MSR_IA32_PERF_STATUS, l, h);
+ rdmsr_on_cpu(cpu, MSR_IA32_PERF_STATUS, &l, &h);
clock_freq = extract_clock(l, cpu, 0);
if (unlikely(clock_freq == 0)) {
@@ -340,11 +334,9 @@ static unsigned int get_cur_freq(unsigned int cpu)
* P-state transition (like TM2). Get the last freq set
* in PERF_CTL.
*/
- rdmsr(MSR_IA32_PERF_CTL, l, h);
+ rdmsr_on_cpu(cpu, MSR_IA32_PERF_CTL, &l, &h);
clock_freq = extract_clock(l, cpu, 1);
}
-
- set_cpus_allowed_ptr(current, &saved_mask);
return clock_freq;
}
@@ -467,15 +459,10 @@ static int centrino_target (struct cpufreq_policy *policy,
struct cpufreq_freqs freqs;
int retval = 0;
unsigned int j, k, first_cpu, tmp;
- cpumask_var_t saved_mask, covered_cpus;
+ cpumask_var_t covered_cpus;
- if (unlikely(!alloc_cpumask_var(&saved_mask, GFP_KERNEL)))
- return -ENOMEM;
- if (unlikely(!alloc_cpumask_var(&covered_cpus, GFP_KERNEL))) {
- free_cpumask_var(saved_mask);
+ if (unlikely(!alloc_cpumask_var(&covered_cpus, GFP_KERNEL)))
return -ENOMEM;
- }
- cpumask_copy(saved_mask, &current->cpus_allowed);
if (unlikely(per_cpu(centrino_model, cpu) == NULL)) {
retval = -ENODEV;
@@ -493,7 +480,7 @@ static int centrino_target (struct cpufreq_policy *policy,
first_cpu = 1;
for_each_cpu(j, policy->cpus) {
- const struct cpumask *mask;
+ int good_cpu;
/* cpufreq holds the hotplug lock, so we are safe here */
if (!cpu_online(j))
@@ -504,32 +491,30 @@ static int centrino_target (struct cpufreq_policy *policy,
* Make sure we are running on CPU that wants to change freq
*/
if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
- mask = policy->cpus;
+ good_cpu = cpumask_any_and(policy->cpus,
+ cpu_online_mask);
else
- mask = cpumask_of(j);
+ good_cpu = j;
- set_cpus_allowed_ptr(current, mask);
- preempt_disable();
- if (unlikely(!cpu_isset(smp_processor_id(), *mask))) {
+ if (good_cpu >= nr_cpu_ids) {
dprintk("couldn't limit to CPUs in this domain\n");
retval = -EAGAIN;
if (first_cpu) {
/* We haven't started the transition yet. */
- goto migrate_end;
+ goto out;
}
- preempt_enable();
break;
}
msr = per_cpu(centrino_model, cpu)->op_points[newstate].index;
if (first_cpu) {
- rdmsr(MSR_IA32_PERF_CTL, oldmsr, h);
+ rdmsr_on_cpu(good_cpu, MSR_IA32_PERF_CTL, &oldmsr, &h);
if (msr == (oldmsr & 0xffff)) {
dprintk("no change needed - msr was and needs "
"to be %x\n", oldmsr);
retval = 0;
- goto migrate_end;
+ goto out;
}
freqs.old = extract_clock(oldmsr, cpu, 0);
@@ -553,14 +538,11 @@ static int centrino_target (struct cpufreq_policy *policy,
oldmsr |= msr;
}
- wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
- if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
- preempt_enable();
+ wrmsr_on_cpu(good_cpu, MSR_IA32_PERF_CTL, oldmsr, h);
+ if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
break;
- }
- cpu_set(j, *covered_cpus);
- preempt_enable();
+ cpumask_set_cpu(j, covered_cpus);
}
for_each_cpu(k, policy->cpus) {
@@ -578,10 +560,8 @@ static int centrino_target (struct cpufreq_policy *policy,
* Best effort undo..
*/
- for_each_cpu_mask_nr(j, *covered_cpus) {
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(j));
- wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
- }
+ for_each_cpu(j, covered_cpus)
+ wrmsr_on_cpu(j, MSR_IA32_PERF_CTL, oldmsr, h);
tmp = freqs.new;
freqs.new = freqs.old;
@@ -593,15 +573,9 @@ static int centrino_target (struct cpufreq_policy *policy,
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
}
- set_cpus_allowed_ptr(current, saved_mask);
retval = 0;
- goto out;
-migrate_end:
- preempt_enable();
- set_cpus_allowed_ptr(current, saved_mask);
out:
- free_cpumask_var(saved_mask);
free_cpumask_var(covered_cpus);
return retval;
}
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
index 016c1a4fa3fc..ed9c539ba646 100644
--- a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
+++ b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
@@ -89,7 +89,8 @@ static int speedstep_find_register(void)
* speedstep_set_state - set the SpeedStep state
* @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH)
*
- * Tries to change the SpeedStep state.
+ * Tries to change the SpeedStep state. Can be called from
+ * smp_call_function_single.
*/
static void speedstep_set_state(unsigned int state)
{
@@ -143,6 +144,11 @@ static void speedstep_set_state(unsigned int state)
return;
}
+/* Wrapper for smp_call_function_single. */
+static void _speedstep_set_state(void *_state)
+{
+ speedstep_set_state(*(unsigned int *)_state);
+}
/**
* speedstep_activate - activate SpeedStep control in the chipset
@@ -226,22 +232,28 @@ static unsigned int speedstep_detect_chipset(void)
return 0;
}
-static unsigned int _speedstep_get(const struct cpumask *cpus)
-{
+struct get_freq_data {
unsigned int speed;
- cpumask_t cpus_allowed;
-
- cpus_allowed = current->cpus_allowed;
- set_cpus_allowed_ptr(current, cpus);
- speed = speedstep_get_frequency(speedstep_processor);
- set_cpus_allowed_ptr(current, &cpus_allowed);
- dprintk("detected %u kHz as current frequency\n", speed);
- return speed;
+ unsigned int processor;
+};
+
+static void get_freq_data(void *_data)
+{
+ struct get_freq_data *data = _data;
+
+ data->speed = speedstep_get_frequency(data->processor);
}
static unsigned int speedstep_get(unsigned int cpu)
{
- return _speedstep_get(cpumask_of(cpu));
+ struct get_freq_data data = { .processor = cpu };
+
+ /* You're supposed to ensure CPU is online. */
+ if (smp_call_function_single(cpu, get_freq_data, &data, 1) != 0)
+ BUG();
+
+ dprintk("detected %u kHz as current frequency\n", data.speed);
+ return data.speed;
}
/**
@@ -257,16 +269,16 @@ static int speedstep_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{
- unsigned int newstate = 0;
+ unsigned int newstate = 0, policy_cpu;
struct cpufreq_freqs freqs;
- cpumask_t cpus_allowed;
int i;
if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0],
target_freq, relation, &newstate))
return -EINVAL;
- freqs.old = _speedstep_get(policy->cpus);
+ policy_cpu = cpumask_any_and(policy->cpus, cpu_online_mask);
+ freqs.old = speedstep_get(policy_cpu);
freqs.new = speedstep_freqs[newstate].frequency;
freqs.cpu = policy->cpu;
@@ -276,20 +288,13 @@ static int speedstep_target(struct cpufreq_policy *policy,
if (freqs.old == freqs.new)
return 0;
- cpus_allowed = current->cpus_allowed;
-
for_each_cpu(i, policy->cpus) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
}
- /* switch to physical CPU where state is to be changed */
- set_cpus_allowed_ptr(current, policy->cpus);
-
- speedstep_set_state(newstate);
-
- /* allow to be run on all CPUs */
- set_cpus_allowed_ptr(current, &cpus_allowed);
+ smp_call_function_single(policy_cpu, _speedstep_set_state, &newstate,
+ true);
for_each_cpu(i, policy->cpus) {
freqs.cpu = i;
@@ -312,33 +317,35 @@ static int speedstep_verify(struct cpufreq_policy *policy)
return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]);
}
+static long get_freqs_on_cpu(void *_policy)
+{
+ struct cpufreq_policy *policy = _policy;
+
+ return speedstep_get_freqs(speedstep_processor,
+ &speedstep_freqs[SPEEDSTEP_LOW].frequency,
+ &speedstep_freqs[SPEEDSTEP_HIGH].frequency,
+ &policy->cpuinfo.transition_latency,
+ &speedstep_set_state);
+}
static int speedstep_cpu_init(struct cpufreq_policy *policy)
{
- int result = 0;
- unsigned int speed;
- cpumask_t cpus_allowed;
+ int result;
+ unsigned int policy_cpu, speed;
/* only run on CPU to be set, or on its sibling */
#ifdef CONFIG_SMP
cpumask_copy(policy->cpus, cpu_sibling_mask(policy->cpu));
#endif
-
- cpus_allowed = current->cpus_allowed;
- set_cpus_allowed_ptr(current, policy->cpus);
+ policy_cpu = cpumask_any_and(policy->cpus, cpu_online_mask);
/* detect low and high frequency and transition latency */
- result = speedstep_get_freqs(speedstep_processor,
- &speedstep_freqs[SPEEDSTEP_LOW].frequency,
- &speedstep_freqs[SPEEDSTEP_HIGH].frequency,
- &policy->cpuinfo.transition_latency,
- &speedstep_set_state);
- set_cpus_allowed_ptr(current, &cpus_allowed);
+ result = work_on_cpu(policy_cpu, get_freqs_on_cpu, policy);
if (result)
return result;
/* get current speed setting */
- speed = _speedstep_get(policy->cpus);
+ speed = speedstep_get(policy_cpu);
if (!speed)
return -EIO;
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c
index 2e3c6862657b..f4c290b8482f 100644
--- a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c
+++ b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c
@@ -226,6 +226,7 @@ static unsigned int pentium4_get_frequency(void)
}
+/* Warning: may get called from smp_call_function_single. */
unsigned int speedstep_get_frequency(unsigned int processor)
{
switch (processor) {
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index 483eda96e102..789efe217e1a 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -17,6 +17,7 @@
#include <asm/processor.h>
#include <asm/smp.h>
+#include <asm/k8.h>
#define LVL_1_INST 1
#define LVL_1_DATA 2
@@ -159,14 +160,6 @@ struct _cpuid4_info_regs {
unsigned long can_disable;
};
-#if defined(CONFIG_PCI) && defined(CONFIG_SYSFS)
-static struct pci_device_id k8_nb_id[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) },
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1203) },
- {}
-};
-#endif
-
unsigned short num_cache_leaves;
/* AMD doesn't have CPUID4. Emulate it here to report the same
@@ -207,10 +200,17 @@ union l3_cache {
};
static const unsigned short __cpuinitconst assocs[] = {
- [1] = 1, [2] = 2, [4] = 4, [6] = 8,
- [8] = 16, [0xa] = 32, [0xb] = 48,
+ [1] = 1,
+ [2] = 2,
+ [4] = 4,
+ [6] = 8,
+ [8] = 16,
+ [0xa] = 32,
+ [0xb] = 48,
[0xc] = 64,
- [0xf] = 0xffff // ??
+ [0xd] = 96,
+ [0xe] = 128,
+ [0xf] = 0xffff /* fully associative - no way to show this currently */
};
static const unsigned char __cpuinitconst levels[] = { 1, 1, 2, 3 };
@@ -271,7 +271,8 @@ amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax,
eax->split.type = types[leaf];
eax->split.level = levels[leaf];
if (leaf == 3)
- eax->split.num_threads_sharing = current_cpu_data.x86_max_cores - 1;
+ eax->split.num_threads_sharing =
+ current_cpu_data.x86_max_cores - 1;
else
eax->split.num_threads_sharing = 0;
eax->split.num_cores_on_die = current_cpu_data.x86_max_cores - 1;
@@ -291,6 +292,14 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
{
if (index < 3)
return;
+
+ if (boot_cpu_data.x86 == 0x11)
+ return;
+
+ /* see erratum #382 */
+ if ((boot_cpu_data.x86 == 0x10) && (boot_cpu_data.x86_model < 0x8))
+ return;
+
this_leaf->can_disable = 1;
}
@@ -696,97 +705,75 @@ static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf)
#define to_object(k) container_of(k, struct _index_kobject, kobj)
#define to_attr(a) container_of(a, struct _cache_attr, attr)
-#ifdef CONFIG_PCI
-static struct pci_dev *get_k8_northbridge(int node)
-{
- struct pci_dev *dev = NULL;
- int i;
-
- for (i = 0; i <= node; i++) {
- do {
- dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
- if (!dev)
- break;
- } while (!pci_match_id(&k8_nb_id[0], dev));
- if (!dev)
- break;
- }
- return dev;
-}
-#else
-static struct pci_dev *get_k8_northbridge(int node)
-{
- return NULL;
-}
-#endif
-
-static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf)
+static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
+ unsigned int index)
{
- const struct cpumask *mask = to_cpumask(this_leaf->shared_cpu_map);
- int node = cpu_to_node(cpumask_first(mask));
- struct pci_dev *dev = NULL;
- ssize_t ret = 0;
- int i;
+ int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
+ int node = cpu_to_node(cpu);
+ struct pci_dev *dev = node_to_k8_nb_misc(node);
+ unsigned int reg = 0;
if (!this_leaf->can_disable)
- return sprintf(buf, "Feature not enabled\n");
-
- dev = get_k8_northbridge(node);
- if (!dev) {
- printk(KERN_ERR "Attempting AMD northbridge operation on a system with no northbridge\n");
return -EINVAL;
- }
- for (i = 0; i < 2; i++) {
- unsigned int reg;
+ if (!dev)
+ return -EINVAL;
- pci_read_config_dword(dev, 0x1BC + i * 4, &reg);
+ pci_read_config_dword(dev, 0x1BC + index * 4, &reg);
+ return sprintf(buf, "%x\n", reg);
+}
- ret += sprintf(buf, "%sEntry: %d\n", buf, i);
- ret += sprintf(buf, "%sReads: %s\tNew Entries: %s\n",
- buf,
- reg & 0x80000000 ? "Disabled" : "Allowed",
- reg & 0x40000000 ? "Disabled" : "Allowed");
- ret += sprintf(buf, "%sSubCache: %x\tIndex: %x\n",
- buf, (reg & 0x30000) >> 16, reg & 0xfff);
- }
- return ret;
+#define SHOW_CACHE_DISABLE(index) \
+static ssize_t \
+show_cache_disable_##index(struct _cpuid4_info *this_leaf, char *buf) \
+{ \
+ return show_cache_disable(this_leaf, buf, index); \
}
+SHOW_CACHE_DISABLE(0)
+SHOW_CACHE_DISABLE(1)
-static ssize_t
-store_cache_disable(struct _cpuid4_info *this_leaf, const char *buf,
- size_t count)
+static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
+ const char *buf, size_t count, unsigned int index)
{
- const struct cpumask *mask = to_cpumask(this_leaf->shared_cpu_map);
- int node = cpu_to_node(cpumask_first(mask));
- struct pci_dev *dev = NULL;
- unsigned int ret, index, val;
+ int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
+ int node = cpu_to_node(cpu);
+ struct pci_dev *dev = node_to_k8_nb_misc(node);
+ unsigned long val = 0;
+ unsigned int scrubber = 0;
if (!this_leaf->can_disable)
- return 0;
-
- if (strlen(buf) > 15)
return -EINVAL;
- ret = sscanf(buf, "%x %x", &index, &val);
- if (ret != 2)
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (!dev)
return -EINVAL;
- if (index > 1)
+
+ if (strict_strtoul(buf, 10, &val) < 0)
return -EINVAL;
val |= 0xc0000000;
- dev = get_k8_northbridge(node);
- if (!dev) {
- printk(KERN_ERR "Attempting AMD northbridge operation on a system with no northbridge\n");
- return -EINVAL;
- }
+
+ pci_read_config_dword(dev, 0x58, &scrubber);
+ scrubber &= ~0x1f000000;
+ pci_write_config_dword(dev, 0x58, scrubber);
pci_write_config_dword(dev, 0x1BC + index * 4, val & ~0x40000000);
wbinvd();
pci_write_config_dword(dev, 0x1BC + index * 4, val);
+ return count;
+}
- return 1;
+#define STORE_CACHE_DISABLE(index) \
+static ssize_t \
+store_cache_disable_##index(struct _cpuid4_info *this_leaf, \
+ const char *buf, size_t count) \
+{ \
+ return store_cache_disable(this_leaf, buf, count, index); \
}
+STORE_CACHE_DISABLE(0)
+STORE_CACHE_DISABLE(1)
struct _cache_attr {
struct attribute attr;
@@ -808,7 +795,10 @@ define_one_ro(size);
define_one_ro(shared_cpu_map);
define_one_ro(shared_cpu_list);
-static struct _cache_attr cache_disable = __ATTR(cache_disable, 0644, show_cache_disable, store_cache_disable);
+static struct _cache_attr cache_disable_0 = __ATTR(cache_disable_0, 0644,
+ show_cache_disable_0, store_cache_disable_0);
+static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644,
+ show_cache_disable_1, store_cache_disable_1);
static struct attribute * default_attrs[] = {
&type.attr,
@@ -820,7 +810,8 @@ static struct attribute * default_attrs[] = {
&size.attr,
&shared_cpu_map.attr,
&shared_cpu_list.attr,
- &cache_disable.attr,
+ &cache_disable_0.attr,
+ &cache_disable_1.attr,
NULL
};
diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c
index 863f89568b1a..6fb0b359d2a5 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_64.c
@@ -239,9 +239,10 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
* Don't get the IP here because it's unlikely to
* have anything to do with the actual error location.
*/
-
- mce_log(&m);
- add_taint(TAINT_MACHINE_CHECK);
+ if (!(flags & MCP_DONTLOG)) {
+ mce_log(&m);
+ add_taint(TAINT_MACHINE_CHECK);
+ }
/*
* Clear state for this bank.
@@ -452,13 +453,14 @@ void mce_log_therm_throt_event(__u64 status)
*/
static int check_interval = 5 * 60; /* 5 minutes */
-static int next_interval; /* in jiffies */
+static DEFINE_PER_CPU(int, next_interval); /* in jiffies */
static void mcheck_timer(unsigned long);
static DEFINE_PER_CPU(struct timer_list, mce_timer);
static void mcheck_timer(unsigned long data)
{
struct timer_list *t = &per_cpu(mce_timer, data);
+ int *n;
WARN_ON(smp_processor_id() != data);
@@ -470,14 +472,14 @@ static void mcheck_timer(unsigned long data)
* Alert userspace if needed. If we logged an MCE, reduce the
* polling interval, otherwise increase the polling interval.
*/
+ n = &__get_cpu_var(next_interval);
if (mce_notify_user()) {
- next_interval = max(next_interval/2, HZ/100);
+ *n = max(*n/2, HZ/100);
} else {
- next_interval = min(next_interval * 2,
- (int)round_jiffies_relative(check_interval*HZ));
+ *n = min(*n*2, (int)round_jiffies_relative(check_interval*HZ));
}
- t->expires = jiffies + next_interval;
+ t->expires = jiffies + *n;
add_timer(t);
}
@@ -584,7 +586,7 @@ static void mce_init(void *dummy)
* Log the machine checks left over from the previous reset.
*/
bitmap_fill(all_banks, MAX_NR_BANKS);
- machine_check_poll(MCP_UC, &all_banks);
+ machine_check_poll(MCP_UC|(!mce_bootlog ? MCP_DONTLOG : 0), &all_banks);
set_in_cr4(X86_CR4_MCE);
@@ -632,14 +634,13 @@ static void mce_cpu_features(struct cpuinfo_x86 *c)
static void mce_init_timer(void)
{
struct timer_list *t = &__get_cpu_var(mce_timer);
+ int *n = &__get_cpu_var(next_interval);
- /* data race harmless because everyone sets to the same value */
- if (!next_interval)
- next_interval = check_interval * HZ;
- if (!next_interval)
+ *n = check_interval * HZ;
+ if (!*n)
return;
setup_timer(t, mcheck_timer, smp_processor_id());
- t->expires = round_jiffies(jiffies + next_interval);
+ t->expires = round_jiffies(jiffies + *n);
add_timer(t);
}
@@ -907,7 +908,6 @@ static void mce_cpu_restart(void *data)
/* Reinit MCEs after user configuration changes */
static void mce_restart(void)
{
- next_interval = check_interval * HZ;
on_each_cpu(mce_cpu_restart, NULL, 1);
}
@@ -1110,7 +1110,8 @@ static int __cpuinit mce_cpu_callback(struct notifier_block *nfb,
break;
case CPU_DOWN_FAILED:
case CPU_DOWN_FAILED_FROZEN:
- t->expires = round_jiffies(jiffies + next_interval);
+ t->expires = round_jiffies(jiffies +
+ __get_cpu_var(next_interval));
add_timer_on(t, cpu);
smp_call_function_single(cpu, mce_reenable_cpu, &action, 1);
break;
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
index d6b72df89d69..cef3ee30744b 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
@@ -151,10 +151,11 @@ static void print_update(char *type, int *hdr, int num)
static void cmci_discover(int banks, int boot)
{
unsigned long *owned = (void *)&__get_cpu_var(mce_banks_owned);
+ unsigned long flags;
int hdr = 0;
int i;
- spin_lock(&cmci_discover_lock);
+ spin_lock_irqsave(&cmci_discover_lock, flags);
for (i = 0; i < banks; i++) {
u64 val;
@@ -184,7 +185,7 @@ static void cmci_discover(int banks, int boot)
WARN_ON(!test_bit(i, __get_cpu_var(mce_poll_banks)));
}
}
- spin_unlock(&cmci_discover_lock);
+ spin_unlock_irqrestore(&cmci_discover_lock, flags);
if (hdr)
printk(KERN_CONT "\n");
}
@@ -211,13 +212,14 @@ void cmci_recheck(void)
*/
void cmci_clear(void)
{
+ unsigned long flags;
int i;
int banks;
u64 val;
if (!cmci_supported(&banks))
return;
- spin_lock(&cmci_discover_lock);
+ spin_lock_irqsave(&cmci_discover_lock, flags);
for (i = 0; i < banks; i++) {
if (!test_bit(i, __get_cpu_var(mce_banks_owned)))
continue;
@@ -227,7 +229,7 @@ void cmci_clear(void)
wrmsrl(MSR_IA32_MC0_CTL2 + i, val);
__clear_bit(i, __get_cpu_var(mce_banks_owned));
}
- spin_unlock(&cmci_discover_lock);
+ spin_unlock_irqrestore(&cmci_discover_lock, flags);
}
/*
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c
index f93047fed791..d5e30397246b 100644
--- a/arch/x86/kernel/cpu/proc.c
+++ b/arch/x86/kernel/cpu/proc.c
@@ -14,7 +14,7 @@ static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c,
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",
- cpumask_weight(cpu_sibling_mask(cpu)));
+ cpumask_weight(cpu_core_mask(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);
seq_printf(m, "apicid\t\t: %d\n", c->apicid);
diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c
index 87b67e3a765a..48bfe1386038 100644
--- a/arch/x86/kernel/ds.c
+++ b/arch/x86/kernel/ds.c
@@ -19,45 +19,61 @@
* Markus Metzger <markus.t.metzger@intel.com>, 2007-2009
*/
-
-#include <asm/ds.h>
-
-#include <linux/errno.h>
+#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/slab.h>
+#include <linux/errno.h>
#include <linux/sched.h>
+#include <linux/slab.h>
#include <linux/mm.h>
-#include <linux/kernel.h>
+#include <linux/trace_clock.h>
+
+#include <asm/ds.h>
+#include "ds_selftest.h"
/*
- * The configuration for a particular DS hardware implementation.
+ * The configuration for a particular DS hardware implementation:
*/
struct ds_configuration {
- /* the name of the configuration */
- const char *name;
- /* the size of one pointer-typed field in the DS structure and
- in the BTS and PEBS buffers in bytes;
- this covers the first 8 DS fields related to buffer management. */
- unsigned char sizeof_field;
- /* the size of a BTS/PEBS record in bytes */
- unsigned char sizeof_rec[2];
- /* a series of bit-masks to control various features indexed
- * by enum ds_feature */
- unsigned long ctl[dsf_ctl_max];
+ /* The name of the configuration: */
+ const char *name;
+
+ /* The size of pointer-typed fields in DS, BTS, and PEBS: */
+ unsigned char sizeof_ptr_field;
+
+ /* The size of a BTS/PEBS record in bytes: */
+ unsigned char sizeof_rec[2];
+
+ /* The number of pebs counter reset values in the DS structure. */
+ unsigned char nr_counter_reset;
+
+ /* Control bit-masks indexed by enum ds_feature: */
+ unsigned long ctl[dsf_ctl_max];
};
-static DEFINE_PER_CPU(struct ds_configuration, ds_cfg_array);
+static struct ds_configuration ds_cfg __read_mostly;
+
+
+/* Maximal size of a DS configuration: */
+#define MAX_SIZEOF_DS 0x80
-#define ds_cfg per_cpu(ds_cfg_array, smp_processor_id())
+/* Maximal size of a BTS record: */
+#define MAX_SIZEOF_BTS (3 * 8)
-#define MAX_SIZEOF_DS (12 * 8) /* maximal size of a DS configuration */
-#define MAX_SIZEOF_BTS (3 * 8) /* maximal size of a BTS record */
-#define DS_ALIGNMENT (1 << 3) /* BTS and PEBS buffer alignment */
+/* BTS and PEBS buffer alignment: */
+#define DS_ALIGNMENT (1 << 3)
-#define BTS_CONTROL \
- (ds_cfg.ctl[dsf_bts] | ds_cfg.ctl[dsf_bts_kernel] | ds_cfg.ctl[dsf_bts_user] |\
- ds_cfg.ctl[dsf_bts_overflow])
+/* Number of buffer pointers in DS: */
+#define NUM_DS_PTR_FIELDS 8
+/* Size of a pebs reset value in DS: */
+#define PEBS_RESET_FIELD_SIZE 8
+
+/* Mask of control bits in the DS MSR register: */
+#define BTS_CONTROL \
+ ( ds_cfg.ctl[dsf_bts] | \
+ ds_cfg.ctl[dsf_bts_kernel] | \
+ ds_cfg.ctl[dsf_bts_user] | \
+ ds_cfg.ctl[dsf_bts_overflow] )
/*
* A BTS or PEBS tracer.
@@ -66,29 +82,36 @@ static DEFINE_PER_CPU(struct ds_configuration, ds_cfg_array);
* to identify tracers.
*/
struct ds_tracer {
- /* the DS context (partially) owned by this tracer */
- struct ds_context *context;
- /* the buffer provided on ds_request() and its size in bytes */
- void *buffer;
- size_t size;
+ /* The DS context (partially) owned by this tracer. */
+ struct ds_context *context;
+ /* The buffer provided on ds_request() and its size in bytes. */
+ void *buffer;
+ size_t size;
};
struct bts_tracer {
- /* the common DS part */
- struct ds_tracer ds;
- /* the trace including the DS configuration */
- struct bts_trace trace;
- /* buffer overflow notification function */
- bts_ovfl_callback_t ovfl;
+ /* The common DS part: */
+ struct ds_tracer ds;
+
+ /* The trace including the DS configuration: */
+ struct bts_trace trace;
+
+ /* Buffer overflow notification function: */
+ bts_ovfl_callback_t ovfl;
+
+ /* Active flags affecting trace collection. */
+ unsigned int flags;
};
struct pebs_tracer {
- /* the common DS part */
- struct ds_tracer ds;
- /* the trace including the DS configuration */
- struct pebs_trace trace;
- /* buffer overflow notification function */
- pebs_ovfl_callback_t ovfl;
+ /* The common DS part: */
+ struct ds_tracer ds;
+
+ /* The trace including the DS configuration: */
+ struct pebs_trace trace;
+
+ /* Buffer overflow notification function: */
+ pebs_ovfl_callback_t ovfl;
};
/*
@@ -97,6 +120,7 @@ struct pebs_tracer {
*
* The DS configuration consists of the following fields; different
* architetures vary in the size of those fields.
+ *
* - double-word aligned base linear address of the BTS buffer
* - write pointer into the BTS buffer
* - end linear address of the BTS buffer (one byte beyond the end of
@@ -135,21 +159,22 @@ enum ds_field {
};
enum ds_qualifier {
- ds_bts = 0,
+ ds_bts = 0,
ds_pebs
};
-static inline unsigned long ds_get(const unsigned char *base,
- enum ds_qualifier qual, enum ds_field field)
+static inline unsigned long
+ds_get(const unsigned char *base, enum ds_qualifier qual, enum ds_field field)
{
- base += (ds_cfg.sizeof_field * (field + (4 * qual)));
+ base += (ds_cfg.sizeof_ptr_field * (field + (4 * qual)));
return *(unsigned long *)base;
}
-static inline void ds_set(unsigned char *base, enum ds_qualifier qual,
- enum ds_field field, unsigned long value)
+static inline void
+ds_set(unsigned char *base, enum ds_qualifier qual, enum ds_field field,
+ unsigned long value)
{
- base += (ds_cfg.sizeof_field * (field + (4 * qual)));
+ base += (ds_cfg.sizeof_ptr_field * (field + (4 * qual)));
(*(unsigned long *)base) = value;
}
@@ -159,7 +184,6 @@ static inline void ds_set(unsigned char *base, enum ds_qualifier qual,
*/
static DEFINE_SPINLOCK(ds_lock);
-
/*
* We either support (system-wide) per-cpu or per-thread allocation.
* We distinguish the two based on the task_struct pointer, where a
@@ -178,12 +202,28 @@ static DEFINE_SPINLOCK(ds_lock);
*/
static atomic_t tracers = ATOMIC_INIT(0);
-static inline void get_tracer(struct task_struct *task)
+static inline int get_tracer(struct task_struct *task)
{
- if (task)
+ int error;
+
+ spin_lock_irq(&ds_lock);
+
+ if (task) {
+ error = -EPERM;
+ if (atomic_read(&tracers) < 0)
+ goto out;
atomic_inc(&tracers);
- else
+ } else {
+ error = -EPERM;
+ if (atomic_read(&tracers) > 0)
+ goto out;
atomic_dec(&tracers);
+ }
+
+ error = 0;
+out:
+ spin_unlock_irq(&ds_lock);
+ return error;
}
static inline void put_tracer(struct task_struct *task)
@@ -194,14 +234,6 @@ static inline void put_tracer(struct task_struct *task)
atomic_inc(&tracers);
}
-static inline int check_tracer(struct task_struct *task)
-{
- return task ?
- (atomic_read(&tracers) >= 0) :
- (atomic_read(&tracers) <= 0);
-}
-
-
/*
* The DS context is either attached to a thread or to a cpu:
* - in the former case, the thread_struct contains a pointer to the
@@ -213,61 +245,58 @@ static inline int check_tracer(struct task_struct *task)
* deallocated when the last user puts the context.
*/
struct ds_context {
- /* pointer to the DS configuration; goes into MSR_IA32_DS_AREA */
- unsigned char ds[MAX_SIZEOF_DS];
- /* the owner of the BTS and PEBS configuration, respectively */
- struct bts_tracer *bts_master;
- struct pebs_tracer *pebs_master;
- /* use count */
- unsigned long count;
- /* a pointer to the context location inside the thread_struct
- * or the per_cpu context array */
- struct ds_context **this;
- /* a pointer to the task owning this context, or NULL, if the
- * context is owned by a cpu */
- struct task_struct *task;
-};
+ /* The DS configuration; goes into MSR_IA32_DS_AREA: */
+ unsigned char ds[MAX_SIZEOF_DS];
+
+ /* The owner of the BTS and PEBS configuration, respectively: */
+ struct bts_tracer *bts_master;
+ struct pebs_tracer *pebs_master;
-static DEFINE_PER_CPU(struct ds_context *, system_context_array);
+ /* Use count: */
+ unsigned long count;
-#define system_context per_cpu(system_context_array, smp_processor_id())
+ /* Pointer to the context pointer field: */
+ struct ds_context **this;
+
+ /* The traced task; NULL for cpu tracing: */
+ struct task_struct *task;
+
+ /* The traced cpu; only valid if task is NULL: */
+ int cpu;
+};
+static DEFINE_PER_CPU(struct ds_context *, cpu_context);
-static inline struct ds_context *ds_get_context(struct task_struct *task)
+
+static struct ds_context *ds_get_context(struct task_struct *task, int cpu)
{
struct ds_context **p_context =
- (task ? &task->thread.ds_ctx : &system_context);
+ (task ? &task->thread.ds_ctx : &per_cpu(cpu_context, cpu));
struct ds_context *context = NULL;
struct ds_context *new_context = NULL;
- unsigned long irq;
/* Chances are small that we already have a context. */
new_context = kzalloc(sizeof(*new_context), GFP_KERNEL);
if (!new_context)
return NULL;
- spin_lock_irqsave(&ds_lock, irq);
+ spin_lock_irq(&ds_lock);
context = *p_context;
- if (!context) {
+ if (likely(!context)) {
context = new_context;
context->this = p_context;
context->task = task;
+ context->cpu = cpu;
context->count = 0;
- if (task)
- set_tsk_thread_flag(task, TIF_DS_AREA_MSR);
-
- if (!task || (task == current))
- wrmsrl(MSR_IA32_DS_AREA, (unsigned long)context->ds);
-
*p_context = context;
}
context->count++;
- spin_unlock_irqrestore(&ds_lock, irq);
+ spin_unlock_irq(&ds_lock);
if (context != new_context)
kfree(new_context);
@@ -275,8 +304,9 @@ static inline struct ds_context *ds_get_context(struct task_struct *task)
return context;
}
-static inline void ds_put_context(struct ds_context *context)
+static void ds_put_context(struct ds_context *context)
{
+ struct task_struct *task;
unsigned long irq;
if (!context)
@@ -291,17 +321,55 @@ static inline void ds_put_context(struct ds_context *context)
*(context->this) = NULL;
- if (context->task)
- clear_tsk_thread_flag(context->task, TIF_DS_AREA_MSR);
+ task = context->task;
+
+ if (task)
+ clear_tsk_thread_flag(task, TIF_DS_AREA_MSR);
- if (!context->task || (context->task == current))
- wrmsrl(MSR_IA32_DS_AREA, 0);
+ /*
+ * We leave the (now dangling) pointer to the DS configuration in
+ * the DS_AREA msr. This is as good or as bad as replacing it with
+ * NULL - the hardware would crash if we enabled tracing.
+ *
+ * This saves us some problems with having to write an msr on a
+ * different cpu while preventing others from doing the same for the
+ * next context for that same cpu.
+ */
spin_unlock_irqrestore(&ds_lock, irq);
+ /* The context might still be in use for context switching. */
+ if (task && (task != current))
+ wait_task_context_switch(task);
+
kfree(context);
}
+static void ds_install_ds_area(struct ds_context *context)
+{
+ unsigned long ds;
+
+ ds = (unsigned long)context->ds;
+
+ /*
+ * There is a race between the bts master and the pebs master.
+ *
+ * The thread/cpu access is synchronized via get/put_cpu() for
+ * task tracing and via wrmsr_on_cpu for cpu tracing.
+ *
+ * If bts and pebs are collected for the same task or same cpu,
+ * the same confiuration is written twice.
+ */
+ if (context->task) {
+ get_cpu();
+ if (context->task == current)
+ wrmsrl(MSR_IA32_DS_AREA, ds);
+ set_tsk_thread_flag(context->task, TIF_DS_AREA_MSR);
+ put_cpu();
+ } else
+ wrmsr_on_cpu(context->cpu, MSR_IA32_DS_AREA,
+ (u32)((u64)ds), (u32)((u64)ds >> 32));
+}
/*
* Call the tracer's callback on a buffer overflow.
@@ -332,9 +400,9 @@ static void ds_overflow(struct ds_context *context, enum ds_qualifier qual)
* The remainder of any partially written record is zeroed out.
*
* context: the DS context
- * qual: the buffer type
- * record: the data to write
- * size: the size of the data
+ * qual: the buffer type
+ * record: the data to write
+ * size: the size of the data
*/
static int ds_write(struct ds_context *context, enum ds_qualifier qual,
const void *record, size_t size)
@@ -349,14 +417,14 @@ static int ds_write(struct ds_context *context, enum ds_qualifier qual,
unsigned long write_size, adj_write_size;
/*
- * write as much as possible without producing an
+ * Write as much as possible without producing an
* overflow interrupt.
*
- * interrupt_threshold must either be
+ * Interrupt_threshold must either be
* - bigger than absolute_maximum or
* - point to a record between buffer_base and absolute_maximum
*
- * index points to a valid record.
+ * Index points to a valid record.
*/
base = ds_get(context->ds, qual, ds_buffer_base);
index = ds_get(context->ds, qual, ds_index);
@@ -365,8 +433,10 @@ static int ds_write(struct ds_context *context, enum ds_qualifier qual,
write_end = min(end, int_th);
- /* if we are already beyond the interrupt threshold,
- * we fill the entire buffer */
+ /*
+ * If we are already beyond the interrupt threshold,
+ * we fill the entire buffer.
+ */
if (write_end <= index)
write_end = end;
@@ -383,7 +453,7 @@ static int ds_write(struct ds_context *context, enum ds_qualifier qual,
adj_write_size = write_size / ds_cfg.sizeof_rec[qual];
adj_write_size *= ds_cfg.sizeof_rec[qual];
- /* zero out trailing bytes */
+ /* Zero out trailing bytes. */
memset((char *)index + write_size, 0,
adj_write_size - write_size);
index += adj_write_size;
@@ -410,7 +480,7 @@ static int ds_write(struct ds_context *context, enum ds_qualifier qual,
* Later architectures use 64bit pointers throughout, whereas earlier
* architectures use 32bit pointers in 32bit mode.
*
- * We compute the base address for the first 8 fields based on:
+ * We compute the base address for the fields based on:
* - the field size stored in the DS configuration
* - the relative field position
*
@@ -431,23 +501,23 @@ enum bts_field {
bts_to,
bts_flags,
- bts_qual = bts_from,
- bts_jiffies = bts_to,
- bts_pid = bts_flags,
+ bts_qual = bts_from,
+ bts_clock = bts_to,
+ bts_pid = bts_flags,
- bts_qual_mask = (bts_qual_max - 1),
- bts_escape = ((unsigned long)-1 & ~bts_qual_mask)
+ bts_qual_mask = (bts_qual_max - 1),
+ bts_escape = ((unsigned long)-1 & ~bts_qual_mask)
};
static inline unsigned long bts_get(const char *base, enum bts_field field)
{
- base += (ds_cfg.sizeof_field * field);
+ base += (ds_cfg.sizeof_ptr_field * field);
return *(unsigned long *)base;
}
static inline void bts_set(char *base, enum bts_field field, unsigned long val)
{
- base += (ds_cfg.sizeof_field * field);;
+ base += (ds_cfg.sizeof_ptr_field * field);;
(*(unsigned long *)base) = val;
}
@@ -463,8 +533,8 @@ static inline void bts_set(char *base, enum bts_field field, unsigned long val)
*
* return: bytes read/written on success; -Eerrno, otherwise
*/
-static int bts_read(struct bts_tracer *tracer, const void *at,
- struct bts_struct *out)
+static int
+bts_read(struct bts_tracer *tracer, const void *at, struct bts_struct *out)
{
if (!tracer)
return -EINVAL;
@@ -478,8 +548,8 @@ static int bts_read(struct bts_tracer *tracer, const void *at,
memset(out, 0, sizeof(*out));
if ((bts_get(at, bts_qual) & ~bts_qual_mask) == bts_escape) {
out->qualifier = (bts_get(at, bts_qual) & bts_qual_mask);
- out->variant.timestamp.jiffies = bts_get(at, bts_jiffies);
- out->variant.timestamp.pid = bts_get(at, bts_pid);
+ out->variant.event.clock = bts_get(at, bts_clock);
+ out->variant.event.pid = bts_get(at, bts_pid);
} else {
out->qualifier = bts_branch;
out->variant.lbr.from = bts_get(at, bts_from);
@@ -516,8 +586,8 @@ static int bts_write(struct bts_tracer *tracer, const struct bts_struct *in)
case bts_task_arrives:
case bts_task_departs:
bts_set(raw, bts_qual, (bts_escape | in->qualifier));
- bts_set(raw, bts_jiffies, in->variant.timestamp.jiffies);
- bts_set(raw, bts_pid, in->variant.timestamp.pid);
+ bts_set(raw, bts_clock, in->variant.event.clock);
+ bts_set(raw, bts_pid, in->variant.event.pid);
break;
default:
return -EINVAL;
@@ -555,7 +625,8 @@ static void ds_init_ds_trace(struct ds_trace *trace, enum ds_qualifier qual,
unsigned int flags) {
unsigned long buffer, adj;
- /* adjust the buffer address and size to meet alignment
+ /*
+ * Adjust the buffer address and size to meet alignment
* constraints:
* - buffer is double-word aligned
* - size is multiple of record size
@@ -577,9 +648,11 @@ static void ds_init_ds_trace(struct ds_trace *trace, enum ds_qualifier qual,
trace->begin = (void *)buffer;
trace->top = trace->begin;
trace->end = (void *)(buffer + size);
- /* The value for 'no threshold' is -1, which will set the
+ /*
+ * The value for 'no threshold' is -1, which will set the
* threshold outside of the buffer, just like we want it.
*/
+ ith *= ds_cfg.sizeof_rec[qual];
trace->ith = (void *)(buffer + size - ith);
trace->flags = flags;
@@ -588,18 +661,27 @@ static void ds_init_ds_trace(struct ds_trace *trace, enum ds_qualifier qual,
static int ds_request(struct ds_tracer *tracer, struct ds_trace *trace,
enum ds_qualifier qual, struct task_struct *task,
- void *base, size_t size, size_t th, unsigned int flags)
+ int cpu, void *base, size_t size, size_t th)
{
struct ds_context *context;
int error;
+ size_t req_size;
+
+ error = -EOPNOTSUPP;
+ if (!ds_cfg.sizeof_rec[qual])
+ goto out;
error = -EINVAL;
if (!base)
goto out;
- /* we require some space to do alignment adjustments below */
+ req_size = ds_cfg.sizeof_rec[qual];
+ /* We might need space for alignment adjustments. */
+ if (!IS_ALIGNED((unsigned long)base, DS_ALIGNMENT))
+ req_size += DS_ALIGNMENT;
+
error = -EINVAL;
- if (size < (DS_ALIGNMENT + ds_cfg.sizeof_rec[qual]))
+ if (size < req_size)
goto out;
if (th != (size_t)-1) {
@@ -614,182 +696,318 @@ static int ds_request(struct ds_tracer *tracer, struct ds_trace *trace,
tracer->size = size;
error = -ENOMEM;
- context = ds_get_context(task);
+ context = ds_get_context(task, cpu);
if (!context)
goto out;
tracer->context = context;
- ds_init_ds_trace(trace, qual, base, size, th, flags);
+ /*
+ * Defer any tracer-specific initialization work for the context until
+ * context ownership has been clarified.
+ */
error = 0;
out:
return error;
}
-struct bts_tracer *ds_request_bts(struct task_struct *task,
- void *base, size_t size,
- bts_ovfl_callback_t ovfl, size_t th,
- unsigned int flags)
+static struct bts_tracer *ds_request_bts(struct task_struct *task, int cpu,
+ void *base, size_t size,
+ bts_ovfl_callback_t ovfl, size_t th,
+ unsigned int flags)
{
struct bts_tracer *tracer;
- unsigned long irq;
int error;
+ /* Buffer overflow notification is not yet implemented. */
error = -EOPNOTSUPP;
- if (!ds_cfg.ctl[dsf_bts])
+ if (ovfl)
goto out;
- /* buffer overflow notification is not yet implemented */
- error = -EOPNOTSUPP;
- if (ovfl)
+ error = get_tracer(task);
+ if (error < 0)
goto out;
error = -ENOMEM;
tracer = kzalloc(sizeof(*tracer), GFP_KERNEL);
if (!tracer)
- goto out;
+ goto out_put_tracer;
tracer->ovfl = ovfl;
+ /* Do some more error checking and acquire a tracing context. */
error = ds_request(&tracer->ds, &tracer->trace.ds,
- ds_bts, task, base, size, th, flags);
+ ds_bts, task, cpu, base, size, th);
if (error < 0)
goto out_tracer;
-
- spin_lock_irqsave(&ds_lock, irq);
-
- error = -EPERM;
- if (!check_tracer(task))
- goto out_unlock;
- get_tracer(task);
+ /* Claim the bts part of the tracing context we acquired above. */
+ spin_lock_irq(&ds_lock);
error = -EPERM;
if (tracer->ds.context->bts_master)
- goto out_put_tracer;
+ goto out_unlock;
tracer->ds.context->bts_master = tracer;
- spin_unlock_irqrestore(&ds_lock, irq);
+ spin_unlock_irq(&ds_lock);
+ /*
+ * Now that we own the bts part of the context, let's complete the
+ * initialization for that part.
+ */
+ ds_init_ds_trace(&tracer->trace.ds, ds_bts, base, size, th, flags);
+ ds_write_config(tracer->ds.context, &tracer->trace.ds, ds_bts);
+ ds_install_ds_area(tracer->ds.context);
tracer->trace.read = bts_read;
tracer->trace.write = bts_write;
- ds_write_config(tracer->ds.context, &tracer->trace.ds, ds_bts);
+ /* Start tracing. */
ds_resume_bts(tracer);
return tracer;
- out_put_tracer:
- put_tracer(task);
out_unlock:
- spin_unlock_irqrestore(&ds_lock, irq);
+ spin_unlock_irq(&ds_lock);
ds_put_context(tracer->ds.context);
out_tracer:
kfree(tracer);
+ out_put_tracer:
+ put_tracer(task);
out:
return ERR_PTR(error);
}
-struct pebs_tracer *ds_request_pebs(struct task_struct *task,
- void *base, size_t size,
- pebs_ovfl_callback_t ovfl, size_t th,
- unsigned int flags)
+struct bts_tracer *ds_request_bts_task(struct task_struct *task,
+ void *base, size_t size,
+ bts_ovfl_callback_t ovfl,
+ size_t th, unsigned int flags)
+{
+ return ds_request_bts(task, 0, base, size, ovfl, th, flags);
+}
+
+struct bts_tracer *ds_request_bts_cpu(int cpu, void *base, size_t size,
+ bts_ovfl_callback_t ovfl,
+ size_t th, unsigned int flags)
+{
+ return ds_request_bts(NULL, cpu, base, size, ovfl, th, flags);
+}
+
+static struct pebs_tracer *ds_request_pebs(struct task_struct *task, int cpu,
+ void *base, size_t size,
+ pebs_ovfl_callback_t ovfl, size_t th,
+ unsigned int flags)
{
struct pebs_tracer *tracer;
- unsigned long irq;
int error;
- /* buffer overflow notification is not yet implemented */
+ /* Buffer overflow notification is not yet implemented. */
error = -EOPNOTSUPP;
if (ovfl)
goto out;
+ error = get_tracer(task);
+ if (error < 0)
+ goto out;
+
error = -ENOMEM;
tracer = kzalloc(sizeof(*tracer), GFP_KERNEL);
if (!tracer)
- goto out;
+ goto out_put_tracer;
tracer->ovfl = ovfl;
+ /* Do some more error checking and acquire a tracing context. */
error = ds_request(&tracer->ds, &tracer->trace.ds,
- ds_pebs, task, base, size, th, flags);
+ ds_pebs, task, cpu, base, size, th);
if (error < 0)
goto out_tracer;
- spin_lock_irqsave(&ds_lock, irq);
-
- error = -EPERM;
- if (!check_tracer(task))
- goto out_unlock;
- get_tracer(task);
+ /* Claim the pebs part of the tracing context we acquired above. */
+ spin_lock_irq(&ds_lock);
error = -EPERM;
if (tracer->ds.context->pebs_master)
- goto out_put_tracer;
+ goto out_unlock;
tracer->ds.context->pebs_master = tracer;
- spin_unlock_irqrestore(&ds_lock, irq);
+ spin_unlock_irq(&ds_lock);
+ /*
+ * Now that we own the pebs part of the context, let's complete the
+ * initialization for that part.
+ */
+ ds_init_ds_trace(&tracer->trace.ds, ds_pebs, base, size, th, flags);
ds_write_config(tracer->ds.context, &tracer->trace.ds, ds_pebs);
+ ds_install_ds_area(tracer->ds.context);
+
+ /* Start tracing. */
ds_resume_pebs(tracer);
return tracer;
- out_put_tracer:
- put_tracer(task);
out_unlock:
- spin_unlock_irqrestore(&ds_lock, irq);
+ spin_unlock_irq(&ds_lock);
ds_put_context(tracer->ds.context);
out_tracer:
kfree(tracer);
+ out_put_tracer:
+ put_tracer(task);
out:
return ERR_PTR(error);
}
-void ds_release_bts(struct bts_tracer *tracer)
+struct pebs_tracer *ds_request_pebs_task(struct task_struct *task,
+ void *base, size_t size,
+ pebs_ovfl_callback_t ovfl,
+ size_t th, unsigned int flags)
{
- if (!tracer)
- return;
+ return ds_request_pebs(task, 0, base, size, ovfl, th, flags);
+}
- ds_suspend_bts(tracer);
+struct pebs_tracer *ds_request_pebs_cpu(int cpu, void *base, size_t size,
+ pebs_ovfl_callback_t ovfl,
+ size_t th, unsigned int flags)
+{
+ return ds_request_pebs(NULL, cpu, base, size, ovfl, th, flags);
+}
+
+static void ds_free_bts(struct bts_tracer *tracer)
+{
+ struct task_struct *task;
+
+ task = tracer->ds.context->task;
WARN_ON_ONCE(tracer->ds.context->bts_master != tracer);
tracer->ds.context->bts_master = NULL;
- put_tracer(tracer->ds.context->task);
+ /* Make sure tracing stopped and the tracer is not in use. */
+ if (task && (task != current))
+ wait_task_context_switch(task);
+
ds_put_context(tracer->ds.context);
+ put_tracer(task);
kfree(tracer);
}
+void ds_release_bts(struct bts_tracer *tracer)
+{
+ might_sleep();
+
+ if (!tracer)
+ return;
+
+ ds_suspend_bts(tracer);
+ ds_free_bts(tracer);
+}
+
+int ds_release_bts_noirq(struct bts_tracer *tracer)
+{
+ struct task_struct *task;
+ unsigned long irq;
+ int error;
+
+ if (!tracer)
+ return 0;
+
+ task = tracer->ds.context->task;
+
+ local_irq_save(irq);
+
+ error = -EPERM;
+ if (!task &&
+ (tracer->ds.context->cpu != smp_processor_id()))
+ goto out;
+
+ error = -EPERM;
+ if (task && (task != current))
+ goto out;
+
+ ds_suspend_bts_noirq(tracer);
+ ds_free_bts(tracer);
+
+ error = 0;
+ out:
+ local_irq_restore(irq);
+ return error;
+}
+
+static void update_task_debugctlmsr(struct task_struct *task,
+ unsigned long debugctlmsr)
+{
+ task->thread.debugctlmsr = debugctlmsr;
+
+ get_cpu();
+ if (task == current)
+ update_debugctlmsr(debugctlmsr);
+ put_cpu();
+}
+
void ds_suspend_bts(struct bts_tracer *tracer)
{
struct task_struct *task;
+ unsigned long debugctlmsr;
+ int cpu;
if (!tracer)
return;
+ tracer->flags = 0;
+
task = tracer->ds.context->task;
+ cpu = tracer->ds.context->cpu;
- if (!task || (task == current))
- update_debugctlmsr(get_debugctlmsr() & ~BTS_CONTROL);
+ WARN_ON(!task && irqs_disabled());
- if (task) {
- task->thread.debugctlmsr &= ~BTS_CONTROL;
+ debugctlmsr = (task ?
+ task->thread.debugctlmsr :
+ get_debugctlmsr_on_cpu(cpu));
+ debugctlmsr &= ~BTS_CONTROL;
- if (!task->thread.debugctlmsr)
- clear_tsk_thread_flag(task, TIF_DEBUGCTLMSR);
- }
+ if (task)
+ update_task_debugctlmsr(task, debugctlmsr);
+ else
+ update_debugctlmsr_on_cpu(cpu, debugctlmsr);
}
-void ds_resume_bts(struct bts_tracer *tracer)
+int ds_suspend_bts_noirq(struct bts_tracer *tracer)
{
struct task_struct *task;
- unsigned long control;
+ unsigned long debugctlmsr, irq;
+ int cpu, error = 0;
if (!tracer)
- return;
+ return 0;
+
+ tracer->flags = 0;
task = tracer->ds.context->task;
+ cpu = tracer->ds.context->cpu;
+
+ local_irq_save(irq);
+
+ error = -EPERM;
+ if (!task && (cpu != smp_processor_id()))
+ goto out;
+
+ debugctlmsr = (task ?
+ task->thread.debugctlmsr :
+ get_debugctlmsr());
+ debugctlmsr &= ~BTS_CONTROL;
+
+ if (task)
+ update_task_debugctlmsr(task, debugctlmsr);
+ else
+ update_debugctlmsr(debugctlmsr);
+
+ error = 0;
+ out:
+ local_irq_restore(irq);
+ return error;
+}
+
+static unsigned long ds_bts_control(struct bts_tracer *tracer)
+{
+ unsigned long control;
control = ds_cfg.ctl[dsf_bts];
if (!(tracer->trace.ds.flags & BTS_KERNEL))
@@ -797,41 +1015,149 @@ void ds_resume_bts(struct bts_tracer *tracer)
if (!(tracer->trace.ds.flags & BTS_USER))
control |= ds_cfg.ctl[dsf_bts_user];
- if (task) {
- task->thread.debugctlmsr |= control;
- set_tsk_thread_flag(task, TIF_DEBUGCTLMSR);
- }
-
- if (!task || (task == current))
- update_debugctlmsr(get_debugctlmsr() | control);
+ return control;
}
-void ds_release_pebs(struct pebs_tracer *tracer)
+void ds_resume_bts(struct bts_tracer *tracer)
{
+ struct task_struct *task;
+ unsigned long debugctlmsr;
+ int cpu;
+
if (!tracer)
return;
- ds_suspend_pebs(tracer);
+ tracer->flags = tracer->trace.ds.flags;
+
+ task = tracer->ds.context->task;
+ cpu = tracer->ds.context->cpu;
+
+ WARN_ON(!task && irqs_disabled());
+
+ debugctlmsr = (task ?
+ task->thread.debugctlmsr :
+ get_debugctlmsr_on_cpu(cpu));
+ debugctlmsr |= ds_bts_control(tracer);
+
+ if (task)
+ update_task_debugctlmsr(task, debugctlmsr);
+ else
+ update_debugctlmsr_on_cpu(cpu, debugctlmsr);
+}
+
+int ds_resume_bts_noirq(struct bts_tracer *tracer)
+{
+ struct task_struct *task;
+ unsigned long debugctlmsr, irq;
+ int cpu, error = 0;
+
+ if (!tracer)
+ return 0;
+
+ tracer->flags = tracer->trace.ds.flags;
+
+ task = tracer->ds.context->task;
+ cpu = tracer->ds.context->cpu;
+
+ local_irq_save(irq);
+
+ error = -EPERM;
+ if (!task && (cpu != smp_processor_id()))
+ goto out;
+
+ debugctlmsr = (task ?
+ task->thread.debugctlmsr :
+ get_debugctlmsr());
+ debugctlmsr |= ds_bts_control(tracer);
+
+ if (task)
+ update_task_debugctlmsr(task, debugctlmsr);
+ else
+ update_debugctlmsr(debugctlmsr);
+
+ error = 0;
+ out:
+ local_irq_restore(irq);
+ return error;
+}
+
+static void ds_free_pebs(struct pebs_tracer *tracer)
+{
+ struct task_struct *task;
+
+ task = tracer->ds.context->task;
WARN_ON_ONCE(tracer->ds.context->pebs_master != tracer);
tracer->ds.context->pebs_master = NULL;
- put_tracer(tracer->ds.context->task);
ds_put_context(tracer->ds.context);
+ put_tracer(task);
kfree(tracer);
}
+void ds_release_pebs(struct pebs_tracer *tracer)
+{
+ might_sleep();
+
+ if (!tracer)
+ return;
+
+ ds_suspend_pebs(tracer);
+ ds_free_pebs(tracer);
+}
+
+int ds_release_pebs_noirq(struct pebs_tracer *tracer)
+{
+ struct task_struct *task;
+ unsigned long irq;
+ int error;
+
+ if (!tracer)
+ return 0;
+
+ task = tracer->ds.context->task;
+
+ local_irq_save(irq);
+
+ error = -EPERM;
+ if (!task &&
+ (tracer->ds.context->cpu != smp_processor_id()))
+ goto out;
+
+ error = -EPERM;
+ if (task && (task != current))
+ goto out;
+
+ ds_suspend_pebs_noirq(tracer);
+ ds_free_pebs(tracer);
+
+ error = 0;
+ out:
+ local_irq_restore(irq);
+ return error;
+}
+
void ds_suspend_pebs(struct pebs_tracer *tracer)
{
}
+int ds_suspend_pebs_noirq(struct pebs_tracer *tracer)
+{
+ return 0;
+}
+
void ds_resume_pebs(struct pebs_tracer *tracer)
{
}
+int ds_resume_pebs_noirq(struct pebs_tracer *tracer)
+{
+ return 0;
+}
+
const struct bts_trace *ds_read_bts(struct bts_tracer *tracer)
{
if (!tracer)
@@ -847,8 +1173,12 @@ const struct pebs_trace *ds_read_pebs(struct pebs_tracer *tracer)
return NULL;
ds_read_config(tracer->ds.context, &tracer->trace.ds, ds_pebs);
- tracer->trace.reset_value =
- *(u64 *)(tracer->ds.context->ds + (ds_cfg.sizeof_field * 8));
+
+ tracer->trace.counters = ds_cfg.nr_counter_reset;
+ memcpy(tracer->trace.counter_reset,
+ tracer->ds.context->ds +
+ (NUM_DS_PTR_FIELDS * ds_cfg.sizeof_ptr_field),
+ ds_cfg.nr_counter_reset * PEBS_RESET_FIELD_SIZE);
return &tracer->trace;
}
@@ -873,18 +1203,24 @@ int ds_reset_pebs(struct pebs_tracer *tracer)
tracer->trace.ds.top = tracer->trace.ds.begin;
- ds_set(tracer->ds.context->ds, ds_bts, ds_index,
+ ds_set(tracer->ds.context->ds, ds_pebs, ds_index,
(unsigned long)tracer->trace.ds.top);
return 0;
}
-int ds_set_pebs_reset(struct pebs_tracer *tracer, u64 value)
+int ds_set_pebs_reset(struct pebs_tracer *tracer,
+ unsigned int counter, u64 value)
{
if (!tracer)
return -EINVAL;
- *(u64 *)(tracer->ds.context->ds + (ds_cfg.sizeof_field * 8)) = value;
+ if (ds_cfg.nr_counter_reset < counter)
+ return -EINVAL;
+
+ *(u64 *)(tracer->ds.context->ds +
+ (NUM_DS_PTR_FIELDS * ds_cfg.sizeof_ptr_field) +
+ (counter * PEBS_RESET_FIELD_SIZE)) = value;
return 0;
}
@@ -894,73 +1230,117 @@ static const struct ds_configuration ds_cfg_netburst = {
.ctl[dsf_bts] = (1 << 2) | (1 << 3),
.ctl[dsf_bts_kernel] = (1 << 5),
.ctl[dsf_bts_user] = (1 << 6),
-
- .sizeof_field = sizeof(long),
- .sizeof_rec[ds_bts] = sizeof(long) * 3,
-#ifdef __i386__
- .sizeof_rec[ds_pebs] = sizeof(long) * 10,
-#else
- .sizeof_rec[ds_pebs] = sizeof(long) * 18,
-#endif
+ .nr_counter_reset = 1,
};
static const struct ds_configuration ds_cfg_pentium_m = {
.name = "Pentium M",
.ctl[dsf_bts] = (1 << 6) | (1 << 7),
-
- .sizeof_field = sizeof(long),
- .sizeof_rec[ds_bts] = sizeof(long) * 3,
-#ifdef __i386__
- .sizeof_rec[ds_pebs] = sizeof(long) * 10,
-#else
- .sizeof_rec[ds_pebs] = sizeof(long) * 18,
-#endif
+ .nr_counter_reset = 1,
};
static const struct ds_configuration ds_cfg_core2_atom = {
.name = "Core 2/Atom",
.ctl[dsf_bts] = (1 << 6) | (1 << 7),
.ctl[dsf_bts_kernel] = (1 << 9),
.ctl[dsf_bts_user] = (1 << 10),
-
- .sizeof_field = 8,
- .sizeof_rec[ds_bts] = 8 * 3,
- .sizeof_rec[ds_pebs] = 8 * 18,
+ .nr_counter_reset = 1,
+};
+static const struct ds_configuration ds_cfg_core_i7 = {
+ .name = "Core i7",
+ .ctl[dsf_bts] = (1 << 6) | (1 << 7),
+ .ctl[dsf_bts_kernel] = (1 << 9),
+ .ctl[dsf_bts_user] = (1 << 10),
+ .nr_counter_reset = 4,
};
static void
-ds_configure(const struct ds_configuration *cfg)
+ds_configure(const struct ds_configuration *cfg,
+ struct cpuinfo_x86 *cpu)
{
+ unsigned long nr_pebs_fields = 0;
+
+ printk(KERN_INFO "[ds] using %s configuration\n", cfg->name);
+
+#ifdef __i386__
+ nr_pebs_fields = 10;
+#else
+ nr_pebs_fields = 18;
+#endif
+
+ /*
+ * Starting with version 2, architectural performance
+ * monitoring supports a format specifier.
+ */
+ if ((cpuid_eax(0xa) & 0xff) > 1) {
+ unsigned long perf_capabilities, format;
+
+ rdmsrl(MSR_IA32_PERF_CAPABILITIES, perf_capabilities);
+
+ format = (perf_capabilities >> 8) & 0xf;
+
+ switch (format) {
+ case 0:
+ nr_pebs_fields = 18;
+ break;
+ case 1:
+ nr_pebs_fields = 22;
+ break;
+ default:
+ printk(KERN_INFO
+ "[ds] unknown PEBS format: %lu\n", format);
+ nr_pebs_fields = 0;
+ break;
+ }
+ }
+
memset(&ds_cfg, 0, sizeof(ds_cfg));
ds_cfg = *cfg;
- printk(KERN_INFO "[ds] using %s configuration\n", ds_cfg.name);
+ ds_cfg.sizeof_ptr_field =
+ (cpu_has(cpu, X86_FEATURE_DTES64) ? 8 : 4);
+
+ ds_cfg.sizeof_rec[ds_bts] = ds_cfg.sizeof_ptr_field * 3;
+ ds_cfg.sizeof_rec[ds_pebs] = ds_cfg.sizeof_ptr_field * nr_pebs_fields;
- if (!cpu_has_bts) {
- ds_cfg.ctl[dsf_bts] = 0;
+ if (!cpu_has(cpu, X86_FEATURE_BTS)) {
+ ds_cfg.sizeof_rec[ds_bts] = 0;
printk(KERN_INFO "[ds] bts not available\n");
}
- if (!cpu_has_pebs)
+ if (!cpu_has(cpu, X86_FEATURE_PEBS)) {
+ ds_cfg.sizeof_rec[ds_pebs] = 0;
printk(KERN_INFO "[ds] pebs not available\n");
+ }
+
+ printk(KERN_INFO "[ds] sizes: address: %u bit, ",
+ 8 * ds_cfg.sizeof_ptr_field);
+ printk("bts/pebs record: %u/%u bytes\n",
+ ds_cfg.sizeof_rec[ds_bts], ds_cfg.sizeof_rec[ds_pebs]);
- WARN_ON_ONCE(MAX_SIZEOF_DS < (12 * ds_cfg.sizeof_field));
+ WARN_ON_ONCE(MAX_PEBS_COUNTERS < ds_cfg.nr_counter_reset);
}
void __cpuinit ds_init_intel(struct cpuinfo_x86 *c)
{
+ /* Only configure the first cpu. Others are identical. */
+ if (ds_cfg.name)
+ return;
+
switch (c->x86) {
case 0x6:
switch (c->x86_model) {
case 0x9:
case 0xd: /* Pentium M */
- ds_configure(&ds_cfg_pentium_m);
+ ds_configure(&ds_cfg_pentium_m, c);
break;
case 0xf:
case 0x17: /* Core2 */
case 0x1c: /* Atom */
- ds_configure(&ds_cfg_core2_atom);
+ ds_configure(&ds_cfg_core2_atom, c);
+ break;
+ case 0x1a: /* Core i7 */
+ ds_configure(&ds_cfg_core_i7, c);
break;
- case 0x1a: /* i7 */
default:
- /* sorry, don't know about them */
+ /* Sorry, don't know about them. */
break;
}
break;
@@ -969,64 +1349,89 @@ void __cpuinit ds_init_intel(struct cpuinfo_x86 *c)
case 0x0:
case 0x1:
case 0x2: /* Netburst */
- ds_configure(&ds_cfg_netburst);
+ ds_configure(&ds_cfg_netburst, c);
break;
default:
- /* sorry, don't know about them */
+ /* Sorry, don't know about them. */
break;
}
break;
default:
- /* sorry, don't know about them */
+ /* Sorry, don't know about them. */
break;
}
}
+static inline void ds_take_timestamp(struct ds_context *context,
+ enum bts_qualifier qualifier,
+ struct task_struct *task)
+{
+ struct bts_tracer *tracer = context->bts_master;
+ struct bts_struct ts;
+
+ /* Prevent compilers from reading the tracer pointer twice. */
+ barrier();
+
+ if (!tracer || !(tracer->flags & BTS_TIMESTAMPS))
+ return;
+
+ memset(&ts, 0, sizeof(ts));
+ ts.qualifier = qualifier;
+ ts.variant.event.clock = trace_clock_global();
+ ts.variant.event.pid = task->pid;
+
+ bts_write(tracer, &ts);
+}
+
/*
* Change the DS configuration from tracing prev to tracing next.
*/
void ds_switch_to(struct task_struct *prev, struct task_struct *next)
{
- struct ds_context *prev_ctx = prev->thread.ds_ctx;
- struct ds_context *next_ctx = next->thread.ds_ctx;
+ struct ds_context *prev_ctx = prev->thread.ds_ctx;
+ struct ds_context *next_ctx = next->thread.ds_ctx;
+ unsigned long debugctlmsr = next->thread.debugctlmsr;
+
+ /* Make sure all data is read before we start. */
+ barrier();
if (prev_ctx) {
update_debugctlmsr(0);
- if (prev_ctx->bts_master &&
- (prev_ctx->bts_master->trace.ds.flags & BTS_TIMESTAMPS)) {
- struct bts_struct ts = {
- .qualifier = bts_task_departs,
- .variant.timestamp.jiffies = jiffies_64,
- .variant.timestamp.pid = prev->pid
- };
- bts_write(prev_ctx->bts_master, &ts);
- }
+ ds_take_timestamp(prev_ctx, bts_task_departs, prev);
}
if (next_ctx) {
- if (next_ctx->bts_master &&
- (next_ctx->bts_master->trace.ds.flags & BTS_TIMESTAMPS)) {
- struct bts_struct ts = {
- .qualifier = bts_task_arrives,
- .variant.timestamp.jiffies = jiffies_64,
- .variant.timestamp.pid = next->pid
- };
- bts_write(next_ctx->bts_master, &ts);
- }
+ ds_take_timestamp(next_ctx, bts_task_arrives, next);
wrmsrl(MSR_IA32_DS_AREA, (unsigned long)next_ctx->ds);
}
- update_debugctlmsr(next->thread.debugctlmsr);
+ update_debugctlmsr(debugctlmsr);
}
-void ds_copy_thread(struct task_struct *tsk, struct task_struct *father)
+static __init int ds_selftest(void)
{
- clear_tsk_thread_flag(tsk, TIF_DS_AREA_MSR);
- tsk->thread.ds_ctx = NULL;
-}
+ if (ds_cfg.sizeof_rec[ds_bts]) {
+ int error;
-void ds_exit_thread(struct task_struct *tsk)
-{
+ error = ds_selftest_bts();
+ if (error) {
+ WARN(1, "[ds] selftest failed. disabling bts.\n");
+ ds_cfg.sizeof_rec[ds_bts] = 0;
+ }
+ }
+
+ if (ds_cfg.sizeof_rec[ds_pebs]) {
+ int error;
+
+ error = ds_selftest_pebs();
+ if (error) {
+ WARN(1, "[ds] selftest failed. disabling pebs.\n");
+ ds_cfg.sizeof_rec[ds_pebs] = 0;
+ }
+ }
+
+ return 0;
}
+device_initcall(ds_selftest);
diff --git a/arch/x86/kernel/ds_selftest.c b/arch/x86/kernel/ds_selftest.c
new file mode 100644
index 000000000000..6bc7c199ab99
--- /dev/null
+++ b/arch/x86/kernel/ds_selftest.c
@@ -0,0 +1,408 @@
+/*
+ * Debug Store support - selftest
+ *
+ *
+ * Copyright (C) 2009 Intel Corporation.
+ * Markus Metzger <markus.t.metzger@intel.com>, 2009
+ */
+
+#include "ds_selftest.h"
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/smp.h>
+#include <linux/cpu.h>
+
+#include <asm/ds.h>
+
+
+#define BUFFER_SIZE 521 /* Intentionally chose an odd size. */
+#define SMALL_BUFFER_SIZE 24 /* A single bts entry. */
+
+struct ds_selftest_bts_conf {
+ struct bts_tracer *tracer;
+ int error;
+ int (*suspend)(struct bts_tracer *);
+ int (*resume)(struct bts_tracer *);
+};
+
+static int ds_selftest_bts_consistency(const struct bts_trace *trace)
+{
+ int error = 0;
+
+ if (!trace) {
+ printk(KERN_CONT "failed to access trace...");
+ /* Bail out. Other tests are pointless. */
+ return -1;
+ }
+
+ if (!trace->read) {
+ printk(KERN_CONT "bts read not available...");
+ error = -1;
+ }
+
+ /* Do some sanity checks on the trace configuration. */
+ if (!trace->ds.n) {
+ printk(KERN_CONT "empty bts buffer...");
+ error = -1;
+ }
+ if (!trace->ds.size) {
+ printk(KERN_CONT "bad bts trace setup...");
+ error = -1;
+ }
+ if (trace->ds.end !=
+ (char *)trace->ds.begin + (trace->ds.n * trace->ds.size)) {
+ printk(KERN_CONT "bad bts buffer setup...");
+ error = -1;
+ }
+ /*
+ * We allow top in [begin; end], since its not clear when the
+ * overflow adjustment happens: after the increment or before the
+ * write.
+ */
+ if ((trace->ds.top < trace->ds.begin) ||
+ (trace->ds.end < trace->ds.top)) {
+ printk(KERN_CONT "bts top out of bounds...");
+ error = -1;
+ }
+
+ return error;
+}
+
+static int ds_selftest_bts_read(struct bts_tracer *tracer,
+ const struct bts_trace *trace,
+ const void *from, const void *to)
+{
+ const unsigned char *at;
+
+ /*
+ * Check a few things which do not belong to this test.
+ * They should be covered by other tests.
+ */
+ if (!trace)
+ return -1;
+
+ if (!trace->read)
+ return -1;
+
+ if (to < from)
+ return -1;
+
+ if (from < trace->ds.begin)
+ return -1;
+
+ if (trace->ds.end < to)
+ return -1;
+
+ if (!trace->ds.size)
+ return -1;
+
+ /* Now to the test itself. */
+ for (at = from; (void *)at < to; at += trace->ds.size) {
+ struct bts_struct bts;
+ unsigned long index;
+ int error;
+
+ if (((void *)at - trace->ds.begin) % trace->ds.size) {
+ printk(KERN_CONT
+ "read from non-integer index...");
+ return -1;
+ }
+ index = ((void *)at - trace->ds.begin) / trace->ds.size;
+
+ memset(&bts, 0, sizeof(bts));
+ error = trace->read(tracer, at, &bts);
+ if (error < 0) {
+ printk(KERN_CONT
+ "error reading bts trace at [%lu] (0x%p)...",
+ index, at);
+ return error;
+ }
+
+ switch (bts.qualifier) {
+ case BTS_BRANCH:
+ break;
+ default:
+ printk(KERN_CONT
+ "unexpected bts entry %llu at [%lu] (0x%p)...",
+ bts.qualifier, index, at);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static void ds_selftest_bts_cpu(void *arg)
+{
+ struct ds_selftest_bts_conf *conf = arg;
+ const struct bts_trace *trace;
+ void *top;
+
+ if (IS_ERR(conf->tracer)) {
+ conf->error = PTR_ERR(conf->tracer);
+ conf->tracer = NULL;
+
+ printk(KERN_CONT
+ "initialization failed (err: %d)...", conf->error);
+ return;
+ }
+
+ /* We should meanwhile have enough trace. */
+ conf->error = conf->suspend(conf->tracer);
+ if (conf->error < 0)
+ return;
+
+ /* Let's see if we can access the trace. */
+ trace = ds_read_bts(conf->tracer);
+
+ conf->error = ds_selftest_bts_consistency(trace);
+ if (conf->error < 0)
+ return;
+
+ /* If everything went well, we should have a few trace entries. */
+ if (trace->ds.top == trace->ds.begin) {
+ /*
+ * It is possible but highly unlikely that we got a
+ * buffer overflow and end up at exactly the same
+ * position we started from.
+ * Let's issue a warning, but continue.
+ */
+ printk(KERN_CONT "no trace/overflow...");
+ }
+
+ /* Let's try to read the trace we collected. */
+ conf->error =
+ ds_selftest_bts_read(conf->tracer, trace,
+ trace->ds.begin, trace->ds.top);
+ if (conf->error < 0)
+ return;
+
+ /*
+ * Let's read the trace again.
+ * Since we suspended tracing, we should get the same result.
+ */
+ top = trace->ds.top;
+
+ trace = ds_read_bts(conf->tracer);
+ conf->error = ds_selftest_bts_consistency(trace);
+ if (conf->error < 0)
+ return;
+
+ if (top != trace->ds.top) {
+ printk(KERN_CONT "suspend not working...");
+ conf->error = -1;
+ return;
+ }
+
+ /* Let's collect some more trace - see if resume is working. */
+ conf->error = conf->resume(conf->tracer);
+ if (conf->error < 0)
+ return;
+
+ conf->error = conf->suspend(conf->tracer);
+ if (conf->error < 0)
+ return;
+
+ trace = ds_read_bts(conf->tracer);
+
+ conf->error = ds_selftest_bts_consistency(trace);
+ if (conf->error < 0)
+ return;
+
+ if (trace->ds.top == top) {
+ /*
+ * It is possible but highly unlikely that we got a
+ * buffer overflow and end up at exactly the same
+ * position we started from.
+ * Let's issue a warning and check the full trace.
+ */
+ printk(KERN_CONT
+ "no resume progress/overflow...");
+
+ conf->error =
+ ds_selftest_bts_read(conf->tracer, trace,
+ trace->ds.begin, trace->ds.end);
+ } else if (trace->ds.top < top) {
+ /*
+ * We had a buffer overflow - the entire buffer should
+ * contain trace records.
+ */
+ conf->error =
+ ds_selftest_bts_read(conf->tracer, trace,
+ trace->ds.begin, trace->ds.end);
+ } else {
+ /*
+ * It is quite likely that the buffer did not overflow.
+ * Let's just check the delta trace.
+ */
+ conf->error =
+ ds_selftest_bts_read(conf->tracer, trace, top,
+ trace->ds.top);
+ }
+ if (conf->error < 0)
+ return;
+
+ conf->error = 0;
+}
+
+static int ds_suspend_bts_wrap(struct bts_tracer *tracer)
+{
+ ds_suspend_bts(tracer);
+ return 0;
+}
+
+static int ds_resume_bts_wrap(struct bts_tracer *tracer)
+{
+ ds_resume_bts(tracer);
+ return 0;
+}
+
+static void ds_release_bts_noirq_wrap(void *tracer)
+{
+ (void)ds_release_bts_noirq(tracer);
+}
+
+static int ds_selftest_bts_bad_release_noirq(int cpu,
+ struct bts_tracer *tracer)
+{
+ int error = -EPERM;
+
+ /* Try to release the tracer on the wrong cpu. */
+ get_cpu();
+ if (cpu != smp_processor_id()) {
+ error = ds_release_bts_noirq(tracer);
+ if (error != -EPERM)
+ printk(KERN_CONT "release on wrong cpu...");
+ }
+ put_cpu();
+
+ return error ? 0 : -1;
+}
+
+static int ds_selftest_bts_bad_request_cpu(int cpu, void *buffer)
+{
+ struct bts_tracer *tracer;
+ int error;
+
+ /* Try to request cpu tracing while task tracing is active. */
+ tracer = ds_request_bts_cpu(cpu, buffer, BUFFER_SIZE, NULL,
+ (size_t)-1, BTS_KERNEL);
+ error = PTR_ERR(tracer);
+ if (!IS_ERR(tracer)) {
+ ds_release_bts(tracer);
+ error = 0;
+ }
+
+ if (error != -EPERM)
+ printk(KERN_CONT "cpu/task tracing overlap...");
+
+ return error ? 0 : -1;
+}
+
+static int ds_selftest_bts_bad_request_task(void *buffer)
+{
+ struct bts_tracer *tracer;
+ int error;
+
+ /* Try to request cpu tracing while task tracing is active. */
+ tracer = ds_request_bts_task(current, buffer, BUFFER_SIZE, NULL,
+ (size_t)-1, BTS_KERNEL);
+ error = PTR_ERR(tracer);
+ if (!IS_ERR(tracer)) {
+ error = 0;
+ ds_release_bts(tracer);
+ }
+
+ if (error != -EPERM)
+ printk(KERN_CONT "task/cpu tracing overlap...");
+
+ return error ? 0 : -1;
+}
+
+int ds_selftest_bts(void)
+{
+ struct ds_selftest_bts_conf conf;
+ unsigned char buffer[BUFFER_SIZE], *small_buffer;
+ unsigned long irq;
+ int cpu;
+
+ printk(KERN_INFO "[ds] bts selftest...");
+ conf.error = 0;
+
+ small_buffer = (unsigned char *)ALIGN((unsigned long)buffer, 8) + 8;
+
+ get_online_cpus();
+ for_each_online_cpu(cpu) {
+ conf.suspend = ds_suspend_bts_wrap;
+ conf.resume = ds_resume_bts_wrap;
+ conf.tracer =
+ ds_request_bts_cpu(cpu, buffer, BUFFER_SIZE,
+ NULL, (size_t)-1, BTS_KERNEL);
+ ds_selftest_bts_cpu(&conf);
+ if (conf.error >= 0)
+ conf.error = ds_selftest_bts_bad_request_task(buffer);
+ ds_release_bts(conf.tracer);
+ if (conf.error < 0)
+ goto out;
+
+ conf.suspend = ds_suspend_bts_noirq;
+ conf.resume = ds_resume_bts_noirq;
+ conf.tracer =
+ ds_request_bts_cpu(cpu, buffer, BUFFER_SIZE,
+ NULL, (size_t)-1, BTS_KERNEL);
+ smp_call_function_single(cpu, ds_selftest_bts_cpu, &conf, 1);
+ if (conf.error >= 0) {
+ conf.error =
+ ds_selftest_bts_bad_release_noirq(cpu,
+ conf.tracer);
+ /* We must not release the tracer twice. */
+ if (conf.error < 0)
+ conf.tracer = NULL;
+ }
+ if (conf.error >= 0)
+ conf.error = ds_selftest_bts_bad_request_task(buffer);
+ smp_call_function_single(cpu, ds_release_bts_noirq_wrap,
+ conf.tracer, 1);
+ if (conf.error < 0)
+ goto out;
+ }
+
+ conf.suspend = ds_suspend_bts_wrap;
+ conf.resume = ds_resume_bts_wrap;
+ conf.tracer =
+ ds_request_bts_task(current, buffer, BUFFER_SIZE,
+ NULL, (size_t)-1, BTS_KERNEL);
+ ds_selftest_bts_cpu(&conf);
+ if (conf.error >= 0)
+ conf.error = ds_selftest_bts_bad_request_cpu(0, buffer);
+ ds_release_bts(conf.tracer);
+ if (conf.error < 0)
+ goto out;
+
+ conf.suspend = ds_suspend_bts_noirq;
+ conf.resume = ds_resume_bts_noirq;
+ conf.tracer =
+ ds_request_bts_task(current, small_buffer, SMALL_BUFFER_SIZE,
+ NULL, (size_t)-1, BTS_KERNEL);
+ local_irq_save(irq);
+ ds_selftest_bts_cpu(&conf);
+ if (conf.error >= 0)
+ conf.error = ds_selftest_bts_bad_request_cpu(0, buffer);
+ ds_release_bts_noirq(conf.tracer);
+ local_irq_restore(irq);
+ if (conf.error < 0)
+ goto out;
+
+ conf.error = 0;
+ out:
+ put_online_cpus();
+ printk(KERN_CONT "%s.\n", (conf.error ? "failed" : "passed"));
+
+ return conf.error;
+}
+
+int ds_selftest_pebs(void)
+{
+ return 0;
+}
diff --git a/arch/x86/kernel/ds_selftest.h b/arch/x86/kernel/ds_selftest.h
new file mode 100644
index 000000000000..2ba8745c6663
--- /dev/null
+++ b/arch/x86/kernel/ds_selftest.h
@@ -0,0 +1,15 @@
+/*
+ * Debug Store support - selftest
+ *
+ *
+ * Copyright (C) 2009 Intel Corporation.
+ * Markus Metzger <markus.t.metzger@intel.com>, 2009
+ */
+
+#ifdef CONFIG_X86_DS_SELFTEST
+extern int ds_selftest_bts(void);
+extern int ds_selftest_pebs(void);
+#else
+static inline int ds_selftest_bts(void) { return 0; }
+static inline int ds_selftest_pebs(void) { return 0; }
+#endif
diff --git a/arch/x86/kernel/dumpstack.h b/arch/x86/kernel/dumpstack.h
index da87590b8698..81086c227ab7 100644
--- a/arch/x86/kernel/dumpstack.h
+++ b/arch/x86/kernel/dumpstack.h
@@ -29,7 +29,6 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
unsigned long *sp, unsigned long bp, char *log_lvl);
extern unsigned int code_bytes;
-extern int kstack_depth_to_print;
/* The form of the top of the frame on the stack */
struct stack_frame {
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index ef2c3563357d..006281302925 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -1074,12 +1074,13 @@ u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align)
u64 addr;
u64 start;
- start = startt;
- while (size < sizet && (start + 1))
+ for (start = startt; ; start += size) {
start = find_e820_area_size(start, &size, align);
-
- if (size < sizet)
- return 0;
+ if (!(start + 1))
+ return 0;
+ if (size >= sizet)
+ break;
+ }
#ifdef CONFIG_X86_32
if (start >= MAXMEM)
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c
index 76b8cd953dee..ebdb85cf2686 100644
--- a/arch/x86/kernel/early-quirks.c
+++ b/arch/x86/kernel/early-quirks.c
@@ -97,6 +97,7 @@ static void __init nvidia_bugs(int num, int slot, int func)
}
#if defined(CONFIG_ACPI) && defined(CONFIG_X86_IO_APIC)
+#if defined(CONFIG_ACPI) && defined(CONFIG_X86_IO_APIC)
static u32 __init ati_ixp4x0_rev(int num, int slot, int func)
{
u32 d;
@@ -114,6 +115,7 @@ static u32 __init ati_ixp4x0_rev(int num, int slot, int func)
d &= 0xff;
return d;
}
+#endif
static void __init ati_bugs(int num, int slot, int func)
{
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index a331ec38af9e..987f91f0f755 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -147,27 +147,14 @@ END(ftrace_graph_caller)
GLOBAL(return_to_handler)
subq $80, %rsp
+ /* Save the return values */
movq %rax, (%rsp)
- movq %rcx, 8(%rsp)
- movq %rdx, 16(%rsp)
- movq %rsi, 24(%rsp)
- movq %rdi, 32(%rsp)
- movq %r8, 40(%rsp)
- movq %r9, 48(%rsp)
- movq %r10, 56(%rsp)
- movq %r11, 64(%rsp)
+ movq %rdx, 8(%rsp)
call ftrace_return_to_handler
movq %rax, 72(%rsp)
- movq 64(%rsp), %r11
- movq 56(%rsp), %r10
- movq 48(%rsp), %r9
- movq 40(%rsp), %r8
- movq 32(%rsp), %rdi
- movq 24(%rsp), %rsi
- movq 16(%rsp), %rdx
- movq 8(%rsp), %rcx
+ movq 8(%rsp), %rdx
movq (%rsp), %rax
addq $72, %rsp
retq
@@ -1410,7 +1397,10 @@ ENTRY(paranoid_exit)
paranoid_swapgs:
TRACE_IRQS_IRETQ 0
SWAPGS_UNSAFE_STACK
+ RESTORE_ALL 8
+ jmp irq_return
paranoid_restore:
+ TRACE_IRQS_IRETQ 0
RESTORE_ALL 8
jmp irq_return
paranoid_userspace:
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 30683883e0cd..dc5ed4bdd88d 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -608,13 +608,6 @@ ignore_int:
ENTRY(initial_code)
.long i386_start_kernel
-.section .text
-/*
- * Real beginning of normal "text" segment
- */
-ENTRY(stext)
-ENTRY(_stext)
-
/*
* BSS section
*/
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 648b3a2a3a44..81408b93f887 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -236,6 +236,10 @@ static void hpet_stop_counter(void)
unsigned long cfg = hpet_readl(HPET_CFG);
cfg &= ~HPET_CFG_ENABLE;
hpet_writel(cfg, HPET_CFG);
+}
+
+static void hpet_reset_counter(void)
+{
hpet_writel(0, HPET_COUNTER);
hpet_writel(0, HPET_COUNTER + 4);
}
@@ -250,6 +254,7 @@ static void hpet_start_counter(void)
static void hpet_restart_counter(void)
{
hpet_stop_counter();
+ hpet_reset_counter();
hpet_start_counter();
}
@@ -309,7 +314,7 @@ static int hpet_setup_msi_irq(unsigned int irq);
static void hpet_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt, int timer)
{
- unsigned long cfg;
+ unsigned long cfg, cmp, now;
uint64_t delta;
switch (mode) {
@@ -317,12 +322,23 @@ static void hpet_set_mode(enum clock_event_mode mode,
hpet_stop_counter();
delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * evt->mult;
delta >>= evt->shift;
+ now = hpet_readl(HPET_COUNTER);
+ cmp = now + (unsigned long) delta;
cfg = hpet_readl(HPET_Tn_CFG(timer));
/* Make sure we use edge triggered interrupts */
cfg &= ~HPET_TN_LEVEL;
cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
HPET_TN_SETVAL | HPET_TN_32BIT;
hpet_writel(cfg, HPET_Tn_CFG(timer));
+ hpet_writel(cmp, HPET_Tn_CMP(timer));
+ udelay(1);
+ /*
+ * HPET on AMD 81xx needs a second write (with HPET_TN_SETVAL
+ * cleared) to T0_CMP to set the period. The HPET_TN_SETVAL
+ * bit is automatically cleared after the first write.
+ * (See AMD-8111 HyperTransport I/O Hub Data Sheet,
+ * Publication # 24674)
+ */
hpet_writel((unsigned long) delta, HPET_Tn_CMP(timer));
hpet_start_counter();
hpet_print_config();
@@ -722,7 +738,7 @@ static int hpet_cpuhp_notify(struct notifier_block *n,
/*
* Clock source related code
*/
-static cycle_t read_hpet(void)
+static cycle_t read_hpet(struct clocksource *cs)
{
return (cycle_t)hpet_readl(HPET_COUNTER);
}
@@ -756,7 +772,7 @@ static int hpet_clocksource_register(void)
hpet_restart_counter();
/* Verify whether hpet counter works */
- t1 = read_hpet();
+ t1 = hpet_readl(HPET_COUNTER);
rdtscll(start);
/*
@@ -770,7 +786,7 @@ static int hpet_clocksource_register(void)
rdtscll(now);
} while ((now - start) < 200000UL);
- if (t1 == read_hpet()) {
+ if (t1 == hpet_readl(HPET_COUNTER)) {
printk(KERN_WARNING
"HPET counter not counting. HPET disabled\n");
return -ENODEV;
diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c
index 3475440baa54..c2e0bb0890d4 100644
--- a/arch/x86/kernel/i8253.c
+++ b/arch/x86/kernel/i8253.c
@@ -129,7 +129,7 @@ void __init setup_pit_timer(void)
* to just read by itself. So use jiffies to emulate a free
* running counter:
*/
-static cycle_t pit_read(void)
+static cycle_t pit_read(struct clocksource *cs)
{
static int old_count;
static u32 old_jifs;
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index c3fe010d74c8..9a391bbb8ba8 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -12,6 +12,7 @@
#include <asm/io_apic.h>
#include <asm/irq.h>
#include <asm/idle.h>
+#include <asm/hw_irq.h>
atomic_t irq_err_count;
@@ -24,9 +25,9 @@ void (*generic_interrupt_extension)(void) = NULL;
*/
void ack_bad_irq(unsigned int irq)
{
- printk(KERN_ERR "unexpected IRQ trap at vector %02x\n", irq);
+ if (printk_ratelimit())
+ pr_err("unexpected IRQ trap at vector %02x\n", irq);
-#ifdef CONFIG_X86_LOCAL_APIC
/*
* Currently unexpected vectors happen only on SMP and APIC.
* We _must_ ack these because every local APIC has only N
@@ -36,9 +37,7 @@ void ack_bad_irq(unsigned int irq)
* completely.
* But only ack when the APIC is enabled -AK
*/
- if (cpu_has_apic)
- ack_APIC_irq();
-#endif
+ ack_APIC_irq();
}
#define irq_stats(x) (&per_cpu(irq_stat, x))
@@ -178,7 +177,7 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
sum += irq_stats(cpu)->irq_thermal_count;
# ifdef CONFIG_X86_64
sum += irq_stats(cpu)->irq_threshold_count;
-#endif
+# endif
#endif
return sum;
}
@@ -213,14 +212,11 @@ unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
irq = __get_cpu_var(vector_irq)[vector];
if (!handle_irq(irq, regs)) {
-#ifdef CONFIG_X86_64
- if (!disable_apic)
- ack_APIC_irq();
-#endif
+ ack_APIC_irq();
if (printk_ratelimit())
- printk(KERN_EMERG "%s: %d.%d No irq handler for vector (irq %d)\n",
- __func__, smp_processor_id(), vector, irq);
+ pr_emerg("%s: %d.%d No irq handler for vector (irq %d)\n",
+ __func__, smp_processor_id(), vector, irq);
}
irq_exit();
diff --git a/arch/x86/kernel/irqinit_32.c b/arch/x86/kernel/irqinit.c
index 368b0a8836f9..2e08b10ad51a 100644
--- a/arch/x86/kernel/irqinit_32.c
+++ b/arch/x86/kernel/irqinit.c
@@ -1,20 +1,25 @@
+#include <linux/linkage.h>
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
+#include <linux/timex.h>
#include <linux/slab.h>
#include <linux/random.h>
+#include <linux/kprobes.h>
#include <linux/init.h>
#include <linux/kernel_stat.h>
#include <linux/sysdev.h>
#include <linux/bitops.h>
+#include <linux/acpi.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <asm/atomic.h>
#include <asm/system.h>
#include <asm/timer.h>
+#include <asm/hw_irq.h>
#include <asm/pgtable.h>
#include <asm/desc.h>
#include <asm/apic.h>
@@ -22,7 +27,23 @@
#include <asm/i8259.h>
#include <asm/traps.h>
+/*
+ * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
+ * (these are usually mapped to vectors 0x30-0x3f)
+ */
+
+/*
+ * The IO-APIC gives us many more interrupt sources. Most of these
+ * are unused but an SMP system is supposed to have enough memory ...
+ * sometimes (mostly wrt. hw bugs) we get corrupted vectors all
+ * across the spectrum, so we really want to be prepared to get all
+ * of these. Plus, more powerful systems might have more than 64
+ * IO-APIC registers.
+ *
+ * (these are usually mapped into the 0x30-0xff vector range)
+ */
+#ifdef CONFIG_X86_32
/*
* Note that on a 486, we don't want to do a SIGFPE on an irq13
* as the irq is unreliable, and exception 16 works correctly
@@ -52,30 +73,7 @@ static struct irqaction fpu_irq = {
.handler = math_error_irq,
.name = "fpu",
};
-
-void __init init_ISA_irqs(void)
-{
- int i;
-
-#ifdef CONFIG_X86_LOCAL_APIC
- init_bsp_APIC();
#endif
- init_8259A(0);
-
- /*
- * 16 old-style INTA-cycle interrupts:
- */
- for (i = 0; i < NR_IRQS_LEGACY; i++) {
- struct irq_desc *desc = irq_to_desc(i);
-
- desc->status = IRQ_DISABLED;
- desc->action = NULL;
- desc->depth = 1;
-
- set_irq_chip_and_handler_name(i, &i8259A_chip,
- handle_level_irq, "XT");
- }
-}
/*
* IRQ2 is cascade interrupt to second interrupt controller
@@ -118,29 +116,37 @@ int vector_used_by_percpu_irq(unsigned int vector)
return 0;
}
-/* Overridden in paravirt.c */
-void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ")));
-
-void __init native_init_IRQ(void)
+static void __init init_ISA_irqs(void)
{
int i;
- /* Execute any quirks before the call gates are initialised: */
- x86_quirk_pre_intr_init();
+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
+ init_bsp_APIC();
+#endif
+ init_8259A(0);
/*
- * Cover the whole vector space, no vector can escape
- * us. (some of these will be overridden and become
- * 'special' SMP interrupts)
+ * 16 old-style INTA-cycle interrupts:
*/
- for (i = FIRST_EXTERNAL_VECTOR; i < NR_VECTORS; i++) {
- /* SYSCALL_VECTOR was reserved in trap_init. */
- if (i != SYSCALL_VECTOR)
- set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]);
+ for (i = 0; i < NR_IRQS_LEGACY; i++) {
+ struct irq_desc *desc = irq_to_desc(i);
+
+ desc->status = IRQ_DISABLED;
+ desc->action = NULL;
+ desc->depth = 1;
+
+ set_irq_chip_and_handler_name(i, &i8259A_chip,
+ handle_level_irq, "XT");
}
+}
+/* Overridden in paravirt.c */
+void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ")));
-#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_SMP)
+static void __init smp_intr_init(void)
+{
+#ifdef CONFIG_SMP
+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
/*
* The reschedule interrupt is a CPU-to-CPU reschedule-helper
* IPI, driven by wakeup.
@@ -160,16 +166,27 @@ void __init native_init_IRQ(void)
/* IPI for generic function call */
alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
- /* IPI for single call function */
+ /* IPI for generic single function call */
alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR,
- call_function_single_interrupt);
+ call_function_single_interrupt);
/* Low priority IPI to cleanup after moving an irq */
set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors);
#endif
+#endif /* CONFIG_SMP */
+}
+
+static void __init apic_intr_init(void)
+{
+ smp_intr_init();
+
+#ifdef CONFIG_X86_64
+ alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
+ alloc_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt);
+#endif
-#ifdef CONFIG_X86_LOCAL_APIC
+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
/* self generated IPI for local APIC timer */
alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
@@ -179,16 +196,67 @@ void __init native_init_IRQ(void)
/* IPI vectors for APIC spurious and error interrupts */
alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
+
+ /* Performance monitoring interrupts: */
+# ifdef CONFIG_PERF_COUNTERS
+ alloc_intr_gate(LOCAL_PERF_VECTOR, perf_counter_interrupt);
+ alloc_intr_gate(LOCAL_PENDING_VECTOR, perf_pending_interrupt);
+# endif
+
#endif
+#ifdef CONFIG_X86_32
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_MCE_P4THERMAL)
/* thermal monitor LVT interrupt */
alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
#endif
+#endif
+}
+
+/**
+ * x86_quirk_pre_intr_init - initialisation prior to setting up interrupt vectors
+ *
+ * Description:
+ * Perform any necessary interrupt initialisation prior to setting up
+ * the "ordinary" interrupt call gates. For legacy reasons, the ISA
+ * interrupts should be initialised here if the machine emulates a PC
+ * in any way.
+ **/
+static void __init x86_quirk_pre_intr_init(void)
+{
+#ifdef CONFIG_X86_32
+ if (x86_quirks->arch_pre_intr_init) {
+ if (x86_quirks->arch_pre_intr_init())
+ return;
+ }
+#endif
+ init_ISA_irqs();
+}
+
+void __init native_init_IRQ(void)
+{
+ int i;
+
+ /* Execute any quirks before the call gates are initialised: */
+ x86_quirk_pre_intr_init();
+
+ apic_intr_init();
+
+ /*
+ * Cover the whole vector space, no vector can escape
+ * us. (some of these will be overridden and become
+ * 'special' SMP interrupts)
+ */
+ for (i = FIRST_EXTERNAL_VECTOR; i < NR_VECTORS; i++) {
+ /* IA32_SYSCALL_VECTOR could be used in trap_init already. */
+ if (!test_bit(i, used_vectors))
+ set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]);
+ }
if (!acpi_ioapic)
setup_irq(2, &irq2);
+#ifdef CONFIG_X86_32
/*
* Call quirks after call gates are initialised (usually add in
* the architecture specific gates):
@@ -203,4 +271,5 @@ void __init native_init_IRQ(void)
setup_irq(FPU_IRQ, &fpu_irq);
irq_ctx_init(smp_processor_id());
+#endif
}
diff --git a/arch/x86/kernel/irqinit_64.c b/arch/x86/kernel/irqinit_64.c
deleted file mode 100644
index 8cd10537fd46..000000000000
--- a/arch/x86/kernel/irqinit_64.c
+++ /dev/null
@@ -1,177 +0,0 @@
-#include <linux/linkage.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/sysdev.h>
-#include <linux/bitops.h>
-#include <linux/acpi.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-
-#include <asm/atomic.h>
-#include <asm/system.h>
-#include <asm/hw_irq.h>
-#include <asm/pgtable.h>
-#include <asm/desc.h>
-#include <asm/apic.h>
-#include <asm/i8259.h>
-
-/*
- * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
- * (these are usually mapped to vectors 0x30-0x3f)
- */
-
-/*
- * The IO-APIC gives us many more interrupt sources. Most of these
- * are unused but an SMP system is supposed to have enough memory ...
- * sometimes (mostly wrt. hw bugs) we get corrupted vectors all
- * across the spectrum, so we really want to be prepared to get all
- * of these. Plus, more powerful systems might have more than 64
- * IO-APIC registers.
- *
- * (these are usually mapped into the 0x30-0xff vector range)
- */
-
-/*
- * IRQ2 is cascade interrupt to second interrupt controller
- */
-
-static struct irqaction irq2 = {
- .handler = no_action,
- .name = "cascade",
-};
-DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
- [0 ... IRQ0_VECTOR - 1] = -1,
- [IRQ0_VECTOR] = 0,
- [IRQ1_VECTOR] = 1,
- [IRQ2_VECTOR] = 2,
- [IRQ3_VECTOR] = 3,
- [IRQ4_VECTOR] = 4,
- [IRQ5_VECTOR] = 5,
- [IRQ6_VECTOR] = 6,
- [IRQ7_VECTOR] = 7,
- [IRQ8_VECTOR] = 8,
- [IRQ9_VECTOR] = 9,
- [IRQ10_VECTOR] = 10,
- [IRQ11_VECTOR] = 11,
- [IRQ12_VECTOR] = 12,
- [IRQ13_VECTOR] = 13,
- [IRQ14_VECTOR] = 14,
- [IRQ15_VECTOR] = 15,
- [IRQ15_VECTOR + 1 ... NR_VECTORS - 1] = -1
-};
-
-int vector_used_by_percpu_irq(unsigned int vector)
-{
- int cpu;
-
- for_each_online_cpu(cpu) {
- if (per_cpu(vector_irq, cpu)[vector] != -1)
- return 1;
- }
-
- return 0;
-}
-
-static void __init init_ISA_irqs(void)
-{
- int i;
-
- init_bsp_APIC();
- init_8259A(0);
-
- for (i = 0; i < NR_IRQS_LEGACY; i++) {
- struct irq_desc *desc = irq_to_desc(i);
-
- desc->status = IRQ_DISABLED;
- desc->action = NULL;
- desc->depth = 1;
-
- /*
- * 16 old-style INTA-cycle interrupts:
- */
- set_irq_chip_and_handler_name(i, &i8259A_chip,
- handle_level_irq, "XT");
- }
-}
-
-void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ")));
-
-static void __init smp_intr_init(void)
-{
-#ifdef CONFIG_SMP
- /*
- * The reschedule interrupt is a CPU-to-CPU reschedule-helper
- * IPI, driven by wakeup.
- */
- alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
-
- /* IPIs for invalidation */
- alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+0, invalidate_interrupt0);
- alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+1, invalidate_interrupt1);
- alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+2, invalidate_interrupt2);
- alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+3, invalidate_interrupt3);
- alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+4, invalidate_interrupt4);
- alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+5, invalidate_interrupt5);
- alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+6, invalidate_interrupt6);
- alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+7, invalidate_interrupt7);
-
- /* IPI for generic function call */
- alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
-
- /* IPI for generic single function call */
- alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR,
- call_function_single_interrupt);
-
- /* Low priority IPI to cleanup after moving an irq */
- set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
- set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors);
-#endif
-}
-
-static void __init apic_intr_init(void)
-{
- smp_intr_init();
-
- alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
- alloc_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt);
-
- /* self generated IPI for local APIC timer */
- alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
-
- /* generic IPI for platform specific use */
- alloc_intr_gate(GENERIC_INTERRUPT_VECTOR, generic_interrupt);
-
- /* IPI vectors for APIC spurious and error interrupts */
- alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
- alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
-}
-
-void __init native_init_IRQ(void)
-{
- int i;
-
- init_ISA_irqs();
- /*
- * Cover the whole vector space, no vector can escape
- * us. (some of these will be overridden and become
- * 'special' SMP interrupts)
- */
- for (i = 0; i < (NR_VECTORS - FIRST_EXTERNAL_VECTOR); i++) {
- int vector = FIRST_EXTERNAL_VECTOR + i;
- if (vector != IA32_SYSCALL_VECTOR)
- set_intr_gate(vector, interrupt[i]);
- }
-
- apic_intr_init();
-
- if (!acpi_ioapic)
- setup_irq(2, &irq2);
-}
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index eedfaebe1063..b1f4dffb919e 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -88,6 +88,7 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
gdb_regs[GDB_SS] = __KERNEL_DS;
gdb_regs[GDB_FS] = 0xFFFF;
gdb_regs[GDB_GS] = 0xFFFF;
+ gdb_regs[GDB_SP] = (int)&regs->sp;
#else
gdb_regs[GDB_R8] = regs->r8;
gdb_regs[GDB_R9] = regs->r9;
@@ -100,8 +101,8 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
gdb_regs32[GDB_PS] = regs->flags;
gdb_regs32[GDB_CS] = regs->cs;
gdb_regs32[GDB_SS] = regs->ss;
-#endif
gdb_regs[GDB_SP] = regs->sp;
+#endif
}
/**
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 33019ddb56b4..a78ecad0c900 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -27,6 +27,7 @@
#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/hardirq.h>
+#include <asm/timer.h>
#define MMU_QUEUE_SIZE 1024
@@ -195,7 +196,7 @@ static void kvm_leave_lazy_mmu(void)
struct kvm_para_state *state = kvm_para_state();
mmu_queue_flush(state);
- paravirt_leave_lazy(paravirt_get_lazy_mode());
+ paravirt_leave_lazy_mmu();
state->mode = paravirt_get_lazy_mode();
}
@@ -230,6 +231,9 @@ static void paravirt_ops_setup(void)
pv_mmu_ops.lazy_mode.enter = kvm_enter_lazy_mmu;
pv_mmu_ops.lazy_mode.leave = kvm_leave_lazy_mmu;
}
+#ifdef CONFIG_X86_IO_APIC
+ no_timer_check = 1;
+#endif
}
void __init kvm_guest_init(void)
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
index 137f2e8132df..223af43f1526 100644
--- a/arch/x86/kernel/kvmclock.c
+++ b/arch/x86/kernel/kvmclock.c
@@ -77,6 +77,11 @@ static cycle_t kvm_clock_read(void)
return ret;
}
+static cycle_t kvm_clock_get_cycles(struct clocksource *cs)
+{
+ return kvm_clock_read();
+}
+
/*
* If we don't do that, there is the possibility that the guest
* will calibrate under heavy load - thus, getting a lower lpj -
@@ -107,7 +112,7 @@ static void kvm_get_preset_lpj(void)
static struct clocksource kvm_clock = {
.name = "kvm-clock",
- .read = kvm_clock_read,
+ .read = kvm_clock_get_cycles,
.rating = 400,
.mask = CLOCKSOURCE_MASK(64),
.mult = 1 << KVM_SCALE,
diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c
index e7368c1da01d..c1c429d00130 100644
--- a/arch/x86/kernel/machine_kexec_32.c
+++ b/arch/x86/kernel/machine_kexec_32.c
@@ -194,7 +194,7 @@ void machine_kexec(struct kimage *image)
unsigned int preserve_context);
#ifdef CONFIG_KEXEC_JUMP
- if (kexec_image->preserve_context)
+ if (image->preserve_context)
save_processor_state();
#endif
@@ -253,7 +253,7 @@ void machine_kexec(struct kimage *image)
image->preserve_context);
#ifdef CONFIG_KEXEC_JUMP
- if (kexec_image->preserve_context)
+ if (image->preserve_context)
restore_processor_state();
#endif
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index 89cea4d44679..84c3bf209e98 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -274,7 +274,7 @@ void machine_kexec(struct kimage *image)
int save_ftrace_enabled;
#ifdef CONFIG_KEXEC_JUMP
- if (kexec_image->preserve_context)
+ if (image->preserve_context)
save_processor_state();
#endif
@@ -333,7 +333,7 @@ void machine_kexec(struct kimage *image)
image->preserve_context);
#ifdef CONFIG_KEXEC_JUMP
- if (kexec_image->preserve_context)
+ if (image->preserve_context)
restore_processor_state();
#endif
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c
index a0f3851ef310..98c470c069d1 100644
--- a/arch/x86/kernel/microcode_core.c
+++ b/arch/x86/kernel/microcode_core.c
@@ -108,40 +108,29 @@ struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
EXPORT_SYMBOL_GPL(ucode_cpu_info);
#ifdef CONFIG_MICROCODE_OLD_INTERFACE
-struct update_for_cpu {
- const void __user *buf;
- size_t size;
-};
-
-static long update_for_cpu(void *_ufc)
-{
- struct update_for_cpu *ufc = _ufc;
- int error;
-
- error = microcode_ops->request_microcode_user(smp_processor_id(),
- ufc->buf, ufc->size);
- if (error < 0)
- return error;
- if (!error)
- microcode_ops->apply_microcode(smp_processor_id());
- return error;
-}
-
static int do_microcode_update(const void __user *buf, size_t size)
{
+ cpumask_t old;
int error = 0;
int cpu;
- struct update_for_cpu ufc = { .buf = buf, .size = size };
+
+ old = current->cpus_allowed;
for_each_online_cpu(cpu) {
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
if (!uci->valid)
continue;
- error = work_on_cpu(cpu, update_for_cpu, &ufc);
+
+ set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ error = microcode_ops->request_microcode_user(cpu, buf, size);
if (error < 0)
- break;
+ goto out;
+ if (!error)
+ microcode_ops->apply_microcode(cpu);
}
+out:
+ set_cpus_allowed_ptr(current, &old);
return error;
}
@@ -391,8 +380,6 @@ static int mc_sysdev_add(struct sys_device *sys_dev)
return err;
err = microcode_init_cpu(cpu);
- if (err)
- sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
return err;
}
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index 8e45f4464880..aa3442340705 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -246,18 +246,16 @@ static DEFINE_PER_CPU(enum paravirt_lazy_mode, paravirt_lazy_mode) = PARAVIRT_LA
static inline void enter_lazy(enum paravirt_lazy_mode mode)
{
- BUG_ON(__get_cpu_var(paravirt_lazy_mode) != PARAVIRT_LAZY_NONE);
- BUG_ON(preemptible());
+ BUG_ON(percpu_read(paravirt_lazy_mode) != PARAVIRT_LAZY_NONE);
- __get_cpu_var(paravirt_lazy_mode) = mode;
+ percpu_write(paravirt_lazy_mode, mode);
}
-void paravirt_leave_lazy(enum paravirt_lazy_mode mode)
+static void leave_lazy(enum paravirt_lazy_mode mode)
{
- BUG_ON(__get_cpu_var(paravirt_lazy_mode) != mode);
- BUG_ON(preemptible());
+ BUG_ON(percpu_read(paravirt_lazy_mode) != mode);
- __get_cpu_var(paravirt_lazy_mode) = PARAVIRT_LAZY_NONE;
+ percpu_write(paravirt_lazy_mode, PARAVIRT_LAZY_NONE);
}
void paravirt_enter_lazy_mmu(void)
@@ -267,22 +265,36 @@ void paravirt_enter_lazy_mmu(void)
void paravirt_leave_lazy_mmu(void)
{
- paravirt_leave_lazy(PARAVIRT_LAZY_MMU);
+ leave_lazy(PARAVIRT_LAZY_MMU);
}
-void paravirt_enter_lazy_cpu(void)
+void paravirt_start_context_switch(struct task_struct *prev)
{
+ BUG_ON(preemptible());
+
+ if (percpu_read(paravirt_lazy_mode) == PARAVIRT_LAZY_MMU) {
+ arch_leave_lazy_mmu_mode();
+ set_ti_thread_flag(task_thread_info(prev), TIF_LAZY_MMU_UPDATES);
+ }
enter_lazy(PARAVIRT_LAZY_CPU);
}
-void paravirt_leave_lazy_cpu(void)
+void paravirt_end_context_switch(struct task_struct *next)
{
- paravirt_leave_lazy(PARAVIRT_LAZY_CPU);
+ BUG_ON(preemptible());
+
+ leave_lazy(PARAVIRT_LAZY_CPU);
+
+ if (test_and_clear_ti_thread_flag(task_thread_info(next), TIF_LAZY_MMU_UPDATES))
+ arch_enter_lazy_mmu_mode();
}
enum paravirt_lazy_mode paravirt_get_lazy_mode(void)
{
- return __get_cpu_var(paravirt_lazy_mode);
+ if (in_interrupt())
+ return PARAVIRT_LAZY_NONE;
+
+ return percpu_read(paravirt_lazy_mode);
}
void arch_flush_lazy_mmu_mode(void)
@@ -290,7 +302,6 @@ void arch_flush_lazy_mmu_mode(void)
preempt_disable();
if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) {
- WARN_ON(preempt_count() == 1);
arch_leave_lazy_mmu_mode();
arch_enter_lazy_mmu_mode();
}
@@ -298,19 +309,6 @@ void arch_flush_lazy_mmu_mode(void)
preempt_enable();
}
-void arch_flush_lazy_cpu_mode(void)
-{
- preempt_disable();
-
- if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_CPU) {
- WARN_ON(preempt_count() == 1);
- arch_leave_lazy_cpu_mode();
- arch_enter_lazy_cpu_mode();
- }
-
- preempt_enable();
-}
-
struct pv_info pv_info = {
.name = "bare hardware",
.paravirt_enabled = 0,
@@ -402,10 +400,8 @@ struct pv_cpu_ops pv_cpu_ops = {
.set_iopl_mask = native_set_iopl_mask,
.io_delay = native_io_delay,
- .lazy_mode = {
- .enter = paravirt_nop,
- .leave = paravirt_nop,
- },
+ .start_context_switch = paravirt_nop,
+ .end_context_switch = paravirt_nop,
};
struct pv_apic_ops pv_apic_ops = {
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 755c21e906f3..971a3bec47a8 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -186,37 +186,6 @@ static struct cal_chipset_ops calioc2_chip_ops = {
static struct calgary_bus_info bus_info[MAX_PHB_BUS_NUM] = { { NULL, 0, 0 }, };
-/* enable this to stress test the chip's TCE cache */
-#ifdef CONFIG_IOMMU_DEBUG
-static int debugging = 1;
-
-static inline unsigned long verify_bit_range(unsigned long* bitmap,
- int expected, unsigned long start, unsigned long end)
-{
- unsigned long idx = start;
-
- BUG_ON(start >= end);
-
- while (idx < end) {
- if (!!test_bit(idx, bitmap) != expected)
- return idx;
- ++idx;
- }
-
- /* all bits have the expected value */
- return ~0UL;
-}
-#else /* debugging is disabled */
-static int debugging;
-
-static inline unsigned long verify_bit_range(unsigned long* bitmap,
- int expected, unsigned long start, unsigned long end)
-{
- return ~0UL;
-}
-
-#endif /* CONFIG_IOMMU_DEBUG */
-
static inline int translation_enabled(struct iommu_table *tbl)
{
/* only PHBs with translation enabled have an IOMMU table */
@@ -228,7 +197,6 @@ static void iommu_range_reserve(struct iommu_table *tbl,
{
unsigned long index;
unsigned long end;
- unsigned long badbit;
unsigned long flags;
index = start_addr >> PAGE_SHIFT;
@@ -243,14 +211,6 @@ static void iommu_range_reserve(struct iommu_table *tbl,
spin_lock_irqsave(&tbl->it_lock, flags);
- badbit = verify_bit_range(tbl->it_map, 0, index, end);
- if (badbit != ~0UL) {
- if (printk_ratelimit())
- printk(KERN_ERR "Calgary: entry already allocated at "
- "0x%lx tbl %p dma 0x%lx npages %u\n",
- badbit, tbl, start_addr, npages);
- }
-
iommu_area_reserve(tbl->it_map, index, npages);
spin_unlock_irqrestore(&tbl->it_lock, flags);
@@ -326,7 +286,6 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
unsigned int npages)
{
unsigned long entry;
- unsigned long badbit;
unsigned long badend;
unsigned long flags;
@@ -346,14 +305,6 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
spin_lock_irqsave(&tbl->it_lock, flags);
- badbit = verify_bit_range(tbl->it_map, 1, entry, entry + npages);
- if (badbit != ~0UL) {
- if (printk_ratelimit())
- printk(KERN_ERR "Calgary: bit is off at 0x%lx "
- "tbl %p dma 0x%Lx entry 0x%lx npages %u\n",
- badbit, tbl, dma_addr, entry, npages);
- }
-
iommu_area_free(tbl->it_map, entry, npages);
spin_unlock_irqrestore(&tbl->it_lock, flags);
@@ -1488,9 +1439,8 @@ void __init detect_calgary(void)
iommu_detected = 1;
calgary_detected = 1;
printk(KERN_INFO "PCI-DMA: Calgary IOMMU detected.\n");
- printk(KERN_INFO "PCI-DMA: Calgary TCE table spec is %d, "
- "CONFIG_IOMMU_DEBUG is %s.\n", specified_table_size,
- debugging ? "enabled" : "disabled");
+ printk(KERN_INFO "PCI-DMA: Calgary TCE table spec is %d\n",
+ specified_table_size);
/* swiotlb for devices that aren't behind the Calgary. */
if (max_pfn > MAX_DMA32_PFN)
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 745579bc8256..049005e82178 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -32,6 +32,8 @@ int no_iommu __read_mostly;
/* Set this to 1 if there is a HW IOMMU in the system */
int iommu_detected __read_mostly = 0;
+int iommu_pass_through;
+
dma_addr_t bad_dma_address __read_mostly = 0;
EXPORT_SYMBOL(bad_dma_address);
@@ -209,6 +211,10 @@ static __init int iommu_setup(char *p)
#ifdef CONFIG_SWIOTLB
if (!strncmp(p, "soft", 4))
swiotlb = 1;
+ if (!strncmp(p, "pt", 2)) {
+ iommu_pass_through = 1;
+ return 1;
+ }
#endif
gart_parse_options(p);
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index b284b58c035c..1e8920d98f7c 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -144,48 +144,21 @@ static void flush_gart(void)
}
#ifdef CONFIG_IOMMU_LEAK
-
-#define SET_LEAK(x) \
- do { \
- if (iommu_leak_tab) \
- iommu_leak_tab[x] = __builtin_return_address(0);\
- } while (0)
-
-#define CLEAR_LEAK(x) \
- do { \
- if (iommu_leak_tab) \
- iommu_leak_tab[x] = NULL; \
- } while (0)
-
/* Debugging aid for drivers that don't free their IOMMU tables */
-static void **iommu_leak_tab;
static int leak_trace;
static int iommu_leak_pages = 20;
static void dump_leak(void)
{
- int i;
static int dump;
- if (dump || !iommu_leak_tab)
+ if (dump)
return;
dump = 1;
- show_stack(NULL, NULL);
- /* Very crude. dump some from the end of the table too */
- printk(KERN_DEBUG "Dumping %d pages from end of IOMMU:\n",
- iommu_leak_pages);
- for (i = 0; i < iommu_leak_pages; i += 2) {
- printk(KERN_DEBUG "%lu: ", iommu_pages-i);
- printk_address((unsigned long) iommu_leak_tab[iommu_pages-i],
- 0);
- printk(KERN_CONT "%c", (i+1)%2 == 0 ? '\n' : ' ');
- }
- printk(KERN_DEBUG "\n");
+ show_stack(NULL, NULL);
+ debug_dma_dump_mappings(NULL);
}
-#else
-# define SET_LEAK(x)
-# define CLEAR_LEAK(x)
#endif
static void iommu_full(struct device *dev, size_t size, int dir)
@@ -248,7 +221,6 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
for (i = 0; i < npages; i++) {
iommu_gatt_base[iommu_page + i] = GPTE_ENCODE(phys_mem);
- SET_LEAK(iommu_page + i);
phys_mem += PAGE_SIZE;
}
return iommu_bus_base + iommu_page*PAGE_SIZE + (phys_mem & ~PAGE_MASK);
@@ -294,7 +266,6 @@ static void gart_unmap_page(struct device *dev, dma_addr_t dma_addr,
npages = iommu_num_pages(dma_addr, size, PAGE_SIZE);
for (i = 0; i < npages; i++) {
iommu_gatt_base[iommu_page + i] = gart_unmapped_entry;
- CLEAR_LEAK(iommu_page + i);
}
free_iommu(iommu_page, npages);
}
@@ -377,7 +348,6 @@ static int __dma_map_cont(struct device *dev, struct scatterlist *start,
pages = iommu_num_pages(s->offset, s->length, PAGE_SIZE);
while (pages--) {
iommu_gatt_base[iommu_page] = GPTE_ENCODE(addr);
- SET_LEAK(iommu_page);
addr += PAGE_SIZE;
iommu_page++;
}
@@ -801,11 +771,12 @@ void __init gart_iommu_init(void)
#ifdef CONFIG_IOMMU_LEAK
if (leak_trace) {
- iommu_leak_tab = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
- get_order(iommu_pages*sizeof(void *)));
- if (!iommu_leak_tab)
+ int ret;
+
+ ret = dma_debug_resize_entries(iommu_pages);
+ if (ret)
printk(KERN_DEBUG
- "PCI-DMA: Cannot allocate leak trace area\n");
+ "PCI-DMA: Cannot trace all the entries\n");
}
#endif
diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c
index 34f12e9996ed..6af96ee44200 100644
--- a/arch/x86/kernel/pci-swiotlb.c
+++ b/arch/x86/kernel/pci-swiotlb.c
@@ -28,7 +28,7 @@ dma_addr_t swiotlb_phys_to_bus(struct device *hwdev, phys_addr_t paddr)
return paddr;
}
-phys_addr_t swiotlb_bus_to_phys(dma_addr_t baddr)
+phys_addr_t swiotlb_bus_to_phys(struct device *hwdev, dma_addr_t baddr)
{
return baddr;
}
@@ -50,7 +50,7 @@ static void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
return swiotlb_alloc_coherent(hwdev, size, dma_handle, flags);
}
-struct dma_map_ops swiotlb_dma_ops = {
+static struct dma_map_ops swiotlb_dma_ops = {
.mapping_error = swiotlb_dma_mapping_error,
.alloc_coherent = x86_swiotlb_alloc_coherent,
.free_coherent = swiotlb_free_coherent,
@@ -71,7 +71,8 @@ void __init pci_swiotlb_init(void)
{
/* don't initialize swiotlb if iommu=off (no_iommu=1) */
#ifdef CONFIG_X86_64
- if (!iommu_detected && !no_iommu && max_pfn > MAX_DMA32_PFN)
+ if ((!iommu_detected && !no_iommu && max_pfn > MAX_DMA32_PFN) ||
+ iommu_pass_through)
swiotlb = 1;
#endif
if (swiotlb_force)
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index ca989158e847..08f23b50af53 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -11,9 +11,11 @@
#include <trace/power.h>
#include <asm/system.h>
#include <asm/apic.h>
+#include <asm/syscalls.h>
#include <asm/idle.h>
#include <asm/uaccess.h>
#include <asm/i387.h>
+#include <asm/ds.h>
unsigned long idle_halt;
EXPORT_SYMBOL(idle_halt);
@@ -45,6 +47,8 @@ void free_thread_xstate(struct task_struct *tsk)
kmem_cache_free(task_xstate_cachep, tsk->thread.xstate);
tsk->thread.xstate = NULL;
}
+
+ WARN(tsk->thread.ds_ctx, "leaking DS context\n");
}
void free_thread_info(struct thread_info *ti)
@@ -83,8 +87,6 @@ void exit_thread(void)
put_cpu();
kfree(bp);
}
-
- ds_exit_thread(current);
}
void flush_thread(void)
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 76f8f84043a2..54638585993b 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -290,7 +290,8 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
p->thread.io_bitmap_max = 0;
}
- ds_copy_thread(p, current);
+ clear_tsk_thread_flag(p, TIF_DS_AREA_MSR);
+ p->thread.ds_ctx = NULL;
clear_tsk_thread_flag(p, TIF_DEBUGCTLMSR);
p->thread.debugctlmsr = 0;
@@ -407,7 +408,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
* done before math_state_restore, so the TS bit is up
* to date.
*/
- arch_leave_lazy_cpu_mode();
+ arch_end_context_switch(next_p);
/* If the task has used fpu the last 5 timeslices, just do a full
* restore of the math state immediately to avoid the trap; the
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index b751a41392b1..2b659f21a83c 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -335,7 +335,8 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
goto out;
}
- ds_copy_thread(p, me);
+ clear_tsk_thread_flag(p, TIF_DS_AREA_MSR);
+ p->thread.ds_ctx = NULL;
clear_tsk_thread_flag(p, TIF_DEBUGCTLMSR);
p->thread.debugctlmsr = 0;
@@ -428,7 +429,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
* done before math_state_restore, so the TS bit is up
* to date.
*/
- arch_leave_lazy_cpu_mode();
+ arch_end_context_switch(next_p);
/*
* Switch FS and GS.
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 23b7c8f017e2..09ecbde91c13 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -21,6 +21,7 @@
#include <linux/audit.h>
#include <linux/seccomp.h>
#include <linux/signal.h>
+#include <linux/workqueue.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -578,17 +579,130 @@ static int ioperm_get(struct task_struct *target,
}
#ifdef CONFIG_X86_PTRACE_BTS
+/*
+ * A branch trace store context.
+ *
+ * Contexts may only be installed by ptrace_bts_config() and only for
+ * ptraced tasks.
+ *
+ * Contexts are destroyed when the tracee is detached from the tracer.
+ * The actual destruction work requires interrupts enabled, so the
+ * work is deferred and will be scheduled during __ptrace_unlink().
+ *
+ * Contexts hold an additional task_struct reference on the traced
+ * task, as well as a reference on the tracer's mm.
+ *
+ * Ptrace already holds a task_struct for the duration of ptrace operations,
+ * but since destruction is deferred, it may be executed after both
+ * tracer and tracee exited.
+ */
+struct bts_context {
+ /* The branch trace handle. */
+ struct bts_tracer *tracer;
+
+ /* The buffer used to store the branch trace and its size. */
+ void *buffer;
+ unsigned int size;
+
+ /* The mm that paid for the above buffer. */
+ struct mm_struct *mm;
+
+ /* The task this context belongs to. */
+ struct task_struct *task;
+
+ /* The signal to send on a bts buffer overflow. */
+ unsigned int bts_ovfl_signal;
+
+ /* The work struct to destroy a context. */
+ struct work_struct work;
+};
+
+static int alloc_bts_buffer(struct bts_context *context, unsigned int size)
+{
+ void *buffer = NULL;
+ int err = -ENOMEM;
+
+ err = account_locked_memory(current->mm, current->signal->rlim, size);
+ if (err < 0)
+ return err;
+
+ buffer = kzalloc(size, GFP_KERNEL);
+ if (!buffer)
+ goto out_refund;
+
+ context->buffer = buffer;
+ context->size = size;
+ context->mm = get_task_mm(current);
+
+ return 0;
+
+ out_refund:
+ refund_locked_memory(current->mm, size);
+ return err;
+}
+
+static inline void free_bts_buffer(struct bts_context *context)
+{
+ if (!context->buffer)
+ return;
+
+ kfree(context->buffer);
+ context->buffer = NULL;
+
+ refund_locked_memory(context->mm, context->size);
+ context->size = 0;
+
+ mmput(context->mm);
+ context->mm = NULL;
+}
+
+static void free_bts_context_work(struct work_struct *w)
+{
+ struct bts_context *context;
+
+ context = container_of(w, struct bts_context, work);
+
+ ds_release_bts(context->tracer);
+ put_task_struct(context->task);
+ free_bts_buffer(context);
+ kfree(context);
+}
+
+static inline void free_bts_context(struct bts_context *context)
+{
+ INIT_WORK(&context->work, free_bts_context_work);
+ schedule_work(&context->work);
+}
+
+static inline struct bts_context *alloc_bts_context(struct task_struct *task)
+{
+ struct bts_context *context = kzalloc(sizeof(*context), GFP_KERNEL);
+ if (context) {
+ context->task = task;
+ task->bts = context;
+
+ get_task_struct(task);
+ }
+
+ return context;
+}
+
static int ptrace_bts_read_record(struct task_struct *child, size_t index,
struct bts_struct __user *out)
{
+ struct bts_context *context;
const struct bts_trace *trace;
struct bts_struct bts;
const unsigned char *at;
int error;
- trace = ds_read_bts(child->bts);
+ context = child->bts;
+ if (!context)
+ return -ESRCH;
+
+ trace = ds_read_bts(context->tracer);
if (!trace)
- return -EPERM;
+ return -ESRCH;
at = trace->ds.top - ((index + 1) * trace->ds.size);
if ((void *)at < trace->ds.begin)
@@ -597,7 +711,7 @@ static int ptrace_bts_read_record(struct task_struct *child, size_t index,
if (!trace->read)
return -EOPNOTSUPP;
- error = trace->read(child->bts, at, &bts);
+ error = trace->read(context->tracer, at, &bts);
if (error < 0)
return error;
@@ -611,13 +725,18 @@ static int ptrace_bts_drain(struct task_struct *child,
long size,
struct bts_struct __user *out)
{
+ struct bts_context *context;
const struct bts_trace *trace;
const unsigned char *at;
int error, drained = 0;
- trace = ds_read_bts(child->bts);
+ context = child->bts;
+ if (!context)
+ return -ESRCH;
+
+ trace = ds_read_bts(context->tracer);
if (!trace)
- return -EPERM;
+ return -ESRCH;
if (!trace->read)
return -EOPNOTSUPP;
@@ -628,9 +747,8 @@ static int ptrace_bts_drain(struct task_struct *child,
for (at = trace->ds.begin; (void *)at < trace->ds.top;
out++, drained++, at += trace->ds.size) {
struct bts_struct bts;
- int error;
- error = trace->read(child->bts, at, &bts);
+ error = trace->read(context->tracer, at, &bts);
if (error < 0)
return error;
@@ -640,35 +758,18 @@ static int ptrace_bts_drain(struct task_struct *child,
memset(trace->ds.begin, 0, trace->ds.n * trace->ds.size);
- error = ds_reset_bts(child->bts);
+ error = ds_reset_bts(context->tracer);
if (error < 0)
return error;
return drained;
}
-static int ptrace_bts_allocate_buffer(struct task_struct *child, size_t size)
-{
- child->bts_buffer = alloc_locked_buffer(size);
- if (!child->bts_buffer)
- return -ENOMEM;
-
- child->bts_size = size;
-
- return 0;
-}
-
-static void ptrace_bts_free_buffer(struct task_struct *child)
-{
- free_locked_buffer(child->bts_buffer, child->bts_size);
- child->bts_buffer = NULL;
- child->bts_size = 0;
-}
-
static int ptrace_bts_config(struct task_struct *child,
long cfg_size,
const struct ptrace_bts_config __user *ucfg)
{
+ struct bts_context *context;
struct ptrace_bts_config cfg;
unsigned int flags = 0;
@@ -678,28 +779,33 @@ static int ptrace_bts_config(struct task_struct *child,
if (copy_from_user(&cfg, ucfg, sizeof(cfg)))
return -EFAULT;
- if (child->bts) {
- ds_release_bts(child->bts);
- child->bts = NULL;
- }
+ context = child->bts;
+ if (!context)
+ context = alloc_bts_context(child);
+ if (!context)
+ return -ENOMEM;
if (cfg.flags & PTRACE_BTS_O_SIGNAL) {
if (!cfg.signal)
return -EINVAL;
- child->thread.bts_ovfl_signal = cfg.signal;
return -EOPNOTSUPP;
+ context->bts_ovfl_signal = cfg.signal;
}
- if ((cfg.flags & PTRACE_BTS_O_ALLOC) &&
- (cfg.size != child->bts_size)) {
- int error;
+ ds_release_bts(context->tracer);
+ context->tracer = NULL;
- ptrace_bts_free_buffer(child);
+ if ((cfg.flags & PTRACE_BTS_O_ALLOC) && (cfg.size != context->size)) {
+ int err;
- error = ptrace_bts_allocate_buffer(child, cfg.size);
- if (error < 0)
- return error;
+ free_bts_buffer(context);
+ if (!cfg.size)
+ return 0;
+
+ err = alloc_bts_buffer(context, cfg.size);
+ if (err < 0)
+ return err;
}
if (cfg.flags & PTRACE_BTS_O_TRACE)
@@ -708,15 +814,14 @@ static int ptrace_bts_config(struct task_struct *child,
if (cfg.flags & PTRACE_BTS_O_SCHED)
flags |= BTS_TIMESTAMPS;
- child->bts = ds_request_bts(child, child->bts_buffer, child->bts_size,
- /* ovfl = */ NULL, /* th = */ (size_t)-1,
- flags);
- if (IS_ERR(child->bts)) {
- int error = PTR_ERR(child->bts);
-
- ptrace_bts_free_buffer(child);
- child->bts = NULL;
+ context->tracer =
+ ds_request_bts_task(child, context->buffer, context->size,
+ NULL, (size_t)-1, flags);
+ if (unlikely(IS_ERR(context->tracer))) {
+ int error = PTR_ERR(context->tracer);
+ free_bts_buffer(context);
+ context->tracer = NULL;
return error;
}
@@ -727,20 +832,25 @@ static int ptrace_bts_status(struct task_struct *child,
long cfg_size,
struct ptrace_bts_config __user *ucfg)
{
+ struct bts_context *context;
const struct bts_trace *trace;
struct ptrace_bts_config cfg;
+ context = child->bts;
+ if (!context)
+ return -ESRCH;
+
if (cfg_size < sizeof(cfg))
return -EIO;
- trace = ds_read_bts(child->bts);
+ trace = ds_read_bts(context->tracer);
if (!trace)
- return -EPERM;
+ return -ESRCH;
memset(&cfg, 0, sizeof(cfg));
- cfg.size = trace->ds.end - trace->ds.begin;
- cfg.signal = child->thread.bts_ovfl_signal;
- cfg.bts_size = sizeof(struct bts_struct);
+ cfg.size = trace->ds.end - trace->ds.begin;
+ cfg.signal = context->bts_ovfl_signal;
+ cfg.bts_size = sizeof(struct bts_struct);
if (cfg.signal)
cfg.flags |= PTRACE_BTS_O_SIGNAL;
@@ -759,80 +869,51 @@ static int ptrace_bts_status(struct task_struct *child,
static int ptrace_bts_clear(struct task_struct *child)
{
+ struct bts_context *context;
const struct bts_trace *trace;
- trace = ds_read_bts(child->bts);
+ context = child->bts;
+ if (!context)
+ return -ESRCH;
+
+ trace = ds_read_bts(context->tracer);
if (!trace)
- return -EPERM;
+ return -ESRCH;
memset(trace->ds.begin, 0, trace->ds.n * trace->ds.size);
- return ds_reset_bts(child->bts);
+ return ds_reset_bts(context->tracer);
}
static int ptrace_bts_size(struct task_struct *child)
{
+ struct bts_context *context;
const struct bts_trace *trace;
- trace = ds_read_bts(child->bts);
+ context = child->bts;
+ if (!context)
+ return -ESRCH;
+
+ trace = ds_read_bts(context->tracer);
if (!trace)
- return -EPERM;
+ return -ESRCH;
return (trace->ds.top - trace->ds.begin) / trace->ds.size;
}
-static void ptrace_bts_fork(struct task_struct *tsk)
-{
- tsk->bts = NULL;
- tsk->bts_buffer = NULL;
- tsk->bts_size = 0;
- tsk->thread.bts_ovfl_signal = 0;
-}
-
-static void ptrace_bts_untrace(struct task_struct *child)
+/*
+ * Called from __ptrace_unlink() after the child has been moved back
+ * to its original parent.
+ */
+void ptrace_bts_untrace(struct task_struct *child)
{
if (unlikely(child->bts)) {
- ds_release_bts(child->bts);
+ free_bts_context(child->bts);
child->bts = NULL;
-
- /* We cannot update total_vm and locked_vm since
- child's mm is already gone. But we can reclaim the
- memory. */
- kfree(child->bts_buffer);
- child->bts_buffer = NULL;
- child->bts_size = 0;
}
}
-
-static void ptrace_bts_detach(struct task_struct *child)
-{
- /*
- * Ptrace_detach() races with ptrace_untrace() in case
- * the child dies and is reaped by another thread.
- *
- * We only do the memory accounting at this point and
- * leave the buffer deallocation and the bts tracer
- * release to ptrace_bts_untrace() which will be called
- * later on with tasklist_lock held.
- */
- release_locked_buffer(child->bts_buffer, child->bts_size);
-}
-#else
-static inline void ptrace_bts_fork(struct task_struct *tsk) {}
-static inline void ptrace_bts_detach(struct task_struct *child) {}
-static inline void ptrace_bts_untrace(struct task_struct *child) {}
#endif /* CONFIG_X86_PTRACE_BTS */
-void x86_ptrace_fork(struct task_struct *child, unsigned long clone_flags)
-{
- ptrace_bts_fork(child);
-}
-
-void x86_ptrace_untrace(struct task_struct *child)
-{
- ptrace_bts_untrace(child);
-}
-
/*
* Called by kernel/ptrace.c when detaching..
*
@@ -844,7 +925,6 @@ void ptrace_disable(struct task_struct *child)
#ifdef TIF_SYSCALL_EMU
clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
#endif
- ptrace_bts_detach(child);
}
#if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c
index e95022e4f5d5..af71d06624bf 100644
--- a/arch/x86/kernel/quirks.c
+++ b/arch/x86/kernel/quirks.c
@@ -261,8 +261,6 @@ static void old_ich_force_enable_hpet_user(struct pci_dev *dev)
{
if (hpet_force_user)
old_ich_force_enable_hpet(dev);
- else
- hpet_print_force_info();
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1,
@@ -493,5 +491,42 @@ void force_hpet_resume(void)
break;
}
}
+#endif
+
+#if defined(CONFIG_PCI) && defined(CONFIG_NUMA)
+/* Set correct numa_node information for AMD NB functions */
+static void __init quirk_amd_nb_node(struct pci_dev *dev)
+{
+ struct pci_dev *nb_ht;
+ unsigned int devfn;
+ u32 val;
+
+ devfn = PCI_DEVFN(PCI_SLOT(dev->devfn), 0);
+ nb_ht = pci_get_slot(dev->bus, devfn);
+ if (!nb_ht)
+ return;
+
+ pci_read_config_dword(nb_ht, 0x60, &val);
+ set_dev_node(&dev->dev, val & 7);
+ pci_dev_put(dev);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB,
+ quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP,
+ quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MEMCTL,
+ quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC,
+ quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_HT,
+ quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MAP,
+ quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_DRAM,
+ quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC,
+ quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_LINK,
+ quirk_amd_nb_node);
#endif
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index b4158439bf63..67d9081e82aa 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -112,6 +112,14 @@
#define ARCH_SETUP
#endif
+/*
+ * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
+ * The direct mapping extends to max_pfn_mapped, so that we can directly access
+ * apertures, ACPI and other tables without having to play with fixmaps.
+ */
+unsigned long max_low_pfn_mapped;
+unsigned long max_pfn_mapped;
+
RESERVE_BRK(dmi_alloc, 65536);
unsigned int boot_cpu_id __read_mostly;
@@ -997,24 +1005,6 @@ void __init setup_arch(char **cmdline_p)
#ifdef CONFIG_X86_32
/**
- * x86_quirk_pre_intr_init - initialisation prior to setting up interrupt vectors
- *
- * Description:
- * Perform any necessary interrupt initialisation prior to setting up
- * the "ordinary" interrupt call gates. For legacy reasons, the ISA
- * interrupts should be initialised here if the machine emulates a PC
- * in any way.
- **/
-void __init x86_quirk_pre_intr_init(void)
-{
- if (x86_quirks->arch_pre_intr_init) {
- if (x86_quirks->arch_pre_intr_init())
- return;
- }
- init_ISA_irqs();
-}
-
-/**
* x86_quirk_intr_init - post gate setup interrupt initialisation
*
* Description:
diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
index 13f33ea8ccaa..28f5fb495a66 100644
--- a/arch/x86/kernel/smp.c
+++ b/arch/x86/kernel/smp.c
@@ -172,6 +172,9 @@ void smp_reschedule_interrupt(struct pt_regs *regs)
{
ack_APIC_irq();
inc_irq_stat(irq_resched_count);
+ /*
+ * KVM uses this interrupt to force a cpu out of guest mode
+ */
}
void smp_call_function_interrupt(struct pt_regs *regs)
@@ -193,19 +196,19 @@ void smp_call_function_single_interrupt(struct pt_regs *regs)
}
struct smp_ops smp_ops = {
- .smp_prepare_boot_cpu = native_smp_prepare_boot_cpu,
- .smp_prepare_cpus = native_smp_prepare_cpus,
- .smp_cpus_done = native_smp_cpus_done,
+ .smp_prepare_boot_cpu = native_smp_prepare_boot_cpu,
+ .smp_prepare_cpus = native_smp_prepare_cpus,
+ .smp_cpus_done = native_smp_cpus_done,
- .smp_send_stop = native_smp_send_stop,
- .smp_send_reschedule = native_smp_send_reschedule,
+ .smp_send_stop = native_smp_send_stop,
+ .smp_send_reschedule = native_smp_send_reschedule,
- .cpu_up = native_cpu_up,
- .cpu_die = native_cpu_die,
- .cpu_disable = native_cpu_disable,
- .play_dead = native_play_dead,
+ .cpu_up = native_cpu_up,
+ .cpu_die = native_cpu_die,
+ .cpu_disable = native_cpu_disable,
+ .play_dead = native_play_dead,
- .send_call_func_ipi = native_send_call_func_ipi,
+ .send_call_func_ipi = native_send_call_func_ipi,
.send_call_func_single_ipi = native_send_call_func_single_ipi,
};
EXPORT_SYMBOL_GPL(smp_ops);
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 58d24ef917d8..d2e8de958156 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -504,7 +504,7 @@ void __inquire_remote_apic(int apicid)
* INIT, INIT, STARTUP sequence will reset the chip hard for us, and this
* won't ... remember to clear down the APIC, etc later.
*/
-int __devinit
+int __cpuinit
wakeup_secondary_cpu_via_nmi(int logical_apicid, unsigned long start_eip)
{
unsigned long send_status, accept_status = 0;
@@ -538,7 +538,7 @@ wakeup_secondary_cpu_via_nmi(int logical_apicid, unsigned long start_eip)
return (send_status | accept_status);
}
-int __devinit
+static int __cpuinit
wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
{
unsigned long send_status, accept_status = 0;
@@ -822,10 +822,12 @@ do_rest:
/* mark "stuck" area as not stuck */
*((volatile unsigned long *)trampoline_base) = 0;
- /*
- * Cleanup possible dangling ends...
- */
- smpboot_restore_warm_reset_vector();
+ if (get_uv_system_type() != UV_NON_UNIQUE_APIC) {
+ /*
+ * Cleanup possible dangling ends...
+ */
+ smpboot_restore_warm_reset_vector();
+ }
return boot_error;
}
diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S
index ff5c8736b491..734f92c02dde 100644
--- a/arch/x86/kernel/syscall_table_32.S
+++ b/arch/x86/kernel/syscall_table_32.S
@@ -334,3 +334,4 @@ ENTRY(sys_call_table)
.long sys_inotify_init1
.long sys_preadv
.long sys_pwritev
+ .long sys_rt_tgsigqueueinfo /* 335 */
diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c
index deb5ebb32c3b..ed0c33761e6d 100644
--- a/arch/x86/kernel/tlb_uv.c
+++ b/arch/x86/kernel/tlb_uv.c
@@ -25,6 +25,8 @@ static int uv_bau_retry_limit __read_mostly;
/* position of pnode (which is nasid>>1): */
static int uv_nshift __read_mostly;
+/* base pnode in this partition */
+static int uv_partition_base_pnode __read_mostly;
static unsigned long uv_mmask __read_mostly;
@@ -32,6 +34,34 @@ static DEFINE_PER_CPU(struct ptc_stats, ptcstats);
static DEFINE_PER_CPU(struct bau_control, bau_control);
/*
+ * Determine the first node on a blade.
+ */
+static int __init blade_to_first_node(int blade)
+{
+ int node, b;
+
+ for_each_online_node(node) {
+ b = uv_node_to_blade_id(node);
+ if (blade == b)
+ return node;
+ }
+ return -1; /* shouldn't happen */
+}
+
+/*
+ * Determine the apicid of the first cpu on a blade.
+ */
+static int __init blade_to_first_apicid(int blade)
+{
+ int cpu;
+
+ for_each_present_cpu(cpu)
+ if (blade == uv_cpu_to_blade_id(cpu))
+ return per_cpu(x86_cpu_to_apicid, cpu);
+ return -1;
+}
+
+/*
* Free a software acknowledge hardware resource by clearing its Pending
* bit. This will return a reply to the sender.
* If the message has timed out, a reply has already been sent by the
@@ -67,7 +97,7 @@ static void uv_bau_process_message(struct bau_payload_queue_entry *msg,
msp = __get_cpu_var(bau_control).msg_statuses + msg_slot;
cpu = uv_blade_processor_id();
msg->number_of_cpus =
- uv_blade_nr_online_cpus(uv_node_to_blade_id(numa_node_id()));
+ uv_blade_nr_online_cpus(uv_node_to_blade_id(numa_node_id()));
this_cpu_mask = 1UL << cpu;
if (msp->seen_by.bits & this_cpu_mask)
return;
@@ -215,14 +245,14 @@ static int uv_wait_completion(struct bau_desc *bau_desc,
* Returns @flush_mask if some remote flushing remains to be done. The
* mask will have some bits still set.
*/
-const struct cpumask *uv_flush_send_and_wait(int cpu, int this_blade,
+const struct cpumask *uv_flush_send_and_wait(int cpu, int this_pnode,
struct bau_desc *bau_desc,
struct cpumask *flush_mask)
{
int completion_status = 0;
int right_shift;
int tries = 0;
- int blade;
+ int pnode;
int bit;
unsigned long mmr_offset;
unsigned long index;
@@ -265,8 +295,8 @@ const struct cpumask *uv_flush_send_and_wait(int cpu, int this_blade,
* use the IPI method of shootdown on them.
*/
for_each_cpu(bit, flush_mask) {
- blade = uv_cpu_to_blade_id(bit);
- if (blade == this_blade)
+ pnode = uv_cpu_to_pnode(bit);
+ if (pnode == this_pnode)
continue;
cpumask_clear_cpu(bit, flush_mask);
}
@@ -309,16 +339,16 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
struct cpumask *flush_mask = __get_cpu_var(uv_flush_tlb_mask);
int i;
int bit;
- int blade;
+ int pnode;
int uv_cpu;
- int this_blade;
+ int this_pnode;
int locals = 0;
struct bau_desc *bau_desc;
cpumask_andnot(flush_mask, cpumask, cpumask_of(cpu));
uv_cpu = uv_blade_processor_id();
- this_blade = uv_numa_blade_id();
+ this_pnode = uv_hub_info->pnode;
bau_desc = __get_cpu_var(bau_control).descriptor_base;
bau_desc += UV_ITEMS_PER_DESCRIPTOR * uv_cpu;
@@ -326,13 +356,14 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
i = 0;
for_each_cpu(bit, flush_mask) {
- blade = uv_cpu_to_blade_id(bit);
- BUG_ON(blade > (UV_DISTRIBUTION_SIZE - 1));
- if (blade == this_blade) {
+ pnode = uv_cpu_to_pnode(bit);
+ BUG_ON(pnode > (UV_DISTRIBUTION_SIZE - 1));
+ if (pnode == this_pnode) {
locals++;
continue;
}
- bau_node_set(blade, &bau_desc->distribution);
+ bau_node_set(pnode - uv_partition_base_pnode,
+ &bau_desc->distribution);
i++;
}
if (i == 0) {
@@ -350,7 +381,7 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
bau_desc->payload.address = va;
bau_desc->payload.sending_cpu = cpu;
- return uv_flush_send_and_wait(uv_cpu, this_blade, bau_desc, flush_mask);
+ return uv_flush_send_and_wait(uv_cpu, this_pnode, bau_desc, flush_mask);
}
/*
@@ -418,24 +449,58 @@ void uv_bau_message_interrupt(struct pt_regs *regs)
set_irq_regs(old_regs);
}
+/*
+ * uv_enable_timeouts
+ *
+ * Each target blade (i.e. blades that have cpu's) needs to have
+ * shootdown message timeouts enabled. The timeout does not cause
+ * an interrupt, but causes an error message to be returned to
+ * the sender.
+ */
static void uv_enable_timeouts(void)
{
- int i;
int blade;
- int last_blade;
+ int nblades;
int pnode;
- int cur_cpu = 0;
- unsigned long apicid;
+ unsigned long mmr_image;
- last_blade = -1;
- for_each_online_node(i) {
- blade = uv_node_to_blade_id(i);
- if (blade == last_blade)
+ nblades = uv_num_possible_blades();
+
+ for (blade = 0; blade < nblades; blade++) {
+ if (!uv_blade_nr_possible_cpus(blade))
continue;
- last_blade = blade;
- apicid = per_cpu(x86_cpu_to_apicid, cur_cpu);
+
pnode = uv_blade_to_pnode(blade);
- cur_cpu += uv_blade_nr_possible_cpus(i);
+ mmr_image =
+ uv_read_global_mmr64(pnode, UVH_LB_BAU_MISC_CONTROL);
+ /*
+ * Set the timeout period and then lock it in, in three
+ * steps; captures and locks in the period.
+ *
+ * To program the period, the SOFT_ACK_MODE must be off.
+ */
+ mmr_image &= ~((unsigned long)1 <<
+ UV_ENABLE_INTD_SOFT_ACK_MODE_SHIFT);
+ uv_write_global_mmr64
+ (pnode, UVH_LB_BAU_MISC_CONTROL, mmr_image);
+ /*
+ * Set the 4-bit period.
+ */
+ mmr_image &= ~((unsigned long)0xf <<
+ UV_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHIFT);
+ mmr_image |= (UV_INTD_SOFT_ACK_TIMEOUT_PERIOD <<
+ UV_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHIFT);
+ uv_write_global_mmr64
+ (pnode, UVH_LB_BAU_MISC_CONTROL, mmr_image);
+ /*
+ * Subsequent reversals of the timebase bit (3) cause an
+ * immediate timeout of one or all INTD resources as
+ * indicated in bits 2:0 (7 causes all of them to timeout).
+ */
+ mmr_image |= ((unsigned long)1 <<
+ UV_ENABLE_INTD_SOFT_ACK_MODE_SHIFT);
+ uv_write_global_mmr64
+ (pnode, UVH_LB_BAU_MISC_CONTROL, mmr_image);
}
}
@@ -482,8 +547,7 @@ static int uv_ptc_seq_show(struct seq_file *file, void *data)
stat->requestee, stat->onetlb, stat->alltlb,
stat->s_retry, stat->d_retry, stat->ptc_i);
seq_printf(file, "%lx %ld %ld %ld %ld %ld %ld\n",
- uv_read_global_mmr64(uv_blade_to_pnode
- (uv_cpu_to_blade_id(cpu)),
+ uv_read_global_mmr64(uv_cpu_to_pnode(cpu),
UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE),
stat->sflush, stat->dflush,
stat->retriesok, stat->nomsg,
@@ -617,16 +681,18 @@ static struct bau_control * __init uv_table_bases_init(int blade, int node)
* finish the initialization of the per-blade control structures
*/
static void __init
-uv_table_bases_finish(int blade, int node, int cur_cpu,
+uv_table_bases_finish(int blade,
struct bau_control *bau_tablesp,
struct bau_desc *adp)
{
struct bau_control *bcp;
- int i;
+ int cpu;
- for (i = cur_cpu; i < cur_cpu + uv_blade_nr_possible_cpus(blade); i++) {
- bcp = (struct bau_control *)&per_cpu(bau_control, i);
+ for_each_present_cpu(cpu) {
+ if (blade != uv_cpu_to_blade_id(cpu))
+ continue;
+ bcp = (struct bau_control *)&per_cpu(bau_control, cpu);
bcp->bau_msg_head = bau_tablesp->va_queue_first;
bcp->va_queue_first = bau_tablesp->va_queue_first;
bcp->va_queue_last = bau_tablesp->va_queue_last;
@@ -649,11 +715,10 @@ uv_activation_descriptor_init(int node, int pnode)
struct bau_desc *adp;
struct bau_desc *ad2;
- adp = (struct bau_desc *)
- kmalloc_node(16384, GFP_KERNEL, node);
+ adp = (struct bau_desc *)kmalloc_node(16384, GFP_KERNEL, node);
BUG_ON(!adp);
- pa = __pa((unsigned long)adp);
+ pa = uv_gpa(adp); /* need the real nasid*/
n = pa >> uv_nshift;
m = pa & uv_mmask;
@@ -667,8 +732,12 @@ uv_activation_descriptor_init(int node, int pnode)
for (i = 0, ad2 = adp; i < UV_ACTIVATION_DESCRIPTOR_SIZE; i++, ad2++) {
memset(ad2, 0, sizeof(struct bau_desc));
ad2->header.sw_ack_flag = 1;
- ad2->header.base_dest_nodeid =
- uv_blade_to_pnode(uv_cpu_to_blade_id(0));
+ /*
+ * base_dest_nodeid is the first node in the partition, so
+ * the bit map will indicate partition-relative node numbers.
+ * note that base_dest_nodeid is actually a nasid.
+ */
+ ad2->header.base_dest_nodeid = uv_partition_base_pnode << 1;
ad2->header.command = UV_NET_ENDPOINT_INTD;
ad2->header.int_both = 1;
/*
@@ -686,6 +755,8 @@ static struct bau_payload_queue_entry * __init
uv_payload_queue_init(int node, int pnode, struct bau_control *bau_tablesp)
{
struct bau_payload_queue_entry *pqp;
+ unsigned long pa;
+ int pn;
char *cp;
pqp = (struct bau_payload_queue_entry *) kmalloc_node(
@@ -696,10 +767,14 @@ uv_payload_queue_init(int node, int pnode, struct bau_control *bau_tablesp)
cp = (char *)pqp + 31;
pqp = (struct bau_payload_queue_entry *)(((unsigned long)cp >> 5) << 5);
bau_tablesp->va_queue_first = pqp;
+ /*
+ * need the pnode of where the memory was really allocated
+ */
+ pa = uv_gpa(pqp);
+ pn = pa >> uv_nshift;
uv_write_global_mmr64(pnode,
UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST,
- ((unsigned long)pnode <<
- UV_PAYLOADQ_PNODE_SHIFT) |
+ ((unsigned long)pn << UV_PAYLOADQ_PNODE_SHIFT) |
uv_physnodeaddr(pqp));
uv_write_global_mmr64(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL,
uv_physnodeaddr(pqp));
@@ -715,8 +790,9 @@ uv_payload_queue_init(int node, int pnode, struct bau_control *bau_tablesp)
/*
* Initialization of each UV blade's structures
*/
-static int __init uv_init_blade(int blade, int node, int cur_cpu)
+static int __init uv_init_blade(int blade)
{
+ int node;
int pnode;
unsigned long pa;
unsigned long apicid;
@@ -724,16 +800,17 @@ static int __init uv_init_blade(int blade, int node, int cur_cpu)
struct bau_payload_queue_entry *pqp;
struct bau_control *bau_tablesp;
+ node = blade_to_first_node(blade);
bau_tablesp = uv_table_bases_init(blade, node);
pnode = uv_blade_to_pnode(blade);
adp = uv_activation_descriptor_init(node, pnode);
pqp = uv_payload_queue_init(node, pnode, bau_tablesp);
- uv_table_bases_finish(blade, node, cur_cpu, bau_tablesp, adp);
+ uv_table_bases_finish(blade, bau_tablesp, adp);
/*
* the below initialization can't be in firmware because the
* messaging IRQ will be determined by the OS
*/
- apicid = per_cpu(x86_cpu_to_apicid, cur_cpu);
+ apicid = blade_to_first_apicid(blade);
pa = uv_read_global_mmr64(pnode, UVH_BAU_DATA_CONFIG);
if ((pa & 0xff) != UV_BAU_MESSAGE) {
uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG,
@@ -748,9 +825,7 @@ static int __init uv_init_blade(int blade, int node, int cur_cpu)
static int __init uv_bau_init(void)
{
int blade;
- int node;
int nblades;
- int last_blade;
int cur_cpu;
if (!is_uv_system())
@@ -763,29 +838,21 @@ static int __init uv_bau_init(void)
uv_bau_retry_limit = 1;
uv_nshift = uv_hub_info->n_val;
uv_mmask = (1UL << uv_hub_info->n_val) - 1;
- nblades = 0;
- last_blade = -1;
- cur_cpu = 0;
- for_each_online_node(node) {
- blade = uv_node_to_blade_id(node);
- if (blade == last_blade)
- continue;
- last_blade = blade;
- nblades++;
- }
+ nblades = uv_num_possible_blades();
+
uv_bau_table_bases = (struct bau_control **)
kmalloc(nblades * sizeof(struct bau_control *), GFP_KERNEL);
BUG_ON(!uv_bau_table_bases);
- last_blade = -1;
- for_each_online_node(node) {
- blade = uv_node_to_blade_id(node);
- if (blade == last_blade)
- continue;
- last_blade = blade;
- uv_init_blade(blade, node, cur_cpu);
- cur_cpu += uv_blade_nr_possible_cpus(blade);
- }
+ uv_partition_base_pnode = 0x7fffffff;
+ for (blade = 0; blade < nblades; blade++)
+ if (uv_blade_nr_possible_cpus(blade) &&
+ (uv_blade_to_pnode(blade) < uv_partition_base_pnode))
+ uv_partition_base_pnode = uv_blade_to_pnode(blade);
+ for (blade = 0; blade < nblades; blade++)
+ if (uv_blade_nr_possible_cpus(blade))
+ uv_init_blade(blade);
+
alloc_intr_gate(UV_BAU_MESSAGE, uv_bau_message_intr1);
uv_enable_timeouts();
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index a1d288327ff0..ede024531f8f 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -839,9 +839,6 @@ asmlinkage void math_state_restore(void)
}
clts(); /* Allow maths ops (or we recurse) */
-#ifdef CONFIG_X86_32
- restore_fpu(tsk);
-#else
/*
* Paranoid restore. send a SIGSEGV if we fail to restore the state.
*/
@@ -850,7 +847,7 @@ asmlinkage void math_state_restore(void)
force_sig(SIGSEGV, tsk);
return;
}
-#endif
+
thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */
tsk->fpu_counter++;
}
@@ -969,11 +966,8 @@ void __init trap_init(void)
for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
set_bit(i, used_vectors);
-#ifdef CONFIG_X86_64
set_bit(IA32_SYSCALL_VECTOR, used_vectors);
-#else
- set_bit(SYSCALL_VECTOR, used_vectors);
-#endif
+
/*
* Should be a barrier for any external CPU state:
*/
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 7a567ebe6361..84d27356c3d0 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -384,13 +384,13 @@ unsigned long native_calibrate_tsc(void)
{
u64 tsc1, tsc2, delta, ref1, ref2;
unsigned long tsc_pit_min = ULONG_MAX, tsc_ref_min = ULONG_MAX;
- unsigned long flags, latch, ms, fast_calibrate, tsc_khz;
+ unsigned long flags, latch, ms, fast_calibrate, hv_tsc_khz;
int hpet = is_hpet_enabled(), i, loopmin;
- tsc_khz = get_hypervisor_tsc_freq();
- if (tsc_khz) {
+ hv_tsc_khz = get_hypervisor_tsc_freq();
+ if (hv_tsc_khz) {
printk(KERN_INFO "TSC: Frequency read from the hypervisor\n");
- return tsc_khz;
+ return hv_tsc_khz;
}
local_irq_save(flags);
@@ -699,7 +699,7 @@ static struct clocksource clocksource_tsc;
* code, which is necessary to support wrapping clocksources like pm
* timer.
*/
-static cycle_t read_tsc(void)
+static cycle_t read_tsc(struct clocksource *cs)
{
cycle_t ret = (cycle_t)get_cycles();
diff --git a/arch/x86/kernel/uv_sysfs.c b/arch/x86/kernel/uv_sysfs.c
index 67f9b9dbf800..36afb98675a4 100644
--- a/arch/x86/kernel/uv_sysfs.c
+++ b/arch/x86/kernel/uv_sysfs.c
@@ -21,6 +21,7 @@
#include <linux/sysdev.h>
#include <asm/uv/bios.h>
+#include <asm/uv/uv.h>
struct kobject *sgi_uv_kobj;
@@ -47,6 +48,9 @@ static int __init sgi_uv_sysfs_init(void)
{
unsigned long ret;
+ if (!is_uv_system())
+ return -ENODEV;
+
if (!sgi_uv_kobj)
sgi_uv_kobj = kobject_create_and_add("sgi_uv", firmware_kobj);
if (!sgi_uv_kobj) {
diff --git a/arch/x86/kernel/uv_time.c b/arch/x86/kernel/uv_time.c
index 2ffb6c53326e..583f11d5c480 100644
--- a/arch/x86/kernel/uv_time.c
+++ b/arch/x86/kernel/uv_time.c
@@ -29,7 +29,7 @@
#define RTC_NAME "sgi_rtc"
-static cycle_t uv_read_rtc(void);
+static cycle_t uv_read_rtc(struct clocksource *cs);
static int uv_rtc_next_event(unsigned long, struct clock_event_device *);
static void uv_rtc_timer_setup(enum clock_event_mode,
struct clock_event_device *);
@@ -123,7 +123,7 @@ static int uv_setup_intr(int cpu, u64 expires)
/* Initialize comparator value */
uv_write_global_mmr64(pnode, UVH_INT_CMPB, expires);
- return (expires < uv_read_rtc() && !uv_intr_pending(pnode));
+ return (expires < uv_read_rtc(NULL) && !uv_intr_pending(pnode));
}
/*
@@ -256,7 +256,7 @@ static int uv_rtc_unset_timer(int cpu)
spin_lock_irqsave(&head->lock, flags);
- if (head->next_cpu == bcpu && uv_read_rtc() >= *t)
+ if (head->next_cpu == bcpu && uv_read_rtc(NULL) >= *t)
rc = 1;
*t = ULLONG_MAX;
@@ -278,7 +278,7 @@ static int uv_rtc_unset_timer(int cpu)
/*
* Read the RTC.
*/
-static cycle_t uv_read_rtc(void)
+static cycle_t uv_read_rtc(struct clocksource *cs)
{
return (cycle_t)uv_read_local_mmr(UVH_RTC);
}
@@ -291,7 +291,7 @@ static int uv_rtc_next_event(unsigned long delta,
{
int ced_cpu = cpumask_first(ced->cpumask);
- return uv_rtc_set_timer(ced_cpu, delta + uv_read_rtc());
+ return uv_rtc_set_timer(ced_cpu, delta + uv_read_rtc(NULL));
}
/*
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
index 95deb9f2211e..b263423fbe2a 100644
--- a/arch/x86/kernel/vmi_32.c
+++ b/arch/x86/kernel/vmi_32.c
@@ -462,22 +462,28 @@ vmi_startup_ipi_hook(int phys_apicid, unsigned long start_eip,
}
#endif
-static void vmi_enter_lazy_cpu(void)
+static void vmi_start_context_switch(struct task_struct *prev)
{
- paravirt_enter_lazy_cpu();
+ paravirt_start_context_switch(prev);
vmi_ops.set_lazy_mode(2);
}
+static void vmi_end_context_switch(struct task_struct *next)
+{
+ vmi_ops.set_lazy_mode(0);
+ paravirt_end_context_switch(next);
+}
+
static void vmi_enter_lazy_mmu(void)
{
paravirt_enter_lazy_mmu();
vmi_ops.set_lazy_mode(1);
}
-static void vmi_leave_lazy(void)
+static void vmi_leave_lazy_mmu(void)
{
- paravirt_leave_lazy(paravirt_get_lazy_mode());
vmi_ops.set_lazy_mode(0);
+ paravirt_leave_lazy_mmu();
}
static inline int __init check_vmi_rom(struct vrom_header *rom)
@@ -711,14 +717,14 @@ static inline int __init activate_vmi(void)
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,
+ para_wrap(pv_cpu_ops.start_context_switch, vmi_start_context_switch,
set_lazy_mode, SetLazyMode);
- para_wrap(pv_cpu_ops.lazy_mode.leave, vmi_leave_lazy,
+ para_wrap(pv_cpu_ops.end_context_switch, vmi_end_context_switch,
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,
+ para_wrap(pv_mmu_ops.lazy_mode.leave, vmi_leave_lazy_mmu,
set_lazy_mode, SetLazyMode);
/* user and kernel flush are just handled with different flags to FlushTLB */
diff --git a/arch/x86/kernel/vmiclock_32.c b/arch/x86/kernel/vmiclock_32.c
index d303369a7bad..2b3eb82efeeb 100644
--- a/arch/x86/kernel/vmiclock_32.c
+++ b/arch/x86/kernel/vmiclock_32.c
@@ -283,7 +283,7 @@ void __devinit vmi_time_ap_init(void)
/** vmi clocksource */
static struct clocksource clocksource_vmi;
-static cycle_t read_real_cycles(void)
+static cycle_t read_real_cycles(struct clocksource *cs)
{
cycle_t ret = (cycle_t)vmi_timer_ops.get_cycle_counter(VMI_CYCLES_REAL);
return max(ret, clocksource_vmi.cycle_last);
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 849ee611f013..9bf94df0d6f4 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -1,5 +1,432 @@
+/*
+ * ld script for the x86 kernel
+ *
+ * Historic 32-bit version written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *
+ * Modernisation, unification and other changes and fixes:
+ * Copyright (C) 2007-2009 Sam Ravnborg <sam@ravnborg.org>
+ *
+ *
+ * Don't define absolute symbols until and unless you know that symbol
+ * value is should remain constant even if kernel image is relocated
+ * at run time. Absolute symbols are not relocated. If symbol value should
+ * change if kernel is relocated, make the symbol section relative and
+ * put it inside the section definition.
+ */
+
#ifdef CONFIG_X86_32
-# include "vmlinux_32.lds.S"
+#define LOAD_OFFSET __PAGE_OFFSET
#else
-# include "vmlinux_64.lds.S"
+#define LOAD_OFFSET __START_KERNEL_map
#endif
+
+#include <asm-generic/vmlinux.lds.h>
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
+#include <asm/page_types.h>
+#include <asm/cache.h>
+#include <asm/boot.h>
+
+#undef i386 /* in case the preprocessor is a 32bit one */
+
+OUTPUT_FORMAT(CONFIG_OUTPUT_FORMAT, CONFIG_OUTPUT_FORMAT, CONFIG_OUTPUT_FORMAT)
+
+#ifdef CONFIG_X86_32
+OUTPUT_ARCH(i386)
+ENTRY(phys_startup_32)
+jiffies = jiffies_64;
+#else
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(phys_startup_64)
+jiffies_64 = jiffies;
+#endif
+
+PHDRS {
+ text PT_LOAD FLAGS(5); /* R_E */
+ data PT_LOAD FLAGS(7); /* RWE */
+#ifdef CONFIG_X86_64
+ user PT_LOAD FLAGS(7); /* RWE */
+ data.init PT_LOAD FLAGS(7); /* RWE */
+#ifdef CONFIG_SMP
+ percpu PT_LOAD FLAGS(7); /* RWE */
+#endif
+ data.init2 PT_LOAD FLAGS(7); /* RWE */
+#endif
+ note PT_NOTE FLAGS(0); /* ___ */
+}
+
+SECTIONS
+{
+#ifdef CONFIG_X86_32
+ . = LOAD_OFFSET + LOAD_PHYSICAL_ADDR;
+ phys_startup_32 = startup_32 - LOAD_OFFSET;
+#else
+ . = __START_KERNEL;
+ phys_startup_64 = startup_64 - LOAD_OFFSET;
+#endif
+
+ /* Text and read-only data */
+
+ /* bootstrapping code */
+ .text.head : AT(ADDR(.text.head) - LOAD_OFFSET) {
+ _text = .;
+ *(.text.head)
+ } :text = 0x9090
+
+ /* The rest of the text */
+ .text : AT(ADDR(.text) - LOAD_OFFSET) {
+#ifdef CONFIG_X86_32
+ /* not really needed, already page aligned */
+ . = ALIGN(PAGE_SIZE);
+ *(.text.page_aligned)
+#endif
+ . = ALIGN(8);
+ _stext = .;
+ TEXT_TEXT
+ SCHED_TEXT
+ LOCK_TEXT
+ KPROBES_TEXT
+ IRQENTRY_TEXT
+ *(.fixup)
+ *(.gnu.warning)
+ /* End of text section */
+ _etext = .;
+ } :text = 0x9090
+
+ NOTES :text :note
+
+ /* Exception table */
+ . = ALIGN(16);
+ __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
+ __start___ex_table = .;
+ *(__ex_table)
+ __stop___ex_table = .;
+ } :text = 0x9090
+
+ RODATA
+
+ /* Data */
+ . = ALIGN(PAGE_SIZE);
+ .data : AT(ADDR(.data) - LOAD_OFFSET) {
+ _sdata = .; /* Start of data section */
+ DATA_DATA
+ CONSTRUCTORS
+
+#ifdef CONFIG_X86_64
+ /* End of data section */
+ _edata = .;
+#endif
+ } :data
+
+#ifdef CONFIG_X86_32
+ /* 32 bit has nosave before _edata */
+ . = ALIGN(PAGE_SIZE);
+ .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
+ __nosave_begin = .;
+ *(.data.nosave)
+ . = ALIGN(PAGE_SIZE);
+ __nosave_end = .;
+ }
+#endif
+
+ . = ALIGN(PAGE_SIZE);
+ .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
+ *(.data.page_aligned)
+ *(.data.idt)
+ }
+
+#ifdef CONFIG_X86_32
+ . = ALIGN(32);
+#else
+ . = ALIGN(PAGE_SIZE);
+ . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
+#endif
+ .data.cacheline_aligned :
+ AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
+ *(.data.cacheline_aligned)
+ }
+
+ /* rarely changed data like cpu maps */
+#ifdef CONFIG_X86_32
+ . = ALIGN(32);
+#else
+ . = ALIGN(CONFIG_X86_INTERNODE_CACHE_BYTES);
+#endif
+ .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) {
+ *(.data.read_mostly)
+
+#ifdef CONFIG_X86_32
+ /* End of data section */
+ _edata = .;
+#endif
+ }
+
+#ifdef CONFIG_X86_64
+
+#define VSYSCALL_ADDR (-10*1024*1024)
+#define VSYSCALL_PHYS_ADDR ((LOADADDR(.data.read_mostly) + \
+ SIZEOF(.data.read_mostly) + 4095) & ~(4095))
+#define VSYSCALL_VIRT_ADDR ((ADDR(.data.read_mostly) + \
+ SIZEOF(.data.read_mostly) + 4095) & ~(4095))
+
+#define VLOAD_OFFSET (VSYSCALL_ADDR - VSYSCALL_PHYS_ADDR)
+#define VLOAD(x) (ADDR(x) - VLOAD_OFFSET)
+
+#define VVIRT_OFFSET (VSYSCALL_ADDR - VSYSCALL_VIRT_ADDR)
+#define VVIRT(x) (ADDR(x) - VVIRT_OFFSET)
+
+ . = VSYSCALL_ADDR;
+ .vsyscall_0 : AT(VSYSCALL_PHYS_ADDR) {
+ *(.vsyscall_0)
+ } :user
+
+ __vsyscall_0 = VSYSCALL_VIRT_ADDR;
+
+ . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
+ .vsyscall_fn : AT(VLOAD(.vsyscall_fn)) {
+ *(.vsyscall_fn)
+ }
+
+ . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
+ .vsyscall_gtod_data : AT(VLOAD(.vsyscall_gtod_data)) {
+ *(.vsyscall_gtod_data)
+ }
+
+ vsyscall_gtod_data = VVIRT(.vsyscall_gtod_data);
+ .vsyscall_clock : AT(VLOAD(.vsyscall_clock)) {
+ *(.vsyscall_clock)
+ }
+ vsyscall_clock = VVIRT(.vsyscall_clock);
+
+
+ .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1)) {
+ *(.vsyscall_1)
+ }
+ .vsyscall_2 ADDR(.vsyscall_0) + 2048: AT(VLOAD(.vsyscall_2)) {
+ *(.vsyscall_2)
+ }
+
+ .vgetcpu_mode : AT(VLOAD(.vgetcpu_mode)) {
+ *(.vgetcpu_mode)
+ }
+ vgetcpu_mode = VVIRT(.vgetcpu_mode);
+
+ . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
+ .jiffies : AT(VLOAD(.jiffies)) {
+ *(.jiffies)
+ }
+ jiffies = VVIRT(.jiffies);
+
+ .vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3)) {
+ *(.vsyscall_3)
+ }
+
+ . = VSYSCALL_VIRT_ADDR + PAGE_SIZE;
+
+#undef VSYSCALL_ADDR
+#undef VSYSCALL_PHYS_ADDR
+#undef VSYSCALL_VIRT_ADDR
+#undef VLOAD_OFFSET
+#undef VLOAD
+#undef VVIRT_OFFSET
+#undef VVIRT
+
+#endif /* CONFIG_X86_64 */
+
+ /* init_task */
+ . = ALIGN(THREAD_SIZE);
+ .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
+ *(.data.init_task)
+ }
+#ifdef CONFIG_X86_64
+ :data.init
+#endif
+
+ /*
+ * smp_locks might be freed after init
+ * start/end must be page aligned
+ */
+ . = ALIGN(PAGE_SIZE);
+ .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
+ __smp_locks = .;
+ *(.smp_locks)
+ __smp_locks_end = .;
+ . = ALIGN(PAGE_SIZE);
+ }
+
+ /* Init code and data - will be freed after init */
+ . = ALIGN(PAGE_SIZE);
+ .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
+ __init_begin = .; /* paired with __init_end */
+ _sinittext = .;
+ INIT_TEXT
+ _einittext = .;
+ }
+
+ .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
+ INIT_DATA
+ }
+
+ . = ALIGN(16);
+ .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
+ __setup_start = .;
+ *(.init.setup)
+ __setup_end = .;
+ }
+ .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
+ __initcall_start = .;
+ INITCALLS
+ __initcall_end = .;
+ }
+
+ .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
+ __con_initcall_start = .;
+ *(.con_initcall.init)
+ __con_initcall_end = .;
+ }
+
+ .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) {
+ __x86_cpu_dev_start = .;
+ *(.x86_cpu_dev.init)
+ __x86_cpu_dev_end = .;
+ }
+
+ SECURITY_INIT
+
+ . = ALIGN(8);
+ .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) {
+ __parainstructions = .;
+ *(.parainstructions)
+ __parainstructions_end = .;
+ }
+
+ . = ALIGN(8);
+ .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
+ __alt_instructions = .;
+ *(.altinstructions)
+ __alt_instructions_end = .;
+ }
+
+ .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
+ *(.altinstr_replacement)
+ }
+
+ /*
+ * .exit.text is discard at runtime, not link time, to deal with
+ * references from .altinstructions and .eh_frame
+ */
+ .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) {
+ EXIT_TEXT
+ }
+
+ .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) {
+ EXIT_DATA
+ }
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ . = ALIGN(PAGE_SIZE);
+ .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
+ __initramfs_start = .;
+ *(.init.ramfs)
+ __initramfs_end = .;
+ }
+#endif
+
+#if defined(CONFIG_X86_64) && defined(CONFIG_SMP)
+ /*
+ * percpu offsets are zero-based on SMP. PERCPU_VADDR() changes the
+ * output PHDR, so the next output section - __data_nosave - should
+ * start another section data.init2. Also, pda should be at the head of
+ * percpu area. Preallocate it and define the percpu offset symbol
+ * so that it can be accessed as a percpu variable.
+ */
+ . = ALIGN(PAGE_SIZE);
+ PERCPU_VADDR(0, :percpu)
+#else
+ PERCPU(PAGE_SIZE)
+#endif
+
+ . = ALIGN(PAGE_SIZE);
+
+ /* freed after init ends here */
+ .init.end : AT(ADDR(.init.end) - LOAD_OFFSET) {
+ __init_end = .;
+ }
+
+#ifdef CONFIG_X86_64
+ .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
+ . = ALIGN(PAGE_SIZE);
+ __nosave_begin = .;
+ *(.data.nosave)
+ . = ALIGN(PAGE_SIZE);
+ __nosave_end = .;
+ } :data.init2
+ /* use another section data.init2, see PERCPU_VADDR() above */
+#endif
+
+ /* BSS */
+ . = ALIGN(PAGE_SIZE);
+ .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
+ __bss_start = .;
+ *(.bss.page_aligned)
+ *(.bss)
+ . = ALIGN(4);
+ __bss_stop = .;
+ }
+
+ . = ALIGN(PAGE_SIZE);
+ .brk : AT(ADDR(.brk) - LOAD_OFFSET) {
+ __brk_base = .;
+ . += 64 * 1024; /* 64k alignment slop space */
+ *(.brk_reservation) /* areas brk users have reserved */
+ __brk_limit = .;
+ }
+
+ .end : AT(ADDR(.end) - LOAD_OFFSET) {
+ _end = .;
+ }
+
+ /* Sections to be discarded */
+ /DISCARD/ : {
+ *(.exitcall.exit)
+ *(.eh_frame)
+ *(.discard)
+ }
+
+ STABS_DEBUG
+ DWARF_DEBUG
+}
+
+
+#ifdef CONFIG_X86_32
+ASSERT((_end - LOAD_OFFSET <= KERNEL_IMAGE_SIZE),
+ "kernel image bigger than KERNEL_IMAGE_SIZE")
+#else
+/*
+ * Per-cpu symbols which need to be offset from __per_cpu_load
+ * for the boot processor.
+ */
+#define INIT_PER_CPU(x) init_per_cpu__##x = per_cpu__##x + __per_cpu_load
+INIT_PER_CPU(gdt_page);
+INIT_PER_CPU(irq_stack_union);
+
+/*
+ * Build-time check on the image size:
+ */
+ASSERT((_end - _text <= KERNEL_IMAGE_SIZE),
+ "kernel image bigger than KERNEL_IMAGE_SIZE")
+
+#ifdef CONFIG_SMP
+ASSERT((per_cpu__irq_stack_union == 0),
+ "irq_stack_union is not at start of per-cpu area");
+#endif
+
+#endif /* CONFIG_X86_32 */
+
+#ifdef CONFIG_KEXEC
+#include <asm/kexec.h>
+
+ASSERT(kexec_control_code_size <= KEXEC_CONTROL_CODE_MAX_SIZE,
+ "kexec control code size is too big")
+#endif
+
diff --git a/arch/x86/kernel/vmlinux_32.lds.S b/arch/x86/kernel/vmlinux_32.lds.S
deleted file mode 100644
index 62ad500d55f3..000000000000
--- a/arch/x86/kernel/vmlinux_32.lds.S
+++ /dev/null
@@ -1,229 +0,0 @@
-/* ld script to make i386 Linux kernel
- * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
- *
- * Don't define absolute symbols until and unless you know that symbol
- * value is should remain constant even if kernel image is relocated
- * at run time. Absolute symbols are not relocated. If symbol value should
- * change if kernel is relocated, make the symbol section relative and
- * put it inside the section definition.
- */
-
-#define LOAD_OFFSET __PAGE_OFFSET
-
-#include <asm-generic/vmlinux.lds.h>
-#include <asm/thread_info.h>
-#include <asm/page_types.h>
-#include <asm/cache.h>
-#include <asm/boot.h>
-
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH(i386)
-ENTRY(phys_startup_32)
-jiffies = jiffies_64;
-
-PHDRS {
- text PT_LOAD FLAGS(5); /* R_E */
- data PT_LOAD FLAGS(7); /* RWE */
- note PT_NOTE FLAGS(0); /* ___ */
-}
-SECTIONS
-{
- . = LOAD_OFFSET + LOAD_PHYSICAL_ADDR;
- phys_startup_32 = startup_32 - LOAD_OFFSET;
-
- .text.head : AT(ADDR(.text.head) - LOAD_OFFSET) {
- _text = .; /* Text and read-only data */
- *(.text.head)
- } :text = 0x9090
-
- /* read-only */
- .text : AT(ADDR(.text) - LOAD_OFFSET) {
- . = ALIGN(PAGE_SIZE); /* not really needed, already page aligned */
- *(.text.page_aligned)
- TEXT_TEXT
- SCHED_TEXT
- LOCK_TEXT
- KPROBES_TEXT
- IRQENTRY_TEXT
- *(.fixup)
- *(.gnu.warning)
- _etext = .; /* End of text section */
- } :text = 0x9090
-
- NOTES :text :note
-
- . = ALIGN(16); /* Exception table */
- __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
- __start___ex_table = .;
- *(__ex_table)
- __stop___ex_table = .;
- } :text = 0x9090
-
- RODATA
-
- /* writeable */
- . = ALIGN(PAGE_SIZE);
- .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */
- DATA_DATA
- CONSTRUCTORS
- } :data
-
- . = ALIGN(PAGE_SIZE);
- .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
- __nosave_begin = .;
- *(.data.nosave)
- . = ALIGN(PAGE_SIZE);
- __nosave_end = .;
- }
-
- . = ALIGN(PAGE_SIZE);
- .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
- *(.data.page_aligned)
- *(.data.idt)
- }
-
- . = ALIGN(32);
- .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
- *(.data.cacheline_aligned)
- }
-
- /* rarely changed data like cpu maps */
- . = ALIGN(32);
- .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) {
- *(.data.read_mostly)
- _edata = .; /* End of data section */
- }
-
- . = ALIGN(THREAD_SIZE); /* init_task */
- .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
- *(.data.init_task)
- }
-
- /* might get freed after init */
- . = ALIGN(PAGE_SIZE);
- .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
- __smp_locks = .;
- *(.smp_locks)
- __smp_locks_end = .;
- }
- /* will be freed after init
- * Following ALIGN() is required to make sure no other data falls on the
- * same page where __smp_alt_end is pointing as that page might be freed
- * after boot. Always make sure that ALIGN() directive is present after
- * the section which contains __smp_alt_end.
- */
- . = ALIGN(PAGE_SIZE);
-
- /* will be freed after init */
- . = ALIGN(PAGE_SIZE); /* Init code and data */
- .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
- __init_begin = .;
- _sinittext = .;
- INIT_TEXT
- _einittext = .;
- }
- .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
- INIT_DATA
- }
- . = ALIGN(16);
- .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
- __setup_start = .;
- *(.init.setup)
- __setup_end = .;
- }
- .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
- __initcall_start = .;
- INITCALLS
- __initcall_end = .;
- }
- .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
- __con_initcall_start = .;
- *(.con_initcall.init)
- __con_initcall_end = .;
- }
- .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) {
- __x86_cpu_dev_start = .;
- *(.x86_cpu_dev.init)
- __x86_cpu_dev_end = .;
- }
- SECURITY_INIT
- . = ALIGN(4);
- .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
- __alt_instructions = .;
- *(.altinstructions)
- __alt_instructions_end = .;
- }
- .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
- *(.altinstr_replacement)
- }
- . = ALIGN(4);
- .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) {
- __parainstructions = .;
- *(.parainstructions)
- __parainstructions_end = .;
- }
- /* .exit.text is discard at runtime, not link time, to deal with references
- from .altinstructions and .eh_frame */
- .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) {
- EXIT_TEXT
- }
- .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) {
- EXIT_DATA
- }
-#if defined(CONFIG_BLK_DEV_INITRD)
- . = ALIGN(PAGE_SIZE);
- .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
- __initramfs_start = .;
- *(.init.ramfs)
- __initramfs_end = .;
- }
-#endif
- PERCPU(PAGE_SIZE)
- . = ALIGN(PAGE_SIZE);
- /* freed after init ends here */
-
- .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
- __init_end = .;
- __bss_start = .; /* BSS */
- *(.bss.page_aligned)
- *(.bss)
- . = ALIGN(4);
- __bss_stop = .;
- }
-
- .brk : AT(ADDR(.brk) - LOAD_OFFSET) {
- . = ALIGN(PAGE_SIZE);
- __brk_base = . ;
- . += 64 * 1024 ; /* 64k alignment slop space */
- *(.brk_reservation) /* areas brk users have reserved */
- __brk_limit = . ;
- }
-
- .end : AT(ADDR(.end) - LOAD_OFFSET) {
- _end = . ;
- }
-
- /* Sections to be discarded */
- /DISCARD/ : {
- *(.exitcall.exit)
- *(.discard)
- }
-
- STABS_DEBUG
-
- DWARF_DEBUG
-}
-
-/*
- * Build-time check on the image size:
- */
-ASSERT((_end - LOAD_OFFSET <= KERNEL_IMAGE_SIZE),
- "kernel image bigger than KERNEL_IMAGE_SIZE")
-
-#ifdef CONFIG_KEXEC
-/* Link time checks */
-#include <asm/kexec.h>
-
-ASSERT(kexec_control_code_size <= KEXEC_CONTROL_CODE_MAX_SIZE,
- "kexec control code size is too big")
-#endif
diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S
deleted file mode 100644
index c8742507b030..000000000000
--- a/arch/x86/kernel/vmlinux_64.lds.S
+++ /dev/null
@@ -1,298 +0,0 @@
-/* ld script to make x86-64 Linux kernel
- * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
- */
-
-#define LOAD_OFFSET __START_KERNEL_map
-
-#include <asm-generic/vmlinux.lds.h>
-#include <asm/asm-offsets.h>
-#include <asm/page_types.h>
-
-#undef i386 /* in case the preprocessor is a 32bit one */
-
-OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
-OUTPUT_ARCH(i386:x86-64)
-ENTRY(phys_startup_64)
-jiffies_64 = jiffies;
-PHDRS {
- text PT_LOAD FLAGS(5); /* R_E */
- data PT_LOAD FLAGS(7); /* RWE */
- user PT_LOAD FLAGS(7); /* RWE */
- data.init PT_LOAD FLAGS(7); /* RWE */
-#ifdef CONFIG_SMP
- percpu PT_LOAD FLAGS(7); /* RWE */
-#endif
- data.init2 PT_LOAD FLAGS(7); /* RWE */
- note PT_NOTE FLAGS(0); /* ___ */
-}
-SECTIONS
-{
- . = __START_KERNEL;
- phys_startup_64 = startup_64 - LOAD_OFFSET;
- .text : AT(ADDR(.text) - LOAD_OFFSET) {
- _text = .; /* Text and read-only data */
- /* First the code that has to be first for bootstrapping */
- *(.text.head)
- _stext = .;
- /* Then the rest */
- TEXT_TEXT
- SCHED_TEXT
- LOCK_TEXT
- KPROBES_TEXT
- IRQENTRY_TEXT
- *(.fixup)
- *(.gnu.warning)
- _etext = .; /* End of text section */
- } :text = 0x9090
-
- NOTES :text :note
-
- . = ALIGN(16); /* Exception table */
- __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
- __start___ex_table = .;
- *(__ex_table)
- __stop___ex_table = .;
- } :text = 0x9090
-
- RODATA
-
- . = ALIGN(PAGE_SIZE); /* Align data segment to page size boundary */
- /* Data */
- .data : AT(ADDR(.data) - LOAD_OFFSET) {
- DATA_DATA
- CONSTRUCTORS
- _edata = .; /* End of data section */
- } :data
-
-
- .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
- . = ALIGN(PAGE_SIZE);
- . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
- *(.data.cacheline_aligned)
- }
- . = ALIGN(CONFIG_X86_INTERNODE_CACHE_BYTES);
- .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) {
- *(.data.read_mostly)
- }
-
-#define VSYSCALL_ADDR (-10*1024*1024)
-#define VSYSCALL_PHYS_ADDR ((LOADADDR(.data.read_mostly) + SIZEOF(.data.read_mostly) + 4095) & ~(4095))
-#define VSYSCALL_VIRT_ADDR ((ADDR(.data.read_mostly) + SIZEOF(.data.read_mostly) + 4095) & ~(4095))
-
-#define VLOAD_OFFSET (VSYSCALL_ADDR - VSYSCALL_PHYS_ADDR)
-#define VLOAD(x) (ADDR(x) - VLOAD_OFFSET)
-
-#define VVIRT_OFFSET (VSYSCALL_ADDR - VSYSCALL_VIRT_ADDR)
-#define VVIRT(x) (ADDR(x) - VVIRT_OFFSET)
-
- . = VSYSCALL_ADDR;
- .vsyscall_0 : AT(VSYSCALL_PHYS_ADDR) { *(.vsyscall_0) } :user
- __vsyscall_0 = VSYSCALL_VIRT_ADDR;
-
- . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
- .vsyscall_fn : AT(VLOAD(.vsyscall_fn)) { *(.vsyscall_fn) }
- . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
- .vsyscall_gtod_data : AT(VLOAD(.vsyscall_gtod_data))
- { *(.vsyscall_gtod_data) }
- vsyscall_gtod_data = VVIRT(.vsyscall_gtod_data);
- .vsyscall_clock : AT(VLOAD(.vsyscall_clock))
- { *(.vsyscall_clock) }
- vsyscall_clock = VVIRT(.vsyscall_clock);
-
-
- .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1))
- { *(.vsyscall_1) }
- .vsyscall_2 ADDR(.vsyscall_0) + 2048: AT(VLOAD(.vsyscall_2))
- { *(.vsyscall_2) }
-
- .vgetcpu_mode : AT(VLOAD(.vgetcpu_mode)) { *(.vgetcpu_mode) }
- vgetcpu_mode = VVIRT(.vgetcpu_mode);
-
- . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
- .jiffies : AT(VLOAD(.jiffies)) { *(.jiffies) }
- jiffies = VVIRT(.jiffies);
-
- .vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3))
- { *(.vsyscall_3) }
-
- . = VSYSCALL_VIRT_ADDR + PAGE_SIZE;
-
-#undef VSYSCALL_ADDR
-#undef VSYSCALL_PHYS_ADDR
-#undef VSYSCALL_VIRT_ADDR
-#undef VLOAD_OFFSET
-#undef VLOAD
-#undef VVIRT_OFFSET
-#undef VVIRT
-
- .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
- . = ALIGN(THREAD_SIZE); /* init_task */
- *(.data.init_task)
- }:data.init
-
- .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
- . = ALIGN(PAGE_SIZE);
- *(.data.page_aligned)
- }
-
- .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
- /* might get freed after init */
- . = ALIGN(PAGE_SIZE);
- __smp_alt_begin = .;
- __smp_locks = .;
- *(.smp_locks)
- __smp_locks_end = .;
- . = ALIGN(PAGE_SIZE);
- __smp_alt_end = .;
- }
-
- . = ALIGN(PAGE_SIZE); /* Init code and data */
- __init_begin = .; /* paired with __init_end */
- .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
- _sinittext = .;
- INIT_TEXT
- _einittext = .;
- }
- .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
- __initdata_begin = .;
- INIT_DATA
- __initdata_end = .;
- }
-
- .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
- . = ALIGN(16);
- __setup_start = .;
- *(.init.setup)
- __setup_end = .;
- }
- .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
- __initcall_start = .;
- INITCALLS
- __initcall_end = .;
- }
- .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
- __con_initcall_start = .;
- *(.con_initcall.init)
- __con_initcall_end = .;
- }
- .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) {
- __x86_cpu_dev_start = .;
- *(.x86_cpu_dev.init)
- __x86_cpu_dev_end = .;
- }
- SECURITY_INIT
-
- . = ALIGN(8);
- .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) {
- __parainstructions = .;
- *(.parainstructions)
- __parainstructions_end = .;
- }
-
- .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
- . = ALIGN(8);
- __alt_instructions = .;
- *(.altinstructions)
- __alt_instructions_end = .;
- }
- .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
- *(.altinstr_replacement)
- }
- /* .exit.text is discard at runtime, not link time, to deal with references
- from .altinstructions and .eh_frame */
- .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) {
- EXIT_TEXT
- }
- .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) {
- EXIT_DATA
- }
-
-#ifdef CONFIG_BLK_DEV_INITRD
- . = ALIGN(PAGE_SIZE);
- .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
- __initramfs_start = .;
- *(.init.ramfs)
- __initramfs_end = .;
- }
-#endif
-
-#ifdef CONFIG_SMP
- /*
- * percpu offsets are zero-based on SMP. PERCPU_VADDR() changes the
- * output PHDR, so the next output section - __data_nosave - should
- * start another section data.init2. Also, pda should be at the head of
- * percpu area. Preallocate it and define the percpu offset symbol
- * so that it can be accessed as a percpu variable.
- */
- . = ALIGN(PAGE_SIZE);
- PERCPU_VADDR(0, :percpu)
-#else
- PERCPU(PAGE_SIZE)
-#endif
-
- . = ALIGN(PAGE_SIZE);
- __init_end = .;
-
- .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
- . = ALIGN(PAGE_SIZE);
- __nosave_begin = .;
- *(.data.nosave)
- . = ALIGN(PAGE_SIZE);
- __nosave_end = .;
- } :data.init2 /* use another section data.init2, see PERCPU_VADDR() above */
-
- .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
- . = ALIGN(PAGE_SIZE);
- __bss_start = .; /* BSS */
- *(.bss.page_aligned)
- *(.bss)
- __bss_stop = .;
- }
-
- .brk : AT(ADDR(.brk) - LOAD_OFFSET) {
- . = ALIGN(PAGE_SIZE);
- __brk_base = . ;
- . += 64 * 1024 ; /* 64k alignment slop space */
- *(.brk_reservation) /* areas brk users have reserved */
- __brk_limit = . ;
- }
-
- _end = . ;
-
- /* Sections to be discarded */
- /DISCARD/ : {
- *(.exitcall.exit)
- *(.eh_frame)
- *(.discard)
- }
-
- STABS_DEBUG
-
- DWARF_DEBUG
-}
-
- /*
- * Per-cpu symbols which need to be offset from __per_cpu_load
- * for the boot processor.
- */
-#define INIT_PER_CPU(x) init_per_cpu__##x = per_cpu__##x + __per_cpu_load
-INIT_PER_CPU(gdt_page);
-INIT_PER_CPU(irq_stack_union);
-
-/*
- * Build-time check on the image size:
- */
-ASSERT((_end - _text <= KERNEL_IMAGE_SIZE),
- "kernel image bigger than KERNEL_IMAGE_SIZE")
-
-#ifdef CONFIG_SMP
-ASSERT((per_cpu__irq_stack_union == 0),
- "irq_stack_union is not at start of per-cpu area");
-#endif
-
-#ifdef CONFIG_KEXEC
-#include <asm/kexec.h>
-
-ASSERT(kexec_control_code_size <= KEXEC_CONTROL_CODE_MAX_SIZE,
- "kexec control code size is too big")
-#endif
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c
index 0a5b04aa98f1..c5ee17e8c6d9 100644
--- a/arch/x86/kernel/xsave.c
+++ b/arch/x86/kernel/xsave.c
@@ -89,7 +89,7 @@ int save_i387_xstate(void __user *buf)
if (!used_math())
return 0;
- clear_used_math(); /* trigger finit */
+
if (task_thread_info(tsk)->status & TS_USEDFPU) {
/*
* Start with clearing the user buffer. This will present a
@@ -114,6 +114,8 @@ int save_i387_xstate(void __user *buf)
return -1;
}
+ clear_used_math(); /* trigger finit */
+
if (task_thread_info(tsk)->status & TS_XSAVE) {
struct _fpstate __user *fx = buf;
struct _xstate __user *x = buf;
diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
index d3ec292f00f2..b43c4efafe80 100644
--- a/arch/x86/kvm/Makefile
+++ b/arch/x86/kvm/Makefile
@@ -14,7 +14,7 @@ endif
EXTRA_CFLAGS += -Ivirt/kvm -Iarch/x86/kvm
kvm-objs := $(common-objs) x86.o mmu.o x86_emulate.o i8259.o irq.o lapic.o \
- i8254.o
+ i8254.o timer.o
obj-$(CONFIG_KVM) += kvm.o
kvm-intel-objs = vmx.o
obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
index c13bb92d3157..4d6f0d293ee2 100644
--- a/arch/x86/kvm/i8254.c
+++ b/arch/x86/kvm/i8254.c
@@ -98,6 +98,37 @@ static int pit_get_gate(struct kvm *kvm, int channel)
return kvm->arch.vpit->pit_state.channels[channel].gate;
}
+static s64 __kpit_elapsed(struct kvm *kvm)
+{
+ s64 elapsed;
+ ktime_t remaining;
+ struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state;
+
+ /*
+ * The Counter does not stop when it reaches zero. In
+ * Modes 0, 1, 4, and 5 the Counter ``wraps around'' to
+ * the highest count, either FFFF hex for binary counting
+ * or 9999 for BCD counting, and continues counting.
+ * Modes 2 and 3 are periodic; the Counter reloads
+ * itself with the initial count and continues counting
+ * from there.
+ */
+ remaining = hrtimer_expires_remaining(&ps->pit_timer.timer);
+ elapsed = ps->pit_timer.period - ktime_to_ns(remaining);
+ elapsed = mod_64(elapsed, ps->pit_timer.period);
+
+ return elapsed;
+}
+
+static s64 kpit_elapsed(struct kvm *kvm, struct kvm_kpit_channel_state *c,
+ int channel)
+{
+ if (channel == 0)
+ return __kpit_elapsed(kvm);
+
+ return ktime_to_ns(ktime_sub(ktime_get(), c->count_load_time));
+}
+
static int pit_get_count(struct kvm *kvm, int channel)
{
struct kvm_kpit_channel_state *c =
@@ -107,7 +138,7 @@ static int pit_get_count(struct kvm *kvm, int channel)
WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
- t = ktime_to_ns(ktime_sub(ktime_get(), c->count_load_time));
+ t = kpit_elapsed(kvm, c, channel);
d = muldiv64(t, KVM_PIT_FREQ, NSEC_PER_SEC);
switch (c->mode) {
@@ -137,7 +168,7 @@ static int pit_get_out(struct kvm *kvm, int channel)
WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
- t = ktime_to_ns(ktime_sub(ktime_get(), c->count_load_time));
+ t = kpit_elapsed(kvm, c, channel);
d = muldiv64(t, KVM_PIT_FREQ, NSEC_PER_SEC);
switch (c->mode) {
@@ -193,28 +224,6 @@ static void pit_latch_status(struct kvm *kvm, int channel)
}
}
-static int __pit_timer_fn(struct kvm_kpit_state *ps)
-{
- struct kvm_vcpu *vcpu0 = ps->pit->kvm->vcpus[0];
- struct kvm_kpit_timer *pt = &ps->pit_timer;
-
- if (!atomic_inc_and_test(&pt->pending))
- set_bit(KVM_REQ_PENDING_TIMER, &vcpu0->requests);
-
- if (!pt->reinject)
- atomic_set(&pt->pending, 1);
-
- if (vcpu0 && waitqueue_active(&vcpu0->wq))
- wake_up_interruptible(&vcpu0->wq);
-
- hrtimer_add_expires_ns(&pt->timer, pt->period);
- pt->scheduled = hrtimer_get_expires_ns(&pt->timer);
- if (pt->period)
- ps->channels[0].count_load_time = ktime_get();
-
- return (pt->period == 0 ? 0 : 1);
-}
-
int pit_has_pending_timer(struct kvm_vcpu *vcpu)
{
struct kvm_pit *pit = vcpu->kvm->arch.vpit;
@@ -235,21 +244,6 @@ static void kvm_pit_ack_irq(struct kvm_irq_ack_notifier *kian)
spin_unlock(&ps->inject_lock);
}
-static enum hrtimer_restart pit_timer_fn(struct hrtimer *data)
-{
- struct kvm_kpit_state *ps;
- int restart_timer = 0;
-
- ps = container_of(data, struct kvm_kpit_state, pit_timer.timer);
-
- restart_timer = __pit_timer_fn(ps);
-
- if (restart_timer)
- return HRTIMER_RESTART;
- else
- return HRTIMER_NORESTART;
-}
-
void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu)
{
struct kvm_pit *pit = vcpu->kvm->arch.vpit;
@@ -263,15 +257,26 @@ void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu)
hrtimer_start_expires(timer, HRTIMER_MODE_ABS);
}
-static void destroy_pit_timer(struct kvm_kpit_timer *pt)
+static void destroy_pit_timer(struct kvm_timer *pt)
{
pr_debug("pit: execute del timer!\n");
hrtimer_cancel(&pt->timer);
}
+static bool kpit_is_periodic(struct kvm_timer *ktimer)
+{
+ struct kvm_kpit_state *ps = container_of(ktimer, struct kvm_kpit_state,
+ pit_timer);
+ return ps->is_periodic;
+}
+
+static struct kvm_timer_ops kpit_ops = {
+ .is_periodic = kpit_is_periodic,
+};
+
static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period)
{
- struct kvm_kpit_timer *pt = &ps->pit_timer;
+ struct kvm_timer *pt = &ps->pit_timer;
s64 interval;
interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ);
@@ -280,8 +285,14 @@ static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period)
/* TODO The new value only affected after the retriggered */
hrtimer_cancel(&pt->timer);
- pt->period = (is_period == 0) ? 0 : interval;
- pt->timer.function = pit_timer_fn;
+ pt->period = interval;
+ ps->is_periodic = is_period;
+
+ pt->timer.function = kvm_timer_fn;
+ pt->t_ops = &kpit_ops;
+ pt->kvm = ps->pit->kvm;
+ pt->vcpu_id = 0;
+
atomic_set(&pt->pending, 0);
ps->irq_ack = 1;
@@ -298,23 +309,23 @@ static void pit_load_count(struct kvm *kvm, int channel, u32 val)
pr_debug("pit: load_count val is %d, channel is %d\n", val, channel);
/*
- * Though spec said the state of 8254 is undefined after power-up,
- * seems some tricky OS like Windows XP depends on IRQ0 interrupt
- * when booting up.
- * So here setting initialize rate for it, and not a specific number
+ * The largest possible initial count is 0; this is equivalent
+ * to 216 for binary counting and 104 for BCD counting.
*/
if (val == 0)
val = 0x10000;
- ps->channels[channel].count_load_time = ktime_get();
ps->channels[channel].count = val;
- if (channel != 0)
+ if (channel != 0) {
+ ps->channels[channel].count_load_time = ktime_get();
return;
+ }
/* Two types of timer
* mode 1 is one shot, mode 2 is period, otherwise del timer */
switch (ps->channels[0].mode) {
+ case 0:
case 1:
/* FIXME: enhance mode 4 precision */
case 4:
diff --git a/arch/x86/kvm/i8254.h b/arch/x86/kvm/i8254.h
index 6acbe4b505d5..bbd863ff60b7 100644
--- a/arch/x86/kvm/i8254.h
+++ b/arch/x86/kvm/i8254.h
@@ -3,15 +3,6 @@
#include "iodev.h"
-struct kvm_kpit_timer {
- struct hrtimer timer;
- int irq;
- s64 period; /* unit: ns */
- s64 scheduled;
- atomic_t pending;
- bool reinject;
-};
-
struct kvm_kpit_channel_state {
u32 count; /* can be 65536 */
u16 latched_count;
@@ -30,7 +21,8 @@ struct kvm_kpit_channel_state {
struct kvm_kpit_state {
struct kvm_kpit_channel_state channels[3];
- struct kvm_kpit_timer pit_timer;
+ struct kvm_timer pit_timer;
+ bool is_periodic;
u32 speaker_data_on;
struct mutex lock;
struct kvm_pit *pit;
diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c
index cf17ed52f6fb..11c2757b808f 100644
--- a/arch/x86/kvm/irq.c
+++ b/arch/x86/kvm/irq.c
@@ -24,6 +24,7 @@
#include "irq.h"
#include "i8254.h"
+#include "x86.h"
/*
* check if there are pending timer events
@@ -48,6 +49,9 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *v)
{
struct kvm_pic *s;
+ if (!irqchip_in_kernel(v->kvm))
+ return v->arch.irq_summary;
+
if (kvm_apic_has_interrupt(v) == -1) { /* LAPIC */
if (kvm_apic_accept_pic_intr(v)) {
s = pic_irqchip(v->kvm); /* PIC */
@@ -67,6 +71,9 @@ int kvm_cpu_get_interrupt(struct kvm_vcpu *v)
struct kvm_pic *s;
int vector;
+ if (!irqchip_in_kernel(v->kvm))
+ return kvm_pop_irq(v);
+
vector = kvm_get_apic_interrupt(v); /* APIC */
if (vector == -1) {
if (kvm_apic_accept_pic_intr(v)) {
diff --git a/arch/x86/kvm/kvm_timer.h b/arch/x86/kvm/kvm_timer.h
new file mode 100644
index 000000000000..26bd6ba74e1c
--- /dev/null
+++ b/arch/x86/kvm/kvm_timer.h
@@ -0,0 +1,18 @@
+
+struct kvm_timer {
+ struct hrtimer timer;
+ s64 period; /* unit: ns */
+ atomic_t pending; /* accumulated triggered timers */
+ bool reinject;
+ struct kvm_timer_ops *t_ops;
+ struct kvm *kvm;
+ int vcpu_id;
+};
+
+struct kvm_timer_ops {
+ bool (*is_periodic)(struct kvm_timer *);
+};
+
+
+enum hrtimer_restart kvm_timer_fn(struct hrtimer *data);
+
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index f0b67f2cdd69..ae99d83f81a3 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -196,20 +196,15 @@ int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL_GPL(kvm_lapic_find_highest_irr);
-int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig)
+static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
+ int vector, int level, int trig_mode);
+
+int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq)
{
struct kvm_lapic *apic = vcpu->arch.apic;
- if (!apic_test_and_set_irr(vec, apic)) {
- /* a new pending irq is set in IRR */
- if (trig)
- apic_set_vector(vec, apic->regs + APIC_TMR);
- else
- apic_clear_vector(vec, apic->regs + APIC_TMR);
- kvm_vcpu_kick(apic->vcpu);
- return 1;
- }
- return 0;
+ return __apic_accept_irq(apic, irq->delivery_mode, irq->vector,
+ irq->level, irq->trig_mode);
}
static inline int apic_find_highest_isr(struct kvm_lapic *apic)
@@ -250,7 +245,7 @@ static void apic_set_tpr(struct kvm_lapic *apic, u32 tpr)
int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest)
{
- return kvm_apic_id(apic) == dest;
+ return dest == 0xff || kvm_apic_id(apic) == dest;
}
int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda)
@@ -279,37 +274,34 @@ int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda)
return result;
}
-static int apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
+int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
int short_hand, int dest, int dest_mode)
{
int result = 0;
struct kvm_lapic *target = vcpu->arch.apic;
apic_debug("target %p, source %p, dest 0x%x, "
- "dest_mode 0x%x, short_hand 0x%x",
+ "dest_mode 0x%x, short_hand 0x%x\n",
target, source, dest, dest_mode, short_hand);
ASSERT(!target);
switch (short_hand) {
case APIC_DEST_NOSHORT:
- if (dest_mode == 0) {
+ if (dest_mode == 0)
/* Physical mode. */
- if ((dest == 0xFF) || (dest == kvm_apic_id(target)))
- result = 1;
- } else
+ result = kvm_apic_match_physical_addr(target, dest);
+ else
/* Logical mode. */
result = kvm_apic_match_logical_addr(target, dest);
break;
case APIC_DEST_SELF:
- if (target == source)
- result = 1;
+ result = (target == source);
break;
case APIC_DEST_ALLINC:
result = 1;
break;
case APIC_DEST_ALLBUT:
- if (target != source)
- result = 1;
+ result = (target != source);
break;
default:
printk(KERN_WARNING "Bad dest shorthand value %x\n",
@@ -327,20 +319,22 @@ static int apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
int vector, int level, int trig_mode)
{
- int orig_irr, result = 0;
+ int result = 0;
struct kvm_vcpu *vcpu = apic->vcpu;
switch (delivery_mode) {
- case APIC_DM_FIXED:
case APIC_DM_LOWEST:
+ vcpu->arch.apic_arb_prio++;
+ case APIC_DM_FIXED:
/* FIXME add logic for vcpu on reset */
if (unlikely(!apic_enabled(apic)))
break;
- orig_irr = apic_test_and_set_irr(vector, apic);
- if (orig_irr && trig_mode) {
- apic_debug("level trig mode repeatedly for vector %d",
- vector);
+ result = !apic_test_and_set_irr(vector, apic);
+ if (!result) {
+ if (trig_mode)
+ apic_debug("level trig mode repeatedly for "
+ "vector %d", vector);
break;
}
@@ -349,10 +343,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
apic_set_vector(vector, apic->regs + APIC_TMR);
} else
apic_clear_vector(vector, apic->regs + APIC_TMR);
-
kvm_vcpu_kick(vcpu);
-
- result = (orig_irr == 0);
break;
case APIC_DM_REMRD:
@@ -364,12 +355,14 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
break;
case APIC_DM_NMI:
+ result = 1;
kvm_inject_nmi(vcpu);
kvm_vcpu_kick(vcpu);
break;
case APIC_DM_INIT:
if (level) {
+ result = 1;
if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE)
printk(KERN_DEBUG
"INIT on a runnable vcpu %d\n",
@@ -386,6 +379,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
apic_debug("SIPI to vcpu %d vector 0x%02x\n",
vcpu->vcpu_id, vector);
if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
+ result = 1;
vcpu->arch.sipi_vector = vector;
vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED;
kvm_vcpu_kick(vcpu);
@@ -408,43 +402,9 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
return result;
}
-static struct kvm_lapic *kvm_apic_round_robin(struct kvm *kvm, u8 vector,
- unsigned long bitmap)
-{
- int last;
- int next;
- struct kvm_lapic *apic = NULL;
-
- last = kvm->arch.round_robin_prev_vcpu;
- next = last;
-
- do {
- if (++next == KVM_MAX_VCPUS)
- next = 0;
- if (kvm->vcpus[next] == NULL || !test_bit(next, &bitmap))
- continue;
- apic = kvm->vcpus[next]->arch.apic;
- if (apic && apic_enabled(apic))
- break;
- apic = NULL;
- } while (next != last);
- kvm->arch.round_robin_prev_vcpu = next;
-
- if (!apic)
- printk(KERN_DEBUG "vcpu not ready for apic_round_robin\n");
-
- return apic;
-}
-
-struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
- unsigned long bitmap)
+int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2)
{
- struct kvm_lapic *apic;
-
- apic = kvm_apic_round_robin(kvm, vector, bitmap);
- if (apic)
- return apic->vcpu;
- return NULL;
+ return vcpu1->arch.apic_arb_prio - vcpu2->arch.apic_arb_prio;
}
static void apic_set_eoi(struct kvm_lapic *apic)
@@ -472,47 +432,24 @@ static void apic_send_ipi(struct kvm_lapic *apic)
{
u32 icr_low = apic_get_reg(apic, APIC_ICR);
u32 icr_high = apic_get_reg(apic, APIC_ICR2);
+ struct kvm_lapic_irq irq;
- unsigned int dest = GET_APIC_DEST_FIELD(icr_high);
- unsigned int short_hand = icr_low & APIC_SHORT_MASK;
- unsigned int trig_mode = icr_low & APIC_INT_LEVELTRIG;
- unsigned int level = icr_low & APIC_INT_ASSERT;
- unsigned int dest_mode = icr_low & APIC_DEST_MASK;
- unsigned int delivery_mode = icr_low & APIC_MODE_MASK;
- unsigned int vector = icr_low & APIC_VECTOR_MASK;
-
- struct kvm_vcpu *target;
- struct kvm_vcpu *vcpu;
- unsigned long lpr_map = 0;
- int i;
+ irq.vector = icr_low & APIC_VECTOR_MASK;
+ irq.delivery_mode = icr_low & APIC_MODE_MASK;
+ irq.dest_mode = icr_low & APIC_DEST_MASK;
+ irq.level = icr_low & APIC_INT_ASSERT;
+ irq.trig_mode = icr_low & APIC_INT_LEVELTRIG;
+ irq.shorthand = icr_low & APIC_SHORT_MASK;
+ irq.dest_id = GET_APIC_DEST_FIELD(icr_high);
apic_debug("icr_high 0x%x, icr_low 0x%x, "
"short_hand 0x%x, dest 0x%x, trig_mode 0x%x, level 0x%x, "
"dest_mode 0x%x, delivery_mode 0x%x, vector 0x%x\n",
- icr_high, icr_low, short_hand, dest,
- trig_mode, level, dest_mode, delivery_mode, vector);
-
- for (i = 0; i < KVM_MAX_VCPUS; i++) {
- vcpu = apic->vcpu->kvm->vcpus[i];
- if (!vcpu)
- continue;
-
- if (vcpu->arch.apic &&
- apic_match_dest(vcpu, apic, short_hand, dest, dest_mode)) {
- if (delivery_mode == APIC_DM_LOWEST)
- set_bit(vcpu->vcpu_id, &lpr_map);
- else
- __apic_accept_irq(vcpu->arch.apic, delivery_mode,
- vector, level, trig_mode);
- }
- }
+ icr_high, icr_low, irq.shorthand, irq.dest_id,
+ irq.trig_mode, irq.level, irq.dest_mode, irq.delivery_mode,
+ irq.vector);
- if (delivery_mode == APIC_DM_LOWEST) {
- target = kvm_get_lowest_prio_vcpu(vcpu->kvm, vector, lpr_map);
- if (target != NULL)
- __apic_accept_irq(target->arch.apic, delivery_mode,
- vector, level, trig_mode);
- }
+ kvm_irq_delivery_to_apic(apic->vcpu->kvm, apic, &irq);
}
static u32 apic_get_tmcct(struct kvm_lapic *apic)
@@ -527,12 +464,13 @@ static u32 apic_get_tmcct(struct kvm_lapic *apic)
if (apic_get_reg(apic, APIC_TMICT) == 0)
return 0;
- remaining = hrtimer_expires_remaining(&apic->timer.dev);
+ remaining = hrtimer_expires_remaining(&apic->lapic_timer.timer);
if (ktime_to_ns(remaining) < 0)
remaining = ktime_set(0, 0);
- ns = mod_64(ktime_to_ns(remaining), apic->timer.period);
- tmcct = div64_u64(ns, (APIC_BUS_CYCLE_NS * apic->timer.divide_count));
+ ns = mod_64(ktime_to_ns(remaining), apic->lapic_timer.period);
+ tmcct = div64_u64(ns,
+ (APIC_BUS_CYCLE_NS * apic->divide_count));
return tmcct;
}
@@ -619,25 +557,25 @@ static void update_divide_count(struct kvm_lapic *apic)
tdcr = apic_get_reg(apic, APIC_TDCR);
tmp1 = tdcr & 0xf;
tmp2 = ((tmp1 & 0x3) | ((tmp1 & 0x8) >> 1)) + 1;
- apic->timer.divide_count = 0x1 << (tmp2 & 0x7);
+ apic->divide_count = 0x1 << (tmp2 & 0x7);
apic_debug("timer divide count is 0x%x\n",
- apic->timer.divide_count);
+ apic->divide_count);
}
static void start_apic_timer(struct kvm_lapic *apic)
{
- ktime_t now = apic->timer.dev.base->get_time();
+ ktime_t now = apic->lapic_timer.timer.base->get_time();
- apic->timer.period = apic_get_reg(apic, APIC_TMICT) *
- APIC_BUS_CYCLE_NS * apic->timer.divide_count;
- atomic_set(&apic->timer.pending, 0);
+ apic->lapic_timer.period = apic_get_reg(apic, APIC_TMICT) *
+ APIC_BUS_CYCLE_NS * apic->divide_count;
+ atomic_set(&apic->lapic_timer.pending, 0);
- if (!apic->timer.period)
+ if (!apic->lapic_timer.period)
return;
- hrtimer_start(&apic->timer.dev,
- ktime_add_ns(now, apic->timer.period),
+ hrtimer_start(&apic->lapic_timer.timer,
+ ktime_add_ns(now, apic->lapic_timer.period),
HRTIMER_MODE_ABS);
apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
@@ -646,9 +584,9 @@ static void start_apic_timer(struct kvm_lapic *apic)
"expire @ 0x%016" PRIx64 ".\n", __func__,
APIC_BUS_CYCLE_NS, ktime_to_ns(now),
apic_get_reg(apic, APIC_TMICT),
- apic->timer.period,
+ apic->lapic_timer.period,
ktime_to_ns(ktime_add_ns(now,
- apic->timer.period)));
+ apic->lapic_timer.period)));
}
static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val)
@@ -730,7 +668,7 @@ static void apic_mmio_write(struct kvm_io_device *this,
apic_set_reg(apic, APIC_LVTT + 0x10 * i,
lvt_val | APIC_LVT_MASKED);
}
- atomic_set(&apic->timer.pending, 0);
+ atomic_set(&apic->lapic_timer.pending, 0);
}
break;
@@ -762,7 +700,7 @@ static void apic_mmio_write(struct kvm_io_device *this,
break;
case APIC_TMICT:
- hrtimer_cancel(&apic->timer.dev);
+ hrtimer_cancel(&apic->lapic_timer.timer);
apic_set_reg(apic, APIC_TMICT, val);
start_apic_timer(apic);
return;
@@ -802,7 +740,7 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu)
if (!vcpu->arch.apic)
return;
- hrtimer_cancel(&vcpu->arch.apic->timer.dev);
+ hrtimer_cancel(&vcpu->arch.apic->lapic_timer.timer);
if (vcpu->arch.apic->regs_page)
__free_page(vcpu->arch.apic->regs_page);
@@ -880,7 +818,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
ASSERT(apic != NULL);
/* Stop the timer in case it's a reset to an active apic */
- hrtimer_cancel(&apic->timer.dev);
+ hrtimer_cancel(&apic->lapic_timer.timer);
apic_set_reg(apic, APIC_ID, vcpu->vcpu_id << 24);
apic_set_reg(apic, APIC_LVR, APIC_VERSION);
@@ -905,11 +843,13 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
apic_set_reg(apic, APIC_TMR + 0x10 * i, 0);
}
update_divide_count(apic);
- atomic_set(&apic->timer.pending, 0);
+ atomic_set(&apic->lapic_timer.pending, 0);
if (vcpu->vcpu_id == 0)
vcpu->arch.apic_base |= MSR_IA32_APICBASE_BSP;
apic_update_ppr(apic);
+ vcpu->arch.apic_arb_prio = 0;
+
apic_debug(KERN_INFO "%s: vcpu=%p, id=%d, base_msr="
"0x%016" PRIx64 ", base_address=0x%0lx.\n", __func__,
vcpu, kvm_apic_id(apic),
@@ -917,16 +857,14 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL_GPL(kvm_lapic_reset);
-int kvm_lapic_enabled(struct kvm_vcpu *vcpu)
+bool kvm_apic_present(struct kvm_vcpu *vcpu)
{
- struct kvm_lapic *apic = vcpu->arch.apic;
- int ret = 0;
-
- if (!apic)
- return 0;
- ret = apic_enabled(apic);
+ return vcpu->arch.apic && apic_hw_enabled(vcpu->arch.apic);
+}
- return ret;
+int kvm_lapic_enabled(struct kvm_vcpu *vcpu)
+{
+ return kvm_apic_present(vcpu) && apic_sw_enabled(vcpu->arch.apic);
}
EXPORT_SYMBOL_GPL(kvm_lapic_enabled);
@@ -936,22 +874,11 @@ EXPORT_SYMBOL_GPL(kvm_lapic_enabled);
*----------------------------------------------------------------------
*/
-/* TODO: make sure __apic_timer_fn runs in current pCPU */
-static int __apic_timer_fn(struct kvm_lapic *apic)
+static bool lapic_is_periodic(struct kvm_timer *ktimer)
{
- int result = 0;
- wait_queue_head_t *q = &apic->vcpu->wq;
-
- if(!atomic_inc_and_test(&apic->timer.pending))
- set_bit(KVM_REQ_PENDING_TIMER, &apic->vcpu->requests);
- if (waitqueue_active(q))
- wake_up_interruptible(q);
-
- if (apic_lvtt_period(apic)) {
- result = 1;
- hrtimer_add_expires_ns(&apic->timer.dev, apic->timer.period);
- }
- return result;
+ struct kvm_lapic *apic = container_of(ktimer, struct kvm_lapic,
+ lapic_timer);
+ return apic_lvtt_period(apic);
}
int apic_has_pending_timer(struct kvm_vcpu *vcpu)
@@ -959,7 +886,7 @@ int apic_has_pending_timer(struct kvm_vcpu *vcpu)
struct kvm_lapic *lapic = vcpu->arch.apic;
if (lapic && apic_enabled(lapic) && apic_lvt_enabled(lapic, APIC_LVTT))
- return atomic_read(&lapic->timer.pending);
+ return atomic_read(&lapic->lapic_timer.pending);
return 0;
}
@@ -986,20 +913,9 @@ void kvm_apic_nmi_wd_deliver(struct kvm_vcpu *vcpu)
kvm_apic_local_deliver(apic, APIC_LVT0);
}
-static enum hrtimer_restart apic_timer_fn(struct hrtimer *data)
-{
- struct kvm_lapic *apic;
- int restart_timer = 0;
-
- apic = container_of(data, struct kvm_lapic, timer.dev);
-
- restart_timer = __apic_timer_fn(apic);
-
- if (restart_timer)
- return HRTIMER_RESTART;
- else
- return HRTIMER_NORESTART;
-}
+static struct kvm_timer_ops lapic_timer_ops = {
+ .is_periodic = lapic_is_periodic,
+};
int kvm_create_lapic(struct kvm_vcpu *vcpu)
{
@@ -1024,8 +940,13 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu)
memset(apic->regs, 0, PAGE_SIZE);
apic->vcpu = vcpu;
- hrtimer_init(&apic->timer.dev, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
- apic->timer.dev.function = apic_timer_fn;
+ hrtimer_init(&apic->lapic_timer.timer, CLOCK_MONOTONIC,
+ HRTIMER_MODE_ABS);
+ apic->lapic_timer.timer.function = kvm_timer_fn;
+ apic->lapic_timer.t_ops = &lapic_timer_ops;
+ apic->lapic_timer.kvm = vcpu->kvm;
+ apic->lapic_timer.vcpu_id = vcpu->vcpu_id;
+
apic->base_address = APIC_DEFAULT_PHYS_BASE;
vcpu->arch.apic_base = APIC_DEFAULT_PHYS_BASE;
@@ -1078,9 +999,9 @@ void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu)
{
struct kvm_lapic *apic = vcpu->arch.apic;
- if (apic && atomic_read(&apic->timer.pending) > 0) {
+ if (apic && atomic_read(&apic->lapic_timer.pending) > 0) {
if (kvm_apic_local_deliver(apic, APIC_LVTT))
- atomic_dec(&apic->timer.pending);
+ atomic_dec(&apic->lapic_timer.pending);
}
}
@@ -1106,7 +1027,7 @@ void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu)
MSR_IA32_APICBASE_BASE;
apic_set_reg(apic, APIC_LVR, APIC_VERSION);
apic_update_ppr(apic);
- hrtimer_cancel(&apic->timer.dev);
+ hrtimer_cancel(&apic->lapic_timer.timer);
update_divide_count(apic);
start_apic_timer(apic);
}
@@ -1119,7 +1040,7 @@ void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu)
if (!apic)
return;
- timer = &apic->timer.dev;
+ timer = &apic->lapic_timer.timer;
if (hrtimer_cancel(timer))
hrtimer_start_expires(timer, HRTIMER_MODE_ABS);
}
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 45ab6ee71209..a587f8349c46 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -2,18 +2,15 @@
#define __KVM_X86_LAPIC_H
#include "iodev.h"
+#include "kvm_timer.h"
#include <linux/kvm_host.h>
struct kvm_lapic {
unsigned long base_address;
struct kvm_io_device dev;
- struct {
- atomic_t pending;
- s64 period; /* unit: ns */
- u32 divide_count;
- struct hrtimer dev;
- } timer;
+ struct kvm_timer lapic_timer;
+ u32 divide_count;
struct kvm_vcpu *vcpu;
struct page *regs_page;
void *regs;
@@ -34,12 +31,13 @@ u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu);
int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
-int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig);
+int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq);
u64 kvm_get_apic_base(struct kvm_vcpu *vcpu);
void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data);
void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu);
int kvm_lapic_enabled(struct kvm_vcpu *vcpu);
+bool kvm_apic_present(struct kvm_vcpu *vcpu);
int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 2a36f7f7c4c7..8fcdae9660f4 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -126,6 +126,7 @@ module_param(oos_shadow, bool, 0644);
#define PFERR_PRESENT_MASK (1U << 0)
#define PFERR_WRITE_MASK (1U << 1)
#define PFERR_USER_MASK (1U << 2)
+#define PFERR_RSVD_MASK (1U << 3)
#define PFERR_FETCH_MASK (1U << 4)
#define PT_DIRECTORY_LEVEL 2
@@ -177,7 +178,11 @@ static u64 __read_mostly shadow_x_mask; /* mutual exclusive with nx_mask */
static u64 __read_mostly shadow_user_mask;
static u64 __read_mostly shadow_accessed_mask;
static u64 __read_mostly shadow_dirty_mask;
-static u64 __read_mostly shadow_mt_mask;
+
+static inline u64 rsvd_bits(int s, int e)
+{
+ return ((1ULL << (e - s + 1)) - 1) << s;
+}
void kvm_mmu_set_nonpresent_ptes(u64 trap_pte, u64 notrap_pte)
{
@@ -193,14 +198,13 @@ void kvm_mmu_set_base_ptes(u64 base_pte)
EXPORT_SYMBOL_GPL(kvm_mmu_set_base_ptes);
void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
- u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 mt_mask)
+ u64 dirty_mask, u64 nx_mask, u64 x_mask)
{
shadow_user_mask = user_mask;
shadow_accessed_mask = accessed_mask;
shadow_dirty_mask = dirty_mask;
shadow_nx_mask = nx_mask;
shadow_x_mask = x_mask;
- shadow_mt_mask = mt_mask;
}
EXPORT_SYMBOL_GPL(kvm_mmu_set_mask_ptes);
@@ -219,11 +223,6 @@ static int is_nx(struct kvm_vcpu *vcpu)
return vcpu->arch.shadow_efer & EFER_NX;
}
-static int is_present_pte(unsigned long pte)
-{
- return pte & PT_PRESENT_MASK;
-}
-
static int is_shadow_present_pte(u64 pte)
{
return pte != shadow_trap_nonpresent_pte
@@ -1074,18 +1073,10 @@ static struct kvm_mmu_page *kvm_mmu_lookup_page(struct kvm *kvm, gfn_t gfn)
return NULL;
}
-static void kvm_unlink_unsync_global(struct kvm *kvm, struct kvm_mmu_page *sp)
-{
- list_del(&sp->oos_link);
- --kvm->stat.mmu_unsync_global;
-}
-
static void kvm_unlink_unsync_page(struct kvm *kvm, struct kvm_mmu_page *sp)
{
WARN_ON(!sp->unsync);
sp->unsync = 0;
- if (sp->global)
- kvm_unlink_unsync_global(kvm, sp);
--kvm->stat.mmu_unsync;
}
@@ -1248,7 +1239,6 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
pgprintk("%s: adding gfn %lx role %x\n", __func__, gfn, role.word);
sp->gfn = gfn;
sp->role = role;
- sp->global = role.cr4_pge;
hlist_add_head(&sp->hash_link, bucket);
if (!direct) {
if (rmap_write_protect(vcpu->kvm, gfn))
@@ -1616,7 +1606,7 @@ static int get_mtrr_type(struct mtrr_state_type *mtrr_state,
return mtrr_state->def_type;
}
-static u8 get_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn)
+u8 kvm_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn)
{
u8 mtrr;
@@ -1626,6 +1616,7 @@ static u8 get_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn)
mtrr = MTRR_TYPE_WRBACK;
return mtrr;
}
+EXPORT_SYMBOL_GPL(kvm_get_guest_memory_type);
static int kvm_unsync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
{
@@ -1646,11 +1637,7 @@ static int kvm_unsync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
++vcpu->kvm->stat.mmu_unsync;
sp->unsync = 1;
- if (sp->global) {
- list_add(&sp->oos_link, &vcpu->kvm->arch.oos_global_pages);
- ++vcpu->kvm->stat.mmu_unsync_global;
- } else
- kvm_mmu_mark_parents_unsync(vcpu, sp);
+ kvm_mmu_mark_parents_unsync(vcpu, sp);
mmu_convert_notrap(sp);
return 0;
@@ -1677,21 +1664,11 @@ static int mmu_need_write_protect(struct kvm_vcpu *vcpu, gfn_t gfn,
static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
unsigned pte_access, int user_fault,
int write_fault, int dirty, int largepage,
- int global, gfn_t gfn, pfn_t pfn, bool speculative,
+ gfn_t gfn, pfn_t pfn, bool speculative,
bool can_unsync)
{
u64 spte;
int ret = 0;
- u64 mt_mask = shadow_mt_mask;
- struct kvm_mmu_page *sp = page_header(__pa(shadow_pte));
-
- if (!global && sp->global) {
- sp->global = 0;
- if (sp->unsync) {
- kvm_unlink_unsync_global(vcpu->kvm, sp);
- kvm_mmu_mark_parents_unsync(vcpu, sp);
- }
- }
/*
* We don't set the accessed bit, since we sometimes want to see
@@ -1711,16 +1688,9 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
spte |= shadow_user_mask;
if (largepage)
spte |= PT_PAGE_SIZE_MASK;
- if (mt_mask) {
- if (!kvm_is_mmio_pfn(pfn)) {
- mt_mask = get_memory_type(vcpu, gfn) <<
- kvm_x86_ops->get_mt_mask_shift();
- mt_mask |= VMX_EPT_IGMT_BIT;
- } else
- mt_mask = MTRR_TYPE_UNCACHABLE <<
- kvm_x86_ops->get_mt_mask_shift();
- spte |= mt_mask;
- }
+ if (tdp_enabled)
+ spte |= kvm_x86_ops->get_mt_mask(vcpu, gfn,
+ kvm_is_mmio_pfn(pfn));
spte |= (u64)pfn << PAGE_SHIFT;
@@ -1765,8 +1735,8 @@ set_pte:
static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
unsigned pt_access, unsigned pte_access,
int user_fault, int write_fault, int dirty,
- int *ptwrite, int largepage, int global,
- gfn_t gfn, pfn_t pfn, bool speculative)
+ int *ptwrite, int largepage, gfn_t gfn,
+ pfn_t pfn, bool speculative)
{
int was_rmapped = 0;
int was_writeble = is_writeble_pte(*shadow_pte);
@@ -1795,7 +1765,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
was_rmapped = 1;
}
if (set_spte(vcpu, shadow_pte, pte_access, user_fault, write_fault,
- dirty, largepage, global, gfn, pfn, speculative, true)) {
+ dirty, largepage, gfn, pfn, speculative, true)) {
if (write_fault)
*ptwrite = 1;
kvm_x86_ops->tlb_flush(vcpu);
@@ -1843,7 +1813,7 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,
|| (largepage && iterator.level == PT_DIRECTORY_LEVEL)) {
mmu_set_spte(vcpu, iterator.sptep, ACC_ALL, ACC_ALL,
0, write, 1, &pt_write,
- largepage, 0, gfn, pfn, false);
+ largepage, gfn, pfn, false);
++vcpu->stat.pf_fixed;
break;
}
@@ -2014,15 +1984,6 @@ static void mmu_sync_roots(struct kvm_vcpu *vcpu)
}
}
-static void mmu_sync_global(struct kvm_vcpu *vcpu)
-{
- struct kvm *kvm = vcpu->kvm;
- struct kvm_mmu_page *sp, *n;
-
- list_for_each_entry_safe(sp, n, &kvm->arch.oos_global_pages, oos_link)
- kvm_sync_page(vcpu, sp);
-}
-
void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu)
{
spin_lock(&vcpu->kvm->mmu_lock);
@@ -2030,13 +1991,6 @@ void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu)
spin_unlock(&vcpu->kvm->mmu_lock);
}
-void kvm_mmu_sync_global(struct kvm_vcpu *vcpu)
-{
- spin_lock(&vcpu->kvm->mmu_lock);
- mmu_sync_global(vcpu);
- spin_unlock(&vcpu->kvm->mmu_lock);
-}
-
static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr)
{
return vaddr;
@@ -2151,6 +2105,14 @@ static void paging_free(struct kvm_vcpu *vcpu)
nonpaging_free(vcpu);
}
+static bool is_rsvd_bits_set(struct kvm_vcpu *vcpu, u64 gpte, int level)
+{
+ int bit7;
+
+ bit7 = (gpte >> 7) & 1;
+ return (gpte & vcpu->arch.mmu.rsvd_bits_mask[bit7][level-1]) != 0;
+}
+
#define PTTYPE 64
#include "paging_tmpl.h"
#undef PTTYPE
@@ -2159,6 +2121,59 @@ static void paging_free(struct kvm_vcpu *vcpu)
#include "paging_tmpl.h"
#undef PTTYPE
+static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu, int level)
+{
+ struct kvm_mmu *context = &vcpu->arch.mmu;
+ int maxphyaddr = cpuid_maxphyaddr(vcpu);
+ u64 exb_bit_rsvd = 0;
+
+ if (!is_nx(vcpu))
+ exb_bit_rsvd = rsvd_bits(63, 63);
+ switch (level) {
+ case PT32_ROOT_LEVEL:
+ /* no rsvd bits for 2 level 4K page table entries */
+ context->rsvd_bits_mask[0][1] = 0;
+ context->rsvd_bits_mask[0][0] = 0;
+ if (is_cpuid_PSE36())
+ /* 36bits PSE 4MB page */
+ context->rsvd_bits_mask[1][1] = rsvd_bits(17, 21);
+ else
+ /* 32 bits PSE 4MB page */
+ context->rsvd_bits_mask[1][1] = rsvd_bits(13, 21);
+ context->rsvd_bits_mask[1][0] = ~0ull;
+ break;
+ case PT32E_ROOT_LEVEL:
+ context->rsvd_bits_mask[0][2] =
+ rsvd_bits(maxphyaddr, 63) |
+ rsvd_bits(7, 8) | rsvd_bits(1, 2); /* PDPTE */
+ context->rsvd_bits_mask[0][1] = exb_bit_rsvd |
+ rsvd_bits(maxphyaddr, 62); /* PDE */
+ context->rsvd_bits_mask[0][0] = exb_bit_rsvd |
+ rsvd_bits(maxphyaddr, 62); /* PTE */
+ context->rsvd_bits_mask[1][1] = exb_bit_rsvd |
+ rsvd_bits(maxphyaddr, 62) |
+ rsvd_bits(13, 20); /* large page */
+ context->rsvd_bits_mask[1][0] = ~0ull;
+ break;
+ case PT64_ROOT_LEVEL:
+ context->rsvd_bits_mask[0][3] = exb_bit_rsvd |
+ rsvd_bits(maxphyaddr, 51) | rsvd_bits(7, 8);
+ context->rsvd_bits_mask[0][2] = exb_bit_rsvd |
+ rsvd_bits(maxphyaddr, 51) | rsvd_bits(7, 8);
+ context->rsvd_bits_mask[0][1] = exb_bit_rsvd |
+ rsvd_bits(maxphyaddr, 51);
+ context->rsvd_bits_mask[0][0] = exb_bit_rsvd |
+ rsvd_bits(maxphyaddr, 51);
+ context->rsvd_bits_mask[1][3] = context->rsvd_bits_mask[0][3];
+ context->rsvd_bits_mask[1][2] = context->rsvd_bits_mask[0][2];
+ context->rsvd_bits_mask[1][1] = exb_bit_rsvd |
+ rsvd_bits(maxphyaddr, 51) |
+ rsvd_bits(13, 20); /* large page */
+ context->rsvd_bits_mask[1][0] = ~0ull;
+ break;
+ }
+}
+
static int paging64_init_context_common(struct kvm_vcpu *vcpu, int level)
{
struct kvm_mmu *context = &vcpu->arch.mmu;
@@ -2179,6 +2194,7 @@ static int paging64_init_context_common(struct kvm_vcpu *vcpu, int level)
static int paging64_init_context(struct kvm_vcpu *vcpu)
{
+ reset_rsvds_bits_mask(vcpu, PT64_ROOT_LEVEL);
return paging64_init_context_common(vcpu, PT64_ROOT_LEVEL);
}
@@ -2186,6 +2202,7 @@ static int paging32_init_context(struct kvm_vcpu *vcpu)
{
struct kvm_mmu *context = &vcpu->arch.mmu;
+ reset_rsvds_bits_mask(vcpu, PT32_ROOT_LEVEL);
context->new_cr3 = paging_new_cr3;
context->page_fault = paging32_page_fault;
context->gva_to_gpa = paging32_gva_to_gpa;
@@ -2201,6 +2218,7 @@ static int paging32_init_context(struct kvm_vcpu *vcpu)
static int paging32E_init_context(struct kvm_vcpu *vcpu)
{
+ reset_rsvds_bits_mask(vcpu, PT32E_ROOT_LEVEL);
return paging64_init_context_common(vcpu, PT32E_ROOT_LEVEL);
}
@@ -2221,12 +2239,15 @@ static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
context->gva_to_gpa = nonpaging_gva_to_gpa;
context->root_level = 0;
} else if (is_long_mode(vcpu)) {
+ reset_rsvds_bits_mask(vcpu, PT64_ROOT_LEVEL);
context->gva_to_gpa = paging64_gva_to_gpa;
context->root_level = PT64_ROOT_LEVEL;
} else if (is_pae(vcpu)) {
+ reset_rsvds_bits_mask(vcpu, PT32E_ROOT_LEVEL);
context->gva_to_gpa = paging64_gva_to_gpa;
context->root_level = PT32E_ROOT_LEVEL;
} else {
+ reset_rsvds_bits_mask(vcpu, PT32_ROOT_LEVEL);
context->gva_to_gpa = paging32_gva_to_gpa;
context->root_level = PT32_ROOT_LEVEL;
}
@@ -2638,14 +2659,6 @@ EXPORT_SYMBOL_GPL(kvm_disable_tdp);
static void free_mmu_pages(struct kvm_vcpu *vcpu)
{
- struct kvm_mmu_page *sp;
-
- while (!list_empty(&vcpu->kvm->arch.active_mmu_pages)) {
- sp = container_of(vcpu->kvm->arch.active_mmu_pages.next,
- struct kvm_mmu_page, link);
- kvm_mmu_zap_page(vcpu->kvm, sp);
- cond_resched();
- }
free_page((unsigned long)vcpu->arch.mmu.pae_root);
}
@@ -3008,11 +3021,13 @@ static void audit_mappings_page(struct kvm_vcpu *vcpu, u64 page_pte,
" in nonleaf level: levels %d gva %lx"
" level %d pte %llx\n", audit_msg,
vcpu->arch.mmu.root_level, va, level, ent);
-
- audit_mappings_page(vcpu, ent, va, level - 1);
+ else
+ audit_mappings_page(vcpu, ent, va, level - 1);
} else {
gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, va);
- hpa_t hpa = (hpa_t)gpa_to_pfn(vcpu, gpa) << PAGE_SHIFT;
+ gfn_t gfn = gpa >> PAGE_SHIFT;
+ pfn_t pfn = gfn_to_pfn(vcpu->kvm, gfn);
+ hpa_t hpa = (hpa_t)pfn << PAGE_SHIFT;
if (is_shadow_present_pte(ent)
&& (ent & PT64_BASE_ADDR_MASK) != hpa)
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index eaab2145f62b..3494a2fb136e 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -75,4 +75,9 @@ static inline int is_paging(struct kvm_vcpu *vcpu)
return vcpu->arch.cr0 & X86_CR0_PG;
}
+static inline int is_present_pte(unsigned long pte)
+{
+ return pte & PT_PRESENT_MASK;
+}
+
#endif
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 6bd70206c561..258e4591e1ca 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -123,6 +123,7 @@ static int FNAME(walk_addr)(struct guest_walker *walker,
gfn_t table_gfn;
unsigned index, pt_access, pte_access;
gpa_t pte_gpa;
+ int rsvd_fault = 0;
pgprintk("%s: addr %lx\n", __func__, addr);
walk:
@@ -157,6 +158,10 @@ walk:
if (!is_present_pte(pte))
goto not_present;
+ rsvd_fault = is_rsvd_bits_set(vcpu, pte, walker->level);
+ if (rsvd_fault)
+ goto access_error;
+
if (write_fault && !is_writeble_pte(pte))
if (user_fault || is_write_protection(vcpu))
goto access_error;
@@ -209,7 +214,6 @@ walk:
if (ret)
goto walk;
pte |= PT_DIRTY_MASK;
- kvm_mmu_pte_write(vcpu, pte_gpa, (u8 *)&pte, sizeof(pte), 0);
walker->ptes[walker->level - 1] = pte;
}
@@ -233,6 +237,8 @@ err:
walker->error_code |= PFERR_USER_MASK;
if (fetch_fault)
walker->error_code |= PFERR_FETCH_MASK;
+ if (rsvd_fault)
+ walker->error_code |= PFERR_RSVD_MASK;
return 0;
}
@@ -262,8 +268,7 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page,
kvm_get_pfn(pfn);
mmu_set_spte(vcpu, spte, page->role.access, pte_access, 0, 0,
gpte & PT_DIRTY_MASK, NULL, largepage,
- gpte & PT_GLOBAL_MASK, gpte_to_gfn(gpte),
- pfn, true);
+ gpte_to_gfn(gpte), pfn, true);
}
/*
@@ -297,7 +302,6 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
user_fault, write_fault,
gw->ptes[gw->level-1] & PT_DIRTY_MASK,
ptwrite, largepage,
- gw->ptes[gw->level-1] & PT_GLOBAL_MASK,
gw->gfn, pfn, false);
break;
}
@@ -380,7 +384,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
return r;
/*
- * Look up the shadow pte for the faulting address.
+ * Look up the guest pte for the faulting address.
*/
r = FNAME(walk_addr)(&walker, vcpu, addr, write_fault, user_fault,
fetch_fault);
@@ -586,7 +590,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
nr_present++;
pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte);
set_spte(vcpu, &sp->spt[i], pte_access, 0, 0,
- is_dirty_pte(gpte), 0, gpte & PT_GLOBAL_MASK, gfn,
+ is_dirty_pte(gpte), 0, gfn,
spte_to_pfn(sp->spt[i]), true, false);
}
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 1821c2078199..27d5b749ac69 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -19,6 +19,7 @@
#include "irq.h"
#include "mmu.h"
#include "kvm_cache_regs.h"
+#include "x86.h"
#include <linux/module.h>
#include <linux/kernel.h>
@@ -69,7 +70,6 @@ module_param(npt, int, S_IRUGO);
static int nested = 0;
module_param(nested, int, S_IRUGO);
-static void kvm_reput_irq(struct vcpu_svm *svm);
static void svm_flush_tlb(struct kvm_vcpu *vcpu);
static int nested_svm_exit_handled(struct vcpu_svm *svm, bool kvm_override);
@@ -132,24 +132,6 @@ static inline u32 svm_has(u32 feat)
return svm_features & feat;
}
-static inline u8 pop_irq(struct kvm_vcpu *vcpu)
-{
- int word_index = __ffs(vcpu->arch.irq_summary);
- int bit_index = __ffs(vcpu->arch.irq_pending[word_index]);
- int irq = word_index * BITS_PER_LONG + bit_index;
-
- clear_bit(bit_index, &vcpu->arch.irq_pending[word_index]);
- if (!vcpu->arch.irq_pending[word_index])
- clear_bit(word_index, &vcpu->arch.irq_summary);
- return irq;
-}
-
-static inline void push_irq(struct kvm_vcpu *vcpu, u8 irq)
-{
- set_bit(irq, vcpu->arch.irq_pending);
- set_bit(irq / BITS_PER_LONG, &vcpu->arch.irq_summary);
-}
-
static inline void clgi(void)
{
asm volatile (__ex(SVM_CLGI));
@@ -214,13 +196,6 @@ static void svm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
svm->vmcb->control.event_inj_err = error_code;
}
-static bool svm_exception_injected(struct kvm_vcpu *vcpu)
-{
- struct vcpu_svm *svm = to_svm(vcpu);
-
- return !(svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID);
-}
-
static int is_external_interrupt(u32 info)
{
info &= SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID;
@@ -241,8 +216,6 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
kvm_rip_write(vcpu, svm->next_rip);
svm->vmcb->control.int_state &= ~SVM_INTERRUPT_SHADOW_MASK;
-
- vcpu->arch.interrupt_window_open = (svm->vcpu.arch.hflags & HF_GIF_MASK);
}
static int has_svm(void)
@@ -796,6 +769,11 @@ static void svm_get_segment(struct kvm_vcpu *vcpu,
var->db = (s->attrib >> SVM_SELECTOR_DB_SHIFT) & 1;
var->g = (s->attrib >> SVM_SELECTOR_G_SHIFT) & 1;
+ /* AMD's VMCB does not have an explicit unusable field, so emulate it
+ * for cross vendor migration purposes by "not present"
+ */
+ var->unusable = !var->present || (var->type == 0);
+
switch (seg) {
case VCPU_SREG_CS:
/*
@@ -826,9 +804,16 @@ static void svm_get_segment(struct kvm_vcpu *vcpu,
if (!var->unusable)
var->type |= 0x1;
break;
+ case VCPU_SREG_SS:
+ /* On AMD CPUs sometimes the DB bit in the segment
+ * descriptor is left as 1, although the whole segment has
+ * been made unusable. Clear it here to pass an Intel VMX
+ * entry check when cross vendor migrating.
+ */
+ if (var->unusable)
+ var->db = 0;
+ break;
}
-
- var->unusable = !var->present;
}
static int svm_get_cpl(struct kvm_vcpu *vcpu)
@@ -991,16 +976,6 @@ static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg)
return 0;
}
-static int svm_get_irq(struct kvm_vcpu *vcpu)
-{
- struct vcpu_svm *svm = to_svm(vcpu);
- u32 exit_int_info = svm->vmcb->control.exit_int_info;
-
- if (is_external_interrupt(exit_int_info))
- return exit_int_info & SVM_EVTINJ_VEC_MASK;
- return -1;
-}
-
static void load_host_msrs(struct kvm_vcpu *vcpu)
{
#ifdef CONFIG_X86_64
@@ -1105,17 +1080,8 @@ static void svm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long value,
static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
{
- u32 exit_int_info = svm->vmcb->control.exit_int_info;
- struct kvm *kvm = svm->vcpu.kvm;
u64 fault_address;
u32 error_code;
- bool event_injection = false;
-
- if (!irqchip_in_kernel(kvm) &&
- is_external_interrupt(exit_int_info)) {
- event_injection = true;
- push_irq(&svm->vcpu, exit_int_info & SVM_EVTINJ_VEC_MASK);
- }
fault_address = svm->vmcb->control.exit_info_2;
error_code = svm->vmcb->control.exit_info_1;
@@ -1135,9 +1101,11 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
*/
if (npt_enabled)
svm_flush_tlb(&svm->vcpu);
-
- if (!npt_enabled && event_injection)
- kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address);
+ else {
+ if (svm->vcpu.arch.interrupt.pending ||
+ svm->vcpu.arch.exception.pending)
+ kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address);
+ }
return kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code);
}
@@ -1840,17 +1808,54 @@ static int task_switch_interception(struct vcpu_svm *svm,
struct kvm_run *kvm_run)
{
u16 tss_selector;
+ int reason;
+ int int_type = svm->vmcb->control.exit_int_info &
+ SVM_EXITINTINFO_TYPE_MASK;
+ int int_vec = svm->vmcb->control.exit_int_info & SVM_EVTINJ_VEC_MASK;
+ uint32_t type =
+ svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_TYPE_MASK;
+ uint32_t idt_v =
+ svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID;
tss_selector = (u16)svm->vmcb->control.exit_info_1;
+
if (svm->vmcb->control.exit_info_2 &
(1ULL << SVM_EXITINFOSHIFT_TS_REASON_IRET))
- return kvm_task_switch(&svm->vcpu, tss_selector,
- TASK_SWITCH_IRET);
- if (svm->vmcb->control.exit_info_2 &
- (1ULL << SVM_EXITINFOSHIFT_TS_REASON_JMP))
- return kvm_task_switch(&svm->vcpu, tss_selector,
- TASK_SWITCH_JMP);
- return kvm_task_switch(&svm->vcpu, tss_selector, TASK_SWITCH_CALL);
+ reason = TASK_SWITCH_IRET;
+ else if (svm->vmcb->control.exit_info_2 &
+ (1ULL << SVM_EXITINFOSHIFT_TS_REASON_JMP))
+ reason = TASK_SWITCH_JMP;
+ else if (idt_v)
+ reason = TASK_SWITCH_GATE;
+ else
+ reason = TASK_SWITCH_CALL;
+
+ if (reason == TASK_SWITCH_GATE) {
+ switch (type) {
+ case SVM_EXITINTINFO_TYPE_NMI:
+ svm->vcpu.arch.nmi_injected = false;
+ break;
+ case SVM_EXITINTINFO_TYPE_EXEPT:
+ kvm_clear_exception_queue(&svm->vcpu);
+ break;
+ case SVM_EXITINTINFO_TYPE_INTR:
+ kvm_clear_interrupt_queue(&svm->vcpu);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (reason != TASK_SWITCH_GATE ||
+ int_type == SVM_EXITINTINFO_TYPE_SOFT ||
+ (int_type == SVM_EXITINTINFO_TYPE_EXEPT &&
+ (int_vec == OF_VECTOR || int_vec == BP_VECTOR))) {
+ if (emulate_instruction(&svm->vcpu, kvm_run, 0, 0,
+ EMULTYPE_SKIP) != EMULATE_DONE)
+ return 0;
+ }
+
+ return kvm_task_switch(&svm->vcpu, tss_selector, reason);
}
static int cpuid_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
@@ -1860,6 +1865,14 @@ static int cpuid_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
return 1;
}
+static int iret_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
+{
+ ++svm->vcpu.stat.nmi_window_exits;
+ svm->vmcb->control.intercept &= ~(1UL << INTERCEPT_IRET);
+ svm->vcpu.arch.hflags &= ~HF_NMI_MASK;
+ return 1;
+}
+
static int invlpg_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
{
if (emulate_instruction(&svm->vcpu, kvm_run, 0, 0, 0) != EMULATE_DONE)
@@ -1877,8 +1890,14 @@ static int emulate_on_interception(struct vcpu_svm *svm,
static int cr8_write_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
{
+ u8 cr8_prev = kvm_get_cr8(&svm->vcpu);
+ /* instruction emulation calls kvm_set_cr8() */
emulate_instruction(&svm->vcpu, NULL, 0, 0, 0);
- if (irqchip_in_kernel(svm->vcpu.kvm))
+ if (irqchip_in_kernel(svm->vcpu.kvm)) {
+ svm->vmcb->control.intercept_cr_write &= ~INTERCEPT_CR8_MASK;
+ return 1;
+ }
+ if (cr8_prev <= kvm_get_cr8(&svm->vcpu))
return 1;
kvm_run->exit_reason = KVM_EXIT_SET_TPR;
return 0;
@@ -2088,8 +2107,9 @@ static int interrupt_window_interception(struct vcpu_svm *svm,
* If the user space waits to inject interrupts, exit as soon as
* possible
*/
- if (kvm_run->request_interrupt_window &&
- !svm->vcpu.arch.irq_summary) {
+ if (!irqchip_in_kernel(svm->vcpu.kvm) &&
+ kvm_run->request_interrupt_window &&
+ !kvm_cpu_has_interrupt(&svm->vcpu)) {
++svm->vcpu.stat.irq_window_exits;
kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
return 0;
@@ -2132,6 +2152,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_IRET] = iret_interception,
[SVM_EXIT_INVD] = emulate_on_interception,
[SVM_EXIT_HLT] = halt_interception,
[SVM_EXIT_INVLPG] = invlpg_interception,
@@ -2192,7 +2213,6 @@ static int handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
}
}
- kvm_reput_irq(svm);
if (svm->vmcb->control.exit_code == SVM_EXIT_ERR) {
kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
@@ -2203,7 +2223,7 @@ static int handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
if (is_external_interrupt(svm->vmcb->control.exit_int_info) &&
exit_code != SVM_EXIT_EXCP_BASE + PF_VECTOR &&
- exit_code != SVM_EXIT_NPF)
+ exit_code != SVM_EXIT_NPF && exit_code != SVM_EXIT_TASK_SWITCH)
printk(KERN_ERR "%s: unexpected exit_ini_info 0x%x "
"exit_code 0x%x\n",
__func__, svm->vmcb->control.exit_int_info,
@@ -2240,6 +2260,21 @@ static void pre_svm_run(struct vcpu_svm *svm)
new_asid(svm, svm_data);
}
+static void svm_drop_interrupt_shadow(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+ svm->vmcb->control.int_state &= ~SVM_INTERRUPT_SHADOW_MASK;
+}
+
+static void svm_inject_nmi(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+
+ svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_NMI;
+ vcpu->arch.hflags |= HF_NMI_MASK;
+ svm->vmcb->control.intercept |= (1UL << INTERCEPT_IRET);
+ ++vcpu->stat.nmi_injections;
+}
static inline void svm_inject_irq(struct vcpu_svm *svm, int irq)
{
@@ -2255,134 +2290,63 @@ static inline void svm_inject_irq(struct vcpu_svm *svm, int irq)
((/*control->int_vector >> 4*/ 0xf) << V_INTR_PRIO_SHIFT);
}
+static void svm_queue_irq(struct kvm_vcpu *vcpu, unsigned nr)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+
+ svm->vmcb->control.event_inj = nr |
+ SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR;
+}
+
static void svm_set_irq(struct kvm_vcpu *vcpu, int irq)
{
struct vcpu_svm *svm = to_svm(vcpu);
nested_svm_intr(svm);
- svm_inject_irq(svm, irq);
+ svm_queue_irq(vcpu, irq);
}
-static void update_cr8_intercept(struct kvm_vcpu *vcpu)
+static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
{
struct vcpu_svm *svm = to_svm(vcpu);
- struct vmcb *vmcb = svm->vmcb;
- int max_irr, tpr;
-
- if (!irqchip_in_kernel(vcpu->kvm) || vcpu->arch.apic->vapic_addr)
- return;
-
- vmcb->control.intercept_cr_write &= ~INTERCEPT_CR8_MASK;
- max_irr = kvm_lapic_find_highest_irr(vcpu);
- if (max_irr == -1)
+ if (irr == -1)
return;
- tpr = kvm_lapic_get_cr8(vcpu) << 4;
-
- if (tpr >= (max_irr & 0xf0))
- vmcb->control.intercept_cr_write |= INTERCEPT_CR8_MASK;
+ if (tpr >= irr)
+ svm->vmcb->control.intercept_cr_write |= INTERCEPT_CR8_MASK;
}
-static void svm_intr_assist(struct kvm_vcpu *vcpu)
+static int svm_nmi_allowed(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
struct vmcb *vmcb = svm->vmcb;
- int intr_vector = -1;
-
- if ((vmcb->control.exit_int_info & SVM_EVTINJ_VALID) &&
- ((vmcb->control.exit_int_info & SVM_EVTINJ_TYPE_MASK) == 0)) {
- intr_vector = vmcb->control.exit_int_info &
- SVM_EVTINJ_VEC_MASK;
- vmcb->control.exit_int_info = 0;
- svm_inject_irq(svm, intr_vector);
- goto out;
- }
-
- if (vmcb->control.int_ctl & V_IRQ_MASK)
- goto out;
-
- if (!kvm_cpu_has_interrupt(vcpu))
- goto out;
-
- if (nested_svm_intr(svm))
- goto out;
-
- if (!(svm->vcpu.arch.hflags & HF_GIF_MASK))
- goto out;
-
- if (!(vmcb->save.rflags & X86_EFLAGS_IF) ||
- (vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) ||
- (vmcb->control.event_inj & SVM_EVTINJ_VALID)) {
- /* unable to deliver irq, set pending irq */
- svm_set_vintr(svm);
- svm_inject_irq(svm, 0x0);
- goto out;
- }
- /* Okay, we can deliver the interrupt: grab it and update PIC state. */
- intr_vector = kvm_cpu_get_interrupt(vcpu);
- svm_inject_irq(svm, intr_vector);
-out:
- update_cr8_intercept(vcpu);
+ return !(vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) &&
+ !(svm->vcpu.arch.hflags & HF_NMI_MASK);
}
-static void kvm_reput_irq(struct vcpu_svm *svm)
+static int svm_interrupt_allowed(struct kvm_vcpu *vcpu)
{
- struct vmcb_control_area *control = &svm->vmcb->control;
-
- if ((control->int_ctl & V_IRQ_MASK)
- && !irqchip_in_kernel(svm->vcpu.kvm)) {
- control->int_ctl &= ~V_IRQ_MASK;
- push_irq(&svm->vcpu, control->int_vector);
- }
-
- svm->vcpu.arch.interrupt_window_open =
- !(control->int_state & SVM_INTERRUPT_SHADOW_MASK) &&
- (svm->vcpu.arch.hflags & HF_GIF_MASK);
+ struct vcpu_svm *svm = to_svm(vcpu);
+ struct vmcb *vmcb = svm->vmcb;
+ return (vmcb->save.rflags & X86_EFLAGS_IF) &&
+ !(vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) &&
+ (svm->vcpu.arch.hflags & HF_GIF_MASK);
}
-static void svm_do_inject_vector(struct vcpu_svm *svm)
+static void enable_irq_window(struct kvm_vcpu *vcpu)
{
- struct kvm_vcpu *vcpu = &svm->vcpu;
- int word_index = __ffs(vcpu->arch.irq_summary);
- int bit_index = __ffs(vcpu->arch.irq_pending[word_index]);
- int irq = word_index * BITS_PER_LONG + bit_index;
-
- clear_bit(bit_index, &vcpu->arch.irq_pending[word_index]);
- if (!vcpu->arch.irq_pending[word_index])
- clear_bit(word_index, &vcpu->arch.irq_summary);
- svm_inject_irq(svm, irq);
+ svm_set_vintr(to_svm(vcpu));
+ svm_inject_irq(to_svm(vcpu), 0x0);
}
-static void do_interrupt_requests(struct kvm_vcpu *vcpu,
- struct kvm_run *kvm_run)
+static void enable_nmi_window(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
- struct vmcb_control_area *control = &svm->vmcb->control;
-
- if (nested_svm_intr(svm))
- return;
-
- svm->vcpu.arch.interrupt_window_open =
- (!(control->int_state & SVM_INTERRUPT_SHADOW_MASK) &&
- (svm->vmcb->save.rflags & X86_EFLAGS_IF) &&
- (svm->vcpu.arch.hflags & HF_GIF_MASK));
- if (svm->vcpu.arch.interrupt_window_open && svm->vcpu.arch.irq_summary)
- /*
- * If interrupts enabled, and not blocked by sti or mov ss. Good.
- */
- svm_do_inject_vector(svm);
-
- /*
- * Interrupts blocked. Wait for unblock.
- */
- if (!svm->vcpu.arch.interrupt_window_open &&
- (svm->vcpu.arch.irq_summary || kvm_run->request_interrupt_window))
- svm_set_vintr(svm);
- else
- svm_clear_vintr(svm);
+ if (svm->vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK)
+ enable_irq_window(vcpu);
}
static int svm_set_tss_addr(struct kvm *kvm, unsigned int addr)
@@ -2405,7 +2369,7 @@ static inline void sync_cr8_to_lapic(struct kvm_vcpu *vcpu)
if (!(svm->vmcb->control.intercept_cr_write & INTERCEPT_CR8_MASK)) {
int cr8 = svm->vmcb->control.int_ctl & V_TPR_MASK;
- kvm_lapic_set_tpr(vcpu, cr8);
+ kvm_set_cr8(vcpu, cr8);
}
}
@@ -2414,14 +2378,51 @@ static inline void sync_lapic_to_cr8(struct kvm_vcpu *vcpu)
struct vcpu_svm *svm = to_svm(vcpu);
u64 cr8;
- if (!irqchip_in_kernel(vcpu->kvm))
- return;
-
cr8 = kvm_get_cr8(vcpu);
svm->vmcb->control.int_ctl &= ~V_TPR_MASK;
svm->vmcb->control.int_ctl |= cr8 & V_TPR_MASK;
}
+static void svm_complete_interrupts(struct vcpu_svm *svm)
+{
+ u8 vector;
+ int type;
+ u32 exitintinfo = svm->vmcb->control.exit_int_info;
+
+ svm->vcpu.arch.nmi_injected = false;
+ kvm_clear_exception_queue(&svm->vcpu);
+ kvm_clear_interrupt_queue(&svm->vcpu);
+
+ if (!(exitintinfo & SVM_EXITINTINFO_VALID))
+ return;
+
+ vector = exitintinfo & SVM_EXITINTINFO_VEC_MASK;
+ type = exitintinfo & SVM_EXITINTINFO_TYPE_MASK;
+
+ switch (type) {
+ case SVM_EXITINTINFO_TYPE_NMI:
+ svm->vcpu.arch.nmi_injected = true;
+ break;
+ case SVM_EXITINTINFO_TYPE_EXEPT:
+ /* In case of software exception do not reinject an exception
+ vector, but re-execute and instruction instead */
+ if (vector == BP_VECTOR || vector == OF_VECTOR)
+ break;
+ if (exitintinfo & SVM_EXITINTINFO_VALID_ERR) {
+ u32 err = svm->vmcb->control.exit_int_info_err;
+ kvm_queue_exception_e(&svm->vcpu, vector, err);
+
+ } else
+ kvm_queue_exception(&svm->vcpu, vector);
+ break;
+ case SVM_EXITINTINFO_TYPE_INTR:
+ kvm_queue_interrupt(&svm->vcpu, vector);
+ break;
+ default:
+ break;
+ }
+}
+
#ifdef CONFIG_X86_64
#define R "r"
#else
@@ -2550,6 +2551,8 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
sync_cr8_to_lapic(vcpu);
svm->next_rip = 0;
+
+ svm_complete_interrupts(svm);
}
#undef R
@@ -2615,7 +2618,7 @@ static int get_npt_level(void)
#endif
}
-static int svm_get_mt_mask_shift(void)
+static u64 svm_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
{
return 0;
}
@@ -2666,16 +2669,19 @@ static struct kvm_x86_ops svm_x86_ops = {
.handle_exit = handle_exit,
.skip_emulated_instruction = skip_emulated_instruction,
.patch_hypercall = svm_patch_hypercall,
- .get_irq = svm_get_irq,
.set_irq = svm_set_irq,
+ .set_nmi = svm_inject_nmi,
.queue_exception = svm_queue_exception,
- .exception_injected = svm_exception_injected,
- .inject_pending_irq = svm_intr_assist,
- .inject_pending_vectors = do_interrupt_requests,
+ .interrupt_allowed = svm_interrupt_allowed,
+ .nmi_allowed = svm_nmi_allowed,
+ .enable_nmi_window = enable_nmi_window,
+ .enable_irq_window = enable_irq_window,
+ .update_cr8_intercept = update_cr8_intercept,
+ .drop_interrupt_shadow = svm_drop_interrupt_shadow,
.set_tss_addr = svm_set_tss_addr,
.get_tdp_level = get_npt_level,
- .get_mt_mask_shift = svm_get_mt_mask_shift,
+ .get_mt_mask = svm_get_mt_mask,
};
static int __init svm_init(void)
diff --git a/arch/x86/kvm/timer.c b/arch/x86/kvm/timer.c
new file mode 100644
index 000000000000..86dbac072d0c
--- /dev/null
+++ b/arch/x86/kvm/timer.c
@@ -0,0 +1,46 @@
+#include <linux/kvm_host.h>
+#include <linux/kvm.h>
+#include <linux/hrtimer.h>
+#include <asm/atomic.h>
+#include "kvm_timer.h"
+
+static int __kvm_timer_fn(struct kvm_vcpu *vcpu, struct kvm_timer *ktimer)
+{
+ int restart_timer = 0;
+ wait_queue_head_t *q = &vcpu->wq;
+
+ /* FIXME: this code should not know anything about vcpus */
+ if (!atomic_inc_and_test(&ktimer->pending))
+ set_bit(KVM_REQ_PENDING_TIMER, &vcpu->requests);
+
+ if (!ktimer->reinject)
+ atomic_set(&ktimer->pending, 1);
+
+ if (waitqueue_active(q))
+ wake_up_interruptible(q);
+
+ if (ktimer->t_ops->is_periodic(ktimer)) {
+ hrtimer_add_expires_ns(&ktimer->timer, ktimer->period);
+ restart_timer = 1;
+ }
+
+ return restart_timer;
+}
+
+enum hrtimer_restart kvm_timer_fn(struct hrtimer *data)
+{
+ int restart_timer;
+ struct kvm_vcpu *vcpu;
+ struct kvm_timer *ktimer = container_of(data, struct kvm_timer, timer);
+
+ vcpu = ktimer->kvm->vcpus[ktimer->vcpu_id];
+ if (!vcpu)
+ return HRTIMER_NORESTART;
+
+ restart_timer = __kvm_timer_fn(vcpu, ktimer);
+ if (restart_timer)
+ return HRTIMER_RESTART;
+ else
+ return HRTIMER_NORESTART;
+}
+
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index bb481330716f..e8a5649f9c15 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -38,20 +38,20 @@
MODULE_AUTHOR("Qumranet");
MODULE_LICENSE("GPL");
-static int bypass_guest_pf = 1;
-module_param(bypass_guest_pf, bool, 0);
+static int __read_mostly bypass_guest_pf = 1;
+module_param(bypass_guest_pf, bool, S_IRUGO);
-static int enable_vpid = 1;
-module_param(enable_vpid, bool, 0);
+static int __read_mostly enable_vpid = 1;
+module_param_named(vpid, enable_vpid, bool, 0444);
-static int flexpriority_enabled = 1;
-module_param(flexpriority_enabled, bool, 0);
+static int __read_mostly flexpriority_enabled = 1;
+module_param_named(flexpriority, flexpriority_enabled, bool, S_IRUGO);
-static int enable_ept = 1;
-module_param(enable_ept, bool, 0);
+static int __read_mostly enable_ept = 1;
+module_param_named(ept, enable_ept, bool, S_IRUGO);
-static int emulate_invalid_guest_state = 0;
-module_param(emulate_invalid_guest_state, bool, 0);
+static int __read_mostly emulate_invalid_guest_state = 0;
+module_param(emulate_invalid_guest_state, bool, S_IRUGO);
struct vmcs {
u32 revision_id;
@@ -111,9 +111,10 @@ static DEFINE_PER_CPU(struct vmcs *, vmxarea);
static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
static DEFINE_PER_CPU(struct list_head, vcpus_on_cpu);
-static struct page *vmx_io_bitmap_a;
-static struct page *vmx_io_bitmap_b;
-static struct page *vmx_msr_bitmap;
+static unsigned long *vmx_io_bitmap_a;
+static unsigned long *vmx_io_bitmap_b;
+static unsigned long *vmx_msr_bitmap_legacy;
+static unsigned long *vmx_msr_bitmap_longmode;
static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS);
static DEFINE_SPINLOCK(vmx_vpid_lock);
@@ -215,68 +216,69 @@ static inline int is_external_interrupt(u32 intr_info)
static inline int cpu_has_vmx_msr_bitmap(void)
{
- return (vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS);
+ return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS;
}
static inline int cpu_has_vmx_tpr_shadow(void)
{
- return (vmcs_config.cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW);
+ return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW;
}
static inline int vm_need_tpr_shadow(struct kvm *kvm)
{
- return ((cpu_has_vmx_tpr_shadow()) && (irqchip_in_kernel(kvm)));
+ return (cpu_has_vmx_tpr_shadow()) && (irqchip_in_kernel(kvm));
}
static inline int cpu_has_secondary_exec_ctrls(void)
{
- return (vmcs_config.cpu_based_exec_ctrl &
- CPU_BASED_ACTIVATE_SECONDARY_CONTROLS);
+ return vmcs_config.cpu_based_exec_ctrl &
+ CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
}
static inline bool cpu_has_vmx_virtualize_apic_accesses(void)
{
- return flexpriority_enabled
- && (vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES);
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+}
+
+static inline bool cpu_has_vmx_flexpriority(void)
+{
+ return cpu_has_vmx_tpr_shadow() &&
+ cpu_has_vmx_virtualize_apic_accesses();
}
static inline int cpu_has_vmx_invept_individual_addr(void)
{
- return (!!(vmx_capability.ept & VMX_EPT_EXTENT_INDIVIDUAL_BIT));
+ return !!(vmx_capability.ept & VMX_EPT_EXTENT_INDIVIDUAL_BIT);
}
static inline int cpu_has_vmx_invept_context(void)
{
- return (!!(vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT));
+ return !!(vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT);
}
static inline int cpu_has_vmx_invept_global(void)
{
- return (!!(vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT));
+ return !!(vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT);
}
static inline int cpu_has_vmx_ept(void)
{
- return (vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_ENABLE_EPT);
-}
-
-static inline int vm_need_ept(void)
-{
- return (cpu_has_vmx_ept() && enable_ept);
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_ENABLE_EPT;
}
static inline int vm_need_virtualize_apic_accesses(struct kvm *kvm)
{
- return ((cpu_has_vmx_virtualize_apic_accesses()) &&
- (irqchip_in_kernel(kvm)));
+ return flexpriority_enabled &&
+ (cpu_has_vmx_virtualize_apic_accesses()) &&
+ (irqchip_in_kernel(kvm));
}
static inline int cpu_has_vmx_vpid(void)
{
- return (vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_ENABLE_VPID);
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_ENABLE_VPID;
}
static inline int cpu_has_virtual_nmis(void)
@@ -284,6 +286,11 @@ static inline int cpu_has_virtual_nmis(void)
return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS;
}
+static inline bool report_flexpriority(void)
+{
+ return flexpriority_enabled;
+}
+
static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr)
{
int i;
@@ -381,7 +388,7 @@ static inline void ept_sync_global(void)
static inline void ept_sync_context(u64 eptp)
{
- if (vm_need_ept()) {
+ if (enable_ept) {
if (cpu_has_vmx_invept_context())
__invept(VMX_EPT_EXTENT_CONTEXT, eptp, 0);
else
@@ -391,7 +398,7 @@ static inline void ept_sync_context(u64 eptp)
static inline void ept_sync_individual_addr(u64 eptp, gpa_t gpa)
{
- if (vm_need_ept()) {
+ if (enable_ept) {
if (cpu_has_vmx_invept_individual_addr())
__invept(VMX_EPT_EXTENT_INDIVIDUAL_ADDR,
eptp, gpa);
@@ -490,7 +497,7 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
}
if (vcpu->arch.rmode.active)
eb = ~0;
- if (vm_need_ept())
+ if (enable_ept)
eb &= ~(1u << PF_VECTOR); /* bypass_guest_pf = 0 */
vmcs_write32(EXCEPTION_BITMAP, eb);
}
@@ -746,7 +753,6 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
if (interruptibility & 3)
vmcs_write32(GUEST_INTERRUPTIBILITY_INFO,
interruptibility & ~3);
- vcpu->arch.interrupt_window_open = 1;
}
static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
@@ -782,11 +788,6 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info);
}
-static bool vmx_exception_injected(struct kvm_vcpu *vcpu)
-{
- return false;
-}
-
/*
* Swap MSR entry in host/guest MSR entry array.
*/
@@ -812,6 +813,7 @@ static void move_msr_up(struct vcpu_vmx *vmx, int from, int to)
static void setup_msrs(struct vcpu_vmx *vmx)
{
int save_nmsrs;
+ unsigned long *msr_bitmap;
vmx_load_host_state(vmx);
save_nmsrs = 0;
@@ -847,6 +849,15 @@ static void setup_msrs(struct vcpu_vmx *vmx)
__find_msr_index(vmx, MSR_KERNEL_GS_BASE);
#endif
vmx->msr_offset_efer = __find_msr_index(vmx, MSR_EFER);
+
+ if (cpu_has_vmx_msr_bitmap()) {
+ if (is_long_mode(&vmx->vcpu))
+ msr_bitmap = vmx_msr_bitmap_longmode;
+ else
+ msr_bitmap = vmx_msr_bitmap_legacy;
+
+ vmcs_write64(MSR_BITMAP, __pa(msr_bitmap));
+ }
}
/*
@@ -1034,13 +1045,6 @@ static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg)
return 0;
}
-static int vmx_get_irq(struct kvm_vcpu *vcpu)
-{
- if (!vcpu->arch.interrupt.pending)
- return -1;
- return vcpu->arch.interrupt.nr;
-}
-
static __init int cpu_has_kvm_support(void)
{
return cpu_has_vmx();
@@ -1294,6 +1298,18 @@ static __init int hardware_setup(void)
if (boot_cpu_has(X86_FEATURE_NX))
kvm_enable_efer_bits(EFER_NX);
+ if (!cpu_has_vmx_vpid())
+ enable_vpid = 0;
+
+ if (!cpu_has_vmx_ept())
+ enable_ept = 0;
+
+ if (!cpu_has_vmx_flexpriority())
+ flexpriority_enabled = 0;
+
+ if (!cpu_has_vmx_tpr_shadow())
+ kvm_x86_ops->update_cr8_intercept = NULL;
+
return alloc_kvm_area();
}
@@ -1485,7 +1501,7 @@ static void exit_lmode(struct kvm_vcpu *vcpu)
static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
{
vpid_sync_vcpu_all(to_vmx(vcpu));
- if (vm_need_ept())
+ if (enable_ept)
ept_sync_context(construct_eptp(vcpu->arch.mmu.root_hpa));
}
@@ -1570,7 +1586,7 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
}
#endif
- if (vm_need_ept())
+ if (enable_ept)
ept_update_paging_mode_cr0(&hw_cr0, cr0, vcpu);
vmcs_writel(CR0_READ_SHADOW, cr0);
@@ -1599,7 +1615,7 @@ static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
u64 eptp;
guest_cr3 = cr3;
- if (vm_need_ept()) {
+ if (enable_ept) {
eptp = construct_eptp(cr3);
vmcs_write64(EPT_POINTER, eptp);
ept_sync_context(eptp);
@@ -1620,7 +1636,7 @@ static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
KVM_RMODE_VM_CR4_ALWAYS_ON : KVM_PMODE_VM_CR4_ALWAYS_ON);
vcpu->arch.cr4 = cr4;
- if (vm_need_ept())
+ if (enable_ept)
ept_update_paging_mode_cr4(&hw_cr4, vcpu);
vmcs_writel(CR4_READ_SHADOW, cr4);
@@ -1982,7 +1998,7 @@ static int init_rmode_identity_map(struct kvm *kvm)
pfn_t identity_map_pfn;
u32 tmp;
- if (!vm_need_ept())
+ if (!enable_ept)
return 1;
if (unlikely(!kvm->arch.ept_identity_pagetable)) {
printk(KERN_ERR "EPT: identity-mapping pagetable "
@@ -2071,7 +2087,7 @@ static void allocate_vpid(struct vcpu_vmx *vmx)
int vpid;
vmx->vpid = 0;
- if (!enable_vpid || !cpu_has_vmx_vpid())
+ if (!enable_vpid)
return;
spin_lock(&vmx_vpid_lock);
vpid = find_first_zero_bit(vmx_vpid_bitmap, VMX_NR_VPIDS);
@@ -2082,9 +2098,9 @@ static void allocate_vpid(struct vcpu_vmx *vmx)
spin_unlock(&vmx_vpid_lock);
}
-static void vmx_disable_intercept_for_msr(struct page *msr_bitmap, u32 msr)
+static void __vmx_disable_intercept_for_msr(unsigned long *msr_bitmap, u32 msr)
{
- void *va;
+ int f = sizeof(unsigned long);
if (!cpu_has_vmx_msr_bitmap())
return;
@@ -2094,16 +2110,21 @@ static void vmx_disable_intercept_for_msr(struct page *msr_bitmap, u32 msr)
* have the write-low and read-high bitmap offsets the wrong way round.
* We can control MSRs 0x00000000-0x00001fff and 0xc0000000-0xc0001fff.
*/
- va = kmap(msr_bitmap);
if (msr <= 0x1fff) {
- __clear_bit(msr, va + 0x000); /* read-low */
- __clear_bit(msr, va + 0x800); /* write-low */
+ __clear_bit(msr, msr_bitmap + 0x000 / f); /* read-low */
+ __clear_bit(msr, msr_bitmap + 0x800 / f); /* write-low */
} else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) {
msr &= 0x1fff;
- __clear_bit(msr, va + 0x400); /* read-high */
- __clear_bit(msr, va + 0xc00); /* write-high */
+ __clear_bit(msr, msr_bitmap + 0x400 / f); /* read-high */
+ __clear_bit(msr, msr_bitmap + 0xc00 / f); /* write-high */
}
- kunmap(msr_bitmap);
+}
+
+static void vmx_disable_intercept_for_msr(u32 msr, bool longmode_only)
+{
+ if (!longmode_only)
+ __vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy, msr);
+ __vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode, msr);
}
/*
@@ -2121,11 +2142,11 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
u32 exec_control;
/* I/O */
- vmcs_write64(IO_BITMAP_A, page_to_phys(vmx_io_bitmap_a));
- vmcs_write64(IO_BITMAP_B, page_to_phys(vmx_io_bitmap_b));
+ vmcs_write64(IO_BITMAP_A, __pa(vmx_io_bitmap_a));
+ vmcs_write64(IO_BITMAP_B, __pa(vmx_io_bitmap_b));
if (cpu_has_vmx_msr_bitmap())
- vmcs_write64(MSR_BITMAP, page_to_phys(vmx_msr_bitmap));
+ vmcs_write64(MSR_BITMAP, __pa(vmx_msr_bitmap_legacy));
vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */
@@ -2141,7 +2162,7 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
CPU_BASED_CR8_LOAD_EXITING;
#endif
}
- if (!vm_need_ept())
+ if (!enable_ept)
exec_control |= CPU_BASED_CR3_STORE_EXITING |
CPU_BASED_CR3_LOAD_EXITING |
CPU_BASED_INVLPG_EXITING;
@@ -2154,7 +2175,7 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
if (vmx->vpid == 0)
exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
- if (!vm_need_ept())
+ if (!enable_ept)
exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
}
@@ -2379,6 +2400,12 @@ out:
return ret;
}
+void vmx_drop_interrupt_shadow(struct kvm_vcpu *vcpu)
+{
+ vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
+ GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS);
+}
+
static void enable_irq_window(struct kvm_vcpu *vcpu)
{
u32 cpu_based_vm_exec_control;
@@ -2456,76 +2483,21 @@ static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR);
}
-static void vmx_update_window_states(struct kvm_vcpu *vcpu)
+static int vmx_nmi_allowed(struct kvm_vcpu *vcpu)
{
- u32 guest_intr = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
-
- vcpu->arch.nmi_window_open =
- !(guest_intr & (GUEST_INTR_STATE_STI |
- GUEST_INTR_STATE_MOV_SS |
- GUEST_INTR_STATE_NMI));
if (!cpu_has_virtual_nmis() && to_vmx(vcpu)->soft_vnmi_blocked)
- vcpu->arch.nmi_window_open = 0;
-
- vcpu->arch.interrupt_window_open =
- ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
- !(guest_intr & (GUEST_INTR_STATE_STI |
- GUEST_INTR_STATE_MOV_SS)));
-}
-
-static void kvm_do_inject_irq(struct kvm_vcpu *vcpu)
-{
- int word_index = __ffs(vcpu->arch.irq_summary);
- int bit_index = __ffs(vcpu->arch.irq_pending[word_index]);
- int irq = word_index * BITS_PER_LONG + bit_index;
+ return 0;
- clear_bit(bit_index, &vcpu->arch.irq_pending[word_index]);
- if (!vcpu->arch.irq_pending[word_index])
- clear_bit(word_index, &vcpu->arch.irq_summary);
- kvm_queue_interrupt(vcpu, irq);
+ return !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
+ (GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS |
+ GUEST_INTR_STATE_NMI));
}
-static void do_interrupt_requests(struct kvm_vcpu *vcpu,
- struct kvm_run *kvm_run)
+static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu)
{
- vmx_update_window_states(vcpu);
-
- if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
- vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
- GUEST_INTR_STATE_STI |
- GUEST_INTR_STATE_MOV_SS);
-
- if (vcpu->arch.nmi_pending && !vcpu->arch.nmi_injected) {
- if (vcpu->arch.interrupt.pending) {
- enable_nmi_window(vcpu);
- } else if (vcpu->arch.nmi_window_open) {
- vcpu->arch.nmi_pending = false;
- vcpu->arch.nmi_injected = true;
- } else {
- enable_nmi_window(vcpu);
- return;
- }
- }
- if (vcpu->arch.nmi_injected) {
- vmx_inject_nmi(vcpu);
- if (vcpu->arch.nmi_pending)
- enable_nmi_window(vcpu);
- else if (vcpu->arch.irq_summary
- || kvm_run->request_interrupt_window)
- enable_irq_window(vcpu);
- return;
- }
-
- if (vcpu->arch.interrupt_window_open) {
- if (vcpu->arch.irq_summary && !vcpu->arch.interrupt.pending)
- kvm_do_inject_irq(vcpu);
-
- if (vcpu->arch.interrupt.pending)
- vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
- }
- if (!vcpu->arch.interrupt_window_open &&
- (vcpu->arch.irq_summary || kvm_run->request_interrupt_window))
- enable_irq_window(vcpu);
+ return (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
+ !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
+ (GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS));
}
static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr)
@@ -2601,12 +2573,6 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
printk(KERN_ERR "%s: unexpected, vectoring info 0x%x "
"intr info 0x%x\n", __func__, vect_info, intr_info);
- if (!irqchip_in_kernel(vcpu->kvm) && is_external_interrupt(vect_info)) {
- int irq = vect_info & VECTORING_INFO_VECTOR_MASK;
- set_bit(irq, vcpu->arch.irq_pending);
- set_bit(irq / BITS_PER_LONG, &vcpu->arch.irq_summary);
- }
-
if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR)
return 1; /* already handled by vmx_vcpu_run() */
@@ -2628,7 +2594,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
if (is_page_fault(intr_info)) {
/* EPT won't cause page fault directly */
- if (vm_need_ept())
+ if (enable_ept)
BUG();
cr2 = vmcs_readl(EXIT_QUALIFICATION);
KVMTRACE_3D(PAGE_FAULT, vcpu, error_code, (u32)cr2,
@@ -2753,13 +2719,18 @@ static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
kvm_set_cr4(vcpu, kvm_register_read(vcpu, reg));
skip_emulated_instruction(vcpu);
return 1;
- case 8:
- kvm_set_cr8(vcpu, kvm_register_read(vcpu, reg));
- skip_emulated_instruction(vcpu);
- if (irqchip_in_kernel(vcpu->kvm))
- return 1;
- kvm_run->exit_reason = KVM_EXIT_SET_TPR;
- return 0;
+ case 8: {
+ u8 cr8_prev = kvm_get_cr8(vcpu);
+ u8 cr8 = kvm_register_read(vcpu, reg);
+ kvm_set_cr8(vcpu, cr8);
+ skip_emulated_instruction(vcpu);
+ if (irqchip_in_kernel(vcpu->kvm))
+ return 1;
+ if (cr8_prev <= cr8)
+ return 1;
+ kvm_run->exit_reason = KVM_EXIT_SET_TPR;
+ return 0;
+ }
};
break;
case 2: /* clts */
@@ -2957,8 +2928,9 @@ static int handle_interrupt_window(struct kvm_vcpu *vcpu,
* If the user space waits to inject interrupts, exit as soon as
* possible
*/
- if (kvm_run->request_interrupt_window &&
- !vcpu->arch.irq_summary) {
+ if (!irqchip_in_kernel(vcpu->kvm) &&
+ kvm_run->request_interrupt_window &&
+ !kvm_cpu_has_interrupt(vcpu)) {
kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
return 0;
}
@@ -2980,7 +2952,7 @@ static int handle_vmcall(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
static int handle_invlpg(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
- u64 exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
+ unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
kvm_mmu_invlpg(vcpu, exit_qualification);
skip_emulated_instruction(vcpu);
@@ -2996,11 +2968,11 @@ static int handle_wbinvd(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
static int handle_apic_access(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
- u64 exit_qualification;
+ unsigned long exit_qualification;
enum emulation_result er;
unsigned long offset;
- exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
+ exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
offset = exit_qualification & 0xffful;
er = emulate_instruction(vcpu, kvm_run, 0, 0, 0);
@@ -3019,22 +2991,40 @@ static int handle_task_switch(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
struct vcpu_vmx *vmx = to_vmx(vcpu);
unsigned long exit_qualification;
u16 tss_selector;
- int reason;
+ int reason, type, idt_v;
+
+ idt_v = (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK);
+ type = (vmx->idt_vectoring_info & VECTORING_INFO_TYPE_MASK);
exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
reason = (u32)exit_qualification >> 30;
- if (reason == TASK_SWITCH_GATE && vmx->vcpu.arch.nmi_injected &&
- (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK) &&
- (vmx->idt_vectoring_info & VECTORING_INFO_TYPE_MASK)
- == INTR_TYPE_NMI_INTR) {
- vcpu->arch.nmi_injected = false;
- if (cpu_has_virtual_nmis())
- vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
- GUEST_INTR_STATE_NMI);
+ if (reason == TASK_SWITCH_GATE && idt_v) {
+ switch (type) {
+ case INTR_TYPE_NMI_INTR:
+ vcpu->arch.nmi_injected = false;
+ if (cpu_has_virtual_nmis())
+ vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
+ GUEST_INTR_STATE_NMI);
+ break;
+ case INTR_TYPE_EXT_INTR:
+ kvm_clear_interrupt_queue(vcpu);
+ break;
+ case INTR_TYPE_HARD_EXCEPTION:
+ case INTR_TYPE_SOFT_EXCEPTION:
+ kvm_clear_exception_queue(vcpu);
+ break;
+ default:
+ break;
+ }
}
tss_selector = exit_qualification;
+ if (!idt_v || (type != INTR_TYPE_HARD_EXCEPTION &&
+ type != INTR_TYPE_EXT_INTR &&
+ type != INTR_TYPE_NMI_INTR))
+ skip_emulated_instruction(vcpu);
+
if (!kvm_task_switch(vcpu, tss_selector, reason))
return 0;
@@ -3051,11 +3041,11 @@ static int handle_task_switch(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
static int handle_ept_violation(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
- u64 exit_qualification;
+ unsigned long exit_qualification;
gpa_t gpa;
int gla_validity;
- exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
+ exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
if (exit_qualification & (1 << 6)) {
printk(KERN_ERR "EPT: GPA exceeds GAW!\n");
@@ -3067,7 +3057,7 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
printk(KERN_ERR "EPT: Handling EPT violation failed!\n");
printk(KERN_ERR "EPT: GPA: 0x%lx, GVA: 0x%lx\n",
(long unsigned int)vmcs_read64(GUEST_PHYSICAL_ADDRESS),
- (long unsigned int)vmcs_read64(GUEST_LINEAR_ADDRESS));
+ vmcs_readl(GUEST_LINEAR_ADDRESS));
printk(KERN_ERR "EPT: Exit qualification is 0x%lx\n",
(long unsigned int)exit_qualification);
kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
@@ -3159,7 +3149,7 @@ static const int kvm_vmx_max_exit_handlers =
* The guest has exited. See if we can fix it or if we need userspace
* assistance.
*/
-static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+static int vmx_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
{
u32 exit_reason = vmcs_read32(VM_EXIT_REASON);
struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -3178,7 +3168,7 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
/* Access CR3 don't cause VMExit in paging mode, so we need
* to sync with guest real CR3. */
- if (vm_need_ept() && is_paging(vcpu)) {
+ if (enable_ept && is_paging(vcpu)) {
vcpu->arch.cr3 = vmcs_readl(GUEST_CR3);
ept_load_pdptrs(vcpu);
}
@@ -3199,9 +3189,8 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
__func__, vectoring_info, exit_reason);
if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked)) {
- if (vcpu->arch.interrupt_window_open) {
+ if (vmx_interrupt_allowed(vcpu)) {
vmx->soft_vnmi_blocked = 0;
- vcpu->arch.nmi_window_open = 1;
} else if (vmx->vnmi_blocked_time > 1000000000LL &&
vcpu->arch.nmi_pending) {
/*
@@ -3214,7 +3203,6 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
"state on VCPU %d after 1 s timeout\n",
__func__, vcpu->vcpu_id);
vmx->soft_vnmi_blocked = 0;
- vmx->vcpu.arch.nmi_window_open = 1;
}
}
@@ -3228,122 +3216,82 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
return 0;
}
-static void update_tpr_threshold(struct kvm_vcpu *vcpu)
+static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
{
- int max_irr, tpr;
-
- if (!vm_need_tpr_shadow(vcpu->kvm))
- return;
-
- if (!kvm_lapic_enabled(vcpu) ||
- ((max_irr = kvm_lapic_find_highest_irr(vcpu)) == -1)) {
+ if (irr == -1 || tpr < irr) {
vmcs_write32(TPR_THRESHOLD, 0);
return;
}
- tpr = (kvm_lapic_get_cr8(vcpu) & 0x0f) << 4;
- vmcs_write32(TPR_THRESHOLD, (max_irr > tpr) ? tpr >> 4 : max_irr >> 4);
+ vmcs_write32(TPR_THRESHOLD, irr);
}
static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
{
u32 exit_intr_info;
- u32 idt_vectoring_info;
+ u32 idt_vectoring_info = vmx->idt_vectoring_info;
bool unblock_nmi;
u8 vector;
int type;
bool idtv_info_valid;
- u32 error;
+ idtv_info_valid = idt_vectoring_info & VECTORING_INFO_VALID_MASK;
exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
if (cpu_has_virtual_nmis()) {
unblock_nmi = (exit_intr_info & INTR_INFO_UNBLOCK_NMI) != 0;
vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
/*
- * SDM 3: 25.7.1.2
+ * SDM 3: 27.7.1.2 (September 2008)
* Re-set bit "block by NMI" before VM entry if vmexit caused by
* a guest IRET fault.
+ * SDM 3: 23.2.2 (September 2008)
+ * Bit 12 is undefined in any of the following cases:
+ * If the VM exit sets the valid bit in the IDT-vectoring
+ * information field.
+ * If the VM exit is due to a double fault.
*/
- if (unblock_nmi && vector != DF_VECTOR)
+ if ((exit_intr_info & INTR_INFO_VALID_MASK) && unblock_nmi &&
+ vector != DF_VECTOR && !idtv_info_valid)
vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
GUEST_INTR_STATE_NMI);
} else if (unlikely(vmx->soft_vnmi_blocked))
vmx->vnmi_blocked_time +=
ktime_to_ns(ktime_sub(ktime_get(), vmx->entry_time));
- idt_vectoring_info = vmx->idt_vectoring_info;
- idtv_info_valid = idt_vectoring_info & VECTORING_INFO_VALID_MASK;
+ vmx->vcpu.arch.nmi_injected = false;
+ kvm_clear_exception_queue(&vmx->vcpu);
+ kvm_clear_interrupt_queue(&vmx->vcpu);
+
+ if (!idtv_info_valid)
+ return;
+
vector = idt_vectoring_info & VECTORING_INFO_VECTOR_MASK;
type = idt_vectoring_info & VECTORING_INFO_TYPE_MASK;
- if (vmx->vcpu.arch.nmi_injected) {
+
+ switch (type) {
+ case INTR_TYPE_NMI_INTR:
+ vmx->vcpu.arch.nmi_injected = true;
/*
- * SDM 3: 25.7.1.2
- * Clear bit "block by NMI" before VM entry if a NMI delivery
- * faulted.
+ * SDM 3: 27.7.1.2 (September 2008)
+ * Clear bit "block by NMI" before VM entry if a NMI
+ * delivery faulted.
*/
- if (idtv_info_valid && type == INTR_TYPE_NMI_INTR)
- vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
- GUEST_INTR_STATE_NMI);
- else
- vmx->vcpu.arch.nmi_injected = false;
- }
- kvm_clear_exception_queue(&vmx->vcpu);
- if (idtv_info_valid && (type == INTR_TYPE_HARD_EXCEPTION ||
- type == INTR_TYPE_SOFT_EXCEPTION)) {
+ vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
+ GUEST_INTR_STATE_NMI);
+ break;
+ case INTR_TYPE_HARD_EXCEPTION:
+ case INTR_TYPE_SOFT_EXCEPTION:
if (idt_vectoring_info & VECTORING_INFO_DELIVER_CODE_MASK) {
- error = vmcs_read32(IDT_VECTORING_ERROR_CODE);
- kvm_queue_exception_e(&vmx->vcpu, vector, error);
+ u32 err = vmcs_read32(IDT_VECTORING_ERROR_CODE);
+ kvm_queue_exception_e(&vmx->vcpu, vector, err);
} else
kvm_queue_exception(&vmx->vcpu, vector);
- vmx->idt_vectoring_info = 0;
- }
- kvm_clear_interrupt_queue(&vmx->vcpu);
- if (idtv_info_valid && type == INTR_TYPE_EXT_INTR) {
+ break;
+ case INTR_TYPE_EXT_INTR:
kvm_queue_interrupt(&vmx->vcpu, vector);
- vmx->idt_vectoring_info = 0;
- }
-}
-
-static void vmx_intr_assist(struct kvm_vcpu *vcpu)
-{
- update_tpr_threshold(vcpu);
-
- vmx_update_window_states(vcpu);
-
- if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
- vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
- GUEST_INTR_STATE_STI |
- GUEST_INTR_STATE_MOV_SS);
-
- if (vcpu->arch.nmi_pending && !vcpu->arch.nmi_injected) {
- if (vcpu->arch.interrupt.pending) {
- enable_nmi_window(vcpu);
- } else if (vcpu->arch.nmi_window_open) {
- vcpu->arch.nmi_pending = false;
- vcpu->arch.nmi_injected = true;
- } else {
- enable_nmi_window(vcpu);
- return;
- }
- }
- if (vcpu->arch.nmi_injected) {
- vmx_inject_nmi(vcpu);
- if (vcpu->arch.nmi_pending)
- enable_nmi_window(vcpu);
- else if (kvm_cpu_has_interrupt(vcpu))
- enable_irq_window(vcpu);
- return;
- }
- if (!vcpu->arch.interrupt.pending && kvm_cpu_has_interrupt(vcpu)) {
- if (vcpu->arch.interrupt_window_open)
- kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
- else
- enable_irq_window(vcpu);
- }
- if (vcpu->arch.interrupt.pending) {
- vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
- if (kvm_cpu_has_interrupt(vcpu))
- enable_irq_window(vcpu);
+ break;
+ default:
+ break;
}
}
@@ -3505,8 +3453,6 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
if (vmx->rmode.irq.pending)
fixup_rmode_irq(vmx);
- vmx_update_window_states(vcpu);
-
asm("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
vmx->launched = 1;
@@ -3593,7 +3539,7 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
if (alloc_apic_access_page(kvm) != 0)
goto free_vmcs;
- if (vm_need_ept())
+ if (enable_ept)
if (alloc_identity_pagetable(kvm) != 0)
goto free_vmcs;
@@ -3631,9 +3577,32 @@ static int get_ept_level(void)
return VMX_EPT_DEFAULT_GAW + 1;
}
-static int vmx_get_mt_mask_shift(void)
+static u64 vmx_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
{
- return VMX_EPT_MT_EPTE_SHIFT;
+ u64 ret;
+
+ /* For VT-d and EPT combination
+ * 1. MMIO: always map as UC
+ * 2. EPT with VT-d:
+ * a. VT-d without snooping control feature: can't guarantee the
+ * result, try to trust guest.
+ * b. VT-d with snooping control feature: snooping control feature of
+ * VT-d engine can guarantee the cache correctness. Just set it
+ * to WB to keep consistent with host. So the same as item 3.
+ * 3. EPT without VT-d: always map as WB and set IGMT=1 to keep
+ * consistent with host MTRR
+ */
+ if (is_mmio)
+ ret = MTRR_TYPE_UNCACHABLE << VMX_EPT_MT_EPTE_SHIFT;
+ else if (vcpu->kvm->arch.iommu_domain &&
+ !(vcpu->kvm->arch.iommu_flags & KVM_IOMMU_CACHE_COHERENCY))
+ ret = kvm_get_guest_memory_type(vcpu, gfn) <<
+ VMX_EPT_MT_EPTE_SHIFT;
+ else
+ ret = (MTRR_TYPE_WRBACK << VMX_EPT_MT_EPTE_SHIFT)
+ | VMX_EPT_IGMT_BIT;
+
+ return ret;
}
static struct kvm_x86_ops vmx_x86_ops = {
@@ -3644,7 +3613,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
.check_processor_compatibility = vmx_check_processor_compat,
.hardware_enable = hardware_enable,
.hardware_disable = hardware_disable,
- .cpu_has_accelerated_tpr = cpu_has_vmx_virtualize_apic_accesses,
+ .cpu_has_accelerated_tpr = report_flexpriority,
.vcpu_create = vmx_create_vcpu,
.vcpu_free = vmx_free_vcpu,
@@ -3678,78 +3647,81 @@ static struct kvm_x86_ops vmx_x86_ops = {
.tlb_flush = vmx_flush_tlb,
.run = vmx_vcpu_run,
- .handle_exit = kvm_handle_exit,
+ .handle_exit = vmx_handle_exit,
.skip_emulated_instruction = skip_emulated_instruction,
.patch_hypercall = vmx_patch_hypercall,
- .get_irq = vmx_get_irq,
.set_irq = vmx_inject_irq,
+ .set_nmi = vmx_inject_nmi,
.queue_exception = vmx_queue_exception,
- .exception_injected = vmx_exception_injected,
- .inject_pending_irq = vmx_intr_assist,
- .inject_pending_vectors = do_interrupt_requests,
+ .interrupt_allowed = vmx_interrupt_allowed,
+ .nmi_allowed = vmx_nmi_allowed,
+ .enable_nmi_window = enable_nmi_window,
+ .enable_irq_window = enable_irq_window,
+ .update_cr8_intercept = update_cr8_intercept,
+ .drop_interrupt_shadow = vmx_drop_interrupt_shadow,
.set_tss_addr = vmx_set_tss_addr,
.get_tdp_level = get_ept_level,
- .get_mt_mask_shift = vmx_get_mt_mask_shift,
+ .get_mt_mask = vmx_get_mt_mask,
};
static int __init vmx_init(void)
{
- void *va;
int r;
- vmx_io_bitmap_a = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
+ vmx_io_bitmap_a = (unsigned long *)__get_free_page(GFP_KERNEL);
if (!vmx_io_bitmap_a)
return -ENOMEM;
- vmx_io_bitmap_b = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
+ vmx_io_bitmap_b = (unsigned long *)__get_free_page(GFP_KERNEL);
if (!vmx_io_bitmap_b) {
r = -ENOMEM;
goto out;
}
- vmx_msr_bitmap = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
- if (!vmx_msr_bitmap) {
+ vmx_msr_bitmap_legacy = (unsigned long *)__get_free_page(GFP_KERNEL);
+ if (!vmx_msr_bitmap_legacy) {
r = -ENOMEM;
goto out1;
}
+ vmx_msr_bitmap_longmode = (unsigned long *)__get_free_page(GFP_KERNEL);
+ if (!vmx_msr_bitmap_longmode) {
+ r = -ENOMEM;
+ goto out2;
+ }
+
/*
* Allow direct access to the PC debug port (it is often used for I/O
* delays, but the vmexits simply slow things down).
*/
- va = kmap(vmx_io_bitmap_a);
- memset(va, 0xff, PAGE_SIZE);
- clear_bit(0x80, va);
- kunmap(vmx_io_bitmap_a);
+ memset(vmx_io_bitmap_a, 0xff, PAGE_SIZE);
+ clear_bit(0x80, vmx_io_bitmap_a);
- va = kmap(vmx_io_bitmap_b);
- memset(va, 0xff, PAGE_SIZE);
- kunmap(vmx_io_bitmap_b);
+ memset(vmx_io_bitmap_b, 0xff, PAGE_SIZE);
- va = kmap(vmx_msr_bitmap);
- memset(va, 0xff, PAGE_SIZE);
- kunmap(vmx_msr_bitmap);
+ memset(vmx_msr_bitmap_legacy, 0xff, PAGE_SIZE);
+ memset(vmx_msr_bitmap_longmode, 0xff, PAGE_SIZE);
set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */
r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx), THIS_MODULE);
if (r)
- goto out2;
+ goto out3;
- vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_FS_BASE);
- vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_GS_BASE);
- vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_CS);
- vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_ESP);
- vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_EIP);
+ vmx_disable_intercept_for_msr(MSR_FS_BASE, false);
+ vmx_disable_intercept_for_msr(MSR_GS_BASE, false);
+ vmx_disable_intercept_for_msr(MSR_KERNEL_GS_BASE, true);
+ vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_CS, false);
+ vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP, false);
+ vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false);
- if (vm_need_ept()) {
+ if (enable_ept) {
bypass_guest_pf = 0;
kvm_mmu_set_base_ptes(VMX_EPT_READABLE_MASK |
VMX_EPT_WRITABLE_MASK);
kvm_mmu_set_mask_ptes(0ull, 0ull, 0ull, 0ull,
- VMX_EPT_EXECUTABLE_MASK,
- VMX_EPT_DEFAULT_MT << VMX_EPT_MT_EPTE_SHIFT);
+ VMX_EPT_EXECUTABLE_MASK);
kvm_enable_tdp();
} else
kvm_disable_tdp();
@@ -3761,20 +3733,23 @@ static int __init vmx_init(void)
return 0;
+out3:
+ free_page((unsigned long)vmx_msr_bitmap_longmode);
out2:
- __free_page(vmx_msr_bitmap);
+ free_page((unsigned long)vmx_msr_bitmap_legacy);
out1:
- __free_page(vmx_io_bitmap_b);
+ free_page((unsigned long)vmx_io_bitmap_b);
out:
- __free_page(vmx_io_bitmap_a);
+ free_page((unsigned long)vmx_io_bitmap_a);
return r;
}
static void __exit vmx_exit(void)
{
- __free_page(vmx_msr_bitmap);
- __free_page(vmx_io_bitmap_b);
- __free_page(vmx_io_bitmap_a);
+ free_page((unsigned long)vmx_msr_bitmap_legacy);
+ free_page((unsigned long)vmx_msr_bitmap_longmode);
+ free_page((unsigned long)vmx_io_bitmap_b);
+ free_page((unsigned long)vmx_io_bitmap_a);
kvm_exit();
}
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 8ca100a9ecac..c6d3ff3f7f97 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -91,7 +91,6 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
{ "halt_wakeup", VCPU_STAT(halt_wakeup) },
{ "hypercalls", VCPU_STAT(hypercalls) },
{ "request_irq", VCPU_STAT(request_irq_exits) },
- { "request_nmi", VCPU_STAT(request_nmi_exits) },
{ "irq_exits", VCPU_STAT(irq_exits) },
{ "host_state_reload", VCPU_STAT(host_state_reload) },
{ "efer_reload", VCPU_STAT(efer_reload) },
@@ -108,7 +107,6 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
{ "mmu_recycled", VM_STAT(mmu_recycled) },
{ "mmu_cache_miss", VM_STAT(mmu_cache_miss) },
{ "mmu_unsync", VM_STAT(mmu_unsync) },
- { "mmu_unsync_global", VM_STAT(mmu_unsync_global) },
{ "remote_tlb_flush", VM_STAT(remote_tlb_flush) },
{ "largepages", VM_STAT(lpages) },
{ NULL }
@@ -234,7 +232,8 @@ int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3)
goto out;
}
for (i = 0; i < ARRAY_SIZE(pdpte); ++i) {
- if ((pdpte[i] & 1) && (pdpte[i] & 0xfffffff0000001e6ull)) {
+ if (is_present_pte(pdpte[i]) &&
+ (pdpte[i] & vcpu->arch.mmu.rsvd_bits_mask[0][2])) {
ret = 0;
goto out;
}
@@ -321,7 +320,6 @@ void kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
kvm_x86_ops->set_cr0(vcpu, cr0);
vcpu->arch.cr0 = cr0;
- kvm_mmu_sync_global(vcpu);
kvm_mmu_reset_context(vcpu);
return;
}
@@ -366,7 +364,6 @@ void kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
kvm_x86_ops->set_cr4(vcpu, cr4);
vcpu->arch.cr4 = cr4;
vcpu->arch.mmu.base_role.cr4_pge = (cr4 & X86_CR4_PGE) && !tdp_enabled;
- kvm_mmu_sync_global(vcpu);
kvm_mmu_reset_context(vcpu);
}
EXPORT_SYMBOL_GPL(kvm_set_cr4);
@@ -519,6 +516,9 @@ static void set_efer(struct kvm_vcpu *vcpu, u64 efer)
efer |= vcpu->arch.shadow_efer & EFER_LMA;
vcpu->arch.shadow_efer = efer;
+
+ vcpu->arch.mmu.base_role.nxe = (efer & EFER_NX) && !tdp_enabled;
+ kvm_mmu_reset_context(vcpu);
}
void kvm_enable_efer_bits(u64 mask)
@@ -626,14 +626,17 @@ static void kvm_write_guest_time(struct kvm_vcpu *v)
unsigned long flags;
struct kvm_vcpu_arch *vcpu = &v->arch;
void *shared_kaddr;
+ unsigned long this_tsc_khz;
if ((!vcpu->time_page))
return;
- if (unlikely(vcpu->hv_clock_tsc_khz != __get_cpu_var(cpu_tsc_khz))) {
- kvm_set_time_scale(__get_cpu_var(cpu_tsc_khz), &vcpu->hv_clock);
- vcpu->hv_clock_tsc_khz = __get_cpu_var(cpu_tsc_khz);
+ this_tsc_khz = get_cpu_var(cpu_tsc_khz);
+ if (unlikely(vcpu->hv_clock_tsc_khz != this_tsc_khz)) {
+ kvm_set_time_scale(this_tsc_khz, &vcpu->hv_clock);
+ vcpu->hv_clock_tsc_khz = this_tsc_khz;
}
+ put_cpu_var(cpu_tsc_khz);
/* Keep irq disabled to prevent changes to the clock */
local_irq_save(flags);
@@ -889,6 +892,8 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
case MSR_IA32_LASTINTFROMIP:
case MSR_IA32_LASTINTTOIP:
case MSR_VM_HSAVE_PA:
+ case MSR_P6_EVNTSEL0:
+ case MSR_P6_EVNTSEL1:
data = 0;
break;
case MSR_MTRRcap:
@@ -1020,6 +1025,7 @@ int kvm_dev_ioctl_check_extension(long ext)
case KVM_CAP_SYNC_MMU:
case KVM_CAP_REINJECT_CONTROL:
case KVM_CAP_IRQ_INJECT_STATUS:
+ case KVM_CAP_ASSIGN_DEV_IRQ:
r = 1;
break;
case KVM_CAP_COALESCED_MMIO:
@@ -1121,9 +1127,9 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
static int is_efer_nx(void)
{
- u64 efer;
+ unsigned long long efer = 0;
- rdmsrl(MSR_EFER, efer);
+ rdmsrl_safe(MSR_EFER, &efer);
return efer & EFER_NX;
}
@@ -1237,41 +1243,53 @@ static void do_cpuid_1_ent(struct kvm_cpuid_entry2 *entry, u32 function,
entry->flags = 0;
}
+#define F(x) bit(X86_FEATURE_##x)
+
static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
u32 index, int *nent, int maxnent)
{
- const u32 kvm_supported_word0_x86_features = bit(X86_FEATURE_FPU) |
- bit(X86_FEATURE_VME) | bit(X86_FEATURE_DE) |
- bit(X86_FEATURE_PSE) | bit(X86_FEATURE_TSC) |
- bit(X86_FEATURE_MSR) | bit(X86_FEATURE_PAE) |
- bit(X86_FEATURE_CX8) | bit(X86_FEATURE_APIC) |
- bit(X86_FEATURE_SEP) | bit(X86_FEATURE_PGE) |
- bit(X86_FEATURE_CMOV) | bit(X86_FEATURE_PSE36) |
- bit(X86_FEATURE_CLFLSH) | bit(X86_FEATURE_MMX) |
- bit(X86_FEATURE_FXSR) | bit(X86_FEATURE_XMM) |
- bit(X86_FEATURE_XMM2) | bit(X86_FEATURE_SELFSNOOP);
- const u32 kvm_supported_word1_x86_features = bit(X86_FEATURE_FPU) |
- bit(X86_FEATURE_VME) | bit(X86_FEATURE_DE) |
- bit(X86_FEATURE_PSE) | bit(X86_FEATURE_TSC) |
- bit(X86_FEATURE_MSR) | bit(X86_FEATURE_PAE) |
- bit(X86_FEATURE_CX8) | bit(X86_FEATURE_APIC) |
- bit(X86_FEATURE_PGE) |
- bit(X86_FEATURE_CMOV) | bit(X86_FEATURE_PSE36) |
- bit(X86_FEATURE_MMX) | bit(X86_FEATURE_FXSR) |
- bit(X86_FEATURE_SYSCALL) |
- (bit(X86_FEATURE_NX) && is_efer_nx()) |
+ unsigned f_nx = is_efer_nx() ? F(NX) : 0;
#ifdef CONFIG_X86_64
- bit(X86_FEATURE_LM) |
+ unsigned f_lm = F(LM);
+#else
+ unsigned f_lm = 0
#endif
- bit(X86_FEATURE_FXSR_OPT) |
- bit(X86_FEATURE_MMXEXT) |
- bit(X86_FEATURE_3DNOWEXT) |
- bit(X86_FEATURE_3DNOW);
- const u32 kvm_supported_word3_x86_features =
- bit(X86_FEATURE_XMM3) | bit(X86_FEATURE_CX16);
+
+ /* cpuid 1.edx */
+ const u32 kvm_supported_word0_x86_features =
+ F(FPU) | F(VME) | F(DE) | F(PSE) |
+ F(TSC) | F(MSR) | F(PAE) | F(MCE) |
+ F(CX8) | F(APIC) | 0 /* Reserved */ | F(SEP) |
+ F(MTRR) | F(PGE) | F(MCA) | F(CMOV) |
+ F(PAT) | F(PSE36) | 0 /* PSN */ | F(CLFLSH) |
+ 0 /* Reserved, DS, ACPI */ | F(MMX) |
+ F(FXSR) | F(XMM) | F(XMM2) | F(SELFSNOOP) |
+ 0 /* HTT, TM, Reserved, PBE */;
+ /* cpuid 0x80000001.edx */
+ const u32 kvm_supported_word1_x86_features =
+ F(FPU) | F(VME) | F(DE) | F(PSE) |
+ F(TSC) | F(MSR) | F(PAE) | F(MCE) |
+ F(CX8) | F(APIC) | 0 /* Reserved */ | F(SYSCALL) |
+ F(MTRR) | F(PGE) | F(MCA) | F(CMOV) |
+ F(PAT) | F(PSE36) | 0 /* Reserved */ |
+ f_nx | 0 /* Reserved */ | F(MMXEXT) | F(MMX) |
+ F(FXSR) | F(FXSR_OPT) | 0 /* GBPAGES */ | 0 /* RDTSCP */ |
+ 0 /* Reserved */ | f_lm | F(3DNOWEXT) | F(3DNOW);
+ /* cpuid 1.ecx */
+ const u32 kvm_supported_word4_x86_features =
+ F(XMM3) | 0 /* Reserved, DTES64, MONITOR */ |
+ 0 /* DS-CPL, VMX, SMX, EST */ |
+ 0 /* TM2 */ | F(SSSE3) | 0 /* CNXT-ID */ | 0 /* Reserved */ |
+ 0 /* Reserved */ | F(CX16) | 0 /* xTPR Update, PDCM */ |
+ 0 /* Reserved, DCA */ | F(XMM4_1) |
+ F(XMM4_2) | 0 /* x2APIC */ | F(MOVBE) | F(POPCNT) |
+ 0 /* Reserved, XSAVE, OSXSAVE */;
+ /* cpuid 0x80000001.ecx */
const u32 kvm_supported_word6_x86_features =
- bit(X86_FEATURE_LAHF_LM) | bit(X86_FEATURE_CMP_LEGACY) |
- bit(X86_FEATURE_SVM);
+ F(LAHF_LM) | F(CMP_LEGACY) | F(SVM) | 0 /* ExtApicSpace */ |
+ F(CR8_LEGACY) | F(ABM) | F(SSE4A) | F(MISALIGNSSE) |
+ F(3DNOWPREFETCH) | 0 /* OSVW */ | 0 /* IBS */ | F(SSE5) |
+ 0 /* SKINIT */ | 0 /* WDT */;
/* all calls to cpuid_count() should be made on the same cpu */
get_cpu();
@@ -1284,7 +1302,7 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
break;
case 1:
entry->edx &= kvm_supported_word0_x86_features;
- entry->ecx &= kvm_supported_word3_x86_features;
+ entry->ecx &= kvm_supported_word4_x86_features;
break;
/* function 2 entries are STATEFUL. That is, repeated cpuid commands
* may return different values. This forces us to get_cpu() before
@@ -1346,6 +1364,8 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
put_cpu();
}
+#undef F
+
static int kvm_dev_ioctl_get_supported_cpuid(struct kvm_cpuid2 *cpuid,
struct kvm_cpuid_entry2 __user *entries)
{
@@ -1580,8 +1600,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
r = -EINVAL;
}
out:
- if (lapic)
- kfree(lapic);
+ kfree(lapic);
return r;
}
@@ -2404,6 +2423,11 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
}
}
+ if (emulation_type & EMULTYPE_SKIP) {
+ kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.decode.eip);
+ return EMULATE_DONE;
+ }
+
r = x86_emulate_insn(&vcpu->arch.emulate_ctxt, &emulate_ops);
if (vcpu->arch.pio.string)
@@ -2757,7 +2781,7 @@ int kvm_arch_init(void *opaque)
kvm_mmu_set_nonpresent_ptes(0ull, 0ull);
kvm_mmu_set_base_ptes(PT_PRESENT_MASK);
kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK,
- PT_DIRTY_MASK, PT64_NX_MASK, 0, 0);
+ PT_DIRTY_MASK, PT64_NX_MASK, 0);
for_each_possible_cpu(cpu)
per_cpu(cpu_tsc_khz, cpu) = tsc_khz;
@@ -2775,6 +2799,9 @@ out:
void kvm_arch_exit(void)
{
+ if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
+ cpufreq_unregister_notifier(&kvmclock_cpufreq_notifier_block,
+ CPUFREQ_TRANSITION_NOTIFIER);
kvm_x86_ops = NULL;
kvm_mmu_module_exit();
}
@@ -3005,6 +3032,16 @@ struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu,
return best;
}
+int cpuid_maxphyaddr(struct kvm_vcpu *vcpu)
+{
+ struct kvm_cpuid_entry2 *best;
+
+ best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0);
+ if (best)
+ return best->eax & 0xff;
+ return 36;
+}
+
void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
{
u32 function, index;
@@ -3041,10 +3078,9 @@ EXPORT_SYMBOL_GPL(kvm_emulate_cpuid);
static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu,
struct kvm_run *kvm_run)
{
- return (!vcpu->arch.irq_summary &&
+ return (!irqchip_in_kernel(vcpu->kvm) && !kvm_cpu_has_interrupt(vcpu) &&
kvm_run->request_interrupt_window &&
- vcpu->arch.interrupt_window_open &&
- (kvm_x86_ops->get_rflags(vcpu) & X86_EFLAGS_IF));
+ kvm_arch_interrupt_allowed(vcpu));
}
static void post_kvm_run_save(struct kvm_vcpu *vcpu,
@@ -3057,8 +3093,8 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu,
kvm_run->ready_for_interrupt_injection = 1;
else
kvm_run->ready_for_interrupt_injection =
- (vcpu->arch.interrupt_window_open &&
- vcpu->arch.irq_summary == 0);
+ (kvm_arch_interrupt_allowed(vcpu) &&
+ !kvm_cpu_has_interrupt(vcpu));
}
static void vapic_enter(struct kvm_vcpu *vcpu)
@@ -3087,6 +3123,68 @@ static void vapic_exit(struct kvm_vcpu *vcpu)
up_read(&vcpu->kvm->slots_lock);
}
+static void update_cr8_intercept(struct kvm_vcpu *vcpu)
+{
+ int max_irr, tpr;
+
+ if (!kvm_x86_ops->update_cr8_intercept)
+ return;
+
+ max_irr = kvm_lapic_find_highest_irr(vcpu);
+
+ if (max_irr != -1)
+ max_irr >>= 4;
+
+ tpr = kvm_lapic_get_cr8(vcpu);
+
+ kvm_x86_ops->update_cr8_intercept(vcpu, tpr, max_irr);
+}
+
+static void inject_irq(struct kvm_vcpu *vcpu)
+{
+ /* try to reinject previous events if any */
+ if (vcpu->arch.nmi_injected) {
+ kvm_x86_ops->set_nmi(vcpu);
+ return;
+ }
+
+ if (vcpu->arch.interrupt.pending) {
+ kvm_x86_ops->set_irq(vcpu, vcpu->arch.interrupt.nr);
+ return;
+ }
+
+ /* try to inject new event if pending */
+ if (vcpu->arch.nmi_pending) {
+ if (kvm_x86_ops->nmi_allowed(vcpu)) {
+ vcpu->arch.nmi_pending = false;
+ vcpu->arch.nmi_injected = true;
+ kvm_x86_ops->set_nmi(vcpu);
+ }
+ } else if (kvm_cpu_has_interrupt(vcpu)) {
+ if (kvm_x86_ops->interrupt_allowed(vcpu)) {
+ kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
+ kvm_x86_ops->set_irq(vcpu, vcpu->arch.interrupt.nr);
+ }
+ }
+}
+
+static void inject_pending_irq(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ bool req_int_win = !irqchip_in_kernel(vcpu->kvm) &&
+ kvm_run->request_interrupt_window;
+
+ if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
+ kvm_x86_ops->drop_interrupt_shadow(vcpu);
+
+ inject_irq(vcpu);
+
+ /* enable NMI/IRQ window open exits if needed */
+ if (vcpu->arch.nmi_pending)
+ kvm_x86_ops->enable_nmi_window(vcpu);
+ else if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
+ kvm_x86_ops->enable_irq_window(vcpu);
+}
+
static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
int r;
@@ -3121,9 +3219,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
}
}
- clear_bit(KVM_REQ_PENDING_TIMER, &vcpu->requests);
- kvm_inject_pending_timer_irqs(vcpu);
-
preempt_disable();
kvm_x86_ops->prepare_guest_switch(vcpu);
@@ -3131,6 +3226,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
local_irq_disable();
+ clear_bit(KVM_REQ_KICK, &vcpu->requests);
+ smp_mb__after_clear_bit();
+
if (vcpu->requests || need_resched() || signal_pending(current)) {
local_irq_enable();
preempt_enable();
@@ -3138,21 +3236,17 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
goto out;
}
- vcpu->guest_mode = 1;
- /*
- * Make sure that guest_mode assignment won't happen after
- * testing the pending IRQ vector bitmap.
- */
- smp_wmb();
-
if (vcpu->arch.exception.pending)
__queue_exception(vcpu);
- else if (irqchip_in_kernel(vcpu->kvm))
- kvm_x86_ops->inject_pending_irq(vcpu);
else
- kvm_x86_ops->inject_pending_vectors(vcpu, kvm_run);
+ inject_pending_irq(vcpu, kvm_run);
- kvm_lapic_sync_to_vapic(vcpu);
+ if (kvm_lapic_enabled(vcpu)) {
+ if (!vcpu->arch.apic->vapic_addr)
+ update_cr8_intercept(vcpu);
+ else
+ kvm_lapic_sync_to_vapic(vcpu);
+ }
up_read(&vcpu->kvm->slots_lock);
@@ -3186,7 +3280,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
set_debugreg(vcpu->arch.host_dr6, 6);
set_debugreg(vcpu->arch.host_dr7, 7);
- vcpu->guest_mode = 0;
+ set_bit(KVM_REQ_KICK, &vcpu->requests);
local_irq_enable();
++vcpu->stat.exits;
@@ -3213,8 +3307,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
profile_hit(KVM_PROFILING, (void *)rip);
}
- if (vcpu->arch.exception.pending && kvm_x86_ops->exception_injected(vcpu))
- vcpu->arch.exception.pending = false;
kvm_lapic_sync_from_vapic(vcpu);
@@ -3223,6 +3315,7 @@ out:
return r;
}
+
static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
int r;
@@ -3249,29 +3342,42 @@ static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
kvm_vcpu_block(vcpu);
down_read(&vcpu->kvm->slots_lock);
if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests))
- if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED)
+ {
+ switch(vcpu->arch.mp_state) {
+ case KVM_MP_STATE_HALTED:
vcpu->arch.mp_state =
- KVM_MP_STATE_RUNNABLE;
- if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE)
- r = -EINTR;
+ KVM_MP_STATE_RUNNABLE;
+ case KVM_MP_STATE_RUNNABLE:
+ break;
+ case KVM_MP_STATE_SIPI_RECEIVED:
+ default:
+ r = -EINTR;
+ break;
+ }
+ }
}
- if (r > 0) {
- if (dm_request_for_irq_injection(vcpu, kvm_run)) {
- r = -EINTR;
- kvm_run->exit_reason = KVM_EXIT_INTR;
- ++vcpu->stat.request_irq_exits;
- }
- if (signal_pending(current)) {
- r = -EINTR;
- kvm_run->exit_reason = KVM_EXIT_INTR;
- ++vcpu->stat.signal_exits;
- }
- if (need_resched()) {
- up_read(&vcpu->kvm->slots_lock);
- kvm_resched(vcpu);
- down_read(&vcpu->kvm->slots_lock);
- }
+ if (r <= 0)
+ break;
+
+ clear_bit(KVM_REQ_PENDING_TIMER, &vcpu->requests);
+ if (kvm_cpu_has_pending_timer(vcpu))
+ kvm_inject_pending_timer_irqs(vcpu);
+
+ if (dm_request_for_irq_injection(vcpu, kvm_run)) {
+ r = -EINTR;
+ kvm_run->exit_reason = KVM_EXIT_INTR;
+ ++vcpu->stat.request_irq_exits;
+ }
+ if (signal_pending(current)) {
+ r = -EINTR;
+ kvm_run->exit_reason = KVM_EXIT_INTR;
+ ++vcpu->stat.signal_exits;
+ }
+ if (need_resched()) {
+ up_read(&vcpu->kvm->slots_lock);
+ kvm_resched(vcpu);
+ down_read(&vcpu->kvm->slots_lock);
}
}
@@ -3435,7 +3541,6 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
struct kvm_sregs *sregs)
{
struct descriptor_table dt;
- int pending_vec;
vcpu_load(vcpu);
@@ -3465,17 +3570,17 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
sregs->efer = vcpu->arch.shadow_efer;
sregs->apic_base = kvm_get_apic_base(vcpu);
- if (irqchip_in_kernel(vcpu->kvm)) {
+ if (irqchip_in_kernel(vcpu->kvm))
memset(sregs->interrupt_bitmap, 0,
sizeof sregs->interrupt_bitmap);
- pending_vec = kvm_x86_ops->get_irq(vcpu);
- if (pending_vec >= 0)
- set_bit(pending_vec,
- (unsigned long *)sregs->interrupt_bitmap);
- } else
+ else
memcpy(sregs->interrupt_bitmap, vcpu->arch.irq_pending,
sizeof sregs->interrupt_bitmap);
+ if (vcpu->arch.interrupt.pending)
+ set_bit(vcpu->arch.interrupt.nr,
+ (unsigned long *)sregs->interrupt_bitmap);
+
vcpu_put(vcpu);
return 0;
@@ -3681,7 +3786,6 @@ static void save_state_to_tss32(struct kvm_vcpu *vcpu,
tss->fs = get_segment_selector(vcpu, VCPU_SREG_FS);
tss->gs = get_segment_selector(vcpu, VCPU_SREG_GS);
tss->ldt_selector = get_segment_selector(vcpu, VCPU_SREG_LDTR);
- tss->prev_task_link = get_segment_selector(vcpu, VCPU_SREG_TR);
}
static int load_state_from_tss32(struct kvm_vcpu *vcpu,
@@ -3778,8 +3882,8 @@ static int load_state_from_tss16(struct kvm_vcpu *vcpu,
}
static int kvm_task_switch_16(struct kvm_vcpu *vcpu, u16 tss_selector,
- u32 old_tss_base,
- struct desc_struct *nseg_desc)
+ u16 old_tss_sel, u32 old_tss_base,
+ struct desc_struct *nseg_desc)
{
struct tss_segment_16 tss_segment_16;
int ret = 0;
@@ -3798,6 +3902,16 @@ static int kvm_task_switch_16(struct kvm_vcpu *vcpu, u16 tss_selector,
&tss_segment_16, sizeof tss_segment_16))
goto out;
+ if (old_tss_sel != 0xffff) {
+ tss_segment_16.prev_task_link = old_tss_sel;
+
+ if (kvm_write_guest(vcpu->kvm,
+ get_tss_base_addr(vcpu, nseg_desc),
+ &tss_segment_16.prev_task_link,
+ sizeof tss_segment_16.prev_task_link))
+ goto out;
+ }
+
if (load_state_from_tss16(vcpu, &tss_segment_16))
goto out;
@@ -3807,7 +3921,7 @@ out:
}
static int kvm_task_switch_32(struct kvm_vcpu *vcpu, u16 tss_selector,
- u32 old_tss_base,
+ u16 old_tss_sel, u32 old_tss_base,
struct desc_struct *nseg_desc)
{
struct tss_segment_32 tss_segment_32;
@@ -3827,6 +3941,16 @@ static int kvm_task_switch_32(struct kvm_vcpu *vcpu, u16 tss_selector,
&tss_segment_32, sizeof tss_segment_32))
goto out;
+ if (old_tss_sel != 0xffff) {
+ tss_segment_32.prev_task_link = old_tss_sel;
+
+ if (kvm_write_guest(vcpu->kvm,
+ get_tss_base_addr(vcpu, nseg_desc),
+ &tss_segment_32.prev_task_link,
+ sizeof tss_segment_32.prev_task_link))
+ goto out;
+ }
+
if (load_state_from_tss32(vcpu, &tss_segment_32))
goto out;
@@ -3880,14 +4004,22 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason)
kvm_x86_ops->set_rflags(vcpu, eflags & ~X86_EFLAGS_NT);
}
- kvm_x86_ops->skip_emulated_instruction(vcpu);
+ /* set back link to prev task only if NT bit is set in eflags
+ note that old_tss_sel is not used afetr this point */
+ if (reason != TASK_SWITCH_CALL && reason != TASK_SWITCH_GATE)
+ old_tss_sel = 0xffff;
+
+ /* set back link to prev task only if NT bit is set in eflags
+ note that old_tss_sel is not used afetr this point */
+ if (reason != TASK_SWITCH_CALL && reason != TASK_SWITCH_GATE)
+ old_tss_sel = 0xffff;
if (nseg_desc.type & 8)
- ret = kvm_task_switch_32(vcpu, tss_selector, old_tss_base,
- &nseg_desc);
+ ret = kvm_task_switch_32(vcpu, tss_selector, old_tss_sel,
+ old_tss_base, &nseg_desc);
else
- ret = kvm_task_switch_16(vcpu, tss_selector, old_tss_base,
- &nseg_desc);
+ ret = kvm_task_switch_16(vcpu, tss_selector, old_tss_sel,
+ old_tss_base, &nseg_desc);
if (reason == TASK_SWITCH_CALL || reason == TASK_SWITCH_GATE) {
u32 eflags = kvm_x86_ops->get_rflags(vcpu);
@@ -3927,7 +4059,13 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
vcpu->arch.cr2 = sregs->cr2;
mmu_reset_needed |= vcpu->arch.cr3 != sregs->cr3;
- vcpu->arch.cr3 = sregs->cr3;
+
+ down_read(&vcpu->kvm->slots_lock);
+ if (gfn_to_memslot(vcpu->kvm, sregs->cr3 >> PAGE_SHIFT))
+ vcpu->arch.cr3 = sregs->cr3;
+ else
+ set_bit(KVM_REQ_TRIPLE_FAULT, &vcpu->requests);
+ up_read(&vcpu->kvm->slots_lock);
kvm_set_cr8(vcpu, sregs->cr8);
@@ -3963,9 +4101,8 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
max_bits);
/* Only pending external irq is handled here */
if (pending_vec < max_bits) {
- kvm_x86_ops->set_irq(vcpu, pending_vec);
- pr_debug("Set back pending irq %d\n",
- pending_vec);
+ kvm_queue_interrupt(vcpu, pending_vec);
+ pr_debug("Set back pending irq %d\n", pending_vec);
}
kvm_pic_clear_isr_ack(vcpu->kvm);
}
@@ -4159,6 +4296,11 @@ EXPORT_SYMBOL_GPL(kvm_put_guest_fpu);
void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
{
+ if (vcpu->arch.time_page) {
+ kvm_release_page_dirty(vcpu->arch.time_page);
+ vcpu->arch.time_page = NULL;
+ }
+
kvm_x86_ops->vcpu_free(vcpu);
}
@@ -4296,7 +4438,6 @@ struct kvm *kvm_arch_create_vm(void)
return ERR_PTR(-ENOMEM);
INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
- INIT_LIST_HEAD(&kvm->arch.oos_global_pages);
INIT_LIST_HEAD(&kvm->arch.assigned_dev_head);
/* Reserve bit 0 of irq_sources_bitmap for userspace irq source */
@@ -4422,28 +4563,24 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
|| vcpu->arch.nmi_pending;
}
-static void vcpu_kick_intr(void *info)
-{
-#ifdef DEBUG
- struct kvm_vcpu *vcpu = (struct kvm_vcpu *)info;
- printk(KERN_DEBUG "vcpu_kick_intr %p \n", vcpu);
-#endif
-}
-
void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
{
- int ipi_pcpu = vcpu->cpu;
- int cpu = get_cpu();
+ int me;
+ int cpu = vcpu->cpu;
if (waitqueue_active(&vcpu->wq)) {
wake_up_interruptible(&vcpu->wq);
++vcpu->stat.halt_wakeup;
}
- /*
- * We may be called synchronously with irqs disabled in guest mode,
- * So need not to call smp_call_function_single() in that case.
- */
- if (vcpu->guest_mode && vcpu->cpu != cpu)
- smp_call_function_single(ipi_pcpu, vcpu_kick_intr, vcpu, 0);
+
+ me = get_cpu();
+ if (cpu != me && (unsigned)cpu < nr_cpu_ids && cpu_online(cpu))
+ if (!test_and_set_bit(KVM_REQ_KICK, &vcpu->requests))
+ smp_send_reschedule(cpu);
put_cpu();
}
+
+int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu)
+{
+ return kvm_x86_ops->interrupt_allowed(vcpu);
+}
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index 6a4be78a7384..39350b252725 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -19,4 +19,15 @@ static inline void kvm_clear_interrupt_queue(struct kvm_vcpu *vcpu)
vcpu->arch.interrupt.pending = false;
}
+static inline u8 kvm_pop_irq(struct kvm_vcpu *vcpu)
+{
+ int word_index = __ffs(vcpu->arch.irq_summary);
+ int bit_index = __ffs(vcpu->arch.irq_pending[word_index]);
+ int irq = word_index * BITS_PER_LONG + bit_index;
+
+ clear_bit(bit_index, &vcpu->arch.irq_pending[word_index]);
+ if (!vcpu->arch.irq_pending[word_index])
+ clear_bit(word_index, &vcpu->arch.irq_summary);
+ return irq;
+}
#endif
diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c
index ca91749d2083..d2664fcba7fa 100644
--- a/arch/x86/kvm/x86_emulate.c
+++ b/arch/x86/kvm/x86_emulate.c
@@ -59,13 +59,14 @@
#define SrcImm (5<<4) /* Immediate operand. */
#define SrcImmByte (6<<4) /* 8-bit sign-extended immediate operand. */
#define SrcOne (7<<4) /* Implied '1' */
-#define SrcMask (7<<4)
+#define SrcImmUByte (8<<4) /* 8-bit unsigned immediate operand. */
+#define SrcMask (0xf<<4)
/* Generic ModRM decode. */
-#define ModRM (1<<7)
+#define ModRM (1<<8)
/* Destination is only written; never read. */
-#define Mov (1<<8)
-#define BitOp (1<<9)
-#define MemAbs (1<<10) /* Memory operand is absolute displacement */
+#define Mov (1<<9)
+#define BitOp (1<<10)
+#define MemAbs (1<<11) /* Memory operand is absolute displacement */
#define String (1<<12) /* String instruction (rep capable) */
#define Stack (1<<13) /* Stack instruction (push/pop) */
#define Group (1<<14) /* Bits 3:5 of modrm byte extend opcode */
@@ -76,6 +77,7 @@
#define Src2CL (1<<29)
#define Src2ImmByte (2<<29)
#define Src2One (3<<29)
+#define Src2Imm16 (4<<29)
#define Src2Mask (7<<29)
enum {
@@ -135,11 +137,11 @@ static u32 opcode_table[256] = {
SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps, /* insb, insw/insd */
SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps, /* outsb, outsw/outsd */
/* 0x70 - 0x77 */
- ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
- ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
+ SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte,
+ SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte,
/* 0x78 - 0x7F */
- ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
- ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
+ SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte,
+ SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte,
/* 0x80 - 0x87 */
Group | Group1_80, Group | Group1_81,
Group | Group1_82, Group | Group1_83,
@@ -153,7 +155,8 @@ static u32 opcode_table[256] = {
/* 0x90 - 0x97 */
DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg,
/* 0x98 - 0x9F */
- 0, 0, 0, 0, ImplicitOps | Stack, ImplicitOps | Stack, 0, 0,
+ 0, 0, SrcImm | Src2Imm16, 0,
+ ImplicitOps | Stack, ImplicitOps | Stack, 0, 0,
/* 0xA0 - 0xA7 */
ByteOp | DstReg | SrcMem | Mov | MemAbs, DstReg | SrcMem | Mov | MemAbs,
ByteOp | DstMem | SrcReg | Mov | MemAbs, DstMem | SrcReg | Mov | MemAbs,
@@ -178,7 +181,8 @@ static u32 opcode_table[256] = {
0, ImplicitOps | Stack, 0, 0,
ByteOp | DstMem | SrcImm | ModRM | Mov, DstMem | SrcImm | ModRM | Mov,
/* 0xC8 - 0xCF */
- 0, 0, 0, ImplicitOps | Stack, 0, 0, 0, 0,
+ 0, 0, 0, ImplicitOps | Stack,
+ ImplicitOps, SrcImmByte, ImplicitOps, ImplicitOps,
/* 0xD0 - 0xD7 */
ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM,
ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM,
@@ -187,11 +191,11 @@ static u32 opcode_table[256] = {
0, 0, 0, 0, 0, 0, 0, 0,
/* 0xE0 - 0xE7 */
0, 0, 0, 0,
- SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps,
- SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps,
+ ByteOp | SrcImmUByte, SrcImmUByte,
+ ByteOp | SrcImmUByte, SrcImmUByte,
/* 0xE8 - 0xEF */
- ImplicitOps | Stack, SrcImm | ImplicitOps,
- ImplicitOps, SrcImmByte | ImplicitOps,
+ SrcImm | Stack, SrcImm | ImplicitOps,
+ SrcImm | Src2Imm16, SrcImmByte | ImplicitOps,
SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps,
SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps,
/* 0xF0 - 0xF7 */
@@ -230,10 +234,8 @@ static u32 twobyte_table[256] = {
/* 0x70 - 0x7F */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x80 - 0x8F */
- ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
- ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
- ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
- ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
+ SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm,
+ SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm,
/* 0x90 - 0x9F */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xA0 - 0xA7 */
@@ -1044,10 +1046,14 @@ done_prefixes:
}
break;
case SrcImmByte:
+ case SrcImmUByte:
c->src.type = OP_IMM;
c->src.ptr = (unsigned long *)c->eip;
c->src.bytes = 1;
- c->src.val = insn_fetch(s8, 1, c->eip);
+ if ((c->d & SrcMask) == SrcImmByte)
+ c->src.val = insn_fetch(s8, 1, c->eip);
+ else
+ c->src.val = insn_fetch(u8, 1, c->eip);
break;
case SrcOne:
c->src.bytes = 1;
@@ -1072,6 +1078,12 @@ done_prefixes:
c->src2.bytes = 1;
c->src2.val = insn_fetch(u8, 1, c->eip);
break;
+ case Src2Imm16:
+ c->src2.type = OP_IMM;
+ c->src2.ptr = (unsigned long *)c->eip;
+ c->src2.bytes = 2;
+ c->src2.val = insn_fetch(u16, 2, c->eip);
+ break;
case Src2One:
c->src2.bytes = 1;
c->src2.val = 1;
@@ -1531,13 +1543,10 @@ special_insn:
return -1;
}
return 0;
- case 0x70 ... 0x7f: /* jcc (short) */ {
- int rel = insn_fetch(s8, 1, c->eip);
-
+ case 0x70 ... 0x7f: /* jcc (short) */
if (test_cc(c->b, ctxt->eflags))
- jmp_rel(c, rel);
+ jmp_rel(c, c->src.val);
break;
- }
case 0x80 ... 0x83: /* Grp1 */
switch (c->modrm_reg) {
case 0:
@@ -1769,59 +1778,32 @@ special_insn:
break;
case 0xe4: /* inb */
case 0xe5: /* in */
- port = insn_fetch(u8, 1, c->eip);
+ port = c->src.val;
io_dir_in = 1;
goto do_io;
case 0xe6: /* outb */
case 0xe7: /* out */
- port = insn_fetch(u8, 1, c->eip);
+ port = c->src.val;
io_dir_in = 0;
goto do_io;
case 0xe8: /* call (near) */ {
- long int rel;
- switch (c->op_bytes) {
- case 2:
- rel = insn_fetch(s16, 2, c->eip);
- break;
- case 4:
- rel = insn_fetch(s32, 4, c->eip);
- break;
- default:
- DPRINTF("Call: Invalid op_bytes\n");
- goto cannot_emulate;
- }
+ long int rel = c->src.val;
c->src.val = (unsigned long) c->eip;
jmp_rel(c, rel);
- c->op_bytes = c->ad_bytes;
emulate_push(ctxt);
break;
}
case 0xe9: /* jmp rel */
goto jmp;
- case 0xea: /* jmp far */ {
- uint32_t eip;
- uint16_t sel;
-
- switch (c->op_bytes) {
- case 2:
- eip = insn_fetch(u16, 2, c->eip);
- break;
- case 4:
- eip = insn_fetch(u32, 4, c->eip);
- break;
- default:
- DPRINTF("jmp far: Invalid op_bytes\n");
- goto cannot_emulate;
- }
- sel = insn_fetch(u16, 2, c->eip);
- if (kvm_load_segment_descriptor(ctxt->vcpu, sel, 9, VCPU_SREG_CS) < 0) {
+ case 0xea: /* jmp far */
+ if (kvm_load_segment_descriptor(ctxt->vcpu, c->src2.val, 9,
+ VCPU_SREG_CS) < 0) {
DPRINTF("jmp far: Failed to load CS descriptor\n");
goto cannot_emulate;
}
- c->eip = eip;
+ c->eip = c->src.val;
break;
- }
case 0xeb:
jmp: /* jmp rel short */
jmp_rel(c, c->src.val);
@@ -2039,28 +2021,11 @@ twobyte_insn:
if (!test_cc(c->b, ctxt->eflags))
c->dst.type = OP_NONE; /* no writeback */
break;
- case 0x80 ... 0x8f: /* jnz rel, etc*/ {
- long int rel;
-
- switch (c->op_bytes) {
- case 2:
- rel = insn_fetch(s16, 2, c->eip);
- break;
- case 4:
- rel = insn_fetch(s32, 4, c->eip);
- break;
- case 8:
- rel = insn_fetch(s64, 8, c->eip);
- break;
- default:
- DPRINTF("jnz: Invalid op_bytes\n");
- goto cannot_emulate;
- }
+ case 0x80 ... 0x8f: /* jnz rel, etc*/
if (test_cc(c->b, ctxt->eflags))
- jmp_rel(c, rel);
+ jmp_rel(c, c->src.val);
c->dst.type = OP_NONE;
break;
- }
case 0xa3:
bt: /* bt */
c->dst.type = OP_NONE;
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index e94a11e42f98..da1d5a276bc5 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -166,10 +166,16 @@ static void lazy_hcall3(unsigned long call,
/* When lazy mode is turned off reset the per-cpu lazy mode variable and then
* issue the do-nothing hypercall to flush any stored calls. */
-static void lguest_leave_lazy_mode(void)
+static void lguest_leave_lazy_mmu_mode(void)
{
- paravirt_leave_lazy(paravirt_get_lazy_mode());
kvm_hypercall0(LHCALL_FLUSH_ASYNC);
+ paravirt_leave_lazy_mmu();
+}
+
+static void lguest_end_context_switch(struct task_struct *next)
+{
+ kvm_hypercall0(LHCALL_FLUSH_ASYNC);
+ paravirt_end_context_switch(next);
}
/*G:033
@@ -273,15 +279,15 @@ static void lguest_load_idt(const struct desc_ptr *desc)
* controls the entire thing and the Guest asks it to make changes using the
* LOAD_GDT hypercall.
*
- * This is the opposite of the IDT code where we have a LOAD_IDT_ENTRY
- * hypercall and use that repeatedly to load a new IDT. I don't think it
- * really matters, but wouldn't it be nice if they were the same? Wouldn't
- * it be even better if you were the one to send the patch to fix it?
+ * This is the exactly like the IDT code.
*/
static void lguest_load_gdt(const struct desc_ptr *desc)
{
- BUG_ON((desc->size + 1) / 8 != GDT_ENTRIES);
- kvm_hypercall2(LHCALL_LOAD_GDT, __pa(desc->address), GDT_ENTRIES);
+ unsigned int i;
+ struct desc_struct *gdt = (void *)desc->address;
+
+ for (i = 0; i < (desc->size+1)/8; i++)
+ kvm_hypercall3(LHCALL_LOAD_GDT_ENTRY, i, gdt[i].a, gdt[i].b);
}
/* For a single GDT entry which changes, we do the lazy thing: alter our GDT,
@@ -291,7 +297,9 @@ static void lguest_write_gdt_entry(struct desc_struct *dt, int entrynum,
const void *desc, int type)
{
native_write_gdt_entry(dt, entrynum, desc, type);
- kvm_hypercall2(LHCALL_LOAD_GDT, __pa(dt), GDT_ENTRIES);
+ /* Tell Host about this new entry. */
+ kvm_hypercall3(LHCALL_LOAD_GDT_ENTRY, entrynum,
+ dt[entrynum].a, dt[entrynum].b);
}
/* OK, I lied. There are three "thread local storage" GDT entries which change
@@ -634,7 +642,7 @@ static void __init lguest_init_IRQ(void)
void lguest_setup_irq(unsigned int irq)
{
- irq_to_desc_alloc_cpu(irq, 0);
+ irq_to_desc_alloc_node(irq, 0);
set_irq_chip_and_handler_name(irq, &lguest_irq_controller,
handle_level_irq, "level");
}
@@ -661,7 +669,7 @@ static unsigned long lguest_tsc_khz(void)
/* If we can't use the TSC, the kernel falls back to our lower-priority
* "lguest_clock", where we read the time value given to us by the Host. */
-static cycle_t lguest_clock_read(void)
+static cycle_t lguest_clock_read(struct clocksource *cs)
{
unsigned long sec, nsec;
@@ -1051,8 +1059,8 @@ __init void lguest_init(void)
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;
+ pv_cpu_ops.start_context_switch = paravirt_start_context_switch;
+ pv_cpu_ops.end_context_switch = lguest_end_context_switch;
/* pagetable management */
pv_mmu_ops.write_cr3 = lguest_write_cr3;
@@ -1065,7 +1073,7 @@ __init void lguest_init(void)
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;
+ pv_mmu_ops.lazy_mode.leave = lguest_leave_lazy_mmu_mode;
pv_mmu_ops.pte_update = lguest_pte_update;
pv_mmu_ops.pte_update_defer = lguest_pte_update;
diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c
index e7277cbcfb40..a725b7f760ae 100644
--- a/arch/x86/mm/dump_pagetables.c
+++ b/arch/x86/mm/dump_pagetables.c
@@ -161,13 +161,14 @@ static void note_page(struct seq_file *m, struct pg_state *st,
st->current_address >= st->marker[1].start_address) {
const char *unit = units;
unsigned long delta;
+ int width = sizeof(unsigned long) * 2;
/*
* Now print the actual finished series
*/
- seq_printf(m, "0x%p-0x%p ",
- (void *)st->start_address,
- (void *)st->current_address);
+ seq_printf(m, "0x%0*lx-0x%0*lx ",
+ width, st->start_address,
+ width, st->current_address);
delta = (st->current_address - st->start_address) >> 10;
while (!(delta & 1023) && unit[1]) {
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index a03b7279efa0..5ec7ae366615 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -3,40 +3,16 @@
* Copyright (C) 2001, 2002 Andi Kleen, SuSE Labs.
* Copyright (C) 2008-2009, Red Hat Inc., Ingo Molnar
*/
-#include <linux/interrupt.h>
-#include <linux/mmiotrace.h>
-#include <linux/bootmem.h>
-#include <linux/compiler.h>
-#include <linux/highmem.h>
-#include <linux/kprobes.h>
-#include <linux/uaccess.h>
-#include <linux/vmalloc.h>
-#include <linux/vt_kern.h>
-#include <linux/signal.h>
-#include <linux/kernel.h>
-#include <linux/ptrace.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/kdebug.h>
-#include <linux/errno.h>
-#include <linux/magic.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/mman.h>
-#include <linux/tty.h>
-#include <linux/smp.h>
-#include <linux/mm.h>
-
-#include <asm-generic/sections.h>
-
-#include <asm/tlbflush.h>
-#include <asm/pgalloc.h>
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <asm/proto.h>
-#include <asm/traps.h>
-#include <asm/desc.h>
+#include <linux/magic.h> /* STACK_END_MAGIC */
+#include <linux/sched.h> /* test_thread_flag(), ... */
+#include <linux/kdebug.h> /* oops_begin/end, ... */
+#include <linux/module.h> /* search_exception_table */
+#include <linux/bootmem.h> /* max_low_pfn */
+#include <linux/kprobes.h> /* __kprobes, ... */
+#include <linux/mmiotrace.h> /* kmmio_handler, ... */
+
+#include <asm/traps.h> /* dotraplinkage, ... */
+#include <asm/pgalloc.h> /* pgd_*(), ... */
/*
* Page fault error code bits:
@@ -225,12 +201,10 @@ static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
if (!pmd_present(*pmd_k))
return NULL;
- if (!pmd_present(*pmd)) {
+ if (!pmd_present(*pmd))
set_pmd(pmd, *pmd_k);
- arch_flush_lazy_mmu_mode();
- } else {
+ else
BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
- }
return pmd_k;
}
@@ -538,8 +512,6 @@ bad:
static int is_errata93(struct pt_regs *regs, unsigned long address)
{
#ifdef CONFIG_X86_64
- static int once;
-
if (address != regs->ip)
return 0;
@@ -549,10 +521,7 @@ static int is_errata93(struct pt_regs *regs, unsigned long address)
address |= 0xffffffffUL << 32;
if ((address >= (u64)_stext && address <= (u64)_etext) ||
(address >= MODULES_VADDR && address <= MODULES_END)) {
- if (!once) {
- printk(errata93_warning);
- once = 1;
- }
+ printk_once(errata93_warning);
regs->ip = address;
return 1;
}
diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c
index 8126e8d1a2a4..58f621e81919 100644
--- a/arch/x86/mm/highmem_32.c
+++ b/arch/x86/mm/highmem_32.c
@@ -44,7 +44,6 @@ void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
BUG_ON(!pte_none(*(kmap_pte-idx)));
set_pte(kmap_pte-idx, mk_pte(page, prot));
- arch_flush_lazy_mmu_mode();
return (void *)vaddr;
}
@@ -74,7 +73,6 @@ void kunmap_atomic(void *kvaddr, enum km_type type)
#endif
}
- arch_flush_lazy_mmu_mode();
pagefault_enable();
}
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index fd3da1dda1c9..5a48ffa58838 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -1,3 +1,4 @@
+#include <linux/initrd.h>
#include <linux/ioport.h>
#include <linux/swap.h>
@@ -7,8 +8,12 @@
#include <asm/page.h>
#include <asm/page_types.h>
#include <asm/sections.h>
+#include <asm/setup.h>
#include <asm/system.h>
#include <asm/tlbflush.h>
+#include <asm/tlb.h>
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
unsigned long __initdata e820_table_start;
unsigned long __meminitdata e820_table_end;
@@ -22,6 +27,69 @@ int direct_gbpages
#endif
;
+int nx_enabled;
+
+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
+static int disable_nx __cpuinitdata;
+
+/*
+ * noexec = on|off
+ *
+ * Control non-executable mappings for processes.
+ *
+ * on Enable
+ * off Disable
+ */
+static int __init noexec_setup(char *str)
+{
+ if (!str)
+ return -EINVAL;
+ if (!strncmp(str, "on", 2)) {
+ __supported_pte_mask |= _PAGE_NX;
+ disable_nx = 0;
+ } else if (!strncmp(str, "off", 3)) {
+ disable_nx = 1;
+ __supported_pte_mask &= ~_PAGE_NX;
+ }
+ return 0;
+}
+early_param("noexec", noexec_setup);
+#endif
+
+#ifdef CONFIG_X86_PAE
+static void __init set_nx(void)
+{
+ unsigned int v[4], l, h;
+
+ if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) {
+ cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]);
+
+ if ((v[3] & (1 << 20)) && !disable_nx) {
+ rdmsr(MSR_EFER, l, h);
+ l |= EFER_NX;
+ wrmsr(MSR_EFER, l, h);
+ nx_enabled = 1;
+ __supported_pte_mask |= _PAGE_NX;
+ }
+ }
+}
+#else
+static inline void set_nx(void)
+{
+}
+#endif
+
+#ifdef CONFIG_X86_64
+void __cpuinit check_efer(void)
+{
+ unsigned long efer;
+
+ rdmsrl(MSR_EFER, efer);
+ if (!(efer & EFER_NX) || disable_nx)
+ __supported_pte_mask &= ~_PAGE_NX;
+}
+#endif
+
static void __init find_early_table_space(unsigned long end, int use_pse,
int use_gbpages)
{
@@ -158,12 +226,9 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
use_gbpages = direct_gbpages;
#endif
-#ifdef CONFIG_X86_32
-#ifdef CONFIG_X86_PAE
set_nx();
if (nx_enabled)
printk(KERN_INFO "NX (Execute Disable) protection: active\n");
-#endif
/* Enable PSE if available */
if (cpu_has_pse)
@@ -174,7 +239,6 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
set_in_cr4(X86_CR4_PGE);
__supported_pte_mask |= _PAGE_GLOBAL;
}
-#endif
if (use_gbpages)
page_size_mask |= 1 << PG_LEVEL_1G;
@@ -304,8 +368,23 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
#endif
#ifdef CONFIG_X86_64
- if (!after_bootmem)
+ if (!after_bootmem && !start) {
+ pud_t *pud;
+ pmd_t *pmd;
+
mmu_cr4_features = read_cr4();
+
+ /*
+ * _brk_end cannot change anymore, but it and _end may be
+ * located on different 2M pages. cleanup_highmap(), however,
+ * can only consider _end when it runs, so destroy any
+ * mappings beyond _brk_end here.
+ */
+ pud = pud_offset(pgd_offset_k(_brk_end), _brk_end);
+ pmd = pmd_offset(pud, _brk_end - 1);
+ while (++pmd <= pmd_offset(pud, (unsigned long)_end - 1))
+ pmd_clear(pmd);
+ }
#endif
__flush_tlb_all();
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index 749559ed80f5..fef1d90d4f15 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -49,12 +49,9 @@
#include <asm/paravirt.h>
#include <asm/setup.h>
#include <asm/cacheflush.h>
+#include <asm/page_types.h>
#include <asm/init.h>
-unsigned long max_low_pfn_mapped;
-unsigned long max_pfn_mapped;
-
-DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
unsigned long highstart_pfn, highend_pfn;
static noinline int do_test_wp_bit(void);
@@ -587,61 +584,9 @@ void zap_low_mappings(void)
flush_tlb_all();
}
-int nx_enabled;
-
pteval_t __supported_pte_mask __read_mostly = ~(_PAGE_NX | _PAGE_GLOBAL | _PAGE_IOMAP);
EXPORT_SYMBOL_GPL(__supported_pte_mask);
-#ifdef CONFIG_X86_PAE
-
-static int disable_nx __initdata;
-
-/*
- * noexec = on|off
- *
- * Control non executable mappings.
- *
- * on Enable
- * off Disable
- */
-static int __init noexec_setup(char *str)
-{
- if (!str || !strcmp(str, "on")) {
- if (cpu_has_nx) {
- __supported_pte_mask |= _PAGE_NX;
- disable_nx = 0;
- }
- } else {
- if (!strcmp(str, "off")) {
- disable_nx = 1;
- __supported_pte_mask &= ~_PAGE_NX;
- } else {
- return -EINVAL;
- }
- }
-
- return 0;
-}
-early_param("noexec", noexec_setup);
-
-void __init set_nx(void)
-{
- unsigned int v[4], l, h;
-
- if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) {
- cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]);
-
- if ((v[3] & (1 << 20)) && !disable_nx) {
- rdmsr(MSR_EFER, l, h);
- l |= EFER_NX;
- wrmsr(MSR_EFER, l, h);
- nx_enabled = 1;
- __supported_pte_mask |= _PAGE_NX;
- }
- }
-}
-#endif
-
/* user-defined highmem size */
static unsigned int highmem_pages = -1;
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 1753e8020df6..6a1a573e20f9 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -50,18 +50,8 @@
#include <asm/cacheflush.h>
#include <asm/init.h>
-/*
- * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
- * The direct mapping extends to max_pfn_mapped, so that we can directly access
- * apertures, ACPI and other tables without having to play with fixmaps.
- */
-unsigned long max_low_pfn_mapped;
-unsigned long max_pfn_mapped;
-
static unsigned long dma_reserve __initdata;
-DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
-
static int __init parse_direct_gbpages_off(char *arg)
{
direct_gbpages = 0;
@@ -85,39 +75,6 @@ early_param("gbpages", parse_direct_gbpages_on);
pteval_t __supported_pte_mask __read_mostly = ~_PAGE_IOMAP;
EXPORT_SYMBOL_GPL(__supported_pte_mask);
-static int disable_nx __cpuinitdata;
-
-/*
- * noexec=on|off
- * Control non-executable mappings for 64-bit processes.
- *
- * on Enable (default)
- * off Disable
- */
-static int __init nonx_setup(char *str)
-{
- if (!str)
- return -EINVAL;
- if (!strncmp(str, "on", 2)) {
- __supported_pte_mask |= _PAGE_NX;
- disable_nx = 0;
- } else if (!strncmp(str, "off", 3)) {
- disable_nx = 1;
- __supported_pte_mask &= ~_PAGE_NX;
- }
- return 0;
-}
-early_param("noexec", nonx_setup);
-
-void __cpuinit check_efer(void)
-{
- unsigned long efer;
-
- rdmsrl(MSR_EFER, efer);
- if (!(efer & EFER_NX) || disable_nx)
- __supported_pte_mask &= ~_PAGE_NX;
-}
-
int force_personality32;
/*
diff --git a/arch/x86/mm/iomap_32.c b/arch/x86/mm/iomap_32.c
index 8056545e2d39..fe6f84ca121e 100644
--- a/arch/x86/mm/iomap_32.c
+++ b/arch/x86/mm/iomap_32.c
@@ -82,7 +82,6 @@ iounmap_atomic(void *kvaddr, enum km_type type)
if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx))
kpte_clear_flush(kmap_pte-idx, vaddr);
- arch_flush_lazy_mmu_mode();
pagefault_enable();
}
EXPORT_SYMBOL_GPL(iounmap_atomic);
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 09daebfdb11c..8a450930834f 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -280,15 +280,16 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
return NULL;
area->phys_addr = phys_addr;
vaddr = (unsigned long) area->addr;
- if (ioremap_page_range(vaddr, vaddr + size, phys_addr, prot)) {
+
+ if (kernel_map_sync_memtype(phys_addr, size, prot_val)) {
free_memtype(phys_addr, phys_addr + size);
free_vm_area(area);
return NULL;
}
- if (ioremap_change_attr(vaddr, size, prot_val) < 0) {
+ if (ioremap_page_range(vaddr, vaddr + size, phys_addr, prot)) {
free_memtype(phys_addr, phys_addr + size);
- vunmap(area->addr);
+ free_vm_area(area);
return NULL;
}
@@ -374,7 +375,8 @@ static void __iomem *ioremap_default(resource_size_t phys_addr,
* - UC_MINUS for non-WB-able memory with no other conflicting mappings
* - Inherit from confliting mappings otherwise
*/
- err = reserve_memtype(phys_addr, phys_addr + size, -1, &flags);
+ err = reserve_memtype(phys_addr, phys_addr + size,
+ _PAGE_CACHE_WB, &flags);
if (err < 0)
return NULL;
diff --git a/arch/x86/mm/kmmio.c b/arch/x86/mm/kmmio.c
index 4f115e00486b..16ccbd77917f 100644
--- a/arch/x86/mm/kmmio.c
+++ b/arch/x86/mm/kmmio.c
@@ -32,7 +32,7 @@ struct kmmio_fault_page {
struct list_head list;
struct kmmio_fault_page *release_next;
unsigned long page; /* location of the fault page */
- bool old_presence; /* page presence prior to arming */
+ pteval_t old_presence; /* page presence prior to arming */
bool armed;
/*
@@ -87,7 +87,7 @@ static struct kmmio_probe *get_kmmio_probe(unsigned long addr)
{
struct kmmio_probe *p;
list_for_each_entry_rcu(p, &kmmio_probes, list) {
- if (addr >= p->addr && addr <= (p->addr + p->len))
+ if (addr >= p->addr && addr < (p->addr + p->len))
return p;
}
return NULL;
@@ -97,60 +97,62 @@ static struct kmmio_probe *get_kmmio_probe(unsigned long addr)
static struct kmmio_fault_page *get_kmmio_fault_page(unsigned long page)
{
struct list_head *head;
- struct kmmio_fault_page *p;
+ struct kmmio_fault_page *f;
page &= PAGE_MASK;
head = kmmio_page_list(page);
- list_for_each_entry_rcu(p, head, list) {
- if (p->page == page)
- return p;
+ list_for_each_entry_rcu(f, head, list) {
+ if (f->page == page)
+ return f;
}
return NULL;
}
-static void set_pmd_presence(pmd_t *pmd, bool present, bool *old)
+static void clear_pmd_presence(pmd_t *pmd, bool clear, pmdval_t *old)
{
pmdval_t v = pmd_val(*pmd);
- *old = !!(v & _PAGE_PRESENT);
- v &= ~_PAGE_PRESENT;
- if (present)
- v |= _PAGE_PRESENT;
+ if (clear) {
+ *old = v & _PAGE_PRESENT;
+ v &= ~_PAGE_PRESENT;
+ } else /* presume this has been called with clear==true previously */
+ v |= *old;
set_pmd(pmd, __pmd(v));
}
-static void set_pte_presence(pte_t *pte, bool present, bool *old)
+static void clear_pte_presence(pte_t *pte, bool clear, pteval_t *old)
{
pteval_t v = pte_val(*pte);
- *old = !!(v & _PAGE_PRESENT);
- v &= ~_PAGE_PRESENT;
- if (present)
- v |= _PAGE_PRESENT;
+ if (clear) {
+ *old = v & _PAGE_PRESENT;
+ v &= ~_PAGE_PRESENT;
+ } else /* presume this has been called with clear==true previously */
+ v |= *old;
set_pte_atomic(pte, __pte(v));
}
-static int set_page_presence(unsigned long addr, bool present, bool *old)
+static int clear_page_presence(struct kmmio_fault_page *f, bool clear)
{
unsigned int level;
- pte_t *pte = lookup_address(addr, &level);
+ pte_t *pte = lookup_address(f->page, &level);
if (!pte) {
- pr_err("kmmio: no pte for page 0x%08lx\n", addr);
+ pr_err("kmmio: no pte for page 0x%08lx\n", f->page);
return -1;
}
switch (level) {
case PG_LEVEL_2M:
- set_pmd_presence((pmd_t *)pte, present, old);
+ clear_pmd_presence((pmd_t *)pte, clear, &f->old_presence);
break;
case PG_LEVEL_4K:
- set_pte_presence(pte, present, old);
+ clear_pte_presence(pte, clear, &f->old_presence);
break;
default:
pr_err("kmmio: unexpected page level 0x%x.\n", level);
return -1;
}
- __flush_tlb_one(addr);
+ __flush_tlb_one(f->page);
return 0;
}
@@ -171,9 +173,9 @@ static int arm_kmmio_fault_page(struct kmmio_fault_page *f)
WARN_ONCE(f->armed, KERN_ERR "kmmio page already armed.\n");
if (f->armed) {
pr_warning("kmmio double-arm: page 0x%08lx, ref %d, old %d\n",
- f->page, f->count, f->old_presence);
+ f->page, f->count, !!f->old_presence);
}
- ret = set_page_presence(f->page, false, &f->old_presence);
+ ret = clear_page_presence(f, true);
WARN_ONCE(ret < 0, KERN_ERR "kmmio arming 0x%08lx failed.\n", f->page);
f->armed = true;
return ret;
@@ -182,8 +184,7 @@ static int arm_kmmio_fault_page(struct kmmio_fault_page *f)
/** Restore the given page to saved presence state. */
static void disarm_kmmio_fault_page(struct kmmio_fault_page *f)
{
- bool tmp;
- int ret = set_page_presence(f->page, f->old_presence, &tmp);
+ int ret = clear_page_presence(f, false);
WARN_ONCE(ret < 0,
KERN_ERR "kmmio disarming 0x%08lx failed.\n", f->page);
f->armed = false;
@@ -310,7 +311,12 @@ static int post_kmmio_handler(unsigned long condition, struct pt_regs *regs)
struct kmmio_context *ctx = &get_cpu_var(kmmio_ctx);
if (!ctx->active) {
- pr_debug("kmmio: spurious debug trap on CPU %d.\n",
+ /*
+ * debug traps without an active context are due to either
+ * something external causing them (f.e. using a debugger while
+ * mmio tracing enabled), or erroneous behaviour
+ */
+ pr_warning("kmmio: unexpected debug trap on CPU %d.\n",
smp_processor_id());
goto out;
}
@@ -439,12 +445,12 @@ static void rcu_free_kmmio_fault_pages(struct rcu_head *head)
head,
struct kmmio_delayed_release,
rcu);
- struct kmmio_fault_page *p = dr->release_list;
- while (p) {
- struct kmmio_fault_page *next = p->release_next;
- BUG_ON(p->count);
- kfree(p);
- p = next;
+ struct kmmio_fault_page *f = dr->release_list;
+ while (f) {
+ struct kmmio_fault_page *next = f->release_next;
+ BUG_ON(f->count);
+ kfree(f);
+ f = next;
}
kfree(dr);
}
@@ -453,19 +459,19 @@ static void remove_kmmio_fault_pages(struct rcu_head *head)
{
struct kmmio_delayed_release *dr =
container_of(head, struct kmmio_delayed_release, rcu);
- struct kmmio_fault_page *p = dr->release_list;
+ struct kmmio_fault_page *f = dr->release_list;
struct kmmio_fault_page **prevp = &dr->release_list;
unsigned long flags;
spin_lock_irqsave(&kmmio_lock, flags);
- while (p) {
- if (!p->count) {
- list_del_rcu(&p->list);
- prevp = &p->release_next;
+ while (f) {
+ if (!f->count) {
+ list_del_rcu(&f->list);
+ prevp = &f->release_next;
} else {
- *prevp = p->release_next;
+ *prevp = f->release_next;
}
- p = p->release_next;
+ f = f->release_next;
}
spin_unlock_irqrestore(&kmmio_lock, flags);
@@ -528,8 +534,8 @@ void unregister_kmmio_probe(struct kmmio_probe *p)
}
EXPORT_SYMBOL(unregister_kmmio_probe);
-static int kmmio_die_notifier(struct notifier_block *nb, unsigned long val,
- void *args)
+static int
+kmmio_die_notifier(struct notifier_block *nb, unsigned long val, void *args)
{
struct die_args *arg = args;
@@ -544,11 +550,23 @@ static struct notifier_block nb_die = {
.notifier_call = kmmio_die_notifier
};
-static int __init init_kmmio(void)
+int kmmio_init(void)
{
int i;
+
for (i = 0; i < KMMIO_PAGE_TABLE_SIZE; i++)
INIT_LIST_HEAD(&kmmio_page_table[i]);
+
return register_die_notifier(&nb_die);
}
-fs_initcall(init_kmmio); /* should be before device_initcall() */
+
+void kmmio_cleanup(void)
+{
+ int i;
+
+ unregister_die_notifier(&nb_die);
+ for (i = 0; i < KMMIO_PAGE_TABLE_SIZE; i++) {
+ WARN_ONCE(!list_empty(&kmmio_page_table[i]),
+ KERN_ERR "kmmio_page_table not empty at cleanup, any further tracing will leak memory.\n");
+ }
+}
diff --git a/arch/x86/mm/mmio-mod.c b/arch/x86/mm/mmio-mod.c
index c9342ed8b402..132772a8ec57 100644
--- a/arch/x86/mm/mmio-mod.c
+++ b/arch/x86/mm/mmio-mod.c
@@ -451,6 +451,7 @@ void enable_mmiotrace(void)
if (nommiotrace)
pr_info(NAME "MMIO tracing disabled.\n");
+ kmmio_init();
enter_uniprocessor();
spin_lock_irq(&trace_lock);
atomic_inc(&mmiotrace_enabled);
@@ -473,6 +474,7 @@ void disable_mmiotrace(void)
clear_trace_list(); /* guarantees: no more kmmio callbacks */
leave_uniprocessor();
+ kmmio_cleanup();
pr_info(NAME "disabled.\n");
out:
mutex_unlock(&mmiotrace_mutex);
diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c
index 3daefa04ace5..d2530062fe00 100644
--- a/arch/x86/mm/numa_32.c
+++ b/arch/x86/mm/numa_32.c
@@ -257,7 +257,7 @@ void resume_map_numa_kva(pgd_t *pgd_base)
}
#endif
-static unsigned long calculate_numa_remap_pages(void)
+static __init unsigned long calculate_numa_remap_pages(void)
{
int nid;
unsigned long size, reserve_pages = 0;
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c
index d73aaa892371..2d05a12029dc 100644
--- a/arch/x86/mm/numa_64.c
+++ b/arch/x86/mm/numa_64.c
@@ -188,6 +188,9 @@ void __init setup_node_bootmem(int nodeid, unsigned long start,
const int pgdat_size = roundup(sizeof(pg_data_t), PAGE_SIZE);
int nid;
+ if (!end)
+ return;
+
start = roundup(start, ZONE_ALIGN);
printk(KERN_INFO "Bootmem setup node %d %016lx-%016lx\n", nodeid,
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index d71e1b636ce6..b81b41a0481f 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -844,13 +844,6 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages,
vm_unmap_aliases();
- /*
- * If we're called with lazy mmu updates enabled, the
- * in-memory pte state may be stale. Flush pending updates to
- * bring them up to date.
- */
- arch_flush_lazy_mmu_mode();
-
cpa.vaddr = addr;
cpa.pages = pages;
cpa.numpages = numpages;
@@ -895,13 +888,6 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages,
} else
cpa_flush_all(cache);
- /*
- * If we've been called with lazy mmu updates enabled, then
- * make sure that everything gets flushed out before we
- * return.
- */
- arch_flush_lazy_mmu_mode();
-
out:
return ret;
}
@@ -945,71 +931,94 @@ int _set_memory_uc(unsigned long addr, int numpages)
int set_memory_uc(unsigned long addr, int numpages)
{
+ int ret;
+
/*
* for now UC MINUS. see comments in ioremap_nocache()
*/
- if (reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
- _PAGE_CACHE_UC_MINUS, NULL))
- return -EINVAL;
+ ret = reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
+ _PAGE_CACHE_UC_MINUS, NULL);
+ if (ret)
+ goto out_err;
- return _set_memory_uc(addr, numpages);
+ ret = _set_memory_uc(addr, numpages);
+ if (ret)
+ goto out_free;
+
+ return 0;
+
+out_free:
+ free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE);
+out_err:
+ return ret;
}
EXPORT_SYMBOL(set_memory_uc);
int set_memory_array_uc(unsigned long *addr, int addrinarray)
{
- unsigned long start;
- unsigned long end;
- int i;
+ int i, j;
+ int ret;
+
/*
* for now UC MINUS. see comments in ioremap_nocache()
*/
for (i = 0; i < addrinarray; i++) {
- start = __pa(addr[i]);
- for (end = start + PAGE_SIZE; i < addrinarray - 1; end += PAGE_SIZE) {
- if (end != __pa(addr[i + 1]))
- break;
- i++;
- }
- if (reserve_memtype(start, end, _PAGE_CACHE_UC_MINUS, NULL))
- goto out;
+ ret = reserve_memtype(__pa(addr[i]), __pa(addr[i]) + PAGE_SIZE,
+ _PAGE_CACHE_UC_MINUS, NULL);
+ if (ret)
+ goto out_free;
}
- return change_page_attr_set(addr, addrinarray,
+ ret = change_page_attr_set(addr, addrinarray,
__pgprot(_PAGE_CACHE_UC_MINUS), 1);
-out:
- for (i = 0; i < addrinarray; i++) {
- unsigned long tmp = __pa(addr[i]);
-
- if (tmp == start)
- break;
- for (end = tmp + PAGE_SIZE; i < addrinarray - 1; end += PAGE_SIZE) {
- if (end != __pa(addr[i + 1]))
- break;
- i++;
- }
- free_memtype(tmp, end);
- }
- return -EINVAL;
+ if (ret)
+ goto out_free;
+
+ return 0;
+
+out_free:
+ for (j = 0; j < i; j++)
+ free_memtype(__pa(addr[j]), __pa(addr[j]) + PAGE_SIZE);
+
+ return ret;
}
EXPORT_SYMBOL(set_memory_array_uc);
int _set_memory_wc(unsigned long addr, int numpages)
{
- return change_page_attr_set(&addr, numpages,
+ int ret;
+ ret = change_page_attr_set(&addr, numpages,
+ __pgprot(_PAGE_CACHE_UC_MINUS), 0);
+
+ if (!ret) {
+ ret = change_page_attr_set(&addr, numpages,
__pgprot(_PAGE_CACHE_WC), 0);
+ }
+ return ret;
}
int set_memory_wc(unsigned long addr, int numpages)
{
+ int ret;
+
if (!pat_enabled)
return set_memory_uc(addr, numpages);
- if (reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
- _PAGE_CACHE_WC, NULL))
- return -EINVAL;
+ ret = reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
+ _PAGE_CACHE_WC, NULL);
+ if (ret)
+ goto out_err;
+
+ ret = _set_memory_wc(addr, numpages);
+ if (ret)
+ goto out_free;
+
+ return 0;
- return _set_memory_wc(addr, numpages);
+out_free:
+ free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE);
+out_err:
+ return ret;
}
EXPORT_SYMBOL(set_memory_wc);
@@ -1021,29 +1030,31 @@ int _set_memory_wb(unsigned long addr, int numpages)
int set_memory_wb(unsigned long addr, int numpages)
{
- free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE);
+ int ret;
- return _set_memory_wb(addr, numpages);
+ ret = _set_memory_wb(addr, numpages);
+ if (ret)
+ return ret;
+
+ free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE);
+ return 0;
}
EXPORT_SYMBOL(set_memory_wb);
int set_memory_array_wb(unsigned long *addr, int addrinarray)
{
int i;
+ int ret;
- for (i = 0; i < addrinarray; i++) {
- unsigned long start = __pa(addr[i]);
- unsigned long end;
-
- for (end = start + PAGE_SIZE; i < addrinarray - 1; end += PAGE_SIZE) {
- if (end != __pa(addr[i + 1]))
- break;
- i++;
- }
- free_memtype(start, end);
- }
- return change_page_attr_clear(addr, addrinarray,
+ ret = change_page_attr_clear(addr, addrinarray,
__pgprot(_PAGE_CACHE_MASK), 1);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < addrinarray; i++)
+ free_memtype(__pa(addr[i]), __pa(addr[i]) + PAGE_SIZE);
+
+ return 0;
}
EXPORT_SYMBOL(set_memory_array_wb);
@@ -1136,6 +1147,8 @@ int set_pages_array_wb(struct page **pages, int addrinarray)
retval = cpa_clear_pages_array(pages, addrinarray,
__pgprot(_PAGE_CACHE_MASK));
+ if (retval)
+ return retval;
for (i = 0; i < addrinarray; i++) {
start = (unsigned long)page_address(pages[i]);
@@ -1143,7 +1156,7 @@ int set_pages_array_wb(struct page **pages, int addrinarray)
free_memtype(start, end);
}
- return retval;
+ return 0;
}
EXPORT_SYMBOL(set_pages_array_wb);
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index c009a241d562..e6718bb28065 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -182,10 +182,10 @@ static unsigned long pat_x_mtrr_type(u64 start, u64 end, unsigned long req_type)
u8 mtrr_type;
mtrr_type = mtrr_type_lookup(start, end);
- if (mtrr_type == MTRR_TYPE_UNCACHABLE)
- return _PAGE_CACHE_UC;
- if (mtrr_type == MTRR_TYPE_WRCOMB)
- return _PAGE_CACHE_WC;
+ if (mtrr_type != MTRR_TYPE_WRBACK)
+ return _PAGE_CACHE_UC_MINUS;
+
+ return _PAGE_CACHE_WB;
}
return req_type;
@@ -352,23 +352,13 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
return 0;
}
- if (req_type == -1) {
- /*
- * Call mtrr_lookup to get the type hint. This is an
- * optimization for /dev/mem mmap'ers into WB memory (BIOS
- * tools and ACPI tools). Use WB request for WB memory and use
- * UC_MINUS otherwise.
- */
- u8 mtrr_type = mtrr_type_lookup(start, end);
-
- if (mtrr_type == MTRR_TYPE_WRBACK)
- actual_type = _PAGE_CACHE_WB;
- else
- actual_type = _PAGE_CACHE_UC_MINUS;
- } else {
- actual_type = pat_x_mtrr_type(start, end,
- req_type & _PAGE_CACHE_MASK);
- }
+ /*
+ * Call mtrr_lookup to get the type hint. This is an
+ * optimization for /dev/mem mmap'ers into WB memory (BIOS
+ * tools and ACPI tools). Use WB request for WB memory and use
+ * UC_MINUS otherwise.
+ */
+ actual_type = pat_x_mtrr_type(start, end, req_type & _PAGE_CACHE_MASK);
if (new_type)
*new_type = actual_type;
@@ -546,9 +536,7 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size)
int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
unsigned long size, pgprot_t *vma_prot)
{
- u64 offset = ((u64) pfn) << PAGE_SHIFT;
- unsigned long flags = -1;
- int retval;
+ unsigned long flags = _PAGE_CACHE_WB;
if (!range_is_allowed(pfn, size))
return 0;
@@ -576,64 +564,11 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
}
#endif
- /*
- * With O_SYNC, we can only take UC_MINUS mapping. Fail if we cannot.
- *
- * Without O_SYNC, we want to get
- * - WB for WB-able memory and no other conflicting mappings
- * - UC_MINUS for non-WB-able memory with no other conflicting mappings
- * - Inherit from confliting mappings otherwise
- */
- if (flags != -1) {
- retval = reserve_memtype(offset, offset + size, flags, NULL);
- } else {
- retval = reserve_memtype(offset, offset + size, -1, &flags);
- }
-
- if (retval < 0)
- return 0;
-
- if (((pfn < max_low_pfn_mapped) ||
- (pfn >= (1UL<<(32 - PAGE_SHIFT)) && pfn < max_pfn_mapped)) &&
- ioremap_change_attr((unsigned long)__va(offset), size, flags) < 0) {
- free_memtype(offset, offset + size);
- printk(KERN_INFO
- "%s:%d /dev/mem ioremap_change_attr failed %s for %Lx-%Lx\n",
- current->comm, current->pid,
- cattr_name(flags),
- offset, (unsigned long long)(offset + size));
- return 0;
- }
-
*vma_prot = __pgprot((pgprot_val(*vma_prot) & ~_PAGE_CACHE_MASK) |
flags);
return 1;
}
-void map_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot)
-{
- unsigned long want_flags = (pgprot_val(vma_prot) & _PAGE_CACHE_MASK);
- u64 addr = (u64)pfn << PAGE_SHIFT;
- unsigned long flags;
-
- reserve_memtype(addr, addr + size, want_flags, &flags);
- if (flags != want_flags) {
- printk(KERN_INFO
- "%s:%d /dev/mem expected mapping type %s for %Lx-%Lx, got %s\n",
- current->comm, current->pid,
- cattr_name(want_flags),
- addr, (unsigned long long)(addr + size),
- cattr_name(flags));
- }
-}
-
-void unmap_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot)
-{
- u64 addr = (u64)pfn << PAGE_SHIFT;
-
- free_memtype(addr, addr + size);
-}
-
/*
* Change the memory type for the physial address range in kernel identity
* mapping space if that range is a part of identity map.
@@ -671,8 +606,8 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
{
int is_ram = 0;
int ret;
- unsigned long flags;
unsigned long want_flags = (pgprot_val(*vma_prot) & _PAGE_CACHE_MASK);
+ unsigned long flags = want_flags;
is_ram = pat_pagerange_is_ram(paddr, paddr + size);
@@ -734,29 +669,28 @@ static void free_pfn_range(u64 paddr, unsigned long size)
*
* If the vma has a linear pfn mapping for the entire range, we get the prot
* from pte and reserve the entire vma range with single reserve_pfn_range call.
- * Otherwise, we reserve the entire vma range, my ging through the PTEs page
- * by page to get physical address and protection.
*/
int track_pfn_vma_copy(struct vm_area_struct *vma)
{
- int retval = 0;
- unsigned long i, j;
resource_size_t paddr;
unsigned long prot;
- unsigned long vma_start = vma->vm_start;
- unsigned long vma_end = vma->vm_end;
- unsigned long vma_size = vma_end - vma_start;
+ unsigned long vma_size = vma->vm_end - vma->vm_start;
pgprot_t pgprot;
if (!pat_enabled)
return 0;
+ /*
+ * For now, only handle remap_pfn_range() vmas where
+ * is_linear_pfn_mapping() == TRUE. Handling of
+ * vm_insert_pfn() is TBD.
+ */
if (is_linear_pfn_mapping(vma)) {
/*
* reserve the whole chunk covered by vma. We need the
* starting address and protection from pte.
*/
- if (follow_phys(vma, vma_start, 0, &prot, &paddr)) {
+ if (follow_phys(vma, vma->vm_start, 0, &prot, &paddr)) {
WARN_ON_ONCE(1);
return -EINVAL;
}
@@ -764,28 +698,7 @@ int track_pfn_vma_copy(struct vm_area_struct *vma)
return reserve_pfn_range(paddr, vma_size, &pgprot, 1);
}
- /* reserve entire vma page by page, using pfn and prot from pte */
- for (i = 0; i < vma_size; i += PAGE_SIZE) {
- if (follow_phys(vma, vma_start + i, 0, &prot, &paddr))
- continue;
-
- pgprot = __pgprot(prot);
- retval = reserve_pfn_range(paddr, PAGE_SIZE, &pgprot, 1);
- if (retval)
- goto cleanup_ret;
- }
return 0;
-
-cleanup_ret:
- /* Reserve error: Cleanup partial reservation and return error */
- for (j = 0; j < i; j += PAGE_SIZE) {
- if (follow_phys(vma, vma_start + j, 0, &prot, &paddr))
- continue;
-
- free_pfn_range(paddr, PAGE_SIZE);
- }
-
- return retval;
}
/*
@@ -795,50 +708,28 @@ cleanup_ret:
* prot is passed in as a parameter for the new mapping. If the vma has a
* linear pfn mapping for the entire range reserve the entire vma range with
* single reserve_pfn_range call.
- * Otherwise, we look t the pfn and size and reserve only the specified range
- * page by page.
- *
- * Note that this function can be called with caller trying to map only a
- * subrange/page inside the vma.
*/
int track_pfn_vma_new(struct vm_area_struct *vma, pgprot_t *prot,
unsigned long pfn, unsigned long size)
{
- int retval = 0;
- unsigned long i, j;
- resource_size_t base_paddr;
resource_size_t paddr;
- unsigned long vma_start = vma->vm_start;
- unsigned long vma_end = vma->vm_end;
- unsigned long vma_size = vma_end - vma_start;
+ unsigned long vma_size = vma->vm_end - vma->vm_start;
if (!pat_enabled)
return 0;
+ /*
+ * For now, only handle remap_pfn_range() vmas where
+ * is_linear_pfn_mapping() == TRUE. Handling of
+ * vm_insert_pfn() is TBD.
+ */
if (is_linear_pfn_mapping(vma)) {
/* reserve the whole chunk starting from vm_pgoff */
paddr = (resource_size_t)vma->vm_pgoff << PAGE_SHIFT;
return reserve_pfn_range(paddr, vma_size, prot, 0);
}
- /* reserve page by page using pfn and size */
- base_paddr = (resource_size_t)pfn << PAGE_SHIFT;
- for (i = 0; i < size; i += PAGE_SIZE) {
- paddr = base_paddr + i;
- retval = reserve_pfn_range(paddr, PAGE_SIZE, prot, 0);
- if (retval)
- goto cleanup_ret;
- }
return 0;
-
-cleanup_ret:
- /* Reserve error: Cleanup partial reservation and return error */
- for (j = 0; j < i; j += PAGE_SIZE) {
- paddr = base_paddr + j;
- free_pfn_range(paddr, PAGE_SIZE);
- }
-
- return retval;
}
/*
@@ -849,39 +740,23 @@ cleanup_ret:
void untrack_pfn_vma(struct vm_area_struct *vma, unsigned long pfn,
unsigned long size)
{
- unsigned long i;
resource_size_t paddr;
- unsigned long prot;
- unsigned long vma_start = vma->vm_start;
- unsigned long vma_end = vma->vm_end;
- unsigned long vma_size = vma_end - vma_start;
+ unsigned long vma_size = vma->vm_end - vma->vm_start;
if (!pat_enabled)
return;
+ /*
+ * For now, only handle remap_pfn_range() vmas where
+ * is_linear_pfn_mapping() == TRUE. Handling of
+ * vm_insert_pfn() is TBD.
+ */
if (is_linear_pfn_mapping(vma)) {
/* free the whole chunk starting from vm_pgoff */
paddr = (resource_size_t)vma->vm_pgoff << PAGE_SHIFT;
free_pfn_range(paddr, vma_size);
return;
}
-
- if (size != 0 && size != vma_size) {
- /* free page by page, using pfn and size */
- paddr = (resource_size_t)pfn << PAGE_SHIFT;
- for (i = 0; i < size; i += PAGE_SIZE) {
- paddr = paddr + i;
- free_pfn_range(paddr, PAGE_SIZE);
- }
- } else {
- /* free entire vma, page by page, using the pfn from pte */
- for (i = 0; i < vma_size; i += PAGE_SIZE) {
- if (follow_phys(vma, vma_start + i, 0, &prot, &paddr))
- continue;
-
- free_pfn_range(paddr, PAGE_SIZE);
- }
- }
}
pgprot_t pgprot_writecombine(pgprot_t prot)
diff --git a/arch/x86/mm/srat_32.c b/arch/x86/mm/srat_32.c
index 16ae70fc57e7..29a0e37114f8 100644
--- a/arch/x86/mm/srat_32.c
+++ b/arch/x86/mm/srat_32.c
@@ -216,7 +216,7 @@ int __init get_memcfg_from_srat(void)
if (num_memory_chunks == 0) {
printk(KERN_WARNING
- "could not finy any ACPI SRAT memory areas.\n");
+ "could not find any ACPI SRAT memory areas.\n");
goto out_fail;
}
diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c
index c7d272b8574c..01765955baaf 100644
--- a/arch/x86/mm/srat_64.c
+++ b/arch/x86/mm/srat_64.c
@@ -28,6 +28,7 @@ int acpi_numa __initdata;
static struct acpi_table_slit *acpi_slit;
static nodemask_t nodes_parsed __initdata;
+static nodemask_t cpu_nodes_parsed __initdata;
static struct bootnode nodes[MAX_NUMNODES] __initdata;
static struct bootnode nodes_add[MAX_NUMNODES];
static int found_add_area __initdata;
@@ -141,6 +142,7 @@ acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
apic_id = pa->apic_id;
apicid_to_node[apic_id] = node;
+ node_set(node, cpu_nodes_parsed);
acpi_numa = 1;
printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> Node %u\n",
pxm, apic_id, node);
@@ -174,6 +176,7 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
else
apic_id = pa->apic_id;
apicid_to_node[apic_id] = node;
+ node_set(node, cpu_nodes_parsed);
acpi_numa = 1;
printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> Node %u\n",
pxm, apic_id, node);
@@ -358,6 +361,7 @@ static void __init unparse_node(int node)
{
int i;
node_clear(node, nodes_parsed);
+ node_clear(node, cpu_nodes_parsed);
for (i = 0; i < MAX_LOCAL_APIC; i++) {
if (apicid_to_node[i] == node)
apicid_to_node[i] = NUMA_NO_NODE;
@@ -402,7 +406,8 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
return -1;
}
- node_possible_map = nodes_parsed;
+ /* Account for nodes with cpus and no memory */
+ nodes_or(node_possible_map, nodes_parsed, cpu_nodes_parsed);
/* Finally register nodes */
for_each_node_mask(i, node_possible_map)
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index 9bb09823b362..f893d6a6e803 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -94,12 +94,16 @@ struct pci_root_info {
static int pci_root_num;
static struct pci_root_info pci_root_info[PCI_ROOT_NR];
-void set_pci_bus_resources_arch_default(struct pci_bus *b)
+void x86_pci_root_bus_res_quirks(struct pci_bus *b)
{
int i;
int j;
struct pci_root_info *info;
+ /* don't go for it if _CRS is used */
+ if (pci_probe & PCI_USE__CRS)
+ return;
+
/* if only one root bus, don't need to anything */
if (pci_root_num < 2)
return;
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 8c362b96b644..2202b6257b82 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -147,10 +147,13 @@ static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
* are examined.
*/
-void __devinit pcibios_fixup_bus(struct pci_bus *b)
+void __devinit pcibios_fixup_bus(struct pci_bus *b)
{
struct pci_dev *dev;
+ /* root bus? */
+ if (!b->parent)
+ x86_pci_root_bus_res_quirks(b);
pci_read_bridge_bases(b);
list_for_each_entry(dev, &b->devices, bus_list)
pcibios_fixup_device_resources(dev);
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index f1817f71e009..a85bef20a3b9 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -238,6 +238,10 @@ void __init pcibios_resource_survey(void)
*/
fs_initcall(pcibios_assign_resources);
+void __weak x86_pci_root_bus_res_quirks(struct pci_bus *b)
+{
+}
+
/*
* If we set up a device for bus mastering, we need to check the latency
* timer as certain crappy BIOSes forget to set it properly.
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 905bb526b133..5fa10bb9604f 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -375,7 +375,7 @@ static acpi_status __init check_mcfg_resource(struct acpi_resource *res,
if (!fixmem32)
return AE_OK;
if ((mcfg_res->start >= fixmem32->address) &&
- (mcfg_res->end < (fixmem32->address +
+ (mcfg_res->end <= (fixmem32->address +
fixmem32->address_length))) {
mcfg_res->flags = 1;
return AE_CTRL_TERMINATE;
@@ -392,7 +392,7 @@ static acpi_status __init check_mcfg_resource(struct acpi_resource *res,
return AE_OK;
if ((mcfg_res->start >= address.minimum) &&
- (mcfg_res->end < (address.minimum + address.address_length))) {
+ (mcfg_res->end <= (address.minimum + address.address_length))) {
mcfg_res->flags = 1;
return AE_CTRL_TERMINATE;
}
@@ -439,7 +439,7 @@ static int __init is_mmconf_reserved(check_reserved_t is_reserved,
u64 old_size = size;
int valid = 0;
- while (!is_reserved(addr, addr + size - 1, E820_RESERVED)) {
+ while (!is_reserved(addr, addr + size, E820_RESERVED)) {
size >>= 1;
if (size < (16UL<<20))
break;
diff --git a/arch/x86/power/Makefile b/arch/x86/power/Makefile
index 58b32db33125..de2abbd07544 100644
--- a/arch/x86/power/Makefile
+++ b/arch/x86/power/Makefile
@@ -3,5 +3,5 @@
nostackp := $(call cc-option, -fno-stack-protector)
CFLAGS_cpu_$(BITS).o := $(nostackp)
-obj-$(CONFIG_PM_SLEEP) += cpu_$(BITS).o
+obj-$(CONFIG_PM_SLEEP) += cpu.o
obj-$(CONFIG_HIBERNATION) += hibernate_$(BITS).o hibernate_asm_$(BITS).o
diff --git a/arch/x86/power/cpu_64.c b/arch/x86/power/cpu.c
index 5343540f2607..d277ef1eea51 100644
--- a/arch/x86/power/cpu_64.c
+++ b/arch/x86/power/cpu.c
@@ -1,5 +1,5 @@
/*
- * Suspend and hibernation support for x86-64
+ * Suspend support specific for i386/x86-64.
*
* Distribute under GPLv2
*
@@ -8,18 +8,28 @@
* Copyright (c) 2001 Patrick Mochel <mochel@osdl.org>
*/
-#include <linux/smp.h>
#include <linux/suspend.h>
-#include <asm/proto.h>
-#include <asm/page.h>
+#include <linux/smp.h>
+
#include <asm/pgtable.h>
+#include <asm/proto.h>
#include <asm/mtrr.h>
+#include <asm/page.h>
+#include <asm/mce.h>
#include <asm/xcr.h>
#include <asm/suspend.h>
-static void fix_processor_context(void);
+#ifdef CONFIG_X86_32
+static struct saved_context saved_context;
+unsigned long saved_context_ebx;
+unsigned long saved_context_esp, saved_context_ebp;
+unsigned long saved_context_esi, saved_context_edi;
+unsigned long saved_context_eflags;
+#else
+/* CONFIG_X86_64 */
struct saved_context saved_context;
+#endif
/**
* __save_processor_state - save CPU registers before creating a
@@ -38,19 +48,35 @@ struct saved_context saved_context;
*/
static void __save_processor_state(struct saved_context *ctxt)
{
+#ifdef CONFIG_X86_32
+ mtrr_save_fixed_ranges(NULL);
+#endif
kernel_fpu_begin();
/*
* descriptor tables
*/
+#ifdef CONFIG_X86_32
+ store_gdt(&ctxt->gdt);
+ store_idt(&ctxt->idt);
+#else
+/* CONFIG_X86_64 */
store_gdt((struct desc_ptr *)&ctxt->gdt_limit);
store_idt((struct desc_ptr *)&ctxt->idt_limit);
+#endif
store_tr(ctxt->tr);
/* XMM0..XMM15 should be handled by kernel_fpu_begin(). */
/*
* segment registers
*/
+#ifdef CONFIG_X86_32
+ savesegment(es, ctxt->es);
+ savesegment(fs, ctxt->fs);
+ savesegment(gs, ctxt->gs);
+ savesegment(ss, ctxt->ss);
+#else
+/* CONFIG_X86_64 */
asm volatile ("movw %%ds, %0" : "=m" (ctxt->ds));
asm volatile ("movw %%es, %0" : "=m" (ctxt->es));
asm volatile ("movw %%fs, %0" : "=m" (ctxt->fs));
@@ -62,30 +88,87 @@ static void __save_processor_state(struct saved_context *ctxt)
rdmsrl(MSR_KERNEL_GS_BASE, ctxt->gs_kernel_base);
mtrr_save_fixed_ranges(NULL);
+ rdmsrl(MSR_EFER, ctxt->efer);
+#endif
+
/*
* control registers
*/
- rdmsrl(MSR_EFER, ctxt->efer);
ctxt->cr0 = read_cr0();
ctxt->cr2 = read_cr2();
ctxt->cr3 = read_cr3();
+#ifdef CONFIG_X86_32
+ ctxt->cr4 = read_cr4_safe();
+#else
+/* CONFIG_X86_64 */
ctxt->cr4 = read_cr4();
ctxt->cr8 = read_cr8();
+#endif
}
+/* Needed by apm.c */
void save_processor_state(void)
{
__save_processor_state(&saved_context);
}
+#ifdef CONFIG_X86_32
+EXPORT_SYMBOL(save_processor_state);
+#endif
static void do_fpu_end(void)
{
/*
- * Restore FPU regs if necessary
+ * Restore FPU regs if necessary.
*/
kernel_fpu_end();
}
+static 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
+ * necessary. But... This is necessary, because
+ * 386 hardware has concept of busy TSS or some
+ * similar stupidity.
+ */
+
+#ifdef CONFIG_X86_64
+ get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS].type = 9;
+
+ syscall_init(); /* This sets MSR_*STAR and related */
+#endif
+ load_TR_desc(); /* This does ltr */
+ load_LDT(&current->active_mm->context); /* This does lldt */
+
+ /*
+ * Now maybe reload the debug registers
+ */
+ if (current->thread.debugreg7) {
+#ifdef CONFIG_X86_32
+ set_debugreg(current->thread.debugreg0, 0);
+ set_debugreg(current->thread.debugreg1, 1);
+ set_debugreg(current->thread.debugreg2, 2);
+ set_debugreg(current->thread.debugreg3, 3);
+ /* no 4 and 5 */
+ set_debugreg(current->thread.debugreg6, 6);
+ set_debugreg(current->thread.debugreg7, 7);
+#else
+ /* CONFIG_X86_64 */
+ loaddebug(&current->thread, 0);
+ loaddebug(&current->thread, 1);
+ loaddebug(&current->thread, 2);
+ loaddebug(&current->thread, 3);
+ /* no 4 and 5 */
+ loaddebug(&current->thread, 6);
+ loaddebug(&current->thread, 7);
+#endif
+ }
+
+}
+
/**
* __restore_processor_state - restore the contents of CPU registers saved
* by __save_processor_state()
@@ -96,9 +179,16 @@ static void __restore_processor_state(struct saved_context *ctxt)
/*
* control registers
*/
+ /* cr4 was introduced in the Pentium CPU */
+#ifdef CONFIG_X86_32
+ if (ctxt->cr4)
+ write_cr4(ctxt->cr4);
+#else
+/* CONFIG X86_64 */
wrmsrl(MSR_EFER, ctxt->efer);
write_cr8(ctxt->cr8);
write_cr4(ctxt->cr4);
+#endif
write_cr3(ctxt->cr3);
write_cr2(ctxt->cr2);
write_cr0(ctxt->cr0);
@@ -107,13 +197,31 @@ static void __restore_processor_state(struct saved_context *ctxt)
* now restore the descriptor tables to their proper values
* ltr is done i fix_processor_context().
*/
+#ifdef CONFIG_X86_32
+ load_gdt(&ctxt->gdt);
+ load_idt(&ctxt->idt);
+#else
+/* CONFIG_X86_64 */
load_gdt((const struct desc_ptr *)&ctxt->gdt_limit);
load_idt((const struct desc_ptr *)&ctxt->idt_limit);
-
+#endif
/*
* segment registers
*/
+#ifdef CONFIG_X86_32
+ loadsegment(es, ctxt->es);
+ loadsegment(fs, ctxt->fs);
+ loadsegment(gs, ctxt->gs);
+ loadsegment(ss, ctxt->ss);
+
+ /*
+ * sysenter MSRs
+ */
+ if (boot_cpu_has(X86_FEATURE_SEP))
+ enable_sep_cpu();
+#else
+/* CONFIG_X86_64 */
asm volatile ("movw %0, %%ds" :: "r" (ctxt->ds));
asm volatile ("movw %0, %%es" :: "r" (ctxt->es));
asm volatile ("movw %0, %%fs" :: "r" (ctxt->fs));
@@ -123,6 +231,7 @@ static void __restore_processor_state(struct saved_context *ctxt)
wrmsrl(MSR_FS_BASE, ctxt->fs_base);
wrmsrl(MSR_GS_BASE, ctxt->gs_base);
wrmsrl(MSR_KERNEL_GS_BASE, ctxt->gs_kernel_base);
+#endif
/*
* restore XCR0 for xsave capable cpu's.
@@ -134,41 +243,17 @@ static void __restore_processor_state(struct saved_context *ctxt)
do_fpu_end();
mtrr_ap_init();
+
+#ifdef CONFIG_X86_32
+ mcheck_init(&boot_cpu_data);
+#endif
}
+/* Needed by apm.c */
void restore_processor_state(void)
{
__restore_processor_state(&saved_context);
}
-
-static void fix_processor_context(void)
-{
- int cpu = smp_processor_id();
- struct tss_struct *t = &per_cpu(init_tss, cpu);
-
- /*
- * This just modifies memory; should not be necessary. But... This
- * is necessary, because 386 hardware has concept of busy TSS or some
- * similar stupidity.
- */
- set_tss_desc(cpu, t);
-
- get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS].type = 9;
-
- syscall_init(); /* This sets MSR_*STAR and related */
- load_TR_desc(); /* This does ltr */
- load_LDT(&current->active_mm->context); /* This does lldt */
-
- /*
- * Now maybe reload the debug registers
- */
- if (current->thread.debugreg7){
- loaddebug(&current->thread, 0);
- loaddebug(&current->thread, 1);
- loaddebug(&current->thread, 2);
- loaddebug(&current->thread, 3);
- /* no 4 and 5 */
- loaddebug(&current->thread, 6);
- loaddebug(&current->thread, 7);
- }
-}
+#ifdef CONFIG_X86_32
+EXPORT_SYMBOL(restore_processor_state);
+#endif
diff --git a/arch/x86/power/cpu_32.c b/arch/x86/power/cpu_32.c
deleted file mode 100644
index ce702c5b3a2c..000000000000
--- a/arch/x86/power/cpu_32.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Suspend support specific for i386.
- *
- * Distribute under GPLv2
- *
- * Copyright (c) 2002 Pavel Machek <pavel@suse.cz>
- * Copyright (c) 2001 Patrick Mochel <mochel@osdl.org>
- */
-
-#include <linux/module.h>
-#include <linux/suspend.h>
-#include <asm/mtrr.h>
-#include <asm/mce.h>
-#include <asm/xcr.h>
-#include <asm/suspend.h>
-
-static struct saved_context saved_context;
-
-unsigned long saved_context_ebx;
-unsigned long saved_context_esp, saved_context_ebp;
-unsigned long saved_context_esi, saved_context_edi;
-unsigned long saved_context_eflags;
-
-static void __save_processor_state(struct saved_context *ctxt)
-{
- mtrr_save_fixed_ranges(NULL);
- kernel_fpu_begin();
-
- /*
- * descriptor tables
- */
- store_gdt(&ctxt->gdt);
- store_idt(&ctxt->idt);
- store_tr(ctxt->tr);
-
- /*
- * segment registers
- */
- savesegment(es, ctxt->es);
- savesegment(fs, ctxt->fs);
- savesegment(gs, ctxt->gs);
- savesegment(ss, ctxt->ss);
-
- /*
- * control registers
- */
- ctxt->cr0 = read_cr0();
- ctxt->cr2 = read_cr2();
- ctxt->cr3 = read_cr3();
- ctxt->cr4 = read_cr4_safe();
-}
-
-/* Needed by apm.c */
-void save_processor_state(void)
-{
- __save_processor_state(&saved_context);
-}
-EXPORT_SYMBOL(save_processor_state);
-
-static void do_fpu_end(void)
-{
- /*
- * Restore FPU regs if necessary.
- */
- kernel_fpu_end();
-}
-
-static 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
- * necessary. But... This is necessary, because
- * 386 hardware has concept of busy TSS or some
- * similar stupidity.
- */
-
- load_TR_desc(); /* This does ltr */
- load_LDT(&current->active_mm->context); /* This does lldt */
-
- /*
- * Now maybe reload the debug registers
- */
- if (current->thread.debugreg7) {
- set_debugreg(current->thread.debugreg0, 0);
- set_debugreg(current->thread.debugreg1, 1);
- set_debugreg(current->thread.debugreg2, 2);
- set_debugreg(current->thread.debugreg3, 3);
- /* no 4 and 5 */
- set_debugreg(current->thread.debugreg6, 6);
- set_debugreg(current->thread.debugreg7, 7);
- }
-
-}
-
-static void __restore_processor_state(struct saved_context *ctxt)
-{
- /*
- * control registers
- */
- /* cr4 was introduced in the Pentium CPU */
- if (ctxt->cr4)
- write_cr4(ctxt->cr4);
- write_cr3(ctxt->cr3);
- write_cr2(ctxt->cr2);
- write_cr0(ctxt->cr0);
-
- /*
- * now restore the descriptor tables to their proper values
- * ltr is done i fix_processor_context().
- */
- load_gdt(&ctxt->gdt);
- load_idt(&ctxt->idt);
-
- /*
- * segment registers
- */
- loadsegment(es, ctxt->es);
- loadsegment(fs, ctxt->fs);
- loadsegment(gs, ctxt->gs);
- loadsegment(ss, ctxt->ss);
-
- /*
- * sysenter MSRs
- */
- if (boot_cpu_has(X86_FEATURE_SEP))
- enable_sep_cpu();
-
- /*
- * restore XCR0 for xsave capable cpu's.
- */
- if (cpu_has_xsave)
- xsetbv(XCR_XFEATURE_ENABLED_MASK, pcntxt_mask);
-
- fix_processor_context();
- do_fpu_end();
- mtrr_ap_init();
- mcheck_init(&boot_cpu_data);
-}
-
-/* Needed by apm.c */
-void restore_processor_state(void)
-{
- __restore_processor_state(&saved_context);
-}
-EXPORT_SYMBOL(restore_processor_state);
diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c
index d9d35824c56f..6a40b78b46aa 100644
--- a/arch/x86/vdso/vclock_gettime.c
+++ b/arch/x86/vdso/vclock_gettime.c
@@ -104,11 +104,13 @@ notrace int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
{
long ret;
if (likely(gtod->sysctl_enabled && gtod->clock.vread)) {
- BUILD_BUG_ON(offsetof(struct timeval, tv_usec) !=
- offsetof(struct timespec, tv_nsec) ||
- sizeof(*tv) != sizeof(struct timespec));
- do_realtime((struct timespec *)tv);
- tv->tv_usec /= 1000;
+ if (likely(tv != NULL)) {
+ BUILD_BUG_ON(offsetof(struct timeval, tv_usec) !=
+ offsetof(struct timespec, tv_nsec) ||
+ sizeof(*tv) != sizeof(struct timespec));
+ do_realtime((struct timespec *)tv);
+ tv->tv_usec /= 1000;
+ }
if (unlikely(tz != NULL)) {
/* Avoid memcpy. Some old compilers fail to inline it */
tz->tz_minuteswest = gtod->sys_tz.tz_minuteswest;
diff --git a/arch/x86/vdso/vma.c b/arch/x86/vdso/vma.c
index 7133cdf9098b..cac083386e03 100644
--- a/arch/x86/vdso/vma.c
+++ b/arch/x86/vdso/vma.c
@@ -8,6 +8,7 @@
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/random.h>
+#include <linux/elf.h>
#include <asm/vsyscall.h>
#include <asm/vgtod.h>
#include <asm/proto.h>
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 82cd39a6cbd3..12a3159333bc 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -42,6 +42,7 @@
#include <asm/xen/hypervisor.h>
#include <asm/fixmap.h>
#include <asm/processor.h>
+#include <asm/proto.h>
#include <asm/msr-index.h>
#include <asm/setup.h>
#include <asm/desc.h>
@@ -168,21 +169,23 @@ static void __init xen_banner(void)
xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : "");
}
+static __read_mostly unsigned int cpuid_leaf1_edx_mask = ~0;
+static __read_mostly unsigned int cpuid_leaf1_ecx_mask = ~0;
+
static void xen_cpuid(unsigned int *ax, unsigned int *bx,
unsigned int *cx, unsigned int *dx)
{
+ unsigned maskecx = ~0;
unsigned maskedx = ~0;
/*
* Mask out inconvenient features, to try and disable as many
* unsupported kernel subsystems as possible.
*/
- if (*ax == 1)
- maskedx = ~((1 << X86_FEATURE_APIC) | /* disable APIC */
- (1 << X86_FEATURE_ACPI) | /* disable ACPI */
- (1 << X86_FEATURE_MCE) | /* disable MCE */
- (1 << X86_FEATURE_MCA) | /* disable MCA */
- (1 << X86_FEATURE_ACC)); /* thermal monitoring */
+ if (*ax == 1) {
+ maskecx = cpuid_leaf1_ecx_mask;
+ maskedx = cpuid_leaf1_edx_mask;
+ }
asm(XEN_EMULATE_PREFIX "cpuid"
: "=a" (*ax),
@@ -190,9 +193,43 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
"=c" (*cx),
"=d" (*dx)
: "0" (*ax), "2" (*cx));
+
+ *cx &= maskecx;
*dx &= maskedx;
}
+static __init void xen_init_cpuid_mask(void)
+{
+ unsigned int ax, bx, cx, dx;
+
+ cpuid_leaf1_edx_mask =
+ ~((1 << X86_FEATURE_MCE) | /* disable MCE */
+ (1 << X86_FEATURE_MCA) | /* disable MCA */
+ (1 << X86_FEATURE_ACC)); /* thermal monitoring */
+
+ if (!xen_initial_domain())
+ cpuid_leaf1_edx_mask &=
+ ~((1 << X86_FEATURE_APIC) | /* disable local APIC */
+ (1 << X86_FEATURE_ACPI)); /* disable ACPI */
+
+ ax = 1;
+ xen_cpuid(&ax, &bx, &cx, &dx);
+
+ /* cpuid claims we support xsave; try enabling it to see what happens */
+ if (cx & (1 << (X86_FEATURE_XSAVE % 32))) {
+ unsigned long cr4;
+
+ set_in_cr4(X86_CR4_OSXSAVE);
+
+ cr4 = read_cr4();
+
+ if ((cr4 & X86_CR4_OSXSAVE) == 0)
+ cpuid_leaf1_ecx_mask &= ~(1 << (X86_FEATURE_XSAVE % 32));
+
+ clear_in_cr4(X86_CR4_OSXSAVE);
+ }
+}
+
static void xen_set_debugreg(int reg, unsigned long val)
{
HYPERVISOR_set_debugreg(reg, val);
@@ -203,10 +240,10 @@ static unsigned long xen_get_debugreg(int reg)
return HYPERVISOR_get_debugreg(reg);
}
-void xen_leave_lazy(void)
+static void xen_end_context_switch(struct task_struct *next)
{
- paravirt_leave_lazy(paravirt_get_lazy_mode());
xen_mc_flush();
+ paravirt_end_context_switch(next);
}
static unsigned long xen_store_tr(void)
@@ -284,12 +321,11 @@ static void xen_set_ldt(const void *addr, unsigned entries)
static void xen_load_gdt(const struct desc_ptr *dtr)
{
- unsigned long *frames;
unsigned long va = dtr->address;
unsigned int size = dtr->size + 1;
unsigned pages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
+ unsigned long frames[pages];
int f;
- struct multicall_space mcs;
/* A GDT can be up to 64k in size, which corresponds to 8192
8-byte entries, or 16 4k pages.. */
@@ -297,19 +333,26 @@ static void xen_load_gdt(const struct desc_ptr *dtr)
BUG_ON(size > 65536);
BUG_ON(va & ~PAGE_MASK);
- mcs = xen_mc_entry(sizeof(*frames) * pages);
- frames = mcs.args;
-
for (f = 0; va < dtr->address + size; va += PAGE_SIZE, f++) {
- frames[f] = arbitrary_virt_to_mfn((void *)va);
+ int level;
+ pte_t *ptep = lookup_address(va, &level);
+ unsigned long pfn, mfn;
+ void *virt;
+
+ BUG_ON(ptep == NULL);
+
+ pfn = pte_pfn(*ptep);
+ mfn = pfn_to_mfn(pfn);
+ virt = __va(PFN_PHYS(pfn));
+
+ frames[f] = mfn;
make_lowmem_page_readonly((void *)va);
- make_lowmem_page_readonly(mfn_to_virt(frames[f]));
+ make_lowmem_page_readonly(virt);
}
- MULTI_set_gdt(mcs.mc, frames, size / sizeof(struct desc_struct));
-
- xen_mc_issue(PARAVIRT_LAZY_CPU);
+ if (HYPERVISOR_set_gdt(frames, size / sizeof(struct desc_struct)))
+ BUG();
}
static void load_TLS_descriptor(struct thread_struct *t,
@@ -385,7 +428,7 @@ static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum,
static int cvt_gate_to_trap(int vector, const gate_desc *val,
struct trap_info *info)
{
- if (val->type != 0xf && val->type != 0xe)
+ if (val->type != GATE_TRAP && val->type != GATE_INTERRUPT)
return 0;
info->vector = vector;
@@ -393,8 +436,8 @@ static int cvt_gate_to_trap(int vector, const gate_desc *val,
info->cs = gate_segment(*val);
info->flags = val->dpl;
/* interrupt gates clear IF */
- if (val->type == 0xe)
- info->flags |= 4;
+ if (val->type == GATE_INTERRUPT)
+ info->flags |= 1 << 2;
return 1;
}
@@ -817,10 +860,8 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = {
/* Xen takes care of %gs when switching to usermode for us */
.swapgs = paravirt_nop,
- .lazy_mode = {
- .enter = paravirt_enter_lazy_cpu,
- .leave = xen_leave_lazy,
- },
+ .start_context_switch = paravirt_start_context_switch,
+ .end_context_switch = xen_end_context_switch,
};
static const struct pv_apic_ops xen_apic_ops __initdata = {
@@ -872,7 +913,6 @@ static const struct machine_ops __initdata xen_machine_ops = {
.emergency_restart = xen_emergency_restart,
};
-
/* First C function to be called on Xen boot */
asmlinkage void __init xen_start_kernel(void)
{
@@ -897,6 +937,8 @@ asmlinkage void __init xen_start_kernel(void)
xen_init_irq_ops();
+ xen_init_cpuid_mask();
+
#ifdef CONFIG_X86_LOCAL_APIC
/*
* set up the basic apic ops.
@@ -938,6 +980,11 @@ asmlinkage void __init xen_start_kernel(void)
if (!xen_initial_domain())
__supported_pte_mask &= ~(_PAGE_PWT | _PAGE_PCD);
+#ifdef CONFIG_X86_64
+ /* Work out if we support NX */
+ check_efer();
+#endif
+
/* Don't do the full vcpu_info placement stuff until we have a
possible map and a non-dummy shared_info. */
per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 2a81838a9ab7..760e3a512059 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -184,7 +184,7 @@ static inline unsigned p2m_index(unsigned long pfn)
}
/* Build the parallel p2m_top_mfn structures */
-void xen_setup_mfn_list_list(void)
+static void __init xen_build_mfn_list_list(void)
{
unsigned pfn, idx;
@@ -198,7 +198,10 @@ void xen_setup_mfn_list_list(void)
unsigned topidx = idx * P2M_ENTRIES_PER_PAGE;
p2m_top_mfn_list[idx] = virt_to_mfn(&p2m_top_mfn[topidx]);
}
+}
+void xen_setup_mfn_list_list(void)
+{
BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info);
HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
@@ -218,6 +221,8 @@ void __init xen_build_dynamic_phys_to_machine(void)
p2m_top[topidx] = &mfn_list[pfn];
}
+
+ xen_build_mfn_list_list();
}
unsigned long get_phys_to_machine(unsigned long pfn)
@@ -233,47 +238,74 @@ unsigned long get_phys_to_machine(unsigned long pfn)
}
EXPORT_SYMBOL_GPL(get_phys_to_machine);
-static void alloc_p2m(unsigned long **pp, unsigned long *mfnp)
+/* install a new p2m_top page */
+bool install_p2mtop_page(unsigned long pfn, unsigned long *p)
{
- unsigned long *p;
+ unsigned topidx = p2m_top_index(pfn);
+ unsigned long **pfnp, *mfnp;
unsigned i;
- p = (void *)__get_free_page(GFP_KERNEL | __GFP_NOFAIL);
- BUG_ON(p == NULL);
+ pfnp = &p2m_top[topidx];
+ mfnp = &p2m_top_mfn[topidx];
for (i = 0; i < P2M_ENTRIES_PER_PAGE; i++)
p[i] = INVALID_P2M_ENTRY;
- if (cmpxchg(pp, p2m_missing, p) != p2m_missing)
- free_page((unsigned long)p);
- else
+ if (cmpxchg(pfnp, p2m_missing, p) == p2m_missing) {
*mfnp = virt_to_mfn(p);
+ return true;
+ }
+
+ return false;
}
-void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+static void alloc_p2m(unsigned long pfn)
{
- unsigned topidx, idx;
+ unsigned long *p;
- if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
- BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
- return;
- }
+ p = (void *)__get_free_page(GFP_KERNEL | __GFP_NOFAIL);
+ BUG_ON(p == NULL);
+
+ if (!install_p2mtop_page(pfn, p))
+ free_page((unsigned long)p);
+}
+
+/* Try to install p2m mapping; fail if intermediate bits missing */
+bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+{
+ unsigned topidx, idx;
if (unlikely(pfn >= MAX_DOMAIN_PAGES)) {
BUG_ON(mfn != INVALID_P2M_ENTRY);
- return;
+ return true;
}
topidx = p2m_top_index(pfn);
if (p2m_top[topidx] == p2m_missing) {
- /* no need to allocate a page to store an invalid entry */
if (mfn == INVALID_P2M_ENTRY)
- return;
- alloc_p2m(&p2m_top[topidx], &p2m_top_mfn[topidx]);
+ return true;
+ return false;
}
idx = p2m_index(pfn);
p2m_top[topidx][idx] = mfn;
+
+ return true;
+}
+
+void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+{
+ if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
+ BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+ return;
+ }
+
+ if (unlikely(!__set_phys_to_machine(pfn, mfn))) {
+ alloc_p2m(pfn);
+
+ if (!__set_phys_to_machine(pfn, mfn))
+ BUG();
+ }
}
unsigned long arbitrary_virt_to_mfn(void *vaddr)
@@ -419,10 +451,6 @@ void set_pte_mfn(unsigned long vaddr, unsigned long mfn, pgprot_t flags)
void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pteval)
{
- /* updates to init_mm may be done without lock */
- if (mm == &init_mm)
- preempt_disable();
-
ADD_STATS(set_pte_at, 1);
// ADD_STATS(set_pte_at_pinned, xen_page_pinned(ptep));
ADD_STATS(set_pte_at_current, mm == current->mm);
@@ -443,9 +471,7 @@ void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
}
xen_set_pte(ptep, pteval);
-out:
- if (mm == &init_mm)
- preempt_enable();
+out: return;
}
pte_t xen_ptep_modify_prot_start(struct mm_struct *mm,
@@ -987,7 +1013,7 @@ static __init int xen_mark_pinned(struct mm_struct *mm, struct page *page,
return 0;
}
-void __init xen_mark_init_mm_pinned(void)
+static void __init xen_mark_init_mm_pinned(void)
{
xen_pgd_walk(&init_mm, xen_mark_pinned, FIXADDR_TOP);
}
@@ -1119,10 +1145,8 @@ static void drop_other_mm_ref(void *info)
/* If this cpu still has a stale cr3 reference, then make sure
it has been flushed. */
- if (percpu_read(xen_current_cr3) == __pa(mm->pgd)) {
+ if (percpu_read(xen_current_cr3) == __pa(mm->pgd))
load_cr3(swapper_pg_dir);
- arch_flush_lazy_cpu_mode();
- }
}
static void xen_drop_mm_ref(struct mm_struct *mm)
@@ -1135,7 +1159,6 @@ static void xen_drop_mm_ref(struct mm_struct *mm)
load_cr3(swapper_pg_dir);
else
leave_mm(smp_processor_id());
- arch_flush_lazy_cpu_mode();
}
/* Get the "official" set of cpus referring to our pagetable. */
@@ -1270,8 +1293,8 @@ static void xen_flush_tlb_others(const struct cpumask *cpus,
} *args;
struct multicall_space mcs;
- BUG_ON(cpumask_empty(cpus));
- BUG_ON(!mm);
+ if (cpumask_empty(cpus))
+ return; /* nothing to do */
mcs = xen_mc_entry(sizeof(*args));
args = mcs.args;
@@ -1438,6 +1461,15 @@ static __init void xen_set_pte_init(pte_t *ptep, pte_t pte)
}
#endif
+static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn)
+{
+ struct mmuext_op op;
+ op.cmd = cmd;
+ op.arg1.mfn = pfn_to_mfn(pfn);
+ if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF))
+ BUG();
+}
+
/* Early in boot, while setting up the initial pagetable, assume
everything is pinned. */
static __init void xen_alloc_pte_init(struct mm_struct *mm, unsigned long pfn)
@@ -1446,22 +1478,29 @@ static __init void xen_alloc_pte_init(struct mm_struct *mm, unsigned long pfn)
BUG_ON(mem_map); /* should only be used early */
#endif
make_lowmem_page_readonly(__va(PFN_PHYS(pfn)));
+ pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn);
+}
+
+/* Used for pmd and pud */
+static __init void xen_alloc_pmd_init(struct mm_struct *mm, unsigned long pfn)
+{
+#ifdef CONFIG_FLATMEM
+ BUG_ON(mem_map); /* should only be used early */
+#endif
+ make_lowmem_page_readonly(__va(PFN_PHYS(pfn)));
}
/* Early release_pte assumes that all pts are pinned, since there's
only init_mm and anything attached to that is pinned. */
-static void xen_release_pte_init(unsigned long pfn)
+static __init void xen_release_pte_init(unsigned long pfn)
{
+ pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn);
make_lowmem_page_readwrite(__va(PFN_PHYS(pfn)));
}
-static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn)
+static __init void xen_release_pmd_init(unsigned long pfn)
{
- struct mmuext_op op;
- op.cmd = cmd;
- op.arg1.mfn = pfn_to_mfn(pfn);
- if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF))
- BUG();
+ make_lowmem_page_readwrite(__va(PFN_PHYS(pfn)));
}
/* This needs to make sure the new pte page is pinned iff its being
@@ -1746,6 +1785,11 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd,
pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(swapper_pg_dir)));
+ reserve_early(__pa(xen_start_info->pt_base),
+ __pa(xen_start_info->pt_base +
+ xen_start_info->nr_pt_frames * PAGE_SIZE),
+ "XEN PAGETABLES");
+
return swapper_pg_dir;
}
#endif /* CONFIG_X86_64 */
@@ -1773,6 +1817,9 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
#ifdef CONFIG_X86_LOCAL_APIC
case FIX_APIC_BASE: /* maps dummy local APIC */
#endif
+ case FIX_TEXT_POKE0:
+ case FIX_TEXT_POKE1:
+ /* All local page mappings */
pte = pfn_pte(phys, prot);
break;
@@ -1819,6 +1866,13 @@ __init void xen_post_allocator_init(void)
xen_mark_init_mm_pinned();
}
+static void xen_leave_lazy_mmu(void)
+{
+ preempt_disable();
+ xen_mc_flush();
+ paravirt_leave_lazy_mmu();
+ preempt_enable();
+}
const struct pv_mmu_ops xen_mmu_ops __initdata = {
.pagetable_setup_start = xen_pagetable_setup_start,
@@ -1843,9 +1897,9 @@ const struct pv_mmu_ops xen_mmu_ops __initdata = {
.alloc_pte = xen_alloc_pte_init,
.release_pte = xen_release_pte_init,
- .alloc_pmd = xen_alloc_pte_init,
+ .alloc_pmd = xen_alloc_pmd_init,
.alloc_pmd_clone = paravirt_nop,
- .release_pmd = xen_release_pte_init,
+ .release_pmd = xen_release_pmd_init,
#ifdef CONFIG_HIGHPTE
.kmap_atomic_pte = xen_kmap_atomic_pte,
@@ -1883,8 +1937,8 @@ const struct pv_mmu_ops xen_mmu_ops __initdata = {
.make_pud = PV_CALLEE_SAVE(xen_make_pud),
.set_pgd = xen_set_pgd_hyper,
- .alloc_pud = xen_alloc_pte_init,
- .release_pud = xen_release_pte_init,
+ .alloc_pud = xen_alloc_pmd_init,
+ .release_pud = xen_release_pmd_init,
#endif /* PAGETABLE_LEVELS == 4 */
.activate_mm = xen_activate_mm,
@@ -1893,7 +1947,7 @@ const struct pv_mmu_ops xen_mmu_ops __initdata = {
.lazy_mode = {
.enter = paravirt_enter_lazy_mmu,
- .leave = xen_leave_lazy,
+ .leave = xen_leave_lazy_mmu,
},
.set_fixmap = xen_set_fixmap,
diff --git a/arch/x86/xen/mmu.h b/arch/x86/xen/mmu.h
index 24d1b44a337d..da7302624897 100644
--- a/arch/x86/xen/mmu.h
+++ b/arch/x86/xen/mmu.h
@@ -11,6 +11,9 @@ enum pt_level {
};
+bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn);
+bool install_p2mtop_page(unsigned long pfn, unsigned long *p);
+
void set_pte_mfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 585a6e330837..429834ec1687 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -317,7 +317,7 @@ static int __cpuinit xen_cpu_up(unsigned int cpu)
BUG_ON(rc);
while(per_cpu(cpu_state, cpu) != CPU_ONLINE) {
- HYPERVISOR_sched_op(SCHEDOP_yield, 0);
+ HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
barrier();
}
@@ -422,7 +422,7 @@ static void xen_smp_send_call_function_ipi(const struct cpumask *mask)
/* Make sure other vcpus get a chance to run if they need to. */
for_each_cpu(cpu, mask) {
if (xen_vcpu_stolen(cpu)) {
- HYPERVISOR_sched_op(SCHEDOP_yield, 0);
+ HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
break;
}
}
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index 14f240623497..0a5aa44299a5 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -213,6 +213,11 @@ cycle_t xen_clocksource_read(void)
return ret;
}
+static cycle_t xen_clocksource_get_cycles(struct clocksource *cs)
+{
+ return xen_clocksource_read();
+}
+
static void xen_read_wallclock(struct timespec *ts)
{
struct shared_info *s = HYPERVISOR_shared_info;
@@ -241,7 +246,7 @@ int xen_set_wallclock(unsigned long now)
static struct clocksource xen_clocksource __read_mostly = {
.name = "xen",
.rating = 400,
- .read = xen_clocksource_read,
+ .read = xen_clocksource_get_cycles,
.mask = ~0,
.mult = 1<<XEN_SHIFT, /* time directly in nanoseconds */
.shift = XEN_SHIFT,
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 2f5ef2632ea2..5c50a1017a37 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -30,7 +30,6 @@ pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn);
void xen_ident_map_ISA(void);
void xen_reserve_top(void);
-void xen_leave_lazy(void);
void xen_post_allocator_init(void);
char * __init xen_memory_setup(void);
@@ -57,8 +56,6 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id);
bool xen_vcpu_stolen(int vcpu);
-void xen_mark_init_mm_pinned(void);
-
void xen_setup_vcpu_info_placement(void);
#ifdef CONFIG_SMP
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index fa6dc4dd3b19..30d21a9e2ef5 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -137,6 +137,8 @@ config PCI
source "drivers/pci/Kconfig"
+endmenu
+
menu "Platform options"
choice
@@ -153,8 +155,6 @@ config XTENSA_PLATFORM_ISS
config XTENSA_PLATFORM_XT2000
bool "XT2000"
- select XTENSA_CALIBRATE_CCOUNT
- select PCI
help
XT2000 is the name of Tensilica's feature-rich emulation platform.
This hardware is capable of running a full Linux distribution.
@@ -192,8 +192,6 @@ config CMDLINE
source "mm/Kconfig"
-endmenu
-
config HOTPLUG
bool "Support for hot-pluggable devices"
help
diff --git a/arch/xtensa/include/asm/checksum.h b/arch/xtensa/include/asm/checksum.h
index f84d3f00774a..e4d831a30772 100644
--- a/arch/xtensa/include/asm/checksum.h
+++ b/arch/xtensa/include/asm/checksum.h
@@ -113,7 +113,8 @@ static __inline__ __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
are modified, we must also specify them as outputs, or gcc
will assume they contain their original values. */
: "=r" (sum), "=r" (iph), "=r" (ihl), "=&r" (tmp), "=&r" (endaddr)
- : "1" (iph), "2" (ihl));
+ : "1" (iph), "2" (ihl)
+ : "memory");
return csum_fold(sum);
}
@@ -227,7 +228,8 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
"1:\t"
: "=r" (sum), "=&r" (__dummy)
: "r" (saddr), "r" (daddr),
- "r" (htonl(len)), "r" (htonl(proto)), "0" (sum));
+ "r" (htonl(len)), "r" (htonl(proto)), "0" (sum)
+ : "memory");
return csum_fold(sum);
}
diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S
index 0817f9db836e..d9ddc1ba761c 100644
--- a/arch/xtensa/kernel/head.S
+++ b/arch/xtensa/kernel/head.S
@@ -19,6 +19,7 @@
#include <asm/page.h>
#include <asm/cacheasm.h>
+#include <linux/init.h>
#include <linux/linkage.h>
/*
@@ -45,7 +46,7 @@
* instruction.
*/
- .section .head.text, "ax"
+ __HEAD
.globl _start
_start: _j 2f
.align 4
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
index c1be9a4a740c..5accf51053da 100644
--- a/arch/xtensa/kernel/vmlinux.lds.S
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -85,8 +85,8 @@ SECTIONS
.text :
{
- /* The .head.text section must be the first section! */
- *(.head.text)
+ /* The HEAD_TEXT section must be the first section! */
+ HEAD_TEXT
*(.literal .text)
VMLINUX_SYMBOL(__sched_text_start) = .;
*(.sched.literal .sched.text)
diff --git a/block/Kconfig b/block/Kconfig
index e7d12782bcfb..2c39527aa7db 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -26,6 +26,7 @@ if BLOCK
config LBD
bool "Support for large block devices and files"
depends on !64BIT
+ default y
help
Enable block devices or files of size 2TB and larger.
@@ -38,11 +39,13 @@ config LBD
The ext4 filesystem requires that this feature be enabled in
order to support filesystems that have the huge_file feature
- enabled. Otherwise, it will refuse to mount any filesystems
- that use the huge_file feature, which is enabled by default
- by mke2fs.ext4. The GFS2 filesystem also requires this feature.
+ enabled. Otherwise, it will refuse to mount in the read-write
+ mode any filesystems that use the huge_file feature, which is
+ enabled by default by mke2fs.ext4.
- If unsure, say N.
+ The GFS2 filesystem also requires this feature.
+
+ If unsure, say Y.
config BLK_DEV_BSG
bool "Block layer SG support v4 (EXPERIMENTAL)"
diff --git a/block/as-iosched.c b/block/as-iosched.c
index 631f6f44460a..45bd07059c28 100644
--- a/block/as-iosched.c
+++ b/block/as-iosched.c
@@ -17,9 +17,6 @@
#include <linux/rbtree.h>
#include <linux/interrupt.h>
-#define REQ_SYNC 1
-#define REQ_ASYNC 0
-
/*
* See Documentation/block/as-iosched.txt
*/
@@ -93,7 +90,7 @@ struct as_data {
struct list_head fifo_list[2];
struct request *next_rq[2]; /* next in sort order */
- sector_t last_sector[2]; /* last REQ_SYNC & REQ_ASYNC sectors */
+ sector_t last_sector[2]; /* last SYNC & ASYNC sectors */
unsigned long exit_prob; /* probability a task will exit while
being waited on */
@@ -109,7 +106,7 @@ struct as_data {
unsigned long last_check_fifo[2];
int changed_batch; /* 1: waiting for old batch to end */
int new_batch; /* 1: waiting on first read complete */
- int batch_data_dir; /* current batch REQ_SYNC / REQ_ASYNC */
+ int batch_data_dir; /* current batch SYNC / ASYNC */
int write_batch_count; /* max # of reqs in a write batch */
int current_write_count; /* how many requests left this batch */
int write_batch_idled; /* has the write batch gone idle? */
@@ -554,7 +551,7 @@ static void as_update_iohist(struct as_data *ad, struct as_io_context *aic,
if (aic == NULL)
return;
- if (data_dir == REQ_SYNC) {
+ if (data_dir == BLK_RW_SYNC) {
unsigned long in_flight = atomic_read(&aic->nr_queued)
+ atomic_read(&aic->nr_dispatched);
spin_lock(&aic->lock);
@@ -811,7 +808,7 @@ static void as_update_rq(struct as_data *ad, struct request *rq)
*/
static void update_write_batch(struct as_data *ad)
{
- unsigned long batch = ad->batch_expire[REQ_ASYNC];
+ unsigned long batch = ad->batch_expire[BLK_RW_ASYNC];
long write_time;
write_time = (jiffies - ad->current_batch_expires) + batch;
@@ -855,7 +852,7 @@ static void as_completed_request(struct request_queue *q, struct request *rq)
kblockd_schedule_work(q, &ad->antic_work);
ad->changed_batch = 0;
- if (ad->batch_data_dir == REQ_SYNC)
+ if (ad->batch_data_dir == BLK_RW_SYNC)
ad->new_batch = 1;
}
WARN_ON(ad->nr_dispatched == 0);
@@ -869,7 +866,7 @@ static void as_completed_request(struct request_queue *q, struct request *rq)
if (ad->new_batch && ad->batch_data_dir == rq_is_sync(rq)) {
update_write_batch(ad);
ad->current_batch_expires = jiffies +
- ad->batch_expire[REQ_SYNC];
+ ad->batch_expire[BLK_RW_SYNC];
ad->new_batch = 0;
}
@@ -960,7 +957,7 @@ static inline int as_batch_expired(struct as_data *ad)
if (ad->changed_batch || ad->new_batch)
return 0;
- if (ad->batch_data_dir == REQ_SYNC)
+ if (ad->batch_data_dir == BLK_RW_SYNC)
/* TODO! add a check so a complete fifo gets written? */
return time_after(jiffies, ad->current_batch_expires);
@@ -986,7 +983,7 @@ static void as_move_to_dispatch(struct as_data *ad, struct request *rq)
*/
ad->last_sector[data_dir] = rq->sector + rq->nr_sectors;
- if (data_dir == REQ_SYNC) {
+ if (data_dir == BLK_RW_SYNC) {
struct io_context *ioc = RQ_IOC(rq);
/* In case we have to anticipate after this */
copy_io_context(&ad->io_context, &ioc);
@@ -1025,41 +1022,41 @@ static void as_move_to_dispatch(struct as_data *ad, struct request *rq)
static int as_dispatch_request(struct request_queue *q, int force)
{
struct as_data *ad = q->elevator->elevator_data;
- const int reads = !list_empty(&ad->fifo_list[REQ_SYNC]);
- const int writes = !list_empty(&ad->fifo_list[REQ_ASYNC]);
+ const int reads = !list_empty(&ad->fifo_list[BLK_RW_SYNC]);
+ const int writes = !list_empty(&ad->fifo_list[BLK_RW_ASYNC]);
struct request *rq;
if (unlikely(force)) {
/*
* Forced dispatch, accounting is useless. Reset
* accounting states and dump fifo_lists. Note that
- * batch_data_dir is reset to REQ_SYNC to avoid
+ * batch_data_dir is reset to BLK_RW_SYNC to avoid
* screwing write batch accounting as write batch
* accounting occurs on W->R transition.
*/
int dispatched = 0;
- ad->batch_data_dir = REQ_SYNC;
+ ad->batch_data_dir = BLK_RW_SYNC;
ad->changed_batch = 0;
ad->new_batch = 0;
- while (ad->next_rq[REQ_SYNC]) {
- as_move_to_dispatch(ad, ad->next_rq[REQ_SYNC]);
+ while (ad->next_rq[BLK_RW_SYNC]) {
+ as_move_to_dispatch(ad, ad->next_rq[BLK_RW_SYNC]);
dispatched++;
}
- ad->last_check_fifo[REQ_SYNC] = jiffies;
+ ad->last_check_fifo[BLK_RW_SYNC] = jiffies;
- while (ad->next_rq[REQ_ASYNC]) {
- as_move_to_dispatch(ad, ad->next_rq[REQ_ASYNC]);
+ while (ad->next_rq[BLK_RW_ASYNC]) {
+ as_move_to_dispatch(ad, ad->next_rq[BLK_RW_ASYNC]);
dispatched++;
}
- ad->last_check_fifo[REQ_ASYNC] = jiffies;
+ ad->last_check_fifo[BLK_RW_ASYNC] = jiffies;
return dispatched;
}
/* Signal that the write batch was uncontended, so we can't time it */
- if (ad->batch_data_dir == REQ_ASYNC && !reads) {
+ if (ad->batch_data_dir == BLK_RW_ASYNC && !reads) {
if (ad->current_write_count == 0 || !writes)
ad->write_batch_idled = 1;
}
@@ -1076,8 +1073,8 @@ static int as_dispatch_request(struct request_queue *q, int force)
*/
rq = ad->next_rq[ad->batch_data_dir];
- if (ad->batch_data_dir == REQ_SYNC && ad->antic_expire) {
- if (as_fifo_expired(ad, REQ_SYNC))
+ if (ad->batch_data_dir == BLK_RW_SYNC && ad->antic_expire) {
+ if (as_fifo_expired(ad, BLK_RW_SYNC))
goto fifo_expired;
if (as_can_anticipate(ad, rq)) {
@@ -1090,7 +1087,7 @@ static int as_dispatch_request(struct request_queue *q, int force)
/* we have a "next request" */
if (reads && !writes)
ad->current_batch_expires =
- jiffies + ad->batch_expire[REQ_SYNC];
+ jiffies + ad->batch_expire[BLK_RW_SYNC];
goto dispatch_request;
}
}
@@ -1101,20 +1098,20 @@ static int as_dispatch_request(struct request_queue *q, int force)
*/
if (reads) {
- BUG_ON(RB_EMPTY_ROOT(&ad->sort_list[REQ_SYNC]));
+ BUG_ON(RB_EMPTY_ROOT(&ad->sort_list[BLK_RW_SYNC]));
- if (writes && ad->batch_data_dir == REQ_SYNC)
+ if (writes && ad->batch_data_dir == BLK_RW_SYNC)
/*
* Last batch was a read, switch to writes
*/
goto dispatch_writes;
- if (ad->batch_data_dir == REQ_ASYNC) {
+ if (ad->batch_data_dir == BLK_RW_ASYNC) {
WARN_ON(ad->new_batch);
ad->changed_batch = 1;
}
- ad->batch_data_dir = REQ_SYNC;
- rq = rq_entry_fifo(ad->fifo_list[REQ_SYNC].next);
+ ad->batch_data_dir = BLK_RW_SYNC;
+ rq = rq_entry_fifo(ad->fifo_list[BLK_RW_SYNC].next);
ad->last_check_fifo[ad->batch_data_dir] = jiffies;
goto dispatch_request;
}
@@ -1125,9 +1122,9 @@ static int as_dispatch_request(struct request_queue *q, int force)
if (writes) {
dispatch_writes:
- BUG_ON(RB_EMPTY_ROOT(&ad->sort_list[REQ_ASYNC]));
+ BUG_ON(RB_EMPTY_ROOT(&ad->sort_list[BLK_RW_ASYNC]));
- if (ad->batch_data_dir == REQ_SYNC) {
+ if (ad->batch_data_dir == BLK_RW_SYNC) {
ad->changed_batch = 1;
/*
@@ -1137,11 +1134,11 @@ dispatch_writes:
*/
ad->new_batch = 0;
}
- ad->batch_data_dir = REQ_ASYNC;
+ ad->batch_data_dir = BLK_RW_ASYNC;
ad->current_write_count = ad->write_batch_count;
ad->write_batch_idled = 0;
- rq = rq_entry_fifo(ad->fifo_list[REQ_ASYNC].next);
- ad->last_check_fifo[REQ_ASYNC] = jiffies;
+ rq = rq_entry_fifo(ad->fifo_list[BLK_RW_ASYNC].next);
+ ad->last_check_fifo[BLK_RW_ASYNC] = jiffies;
goto dispatch_request;
}
@@ -1164,9 +1161,9 @@ fifo_expired:
if (ad->nr_dispatched)
return 0;
- if (ad->batch_data_dir == REQ_ASYNC)
+ if (ad->batch_data_dir == BLK_RW_ASYNC)
ad->current_batch_expires = jiffies +
- ad->batch_expire[REQ_ASYNC];
+ ad->batch_expire[BLK_RW_ASYNC];
else
ad->new_batch = 1;
@@ -1238,8 +1235,8 @@ static int as_queue_empty(struct request_queue *q)
{
struct as_data *ad = q->elevator->elevator_data;
- return list_empty(&ad->fifo_list[REQ_ASYNC])
- && list_empty(&ad->fifo_list[REQ_SYNC]);
+ return list_empty(&ad->fifo_list[BLK_RW_ASYNC])
+ && list_empty(&ad->fifo_list[BLK_RW_SYNC]);
}
static int
@@ -1315,12 +1312,8 @@ static void as_merged_requests(struct request_queue *q, struct request *req,
static void as_work_handler(struct work_struct *work)
{
struct as_data *ad = container_of(work, struct as_data, antic_work);
- struct request_queue *q = ad->q;
- unsigned long flags;
- spin_lock_irqsave(q->queue_lock, flags);
- blk_start_queueing(q);
- spin_unlock_irqrestore(q->queue_lock, flags);
+ blk_run_queue(ad->q);
}
static int as_may_queue(struct request_queue *q, int rw)
@@ -1346,8 +1339,8 @@ static void as_exit_queue(struct elevator_queue *e)
del_timer_sync(&ad->antic_timer);
cancel_work_sync(&ad->antic_work);
- BUG_ON(!list_empty(&ad->fifo_list[REQ_SYNC]));
- BUG_ON(!list_empty(&ad->fifo_list[REQ_ASYNC]));
+ BUG_ON(!list_empty(&ad->fifo_list[BLK_RW_SYNC]));
+ BUG_ON(!list_empty(&ad->fifo_list[BLK_RW_ASYNC]));
put_io_context(ad->io_context);
kfree(ad);
@@ -1372,18 +1365,18 @@ static void *as_init_queue(struct request_queue *q)
init_timer(&ad->antic_timer);
INIT_WORK(&ad->antic_work, as_work_handler);
- INIT_LIST_HEAD(&ad->fifo_list[REQ_SYNC]);
- INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]);
- ad->sort_list[REQ_SYNC] = RB_ROOT;
- ad->sort_list[REQ_ASYNC] = RB_ROOT;
- ad->fifo_expire[REQ_SYNC] = default_read_expire;
- ad->fifo_expire[REQ_ASYNC] = default_write_expire;
+ INIT_LIST_HEAD(&ad->fifo_list[BLK_RW_SYNC]);
+ INIT_LIST_HEAD(&ad->fifo_list[BLK_RW_ASYNC]);
+ ad->sort_list[BLK_RW_SYNC] = RB_ROOT;
+ ad->sort_list[BLK_RW_ASYNC] = RB_ROOT;
+ ad->fifo_expire[BLK_RW_SYNC] = default_read_expire;
+ ad->fifo_expire[BLK_RW_ASYNC] = default_write_expire;
ad->antic_expire = default_antic_expire;
- ad->batch_expire[REQ_SYNC] = default_read_batch_expire;
- ad->batch_expire[REQ_ASYNC] = default_write_batch_expire;
+ ad->batch_expire[BLK_RW_SYNC] = default_read_batch_expire;
+ ad->batch_expire[BLK_RW_ASYNC] = default_write_batch_expire;
- ad->current_batch_expires = jiffies + ad->batch_expire[REQ_SYNC];
- ad->write_batch_count = ad->batch_expire[REQ_ASYNC] / 10;
+ ad->current_batch_expires = jiffies + ad->batch_expire[BLK_RW_SYNC];
+ ad->write_batch_count = ad->batch_expire[BLK_RW_ASYNC] / 10;
if (ad->write_batch_count < 2)
ad->write_batch_count = 2;
@@ -1432,11 +1425,11 @@ static ssize_t __FUNC(struct elevator_queue *e, char *page) \
struct as_data *ad = e->elevator_data; \
return as_var_show(jiffies_to_msecs((__VAR)), (page)); \
}
-SHOW_FUNCTION(as_read_expire_show, ad->fifo_expire[REQ_SYNC]);
-SHOW_FUNCTION(as_write_expire_show, ad->fifo_expire[REQ_ASYNC]);
+SHOW_FUNCTION(as_read_expire_show, ad->fifo_expire[BLK_RW_SYNC]);
+SHOW_FUNCTION(as_write_expire_show, ad->fifo_expire[BLK_RW_ASYNC]);
SHOW_FUNCTION(as_antic_expire_show, ad->antic_expire);
-SHOW_FUNCTION(as_read_batch_expire_show, ad->batch_expire[REQ_SYNC]);
-SHOW_FUNCTION(as_write_batch_expire_show, ad->batch_expire[REQ_ASYNC]);
+SHOW_FUNCTION(as_read_batch_expire_show, ad->batch_expire[BLK_RW_SYNC]);
+SHOW_FUNCTION(as_write_batch_expire_show, ad->batch_expire[BLK_RW_ASYNC]);
#undef SHOW_FUNCTION
#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX) \
@@ -1451,13 +1444,14 @@ static ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count)
*(__PTR) = msecs_to_jiffies(*(__PTR)); \
return ret; \
}
-STORE_FUNCTION(as_read_expire_store, &ad->fifo_expire[REQ_SYNC], 0, INT_MAX);
-STORE_FUNCTION(as_write_expire_store, &ad->fifo_expire[REQ_ASYNC], 0, INT_MAX);
+STORE_FUNCTION(as_read_expire_store, &ad->fifo_expire[BLK_RW_SYNC], 0, INT_MAX);
+STORE_FUNCTION(as_write_expire_store,
+ &ad->fifo_expire[BLK_RW_ASYNC], 0, INT_MAX);
STORE_FUNCTION(as_antic_expire_store, &ad->antic_expire, 0, INT_MAX);
STORE_FUNCTION(as_read_batch_expire_store,
- &ad->batch_expire[REQ_SYNC], 0, INT_MAX);
+ &ad->batch_expire[BLK_RW_SYNC], 0, INT_MAX);
STORE_FUNCTION(as_write_batch_expire_store,
- &ad->batch_expire[REQ_ASYNC], 0, INT_MAX);
+ &ad->batch_expire[BLK_RW_ASYNC], 0, INT_MAX);
#undef STORE_FUNCTION
#define AS_ATTR(name) \
diff --git a/block/blk-barrier.c b/block/blk-barrier.c
index f7dae57e6cab..c8d087655eff 100644
--- a/block/blk-barrier.c
+++ b/block/blk-barrier.c
@@ -106,10 +106,7 @@ bool blk_ordered_complete_seq(struct request_queue *q, unsigned seq, int error)
*/
q->ordseq = 0;
rq = q->orig_bar_rq;
-
- if (__blk_end_request(rq, q->orderr, blk_rq_bytes(rq)))
- BUG();
-
+ __blk_end_request_all(rq, q->orderr);
return true;
}
@@ -252,9 +249,7 @@ bool blk_do_ordered(struct request_queue *q, struct request **rqp)
* with prejudice.
*/
elv_dequeue_request(q, rq);
- if (__blk_end_request(rq, -EOPNOTSUPP,
- blk_rq_bytes(rq)))
- BUG();
+ __blk_end_request_all(rq, -EOPNOTSUPP);
*rqp = NULL;
return false;
}
@@ -319,9 +314,6 @@ int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector)
return -ENXIO;
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;
diff --git a/block/blk-core.c b/block/blk-core.c
index 07ab75403e1a..1b14c2c7a65d 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -68,7 +68,7 @@ static void drive_stat_acct(struct request *rq, int new_io)
int rw = rq_data_dir(rq);
int cpu;
- if (!blk_fs_request(rq) || !blk_do_io_stat(rq))
+ if (!blk_do_io_stat(rq))
return;
cpu = part_stat_lock();
@@ -134,6 +134,7 @@ void blk_rq_init(struct request_queue *q, struct request *rq)
rq->cmd_len = BLK_MAX_CDB;
rq->tag = -1;
rq->ref_count = 1;
+ rq->start_time = jiffies;
}
EXPORT_SYMBOL(blk_rq_init);
@@ -188,10 +189,9 @@ void blk_dump_rq_flags(struct request *rq, char *msg)
(unsigned long long)rq->sector,
rq->nr_sectors,
rq->current_nr_sectors);
- printk(KERN_INFO " bio %p, biotail %p, buffer %p, data %p, len %u\n",
+ printk(KERN_INFO " bio %p, biotail %p, buffer %p, len %u\n",
rq->bio, rq->biotail,
- rq->buffer, rq->data,
- rq->data_len);
+ rq->buffer, rq->data_len);
if (blk_pc_request(rq)) {
printk(KERN_INFO " cdb: ");
@@ -333,24 +333,6 @@ void blk_unplug(struct request_queue *q)
}
EXPORT_SYMBOL(blk_unplug);
-static void blk_invoke_request_fn(struct request_queue *q)
-{
- if (unlikely(blk_queue_stopped(q)))
- return;
-
- /*
- * one level of recursion is ok and is much faster than kicking
- * the unplug handling
- */
- if (!queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) {
- q->request_fn(q);
- queue_flag_clear(QUEUE_FLAG_REENTER, q);
- } else {
- queue_flag_set(QUEUE_FLAG_PLUGGED, q);
- kblockd_schedule_work(q, &q->unplug_work);
- }
-}
-
/**
* blk_start_queue - restart a previously stopped queue
* @q: The &struct request_queue in question
@@ -365,7 +347,7 @@ void blk_start_queue(struct request_queue *q)
WARN_ON(!irqs_disabled());
queue_flag_clear(QUEUE_FLAG_STOPPED, q);
- blk_invoke_request_fn(q);
+ __blk_run_queue(q);
}
EXPORT_SYMBOL(blk_start_queue);
@@ -425,12 +407,23 @@ void __blk_run_queue(struct request_queue *q)
{
blk_remove_plug(q);
+ if (unlikely(blk_queue_stopped(q)))
+ return;
+
+ if (elv_queue_empty(q))
+ return;
+
/*
* Only recurse once to avoid overrunning the stack, let the unplug
* handling reinvoke the handler shortly if we already got there.
*/
- if (!elv_queue_empty(q))
- blk_invoke_request_fn(q);
+ if (!queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) {
+ q->request_fn(q);
+ queue_flag_clear(QUEUE_FLAG_REENTER, q);
+ } else {
+ queue_flag_set(QUEUE_FLAG_PLUGGED, q);
+ kblockd_schedule_work(q, &q->unplug_work);
+ }
}
EXPORT_SYMBOL(__blk_run_queue);
@@ -440,9 +433,7 @@ EXPORT_SYMBOL(__blk_run_queue);
*
* Description:
* Invoke request handling on this queue, if it has pending work to do.
- * May be used to restart queueing when a request has completed. Also
- * See @blk_start_queueing.
- *
+ * May be used to restart queueing when a request has completed.
*/
void blk_run_queue(struct request_queue *q)
{
@@ -643,7 +634,7 @@ static inline void blk_free_request(struct request_queue *q, struct request *rq)
}
static struct request *
-blk_alloc_request(struct request_queue *q, int rw, int priv, gfp_t gfp_mask)
+blk_alloc_request(struct request_queue *q, int flags, int priv, gfp_t gfp_mask)
{
struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask);
@@ -652,7 +643,7 @@ blk_alloc_request(struct request_queue *q, int rw, int priv, gfp_t gfp_mask)
blk_rq_init(q, rq);
- rq->cmd_flags = rw | REQ_ALLOCED;
+ rq->cmd_flags = flags | REQ_ALLOCED;
if (priv) {
if (unlikely(elv_set_request(q, rq, gfp_mask))) {
@@ -792,6 +783,8 @@ static struct request *get_request(struct request_queue *q, int rw_flags,
if (priv)
rl->elvpriv++;
+ if (blk_queue_io_stat(q))
+ rw_flags |= REQ_IO_STAT;
spin_unlock_irq(q->queue_lock);
rq = blk_alloc_request(q, rw_flags, priv, gfp_mask);
@@ -900,28 +893,6 @@ struct request *blk_get_request(struct request_queue *q, int rw, gfp_t gfp_mask)
EXPORT_SYMBOL(blk_get_request);
/**
- * blk_start_queueing - initiate dispatch of requests to device
- * @q: request queue to kick into gear
- *
- * This is basically a helper to remove the need to know whether a queue
- * is plugged or not if someone just wants to initiate dispatch of requests
- * for this queue. Should be used to start queueing on a device outside
- * of ->request_fn() context. Also see @blk_run_queue.
- *
- * The queue lock must be held with interrupts disabled.
- */
-void blk_start_queueing(struct request_queue *q)
-{
- if (!blk_queue_plugged(q)) {
- if (unlikely(blk_queue_stopped(q)))
- return;
- q->request_fn(q);
- } else
- __generic_unplug_device(q);
-}
-EXPORT_SYMBOL(blk_start_queueing);
-
-/**
* blk_requeue_request - put a request back on queue
* @q: request queue where request should be inserted
* @rq: request to be inserted
@@ -975,7 +946,6 @@ void blk_insert_request(struct request_queue *q, struct request *rq,
* barrier
*/
rq->cmd_type = REQ_TYPE_SPECIAL;
- rq->cmd_flags |= REQ_SOFTBARRIER;
rq->special = data;
@@ -989,7 +959,7 @@ void blk_insert_request(struct request_queue *q, struct request *rq,
drive_stat_acct(rq, 1);
__elv_add_request(q, rq, where, 0);
- blk_start_queueing(q);
+ __blk_run_queue(q);
spin_unlock_irqrestore(q->queue_lock, flags);
}
EXPORT_SYMBOL(blk_insert_request);
@@ -1111,16 +1081,13 @@ void init_request_from_bio(struct request *req, struct bio *bio)
if (bio_failfast_driver(bio))
req->cmd_flags |= REQ_FAILFAST_DRIVER;
- /*
- * REQ_BARRIER implies no merging, but lets make it explicit
- */
if (unlikely(bio_discard(bio))) {
req->cmd_flags |= REQ_DISCARD;
if (bio_barrier(bio))
req->cmd_flags |= REQ_SOFTBARRIER;
req->q->prepare_discard_fn(req->q, req);
} else if (unlikely(bio_barrier(bio)))
- req->cmd_flags |= (REQ_HARDBARRIER | REQ_NOMERGE);
+ req->cmd_flags |= REQ_HARDBARRIER;
if (bio_sync(bio))
req->cmd_flags |= REQ_RW_SYNC;
@@ -1132,7 +1099,6 @@ void init_request_from_bio(struct request *req, struct bio *bio)
req->errors = 0;
req->hard_sector = req->sector = bio->bi_sector;
req->ioprio = bio_prio(bio);
- req->start_time = jiffies;
blk_rq_bio_prep(req->q, req, bio);
}
@@ -1275,7 +1241,7 @@ static inline void blk_partition_remap(struct bio *bio)
bio->bi_bdev = bdev->bd_contains;
trace_block_remap(bdev_get_queue(bio->bi_bdev), bio,
- bdev->bd_dev, bio->bi_sector,
+ bdev->bd_dev,
bio->bi_sector - p->start_sect);
}
}
@@ -1444,8 +1410,7 @@ static inline void __generic_make_request(struct bio *bio)
goto end_io;
if (old_sector != -1)
- trace_block_remap(q, bio, old_dev, bio->bi_sector,
- old_sector);
+ trace_block_remap(q, bio, old_dev, old_sector);
trace_block_bio_queue(q, bio);
@@ -1673,10 +1638,7 @@ EXPORT_SYMBOL(blkdev_dequeue_request);
static void blk_account_io_completion(struct request *req, unsigned int bytes)
{
- if (!blk_do_io_stat(req))
- return;
-
- if (blk_fs_request(req)) {
+ if (blk_do_io_stat(req)) {
const int rw = rq_data_dir(req);
struct hd_struct *part;
int cpu;
@@ -1690,15 +1652,12 @@ static void blk_account_io_completion(struct request *req, unsigned int bytes)
static void blk_account_io_done(struct request *req)
{
- if (!blk_do_io_stat(req))
- return;
-
/*
* Account IO completion. bar_rq isn't accounted as a normal
* IO on queueing nor completion. Accounting the containing
* request is enough.
*/
- if (blk_fs_request(req) && req != &req->q->bar_rq) {
+ if (blk_do_io_stat(req) && req != &req->q->bar_rq) {
unsigned long duration = jiffies - req->start_time;
const int rw = rq_data_dir(req);
struct hd_struct *part;
@@ -1717,32 +1676,170 @@ static void blk_account_io_done(struct request *req)
}
/**
- * __end_that_request_first - end I/O on a request
- * @req: the request being processed
+ * blk_rq_bytes - Returns bytes left to complete in the entire request
+ * @rq: the request being processed
+ **/
+unsigned int blk_rq_bytes(struct request *rq)
+{
+ if (blk_fs_request(rq))
+ return rq->hard_nr_sectors << 9;
+
+ return rq->data_len;
+}
+EXPORT_SYMBOL_GPL(blk_rq_bytes);
+
+/**
+ * blk_rq_cur_bytes - Returns bytes left to complete in the current segment
+ * @rq: the request being processed
+ **/
+unsigned int blk_rq_cur_bytes(struct request *rq)
+{
+ if (blk_fs_request(rq))
+ return rq->current_nr_sectors << 9;
+
+ if (rq->bio)
+ return rq->bio->bi_size;
+
+ return rq->data_len;
+}
+EXPORT_SYMBOL_GPL(blk_rq_cur_bytes);
+
+struct request *elv_next_request(struct request_queue *q)
+{
+ struct request *rq;
+ int ret;
+
+ while ((rq = __elv_next_request(q)) != NULL) {
+ if (!(rq->cmd_flags & REQ_STARTED)) {
+ /*
+ * This is the first time the device driver
+ * sees this request (possibly after
+ * requeueing). Notify IO scheduler.
+ */
+ if (blk_sorted_rq(rq))
+ elv_activate_rq(q, rq);
+
+ /*
+ * just mark as started even if we don't start
+ * it, a request that has been delayed should
+ * not be passed by new incoming requests
+ */
+ rq->cmd_flags |= REQ_STARTED;
+ trace_block_rq_issue(q, rq);
+ }
+
+ if (!q->boundary_rq || q->boundary_rq == rq) {
+ q->end_sector = rq_end_sector(rq);
+ q->boundary_rq = NULL;
+ }
+
+ if (rq->cmd_flags & REQ_DONTPREP)
+ break;
+
+ if (q->dma_drain_size && rq->data_len) {
+ /*
+ * make sure space for the drain appears we
+ * know we can do this because max_hw_segments
+ * has been adjusted to be one fewer than the
+ * device can handle
+ */
+ rq->nr_phys_segments++;
+ }
+
+ if (!q->prep_rq_fn)
+ break;
+
+ ret = q->prep_rq_fn(q, rq);
+ if (ret == BLKPREP_OK) {
+ break;
+ } else if (ret == BLKPREP_DEFER) {
+ /*
+ * the request may have been (partially) prepped.
+ * we need to keep this request in the front to
+ * avoid resource deadlock. REQ_STARTED will
+ * prevent other fs requests from passing this one.
+ */
+ if (q->dma_drain_size && rq->data_len &&
+ !(rq->cmd_flags & REQ_DONTPREP)) {
+ /*
+ * remove the space for the drain we added
+ * so that we don't add it again
+ */
+ --rq->nr_phys_segments;
+ }
+
+ rq = NULL;
+ break;
+ } else if (ret == BLKPREP_KILL) {
+ rq->cmd_flags |= REQ_QUIET;
+ __blk_end_request_all(rq, -EIO);
+ } else {
+ printk(KERN_ERR "%s: bad return=%d\n", __func__, ret);
+ break;
+ }
+ }
+
+ return rq;
+}
+EXPORT_SYMBOL(elv_next_request);
+
+void elv_dequeue_request(struct request_queue *q, struct request *rq)
+{
+ BUG_ON(list_empty(&rq->queuelist));
+ BUG_ON(ELV_ON_HASH(rq));
+
+ list_del_init(&rq->queuelist);
+
+ /*
+ * the time frame between a request being removed from the lists
+ * and to it is freed is accounted as io that is in progress at
+ * the driver side.
+ */
+ if (blk_account_rq(rq))
+ q->in_flight++;
+}
+
+/**
+ * blk_update_request - Special helper function for request stacking drivers
+ * @rq: the request being processed
* @error: %0 for success, < %0 for error
- * @nr_bytes: number of bytes to complete
+ * @nr_bytes: number of bytes to complete @rq
*
* Description:
- * Ends I/O on a number of bytes attached to @req, and sets it up
- * for the next range of segments (if any) in the cluster.
+ * Ends I/O on a number of bytes attached to @rq, but doesn't complete
+ * the request structure even if @rq doesn't have leftover.
+ * If @rq has leftover, sets it up for the next range of segments.
+ *
+ * This special helper function is only for request stacking drivers
+ * (e.g. request-based dm) so that they can handle partial completion.
+ * Actual device drivers should use blk_end_request instead.
+ *
+ * Passing the result of blk_rq_bytes() as @nr_bytes guarantees
+ * %false return from this function.
*
* Return:
- * %0 - we are done with this request, call end_that_request_last()
- * %1 - still buffers pending for this request
+ * %false - this request doesn't have any more data
+ * %true - this request has more data
**/
-static int __end_that_request_first(struct request *req, int error,
- int nr_bytes)
+bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
{
int total_bytes, bio_nbytes, next_idx = 0;
struct bio *bio;
+ if (!req->bio)
+ return false;
+
trace_block_rq_complete(req->q, req);
/*
- * for a REQ_TYPE_BLOCK_PC request, we want to carry any eventual
- * sense key with us all the way through
+ * For fs requests, rq is just carrier of independent bio's
+ * and each partial completion should be handled separately.
+ * Reset per-request error on each partial completion.
+ *
+ * TODO: tj: This is too subtle. It would be better to let
+ * low level drivers do what they see fit.
*/
- if (!blk_pc_request(req))
+ if (blk_fs_request(req))
req->errors = 0;
if (error && (blk_fs_request(req) && !(req->cmd_flags & REQ_QUIET))) {
@@ -1808,8 +1905,16 @@ static int __end_that_request_first(struct request *req, int error,
/*
* completely done
*/
- if (!req->bio)
- return 0;
+ if (!req->bio) {
+ /*
+ * Reset counters so that the request stacking driver
+ * can find how many bytes remain in the request
+ * later.
+ */
+ req->nr_sectors = req->hard_nr_sectors = 0;
+ req->current_nr_sectors = req->hard_cur_sectors = 0;
+ return false;
+ }
/*
* if the request wasn't completed, update state
@@ -1823,13 +1928,31 @@ static int __end_that_request_first(struct request *req, int error,
blk_recalc_rq_sectors(req, total_bytes >> 9);
blk_recalc_rq_segments(req);
- return 1;
+ return true;
+}
+EXPORT_SYMBOL_GPL(blk_update_request);
+
+static bool blk_update_bidi_request(struct request *rq, int error,
+ unsigned int nr_bytes,
+ unsigned int bidi_bytes)
+{
+ if (blk_update_request(rq, error, nr_bytes))
+ return true;
+
+ /* Bidi request must be completed as a whole */
+ if (unlikely(blk_bidi_rq(rq)) &&
+ blk_update_request(rq->next_rq, error, bidi_bytes))
+ return true;
+
+ add_disk_randomness(rq->rq_disk);
+
+ return false;
}
/*
* queue lock must be held
*/
-static void end_that_request_last(struct request *req, int error)
+static void blk_finish_request(struct request *req, int error)
{
if (blk_rq_tagged(req))
blk_queue_end_tag(req->q, req);
@@ -1855,248 +1978,65 @@ static void end_that_request_last(struct request *req, int error)
}
/**
- * blk_rq_bytes - Returns bytes left to complete in the entire request
- * @rq: the request being processed
- **/
-unsigned int blk_rq_bytes(struct request *rq)
-{
- if (blk_fs_request(rq))
- return rq->hard_nr_sectors << 9;
-
- return rq->data_len;
-}
-EXPORT_SYMBOL_GPL(blk_rq_bytes);
-
-/**
- * blk_rq_cur_bytes - Returns bytes left to complete in the current segment
- * @rq: the request being processed
- **/
-unsigned int blk_rq_cur_bytes(struct request *rq)
-{
- if (blk_fs_request(rq))
- return rq->current_nr_sectors << 9;
-
- if (rq->bio)
- return rq->bio->bi_size;
-
- return rq->data_len;
-}
-EXPORT_SYMBOL_GPL(blk_rq_cur_bytes);
-
-/**
- * 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 I/O completions.
- * Modern drivers typically end I/O 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. Use blk_end_request() or __blk_end_request() to end a request.
- **/
-void end_request(struct request *req, int uptodate)
-{
- int error = 0;
-
- if (uptodate <= 0)
- error = uptodate ? uptodate : -EIO;
-
- __blk_end_request(req, error, req->hard_cur_sectors << 9);
-}
-EXPORT_SYMBOL(end_request);
-
-static int end_that_request_data(struct request *rq, int error,
- unsigned int nr_bytes, unsigned int bidi_bytes)
-{
- if (rq->bio) {
- if (__end_that_request_first(rq, error, nr_bytes))
- return 1;
-
- /* Bidi request must be completed as a whole */
- if (blk_bidi_rq(rq) &&
- __end_that_request_first(rq->next_rq, error, bidi_bytes))
- return 1;
- }
-
- return 0;
-}
-
-/**
- * blk_end_io - Generic end_io function to complete a request.
- * @rq: the request being processed
- * @error: %0 for success, < %0 for error
- * @nr_bytes: number of bytes to complete @rq
- * @bidi_bytes: number of bytes to complete @rq->next_rq
- * @drv_callback: function called between completion of bios in the request
- * and completion of the request.
- * If the callback returns non %0, this helper returns without
- * completion of the request.
+ * blk_end_bidi_request - Complete a bidi request
+ * @rq: the request to complete
+ * @error: %0 for success, < %0 for error
+ * @nr_bytes: number of bytes to complete @rq
+ * @bidi_bytes: number of bytes to complete @rq->next_rq
*
* Description:
* Ends I/O on a number of bytes attached to @rq and @rq->next_rq.
- * If @rq has leftover, sets it up for the next range of segments.
+ * Drivers that supports bidi can safely call this member for any
+ * type of request, bidi or uni. In the later case @bidi_bytes is
+ * just ignored.
*
* Return:
- * %0 - we are done with this request
- * %1 - this request is not freed yet, it still has pending buffers.
+ * %false - we are done with this request
+ * %true - still buffers pending for this request
**/
-static int blk_end_io(struct request *rq, int error, unsigned int nr_bytes,
- unsigned int bidi_bytes,
- int (drv_callback)(struct request *))
+bool blk_end_bidi_request(struct request *rq, int error,
+ unsigned int nr_bytes, unsigned int bidi_bytes)
{
struct request_queue *q = rq->q;
- unsigned long flags = 0UL;
-
- if (end_that_request_data(rq, error, nr_bytes, bidi_bytes))
- return 1;
-
- /* Special feature for tricky drivers */
- if (drv_callback && drv_callback(rq))
- return 1;
+ unsigned long flags;
- add_disk_randomness(rq->rq_disk);
+ if (blk_update_bidi_request(rq, error, nr_bytes, bidi_bytes))
+ return true;
spin_lock_irqsave(q->queue_lock, flags);
- end_that_request_last(rq, error);
+ blk_finish_request(rq, error);
spin_unlock_irqrestore(q->queue_lock, flags);
- return 0;
-}
-
-/**
- * blk_end_request - Helper function for drivers to complete the request.
- * @rq: the request being processed
- * @error: %0 for success, < %0 for error
- * @nr_bytes: number of bytes to complete
- *
- * Description:
- * Ends I/O on a number of bytes attached to @rq.
- * If @rq has leftover, sets it up for the next range of segments.
- *
- * Return:
- * %0 - we are done with this request
- * %1 - still buffers pending for this request
- **/
-int blk_end_request(struct request *rq, int error, unsigned int nr_bytes)
-{
- return blk_end_io(rq, error, nr_bytes, 0, NULL);
-}
-EXPORT_SYMBOL_GPL(blk_end_request);
-
-/**
- * __blk_end_request - Helper function for drivers to complete the request.
- * @rq: the request being processed
- * @error: %0 for success, < %0 for error
- * @nr_bytes: number of bytes to complete
- *
- * Description:
- * Must be called with queue lock held unlike blk_end_request().
- *
- * Return:
- * %0 - we are done with this request
- * %1 - still buffers pending for this request
- **/
-int __blk_end_request(struct request *rq, int error, unsigned int nr_bytes)
-{
- if (rq->bio && __end_that_request_first(rq, error, nr_bytes))
- return 1;
-
- add_disk_randomness(rq->rq_disk);
-
- end_that_request_last(rq, error);
-
- return 0;
+ return false;
}
-EXPORT_SYMBOL_GPL(__blk_end_request);
+EXPORT_SYMBOL_GPL(blk_end_bidi_request);
/**
- * blk_end_bidi_request - Helper function for drivers to complete bidi request.
- * @rq: the bidi request being processed
+ * __blk_end_bidi_request - Complete a bidi request with queue lock held
+ * @rq: the request to complete
* @error: %0 for success, < %0 for error
* @nr_bytes: number of bytes to complete @rq
* @bidi_bytes: number of bytes to complete @rq->next_rq
*
* Description:
- * Ends I/O on a number of bytes attached to @rq and @rq->next_rq.
+ * Identical to blk_end_bidi_request() except that queue lock is
+ * assumed to be locked on entry and remains so on return.
*
* Return:
- * %0 - we are done with this request
- * %1 - still buffers pending for this request
+ * %false - we are done with this request
+ * %true - still buffers pending for this request
**/
-int blk_end_bidi_request(struct request *rq, int error, unsigned int nr_bytes,
- unsigned int bidi_bytes)
+bool __blk_end_bidi_request(struct request *rq, int error,
+ unsigned int nr_bytes, unsigned int bidi_bytes)
{
- return blk_end_io(rq, error, nr_bytes, bidi_bytes, NULL);
-}
-EXPORT_SYMBOL_GPL(blk_end_bidi_request);
+ if (blk_update_bidi_request(rq, error, nr_bytes, bidi_bytes))
+ return true;
-/**
- * blk_update_request - Special helper function for request stacking drivers
- * @rq: the request being processed
- * @error: %0 for success, < %0 for error
- * @nr_bytes: number of bytes to complete @rq
- *
- * Description:
- * Ends I/O on a number of bytes attached to @rq, but doesn't complete
- * the request structure even if @rq doesn't have leftover.
- * If @rq has leftover, sets it up for the next range of segments.
- *
- * This special helper function is only for request stacking drivers
- * (e.g. request-based dm) so that they can handle partial completion.
- * Actual device drivers should use blk_end_request instead.
- */
-void blk_update_request(struct request *rq, int error, unsigned int nr_bytes)
-{
- if (!end_that_request_data(rq, error, nr_bytes, 0)) {
- /*
- * These members are not updated in end_that_request_data()
- * when all bios are completed.
- * Update them so that the request stacking driver can find
- * how many bytes remain in the request later.
- */
- rq->nr_sectors = rq->hard_nr_sectors = 0;
- rq->current_nr_sectors = rq->hard_cur_sectors = 0;
- }
-}
-EXPORT_SYMBOL_GPL(blk_update_request);
+ blk_finish_request(rq, error);
-/**
- * blk_end_request_callback - Special helper function for tricky drivers
- * @rq: the request being processed
- * @error: %0 for success, < %0 for error
- * @nr_bytes: number of bytes to complete
- * @drv_callback: function called between completion of bios in the request
- * and completion of the request.
- * If the callback returns non %0, this helper returns without
- * completion of the request.
- *
- * Description:
- * Ends I/O on a number of bytes attached to @rq.
- * If @rq has leftover, sets it up for the next range of segments.
- *
- * This special helper function is used only for existing tricky drivers.
- * (e.g. cdrom_newpc_intr() of ide-cd)
- * This interface will be removed when such drivers are rewritten.
- * Don't use this interface in other places anymore.
- *
- * Return:
- * %0 - we are done with this request
- * %1 - this request is not freed yet.
- * this request still has pending buffers or
- * the driver doesn't want to finish this request yet.
- **/
-int blk_end_request_callback(struct request *rq, int error,
- unsigned int nr_bytes,
- int (drv_callback)(struct request *))
-{
- return blk_end_io(rq, error, nr_bytes, 0, drv_callback);
+ return false;
}
-EXPORT_SYMBOL_GPL(blk_end_request_callback);
+EXPORT_SYMBOL_GPL(__blk_end_bidi_request);
void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
struct bio *bio)
@@ -2156,6 +2096,9 @@ EXPORT_SYMBOL(kblockd_schedule_work);
int __init blk_dev_init(void)
{
+ BUILD_BUG_ON(__REQ_NR_BITS > 8 *
+ sizeof(((struct request *)0)->cmd_flags));
+
kblockd_workqueue = create_workqueue("kblockd");
if (!kblockd_workqueue)
panic("Failed to create kblockd\n");
diff --git a/block/blk-exec.c b/block/blk-exec.c
index 6af716d1e54e..49557e91f0da 100644
--- a/block/blk-exec.c
+++ b/block/blk-exec.c
@@ -51,7 +51,6 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
rq->rq_disk = bd_disk;
- rq->cmd_flags |= REQ_NOMERGE;
rq->end_io = done;
WARN_ON(irqs_disabled());
spin_lock_irq(q->queue_lock);
diff --git a/block/blk-map.c b/block/blk-map.c
index f103729b462f..694fefad34e7 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -156,7 +156,7 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq,
if (!bio_flagged(bio, BIO_USER_MAPPED))
rq->cmd_flags |= REQ_COPY_USER;
- rq->buffer = rq->data = NULL;
+ rq->buffer = NULL;
return 0;
unmap_rq:
blk_rq_unmap_user(bio);
@@ -235,7 +235,7 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
blk_queue_bounce(q, &bio);
bio_get(bio);
blk_rq_bio_prep(q, rq, bio);
- rq->buffer = rq->data = NULL;
+ rq->buffer = NULL;
return 0;
}
EXPORT_SYMBOL(blk_rq_map_user_iov);
@@ -313,7 +313,7 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
blk_rq_bio_prep(q, rq, bio);
blk_queue_bounce(q, &rq->bio);
- rq->buffer = rq->data = NULL;
+ rq->buffer = NULL;
return 0;
}
EXPORT_SYMBOL(blk_rq_map_kern);
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 63760ca3da0f..23d2a6fe34a3 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -402,7 +402,10 @@ static int attempt_merge(struct request_queue *q, struct request *req,
elv_merge_requests(q, req, next);
- blk_account_io_merge(req);
+ /*
+ * 'next' is going away, so update stats accordingly
+ */
+ blk_account_io_merge(next);
req->ioprio = ioprio_best(req->ioprio, next->ioprio);
if (blk_rq_cpu_valid(next))
diff --git a/block/blk-settings.c b/block/blk-settings.c
index 69c42adde52b..57af728d94bb 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -156,26 +156,28 @@ EXPORT_SYMBOL(blk_queue_make_request);
/**
* blk_queue_bounce_limit - set bounce buffer limit for queue
- * @q: the request queue for the device
- * @dma_addr: bus address limit
+ * @q: the request queue for the device
+ * @dma_mask: the maximum address the device can handle
*
* Description:
* Different hardware can have different requirements as to what pages
* it can do I/O directly to. A low level driver can call
* blk_queue_bounce_limit to have lower memory pages allocated as bounce
- * buffers for doing I/O to pages residing above @dma_addr.
+ * buffers for doing I/O to pages residing above @dma_mask.
**/
-void blk_queue_bounce_limit(struct request_queue *q, u64 dma_addr)
+void blk_queue_bounce_limit(struct request_queue *q, u64 dma_mask)
{
- unsigned long b_pfn = dma_addr >> PAGE_SHIFT;
+ unsigned long b_pfn = dma_mask >> PAGE_SHIFT;
int dma = 0;
q->bounce_gfp = GFP_NOIO;
#if BITS_PER_LONG == 64
- /* Assume anything <= 4GB can be handled by IOMMU.
- Actually some IOMMUs can handle everything, but I don't
- know of a way to test this here. */
- if (b_pfn < (min_t(u64, 0x100000000UL, BLK_BOUNCE_HIGH) >> PAGE_SHIFT))
+ /*
+ * Assume anything <= 4GB can be handled by IOMMU. Actually
+ * some IOMMUs can handle everything, but I don't know of a
+ * way to test this here.
+ */
+ if (b_pfn < (min_t(u64, 0xffffffffUL, BLK_BOUNCE_HIGH) >> PAGE_SHIFT))
dma = 1;
q->bounce_pfn = max_low_pfn;
#else
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 73f36beff5cd..26f9ec28f56c 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -209,14 +209,10 @@ static ssize_t queue_iostats_store(struct request_queue *q, const char *page,
ssize_t ret = queue_var_store(&stats, page, count);
spin_lock_irq(q->queue_lock);
- elv_quisce_start(q);
-
if (stats)
queue_flag_set(QUEUE_FLAG_IO_STAT, q);
else
queue_flag_clear(QUEUE_FLAG_IO_STAT, q);
-
- elv_quisce_end(q);
spin_unlock_irq(q->queue_lock);
return ret;
@@ -387,16 +383,21 @@ struct kobj_type blk_queue_ktype = {
int blk_register_queue(struct gendisk *disk)
{
int ret;
+ struct device *dev = disk_to_dev(disk);
struct request_queue *q = disk->queue;
if (WARN_ON(!q))
return -ENXIO;
+ ret = blk_trace_init_sysfs(dev);
+ if (ret)
+ return ret;
+
if (!q->request_fn)
return 0;
- ret = kobject_add(&q->kobj, kobject_get(&disk_to_dev(disk)->kobj),
+ ret = kobject_add(&q->kobj, kobject_get(&dev->kobj),
"%s", "queue");
if (ret < 0)
return ret;
diff --git a/block/blk-timeout.c b/block/blk-timeout.c
index bbbdc4b8ccf2..1ba7e0aca878 100644
--- a/block/blk-timeout.c
+++ b/block/blk-timeout.c
@@ -122,10 +122,8 @@ void blk_rq_timed_out_timer(unsigned long data)
if (blk_mark_rq_complete(rq))
continue;
blk_rq_timed_out(rq);
- } else {
- if (!next || time_after(next, rq->deadline))
- next = rq->deadline;
- }
+ } else if (!next || time_after(next, rq->deadline))
+ next = rq->deadline;
}
/*
@@ -176,16 +174,14 @@ void blk_add_timer(struct request *req)
BUG_ON(!list_empty(&req->timeout_list));
BUG_ON(test_bit(REQ_ATOM_COMPLETE, &req->atomic_flags));
- if (req->timeout)
- req->deadline = jiffies + req->timeout;
- else {
- req->deadline = jiffies + q->rq_timeout;
- /*
- * Some LLDs, like scsi, peek at the timeout to prevent
- * a command from being retried forever.
- */
+ /*
+ * Some LLDs, like scsi, peek at the timeout to prevent a
+ * command from being retried forever.
+ */
+ if (!req->timeout)
req->timeout = q->rq_timeout;
- }
+
+ req->deadline = jiffies + req->timeout;
list_add_tail(&req->timeout_list, &q->timeout_list);
/*
@@ -211,6 +207,12 @@ void blk_abort_queue(struct request_queue *q)
struct request *rq, *tmp;
LIST_HEAD(list);
+ /*
+ * Not a request based block device, nothing to abort
+ */
+ if (!q->request_fn)
+ return;
+
spin_lock_irqsave(q->queue_lock, flags);
elv_abort_queue(q);
@@ -224,6 +226,13 @@ void blk_abort_queue(struct request_queue *q)
list_for_each_entry_safe(rq, tmp, &list, timeout_list)
blk_abort_request(rq);
+ /*
+ * Occasionally, blk_abort_request() will return without
+ * deleting the element from the list. Make sure we add those back
+ * instead of leaving them on the local stack list.
+ */
+ list_splice(&list, &q->timeout_list);
+
spin_unlock_irqrestore(q->queue_lock, flags);
}
diff --git a/block/blk.h b/block/blk.h
index 24fcaeeaf620..51115599df9b 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -43,6 +43,43 @@ static inline void blk_clear_rq_complete(struct request *rq)
clear_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags);
}
+/*
+ * Internal elevator interface
+ */
+#define ELV_ON_HASH(rq) (!hlist_unhashed(&(rq)->hash))
+
+static inline struct request *__elv_next_request(struct request_queue *q)
+{
+ struct request *rq;
+
+ while (1) {
+ while (!list_empty(&q->queue_head)) {
+ rq = list_entry_rq(q->queue_head.next);
+ if (blk_do_ordered(q, &rq))
+ return rq;
+ }
+
+ if (!q->elevator->ops->elevator_dispatch_fn(q, 0))
+ return NULL;
+ }
+}
+
+static inline void elv_activate_rq(struct request_queue *q, struct request *rq)
+{
+ struct elevator_queue *e = q->elevator;
+
+ if (e->ops->elevator_activate_req_fn)
+ e->ops->elevator_activate_req_fn(q, rq);
+}
+
+static inline void elv_deactivate_rq(struct request_queue *q, struct request *rq)
+{
+ struct elevator_queue *e = q->elevator;
+
+ if (e->ops->elevator_deactivate_req_fn)
+ e->ops->elevator_deactivate_req_fn(q, rq);
+}
+
#ifdef CONFIG_FAIL_IO_TIMEOUT
int blk_should_fake_timeout(struct request_queue *);
ssize_t part_timeout_show(struct device *, struct device_attribute *, char *);
@@ -70,8 +107,8 @@ void blk_queue_congestion_threshold(struct request_queue *q);
int blk_dev_init(void);
-void elv_quisce_start(struct request_queue *q);
-void elv_quisce_end(struct request_queue *q);
+void elv_quiesce_start(struct request_queue *q);
+void elv_quiesce_end(struct request_queue *q);
/*
@@ -112,14 +149,17 @@ static inline int blk_cpu_to_group(int cpu)
#endif
}
+/*
+ * Contribute to IO statistics IFF:
+ *
+ * a) it's attached to a gendisk, and
+ * b) the queue had IO stats enabled when this request was started, and
+ * c) it's a file system request
+ */
static inline int blk_do_io_stat(struct request *rq)
{
- struct gendisk *disk = rq->rq_disk;
-
- if (!disk || !disk->queue)
- return 0;
-
- return blk_queue_io_stat(disk->queue) && (rq->cmd_flags & REQ_ELVPRIV);
+ return rq->rq_disk && blk_rq_io_stat(rq) && blk_fs_request(rq) &&
+ blk_discard_rq(rq);
}
#endif
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index a4809de6fea6..def0c698a4bc 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -56,9 +56,6 @@ static DEFINE_SPINLOCK(ioc_gone_lock);
#define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE)
#define cfq_class_rt(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_RT)
-#define ASYNC (0)
-#define SYNC (1)
-
#define sample_valid(samples) ((samples) > 80)
/*
@@ -83,6 +80,14 @@ struct cfq_data {
* rr list of queues with requests and the count of them
*/
struct cfq_rb_root service_tree;
+
+ /*
+ * Each priority tree is sorted by next_request position. These
+ * trees are used when determining if two or more queues are
+ * interleaving requests (see cfq_close_cooperator).
+ */
+ struct rb_root prio_trees[CFQ_PRIO_LISTS];
+
unsigned int busy_queues;
/*
* Used to track any pending rt requests so we can pre-empt current
@@ -147,6 +152,10 @@ struct cfq_queue {
struct rb_node rb_node;
/* service_tree key */
unsigned long rb_key;
+ /* prio tree member */
+ struct rb_node p_node;
+ /* prio tree root we belong to, if any */
+ struct rb_root *p_root;
/* sorted list of pending requests */
struct rb_root sort_list;
/* if fifo isn't expired, next request to serve */
@@ -185,6 +194,7 @@ enum cfqq_state_flags {
CFQ_CFQQ_FLAG_prio_changed, /* task priority has changed */
CFQ_CFQQ_FLAG_slice_new, /* no requests dispatched in slice */
CFQ_CFQQ_FLAG_sync, /* synchronous queue */
+ CFQ_CFQQ_FLAG_coop, /* has done a coop jump of the queue */
};
#define CFQ_CFQQ_FNS(name) \
@@ -211,6 +221,7 @@ CFQ_CFQQ_FNS(idle_window);
CFQ_CFQQ_FNS(prio_changed);
CFQ_CFQQ_FNS(slice_new);
CFQ_CFQQ_FNS(sync);
+CFQ_CFQQ_FNS(coop);
#undef CFQ_CFQQ_FNS
#define cfq_log_cfqq(cfqd, cfqq, fmt, args...) \
@@ -419,13 +430,17 @@ static struct cfq_queue *cfq_rb_first(struct cfq_rb_root *root)
return NULL;
}
+static void rb_erase_init(struct rb_node *n, struct rb_root *root)
+{
+ rb_erase(n, root);
+ RB_CLEAR_NODE(n);
+}
+
static void cfq_rb_erase(struct rb_node *n, struct cfq_rb_root *root)
{
if (root->left == n)
root->left = NULL;
-
- rb_erase(n, &root->rb);
- RB_CLEAR_NODE(n);
+ rb_erase_init(n, &root->rb);
}
/*
@@ -470,8 +485,8 @@ static unsigned long cfq_slice_offset(struct cfq_data *cfqd,
* requests waiting to be processed. It is sorted in the order that
* we will service the queues.
*/
-static void cfq_service_tree_add(struct cfq_data *cfqd,
- struct cfq_queue *cfqq, int add_front)
+static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq,
+ int add_front)
{
struct rb_node **p, *parent;
struct cfq_queue *__cfqq;
@@ -544,6 +559,67 @@ static void cfq_service_tree_add(struct cfq_data *cfqd,
rb_insert_color(&cfqq->rb_node, &cfqd->service_tree.rb);
}
+static struct cfq_queue *
+cfq_prio_tree_lookup(struct cfq_data *cfqd, struct rb_root *root,
+ sector_t sector, struct rb_node **ret_parent,
+ struct rb_node ***rb_link)
+{
+ struct rb_node **p, *parent;
+ struct cfq_queue *cfqq = NULL;
+
+ parent = NULL;
+ p = &root->rb_node;
+ while (*p) {
+ struct rb_node **n;
+
+ parent = *p;
+ cfqq = rb_entry(parent, struct cfq_queue, p_node);
+
+ /*
+ * Sort strictly based on sector. Smallest to the left,
+ * largest to the right.
+ */
+ if (sector > cfqq->next_rq->sector)
+ n = &(*p)->rb_right;
+ else if (sector < cfqq->next_rq->sector)
+ n = &(*p)->rb_left;
+ else
+ break;
+ p = n;
+ cfqq = NULL;
+ }
+
+ *ret_parent = parent;
+ if (rb_link)
+ *rb_link = p;
+ return cfqq;
+}
+
+static void cfq_prio_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+{
+ struct rb_node **p, *parent;
+ struct cfq_queue *__cfqq;
+
+ if (cfqq->p_root) {
+ rb_erase(&cfqq->p_node, cfqq->p_root);
+ cfqq->p_root = NULL;
+ }
+
+ if (cfq_class_idle(cfqq))
+ return;
+ if (!cfqq->next_rq)
+ return;
+
+ cfqq->p_root = &cfqd->prio_trees[cfqq->org_ioprio];
+ __cfqq = cfq_prio_tree_lookup(cfqd, cfqq->p_root, cfqq->next_rq->sector,
+ &parent, &p);
+ if (!__cfqq) {
+ rb_link_node(&cfqq->p_node, parent, p);
+ rb_insert_color(&cfqq->p_node, cfqq->p_root);
+ } else
+ cfqq->p_root = NULL;
+}
+
/*
* Update cfqq's position in the service tree.
*/
@@ -552,8 +628,10 @@ static void cfq_resort_rr_list(struct cfq_data *cfqd, struct cfq_queue *cfqq)
/*
* Resorting requires the cfqq to be on the RR list already.
*/
- if (cfq_cfqq_on_rr(cfqq))
+ if (cfq_cfqq_on_rr(cfqq)) {
cfq_service_tree_add(cfqd, cfqq, 0);
+ cfq_prio_tree_add(cfqd, cfqq);
+ }
}
/*
@@ -584,6 +662,10 @@ static void cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
if (!RB_EMPTY_NODE(&cfqq->rb_node))
cfq_rb_erase(&cfqq->rb_node, &cfqd->service_tree);
+ if (cfqq->p_root) {
+ rb_erase(&cfqq->p_node, cfqq->p_root);
+ cfqq->p_root = NULL;
+ }
BUG_ON(!cfqd->busy_queues);
cfqd->busy_queues--;
@@ -613,7 +695,7 @@ static void cfq_add_rq_rb(struct request *rq)
{
struct cfq_queue *cfqq = RQ_CFQQ(rq);
struct cfq_data *cfqd = cfqq->cfqd;
- struct request *__alias;
+ struct request *__alias, *prev;
cfqq->queued[rq_is_sync(rq)]++;
@@ -630,7 +712,15 @@ static void cfq_add_rq_rb(struct request *rq)
/*
* check if this request is a better next-serve candidate
*/
+ prev = cfqq->next_rq;
cfqq->next_rq = cfq_choose_req(cfqd, cfqq->next_rq, rq);
+
+ /*
+ * adjust priority tree position, if ->next_rq changes
+ */
+ if (prev != cfqq->next_rq)
+ cfq_prio_tree_add(cfqd, cfqq);
+
BUG_ON(!cfqq->next_rq);
}
@@ -843,11 +933,15 @@ static struct cfq_queue *cfq_get_next_queue(struct cfq_data *cfqd)
/*
* Get and set a new active queue for service.
*/
-static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd)
+static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd,
+ struct cfq_queue *cfqq)
{
- struct cfq_queue *cfqq;
+ if (!cfqq) {
+ cfqq = cfq_get_next_queue(cfqd);
+ if (cfqq)
+ cfq_clear_cfqq_coop(cfqq);
+ }
- cfqq = cfq_get_next_queue(cfqd);
__cfq_set_active_queue(cfqd, cfqq);
return cfqq;
}
@@ -861,28 +955,100 @@ static inline sector_t cfq_dist_from_last(struct cfq_data *cfqd,
return cfqd->last_position - rq->sector;
}
+#define CIC_SEEK_THR 8 * 1024
+#define CIC_SEEKY(cic) ((cic)->seek_mean > CIC_SEEK_THR)
+
static inline int cfq_rq_close(struct cfq_data *cfqd, struct request *rq)
{
struct cfq_io_context *cic = cfqd->active_cic;
+ sector_t sdist = cic->seek_mean;
if (!sample_valid(cic->seek_samples))
- return 0;
+ sdist = CIC_SEEK_THR;
+
+ return cfq_dist_from_last(cfqd, rq) <= sdist;
+}
+
+static struct cfq_queue *cfqq_close(struct cfq_data *cfqd,
+ struct cfq_queue *cur_cfqq)
+{
+ struct rb_root *root = &cfqd->prio_trees[cur_cfqq->org_ioprio];
+ struct rb_node *parent, *node;
+ struct cfq_queue *__cfqq;
+ sector_t sector = cfqd->last_position;
+
+ if (RB_EMPTY_ROOT(root))
+ return NULL;
+
+ /*
+ * First, if we find a request starting at the end of the last
+ * request, choose it.
+ */
+ __cfqq = cfq_prio_tree_lookup(cfqd, root, sector, &parent, NULL);
+ if (__cfqq)
+ return __cfqq;
+
+ /*
+ * If the exact sector wasn't found, the parent of the NULL leaf
+ * will contain the closest sector.
+ */
+ __cfqq = rb_entry(parent, struct cfq_queue, p_node);
+ if (cfq_rq_close(cfqd, __cfqq->next_rq))
+ return __cfqq;
+
+ if (__cfqq->next_rq->sector < sector)
+ node = rb_next(&__cfqq->p_node);
+ else
+ node = rb_prev(&__cfqq->p_node);
+ if (!node)
+ return NULL;
- return cfq_dist_from_last(cfqd, rq) <= cic->seek_mean;
+ __cfqq = rb_entry(node, struct cfq_queue, p_node);
+ if (cfq_rq_close(cfqd, __cfqq->next_rq))
+ return __cfqq;
+
+ return NULL;
}
-static int cfq_close_cooperator(struct cfq_data *cfq_data,
- struct cfq_queue *cfqq)
+/*
+ * cfqd - obvious
+ * cur_cfqq - passed in so that we don't decide that the current queue is
+ * closely cooperating with itself.
+ *
+ * So, basically we're assuming that that cur_cfqq has dispatched at least
+ * one request, and that cfqd->last_position reflects a position on the disk
+ * associated with the I/O issued by cur_cfqq. I'm not sure this is a valid
+ * assumption.
+ */
+static struct cfq_queue *cfq_close_cooperator(struct cfq_data *cfqd,
+ struct cfq_queue *cur_cfqq,
+ int probe)
{
+ struct cfq_queue *cfqq;
+
+ /*
+ * A valid cfq_io_context is necessary to compare requests against
+ * the seek_mean of the current cfqq.
+ */
+ if (!cfqd->active_cic)
+ return NULL;
+
/*
* We should notice if some of the queues are cooperating, eg
* working closely on the same area of the disk. In that case,
* we can group them together and don't waste time idling.
*/
- return 0;
-}
+ cfqq = cfqq_close(cfqd, cur_cfqq);
+ if (!cfqq)
+ return NULL;
-#define CIC_SEEKY(cic) ((cic)->seek_mean > (8 * 1024))
+ if (cfq_cfqq_coop(cfqq))
+ return NULL;
+
+ if (!probe)
+ cfq_mark_cfqq_coop(cfqq);
+ return cfqq;
+}
static void cfq_arm_slice_timer(struct cfq_data *cfqd)
{
@@ -920,13 +1086,6 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
if (!cic || !atomic_read(&cic->ioc->nr_tasks))
return;
- /*
- * See if this prio level has a good candidate
- */
- if (cfq_close_cooperator(cfqd, cfqq) &&
- (sample_valid(cic->ttime_samples) && cic->ttime_mean > 2))
- return;
-
cfq_mark_cfqq_wait_request(cfqq);
/*
@@ -939,7 +1098,7 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
sl = min(sl, msecs_to_jiffies(CFQ_MIN_TT));
mod_timer(&cfqd->idle_slice_timer, jiffies + sl);
- cfq_log(cfqd, "arm_idle: %lu", sl);
+ cfq_log_cfqq(cfqd, cfqq, "arm_idle: %lu", sl);
}
/*
@@ -1003,7 +1162,7 @@ cfq_prio_to_maxrq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
*/
static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd)
{
- struct cfq_queue *cfqq;
+ struct cfq_queue *cfqq, *new_cfqq = NULL;
cfqq = cfqd->active_queue;
if (!cfqq)
@@ -1037,6 +1196,16 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd)
goto keep_queue;
/*
+ * If another queue has a request waiting within our mean seek
+ * distance, let it run. The expire code will check for close
+ * cooperators and put the close queue at the front of the service
+ * tree.
+ */
+ new_cfqq = cfq_close_cooperator(cfqd, cfqq, 0);
+ if (new_cfqq)
+ goto expire;
+
+ /*
* No requests pending. If the active queue still has requests in
* flight or is idling for a new request, allow either of these
* conditions to happen (or time out) before selecting a new queue.
@@ -1050,7 +1219,7 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd)
expire:
cfq_slice_expired(cfqd, 0);
new_queue:
- cfqq = cfq_set_active_queue(cfqd);
+ cfqq = cfq_set_active_queue(cfqd, new_cfqq);
keep_queue:
return cfqq;
}
@@ -1333,14 +1502,14 @@ static void __cfq_exit_single_io_context(struct cfq_data *cfqd,
if (ioc->ioc_data == cic)
rcu_assign_pointer(ioc->ioc_data, NULL);
- if (cic->cfqq[ASYNC]) {
- cfq_exit_cfqq(cfqd, cic->cfqq[ASYNC]);
- cic->cfqq[ASYNC] = NULL;
+ if (cic->cfqq[BLK_RW_ASYNC]) {
+ cfq_exit_cfqq(cfqd, cic->cfqq[BLK_RW_ASYNC]);
+ cic->cfqq[BLK_RW_ASYNC] = NULL;
}
- if (cic->cfqq[SYNC]) {
- cfq_exit_cfqq(cfqd, cic->cfqq[SYNC]);
- cic->cfqq[SYNC] = NULL;
+ if (cic->cfqq[BLK_RW_SYNC]) {
+ cfq_exit_cfqq(cfqd, cic->cfqq[BLK_RW_SYNC]);
+ cic->cfqq[BLK_RW_SYNC] = NULL;
}
}
@@ -1449,17 +1618,18 @@ static void changed_ioprio(struct io_context *ioc, struct cfq_io_context *cic)
spin_lock_irqsave(cfqd->queue->queue_lock, flags);
- cfqq = cic->cfqq[ASYNC];
+ cfqq = cic->cfqq[BLK_RW_ASYNC];
if (cfqq) {
struct cfq_queue *new_cfqq;
- new_cfqq = cfq_get_queue(cfqd, ASYNC, cic->ioc, GFP_ATOMIC);
+ new_cfqq = cfq_get_queue(cfqd, BLK_RW_ASYNC, cic->ioc,
+ GFP_ATOMIC);
if (new_cfqq) {
- cic->cfqq[ASYNC] = new_cfqq;
+ cic->cfqq[BLK_RW_ASYNC] = new_cfqq;
cfq_put_queue(cfqq);
}
}
- cfqq = cic->cfqq[SYNC];
+ cfqq = cic->cfqq[BLK_RW_SYNC];
if (cfqq)
cfq_mark_cfqq_prio_changed(cfqq);
@@ -1510,6 +1680,7 @@ retry:
}
RB_CLEAR_NODE(&cfqq->rb_node);
+ RB_CLEAR_NODE(&cfqq->p_node);
INIT_LIST_HEAD(&cfqq->fifo);
atomic_set(&cfqq->ref, 0);
@@ -1745,7 +1916,9 @@ cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_io_context *cic,
sector_t sdist;
u64 total;
- if (cic->last_request_pos < rq->sector)
+ if (!cic->last_request_pos)
+ sdist = 0;
+ else if (cic->last_request_pos < rq->sector)
sdist = rq->sector - cic->last_request_pos;
else
sdist = cic->last_request_pos - rq->sector;
@@ -1905,10 +2078,20 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
* Remember that we saw a request from this process, but
* don't start queuing just yet. Otherwise we risk seeing lots
* of tiny requests, because we disrupt the normal plugging
- * and merging.
+ * and merging. If the request is already larger than a single
+ * page, let it rip immediately. For that case we assume that
+ * merging is already done. Ditto for a busy system that
+ * has other work pending, don't risk delaying until the
+ * idle timer unplug to continue working.
*/
- if (cfq_cfqq_wait_request(cfqq))
+ if (cfq_cfqq_wait_request(cfqq)) {
+ if (blk_rq_bytes(rq) > PAGE_CACHE_SIZE ||
+ cfqd->busy_queues > 1) {
+ del_timer(&cfqd->idle_slice_timer);
+ __blk_run_queue(cfqd->queue);
+ }
cfq_mark_cfqq_must_dispatch(cfqq);
+ }
} else if (cfq_should_preempt(cfqd, cfqq, rq)) {
/*
* not the active queue - expire current slice if it is
@@ -1917,7 +2100,7 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
* this new queue is RT and the current one is BE
*/
cfq_preempt_queue(cfqd, cfqq);
- blk_start_queueing(cfqd->queue);
+ __blk_run_queue(cfqd->queue);
}
}
@@ -1992,16 +2175,24 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
* or if we want to idle in case it has no pending requests.
*/
if (cfqd->active_queue == cfqq) {
+ const bool cfqq_empty = RB_EMPTY_ROOT(&cfqq->sort_list);
+
if (cfq_cfqq_slice_new(cfqq)) {
cfq_set_prio_slice(cfqd, cfqq);
cfq_clear_cfqq_slice_new(cfqq);
}
+ /*
+ * If there are no requests waiting in this queue, and
+ * there are other queues ready to issue requests, AND
+ * those other queues are issuing requests within our
+ * mean seek distance, give them a chance to run instead
+ * of idling.
+ */
if (cfq_slice_used(cfqq) || cfq_class_idle(cfqq))
cfq_slice_expired(cfqd, 1);
- else if (sync && !rq_noidle(rq) &&
- RB_EMPTY_ROOT(&cfqq->sort_list)) {
+ else if (cfqq_empty && !cfq_close_cooperator(cfqd, cfqq, 1) &&
+ sync && !rq_noidle(rq))
cfq_arm_slice_timer(cfqd);
- }
}
if (!cfqd->rq_in_driver)
@@ -2062,7 +2253,7 @@ static int cfq_may_queue(struct request_queue *q, int rw)
if (!cic)
return ELV_MQUEUE_MAY;
- cfqq = cic_to_cfqq(cic, rw & REQ_RW_SYNC);
+ cfqq = cic_to_cfqq(cic, rw_is_sync(rw));
if (cfqq) {
cfq_init_prio_data(cfqq, cic->ioc);
cfq_prio_boost(cfqq);
@@ -2152,11 +2343,10 @@ static void cfq_kick_queue(struct work_struct *work)
struct cfq_data *cfqd =
container_of(work, struct cfq_data, unplug_work);
struct request_queue *q = cfqd->queue;
- unsigned long flags;
- spin_lock_irqsave(q->queue_lock, flags);
- blk_start_queueing(q);
- spin_unlock_irqrestore(q->queue_lock, flags);
+ spin_lock_irq(q->queue_lock);
+ __blk_run_queue(cfqd->queue);
+ spin_unlock_irq(q->queue_lock);
}
/*
@@ -2263,12 +2453,22 @@ static void cfq_exit_queue(struct elevator_queue *e)
static void *cfq_init_queue(struct request_queue *q)
{
struct cfq_data *cfqd;
+ int i;
cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL | __GFP_ZERO, q->node);
if (!cfqd)
return NULL;
cfqd->service_tree = CFQ_RB_ROOT;
+
+ /*
+ * Not strictly needed (since RB_ROOT just clears the node and we
+ * zeroed cfqd on alloc), but better be safe in case someone decides
+ * to add magic to the rb code
+ */
+ for (i = 0; i < CFQ_PRIO_LISTS; i++)
+ cfqd->prio_trees[i] = RB_ROOT;
+
INIT_LIST_HEAD(&cfqd->cic_list);
cfqd->queue = q;
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index f87615dea46b..f8c218cd08e1 100644
--- a/block/compat_ioctl.c
+++ b/block/compat_ioctl.c
@@ -568,7 +568,7 @@ static int compat_blk_trace_setup(struct block_device *bdev, char __user *arg)
memcpy(&buts.name, &cbuts.name, 32);
mutex_lock(&bdev->bd_mutex);
- ret = do_blk_trace_setup(q, b, bdev->bd_dev, &buts);
+ ret = do_blk_trace_setup(q, b, bdev->bd_dev, bdev, &buts);
mutex_unlock(&bdev->bd_mutex);
if (ret)
return ret;
diff --git a/block/elevator.c b/block/elevator.c
index fb81bcc14a8c..1af5d9f04aff 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -53,7 +53,6 @@ static const int elv_hash_shift = 6;
(hash_long(ELV_HASH_BLOCK((sec)), elv_hash_shift))
#define ELV_HASH_ENTRIES (1 << elv_hash_shift)
#define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors)
-#define ELV_ON_HASH(rq) (!hlist_unhashed(&(rq)->hash))
DEFINE_TRACE(block_rq_insert);
DEFINE_TRACE(block_rq_issue);
@@ -310,22 +309,6 @@ void elevator_exit(struct elevator_queue *e)
}
EXPORT_SYMBOL(elevator_exit);
-static void elv_activate_rq(struct request_queue *q, struct request *rq)
-{
- struct elevator_queue *e = q->elevator;
-
- if (e->ops->elevator_activate_req_fn)
- e->ops->elevator_activate_req_fn(q, rq);
-}
-
-static void elv_deactivate_rq(struct request_queue *q, struct request *rq)
-{
- struct elevator_queue *e = q->elevator;
-
- if (e->ops->elevator_deactivate_req_fn)
- e->ops->elevator_deactivate_req_fn(q, rq);
-}
-
static inline void __elv_rqhash_del(struct request *rq)
{
hlist_del_init(&rq->hash);
@@ -590,7 +573,7 @@ void elv_drain_elevator(struct request_queue *q)
/*
* Call with queue lock held, interrupts disabled
*/
-void elv_quisce_start(struct request_queue *q)
+void elv_quiesce_start(struct request_queue *q)
{
queue_flag_set(QUEUE_FLAG_ELVSWITCH, q);
@@ -599,7 +582,7 @@ void elv_quisce_start(struct request_queue *q)
*/
elv_drain_elevator(q);
while (q->rq.elvpriv) {
- blk_start_queueing(q);
+ __blk_run_queue(q);
spin_unlock_irq(q->queue_lock);
msleep(10);
spin_lock_irq(q->queue_lock);
@@ -607,7 +590,7 @@ void elv_quisce_start(struct request_queue *q)
}
}
-void elv_quisce_end(struct request_queue *q)
+void elv_quiesce_end(struct request_queue *q)
{
queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
}
@@ -643,8 +626,7 @@ void elv_insert(struct request_queue *q, struct request *rq, int where)
* with anything. There's no point in delaying queue
* processing.
*/
- blk_remove_plug(q);
- blk_start_queueing(q);
+ __blk_run_queue(q);
break;
case ELEVATOR_INSERT_SORT:
@@ -759,117 +741,6 @@ void elv_add_request(struct request_queue *q, struct request *rq, int where,
}
EXPORT_SYMBOL(elv_add_request);
-static inline struct request *__elv_next_request(struct request_queue *q)
-{
- struct request *rq;
-
- while (1) {
- while (!list_empty(&q->queue_head)) {
- rq = list_entry_rq(q->queue_head.next);
- if (blk_do_ordered(q, &rq))
- return rq;
- }
-
- if (!q->elevator->ops->elevator_dispatch_fn(q, 0))
- return NULL;
- }
-}
-
-struct request *elv_next_request(struct request_queue *q)
-{
- struct request *rq;
- int ret;
-
- while ((rq = __elv_next_request(q)) != NULL) {
- if (!(rq->cmd_flags & REQ_STARTED)) {
- /*
- * This is the first time the device driver
- * sees this request (possibly after
- * requeueing). Notify IO scheduler.
- */
- if (blk_sorted_rq(rq))
- elv_activate_rq(q, rq);
-
- /*
- * just mark as started even if we don't start
- * it, a request that has been delayed should
- * not be passed by new incoming requests
- */
- rq->cmd_flags |= REQ_STARTED;
- trace_block_rq_issue(q, rq);
- }
-
- if (!q->boundary_rq || q->boundary_rq == rq) {
- q->end_sector = rq_end_sector(rq);
- q->boundary_rq = NULL;
- }
-
- if (rq->cmd_flags & REQ_DONTPREP)
- break;
-
- if (q->dma_drain_size && rq->data_len) {
- /*
- * make sure space for the drain appears we
- * know we can do this because max_hw_segments
- * has been adjusted to be one fewer than the
- * device can handle
- */
- rq->nr_phys_segments++;
- }
-
- if (!q->prep_rq_fn)
- break;
-
- ret = q->prep_rq_fn(q, rq);
- if (ret == BLKPREP_OK) {
- break;
- } else if (ret == BLKPREP_DEFER) {
- /*
- * the request may have been (partially) prepped.
- * we need to keep this request in the front to
- * avoid resource deadlock. REQ_STARTED will
- * prevent other fs requests from passing this one.
- */
- if (q->dma_drain_size && rq->data_len &&
- !(rq->cmd_flags & REQ_DONTPREP)) {
- /*
- * remove the space for the drain we added
- * so that we don't add it again
- */
- --rq->nr_phys_segments;
- }
-
- rq = NULL;
- break;
- } else if (ret == BLKPREP_KILL) {
- rq->cmd_flags |= REQ_QUIET;
- __blk_end_request(rq, -EIO, blk_rq_bytes(rq));
- } else {
- printk(KERN_ERR "%s: bad return=%d\n", __func__, ret);
- break;
- }
- }
-
- return rq;
-}
-EXPORT_SYMBOL(elv_next_request);
-
-void elv_dequeue_request(struct request_queue *q, struct request *rq)
-{
- BUG_ON(list_empty(&rq->queuelist));
- BUG_ON(ELV_ON_HASH(rq));
-
- list_del_init(&rq->queuelist);
-
- /*
- * the time frame between a request being removed from the lists
- * and to it is freed is accounted as io that is in progress at
- * the driver side.
- */
- if (blk_account_rq(rq))
- q->in_flight++;
-}
-
int elv_queue_empty(struct request_queue *q)
{
struct elevator_queue *e = q->elevator;
@@ -939,7 +810,7 @@ void elv_abort_queue(struct request_queue *q)
rq = list_entry_rq(q->queue_head.next);
rq->cmd_flags |= REQ_QUIET;
trace_block_rq_abort(q, rq);
- __blk_end_request(rq, -EIO, blk_rq_bytes(rq));
+ __blk_end_request_all(rq, -EIO);
}
}
EXPORT_SYMBOL(elv_abort_queue);
@@ -971,7 +842,7 @@ void elv_completed_request(struct request_queue *q, struct request *rq)
blk_ordered_cur_seq(q) == QUEUE_ORDSEQ_DRAIN &&
(!next || blk_ordered_req_seq(next) > QUEUE_ORDSEQ_DRAIN)) {
blk_ordered_complete_seq(q, QUEUE_ORDSEQ_DRAIN, 0);
- blk_start_queueing(q);
+ __blk_run_queue(q);
}
}
}
@@ -1126,7 +997,7 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
* Turn on BYPASS and drain all requests w/ elevator private data
*/
spin_lock_irq(q->queue_lock);
- elv_quisce_start(q);
+ elv_quiesce_start(q);
/*
* Remember old elevator.
@@ -1150,7 +1021,7 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
*/
elevator_exit(old_elevator);
spin_lock_irq(q->queue_lock);
- elv_quisce_end(q);
+ elv_quiesce_end(q);
spin_unlock_irq(q->queue_lock);
blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name);
diff --git a/block/genhd.c b/block/genhd.c
index a9ec910974c1..1a4916e01732 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -98,7 +98,7 @@ void disk_part_iter_init(struct disk_part_iter *piter, struct gendisk *disk,
if (flags & DISK_PITER_REVERSE)
piter->idx = ptbl->len - 1;
- else if (flags & DISK_PITER_INCL_PART0)
+ else if (flags & (DISK_PITER_INCL_PART0 | DISK_PITER_INCL_EMPTY_PART0))
piter->idx = 0;
else
piter->idx = 1;
@@ -134,7 +134,8 @@ struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter)
/* determine iteration parameters */
if (piter->flags & DISK_PITER_REVERSE) {
inc = -1;
- if (piter->flags & DISK_PITER_INCL_PART0)
+ if (piter->flags & (DISK_PITER_INCL_PART0 |
+ DISK_PITER_INCL_EMPTY_PART0))
end = -1;
else
end = 0;
@@ -150,7 +151,10 @@ struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter)
part = rcu_dereference(ptbl->part[piter->idx]);
if (!part)
continue;
- if (!(piter->flags & DISK_PITER_INCL_EMPTY) && !part->nr_sects)
+ if (!part->nr_sects &&
+ !(piter->flags & DISK_PITER_INCL_EMPTY) &&
+ !(piter->flags & DISK_PITER_INCL_EMPTY_PART0 &&
+ piter->idx == 0))
continue;
get_device(part_to_dev(part));
@@ -1011,7 +1015,7 @@ static int diskstats_show(struct seq_file *seqf, void *v)
"\n\n");
*/
- disk_part_iter_init(&piter, gp, DISK_PITER_INCL_PART0);
+ disk_part_iter_init(&piter, gp, DISK_PITER_INCL_EMPTY_PART0);
while ((hd = disk_part_iter_next(&piter))) {
cpu = part_stat_lock();
part_round_stats(cpu, hd);
diff --git a/block/ioctl.c b/block/ioctl.c
index 0f22e629b13c..ad474d4bbcce 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -146,8 +146,6 @@ static int blk_ioctl_discard(struct block_device *bdev, uint64_t start,
struct bio *bio;
bio = bio_alloc(GFP_KERNEL, 0);
- if (!bio)
- return -ENOMEM;
bio->bi_end_io = blk_ioc_discard_endio;
bio->bi_bdev = bdev;
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 626ee274c5c4..58cf4560f742 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -217,7 +217,7 @@ static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
struct bio *bio)
{
- int ret = 0;
+ int r, ret = 0;
/*
* fill in all the output members
@@ -242,7 +242,9 @@ static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
ret = -EFAULT;
}
- blk_rq_unmap_user(bio);
+ r = blk_rq_unmap_user(bio);
+ if (!ret)
+ ret = r;
blk_put_request(rq);
return ret;
@@ -288,6 +290,7 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
if (hdr->iovec_count) {
const int size = sizeof(struct sg_iovec) * hdr->iovec_count;
+ size_t iov_data_len;
struct sg_iovec *iov;
iov = kmalloc(size, GFP_KERNEL);
@@ -302,8 +305,18 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
goto out;
}
+ /* SG_IO howto says that the shorter of the two wins */
+ iov_data_len = iov_length((struct iovec *)iov,
+ hdr->iovec_count);
+ if (hdr->dxfer_len < iov_data_len) {
+ hdr->iovec_count = iov_shorten((struct iovec *)iov,
+ hdr->iovec_count,
+ hdr->dxfer_len);
+ iov_data_len = hdr->dxfer_len;
+ }
+
ret = blk_rq_map_user_iov(q, rq, NULL, iov, hdr->iovec_count,
- hdr->dxfer_len, GFP_KERNEL);
+ iov_data_len, GFP_KERNEL);
kfree(iov);
} else if (hdr->dxfer_len)
ret = blk_rq_map_user(q, rq, NULL, hdr->dxferp, hdr->dxfer_len,
@@ -487,9 +500,6 @@ static int __blk_send_generic(struct request_queue *q, struct gendisk *bd_disk,
rq = blk_get_request(q, WRITE, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_BLOCK_PC;
- rq->data = NULL;
- rq->data_len = 0;
- rq->extra_len = 0;
rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
rq->cmd[0] = cmd;
rq->cmd[4] = data;
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 74d0e622a515..4dfdd03e708f 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -241,6 +241,11 @@ config CRYPTO_XTS
key size 256, 384 or 512 bits. This implementation currently
can't handle a sectorsize which is not a multiple of 16 bytes.
+config CRYPTO_FPU
+ tristate
+ select CRYPTO_BLKCIPHER
+ select CRYPTO_MANAGER
+
comment "Hash modes"
config CRYPTO_HMAC
@@ -486,6 +491,7 @@ config CRYPTO_AES_NI_INTEL
select CRYPTO_AES_X86_64
select CRYPTO_CRYPTD
select CRYPTO_ALGAPI
+ select CRYPTO_FPU
help
Use Intel AES-NI instructions for AES algorithm.
@@ -505,6 +511,10 @@ config CRYPTO_AES_NI_INTEL
See <http://csrc.nist.gov/encryption/aes/> for more information.
+ In addition to AES cipher algorithm support, the
+ acceleration for some popular block cipher mode is supported
+ too, including ECB, CBC, CTR, LRW, PCBC, XTS.
+
config CRYPTO_ANUBIS
tristate "Anubis cipher algorithm"
select CRYPTO_ALGAPI
diff --git a/crypto/algboss.c b/crypto/algboss.c
index 6906f92aeac0..9908dd830c26 100644
--- a/crypto/algboss.c
+++ b/crypto/algboss.c
@@ -280,29 +280,13 @@ static struct notifier_block cryptomgr_notifier = {
static int __init cryptomgr_init(void)
{
- int err;
-
- err = testmgr_init();
- if (err)
- return err;
-
- err = crypto_register_notifier(&cryptomgr_notifier);
- if (err)
- goto free_testmgr;
-
- return 0;
-
-free_testmgr:
- testmgr_exit();
- return err;
+ return crypto_register_notifier(&cryptomgr_notifier);
}
static void __exit cryptomgr_exit(void)
{
int err = crypto_unregister_notifier(&cryptomgr_notifier);
BUG_ON(err);
-
- testmgr_exit();
}
subsys_initcall(cryptomgr_init);
diff --git a/crypto/api.c b/crypto/api.c
index 314dab96840e..f500fb840be9 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -221,7 +221,8 @@ struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask)
request_module(name);
- if (!((type ^ CRYPTO_ALG_NEED_FALLBACK) & mask) &&
+ if (!((type ^ CRYPTO_ALG_NEED_FALLBACK) & mask &
+ CRYPTO_ALG_NEED_FALLBACK) &&
snprintf(tmp, sizeof(tmp), "%s-all", name) < sizeof(tmp))
request_module(tmp);
@@ -579,20 +580,17 @@ EXPORT_SYMBOL_GPL(crypto_alloc_tfm);
void crypto_destroy_tfm(void *mem, struct crypto_tfm *tfm)
{
struct crypto_alg *alg;
- int size;
if (unlikely(!mem))
return;
alg = tfm->__crt_alg;
- size = ksize(mem);
if (!tfm->exit && alg->cra_exit)
alg->cra_exit(tfm);
crypto_exit_ops(tfm);
crypto_mod_put(alg);
- memset(mem, 0, size);
- kfree(mem);
+ kzfree(mem);
}
EXPORT_SYMBOL_GPL(crypto_destroy_tfm);
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
index d14b22658d7a..ae5fa99d5d36 100644
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -586,20 +586,24 @@ struct cryptd_ablkcipher *cryptd_alloc_ablkcipher(const char *alg_name,
u32 type, u32 mask)
{
char cryptd_alg_name[CRYPTO_MAX_ALG_NAME];
- struct crypto_ablkcipher *tfm;
+ struct crypto_tfm *tfm;
if (snprintf(cryptd_alg_name, CRYPTO_MAX_ALG_NAME,
"cryptd(%s)", alg_name) >= CRYPTO_MAX_ALG_NAME)
return ERR_PTR(-EINVAL);
- tfm = crypto_alloc_ablkcipher(cryptd_alg_name, type, mask);
+ type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
+ type |= CRYPTO_ALG_TYPE_BLKCIPHER;
+ mask &= ~CRYPTO_ALG_TYPE_MASK;
+ mask |= (CRYPTO_ALG_GENIV | CRYPTO_ALG_TYPE_BLKCIPHER_MASK);
+ tfm = crypto_alloc_base(cryptd_alg_name, type, mask);
if (IS_ERR(tfm))
return ERR_CAST(tfm);
- if (crypto_ablkcipher_tfm(tfm)->__crt_alg->cra_module != THIS_MODULE) {
- crypto_free_ablkcipher(tfm);
+ if (tfm->__crt_alg->cra_module != THIS_MODULE) {
+ crypto_free_tfm(tfm);
return ERR_PTR(-EINVAL);
}
- return __cryptd_ablkcipher_cast(tfm);
+ return __cryptd_ablkcipher_cast(__crypto_ablkcipher_cast(tfm));
}
EXPORT_SYMBOL_GPL(cryptd_alloc_ablkcipher);
diff --git a/crypto/eseqiv.c b/crypto/eseqiv.c
index 2a342c8e52b3..3ca3b669d5d5 100644
--- a/crypto/eseqiv.c
+++ b/crypto/eseqiv.c
@@ -153,7 +153,8 @@ static int eseqiv_givencrypt(struct skcipher_givcrypt_request *req)
if (err)
goto out;
- eseqiv_complete2(req);
+ if (giv != req->giv)
+ eseqiv_complete2(req);
out:
return err;
diff --git a/crypto/internal.h b/crypto/internal.h
index fc76e1f37fc3..113579a82dff 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -121,9 +121,6 @@ int crypto_register_notifier(struct notifier_block *nb);
int crypto_unregister_notifier(struct notifier_block *nb);
int crypto_probing_notify(unsigned long val, void *v);
-int __init testmgr_init(void);
-void testmgr_exit(void);
-
static inline void crypto_alg_put(struct crypto_alg *alg)
{
if (atomic_dec_and_test(&alg->cra_refcnt) && alg->cra_destroy)
diff --git a/crypto/pcompress.c b/crypto/pcompress.c
index ca9a4af91efe..bcadc03726b7 100644
--- a/crypto/pcompress.c
+++ b/crypto/pcompress.c
@@ -26,6 +26,7 @@
#include <linux/string.h>
#include <crypto/compress.h>
+#include <crypto/internal/compress.h>
#include "internal.h"
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index c3c9124209a1..9e4974eb7825 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -396,16 +396,16 @@ static void test_hash_speed(const char *algo, unsigned int sec,
struct scatterlist sg[TVMEMSIZE];
struct crypto_hash *tfm;
struct hash_desc desc;
- char output[1024];
+ static char output[1024];
int i;
int ret;
- printk("\ntesting speed of %s\n", algo);
+ printk(KERN_INFO "\ntesting speed of %s\n", algo);
tfm = crypto_alloc_hash(algo, 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm)) {
- printk("failed to load transform for %s: %ld\n", algo,
+ printk(KERN_ERR "failed to load transform for %s: %ld\n", algo,
PTR_ERR(tfm));
return;
}
@@ -414,7 +414,7 @@ static void test_hash_speed(const char *algo, unsigned int sec,
desc.flags = 0;
if (crypto_hash_digestsize(tfm) > sizeof(output)) {
- printk("digestsize(%u) > outputbuffer(%zu)\n",
+ printk(KERN_ERR "digestsize(%u) > outputbuffer(%zu)\n",
crypto_hash_digestsize(tfm), sizeof(output));
goto out;
}
@@ -427,12 +427,14 @@ static void test_hash_speed(const char *algo, unsigned int sec,
for (i = 0; speed[i].blen != 0; i++) {
if (speed[i].blen > TVMEMSIZE * PAGE_SIZE) {
- printk("template (%u) too big for tvmem (%lu)\n",
+ printk(KERN_ERR
+ "template (%u) too big for tvmem (%lu)\n",
speed[i].blen, TVMEMSIZE * PAGE_SIZE);
goto out;
}
- printk("test%3u (%5u byte blocks,%5u bytes per update,%4u updates): ",
+ printk(KERN_INFO "test%3u "
+ "(%5u byte blocks,%5u bytes per update,%4u updates): ",
i, speed[i].blen, speed[i].plen, speed[i].blen / speed[i].plen);
if (sec)
@@ -443,7 +445,7 @@ static void test_hash_speed(const char *algo, unsigned int sec,
speed[i].plen, output);
if (ret) {
- printk("hashing failed ret=%d\n", ret);
+ printk(KERN_ERR "hashing failed ret=%d\n", ret);
break;
}
}
@@ -524,6 +526,7 @@ static void do_test(int m)
tcrypt_test("cbc(aes)");
tcrypt_test("lrw(aes)");
tcrypt_test("xts(aes)");
+ tcrypt_test("ctr(aes)");
tcrypt_test("rfc3686(ctr(aes))");
break;
@@ -665,6 +668,10 @@ static void do_test(int m)
tcrypt_test("zlib");
break;
+ case 45:
+ tcrypt_test("rfc4309(ccm(aes))");
+ break;
+
case 100:
tcrypt_test("hmac(md5)");
break;
@@ -701,6 +708,10 @@ static void do_test(int m)
tcrypt_test("hmac(rmd160)");
break;
+ case 150:
+ tcrypt_test("ansi_cprng");
+ break;
+
case 200:
test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0,
speed_template_16_24_32);
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index b50c3c6b17a2..f4cc1780aee2 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -19,6 +19,7 @@
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <crypto/rng.h>
#include "internal.h"
#include "testmgr.h"
@@ -84,6 +85,11 @@ struct hash_test_suite {
unsigned int count;
};
+struct cprng_test_suite {
+ struct cprng_testvec *vecs;
+ unsigned int count;
+};
+
struct alg_test_desc {
const char *alg;
int (*test)(const struct alg_test_desc *desc, const char *driver,
@@ -95,14 +101,12 @@ struct alg_test_desc {
struct comp_test_suite comp;
struct pcomp_test_suite pcomp;
struct hash_test_suite hash;
+ struct cprng_test_suite cprng;
} suite;
};
static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 };
-static char *xbuf[XBUFSIZE];
-static char *axbuf[XBUFSIZE];
-
static void hexdump(unsigned char *buf, unsigned int len)
{
print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET,
@@ -121,6 +125,33 @@ static void tcrypt_complete(struct crypto_async_request *req, int err)
complete(&res->completion);
}
+static int testmgr_alloc_buf(char *buf[XBUFSIZE])
+{
+ int i;
+
+ for (i = 0; i < XBUFSIZE; i++) {
+ buf[i] = (void *)__get_free_page(GFP_KERNEL);
+ if (!buf[i])
+ goto err_free_buf;
+ }
+
+ return 0;
+
+err_free_buf:
+ while (i-- > 0)
+ free_page((unsigned long)buf[i]);
+
+ return -ENOMEM;
+}
+
+static void testmgr_free_buf(char *buf[XBUFSIZE])
+{
+ int i;
+
+ for (i = 0; i < XBUFSIZE; i++)
+ free_page((unsigned long)buf[i]);
+}
+
static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
unsigned int tcount)
{
@@ -130,8 +161,12 @@ static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
char result[64];
struct ahash_request *req;
struct tcrypt_result tresult;
- int ret;
void *hash_buff;
+ char *xbuf[XBUFSIZE];
+ int ret = -ENOMEM;
+
+ if (testmgr_alloc_buf(xbuf))
+ goto out_nobuf;
init_completion(&tresult.completion);
@@ -139,7 +174,6 @@ static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
if (!req) {
printk(KERN_ERR "alg: hash: Failed to allocate request for "
"%s\n", algo);
- ret = -ENOMEM;
goto out_noreq;
}
ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
@@ -265,6 +299,8 @@ static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
out:
ahash_request_free(req);
out_noreq:
+ testmgr_free_buf(xbuf);
+out_nobuf:
return ret;
}
@@ -273,7 +309,7 @@ static int test_aead(struct crypto_aead *tfm, int enc,
{
const char *algo = crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm));
unsigned int i, j, k, n, temp;
- int ret = 0;
+ int ret = -ENOMEM;
char *q;
char *key;
struct aead_request *req;
@@ -285,6 +321,13 @@ static int test_aead(struct crypto_aead *tfm, int enc,
void *input;
void *assoc;
char iv[MAX_IVLEN];
+ char *xbuf[XBUFSIZE];
+ char *axbuf[XBUFSIZE];
+
+ if (testmgr_alloc_buf(xbuf))
+ goto out_noxbuf;
+ if (testmgr_alloc_buf(axbuf))
+ goto out_noaxbuf;
if (enc == ENCRYPT)
e = "encryption";
@@ -297,7 +340,6 @@ static int test_aead(struct crypto_aead *tfm, int enc,
if (!req) {
printk(KERN_ERR "alg: aead: Failed to allocate request for "
"%s\n", algo);
- ret = -ENOMEM;
goto out;
}
@@ -363,6 +405,16 @@ static int test_aead(struct crypto_aead *tfm, int enc,
switch (ret) {
case 0:
+ if (template[i].novrfy) {
+ /* verification was supposed to fail */
+ printk(KERN_ERR "alg: aead: %s failed "
+ "on test %d for %s: ret was 0, "
+ "expected -EBADMSG\n",
+ e, j, algo);
+ /* so really, we got a bad message */
+ ret = -EBADMSG;
+ goto out;
+ }
break;
case -EINPROGRESS:
case -EBUSY:
@@ -372,6 +424,10 @@ static int test_aead(struct crypto_aead *tfm, int enc,
INIT_COMPLETION(result.completion);
break;
}
+ case -EBADMSG:
+ if (template[i].novrfy)
+ /* verification failure was expected */
+ continue;
/* fall through */
default:
printk(KERN_ERR "alg: aead: %s failed on test "
@@ -481,6 +537,16 @@ static int test_aead(struct crypto_aead *tfm, int enc,
switch (ret) {
case 0:
+ if (template[i].novrfy) {
+ /* verification was supposed to fail */
+ printk(KERN_ERR "alg: aead: %s failed "
+ "on chunk test %d for %s: ret "
+ "was 0, expected -EBADMSG\n",
+ e, j, algo);
+ /* so really, we got a bad message */
+ ret = -EBADMSG;
+ goto out;
+ }
break;
case -EINPROGRESS:
case -EBUSY:
@@ -490,6 +556,10 @@ static int test_aead(struct crypto_aead *tfm, int enc,
INIT_COMPLETION(result.completion);
break;
}
+ case -EBADMSG:
+ if (template[i].novrfy)
+ /* verification failure was expected */
+ continue;
/* fall through */
default:
printk(KERN_ERR "alg: aead: %s failed on "
@@ -546,6 +616,10 @@ static int test_aead(struct crypto_aead *tfm, int enc,
out:
aead_request_free(req);
+ testmgr_free_buf(axbuf);
+out_noaxbuf:
+ testmgr_free_buf(xbuf);
+out_noxbuf:
return ret;
}
@@ -554,10 +628,14 @@ static int test_cipher(struct crypto_cipher *tfm, int enc,
{
const char *algo = crypto_tfm_alg_driver_name(crypto_cipher_tfm(tfm));
unsigned int i, j, k;
- int ret;
char *q;
const char *e;
void *data;
+ char *xbuf[XBUFSIZE];
+ int ret = -ENOMEM;
+
+ if (testmgr_alloc_buf(xbuf))
+ goto out_nobuf;
if (enc == ENCRYPT)
e = "encryption";
@@ -611,6 +689,8 @@ static int test_cipher(struct crypto_cipher *tfm, int enc,
ret = 0;
out:
+ testmgr_free_buf(xbuf);
+out_nobuf:
return ret;
}
@@ -620,7 +700,6 @@ static int test_skcipher(struct crypto_ablkcipher *tfm, int enc,
const char *algo =
crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm));
unsigned int i, j, k, n, temp;
- int ret;
char *q;
struct ablkcipher_request *req;
struct scatterlist sg[8];
@@ -628,6 +707,11 @@ static int test_skcipher(struct crypto_ablkcipher *tfm, int enc,
struct tcrypt_result result;
void *data;
char iv[MAX_IVLEN];
+ char *xbuf[XBUFSIZE];
+ int ret = -ENOMEM;
+
+ if (testmgr_alloc_buf(xbuf))
+ goto out_nobuf;
if (enc == ENCRYPT)
e = "encryption";
@@ -640,7 +724,6 @@ static int test_skcipher(struct crypto_ablkcipher *tfm, int enc,
if (!req) {
printk(KERN_ERR "alg: skcipher: Failed to allocate request "
"for %s\n", algo);
- ret = -ENOMEM;
goto out;
}
@@ -825,6 +908,8 @@ static int test_skcipher(struct crypto_ablkcipher *tfm, int enc,
out:
ablkcipher_request_free(req);
+ testmgr_free_buf(xbuf);
+out_nobuf:
return ret;
}
@@ -837,7 +922,8 @@ static int test_comp(struct crypto_comp *tfm, struct comp_testvec *ctemplate,
int ret;
for (i = 0; i < ctcount; i++) {
- int ilen, dlen = COMP_BUF_SIZE;
+ int ilen;
+ unsigned int dlen = COMP_BUF_SIZE;
memset(result, 0, sizeof (result));
@@ -869,7 +955,8 @@ static int test_comp(struct crypto_comp *tfm, struct comp_testvec *ctemplate,
}
for (i = 0; i < dtcount; i++) {
- int ilen, dlen = COMP_BUF_SIZE;
+ int ilen;
+ unsigned int dlen = COMP_BUF_SIZE;
memset(result, 0, sizeof (result));
@@ -1059,6 +1146,68 @@ static int test_pcomp(struct crypto_pcomp *tfm,
return 0;
}
+
+static int test_cprng(struct crypto_rng *tfm, struct cprng_testvec *template,
+ unsigned int tcount)
+{
+ const char *algo = crypto_tfm_alg_driver_name(crypto_rng_tfm(tfm));
+ int err, i, j, seedsize;
+ u8 *seed;
+ char result[32];
+
+ seedsize = crypto_rng_seedsize(tfm);
+
+ seed = kmalloc(seedsize, GFP_KERNEL);
+ if (!seed) {
+ printk(KERN_ERR "alg: cprng: Failed to allocate seed space "
+ "for %s\n", algo);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < tcount; i++) {
+ memset(result, 0, 32);
+
+ memcpy(seed, template[i].v, template[i].vlen);
+ memcpy(seed + template[i].vlen, template[i].key,
+ template[i].klen);
+ memcpy(seed + template[i].vlen + template[i].klen,
+ template[i].dt, template[i].dtlen);
+
+ err = crypto_rng_reset(tfm, seed, seedsize);
+ if (err) {
+ printk(KERN_ERR "alg: cprng: Failed to reset rng "
+ "for %s\n", algo);
+ goto out;
+ }
+
+ for (j = 0; j < template[i].loops; j++) {
+ err = crypto_rng_get_bytes(tfm, result,
+ template[i].rlen);
+ if (err != template[i].rlen) {
+ printk(KERN_ERR "alg: cprng: Failed to obtain "
+ "the correct amount of random data for "
+ "%s (requested %d, got %d)\n", algo,
+ template[i].rlen, err);
+ goto out;
+ }
+ }
+
+ err = memcmp(result, template[i].result,
+ template[i].rlen);
+ if (err) {
+ printk(KERN_ERR "alg: cprng: Test %d failed for %s\n",
+ i, algo);
+ hexdump(result, template[i].rlen);
+ err = -EINVAL;
+ goto out;
+ }
+ }
+
+out:
+ kfree(seed);
+ return err;
+}
+
static int alg_test_aead(const struct alg_test_desc *desc, const char *driver,
u32 type, u32 mask)
{
@@ -1258,9 +1407,38 @@ out:
return err;
}
+static int alg_test_cprng(const struct alg_test_desc *desc, const char *driver,
+ u32 type, u32 mask)
+{
+ struct crypto_rng *rng;
+ int err;
+
+ rng = crypto_alloc_rng(driver, type, mask);
+ if (IS_ERR(rng)) {
+ printk(KERN_ERR "alg: cprng: Failed to load transform for %s: "
+ "%ld\n", driver, PTR_ERR(rng));
+ return PTR_ERR(rng);
+ }
+
+ err = test_cprng(rng, desc->suite.cprng.vecs, desc->suite.cprng.count);
+
+ crypto_free_rng(rng);
+
+ return err;
+}
+
/* Please keep this list sorted by algorithm name. */
static const struct alg_test_desc alg_test_descs[] = {
{
+ .alg = "ansi_cprng",
+ .test = alg_test_cprng,
+ .suite = {
+ .cprng = {
+ .vecs = ansi_cprng_aes_tv_template,
+ .count = ANSI_CPRNG_AES_TEST_VECTORS
+ }
+ }
+ }, {
.alg = "cbc(aes)",
.test = alg_test_skcipher,
.suite = {
@@ -1390,6 +1568,21 @@ static const struct alg_test_desc alg_test_descs[] = {
}
}
}, {
+ .alg = "ctr(aes)",
+ .test = alg_test_skcipher,
+ .suite = {
+ .cipher = {
+ .enc = {
+ .vecs = aes_ctr_enc_tv_template,
+ .count = AES_CTR_ENC_TEST_VECTORS
+ },
+ .dec = {
+ .vecs = aes_ctr_dec_tv_template,
+ .count = AES_CTR_DEC_TEST_VECTORS
+ }
+ }
+ }
+ }, {
.alg = "cts(cbc(aes))",
.test = alg_test_skcipher,
.suite = {
@@ -1839,12 +2032,27 @@ static const struct alg_test_desc alg_test_descs[] = {
.suite = {
.cipher = {
.enc = {
- .vecs = aes_ctr_enc_tv_template,
- .count = AES_CTR_ENC_TEST_VECTORS
+ .vecs = aes_ctr_rfc3686_enc_tv_template,
+ .count = AES_CTR_3686_ENC_TEST_VECTORS
},
.dec = {
- .vecs = aes_ctr_dec_tv_template,
- .count = AES_CTR_DEC_TEST_VECTORS
+ .vecs = aes_ctr_rfc3686_dec_tv_template,
+ .count = AES_CTR_3686_DEC_TEST_VECTORS
+ }
+ }
+ }
+ }, {
+ .alg = "rfc4309(ccm(aes))",
+ .test = alg_test_aead,
+ .suite = {
+ .aead = {
+ .enc = {
+ .vecs = aes_ccm_rfc4309_enc_tv_template,
+ .count = AES_CCM_4309_ENC_TEST_VECTORS
+ },
+ .dec = {
+ .vecs = aes_ccm_rfc4309_dec_tv_template,
+ .count = AES_CCM_4309_DEC_TEST_VECTORS
}
}
}
@@ -2077,7 +2285,8 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
if (i < 0)
goto notest;
- return alg_test_cipher(alg_test_descs + i, driver, type, mask);
+ rc = alg_test_cipher(alg_test_descs + i, driver, type, mask);
+ goto test_done;
}
i = alg_find_test(alg);
@@ -2086,9 +2295,14 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
rc = alg_test_descs[i].test(alg_test_descs + i, driver,
type, mask);
+test_done:
if (fips_enabled && rc)
panic("%s: %s alg self test failed in fips mode!\n", driver, alg);
+ if (fips_enabled && !rc)
+ printk(KERN_INFO "alg: self-tests for %s (%s) passed\n",
+ driver, alg);
+
return rc;
notest:
@@ -2096,41 +2310,3 @@ notest:
return 0;
}
EXPORT_SYMBOL_GPL(alg_test);
-
-int __init testmgr_init(void)
-{
- int i;
-
- for (i = 0; i < XBUFSIZE; i++) {
- xbuf[i] = (void *)__get_free_page(GFP_KERNEL);
- if (!xbuf[i])
- goto err_free_xbuf;
- }
-
- for (i = 0; i < XBUFSIZE; i++) {
- axbuf[i] = (void *)__get_free_page(GFP_KERNEL);
- if (!axbuf[i])
- goto err_free_axbuf;
- }
-
- return 0;
-
-err_free_axbuf:
- for (i = 0; i < XBUFSIZE && axbuf[i]; i++)
- free_page((unsigned long)axbuf[i]);
-err_free_xbuf:
- for (i = 0; i < XBUFSIZE && xbuf[i]; i++)
- free_page((unsigned long)xbuf[i]);
-
- return -ENOMEM;
-}
-
-void testmgr_exit(void)
-{
- int i;
-
- for (i = 0; i < XBUFSIZE; i++)
- free_page((unsigned long)axbuf[i]);
- for (i = 0; i < XBUFSIZE; i++)
- free_page((unsigned long)xbuf[i]);
-}
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 526f00a9c72f..69316228fc19 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -62,6 +62,7 @@ struct aead_testvec {
int np;
int anp;
unsigned char fail;
+ unsigned char novrfy; /* ccm dec verification failure expected */
unsigned char wk; /* weak key flag */
unsigned char klen;
unsigned short ilen;
@@ -69,6 +70,18 @@ struct aead_testvec {
unsigned short rlen;
};
+struct cprng_testvec {
+ char *key;
+ char *dt;
+ char *v;
+ char *result;
+ unsigned char klen;
+ unsigned short dtlen;
+ unsigned short vlen;
+ unsigned short rlen;
+ unsigned short loops;
+};
+
static char zeroed_string[48];
/*
@@ -2841,12 +2854,16 @@ static struct cipher_testvec cast6_dec_tv_template[] = {
#define AES_LRW_DEC_TEST_VECTORS 8
#define AES_XTS_ENC_TEST_VECTORS 4
#define AES_XTS_DEC_TEST_VECTORS 4
-#define AES_CTR_ENC_TEST_VECTORS 7
-#define AES_CTR_DEC_TEST_VECTORS 6
+#define AES_CTR_ENC_TEST_VECTORS 3
+#define AES_CTR_DEC_TEST_VECTORS 3
+#define AES_CTR_3686_ENC_TEST_VECTORS 7
+#define AES_CTR_3686_DEC_TEST_VECTORS 6
#define AES_GCM_ENC_TEST_VECTORS 9
#define AES_GCM_DEC_TEST_VECTORS 8
#define AES_CCM_ENC_TEST_VECTORS 7
#define AES_CCM_DEC_TEST_VECTORS 7
+#define AES_CCM_4309_ENC_TEST_VECTORS 7
+#define AES_CCM_4309_DEC_TEST_VECTORS 10
static struct cipher_testvec aes_enc_tv_template[] = {
{ /* From FIPS-197 */
@@ -3983,6 +4000,164 @@ static struct cipher_testvec aes_xts_dec_tv_template[] = {
static struct cipher_testvec aes_ctr_enc_tv_template[] = {
+ { /* From NIST Special Publication 800-38A, Appendix F.5 */
+ .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6"
+ "\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
+ .klen = 16,
+ .iv = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+ "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+ .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
+ "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
+ "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
+ "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
+ "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+ .ilen = 64,
+ .result = "\x87\x4d\x61\x91\xb6\x20\xe3\x26"
+ "\x1b\xef\x68\x64\x99\x0d\xb6\xce"
+ "\x98\x06\xf6\x6b\x79\x70\xfd\xff"
+ "\x86\x17\x18\x7b\xb9\xff\xfd\xff"
+ "\x5a\xe4\xdf\x3e\xdb\xd5\xd3\x5e"
+ "\x5b\x4f\x09\x02\x0d\xb0\x3e\xab"
+ "\x1e\x03\x1d\xda\x2f\xbe\x03\xd1"
+ "\x79\x21\x70\xa0\xf3\x00\x9c\xee",
+ .rlen = 64,
+ }, {
+ .key = "\x8e\x73\xb0\xf7\xda\x0e\x64\x52"
+ "\xc8\x10\xf3\x2b\x80\x90\x79\xe5"
+ "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b",
+ .klen = 24,
+ .iv = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+ "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+ .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
+ "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
+ "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
+ "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
+ "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+ .ilen = 64,
+ .result = "\x1a\xbc\x93\x24\x17\x52\x1c\xa2"
+ "\x4f\x2b\x04\x59\xfe\x7e\x6e\x0b"
+ "\x09\x03\x39\xec\x0a\xa6\xfa\xef"
+ "\xd5\xcc\xc2\xc6\xf4\xce\x8e\x94"
+ "\x1e\x36\xb2\x6b\xd1\xeb\xc6\x70"
+ "\xd1\xbd\x1d\x66\x56\x20\xab\xf7"
+ "\x4f\x78\xa7\xf6\xd2\x98\x09\x58"
+ "\x5a\x97\xda\xec\x58\xc6\xb0\x50",
+ .rlen = 64,
+ }, {
+ .key = "\x60\x3d\xeb\x10\x15\xca\x71\xbe"
+ "\x2b\x73\xae\xf0\x85\x7d\x77\x81"
+ "\x1f\x35\x2c\x07\x3b\x61\x08\xd7"
+ "\x2d\x98\x10\xa3\x09\x14\xdf\xf4",
+ .klen = 32,
+ .iv = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+ "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+ .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
+ "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
+ "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
+ "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
+ "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+ .ilen = 64,
+ .result = "\x60\x1e\xc3\x13\x77\x57\x89\xa5"
+ "\xb7\xa7\xf5\x04\xbb\xf3\xd2\x28"
+ "\xf4\x43\xe3\xca\x4d\x62\xb5\x9a"
+ "\xca\x84\xe9\x90\xca\xca\xf5\xc5"
+ "\x2b\x09\x30\xda\xa2\x3d\xe9\x4c"
+ "\xe8\x70\x17\xba\x2d\x84\x98\x8d"
+ "\xdf\xc9\xc5\x8d\xb6\x7a\xad\xa6"
+ "\x13\xc2\xdd\x08\x45\x79\x41\xa6",
+ .rlen = 64,
+ }
+};
+
+static struct cipher_testvec aes_ctr_dec_tv_template[] = {
+ { /* From NIST Special Publication 800-38A, Appendix F.5 */
+ .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6"
+ "\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
+ .klen = 16,
+ .iv = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+ "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+ .input = "\x87\x4d\x61\x91\xb6\x20\xe3\x26"
+ "\x1b\xef\x68\x64\x99\x0d\xb6\xce"
+ "\x98\x06\xf6\x6b\x79\x70\xfd\xff"
+ "\x86\x17\x18\x7b\xb9\xff\xfd\xff"
+ "\x5a\xe4\xdf\x3e\xdb\xd5\xd3\x5e"
+ "\x5b\x4f\x09\x02\x0d\xb0\x3e\xab"
+ "\x1e\x03\x1d\xda\x2f\xbe\x03\xd1"
+ "\x79\x21\x70\xa0\xf3\x00\x9c\xee",
+ .ilen = 64,
+ .result = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
+ "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
+ "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
+ "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
+ "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+ .rlen = 64,
+ }, {
+ .key = "\x8e\x73\xb0\xf7\xda\x0e\x64\x52"
+ "\xc8\x10\xf3\x2b\x80\x90\x79\xe5"
+ "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b",
+ .klen = 24,
+ .iv = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+ "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+ .input = "\x1a\xbc\x93\x24\x17\x52\x1c\xa2"
+ "\x4f\x2b\x04\x59\xfe\x7e\x6e\x0b"
+ "\x09\x03\x39\xec\x0a\xa6\xfa\xef"
+ "\xd5\xcc\xc2\xc6\xf4\xce\x8e\x94"
+ "\x1e\x36\xb2\x6b\xd1\xeb\xc6\x70"
+ "\xd1\xbd\x1d\x66\x56\x20\xab\xf7"
+ "\x4f\x78\xa7\xf6\xd2\x98\x09\x58"
+ "\x5a\x97\xda\xec\x58\xc6\xb0\x50",
+ .ilen = 64,
+ .result = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
+ "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
+ "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
+ "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
+ "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+ .rlen = 64,
+ }, {
+ .key = "\x60\x3d\xeb\x10\x15\xca\x71\xbe"
+ "\x2b\x73\xae\xf0\x85\x7d\x77\x81"
+ "\x1f\x35\x2c\x07\x3b\x61\x08\xd7"
+ "\x2d\x98\x10\xa3\x09\x14\xdf\xf4",
+ .klen = 32,
+ .iv = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+ "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+ .input = "\x60\x1e\xc3\x13\x77\x57\x89\xa5"
+ "\xb7\xa7\xf5\x04\xbb\xf3\xd2\x28"
+ "\xf4\x43\xe3\xca\x4d\x62\xb5\x9a"
+ "\xca\x84\xe9\x90\xca\xca\xf5\xc5"
+ "\x2b\x09\x30\xda\xa2\x3d\xe9\x4c"
+ "\xe8\x70\x17\xba\x2d\x84\x98\x8d"
+ "\xdf\xc9\xc5\x8d\xb6\x7a\xad\xa6"
+ "\x13\xc2\xdd\x08\x45\x79\x41\xa6",
+ .ilen = 64,
+ .result = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
+ "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
+ "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
+ "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
+ "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+ .rlen = 64,
+ }
+};
+
+static struct cipher_testvec aes_ctr_rfc3686_enc_tv_template[] = {
{ /* From RFC 3686 */
.key = "\xae\x68\x52\xf8\x12\x10\x67\xcc"
"\x4b\xf7\xa5\x76\x55\x77\xf3\x9e"
@@ -5114,7 +5289,7 @@ static struct cipher_testvec aes_ctr_enc_tv_template[] = {
},
};
-static struct cipher_testvec aes_ctr_dec_tv_template[] = {
+static struct cipher_testvec aes_ctr_rfc3686_dec_tv_template[] = {
{ /* From RFC 3686 */
.key = "\xae\x68\x52\xf8\x12\x10\x67\xcc"
"\x4b\xf7\xa5\x76\x55\x77\xf3\x9e"
@@ -5825,6 +6000,470 @@ static struct aead_testvec aes_ccm_dec_tv_template[] = {
},
};
+/*
+ * rfc4309 refers to section 8 of rfc3610 for test vectors, but they all
+ * use a 13-byte nonce, we only support an 11-byte nonce. Similarly, all of
+ * Special Publication 800-38C's test vectors also use nonce lengths our
+ * implementation doesn't support. The following are taken from fips cavs
+ * fax files on hand at Red Hat.
+ *
+ * nb: actual key lengths are (klen - 3), the last 3 bytes are actually
+ * part of the nonce which combine w/the iv, but need to be input this way.
+ */
+static struct aead_testvec aes_ccm_rfc4309_enc_tv_template[] = {
+ {
+ .key = "\x83\xac\x54\x66\xc2\xeb\xe5\x05"
+ "\x2e\x01\xd1\xfc\x5d\x82\x66\x2e"
+ "\x96\xac\x59",
+ .klen = 19,
+ .iv = "\x30\x07\xa1\xe2\xa2\xc7\x55\x24",
+ .alen = 0,
+ .input = "\x19\xc8\x81\xf6\xe9\x86\xff\x93"
+ "\x0b\x78\x67\xe5\xbb\xb7\xfc\x6e"
+ "\x83\x77\xb3\xa6\x0c\x8c\x9f\x9c"
+ "\x35\x2e\xad\xe0\x62\xf9\x91\xa1",
+ .ilen = 32,
+ .result = "\xab\x6f\xe1\x69\x1d\x19\x99\xa8"
+ "\x92\xa0\xc4\x6f\x7e\xe2\x8b\xb1"
+ "\x70\xbb\x8c\xa6\x4c\x6e\x97\x8a"
+ "\x57\x2b\xbe\x5d\x98\xa6\xb1\x32"
+ "\xda\x24\xea\xd9\xa1\x39\x98\xfd"
+ "\xa4\xbe\xd9\xf2\x1a\x6d\x22\xa8",
+ .rlen = 48,
+ }, {
+ .key = "\x1e\x2c\x7e\x01\x41\x9a\xef\xc0"
+ "\x0d\x58\x96\x6e\x5c\xa2\x4b\xd3"
+ "\x4f\xa3\x19",
+ .klen = 19,
+ .iv = "\xd3\x01\x5a\xd8\x30\x60\x15\x56",
+ .assoc = "\xda\xe6\x28\x9c\x45\x2d\xfd\x63"
+ "\x5e\xda\x4c\xb6\xe6\xfc\xf9\xb7"
+ "\x0c\x56\xcb\xe4\xe0\x05\x7a\xe1"
+ "\x0a\x63\x09\x78\xbc\x2c\x55\xde",
+ .alen = 32,
+ .input = "\x87\xa3\x36\xfd\x96\xb3\x93\x78"
+ "\xa9\x28\x63\xba\x12\xa3\x14\x85"
+ "\x57\x1e\x06\xc9\x7b\x21\xef\x76"
+ "\x7f\x38\x7e\x8e\x29\xa4\x3e\x7e",
+ .ilen = 32,
+ .result = "\x8a\x1e\x11\xf0\x02\x6b\xe2\x19"
+ "\xfc\x70\xc4\x6d\x8e\xb7\x99\xab"
+ "\xc5\x4b\xa2\xac\xd3\xf3\x48\xff"
+ "\x3b\xb5\xce\x53\xef\xde\xbb\x02"
+ "\xa9\x86\x15\x6c\x13\xfe\xda\x0a"
+ "\x22\xb8\x29\x3d\xd8\x39\x9a\x23",
+ .rlen = 48,
+ }, {
+ .key = "\xf4\x6b\xc2\x75\x62\xfe\xb4\xe1"
+ "\xa3\xf0\xff\xdd\x4e\x4b\x12\x75"
+ "\x53\x14\x73\x66\x8d\x88\xf6\x80"
+ "\xa0\x20\x35",
+ .klen = 27,
+ .iv = "\x26\xf2\x21\x8d\x50\x20\xda\xe2",
+ .assoc = "\x5b\x9e\x13\x67\x02\x5e\xef\xc1"
+ "\x6c\xf9\xd7\x1e\x52\x8f\x7a\x47"
+ "\xe9\xd4\xcf\x20\x14\x6e\xf0\x2d"
+ "\xd8\x9e\x2b\x56\x10\x23\x56\xe7",
+ .alen = 32,
+ .ilen = 0,
+ .result = "\x36\xea\x7a\x70\x08\xdc\x6a\xbc"
+ "\xad\x0c\x7a\x63\xf6\x61\xfd\x9b",
+ .rlen = 16,
+ }, {
+ .key = "\x56\xdf\x5c\x8f\x26\x3f\x0e\x42"
+ "\xef\x7a\xd3\xce\xfc\x84\x60\x62"
+ "\xca\xb4\x40\xaf\x5f\xc9\xc9\x01"
+ "\xd6\x3c\x8c",
+ .klen = 27,
+ .iv = "\x86\x84\xb6\xcd\xef\x09\x2e\x94",
+ .assoc = "\x02\x65\x78\x3c\xe9\x21\x30\x91"
+ "\xb1\xb9\xda\x76\x9a\x78\x6d\x95"
+ "\xf2\x88\x32\xa3\xf2\x50\xcb\x4c"
+ "\xe3\x00\x73\x69\x84\x69\x87\x79",
+ .alen = 32,
+ .input = "\x9f\xd2\x02\x4b\x52\x49\x31\x3c"
+ "\x43\x69\x3a\x2d\x8e\x70\xad\x7e"
+ "\xe0\xe5\x46\x09\x80\x89\x13\xb2"
+ "\x8c\x8b\xd9\x3f\x86\xfb\xb5\x6b",
+ .ilen = 32,
+ .result = "\x39\xdf\x7c\x3c\x5a\x29\xb9\x62"
+ "\x5d\x51\xc2\x16\xd8\xbd\x06\x9f"
+ "\x9b\x6a\x09\x70\xc1\x51\x83\xc2"
+ "\x66\x88\x1d\x4f\x9a\xda\xe0\x1e"
+ "\xc7\x79\x11\x58\xe5\x6b\x20\x40"
+ "\x7a\xea\x46\x42\x8b\xe4\x6f\xe1",
+ .rlen = 48,
+ }, {
+ .key = "\xe0\x8d\x99\x71\x60\xd7\x97\x1a"
+ "\xbd\x01\x99\xd5\x8a\xdf\x71\x3a"
+ "\xd3\xdf\x24\x4b\x5e\x3d\x4b\x4e"
+ "\x30\x7a\xb9\xd8\x53\x0a\x5e\x2b"
+ "\x1e\x29\x91",
+ .klen = 35,
+ .iv = "\xad\x8e\xc1\x53\x0a\xcf\x2d\xbe",
+ .assoc = "\x19\xb6\x1f\x57\xc4\xf3\xf0\x8b"
+ "\x78\x2b\x94\x02\x29\x0f\x42\x27"
+ "\x6b\x75\xcb\x98\x34\x08\x7e\x79"
+ "\xe4\x3e\x49\x0d\x84\x8b\x22\x87",
+ .alen = 32,
+ .input = "\xe1\xd9\xd8\x13\xeb\x3a\x75\x3f"
+ "\x9d\xbd\x5f\x66\xbe\xdc\xbb\x66"
+ "\xbf\x17\x99\x62\x4a\x39\x27\x1f"
+ "\x1d\xdc\x24\xae\x19\x2f\x98\x4c",
+ .ilen = 32,
+ .result = "\x19\xb8\x61\x33\x45\x2b\x43\x96"
+ "\x6f\x51\xd0\x20\x30\x7d\x9b\xc6"
+ "\x26\x3d\xf8\xc9\x65\x16\xa8\x9f"
+ "\xf0\x62\x17\x34\xf2\x1e\x8d\x75"
+ "\x4e\x13\xcc\xc0\xc3\x2a\x54\x2d",
+ .rlen = 40,
+ }, {
+ .key = "\x7c\xc8\x18\x3b\x8d\x99\xe0\x7c"
+ "\x45\x41\xb8\xbd\x5c\xa7\xc2\x32"
+ "\x8a\xb8\x02\x59\xa4\xfe\xa9\x2c"
+ "\x09\x75\x9a\x9b\x3c\x9b\x27\x39"
+ "\xf9\xd9\x4e",
+ .klen = 35,
+ .iv = "\x63\xb5\x3d\x9d\x43\xf6\x1e\x50",
+ .assoc = "\x57\xf5\x6b\x8b\x57\x5c\x3d\x3b"
+ "\x13\x02\x01\x0c\x83\x4c\x96\x35"
+ "\x8e\xd6\x39\xcf\x7d\x14\x9b\x94"
+ "\xb0\x39\x36\xe6\x8f\x57\xe0\x13",
+ .alen = 32,
+ .input = "\x3b\x6c\x29\x36\xb6\xef\x07\xa6"
+ "\x83\x72\x07\x4f\xcf\xfa\x66\x89"
+ "\x5f\xca\xb1\xba\xd5\x8f\x2c\x27"
+ "\x30\xdb\x75\x09\x93\xd4\x65\xe4",
+ .ilen = 32,
+ .result = "\xb0\x88\x5a\x33\xaa\xe5\xc7\x1d"
+ "\x85\x23\xc7\xc6\x2f\xf4\x1e\x3d"
+ "\xcc\x63\x44\x25\x07\x78\x4f\x9e"
+ "\x96\xb8\x88\xeb\xbc\x48\x1f\x06"
+ "\x39\xaf\x39\xac\xd8\x4a\x80\x39"
+ "\x7b\x72\x8a\xf7",
+ .rlen = 44,
+ }, {
+ .key = "\xab\xd0\xe9\x33\x07\x26\xe5\x83"
+ "\x8c\x76\x95\xd4\xb6\xdc\xf3\x46"
+ "\xf9\x8f\xad\xe3\x02\x13\x83\x77"
+ "\x3f\xb0\xf1\xa1\xa1\x22\x0f\x2b"
+ "\x24\xa7\x8b",
+ .klen = 35,
+ .iv = "\x07\xcb\xcc\x0e\xe6\x33\xbf\xf5",
+ .assoc = "\xd4\xdb\x30\x1d\x03\xfe\xfd\x5f"
+ "\x87\xd4\x8c\xb6\xb6\xf1\x7a\x5d"
+ "\xab\x90\x65\x8d\x8e\xca\x4d\x4f"
+ "\x16\x0c\x40\x90\x4b\xc7\x36\x73",
+ .alen = 32,
+ .input = "\xf5\xc6\x7d\x48\xc1\xb7\xe6\x92"
+ "\x97\x5a\xca\xc4\xa9\x6d\xf9\x3d"
+ "\x6c\xde\xbc\xf1\x90\xea\x6a\xb2"
+ "\x35\x86\x36\xaf\x5c\xfe\x4b\x3a",
+ .ilen = 32,
+ .result = "\x83\x6f\x40\x87\x72\xcf\xc1\x13"
+ "\xef\xbb\x80\x21\x04\x6c\x58\x09"
+ "\x07\x1b\xfc\xdf\xc0\x3f\x5b\xc7"
+ "\xe0\x79\xa8\x6e\x71\x7c\x3f\xcf"
+ "\x5c\xda\xb2\x33\xe5\x13\xe2\x0d"
+ "\x74\xd1\xef\xb5\x0f\x3a\xb5\xf8",
+ .rlen = 48,
+ },
+};
+
+static struct aead_testvec aes_ccm_rfc4309_dec_tv_template[] = {
+ {
+ .key = "\xab\x2f\x8a\x74\xb7\x1c\xd2\xb1"
+ "\xff\x80\x2e\x48\x7d\x82\xf8\xb9"
+ "\xc6\xfb\x7d",
+ .klen = 19,
+ .iv = "\x80\x0d\x13\xab\xd8\xa6\xb2\xd8",
+ .alen = 0,
+ .input = "\xd5\xe8\x93\x9f\xc7\x89\x2e\x2b",
+ .ilen = 8,
+ .result = "\x00",
+ .rlen = 0,
+ .novrfy = 1,
+ }, {
+ .key = "\xab\x2f\x8a\x74\xb7\x1c\xd2\xb1"
+ "\xff\x80\x2e\x48\x7d\x82\xf8\xb9"
+ "\xaf\x94\x87",
+ .klen = 19,
+ .iv = "\x78\x35\x82\x81\x7f\x88\x94\x68",
+ .alen = 0,
+ .input = "\x41\x3c\xb8\x87\x73\xcb\xf3\xf3",
+ .ilen = 8,
+ .result = "\x00",
+ .rlen = 0,
+ }, {
+ .key = "\x61\x0e\x8c\xae\xe3\x23\xb6\x38"
+ "\x76\x1c\xf6\x3a\x67\xa3\x9c\xd8"
+ "\xc6\xfb\x7d",
+ .klen = 19,
+ .iv = "\x80\x0d\x13\xab\xd8\xa6\xb2\xd8",
+ .assoc = "\xf3\x94\x87\x78\x35\x82\x81\x7f"
+ "\x88\x94\x68\xb1\x78\x6b\x2b\xd6"
+ "\x04\x1f\x4e\xed\x78\xd5\x33\x66"
+ "\xd8\x94\x99\x91\x81\x54\x62\x57",
+ .alen = 32,
+ .input = "\xf0\x7c\x29\x02\xae\x1c\x2f\x55"
+ "\xd0\xd1\x3d\x1a\xa3\x6d\xe4\x0a"
+ "\x86\xb0\x87\x6b\x62\x33\x8c\x34"
+ "\xce\xab\x57\xcc\x79\x0b\xe0\x6f"
+ "\x5c\x3e\x48\x1f\x6c\x46\xf7\x51"
+ "\x8b\x84\x83\x2a\xc1\x05\xb8\xc5",
+ .ilen = 48,
+ .result = "\x50\x82\x3e\x07\xe2\x1e\xb6\xfb"
+ "\x33\xe4\x73\xce\xd2\xfb\x95\x79"
+ "\xe8\xb4\xb5\x77\x11\x10\x62\x6f"
+ "\x6a\x82\xd1\x13\xec\xf5\xd0\x48",
+ .rlen = 32,
+ .novrfy = 1,
+ }, {
+ .key = "\x61\x0e\x8c\xae\xe3\x23\xb6\x38"
+ "\x76\x1c\xf6\x3a\x67\xa3\x9c\xd8"
+ "\x05\xe0\xc9",
+ .klen = 19,
+ .iv = "\x0f\xed\x34\xea\x97\xd4\x3b\xdf",
+ .assoc = "\x49\x5c\x50\x1f\x1d\x94\xcc\x81"
+ "\xba\xb7\xb6\x03\xaf\xa5\xc1\xa1"
+ "\xd8\x5c\x42\x68\xe0\x6c\xda\x89"
+ "\x05\xac\x56\xac\x1b\x2a\xd3\x86",
+ .alen = 32,
+ .input = "\x39\xbe\x7d\x15\x62\x77\xf3\x3c"
+ "\xad\x83\x52\x6d\x71\x03\x25\x1c"
+ "\xed\x81\x3a\x9a\x16\x7d\x19\x80"
+ "\x72\x04\x72\xd0\xf6\xff\x05\x0f"
+ "\xb7\x14\x30\x00\x32\x9e\xa0\xa6"
+ "\x9e\x5a\x18\xa1\xb8\xfe\xdb\xd3",
+ .ilen = 48,
+ .result = "\x75\x05\xbe\xc2\xd9\x1e\xde\x60"
+ "\x47\x3d\x8c\x7d\xbd\xb5\xd9\xb7"
+ "\xf2\xae\x61\x05\x8f\x82\x24\x3f"
+ "\x9c\x67\x91\xe1\x38\x4f\xe4\x0c",
+ .rlen = 32,
+ }, {
+ .key = "\x39\xbb\xa7\xbe\x59\x97\x9e\x73"
+ "\xa2\xbc\x6b\x98\xd7\x75\x7f\xe3"
+ "\xa4\x48\x93\x39\x26\x71\x4a\xc6"
+ "\xee\x49\x83",
+ .klen = 27,
+ .iv = "\xe9\xa9\xff\xe9\x57\xba\xfd\x9e",
+ .assoc = "\x44\xa6\x2c\x05\xe9\xe1\x43\xb1"
+ "\x58\x7c\xf2\x5c\x6d\x39\x0a\x64"
+ "\xa4\xf0\x13\x05\xd1\x77\x99\x67"
+ "\x11\xc4\xc6\xdb\x00\x56\x36\x61",
+ .alen = 32,
+ .input = "\x71\x99\xfa\xf4\x44\x12\x68\x9b",
+ .ilen = 8,
+ .result = "\x00",
+ .rlen = 0,
+ }, {
+ .key = "\x58\x5d\xa0\x96\x65\x1a\x04\xd7"
+ "\x96\xe5\xc5\x68\xaa\x95\x35\xe0"
+ "\x29\xa0\xba\x9e\x48\x78\xd1\xba"
+ "\xee\x49\x83",
+ .klen = 27,
+ .iv = "\xe9\xa9\xff\xe9\x57\xba\xfd\x9e",
+ .assoc = "\x44\xa6\x2c\x05\xe9\xe1\x43\xb1"
+ "\x58\x7c\xf2\x5c\x6d\x39\x0a\x64"
+ "\xa4\xf0\x13\x05\xd1\x77\x99\x67"
+ "\x11\xc4\xc6\xdb\x00\x56\x36\x61",
+ .alen = 32,
+ .input = "\xfb\xe5\x5d\x34\xbe\xe5\xe8\xe7"
+ "\x5a\xef\x2f\xbf\x1f\x7f\xd4\xb2"
+ "\x66\xca\x61\x1e\x96\x7a\x61\xb3"
+ "\x1c\x16\x45\x52\xba\x04\x9c\x9f"
+ "\xb1\xd2\x40\xbc\x52\x7c\x6f\xb1",
+ .ilen = 40,
+ .result = "\x85\x34\x66\x42\xc8\x92\x0f\x36"
+ "\x58\xe0\x6b\x91\x3c\x98\x5c\xbb"
+ "\x0a\x85\xcc\x02\xad\x7a\x96\xe9"
+ "\x65\x43\xa4\xc3\x0f\xdc\x55\x81",
+ .rlen = 32,
+ }, {
+ .key = "\x58\x5d\xa0\x96\x65\x1a\x04\xd7"
+ "\x96\xe5\xc5\x68\xaa\x95\x35\xe0"
+ "\x29\xa0\xba\x9e\x48\x78\xd1\xba"
+ "\xd1\xfc\x57",
+ .klen = 27,
+ .iv = "\x9c\xfe\xb8\x9c\xad\x71\xaa\x1f",
+ .assoc = "\x86\x67\xa5\xa9\x14\x5f\x0d\xc6"
+ "\xff\x14\xc7\x44\xbf\x6c\x3a\xc3"
+ "\xff\xb6\x81\xbd\xe2\xd5\x06\xc7"
+ "\x3c\xa1\x52\x13\x03\x8a\x23\x3a",
+ .alen = 32,
+ .input = "\x3f\x66\xb0\x9d\xe5\x4b\x38\x00"
+ "\xc6\x0e\x6e\xe5\xd6\x98\xa6\x37"
+ "\x8c\x26\x33\xc6\xb2\xa2\x17\xfa"
+ "\x64\x19\xc0\x30\xd7\xfc\x14\x6b"
+ "\xe3\x33\xc2\x04\xb0\x37\xbe\x3f"
+ "\xa9\xb4\x2d\x68\x03\xa3\x44\xef",
+ .ilen = 48,
+ .result = "\x02\x87\x4d\x28\x80\x6e\xb2\xed"
+ "\x99\x2a\xa8\xca\x04\x25\x45\x90"
+ "\x1d\xdd\x5a\xd9\xe4\xdb\x9c\x9c"
+ "\x49\xe9\x01\xfe\xa7\x80\x6d\x6b",
+ .rlen = 32,
+ .novrfy = 1,
+ }, {
+ .key = "\xa4\x4b\x54\x29\x0a\xb8\x6d\x01"
+ "\x5b\x80\x2a\xcf\x25\xc4\xb7\x5c"
+ "\x20\x2c\xad\x30\xc2\x2b\x41\xfb"
+ "\x0e\x85\xbc\x33\xad\x0f\x2b\xff"
+ "\xee\x49\x83",
+ .klen = 35,
+ .iv = "\xe9\xa9\xff\xe9\x57\xba\xfd\x9e",
+ .alen = 0,
+ .input = "\x1f\xb8\x8f\xa3\xdd\x54\x00\xf2",
+ .ilen = 8,
+ .result = "\x00",
+ .rlen = 0,
+ }, {
+ .key = "\x39\xbb\xa7\xbe\x59\x97\x9e\x73"
+ "\xa2\xbc\x6b\x98\xd7\x75\x7f\xe3"
+ "\xa4\x48\x93\x39\x26\x71\x4a\xc6"
+ "\xae\x8f\x11\x4c\xc2\x9c\x4a\xbb"
+ "\x85\x34\x66",
+ .klen = 35,
+ .iv = "\x42\xc8\x92\x0f\x36\x58\xe0\x6b",
+ .alen = 0,
+ .input = "\x48\x01\x5e\x02\x24\x04\x66\x47"
+ "\xa1\xea\x6f\xaf\xe8\xfc\xfb\xdd"
+ "\xa5\xa9\x87\x8d\x84\xee\x2e\x77"
+ "\xbb\x86\xb9\xf5\x5c\x6c\xff\xf6"
+ "\x72\xc3\x8e\xf7\x70\xb1\xb2\x07"
+ "\xbc\xa8\xa3\xbd\x83\x7c\x1d\x2a",
+ .ilen = 48,
+ .result = "\xdc\x56\xf2\x71\xb0\xb1\xa0\x6c"
+ "\xf0\x97\x3a\xfb\x6d\xe7\x32\x99"
+ "\x3e\xaf\x70\x5e\xb2\x4d\xea\x39"
+ "\x89\xd4\x75\x7a\x63\xb1\xda\x93",
+ .rlen = 32,
+ .novrfy = 1,
+ }, {
+ .key = "\x58\x5d\xa0\x96\x65\x1a\x04\xd7"
+ "\x96\xe5\xc5\x68\xaa\x95\x35\xe0"
+ "\x29\xa0\xba\x9e\x48\x78\xd1\xba"
+ "\x0d\x1a\x53\x3b\xb5\xe3\xf8\x8b"
+ "\xcf\x76\x3f",
+ .klen = 35,
+ .iv = "\xd9\x95\x75\x8f\x44\x89\x40\x7b",
+ .assoc = "\x8f\x86\x6c\x4d\x1d\xc5\x39\x88"
+ "\xc8\xf3\x5c\x52\x10\x63\x6f\x2b"
+ "\x8a\x2a\xc5\x6f\x30\x23\x58\x7b"
+ "\xfb\x36\x03\x11\xb4\xd9\xf2\xfe",
+ .alen = 32,
+ .input = "\x48\x58\xd6\xf3\xad\x63\x58\xbf"
+ "\xae\xc7\x5e\xae\x83\x8f\x7b\xe4"
+ "\x78\x5c\x4c\x67\x71\x89\x94\xbf"
+ "\x47\xf1\x63\x7e\x1c\x59\xbd\xc5"
+ "\x7f\x44\x0a\x0c\x01\x18\x07\x92"
+ "\xe1\xd3\x51\xce\x32\x6d\x0c\x5b",
+ .ilen = 48,
+ .result = "\xc2\x54\xc8\xde\x78\x87\x77\x40"
+ "\x49\x71\xe4\xb7\xe7\xcb\x76\x61"
+ "\x0a\x41\xb9\xe9\xc0\x76\x54\xab"
+ "\x04\x49\x3b\x19\x93\x57\x25\x5d",
+ .rlen = 32,
+ },
+};
+
+/*
+ * ANSI X9.31 Continuous Pseudo-Random Number Generator (AES mode)
+ * test vectors, taken from Appendix B.2.9 and B.2.10:
+ * http://csrc.nist.gov/groups/STM/cavp/documents/rng/RNGVS.pdf
+ * Only AES-128 is supported at this time.
+ */
+#define ANSI_CPRNG_AES_TEST_VECTORS 6
+
+static struct cprng_testvec ansi_cprng_aes_tv_template[] = {
+ {
+ .key = "\xf3\xb1\x66\x6d\x13\x60\x72\x42"
+ "\xed\x06\x1c\xab\xb8\xd4\x62\x02",
+ .klen = 16,
+ .dt = "\xe6\xb3\xbe\x78\x2a\x23\xfa\x62"
+ "\xd7\x1d\x4a\xfb\xb0\xe9\x22\xf9",
+ .dtlen = 16,
+ .v = "\x80\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .vlen = 16,
+ .result = "\x59\x53\x1e\xd1\x3b\xb0\xc0\x55"
+ "\x84\x79\x66\x85\xc1\x2f\x76\x41",
+ .rlen = 16,
+ .loops = 1,
+ }, {
+ .key = "\xf3\xb1\x66\x6d\x13\x60\x72\x42"
+ "\xed\x06\x1c\xab\xb8\xd4\x62\x02",
+ .klen = 16,
+ .dt = "\xe6\xb3\xbe\x78\x2a\x23\xfa\x62"
+ "\xd7\x1d\x4a\xfb\xb0\xe9\x22\xfa",
+ .dtlen = 16,
+ .v = "\xc0\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .vlen = 16,
+ .result = "\x7c\x22\x2c\xf4\xca\x8f\xa2\x4c"
+ "\x1c\x9c\xb6\x41\xa9\xf3\x22\x0d",
+ .rlen = 16,
+ .loops = 1,
+ }, {
+ .key = "\xf3\xb1\x66\x6d\x13\x60\x72\x42"
+ "\xed\x06\x1c\xab\xb8\xd4\x62\x02",
+ .klen = 16,
+ .dt = "\xe6\xb3\xbe\x78\x2a\x23\xfa\x62"
+ "\xd7\x1d\x4a\xfb\xb0\xe9\x22\xfb",
+ .dtlen = 16,
+ .v = "\xe0\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .vlen = 16,
+ .result = "\x8a\xaa\x00\x39\x66\x67\x5b\xe5"
+ "\x29\x14\x28\x81\xa9\x4d\x4e\xc7",
+ .rlen = 16,
+ .loops = 1,
+ }, {
+ .key = "\xf3\xb1\x66\x6d\x13\x60\x72\x42"
+ "\xed\x06\x1c\xab\xb8\xd4\x62\x02",
+ .klen = 16,
+ .dt = "\xe6\xb3\xbe\x78\x2a\x23\xfa\x62"
+ "\xd7\x1d\x4a\xfb\xb0\xe9\x22\xfc",
+ .dtlen = 16,
+ .v = "\xf0\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .vlen = 16,
+ .result = "\x88\xdd\xa4\x56\x30\x24\x23\xe5"
+ "\xf6\x9d\xa5\x7e\x7b\x95\xc7\x3a",
+ .rlen = 16,
+ .loops = 1,
+ }, {
+ .key = "\xf3\xb1\x66\x6d\x13\x60\x72\x42"
+ "\xed\x06\x1c\xab\xb8\xd4\x62\x02",
+ .klen = 16,
+ .dt = "\xe6\xb3\xbe\x78\x2a\x23\xfa\x62"
+ "\xd7\x1d\x4a\xfb\xb0\xe9\x22\xfd",
+ .dtlen = 16,
+ .v = "\xf8\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .vlen = 16,
+ .result = "\x05\x25\x92\x46\x61\x79\xd2\xcb"
+ "\x78\xc4\x0b\x14\x0a\x5a\x9a\xc8",
+ .rlen = 16,
+ .loops = 1,
+ }, { /* Monte Carlo Test */
+ .key = "\x9f\x5b\x51\x20\x0b\xf3\x34\xb5"
+ "\xd8\x2b\xe8\xc3\x72\x55\xc8\x48",
+ .klen = 16,
+ .dt = "\x63\x76\xbb\xe5\x29\x02\xba\x3b"
+ "\x67\xc9\x25\xfa\x70\x1f\x11\xac",
+ .dtlen = 16,
+ .v = "\x57\x2c\x8e\x76\x87\x26\x47\x97"
+ "\x7e\x74\xfb\xdd\xc4\x95\x01\xd1",
+ .vlen = 16,
+ .result = "\x48\xe9\xbd\x0d\x06\xee\x18\xfb"
+ "\xe4\x57\x90\xd5\xc3\xfc\x9b\x73",
+ .rlen = 16,
+ .loops = 10000,
+ },
+};
+
/* Cast5 test vectors from RFC 2144 */
#define CAST5_ENC_TEST_VECTORS 3
#define CAST5_DEC_TEST_VECTORS 3
diff --git a/drivers/Makefile b/drivers/Makefile
index 2618a6169a13..1266ead6ace0 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -36,7 +36,7 @@ obj-$(CONFIG_FB_INTEL) += video/intelfb/
obj-y += serial/
obj-$(CONFIG_PARPORT) += parport/
-obj-y += base/ block/ misc/ mfd/ media/
+obj-y += base/ block/ misc/ mfd/
obj-$(CONFIG_NUBUS) += nubus/
obj-y += macintosh/
obj-$(CONFIG_IDE) += ide/
@@ -71,7 +71,7 @@ obj-$(CONFIG_GAMEPORT) += input/gameport/
obj-$(CONFIG_INPUT) += input/
obj-$(CONFIG_I2O) += message/
obj-$(CONFIG_RTC_LIB) += rtc/
-obj-y += i2c/
+obj-y += i2c/ media/
obj-$(CONFIG_W1) += w1/
obj-$(CONFIG_POWER_SUPPLY) += power/
obj-$(CONFIG_HWMON) += hwmon/
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
index 17e50824a6f1..72ac28da14e3 100644
--- a/drivers/acpi/acpica/Makefile
+++ b/drivers/acpi/acpica/Makefile
@@ -5,40 +5,43 @@
ccflags-y := -Os
ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT
-obj-y := dsfield.o dsmthdat.o dsopcode.o dswexec.o dswscope.o \
+# use acpi.o to put all files here into acpi.o modparam namespace
+obj-y += acpi.o
+
+acpi-y := dsfield.o dsmthdat.o dsopcode.o dswexec.o dswscope.o \
dsmethod.o dsobject.o dsutils.o dswload.o dswstate.o \
dsinit.o
-obj-y += evevent.o evregion.o evsci.o evxfevnt.o \
+acpi-y += evevent.o evregion.o evsci.o evxfevnt.o \
evmisc.o evrgnini.o evxface.o evxfregn.o \
evgpe.o evgpeblk.o
-obj-y += exconfig.o exfield.o exnames.o exoparg6.o exresolv.o exstorob.o\
+acpi-y += exconfig.o exfield.o exnames.o exoparg6.o exresolv.o exstorob.o\
exconvrt.o exfldio.o exoparg1.o exprep.o exresop.o exsystem.o\
excreate.o exmisc.o exoparg2.o exregion.o exstore.o exutils.o \
exdump.o exmutex.o exoparg3.o exresnte.o exstoren.o
-obj-y += hwacpi.o hwgpe.o hwregs.o hwsleep.o hwxface.o hwvalid.o
+acpi-y += hwacpi.o hwgpe.o hwregs.o hwsleep.o hwxface.o hwvalid.o
-obj-$(ACPI_FUTURE_USAGE) += hwtimer.o
+acpi-$(ACPI_FUTURE_USAGE) += hwtimer.o
-obj-y += nsaccess.o nsload.o nssearch.o nsxfeval.o \
+acpi-y += nsaccess.o nsload.o nssearch.o nsxfeval.o \
nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \
nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \
nsparse.o nspredef.o
-obj-$(ACPI_FUTURE_USAGE) += nsdumpdv.o
+acpi-$(ACPI_FUTURE_USAGE) += nsdumpdv.o
-obj-y += psargs.o psparse.o psloop.o pstree.o pswalk.o \
+acpi-y += psargs.o psparse.o psloop.o pstree.o pswalk.o \
psopcode.o psscope.o psutils.o psxface.o
-obj-y += rsaddr.o rscreate.o rsinfo.o rsio.o rslist.o rsmisc.o rsxface.o \
+acpi-y += rsaddr.o rscreate.o rsinfo.o rsio.o rslist.o rsmisc.o rsxface.o \
rscalc.o rsirq.o rsmemory.o rsutils.o
-obj-$(ACPI_FUTURE_USAGE) += rsdump.o
+acpi-$(ACPI_FUTURE_USAGE) += rsdump.o
-obj-y += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o
+acpi-y += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o
-obj-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
+acpi-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
utcopy.o utdelete.o utglobal.o utmath.o utobject.o \
utstate.o utmutex.o utobject.o utresrc.o utlock.o
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 16e5210ae936..3d87362d17ed 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -362,9 +362,6 @@ extern u8 acpi_gbl_method_executing;
extern u8 acpi_gbl_abort_method;
extern u8 acpi_gbl_db_terminate_threads;
-ACPI_EXTERN int optind;
-ACPI_EXTERN char *optarg;
-
ACPI_EXTERN u8 acpi_gbl_db_opt_tables;
ACPI_EXTERN u8 acpi_gbl_db_opt_stats;
ACPI_EXTERN u8 acpi_gbl_db_opt_ini_methods;
diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c
index dab3f48f0b42..02e6caad4a76 100644
--- a/drivers/acpi/acpica/dsobject.c
+++ b/drivers/acpi/acpica/dsobject.c
@@ -734,7 +734,8 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
/* Local ID (0-7) is (AML opcode - base AML_LOCAL_OP) */
- obj_desc->reference.value = opcode - AML_LOCAL_OP;
+ obj_desc->reference.value =
+ ((u32)opcode) - AML_LOCAL_OP;
obj_desc->reference.class = ACPI_REFCLASS_LOCAL;
#ifndef ACPI_NO_METHOD_EXECUTION
@@ -754,7 +755,7 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
/* Arg ID (0-6) is (AML opcode - base AML_ARG_OP) */
- obj_desc->reference.value = opcode - AML_ARG_OP;
+ obj_desc->reference.value = ((u32)opcode) - AML_ARG_OP;
obj_desc->reference.class = ACPI_REFCLASS_ARG;
#ifndef ACPI_NO_METHOD_EXECUTION
diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c
index b4c87b5053e6..584d766e6f12 100644
--- a/drivers/acpi/acpica/dsopcode.c
+++ b/drivers/acpi/acpica/dsopcode.c
@@ -1386,14 +1386,19 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
case AML_BREAK_POINT_OP:
- /* Call up to the OS service layer to handle this */
-
- status =
- acpi_os_signal(ACPI_SIGNAL_BREAKPOINT,
- "Executed AML Breakpoint opcode");
+ /*
+ * Set the single-step flag. This will cause the debugger (if present)
+ * to break to the console within the AML debugger at the start of the
+ * next AML instruction.
+ */
+ ACPI_DEBUGGER_EXEC(acpi_gbl_cm_single_step = TRUE);
+ ACPI_DEBUGGER_EXEC(acpi_os_printf
+ ("**break** Executed AML BreakPoint opcode\n"));
- /* If and when it returns, all done. */
+ /* Call to the OSL in case OS wants a piece of the action */
+ status = acpi_os_signal(ACPI_SIGNAL_BREAKPOINT,
+ "Executed AML Breakpoint opcode");
break;
case AML_BREAK_OP:
diff --git a/drivers/acpi/acpica/dswstate.c b/drivers/acpi/acpica/dswstate.c
index 40f92bf7dce5..e46c821cf572 100644
--- a/drivers/acpi/acpica/dswstate.c
+++ b/drivers/acpi/acpica/dswstate.c
@@ -102,7 +102,7 @@ acpi_ds_result_pop(union acpi_operand_object **object,
/* Return object of the top element and clean that top element result stack */
walk_state->result_count--;
- index = walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM;
+ index = (u32)walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM;
*object = state->results.obj_desc[index];
if (!*object) {
@@ -186,7 +186,7 @@ acpi_ds_result_push(union acpi_operand_object * object,
/* Assign the address of object to the top free element of result stack */
- index = walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM;
+ index = (u32)walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM;
state->results.obj_desc[index] = object;
walk_state->result_count++;
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index d0a080747ec3..4721f58fe42c 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -51,7 +51,7 @@
ACPI_MODULE_NAME("evxfevnt")
/* Local prototypes */
-acpi_status
+static acpi_status
acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block, void *context);
@@ -785,7 +785,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
* block device. NULL if the GPE is one of the FADT-defined GPEs.
*
******************************************************************************/
-acpi_status
+static acpi_status
acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block, void *context)
{
diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c
index d301c1f363ef..d7cb030a21f8 100644
--- a/drivers/acpi/acpica/exmutex.c
+++ b/drivers/acpi/acpica/exmutex.c
@@ -373,11 +373,12 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
walk_state->thread->thread_id)
&& (obj_desc != acpi_gbl_global_lock_mutex)) {
ACPI_ERROR((AE_INFO,
- "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX",
- (unsigned long)walk_state->thread->thread_id,
+ "Thread %p cannot release Mutex [%4.4s] acquired by thread %p",
+ ACPI_CAST_PTR(void, walk_state->thread->thread_id),
acpi_ut_get_node_name(obj_desc->mutex.node),
- (unsigned long)obj_desc->mutex.owner_thread->
- thread_id));
+ ACPI_CAST_PTR(void,
+ obj_desc->mutex.owner_thread->
+ thread_id)));
return_ACPI_STATUS(AE_AML_NOT_OWNER);
}
diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c
index 7b2fb602b5cb..23d5505cb1f7 100644
--- a/drivers/acpi/acpica/hwregs.c
+++ b/drivers/acpi/acpica/hwregs.c
@@ -81,9 +81,9 @@ acpi_status acpi_hw_clear_acpi_status(void)
ACPI_FUNCTION_TRACE(hw_clear_acpi_status);
- ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %0llX\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n",
ACPI_BITMASK_ALL_FIXED_STATUS,
- acpi_gbl_xpm1a_status.address));
+ ACPI_FORMAT_UINT64(acpi_gbl_xpm1a_status.address)));
lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c
index baa5fc05e124..db307a356f08 100644
--- a/drivers/acpi/acpica/hwsleep.c
+++ b/drivers/acpi/acpica/hwsleep.c
@@ -211,6 +211,12 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)
+static unsigned int gts, bfs;
+module_param(gts, uint, 0644);
+module_param(bfs, uint, 0644);
+MODULE_PARM_DESC(gts, "Enable evaluation of _GTS on suspend.");
+MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".);
+
/*******************************************************************************
*
* FUNCTION: acpi_enter_sleep_state
@@ -278,16 +284,18 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
return_ACPI_STATUS(status);
}
- /* Execute the _GTS method */
+ if (gts) {
+ /* Execute the _GTS method */
- arg_list.count = 1;
- arg_list.pointer = &arg;
- arg.type = ACPI_TYPE_INTEGER;
- arg.integer.value = sleep_state;
+ arg_list.count = 1;
+ arg_list.pointer = &arg;
+ arg.type = ACPI_TYPE_INTEGER;
+ arg.integer.value = sleep_state;
- status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL);
- if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
- return_ACPI_STATUS(status);
+ status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ return_ACPI_STATUS(status);
+ }
}
/* Get current value of PM1A control */
@@ -513,18 +521,19 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state)
}
}
- /* Execute the _BFS method */
+ if (bfs) {
+ /* Execute the _BFS method */
- arg_list.count = 1;
- arg_list.pointer = &arg;
- arg.type = ACPI_TYPE_INTEGER;
- arg.integer.value = sleep_state;
+ arg_list.count = 1;
+ arg_list.pointer = &arg;
+ arg.type = ACPI_TYPE_INTEGER;
+ arg.integer.value = sleep_state;
- status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL);
- if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
- ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS"));
+ status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS"));
+ }
}
-
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c
index 7737afb157c3..ec33f270c5b7 100644
--- a/drivers/acpi/acpica/hwvalid.c
+++ b/drivers/acpi/acpica/hwvalid.c
@@ -90,6 +90,7 @@ static const struct acpi_port_info acpi_protected_ports[] = {
{"PIT2", 0x0048, 0x004B, ACPI_OSI_WIN_XP},
{"RTC", 0x0070, 0x0071, ACPI_OSI_WIN_XP},
{"CMOS", 0x0074, 0x0076, ACPI_OSI_WIN_XP},
+ {"DMA1", 0x0081, 0x0083, ACPI_OSI_WIN_XP},
{"DMA1L", 0x0087, 0x0087, ACPI_OSI_WIN_XP},
{"DMA2", 0x0089, 0x008B, ACPI_OSI_WIN_XP},
{"DMA2L", 0x008F, 0x008F, ACPI_OSI_WIN_XP},
@@ -151,7 +152,7 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
ACPI_ERROR((AE_INFO,
"Illegal I/O port address/length above 64K: 0x%p/%X",
ACPI_CAST_PTR(void, address), byte_width));
- return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS);
+ return_ACPI_STATUS(AE_LIMIT);
}
/* Exit if requested address is not within the protected port table */
@@ -178,11 +179,12 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
/* Port illegality may depend on the _OSI calls made by the BIOS */
if (acpi_gbl_osi_data >= port_info->osi_dependency) {
- ACPI_ERROR((AE_INFO,
- "Denied AML access to port 0x%p/%X (%s 0x%.4X-0x%.4X)",
- ACPI_CAST_PTR(void, address),
- byte_width, port_info->name,
- port_info->start, port_info->end));
+ ACPI_DEBUG_PRINT((ACPI_DB_IO,
+ "Denied AML access to port 0x%p/%X (%s 0x%.4X-0x%.4X)",
+ ACPI_CAST_PTR(void, address),
+ byte_width, port_info->name,
+ port_info->start,
+ port_info->end));
return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS);
}
@@ -206,7 +208,7 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
* Value Where value is placed
* Width Number of bits
*
- * RETURN: Value read from port
+ * RETURN: Status and value read from port
*
* DESCRIPTION: Read data from an I/O port or register. This is a front-end
* to acpi_os_read_port that performs validation on both the port
@@ -217,14 +219,43 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width)
{
acpi_status status;
+ u32 one_byte;
+ u32 i;
+
+ /* Validate the entire request and perform the I/O */
status = acpi_hw_validate_io_request(address, width);
- if (ACPI_FAILURE(status)) {
+ if (ACPI_SUCCESS(status)) {
+ status = acpi_os_read_port(address, value, width);
return status;
}
- status = acpi_os_read_port(address, value, width);
- return status;
+ if (status != AE_AML_ILLEGAL_ADDRESS) {
+ return status;
+ }
+
+ /*
+ * There has been a protection violation within the request. Fall
+ * back to byte granularity port I/O and ignore the failing bytes.
+ * This provides Windows compatibility.
+ */
+ for (i = 0, *value = 0; i < width; i += 8) {
+
+ /* Validate and read one byte */
+
+ if (acpi_hw_validate_io_request(address, 8) == AE_OK) {
+ status = acpi_os_read_port(address, &one_byte, 8);
+ if (ACPI_FAILURE(status)) {
+ return status;
+ }
+
+ *value |= (one_byte << i);
+ }
+
+ address++;
+ }
+
+ return AE_OK;
}
/******************************************************************************
@@ -235,7 +266,7 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width)
* Value Value to write
* Width Number of bits
*
- * RETURN: None
+ * RETURN: Status
*
* DESCRIPTION: Write data to an I/O port or register. This is a front-end
* to acpi_os_write_port that performs validation on both the port
@@ -246,12 +277,39 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width)
acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width)
{
acpi_status status;
+ u32 i;
+
+ /* Validate the entire request and perform the I/O */
status = acpi_hw_validate_io_request(address, width);
- if (ACPI_FAILURE(status)) {
+ if (ACPI_SUCCESS(status)) {
+ status = acpi_os_write_port(address, value, width);
return status;
}
- status = acpi_os_write_port(address, value, width);
- return status;
+ if (status != AE_AML_ILLEGAL_ADDRESS) {
+ return status;
+ }
+
+ /*
+ * There has been a protection violation within the request. Fall
+ * back to byte granularity port I/O and ignore the failing bytes.
+ * This provides Windows compatibility.
+ */
+ for (i = 0; i < width; i += 8) {
+
+ /* Validate and write one byte */
+
+ if (acpi_hw_validate_io_request(address, 8) == AE_OK) {
+ status =
+ acpi_os_write_port(address, (value >> i) & 0xFF, 8);
+ if (ACPI_FAILURE(status)) {
+ return status;
+ }
+ }
+
+ address++;
+ }
+
+ return AE_OK;
}
diff --git a/drivers/acpi/acpica/nsnames.c b/drivers/acpi/acpica/nsnames.c
index ae3dc10a7e81..af8e6bcee07e 100644
--- a/drivers/acpi/acpica/nsnames.c
+++ b/drivers/acpi/acpica/nsnames.c
@@ -149,7 +149,7 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
name_buffer = ACPI_ALLOCATE_ZEROED(size);
if (!name_buffer) {
- ACPI_ERROR((AE_INFO, "Allocation failure"));
+ ACPI_ERROR((AE_INFO, "Could not allocate %u bytes", (u32)size));
return_PTR(NULL);
}
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c
index d9e8cbc6e679..7f8e066b12a3 100644
--- a/drivers/acpi/acpica/nspredef.c
+++ b/drivers/acpi/acpica/nspredef.c
@@ -144,7 +144,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
pathname = acpi_ns_get_external_pathname(node);
if (!pathname) {
- pathname = ACPI_CAST_PTR(char, predefined->info.name);
+ return AE_OK; /* Could not get pathname, ignore */
}
/*
@@ -230,10 +230,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
}
exit:
- if (pathname != predefined->info.name) {
- ACPI_FREE(pathname);
- }
-
+ ACPI_FREE(pathname);
return (status);
}
diff --git a/drivers/acpi/acpica/nssearch.c b/drivers/acpi/acpica/nssearch.c
index f9b4f51bf8f2..7e865639a928 100644
--- a/drivers/acpi/acpica/nssearch.c
+++ b/drivers/acpi/acpica/nssearch.c
@@ -45,6 +45,10 @@
#include "accommon.h"
#include "acnamesp.h"
+#ifdef ACPI_ASL_COMPILER
+#include "amlcode.h"
+#endif
+
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nssearch")
diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c
index b6667ff059e5..d3f77a5df79d 100644
--- a/drivers/acpi/acpica/rscalc.c
+++ b/drivers/acpi/acpica/rscalc.c
@@ -543,6 +543,13 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
package_element = *top_object_list;
+ /* We must have a valid Package object */
+
+ if (!package_element ||
+ (package_element->common.type != ACPI_TYPE_PACKAGE)) {
+ return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ }
+
/*
* The sub_object_list will now point to an array of the
* four IRQ elements: Address, Pin, Source and source_index
@@ -586,9 +593,6 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
} else {
temp_size_needed +=
acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
- if (!temp_size_needed) {
- return_ACPI_STATUS(AE_BAD_PARAMETER);
- }
}
} else {
/*
diff --git a/drivers/acpi/acpica/rscreate.c b/drivers/acpi/acpica/rscreate.c
index 663f692fffcf..a3c23d686d5f 100644
--- a/drivers/acpi/acpica/rscreate.c
+++ b/drivers/acpi/acpica/rscreate.c
@@ -191,8 +191,6 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);
for (index = 0; index < number_of_elements; index++) {
- int source_name_index = 2;
- int source_index_index = 3;
/*
* Point user_prt past this current structure
@@ -261,27 +259,6 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
return_ACPI_STATUS(AE_BAD_DATA);
}
- /*
- * If BIOS erroneously reversed the _PRT source_name and source_index,
- * then reverse them back.
- */
- if ((sub_object_list[3])->common.type !=
- ACPI_TYPE_INTEGER) {
- if (acpi_gbl_enable_interpreter_slack) {
- source_name_index = 3;
- source_index_index = 2;
- printk(KERN_WARNING
- "ACPI: Handling Garbled _PRT entry\n");
- } else {
- ACPI_ERROR((AE_INFO,
- "(PRT[%X].source_index) Need Integer, found %s",
- index,
- acpi_ut_get_object_type_name
- (sub_object_list[3])));
- return_ACPI_STATUS(AE_BAD_DATA);
- }
- }
-
user_prt->pin = (u32) obj_desc->integer.value;
/*
@@ -304,7 +281,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
* 3) Third subobject: Dereference the PRT.source_name
* The name may be unresolved (slack mode), so allow a null object
*/
- obj_desc = sub_object_list[source_name_index];
+ obj_desc = sub_object_list[2];
if (obj_desc) {
switch (obj_desc->common.type) {
case ACPI_TYPE_LOCAL_REFERENCE:
@@ -378,7 +355,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
/* 4) Fourth subobject: Dereference the PRT.source_index */
- obj_desc = sub_object_list[source_index_index];
+ obj_desc = sub_object_list[3];
if (obj_desc->common.type != ACPI_TYPE_INTEGER) {
ACPI_ERROR((AE_INFO,
"(PRT[%X].SourceIndex) Need Integer, found %s",
diff --git a/drivers/acpi/acpica/rsxface.c b/drivers/acpi/acpica/rsxface.c
index 69a2aa5b5d83..395212bcd19b 100644
--- a/drivers/acpi/acpica/rsxface.c
+++ b/drivers/acpi/acpica/rsxface.c
@@ -338,13 +338,17 @@ acpi_resource_to_address64(struct acpi_resource *resource,
switch (resource->type) {
case ACPI_RESOURCE_TYPE_ADDRESS16:
- address16 = (struct acpi_resource_address16 *)&resource->data;
+ address16 =
+ ACPI_CAST_PTR(struct acpi_resource_address16,
+ &resource->data);
ACPI_COPY_ADDRESS(out, address16);
break;
case ACPI_RESOURCE_TYPE_ADDRESS32:
- address32 = (struct acpi_resource_address32 *)&resource->data;
+ address32 =
+ ACPI_CAST_PTR(struct acpi_resource_address32,
+ &resource->data);
ACPI_COPY_ADDRESS(out, address32);
break;
diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c
index 71e655d14cb0..82b02dcb942e 100644
--- a/drivers/acpi/acpica/tbfadt.c
+++ b/drivers/acpi/acpica/tbfadt.c
@@ -284,9 +284,9 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
if (length > sizeof(struct acpi_table_fadt)) {
ACPI_WARNING((AE_INFO,
"FADT (revision %u) is longer than ACPI 2.0 version, "
- "truncating length 0x%X to 0x%zX",
- table->revision, (unsigned)length,
- sizeof(struct acpi_table_fadt)));
+ "truncating length 0x%X to 0x%X",
+ table->revision, length,
+ (u32)sizeof(struct acpi_table_fadt)));
}
/* Clear the entire local FADT */
@@ -441,7 +441,7 @@ static void acpi_tb_convert_fadt(void)
&acpi_gbl_FADT,
fadt_info_table
[i].length),
- address32);
+ (u64) address32);
}
}
}
@@ -469,7 +469,6 @@ static void acpi_tb_convert_fadt(void)
static void acpi_tb_validate_fadt(void)
{
char *name;
- u32 *address32;
struct acpi_generic_address *address64;
u8 length;
u32 i;
@@ -505,15 +504,12 @@ static void acpi_tb_validate_fadt(void)
for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
/*
- * Generate pointers to the 32-bit and 64-bit addresses, get the
- * register length (width), and the register name
+ * Generate pointer to the 64-bit address, get the register
+ * length (width) and the register name
*/
address64 = ACPI_ADD_PTR(struct acpi_generic_address,
&acpi_gbl_FADT,
fadt_info_table[i].address64);
- address32 =
- ACPI_ADD_PTR(u32, &acpi_gbl_FADT,
- fadt_info_table[i].address32);
length =
*ACPI_ADD_PTR(u8, &acpi_gbl_FADT,
fadt_info_table[i].length);
diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c
index f865d5a096de..63e82329a9e8 100644
--- a/drivers/acpi/acpica/tbinstal.c
+++ b/drivers/acpi/acpica/tbinstal.c
@@ -472,7 +472,7 @@ acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index)
* lock may block, and also since the execution of a namespace walk
* must be allowed to use the interpreter.
*/
- acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
+ (void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock);
acpi_ns_delete_namespace_by_owner(owner_id);
diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c
index 919624f123d5..0f0c64bf8ac9 100644
--- a/drivers/acpi/acpica/utcopy.c
+++ b/drivers/acpi/acpica/utcopy.c
@@ -676,6 +676,7 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
{
u16 reference_count;
union acpi_operand_object *next_object;
+ acpi_status status;
/* Save fields from destination that we don't want to overwrite */
@@ -768,6 +769,28 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
}
break;
+ /*
+ * For Mutex and Event objects, we cannot simply copy the underlying
+ * OS object. We must create a new one.
+ */
+ case ACPI_TYPE_MUTEX:
+
+ status = acpi_os_create_mutex(&dest_desc->mutex.os_mutex);
+ if (ACPI_FAILURE(status)) {
+ return status;
+ }
+ break;
+
+ case ACPI_TYPE_EVENT:
+
+ status = acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0,
+ &dest_desc->event.
+ os_semaphore);
+ if (ACPI_FAILURE(status)) {
+ return status;
+ }
+ break;
+
default:
/* Nothing to do for other simple objects */
break;
diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c
index 38821f53042c..527d729f6815 100644
--- a/drivers/acpi/acpica/utdebug.c
+++ b/drivers/acpi/acpica/utdebug.c
@@ -179,9 +179,9 @@ acpi_debug_print(u32 requested_debug_level,
if (thread_id != acpi_gbl_prev_thread_id) {
if (ACPI_LV_THREADS & acpi_dbg_level) {
acpi_os_printf
- ("\n**** Context Switch from TID %lX to TID %lX ****\n\n",
- (unsigned long)acpi_gbl_prev_thread_id,
- (unsigned long)thread_id);
+ ("\n**** Context Switch from TID %p to TID %p ****\n\n",
+ ACPI_CAST_PTR(void, acpi_gbl_prev_thread_id),
+ ACPI_CAST_PTR(void, thread_id));
}
acpi_gbl_prev_thread_id = thread_id;
@@ -194,7 +194,7 @@ acpi_debug_print(u32 requested_debug_level,
acpi_os_printf("%8s-%04ld ", module_name, line_number);
if (ACPI_LV_THREADS & acpi_dbg_level) {
- acpi_os_printf("[%04lX] ", (unsigned long)thread_id);
+ acpi_os_printf("[%p] ", ACPI_CAST_PTR(void, thread_id));
}
acpi_os_printf("[%02ld] %-22.22s: ",
diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c
index 1c9e250caefb..fbe782348b0b 100644
--- a/drivers/acpi/acpica/utmisc.c
+++ b/drivers/acpi/acpica/utmisc.c
@@ -1033,11 +1033,12 @@ acpi_error(const char *module_name, u32 line_number, const char *format, ...)
{
va_list args;
- acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number);
+ acpi_os_printf("ACPI Error: ");
va_start(args, format);
acpi_os_vprintf(format, args);
- acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
+ acpi_os_printf(" %8.8X %s-%u\n", ACPI_CA_VERSION, module_name,
+ line_number);
va_end(args);
}
@@ -1047,12 +1048,12 @@ acpi_exception(const char *module_name,
{
va_list args;
- acpi_os_printf("ACPI Exception (%s-%04d): %s, ", module_name,
- line_number, acpi_format_exception(status));
+ acpi_os_printf("ACPI Exception: %s, ", acpi_format_exception(status));
va_start(args, format);
acpi_os_vprintf(format, args);
- acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
+ acpi_os_printf(" %8.8X %s-%u\n", ACPI_CA_VERSION, module_name,
+ line_number);
va_end(args);
}
@@ -1061,11 +1062,12 @@ acpi_warning(const char *module_name, u32 line_number, const char *format, ...)
{
va_list args;
- acpi_os_printf("ACPI Warning (%s-%04d): ", module_name, line_number);
+ acpi_os_printf("ACPI Warning: ");
va_start(args, format);
acpi_os_vprintf(format, args);
- acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
+ acpi_os_printf(" %8.8X %s-%u\n", ACPI_CA_VERSION, module_name,
+ line_number);
va_end(args);
}
@@ -1074,10 +1076,6 @@ acpi_info(const char *module_name, u32 line_number, const char *format, ...)
{
va_list args;
- /*
- * Removed module_name, line_number, and acpica version, not needed
- * for info output
- */
acpi_os_printf("ACPI: ");
va_start(args, format);
diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c
index 26c93a748e64..80bb65154117 100644
--- a/drivers/acpi/acpica/utmutex.c
+++ b/drivers/acpi/acpica/utmutex.c
@@ -230,17 +230,18 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
if (i == mutex_id) {
ACPI_ERROR((AE_INFO,
- "Mutex [%s] already acquired by this thread [%X]",
+ "Mutex [%s] already acquired by this thread [%p]",
acpi_ut_get_mutex_name
(mutex_id),
- this_thread_id));
+ ACPI_CAST_PTR(void,
+ this_thread_id)));
return (AE_ALREADY_ACQUIRED);
}
ACPI_ERROR((AE_INFO,
- "Invalid acquire order: Thread %X owns [%s], wants [%s]",
- this_thread_id,
+ "Invalid acquire order: Thread %p owns [%s], wants [%s]",
+ ACPI_CAST_PTR(void, this_thread_id),
acpi_ut_get_mutex_name(i),
acpi_ut_get_mutex_name(mutex_id)));
@@ -251,24 +252,24 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
#endif
ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
- "Thread %lX attempting to acquire Mutex [%s]\n",
- (unsigned long)this_thread_id,
+ "Thread %p attempting to acquire Mutex [%s]\n",
+ ACPI_CAST_PTR(void, this_thread_id),
acpi_ut_get_mutex_name(mutex_id)));
status = acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex,
ACPI_WAIT_FOREVER);
if (ACPI_SUCCESS(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
- "Thread %lX acquired Mutex [%s]\n",
- (unsigned long)this_thread_id,
+ "Thread %p acquired Mutex [%s]\n",
+ ACPI_CAST_PTR(void, this_thread_id),
acpi_ut_get_mutex_name(mutex_id)));
acpi_gbl_mutex_info[mutex_id].use_count++;
acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id;
} else {
ACPI_EXCEPTION((AE_INFO, status,
- "Thread %lX could not acquire Mutex [%X]",
- (unsigned long)this_thread_id, mutex_id));
+ "Thread %p could not acquire Mutex [%X]",
+ ACPI_CAST_PTR(void, this_thread_id), mutex_id));
}
return (status);
@@ -293,9 +294,8 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
ACPI_FUNCTION_NAME(ut_release_mutex);
this_thread_id = acpi_os_get_thread_id();
- ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
- "Thread %lX releasing Mutex [%s]\n",
- (unsigned long)this_thread_id,
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %p releasing Mutex [%s]\n",
+ ACPI_CAST_PTR(void, this_thread_id),
acpi_ut_get_mutex_name(mutex_id)));
if (mutex_id > ACPI_MAX_MUTEX) {
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index e8f7b64e92da..ae862f1798dc 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -312,7 +312,7 @@ int acpi_bus_set_power(acpi_handle handle, int state)
end:
if (result)
printk(KERN_WARNING PREFIX
- "Transitioning device [%s] to D%d\n",
+ "Device [%s] failed to transition to D%d\n",
device->pnp.bus_id, state);
else {
device->power.state = state;
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index d73c94b8441d..9195deba9d94 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -1,5 +1,5 @@
/*
- * acpi_button.c - ACPI Button Driver ($Revision: 30 $)
+ * button.c - ACPI Button Driver
*
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -41,17 +41,13 @@
#define ACPI_BUTTON_SUBCLASS_POWER "power"
#define ACPI_BUTTON_HID_POWER "PNP0C0C"
-#define ACPI_BUTTON_DEVICE_NAME_POWER "Power Button (CM)"
-#define ACPI_BUTTON_DEVICE_NAME_POWERF "Power Button (FF)"
+#define ACPI_BUTTON_DEVICE_NAME_POWER "Power Button"
#define ACPI_BUTTON_TYPE_POWER 0x01
-#define ACPI_BUTTON_TYPE_POWERF 0x02
#define ACPI_BUTTON_SUBCLASS_SLEEP "sleep"
#define ACPI_BUTTON_HID_SLEEP "PNP0C0E"
-#define ACPI_BUTTON_DEVICE_NAME_SLEEP "Sleep Button (CM)"
-#define ACPI_BUTTON_DEVICE_NAME_SLEEPF "Sleep Button (FF)"
+#define ACPI_BUTTON_DEVICE_NAME_SLEEP "Sleep Button"
#define ACPI_BUTTON_TYPE_SLEEP 0x03
-#define ACPI_BUTTON_TYPE_SLEEPF 0x04
#define ACPI_BUTTON_SUBCLASS_LID "lid"
#define ACPI_BUTTON_HID_LID "PNP0C0D"
@@ -95,7 +91,6 @@ static struct acpi_driver acpi_button_driver = {
};
struct acpi_button {
- struct acpi_device *device; /* Fixed button kludge */
unsigned int type;
struct input_dev *input;
char phys[32]; /* for input device */
@@ -126,14 +121,10 @@ static struct proc_dir_entry *acpi_button_dir;
static int acpi_button_info_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_button *button = seq->private;
-
- if (!button || !button->device)
- return 0;
+ struct acpi_device *device = seq->private;
seq_printf(seq, "type: %s\n",
- acpi_device_name(button->device));
-
+ acpi_device_name(device));
return 0;
}
@@ -144,14 +135,11 @@ static int acpi_button_info_open_fs(struct inode *inode, struct file *file)
static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_button *button = seq->private;
+ struct acpi_device *device = seq->private;
acpi_status status;
unsigned long long state;
- if (!button || !button->device)
- return 0;
-
- status = acpi_evaluate_integer(button->device->handle, "_LID", NULL, &state);
+ status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state);
seq_printf(seq, "state: %s\n",
ACPI_FAILURE(status) ? "unsupported" :
(state ? "open" : "closed"));
@@ -169,24 +157,17 @@ static struct proc_dir_entry *acpi_lid_dir;
static int acpi_button_add_fs(struct acpi_device *device)
{
+ struct acpi_button *button = acpi_driver_data(device);
struct proc_dir_entry *entry = NULL;
- struct acpi_button *button;
-
- if (!device || !acpi_driver_data(device))
- return -EINVAL;
-
- button = acpi_driver_data(device);
switch (button->type) {
case ACPI_BUTTON_TYPE_POWER:
- case ACPI_BUTTON_TYPE_POWERF:
if (!acpi_power_dir)
acpi_power_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER,
acpi_button_dir);
entry = acpi_power_dir;
break;
case ACPI_BUTTON_TYPE_SLEEP:
- case ACPI_BUTTON_TYPE_SLEEPF:
if (!acpi_sleep_dir)
acpi_sleep_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP,
acpi_button_dir);
@@ -210,8 +191,7 @@ static int acpi_button_add_fs(struct acpi_device *device)
/* 'info' [R] */
entry = proc_create_data(ACPI_BUTTON_FILE_INFO,
S_IRUGO, acpi_device_dir(device),
- &acpi_button_info_fops,
- acpi_driver_data(device));
+ &acpi_button_info_fops, device);
if (!entry)
return -ENODEV;
@@ -219,8 +199,7 @@ static int acpi_button_add_fs(struct acpi_device *device)
if (button->type == ACPI_BUTTON_TYPE_LID) {
entry = proc_create_data(ACPI_BUTTON_FILE_STATE,
S_IRUGO, acpi_device_dir(device),
- &acpi_button_state_fops,
- acpi_driver_data(device));
+ &acpi_button_state_fops, device);
if (!entry)
return -ENODEV;
}
@@ -250,15 +229,16 @@ static int acpi_button_remove_fs(struct acpi_device *device)
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
-static int acpi_lid_send_state(struct acpi_button *button)
+static int acpi_lid_send_state(struct acpi_device *device)
{
+ struct acpi_button *button = acpi_driver_data(device);
unsigned long long state;
acpi_status status;
- status = acpi_evaluate_integer(button->device->handle, "_LID", NULL,
- &state);
+ status = acpi_evaluate_integer(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);
input_sync(button->input);
@@ -270,9 +250,6 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
struct acpi_button *button = acpi_driver_data(device);
struct input_dev *input;
- if (!button || !button->device)
- return;
-
switch (event) {
case ACPI_FIXED_HARDWARE_EVENT:
event = ACPI_BUTTON_NOTIFY_STATUS;
@@ -280,7 +257,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
case ACPI_BUTTON_NOTIFY_STATUS:
input = button->input;
if (button->type == ACPI_BUTTON_TYPE_LID) {
- acpi_lid_send_state(button);
+ acpi_lid_send_state(device);
} else {
int keycode = test_bit(KEY_SLEEP, input->keybit) ?
KEY_SLEEP : KEY_POWER;
@@ -291,43 +268,35 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
input_sync(input);
}
- acpi_bus_generate_proc_event(button->device, event,
- ++button->pushed);
+ acpi_bus_generate_proc_event(device, event, ++button->pushed);
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Unsupported event [0x%x]\n", event));
break;
}
-
- return;
}
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);
+ struct acpi_button *button = acpi_driver_data(device);
+
+ if (button->type == ACPI_BUTTON_TYPE_LID)
+ return acpi_lid_send_state(device);
return 0;
}
static int acpi_button_add(struct acpi_device *device)
{
- int error;
struct acpi_button *button;
struct input_dev *input;
-
- if (!device)
- return -EINVAL;
+ char *hid, *name, *class;
+ int error;
button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL);
if (!button)
return -ENOMEM;
- button->device = device;
device->driver_data = button;
button->input = input = input_allocate_device();
@@ -336,40 +305,29 @@ static int acpi_button_add(struct acpi_device *device)
goto err_free_button;
}
- /*
- * Determine the button type (via hid), as fixed-feature buttons
- * need to be handled a bit differently than generic-space.
- */
- if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWER)) {
+ hid = acpi_device_hid(device);
+ name = acpi_device_name(device);
+ class = acpi_device_class(device);
+
+ if (!strcmp(hid, ACPI_BUTTON_HID_POWER) ||
+ !strcmp(hid, ACPI_BUTTON_HID_POWERF)) {
button->type = ACPI_BUTTON_TYPE_POWER;
- strcpy(acpi_device_name(device), ACPI_BUTTON_DEVICE_NAME_POWER);
- sprintf(acpi_device_class(device), "%s/%s",
- ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
- } else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWERF)) {
- button->type = ACPI_BUTTON_TYPE_POWERF;
- strcpy(acpi_device_name(device),
- ACPI_BUTTON_DEVICE_NAME_POWERF);
- sprintf(acpi_device_class(device), "%s/%s",
+ strcpy(name, ACPI_BUTTON_DEVICE_NAME_POWER);
+ sprintf(class, "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
- } else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEP)) {
+ } else if (!strcmp(hid, ACPI_BUTTON_HID_SLEEP) ||
+ !strcmp(hid, ACPI_BUTTON_HID_SLEEPF)) {
button->type = ACPI_BUTTON_TYPE_SLEEP;
- strcpy(acpi_device_name(device), ACPI_BUTTON_DEVICE_NAME_SLEEP);
- sprintf(acpi_device_class(device), "%s/%s",
- ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
- } else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEPF)) {
- button->type = ACPI_BUTTON_TYPE_SLEEPF;
- strcpy(acpi_device_name(device),
- ACPI_BUTTON_DEVICE_NAME_SLEEPF);
- sprintf(acpi_device_class(device), "%s/%s",
+ strcpy(name, ACPI_BUTTON_DEVICE_NAME_SLEEP);
+ sprintf(class, "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
- } else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_LID)) {
+ } else if (!strcmp(hid, ACPI_BUTTON_HID_LID)) {
button->type = ACPI_BUTTON_TYPE_LID;
- strcpy(acpi_device_name(device), ACPI_BUTTON_DEVICE_NAME_LID);
- sprintf(acpi_device_class(device), "%s/%s",
+ strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
+ sprintf(class, "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
} else {
- printk(KERN_ERR PREFIX "Unsupported hid [%s]\n",
- acpi_device_hid(device));
+ printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
error = -ENODEV;
goto err_free_input;
}
@@ -378,10 +336,9 @@ static int acpi_button_add(struct acpi_device *device)
if (error)
goto err_free_input;
- snprintf(button->phys, sizeof(button->phys),
- "%s/button/input0", acpi_device_hid(device));
+ snprintf(button->phys, sizeof(button->phys), "%s/button/input0", hid);
- input->name = acpi_device_name(device);
+ input->name = name;
input->phys = button->phys;
input->id.bustype = BUS_HOST;
input->id.product = button->type;
@@ -389,13 +346,11 @@ 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_MASK(EV_KEY);
set_bit(KEY_POWER, input->keybit);
break;
case ACPI_BUTTON_TYPE_SLEEP:
- case ACPI_BUTTON_TYPE_SLEEPF:
input->evbit[0] = BIT_MASK(EV_KEY);
set_bit(KEY_SLEEP, input->keybit);
break;
@@ -410,7 +365,7 @@ static int acpi_button_add(struct acpi_device *device)
if (error)
goto err_remove_fs;
if (button->type == ACPI_BUTTON_TYPE_LID)
- acpi_lid_send_state(button);
+ acpi_lid_send_state(device);
if (device->wakeup.flags.valid) {
/* Button's GPE is run-wake GPE */
@@ -422,9 +377,7 @@ static int acpi_button_add(struct acpi_device *device)
device->wakeup.state.enabled = 1;
}
- printk(KERN_INFO PREFIX "%s [%s]\n",
- acpi_device_name(device), acpi_device_bid(device));
-
+ printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device));
return 0;
err_remove_fs:
@@ -438,17 +391,11 @@ static int acpi_button_add(struct acpi_device *device)
static int acpi_button_remove(struct acpi_device *device, int type)
{
- struct acpi_button *button;
-
- if (!device || !acpi_driver_data(device))
- return -EINVAL;
-
- button = acpi_driver_data(device);
+ struct acpi_button *button = acpi_driver_data(device);
acpi_button_remove_fs(device);
input_unregister_device(button->input);
kfree(button);
-
return 0;
}
@@ -459,6 +406,7 @@ static int __init acpi_button_init(void)
acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
if (!acpi_button_dir)
return -ENODEV;
+
result = acpi_bus_register_driver(&acpi_button_driver);
if (result < 0) {
remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 04e90443eff7..391f331674c7 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -1065,6 +1065,7 @@ static int acpi_ec_resume(struct acpi_device *device)
struct acpi_ec *ec = acpi_driver_data(device);
/* Enable use of GPE back */
clear_bit(EC_FLAGS_NO_GPE, &ec->flags);
+ set_bit(EC_FLAGS_GPE_MODE, &ec->flags);
acpi_enable_gpe(NULL, ec->gpe);
return 0;
}
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index d59f08ecaf16..d916bea729f1 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -353,8 +353,10 @@ static irqreturn_t acpi_irq(int irq, void *dev_id)
if (handled) {
acpi_irq_handled++;
return IRQ_HANDLED;
- } else
+ } else {
+ acpi_irq_not_handled++;
return IRQ_NONE;
+ }
}
acpi_status
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 51b9f8280f88..2faa9e2ac893 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -401,7 +401,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
/* Interrupt Line values above 0xF are forbidden */
if (dev->irq > 0 && (dev->irq <= 0xF)) {
printk(" - using IRQ %d\n", dev->irq);
- acpi_register_gsi(dev->irq, ACPI_LEVEL_SENSITIVE,
+ acpi_register_gsi(&dev->dev, dev->irq,
+ ACPI_LEVEL_SENSITIVE,
ACPI_ACTIVE_LOW);
return 0;
} else {
@@ -410,7 +411,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
}
}
- rc = acpi_register_gsi(gsi, triggering, polarity);
+ rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
if (rc < 0) {
dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
pin_name(pin));
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 6fe121434ffb..afa5c0341e5d 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -202,15 +202,41 @@ static void acpi_state_timer_broadcast(struct acpi_processor *pr,
* Suspend / resume control
*/
static int acpi_idle_suspend;
+static u32 saved_bm_rld;
+
+static void acpi_idle_bm_rld_save(void)
+{
+ acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_RLD, &saved_bm_rld);
+ printk(KERN_NOTICE PREFIX "saved: BM_RLD %u\n", saved_bm_rld);
+}
+static void acpi_idle_bm_rld_restore(void)
+{
+ u32 resumed_bm_rld;
+
+ acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_RLD, &resumed_bm_rld);
+ printk(KERN_NOTICE PREFIX "resumed: BM_RLD %u\n", resumed_bm_rld);
+ if (resumed_bm_rld != saved_bm_rld) {
+ printk(KERN_WARNING PREFIX "restored BM_RLD %u\n", saved_bm_rld);
+ acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, saved_bm_rld);
+ }
+}
int acpi_processor_suspend(struct acpi_device * device, pm_message_t state)
{
+ if (acpi_idle_suspend == 1)
+ return 0;
+
+ acpi_idle_bm_rld_save();
acpi_idle_suspend = 1;
return 0;
}
int acpi_processor_resume(struct acpi_device * device)
{
+ if (acpi_idle_suspend == 0)
+ return 0;
+
+ acpi_idle_bm_rld_restore();
acpi_idle_suspend = 0;
return 0;
}
@@ -581,6 +607,11 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
struct acpi_processor_cx *cx = &pr->power.states[i];
+#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86)
+ /* TSC could halt in idle, so notify users */
+ if (tsc_halts_in_c(cx->type))
+ mark_tsc_unstable("TSC halts in idle");;
+#endif
switch (cx->type) {
case ACPI_STATE_C1:
cx->valid = 1;
@@ -657,11 +688,9 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
seq_printf(seq, "active state: C%zd\n"
"max_cstate: C%d\n"
- "bus master activity: %08x\n"
"maximum allowed latency: %d usec\n",
pr->power.state ? pr->power.state - pr->power.states : 0,
- max_cstate, (unsigned)pr->power.bm_activity,
- pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY));
+ max_cstate, pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY));
seq_puts(seq, "states:\n");
@@ -871,11 +900,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
kt2 = ktime_get_real();
idle_time = ktime_to_us(ktime_sub(kt2, kt1));
-#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86)
- /* TSC could halt in idle, so notify users */
- if (tsc_halts_in_c(cx->type))
- mark_tsc_unstable("TSC halts in idle");;
-#endif
sleep_ticks = us_to_pm_timer_ticks(idle_time);
/* Tell the scheduler how much we idled: */
@@ -955,6 +979,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
*/
acpi_state_timer_broadcast(pr, cx, 1);
+ kt1 = ktime_get_real();
/*
* disable bus master
* bm_check implies we need ARB_DIS
@@ -976,10 +1001,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
ACPI_FLUSH_CPU_CACHE();
}
- kt1 = ktime_get_real();
acpi_idle_do_entry(cx);
- kt2 = ktime_get_real();
- idle_time = ktime_to_us(ktime_sub(kt2, kt1));
/* Re-enable bus master arbitration */
if (pr->flags.bm_check && pr->flags.bm_control) {
@@ -988,12 +1010,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
c3_cpu_count--;
spin_unlock(&c3_lock);
}
+ kt2 = ktime_get_real();
+ idle_time = ktime_to_us(ktime_sub(kt2, kt1));
-#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86)
- /* TSC could halt in idle, so notify users */
- if (tsc_halts_in_c(ACPI_STATE_C3))
- mark_tsc_unstable("TSC halts in idle");
-#endif
sleep_ticks = us_to_pm_timer_ticks(idle_time);
/* Tell the scheduler how much we idled: */
sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS);
@@ -1037,6 +1056,9 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
dev->states[i].desc[0] = '\0';
}
+ if (max_cstate == 0)
+ max_cstate = 1;
+
for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {
cx = &pr->power.states[i];
state = &dev->states[count];
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index d0d1f4d50434..9b37dda58895 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -827,32 +827,22 @@ static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr)
return 0;
}
-static int acpi_processor_get_throttling(struct acpi_processor *pr)
+static long get_throttling(void *_pr)
{
- cpumask_var_t saved_mask;
- int ret;
+ struct acpi_processor *pr = _pr;
+
+ return pr->throttling.acpi_processor_get_throttling(pr);
+}
+static int acpi_processor_get_throttling(struct acpi_processor *pr)
+{
if (!pr)
return -EINVAL;
if (!pr->flags.throttling)
return -ENODEV;
- if (!alloc_cpumask_var(&saved_mask, GFP_KERNEL))
- return -ENOMEM;
-
- /*
- * Migrate task to the cpu pointed by pr.
- */
- cpumask_copy(saved_mask, &current->cpus_allowed);
- /* FIXME: use work_on_cpu() */
- set_cpus_allowed_ptr(current, cpumask_of(pr->id));
- ret = pr->throttling.acpi_processor_get_throttling(pr);
- /* restore the previous state */
- set_cpus_allowed_ptr(current, saved_mask);
- free_cpumask_var(saved_mask);
-
- return ret;
+ return work_on_cpu(pr->id, get_throttling, pr);
}
static int acpi_processor_get_fadt_info(struct acpi_processor *pr)
@@ -993,9 +983,22 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
return 0;
}
+struct set_throttling_info {
+ struct acpi_processor *pr;
+ struct acpi_processor_throttling *p_throttling;
+ int target_state;
+};
+
+static long set_throttling(void *_sti)
+{
+ struct set_throttling_info *s = _sti;
+
+ return s->p_throttling->acpi_processor_set_throttling(s->pr,
+ s->target_state);
+}
+
int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
{
- cpumask_var_t saved_mask;
int ret = 0;
unsigned int i;
struct acpi_processor *match_pr;
@@ -1012,15 +1015,9 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
if ((state < 0) || (state > (pr->throttling.state_count - 1)))
return -EINVAL;
- if (!alloc_cpumask_var(&saved_mask, GFP_KERNEL))
- return -ENOMEM;
-
- if (!alloc_cpumask_var(&online_throttling_cpus, GFP_KERNEL)) {
- free_cpumask_var(saved_mask);
+ if (!alloc_cpumask_var(&online_throttling_cpus, GFP_KERNEL))
return -ENOMEM;
- }
- cpumask_copy(saved_mask, &current->cpus_allowed);
t_state.target_state = state;
p_throttling = &(pr->throttling);
cpumask_and(online_throttling_cpus, cpu_online_mask,
@@ -1042,10 +1039,9 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
* it can be called only for the cpu pointed by pr.
*/
if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
- /* FIXME: use work_on_cpu() */
- set_cpus_allowed_ptr(current, cpumask_of(pr->id));
- ret = p_throttling->acpi_processor_set_throttling(pr,
- t_state.target_state);
+ struct set_throttling_info sti
+ = { pr, p_throttling, t_state.target_state };
+ ret = work_on_cpu(pr->id, set_throttling, &sti);
} else {
/*
* When the T-state coordination is SW_ALL or HW_ALL,
@@ -1053,6 +1049,8 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
* cpus.
*/
for_each_cpu(i, online_throttling_cpus) {
+ struct set_throttling_info sti;
+
match_pr = per_cpu(processors, i);
/*
* If the pointer is invalid, we will report the
@@ -1074,11 +1072,10 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
continue;
}
t_state.cpu = i;
- /* FIXME: use work_on_cpu() */
- set_cpus_allowed_ptr(current, cpumask_of(i));
- ret = match_pr->throttling.
- acpi_processor_set_throttling(
- match_pr, t_state.target_state);
+ sti.pr = match_pr;
+ sti.p_throttling = &match_pr->throttling;
+ sti.target_state = t_state.target_state;
+ ret = work_on_cpu(i, set_throttling, &sti);
}
}
/*
@@ -1092,11 +1089,6 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE,
&t_state);
}
- /* restore the previous state */
- /* FIXME: use work_on_cpu() */
- set_cpus_allowed_ptr(current, saved_mask);
- free_cpumask_var(online_throttling_cpus);
- free_cpumask_var(saved_mask);
return ret;
}
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 779e4e500df4..01574a066534 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -300,9 +300,9 @@ static int acpi_suspend_state_valid(suspend_state_t pm_state)
static struct platform_suspend_ops acpi_suspend_ops = {
.valid = acpi_suspend_state_valid,
.begin = acpi_suspend_begin,
- .prepare = acpi_pm_prepare,
+ .prepare_late = acpi_pm_prepare,
.enter = acpi_suspend_enter,
- .finish = acpi_pm_finish,
+ .wake = acpi_pm_finish,
.end = acpi_pm_end,
};
@@ -328,9 +328,9 @@ static int acpi_suspend_begin_old(suspend_state_t pm_state)
static struct platform_suspend_ops acpi_suspend_ops_old = {
.valid = acpi_suspend_state_valid,
.begin = acpi_suspend_begin_old,
- .prepare = acpi_pm_disable_gpes,
+ .prepare_late = acpi_pm_disable_gpes,
.enter = acpi_suspend_enter,
- .finish = acpi_pm_finish,
+ .wake = acpi_pm_finish,
.end = acpi_pm_end,
.recover = acpi_pm_finish,
};
@@ -713,6 +713,32 @@ static void acpi_power_off(void)
acpi_enter_sleep_state(ACPI_STATE_S5);
}
+/*
+ * ACPI 2.0 created the optional _GTS and _BFS,
+ * but industry adoption has been neither rapid nor broad.
+ *
+ * Linux gets into trouble when it executes poorly validated
+ * paths through the BIOS, so disable _GTS and _BFS by default,
+ * but do speak up and offer the option to enable them.
+ */
+void __init acpi_gts_bfs_check(void)
+{
+ acpi_handle dummy;
+
+ if (ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, METHOD_NAME__GTS, &dummy)))
+ {
+ printk(KERN_NOTICE PREFIX "BIOS offers _GTS\n");
+ printk(KERN_NOTICE PREFIX "If \"acpi.gts=1\" improves suspend, "
+ "please notify linux-acpi@vger.kernel.org\n");
+ }
+ if (ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, METHOD_NAME__BFS, &dummy)))
+ {
+ printk(KERN_NOTICE PREFIX "BIOS offers _BFS\n");
+ printk(KERN_NOTICE PREFIX "If \"acpi.bfs=1\" improves resume, "
+ "please notify linux-acpi@vger.kernel.org\n");
+ }
+}
+
int __init acpi_sleep_init(void)
{
acpi_status status;
@@ -771,5 +797,6 @@ int __init acpi_sleep_init(void)
* object can also be evaluated when the system enters S5.
*/
register_reboot_notifier(&tts_notifier);
+ acpi_gts_bfs_check();
return 0;
}
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index da51f05ef8d8..0944daec064f 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -38,6 +38,7 @@ ACPI_MODULE_NAME("system");
#define ACPI_SYSTEM_DEVICE_NAME "System"
u32 acpi_irq_handled;
+u32 acpi_irq_not_handled;
/*
* Make ACPICA version work as module param
@@ -214,8 +215,9 @@ err:
#define COUNT_GPE 0
#define COUNT_SCI 1 /* acpi_irq_handled */
-#define COUNT_ERROR 2 /* other */
-#define NUM_COUNTERS_EXTRA 3
+#define COUNT_SCI_NOT 2 /* acpi_irq_not_handled */
+#define COUNT_ERROR 3 /* other */
+#define NUM_COUNTERS_EXTRA 4
struct event_counter {
u32 count;
@@ -317,6 +319,8 @@ static ssize_t counter_show(struct kobject *kobj,
all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI].count =
acpi_irq_handled;
+ all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI_NOT].count =
+ acpi_irq_not_handled;
all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE].count =
acpi_gpe_count;
@@ -363,6 +367,7 @@ static ssize_t counter_set(struct kobject *kobj,
all_counters[i].count = 0;
acpi_gpe_count = 0;
acpi_irq_handled = 0;
+ acpi_irq_not_handled = 0;
goto end;
}
@@ -456,6 +461,8 @@ void acpi_irq_stats_init(void)
sprintf(buffer, "gpe_all");
else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI)
sprintf(buffer, "sci");
+ else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI_NOT)
+ sprintf(buffer, "sci_not");
else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR)
sprintf(buffer, "error");
else
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 9cd15e8c8932..564ea1424288 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -909,7 +909,7 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
thermal_zone_device_register("acpitz", trips, tz,
&acpi_thermal_zone_ops,
0, 0, 0,
- tz->polling_frequency);
+ tz->polling_frequency*100);
if (IS_ERR(tz->thermal_zone))
return -ENODEV;
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index cd4fb7543a90..810cca90ca7f 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -538,6 +538,41 @@ acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
return -EINVAL;
}
+/*
+ * For some buggy _BQC methods, we need to add a constant value to
+ * the _BQC return value to get the actual current brightness level
+ */
+
+static int bqc_offset_aml_bug_workaround;
+static int __init video_set_bqc_offset(const struct dmi_system_id *d)
+{
+ bqc_offset_aml_bug_workaround = 9;
+ return 0;
+}
+
+static struct dmi_system_id video_dmi_table[] __initdata = {
+ /*
+ * Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121
+ */
+ {
+ .callback = video_set_bqc_offset,
+ .ident = "Acer Aspire 5720",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5720"),
+ },
+ },
+ {
+ .callback = video_set_bqc_offset,
+ .ident = "Acer Aspire 5710Z",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5710Z"),
+ },
+ },
+ {}
+};
+
static int
acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
unsigned long long *level)
@@ -557,6 +592,7 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
*level = device->brightness->levels[*level + 2];
}
+ *level += bqc_offset_aml_bug_workaround;
device->brightness->curr = *level;
return 0;
} else {
@@ -770,10 +806,12 @@ acpi_video_init_brightness(struct acpi_video_device *device)
* In this case, the first two elements in _BCL packages
* are also supported brightness levels that OS should take care of.
*/
- for (i = 2; i < count; i++)
- if (br->levels[i] == br->levels[0] ||
- br->levels[i] == br->levels[1])
+ for (i = 2; i < count; i++) {
+ if (br->levels[i] == br->levels[0])
+ level_ac_battery++;
+ if (br->levels[i] == br->levels[1])
level_ac_battery++;
+ }
if (level_ac_battery < 2) {
level_ac_battery = 2 - level_ac_battery;
@@ -807,12 +845,19 @@ acpi_video_init_brightness(struct acpi_video_device *device)
br->flags._BCM_use_index = br->flags._BCL_use_index;
/* _BQC uses INDEX while _BCL uses VALUE in some laptops */
- br->curr = max_level;
+ br->curr = level_old = max_level;
+
+ if (!device->cap._BQC)
+ goto set_level;
+
result = acpi_video_device_lcd_get_level_current(device, &level_old);
if (result)
goto out_free_levels;
- result = acpi_video_device_lcd_set_level(device, br->curr);
+ /*
+ * Set the level to maximum and check if _BQC uses indexed value
+ */
+ result = acpi_video_device_lcd_set_level(device, max_level);
if (result)
goto out_free_levels;
@@ -820,25 +865,19 @@ acpi_video_init_brightness(struct acpi_video_device *device)
if (result)
goto out_free_levels;
- if ((level != level_old) && !br->flags._BCM_use_index) {
- /* Note:
- * This piece of code does not work correctly if the current
- * brightness levels is 0.
- * But I guess boxes that boot with such a dark screen are rare
- * and no more code is needed to cover this specifial case.
- */
-
- if (level_ac_battery != 2) {
- /*
- * For now, we don't support the _BCL like this:
- * 16, 15, 0, 1, 2, 3, ..., 14, 15, 16
- * because we may mess up the index returned by _BQC.
- * Plus: we have not got a box like this.
- */
- ACPI_ERROR((AE_INFO, "_BCL not supported\n"));
- }
- br->flags._BQC_use_index = 1;
- }
+ br->flags._BQC_use_index = (level == max_level ? 0 : 1);
+
+ if (!br->flags._BQC_use_index)
+ goto set_level;
+
+ if (br->flags._BCL_reversed)
+ level_old = (br->count - 1) - level_old;
+ level_old = br->levels[level_old];
+
+set_level:
+ result = acpi_video_device_lcd_set_level(device, level_old);
+ if (result)
+ goto out_free_levels;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"found %d brightness levels\n", count - 2));
@@ -2287,13 +2326,15 @@ EXPORT_SYMBOL(acpi_video_register);
static int __init acpi_video_init(void)
{
+ dmi_check_system(video_dmi_table);
+
if (intel_opregion_present())
return 0;
return acpi_video_register();
}
-static void __exit acpi_video_exit(void)
+void __exit acpi_video_exit(void)
{
acpi_bus_unregister_driver(&acpi_video_bus);
@@ -2302,6 +2343,7 @@ static void __exit acpi_video_exit(void)
return;
}
+EXPORT_SYMBOL(acpi_video_exit);
module_init(acpi_video_init);
module_exit(acpi_video_exit);
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 08186ecbaf8d..3489085b448b 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -312,7 +312,6 @@ static void ahci_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 void ahci_dev_config(struct ata_device *dev);
-static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl);
static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
u32 opts);
#ifdef CONFIG_PM
@@ -403,14 +402,14 @@ static struct ata_port_operations ahci_sb600_ops = {
#define AHCI_HFLAGS(flags) .private_data = (void *)(flags)
static const struct ata_port_info ahci_port_info[] = {
- /* board_ahci */
+ [board_ahci] =
{
.flags = AHCI_FLAG_COMMON,
.pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
- /* board_ahci_vt8251 */
+ [board_ahci_vt8251] =
{
AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
.flags = AHCI_FLAG_COMMON,
@@ -418,7 +417,7 @@ static const struct ata_port_info ahci_port_info[] = {
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_vt8251_ops,
},
- /* board_ahci_ign_iferr */
+ [board_ahci_ign_iferr] =
{
AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR),
.flags = AHCI_FLAG_COMMON,
@@ -426,7 +425,7 @@ static const struct ata_port_info ahci_port_info[] = {
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
- /* board_ahci_sb600 */
+ [board_ahci_sb600] =
{
AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL |
AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
@@ -436,7 +435,7 @@ static const struct ata_port_info ahci_port_info[] = {
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_sb600_ops,
},
- /* board_ahci_mv */
+ [board_ahci_mv] =
{
AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
@@ -446,7 +445,7 @@ static const struct ata_port_info ahci_port_info[] = {
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
- /* board_ahci_sb700, for SB700 and SB800 */
+ [board_ahci_sb700] = /* for SB700 and SB800 */
{
AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL),
.flags = AHCI_FLAG_COMMON,
@@ -454,7 +453,7 @@ static const struct ata_port_info ahci_port_info[] = {
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_sb600_ops,
},
- /* board_ahci_mcp65 */
+ [board_ahci_mcp65] =
{
AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ),
.flags = AHCI_FLAG_COMMON,
@@ -462,7 +461,7 @@ static const struct ata_port_info ahci_port_info[] = {
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
- /* board_ahci_nopmp */
+ [board_ahci_nopmp] =
{
AHCI_HFLAGS (AHCI_HFLAG_NO_PMP),
.flags = AHCI_FLAG_COMMON,
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 942d14ac8792..d51a17c0f59b 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -72,6 +72,7 @@
* ICH2 spec c #20 - IDE PRD must not cross a 64K boundary
* and must be dword aligned
* ICH2 spec c #24 - UDMA mode 4,5 t85/86 should be 6ns not 3.3
+ * ICH7 errata #16 - MWDMA1 timings are incorrect
*
* Should have been BIOS fixed:
* 450NX: errata #19 - DMA hangs on old 450NX
@@ -94,7 +95,7 @@
#include <linux/dmi.h>
#define DRV_NAME "ata_piix"
-#define DRV_VERSION "2.12"
+#define DRV_VERSION "2.13"
enum {
PIIX_IOCFG = 0x54, /* IDE I/O configuration register */
@@ -136,6 +137,7 @@ enum piix_controller_ids {
ich_pata_33, /* ICH up to UDMA 33 only */
ich_pata_66, /* ICH up to 66 Mhz */
ich_pata_100, /* ICH up to UDMA 100 */
+ ich_pata_100_nomwdma1, /* ICH up to UDMA 100 but with no MWDMA1*/
ich5_sata,
ich6_sata,
ich6m_sata,
@@ -216,8 +218,8 @@ static const struct pci_device_id piix_pci_tbl[] = {
/* ICH6 (and 6) (i915) UDMA 100 */
{ 0x8086, 0x266F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
/* ICH7/7-R (i945, i975) UDMA 100*/
- { 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
- { 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
+ { 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100_nomwdma1 },
+ { 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100_nomwdma1 },
/* ICH8 Mobile PATA Controller */
{ 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
@@ -487,6 +489,15 @@ static struct ata_port_info piix_port_info[] = {
.port_ops = &ich_pata_ops,
},
+ [ich_pata_100_nomwdma1] =
+ {
+ .flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2_ONLY,
+ .udma_mask = ATA_UDMA5,
+ .port_ops = &ich_pata_ops,
+ },
+
[ich5_sata] =
{
.flags = PIIX_SATA_FLAGS,
@@ -594,6 +605,7 @@ static const struct ich_laptop ich_laptop[] = {
{ 0x24CA, 0x1025, 0x003d }, /* ICH4 on ACER TM290 */
{ 0x266F, 0x1025, 0x0066 }, /* ICH6 on ACER Aspire 1694WLMi */
{ 0x2653, 0x1043, 0x82D8 }, /* ICH6M on Asus Eee 701 */
+ { 0x27df, 0x104d, 0x900e }, /* ICH7 on Sony TZ-90 */
/* end marker */
{ 0, }
};
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 6273d98d00eb..ac176da1f94e 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -748,9 +748,9 @@ static int ata_acpi_run_tf(struct ata_device *dev,
/**
* ata_acpi_exec_tfs - get then write drive taskfile settings
* @dev: target ATA device
- * @nr_executed: out paramter for the number of executed commands
+ * @nr_executed: out parameter for the number of executed commands
*
- * Evaluate _GTF and excute returned taskfiles.
+ * Evaluate _GTF and execute returned taskfiles.
*
* LOCKING:
* EH context.
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 065507c46644..c9242301cfa1 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1231,6 +1231,9 @@ unsigned int ata_dev_classify(const struct ata_taskfile *tf)
*
* We follow the current spec and consider that 0x69/0x96
* identifies a port multiplier and 0x3c/0xc3 a SEMB device.
+ * Unfortunately, WDC WD1600JS-62MHB5 (a hard drive) reports
+ * SEMB signature. This is worked around in
+ * ata_dev_read_id().
*/
if ((tf->lbam == 0) && (tf->lbah == 0)) {
DPRINTK("found ATA device by sig\n");
@@ -1248,8 +1251,8 @@ unsigned int ata_dev_classify(const struct ata_taskfile *tf)
}
if ((tf->lbam == 0x3c) && (tf->lbah == 0xc3)) {
- printk(KERN_INFO "ata: SEMB device ignored\n");
- return ATA_DEV_SEMB_UNSUP; /* not yet */
+ DPRINTK("found SEMB device by sig (could be ATA device)\n");
+ return ATA_DEV_SEMB;
}
DPRINTK("unknown device\n");
@@ -1653,8 +1656,8 @@ unsigned long ata_id_xfermask(const u16 *id)
/*
* Process compact flash extended modes
*/
- int pio = id[163] & 0x7;
- int dma = (id[163] >> 3) & 7;
+ int pio = (id[ATA_ID_CFA_MODES] >> 0) & 0x7;
+ int dma = (id[ATA_ID_CFA_MODES] >> 3) & 0x7;
if (pio)
pio_mask |= (1 << 5);
@@ -2080,6 +2083,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
struct ata_taskfile tf;
unsigned int err_mask = 0;
const char *reason;
+ bool is_semb = class == ATA_DEV_SEMB;
int may_fallback = 1, tried_spinup = 0;
int rc;
@@ -2090,6 +2094,8 @@ retry:
ata_tf_init(dev, &tf);
switch (class) {
+ case ATA_DEV_SEMB:
+ class = ATA_DEV_ATA; /* some hard drives report SEMB sig */
case ATA_DEV_ATA:
tf.command = ATA_CMD_ID_ATA;
break;
@@ -2126,6 +2132,14 @@ retry:
return -ENOENT;
}
+ if (is_semb) {
+ ata_dev_printk(dev, KERN_INFO, "IDENTIFY failed on "
+ "device w/ SEMB sig, disabled\n");
+ /* SEMB is not supported yet */
+ *p_class = ATA_DEV_SEMB_UNSUP;
+ return 0;
+ }
+
if ((err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) {
/* Device or controller might have reported
* the wrong device class. Give a shot at the
@@ -2412,7 +2426,8 @@ int ata_dev_configure(struct ata_device *dev)
/* ATA-specific feature tests */
if (dev->class == ATA_DEV_ATA) {
if (ata_id_is_cfa(id)) {
- if (id[162] & 1) /* CPRM may make this media unusable */
+ /* CPRM may make this media unusable */
+ if (id[ATA_ID_CFA_KEY_MGMT] & 1)
ata_dev_printk(dev, KERN_WARNING,
"supports DRM functions and may "
"not be fully accessable.\n");
@@ -4076,7 +4091,9 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
/* fail early if !ATA && !ATAPI to avoid issuing [P]IDENTIFY to PMP */
if (ata_class_enabled(new_class) &&
- new_class != ATA_DEV_ATA && new_class != ATA_DEV_ATAPI) {
+ new_class != ATA_DEV_ATA &&
+ new_class != ATA_DEV_ATAPI &&
+ new_class != ATA_DEV_SEMB) {
ata_dev_printk(dev, KERN_INFO, "class mismatch %u != %u\n",
dev->class, new_class);
rc = -ENODEV;
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 01831312c360..fa22f94ca415 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2783,6 +2783,12 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
} else if (dev->class == ATA_DEV_UNKNOWN &&
ehc->tries[dev->devno] &&
ata_class_enabled(ehc->classes[dev->devno])) {
+ /* Temporarily set dev->class, it will be
+ * permanently set once all configurations are
+ * complete. This is necessary because new
+ * device configuration is done in two
+ * separate loops.
+ */
dev->class = ehc->classes[dev->devno];
if (dev->class == ATA_DEV_PMP)
@@ -2790,6 +2796,11 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
else
rc = ata_dev_read_id(dev, &dev->class,
readid_flags, dev->id);
+
+ /* read_id might have changed class, store and reset */
+ ehc->classes[dev->devno] = dev->class;
+ dev->class = ATA_DEV_UNKNOWN;
+
switch (rc) {
case 0:
/* clear error info accumulated during probe */
@@ -2799,13 +2810,11 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
case -ENOENT:
/* IDENTIFY was issued to non-existent
* device. No need to reset. Just
- * thaw and kill the device.
+ * thaw and ignore the device.
*/
ata_eh_thaw_port(ap);
- dev->class = ATA_DEV_UNKNOWN;
break;
default:
- dev->class = ATA_DEV_UNKNOWN;
goto err;
}
}
@@ -2826,11 +2835,15 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
dev->class == ATA_DEV_PMP)
continue;
+ dev->class = ehc->classes[dev->devno];
+
ehc->i.flags |= ATA_EHI_PRINTINFO;
rc = ata_dev_configure(dev);
ehc->i.flags &= ~ATA_EHI_PRINTINFO;
- if (rc)
+ if (rc) {
+ dev->class = ATA_DEV_UNKNOWN;
goto err;
+ }
spin_lock_irqsave(ap->lock, flags);
ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
@@ -2851,7 +2864,7 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
/**
* ata_set_mode - Program timings and issue SET FEATURES - XFER
* @link: link on which timings will be programmed
- * @r_failed_dev: out paramter for failed device
+ * @r_failed_dev: out parameter for failed device
*
* Set ATA device disk transfer mode (PIO3, UDMA6, etc.). If
* ata_set_mode() fails, pointer to the failing device is
@@ -3494,6 +3507,8 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap)
*/
static void ata_eh_handle_port_resume(struct ata_port *ap)
{
+ struct ata_link *link;
+ struct ata_device *dev;
unsigned long flags;
int rc = 0;
@@ -3508,6 +3523,17 @@ static void ata_eh_handle_port_resume(struct ata_port *ap)
WARN_ON(!(ap->pflags & ATA_PFLAG_SUSPENDED));
+ /*
+ * Error timestamps are in jiffies which doesn't run while
+ * suspended and PHY events during resume isn't too uncommon.
+ * When the two are combined, it can lead to unnecessary speed
+ * downs if the machine is suspended and resumed repeatedly.
+ * Clear error history.
+ */
+ ata_for_each_link(link, ap, HOST_FIRST)
+ ata_for_each_dev(dev, link, ALL)
+ ata_ering_clear(&dev->ering);
+
ata_acpi_set_state(ap, PMSG_ON);
if (ap->ops->port_resume)
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index b9747fa59e54..68d9132d8f6f 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -313,7 +313,7 @@ ata_scsi_em_message_show(struct device *dev, struct device_attribute *attr,
return ap->ops->em_show(ap, buf);
return -EINVAL;
}
-DEVICE_ATTR(em_message, S_IRUGO | S_IWUGO,
+DEVICE_ATTR(em_message, S_IRUGO | S_IWUSR,
ata_scsi_em_message_show, ata_scsi_em_message_store);
EXPORT_SYMBOL_GPL(dev_attr_em_message);
@@ -366,7 +366,7 @@ ata_scsi_activity_store(struct device *dev, struct device_attribute *attr,
}
return -EINVAL;
}
-DEVICE_ATTR(sw_activity, S_IWUGO | S_IRUGO, ata_scsi_activity_show,
+DEVICE_ATTR(sw_activity, S_IWUSR | S_IRUGO, ata_scsi_activity_show,
ata_scsi_activity_store);
EXPORT_SYMBOL_GPL(dev_attr_sw_activity);
@@ -647,23 +647,45 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
return rc;
}
+static int ata_ioc32(struct ata_port *ap)
+{
+ if (ap->flags & ATA_FLAG_PIO_DMA)
+ return 1;
+ if (ap->pflags & ATA_PFLAG_PIO32)
+ return 1;
+ return 0;
+}
+
int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *scsidev,
int cmd, void __user *arg)
{
int val = -EINVAL, rc = -EINVAL;
+ unsigned long flags;
switch (cmd) {
case ATA_IOC_GET_IO32:
- val = 0;
+ spin_lock_irqsave(ap->lock, flags);
+ val = ata_ioc32(ap);
+ spin_unlock_irqrestore(ap->lock, flags);
if (copy_to_user(arg, &val, 1))
return -EFAULT;
return 0;
case ATA_IOC_SET_IO32:
val = (unsigned long) arg;
- if (val != 0)
- return -EINVAL;
- return 0;
+ rc = 0;
+ spin_lock_irqsave(ap->lock, flags);
+ if (ap->pflags & ATA_PFLAG_PIO32CHANGE) {
+ if (val)
+ ap->pflags |= ATA_PFLAG_PIO32;
+ else
+ ap->pflags &= ~ATA_PFLAG_PIO32;
+ } else {
+ if (val != ata_ioc32(ap))
+ rc = -EINVAL;
+ }
+ spin_unlock_irqrestore(ap->lock, flags);
+ return rc;
case HDIO_GET_IDENTITY:
return ata_get_identity(ap, scsidev, arg);
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 8332e97a9de3..bbbb1fab1755 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -87,6 +87,7 @@ const struct ata_port_operations ata_bmdma32_port_ops = {
.inherits = &ata_bmdma_port_ops,
.sff_data_xfer = ata_sff_data_xfer32,
+ .port_start = ata_sff_port_start32,
};
EXPORT_SYMBOL_GPL(ata_bmdma32_port_ops);
@@ -726,17 +727,23 @@ unsigned int ata_sff_data_xfer(struct ata_device *dev, unsigned char *buf,
else
iowrite16_rep(data_addr, buf, words);
- /* Transfer trailing 1 byte, if any. */
+ /* Transfer trailing byte, if any. */
if (unlikely(buflen & 0x01)) {
- __le16 align_buf[1] = { 0 };
- unsigned char *trailing_buf = buf + buflen - 1;
+ unsigned char pad[2];
+ /* Point buf to the tail of buffer */
+ buf += buflen - 1;
+
+ /*
+ * Use io*16_rep() accessors here as well to avoid pointlessly
+ * swapping bytes to and fro on the big endian machines...
+ */
if (rw == READ) {
- align_buf[0] = cpu_to_le16(ioread16(data_addr));
- memcpy(trailing_buf, align_buf, 1);
+ ioread16_rep(data_addr, pad, 1);
+ *buf = pad[0];
} else {
- memcpy(align_buf, trailing_buf, 1);
- iowrite16(le16_to_cpu(align_buf[0]), data_addr);
+ pad[0] = *buf;
+ iowrite16_rep(data_addr, pad, 1);
}
words++;
}
@@ -769,6 +776,9 @@ unsigned int ata_sff_data_xfer32(struct ata_device *dev, unsigned char *buf,
void __iomem *data_addr = ap->ioaddr.data_addr;
unsigned int words = buflen >> 2;
int slop = buflen & 3;
+
+ if (!(ap->pflags & ATA_PFLAG_PIO32))
+ return ata_sff_data_xfer(dev, buf, buflen, rw);
/* Transfer multiple of 4 bytes */
if (rw == READ)
@@ -2402,6 +2412,29 @@ int ata_sff_port_start(struct ata_port *ap)
EXPORT_SYMBOL_GPL(ata_sff_port_start);
/**
+ * ata_sff_port_start32 - Set port up for dma.
+ * @ap: Port to initialize
+ *
+ * Called just after data structures for each port are
+ * initialized. Allocates space for PRD table if the device
+ * is DMA capable SFF.
+ *
+ * May be used as the port_start() entry in ata_port_operations for
+ * devices that are capable of 32bit PIO.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+int ata_sff_port_start32(struct ata_port *ap)
+{
+ ap->pflags |= ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE;
+ if (ap->ioaddr.bmdma_addr)
+ return ata_port_start(ap);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ata_sff_port_start32);
+
+/**
* ata_sff_std_ports - initialize ioaddr with standard port offsets.
* @ioaddr: IO address structure to be initialized
*
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index 81ab57003aba..122c786449a9 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -8,7 +8,7 @@
* 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) 2005-2007 MontaVista Software, Inc.
+ * Portions Copyright (C) 2005-2009 MontaVista Software, Inc.
*
* TODO
* Look into engine reset on timeout errors. Should not be required.
@@ -24,7 +24,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_hpt37x"
-#define DRV_VERSION "0.6.11"
+#define DRV_VERSION "0.6.12"
struct hpt_clock {
u8 xfer_speed;
@@ -445,23 +445,6 @@ static void hpt370_set_dmamode(struct ata_port *ap, struct ata_device *adev)
}
/**
- * hpt370_bmdma_start - DMA engine begin
- * @qc: ATA command
- *
- * The 370 and 370A want us to reset the DMA engine each time we
- * use it. The 372 and later are fine.
- */
-
-static void hpt370_bmdma_start(struct ata_queued_cmd *qc)
-{
- struct ata_port *ap = qc->ap;
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
- udelay(10);
- ata_bmdma_start(qc);
-}
-
-/**
* hpt370_bmdma_end - DMA engine stop
* @qc: ATA command
*
@@ -598,7 +581,6 @@ static struct scsi_host_template hpt37x_sht = {
static struct ata_port_operations hpt370_port_ops = {
.inherits = &ata_bmdma_port_ops,
- .bmdma_start = hpt370_bmdma_start,
.bmdma_stop = hpt370_bmdma_stop,
.mode_filter = hpt370_filter,
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
index 3f830f0fe2cc..f72c6c5b820f 100644
--- a/drivers/ata/pata_legacy.c
+++ b/drivers/ata/pata_legacy.c
@@ -108,6 +108,7 @@ struct legacy_controller {
struct ata_port_operations *ops;
unsigned int pio_mask;
unsigned int flags;
+ unsigned int pflags;
int (*setup)(struct platform_device *, struct legacy_probe *probe,
struct legacy_data *data);
};
@@ -284,9 +285,11 @@ static unsigned int pdc_data_xfer_vlb(struct ata_device *dev,
unsigned char *buf, unsigned int buflen, int rw)
{
int slop = buflen & 3;
+ struct ata_port *ap = dev->link->ap;
+
/* 32bit I/O capable *and* we need to write a whole number of dwords */
- if (ata_id_has_dword_io(dev->id) && (slop == 0 || slop == 3)) {
- struct ata_port *ap = dev->link->ap;
+ if (ata_id_has_dword_io(dev->id) && (slop == 0 || slop == 3)
+ && (ap->pflags & ATA_PFLAG_PIO32)) {
unsigned long flags;
local_irq_save(flags);
@@ -736,7 +739,8 @@ static unsigned int vlb32_data_xfer(struct ata_device *adev, unsigned char *buf,
struct ata_port *ap = adev->link->ap;
int slop = buflen & 3;
- if (ata_id_has_dword_io(adev->id) && (slop == 0 || slop == 3)) {
+ if (ata_id_has_dword_io(adev->id) && (slop == 0 || slop == 3)
+ && (ap->pflags & ATA_PFLAG_PIO32)) {
if (rw == WRITE)
iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
else
@@ -858,27 +862,30 @@ static struct ata_port_operations winbond_port_ops = {
static struct legacy_controller controllers[] = {
{"BIOS", &legacy_port_ops, 0x1F,
- ATA_FLAG_NO_IORDY, NULL },
+ ATA_FLAG_NO_IORDY, 0, NULL },
{"Snooping", &simple_port_ops, 0x1F,
- 0 , NULL },
+ 0, 0, NULL },
{"PDC20230", &pdc20230_port_ops, 0x7,
- ATA_FLAG_NO_IORDY, NULL },
+ ATA_FLAG_NO_IORDY,
+ ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE, NULL },
{"HT6560A", &ht6560a_port_ops, 0x07,
- ATA_FLAG_NO_IORDY, NULL },
+ ATA_FLAG_NO_IORDY, 0, NULL },
{"HT6560B", &ht6560b_port_ops, 0x1F,
- ATA_FLAG_NO_IORDY, NULL },
+ ATA_FLAG_NO_IORDY, 0, NULL },
{"OPTI82C611A", &opti82c611a_port_ops, 0x0F,
- 0 , NULL },
+ 0, 0, NULL },
{"OPTI82C46X", &opti82c46x_port_ops, 0x0F,
- 0 , NULL },
+ 0, 0, NULL },
{"QDI6500", &qdi6500_port_ops, 0x07,
- ATA_FLAG_NO_IORDY, qdi_port },
+ ATA_FLAG_NO_IORDY,
+ ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE, qdi_port },
{"QDI6580", &qdi6580_port_ops, 0x1F,
- 0 , qdi_port },
+ 0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE, qdi_port },
{"QDI6580DP", &qdi6580dp_port_ops, 0x1F,
- 0 , qdi_port },
+ 0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE, qdi_port },
{"W83759A", &winbond_port_ops, 0x1F,
- 0 , winbond_port }
+ 0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE,
+ winbond_port }
};
/**
@@ -1008,6 +1015,7 @@ static __init int legacy_init_one(struct legacy_probe *probe)
ap->ops = ops;
ap->pio_mask = pio_modes;
ap->flags |= ATA_FLAG_SLAVE_POSS | iordy;
+ ap->pflags |= controller->pflags;
ap->ioaddr.cmd_addr = io_addr;
ap->ioaddr.altstatus_addr = ctrl_addr;
ap->ioaddr.ctl_addr = ctrl_addr;
@@ -1032,6 +1040,7 @@ static __init int legacy_init_one(struct legacy_probe *probe)
return 0;
}
}
+ ata_host_detach(host);
fail:
platform_device_unregister(pdev);
return ret;
diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c
index 0fb6b1b1e634..dd53a66b19e3 100644
--- a/drivers/ata/pata_ninja32.c
+++ b/drivers/ata/pata_ninja32.c
@@ -44,7 +44,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_ninja32"
-#define DRV_VERSION "0.1.3"
+#define DRV_VERSION "0.1.5"
/**
@@ -86,6 +86,7 @@ static struct ata_port_operations ninja32_port_ops = {
.sff_dev_select = ninja32_dev_select,
.cable_detect = ata_cable_40wire,
.set_piomode = ninja32_set_piomode,
+ .sff_data_xfer = ata_sff_data_xfer32
};
static void ninja32_program(void __iomem *base)
@@ -144,6 +145,7 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
ap->ioaddr.altstatus_addr = base + 0x1E;
ap->ioaddr.bmdma_addr = base;
ata_sff_std_ports(&ap->ioaddr);
+ ap->pflags = ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE;
ninja32_program(base);
/* FIXME: Should we disable them at remove ? */
diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c
index 5fedb3d4032b..2f3c9bed63d9 100644
--- a/drivers/ata/pata_pdc202xx_old.c
+++ b/drivers/ata/pata_pdc202xx_old.c
@@ -2,7 +2,7 @@
* pata_pdc202xx_old.c - Promise PDC202xx PATA for new ATA layer
* (C) 2005 Red Hat Inc
* Alan Cox <alan@lxorguk.ukuu.org.uk>
- * (C) 2007 Bartlomiej Zolnierkiewicz
+ * (C) 2007,2009 Bartlomiej Zolnierkiewicz
*
* Based in part on linux/drivers/ide/pci/pdc202xx_old.c
*
@@ -158,7 +158,7 @@ static void pdc2026x_bmdma_start(struct ata_queued_cmd *qc)
u32 len;
/* Check we keep host level locking here */
- if (adev->dma_mode >= XFER_UDMA_2)
+ if (adev->dma_mode > XFER_UDMA_2)
iowrite8(ioread8(clock) | sel66, clock);
else
iowrite8(ioread8(clock) & ~sel66, clock);
@@ -212,7 +212,7 @@ static void pdc2026x_bmdma_stop(struct ata_queued_cmd *qc)
iowrite8(ioread8(clock) & ~sel66, clock);
}
/* Flip back to 33Mhz for PIO */
- if (adev->dma_mode >= XFER_UDMA_2)
+ if (adev->dma_mode > XFER_UDMA_2)
iowrite8(ioread8(clock) & ~sel66, clock);
ata_bmdma_stop(qc);
pdc202xx_set_piomode(ap, adev);
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index b08e6e0f82b6..45657cacec43 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -62,7 +62,7 @@
#include <linux/dmi.h>
#define DRV_NAME "pata_via"
-#define DRV_VERSION "0.3.3"
+#define DRV_VERSION "0.3.4"
/*
* The following comes directly from Vojtech Pavlik's ide/pci/via82cxxx
@@ -136,6 +136,9 @@ static const struct via_isa_bridge {
{ NULL }
};
+struct via_port {
+ u8 cached_device;
+};
/*
* Cable special cases
@@ -346,14 +349,70 @@ static void via_set_dmamode(struct ata_port *ap, struct ata_device *adev)
*/
static void via_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
{
- struct ata_taskfile tmp_tf;
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+ struct via_port *vp = ap->private_data;
+ unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+ int newctl = 0;
+
+ if (tf->ctl != ap->last_ctl) {
+ iowrite8(tf->ctl, ioaddr->ctl_addr);
+ ap->last_ctl = tf->ctl;
+ ata_wait_idle(ap);
+ newctl = 1;
+ }
+
+ if (tf->flags & ATA_TFLAG_DEVICE) {
+ iowrite8(tf->device, ioaddr->device_addr);
+ vp->cached_device = tf->device;
+ } else if (newctl)
+ iowrite8(vp->cached_device, ioaddr->device_addr);
+
+ if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+ WARN_ON_ONCE(!ioaddr->ctl_addr);
+ iowrite8(tf->hob_feature, ioaddr->feature_addr);
+ iowrite8(tf->hob_nsect, ioaddr->nsect_addr);
+ iowrite8(tf->hob_lbal, ioaddr->lbal_addr);
+ iowrite8(tf->hob_lbam, ioaddr->lbam_addr);
+ iowrite8(tf->hob_lbah, ioaddr->lbah_addr);
+ VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
+ tf->hob_feature,
+ tf->hob_nsect,
+ tf->hob_lbal,
+ tf->hob_lbam,
+ tf->hob_lbah);
+ }
- if (ap->ctl != ap->last_ctl && !(tf->flags & ATA_TFLAG_DEVICE)) {
- tmp_tf = *tf;
- tmp_tf.flags |= ATA_TFLAG_DEVICE;
- tf = &tmp_tf;
+ if (is_addr) {
+ iowrite8(tf->feature, ioaddr->feature_addr);
+ iowrite8(tf->nsect, ioaddr->nsect_addr);
+ iowrite8(tf->lbal, ioaddr->lbal_addr);
+ iowrite8(tf->lbam, ioaddr->lbam_addr);
+ iowrite8(tf->lbah, ioaddr->lbah_addr);
+ VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
+ tf->feature,
+ tf->nsect,
+ tf->lbal,
+ tf->lbam,
+ tf->lbah);
}
- ata_sff_tf_load(ap, tf);
+
+ ata_wait_idle(ap);
+}
+
+static int via_port_start(struct ata_port *ap)
+{
+ struct via_port *vp;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+
+ int ret = ata_sff_port_start(ap);
+ if (ret < 0)
+ return ret;
+
+ vp = devm_kzalloc(&pdev->dev, sizeof(struct via_port), GFP_KERNEL);
+ if (vp == NULL)
+ return -ENOMEM;
+ ap->private_data = vp;
+ return 0;
}
static struct scsi_host_template via_sht = {
@@ -367,6 +426,7 @@ static struct ata_port_operations via_port_ops = {
.set_dmamode = via_set_dmamode,
.prereset = via_pre_reset,
.sff_tf_load = via_tf_load,
+ .port_start = via_port_start,
};
static struct ata_port_operations via_port_ops_noirq = {
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 37ae5dc1070c..23714aefb825 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -293,6 +293,10 @@ enum {
FISCFG_WAIT_DEV_ERR = (1 << 8), /* wait for host on DevErr */
FISCFG_SINGLE_SYNC = (1 << 16), /* SYNC on DMA activation */
+ PHY_MODE9_GEN2 = 0x398,
+ PHY_MODE9_GEN1 = 0x39c,
+ PHYCFG_OFS = 0x3a0, /* only in 65n devices */
+
MV5_PHY_MODE = 0x74,
MV5_LTMODE = 0x30,
MV5_PHY_CTL = 0x0C,
@@ -609,6 +613,8 @@ static int mv_soc_reset_hc(struct mv_host_priv *hpriv,
static void mv_soc_reset_flash(struct mv_host_priv *hpriv,
void __iomem *mmio);
static void mv_soc_reset_bus(struct ata_host *host, void __iomem *mmio);
+static void mv_soc_65n_phy_errata(struct mv_host_priv *hpriv,
+ void __iomem *mmio, unsigned int port);
static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio);
static void mv_reset_channel(struct mv_host_priv *hpriv, void __iomem *mmio,
unsigned int port_no);
@@ -807,6 +813,14 @@ static const struct mv_hw_ops mv_soc_ops = {
.reset_bus = mv_soc_reset_bus,
};
+static const struct mv_hw_ops mv_soc_65n_ops = {
+ .phy_errata = mv_soc_65n_phy_errata,
+ .enable_leds = mv_soc_enable_leds,
+ .reset_hc = mv_soc_reset_hc,
+ .reset_flash = mv_soc_reset_flash,
+ .reset_bus = mv_soc_reset_bus,
+};
+
/*
* Functions
*/
@@ -1881,6 +1895,39 @@ static u8 mv_bmdma_status(struct ata_port *ap)
return status;
}
+static void mv_rw_multi_errata_sata24(struct ata_queued_cmd *qc)
+{
+ struct ata_taskfile *tf = &qc->tf;
+ /*
+ * Workaround for 88SX60x1 FEr SATA#24.
+ *
+ * Chip may corrupt WRITEs if multi_count >= 4kB.
+ * Note that READs are unaffected.
+ *
+ * It's not clear if this errata really means "4K bytes",
+ * or if it always happens for multi_count > 7
+ * regardless of device sector_size.
+ *
+ * So, for safety, any write with multi_count > 7
+ * gets converted here into a regular PIO write instead:
+ */
+ if ((tf->flags & ATA_TFLAG_WRITE) && is_multi_taskfile(tf)) {
+ if (qc->dev->multi_count > 7) {
+ switch (tf->command) {
+ case ATA_CMD_WRITE_MULTI:
+ tf->command = ATA_CMD_PIO_WRITE;
+ break;
+ case ATA_CMD_WRITE_MULTI_FUA_EXT:
+ tf->flags &= ~ATA_TFLAG_FUA; /* ugh */
+ /* fall through */
+ case ATA_CMD_WRITE_MULTI_EXT:
+ tf->command = ATA_CMD_PIO_WRITE_EXT;
+ break;
+ }
+ }
+ }
+}
+
/**
* mv_qc_prep - Host specific command preparation.
* @qc: queued command to prepare
@@ -1898,17 +1945,24 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
struct ata_port *ap = qc->ap;
struct mv_port_priv *pp = ap->private_data;
__le16 *cw;
- struct ata_taskfile *tf;
+ struct ata_taskfile *tf = &qc->tf;
u16 flags = 0;
unsigned in_index;
- if ((qc->tf.protocol != ATA_PROT_DMA) &&
- (qc->tf.protocol != ATA_PROT_NCQ))
+ switch (tf->protocol) {
+ case ATA_PROT_DMA:
+ case ATA_PROT_NCQ:
+ break; /* continue below */
+ case ATA_PROT_PIO:
+ mv_rw_multi_errata_sata24(qc);
+ return;
+ default:
return;
+ }
/* Fill in command request block
*/
- if (!(qc->tf.flags & ATA_TFLAG_WRITE))
+ if (!(tf->flags & ATA_TFLAG_WRITE))
flags |= CRQB_FLAG_READ;
WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
flags |= qc->tag << CRQB_TAG_SHIFT;
@@ -1924,7 +1978,6 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags);
cw = &pp->crqb[in_index].ata_cmd[0];
- tf = &qc->tf;
/* Sadly, the CRQB cannot accomodate all registers--there are
* only 11 bytes...so we must pick and choose required
@@ -1990,16 +2043,16 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
struct ata_port *ap = qc->ap;
struct mv_port_priv *pp = ap->private_data;
struct mv_crqb_iie *crqb;
- struct ata_taskfile *tf;
+ struct ata_taskfile *tf = &qc->tf;
unsigned in_index;
u32 flags = 0;
- if ((qc->tf.protocol != ATA_PROT_DMA) &&
- (qc->tf.protocol != ATA_PROT_NCQ))
+ if ((tf->protocol != ATA_PROT_DMA) &&
+ (tf->protocol != ATA_PROT_NCQ))
return;
/* Fill in Gen IIE command request block */
- if (!(qc->tf.flags & ATA_TFLAG_WRITE))
+ if (!(tf->flags & ATA_TFLAG_WRITE))
flags |= CRQB_FLAG_READ;
WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
@@ -2015,7 +2068,6 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma[qc->tag] >> 16) >> 16);
crqb->flags = cpu_to_le32(flags);
- tf = &qc->tf;
crqb->ata_cmd[0] = cpu_to_le32(
(tf->command << 16) |
(tf->feature << 24)
@@ -3359,6 +3411,53 @@ static void mv_soc_reset_bus(struct ata_host *host, void __iomem *mmio)
return;
}
+static void mv_soc_65n_phy_errata(struct mv_host_priv *hpriv,
+ void __iomem *mmio, unsigned int port)
+{
+ void __iomem *port_mmio = mv_port_base(mmio, port);
+ u32 reg;
+
+ reg = readl(port_mmio + PHY_MODE3);
+ reg &= ~(0x3 << 27); /* SELMUPF (bits 28:27) to 1 */
+ reg |= (0x1 << 27);
+ reg &= ~(0x3 << 29); /* SELMUPI (bits 30:29) to 1 */
+ reg |= (0x1 << 29);
+ writel(reg, port_mmio + PHY_MODE3);
+
+ reg = readl(port_mmio + PHY_MODE4);
+ reg &= ~0x1; /* SATU_OD8 (bit 0) to 0, reserved bit 16 must be set */
+ reg |= (0x1 << 16);
+ writel(reg, port_mmio + PHY_MODE4);
+
+ reg = readl(port_mmio + PHY_MODE9_GEN2);
+ reg &= ~0xf; /* TXAMP[3:0] (bits 3:0) to 8 */
+ reg |= 0x8;
+ reg &= ~(0x1 << 14); /* TXAMP[4] (bit 14) to 0 */
+ writel(reg, port_mmio + PHY_MODE9_GEN2);
+
+ reg = readl(port_mmio + PHY_MODE9_GEN1);
+ reg &= ~0xf; /* TXAMP[3:0] (bits 3:0) to 8 */
+ reg |= 0x8;
+ reg &= ~(0x1 << 14); /* TXAMP[4] (bit 14) to 0 */
+ writel(reg, port_mmio + PHY_MODE9_GEN1);
+}
+
+/**
+ * soc_is_65 - check if the soc is 65 nano device
+ *
+ * Detect the type of the SoC, this is done by reading the PHYCFG_OFS
+ * register, this register should contain non-zero value and it exists only
+ * in the 65 nano devices, when reading it from older devices we get 0.
+ */
+static bool soc_is_65n(struct mv_host_priv *hpriv)
+{
+ void __iomem *port0_mmio = mv_port_base(hpriv->base, 0);
+
+ if (readl(port0_mmio + PHYCFG_OFS))
+ return true;
+ return false;
+}
+
static void mv_setup_ifcfg(void __iomem *port_mmio, int want_gen2i)
{
u32 ifcfg = readl(port_mmio + SATA_IFCFG);
@@ -3699,7 +3798,10 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
}
break;
case chip_soc:
- hpriv->ops = &mv_soc_ops;
+ if (soc_is_65n(hpriv))
+ hpriv->ops = &mv_soc_65n_ops;
+ else
+ hpriv->ops = &mv_soc_ops;
hp_flags |= MV_HP_FLAG_SOC | MV_HP_GEN_IIE |
MV_HP_ERRATA_60X1C0;
break;
@@ -3762,7 +3864,8 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
n_hc = mv_get_hc_count(host->ports[0]->flags);
for (port = 0; port < host->n_ports; port++)
- hpriv->ops->read_preamp(hpriv, port, mmio);
+ if (hpriv->ops->read_preamp)
+ hpriv->ops->read_preamp(hpriv, port, mmio);
rc = hpriv->ops->reset_hc(hpriv, mmio, n_hc);
if (rc)
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index e67ce8e5caa5..030ec079b184 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -183,7 +183,7 @@ static struct scsi_host_template sil_sht = {
};
static struct ata_port_operations sil_ops = {
- .inherits = &ata_bmdma_port_ops,
+ .inherits = &ata_bmdma32_port_ops,
.dev_config = sil_dev_config,
.set_mode = sil_set_mode,
.bmdma_setup = sil_bmdma_setup,
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index dce3dccced3f..ac723f5181ee 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -193,6 +193,7 @@ enum {
PDC_TIMER_MASK_INT,
};
+#define ECC_ERASE_BUF_SZ (128 * 1024)
struct pdc_port_priv {
u8 dimm_buf[(ATA_PRD_SZ * ATA_MAX_PRD) + 512];
@@ -1208,7 +1209,6 @@ 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;
@@ -1323,14 +1323,17 @@ static unsigned int pdc20621_dimm_init(struct ata_host *host)
pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
PDC_DIMM_SPD_TYPE, &spd0);
if (spd0 == 0x02) {
+ void *buf;
VPRINTK("Start ECC initialization\n");
addr = 0;
length = size * 1024 * 1024;
+ buf = kzalloc(ECC_ERASE_BUF_SZ, GFP_KERNEL);
while (addr < length) {
- pdc20621_put_to_dimm(host, (void *) &tmp, addr,
- sizeof(u32));
- addr += sizeof(u32);
+ pdc20621_put_to_dimm(host, buf, addr,
+ ECC_ERASE_BUF_SZ);
+ addr += ECC_ERASE_BUF_SZ;
}
+ kfree(buf);
VPRINTK("Finish ECC initialization\n");
}
return 0;
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index be204308cc1b..9359613addc5 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -1059,7 +1059,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
goto out;
}
- err = pci_set_dma_mask(dev, DMA_32BIT_MASK);
+ err = pci_set_dma_mask(dev, DMA_BIT_MASK(32));
if (err) {
dev_warn(&dev->dev, "Failed to set 32-bit DMA mask\n");
goto out;
diff --git a/drivers/base/base.h b/drivers/base/base.h
index ddc97496db4a..b528145a078f 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -115,7 +115,7 @@ extern int driver_probe_device(struct device_driver *drv, struct device *dev);
static inline int driver_match_device(struct device_driver *drv,
struct device *dev)
{
- return drv->bus->match && drv->bus->match(dev, drv);
+ return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}
extern void sysdev_shutdown(void);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index e73c92d13a23..4aa527b8a913 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -891,7 +891,8 @@ int device_add(struct device *dev)
set_dev_node(dev, dev_to_node(parent));
/* first, register with generic layer. */
- error = kobject_add(&dev->kobj, dev->kobj.parent, "%s", dev_name(dev));
+ /* we require the name to be set before, and pass NULL */
+ error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
if (error)
goto Error;
@@ -1142,6 +1143,9 @@ int device_for_each_child(struct device *parent, void *data,
struct device *child;
int error = 0;
+ if (!parent->p)
+ return 0;
+
klist_iter_init(&parent->p->klist_children, &i);
while ((child = next_device(&i)) && !error)
error = fn(child, data);
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index f17c3266a0e0..742cbe6b042b 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -179,6 +179,7 @@ void wait_for_device_probe(void)
wait_event(probe_waitqueue, atomic_read(&probe_count) == 0);
async_synchronize_full();
}
+EXPORT_SYMBOL_GPL(wait_for_device_probe);
/**
* driver_probe_device - attempt to bind device & driver together
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index d3a59c688fe4..f19afa8b4583 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -17,7 +17,7 @@
#include <linux/bitops.h>
#include <linux/mutex.h>
#include <linux/kthread.h>
-
+#include <linux/highmem.h>
#include <linux/firmware.h>
#include "base.h"
@@ -45,7 +45,10 @@ struct firmware_priv {
struct bin_attribute attr_data;
struct firmware *fw;
unsigned long status;
- int alloc_size;
+ struct page **pages;
+ int nr_pages;
+ int page_array_size;
+ const char *vdata;
struct timer_list timeout;
};
@@ -122,6 +125,10 @@ static ssize_t firmware_loading_show(struct device *dev,
return sprintf(buf, "%d\n", loading);
}
+/* Some architectures don't have PAGE_KERNEL_RO */
+#ifndef PAGE_KERNEL_RO
+#define PAGE_KERNEL_RO PAGE_KERNEL
+#endif
/**
* firmware_loading_store - set value in the 'loading' control file
* @dev: device pointer
@@ -141,6 +148,7 @@ static ssize_t firmware_loading_store(struct device *dev,
{
struct firmware_priv *fw_priv = dev_get_drvdata(dev);
int loading = simple_strtol(buf, NULL, 10);
+ int i;
switch (loading) {
case 1:
@@ -151,13 +159,30 @@ static ssize_t firmware_loading_store(struct device *dev,
}
vfree(fw_priv->fw->data);
fw_priv->fw->data = NULL;
+ for (i = 0; i < fw_priv->nr_pages; i++)
+ __free_page(fw_priv->pages[i]);
+ kfree(fw_priv->pages);
+ fw_priv->pages = NULL;
+ fw_priv->page_array_size = 0;
+ fw_priv->nr_pages = 0;
fw_priv->fw->size = 0;
- fw_priv->alloc_size = 0;
set_bit(FW_STATUS_LOADING, &fw_priv->status);
mutex_unlock(&fw_lock);
break;
case 0:
if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) {
+ vfree(fw_priv->fw->data);
+ fw_priv->fw->data = vmap(fw_priv->pages,
+ fw_priv->nr_pages,
+ 0, PAGE_KERNEL_RO);
+ if (!fw_priv->fw->data) {
+ dev_err(dev, "%s: vmap() failed\n", __func__);
+ goto err;
+ }
+ /* Pages will be freed by vfree() */
+ fw_priv->pages = NULL;
+ fw_priv->page_array_size = 0;
+ fw_priv->nr_pages = 0;
complete(&fw_priv->completion);
clear_bit(FW_STATUS_LOADING, &fw_priv->status);
break;
@@ -167,6 +192,7 @@ static ssize_t firmware_loading_store(struct device *dev,
dev_err(dev, "%s: unexpected value (%d)\n", __func__, loading);
/* fallthrough */
case -1:
+ err:
fw_load_abort(fw_priv);
break;
}
@@ -191,8 +217,28 @@ firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr,
ret_count = -ENODEV;
goto out;
}
- ret_count = memory_read_from_buffer(buffer, count, &offset,
- fw->data, fw->size);
+ if (offset > fw->size)
+ return 0;
+ if (count > fw->size - offset)
+ count = fw->size - offset;
+
+ ret_count = count;
+
+ while (count) {
+ void *page_data;
+ int page_nr = offset >> PAGE_SHIFT;
+ int page_ofs = offset & (PAGE_SIZE-1);
+ int page_cnt = min_t(size_t, PAGE_SIZE - page_ofs, count);
+
+ page_data = kmap(fw_priv->pages[page_nr]);
+
+ memcpy(buffer, page_data + page_ofs, page_cnt);
+
+ kunmap(page_data);
+ buffer += page_cnt;
+ offset += page_cnt;
+ count -= page_cnt;
+ }
out:
mutex_unlock(&fw_lock);
return ret_count;
@@ -201,27 +247,39 @@ out:
static int
fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
{
- u8 *new_data;
- int new_size = fw_priv->alloc_size;
+ int pages_needed = ALIGN(min_size, PAGE_SIZE) >> PAGE_SHIFT;
+
+ /* If the array of pages is too small, grow it... */
+ if (fw_priv->page_array_size < pages_needed) {
+ int new_array_size = max(pages_needed,
+ fw_priv->page_array_size * 2);
+ struct page **new_pages;
+
+ new_pages = kmalloc(new_array_size * sizeof(void *),
+ GFP_KERNEL);
+ if (!new_pages) {
+ fw_load_abort(fw_priv);
+ return -ENOMEM;
+ }
+ memcpy(new_pages, fw_priv->pages,
+ fw_priv->page_array_size * sizeof(void *));
+ memset(&new_pages[fw_priv->page_array_size], 0, sizeof(void *) *
+ (new_array_size - fw_priv->page_array_size));
+ kfree(fw_priv->pages);
+ fw_priv->pages = new_pages;
+ fw_priv->page_array_size = new_array_size;
+ }
- if (min_size <= fw_priv->alloc_size)
- return 0;
+ while (fw_priv->nr_pages < pages_needed) {
+ fw_priv->pages[fw_priv->nr_pages] =
+ alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
- new_size = ALIGN(min_size, PAGE_SIZE);
- new_data = vmalloc(new_size);
- if (!new_data) {
- printk(KERN_ERR "%s: unable to alloc buffer\n", __func__);
- /* Make sure that we don't keep incomplete data */
- fw_load_abort(fw_priv);
- return -ENOMEM;
- }
- fw_priv->alloc_size = new_size;
- if (fw_priv->fw->data) {
- memcpy(new_data, fw_priv->fw->data, fw_priv->fw->size);
- vfree(fw_priv->fw->data);
+ if (!fw_priv->pages[fw_priv->nr_pages]) {
+ fw_load_abort(fw_priv);
+ return -ENOMEM;
+ }
+ fw_priv->nr_pages++;
}
- fw_priv->fw->data = new_data;
- BUG_ON(min_size > fw_priv->alloc_size);
return 0;
}
@@ -258,10 +316,25 @@ firmware_data_write(struct kobject *kobj, struct bin_attribute *bin_attr,
if (retval)
goto out;
- memcpy((u8 *)fw->data + offset, buffer, count);
-
- fw->size = max_t(size_t, offset + count, fw->size);
retval = count;
+
+ while (count) {
+ void *page_data;
+ int page_nr = offset >> PAGE_SHIFT;
+ int page_ofs = offset & (PAGE_SIZE - 1);
+ int page_cnt = min_t(size_t, PAGE_SIZE - page_ofs, count);
+
+ page_data = kmap(fw_priv->pages[page_nr]);
+
+ memcpy(page_data + page_ofs, buffer, page_cnt);
+
+ kunmap(page_data);
+ buffer += page_cnt;
+ offset += page_cnt;
+ count -= page_cnt;
+ }
+
+ fw->size = max_t(size_t, offset, fw->size);
out:
mutex_unlock(&fw_lock);
return retval;
@@ -277,7 +350,11 @@ static struct bin_attribute firmware_attr_data_tmpl = {
static void fw_dev_release(struct device *dev)
{
struct firmware_priv *fw_priv = dev_get_drvdata(dev);
+ int i;
+ for (i = 0; i < fw_priv->nr_pages; i++)
+ __free_page(fw_priv->pages[i]);
+ kfree(fw_priv->pages);
kfree(fw_priv);
kfree(dev);
diff --git a/drivers/base/iommu.c b/drivers/base/iommu.c
index 9f0e672f4be8..8ad4ffea6920 100644
--- a/drivers/base/iommu.c
+++ b/drivers/base/iommu.c
@@ -18,6 +18,8 @@
#include <linux/bug.h>
#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/iommu.h>
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index d2198f64ad4e..8b4708e06244 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -217,7 +217,6 @@ int platform_device_add_data(struct platform_device *pdev, const void *data,
if (d) {
memcpy(d, data, size);
pdev->dev.platform_data = d;
- pdev->platform_data = d;
}
return d ? 0 : -ENOMEM;
}
@@ -247,21 +246,6 @@ int platform_device_add(struct platform_device *pdev)
else
dev_set_name(&pdev->dev, pdev->name);
- /* We will remove platform_data field from struct device
- * if all platform devices pass its platform specific data
- * from platform_device. The conversion is going to be a
- * long time, so we allow the two cases coexist to make
- * this kind of fix more easily*/
- if (pdev->platform_data && pdev->dev.platform_data) {
- printk(KERN_ERR
- "%s: use which platform_data?\n",
- dev_name(&pdev->dev));
- } else if (pdev->platform_data) {
- pdev->dev.platform_data = pdev->platform_data;
- } else if (pdev->dev.platform_data) {
- pdev->platform_data = pdev->dev.platform_data;
- }
-
for (i = 0; i < pdev->num_resources; i++) {
struct resource *p, *r = &pdev->resource[i];
@@ -990,6 +974,8 @@ int __init platform_bus_init(void)
{
int error;
+ early_platform_cleanup();
+
error = device_register(&platform_bus);
if (error)
return error;
@@ -1020,3 +1006,240 @@ u64 dma_get_required_mask(struct device *dev)
}
EXPORT_SYMBOL_GPL(dma_get_required_mask);
#endif
+
+static __initdata LIST_HEAD(early_platform_driver_list);
+static __initdata LIST_HEAD(early_platform_device_list);
+
+/**
+ * early_platform_driver_register
+ * @epdrv: early_platform driver structure
+ * @buf: string passed from early_param()
+ */
+int __init early_platform_driver_register(struct early_platform_driver *epdrv,
+ char *buf)
+{
+ unsigned long index;
+ int n;
+
+ /* Simply add the driver to the end of the global list.
+ * Drivers will by default be put on the list in compiled-in order.
+ */
+ if (!epdrv->list.next) {
+ INIT_LIST_HEAD(&epdrv->list);
+ list_add_tail(&epdrv->list, &early_platform_driver_list);
+ }
+
+ /* If the user has specified device then make sure the driver
+ * gets prioritized. The driver of the last device specified on
+ * command line will be put first on the list.
+ */
+ n = strlen(epdrv->pdrv->driver.name);
+ if (buf && !strncmp(buf, epdrv->pdrv->driver.name, n)) {
+ list_move(&epdrv->list, &early_platform_driver_list);
+
+ if (!strcmp(buf, epdrv->pdrv->driver.name))
+ epdrv->requested_id = -1;
+ else if (buf[n] == '.' && strict_strtoul(&buf[n + 1], 10,
+ &index) == 0)
+ epdrv->requested_id = index;
+ else
+ epdrv->requested_id = EARLY_PLATFORM_ID_ERROR;
+ }
+
+ return 0;
+}
+
+/**
+ * early_platform_add_devices - add a numbers of early platform devices
+ * @devs: array of early platform devices to add
+ * @num: number of early platform devices in array
+ */
+void __init early_platform_add_devices(struct platform_device **devs, int num)
+{
+ struct device *dev;
+ int i;
+
+ /* simply add the devices to list */
+ for (i = 0; i < num; i++) {
+ dev = &devs[i]->dev;
+
+ if (!dev->devres_head.next) {
+ INIT_LIST_HEAD(&dev->devres_head);
+ list_add_tail(&dev->devres_head,
+ &early_platform_device_list);
+ }
+ }
+}
+
+/**
+ * early_platform_driver_register_all
+ * @class_str: string to identify early platform driver class
+ */
+void __init early_platform_driver_register_all(char *class_str)
+{
+ /* The "class_str" parameter may or may not be present on the kernel
+ * command line. If it is present then there may be more than one
+ * matching parameter.
+ *
+ * Since we register our early platform drivers using early_param()
+ * we need to make sure that they also get registered in the case
+ * when the parameter is missing from the kernel command line.
+ *
+ * We use parse_early_options() to make sure the early_param() gets
+ * called at least once. The early_param() may be called more than
+ * once since the name of the preferred device may be specified on
+ * the kernel command line. early_platform_driver_register() handles
+ * this case for us.
+ */
+ parse_early_options(class_str);
+}
+
+/**
+ * early_platform_match
+ * @epdrv: early platform driver structure
+ * @id: id to match against
+ */
+static __init struct platform_device *
+early_platform_match(struct early_platform_driver *epdrv, int id)
+{
+ struct platform_device *pd;
+
+ list_for_each_entry(pd, &early_platform_device_list, dev.devres_head)
+ if (platform_match(&pd->dev, &epdrv->pdrv->driver))
+ if (pd->id == id)
+ return pd;
+
+ return NULL;
+}
+
+/**
+ * early_platform_left
+ * @epdrv: early platform driver structure
+ * @id: return true if id or above exists
+ */
+static __init int early_platform_left(struct early_platform_driver *epdrv,
+ int id)
+{
+ struct platform_device *pd;
+
+ list_for_each_entry(pd, &early_platform_device_list, dev.devres_head)
+ if (platform_match(&pd->dev, &epdrv->pdrv->driver))
+ if (pd->id >= id)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * early_platform_driver_probe_id
+ * @class_str: string to identify early platform driver class
+ * @id: id to match against
+ * @nr_probe: number of platform devices to successfully probe before exiting
+ */
+static int __init early_platform_driver_probe_id(char *class_str,
+ int id,
+ int nr_probe)
+{
+ struct early_platform_driver *epdrv;
+ struct platform_device *match;
+ int match_id;
+ int n = 0;
+ int left = 0;
+
+ list_for_each_entry(epdrv, &early_platform_driver_list, list) {
+ /* only use drivers matching our class_str */
+ if (strcmp(class_str, epdrv->class_str))
+ continue;
+
+ if (id == -2) {
+ match_id = epdrv->requested_id;
+ left = 1;
+
+ } else {
+ match_id = id;
+ left += early_platform_left(epdrv, id);
+
+ /* skip requested id */
+ switch (epdrv->requested_id) {
+ case EARLY_PLATFORM_ID_ERROR:
+ case EARLY_PLATFORM_ID_UNSET:
+ break;
+ default:
+ if (epdrv->requested_id == id)
+ match_id = EARLY_PLATFORM_ID_UNSET;
+ }
+ }
+
+ switch (match_id) {
+ case EARLY_PLATFORM_ID_ERROR:
+ pr_warning("%s: unable to parse %s parameter\n",
+ class_str, epdrv->pdrv->driver.name);
+ /* fall-through */
+ case EARLY_PLATFORM_ID_UNSET:
+ match = NULL;
+ break;
+ default:
+ match = early_platform_match(epdrv, match_id);
+ }
+
+ if (match) {
+ if (epdrv->pdrv->probe(match))
+ pr_warning("%s: unable to probe %s early.\n",
+ class_str, match->name);
+ else
+ n++;
+ }
+
+ if (n >= nr_probe)
+ break;
+ }
+
+ if (left)
+ return n;
+ else
+ return -ENODEV;
+}
+
+/**
+ * early_platform_driver_probe
+ * @class_str: string to identify early platform driver class
+ * @nr_probe: number of platform devices to successfully probe before exiting
+ * @user_only: only probe user specified early platform devices
+ */
+int __init early_platform_driver_probe(char *class_str,
+ int nr_probe,
+ int user_only)
+{
+ int k, n, i;
+
+ n = 0;
+ for (i = -2; n < nr_probe; i++) {
+ k = early_platform_driver_probe_id(class_str, i, nr_probe - n);
+
+ if (k < 0)
+ break;
+
+ n += k;
+
+ if (user_only)
+ break;
+ }
+
+ return n;
+}
+
+/**
+ * early_platform_cleanup - clean up early platform code
+ */
+void __init early_platform_cleanup(void)
+{
+ struct platform_device *pd, *pd2;
+
+ /* clean up the devres list used to chain devices */
+ list_for_each_entry_safe(pd, pd2, &early_platform_device_list,
+ dev.devres_head) {
+ list_del(&pd->dev.devres_head);
+ memset(&pd->dev.devres_head, 0, sizeof(pd->dev.devres_head));
+ }
+}
+
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 3236b434b964..9742a78c9fe4 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -343,11 +343,15 @@ static void __sysdev_resume(struct sys_device *dev)
/* First, call the class-specific one */
if (cls->resume)
cls->resume(dev);
+ WARN_ONCE(!irqs_disabled(),
+ "Interrupts enabled after %pF\n", cls->resume);
/* Call auxillary drivers next. */
list_for_each_entry(drv, &cls->drivers, entry) {
if (drv->resume)
drv->resume(dev);
+ WARN_ONCE(!irqs_disabled(),
+ "Interrupts enabled after %pF\n", drv->resume);
}
}
@@ -377,6 +381,9 @@ int sysdev_suspend(pm_message_t state)
if (ret)
return ret;
+ WARN_ONCE(!irqs_disabled(),
+ "Interrupts enabled while suspending system devices\n");
+
pr_debug("Suspending System Devices\n");
list_for_each_entry_reverse(cls, &system_kset->list, kset.kobj.entry) {
@@ -393,6 +400,9 @@ int sysdev_suspend(pm_message_t state)
if (ret)
goto aux_driver;
}
+ WARN_ONCE(!irqs_disabled(),
+ "Interrupts enabled after %pF\n",
+ drv->suspend);
}
/* Now call the generic one */
@@ -400,6 +410,9 @@ int sysdev_suspend(pm_message_t state)
ret = cls->suspend(sysdev, state);
if (ret)
goto cls_driver;
+ WARN_ONCE(!irqs_disabled(),
+ "Interrupts enabled after %pF\n",
+ cls->suspend);
}
}
}
@@ -452,6 +465,9 @@ int sysdev_resume(void)
{
struct sysdev_class *cls;
+ WARN_ONCE(!irqs_disabled(),
+ "Interrupts enabled while resuming system devices\n");
+
pr_debug("Resuming System Devices\n");
list_for_each_entry(cls, &system_kset->list, kset.kobj.entry) {
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index ddea8e485cc9..f42fa50d3550 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -412,7 +412,7 @@ config ATA_OVER_ETH
config MG_DISK
tristate "mGine mflash, gflash support"
- depends on ARM && ATA && GPIOLIB
+ depends on ARM && GPIOLIB
help
mGine mFlash(gFlash) block device driver
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 8df436ff7068..8ff95f2c0ede 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -1359,7 +1359,7 @@ static void redo_fd_request(void)
#endif
block = CURRENT->sector + cnt;
if ((int)block > floppy->blocks) {
- end_request(CURRENT, 0);
+ __blk_end_request_cur(CURRENT, -EIO);
goto repeat;
}
@@ -1371,13 +1371,8 @@ static void redo_fd_request(void)
"0x%08lx\n", track, sector, data);
#endif
- if ((rq_data_dir(CURRENT) != READ) && (rq_data_dir(CURRENT) != WRITE)) {
- printk(KERN_WARNING "do_fd_request: unknown command\n");
- end_request(CURRENT, 0);
- goto repeat;
- }
if (get_track(drive, track) == -1) {
- end_request(CURRENT, 0);
+ __blk_end_request_cur(CURRENT, -EIO);
goto repeat;
}
@@ -1391,7 +1386,7 @@ static void redo_fd_request(void)
/* keep the drive spinning while writes are scheduled */
if (!fd_motor_on(drive)) {
- end_request(CURRENT, 0);
+ __blk_end_request_cur(CURRENT, -EIO);
goto repeat;
}
/*
@@ -1407,10 +1402,8 @@ static void redo_fd_request(void)
break;
}
}
- CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
- CURRENT->sector += CURRENT->current_nr_sectors;
- end_request(CURRENT, 1);
+ __blk_end_request_cur(CURRENT, 0);
goto repeat;
}
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index 4234c11c1e4c..25067287211f 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -612,7 +612,7 @@ static void fd_error( void )
CURRENT->errors++;
if (CURRENT->errors >= MAX_ERRORS) {
printk(KERN_ERR "fd%d: too many errors.\n", SelectedDrive );
- end_request(CURRENT, 0);
+ __blk_end_request_cur(CURRENT, -EIO);
}
else if (CURRENT->errors == RECALIBRATE_ERRORS) {
printk(KERN_WARNING "fd%d: recalibrating\n", SelectedDrive );
@@ -732,9 +732,7 @@ static void do_fd_action( int drive )
}
else {
/* all sectors finished */
- CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
- CURRENT->sector += CURRENT->current_nr_sectors;
- end_request(CURRENT, 1);
+ __blk_end_request_cur(CURRENT, 0);
redo_fd_request();
return;
}
@@ -1139,9 +1137,7 @@ static void fd_rwsec_done1(int status)
}
else {
/* all sectors finished */
- CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
- CURRENT->sector += CURRENT->current_nr_sectors;
- end_request(CURRENT, 1);
+ __blk_end_request_cur(CURRENT, 0);
redo_fd_request();
}
return;
@@ -1414,7 +1410,7 @@ repeat:
if (!UD.connected) {
/* drive not connected */
printk(KERN_ERR "Unknown Device: fd%d\n", drive );
- end_request(CURRENT, 0);
+ __blk_end_request_cur(CURRENT, -EIO);
goto repeat;
}
@@ -1430,12 +1426,12 @@ repeat:
/* user supplied disk type */
if (--type >= NUM_DISK_MINORS) {
printk(KERN_WARNING "fd%d: invalid disk format", drive );
- end_request(CURRENT, 0);
+ __blk_end_request_cur(CURRENT, -EIO);
goto repeat;
}
if (minor2disktype[type].drive_types > DriveType) {
printk(KERN_WARNING "fd%d: unsupported disk format", drive );
- end_request(CURRENT, 0);
+ __blk_end_request_cur(CURRENT, -EIO);
goto repeat;
}
type = minor2disktype[type].index;
@@ -1445,7 +1441,7 @@ repeat:
}
if (CURRENT->sector + 1 > UDT->blocks) {
- end_request(CURRENT, 0);
+ __blk_end_request_cur(CURRENT, -EIO);
goto repeat;
}
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index bdd4f5f45575..5f7e64ba87e5 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -275,8 +275,10 @@ static int brd_do_bvec(struct brd_device *brd, struct page *page,
if (rw == READ) {
copy_from_brd(mem + off, brd, sector, len);
flush_dcache_page(page);
- } else
+ } else {
+ flush_dcache_page(page);
copy_to_brd(brd, mem + off, sector, len);
+ }
kunmap_atomic(mem, KM_USER0);
out:
@@ -436,6 +438,7 @@ static struct brd_device *brd_alloc(int i)
if (!brd->brd_queue)
goto out_free_dev;
blk_queue_make_request(brd->brd_queue, brd_make_request);
+ blk_queue_ordered(brd->brd_queue, QUEUE_ORDERED_TAG, NULL);
blk_queue_max_sectors(brd->brd_queue, 1024);
blk_queue_bounce_limit(brd->brd_queue, BLK_BOUNCE_ANY);
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 0ef6f08aa6ea..4d4d5e0d3fa6 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -3505,7 +3505,7 @@ static __devinit int cciss_message(struct pci_dev *pdev, unsigned char opcode, u
/* The Inbound Post Queue only accepts 32-bit physical addresses for the
CCISS commands, so they must be allocated from the lower 4GiB of
memory. */
- err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
if (err) {
iounmap(vaddr);
return -ENOMEM;
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index ca268ca11159..488a8f4a60aa 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -1024,8 +1024,7 @@ static inline void complete_command(cmdlist_t *cmd, int timeout)
cmd->req.sg[i].size, ddir);
DBGPX(printk("Done with %p\n", rq););
- if (__blk_end_request(rq, error, blk_rq_bytes(rq)))
- BUG();
+ __blk_end_request_all(rq, error);
}
/*
diff --git a/drivers/block/hd.c b/drivers/block/hd.c
index 3c11f062a18c..75b9ca95c4eb 100644
--- a/drivers/block/hd.c
+++ b/drivers/block/hd.c
@@ -410,7 +410,7 @@ static void bad_rw_intr(void)
if (req != NULL) {
struct hd_i_struct *disk = req->rq_disk->private_data;
if (++req->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
disk->special_op = disk->recalibrate = 1;
} else if (req->errors % RESET_FREQ == 0)
reset = 1;
@@ -452,32 +452,25 @@ static void read_intr(void)
bad_rw_intr();
hd_request();
return;
+
ok_to_read:
req = CURRENT;
insw(HD_DATA, req->buffer, 256);
- req->sector++;
- req->buffer += 512;
- req->errors = 0;
- i = --req->nr_sectors;
- --req->current_nr_sectors;
#ifdef DEBUG
printk("%s: read: sector %ld, remaining = %ld, buffer=%p\n",
- req->rq_disk->disk_name, req->sector, req->nr_sectors,
+ req->rq_disk->disk_name, req->sector + 1, req->nr_sectors - 1,
req->buffer+512);
#endif
- if (req->current_nr_sectors <= 0)
- end_request(req, 1);
- if (i > 0) {
+ if (__blk_end_request(req, 0, 512)) {
SET_HANDLER(&read_intr);
return;
}
+
(void) inb_p(HD_STATUS);
#if (HD_DELAY > 0)
last_req = read_timer();
#endif
- if (elv_next_request(QUEUE))
- hd_request();
- return;
+ hd_request();
}
static void write_intr(void)
@@ -499,24 +492,18 @@ static void write_intr(void)
bad_rw_intr();
hd_request();
return;
+
ok_to_write:
- req->sector++;
- i = --req->nr_sectors;
- --req->current_nr_sectors;
- req->buffer += 512;
- if (!i || (req->bio && req->current_nr_sectors <= 0))
- end_request(req, 1);
- if (i > 0) {
+ if (__blk_end_request(req, 0, 512)) {
SET_HANDLER(&write_intr);
outsw(HD_DATA, req->buffer, 256);
- local_irq_enable();
- } else {
+ return;
+ }
+
#if (HD_DELAY > 0)
- last_req = read_timer();
+ last_req = read_timer();
#endif
- hd_request();
- }
- return;
+ hd_request();
}
static void recal_intr(void)
@@ -541,8 +528,7 @@ static void hd_times_out(unsigned long dummy)
if (!CURRENT)
return;
- disable_irq(HD_IRQ);
- local_irq_enable();
+ spin_lock_irq(hd_queue->queue_lock);
reset = 1;
name = CURRENT->rq_disk->disk_name;
printk("%s: timeout\n", name);
@@ -550,11 +536,10 @@ static void hd_times_out(unsigned long dummy)
#ifdef DEBUG
printk("%s: too many errors\n", name);
#endif
- end_request(CURRENT, 0);
+ __blk_end_request_cur(CURRENT, -EIO);
}
- local_irq_disable();
hd_request();
- enable_irq(HD_IRQ);
+ spin_unlock_irq(hd_queue->queue_lock);
}
static int do_special_op(struct hd_i_struct *disk, struct request *req)
@@ -566,7 +551,7 @@ static int do_special_op(struct hd_i_struct *disk, struct request *req)
}
if (disk->head > 16) {
printk("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name);
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
}
disk->special_op = 0;
return 1;
@@ -592,7 +577,6 @@ static void hd_request(void)
return;
repeat:
del_timer(&device_timer);
- local_irq_enable();
req = CURRENT;
if (!req) {
@@ -601,7 +585,6 @@ repeat:
}
if (reset) {
- local_irq_disable();
reset_hd();
return;
}
@@ -612,7 +595,7 @@ repeat:
((block+nsect) > get_capacity(req->rq_disk))) {
printk("%s: bad access: block=%d, count=%d\n",
req->rq_disk->disk_name, block, nsect);
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
goto repeat;
}
@@ -652,7 +635,7 @@ repeat:
break;
default:
printk("unknown hd-command\n");
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
break;
}
}
@@ -660,9 +643,7 @@ repeat:
static void do_hd_request(struct request_queue *q)
{
- disable_irq(HD_IRQ);
hd_request();
- enable_irq(HD_IRQ);
}
static int hd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
@@ -684,12 +665,16 @@ static irqreturn_t hd_interrupt(int irq, void *dev_id)
{
void (*handler)(void) = do_hd;
+ spin_lock(hd_queue->queue_lock);
+
do_hd = NULL;
del_timer(&device_timer);
if (!handler)
handler = unexpected_hd_interrupt;
handler();
- local_irq_enable();
+
+ spin_unlock(hd_queue->queue_lock);
+
return IRQ_HANDLED;
}
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index ddae80825899..9ca4bb014657 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -511,11 +511,7 @@ out:
*/
static void loop_add_bio(struct loop_device *lo, struct bio *bio)
{
- if (lo->lo_biotail) {
- lo->lo_biotail->bi_next = bio;
- lo->lo_biotail = bio;
- } else
- lo->lo_bio = lo->lo_biotail = bio;
+ bio_list_add(&lo->lo_bio_list, bio);
}
/*
@@ -523,16 +519,7 @@ static void loop_add_bio(struct loop_device *lo, struct bio *bio)
*/
static struct bio *loop_get_bio(struct loop_device *lo)
{
- struct bio *bio;
-
- if ((bio = lo->lo_bio)) {
- if (bio == lo->lo_biotail)
- lo->lo_biotail = NULL;
- lo->lo_bio = bio->bi_next;
- bio->bi_next = NULL;
- }
-
- return bio;
+ return bio_list_pop(&lo->lo_bio_list);
}
static int loop_make_request(struct request_queue *q, struct bio *old_bio)
@@ -609,12 +596,13 @@ static int loop_thread(void *data)
set_user_nice(current, -20);
- while (!kthread_should_stop() || lo->lo_bio) {
+ while (!kthread_should_stop() || !bio_list_empty(&lo->lo_bio_list)) {
wait_event_interruptible(lo->lo_event,
- lo->lo_bio || kthread_should_stop());
+ !bio_list_empty(&lo->lo_bio_list) ||
+ kthread_should_stop());
- if (!lo->lo_bio)
+ if (bio_list_empty(&lo->lo_bio_list))
continue;
spin_lock_irq(&lo->lo_lock);
bio = loop_get_bio(lo);
@@ -841,7 +829,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
lo->old_gfp_mask = mapping_gfp_mask(mapping);
mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
- lo->lo_bio = lo->lo_biotail = NULL;
+ bio_list_init(&lo->lo_bio_list);
/*
* set queue make_request_fn, and add limits based on lower level
diff --git a/drivers/block/mg_disk.c b/drivers/block/mg_disk.c
index fb39d9aa3cdc..71e56cc28cac 100644
--- a/drivers/block/mg_disk.c
+++ b/drivers/block/mg_disk.c
@@ -17,15 +17,158 @@
#include <linux/fs.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>
-#include <linux/libata.h>
+#include <linux/ata.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
-#include <linux/mg_disk.h>
#define MG_RES_SEC (CONFIG_MG_DISK_RES << 1)
+/* name for block device */
+#define MG_DISK_NAME "mgd"
+/* name for platform device */
+#define MG_DEV_NAME "mg_disk"
+
+#define MG_DISK_MAJ 0
+#define MG_DISK_MAX_PART 16
+#define MG_SECTOR_SIZE 512
+#define MG_MAX_SECTS 256
+
+/* Register offsets */
+#define MG_BUFF_OFFSET 0x8000
+#define MG_STORAGE_BUFFER_SIZE 0x200
+#define MG_REG_OFFSET 0xC000
+#define MG_REG_FEATURE (MG_REG_OFFSET + 2) /* write case */
+#define MG_REG_ERROR (MG_REG_OFFSET + 2) /* read case */
+#define MG_REG_SECT_CNT (MG_REG_OFFSET + 4)
+#define MG_REG_SECT_NUM (MG_REG_OFFSET + 6)
+#define MG_REG_CYL_LOW (MG_REG_OFFSET + 8)
+#define MG_REG_CYL_HIGH (MG_REG_OFFSET + 0xA)
+#define MG_REG_DRV_HEAD (MG_REG_OFFSET + 0xC)
+#define MG_REG_COMMAND (MG_REG_OFFSET + 0xE) /* write case */
+#define MG_REG_STATUS (MG_REG_OFFSET + 0xE) /* read case */
+#define MG_REG_DRV_CTRL (MG_REG_OFFSET + 0x10)
+#define MG_REG_BURST_CTRL (MG_REG_OFFSET + 0x12)
+
+/* handy status */
+#define MG_STAT_READY (ATA_DRDY | ATA_DSC)
+#define MG_READY_OK(s) (((s) & (MG_STAT_READY | (ATA_BUSY | ATA_DF | \
+ ATA_ERR))) == MG_STAT_READY)
+
+/* error code for others */
+#define MG_ERR_NONE 0
+#define MG_ERR_TIMEOUT 0x100
+#define MG_ERR_INIT_STAT 0x101
+#define MG_ERR_TRANSLATION 0x102
+#define MG_ERR_CTRL_RST 0x103
+#define MG_ERR_INV_STAT 0x104
+#define MG_ERR_RSTOUT 0x105
+
+#define MG_MAX_ERRORS 6 /* Max read/write errors */
+
+/* command */
+#define MG_CMD_RD 0x20
+#define MG_CMD_WR 0x30
+#define MG_CMD_SLEEP 0x99
+#define MG_CMD_WAKEUP 0xC3
+#define MG_CMD_ID 0xEC
+#define MG_CMD_WR_CONF 0x3C
+#define MG_CMD_RD_CONF 0x40
+
+/* operation mode */
+#define MG_OP_CASCADE (1 << 0)
+#define MG_OP_CASCADE_SYNC_RD (1 << 1)
+#define MG_OP_CASCADE_SYNC_WR (1 << 2)
+#define MG_OP_INTERLEAVE (1 << 3)
+
+/* synchronous */
+#define MG_BURST_LAT_4 (3 << 4)
+#define MG_BURST_LAT_5 (4 << 4)
+#define MG_BURST_LAT_6 (5 << 4)
+#define MG_BURST_LAT_7 (6 << 4)
+#define MG_BURST_LAT_8 (7 << 4)
+#define MG_BURST_LEN_4 (1 << 1)
+#define MG_BURST_LEN_8 (2 << 1)
+#define MG_BURST_LEN_16 (3 << 1)
+#define MG_BURST_LEN_32 (4 << 1)
+#define MG_BURST_LEN_CONT (0 << 1)
+
+/* timeout value (unit: ms) */
+#define MG_TMAX_CONF_TO_CMD 1
+#define MG_TMAX_WAIT_RD_DRQ 10
+#define MG_TMAX_WAIT_WR_DRQ 500
+#define MG_TMAX_RST_TO_BUSY 10
+#define MG_TMAX_HDRST_TO_RDY 500
+#define MG_TMAX_SWRST_TO_RDY 500
+#define MG_TMAX_RSTOUT 3000
+
+/* device attribution */
+/* use mflash as boot device */
+#define MG_BOOT_DEV (1 << 0)
+/* use mflash as storage device */
+#define MG_STORAGE_DEV (1 << 1)
+/* same as MG_STORAGE_DEV, but bootloader already done reset sequence */
+#define MG_STORAGE_DEV_SKIP_RST (1 << 2)
+
+#define MG_DEV_MASK (MG_BOOT_DEV | MG_STORAGE_DEV | MG_STORAGE_DEV_SKIP_RST)
+
+/* names of GPIO resource */
+#define MG_RST_PIN "mg_rst"
+/* except MG_BOOT_DEV, reset-out pin should be assigned */
+#define MG_RSTOUT_PIN "mg_rstout"
+
+/* private driver data */
+struct mg_drv_data {
+ /* disk resource */
+ u32 use_polling;
+
+ /* device attribution */
+ u32 dev_attr;
+
+ /* internally used */
+ struct mg_host *host;
+};
+
+/* main structure for mflash driver */
+struct mg_host {
+ struct device *dev;
+
+ struct request_queue *breq;
+ spinlock_t lock;
+ struct gendisk *gd;
+
+ struct timer_list timer;
+ void (*mg_do_intr) (struct mg_host *);
+
+ u16 id[ATA_ID_WORDS];
+
+ u16 cyls;
+ u16 heads;
+ u16 sectors;
+ u32 n_sectors;
+ u32 nres_sectors;
+
+ void __iomem *dev_base;
+ unsigned int irq;
+ unsigned int rst;
+ unsigned int rstout;
+
+ u32 major;
+ u32 error;
+};
+
+/*
+ * Debugging macro and defines
+ */
+#undef DO_MG_DEBUG
+#ifdef DO_MG_DEBUG
+# define MG_DBG(fmt, args...) \
+ printk(KERN_DEBUG "%s:%d "fmt, __func__, __LINE__, ##args)
+#else /* CONFIG_MG_DEBUG */
+# define MG_DBG(fmt, args...) do { } while (0)
+#endif /* CONFIG_MG_DEBUG */
+
static void mg_request(struct request_queue *);
static void mg_dump_status(const char *msg, unsigned int stat,
@@ -41,45 +184,43 @@ static void mg_dump_status(const char *msg, unsigned int stat,
}
printk(KERN_ERR "%s: %s: status=0x%02x { ", name, msg, stat & 0xff);
- if (stat & MG_REG_STATUS_BIT_BUSY)
+ if (stat & ATA_BUSY)
printk("Busy ");
- if (stat & MG_REG_STATUS_BIT_READY)
+ if (stat & ATA_DRDY)
printk("DriveReady ");
- if (stat & MG_REG_STATUS_BIT_WRITE_FAULT)
+ if (stat & ATA_DF)
printk("WriteFault ");
- if (stat & MG_REG_STATUS_BIT_SEEK_DONE)
+ if (stat & ATA_DSC)
printk("SeekComplete ");
- if (stat & MG_REG_STATUS_BIT_DATA_REQ)
+ if (stat & ATA_DRQ)
printk("DataRequest ");
- if (stat & MG_REG_STATUS_BIT_CORRECTED_ERROR)
+ if (stat & ATA_CORR)
printk("CorrectedError ");
- if (stat & MG_REG_STATUS_BIT_ERROR)
+ if (stat & ATA_ERR)
printk("Error ");
printk("}\n");
- if ((stat & MG_REG_STATUS_BIT_ERROR) == 0) {
+ if ((stat & ATA_ERR) == 0) {
host->error = 0;
} else {
host->error = inb((unsigned long)host->dev_base + MG_REG_ERROR);
printk(KERN_ERR "%s: %s: error=0x%02x { ", name, msg,
host->error & 0xff);
- if (host->error & MG_REG_ERR_BBK)
+ if (host->error & ATA_BBK)
printk("BadSector ");
- if (host->error & MG_REG_ERR_UNC)
+ if (host->error & ATA_UNC)
printk("UncorrectableError ");
- if (host->error & MG_REG_ERR_IDNF)
+ if (host->error & ATA_IDNF)
printk("SectorIdNotFound ");
- if (host->error & MG_REG_ERR_ABRT)
+ if (host->error & ATA_ABORTED)
printk("DriveStatusError ");
- if (host->error & MG_REG_ERR_AMNF)
+ if (host->error & ATA_AMNF)
printk("AddrMarkNotFound ");
printk("}");
- if (host->error &
- (MG_REG_ERR_BBK | MG_REG_ERR_UNC |
- MG_REG_ERR_IDNF | MG_REG_ERR_AMNF)) {
+ if (host->error & (ATA_BBK | ATA_UNC | ATA_IDNF | ATA_AMNF)) {
if (host->breq) {
req = elv_next_request(host->breq);
if (req)
- printk(", sector=%ld", req->sector);
+ printk(", sector=%u", (u32)req->sector);
}
}
@@ -100,12 +241,12 @@ static unsigned int mg_wait(struct mg_host *host, u32 expect, u32 msec)
do {
cur_jiffies = jiffies;
- if (status & MG_REG_STATUS_BIT_BUSY) {
- if (expect == MG_REG_STATUS_BIT_BUSY)
+ if (status & ATA_BUSY) {
+ if (expect == ATA_BUSY)
break;
} else {
/* Check the error condition! */
- if (status & MG_REG_STATUS_BIT_ERROR) {
+ if (status & ATA_ERR) {
mg_dump_status("mg_wait", status, host);
break;
}
@@ -114,8 +255,8 @@ static unsigned int mg_wait(struct mg_host *host, u32 expect, u32 msec)
if (MG_READY_OK(status))
break;
- if (expect == MG_REG_STATUS_BIT_DATA_REQ)
- if (status & MG_REG_STATUS_BIT_DATA_REQ)
+ if (expect == ATA_DRQ)
+ if (status & ATA_DRQ)
break;
}
if (!msec) {
@@ -160,14 +301,55 @@ static irqreturn_t mg_irq(int irq, void *dev_id)
struct mg_host *host = dev_id;
void (*handler)(struct mg_host *) = host->mg_do_intr;
- host->mg_do_intr = 0;
+ spin_lock(&host->lock);
+
+ host->mg_do_intr = NULL;
del_timer(&host->timer);
if (!handler)
handler = mg_unexpected_intr;
handler(host);
+
+ spin_unlock(&host->lock);
+
return IRQ_HANDLED;
}
+/* local copy of ata_id_string() */
+static void mg_id_string(const u16 *id, unsigned char *s,
+ unsigned int ofs, unsigned int len)
+{
+ unsigned int c;
+
+ BUG_ON(len & 1);
+
+ while (len > 0) {
+ c = id[ofs] >> 8;
+ *s = c;
+ s++;
+
+ c = id[ofs] & 0xff;
+ *s = c;
+ s++;
+
+ ofs++;
+ len -= 2;
+ }
+}
+
+/* local copy of ata_id_c_string() */
+static void mg_id_c_string(const u16 *id, unsigned char *s,
+ unsigned int ofs, unsigned int len)
+{
+ unsigned char *p;
+
+ mg_id_string(id, s, ofs, len - 1);
+
+ p = s + strnlen(s, len - 1);
+ while (p > s && p[-1] == ' ')
+ p--;
+ *p = '\0';
+}
+
static int mg_get_disk_id(struct mg_host *host)
{
u32 i;
@@ -179,12 +361,10 @@ static int mg_get_disk_id(struct mg_host *host)
char serial[ATA_ID_SERNO_LEN + 1];
if (!prv_data->use_polling)
- outb(MG_REG_CTRL_INTR_DISABLE,
- (unsigned long)host->dev_base +
- MG_REG_DRV_CTRL);
+ outb(ATA_NIEN, (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
outb(MG_CMD_ID, (unsigned long)host->dev_base + MG_REG_COMMAND);
- err = mg_wait(host, MG_REG_STATUS_BIT_DATA_REQ, MG_TMAX_WAIT_RD_DRQ);
+ err = mg_wait(host, ATA_DRQ, MG_TMAX_WAIT_RD_DRQ);
if (err)
return err;
@@ -214,9 +394,9 @@ static int mg_get_disk_id(struct mg_host *host)
host->n_sectors -= host->nres_sectors;
}
- ata_id_c_string(id, fwrev, ATA_ID_FW_REV, sizeof(fwrev));
- ata_id_c_string(id, model, ATA_ID_PROD, sizeof(model));
- ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial));
+ mg_id_c_string(id, fwrev, ATA_ID_FW_REV, sizeof(fwrev));
+ mg_id_c_string(id, model, ATA_ID_PROD, sizeof(model));
+ mg_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial));
printk(KERN_INFO "mg_disk: model: %s\n", model);
printk(KERN_INFO "mg_disk: firm: %.8s\n", fwrev);
printk(KERN_INFO "mg_disk: serial: %s\n", serial);
@@ -224,8 +404,7 @@ static int mg_get_disk_id(struct mg_host *host)
host->n_sectors, host->nres_sectors);
if (!prv_data->use_polling)
- outb(MG_REG_CTRL_INTR_ENABLE, (unsigned long)host->dev_base +
- MG_REG_DRV_CTRL);
+ outb(0, (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
return err;
}
@@ -239,7 +418,7 @@ static int mg_disk_init(struct mg_host *host)
/* hdd rst low */
gpio_set_value(host->rst, 0);
- err = mg_wait(host, MG_REG_STATUS_BIT_BUSY, MG_TMAX_RST_TO_BUSY);
+ err = mg_wait(host, ATA_BUSY, MG_TMAX_RST_TO_BUSY);
if (err)
return err;
@@ -250,17 +429,14 @@ static int mg_disk_init(struct mg_host *host)
return err;
/* soft reset on */
- outb(MG_REG_CTRL_RESET |
- (prv_data->use_polling ? MG_REG_CTRL_INTR_DISABLE :
- MG_REG_CTRL_INTR_ENABLE),
+ outb(ATA_SRST | (prv_data->use_polling ? ATA_NIEN : 0),
(unsigned long)host->dev_base + MG_REG_DRV_CTRL);
- err = mg_wait(host, MG_REG_STATUS_BIT_BUSY, MG_TMAX_RST_TO_BUSY);
+ err = mg_wait(host, ATA_BUSY, MG_TMAX_RST_TO_BUSY);
if (err)
return err;
/* soft reset off */
- outb(prv_data->use_polling ? MG_REG_CTRL_INTR_DISABLE :
- MG_REG_CTRL_INTR_ENABLE,
+ outb(prv_data->use_polling ? ATA_NIEN : 0,
(unsigned long)host->dev_base + MG_REG_DRV_CTRL);
err = mg_wait(host, MG_STAT_READY, MG_TMAX_SWRST_TO_RDY);
if (err)
@@ -280,7 +456,7 @@ static void mg_bad_rw_intr(struct mg_host *host)
if (req != NULL)
if (++req->errors >= MG_MAX_ERRORS ||
host->error == MG_ERR_TIMEOUT)
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
}
static unsigned int mg_out(struct mg_host *host,
@@ -306,7 +482,7 @@ static unsigned int mg_out(struct mg_host *host,
MG_REG_CYL_LOW);
outb((u8)(sect_num >> 16), (unsigned long)host->dev_base +
MG_REG_CYL_HIGH);
- outb((u8)((sect_num >> 24) | MG_REG_HEAD_LBA_MODE),
+ outb((u8)((sect_num >> 24) | ATA_LBA | ATA_DEVICE_OBS),
(unsigned long)host->dev_base + MG_REG_DRV_HEAD);
outb(cmd, (unsigned long)host->dev_base + MG_REG_COMMAND);
return MG_ERR_NONE;
@@ -314,105 +490,77 @@ static unsigned int mg_out(struct mg_host *host,
static void mg_read(struct request *req)
{
- u32 remains, j;
+ u32 j;
struct mg_host *host = req->rq_disk->private_data;
- remains = req->nr_sectors;
-
- if (mg_out(host, req->sector, req->nr_sectors, MG_CMD_RD, 0) !=
+ if (mg_out(host, req->sector, req->nr_sectors, MG_CMD_RD, NULL) !=
MG_ERR_NONE)
mg_bad_rw_intr(host);
MG_DBG("requested %d sects (from %ld), buffer=0x%p\n",
- remains, req->sector, req->buffer);
+ req->nr_sectors, req->sector, req->buffer);
- while (remains) {
- if (mg_wait(host, MG_REG_STATUS_BIT_DATA_REQ,
- MG_TMAX_WAIT_RD_DRQ) != MG_ERR_NONE) {
+ do {
+ u16 *buff = (u16 *)req->buffer;
+
+ if (mg_wait(host, ATA_DRQ,
+ MG_TMAX_WAIT_RD_DRQ) != MG_ERR_NONE) {
mg_bad_rw_intr(host);
return;
}
- for (j = 0; j < MG_SECTOR_SIZE >> 1; j++) {
- *(u16 *)req->buffer =
- inw((unsigned long)host->dev_base +
- MG_BUFF_OFFSET + (j << 1));
- req->buffer += 2;
- }
-
- req->sector++;
- req->errors = 0;
- remains = --req->nr_sectors;
- --req->current_nr_sectors;
-
- if (req->current_nr_sectors <= 0) {
- MG_DBG("remain : %d sects\n", remains);
- end_request(req, 1);
- if (remains > 0)
- req = elv_next_request(host->breq);
- }
+ for (j = 0; j < MG_SECTOR_SIZE >> 1; j++)
+ *buff++ = inw((unsigned long)host->dev_base +
+ MG_BUFF_OFFSET + (j << 1));
outb(MG_CMD_RD_CONF, (unsigned long)host->dev_base +
MG_REG_COMMAND);
- }
+ } while (__blk_end_request(req, 0, MG_SECTOR_SIZE));
}
static void mg_write(struct request *req)
{
- u32 remains, j;
+ u32 j;
struct mg_host *host = req->rq_disk->private_data;
- remains = req->nr_sectors;
-
- if (mg_out(host, req->sector, req->nr_sectors, MG_CMD_WR, 0) !=
+ if (mg_out(host, req->sector, req->nr_sectors, MG_CMD_WR, NULL) !=
MG_ERR_NONE) {
mg_bad_rw_intr(host);
return;
}
-
MG_DBG("requested %d sects (from %ld), buffer=0x%p\n",
- remains, req->sector, req->buffer);
- while (remains) {
- if (mg_wait(host, MG_REG_STATUS_BIT_DATA_REQ,
- MG_TMAX_WAIT_WR_DRQ) != MG_ERR_NONE) {
+ req->nr_sectors, req->sector, req->buffer);
+
+ do {
+ u16 *buff = (u16 *)req->buffer;
+
+ if (mg_wait(host, ATA_DRQ, MG_TMAX_WAIT_WR_DRQ) != MG_ERR_NONE) {
mg_bad_rw_intr(host);
return;
}
- for (j = 0; j < MG_SECTOR_SIZE >> 1; j++) {
- outw(*(u16 *)req->buffer,
- (unsigned long)host->dev_base +
- MG_BUFF_OFFSET + (j << 1));
- req->buffer += 2;
- }
- req->sector++;
- remains = --req->nr_sectors;
- --req->current_nr_sectors;
-
- if (req->current_nr_sectors <= 0) {
- MG_DBG("remain : %d sects\n", remains);
- end_request(req, 1);
- if (remains > 0)
- req = elv_next_request(host->breq);
- }
+ for (j = 0; j < MG_SECTOR_SIZE >> 1; j++)
+ outw(*buff++, (unsigned long)host->dev_base +
+ MG_BUFF_OFFSET + (j << 1));
outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base +
MG_REG_COMMAND);
- }
+ } while (__blk_end_request(req, 0, MG_SECTOR_SIZE));
}
static void mg_read_intr(struct mg_host *host)
{
u32 i;
+ u16 *buff;
struct request *req;
/* check status */
do {
i = inb((unsigned long)host->dev_base + MG_REG_STATUS);
- if (i & MG_REG_STATUS_BIT_BUSY)
+ if (i & ATA_BUSY)
break;
if (!MG_READY_OK(i))
break;
- if (i & MG_REG_STATUS_BIT_DATA_REQ)
+ if (i & ATA_DRQ)
goto ok_to_read;
} while (0);
mg_dump_status("mg_read_intr", i, host);
@@ -423,39 +571,24 @@ static void mg_read_intr(struct mg_host *host)
ok_to_read:
/* get current segment of request */
req = elv_next_request(host->breq);
+ buff = (u16 *)req->buffer;
/* read 1 sector */
- for (i = 0; i < MG_SECTOR_SIZE >> 1; i++) {
- *(u16 *)req->buffer =
- inw((unsigned long)host->dev_base + MG_BUFF_OFFSET +
- (i << 1));
- req->buffer += 2;
- }
+ for (i = 0; i < MG_SECTOR_SIZE >> 1; i++)
+ *buff++ = inw((unsigned long)host->dev_base + MG_BUFF_OFFSET +
+ (i << 1));
- /* manipulate request */
MG_DBG("sector %ld, remaining=%ld, buffer=0x%p\n",
req->sector, req->nr_sectors - 1, req->buffer);
- req->sector++;
- req->errors = 0;
- i = --req->nr_sectors;
- --req->current_nr_sectors;
-
- /* let know if current segment done */
- if (req->current_nr_sectors <= 0)
- end_request(req, 1);
-
- /* set handler if read remains */
- if (i > 0) {
- host->mg_do_intr = mg_read_intr;
- mod_timer(&host->timer, jiffies + 3 * HZ);
- }
-
/* send read confirm */
outb(MG_CMD_RD_CONF, (unsigned long)host->dev_base + MG_REG_COMMAND);
- /* goto next request */
- if (!i)
+ if (__blk_end_request(req, 0, MG_SECTOR_SIZE)) {
+ /* set handler if read remains */
+ host->mg_do_intr = mg_read_intr;
+ mod_timer(&host->timer, jiffies + 3 * HZ);
+ } else /* goto next request */
mg_request(host->breq);
}
@@ -464,6 +597,7 @@ static void mg_write_intr(struct mg_host *host)
u32 i, j;
u16 *buff;
struct request *req;
+ bool rem;
/* get current segment of request */
req = elv_next_request(host->breq);
@@ -471,11 +605,11 @@ static void mg_write_intr(struct mg_host *host)
/* check status */
do {
i = inb((unsigned long)host->dev_base + MG_REG_STATUS);
- if (i & MG_REG_STATUS_BIT_BUSY)
+ if (i & ATA_BUSY)
break;
if (!MG_READY_OK(i))
break;
- if ((req->nr_sectors <= 1) || (i & MG_REG_STATUS_BIT_DATA_REQ))
+ if ((req->nr_sectors <= 1) || (i & ATA_DRQ))
goto ok_to_write;
} while (0);
mg_dump_status("mg_write_intr", i, host);
@@ -484,18 +618,8 @@ static void mg_write_intr(struct mg_host *host)
return;
ok_to_write:
- /* manipulate request */
- req->sector++;
- i = --req->nr_sectors;
- --req->current_nr_sectors;
- req->buffer += MG_SECTOR_SIZE;
-
- /* let know if current segment or all done */
- if (!i || (req->bio && req->current_nr_sectors <= 0))
- end_request(req, 1);
-
- /* write 1 sector and set handler if remains */
- if (i > 0) {
+ if ((rem = __blk_end_request(req, 0, MG_SECTOR_SIZE))) {
+ /* write 1 sector and set handler if remains */
buff = (u16 *)req->buffer;
for (j = 0; j < MG_STORAGE_BUFFER_SIZE >> 1; j++) {
outw(*buff, (unsigned long)host->dev_base +
@@ -511,7 +635,7 @@ ok_to_write:
/* send write confirm */
outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base + MG_REG_COMMAND);
- if (!i)
+ if (!rem)
mg_request(host->breq);
}
@@ -521,9 +645,11 @@ void mg_times_out(unsigned long data)
char *name;
struct request *req;
+ spin_lock_irq(&host->lock);
+
req = elv_next_request(host->breq);
if (!req)
- return;
+ goto out_unlock;
host->mg_do_intr = NULL;
@@ -534,6 +660,8 @@ void mg_times_out(unsigned long data)
mg_bad_rw_intr(host);
mg_request(host->breq);
+out_unlock:
+ spin_unlock_irq(&host->lock);
}
static void mg_request_poll(struct request_queue *q)
@@ -551,11 +679,6 @@ static void mg_request_poll(struct request_queue *q)
case WRITE:
mg_write(req);
break;
- default:
- printk(KERN_WARNING "%s:%d unknown command\n",
- __func__, __LINE__);
- end_request(req, 0);
- break;
}
}
}
@@ -579,18 +702,15 @@ static unsigned int mg_issue_req(struct request *req,
break;
case WRITE:
/* TODO : handler */
- outb(MG_REG_CTRL_INTR_DISABLE,
- (unsigned long)host->dev_base +
- MG_REG_DRV_CTRL);
+ outb(ATA_NIEN, (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
if (mg_out(host, sect_num, sect_cnt, MG_CMD_WR, &mg_write_intr)
!= MG_ERR_NONE) {
mg_bad_rw_intr(host);
return host->error;
}
del_timer(&host->timer);
- mg_wait(host, MG_REG_STATUS_BIT_DATA_REQ, MG_TMAX_WAIT_WR_DRQ);
- outb(MG_REG_CTRL_INTR_ENABLE, (unsigned long)host->dev_base +
- MG_REG_DRV_CTRL);
+ mg_wait(host, ATA_DRQ, MG_TMAX_WAIT_WR_DRQ);
+ outb(0, (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
if (host->error) {
mg_bad_rw_intr(host);
return host->error;
@@ -605,11 +725,6 @@ static unsigned int mg_issue_req(struct request *req,
outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base +
MG_REG_COMMAND);
break;
- default:
- printk(KERN_WARNING "%s:%d unknown command\n",
- __func__, __LINE__);
- end_request(req, 0);
- break;
}
return MG_ERR_NONE;
}
@@ -646,7 +761,7 @@ static void mg_request(struct request_queue *q)
"%s: bad access: sector=%d, count=%d\n",
req->rq_disk->disk_name,
sect_num, sect_cnt);
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
continue;
}
@@ -681,9 +796,7 @@ static int mg_suspend(struct platform_device *plat_dev, pm_message_t state)
return -EIO;
if (!prv_data->use_polling)
- outb(MG_REG_CTRL_INTR_DISABLE,
- (unsigned long)host->dev_base +
- MG_REG_DRV_CTRL);
+ outb(ATA_NIEN, (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
outb(MG_CMD_SLEEP, (unsigned long)host->dev_base + MG_REG_COMMAND);
/* wait until mflash deep sleep */
@@ -691,9 +804,7 @@ static int mg_suspend(struct platform_device *plat_dev, pm_message_t state)
if (mg_wait(host, MG_STAT_READY, MG_TMAX_CONF_TO_CMD)) {
if (!prv_data->use_polling)
- outb(MG_REG_CTRL_INTR_ENABLE,
- (unsigned long)host->dev_base +
- MG_REG_DRV_CTRL);
+ outb(0, (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
return -EIO;
}
@@ -716,8 +827,7 @@ static int mg_resume(struct platform_device *plat_dev)
return -EIO;
if (!prv_data->use_polling)
- outb(MG_REG_CTRL_INTR_ENABLE, (unsigned long)host->dev_base +
- MG_REG_DRV_CTRL);
+ outb(0, (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
return 0;
}
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index e91d4b4b014f..9fd57c2aa463 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -735,16 +735,16 @@ static void do_pcd_request(struct request_queue * q)
ps_set_intr(do_pcd_read, NULL, 0, nice);
return;
} else
- end_request(pcd_req, 0);
+ __blk_end_request_cur(pcd_req, -EIO);
}
}
-static inline void next_request(int success)
+static inline void next_request(int err)
{
unsigned long saved_flags;
spin_lock_irqsave(&pcd_lock, saved_flags);
- end_request(pcd_req, success);
+ __blk_end_request_cur(pcd_req, err);
pcd_busy = 0;
do_pcd_request(pcd_queue);
spin_unlock_irqrestore(&pcd_lock, saved_flags);
@@ -781,7 +781,7 @@ static void pcd_start(void)
if (pcd_command(pcd_current, rd_cmd, 2048, "read block")) {
pcd_bufblk = -1;
- next_request(0);
+ next_request(-EIO);
return;
}
@@ -796,7 +796,7 @@ static void do_pcd_read(void)
pcd_retries = 0;
pcd_transfer();
if (!pcd_count) {
- next_request(1);
+ next_request(0);
return;
}
@@ -815,7 +815,7 @@ static void do_pcd_read_drq(void)
return;
}
pcd_bufblk = -1;
- next_request(0);
+ next_request(-EIO);
return;
}
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 9299455b0af6..0732df4e901a 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -410,7 +410,8 @@ static void run_fsm(void)
pd_claimed = 0;
phase = NULL;
spin_lock_irqsave(&pd_lock, saved_flags);
- end_request(pd_req, res);
+ __blk_end_request_cur(pd_req,
+ res == Ok ? 0 : -EIO);
pd_req = elv_next_request(pd_queue);
if (!pd_req)
stop = 1;
@@ -477,7 +478,7 @@ static int pd_next_buf(void)
if (pd_count)
return 0;
spin_lock_irqsave(&pd_lock, saved_flags);
- end_request(pd_req, 1);
+ __blk_end_request_cur(pd_req, 0);
pd_count = pd_req->current_nr_sectors;
pd_buf = pd_req->buffer;
spin_unlock_irqrestore(&pd_lock, saved_flags);
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index bef3b997ba3e..3871e3586d6d 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -750,10 +750,10 @@ static int pf_ready(void)
static struct request_queue *pf_queue;
-static void pf_end_request(int uptodate)
+static void pf_end_request(int err)
{
if (pf_req) {
- end_request(pf_req, uptodate);
+ __blk_end_request_cur(pf_req, err);
pf_req = NULL;
}
}
@@ -773,7 +773,7 @@ repeat:
pf_count = pf_req->current_nr_sectors;
if (pf_block + pf_count > get_capacity(pf_req->rq_disk)) {
- pf_end_request(0);
+ pf_end_request(-EIO);
goto repeat;
}
@@ -788,7 +788,7 @@ repeat:
pi_do_claimed(pf_current->pi, do_pf_write);
else {
pf_busy = 0;
- pf_end_request(0);
+ pf_end_request(-EIO);
goto repeat;
}
}
@@ -805,7 +805,7 @@ static int pf_next_buf(void)
return 1;
if (!pf_count) {
spin_lock_irqsave(&pf_spin_lock, saved_flags);
- pf_end_request(1);
+ pf_end_request(0);
pf_req = elv_next_request(pf_queue);
spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
if (!pf_req)
@@ -816,12 +816,12 @@ static int pf_next_buf(void)
return 0;
}
-static inline void next_request(int success)
+static inline void next_request(int err)
{
unsigned long saved_flags;
spin_lock_irqsave(&pf_spin_lock, saved_flags);
- pf_end_request(success);
+ pf_end_request(err);
pf_busy = 0;
do_pf_request(pf_queue);
spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
@@ -844,7 +844,7 @@ static void do_pf_read_start(void)
pi_do_claimed(pf_current->pi, do_pf_read_start);
return;
}
- next_request(0);
+ next_request(-EIO);
return;
}
pf_mask = STAT_DRQ;
@@ -863,7 +863,7 @@ static void do_pf_read_drq(void)
pi_do_claimed(pf_current->pi, do_pf_read_start);
return;
}
- next_request(0);
+ next_request(-EIO);
return;
}
pi_read_block(pf_current->pi, pf_buf, 512);
@@ -871,7 +871,7 @@ static void do_pf_read_drq(void)
break;
}
pi_disconnect(pf_current->pi);
- next_request(1);
+ next_request(0);
}
static void do_pf_write(void)
@@ -890,7 +890,7 @@ static void do_pf_write_start(void)
pi_do_claimed(pf_current->pi, do_pf_write_start);
return;
}
- next_request(0);
+ next_request(-EIO);
return;
}
@@ -903,7 +903,7 @@ static void do_pf_write_start(void)
pi_do_claimed(pf_current->pi, do_pf_write_start);
return;
}
- next_request(0);
+ next_request(-EIO);
return;
}
pi_write_block(pf_current->pi, pf_buf, 512);
@@ -923,11 +923,11 @@ static void do_pf_write_done(void)
pi_do_claimed(pf_current->pi, do_pf_write_start);
return;
}
- next_request(0);
+ next_request(-EIO);
return;
}
pi_disconnect(pf_current->pi);
- next_request(1);
+ next_request(0);
}
static int __init pf_init(void)
diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
index bccc42bb9212..f6586e4d351c 100644
--- a/drivers/block/ps3disk.c
+++ b/drivers/block/ps3disk.c
@@ -158,7 +158,7 @@ static int ps3disk_submit_request_sg(struct ps3_storage_device *dev,
if (res) {
dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
__LINE__, op, res);
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
return 0;
}
@@ -180,7 +180,7 @@ static int ps3disk_submit_flush_request(struct ps3_storage_device *dev,
if (res) {
dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n",
__func__, __LINE__, res);
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
return 0;
}
@@ -205,7 +205,7 @@ static void ps3disk_do_request(struct ps3_storage_device *dev,
break;
} else {
blk_dump_rq_flags(req, DEVICE_NAME " bad request");
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
continue;
}
}
@@ -231,7 +231,6 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data)
struct request *req;
int res, read, error;
u64 tag, status;
- unsigned long num_sectors;
const char *op;
res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status);
@@ -261,11 +260,9 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data)
if (req->cmd_type == REQ_TYPE_LINUX_BLOCK &&
req->cmd[0] == REQ_LB_OP_FLUSH) {
read = 0;
- num_sectors = req->hard_cur_sectors;
op = "flush";
} else {
read = !rq_data_dir(req);
- num_sectors = req->nr_sectors;
op = read ? "read" : "write";
}
if (status) {
@@ -281,7 +278,7 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data)
}
spin_lock(&priv->lock);
- __blk_end_request(req, error, num_sectors << 9);
+ __blk_end_request_all(req, error);
priv->req = NULL;
ps3disk_do_request(dev, priv->queue);
spin_unlock(&priv->lock);
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
index 5861e33efe63..f59887c5ffbd 100644
--- a/drivers/block/sunvdc.c
+++ b/drivers/block/sunvdc.c
@@ -212,11 +212,6 @@ static void vdc_end_special(struct vdc_port *port, struct vio_disk_desc *desc)
vdc_finish(&port->vio, -err, WAITING_FOR_GEN_CMD);
}
-static void vdc_end_request(struct request *req, int error, int num_sectors)
-{
- __blk_end_request(req, error, num_sectors << 9);
-}
-
static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr,
unsigned int index)
{
@@ -239,7 +234,7 @@ static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr,
rqe->req = NULL;
- vdc_end_request(req, (desc->status ? -EIO : 0), desc->size >> 9);
+ __blk_end_request(req, (desc->status ? -EIO : 0), desc->size);
if (blk_queue_stopped(port->disk->queue))
blk_start_queue(port->disk->queue);
@@ -453,7 +448,7 @@ static void do_vdc_request(struct request_queue *q)
blkdev_dequeue_request(req);
if (__send_request(req) < 0)
- vdc_end_request(req, -EIO, req->hard_nr_sectors);
+ __blk_end_request_all(req, -EIO);
}
}
diff --git a/drivers/block/swim.c b/drivers/block/swim.c
index d22cc3856937..97ef4266c4c7 100644
--- a/drivers/block/swim.c
+++ b/drivers/block/swim.c
@@ -532,39 +532,32 @@ static void redo_fd_request(struct request_queue *q)
fs = req->rq_disk->private_data;
if (req->sector < 0 || req->sector >= fs->total_secs) {
- end_request(req, 0);
- continue;
- }
- if (req->current_nr_sectors == 0) {
- end_request(req, 1);
+ __blk_end_request_cur(req, -EIO);
continue;
}
if (!fs->disk_in) {
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
continue;
}
if (rq_data_dir(req) == WRITE) {
if (fs->write_protected) {
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
continue;
}
}
switch (rq_data_dir(req)) {
case WRITE:
/* NOT IMPLEMENTED */
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
break;
case READ:
if (floppy_read_sectors(fs, req->sector,
req->current_nr_sectors,
req->buffer)) {
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
continue;
}
- req->nr_sectors -= req->current_nr_sectors;
- req->sector += req->current_nr_sectors;
- req->buffer += req->current_nr_sectors * 512;
- end_request(req, 1);
+ __blk_end_request_cur(req, 0);
break;
}
}
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index 612965307ba0..424855945b9b 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -319,16 +319,12 @@ static void start_request(struct floppy_state *fs)
req->errors, req->current_nr_sectors);
#endif
- if (req->sector < 0 || req->sector >= fs->total_secs) {
- end_request(req, 0);
- continue;
- }
- if (req->current_nr_sectors == 0) {
- end_request(req, 1);
+ if (req->sector >= fs->total_secs) {
+ __blk_end_request_cur(req, -EIO);
continue;
}
if (fs->ejected) {
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
continue;
}
@@ -336,7 +332,7 @@ static void start_request(struct floppy_state *fs)
if (fs->write_prot < 0)
fs->write_prot = swim3_readbit(fs, WRITE_PROT);
if (fs->write_prot) {
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
continue;
}
}
@@ -508,7 +504,7 @@ static void act(struct floppy_state *fs)
case do_transfer:
if (fs->cur_cyl != fs->req_cyl) {
if (fs->retries > 5) {
- end_request(fd_req, 0);
+ __blk_end_request_cur(fd_req, -EIO);
fs->state = idle;
return;
}
@@ -540,7 +536,7 @@ static void scan_timeout(unsigned long data)
out_8(&sw->intr_enable, 0);
fs->cur_cyl = -1;
if (fs->retries > 5) {
- end_request(fd_req, 0);
+ __blk_end_request_cur(fd_req, -EIO);
fs->state = idle;
start_request(fs);
} else {
@@ -559,7 +555,7 @@ static void seek_timeout(unsigned long data)
out_8(&sw->select, RELAX);
out_8(&sw->intr_enable, 0);
printk(KERN_ERR "swim3: seek timeout\n");
- end_request(fd_req, 0);
+ __blk_end_request_cur(fd_req, -EIO);
fs->state = idle;
start_request(fs);
}
@@ -583,7 +579,7 @@ static void settle_timeout(unsigned long data)
return;
}
printk(KERN_ERR "swim3: seek settle timeout\n");
- end_request(fd_req, 0);
+ __blk_end_request_cur(fd_req, -EIO);
fs->state = idle;
start_request(fs);
}
@@ -593,8 +589,6 @@ static void xfer_timeout(unsigned long data)
struct floppy_state *fs = (struct floppy_state *) data;
struct swim3 __iomem *sw = fs->swim3;
struct dbdma_regs __iomem *dr = fs->dma;
- struct dbdma_cmd *cp = fs->dma_cmd;
- unsigned long s;
int n;
fs->timeout_pending = 0;
@@ -605,17 +599,9 @@ static void xfer_timeout(unsigned long data)
out_8(&sw->intr_enable, 0);
out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION);
out_8(&sw->select, RELAX);
- if (rq_data_dir(fd_req) == WRITE)
- ++cp;
- if (ld_le16(&cp->xfer_status) != 0)
- s = fs->scount - ((ld_le16(&cp->res_count) + 511) >> 9);
- else
- s = 0;
- fd_req->sector += s;
- fd_req->current_nr_sectors -= s;
printk(KERN_ERR "swim3: timeout %sing sector %ld\n",
(rq_data_dir(fd_req)==WRITE? "writ": "read"), (long)fd_req->sector);
- end_request(fd_req, 0);
+ __blk_end_request_cur(fd_req, -EIO);
fs->state = idle;
start_request(fs);
}
@@ -646,7 +632,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id)
printk(KERN_ERR "swim3: seen sector but cyl=ff?\n");
fs->cur_cyl = -1;
if (fs->retries > 5) {
- end_request(fd_req, 0);
+ __blk_end_request_cur(fd_req, -EIO);
fs->state = idle;
start_request(fs);
} else {
@@ -719,9 +705,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id)
if (intr & ERROR_INTR) {
n = fs->scount - 1 - resid / 512;
if (n > 0) {
- fd_req->sector += n;
- fd_req->current_nr_sectors -= n;
- fd_req->buffer += n * 512;
+ blk_update_request(fd_req, 0, n << 9);
fs->req_sector += n;
}
if (fs->retries < 5) {
@@ -731,7 +715,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id)
printk("swim3: error %sing block %ld (err=%x)\n",
rq_data_dir(fd_req) == WRITE? "writ": "read",
(long)fd_req->sector, err);
- end_request(fd_req, 0);
+ __blk_end_request_cur(fd_req, -EIO);
fs->state = idle;
}
} else {
@@ -740,18 +724,12 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id)
printk(KERN_ERR "swim3: fd dma: stat=%x resid=%d\n", stat, resid);
printk(KERN_ERR " state=%d, dir=%x, intr=%x, err=%x\n",
fs->state, rq_data_dir(fd_req), intr, err);
- end_request(fd_req, 0);
+ __blk_end_request_cur(fd_req, -EIO);
fs->state = idle;
start_request(fs);
break;
}
- fd_req->sector += fs->scount;
- fd_req->current_nr_sectors -= fs->scount;
- fd_req->buffer += fs->scount * 512;
- if (fd_req->current_nr_sectors <= 0) {
- end_request(fd_req, 1);
- fs->state = idle;
- } else {
+ if (__blk_end_request(fd_req, 0, fs->scount << 9)) {
fs->req_sector += fs->scount;
if (fs->req_sector > fs->secpertrack) {
fs->req_sector -= fs->secpertrack;
@@ -761,7 +739,8 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id)
}
}
act(fs);
- }
+ } else
+ fs->state = idle;
}
if (fs->state == idle)
start_request(fs);
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index ff0448e4bf03..60e85bb6f790 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -749,8 +749,7 @@ static inline void carm_end_request_queued(struct carm_host *host,
struct request *req = crq->rq;
int rc;
- rc = __blk_end_request(req, error, blk_rq_bytes(req));
- assert(rc == 0);
+ __blk_end_request_all(req, error);
rc = carm_put_request(host, crq);
assert(rc == 0);
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index 69b7f8e77596..689cd27ac890 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -1025,6 +1025,7 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
{
struct urb *urb = &sc->work_urb;
struct bulk_cs_wrap *bcs;
+ int endp;
int len;
int rc;
@@ -1033,6 +1034,10 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
return;
}
+ endp = usb_pipeendpoint(sc->last_pipe);
+ if (usb_pipein(sc->last_pipe))
+ endp |= USB_DIR_IN;
+
if (cmd->state == UB_CMDST_CLEAR) {
if (urb->status == -EPIPE) {
/*
@@ -1048,9 +1053,7 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
* We ignore the result for the halt clear.
*/
- /* reset the endpoint toggle */
- usb_settoggle(sc->dev, usb_pipeendpoint(sc->last_pipe),
- usb_pipeout(sc->last_pipe), 0);
+ usb_reset_endpoint(sc->dev, endp);
ub_state_sense(sc, cmd);
@@ -1065,9 +1068,7 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
* We ignore the result for the halt clear.
*/
- /* reset the endpoint toggle */
- usb_settoggle(sc->dev, usb_pipeendpoint(sc->last_pipe),
- usb_pipeout(sc->last_pipe), 0);
+ usb_reset_endpoint(sc->dev, endp);
ub_state_stat(sc, cmd);
@@ -1082,9 +1083,7 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
* We ignore the result for the halt clear.
*/
- /* reset the endpoint toggle */
- usb_settoggle(sc->dev, usb_pipeendpoint(sc->last_pipe),
- usb_pipeout(sc->last_pipe), 0);
+ usb_reset_endpoint(sc->dev, endp);
ub_state_stat_counted(sc, cmd);
@@ -2119,8 +2118,7 @@ static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe)
del_timer_sync(&timer);
usb_kill_urb(&sc->work_urb);
- /* reset the endpoint toggle */
- usb_settoggle(sc->dev, endp, usb_pipeout(sc->last_pipe), 0);
+ usb_reset_endpoint(sc->dev, endp);
return 0;
}
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 9744d59a69f2..858c34dd032d 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -906,6 +906,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev,
goto failed_alloc;
blk_queue_make_request(card->queue, mm_make_request);
+ card->queue->queue_lock = &card->lock;
card->queue->queuedata = card;
card->queue->unplug_fn = mm_unplug_device;
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 5d34764c8a87..50745e64414e 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -62,7 +62,7 @@ static void blk_done(struct virtqueue *vq)
break;
}
- __blk_end_request(vbr->req, error, blk_rq_bytes(vbr->req));
+ __blk_end_request_all(vbr->req, error);
list_del(&vbr->list);
mempool_free(vbr, vblk->pool);
}
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index 64b496fce98b..14be4c1ed1aa 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -308,27 +308,23 @@ static void do_xd_request (struct request_queue * q)
while ((req = elv_next_request(q)) != NULL) {
unsigned block = req->sector;
unsigned count = req->nr_sectors;
- int rw = rq_data_dir(req);
XD_INFO *disk = req->rq_disk->private_data;
int res = 0;
int retry;
if (!blk_fs_request(req)) {
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
continue;
}
if (block + count > get_capacity(req->rq_disk)) {
- end_request(req, 0);
- continue;
- }
- if (rw != READ && rw != WRITE) {
- printk("do_xd_request: unknown request\n");
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
continue;
}
for (retry = 0; (retry < XD_RETRIES) && !res; retry++)
- res = xd_readwrite(rw, disk, req->buffer, block, count);
- end_request(req, res); /* wrap up, 0 = fail, 1 = success */
+ res = xd_readwrite(rq_data_dir(req), disk, req->buffer,
+ block, count);
+ /* wrap up, 0 = success, -errno = fail */
+ __blk_end_request_cur(req, res);
}
}
@@ -418,7 +414,7 @@ static int xd_readwrite (u_char operation,XD_INFO *p,char *buffer,u_int block,u_
printk("xd%c: %s timeout, recalibrating drive\n",'a'+drive,(operation == READ ? "read" : "write"));
xd_recalibrate(drive);
spin_lock_irq(&xd_lock);
- return (0);
+ return -EIO;
case 2:
if (sense[0] & 0x30) {
printk("xd%c: %s - ",'a'+drive,(operation == READ ? "reading" : "writing"));
@@ -439,7 +435,7 @@ static int xd_readwrite (u_char operation,XD_INFO *p,char *buffer,u_int block,u_
else
printk(" - no valid disk address\n");
spin_lock_irq(&xd_lock);
- return (0);
+ return -EIO;
}
if (xd_dma_buffer)
for (i=0; i < (temp * 0x200); i++)
@@ -448,7 +444,7 @@ static int xd_readwrite (u_char operation,XD_INFO *p,char *buffer,u_int block,u_
count -= temp, buffer += temp * 0x200, block += temp;
}
spin_lock_irq(&xd_lock);
- return (1);
+ return 0;
}
/* xd_recalibrate: recalibrate a given drive and reset controller if necessary */
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 8f905089b72b..b4564479f641 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -302,7 +302,7 @@ static void do_blkif_request(struct request_queue *rq)
while ((req = elv_next_request(rq)) != NULL) {
info = req->rq_disk->private_data;
if (!blk_fs_request(req)) {
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
continue;
}
@@ -551,7 +551,6 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
for (i = info->ring.rsp_cons; i != rp; i++) {
unsigned long id;
- int ret;
bret = RING_GET_RESPONSE(&info->ring, i);
id = bret->id;
@@ -578,8 +577,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
dev_dbg(&info->xbdev->dev, "Bad return from blkdev data "
"request: %x\n", bret->status);
- ret = __blk_end_request(req, error, blk_rq_bytes(req));
- BUG_ON(ret);
+ __blk_end_request_all(req, error);
break;
default:
BUG();
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
index 4aecf5dc6a93..b1e1d7e5ab1e 100644
--- a/drivers/block/xsysace.c
+++ b/drivers/block/xsysace.c
@@ -466,7 +466,7 @@ struct request *ace_get_next_request(struct request_queue * q)
while ((req = elv_next_request(q)) != NULL) {
if (blk_fs_request(req))
break;
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
}
return req;
}
@@ -494,7 +494,7 @@ static void ace_fsm_dostate(struct ace_device *ace)
/* Drop all pending requests */
while ((req = elv_next_request(ace->queue)) != NULL)
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
/* Drop back to IDLE state and notify waiters */
ace->fsm_state = ACE_FSM_STATE_IDLE;
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index 80754cdd3119..b66ad58a3c38 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -77,7 +77,7 @@ static void do_z2_request(struct request_queue *q)
if (start + len > z2ram_size) {
printk( KERN_ERR DEVICE_NAME ": bad access: block=%lu, count=%u\n",
req->sector, req->current_nr_sectors);
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
continue;
}
while (len) {
@@ -93,7 +93,7 @@ static void do_z2_request(struct request_queue *q)
start += size;
len -= size;
}
- end_request(req, 1);
+ __blk_end_request_cur(req, 0);
}
}
diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
index 2eecb779437b..cab2b1fb2fe7 100644
--- a/drivers/cdrom/gdrom.c
+++ b/drivers/cdrom/gdrom.c
@@ -632,7 +632,7 @@ static void gdrom_readdisk_dma(struct work_struct *work)
* before handling ending the request */
spin_lock(&gdrom_lock);
list_del_init(&req->queuelist);
- __blk_end_request(req, err, blk_rq_bytes(req));
+ __blk_end_request_all(req, err);
}
spin_unlock(&gdrom_lock);
kfree(read_command);
@@ -654,17 +654,17 @@ static void gdrom_request(struct request_queue *rq)
while ((req = elv_next_request(rq)) != NULL) {
if (!blk_fs_request(req)) {
printk(KERN_DEBUG "GDROM: Non-fs request ignored\n");
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
}
if (rq_data_dir(req) != READ) {
printk(KERN_NOTICE "GDROM: Read only device -");
printk(" write request ignored\n");
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
}
if (req->nr_sectors)
gdrom_request_handler_dma(req);
else
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
}
}
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index 13929356135c..cc3efa096e1a 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -291,23 +291,6 @@ static int send_request(struct request *req)
return 0;
}
-static void viocd_end_request(struct request *req, int error)
-{
- int nsectors = req->hard_nr_sectors;
-
- /*
- * Make sure it's fully ended, and ensure that we process
- * at least one sector.
- */
- if (blk_pc_request(req))
- nsectors = (req->data_len + 511) >> 9;
- if (!nsectors)
- nsectors = 1;
-
- if (__blk_end_request(req, error, nsectors << 9))
- BUG();
-}
-
static int rwreq;
static void do_viocd_request(struct request_queue *q)
@@ -316,11 +299,11 @@ static void do_viocd_request(struct request_queue *q)
while ((rwreq == 0) && ((req = elv_next_request(q)) != NULL)) {
if (!blk_fs_request(req))
- viocd_end_request(req, -EIO);
+ __blk_end_request_all(req, -EIO);
else if (send_request(req) < 0) {
printk(VIOCD_KERN_WARNING
"unable to send message to OS/400!");
- viocd_end_request(req, -EIO);
+ __blk_end_request_all(req, -EIO);
} else
rwreq++;
}
@@ -531,9 +514,9 @@ return_complete:
"with rc %d:0x%04X: %s\n",
req, event->xRc,
bevent->sub_result, err->msg);
- viocd_end_request(req, -EIO);
+ __blk_end_request_all(req, -EIO);
} else
- viocd_end_request(req, 0);
+ __blk_end_request_all(req, 0);
/* restart handling of incoming requests */
spin_unlock_irqrestore(&viocd_reqlock, flags);
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index 10d6cbd7c05e..2224b762b7fb 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -1226,7 +1226,7 @@ int agp_generic_alloc_pages(struct agp_bridge_data *bridge, struct agp_memory *m
int i, ret = -ENOMEM;
for (i = 0; i < num_pages; i++) {
- page = alloc_page(GFP_KERNEL | GFP_DMA32);
+ page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO);
/* agp_free_memory() needs gart address */
if (page == NULL)
goto out;
@@ -1257,7 +1257,7 @@ void *agp_generic_alloc_page(struct agp_bridge_data *bridge)
{
struct page * page;
- page = alloc_page(GFP_KERNEL | GFP_DMA32);
+ page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO);
if (page == NULL)
return NULL;
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 9d9490e22e07..3686912427ba 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -2131,6 +2131,8 @@ static const struct intel_driver_description {
{ PCI_DEVICE_ID_INTEL_82845G_HB, PCI_DEVICE_ID_INTEL_82845G_IG, 0, "830M",
&intel_845_driver, &intel_830_driver },
{ PCI_DEVICE_ID_INTEL_82850_HB, 0, 0, "i850", &intel_850_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82854_HB, PCI_DEVICE_ID_INTEL_82854_IG, 0, "854",
+ &intel_845_driver, &intel_830_driver },
{ PCI_DEVICE_ID_INTEL_82855PM_HB, 0, 0, "855PM", &intel_845_driver, NULL },
{ PCI_DEVICE_ID_INTEL_82855GM_HB, PCI_DEVICE_ID_INTEL_82855GM_IG, 0, "855GM",
&intel_845_driver, &intel_830_driver },
@@ -2355,6 +2357,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
ID(PCI_DEVICE_ID_INTEL_82845_HB),
ID(PCI_DEVICE_ID_INTEL_82845G_HB),
ID(PCI_DEVICE_ID_INTEL_82850_HB),
+ ID(PCI_DEVICE_ID_INTEL_82854_HB),
ID(PCI_DEVICE_ID_INTEL_82855PM_HB),
ID(PCI_DEVICE_ID_INTEL_82855GM_HB),
ID(PCI_DEVICE_ID_INTEL_82860_HB),
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index fd3ebd1be570..72429b6b2fa8 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -779,7 +779,7 @@ static void change_speed(struct async_struct *info,
info->IER |= UART_IER_MSI;
}
/* TBD:
- * Does clearing IER_MSI imply that we should disbale the VBL interrupt ?
+ * Does clearing IER_MSI imply that we should disable the VBL interrupt ?
*/
/*
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 1fdb9f657d8f..456019051742 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -604,7 +604,6 @@
#define NR_PORTS 256
-#define ZE_V1_NPORTS 64
#define ZO_V1 0
#define ZO_V2 1
#define ZE_V1 2
@@ -663,18 +662,6 @@
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 == (unsigned int)-1)
-
-#define Z_FPGA_CHECK(card) \
- ((readl(&((struct RUNTIME_9060 __iomem *) \
- ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0)
-
-#define ISZLOADED(card) (((ZO_V1 == readl(&((struct RUNTIME_9060 __iomem *) \
- ((card).ctl_addr))->mail_box_0)) || \
- Z_FPGA_CHECK(card)) && \
- (ZFIRM_ID == readl(&((struct FIRM_ID __iomem *) \
- ((card).base_addr+ID_ADDRESS))->signature)))
-
#ifndef SERIAL_XMIT_SIZE
#define SERIAL_XMIT_SIZE (min(PAGE_SIZE, 4096))
#endif
@@ -687,8 +674,6 @@ static void cy_send_xchar(struct tty_struct *tty, char ch);
#define DRIVER_VERSION 0x02010203
#define RAM_SIZE 0x80000
-#define Z_FPGA_LOADED(X) ((readl(&(X)->init_ctrl) & (1<<17)) != 0)
-
enum zblock_type {
ZBLOCK_PRG = 0,
ZBLOCK_FPGA = 1
@@ -883,6 +868,29 @@ static void cyz_rx_restart(unsigned long);
static struct timer_list cyz_rx_full_timer[NR_PORTS];
#endif /* CONFIG_CYZ_INTR */
+static inline bool cy_is_Z(struct cyclades_card *card)
+{
+ return card->num_chips == (unsigned int)-1;
+}
+
+static inline bool __cyz_fpga_loaded(struct RUNTIME_9060 __iomem *ctl_addr)
+{
+ return readl(&ctl_addr->init_ctrl) & (1 << 17);
+}
+
+static inline bool cyz_fpga_loaded(struct cyclades_card *card)
+{
+ return __cyz_fpga_loaded(card->ctl_addr.p9060);
+}
+
+static inline bool cyz_is_loaded(struct cyclades_card *card)
+{
+ struct FIRM_ID __iomem *fw_id = card->base_addr + ID_ADDRESS;
+
+ return (card->hw_ver == ZO_V1 || cyz_fpga_loaded(card)) &&
+ readl(&fw_id->signature) == ZFIRM_ID;
+}
+
static inline int serial_paranoia_check(struct cyclades_port *info,
char *name, const char *routine)
{
@@ -1395,19 +1403,15 @@ cyz_fetch_msg(struct cyclades_card *cinfo,
unsigned long loc_doorbell;
firm_id = cinfo->base_addr + ID_ADDRESS;
- if (!ISZLOADED(*cinfo))
- return -1;
zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
board_ctrl = &zfw_ctrl->board_ctrl;
- loc_doorbell = readl(&((struct RUNTIME_9060 __iomem *)
- (cinfo->ctl_addr))->loc_doorbell);
+ loc_doorbell = readl(&cinfo->ctl_addr.p9060->loc_doorbell);
if (loc_doorbell) {
*cmd = (char)(0xff & loc_doorbell);
*channel = readl(&board_ctrl->fwcmd_channel);
*param = (__u32) readl(&board_ctrl->fwcmd_param);
- cy_writel(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->
- loc_doorbell, 0xffffffff);
+ cy_writel(&cinfo->ctl_addr.p9060->loc_doorbell, 0xffffffff);
return 1;
}
return 0;
@@ -1424,15 +1428,14 @@ cyz_issue_cmd(struct cyclades_card *cinfo,
unsigned int index;
firm_id = cinfo->base_addr + ID_ADDRESS;
- if (!ISZLOADED(*cinfo))
+ if (!cyz_is_loaded(cinfo))
return -1;
zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
board_ctrl = &zfw_ctrl->board_ctrl;
index = 0;
- pci_doorbell =
- &((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->pci_doorbell;
+ pci_doorbell = &cinfo->ctl_addr.p9060->pci_doorbell;
while ((readl(pci_doorbell) & 0xff) != 0) {
if (index++ == 1000)
return (int)(readl(pci_doorbell) & 0xff);
@@ -1624,10 +1627,8 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
static struct BOARD_CTRL __iomem *board_ctrl;
static struct CH_CTRL __iomem *ch_ctrl;
static struct BUF_CTRL __iomem *buf_ctrl;
- __u32 channel;
+ __u32 channel, param, fw_ver;
__u8 cmd;
- __u32 param;
- __u32 hw_ver, fw_ver;
int special_count;
int delta_count;
@@ -1635,8 +1636,6 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
board_ctrl = &zfw_ctrl->board_ctrl;
fw_ver = readl(&board_ctrl->fw_version);
- hw_ver = readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->
- mail_box_0);
while (cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
special_count = 0;
@@ -1737,15 +1736,7 @@ static irqreturn_t cyz_interrupt(int irq, void *dev_id)
{
struct cyclades_card *cinfo = dev_id;
- if (unlikely(cinfo == NULL)) {
-#ifdef CY_DEBUG_INTERRUPTS
- printk(KERN_DEBUG "cyz_interrupt: spurious interrupt %d\n",
- irq);
-#endif
- return IRQ_NONE; /* spurious interrupt */
- }
-
- if (unlikely(!ISZLOADED(*cinfo))) {
+ if (unlikely(!cyz_is_loaded(cinfo))) {
#ifdef CY_DEBUG_INTERRUPTS
printk(KERN_DEBUG "cyz_interrupt: board not yet loaded "
"(IRQ%d).\n", irq);
@@ -1785,7 +1776,6 @@ static void cyz_poll(unsigned long arg)
struct tty_struct *tty;
struct FIRM_ID __iomem *firm_id;
struct ZFW_CTRL __iomem *zfw_ctrl;
- struct BOARD_CTRL __iomem *board_ctrl;
struct BUF_CTRL __iomem *buf_ctrl;
unsigned long expires = jiffies + HZ;
unsigned int port, card;
@@ -1793,19 +1783,17 @@ static void cyz_poll(unsigned long arg)
for (card = 0; card < NR_CARDS; card++) {
cinfo = &cy_card[card];
- if (!IS_CYC_Z(*cinfo))
+ if (!cy_is_Z(cinfo))
continue;
- if (!ISZLOADED(*cinfo))
+ if (!cyz_is_loaded(cinfo))
continue;
firm_id = cinfo->base_addr + ID_ADDRESS;
zfw_ctrl = cinfo->base_addr +
(readl(&firm_id->zfwctrl_addr) & 0xfffff);
- board_ctrl = &(zfw_ctrl->board_ctrl);
/* Skip first polling cycle to avoid racing conditions with the FW */
if (!cinfo->intr_enabled) {
- cinfo->nports = (int)readl(&board_ctrl->n_channel);
cinfo->intr_enabled = 1;
continue;
}
@@ -1874,7 +1862,7 @@ static int startup(struct cyclades_port *info)
set_line_char(info);
- if (!IS_CYC_Z(*card)) {
+ if (!cy_is_Z(card)) {
chip = channel >> 2;
channel &= 0x03;
index = card->bus_index;
@@ -1931,7 +1919,7 @@ static int startup(struct cyclades_port *info)
base_addr = card->base_addr;
firm_id = base_addr + ID_ADDRESS;
- if (!ISZLOADED(*card))
+ if (!cyz_is_loaded(card))
return -ENODEV;
zfw_ctrl = card->base_addr +
@@ -2026,7 +2014,7 @@ static void start_xmit(struct cyclades_port *info)
card = info->card;
channel = info->line - card->first_line;
- if (!IS_CYC_Z(*card)) {
+ if (!cy_is_Z(card)) {
chip = channel >> 2;
channel &= 0x03;
index = card->bus_index;
@@ -2070,7 +2058,7 @@ static void shutdown(struct cyclades_port *info)
card = info->card;
channel = info->line - card->first_line;
- if (!IS_CYC_Z(*card)) {
+ if (!cy_is_Z(card)) {
chip = channel >> 2;
channel &= 0x03;
index = card->bus_index;
@@ -2126,7 +2114,7 @@ static void shutdown(struct cyclades_port *info)
#endif
firm_id = base_addr + ID_ADDRESS;
- if (!ISZLOADED(*card))
+ if (!cyz_is_loaded(card))
return;
zfw_ctrl = card->base_addr +
@@ -2233,7 +2221,7 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
#endif
info->port.blocked_open++;
- if (!IS_CYC_Z(*cinfo)) {
+ if (!cy_is_Z(cinfo)) {
chip = channel >> 2;
channel &= 0x03;
index = cinfo->bus_index;
@@ -2296,7 +2284,7 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
base_addr = cinfo->base_addr;
firm_id = base_addr + ID_ADDRESS;
- if (!ISZLOADED(*cinfo)) {
+ if (!cyz_is_loaded(cinfo)) {
__set_current_state(TASK_RUNNING);
remove_wait_queue(&info->port.open_wait, &wait);
return -EINVAL;
@@ -2397,16 +2385,14 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
treat it as absent from the system. This
will make the user pay attention.
*/
- if (IS_CYC_Z(*info->card)) {
+ if (cy_is_Z(info->card)) {
struct cyclades_card *cinfo = info->card;
struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS;
- if (!ISZLOADED(*cinfo)) {
- if (((ZE_V1 == readl(&((struct RUNTIME_9060 __iomem *)
- (cinfo->ctl_addr))->mail_box_0)) &&
- Z_FPGA_CHECK(*cinfo)) &&
- (ZFIRM_HLT == readl(
- &firm_id->signature))) {
+ if (!cyz_is_loaded(cinfo)) {
+ if (cinfo->hw_ver == ZE_V1 && cyz_fpga_loaded(cinfo) &&
+ readl(&firm_id->signature) ==
+ ZFIRM_HLT) {
printk(KERN_ERR "cyc:Cyclades-Z Error: you "
"need an external power supply for "
"this number of ports.\nFirmware "
@@ -2423,18 +2409,13 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
interrupts should be enabled as soon as the first open
happens to one of its ports. */
if (!cinfo->intr_enabled) {
- struct ZFW_CTRL __iomem *zfw_ctrl;
- struct BOARD_CTRL __iomem *board_ctrl;
-
- zfw_ctrl = cinfo->base_addr +
- (readl(&firm_id->zfwctrl_addr) &
- 0xfffff);
-
- board_ctrl = &zfw_ctrl->board_ctrl;
+ u16 intr;
/* Enable interrupts on the PLX chip */
- cy_writew(cinfo->ctl_addr + 0x68,
- readw(cinfo->ctl_addr + 0x68) | 0x0900);
+ intr = readw(&cinfo->ctl_addr.p9060->
+ intr_ctrl_stat) | 0x0900;
+ cy_writew(&cinfo->ctl_addr.p9060->
+ intr_ctrl_stat, intr);
/* Enable interrupts on the FW */
retval = cyz_issue_cmd(cinfo, 0,
C_CM_IRQ_ENBL, 0L);
@@ -2442,8 +2423,6 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
printk(KERN_ERR "cyc:IRQ enable retval "
"was %x\n", retval);
}
- cinfo->nports =
- (int)readl(&board_ctrl->n_channel);
cinfo->intr_enabled = 1;
}
}
@@ -2556,7 +2535,7 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
#endif
card = info->card;
channel = (info->line) - (card->first_line);
- if (!IS_CYC_Z(*card)) {
+ if (!cy_is_Z(card)) {
chip = channel >> 2;
channel &= 0x03;
index = card->bus_index;
@@ -2601,7 +2580,7 @@ static void cy_flush_buffer(struct tty_struct *tty)
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
spin_unlock_irqrestore(&card->card_lock, flags);
- if (IS_CYC_Z(*card)) { /* If it is a Z card, flush the on-board
+ if (cy_is_Z(card)) { /* If it is a Z card, flush the on-board
buffers as well */
spin_lock_irqsave(&card->card_lock, flags);
retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L);
@@ -2682,7 +2661,7 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
spin_lock_irqsave(&card->card_lock, flags);
- if (!IS_CYC_Z(*card)) {
+ if (!cy_is_Z(card)) {
int channel = info->line - card->first_line;
int index = card->bus_index;
void __iomem *base_addr = card->base_addr +
@@ -2902,7 +2881,7 @@ static int cy_chars_in_buffer(struct tty_struct *tty)
channel = (info->line) - (card->first_line);
#ifdef Z_EXT_CHARS_IN_BUFFER
- if (!IS_CYC_Z(cy_card[card])) {
+ if (!cy_is_Z(card)) {
#endif /* Z_EXT_CHARS_IN_BUFFER */
#ifdef CY_DEBUG_IO
printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
@@ -2984,7 +2963,6 @@ static void set_line_char(struct cyclades_port *info)
void __iomem *base_addr;
int chip, channel, index;
unsigned cflag, iflag;
- unsigned short chip_number;
int baud, baud_rate = 0;
int i;
@@ -3013,9 +2991,8 @@ static void set_line_char(struct cyclades_port *info)
card = info->card;
channel = info->line - card->first_line;
- chip_number = channel / 4;
- if (!IS_CYC_Z(*card)) {
+ if (!cy_is_Z(card)) {
index = card->bus_index;
@@ -3233,21 +3210,17 @@ static void set_line_char(struct cyclades_port *info)
} else {
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;
__u32 sw_flow;
int retval;
firm_id = card->base_addr + ID_ADDRESS;
- if (!ISZLOADED(*card))
+ if (!cyz_is_loaded(card))
return;
zfw_ctrl = card->base_addr +
(readl(&firm_id->zfwctrl_addr) & 0xfffff);
- board_ctrl = &zfw_ctrl->board_ctrl;
ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
- buf_ctrl = &zfw_ctrl->buf_ctrl[channel];
/* baud rate */
baud = tty_get_baud_rate(info->port.tty);
@@ -3457,7 +3430,7 @@ static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value)
card = info->card;
channel = (info->line) - (card->first_line);
- if (!IS_CYC_Z(*card)) {
+ if (!cy_is_Z(card)) {
chip = channel >> 2;
channel &= 0x03;
index = card->bus_index;
@@ -3497,7 +3470,7 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file)
card = info->card;
channel = info->line - card->first_line;
- if (!IS_CYC_Z(*card)) {
+ if (!cy_is_Z(card)) {
chip = channel >> 2;
channel &= 0x03;
index = card->bus_index;
@@ -3523,7 +3496,7 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file)
} else {
base_addr = card->base_addr;
firm_id = card->base_addr + ID_ADDRESS;
- if (ISZLOADED(*card)) {
+ if (cyz_is_loaded(card)) {
zfw_ctrl = card->base_addr +
(readl(&firm_id->zfwctrl_addr) & 0xfffff);
board_ctrl = &zfw_ctrl->board_ctrl;
@@ -3566,7 +3539,7 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
card = info->card;
channel = (info->line) - (card->first_line);
- if (!IS_CYC_Z(*card)) {
+ if (!cy_is_Z(card)) {
chip = channel >> 2;
channel &= 0x03;
index = card->bus_index;
@@ -3641,7 +3614,7 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
base_addr = card->base_addr;
firm_id = card->base_addr + ID_ADDRESS;
- if (ISZLOADED(*card)) {
+ if (cyz_is_loaded(card)) {
zfw_ctrl = card->base_addr +
(readl(&firm_id->zfwctrl_addr) & 0xfffff);
board_ctrl = &zfw_ctrl->board_ctrl;
@@ -3713,7 +3686,7 @@ static int cy_break(struct tty_struct *tty, int break_state)
card = info->card;
spin_lock_irqsave(&card->card_lock, flags);
- if (!IS_CYC_Z(*card)) {
+ if (!cy_is_Z(card)) {
/* Let the transmit ISR take care of this (since it
requires stuffing characters into the output stream).
*/
@@ -3782,7 +3755,7 @@ static int set_threshold(struct cyclades_port *info, unsigned long value)
card = info->card;
channel = info->line - card->first_line;
- if (!IS_CYC_Z(*card)) {
+ if (!cy_is_Z(card)) {
chip = channel >> 2;
channel &= 0x03;
index = card->bus_index;
@@ -3810,7 +3783,7 @@ static int get_threshold(struct cyclades_port *info,
card = info->card;
channel = info->line - card->first_line;
- if (!IS_CYC_Z(*card)) {
+ if (!cy_is_Z(card)) {
chip = channel >> 2;
channel &= 0x03;
index = card->bus_index;
@@ -3844,7 +3817,7 @@ static int set_timeout(struct cyclades_port *info, unsigned long value)
card = info->card;
channel = info->line - card->first_line;
- if (!IS_CYC_Z(*card)) {
+ if (!cy_is_Z(card)) {
chip = channel >> 2;
channel &= 0x03;
index = card->bus_index;
@@ -3867,7 +3840,7 @@ static int get_timeout(struct cyclades_port *info,
card = info->card;
channel = info->line - card->first_line;
- if (!IS_CYC_Z(*card)) {
+ if (!cy_is_Z(card)) {
chip = channel >> 2;
channel &= 0x03;
index = card->bus_index;
@@ -4121,7 +4094,7 @@ static void cy_send_xchar(struct tty_struct *tty, char ch)
card = info->card;
channel = info->line - card->first_line;
- if (IS_CYC_Z(*card)) {
+ if (cy_is_Z(card)) {
if (ch == STOP_CHAR(tty))
cyz_issue_cmd(card, channel, C_CM_SENDXOFF, 0L);
else if (ch == START_CHAR(tty))
@@ -4154,7 +4127,7 @@ static void cy_throttle(struct tty_struct *tty)
card = info->card;
if (I_IXOFF(tty)) {
- if (!IS_CYC_Z(*card))
+ if (!cy_is_Z(card))
cy_send_xchar(tty, STOP_CHAR(tty));
else
info->throttle = 1;
@@ -4162,7 +4135,7 @@ static void cy_throttle(struct tty_struct *tty)
if (tty->termios->c_cflag & CRTSCTS) {
channel = info->line - card->first_line;
- if (!IS_CYC_Z(*card)) {
+ if (!cy_is_Z(card)) {
chip = channel >> 2;
channel &= 0x03;
index = card->bus_index;
@@ -4219,7 +4192,7 @@ static void cy_unthrottle(struct tty_struct *tty)
if (tty->termios->c_cflag & CRTSCTS) {
card = info->card;
channel = info->line - card->first_line;
- if (!IS_CYC_Z(*card)) {
+ if (!cy_is_Z(card)) {
chip = channel >> 2;
channel &= 0x03;
index = card->bus_index;
@@ -4263,7 +4236,7 @@ static void cy_stop(struct tty_struct *tty)
cinfo = info->card;
channel = info->line - cinfo->first_line;
- if (!IS_CYC_Z(*cinfo)) {
+ if (!cy_is_Z(cinfo)) {
index = cinfo->bus_index;
chip = channel >> 2;
channel &= 0x03;
@@ -4296,7 +4269,7 @@ static void cy_start(struct tty_struct *tty)
cinfo = info->card;
channel = info->line - cinfo->first_line;
index = cinfo->bus_index;
- if (!IS_CYC_Z(*cinfo)) {
+ if (!cy_is_Z(cinfo)) {
chip = channel >> 2;
channel &= 0x03;
base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index);
@@ -4347,33 +4320,20 @@ static void cy_hangup(struct tty_struct *tty)
static int __devinit cy_init_card(struct cyclades_card *cinfo)
{
struct cyclades_port *info;
- u32 uninitialized_var(mailbox);
- unsigned int nports, port;
+ unsigned int port;
unsigned short chip_number;
- int uninitialized_var(index);
spin_lock_init(&cinfo->card_lock);
+ cinfo->intr_enabled = 0;
- if (IS_CYC_Z(*cinfo)) { /* Cyclades-Z */
- mailbox = readl(&((struct RUNTIME_9060 __iomem *)
- cinfo->ctl_addr)->mail_box_0);
- nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8;
- cinfo->intr_enabled = 0;
- cinfo->nports = 0; /* Will be correctly set later, after
- Z FW is loaded */
- } else {
- index = cinfo->bus_index;
- nports = cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips;
- }
-
- cinfo->ports = kzalloc(sizeof(*cinfo->ports) * nports, GFP_KERNEL);
+ cinfo->ports = kcalloc(cinfo->nports, sizeof(*cinfo->ports),
+ GFP_KERNEL);
if (cinfo->ports == NULL) {
printk(KERN_ERR "Cyclades: cannot allocate ports\n");
- cinfo->nports = 0;
return -ENOMEM;
}
- for (port = cinfo->first_line; port < cinfo->first_line + nports;
+ for (port = cinfo->first_line; port < cinfo->first_line + cinfo->nports;
port++) {
info = &cinfo->ports[port - cinfo->first_line];
tty_port_init(&info->port);
@@ -4387,9 +4347,9 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
init_completion(&info->shutdown_wait);
init_waitqueue_head(&info->delta_msr_wait);
- if (IS_CYC_Z(*cinfo)) {
+ if (cy_is_Z(cinfo)) {
info->type = PORT_STARTECH;
- if (mailbox == ZO_V1)
+ if (cinfo->hw_ver == ZO_V1)
info->xmit_fifo_size = CYZ_FIFO_SIZE;
else
info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE;
@@ -4398,6 +4358,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
cyz_rx_restart, (unsigned long)info);
#endif
} else {
+ int index = cinfo->bus_index;
info->type = PORT_CIRRUS;
info->xmit_fifo_size = CyMAX_CHAR_FIFO;
info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS;
@@ -4430,7 +4391,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
}
#ifndef CONFIG_CYZ_INTR
- if (IS_CYC_Z(*cinfo) && !timer_pending(&cyz_timerlist)) {
+ if (cy_is_Z(cinfo) && !timer_pending(&cyz_timerlist)) {
mod_timer(&cyz_timerlist, jiffies + 1);
#ifdef CY_PCI_DEBUG
printk(KERN_DEBUG "Cyclades-Z polling initialized\n");
@@ -4621,11 +4582,12 @@ static int __init cy_detect_isa(void)
/* set cy_card */
cy_card[j].base_addr = cy_isa_address;
- cy_card[j].ctl_addr = NULL;
+ cy_card[j].ctl_addr.p9050 = NULL;
cy_card[j].irq = (int)cy_isa_irq;
cy_card[j].bus_index = 0;
cy_card[j].first_line = cy_next_channel;
- cy_card[j].num_chips = cy_isa_nchan / 4;
+ cy_card[j].num_chips = cy_isa_nchan / CyPORTS_PER_CHIP;
+ cy_card[j].nports = cy_isa_nchan;
if (cy_init_card(&cy_card[j])) {
cy_card[j].base_addr = NULL;
free_irq(cy_isa_irq, &cy_card[j]);
@@ -4781,7 +4743,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
struct CUSTOM_REG __iomem *cust = base_addr;
struct ZFW_CTRL __iomem *pt_zfwctrl;
void __iomem *tmp;
- u32 mailbox, status;
+ u32 mailbox, status, nchan;
unsigned int i;
int retval;
@@ -4793,7 +4755,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
/* Check whether the firmware is already loaded and running. If
positive, skip this board */
- if (Z_FPGA_LOADED(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) {
+ if (__cyz_fpga_loaded(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) {
u32 cntval = readl(base_addr + 0x190);
udelay(100);
@@ -4812,7 +4774,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
mailbox = readl(&ctl_addr->mail_box_0);
- if (mailbox == 0 || Z_FPGA_LOADED(ctl_addr)) {
+ if (mailbox == 0 || __cyz_fpga_loaded(ctl_addr)) {
/* stops CPU and set window to beginning of RAM */
cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
cy_writel(&cust->cpu_stop, 0);
@@ -4828,7 +4790,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
base_addr);
if (retval)
goto err_rel;
- if (!Z_FPGA_LOADED(ctl_addr)) {
+ if (!__cyz_fpga_loaded(ctl_addr)) {
dev_err(&pdev->dev, "fw upload successful, but fw is "
"not loaded\n");
goto err_rel;
@@ -4887,7 +4849,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
"system before loading the new FW to the "
"Cyclades-Z.\n");
- if (Z_FPGA_LOADED(ctl_addr))
+ if (__cyz_fpga_loaded(ctl_addr))
plx_init(pdev, irq, ctl_addr);
retval = -EIO;
@@ -4902,16 +4864,16 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr),
base_addr + readl(&fid->zfwctrl_addr));
+ nchan = readl(&pt_zfwctrl->board_ctrl.n_channel);
dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u\n",
- readl(&pt_zfwctrl->board_ctrl.fw_version),
- readl(&pt_zfwctrl->board_ctrl.n_channel));
+ readl(&pt_zfwctrl->board_ctrl.fw_version), nchan);
- if (readl(&pt_zfwctrl->board_ctrl.n_channel) == 0) {
+ if (nchan == 0) {
dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please "
"check the connection between the Z host card and the "
"serial expanders.\n");
- if (Z_FPGA_LOADED(ctl_addr))
+ if (__cyz_fpga_loaded(ctl_addr))
plx_init(pdev, irq, ctl_addr);
dev_info(&pdev->dev, "Null number of ports detected. Board "
@@ -4932,9 +4894,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
0x00030800UL);
- plx_init(pdev, irq, ctl_addr);
-
- return 0;
+ return nchan;
err_rel:
release_firmware(fw);
err:
@@ -4946,7 +4906,7 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
{
void __iomem *addr0 = NULL, *addr2 = NULL;
char *card_name = NULL;
- u32 mailbox;
+ u32 uninitialized_var(mailbox);
unsigned int device_id, nchan = 0, card_no, i;
unsigned char plx_ver;
int retval, irq;
@@ -5023,11 +4983,12 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
}
/* Disable interrupts on the PLX before resetting it */
- cy_writew(addr0 + 0x68, readw(addr0 + 0x68) & ~0x0900);
+ cy_writew(&ctl_addr->intr_ctrl_stat,
+ readw(&ctl_addr->intr_ctrl_stat) & ~0x0900);
plx_init(pdev, irq, addr0);
- mailbox = (u32)readl(&ctl_addr->mail_box_0);
+ mailbox = readl(&ctl_addr->mail_box_0);
addr2 = ioremap_nocache(pci_resource_start(pdev, 2),
mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin);
@@ -5038,12 +4999,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
if (mailbox == ZE_V1) {
card_name = "Cyclades-Ze";
-
- readl(&ctl_addr->mail_box_0);
- nchan = ZE_V1_NPORTS;
} else {
card_name = "Cyclades-8Zo";
-
#ifdef CY_PCI_DEBUG
if (mailbox == ZO_V1) {
cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
@@ -5065,15 +5022,12 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
*/
if ((mailbox == ZO_V1) || (mailbox == ZO_V2))
cy_writel(addr2 + ID_ADDRESS, 0L);
-
- retval = cyz_load_fw(pdev, addr2, addr0, irq);
- if (retval)
- goto err_unmap;
- /* This must be a Cyclades-8Zo/PCI. The extendable
- version will have a different device_id and will
- be allocated its maximum number of ports. */
- nchan = 8;
}
+
+ retval = cyz_load_fw(pdev, addr2, addr0, irq);
+ if (retval <= 0)
+ goto err_unmap;
+ nchan = retval;
}
if ((cy_next_channel + nchan) > NR_PORTS) {
@@ -5103,8 +5057,10 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
dev_err(&pdev->dev, "could not allocate IRQ\n");
goto err_unmap;
}
- cy_card[card_no].num_chips = nchan / 4;
+ cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP;
} else {
+ cy_card[card_no].hw_ver = mailbox;
+ cy_card[card_no].num_chips = (unsigned int)-1;
#ifdef CONFIG_CYZ_INTR
/* allocate IRQ only if board has an IRQ */
if (irq != 0 && irq != 255) {
@@ -5117,15 +5073,15 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
}
}
#endif /* CONFIG_CYZ_INTR */
- cy_card[card_no].num_chips = (unsigned int)-1;
}
/* set cy_card */
cy_card[card_no].base_addr = addr2;
- cy_card[card_no].ctl_addr = addr0;
+ cy_card[card_no].ctl_addr.p9050 = addr0;
cy_card[card_no].irq = irq;
cy_card[card_no].bus_index = 1;
cy_card[card_no].first_line = cy_next_channel;
+ cy_card[card_no].nports = nchan;
retval = cy_init_card(&cy_card[card_no]);
if (retval)
goto err_null;
@@ -5138,17 +5094,20 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
plx_ver = readb(addr2 + CyPLX_VER) & 0x0f;
switch (plx_ver) {
case PLX_9050:
-
cy_writeb(addr0 + 0x4c, 0x43);
break;
case PLX_9060:
case PLX_9080:
default: /* Old boards, use PLX_9060 */
- plx_init(pdev, irq, addr0);
- cy_writew(addr0 + 0x68, readw(addr0 + 0x68) | 0x0900);
+ {
+ struct RUNTIME_9060 __iomem *ctl_addr = addr0;
+ plx_init(pdev, irq, ctl_addr);
+ cy_writew(&ctl_addr->intr_ctrl_stat,
+ readw(&ctl_addr->intr_ctrl_stat) | 0x0900);
break;
}
+ }
}
dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from "
@@ -5179,22 +5138,23 @@ static void __devexit cy_pci_remove(struct pci_dev *pdev)
unsigned int i;
/* non-Z with old PLX */
- if (!IS_CYC_Z(*cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) ==
+ if (!cy_is_Z(cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) ==
PLX_9050)
- cy_writeb(cinfo->ctl_addr + 0x4c, 0);
+ cy_writeb(cinfo->ctl_addr.p9050 + 0x4c, 0);
else
#ifndef CONFIG_CYZ_INTR
- if (!IS_CYC_Z(*cinfo))
+ if (!cy_is_Z(cinfo))
#endif
- cy_writew(cinfo->ctl_addr + 0x68,
- readw(cinfo->ctl_addr + 0x68) & ~0x0900);
+ cy_writew(&cinfo->ctl_addr.p9060->intr_ctrl_stat,
+ readw(&cinfo->ctl_addr.p9060->intr_ctrl_stat) &
+ ~0x0900);
iounmap(cinfo->base_addr);
- if (cinfo->ctl_addr)
- iounmap(cinfo->ctl_addr);
+ if (cinfo->ctl_addr.p9050)
+ iounmap(cinfo->ctl_addr.p9050);
if (cinfo->irq
#ifndef CONFIG_CYZ_INTR
- && !IS_CYC_Z(*cinfo)
+ && !cy_is_Z(cinfo)
#endif /* CONFIG_CYZ_INTR */
)
free_irq(cinfo->irq, cinfo);
@@ -5386,11 +5346,11 @@ static void __exit cy_cleanup_module(void)
/* clear interrupt */
cy_writeb(card->base_addr + Cy_ClrIntr, 0);
iounmap(card->base_addr);
- if (card->ctl_addr)
- iounmap(card->ctl_addr);
+ if (card->ctl_addr.p9050)
+ iounmap(card->ctl_addr.p9050);
if (card->irq
#ifndef CONFIG_CYZ_INTR
- && !IS_CYC_Z(*card)
+ && !cy_is_Z(card)
#endif /* CONFIG_CYZ_INTR */
)
free_irq(card->irq, card);
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index af7c13ca9493..8797b7742350 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -745,7 +745,7 @@ static int epca_carrier_raised(struct tty_port *port)
return 0;
}
-static void epca_raise_dtr_rts(struct tty_port *port)
+static void epca_dtr_rts(struct tty_port *port, int onoff)
{
}
@@ -925,7 +925,7 @@ static const struct tty_operations pc_ops = {
static const struct tty_port_operations epca_port_ops = {
.carrier_raised = epca_carrier_raised,
- .raise_dtr_rts = epca_raise_dtr_rts,
+ .dtr_rts = epca_dtr_rts,
};
static int info_open(struct tty_struct *tty, struct file *filp)
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 50dfa3bc71ce..4a9f3492b921 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -72,7 +72,7 @@ static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ;
#ifdef CONFIG_IA64
static void __iomem *hpet_mctr;
-static cycle_t read_hpet(void)
+static cycle_t read_hpet(struct clocksource *cs)
{
return (cycle_t)read_counter((void __iomem *)hpet_mctr);
}
@@ -224,7 +224,7 @@ static void hpet_timer_set_irq(struct hpet_dev *devp)
break;
}
- gsi = acpi_register_gsi(irq, ACPI_LEVEL_SENSITIVE,
+ gsi = acpi_register_gsi(NULL, irq, ACPI_LEVEL_SENSITIVE,
ACPI_ACTIVE_LOW);
if (gsi > 0)
break;
@@ -939,7 +939,7 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
irqp = &res->data.extended_irq;
for (i = 0; i < irqp->interrupt_count; i++) {
- irq = acpi_register_gsi(irqp->interrupts[i],
+ irq = acpi_register_gsi(NULL, irqp->interrupts[i],
irqp->triggering, irqp->polarity);
if (irq < 0)
return AE_ERROR;
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index 538313f9e7ac..00dd3de1be51 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -89,7 +89,7 @@ static struct hwrng omap_rng_ops = {
.data_read = omap_rng_data_read,
};
-static int __init omap_rng_probe(struct platform_device *pdev)
+static int __devinit omap_rng_probe(struct platform_device *pdev)
{
struct resource *res, *mem;
int ret;
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
index d0e563e4fc39..86e83f883139 100644
--- a/drivers/char/hw_random/virtio-rng.c
+++ b/drivers/char/hw_random/virtio-rng.c
@@ -37,9 +37,9 @@ static void random_recv_done(struct virtqueue *vq)
{
int len;
- /* We never get spurious callbacks. */
+ /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */
if (!vq->vq_ops->get_buf(vq, &len))
- BUG();
+ return;
data_left = len / sizeof(random_data[0]);
complete(&have_data);
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index e93fc8d22fb2..aa83a0865ec1 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -285,6 +285,11 @@ enum ipmi_stat_indexes {
/* Events that were received with the proper format. */
IPMI_STAT_events,
+ /* Retransmissions on IPMB that failed. */
+ IPMI_STAT_dropped_rexmit_ipmb_commands,
+
+ /* Retransmissions on LAN that failed. */
+ IPMI_STAT_dropped_rexmit_lan_commands,
/* This *must* remain last, add new values above this. */
IPMI_NUM_STATS
@@ -445,6 +450,20 @@ static DEFINE_MUTEX(smi_watchers_mutex);
#define ipmi_get_stat(intf, stat) \
((unsigned int) atomic_read(&(intf)->stats[IPMI_STAT_ ## stat]))
+static int is_lan_addr(struct ipmi_addr *addr)
+{
+ return addr->addr_type == IPMI_LAN_ADDR_TYPE;
+}
+
+static int is_ipmb_addr(struct ipmi_addr *addr)
+{
+ return addr->addr_type == IPMI_IPMB_ADDR_TYPE;
+}
+
+static int is_ipmb_bcast_addr(struct ipmi_addr *addr)
+{
+ return addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE;
+}
static void free_recv_msg_list(struct list_head *q)
{
@@ -601,8 +620,7 @@ ipmi_addr_equal(struct ipmi_addr *addr1, struct ipmi_addr *addr2)
return (smi_addr1->lun == smi_addr2->lun);
}
- if ((addr1->addr_type == IPMI_IPMB_ADDR_TYPE)
- || (addr1->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)) {
+ if (is_ipmb_addr(addr1) || is_ipmb_bcast_addr(addr1)) {
struct ipmi_ipmb_addr *ipmb_addr1
= (struct ipmi_ipmb_addr *) addr1;
struct ipmi_ipmb_addr *ipmb_addr2
@@ -612,7 +630,7 @@ ipmi_addr_equal(struct ipmi_addr *addr1, struct ipmi_addr *addr2)
&& (ipmb_addr1->lun == ipmb_addr2->lun));
}
- if (addr1->addr_type == IPMI_LAN_ADDR_TYPE) {
+ if (is_lan_addr(addr1)) {
struct ipmi_lan_addr *lan_addr1
= (struct ipmi_lan_addr *) addr1;
struct ipmi_lan_addr *lan_addr2
@@ -644,14 +662,13 @@ int ipmi_validate_addr(struct ipmi_addr *addr, int len)
|| (addr->channel < 0))
return -EINVAL;
- if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE)
- || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)) {
+ if (is_ipmb_addr(addr) || is_ipmb_bcast_addr(addr)) {
if (len < sizeof(struct ipmi_ipmb_addr))
return -EINVAL;
return 0;
}
- if (addr->addr_type == IPMI_LAN_ADDR_TYPE) {
+ if (is_lan_addr(addr)) {
if (len < sizeof(struct ipmi_lan_addr))
return -EINVAL;
return 0;
@@ -1503,8 +1520,7 @@ static int i_ipmi_request(ipmi_user_t user,
memcpy(&(smi_msg->data[2]), msg->data, msg->data_len);
smi_msg->data_size = msg->data_len + 2;
ipmi_inc_stat(intf, sent_local_commands);
- } else if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE)
- || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)) {
+ } else if (is_ipmb_addr(addr) || is_ipmb_bcast_addr(addr)) {
struct ipmi_ipmb_addr *ipmb_addr;
unsigned char ipmb_seq;
long seqid;
@@ -1583,8 +1599,6 @@ static int i_ipmi_request(ipmi_user_t user,
spin_lock_irqsave(&(intf->seq_lock), flags);
- ipmi_inc_stat(intf, sent_ipmb_commands);
-
/*
* Create a sequence number with a 1 second
* timeout and 4 retries.
@@ -1606,6 +1620,8 @@ static int i_ipmi_request(ipmi_user_t user,
goto out_err;
}
+ ipmi_inc_stat(intf, sent_ipmb_commands);
+
/*
* Store the sequence number in the message,
* so that when the send message response
@@ -1635,7 +1651,7 @@ static int i_ipmi_request(ipmi_user_t user,
*/
spin_unlock_irqrestore(&(intf->seq_lock), flags);
}
- } else if (addr->addr_type == IPMI_LAN_ADDR_TYPE) {
+ } else if (is_lan_addr(addr)) {
struct ipmi_lan_addr *lan_addr;
unsigned char ipmb_seq;
long seqid;
@@ -1696,8 +1712,6 @@ static int i_ipmi_request(ipmi_user_t user,
spin_lock_irqsave(&(intf->seq_lock), flags);
- ipmi_inc_stat(intf, sent_lan_commands);
-
/*
* Create a sequence number with a 1 second
* timeout and 4 retries.
@@ -1719,6 +1733,8 @@ static int i_ipmi_request(ipmi_user_t user,
goto out_err;
}
+ ipmi_inc_stat(intf, sent_lan_commands);
+
/*
* Store the sequence number in the message,
* so that when the send message response
@@ -1937,6 +1953,10 @@ static int stat_file_read_proc(char *page, char **start, off_t off,
ipmi_get_stat(intf, invalid_events));
out += sprintf(out, "events: %u\n",
ipmi_get_stat(intf, events));
+ out += sprintf(out, "failed rexmit LAN msgs: %u\n",
+ ipmi_get_stat(intf, dropped_rexmit_lan_commands));
+ out += sprintf(out, "failed rexmit IPMB msgs: %u\n",
+ ipmi_get_stat(intf, dropped_rexmit_ipmb_commands));
return (out - ((char *) page));
}
@@ -3264,6 +3284,114 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf,
return rv;
}
+/*
+ * This routine will handle "Get Message" command responses with
+ * channels that use an OEM Medium. The message format belongs to
+ * the OEM. See IPMI 2.0 specification, Chapter 6 and
+ * Chapter 22, sections 22.6 and 22.24 for more details.
+ */
+static int handle_oem_get_msg_cmd(ipmi_smi_t intf,
+ struct ipmi_smi_msg *msg)
+{
+ struct cmd_rcvr *rcvr;
+ int rv = 0;
+ unsigned char netfn;
+ unsigned char cmd;
+ unsigned char chan;
+ ipmi_user_t user = NULL;
+ struct ipmi_system_interface_addr *smi_addr;
+ struct ipmi_recv_msg *recv_msg;
+
+ /*
+ * We expect the OEM SW to perform error checking
+ * so we just do some basic sanity checks
+ */
+ if (msg->rsp_size < 4) {
+ /* Message not big enough, just ignore it. */
+ ipmi_inc_stat(intf, invalid_commands);
+ return 0;
+ }
+
+ if (msg->rsp[2] != 0) {
+ /* An error getting the response, just ignore it. */
+ return 0;
+ }
+
+ /*
+ * This is an OEM Message so the OEM needs to know how
+ * handle the message. We do no interpretation.
+ */
+ netfn = msg->rsp[0] >> 2;
+ cmd = msg->rsp[1];
+ chan = msg->rsp[3] & 0xf;
+
+ rcu_read_lock();
+ rcvr = find_cmd_rcvr(intf, netfn, cmd, chan);
+ if (rcvr) {
+ user = rcvr->user;
+ kref_get(&user->refcount);
+ } else
+ user = NULL;
+ rcu_read_unlock();
+
+ if (user == NULL) {
+ /* We didn't find a user, just give up. */
+ ipmi_inc_stat(intf, unhandled_commands);
+
+ /*
+ * Don't do anything with these messages, just allow
+ * them to be freed.
+ */
+
+ rv = 0;
+ } else {
+ /* Deliver the message to the user. */
+ ipmi_inc_stat(intf, handled_commands);
+
+ recv_msg = ipmi_alloc_recv_msg();
+ if (!recv_msg) {
+ /*
+ * We couldn't allocate memory for the
+ * message, so requeue it for handling
+ * later.
+ */
+ rv = 1;
+ kref_put(&user->refcount, free_user);
+ } else {
+ /*
+ * OEM Messages are expected to be delivered via
+ * the system interface to SMS software. We might
+ * need to visit this again depending on OEM
+ * requirements
+ */
+ smi_addr = ((struct ipmi_system_interface_addr *)
+ &(recv_msg->addr));
+ smi_addr->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+ smi_addr->channel = IPMI_BMC_CHANNEL;
+ smi_addr->lun = msg->rsp[0] & 3;
+
+ recv_msg->user = user;
+ recv_msg->user_msg_data = NULL;
+ recv_msg->recv_type = IPMI_OEM_RECV_TYPE;
+ recv_msg->msg.netfn = msg->rsp[0] >> 2;
+ recv_msg->msg.cmd = msg->rsp[1];
+ recv_msg->msg.data = recv_msg->msg_data;
+
+ /*
+ * The message starts at byte 4 which follows the
+ * the Channel Byte in the "GET MESSAGE" command
+ */
+ recv_msg->msg.data_len = msg->rsp_size - 4;
+ memcpy(recv_msg->msg_data,
+ &(msg->rsp[4]),
+ msg->rsp_size - 4);
+ deliver_response(recv_msg);
+ }
+ }
+
+ return rv;
+}
+
static void copy_event_into_recv_msg(struct ipmi_recv_msg *recv_msg,
struct ipmi_smi_msg *msg)
{
@@ -3519,6 +3647,17 @@ static int handle_new_recv_msg(ipmi_smi_t intf,
goto out;
}
+ /*
+ ** We need to make sure the channels have been initialized.
+ ** The channel_handler routine will set the "curr_channel"
+ ** equal to or greater than IPMI_MAX_CHANNELS when all the
+ ** channels for this interface have been initialized.
+ */
+ if (intf->curr_channel < IPMI_MAX_CHANNELS) {
+ requeue = 1; /* Just put the message back for now */
+ goto out;
+ }
+
switch (intf->channels[chan].medium) {
case IPMI_CHANNEL_MEDIUM_IPMB:
if (msg->rsp[4] & 0x04) {
@@ -3554,11 +3693,20 @@ static int handle_new_recv_msg(ipmi_smi_t intf,
break;
default:
- /*
- * We don't handle the channel type, so just
- * free the message.
- */
- requeue = 0;
+ /* Check for OEM Channels. Clients had better
+ register for these commands. */
+ if ((intf->channels[chan].medium
+ >= IPMI_CHANNEL_MEDIUM_OEM_MIN)
+ && (intf->channels[chan].medium
+ <= IPMI_CHANNEL_MEDIUM_OEM_MAX)) {
+ requeue = handle_oem_get_msg_cmd(intf, msg);
+ } else {
+ /*
+ * We don't handle the channel type, so just
+ * free the message.
+ */
+ requeue = 0;
+ }
}
} else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2))
@@ -3730,7 +3878,7 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent,
list_add_tail(&msg->link, timeouts);
if (ent->broadcast)
ipmi_inc_stat(intf, timed_out_ipmb_broadcasts);
- else if (ent->recv_msg->addr.addr_type == IPMI_LAN_ADDR_TYPE)
+ else if (is_lan_addr(&ent->recv_msg->addr))
ipmi_inc_stat(intf, timed_out_lan_commands);
else
ipmi_inc_stat(intf, timed_out_ipmb_commands);
@@ -3744,15 +3892,17 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent,
*/
ent->timeout = MAX_MSG_TIMEOUT;
ent->retries_left--;
- if (ent->recv_msg->addr.addr_type == IPMI_LAN_ADDR_TYPE)
- ipmi_inc_stat(intf, retransmitted_lan_commands);
- else
- ipmi_inc_stat(intf, retransmitted_ipmb_commands);
-
smi_msg = smi_from_recv_msg(intf, ent->recv_msg, slot,
ent->seqid);
- if (!smi_msg)
+ if (!smi_msg) {
+ if (is_lan_addr(&ent->recv_msg->addr))
+ ipmi_inc_stat(intf,
+ dropped_rexmit_lan_commands);
+ else
+ ipmi_inc_stat(intf,
+ dropped_rexmit_ipmb_commands);
return;
+ }
spin_unlock_irqrestore(&intf->seq_lock, *flags);
@@ -3764,10 +3914,17 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent,
* resent.
*/
handlers = intf->handlers;
- if (handlers)
+ if (handlers) {
+ if (is_lan_addr(&ent->recv_msg->addr))
+ ipmi_inc_stat(intf,
+ retransmitted_lan_commands);
+ else
+ ipmi_inc_stat(intf,
+ retransmitted_ipmb_commands);
+
intf->handlers->sender(intf->send_info,
smi_msg, 0);
- else
+ } else
ipmi_free_smi_msg(smi_msg);
spin_lock_irqsave(&intf->seq_lock, *flags);
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index e58ea4cd55ce..259644646b82 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -82,12 +82,6 @@
#define SI_SHORT_TIMEOUT_USEC 250 /* .25ms when the SM request a
short timeout */
-/* Bit for BMC global enables. */
-#define IPMI_BMC_RCV_MSG_INTR 0x01
-#define IPMI_BMC_EVT_MSG_INTR 0x02
-#define IPMI_BMC_EVT_MSG_BUFF 0x04
-#define IPMI_BMC_SYS_LOG 0x08
-
enum si_intf_state {
SI_NORMAL,
SI_GETTING_FLAGS,
@@ -220,6 +214,9 @@ struct smi_info {
OEM2_DATA_AVAIL)
unsigned char msg_flags;
+ /* Does the BMC have an event buffer? */
+ char has_event_buffer;
+
/*
* If set to true, this will request events the next time the
* state machine is idle.
@@ -968,7 +965,8 @@ static void request_events(void *send_info)
{
struct smi_info *smi_info = send_info;
- if (atomic_read(&smi_info->stop_operation))
+ if (atomic_read(&smi_info->stop_operation) ||
+ !smi_info->has_event_buffer)
return;
atomic_set(&smi_info->req_events, 1);
@@ -2407,26 +2405,9 @@ static struct of_platform_driver ipmi_of_platform_driver = {
};
#endif /* CONFIG_PPC_OF */
-
-static int try_get_dev_id(struct smi_info *smi_info)
+static int wait_for_msg_done(struct smi_info *smi_info)
{
- unsigned char msg[2];
- unsigned char *resp;
- unsigned long resp_len;
enum si_sm_result smi_result;
- int rv = 0;
-
- resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
- if (!resp)
- return -ENOMEM;
-
- /*
- * Do a Get Device ID command, since it comes back with some
- * useful info.
- */
- msg[0] = IPMI_NETFN_APP_REQUEST << 2;
- msg[1] = IPMI_GET_DEVICE_ID_CMD;
- smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
smi_result = smi_info->handlers->event(smi_info->si_sm, 0);
for (;;) {
@@ -2441,16 +2422,39 @@ static int try_get_dev_id(struct smi_info *smi_info)
} else
break;
}
- if (smi_result == SI_SM_HOSED) {
+ if (smi_result == SI_SM_HOSED)
/*
* We couldn't get the state machine to run, so whatever's at
* the port is probably not an IPMI SMI interface.
*/
- rv = -ENODEV;
+ return -ENODEV;
+
+ return 0;
+}
+
+static int try_get_dev_id(struct smi_info *smi_info)
+{
+ unsigned char msg[2];
+ unsigned char *resp;
+ unsigned long resp_len;
+ int rv = 0;
+
+ resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
+ if (!resp)
+ return -ENOMEM;
+
+ /*
+ * Do a Get Device ID command, since it comes back with some
+ * useful info.
+ */
+ msg[0] = IPMI_NETFN_APP_REQUEST << 2;
+ msg[1] = IPMI_GET_DEVICE_ID_CMD;
+ smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
+
+ rv = wait_for_msg_done(smi_info);
+ if (rv)
goto out;
- }
- /* Otherwise, we got some data. */
resp_len = smi_info->handlers->get_result(smi_info->si_sm,
resp, IPMI_MAX_MSG_LENGTH);
@@ -2462,6 +2466,88 @@ static int try_get_dev_id(struct smi_info *smi_info)
return rv;
}
+static int try_enable_event_buffer(struct smi_info *smi_info)
+{
+ unsigned char msg[3];
+ unsigned char *resp;
+ unsigned long resp_len;
+ int rv = 0;
+
+ resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
+ if (!resp)
+ return -ENOMEM;
+
+ msg[0] = IPMI_NETFN_APP_REQUEST << 2;
+ msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
+ smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
+
+ rv = wait_for_msg_done(smi_info);
+ if (rv) {
+ printk(KERN_WARNING
+ "ipmi_si: Error getting response from get global,"
+ " enables command, the event buffer is not"
+ " enabled.\n");
+ goto out;
+ }
+
+ resp_len = smi_info->handlers->get_result(smi_info->si_sm,
+ resp, IPMI_MAX_MSG_LENGTH);
+
+ if (resp_len < 4 ||
+ resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 ||
+ resp[1] != IPMI_GET_BMC_GLOBAL_ENABLES_CMD ||
+ resp[2] != 0) {
+ printk(KERN_WARNING
+ "ipmi_si: Invalid return from get global"
+ " enables command, cannot enable the event"
+ " buffer.\n");
+ rv = -EINVAL;
+ goto out;
+ }
+
+ if (resp[3] & IPMI_BMC_EVT_MSG_BUFF)
+ /* buffer is already enabled, nothing to do. */
+ goto out;
+
+ msg[0] = IPMI_NETFN_APP_REQUEST << 2;
+ msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
+ msg[2] = resp[3] | IPMI_BMC_EVT_MSG_BUFF;
+ smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3);
+
+ rv = wait_for_msg_done(smi_info);
+ if (rv) {
+ printk(KERN_WARNING
+ "ipmi_si: Error getting response from set global,"
+ " enables command, the event buffer is not"
+ " enabled.\n");
+ goto out;
+ }
+
+ resp_len = smi_info->handlers->get_result(smi_info->si_sm,
+ resp, IPMI_MAX_MSG_LENGTH);
+
+ if (resp_len < 3 ||
+ resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 ||
+ resp[1] != IPMI_SET_BMC_GLOBAL_ENABLES_CMD) {
+ printk(KERN_WARNING
+ "ipmi_si: Invalid return from get global,"
+ "enables command, not enable the event"
+ " buffer.\n");
+ rv = -EINVAL;
+ goto out;
+ }
+
+ if (resp[2] != 0)
+ /*
+ * An error when setting the event buffer bit means
+ * that the event buffer is not supported.
+ */
+ rv = -ENOENT;
+ out:
+ kfree(resp);
+ return rv;
+}
+
static int type_file_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
@@ -2847,6 +2933,10 @@ static int try_smi_init(struct smi_info *new_smi)
new_smi->intf_num = smi_num;
smi_num++;
+ rv = try_enable_event_buffer(new_smi);
+ if (rv == 0)
+ new_smi->has_event_buffer = 1;
+
/*
* Start clearing the flags before we enable interrupts or the
* timer to avoid racing with the timer.
@@ -2863,7 +2953,7 @@ static int try_smi_init(struct smi_info *new_smi)
*/
new_smi->pdev = platform_device_alloc("ipmi_si",
new_smi->intf_num);
- if (rv) {
+ if (!new_smi->pdev) {
printk(KERN_ERR
"ipmi_si_intf:"
" Unable to allocate platform device\n");
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index a59eac584d16..4d745a89504f 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -329,7 +329,7 @@ static inline void drop_rts(struct isi_port *port)
/* card->lock MUST NOT be held */
-static void isicom_raise_dtr_rts(struct tty_port *port)
+static void isicom_dtr_rts(struct tty_port *port, int on)
{
struct isi_port *ip = container_of(port, struct isi_port, port);
struct isi_board *card = ip->card;
@@ -339,10 +339,17 @@ static void isicom_raise_dtr_rts(struct tty_port *port)
if (!lock_card(card))
return;
- outw(0x8000 | (channel << card->shift_count) | 0x02, base);
- outw(0x0f04, base);
- InterruptTheCard(base);
- ip->status |= (ISI_DTR | ISI_RTS);
+ if (on) {
+ outw(0x8000 | (channel << card->shift_count) | 0x02, base);
+ outw(0x0f04, base);
+ InterruptTheCard(base);
+ ip->status |= (ISI_DTR | ISI_RTS);
+ } else {
+ outw(0x8000 | (channel << card->shift_count) | 0x02, base);
+ outw(0x0C04, base);
+ InterruptTheCard(base);
+ ip->status &= ~(ISI_DTR | ISI_RTS);
+ }
unlock_card(card);
}
@@ -1339,7 +1346,7 @@ static const struct tty_operations isicom_ops = {
static const struct tty_port_operations isicom_port_ops = {
.carrier_raised = isicom_carrier_raised,
- .raise_dtr_rts = isicom_raise_dtr_rts,
+ .dtr_rts = isicom_dtr_rts,
};
static int __devinit reset_card(struct pci_dev *pdev,
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index fff19f7e29d2..e18800c400b1 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -1140,14 +1140,14 @@ static int stli_carrier_raised(struct tty_port *port)
return (portp->sigs & TIOCM_CD) ? 1 : 0;
}
-static void stli_raise_dtr_rts(struct tty_port *port)
+static void stli_dtr_rts(struct tty_port *port, int on)
{
struct stliport *portp = container_of(port, struct stliport, port);
struct stlibrd *brdp = stli_brds[portp->brdnr];
- stli_mkasysigs(&portp->asig, 1, 1);
+ stli_mkasysigs(&portp->asig, on, on);
if (stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
sizeof(asysigs_t), 0) < 0)
- printk(KERN_WARNING "istallion: dtr raise failed.\n");
+ printk(KERN_WARNING "istallion: dtr set failed.\n");
}
@@ -4417,7 +4417,7 @@ static const struct tty_operations stli_ops = {
static const struct tty_port_operations stli_port_ops = {
.carrier_raised = stli_carrier_raised,
- .raise_dtr_rts = stli_raise_dtr_rts,
+ .dtr_rts = stli_dtr_rts,
};
/*****************************************************************************/
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index de26a978fbdd..737be953cc58 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -1123,8 +1123,6 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode,
#define HW_RAW(dev) 0
-#warning "Cannot generate rawmode keyboard for your architecture yet."
-
static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag)
{
if (keycode > 127)
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 3586b3b3df3f..8f05c38c2f06 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -301,33 +301,7 @@ static inline int private_mapping_ok(struct vm_area_struct *vma)
}
#endif
-void __attribute__((weak))
-map_devmem(unsigned long pfn, unsigned long len, pgprot_t prot)
-{
- /* nothing. architectures can override. */
-}
-
-void __attribute__((weak))
-unmap_devmem(unsigned long pfn, unsigned long len, pgprot_t prot)
-{
- /* nothing. architectures can override. */
-}
-
-static void mmap_mem_open(struct vm_area_struct *vma)
-{
- map_devmem(vma->vm_pgoff, vma->vm_end - vma->vm_start,
- vma->vm_page_prot);
-}
-
-static void mmap_mem_close(struct vm_area_struct *vma)
-{
- unmap_devmem(vma->vm_pgoff, vma->vm_end - vma->vm_start,
- vma->vm_page_prot);
-}
-
static struct vm_operations_struct mmap_mem_ops = {
- .open = mmap_mem_open,
- .close = mmap_mem_close,
#ifdef CONFIG_HAVE_IOREMAP_PROT
.access = generic_access_phys
#endif
@@ -362,7 +336,6 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
vma->vm_pgoff,
size,
vma->vm_page_prot)) {
- unmap_devmem(vma->vm_pgoff, size, vma->vm_page_prot);
return -EAGAIN;
}
return 0;
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index a420e8d437dd..6dfef561ee50 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -547,14 +547,18 @@ static int mxser_carrier_raised(struct tty_port *port)
return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0;
}
-static void mxser_raise_dtr_rts(struct tty_port *port)
+static void mxser_dtr_rts(struct tty_port *port, int on)
{
struct mxser_port *mp = container_of(port, struct mxser_port, port);
unsigned long flags;
spin_lock_irqsave(&mp->slock, flags);
- outb(inb(mp->ioaddr + UART_MCR) |
- UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR);
+ if (on)
+ outb(inb(mp->ioaddr + UART_MCR) |
+ UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR);
+ else
+ outb(inb(mp->ioaddr + UART_MCR)&~(UART_MCR_DTR | UART_MCR_RTS),
+ mp->ioaddr + UART_MCR);
spin_unlock_irqrestore(&mp->slock, flags);
}
@@ -2356,7 +2360,7 @@ static const struct tty_operations mxser_ops = {
struct tty_port_operations mxser_port_ops = {
.carrier_raised = mxser_carrier_raised,
- .raise_dtr_rts = mxser_raise_dtr_rts,
+ .dtr_rts = mxser_dtr_rts,
};
/*
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 19d79fc54461..77b364889224 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -383,7 +383,7 @@ static void async_mode(MGSLPC_INFO *info);
static void tx_timeout(unsigned long context);
static int carrier_raised(struct tty_port *port);
-static void raise_dtr_rts(struct tty_port *port);
+static void dtr_rts(struct tty_port *port, int onoff);
#if SYNCLINK_GENERIC_HDLC
#define dev_to_port(D) (dev_to_hdlc(D)->priv)
@@ -513,7 +513,7 @@ static void ldisc_receive_buf(struct tty_struct *tty,
static const struct tty_port_operations mgslpc_port_ops = {
.carrier_raised = carrier_raised,
- .raise_dtr_rts = raise_dtr_rts
+ .dtr_rts = dtr_rts
};
static int mgslpc_probe(struct pcmcia_device *link)
@@ -2528,13 +2528,16 @@ static int carrier_raised(struct tty_port *port)
return 0;
}
-static void raise_dtr_rts(struct tty_port *port)
+static void dtr_rts(struct tty_port *port, int onoff)
{
MGSLPC_INFO *info = container_of(port, MGSLPC_INFO, port);
unsigned long flags;
spin_lock_irqsave(&info->lock,flags);
- info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+ if (onoff)
+ info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+ else
+ info->serial_signals &= ~SerialSignal_RTS + SerialSignal_DTR;
set_signals(info);
spin_unlock_irqrestore(&info->lock,flags);
}
diff --git a/drivers/char/random.c b/drivers/char/random.c
index f824ef8a9273..b2ced39d76b2 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1665,15 +1665,20 @@ EXPORT_SYMBOL(secure_dccp_sequence_number);
* value is not cryptographically secure but for several uses the cost of
* depleting entropy is too high
*/
+DEFINE_PER_CPU(__u32 [4], get_random_int_hash);
unsigned int get_random_int(void)
{
- /*
- * Use IP's RNG. It suits our purpose perfectly: it re-keys itself
- * every second, from the entropy pool (and thus creates a limited
- * drain on it), and uses halfMD4Transform within the second. We
- * also mix it with jiffies and the PID:
- */
- return secure_ip_id((__force __be32)(current->pid + jiffies));
+ struct keydata *keyptr;
+ __u32 *hash = get_cpu_var(get_random_int_hash);
+ int ret;
+
+ keyptr = get_keyptr();
+ hash[0] += current->pid + jiffies + get_cycles() + (int)(long)&ret;
+
+ ret = half_md4_transform(hash, keyptr->secret);
+ put_cpu_var(get_random_int_hash);
+
+ return ret;
}
/*
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index f59fc5cea067..7399188049d8 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -872,11 +872,16 @@ static int carrier_raised(struct tty_port *port)
return (sGetChanStatusLo(&info->channel) & CD_ACT) ? 1 : 0;
}
-static void raise_dtr_rts(struct tty_port *port)
+static void dtr_rts(struct tty_port *port, int on)
{
struct r_port *info = container_of(port, struct r_port, port);
- sSetDTR(&info->channel);
- sSetRTS(&info->channel);
+ if (on) {
+ sSetDTR(&info->channel);
+ sSetRTS(&info->channel);
+ } else {
+ sClrDTR(&info->channel);
+ sClrRTS(&info->channel);
+ }
}
/*
@@ -2250,7 +2255,7 @@ static const struct tty_operations rocket_ops = {
static const struct tty_port_operations rocket_port_ops = {
.carrier_raised = carrier_raised,
- .raise_dtr_rts = raise_dtr_rts,
+ .dtr_rts = dtr_rts,
};
/*
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 2ad813a801dc..53e504f41b20 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -772,11 +772,11 @@ static int stl_carrier_raised(struct tty_port *port)
return (portp->sigs & TIOCM_CD) ? 1 : 0;
}
-static void stl_raise_dtr_rts(struct tty_port *port)
+static void stl_dtr_rts(struct tty_port *port, int on)
{
struct stlport *portp = container_of(port, struct stlport, port);
/* Takes brd_lock internally */
- stl_setsignals(portp, 1, 1);
+ stl_setsignals(portp, on, on);
}
/*****************************************************************************/
@@ -2547,7 +2547,7 @@ static const struct tty_operations stl_ops = {
static const struct tty_port_operations stl_port_ops = {
.carrier_raised = stl_carrier_raised,
- .raise_dtr_rts = stl_raise_dtr_rts,
+ .dtr_rts = stl_dtr_rts,
};
/*****************************************************************************/
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index afd0b26ca056..afded3a2379c 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -3247,13 +3247,16 @@ static int carrier_raised(struct tty_port *port)
return (info->serial_signals & SerialSignal_DCD) ? 1 : 0;
}
-static void raise_dtr_rts(struct tty_port *port)
+static void dtr_rts(struct tty_port *port, int on)
{
struct mgsl_struct *info = container_of(port, struct mgsl_struct, port);
unsigned long flags;
spin_lock_irqsave(&info->irq_spinlock,flags);
- info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+ if (on)
+ info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+ else
+ info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
usc_set_serial_signals(info);
spin_unlock_irqrestore(&info->irq_spinlock,flags);
}
@@ -4258,7 +4261,7 @@ static void mgsl_add_device( struct mgsl_struct *info )
static const struct tty_port_operations mgsl_port_ops = {
.carrier_raised = carrier_raised,
- .raise_dtr_rts = raise_dtr_rts,
+ .dtr_rts = dtr_rts,
};
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 5e256494686a..1386625fc4ca 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -214,6 +214,7 @@ struct slgt_desc
#define set_desc_next(a,b) (a).next = cpu_to_le32((unsigned int)(b))
#define set_desc_count(a,b)(a).count = cpu_to_le16((unsigned short)(b))
#define set_desc_eof(a,b) (a).status = cpu_to_le16((b) ? (le16_to_cpu((a).status) | BIT0) : (le16_to_cpu((a).status) & ~BIT0))
+#define set_desc_status(a, b) (a).status = cpu_to_le16((unsigned short)(b))
#define desc_count(a) (le16_to_cpu((a).count))
#define desc_status(a) (le16_to_cpu((a).status))
#define desc_complete(a) (le16_to_cpu((a).status) & BIT15)
@@ -297,6 +298,7 @@ struct slgt_info {
u32 max_frame_size; /* as set by device config */
unsigned int rbuf_fill_level;
+ unsigned int rx_pio;
unsigned int if_mode;
unsigned int base_clock;
@@ -331,6 +333,8 @@ struct slgt_info {
struct slgt_desc *rbufs;
unsigned int rbuf_current;
unsigned int rbuf_index;
+ unsigned int rbuf_fill_index;
+ unsigned short rbuf_fill_count;
unsigned int tbuf_count;
struct slgt_desc *tbufs;
@@ -2110,6 +2114,40 @@ static void ri_change(struct slgt_info *info, unsigned short status)
info->pending_bh |= BH_STATUS;
}
+static void isr_rxdata(struct slgt_info *info)
+{
+ unsigned int count = info->rbuf_fill_count;
+ unsigned int i = info->rbuf_fill_index;
+ unsigned short reg;
+
+ while (rd_reg16(info, SSR) & IRQ_RXDATA) {
+ reg = rd_reg16(info, RDR);
+ DBGISR(("isr_rxdata %s RDR=%04X\n", info->device_name, reg));
+ if (desc_complete(info->rbufs[i])) {
+ /* all buffers full */
+ rx_stop(info);
+ info->rx_restart = 1;
+ continue;
+ }
+ info->rbufs[i].buf[count++] = (unsigned char)reg;
+ /* async mode saves status byte to buffer for each data byte */
+ if (info->params.mode == MGSL_MODE_ASYNC)
+ info->rbufs[i].buf[count++] = (unsigned char)(reg >> 8);
+ if (count == info->rbuf_fill_level || (reg & BIT10)) {
+ /* buffer full or end of frame */
+ set_desc_count(info->rbufs[i], count);
+ set_desc_status(info->rbufs[i], BIT15 | (reg >> 8));
+ info->rbuf_fill_count = count = 0;
+ if (++i == info->rbuf_count)
+ i = 0;
+ info->pending_bh |= BH_RECEIVE;
+ }
+ }
+
+ info->rbuf_fill_index = i;
+ info->rbuf_fill_count = count;
+}
+
static void isr_serial(struct slgt_info *info)
{
unsigned short status = rd_reg16(info, SSR);
@@ -2125,6 +2163,8 @@ static void isr_serial(struct slgt_info *info)
if (info->tx_count)
isr_txeom(info, status);
}
+ if (info->rx_pio && (status & IRQ_RXDATA))
+ isr_rxdata(info);
if ((status & IRQ_RXBREAK) && (status & RXBREAK)) {
info->icount.brk++;
/* process break detection if tty control allows */
@@ -2141,7 +2181,8 @@ static void isr_serial(struct slgt_info *info)
} else {
if (status & (IRQ_TXIDLE + IRQ_TXUNDER))
isr_txeom(info, status);
-
+ if (info->rx_pio && (status & IRQ_RXDATA))
+ isr_rxdata(info);
if (status & IRQ_RXIDLE) {
if (status & RXIDLE)
info->icount.rxidle++;
@@ -2642,6 +2683,10 @@ static int rx_enable(struct slgt_info *info, int enable)
return -EINVAL;
}
info->rbuf_fill_level = rbuf_fill_level;
+ if (rbuf_fill_level < 128)
+ info->rx_pio = 1; /* PIO mode */
+ else
+ info->rx_pio = 0; /* DMA mode */
rx_stop(info); /* restart receiver to use new fill level */
}
@@ -3099,13 +3144,16 @@ static int carrier_raised(struct tty_port *port)
return (info->signals & SerialSignal_DCD) ? 1 : 0;
}
-static void raise_dtr_rts(struct tty_port *port)
+static void dtr_rts(struct tty_port *port, int on)
{
unsigned long flags;
struct slgt_info *info = container_of(port, struct slgt_info, port);
spin_lock_irqsave(&info->lock,flags);
- info->signals |= SerialSignal_RTS + SerialSignal_DTR;
+ if (on)
+ info->signals |= SerialSignal_RTS + SerialSignal_DTR;
+ else
+ info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
set_signals(info);
spin_unlock_irqrestore(&info->lock,flags);
}
@@ -3419,7 +3467,7 @@ static void add_device(struct slgt_info *info)
static const struct tty_port_operations slgt_port_ops = {
.carrier_raised = carrier_raised,
- .raise_dtr_rts = raise_dtr_rts,
+ .dtr_rts = dtr_rts,
};
/*
@@ -3841,15 +3889,27 @@ static void rx_start(struct slgt_info *info)
rdma_reset(info);
reset_rbufs(info);
- /* set 1st descriptor address */
- wr_reg32(info, RDDAR, info->rbufs[0].pdesc);
-
- if (info->params.mode != MGSL_MODE_ASYNC) {
- /* enable rx DMA and DMA interrupt */
- wr_reg32(info, RDCSR, (BIT2 + BIT0));
+ if (info->rx_pio) {
+ /* rx request when rx FIFO not empty */
+ wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) & ~BIT14));
+ slgt_irq_on(info, IRQ_RXDATA);
+ if (info->params.mode == MGSL_MODE_ASYNC) {
+ /* enable saving of rx status */
+ wr_reg32(info, RDCSR, BIT6);
+ }
} else {
- /* enable saving of rx status, rx DMA and DMA interrupt */
- wr_reg32(info, RDCSR, (BIT6 + BIT2 + BIT0));
+ /* rx request when rx FIFO half full */
+ wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) | BIT14));
+ /* set 1st descriptor address */
+ wr_reg32(info, RDDAR, info->rbufs[0].pdesc);
+
+ if (info->params.mode != MGSL_MODE_ASYNC) {
+ /* enable rx DMA and DMA interrupt */
+ wr_reg32(info, RDCSR, (BIT2 + BIT0));
+ } else {
+ /* enable saving of rx status, rx DMA and DMA interrupt */
+ wr_reg32(info, RDCSR, (BIT6 + BIT2 + BIT0));
+ }
}
slgt_irq_on(info, IRQ_RXOVER);
@@ -4467,6 +4527,8 @@ static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last
static void reset_rbufs(struct slgt_info *info)
{
free_rbufs(info, 0, info->rbuf_count - 1);
+ info->rbuf_fill_index = 0;
+ info->rbuf_fill_count = 0;
}
/*
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index 26de60efe4b2..6f727e3c53ad 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -3277,13 +3277,16 @@ static int carrier_raised(struct tty_port *port)
return (info->serial_signals & SerialSignal_DCD) ? 1 : 0;
}
-static void raise_dtr_rts(struct tty_port *port)
+static void dtr_rts(struct tty_port *port, int on)
{
SLMP_INFO *info = container_of(port, SLMP_INFO, port);
unsigned long flags;
spin_lock_irqsave(&info->lock,flags);
- info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+ if (on)
+ info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+ else
+ info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
set_signals(info);
spin_unlock_irqrestore(&info->lock,flags);
}
@@ -3746,7 +3749,7 @@ static void add_device(SLMP_INFO *info)
static const struct tty_port_operations port_ops = {
.carrier_raised = carrier_raised,
- .raise_dtr_rts = raise_dtr_rts,
+ .dtr_rts = dtr_rts,
};
/* Allocate and initialize a device instance structure
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 6de020d078e1..b0a6a3e51924 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -35,7 +35,6 @@
#include <linux/vt_kern.h>
#include <linux/workqueue.h>
#include <linux/kexec.h>
-#include <linux/interrupt.h>
#include <linux/hrtimer.h>
#include <linux/oom.h>
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c
index 9b8004c72686..4d08b6d27c28 100644
--- a/drivers/char/tty_port.c
+++ b/drivers/char/tty_port.c
@@ -137,7 +137,7 @@ int tty_port_carrier_raised(struct tty_port *port)
EXPORT_SYMBOL(tty_port_carrier_raised);
/**
- * tty_port_raise_dtr_rts - Riase DTR/RTS
+ * tty_port_raise_dtr_rts - Raise DTR/RTS
* @port: tty port
*
* Wrapper for the DTR/RTS raise logic. For the moment this is used
@@ -147,12 +147,28 @@ EXPORT_SYMBOL(tty_port_carrier_raised);
void tty_port_raise_dtr_rts(struct tty_port *port)
{
- if (port->ops->raise_dtr_rts)
- port->ops->raise_dtr_rts(port);
+ if (port->ops->dtr_rts)
+ port->ops->dtr_rts(port, 1);
}
EXPORT_SYMBOL(tty_port_raise_dtr_rts);
/**
+ * tty_port_lower_dtr_rts - Lower DTR/RTS
+ * @port: tty port
+ *
+ * Wrapper for the DTR/RTS raise logic. For the moment this is used
+ * to hide some internal details. This will eventually become entirely
+ * internal to the tty port.
+ */
+
+void tty_port_lower_dtr_rts(struct tty_port *port)
+{
+ if (port->ops->dtr_rts)
+ port->ops->dtr_rts(port, 0);
+}
+EXPORT_SYMBOL(tty_port_lower_dtr_rts);
+
+/**
* tty_port_block_til_ready - Waiting logic for tty open
* @port: the tty port being opened
* @tty: the tty device being bound
@@ -167,7 +183,7 @@ EXPORT_SYMBOL(tty_port_raise_dtr_rts);
* - port flags and counts
*
* The passed tty_port must implement the carrier_raised method if it can
- * do carrier detect and the raise_dtr_rts method if it supports software
+ * do carrier detect and the dtr_rts method if it supports software
* management of these lines. Note that the dtr/rts raise is done each
* iteration as a hangup may have previously dropped them while we wait.
*/
@@ -292,6 +308,17 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f
if (port->flags & ASYNC_INITIALIZED &&
port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
tty_wait_until_sent(tty, port->closing_wait);
+ if (port->drain_delay) {
+ unsigned int bps = tty_get_baud_rate(tty);
+ long timeout;
+
+ if (bps > 1200)
+ timeout = max_t(long, (HZ * 10 * port->drain_delay) / bps,
+ HZ / 10);
+ else
+ timeout = 2 * HZ;
+ schedule_timeout_interruptible(timeout);
+ }
return 1;
}
EXPORT_SYMBOL(tty_port_close_start);
@@ -302,6 +329,9 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
tty_ldisc_flush(tty);
+ if (tty->termios->c_cflag & HUPCL)
+ tty_port_lower_dtr_rts(port);
+
spin_lock_irqsave(&port->lock, flags);
tty->closing = 0;
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 2c1d133819b5..961c1a788c61 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -104,6 +104,7 @@
#include <linux/io.h>
#include <asm/system.h>
#include <linux/uaccess.h>
+#include <linux/kmemleak.h>
#define MAX_NR_CON_DRIVER 16
@@ -2274,7 +2275,7 @@ rescan_last_byte:
continue; /* nothing to display */
}
/* Glyph not found */
- if ((!(vc->vc_utf && !vc->vc_disp_ctrl) && c < 128) && !(c & ~charmask)) {
+ if ((!(vc->vc_utf && !vc->vc_disp_ctrl) || c < 128) && !(c & ~charmask)) {
/* In legacy mode use the glyph we get by a 1:1 mapping.
This would make absolutely no sense with Unicode in mind,
but do this for ASCII characters since a font may lack
@@ -2880,6 +2881,12 @@ static int __init con_init(void)
*/
for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
vc_cons[currcons].d = vc = alloc_bootmem(sizeof(struct vc_data));
+ /*
+ * Kmemleak does not track the memory allocated via
+ * alloc_bootmem() but this block contains pointers to
+ * other blocks allocated via kmalloc.
+ */
+ kmemleak_alloc(vc, sizeof(struct vc_data), 1, GFP_ATOMIC);
INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
visual_init(vc, currcons, 1);
vc->vc_screenbuf = (unsigned short *)alloc_bootmem(vc->vc_screenbuf_size);
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index a2dee0eb6dad..e6ce632a393e 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -400,6 +400,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
case KIOCSOUND:
if (!perm)
goto eperm;
+ /* FIXME: This is an old broken API but we need to keep it
+ supported and somehow separate the historic advertised
+ tick rate from any real one */
if (arg)
arg = CLOCK_TICK_RATE / arg;
kd_mksound(arg, 0);
@@ -417,6 +420,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
*/
ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
count = ticks ? (arg & 0xffff) : 0;
+ /* FIXME: This is an old broken API but we need to keep it
+ supported and somehow separate the historic advertised
+ tick rate from any real one */
if (count)
count = CLOCK_TICK_RATE / count;
kd_mksound(count, ticks);
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 1efb2879a94f..eef216f7f61d 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -3,3 +3,5 @@ obj-$(CONFIG_X86_CYCLONE_TIMER) += cyclone.o
obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o
obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o
obj-$(CONFIG_SH_TIMER_CMT) += sh_cmt.o
+obj-$(CONFIG_SH_TIMER_MTU2) += sh_mtu2.o
+obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c
index ee19b6e8fcb4..40bd8c61c7d7 100644
--- a/drivers/clocksource/acpi_pm.c
+++ b/drivers/clocksource/acpi_pm.c
@@ -57,7 +57,7 @@ u32 acpi_pm_read_verified(void)
return v2;
}
-static cycle_t acpi_pm_read(void)
+static cycle_t acpi_pm_read(struct clocksource *cs)
{
return (cycle_t)read_pmtmr();
}
@@ -83,7 +83,7 @@ static int __init acpi_pm_good_setup(char *__str)
}
__setup("acpi_pm_good", acpi_pm_good_setup);
-static cycle_t acpi_pm_read_slow(void)
+static cycle_t acpi_pm_read_slow(struct clocksource *cs)
{
return (cycle_t)acpi_pm_read_verified();
}
@@ -156,9 +156,9 @@ static int verify_pmtmr_rate(void)
unsigned long count, delta;
mach_prepare_counter();
- value1 = clocksource_acpi_pm.read();
+ value1 = clocksource_acpi_pm.read(&clocksource_acpi_pm);
mach_countup(&count);
- value2 = clocksource_acpi_pm.read();
+ value2 = clocksource_acpi_pm.read(&clocksource_acpi_pm);
delta = (value2 - value1) & ACPI_PM_MASK;
/* Check that the PMTMR delta is within 5% of what we expect */
@@ -195,9 +195,9 @@ static int __init init_acpi_pm_clocksource(void)
/* "verify" this timing source: */
for (j = 0; j < ACPI_PM_MONOTONICITY_CHECKS; j++) {
udelay(100 * j);
- value1 = clocksource_acpi_pm.read();
+ value1 = clocksource_acpi_pm.read(&clocksource_acpi_pm);
for (i = 0; i < ACPI_PM_READ_CHECKS; i++) {
- value2 = clocksource_acpi_pm.read();
+ value2 = clocksource_acpi_pm.read(&clocksource_acpi_pm);
if (value2 == value1)
continue;
if (value2 > value1)
diff --git a/drivers/clocksource/cyclone.c b/drivers/clocksource/cyclone.c
index 8615059a8729..64e528e8bfa6 100644
--- a/drivers/clocksource/cyclone.c
+++ b/drivers/clocksource/cyclone.c
@@ -19,7 +19,7 @@
int use_cyclone = 0;
static void __iomem *cyclone_ptr;
-static cycle_t read_cyclone(void)
+static cycle_t read_cyclone(struct clocksource *cs)
{
return (cycle_t)readl(cyclone_ptr);
}
diff --git a/drivers/clocksource/scx200_hrt.c b/drivers/clocksource/scx200_hrt.c
index b92da677aa5d..27f4d9637b62 100644
--- a/drivers/clocksource/scx200_hrt.c
+++ b/drivers/clocksource/scx200_hrt.c
@@ -43,7 +43,7 @@ MODULE_PARM_DESC(ppm, "+-adjust to actual XO freq (ppm)");
/* The base timer frequency, * 27 if selected */
#define HRT_FREQ 1000000
-static cycle_t read_hrt(void)
+static cycle_t read_hrt(struct clocksource *cs)
{
/* Read the timer value */
return (cycle_t) inl(scx200_cb_base + SCx200_TIMER_OFFSET);
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 1c92c39a53aa..cf56a2af5fe1 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -18,7 +18,6 @@
*/
#include <linux/init.h>
-#include <linux/bootmem.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
@@ -29,7 +28,7 @@
#include <linux/err.h>
#include <linux/clocksource.h>
#include <linux/clockchips.h>
-#include <linux/sh_cmt.h>
+#include <linux/sh_timer.h>
struct sh_cmt_priv {
void __iomem *mapbase;
@@ -47,6 +46,7 @@ struct sh_cmt_priv {
unsigned long rate;
spinlock_t lock;
struct clock_event_device ced;
+ struct clocksource cs;
unsigned long total_cycles;
};
@@ -59,7 +59,7 @@ static DEFINE_SPINLOCK(sh_cmt_lock);
static inline unsigned long sh_cmt_read(struct sh_cmt_priv *p, int reg_nr)
{
- struct sh_cmt_config *cfg = p->pdev->dev.platform_data;
+ struct sh_timer_config *cfg = p->pdev->dev.platform_data;
void __iomem *base = p->mapbase;
unsigned long offs;
@@ -83,7 +83,7 @@ static inline unsigned long sh_cmt_read(struct sh_cmt_priv *p, int reg_nr)
static inline void sh_cmt_write(struct sh_cmt_priv *p, int reg_nr,
unsigned long value)
{
- struct sh_cmt_config *cfg = p->pdev->dev.platform_data;
+ struct sh_timer_config *cfg = p->pdev->dev.platform_data;
void __iomem *base = p->mapbase;
unsigned long offs;
@@ -110,23 +110,28 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p,
int *has_wrapped)
{
unsigned long v1, v2, v3;
+ int o1, o2;
+
+ o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
/* Make sure the timer value is stable. Stolen from acpi_pm.c */
do {
+ o2 = o1;
v1 = sh_cmt_read(p, CMCNT);
v2 = sh_cmt_read(p, CMCNT);
v3 = sh_cmt_read(p, CMCNT);
- } while (unlikely((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1)
- || (v3 > v1 && v3 < v2)));
+ o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
+ } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
+ || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
- *has_wrapped = sh_cmt_read(p, CMCSR) & p->overflow_bit;
+ *has_wrapped = o1;
return v2;
}
static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
{
- struct sh_cmt_config *cfg = p->pdev->dev.platform_data;
+ struct sh_timer_config *cfg = p->pdev->dev.platform_data;
unsigned long flags, value;
/* start stop register shared by multiple timer channels */
@@ -144,7 +149,7 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)
{
- struct sh_cmt_config *cfg = p->pdev->dev.platform_data;
+ struct sh_timer_config *cfg = p->pdev->dev.platform_data;
int ret;
/* enable clock */
@@ -153,16 +158,18 @@ static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)
pr_err("sh_cmt: cannot enable clock \"%s\"\n", cfg->clk);
return ret;
}
- *rate = clk_get_rate(p->clk) / 8;
/* make sure channel is disabled */
sh_cmt_start_stop_ch(p, 0);
/* configure channel, periodic mode and maximum timeout */
- if (p->width == 16)
- sh_cmt_write(p, CMCSR, 0);
- else
+ if (p->width == 16) {
+ *rate = clk_get_rate(p->clk) / 512;
+ sh_cmt_write(p, CMCSR, 0x43);
+ } else {
+ *rate = clk_get_rate(p->clk) / 8;
sh_cmt_write(p, CMCSR, 0x01a4);
+ }
sh_cmt_write(p, CMCOR, 0xffffffff);
sh_cmt_write(p, CMCNT, 0);
@@ -376,6 +383,68 @@ static void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag)
spin_unlock_irqrestore(&p->lock, flags);
}
+static struct sh_cmt_priv *cs_to_sh_cmt(struct clocksource *cs)
+{
+ return container_of(cs, struct sh_cmt_priv, cs);
+}
+
+static cycle_t sh_cmt_clocksource_read(struct clocksource *cs)
+{
+ struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
+ unsigned long flags, raw;
+ unsigned long value;
+ int has_wrapped;
+
+ spin_lock_irqsave(&p->lock, flags);
+ value = p->total_cycles;
+ raw = sh_cmt_get_counter(p, &has_wrapped);
+
+ if (unlikely(has_wrapped))
+ raw += p->match_value;
+ spin_unlock_irqrestore(&p->lock, flags);
+
+ return value + raw;
+}
+
+static int sh_cmt_clocksource_enable(struct clocksource *cs)
+{
+ struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
+ int ret;
+
+ p->total_cycles = 0;
+
+ ret = sh_cmt_start(p, FLAG_CLOCKSOURCE);
+ if (ret)
+ return ret;
+
+ /* TODO: calculate good shift from rate and counter bit width */
+ cs->shift = 0;
+ cs->mult = clocksource_hz2mult(p->rate, cs->shift);
+ return 0;
+}
+
+static void sh_cmt_clocksource_disable(struct clocksource *cs)
+{
+ sh_cmt_stop(cs_to_sh_cmt(cs), FLAG_CLOCKSOURCE);
+}
+
+static int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
+ char *name, unsigned long rating)
+{
+ struct clocksource *cs = &p->cs;
+
+ cs->name = name;
+ cs->rating = rating;
+ cs->read = sh_cmt_clocksource_read;
+ cs->enable = sh_cmt_clocksource_enable;
+ cs->disable = sh_cmt_clocksource_disable;
+ cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
+ cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
+ pr_info("sh_cmt: %s used as clock source\n", cs->name);
+ clocksource_register(cs);
+ return 0;
+}
+
static struct sh_cmt_priv *ced_to_sh_cmt(struct clock_event_device *ced)
{
return container_of(ced, struct sh_cmt_priv, ced);
@@ -468,9 +537,9 @@ static void sh_cmt_register_clockevent(struct sh_cmt_priv *p,
clockevents_register_device(ced);
}
-int sh_cmt_register(struct sh_cmt_priv *p, char *name,
- unsigned long clockevent_rating,
- unsigned long clocksource_rating)
+static int sh_cmt_register(struct sh_cmt_priv *p, char *name,
+ unsigned long clockevent_rating,
+ unsigned long clocksource_rating)
{
if (p->width == (sizeof(p->max_match_value) * 8))
p->max_match_value = ~0;
@@ -483,12 +552,15 @@ int sh_cmt_register(struct sh_cmt_priv *p, char *name,
if (clockevent_rating)
sh_cmt_register_clockevent(p, name, clockevent_rating);
+ if (clocksource_rating)
+ sh_cmt_register_clocksource(p, name, clocksource_rating);
+
return 0;
}
static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
{
- struct sh_cmt_config *cfg = pdev->dev.platform_data;
+ struct sh_timer_config *cfg = pdev->dev.platform_data;
struct resource *res;
int irq, ret;
ret = -ENXIO;
@@ -545,7 +617,7 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
if (resource_size(res) == 6) {
p->width = 16;
p->overflow_bit = 0x80;
- p->clear_bits = ~0xc0;
+ p->clear_bits = ~0x80;
} else {
p->width = 32;
p->overflow_bit = 0x8000;
@@ -566,8 +638,14 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
static int __devinit sh_cmt_probe(struct platform_device *pdev)
{
struct sh_cmt_priv *p = platform_get_drvdata(pdev);
+ struct sh_timer_config *cfg = pdev->dev.platform_data;
int ret;
+ if (p) {
+ pr_info("sh_cmt: %s kept as earlytimer\n", cfg->name);
+ return 0;
+ }
+
p = kmalloc(sizeof(*p), GFP_KERNEL);
if (p == NULL) {
dev_err(&pdev->dev, "failed to allocate driver data\n");
@@ -577,7 +655,6 @@ static int __devinit sh_cmt_probe(struct platform_device *pdev)
ret = sh_cmt_setup(p, pdev);
if (ret) {
kfree(p);
-
platform_set_drvdata(pdev, NULL);
}
return ret;
@@ -606,6 +683,7 @@ static void __exit sh_cmt_exit(void)
platform_driver_unregister(&sh_cmt_device_driver);
}
+early_platform_init("earlytimer", &sh_cmt_device_driver);
module_init(sh_cmt_init);
module_exit(sh_cmt_exit);
diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
new file mode 100644
index 000000000000..d1ae75454d10
--- /dev/null
+++ b/drivers/clocksource/sh_mtu2.c
@@ -0,0 +1,357 @@
+/*
+ * SuperH Timer Support - MTU2
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * 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
+ *
+ * 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/init.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/clockchips.h>
+#include <linux/sh_timer.h>
+
+struct sh_mtu2_priv {
+ void __iomem *mapbase;
+ struct clk *clk;
+ struct irqaction irqaction;
+ struct platform_device *pdev;
+ unsigned long rate;
+ unsigned long periodic;
+ struct clock_event_device ced;
+};
+
+static DEFINE_SPINLOCK(sh_mtu2_lock);
+
+#define TSTR -1 /* shared register */
+#define TCR 0 /* channel register */
+#define TMDR 1 /* channel register */
+#define TIOR 2 /* channel register */
+#define TIER 3 /* channel register */
+#define TSR 4 /* channel register */
+#define TCNT 5 /* channel register */
+#define TGR 6 /* channel register */
+
+static unsigned long mtu2_reg_offs[] = {
+ [TCR] = 0,
+ [TMDR] = 1,
+ [TIOR] = 2,
+ [TIER] = 4,
+ [TSR] = 5,
+ [TCNT] = 6,
+ [TGR] = 8,
+};
+
+static inline unsigned long sh_mtu2_read(struct sh_mtu2_priv *p, int reg_nr)
+{
+ struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+ void __iomem *base = p->mapbase;
+ unsigned long offs;
+
+ if (reg_nr == TSTR)
+ return ioread8(base + cfg->channel_offset);
+
+ offs = mtu2_reg_offs[reg_nr];
+
+ if ((reg_nr == TCNT) || (reg_nr == TGR))
+ return ioread16(base + offs);
+ else
+ return ioread8(base + offs);
+}
+
+static inline void sh_mtu2_write(struct sh_mtu2_priv *p, int reg_nr,
+ unsigned long value)
+{
+ struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+ void __iomem *base = p->mapbase;
+ unsigned long offs;
+
+ if (reg_nr == TSTR) {
+ iowrite8(value, base + cfg->channel_offset);
+ return;
+ }
+
+ offs = mtu2_reg_offs[reg_nr];
+
+ if ((reg_nr == TCNT) || (reg_nr == TGR))
+ iowrite16(value, base + offs);
+ else
+ iowrite8(value, base + offs);
+}
+
+static void sh_mtu2_start_stop_ch(struct sh_mtu2_priv *p, int start)
+{
+ struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+ unsigned long flags, value;
+
+ /* start stop register shared by multiple timer channels */
+ spin_lock_irqsave(&sh_mtu2_lock, flags);
+ value = sh_mtu2_read(p, TSTR);
+
+ if (start)
+ value |= 1 << cfg->timer_bit;
+ else
+ value &= ~(1 << cfg->timer_bit);
+
+ sh_mtu2_write(p, TSTR, value);
+ spin_unlock_irqrestore(&sh_mtu2_lock, flags);
+}
+
+static int sh_mtu2_enable(struct sh_mtu2_priv *p)
+{
+ struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+ int ret;
+
+ /* enable clock */
+ ret = clk_enable(p->clk);
+ if (ret) {
+ pr_err("sh_mtu2: cannot enable clock \"%s\"\n", cfg->clk);
+ return ret;
+ }
+
+ /* make sure channel is disabled */
+ sh_mtu2_start_stop_ch(p, 0);
+
+ p->rate = clk_get_rate(p->clk) / 64;
+ p->periodic = (p->rate + HZ/2) / HZ;
+
+ /* "Periodic Counter Operation" */
+ sh_mtu2_write(p, TCR, 0x23); /* TGRA clear, divide clock by 64 */
+ sh_mtu2_write(p, TIOR, 0);
+ sh_mtu2_write(p, TGR, p->periodic);
+ sh_mtu2_write(p, TCNT, 0);
+ sh_mtu2_write(p, TMDR, 0);
+ sh_mtu2_write(p, TIER, 0x01);
+
+ /* enable channel */
+ sh_mtu2_start_stop_ch(p, 1);
+
+ return 0;
+}
+
+static void sh_mtu2_disable(struct sh_mtu2_priv *p)
+{
+ /* disable channel */
+ sh_mtu2_start_stop_ch(p, 0);
+
+ /* stop clock */
+ clk_disable(p->clk);
+}
+
+static irqreturn_t sh_mtu2_interrupt(int irq, void *dev_id)
+{
+ struct sh_mtu2_priv *p = dev_id;
+
+ /* acknowledge interrupt */
+ sh_mtu2_read(p, TSR);
+ sh_mtu2_write(p, TSR, 0xfe);
+
+ /* notify clockevent layer */
+ p->ced.event_handler(&p->ced);
+ return IRQ_HANDLED;
+}
+
+static struct sh_mtu2_priv *ced_to_sh_mtu2(struct clock_event_device *ced)
+{
+ return container_of(ced, struct sh_mtu2_priv, ced);
+}
+
+static void sh_mtu2_clock_event_mode(enum clock_event_mode mode,
+ struct clock_event_device *ced)
+{
+ struct sh_mtu2_priv *p = ced_to_sh_mtu2(ced);
+ int disabled = 0;
+
+ /* deal with old setting first */
+ switch (ced->mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ sh_mtu2_disable(p);
+ disabled = 1;
+ break;
+ default:
+ break;
+ }
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ pr_info("sh_mtu2: %s used for periodic clock events\n",
+ ced->name);
+ sh_mtu2_enable(p);
+ break;
+ case CLOCK_EVT_MODE_UNUSED:
+ if (!disabled)
+ sh_mtu2_disable(p);
+ break;
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ default:
+ break;
+ }
+}
+
+static void sh_mtu2_register_clockevent(struct sh_mtu2_priv *p,
+ char *name, unsigned long rating)
+{
+ struct clock_event_device *ced = &p->ced;
+ int ret;
+
+ memset(ced, 0, sizeof(*ced));
+
+ ced->name = name;
+ ced->features = CLOCK_EVT_FEAT_PERIODIC;
+ ced->rating = rating;
+ ced->cpumask = cpumask_of(0);
+ ced->set_mode = sh_mtu2_clock_event_mode;
+
+ ret = setup_irq(p->irqaction.irq, &p->irqaction);
+ if (ret) {
+ pr_err("sh_mtu2: failed to request irq %d\n",
+ p->irqaction.irq);
+ return;
+ }
+
+ pr_info("sh_mtu2: %s used for clock events\n", ced->name);
+ clockevents_register_device(ced);
+}
+
+static int sh_mtu2_register(struct sh_mtu2_priv *p, char *name,
+ unsigned long clockevent_rating)
+{
+ if (clockevent_rating)
+ sh_mtu2_register_clockevent(p, name, clockevent_rating);
+
+ return 0;
+}
+
+static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev)
+{
+ struct sh_timer_config *cfg = pdev->dev.platform_data;
+ struct resource *res;
+ int irq, ret;
+ ret = -ENXIO;
+
+ memset(p, 0, sizeof(*p));
+ p->pdev = pdev;
+
+ if (!cfg) {
+ dev_err(&p->pdev->dev, "missing platform data\n");
+ goto err0;
+ }
+
+ platform_set_drvdata(pdev, p);
+
+ res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&p->pdev->dev, "failed to get I/O memory\n");
+ goto err0;
+ }
+
+ irq = platform_get_irq(p->pdev, 0);
+ if (irq < 0) {
+ dev_err(&p->pdev->dev, "failed to get irq\n");
+ goto err0;
+ }
+
+ /* map memory, let mapbase point to our channel */
+ p->mapbase = ioremap_nocache(res->start, resource_size(res));
+ if (p->mapbase == NULL) {
+ pr_err("sh_mtu2: failed to remap I/O memory\n");
+ goto err0;
+ }
+
+ /* setup data for setup_irq() (too early for request_irq()) */
+ p->irqaction.name = cfg->name;
+ p->irqaction.handler = sh_mtu2_interrupt;
+ p->irqaction.dev_id = p;
+ p->irqaction.irq = irq;
+ p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL;
+ p->irqaction.mask = CPU_MASK_NONE;
+
+ /* get hold of clock */
+ p->clk = clk_get(&p->pdev->dev, cfg->clk);
+ if (IS_ERR(p->clk)) {
+ pr_err("sh_mtu2: cannot get clock \"%s\"\n", cfg->clk);
+ ret = PTR_ERR(p->clk);
+ goto err1;
+ }
+
+ return sh_mtu2_register(p, cfg->name, cfg->clockevent_rating);
+ err1:
+ iounmap(p->mapbase);
+ err0:
+ return ret;
+}
+
+static int __devinit sh_mtu2_probe(struct platform_device *pdev)
+{
+ struct sh_mtu2_priv *p = platform_get_drvdata(pdev);
+ struct sh_timer_config *cfg = pdev->dev.platform_data;
+ int ret;
+
+ if (p) {
+ pr_info("sh_mtu2: %s kept as earlytimer\n", cfg->name);
+ return 0;
+ }
+
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (p == NULL) {
+ dev_err(&pdev->dev, "failed to allocate driver data\n");
+ return -ENOMEM;
+ }
+
+ ret = sh_mtu2_setup(p, pdev);
+ if (ret) {
+ kfree(p);
+ platform_set_drvdata(pdev, NULL);
+ }
+ return ret;
+}
+
+static int __devexit sh_mtu2_remove(struct platform_device *pdev)
+{
+ return -EBUSY; /* cannot unregister clockevent */
+}
+
+static struct platform_driver sh_mtu2_device_driver = {
+ .probe = sh_mtu2_probe,
+ .remove = __devexit_p(sh_mtu2_remove),
+ .driver = {
+ .name = "sh_mtu2",
+ }
+};
+
+static int __init sh_mtu2_init(void)
+{
+ return platform_driver_register(&sh_mtu2_device_driver);
+}
+
+static void __exit sh_mtu2_exit(void)
+{
+ platform_driver_unregister(&sh_mtu2_device_driver);
+}
+
+early_platform_init("earlytimer", &sh_mtu2_device_driver);
+module_init(sh_mtu2_init);
+module_exit(sh_mtu2_exit);
+
+MODULE_AUTHOR("Magnus Damm");
+MODULE_DESCRIPTION("SuperH MTU2 Timer Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
new file mode 100644
index 000000000000..d6ea4398bf62
--- /dev/null
+++ b/drivers/clocksource/sh_tmu.c
@@ -0,0 +1,461 @@
+/*
+ * SuperH Timer Support - TMU
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * 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
+ *
+ * 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/init.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/sh_timer.h>
+
+struct sh_tmu_priv {
+ void __iomem *mapbase;
+ struct clk *clk;
+ struct irqaction irqaction;
+ struct platform_device *pdev;
+ unsigned long rate;
+ unsigned long periodic;
+ struct clock_event_device ced;
+ struct clocksource cs;
+};
+
+static DEFINE_SPINLOCK(sh_tmu_lock);
+
+#define TSTR -1 /* shared register */
+#define TCOR 0 /* channel register */
+#define TCNT 1 /* channel register */
+#define TCR 2 /* channel register */
+
+static inline unsigned long sh_tmu_read(struct sh_tmu_priv *p, int reg_nr)
+{
+ struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+ void __iomem *base = p->mapbase;
+ unsigned long offs;
+
+ if (reg_nr == TSTR)
+ return ioread8(base - cfg->channel_offset);
+
+ offs = reg_nr << 2;
+
+ if (reg_nr == TCR)
+ return ioread16(base + offs);
+ else
+ return ioread32(base + offs);
+}
+
+static inline void sh_tmu_write(struct sh_tmu_priv *p, int reg_nr,
+ unsigned long value)
+{
+ struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+ void __iomem *base = p->mapbase;
+ unsigned long offs;
+
+ if (reg_nr == TSTR) {
+ iowrite8(value, base - cfg->channel_offset);
+ return;
+ }
+
+ offs = reg_nr << 2;
+
+ if (reg_nr == TCR)
+ iowrite16(value, base + offs);
+ else
+ iowrite32(value, base + offs);
+}
+
+static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start)
+{
+ struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+ unsigned long flags, value;
+
+ /* start stop register shared by multiple timer channels */
+ spin_lock_irqsave(&sh_tmu_lock, flags);
+ value = sh_tmu_read(p, TSTR);
+
+ if (start)
+ value |= 1 << cfg->timer_bit;
+ else
+ value &= ~(1 << cfg->timer_bit);
+
+ sh_tmu_write(p, TSTR, value);
+ spin_unlock_irqrestore(&sh_tmu_lock, flags);
+}
+
+static int sh_tmu_enable(struct sh_tmu_priv *p)
+{
+ struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+ int ret;
+
+ /* enable clock */
+ ret = clk_enable(p->clk);
+ if (ret) {
+ pr_err("sh_tmu: cannot enable clock \"%s\"\n", cfg->clk);
+ return ret;
+ }
+
+ /* make sure channel is disabled */
+ sh_tmu_start_stop_ch(p, 0);
+
+ /* maximum timeout */
+ sh_tmu_write(p, TCOR, 0xffffffff);
+ sh_tmu_write(p, TCNT, 0xffffffff);
+
+ /* configure channel to parent clock / 4, irq off */
+ p->rate = clk_get_rate(p->clk) / 4;
+ sh_tmu_write(p, TCR, 0x0000);
+
+ /* enable channel */
+ sh_tmu_start_stop_ch(p, 1);
+
+ return 0;
+}
+
+static void sh_tmu_disable(struct sh_tmu_priv *p)
+{
+ /* disable channel */
+ sh_tmu_start_stop_ch(p, 0);
+
+ /* stop clock */
+ clk_disable(p->clk);
+}
+
+static void sh_tmu_set_next(struct sh_tmu_priv *p, unsigned long delta,
+ int periodic)
+{
+ /* stop timer */
+ sh_tmu_start_stop_ch(p, 0);
+
+ /* acknowledge interrupt */
+ sh_tmu_read(p, TCR);
+
+ /* enable interrupt */
+ sh_tmu_write(p, TCR, 0x0020);
+
+ /* reload delta value in case of periodic timer */
+ if (periodic)
+ sh_tmu_write(p, TCOR, delta);
+ else
+ sh_tmu_write(p, TCOR, 0);
+
+ sh_tmu_write(p, TCNT, delta);
+
+ /* start timer */
+ sh_tmu_start_stop_ch(p, 1);
+}
+
+static irqreturn_t sh_tmu_interrupt(int irq, void *dev_id)
+{
+ struct sh_tmu_priv *p = dev_id;
+
+ /* disable or acknowledge interrupt */
+ if (p->ced.mode == CLOCK_EVT_MODE_ONESHOT)
+ sh_tmu_write(p, TCR, 0x0000);
+ else
+ sh_tmu_write(p, TCR, 0x0020);
+
+ /* notify clockevent layer */
+ p->ced.event_handler(&p->ced);
+ return IRQ_HANDLED;
+}
+
+static struct sh_tmu_priv *cs_to_sh_tmu(struct clocksource *cs)
+{
+ return container_of(cs, struct sh_tmu_priv, cs);
+}
+
+static cycle_t sh_tmu_clocksource_read(struct clocksource *cs)
+{
+ struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
+
+ return sh_tmu_read(p, TCNT) ^ 0xffffffff;
+}
+
+static int sh_tmu_clocksource_enable(struct clocksource *cs)
+{
+ struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
+ int ret;
+
+ ret = sh_tmu_enable(p);
+ if (ret)
+ return ret;
+
+ /* TODO: calculate good shift from rate and counter bit width */
+ cs->shift = 10;
+ cs->mult = clocksource_hz2mult(p->rate, cs->shift);
+ return 0;
+}
+
+static void sh_tmu_clocksource_disable(struct clocksource *cs)
+{
+ sh_tmu_disable(cs_to_sh_tmu(cs));
+}
+
+static int sh_tmu_register_clocksource(struct sh_tmu_priv *p,
+ char *name, unsigned long rating)
+{
+ struct clocksource *cs = &p->cs;
+
+ cs->name = name;
+ cs->rating = rating;
+ cs->read = sh_tmu_clocksource_read;
+ cs->enable = sh_tmu_clocksource_enable;
+ cs->disable = sh_tmu_clocksource_disable;
+ cs->mask = CLOCKSOURCE_MASK(32);
+ cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
+ pr_info("sh_tmu: %s used as clock source\n", cs->name);
+ clocksource_register(cs);
+ return 0;
+}
+
+static struct sh_tmu_priv *ced_to_sh_tmu(struct clock_event_device *ced)
+{
+ return container_of(ced, struct sh_tmu_priv, ced);
+}
+
+static void sh_tmu_clock_event_start(struct sh_tmu_priv *p, int periodic)
+{
+ struct clock_event_device *ced = &p->ced;
+
+ sh_tmu_enable(p);
+
+ /* TODO: calculate good shift from rate and counter bit width */
+
+ ced->shift = 32;
+ ced->mult = div_sc(p->rate, NSEC_PER_SEC, ced->shift);
+ ced->max_delta_ns = clockevent_delta2ns(0xffffffff, ced);
+ ced->min_delta_ns = 5000;
+
+ if (periodic) {
+ p->periodic = (p->rate + HZ/2) / HZ;
+ sh_tmu_set_next(p, p->periodic, 1);
+ }
+}
+
+static void sh_tmu_clock_event_mode(enum clock_event_mode mode,
+ struct clock_event_device *ced)
+{
+ struct sh_tmu_priv *p = ced_to_sh_tmu(ced);
+ int disabled = 0;
+
+ /* deal with old setting first */
+ switch (ced->mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ case CLOCK_EVT_MODE_ONESHOT:
+ sh_tmu_disable(p);
+ disabled = 1;
+ break;
+ default:
+ break;
+ }
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ pr_info("sh_tmu: %s used for periodic clock events\n",
+ ced->name);
+ sh_tmu_clock_event_start(p, 1);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ pr_info("sh_tmu: %s used for oneshot clock events\n",
+ ced->name);
+ sh_tmu_clock_event_start(p, 0);
+ break;
+ case CLOCK_EVT_MODE_UNUSED:
+ if (!disabled)
+ sh_tmu_disable(p);
+ break;
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ default:
+ break;
+ }
+}
+
+static int sh_tmu_clock_event_next(unsigned long delta,
+ struct clock_event_device *ced)
+{
+ struct sh_tmu_priv *p = ced_to_sh_tmu(ced);
+
+ BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT);
+
+ /* program new delta value */
+ sh_tmu_set_next(p, delta, 0);
+ return 0;
+}
+
+static void sh_tmu_register_clockevent(struct sh_tmu_priv *p,
+ char *name, unsigned long rating)
+{
+ struct clock_event_device *ced = &p->ced;
+ int ret;
+
+ memset(ced, 0, sizeof(*ced));
+
+ ced->name = name;
+ ced->features = CLOCK_EVT_FEAT_PERIODIC;
+ ced->features |= CLOCK_EVT_FEAT_ONESHOT;
+ ced->rating = rating;
+ ced->cpumask = cpumask_of(0);
+ ced->set_next_event = sh_tmu_clock_event_next;
+ ced->set_mode = sh_tmu_clock_event_mode;
+
+ ret = setup_irq(p->irqaction.irq, &p->irqaction);
+ if (ret) {
+ pr_err("sh_tmu: failed to request irq %d\n",
+ p->irqaction.irq);
+ return;
+ }
+
+ pr_info("sh_tmu: %s used for clock events\n", ced->name);
+ clockevents_register_device(ced);
+}
+
+static int sh_tmu_register(struct sh_tmu_priv *p, char *name,
+ unsigned long clockevent_rating,
+ unsigned long clocksource_rating)
+{
+ if (clockevent_rating)
+ sh_tmu_register_clockevent(p, name, clockevent_rating);
+ else if (clocksource_rating)
+ sh_tmu_register_clocksource(p, name, clocksource_rating);
+
+ return 0;
+}
+
+static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
+{
+ struct sh_timer_config *cfg = pdev->dev.platform_data;
+ struct resource *res;
+ int irq, ret;
+ ret = -ENXIO;
+
+ memset(p, 0, sizeof(*p));
+ p->pdev = pdev;
+
+ if (!cfg) {
+ dev_err(&p->pdev->dev, "missing platform data\n");
+ goto err0;
+ }
+
+ platform_set_drvdata(pdev, p);
+
+ res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&p->pdev->dev, "failed to get I/O memory\n");
+ goto err0;
+ }
+
+ irq = platform_get_irq(p->pdev, 0);
+ if (irq < 0) {
+ dev_err(&p->pdev->dev, "failed to get irq\n");
+ goto err0;
+ }
+
+ /* map memory, let mapbase point to our channel */
+ p->mapbase = ioremap_nocache(res->start, resource_size(res));
+ if (p->mapbase == NULL) {
+ pr_err("sh_tmu: failed to remap I/O memory\n");
+ goto err0;
+ }
+
+ /* setup data for setup_irq() (too early for request_irq()) */
+ p->irqaction.name = cfg->name;
+ p->irqaction.handler = sh_tmu_interrupt;
+ p->irqaction.dev_id = p;
+ p->irqaction.irq = irq;
+ p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL;
+ p->irqaction.mask = CPU_MASK_NONE;
+
+ /* get hold of clock */
+ p->clk = clk_get(&p->pdev->dev, cfg->clk);
+ if (IS_ERR(p->clk)) {
+ pr_err("sh_tmu: cannot get clock \"%s\"\n", cfg->clk);
+ ret = PTR_ERR(p->clk);
+ goto err1;
+ }
+
+ return sh_tmu_register(p, cfg->name,
+ cfg->clockevent_rating,
+ cfg->clocksource_rating);
+ err1:
+ iounmap(p->mapbase);
+ err0:
+ return ret;
+}
+
+static int __devinit sh_tmu_probe(struct platform_device *pdev)
+{
+ struct sh_tmu_priv *p = platform_get_drvdata(pdev);
+ struct sh_timer_config *cfg = pdev->dev.platform_data;
+ int ret;
+
+ if (p) {
+ pr_info("sh_tmu: %s kept as earlytimer\n", cfg->name);
+ return 0;
+ }
+
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (p == NULL) {
+ dev_err(&pdev->dev, "failed to allocate driver data\n");
+ return -ENOMEM;
+ }
+
+ ret = sh_tmu_setup(p, pdev);
+ if (ret) {
+ kfree(p);
+ platform_set_drvdata(pdev, NULL);
+ }
+ return ret;
+}
+
+static int __devexit sh_tmu_remove(struct platform_device *pdev)
+{
+ return -EBUSY; /* cannot unregister clockevent and clocksource */
+}
+
+static struct platform_driver sh_tmu_device_driver = {
+ .probe = sh_tmu_probe,
+ .remove = __devexit_p(sh_tmu_remove),
+ .driver = {
+ .name = "sh_tmu",
+ }
+};
+
+static int __init sh_tmu_init(void)
+{
+ return platform_driver_register(&sh_tmu_device_driver);
+}
+
+static void __exit sh_tmu_exit(void)
+{
+ platform_driver_unregister(&sh_tmu_device_driver);
+}
+
+early_platform_init("earlytimer", &sh_tmu_device_driver);
+module_init(sh_tmu_init);
+module_exit(sh_tmu_exit);
+
+MODULE_AUTHOR("Magnus Damm");
+MODULE_DESCRIPTION("SuperH TMU Timer Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c
index 254f1064d973..01b886e68822 100644
--- a/drivers/clocksource/tcb_clksrc.c
+++ b/drivers/clocksource/tcb_clksrc.c
@@ -39,7 +39,7 @@
static void __iomem *tcaddr;
-static cycle_t tc_get_cycles(void)
+static cycle_t tc_get_cycles(struct clocksource *cs)
{
unsigned long flags;
u32 lower, upper;
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 01afd758072f..e748e55bd86b 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -12,7 +12,7 @@ if CRYPTO_HW
config CRYPTO_DEV_PADLOCK
tristate "Support for VIA PadLock ACE"
- depends on X86_32 && !UML
+ depends on X86 && !UML
select CRYPTO_ALGAPI
help
Some VIA processors come with an integrated crypto engine
diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c
index f9f05d7a707d..6c6656d3b1e2 100644
--- a/drivers/crypto/ixp4xx_crypto.c
+++ b/drivers/crypto/ixp4xx_crypto.c
@@ -415,6 +415,7 @@ static void crypto_done_action(unsigned long arg)
static int init_ixp_crypto(void)
{
int ret = -ENODEV;
+ u32 msg[2] = { 0, 0 };
if (! ( ~(*IXP4XX_EXP_CFG2) & (IXP4XX_FEATURE_HASH |
IXP4XX_FEATURE_AES | IXP4XX_FEATURE_DES))) {
@@ -426,9 +427,35 @@ static int init_ixp_crypto(void)
return ret;
if (!npe_running(npe_c)) {
- npe_load_firmware(npe_c, npe_name(npe_c), dev);
+ ret = npe_load_firmware(npe_c, npe_name(npe_c), dev);
+ if (ret) {
+ return ret;
+ }
+ if (npe_recv_message(npe_c, msg, "STATUS_MSG"))
+ goto npe_error;
+ } else {
+ if (npe_send_message(npe_c, msg, "STATUS_MSG"))
+ goto npe_error;
+
+ if (npe_recv_message(npe_c, msg, "STATUS_MSG"))
+ goto npe_error;
}
+ switch ((msg[1]>>16) & 0xff) {
+ case 3:
+ printk(KERN_WARNING "Firmware of %s lacks AES support\n",
+ npe_name(npe_c));
+ support_aes = 0;
+ break;
+ case 4:
+ case 5:
+ support_aes = 1;
+ break;
+ default:
+ printk(KERN_ERR "Firmware of %s lacks crypto support\n",
+ npe_name(npe_c));
+ return -ENODEV;
+ }
/* buffer_pool will also be used to sometimes store the hmac,
* so assure it is large enough
*/
@@ -459,6 +486,10 @@ static int init_ixp_crypto(void)
qmgr_enable_irq(RECV_QID);
return 0;
+
+npe_error:
+ printk(KERN_ERR "%s not responding\n", npe_name(npe_c));
+ ret = -EIO;
err:
if (ctx_pool)
dma_pool_destroy(ctx_pool);
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
index 3f0fdd18255d..87f92c39b5f0 100644
--- a/drivers/crypto/padlock-aes.c
+++ b/drivers/crypto/padlock-aes.c
@@ -154,7 +154,11 @@ static inline void padlock_reset_key(struct cword *cword)
int cpu = raw_smp_processor_id();
if (cword != per_cpu(last_cword, cpu))
+#ifndef CONFIG_X86_64
asm volatile ("pushfl; popfl");
+#else
+ asm volatile ("pushfq; popfq");
+#endif
}
static inline void padlock_store_cword(struct cword *cword)
@@ -208,10 +212,19 @@ static inline void padlock_xcrypt_ecb(const u8 *input, u8 *output, void *key,
asm volatile ("test $1, %%cl;"
"je 1f;"
+#ifndef CONFIG_X86_64
"lea -1(%%ecx), %%eax;"
"mov $1, %%ecx;"
+#else
+ "lea -1(%%rcx), %%rax;"
+ "mov $1, %%rcx;"
+#endif
".byte 0xf3,0x0f,0xa7,0xc8;" /* rep xcryptecb */
+#ifndef CONFIG_X86_64
"mov %%eax, %%ecx;"
+#else
+ "mov %%rax, %%rcx;"
+#endif
"1:"
".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */
: "+S"(input), "+D"(output)
@@ -489,4 +502,4 @@ MODULE_DESCRIPTION("VIA PadLock AES algorithm support");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Michal Ludvig");
-MODULE_ALIAS("aes-all");
+MODULE_ALIAS("aes");
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index a3918c16b3db..c70775fd3ce2 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -44,6 +44,8 @@
#include <crypto/sha.h>
#include <crypto/aead.h>
#include <crypto/authenc.h>
+#include <crypto/skcipher.h>
+#include <crypto/scatterwalk.h>
#include "talitos.h"
@@ -339,7 +341,8 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
status = error;
dma_unmap_single(dev, request->dma_desc,
- sizeof(struct talitos_desc), DMA_BIDIRECTIONAL);
+ sizeof(struct talitos_desc),
+ DMA_BIDIRECTIONAL);
/* copy entries so we can call callback outside lock */
saved_req.desc = request->desc;
@@ -413,7 +416,8 @@ static struct talitos_desc *current_desc(struct device *dev, int ch)
/*
* user diagnostics; report root cause of error based on execution unit status
*/
-static void report_eu_error(struct device *dev, int ch, struct talitos_desc *desc)
+static void report_eu_error(struct device *dev, int ch,
+ struct talitos_desc *desc)
{
struct talitos_private *priv = dev_get_drvdata(dev);
int i;
@@ -684,8 +688,8 @@ struct talitos_ctx {
unsigned int authsize;
};
-static int aead_authenc_setauthsize(struct crypto_aead *authenc,
- unsigned int authsize)
+static int aead_setauthsize(struct crypto_aead *authenc,
+ unsigned int authsize)
{
struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
@@ -694,8 +698,8 @@ static int aead_authenc_setauthsize(struct crypto_aead *authenc,
return 0;
}
-static int aead_authenc_setkey(struct crypto_aead *authenc,
- const u8 *key, unsigned int keylen)
+static int aead_setkey(struct crypto_aead *authenc,
+ const u8 *key, unsigned int keylen)
{
struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
struct rtattr *rta = (void *)key;
@@ -740,7 +744,7 @@ badkey:
}
/*
- * ipsec_esp_edesc - s/w-extended ipsec_esp descriptor
+ * talitos_edesc - s/w-extended descriptor
* @src_nents: number of segments in input scatterlist
* @dst_nents: number of segments in output scatterlist
* @dma_len: length of dma mapped link_tbl space
@@ -752,17 +756,67 @@ badkey:
* is greater than 1, an integrity check value is concatenated to the end
* of link_tbl data
*/
-struct ipsec_esp_edesc {
+struct talitos_edesc {
int src_nents;
int dst_nents;
+ int src_is_chained;
+ int dst_is_chained;
int dma_len;
dma_addr_t dma_link_tbl;
struct talitos_desc desc;
struct talitos_ptr link_tbl[0];
};
+static int talitos_map_sg(struct device *dev, struct scatterlist *sg,
+ unsigned int nents, enum dma_data_direction dir,
+ int chained)
+{
+ if (unlikely(chained))
+ while (sg) {
+ dma_map_sg(dev, sg, 1, dir);
+ sg = scatterwalk_sg_next(sg);
+ }
+ else
+ dma_map_sg(dev, sg, nents, dir);
+ return nents;
+}
+
+static void talitos_unmap_sg_chain(struct device *dev, struct scatterlist *sg,
+ enum dma_data_direction dir)
+{
+ while (sg) {
+ dma_unmap_sg(dev, sg, 1, dir);
+ sg = scatterwalk_sg_next(sg);
+ }
+}
+
+static void talitos_sg_unmap(struct device *dev,
+ struct talitos_edesc *edesc,
+ struct scatterlist *src,
+ struct scatterlist *dst)
+{
+ unsigned int src_nents = edesc->src_nents ? : 1;
+ unsigned int dst_nents = edesc->dst_nents ? : 1;
+
+ if (src != dst) {
+ if (edesc->src_is_chained)
+ talitos_unmap_sg_chain(dev, src, DMA_TO_DEVICE);
+ else
+ dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
+
+ if (edesc->dst_is_chained)
+ talitos_unmap_sg_chain(dev, dst, DMA_FROM_DEVICE);
+ else
+ dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
+ } else
+ if (edesc->src_is_chained)
+ talitos_unmap_sg_chain(dev, src, DMA_BIDIRECTIONAL);
+ else
+ dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
+}
+
static void ipsec_esp_unmap(struct device *dev,
- struct ipsec_esp_edesc *edesc,
+ struct talitos_edesc *edesc,
struct aead_request *areq)
{
unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6], DMA_FROM_DEVICE);
@@ -772,15 +826,7 @@ static void ipsec_esp_unmap(struct device *dev,
dma_unmap_sg(dev, areq->assoc, 1, DMA_TO_DEVICE);
- if (areq->src != areq->dst) {
- dma_unmap_sg(dev, areq->src, edesc->src_nents ? : 1,
- DMA_TO_DEVICE);
- dma_unmap_sg(dev, areq->dst, edesc->dst_nents ? : 1,
- DMA_FROM_DEVICE);
- } else {
- dma_unmap_sg(dev, areq->src, edesc->src_nents ? : 1,
- DMA_BIDIRECTIONAL);
- }
+ talitos_sg_unmap(dev, edesc, areq->src, areq->dst);
if (edesc->dma_len)
dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
@@ -795,13 +841,14 @@ static void ipsec_esp_encrypt_done(struct device *dev,
int err)
{
struct aead_request *areq = context;
- struct ipsec_esp_edesc *edesc =
- container_of(desc, struct ipsec_esp_edesc, desc);
struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
+ struct talitos_edesc *edesc;
struct scatterlist *sg;
void *icvdata;
+ edesc = container_of(desc, struct talitos_edesc, desc);
+
ipsec_esp_unmap(dev, edesc, areq);
/* copy the generated ICV to dst */
@@ -819,17 +866,18 @@ static void ipsec_esp_encrypt_done(struct device *dev,
}
static void ipsec_esp_decrypt_swauth_done(struct device *dev,
- struct talitos_desc *desc, void *context,
- int err)
+ struct talitos_desc *desc,
+ void *context, int err)
{
struct aead_request *req = context;
- struct ipsec_esp_edesc *edesc =
- container_of(desc, struct ipsec_esp_edesc, desc);
struct crypto_aead *authenc = crypto_aead_reqtfm(req);
struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
+ struct talitos_edesc *edesc;
struct scatterlist *sg;
void *icvdata;
+ edesc = container_of(desc, struct talitos_edesc, desc);
+
ipsec_esp_unmap(dev, edesc, req);
if (!err) {
@@ -851,20 +899,20 @@ static void ipsec_esp_decrypt_swauth_done(struct device *dev,
}
static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
- struct talitos_desc *desc, void *context,
- int err)
+ struct talitos_desc *desc,
+ void *context, int err)
{
struct aead_request *req = context;
- struct ipsec_esp_edesc *edesc =
- container_of(desc, struct ipsec_esp_edesc, desc);
+ struct talitos_edesc *edesc;
+
+ edesc = container_of(desc, struct talitos_edesc, desc);
ipsec_esp_unmap(dev, edesc, req);
/* check ICV auth status */
- if (!err)
- if ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
- DESC_HDR_LO_ICCR1_PASS)
- err = -EBADMSG;
+ if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
+ DESC_HDR_LO_ICCR1_PASS))
+ err = -EBADMSG;
kfree(edesc);
@@ -886,7 +934,7 @@ static int sg_to_link_tbl(struct scatterlist *sg, int sg_count,
link_tbl_ptr->j_extent = 0;
link_tbl_ptr++;
cryptlen -= sg_dma_len(sg);
- sg = sg_next(sg);
+ sg = scatterwalk_sg_next(sg);
}
/* adjust (decrease) last one (or two) entry's len to cryptlen */
@@ -910,7 +958,7 @@ static int sg_to_link_tbl(struct scatterlist *sg, int sg_count,
/*
* fill in and submit ipsec_esp descriptor
*/
-static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq,
+static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
u8 *giv, u64 seq,
void (*callback) (struct device *dev,
struct talitos_desc *desc,
@@ -952,32 +1000,31 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq,
desc->ptr[4].len = cpu_to_be16(cryptlen);
desc->ptr[4].j_extent = authsize;
- if (areq->src == areq->dst)
- sg_count = dma_map_sg(dev, areq->src, edesc->src_nents ? : 1,
- DMA_BIDIRECTIONAL);
- else
- sg_count = dma_map_sg(dev, areq->src, edesc->src_nents ? : 1,
- DMA_TO_DEVICE);
+ sg_count = talitos_map_sg(dev, areq->src, edesc->src_nents ? : 1,
+ (areq->src == areq->dst) ? DMA_BIDIRECTIONAL
+ : DMA_TO_DEVICE,
+ edesc->src_is_chained);
if (sg_count == 1) {
desc->ptr[4].ptr = cpu_to_be32(sg_dma_address(areq->src));
} else {
sg_link_tbl_len = cryptlen;
- if ((edesc->desc.hdr & DESC_HDR_MODE1_MDEU_CICV) &&
- (edesc->desc.hdr & DESC_HDR_MODE0_ENCRYPT) == 0) {
+ if (edesc->desc.hdr & DESC_HDR_MODE1_MDEU_CICV)
sg_link_tbl_len = cryptlen + authsize;
- }
+
sg_count = sg_to_link_tbl(areq->src, sg_count, sg_link_tbl_len,
&edesc->link_tbl[0]);
if (sg_count > 1) {
desc->ptr[4].j_extent |= DESC_PTR_LNKTBL_JUMP;
desc->ptr[4].ptr = cpu_to_be32(edesc->dma_link_tbl);
- dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl,
- edesc->dma_len, DMA_BIDIRECTIONAL);
+ dma_sync_single_for_device(dev, edesc->dma_link_tbl,
+ edesc->dma_len,
+ DMA_BIDIRECTIONAL);
} else {
/* Only one segment now, so no link tbl needed */
- desc->ptr[4].ptr = cpu_to_be32(sg_dma_address(areq->src));
+ desc->ptr[4].ptr = cpu_to_be32(sg_dma_address(areq->
+ src));
}
}
@@ -985,10 +1032,11 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq,
desc->ptr[5].len = cpu_to_be16(cryptlen);
desc->ptr[5].j_extent = authsize;
- if (areq->src != areq->dst) {
- sg_count = dma_map_sg(dev, areq->dst, edesc->dst_nents ? : 1,
- DMA_FROM_DEVICE);
- }
+ if (areq->src != areq->dst)
+ sg_count = talitos_map_sg(dev, areq->dst,
+ edesc->dst_nents ? : 1,
+ DMA_FROM_DEVICE,
+ edesc->dst_is_chained);
if (sg_count == 1) {
desc->ptr[5].ptr = cpu_to_be32(sg_dma_address(areq->dst));
@@ -1033,49 +1081,55 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq,
return ret;
}
-
/*
* derive number of elements in scatterlist
*/
-static int sg_count(struct scatterlist *sg_list, int nbytes)
+static int sg_count(struct scatterlist *sg_list, int nbytes, int *chained)
{
struct scatterlist *sg = sg_list;
int sg_nents = 0;
- while (nbytes) {
+ *chained = 0;
+ while (nbytes > 0) {
sg_nents++;
nbytes -= sg->length;
- sg = sg_next(sg);
+ if (!sg_is_last(sg) && (sg + 1)->length == 0)
+ *chained = 1;
+ sg = scatterwalk_sg_next(sg);
}
return sg_nents;
}
/*
- * allocate and map the ipsec_esp extended descriptor
+ * allocate and map the extended descriptor
*/
-static struct ipsec_esp_edesc *ipsec_esp_edesc_alloc(struct aead_request *areq,
- int icv_stashing)
+static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
+ struct scatterlist *src,
+ struct scatterlist *dst,
+ unsigned int cryptlen,
+ unsigned int authsize,
+ int icv_stashing,
+ u32 cryptoflags)
{
- struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
- struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
- struct ipsec_esp_edesc *edesc;
+ struct talitos_edesc *edesc;
int src_nents, dst_nents, alloc_len, dma_len;
- gfp_t flags = areq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
+ int src_chained, dst_chained = 0;
+ gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
GFP_ATOMIC;
- if (areq->cryptlen + ctx->authsize > TALITOS_MAX_DATA_LEN) {
- dev_err(ctx->dev, "cryptlen exceeds h/w max limit\n");
+ if (cryptlen + authsize > TALITOS_MAX_DATA_LEN) {
+ dev_err(dev, "length exceeds h/w max limit\n");
return ERR_PTR(-EINVAL);
}
- src_nents = sg_count(areq->src, areq->cryptlen + ctx->authsize);
+ src_nents = sg_count(src, cryptlen + authsize, &src_chained);
src_nents = (src_nents == 1) ? 0 : src_nents;
- if (areq->dst == areq->src) {
+ if (dst == src) {
dst_nents = src_nents;
} else {
- dst_nents = sg_count(areq->dst, areq->cryptlen + ctx->authsize);
+ dst_nents = sg_count(dst, cryptlen + authsize, &dst_chained);
dst_nents = (dst_nents == 1) ? 0 : dst_nents;
}
@@ -1084,39 +1138,52 @@ static struct ipsec_esp_edesc *ipsec_esp_edesc_alloc(struct aead_request *areq,
* allowing for two separate entries for ICV and generated ICV (+ 2),
* and the ICV data itself
*/
- alloc_len = sizeof(struct ipsec_esp_edesc);
+ alloc_len = sizeof(struct talitos_edesc);
if (src_nents || dst_nents) {
dma_len = (src_nents + dst_nents + 2) *
- sizeof(struct talitos_ptr) + ctx->authsize;
+ sizeof(struct talitos_ptr) + authsize;
alloc_len += dma_len;
} else {
dma_len = 0;
- alloc_len += icv_stashing ? ctx->authsize : 0;
+ alloc_len += icv_stashing ? authsize : 0;
}
edesc = kmalloc(alloc_len, GFP_DMA | flags);
if (!edesc) {
- dev_err(ctx->dev, "could not allocate edescriptor\n");
+ dev_err(dev, "could not allocate edescriptor\n");
return ERR_PTR(-ENOMEM);
}
edesc->src_nents = src_nents;
edesc->dst_nents = dst_nents;
+ edesc->src_is_chained = src_chained;
+ edesc->dst_is_chained = dst_chained;
edesc->dma_len = dma_len;
- edesc->dma_link_tbl = dma_map_single(ctx->dev, &edesc->link_tbl[0],
+ edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0],
edesc->dma_len, DMA_BIDIRECTIONAL);
return edesc;
}
-static int aead_authenc_encrypt(struct aead_request *req)
+static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq,
+ int icv_stashing)
+{
+ struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
+ struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
+
+ return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
+ areq->cryptlen, ctx->authsize, icv_stashing,
+ areq->base.flags);
+}
+
+static int aead_encrypt(struct aead_request *req)
{
struct crypto_aead *authenc = crypto_aead_reqtfm(req);
struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
- struct ipsec_esp_edesc *edesc;
+ struct talitos_edesc *edesc;
/* allocate extended descriptor */
- edesc = ipsec_esp_edesc_alloc(req, 0);
+ edesc = aead_edesc_alloc(req, 0);
if (IS_ERR(edesc))
return PTR_ERR(edesc);
@@ -1126,70 +1193,67 @@ static int aead_authenc_encrypt(struct aead_request *req)
return ipsec_esp(edesc, req, NULL, 0, ipsec_esp_encrypt_done);
}
-
-
-static int aead_authenc_decrypt(struct aead_request *req)
+static int aead_decrypt(struct aead_request *req)
{
struct crypto_aead *authenc = crypto_aead_reqtfm(req);
struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
unsigned int authsize = ctx->authsize;
struct talitos_private *priv = dev_get_drvdata(ctx->dev);
- struct ipsec_esp_edesc *edesc;
+ struct talitos_edesc *edesc;
struct scatterlist *sg;
void *icvdata;
req->cryptlen -= authsize;
/* allocate extended descriptor */
- edesc = ipsec_esp_edesc_alloc(req, 1);
+ edesc = aead_edesc_alloc(req, 1);
if (IS_ERR(edesc))
return PTR_ERR(edesc);
if ((priv->features & TALITOS_FTR_HW_AUTH_CHECK) &&
- (((!edesc->src_nents && !edesc->dst_nents) ||
- priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT))) {
+ ((!edesc->src_nents && !edesc->dst_nents) ||
+ priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) {
/* decrypt and check the ICV */
- edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND |
+ edesc->desc.hdr = ctx->desc_hdr_template |
+ DESC_HDR_DIR_INBOUND |
DESC_HDR_MODE1_MDEU_CICV;
/* reset integrity check result bits */
edesc->desc.hdr_lo = 0;
- return ipsec_esp(edesc, req, NULL, 0, ipsec_esp_decrypt_hwauth_done);
+ return ipsec_esp(edesc, req, NULL, 0,
+ ipsec_esp_decrypt_hwauth_done);
- } else {
-
- /* Have to check the ICV with software */
+ }
- edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
+ /* Have to check the ICV with software */
+ edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
- /* stash incoming ICV for later cmp with ICV generated by the h/w */
- if (edesc->dma_len)
- icvdata = &edesc->link_tbl[edesc->src_nents +
- edesc->dst_nents + 2];
- else
- icvdata = &edesc->link_tbl[0];
+ /* stash incoming ICV for later cmp with ICV generated by the h/w */
+ if (edesc->dma_len)
+ icvdata = &edesc->link_tbl[edesc->src_nents +
+ edesc->dst_nents + 2];
+ else
+ icvdata = &edesc->link_tbl[0];
- sg = sg_last(req->src, edesc->src_nents ? : 1);
+ sg = sg_last(req->src, edesc->src_nents ? : 1);
- memcpy(icvdata, (char *)sg_virt(sg) + sg->length - ctx->authsize,
- ctx->authsize);
+ memcpy(icvdata, (char *)sg_virt(sg) + sg->length - ctx->authsize,
+ ctx->authsize);
- return ipsec_esp(edesc, req, NULL, 0, ipsec_esp_decrypt_swauth_done);
- }
+ return ipsec_esp(edesc, req, NULL, 0, ipsec_esp_decrypt_swauth_done);
}
-static int aead_authenc_givencrypt(
- struct aead_givcrypt_request *req)
+static int aead_givencrypt(struct aead_givcrypt_request *req)
{
struct aead_request *areq = &req->areq;
struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
- struct ipsec_esp_edesc *edesc;
+ struct talitos_edesc *edesc;
/* allocate extended descriptor */
- edesc = ipsec_esp_edesc_alloc(areq, 0);
+ edesc = aead_edesc_alloc(areq, 0);
if (IS_ERR(edesc))
return PTR_ERR(edesc);
@@ -1204,31 +1268,228 @@ static int aead_authenc_givencrypt(
ipsec_esp_encrypt_done);
}
+static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
+ const u8 *key, unsigned int keylen)
+{
+ struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+ struct ablkcipher_alg *alg = crypto_ablkcipher_alg(cipher);
+
+ if (keylen > TALITOS_MAX_KEY_SIZE)
+ goto badkey;
+
+ if (keylen < alg->min_keysize || keylen > alg->max_keysize)
+ goto badkey;
+
+ memcpy(&ctx->key, key, keylen);
+ ctx->keylen = keylen;
+
+ return 0;
+
+badkey:
+ crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
+ return -EINVAL;
+}
+
+static void common_nonsnoop_unmap(struct device *dev,
+ struct talitos_edesc *edesc,
+ struct ablkcipher_request *areq)
+{
+ unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
+ unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], DMA_TO_DEVICE);
+ unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE);
+
+ talitos_sg_unmap(dev, edesc, areq->src, areq->dst);
+
+ if (edesc->dma_len)
+ dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
+ DMA_BIDIRECTIONAL);
+}
+
+static void ablkcipher_done(struct device *dev,
+ struct talitos_desc *desc, void *context,
+ int err)
+{
+ struct ablkcipher_request *areq = context;
+ struct talitos_edesc *edesc;
+
+ edesc = container_of(desc, struct talitos_edesc, desc);
+
+ common_nonsnoop_unmap(dev, edesc, areq);
+
+ kfree(edesc);
+
+ areq->base.complete(&areq->base, err);
+}
+
+static int common_nonsnoop(struct talitos_edesc *edesc,
+ struct ablkcipher_request *areq,
+ u8 *giv,
+ void (*callback) (struct device *dev,
+ struct talitos_desc *desc,
+ void *context, int error))
+{
+ struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
+ struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+ struct device *dev = ctx->dev;
+ struct talitos_desc *desc = &edesc->desc;
+ unsigned int cryptlen = areq->nbytes;
+ unsigned int ivsize;
+ int sg_count, ret;
+
+ /* first DWORD empty */
+ desc->ptr[0].len = 0;
+ desc->ptr[0].ptr = 0;
+ desc->ptr[0].j_extent = 0;
+
+ /* cipher iv */
+ ivsize = crypto_ablkcipher_ivsize(cipher);
+ map_single_talitos_ptr(dev, &desc->ptr[1], ivsize, giv ?: areq->info, 0,
+ DMA_TO_DEVICE);
+
+ /* cipher key */
+ map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen,
+ (char *)&ctx->key, 0, DMA_TO_DEVICE);
+
+ /*
+ * cipher in
+ */
+ desc->ptr[3].len = cpu_to_be16(cryptlen);
+ desc->ptr[3].j_extent = 0;
+
+ sg_count = talitos_map_sg(dev, areq->src, edesc->src_nents ? : 1,
+ (areq->src == areq->dst) ? DMA_BIDIRECTIONAL
+ : DMA_TO_DEVICE,
+ edesc->src_is_chained);
+
+ if (sg_count == 1) {
+ desc->ptr[3].ptr = cpu_to_be32(sg_dma_address(areq->src));
+ } else {
+ sg_count = sg_to_link_tbl(areq->src, sg_count, cryptlen,
+ &edesc->link_tbl[0]);
+ if (sg_count > 1) {
+ desc->ptr[3].j_extent |= DESC_PTR_LNKTBL_JUMP;
+ desc->ptr[3].ptr = cpu_to_be32(edesc->dma_link_tbl);
+ dma_sync_single_for_device(dev, edesc->dma_link_tbl,
+ edesc->dma_len,
+ DMA_BIDIRECTIONAL);
+ } else {
+ /* Only one segment now, so no link tbl needed */
+ desc->ptr[3].ptr = cpu_to_be32(sg_dma_address(areq->
+ src));
+ }
+ }
+
+ /* cipher out */
+ desc->ptr[4].len = cpu_to_be16(cryptlen);
+ desc->ptr[4].j_extent = 0;
+
+ if (areq->src != areq->dst)
+ sg_count = talitos_map_sg(dev, areq->dst,
+ edesc->dst_nents ? : 1,
+ DMA_FROM_DEVICE,
+ edesc->dst_is_chained);
+
+ if (sg_count == 1) {
+ desc->ptr[4].ptr = cpu_to_be32(sg_dma_address(areq->dst));
+ } else {
+ struct talitos_ptr *link_tbl_ptr =
+ &edesc->link_tbl[edesc->src_nents + 1];
+
+ desc->ptr[4].j_extent |= DESC_PTR_LNKTBL_JUMP;
+ desc->ptr[4].ptr = cpu_to_be32((struct talitos_ptr *)
+ edesc->dma_link_tbl +
+ edesc->src_nents + 1);
+ sg_count = sg_to_link_tbl(areq->dst, sg_count, cryptlen,
+ link_tbl_ptr);
+ dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl,
+ edesc->dma_len, DMA_BIDIRECTIONAL);
+ }
+
+ /* iv out */
+ map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv, 0,
+ DMA_FROM_DEVICE);
+
+ /* last DWORD empty */
+ desc->ptr[6].len = 0;
+ desc->ptr[6].ptr = 0;
+ desc->ptr[6].j_extent = 0;
+
+ ret = talitos_submit(dev, desc, callback, areq);
+ if (ret != -EINPROGRESS) {
+ common_nonsnoop_unmap(dev, edesc, areq);
+ kfree(edesc);
+ }
+ return ret;
+}
+
+static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
+ areq)
+{
+ struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
+ struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+
+ return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst, areq->nbytes,
+ 0, 0, areq->base.flags);
+}
+
+static int ablkcipher_encrypt(struct ablkcipher_request *areq)
+{
+ struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
+ struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+ struct talitos_edesc *edesc;
+
+ /* allocate extended descriptor */
+ edesc = ablkcipher_edesc_alloc(areq);
+ if (IS_ERR(edesc))
+ return PTR_ERR(edesc);
+
+ /* set encrypt */
+ edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
+
+ return common_nonsnoop(edesc, areq, NULL, ablkcipher_done);
+}
+
+static int ablkcipher_decrypt(struct ablkcipher_request *areq)
+{
+ struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
+ struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+ struct talitos_edesc *edesc;
+
+ /* allocate extended descriptor */
+ edesc = ablkcipher_edesc_alloc(areq);
+ if (IS_ERR(edesc))
+ return PTR_ERR(edesc);
+
+ edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
+
+ return common_nonsnoop(edesc, areq, NULL, ablkcipher_done);
+}
+
struct talitos_alg_template {
- char name[CRYPTO_MAX_ALG_NAME];
- char driver_name[CRYPTO_MAX_ALG_NAME];
- unsigned int blocksize;
- struct aead_alg aead;
- struct device *dev;
+ struct crypto_alg alg;
__be32 desc_hdr_template;
};
static struct talitos_alg_template driver_algs[] = {
- /* single-pass ipsec_esp descriptor */
+ /* AEAD algorithms. These use a single-pass ipsec_esp descriptor */
{
- .name = "authenc(hmac(sha1),cbc(aes))",
- .driver_name = "authenc-hmac-sha1-cbc-aes-talitos",
- .blocksize = AES_BLOCK_SIZE,
- .aead = {
- .setkey = aead_authenc_setkey,
- .setauthsize = aead_authenc_setauthsize,
- .encrypt = aead_authenc_encrypt,
- .decrypt = aead_authenc_decrypt,
- .givencrypt = aead_authenc_givencrypt,
- .geniv = "<built-in>",
- .ivsize = AES_BLOCK_SIZE,
- .maxauthsize = SHA1_DIGEST_SIZE,
- },
+ .alg = {
+ .cra_name = "authenc(hmac(sha1),cbc(aes))",
+ .cra_driver_name = "authenc-hmac-sha1-cbc-aes-talitos",
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+ .cra_type = &crypto_aead_type,
+ .cra_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = SHA1_DIGEST_SIZE,
+ }
+ },
.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
DESC_HDR_SEL0_AESU |
DESC_HDR_MODE0_AESU_CBC |
@@ -1238,19 +1499,23 @@ static struct talitos_alg_template driver_algs[] = {
DESC_HDR_MODE1_MDEU_SHA1_HMAC,
},
{
- .name = "authenc(hmac(sha1),cbc(des3_ede))",
- .driver_name = "authenc-hmac-sha1-cbc-3des-talitos",
- .blocksize = DES3_EDE_BLOCK_SIZE,
- .aead = {
- .setkey = aead_authenc_setkey,
- .setauthsize = aead_authenc_setauthsize,
- .encrypt = aead_authenc_encrypt,
- .decrypt = aead_authenc_decrypt,
- .givencrypt = aead_authenc_givencrypt,
- .geniv = "<built-in>",
- .ivsize = DES3_EDE_BLOCK_SIZE,
- .maxauthsize = SHA1_DIGEST_SIZE,
- },
+ .alg = {
+ .cra_name = "authenc(hmac(sha1),cbc(des3_ede))",
+ .cra_driver_name = "authenc-hmac-sha1-cbc-3des-talitos",
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+ .cra_type = &crypto_aead_type,
+ .cra_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .maxauthsize = SHA1_DIGEST_SIZE,
+ }
+ },
.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
DESC_HDR_SEL0_DEU |
DESC_HDR_MODE0_DEU_CBC |
@@ -1261,19 +1526,23 @@ static struct talitos_alg_template driver_algs[] = {
DESC_HDR_MODE1_MDEU_SHA1_HMAC,
},
{
- .name = "authenc(hmac(sha256),cbc(aes))",
- .driver_name = "authenc-hmac-sha256-cbc-aes-talitos",
- .blocksize = AES_BLOCK_SIZE,
- .aead = {
- .setkey = aead_authenc_setkey,
- .setauthsize = aead_authenc_setauthsize,
- .encrypt = aead_authenc_encrypt,
- .decrypt = aead_authenc_decrypt,
- .givencrypt = aead_authenc_givencrypt,
- .geniv = "<built-in>",
- .ivsize = AES_BLOCK_SIZE,
- .maxauthsize = SHA256_DIGEST_SIZE,
- },
+ .alg = {
+ .cra_name = "authenc(hmac(sha256),cbc(aes))",
+ .cra_driver_name = "authenc-hmac-sha256-cbc-aes-talitos",
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+ .cra_type = &crypto_aead_type,
+ .cra_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = SHA256_DIGEST_SIZE,
+ }
+ },
.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
DESC_HDR_SEL0_AESU |
DESC_HDR_MODE0_AESU_CBC |
@@ -1283,19 +1552,23 @@ static struct talitos_alg_template driver_algs[] = {
DESC_HDR_MODE1_MDEU_SHA256_HMAC,
},
{
- .name = "authenc(hmac(sha256),cbc(des3_ede))",
- .driver_name = "authenc-hmac-sha256-cbc-3des-talitos",
- .blocksize = DES3_EDE_BLOCK_SIZE,
- .aead = {
- .setkey = aead_authenc_setkey,
- .setauthsize = aead_authenc_setauthsize,
- .encrypt = aead_authenc_encrypt,
- .decrypt = aead_authenc_decrypt,
- .givencrypt = aead_authenc_givencrypt,
- .geniv = "<built-in>",
- .ivsize = DES3_EDE_BLOCK_SIZE,
- .maxauthsize = SHA256_DIGEST_SIZE,
- },
+ .alg = {
+ .cra_name = "authenc(hmac(sha256),cbc(des3_ede))",
+ .cra_driver_name = "authenc-hmac-sha256-cbc-3des-talitos",
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+ .cra_type = &crypto_aead_type,
+ .cra_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .maxauthsize = SHA256_DIGEST_SIZE,
+ }
+ },
.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
DESC_HDR_SEL0_DEU |
DESC_HDR_MODE0_DEU_CBC |
@@ -1306,19 +1579,23 @@ static struct talitos_alg_template driver_algs[] = {
DESC_HDR_MODE1_MDEU_SHA256_HMAC,
},
{
- .name = "authenc(hmac(md5),cbc(aes))",
- .driver_name = "authenc-hmac-md5-cbc-aes-talitos",
- .blocksize = AES_BLOCK_SIZE,
- .aead = {
- .setkey = aead_authenc_setkey,
- .setauthsize = aead_authenc_setauthsize,
- .encrypt = aead_authenc_encrypt,
- .decrypt = aead_authenc_decrypt,
- .givencrypt = aead_authenc_givencrypt,
- .geniv = "<built-in>",
- .ivsize = AES_BLOCK_SIZE,
- .maxauthsize = MD5_DIGEST_SIZE,
- },
+ .alg = {
+ .cra_name = "authenc(hmac(md5),cbc(aes))",
+ .cra_driver_name = "authenc-hmac-md5-cbc-aes-talitos",
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+ .cra_type = &crypto_aead_type,
+ .cra_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = MD5_DIGEST_SIZE,
+ }
+ },
.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
DESC_HDR_SEL0_AESU |
DESC_HDR_MODE0_AESU_CBC |
@@ -1328,19 +1605,23 @@ static struct talitos_alg_template driver_algs[] = {
DESC_HDR_MODE1_MDEU_MD5_HMAC,
},
{
- .name = "authenc(hmac(md5),cbc(des3_ede))",
- .driver_name = "authenc-hmac-md5-cbc-3des-talitos",
- .blocksize = DES3_EDE_BLOCK_SIZE,
- .aead = {
- .setkey = aead_authenc_setkey,
- .setauthsize = aead_authenc_setauthsize,
- .encrypt = aead_authenc_encrypt,
- .decrypt = aead_authenc_decrypt,
- .givencrypt = aead_authenc_givencrypt,
- .geniv = "<built-in>",
- .ivsize = DES3_EDE_BLOCK_SIZE,
- .maxauthsize = MD5_DIGEST_SIZE,
- },
+ .alg = {
+ .cra_name = "authenc(hmac(md5),cbc(des3_ede))",
+ .cra_driver_name = "authenc-hmac-md5-cbc-3des-talitos",
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+ .cra_type = &crypto_aead_type,
+ .cra_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .maxauthsize = MD5_DIGEST_SIZE,
+ }
+ },
.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
DESC_HDR_SEL0_DEU |
DESC_HDR_MODE0_DEU_CBC |
@@ -1349,6 +1630,52 @@ static struct talitos_alg_template driver_algs[] = {
DESC_HDR_MODE1_MDEU_INIT |
DESC_HDR_MODE1_MDEU_PAD |
DESC_HDR_MODE1_MDEU_MD5_HMAC,
+ },
+ /* ABLKCIPHER algorithms. */
+ {
+ .alg = {
+ .cra_name = "cbc(aes)",
+ .cra_driver_name = "cbc-aes-talitos",
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_ablkcipher = {
+ .setkey = ablkcipher_setkey,
+ .encrypt = ablkcipher_encrypt,
+ .decrypt = ablkcipher_decrypt,
+ .geniv = "eseqiv",
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ }
+ },
+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
+ DESC_HDR_SEL0_AESU |
+ DESC_HDR_MODE0_AESU_CBC,
+ },
+ {
+ .alg = {
+ .cra_name = "cbc(des3_ede)",
+ .cra_driver_name = "cbc-3des-talitos",
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_ablkcipher = {
+ .setkey = ablkcipher_setkey,
+ .encrypt = ablkcipher_encrypt,
+ .decrypt = ablkcipher_decrypt,
+ .geniv = "eseqiv",
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ }
+ },
+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
+ DESC_HDR_SEL0_DEU |
+ DESC_HDR_MODE0_DEU_CBC |
+ DESC_HDR_MODE0_DEU_3DES,
}
};
@@ -1362,12 +1689,14 @@ struct talitos_crypto_alg {
static int talitos_cra_init(struct crypto_tfm *tfm)
{
struct crypto_alg *alg = tfm->__crt_alg;
- struct talitos_crypto_alg *talitos_alg =
- container_of(alg, struct talitos_crypto_alg, crypto_alg);
+ struct talitos_crypto_alg *talitos_alg;
struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
+ talitos_alg = container_of(alg, struct talitos_crypto_alg, crypto_alg);
+
/* update context with ptr to dev */
ctx->dev = talitos_alg->dev;
+
/* copy descriptor header template value */
ctx->desc_hdr_template = talitos_alg->desc_hdr_template;
@@ -1453,19 +1782,13 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
return ERR_PTR(-ENOMEM);
alg = &t_alg->crypto_alg;
+ *alg = template->alg;
- snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", template->name);
- snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
- template->driver_name);
alg->cra_module = THIS_MODULE;
alg->cra_init = talitos_cra_init;
alg->cra_priority = TALITOS_CRA_PRIORITY;
- alg->cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC;
- alg->cra_blocksize = template->blocksize;
alg->cra_alignmask = 0;
- alg->cra_type = &crypto_aead_type;
alg->cra_ctxsize = sizeof(struct talitos_ctx);
- alg->cra_u.aead = template->aead;
t_alg->desc_hdr_template = template->desc_hdr_template;
t_alg->dev = dev;
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 3b3c01b6f1ee..070357aaedbc 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -81,6 +81,14 @@ config MX3_IPU_IRQS
To avoid bloating the irq_desc[] array we allocate a sufficient
number of IRQ slots and map them dynamically to specific sources.
+config TXX9_DMAC
+ tristate "Toshiba TXx9 SoC DMA support"
+ depends on MACH_TX49XX || MACH_TX39XX
+ select DMA_ENGINE
+ help
+ Support the TXx9 SoC internal DMA controller. This can be
+ integrated in chips such as the Toshiba TX4927/38/39.
+
config DMA_ENGINE
bool
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 2e5dc96700d2..a0b6564800c4 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_FSL_DMA) += fsldma.o
obj-$(CONFIG_MV_XOR) += mv_xor.o
obj-$(CONFIG_DW_DMAC) += dw_dmac.o
obj-$(CONFIG_MX3_IPU) += ipu/
+obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 92438e9dacc3..5a87384ea4ff 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -804,11 +804,14 @@ dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest,
dma_addr_t dma_dest, dma_src;
dma_cookie_t cookie;
int cpu;
+ unsigned long flags;
dma_src = dma_map_single(dev->dev, src, len, DMA_TO_DEVICE);
dma_dest = dma_map_single(dev->dev, dest, len, DMA_FROM_DEVICE);
- tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len,
- DMA_CTRL_ACK);
+ flags = DMA_CTRL_ACK |
+ DMA_COMPL_SRC_UNMAP_SINGLE |
+ DMA_COMPL_DEST_UNMAP_SINGLE;
+ tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, flags);
if (!tx) {
dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE);
@@ -850,11 +853,12 @@ dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page,
dma_addr_t dma_dest, dma_src;
dma_cookie_t cookie;
int cpu;
+ unsigned long flags;
dma_src = dma_map_single(dev->dev, kdata, len, DMA_TO_DEVICE);
dma_dest = dma_map_page(dev->dev, page, offset, len, DMA_FROM_DEVICE);
- tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len,
- DMA_CTRL_ACK);
+ flags = DMA_CTRL_ACK | DMA_COMPL_SRC_UNMAP_SINGLE;
+ tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, flags);
if (!tx) {
dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE);
@@ -898,12 +902,13 @@ dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg,
dma_addr_t dma_dest, dma_src;
dma_cookie_t cookie;
int cpu;
+ unsigned long flags;
dma_src = dma_map_page(dev->dev, src_pg, src_off, len, DMA_TO_DEVICE);
dma_dest = dma_map_page(dev->dev, dest_pg, dest_off, len,
DMA_FROM_DEVICE);
- tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len,
- DMA_CTRL_ACK);
+ flags = DMA_CTRL_ACK;
+ tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, flags);
if (!tx) {
dma_unmap_page(dev->dev, dma_src, len, DMA_TO_DEVICE);
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index a27c0fb1bc11..fb7da5141e96 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -531,9 +531,7 @@ static int __init dmatest_init(void)
chan = dma_request_channel(mask, filter, NULL);
if (chan) {
err = dmatest_add_channel(chan);
- if (err == 0)
- continue;
- else {
+ if (err) {
dma_release_channel(chan);
break; /* add_channel failed, punt */
}
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
index e4fc33c1c32f..1955ee8d6d20 100644
--- a/drivers/dma/ioat_dma.c
+++ b/drivers/dma/ioat_dma.c
@@ -1063,22 +1063,31 @@ static void ioat_dma_cleanup_tasklet(unsigned long data)
static void
ioat_dma_unmap(struct ioat_dma_chan *ioat_chan, struct ioat_desc_sw *desc)
{
- /*
- * yes we are unmapping both _page and _single
- * alloc'd regions with unmap_page. Is this
- * *really* that bad?
- */
- if (!(desc->async_tx.flags & DMA_COMPL_SKIP_DEST_UNMAP))
- pci_unmap_page(ioat_chan->device->pdev,
- pci_unmap_addr(desc, dst),
- pci_unmap_len(desc, len),
- PCI_DMA_FROMDEVICE);
-
- if (!(desc->async_tx.flags & DMA_COMPL_SKIP_SRC_UNMAP))
- pci_unmap_page(ioat_chan->device->pdev,
- pci_unmap_addr(desc, src),
- pci_unmap_len(desc, len),
- PCI_DMA_TODEVICE);
+ if (!(desc->async_tx.flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
+ if (desc->async_tx.flags & DMA_COMPL_DEST_UNMAP_SINGLE)
+ pci_unmap_single(ioat_chan->device->pdev,
+ pci_unmap_addr(desc, dst),
+ pci_unmap_len(desc, len),
+ PCI_DMA_FROMDEVICE);
+ else
+ pci_unmap_page(ioat_chan->device->pdev,
+ pci_unmap_addr(desc, dst),
+ pci_unmap_len(desc, len),
+ PCI_DMA_FROMDEVICE);
+ }
+
+ if (!(desc->async_tx.flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
+ if (desc->async_tx.flags & DMA_COMPL_SRC_UNMAP_SINGLE)
+ pci_unmap_single(ioat_chan->device->pdev,
+ pci_unmap_addr(desc, src),
+ pci_unmap_len(desc, len),
+ PCI_DMA_TODEVICE);
+ else
+ pci_unmap_page(ioat_chan->device->pdev,
+ pci_unmap_addr(desc, src),
+ pci_unmap_len(desc, len),
+ PCI_DMA_TODEVICE);
+ }
}
/**
@@ -1363,6 +1372,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device)
int err = 0;
struct completion cmp;
unsigned long tmo;
+ unsigned long flags;
src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL);
if (!src)
@@ -1392,8 +1402,9 @@ static int ioat_dma_self_test(struct ioatdma_device *device)
DMA_TO_DEVICE);
dma_dest = dma_map_single(dma_chan->device->dev, dest, IOAT_TEST_SIZE,
DMA_FROM_DEVICE);
+ flags = DMA_COMPL_SRC_UNMAP_SINGLE | DMA_COMPL_DEST_UNMAP_SINGLE;
tx = device->common.device_prep_dma_memcpy(dma_chan, dma_dest, dma_src,
- IOAT_TEST_SIZE, 0);
+ IOAT_TEST_SIZE, flags);
if (!tx) {
dev_err(&device->pdev->dev,
"Self-test prep failed, disabling\n");
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
index e202a6ce5573..3a4deea78a71 100644
--- a/drivers/dma/ipu/ipu_idmac.c
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -1547,7 +1547,7 @@ static irqreturn_t ic_sof_irq(int irq, void *dev_id)
struct idmac_channel *ichan = dev_id;
printk(KERN_DEBUG "Got SOF IRQ %d on Channel %d\n",
irq, ichan->dma_chan.chan_id);
- disable_irq(irq);
+ disable_irq_nosync(irq);
return IRQ_HANDLED;
}
@@ -1556,7 +1556,7 @@ static irqreturn_t ic_eof_irq(int irq, void *dev_id)
struct idmac_channel *ichan = dev_id;
printk(KERN_DEBUG "Got EOF IRQ %d on Channel %d\n",
irq, ichan->dma_chan.chan_id);
- disable_irq(irq);
+ disable_irq_nosync(irq);
return IRQ_HANDLED;
}
diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c
new file mode 100644
index 000000000000..9aa9ea9822c8
--- /dev/null
+++ b/drivers/dma/txx9dmac.c
@@ -0,0 +1,1354 @@
+/*
+ * Driver for the TXx9 SoC DMA Controller
+ *
+ * Copyright (C) 2009 Atsushi Nemoto
+ *
+ * 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/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/scatterlist.h>
+#include "txx9dmac.h"
+
+static struct txx9dmac_chan *to_txx9dmac_chan(struct dma_chan *chan)
+{
+ return container_of(chan, struct txx9dmac_chan, chan);
+}
+
+static struct txx9dmac_cregs __iomem *__dma_regs(const struct txx9dmac_chan *dc)
+{
+ return dc->ch_regs;
+}
+
+static struct txx9dmac_cregs32 __iomem *__dma_regs32(
+ const struct txx9dmac_chan *dc)
+{
+ return dc->ch_regs;
+}
+
+#define channel64_readq(dc, name) \
+ __raw_readq(&(__dma_regs(dc)->name))
+#define channel64_writeq(dc, name, val) \
+ __raw_writeq((val), &(__dma_regs(dc)->name))
+#define channel64_readl(dc, name) \
+ __raw_readl(&(__dma_regs(dc)->name))
+#define channel64_writel(dc, name, val) \
+ __raw_writel((val), &(__dma_regs(dc)->name))
+
+#define channel32_readl(dc, name) \
+ __raw_readl(&(__dma_regs32(dc)->name))
+#define channel32_writel(dc, name, val) \
+ __raw_writel((val), &(__dma_regs32(dc)->name))
+
+#define channel_readq(dc, name) channel64_readq(dc, name)
+#define channel_writeq(dc, name, val) channel64_writeq(dc, name, val)
+#define channel_readl(dc, name) \
+ (is_dmac64(dc) ? \
+ channel64_readl(dc, name) : channel32_readl(dc, name))
+#define channel_writel(dc, name, val) \
+ (is_dmac64(dc) ? \
+ channel64_writel(dc, name, val) : channel32_writel(dc, name, val))
+
+static dma_addr_t channel64_read_CHAR(const struct txx9dmac_chan *dc)
+{
+ if (sizeof(__dma_regs(dc)->CHAR) == sizeof(u64))
+ return channel64_readq(dc, CHAR);
+ else
+ return channel64_readl(dc, CHAR);
+}
+
+static void channel64_write_CHAR(const struct txx9dmac_chan *dc, dma_addr_t val)
+{
+ if (sizeof(__dma_regs(dc)->CHAR) == sizeof(u64))
+ channel64_writeq(dc, CHAR, val);
+ else
+ channel64_writel(dc, CHAR, val);
+}
+
+static void channel64_clear_CHAR(const struct txx9dmac_chan *dc)
+{
+#if defined(CONFIG_32BIT) && !defined(CONFIG_64BIT_PHYS_ADDR)
+ channel64_writel(dc, CHAR, 0);
+ channel64_writel(dc, __pad_CHAR, 0);
+#else
+ channel64_writeq(dc, CHAR, 0);
+#endif
+}
+
+static dma_addr_t channel_read_CHAR(const struct txx9dmac_chan *dc)
+{
+ if (is_dmac64(dc))
+ return channel64_read_CHAR(dc);
+ else
+ return channel32_readl(dc, CHAR);
+}
+
+static void channel_write_CHAR(const struct txx9dmac_chan *dc, dma_addr_t val)
+{
+ if (is_dmac64(dc))
+ channel64_write_CHAR(dc, val);
+ else
+ channel32_writel(dc, CHAR, val);
+}
+
+static struct txx9dmac_regs __iomem *__txx9dmac_regs(
+ const struct txx9dmac_dev *ddev)
+{
+ return ddev->regs;
+}
+
+static struct txx9dmac_regs32 __iomem *__txx9dmac_regs32(
+ const struct txx9dmac_dev *ddev)
+{
+ return ddev->regs;
+}
+
+#define dma64_readl(ddev, name) \
+ __raw_readl(&(__txx9dmac_regs(ddev)->name))
+#define dma64_writel(ddev, name, val) \
+ __raw_writel((val), &(__txx9dmac_regs(ddev)->name))
+
+#define dma32_readl(ddev, name) \
+ __raw_readl(&(__txx9dmac_regs32(ddev)->name))
+#define dma32_writel(ddev, name, val) \
+ __raw_writel((val), &(__txx9dmac_regs32(ddev)->name))
+
+#define dma_readl(ddev, name) \
+ (__is_dmac64(ddev) ? \
+ dma64_readl(ddev, name) : dma32_readl(ddev, name))
+#define dma_writel(ddev, name, val) \
+ (__is_dmac64(ddev) ? \
+ dma64_writel(ddev, name, val) : dma32_writel(ddev, name, val))
+
+static struct device *chan2dev(struct dma_chan *chan)
+{
+ return &chan->dev->device;
+}
+static struct device *chan2parent(struct dma_chan *chan)
+{
+ return chan->dev->device.parent;
+}
+
+static struct txx9dmac_desc *
+txd_to_txx9dmac_desc(struct dma_async_tx_descriptor *txd)
+{
+ return container_of(txd, struct txx9dmac_desc, txd);
+}
+
+static dma_addr_t desc_read_CHAR(const struct txx9dmac_chan *dc,
+ const struct txx9dmac_desc *desc)
+{
+ return is_dmac64(dc) ? desc->hwdesc.CHAR : desc->hwdesc32.CHAR;
+}
+
+static void desc_write_CHAR(const struct txx9dmac_chan *dc,
+ struct txx9dmac_desc *desc, dma_addr_t val)
+{
+ if (is_dmac64(dc))
+ desc->hwdesc.CHAR = val;
+ else
+ desc->hwdesc32.CHAR = val;
+}
+
+#define TXX9_DMA_MAX_COUNT 0x04000000
+
+#define TXX9_DMA_INITIAL_DESC_COUNT 64
+
+static struct txx9dmac_desc *txx9dmac_first_active(struct txx9dmac_chan *dc)
+{
+ return list_entry(dc->active_list.next,
+ struct txx9dmac_desc, desc_node);
+}
+
+static struct txx9dmac_desc *txx9dmac_last_active(struct txx9dmac_chan *dc)
+{
+ return list_entry(dc->active_list.prev,
+ struct txx9dmac_desc, desc_node);
+}
+
+static struct txx9dmac_desc *txx9dmac_first_queued(struct txx9dmac_chan *dc)
+{
+ return list_entry(dc->queue.next, struct txx9dmac_desc, desc_node);
+}
+
+static struct txx9dmac_desc *txx9dmac_last_child(struct txx9dmac_desc *desc)
+{
+ if (!list_empty(&desc->txd.tx_list))
+ desc = list_entry(desc->txd.tx_list.prev,
+ struct txx9dmac_desc, desc_node);
+ return desc;
+}
+
+static dma_cookie_t txx9dmac_tx_submit(struct dma_async_tx_descriptor *tx);
+
+static struct txx9dmac_desc *txx9dmac_desc_alloc(struct txx9dmac_chan *dc,
+ gfp_t flags)
+{
+ struct txx9dmac_dev *ddev = dc->ddev;
+ struct txx9dmac_desc *desc;
+
+ desc = kzalloc(sizeof(*desc), flags);
+ if (!desc)
+ return NULL;
+ dma_async_tx_descriptor_init(&desc->txd, &dc->chan);
+ desc->txd.tx_submit = txx9dmac_tx_submit;
+ /* txd.flags will be overwritten in prep funcs */
+ desc->txd.flags = DMA_CTRL_ACK;
+ desc->txd.phys = dma_map_single(chan2parent(&dc->chan), &desc->hwdesc,
+ ddev->descsize, DMA_TO_DEVICE);
+ return desc;
+}
+
+static struct txx9dmac_desc *txx9dmac_desc_get(struct txx9dmac_chan *dc)
+{
+ struct txx9dmac_desc *desc, *_desc;
+ struct txx9dmac_desc *ret = NULL;
+ unsigned int i = 0;
+
+ spin_lock_bh(&dc->lock);
+ list_for_each_entry_safe(desc, _desc, &dc->free_list, desc_node) {
+ if (async_tx_test_ack(&desc->txd)) {
+ list_del(&desc->desc_node);
+ ret = desc;
+ break;
+ }
+ dev_dbg(chan2dev(&dc->chan), "desc %p not ACKed\n", desc);
+ i++;
+ }
+ spin_unlock_bh(&dc->lock);
+
+ dev_vdbg(chan2dev(&dc->chan), "scanned %u descriptors on freelist\n",
+ i);
+ if (!ret) {
+ ret = txx9dmac_desc_alloc(dc, GFP_ATOMIC);
+ if (ret) {
+ spin_lock_bh(&dc->lock);
+ dc->descs_allocated++;
+ spin_unlock_bh(&dc->lock);
+ } else
+ dev_err(chan2dev(&dc->chan),
+ "not enough descriptors available\n");
+ }
+ return ret;
+}
+
+static void txx9dmac_sync_desc_for_cpu(struct txx9dmac_chan *dc,
+ struct txx9dmac_desc *desc)
+{
+ struct txx9dmac_dev *ddev = dc->ddev;
+ struct txx9dmac_desc *child;
+
+ list_for_each_entry(child, &desc->txd.tx_list, desc_node)
+ dma_sync_single_for_cpu(chan2parent(&dc->chan),
+ child->txd.phys, ddev->descsize,
+ DMA_TO_DEVICE);
+ dma_sync_single_for_cpu(chan2parent(&dc->chan),
+ desc->txd.phys, ddev->descsize,
+ DMA_TO_DEVICE);
+}
+
+/*
+ * Move a descriptor, including any children, to the free list.
+ * `desc' must not be on any lists.
+ */
+static void txx9dmac_desc_put(struct txx9dmac_chan *dc,
+ struct txx9dmac_desc *desc)
+{
+ if (desc) {
+ struct txx9dmac_desc *child;
+
+ txx9dmac_sync_desc_for_cpu(dc, desc);
+
+ spin_lock_bh(&dc->lock);
+ list_for_each_entry(child, &desc->txd.tx_list, desc_node)
+ dev_vdbg(chan2dev(&dc->chan),
+ "moving child desc %p to freelist\n",
+ child);
+ list_splice_init(&desc->txd.tx_list, &dc->free_list);
+ dev_vdbg(chan2dev(&dc->chan), "moving desc %p to freelist\n",
+ desc);
+ list_add(&desc->desc_node, &dc->free_list);
+ spin_unlock_bh(&dc->lock);
+ }
+}
+
+/* Called with dc->lock held and bh disabled */
+static dma_cookie_t
+txx9dmac_assign_cookie(struct txx9dmac_chan *dc, struct txx9dmac_desc *desc)
+{
+ dma_cookie_t cookie = dc->chan.cookie;
+
+ if (++cookie < 0)
+ cookie = 1;
+
+ dc->chan.cookie = cookie;
+ desc->txd.cookie = cookie;
+
+ return cookie;
+}
+
+/*----------------------------------------------------------------------*/
+
+static void txx9dmac_dump_regs(struct txx9dmac_chan *dc)
+{
+ if (is_dmac64(dc))
+ dev_err(chan2dev(&dc->chan),
+ " CHAR: %#llx SAR: %#llx DAR: %#llx CNTR: %#x"
+ " SAIR: %#x DAIR: %#x CCR: %#x CSR: %#x\n",
+ (u64)channel64_read_CHAR(dc),
+ channel64_readq(dc, SAR),
+ channel64_readq(dc, DAR),
+ channel64_readl(dc, CNTR),
+ channel64_readl(dc, SAIR),
+ channel64_readl(dc, DAIR),
+ channel64_readl(dc, CCR),
+ channel64_readl(dc, CSR));
+ else
+ dev_err(chan2dev(&dc->chan),
+ " CHAR: %#x SAR: %#x DAR: %#x CNTR: %#x"
+ " SAIR: %#x DAIR: %#x CCR: %#x CSR: %#x\n",
+ channel32_readl(dc, CHAR),
+ channel32_readl(dc, SAR),
+ channel32_readl(dc, DAR),
+ channel32_readl(dc, CNTR),
+ channel32_readl(dc, SAIR),
+ channel32_readl(dc, DAIR),
+ channel32_readl(dc, CCR),
+ channel32_readl(dc, CSR));
+}
+
+static void txx9dmac_reset_chan(struct txx9dmac_chan *dc)
+{
+ channel_writel(dc, CCR, TXX9_DMA_CCR_CHRST);
+ if (is_dmac64(dc)) {
+ channel64_clear_CHAR(dc);
+ channel_writeq(dc, SAR, 0);
+ channel_writeq(dc, DAR, 0);
+ } else {
+ channel_writel(dc, CHAR, 0);
+ channel_writel(dc, SAR, 0);
+ channel_writel(dc, DAR, 0);
+ }
+ channel_writel(dc, CNTR, 0);
+ channel_writel(dc, SAIR, 0);
+ channel_writel(dc, DAIR, 0);
+ channel_writel(dc, CCR, 0);
+ mmiowb();
+}
+
+/* Called with dc->lock held and bh disabled */
+static void txx9dmac_dostart(struct txx9dmac_chan *dc,
+ struct txx9dmac_desc *first)
+{
+ struct txx9dmac_slave *ds = dc->chan.private;
+ u32 sai, dai;
+
+ dev_vdbg(chan2dev(&dc->chan), "dostart %u %p\n",
+ first->txd.cookie, first);
+ /* ASSERT: channel is idle */
+ if (channel_readl(dc, CSR) & TXX9_DMA_CSR_XFACT) {
+ dev_err(chan2dev(&dc->chan),
+ "BUG: Attempted to start non-idle channel\n");
+ txx9dmac_dump_regs(dc);
+ /* The tasklet will hopefully advance the queue... */
+ return;
+ }
+
+ if (is_dmac64(dc)) {
+ channel64_writel(dc, CNTR, 0);
+ channel64_writel(dc, CSR, 0xffffffff);
+ if (ds) {
+ if (ds->tx_reg) {
+ sai = ds->reg_width;
+ dai = 0;
+ } else {
+ sai = 0;
+ dai = ds->reg_width;
+ }
+ } else {
+ sai = 8;
+ dai = 8;
+ }
+ channel64_writel(dc, SAIR, sai);
+ channel64_writel(dc, DAIR, dai);
+ /* All 64-bit DMAC supports SMPCHN */
+ channel64_writel(dc, CCR, dc->ccr);
+ /* Writing a non zero value to CHAR will assert XFACT */
+ channel64_write_CHAR(dc, first->txd.phys);
+ } else {
+ channel32_writel(dc, CNTR, 0);
+ channel32_writel(dc, CSR, 0xffffffff);
+ if (ds) {
+ if (ds->tx_reg) {
+ sai = ds->reg_width;
+ dai = 0;
+ } else {
+ sai = 0;
+ dai = ds->reg_width;
+ }
+ } else {
+ sai = 4;
+ dai = 4;
+ }
+ channel32_writel(dc, SAIR, sai);
+ channel32_writel(dc, DAIR, dai);
+ if (txx9_dma_have_SMPCHN()) {
+ channel32_writel(dc, CCR, dc->ccr);
+ /* Writing a non zero value to CHAR will assert XFACT */
+ channel32_writel(dc, CHAR, first->txd.phys);
+ } else {
+ channel32_writel(dc, CHAR, first->txd.phys);
+ channel32_writel(dc, CCR, dc->ccr);
+ }
+ }
+}
+
+/*----------------------------------------------------------------------*/
+
+static void
+txx9dmac_descriptor_complete(struct txx9dmac_chan *dc,
+ struct txx9dmac_desc *desc)
+{
+ dma_async_tx_callback callback;
+ void *param;
+ struct dma_async_tx_descriptor *txd = &desc->txd;
+ struct txx9dmac_slave *ds = dc->chan.private;
+
+ dev_vdbg(chan2dev(&dc->chan), "descriptor %u %p complete\n",
+ txd->cookie, desc);
+
+ dc->completed = txd->cookie;
+ callback = txd->callback;
+ param = txd->callback_param;
+
+ txx9dmac_sync_desc_for_cpu(dc, desc);
+ list_splice_init(&txd->tx_list, &dc->free_list);
+ list_move(&desc->desc_node, &dc->free_list);
+
+ /*
+ * We use dma_unmap_page() regardless of how the buffers were
+ * mapped before they were submitted...
+ */
+ if (!ds) {
+ dma_addr_t dmaaddr;
+ if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
+ dmaaddr = is_dmac64(dc) ?
+ desc->hwdesc.DAR : desc->hwdesc32.DAR;
+ dma_unmap_page(chan2parent(&dc->chan), dmaaddr,
+ desc->len, DMA_FROM_DEVICE);
+ }
+ if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
+ dmaaddr = is_dmac64(dc) ?
+ desc->hwdesc.SAR : desc->hwdesc32.SAR;
+ dma_unmap_page(chan2parent(&dc->chan), dmaaddr,
+ desc->len, DMA_TO_DEVICE);
+ }
+ }
+
+ /*
+ * The API requires that no submissions are done from a
+ * callback, so we don't need to drop the lock here
+ */
+ if (callback)
+ callback(param);
+ dma_run_dependencies(txd);
+}
+
+static void txx9dmac_dequeue(struct txx9dmac_chan *dc, struct list_head *list)
+{
+ struct txx9dmac_dev *ddev = dc->ddev;
+ struct txx9dmac_desc *desc;
+ struct txx9dmac_desc *prev = NULL;
+
+ BUG_ON(!list_empty(list));
+ do {
+ desc = txx9dmac_first_queued(dc);
+ if (prev) {
+ desc_write_CHAR(dc, prev, desc->txd.phys);
+ dma_sync_single_for_device(chan2parent(&dc->chan),
+ prev->txd.phys, ddev->descsize,
+ DMA_TO_DEVICE);
+ }
+ prev = txx9dmac_last_child(desc);
+ list_move_tail(&desc->desc_node, list);
+ /* Make chain-completion interrupt happen */
+ if ((desc->txd.flags & DMA_PREP_INTERRUPT) &&
+ !txx9dmac_chan_INTENT(dc))
+ break;
+ } while (!list_empty(&dc->queue));
+}
+
+static void txx9dmac_complete_all(struct txx9dmac_chan *dc)
+{
+ struct txx9dmac_desc *desc, *_desc;
+ LIST_HEAD(list);
+
+ /*
+ * Submit queued descriptors ASAP, i.e. before we go through
+ * the completed ones.
+ */
+ list_splice_init(&dc->active_list, &list);
+ if (!list_empty(&dc->queue)) {
+ txx9dmac_dequeue(dc, &dc->active_list);
+ txx9dmac_dostart(dc, txx9dmac_first_active(dc));
+ }
+
+ list_for_each_entry_safe(desc, _desc, &list, desc_node)
+ txx9dmac_descriptor_complete(dc, desc);
+}
+
+static void txx9dmac_dump_desc(struct txx9dmac_chan *dc,
+ struct txx9dmac_hwdesc *desc)
+{
+ if (is_dmac64(dc)) {
+#ifdef TXX9_DMA_USE_SIMPLE_CHAIN
+ dev_crit(chan2dev(&dc->chan),
+ " desc: ch%#llx s%#llx d%#llx c%#x\n",
+ (u64)desc->CHAR, desc->SAR, desc->DAR, desc->CNTR);
+#else
+ dev_crit(chan2dev(&dc->chan),
+ " desc: ch%#llx s%#llx d%#llx c%#x"
+ " si%#x di%#x cc%#x cs%#x\n",
+ (u64)desc->CHAR, desc->SAR, desc->DAR, desc->CNTR,
+ desc->SAIR, desc->DAIR, desc->CCR, desc->CSR);
+#endif
+ } else {
+ struct txx9dmac_hwdesc32 *d = (struct txx9dmac_hwdesc32 *)desc;
+#ifdef TXX9_DMA_USE_SIMPLE_CHAIN
+ dev_crit(chan2dev(&dc->chan),
+ " desc: ch%#x s%#x d%#x c%#x\n",
+ d->CHAR, d->SAR, d->DAR, d->CNTR);
+#else
+ dev_crit(chan2dev(&dc->chan),
+ " desc: ch%#x s%#x d%#x c%#x"
+ " si%#x di%#x cc%#x cs%#x\n",
+ d->CHAR, d->SAR, d->DAR, d->CNTR,
+ d->SAIR, d->DAIR, d->CCR, d->CSR);
+#endif
+ }
+}
+
+static void txx9dmac_handle_error(struct txx9dmac_chan *dc, u32 csr)
+{
+ struct txx9dmac_desc *bad_desc;
+ struct txx9dmac_desc *child;
+ u32 errors;
+
+ /*
+ * The descriptor currently at the head of the active list is
+ * borked. Since we don't have any way to report errors, we'll
+ * just have to scream loudly and try to carry on.
+ */
+ dev_crit(chan2dev(&dc->chan), "Abnormal Chain Completion\n");
+ txx9dmac_dump_regs(dc);
+
+ bad_desc = txx9dmac_first_active(dc);
+ list_del_init(&bad_desc->desc_node);
+
+ /* Clear all error flags and try to restart the controller */
+ errors = csr & (TXX9_DMA_CSR_ABCHC |
+ TXX9_DMA_CSR_CFERR | TXX9_DMA_CSR_CHERR |
+ TXX9_DMA_CSR_DESERR | TXX9_DMA_CSR_SORERR);
+ channel_writel(dc, CSR, errors);
+
+ if (list_empty(&dc->active_list) && !list_empty(&dc->queue))
+ txx9dmac_dequeue(dc, &dc->active_list);
+ if (!list_empty(&dc->active_list))
+ txx9dmac_dostart(dc, txx9dmac_first_active(dc));
+
+ dev_crit(chan2dev(&dc->chan),
+ "Bad descriptor submitted for DMA! (cookie: %d)\n",
+ bad_desc->txd.cookie);
+ txx9dmac_dump_desc(dc, &bad_desc->hwdesc);
+ list_for_each_entry(child, &bad_desc->txd.tx_list, desc_node)
+ txx9dmac_dump_desc(dc, &child->hwdesc);
+ /* Pretend the descriptor completed successfully */
+ txx9dmac_descriptor_complete(dc, bad_desc);
+}
+
+static void txx9dmac_scan_descriptors(struct txx9dmac_chan *dc)
+{
+ dma_addr_t chain;
+ struct txx9dmac_desc *desc, *_desc;
+ struct txx9dmac_desc *child;
+ u32 csr;
+
+ if (is_dmac64(dc)) {
+ chain = channel64_read_CHAR(dc);
+ csr = channel64_readl(dc, CSR);
+ channel64_writel(dc, CSR, csr);
+ } else {
+ chain = channel32_readl(dc, CHAR);
+ csr = channel32_readl(dc, CSR);
+ channel32_writel(dc, CSR, csr);
+ }
+ /* For dynamic chain, we should look at XFACT instead of NCHNC */
+ if (!(csr & (TXX9_DMA_CSR_XFACT | TXX9_DMA_CSR_ABCHC))) {
+ /* Everything we've submitted is done */
+ txx9dmac_complete_all(dc);
+ return;
+ }
+ if (!(csr & TXX9_DMA_CSR_CHNEN))
+ chain = 0; /* last descriptor of this chain */
+
+ dev_vdbg(chan2dev(&dc->chan), "scan_descriptors: char=%#llx\n",
+ (u64)chain);
+
+ list_for_each_entry_safe(desc, _desc, &dc->active_list, desc_node) {
+ if (desc_read_CHAR(dc, desc) == chain) {
+ /* This one is currently in progress */
+ if (csr & TXX9_DMA_CSR_ABCHC)
+ goto scan_done;
+ return;
+ }
+
+ list_for_each_entry(child, &desc->txd.tx_list, desc_node)
+ if (desc_read_CHAR(dc, child) == chain) {
+ /* Currently in progress */
+ if (csr & TXX9_DMA_CSR_ABCHC)
+ goto scan_done;
+ return;
+ }
+
+ /*
+ * No descriptors so far seem to be in progress, i.e.
+ * this one must be done.
+ */
+ txx9dmac_descriptor_complete(dc, desc);
+ }
+scan_done:
+ if (csr & TXX9_DMA_CSR_ABCHC) {
+ txx9dmac_handle_error(dc, csr);
+ return;
+ }
+
+ dev_err(chan2dev(&dc->chan),
+ "BUG: All descriptors done, but channel not idle!\n");
+
+ /* Try to continue after resetting the channel... */
+ txx9dmac_reset_chan(dc);
+
+ if (!list_empty(&dc->queue)) {
+ txx9dmac_dequeue(dc, &dc->active_list);
+ txx9dmac_dostart(dc, txx9dmac_first_active(dc));
+ }
+}
+
+static void txx9dmac_chan_tasklet(unsigned long data)
+{
+ int irq;
+ u32 csr;
+ struct txx9dmac_chan *dc;
+
+ dc = (struct txx9dmac_chan *)data;
+ csr = channel_readl(dc, CSR);
+ dev_vdbg(chan2dev(&dc->chan), "tasklet: status=%x\n", csr);
+
+ spin_lock(&dc->lock);
+ if (csr & (TXX9_DMA_CSR_ABCHC | TXX9_DMA_CSR_NCHNC |
+ TXX9_DMA_CSR_NTRNFC))
+ txx9dmac_scan_descriptors(dc);
+ spin_unlock(&dc->lock);
+ irq = dc->irq;
+
+ enable_irq(irq);
+}
+
+static irqreturn_t txx9dmac_chan_interrupt(int irq, void *dev_id)
+{
+ struct txx9dmac_chan *dc = dev_id;
+
+ dev_vdbg(chan2dev(&dc->chan), "interrupt: status=%#x\n",
+ channel_readl(dc, CSR));
+
+ tasklet_schedule(&dc->tasklet);
+ /*
+ * Just disable the interrupts. We'll turn them back on in the
+ * softirq handler.
+ */
+ disable_irq_nosync(irq);
+
+ return IRQ_HANDLED;
+}
+
+static void txx9dmac_tasklet(unsigned long data)
+{
+ int irq;
+ u32 csr;
+ struct txx9dmac_chan *dc;
+
+ struct txx9dmac_dev *ddev = (struct txx9dmac_dev *)data;
+ u32 mcr;
+ int i;
+
+ mcr = dma_readl(ddev, MCR);
+ dev_vdbg(ddev->chan[0]->dma.dev, "tasklet: mcr=%x\n", mcr);
+ for (i = 0; i < TXX9_DMA_MAX_NR_CHANNELS; i++) {
+ if ((mcr >> (24 + i)) & 0x11) {
+ dc = ddev->chan[i];
+ csr = channel_readl(dc, CSR);
+ dev_vdbg(chan2dev(&dc->chan), "tasklet: status=%x\n",
+ csr);
+ spin_lock(&dc->lock);
+ if (csr & (TXX9_DMA_CSR_ABCHC | TXX9_DMA_CSR_NCHNC |
+ TXX9_DMA_CSR_NTRNFC))
+ txx9dmac_scan_descriptors(dc);
+ spin_unlock(&dc->lock);
+ }
+ }
+ irq = ddev->irq;
+
+ enable_irq(irq);
+}
+
+static irqreturn_t txx9dmac_interrupt(int irq, void *dev_id)
+{
+ struct txx9dmac_dev *ddev = dev_id;
+
+ dev_vdbg(ddev->chan[0]->dma.dev, "interrupt: status=%#x\n",
+ dma_readl(ddev, MCR));
+
+ tasklet_schedule(&ddev->tasklet);
+ /*
+ * Just disable the interrupts. We'll turn them back on in the
+ * softirq handler.
+ */
+ disable_irq_nosync(irq);
+
+ return IRQ_HANDLED;
+}
+
+/*----------------------------------------------------------------------*/
+
+static dma_cookie_t txx9dmac_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+ struct txx9dmac_desc *desc = txd_to_txx9dmac_desc(tx);
+ struct txx9dmac_chan *dc = to_txx9dmac_chan(tx->chan);
+ dma_cookie_t cookie;
+
+ spin_lock_bh(&dc->lock);
+ cookie = txx9dmac_assign_cookie(dc, desc);
+
+ dev_vdbg(chan2dev(tx->chan), "tx_submit: queued %u %p\n",
+ desc->txd.cookie, desc);
+
+ list_add_tail(&desc->desc_node, &dc->queue);
+ spin_unlock_bh(&dc->lock);
+
+ return cookie;
+}
+
+static struct dma_async_tx_descriptor *
+txx9dmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+ size_t len, unsigned long flags)
+{
+ struct txx9dmac_chan *dc = to_txx9dmac_chan(chan);
+ struct txx9dmac_dev *ddev = dc->ddev;
+ struct txx9dmac_desc *desc;
+ struct txx9dmac_desc *first;
+ struct txx9dmac_desc *prev;
+ size_t xfer_count;
+ size_t offset;
+
+ dev_vdbg(chan2dev(chan), "prep_dma_memcpy d%#llx s%#llx l%#zx f%#lx\n",
+ (u64)dest, (u64)src, len, flags);
+
+ if (unlikely(!len)) {
+ dev_dbg(chan2dev(chan), "prep_dma_memcpy: length is zero!\n");
+ return NULL;
+ }
+
+ prev = first = NULL;
+
+ for (offset = 0; offset < len; offset += xfer_count) {
+ xfer_count = min_t(size_t, len - offset, TXX9_DMA_MAX_COUNT);
+ /*
+ * Workaround for ERT-TX49H2-033, ERT-TX49H3-020,
+ * ERT-TX49H4-016 (slightly conservative)
+ */
+ if (__is_dmac64(ddev)) {
+ if (xfer_count > 0x100 &&
+ (xfer_count & 0xff) >= 0xfa &&
+ (xfer_count & 0xff) <= 0xff)
+ xfer_count -= 0x20;
+ } else {
+ if (xfer_count > 0x80 &&
+ (xfer_count & 0x7f) >= 0x7e &&
+ (xfer_count & 0x7f) <= 0x7f)
+ xfer_count -= 0x20;
+ }
+
+ desc = txx9dmac_desc_get(dc);
+ if (!desc) {
+ txx9dmac_desc_put(dc, first);
+ return NULL;
+ }
+
+ if (__is_dmac64(ddev)) {
+ desc->hwdesc.SAR = src + offset;
+ desc->hwdesc.DAR = dest + offset;
+ desc->hwdesc.CNTR = xfer_count;
+ txx9dmac_desc_set_nosimple(ddev, desc, 8, 8,
+ dc->ccr | TXX9_DMA_CCR_XFACT);
+ } else {
+ desc->hwdesc32.SAR = src + offset;
+ desc->hwdesc32.DAR = dest + offset;
+ desc->hwdesc32.CNTR = xfer_count;
+ txx9dmac_desc_set_nosimple(ddev, desc, 4, 4,
+ dc->ccr | TXX9_DMA_CCR_XFACT);
+ }
+
+ /*
+ * The descriptors on tx_list are not reachable from
+ * the dc->queue list or dc->active_list after a
+ * submit. If we put all descriptors on active_list,
+ * calling of callback on the completion will be more
+ * complex.
+ */
+ if (!first) {
+ first = desc;
+ } else {
+ desc_write_CHAR(dc, prev, desc->txd.phys);
+ dma_sync_single_for_device(chan2parent(&dc->chan),
+ prev->txd.phys, ddev->descsize,
+ DMA_TO_DEVICE);
+ list_add_tail(&desc->desc_node,
+ &first->txd.tx_list);
+ }
+ prev = desc;
+ }
+
+ /* Trigger interrupt after last block */
+ if (flags & DMA_PREP_INTERRUPT)
+ txx9dmac_desc_set_INTENT(ddev, prev);
+
+ desc_write_CHAR(dc, prev, 0);
+ dma_sync_single_for_device(chan2parent(&dc->chan),
+ prev->txd.phys, ddev->descsize,
+ DMA_TO_DEVICE);
+
+ first->txd.flags = flags;
+ first->len = len;
+
+ return &first->txd;
+}
+
+static struct dma_async_tx_descriptor *
+txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sg_len, enum dma_data_direction direction,
+ unsigned long flags)
+{
+ struct txx9dmac_chan *dc = to_txx9dmac_chan(chan);
+ struct txx9dmac_dev *ddev = dc->ddev;
+ struct txx9dmac_slave *ds = chan->private;
+ struct txx9dmac_desc *prev;
+ struct txx9dmac_desc *first;
+ unsigned int i;
+ struct scatterlist *sg;
+
+ dev_vdbg(chan2dev(chan), "prep_dma_slave\n");
+
+ BUG_ON(!ds || !ds->reg_width);
+ if (ds->tx_reg)
+ BUG_ON(direction != DMA_TO_DEVICE);
+ else
+ BUG_ON(direction != DMA_FROM_DEVICE);
+ if (unlikely(!sg_len))
+ return NULL;
+
+ prev = first = NULL;
+
+ for_each_sg(sgl, sg, sg_len, i) {
+ struct txx9dmac_desc *desc;
+ dma_addr_t mem;
+ u32 sai, dai;
+
+ desc = txx9dmac_desc_get(dc);
+ if (!desc) {
+ txx9dmac_desc_put(dc, first);
+ return NULL;
+ }
+
+ mem = sg_dma_address(sg);
+
+ if (__is_dmac64(ddev)) {
+ if (direction == DMA_TO_DEVICE) {
+ desc->hwdesc.SAR = mem;
+ desc->hwdesc.DAR = ds->tx_reg;
+ } else {
+ desc->hwdesc.SAR = ds->rx_reg;
+ desc->hwdesc.DAR = mem;
+ }
+ desc->hwdesc.CNTR = sg_dma_len(sg);
+ } else {
+ if (direction == DMA_TO_DEVICE) {
+ desc->hwdesc32.SAR = mem;
+ desc->hwdesc32.DAR = ds->tx_reg;
+ } else {
+ desc->hwdesc32.SAR = ds->rx_reg;
+ desc->hwdesc32.DAR = mem;
+ }
+ desc->hwdesc32.CNTR = sg_dma_len(sg);
+ }
+ if (direction == DMA_TO_DEVICE) {
+ sai = ds->reg_width;
+ dai = 0;
+ } else {
+ sai = 0;
+ dai = ds->reg_width;
+ }
+ txx9dmac_desc_set_nosimple(ddev, desc, sai, dai,
+ dc->ccr | TXX9_DMA_CCR_XFACT);
+
+ if (!first) {
+ first = desc;
+ } else {
+ desc_write_CHAR(dc, prev, desc->txd.phys);
+ dma_sync_single_for_device(chan2parent(&dc->chan),
+ prev->txd.phys,
+ ddev->descsize,
+ DMA_TO_DEVICE);
+ list_add_tail(&desc->desc_node,
+ &first->txd.tx_list);
+ }
+ prev = desc;
+ }
+
+ /* Trigger interrupt after last block */
+ if (flags & DMA_PREP_INTERRUPT)
+ txx9dmac_desc_set_INTENT(ddev, prev);
+
+ desc_write_CHAR(dc, prev, 0);
+ dma_sync_single_for_device(chan2parent(&dc->chan),
+ prev->txd.phys, ddev->descsize,
+ DMA_TO_DEVICE);
+
+ first->txd.flags = flags;
+ first->len = 0;
+
+ return &first->txd;
+}
+
+static void txx9dmac_terminate_all(struct dma_chan *chan)
+{
+ struct txx9dmac_chan *dc = to_txx9dmac_chan(chan);
+ struct txx9dmac_desc *desc, *_desc;
+ LIST_HEAD(list);
+
+ dev_vdbg(chan2dev(chan), "terminate_all\n");
+ spin_lock_bh(&dc->lock);
+
+ txx9dmac_reset_chan(dc);
+
+ /* active_list entries will end up before queued entries */
+ list_splice_init(&dc->queue, &list);
+ list_splice_init(&dc->active_list, &list);
+
+ spin_unlock_bh(&dc->lock);
+
+ /* Flush all pending and queued descriptors */
+ list_for_each_entry_safe(desc, _desc, &list, desc_node)
+ txx9dmac_descriptor_complete(dc, desc);
+}
+
+static enum dma_status
+txx9dmac_is_tx_complete(struct dma_chan *chan,
+ dma_cookie_t cookie,
+ dma_cookie_t *done, dma_cookie_t *used)
+{
+ struct txx9dmac_chan *dc = to_txx9dmac_chan(chan);
+ dma_cookie_t last_used;
+ dma_cookie_t last_complete;
+ int ret;
+
+ last_complete = dc->completed;
+ last_used = chan->cookie;
+
+ ret = dma_async_is_complete(cookie, last_complete, last_used);
+ if (ret != DMA_SUCCESS) {
+ spin_lock_bh(&dc->lock);
+ txx9dmac_scan_descriptors(dc);
+ spin_unlock_bh(&dc->lock);
+
+ last_complete = dc->completed;
+ last_used = chan->cookie;
+
+ ret = dma_async_is_complete(cookie, last_complete, last_used);
+ }
+
+ if (done)
+ *done = last_complete;
+ if (used)
+ *used = last_used;
+
+ return ret;
+}
+
+static void txx9dmac_chain_dynamic(struct txx9dmac_chan *dc,
+ struct txx9dmac_desc *prev)
+{
+ struct txx9dmac_dev *ddev = dc->ddev;
+ struct txx9dmac_desc *desc;
+ LIST_HEAD(list);
+
+ prev = txx9dmac_last_child(prev);
+ txx9dmac_dequeue(dc, &list);
+ desc = list_entry(list.next, struct txx9dmac_desc, desc_node);
+ desc_write_CHAR(dc, prev, desc->txd.phys);
+ dma_sync_single_for_device(chan2parent(&dc->chan),
+ prev->txd.phys, ddev->descsize,
+ DMA_TO_DEVICE);
+ mmiowb();
+ if (!(channel_readl(dc, CSR) & TXX9_DMA_CSR_CHNEN) &&
+ channel_read_CHAR(dc) == prev->txd.phys)
+ /* Restart chain DMA */
+ channel_write_CHAR(dc, desc->txd.phys);
+ list_splice_tail(&list, &dc->active_list);
+}
+
+static void txx9dmac_issue_pending(struct dma_chan *chan)
+{
+ struct txx9dmac_chan *dc = to_txx9dmac_chan(chan);
+
+ spin_lock_bh(&dc->lock);
+
+ if (!list_empty(&dc->active_list))
+ txx9dmac_scan_descriptors(dc);
+ if (!list_empty(&dc->queue)) {
+ if (list_empty(&dc->active_list)) {
+ txx9dmac_dequeue(dc, &dc->active_list);
+ txx9dmac_dostart(dc, txx9dmac_first_active(dc));
+ } else if (txx9_dma_have_SMPCHN()) {
+ struct txx9dmac_desc *prev = txx9dmac_last_active(dc);
+
+ if (!(prev->txd.flags & DMA_PREP_INTERRUPT) ||
+ txx9dmac_chan_INTENT(dc))
+ txx9dmac_chain_dynamic(dc, prev);
+ }
+ }
+
+ spin_unlock_bh(&dc->lock);
+}
+
+static int txx9dmac_alloc_chan_resources(struct dma_chan *chan)
+{
+ struct txx9dmac_chan *dc = to_txx9dmac_chan(chan);
+ struct txx9dmac_slave *ds = chan->private;
+ struct txx9dmac_desc *desc;
+ int i;
+
+ dev_vdbg(chan2dev(chan), "alloc_chan_resources\n");
+
+ /* ASSERT: channel is idle */
+ if (channel_readl(dc, CSR) & TXX9_DMA_CSR_XFACT) {
+ dev_dbg(chan2dev(chan), "DMA channel not idle?\n");
+ return -EIO;
+ }
+
+ dc->completed = chan->cookie = 1;
+
+ dc->ccr = TXX9_DMA_CCR_IMMCHN | TXX9_DMA_CCR_INTENE | CCR_LE;
+ txx9dmac_chan_set_SMPCHN(dc);
+ if (!txx9_dma_have_SMPCHN() || (dc->ccr & TXX9_DMA_CCR_SMPCHN))
+ dc->ccr |= TXX9_DMA_CCR_INTENC;
+ if (chan->device->device_prep_dma_memcpy) {
+ if (ds)
+ return -EINVAL;
+ dc->ccr |= TXX9_DMA_CCR_XFSZ_X8;
+ } else {
+ if (!ds ||
+ (ds->tx_reg && ds->rx_reg) || (!ds->tx_reg && !ds->rx_reg))
+ return -EINVAL;
+ dc->ccr |= TXX9_DMA_CCR_EXTRQ |
+ TXX9_DMA_CCR_XFSZ(__ffs(ds->reg_width));
+ txx9dmac_chan_set_INTENT(dc);
+ }
+
+ spin_lock_bh(&dc->lock);
+ i = dc->descs_allocated;
+ while (dc->descs_allocated < TXX9_DMA_INITIAL_DESC_COUNT) {
+ spin_unlock_bh(&dc->lock);
+
+ desc = txx9dmac_desc_alloc(dc, GFP_KERNEL);
+ if (!desc) {
+ dev_info(chan2dev(chan),
+ "only allocated %d descriptors\n", i);
+ spin_lock_bh(&dc->lock);
+ break;
+ }
+ txx9dmac_desc_put(dc, desc);
+
+ spin_lock_bh(&dc->lock);
+ i = ++dc->descs_allocated;
+ }
+ spin_unlock_bh(&dc->lock);
+
+ dev_dbg(chan2dev(chan),
+ "alloc_chan_resources allocated %d descriptors\n", i);
+
+ return i;
+}
+
+static void txx9dmac_free_chan_resources(struct dma_chan *chan)
+{
+ struct txx9dmac_chan *dc = to_txx9dmac_chan(chan);
+ struct txx9dmac_dev *ddev = dc->ddev;
+ struct txx9dmac_desc *desc, *_desc;
+ LIST_HEAD(list);
+
+ dev_dbg(chan2dev(chan), "free_chan_resources (descs allocated=%u)\n",
+ dc->descs_allocated);
+
+ /* ASSERT: channel is idle */
+ BUG_ON(!list_empty(&dc->active_list));
+ BUG_ON(!list_empty(&dc->queue));
+ BUG_ON(channel_readl(dc, CSR) & TXX9_DMA_CSR_XFACT);
+
+ spin_lock_bh(&dc->lock);
+ list_splice_init(&dc->free_list, &list);
+ dc->descs_allocated = 0;
+ spin_unlock_bh(&dc->lock);
+
+ list_for_each_entry_safe(desc, _desc, &list, desc_node) {
+ dev_vdbg(chan2dev(chan), " freeing descriptor %p\n", desc);
+ dma_unmap_single(chan2parent(chan), desc->txd.phys,
+ ddev->descsize, DMA_TO_DEVICE);
+ kfree(desc);
+ }
+
+ dev_vdbg(chan2dev(chan), "free_chan_resources done\n");
+}
+
+/*----------------------------------------------------------------------*/
+
+static void txx9dmac_off(struct txx9dmac_dev *ddev)
+{
+ dma_writel(ddev, MCR, 0);
+ mmiowb();
+}
+
+static int __init txx9dmac_chan_probe(struct platform_device *pdev)
+{
+ struct txx9dmac_chan_platform_data *cpdata = pdev->dev.platform_data;
+ struct platform_device *dmac_dev = cpdata->dmac_dev;
+ struct txx9dmac_platform_data *pdata = dmac_dev->dev.platform_data;
+ struct txx9dmac_chan *dc;
+ int err;
+ int ch = pdev->id % TXX9_DMA_MAX_NR_CHANNELS;
+ int irq;
+
+ dc = devm_kzalloc(&pdev->dev, sizeof(*dc), GFP_KERNEL);
+ if (!dc)
+ return -ENOMEM;
+
+ dc->dma.dev = &pdev->dev;
+ dc->dma.device_alloc_chan_resources = txx9dmac_alloc_chan_resources;
+ dc->dma.device_free_chan_resources = txx9dmac_free_chan_resources;
+ dc->dma.device_terminate_all = txx9dmac_terminate_all;
+ dc->dma.device_is_tx_complete = txx9dmac_is_tx_complete;
+ dc->dma.device_issue_pending = txx9dmac_issue_pending;
+ if (pdata && pdata->memcpy_chan == ch) {
+ dc->dma.device_prep_dma_memcpy = txx9dmac_prep_dma_memcpy;
+ dma_cap_set(DMA_MEMCPY, dc->dma.cap_mask);
+ } else {
+ dc->dma.device_prep_slave_sg = txx9dmac_prep_slave_sg;
+ dma_cap_set(DMA_SLAVE, dc->dma.cap_mask);
+ dma_cap_set(DMA_PRIVATE, dc->dma.cap_mask);
+ }
+
+ INIT_LIST_HEAD(&dc->dma.channels);
+ dc->ddev = platform_get_drvdata(dmac_dev);
+ if (dc->ddev->irq < 0) {
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+ tasklet_init(&dc->tasklet, txx9dmac_chan_tasklet,
+ (unsigned long)dc);
+ dc->irq = irq;
+ err = devm_request_irq(&pdev->dev, dc->irq,
+ txx9dmac_chan_interrupt, 0, dev_name(&pdev->dev), dc);
+ if (err)
+ return err;
+ } else
+ dc->irq = -1;
+ dc->ddev->chan[ch] = dc;
+ dc->chan.device = &dc->dma;
+ list_add_tail(&dc->chan.device_node, &dc->chan.device->channels);
+ dc->chan.cookie = dc->completed = 1;
+
+ if (is_dmac64(dc))
+ dc->ch_regs = &__txx9dmac_regs(dc->ddev)->CHAN[ch];
+ else
+ dc->ch_regs = &__txx9dmac_regs32(dc->ddev)->CHAN[ch];
+ spin_lock_init(&dc->lock);
+
+ INIT_LIST_HEAD(&dc->active_list);
+ INIT_LIST_HEAD(&dc->queue);
+ INIT_LIST_HEAD(&dc->free_list);
+
+ txx9dmac_reset_chan(dc);
+
+ platform_set_drvdata(pdev, dc);
+
+ err = dma_async_device_register(&dc->dma);
+ if (err)
+ return err;
+ dev_dbg(&pdev->dev, "TXx9 DMA Channel (dma%d%s%s)\n",
+ dc->dma.dev_id,
+ dma_has_cap(DMA_MEMCPY, dc->dma.cap_mask) ? " memcpy" : "",
+ dma_has_cap(DMA_SLAVE, dc->dma.cap_mask) ? " slave" : "");
+
+ return 0;
+}
+
+static int __exit txx9dmac_chan_remove(struct platform_device *pdev)
+{
+ struct txx9dmac_chan *dc = platform_get_drvdata(pdev);
+
+ dma_async_device_unregister(&dc->dma);
+ if (dc->irq >= 0)
+ tasklet_kill(&dc->tasklet);
+ dc->ddev->chan[pdev->id % TXX9_DMA_MAX_NR_CHANNELS] = NULL;
+ return 0;
+}
+
+static int __init txx9dmac_probe(struct platform_device *pdev)
+{
+ struct txx9dmac_platform_data *pdata = pdev->dev.platform_data;
+ struct resource *io;
+ struct txx9dmac_dev *ddev;
+ u32 mcr;
+ int err;
+
+ io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!io)
+ return -EINVAL;
+
+ ddev = devm_kzalloc(&pdev->dev, sizeof(*ddev), GFP_KERNEL);
+ if (!ddev)
+ return -ENOMEM;
+
+ if (!devm_request_mem_region(&pdev->dev, io->start, resource_size(io),
+ dev_name(&pdev->dev)))
+ return -EBUSY;
+
+ ddev->regs = devm_ioremap(&pdev->dev, io->start, resource_size(io));
+ if (!ddev->regs)
+ return -ENOMEM;
+ ddev->have_64bit_regs = pdata->have_64bit_regs;
+ if (__is_dmac64(ddev))
+ ddev->descsize = sizeof(struct txx9dmac_hwdesc);
+ else
+ ddev->descsize = sizeof(struct txx9dmac_hwdesc32);
+
+ /* force dma off, just in case */
+ txx9dmac_off(ddev);
+
+ ddev->irq = platform_get_irq(pdev, 0);
+ if (ddev->irq >= 0) {
+ tasklet_init(&ddev->tasklet, txx9dmac_tasklet,
+ (unsigned long)ddev);
+ err = devm_request_irq(&pdev->dev, ddev->irq,
+ txx9dmac_interrupt, 0, dev_name(&pdev->dev), ddev);
+ if (err)
+ return err;
+ }
+
+ mcr = TXX9_DMA_MCR_MSTEN | MCR_LE;
+ if (pdata && pdata->memcpy_chan >= 0)
+ mcr |= TXX9_DMA_MCR_FIFUM(pdata->memcpy_chan);
+ dma_writel(ddev, MCR, mcr);
+
+ platform_set_drvdata(pdev, ddev);
+ return 0;
+}
+
+static int __exit txx9dmac_remove(struct platform_device *pdev)
+{
+ struct txx9dmac_dev *ddev = platform_get_drvdata(pdev);
+
+ txx9dmac_off(ddev);
+ if (ddev->irq >= 0)
+ tasklet_kill(&ddev->tasklet);
+ return 0;
+}
+
+static void txx9dmac_shutdown(struct platform_device *pdev)
+{
+ struct txx9dmac_dev *ddev = platform_get_drvdata(pdev);
+
+ txx9dmac_off(ddev);
+}
+
+static int txx9dmac_suspend_late(struct platform_device *pdev,
+ pm_message_t mesg)
+{
+ struct txx9dmac_dev *ddev = platform_get_drvdata(pdev);
+
+ txx9dmac_off(ddev);
+ return 0;
+}
+
+static int txx9dmac_resume_early(struct platform_device *pdev)
+{
+ struct txx9dmac_dev *ddev = platform_get_drvdata(pdev);
+ struct txx9dmac_platform_data *pdata = pdev->dev.platform_data;
+ u32 mcr;
+
+ mcr = TXX9_DMA_MCR_MSTEN | MCR_LE;
+ if (pdata && pdata->memcpy_chan >= 0)
+ mcr |= TXX9_DMA_MCR_FIFUM(pdata->memcpy_chan);
+ dma_writel(ddev, MCR, mcr);
+ return 0;
+
+}
+
+static struct platform_driver txx9dmac_chan_driver = {
+ .remove = __exit_p(txx9dmac_chan_remove),
+ .driver = {
+ .name = "txx9dmac-chan",
+ },
+};
+
+static struct platform_driver txx9dmac_driver = {
+ .remove = __exit_p(txx9dmac_remove),
+ .shutdown = txx9dmac_shutdown,
+ .suspend_late = txx9dmac_suspend_late,
+ .resume_early = txx9dmac_resume_early,
+ .driver = {
+ .name = "txx9dmac",
+ },
+};
+
+static int __init txx9dmac_init(void)
+{
+ int rc;
+
+ rc = platform_driver_probe(&txx9dmac_driver, txx9dmac_probe);
+ if (!rc) {
+ rc = platform_driver_probe(&txx9dmac_chan_driver,
+ txx9dmac_chan_probe);
+ if (rc)
+ platform_driver_unregister(&txx9dmac_driver);
+ }
+ return rc;
+}
+module_init(txx9dmac_init);
+
+static void __exit txx9dmac_exit(void)
+{
+ platform_driver_unregister(&txx9dmac_chan_driver);
+ platform_driver_unregister(&txx9dmac_driver);
+}
+module_exit(txx9dmac_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TXx9 DMA Controller driver");
+MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
diff --git a/drivers/dma/txx9dmac.h b/drivers/dma/txx9dmac.h
new file mode 100644
index 000000000000..c907ff01d276
--- /dev/null
+++ b/drivers/dma/txx9dmac.h
@@ -0,0 +1,307 @@
+/*
+ * Driver for the TXx9 SoC DMA Controller
+ *
+ * Copyright (C) 2009 Atsushi Nemoto
+ *
+ * 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 TXX9DMAC_H
+#define TXX9DMAC_H
+
+#include <linux/dmaengine.h>
+#include <asm/txx9/dmac.h>
+
+/*
+ * Design Notes:
+ *
+ * This DMAC have four channels and one FIFO buffer. Each channel can
+ * be configured for memory-memory or device-memory transfer, but only
+ * one channel can do alignment-free memory-memory transfer at a time
+ * while the channel should occupy the FIFO buffer for effective
+ * transfers.
+ *
+ * Instead of dynamically assign the FIFO buffer to channels, I chose
+ * make one dedicated channel for memory-memory transfer. The
+ * dedicated channel is public. Other channels are private and used
+ * for slave transfer. Some devices in the SoC are wired to certain
+ * DMA channel.
+ */
+
+#ifdef CONFIG_MACH_TX49XX
+static inline bool txx9_dma_have_SMPCHN(void)
+{
+ return true;
+}
+#define TXX9_DMA_USE_SIMPLE_CHAIN
+#else
+static inline bool txx9_dma_have_SMPCHN(void)
+{
+ return false;
+}
+#endif
+
+#ifdef __LITTLE_ENDIAN
+#ifdef CONFIG_MACH_TX49XX
+#define CCR_LE TXX9_DMA_CCR_LE
+#define MCR_LE 0
+#else
+#define CCR_LE 0
+#define MCR_LE TXX9_DMA_MCR_LE
+#endif
+#else
+#define CCR_LE 0
+#define MCR_LE 0
+#endif
+
+/*
+ * Redefine this macro to handle differences between 32- and 64-bit
+ * addressing, big vs. little endian, etc.
+ */
+#ifdef __BIG_ENDIAN
+#define TXX9_DMA_REG32(name) u32 __pad_##name; u32 name
+#else
+#define TXX9_DMA_REG32(name) u32 name; u32 __pad_##name
+#endif
+
+/* Hardware register definitions. */
+struct txx9dmac_cregs {
+#if defined(CONFIG_32BIT) && !defined(CONFIG_64BIT_PHYS_ADDR)
+ TXX9_DMA_REG32(CHAR); /* Chain Address Register */
+#else
+ u64 CHAR; /* Chain Address Register */
+#endif
+ u64 SAR; /* Source Address Register */
+ u64 DAR; /* Destination Address Register */
+ TXX9_DMA_REG32(CNTR); /* Count Register */
+ TXX9_DMA_REG32(SAIR); /* Source Address Increment Register */
+ TXX9_DMA_REG32(DAIR); /* Destination Address Increment Register */
+ TXX9_DMA_REG32(CCR); /* Channel Control Register */
+ TXX9_DMA_REG32(CSR); /* Channel Status Register */
+};
+struct txx9dmac_cregs32 {
+ u32 CHAR;
+ u32 SAR;
+ u32 DAR;
+ u32 CNTR;
+ u32 SAIR;
+ u32 DAIR;
+ u32 CCR;
+ u32 CSR;
+};
+
+struct txx9dmac_regs {
+ /* per-channel registers */
+ struct txx9dmac_cregs CHAN[TXX9_DMA_MAX_NR_CHANNELS];
+ u64 __pad[9];
+ u64 MFDR; /* Memory Fill Data Register */
+ TXX9_DMA_REG32(MCR); /* Master Control Register */
+};
+struct txx9dmac_regs32 {
+ struct txx9dmac_cregs32 CHAN[TXX9_DMA_MAX_NR_CHANNELS];
+ u32 __pad[9];
+ u32 MFDR;
+ u32 MCR;
+};
+
+/* bits for MCR */
+#define TXX9_DMA_MCR_EIS(ch) (0x10000000<<(ch))
+#define TXX9_DMA_MCR_DIS(ch) (0x01000000<<(ch))
+#define TXX9_DMA_MCR_RSFIF 0x00000080
+#define TXX9_DMA_MCR_FIFUM(ch) (0x00000008<<(ch))
+#define TXX9_DMA_MCR_LE 0x00000004
+#define TXX9_DMA_MCR_RPRT 0x00000002
+#define TXX9_DMA_MCR_MSTEN 0x00000001
+
+/* bits for CCRn */
+#define TXX9_DMA_CCR_IMMCHN 0x20000000
+#define TXX9_DMA_CCR_USEXFSZ 0x10000000
+#define TXX9_DMA_CCR_LE 0x08000000
+#define TXX9_DMA_CCR_DBINH 0x04000000
+#define TXX9_DMA_CCR_SBINH 0x02000000
+#define TXX9_DMA_CCR_CHRST 0x01000000
+#define TXX9_DMA_CCR_RVBYTE 0x00800000
+#define TXX9_DMA_CCR_ACKPOL 0x00400000
+#define TXX9_DMA_CCR_REQPL 0x00200000
+#define TXX9_DMA_CCR_EGREQ 0x00100000
+#define TXX9_DMA_CCR_CHDN 0x00080000
+#define TXX9_DMA_CCR_DNCTL 0x00060000
+#define TXX9_DMA_CCR_EXTRQ 0x00010000
+#define TXX9_DMA_CCR_INTRQD 0x0000e000
+#define TXX9_DMA_CCR_INTENE 0x00001000
+#define TXX9_DMA_CCR_INTENC 0x00000800
+#define TXX9_DMA_CCR_INTENT 0x00000400
+#define TXX9_DMA_CCR_CHNEN 0x00000200
+#define TXX9_DMA_CCR_XFACT 0x00000100
+#define TXX9_DMA_CCR_SMPCHN 0x00000020
+#define TXX9_DMA_CCR_XFSZ(order) (((order) << 2) & 0x0000001c)
+#define TXX9_DMA_CCR_XFSZ_1 TXX9_DMA_CCR_XFSZ(0)
+#define TXX9_DMA_CCR_XFSZ_2 TXX9_DMA_CCR_XFSZ(1)
+#define TXX9_DMA_CCR_XFSZ_4 TXX9_DMA_CCR_XFSZ(2)
+#define TXX9_DMA_CCR_XFSZ_8 TXX9_DMA_CCR_XFSZ(3)
+#define TXX9_DMA_CCR_XFSZ_X4 TXX9_DMA_CCR_XFSZ(4)
+#define TXX9_DMA_CCR_XFSZ_X8 TXX9_DMA_CCR_XFSZ(5)
+#define TXX9_DMA_CCR_XFSZ_X16 TXX9_DMA_CCR_XFSZ(6)
+#define TXX9_DMA_CCR_XFSZ_X32 TXX9_DMA_CCR_XFSZ(7)
+#define TXX9_DMA_CCR_MEMIO 0x00000002
+#define TXX9_DMA_CCR_SNGAD 0x00000001
+
+/* bits for CSRn */
+#define TXX9_DMA_CSR_CHNEN 0x00000400
+#define TXX9_DMA_CSR_STLXFER 0x00000200
+#define TXX9_DMA_CSR_XFACT 0x00000100
+#define TXX9_DMA_CSR_ABCHC 0x00000080
+#define TXX9_DMA_CSR_NCHNC 0x00000040
+#define TXX9_DMA_CSR_NTRNFC 0x00000020
+#define TXX9_DMA_CSR_EXTDN 0x00000010
+#define TXX9_DMA_CSR_CFERR 0x00000008
+#define TXX9_DMA_CSR_CHERR 0x00000004
+#define TXX9_DMA_CSR_DESERR 0x00000002
+#define TXX9_DMA_CSR_SORERR 0x00000001
+
+struct txx9dmac_chan {
+ struct dma_chan chan;
+ struct dma_device dma;
+ struct txx9dmac_dev *ddev;
+ void __iomem *ch_regs;
+ struct tasklet_struct tasklet;
+ int irq;
+ u32 ccr;
+
+ spinlock_t lock;
+
+ /* these other elements are all protected by lock */
+ dma_cookie_t completed;
+ struct list_head active_list;
+ struct list_head queue;
+ struct list_head free_list;
+
+ unsigned int descs_allocated;
+};
+
+struct txx9dmac_dev {
+ void __iomem *regs;
+ struct tasklet_struct tasklet;
+ int irq;
+ struct txx9dmac_chan *chan[TXX9_DMA_MAX_NR_CHANNELS];
+ bool have_64bit_regs;
+ unsigned int descsize;
+};
+
+static inline bool __is_dmac64(const struct txx9dmac_dev *ddev)
+{
+ return ddev->have_64bit_regs;
+}
+
+static inline bool is_dmac64(const struct txx9dmac_chan *dc)
+{
+ return __is_dmac64(dc->ddev);
+}
+
+#ifdef TXX9_DMA_USE_SIMPLE_CHAIN
+/* Hardware descriptor definition. (for simple-chain) */
+struct txx9dmac_hwdesc {
+#if defined(CONFIG_32BIT) && !defined(CONFIG_64BIT_PHYS_ADDR)
+ TXX9_DMA_REG32(CHAR);
+#else
+ u64 CHAR;
+#endif
+ u64 SAR;
+ u64 DAR;
+ TXX9_DMA_REG32(CNTR);
+};
+struct txx9dmac_hwdesc32 {
+ u32 CHAR;
+ u32 SAR;
+ u32 DAR;
+ u32 CNTR;
+};
+#else
+#define txx9dmac_hwdesc txx9dmac_cregs
+#define txx9dmac_hwdesc32 txx9dmac_cregs32
+#endif
+
+struct txx9dmac_desc {
+ /* FIRST values the hardware uses */
+ union {
+ struct txx9dmac_hwdesc hwdesc;
+ struct txx9dmac_hwdesc32 hwdesc32;
+ };
+
+ /* THEN values for driver housekeeping */
+ struct list_head desc_node ____cacheline_aligned;
+ struct dma_async_tx_descriptor txd;
+ size_t len;
+};
+
+#ifdef TXX9_DMA_USE_SIMPLE_CHAIN
+
+static inline bool txx9dmac_chan_INTENT(struct txx9dmac_chan *dc)
+{
+ return (dc->ccr & TXX9_DMA_CCR_INTENT) != 0;
+}
+
+static inline void txx9dmac_chan_set_INTENT(struct txx9dmac_chan *dc)
+{
+ dc->ccr |= TXX9_DMA_CCR_INTENT;
+}
+
+static inline void txx9dmac_desc_set_INTENT(struct txx9dmac_dev *ddev,
+ struct txx9dmac_desc *desc)
+{
+}
+
+static inline void txx9dmac_chan_set_SMPCHN(struct txx9dmac_chan *dc)
+{
+ dc->ccr |= TXX9_DMA_CCR_SMPCHN;
+}
+
+static inline void txx9dmac_desc_set_nosimple(struct txx9dmac_dev *ddev,
+ struct txx9dmac_desc *desc,
+ u32 sair, u32 dair, u32 ccr)
+{
+}
+
+#else /* TXX9_DMA_USE_SIMPLE_CHAIN */
+
+static inline bool txx9dmac_chan_INTENT(struct txx9dmac_chan *dc)
+{
+ return true;
+}
+
+static void txx9dmac_chan_set_INTENT(struct txx9dmac_chan *dc)
+{
+}
+
+static inline void txx9dmac_desc_set_INTENT(struct txx9dmac_dev *ddev,
+ struct txx9dmac_desc *desc)
+{
+ if (__is_dmac64(ddev))
+ desc->hwdesc.CCR |= TXX9_DMA_CCR_INTENT;
+ else
+ desc->hwdesc32.CCR |= TXX9_DMA_CCR_INTENT;
+}
+
+static inline void txx9dmac_chan_set_SMPCHN(struct txx9dmac_chan *dc)
+{
+}
+
+static inline void txx9dmac_desc_set_nosimple(struct txx9dmac_dev *ddev,
+ struct txx9dmac_desc *desc,
+ u32 sai, u32 dai, u32 ccr)
+{
+ if (__is_dmac64(ddev)) {
+ desc->hwdesc.SAIR = sai;
+ desc->hwdesc.DAIR = dai;
+ desc->hwdesc.CCR = ccr;
+ } else {
+ desc->hwdesc32.SAIR = sai;
+ desc->hwdesc32.DAIR = dai;
+ desc->hwdesc32.CCR = ccr;
+ }
+}
+
+#endif /* TXX9_DMA_USE_SIMPLE_CHAIN */
+
+#endif /* TXX9DMAC_H */
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c
index facfdb1fa71c..d205d493a68a 100644
--- a/drivers/edac/e752x_edac.c
+++ b/drivers/edac/e752x_edac.c
@@ -1084,7 +1084,7 @@ static void e752x_init_sysbus_parity_mask(struct e752x_pvt *pvt)
struct pci_dev *dev = pvt->dev_d0f1;
int enable = 1;
- /* Allow module paramter override, else see if CPU supports parity */
+ /* Allow module parameter override, else see if CPU supports parity */
if (sysbus_parity != -1) {
enable = sysbus_parity;
} else if (cpu_id[0] &&
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h
index 28f2c3f959b5..6ad95c8d6363 100644
--- a/drivers/edac/edac_core.h
+++ b/drivers/edac/edac_core.h
@@ -767,11 +767,19 @@ static inline void pci_write_bits16(struct pci_dev *pdev, int offset,
pci_write_config_word(pdev, offset, value);
}
-/* write all or some bits in a dword-register*/
+/*
+ * pci_write_bits32
+ *
+ * edac local routine to do pci_write_config_dword, but adds
+ * a mask parameter. If mask is all ones, ignore the mask.
+ * Otherwise utilize the mask to isolate specified bits
+ *
+ * write all or some bits in a dword-register
+ */
static inline void pci_write_bits32(struct pci_dev *pdev, int offset,
u32 value, u32 mask)
{
- if (mask != 0xffff) {
+ if (mask != 0xffffffff) {
u32 buf;
pci_read_config_dword(pdev, offset, &buf);
diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c
index ca9113e1c106..a7d2c717d033 100644
--- a/drivers/edac/edac_device.c
+++ b/drivers/edac/edac_device.c
@@ -389,7 +389,7 @@ static void del_edac_device_from_global_list(struct edac_device_ctl_info
*/
static void edac_device_workq_function(struct work_struct *work_req)
{
- struct delayed_work *d_work = (struct delayed_work *)work_req;
+ struct delayed_work *d_work = to_delayed_work(work_req);
struct edac_device_ctl_info *edac_dev = to_edac_device_ctl_work(d_work);
mutex_lock(&device_ctls_mutex);
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 25d66940b4fa..335b7ebdb11c 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -260,7 +260,7 @@ static int edac_mc_assert_error_check_and_clear(void)
*/
static void edac_mc_workq_function(struct work_struct *work_req)
{
- struct delayed_work *d_work = (struct delayed_work *)work_req;
+ struct delayed_work *d_work = to_delayed_work(work_req);
struct mem_ctl_info *mci = to_edac_mem_ctl_work(d_work);
mutex_lock(&mem_ctls_mutex);
diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c
index 5b150aea703a..30b585b1d60b 100644
--- a/drivers/edac/edac_pci.c
+++ b/drivers/edac/edac_pci.c
@@ -233,7 +233,7 @@ EXPORT_SYMBOL_GPL(edac_pci_find);
*/
static void edac_pci_workq_function(struct work_struct *work_req)
{
- struct delayed_work *d_work = (struct delayed_work *)work_req;
+ struct delayed_work *d_work = to_delayed_work(work_req);
struct edac_pci_ctl_info *pci = to_edac_pci_ctl_work(d_work);
int msec;
unsigned long delay;
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index 4637a4a757df..7c8c2d72916f 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -674,7 +674,7 @@ static void mpc85xx_mc_check(struct mem_ctl_info *mci)
int row_index;
err_detect = in_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT);
- if (err_detect)
+ if (!err_detect)
return;
mpc85xx_mc_printk(mci, KERN_ERR, "Err Detect Register: %#8.8x\n",
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
index 18d65fb42ee7..e8727817c8b5 100644
--- a/drivers/firmware/dcdbas.c
+++ b/drivers/firmware/dcdbas.c
@@ -237,6 +237,23 @@ static ssize_t host_control_on_shutdown_store(struct device *dev,
return count;
}
+static long generate_smi(void *_smi_cmd)
+{
+ struct smi_cmd *smi_cmd = _smi_cmd;
+
+ /* generate SMI */
+ asm volatile (
+ "outb %b0,%w1"
+ : /* no output args */
+ : "a" (smi_cmd->command_code),
+ "d" (smi_cmd->command_address),
+ "b" (smi_cmd->ebx),
+ "c" (smi_cmd->ecx)
+ : "memory"
+ );
+ return 0;
+}
+
/**
* dcdbas_smi_request: generate SMI request
*
@@ -244,9 +261,6 @@ static ssize_t host_control_on_shutdown_store(struct device *dev,
*/
int dcdbas_smi_request(struct smi_cmd *smi_cmd)
{
- cpumask_var_t old_mask;
- int ret = 0;
-
if (smi_cmd->magic != SMI_CMD_MAGIC) {
dev_info(&dcdbas_pdev->dev, "%s: invalid magic value\n",
__func__);
@@ -254,35 +268,8 @@ int dcdbas_smi_request(struct smi_cmd *smi_cmd)
}
/* SMI requires CPU 0 */
- if (!alloc_cpumask_var(&old_mask, GFP_KERNEL))
- return -ENOMEM;
-
- cpumask_copy(old_mask, &current->cpus_allowed);
- set_cpus_allowed_ptr(current, cpumask_of(0));
- if (smp_processor_id() != 0) {
- dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n",
- __func__);
- ret = -EBUSY;
- goto out;
- }
-
- /* generate SMI */
- asm volatile (
- "outb %b0,%w1"
- : /* no output args */
- : "a" (smi_cmd->command_code),
- "d" (smi_cmd->command_address),
- "b" (smi_cmd->ebx),
- "c" (smi_cmd->ecx)
- : "memory"
- );
-
-out:
- set_cpus_allowed_ptr(current, old_mask);
- free_cpumask_var(old_mask);
- return ret;
+ return work_on_cpu(0, generate_smi, smi_cmd);
}
-
/**
* smi_request_store:
*
diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
index 7b7ddc2d51c9..420a96e7f2db 100644
--- a/drivers/firmware/iscsi_ibft.c
+++ b/drivers/firmware/iscsi_ibft.c
@@ -754,11 +754,11 @@ static int __init ibft_check_nic_for(struct ibft_nic *nic, int entry)
rc = 1;
break;
case ibft_eth_ip_addr:
- if (!memcmp(nic->dhcp, nulls, sizeof(nic->dhcp)))
+ if (memcmp(nic->ip_addr, nulls, sizeof(nic->ip_addr)))
rc = 1;
break;
case ibft_eth_subnet_mask:
- if (!memcmp(nic->dhcp, nulls, sizeof(nic->dhcp)))
+ if (nic->subnet_mask_prefix)
rc = 1;
break;
case ibft_eth_origin:
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 3a22eb9be378..f33d25279912 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -83,6 +83,12 @@ config DRM_I915
config DRM_I915_KMS
bool "Enable modesetting on intel by default"
depends on DRM_I915
+ # i915 KMS depends on ACPI_VIDEO when ACPI is enabled
+ # but for select to work, need to select ACPI_VIDEO's dependencies, ick
+ select VIDEO_OUTPUT_CONTROL if ACPI
+ select BACKLIGHT_CLASS_DEVICE if ACPI
+ select INPUT if ACPI
+ select ACPI_VIDEO if ACPI
help
Choose this option if you want kernel modesetting enabled by default,
and you have a new enough userspace to support this. Running old
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index a04639dc633d..45890447feec 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -561,7 +561,6 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
int saved_x, saved_y;
struct drm_encoder *encoder;
bool ret = true;
- bool depth_changed, bpp_changed;
adjusted_mode = drm_mode_duplicate(dev, mode);
@@ -570,15 +569,6 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
if (!crtc->enabled)
return true;
- if (old_fb && crtc->fb) {
- depth_changed = (old_fb->depth != crtc->fb->depth);
- bpp_changed = (old_fb->bits_per_pixel !=
- crtc->fb->bits_per_pixel);
- } else {
- depth_changed = true;
- bpp_changed = true;
- }
-
saved_mode = crtc->mode;
saved_x = crtc->x;
saved_y = crtc->y;
@@ -590,15 +580,6 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
crtc->x = x;
crtc->y = y;
- if (drm_mode_equal(&saved_mode, &crtc->mode)) {
- if (saved_x != crtc->x || saved_y != crtc->y ||
- depth_changed || bpp_changed) {
- ret = !crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y,
- old_fb);
- goto done;
- }
- }
-
/* Pass our mode to the connectors and the CRTC to give them a chance to
* adjust it according to limitations or connector properties, and also
* a chance to reject the mode entirely.
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index c4ada8b6295b..f01def16a669 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -456,7 +456,8 @@ int drm_ioctl(struct inode *inode, struct file *filp,
retcode = -EINVAL;
} else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) ||
((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) ||
- ((ioctl->flags & DRM_MASTER) && !file_priv->is_master)) {
+ ((ioctl->flags & DRM_MASTER) && !file_priv->is_master) ||
+ (!(ioctl->flags & DRM_CONTROL_ALLOW) && (file_priv->minor->type == DRM_MINOR_CONTROL))) {
retcode = -EACCES;
} else {
if (cmd & (IOC_IN | IOC_OUT)) {
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index d009661781bc..b9631e3a1ea6 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -159,6 +159,9 @@ void drm_master_put(struct drm_master **master)
int drm_setmaster_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
+ if (file_priv->is_master)
+ return 0;
+
if (file_priv->minor->master && file_priv->minor->master != file_priv->master)
return -EINVAL;
@@ -169,6 +172,7 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
file_priv->minor->master != file_priv->master) {
mutex_lock(&dev->struct_mutex);
file_priv->minor->master = drm_master_get(file_priv->master);
+ file_priv->is_master = 1;
mutex_unlock(&dev->struct_mutex);
}
@@ -178,10 +182,15 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- if (!file_priv->master)
+ if (!file_priv->is_master)
+ return -EINVAL;
+
+ if (!file_priv->minor->master)
return -EINVAL;
+
mutex_lock(&dev->struct_mutex);
drm_master_put(&file_priv->minor->master);
+ file_priv->is_master = 0;
mutex_unlock(&dev->struct_mutex);
return 0;
}
@@ -393,14 +402,14 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
if (dev->driver->load) {
ret = dev->driver->load(dev, ent->driver_data);
if (ret)
- goto err_g3;
+ goto err_g4;
}
/* setup the grouping for the legacy output */
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
ret = drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group);
if (ret)
- goto err_g3;
+ goto err_g4;
}
list_add_tail(&dev->driver_item, &driver->device_list);
@@ -411,8 +420,11 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
return 0;
-err_g3:
+err_g4:
drm_put_minor(&dev->primary);
+err_g3:
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ drm_put_minor(&dev->control);
err_g2:
pci_disable_device(pdev);
err_g1:
@@ -493,11 +505,11 @@ void drm_put_dev(struct drm_device *dev)
dev->agp = NULL;
}
- drm_ht_remove(&dev->map_hash);
- drm_ctxbitmap_cleanup(dev);
-
list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
drm_rmmap(dev, r_list->map);
+ drm_ht_remove(&dev->map_hash);
+
+ drm_ctxbitmap_cleanup(dev);
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_put_minor(&dev->control);
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index bc0c6849360c..8f9372921f82 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -132,6 +132,7 @@ void drm_sysfs_destroy(void)
*/
static void drm_sysfs_device_release(struct device *dev)
{
+ memset(dev, 0, sizeof(struct device));
return;
}
@@ -488,9 +489,7 @@ int drm_sysfs_device_add(struct drm_minor *minor)
return 0;
- device_unregister(&minor->kdev);
err_out:
-
return err;
}
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index a000cf028826..051134c56aef 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -713,18 +713,18 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
mutex_unlock(&dev->struct_mutex);
if (ret) {
DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
- goto fail_batch_free;
+ goto fail_clip_free;
}
if (sarea_priv)
sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
-fail_batch_free:
- drm_free(batch_data, cmdbuf->sz, DRM_MEM_DRIVER);
fail_clip_free:
drm_free(cliprects,
cmdbuf->num_cliprects * sizeof(struct drm_clip_rect),
DRM_MEM_DRIVER);
+fail_batch_free:
+ drm_free(batch_data, cmdbuf->sz, DRM_MEM_DRIVER);
return ret;
}
@@ -1232,7 +1232,7 @@ int i915_driver_unload(struct drm_device *dev)
if (dev_priv->regs != NULL)
iounmap(dev_priv->regs);
- intel_opregion_free(dev);
+ intel_opregion_free(dev, 0);
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
intel_modeset_cleanup(dev);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 6503e2210f65..98560e1e899a 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -77,7 +77,7 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
drm_irq_uninstall(dev);
}
- intel_opregion_free(dev);
+ intel_opregion_free(dev, 1);
if (state.event == PM_EVENT_SUSPEND) {
/* Shut down the device */
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 3750d8003048..25065923b8a8 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -446,6 +446,9 @@ struct drm_i915_gem_object {
uint32_t tiling_mode;
uint32_t stride;
+ /** Record of address bit 17 of each page at last unbind. */
+ long *bit_17;
+
/** AGP mapping type (AGP_USER_MEMORY or AGP_USER_CACHED_MEMORY */
uint32_t agp_type;
@@ -635,9 +638,13 @@ int i915_gem_attach_phys_object(struct drm_device *dev,
void i915_gem_detach_phys_object(struct drm_device *dev,
struct drm_gem_object *obj);
void i915_gem_free_all_phys_object(struct drm_device *dev);
+int i915_gem_object_get_pages(struct drm_gem_object *obj);
+void i915_gem_object_put_pages(struct drm_gem_object *obj);
/* i915_gem_tiling.c */
void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
+void i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj);
+void i915_gem_object_save_bit_17_swizzle(struct drm_gem_object *obj);
/* i915_gem_debug.c */
void i915_gem_dump_object(struct drm_gem_object *obj, int len,
@@ -667,12 +674,12 @@ extern int i915_restore_state(struct drm_device *dev);
#ifdef CONFIG_ACPI
/* i915_opregion.c */
extern int intel_opregion_init(struct drm_device *dev, int resume);
-extern void intel_opregion_free(struct drm_device *dev);
+extern void intel_opregion_free(struct drm_device *dev, int suspend);
extern void opregion_asle_intr(struct drm_device *dev);
extern void opregion_enable_asle(struct drm_device *dev);
#else
static inline int intel_opregion_init(struct drm_device *dev, int resume) { return 0; }
-static inline void intel_opregion_free(struct drm_device *dev) { return; }
+static inline void intel_opregion_free(struct drm_device *dev, int suspend) { return; }
static inline void opregion_asle_intr(struct drm_device *dev) { return; }
static inline void opregion_enable_asle(struct drm_device *dev) { return; }
#endif
@@ -780,7 +787,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
(dev)->pci_device == 0x2A42 || \
(dev)->pci_device == 0x2E02 || \
(dev)->pci_device == 0x2E12 || \
- (dev)->pci_device == 0x2E22)
+ (dev)->pci_device == 0x2E22 || \
+ (dev)->pci_device == 0x2E32)
#define IS_I965GM(dev) ((dev)->pci_device == 0x2A02)
@@ -789,6 +797,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define IS_G4X(dev) ((dev)->pci_device == 0x2E02 || \
(dev)->pci_device == 0x2E12 || \
(dev)->pci_device == 0x2E22 || \
+ (dev)->pci_device == 0x2E32 || \
IS_GM45(dev))
#define IS_IGDG(dev) ((dev)->pci_device == 0xa001)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 1449b452cc63..ee896d91c5bc 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -43,8 +43,6 @@ static int i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj,
uint64_t offset,
uint64_t size);
static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj);
-static int i915_gem_object_get_pages(struct drm_gem_object *obj);
-static void i915_gem_object_put_pages(struct drm_gem_object *obj);
static int i915_gem_object_wait_rendering(struct drm_gem_object *obj);
static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
unsigned alignment);
@@ -143,15 +141,27 @@ fast_shmem_read(struct page **pages,
int length)
{
char __iomem *vaddr;
- int ret;
+ int unwritten;
vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0);
if (vaddr == NULL)
return -ENOMEM;
- ret = __copy_to_user_inatomic(data, vaddr + page_offset, length);
+ unwritten = __copy_to_user_inatomic(data, vaddr + page_offset, length);
kunmap_atomic(vaddr, KM_USER0);
- return ret;
+ if (unwritten)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int i915_gem_object_needs_bit17_swizzle(struct drm_gem_object *obj)
+{
+ drm_i915_private_t *dev_priv = obj->dev->dev_private;
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+ return dev_priv->mm.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_9_10_17 &&
+ obj_priv->tiling_mode != I915_TILING_NONE;
}
static inline int
@@ -181,6 +191,64 @@ slow_shmem_copy(struct page *dst_page,
return 0;
}
+static inline int
+slow_shmem_bit17_copy(struct page *gpu_page,
+ int gpu_offset,
+ struct page *cpu_page,
+ int cpu_offset,
+ int length,
+ int is_read)
+{
+ char *gpu_vaddr, *cpu_vaddr;
+
+ /* Use the unswizzled path if this page isn't affected. */
+ if ((page_to_phys(gpu_page) & (1 << 17)) == 0) {
+ if (is_read)
+ return slow_shmem_copy(cpu_page, cpu_offset,
+ gpu_page, gpu_offset, length);
+ else
+ return slow_shmem_copy(gpu_page, gpu_offset,
+ cpu_page, cpu_offset, length);
+ }
+
+ gpu_vaddr = kmap_atomic(gpu_page, KM_USER0);
+ if (gpu_vaddr == NULL)
+ return -ENOMEM;
+
+ cpu_vaddr = kmap_atomic(cpu_page, KM_USER1);
+ if (cpu_vaddr == NULL) {
+ kunmap_atomic(gpu_vaddr, KM_USER0);
+ return -ENOMEM;
+ }
+
+ /* Copy the data, XORing A6 with A17 (1). The user already knows he's
+ * XORing with the other bits (A9 for Y, A9 and A10 for X)
+ */
+ while (length > 0) {
+ int cacheline_end = ALIGN(gpu_offset + 1, 64);
+ int this_length = min(cacheline_end - gpu_offset, length);
+ int swizzled_gpu_offset = gpu_offset ^ 64;
+
+ if (is_read) {
+ memcpy(cpu_vaddr + cpu_offset,
+ gpu_vaddr + swizzled_gpu_offset,
+ this_length);
+ } else {
+ memcpy(gpu_vaddr + swizzled_gpu_offset,
+ cpu_vaddr + cpu_offset,
+ this_length);
+ }
+ cpu_offset += this_length;
+ gpu_offset += this_length;
+ length -= this_length;
+ }
+
+ kunmap_atomic(cpu_vaddr, KM_USER1);
+ kunmap_atomic(gpu_vaddr, KM_USER0);
+
+ return 0;
+}
+
/**
* This is the fast shmem pread path, which attempts to copy_from_user directly
* from the backing pages of the object to the user's address space. On a
@@ -269,6 +337,7 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj,
int page_length;
int ret;
uint64_t data_ptr = args->data_ptr;
+ int do_bit17_swizzling;
remain = args->size;
@@ -286,13 +355,15 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj,
down_read(&mm->mmap_sem);
pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr,
- num_pages, 0, 0, user_pages, NULL);
+ num_pages, 1, 0, user_pages, NULL);
up_read(&mm->mmap_sem);
if (pinned_pages < num_pages) {
ret = -EFAULT;
goto fail_put_user_pages;
}
+ do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj);
+
mutex_lock(&dev->struct_mutex);
ret = i915_gem_object_get_pages(obj);
@@ -327,11 +398,20 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj,
if ((data_page_offset + page_length) > PAGE_SIZE)
page_length = PAGE_SIZE - data_page_offset;
- ret = slow_shmem_copy(user_pages[data_page_index],
- data_page_offset,
- obj_priv->pages[shmem_page_index],
- shmem_page_offset,
- page_length);
+ if (do_bit17_swizzling) {
+ ret = slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index],
+ shmem_page_offset,
+ user_pages[data_page_index],
+ data_page_offset,
+ page_length,
+ 1);
+ } else {
+ ret = slow_shmem_copy(user_pages[data_page_index],
+ data_page_offset,
+ obj_priv->pages[shmem_page_index],
+ shmem_page_offset,
+ page_length);
+ }
if (ret)
goto fail_put_pages;
@@ -383,9 +463,14 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
return -EINVAL;
}
- ret = i915_gem_shmem_pread_fast(dev, obj, args, file_priv);
- if (ret != 0)
+ if (i915_gem_object_needs_bit17_swizzle(obj)) {
ret = i915_gem_shmem_pread_slow(dev, obj, args, file_priv);
+ } else {
+ ret = i915_gem_shmem_pread_fast(dev, obj, args, file_priv);
+ if (ret != 0)
+ ret = i915_gem_shmem_pread_slow(dev, obj, args,
+ file_priv);
+ }
drm_gem_object_unreference(obj);
@@ -727,6 +812,7 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
int page_length;
int ret;
uint64_t data_ptr = args->data_ptr;
+ int do_bit17_swizzling;
remain = args->size;
@@ -751,6 +837,8 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
goto fail_put_user_pages;
}
+ do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj);
+
mutex_lock(&dev->struct_mutex);
ret = i915_gem_object_get_pages(obj);
@@ -785,11 +873,20 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
if ((data_page_offset + page_length) > PAGE_SIZE)
page_length = PAGE_SIZE - data_page_offset;
- ret = slow_shmem_copy(obj_priv->pages[shmem_page_index],
- shmem_page_offset,
- user_pages[data_page_index],
- data_page_offset,
- page_length);
+ if (do_bit17_swizzling) {
+ ret = slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index],
+ shmem_page_offset,
+ user_pages[data_page_index],
+ data_page_offset,
+ page_length,
+ 0);
+ } else {
+ ret = slow_shmem_copy(obj_priv->pages[shmem_page_index],
+ shmem_page_offset,
+ user_pages[data_page_index],
+ data_page_offset,
+ page_length);
+ }
if (ret)
goto fail_put_pages;
@@ -854,6 +951,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
ret = i915_gem_gtt_pwrite_slow(dev, obj, args,
file_priv);
}
+ } else if (i915_gem_object_needs_bit17_swizzle(obj)) {
+ ret = i915_gem_shmem_pwrite_slow(dev, obj, args, file_priv);
} else {
ret = i915_gem_shmem_pwrite_fast(dev, obj, args, file_priv);
if (ret == -EFAULT) {
@@ -1285,7 +1384,7 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
return 0;
}
-static void
+void
i915_gem_object_put_pages(struct drm_gem_object *obj)
{
struct drm_i915_gem_object *obj_priv = obj->driver_private;
@@ -1297,6 +1396,9 @@ i915_gem_object_put_pages(struct drm_gem_object *obj)
if (--obj_priv->pages_refcount != 0)
return;
+ if (obj_priv->tiling_mode != I915_TILING_NONE)
+ i915_gem_object_save_bit_17_swizzle(obj);
+
for (i = 0; i < page_count; i++)
if (obj_priv->pages[i] != NULL) {
if (obj_priv->dirty)
@@ -1494,8 +1596,19 @@ i915_gem_retire_request(struct drm_device *dev,
if (obj->write_domain != 0)
i915_gem_object_move_to_flushing(obj);
- else
+ else {
+ /* Take a reference on the object so it won't be
+ * freed while the spinlock is held. The list
+ * protection for this spinlock is safe when breaking
+ * the lock like this since the next thing we do
+ * is just get the head of the list again.
+ */
+ drm_gem_object_reference(obj);
i915_gem_object_move_to_inactive(obj);
+ spin_unlock(&dev_priv->mm.active_list_lock);
+ drm_gem_object_unreference(obj);
+ spin_lock(&dev_priv->mm.active_list_lock);
+ }
}
out:
spin_unlock(&dev_priv->mm.active_list_lock);
@@ -1884,7 +1997,7 @@ i915_gem_evict_everything(struct drm_device *dev)
return ret;
}
-static int
+int
i915_gem_object_get_pages(struct drm_gem_object *obj)
{
struct drm_i915_gem_object *obj_priv = obj->driver_private;
@@ -1922,6 +2035,10 @@ i915_gem_object_get_pages(struct drm_gem_object *obj)
}
obj_priv->pages[i] = page;
}
+
+ if (obj_priv->tiling_mode != I915_TILING_NONE)
+ i915_gem_object_do_bit_17_swizzle(obj);
+
return 0;
}
@@ -3002,13 +3119,13 @@ i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list,
drm_free(*relocs, reloc_count * sizeof(**relocs),
DRM_MEM_DRIVER);
*relocs = NULL;
- return ret;
+ return -EFAULT;
}
reloc_index += exec_list[i].relocation_count;
}
- return ret;
+ return 0;
}
static int
@@ -3017,23 +3134,28 @@ i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object *exec_list,
struct drm_i915_gem_relocation_entry *relocs)
{
uint32_t reloc_count = 0, i;
- int ret;
+ int ret = 0;
for (i = 0; i < buffer_count; i++) {
struct drm_i915_gem_relocation_entry __user *user_relocs;
+ int unwritten;
user_relocs = (void __user *)(uintptr_t)exec_list[i].relocs_ptr;
- if (ret == 0) {
- ret = copy_to_user(user_relocs,
- &relocs[reloc_count],
- exec_list[i].relocation_count *
- sizeof(*relocs));
+ unwritten = copy_to_user(user_relocs,
+ &relocs[reloc_count],
+ exec_list[i].relocation_count *
+ sizeof(*relocs));
+
+ if (unwritten) {
+ ret = -EFAULT;
+ goto err;
}
reloc_count += exec_list[i].relocation_count;
}
+err:
drm_free(relocs, reloc_count * sizeof(*relocs), DRM_MEM_DRIVER);
return ret;
@@ -3243,7 +3365,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
exec_offset = exec_list[args->buffer_count - 1].offset;
#if WATCH_EXEC
- i915_gem_dump_object(object_list[args->buffer_count - 1],
+ i915_gem_dump_object(batch_obj,
args->batch_len,
__func__,
~0);
@@ -3308,10 +3430,12 @@ err:
(uintptr_t) args->buffers_ptr,
exec_list,
sizeof(*exec_list) * args->buffer_count);
- if (ret)
+ if (ret) {
+ ret = -EFAULT;
DRM_ERROR("failed to copy %d exec entries "
"back to user (%d)\n",
args->buffer_count, ret);
+ }
}
/* Copy the updated relocations out regardless of current error
@@ -3593,6 +3717,7 @@ void i915_gem_free_object(struct drm_gem_object *obj)
i915_gem_free_mmap_offset(obj);
drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER);
+ kfree(obj_priv->bit_17);
drm_free(obj->driver_private, 1, DRM_MEM_DRIVER);
}
@@ -3962,8 +4087,10 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
dev_priv->mm.suspended = 0;
ret = i915_gem_init_ringbuffer(dev);
- if (ret != 0)
+ if (ret != 0) {
+ mutex_unlock(&dev->struct_mutex);
return ret;
+ }
spin_lock(&dev_priv->mm.active_list_lock);
BUG_ON(!list_empty(&dev_priv->mm.active_list));
diff --git a/drivers/gpu/drm/i915/i915_gem_debugfs.c b/drivers/gpu/drm/i915/i915_gem_debugfs.c
index a1ac0c5e7307..986f1082c596 100644
--- a/drivers/gpu/drm/i915/i915_gem_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_gem_debugfs.c
@@ -234,6 +234,96 @@ static int i915_hws_info(struct seq_file *m, void *data)
return 0;
}
+static void i915_dump_pages(struct seq_file *m, struct page **pages, int page_count)
+{
+ int page, i;
+ uint32_t *mem;
+
+ for (page = 0; page < page_count; page++) {
+ mem = kmap(pages[page]);
+ for (i = 0; i < PAGE_SIZE; i += 4)
+ seq_printf(m, "%08x : %08x\n", i, mem[i / 4]);
+ kunmap(pages[page]);
+ }
+}
+
+static int i915_batchbuffer_info(struct seq_file *m, void *data)
+{
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_device *dev = node->minor->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_gem_object *obj;
+ struct drm_i915_gem_object *obj_priv;
+ int ret;
+
+ spin_lock(&dev_priv->mm.active_list_lock);
+
+ list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) {
+ obj = obj_priv->obj;
+ if (obj->read_domains & I915_GEM_DOMAIN_COMMAND) {
+ ret = i915_gem_object_get_pages(obj);
+ if (ret) {
+ DRM_ERROR("Failed to get pages: %d\n", ret);
+ spin_unlock(&dev_priv->mm.active_list_lock);
+ return ret;
+ }
+
+ seq_printf(m, "--- gtt_offset = 0x%08x\n", obj_priv->gtt_offset);
+ i915_dump_pages(m, obj_priv->pages, obj->size / PAGE_SIZE);
+
+ i915_gem_object_put_pages(obj);
+ }
+ }
+
+ spin_unlock(&dev_priv->mm.active_list_lock);
+
+ return 0;
+}
+
+static int i915_ringbuffer_data(struct seq_file *m, void *data)
+{
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_device *dev = node->minor->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ u8 *virt;
+ uint32_t *ptr, off;
+
+ if (!dev_priv->ring.ring_obj) {
+ seq_printf(m, "No ringbuffer setup\n");
+ return 0;
+ }
+
+ virt = dev_priv->ring.virtual_start;
+
+ for (off = 0; off < dev_priv->ring.Size; off += 4) {
+ ptr = (uint32_t *)(virt + off);
+ seq_printf(m, "%08x : %08x\n", off, *ptr);
+ }
+
+ return 0;
+}
+
+static int i915_ringbuffer_info(struct seq_file *m, void *data)
+{
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_device *dev = node->minor->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ unsigned int head, tail, mask;
+
+ head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
+ tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
+ mask = dev_priv->ring.tail_mask;
+
+ seq_printf(m, "RingHead : %08x\n", head);
+ seq_printf(m, "RingTail : %08x\n", tail);
+ seq_printf(m, "RingMask : %08x\n", mask);
+ seq_printf(m, "RingSize : %08lx\n", dev_priv->ring.Size);
+ seq_printf(m, "Acthd : %08x\n", I915_READ(IS_I965G(dev) ? ACTHD_I965 : ACTHD));
+
+ return 0;
+}
+
+
static struct drm_info_list i915_gem_debugfs_list[] = {
{"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
{"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST},
@@ -243,6 +333,9 @@ static struct drm_info_list i915_gem_debugfs_list[] = {
{"i915_gem_fence_regs", i915_gem_fence_regs_info, 0},
{"i915_gem_interrupt", i915_interrupt_info, 0},
{"i915_gem_hws", i915_hws_info, 0},
+ {"i915_ringbuffer_data", i915_ringbuffer_data, 0},
+ {"i915_ringbuffer_info", i915_ringbuffer_info, 0},
+ {"i915_batchbuffers", i915_batchbuffer_info, 0},
};
#define I915_GEM_DEBUGFS_ENTRIES ARRAY_SIZE(i915_gem_debugfs_list)
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index 6be3f927c86a..52a059354e83 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -25,6 +25,8 @@
*
*/
+#include "linux/string.h"
+#include "linux/bitops.h"
#include "drmP.h"
#include "drm.h"
#include "i915_drm.h"
@@ -127,8 +129,8 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
swizzle_y = I915_BIT_6_SWIZZLE_9_11;
} else {
/* Bit 17 swizzling by the CPU in addition. */
- swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
- swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
+ swizzle_x = I915_BIT_6_SWIZZLE_9_10_17;
+ swizzle_y = I915_BIT_6_SWIZZLE_9_17;
}
break;
}
@@ -281,13 +283,25 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
mutex_lock(&dev->struct_mutex);
if (args->tiling_mode == I915_TILING_NONE) {
- obj_priv->tiling_mode = I915_TILING_NONE;
args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
} else {
if (args->tiling_mode == I915_TILING_X)
args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
else
args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y;
+
+ /* Hide bit 17 swizzling from the user. This prevents old Mesa
+ * from aborting the application on sw fallbacks to bit 17,
+ * and we use the pread/pwrite bit17 paths to swizzle for it.
+ * If there was a user that was relying on the swizzle
+ * information for drm_intel_bo_map()ed reads/writes this would
+ * break it, but we don't have any of those.
+ */
+ if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_17)
+ args->swizzle_mode = I915_BIT_6_SWIZZLE_9;
+ if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17)
+ args->swizzle_mode = I915_BIT_6_SWIZZLE_9_10;
+
/* If we can't handle the swizzling, make it untiled. */
if (args->swizzle_mode == I915_BIT_6_SWIZZLE_UNKNOWN) {
args->tiling_mode = I915_TILING_NONE;
@@ -354,8 +368,100 @@ i915_gem_get_tiling(struct drm_device *dev, void *data,
DRM_ERROR("unknown tiling mode\n");
}
+ /* Hide bit 17 from the user -- see comment in i915_gem_set_tiling */
+ if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_17)
+ args->swizzle_mode = I915_BIT_6_SWIZZLE_9;
+ if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17)
+ args->swizzle_mode = I915_BIT_6_SWIZZLE_9_10;
+
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
return 0;
}
+
+/**
+ * Swap every 64 bytes of this page around, to account for it having a new
+ * bit 17 of its physical address and therefore being interpreted differently
+ * by the GPU.
+ */
+static int
+i915_gem_swizzle_page(struct page *page)
+{
+ char *vaddr;
+ int i;
+ char temp[64];
+
+ vaddr = kmap(page);
+ if (vaddr == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i < PAGE_SIZE; i += 128) {
+ memcpy(temp, &vaddr[i], 64);
+ memcpy(&vaddr[i], &vaddr[i + 64], 64);
+ memcpy(&vaddr[i + 64], temp, 64);
+ }
+
+ kunmap(page);
+
+ return 0;
+}
+
+void
+i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj)
+{
+ struct drm_device *dev = obj->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+ int page_count = obj->size >> PAGE_SHIFT;
+ int i;
+
+ if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17)
+ return;
+
+ if (obj_priv->bit_17 == NULL)
+ return;
+
+ for (i = 0; i < page_count; i++) {
+ char new_bit_17 = page_to_phys(obj_priv->pages[i]) >> 17;
+ if ((new_bit_17 & 0x1) !=
+ (test_bit(i, obj_priv->bit_17) != 0)) {
+ int ret = i915_gem_swizzle_page(obj_priv->pages[i]);
+ if (ret != 0) {
+ DRM_ERROR("Failed to swizzle page\n");
+ return;
+ }
+ set_page_dirty(obj_priv->pages[i]);
+ }
+ }
+}
+
+void
+i915_gem_object_save_bit_17_swizzle(struct drm_gem_object *obj)
+{
+ struct drm_device *dev = obj->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+ int page_count = obj->size >> PAGE_SHIFT;
+ int i;
+
+ if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17)
+ return;
+
+ if (obj_priv->bit_17 == NULL) {
+ obj_priv->bit_17 = kmalloc(BITS_TO_LONGS(page_count) *
+ sizeof(long), GFP_KERNEL);
+ if (obj_priv->bit_17 == NULL) {
+ DRM_ERROR("Failed to allocate memory for bit 17 "
+ "record\n");
+ return;
+ }
+ }
+
+ for (i = 0; i < page_count; i++) {
+ if (page_to_phys(obj_priv->pages[i]) & (1 << 17))
+ __set_bit(i, obj_priv->bit_17);
+ else
+ __clear_bit(i, obj_priv->bit_17);
+ }
+}
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index ee7ce7b78cf7..98bb4c878c4e 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -406,7 +406,7 @@ int i915_irq_emit(struct drm_device *dev, void *data,
drm_i915_irq_emit_t *emit = data;
int result;
- if (!dev_priv) {
+ if (!dev_priv || !dev_priv->ring.virtual_start) {
DRM_ERROR("called with no initialization\n");
return -EINVAL;
}
diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/i915_opregion.c
index 69427722d20e..dc425e74a268 100644
--- a/drivers/gpu/drm/i915/i915_opregion.c
+++ b/drivers/gpu/drm/i915/i915_opregion.c
@@ -370,11 +370,8 @@ int intel_opregion_init(struct drm_device *dev, int resume)
if (mboxes & MBOX_ACPI) {
DRM_DEBUG("Public ACPI methods supported\n");
opregion->acpi = base + OPREGION_ACPI_OFFSET;
- if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
intel_didl_outputs(dev);
- if (!resume)
- acpi_video_register();
- }
} else {
DRM_DEBUG("Public ACPI methods not supported\n");
err = -ENOTSUPP;
@@ -389,8 +386,13 @@ int intel_opregion_init(struct drm_device *dev, int resume)
if (mboxes & MBOX_ASLE) {
DRM_DEBUG("ASLE supported\n");
opregion->asle = base + OPREGION_ASLE_OFFSET;
+ opregion_enable_asle(dev);
}
+ if (!resume)
+ acpi_video_register();
+
+
/* Notify BIOS we are ready to handle ACPI video ext notifs.
* Right now, all the events are handled by the ACPI video module.
* We don't actually need to do anything with them. */
@@ -408,7 +410,7 @@ err_out:
return err;
}
-void intel_opregion_free(struct drm_device *dev)
+void intel_opregion_free(struct drm_device *dev, int suspend)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_opregion *opregion = &dev_priv->opregion;
@@ -416,6 +418,9 @@ void intel_opregion_free(struct drm_device *dev)
if (!opregion->enabled)
return;
+ if (!suspend)
+ acpi_video_exit();
+
opregion->acpi->drdy = 0;
system_opregion = NULL;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index e805b590ae71..521194732266 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1446,6 +1446,7 @@
#define DISPPLANE_NO_LINE_DOUBLE 0
#define DISPPLANE_STEREO_POLARITY_FIRST 0
#define DISPPLANE_STEREO_POLARITY_SECOND (1<<18)
+#define DISPPLANE_TILED (1<<10)
#define DSPAADDR 0x70184
#define DSPASTRIDE 0x70188
#define DSPAPOS 0x7018C /* reserved */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 64773ce52964..bdcda36953b0 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -367,6 +367,7 @@ static const intel_limit_t intel_limits[] = {
.p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX },
.p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
.p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST },
+ .find_pll = intel_find_best_PLL,
},
{ /* INTEL_LIMIT_IGD_LVDS */
.dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX },
@@ -380,6 +381,7 @@ static const intel_limit_t intel_limits[] = {
/* IGD only supports single-channel mode. */
.p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
.p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW },
+ .find_pll = intel_find_best_PLL,
},
};
@@ -655,6 +657,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR);
int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
+ int dsptileoff = (pipe == 0 ? DSPATILEOFF : DSPBTILEOFF);
int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
u32 dspcntr, alignment;
int ret;
@@ -731,6 +734,13 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
+ if (IS_I965G(dev)) {
+ if (obj_priv->tiling_mode != I915_TILING_NONE)
+ dspcntr |= DISPPLANE_TILED;
+ else
+ dspcntr &= ~DISPPLANE_TILED;
+ }
+
I915_WRITE(dspcntr_reg, dspcntr);
Start = obj_priv->gtt_offset;
@@ -743,6 +753,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
I915_READ(dspbase);
I915_WRITE(dspsurf, Start);
I915_READ(dspsurf);
+ I915_WRITE(dsptileoff, (y << 16) | x);
} else {
I915_WRITE(dspbase, Start + Offset);
I915_READ(dspbase);
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index b7f0ebe9f810..3e094beecb99 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -864,8 +864,8 @@ static void intelfb_sysrq(int dummy1, struct tty_struct *dummy3)
static struct sysrq_key_op sysrq_intelfb_restore_op = {
.handler = intelfb_sysrq,
- .help_msg = "force fb",
- .action_msg = "force restore of fb console",
+ .help_msg = "force-fb(G)",
+ .action_msg = "Restore framebuffer console",
};
int intelfb_probe(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index b06a4a3ff08d..550374225388 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -38,7 +38,7 @@
struct intel_hdmi_priv {
u32 sdvox_reg;
u32 save_SDVOX;
- int has_hdmi_sink;
+ bool has_hdmi_sink;
};
static void intel_hdmi_mode_set(struct drm_encoder *encoder,
@@ -128,6 +128,22 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
return true;
}
+static void
+intel_hdmi_sink_detect(struct drm_connector *connector)
+{
+ struct intel_output *intel_output = to_intel_output(connector);
+ struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv;
+ struct edid *edid = NULL;
+
+ edid = drm_get_edid(&intel_output->base,
+ &intel_output->ddc_bus->adapter);
+ if (edid != NULL) {
+ hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
+ kfree(edid);
+ intel_output->base.display_info.raw_edid = NULL;
+ }
+}
+
static enum drm_connector_status
intel_hdmi_detect(struct drm_connector *connector)
{
@@ -158,9 +174,10 @@ intel_hdmi_detect(struct drm_connector *connector)
return connector_status_unknown;
}
- if ((I915_READ(PORT_HOTPLUG_STAT) & bit) != 0)
+ if ((I915_READ(PORT_HOTPLUG_STAT) & bit) != 0) {
+ intel_hdmi_sink_detect(connector);
return connector_status_connected;
- else
+ } else
return connector_status_disconnected;
}
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 7b31f55f55c8..9913651c1e17 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1357,6 +1357,23 @@ void intel_sdvo_set_hotplug(struct drm_connector *connector, int on)
intel_sdvo_read_response(intel_output, &response, 2);
}
+static void
+intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
+{
+ struct intel_output *intel_output = to_intel_output(connector);
+ struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+ struct edid *edid = NULL;
+
+ intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus);
+ edid = drm_get_edid(&intel_output->base,
+ &intel_output->ddc_bus->adapter);
+ if (edid != NULL) {
+ sdvo_priv->is_hdmi = drm_detect_hdmi_monitor(edid);
+ kfree(edid);
+ intel_output->base.display_info.raw_edid = NULL;
+ }
+}
+
static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector)
{
u8 response[2];
@@ -1371,9 +1388,10 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect
if (status != SDVO_CMD_STATUS_SUCCESS)
return connector_status_unknown;
- if ((response[0] != 0) || (response[1] != 0))
+ if ((response[0] != 0) || (response[1] != 0)) {
+ intel_sdvo_hdmi_sink_detect(connector);
return connector_status_connected;
- else
+ } else
return connector_status_disconnected;
}
diff --git a/drivers/gpu/drm/r128/r128_cce.c b/drivers/gpu/drm/r128/r128_cce.c
index 32de4cedc363..077c0455a6b9 100644
--- a/drivers/gpu/drm/r128/r128_cce.c
+++ b/drivers/gpu/drm/r128/r128_cce.c
@@ -511,9 +511,9 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
#if __OS_HAS_AGP
if (!dev_priv->is_pci) {
- drm_core_ioremap(dev_priv->cce_ring, dev);
- drm_core_ioremap(dev_priv->ring_rptr, dev);
- drm_core_ioremap(dev->agp_buffer_map, dev);
+ drm_core_ioremap_wc(dev_priv->cce_ring, dev);
+ drm_core_ioremap_wc(dev_priv->ring_rptr, dev);
+ drm_core_ioremap_wc(dev->agp_buffer_map, dev);
if (!dev_priv->cce_ring->handle ||
!dev_priv->ring_rptr->handle ||
!dev->agp_buffer_map->handle) {
diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h
index ed4d27e6ee6f..8071d965f142 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.h
+++ b/drivers/gpu/drm/radeon/radeon_drv.h
@@ -99,9 +99,10 @@
* 1.27- Add support for IGP GART
* 1.28- Add support for VBL on CRTC2
* 1.29- R500 3D cmd buffer support
+ * 1.30- Add support for occlusion queries
*/
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 29
+#define DRIVER_MINOR 30
#define DRIVER_PATCHLEVEL 0
/*
diff --git a/drivers/gpu/drm/via/via_dma.c b/drivers/gpu/drm/via/via_dma.c
index 7a339dba6a69..bfb92d283260 100644
--- a/drivers/gpu/drm/via/via_dma.c
+++ b/drivers/gpu/drm/via/via_dma.c
@@ -481,11 +481,13 @@ static int via_wait_idle(drm_via_private_t * dev_priv)
{
int count = 10000000;
- while (!(VIA_READ(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && count--);
+ while (!(VIA_READ(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && --count)
+ ;
- while (count-- && (VIA_READ(VIA_REG_STATUS) &
+ while (count && (VIA_READ(VIA_REG_STATUS) &
(VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY |
- VIA_3D_ENG_BUSY))) ;
+ VIA_3D_ENG_BUSY)))
+ --count;
return count;
}
@@ -705,7 +707,7 @@ static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file *
switch (d_siz->func) {
case VIA_CMDBUF_SPACE:
while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz->size)
- && count--) {
+ && --count) {
if (!d_siz->wait) {
break;
}
@@ -717,7 +719,7 @@ static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file *
break;
case VIA_CMDBUF_LAG:
while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz->size)
- && count--) {
+ && --count) {
if (!d_siz->wait) {
break;
}
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 7e67dcb3d4f6..21edf407bbda 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -271,6 +271,13 @@ config THRUSTMASTER_FF
Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or
a THRUSTMASTER Ferrari GT Rumble Force or Force Feedback Wheel.
+config HID_WACOM
+ tristate "Wacom Bluetooth devices support" if EMBEDDED
+ depends on BT_HIDP
+ default !EMBEDDED
+ ---help---
+ Support for Wacom Graphire Bluetooth tablet.
+
config ZEROPLUS_FF
tristate "Zeroplus based game controller support"
depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 1f7cb0fd4505..39cebcfa898c 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_GREENASIA_FF) += hid-gaff.o
obj-$(CONFIG_THRUSTMASTER_FF) += hid-tmff.o
obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o
obj-$(CONFIG_ZEROPLUS_FF) += hid-zpff.o
+obj-$(CONFIG_HID_WACOM) += hid-wacom.o
obj-$(CONFIG_USB_HID) += usbhid/
obj-$(CONFIG_USB_MOUSE) += usbhid/
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index 7359d9d88e46..acbce5745b0c 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -151,7 +151,7 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
if (fnmode) {
int do_translate;
- trans = apple_find_translation((hid->product < 0x220 ||
+ trans = apple_find_translation((hid->product < 0x21d ||
hid->product >= 0x300) ?
powerbook_fn_keys : apple_fn_keys,
usage->code);
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 5746a5903bce..9f38ab874c93 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1293,6 +1293,7 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K) },
@@ -1311,6 +1312,7 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
@@ -1824,6 +1826,9 @@ int hid_check_keys_pressed(struct hid_device *hid)
struct hid_input *hidinput;
int i;
+ if (!(hid->claimed & HID_CLAIMED_INPUT))
+ return 0;
+
list_for_each_entry(hidinput, &hid->inputs, list) {
for (i = 0; i < BITS_TO_LONGS(KEY_MAX); i++)
if (hidinput->input->key[i])
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index bdeda4c7cc13..b519692732db 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -113,6 +113,11 @@
#define USB_VENDOR_ID_BERKSHIRE 0x0c98
#define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140
+#define USB_VENDOR_ID_CH 0x068e
+#define USB_DEVICE_ID_CH_PRO_PEDALS 0x00f2
+#define USB_DEVICE_ID_CH_COMBATSTICK 0x00f4
+#define USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE 0x00ff
+
#define USB_VENDOR_ID_CHERRY 0x046a
#define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023
@@ -292,6 +297,7 @@
#define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286
#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294
#define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295
+#define USB_DEVICE_ID_LOGITECH_G25_WHEEL 0xc299
#define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a
#define USB_DEVICE_ID_S510_RECEIVER 0xc50c
#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
@@ -408,6 +414,7 @@
#define USB_DEVICE_ID_VERNIER_LCSPEC 0x0006
#define USB_VENDOR_ID_WACOM 0x056a
+#define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81
#define USB_VENDOR_ID_WISEGROUP 0x0925
#define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index 7b80cb694982..7afbaa0efd18 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -297,6 +297,8 @@ static const struct hid_device_id lg_devices[] = {
.driver_data = LG_FF },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2),
.driver_data = LG_FF },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL),
+ .driver_data = LG_FF },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
.driver_data = LG_FF2 },
{ }
diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c
index 51aff08e10ce..9735be6ee4ff 100644
--- a/drivers/hid/hid-lgff.c
+++ b/drivers/hid/hid-lgff.c
@@ -61,7 +61,7 @@ static const struct dev_type devices[] = {
{ 0x046d, 0xc219, ff_rumble },
{ 0x046d, 0xc283, ff_joystick },
{ 0x046d, 0xc286, ff_joystick },
- { 0x046d, 0xc294, ff_joystick },
+ { 0x046d, 0xc294, ff_wheel },
{ 0x046d, 0xc295, ff_joystick },
{ 0x046d, 0xca03, ff_wheel },
};
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c
new file mode 100644
index 000000000000..1f9237f511e3
--- /dev/null
+++ b/drivers/hid/hid-wacom.c
@@ -0,0 +1,259 @@
+/*
+ * Bluetooth Wacom Tablet support
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com>
+ * Copyright (c) 2006 Andrew Zabolotny <zap@homelink.ru>
+ * Copyright (c) 2009 Bastien Nocera <hadess@hadess.net>
+ */
+
+/*
+ * 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+struct wacom_data {
+ __u16 tool;
+ unsigned char butstate;
+};
+
+static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
+ u8 *raw_data, int size)
+{
+ struct wacom_data *wdata = hid_get_drvdata(hdev);
+ struct hid_input *hidinput;
+ struct input_dev *input;
+ unsigned char *data = (unsigned char *) raw_data;
+ int tool, x, y, rw;
+
+ if (!(hdev->claimed & HID_CLAIMED_INPUT))
+ return 0;
+
+ tool = 0;
+ hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
+ input = hidinput->input;
+
+ /* Check if this is a tablet report */
+ if (data[0] != 0x03)
+ return 0;
+
+ /* Get X & Y positions */
+ x = le16_to_cpu(*(__le16 *) &data[2]);
+ y = le16_to_cpu(*(__le16 *) &data[4]);
+
+ /* Get current tool identifier */
+ if (data[1] & 0x90) { /* If pen is in the in/active area */
+ switch ((data[1] >> 5) & 3) {
+ case 0: /* Pen */
+ tool = BTN_TOOL_PEN;
+ break;
+
+ case 1: /* Rubber */
+ tool = BTN_TOOL_RUBBER;
+ break;
+
+ case 2: /* Mouse with wheel */
+ case 3: /* Mouse without wheel */
+ tool = BTN_TOOL_MOUSE;
+ break;
+ }
+
+ /* Reset tool if out of active tablet area */
+ if (!(data[1] & 0x10))
+ tool = 0;
+ }
+
+ /* If tool changed, notify input subsystem */
+ if (wdata->tool != tool) {
+ if (wdata->tool) {
+ /* Completely reset old tool state */
+ if (wdata->tool == BTN_TOOL_MOUSE) {
+ input_report_key(input, BTN_LEFT, 0);
+ input_report_key(input, BTN_RIGHT, 0);
+ input_report_key(input, BTN_MIDDLE, 0);
+ input_report_abs(input, ABS_DISTANCE,
+ input->absmax[ABS_DISTANCE]);
+ } else {
+ input_report_key(input, BTN_TOUCH, 0);
+ input_report_key(input, BTN_STYLUS, 0);
+ input_report_key(input, BTN_STYLUS2, 0);
+ input_report_abs(input, ABS_PRESSURE, 0);
+ }
+ input_report_key(input, wdata->tool, 0);
+ input_sync(input);
+ }
+ wdata->tool = tool;
+ if (tool)
+ input_report_key(input, tool, 1);
+ }
+
+ if (tool) {
+ input_report_abs(input, ABS_X, x);
+ input_report_abs(input, ABS_Y, y);
+
+ switch ((data[1] >> 5) & 3) {
+ case 2: /* Mouse with wheel */
+ input_report_key(input, BTN_MIDDLE, data[1] & 0x04);
+ rw = (data[6] & 0x01) ? -1 :
+ (data[6] & 0x02) ? 1 : 0;
+ input_report_rel(input, REL_WHEEL, rw);
+ /* fall through */
+
+ case 3: /* Mouse without wheel */
+ input_report_key(input, BTN_LEFT, data[1] & 0x01);
+ input_report_key(input, BTN_RIGHT, data[1] & 0x02);
+ /* Compute distance between mouse and tablet */
+ rw = 44 - (data[6] >> 2);
+ if (rw < 0)
+ rw = 0;
+ else if (rw > 31)
+ rw = 31;
+ input_report_abs(input, ABS_DISTANCE, rw);
+ break;
+
+ default:
+ input_report_abs(input, ABS_PRESSURE,
+ data[6] | (((__u16) (data[1] & 0x08)) << 5));
+ input_report_key(input, BTN_TOUCH, data[1] & 0x01);
+ input_report_key(input, BTN_STYLUS, data[1] & 0x02);
+ input_report_key(input, BTN_STYLUS2, (tool == BTN_TOOL_PEN) && data[1] & 0x04);
+ break;
+ }
+
+ input_sync(input);
+ }
+
+ /* Report the state of the two buttons at the top of the tablet
+ * as two extra fingerpad keys (buttons 4 & 5). */
+ rw = data[7] & 0x03;
+ if (rw != wdata->butstate) {
+ wdata->butstate = rw;
+ input_report_key(input, BTN_0, rw & 0x02);
+ input_report_key(input, BTN_1, rw & 0x01);
+ input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
+ input_sync(input);
+ }
+
+ return 1;
+}
+
+static int wacom_probe(struct hid_device *hdev,
+ const struct hid_device_id *id)
+{
+ struct hid_input *hidinput;
+ struct input_dev *input;
+ struct wacom_data *wdata;
+ int ret;
+
+ wdata = kzalloc(sizeof(*wdata), GFP_KERNEL);
+ if (wdata == NULL) {
+ dev_err(&hdev->dev, "can't alloc wacom descriptor\n");
+ return -ENOMEM;
+ }
+
+ hid_set_drvdata(hdev, wdata);
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "parse failed\n");
+ goto err_free;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+ if (ret) {
+ dev_err(&hdev->dev, "hw start failed\n");
+ goto err_free;
+ }
+
+ hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
+ input = hidinput->input;
+
+ /* Basics */
+ input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL);
+ input->absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) |
+ BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE);
+ input->relbit[0] |= BIT(REL_WHEEL);
+ set_bit(BTN_TOOL_PEN, input->keybit);
+ set_bit(BTN_TOUCH, input->keybit);
+ set_bit(BTN_STYLUS, input->keybit);
+ set_bit(BTN_STYLUS2, input->keybit);
+ set_bit(BTN_LEFT, input->keybit);
+ set_bit(BTN_RIGHT, input->keybit);
+ set_bit(BTN_MIDDLE, input->keybit);
+
+ /* Pad */
+ input->evbit[0] |= BIT(EV_MSC);
+ input->mscbit[0] |= BIT(MSC_SERIAL);
+
+ /* Distance, rubber and mouse */
+ input->absbit[0] |= BIT(ABS_DISTANCE);
+ set_bit(BTN_TOOL_RUBBER, input->keybit);
+ set_bit(BTN_TOOL_MOUSE, input->keybit);
+
+ input->absmax[ABS_PRESSURE] = 511;
+ input->absmax[ABS_DISTANCE] = 32;
+
+ input->absmax[ABS_X] = 16704;
+ input->absmax[ABS_Y] = 12064;
+ input->absfuzz[ABS_X] = 4;
+ input->absfuzz[ABS_Y] = 4;
+
+ return 0;
+err_free:
+ kfree(wdata);
+ return ret;
+}
+
+static void wacom_remove(struct hid_device *hdev)
+{
+ hid_hw_stop(hdev);
+ kfree(hid_get_drvdata(hdev));
+}
+
+static const struct hid_device_id wacom_devices[] = {
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
+
+ { }
+};
+MODULE_DEVICE_TABLE(hid, wacom_devices);
+
+static struct hid_driver wacom_driver = {
+ .name = "wacom",
+ .id_table = wacom_devices,
+ .probe = wacom_probe,
+ .remove = wacom_remove,
+ .raw_event = wacom_raw_event,
+};
+
+static int wacom_init(void)
+{
+ int ret;
+
+ ret = hid_register_driver(&wacom_driver);
+ if (ret)
+ printk(KERN_ERR "can't register wacom driver\n");
+ printk(KERN_ERR "wacom driver registered\n");
+ return ret;
+}
+
+static void wacom_exit(void)
+{
+ hid_unregister_driver(&wacom_driver);
+}
+
+module_init(wacom_init);
+module_exit(wacom_exit);
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index e263d4731179..00ccf4b1985d 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -285,8 +285,10 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) {
int len;
- if (!hid->name)
- return 0;
+ if (!hid->name) {
+ ret = 0;
+ break;
+ }
len = strlen(hid->name) + 1;
if (len > _IOC_SIZE(cmd))
len = _IOC_SIZE(cmd);
@@ -297,8 +299,10 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) {
int len;
- if (!hid->phys)
- return 0;
+ if (!hid->phys) {
+ ret = 0;
+ break;
+ }
len = strlen(hid->phys) + 1;
if (len > _IOC_SIZE(cmd))
len = _IOC_SIZE(cmd);
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 4306cb1b8ce5..ac8049b5f1e9 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -662,8 +662,8 @@ void usbhid_close(struct hid_device *hid)
spin_lock_irq(&usbhid->lock);
if (!--hid->open) {
spin_unlock_irq(&usbhid->lock);
+ hid_cancel_delayed_stuff(usbhid);
usb_kill_urb(usbhid->urbin);
- flush_scheduled_work();
usbhid->intf->needs_remote_wakeup = 0;
} else {
spin_unlock_irq(&usbhid->lock);
@@ -898,7 +898,7 @@ static int usbhid_parse(struct hid_device *hid)
goto err;
}
- hid->quirks = quirks;
+ hid->quirks |= quirks;
return 0;
err:
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 4391717d2519..d8f7423f363e 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -50,6 +50,9 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 0e8a9185f676..86a5cff0c027 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -418,7 +418,7 @@ config SENSORS_IBMAEM
power sensors and capping hardware in various IBM System X
servers that support Active Energy Manager. This includes
the x3350, x3550, x3650, x3655, x3755, x3850 M2, x3950 M2,
- and certain HS2x/LS2x/QS2x blades.
+ and certain HC10/HS2x/LS2x/QS2x blades.
This driver can also be built as a module. If so, the module
will be called ibmaem.
@@ -692,6 +692,16 @@ config SENSORS_PCF8591
These devices are hard to detect and rarely found on mainstream
hardware. If unsure, say N.
+config SENSORS_SHT15
+ tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
+ depends on GENERIC_GPIO
+ help
+ If you say yes here you get support for the Sensiron SHT10, SHT11,
+ SHT15, SHT71, SHT75 humidity and temperature sensors.
+
+ This driver can also be built as a module. If so, the module
+ will be called sht15.
+
config SENSORS_SIS5595
tristate "Silicon Integrated Systems Corp. SiS5595"
depends on PCI
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 1d3757837b4f..0ae26984ba45 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_SENSORS_MAX6650) += max6650.o
obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
+obj-$(CONFIG_SENSORS_SHT15) += sht15.o
obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c
index 0897edef2574..bff0103610c1 100644
--- a/drivers/hwmon/asus_atk0110.c
+++ b/drivers/hwmon/asus_atk0110.c
@@ -348,6 +348,7 @@ static int validate_hwmon_pack(struct atk_data *data, union acpi_object *obj)
return 0;
}
+#ifdef DEBUG
static char const *atk_sensor_type(union acpi_object *flags)
{
u64 type = flags->integer.value & ATK_TYPE_MASK;
@@ -370,6 +371,7 @@ static char const *atk_sensor_type(union acpi_object *flags)
return what;
}
+#endif
static void atk_print_sensor(struct atk_data *data, union acpi_object *obj)
{
diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c
index 55d3dc565be6..abca7e9f953b 100644
--- a/drivers/hwmon/hp_accel.c
+++ b/drivers/hwmon/hp_accel.c
@@ -34,7 +34,6 @@
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/freezer.h>
-#include <linux/version.h>
#include <linux/uaccess.h>
#include <linux/leds.h>
#include <acpi/acpi_drivers.h>
diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c
index fe74609a7feb..405d3fb5d76f 100644
--- a/drivers/hwmon/ibmaem.c
+++ b/drivers/hwmon/ibmaem.c
@@ -1127,3 +1127,4 @@ MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3650-*");
MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3655-*");
MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3755-*");
MODULE_ALIAS("dmi:bvnIBM:*:pnIBM3850M2/x3950M2-*");
+MODULE_ALIAS("dmi:bvnIBM:*:pnIBMBladeHC10-*");
diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c
new file mode 100644
index 000000000000..6cbdc2fea734
--- /dev/null
+++ b/drivers/hwmon/sht15.c
@@ -0,0 +1,692 @@
+/*
+ * sht15.c - support for the SHT15 Temperature and Humidity Sensor
+ *
+ * Copyright (c) 2009 Jonathan Cameron
+ *
+ * Copyright (c) 2007 Wouter Horre
+ *
+ * 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.
+ *
+ * Currently ignoring checksum on readings.
+ * Default resolution only (14bit temp, 12bit humidity)
+ * Ignoring battery status.
+ * Heater not enabled.
+ * Timings are all conservative.
+ *
+ * Data sheet available (1/2009) at
+ * http://www.sensirion.ch/en/pdf/product_information/Datasheet-humidity-sensor-SHT1x.pdf
+ *
+ * Regulator supply name = vcc
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/err.h>
+#include <linux/sht15.h>
+#include <linux/regulator/consumer.h>
+#include <asm/atomic.h>
+
+#define SHT15_MEASURE_TEMP 3
+#define SHT15_MEASURE_RH 5
+
+#define SHT15_READING_NOTHING 0
+#define SHT15_READING_TEMP 1
+#define SHT15_READING_HUMID 2
+
+/* Min timings in nsecs */
+#define SHT15_TSCKL 100 /* clock low */
+#define SHT15_TSCKH 100 /* clock high */
+#define SHT15_TSU 150 /* data setup time */
+
+/**
+ * struct sht15_temppair - elements of voltage dependant temp calc
+ * @vdd: supply voltage in microvolts
+ * @d1: see data sheet
+ */
+struct sht15_temppair {
+ int vdd; /* microvolts */
+ int d1;
+};
+
+/* Table 9 from data sheet - relates temperature calculation
+ * to supply voltage.
+ */
+static const struct sht15_temppair temppoints[] = {
+ { 2500000, -39400 },
+ { 3000000, -39600 },
+ { 3500000, -39700 },
+ { 4000000, -39800 },
+ { 5000000, -40100 },
+};
+
+/**
+ * struct sht15_data - device instance specific data
+ * @pdata: platform data (gpio's etc)
+ * @read_work: bh of interrupt handler
+ * @wait_queue: wait queue for getting values from device
+ * @val_temp: last temperature value read from device
+ * @val_humid: last humidity value read from device
+ * @flag: status flag used to identify what the last request was
+ * @valid: are the current stored values valid (start condition)
+ * @last_updat: time of last update
+ * @read_lock: mutex to ensure only one read in progress
+ * at a time.
+ * @dev: associate device structure
+ * @hwmon_dev: device associated with hwmon subsystem
+ * @reg: associated regulator (if specified)
+ * @nb: notifier block to handle notifications of voltage changes
+ * @supply_uV: local copy of supply voltage used to allow
+ * use of regulator consumer if available
+ * @supply_uV_valid: indicates that an updated value has not yet
+ * been obtained from the regulator and so any calculations
+ * based upon it will be invalid.
+ * @update_supply_work: work struct that is used to update the supply_uV
+ * @interrupt_handled: flag used to indicate a hander has been scheduled
+ */
+struct sht15_data {
+ struct sht15_platform_data *pdata;
+ struct work_struct read_work;
+ wait_queue_head_t wait_queue;
+ uint16_t val_temp;
+ uint16_t val_humid;
+ u8 flag;
+ u8 valid;
+ unsigned long last_updat;
+ struct mutex read_lock;
+ struct device *dev;
+ struct device *hwmon_dev;
+ struct regulator *reg;
+ struct notifier_block nb;
+ int supply_uV;
+ int supply_uV_valid;
+ struct work_struct update_supply_work;
+ atomic_t interrupt_handled;
+};
+
+/**
+ * sht15_connection_reset() - reset the comms interface
+ * @data: sht15 specific data
+ *
+ * This implements section 3.4 of the data sheet
+ */
+static void sht15_connection_reset(struct sht15_data *data)
+{
+ int i;
+ gpio_direction_output(data->pdata->gpio_data, 1);
+ ndelay(SHT15_TSCKL);
+ gpio_set_value(data->pdata->gpio_sck, 0);
+ ndelay(SHT15_TSCKL);
+ for (i = 0; i < 9; ++i) {
+ gpio_set_value(data->pdata->gpio_sck, 1);
+ ndelay(SHT15_TSCKH);
+ gpio_set_value(data->pdata->gpio_sck, 0);
+ ndelay(SHT15_TSCKL);
+ }
+}
+/**
+ * sht15_send_bit() - send an individual bit to the device
+ * @data: device state data
+ * @val: value of bit to be sent
+ **/
+static inline void sht15_send_bit(struct sht15_data *data, int val)
+{
+
+ gpio_set_value(data->pdata->gpio_data, val);
+ ndelay(SHT15_TSU);
+ gpio_set_value(data->pdata->gpio_sck, 1);
+ ndelay(SHT15_TSCKH);
+ gpio_set_value(data->pdata->gpio_sck, 0);
+ ndelay(SHT15_TSCKL); /* clock low time */
+}
+
+/**
+ * sht15_transmission_start() - specific sequence for new transmission
+ *
+ * @data: device state data
+ * Timings for this are not documented on the data sheet, so very
+ * conservative ones used in implementation. This implements
+ * figure 12 on the data sheet.
+ **/
+static void sht15_transmission_start(struct sht15_data *data)
+{
+ /* ensure data is high and output */
+ gpio_direction_output(data->pdata->gpio_data, 1);
+ ndelay(SHT15_TSU);
+ gpio_set_value(data->pdata->gpio_sck, 0);
+ ndelay(SHT15_TSCKL);
+ gpio_set_value(data->pdata->gpio_sck, 1);
+ ndelay(SHT15_TSCKH);
+ gpio_set_value(data->pdata->gpio_data, 0);
+ ndelay(SHT15_TSU);
+ gpio_set_value(data->pdata->gpio_sck, 0);
+ ndelay(SHT15_TSCKL);
+ gpio_set_value(data->pdata->gpio_sck, 1);
+ ndelay(SHT15_TSCKH);
+ gpio_set_value(data->pdata->gpio_data, 1);
+ ndelay(SHT15_TSU);
+ gpio_set_value(data->pdata->gpio_sck, 0);
+ ndelay(SHT15_TSCKL);
+}
+/**
+ * sht15_send_byte() - send a single byte to the device
+ * @data: device state
+ * @byte: value to be sent
+ **/
+static void sht15_send_byte(struct sht15_data *data, u8 byte)
+{
+ int i;
+ for (i = 0; i < 8; i++) {
+ sht15_send_bit(data, !!(byte & 0x80));
+ byte <<= 1;
+ }
+}
+/**
+ * sht15_wait_for_response() - checks for ack from device
+ * @data: device state
+ **/
+static int sht15_wait_for_response(struct sht15_data *data)
+{
+ gpio_direction_input(data->pdata->gpio_data);
+ gpio_set_value(data->pdata->gpio_sck, 1);
+ ndelay(SHT15_TSCKH);
+ if (gpio_get_value(data->pdata->gpio_data)) {
+ gpio_set_value(data->pdata->gpio_sck, 0);
+ dev_err(data->dev, "Command not acknowledged\n");
+ sht15_connection_reset(data);
+ return -EIO;
+ }
+ gpio_set_value(data->pdata->gpio_sck, 0);
+ ndelay(SHT15_TSCKL);
+ return 0;
+}
+
+/**
+ * sht15_send_cmd() - Sends a command to the device.
+ * @data: device state
+ * @cmd: command byte to be sent
+ *
+ * On entry, sck is output low, data is output pull high
+ * and the interrupt disabled.
+ **/
+static int sht15_send_cmd(struct sht15_data *data, u8 cmd)
+{
+ int ret = 0;
+ sht15_transmission_start(data);
+ sht15_send_byte(data, cmd);
+ ret = sht15_wait_for_response(data);
+ return ret;
+}
+/**
+ * sht15_update_single_val() - get a new value from device
+ * @data: device instance specific data
+ * @command: command sent to request value
+ * @timeout_msecs: timeout after which comms are assumed
+ * to have failed are reset.
+ **/
+static inline int sht15_update_single_val(struct sht15_data *data,
+ int command,
+ int timeout_msecs)
+{
+ int ret;
+ ret = sht15_send_cmd(data, command);
+ if (ret)
+ return ret;
+
+ gpio_direction_input(data->pdata->gpio_data);
+ atomic_set(&data->interrupt_handled, 0);
+
+ enable_irq(gpio_to_irq(data->pdata->gpio_data));
+ if (gpio_get_value(data->pdata->gpio_data) == 0) {
+ disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data));
+ /* Only relevant if the interrupt hasn't occured. */
+ if (!atomic_read(&data->interrupt_handled))
+ schedule_work(&data->read_work);
+ }
+ ret = wait_event_timeout(data->wait_queue,
+ (data->flag == SHT15_READING_NOTHING),
+ msecs_to_jiffies(timeout_msecs));
+ if (ret == 0) {/* timeout occurred */
+ disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data));;
+ sht15_connection_reset(data);
+ return -ETIME;
+ }
+ return 0;
+}
+
+/**
+ * sht15_update_vals() - get updated readings from device if too old
+ * @data: device state
+ **/
+static int sht15_update_vals(struct sht15_data *data)
+{
+ int ret = 0;
+ int timeout = HZ;
+
+ mutex_lock(&data->read_lock);
+ if (time_after(jiffies, data->last_updat + timeout)
+ || !data->valid) {
+ data->flag = SHT15_READING_HUMID;
+ ret = sht15_update_single_val(data, SHT15_MEASURE_RH, 160);
+ if (ret)
+ goto error_ret;
+ data->flag = SHT15_READING_TEMP;
+ ret = sht15_update_single_val(data, SHT15_MEASURE_TEMP, 400);
+ if (ret)
+ goto error_ret;
+ data->valid = 1;
+ data->last_updat = jiffies;
+ }
+error_ret:
+ mutex_unlock(&data->read_lock);
+
+ return ret;
+}
+
+/**
+ * sht15_calc_temp() - convert the raw reading to a temperature
+ * @data: device state
+ *
+ * As per section 4.3 of the data sheet.
+ **/
+static inline int sht15_calc_temp(struct sht15_data *data)
+{
+ int d1 = 0;
+ int i;
+
+ for (i = 1; i < ARRAY_SIZE(temppoints) - 1; i++)
+ /* Find pointer to interpolate */
+ if (data->supply_uV > temppoints[i - 1].vdd) {
+ d1 = (data->supply_uV/1000 - temppoints[i - 1].vdd)
+ * (temppoints[i].d1 - temppoints[i - 1].d1)
+ / (temppoints[i].vdd - temppoints[i - 1].vdd)
+ + temppoints[i - 1].d1;
+ break;
+ }
+
+ return data->val_temp*10 + d1;
+}
+
+/**
+ * sht15_calc_humid() - using last temperature convert raw to humid
+ * @data: device state
+ *
+ * This is the temperature compensated version as per section 4.2 of
+ * the data sheet.
+ **/
+static inline int sht15_calc_humid(struct sht15_data *data)
+{
+ int RHlinear; /* milli percent */
+ int temp = sht15_calc_temp(data);
+
+ const int c1 = -4;
+ const int c2 = 40500; /* x 10 ^ -6 */
+ const int c3 = 2800; /* x10 ^ -9 */
+
+ RHlinear = c1*1000
+ + c2 * data->val_humid/1000
+ + (data->val_humid * data->val_humid * c3)/1000000;
+ return (temp - 25000) * (10000 + 800 * data->val_humid)
+ / 1000000 + RHlinear;
+}
+
+static ssize_t sht15_show_temp(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int ret;
+ struct sht15_data *data = dev_get_drvdata(dev);
+
+ /* Technically no need to read humidity as well */
+ ret = sht15_update_vals(data);
+
+ return ret ? ret : sprintf(buf, "%d\n",
+ sht15_calc_temp(data));
+}
+
+static ssize_t sht15_show_humidity(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int ret;
+ struct sht15_data *data = dev_get_drvdata(dev);
+
+ ret = sht15_update_vals(data);
+
+ return ret ? ret : sprintf(buf, "%d\n", sht15_calc_humid(data));
+
+};
+static ssize_t show_name(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ return sprintf(buf, "%s\n", pdev->name);
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input,
+ S_IRUGO, sht15_show_temp,
+ NULL, 0);
+static SENSOR_DEVICE_ATTR(humidity1_input,
+ S_IRUGO, sht15_show_humidity,
+ NULL, 0);
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+static struct attribute *sht15_attrs[] = {
+ &sensor_dev_attr_temp1_input.dev_attr.attr,
+ &sensor_dev_attr_humidity1_input.dev_attr.attr,
+ &dev_attr_name.attr,
+ NULL,
+};
+
+static const struct attribute_group sht15_attr_group = {
+ .attrs = sht15_attrs,
+};
+
+static irqreturn_t sht15_interrupt_fired(int irq, void *d)
+{
+ struct sht15_data *data = d;
+ /* First disable the interrupt */
+ disable_irq_nosync(irq);
+ atomic_inc(&data->interrupt_handled);
+ /* Then schedule a reading work struct */
+ if (data->flag != SHT15_READING_NOTHING)
+ schedule_work(&data->read_work);
+ return IRQ_HANDLED;
+}
+
+/* Each byte of data is acknowledged by pulling the data line
+ * low for one clock pulse.
+ */
+static void sht15_ack(struct sht15_data *data)
+{
+ gpio_direction_output(data->pdata->gpio_data, 0);
+ ndelay(SHT15_TSU);
+ gpio_set_value(data->pdata->gpio_sck, 1);
+ ndelay(SHT15_TSU);
+ gpio_set_value(data->pdata->gpio_sck, 0);
+ ndelay(SHT15_TSU);
+ gpio_set_value(data->pdata->gpio_data, 1);
+
+ gpio_direction_input(data->pdata->gpio_data);
+}
+/**
+ * sht15_end_transmission() - notify device of end of transmission
+ * @data: device state
+ *
+ * This is basically a NAK. (single clock pulse, data high)
+ **/
+static void sht15_end_transmission(struct sht15_data *data)
+{
+ gpio_direction_output(data->pdata->gpio_data, 1);
+ ndelay(SHT15_TSU);
+ gpio_set_value(data->pdata->gpio_sck, 1);
+ ndelay(SHT15_TSCKH);
+ gpio_set_value(data->pdata->gpio_sck, 0);
+ ndelay(SHT15_TSCKL);
+}
+
+static void sht15_bh_read_data(struct work_struct *work_s)
+{
+ int i;
+ uint16_t val = 0;
+ struct sht15_data *data
+ = container_of(work_s, struct sht15_data,
+ read_work);
+ /* Firstly, verify the line is low */
+ if (gpio_get_value(data->pdata->gpio_data)) {
+ /* If not, then start the interrupt again - care
+ here as could have gone low in meantime so verify
+ it hasn't!
+ */
+ atomic_set(&data->interrupt_handled, 0);
+ enable_irq(gpio_to_irq(data->pdata->gpio_data));
+ /* If still not occured or another handler has been scheduled */
+ if (gpio_get_value(data->pdata->gpio_data)
+ || atomic_read(&data->interrupt_handled))
+ return;
+ }
+ /* Read the data back from the device */
+ for (i = 0; i < 16; ++i) {
+ val <<= 1;
+ gpio_set_value(data->pdata->gpio_sck, 1);
+ ndelay(SHT15_TSCKH);
+ val |= !!gpio_get_value(data->pdata->gpio_data);
+ gpio_set_value(data->pdata->gpio_sck, 0);
+ ndelay(SHT15_TSCKL);
+ if (i == 7)
+ sht15_ack(data);
+ }
+ /* Tell the device we are done */
+ sht15_end_transmission(data);
+
+ switch (data->flag) {
+ case SHT15_READING_TEMP:
+ data->val_temp = val;
+ break;
+ case SHT15_READING_HUMID:
+ data->val_humid = val;
+ break;
+ }
+
+ data->flag = SHT15_READING_NOTHING;
+ wake_up(&data->wait_queue);
+}
+
+static void sht15_update_voltage(struct work_struct *work_s)
+{
+ struct sht15_data *data
+ = container_of(work_s, struct sht15_data,
+ update_supply_work);
+ data->supply_uV = regulator_get_voltage(data->reg);
+}
+
+/**
+ * sht15_invalidate_voltage() - mark supply voltage invalid when notified by reg
+ * @nb: associated notification structure
+ * @event: voltage regulator state change event code
+ * @ignored: function parameter - ignored here
+ *
+ * Note that as the notification code holds the regulator lock, we have
+ * to schedule an update of the supply voltage rather than getting it directly.
+ **/
+static int sht15_invalidate_voltage(struct notifier_block *nb,
+ unsigned long event,
+ void *ignored)
+{
+ struct sht15_data *data = container_of(nb, struct sht15_data, nb);
+
+ if (event == REGULATOR_EVENT_VOLTAGE_CHANGE)
+ data->supply_uV_valid = false;
+ schedule_work(&data->update_supply_work);
+
+ return NOTIFY_OK;
+}
+
+static int __devinit sht15_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct sht15_data *data = kzalloc(sizeof(*data), GFP_KERNEL);
+
+ if (!data) {
+ ret = -ENOMEM;
+ dev_err(&pdev->dev, "kzalloc failed");
+ goto error_ret;
+ }
+
+ INIT_WORK(&data->read_work, sht15_bh_read_data);
+ INIT_WORK(&data->update_supply_work, sht15_update_voltage);
+ platform_set_drvdata(pdev, data);
+ mutex_init(&data->read_lock);
+ data->dev = &pdev->dev;
+ init_waitqueue_head(&data->wait_queue);
+
+ if (pdev->dev.platform_data == NULL) {
+ dev_err(&pdev->dev, "no platform data supplied");
+ goto err_free_data;
+ }
+ data->pdata = pdev->dev.platform_data;
+ data->supply_uV = data->pdata->supply_mv*1000;
+
+/* If a regulator is available, query what the supply voltage actually is!*/
+ data->reg = regulator_get(data->dev, "vcc");
+ if (!IS_ERR(data->reg)) {
+ data->supply_uV = regulator_get_voltage(data->reg);
+ regulator_enable(data->reg);
+ /* setup a notifier block to update this if another device
+ * causes the voltage to change */
+ data->nb.notifier_call = &sht15_invalidate_voltage;
+ ret = regulator_register_notifier(data->reg, &data->nb);
+ }
+/* Try requesting the GPIOs */
+ ret = gpio_request(data->pdata->gpio_sck, "SHT15 sck");
+ if (ret) {
+ dev_err(&pdev->dev, "gpio request failed");
+ goto err_free_data;
+ }
+ gpio_direction_output(data->pdata->gpio_sck, 0);
+ ret = gpio_request(data->pdata->gpio_data, "SHT15 data");
+ if (ret) {
+ dev_err(&pdev->dev, "gpio request failed");
+ goto err_release_gpio_sck;
+ }
+ ret = sysfs_create_group(&pdev->dev.kobj, &sht15_attr_group);
+ if (ret) {
+ dev_err(&pdev->dev, "sysfs create failed");
+ goto err_free_data;
+ }
+
+ ret = request_irq(gpio_to_irq(data->pdata->gpio_data),
+ sht15_interrupt_fired,
+ IRQF_TRIGGER_FALLING,
+ "sht15 data",
+ data);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get irq for data line");
+ goto err_release_gpio_data;
+ }
+ disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data));
+ sht15_connection_reset(data);
+ sht15_send_cmd(data, 0x1E);
+
+ data->hwmon_dev = hwmon_device_register(data->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ ret = PTR_ERR(data->hwmon_dev);
+ goto err_release_gpio_data;
+ }
+ return 0;
+
+err_release_gpio_data:
+ gpio_free(data->pdata->gpio_data);
+err_release_gpio_sck:
+ gpio_free(data->pdata->gpio_sck);
+err_free_data:
+ kfree(data);
+error_ret:
+
+ return ret;
+}
+
+static int __devexit sht15_remove(struct platform_device *pdev)
+{
+ struct sht15_data *data = platform_get_drvdata(pdev);
+
+ /* Make sure any reads from the device are done and
+ * prevent new ones beginnning */
+ mutex_lock(&data->read_lock);
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&pdev->dev.kobj, &sht15_attr_group);
+ if (!IS_ERR(data->reg)) {
+ regulator_unregister_notifier(data->reg, &data->nb);
+ regulator_disable(data->reg);
+ regulator_put(data->reg);
+ }
+
+ free_irq(gpio_to_irq(data->pdata->gpio_data), data);
+ gpio_free(data->pdata->gpio_data);
+ gpio_free(data->pdata->gpio_sck);
+ mutex_unlock(&data->read_lock);
+ kfree(data);
+ return 0;
+}
+
+
+static struct platform_driver sht_drivers[] = {
+ {
+ .driver = {
+ .name = "sht10",
+ .owner = THIS_MODULE,
+ },
+ .probe = sht15_probe,
+ .remove = sht15_remove,
+ }, {
+ .driver = {
+ .name = "sht11",
+ .owner = THIS_MODULE,
+ },
+ .probe = sht15_probe,
+ .remove = sht15_remove,
+ }, {
+ .driver = {
+ .name = "sht15",
+ .owner = THIS_MODULE,
+ },
+ .probe = sht15_probe,
+ .remove = sht15_remove,
+ }, {
+ .driver = {
+ .name = "sht71",
+ .owner = THIS_MODULE,
+ },
+ .probe = sht15_probe,
+ .remove = sht15_remove,
+ }, {
+ .driver = {
+ .name = "sht75",
+ .owner = THIS_MODULE,
+ },
+ .probe = sht15_probe,
+ .remove = sht15_remove,
+ },
+};
+
+
+static int __init sht15_init(void)
+{
+ int ret;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sht_drivers); i++) {
+ ret = platform_driver_register(&sht_drivers[i]);
+ if (ret)
+ goto error_unreg;
+ }
+
+ return 0;
+
+error_unreg:
+ while (--i >= 0)
+ platform_driver_unregister(&sht_drivers[i]);
+
+ return ret;
+}
+module_init(sht15_init);
+
+static void __exit sht15_exit(void)
+{
+ int i;
+ for (i = ARRAY_SIZE(sht_drivers) - 1; i >= 0; i--)
+ platform_driver_unregister(&sht_drivers[i]);
+}
+module_exit(sht15_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index dbfb30c588d8..0bdab959b736 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -1462,7 +1462,8 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
data->pwm[i] =
w83781d_read_value(data,
W83781D_REG_PWM[i]);
- if ((data->type != w83782d || !client->driver)
+ /* Only W83782D on SMBus has PWM3 and PWM4 */
+ if ((data->type != w83782d || !client)
&& i == 1)
break;
}
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index d420cc5f5633..e25e13980af3 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -104,7 +104,7 @@ static int sclhi(struct i2c_algo_bit_data *adap)
* chips may hold it low ("clock stretching") while they
* are processing data internally.
*/
- if (time_after_eq(jiffies, start + adap->timeout))
+ if (time_after(jiffies, start + adap->timeout))
return -ETIMEDOUT;
cond_resched();
}
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
index 6318f7ddc1d4..78d42aae0089 100644
--- a/drivers/i2c/algos/i2c-algo-pca.c
+++ b/drivers/i2c/algos/i2c-algo-pca.c
@@ -287,10 +287,21 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
case 0x30: /* Data byte in I2CDAT has been transmitted; NOT ACK has been received */
DEB2("NOT ACK received after data byte\n");
+ pca_stop(adap);
goto out;
case 0x38: /* Arbitration lost during SLA+W, SLA+R or data bytes */
DEB2("Arbitration lost\n");
+ /*
+ * The PCA9564 data sheet (2006-09-01) says "A
+ * START condition will be transmitted when the
+ * bus becomes free (STOP or SCL and SDA high)"
+ * when the STA bit is set (p. 11).
+ *
+ * In case this won't work, try pca_reset()
+ * instead.
+ */
+ pca_start(adap);
goto out;
case 0x58: /* Data byte has been received; NOT ACK has been returned */
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index 981e080b32ae..d108450df064 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -284,7 +284,7 @@ static int ali1535_transaction(struct i2c_adapter *adap)
&& (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */
- if (timeout >= MAX_TIMEOUT) {
+ if (timeout > MAX_TIMEOUT) {
result = -ETIMEDOUT;
dev_err(&adap->dev, "SMBus Timeout!\n");
}
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
index 39066dee46e3..d627fceb790b 100644
--- a/drivers/i2c/busses/i2c-ali15x3.c
+++ b/drivers/i2c/busses/i2c-ali15x3.c
@@ -306,7 +306,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap)
&& (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */
- if (timeout >= MAX_TIMEOUT) {
+ if (timeout > MAX_TIMEOUT) {
result = -ETIMEDOUT;
dev_err(&adap->dev, "SMBus Timeout!\n");
}
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index 220f4a1eee1d..f7d6fe9c49ba 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -126,7 +126,7 @@ static int amd756_transaction(struct i2c_adapter *adap)
} while ((temp & (GS_HST_STS | GS_SMB_STS)) &&
(timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */
- if (timeout >= MAX_TIMEOUT) {
+ if (timeout > MAX_TIMEOUT) {
dev_dbg(&adap->dev, "Busy wait timeout (%04x)\n", temp);
goto abort;
}
@@ -143,7 +143,7 @@ static int amd756_transaction(struct i2c_adapter *adap)
} while ((temp & GS_HST_STS) && (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */
- if (timeout >= MAX_TIMEOUT) {
+ if (timeout > MAX_TIMEOUT) {
dev_dbg(&adap->dev, "Completion timeout!\n");
goto abort;
}
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 10411848fd70..9d2c5adf5d4f 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -237,7 +237,7 @@ static int i801_transaction(int xact)
status = inb_p(SMBHSTSTS);
} while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
- result = i801_check_post(status, timeout >= MAX_TIMEOUT);
+ result = i801_check_post(status, timeout > MAX_TIMEOUT);
if (result < 0)
return result;
@@ -257,9 +257,9 @@ static void i801_wait_hwpec(void)
} while ((!(status & SMBHSTSTS_INTR))
&& (timeout++ < MAX_TIMEOUT));
- if (timeout >= MAX_TIMEOUT) {
+ if (timeout > MAX_TIMEOUT)
dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
- }
+
outb_p(status, SMBHSTSTS);
}
@@ -344,7 +344,7 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
while ((!(status & SMBHSTSTS_BYTE_DONE))
&& (timeout++ < MAX_TIMEOUT));
- result = i801_check_post(status, timeout >= MAX_TIMEOUT);
+ result = i801_check_post(status, timeout > MAX_TIMEOUT);
if (result < 0)
return result;
diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c
index b9c01aa90036..9f6b8e0f8632 100644
--- a/drivers/i2c/busses/i2c-isch.c
+++ b/drivers/i2c/busses/i2c-isch.c
@@ -112,7 +112,7 @@ static int sch_transaction(void)
} while ((temp & 0x08) && (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */
- if (timeout >= MAX_TIMEOUT) {
+ if (timeout > MAX_TIMEOUT) {
dev_err(&sch_adapter.dev, "SMBus Timeout!\n");
result = -ETIMEDOUT;
}
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 2ff4683703a8..ec11d1c4e77b 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -173,7 +173,7 @@ static int nforce2_check_status(struct i2c_adapter *adap)
temp = inb_p(NVIDIA_SMB_STS);
} while ((!temp) && (timeout++ < MAX_TIMEOUT));
- if (timeout >= MAX_TIMEOUT) {
+ if (timeout > MAX_TIMEOUT) {
dev_dbg(&adap->dev, "SMBus Timeout!\n");
if (smbus->can_abort)
nforce2_abort(adap);
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index c1405c8f6ba5..486d327a523a 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -34,10 +34,24 @@
#include <linux/err.h>
#include <linux/clk.h>
-#include <mach/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
+
+/*
+ * I2C register offsets will be shifted 0 or 1 bit left, depending on
+ * different SoCs
+ */
+#define REG_SHIFT_0 (0 << 0)
+#define REG_SHIFT_1 (1 << 0)
+#define REG_SHIFT(d) ((d) & 0x1)
+
+static const struct platform_device_id i2c_pxa_id_table[] = {
+ { "pxa2xx-i2c", REG_SHIFT_1 },
+ { "pxa3xx-pwri2c", REG_SHIFT_0 },
+ { },
+};
+MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
/*
* I2C registers and bit definitions
@@ -985,6 +999,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
struct pxa_i2c *i2c;
struct resource *res;
struct i2c_pxa_platform_data *plat = dev->dev.platform_data;
+ struct platform_device_id *id = platform_get_device_id(dev);
int ret;
int irq;
@@ -1028,7 +1043,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
ret = -EIO;
goto eremap;
}
- i2c->reg_shift = (cpu_is_pxa3xx() && (dev->id == 1)) ? 0 : 1;
+ i2c->reg_shift = REG_SHIFT(id->driver_data);
i2c->iobase = res->start;
i2c->iosize = res_len(res);
@@ -1150,6 +1165,7 @@ static struct platform_driver i2c_pxa_driver = {
.name = "pxa2xx-i2c",
.owner = THIS_MODULE,
},
+ .id_table = i2c_pxa_id_table,
};
static int __init i2c_adap_pxa_init(void)
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
index f320ab27da46..139f0c7f12a4 100644
--- a/drivers/i2c/busses/i2c-sis5595.c
+++ b/drivers/i2c/busses/i2c-sis5595.c
@@ -256,7 +256,7 @@ static int sis5595_transaction(struct i2c_adapter *adap)
} while (!(temp & 0x40) && (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */
- if (timeout >= MAX_TIMEOUT) {
+ if (timeout > MAX_TIMEOUT) {
dev_dbg(&adap->dev, "SMBus Timeout!\n");
result = -ETIMEDOUT;
}
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
index 50c3610e6028..70ca41e90e58 100644
--- a/drivers/i2c/busses/i2c-sis630.c
+++ b/drivers/i2c/busses/i2c-sis630.c
@@ -173,7 +173,7 @@ static int sis630_transaction_wait(struct i2c_adapter *adap, int size)
} while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */
- if (timeout >= MAX_TIMEOUT) {
+ if (timeout > MAX_TIMEOUT) {
dev_dbg(&adap->dev, "SMBus Timeout!\n");
result = -ETIMEDOUT;
}
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index 7e1594b40579..8295885b2fdb 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -132,7 +132,7 @@ static int sis96x_transaction(int size)
} while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */
- if (timeout >= MAX_TIMEOUT) {
+ if (timeout > MAX_TIMEOUT) {
dev_dbg(&sis96x_adapter.dev, "SMBus Timeout! (0x%02x)\n", temp);
result = -ETIMEDOUT;
}
diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c
index 1a474acc0ddd..7663d57833a0 100644
--- a/drivers/i2c/busses/i2c-voodoo3.c
+++ b/drivers/i2c/busses/i2c-voodoo3.c
@@ -163,7 +163,6 @@ static struct i2c_algo_bit_data voo_i2c_bit_data = {
static struct i2c_adapter voodoo3_i2c_adapter = {
.owner = THIS_MODULE,
- .class = I2C_CLASS_TV_ANALOG,
.name = "I2C Voodoo3/Banshee adapter",
.algo_data = &voo_i2c_bit_data,
};
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 8f8c81eb0aee..02d746c9c474 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -64,21 +64,6 @@ config SENSORS_PCA9539
This driver is deprecated and will be dropped soon. Use
drivers/gpio/pca953x.c instead.
-config SENSORS_MAX6875
- tristate "Maxim MAX6875 Power supply supervisor"
- depends on EXPERIMENTAL
- help
- If you say yes here you get support for the Maxim MAX6875
- EEPROM-programmable, quad power-supply sequencer/supervisor.
-
- This provides an interface to program the EEPROM and reset the chip.
-
- This driver also supports the Maxim MAX6874 hex power-supply
- sequencer/supervisor if found at a compatible address.
-
- This driver can also be built as a module. If so, the module
- will be called max6875.
-
config SENSORS_TSL2550
tristate "Taos TSL2550 ambient light sensor"
depends on EXPERIMENTAL
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 55a376037183..f4680d16ee34 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -11,7 +11,6 @@
#
obj-$(CONFIG_DS1682) += ds1682.o
-obj-$(CONFIG_SENSORS_MAX6875) += max6875.o
obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o
obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
obj-$(CONFIG_PCF8575) += pcf8575.o
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 85e2e919d1cd..864e9e10c36e 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -29,7 +29,6 @@
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/idr.h>
-#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <linux/completion.h>
#include <linux/hardirq.h>
@@ -39,11 +38,12 @@
#include "i2c-core.h"
+/* core_lock protects i2c_adapter_idr and userspace_devices, amongst others */
static DEFINE_MUTEX(core_lock);
static DEFINE_IDR(i2c_adapter_idr);
+static LIST_HEAD(userspace_devices);
-#define is_newstyle_driver(d) ((d)->probe || (d)->remove || (d)->detect)
-
+static int i2c_check_addr(struct i2c_adapter *adapter, int addr);
static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
/* ------------------------------------------------------------------------- */
@@ -64,12 +64,6 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)
struct i2c_client *client = to_i2c_client(dev);
struct i2c_driver *driver = to_i2c_driver(drv);
- /* make legacy i2c drivers bypass driver model probing entirely;
- * such drivers scan each i2c adapter/bus themselves.
- */
- if (!is_newstyle_driver(driver))
- return 0;
-
/* match on an id table if there is one */
if (driver->id_table)
return i2c_match_id(driver->id_table, client) != NULL;
@@ -84,10 +78,6 @@ static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct i2c_client *client = to_i2c_client(dev);
- /* by definition, legacy drivers can't hotplug */
- if (dev->driver)
- return 0;
-
if (add_uevent_var(env, "MODALIAS=%s%s",
I2C_MODULE_PREFIX, client->name))
return -ENOMEM;
@@ -176,12 +166,6 @@ static int i2c_device_resume(struct device *dev)
return driver->resume(to_i2c_client(dev));
}
-static void i2c_client_release(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- complete(&client->released);
-}
-
static void i2c_client_dev_release(struct device *dev)
{
kfree(to_i2c_client(dev));
@@ -241,15 +225,17 @@ EXPORT_SYMBOL(i2c_verify_client);
/**
- * i2c_new_device - instantiate an i2c device for use with a new style driver
+ * i2c_new_device - instantiate an i2c device
* @adap: the adapter managing the device
* @info: describes one I2C device; bus_num is ignored
* Context: can sleep
*
- * Create a device to work with a new style i2c driver, where binding is
- * handled through driver model probe()/remove() methods. This call is not
- * appropriate for use by mainboad initialization logic, which usually runs
- * during an arch_initcall() long before any i2c_adapter could exist.
+ * Create an i2c device. Binding is handled through driver model
+ * probe()/remove() methods. A driver may be bound to this device when we
+ * return from this function, or any later moment (e.g. maybe hotplugging will
+ * load the driver module). This call is not appropriate for use by mainboard
+ * initialization logic, which usually runs during an arch_initcall() long
+ * before any i2c_adapter could exist.
*
* This returns the new i2c client, which may be saved for later use with
* i2c_unregister_device(); or NULL to indicate an error.
@@ -277,17 +263,31 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
strlcpy(client->name, info->type, sizeof(client->name));
- /* a new style driver may be bound to this device when we
- * return from this function, or any later moment (e.g. maybe
- * hotplugging will load the driver module). and the device
- * refcount model is the standard driver model one.
- */
- status = i2c_attach_client(client);
- if (status < 0) {
- kfree(client);
- client = NULL;
- }
+ /* Check for address business */
+ status = i2c_check_addr(adap, client->addr);
+ if (status)
+ goto out_err;
+
+ client->dev.parent = &client->adapter->dev;
+ client->dev.bus = &i2c_bus_type;
+ client->dev.release = i2c_client_dev_release;
+
+ dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
+ client->addr);
+ status = device_register(&client->dev);
+ if (status)
+ goto out_err;
+
+ dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n",
+ client->name, dev_name(&client->dev));
+
return client;
+
+out_err:
+ dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x "
+ "(%d)\n", client->name, client->addr, status);
+ kfree(client);
+ return NULL;
}
EXPORT_SYMBOL_GPL(i2c_new_device);
@@ -299,28 +299,6 @@ EXPORT_SYMBOL_GPL(i2c_new_device);
*/
void i2c_unregister_device(struct i2c_client *client)
{
- struct i2c_adapter *adapter = client->adapter;
- struct i2c_driver *driver = client->driver;
-
- if (driver && !is_newstyle_driver(driver)) {
- dev_err(&client->dev, "can't unregister devices "
- "with legacy drivers\n");
- WARN_ON(1);
- return;
- }
-
- if (adapter->client_unregister) {
- if (adapter->client_unregister(client)) {
- dev_warn(&client->dev,
- "client_unregister [%s] failed\n",
- client->name);
- }
- }
-
- mutex_lock(&adapter->clist_lock);
- list_del(&client->list);
- mutex_unlock(&adapter->clist_lock);
-
device_unregister(&client->dev);
}
EXPORT_SYMBOL_GPL(i2c_unregister_device);
@@ -394,8 +372,128 @@ show_adapter_name(struct device *dev, struct device_attribute *attr, char *buf)
return sprintf(buf, "%s\n", adap->name);
}
+/*
+ * Let users instantiate I2C devices through sysfs. This can be used when
+ * platform initialization code doesn't contain the proper data for
+ * whatever reason. Also useful for drivers that do device detection and
+ * detection fails, either because the device uses an unexpected address,
+ * or this is a compatible device with different ID register values.
+ *
+ * Parameter checking may look overzealous, but we really don't want
+ * the user to provide incorrect parameters.
+ */
+static ssize_t
+i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_adapter *adap = to_i2c_adapter(dev);
+ struct i2c_board_info info;
+ struct i2c_client *client;
+ char *blank, end;
+ int res;
+
+ dev_warn(dev, "The new_device interface is still experimental "
+ "and may change in a near future\n");
+ memset(&info, 0, sizeof(struct i2c_board_info));
+
+ blank = strchr(buf, ' ');
+ if (!blank) {
+ dev_err(dev, "%s: Missing parameters\n", "new_device");
+ return -EINVAL;
+ }
+ if (blank - buf > I2C_NAME_SIZE - 1) {
+ dev_err(dev, "%s: Invalid device name\n", "new_device");
+ return -EINVAL;
+ }
+ memcpy(info.type, buf, blank - buf);
+
+ /* Parse remaining parameters, reject extra parameters */
+ res = sscanf(++blank, "%hi%c", &info.addr, &end);
+ if (res < 1) {
+ dev_err(dev, "%s: Can't parse I2C address\n", "new_device");
+ return -EINVAL;
+ }
+ if (res > 1 && end != '\n') {
+ dev_err(dev, "%s: Extra parameters\n", "new_device");
+ return -EINVAL;
+ }
+
+ if (info.addr < 0x03 || info.addr > 0x77) {
+ dev_err(dev, "%s: Invalid I2C address 0x%hx\n", "new_device",
+ info.addr);
+ return -EINVAL;
+ }
+
+ client = i2c_new_device(adap, &info);
+ if (!client)
+ return -EEXIST;
+
+ /* Keep track of the added device */
+ mutex_lock(&core_lock);
+ list_add_tail(&client->detected, &userspace_devices);
+ mutex_unlock(&core_lock);
+ dev_info(dev, "%s: Instantiated device %s at 0x%02hx\n", "new_device",
+ info.type, info.addr);
+
+ return count;
+}
+
+/*
+ * And of course let the users delete the devices they instantiated, if
+ * they got it wrong. This interface can only be used to delete devices
+ * instantiated by i2c_sysfs_new_device above. This guarantees that we
+ * don't delete devices to which some kernel code still has references.
+ *
+ * Parameter checking may look overzealous, but we really don't want
+ * the user to delete the wrong device.
+ */
+static ssize_t
+i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_adapter *adap = to_i2c_adapter(dev);
+ struct i2c_client *client, *next;
+ unsigned short addr;
+ char end;
+ int res;
+
+ /* Parse parameters, reject extra parameters */
+ res = sscanf(buf, "%hi%c", &addr, &end);
+ if (res < 1) {
+ dev_err(dev, "%s: Can't parse I2C address\n", "delete_device");
+ return -EINVAL;
+ }
+ if (res > 1 && end != '\n') {
+ dev_err(dev, "%s: Extra parameters\n", "delete_device");
+ return -EINVAL;
+ }
+
+ /* Make sure the device was added through sysfs */
+ res = -ENOENT;
+ mutex_lock(&core_lock);
+ list_for_each_entry_safe(client, next, &userspace_devices, detected) {
+ if (client->addr == addr && client->adapter == adap) {
+ dev_info(dev, "%s: Deleting device %s at 0x%02hx\n",
+ "delete_device", client->name, client->addr);
+
+ list_del(&client->detected);
+ i2c_unregister_device(client);
+ res = count;
+ break;
+ }
+ }
+ mutex_unlock(&core_lock);
+
+ if (res < 0)
+ dev_err(dev, "%s: Can't find device in list\n",
+ "delete_device");
+ return res;
+}
+
static struct device_attribute i2c_adapter_attrs[] = {
__ATTR(name, S_IRUGO, show_adapter_name, NULL),
+ __ATTR(new_device, S_IWUSR, NULL, i2c_sysfs_new_device),
+ __ATTR(delete_device, S_IWUSR, NULL, i2c_sysfs_delete_device),
{ },
};
@@ -446,21 +544,9 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
return -EAGAIN;
mutex_init(&adap->bus_lock);
- mutex_init(&adap->clist_lock);
- INIT_LIST_HEAD(&adap->clients);
mutex_lock(&core_lock);
- /* Add the adapter to the driver core.
- * If the parent pointer is not set up,
- * we add this adapter to the host bus.
- */
- if (adap->dev.parent == NULL) {
- adap->dev.parent = &platform_bus;
- pr_debug("I2C adapter driver [%s] forgot to specify "
- "physical device\n", adap->name);
- }
-
/* Set default timeout to 1 second if not already set */
if (adap->timeout == 0)
adap->timeout = HZ;
@@ -474,7 +560,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
- /* create pre-declared device nodes for new-style drivers */
+ /* create pre-declared device nodes */
if (adap->nr < __i2c_first_dynamic_bus_num)
i2c_scan_static_board_info(adap);
@@ -617,7 +703,6 @@ static int i2c_do_del_adapter(struct device_driver *d, void *data)
*/
int i2c_del_adapter(struct i2c_adapter *adap)
{
- struct i2c_client *client, *_n;
int res = 0;
mutex_lock(&core_lock);
@@ -636,28 +721,6 @@ int i2c_del_adapter(struct i2c_adapter *adap)
if (res)
goto out_unlock;
- /* detach any active clients. This must be done first, because
- * it can fail; in which case we give up. */
- list_for_each_entry_safe_reverse(client, _n, &adap->clients, list) {
- struct i2c_driver *driver;
-
- driver = client->driver;
-
- /* new style, follow standard driver model */
- if (!driver || is_newstyle_driver(driver)) {
- i2c_unregister_device(client);
- continue;
- }
-
- /* legacy drivers create and remove clients themselves */
- if ((res = driver->detach_client(client))) {
- dev_err(&adap->dev, "detach_client failed for client "
- "[%s] at address 0x%02x\n", client->name,
- client->addr);
- goto out_unlock;
- }
- }
-
/* clean up the sysfs representation */
init_completion(&adap->dev_released);
device_unregister(&adap->dev);
@@ -699,11 +762,7 @@ static int __attach_adapter(struct device *dev, void *data)
/*
* An i2c_driver is used with one or more i2c_client (device) nodes to access
- * i2c slave chips, on a bus instance associated with some i2c_adapter. There
- * are two models for binding the driver to its device: "new style" drivers
- * follow the standard Linux driver model and just respond to probe() calls
- * issued if the driver core sees they match(); "legacy" drivers create device
- * nodes themselves.
+ * i2c slave chips, on a bus instance associated with some i2c_adapter.
*/
int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
@@ -714,21 +773,11 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
if (unlikely(WARN_ON(!i2c_bus_type.p)))
return -EAGAIN;
- /* new style driver methods can't mix with legacy ones */
- if (is_newstyle_driver(driver)) {
- if (driver->detach_adapter || driver->detach_client) {
- printk(KERN_WARNING
- "i2c-core: driver [%s] is confused\n",
- driver->driver.name);
- return -EINVAL;
- }
- }
-
/* add the driver to the list of i2c drivers in the driver core */
driver->driver.owner = owner;
driver->driver.bus = &i2c_bus_type;
- /* for new style drivers, when registration returns the driver core
+ /* When registration returns, the driver core
* will have called probe() for all matching-but-unbound devices.
*/
res = driver_register(&driver->driver);
@@ -764,32 +813,11 @@ static int __detach_adapter(struct device *dev, void *data)
i2c_unregister_device(client);
}
- if (is_newstyle_driver(driver))
- return 0;
-
- /* Have a look at each adapter, if clients of this driver are still
- * attached. If so, detach them to be able to kill the driver
- * afterwards.
- */
if (driver->detach_adapter) {
if (driver->detach_adapter(adapter))
dev_err(&adapter->dev,
"detach_adapter failed for driver [%s]\n",
driver->driver.name);
- } else {
- struct i2c_client *client, *_n;
-
- list_for_each_entry_safe(client, _n, &adapter->clients, list) {
- if (client->driver != driver)
- continue;
- dev_dbg(&adapter->dev,
- "detaching client [%s] at 0x%02x\n",
- client->name, client->addr);
- if (driver->detach_client(client))
- dev_err(&adapter->dev, "detach_client "
- "failed for client [%s] at 0x%02x\n",
- client->name, client->addr);
- }
}
return 0;
@@ -831,86 +859,6 @@ static int i2c_check_addr(struct i2c_adapter *adapter, int addr)
return device_for_each_child(&adapter->dev, &addr, __i2c_check_addr);
}
-int i2c_attach_client(struct i2c_client *client)
-{
- struct i2c_adapter *adapter = client->adapter;
- int res;
-
- /* Check for address business */
- res = i2c_check_addr(adapter, client->addr);
- if (res)
- return res;
-
- client->dev.parent = &client->adapter->dev;
- client->dev.bus = &i2c_bus_type;
-
- if (client->driver)
- client->dev.driver = &client->driver->driver;
-
- if (client->driver && !is_newstyle_driver(client->driver)) {
- client->dev.release = i2c_client_release;
- dev_set_uevent_suppress(&client->dev, 1);
- } else
- client->dev.release = i2c_client_dev_release;
-
- dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adapter),
- client->addr);
- res = device_register(&client->dev);
- if (res)
- goto out_err;
-
- mutex_lock(&adapter->clist_lock);
- list_add_tail(&client->list, &adapter->clients);
- mutex_unlock(&adapter->clist_lock);
-
- dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
- client->name, dev_name(&client->dev));
-
- if (adapter->client_register) {
- if (adapter->client_register(client)) {
- dev_dbg(&adapter->dev, "client_register "
- "failed for client [%s] at 0x%02x\n",
- client->name, client->addr);
- }
- }
-
- return 0;
-
-out_err:
- dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x "
- "(%d)\n", client->name, client->addr, res);
- return res;
-}
-EXPORT_SYMBOL(i2c_attach_client);
-
-int i2c_detach_client(struct i2c_client *client)
-{
- struct i2c_adapter *adapter = client->adapter;
- int res = 0;
-
- if (adapter->client_unregister) {
- res = adapter->client_unregister(client);
- if (res) {
- dev_err(&client->dev,
- "client_unregister [%s] failed, "
- "client not detached\n", client->name);
- goto out;
- }
- }
-
- mutex_lock(&adapter->clist_lock);
- list_del(&client->list);
- mutex_unlock(&adapter->clist_lock);
-
- init_completion(&client->released);
- device_unregister(&client->dev);
- wait_for_completion(&client->released);
-
- out:
- return res;
-}
-EXPORT_SYMBOL(i2c_detach_client);
-
/**
* i2c_use_client - increments the reference count of the i2c client structure
* @client: the client being referenced
@@ -1022,7 +970,8 @@ module_exit(i2c_exit);
*/
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
- int ret;
+ unsigned long orig_jiffies;
+ int ret, try;
/* REVISIT the fault reporting model here is weak:
*
@@ -1060,7 +1009,15 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
mutex_lock_nested(&adap->bus_lock, adap->level);
}
- ret = adap->algo->master_xfer(adap,msgs,num);
+ /* Retry automatically on arbitration loss */
+ orig_jiffies = jiffies;
+ for (ret = 0, try = 0; try <= adap->retries; try++) {
+ ret = adap->algo->master_xfer(adap, msgs, num);
+ if (ret != -EAGAIN)
+ break;
+ if (time_after(jiffies, orig_jiffies + adap->timeout))
+ break;
+ }
mutex_unlock(&adap->bus_lock);
return ret;
@@ -1131,144 +1088,7 @@ EXPORT_SYMBOL(i2c_master_recv);
* Will not work for 10-bit addresses!
* ----------------------------------------------------
*/
-static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind,
- int (*found_proc) (struct i2c_adapter *, int, int))
-{
- int err;
-
- /* Make sure the address is valid */
- if (addr < 0x03 || addr > 0x77) {
- dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",
- addr);
- return -EINVAL;
- }
- /* Skip if already in use */
- if (i2c_check_addr(adapter, addr))
- return 0;
-
- /* Make sure there is something at this address, unless forced */
- if (kind < 0) {
- if (i2c_smbus_xfer(adapter, addr, 0, 0, 0,
- I2C_SMBUS_QUICK, NULL) < 0)
- return 0;
-
- /* prevent 24RF08 corruption */
- if ((addr & ~0x0f) == 0x50)
- i2c_smbus_xfer(adapter, addr, 0, 0, 0,
- I2C_SMBUS_QUICK, NULL);
- }
-
- /* Finally call the custom detection function */
- err = found_proc(adapter, addr, kind);
- /* -ENODEV can be returned if there is a chip at the given address
- but it isn't supported by this chip driver. We catch it here as
- this isn't an error. */
- if (err == -ENODEV)
- err = 0;
-
- if (err)
- dev_warn(&adapter->dev, "Client creation failed at 0x%x (%d)\n",
- addr, err);
- return err;
-}
-
-int i2c_probe(struct i2c_adapter *adapter,
- const struct i2c_client_address_data *address_data,
- int (*found_proc) (struct i2c_adapter *, int, int))
-{
- int i, err;
- int adap_id = i2c_adapter_id(adapter);
-
- /* Force entries are done first, and are not affected by ignore
- entries */
- if (address_data->forces) {
- const unsigned short * const *forces = address_data->forces;
- int kind;
-
- for (kind = 0; forces[kind]; kind++) {
- for (i = 0; forces[kind][i] != I2C_CLIENT_END;
- i += 2) {
- if (forces[kind][i] == adap_id
- || forces[kind][i] == ANY_I2C_BUS) {
- dev_dbg(&adapter->dev, "found force "
- "parameter for adapter %d, "
- "addr 0x%02x, kind %d\n",
- adap_id, forces[kind][i + 1],
- kind);
- err = i2c_probe_address(adapter,
- forces[kind][i + 1],
- kind, found_proc);
- if (err)
- return err;
- }
- }
- }
- }
-
- /* Stop here if we can't use SMBUS_QUICK */
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) {
- if (address_data->probe[0] == I2C_CLIENT_END
- && address_data->normal_i2c[0] == I2C_CLIENT_END)
- return 0;
-
- dev_dbg(&adapter->dev, "SMBus Quick command not supported, "
- "can't probe for chips\n");
- return -EOPNOTSUPP;
- }
-
- /* Probe entries are done second, and are not affected by ignore
- entries either */
- for (i = 0; address_data->probe[i] != I2C_CLIENT_END; i += 2) {
- if (address_data->probe[i] == adap_id
- || address_data->probe[i] == ANY_I2C_BUS) {
- dev_dbg(&adapter->dev, "found probe parameter for "
- "adapter %d, addr 0x%02x\n", adap_id,
- address_data->probe[i + 1]);
- err = i2c_probe_address(adapter,
- address_data->probe[i + 1],
- -1, found_proc);
- if (err)
- return err;
- }
- }
-
- /* Normal entries are done last, unless shadowed by an ignore entry */
- for (i = 0; address_data->normal_i2c[i] != I2C_CLIENT_END; i += 1) {
- int j, ignore;
-
- ignore = 0;
- for (j = 0; address_data->ignore[j] != I2C_CLIENT_END;
- j += 2) {
- if ((address_data->ignore[j] == adap_id ||
- address_data->ignore[j] == ANY_I2C_BUS)
- && address_data->ignore[j + 1]
- == address_data->normal_i2c[i]) {
- dev_dbg(&adapter->dev, "found ignore "
- "parameter for adapter %d, "
- "addr 0x%02x\n", adap_id,
- address_data->ignore[j + 1]);
- ignore = 1;
- break;
- }
- }
- if (ignore)
- continue;
-
- dev_dbg(&adapter->dev, "found normal entry for adapter %d, "
- "addr 0x%02x\n", adap_id,
- address_data->normal_i2c[i]);
- err = i2c_probe_address(adapter, address_data->normal_i2c[i],
- -1, found_proc);
- if (err)
- return err;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(i2c_probe);
-
-/* Separate detection function for new-style drivers */
static int i2c_detect_address(struct i2c_client *temp_client, int kind,
struct i2c_driver *driver)
{
@@ -1509,7 +1329,7 @@ struct i2c_adapter* i2c_get_adapter(int id)
struct i2c_adapter *adapter;
mutex_lock(&core_lock);
- adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id);
+ adapter = idr_find(&i2c_adapter_idr, id);
if (adapter && !try_module_get(adapter->owner))
adapter = NULL;
@@ -1995,14 +1815,27 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
char read_write, u8 command, int protocol,
union i2c_smbus_data *data)
{
+ unsigned long orig_jiffies;
+ int try;
s32 res;
flags &= I2C_M_TEN | I2C_CLIENT_PEC;
if (adapter->algo->smbus_xfer) {
mutex_lock(&adapter->bus_lock);
- res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write,
- command, protocol, data);
+
+ /* Retry automatically on arbitration loss */
+ orig_jiffies = jiffies;
+ for (res = 0, try = 0; try <= adapter->retries; try++) {
+ res = adapter->algo->smbus_xfer(adapter, addr, flags,
+ read_write, command,
+ protocol, data);
+ if (res != -EAGAIN)
+ break;
+ if (time_after(jiffies,
+ orig_jiffies + adapter->timeout))
+ break;
+ }
mutex_unlock(&adapter->bus_lock);
} else
res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c
index 537da1cde16d..e59b6dee9ae2 100644
--- a/drivers/ide/alim15x3.c
+++ b/drivers/ide/alim15x3.c
@@ -402,27 +402,23 @@ static u8 ali_cable_detect(ide_hwif_t *hwif)
return cbl;
}
-#if !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC)
+#ifndef CONFIG_SPARC64
/**
* init_hwif_ali15x3 - Initialize the ALI IDE x86 stuff
* @hwif: interface to configure
*
* Obtain the IRQ tables for an ALi based IDE solution on the PC
* class platforms. This part of the code isn't applicable to the
- * Sparc and PowerPC systems.
+ * Sparc systems.
*/
static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif)
{
- struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 ideic, inmir;
s8 irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6,
1, 11, 0, 12, 0, 14, 0, 15 };
int irq = -1;
- if (dev->device == PCI_DEVICE_ID_AL_M5229)
- hwif->irq = hwif->channel ? 15 : 14;
-
if (isa_dev) {
/*
* read IDE interface control
@@ -455,7 +451,7 @@ static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif)
}
#else
#define init_hwif_ali15x3 NULL
-#endif /* !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC) */
+#endif /* CONFIG_SPARC64 */
/**
* init_dma_ali15x3 - set up DMA on ALi15x3
diff --git a/drivers/ide/cs5536.c b/drivers/ide/cs5536.c
index 353a35bbba63..0332a95eefd4 100644
--- a/drivers/ide/cs5536.c
+++ b/drivers/ide/cs5536.c
@@ -236,6 +236,7 @@ static const struct ide_dma_ops cs5536_dma_ops = {
.dma_test_irq = ide_dma_test_irq,
.dma_lost_irq = ide_dma_lost_irq,
.dma_timer_expiry = ide_dma_sff_timer_expiry,
+ .dma_sff_read_status = ide_dma_sff_read_status,
};
static const struct ide_port_info cs5536_info = {
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
index a0eb87f59134..0feb66c720e1 100644
--- a/drivers/ide/hpt366.c
+++ b/drivers/ide/hpt366.c
@@ -3,7 +3,7 @@
* Portions Copyright (C) 2001 Sun Microsystems, Inc.
* Portions Copyright (C) 2003 Red Hat Inc
* Portions Copyright (C) 2007 Bartlomiej Zolnierkiewicz
- * Portions Copyright (C) 2005-2008 MontaVista Software, Inc.
+ * Portions Copyright (C) 2005-2009 MontaVista Software, Inc.
*
* Thanks to HighPoint Technologies for their assistance, and hardware.
* Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his
@@ -114,6 +114,8 @@
* the register setting lists into the table indexed by the clock selected
* - set the correct hwif->ultra_mask for each individual chip
* - add Ultra and MW DMA mode filtering for the HPT37[24] based SATA cards
+ * - stop resetting HPT370's state machine before each DMA transfer as that has
+ * caused more harm than good
* Sergei Shtylyov, <sshtylyov@ru.mvista.com> or <source@mvista.com>
*/
@@ -133,7 +135,7 @@
#define DRV_NAME "hpt366"
/* various tuning parameters */
-#define HPT_RESET_STATE_ENGINE
+#undef HPT_RESET_STATE_ENGINE
#undef HPT_DELAY_INTERRUPT
static const char *quirk_drives[] = {
@@ -808,7 +810,7 @@ static void hpt370_irq_timeout(ide_drive_t *drive)
/* get DMA command mode */
dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
/* stop DMA */
- outb(dma_cmd & ~0x1, hwif->dma_base + ATA_DMA_CMD);
+ outb(dma_cmd & ~ATA_DMA_START, hwif->dma_base + ATA_DMA_CMD);
hpt370_clear_engine(drive);
}
@@ -825,11 +827,11 @@ static int hpt370_dma_end(ide_drive_t *drive)
ide_hwif_t *hwif = drive->hwif;
u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
- if (dma_stat & 0x01) {
+ if (dma_stat & ATA_DMA_ACTIVE) {
/* wait a little */
udelay(20);
dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
- if (dma_stat & 0x01)
+ if (dma_stat & ATA_DMA_ACTIVE)
hpt370_irq_timeout(drive);
}
return ide_dma_end(drive);
@@ -851,7 +853,7 @@ static int hpt374_dma_test_irq(ide_drive_t *drive)
dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
/* return 1 if INTR asserted */
- if (dma_stat & 4)
+ if (dma_stat & ATA_DMA_INTR)
return 1;
return 0;
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index 7201b176d75b..701d2cafcd4f 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -80,34 +80,6 @@ void ide_init_pc(struct ide_atapi_pc *pc)
EXPORT_SYMBOL_GPL(ide_init_pc);
/*
- * Generate a new packet command request in front of the request queue, before
- * the current request, so that it will be processed immediately, on the next
- * pass through the driver.
- */
-static void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk,
- struct ide_atapi_pc *pc, struct request *rq)
-{
- blk_rq_init(NULL, rq);
- rq->cmd_type = REQ_TYPE_SPECIAL;
- rq->cmd_flags |= REQ_PREEMPT;
- rq->buffer = (char *)pc;
- rq->rq_disk = disk;
-
- if (pc->req_xfer) {
- rq->data = pc->buf;
- rq->data_len = pc->req_xfer;
- }
-
- memcpy(rq->cmd, pc->c, 12);
- if (drive->media == ide_tape)
- rq->cmd[13] = REQ_IDETAPE_PC1;
-
- drive->hwif->rq = NULL;
-
- elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0);
-}
-
-/*
* Add a special packet command request to the tail of the request queue,
* and wait for it to be serviced.
*/
@@ -119,19 +91,21 @@ int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk,
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_SPECIAL;
- rq->buffer = (char *)pc;
+ rq->special = (char *)pc;
if (pc->req_xfer) {
- rq->data = pc->buf;
- rq->data_len = pc->req_xfer;
+ error = blk_rq_map_kern(drive->queue, rq, pc->buf, pc->req_xfer,
+ GFP_NOIO);
+ if (error)
+ goto put_req;
}
memcpy(rq->cmd, pc->c, 12);
if (drive->media == ide_tape)
rq->cmd[13] = REQ_IDETAPE_PC1;
error = blk_execute_rq(drive->queue, disk, rq, 0);
+put_req:
blk_put_request(rq);
-
return error;
}
EXPORT_SYMBOL_GPL(ide_queue_pc_tail);
@@ -191,20 +165,103 @@ void ide_create_request_sense_cmd(ide_drive_t *drive, struct ide_atapi_pc *pc)
}
EXPORT_SYMBOL_GPL(ide_create_request_sense_cmd);
+void ide_prep_sense(ide_drive_t *drive, struct request *rq)
+{
+ struct request_sense *sense = &drive->sense_data;
+ struct request *sense_rq = &drive->sense_rq;
+ unsigned int cmd_len, sense_len;
+ int err;
+
+ debug_log("%s: enter\n", __func__);
+
+ switch (drive->media) {
+ case ide_floppy:
+ cmd_len = 255;
+ sense_len = 18;
+ break;
+ case ide_tape:
+ cmd_len = 20;
+ sense_len = 20;
+ break;
+ default:
+ cmd_len = 18;
+ sense_len = 18;
+ }
+
+ BUG_ON(sense_len > sizeof(*sense));
+
+ if (blk_sense_request(rq) || drive->sense_rq_armed)
+ return;
+
+ memset(sense, 0, sizeof(*sense));
+
+ blk_rq_init(rq->q, sense_rq);
+
+ err = blk_rq_map_kern(drive->queue, sense_rq, sense, sense_len,
+ GFP_NOIO);
+ if (unlikely(err)) {
+ if (printk_ratelimit())
+ printk(KERN_WARNING "%s: failed to map sense buffer\n",
+ drive->name);
+ return;
+ }
+
+ sense_rq->rq_disk = rq->rq_disk;
+ sense_rq->cmd[0] = GPCMD_REQUEST_SENSE;
+ sense_rq->cmd[4] = cmd_len;
+ sense_rq->cmd_type = REQ_TYPE_SENSE;
+ sense_rq->cmd_flags |= REQ_PREEMPT;
+
+ if (drive->media == ide_tape)
+ sense_rq->cmd[13] = REQ_IDETAPE_PC1;
+
+ drive->sense_rq_armed = true;
+}
+EXPORT_SYMBOL_GPL(ide_prep_sense);
+
+int ide_queue_sense_rq(ide_drive_t *drive, void *special)
+{
+ /* deferred failure from ide_prep_sense() */
+ if (!drive->sense_rq_armed) {
+ printk(KERN_WARNING "%s: failed queue sense request\n",
+ drive->name);
+ return -ENOMEM;
+ }
+
+ drive->sense_rq.special = special;
+ drive->sense_rq_armed = false;
+
+ drive->hwif->rq = NULL;
+
+ elv_add_request(drive->queue, &drive->sense_rq,
+ ELEVATOR_INSERT_FRONT, 0);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ide_queue_sense_rq);
+
/*
* Called when an error was detected during the last packet command.
- * We queue a request sense packet command in the head of the request list.
+ * We queue a request sense packet command at the head of the request
+ * queue.
*/
-void ide_retry_pc(ide_drive_t *drive, struct gendisk *disk)
+void ide_retry_pc(ide_drive_t *drive)
{
- struct request *rq = &drive->request_sense_rq;
+ struct request *sense_rq = &drive->sense_rq;
struct ide_atapi_pc *pc = &drive->request_sense_pc;
(void)ide_read_error(drive);
- ide_create_request_sense_cmd(drive, pc);
+
+ /* init pc from sense_rq */
+ ide_init_pc(pc);
+ memcpy(pc->c, sense_rq->cmd, 12);
+ pc->buf = bio_data(sense_rq->bio); /* pointer to mapped address */
+ pc->req_xfer = sense_rq->data_len;
+
if (drive->media == ide_tape)
set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
- ide_queue_pc_head(drive, disk, pc, rq);
+
+ if (ide_queue_sense_rq(drive, pc))
+ ide_complete_rq(drive, -EIO, blk_rq_bytes(drive->hwif->rq));
}
EXPORT_SYMBOL_GPL(ide_retry_pc);
@@ -276,7 +333,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
struct ide_cmd *cmd = &hwif->cmd;
struct request *rq = hwif->rq;
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
- xfer_func_t *xferfunc;
unsigned int timeout, done;
u16 bcount;
u8 stat, ireason, dsc = 0;
@@ -303,11 +359,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
drive->name, rq_data_dir(pc->rq)
? "write" : "read");
pc->flags |= PC_FLAG_DMA_ERROR;
- } else {
+ } else
pc->xferred = pc->req_xfer;
- if (drive->pc_update_buffers)
- drive->pc_update_buffers(drive, pc);
- }
debug_log("%s: DMA finished\n", drive->name);
}
@@ -343,7 +396,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
debug_log("[cmd %x]: check condition\n", rq->cmd[0]);
/* Retry operation */
- ide_retry_pc(drive, rq->rq_disk);
+ ide_retry_pc(drive);
/* queued, but not started */
return ide_stopped;
@@ -353,6 +406,12 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0)
dsc = 1;
+ /*
+ * ->pc_callback() might change rq->data_len for
+ * residual count, cache total length.
+ */
+ done = blk_rq_bytes(rq);
+
/* Command finished - Call the callback function */
uptodate = drive->pc_callback(drive, dsc);
@@ -361,7 +420,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
if (blk_special_request(rq)) {
rq->errors = 0;
- done = blk_rq_bytes(rq);
error = 0;
} else {
@@ -370,11 +428,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
rq->errors = -EIO;
}
- if (drive->media == ide_tape)
- done = ide_rq_bytes(rq); /* FIXME */
- else
- done = blk_rq_bytes(rq);
-
error = uptodate ? 0 : -EIO;
}
@@ -407,21 +460,11 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
return ide_do_reset(drive);
}
- xferfunc = write ? tp_ops->output_data : tp_ops->input_data;
-
- if (drive->media == ide_floppy && pc->buf == NULL) {
- done = min_t(unsigned int, bcount, cmd->nleft);
- ide_pio_bytes(drive, cmd, write, done);
- } else if (drive->media == ide_tape && pc->bh) {
- done = drive->pc_io_buffers(drive, pc, bcount, write);
- } else {
- done = min_t(unsigned int, bcount, pc->req_xfer - pc->xferred);
- xferfunc(drive, NULL, pc->cur_pos, done);
- }
+ done = min_t(unsigned int, bcount, cmd->nleft);
+ ide_pio_bytes(drive, cmd, write, done);
- /* Update the current position */
+ /* Update transferred byte count */
pc->xferred += done;
- pc->cur_pos += done;
bcount -= done;
@@ -525,7 +568,7 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
/*
* If necessary schedule the packet transfer to occur 'timeout'
- * miliseconds later in ide_delayed_transfer_pc() after the
+ * milliseconds later in ide_delayed_transfer_pc() after the
* device says it's ready for a packet.
*/
if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) {
@@ -599,7 +642,6 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd)
/* We haven't transferred any data yet */
pc->xferred = 0;
- pc->cur_pos = pc->buf;
valid_tf = IDE_VALID_DEVICE;
bcount = ((drive->media == ide_tape) ?
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 3aec19d1fdfc..a75e4ee1cd17 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -206,54 +206,25 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive,
ide_cd_log_error(drive->name, failed_command, sense);
}
-static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
- struct request *failed_command)
-{
- struct cdrom_info *info = drive->driver_data;
- struct request *rq = &drive->request_sense_rq;
-
- ide_debug_log(IDE_DBG_SENSE, "enter");
-
- if (sense == NULL)
- sense = &info->sense_data;
-
- /* stuff the sense request in front of our current request */
- blk_rq_init(NULL, rq);
- rq->cmd_type = REQ_TYPE_ATA_PC;
- rq->rq_disk = info->disk;
-
- rq->data = sense;
- rq->cmd[0] = GPCMD_REQUEST_SENSE;
- rq->cmd[4] = 18;
- rq->data_len = 18;
-
- rq->cmd_type = REQ_TYPE_SENSE;
- rq->cmd_flags |= REQ_PREEMPT;
-
- /* NOTE! Save the failed command in "rq->buffer" */
- rq->buffer = (void *) failed_command;
-
- if (failed_command)
- ide_debug_log(IDE_DBG_SENSE, "failed_cmd: 0x%x",
- failed_command->cmd[0]);
-
- drive->hwif->rq = NULL;
-
- elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0);
-}
-
static void ide_cd_complete_failed_rq(ide_drive_t *drive, struct request *rq)
{
/*
- * For REQ_TYPE_SENSE, "rq->buffer" points to the original
- * failed request
+ * For REQ_TYPE_SENSE, "rq->special" points to the original
+ * failed request. Also, the sense data should be read
+ * directly from rq which might be different from the original
+ * sense buffer if it got copied during mapping.
*/
- struct request *failed = (struct request *)rq->buffer;
- struct cdrom_info *info = drive->driver_data;
- void *sense = &info->sense_data;
+ struct request *failed = (struct request *)rq->special;
+ void *sense = bio_data(rq->bio);
if (failed) {
if (failed->sense) {
+ /*
+ * Sense is always read into drive->sense_data.
+ * Copy back if the failed request has its
+ * sense pointer set.
+ */
+ memcpy(failed->sense, sense, 18);
sense = failed->sense;
failed->sense_len = rq->sense_len;
}
@@ -312,7 +283,6 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat)
ide_hwif_t *hwif = drive->hwif;
struct request *rq = hwif->rq;
int err, sense_key, do_end_request = 0;
- u8 quiet = rq->cmd_flags & REQ_QUIET;
/* get the IDE error register */
err = ide_read_error(drive);
@@ -347,7 +317,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat)
} else {
cdrom_saw_media_change(drive);
- if (blk_fs_request(rq) && !quiet)
+ if (blk_fs_request(rq) && !blk_rq_quiet(rq))
printk(KERN_ERR PFX "%s: tray open\n",
drive->name);
}
@@ -382,7 +352,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat)
* No point in retrying after an illegal request or data
* protect error.
*/
- if (!quiet)
+ if (!blk_rq_quiet(rq))
ide_dump_status(drive, "command error", stat);
do_end_request = 1;
break;
@@ -391,14 +361,14 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat)
* No point in re-trying a zillion times on a bad sector.
* If we got here the error is not correctable.
*/
- if (!quiet)
+ if (!blk_rq_quiet(rq))
ide_dump_status(drive, "media error "
"(bad sector)", stat);
do_end_request = 1;
break;
case BLANK_CHECK:
/* disk appears blank? */
- if (!quiet)
+ if (!blk_rq_quiet(rq))
ide_dump_status(drive, "media error (blank)",
stat);
do_end_request = 1;
@@ -429,7 +399,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat)
/* if we got a CHECK_CONDITION status, queue a request sense command */
if (stat & ATA_ERR)
- cdrom_queue_request_sense(drive, NULL, NULL);
+ return ide_queue_sense_rq(drive, NULL) ? 2 : 1;
return 1;
end_request:
@@ -443,8 +413,7 @@ end_request:
hwif->rq = NULL;
- cdrom_queue_request_sense(drive, rq->sense, rq);
- return 1;
+ return ide_queue_sense_rq(drive, rq) ? 2 : 1;
} else
return 2;
}
@@ -504,14 +473,8 @@ static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct ide_cmd *cmd)
* and some drives don't send them. Sigh.
*/
if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&
- cmd->nleft > 0 && cmd->nleft <= 5) {
- unsigned int ofs = cmd->nbytes - cmd->nleft;
-
- while (cmd->nleft > 0) {
- *((u8 *)rq->data + ofs++) = 0;
- cmd->nleft--;
- }
- }
+ cmd->nleft > 0 && cmd->nleft <= 5)
+ cmd->nleft = 0;
}
int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
@@ -544,8 +507,12 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
rq->cmd_flags |= cmd_flags;
rq->timeout = timeout;
if (buffer) {
- rq->data = buffer;
- rq->data_len = *bufflen;
+ error = blk_rq_map_kern(drive->queue, rq, buffer,
+ *bufflen, GFP_NOIO);
+ if (error) {
+ blk_put_request(rq);
+ return error;
+ }
}
error = blk_execute_rq(drive->queue, info->disk, rq, 0);
@@ -609,7 +576,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
struct request *rq = hwif->rq;
ide_expiry_t *expiry = NULL;
int dma_error = 0, dma, thislen, uptodate = 0;
- int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc, nsectors;
+ int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc = 0, nsectors;
int sense = blk_sense_request(rq);
unsigned int timeout;
u16 len;
@@ -839,15 +806,10 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
drive->dma = 0;
/* sg request */
- if (rq->bio || ((rq->cmd_type == REQ_TYPE_ATA_PC) && rq->data_len)) {
+ if (rq->bio) {
struct request_queue *q = drive->queue;
+ char *buf = bio_data(rq->bio);
unsigned int alignment;
- char *buf;
-
- if (rq->bio)
- buf = bio_data(rq->bio);
- else
- buf = rq->data;
drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
@@ -897,6 +859,9 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
goto out_end;
}
+ /* prepare sense request for this command */
+ ide_prep_sense(drive, rq);
+
memset(&cmd, 0, sizeof(cmd));
if (rq_data_dir(rq))
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index 1d97101099ce..93a3cf1b0f3f 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -87,10 +87,6 @@ struct cdrom_info {
struct atapi_toc *toc;
- /* The result of the last successful request sense command
- on this device. */
- struct request_sense sense_data;
-
u8 max_speed; /* Max speed of the drive. */
u8 current_speed; /* Current speed of the drive. */
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index a9fbe2c31210..c2438804d3c4 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -411,7 +411,6 @@ static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
cmd->protocol = ATA_PROT_NODATA;
rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
- rq->cmd_flags |= REQ_SOFTBARRIER;
rq->special = cmd;
}
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index a0b8cab1d9a6..d9123ecae4a9 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -510,23 +510,11 @@ ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
/*
* un-busy drive etc and make sure request is sane
*/
-
rq = hwif->rq;
- if (!rq)
- goto out;
-
- hwif->rq = NULL;
-
- rq->errors = 0;
-
- if (!rq->bio)
- goto out;
-
- rq->sector = rq->bio->bi_sector;
- rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
- rq->hard_cur_sectors = rq->current_nr_sectors;
- rq->buffer = bio_data(rq->bio);
-out:
+ if (rq) {
+ hwif->rq = NULL;
+ rq->errors = 0;
+ }
return ret;
}
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 2b4868d95f8b..537b7c558033 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -134,13 +134,17 @@ static ide_startstop_t ide_floppy_issue_pc(ide_drive_t *drive,
drive->pc = pc;
if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) {
+ unsigned int done = blk_rq_bytes(drive->hwif->rq);
+
if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR))
ide_floppy_report_error(floppy, pc);
+
/* Giving up */
pc->error = IDE_DRV_ERROR_GENERAL;
drive->failed_pc = NULL;
drive->pc_callback(drive, 0);
+ ide_complete_rq(drive, -EIO, done);
return ide_stopped;
}
@@ -216,15 +220,13 @@ static void idefloppy_blockpc_cmd(struct ide_disk_obj *floppy,
ide_init_pc(pc);
memcpy(pc->c, rq->cmd, sizeof(pc->c));
pc->rq = rq;
- if (rq->data_len && rq_data_dir(rq) == WRITE)
- pc->flags |= PC_FLAG_WRITING;
- pc->buf = rq->data;
- if (rq->bio)
+ if (rq->data_len) {
pc->flags |= PC_FLAG_DMA_OK;
- /*
- * possibly problematic, doesn't look like ide-floppy correctly
- * handled scattered requests if dma fails...
- */
+ if (rq_data_dir(rq) == WRITE)
+ pc->flags |= PC_FLAG_WRITING;
+ }
+ /* pio will be performed by ide_pio_bytes() which handles sg fine */
+ pc->buf = NULL;
pc->req_xfer = pc->buf_size = rq->data_len;
}
@@ -265,8 +267,8 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive,
}
pc = &floppy->queued_pc;
idefloppy_create_rw_cmd(drive, pc, rq, (unsigned long)block);
- } else if (blk_special_request(rq)) {
- pc = (struct ide_atapi_pc *) rq->buffer;
+ } else if (blk_special_request(rq) || blk_sense_request(rq)) {
+ pc = (struct ide_atapi_pc *)rq->special;
} else if (blk_pc_request(rq)) {
pc = &floppy->queued_pc;
idefloppy_blockpc_cmd(floppy, pc, rq);
@@ -275,6 +277,8 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive,
goto out_end;
}
+ ide_prep_sense(drive, rq);
+
memset(&cmd, 0, sizeof(cmd));
if (rq_data_dir(rq))
diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c
index 1aebdf1a4f58..4b6b71e2cdf5 100644
--- a/drivers/ide/ide-gd.c
+++ b/drivers/ide/ide-gd.c
@@ -7,6 +7,7 @@
#include <linux/mutex.h>
#include <linux/ide.h>
#include <linux/hdreg.h>
+#include <linux/dmi.h>
#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
#define IDE_DISK_MINORS (1 << PARTN_BITS)
@@ -99,6 +100,19 @@ static void ide_gd_resume(ide_drive_t *drive)
(void)drive->disk_ops->get_capacity(drive);
}
+static const struct dmi_system_id ide_coldreboot_table[] = {
+ {
+ /* Acer TravelMate 66x cuts power during reboot */
+ .ident = "Acer TravelMate 660",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 660"),
+ },
+ },
+
+ { } /* terminate list */
+};
+
static void ide_gd_shutdown(ide_drive_t *drive)
{
#ifdef CONFIG_ALPHA
@@ -115,7 +129,8 @@ static void ide_gd_shutdown(ide_drive_t *drive)
the disk to expire its write cache. */
if (system_state != SYSTEM_POWER_OFF) {
#else
- if (system_state == SYSTEM_RESTART) {
+ if (system_state == SYSTEM_RESTART &&
+ !dmi_check_system(ide_coldreboot_table)) {
#endif
drive->disk_ops->flush(drive);
return;
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 2ae02b8d7f8e..a0309ea661ac 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -102,11 +102,14 @@ void ide_complete_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat, u8 err)
drive->dev_flags |= IDE_DFLAG_PARKED;
}
- if (rq && rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
- memcpy(rq->special, cmd, sizeof(*cmd));
+ if (rq && rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
+ struct ide_cmd *orig_cmd = rq->special;
- if (cmd->tf_flags & IDE_TFLAG_DYN)
- kfree(cmd);
+ if (cmd->tf_flags & IDE_TFLAG_DYN)
+ kfree(orig_cmd);
+ else
+ memcpy(orig_cmd, cmd, sizeof(*cmd));
+ }
}
/* obsolete, blk_rq_bytes() should be used instead */
@@ -245,14 +248,7 @@ void ide_map_sg(ide_drive_t *drive, struct ide_cmd *cmd)
struct scatterlist *sg = hwif->sg_table;
struct request *rq = cmd->rq;
- if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
- sg_init_one(sg, rq->buffer, rq->nr_sectors * SECTOR_SIZE);
- cmd->sg_nents = 1;
- } else if (!rq->bio) {
- sg_init_one(sg, rq->data, rq->data_len);
- cmd->sg_nents = 1;
- } else
- cmd->sg_nents = blk_rq_map_sg(drive->queue, rq, sg);
+ cmd->sg_nents = blk_rq_map_sg(drive->queue, rq, sg);
}
EXPORT_SYMBOL_GPL(ide_map_sg);
@@ -368,7 +364,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
return execute_drive_cmd(drive, rq);
else if (blk_pm_request(rq)) {
- struct request_pm_state *pm = rq->data;
+ struct request_pm_state *pm = rq->special;
#ifdef DEBUG_PM
printk("%s: start_power_step(step: %d)\n",
drive->name, pm->pm_step);
@@ -481,6 +477,9 @@ void do_ide_request(struct request_queue *q)
spin_unlock_irq(q->queue_lock);
+ /* HLD do_request() callback might sleep, make sure it's okay */
+ might_sleep();
+
if (ide_lock_host(host, hwif))
goto plug_device_2;
diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c
index c1c25ebbaa1f..5991b23793f2 100644
--- a/drivers/ide/ide-ioctls.c
+++ b/drivers/ide/ide-ioctls.c
@@ -231,7 +231,6 @@ static int generic_drive_reset(ide_drive_t *drive)
rq->cmd_type = REQ_TYPE_SPECIAL;
rq->cmd_len = 1;
rq->cmd[0] = REQ_DRIVE_RESET;
- rq->cmd_flags |= REQ_SOFTBARRIER;
if (blk_execute_rq(drive->queue, NULL, rq, 1))
ret = rq->errors;
blk_put_request(rq);
diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c
index 310d03f2b5b7..a914023d6d03 100644
--- a/drivers/ide/ide-park.c
+++ b/drivers/ide/ide-park.c
@@ -24,11 +24,8 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout)
start_queue = 1;
spin_unlock_irq(&hwif->lock);
- if (start_queue) {
- spin_lock_irq(q->queue_lock);
- blk_start_queueing(q);
- spin_unlock_irq(q->queue_lock);
- }
+ if (start_queue)
+ blk_run_queue(q);
return;
}
spin_unlock_irq(&hwif->lock);
diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c
index 0d8a151c0a01..ba1488bd8430 100644
--- a/drivers/ide/ide-pm.c
+++ b/drivers/ide/ide-pm.c
@@ -7,7 +7,6 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg)
ide_hwif_t *hwif = drive->hwif;
struct request *rq;
struct request_pm_state rqpm;
- struct ide_cmd cmd;
int ret;
/* call ACPI _GTM only once */
@@ -15,11 +14,9 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg)
ide_acpi_get_timing(hwif);
memset(&rqpm, 0, sizeof(rqpm));
- memset(&cmd, 0, sizeof(cmd));
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_PM_SUSPEND;
- rq->special = &cmd;
- rq->data = &rqpm;
+ rq->special = &rqpm;
rqpm.pm_step = IDE_PM_START_SUSPEND;
if (mesg.event == PM_EVENT_PRETHAW)
mesg.event = PM_EVENT_FREEZE;
@@ -41,7 +38,6 @@ int generic_ide_resume(struct device *dev)
ide_hwif_t *hwif = drive->hwif;
struct request *rq;
struct request_pm_state rqpm;
- struct ide_cmd cmd;
int err;
/* call ACPI _PS0 / _STM only once */
@@ -53,12 +49,10 @@ int generic_ide_resume(struct device *dev)
ide_acpi_exec_tfs(drive);
memset(&rqpm, 0, sizeof(rqpm));
- memset(&cmd, 0, sizeof(cmd));
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_PM_RESUME;
rq->cmd_flags |= REQ_PREEMPT;
- rq->special = &cmd;
- rq->data = &rqpm;
+ rq->special = &rqpm;
rqpm.pm_step = IDE_PM_START_RESUME;
rqpm.pm_state = PM_EVENT_ON;
@@ -77,7 +71,7 @@ int generic_ide_resume(struct device *dev)
void ide_complete_power_step(ide_drive_t *drive, struct request *rq)
{
- struct request_pm_state *pm = rq->data;
+ struct request_pm_state *pm = rq->special;
#ifdef DEBUG_PM
printk(KERN_INFO "%s: complete_power_step(step: %d)\n",
@@ -107,10 +101,8 @@ void ide_complete_power_step(ide_drive_t *drive, struct request *rq)
ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
{
- struct request_pm_state *pm = rq->data;
- struct ide_cmd *cmd = rq->special;
-
- memset(cmd, 0, sizeof(*cmd));
+ struct request_pm_state *pm = rq->special;
+ struct ide_cmd cmd = { };
switch (pm->pm_step) {
case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */
@@ -123,12 +115,12 @@ ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
return ide_stopped;
}
if (ata_id_flush_ext_enabled(drive->id))
- cmd->tf.command = ATA_CMD_FLUSH_EXT;
+ cmd.tf.command = ATA_CMD_FLUSH_EXT;
else
- cmd->tf.command = ATA_CMD_FLUSH;
+ cmd.tf.command = ATA_CMD_FLUSH;
goto out_do_tf;
case IDE_PM_STANDBY: /* Suspend step 2 (standby) */
- cmd->tf.command = ATA_CMD_STANDBYNOW1;
+ cmd.tf.command = ATA_CMD_STANDBYNOW1;
goto out_do_tf;
case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */
ide_set_max_pio(drive);
@@ -141,7 +133,7 @@ ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
ide_complete_power_step(drive, rq);
return ide_stopped;
case IDE_PM_IDLE: /* Resume step 2 (idle) */
- cmd->tf.command = ATA_CMD_IDLEIMMEDIATE;
+ cmd.tf.command = ATA_CMD_IDLEIMMEDIATE;
goto out_do_tf;
case IDE_PM_RESTORE_DMA: /* Resume step 3 (restore DMA) */
/*
@@ -163,11 +155,11 @@ ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
return ide_stopped;
out_do_tf:
- cmd->valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
- cmd->valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE;
- cmd->protocol = ATA_PROT_NODATA;
+ cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
+ cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE;
+ cmd.protocol = ATA_PROT_NODATA;
- return do_rw_taskfile(drive, cmd);
+ return do_rw_taskfile(drive, &cmd);
}
/**
@@ -181,7 +173,7 @@ out_do_tf:
void ide_complete_pm_rq(ide_drive_t *drive, struct request *rq)
{
struct request_queue *q = drive->queue;
- struct request_pm_state *pm = rq->data;
+ struct request_pm_state *pm = rq->special;
unsigned long flags;
ide_complete_power_step(drive, rq);
@@ -207,7 +199,7 @@ void ide_complete_pm_rq(ide_drive_t *drive, struct request *rq)
void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
{
- struct request_pm_state *pm = rq->data;
+ struct request_pm_state *pm = rq->special;
if (blk_pm_suspend_request(rq) &&
pm->pm_step == IDE_PM_START_SUSPEND)
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index cb942a9b580f..8dfc68892d6a 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -131,13 +131,6 @@ enum {
IDETAPE_DIR_WRITE = (1 << 2),
};
-struct idetape_bh {
- u32 b_size;
- atomic_t b_count;
- struct idetape_bh *b_reqnext;
- char *b_data;
-};
-
/* Tape door status */
#define DOOR_UNLOCKED 0
#define DOOR_LOCKED 1
@@ -219,18 +212,12 @@ typedef struct ide_tape_obj {
/* Data buffer size chosen based on the tape's recommendation */
int buffer_size;
- /* merge buffer */
- struct idetape_bh *merge_bh;
- /* size of the merge buffer */
- int merge_bh_size;
- /* pointer to current buffer head within the merge buffer */
- struct idetape_bh *bh;
- char *b_data;
- int b_count;
-
- int pages_per_buffer;
- /* Wasted space in each stage */
- int excess_bh_size;
+ /* Staging buffer of buffer_size bytes */
+ void *buf;
+ /* The read/write cursor */
+ void *cur;
+ /* The number of valid bytes in buf */
+ size_t valid;
/* Measures average tape speed */
unsigned long avg_time;
@@ -297,84 +284,6 @@ static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i)
return tape;
}
-static int idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
- unsigned int bcount)
-{
- struct idetape_bh *bh = pc->bh;
- int count;
-
- while (bcount) {
- if (bh == NULL)
- break;
- count = min(
- (unsigned int)(bh->b_size - atomic_read(&bh->b_count)),
- bcount);
- drive->hwif->tp_ops->input_data(drive, NULL, bh->b_data +
- atomic_read(&bh->b_count), count);
- bcount -= count;
- atomic_add(count, &bh->b_count);
- if (atomic_read(&bh->b_count) == bh->b_size) {
- bh = bh->b_reqnext;
- if (bh)
- atomic_set(&bh->b_count, 0);
- }
- }
-
- pc->bh = bh;
-
- return bcount;
-}
-
-static int idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
- unsigned int bcount)
-{
- struct idetape_bh *bh = pc->bh;
- int count;
-
- while (bcount) {
- if (bh == NULL)
- break;
- count = min((unsigned int)pc->b_count, (unsigned int)bcount);
- drive->hwif->tp_ops->output_data(drive, NULL, pc->b_data, count);
- bcount -= count;
- pc->b_data += count;
- pc->b_count -= count;
- if (!pc->b_count) {
- bh = bh->b_reqnext;
- pc->bh = bh;
- if (bh) {
- pc->b_data = bh->b_data;
- pc->b_count = atomic_read(&bh->b_count);
- }
- }
- }
-
- return bcount;
-}
-
-static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc)
-{
- struct idetape_bh *bh = pc->bh;
- int count;
- unsigned int bcount = pc->xferred;
-
- if (pc->flags & PC_FLAG_WRITING)
- return;
- while (bcount) {
- if (bh == NULL) {
- printk(KERN_ERR "ide-tape: bh == NULL in %s\n",
- __func__);
- return;
- }
- count = min((unsigned int)bh->b_size, (unsigned int)bcount);
- atomic_set(&bh->b_count, count);
- if (atomic_read(&bh->b_count) == bh->b_size)
- bh = bh->b_reqnext;
- bcount -= count;
- }
- pc->bh = bh;
-}
-
/*
* called on each failed packet command retry to analyze the request sense. We
* currently do not utilize this information.
@@ -392,12 +301,10 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
pc->c[0], tape->sense_key, tape->asc, tape->ascq);
/* Correct pc->xferred by asking the tape. */
- if (pc->flags & PC_FLAG_DMA_ERROR) {
+ if (pc->flags & PC_FLAG_DMA_ERROR)
pc->xferred = pc->req_xfer -
tape->blk_size *
get_unaligned_be32(&sense[3]);
- idetape_update_buffers(drive, pc);
- }
/*
* If error was the result of a zero-length read or write command,
@@ -436,29 +343,6 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
}
}
-/* Free data buffers completely. */
-static void ide_tape_kfree_buffer(idetape_tape_t *tape)
-{
- struct idetape_bh *prev_bh, *bh = tape->merge_bh;
-
- while (bh) {
- u32 size = bh->b_size;
-
- while (size) {
- unsigned int order = fls(size >> PAGE_SHIFT)-1;
-
- if (bh->b_data)
- free_pages((unsigned long)bh->b_data, order);
-
- size &= (order-1);
- bh->b_data += (1 << order) * PAGE_SIZE;
- }
- prev_bh = bh;
- bh = bh->b_reqnext;
- kfree(prev_bh);
- }
-}
-
static void ide_tape_handle_dsc(ide_drive_t *);
static int ide_tape_callback(ide_drive_t *drive, int dsc)
@@ -496,7 +380,7 @@ static int ide_tape_callback(ide_drive_t *drive, int dsc)
}
tape->first_frame += blocks;
- rq->current_nr_sectors -= blocks;
+ rq->data_len -= blocks * tape->blk_size;
if (pc->error) {
uptodate = 0;
@@ -558,19 +442,6 @@ static void ide_tape_handle_dsc(ide_drive_t *drive)
idetape_postpone_request(drive);
}
-static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
- unsigned int bcount, int write)
-{
- unsigned int bleft;
-
- if (write)
- bleft = idetape_output_buffers(drive, pc, bcount);
- else
- bleft = idetape_input_buffers(drive, pc, bcount);
-
- return bcount - bleft;
-}
-
/*
* Packet Command Interface
*
@@ -614,12 +485,6 @@ static ide_startstop_t ide_tape_issue_pc(ide_drive_t *drive,
{
idetape_tape_t *tape = drive->driver_data;
- if (drive->pc->c[0] == REQUEST_SENSE &&
- pc->c[0] == REQUEST_SENSE) {
- printk(KERN_ERR "ide-tape: possible ide-tape.c bug - "
- "Two request sense in serial were issued\n");
- }
-
if (drive->failed_pc == NULL && pc->c[0] != REQUEST_SENSE)
drive->failed_pc = pc;
@@ -628,6 +493,8 @@ static ide_startstop_t ide_tape_issue_pc(ide_drive_t *drive,
if (pc->retries > IDETAPE_MAX_PC_RETRIES ||
(pc->flags & PC_FLAG_ABORT)) {
+ unsigned int done = blk_rq_bytes(drive->hwif->rq);
+
/*
* We will "abort" retrying a packet command in case legitimate
* error code was received (crossing a filemark, or end of the
@@ -647,8 +514,10 @@ static ide_startstop_t ide_tape_issue_pc(ide_drive_t *drive,
/* Giving up */
pc->error = IDE_DRV_ERROR_GENERAL;
}
+
drive->failed_pc = NULL;
drive->pc_callback(drive, 0);
+ ide_complete_rq(drive, -EIO, done);
return ide_stopped;
}
debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]);
@@ -701,7 +570,7 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
printk(KERN_ERR "ide-tape: %s: I/O error, ",
tape->name);
/* Retry operation */
- ide_retry_pc(drive, tape->disk);
+ ide_retry_pc(drive);
return ide_stopped;
}
pc->error = 0;
@@ -717,27 +586,22 @@ static void ide_tape_create_rw_cmd(idetape_tape_t *tape,
struct ide_atapi_pc *pc, struct request *rq,
u8 opcode)
{
- struct idetape_bh *bh = (struct idetape_bh *)rq->special;
- unsigned int length = rq->current_nr_sectors;
+ unsigned int length = rq->nr_sectors;
ide_init_pc(pc);
put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
pc->c[1] = 1;
- pc->bh = bh;
pc->buf = NULL;
pc->buf_size = length * tape->blk_size;
pc->req_xfer = pc->buf_size;
if (pc->req_xfer == tape->buffer_size)
pc->flags |= PC_FLAG_DMA_OK;
- if (opcode == READ_6) {
+ if (opcode == READ_6)
pc->c[0] = READ_6;
- atomic_set(&bh->b_count, 0);
- } else if (opcode == WRITE_6) {
+ else if (opcode == WRITE_6) {
pc->c[0] = WRITE_6;
pc->flags |= PC_FLAG_WRITING;
- pc->b_data = bh->b_data;
- pc->b_count = atomic_read(&bh->b_count);
}
memcpy(rq->cmd, pc->c, 12);
@@ -753,12 +617,10 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
struct ide_cmd cmd;
u8 stat;
- debug_log(DBG_SENSE, "sector: %llu, nr_sectors: %lu,"
- " current_nr_sectors: %u\n",
- (unsigned long long)rq->sector, rq->nr_sectors,
- rq->current_nr_sectors);
+ debug_log(DBG_SENSE, "sector: %llu, nr_sectors: %lu\n"
+ (unsigned long long)rq->sector, rq->nr_sectors);
- if (!blk_special_request(rq)) {
+ if (!(blk_special_request(rq) || blk_sense_request(rq))) {
/* We do not support buffer cache originated requests. */
printk(KERN_NOTICE "ide-tape: %s: Unsupported request in "
"request queue (%d)\n", drive->name, rq->cmd_type);
@@ -834,7 +696,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
goto out;
}
if (rq->cmd[13] & REQ_IDETAPE_PC1) {
- pc = (struct ide_atapi_pc *) rq->buffer;
+ pc = (struct ide_atapi_pc *)rq->special;
rq->cmd[13] &= ~(REQ_IDETAPE_PC1);
rq->cmd[13] |= REQ_IDETAPE_PC2;
goto out;
@@ -846,6 +708,9 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
BUG();
out:
+ /* prepare sense request for this command */
+ ide_prep_sense(drive, rq);
+
memset(&cmd, 0, sizeof(cmd));
if (rq_data_dir(rq))
@@ -853,167 +718,10 @@ out:
cmd.rq = rq;
- return ide_tape_issue_pc(drive, &cmd, pc);
-}
-
-/*
- * The function below uses __get_free_pages to allocate a data buffer of size
- * tape->buffer_size (or a bit more). We attempt to combine sequential pages as
- * much as possible.
- *
- * It returns a pointer to the newly allocated buffer, or NULL in case of
- * failure.
- */
-static struct idetape_bh *ide_tape_kmalloc_buffer(idetape_tape_t *tape,
- int full, int clear)
-{
- struct idetape_bh *prev_bh, *bh, *merge_bh;
- int pages = tape->pages_per_buffer;
- unsigned int order, b_allocd;
- char *b_data = NULL;
-
- merge_bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
- bh = merge_bh;
- if (bh == NULL)
- goto abort;
-
- order = fls(pages) - 1;
- bh->b_data = (char *) __get_free_pages(GFP_KERNEL, order);
- if (!bh->b_data)
- goto abort;
- b_allocd = (1 << order) * PAGE_SIZE;
- pages &= (order-1);
-
- if (clear)
- memset(bh->b_data, 0, b_allocd);
- bh->b_reqnext = NULL;
- bh->b_size = b_allocd;
- atomic_set(&bh->b_count, full ? bh->b_size : 0);
-
- while (pages) {
- order = fls(pages) - 1;
- b_data = (char *) __get_free_pages(GFP_KERNEL, order);
- if (!b_data)
- goto abort;
- b_allocd = (1 << order) * PAGE_SIZE;
-
- if (clear)
- memset(b_data, 0, b_allocd);
-
- /* newly allocated page frames below buffer header or ...*/
- if (bh->b_data == b_data + b_allocd) {
- bh->b_size += b_allocd;
- bh->b_data -= b_allocd;
- if (full)
- atomic_add(b_allocd, &bh->b_count);
- continue;
- }
- /* they are above the header */
- if (b_data == bh->b_data + bh->b_size) {
- bh->b_size += b_allocd;
- if (full)
- atomic_add(b_allocd, &bh->b_count);
- continue;
- }
- prev_bh = bh;
- bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
- if (!bh) {
- free_pages((unsigned long) b_data, order);
- goto abort;
- }
- bh->b_reqnext = NULL;
- bh->b_data = b_data;
- bh->b_size = b_allocd;
- atomic_set(&bh->b_count, full ? bh->b_size : 0);
- prev_bh->b_reqnext = bh;
-
- pages &= (order-1);
- }
+ ide_init_sg_cmd(&cmd, pc->req_xfer);
+ ide_map_sg(drive, &cmd);
- bh->b_size -= tape->excess_bh_size;
- if (full)
- atomic_sub(tape->excess_bh_size, &bh->b_count);
- return merge_bh;
-abort:
- ide_tape_kfree_buffer(tape);
- return NULL;
-}
-
-static int idetape_copy_stage_from_user(idetape_tape_t *tape,
- const char __user *buf, int n)
-{
- struct idetape_bh *bh = tape->bh;
- int count;
- int ret = 0;
-
- while (n) {
- if (bh == NULL) {
- printk(KERN_ERR "ide-tape: bh == NULL in %s\n",
- __func__);
- return 1;
- }
- count = min((unsigned int)
- (bh->b_size - atomic_read(&bh->b_count)),
- (unsigned int)n);
- if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf,
- count))
- ret = 1;
- n -= count;
- atomic_add(count, &bh->b_count);
- buf += count;
- if (atomic_read(&bh->b_count) == bh->b_size) {
- bh = bh->b_reqnext;
- if (bh)
- atomic_set(&bh->b_count, 0);
- }
- }
- tape->bh = bh;
- return ret;
-}
-
-static int idetape_copy_stage_to_user(idetape_tape_t *tape, char __user *buf,
- int n)
-{
- struct idetape_bh *bh = tape->bh;
- int count;
- int ret = 0;
-
- while (n) {
- if (bh == NULL) {
- printk(KERN_ERR "ide-tape: bh == NULL in %s\n",
- __func__);
- return 1;
- }
- count = min(tape->b_count, n);
- if (copy_to_user(buf, tape->b_data, count))
- ret = 1;
- n -= count;
- tape->b_data += count;
- tape->b_count -= count;
- buf += count;
- if (!tape->b_count) {
- bh = bh->b_reqnext;
- tape->bh = bh;
- if (bh) {
- tape->b_data = bh->b_data;
- tape->b_count = atomic_read(&bh->b_count);
- }
- }
- }
- return ret;
-}
-
-static void idetape_init_merge_buffer(idetape_tape_t *tape)
-{
- struct idetape_bh *bh = tape->merge_bh;
- tape->bh = tape->merge_bh;
-
- if (tape->chrdev_dir == IDETAPE_DIR_WRITE)
- atomic_set(&bh->b_count, 0);
- else {
- tape->b_data = bh->b_data;
- tape->b_count = atomic_read(&bh->b_count);
- }
+ return ide_tape_issue_pc(drive, &cmd, pc);
}
/*
@@ -1113,10 +821,10 @@ static void __ide_tape_discard_merge_buffer(ide_drive_t *drive)
return;
clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags);
- tape->merge_bh_size = 0;
- if (tape->merge_bh != NULL) {
- ide_tape_kfree_buffer(tape);
- tape->merge_bh = NULL;
+ tape->valid = 0;
+ if (tape->buf != NULL) {
+ kfree(tape->buf);
+ tape->buf = NULL;
}
tape->chrdev_dir = IDETAPE_DIR_NONE;
@@ -1170,36 +878,44 @@ static void ide_tape_discard_merge_buffer(ide_drive_t *drive,
* Generate a read/write request for the block device interface and wait for it
* to be serviced.
*/
-static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks,
- struct idetape_bh *bh)
+static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int size)
{
idetape_tape_t *tape = drive->driver_data;
struct request *rq;
- int ret, errors;
+ int ret;
debug_log(DBG_SENSE, "%s: cmd=%d\n", __func__, cmd);
+ BUG_ON(cmd != REQ_IDETAPE_READ && cmd != REQ_IDETAPE_WRITE);
+ BUG_ON(size < 0 || size % tape->blk_size);
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_SPECIAL;
rq->cmd[13] = cmd;
rq->rq_disk = tape->disk;
- rq->special = (void *)bh;
rq->sector = tape->first_frame;
- rq->nr_sectors = blocks;
- rq->current_nr_sectors = blocks;
- blk_execute_rq(drive->queue, tape->disk, rq, 0);
- errors = rq->errors;
- ret = tape->blk_size * (blocks - rq->current_nr_sectors);
- blk_put_request(rq);
+ if (size) {
+ ret = blk_rq_map_kern(drive->queue, rq, tape->buf, size,
+ __GFP_WAIT);
+ if (ret)
+ goto out_put;
+ }
- if ((cmd & (REQ_IDETAPE_READ | REQ_IDETAPE_WRITE)) == 0)
- return 0;
+ blk_execute_rq(drive->queue, tape->disk, rq, 0);
- if (tape->merge_bh)
- idetape_init_merge_buffer(tape);
- if (errors == IDE_DRV_ERROR_GENERAL)
- return -EIO;
+ /* calculate the number of transferred bytes and update buffer state */
+ size -= rq->data_len;
+ tape->cur = tape->buf;
+ if (cmd == REQ_IDETAPE_READ)
+ tape->valid = size;
+ else
+ tape->valid = 0;
+
+ ret = size;
+ if (rq->errors == IDE_DRV_ERROR_GENERAL)
+ ret = -EIO;
+out_put:
+ blk_put_request(rq);
return ret;
}
@@ -1236,153 +952,87 @@ static void idetape_create_space_cmd(struct ide_atapi_pc *pc, int count, u8 cmd)
pc->flags |= PC_FLAG_WAIT_FOR_DSC;
}
-/* Queue up a character device originated write request. */
-static int idetape_add_chrdev_write_request(ide_drive_t *drive, int blocks)
-{
- idetape_tape_t *tape = drive->driver_data;
-
- debug_log(DBG_CHRDEV, "Enter %s\n", __func__);
-
- return idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE,
- blocks, tape->merge_bh);
-}
-
static void ide_tape_flush_merge_buffer(ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
- int blocks, min;
- struct idetape_bh *bh;
if (tape->chrdev_dir != IDETAPE_DIR_WRITE) {
printk(KERN_ERR "ide-tape: bug: Trying to empty merge buffer"
" but we are not writing.\n");
return;
}
- if (tape->merge_bh_size > tape->buffer_size) {
- printk(KERN_ERR "ide-tape: bug: merge_buffer too big\n");
- tape->merge_bh_size = tape->buffer_size;
- }
- if (tape->merge_bh_size) {
- blocks = tape->merge_bh_size / tape->blk_size;
- if (tape->merge_bh_size % tape->blk_size) {
- unsigned int i;
-
- blocks++;
- i = tape->blk_size - tape->merge_bh_size %
- tape->blk_size;
- bh = tape->bh->b_reqnext;
- while (bh) {
- atomic_set(&bh->b_count, 0);
- bh = bh->b_reqnext;
- }
- bh = tape->bh;
- while (i) {
- if (bh == NULL) {
- printk(KERN_INFO "ide-tape: bug,"
- " bh NULL\n");
- break;
- }
- min = min(i, (unsigned int)(bh->b_size -
- atomic_read(&bh->b_count)));
- memset(bh->b_data + atomic_read(&bh->b_count),
- 0, min);
- atomic_add(min, &bh->b_count);
- i -= min;
- bh = bh->b_reqnext;
- }
- }
- (void) idetape_add_chrdev_write_request(drive, blocks);
- tape->merge_bh_size = 0;
- }
- if (tape->merge_bh != NULL) {
- ide_tape_kfree_buffer(tape);
- tape->merge_bh = NULL;
+ if (tape->buf) {
+ size_t aligned = roundup(tape->valid, tape->blk_size);
+
+ memset(tape->cur, 0, aligned - tape->valid);
+ idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, aligned);
+ kfree(tape->buf);
+ tape->buf = NULL;
}
tape->chrdev_dir = IDETAPE_DIR_NONE;
}
-static int idetape_init_read(ide_drive_t *drive)
+static int idetape_init_rw(ide_drive_t *drive, int dir)
{
idetape_tape_t *tape = drive->driver_data;
- int bytes_read;
-
- /* Initialize read operation */
- if (tape->chrdev_dir != IDETAPE_DIR_READ) {
- if (tape->chrdev_dir == IDETAPE_DIR_WRITE) {
- ide_tape_flush_merge_buffer(drive);
- idetape_flush_tape_buffers(drive);
- }
- if (tape->merge_bh || tape->merge_bh_size) {
- printk(KERN_ERR "ide-tape: merge_bh_size should be"
- " 0 now\n");
- tape->merge_bh_size = 0;
- }
- tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0);
- if (!tape->merge_bh)
- return -ENOMEM;
- tape->chrdev_dir = IDETAPE_DIR_READ;
+ int rc;
- /*
- * Issue a read 0 command to ensure that DSC handshake is
- * switched from completion mode to buffer available mode.
- * No point in issuing this if DSC overlap isn't supported, some
- * drives (Seagate STT3401A) will return an error.
- */
- if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) {
- bytes_read = idetape_queue_rw_tail(drive,
- REQ_IDETAPE_READ, 0,
- tape->merge_bh);
- if (bytes_read < 0) {
- ide_tape_kfree_buffer(tape);
- tape->merge_bh = NULL;
- tape->chrdev_dir = IDETAPE_DIR_NONE;
- return bytes_read;
- }
- }
- }
+ BUG_ON(dir != IDETAPE_DIR_READ && dir != IDETAPE_DIR_WRITE);
- return 0;
-}
+ if (tape->chrdev_dir == dir)
+ return 0;
-/* called from idetape_chrdev_read() to service a chrdev read request. */
-static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks)
-{
- idetape_tape_t *tape = drive->driver_data;
+ if (tape->chrdev_dir == IDETAPE_DIR_READ)
+ ide_tape_discard_merge_buffer(drive, 1);
+ else if (tape->chrdev_dir == IDETAPE_DIR_WRITE) {
+ ide_tape_flush_merge_buffer(drive);
+ idetape_flush_tape_buffers(drive);
+ }
- debug_log(DBG_PROCS, "Enter %s, %d blocks\n", __func__, blocks);
+ if (tape->buf || tape->valid) {
+ printk(KERN_ERR "ide-tape: valid should be 0 now\n");
+ tape->valid = 0;
+ }
- /* If we are at a filemark, return a read length of 0 */
- if (test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags))
- return 0;
+ tape->buf = kmalloc(tape->buffer_size, GFP_KERNEL);
+ if (!tape->buf)
+ return -ENOMEM;
+ tape->chrdev_dir = dir;
+ tape->cur = tape->buf;
- idetape_init_read(drive);
+ /*
+ * Issue a 0 rw command to ensure that DSC handshake is
+ * switched from completion mode to buffer available mode. No
+ * point in issuing this if DSC overlap isn't supported, some
+ * drives (Seagate STT3401A) will return an error.
+ */
+ if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) {
+ int cmd = dir == IDETAPE_DIR_READ ? REQ_IDETAPE_READ
+ : REQ_IDETAPE_WRITE;
+
+ rc = idetape_queue_rw_tail(drive, cmd, 0);
+ if (rc < 0) {
+ kfree(tape->buf);
+ tape->buf = NULL;
+ tape->chrdev_dir = IDETAPE_DIR_NONE;
+ return rc;
+ }
+ }
- return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks,
- tape->merge_bh);
+ return 0;
}
static void idetape_pad_zeros(ide_drive_t *drive, int bcount)
{
idetape_tape_t *tape = drive->driver_data;
- struct idetape_bh *bh;
- int blocks;
+
+ memset(tape->buf, 0, tape->buffer_size);
while (bcount) {
- unsigned int count;
+ unsigned int count = min(tape->buffer_size, bcount);
- bh = tape->merge_bh;
- count = min(tape->buffer_size, bcount);
+ idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, count);
bcount -= count;
- blocks = count / tape->blk_size;
- while (count) {
- atomic_set(&bh->b_count,
- min(count, (unsigned int)bh->b_size));
- memset(bh->b_data, 0, atomic_read(&bh->b_count));
- count -= atomic_read(&bh->b_count);
- bh = bh->b_reqnext;
- }
- idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, blocks,
- tape->merge_bh);
}
}
@@ -1462,7 +1112,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
}
if (tape->chrdev_dir == IDETAPE_DIR_READ) {
- tape->merge_bh_size = 0;
+ tape->valid = 0;
if (test_and_clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags))
++count;
ide_tape_discard_merge_buffer(drive, 0);
@@ -1511,9 +1161,9 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
{
struct ide_tape_obj *tape = file->private_data;
ide_drive_t *drive = tape->drive;
- ssize_t bytes_read, temp, actually_read = 0, rc;
+ size_t done = 0;
ssize_t ret = 0;
- u16 ctl = *(u16 *)&tape->caps[12];
+ int rc;
debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count);
@@ -1523,49 +1173,43 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
(count % tape->blk_size) == 0)
tape->user_bs_factor = count / tape->blk_size;
}
- rc = idetape_init_read(drive);
+
+ rc = idetape_init_rw(drive, IDETAPE_DIR_READ);
if (rc < 0)
return rc;
- if (count == 0)
- return (0);
- if (tape->merge_bh_size) {
- actually_read = min((unsigned int)(tape->merge_bh_size),
- (unsigned int)count);
- if (idetape_copy_stage_to_user(tape, buf, actually_read))
- ret = -EFAULT;
- buf += actually_read;
- tape->merge_bh_size -= actually_read;
- count -= actually_read;
- }
- while (count >= tape->buffer_size) {
- bytes_read = idetape_add_chrdev_read_request(drive, ctl);
- if (bytes_read <= 0)
- goto finish;
- if (idetape_copy_stage_to_user(tape, buf, bytes_read))
- ret = -EFAULT;
- buf += bytes_read;
- count -= bytes_read;
- actually_read += bytes_read;
- }
- if (count) {
- bytes_read = idetape_add_chrdev_read_request(drive, ctl);
- if (bytes_read <= 0)
- goto finish;
- temp = min((unsigned long)count, (unsigned long)bytes_read);
- if (idetape_copy_stage_to_user(tape, buf, temp))
+
+ while (done < count) {
+ size_t todo;
+
+ /* refill if staging buffer is empty */
+ if (!tape->valid) {
+ /* If we are at a filemark, nothing more to read */
+ if (test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags))
+ break;
+ /* read */
+ if (idetape_queue_rw_tail(drive, REQ_IDETAPE_READ,
+ tape->buffer_size) <= 0)
+ break;
+ }
+
+ /* copy out */
+ todo = min_t(size_t, count - done, tape->valid);
+ if (copy_to_user(buf + done, tape->cur, todo))
ret = -EFAULT;
- actually_read += temp;
- tape->merge_bh_size = bytes_read-temp;
+
+ tape->cur += todo;
+ tape->valid -= todo;
+ done += todo;
}
-finish:
- if (!actually_read && test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) {
+
+ if (!done && test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) {
debug_log(DBG_SENSE, "%s: spacing over filemark\n", tape->name);
idetape_space_over_filemarks(drive, MTFSF, 1);
return 0;
}
- return ret ? ret : actually_read;
+ return ret ? ret : done;
}
static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
@@ -1573,9 +1217,9 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
{
struct ide_tape_obj *tape = file->private_data;
ide_drive_t *drive = tape->drive;
- ssize_t actually_written = 0;
+ size_t done = 0;
ssize_t ret = 0;
- u16 ctl = *(u16 *)&tape->caps[12];
+ int rc;
/* The drive is write protected. */
if (tape->write_prot)
@@ -1584,80 +1228,31 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count);
/* Initialize write operation */
- if (tape->chrdev_dir != IDETAPE_DIR_WRITE) {
- if (tape->chrdev_dir == IDETAPE_DIR_READ)
- ide_tape_discard_merge_buffer(drive, 1);
- if (tape->merge_bh || tape->merge_bh_size) {
- printk(KERN_ERR "ide-tape: merge_bh_size "
- "should be 0 now\n");
- tape->merge_bh_size = 0;
- }
- tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0);
- if (!tape->merge_bh)
- return -ENOMEM;
- tape->chrdev_dir = IDETAPE_DIR_WRITE;
- idetape_init_merge_buffer(tape);
+ rc = idetape_init_rw(drive, IDETAPE_DIR_WRITE);
+ if (rc < 0)
+ return rc;
- /*
- * Issue a write 0 command to ensure that DSC handshake is
- * switched from completion mode to buffer available mode. No
- * point in issuing this if DSC overlap isn't supported, some
- * drives (Seagate STT3401A) will return an error.
- */
- if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) {
- ssize_t retval = idetape_queue_rw_tail(drive,
- REQ_IDETAPE_WRITE, 0,
- tape->merge_bh);
- if (retval < 0) {
- ide_tape_kfree_buffer(tape);
- tape->merge_bh = NULL;
- tape->chrdev_dir = IDETAPE_DIR_NONE;
- return retval;
- }
- }
- }
- if (count == 0)
- return (0);
- if (tape->merge_bh_size) {
- if (tape->merge_bh_size >= tape->buffer_size) {
- printk(KERN_ERR "ide-tape: bug: merge buf too big\n");
- tape->merge_bh_size = 0;
- }
- actually_written = min((unsigned int)
- (tape->buffer_size - tape->merge_bh_size),
- (unsigned int)count);
- if (idetape_copy_stage_from_user(tape, buf, actually_written))
- ret = -EFAULT;
- buf += actually_written;
- tape->merge_bh_size += actually_written;
- count -= actually_written;
-
- if (tape->merge_bh_size == tape->buffer_size) {
- ssize_t retval;
- tape->merge_bh_size = 0;
- retval = idetape_add_chrdev_write_request(drive, ctl);
- if (retval <= 0)
- return (retval);
- }
- }
- while (count >= tape->buffer_size) {
- ssize_t retval;
- if (idetape_copy_stage_from_user(tape, buf, tape->buffer_size))
- ret = -EFAULT;
- buf += tape->buffer_size;
- count -= tape->buffer_size;
- retval = idetape_add_chrdev_write_request(drive, ctl);
- actually_written += tape->buffer_size;
- if (retval <= 0)
- return (retval);
- }
- if (count) {
- actually_written += count;
- if (idetape_copy_stage_from_user(tape, buf, count))
+ while (done < count) {
+ size_t todo;
+
+ /* flush if staging buffer is full */
+ if (tape->valid == tape->buffer_size &&
+ idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE,
+ tape->buffer_size) <= 0)
+ return rc;
+
+ /* copy in */
+ todo = min_t(size_t, count - done,
+ tape->buffer_size - tape->valid);
+ if (copy_from_user(tape->cur, buf + done, todo))
ret = -EFAULT;
- tape->merge_bh_size += count;
+
+ tape->cur += todo;
+ tape->valid += todo;
+ done += todo;
}
- return ret ? ret : actually_written;
+
+ return ret ? ret : done;
}
static int idetape_write_filemark(ide_drive_t *drive)
@@ -1818,7 +1413,7 @@ static int idetape_chrdev_ioctl(struct inode *inode, struct file *file,
idetape_flush_tape_buffers(drive);
}
if (cmd == MTIOCGET || cmd == MTIOCPOS) {
- block_offset = tape->merge_bh_size /
+ block_offset = tape->valid /
(tape->blk_size * tape->user_bs_factor);
position = idetape_read_position(drive);
if (position < 0)
@@ -1966,12 +1561,12 @@ static void idetape_write_release(ide_drive_t *drive, unsigned int minor)
idetape_tape_t *tape = drive->driver_data;
ide_tape_flush_merge_buffer(drive);
- tape->merge_bh = ide_tape_kmalloc_buffer(tape, 1, 0);
- if (tape->merge_bh != NULL) {
+ tape->buf = kmalloc(tape->buffer_size, GFP_KERNEL);
+ if (tape->buf != NULL) {
idetape_pad_zeros(drive, tape->blk_size *
(tape->user_bs_factor - 1));
- ide_tape_kfree_buffer(tape);
- tape->merge_bh = NULL;
+ kfree(tape->buf);
+ tape->buf = NULL;
}
idetape_write_filemark(drive);
idetape_flush_tape_buffers(drive);
@@ -2165,8 +1760,6 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
u16 *ctl = (u16 *)&tape->caps[12];
drive->pc_callback = ide_tape_callback;
- drive->pc_update_buffers = idetape_update_buffers;
- drive->pc_io_buffers = ide_tape_io_buffers;
drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
@@ -2197,11 +1790,6 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
tape->buffer_size = *ctl * tape->blk_size;
}
buffer_size = tape->buffer_size;
- tape->pages_per_buffer = buffer_size / PAGE_SIZE;
- if (buffer_size % PAGE_SIZE) {
- tape->pages_per_buffer++;
- tape->excess_bh_size = PAGE_SIZE - buffer_size % PAGE_SIZE;
- }
/* select the "best" DSC read/write polling freq */
speed = max(*(u16 *)&tape->caps[14], *(u16 *)&tape->caps[8]);
@@ -2244,7 +1832,7 @@ static void ide_tape_release(struct device *dev)
ide_drive_t *drive = tape->drive;
struct gendisk *g = tape->disk;
- BUG_ON(tape->merge_bh_size);
+ BUG_ON(tape->valid);
drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
drive->driver_data = NULL;
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 4aa6223c11be..f400eb4d4aff 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -424,7 +424,9 @@ int ide_raw_taskfile(ide_drive_t *drive, struct ide_cmd *cmd, u8 *buf,
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
- rq->buffer = buf;
+
+ if (cmd->tf_flags & IDE_TFLAG_WRITE)
+ rq->cmd_flags |= REQ_RW;
/*
* (ks) We transfer currently only whole sectors.
@@ -432,18 +434,20 @@ int ide_raw_taskfile(ide_drive_t *drive, struct ide_cmd *cmd, u8 *buf,
* if we would find a solution to transfer any size.
* To support special commands like READ LONG.
*/
- rq->hard_nr_sectors = rq->nr_sectors = nsect;
- rq->hard_cur_sectors = rq->current_nr_sectors = nsect;
-
- if (cmd->tf_flags & IDE_TFLAG_WRITE)
- rq->cmd_flags |= REQ_RW;
+ if (nsect) {
+ error = blk_rq_map_kern(drive->queue, rq, buf,
+ nsect * SECTOR_SIZE, __GFP_WAIT);
+ if (error)
+ goto put_req;
+ }
rq->special = cmd;
cmd->rq = rq;
error = blk_execute_rq(drive->queue, NULL, rq, 0);
- blk_put_request(rq);
+put_req:
+ blk_put_request(rq);
return error;
}
diff --git a/drivers/ide/palm_bk3710.c b/drivers/ide/palm_bk3710.c
index c7acca0b8733..09d813d313f4 100644
--- a/drivers/ide/palm_bk3710.c
+++ b/drivers/ide/palm_bk3710.c
@@ -39,27 +39,12 @@
/* Primary Control Offset */
#define IDE_PALM_ATA_PRI_CTL_OFFSET 0x3F6
-/*
- * PalmChip 3710 IDE Controller UDMA timing structure Definition
- */
-struct palm_bk3710_udmatiming {
- unsigned int rptime; /* Ready to pause time */
- unsigned int cycletime; /* Cycle Time */
-};
-
#define BK3710_BMICP 0x00
#define BK3710_BMISP 0x02
#define BK3710_BMIDTP 0x04
-#define BK3710_BMICS 0x08
-#define BK3710_BMISS 0x0A
-#define BK3710_BMIDTS 0x0C
#define BK3710_IDETIMP 0x40
-#define BK3710_IDETIMS 0x42
-#define BK3710_SIDETIM 0x44
-#define BK3710_SLEWCTL 0x45
#define BK3710_IDESTATUS 0x47
#define BK3710_UDMACTL 0x48
-#define BK3710_UDMATIM 0x4A
#define BK3710_MISCCTL 0x50
#define BK3710_REGSTB 0x54
#define BK3710_REGRCVR 0x58
@@ -71,17 +56,22 @@ struct palm_bk3710_udmatiming {
#define BK3710_UDMATRP 0x70
#define BK3710_UDMAENV 0x74
#define BK3710_IORDYTMP 0x78
-#define BK3710_IORDYTMS 0x7C
static unsigned ideclk_period; /* in nanoseconds */
+struct palm_bk3710_udmatiming {
+ unsigned int rptime; /* tRP -- Ready to pause time (nsec) */
+ unsigned int cycletime; /* tCYCTYP2/2 -- avg Cycle Time (nsec) */
+ /* tENV is always a minimum of 20 nsec */
+};
+
static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = {
- {160, 240}, /* UDMA Mode 0 */
- {125, 160}, /* UDMA Mode 1 */
- {100, 120}, /* UDMA Mode 2 */
- {100, 90}, /* UDMA Mode 3 */
- {100, 60}, /* UDMA Mode 4 */
- {85, 40}, /* UDMA Mode 5 */
+ { 160, 240 / 2 }, /* UDMA Mode 0 */
+ { 125, 160 / 2 }, /* UDMA Mode 1 */
+ { 100, 120 / 2 }, /* UDMA Mode 2 */
+ { 100, 90 / 2 }, /* UDMA Mode 3 */
+ { 100, 60 / 2 }, /* UDMA Mode 4 */
+ { 85, 40 / 2 }, /* UDMA Mode 5 */
};
static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev,
@@ -98,11 +88,6 @@ static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev,
trp = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].rptime,
ideclk_period) - 1;
- /* udmatim Register */
- val16 = readw(base + BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0);
- val16 |= (mode << (dev ? 4 : 0));
- writew(val16, base + BK3710_UDMATIM);
-
/* udmastb Ultra DMA Access Strobe Width */
val32 = readl(base + BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8));
val32 |= (t0 << (dev ? 8 : 0));
@@ -163,10 +148,11 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
u32 val32;
struct ide_timing *t;
+ t = ide_timing_find_mode(XFER_PIO_0 + mode);
+
/* PIO Data Setup */
t0 = DIV_ROUND_UP(cycletime, ideclk_period);
- t2 = DIV_ROUND_UP(ide_timing_find_mode(XFER_PIO_0 + mode)->active,
- ideclk_period);
+ t2 = DIV_ROUND_UP(t->active, ideclk_period);
t2i = t0 - t2 - 1;
t2 -= 1;
@@ -187,7 +173,6 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
}
/* TASKFILE Setup */
- t = ide_timing_find_mode(XFER_PIO_0 + mode);
t0 = DIV_ROUND_UP(t->cyc8b, ideclk_period);
t2 = DIV_ROUND_UP(t->act8b, ideclk_period);
@@ -236,42 +221,23 @@ static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio)
static void __devinit palm_bk3710_chipinit(void __iomem *base)
{
/*
- * enable the reset_en of ATA controller so that when ata signals
- * are brought out, by writing into device config. at that
- * time por_n signal should not be 'Z' and have a stable value.
+ * REVISIT: the ATA reset signal needs to be managed through a
+ * GPIO, which means it should come from platform_data. Until
+ * we get and use such information, we have to trust that things
+ * have been reset before we get here.
*/
- writel(0x0300, base + BK3710_MISCCTL);
-
- /* wait for some time and deassert the reset of ATA Device. */
- mdelay(100);
-
- /* Deassert the Reset */
- writel(0x0200, base + BK3710_MISCCTL);
/*
* Program the IDETIMP Register Value based on the following assumptions
*
* (ATA_IDETIMP_IDEEN , ENABLE ) |
- * (ATA_IDETIMP_SLVTIMEN , DISABLE) |
- * (ATA_IDETIMP_RDYSMPL , 70NS) |
- * (ATA_IDETIMP_RDYRCVRY , 50NS) |
- * (ATA_IDETIMP_DMAFTIM1 , PIOCOMP) |
* (ATA_IDETIMP_PREPOST1 , DISABLE) |
- * (ATA_IDETIMP_RDYSEN1 , DISABLE) |
- * (ATA_IDETIMP_PIOFTIM1 , DISABLE) |
- * (ATA_IDETIMP_DMAFTIM0 , PIOCOMP) |
* (ATA_IDETIMP_PREPOST0 , DISABLE) |
- * (ATA_IDETIMP_RDYSEN0 , DISABLE) |
- * (ATA_IDETIMP_PIOFTIM0 , DISABLE)
- */
- writew(0xB388, base + BK3710_IDETIMP);
-
- /*
- * Configure SIDETIM Register
- * (ATA_SIDETIM_RDYSMPS1 ,120NS ) |
- * (ATA_SIDETIM_RDYRCYS1 ,120NS )
+ *
+ * DM6446 silicon rev 2.1 and earlier have no observed net benefit
+ * from enabling prefetch/postwrite.
*/
- writeb(0, base + BK3710_SIDETIM);
+ writew(BIT(15), base + BK3710_IDETIMP);
/*
* UDMACTL Ultra-ATA DMA Control
@@ -283,11 +249,11 @@ static void __devinit palm_bk3710_chipinit(void __iomem *base)
/*
* MISCCTL Miscellaneous Conrol Register
- * (ATA_MISCCTL_RSTMODEP , 1) |
- * (ATA_MISCCTL_RESETP , 0) |
+ * (ATA_MISCCTL_HWNHLD1P , 1 cycle)
+ * (ATA_MISCCTL_HWNHLD0P , 1 cycle)
* (ATA_MISCCTL_TIMORIDE , 1)
*/
- writel(0x201, base + BK3710_MISCCTL);
+ writel(0x001, base + BK3710_MISCCTL);
/*
* IORDYTMP IORDY Timer for Primary Register
@@ -357,10 +323,9 @@ static int __init palm_bk3710_probe(struct platform_device *pdev)
clk_enable(clk);
rate = clk_get_rate(clk);
- ideclk_period = 1000000000UL / rate;
- /* Register the IDE interface with Linux ATA Interface */
- memset(&hw, 0, sizeof(hw));
+ /* NOTE: round *down* to meet minimum timings; we count in clocks */
+ ideclk_period = 1000000000UL / rate;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (mem == NULL) {
@@ -390,6 +355,7 @@ static int __init palm_bk3710_probe(struct platform_device *pdev)
/* Configure the Palm Chip controller */
palm_bk3710_chipinit(base);
+ memset(&hw, 0, sizeof(hw));
for (i = 0; i < IDE_NR_PORTS - 2; i++)
hw.io_ports_array[i] = (unsigned long)
(base + IDE_PALM_ATA_PRI_REG_OFFSET + i);
@@ -402,6 +368,7 @@ static int __init palm_bk3710_probe(struct platform_device *pdev)
palm_bk3710_port_info.udma_mask = rate < 100000000 ? ATA_UDMA4 :
ATA_UDMA5;
+ /* Register the IDE interface with Linux */
rc = ide_host_add(&palm_bk3710_port_info, hws, NULL);
if (rc)
goto out;
diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c
index 052b9bf1f8fb..f76e4e6b408f 100644
--- a/drivers/ide/pmac.c
+++ b/drivers/ide/pmac.c
@@ -1682,7 +1682,7 @@ static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif,
* The +2 is +1 for the stop command and +1 to allow for
* aligning the start address to a multiple of 16 bytes.
*/
- pmif->dma_table_cpu = (struct dbdma_cmd*)pci_alloc_consistent(
+ pmif->dma_table_cpu = pci_alloc_consistent(
dev,
(MAX_DCMDS + 2) * sizeof(struct dbdma_cmd),
&hwif->dmatable_dma);
diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c
index 8d71086f5a1c..62f9cf2f94ec 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_hal.c
+++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c
@@ -410,6 +410,7 @@ int cxio_flush_sq(struct t3_wq *wq, struct t3_cq *cq, int count)
ptr = wq->sq_rptr + count;
sqp = wq->sq + Q_PTR2IDX(ptr, wq->sq_size_log2);
while (ptr != wq->sq_wptr) {
+ sqp->signaled = 0;
insert_sq_cqe(wq, cq, sqp);
ptr++;
sqp = wq->sq + Q_PTR2IDX(ptr, wq->sq_size_log2);
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index fef3f1ae7225..52d7bb0c2a12 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -1830,6 +1830,10 @@ int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
ep->com.rpl_err = 0;
ep->ird = conn_param->ird;
ep->ord = conn_param->ord;
+
+ if (peer2peer && ep->ird == 0)
+ ep->ird = 1;
+
PDBG("%s %d ird %d ord %d\n", __func__, __LINE__, ep->ird, ep->ord);
get_ep(&ep->com);
@@ -1915,6 +1919,10 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
conn_param->private_data, ep->plen);
ep->ird = conn_param->ird;
ep->ord = conn_param->ord;
+
+ if (peer2peer && ep->ord == 0)
+ ep->ord = 1;
+
ep->com.tdev = h->rdev.t3cdev_p;
cm_id->add_ref(cm_id);
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
index 2f546a625330..27bbdc8e773a 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
@@ -1069,7 +1069,6 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
goto out;
}
qhp->attr.state = IWCH_QP_STATE_IDLE;
- memset(&qhp->attr, 0, sizeof(qhp->attr));
break;
case IWCH_QP_STATE_TERMINATE:
if (!internal) {
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index 368311ce332b..85905ab9391f 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -52,7 +52,7 @@
#include "ehca_tools.h"
#include "hcp_if.h"
-#define HCAD_VERSION "0026"
+#define HCAD_VERSION "0027"
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index 00c108159714..ead4e718c082 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -461,7 +461,7 @@ static struct ehca_qp *internal_create_qp(
ib_device);
struct ib_ucontext *context = NULL;
u64 h_ret;
- int is_llqp = 0, has_srq = 0;
+ int is_llqp = 0, has_srq = 0, is_user = 0;
int qp_type, max_send_sge, max_recv_sge, ret;
/* h_call's out parameters */
@@ -609,9 +609,6 @@ static struct ehca_qp *internal_create_qp(
}
}
- if (pd->uobject && udata)
- context = pd->uobject->context;
-
my_qp = kmem_cache_zalloc(qp_cache, GFP_KERNEL);
if (!my_qp) {
ehca_err(pd->device, "pd=%p not enough memory to alloc qp", pd);
@@ -619,6 +616,11 @@ static struct ehca_qp *internal_create_qp(
return ERR_PTR(-ENOMEM);
}
+ if (pd->uobject && udata) {
+ is_user = 1;
+ context = pd->uobject->context;
+ }
+
atomic_set(&my_qp->nr_events, 0);
init_waitqueue_head(&my_qp->wait_completion);
spin_lock_init(&my_qp->spinlock_s);
@@ -707,7 +709,7 @@ static struct ehca_qp *internal_create_qp(
(parms.squeue.is_small || parms.rqueue.is_small);
}
- h_ret = hipz_h_alloc_resource_qp(shca->ipz_hca_handle, &parms);
+ h_ret = hipz_h_alloc_resource_qp(shca->ipz_hca_handle, &parms, is_user);
if (h_ret != H_SUCCESS) {
ehca_err(pd->device, "h_alloc_resource_qp() failed h_ret=%lli",
h_ret);
@@ -769,18 +771,20 @@ static struct ehca_qp *internal_create_qp(
goto create_qp_exit2;
}
- my_qp->sq_map.entries = my_qp->ipz_squeue.queue_length /
- my_qp->ipz_squeue.qe_size;
- my_qp->sq_map.map = vmalloc(my_qp->sq_map.entries *
- sizeof(struct ehca_qmap_entry));
- if (!my_qp->sq_map.map) {
- ehca_err(pd->device, "Couldn't allocate squeue "
- "map ret=%i", ret);
- goto create_qp_exit3;
+ if (!is_user) {
+ my_qp->sq_map.entries = my_qp->ipz_squeue.queue_length /
+ my_qp->ipz_squeue.qe_size;
+ my_qp->sq_map.map = vmalloc(my_qp->sq_map.entries *
+ sizeof(struct ehca_qmap_entry));
+ if (!my_qp->sq_map.map) {
+ ehca_err(pd->device, "Couldn't allocate squeue "
+ "map ret=%i", ret);
+ goto create_qp_exit3;
+ }
+ INIT_LIST_HEAD(&my_qp->sq_err_node);
+ /* to avoid the generation of bogus flush CQEs */
+ reset_queue_map(&my_qp->sq_map);
}
- INIT_LIST_HEAD(&my_qp->sq_err_node);
- /* to avoid the generation of bogus flush CQEs */
- reset_queue_map(&my_qp->sq_map);
}
if (HAS_RQ(my_qp)) {
@@ -792,20 +796,21 @@ static struct ehca_qp *internal_create_qp(
"and pages ret=%i", ret);
goto create_qp_exit4;
}
-
- my_qp->rq_map.entries = my_qp->ipz_rqueue.queue_length /
- my_qp->ipz_rqueue.qe_size;
- my_qp->rq_map.map = vmalloc(my_qp->rq_map.entries *
- sizeof(struct ehca_qmap_entry));
- if (!my_qp->rq_map.map) {
- ehca_err(pd->device, "Couldn't allocate squeue "
- "map ret=%i", ret);
- goto create_qp_exit5;
+ if (!is_user) {
+ my_qp->rq_map.entries = my_qp->ipz_rqueue.queue_length /
+ my_qp->ipz_rqueue.qe_size;
+ my_qp->rq_map.map = vmalloc(my_qp->rq_map.entries *
+ sizeof(struct ehca_qmap_entry));
+ if (!my_qp->rq_map.map) {
+ ehca_err(pd->device, "Couldn't allocate squeue "
+ "map ret=%i", ret);
+ goto create_qp_exit5;
+ }
+ INIT_LIST_HEAD(&my_qp->rq_err_node);
+ /* to avoid the generation of bogus flush CQEs */
+ reset_queue_map(&my_qp->rq_map);
}
- INIT_LIST_HEAD(&my_qp->rq_err_node);
- /* to avoid the generation of bogus flush CQEs */
- reset_queue_map(&my_qp->rq_map);
- } else if (init_attr->srq) {
+ } else if (init_attr->srq && !is_user) {
/* this is a base QP, use the queue map of the SRQ */
my_qp->rq_map = my_srq->rq_map;
INIT_LIST_HEAD(&my_qp->rq_err_node);
@@ -918,7 +923,7 @@ create_qp_exit7:
kfree(my_qp->mod_qp_parm);
create_qp_exit6:
- if (HAS_RQ(my_qp))
+ if (HAS_RQ(my_qp) && !is_user)
vfree(my_qp->rq_map.map);
create_qp_exit5:
@@ -926,7 +931,7 @@ create_qp_exit5:
ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);
create_qp_exit4:
- if (HAS_SQ(my_qp))
+ if (HAS_SQ(my_qp) && !is_user)
vfree(my_qp->sq_map.map);
create_qp_exit3:
@@ -1244,6 +1249,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
u64 update_mask;
u64 h_ret;
int bad_wqe_cnt = 0;
+ int is_user = 0;
int squeue_locked = 0;
unsigned long flags = 0;
@@ -1266,6 +1272,8 @@ static int internal_modify_qp(struct ib_qp *ibqp,
ret = ehca2ib_return_code(h_ret);
goto modify_qp_exit1;
}
+ if (ibqp->uobject)
+ is_user = 1;
qp_cur_state = ehca2ib_qp_state(mqpcb->qp_state);
@@ -1728,7 +1736,8 @@ static int internal_modify_qp(struct ib_qp *ibqp,
goto modify_qp_exit2;
}
}
- if ((qp_new_state == IB_QPS_ERR) && (qp_cur_state != IB_QPS_ERR)) {
+ if ((qp_new_state == IB_QPS_ERR) && (qp_cur_state != IB_QPS_ERR)
+ && !is_user) {
ret = check_for_left_cqes(my_qp, shca);
if (ret)
goto modify_qp_exit2;
@@ -1738,16 +1747,17 @@ static int internal_modify_qp(struct ib_qp *ibqp,
ipz_qeit_reset(&my_qp->ipz_rqueue);
ipz_qeit_reset(&my_qp->ipz_squeue);
- if (qp_cur_state == IB_QPS_ERR) {
+ if (qp_cur_state == IB_QPS_ERR && !is_user) {
del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node);
if (HAS_RQ(my_qp))
del_from_err_list(my_qp->recv_cq,
&my_qp->rq_err_node);
}
- reset_queue_map(&my_qp->sq_map);
+ if (!is_user)
+ reset_queue_map(&my_qp->sq_map);
- if (HAS_RQ(my_qp))
+ if (HAS_RQ(my_qp) && !is_user)
reset_queue_map(&my_qp->rq_map);
}
@@ -2138,10 +2148,12 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
int ret;
u64 h_ret;
u8 port_num;
+ int is_user = 0;
enum ib_qp_type qp_type;
unsigned long flags;
if (uobject) {
+ is_user = 1;
if (my_qp->mm_count_galpa ||
my_qp->mm_count_rqueue || my_qp->mm_count_squeue) {
ehca_err(dev, "Resources still referenced in "
@@ -2168,10 +2180,10 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
* SRQs will never get into an error list and do not have a recv_cq,
* so we need to skip them here.
*/
- if (HAS_RQ(my_qp) && !IS_SRQ(my_qp))
+ if (HAS_RQ(my_qp) && !IS_SRQ(my_qp) && !is_user)
del_from_err_list(my_qp->recv_cq, &my_qp->rq_err_node);
- if (HAS_SQ(my_qp))
+ if (HAS_SQ(my_qp) && !is_user)
del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node);
/* now wait until all pending events have completed */
@@ -2209,13 +2221,13 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
if (HAS_RQ(my_qp)) {
ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);
-
- vfree(my_qp->rq_map.map);
+ if (!is_user)
+ vfree(my_qp->rq_map.map);
}
if (HAS_SQ(my_qp)) {
ipz_queue_dtor(my_pd, &my_qp->ipz_squeue);
-
- vfree(my_qp->sq_map.map);
+ if (!is_user)
+ vfree(my_qp->sq_map.map);
}
kmem_cache_free(qp_cache, my_qp);
atomic_dec(&shca->num_qps);
diff --git a/drivers/infiniband/hw/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c
index d0ab0c0d5e91..4d5dc3304d42 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.c
+++ b/drivers/infiniband/hw/ehca/hcp_if.c
@@ -284,7 +284,7 @@ u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
param->act_pages = (u32)outs[4];
if (ret == H_SUCCESS)
- hcp_galpas_ctor(&cq->galpas, outs[5], outs[6]);
+ hcp_galpas_ctor(&cq->galpas, 0, outs[5], outs[6]);
if (ret == H_NOT_ENOUGH_RESOURCES)
ehca_gen_err("Not enough resources. ret=%lli", ret);
@@ -293,7 +293,7 @@ u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
}
u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
- struct ehca_alloc_qp_parms *parms)
+ struct ehca_alloc_qp_parms *parms, int is_user)
{
u64 ret;
u64 allocate_controls, max_r10_reg, r11, r12;
@@ -359,7 +359,7 @@ u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
(u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]);
if (ret == H_SUCCESS)
- hcp_galpas_ctor(&parms->galpas, outs[6], outs[6]);
+ hcp_galpas_ctor(&parms->galpas, is_user, outs[6], outs[6]);
if (ret == H_NOT_ENOUGH_RESOURCES)
ehca_gen_err("Not enough resources. ret=%lli", ret);
diff --git a/drivers/infiniband/hw/ehca/hcp_if.h b/drivers/infiniband/hw/ehca/hcp_if.h
index 2c3c6e0ea5c2..39c1c3618ec7 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.h
+++ b/drivers/infiniband/hw/ehca/hcp_if.h
@@ -78,7 +78,7 @@ u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
* initialize resources, create empty QPPTs (2 rings).
*/
u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
- struct ehca_alloc_qp_parms *parms);
+ struct ehca_alloc_qp_parms *parms, int is_user);
u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
const u8 port_id,
diff --git a/drivers/infiniband/hw/ehca/hcp_phyp.c b/drivers/infiniband/hw/ehca/hcp_phyp.c
index 214821095cb1..b3e0e72e8a73 100644
--- a/drivers/infiniband/hw/ehca/hcp_phyp.c
+++ b/drivers/infiniband/hw/ehca/hcp_phyp.c
@@ -54,12 +54,15 @@ int hcall_unmap_page(u64 mapaddr)
return 0;
}
-int hcp_galpas_ctor(struct h_galpas *galpas,
+int hcp_galpas_ctor(struct h_galpas *galpas, int is_user,
u64 paddr_kernel, u64 paddr_user)
{
- int ret = hcall_map_page(paddr_kernel, &galpas->kernel.fw_handle);
- if (ret)
- return ret;
+ if (!is_user) {
+ int ret = hcall_map_page(paddr_kernel, &galpas->kernel.fw_handle);
+ if (ret)
+ return ret;
+ } else
+ galpas->kernel.fw_handle = 0;
galpas->user.fw_handle = paddr_user;
diff --git a/drivers/infiniband/hw/ehca/hcp_phyp.h b/drivers/infiniband/hw/ehca/hcp_phyp.h
index 5305c2a3ed94..204227d5303a 100644
--- a/drivers/infiniband/hw/ehca/hcp_phyp.h
+++ b/drivers/infiniband/hw/ehca/hcp_phyp.h
@@ -78,7 +78,7 @@ static inline void hipz_galpa_store(struct h_galpa galpa, u32 offset, u64 value)
*(volatile u64 __force *)addr = value;
}
-int hcp_galpas_ctor(struct h_galpas *galpas,
+int hcp_galpas_ctor(struct h_galpas *galpas, int is_user,
u64 paddr_kernel, u64 paddr_user);
int hcp_galpas_dtor(struct h_galpas *galpas);
diff --git a/drivers/infiniband/hw/ehca/ipz_pt_fn.c b/drivers/infiniband/hw/ehca/ipz_pt_fn.c
index c3a328465431..1227c593627a 100644
--- a/drivers/infiniband/hw/ehca/ipz_pt_fn.c
+++ b/drivers/infiniband/hw/ehca/ipz_pt_fn.c
@@ -220,10 +220,13 @@ int ipz_queue_ctor(struct ehca_pd *pd, struct ipz_queue *queue,
queue->small_page = NULL;
/* allocate queue page pointers */
- queue->queue_pages = vmalloc(nr_of_pages * sizeof(void *));
+ queue->queue_pages = kmalloc(nr_of_pages * sizeof(void *), GFP_KERNEL);
if (!queue->queue_pages) {
- ehca_gen_err("Couldn't allocate queue page list");
- return 0;
+ queue->queue_pages = vmalloc(nr_of_pages * sizeof(void *));
+ if (!queue->queue_pages) {
+ ehca_gen_err("Couldn't allocate queue page list");
+ return 0;
+ }
}
memset(queue->queue_pages, 0, nr_of_pages * sizeof(void *));
@@ -240,7 +243,10 @@ int ipz_queue_ctor(struct ehca_pd *pd, struct ipz_queue *queue,
ipz_queue_ctor_exit0:
ehca_gen_err("Couldn't alloc pages queue=%p "
"nr_of_pages=%x", queue, nr_of_pages);
- vfree(queue->queue_pages);
+ if (is_vmalloc_addr(queue->queue_pages))
+ vfree(queue->queue_pages);
+ else
+ kfree(queue->queue_pages);
return 0;
}
@@ -262,7 +268,10 @@ int ipz_queue_dtor(struct ehca_pd *pd, struct ipz_queue *queue)
free_page((unsigned long)queue->queue_pages[i]);
}
- vfree(queue->queue_pages);
+ if (is_vmalloc_addr(queue->queue_pages))
+ vfree(queue->queue_pages);
+ else
+ kfree(queue->queue_pages);
return 1;
}
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
index 8dc2bb781605..b3684060465e 100644
--- a/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -347,7 +347,7 @@ static int ipathfs_fill_super(struct super_block *sb, void *data,
spin_unlock_irqrestore(&ipath_devs_lock, flags);
ret = create_device_files(sb, dd);
if (ret) {
- deactivate_super(sb);
+ deactivate_locked_super(sb);
goto bail;
}
spin_lock_irqsave(&ipath_devs_lock, flags);
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index 9974e886b8de..8a7dd6795fa0 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -86,6 +86,7 @@ struct mlx4_ib_mr {
struct mlx4_ib_fast_reg_page_list {
struct ib_fast_reg_page_list ibfrpl;
+ __be64 *mapped_page_list;
dma_addr_t map;
};
diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c
index 8e4d26d56a95..8f3666b20ea4 100644
--- a/drivers/infiniband/hw/mlx4/mr.c
+++ b/drivers/infiniband/hw/mlx4/mr.c
@@ -231,7 +231,11 @@ struct ib_fast_reg_page_list *mlx4_ib_alloc_fast_reg_page_list(struct ib_device
if (!mfrpl)
return ERR_PTR(-ENOMEM);
- mfrpl->ibfrpl.page_list = dma_alloc_coherent(&dev->dev->pdev->dev,
+ mfrpl->ibfrpl.page_list = kmalloc(size, GFP_KERNEL);
+ if (!mfrpl->ibfrpl.page_list)
+ goto err_free;
+
+ mfrpl->mapped_page_list = dma_alloc_coherent(&dev->dev->pdev->dev,
size, &mfrpl->map,
GFP_KERNEL);
if (!mfrpl->ibfrpl.page_list)
@@ -242,6 +246,7 @@ struct ib_fast_reg_page_list *mlx4_ib_alloc_fast_reg_page_list(struct ib_device
return &mfrpl->ibfrpl;
err_free:
+ kfree(mfrpl->ibfrpl.page_list);
kfree(mfrpl);
return ERR_PTR(-ENOMEM);
}
@@ -252,8 +257,9 @@ void mlx4_ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list)
struct mlx4_ib_fast_reg_page_list *mfrpl = to_mfrpl(page_list);
int size = page_list->max_page_list_len * sizeof (u64);
- dma_free_coherent(&dev->dev->pdev->dev, size, page_list->page_list,
+ dma_free_coherent(&dev->dev->pdev->dev, size, mfrpl->mapped_page_list,
mfrpl->map);
+ kfree(mfrpl->ibfrpl.page_list);
kfree(mfrpl);
}
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index f385a24d31d2..20724aee76f4 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -1365,7 +1365,7 @@ static void set_fmr_seg(struct mlx4_wqe_fmr_seg *fseg, struct ib_send_wr *wr)
int i;
for (i = 0; i < wr->wr.fast_reg.page_list_len; ++i)
- wr->wr.fast_reg.page_list->page_list[i] =
+ mfrpl->mapped_page_list[i] =
cpu_to_be64(wr->wr.fast_reg.page_list->page_list[i] |
MLX4_MTT_FLAG_PRESENT);
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index c33e1c53c799..6d55f9d748f6 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -157,13 +157,15 @@ enum {
enum {
CMD_TIME_CLASS_A = (HZ + 999) / 1000 + 1,
CMD_TIME_CLASS_B = (HZ + 99) / 100 + 1,
- CMD_TIME_CLASS_C = (HZ + 9) / 10 + 1
+ CMD_TIME_CLASS_C = (HZ + 9) / 10 + 1,
+ CMD_TIME_CLASS_D = 60 * HZ
};
#else
enum {
CMD_TIME_CLASS_A = 60 * HZ,
CMD_TIME_CLASS_B = 60 * HZ,
- CMD_TIME_CLASS_C = 60 * HZ
+ CMD_TIME_CLASS_C = 60 * HZ,
+ CMD_TIME_CLASS_D = 60 * HZ
};
#endif
@@ -598,7 +600,7 @@ int mthca_SYS_EN(struct mthca_dev *dev, u8 *status)
u64 out;
int ret;
- ret = mthca_cmd_imm(dev, 0, &out, 0, 0, CMD_SYS_EN, HZ, status);
+ ret = mthca_cmd_imm(dev, 0, &out, 0, 0, CMD_SYS_EN, CMD_TIME_CLASS_D, status);
if (*status == MTHCA_CMD_STAT_DDR_MEM_ERR)
mthca_warn(dev, "SYS_EN DDR error: syn=%x, sock=%d, "
@@ -611,7 +613,7 @@ int mthca_SYS_EN(struct mthca_dev *dev, u8 *status)
int mthca_SYS_DIS(struct mthca_dev *dev, u8 *status)
{
- return mthca_cmd(dev, 0, 0, 0, CMD_SYS_DIS, HZ, status);
+ return mthca_cmd(dev, 0, 0, 0, CMD_SYS_DIS, CMD_TIME_CLASS_C, status);
}
static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
@@ -1390,7 +1392,7 @@ int mthca_INIT_HCA(struct mthca_dev *dev,
MTHCA_PUT(inbox, param->uarc_base, INIT_HCA_UAR_CTX_BASE_OFFSET);
}
- err = mthca_cmd(dev, mailbox->dma, 0, 0, CMD_INIT_HCA, HZ, status);
+ err = mthca_cmd(dev, mailbox->dma, 0, 0, CMD_INIT_HCA, CMD_TIME_CLASS_D, status);
mthca_free_mailbox(dev, mailbox);
return err;
@@ -1450,12 +1452,12 @@ int mthca_INIT_IB(struct mthca_dev *dev,
int mthca_CLOSE_IB(struct mthca_dev *dev, int port, u8 *status)
{
- return mthca_cmd(dev, 0, port, 0, CMD_CLOSE_IB, HZ, status);
+ return mthca_cmd(dev, 0, port, 0, CMD_CLOSE_IB, CMD_TIME_CLASS_A, status);
}
int mthca_CLOSE_HCA(struct mthca_dev *dev, int panic, u8 *status)
{
- return mthca_cmd(dev, 0, 0, panic, CMD_CLOSE_HCA, HZ, status);
+ return mthca_cmd(dev, 0, 0, panic, CMD_CLOSE_HCA, CMD_TIME_CLASS_C, status);
}
int mthca_SET_IB(struct mthca_dev *dev, struct mthca_set_ib_param *param,
diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h
index 17621de54a9f..bf1720f7f35f 100644
--- a/drivers/infiniband/hw/nes/nes.h
+++ b/drivers/infiniband/hw/nes/nes.h
@@ -56,10 +56,8 @@
#define QUEUE_DISCONNECTS
-#define DRV_BUILD "1"
-
#define DRV_NAME "iw_nes"
-#define DRV_VERSION "1.0 KO Build " DRV_BUILD
+#define DRV_VERSION "1.5.0.0"
#define PFX DRV_NAME ": "
/*
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index dbd9a75474e3..11c7d6642014 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -56,6 +56,7 @@
#include <net/neighbour.h>
#include <net/route.h>
#include <net/ip_fib.h>
+#include <net/tcp.h>
#include "nes.h"
@@ -540,6 +541,7 @@ static void nes_cm_timer_tick(unsigned long pass)
struct list_head *list_node;
struct nes_cm_core *cm_core = g_cm_core;
u32 settimer = 0;
+ unsigned long timetosend;
int ret = NETDEV_TX_OK;
struct list_head timer_list;
@@ -644,8 +646,11 @@ static void nes_cm_timer_tick(unsigned long pass)
send_entry->retrycount);
if (send_entry->send_retrans) {
send_entry->retranscount--;
+ timetosend = (NES_RETRY_TIMEOUT <<
+ (NES_DEFAULT_RETRANS - send_entry->retranscount));
+
send_entry->timetosend = jiffies +
- NES_RETRY_TIMEOUT;
+ min(timetosend, NES_MAX_TIMEOUT);
if (nexttimeout > send_entry->timetosend ||
!settimer) {
nexttimeout = send_entry->timetosend;
@@ -854,7 +859,6 @@ static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core,
{
unsigned long flags;
struct nes_cm_listener *listen_node;
- __be32 tmp_addr = cpu_to_be32(dst_addr);
/* walk list and find cm_node associated with this session ID */
spin_lock_irqsave(&cm_core->listen_list_lock, flags);
@@ -871,9 +875,6 @@ static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core,
}
spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
- nes_debug(NES_DBG_CM, "Unable to find listener for %pI4:%x\n",
- &tmp_addr, dst_port);
-
/* no listener */
return NULL;
}
@@ -1325,18 +1326,20 @@ static void handle_fin_pkt(struct nes_cm_node *cm_node)
nes_debug(NES_DBG_CM, "Received FIN, cm_node = %p, state = %u. "
"refcnt=%d\n", cm_node, cm_node->state,
atomic_read(&cm_node->ref_count));
- cm_node->tcp_cntxt.rcv_nxt++;
- cleanup_retrans_entry(cm_node);
switch (cm_node->state) {
case NES_CM_STATE_SYN_RCVD:
case NES_CM_STATE_SYN_SENT:
case NES_CM_STATE_ESTABLISHED:
case NES_CM_STATE_MPAREQ_SENT:
case NES_CM_STATE_MPAREJ_RCVD:
+ cm_node->tcp_cntxt.rcv_nxt++;
+ cleanup_retrans_entry(cm_node);
cm_node->state = NES_CM_STATE_LAST_ACK;
send_fin(cm_node, NULL);
break;
case NES_CM_STATE_FIN_WAIT1:
+ cm_node->tcp_cntxt.rcv_nxt++;
+ cleanup_retrans_entry(cm_node);
cm_node->state = NES_CM_STATE_CLOSING;
send_ack(cm_node, NULL);
/* Wait for ACK as this is simultanous close..
@@ -1344,11 +1347,15 @@ static void handle_fin_pkt(struct nes_cm_node *cm_node)
* Just rm the node.. Done.. */
break;
case NES_CM_STATE_FIN_WAIT2:
+ cm_node->tcp_cntxt.rcv_nxt++;
+ cleanup_retrans_entry(cm_node);
cm_node->state = NES_CM_STATE_TIME_WAIT;
send_ack(cm_node, NULL);
schedule_nes_timer(cm_node, NULL, NES_TIMER_TYPE_CLOSE, 1, 0);
break;
case NES_CM_STATE_TIME_WAIT:
+ cm_node->tcp_cntxt.rcv_nxt++;
+ cleanup_retrans_entry(cm_node);
cm_node->state = NES_CM_STATE_CLOSED;
rem_ref_cm_node(cm_node->cm_core, cm_node);
break;
@@ -1384,7 +1391,6 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
passive_state = atomic_add_return(1, &cm_node->passive_state);
if (passive_state == NES_SEND_RESET_EVENT)
create_event(cm_node, NES_CM_EVENT_RESET);
- cleanup_retrans_entry(cm_node);
cm_node->state = NES_CM_STATE_CLOSED;
dev_kfree_skb_any(skb);
break;
@@ -1398,17 +1404,16 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
active_open_err(cm_node, skb, reset);
break;
case NES_CM_STATE_CLOSED:
- cleanup_retrans_entry(cm_node);
drop_packet(skb);
break;
+ case NES_CM_STATE_LAST_ACK:
+ cm_node->cm_id->rem_ref(cm_node->cm_id);
case NES_CM_STATE_TIME_WAIT:
- cleanup_retrans_entry(cm_node);
cm_node->state = NES_CM_STATE_CLOSED;
rem_ref_cm_node(cm_node->cm_core, cm_node);
drop_packet(skb);
break;
case NES_CM_STATE_FIN_WAIT1:
- cleanup_retrans_entry(cm_node);
nes_debug(NES_DBG_CM, "Bad state %s[%u]\n", __func__, __LINE__);
default:
drop_packet(skb);
@@ -1455,6 +1460,7 @@ static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb)
NES_PASSIVE_STATE_INDICATED);
break;
case NES_CM_STATE_MPAREQ_SENT:
+ cleanup_retrans_entry(cm_node);
if (res_type == NES_MPA_REQUEST_REJECT) {
type = NES_CM_EVENT_MPA_REJECT;
cm_node->state = NES_CM_STATE_MPAREJ_RCVD;
@@ -1518,7 +1524,7 @@ static int check_seq(struct nes_cm_node *cm_node, struct tcphdr *tcph,
rcv_wnd = cm_node->tcp_cntxt.rcv_wnd;
if (ack_seq != loc_seq_num)
err = 1;
- else if ((seq + rcv_wnd) < rcv_nxt)
+ else if (!between(seq, rcv_nxt, (rcv_nxt+rcv_wnd)))
err = 1;
if (err) {
nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p "
@@ -1652,49 +1658,39 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
}
}
-static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
+static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
struct tcphdr *tcph)
{
int datasize = 0;
u32 inc_sequence;
u32 rem_seq_ack;
u32 rem_seq;
- int ret;
+ int ret = 0;
int optionsize;
optionsize = (tcph->doff << 2) - sizeof(struct tcphdr);
if (check_seq(cm_node, tcph, skb))
- return;
+ return -EINVAL;
skb_pull(skb, tcph->doff << 2);
inc_sequence = ntohl(tcph->seq);
rem_seq = ntohl(tcph->seq);
rem_seq_ack = ntohl(tcph->ack_seq);
datasize = skb->len;
- cleanup_retrans_entry(cm_node);
switch (cm_node->state) {
case NES_CM_STATE_SYN_RCVD:
/* Passive OPEN */
+ cleanup_retrans_entry(cm_node);
ret = handle_tcp_options(cm_node, tcph, skb, optionsize, 1);
if (ret)
break;
cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq);
- if (cm_node->tcp_cntxt.rem_ack_num !=
- cm_node->tcp_cntxt.loc_seq_num) {
- nes_debug(NES_DBG_CM, "rem_ack_num != loc_seq_num\n");
- cleanup_retrans_entry(cm_node);
- send_reset(cm_node, skb);
- return;
- }
cm_node->state = NES_CM_STATE_ESTABLISHED;
- cleanup_retrans_entry(cm_node);
if (datasize) {
cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
handle_rcv_mpa(cm_node, skb);
- } else { /* rcvd ACK only */
+ } else /* rcvd ACK only */
dev_kfree_skb_any(skb);
- cleanup_retrans_entry(cm_node);
- }
break;
case NES_CM_STATE_ESTABLISHED:
/* Passive OPEN */
@@ -1706,15 +1702,12 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
drop_packet(skb);
break;
case NES_CM_STATE_MPAREQ_SENT:
- cleanup_retrans_entry(cm_node);
cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq);
if (datasize) {
cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
handle_rcv_mpa(cm_node, skb);
- } else { /* Could be just an ack pkt.. */
- cleanup_retrans_entry(cm_node);
+ } else /* Could be just an ack pkt.. */
dev_kfree_skb_any(skb);
- }
break;
case NES_CM_STATE_LISTENING:
case NES_CM_STATE_CLOSED:
@@ -1722,11 +1715,10 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
send_reset(cm_node, skb);
break;
case NES_CM_STATE_LAST_ACK:
+ case NES_CM_STATE_CLOSING:
cleanup_retrans_entry(cm_node);
cm_node->state = NES_CM_STATE_CLOSED;
cm_node->cm_id->rem_ref(cm_node->cm_id);
- case NES_CM_STATE_CLOSING:
- cleanup_retrans_entry(cm_node);
rem_ref_cm_node(cm_node->cm_core, cm_node);
drop_packet(skb);
break;
@@ -1741,9 +1733,11 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
case NES_CM_STATE_MPAREQ_RCVD:
case NES_CM_STATE_UNKNOWN:
default:
+ cleanup_retrans_entry(cm_node);
drop_packet(skb);
break;
}
+ return ret;
}
@@ -1849,6 +1843,7 @@ static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
enum nes_tcpip_pkt_type pkt_type = NES_PKT_TYPE_UNKNOWN;
struct tcphdr *tcph = tcp_hdr(skb);
u32 fin_set = 0;
+ int ret = 0;
skb_pull(skb, ip_hdr(skb)->ihl << 2);
nes_debug(NES_DBG_CM, "process_packet: cm_node=%p state =%d syn=%d "
@@ -1874,17 +1869,17 @@ static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
handle_synack_pkt(cm_node, skb, tcph);
break;
case NES_PKT_TYPE_ACK:
- handle_ack_pkt(cm_node, skb, tcph);
- if (fin_set)
+ ret = handle_ack_pkt(cm_node, skb, tcph);
+ if (fin_set && !ret)
handle_fin_pkt(cm_node);
break;
case NES_PKT_TYPE_RST:
handle_rst_pkt(cm_node, skb, tcph);
break;
default:
- drop_packet(skb);
- if (fin_set)
+ if ((fin_set) && (!check_seq(cm_node, tcph, skb)))
handle_fin_pkt(cm_node);
+ drop_packet(skb);
break;
}
}
@@ -2710,7 +2705,6 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
/* associate the node with the QP */
nesqp->cm_node = (void *)cm_node;
cm_node->nesqp = nesqp;
- nes_add_ref(&nesqp->ibqp);
nes_debug(NES_DBG_CM, "QP%u, cm_node=%p, jiffies = %lu listener = %p\n",
nesqp->hwqp.qp_id, cm_node, jiffies, cm_node->listener);
@@ -2763,6 +2757,9 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
nes_debug(NES_DBG_CM, "Unable to register memory region"
"for lSMM for cm_node = %p \n",
cm_node);
+ pci_free_consistent(nesdev->pcidev,
+ nesqp->private_data_len+sizeof(struct ietf_mpa_frame),
+ nesqp->ietf_frame, nesqp->ietf_frame_pbase);
return -ENOMEM;
}
@@ -2879,6 +2876,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
/* notify OF layer that accept event was successful */
cm_id->add_ref(cm_id);
+ nes_add_ref(&nesqp->ibqp);
cm_event.event = IW_CM_EVENT_ESTABLISHED;
cm_event.status = IW_CM_EVENT_STATUS_ACCEPTED;
@@ -2959,6 +2957,7 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
struct nes_device *nesdev;
struct nes_cm_node *cm_node;
struct nes_cm_info cm_info;
+ int apbvt_set = 0;
ibqp = nes_get_qp(cm_id->device, conn_param->qpn);
if (!ibqp)
@@ -2996,9 +2995,11 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
conn_param->private_data_len);
if (cm_id->local_addr.sin_addr.s_addr !=
- cm_id->remote_addr.sin_addr.s_addr)
+ cm_id->remote_addr.sin_addr.s_addr) {
nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port),
PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD);
+ apbvt_set = 1;
+ }
/* set up the connection params for the node */
cm_info.loc_addr = htonl(cm_id->local_addr.sin_addr.s_addr);
@@ -3015,8 +3016,7 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
conn_param->private_data_len, (void *)conn_param->private_data,
&cm_info);
if (!cm_node) {
- if (cm_id->local_addr.sin_addr.s_addr !=
- cm_id->remote_addr.sin_addr.s_addr)
+ if (apbvt_set)
nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port),
PCI_FUNC(nesdev->pcidev->devfn),
NES_MANAGE_APBVT_DEL);
@@ -3025,7 +3025,7 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
return -ENOMEM;
}
- cm_node->apbvt_set = 1;
+ cm_node->apbvt_set = apbvt_set;
nesqp->cm_node = cm_node;
cm_node->nesqp = nesqp;
nes_add_ref(&nesqp->ibqp);
diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h
index 80bba1892571..8b7e7c0e496e 100644
--- a/drivers/infiniband/hw/nes/nes_cm.h
+++ b/drivers/infiniband/hw/nes/nes_cm.h
@@ -149,6 +149,7 @@ struct nes_timer_entry {
#endif
#define NES_SHORT_TIME (10)
#define NES_LONG_TIME (2000*HZ/1000)
+#define NES_MAX_TIMEOUT ((unsigned long) (12*HZ))
#define NES_CM_HASHTABLE_SIZE 1024
#define NES_CM_TCP_TIMER_INTERVAL 3000
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
index d6fc9ae44062..b832a7b814a2 100644
--- a/drivers/infiniband/hw/nes/nes_hw.c
+++ b/drivers/infiniband/hw/nes/nes_hw.c
@@ -550,11 +550,8 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) {
msleep(1);
}
if (int_cnt > 1) {
- u32 sds;
spin_lock_irqsave(&nesadapter->phy_lock, flags);
- sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);
- sds |= 0x00000040;
- nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, sds);
+ nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F0C8);
mh_detected++;
reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET);
reset_value |= 0x0000003d;
@@ -579,7 +576,7 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) {
if (++ext_cnt > int_cnt) {
spin_lock_irqsave(&nesadapter->phy_lock, flags);
nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1,
- 0x0000F0C8);
+ 0x0000F088);
mh_detected++;
reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET);
reset_value |= 0x0000003d;
@@ -764,6 +761,9 @@ static int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count,
return 0;
/* init serdes 1 */
+ if (!(OneG_Mode && (nesadapter->phy_type[1] != NES_PHY_TYPE_PUMA_1G)))
+ nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000FF);
+
switch (nesadapter->phy_type[1]) {
case NES_PHY_TYPE_ARGUS:
case NES_PHY_TYPE_SFP_D:
@@ -771,21 +771,20 @@ static int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count,
nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP1, 0x00000000);
break;
case NES_PHY_TYPE_CX4:
- sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);
- sds &= 0xFFFFFFBF;
- nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, sds);
if (wide_ppm_offset)
nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000FFFAA);
- else
- nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000FF);
break;
case NES_PHY_TYPE_PUMA_1G:
sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);
sds |= 0x000000100;
nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, sds);
}
- if (!OneG_Mode)
+ if (!OneG_Mode) {
nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE1, 0x11110000);
+ sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);
+ sds &= 0xFFFFFFBF;
+ nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, sds);
+ }
} else {
/* init serdes 0 */
nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, 0x00000008);
@@ -913,6 +912,12 @@ static void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_cou
u32temp &= 0x7fffffff;
u32temp |= 0x7fff0010;
nes_write_indexed(nesdev, 0x000021f8, u32temp);
+ if (port_count > 1) {
+ u32temp = nes_read_indexed(nesdev, 0x000023f8);
+ u32temp &= 0x7fffffff;
+ u32temp |= 0x7fff0010;
+ nes_write_indexed(nesdev, 0x000023f8, u32temp);
+ }
}
}
@@ -1366,13 +1371,14 @@ int nes_init_phy(struct nes_device *nesdev)
if (phy_type == NES_PHY_TYPE_ARGUS) {
nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc302, 0x000C);
nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc319, 0x0008);
+ nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0027, 0x0001);
} else {
nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc302, 0x0004);
nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc319, 0x0038);
+ nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0027, 0x0013);
}
nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc31a, 0x0098);
nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0026, 0x0E00);
- nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0027, 0x0001);
/* setup LEDs */
nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd006, 0x0007);
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 7e5b5ba13a74..64d5cfd8f380 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -1627,6 +1627,7 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries,
nescq->hw_cq.cq_number = nes_ucontext->mcrqf & 0xffff;
else
nescq->hw_cq.cq_number = nesvnic->mcrq_qp_id + nes_ucontext->mcrqf-1;
+ nescq->mcrqf = nes_ucontext->mcrqf;
nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
}
nes_debug(NES_DBG_CQ, "CQ Virtual Address = %08lX, size = %u.\n",
@@ -1682,6 +1683,12 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries,
if (!context)
pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem,
nescq->hw_cq.cq_pbase);
+ else {
+ pci_free_consistent(nesdev->pcidev, nespbl->pbl_size,
+ nespbl->pbl_vbase, nespbl->pbl_pbase);
+ kfree(nespbl);
+ }
+
nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
kfree(nescq);
return ERR_PTR(-ENOMEM);
@@ -1705,6 +1712,11 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries,
if (!context)
pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem,
nescq->hw_cq.cq_pbase);
+ else {
+ pci_free_consistent(nesdev->pcidev, nespbl->pbl_size,
+ nespbl->pbl_vbase, nespbl->pbl_pbase);
+ kfree(nespbl);
+ }
nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
kfree(nescq);
return ERR_PTR(-ENOMEM);
@@ -1722,6 +1734,11 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries,
if (!context)
pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem,
nescq->hw_cq.cq_pbase);
+ else {
+ pci_free_consistent(nesdev->pcidev, nespbl->pbl_size,
+ nespbl->pbl_vbase, nespbl->pbl_pbase);
+ kfree(nespbl);
+ }
nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
kfree(nescq);
return ERR_PTR(-ENOMEM);
@@ -1774,6 +1791,11 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries,
if (!context)
pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem,
nescq->hw_cq.cq_pbase);
+ else {
+ pci_free_consistent(nesdev->pcidev, nespbl->pbl_size,
+ nespbl->pbl_vbase, nespbl->pbl_pbase);
+ kfree(nespbl);
+ }
nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
kfree(nescq);
return ERR_PTR(-EIO);
@@ -1855,7 +1877,9 @@ static int nes_destroy_cq(struct ib_cq *ib_cq)
set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode);
set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
(nescq->hw_cq.cq_number | ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 16)));
- nes_free_resource(nesadapter, nesadapter->allocated_cqs, nescq->hw_cq.cq_number);
+ if (!nescq->mcrqf)
+ nes_free_resource(nesadapter, nesadapter->allocated_cqs, nescq->hw_cq.cq_number);
+
atomic_set(&cqp_request->refcount, 2);
nes_post_cqp_request(nesdev, cqp_request);
@@ -1895,8 +1919,7 @@ static int nes_destroy_cq(struct ib_cq *ib_cq)
static u32 root_256(struct nes_device *nesdev,
struct nes_root_vpbl *root_vpbl,
struct nes_root_vpbl *new_root,
- u16 pbl_count_4k,
- u16 pbl_count_256)
+ u16 pbl_count_4k)
{
u64 leaf_pbl;
int i, j, k;
@@ -1952,7 +1975,7 @@ static int nes_reg_mr(struct nes_device *nesdev, struct nes_pd *nespd,
int ret;
struct nes_adapter *nesadapter = nesdev->nesadapter;
uint pg_cnt = 0;
- u16 pbl_count_256;
+ u16 pbl_count_256 = 0;
u16 pbl_count = 0;
u8 use_256_pbls = 0;
u8 use_4k_pbls = 0;
@@ -2012,7 +2035,7 @@ static int nes_reg_mr(struct nes_device *nesdev, struct nes_pd *nespd,
}
if (use_256_pbls && use_two_level) {
- if (root_256(nesdev, root_vpbl, &new_root, pbl_count_4k, pbl_count_256) == 1) {
+ if (root_256(nesdev, root_vpbl, &new_root, pbl_count_4k) == 1) {
if (new_root.pbl_pbase != 0)
root_vpbl = &new_root;
} else {
@@ -2122,6 +2145,7 @@ static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd,
struct nes_root_vpbl root_vpbl;
u32 stag;
u32 i;
+ unsigned long mask;
u32 stag_index = 0;
u32 next_stag_index = 0;
u32 driver_key = 0;
@@ -2150,6 +2174,9 @@ static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd,
return ERR_PTR(-E2BIG);
}
+ if ((buffer_list[0].addr ^ *iova_start) & ~PAGE_MASK)
+ return ERR_PTR(-EINVAL);
+
err = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs, nesadapter->max_mr,
&stag_index, &next_stag_index);
if (err) {
@@ -2215,19 +2242,16 @@ static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd,
root_pbl_index++;
cur_pbl_index = 0;
}
- if (buffer_list[i].addr & ~PAGE_MASK) {
- /* TODO: Unwind allocated buffers */
- nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
- nes_debug(NES_DBG_MR, "Unaligned Memory Buffer: 0x%x\n",
- (unsigned int) buffer_list[i].addr);
- ibmr = ERR_PTR(-EINVAL);
- kfree(nesmr);
- goto reg_phys_err;
- }
- if (!buffer_list[i].size) {
+ mask = !buffer_list[i].size;
+ if (i != 0)
+ mask |= buffer_list[i].addr;
+ if (i != num_phys_buf - 1)
+ mask |= buffer_list[i].addr + buffer_list[i].size;
+
+ if (mask & ~PAGE_MASK) {
nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
- nes_debug(NES_DBG_MR, "Invalid Buffer Size\n");
+ nes_debug(NES_DBG_MR, "Invalid buffer addr or size\n");
ibmr = ERR_PTR(-EINVAL);
kfree(nesmr);
goto reg_phys_err;
@@ -2238,7 +2262,7 @@ static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd,
if ((buffer_list[i-1].addr+PAGE_SIZE) != buffer_list[i].addr)
single_page = 0;
}
- vpbl.pbl_vbase[cur_pbl_index].pa_low = cpu_to_le32((u32)buffer_list[i].addr);
+ vpbl.pbl_vbase[cur_pbl_index].pa_low = cpu_to_le32((u32)buffer_list[i].addr & PAGE_MASK);
vpbl.pbl_vbase[cur_pbl_index++].pa_high =
cpu_to_le32((u32)((((u64)buffer_list[i].addr) >> 32)));
}
@@ -2251,8 +2275,6 @@ static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd,
" length = 0x%016lX, index = 0x%08X\n",
stag, (unsigned long)*iova_start, (unsigned long)region_length, stag_index);
- region_length -= (*iova_start)&PAGE_MASK;
-
/* Make the leaf PBL the root if only one PBL */
if (root_pbl_index == 1) {
root_vpbl.pbl_pbase = vpbl.pbl_pbase;
@@ -2786,10 +2808,9 @@ static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr,
struct nes_vnic *nesvnic = nesibdev->nesvnic;
nes_debug(NES_DBG_INIT, "\n");
- return sprintf(buf, "%x.%x.%x\n",
- (int)(nesvnic->nesdev->nesadapter->fw_ver >> 32),
- (int)(nesvnic->nesdev->nesadapter->fw_ver >> 16) & 0xffff,
- (int)(nesvnic->nesdev->nesadapter->fw_ver & 0xffff));
+ return sprintf(buf, "%u.%u\n",
+ (nesvnic->nesdev->nesadapter->firmware_version >> 16),
+ (nesvnic->nesdev->nesadapter->firmware_version & 0x000000ff));
}
diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h
index 5e48f67fbe8d..41c07f29f7c9 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.h
+++ b/drivers/infiniband/hw/nes/nes_verbs.h
@@ -112,6 +112,7 @@ struct nes_cq {
spinlock_t lock;
u8 virtual_cq;
u8 pad[3];
+ u32 mcrqf;
};
struct nes_wq {
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index da6082739839..e7e5adf84e84 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -685,7 +685,8 @@ int ipoib_ib_dev_open(struct net_device *dev)
queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task,
round_jiffies_relative(HZ));
- set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
+ if (!test_and_set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags))
+ napi_enable(&priv->napi);
return 0;
}
@@ -804,7 +805,8 @@ int ipoib_ib_dev_stop(struct net_device *dev, int flush)
struct ipoib_tx_buf *tx_req;
int i;
- clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
+ if (test_and_clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags))
+ napi_disable(&priv->napi);
ipoib_cm_dev_stop(dev);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 421a6640c9bd..ab2c192c76bc 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -106,8 +106,7 @@ int ipoib_open(struct net_device *dev)
ipoib_dbg(priv, "bringing up interface\n");
- if (!test_and_set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
- napi_enable(&priv->napi);
+ set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
if (ipoib_pkey_dev_delay_open(dev))
return 0;
@@ -143,7 +142,6 @@ err_stop:
ipoib_ib_dev_stop(dev, 1);
err_disable:
- napi_disable(&priv->napi);
clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
return -EINVAL;
@@ -156,7 +154,6 @@ static int ipoib_stop(struct net_device *dev)
ipoib_dbg(priv, "stopping interface\n");
clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
- napi_disable(&priv->napi);
netif_stop_queue(dev);
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 13d7674b293d..75223f50de58 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -599,6 +599,7 @@ static struct scsi_host_template iscsi_iser_sht = {
.eh_abort_handler = iscsi_eh_abort,
.eh_device_reset_handler= iscsi_eh_device_reset,
.eh_target_reset_handler= iscsi_eh_target_reset,
+ .target_alloc = iscsi_target_alloc,
.use_clustering = DISABLE_CLUSTERING,
.proc_name = "iscsi_iser",
.this_id = -1,
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 7a7a026ba712..c238116400b3 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -25,7 +25,6 @@ struct evdev {
int exist;
int open;
int minor;
- char name[16];
struct input_handle handle;
wait_queue_head_t wait;
struct evdev_client *grab;
@@ -609,7 +608,8 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
p, compat_mode);
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0)))
- return str_to_user(dev->name, _IOC_SIZE(cmd), p);
+ return str_to_user(dev_name(&evdev->dev),
+ _IOC_SIZE(cmd), p);
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0)))
return str_to_user(dev->phys, _IOC_SIZE(cmd), p);
@@ -807,16 +807,15 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
mutex_init(&evdev->mutex);
init_waitqueue_head(&evdev->wait);
- snprintf(evdev->name, sizeof(evdev->name), "event%d", minor);
+ dev_set_name(&evdev->dev, "event%d", minor);
evdev->exist = 1;
evdev->minor = minor;
evdev->handle.dev = input_get_device(dev);
- evdev->handle.name = evdev->name;
+ evdev->handle.name = dev_name(&evdev->dev);
evdev->handle.handler = handler;
evdev->handle.private = evdev;
- dev_set_name(&evdev->dev, evdev->name);
evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
evdev->dev.class = &input_class;
evdev->dev.parent = &dev->dev;
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
index bc4e40f3ede7..2d1415e16834 100644
--- a/drivers/input/ff-memless.c
+++ b/drivers/input/ff-memless.c
@@ -226,7 +226,7 @@ static int get_compatible_type(struct ff_device *ff, int effect_type)
*/
static void ml_combine_effects(struct ff_effect *effect,
struct ml_effect_state *state,
- int gain)
+ unsigned int gain)
{
struct ff_effect *new = state->effect;
unsigned int strong, weak, i;
diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c
index 1dec00e20dbc..8a1810f88b9e 100644
--- a/drivers/input/gameport/fm801-gp.c
+++ b/drivers/input/gameport/fm801-gp.c
@@ -167,5 +167,6 @@ module_exit(fm801_gp_exit);
MODULE_DEVICE_TABLE(pci, fm801_gp_id_table);
+MODULE_DESCRIPTION("FM801 gameport driver");
MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
MODULE_LICENSE("GPL");
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index ebf4be5b7c4e..ac11be08585e 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -30,16 +30,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Generic gameport layer");
MODULE_LICENSE("GPL");
-EXPORT_SYMBOL(__gameport_register_port);
-EXPORT_SYMBOL(gameport_unregister_port);
-EXPORT_SYMBOL(__gameport_register_driver);
-EXPORT_SYMBOL(gameport_unregister_driver);
-EXPORT_SYMBOL(gameport_open);
-EXPORT_SYMBOL(gameport_close);
-EXPORT_SYMBOL(gameport_set_phys);
-EXPORT_SYMBOL(gameport_start_polling);
-EXPORT_SYMBOL(gameport_stop_polling);
-
/*
* gameport_mutex protects entire gameport subsystem and is taken
* every time gameport port or driver registrered or unregistered.
@@ -50,9 +40,8 @@ static LIST_HEAD(gameport_list);
static struct bus_type gameport_bus;
-static void gameport_add_driver(struct gameport_driver *drv);
static void gameport_add_port(struct gameport *gameport);
-static void gameport_destroy_port(struct gameport *gameport);
+static void gameport_attach_driver(struct gameport_driver *drv);
static void gameport_reconnect_port(struct gameport *gameport);
static void gameport_disconnect_port(struct gameport *gameport);
@@ -163,6 +152,7 @@ void gameport_start_polling(struct gameport *gameport)
spin_unlock(&gameport->timer_lock);
}
+EXPORT_SYMBOL(gameport_start_polling);
void gameport_stop_polling(struct gameport *gameport)
{
@@ -173,6 +163,7 @@ void gameport_stop_polling(struct gameport *gameport)
spin_unlock(&gameport->timer_lock);
}
+EXPORT_SYMBOL(gameport_stop_polling);
static void gameport_run_poll_handler(unsigned long d)
{
@@ -230,7 +221,6 @@ static void gameport_find_driver(struct gameport *gameport)
enum gameport_event_type {
GAMEPORT_REGISTER_PORT,
- GAMEPORT_REGISTER_DRIVER,
GAMEPORT_ATTACH_DRIVER,
};
@@ -374,8 +364,8 @@ static void gameport_handle_event(void)
gameport_add_port(event->object);
break;
- case GAMEPORT_REGISTER_DRIVER:
- gameport_add_driver(event->object);
+ case GAMEPORT_ATTACH_DRIVER:
+ gameport_attach_driver(event->object);
break;
default:
@@ -518,6 +508,7 @@ void gameport_set_phys(struct gameport *gameport, const char *fmt, ...)
vsnprintf(gameport->phys, sizeof(gameport->phys), fmt, args);
va_end(args);
}
+EXPORT_SYMBOL(gameport_set_phys);
/*
* Prepare gameport port for registration.
@@ -660,6 +651,7 @@ void __gameport_register_port(struct gameport *gameport, struct module *owner)
gameport_init_port(gameport);
gameport_queue_event(gameport, owner, GAMEPORT_REGISTER_PORT);
}
+EXPORT_SYMBOL(__gameport_register_port);
/*
* Synchronously unregisters gameport port.
@@ -671,6 +663,7 @@ void gameport_unregister_port(struct gameport *gameport)
gameport_destroy_port(gameport);
mutex_unlock(&gameport_mutex);
}
+EXPORT_SYMBOL(gameport_unregister_port);
/*
@@ -706,14 +699,14 @@ static int gameport_driver_remove(struct device *dev)
return 0;
}
-static void gameport_add_driver(struct gameport_driver *drv)
+static void gameport_attach_driver(struct gameport_driver *drv)
{
int error;
- error = driver_register(&drv->driver);
+ error = driver_attach(&drv->driver);
if (error)
printk(KERN_ERR
- "gameport: driver_register() failed for %s, error: %d\n",
+ "gameport: driver_attach() failed for %s, error: %d\n",
drv->driver.name, error);
}
@@ -730,7 +723,7 @@ int __gameport_register_driver(struct gameport_driver *drv, struct module *owner
* Temporarily disable automatic binding because probing
* takes long time and we are better off doing it in kgameportd
*/
- drv->ignore = 1;
+ drv->ignore = true;
error = driver_register(&drv->driver);
if (error) {
@@ -743,7 +736,7 @@ int __gameport_register_driver(struct gameport_driver *drv, struct module *owner
/*
* Reset ignore flag and let kgameportd bind the driver to free ports
*/
- drv->ignore = 0;
+ drv->ignore = false;
error = gameport_queue_event(drv, NULL, GAMEPORT_ATTACH_DRIVER);
if (error) {
driver_unregister(&drv->driver);
@@ -752,6 +745,7 @@ int __gameport_register_driver(struct gameport_driver *drv, struct module *owner
return 0;
}
+EXPORT_SYMBOL(__gameport_register_driver);
void gameport_unregister_driver(struct gameport_driver *drv)
{
@@ -759,7 +753,7 @@ void gameport_unregister_driver(struct gameport_driver *drv)
mutex_lock(&gameport_mutex);
- drv->ignore = 1; /* so gameport_find_driver ignores it */
+ drv->ignore = true; /* so gameport_find_driver ignores it */
gameport_remove_pending_events(drv);
start_over:
@@ -776,6 +770,7 @@ start_over:
mutex_unlock(&gameport_mutex);
}
+EXPORT_SYMBOL(gameport_unregister_driver);
static int gameport_bus_match(struct device *dev, struct device_driver *drv)
{
@@ -814,6 +809,7 @@ int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mo
gameport_set_drv(gameport, drv);
return 0;
}
+EXPORT_SYMBOL(gameport_open);
void gameport_close(struct gameport *gameport)
{
@@ -824,6 +820,7 @@ void gameport_close(struct gameport *gameport)
if (gameport->close)
gameport->close(gameport);
}
+EXPORT_SYMBOL(gameport_close);
static int __init gameport_init(void)
{
diff --git a/drivers/input/input.c b/drivers/input/input.c
index d44065d2e662..e54e002665b0 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -29,6 +29,23 @@ MODULE_LICENSE("GPL");
#define INPUT_DEVICES 256
+/*
+ * EV_ABS events which should not be cached are listed here.
+ */
+static unsigned int input_abs_bypass_init_data[] __initdata = {
+ ABS_MT_TOUCH_MAJOR,
+ ABS_MT_TOUCH_MINOR,
+ ABS_MT_WIDTH_MAJOR,
+ ABS_MT_WIDTH_MINOR,
+ ABS_MT_ORIENTATION,
+ ABS_MT_POSITION_X,
+ ABS_MT_POSITION_Y,
+ ABS_MT_TOOL_TYPE,
+ ABS_MT_BLOB_ID,
+ 0
+};
+static unsigned long input_abs_bypass[BITS_TO_LONGS(ABS_CNT)];
+
static LIST_HEAD(input_dev_list);
static LIST_HEAD(input_handler_list);
@@ -161,6 +178,10 @@ static void input_handle_event(struct input_dev *dev,
disposition = INPUT_PASS_TO_HANDLERS;
}
break;
+ case SYN_MT_REPORT:
+ dev->sync = 0;
+ disposition = INPUT_PASS_TO_HANDLERS;
+ break;
}
break;
@@ -192,6 +213,11 @@ static void input_handle_event(struct input_dev *dev,
case EV_ABS:
if (is_event_supported(code, dev->absbit, ABS_MAX)) {
+ if (test_bit(code, input_abs_bypass)) {
+ disposition = INPUT_PASS_TO_HANDLERS;
+ break;
+ }
+
value = input_defuzz_abs_event(value,
dev->abs[code], dev->absfuzz[code]);
@@ -1549,7 +1575,6 @@ int input_register_handle(struct input_handle *handle)
return error;
list_add_tail_rcu(&handle->d_node, &dev->h_list);
mutex_unlock(&dev->mutex);
- synchronize_rcu();
/*
* Since we are supposed to be called from ->connect()
@@ -1635,10 +1660,20 @@ static const struct file_operations input_fops = {
.open = input_open_file,
};
+static void __init input_init_abs_bypass(void)
+{
+ const unsigned int *p;
+
+ for (p = input_abs_bypass_init_data; *p; p++)
+ input_abs_bypass[BIT_WORD(*p)] |= BIT_MASK(*p);
+}
+
static int __init input_init(void)
{
int err;
+ input_init_abs_bypass();
+
err = class_register(&input_class);
if (err) {
printk(KERN_ERR "input: unable to register input_dev class\n");
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 4224f0112849..0e12f89276a3 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -39,7 +39,6 @@ struct joydev {
int exist;
int open;
int minor;
- char name[16];
struct input_handle handle;
wait_queue_head_t wait;
struct list_head client_list;
@@ -537,12 +536,14 @@ static int joydev_ioctl_common(struct joydev *joydev,
default:
if ((cmd & ~IOCSIZE_MASK) == JSIOCGNAME(0)) {
int len;
- if (!dev->name)
+ const char *name = dev_name(&dev->dev);
+
+ if (!name)
return 0;
- len = strlen(dev->name) + 1;
+ len = strlen(name) + 1;
if (len > _IOC_SIZE(cmd))
len = _IOC_SIZE(cmd);
- if (copy_to_user(argp, dev->name, len))
+ if (copy_to_user(argp, name, len))
return -EFAULT;
return len;
}
@@ -742,13 +743,13 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
mutex_init(&joydev->mutex);
init_waitqueue_head(&joydev->wait);
- snprintf(joydev->name, sizeof(joydev->name), "js%d", minor);
+ dev_set_name(&joydev->dev, "js%d", minor);
joydev->exist = 1;
joydev->minor = minor;
joydev->exist = 1;
joydev->handle.dev = input_get_device(dev);
- joydev->handle.name = joydev->name;
+ joydev->handle.name = dev_name(&joydev->dev);
joydev->handle.handler = handler;
joydev->handle.private = joydev;
@@ -797,7 +798,6 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
}
}
- dev_set_name(&joydev->dev, joydev->name);
joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor);
joydev->dev.class = &input_class;
joydev->dev.parent = &dev->dev;
@@ -843,7 +843,13 @@ static const struct input_device_id joydev_blacklist[] = {
INPUT_DEVICE_ID_MATCH_KEYBIT,
.evbit = { BIT_MASK(EV_KEY) },
.keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) },
- }, /* Avoid itouchpads, touchscreens and tablets */
+ }, /* Avoid itouchpads and touchscreens */
+ {
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
+ INPUT_DEVICE_ID_MATCH_KEYBIT,
+ .evbit = { BIT_MASK(EV_KEY) },
+ .keybit = { [BIT_WORD(BTN_DIGI)] = BIT_MASK(BTN_DIGI) },
+ }, /* Avoid tablets, digitisers and similar devices */
{ } /* Terminating entry */
};
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index ea2638b41982..54775aaa7be7 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -332,4 +332,14 @@ config KEYBOARD_SH_KEYSC
To compile this driver as a module, choose M here: the
module will be called sh_keysc.
++
+config KEYBOARD_EP93XX
+ tristate "EP93xx Matrix Keypad support"
+ depends on ARCH_EP93XX
+ help
+ Say Y here to enable the matrix keypad on the Cirrus EP93XX.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ep93xx_keypad.
+
endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 36351e1190f9..13ba9c954938 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -28,3 +28,4 @@ obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o
obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o
obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o
+obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index f999dc60c3b8..df3f8aa68115 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -880,7 +880,7 @@ static unsigned int atkbd_hp_zv6100_forced_release_keys[] = {
};
/*
- * Samsung NC10 with Fn+F? key release not working
+ * Samsung NC10,NC20 with Fn+F? key release not working
*/
static unsigned int atkbd_samsung_forced_release_keys[] = {
0x82, 0x83, 0x84, 0x86, 0x88, 0x89, 0xb3, 0xf7, 0xf9, -1U
@@ -895,6 +895,13 @@ static unsigned int atkbd_amilo_pa1510_forced_release_keys[] = {
};
/*
+ * Amilo Xi 3650 key release for light touch bar not working
+ */
+static unsigned int atkbd_amilo_xi3650_forced_release_keys[] = {
+ 0x67, 0xed, 0x90, 0xa2, 0x99, 0xa4, 0xae, 0xb0, -1U
+};
+
+/*
* atkbd_set_keycode_table() initializes keyboard's keycode table
* according to the selected scancode set
*/
@@ -1534,6 +1541,24 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.driver_data = atkbd_samsung_forced_release_keys,
},
{
+ .ident = "Samsung NC20",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "NC20"),
+ },
+ .callback = atkbd_setup_forced_release,
+ .driver_data = atkbd_samsung_forced_release_keys,
+ },
+ {
+ .ident = "Samsung SQ45S70S",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "SQ45S70S"),
+ },
+ .callback = atkbd_setup_forced_release,
+ .driver_data = atkbd_samsung_forced_release_keys,
+ },
+ {
.ident = "Fujitsu Amilo PA 1510",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
@@ -1542,6 +1567,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.callback = atkbd_setup_forced_release,
.driver_data = atkbd_amilo_pa1510_forced_release_keys,
},
+ {
+ .ident = "Fujitsu Amilo Xi 3650",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 3650"),
+ },
+ .callback = atkbd_setup_forced_release,
+ .driver_data = atkbd_amilo_xi3650_forced_release_keys,
+ },
{ }
};
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c
index e94b7d735aca..d427f322e207 100644
--- a/drivers/input/keyboard/bf54x-keys.c
+++ b/drivers/input/keyboard/bf54x-keys.c
@@ -252,7 +252,7 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev)
}
error = request_irq(bf54x_kpad->irq, bfin_kpad_isr,
- IRQF_SAMPLE_RANDOM, DRV_NAME, pdev);
+ 0, DRV_NAME, pdev);
if (error) {
printk(KERN_ERR DRV_NAME
": unable to claim irq %d; error %d\n",
diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c
new file mode 100644
index 000000000000..181d30e3018e
--- /dev/null
+++ b/drivers/input/keyboard/ep93xx_keypad.c
@@ -0,0 +1,470 @@
+/*
+ * Driver for the Cirrus EP93xx matrix keypad controller.
+ *
+ * Copyright (c) 2008 H Hartley Sweeten <hsweeten@visionengravers.com>
+ *
+ * Based on the pxa27x matrix keypad controller by Rodolfo Giometti.
+ *
+ * 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.
+ *
+ * NOTE:
+ *
+ * The 3-key reset is triggered by pressing the 3 keys in
+ * Row 0, Columns 2, 4, and 7 at the same time. This action can
+ * be disabled by setting the EP93XX_KEYPAD_DISABLE_3_KEY flag.
+ *
+ * Normal operation for the matrix does not autorepeat the key press.
+ * This action can be enabled by setting the EP93XX_KEYPAD_AUTOREPEAT
+ * flag.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/clk.h>
+
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/ep93xx_keypad.h>
+
+/*
+ * Keypad Interface Register offsets
+ */
+#define KEY_INIT 0x00 /* Key Scan Initialization register */
+#define KEY_DIAG 0x04 /* Key Scan Diagnostic register */
+#define KEY_REG 0x08 /* Key Value Capture register */
+
+/* Key Scan Initialization Register bit defines */
+#define KEY_INIT_DBNC_MASK (0x00ff0000)
+#define KEY_INIT_DBNC_SHIFT (16)
+#define KEY_INIT_DIS3KY (1<<15)
+#define KEY_INIT_DIAG (1<<14)
+#define KEY_INIT_BACK (1<<13)
+#define KEY_INIT_T2 (1<<12)
+#define KEY_INIT_PRSCL_MASK (0x000003ff)
+#define KEY_INIT_PRSCL_SHIFT (0)
+
+/* Key Scan Diagnostic Register bit defines */
+#define KEY_DIAG_MASK (0x0000003f)
+#define KEY_DIAG_SHIFT (0)
+
+/* Key Value Capture Register bit defines */
+#define KEY_REG_K (1<<15)
+#define KEY_REG_INT (1<<14)
+#define KEY_REG_2KEYS (1<<13)
+#define KEY_REG_1KEY (1<<12)
+#define KEY_REG_KEY2_MASK (0x00000fc0)
+#define KEY_REG_KEY2_SHIFT (6)
+#define KEY_REG_KEY1_MASK (0x0000003f)
+#define KEY_REG_KEY1_SHIFT (0)
+
+#define keypad_readl(off) __raw_readl(keypad->mmio_base + (off))
+#define keypad_writel(v, off) __raw_writel((v), keypad->mmio_base + (off))
+
+#define MAX_MATRIX_KEY_NUM (MAX_MATRIX_KEY_ROWS * MAX_MATRIX_KEY_COLS)
+
+struct ep93xx_keypad {
+ struct ep93xx_keypad_platform_data *pdata;
+
+ struct clk *clk;
+ struct input_dev *input_dev;
+ void __iomem *mmio_base;
+
+ int irq;
+ int enabled;
+
+ int key1;
+ int key2;
+
+ unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM];
+};
+
+static void ep93xx_keypad_build_keycode(struct ep93xx_keypad *keypad)
+{
+ struct ep93xx_keypad_platform_data *pdata = keypad->pdata;
+ struct input_dev *input_dev = keypad->input_dev;
+ int i;
+
+ for (i = 0; i < pdata->matrix_key_map_size; i++) {
+ unsigned int key = pdata->matrix_key_map[i];
+ int row = (key >> 28) & 0xf;
+ int col = (key >> 24) & 0xf;
+ int code = key & 0xffffff;
+
+ keypad->matrix_keycodes[(row << 3) + col] = code;
+ __set_bit(code, input_dev->keybit);
+ }
+}
+
+static irqreturn_t ep93xx_keypad_irq_handler(int irq, void *dev_id)
+{
+ struct ep93xx_keypad *keypad = dev_id;
+ struct input_dev *input_dev = keypad->input_dev;
+ unsigned int status = keypad_readl(KEY_REG);
+ int keycode, key1, key2;
+
+ keycode = (status & KEY_REG_KEY1_MASK) >> KEY_REG_KEY1_SHIFT;
+ key1 = keypad->matrix_keycodes[keycode];
+
+ keycode = (status & KEY_REG_KEY2_MASK) >> KEY_REG_KEY2_SHIFT;
+ key2 = keypad->matrix_keycodes[keycode];
+
+ if (status & KEY_REG_2KEYS) {
+ if (keypad->key1 && key1 != keypad->key1 && key2 != keypad->key1)
+ input_report_key(input_dev, keypad->key1, 0);
+
+ if (keypad->key2 && key1 != keypad->key2 && key2 != keypad->key2)
+ input_report_key(input_dev, keypad->key2, 0);
+
+ input_report_key(input_dev, key1, 1);
+ input_report_key(input_dev, key2, 1);
+
+ keypad->key1 = key1;
+ keypad->key2 = key2;
+
+ } else if (status & KEY_REG_1KEY) {
+ if (keypad->key1 && key1 != keypad->key1)
+ input_report_key(input_dev, keypad->key1, 0);
+
+ if (keypad->key2 && key1 != keypad->key2)
+ input_report_key(input_dev, keypad->key2, 0);
+
+ input_report_key(input_dev, key1, 1);
+
+ keypad->key1 = key1;
+ keypad->key2 = 0;
+
+ } else {
+ input_report_key(input_dev, keypad->key1, 0);
+ input_report_key(input_dev, keypad->key2, 0);
+
+ keypad->key1 = keypad->key2 = 0;
+ }
+ input_sync(input_dev);
+
+ return IRQ_HANDLED;
+}
+
+static void ep93xx_keypad_config(struct ep93xx_keypad *keypad)
+{
+ struct ep93xx_keypad_platform_data *pdata = keypad->pdata;
+ unsigned int val = 0;
+
+ clk_set_rate(keypad->clk, pdata->flags & EP93XX_KEYPAD_KDIV);
+
+ if (pdata->flags & EP93XX_KEYPAD_DISABLE_3_KEY)
+ val |= KEY_INIT_DIS3KY;
+ if (pdata->flags & EP93XX_KEYPAD_DIAG_MODE)
+ val |= KEY_INIT_DIAG;
+ if (pdata->flags & EP93XX_KEYPAD_BACK_DRIVE)
+ val |= KEY_INIT_BACK;
+ if (pdata->flags & EP93XX_KEYPAD_TEST_MODE)
+ val |= KEY_INIT_T2;
+
+ val |= ((pdata->debounce << KEY_INIT_DBNC_SHIFT) & KEY_INIT_DBNC_MASK);
+
+ val |= ((pdata->prescale << KEY_INIT_PRSCL_SHIFT) & KEY_INIT_PRSCL_MASK);
+
+ keypad_writel(val, KEY_INIT);
+}
+
+static int ep93xx_keypad_open(struct input_dev *pdev)
+{
+ struct ep93xx_keypad *keypad = input_get_drvdata(pdev);
+
+ if (!keypad->enabled) {
+ ep93xx_keypad_config(keypad);
+ clk_enable(keypad->clk);
+ keypad->enabled = 1;
+ }
+
+ return 0;
+}
+
+static void ep93xx_keypad_close(struct input_dev *pdev)
+{
+ struct ep93xx_keypad *keypad = input_get_drvdata(pdev);
+
+ if (keypad->enabled) {
+ clk_disable(keypad->clk);
+ keypad->enabled = 0;
+ }
+}
+
+
+#ifdef CONFIG_PM
+/*
+ * NOTE: I don't know if this is correct, or will work on the ep93xx.
+ *
+ * None of the existing ep93xx drivers have power management support.
+ * But, this is basically what the pxa27x_keypad driver does.
+ */
+static int ep93xx_keypad_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
+ struct input_dev *input_dev = keypad->input_dev;
+
+ mutex_lock(&input_dev->mutex);
+
+ if (keypad->enabled) {
+ clk_disable(keypad->clk);
+ keypad->enabled = 0;
+ }
+
+ mutex_unlock(&input_dev->mutex);
+
+ if (device_may_wakeup(&pdev->dev))
+ enable_irq_wake(keypad->irq);
+
+ return 0;
+}
+
+static int ep93xx_keypad_resume(struct platform_device *pdev)
+{
+ struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
+ struct input_dev *input_dev = keypad->input_dev;
+
+ if (device_may_wakeup(&pdev->dev))
+ disable_irq_wake(keypad->irq);
+
+ mutex_lock(&input_dev->mutex);
+
+ if (input_dev->users) {
+ if (!keypad->enabled) {
+ ep93xx_keypad_config(keypad);
+ clk_enable(keypad->clk);
+ keypad->enabled = 1;
+ }
+ }
+
+ mutex_unlock(&input_dev->mutex);
+
+ return 0;
+}
+#else /* !CONFIG_PM */
+#define ep93xx_keypad_suspend NULL
+#define ep93xx_keypad_resume NULL
+#endif /* !CONFIG_PM */
+
+static int __devinit ep93xx_keypad_probe(struct platform_device *pdev)
+{
+ struct ep93xx_keypad *keypad;
+ struct ep93xx_keypad_platform_data *pdata = pdev->dev.platform_data;
+ struct input_dev *input_dev;
+ struct resource *res;
+ int irq, err, i, gpio;
+
+ if (!pdata ||
+ !pdata->matrix_key_rows ||
+ pdata->matrix_key_rows > MAX_MATRIX_KEY_ROWS ||
+ !pdata->matrix_key_cols ||
+ pdata->matrix_key_cols > MAX_MATRIX_KEY_COLS) {
+ dev_err(&pdev->dev, "invalid or missing platform data\n");
+ return -EINVAL;
+ }
+
+ keypad = kzalloc(sizeof(struct ep93xx_keypad), GFP_KERNEL);
+ if (!keypad) {
+ dev_err(&pdev->dev, "failed to allocate driver data\n");
+ return -ENOMEM;
+ }
+
+ keypad->pdata = pdata;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "failed to get keypad irq\n");
+ err = -ENXIO;
+ goto failed_free;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "failed to get I/O memory\n");
+ err = -ENXIO;
+ goto failed_free;
+ }
+
+ res = request_mem_region(res->start, resource_size(res), pdev->name);
+ if (!res) {
+ dev_err(&pdev->dev, "failed to request I/O memory\n");
+ err = -EBUSY;
+ goto failed_free;
+ }
+
+ keypad->mmio_base = ioremap(res->start, resource_size(res));
+ if (keypad->mmio_base == NULL) {
+ dev_err(&pdev->dev, "failed to remap I/O memory\n");
+ err = -ENXIO;
+ goto failed_free_mem;
+ }
+
+ /* Request the needed GPIO's */
+ gpio = EP93XX_GPIO_LINE_ROW0;
+ for (i = 0; i < keypad->pdata->matrix_key_rows; i++, gpio++) {
+ err = gpio_request(gpio, pdev->name);
+ if (err) {
+ dev_err(&pdev->dev, "failed to request gpio-%d\n",
+ gpio);
+ goto failed_free_rows;
+ }
+ }
+
+ gpio = EP93XX_GPIO_LINE_COL0;
+ for (i = 0; i < keypad->pdata->matrix_key_cols; i++, gpio++) {
+ err = gpio_request(gpio, pdev->name);
+ if (err) {
+ dev_err(&pdev->dev, "failed to request gpio-%d\n",
+ gpio);
+ goto failed_free_cols;
+ }
+ }
+
+ keypad->clk = clk_get(&pdev->dev, "key_clk");
+ if (IS_ERR(keypad->clk)) {
+ dev_err(&pdev->dev, "failed to get keypad clock\n");
+ err = PTR_ERR(keypad->clk);
+ goto failed_free_io;
+ }
+
+ /* Create and register the input driver */
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ dev_err(&pdev->dev, "failed to allocate input device\n");
+ err = -ENOMEM;
+ goto failed_put_clk;
+ }
+
+ keypad->input_dev = input_dev;
+
+ input_dev->name = pdev->name;
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->open = ep93xx_keypad_open;
+ input_dev->close = ep93xx_keypad_close;
+ input_dev->dev.parent = &pdev->dev;
+ input_dev->keycode = keypad->matrix_keycodes;
+ input_dev->keycodesize = sizeof(keypad->matrix_keycodes[0]);
+ input_dev->keycodemax = ARRAY_SIZE(keypad->matrix_keycodes);
+
+ input_set_drvdata(input_dev, keypad);
+
+ input_dev->evbit[0] = BIT_MASK(EV_KEY);
+ if (keypad->pdata->flags & EP93XX_KEYPAD_AUTOREPEAT)
+ input_dev->evbit[0] |= BIT_MASK(EV_REP);
+
+ ep93xx_keypad_build_keycode(keypad);
+ platform_set_drvdata(pdev, keypad);
+
+ err = request_irq(irq, ep93xx_keypad_irq_handler, IRQF_DISABLED,
+ pdev->name, keypad);
+ if (err) {
+ dev_err(&pdev->dev, "failed to request IRQ\n");
+ goto failed_free_dev;
+ }
+
+ keypad->irq = irq;
+
+ /* Register the input device */
+ err = input_register_device(input_dev);
+ if (err) {
+ dev_err(&pdev->dev, "failed to register input device\n");
+ goto failed_free_irq;
+ }
+
+ device_init_wakeup(&pdev->dev, 1);
+
+ return 0;
+
+failed_free_irq:
+ free_irq(irq, pdev);
+ platform_set_drvdata(pdev, NULL);
+failed_free_dev:
+ input_free_device(input_dev);
+failed_put_clk:
+ clk_put(keypad->clk);
+failed_free_io:
+ i = keypad->pdata->matrix_key_cols - 1;
+ gpio = EP93XX_GPIO_LINE_COL0 + i;
+failed_free_cols:
+ for ( ; i >= 0; i--, gpio--)
+ gpio_free(gpio);
+ i = keypad->pdata->matrix_key_rows - 1;
+ gpio = EP93XX_GPIO_LINE_ROW0 + i;
+failed_free_rows:
+ for ( ; i >= 0; i--, gpio--)
+ gpio_free(gpio);
+ iounmap(keypad->mmio_base);
+failed_free_mem:
+ release_mem_region(res->start, resource_size(res));
+failed_free:
+ kfree(keypad);
+ return err;
+}
+
+static int __devexit ep93xx_keypad_remove(struct platform_device *pdev)
+{
+ struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
+ struct resource *res;
+ int i, gpio;
+
+ free_irq(keypad->irq, pdev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ if (keypad->enabled)
+ clk_disable(keypad->clk);
+ clk_put(keypad->clk);
+
+ input_unregister_device(keypad->input_dev);
+
+ i = keypad->pdata->matrix_key_cols - 1;
+ gpio = EP93XX_GPIO_LINE_COL0 + i;
+ for ( ; i >= 0; i--, gpio--)
+ gpio_free(gpio);
+
+ i = keypad->pdata->matrix_key_rows - 1;
+ gpio = EP93XX_GPIO_LINE_ROW0 + i;
+ for ( ; i >= 0; i--, gpio--)
+ gpio_free(gpio);
+
+ iounmap(keypad->mmio_base);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, resource_size(res));
+
+ kfree(keypad);
+
+ return 0;
+}
+
+static struct platform_driver ep93xx_keypad_driver = {
+ .driver = {
+ .name = "ep93xx-keypad",
+ .owner = THIS_MODULE,
+ },
+ .probe = ep93xx_keypad_probe,
+ .remove = __devexit_p(ep93xx_keypad_remove),
+ .suspend = ep93xx_keypad_suspend,
+ .resume = ep93xx_keypad_resume,
+};
+
+static int __init ep93xx_keypad_init(void)
+{
+ return platform_driver_register(&ep93xx_keypad_driver);
+}
+
+static void __exit ep93xx_keypad_exit(void)
+{
+ platform_driver_unregister(&ep93xx_keypad_driver);
+}
+
+module_init(ep93xx_keypad_init);
+module_exit(ep93xx_keypad_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
+MODULE_DESCRIPTION("EP93xx Matrix Keypad Controller");
+MODULE_ALIAS("platform:ep93xx-keypad");
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index ad67d763fdbd..9767213b6c8f 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -142,8 +142,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
}
error = request_irq(irq, gpio_keys_isr,
- IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING |
- IRQF_TRIGGER_FALLING,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
button->desc ? button->desc : "gpio_keys",
bdata);
if (error) {
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
index 058fa8b02c21..87ec7b18ac69 100644
--- a/drivers/input/keyboard/omap-keypad.c
+++ b/drivers/input/keyboard/omap-keypad.c
@@ -100,8 +100,20 @@ static irqreturn_t omap_kp_interrupt(int irq, void *dev_id)
/* disable keyboard interrupt and schedule for handling */
if (cpu_is_omap24xx()) {
int i;
- for (i = 0; i < omap_kp->rows; i++)
- disable_irq(gpio_to_irq(row_gpios[i]));
+
+ for (i = 0; i < omap_kp->rows; i++) {
+ int gpio_irq = gpio_to_irq(row_gpios[i]);
+ /*
+ * The interrupt which we're currently handling should
+ * be disabled _nosync() to avoid deadlocks waiting
+ * for this handler to complete. All others should
+ * be disabled the regular way for SMP safety.
+ */
+ if (gpio_irq == irq)
+ disable_irq_nosync(gpio_irq);
+ else
+ disable_irq(gpio_irq);
+ }
} else
/* disable keyboard interrupt and schedule for handling */
omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 203abac1e23e..4399f54c043c 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -193,6 +193,16 @@ config INPUT_CM109
To compile this driver as a module, choose M here: the module will be
called cm109.
+config INPUT_TWL4030_PWRBUTTON
+ tristate "TWL4030 Power button Driver"
+ depends on TWL4030_CORE
+ help
+ Say Y here if you want to enable power key reporting via the
+ TWL4030 family of chips.
+
+ To compile this driver as a module, choose M here. The module will
+ be called twl4030_pwrbutton.
+
config INPUT_UINPUT
tristate "User level driver support"
help
@@ -214,7 +224,7 @@ config INPUT_SGI_BTNS
config HP_SDC_RTC
tristate "HP SDC Real Time Clock"
- depends on GSC || HP300
+ depends on (GSC || HP300) && SERIO
select HP_SDC
help
Say Y here if you want to support the built-in real time clock
@@ -250,4 +260,13 @@ config INPUT_RB532_BUTTON
To compile this driver as a module, choose M here: the
module will be called rb532_button.
+config INPUT_DM355EVM
+ tristate "TI DaVinci DM355 EVM Keypad and IR Remote"
+ depends on MFD_DM355EVM_MSP
+ help
+ Supports the pushbuttons and IR remote used with
+ the DM355 EVM board.
+
+ To compile this driver as a module, choose M here: the
+ module will be called dm355evm_keys.
endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index eb3f407baedf..0d979fd4cd57 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o
obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o
obj-$(CONFIG_INPUT_CM109) += cm109.o
obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o
+obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o
obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o
obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o
@@ -21,6 +22,7 @@ obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o
obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o
obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o
+obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o
obj-$(CONFIG_INPUT_YEALINK) += yealink.o
diff --git a/drivers/input/misc/dm355evm_keys.c b/drivers/input/misc/dm355evm_keys.c
new file mode 100644
index 000000000000..a63315ce4a6c
--- /dev/null
+++ b/drivers/input/misc/dm355evm_keys.c
@@ -0,0 +1,329 @@
+/*
+ * dm355evm_keys.c - support buttons and IR remote on DM355 EVM board
+ *
+ * Copyright (c) 2008 by David Brownell
+ *
+ * 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/input.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+
+#include <linux/i2c/dm355evm_msp.h>
+
+
+/*
+ * The MSP430 firmware on the DM355 EVM monitors on-board pushbuttons
+ * and an IR receptor used for the remote control. When any key is
+ * pressed, or its autorepeat kicks in, an event is sent. This driver
+ * read those events from the small (32 event) queue and reports them.
+ *
+ * Because we communicate with the MSP430 using I2C, and all I2C calls
+ * in Linux sleep, we need to cons up a kind of threaded IRQ handler
+ * using a work_struct. The IRQ is active low, but we use it through
+ * the GPIO controller so we can trigger on falling edges.
+ *
+ * Note that physically there can only be one of these devices.
+ *
+ * This driver was tested with firmware revision A4.
+ */
+struct dm355evm_keys {
+ struct work_struct work;
+ struct input_dev *input;
+ struct device *dev;
+ int irq;
+};
+
+static irqreturn_t dm355evm_keys_irq(int irq, void *_keys)
+{
+ struct dm355evm_keys *keys = _keys;
+
+ schedule_work(&keys->work);
+ return IRQ_HANDLED;
+}
+
+/* These initial keycodes can be remapped by dm355evm_setkeycode(). */
+static struct {
+ u16 event;
+ u16 keycode;
+} dm355evm_keys[] = {
+
+ /*
+ * Pushbuttons on the EVM board ... note that the labels for these
+ * are SW10/SW11/etc on the PC board. The left/right orientation
+ * comes only from the firmware's documentation, and presumes the
+ * power connector is immediately in front of you and the IR sensor
+ * is to the right. (That is, rotate the board counter-clockwise
+ * by 90 degrees from the SW10/etc and "DM355 EVM" labels.)
+ */
+ { 0x00d8, KEY_OK, }, /* SW12 */
+ { 0x00b8, KEY_UP, }, /* SW13 */
+ { 0x00e8, KEY_DOWN, }, /* SW11 */
+ { 0x0078, KEY_LEFT, }, /* SW14 */
+ { 0x00f0, KEY_RIGHT, }, /* SW10 */
+
+ /*
+ * IR buttons ... codes assigned to match the universal remote
+ * provided with the EVM (Philips PM4S) using DVD code 0020.
+ *
+ * These event codes match firmware documentation, but other
+ * remote controls could easily send more RC5-encoded events.
+ * The PM4S manual was used in several cases to help select
+ * a keycode reflecting the intended usage.
+ *
+ * RC5 codes are 14 bits, with two start bits (0x3 prefix)
+ * and a toggle bit (masked out below).
+ */
+ { 0x300c, KEY_POWER, }, /* NOTE: docs omit this */
+ { 0x3000, KEY_NUMERIC_0, },
+ { 0x3001, KEY_NUMERIC_1, },
+ { 0x3002, KEY_NUMERIC_2, },
+ { 0x3003, KEY_NUMERIC_3, },
+ { 0x3004, KEY_NUMERIC_4, },
+ { 0x3005, KEY_NUMERIC_5, },
+ { 0x3006, KEY_NUMERIC_6, },
+ { 0x3007, KEY_NUMERIC_7, },
+ { 0x3008, KEY_NUMERIC_8, },
+ { 0x3009, KEY_NUMERIC_9, },
+ { 0x3022, KEY_ENTER, },
+ { 0x30ec, KEY_MODE, }, /* "tv/vcr/..." */
+ { 0x300f, KEY_SELECT, }, /* "info" */
+ { 0x3020, KEY_CHANNELUP, }, /* "up" */
+ { 0x302e, KEY_MENU, }, /* "in/out" */
+ { 0x3011, KEY_VOLUMEDOWN, }, /* "left" */
+ { 0x300d, KEY_MUTE, }, /* "ok" */
+ { 0x3010, KEY_VOLUMEUP, }, /* "right" */
+ { 0x301e, KEY_SUBTITLE, }, /* "cc" */
+ { 0x3021, KEY_CHANNELDOWN, }, /* "down" */
+ { 0x3022, KEY_PREVIOUS, },
+ { 0x3026, KEY_SLEEP, },
+ { 0x3172, KEY_REWIND, }, /* NOTE: docs wrongly say 0x30ca */
+ { 0x3175, KEY_PLAY, },
+ { 0x3174, KEY_FASTFORWARD, },
+ { 0x3177, KEY_RECORD, },
+ { 0x3176, KEY_STOP, },
+ { 0x3169, KEY_PAUSE, },
+};
+
+static void dm355evm_keys_work(struct work_struct *work)
+{
+ struct dm355evm_keys *keys;
+ int status;
+
+ keys = container_of(work, struct dm355evm_keys, work);
+
+ /* For simplicity we ignore INPUT_COUNT and just read
+ * events until we get the "queue empty" indicator.
+ * Reading INPUT_LOW decrements the count.
+ */
+ for (;;) {
+ static u16 last_event;
+ u16 event;
+ int keycode;
+ int i;
+
+ status = dm355evm_msp_read(DM355EVM_MSP_INPUT_HIGH);
+ if (status < 0) {
+ dev_dbg(keys->dev, "input high err %d\n",
+ status);
+ break;
+ }
+ event = status << 8;
+
+ status = dm355evm_msp_read(DM355EVM_MSP_INPUT_LOW);
+ if (status < 0) {
+ dev_dbg(keys->dev, "input low err %d\n",
+ status);
+ break;
+ }
+ event |= status;
+ if (event == 0xdead)
+ break;
+
+ /* Press and release a button: two events, same code.
+ * Press and hold (autorepeat), then release: N events
+ * (N > 2), same code. For RC5 buttons the toggle bits
+ * distinguish (for example) "1-autorepeat" from "1 1";
+ * but PCB buttons don't support that bit.
+ *
+ * So we must synthesize release events. We do that by
+ * mapping events to a press/release event pair; then
+ * to avoid adding extra events, skip the second event
+ * of each pair.
+ */
+ if (event == last_event) {
+ last_event = 0;
+ continue;
+ }
+ last_event = event;
+
+ /* ignore the RC5 toggle bit */
+ event &= ~0x0800;
+
+ /* find the key, or leave it as unknown */
+ keycode = KEY_UNKNOWN;
+ for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++) {
+ if (dm355evm_keys[i].event != event)
+ continue;
+ keycode = dm355evm_keys[i].keycode;
+ break;
+ }
+ dev_dbg(keys->dev,
+ "input event 0x%04x--> keycode %d\n",
+ event, keycode);
+
+ /* report press + release */
+ input_report_key(keys->input, keycode, 1);
+ input_sync(keys->input);
+ input_report_key(keys->input, keycode, 0);
+ input_sync(keys->input);
+ }
+}
+
+static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode)
+{
+ u16 old_keycode;
+ unsigned i;
+
+ if (((unsigned)index) >= ARRAY_SIZE(dm355evm_keys))
+ return -EINVAL;
+
+ old_keycode = dm355evm_keys[index].keycode;
+ dm355evm_keys[index].keycode = keycode;
+ set_bit(keycode, dev->keybit);
+
+ for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++) {
+ if (dm355evm_keys[index].keycode == old_keycode)
+ goto done;
+ }
+ clear_bit(old_keycode, dev->keybit);
+done:
+ return 0;
+}
+
+static int dm355evm_getkeycode(struct input_dev *dev, int index, int *keycode)
+{
+ if (((unsigned)index) >= ARRAY_SIZE(dm355evm_keys))
+ return -EINVAL;
+
+ return dm355evm_keys[index].keycode;
+}
+
+/*----------------------------------------------------------------------*/
+
+static int __devinit dm355evm_keys_probe(struct platform_device *pdev)
+{
+ struct dm355evm_keys *keys;
+ struct input_dev *input;
+ int status;
+ int i;
+
+ /* allocate instance struct and input dev */
+ keys = kzalloc(sizeof *keys, GFP_KERNEL);
+ input = input_allocate_device();
+ if (!keys || !input) {
+ status = -ENOMEM;
+ goto fail1;
+ }
+
+ keys->dev = &pdev->dev;
+ keys->input = input;
+ INIT_WORK(&keys->work, dm355evm_keys_work);
+
+ /* set up "threaded IRQ handler" */
+ status = platform_get_irq(pdev, 0);
+ if (status < 0)
+ goto fail1;
+ keys->irq = status;
+
+ input_set_drvdata(input, keys);
+
+ input->name = "DM355 EVM Controls";
+ input->phys = "dm355evm/input0";
+ input->dev.parent = &pdev->dev;
+
+ input->id.bustype = BUS_I2C;
+ input->id.product = 0x0355;
+ input->id.version = dm355evm_msp_read(DM355EVM_MSP_FIRMREV);
+
+ input->evbit[0] = BIT(EV_KEY);
+ for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++)
+ __set_bit(dm355evm_keys[i].keycode, input->keybit);
+
+ input->setkeycode = dm355evm_setkeycode;
+ input->getkeycode = dm355evm_getkeycode;
+
+ /* REVISIT: flush the event queue? */
+
+ status = request_irq(keys->irq, dm355evm_keys_irq,
+ IRQF_TRIGGER_FALLING,
+ dev_name(&pdev->dev), keys);
+ if (status < 0)
+ goto fail1;
+
+ /* register */
+ status = input_register_device(input);
+ if (status < 0)
+ goto fail2;
+
+ platform_set_drvdata(pdev, keys);
+
+ return 0;
+
+fail2:
+ free_irq(keys->irq, keys);
+fail1:
+ input_free_device(input);
+ kfree(keys);
+ dev_err(&pdev->dev, "can't register, err %d\n", status);
+
+ return status;
+}
+
+static int __devexit dm355evm_keys_remove(struct platform_device *pdev)
+{
+ struct dm355evm_keys *keys = platform_get_drvdata(pdev);
+
+ free_irq(keys->irq, keys);
+ input_unregister_device(keys->input);
+ kfree(keys);
+
+ return 0;
+}
+
+/* REVISIT: add suspend/resume when DaVinci supports it. The IRQ should
+ * be able to wake up the system. When device_may_wakeup(&pdev->dev), call
+ * enable_irq_wake() on suspend, and disable_irq_wake() on resume.
+ */
+
+/*
+ * I2C is used to talk to the MSP430, but this platform device is
+ * exposed by an MFD driver that manages I2C communications.
+ */
+static struct platform_driver dm355evm_keys_driver = {
+ .probe = dm355evm_keys_probe,
+ .remove = __devexit_p(dm355evm_keys_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "dm355evm_keys",
+ },
+};
+
+static int __init dm355evm_keys_init(void)
+{
+ return platform_driver_register(&dm355evm_keys_driver);
+}
+module_init(dm355evm_keys_init);
+
+static void __exit dm355evm_keys_exit(void)
+{
+ platform_driver_unregister(&dm355evm_keys_driver);
+}
+module_exit(dm355evm_keys_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
index 5bb3ab51b8c6..c806fbf1e174 100644
--- a/drivers/input/misc/rotary_encoder.c
+++ b/drivers/input/misc/rotary_encoder.c
@@ -26,13 +26,17 @@
#define DRV_NAME "rotary-encoder"
struct rotary_encoder {
- unsigned int irq_a;
- unsigned int irq_b;
- unsigned int pos;
- unsigned int armed;
- unsigned int dir;
struct input_dev *input;
struct rotary_encoder_platform_data *pdata;
+
+ unsigned int axis;
+ unsigned int pos;
+
+ unsigned int irq_a;
+ unsigned int irq_b;
+
+ bool armed;
+ unsigned char dir; /* 0 - clockwise, 1 - CCW */
};
static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
@@ -53,21 +57,32 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
if (!encoder->armed)
break;
- if (encoder->dir) {
- /* turning counter-clockwise */
- encoder->pos += pdata->steps;
- encoder->pos--;
- encoder->pos %= pdata->steps;
+ if (pdata->relative_axis) {
+ input_report_rel(encoder->input, pdata->axis,
+ encoder->dir ? -1 : 1);
} else {
- /* turning clockwise */
- encoder->pos++;
- encoder->pos %= pdata->steps;
+ unsigned int pos = encoder->pos;
+
+ if (encoder->dir) {
+ /* turning counter-clockwise */
+ if (pdata->rollover)
+ pos += pdata->steps;
+ if (pos)
+ pos--;
+ } else {
+ /* turning clockwise */
+ if (pdata->rollover || pos < pdata->steps)
+ pos++;
+ }
+ if (pdata->rollover)
+ pos %= pdata->steps;
+ encoder->pos = pos;
+ input_report_abs(encoder->input, pdata->axis,
+ encoder->pos);
}
-
- input_report_abs(encoder->input, pdata->axis, encoder->pos);
input_sync(encoder->input);
- encoder->armed = 0;
+ encoder->armed = false;
break;
case 0x1:
@@ -77,7 +92,7 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
break;
case 0x3:
- encoder->armed = 1;
+ encoder->armed = true;
break;
}
@@ -113,9 +128,15 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev)
input->name = pdev->name;
input->id.bustype = BUS_HOST;
input->dev.parent = &pdev->dev;
- input->evbit[0] = BIT_MASK(EV_ABS);
- input_set_abs_params(encoder->input,
- pdata->axis, 0, pdata->steps, 0, 1);
+
+ if (pdata->relative_axis) {
+ input->evbit[0] = BIT_MASK(EV_REL);
+ input->relbit[0] = BIT_MASK(pdata->axis);
+ } else {
+ input->evbit[0] = BIT_MASK(EV_ABS);
+ input_set_abs_params(encoder->input,
+ pdata->axis, 0, pdata->steps, 0, 1);
+ }
err = input_register_device(input);
if (err) {
diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c
new file mode 100644
index 000000000000..f5fc9974a111
--- /dev/null
+++ b/drivers/input/misc/twl4030-pwrbutton.c
@@ -0,0 +1,145 @@
+/**
+ * twl4030-pwrbutton.c - TWL4030 Power Button Input Driver
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Written by Peter De Schrijver <peter.de-schrijver@nokia.com>
+ * Several fixes by Felipe Balbi <felipe.balbi@nokia.com>
+ *
+ * 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.
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/twl4030.h>
+
+#define PWR_PWRON_IRQ (1 << 0)
+
+#define STS_HW_CONDITIONS 0xf
+
+static irqreturn_t powerbutton_irq(int irq, void *_pwr)
+{
+ struct input_dev *pwr = _pwr;
+ int err;
+ u8 value;
+
+#ifdef CONFIG_LOCKDEP
+ /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
+ * we don't want and can't tolerate since this is a threaded
+ * IRQ and can sleep due to the i2c reads it has to issue.
+ * Although it might be friendlier not to borrow this thread
+ * context...
+ */
+ local_irq_enable();
+#endif
+
+ err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &value,
+ STS_HW_CONDITIONS);
+ if (!err) {
+ input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ);
+ input_sync(pwr);
+ } else {
+ dev_err(pwr->dev.parent, "twl4030: i2c error %d while reading"
+ " TWL4030 PM_MASTER STS_HW_CONDITIONS register\n", err);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int __devinit twl4030_pwrbutton_probe(struct platform_device *pdev)
+{
+ struct input_dev *pwr;
+ int irq = platform_get_irq(pdev, 0);
+ int err;
+
+ pwr = input_allocate_device();
+ if (!pwr) {
+ dev_dbg(&pdev->dev, "Can't allocate power button\n");
+ return -ENOMEM;
+ }
+
+ pwr->evbit[0] = BIT_MASK(EV_KEY);
+ pwr->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER);
+ pwr->name = "twl4030_pwrbutton";
+ pwr->phys = "twl4030_pwrbutton/input0";
+ pwr->dev.parent = &pdev->dev;
+
+ err = request_irq(irq, powerbutton_irq,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ "twl4030_pwrbutton", pwr);
+ if (err < 0) {
+ dev_dbg(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err);
+ goto free_input_dev;
+ }
+
+ err = input_register_device(pwr);
+ if (err) {
+ dev_dbg(&pdev->dev, "Can't register power button: %d\n", err);
+ goto free_irq;
+ }
+
+ platform_set_drvdata(pdev, pwr);
+
+ return 0;
+
+free_irq:
+ free_irq(irq, NULL);
+free_input_dev:
+ input_free_device(pwr);
+ return err;
+}
+
+static int __devexit twl4030_pwrbutton_remove(struct platform_device *pdev)
+{
+ struct input_dev *pwr = platform_get_drvdata(pdev);
+ int irq = platform_get_irq(pdev, 0);
+
+ free_irq(irq, pwr);
+ input_unregister_device(pwr);
+
+ return 0;
+}
+
+struct platform_driver twl4030_pwrbutton_driver = {
+ .probe = twl4030_pwrbutton_probe,
+ .remove = __devexit_p(twl4030_pwrbutton_remove),
+ .driver = {
+ .name = "twl4030_pwrbutton",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init twl4030_pwrbutton_init(void)
+{
+ return platform_driver_register(&twl4030_pwrbutton_driver);
+}
+module_init(twl4030_pwrbutton_init);
+
+static void __exit twl4030_pwrbutton_exit(void)
+{
+ platform_driver_unregister(&twl4030_pwrbutton_driver);
+}
+module_exit(twl4030_pwrbutton_exit);
+
+MODULE_ALIAS("platform:twl4030_pwrbutton");
+MODULE_DESCRIPTION("Triton2 Power Button");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Peter De Schrijver <peter.de-schrijver@nokia.com>");
+MODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>");
+
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index cbedf957cc58..cd4203c4deb9 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -37,25 +37,26 @@
#define ALPS_FW_BK_2 0x40
static const struct alps_model_info alps_model_data[] = {
- { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */
+ { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */
+ { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */
{ { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
{ { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
- { { 0x60, 0x03, 0xc8 }, 0xf8, 0xf8, 0 }, /* HP ze1115 */
+ { { 0x60, 0x03, 0xc8 }, 0xf8, 0xf8, 0 }, /* HP ze1115 */
{ { 0x63, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
{ { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
- { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */
- { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */
- { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */
+ { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */
+ { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */
+ { { 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 */
+ { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* 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 */
+ { { 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 */
{ { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */
- { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 } /* Dell Vostro 1400 */
+ { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 }, /* Dell Vostro 1400 */
};
/*
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c
index 454b96112f03..e0140fdc02a5 100644
--- a/drivers/input/mouse/appletouch.c
+++ b/drivers/input/mouse/appletouch.c
@@ -255,15 +255,22 @@ MODULE_PARM_DESC(debug, "Activate debugging output");
*/
static int atp_geyser_init(struct usb_device *udev)
{
- char data[8];
+ char *data;
int size;
int i;
+ int ret;
+
+ data = kmalloc(8, GFP_KERNEL);
+ if (!data) {
+ err("Out of memory");
+ return -ENOMEM;
+ }
size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
ATP_GEYSER_MODE_READ_REQUEST_ID,
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
ATP_GEYSER_MODE_REQUEST_VALUE,
- ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000);
+ ATP_GEYSER_MODE_REQUEST_INDEX, data, 8, 5000);
if (size != 8) {
dprintk("atp_geyser_init: read error\n");
@@ -271,7 +278,8 @@ static int atp_geyser_init(struct usb_device *udev)
dprintk("appletouch[%d]: %d\n", i, data[i]);
err("Failed to read mode from device.");
- return -EIO;
+ ret = -EIO;
+ goto out_free;
}
/* Apply the mode switch */
@@ -281,7 +289,7 @@ static int atp_geyser_init(struct usb_device *udev)
ATP_GEYSER_MODE_WRITE_REQUEST_ID,
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
ATP_GEYSER_MODE_REQUEST_VALUE,
- ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000);
+ ATP_GEYSER_MODE_REQUEST_INDEX, data, 8, 5000);
if (size != 8) {
dprintk("atp_geyser_init: write error\n");
@@ -289,9 +297,13 @@ static int atp_geyser_init(struct usb_device *udev)
dprintk("appletouch[%d]: %d\n", i, data[i]);
err("Failed to request geyser raw mode");
- return -EIO;
+ ret = -EIO;
+ goto out_free;
}
- return 0;
+ ret = 0;
+out_free:
+ kfree(data);
+ return ret;
}
/*
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
index 2998a6ac9ae4..2d8fc0bf6923 100644
--- a/drivers/input/mouse/bcm5974.c
+++ b/drivers/input/mouse/bcm5974.c
@@ -51,6 +51,10 @@
#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230
#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231
#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232
+/* Macbook5,1 (unibody), aka wellspring3 */
+#define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236
+#define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237
+#define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238
#define BCM5974_DEVICE(prod) { \
.match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \
@@ -72,6 +76,10 @@ static const struct usb_device_id bcm5974_table[] = {
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI),
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ISO),
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_JIS),
+ /* Macbook5,1 */
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI),
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ISO),
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_JIS),
/* Terminating entry */
{}
};
@@ -96,14 +104,23 @@ struct bt_data {
u8 rel_y; /* relative y coordinate */
};
-/* trackpad header structure */
-struct tp_header {
- u8 unknown1[16]; /* constants, timers, etc */
- u8 fingers; /* number of fingers on trackpad */
- u8 unknown2[9]; /* constants, timers, etc */
+/* trackpad header types */
+enum tp_type {
+ TYPE1, /* plain trackpad */
+ TYPE2 /* button integrated in trackpad */
};
-/* trackpad finger structure */
+/* trackpad finger data offsets, le16-aligned */
+#define FINGER_TYPE1 (13 * sizeof(__le16))
+#define FINGER_TYPE2 (15 * sizeof(__le16))
+
+/* trackpad button data offsets */
+#define BUTTON_TYPE2 15
+
+/* list of device capability bits */
+#define HAS_INTEGRATED_BUTTON 1
+
+/* trackpad finger structure, le16-aligned */
struct tp_finger {
__le16 origin; /* zero when switching track finger */
__le16 abs_x; /* absolute x coodinate */
@@ -117,13 +134,11 @@ struct tp_finger {
__le16 force_minor; /* trackpad force, minor axis? */
__le16 unused[3]; /* zeros */
__le16 multi; /* one finger: varies, more fingers: constant */
-};
+} __attribute__((packed,aligned(2)));
-/* trackpad data structure, empirically at least ten fingers */
-struct tp_data {
- struct tp_header header;
- struct tp_finger finger[16];
-};
+/* trackpad finger data size, empirically at least ten fingers */
+#define SIZEOF_FINGER sizeof(struct tp_finger)
+#define SIZEOF_ALL_FINGERS (16 * SIZEOF_FINGER)
/* device-specific parameters */
struct bcm5974_param {
@@ -136,9 +151,12 @@ struct bcm5974_param {
/* device-specific configuration */
struct bcm5974_config {
int ansi, iso, jis; /* the product id of this device */
+ int caps; /* device capability bitmask */
int bt_ep; /* the endpoint of the button interface */
int bt_datalen; /* data length of the button interface */
int tp_ep; /* the endpoint of the trackpad interface */
+ enum tp_type tp_type; /* type of trackpad interface */
+ int tp_offset; /* offset to trackpad finger data */
int tp_datalen; /* data length of the trackpad interface */
struct bcm5974_param p; /* finger pressure limits */
struct bcm5974_param w; /* finger width limits */
@@ -158,7 +176,7 @@ struct bcm5974 {
struct urb *bt_urb; /* button usb request block */
struct bt_data *bt_data; /* button transferred data */
struct urb *tp_urb; /* trackpad usb request block */
- struct tp_data *tp_data; /* trackpad transferred data */
+ u8 *tp_data; /* trackpad transferred data */
int fingers; /* number of fingers on trackpad */
};
@@ -183,8 +201,9 @@ static const struct bcm5974_config bcm5974_config_table[] = {
USB_DEVICE_ID_APPLE_WELLSPRING_ANSI,
USB_DEVICE_ID_APPLE_WELLSPRING_ISO,
USB_DEVICE_ID_APPLE_WELLSPRING_JIS,
+ 0,
0x84, sizeof(struct bt_data),
- 0x81, sizeof(struct tp_data),
+ 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 },
{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
{ DIM_X, DIM_X / SN_COORD, -4824, 5342 },
@@ -194,13 +213,26 @@ static const struct bcm5974_config bcm5974_config_table[] = {
USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI,
USB_DEVICE_ID_APPLE_WELLSPRING2_ISO,
USB_DEVICE_ID_APPLE_WELLSPRING2_JIS,
+ 0,
0x84, sizeof(struct bt_data),
- 0x81, sizeof(struct tp_data),
+ 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 },
{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
{ DIM_X, DIM_X / SN_COORD, -4824, 4824 },
{ DIM_Y, DIM_Y / SN_COORD, -172, 4290 }
},
+ {
+ USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI,
+ USB_DEVICE_ID_APPLE_WELLSPRING3_ISO,
+ USB_DEVICE_ID_APPLE_WELLSPRING3_JIS,
+ HAS_INTEGRATED_BUTTON,
+ 0x84, sizeof(struct bt_data),
+ 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+ { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
+ { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
+ { DIM_X, DIM_X / SN_COORD, -4460, 5166 },
+ { DIM_Y, DIM_Y / SN_COORD, -75, 6700 }
+ },
{}
};
@@ -257,6 +289,7 @@ static void setup_events_to_report(struct input_dev *input_dev,
__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
__set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
+ __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit);
__set_bit(BTN_LEFT, input_dev->keybit);
}
@@ -266,6 +299,11 @@ static int report_bt_state(struct bcm5974 *dev, int size)
if (size != sizeof(struct bt_data))
return -EIO;
+ dprintk(7,
+ "bcm5974: button data: %x %x %x %x\n",
+ dev->bt_data->unknown1, dev->bt_data->button,
+ dev->bt_data->rel_x, dev->bt_data->rel_y);
+
input_report_key(dev->input, BTN_LEFT, dev->bt_data->button);
input_sync(dev->input);
@@ -276,29 +314,37 @@ static int report_bt_state(struct bcm5974 *dev, int size)
static int report_tp_state(struct bcm5974 *dev, int size)
{
const struct bcm5974_config *c = &dev->cfg;
- const struct tp_finger *f = dev->tp_data->finger;
+ const struct tp_finger *f;
struct input_dev *input = dev->input;
- const int fingers = (size - 26) / 28;
- int raw_p, raw_w, raw_x, raw_y;
- int ptest = 0, origin = 0, nmin = 0, nmax = 0;
+ int raw_p, raw_w, raw_x, raw_y, raw_n;
+ int ptest = 0, origin = 0, ibt = 0, nmin = 0, nmax = 0;
int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0;
- if (size < 26 || (size - 26) % 28 != 0)
+ if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0)
return -EIO;
+ /* finger data, le16-aligned */
+ f = (const struct tp_finger *)(dev->tp_data + c->tp_offset);
+ raw_n = (size - c->tp_offset) / SIZEOF_FINGER;
+
/* always track the first finger; when detached, start over */
- if (fingers) {
+ if (raw_n) {
raw_p = raw2int(f->force_major);
raw_w = raw2int(f->size_major);
raw_x = raw2int(f->abs_x);
raw_y = raw2int(f->abs_y);
dprintk(9,
- "bcm5974: raw: p: %+05d w: %+05d x: %+05d y: %+05d\n",
- raw_p, raw_w, raw_x, raw_y);
+ "bcm5974: "
+ "raw: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n",
+ raw_p, raw_w, raw_x, raw_y, raw_n);
ptest = int2bound(&c->p, raw_p);
origin = raw2int(f->origin);
+
+ /* set the integrated button if applicable */
+ if (c->tp_type == TYPE2)
+ ibt = raw2int(dev->tp_data[BUTTON_TYPE2]);
}
/* while tracking finger still valid, count all fingers */
@@ -307,12 +353,13 @@ static int report_tp_state(struct bcm5974 *dev, int size)
abs_w = int2bound(&c->w, raw_w);
abs_x = int2bound(&c->x, raw_x - c->x.devmin);
abs_y = int2bound(&c->y, c->y.devmax - raw_y);
- for (; f != dev->tp_data->finger + fingers; f++) {
+ while (raw_n--) {
ptest = int2bound(&c->p, raw2int(f->force_major));
if (ptest > PRESSURE_LOW)
nmax++;
if (ptest > PRESSURE_HIGH)
nmin++;
+ f++;
}
}
@@ -324,7 +371,8 @@ static int report_tp_state(struct bcm5974 *dev, int size)
input_report_key(input, BTN_TOUCH, dev->fingers > 0);
input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1);
input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2);
- input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers > 2);
+ input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers == 3);
+ input_report_key(input, BTN_TOOL_QUADTAP, dev->fingers > 3);
input_report_abs(input, ABS_PRESSURE, abs_p);
input_report_abs(input, ABS_TOOL_WIDTH, abs_w);
@@ -335,11 +383,15 @@ static int report_tp_state(struct bcm5974 *dev, int size)
dprintk(8,
"bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d "
- "nmin: %d nmax: %d n: %d\n",
- abs_p, abs_w, abs_x, abs_y, nmin, nmax, dev->fingers);
+ "nmin: %d nmax: %d n: %d ibt: %d\n", abs_p, abs_w,
+ abs_x, abs_y, nmin, nmax, dev->fingers, ibt);
}
+ /* type 2 reports button events via ibt only */
+ if (c->tp_type == TYPE2)
+ input_report_key(input, BTN_LEFT, ibt);
+
input_sync(input);
return 0;
@@ -649,6 +701,8 @@ static int bcm5974_probe(struct usb_interface *iface,
input_dev->name = "bcm5974";
input_dev->phys = dev->phys;
usb_to_input_id(dev->udev, &input_dev->id);
+ /* report driver capabilities via the version field */
+ input_dev->id.version = cfg->caps;
input_dev->dev.parent = &iface->dev;
input_set_drvdata(input_dev, dev);
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 6ab0eb1ada1c..4bc78892ba91 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1,7 +1,7 @@
/*
- * Elantech Touchpad driver (v5)
+ * Elantech Touchpad driver (v6)
*
- * Copyright (C) 2007-2008 Arjan Opmeer <arjan@opmeer.net>
+ * Copyright (C) 2007-2009 Arjan Opmeer <arjan@opmeer.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
@@ -178,6 +178,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
struct elantech_data *etd = psmouse->private;
unsigned char *packet = psmouse->packet;
int fingers;
+ static int old_fingers;
if (etd->fw_version_maj == 0x01) {
/* byte 0: D U p1 p2 1 p3 R L
@@ -190,6 +191,14 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
fingers = (packet[0] & 0xc0) >> 6;
}
+ if (etd->jumpy_cursor) {
+ /* Discard packets that are likely to have bogus coordinates */
+ if (fingers > old_fingers) {
+ elantech_debug("elantech.c: discarding packet\n");
+ goto discard_packet_v1;
+ }
+ }
+
input_report_key(dev, BTN_TOUCH, fingers != 0);
/* byte 2: x7 x6 x5 x4 x3 x2 x1 x0
@@ -216,6 +225,9 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
}
input_sync(dev);
+
+ discard_packet_v1:
+ old_fingers = fingers;
}
/*
@@ -363,9 +375,14 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
rc = -1;
break;
}
+ }
+
+ if (rc == 0) {
/*
- * Read back reg 0x10. The touchpad is probably initalising
- * and not ready until we read back the value we just wrote.
+ * Read back reg 0x10. For hardware version 1 we must make
+ * sure the absolute mode bit is set. For hardware version 2
+ * the touchpad is probably initalising and not ready until
+ * we read back the value we just wrote.
*/
do {
rc = elantech_read_reg(psmouse, 0x10, &val);
@@ -373,12 +390,18 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
break;
tries--;
elantech_debug("elantech.c: retrying read (%d).\n",
- tries);
+ tries);
msleep(ETP_READ_BACK_DELAY);
} while (tries > 0);
- if (rc)
+
+ if (rc) {
pr_err("elantech.c: failed to read back register 0x10.\n");
- break;
+ } else if (etd->hw_version == 1 &&
+ !(val & ETP_R10_ABSOLUTE_MODE)) {
+ pr_err("elantech.c: touchpad refuses "
+ "to switch to absolute mode.\n");
+ rc = -1;
+ }
}
if (rc)
@@ -662,6 +685,17 @@ int elantech_init(struct psmouse *psmouse)
param[0], param[1], param[2]);
etd->capabilities = param[0];
+ /*
+ * This firmware seems to suffer from misreporting coordinates when
+ * a touch action starts causing the mouse cursor or scrolled page
+ * to jump. Enable a workaround.
+ */
+ if (etd->fw_version_maj == 0x02 && etd->fw_version_min == 0x22) {
+ pr_info("elantech.c: firmware version 2.34 detected, "
+ "enabling jumpy cursor workaround\n");
+ etd->jumpy_cursor = 1;
+ }
+
if (elantech_set_absolute_mode(psmouse)) {
pr_err("elantech.c: failed to put touchpad into absolute mode.\n");
goto init_fail;
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index bee282b540bc..ed848cc80814 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -1,7 +1,7 @@
/*
- * Elantech Touchpad driver (v5)
+ * Elantech Touchpad driver (v6)
*
- * Copyright (C) 2007-2008 Arjan Opmeer <arjan@opmeer.net>
+ * Copyright (C) 2007-2009 Arjan Opmeer <arjan@opmeer.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
@@ -104,6 +104,7 @@ struct elantech_data {
unsigned char fw_version_min;
unsigned char hw_version;
unsigned char paritycheck;
+ unsigned char jumpy_cursor;
unsigned char parity[256];
};
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c
index df81b0aaa9f8..dcd4236af1e3 100644
--- a/drivers/input/mouse/lifebook.c
+++ b/drivers/input/mouse/lifebook.c
@@ -61,6 +61,12 @@ static const struct dmi_system_id lifebook_dmi_table[] = {
},
},
{
+ .ident = "Lifebook B-2130",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "ZEPHYR"),
+ },
+ },
+ {
.ident = "Lifebook B213x/B2150",
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B2131/B2133/B2150"),
@@ -153,21 +159,22 @@ static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse)
if (!dev2)
printk(KERN_WARNING "lifebook.c: got relative packet "
"but no relative device set up\n");
- } else if (lifebook_use_6byte_proto) {
- input_report_abs(dev1, ABS_X,
- ((packet[1] & 0x3f) << 6) | (packet[2] & 0x3f));
- input_report_abs(dev1, ABS_Y,
- 4096 - (((packet[4] & 0x3f) << 6) | (packet[5] & 0x3f)));
} else {
- input_report_abs(dev1, ABS_X,
- (packet[1] | ((packet[0] & 0x30) << 4)));
- input_report_abs(dev1, ABS_Y,
- 1024 - (packet[2] | ((packet[0] & 0xC0) << 2)));
+ if (lifebook_use_6byte_proto) {
+ input_report_abs(dev1, ABS_X,
+ ((packet[1] & 0x3f) << 6) | (packet[2] & 0x3f));
+ input_report_abs(dev1, ABS_Y,
+ 4096 - (((packet[4] & 0x3f) << 6) | (packet[5] & 0x3f)));
+ } else {
+ input_report_abs(dev1, ABS_X,
+ (packet[1] | ((packet[0] & 0x30) << 4)));
+ input_report_abs(dev1, ABS_Y,
+ 1024 - (packet[2] | ((packet[0] & 0xC0) << 2)));
+ }
+ input_report_key(dev1, BTN_TOUCH, packet[0] & 0x04);
+ input_sync(dev1);
}
- input_report_key(dev1, BTN_TOUCH, packet[0] & 0x04);
- input_sync(dev1);
-
if (dev2) {
if (relative_packet) {
input_report_rel(dev2, REL_X,
diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c
index d196abfb68bc..5f278176eb9b 100644
--- a/drivers/input/mouse/maplemouse.c
+++ b/drivers/input/mouse/maplemouse.c
@@ -2,8 +2,8 @@
* SEGA Dreamcast mouse driver
* Based on drivers/usb/usbmouse.c
*
- * Copyright Yaegashi Takeshi, 2001
- * Adrian McMenamin, 2008
+ * Copyright (c) Yaegashi Takeshi, 2001
+ * Copyright (c) Adrian McMenamin, 2008 - 2009
*/
#include <linux/kernel.h>
@@ -29,7 +29,7 @@ static void dc_mouse_callback(struct mapleq *mq)
struct maple_device *mapledev = mq->dev;
struct dc_mouse *mse = maple_get_drvdata(mapledev);
struct input_dev *dev = mse->dev;
- unsigned char *res = mq->recvbuf;
+ unsigned char *res = mq->recvbuf->buf;
buttons = ~res[8];
relx = *(unsigned short *)(res + 12) - 512;
@@ -47,7 +47,7 @@ static void dc_mouse_callback(struct mapleq *mq)
static int dc_mouse_open(struct input_dev *dev)
{
- struct dc_mouse *mse = dev->dev.platform_data;
+ struct dc_mouse *mse = maple_get_drvdata(to_maple_dev(&dev->dev));
maple_getcond_callback(mse->mdev, dc_mouse_callback, HZ/50,
MAPLE_FUNC_MOUSE);
@@ -57,29 +57,33 @@ static int dc_mouse_open(struct input_dev *dev)
static void dc_mouse_close(struct input_dev *dev)
{
- struct dc_mouse *mse = dev->dev.platform_data;
+ struct dc_mouse *mse = maple_get_drvdata(to_maple_dev(&dev->dev));
maple_getcond_callback(mse->mdev, dc_mouse_callback, 0,
MAPLE_FUNC_MOUSE);
}
-
+/* allow the mouse to be used */
static int __devinit probe_maple_mouse(struct device *dev)
{
struct maple_device *mdev = to_maple_dev(dev);
struct maple_driver *mdrv = to_maple_driver(dev->driver);
+ int error;
struct input_dev *input_dev;
struct dc_mouse *mse;
- int error;
mse = kzalloc(sizeof(struct dc_mouse), GFP_KERNEL);
- input_dev = input_allocate_device();
-
- if (!mse || !input_dev) {
+ if (!mse) {
error = -ENOMEM;
goto fail;
}
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ error = -ENOMEM;
+ goto fail_nomem;
+ }
+
mse->dev = input_dev;
mse->mdev = mdev;
@@ -89,25 +93,24 @@ static int __devinit probe_maple_mouse(struct device *dev)
BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y) |
BIT_MASK(REL_WHEEL);
- input_dev->name = mdev->product_name;
- input_dev->id.bustype = BUS_HOST;
input_dev->open = dc_mouse_open;
input_dev->close = dc_mouse_close;
+ input_dev->name = mdev->product_name;
+ input_dev->id.bustype = BUS_HOST;
+ error = input_register_device(input_dev);
+ if (error)
+ goto fail_register;
mdev->driver = mdrv;
maple_set_drvdata(mdev, mse);
- error = input_register_device(input_dev);
- if (error)
- goto fail;
-
- return 0;
+ return error;
-fail:
+fail_register:
input_free_device(input_dev);
- maple_set_drvdata(mdev, NULL);
+fail_nomem:
kfree(mse);
- mdev->driver = NULL;
+fail:
return error;
}
diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c
index f63995f854ff..3941f97cfa60 100644
--- a/drivers/input/mouse/pc110pad.c
+++ b/drivers/input/mouse/pc110pad.c
@@ -108,7 +108,6 @@ static int pc110pad_open(struct input_dev *dev)
*/
static int __init pc110pad_init(void)
{
- struct pci_dev *dev;
int err;
if (!no_pci_devices())
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 17fd6d46d082..966b8868f792 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -60,7 +60,6 @@ struct mousedev {
int exist;
int open;
int minor;
- char name[16];
struct input_handle handle;
wait_queue_head_t wait;
struct list_head client_list;
@@ -863,19 +862,17 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
init_waitqueue_head(&mousedev->wait);
if (minor == MOUSEDEV_MIX)
- strlcpy(mousedev->name, "mice", sizeof(mousedev->name));
+ dev_set_name(&mousedev->dev, "mice");
else
- snprintf(mousedev->name, sizeof(mousedev->name),
- "mouse%d", minor);
+ dev_set_name(&mousedev->dev, "mouse%d", minor);
mousedev->minor = minor;
mousedev->exist = 1;
mousedev->handle.dev = input_get_device(dev);
- mousedev->handle.name = mousedev->name;
+ mousedev->handle.name = dev_name(&mousedev->dev);
mousedev->handle.handler = handler;
mousedev->handle.private = mousedev;
- dev_set_name(&mousedev->dev, mousedev->name);
mousedev->dev.class = &input_class;
if (dev)
mousedev->dev.parent = &dev->dev;
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index bfe49243f38b..1c9410d1822c 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -819,6 +819,7 @@ static const struct parisc_device_id hp_sdc_tbl[] = {
MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl);
static int __init hp_sdc_init_hppa(struct parisc_device *d);
+static struct delayed_work moduleloader_work;
static struct parisc_driver hp_sdc_driver = {
.name = "hp_sdc",
@@ -930,8 +931,15 @@ static int __init hp_sdc_init(void)
#if defined(__hppa__)
+static void request_module_delayed(struct work_struct *work)
+{
+ request_module("hp_sdc_mlc");
+}
+
static int __init hp_sdc_init_hppa(struct parisc_device *d)
{
+ int ret;
+
if (!d)
return 1;
if (hp_sdc.dev != NULL)
@@ -944,13 +952,26 @@ static int __init hp_sdc_init_hppa(struct parisc_device *d)
hp_sdc.data_io = d->hpa.start + 0x800;
hp_sdc.status_io = d->hpa.start + 0x801;
- return hp_sdc_init();
+ INIT_DELAYED_WORK(&moduleloader_work, request_module_delayed);
+
+ ret = hp_sdc_init();
+ /* after sucessfull initialization give SDC some time to settle
+ * and then load the hp_sdc_mlc upper layer driver */
+ if (!ret)
+ schedule_delayed_work(&moduleloader_work,
+ msecs_to_jiffies(2000));
+
+ return ret;
}
#endif /* __hppa__ */
static void hp_sdc_exit(void)
{
+ /* do nothing if we don't have a SDC */
+ if (!hp_sdc.dev)
+ return;
+
write_lock_irq(&hp_sdc.lock);
/* Turn off all maskable "sub-function" irq's. */
@@ -969,6 +990,7 @@ static void hp_sdc_exit(void)
tasklet_kill(&hp_sdc.task);
#if defined(__hppa__)
+ cancel_delayed_work_sync(&moduleloader_work);
if (unregister_parisc_driver(&hp_sdc_driver))
printk(KERN_WARNING PREFIX "Error unregistering HP SDC");
#endif
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 83ed2d56b924..fb8a3cd3ffd0 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -377,6 +377,24 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
{ }
};
+static struct dmi_system_id __initdata i8042_dmi_reset_table[] = {
+ {
+ .ident = "MSI Wind U-100",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "U-100"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
+ },
+ },
+ {
+ .ident = "LG Electronics X110",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "X110"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."),
+ },
+ },
+ { }
+};
+
#ifdef CONFIG_PNP
static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = {
{
@@ -386,6 +404,13 @@ static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = {
DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
},
},
+ {
+ .ident = "MSI Wind U-100",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "U-100"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
+ },
+ },
{ }
};
#endif
@@ -698,6 +723,9 @@ static int __init i8042_platform_init(void)
#endif
#ifdef CONFIG_X86
+ if (dmi_check_system(i8042_dmi_reset_table))
+ i8042_reset = 1;
+
if (dmi_check_system(i8042_dmi_noloop_table))
i8042_noloop = 1;
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 170f71ee5772..f919bf57293c 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -10,6 +10,7 @@
* the Free Software Foundation.
*/
+#include <linux/types.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/interrupt.h>
@@ -712,22 +713,43 @@ static int i8042_controller_check(void)
static int i8042_controller_selftest(void)
{
unsigned char param;
+ int i = 0;
if (!i8042_reset)
return 0;
- if (i8042_command(&param, I8042_CMD_CTL_TEST)) {
- printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n");
- return -ENODEV;
- }
+ /*
+ * We try this 5 times; on some really fragile systems this does not
+ * take the first time...
+ */
+ do {
+
+ if (i8042_command(&param, I8042_CMD_CTL_TEST)) {
+ printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n");
+ return -ENODEV;
+ }
+
+ if (param == I8042_RET_CTL_TEST)
+ return 0;
- if (param != I8042_RET_CTL_TEST) {
printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n",
- param, I8042_RET_CTL_TEST);
- return -EIO;
- }
+ param, I8042_RET_CTL_TEST);
+ msleep(50);
+ } while (i++ < 5);
+#ifdef CONFIG_X86
+ /*
+ * On x86, we don't fail entire i8042 initialization if controller
+ * reset fails in hopes that keyboard port will still be functional
+ * and user will still get a working keyboard. This is especially
+ * important on netbooks. On other arches we trust hardware more.
+ */
+ printk(KERN_INFO
+ "i8042: giving up on controller selftest, continuing anyway...\n");
return 0;
+#else
+ return -EIO;
+#endif
}
/*
@@ -900,6 +922,9 @@ static void i8042_dritek_enable(void)
#endif
#ifdef CONFIG_PM
+
+static bool i8042_suspended;
+
/*
* Here we try to restore the original BIOS settings. We only want to
* do that once, when we really suspend, not when we taking memory
@@ -909,11 +934,9 @@ static void i8042_dritek_enable(void)
static int i8042_suspend(struct platform_device *dev, pm_message_t state)
{
- if (dev->dev.power.power_state.event != state.event) {
- if (state.event == PM_EVENT_SUSPEND)
- i8042_controller_reset();
-
- dev->dev.power.power_state = state;
+ if (!i8042_suspended && state.event == PM_EVENT_SUSPEND) {
+ i8042_controller_reset();
+ i8042_suspended = true;
}
return 0;
@@ -931,7 +954,7 @@ static int i8042_resume(struct platform_device *dev)
/*
* Do not bother with restoring state if we haven't suspened yet
*/
- if (dev->dev.power.power_state.event == PM_EVENT_ON)
+ if (!i8042_suspended)
return 0;
error = i8042_controller_check();
@@ -977,10 +1000,9 @@ static int i8042_resume(struct platform_device *dev)
if (i8042_ports[I8042_KBD_PORT_NO].serio)
i8042_enable_kbd_port();
+ i8042_suspended = false;
i8042_interrupt(0, NULL);
- dev->dev.power.power_state = PMSG_ON;
-
return 0;
}
#endif /* CONFIG_PM */
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
index 57953c0eb82f..f412c69478a8 100644
--- a/drivers/input/serio/sa1111ps2.c
+++ b/drivers/input/serio/sa1111ps2.c
@@ -77,7 +77,7 @@ static irqreturn_t ps2_txint(int irq, void *dev_id)
spin_lock(&ps2if->lock);
status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
if (ps2if->head == ps2if->tail) {
- disable_irq(irq);
+ disable_irq_nosync(irq);
/* done */
} else if (status & PS2STAT_TXE) {
sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + SA1111_PS2DATA);
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index bc033250dfcd..fb17573f8f2d 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -41,17 +41,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Serio abstraction core");
MODULE_LICENSE("GPL");
-EXPORT_SYMBOL(serio_interrupt);
-EXPORT_SYMBOL(__serio_register_port);
-EXPORT_SYMBOL(serio_unregister_port);
-EXPORT_SYMBOL(serio_unregister_child_port);
-EXPORT_SYMBOL(__serio_register_driver);
-EXPORT_SYMBOL(serio_unregister_driver);
-EXPORT_SYMBOL(serio_open);
-EXPORT_SYMBOL(serio_close);
-EXPORT_SYMBOL(serio_rescan);
-EXPORT_SYMBOL(serio_reconnect);
-
/*
* serio_mutex protects entire serio subsystem and is taken every time
* serio port or driver registrered or unregistered.
@@ -506,9 +495,9 @@ static ssize_t serio_set_bind_mode(struct device *dev, struct device_attribute *
retval = count;
if (!strncmp(buf, "manual", count)) {
- serio->manual_bind = 1;
+ serio->manual_bind = true;
} else if (!strncmp(buf, "auto", count)) {
- serio->manual_bind = 0;
+ serio->manual_bind = false;
} else {
retval = -EINVAL;
}
@@ -581,7 +570,7 @@ static void serio_add_port(struct serio *serio)
"serio: device_add() failed for %s (%s), error: %d\n",
serio->phys, serio->name, error);
else {
- serio->registered = 1;
+ serio->registered = true;
error = sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group);
if (error)
printk(KERN_ERR
@@ -617,7 +606,7 @@ static void serio_destroy_port(struct serio *serio)
if (serio->registered) {
sysfs_remove_group(&serio->dev.kobj, &serio_id_attr_group);
device_del(&serio->dev);
- serio->registered = 0;
+ serio->registered = false;
}
list_del_init(&serio->node);
@@ -692,11 +681,13 @@ void serio_rescan(struct serio *serio)
{
serio_queue_event(serio, NULL, SERIO_RESCAN_PORT);
}
+EXPORT_SYMBOL(serio_rescan);
void serio_reconnect(struct serio *serio)
{
serio_queue_event(serio, NULL, SERIO_RECONNECT_CHAIN);
}
+EXPORT_SYMBOL(serio_reconnect);
/*
* Submits register request to kseriod for subsequent execution.
@@ -707,6 +698,7 @@ void __serio_register_port(struct serio *serio, struct module *owner)
serio_init_port(serio);
serio_queue_event(serio, owner, SERIO_REGISTER_PORT);
}
+EXPORT_SYMBOL(__serio_register_port);
/*
* Synchronously unregisters serio port.
@@ -718,6 +710,7 @@ void serio_unregister_port(struct serio *serio)
serio_destroy_port(serio);
mutex_unlock(&serio_mutex);
}
+EXPORT_SYMBOL(serio_unregister_port);
/*
* Safely unregisters child port if one is present.
@@ -731,6 +724,7 @@ void serio_unregister_child_port(struct serio *serio)
}
mutex_unlock(&serio_mutex);
}
+EXPORT_SYMBOL(serio_unregister_child_port);
/*
@@ -756,9 +750,9 @@ static ssize_t serio_driver_set_bind_mode(struct device_driver *drv, const char
retval = count;
if (!strncmp(buf, "manual", count)) {
- serio_drv->manual_bind = 1;
+ serio_drv->manual_bind = true;
} else if (!strncmp(buf, "auto", count)) {
- serio_drv->manual_bind = 0;
+ serio_drv->manual_bind = false;
} else {
retval = -EINVAL;
}
@@ -818,7 +812,7 @@ static void serio_attach_driver(struct serio_driver *drv)
int __serio_register_driver(struct serio_driver *drv, struct module *owner, const char *mod_name)
{
- int manual_bind = drv->manual_bind;
+ bool manual_bind = drv->manual_bind;
int error;
drv->driver.bus = &serio_bus;
@@ -829,7 +823,7 @@ int __serio_register_driver(struct serio_driver *drv, struct module *owner, cons
* Temporarily disable automatic binding because probing
* takes long time and we are better off doing it in kseriod
*/
- drv->manual_bind = 1;
+ drv->manual_bind = true;
error = driver_register(&drv->driver);
if (error) {
@@ -844,7 +838,7 @@ int __serio_register_driver(struct serio_driver *drv, struct module *owner, cons
* driver to free ports
*/
if (!manual_bind) {
- drv->manual_bind = 0;
+ drv->manual_bind = false;
error = serio_queue_event(drv, NULL, SERIO_ATTACH_DRIVER);
if (error) {
driver_unregister(&drv->driver);
@@ -854,6 +848,7 @@ int __serio_register_driver(struct serio_driver *drv, struct module *owner, cons
return 0;
}
+EXPORT_SYMBOL(__serio_register_driver);
void serio_unregister_driver(struct serio_driver *drv)
{
@@ -861,7 +856,7 @@ void serio_unregister_driver(struct serio_driver *drv)
mutex_lock(&serio_mutex);
- drv->manual_bind = 1; /* so serio_find_driver ignores it */
+ drv->manual_bind = true; /* so serio_find_driver ignores it */
serio_remove_pending_events(drv);
start_over:
@@ -877,6 +872,7 @@ start_over:
driver_unregister(&drv->driver);
mutex_unlock(&serio_mutex);
}
+EXPORT_SYMBOL(serio_unregister_driver);
static void serio_set_drv(struct serio *serio, struct serio_driver *drv)
{
@@ -937,11 +933,11 @@ static int serio_uevent(struct device *dev, struct kobj_uevent_env *env)
#ifdef CONFIG_PM
static int serio_suspend(struct device *dev, pm_message_t state)
{
- if (dev->power.power_state.event != state.event) {
- if (state.event == PM_EVENT_SUSPEND)
- serio_cleanup(to_serio_port(dev));
+ struct serio *serio = to_serio_port(dev);
- dev->power.power_state = state;
+ if (!serio->suspended && state.event == PM_EVENT_SUSPEND) {
+ serio_cleanup(serio);
+ serio->suspended = true;
}
return 0;
@@ -949,14 +945,15 @@ static int serio_suspend(struct device *dev, pm_message_t state)
static int serio_resume(struct device *dev)
{
+ struct serio *serio = to_serio_port(dev);
+
/*
* Driver reconnect can take a while, so better let kseriod
* deal with it.
*/
- if (dev->power.power_state.event != PM_EVENT_ON) {
- dev->power.power_state = PMSG_ON;
- serio_queue_event(to_serio_port(dev), NULL,
- SERIO_RECONNECT_PORT);
+ if (serio->suspended) {
+ serio->suspended = false;
+ serio_queue_event(serio, NULL, SERIO_RECONNECT_PORT);
}
return 0;
@@ -974,6 +971,7 @@ int serio_open(struct serio *serio, struct serio_driver *drv)
}
return 0;
}
+EXPORT_SYMBOL(serio_open);
/* called from serio_driver->connect/disconnect methods under serio_mutex */
void serio_close(struct serio *serio)
@@ -983,6 +981,7 @@ void serio_close(struct serio *serio)
serio_set_drv(serio, NULL);
}
+EXPORT_SYMBOL(serio_close);
irqreturn_t serio_interrupt(struct serio *serio,
unsigned char data, unsigned int dfl)
@@ -1003,6 +1002,7 @@ irqreturn_t serio_interrupt(struct serio *serio,
return ret;
}
+EXPORT_SYMBOL(serio_interrupt);
static struct bus_type serio_bus = {
.name = "serio",
diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c
index 2e18a1c0c351..3d32d3f4e486 100644
--- a/drivers/input/tablet/gtco.c
+++ b/drivers/input/tablet/gtco.c
@@ -1050,4 +1050,5 @@ static void __exit gtco_exit(void)
module_init(gtco_init);
module_exit(gtco_exit);
+MODULE_DESCRIPTION("GTCO digitizer USB driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index 677680e9f54f..9114ae1c7488 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -11,7 +11,7 @@
* Copyright (c) 2000 Daniel Egger <egger@suse.de>
* Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com>
* Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be>
- * Copyright (c) 2002-2008 Ping Cheng <pingc@wacom.com>
+ * Copyright (c) 2002-2009 Ping Cheng <pingc@wacom.com>
*
* ChangeLog:
* v0.1 (vp) - Initial release
@@ -67,6 +67,8 @@
* v1.47 (pc) - Added support for Bamboo
* v1.48 (pc) - Added support for Bamboo1, BambooFun, and Cintiq 12WX
* v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A)
+ * v1.50 (pc) - Fixed a TabletPC touch bug in 2.6.28
+ * v1.51 (pc) - Added support for Intuos4
*/
/*
@@ -87,7 +89,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.49"
+#define DRIVER_VERSION "v1.51"
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
#define DRIVER_LICENSE "GPL"
@@ -127,6 +129,8 @@ extern void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac
extern void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_i4s(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 484496daa0f3..a9d5031b855e 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -229,6 +229,19 @@ void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
}
+void input_dev_i4s(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+ input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER);
+ input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) | BIT_MASK(BTN_1) | BIT_MASK(BTN_2) | BIT_MASK(BTN_3);
+ input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_4) | BIT_MASK(BTN_5) | BIT_MASK(BTN_6);
+ input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
+}
+
+void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+ input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_7) | BIT_MASK(BTN_8);
+}
+
void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_8) | BIT_MASK(BTN_9);
@@ -289,6 +302,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
5000); /* 5 secs */
} while (result < 0 && limit++ < 5);
+ /* No need to parse the Descriptor. It isn't an error though */
if (result < 0)
goto out;
@@ -368,9 +382,8 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
}
}
- result = 0;
-
out:
+ result = 0;
kfree(report);
return result;
}
@@ -425,6 +438,15 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
endpoint = &intf->cur_altsetting->endpoint[0].desc;
+ /* Initialize touch_x_max and touch_y_max in case it is not defined */
+ if (wacom_wac->features->type == TABLETPC) {
+ features->touch_x_max = 1023;
+ features->touch_y_max = 1023;
+ } else {
+ features->touch_x_max = 0;
+ features->touch_y_max = 0;
+ }
+
/* TabletPC need to retrieve the physical and logical maximum from report descriptor */
if (wacom_wac->features->type == TABLETPC) {
if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) {
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 2638811c61ac..2ff89904f26f 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -283,10 +283,11 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
{
unsigned char *data = wacom->data;
- int idx;
+ int idx = 0;
/* tool number */
- idx = data[1] & 0x01;
+ if (wacom->features->type == INTUOS)
+ idx = data[1] & 0x01;
/* Enter report */
if ((data[1] & 0xfc) == 0xc0) {
@@ -299,6 +300,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
switch (wacom->id[idx]) {
case 0x812: /* Inking pen */
case 0x801: /* Intuos3 Inking pen */
+ case 0x20802: /* Intuos4 Classic Pen */
case 0x012:
wacom->tool[idx] = BTN_TOOL_PENCIL;
break;
@@ -308,6 +310,9 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
case 0x823: /* Intuos3 Grip Pen */
case 0x813: /* Intuos3 Classic Pen */
case 0x885: /* Intuos3 Marker Pen */
+ case 0x802: /* Intuos4 Grip Pen Eraser */
+ case 0x804: /* Intuos4 Marker Pen */
+ case 0x40802: /* Intuos4 Classic Pen */
case 0x022:
wacom->tool[idx] = BTN_TOOL_PEN;
break;
@@ -319,10 +324,12 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
case 0x09c:
case 0x094:
case 0x017: /* Intuos3 2D Mouse */
+ case 0x806: /* Intuos4 Mouse */
wacom->tool[idx] = BTN_TOOL_MOUSE;
break;
case 0x096: /* Lens cursor */
case 0x097: /* Intuos3 Lens cursor */
+ case 0x006: /* Intuos4 Lens cursor */
wacom->tool[idx] = BTN_TOOL_LENS;
break;
case 0x82a: /* Eraser */
@@ -333,12 +340,17 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
case 0x82b: /* Intuos3 Grip Pen Eraser */
case 0x81b: /* Intuos3 Classic Pen Eraser */
case 0x91b: /* Intuos3 Airbrush Eraser */
+ case 0x80c: /* Intuos4 Marker Pen Eraser */
+ case 0x80a: /* Intuos4 Grip Pen Eraser */
+ case 0x4080a: /* Intuos4 Classic Pen Eraser */
+ case 0x90a: /* Intuos4 Airbrush Eraser */
wacom->tool[idx] = BTN_TOOL_RUBBER;
break;
case 0xd12:
case 0x912:
case 0x112:
case 0x913: /* Intuos3 Airbrush */
+ case 0x902: /* Intuos4 Airbrush */
wacom->tool[idx] = BTN_TOOL_AIRBRUSH;
break;
default: /* Unknown tool */
@@ -349,9 +361,15 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
/* Exit report */
if ((data[1] & 0xfe) == 0x80) {
+ /*
+ * Reset all states otherwise we lose the initial states
+ * when in-prox next time
+ */
wacom_report_abs(wcombo, ABS_X, 0);
wacom_report_abs(wcombo, ABS_Y, 0);
wacom_report_abs(wcombo, ABS_DISTANCE, 0);
+ wacom_report_abs(wcombo, ABS_TILT_X, 0);
+ wacom_report_abs(wcombo, ABS_TILT_Y, 0);
if (wacom->tool[idx] >= BTN_TOOL_MOUSE) {
wacom_report_key(wcombo, BTN_LEFT, 0);
wacom_report_key(wcombo, BTN_MIDDLE, 0);
@@ -362,8 +380,6 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
wacom_report_abs(wcombo, ABS_RZ, 0);
} else {
wacom_report_abs(wcombo, ABS_PRESSURE, 0);
- wacom_report_abs(wcombo, ABS_TILT_X, 0);
- wacom_report_abs(wcombo, ABS_TILT_Y, 0);
wacom_report_key(wcombo, BTN_STYLUS, 0);
wacom_report_key(wcombo, BTN_STYLUS2, 0);
wacom_report_key(wcombo, BTN_TOUCH, 0);
@@ -372,6 +388,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
wacom_report_key(wcombo, wacom->tool[idx], 0);
wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+ wacom->id[idx] = 0;
return 2;
}
return 0;
@@ -385,6 +402,8 @@ static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo)
/* general pen packet */
if ((data[1] & 0xb8) == 0xa0) {
t = (data[6] << 2) | ((data[7] >> 6) & 3);
+ if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L)
+ t = (t << 1) | (data[1] & 1);
wacom_report_abs(wcombo, ABS_PRESSURE, t);
wacom_report_abs(wcombo, ABS_TILT_X,
((data[7] << 1) & 0x7e) | (data[8] >> 7));
@@ -409,7 +428,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
{
unsigned char *data = wacom->data;
unsigned int t;
- int idx, result;
+ int idx = 0, result;
if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) {
dbg("wacom_intuos_irq: received unknown report #%d", data[0]);
@@ -417,7 +436,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
}
/* tool number */
- idx = data[1] & 0x01;
+ if (wacom->features->type == INTUOS)
+ idx = data[1] & 0x01;
/* pad packets. Works as a second tool and is always in prox */
if (data[0] == 12) {
@@ -425,25 +445,51 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
if (wacom->tool[1] != BTN_TOOL_FINGER)
wacom->tool[1] = BTN_TOOL_FINGER;
- wacom_report_key(wcombo, BTN_0, (data[5] & 0x01));
- wacom_report_key(wcombo, BTN_1, (data[5] & 0x02));
- wacom_report_key(wcombo, BTN_2, (data[5] & 0x04));
- wacom_report_key(wcombo, BTN_3, (data[5] & 0x08));
- wacom_report_key(wcombo, BTN_4, (data[6] & 0x01));
- wacom_report_key(wcombo, BTN_5, (data[6] & 0x02));
- wacom_report_key(wcombo, BTN_6, (data[6] & 0x04));
- wacom_report_key(wcombo, BTN_7, (data[6] & 0x08));
- wacom_report_key(wcombo, BTN_8, (data[5] & 0x10));
- wacom_report_key(wcombo, BTN_9, (data[6] & 0x10));
- wacom_report_abs(wcombo, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
- wacom_report_abs(wcombo, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
-
- if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) |
- data[2] | (data[3] & 0x1f) | data[4])
- wacom_report_key(wcombo, wacom->tool[1], 1);
- else
- wacom_report_key(wcombo, wacom->tool[1], 0);
- wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
+ if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) {
+ wacom_report_key(wcombo, BTN_0, (data[2] & 0x01));
+ wacom_report_key(wcombo, BTN_1, (data[3] & 0x01));
+ wacom_report_key(wcombo, BTN_2, (data[3] & 0x02));
+ wacom_report_key(wcombo, BTN_3, (data[3] & 0x04));
+ wacom_report_key(wcombo, BTN_4, (data[3] & 0x08));
+ wacom_report_key(wcombo, BTN_5, (data[3] & 0x10));
+ wacom_report_key(wcombo, BTN_6, (data[3] & 0x20));
+ if (data[1] & 0x80) {
+ wacom_report_abs(wcombo, ABS_WHEEL, (data[1] & 0x7f));
+ }
+ if (wacom->features->type != INTUOS4S) {
+ wacom_report_key(wcombo, BTN_7, (data[3] & 0x40));
+ wacom_report_key(wcombo, BTN_8, (data[3] & 0x80));
+ }
+ if (data[1] | (data[2] & 0x01) | data[3]) {
+ wacom_report_key(wcombo, wacom->tool[1], 1);
+ wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
+ } else {
+ wacom_report_key(wcombo, wacom->tool[1], 0);
+ wacom_report_abs(wcombo, ABS_MISC, 0);
+ }
+ } else {
+ wacom_report_key(wcombo, BTN_0, (data[5] & 0x01));
+ wacom_report_key(wcombo, BTN_1, (data[5] & 0x02));
+ wacom_report_key(wcombo, BTN_2, (data[5] & 0x04));
+ wacom_report_key(wcombo, BTN_3, (data[5] & 0x08));
+ wacom_report_key(wcombo, BTN_4, (data[6] & 0x01));
+ wacom_report_key(wcombo, BTN_5, (data[6] & 0x02));
+ wacom_report_key(wcombo, BTN_6, (data[6] & 0x04));
+ wacom_report_key(wcombo, BTN_7, (data[6] & 0x08));
+ wacom_report_key(wcombo, BTN_8, (data[5] & 0x10));
+ wacom_report_key(wcombo, BTN_9, (data[6] & 0x10));
+ wacom_report_abs(wcombo, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
+ wacom_report_abs(wcombo, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
+
+ if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) |
+ data[2] | (data[3] & 0x1f) | data[4]) {
+ wacom_report_key(wcombo, wacom->tool[1], 1);
+ wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
+ } else {
+ wacom_report_key(wcombo, wacom->tool[1], 0);
+ wacom_report_abs(wcombo, ABS_MISC, 0);
+ }
+ }
wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff);
return 1;
}
@@ -453,10 +499,16 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
if (result)
return result-1;
- /* Only large I3 and I1 & I2 support Lense Cursor */
+ /* don't proceed if we don't know the ID */
+ if (!wacom->id[idx])
+ return 0;
+
+ /* Only large Intuos support Lense Cursor */
if ((wacom->tool[idx] == BTN_TOOL_LENS)
&& ((wacom->features->type == INTUOS3)
- || (wacom->features->type == INTUOS3S)))
+ || (wacom->features->type == INTUOS3S)
+ || (wacom->features->type == INTUOS4)
+ || (wacom->features->type == INTUOS4S)))
return 0;
/* Cintiq doesn't send data when RDY bit isn't set */
@@ -476,8 +528,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
/* process general packets */
wacom_intuos_general(wacom, wcombo);
- /* 4D mouse, 2D mouse, marker pen rotation, or Lens cursor packets */
- if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) {
+ /* 4D mouse, 2D mouse, marker pen rotation, tilt mouse, or Lens cursor packets */
+ if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0 || (data[1] & 0xbc) == 0xac) {
if (data[1] & 0x02) {
/* Rotation packet */
@@ -506,20 +558,36 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
wacom_report_abs(wcombo, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
} else if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
- /* 2D mouse packet */
- wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x04);
- wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x08);
- wacom_report_key(wcombo, BTN_RIGHT, data[8] & 0x10);
- wacom_report_rel(wcombo, REL_WHEEL, (data[8] & 0x01)
+ /* I4 mouse */
+ if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) {
+ wacom_report_key(wcombo, BTN_LEFT, data[6] & 0x01);
+ wacom_report_key(wcombo, BTN_MIDDLE, data[6] & 0x02);
+ wacom_report_key(wcombo, BTN_RIGHT, data[6] & 0x04);
+ wacom_report_rel(wcombo, REL_WHEEL, ((data[7] & 0x80) >> 7)
+ - ((data[7] & 0x40) >> 6));
+ wacom_report_key(wcombo, BTN_SIDE, data[6] & 0x08);
+ wacom_report_key(wcombo, BTN_EXTRA, data[6] & 0x10);
+
+ wacom_report_abs(wcombo, ABS_TILT_X,
+ ((data[7] << 1) & 0x7e) | (data[8] >> 7));
+ wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f);
+ } else {
+ /* 2D mouse packet */
+ wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x04);
+ wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x08);
+ wacom_report_key(wcombo, BTN_RIGHT, data[8] & 0x10);
+ wacom_report_rel(wcombo, REL_WHEEL, (data[8] & 0x01)
- ((data[8] & 0x02) >> 1));
- /* I3 2D mouse side buttons */
- if (wacom->features->type >= INTUOS3S && wacom->features->type <= INTUOS3L) {
- wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x40);
- wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x20);
+ /* I3 2D mouse side buttons */
+ if (wacom->features->type >= INTUOS3S && wacom->features->type <= INTUOS3L) {
+ wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x40);
+ wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x20);
+ }
}
-
- } else if (wacom->features->type < INTUOS3S || wacom->features->type == INTUOS3L) {
+ } else if ((wacom->features->type < INTUOS3S || wacom->features->type == INTUOS3L ||
+ wacom->features->type == INTUOS4L) &&
+ wacom->tool[idx] == BTN_TOOL_LENS) {
/* Lens cursor packets */
wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01);
wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02);
@@ -581,6 +649,7 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
}
} else if (touchOut || !prox) { /* force touch out-prox */
wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID);
+ wacom_report_key(wcombo, wacom->tool[1], 0);
wacom_report_key(wcombo, BTN_TOUCH, 0);
touchOut = 0;
touchInProx = 1;
@@ -669,6 +738,9 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo)
case INTUOS3S:
case INTUOS3:
case INTUOS3L:
+ case INTUOS4S:
+ case INTUOS4:
+ case INTUOS4L:
case CINTIQ:
case WACOM_BEE:
return wacom_intuos_irq(wacom_wac, wcombo);
@@ -706,6 +778,14 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w
case INTUOS:
input_dev_i(input_dev, wacom_wac);
break;
+ case INTUOS4:
+ case INTUOS4L:
+ input_dev_i4(input_dev, wacom_wac);
+ /* fall through */
+ case INTUOS4S:
+ input_dev_i4s(input_dev, wacom_wac);
+ input_dev_i(input_dev, wacom_wac);
+ break;
case PL:
case PTU:
case TABLETPC:
@@ -766,6 +846,10 @@ static struct wacom_features wacom_features[] = {
{ "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 63, INTUOS3L },
{ "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 63, INTUOS3 },
{ "Wacom Intuos3 4x6", 10, 31496, 19685, 1023, 63, INTUOS3S },
+ { "Wacom Intuos4 4x6", 10, 31496, 19685, 2047, 63, INTUOS4S },
+ { "Wacom Intuos4 6x9", 10, 44704, 27940, 2047, 63, INTUOS4 },
+ { "Wacom Intuos4 8x13", 10, 65024, 40640, 2047, 63, INTUOS4L },
+ { "Wacom Intuos4 12x19", 10, 97536, 60960, 2047, 63, INTUOS4L },
{ "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ },
{ "Wacom Cintiq 20WSX", 10, 86680, 54180, 1023, 63, WACOM_BEE },
{ "Wacom Cintiq 12WX", 10, 53020, 33440, 1023, 63, WACOM_BEE },
@@ -825,6 +909,10 @@ static struct usb_device_id wacom_ids[] = {
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB7) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB8) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB9) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xBA) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xBB) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC5) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC6) },
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index f9c8b69673b7..c10235aba7e5 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -25,6 +25,9 @@ enum {
INTUOS3S,
INTUOS3,
INTUOS3L,
+ INTUOS4S,
+ INTUOS4,
+ INTUOS4L,
CINTIQ,
WACOM_BEE,
WACOM_MO,
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index b01fd61dadcc..82c388e0fe3e 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -341,6 +341,21 @@ config TOUCHSCREEN_WM9713
Say Y here to enable support for the Wolfson Microelectronics
WM9713 touchscreen controller.
+config TOUCHSCREEN_WM97XX_ATMEL
+ tristate "WM97xx Atmel accelerated touch"
+ depends on TOUCHSCREEN_WM97XX && (AVR32 || ARCH_AT91)
+ help
+ Say Y here for support for streaming mode with WM97xx touchscreens
+ on Atmel AT91 or AVR32 systems with an AC97C module.
+
+ Be aware that this will use channel B in the controller for
+ streaming data, this must not conflict with other AC97C drivers.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the module will
+ be called atmel-wm97xx.
+
config TOUCHSCREEN_WM97XX_MAINSTONE
tristate "WM97xx Mainstone accelerated touch"
depends on TOUCHSCREEN_WM97XX && ARCH_PXA
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 6700f7b9d165..bef741522954 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -35,5 +35,6 @@ obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
+obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c
index e4728a28f492..ecaeb7e8e75e 100644
--- a/drivers/input/touchscreen/ad7877.c
+++ b/drivers/input/touchscreen/ad7877.c
@@ -736,8 +736,8 @@ static int __devinit ad7877_probe(struct spi_device *spi)
/* Request AD7877 /DAV GPIO interrupt */
- err = request_irq(spi->irq, ad7877_irq, IRQF_TRIGGER_FALLING |
- IRQF_SAMPLE_RANDOM, spi->dev.driver->name, ts);
+ err = request_irq(spi->irq, ad7877_irq, IRQF_TRIGGER_FALLING,
+ spi->dev.driver->name, ts);
if (err) {
dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
goto err_free_mem;
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c
index ea4c61d68683..5d8a70398807 100644
--- a/drivers/input/touchscreen/ad7879.c
+++ b/drivers/input/touchscreen/ad7879.c
@@ -448,8 +448,7 @@ static int __devinit ad7879_construct(bus_device *bus, struct ad7879 *ts)
ad7879_setup(ts);
err = request_irq(bus->irq, ad7879_irq,
- IRQF_TRIGGER_FALLING | IRQF_SAMPLE_RANDOM,
- bus->dev.driver->name, ts);
+ IRQF_TRIGGER_FALLING, bus->dev.driver->name, ts);
if (err) {
dev_err(&bus->dev, "irq %d busy?\n", bus->irq);
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 056ac77e2cf0..2b01e56568f8 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -127,6 +127,8 @@ struct ads7846 {
void (*filter_cleanup)(void *data);
int (*get_pendown_state)(void);
int gpio_pendown;
+
+ void (*wait_for_sync)(void);
};
/* leave chip selected when we're done, for quicker re-select? */
@@ -511,6 +513,10 @@ static int get_pendown_state(struct ads7846 *ts)
return !gpio_get_value(ts->gpio_pendown);
}
+static void null_wait_for_sync(void)
+{
+}
+
/*
* PENIRQ only kicks the timer. The timer only reissues the SPI transfer,
* to retrieve touchscreen status.
@@ -686,6 +692,7 @@ static void ads7846_rx_val(void *ads)
default:
BUG();
}
+ ts->wait_for_sync();
status = spi_async(ts->spi, m);
if (status)
dev_err(&ts->spi->dev, "spi_async --> %d\n",
@@ -723,6 +730,7 @@ static enum hrtimer_restart ads7846_timer(struct hrtimer *handle)
} else {
/* pen is still down, continue with the measurement */
ts->msg_idx = 0;
+ ts->wait_for_sync();
status = spi_async(ts->spi, &ts->msg[0]);
if (status)
dev_err(&ts->spi->dev, "spi_async --> %d\n", status);
@@ -746,7 +754,7 @@ static irqreturn_t ads7846_irq(int irq, void *handle)
* that here. (The "generic irq" framework may help...)
*/
ts->irq_disabled = 1;
- disable_irq(ts->spi->irq);
+ disable_irq_nosync(ts->spi->irq);
ts->pending = 1;
hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY),
HRTIMER_MODE_REL);
@@ -947,6 +955,8 @@ static int __devinit ads7846_probe(struct spi_device *spi)
ts->penirq_recheck_delay_usecs =
pdata->penirq_recheck_delay_usecs;
+ ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync;
+
snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev));
input_dev->name = "ADS784x Touchscreen";
diff --git a/drivers/input/touchscreen/atmel-wm97xx.c b/drivers/input/touchscreen/atmel-wm97xx.c
new file mode 100644
index 000000000000..35377f583e28
--- /dev/null
+++ b/drivers/input/touchscreen/atmel-wm97xx.c
@@ -0,0 +1,446 @@
+/*
+ * Atmel AT91 and AVR32 continuous touch screen driver for Wolfson WM97xx AC97
+ * codecs.
+ *
+ * Copyright (C) 2008 - 2009 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/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/wm97xx.h>
+#include <linux/timer.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+
+#define AC97C_ICA 0x10
+#define AC97C_CBRHR 0x30
+#define AC97C_CBSR 0x38
+#define AC97C_CBMR 0x3c
+#define AC97C_IER 0x54
+#define AC97C_IDR 0x58
+
+#define AC97C_RXRDY (1 << 4)
+#define AC97C_OVRUN (1 << 5)
+
+#define AC97C_CMR_SIZE_20 (0 << 16)
+#define AC97C_CMR_SIZE_18 (1 << 16)
+#define AC97C_CMR_SIZE_16 (2 << 16)
+#define AC97C_CMR_SIZE_10 (3 << 16)
+#define AC97C_CMR_CEM_LITTLE (1 << 18)
+#define AC97C_CMR_CEM_BIG (0 << 18)
+#define AC97C_CMR_CENA (1 << 21)
+
+#define AC97C_INT_CBEVT (1 << 4)
+
+#define AC97C_SR_CAEVT (1 << 3)
+
+#define AC97C_CH_MASK(slot) \
+ (0x7 << (3 * (slot - 3)))
+#define AC97C_CH_ASSIGN(slot, channel) \
+ (AC97C_CHANNEL_##channel << (3 * (slot - 3)))
+#define AC97C_CHANNEL_NONE 0x0
+#define AC97C_CHANNEL_B 0x2
+
+#define ac97c_writel(chip, reg, val) \
+ __raw_writel((val), (chip)->regs + AC97C_##reg)
+#define ac97c_readl(chip, reg) \
+ __raw_readl((chip)->regs + AC97C_##reg)
+
+#ifdef CONFIG_CPU_AT32AP700X
+#define ATMEL_WM97XX_AC97C_IOMEM (0xfff02800)
+#define ATMEL_WM97XX_AC97C_IRQ (29)
+#define ATMEL_WM97XX_GPIO_DEFAULT (32+16) /* Pin 16 on port B. */
+#else
+#error Unkown CPU, this driver only supports AT32AP700X CPUs.
+#endif
+
+struct continuous {
+ u16 id; /* codec id */
+ u8 code; /* continuous code */
+ u8 reads; /* number of coord reads per read cycle */
+ u32 speed; /* number of coords per second */
+};
+
+#define WM_READS(sp) ((sp / HZ) + 1)
+
+static const struct continuous cinfo[] = {
+ {WM9705_ID2, 0, WM_READS(94), 94},
+ {WM9705_ID2, 1, WM_READS(188), 188},
+ {WM9705_ID2, 2, WM_READS(375), 375},
+ {WM9705_ID2, 3, WM_READS(750), 750},
+ {WM9712_ID2, 0, WM_READS(94), 94},
+ {WM9712_ID2, 1, WM_READS(188), 188},
+ {WM9712_ID2, 2, WM_READS(375), 375},
+ {WM9712_ID2, 3, WM_READS(750), 750},
+ {WM9713_ID2, 0, WM_READS(94), 94},
+ {WM9713_ID2, 1, WM_READS(120), 120},
+ {WM9713_ID2, 2, WM_READS(154), 154},
+ {WM9713_ID2, 3, WM_READS(188), 188},
+};
+
+/* Continuous speed index. */
+static int sp_idx;
+
+/*
+ * Pen sampling frequency (Hz) in continuous mode.
+ */
+static int cont_rate = 188;
+module_param(cont_rate, int, 0);
+MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)");
+
+/*
+ * Pen down detection.
+ *
+ * This driver can either poll or use an interrupt to indicate a pen down
+ * event. If the irq request fails then it will fall back to polling mode.
+ */
+static int pen_int = 1;
+module_param(pen_int, int, 0);
+MODULE_PARM_DESC(pen_int, "Pen down detection (1 = interrupt, 0 = polling)");
+
+/*
+ * Pressure readback.
+ *
+ * Set to 1 to read back pen down pressure.
+ */
+static int pressure;
+module_param(pressure, int, 0);
+MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)");
+
+/*
+ * AC97 touch data slot.
+ *
+ * Touch screen readback data ac97 slot.
+ */
+static int ac97_touch_slot = 5;
+module_param(ac97_touch_slot, int, 0);
+MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number");
+
+/*
+ * GPIO line number.
+ *
+ * Set to GPIO number where the signal from the WM97xx device is hooked up.
+ */
+static int atmel_gpio_line = ATMEL_WM97XX_GPIO_DEFAULT;
+module_param(atmel_gpio_line, int, 0);
+MODULE_PARM_DESC(atmel_gpio_line, "GPIO line number connected to WM97xx");
+
+struct atmel_wm97xx {
+ struct wm97xx *wm;
+ struct timer_list pen_timer;
+ void __iomem *regs;
+ unsigned long ac97c_irq;
+ unsigned long gpio_pen;
+ unsigned long gpio_irq;
+ unsigned short x;
+ unsigned short y;
+};
+
+static irqreturn_t atmel_wm97xx_channel_b_interrupt(int irq, void *dev_id)
+{
+ struct atmel_wm97xx *atmel_wm97xx = dev_id;
+ struct wm97xx *wm = atmel_wm97xx->wm;
+ int status = ac97c_readl(atmel_wm97xx, CBSR);
+ irqreturn_t retval = IRQ_NONE;
+
+ if (status & AC97C_OVRUN) {
+ dev_dbg(&wm->touch_dev->dev, "AC97C overrun\n");
+ ac97c_readl(atmel_wm97xx, CBRHR);
+ retval = IRQ_HANDLED;
+ } else if (status & AC97C_RXRDY) {
+ u16 data;
+ u16 value;
+ u16 source;
+ u16 pen_down;
+
+ data = ac97c_readl(atmel_wm97xx, CBRHR);
+ value = data & 0x0fff;
+ source = data & WM97XX_ADCSRC_MASK;
+ pen_down = (data & WM97XX_PEN_DOWN) >> 8;
+
+ if (source == WM97XX_ADCSEL_X)
+ atmel_wm97xx->x = value;
+ if (source == WM97XX_ADCSEL_Y)
+ atmel_wm97xx->y = value;
+
+ if (!pressure && source == WM97XX_ADCSEL_Y) {
+ input_report_abs(wm->input_dev, ABS_X, atmel_wm97xx->x);
+ input_report_abs(wm->input_dev, ABS_Y, atmel_wm97xx->y);
+ input_report_key(wm->input_dev, BTN_TOUCH, pen_down);
+ input_sync(wm->input_dev);
+ } else if (pressure && source == WM97XX_ADCSEL_PRES) {
+ input_report_abs(wm->input_dev, ABS_X, atmel_wm97xx->x);
+ input_report_abs(wm->input_dev, ABS_Y, atmel_wm97xx->y);
+ input_report_abs(wm->input_dev, ABS_PRESSURE, value);
+ input_report_key(wm->input_dev, BTN_TOUCH, value);
+ input_sync(wm->input_dev);
+ }
+
+ retval = IRQ_HANDLED;
+ }
+
+ return retval;
+}
+
+static void atmel_wm97xx_acc_pen_up(struct wm97xx *wm)
+{
+ struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(wm->touch_dev);
+ struct input_dev *input_dev = wm->input_dev;
+ int pen_down = gpio_get_value(atmel_wm97xx->gpio_pen);
+
+ if (pen_down != 0) {
+ mod_timer(&atmel_wm97xx->pen_timer,
+ jiffies + msecs_to_jiffies(1));
+ } else {
+ if (pressure)
+ input_report_abs(input_dev, ABS_PRESSURE, 0);
+ input_report_key(input_dev, BTN_TOUCH, 0);
+ input_sync(input_dev);
+ }
+}
+
+static void atmel_wm97xx_pen_timer(unsigned long data)
+{
+ atmel_wm97xx_acc_pen_up((struct wm97xx *)data);
+}
+
+static int atmel_wm97xx_acc_startup(struct wm97xx *wm)
+{
+ struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(wm->touch_dev);
+ int idx = 0;
+
+ if (wm->ac97 == NULL)
+ return -ENODEV;
+
+ for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) {
+ if (wm->id != cinfo[idx].id)
+ continue;
+
+ sp_idx = idx;
+
+ if (cont_rate <= cinfo[idx].speed)
+ break;
+ }
+
+ wm->acc_rate = cinfo[sp_idx].code;
+ wm->acc_slot = ac97_touch_slot;
+ dev_info(&wm->touch_dev->dev, "atmel accelerated touchscreen driver, "
+ "%d samples/sec\n", cinfo[sp_idx].speed);
+
+ if (pen_int) {
+ unsigned long reg;
+
+ wm->pen_irq = atmel_wm97xx->gpio_irq;
+
+ switch (wm->id) {
+ case WM9712_ID2: /* Fall through. */
+ case WM9713_ID2:
+ /*
+ * Use GPIO 13 (PEN_DOWN) to assert GPIO line 3
+ * (PENDOWN).
+ */
+ wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
+ WM97XX_GPIO_POL_HIGH,
+ WM97XX_GPIO_STICKY,
+ WM97XX_GPIO_WAKE);
+ wm97xx_config_gpio(wm, WM97XX_GPIO_3, WM97XX_GPIO_OUT,
+ WM97XX_GPIO_POL_HIGH,
+ WM97XX_GPIO_NOTSTICKY,
+ WM97XX_GPIO_NOWAKE);
+ case WM9705_ID2: /* Fall through. */
+ /*
+ * Enable touch data slot in AC97 controller channel B.
+ */
+ reg = ac97c_readl(atmel_wm97xx, ICA);
+ reg &= ~AC97C_CH_MASK(wm->acc_slot);
+ reg |= AC97C_CH_ASSIGN(wm->acc_slot, B);
+ ac97c_writel(atmel_wm97xx, ICA, reg);
+
+ /*
+ * Enable channel and interrupt for RXRDY and OVERRUN.
+ */
+ ac97c_writel(atmel_wm97xx, CBMR, AC97C_CMR_CENA
+ | AC97C_CMR_CEM_BIG
+ | AC97C_CMR_SIZE_16
+ | AC97C_OVRUN
+ | AC97C_RXRDY);
+ /* Dummy read to empty RXRHR. */
+ ac97c_readl(atmel_wm97xx, CBRHR);
+ /*
+ * Enable interrupt for channel B in the AC97
+ * controller.
+ */
+ ac97c_writel(atmel_wm97xx, IER, AC97C_INT_CBEVT);
+ break;
+ default:
+ dev_err(&wm->touch_dev->dev, "pen down irq not "
+ "supported on this device\n");
+ pen_int = 0;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static void atmel_wm97xx_acc_shutdown(struct wm97xx *wm)
+{
+ if (pen_int) {
+ struct atmel_wm97xx *atmel_wm97xx =
+ platform_get_drvdata(wm->touch_dev);
+ unsigned long ica;
+
+ switch (wm->id & 0xffff) {
+ case WM9705_ID2: /* Fall through. */
+ case WM9712_ID2: /* Fall through. */
+ case WM9713_ID2:
+ /* Disable slot and turn off channel B interrupts. */
+ ica = ac97c_readl(atmel_wm97xx, ICA);
+ ica &= ~AC97C_CH_MASK(wm->acc_slot);
+ ac97c_writel(atmel_wm97xx, ICA, ica);
+ ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT);
+ ac97c_writel(atmel_wm97xx, CBMR, 0);
+ wm->pen_irq = 0;
+ break;
+ default:
+ dev_err(&wm->touch_dev->dev, "unknown codec\n");
+ break;
+ }
+ }
+}
+
+static void atmel_wm97xx_irq_enable(struct wm97xx *wm, int enable)
+{
+ /* Intentionally left empty. */
+}
+
+static struct wm97xx_mach_ops atmel_mach_ops = {
+ .acc_enabled = 1,
+ .acc_pen_up = atmel_wm97xx_acc_pen_up,
+ .acc_startup = atmel_wm97xx_acc_startup,
+ .acc_shutdown = atmel_wm97xx_acc_shutdown,
+ .irq_enable = atmel_wm97xx_irq_enable,
+ .irq_gpio = WM97XX_GPIO_3,
+};
+
+static int __init atmel_wm97xx_probe(struct platform_device *pdev)
+{
+ struct wm97xx *wm = platform_get_drvdata(pdev);
+ struct atmel_wm97xx *atmel_wm97xx;
+ int ret;
+
+ atmel_wm97xx = kzalloc(sizeof(struct atmel_wm97xx), GFP_KERNEL);
+ if (!atmel_wm97xx) {
+ dev_dbg(&pdev->dev, "out of memory\n");
+ return -ENOMEM;
+ }
+
+ atmel_wm97xx->wm = wm;
+ atmel_wm97xx->regs = (void *)ATMEL_WM97XX_AC97C_IOMEM;
+ atmel_wm97xx->ac97c_irq = ATMEL_WM97XX_AC97C_IRQ;
+ atmel_wm97xx->gpio_pen = atmel_gpio_line;
+ atmel_wm97xx->gpio_irq = gpio_to_irq(atmel_wm97xx->gpio_pen);
+
+ setup_timer(&atmel_wm97xx->pen_timer, atmel_wm97xx_pen_timer,
+ (unsigned long)wm);
+
+ ret = request_irq(atmel_wm97xx->ac97c_irq,
+ atmel_wm97xx_channel_b_interrupt,
+ IRQF_SHARED, "atmel-wm97xx-ch-b", atmel_wm97xx);
+ if (ret) {
+ dev_dbg(&pdev->dev, "could not request ac97c irq\n");
+ goto err;
+ }
+
+ platform_set_drvdata(pdev, atmel_wm97xx);
+
+ ret = wm97xx_register_mach_ops(wm, &atmel_mach_ops);
+ if (ret)
+ goto err_irq;
+
+ return ret;
+
+err_irq:
+ free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx);
+err:
+ platform_set_drvdata(pdev, NULL);
+ kfree(atmel_wm97xx);
+ return ret;
+}
+
+static int __exit atmel_wm97xx_remove(struct platform_device *pdev)
+{
+ struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev);
+ struct wm97xx *wm = atmel_wm97xx->wm;
+
+ ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT);
+ free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx);
+ del_timer_sync(&atmel_wm97xx->pen_timer);
+ wm97xx_unregister_mach_ops(wm);
+ platform_set_drvdata(pdev, NULL);
+ kfree(atmel_wm97xx);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int atmel_wm97xx_suspend(struct platform_device *pdev, pm_message_t msg)
+{
+ struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev);
+
+ ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT);
+ disable_irq(atmel_wm97xx->gpio_irq);
+ del_timer_sync(&atmel_wm97xx->pen_timer);
+
+ return 0;
+}
+
+static int atmel_wm97xx_resume(struct platform_device *pdev)
+{
+ struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev);
+ struct wm97xx *wm = atmel_wm97xx->wm;
+
+ if (wm->input_dev->users) {
+ enable_irq(atmel_wm97xx->gpio_irq);
+ ac97c_writel(atmel_wm97xx, IER, AC97C_INT_CBEVT);
+ }
+
+ return 0;
+}
+#else
+#define atmel_wm97xx_suspend NULL
+#define atmel_wm97xx_resume NULL
+#endif
+
+static struct platform_driver atmel_wm97xx_driver = {
+ .remove = __exit_p(atmel_wm97xx_remove),
+ .driver = {
+ .name = "wm97xx-touch",
+ },
+ .suspend = atmel_wm97xx_suspend,
+ .resume = atmel_wm97xx_resume,
+};
+
+static int __init atmel_wm97xx_init(void)
+{
+ return platform_driver_probe(&atmel_wm97xx_driver, atmel_wm97xx_probe);
+}
+module_init(atmel_wm97xx_init);
+
+static void __exit atmel_wm97xx_exit(void)
+{
+ platform_driver_unregister(&atmel_wm97xx_driver);
+}
+module_exit(atmel_wm97xx_exit);
+
+MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>");
+MODULE_DESCRIPTION("wm97xx continuous touch driver for Atmel AT91 and AVR32");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/da9034-ts.c b/drivers/input/touchscreen/da9034-ts.c
index fa67d782c3c3..3ffd4c4b170c 100644
--- a/drivers/input/touchscreen/da9034-ts.c
+++ b/drivers/input/touchscreen/da9034-ts.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2006-2008 Marvell International Ltd.
* Fengwei Yin <fengwei.yin@marvell.com>
+ * Bin Yang <bin.yang@marvell.com>
* Eric Miao <eric.miao@marvell.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -175,6 +176,16 @@ static void da9034_event_handler(struct da9034_touch *touch, int event)
goto err_reset;
touch->state = STATE_STOP;
+
+ /* FIXME: PEN_{UP/DOWN} events are expected to be
+ * available by stopping TSI, but this is found not
+ * always true, delay and simulate such an event
+ * here is more reliable
+ */
+ mdelay(1);
+ da9034_event_handler(touch,
+ is_pen_down(touch) ? EVENT_PEN_DOWN :
+ EVENT_PEN_UP);
break;
case STATE_STOP:
@@ -189,8 +200,6 @@ static void da9034_event_handler(struct da9034_touch *touch, int event)
report_pen_up(touch);
touch->state = STATE_IDLE;
}
-
- input_sync(touch->input_dev);
break;
case STATE_WAIT:
@@ -200,8 +209,10 @@ static void da9034_event_handler(struct da9034_touch *touch, int event)
if (is_pen_down(touch)) {
start_tsi(touch);
touch->state = STATE_BUSY;
- } else
+ } else {
+ report_pen_up(touch);
touch->state = STATE_IDLE;
+ }
break;
}
return;
@@ -226,16 +237,12 @@ static int da9034_touch_notifier(struct notifier_block *nb,
struct da9034_touch *touch =
container_of(nb, struct da9034_touch, notifier);
- if (event & DA9034_EVENT_PEN_DOWN) {
- if (is_pen_down(touch))
- da9034_event_handler(touch, EVENT_PEN_DOWN);
- else
- da9034_event_handler(touch, EVENT_PEN_UP);
- }
-
if (event & DA9034_EVENT_TSI_READY)
da9034_event_handler(touch, EVENT_TSI_READY);
+ if ((event & DA9034_EVENT_PEN_DOWN) && touch->state == STATE_IDLE)
+ da9034_event_handler(touch, EVENT_PEN_DOWN);
+
return 0;
}
@@ -385,6 +392,6 @@ static void __exit da9034_touch_exit(void)
module_exit(da9034_touch_exit);
MODULE_DESCRIPTION("Touchscreen driver for Dialog Semiconductor DA9034");
-MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>, Bin Yang <bin.yang@marvell.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:da9034-touch");
diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c
index dfa6a84ab50a..4cc047a5116e 100644
--- a/drivers/input/touchscreen/mainstone-wm97xx.c
+++ b/drivers/input/touchscreen/mainstone-wm97xx.c
@@ -111,13 +111,12 @@ static void wm97xx_acc_pen_up(struct wm97xx *wm)
#else
static void wm97xx_acc_pen_up(struct wm97xx *wm)
{
- int count = 16;
+ unsigned int count;
+
schedule_timeout_uninterruptible(1);
- while (count < 16) {
+ for (count = 0; count < 16; count++)
MODR;
- count--;
- }
}
#endif
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c
index 4ab070246892..948e167557f1 100644
--- a/drivers/input/touchscreen/tsc2007.c
+++ b/drivers/input/touchscreen/tsc2007.c
@@ -200,8 +200,9 @@ static int tsc2007_read_values(struct tsc2007 *tsc)
static enum hrtimer_restart tsc2007_timer(struct hrtimer *handle)
{
struct tsc2007 *ts = container_of(handle, struct tsc2007, timer);
+ unsigned long flags;
- spin_lock_irq(&ts->lock);
+ spin_lock_irqsave(&ts->lock, flags);
if (unlikely(!ts->get_pendown_state() && ts->pendown)) {
struct input_dev *input = ts->input;
@@ -222,7 +223,7 @@ static enum hrtimer_restart tsc2007_timer(struct hrtimer *handle)
tsc2007_send_event(ts);
}
- spin_unlock_irq(&ts->lock);
+ spin_unlock_irqrestore(&ts->lock, flags);
return HRTIMER_NORESTART;
}
@@ -235,7 +236,7 @@ static irqreturn_t tsc2007_irq(int irq, void *handle)
spin_lock_irqsave(&ts->lock, flags);
if (likely(ts->get_pendown_state())) {
- disable_irq(ts->irq);
+ disable_irq_nosync(ts->irq);
hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY),
HRTIMER_MODE_REL);
}
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
index e868264fe799..f100c7f4c1db 100644
--- a/drivers/input/touchscreen/ucb1400_ts.c
+++ b/drivers/input/touchscreen/ucb1400_ts.c
@@ -256,7 +256,7 @@ static irqreturn_t ucb1400_hard_irq(int irqnr, void *devid)
struct ucb1400_ts *ucb = devid;
if (irqnr == ucb->irq) {
- disable_irq(ucb->irq);
+ disable_irq_nosync(ucb->irq);
ucb->irq_pending = 1;
wake_up(&ucb->ts_wait);
return IRQ_HANDLED;
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
index cec480bffe38..2957d48e0045 100644
--- a/drivers/input/touchscreen/wm97xx-core.c
+++ b/drivers/input/touchscreen/wm97xx-core.c
@@ -370,8 +370,7 @@ static int wm97xx_init_pen_irq(struct wm97xx *wm)
* provided. */
BUG_ON(!wm->mach_ops->irq_enable);
- if (request_irq(wm->pen_irq, wm97xx_pen_interrupt,
- IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+ if (request_irq(wm->pen_irq, wm97xx_pen_interrupt, IRQF_SHARED,
"wm97xx-pen", wm)) {
dev_err(wm->dev,
"Failed to register pen down interrupt, polling");
@@ -570,7 +569,7 @@ static int wm97xx_probe(struct device *dev)
mutex_init(&wm->codec_mutex);
wm->dev = dev;
- dev->driver_data = wm;
+ dev_set_drvdata(dev, wm);
wm->ac97 = to_ac97_t(dev);
/* check that we have a supported codec */
diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c
index b129409925af..bff72d81f263 100644
--- a/drivers/isdn/capi/capifs.c
+++ b/drivers/isdn/capi/capifs.c
@@ -75,15 +75,17 @@ static int capifs_remount(struct super_block *s, int *flags, char *data)
}
}
- kfree(s->s_options);
- s->s_options = new_opt;
+ mutex_lock(&s->s_root->d_inode->i_mutex);
+ replace_mount_options(s, new_opt);
config.setuid = setuid;
config.setgid = setgid;
config.uid = uid;
config.gid = gid;
config.mode = mode;
+ mutex_unlock(&s->s_root->d_inode->i_mutex);
+
return 0;
}
@@ -154,13 +156,16 @@ void capifs_new_ncci(unsigned int number, dev_t device)
if (!inode)
return;
inode->i_ino = number+2;
+
+ dentry = get_node(number);
+
+ /* config contents is protected by root's i_mutex */
inode->i_uid = config.setuid ? config.uid : current_fsuid();
inode->i_gid = config.setgid ? config.gid : current_fsgid();
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
init_special_inode(inode, S_IFCHR|config.mode, device);
//inode->i_op = &capifs_file_inode_operations;
- dentry = get_node(number);
if (!IS_ERR(dentry) && !dentry->d_inode)
d_instantiate(dentry, inode);
mutex_unlock(&capifs_root->d_inode->i_mutex);
diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c
index 7d97d54588d9..77e9fdda0597 100644
--- a/drivers/isdn/divert/isdn_divert.c
+++ b/drivers/isdn/divert/isdn_divert.c
@@ -183,7 +183,7 @@ int cf_command(int drvid, int mode,
(mode != 1) ? "" : " 0 ",
(mode != 1) ? "" : fwd_nr);
- retval = divert_if.ll_cmd(&cs->ics); /* excute command */
+ retval = divert_if.ll_cmd(&cs->ics); /* execute command */
if (!retval)
{ cs->prev = NULL;
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
index ec3c0e507669..2b3a055059ea 100644
--- a/drivers/isdn/hisax/st5481_usb.c
+++ b/drivers/isdn/hisax/st5481_usb.c
@@ -149,14 +149,7 @@ static void usb_ctrl_complete(struct urb *urb)
if (ctrl_msg->dr.bRequest == USB_REQ_CLEAR_FEATURE) {
/* Special case handling for pipe reset */
le16_to_cpus(&ctrl_msg->dr.wIndex);
-
- /* toggle is reset on clear */
- usb_settoggle(adapter->usb_dev,
- ctrl_msg->dr.wIndex & ~USB_DIR_IN,
- (ctrl_msg->dr.wIndex & USB_DIR_IN) == 0,
- 0);
-
-
+ usb_reset_endpoint(adapter->usb_dev, ctrl_msg->dr.wIndex);
}
if (ctrl_msg->complete)
diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c
index 3083338716b2..47dbfe298b43 100644
--- a/drivers/isdn/mISDN/dsp_core.c
+++ b/drivers/isdn/mISDN/dsp_core.c
@@ -502,7 +502,7 @@ tone_off:
break;
}
dsp->cmx_delay = (*((int *)data)) << 3;
- /* miliseconds to samples */
+ /* milliseconds to samples */
if (dsp->cmx_delay >= (CMX_BUFF_HALF>>1))
/* clip to half of maximum usable buffer
(half of half buffer) */
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h
index ac8a4a3741b8..af92a176697f 100644
--- a/drivers/lguest/lg.h
+++ b/drivers/lguest/lg.h
@@ -158,7 +158,8 @@ void free_interrupts(void);
/* segments.c: */
void setup_default_gdt_entries(struct lguest_ro_state *state);
void setup_guest_gdt(struct lg_cpu *cpu);
-void load_guest_gdt(struct lg_cpu *cpu, unsigned long table, u32 num);
+void load_guest_gdt_entry(struct lg_cpu *cpu, unsigned int i,
+ u32 low, u32 hi);
void guest_load_tls(struct lg_cpu *cpu, unsigned long tls_array);
void copy_gdt(const struct lg_cpu *cpu, struct desc_struct *gdt);
void copy_gdt_tls(const struct lg_cpu *cpu, struct desc_struct *gdt);
diff --git a/drivers/lguest/segments.c b/drivers/lguest/segments.c
index 4f15439b7f12..7ede64ffeef9 100644
--- a/drivers/lguest/segments.c
+++ b/drivers/lguest/segments.c
@@ -144,18 +144,19 @@ void copy_gdt(const struct lg_cpu *cpu, struct desc_struct *gdt)
gdt[i] = cpu->arch.gdt[i];
}
-/*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 lg_cpu *cpu, unsigned long table, u32 num)
+/*H:620 This is where the Guest asks us to load a new GDT entry
+ * (LHCALL_LOAD_GDT_ENTRY). We tweak the entry and copy it in. */
+void load_guest_gdt_entry(struct lg_cpu *cpu, u32 num, u32 lo, u32 hi)
{
/* 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(cpu->arch.gdt))
kill_guest(cpu, "too many gdt entries %i", num);
- /* We read the whole thing in, then fix it up. */
- __lgread(cpu, cpu->arch.gdt, table, num * sizeof(cpu->arch.gdt[0]));
- fixup_gdt_table(cpu, 0, ARRAY_SIZE(cpu->arch.gdt));
+ /* Set it up, then fix it. */
+ cpu->arch.gdt[num].a = lo;
+ cpu->arch.gdt[num].b = hi;
+ fixup_gdt_table(cpu, num, num+1);
/* 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. */
cpu->changed |= CHANGED_GDT;
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c
index a6b717644be0..1a83910f674f 100644
--- a/drivers/lguest/x86/core.c
+++ b/drivers/lguest/x86/core.c
@@ -324,6 +324,11 @@ static void rewrite_hypercall(struct lg_cpu *cpu)
u8 insn[3] = {0xcd, 0x1f, 0x90};
__lgwrite(cpu, guest_pa(cpu, cpu->regs->eip), insn, sizeof(insn));
+ /* The above write might have caused a copy of that page to be made
+ * (if it was read-only). We need to make sure the Guest has
+ * up-to-date pagetables. As this doesn't happen often, we can just
+ * drop them all. */
+ guest_pagetable_clear_all(cpu);
}
static bool is_hypercall(struct lg_cpu *cpu)
@@ -563,8 +568,8 @@ void __exit lguest_arch_host_fini(void)
int lguest_arch_do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
{
switch (args->arg0) {
- case LHCALL_LOAD_GDT:
- load_guest_gdt(cpu, args->arg1, args->arg2);
+ case LHCALL_LOAD_GDT_ENTRY:
+ load_guest_gdt_entry(cpu, args->arg1, args->arg2, args->arg3);
break;
case LHCALL_LOAD_IDT_ENTRY:
load_guest_idt_entry(cpu, args->arg1, args->arg2, args->arg3);
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index 173cf55c64d0..3d906833948d 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -123,7 +123,7 @@ config PMAC_APM_EMU
config PMAC_MEDIABAY
bool "Support PowerBook hotswap media bay"
- depends on PPC_PMAC && PPC32
+ depends on PPC_PMAC && PPC32 && BLOCK
help
This option adds support for older PowerBook's hotswap media bay
that can contains batteries, floppy drives, or IDE devices. PCI
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
index d7e46d345d9e..029ad8ce8a7e 100644
--- a/drivers/macintosh/mediabay.c
+++ b/drivers/macintosh/mediabay.c
@@ -18,7 +18,6 @@
#include <linux/timer.h>
#include <linux/stddef.h>
#include <linux/init.h>
-#include <linux/ide.h>
#include <linux/kthread.h>
#include <linux/mutex.h>
#include <asm/prom.h>
@@ -447,6 +446,7 @@ int check_media_bay_by_base(unsigned long base, int what)
return -ENODEV;
}
+EXPORT_SYMBOL_GPL(check_media_bay_by_base);
int media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base,
int irq, ide_hwif_t *hwif)
@@ -486,6 +486,7 @@ int media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base,
return -ENODEV;
}
+EXPORT_SYMBOL_GPL(media_bay_set_ide_infos);
#endif /* CONFIG_BLK_DEV_IDE_PMAC */
static void media_bay_step(int i)
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index c0621d50c8a0..4a8bf467ff43 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -71,7 +71,7 @@ MODULE_PARM_DESC(verbose,"Verbose log operations "
"(default 0)");
struct thermostat {
- struct i2c_client clt;
+ struct i2c_client *clt;
u8 temps[3];
u8 cached_temp[3];
u8 initial_limits[3];
@@ -86,9 +86,6 @@ static struct of_device * of_dev;
static struct thermostat* thermostat;
static struct task_struct *thread_therm = NULL;
-static int attach_one_thermostat(struct i2c_adapter *adapter, int addr,
- int busno);
-
static void write_both_fan_speed(struct thermostat *th, int speed);
static void write_fan_speed(struct thermostat *th, int speed, int fan);
@@ -100,7 +97,7 @@ write_reg(struct thermostat* th, int reg, u8 data)
tmp[0] = reg;
tmp[1] = data;
- rc = i2c_master_send(&th->clt, (const char *)tmp, 2);
+ rc = i2c_master_send(th->clt, (const char *)tmp, 2);
if (rc < 0)
return rc;
if (rc != 2)
@@ -115,12 +112,12 @@ read_reg(struct thermostat* th, int reg)
int rc;
reg_addr = (u8)reg;
- rc = i2c_master_send(&th->clt, &reg_addr, 1);
+ rc = i2c_master_send(th->clt, &reg_addr, 1);
if (rc < 0)
return rc;
if (rc != 1)
return -ENODEV;
- rc = i2c_master_recv(&th->clt, (char *)&data, 1);
+ rc = i2c_master_recv(th->clt, (char *)&data, 1);
if (rc < 0)
return rc;
return data;
@@ -130,26 +127,36 @@ static int
attach_thermostat(struct i2c_adapter *adapter)
{
unsigned long bus_no;
+ struct i2c_board_info info;
+ struct i2c_client *client;
if (strncmp(adapter->name, "uni-n", 5))
return -ENODEV;
bus_no = simple_strtoul(adapter->name + 6, NULL, 10);
if (bus_no != therm_bus)
return -ENODEV;
- return attach_one_thermostat(adapter, therm_address, bus_no);
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "therm_adt746x", I2C_NAME_SIZE);
+ info.addr = therm_address;
+ client = i2c_new_device(adapter, &info);
+ if (!client)
+ return -ENODEV;
+
+ /*
+ * Let i2c-core delete that device on driver removal.
+ * This is safe because i2c-core holds the core_lock mutex for us.
+ */
+ list_add_tail(&client->detected, &client->driver->clients);
+ return 0;
}
static int
-detach_thermostat(struct i2c_adapter *adapter)
+remove_thermostat(struct i2c_client *client)
{
- struct thermostat* th;
+ struct thermostat *th = i2c_get_clientdata(client);
int i;
- if (thermostat == NULL)
- return 0;
-
- th = thermostat;
-
if (thread_therm != NULL) {
kthread_stop(thread_therm);
}
@@ -165,8 +172,6 @@ detach_thermostat(struct i2c_adapter *adapter)
write_both_fan_speed(th, -1);
- i2c_detach_client(&th->clt);
-
thermostat = NULL;
kfree(th);
@@ -174,14 +179,6 @@ detach_thermostat(struct i2c_adapter *adapter)
return 0;
}
-static struct i2c_driver thermostat_driver = {
- .driver = {
- .name = "therm_adt746x",
- },
- .attach_adapter = attach_thermostat,
- .detach_adapter = detach_thermostat,
-};
-
static int read_fan_speed(struct thermostat *th, u8 addr)
{
u8 tmp[2];
@@ -369,8 +366,8 @@ static void set_limit(struct thermostat *th, int i)
th->limits[i] = default_limits_local[i] + limit_adjust;
}
-static int attach_one_thermostat(struct i2c_adapter *adapter, int addr,
- int busno)
+static int probe_thermostat(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct thermostat* th;
int rc;
@@ -383,16 +380,12 @@ static int attach_one_thermostat(struct i2c_adapter *adapter, int addr,
if (!th)
return -ENOMEM;
- th->clt.addr = addr;
- th->clt.adapter = adapter;
- th->clt.driver = &thermostat_driver;
- strcpy(th->clt.name, "thermostat");
+ i2c_set_clientdata(client, th);
+ th->clt = client;
rc = read_reg(th, 0);
if (rc < 0) {
- printk(KERN_ERR "adt746x: Thermostat failed to read config "
- "from bus %d !\n",
- busno);
+ dev_err(&client->dev, "Thermostat failed to read config!\n");
kfree(th);
return -ENODEV;
}
@@ -421,14 +414,6 @@ static int attach_one_thermostat(struct i2c_adapter *adapter, int addr,
thermostat = th;
- if (i2c_attach_client(&th->clt)) {
- printk(KERN_INFO "adt746x: Thermostat failed to attach "
- "client !\n");
- thermostat = NULL;
- kfree(th);
- return -ENODEV;
- }
-
/* be sure to really write fan speed the first time */
th->last_speed[0] = -2;
th->last_speed[1] = -2;
@@ -454,6 +439,21 @@ static int attach_one_thermostat(struct i2c_adapter *adapter, int addr,
return 0;
}
+static const struct i2c_device_id therm_adt746x_id[] = {
+ { "therm_adt746x", 0 },
+ { }
+};
+
+static struct i2c_driver thermostat_driver = {
+ .driver = {
+ .name = "therm_adt746x",
+ },
+ .attach_adapter = attach_thermostat,
+ .probe = probe_thermostat,
+ .remove = remove_thermostat,
+ .id_table = therm_adt746x_id,
+};
+
/*
* Now, unfortunately, sysfs doesn't give us a nice void * we could
* pass around to the attribute functions, so we don't really have
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index 817607e2af6a..a028598af2d3 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -287,22 +287,6 @@ struct fcu_fan_table fcu_fans[] = {
};
/*
- * i2c_driver structure to attach to the host i2c controller
- */
-
-static int therm_pm72_attach(struct i2c_adapter *adapter);
-static int therm_pm72_detach(struct i2c_adapter *adapter);
-
-static struct i2c_driver therm_pm72_driver =
-{
- .driver = {
- .name = "therm_pm72",
- },
- .attach_adapter = therm_pm72_attach,
- .detach_adapter = therm_pm72_detach,
-};
-
-/*
* Utility function to create an i2c_client structure and
* attach it to one of u3 adapters
*/
@@ -310,6 +294,7 @@ static struct i2c_client *attach_i2c_chip(int id, const char *name)
{
struct i2c_client *clt;
struct i2c_adapter *adap;
+ struct i2c_board_info info;
if (id & 0x200)
adap = k2;
@@ -320,31 +305,21 @@ static struct i2c_client *attach_i2c_chip(int id, const char *name)
if (adap == NULL)
return NULL;
- clt = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (clt == NULL)
- return NULL;
-
- clt->addr = (id >> 1) & 0x7f;
- clt->adapter = adap;
- clt->driver = &therm_pm72_driver;
- strncpy(clt->name, name, I2C_NAME_SIZE-1);
-
- if (i2c_attach_client(clt)) {
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ info.addr = (id >> 1) & 0x7f;
+ strlcpy(info.type, "therm_pm72", I2C_NAME_SIZE);
+ clt = i2c_new_device(adap, &info);
+ if (!clt) {
printk(KERN_ERR "therm_pm72: Failed to attach to i2c ID 0x%x\n", id);
- kfree(clt);
return NULL;
}
- return clt;
-}
-/*
- * Utility function to get rid of the i2c_client structure
- * (will also detach from the adapter hopepfully)
- */
-static void detach_i2c_chip(struct i2c_client *clt)
-{
- i2c_detach_client(clt);
- kfree(clt);
+ /*
+ * Let i2c-core delete that device on driver removal.
+ * This is safe because i2c-core holds the core_lock mutex for us.
+ */
+ list_add_tail(&clt->detected, &clt->driver->clients);
+ return clt;
}
/*
@@ -1203,8 +1178,6 @@ static int init_cpu_state(struct cpu_pid_state *state, int index)
return 0;
fail:
- if (state->monitor)
- detach_i2c_chip(state->monitor);
state->monitor = NULL;
return -ENODEV;
@@ -1232,7 +1205,6 @@ static void dispose_cpu_state(struct cpu_pid_state *state)
device_remove_file(&of_dev->dev, &dev_attr_cpu1_intake_fan_rpm);
}
- detach_i2c_chip(state->monitor);
state->monitor = NULL;
}
@@ -1407,7 +1379,6 @@ static void dispose_backside_state(struct backside_pid_state *state)
device_remove_file(&of_dev->dev, &dev_attr_backside_temperature);
device_remove_file(&of_dev->dev, &dev_attr_backside_fan_pwm);
- detach_i2c_chip(state->monitor);
state->monitor = NULL;
}
@@ -1532,7 +1503,6 @@ static void dispose_drives_state(struct drives_pid_state *state)
device_remove_file(&of_dev->dev, &dev_attr_drives_temperature);
device_remove_file(&of_dev->dev, &dev_attr_drives_fan_rpm);
- detach_i2c_chip(state->monitor);
state->monitor = NULL;
}
@@ -1654,7 +1624,6 @@ static void dispose_dimms_state(struct dimm_pid_state *state)
device_remove_file(&of_dev->dev, &dev_attr_dimms_temperature);
- detach_i2c_chip(state->monitor);
state->monitor = NULL;
}
@@ -1779,7 +1748,6 @@ static void dispose_slots_state(struct slots_pid_state *state)
device_remove_file(&of_dev->dev, &dev_attr_slots_temperature);
device_remove_file(&of_dev->dev, &dev_attr_slots_fan_pwm);
- detach_i2c_chip(state->monitor);
state->monitor = NULL;
}
@@ -2008,8 +1976,6 @@ static int attach_fcu(void)
*/
static void detach_fcu(void)
{
- if (fcu)
- detach_i2c_chip(fcu);
fcu = NULL;
}
@@ -2060,12 +2026,21 @@ static int therm_pm72_attach(struct i2c_adapter *adapter)
return 0;
}
+static int therm_pm72_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ /* Always succeed, the real work was done in therm_pm72_attach() */
+ return 0;
+}
+
/*
- * Called on every adapter when the driver or the i2c controller
+ * Called when any of the devices which participates into thermal management
* is going away.
*/
-static int therm_pm72_detach(struct i2c_adapter *adapter)
+static int therm_pm72_remove(struct i2c_client *client)
{
+ struct i2c_adapter *adapter = client->adapter;
+
mutex_lock(&driver_lock);
if (state != state_detached)
@@ -2096,6 +2071,30 @@ static int therm_pm72_detach(struct i2c_adapter *adapter)
return 0;
}
+/*
+ * i2c_driver structure to attach to the host i2c controller
+ */
+
+static const struct i2c_device_id therm_pm72_id[] = {
+ /*
+ * Fake device name, thermal management is done by several
+ * chips but we don't need to differentiate between them at
+ * this point.
+ */
+ { "therm_pm72", 0 },
+ { }
+};
+
+static struct i2c_driver therm_pm72_driver = {
+ .driver = {
+ .name = "therm_pm72",
+ },
+ .attach_adapter = therm_pm72_attach,
+ .probe = therm_pm72_probe,
+ .remove = therm_pm72_remove,
+ .id_table = therm_pm72_id,
+};
+
static int fan_check_loc_match(const char *loc, int fan)
{
char tmp[64];
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 3da0a02efd76..40023313a760 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -48,16 +48,6 @@
#define LOG_TEMP 0 /* continously log temperature */
-static int do_probe( struct i2c_adapter *adapter, int addr, int kind);
-
-/* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */
-static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
- 0x4c, 0x4d, 0x4e, 0x4f,
- 0x2c, 0x2d, 0x2e, 0x2f,
- I2C_CLIENT_END };
-
-I2C_CLIENT_INSMOD;
-
static struct {
volatile int running;
struct task_struct *poll_task;
@@ -315,53 +305,54 @@ static int control_loop(void *dummy)
static int
do_attach( struct i2c_adapter *adapter )
{
- int ret = 0;
+ /* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */
+ static const unsigned short scan_ds1775[] = {
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ I2C_CLIENT_END
+ };
+ static const unsigned short scan_adm1030[] = {
+ 0x2c, 0x2d, 0x2e, 0x2f,
+ I2C_CLIENT_END
+ };
if( strncmp(adapter->name, "uni-n", 5) )
return 0;
if( !x.running ) {
- ret = i2c_probe( adapter, &addr_data, &do_probe );
+ struct i2c_board_info info;
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "therm_ds1775", I2C_NAME_SIZE);
+ i2c_new_probed_device(adapter, &info, scan_ds1775);
+
+ strlcpy(info.type, "therm_adm1030", I2C_NAME_SIZE);
+ i2c_new_probed_device(adapter, &info, scan_adm1030);
+
if( x.thermostat && x.fan ) {
x.running = 1;
x.poll_task = kthread_run(control_loop, NULL, "g4fand");
}
}
- return ret;
+ return 0;
}
static int
-do_detach( struct i2c_client *client )
+do_remove(struct i2c_client *client)
{
- int err;
-
- if( (err=i2c_detach_client(client)) )
- printk(KERN_ERR "failed to detach thermostat client\n");
- else {
- if( x.running ) {
- x.running = 0;
- kthread_stop(x.poll_task);
- x.poll_task = NULL;
- }
- if( client == x.thermostat )
- x.thermostat = NULL;
- else if( client == x.fan )
- x.fan = NULL;
- else {
- printk(KERN_ERR "g4fan: bad client\n");
- }
- kfree( client );
+ if (x.running) {
+ x.running = 0;
+ kthread_stop(x.poll_task);
+ x.poll_task = NULL;
}
- return err;
-}
+ if (client == x.thermostat)
+ x.thermostat = NULL;
+ else if (client == x.fan)
+ x.fan = NULL;
+ else
+ printk(KERN_ERR "g4fan: bad client\n");
-static struct i2c_driver g4fan_driver = {
- .driver = {
- .name = "therm_windtunnel",
- },
- .attach_adapter = do_attach,
- .detach_client = do_detach,
-};
+ return 0;
+}
static int
attach_fan( struct i2c_client *cl )
@@ -374,13 +365,8 @@ attach_fan( struct i2c_client *cl )
goto out;
printk("ADM1030 fan controller [@%02x]\n", cl->addr );
- strlcpy( cl->name, "ADM1030 fan controller", sizeof(cl->name) );
-
- if( !i2c_attach_client(cl) )
- x.fan = cl;
+ x.fan = cl;
out:
- if( cl != x.fan )
- kfree( cl );
return 0;
}
@@ -412,39 +398,47 @@ attach_thermostat( struct i2c_client *cl )
x.temp = temp;
x.overheat_temp = os_temp;
x.overheat_hyst = hyst_temp;
-
- strlcpy( cl->name, "DS1775 thermostat", sizeof(cl->name) );
-
- if( !i2c_attach_client(cl) )
- x.thermostat = cl;
+ x.thermostat = cl;
out:
- if( cl != x.thermostat )
- kfree( cl );
return 0;
}
+enum chip { ds1775, adm1030 };
+
+static const struct i2c_device_id therm_windtunnel_id[] = {
+ { "therm_ds1775", ds1775 },
+ { "therm_adm1030", adm1030 },
+ { }
+};
+
static int
-do_probe( struct i2c_adapter *adapter, int addr, int kind )
+do_probe(struct i2c_client *cl, const struct i2c_device_id *id)
{
- struct i2c_client *cl;
+ struct i2c_adapter *adapter = cl->adapter;
if( !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA
| I2C_FUNC_SMBUS_WRITE_BYTE) )
return 0;
- if( !(cl=kzalloc(sizeof(*cl), GFP_KERNEL)) )
- return -ENOMEM;
-
- cl->addr = addr;
- cl->adapter = adapter;
- cl->driver = &g4fan_driver;
- cl->flags = 0;
-
- if( addr < 0x48 )
+ switch (id->driver_data) {
+ case adm1030:
return attach_fan( cl );
- return attach_thermostat( cl );
+ case ds1775:
+ return attach_thermostat(cl);
+ }
+ return 0;
}
+static struct i2c_driver g4fan_driver = {
+ .driver = {
+ .name = "therm_windtunnel",
+ },
+ .attach_adapter = do_attach,
+ .probe = do_probe,
+ .remove = do_remove,
+ .id_table = therm_windtunnel_id,
+};
+
/************************************************************************/
/* initialization / cleanup */
diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c
index b92b959fe16e..529886c7a826 100644
--- a/drivers/macintosh/windfarm_lm75_sensor.c
+++ b/drivers/macintosh/windfarm_lm75_sensor.c
@@ -37,34 +37,22 @@
struct wf_lm75_sensor {
int ds1775 : 1;
int inited : 1;
- struct i2c_client i2c;
+ struct i2c_client *i2c;
struct wf_sensor sens;
};
#define wf_to_lm75(c) container_of(c, struct wf_lm75_sensor, sens)
-#define i2c_to_lm75(c) container_of(c, struct wf_lm75_sensor, i2c)
-
-static int wf_lm75_attach(struct i2c_adapter *adapter);
-static int wf_lm75_detach(struct i2c_client *client);
-
-static struct i2c_driver wf_lm75_driver = {
- .driver = {
- .name = "wf_lm75",
- },
- .attach_adapter = wf_lm75_attach,
- .detach_client = wf_lm75_detach,
-};
static int wf_lm75_get(struct wf_sensor *sr, s32 *value)
{
struct wf_lm75_sensor *lm = wf_to_lm75(sr);
s32 data;
- if (lm->i2c.adapter == NULL)
+ if (lm->i2c == NULL)
return -ENODEV;
/* Init chip if necessary */
if (!lm->inited) {
- u8 cfg_new, cfg = (u8)i2c_smbus_read_byte_data(&lm->i2c, 1);
+ u8 cfg_new, cfg = (u8)i2c_smbus_read_byte_data(lm->i2c, 1);
DBG("wf_lm75: Initializing %s, cfg was: %02x\n",
sr->name, cfg);
@@ -73,7 +61,7 @@ static int wf_lm75_get(struct wf_sensor *sr, s32 *value)
* the firmware for now
*/
cfg_new = cfg & ~0x01;
- i2c_smbus_write_byte_data(&lm->i2c, 1, cfg_new);
+ i2c_smbus_write_byte_data(lm->i2c, 1, cfg_new);
lm->inited = 1;
/* If we just powered it up, let's wait 200 ms */
@@ -81,7 +69,7 @@ static int wf_lm75_get(struct wf_sensor *sr, s32 *value)
}
/* Read temperature register */
- data = (s32)le16_to_cpu(i2c_smbus_read_word_data(&lm->i2c, 0));
+ data = (s32)le16_to_cpu(i2c_smbus_read_word_data(lm->i2c, 0));
data <<= 8;
*value = data;
@@ -92,12 +80,6 @@ static void wf_lm75_release(struct wf_sensor *sr)
{
struct wf_lm75_sensor *lm = wf_to_lm75(sr);
- /* check if client is registered and detach from i2c */
- if (lm->i2c.adapter) {
- i2c_detach_client(&lm->i2c);
- lm->i2c.adapter = NULL;
- }
-
kfree(lm);
}
@@ -107,59 +89,77 @@ static struct wf_sensor_ops wf_lm75_ops = {
.owner = THIS_MODULE,
};
-static struct wf_lm75_sensor *wf_lm75_create(struct i2c_adapter *adapter,
- u8 addr, int ds1775,
- const char *loc)
+static int wf_lm75_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct wf_lm75_sensor *lm;
int rc;
- DBG("wf_lm75: creating %s device at address 0x%02x\n",
- ds1775 ? "ds1775" : "lm75", addr);
-
lm = kzalloc(sizeof(struct wf_lm75_sensor), GFP_KERNEL);
if (lm == NULL)
- return NULL;
+ return -ENODEV;
+
+ lm->inited = 0;
+ lm->ds1775 = id->driver_data;
+ lm->i2c = client;
+ lm->sens.name = client->dev.platform_data;
+ lm->sens.ops = &wf_lm75_ops;
+ i2c_set_clientdata(client, lm);
+
+ rc = wf_register_sensor(&lm->sens);
+ if (rc) {
+ i2c_set_clientdata(client, NULL);
+ kfree(lm);
+ }
+
+ return rc;
+}
+
+static struct i2c_client *wf_lm75_create(struct i2c_adapter *adapter,
+ u8 addr, int ds1775,
+ const char *loc)
+{
+ struct i2c_board_info info;
+ struct i2c_client *client;
+ char *name;
+
+ DBG("wf_lm75: creating %s device at address 0x%02x\n",
+ ds1775 ? "ds1775" : "lm75", addr);
/* Usual rant about sensor names not beeing very consistent in
* the device-tree, oh well ...
* Add more entries below as you deal with more setups
*/
if (!strcmp(loc, "Hard drive") || !strcmp(loc, "DRIVE BAY"))
- lm->sens.name = "hd-temp";
+ name = "hd-temp";
else if (!strcmp(loc, "Incoming Air Temp"))
- lm->sens.name = "incoming-air-temp";
+ name = "incoming-air-temp";
else if (!strcmp(loc, "ODD Temp"))
- lm->sens.name = "optical-drive-temp";
+ name = "optical-drive-temp";
else if (!strcmp(loc, "HD Temp"))
- lm->sens.name = "hard-drive-temp";
+ name = "hard-drive-temp";
else
goto fail;
- lm->inited = 0;
- lm->sens.ops = &wf_lm75_ops;
- lm->ds1775 = ds1775;
- lm->i2c.addr = (addr >> 1) & 0x7f;
- lm->i2c.adapter = adapter;
- lm->i2c.driver = &wf_lm75_driver;
- strncpy(lm->i2c.name, lm->sens.name, I2C_NAME_SIZE-1);
-
- rc = i2c_attach_client(&lm->i2c);
- if (rc) {
- printk(KERN_ERR "windfarm: failed to attach %s %s to i2c,"
- " err %d\n", ds1775 ? "ds1775" : "lm75",
- lm->i2c.name, rc);
- goto fail;
- }
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ info.addr = (addr >> 1) & 0x7f;
+ info.platform_data = name;
+ strlcpy(info.type, ds1775 ? "wf_ds1775" : "wf_lm75", I2C_NAME_SIZE);
- if (wf_register_sensor(&lm->sens)) {
- i2c_detach_client(&lm->i2c);
+ client = i2c_new_device(adapter, &info);
+ if (client == NULL) {
+ printk(KERN_ERR "windfarm: failed to attach %s %s to i2c\n",
+ ds1775 ? "ds1775" : "lm75", name);
goto fail;
}
- return lm;
+ /*
+ * Let i2c-core delete that device on driver removal.
+ * This is safe because i2c-core holds the core_lock mutex for us.
+ */
+ list_add_tail(&client->detected, &client->driver->clients);
+ return client;
fail:
- kfree(lm);
return NULL;
}
@@ -202,21 +202,38 @@ static int wf_lm75_attach(struct i2c_adapter *adapter)
return 0;
}
-static int wf_lm75_detach(struct i2c_client *client)
+static int wf_lm75_remove(struct i2c_client *client)
{
- struct wf_lm75_sensor *lm = i2c_to_lm75(client);
+ struct wf_lm75_sensor *lm = i2c_get_clientdata(client);
DBG("wf_lm75: i2c detatch called for %s\n", lm->sens.name);
/* Mark client detached */
- lm->i2c.adapter = NULL;
+ lm->i2c = NULL;
/* release sensor */
wf_unregister_sensor(&lm->sens);
+ i2c_set_clientdata(client, NULL);
return 0;
}
+static const struct i2c_device_id wf_lm75_id[] = {
+ { "wf_lm75", 0 },
+ { "wf_ds1775", 1 },
+ { }
+};
+
+static struct i2c_driver wf_lm75_driver = {
+ .driver = {
+ .name = "wf_lm75",
+ },
+ .attach_adapter = wf_lm75_attach,
+ .probe = wf_lm75_probe,
+ .remove = wf_lm75_remove,
+ .id_table = wf_lm75_id,
+};
+
static int __init wf_lm75_sensor_init(void)
{
/* Don't register on old machines that use therm_pm72 for now */
diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c
index e207a90d6b27..e2a55ecda2b2 100644
--- a/drivers/macintosh/windfarm_max6690_sensor.c
+++ b/drivers/macintosh/windfarm_max6690_sensor.c
@@ -26,34 +26,22 @@
#define MAX6690_EXTERNAL_TEMP 1
struct wf_6690_sensor {
- struct i2c_client i2c;
+ struct i2c_client *i2c;
struct wf_sensor sens;
};
#define wf_to_6690(x) container_of((x), struct wf_6690_sensor, sens)
-#define i2c_to_6690(x) container_of((x), struct wf_6690_sensor, i2c)
-
-static int wf_max6690_attach(struct i2c_adapter *adapter);
-static int wf_max6690_detach(struct i2c_client *client);
-
-static struct i2c_driver wf_max6690_driver = {
- .driver = {
- .name = "wf_max6690",
- },
- .attach_adapter = wf_max6690_attach,
- .detach_client = wf_max6690_detach,
-};
static int wf_max6690_get(struct wf_sensor *sr, s32 *value)
{
struct wf_6690_sensor *max = wf_to_6690(sr);
s32 data;
- if (max->i2c.adapter == NULL)
+ if (max->i2c == NULL)
return -ENODEV;
/* chip gets initialized by firmware */
- data = i2c_smbus_read_byte_data(&max->i2c, MAX6690_EXTERNAL_TEMP);
+ data = i2c_smbus_read_byte_data(max->i2c, MAX6690_EXTERNAL_TEMP);
if (data < 0)
return data;
*value = data << 16;
@@ -64,10 +52,6 @@ static void wf_max6690_release(struct wf_sensor *sr)
{
struct wf_6690_sensor *max = wf_to_6690(sr);
- if (max->i2c.adapter) {
- i2c_detach_client(&max->i2c);
- max->i2c.adapter = NULL;
- }
kfree(max);
}
@@ -77,19 +61,40 @@ static struct wf_sensor_ops wf_max6690_ops = {
.owner = THIS_MODULE,
};
-static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr,
- const char *loc)
+static int wf_max6690_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct wf_6690_sensor *max;
- char *name;
+ int rc;
max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL);
if (max == NULL) {
- printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor %s: "
- "no memory\n", loc);
- return;
+ printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor: "
+ "no memory\n");
+ return -ENOMEM;
+ }
+
+ max->i2c = client;
+ max->sens.name = client->dev.platform_data;
+ max->sens.ops = &wf_max6690_ops;
+ i2c_set_clientdata(client, max);
+
+ rc = wf_register_sensor(&max->sens);
+ if (rc) {
+ i2c_set_clientdata(client, NULL);
+ kfree(max);
}
+ return rc;
+}
+
+static struct i2c_client *wf_max6690_create(struct i2c_adapter *adapter,
+ u8 addr, const char *loc)
+{
+ struct i2c_board_info info;
+ struct i2c_client *client;
+ char *name;
+
if (!strcmp(loc, "BACKSIDE"))
name = "backside-temp";
else if (!strcmp(loc, "NB Ambient"))
@@ -99,27 +104,26 @@ static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr,
else
goto fail;
- max->sens.ops = &wf_max6690_ops;
- max->sens.name = name;
- max->i2c.addr = addr >> 1;
- max->i2c.adapter = adapter;
- max->i2c.driver = &wf_max6690_driver;
- strncpy(max->i2c.name, name, I2C_NAME_SIZE-1);
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ info.addr = addr >> 1;
+ info.platform_data = name;
+ strlcpy(info.type, "wf_max6690", I2C_NAME_SIZE);
- if (i2c_attach_client(&max->i2c)) {
+ client = i2c_new_device(adapter, &info);
+ if (client == NULL) {
printk(KERN_ERR "windfarm: failed to attach MAX6690 sensor\n");
goto fail;
}
- if (wf_register_sensor(&max->sens)) {
- i2c_detach_client(&max->i2c);
- goto fail;
- }
-
- return;
+ /*
+ * Let i2c-core delete that device on driver removal.
+ * This is safe because i2c-core holds the core_lock mutex for us.
+ */
+ list_add_tail(&client->detected, &client->driver->clients);
+ return client;
fail:
- kfree(max);
+ return NULL;
}
static int wf_max6690_attach(struct i2c_adapter *adapter)
@@ -154,16 +158,31 @@ static int wf_max6690_attach(struct i2c_adapter *adapter)
return 0;
}
-static int wf_max6690_detach(struct i2c_client *client)
+static int wf_max6690_remove(struct i2c_client *client)
{
- struct wf_6690_sensor *max = i2c_to_6690(client);
+ struct wf_6690_sensor *max = i2c_get_clientdata(client);
- max->i2c.adapter = NULL;
+ max->i2c = NULL;
wf_unregister_sensor(&max->sens);
return 0;
}
+static const struct i2c_device_id wf_max6690_id[] = {
+ { "wf_max6690", 0 },
+ { }
+};
+
+static struct i2c_driver wf_max6690_driver = {
+ .driver = {
+ .name = "wf_max6690",
+ },
+ .attach_adapter = wf_max6690_attach,
+ .probe = wf_max6690_probe,
+ .remove = wf_max6690_remove,
+ .id_table = wf_max6690_id,
+};
+
static int __init wf_max6690_sensor_init(void)
{
/* Don't register on old machines that use therm_pm72 for now */
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c
index 7847e981ac33..5da729e58f99 100644
--- a/drivers/macintosh/windfarm_smu_sat.c
+++ b/drivers/macintosh/windfarm_smu_sat.c
@@ -39,7 +39,7 @@ struct wf_sat {
struct mutex mutex;
unsigned long last_read; /* jiffies when cache last updated */
u8 cache[16];
- struct i2c_client i2c;
+ struct i2c_client *i2c;
struct device_node *node;
};
@@ -54,18 +54,6 @@ struct wf_sat_sensor {
};
#define wf_to_sat(c) container_of(c, struct wf_sat_sensor, sens)
-#define i2c_to_sat(c) container_of(c, struct wf_sat, i2c)
-
-static int wf_sat_attach(struct i2c_adapter *adapter);
-static int wf_sat_detach(struct i2c_client *client);
-
-static struct i2c_driver wf_sat_driver = {
- .driver = {
- .name = "wf_smu_sat",
- },
- .attach_adapter = wf_sat_attach,
- .detach_client = wf_sat_detach,
-};
struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id,
unsigned int *size)
@@ -81,13 +69,13 @@ struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id,
if (sat_id > 1 || (sat = sats[sat_id]) == NULL)
return NULL;
- err = i2c_smbus_write_word_data(&sat->i2c, 8, id << 8);
+ err = i2c_smbus_write_word_data(sat->i2c, 8, id << 8);
if (err) {
printk(KERN_ERR "smu_sat_get_sdb_part wr error %d\n", err);
return NULL;
}
- err = i2c_smbus_read_word_data(&sat->i2c, 9);
+ err = i2c_smbus_read_word_data(sat->i2c, 9);
if (err < 0) {
printk(KERN_ERR "smu_sat_get_sdb_part rd len error\n");
return NULL;
@@ -105,7 +93,7 @@ struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id,
return NULL;
for (i = 0; i < len; i += 4) {
- err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0xa, 4, data);
+ err = i2c_smbus_read_i2c_block_data(sat->i2c, 0xa, 4, data);
if (err < 0) {
printk(KERN_ERR "smu_sat_get_sdb_part rd err %d\n",
err);
@@ -138,7 +126,7 @@ static int wf_sat_read_cache(struct wf_sat *sat)
{
int err;
- err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0x3f, 16, sat->cache);
+ err = i2c_smbus_read_i2c_block_data(sat->i2c, 0x3f, 16, sat->cache);
if (err < 0)
return err;
sat->last_read = jiffies;
@@ -161,7 +149,7 @@ static int wf_sat_get(struct wf_sensor *sr, s32 *value)
int i, err;
s32 val;
- if (sat->i2c.adapter == NULL)
+ if (sat->i2c == NULL)
return -ENODEV;
mutex_lock(&sat->mutex);
@@ -193,10 +181,6 @@ static void wf_sat_release(struct wf_sensor *sr)
struct wf_sat *sat = sens->sat;
if (atomic_dec_and_test(&sat->refcnt)) {
- if (sat->i2c.adapter) {
- i2c_detach_client(&sat->i2c);
- sat->i2c.adapter = NULL;
- }
if (sat->nr >= 0)
sats[sat->nr] = NULL;
kfree(sat);
@@ -212,38 +196,58 @@ static struct wf_sensor_ops wf_sat_ops = {
static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev)
{
+ struct i2c_board_info info;
+ struct i2c_client *client;
+ const u32 *reg;
+ u8 addr;
+
+ reg = of_get_property(dev, "reg", NULL);
+ if (reg == NULL)
+ return;
+ addr = *reg;
+ DBG(KERN_DEBUG "wf_sat: creating sat at address %x\n", addr);
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ info.addr = (addr >> 1) & 0x7f;
+ info.platform_data = dev;
+ strlcpy(info.type, "wf_sat", I2C_NAME_SIZE);
+
+ client = i2c_new_device(adapter, &info);
+ if (client == NULL) {
+ printk(KERN_ERR "windfarm: failed to attach smu-sat to i2c\n");
+ return;
+ }
+
+ /*
+ * Let i2c-core delete that device on driver removal.
+ * This is safe because i2c-core holds the core_lock mutex for us.
+ */
+ list_add_tail(&client->detected, &client->driver->clients);
+}
+
+static int wf_sat_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device_node *dev = client->dev.platform_data;
struct wf_sat *sat;
struct wf_sat_sensor *sens;
const u32 *reg;
const char *loc, *type;
- u8 addr, chip, core;
+ u8 chip, core;
struct device_node *child;
int shift, cpu, index;
char *name;
int vsens[2], isens[2];
- reg = of_get_property(dev, "reg", NULL);
- if (reg == NULL)
- return;
- addr = *reg;
- DBG(KERN_DEBUG "wf_sat: creating sat at address %x\n", addr);
-
sat = kzalloc(sizeof(struct wf_sat), GFP_KERNEL);
if (sat == NULL)
- return;
+ return -ENOMEM;
sat->nr = -1;
sat->node = of_node_get(dev);
atomic_set(&sat->refcnt, 0);
mutex_init(&sat->mutex);
- sat->i2c.addr = (addr >> 1) & 0x7f;
- sat->i2c.adapter = adapter;
- sat->i2c.driver = &wf_sat_driver;
- strncpy(sat->i2c.name, "smu-sat", I2C_NAME_SIZE-1);
-
- if (i2c_attach_client(&sat->i2c)) {
- printk(KERN_ERR "windfarm: failed to attach smu-sat to i2c\n");
- goto fail;
- }
+ sat->i2c = client;
+ i2c_set_clientdata(client, sat);
vsens[0] = vsens[1] = -1;
isens[0] = isens[1] = -1;
@@ -344,10 +348,7 @@ static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev)
if (sat->nr >= 0)
sats[sat->nr] = sat;
- return;
-
- fail:
- kfree(sat);
+ return 0;
}
static int wf_sat_attach(struct i2c_adapter *adapter)
@@ -366,16 +367,32 @@ static int wf_sat_attach(struct i2c_adapter *adapter)
return 0;
}
-static int wf_sat_detach(struct i2c_client *client)
+static int wf_sat_remove(struct i2c_client *client)
{
- struct wf_sat *sat = i2c_to_sat(client);
+ struct wf_sat *sat = i2c_get_clientdata(client);
/* XXX TODO */
- sat->i2c.adapter = NULL;
+ sat->i2c = NULL;
+ i2c_set_clientdata(client, NULL);
return 0;
}
+static const struct i2c_device_id wf_sat_id[] = {
+ { "wf_sat", 0 },
+ { }
+};
+
+static struct i2c_driver wf_sat_driver = {
+ .driver = {
+ .name = "wf_smu_sat",
+ },
+ .attach_adapter = wf_sat_attach,
+ .probe = wf_sat_probe,
+ .remove = wf_sat_remove,
+ .id_table = wf_sat_id,
+};
+
static int __init sat_sensors_init(void)
{
return i2c_add_driver(&wf_sat_driver);
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index f8a9f7ab2cb8..47c68bc75a17 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -986,6 +986,9 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
oldindex = index;
oldpage = page;
+ bitmap->filemap[bitmap->file_pages++] = page;
+ bitmap->last_page_size = count;
+
if (outofdate) {
/*
* if bitmap is out of date, dirty the
@@ -998,15 +1001,9 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
write_page(bitmap, page, 1);
ret = -EIO;
- if (bitmap->flags & BITMAP_WRITE_ERROR) {
- /* release, page not in filemap yet */
- put_page(page);
+ if (bitmap->flags & BITMAP_WRITE_ERROR)
goto err;
- }
}
-
- bitmap->filemap[bitmap->file_pages++] = page;
- bitmap->last_page_size = count;
}
paddr = kmap_atomic(page, KM_USER0);
if (bitmap->flags & BITMAP_HOSTENDIAN)
@@ -1016,9 +1013,11 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
kunmap_atomic(paddr, KM_USER0);
if (b) {
/* if the disk bit is set, set the memory bit */
- bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap),
- ((i+1) << (CHUNK_BLOCK_SHIFT(bitmap)) >= start)
- );
+ int needed = ((sector_t)(i+1) << (CHUNK_BLOCK_SHIFT(bitmap))
+ >= start);
+ bitmap_set_memory_bits(bitmap,
+ (sector_t)i << CHUNK_BLOCK_SHIFT(bitmap),
+ needed);
bit_cnt++;
set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
}
@@ -1154,8 +1153,9 @@ void bitmap_daemon_work(struct bitmap *bitmap)
spin_lock_irqsave(&bitmap->lock, flags);
clear_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
}
- bmc = bitmap_get_counter(bitmap, j << CHUNK_BLOCK_SHIFT(bitmap),
- &blocks, 0);
+ bmc = bitmap_get_counter(bitmap,
+ (sector_t)j << CHUNK_BLOCK_SHIFT(bitmap),
+ &blocks, 0);
if (bmc) {
/*
if (j < 100) printk("bitmap: j=%lu, *bmc = 0x%x\n", j, *bmc);
@@ -1169,7 +1169,8 @@ void bitmap_daemon_work(struct bitmap *bitmap)
} else if (*bmc == 1) {
/* we can clear the bit */
*bmc = 0;
- bitmap_count_page(bitmap, j << CHUNK_BLOCK_SHIFT(bitmap),
+ bitmap_count_page(bitmap,
+ (sector_t)j << CHUNK_BLOCK_SHIFT(bitmap),
-1);
/* clear the bit */
@@ -1479,6 +1480,7 @@ void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector)
s += blocks;
}
bitmap->last_end_sync = jiffies;
+ sysfs_notify(&bitmap->mddev->kobj, NULL, "sync_completed");
}
static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed)
@@ -1513,7 +1515,7 @@ void bitmap_dirty_bits(struct bitmap *bitmap, unsigned long s, unsigned long e)
unsigned long chunk;
for (chunk = s; chunk <= e; chunk++) {
- sector_t sec = chunk << CHUNK_BLOCK_SHIFT(bitmap);
+ sector_t sec = (sector_t)chunk << CHUNK_BLOCK_SHIFT(bitmap);
bitmap_set_memory_bits(bitmap, sec, 1);
bitmap_file_set_bit(bitmap, sec);
}
@@ -1589,7 +1591,7 @@ void bitmap_destroy(mddev_t *mddev)
int bitmap_create(mddev_t *mddev)
{
struct bitmap *bitmap;
- unsigned long blocks = mddev->resync_max_sectors;
+ sector_t blocks = mddev->resync_max_sectors;
unsigned long chunks;
unsigned long pages;
struct file *file = mddev->bitmap_file;
@@ -1631,8 +1633,8 @@ int bitmap_create(mddev_t *mddev)
bitmap->chunkshift = ffz(~bitmap->chunksize);
/* now that chunksize and chunkshift are set, we can use these macros */
- chunks = (blocks + CHUNK_BLOCK_RATIO(bitmap) - 1) /
- CHUNK_BLOCK_RATIO(bitmap);
+ chunks = (blocks + CHUNK_BLOCK_RATIO(bitmap) - 1) >>
+ CHUNK_BLOCK_SHIFT(bitmap);
pages = (chunks + PAGE_COUNTER_RATIO - 1) / PAGE_COUNTER_RATIO;
BUG_ON(!pages);
diff --git a/drivers/md/dm-bio-list.h b/drivers/md/dm-bio-list.h
deleted file mode 100644
index 345098b4ca77..000000000000
--- a/drivers/md/dm-bio-list.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2004 Red Hat UK Ltd.
- *
- * This file is released under the GPL.
- */
-
-#ifndef DM_BIO_LIST_H
-#define DM_BIO_LIST_H
-
-#include <linux/bio.h>
-
-#ifdef CONFIG_BLOCK
-
-struct bio_list {
- struct bio *head;
- struct bio *tail;
-};
-
-static inline int bio_list_empty(const struct bio_list *bl)
-{
- return bl->head == NULL;
-}
-
-static inline void bio_list_init(struct bio_list *bl)
-{
- bl->head = bl->tail = NULL;
-}
-
-#define bio_list_for_each(bio, bl) \
- for (bio = (bl)->head; bio; bio = bio->bi_next)
-
-static inline unsigned bio_list_size(const struct bio_list *bl)
-{
- unsigned sz = 0;
- struct bio *bio;
-
- bio_list_for_each(bio, bl)
- sz++;
-
- return sz;
-}
-
-static inline void bio_list_add(struct bio_list *bl, struct bio *bio)
-{
- bio->bi_next = NULL;
-
- if (bl->tail)
- bl->tail->bi_next = bio;
- else
- bl->head = bio;
-
- bl->tail = bio;
-}
-
-static inline void bio_list_add_head(struct bio_list *bl, struct bio *bio)
-{
- bio->bi_next = bl->head;
-
- bl->head = bio;
-
- if (!bl->tail)
- bl->tail = bio;
-}
-
-static inline void bio_list_merge(struct bio_list *bl, struct bio_list *bl2)
-{
- if (!bl2->head)
- return;
-
- if (bl->tail)
- bl->tail->bi_next = bl2->head;
- else
- bl->head = bl2->head;
-
- bl->tail = bl2->tail;
-}
-
-static inline void bio_list_merge_head(struct bio_list *bl,
- struct bio_list *bl2)
-{
- if (!bl2->head)
- return;
-
- if (bl->head)
- bl2->tail->bi_next = bl->head;
- else
- bl->tail = bl2->tail;
-
- bl->head = bl2->head;
-}
-
-static inline struct bio *bio_list_pop(struct bio_list *bl)
-{
- struct bio *bio = bl->head;
-
- if (bio) {
- bl->head = bl->head->bi_next;
- if (!bl->head)
- bl->tail = NULL;
-
- bio->bi_next = NULL;
- }
-
- return bio;
-}
-
-static inline struct bio *bio_list_get(struct bio_list *bl)
-{
- struct bio *bio = bl->head;
-
- bl->head = bl->tail = NULL;
-
- return bio;
-}
-
-#endif /* CONFIG_BLOCK */
-#endif
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 53394e863c74..04db6c4004a8 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1132,6 +1132,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad_crypt_queue;
}
+ ti->num_flush_requests = 1;
ti->private = cc;
return 0;
@@ -1189,6 +1190,13 @@ static int crypt_map(struct dm_target *ti, struct bio *bio,
union map_info *map_context)
{
struct dm_crypt_io *io;
+ struct crypt_config *cc;
+
+ if (unlikely(bio_empty_barrier(bio))) {
+ cc = ti->private;
+ bio->bi_bdev = cc->dev->bdev;
+ return DM_MAPIO_REMAPPED;
+ }
io = crypt_io_alloc(ti, bio, bio->bi_sector - ti->begin);
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c
index 59ee1b015d2d..8ad8a9044bbf 100644
--- a/drivers/md/dm-delay.c
+++ b/drivers/md/dm-delay.c
@@ -15,8 +15,6 @@
#include <linux/device-mapper.h>
-#include "dm-bio-list.h"
-
#define DM_MSG_PREFIX "delay"
struct delay_c {
@@ -199,6 +197,7 @@ out:
mutex_init(&dc->timer_lock);
atomic_set(&dc->may_delay, 1);
+ ti->num_flush_requests = 1;
ti->private = dc;
return 0;
@@ -280,8 +279,9 @@ static int delay_map(struct dm_target *ti, struct bio *bio,
if ((bio_data_dir(bio) == WRITE) && (dc->dev_write)) {
bio->bi_bdev = dc->dev_write->bdev;
- bio->bi_sector = dc->start_write +
- (bio->bi_sector - ti->begin);
+ if (bio_sectors(bio))
+ bio->bi_sector = dc->start_write +
+ (bio->bi_sector - ti->begin);
return delay_bio(dc, dc->write_delay, bio);
}
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index e73aabd61cd7..3a2e6a2f8bdd 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -22,6 +22,7 @@ struct dm_io_client {
/* FIXME: can we shrink this ? */
struct io {
unsigned long error_bits;
+ unsigned long eopnotsupp_bits;
atomic_t count;
struct task_struct *sleeper;
struct dm_io_client *client;
@@ -107,8 +108,11 @@ static inline unsigned bio_get_region(struct bio *bio)
*---------------------------------------------------------------*/
static void dec_count(struct io *io, unsigned int region, int error)
{
- if (error)
+ if (error) {
set_bit(region, &io->error_bits);
+ if (error == -EOPNOTSUPP)
+ set_bit(region, &io->eopnotsupp_bits);
+ }
if (atomic_dec_and_test(&io->count)) {
if (io->sleeper)
@@ -360,7 +364,9 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
return -EIO;
}
+retry:
io.error_bits = 0;
+ io.eopnotsupp_bits = 0;
atomic_set(&io.count, 1); /* see dispatch_io() */
io.sleeper = current;
io.client = client;
@@ -377,6 +383,11 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
}
set_current_state(TASK_RUNNING);
+ if (io.eopnotsupp_bits && (rw & (1 << BIO_RW_BARRIER))) {
+ rw &= ~(1 << BIO_RW_BARRIER);
+ goto retry;
+ }
+
if (error_bits)
*error_bits = io.error_bits;
@@ -397,6 +408,7 @@ static int async_io(struct dm_io_client *client, unsigned int num_regions,
io = mempool_alloc(client->pool, GFP_NOIO);
io->error_bits = 0;
+ io->eopnotsupp_bits = 0;
atomic_set(&io->count, 1); /* see dispatch_io() */
io->sleeper = NULL;
io->client = client;
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 79fb53e51c70..ecbb17421da4 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -53,6 +53,7 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad;
}
+ ti->num_flush_requests = 1;
ti->private = lc;
return 0;
@@ -81,7 +82,8 @@ static void linear_map_bio(struct dm_target *ti, struct bio *bio)
struct linear_c *lc = ti->private;
bio->bi_bdev = lc->dev->bdev;
- bio->bi_sector = linear_map_sector(ti, bio->bi_sector);
+ if (bio_sectors(bio))
+ bio->bi_sector = linear_map_sector(ti, bio->bi_sector);
}
static int linear_map(struct dm_target *ti, struct bio *bio,
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 095f77bf9681..0f50f65ed13e 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -8,7 +8,6 @@
#include <linux/device-mapper.h>
#include "dm-path-selector.h"
-#include "dm-bio-list.h"
#include "dm-bio-record.h"
#include "dm-uevent.h"
@@ -36,6 +35,7 @@ struct pgpath {
struct dm_path path;
struct work_struct deactivate_path;
+ struct work_struct activate_path;
};
#define path_to_pgpath(__pgp) container_of((__pgp), struct pgpath, path)
@@ -65,8 +65,6 @@ struct multipath {
spinlock_t lock;
const char *hw_handler_name;
- struct work_struct activate_path;
- struct pgpath *pgpath_to_activate;
unsigned nr_priority_groups;
struct list_head priority_groups;
unsigned pg_init_required; /* pg_init needs calling? */
@@ -129,6 +127,7 @@ static struct pgpath *alloc_pgpath(void)
if (pgpath) {
pgpath->is_active = 1;
INIT_WORK(&pgpath->deactivate_path, deactivate_path);
+ INIT_WORK(&pgpath->activate_path, activate_path);
}
return pgpath;
@@ -161,7 +160,6 @@ static struct priority_group *alloc_priority_group(void)
static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)
{
- unsigned long flags;
struct pgpath *pgpath, *tmp;
struct multipath *m = ti->private;
@@ -170,10 +168,6 @@ static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)
if (m->hw_handler_name)
scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev));
dm_put_device(ti, pgpath->path.dev);
- spin_lock_irqsave(&m->lock, flags);
- if (m->pgpath_to_activate == pgpath)
- m->pgpath_to_activate = NULL;
- spin_unlock_irqrestore(&m->lock, flags);
free_pgpath(pgpath);
}
}
@@ -203,7 +197,6 @@ static struct multipath *alloc_multipath(struct dm_target *ti)
m->queue_io = 1;
INIT_WORK(&m->process_queued_ios, process_queued_ios);
INIT_WORK(&m->trigger_event, trigger_event);
- INIT_WORK(&m->activate_path, activate_path);
m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache);
if (!m->mpio_pool) {
kfree(m);
@@ -428,8 +421,8 @@ static void process_queued_ios(struct work_struct *work)
{
struct multipath *m =
container_of(work, struct multipath, process_queued_ios);
- struct pgpath *pgpath = NULL;
- unsigned init_required = 0, must_queue = 1;
+ struct pgpath *pgpath = NULL, *tmp;
+ unsigned must_queue = 1;
unsigned long flags;
spin_lock_irqsave(&m->lock, flags);
@@ -447,19 +440,15 @@ static void process_queued_ios(struct work_struct *work)
must_queue = 0;
if (m->pg_init_required && !m->pg_init_in_progress && pgpath) {
- m->pgpath_to_activate = pgpath;
m->pg_init_count++;
m->pg_init_required = 0;
- m->pg_init_in_progress = 1;
- init_required = 1;
+ list_for_each_entry(tmp, &pgpath->pg->pgpaths, list) {
+ queue_work(kmpath_handlerd, &tmp->activate_path);
+ m->pg_init_in_progress++;
+ }
}
-
out:
spin_unlock_irqrestore(&m->lock, flags);
-
- if (init_required)
- queue_work(kmpath_handlerd, &m->activate_path);
-
if (!must_queue)
dispatch_queued_ios(m);
}
@@ -554,6 +543,12 @@ static int parse_path_selector(struct arg_set *as, struct priority_group *pg,
return -EINVAL;
}
+ if (ps_argc > as->argc) {
+ dm_put_path_selector(pst);
+ ti->error = "not enough arguments for path selector";
+ return -EINVAL;
+ }
+
r = pst->create(&pg->ps, ps_argc, as->argv);
if (r) {
dm_put_path_selector(pst);
@@ -592,9 +587,20 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
}
if (m->hw_handler_name) {
- r = scsi_dh_attach(bdev_get_queue(p->path.dev->bdev),
- m->hw_handler_name);
+ struct request_queue *q = bdev_get_queue(p->path.dev->bdev);
+
+ r = scsi_dh_attach(q, m->hw_handler_name);
+ if (r == -EBUSY) {
+ /*
+ * Already attached to different hw_handler,
+ * try to reattach with correct one.
+ */
+ scsi_dh_detach(q);
+ r = scsi_dh_attach(q, m->hw_handler_name);
+ }
+
if (r < 0) {
+ ti->error = "error attaching hardware handler";
dm_put_device(ti, p->path.dev);
goto bad;
}
@@ -700,6 +706,11 @@ static int parse_hw_handler(struct arg_set *as, struct multipath *m)
if (!hw_argc)
return 0;
+ if (hw_argc > as->argc) {
+ ti->error = "not enough arguments for hardware handler";
+ return -EINVAL;
+ }
+
m->hw_handler_name = kstrdup(shift(as), GFP_KERNEL);
request_module("scsi_dh_%s", m->hw_handler_name);
if (scsi_dh_handler_exist(m->hw_handler_name) == 0) {
@@ -824,6 +835,8 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc,
goto bad;
}
+ ti->num_flush_requests = 1;
+
return 0;
bad:
@@ -925,9 +938,13 @@ static int reinstate_path(struct pgpath *pgpath)
pgpath->is_active = 1;
- m->current_pgpath = NULL;
- if (!m->nr_valid_paths++ && m->queue_size)
+ if (!m->nr_valid_paths++ && m->queue_size) {
+ m->current_pgpath = NULL;
queue_work(kmultipathd, &m->process_queued_ios);
+ } else if (m->hw_handler_name && (m->current_pg == pgpath->pg)) {
+ m->pg_init_in_progress++;
+ queue_work(kmpath_handlerd, &pgpath->activate_path);
+ }
dm_path_uevent(DM_UEVENT_PATH_REINSTATED, m->ti,
pgpath->path.dev->name, m->nr_valid_paths);
@@ -1103,35 +1120,30 @@ static void pg_init_done(struct dm_path *path, int errors)
spin_lock_irqsave(&m->lock, flags);
if (errors) {
- DMERR("Could not failover device. Error %d.", errors);
- m->current_pgpath = NULL;
- m->current_pg = NULL;
+ if (pgpath == m->current_pgpath) {
+ DMERR("Could not failover device. Error %d.", errors);
+ m->current_pgpath = NULL;
+ m->current_pg = NULL;
+ }
} else if (!m->pg_init_required) {
m->queue_io = 0;
pg->bypassed = 0;
}
- m->pg_init_in_progress = 0;
- queue_work(kmultipathd, &m->process_queued_ios);
+ m->pg_init_in_progress--;
+ if (!m->pg_init_in_progress)
+ queue_work(kmultipathd, &m->process_queued_ios);
spin_unlock_irqrestore(&m->lock, flags);
}
static void activate_path(struct work_struct *work)
{
int ret;
- struct multipath *m =
- container_of(work, struct multipath, activate_path);
- struct dm_path *path;
- unsigned long flags;
+ struct pgpath *pgpath =
+ container_of(work, struct pgpath, activate_path);
- spin_lock_irqsave(&m->lock, flags);
- path = &m->pgpath_to_activate->path;
- m->pgpath_to_activate = NULL;
- spin_unlock_irqrestore(&m->lock, flags);
- if (!path)
- return;
- ret = scsi_dh_activate(bdev_get_queue(path->dev->bdev));
- pg_init_done(path, ret);
+ ret = scsi_dh_activate(bdev_get_queue(pgpath->path.dev->bdev));
+ pg_init_done(&pgpath->path, ret);
}
/*
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 536ef0bef154..076fbb4e967a 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -5,7 +5,6 @@
* This file is released under the GPL.
*/
-#include "dm-bio-list.h"
#include "dm-bio-record.h"
#include <linux/init.h>
diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c
index 59f8d9df9e1a..36dbe29f2fd6 100644
--- a/drivers/md/dm-region-hash.c
+++ b/drivers/md/dm-region-hash.c
@@ -14,7 +14,6 @@
#include <linux/vmalloc.h>
#include "dm.h"
-#include "dm-bio-list.h"
#define DM_MSG_PREFIX "region hash"
@@ -284,7 +283,7 @@ static struct dm_region *__rh_alloc(struct dm_region_hash *rh, region_t region)
nreg = mempool_alloc(rh->region_pool, GFP_ATOMIC);
if (unlikely(!nreg))
- nreg = kmalloc(sizeof(*nreg), GFP_NOIO);
+ nreg = kmalloc(sizeof(*nreg), GFP_NOIO | __GFP_NOFAIL);
nreg->state = rh->log->type->in_sync(rh->log, region, 1) ?
DM_RH_CLEAN : DM_RH_NOSYNC;
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
index e75c6dd76a9a..9761468aa474 100644
--- a/drivers/md/dm-snap-persistent.c
+++ b/drivers/md/dm-snap-persistent.c
@@ -636,7 +636,7 @@ static void persistent_commit_exception(struct dm_exception_store *store,
/*
* Commit exceptions to disk.
*/
- if (ps->valid && area_io(ps, WRITE))
+ if (ps->valid && area_io(ps, WRITE_BARRIER))
ps->valid = 0;
/*
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 981a0413068f..d573165cd2b7 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -22,7 +22,6 @@
#include <linux/workqueue.h>
#include "dm-exception-store.h"
-#include "dm-bio-list.h"
#define DM_MSG_PREFIX "snapshots"
@@ -679,6 +678,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
ti->private = s;
ti->split_io = s->store->chunk_size;
+ ti->num_flush_requests = 1;
return 0;
@@ -1031,6 +1031,11 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
chunk_t chunk;
struct dm_snap_pending_exception *pe = NULL;
+ if (unlikely(bio_empty_barrier(bio))) {
+ bio->bi_bdev = s->store->cow->bdev;
+ return DM_MAPIO_REMAPPED;
+ }
+
chunk = sector_to_chunk(s->store, bio->bi_sector);
/* Full snapshots are not usable */
@@ -1339,6 +1344,8 @@ static int origin_ctr(struct dm_target *ti, unsigned int argc, char **argv)
}
ti->private = dev;
+ ti->num_flush_requests = 1;
+
return 0;
}
@@ -1354,6 +1361,9 @@ static int origin_map(struct dm_target *ti, struct bio *bio,
struct dm_dev *dev = ti->private;
bio->bi_bdev = dev->bdev;
+ if (unlikely(bio_empty_barrier(bio)))
+ return DM_MAPIO_REMAPPED;
+
/* Only tell snapshots if this is a write */
return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : DM_MAPIO_REMAPPED;
}
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index 41569bc60abc..c64fe827a5f1 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -167,6 +167,7 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
sc->stripes = stripes;
sc->stripe_width = width;
ti->split_io = chunk_size;
+ ti->num_flush_requests = stripes;
sc->chunk_mask = ((sector_t) chunk_size) - 1;
for (sc->chunk_shift = 0; chunk_size; sc->chunk_shift++)
@@ -211,10 +212,18 @@ static int stripe_map(struct dm_target *ti, struct bio *bio,
union map_info *map_context)
{
struct stripe_c *sc = (struct stripe_c *) ti->private;
+ sector_t offset, chunk;
+ uint32_t stripe;
- sector_t offset = bio->bi_sector - ti->begin;
- sector_t chunk = offset >> sc->chunk_shift;
- uint32_t stripe = sector_div(chunk, sc->stripes);
+ if (unlikely(bio_empty_barrier(bio))) {
+ BUG_ON(map_context->flush_request >= sc->stripes);
+ bio->bi_bdev = sc->stripe[map_context->flush_request].dev->bdev;
+ return DM_MAPIO_REMAPPED;
+ }
+
+ offset = bio->bi_sector - ti->begin;
+ chunk = offset >> sc->chunk_shift;
+ stripe = sector_div(chunk, sc->stripes);
bio->bi_bdev = sc->stripe[stripe].dev->bdev;
bio->bi_sector = sc->stripe[stripe].physical_start +
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 429b50b975d5..d0c78f3dde72 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -384,15 +384,40 @@ static void close_dev(struct dm_dev_internal *d, struct mapped_device *md)
/*
* If possible, this checks an area of a destination device is valid.
*/
-static int check_device_area(struct dm_dev_internal *dd, sector_t start,
- sector_t len)
+static int device_area_is_valid(struct dm_target *ti, struct block_device *bdev,
+ sector_t start, sector_t len)
{
- sector_t dev_size = dd->dm_dev.bdev->bd_inode->i_size >> SECTOR_SHIFT;
+ sector_t dev_size = bdev->bd_inode->i_size >> SECTOR_SHIFT;
+ unsigned short hardsect_size_sectors = ti->limits.hardsect_size >>
+ SECTOR_SHIFT;
+ char b[BDEVNAME_SIZE];
if (!dev_size)
return 1;
- return ((start < dev_size) && (len <= (dev_size - start)));
+ if ((start >= dev_size) || (start + len > dev_size)) {
+ DMWARN("%s: %s too small for target",
+ dm_device_name(ti->table->md), bdevname(bdev, b));
+ return 0;
+ }
+
+ if (hardsect_size_sectors <= 1)
+ return 1;
+
+ if (start & (hardsect_size_sectors - 1)) {
+ DMWARN("%s: start=%lu not aligned to h/w sector of %s",
+ dm_device_name(ti->table->md), start, bdevname(bdev, b));
+ return 0;
+ }
+
+ if (len & (hardsect_size_sectors - 1)) {
+ DMWARN("%s: len=%lu not aligned to h/w sector size %hu of %s",
+ dm_device_name(ti->table->md), len,
+ ti->limits.hardsect_size, bdevname(bdev, b));
+ return 0;
+ }
+
+ return 1;
}
/*
@@ -478,14 +503,7 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti,
}
atomic_inc(&dd->count);
- if (!check_device_area(dd, start, len)) {
- DMWARN("device %s too small for target", path);
- dm_put_device(ti, &dd->dm_dev);
- return -EINVAL;
- }
-
*result = &dd->dm_dev;
-
return 0;
}
@@ -553,8 +571,16 @@ int dm_get_device(struct dm_target *ti, const char *path, sector_t start,
int r = __table_get_device(ti->table, ti, path,
start, len, mode, result);
- if (!r)
- dm_set_device_limits(ti, (*result)->bdev);
+ if (r)
+ return r;
+
+ dm_set_device_limits(ti, (*result)->bdev);
+
+ if (!device_area_is_valid(ti, (*result)->bdev, start, len)) {
+ dm_put_device(ti, *result);
+ *result = NULL;
+ return -EINVAL;
+ }
return r;
}
@@ -693,6 +719,71 @@ static void check_for_valid_limits(struct io_restrictions *rs)
rs->bounce_pfn = -1;
}
+/*
+ * Impose necessary and sufficient conditions on a devices's table such
+ * that any incoming bio which respects its hardsect_size can be
+ * processed successfully. If it falls across the boundary between
+ * two or more targets, the size of each piece it gets split into must
+ * be compatible with the hardsect_size of the target processing it.
+ */
+static int validate_hardsect_alignment(struct dm_table *table)
+{
+ /*
+ * This function uses arithmetic modulo the hardsect_size
+ * (in units of 512-byte sectors).
+ */
+ unsigned short device_hardsect_size_sects =
+ table->limits.hardsect_size >> SECTOR_SHIFT;
+
+ /*
+ * Offset of the start of the next table entry, mod hardsect_size.
+ */
+ unsigned short next_target_start = 0;
+
+ /*
+ * Given an aligned bio that extends beyond the end of a
+ * target, how many sectors must the next target handle?
+ */
+ unsigned short remaining = 0;
+
+ struct dm_target *uninitialized_var(ti);
+ unsigned i = 0;
+
+ /*
+ * Check each entry in the table in turn.
+ */
+ while (i < dm_table_get_num_targets(table)) {
+ ti = dm_table_get_target(table, i++);
+
+ /*
+ * If the remaining sectors fall entirely within this
+ * table entry are they compatible with its hardsect_size?
+ */
+ if (remaining < ti->len &&
+ remaining & ((ti->limits.hardsect_size >>
+ SECTOR_SHIFT) - 1))
+ break; /* Error */
+
+ next_target_start =
+ (unsigned short) ((next_target_start + ti->len) &
+ (device_hardsect_size_sects - 1));
+ remaining = next_target_start ?
+ device_hardsect_size_sects - next_target_start : 0;
+ }
+
+ if (remaining) {
+ DMWARN("%s: table line %u (start sect %llu len %llu) "
+ "not aligned to hardware sector size %hu",
+ dm_device_name(table->md), i,
+ (unsigned long long) ti->begin,
+ (unsigned long long) ti->len,
+ table->limits.hardsect_size);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
int dm_table_add_target(struct dm_table *t, const char *type,
sector_t start, sector_t len, char *params)
{
@@ -792,6 +883,10 @@ int dm_table_complete(struct dm_table *t)
check_for_valid_limits(&t->limits);
+ r = validate_hardsect_alignment(t);
+ if (r)
+ return r;
+
/* how many indexes will the btree have ? */
leaf_nodes = dm_div_up(t->num_targets, KEYS_PER_NODE);
t->depth = 1 + int_log(leaf_nodes, CHILDREN_PER_NODE);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 8a994be035ba..7b73ebc83207 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -6,7 +6,6 @@
*/
#include "dm.h"
-#include "dm-bio-list.h"
#include "dm-uevent.h"
#include <linux/init.h>
@@ -160,13 +159,16 @@ struct mapped_device {
* freeze/thaw support require holding onto a super block
*/
struct super_block *frozen_sb;
- struct block_device *suspended_bdev;
+ struct block_device *bdev;
/* forced geometry settings */
struct hd_geometry geometry;
/* sysfs handle */
struct kobject kobj;
+
+ /* zero-length barrier that will be cloned and submitted to targets */
+ struct bio barrier_bio;
};
#define MIN_IOS 256
@@ -394,11 +396,6 @@ static void free_io(struct mapped_device *md, struct dm_io *io)
mempool_free(io, md->io_pool);
}
-static struct dm_target_io *alloc_tio(struct mapped_device *md)
-{
- return mempool_alloc(md->tio_pool, GFP_NOIO);
-}
-
static void free_tio(struct mapped_device *md, struct dm_target_io *tio)
{
mempool_free(tio, md->tio_pool);
@@ -539,9 +536,11 @@ static void dec_pending(struct dm_io *io, int error)
* Target requested pushing back the I/O.
*/
spin_lock_irqsave(&md->deferred_lock, flags);
- if (__noflush_suspending(md))
- bio_list_add_head(&md->deferred, io->bio);
- else
+ if (__noflush_suspending(md)) {
+ if (!bio_barrier(io->bio))
+ bio_list_add_head(&md->deferred,
+ io->bio);
+ } else
/* noflush suspend was interrupted. */
io->error = -EIO;
spin_unlock_irqrestore(&md->deferred_lock, flags);
@@ -556,7 +555,8 @@ static void dec_pending(struct dm_io *io, int error)
* a per-device variable for error reporting.
* Note that you can't touch the bio after end_io_acct
*/
- md->barrier_error = io_error;
+ if (!md->barrier_error && io_error != -EOPNOTSUPP)
+ md->barrier_error = io_error;
end_io_acct(io);
} else {
end_io_acct(io);
@@ -637,11 +637,6 @@ static void __map_bio(struct dm_target *ti, struct bio *clone,
sector_t sector;
struct mapped_device *md;
- /*
- * Sanity checks.
- */
- BUG_ON(!clone->bi_size);
-
clone->bi_end_io = clone_endio;
clone->bi_private = tio;
@@ -657,8 +652,7 @@ static void __map_bio(struct dm_target *ti, struct bio *clone,
/* the bio has been remapped so dispatch it */
trace_block_remap(bdev_get_queue(clone->bi_bdev), clone,
- tio->io->bio->bi_bdev->bd_dev,
- clone->bi_sector, sector);
+ tio->io->bio->bi_bdev->bd_dev, sector);
generic_make_request(clone);
} else if (r < 0 || r == DM_MAPIO_REQUEUE) {
@@ -756,6 +750,48 @@ static struct bio *clone_bio(struct bio *bio, sector_t sector,
return clone;
}
+static struct dm_target_io *alloc_tio(struct clone_info *ci,
+ struct dm_target *ti)
+{
+ struct dm_target_io *tio = mempool_alloc(ci->md->tio_pool, GFP_NOIO);
+
+ tio->io = ci->io;
+ tio->ti = ti;
+ memset(&tio->info, 0, sizeof(tio->info));
+
+ return tio;
+}
+
+static void __flush_target(struct clone_info *ci, struct dm_target *ti,
+ unsigned flush_nr)
+{
+ struct dm_target_io *tio = alloc_tio(ci, ti);
+ struct bio *clone;
+
+ tio->info.flush_request = flush_nr;
+
+ clone = bio_alloc_bioset(GFP_NOIO, 0, ci->md->bs);
+ __bio_clone(clone, ci->bio);
+ clone->bi_destructor = dm_bio_destructor;
+
+ __map_bio(ti, clone, tio);
+}
+
+static int __clone_and_map_empty_barrier(struct clone_info *ci)
+{
+ unsigned target_nr = 0, flush_nr;
+ struct dm_target *ti;
+
+ while ((ti = dm_table_get_target(ci->map, target_nr++)))
+ for (flush_nr = 0; flush_nr < ti->num_flush_requests;
+ flush_nr++)
+ __flush_target(ci, ti, flush_nr);
+
+ ci->sector_count = 0;
+
+ return 0;
+}
+
static int __clone_and_map(struct clone_info *ci)
{
struct bio *clone, *bio = ci->bio;
@@ -763,6 +799,9 @@ static int __clone_and_map(struct clone_info *ci)
sector_t len = 0, max;
struct dm_target_io *tio;
+ if (unlikely(bio_empty_barrier(bio)))
+ return __clone_and_map_empty_barrier(ci);
+
ti = dm_table_find_target(ci->map, ci->sector);
if (!dm_target_is_valid(ti))
return -EIO;
@@ -772,10 +811,7 @@ static int __clone_and_map(struct clone_info *ci)
/*
* Allocate a target io object.
*/
- tio = alloc_tio(ci->md);
- tio->io = ci->io;
- tio->ti = ti;
- memset(&tio->info, 0, sizeof(tio->info));
+ tio = alloc_tio(ci, ti);
if (ci->sector_count <= max) {
/*
@@ -831,10 +867,7 @@ static int __clone_and_map(struct clone_info *ci)
max = max_io_len(ci->md, ci->sector, ti);
- tio = alloc_tio(ci->md);
- tio->io = ci->io;
- tio->ti = ti;
- memset(&tio->info, 0, sizeof(tio->info));
+ tio = alloc_tio(ci, ti);
}
len = min(remaining, max);
@@ -869,7 +902,8 @@ static void __split_and_process_bio(struct mapped_device *md, struct bio *bio)
if (!bio_barrier(bio))
bio_io_error(bio);
else
- md->barrier_error = -EIO;
+ if (!md->barrier_error)
+ md->barrier_error = -EIO;
return;
}
@@ -882,6 +916,8 @@ static void __split_and_process_bio(struct mapped_device *md, struct bio *bio)
ci.io->md = md;
ci.sector = bio->bi_sector;
ci.sector_count = bio_sectors(bio);
+ if (unlikely(bio_empty_barrier(bio)))
+ ci.sector_count = 1;
ci.idx = bio->bi_idx;
start_io_acct(ci.io);
@@ -1174,6 +1210,10 @@ static struct mapped_device *alloc_dev(int minor)
if (!md->wq)
goto bad_thread;
+ md->bdev = bdget_disk(md->disk, 0);
+ if (!md->bdev)
+ goto bad_bdev;
+
/* Populate the mapping, nobody knows we exist yet */
spin_lock(&_minor_lock);
old_md = idr_replace(&_minor_idr, md, minor);
@@ -1183,6 +1223,8 @@ static struct mapped_device *alloc_dev(int minor)
return md;
+bad_bdev:
+ destroy_workqueue(md->wq);
bad_thread:
put_disk(md->disk);
bad_disk:
@@ -1208,10 +1250,8 @@ static void free_dev(struct mapped_device *md)
{
int minor = MINOR(disk_devt(md->disk));
- if (md->suspended_bdev) {
- unlock_fs(md);
- bdput(md->suspended_bdev);
- }
+ unlock_fs(md);
+ bdput(md->bdev);
destroy_workqueue(md->wq);
mempool_destroy(md->tio_pool);
mempool_destroy(md->io_pool);
@@ -1253,9 +1293,9 @@ static void __set_size(struct mapped_device *md, sector_t size)
{
set_capacity(md->disk, size);
- mutex_lock(&md->suspended_bdev->bd_inode->i_mutex);
- i_size_write(md->suspended_bdev->bd_inode, (loff_t)size << SECTOR_SHIFT);
- mutex_unlock(&md->suspended_bdev->bd_inode->i_mutex);
+ mutex_lock(&md->bdev->bd_inode->i_mutex);
+ i_size_write(md->bdev->bd_inode, (loff_t)size << SECTOR_SHIFT);
+ mutex_unlock(&md->bdev->bd_inode->i_mutex);
}
static int __bind(struct mapped_device *md, struct dm_table *t)
@@ -1271,8 +1311,7 @@ static int __bind(struct mapped_device *md, struct dm_table *t)
if (size != get_capacity(md->disk))
memset(&md->geometry, 0, sizeof(md->geometry));
- if (md->suspended_bdev)
- __set_size(md, size);
+ __set_size(md, size);
if (!size) {
dm_table_destroy(t);
@@ -1430,34 +1469,36 @@ static int dm_wait_for_completion(struct mapped_device *md, int interruptible)
return r;
}
-static int dm_flush(struct mapped_device *md)
+static void dm_flush(struct mapped_device *md)
{
dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE);
- return 0;
+
+ bio_init(&md->barrier_bio);
+ md->barrier_bio.bi_bdev = md->bdev;
+ md->barrier_bio.bi_rw = WRITE_BARRIER;
+ __split_and_process_bio(md, &md->barrier_bio);
+
+ dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE);
}
static void process_barrier(struct mapped_device *md, struct bio *bio)
{
- int error = dm_flush(md);
+ md->barrier_error = 0;
- if (unlikely(error)) {
- bio_endio(bio, error);
- return;
- }
- if (bio_empty_barrier(bio)) {
- bio_endio(bio, 0);
- return;
- }
+ dm_flush(md);
- __split_and_process_bio(md, bio);
-
- error = dm_flush(md);
-
- if (!error && md->barrier_error)
- error = md->barrier_error;
+ if (!bio_empty_barrier(bio)) {
+ __split_and_process_bio(md, bio);
+ dm_flush(md);
+ }
if (md->barrier_error != DM_ENDIO_REQUEUE)
- bio_endio(bio, error);
+ bio_endio(bio, md->barrier_error);
+ else {
+ spin_lock_irq(&md->deferred_lock);
+ bio_list_add_head(&md->deferred, bio);
+ spin_unlock_irq(&md->deferred_lock);
+ }
}
/*
@@ -1514,11 +1555,6 @@ int dm_swap_table(struct mapped_device *md, struct dm_table *table)
if (!dm_suspended(md))
goto out;
- /* without bdev, the device size cannot be changed */
- if (!md->suspended_bdev)
- if (get_capacity(md->disk) != dm_table_get_size(table))
- goto out;
-
__unbind(md);
r = __bind(md, table);
@@ -1537,7 +1573,7 @@ static int lock_fs(struct mapped_device *md)
WARN_ON(md->frozen_sb);
- md->frozen_sb = freeze_bdev(md->suspended_bdev);
+ md->frozen_sb = freeze_bdev(md->bdev);
if (IS_ERR(md->frozen_sb)) {
r = PTR_ERR(md->frozen_sb);
md->frozen_sb = NULL;
@@ -1546,9 +1582,6 @@ static int lock_fs(struct mapped_device *md)
set_bit(DMF_FROZEN, &md->flags);
- /* don't bdput right now, we don't want the bdev
- * to go away while it is locked.
- */
return 0;
}
@@ -1557,7 +1590,7 @@ static void unlock_fs(struct mapped_device *md)
if (!test_bit(DMF_FROZEN, &md->flags))
return;
- thaw_bdev(md->suspended_bdev, md->frozen_sb);
+ thaw_bdev(md->bdev, md->frozen_sb);
md->frozen_sb = NULL;
clear_bit(DMF_FROZEN, &md->flags);
}
@@ -1595,24 +1628,14 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
/* This does not get reverted if there's an error later. */
dm_table_presuspend_targets(map);
- /* bdget() can stall if the pending I/Os are not flushed */
- if (!noflush) {
- md->suspended_bdev = bdget_disk(md->disk, 0);
- if (!md->suspended_bdev) {
- DMWARN("bdget failed in dm_suspend");
- r = -ENOMEM;
+ /*
+ * Flush I/O to the device. noflush supersedes do_lockfs,
+ * because lock_fs() needs to flush I/Os.
+ */
+ if (!noflush && do_lockfs) {
+ r = lock_fs(md);
+ if (r)
goto out;
- }
-
- /*
- * Flush I/O to the device. noflush supersedes do_lockfs,
- * because lock_fs() needs to flush I/Os.
- */
- if (do_lockfs) {
- r = lock_fs(md);
- if (r)
- goto out;
- }
}
/*
@@ -1669,11 +1692,6 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
set_bit(DMF_SUSPENDED, &md->flags);
out:
- if (r && md->suspended_bdev) {
- bdput(md->suspended_bdev);
- md->suspended_bdev = NULL;
- }
-
dm_table_put(map);
out_unlock:
@@ -1702,11 +1720,6 @@ int dm_resume(struct mapped_device *md)
unlock_fs(md);
- if (md->suspended_bdev) {
- bdput(md->suspended_bdev);
- md->suspended_bdev = NULL;
- }
-
clear_bit(DMF_SUSPENDED, &md->flags);
dm_table_unplug_all(map);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index ed5727c089a9..fccc8343a250 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2017,6 +2017,8 @@ repeat:
clear_bit(MD_CHANGE_PENDING, &mddev->flags);
spin_unlock_irq(&mddev->write_lock);
wake_up(&mddev->sb_wait);
+ if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
+ sysfs_notify(&mddev->kobj, NULL, "sync_completed");
}
@@ -2086,6 +2088,7 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
* -writemostly - clears write_mostly
* blocked - sets the Blocked flag
* -blocked - clears the Blocked flag
+ * insync - sets Insync providing device isn't active
*/
int err = -EINVAL;
if (cmd_match(buf, "faulty") && rdev->mddev->pers) {
@@ -2118,6 +2121,9 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
md_wakeup_thread(rdev->mddev->thread);
err = 0;
+ } else if (cmd_match(buf, "insync") && rdev->raid_disk == -1) {
+ set_bit(In_sync, &rdev->flags);
+ err = 0;
}
if (!err && rdev->sysfs_state)
sysfs_notify_dirent(rdev->sysfs_state);
@@ -2190,7 +2196,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
} else if (rdev->mddev->pers) {
mdk_rdev_t *rdev2;
/* Activating a spare .. or possibly reactivating
- * if we every get bitmaps working here.
+ * if we ever get bitmaps working here.
*/
if (rdev->raid_disk != -1)
@@ -3060,11 +3066,8 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
} else
err = -EBUSY;
spin_unlock_irq(&mddev->write_lock);
- } else {
- mddev->ro = 0;
- mddev->recovery_cp = MaxSector;
- err = do_md_run(mddev);
- }
+ } else
+ err = -EINVAL;
break;
case active:
if (mddev->pers) {
@@ -3482,12 +3485,15 @@ sync_completed_show(mddev_t *mddev, char *page)
{
unsigned long max_sectors, resync;
+ if (!test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
+ return sprintf(page, "none\n");
+
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
max_sectors = mddev->resync_max_sectors;
else
max_sectors = mddev->dev_sectors;
- resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active));
+ resync = mddev->curr_resync_completed;
return sprintf(page, "%lu / %lu\n", resync, max_sectors);
}
@@ -4288,6 +4294,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
{
int err = 0;
struct gendisk *disk = mddev->gendisk;
+ mdk_rdev_t *rdev;
if (atomic_read(&mddev->openers) > is_open) {
printk("md: %s still in use.\n",mdname(mddev));
@@ -4330,6 +4337,13 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
/* tell userspace to handle 'inactive' */
sysfs_notify_dirent(mddev->sysfs_state);
+ list_for_each_entry(rdev, &mddev->disks, same_set)
+ if (rdev->raid_disk >= 0) {
+ char nm[20];
+ sprintf(nm, "rd%d", rdev->raid_disk);
+ sysfs_remove_link(&mddev->kobj, nm);
+ }
+
set_capacity(disk, 0);
mddev->changed = 1;
@@ -4350,7 +4364,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
* Free resources if final stop
*/
if (mode == 0) {
- mdk_rdev_t *rdev;
printk(KERN_INFO "md: %s stopped.\n", mdname(mddev));
@@ -4362,13 +4375,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
}
mddev->bitmap_offset = 0;
- list_for_each_entry(rdev, &mddev->disks, same_set)
- if (rdev->raid_disk >= 0) {
- char nm[20];
- sprintf(nm, "rd%d", rdev->raid_disk);
- sysfs_remove_link(&mddev->kobj, nm);
- }
-
/* make sure all md_delayed_delete calls have finished */
flush_scheduled_work();
@@ -5696,37 +5702,38 @@ static void status_unused(struct seq_file *seq)
static void status_resync(struct seq_file *seq, mddev_t * mddev)
{
- sector_t max_blocks, resync, res;
- unsigned long dt, db, rt;
+ sector_t max_sectors, resync, res;
+ unsigned long dt, db;
+ sector_t rt;
int scale;
unsigned int per_milli;
- resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active))/2;
+ resync = mddev->curr_resync - atomic_read(&mddev->recovery_active);
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
- max_blocks = mddev->resync_max_sectors >> 1;
+ max_sectors = mddev->resync_max_sectors;
else
- max_blocks = mddev->dev_sectors / 2;
+ max_sectors = mddev->dev_sectors;
/*
* Should not happen.
*/
- if (!max_blocks) {
+ if (!max_sectors) {
MD_BUG();
return;
}
/* Pick 'scale' such that (resync>>scale)*1000 will fit
- * in a sector_t, and (max_blocks>>scale) will fit in a
+ * in a sector_t, and (max_sectors>>scale) will fit in a
* u32, as those are the requirements for sector_div.
* Thus 'scale' must be at least 10
*/
scale = 10;
if (sizeof(sector_t) > sizeof(unsigned long)) {
- while ( max_blocks/2 > (1ULL<<(scale+32)))
+ while ( max_sectors/2 > (1ULL<<(scale+32)))
scale++;
}
res = (resync>>scale)*1000;
- sector_div(res, (u32)((max_blocks>>scale)+1));
+ sector_div(res, (u32)((max_sectors>>scale)+1));
per_milli = res;
{
@@ -5747,25 +5754,35 @@ static void status_resync(struct seq_file *seq, mddev_t * mddev)
(test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ?
"resync" : "recovery"))),
per_milli/10, per_milli % 10,
- (unsigned long long) resync,
- (unsigned long long) max_blocks);
+ (unsigned long long) resync/2,
+ (unsigned long long) max_sectors/2);
/*
- * We do not want to overflow, so the order of operands and
- * the * 100 / 100 trick are important. We do a +1 to be
- * safe against division by zero. We only estimate anyway.
- *
* dt: time from mark until now
* db: blocks written from mark until now
* rt: remaining time
+ *
+ * rt is a sector_t, so could be 32bit or 64bit.
+ * So we divide before multiply in case it is 32bit and close
+ * to the limit.
+ * We scale the divisor (db) by 32 to avoid loosing precision
+ * near the end of resync when the number of remaining sectors
+ * is close to 'db'.
+ * We then divide rt by 32 after multiplying by db to compensate.
+ * The '+1' avoids division by zero if db is very small.
*/
dt = ((jiffies - mddev->resync_mark) / HZ);
if (!dt) dt++;
db = (mddev->curr_mark_cnt - atomic_read(&mddev->recovery_active))
- mddev->resync_mark_cnt;
- rt = (dt * ((unsigned long)(max_blocks-resync) / (db/2/100+1)))/100;
- seq_printf(seq, " finish=%lu.%lumin", rt / 60, (rt % 60)/6);
+ rt = max_sectors - resync; /* number of remaining sectors */
+ sector_div(rt, db/32+1);
+ rt *= dt;
+ rt >>= 5;
+
+ seq_printf(seq, " finish=%lu.%lumin", (unsigned long)rt / 60,
+ ((unsigned long)rt % 60)/6);
seq_printf(seq, " speed=%ldK/sec", db/2/dt);
}
@@ -5956,7 +5973,7 @@ static int md_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations md_seq_ops = {
+static const struct seq_operations md_seq_ops = {
.start = md_seq_start,
.next = md_seq_next,
.stop = md_seq_stop,
@@ -6334,18 +6351,13 @@ void md_do_sync(mddev_t *mddev)
sector_t sectors;
skipped = 0;
- if (j >= mddev->resync_max) {
- sysfs_notify(&mddev->kobj, NULL, "sync_completed");
- wait_event(mddev->recovery_wait,
- mddev->resync_max > j
- || kthread_should_stop());
- }
- if (kthread_should_stop())
- goto interrupted;
- if (mddev->curr_resync > mddev->curr_resync_completed &&
- (mddev->curr_resync - mddev->curr_resync_completed)
- > (max_sectors >> 4)) {
+ if ((mddev->curr_resync > mddev->curr_resync_completed &&
+ (mddev->curr_resync - mddev->curr_resync_completed)
+ > (max_sectors >> 4)) ||
+ (j - mddev->curr_resync_completed)*2
+ >= mddev->resync_max - mddev->curr_resync_completed
+ ) {
/* time to update curr_resync_completed */
blk_unplug(mddev->queue);
wait_event(mddev->recovery_wait,
@@ -6353,7 +6365,17 @@ void md_do_sync(mddev_t *mddev)
mddev->curr_resync_completed =
mddev->curr_resync;
set_bit(MD_CHANGE_CLEAN, &mddev->flags);
+ sysfs_notify(&mddev->kobj, NULL, "sync_completed");
}
+
+ if (j >= mddev->resync_max)
+ wait_event(mddev->recovery_wait,
+ mddev->resync_max > j
+ || kthread_should_stop());
+
+ if (kthread_should_stop())
+ goto interrupted;
+
sectors = mddev->pers->sync_request(mddev, j, &skipped,
currspeed < speed_min(mddev));
if (sectors == 0) {
@@ -6461,6 +6483,7 @@ void md_do_sync(mddev_t *mddev)
skip:
mddev->curr_resync = 0;
+ mddev->curr_resync_completed = 0;
mddev->resync_min = 0;
mddev->resync_max = MaxSector;
sysfs_notify(&mddev->kobj, NULL, "sync_completed");
diff --git a/drivers/md/md.h b/drivers/md/md.h
index e9b7f54c24d6..8227ab909d44 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -12,10 +12,17 @@
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#ifndef _MD_K_H
-#define _MD_K_H
-
-#ifdef CONFIG_BLOCK
+#ifndef _MD_MD_H
+#define _MD_MD_H
+
+#include <linux/blkdev.h>
+#include <linux/kobject.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/timer.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
#define MaxSector (~(sector_t)0)
@@ -408,10 +415,6 @@ static inline void safe_put_page(struct page *p)
if (p) put_page(p);
}
-#endif /* CONFIG_BLOCK */
-#endif
-
-
extern int register_md_personality(struct mdk_personality *p);
extern int unregister_md_personality(struct mdk_personality *p);
extern mdk_thread_t * md_register_thread(void (*run) (mddev_t *mddev),
@@ -434,3 +437,5 @@ extern void md_new_event(mddev_t *mddev);
extern int md_allow_write(mddev_t *mddev);
extern void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
extern void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors);
+
+#endif /* _MD_MD_H */
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 274b491a11c1..36df9109cde1 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -35,7 +35,6 @@
#include <linux/blkdev.h>
#include <linux/seq_file.h>
#include "md.h"
-#include "dm-bio-list.h"
#include "raid1.h"
#include "bitmap.h"
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index e293d92641ac..499620afb44b 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -22,7 +22,6 @@
#include <linux/blkdev.h>
#include <linux/seq_file.h>
#include "md.h"
-#include "dm-bio-list.h"
#include "raid10.h"
#include "bitmap.h"
@@ -1810,17 +1809,17 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
r10_bio->sector = sect;
raid10_find_phys(conf, r10_bio);
- /* Need to check if this section will still be
+
+ /* Need to check if the array will still be
* degraded
*/
- for (j=0; j<conf->copies;j++) {
- int d = r10_bio->devs[j].devnum;
- if (conf->mirrors[d].rdev == NULL ||
- test_bit(Faulty, &conf->mirrors[d].rdev->flags)) {
+ for (j=0; j<conf->raid_disks; j++)
+ if (conf->mirrors[j].rdev == NULL ||
+ test_bit(Faulty, &conf->mirrors[j].rdev->flags)) {
still_degraded = 1;
break;
}
- }
+
must_sync = bitmap_start_sync(mddev->bitmap, sect,
&sync_blocks, still_degraded);
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 3bbc6d647044..4616bc3a6e71 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -3845,6 +3845,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
wait_event(conf->wait_for_overlap,
atomic_read(&conf->reshape_stripes)==0);
mddev->reshape_position = conf->reshape_progress;
+ mddev->curr_resync_completed = mddev->curr_resync;
conf->reshape_checkpoint = jiffies;
set_bit(MD_CHANGE_DEVS, &mddev->flags);
md_wakeup_thread(mddev->thread);
@@ -3854,6 +3855,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
conf->reshape_safe = mddev->reshape_position;
spin_unlock_irq(&conf->device_lock);
wake_up(&conf->wait_for_overlap);
+ sysfs_notify(&mddev->kobj, NULL, "sync_completed");
}
if (mddev->delta_disks < 0) {
@@ -3938,11 +3940,13 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
* then we need to write out the superblock.
*/
sector_nr += reshape_sectors;
- if (sector_nr >= mddev->resync_max) {
+ if ((sector_nr - mddev->curr_resync_completed) * 2
+ >= mddev->resync_max - mddev->curr_resync_completed) {
/* Cannot proceed until we've updated the superblock... */
wait_event(conf->wait_for_overlap,
atomic_read(&conf->reshape_stripes) == 0);
mddev->reshape_position = conf->reshape_progress;
+ mddev->curr_resync_completed = mddev->curr_resync;
conf->reshape_checkpoint = jiffies;
set_bit(MD_CHANGE_DEVS, &mddev->flags);
md_wakeup_thread(mddev->thread);
@@ -3953,6 +3957,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
conf->reshape_safe = mddev->reshape_position;
spin_unlock_irq(&conf->device_lock);
wake_up(&conf->wait_for_overlap);
+ sysfs_notify(&mddev->kobj, NULL, "sync_completed");
}
return reshape_sectors;
}
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c
index 53bfc8e42fb9..965d7bd1b76c 100644
--- a/drivers/media/dvb/dvb-usb/af9015.c
+++ b/drivers/media/dvb/dvb-usb/af9015.c
@@ -40,7 +40,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static DEFINE_MUTEX(af9015_usb_mutex);
static struct af9015_config af9015_config;
-static struct dvb_usb_device_properties af9015_properties[2];
+static struct dvb_usb_device_properties af9015_properties[3];
static int af9015_properties_count = ARRAY_SIZE(af9015_properties);
static struct af9013_config af9015_af9013_config[] = {
@@ -1261,7 +1261,9 @@ static struct usb_device_id af9015_usb_table[] = {
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2)},
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3)},
{USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT)},
- {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)},
+/* 20 */{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)},
+ {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A805)},
+ {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU)},
{0},
};
MODULE_DEVICE_TABLE(usb, af9015_usb_table);
@@ -1321,7 +1323,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.i2c_algo = &af9015_i2c_algo,
- .num_device_descs = 9,
+ .num_device_descs = 9, /* max 9 */
.devices = {
{
.name = "Afatech AF9015 DVB-T USB2.0 stick",
@@ -1426,7 +1428,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.i2c_algo = &af9015_i2c_algo,
- .num_device_descs = 9,
+ .num_device_descs = 9, /* max 9 */
.devices = {
{
.name = "Xtensions XD-380",
@@ -1478,7 +1480,75 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.warm_ids = {NULL},
},
}
- }
+ }, {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .download_firmware = af9015_download_firmware,
+ .firmware = "dvb-usb-af9015.fw",
+ .no_reconnect = 1,
+
+ .size_of_priv = sizeof(struct af9015_state), \
+
+ .num_adapters = 2,
+ .adapter = {
+ {
+ .caps = DVB_USB_ADAP_HAS_PID_FILTER |
+ DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+
+ .pid_filter_count = 32,
+ .pid_filter = af9015_pid_filter,
+ .pid_filter_ctrl = af9015_pid_filter_ctrl,
+
+ .frontend_attach =
+ af9015_af9013_frontend_attach,
+ .tuner_attach = af9015_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 6,
+ .endpoint = 0x84,
+ },
+ },
+ {
+ .frontend_attach =
+ af9015_af9013_frontend_attach,
+ .tuner_attach = af9015_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 6,
+ .endpoint = 0x85,
+ .u = {
+ .bulk = {
+ .buffersize =
+ TS_USB20_MAX_PACKET_SIZE,
+ }
+ }
+ },
+ }
+ },
+
+ .identify_state = af9015_identify_state,
+
+ .rc_query = af9015_rc_query,
+ .rc_interval = 150,
+
+ .i2c_algo = &af9015_i2c_algo,
+
+ .num_device_descs = 2, /* max 9 */
+ .devices = {
+ {
+ .name = "AverMedia AVerTV Volar GPS 805 (A805)",
+ .cold_ids = {&af9015_usb_table[21], NULL},
+ .warm_ids = {NULL},
+ },
+ {
+ .name = "Conceptronic USB2.0 DVB-T CTVDIGRCU " \
+ "V3.0",
+ .cold_ids = {&af9015_usb_table[22], NULL},
+ .warm_ids = {NULL},
+ },
+ }
+ },
};
static int af9015_usb_probe(struct usb_interface *intf,
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index 8ddbadf62194..6251b384fb53 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -1493,6 +1493,7 @@ struct usb_device_id dib0700_usb_id_table[] = {
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_TIGER_ATSC_B210) },
{ USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_MC770) },
{ USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT) },
+/* 50 */{ USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT_Dlx) },
{ 0 } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -1692,7 +1693,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
},
},
- .num_device_descs = 11,
+ .num_device_descs = 12,
.devices = {
{ "DiBcom STK7070P reference design",
{ &dib0700_usb_id_table[15], NULL },
@@ -1738,6 +1739,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ &dib0700_usb_id_table[45], NULL },
{ NULL },
},
+ { "Elgato EyeTV Dtt Dlx PD378S",
+ { &dib0700_usb_id_table[50], NULL },
+ { NULL },
+ },
},
.rc_interval = DEFAULT_RC_INTERVAL,
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index f506c74119f3..6a4062d5d0af 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -80,6 +80,7 @@
#define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d
#define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78
#define USB_PID_COMPRO_VIDEOMATE_U500_PC 0x1e80
+#define USB_PID_CONCEPTRONIC_CTVDIGRCU 0xe397
#define USB_PID_CONEXANT_D680_DMB 0x86d6
#define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064
#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065
@@ -171,6 +172,7 @@
#define USB_PID_AVERMEDIA_A309 0xa309
#define USB_PID_AVERMEDIA_A310 0xa310
#define USB_PID_AVERMEDIA_A850 0x850a
+#define USB_PID_AVERMEDIA_A805 0xa805
#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081
@@ -251,5 +253,6 @@
#define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807
#define USB_PID_SONY_PLAYTV 0x0003
#define USB_PID_ELGATO_EYETV_DTT 0x0021
+#define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020
#endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index 2d5352e54dc0..97495154f746 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -223,7 +223,7 @@ struct dvb_usb_device_properties {
int generic_bulk_ctrl_endpoint;
int num_device_descs;
- struct dvb_usb_device_description devices[11];
+ struct dvb_usb_device_description devices[12];
};
/**
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 23e4cffeba38..be967ac09a39 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -35,6 +35,21 @@ config DVB_STB6100
A Silicon tuner from ST used in conjunction with the STB0899
demodulator. Say Y when you want to support this tuner.
+config DVB_STV090x
+ tristate "STV0900/STV0903(A/B) based"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ DVB-S/S2/DSS Multistandard Professional/Broadcast demodulators.
+ Say Y when you want to support these frontends.
+
+config DVB_STV6110x
+ tristate "STV6110/(A) based tuners"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A Silicon tuner that supports DVB-S and DVB-S2 modes
+
comment "DVB-S (satellite) frontends"
depends on DVB_CORE
@@ -506,6 +521,13 @@ config DVB_ISL6421
help
An SEC control chip.
+config DVB_ISL6423
+ tristate "ISL6423 SEC controller"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A SEC controller chip from Intersil
+
config DVB_LGS8GL5
tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)"
depends on DVB_CORE && I2C
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index bc2b00abd106..832473c1e512 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -71,4 +71,6 @@ obj-$(CONFIG_DVB_STB6000) += stb6000.o
obj-$(CONFIG_DVB_S921) += s921.o
obj-$(CONFIG_DVB_STV6110) += stv6110.o
obj-$(CONFIG_DVB_STV0900) += stv0900.o
-
+obj-$(CONFIG_DVB_STV090x) += stv090x.o
+obj-$(CONFIG_DVB_STV6110x) += stv6110x.o
+obj-$(CONFIG_DVB_ISL6423) += isl6423.o
diff --git a/drivers/media/dvb/frontends/isl6423.c b/drivers/media/dvb/frontends/isl6423.c
new file mode 100644
index 000000000000..dca5bebfeeb5
--- /dev/null
+++ b/drivers/media/dvb/frontends/isl6423.c
@@ -0,0 +1,308 @@
+/*
+ Intersil ISL6423 SEC and LNB Power supply controller
+
+ Copyright (C) Manu Abraham <abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "isl6423.h"
+
+static unsigned int verbose;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "Set Verbosity level");
+
+#define FE_ERROR 0
+#define FE_NOTICE 1
+#define FE_INFO 2
+#define FE_DEBUG 3
+#define FE_DEBUGREG 4
+
+#define dprintk(__y, __z, format, arg...) do { \
+ if (__z) { \
+ if ((verbose > FE_ERROR) && (verbose > __y)) \
+ printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \
+ else if ((verbose > FE_NOTICE) && (verbose > __y)) \
+ printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \
+ else if ((verbose > FE_INFO) && (verbose > __y)) \
+ printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \
+ else if ((verbose > FE_DEBUG) && (verbose > __y)) \
+ printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \
+ } else { \
+ if (verbose > __y) \
+ printk(format, ##arg); \
+ } \
+} while (0)
+
+struct isl6423_dev {
+ const struct isl6423_config *config;
+ struct i2c_adapter *i2c;
+
+ u8 reg_3;
+ u8 reg_4;
+
+ unsigned int verbose;
+};
+
+static int isl6423_write(struct isl6423_dev *isl6423, u8 reg)
+{
+ struct i2c_adapter *i2c = isl6423->i2c;
+ u8 addr = isl6423->config->addr;
+ int err = 0;
+
+ struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = &reg, .len = 1 };
+
+ dprintk(FE_DEBUG, 1, "write reg %02X", reg);
+ err = i2c_transfer(i2c, &msg, 1);
+ if (err < 0)
+ goto exit;
+ return 0;
+
+exit:
+ dprintk(FE_ERROR, 1, "I/O error <%d>", err);
+ return err;
+}
+
+static int isl6423_set_modulation(struct dvb_frontend *fe)
+{
+ struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv;
+ const struct isl6423_config *config = isl6423->config;
+ int err = 0;
+ u8 reg_2 = 0;
+
+ reg_2 = 0x01 << 5;
+
+ if (config->mod_extern)
+ reg_2 |= (1 << 3);
+ else
+ reg_2 |= (1 << 4);
+
+ err = isl6423_write(isl6423, reg_2);
+ if (err < 0)
+ goto exit;
+ return 0;
+
+exit:
+ dprintk(FE_ERROR, 1, "I/O error <%d>", err);
+ return err;
+}
+
+static int isl6423_voltage_boost(struct dvb_frontend *fe, long arg)
+{
+ struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv;
+ u8 reg_3 = isl6423->reg_3;
+ u8 reg_4 = isl6423->reg_4;
+ int err = 0;
+
+ if (arg) {
+ /* EN = 1, VSPEN = 1, VBOT = 1 */
+ reg_4 |= (1 << 4);
+ reg_4 |= 0x1;
+ reg_3 |= (1 << 3);
+ } else {
+ /* EN = 1, VSPEN = 1, VBOT = 0 */
+ reg_4 |= (1 << 4);
+ reg_4 &= ~0x1;
+ reg_3 |= (1 << 3);
+ }
+ err = isl6423_write(isl6423, reg_3);
+ if (err < 0)
+ goto exit;
+
+ err = isl6423_write(isl6423, reg_4);
+ if (err < 0)
+ goto exit;
+
+ isl6423->reg_3 = reg_3;
+ isl6423->reg_4 = reg_4;
+
+ return 0;
+exit:
+ dprintk(FE_ERROR, 1, "I/O error <%d>", err);
+ return err;
+}
+
+
+static int isl6423_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage)
+{
+ struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv;
+ u8 reg_3 = isl6423->reg_3;
+ u8 reg_4 = isl6423->reg_4;
+ int err = 0;
+
+ switch (voltage) {
+ case SEC_VOLTAGE_OFF:
+ /* EN = 0 */
+ reg_4 &= ~(1 << 4);
+ break;
+
+ case SEC_VOLTAGE_13:
+ /* EN = 1, VSPEN = 1, VTOP = 0, VBOT = 0 */
+ reg_4 |= (1 << 4);
+ reg_4 &= ~0x3;
+ reg_3 |= (1 << 3);
+ break;
+
+ case SEC_VOLTAGE_18:
+ /* EN = 1, VSPEN = 1, VTOP = 1, VBOT = 0 */
+ reg_4 |= (1 << 4);
+ reg_4 |= 0x2;
+ reg_4 &= ~0x1;
+ reg_3 |= (1 << 3);
+ break;
+
+ default:
+ break;
+ }
+ err = isl6423_write(isl6423, reg_3);
+ if (err < 0)
+ goto exit;
+
+ err = isl6423_write(isl6423, reg_4);
+ if (err < 0)
+ goto exit;
+
+ isl6423->reg_3 = reg_3;
+ isl6423->reg_4 = reg_4;
+
+ return 0;
+exit:
+ dprintk(FE_ERROR, 1, "I/O error <%d>", err);
+ return err;
+}
+
+static int isl6423_set_current(struct dvb_frontend *fe)
+{
+ struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv;
+ u8 reg_3 = isl6423->reg_3;
+ const struct isl6423_config *config = isl6423->config;
+ int err = 0;
+
+ switch (config->current_max) {
+ case SEC_CURRENT_275m:
+ /* 275mA */
+ /* ISELH = 0, ISELL = 0 */
+ reg_3 &= ~0x3;
+ break;
+
+ case SEC_CURRENT_515m:
+ /* 515mA */
+ /* ISELH = 0, ISELL = 1 */
+ reg_3 &= ~0x2;
+ reg_3 |= 0x1;
+ break;
+
+ case SEC_CURRENT_635m:
+ /* 635mA */
+ /* ISELH = 1, ISELL = 0 */
+ reg_3 &= ~0x1;
+ reg_3 |= 0x2;
+ break;
+
+ case SEC_CURRENT_800m:
+ /* 800mA */
+ /* ISELH = 1, ISELL = 1 */
+ reg_3 |= 0x3;
+ break;
+ }
+
+ err = isl6423_write(isl6423, reg_3);
+ if (err < 0)
+ goto exit;
+
+ switch (config->curlim) {
+ case SEC_CURRENT_LIM_ON:
+ /* DCL = 0 */
+ reg_3 &= ~0x10;
+ break;
+
+ case SEC_CURRENT_LIM_OFF:
+ /* DCL = 1 */
+ reg_3 |= 0x10;
+ break;
+ }
+
+ err = isl6423_write(isl6423, reg_3);
+ if (err < 0)
+ goto exit;
+
+ isl6423->reg_3 = reg_3;
+
+ return 0;
+exit:
+ dprintk(FE_ERROR, 1, "I/O error <%d>", err);
+ return err;
+}
+
+static void isl6423_release(struct dvb_frontend *fe)
+{
+ isl6423_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+ kfree(fe->sec_priv);
+ fe->sec_priv = NULL;
+}
+
+struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ const struct isl6423_config *config)
+{
+ struct isl6423_dev *isl6423;
+
+ isl6423 = kzalloc(sizeof(struct isl6423_dev), GFP_KERNEL);
+ if (!isl6423)
+ return NULL;
+
+ isl6423->config = config;
+ isl6423->i2c = i2c;
+ fe->sec_priv = isl6423;
+
+ /* SR3H = 0, SR3M = 1, SR3L = 0 */
+ isl6423->reg_3 = 0x02 << 5;
+ /* SR4H = 0, SR4M = 1, SR4L = 1 */
+ isl6423->reg_4 = 0x03 << 5;
+
+ if (isl6423_set_current(fe))
+ goto exit;
+
+ if (isl6423_set_modulation(fe))
+ goto exit;
+
+ fe->ops.release_sec = isl6423_release;
+ fe->ops.set_voltage = isl6423_set_voltage;
+ fe->ops.enable_high_lnb_voltage = isl6423_voltage_boost;
+ isl6423->verbose = verbose;
+
+ return fe;
+
+exit:
+ kfree(isl6423);
+ fe->sec_priv = NULL;
+ return NULL;
+}
+EXPORT_SYMBOL(isl6423_attach);
+
+MODULE_DESCRIPTION("ISL6423 SEC");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/isl6423.h b/drivers/media/dvb/frontends/isl6423.h
new file mode 100644
index 000000000000..e1a37fba01ca
--- /dev/null
+++ b/drivers/media/dvb/frontends/isl6423.h
@@ -0,0 +1,63 @@
+/*
+ Intersil ISL6423 SEC and LNB Power supply controller
+
+ Copyright (C) Manu Abraham <abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __ISL_6423_H
+#define __ISL_6423_H
+
+#include <linux/dvb/frontend.h>
+
+enum isl6423_current {
+ SEC_CURRENT_275m = 0,
+ SEC_CURRENT_515m,
+ SEC_CURRENT_635m,
+ SEC_CURRENT_800m,
+};
+
+enum isl6423_curlim {
+ SEC_CURRENT_LIM_ON = 1,
+ SEC_CURRENT_LIM_OFF
+};
+
+struct isl6423_config {
+ enum isl6423_current current_max;
+ enum isl6423_curlim curlim;
+ u8 addr;
+ u8 mod_extern;
+};
+
+#if defined(CONFIG_DVB_ISL6423) || (defined(CONFIG_DVB_ISL6423_MODULE) && defined(MODULE))
+
+
+extern struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ const struct isl6423_config *config);
+
+#else
+static inline struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ const struct isl6423_config *config)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+
+#endif /* CONFIG_DVB_ISL6423 */
+
+#endif /* __ISL_6423_H */
diff --git a/drivers/media/dvb/frontends/stv0900_priv.h b/drivers/media/dvb/frontends/stv0900_priv.h
index 762d5af62d7a..67dc8ec634e2 100644
--- a/drivers/media/dvb/frontends/stv0900_priv.h
+++ b/drivers/media/dvb/frontends/stv0900_priv.h
@@ -60,8 +60,6 @@
} \
} while (0)
-#define dmd_choose(a, b) (demod = STV0900_DEMOD_2 ? b : a))
-
static int stvdebug;
#define dprintk(args...) \
diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c
new file mode 100644
index 000000000000..96ef745a2e4e
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv090x.c
@@ -0,0 +1,4299 @@
+/*
+ STV0900/0903 Multistandard Broadcast Frontend driver
+ Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+ Copyright (C) ST Microelectronics
+
+ 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.
+*/
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/mutex.h>
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+#include "stv6110x.h" /* for demodulator internal modes */
+
+#include "stv090x_reg.h"
+#include "stv090x.h"
+#include "stv090x_priv.h"
+
+static unsigned int verbose;
+module_param(verbose, int, 0644);
+
+struct mutex demod_lock;
+
+/* DVBS1 and DSS C/N Lookup table */
+static const struct stv090x_tab stv090x_s1cn_tab[] = {
+ { 0, 8917 }, /* 0.0dB */
+ { 5, 8801 }, /* 0.5dB */
+ { 10, 8667 }, /* 1.0dB */
+ { 15, 8522 }, /* 1.5dB */
+ { 20, 8355 }, /* 2.0dB */
+ { 25, 8175 }, /* 2.5dB */
+ { 30, 7979 }, /* 3.0dB */
+ { 35, 7763 }, /* 3.5dB */
+ { 40, 7530 }, /* 4.0dB */
+ { 45, 7282 }, /* 4.5dB */
+ { 50, 7026 }, /* 5.0dB */
+ { 55, 6781 }, /* 5.5dB */
+ { 60, 6514 }, /* 6.0dB */
+ { 65, 6241 }, /* 6.5dB */
+ { 70, 5965 }, /* 7.0dB */
+ { 75, 5690 }, /* 7.5dB */
+ { 80, 5424 }, /* 8.0dB */
+ { 85, 5161 }, /* 8.5dB */
+ { 90, 4902 }, /* 9.0dB */
+ { 95, 4654 }, /* 9.5dB */
+ { 100, 4417 }, /* 10.0dB */
+ { 105, 4186 }, /* 10.5dB */
+ { 110, 3968 }, /* 11.0dB */
+ { 115, 3757 }, /* 11.5dB */
+ { 120, 3558 }, /* 12.0dB */
+ { 125, 3366 }, /* 12.5dB */
+ { 130, 3185 }, /* 13.0dB */
+ { 135, 3012 }, /* 13.5dB */
+ { 140, 2850 }, /* 14.0dB */
+ { 145, 2698 }, /* 14.5dB */
+ { 150, 2550 }, /* 15.0dB */
+ { 160, 2283 }, /* 16.0dB */
+ { 170, 2042 }, /* 17.0dB */
+ { 180, 1827 }, /* 18.0dB */
+ { 190, 1636 }, /* 19.0dB */
+ { 200, 1466 }, /* 20.0dB */
+ { 210, 1315 }, /* 21.0dB */
+ { 220, 1181 }, /* 22.0dB */
+ { 230, 1064 }, /* 23.0dB */
+ { 240, 960 }, /* 24.0dB */
+ { 250, 869 }, /* 25.0dB */
+ { 260, 792 }, /* 26.0dB */
+ { 270, 724 }, /* 27.0dB */
+ { 280, 665 }, /* 28.0dB */
+ { 290, 616 }, /* 29.0dB */
+ { 300, 573 }, /* 30.0dB */
+ { 310, 537 }, /* 31.0dB */
+ { 320, 507 }, /* 32.0dB */
+ { 330, 483 }, /* 33.0dB */
+ { 400, 398 }, /* 40.0dB */
+ { 450, 381 }, /* 45.0dB */
+ { 500, 377 } /* 50.0dB */
+};
+
+/* DVBS2 C/N Lookup table */
+static const struct stv090x_tab stv090x_s2cn_tab[] = {
+ { -30, 13348 }, /* -3.0dB */
+ { -20, 12640 }, /* -2d.0B */
+ { -10, 11883 }, /* -1.0dB */
+ { 0, 11101 }, /* -0.0dB */
+ { 5, 10718 }, /* 0.5dB */
+ { 10, 10339 }, /* 1.0dB */
+ { 15, 9947 }, /* 1.5dB */
+ { 20, 9552 }, /* 2.0dB */
+ { 25, 9183 }, /* 2.5dB */
+ { 30, 8799 }, /* 3.0dB */
+ { 35, 8422 }, /* 3.5dB */
+ { 40, 8062 }, /* 4.0dB */
+ { 45, 7707 }, /* 4.5dB */
+ { 50, 7353 }, /* 5.0dB */
+ { 55, 7025 }, /* 5.5dB */
+ { 60, 6684 }, /* 6.0dB */
+ { 65, 6331 }, /* 6.5dB */
+ { 70, 6036 }, /* 7.0dB */
+ { 75, 5727 }, /* 7.5dB */
+ { 80, 5437 }, /* 8.0dB */
+ { 85, 5164 }, /* 8.5dB */
+ { 90, 4902 }, /* 9.0dB */
+ { 95, 4653 }, /* 9.5dB */
+ { 100, 4408 }, /* 10.0dB */
+ { 105, 4187 }, /* 10.5dB */
+ { 110, 3961 }, /* 11.0dB */
+ { 115, 3751 }, /* 11.5dB */
+ { 120, 3558 }, /* 12.0dB */
+ { 125, 3368 }, /* 12.5dB */
+ { 130, 3191 }, /* 13.0dB */
+ { 135, 3017 }, /* 13.5dB */
+ { 140, 2862 }, /* 14.0dB */
+ { 145, 2710 }, /* 14.5dB */
+ { 150, 2565 }, /* 15.0dB */
+ { 160, 2300 }, /* 16.0dB */
+ { 170, 2058 }, /* 17.0dB */
+ { 180, 1849 }, /* 18.0dB */
+ { 190, 1663 }, /* 19.0dB */
+ { 200, 1495 }, /* 20.0dB */
+ { 210, 1349 }, /* 21.0dB */
+ { 220, 1222 }, /* 22.0dB */
+ { 230, 1110 }, /* 23.0dB */
+ { 240, 1011 }, /* 24.0dB */
+ { 250, 925 }, /* 25.0dB */
+ { 260, 853 }, /* 26.0dB */
+ { 270, 789 }, /* 27.0dB */
+ { 280, 734 }, /* 28.0dB */
+ { 290, 690 }, /* 29.0dB */
+ { 300, 650 }, /* 30.0dB */
+ { 310, 619 }, /* 31.0dB */
+ { 320, 593 }, /* 32.0dB */
+ { 330, 571 }, /* 33.0dB */
+ { 400, 498 }, /* 40.0dB */
+ { 450, 484 }, /* 45.0dB */
+ { 500, 481 } /* 50.0dB */
+};
+
+/* RF level C/N lookup table */
+static const struct stv090x_tab stv090x_rf_tab[] = {
+ { -5, 0xcaa1 }, /* -5dBm */
+ { -10, 0xc229 }, /* -10dBm */
+ { -15, 0xbb08 }, /* -15dBm */
+ { -20, 0xb4bc }, /* -20dBm */
+ { -25, 0xad5a }, /* -25dBm */
+ { -30, 0xa298 }, /* -30dBm */
+ { -35, 0x98a8 }, /* -35dBm */
+ { -40, 0x8389 }, /* -40dBm */
+ { -45, 0x59be }, /* -45dBm */
+ { -50, 0x3a14 }, /* -50dBm */
+ { -55, 0x2d11 }, /* -55dBm */
+ { -60, 0x210d }, /* -60dBm */
+ { -65, 0xa14f }, /* -65dBm */
+ { -70, 0x07aa } /* -70dBm */
+};
+
+
+static struct stv090x_reg stv0900_initval[] = {
+
+ { STV090x_OUTCFG, 0x00 },
+ { STV090x_MODECFG, 0xff },
+ { STV090x_AGCRF1CFG, 0x11 },
+ { STV090x_AGCRF2CFG, 0x13 },
+ { STV090x_TSGENERAL1X, 0x14 },
+ { STV090x_TSTTNR2, 0x21 },
+ { STV090x_TSTTNR4, 0x21 },
+ { STV090x_P2_DISTXCTL, 0x22 },
+ { STV090x_P2_F22TX, 0xc0 },
+ { STV090x_P2_F22RX, 0xc0 },
+ { STV090x_P2_DISRXCTL, 0x00 },
+ { STV090x_P2_DMDCFGMD, 0xF9 },
+ { STV090x_P2_DEMOD, 0x08 },
+ { STV090x_P2_DMDCFG3, 0xc4 },
+ { STV090x_P2_CARFREQ, 0xed },
+ { STV090x_P2_LDT, 0xd0 },
+ { STV090x_P2_LDT2, 0xb8 },
+ { STV090x_P2_TMGCFG, 0xd2 },
+ { STV090x_P2_TMGTHRISE, 0x20 },
+ { STV090x_P1_TMGCFG, 0xd2 },
+
+ { STV090x_P2_TMGTHFALL, 0x00 },
+ { STV090x_P2_FECSPY, 0x88 },
+ { STV090x_P2_FSPYDATA, 0x3a },
+ { STV090x_P2_FBERCPT4, 0x00 },
+ { STV090x_P2_FSPYBER, 0x10 },
+ { STV090x_P2_ERRCTRL1, 0x35 },
+ { STV090x_P2_ERRCTRL2, 0xc1 },
+ { STV090x_P2_CFRICFG, 0xf8 },
+ { STV090x_P2_NOSCFG, 0x1c },
+ { STV090x_P2_DMDTOM, 0x20 },
+ { STV090x_P2_CORRELMANT, 0x70 },
+ { STV090x_P2_CORRELABS, 0x88 },
+ { STV090x_P2_AGC2O, 0x5b },
+ { STV090x_P2_AGC2REF, 0x38 },
+ { STV090x_P2_CARCFG, 0xe4 },
+ { STV090x_P2_ACLC, 0x1A },
+ { STV090x_P2_BCLC, 0x09 },
+ { STV090x_P2_CARHDR, 0x08 },
+ { STV090x_P2_KREFTMG, 0xc1 },
+ { STV090x_P2_SFRUPRATIO, 0xf0 },
+ { STV090x_P2_SFRLOWRATIO, 0x70 },
+ { STV090x_P2_SFRSTEP, 0x58 },
+ { STV090x_P2_TMGCFG2, 0x01 },
+ { STV090x_P2_CAR2CFG, 0x26 },
+ { STV090x_P2_BCLC2S2Q, 0x86 },
+ { STV090x_P2_BCLC2S28, 0x86 },
+ { STV090x_P2_SMAPCOEF7, 0x77 },
+ { STV090x_P2_SMAPCOEF6, 0x85 },
+ { STV090x_P2_SMAPCOEF5, 0x77 },
+ { STV090x_P2_TSCFGL, 0x20 },
+ { STV090x_P2_DMDCFG2, 0x3b },
+ { STV090x_P2_MODCODLST0, 0xff },
+ { STV090x_P2_MODCODLST1, 0xff },
+ { STV090x_P2_MODCODLST2, 0xff },
+ { STV090x_P2_MODCODLST3, 0xff },
+ { STV090x_P2_MODCODLST4, 0xff },
+ { STV090x_P2_MODCODLST5, 0xff },
+ { STV090x_P2_MODCODLST6, 0xff },
+ { STV090x_P2_MODCODLST7, 0xcc },
+ { STV090x_P2_MODCODLST8, 0xcc },
+ { STV090x_P2_MODCODLST9, 0xcc },
+ { STV090x_P2_MODCODLSTA, 0xcc },
+ { STV090x_P2_MODCODLSTB, 0xcc },
+ { STV090x_P2_MODCODLSTC, 0xcc },
+ { STV090x_P2_MODCODLSTD, 0xcc },
+ { STV090x_P2_MODCODLSTE, 0xcc },
+ { STV090x_P2_MODCODLSTF, 0xcf },
+ { STV090x_P1_DISTXCTL, 0x22 },
+ { STV090x_P1_F22TX, 0xc0 },
+ { STV090x_P1_F22RX, 0xc0 },
+ { STV090x_P1_DISRXCTL, 0x00 },
+ { STV090x_P1_DMDCFGMD, 0xf9 },
+ { STV090x_P1_DEMOD, 0x08 },
+ { STV090x_P1_DMDCFG3, 0xc4 },
+ { STV090x_P1_DMDTOM, 0x20 },
+ { STV090x_P1_CARFREQ, 0xed },
+ { STV090x_P1_LDT, 0xd0 },
+ { STV090x_P1_LDT2, 0xb8 },
+ { STV090x_P1_TMGCFG, 0xd2 },
+ { STV090x_P1_TMGTHRISE, 0x20 },
+ { STV090x_P1_TMGTHFALL, 0x00 },
+ { STV090x_P1_SFRUPRATIO, 0xf0 },
+ { STV090x_P1_SFRLOWRATIO, 0x70 },
+ { STV090x_P1_TSCFGL, 0x20 },
+ { STV090x_P1_FECSPY, 0x88 },
+ { STV090x_P1_FSPYDATA, 0x3a },
+ { STV090x_P1_FBERCPT4, 0x00 },
+ { STV090x_P1_FSPYBER, 0x10 },
+ { STV090x_P1_ERRCTRL1, 0x35 },
+ { STV090x_P1_ERRCTRL2, 0xc1 },
+ { STV090x_P1_CFRICFG, 0xf8 },
+ { STV090x_P1_NOSCFG, 0x1c },
+ { STV090x_P1_CORRELMANT, 0x70 },
+ { STV090x_P1_CORRELABS, 0x88 },
+ { STV090x_P1_AGC2O, 0x5b },
+ { STV090x_P1_AGC2REF, 0x38 },
+ { STV090x_P1_CARCFG, 0xe4 },
+ { STV090x_P1_ACLC, 0x1A },
+ { STV090x_P1_BCLC, 0x09 },
+ { STV090x_P1_CARHDR, 0x08 },
+ { STV090x_P1_KREFTMG, 0xc1 },
+ { STV090x_P1_SFRSTEP, 0x58 },
+ { STV090x_P1_TMGCFG2, 0x01 },
+ { STV090x_P1_CAR2CFG, 0x26 },
+ { STV090x_P1_BCLC2S2Q, 0x86 },
+ { STV090x_P1_BCLC2S28, 0x86 },
+ { STV090x_P1_SMAPCOEF7, 0x77 },
+ { STV090x_P1_SMAPCOEF6, 0x85 },
+ { STV090x_P1_SMAPCOEF5, 0x77 },
+ { STV090x_P1_DMDCFG2, 0x3b },
+ { STV090x_P1_MODCODLST0, 0xff },
+ { STV090x_P1_MODCODLST1, 0xff },
+ { STV090x_P1_MODCODLST2, 0xff },
+ { STV090x_P1_MODCODLST3, 0xff },
+ { STV090x_P1_MODCODLST4, 0xff },
+ { STV090x_P1_MODCODLST5, 0xff },
+ { STV090x_P1_MODCODLST6, 0xff },
+ { STV090x_P1_MODCODLST7, 0xcc },
+ { STV090x_P1_MODCODLST8, 0xcc },
+ { STV090x_P1_MODCODLST9, 0xcc },
+ { STV090x_P1_MODCODLSTA, 0xcc },
+ { STV090x_P1_MODCODLSTB, 0xcc },
+ { STV090x_P1_MODCODLSTC, 0xcc },
+ { STV090x_P1_MODCODLSTD, 0xcc },
+ { STV090x_P1_MODCODLSTE, 0xcc },
+ { STV090x_P1_MODCODLSTF, 0xcf },
+ { STV090x_GENCFG, 0x1d },
+ { STV090x_NBITER_NF4, 0x37 },
+ { STV090x_NBITER_NF5, 0x29 },
+ { STV090x_NBITER_NF6, 0x37 },
+ { STV090x_NBITER_NF7, 0x33 },
+ { STV090x_NBITER_NF8, 0x31 },
+ { STV090x_NBITER_NF9, 0x2f },
+ { STV090x_NBITER_NF10, 0x39 },
+ { STV090x_NBITER_NF11, 0x3a },
+ { STV090x_NBITER_NF12, 0x29 },
+ { STV090x_NBITER_NF13, 0x37 },
+ { STV090x_NBITER_NF14, 0x33 },
+ { STV090x_NBITER_NF15, 0x2f },
+ { STV090x_NBITER_NF16, 0x39 },
+ { STV090x_NBITER_NF17, 0x3a },
+ { STV090x_NBITERNOERR, 0x04 },
+ { STV090x_GAINLLR_NF4, 0x0C },
+ { STV090x_GAINLLR_NF5, 0x0F },
+ { STV090x_GAINLLR_NF6, 0x11 },
+ { STV090x_GAINLLR_NF7, 0x14 },
+ { STV090x_GAINLLR_NF8, 0x17 },
+ { STV090x_GAINLLR_NF9, 0x19 },
+ { STV090x_GAINLLR_NF10, 0x20 },
+ { STV090x_GAINLLR_NF11, 0x21 },
+ { STV090x_GAINLLR_NF12, 0x0D },
+ { STV090x_GAINLLR_NF13, 0x0F },
+ { STV090x_GAINLLR_NF14, 0x13 },
+ { STV090x_GAINLLR_NF15, 0x1A },
+ { STV090x_GAINLLR_NF16, 0x1F },
+ { STV090x_GAINLLR_NF17, 0x21 },
+ { STV090x_RCCFGH, 0x20 },
+ { STV090x_P1_FECM, 0x01 }, /* disable DSS modes */
+ { STV090x_P2_FECM, 0x01 }, /* disable DSS modes */
+ { STV090x_P1_PRVIT, 0x2F }, /* disable PR 6/7 */
+ { STV090x_P2_PRVIT, 0x2F }, /* disable PR 6/7 */
+};
+
+static struct stv090x_reg stv0903_initval[] = {
+ { STV090x_OUTCFG, 0x00 },
+ { STV090x_AGCRF1CFG, 0x11 },
+ { STV090x_STOPCLK1, 0x48 },
+ { STV090x_STOPCLK2, 0x14 },
+ { STV090x_TSTTNR1, 0x27 },
+ { STV090x_TSTTNR2, 0x21 },
+ { STV090x_P1_DISTXCTL, 0x22 },
+ { STV090x_P1_F22TX, 0xc0 },
+ { STV090x_P1_F22RX, 0xc0 },
+ { STV090x_P1_DISRXCTL, 0x00 },
+ { STV090x_P1_DMDCFGMD, 0xF9 },
+ { STV090x_P1_DEMOD, 0x08 },
+ { STV090x_P1_DMDCFG3, 0xc4 },
+ { STV090x_P1_CARFREQ, 0xed },
+ { STV090x_P1_TNRCFG2, 0x82 },
+ { STV090x_P1_LDT, 0xd0 },
+ { STV090x_P1_LDT2, 0xb8 },
+ { STV090x_P1_TMGCFG, 0xd2 },
+ { STV090x_P1_TMGTHRISE, 0x20 },
+ { STV090x_P1_TMGTHFALL, 0x00 },
+ { STV090x_P1_SFRUPRATIO, 0xf0 },
+ { STV090x_P1_SFRLOWRATIO, 0x70 },
+ { STV090x_P1_TSCFGL, 0x20 },
+ { STV090x_P1_FECSPY, 0x88 },
+ { STV090x_P1_FSPYDATA, 0x3a },
+ { STV090x_P1_FBERCPT4, 0x00 },
+ { STV090x_P1_FSPYBER, 0x10 },
+ { STV090x_P1_ERRCTRL1, 0x35 },
+ { STV090x_P1_ERRCTRL2, 0xc1 },
+ { STV090x_P1_CFRICFG, 0xf8 },
+ { STV090x_P1_NOSCFG, 0x1c },
+ { STV090x_P1_DMDTOM, 0x20 },
+ { STV090x_P1_CORRELMANT, 0x70 },
+ { STV090x_P1_CORRELABS, 0x88 },
+ { STV090x_P1_AGC2O, 0x5b },
+ { STV090x_P1_AGC2REF, 0x38 },
+ { STV090x_P1_CARCFG, 0xe4 },
+ { STV090x_P1_ACLC, 0x1A },
+ { STV090x_P1_BCLC, 0x09 },
+ { STV090x_P1_CARHDR, 0x08 },
+ { STV090x_P1_KREFTMG, 0xc1 },
+ { STV090x_P1_SFRSTEP, 0x58 },
+ { STV090x_P1_TMGCFG2, 0x01 },
+ { STV090x_P1_CAR2CFG, 0x26 },
+ { STV090x_P1_BCLC2S2Q, 0x86 },
+ { STV090x_P1_BCLC2S28, 0x86 },
+ { STV090x_P1_SMAPCOEF7, 0x77 },
+ { STV090x_P1_SMAPCOEF6, 0x85 },
+ { STV090x_P1_SMAPCOEF5, 0x77 },
+ { STV090x_P1_DMDCFG2, 0x3b },
+ { STV090x_P1_MODCODLST0, 0xff },
+ { STV090x_P1_MODCODLST1, 0xff },
+ { STV090x_P1_MODCODLST2, 0xff },
+ { STV090x_P1_MODCODLST3, 0xff },
+ { STV090x_P1_MODCODLST4, 0xff },
+ { STV090x_P1_MODCODLST5, 0xff },
+ { STV090x_P1_MODCODLST6, 0xff },
+ { STV090x_P1_MODCODLST7, 0xcc },
+ { STV090x_P1_MODCODLST8, 0xcc },
+ { STV090x_P1_MODCODLST9, 0xcc },
+ { STV090x_P1_MODCODLSTA, 0xcc },
+ { STV090x_P1_MODCODLSTB, 0xcc },
+ { STV090x_P1_MODCODLSTC, 0xcc },
+ { STV090x_P1_MODCODLSTD, 0xcc },
+ { STV090x_P1_MODCODLSTE, 0xcc },
+ { STV090x_P1_MODCODLSTF, 0xcf },
+ { STV090x_GENCFG, 0x1c },
+ { STV090x_NBITER_NF4, 0x37 },
+ { STV090x_NBITER_NF5, 0x29 },
+ { STV090x_NBITER_NF6, 0x37 },
+ { STV090x_NBITER_NF7, 0x33 },
+ { STV090x_NBITER_NF8, 0x31 },
+ { STV090x_NBITER_NF9, 0x2f },
+ { STV090x_NBITER_NF10, 0x39 },
+ { STV090x_NBITER_NF11, 0x3a },
+ { STV090x_NBITER_NF12, 0x29 },
+ { STV090x_NBITER_NF13, 0x37 },
+ { STV090x_NBITER_NF14, 0x33 },
+ { STV090x_NBITER_NF15, 0x2f },
+ { STV090x_NBITER_NF16, 0x39 },
+ { STV090x_NBITER_NF17, 0x3a },
+ { STV090x_NBITERNOERR, 0x04 },
+ { STV090x_GAINLLR_NF4, 0x0C },
+ { STV090x_GAINLLR_NF5, 0x0F },
+ { STV090x_GAINLLR_NF6, 0x11 },
+ { STV090x_GAINLLR_NF7, 0x14 },
+ { STV090x_GAINLLR_NF8, 0x17 },
+ { STV090x_GAINLLR_NF9, 0x19 },
+ { STV090x_GAINLLR_NF10, 0x20 },
+ { STV090x_GAINLLR_NF11, 0x21 },
+ { STV090x_GAINLLR_NF12, 0x0D },
+ { STV090x_GAINLLR_NF13, 0x0F },
+ { STV090x_GAINLLR_NF14, 0x13 },
+ { STV090x_GAINLLR_NF15, 0x1A },
+ { STV090x_GAINLLR_NF16, 0x1F },
+ { STV090x_GAINLLR_NF17, 0x21 },
+ { STV090x_RCCFGH, 0x20 },
+ { STV090x_P1_FECM, 0x01 }, /*disable the DSS mode */
+ { STV090x_P1_PRVIT, 0x2f } /*disable puncture rate 6/7*/
+};
+
+static struct stv090x_reg stv0900_cut20_val[] = {
+
+ { STV090x_P2_DMDCFG3, 0xe8 },
+ { STV090x_P2_DMDCFG4, 0x10 },
+ { STV090x_P2_CARFREQ, 0x38 },
+ { STV090x_P2_CARHDR, 0x20 },
+ { STV090x_P2_KREFTMG, 0x5a },
+ { STV090x_P2_SMAPCOEF7, 0x06 },
+ { STV090x_P2_SMAPCOEF6, 0x00 },
+ { STV090x_P2_SMAPCOEF5, 0x04 },
+ { STV090x_P2_NOSCFG, 0x0c },
+ { STV090x_P1_DMDCFG3, 0xe8 },
+ { STV090x_P1_DMDCFG4, 0x10 },
+ { STV090x_P1_CARFREQ, 0x38 },
+ { STV090x_P1_CARHDR, 0x20 },
+ { STV090x_P1_KREFTMG, 0x5a },
+ { STV090x_P1_SMAPCOEF7, 0x06 },
+ { STV090x_P1_SMAPCOEF6, 0x00 },
+ { STV090x_P1_SMAPCOEF5, 0x04 },
+ { STV090x_P1_NOSCFG, 0x0c },
+ { STV090x_GAINLLR_NF4, 0x21 },
+ { STV090x_GAINLLR_NF5, 0x21 },
+ { STV090x_GAINLLR_NF6, 0x20 },
+ { STV090x_GAINLLR_NF7, 0x1F },
+ { STV090x_GAINLLR_NF8, 0x1E },
+ { STV090x_GAINLLR_NF9, 0x1E },
+ { STV090x_GAINLLR_NF10, 0x1D },
+ { STV090x_GAINLLR_NF11, 0x1B },
+ { STV090x_GAINLLR_NF12, 0x20 },
+ { STV090x_GAINLLR_NF13, 0x20 },
+ { STV090x_GAINLLR_NF14, 0x20 },
+ { STV090x_GAINLLR_NF15, 0x20 },
+ { STV090x_GAINLLR_NF16, 0x20 },
+ { STV090x_GAINLLR_NF17, 0x21 },
+};
+
+static struct stv090x_reg stv0903_cut20_val[] = {
+ { STV090x_P1_DMDCFG3, 0xe8 },
+ { STV090x_P1_DMDCFG4, 0x10 },
+ { STV090x_P1_CARFREQ, 0x38 },
+ { STV090x_P1_CARHDR, 0x20 },
+ { STV090x_P1_KREFTMG, 0x5a },
+ { STV090x_P1_SMAPCOEF7, 0x06 },
+ { STV090x_P1_SMAPCOEF6, 0x00 },
+ { STV090x_P1_SMAPCOEF5, 0x04 },
+ { STV090x_P1_NOSCFG, 0x0c },
+ { STV090x_GAINLLR_NF4, 0x21 },
+ { STV090x_GAINLLR_NF5, 0x21 },
+ { STV090x_GAINLLR_NF6, 0x20 },
+ { STV090x_GAINLLR_NF7, 0x1F },
+ { STV090x_GAINLLR_NF8, 0x1E },
+ { STV090x_GAINLLR_NF9, 0x1E },
+ { STV090x_GAINLLR_NF10, 0x1D },
+ { STV090x_GAINLLR_NF11, 0x1B },
+ { STV090x_GAINLLR_NF12, 0x20 },
+ { STV090x_GAINLLR_NF13, 0x20 },
+ { STV090x_GAINLLR_NF14, 0x20 },
+ { STV090x_GAINLLR_NF15, 0x20 },
+ { STV090x_GAINLLR_NF16, 0x20 },
+ { STV090x_GAINLLR_NF17, 0x21 }
+};
+
+/* Cut 2.0 Long Frame Tracking CR loop */
+static struct stv090x_long_frame_crloop stv090x_s2_crl_cut20[] = {
+ /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
+ { STV090x_QPSK_12, 0x1f, 0x3f, 0x1e, 0x3f, 0x3d, 0x1f, 0x3d, 0x3e, 0x3d, 0x1e },
+ { STV090x_QPSK_35, 0x2f, 0x3f, 0x2e, 0x2f, 0x3d, 0x0f, 0x0e, 0x2e, 0x3d, 0x0e },
+ { STV090x_QPSK_23, 0x2f, 0x3f, 0x2e, 0x2f, 0x0e, 0x0f, 0x0e, 0x1e, 0x3d, 0x3d },
+ { STV090x_QPSK_34, 0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
+ { STV090x_QPSK_45, 0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
+ { STV090x_QPSK_56, 0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
+ { STV090x_QPSK_89, 0x3f, 0x3f, 0x3e, 0x1f, 0x1e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
+ { STV090x_QPSK_910, 0x3f, 0x3f, 0x3e, 0x1f, 0x1e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
+ { STV090x_8PSK_35, 0x3c, 0x3e, 0x1c, 0x2e, 0x0c, 0x1e, 0x2b, 0x2d, 0x1b, 0x1d },
+ { STV090x_8PSK_23, 0x1d, 0x3e, 0x3c, 0x2e, 0x2c, 0x1e, 0x0c, 0x2d, 0x2b, 0x1d },
+ { STV090x_8PSK_34, 0x0e, 0x3e, 0x3d, 0x2e, 0x0d, 0x1e, 0x2c, 0x2d, 0x0c, 0x1d },
+ { STV090x_8PSK_56, 0x2e, 0x3e, 0x1e, 0x2e, 0x2d, 0x1e, 0x3c, 0x2d, 0x2c, 0x1d },
+ { STV090x_8PSK_89, 0x3e, 0x3e, 0x1e, 0x2e, 0x3d, 0x1e, 0x0d, 0x2d, 0x3c, 0x1d },
+ { STV090x_8PSK_910, 0x3e, 0x3e, 0x1e, 0x2e, 0x3d, 0x1e, 0x1d, 0x2d, 0x0d, 0x1d }
+};
+
+/* Cut 3.0 Long Frame Tracking CR loop */
+static struct stv090x_long_frame_crloop stv090x_s2_crl_cut30[] = {
+ /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
+ { STV090x_QPSK_12, 0x3c, 0x2c, 0x0c, 0x2c, 0x1b, 0x2c, 0x1b, 0x1c, 0x0b, 0x3b },
+ { STV090x_QPSK_35, 0x0d, 0x0d, 0x0c, 0x0d, 0x1b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b },
+ { STV090x_QPSK_23, 0x1d, 0x0d, 0x0c, 0x1d, 0x2b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b },
+ { STV090x_QPSK_34, 0x1d, 0x1d, 0x0c, 0x1d, 0x2b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b },
+ { STV090x_QPSK_45, 0x2d, 0x1d, 0x1c, 0x1d, 0x2b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b },
+ { STV090x_QPSK_56, 0x2d, 0x1d, 0x1c, 0x1d, 0x2b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b },
+ { STV090x_QPSK_89, 0x3d, 0x2d, 0x1c, 0x1d, 0x3b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b },
+ { STV090x_QPSK_910, 0x3d, 0x2d, 0x1c, 0x1d, 0x3b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b },
+ { STV090x_8PSK_35, 0x39, 0x29, 0x39, 0x19, 0x19, 0x19, 0x19, 0x19, 0x09, 0x19 },
+ { STV090x_8PSK_23, 0x2a, 0x39, 0x1a, 0x0a, 0x39, 0x0a, 0x29, 0x39, 0x29, 0x0a },
+ { STV090x_8PSK_34, 0x2b, 0x3a, 0x1b, 0x1b, 0x3a, 0x1b, 0x1a, 0x0b, 0x1a, 0x3a },
+ { STV090x_8PSK_56, 0x0c, 0x1b, 0x3b, 0x3b, 0x1b, 0x3b, 0x3a, 0x3b, 0x3a, 0x1b },
+ { STV090x_8PSK_89, 0x0d, 0x3c, 0x2c, 0x2c, 0x2b, 0x0c, 0x0b, 0x3b, 0x0b, 0x1b },
+ { STV090x_8PSK_910, 0x0d, 0x0d, 0x2c, 0x3c, 0x3b, 0x1c, 0x0b, 0x3b, 0x0b, 0x1b }
+};
+
+/* Cut 2.0 Long Frame Tracking CR Loop */
+static struct stv090x_long_frame_crloop stv090x_s2_apsk_crl_cut20[] = {
+ /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
+ { STV090x_16APSK_23, 0x0c, 0x0c, 0x0c, 0x0c, 0x1d, 0x0c, 0x3c, 0x0c, 0x2c, 0x0c },
+ { STV090x_16APSK_34, 0x0c, 0x0c, 0x0c, 0x0c, 0x0e, 0x0c, 0x2d, 0x0c, 0x1d, 0x0c },
+ { STV090x_16APSK_45, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x0c, 0x3d, 0x0c, 0x2d, 0x0c },
+ { STV090x_16APSK_56, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x0c, 0x3d, 0x0c, 0x2d, 0x0c },
+ { STV090x_16APSK_89, 0x0c, 0x0c, 0x0c, 0x0c, 0x2e, 0x0c, 0x0e, 0x0c, 0x3d, 0x0c },
+ { STV090x_16APSK_910, 0x0c, 0x0c, 0x0c, 0x0c, 0x2e, 0x0c, 0x0e, 0x0c, 0x3d, 0x0c },
+ { STV090x_32APSK_34, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c },
+ { STV090x_32APSK_45, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c },
+ { STV090x_32APSK_56, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c },
+ { STV090x_32APSK_89, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c },
+ { STV090x_32APSK_910, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }
+};
+
+/* Cut 3.0 Long Frame Tracking CR Loop */
+static struct stv090x_long_frame_crloop stv090x_s2_apsk_crl_cut30[] = {
+ /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
+ { STV090x_16APSK_23, 0x0a, 0x0a, 0x0a, 0x0a, 0x1a, 0x0a, 0x3a, 0x0a, 0x2a, 0x0a },
+ { STV090x_16APSK_34, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0a, 0x3b, 0x0a, 0x1b, 0x0a },
+ { STV090x_16APSK_45, 0x0a, 0x0a, 0x0a, 0x0a, 0x1b, 0x0a, 0x3b, 0x0a, 0x2b, 0x0a },
+ { STV090x_16APSK_56, 0x0a, 0x0a, 0x0a, 0x0a, 0x1b, 0x0a, 0x3b, 0x0a, 0x2b, 0x0a },
+ { STV090x_16APSK_89, 0x0a, 0x0a, 0x0a, 0x0a, 0x2b, 0x0a, 0x0c, 0x0a, 0x3b, 0x0a },
+ { STV090x_16APSK_910, 0x0a, 0x0a, 0x0a, 0x0a, 0x2b, 0x0a, 0x0c, 0x0a, 0x3b, 0x0a },
+ { STV090x_32APSK_34, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a },
+ { STV090x_32APSK_45, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a },
+ { STV090x_32APSK_56, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a },
+ { STV090x_32APSK_89, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a },
+ { STV090x_32APSK_910, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a }
+};
+
+static struct stv090x_long_frame_crloop stv090x_s2_lowqpsk_crl_cut20[] = {
+ /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
+ { STV090x_QPSK_14, 0x0f, 0x3f, 0x0e, 0x3f, 0x2d, 0x2f, 0x2d, 0x1f, 0x3d, 0x3e },
+ { STV090x_QPSK_13, 0x0f, 0x3f, 0x0e, 0x3f, 0x2d, 0x2f, 0x3d, 0x0f, 0x3d, 0x2e },
+ { STV090x_QPSK_25, 0x1f, 0x3f, 0x1e, 0x3f, 0x3d, 0x1f, 0x3d, 0x3e, 0x3d, 0x2e }
+};
+
+static struct stv090x_long_frame_crloop stv090x_s2_lowqpsk_crl_cut30[] = {
+ /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
+ { STV090x_QPSK_14, 0x0c, 0x3c, 0x0b, 0x3c, 0x2a, 0x2c, 0x2a, 0x1c, 0x3a, 0x3b },
+ { STV090x_QPSK_13, 0x0c, 0x3c, 0x0b, 0x3c, 0x2a, 0x2c, 0x3a, 0x0c, 0x3a, 0x2b },
+ { STV090x_QPSK_25, 0x1c, 0x3c, 0x1b, 0x3c, 0x3a, 0x1c, 0x3a, 0x3b, 0x3a, 0x2b }
+};
+
+/* Cut 2.0 Short Frame Tracking CR Loop */
+static struct stv090x_short_frame_crloop stv090x_s2_short_crl_cut20[] = {
+ /* MODCOD 2M 5M 10M 20M 30M */
+ { STV090x_QPSK, 0x2f, 0x2e, 0x0e, 0x0e, 0x3d },
+ { STV090x_8PSK, 0x3e, 0x0e, 0x2d, 0x0d, 0x3c },
+ { STV090x_16APSK, 0x1e, 0x1e, 0x1e, 0x3d, 0x2d },
+ { STV090x_32APSK, 0x1e, 0x1e, 0x1e, 0x3d, 0x2d }
+};
+
+/* Cut 3.0 Short Frame Tracking CR Loop */
+static struct stv090x_short_frame_crloop stv090x_s2_short_crl_cut30[] = {
+ /* MODCOD 2M 5M 10M 20M 30M */
+ { STV090x_QPSK, 0x2C, 0x2B, 0x0B, 0x0B, 0x3A },
+ { STV090x_8PSK, 0x3B, 0x0B, 0x2A, 0x0A, 0x39 },
+ { STV090x_16APSK, 0x1B, 0x1B, 0x1B, 0x3A, 0x2A },
+ { STV090x_32APSK, 0x1B, 0x1B, 0x1B, 0x3A, 0x2A }
+};
+
+static inline s32 comp2(s32 __x, s32 __width)
+{
+ if (__width == 32)
+ return __x;
+ else
+ return (__x >= (1 << (__width - 1))) ? (__x - (1 << __width)) : __x;
+}
+
+static int stv090x_read_reg(struct stv090x_state *state, unsigned int reg)
+{
+ const struct stv090x_config *config = state->config;
+ int ret;
+
+ u8 b0[] = { reg >> 8, reg & 0xff };
+ u8 buf;
+
+ struct i2c_msg msg[] = {
+ { .addr = config->address, .flags = 0, .buf = b0, .len = 2 },
+ { .addr = config->address, .flags = I2C_M_RD, .buf = &buf, .len = 1 }
+ };
+
+ ret = i2c_transfer(state->i2c, msg, 2);
+ if (ret != 2) {
+ if (ret != -ERESTARTSYS)
+ dprintk(FE_ERROR, 1,
+ "Read error, Reg=[0x%02x], Status=%d",
+ reg, ret);
+
+ return ret < 0 ? ret : -EREMOTEIO;
+ }
+ if (unlikely(*state->verbose >= FE_DEBUGREG))
+ dprintk(FE_ERROR, 1, "Reg=[0x%02x], data=%02x",
+ reg, buf);
+
+ return (unsigned int) buf;
+}
+
+static int stv090x_write_regs(struct stv090x_state *state, unsigned int reg, u8 *data, u32 count)
+{
+ const struct stv090x_config *config = state->config;
+ int ret;
+ u8 buf[2 + count];
+ struct i2c_msg i2c_msg = { .addr = config->address, .flags = 0, .buf = buf, .len = 2 + count };
+
+ buf[0] = reg >> 8;
+ buf[1] = reg & 0xff;
+ memcpy(&buf[2], data, count);
+
+ if (unlikely(*state->verbose >= FE_DEBUGREG)) {
+ int i;
+
+ printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg);
+ for (i = 0; i < count; i++)
+ printk(" %02x", data[i]);
+ printk("\n");
+ }
+
+ ret = i2c_transfer(state->i2c, &i2c_msg, 1);
+ if (ret != 1) {
+ if (ret != -ERESTARTSYS)
+ dprintk(FE_ERROR, 1, "Reg=[0x%04x], Data=[0x%02x ...], Count=%u, Status=%d",
+ reg, data[0], count, ret);
+ return ret < 0 ? ret : -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+static int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 data)
+{
+ return stv090x_write_regs(state, reg, &data, 1);
+}
+
+static int stv090x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+ struct stv090x_state *state = fe->demodulator_priv;
+ u32 reg;
+
+ reg = STV090x_READ_DEMOD(state, I2CRPT);
+ if (enable) {
+ dprintk(FE_DEBUG, 1, "Enable Gate");
+ STV090x_SETFIELD_Px(reg, I2CT_ON_FIELD, 1);
+ if (STV090x_WRITE_DEMOD(state, I2CRPT, reg) < 0)
+ goto err;
+
+ } else {
+ dprintk(FE_DEBUG, 1, "Disable Gate");
+ STV090x_SETFIELD_Px(reg, I2CT_ON_FIELD, 0);
+ if ((STV090x_WRITE_DEMOD(state, I2CRPT, reg)) < 0)
+ goto err;
+ }
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static void stv090x_get_lock_tmg(struct stv090x_state *state)
+{
+ switch (state->algo) {
+ case STV090x_BLIND_SEARCH:
+ dprintk(FE_DEBUG, 1, "Blind Search");
+ if (state->srate <= 1500000) { /*10Msps< SR <=15Msps*/
+ state->DemodTimeout = 1500;
+ state->FecTimeout = 400;
+ } else if (state->srate <= 5000000) { /*10Msps< SR <=15Msps*/
+ state->DemodTimeout = 1000;
+ state->FecTimeout = 300;
+ } else { /*SR >20Msps*/
+ state->DemodTimeout = 700;
+ state->FecTimeout = 100;
+ }
+ break;
+
+ case STV090x_COLD_SEARCH:
+ case STV090x_WARM_SEARCH:
+ default:
+ dprintk(FE_DEBUG, 1, "Normal Search");
+ if (state->srate <= 1000000) { /*SR <=1Msps*/
+ state->DemodTimeout = 4500;
+ state->FecTimeout = 1700;
+ } else if (state->srate <= 2000000) { /*1Msps < SR <= 2Msps */
+ state->DemodTimeout = 2500;
+ state->FecTimeout = 1100;
+ } else if (state->srate <= 5000000) { /*2Msps < SR <= 5Msps */
+ state->DemodTimeout = 1000;
+ state->FecTimeout = 550;
+ } else if (state->srate <= 10000000) { /*5Msps < SR <= 10Msps */
+ state->DemodTimeout = 700;
+ state->FecTimeout = 250;
+ } else if (state->srate <= 20000000) { /*10Msps < SR <= 20Msps */
+ state->DemodTimeout = 400;
+ state->FecTimeout = 130;
+ } else { /*SR >20Msps*/
+ state->DemodTimeout = 300;
+ state->FecTimeout = 100;
+ }
+ break;
+ }
+
+ if (state->algo == STV090x_WARM_SEARCH)
+ state->DemodTimeout /= 2;
+}
+
+static int stv090x_set_srate(struct stv090x_state *state, u32 srate)
+{
+ u32 sym;
+
+ if (srate > 60000000) {
+ sym = (srate << 4); /* SR * 2^16 / master_clk */
+ sym /= (state->mclk >> 12);
+ } else if (srate > 6000000) {
+ sym = (srate << 6);
+ sym /= (state->mclk >> 10);
+ } else {
+ sym = (srate << 9);
+ sym /= (state->mclk >> 7);
+ }
+
+ if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0x7f) < 0) /* MSB */
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, SFRINIT0, (sym & 0xff)) < 0) /* LSB */
+ goto err;
+
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_set_max_srate(struct stv090x_state *state, u32 clk, u32 srate)
+{
+ u32 sym;
+
+ srate = 105 * (srate / 100);
+ if (srate > 60000000) {
+ sym = (srate << 4); /* SR * 2^16 / master_clk */
+ sym /= (state->mclk >> 12);
+ } else if (srate > 6000000) {
+ sym = (srate << 6);
+ sym /= (state->mclk >> 10);
+ } else {
+ sym = (srate << 9);
+ sym /= (state->mclk >> 7);
+ }
+
+ if (sym < 0x7fff) {
+ if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) /* MSB */
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) /* LSB */
+ goto err;
+ } else {
+ if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x7f) < 0) /* MSB */
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xff) < 0) /* LSB */
+ goto err;
+ }
+
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_set_min_srate(struct stv090x_state *state, u32 clk, u32 srate)
+{
+ u32 sym;
+
+ srate = 95 * (srate / 100);
+ if (srate > 60000000) {
+ sym = (srate << 4); /* SR * 2^16 / master_clk */
+ sym /= (state->mclk >> 12);
+ } else if (srate > 6000000) {
+ sym = (srate << 6);
+ sym /= (state->mclk >> 10);
+ } else {
+ sym = (srate << 9);
+ sym /= (state->mclk >> 7);
+ }
+
+ if (STV090x_WRITE_DEMOD(state, SFRLOW1, ((sym >> 8) & 0xff)) < 0) /* MSB */
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, SFRLOW0, (sym & 0xff)) < 0) /* LSB */
+ goto err;
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static u32 stv090x_car_width(u32 srate, enum stv090x_rolloff rolloff)
+{
+ u32 ro;
+
+ switch (rolloff) {
+ case STV090x_RO_20:
+ ro = 20;
+ break;
+ case STV090x_RO_25:
+ ro = 25;
+ break;
+ case STV090x_RO_35:
+ default:
+ ro = 35;
+ break;
+ }
+
+ return srate + (srate * ro) / 100;
+}
+
+static int stv090x_set_vit_thacq(struct stv090x_state *state)
+{
+ if (STV090x_WRITE_DEMOD(state, VTH12, 0x96) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, VTH23, 0x64) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, VTH34, 0x36) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, VTH56, 0x23) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, VTH67, 0x1e) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, VTH78, 0x19) < 0)
+ goto err;
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_set_vit_thtracq(struct stv090x_state *state)
+{
+ if (STV090x_WRITE_DEMOD(state, VTH12, 0xd0) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, VTH23, 0x7d) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, VTH34, 0x53) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, VTH56, 0x2f) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, VTH67, 0x24) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, VTH78, 0x1f) < 0)
+ goto err;
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_set_viterbi(struct stv090x_state *state)
+{
+ switch (state->search_mode) {
+ case STV090x_SEARCH_AUTO:
+ if (STV090x_WRITE_DEMOD(state, FECM, 0x10) < 0) /* DVB-S and DVB-S2 */
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, PRVIT, 0x3f) < 0) /* all puncture rate */
+ goto err;
+ break;
+ case STV090x_SEARCH_DVBS1:
+ if (STV090x_WRITE_DEMOD(state, FECM, 0x00) < 0) /* disable DSS */
+ goto err;
+ switch (state->fec) {
+ case STV090x_PR12:
+ if (STV090x_WRITE_DEMOD(state, PRVIT, 0x01) < 0)
+ goto err;
+ break;
+
+ case STV090x_PR23:
+ if (STV090x_WRITE_DEMOD(state, PRVIT, 0x02) < 0)
+ goto err;
+ break;
+
+ case STV090x_PR34:
+ if (STV090x_WRITE_DEMOD(state, PRVIT, 0x04) < 0)
+ goto err;
+ break;
+
+ case STV090x_PR56:
+ if (STV090x_WRITE_DEMOD(state, PRVIT, 0x08) < 0)
+ goto err;
+ break;
+
+ case STV090x_PR78:
+ if (STV090x_WRITE_DEMOD(state, PRVIT, 0x20) < 0)
+ goto err;
+ break;
+
+ default:
+ if (STV090x_WRITE_DEMOD(state, PRVIT, 0x2f) < 0) /* all */
+ goto err;
+ break;
+ }
+ break;
+ case STV090x_SEARCH_DSS:
+ if (STV090x_WRITE_DEMOD(state, FECM, 0x80) < 0)
+ goto err;
+ switch (state->fec) {
+ case STV090x_PR12:
+ if (STV090x_WRITE_DEMOD(state, PRVIT, 0x01) < 0)
+ goto err;
+ break;
+
+ case STV090x_PR23:
+ if (STV090x_WRITE_DEMOD(state, PRVIT, 0x02) < 0)
+ goto err;
+ break;
+
+ case STV090x_PR67:
+ if (STV090x_WRITE_DEMOD(state, PRVIT, 0x10) < 0)
+ goto err;
+ break;
+
+ default:
+ if (STV090x_WRITE_DEMOD(state, PRVIT, 0x13) < 0) /* 1/2, 2/3, 6/7 */
+ goto err;
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_stop_modcod(struct stv090x_state *state)
+{
+ if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xff) < 0)
+ goto err;
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_activate_modcod(struct stv090x_state *state)
+{
+ if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xfc) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xcc) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xcc) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xcc) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xcc) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xcc) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xcc) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xcc) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xcc) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xcc) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xcc) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xcc) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xcc) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xcc) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xcf) < 0)
+ goto err;
+
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_activate_modcod_single(struct stv090x_state *state)
+{
+
+ if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xf0) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0x00) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0x00) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0x00) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0x00) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0x00) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0x00) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0x00) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0x00) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0x00) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0x00) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0x00) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0x00) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0x00) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0x0f) < 0)
+ goto err;
+
+ return 0;
+
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_vitclk_ctl(struct stv090x_state *state, int enable)
+{
+ u32 reg;
+
+ switch (state->demod) {
+ case STV090x_DEMODULATOR_0:
+ mutex_lock(&demod_lock);
+ reg = stv090x_read_reg(state, STV090x_STOPCLK2);
+ STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, enable);
+ if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
+ goto err;
+ mutex_unlock(&demod_lock);
+ break;
+
+ case STV090x_DEMODULATOR_1:
+ mutex_lock(&demod_lock);
+ reg = stv090x_read_reg(state, STV090x_STOPCLK2);
+ STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, enable);
+ if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
+ goto err;
+ mutex_unlock(&demod_lock);
+ break;
+
+ default:
+ dprintk(FE_ERROR, 1, "Wrong demodulator!");
+ break;
+ }
+ return 0;
+err:
+ mutex_unlock(&demod_lock);
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_dvbs_track_crl(struct stv090x_state *state)
+{
+ if (state->dev_ver >= 0x30) {
+ /* Set ACLC BCLC optimised value vs SR */
+ if (state->srate >= 15000000) {
+ if (STV090x_WRITE_DEMOD(state, ACLC, 0x2b) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, BCLC, 0x1a) < 0)
+ goto err;
+ } else if ((state->srate >= 7000000) && (15000000 > state->srate)) {
+ if (STV090x_WRITE_DEMOD(state, ACLC, 0x0c) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, BCLC, 0x1b) < 0)
+ goto err;
+ } else if (state->srate < 7000000) {
+ if (STV090x_WRITE_DEMOD(state, ACLC, 0x2c) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, BCLC, 0x1c) < 0)
+ goto err;
+ }
+
+ } else {
+ /* Cut 2.0 */
+ if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0)
+ goto err;
+ }
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_delivery_search(struct stv090x_state *state)
+{
+ u32 reg;
+
+ switch (state->search_mode) {
+ case STV090x_SEARCH_DVBS1:
+ case STV090x_SEARCH_DSS:
+ reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+ STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
+ STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
+ if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+ goto err;
+
+ /* Activate Viterbi decoder in legacy search,
+ * do not use FRESVIT1, might impact VITERBI2
+ */
+ if (stv090x_vitclk_ctl(state, 0) < 0)
+ goto err;
+
+ if (stv090x_dvbs_track_crl(state) < 0)
+ goto err;
+
+ if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x22) < 0) /* disable DVB-S2 */
+ goto err;
+
+ if (stv090x_set_vit_thacq(state) < 0)
+ goto err;
+ if (stv090x_set_viterbi(state) < 0)
+ goto err;
+ break;
+
+ case STV090x_SEARCH_DVBS2:
+ reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+ STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0);
+ STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
+ if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+ goto err;
+ STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
+ STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
+ if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+ goto err;
+
+ if (stv090x_vitclk_ctl(state, 1) < 0)
+ goto err;
+
+ if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0) /* stop DVB-S CR loop */
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0)
+ goto err;
+
+ if (state->dev_ver <= 0x20) {
+ /* enable S2 carrier loop */
+ if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0)
+ goto err;
+ } else {
+ /* > Cut 3: Stop carrier 3 */
+ if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x66) < 0)
+ goto err;
+ }
+
+ if (state->demod_mode != STV090x_SINGLE) {
+ /* Cut 2: enable link during search */
+ if (stv090x_activate_modcod(state) < 0)
+ goto err;
+ } else {
+ /* Single demodulator
+ * Authorize SHORT and LONG frames,
+ * QPSK, 8PSK, 16APSK and 32APSK
+ */
+ if (stv090x_activate_modcod_single(state) < 0)
+ goto err;
+ }
+
+ break;
+
+ case STV090x_SEARCH_AUTO:
+ default:
+ /* enable DVB-S2 and DVB-S2 in Auto MODE */
+ reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+ STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
+ STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
+ if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+ goto err;
+
+ if (stv090x_vitclk_ctl(state, 0) < 0)
+ goto err;
+
+ if (stv090x_dvbs_track_crl(state) < 0)
+ goto err;
+
+ if (state->dev_ver <= 0x20) {
+ /* enable S2 carrier loop */
+ if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0)
+ goto err;
+ } else {
+ /* > Cut 3: Stop carrier 3 */
+ if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x66) < 0)
+ goto err;
+ }
+
+ if (state->demod_mode != STV090x_SINGLE) {
+ /* Cut 2: enable link during search */
+ if (stv090x_activate_modcod(state) < 0)
+ goto err;
+ } else {
+ /* Single demodulator
+ * Authorize SHORT and LONG frames,
+ * QPSK, 8PSK, 16APSK and 32APSK
+ */
+ if (stv090x_activate_modcod_single(state) < 0)
+ goto err;
+ }
+
+ if (state->srate >= 2000000) {
+ /* Srate >= 2MSPS, Viterbi threshold to acquire */
+ if (stv090x_set_vit_thacq(state) < 0)
+ goto err;
+ } else {
+ /* Srate < 2MSPS, Reset Viterbi thresholdto track
+ * and then re-acquire
+ */
+ if (stv090x_set_vit_thtracq(state) < 0)
+ goto err;
+ }
+
+ if (stv090x_set_viterbi(state) < 0)
+ goto err;
+ break;
+ }
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_start_search(struct stv090x_state *state)
+{
+ u32 reg, freq_abs;
+ s16 freq;
+
+ /* Reset demodulator */
+ reg = STV090x_READ_DEMOD(state, DMDISTATE);
+ STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x1f);
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0)
+ goto err;
+
+ if (state->dev_ver <= 0x20) {
+ if (state->srate <= 5000000) {
+ if (STV090x_WRITE_DEMOD(state, CARCFG, 0x44) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CFRUP1, 0x0f) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CFRUP1, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CFRLOW1, 0xf0) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CFRLOW0, 0x00) < 0)
+ goto err;
+
+ /*enlarge the timing bandwith for Low SR*/
+ if (STV090x_WRITE_DEMOD(state, RTCS2, 0x68) < 0)
+ goto err;
+ } else {
+ /* If the symbol rate is >5 Msps
+ Set The carrier search up and low to auto mode */
+ if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0)
+ goto err;
+ /*reduce the timing bandwith for high SR*/
+ if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0)
+ goto err;
+ }
+ } else {
+ /* >= Cut 3 */
+ if (state->srate <= 5000000) {
+ /* enlarge the timing bandwith for Low SR */
+ STV090x_WRITE_DEMOD(state, RTCS2, 0x68);
+ } else {
+ /* reduce timing bandwith for high SR */
+ STV090x_WRITE_DEMOD(state, RTCS2, 0x44);
+ }
+
+ /* Set CFR min and max to manual mode */
+ STV090x_WRITE_DEMOD(state, CARCFG, 0x46);
+
+ if (state->algo == STV090x_WARM_SEARCH) {
+ /* WARM Start
+ * CFR min = -1MHz,
+ * CFR max = +1MHz
+ */
+ freq_abs = 1000 << 16;
+ freq_abs /= (state->mclk / 1000);
+ freq = (s16) freq_abs;
+ } else {
+ /* COLD Start
+ * CFR min =- (SearchRange / 2 + 600KHz)
+ * CFR max = +(SearchRange / 2 + 600KHz)
+ * (600KHz for the tuner step size)
+ */
+ freq_abs = (state->search_range / 2000) + 600;
+ freq_abs = freq_abs << 16;
+ freq_abs /= (state->mclk / 1000);
+ freq = (s16) freq_abs;
+ }
+
+ if (STV090x_WRITE_DEMOD(state, CFRUP1, MSB(freq)) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CFRUP1, LSB(freq)) < 0)
+ goto err;
+
+ freq *= -1;
+
+ if (STV090x_WRITE_DEMOD(state, CFRLOW1, MSB(freq)) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CFRLOW0, LSB(freq)) < 0)
+ goto err;
+
+ }
+
+ if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0) < 0)
+ goto err;
+
+ if (state->dev_ver >= 0x20) {
+ if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0)
+ goto err;
+
+ if ((state->search_mode == STV090x_DVBS1) ||
+ (state->search_mode == STV090x_DSS) ||
+ (state->search_mode == STV090x_SEARCH_AUTO)) {
+
+ if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x82) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x00) < 0)
+ goto err;
+ }
+ }
+
+ if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x00) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0xe0) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0xc0) < 0)
+ goto err;
+
+ reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+ STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 0);
+ STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0);
+ if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+ goto err;
+ reg = STV090x_READ_DEMOD(state, DMDCFG2);
+ STV090x_SETFIELD_Px(reg, S1S2_SEQUENTIAL_FIELD, 0x0);
+ if (STV090x_WRITE_DEMOD(state, DMDCFG2, reg) < 0)
+ goto err;
+
+ if (state->dev_ver >= 0x20) {
+ /*Frequency offset detector setting*/
+ if (state->srate < 2000000) {
+ if (state->dev_ver <= 0x20) {
+ /* Cut 2 */
+ if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x39) < 0)
+ goto err;
+ } else {
+ /* Cut 2 */
+ if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x89) < 0)
+ goto err;
+ }
+ if (STV090x_WRITE_DEMOD(state, CARHDR, 0x40) < 0)
+ goto err;
+ }
+
+ if (state->srate < 10000000) {
+ if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x4c) < 0)
+ goto err;
+ } else {
+ if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x4b) < 0)
+ goto err;
+ }
+ } else {
+ if (state->srate < 10000000) {
+ if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xef) < 0)
+ goto err;
+ } else {
+ if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xed) < 0)
+ goto err;
+ }
+ }
+
+ switch (state->algo) {
+ case STV090x_WARM_SEARCH:
+ /* The symbol rate and the exact
+ * carrier Frequency are known
+ */
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0)
+ goto err;
+ break;
+
+ case STV090x_COLD_SEARCH:
+ /* The symbol rate is known */
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
+ goto err;
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_get_agc2_min_level(struct stv090x_state *state)
+{
+ u32 agc2_min = 0, agc2 = 0, freq_init, freq_step, reg;
+ s32 i, j, steps, dir;
+
+ if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
+ goto err;
+ reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+ STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 1);
+ STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 1);
+ if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+ goto err;
+
+ if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x83) < 0) /* SR = 65 Msps Max */
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xc0) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x82) < 0) /* SR= 400 ksps Min */
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, SFRLOW0, 0xa0) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x00) < 0) /* stop acq @ coarse carrier state */
+ goto err;
+ if (stv090x_set_srate(state, 1000000) < 0)
+ goto err;
+
+ steps = -1 + state->search_range / 1000000;
+ steps /= 2;
+ steps = (2 * steps) + 1;
+ if (steps < 0)
+ steps = 1;
+
+ dir = 1;
+ freq_step = (1000000 * 256) / (state->mclk / 256);
+ freq_init = 0;
+
+ for (i = 0; i < steps; i++) {
+ if (dir > 0)
+ freq_init = freq_init + (freq_step * i);
+ else
+ freq_init = freq_init - (freq_step * i);
+
+ dir = -1;
+
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Demod RESET */
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CFRINIT1, (freq_init >> 8) & 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CFRINIT0, freq_init & 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x58) < 0) /* Demod RESET */
+ goto err;
+ msleep(10);
+ for (j = 0; j < 10; j++) {
+ agc2 += STV090x_READ_DEMOD(state, AGC2I1) << 8;
+ agc2 |= STV090x_READ_DEMOD(state, AGC2I0);
+ }
+ agc2 /= 10;
+ agc2_min = 0xffff;
+ if (agc2 < 0xffff)
+ agc2_min = agc2;
+ }
+
+ return agc2_min;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static u32 stv090x_get_srate(struct stv090x_state *state, u32 clk)
+{
+ u8 r3, r2, r1, r0;
+ s32 srate, int_1, int_2, tmp_1, tmp_2;
+
+ r3 = STV090x_READ_DEMOD(state, SFR3);
+ r2 = STV090x_READ_DEMOD(state, SFR2);
+ r1 = STV090x_READ_DEMOD(state, SFR1);
+ r0 = STV090x_READ_DEMOD(state, SFR0);
+
+ srate = ((r3 << 24) | (r2 << 16) | (r1 << 8) | r0);
+
+ int_1 = clk >> 16;
+ int_2 = srate >> 16;
+
+ tmp_1 = clk % 0x10000;
+ tmp_2 = srate % 0x10000;
+
+ srate = (int_1 * int_2) +
+ ((int_1 * tmp_2) >> 16) +
+ ((int_2 * tmp_1) >> 16);
+
+ return srate;
+}
+
+static u32 stv090x_srate_srch_coarse(struct stv090x_state *state)
+{
+ struct dvb_frontend *fe = &state->frontend;
+
+ int tmg_lock = 0, i;
+ s32 tmg_cpt = 0, dir = 1, steps, cur_step = 0, freq;
+ u32 srate_coarse = 0, agc2 = 0, car_step = 1200, reg;
+
+ reg = STV090x_READ_DEMOD(state, DMDISTATE);
+ STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x1f); /* Demod RESET */
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, TMGCFG, 0x12) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0xf0) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0xe0) < 0)
+ goto err;
+ reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+ STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 1);
+ STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 1);
+ if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+ goto err;
+
+ if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x83) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xc0) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x82) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, SFRLOW0, 0xa0) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x00) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x60) < 0)
+ goto err;
+
+ if (state->dev_ver >= 0x30) {
+ if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x99) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x95) < 0)
+ goto err;
+
+ } else if (state->dev_ver >= 0x20) {
+ if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x6a) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x95) < 0)
+ goto err;
+ }
+
+ if (state->srate <= 2000000)
+ car_step = 1000;
+ else if (state->srate <= 5000000)
+ car_step = 2000;
+ else if (state->srate <= 12000000)
+ car_step = 3000;
+ else
+ car_step = 5000;
+
+ steps = -1 + ((state->search_range / 1000) / car_step);
+ steps /= 2;
+ steps = (2 * steps) + 1;
+ if (steps < 0)
+ steps = 1;
+ else if (steps > 10) {
+ steps = 11;
+ car_step = (state->search_range / 1000) / 10;
+ }
+ cur_step = 0;
+ dir = 1;
+ freq = state->frequency;
+
+ while ((!tmg_lock) && (cur_step < steps)) {
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5f) < 0) /* Demod RESET */
+ goto err;
+ reg = STV090x_READ_DEMOD(state, DMDISTATE);
+ STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x00); /* trigger acquisition */
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0)
+ goto err;
+ msleep(50);
+ for (i = 0; i < 10; i++) {
+ reg = STV090x_READ_DEMOD(state, DSTATUS);
+ if (STV090x_GETFIELD_Px(reg, TMGLOCK_QUALITY_FIELD) >= 2)
+ tmg_cpt++;
+ agc2 += STV090x_READ_DEMOD(state, AGC2I1) << 8;
+ agc2 |= STV090x_READ_DEMOD(state, AGC2I0);
+ }
+ agc2 /= 10;
+ srate_coarse = stv090x_get_srate(state, state->mclk);
+ cur_step++;
+ dir *= -1;
+ if ((tmg_cpt >= 5) && (agc2 < 0x1f00) && (srate_coarse < 55000000) && (srate_coarse > 850000))
+ tmg_lock = 1;
+ else if (cur_step < steps) {
+ if (dir > 0)
+ freq += cur_step * car_step;
+ else
+ freq -= cur_step * car_step;
+
+ /* Setup tuner */
+ if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+ goto err;
+
+ if (state->config->tuner_set_frequency) {
+ if (state->config->tuner_set_frequency(fe, state->frequency) < 0)
+ goto err;
+ }
+
+ if (state->config->tuner_set_bandwidth) {
+ if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
+ goto err;
+ }
+
+ if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+ goto err;
+
+ msleep(50);
+
+ if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+ goto err;
+
+ if (state->config->tuner_get_status) {
+ if (state->config->tuner_get_status(fe, &reg) < 0)
+ goto err;
+ }
+
+ if (reg)
+ dprintk(FE_DEBUG, 1, "Tuner phase locked");
+ else
+ dprintk(FE_DEBUG, 1, "Tuner unlocked");
+
+ if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+ goto err;
+
+ }
+ }
+ if (!tmg_lock)
+ srate_coarse = 0;
+ else
+ srate_coarse = stv090x_get_srate(state, state->mclk);
+
+ return srate_coarse;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static u32 stv090x_srate_srch_fine(struct stv090x_state *state)
+{
+ u32 srate_coarse, freq_coarse, sym, reg;
+
+ srate_coarse = stv090x_get_srate(state, state->mclk);
+ freq_coarse = STV090x_READ_DEMOD(state, CFR2) << 8;
+ freq_coarse |= STV090x_READ_DEMOD(state, CFR1);
+ sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */
+
+ if (sym < state->srate)
+ srate_coarse = 0;
+ else {
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) /* Demod RESET */
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0x01) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0x20) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0x00) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, TMGCFG, 0xd2) < 0)
+ goto err;
+ reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+ STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00);
+ if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+ goto err;
+
+ if (state->dev_ver >= 0x30) {
+ if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x79) < 0)
+ goto err;
+ } else if (state->dev_ver >= 0x20) {
+ if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0)
+ goto err;
+ }
+
+ if (srate_coarse > 3000000) {
+ sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */
+ sym = (sym / 1000) * 65536;
+ sym /= (state->mclk / 1000);
+ if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0)
+ goto err;
+ sym = 10 * (srate_coarse / 13); /* SFRLOW = SFR - 30% */
+ sym = (sym / 1000) * 65536;
+ sym /= (state->mclk / 1000);
+ if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0)
+ goto err;
+ sym = (srate_coarse / 1000) * 65536;
+ sym /= (state->mclk / 1000);
+ if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0)
+ goto err;
+ } else {
+ sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */
+ sym = (sym / 100) * 65536;
+ sym /= (state->mclk / 100);
+ if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0)
+ goto err;
+ sym = 10 * (srate_coarse / 14); /* SFRLOW = SFR - 30% */
+ sym = (sym / 100) * 65536;
+ sym /= (state->mclk / 100);
+ if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0)
+ goto err;
+ sym = (srate_coarse / 100) * 65536;
+ sym /= (state->mclk / 100);
+ if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0)
+ goto err;
+ }
+ if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x20) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CFRINIT1, (freq_coarse >> 8) & 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CFRINIT0, freq_coarse & 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0) /* trigger acquisition */
+ goto err;
+ }
+
+ return srate_coarse;
+
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_get_dmdlock(struct stv090x_state *state, s32 timeout)
+{
+ s32 timer = 0, lock = 0;
+ u32 reg;
+ u8 stat;
+
+ while ((timer < timeout) && (!lock)) {
+ reg = STV090x_READ_DEMOD(state, DMDSTATE);
+ stat = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD);
+
+ switch (stat) {
+ case 0: /* searching */
+ case 1: /* first PLH detected */
+ default:
+ dprintk(FE_DEBUG, 1, "Demodulator searching ..");
+ lock = 0;
+ break;
+ case 2: /* DVB-S2 mode */
+ case 3: /* DVB-S1/legacy mode */
+ reg = STV090x_READ_DEMOD(state, DSTATUS);
+ lock = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD);
+ break;
+ }
+
+ if (!lock)
+ msleep(10);
+ else
+ dprintk(FE_DEBUG, 1, "Demodulator acquired LOCK");
+
+ timer += 10;
+ }
+ return lock;
+}
+
+static int stv090x_blind_search(struct stv090x_state *state)
+{
+ u32 agc2, reg, srate_coarse;
+ s32 timeout_dmd = 500, cpt_fail, agc2_ovflw, i;
+ u8 k_ref, k_max, k_min;
+ int coarse_fail, lock;
+
+ k_max = 120;
+ k_min = 30;
+
+ agc2 = stv090x_get_agc2_min_level(state);
+
+ if (agc2 > STV090x_SEARCH_AGC2_TH(state->dev_ver)) {
+ lock = 0;
+ } else {
+
+ if (state->dev_ver <= 0x20) {
+ if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0)
+ goto err;
+ } else {
+ /* > Cut 3 */
+ if (STV090x_WRITE_DEMOD(state, CARCFG, 0x06) < 0)
+ goto err;
+ }
+
+ if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0)
+ goto err;
+
+ if (state->dev_ver >= 0x20) {
+ if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x82) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x00) < 0) /* set viterbi hysteresis */
+ goto err;
+ }
+
+ k_ref = k_max;
+ do {
+ if (STV090x_WRITE_DEMOD(state, KREFTMG, k_ref) < 0)
+ goto err;
+ if (stv090x_srate_srch_coarse(state) != 0) {
+ srate_coarse = stv090x_srate_srch_fine(state);
+ if (srate_coarse != 0) {
+ stv090x_get_lock_tmg(state);
+ lock = stv090x_get_dmdlock(state, timeout_dmd);
+ } else {
+ lock = 0;
+ }
+ } else {
+ cpt_fail = 0;
+ agc2_ovflw = 0;
+ for (i = 0; i < 10; i++) {
+ agc2 = STV090x_READ_DEMOD(state, AGC2I1) << 8;
+ agc2 |= STV090x_READ_DEMOD(state, AGC2I0);
+ if (agc2 >= 0xff00)
+ agc2_ovflw++;
+ reg = STV090x_READ_DEMOD(state, DSTATUS2);
+ if ((STV090x_GETFIELD_Px(reg, CFR_OVERFLOW_FIELD) == 0x01) &&
+ (STV090x_GETFIELD_Px(reg, DEMOD_DELOCK_FIELD) == 0x01))
+
+ cpt_fail++;
+ }
+ if ((cpt_fail > 7) || (agc2_ovflw > 7))
+ coarse_fail = 1;
+
+ lock = 0;
+ }
+ k_ref -= 30;
+ } while ((k_ref >= k_min) && (!lock) && (!coarse_fail));
+ }
+
+ return lock;
+
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_chk_tmg(struct stv090x_state *state)
+{
+ u32 reg;
+ s32 tmg_cpt = 0, i;
+ u8 freq, tmg_thh, tmg_thl;
+ int tmg_lock;
+
+ freq = STV090x_READ_DEMOD(state, CARFREQ);
+ tmg_thh = STV090x_READ_DEMOD(state, TMGTHRISE);
+ tmg_thl = STV090x_READ_DEMOD(state, TMGTHFALL);
+ if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0x20) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0x00) < 0)
+ goto err;
+
+ reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+ STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00); /* stop carrier offset search */
+ if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, RTC, 0x80) < 0)
+ goto err;
+
+ if (STV090x_WRITE_DEMOD(state, RTCS2, 0x40) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x00) < 0)
+ goto err;
+
+ if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0) /* set car ofset to 0 */
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x65) < 0)
+ goto err;
+
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) /* trigger acquisition */
+ goto err;
+ msleep(10);
+
+ for (i = 0; i < 10; i++) {
+ reg = STV090x_READ_DEMOD(state, DSTATUS);
+ if (STV090x_GETFIELD_Px(reg, TMGLOCK_QUALITY_FIELD) >= 2)
+ tmg_cpt++;
+ msleep(1);
+ }
+ if (tmg_cpt >= 3)
+ tmg_lock = 1;
+
+ if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, RTC, 0x88) < 0) /* DVB-S1 timing */
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, RTCS2, 0x68) < 0) /* DVB-S2 timing */
+ goto err;
+
+ if (STV090x_WRITE_DEMOD(state, CARFREQ, freq) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, TMGTHRISE, tmg_thh) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, TMGTHFALL, tmg_thl) < 0)
+ goto err;
+
+ return tmg_lock;
+
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd)
+{
+ struct dvb_frontend *fe = &state->frontend;
+
+ u32 reg;
+ s32 car_step, steps, cur_step, dir, freq, timeout_lock;
+ int lock = 0;
+
+ if (state->srate >= 10000000)
+ timeout_lock = timeout_dmd / 3;
+ else
+ timeout_lock = timeout_dmd / 2;
+
+ lock = stv090x_get_dmdlock(state, timeout_lock); /* cold start wait */
+ if (!lock) {
+ if (state->srate >= 10000000) {
+ if (stv090x_chk_tmg(state)) {
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
+ goto err;
+ lock = stv090x_get_dmdlock(state, timeout_dmd);
+ } else {
+ lock = 0;
+ }
+ } else {
+ if (state->srate <= 4000000)
+ car_step = 1000;
+ else if (state->srate <= 7000000)
+ car_step = 2000;
+ else if (state->srate <= 10000000)
+ car_step = 3000;
+ else
+ car_step = 5000;
+
+ steps = (state->search_range / 1000) / car_step;
+ steps /= 2;
+ steps = 2 * (steps + 1);
+ if (steps < 0)
+ steps = 2;
+ else if (steps > 12)
+ steps = 12;
+
+ cur_step = 1;
+ dir = 1;
+
+ if (!lock) {
+ freq = state->frequency;
+ state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + state->srate;
+ while ((cur_step <= steps) && (!lock)) {
+ if (dir > 0)
+ freq += cur_step * car_step;
+ else
+ freq -= cur_step * car_step;
+
+ /* Setup tuner */
+ if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+ goto err;
+
+ if (state->config->tuner_set_frequency) {
+ if (state->config->tuner_set_frequency(fe, state->frequency) < 0)
+ goto err;
+ }
+
+ if (state->config->tuner_set_bandwidth) {
+ if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
+ goto err;
+ }
+
+ if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+ goto err;
+
+ msleep(50);
+
+ if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+ goto err;
+
+ if (state->config->tuner_get_status) {
+ if (state->config->tuner_get_status(fe, &reg) < 0)
+ goto err;
+ }
+
+ if (reg)
+ dprintk(FE_DEBUG, 1, "Tuner phase locked");
+ else
+ dprintk(FE_DEBUG, 1, "Tuner unlocked");
+
+ if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+ goto err;
+
+ STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c);
+ if (state->delsys == STV090x_DVBS2) {
+ reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+ STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0);
+ STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
+ if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+ goto err;
+ STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
+ STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
+ if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+ goto err;
+ }
+ if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
+ goto err;
+ lock = stv090x_get_dmdlock(state, (timeout_dmd / 3));
+
+ dir *= -1;
+ cur_step++;
+ }
+ }
+ }
+ }
+
+ return lock;
+
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_get_loop_params(struct stv090x_state *state, s32 *freq_inc, s32 *timeout_sw, s32 *steps)
+{
+ s32 timeout, inc, steps_max, srate, car_max;
+
+ srate = state->srate;
+ car_max = state->search_range / 1000;
+ car_max += car_max / 10;
+ car_max = 65536 * (car_max / 2);
+ car_max /= (state->mclk / 1000);
+
+ if (car_max > 0x4000)
+ car_max = 0x4000 ; /* maxcarrier should be<= +-1/4 Mclk */
+
+ inc = srate;
+ inc /= state->mclk / 1000;
+ inc *= 256;
+ inc *= 256;
+ inc /= 1000;
+
+ switch (state->search_mode) {
+ case STV090x_SEARCH_DVBS1:
+ case STV090x_SEARCH_DSS:
+ inc *= 3; /* freq step = 3% of srate */
+ timeout = 20;
+ break;
+
+ case STV090x_SEARCH_DVBS2:
+ inc *= 4;
+ timeout = 25;
+ break;
+
+ case STV090x_SEARCH_AUTO:
+ default:
+ inc *= 3;
+ timeout = 25;
+ break;
+ }
+ inc /= 100;
+ if ((inc > car_max) || (inc < 0))
+ inc = car_max / 2; /* increment <= 1/8 Mclk */
+
+ timeout *= 27500; /* 27.5 Msps reference */
+ if (srate > 0)
+ timeout /= (srate / 1000);
+
+ if ((timeout > 100) || (timeout < 0))
+ timeout = 100;
+
+ steps_max = (car_max / inc) + 1; /* min steps = 3 */
+ if ((steps_max > 100) || (steps_max < 0)) {
+ steps_max = 100; /* max steps <= 100 */
+ inc = car_max / steps_max;
+ }
+ *freq_inc = inc;
+ *timeout_sw = timeout;
+ *steps = steps_max;
+
+ return 0;
+}
+
+static int stv090x_chk_signal(struct stv090x_state *state)
+{
+ s32 offst_car, agc2, car_max;
+ int no_signal;
+
+ offst_car = STV090x_READ_DEMOD(state, CFR2) << 8;
+ offst_car |= STV090x_READ_DEMOD(state, CFR1);
+ offst_car = comp2(offst_car, 16);
+
+ agc2 = STV090x_READ_DEMOD(state, AGC2I1) << 8;
+ agc2 |= STV090x_READ_DEMOD(state, AGC2I0);
+ car_max = state->search_range / 1000;
+
+ car_max += (car_max / 10); /* 10% margin */
+ car_max = (65536 * car_max / 2);
+ car_max /= state->mclk / 1000;
+
+ if (car_max > 0x4000)
+ car_max = 0x4000;
+
+ if ((agc2 > 0x2000) || (offst_car > 2 * car_max) || (offst_car < -2 * car_max)) {
+ no_signal = 1;
+ dprintk(FE_DEBUG, 1, "No Signal");
+ } else {
+ no_signal = 0;
+ dprintk(FE_DEBUG, 1, "Found Signal");
+ }
+
+ return no_signal;
+}
+
+static int stv090x_search_car_loop(struct stv090x_state *state, s32 inc, s32 timeout, int zigzag, s32 steps_max)
+{
+ int no_signal, lock = 0;
+ s32 cpt_step = 0, offst_freq, car_max;
+ u32 reg;
+
+ car_max = state->search_range / 1000;
+ car_max += (car_max / 10);
+ car_max = (65536 * car_max / 2);
+ car_max /= (state->mclk / 1000);
+ if (car_max > 0x4000)
+ car_max = 0x4000;
+
+ if (zigzag)
+ offst_freq = 0;
+ else
+ offst_freq = -car_max + inc;
+
+ do {
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CFRINIT1, ((offst_freq / 256) & 0xff)) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CFRINIT0, offst_freq & 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0)
+ goto err;
+
+ reg = STV090x_READ_DEMOD(state, PDELCTRL1);
+ STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x1); /* stop DVB-S2 packet delin */
+ if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
+ goto err;
+
+ if (zigzag) {
+ if (offst_freq >= 0)
+ offst_freq = -offst_freq - 2 * inc;
+ else
+ offst_freq = -offst_freq;
+ } else {
+ offst_freq += 2 * inc;
+ }
+
+ cpt_step++;
+
+ lock = stv090x_get_dmdlock(state, timeout);
+ no_signal = stv090x_chk_signal(state);
+
+ } while ((!lock) &&
+ (!no_signal) &&
+ ((offst_freq - inc) < car_max) &&
+ ((offst_freq + inc) > -car_max) &&
+ (cpt_step < steps_max));
+
+ reg = STV090x_READ_DEMOD(state, PDELCTRL1);
+ STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0);
+ if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
+ goto err;
+
+ return lock;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_sw_algo(struct stv090x_state *state)
+{
+ int no_signal, zigzag, lock = 0;
+ u32 reg;
+
+ s32 dvbs2_fly_wheel;
+ s32 inc, timeout_step, trials, steps_max;
+
+ /* get params */
+ stv090x_get_loop_params(state, &inc, &timeout_step, &steps_max);
+
+ switch (state->search_mode) {
+ case STV090x_SEARCH_DVBS1:
+ case STV090x_SEARCH_DSS:
+ /* accelerate the frequency detector */
+ if (state->dev_ver >= 0x20) {
+ if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3B) < 0)
+ goto err;
+ }
+
+ if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x49) < 0)
+ goto err;
+ zigzag = 0;
+ break;
+
+ case STV090x_SEARCH_DVBS2:
+ if (state->dev_ver >= 0x20) {
+ if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0)
+ goto err;
+ }
+
+ if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x89) < 0)
+ goto err;
+ zigzag = 1;
+ break;
+
+ case STV090x_SEARCH_AUTO:
+ default:
+ /* accelerate the frequency detector */
+ if (state->dev_ver >= 0x20) {
+ if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3b) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0)
+ goto err;
+ }
+
+ if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0xc9) < 0)
+ goto err;
+ zigzag = 0;
+ break;
+ }
+
+ trials = 0;
+ do {
+ lock = stv090x_search_car_loop(state, inc, timeout_step, zigzag, steps_max);
+ no_signal = stv090x_chk_signal(state);
+ trials++;
+
+ /*run the SW search 2 times maximum*/
+ if (lock || no_signal || (trials == 2)) {
+ /*Check if the demod is not losing lock in DVBS2*/
+ if (state->dev_ver >= 0x20) {
+ if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0)
+ goto err;
+ }
+
+ reg = STV090x_READ_DEMOD(state, DMDSTATE);
+ if ((lock) && (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == STV090x_DVBS2)) {
+ /*Check if the demod is not losing lock in DVBS2*/
+ msleep(timeout_step);
+ reg = STV090x_READ_DEMOD(state, DMDFLYW);
+ dvbs2_fly_wheel = STV090x_GETFIELD_Px(reg, FLYWHEEL_CPT_FIELD);
+ if (dvbs2_fly_wheel < 0xd) { /*if correct frames is decrementing */
+ msleep(timeout_step);
+ reg = STV090x_READ_DEMOD(state, DMDFLYW);
+ dvbs2_fly_wheel = STV090x_GETFIELD_Px(reg, FLYWHEEL_CPT_FIELD);
+ }
+ if (dvbs2_fly_wheel < 0xd) {
+ /*FALSE lock, The demod is loosing lock */
+ lock = 0;
+ if (trials < 2) {
+ if (state->dev_ver >= 0x20) {
+ if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0)
+ goto err;
+ }
+
+ if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x89) < 0)
+ goto err;
+ }
+ }
+ }
+ }
+ } while ((!lock) && (trials < 2) && (!no_signal));
+
+ return lock;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static enum stv090x_delsys stv090x_get_std(struct stv090x_state *state)
+{
+ u32 reg;
+ enum stv090x_delsys delsys;
+
+ reg = STV090x_READ_DEMOD(state, DMDSTATE);
+ if (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == 2)
+ delsys = STV090x_DVBS2;
+ else if (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == 3) {
+ reg = STV090x_READ_DEMOD(state, FECM);
+ if (STV090x_GETFIELD_Px(reg, DSS_DVB_FIELD) == 1)
+ delsys = STV090x_DSS;
+ else
+ delsys = STV090x_DVBS1;
+ } else {
+ delsys = STV090x_ERROR;
+ }
+
+ return delsys;
+}
+
+/* in Hz */
+static s32 stv090x_get_car_freq(struct stv090x_state *state, u32 mclk)
+{
+ s32 derot, int_1, int_2, tmp_1, tmp_2;
+
+ derot = STV090x_READ_DEMOD(state, CFR2) << 16;
+ derot |= STV090x_READ_DEMOD(state, CFR1) << 8;
+ derot |= STV090x_READ_DEMOD(state, CFR0);
+
+ derot = comp2(derot, 24);
+ int_1 = state->mclk >> 12;
+ int_2 = derot >> 12;
+
+ /* carrier_frequency = MasterClock * Reg / 2^24 */
+ tmp_1 = state->mclk % 0x1000;
+ tmp_2 = derot % 0x1000;
+
+ derot = (int_1 * int_2) +
+ ((int_1 * tmp_2) >> 12) +
+ ((int_1 * tmp_1) >> 12);
+
+ return derot;
+}
+
+static int stv090x_get_viterbi(struct stv090x_state *state)
+{
+ u32 reg, rate;
+
+ reg = STV090x_READ_DEMOD(state, VITCURPUN);
+ rate = STV090x_GETFIELD_Px(reg, VIT_CURPUN_FIELD);
+
+ switch (rate) {
+ case 13:
+ state->fec = STV090x_PR12;
+ break;
+
+ case 18:
+ state->fec = STV090x_PR23;
+ break;
+
+ case 21:
+ state->fec = STV090x_PR34;
+ break;
+
+ case 24:
+ state->fec = STV090x_PR56;
+ break;
+
+ case 25:
+ state->fec = STV090x_PR67;
+ break;
+
+ case 26:
+ state->fec = STV090x_PR78;
+ break;
+
+ default:
+ state->fec = STV090x_PRERR;
+ break;
+ }
+
+ return 0;
+}
+
+static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *state)
+{
+ struct dvb_frontend *fe = &state->frontend;
+
+ u8 tmg;
+ u32 reg;
+ s32 i = 0, offst_freq;
+
+ msleep(5);
+
+ if (state->algo == STV090x_BLIND_SEARCH) {
+ tmg = STV090x_READ_DEMOD(state, TMGREG2);
+ STV090x_WRITE_DEMOD(state, SFRSTEP, 0x5c);
+ while ((i <= 50) && (tmg != 0) && (tmg != 0xff)) {
+ tmg = STV090x_READ_DEMOD(state, TMGREG2);
+ msleep(5);
+ i += 5;
+ }
+ }
+ state->delsys = stv090x_get_std(state);
+
+ if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+ goto err;
+
+ if (state->config->tuner_get_frequency) {
+ if (state->config->tuner_get_frequency(fe, &state->frequency) < 0)
+ goto err;
+ }
+
+ if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+ goto err;
+
+ offst_freq = stv090x_get_car_freq(state, state->mclk) / 1000;
+ state->frequency += offst_freq;
+
+ if (stv090x_get_viterbi(state) < 0)
+ goto err;
+
+ reg = STV090x_READ_DEMOD(state, DMDMODCOD);
+ state->modcod = STV090x_GETFIELD_Px(reg, DEMOD_MODCOD_FIELD);
+ state->pilots = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) & 0x01;
+ state->frame_len = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) >> 1;
+ reg = STV090x_READ_DEMOD(state, TMGOBS);
+ state->rolloff = STV090x_GETFIELD_Px(reg, ROLLOFF_STATUS_FIELD);
+ reg = STV090x_READ_DEMOD(state, FECM);
+ state->inversion = STV090x_GETFIELD_Px(reg, IQINV_FIELD);
+
+ if ((state->algo == STV090x_BLIND_SEARCH) || (state->srate < 10000000)) {
+
+ if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+ goto err;
+
+ if (state->config->tuner_get_frequency) {
+ if (state->config->tuner_get_frequency(fe, &state->frequency) < 0)
+ goto err;
+ }
+
+ if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+ goto err;
+
+ if (abs(offst_freq) <= ((state->search_range / 2000) + 500))
+ return STV090x_RANGEOK;
+ else if (abs(offst_freq) <= (stv090x_car_width(state->srate, state->rolloff) / 2000))
+ return STV090x_RANGEOK;
+ else
+ return STV090x_OUTOFRANGE; /* Out of Range */
+ } else {
+ if (abs(offst_freq) <= ((state->search_range / 2000) + 500))
+ return STV090x_RANGEOK;
+ else
+ return STV090x_OUTOFRANGE;
+ }
+
+ return STV090x_OUTOFRANGE;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static u32 stv090x_get_tmgoffst(struct stv090x_state *state, u32 srate)
+{
+ s32 offst_tmg;
+
+ offst_tmg = STV090x_READ_DEMOD(state, TMGREG2) << 16;
+ offst_tmg |= STV090x_READ_DEMOD(state, TMGREG1) << 8;
+ offst_tmg |= STV090x_READ_DEMOD(state, TMGREG0);
+
+ offst_tmg = comp2(offst_tmg, 24); /* 2's complement */
+ if (!offst_tmg)
+ offst_tmg = 1;
+
+ offst_tmg = ((s32) srate * 10) / ((s32) 0x1000000 / offst_tmg);
+ offst_tmg /= 320;
+
+ return offst_tmg;
+}
+
+static u8 stv090x_optimize_carloop(struct stv090x_state *state, enum stv090x_modcod modcod, s32 pilots)
+{
+ u8 aclc = 0x29;
+ s32 i;
+ struct stv090x_long_frame_crloop *car_loop, *car_loop_qpsk_low, *car_loop_apsk_low;
+
+ if (state->dev_ver == 0x20) {
+ car_loop = stv090x_s2_crl_cut20;
+ car_loop_qpsk_low = stv090x_s2_lowqpsk_crl_cut20;
+ car_loop_apsk_low = stv090x_s2_apsk_crl_cut20;
+ } else {
+ /* >= Cut 3 */
+ car_loop = stv090x_s2_crl_cut30;
+ car_loop_qpsk_low = stv090x_s2_lowqpsk_crl_cut30;
+ car_loop_apsk_low = stv090x_s2_apsk_crl_cut30;
+ }
+
+ if (modcod < STV090x_QPSK_12) {
+ i = 0;
+ while ((i < 3) && (modcod != car_loop_qpsk_low[i].modcod))
+ i++;
+
+ if (i >= 3)
+ i = 2;
+
+ } else {
+ i = 0;
+ while ((i < 14) && (modcod != car_loop[i].modcod))
+ i++;
+
+ if (i >= 14) {
+ i = 0;
+ while ((i < 11) && (modcod != car_loop_apsk_low[i].modcod))
+ i++;
+
+ if (i >= 11)
+ i = 10;
+ }
+ }
+
+ if (modcod <= STV090x_QPSK_25) {
+ if (pilots) {
+ if (state->srate <= 3000000)
+ aclc = car_loop_qpsk_low[i].crl_pilots_on_2;
+ else if (state->srate <= 7000000)
+ aclc = car_loop_qpsk_low[i].crl_pilots_on_5;
+ else if (state->srate <= 15000000)
+ aclc = car_loop_qpsk_low[i].crl_pilots_on_10;
+ else if (state->srate <= 25000000)
+ aclc = car_loop_qpsk_low[i].crl_pilots_on_20;
+ else
+ aclc = car_loop_qpsk_low[i].crl_pilots_on_30;
+ } else {
+ if (state->srate <= 3000000)
+ aclc = car_loop_qpsk_low[i].crl_pilots_off_2;
+ else if (state->srate <= 7000000)
+ aclc = car_loop_qpsk_low[i].crl_pilots_off_5;
+ else if (state->srate <= 15000000)
+ aclc = car_loop_qpsk_low[i].crl_pilots_off_10;
+ else if (state->srate <= 25000000)
+ aclc = car_loop_qpsk_low[i].crl_pilots_off_20;
+ else
+ aclc = car_loop_qpsk_low[i].crl_pilots_off_30;
+ }
+
+ } else if (modcod <= STV090x_8PSK_910) {
+ if (pilots) {
+ if (state->srate <= 3000000)
+ aclc = car_loop[i].crl_pilots_on_2;
+ else if (state->srate <= 7000000)
+ aclc = car_loop[i].crl_pilots_on_5;
+ else if (state->srate <= 15000000)
+ aclc = car_loop[i].crl_pilots_on_10;
+ else if (state->srate <= 25000000)
+ aclc = car_loop[i].crl_pilots_on_20;
+ else
+ aclc = car_loop[i].crl_pilots_on_30;
+ } else {
+ if (state->srate <= 3000000)
+ aclc = car_loop[i].crl_pilots_off_2;
+ else if (state->srate <= 7000000)
+ aclc = car_loop[i].crl_pilots_off_5;
+ else if (state->srate <= 15000000)
+ aclc = car_loop[i].crl_pilots_off_10;
+ else if (state->srate <= 25000000)
+ aclc = car_loop[i].crl_pilots_off_20;
+ else
+ aclc = car_loop[i].crl_pilots_off_30;
+ }
+ } else { /* 16APSK and 32APSK */
+ if (state->srate <= 3000000)
+ aclc = car_loop_apsk_low[i].crl_pilots_on_2;
+ else if (state->srate <= 7000000)
+ aclc = car_loop_apsk_low[i].crl_pilots_on_5;
+ else if (state->srate <= 15000000)
+ aclc = car_loop_apsk_low[i].crl_pilots_on_10;
+ else if (state->srate <= 25000000)
+ aclc = car_loop_apsk_low[i].crl_pilots_on_20;
+ else
+ aclc = car_loop_apsk_low[i].crl_pilots_on_30;
+ }
+
+ return aclc;
+}
+
+static u8 stv090x_optimize_carloop_short(struct stv090x_state *state)
+{
+ struct stv090x_short_frame_crloop *short_crl;
+ s32 index = 0;
+ u8 aclc = 0x0b;
+
+ switch (state->modulation) {
+ case STV090x_QPSK:
+ default:
+ index = 0;
+ break;
+ case STV090x_8PSK:
+ index = 1;
+ break;
+ case STV090x_16APSK:
+ index = 2;
+ break;
+ case STV090x_32APSK:
+ index = 3;
+ break;
+ }
+
+ if (state->dev_ver >= 0x30)
+ short_crl = stv090x_s2_short_crl_cut20;
+ else if (state->dev_ver >= 0x20)
+ short_crl = stv090x_s2_short_crl_cut30;
+
+ if (state->srate <= 3000000)
+ aclc = short_crl[index].crl_2;
+ else if (state->srate <= 7000000)
+ aclc = short_crl[index].crl_5;
+ else if (state->srate <= 15000000)
+ aclc = short_crl[index].crl_10;
+ else if (state->srate <= 25000000)
+ aclc = short_crl[index].crl_20;
+ else
+ aclc = short_crl[index].crl_30;
+
+ return aclc;
+}
+
+static int stv090x_optimize_track(struct stv090x_state *state)
+{
+ struct dvb_frontend *fe = &state->frontend;
+
+ enum stv090x_rolloff rolloff;
+ enum stv090x_modcod modcod;
+
+ s32 srate, pilots, aclc, f_1, f_0, i = 0, blind_tune = 0;
+ u32 reg;
+
+ srate = stv090x_get_srate(state, state->mclk);
+ srate += stv090x_get_tmgoffst(state, srate);
+
+ switch (state->delsys) {
+ case STV090x_DVBS1:
+ case STV090x_DSS:
+ if (state->algo == STV090x_SEARCH_AUTO) {
+ reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+ STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
+ STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
+ if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+ goto err;
+ }
+ reg = STV090x_READ_DEMOD(state, DEMOD);
+ STV090x_SETFIELD_Px(reg, ROLLOFF_CONTROL_FIELD, state->rolloff);
+ STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 0x01);
+ if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
+ goto err;
+
+ if (state->dev_ver >= 0x30) {
+ if (stv090x_get_viterbi(state) < 0)
+ goto err;
+
+ if (state->fec == STV090x_PR12) {
+ if (STV090x_WRITE_DEMOD(state, GAUSSR0, 0x98) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CCIR0, 0x18) < 0)
+ goto err;
+ } else {
+ if (STV090x_WRITE_DEMOD(state, GAUSSR0, 0x18) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CCIR0, 0x18) < 0)
+ goto err;
+ }
+ }
+
+ if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x75) < 0)
+ goto err;
+ break;
+
+ case STV090x_DVBS2:
+ reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+ STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0);
+ STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
+ if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, ACLC, 0) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, BCLC, 0) < 0)
+ goto err;
+ if (state->frame_len == STV090x_LONG_FRAME) {
+ reg = STV090x_READ_DEMOD(state, DMDMODCOD);
+ modcod = STV090x_GETFIELD_Px(reg, DEMOD_MODCOD_FIELD);
+ pilots = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) & 0x01;
+ aclc = stv090x_optimize_carloop(state, modcod, pilots);
+ if (modcod <= STV090x_QPSK_910) {
+ STV090x_WRITE_DEMOD(state, ACLC2S2Q, aclc);
+ } else if (modcod <= STV090x_8PSK_910) {
+ if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, ACLC2S28, aclc) < 0)
+ goto err;
+ }
+ if ((state->demod_mode == STV090x_SINGLE) && (modcod > STV090x_8PSK_910)) {
+ if (modcod <= STV090x_16APSK_910) {
+ if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, ACLC2S216A, aclc) < 0)
+ goto err;
+ } else {
+ if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, ACLC2S232A, aclc) < 0)
+ goto err;
+ }
+ }
+ } else {
+ /*Carrier loop setting for short frame*/
+ aclc = stv090x_optimize_carloop_short(state);
+ if (state->modulation == STV090x_QPSK) {
+ if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, aclc) < 0)
+ goto err;
+ } else if (state->modulation == STV090x_8PSK) {
+ if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, ACLC2S28, aclc) < 0)
+ goto err;
+ } else if (state->modulation == STV090x_16APSK) {
+ if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, ACLC2S216A, aclc) < 0)
+ goto err;
+ } else if (state->modulation == STV090x_32APSK) {
+ if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, ACLC2S232A, aclc) < 0)
+ goto err;
+ }
+ }
+
+ STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67); /* PER */
+ break;
+
+ case STV090x_UNKNOWN:
+ default:
+ reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+ STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
+ STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
+ if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+ goto err;
+ break;
+ }
+
+ f_1 = STV090x_READ_DEMOD(state, CFR2);
+ f_0 = STV090x_READ_DEMOD(state, CFR1);
+ reg = STV090x_READ_DEMOD(state, TMGOBS);
+ rolloff = STV090x_GETFIELD_Px(reg, ROLLOFF_STATUS_FIELD);
+
+ if (state->algo == STV090x_BLIND_SEARCH) {
+ STV090x_WRITE_DEMOD(state, SFRSTEP, 0x00);
+ reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+ STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 0x00);
+ STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00);
+ if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc1) < 0)
+ goto err;
+
+ if (stv090x_set_srate(state, srate) < 0)
+ goto err;
+ blind_tune = 1;
+ }
+
+ if (state->dev_ver >= 0x20) {
+ if ((state->search_mode == STV090x_SEARCH_DVBS1) ||
+ (state->search_mode == STV090x_SEARCH_DSS) ||
+ (state->search_mode == STV090x_SEARCH_AUTO)) {
+
+ if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x0a) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x00) < 0)
+ goto err;
+ }
+ }
+
+ if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
+ goto err;
+
+ /* AUTO tracking MODE */
+ if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x80) < 0)
+ goto err;
+ /* AUTO tracking MODE */
+ if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x80) < 0)
+ goto err;
+
+ if ((state->dev_ver >= 0x20) || (blind_tune == 1) || (state->srate < 10000000)) {
+ /* update initial carrier freq with the found freq offset */
+ if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0)
+ goto err;
+ state->tuner_bw = stv090x_car_width(srate, state->rolloff) + 10000000;
+
+ if ((state->dev_ver >= 0x20) || (blind_tune == 1)) {
+
+ if (state->algo != STV090x_WARM_SEARCH) {
+
+ if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+ goto err;
+
+ if (state->config->tuner_set_bandwidth) {
+ if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
+ goto err;
+ }
+
+ if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+ goto err;
+
+ }
+ }
+ if ((state->algo == STV090x_BLIND_SEARCH) || (state->srate < 10000000))
+ msleep(50); /* blind search: wait 50ms for SR stabilization */
+ else
+ msleep(5);
+
+ stv090x_get_lock_tmg(state);
+
+ if (!(stv090x_get_dmdlock(state, (state->DemodTimeout / 2)))) {
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0)
+ goto err;
+
+ i = 0;
+
+ while ((!(stv090x_get_dmdlock(state, (state->DemodTimeout / 2)))) && (i <= 2)) {
+
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0)
+ goto err;
+ i++;
+ }
+ }
+
+ }
+
+ if (state->dev_ver >= 0x20) {
+ if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0)
+ goto err;
+ }
+
+ if ((state->delsys == STV090x_DVBS1) || (state->delsys == STV090x_DSS))
+ stv090x_set_vit_thtracq(state);
+
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_get_feclock(struct stv090x_state *state, s32 timeout)
+{
+ s32 timer = 0, lock = 0, stat;
+ u32 reg;
+
+ while ((timer < timeout) && (!lock)) {
+ reg = STV090x_READ_DEMOD(state, DMDSTATE);
+ stat = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD);
+
+ switch (stat) {
+ case 0: /* searching */
+ case 1: /* first PLH detected */
+ default:
+ lock = 0;
+ break;
+
+ case 2: /* DVB-S2 mode */
+ reg = STV090x_READ_DEMOD(state, PDELSTATUS1);
+ lock = STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD);
+ break;
+
+ case 3: /* DVB-S1/legacy mode */
+ reg = STV090x_READ_DEMOD(state, VSTATUSVIT);
+ lock = STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD);
+ break;
+ }
+ if (!lock) {
+ msleep(10);
+ timer += 10;
+ }
+ }
+ return lock;
+}
+
+static int stv090x_get_lock(struct stv090x_state *state, s32 timeout_dmd, s32 timeout_fec)
+{
+ u32 reg;
+ s32 timer = 0;
+ int lock;
+
+ lock = stv090x_get_dmdlock(state, timeout_dmd);
+ if (lock)
+ lock = stv090x_get_feclock(state, timeout_fec);
+
+ if (lock) {
+ lock = 0;
+
+ while ((timer < timeout_fec) && (!lock)) {
+ reg = STV090x_READ_DEMOD(state, TSSTATUS);
+ lock = STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD);
+ msleep(1);
+ timer++;
+ }
+ }
+
+ return lock;
+}
+
+static int stv090x_set_s2rolloff(struct stv090x_state *state)
+{
+ u32 reg;
+
+ if (state->dev_ver <= 0x20) {
+ /* rolloff to auto mode if DVBS2 */
+ reg = STV090x_READ_DEMOD(state, DEMOD);
+ STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 0x00);
+ if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
+ goto err;
+ } else {
+ /* DVB-S2 rolloff to auto mode if DVBS2 */
+ reg = STV090x_READ_DEMOD(state, DEMOD);
+ STV090x_SETFIELD_Px(reg, MANUAL_S2ROLLOFF_FIELD, 0x00);
+ if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
+ goto err;
+ }
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+
+static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
+{
+ struct dvb_frontend *fe = &state->frontend;
+ enum stv090x_signal_state signal_state = STV090x_NOCARRIER;
+ u32 reg;
+ s32 timeout_dmd = 500, timeout_fec = 50, agc1_power, power_iq = 0, i;
+ int lock = 0, low_sr = 0, no_signal = 0;
+
+ reg = STV090x_READ_DEMOD(state, TSCFGH);
+ STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* Stop path 1 stream merger */
+ if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
+ goto err;
+
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Demod stop */
+ goto err;
+
+ if (state->dev_ver >= 0x20) {
+ if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0) /* cut 2.0 */
+ goto err;
+ }
+
+ stv090x_get_lock_tmg(state);
+
+ if (state->algo == STV090x_BLIND_SEARCH) {
+ state->tuner_bw = 2 * 36000000; /* wide bw for unknown srate */
+ if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc0) < 0) /* wider srate scan */
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x70) < 0)
+ goto err;
+ if (stv090x_set_srate(state, 1000000) < 0) /* inital srate = 1Msps */
+ goto err;
+ } else {
+ /* known srate */
+ if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x20) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, TMGCFG, 0xd2) < 0)
+ goto err;
+
+ if (state->srate < 2000000) {
+ /* SR < 2MSPS */
+ if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x63) < 0)
+ goto err;
+ } else {
+ /* SR >= 2Msps */
+ if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x70) < 0)
+ goto err;
+ }
+
+ if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
+ goto err;
+
+ if (state->dev_ver >= 0x20) {
+ if (STV090x_WRITE_DEMOD(state, KREFTMG, 0x5a) < 0)
+ goto err;
+ if (state->algo == STV090x_COLD_SEARCH)
+ state->tuner_bw = (15 * (stv090x_car_width(state->srate, state->rolloff) + 10000000)) / 10;
+ else if (state->algo == STV090x_WARM_SEARCH)
+ state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + 10000000;
+ }
+
+ /* if cold start or warm (Symbolrate is known)
+ * use a Narrow symbol rate scan range
+ */
+ if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc1) < 0) /* narrow srate scan */
+ goto err;
+
+ if (stv090x_set_srate(state, state->srate) < 0)
+ goto err;
+
+ if (stv090x_set_max_srate(state, state->mclk, state->srate) < 0)
+ goto err;
+ if (stv090x_set_min_srate(state, state->mclk, state->srate) < 0)
+ goto err;
+
+ if (state->srate >= 10000000)
+ low_sr = 0;
+ else
+ low_sr = 1;
+ }
+
+ /* Setup tuner */
+ if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+ goto err;
+
+ if (state->config->tuner_set_bbgain) {
+ if (state->config->tuner_set_bbgain(fe, 10) < 0) /* 10dB */
+ goto err;
+ }
+
+ if (state->config->tuner_set_frequency) {
+ if (state->config->tuner_set_frequency(fe, state->frequency) < 0)
+ goto err;
+ }
+
+ if (state->config->tuner_set_bandwidth) {
+ if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
+ goto err;
+ }
+
+ if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+ goto err;
+
+ msleep(50);
+
+ if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+ goto err;
+
+ if (state->config->tuner_get_status) {
+ if (state->config->tuner_get_status(fe, &reg) < 0)
+ goto err;
+ }
+
+ if (reg)
+ dprintk(FE_DEBUG, 1, "Tuner phase locked");
+ else
+ dprintk(FE_DEBUG, 1, "Tuner unlocked");
+
+ if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+ goto err;
+
+ msleep(10);
+ agc1_power = MAKEWORD16(STV090x_READ_DEMOD(state, AGCIQIN1),
+ STV090x_READ_DEMOD(state, AGCIQIN0));
+
+ if (agc1_power == 0) {
+ /* If AGC1 integrator value is 0
+ * then read POWERI, POWERQ
+ */
+ for (i = 0; i < 5; i++) {
+ power_iq += (STV090x_READ_DEMOD(state, POWERI) +
+ STV090x_READ_DEMOD(state, POWERQ)) >> 1;
+ }
+ power_iq /= 5;
+ }
+
+ if ((agc1_power == 0) && (power_iq < STV090x_IQPOWER_THRESHOLD)) {
+ dprintk(FE_ERROR, 1, "No Signal: POWER_IQ=0x%02x", power_iq);
+ lock = 0;
+
+ } else {
+ reg = STV090x_READ_DEMOD(state, DEMOD);
+ STV090x_SETFIELD_Px(reg, SPECINV_CONTROL_FIELD, state->inversion);
+
+ if (state->dev_ver <= 0x20) {
+ /* rolloff to auto mode if DVBS2 */
+ STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 1);
+ } else {
+ /* DVB-S2 rolloff to auto mode if DVBS2 */
+ STV090x_SETFIELD_Px(reg, MANUAL_S2ROLLOFF_FIELD, 1);
+ }
+ if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
+ goto err;
+
+ if (stv090x_delivery_search(state) < 0)
+ goto err;
+
+ if (state->algo != STV090x_BLIND_SEARCH) {
+ if (stv090x_start_search(state) < 0)
+ goto err;
+ }
+ }
+
+ /* need to check for AGC1 state */
+
+
+
+ if (state->algo == STV090x_BLIND_SEARCH)
+ lock = stv090x_blind_search(state);
+
+ else if (state->algo == STV090x_COLD_SEARCH)
+ lock = stv090x_get_coldlock(state, timeout_dmd);
+
+ else if (state->algo == STV090x_WARM_SEARCH)
+ lock = stv090x_get_dmdlock(state, timeout_dmd);
+
+ if ((!lock) && (state->algo == STV090x_COLD_SEARCH)) {
+ if (!low_sr) {
+ if (stv090x_chk_tmg(state))
+ lock = stv090x_sw_algo(state);
+ }
+ }
+
+ if (lock)
+ signal_state = stv090x_get_sig_params(state);
+
+ if ((lock) && (signal_state == STV090x_RANGEOK)) { /* signal within Range */
+ stv090x_optimize_track(state);
+
+ if (state->dev_ver >= 0x20) {
+ /* >= Cut 2.0 :release TS reset after
+ * demod lock and optimized Tracking
+ */
+ reg = STV090x_READ_DEMOD(state, TSCFGH);
+ STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */
+ if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
+ goto err;
+
+ msleep(3);
+
+ STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* merger reset */
+ if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
+ goto err;
+
+ STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */
+ if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
+ goto err;
+ }
+
+ if (stv090x_get_lock(state, timeout_fec, timeout_fec)) {
+ lock = 1;
+ if (state->delsys == STV090x_DVBS2) {
+ stv090x_set_s2rolloff(state);
+
+ reg = STV090x_READ_DEMOD(state, PDELCTRL2);
+ STV090x_SETFIELD_Px(reg, RESET_UPKO_COUNT, 1);
+ if (STV090x_WRITE_DEMOD(state, PDELCTRL2, reg) < 0)
+ goto err;
+ /* Reset DVBS2 packet delinator error counter */
+ reg = STV090x_READ_DEMOD(state, PDELCTRL2);
+ STV090x_SETFIELD_Px(reg, RESET_UPKO_COUNT, 0);
+ if (STV090x_WRITE_DEMOD(state, PDELCTRL2, reg) < 0)
+ goto err;
+
+ if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67) < 0) /* PER */
+ goto err;
+ } else {
+ if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x75) < 0)
+ goto err;
+ }
+ /* Reset the Total packet counter */
+ if (STV090x_WRITE_DEMOD(state, FBERCPT4, 0x00) < 0)
+ goto err;
+ /* Reset the packet Error counter2 */
+ if (STV090x_WRITE_DEMOD(state, ERRCTRL2, 0xc1) < 0)
+ goto err;
+ } else {
+ lock = 0;
+ signal_state = STV090x_NODATA;
+ no_signal = stv090x_chk_signal(state);
+ }
+ }
+ return signal_state;
+
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static enum dvbfe_search stv090x_search(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+ struct stv090x_state *state = fe->demodulator_priv;
+ struct dtv_frontend_properties *props = &fe->dtv_property_cache;
+
+ state->delsys = props->delivery_system;
+ state->frequency = p->frequency;
+ state->srate = p->u.qpsk.symbol_rate;
+ state->search_mode = STV090x_SEARCH_AUTO;
+ state->algo = STV090x_COLD_SEARCH;
+ state->fec = STV090x_PRERR;
+ state->search_range = 2000000;
+
+ if (stv090x_algo(state) == STV090x_RANGEOK) {
+ dprintk(FE_DEBUG, 1, "Search success!");
+ return DVBFE_ALGO_SEARCH_SUCCESS;
+ } else {
+ dprintk(FE_DEBUG, 1, "Search failed!");
+ return DVBFE_ALGO_SEARCH_FAILED;
+ }
+
+ return DVBFE_ALGO_SEARCH_ERROR;
+}
+
+/* FIXME! */
+static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
+{
+ struct stv090x_state *state = fe->demodulator_priv;
+ u32 reg;
+ u8 search_state;
+
+ reg = STV090x_READ_DEMOD(state, DMDSTATE);
+ search_state = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD);
+
+ switch (search_state) {
+ case 0: /* searching */
+ case 1: /* first PLH detected */
+ default:
+ dprintk(FE_DEBUG, 1, "Status: Unlocked (Searching ..)");
+ *status = 0;
+ break;
+
+ case 2: /* DVB-S2 mode */
+ dprintk(FE_DEBUG, 1, "Delivery system: DVB-S2");
+ reg = STV090x_READ_DEMOD(state, DSTATUS);
+ if (STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD)) {
+ reg = STV090x_READ_DEMOD(state, TSSTATUS);
+ if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) {
+ *status = FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+ }
+ }
+ break;
+
+ case 3: /* DVB-S1/legacy mode */
+ dprintk(FE_DEBUG, 1, "Delivery system: DVB-S");
+ reg = STV090x_READ_DEMOD(state, DSTATUS);
+ if (STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD)) {
+ reg = STV090x_READ_DEMOD(state, VSTATUSVIT);
+ if (STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD)) {
+ reg = STV090x_READ_DEMOD(state, TSSTATUS);
+ if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) {
+ *status = FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+ }
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static int stv090x_read_per(struct dvb_frontend *fe, u32 *per)
+{
+ struct stv090x_state *state = fe->demodulator_priv;
+
+ s32 count_4, count_3, count_2, count_1, count_0, count;
+ u32 reg, h, m, l;
+ enum fe_status status;
+
+ stv090x_read_status(fe, &status);
+ if (!(status & FE_HAS_LOCK)) {
+ *per = 1 << 23; /* Max PER */
+ } else {
+ /* Counter 2 */
+ reg = STV090x_READ_DEMOD(state, ERRCNT22);
+ h = STV090x_GETFIELD_Px(reg, ERR_CNT2_FIELD);
+
+ reg = STV090x_READ_DEMOD(state, ERRCNT21);
+ m = STV090x_GETFIELD_Px(reg, ERR_CNT21_FIELD);
+
+ reg = STV090x_READ_DEMOD(state, ERRCNT20);
+ l = STV090x_GETFIELD_Px(reg, ERR_CNT20_FIELD);
+
+ *per = ((h << 16) | (m << 8) | l);
+
+ count_4 = STV090x_READ_DEMOD(state, FBERCPT4);
+ count_3 = STV090x_READ_DEMOD(state, FBERCPT3);
+ count_2 = STV090x_READ_DEMOD(state, FBERCPT2);
+ count_1 = STV090x_READ_DEMOD(state, FBERCPT1);
+ count_0 = STV090x_READ_DEMOD(state, FBERCPT0);
+
+ if ((!count_4) && (!count_3)) {
+ count = (count_2 & 0xff) << 16;
+ count |= (count_1 & 0xff) << 8;
+ count |= count_0 & 0xff;
+ } else {
+ count = 1 << 24;
+ }
+ if (count == 0)
+ *per = 1;
+ }
+ if (STV090x_WRITE_DEMOD(state, FBERCPT4, 0) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, ERRCTRL2, 0xc1) < 0)
+ goto err;
+
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_table_lookup(const struct stv090x_tab *tab, int max, int val)
+{
+ int res = 0;
+ int min = 0, med;
+
+ if (val < tab[min].read)
+ res = tab[min].real;
+ else if (val >= tab[max].read)
+ res = tab[max].real;
+ else {
+ while ((max - min) > 1) {
+ med = (max + min) / 2;
+ if (val >= tab[min].read && val < tab[med].read)
+ max = med;
+ else
+ min = med;
+ }
+ res = ((val - tab[min].read) *
+ (tab[max].real - tab[min].real) /
+ (tab[max].read - tab[min].read)) +
+ tab[min].real;
+ }
+
+ return res;
+}
+
+static int stv090x_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+ struct stv090x_state *state = fe->demodulator_priv;
+ u32 reg;
+ s32 agc;
+
+ reg = STV090x_READ_DEMOD(state, AGCIQIN1);
+ agc = STV090x_GETFIELD_Px(reg, AGCIQ_VALUE_FIELD);
+
+ *strength = stv090x_table_lookup(stv090x_rf_tab, ARRAY_SIZE(stv090x_rf_tab) - 1, agc);
+ if (agc > stv090x_rf_tab[0].read)
+ *strength = 5;
+ else if (agc < stv090x_rf_tab[ARRAY_SIZE(stv090x_rf_tab) - 1].read)
+ *strength = -100;
+
+ return 0;
+}
+
+static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr)
+{
+ struct stv090x_state *state = fe->demodulator_priv;
+ u32 reg_0, reg_1, reg, i;
+ s32 val_0, val_1, val = 0;
+ u8 lock_f;
+
+ switch (state->delsys) {
+ case STV090x_DVBS2:
+ reg = STV090x_READ_DEMOD(state, DSTATUS);
+ lock_f = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD);
+ if (lock_f) {
+ msleep(5);
+ for (i = 0; i < 16; i++) {
+ reg_1 = STV090x_READ_DEMOD(state, NNOSPLHT1);
+ val_1 = STV090x_GETFIELD_Px(reg_1, NOSPLHT_NORMED_FIELD);
+ reg_0 = STV090x_READ_DEMOD(state, NNOSPLHT0);
+ val_0 = STV090x_GETFIELD_Px(reg_1, NOSPLHT_NORMED_FIELD);
+ val += MAKEWORD16(val_1, val_0);
+ msleep(1);
+ }
+ val /= 16;
+ *cnr = stv090x_table_lookup(stv090x_s2cn_tab, ARRAY_SIZE(stv090x_s2cn_tab) - 1, val);
+ if (val < stv090x_s2cn_tab[ARRAY_SIZE(stv090x_s2cn_tab) - 1].read)
+ *cnr = 1000;
+ }
+ break;
+
+ case STV090x_DVBS1:
+ case STV090x_DSS:
+ reg = STV090x_READ_DEMOD(state, DSTATUS);
+ lock_f = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD);
+ if (lock_f) {
+ msleep(5);
+ for (i = 0; i < 16; i++) {
+ reg_1 = STV090x_READ_DEMOD(state, NOSDATAT1);
+ val_1 = STV090x_GETFIELD_Px(reg_1, NOSDATAT_UNNORMED_FIELD);
+ reg_0 = STV090x_READ_DEMOD(state, NOSDATAT0);
+ val_0 = STV090x_GETFIELD_Px(reg_1, NOSDATAT_UNNORMED_FIELD);
+ val += MAKEWORD16(val_1, val_0);
+ msleep(1);
+ }
+ val /= 16;
+ *cnr = stv090x_table_lookup(stv090x_s1cn_tab, ARRAY_SIZE(stv090x_s1cn_tab) - 1, val);
+ if (val < stv090x_s2cn_tab[ARRAY_SIZE(stv090x_s1cn_tab) - 1].read)
+ *cnr = 1000;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int stv090x_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+ struct stv090x_state *state = fe->demodulator_priv;
+ u32 reg;
+
+ reg = STV090x_READ_DEMOD(state, DISTXCTL);
+ switch (tone) {
+ case SEC_TONE_ON:
+ STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 0);
+ STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
+ if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+ goto err;
+ STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0);
+ if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+ goto err;
+ break;
+
+ case SEC_TONE_OFF:
+ STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 0);
+ STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
+ if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+ goto err;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+
+static enum dvbfe_algo stv090x_frontend_algo(struct dvb_frontend *fe)
+{
+ return DVBFE_ALGO_CUSTOM;
+}
+
+static int stv090x_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd)
+{
+ struct stv090x_state *state = fe->demodulator_priv;
+ u32 reg, idle = 0, fifo_full = 1;
+ int i;
+
+ reg = STV090x_READ_DEMOD(state, DISTXCTL);
+
+ STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 2);
+ STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
+ if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+ goto err;
+ STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0);
+ if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+ goto err;
+
+ STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 1);
+ if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+ goto err;
+
+ for (i = 0; i < cmd->msg_len; i++) {
+
+ while (fifo_full) {
+ reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
+ fifo_full = STV090x_GETFIELD_Px(reg, FIFO_FULL_FIELD);
+ }
+
+ if (STV090x_WRITE_DEMOD(state, DISTXDATA, cmd->msg[i]) < 0)
+ goto err;
+ }
+ reg = STV090x_READ_DEMOD(state, DISTXCTL);
+ STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 0);
+ if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+ goto err;
+
+ i = 0;
+
+ while ((!idle) && (i < 10)) {
+ reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
+ idle = STV090x_GETFIELD_Px(reg, TX_IDLE_FIELD);
+ msleep(10);
+ i++;
+ }
+
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst)
+{
+ struct stv090x_state *state = fe->demodulator_priv;
+ u32 reg, idle = 0, fifo_full = 1;
+ u8 mode, value;
+ int i;
+
+ reg = STV090x_READ_DEMOD(state, DISTXCTL);
+
+ if (burst == SEC_MINI_A) {
+ mode = 3;
+ value = 0x00;
+ } else {
+ mode = 2;
+ value = 0xFF;
+ }
+
+ STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, mode);
+ STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
+ if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+ goto err;
+ STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0);
+ if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+ goto err;
+
+ STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 1);
+ if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+ goto err;
+
+ while (fifo_full) {
+ reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
+ fifo_full = STV090x_GETFIELD_Px(reg, FIFO_FULL_FIELD);
+ }
+
+ if (STV090x_WRITE_DEMOD(state, DISTXDATA, value) < 0)
+ goto err;
+
+ reg = STV090x_READ_DEMOD(state, DISTXCTL);
+ STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 0);
+ if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+ goto err;
+
+ i = 0;
+
+ while ((!idle) && (i < 10)) {
+ reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
+ idle = STV090x_GETFIELD_Px(reg, TX_IDLE_FIELD);
+ msleep(10);
+ i++;
+ }
+
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_recv_slave_reply(struct dvb_frontend *fe, struct dvb_diseqc_slave_reply *reply)
+{
+ struct stv090x_state *state = fe->demodulator_priv;
+ u32 reg = 0, i = 0, rx_end = 0;
+
+ while ((rx_end != 1) && (i < 10)) {
+ msleep(10);
+ i++;
+ reg = STV090x_READ_DEMOD(state, DISRX_ST0);
+ rx_end = STV090x_GETFIELD_Px(reg, RX_END_FIELD);
+ }
+
+ if (rx_end) {
+ reply->msg_len = STV090x_GETFIELD_Px(reg, FIFO_BYTENBR_FIELD);
+ for (i = 0; i < reply->msg_len; i++)
+ reply->msg[i] = STV090x_READ_DEMOD(state, DISRXDATA);
+ }
+
+ return 0;
+}
+
+static int stv090x_sleep(struct dvb_frontend *fe)
+{
+ struct stv090x_state *state = fe->demodulator_priv;
+ u32 reg;
+
+ dprintk(FE_DEBUG, 1, "Set %s to sleep",
+ state->device == STV0900 ? "STV0900" : "STV0903");
+
+ reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
+ STV090x_SETFIELD(reg, STANDBY_FIELD, 0x01);
+ if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0)
+ goto err;
+
+ reg = stv090x_read_reg(state, STV090x_TSTTNR1);
+ STV090x_SETFIELD(reg, ADC1_PON_FIELD, 0);
+ if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0)
+ goto err;
+
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_wakeup(struct dvb_frontend *fe)
+{
+ struct stv090x_state *state = fe->demodulator_priv;
+ u32 reg;
+
+ dprintk(FE_DEBUG, 1, "Wake %s from standby",
+ state->device == STV0900 ? "STV0900" : "STV0903");
+
+ reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
+ STV090x_SETFIELD(reg, STANDBY_FIELD, 0x00);
+ if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0)
+ goto err;
+
+ reg = stv090x_read_reg(state, STV090x_TSTTNR1);
+ STV090x_SETFIELD(reg, ADC1_PON_FIELD, 1);
+ if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0)
+ goto err;
+
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static void stv090x_release(struct dvb_frontend *fe)
+{
+ struct stv090x_state *state = fe->demodulator_priv;
+
+ kfree(state);
+}
+
+static int stv090x_ldpc_mode(struct stv090x_state *state, enum stv090x_mode ldpc_mode)
+{
+ u32 reg = 0;
+
+ switch (ldpc_mode) {
+ case STV090x_DUAL:
+ default:
+ if ((state->demod_mode != STV090x_DUAL) || (STV090x_GETFIELD(reg, DDEMOD_FIELD) != 1)) {
+ /* set LDPC to dual mode */
+ if (stv090x_write_reg(state, STV090x_GENCFG, 0x1d) < 0)
+ goto err;
+
+ state->demod_mode = STV090x_DUAL;
+
+ reg = stv090x_read_reg(state, STV090x_TSTRES0);
+ STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x1);
+ if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0)
+ goto err;
+ STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x0);
+ if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0)
+ goto err;
+
+ if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xff) < 0)
+ goto err;
+
+ if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xcc) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xcc) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xcc) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xcc) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xcc) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xcc) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xcc) < 0)
+ goto err;
+
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xff) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xcf) < 0)
+ goto err;
+ }
+ break;
+
+ case STV090x_SINGLE:
+ if (stv090x_stop_modcod(state) < 0)
+ goto err;
+ if (stv090x_activate_modcod_single(state) < 0)
+ goto err;
+
+ if (state->demod == STV090x_DEMODULATOR_1) {
+ if (stv090x_write_reg(state, STV090x_GENCFG, 0x06) < 0) /* path 2 */
+ goto err;
+ } else {
+ if (stv090x_write_reg(state, STV090x_GENCFG, 0x04) < 0) /* path 1 */
+ goto err;
+ }
+
+ reg = stv090x_read_reg(state, STV090x_TSTRES0);
+ STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x1);
+ if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0)
+ goto err;
+ STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x0);
+ if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0)
+ goto err;
+
+ reg = STV090x_READ_DEMOD(state, PDELCTRL1);
+ STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x01);
+ if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
+ goto err;
+ STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x00);
+ if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
+ goto err;
+ break;
+ }
+
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+/* return (Hz), clk in Hz*/
+static u32 stv090x_get_mclk(struct stv090x_state *state)
+{
+ const struct stv090x_config *config = state->config;
+ u32 div, reg;
+ u8 ratio;
+
+ div = stv090x_read_reg(state, STV090x_NCOARSE);
+ reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
+ ratio = STV090x_GETFIELD(reg, SELX1RATIO_FIELD) ? 4 : 6;
+
+ return (div + 1) * config->xtal / ratio; /* kHz */
+}
+
+static int stv090x_set_mclk(struct stv090x_state *state, u32 mclk, u32 clk)
+{
+ const struct stv090x_config *config = state->config;
+ u32 reg, div, clk_sel;
+
+ reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
+ clk_sel = ((STV090x_GETFIELD(reg, SELX1RATIO_FIELD) == 1) ? 4 : 6);
+
+ div = ((clk_sel * mclk) / config->xtal) - 1;
+
+ reg = stv090x_read_reg(state, STV090x_NCOARSE);
+ STV090x_SETFIELD(reg, M_DIV_FIELD, div);
+ if (stv090x_write_reg(state, STV090x_NCOARSE, reg) < 0)
+ goto err;
+
+ state->mclk = stv090x_get_mclk(state);
+
+ /*Set the DiseqC frequency to 22KHz */
+ div = state->mclk / 704000;
+ if (STV090x_WRITE_DEMOD(state, F22TX, div) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, F22RX, div) < 0)
+ goto err;
+
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_set_tspath(struct stv090x_state *state)
+{
+ u32 reg;
+
+ if (state->dev_ver >= 0x20) {
+ switch (state->config->ts1_mode) {
+ case STV090x_TSMODE_PARALLEL_PUNCTURED:
+ case STV090x_TSMODE_DVBCI:
+ switch (state->config->ts2_mode) {
+ case STV090x_TSMODE_SERIAL_PUNCTURED:
+ case STV090x_TSMODE_SERIAL_CONTINUOUS:
+ default:
+ stv090x_write_reg(state, STV090x_TSGENERAL, 0x00);
+ break;
+
+ case STV090x_TSMODE_PARALLEL_PUNCTURED:
+ case STV090x_TSMODE_DVBCI:
+ if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x06) < 0) /* Mux'd stream mode */
+ goto err;
+ reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
+ STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
+ if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
+ goto err;
+ reg = stv090x_read_reg(state, STV090x_P2_TSCFGM);
+ STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
+ if (stv090x_write_reg(state, STV090x_P2_TSCFGM, reg) < 0)
+ goto err;
+ if (stv090x_write_reg(state, STV090x_P1_TSSPEED, 0x14) < 0)
+ goto err;
+ if (stv090x_write_reg(state, STV090x_P2_TSSPEED, 0x28) < 0)
+ goto err;
+ break;
+ }
+ break;
+
+ case STV090x_TSMODE_SERIAL_PUNCTURED:
+ case STV090x_TSMODE_SERIAL_CONTINUOUS:
+ default:
+ switch (state->config->ts2_mode) {
+ case STV090x_TSMODE_SERIAL_PUNCTURED:
+ case STV090x_TSMODE_SERIAL_CONTINUOUS:
+ default:
+ if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0)
+ goto err;
+ break;
+
+ case STV090x_TSMODE_PARALLEL_PUNCTURED:
+ case STV090x_TSMODE_DVBCI:
+ if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0a) < 0)
+ goto err;
+ break;
+ }
+ break;
+ }
+ } else {
+ switch (state->config->ts1_mode) {
+ case STV090x_TSMODE_PARALLEL_PUNCTURED:
+ case STV090x_TSMODE_DVBCI:
+ switch (state->config->ts2_mode) {
+ case STV090x_TSMODE_SERIAL_PUNCTURED:
+ case STV090x_TSMODE_SERIAL_CONTINUOUS:
+ default:
+ stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x10);
+ break;
+
+ case STV090x_TSMODE_PARALLEL_PUNCTURED:
+ case STV090x_TSMODE_DVBCI:
+ stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x16);
+ reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
+ STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
+ if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
+ goto err;
+ reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
+ STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 0);
+ if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
+ goto err;
+ if (stv090x_write_reg(state, STV090x_P1_TSSPEED, 0x14) < 0)
+ goto err;
+ if (stv090x_write_reg(state, STV090x_P2_TSSPEED, 0x28) < 0)
+ goto err;
+ break;
+ }
+ break;
+
+ case STV090x_TSMODE_SERIAL_PUNCTURED:
+ case STV090x_TSMODE_SERIAL_CONTINUOUS:
+ default:
+ switch (state->config->ts2_mode) {
+ case STV090x_TSMODE_SERIAL_PUNCTURED:
+ case STV090x_TSMODE_SERIAL_CONTINUOUS:
+ default:
+ stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x14);
+ break;
+
+ case STV090x_TSMODE_PARALLEL_PUNCTURED:
+ case STV090x_TSMODE_DVBCI:
+ stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x12);
+ break;
+ }
+ break;
+ }
+ }
+
+ switch (state->config->ts1_mode) {
+ case STV090x_TSMODE_PARALLEL_PUNCTURED:
+ reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+ STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
+ STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
+ if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+ goto err;
+ break;
+
+ case STV090x_TSMODE_DVBCI:
+ reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+ STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
+ STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
+ if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+ goto err;
+ break;
+
+ case STV090x_TSMODE_SERIAL_PUNCTURED:
+ reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+ STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
+ STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
+ if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+ goto err;
+ break;
+
+ case STV090x_TSMODE_SERIAL_CONTINUOUS:
+ reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+ STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
+ STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
+ if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+ goto err;
+ break;
+
+ default:
+ break;
+ }
+
+ switch (state->config->ts2_mode) {
+ case STV090x_TSMODE_PARALLEL_PUNCTURED:
+ reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
+ STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
+ STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
+ if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
+ goto err;
+ break;
+
+ case STV090x_TSMODE_DVBCI:
+ reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
+ STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
+ STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
+ if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
+ goto err;
+ break;
+
+ case STV090x_TSMODE_SERIAL_PUNCTURED:
+ reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
+ STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
+ STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
+ if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
+ goto err;
+ break;
+
+ case STV090x_TSMODE_SERIAL_CONTINUOUS:
+ reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
+ STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
+ STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
+ if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
+ goto err;
+ break;
+
+ default:
+ break;
+ }
+ reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
+ STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01);
+ if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
+ goto err;
+ STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x00);
+ if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
+ goto err;
+
+ reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+ STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01);
+ if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+ goto err;
+ STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x00);
+ if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+ goto err;
+
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_init(struct dvb_frontend *fe)
+{
+ struct stv090x_state *state = fe->demodulator_priv;
+ const struct stv090x_config *config = state->config;
+ u32 reg;
+
+ if (stv090x_wakeup(fe) < 0) {
+ dprintk(FE_ERROR, 1, "Error waking device");
+ goto err;
+ }
+
+ if (stv090x_ldpc_mode(state, state->demod_mode) < 0)
+ goto err;
+
+ reg = STV090x_READ_DEMOD(state, TNRCFG2);
+ STV090x_SETFIELD_Px(reg, TUN_IQSWAP_FIELD, state->inversion);
+ if (STV090x_WRITE_DEMOD(state, TNRCFG2, reg) < 0)
+ goto err;
+ reg = STV090x_READ_DEMOD(state, DEMOD);
+ STV090x_SETFIELD_Px(reg, ROLLOFF_CONTROL_FIELD, state->rolloff);
+ if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
+ goto err;
+
+ if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+ goto err;
+
+ if (config->tuner_set_mode) {
+ if (config->tuner_set_mode(fe, TUNER_WAKE) < 0)
+ goto err;
+ }
+
+ if (config->tuner_init) {
+ if (config->tuner_init(fe) < 0)
+ goto err;
+ }
+
+ if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+ goto err;
+
+ if (stv090x_set_tspath(state) < 0)
+ goto err;
+
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static int stv090x_setup(struct dvb_frontend *fe)
+{
+ struct stv090x_state *state = fe->demodulator_priv;
+ const struct stv090x_config *config = state->config;
+ const struct stv090x_reg *stv090x_initval = NULL;
+ const struct stv090x_reg *stv090x_cut20_val = NULL;
+ unsigned long t1_size = 0, t2_size = 0;
+ u32 reg = 0;
+
+ int i;
+
+ if (state->device == STV0900) {
+ dprintk(FE_DEBUG, 1, "Initializing STV0900");
+ stv090x_initval = stv0900_initval;
+ t1_size = ARRAY_SIZE(stv0900_initval);
+ stv090x_cut20_val = stv0900_cut20_val;
+ t2_size = ARRAY_SIZE(stv0900_cut20_val);
+ } else if (state->device == STV0903) {
+ dprintk(FE_DEBUG, 1, "Initializing STV0903");
+ stv090x_initval = stv0903_initval;
+ t1_size = ARRAY_SIZE(stv0903_initval);
+ stv090x_cut20_val = stv0903_cut20_val;
+ t2_size = ARRAY_SIZE(stv0903_cut20_val);
+ }
+
+ /* STV090x init */
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Stop Demod */
+ goto err;
+
+ msleep(5);
+
+ if (STV090x_WRITE_DEMOD(state, TNRCFG, 0x6c) < 0) /* check register ! (No Tuner Mode) */
+ goto err;
+
+ STV090x_SETFIELD_Px(reg, ENARPT_LEVEL_FIELD, config->repeater_level);
+ if (STV090x_WRITE_DEMOD(state, I2CRPT, reg) < 0) /* repeater OFF */
+ goto err;
+
+ if (stv090x_write_reg(state, STV090x_NCOARSE, 0x13) < 0) /* set PLL divider */
+ goto err;
+ msleep(5);
+ if (stv090x_write_reg(state, STV090x_I2CCFG, 0x08) < 0) /* 1/41 oversampling */
+ goto err;
+ if (stv090x_write_reg(state, STV090x_SYNTCTRL, 0x20 | config->clk_mode) < 0) /* enable PLL */
+ goto err;
+ msleep(5);
+
+ /* write initval */
+ dprintk(FE_DEBUG, 1, "Setting up initial values");
+ for (i = 0; i < t1_size; i++) {
+ if (stv090x_write_reg(state, stv090x_initval[i].addr, stv090x_initval[i].data) < 0)
+ goto err;
+ }
+
+ state->dev_ver = stv090x_read_reg(state, STV090x_MID);
+ if (state->dev_ver >= 0x20) {
+ if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0)
+ goto err;
+
+ /* write cut20_val*/
+ dprintk(FE_DEBUG, 1, "Setting up Cut 2.0 initial values");
+ for (i = 0; i < t2_size; i++) {
+ if (stv090x_write_reg(state, stv090x_cut20_val[i].addr, stv090x_cut20_val[i].data) < 0)
+ goto err;
+ }
+
+ } else if (state->dev_ver < 0x20) {
+ dprintk(FE_ERROR, 1, "ERROR: Unsupported Cut: 0x%02x!",
+ state->dev_ver);
+
+ goto err;
+ } else if (state->dev_ver > 0x30) {
+ /* we shouldn't bail out from here */
+ dprintk(FE_ERROR, 1, "INFO: Cut: 0x%02x probably incomplete support!",
+ state->dev_ver);
+ }
+
+ if (stv090x_write_reg(state, STV090x_TSTRES0, 0x80) < 0)
+ goto err;
+ if (stv090x_write_reg(state, STV090x_TSTRES0, 0x00) < 0)
+ goto err;
+
+ stv090x_set_mclk(state, 135000000, config->xtal); /* 135 Mhz */
+ msleep(5);
+ if (stv090x_write_reg(state, STV090x_SYNTCTRL, 0x20 | config->clk_mode) < 0)
+ goto err;
+ stv090x_get_mclk(state);
+
+ return 0;
+err:
+ dprintk(FE_ERROR, 1, "I/O error");
+ return -1;
+}
+
+static struct dvb_frontend_ops stv090x_ops = {
+
+ .info = {
+ .name = "STV090x Multistandard",
+ .type = FE_QPSK,
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+ .frequency_stepsize = 0,
+ .frequency_tolerance = 0,
+ .symbol_rate_min = 1000000,
+ .symbol_rate_max = 45000000,
+ .caps = FE_CAN_INVERSION_AUTO |
+ FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK |
+ FE_CAN_2G_MODULATION
+ },
+
+ .release = stv090x_release,
+ .init = stv090x_init,
+
+ .sleep = stv090x_sleep,
+ .get_frontend_algo = stv090x_frontend_algo,
+
+ .i2c_gate_ctrl = stv090x_i2c_gate_ctrl,
+
+ .diseqc_send_master_cmd = stv090x_send_diseqc_msg,
+ .diseqc_send_burst = stv090x_send_diseqc_burst,
+ .diseqc_recv_slave_reply = stv090x_recv_slave_reply,
+ .set_tone = stv090x_set_tone,
+
+ .search = stv090x_search,
+ .read_status = stv090x_read_status,
+ .read_ber = stv090x_read_per,
+ .read_signal_strength = stv090x_read_signal_strength,
+ .read_snr = stv090x_read_cnr
+};
+
+
+struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
+ struct i2c_adapter *i2c,
+ enum stv090x_demodulator demod)
+{
+ struct stv090x_state *state = NULL;
+
+ state = kzalloc(sizeof (struct stv090x_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error;
+
+ state->verbose = &verbose;
+ state->config = config;
+ state->i2c = i2c;
+ state->frontend.ops = stv090x_ops;
+ state->frontend.demodulator_priv = state;
+ state->demod = demod;
+ state->demod_mode = config->demod_mode; /* Single or Dual mode */
+ state->device = config->device;
+ state->rolloff = STV090x_RO_35; /* default */
+
+ if (state->demod == STV090x_DEMODULATOR_0)
+ mutex_init(&demod_lock);
+
+ if (stv090x_sleep(&state->frontend) < 0) {
+ dprintk(FE_ERROR, 1, "Error putting device to sleep");
+ goto error;
+ }
+
+ if (stv090x_setup(&state->frontend) < 0) {
+ dprintk(FE_ERROR, 1, "Error setting up device");
+ goto error;
+ }
+ if (stv090x_wakeup(&state->frontend) < 0) {
+ dprintk(FE_ERROR, 1, "Error waking device");
+ goto error;
+ }
+
+ dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x\n",
+ state->device == STV0900 ? "STV0900" : "STV0903",
+ demod,
+ state->dev_ver);
+
+ return &state->frontend;
+
+error:
+ kfree(state);
+ return NULL;
+}
+EXPORT_SYMBOL(stv090x_attach);
+MODULE_PARM_DESC(verbose, "Set Verbosity level");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_DESCRIPTION("STV090x Multi-Std Broadcast frontend");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/stv090x.h b/drivers/media/dvb/frontends/stv090x.h
new file mode 100644
index 000000000000..e968c98bb70f
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv090x.h
@@ -0,0 +1,106 @@
+/*
+ STV0900/0903 Multistandard Broadcast Frontend driver
+ Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+ Copyright (C) ST Microelectronics
+
+ 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.
+*/
+
+#ifndef __STV090x_H
+#define __STV090x_H
+
+enum stv090x_demodulator {
+ STV090x_DEMODULATOR_0 = 1,
+ STV090x_DEMODULATOR_1
+};
+
+enum stv090x_device {
+ STV0903 = 0,
+ STV0900,
+};
+
+enum stv090x_mode {
+ STV090x_DUAL = 0,
+ STV090x_SINGLE
+};
+
+enum stv090x_tsmode {
+ STV090x_TSMODE_SERIAL_PUNCTURED = 1,
+ STV090x_TSMODE_SERIAL_CONTINUOUS,
+ STV090x_TSMODE_PARALLEL_PUNCTURED,
+ STV090x_TSMODE_DVBCI
+};
+
+enum stv090x_clkmode {
+ STV090x_CLK_INT = 0, /* Clk i/p = CLKI */
+ STV090x_CLK_EXT = 2 /* Clk i/p = XTALI */
+};
+
+enum stv090x_i2crpt {
+ STV090x_RPTLEVEL_256 = 0,
+ STV090x_RPTLEVEL_128 = 1,
+ STV090x_RPTLEVEL_64 = 2,
+ STV090x_RPTLEVEL_32 = 3,
+ STV090x_RPTLEVEL_16 = 4,
+ STV090x_RPTLEVEL_8 = 5,
+ STV090x_RPTLEVEL_4 = 6,
+ STV090x_RPTLEVEL_2 = 7,
+};
+
+struct stv090x_config {
+ enum stv090x_device device;
+ enum stv090x_mode demod_mode;
+ enum stv090x_clkmode clk_mode;
+
+ u32 xtal; /* default: 8000000 */
+ u8 address; /* default: 0x68 */
+
+ u32 ref_clk; /* default: 16000000 FIXME to tuner config */
+
+ u8 ts1_mode;
+ u8 ts2_mode;
+
+ enum stv090x_i2crpt repeater_level;
+
+ int (*tuner_init) (struct dvb_frontend *fe);
+ int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode);
+ int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency);
+ int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency);
+ int (*tuner_set_bandwidth) (struct dvb_frontend *fe, u32 bandwidth);
+ int (*tuner_get_bandwidth) (struct dvb_frontend *fe, u32 *bandwidth);
+ int (*tuner_set_bbgain) (struct dvb_frontend *fe, u32 gain);
+ int (*tuner_get_bbgain) (struct dvb_frontend *fe, u32 *gain);
+ int (*tuner_set_refclk) (struct dvb_frontend *fe, u32 refclk);
+ int (*tuner_get_status) (struct dvb_frontend *fe, u32 *status);
+};
+
+#if defined(CONFIG_DVB_STV090x) || (defined(CONFIG_DVB_STV090x_MODULE) && defined(MODULE))
+
+extern struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
+ struct i2c_adapter *i2c,
+ enum stv090x_demodulator demod);
+#else
+
+static inline struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
+ struct i2c_adapter *i2c,
+ enum stv090x_demodulator demod)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif /* CONFIG_DVB_STV090x */
+
+#endif /* __STV090x_H */
diff --git a/drivers/media/dvb/frontends/stv090x_priv.h b/drivers/media/dvb/frontends/stv090x_priv.h
new file mode 100644
index 000000000000..5a4a01740d88
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv090x_priv.h
@@ -0,0 +1,269 @@
+/*
+ STV0900/0903 Multistandard Broadcast Frontend driver
+ Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+ Copyright (C) ST Microelectronics
+
+ 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.
+*/
+
+#ifndef __STV090x_PRIV_H
+#define __STV090x_PRIV_H
+
+#include "dvb_frontend.h"
+
+#define FE_ERROR 0
+#define FE_NOTICE 1
+#define FE_INFO 2
+#define FE_DEBUG 3
+#define FE_DEBUGREG 4
+
+#define dprintk(__y, __z, format, arg...) do { \
+ if (__z) { \
+ if ((verbose > FE_ERROR) && (verbose > __y)) \
+ printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \
+ else if ((verbose > FE_NOTICE) && (verbose > __y)) \
+ printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \
+ else if ((verbose > FE_INFO) && (verbose > __y)) \
+ printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \
+ else if ((verbose > FE_DEBUG) && (verbose > __y)) \
+ printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \
+ } else { \
+ if (verbose > __y) \
+ printk(format, ##arg); \
+ } \
+} while (0)
+
+#define STV090x_READ_DEMOD(__state, __reg) (( \
+ (__state)->demod == STV090x_DEMODULATOR_1) ? \
+ stv090x_read_reg(__state, STV090x_P2_##__reg) : \
+ stv090x_read_reg(__state, STV090x_P1_##__reg))
+
+#define STV090x_WRITE_DEMOD(__state, __reg, __data) (( \
+ (__state)->demod == STV090x_DEMODULATOR_1) ? \
+ stv090x_write_reg(__state, STV090x_P2_##__reg, __data) :\
+ stv090x_write_reg(__state, STV090x_P1_##__reg, __data))
+
+#define STV090x_ADDR_OFFST(__state, __x) (( \
+ (__state->demod) == STV090x_DEMODULATOR_1) ? \
+ STV090x_P1_##__x : \
+ STV090x_P2_##__x)
+
+
+#define STV090x_SETFIELD(mask, bitf, val) (mask = (mask & (~(((1 << STV090x_WIDTH_##bitf) - 1) <<\
+ STV090x_OFFST_##bitf))) | \
+ (val << STV090x_OFFST_##bitf))
+
+#define STV090x_GETFIELD(val, bitf) ((val >> STV090x_OFFST_##bitf) & ((1 << STV090x_WIDTH_##bitf) - 1))
+
+
+#define STV090x_SETFIELD_Px(mask, bitf, val) (mask = (mask & (~(((1 << STV090x_WIDTH_Px_##bitf) - 1) <<\
+ STV090x_OFFST_Px_##bitf))) | \
+ (val << STV090x_OFFST_Px_##bitf))
+
+#define STV090x_GETFIELD_Px(val, bitf) ((val >> STV090x_OFFST_Px_##bitf) & ((1 << STV090x_WIDTH_Px_##bitf) - 1))
+
+#define MAKEWORD16(__a, __b) (((__a) << 8) | (__b))
+
+#define MSB(__x) ((__x >> 8) & 0xff)
+#define LSB(__x) (__x & 0xff)
+
+
+#define STV090x_IQPOWER_THRESHOLD 30
+#define STV090x_SEARCH_AGC2_TH_CUT20 700
+#define STV090x_SEARCH_AGC2_TH_CUT30 1200
+
+#define STV090x_SEARCH_AGC2_TH(__ver) \
+ ((__ver <= 0x20) ? \
+ STV090x_SEARCH_AGC2_TH_CUT20 : \
+ STV090x_SEARCH_AGC2_TH_CUT30)
+
+enum stv090x_signal_state {
+ STV090x_NOCARRIER,
+ STV090x_NODATA,
+ STV090x_DATAOK,
+ STV090x_RANGEOK,
+ STV090x_OUTOFRANGE
+};
+
+enum stv090x_fec {
+ STV090x_PR12 = 0,
+ STV090x_PR23,
+ STV090x_PR34,
+ STV090x_PR45,
+ STV090x_PR56,
+ STV090x_PR67,
+ STV090x_PR78,
+ STV090x_PR89,
+ STV090x_PR910,
+ STV090x_PRERR
+};
+
+enum stv090x_modulation {
+ STV090x_QPSK,
+ STV090x_8PSK,
+ STV090x_16APSK,
+ STV090x_32APSK,
+ STV090x_UNKNOWN
+};
+
+enum stv090x_frame {
+ STV090x_LONG_FRAME,
+ STV090x_SHORT_FRAME
+};
+
+enum stv090x_pilot {
+ STV090x_PILOTS_OFF,
+ STV090x_PILOTS_ON
+};
+
+enum stv090x_rolloff {
+ STV090x_RO_35,
+ STV090x_RO_25,
+ STV090x_RO_20
+};
+
+enum stv090x_inversion {
+ STV090x_IQ_AUTO,
+ STV090x_IQ_NORMAL,
+ STV090x_IQ_SWAP
+};
+
+enum stv090x_modcod {
+ STV090x_DUMMY_PLF = 0,
+ STV090x_QPSK_14,
+ STV090x_QPSK_13,
+ STV090x_QPSK_25,
+ STV090x_QPSK_12,
+ STV090x_QPSK_35,
+ STV090x_QPSK_23,
+ STV090x_QPSK_34,
+ STV090x_QPSK_45,
+ STV090x_QPSK_56,
+ STV090x_QPSK_89,
+ STV090x_QPSK_910,
+ STV090x_8PSK_35,
+ STV090x_8PSK_23,
+ STV090x_8PSK_34,
+ STV090x_8PSK_56,
+ STV090x_8PSK_89,
+ STV090x_8PSK_910,
+ STV090x_16APSK_23,
+ STV090x_16APSK_34,
+ STV090x_16APSK_45,
+ STV090x_16APSK_56,
+ STV090x_16APSK_89,
+ STV090x_16APSK_910,
+ STV090x_32APSK_34,
+ STV090x_32APSK_45,
+ STV090x_32APSK_56,
+ STV090x_32APSK_89,
+ STV090x_32APSK_910,
+ STV090x_MODCODE_UNKNOWN
+};
+
+enum stv090x_search {
+ STV090x_SEARCH_DSS = 0,
+ STV090x_SEARCH_DVBS1,
+ STV090x_SEARCH_DVBS2,
+ STV090x_SEARCH_AUTO
+};
+
+enum stv090x_algo {
+ STV090x_BLIND_SEARCH,
+ STV090x_COLD_SEARCH,
+ STV090x_WARM_SEARCH
+};
+
+enum stv090x_delsys {
+ STV090x_ERROR = 0,
+ STV090x_DVBS1 = 1,
+ STV090x_DVBS2,
+ STV090x_DSS
+};
+
+struct stv090x_long_frame_crloop {
+ enum stv090x_modcod modcod;
+
+ u8 crl_pilots_on_2;
+ u8 crl_pilots_off_2;
+ u8 crl_pilots_on_5;
+ u8 crl_pilots_off_5;
+ u8 crl_pilots_on_10;
+ u8 crl_pilots_off_10;
+ u8 crl_pilots_on_20;
+ u8 crl_pilots_off_20;
+ u8 crl_pilots_on_30;
+ u8 crl_pilots_off_30;
+};
+
+struct stv090x_short_frame_crloop {
+ enum stv090x_modulation modulation;
+
+ u8 crl_2; /* SR < 3M */
+ u8 crl_5; /* 3 < SR <= 7M */
+ u8 crl_10; /* 7 < SR <= 15M */
+ u8 crl_20; /* 10 < SR <= 25M */
+ u8 crl_30; /* 10 < SR <= 45M */
+};
+
+struct stv090x_reg {
+ u16 addr;
+ u8 data;
+};
+
+struct stv090x_tab {
+ s32 real;
+ s32 read;
+};
+
+struct stv090x_state {
+ enum stv090x_device device;
+ enum stv090x_demodulator demod;
+ enum stv090x_mode demod_mode;
+ u32 dev_ver;
+
+ struct i2c_adapter *i2c;
+ const struct stv090x_config *config;
+ struct dvb_frontend frontend;
+
+ u32 *verbose; /* Cached module verbosity */
+
+ enum stv090x_delsys delsys;
+ enum stv090x_fec fec;
+ enum stv090x_modulation modulation;
+ enum stv090x_modcod modcod;
+ enum stv090x_search search_mode;
+ enum stv090x_frame frame_len;
+ enum stv090x_pilot pilots;
+ enum stv090x_rolloff rolloff;
+ enum stv090x_inversion inversion;
+ enum stv090x_algo algo;
+
+ u32 frequency;
+ u32 srate;
+
+ s32 mclk; /* Masterclock Divider factor */
+ s32 tuner_bw;
+
+ u32 tuner_refclk;
+
+ s32 search_range;
+
+ s32 DemodTimeout;
+ s32 FecTimeout;
+};
+
+#endif /* __STV090x_PRIV_H */
diff --git a/drivers/media/dvb/frontends/stv090x_reg.h b/drivers/media/dvb/frontends/stv090x_reg.h
new file mode 100644
index 000000000000..57b6abbbd32d
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv090x_reg.h
@@ -0,0 +1,2373 @@
+/*
+ STV0900/0903 Multistandard Broadcast Frontend driver
+ Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+ Copyright (C) ST Microelectronics
+
+ 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.
+*/
+
+#ifndef __STV090x_REG_H
+#define __STV090x_REG_H
+
+#define STV090x_MID 0xf100
+#define STV090x_OFFST_MCHIP_IDENT_FIELD 4
+#define STV090x_WIDTH_MCHIP_IDENT_FIELD 4
+#define STV090x_OFFST_MRELEASE_FIELD 0
+#define STV090x_WIDTH_MRELEASE_FIELD 4
+
+#define STV090x_DACR1 0xf113
+#define STV090x_OFFST_DACR1_MODE_FIELD 5
+#define STV090x_WIDTH_DACR1_MODE_FIELD 3
+#define STV090x_OFFST_DACR1_VALUE_FIELD 0
+#define STV090x_WIDTH_DACR1_VALUE_FIELD 4
+
+#define STV090x_DACR2 0xf114
+#define STV090x_OFFST_DACR2_VALUE_FIELD 0
+#define STV090x_WIDTH_DACR2_VALUE_FIELD 8
+
+#define STV090x_OUTCFG 0xf11c
+#define STV090x_OFFST_OUTSERRS1_HZ_FIELD 6
+#define STV090x_WIDTH_OUTSERRS1_HZ_FIELD 1
+#define STV090x_OFFST_OUTSERRS2_HZ_FIELD 5
+#define STV090x_WIDTH_OUTSERRS2_HZ_FIELD 1
+#define STV090x_OFFST_OUTSERRS3_HZ_FIELD 4
+#define STV090x_WIDTH_OUTPARRS3_HZ_FIELD 1
+#define STV090x_OFFST_OUTPARRS3_HZ_FIELD 3
+#define STV090x_WIDTH_OUTPARRS3_HZ_FIELD 1
+
+#define STV090x_MODECFG 0xf11d
+
+#define STV090x_IRQSTATUS3 0xf120
+#define STV090x_OFFST_SPLL_LOCK_FIELD 5
+#define STV090x_WIDTH_SPLL_LOCK_FIELD 1
+#define STV090x_OFFST_SSTREAM_LCK_3_FIELD 4
+#define STV090x_WIDTH_SSTREAM_LCK_3_FIELD 1
+#define STV090x_OFFST_SSTREAM_LCK_2_FIELD 3
+#define STV090x_WIDTH_SSTREAM_LCK_2_FIELD 1
+#define STV090x_OFFST_SSTREAM_LCK_1_FIELD 2
+#define STV090x_WIDTH_SSTREAM_LCK_1_FIELD 1
+#define STV090x_OFFST_SDVBS1_PRF_2_FIELD 1
+#define STV090x_WIDTH_SDVBS1_PRF_2_FIELD 1
+#define STV090x_OFFST_SDVBS1_PRF_1_FIELD 0
+#define STV090x_WIDTH_SDVBS1_PRF_1_FIELD 1
+
+#define STV090x_IRQSTATUS2 0xf121
+#define STV090x_OFFST_SSPY_ENDSIM_3_FIELD 7
+#define STV090x_WIDTH_SSPY_ENDSIM_3_FIELD 1
+#define STV090x_OFFST_SSPY_ENDSIM_2_FIELD 6
+#define STV090x_WIDTH_SSPY_ENDSIM_2_FIELD 1
+#define STV090x_OFFST_SSPY_ENDSIM_1_FIELD 5
+#define STV090x_WIDTH_SSPY_ENDSIM_1_FIELD 1
+#define STV090x_OFFST_SPKTDEL_ERROR_2_FIELD 4
+#define STV090x_WIDTH_SPKTDEL_ERROR_2_FIELD 1
+#define STV090x_OFFST_SPKTDEL_LOCKB_2_FIELD 3
+#define STV090x_WIDTH_SPKTDEL_LOCKB_2_FIELD 1
+#define STV090x_OFFST_SPKTDEL_LOCK_2_FIELD 2
+#define STV090x_WIDTH_SPKTDEL_LOCK_2_FIELD 1
+#define STV090x_OFFST_SPKTDEL_ERROR_1_FIELD 1
+#define STV090x_WIDTH_SPKTDEL_ERROR_1_FIELD 1
+#define STV090x_OFFST_SPKTDEL_LOCKB_1_FIELD 0
+#define STV090x_WIDTH_SPKTDEL_LOCKB_1_FIELD 1
+
+#define STV090x_IRQSTATUS1 0xf122
+#define STV090x_OFFST_SPKTDEL_LOCK_1_FIELD 7
+#define STV090x_WIDTH_SPKTDEL_LOCK_1_FIELD 1
+#define STV090x_OFFST_SDEMOD_LOCKB_2_FIELD 2
+#define STV090x_WIDTH_SDEMOD_LOCKB_2_FIELD 1
+#define STV090x_OFFST_SDEMOD_LOCK_2_FIELD 1
+#define STV090x_WIDTH_SDEMOD_LOCK_2_FIELD 1
+#define STV090x_OFFST_SDEMOD_IRQ_2_FIELD 0
+#define STV090x_WIDTH_SDEMOD_IRQ_2_FIELD 1
+
+#define STV090x_IRQSTATUS0 0xf123
+#define STV090x_OFFST_SDEMOD_LOCKB_1_FIELD 7
+#define STV090x_WIDTH_SDEMOD_LOCKB_1_FIELD 1
+#define STV090x_OFFST_SDEMOD_LOCK_1_FIELD 6
+#define STV090x_WIDTH_SDEMOD_LOCK_1_FIELD 1
+#define STV090x_OFFST_SDEMOD_IRQ_1_FIELD 5
+#define STV090x_WIDTH_SDEMOD_IRQ_1_FIELD 1
+#define STV090x_OFFST_SBCH_ERRFLAG_FIELD 4
+#define STV090x_WIDTH_SBCH_ERRFLAG_FIELD 1
+#define STV090x_OFFST_SDISEQC2RX_IRQ_FIELD 3
+#define STV090x_WIDTH_SDISEQC2RX_IRQ_FIELD 1
+#define STV090x_OFFST_SDISEQC2TX_IRQ_FIELD 2
+#define STV090x_WIDTH_SDISEQC2TX_IRQ_FIELD 1
+#define STV090x_OFFST_SDISEQC1RX_IRQ_FIELD 1
+#define STV090x_WIDTH_SDISEQC1RX_IRQ_FIELD 1
+#define STV090x_OFFST_SDISEQC1TX_IRQ_FIELD 0
+#define STV090x_WIDTH_SDISEQC1TX_IRQ_FIELD 1
+
+#define STV090x_IRQMASK3 0xf124
+#define STV090x_OFFST_MPLL_LOCK_FIELD 5
+#define STV090x_WIDTH_MPLL_LOCK_FIELD 1
+#define STV090x_OFFST_MSTREAM_LCK_3_FIELD 2
+#define STV090x_WIDTH_MSTREAM_LCK_3_FIELD 3
+#define STV090x_OFFST_MSTREAM_LCK_2_FIELD 2
+#define STV090x_WIDTH_MSTREAM_LCK_2_FIELD 3
+#define STV090x_OFFST_MSTREAM_LCK_1_FIELD 2
+#define STV090x_WIDTH_MSTREAM_LCK_1_FIELD 3
+#define STV090x_OFFST_MDVBS1_PRF_2_FIELD 1
+#define STV090x_WIDTH_MDVBS1_PRF_2_FIELD 1
+#define STV090x_OFFST_MDVBS1_PRF_1_FIELD 0
+#define STV090x_WIDTH_MDVBS1_PRF_1_FIELD 1
+
+#define STV090x_IRQMASK2 0xf125
+#define STV090x_OFFST_MSPY_ENDSIM_3_FIELD 5
+#define STV090x_WIDTH_MSPY_ENDSIM_3_FIELD 3
+#define STV090x_OFFST_MSPY_ENDSIM_2_FIELD 5
+#define STV090x_WIDTH_MSPY_ENDSIM_2_FIELD 3
+#define STV090x_OFFST_MSPY_ENDSIM_1_FIELD 5
+#define STV090x_WIDTH_MSPY_ENDSIM_1_FIELD 3
+#define STV090x_OFFST_MPKTDEL_ERROR_2_FIELD 4
+#define STV090x_WIDTH_MPKTDEL_ERROR_2_FIELD 1
+#define STV090x_OFFST_MPKTDEL_LOCKB_2_FIELD 3
+#define STV090x_WIDTH_MPKTDEL_LOCKB_2_FIELD 1
+#define STV090x_OFFST_MPKTDEL_LOCK_2_FIELD 2
+#define STV090x_WIDTH_MPKTDEL_LOCK_2_FIELD 1
+#define STV090x_OFFST_MPKTDEL_ERROR_1_FIELD 1
+#define STV090x_WIDTH_MPKTDEL_ERROR_1_FIELD 1
+#define STV090x_OFFST_MPKTDEL_LOCKB_1_FIELD 0
+#define STV090x_WIDTH_MPKTDEL_LOCKB_1_FIELD 1
+
+#define STV090x_IRQMASK1 0xf126
+#define STV090x_OFFST_MPKTDEL_LOCK_1_FIELD 7
+#define STV090x_WIDTH_MPKTDEL_LOCK_1_FIELD 1
+#define STV090x_OFFST_MEXTPINB2_FIELD 6
+#define STV090x_WIDTH_MEXTPINB2_FIELD 1
+#define STV090x_OFFST_MEXTPIN2_FIELD 5
+#define STV090x_WIDTH_MEXTPIN2_FIELD 1
+#define STV090x_OFFST_MEXTPINB1_FIELD 4
+#define STV090x_WIDTH_MEXTPINB1_FIELD 1
+#define STV090x_OFFST_MEXTPIN1_FIELD 3
+#define STV090x_WIDTH_MEXTPIN1_FIELD 1
+#define STV090x_OFFST_MDEMOD_LOCKB_2_FIELD 2
+#define STV090x_WIDTH_MDEMOD_LOCKB_2_FIELD 1
+#define STV090x_OFFST_MDEMOD_LOCK_2_FIELD 1
+#define STV090x_WIDTH_MDEMOD_LOCK_2_FIELD 1
+#define STV090x_OFFST_MDEMOD_IRQ_2_FIELD 0
+#define STV090x_WIDTH_MDEMOD_IRQ_2_FIELD 1
+
+#define STV090x_IRQMASK0 0xf127
+#define STV090x_OFFST_MDEMOD_LOCKB_1_FIELD 7
+#define STV090x_WIDTH_MDEMOD_LOCKB_1_FIELD 1
+#define STV090x_OFFST_MDEMOD_LOCK_1_FIELD 6
+#define STV090x_WIDTH_MDEMOD_LOCK_1_FIELD 1
+#define STV090x_OFFST_MDEMOD_IRQ_1_FIELD 5
+#define STV090x_WIDTH_MDEMOD_IRQ_1_FIELD 1
+#define STV090x_OFFST_MBCH_ERRFLAG_FIELD 4
+#define STV090x_WIDTH_MBCH_ERRFLAG_FIELD 1
+#define STV090x_OFFST_MDISEQC2RX_IRQ_FIELD 3
+#define STV090x_WIDTH_MDISEQC2RX_IRQ_FIELD 1
+#define STV090x_OFFST_MDISEQC2TX_IRQ_FIELD 2
+#define STV090x_WIDTH_MDISEQC2TX_IRQ_FIELD 1
+#define STV090x_OFFST_MDISEQC1RX_IRQ_FIELD 1
+#define STV090x_WIDTH_MDISEQC1RX_IRQ_FIELD 1
+#define STV090x_OFFST_MDISEQC1TX_IRQ_FIELD 0
+#define STV090x_WIDTH_MDISEQC1TX_IRQ_FIELD 1
+
+#define STV090x_I2CCFG 0xf129
+#define STV090x_OFFST_12C_FASTMODE_FIELD 3
+#define STV090x_WIDTH_12C_FASTMODE_FIELD 1
+#define STV090x_OFFST_12CADDR_INC_FIELD 0
+#define STV090x_WIDTH_12CADDR_INC_FIELD 2
+
+#define STV090x_Px_I2CRPT(__x) (0xf12a + (__x - 1) * 0x1)
+#define STV090x_P1_I2CRPT STV090x_Px_I2CRPT(1)
+#define STV090x_P2_I2CRPT STV090x_Px_I2CRPT(2)
+#define STV090x_OFFST_Px_I2CT_ON_FIELD 7
+#define STV090x_WIDTH_Px_I2CT_ON_FIELD 1
+#define STV090x_OFFST_Px_ENARPT_LEVEL_FIELD 4
+#define STV090x_WIDTH_Px_ENARPT_LEVEL_FIELD 3
+#define STV090x_OFFST_Px_SCLT_DELAY_FIELD 3
+#define STV090x_WIDTH_Px_SCLT_DELAY_FIELD 1
+#define STV090x_OFFST_Px_STOP_ENABLE_FIELD 2
+#define STV090x_WIDTH_Px_STOP_ENABLE_FIELD 1
+#define STV090x_OFFST_Px_STOP_SDAT2SDA_FIELD 1
+#define STV090x_WIDTH_Px_STOP_SDAT2SDA_FIELD 1
+
+#define STV090x_CLKI2CFG 0xf140
+#define STV090x_OFFST_CLKI2_OPD_FIELD 7
+#define STV090x_WIDTH_CLKI2_OPD_FIELD 1
+#define STV090x_OFFST_CLKI2_CONFIG_FIELD 1
+#define STV090x_WIDTH_CLKI2_CONFIG_FIELD 6
+#define STV090x_OFFST_CLKI2_XOR_FIELD 0
+#define STV090x_WIDTH_CLKI2_XOR_FIELD 1
+
+#define STV090x_GPIOxCFG(__x) (0xf141 + (__x - 1))
+#define STV090x_GPIO1CFG STV090x_GPIOxCFG(1)
+#define STV090x_GPIO2CFG STV090x_GPIOxCFG(2)
+#define STV090x_GPIO3CFG STV090x_GPIOxCFG(3)
+#define STV090x_GPIO4CFG STV090x_GPIOxCFG(4)
+#define STV090x_GPIO5CFG STV090x_GPIOxCFG(5)
+#define STV090x_GPIO6CFG STV090x_GPIOxCFG(6)
+#define STV090x_GPIO7CFG STV090x_GPIOxCFG(7)
+#define STV090x_GPIO8CFG STV090x_GPIOxCFG(8)
+#define STV090x_GPIO9CFG STV090x_GPIOxCFG(9)
+#define STV090x_GPIO10CFG STV090x_GPIOxCFG(10)
+#define STV090x_GPIO11CFG STV090x_GPIOxCFG(11)
+#define STV090x_GPIO12CFG STV090x_GPIOxCFG(12)
+#define STV090x_GPIO13CFG STV090x_GPIOxCFG(13)
+#define STV090x_OFFST_GPIOx_OPD_FIELD 7
+#define STV090x_WIDTH_GPIOx_OPD_FIELD 1
+#define STV090x_OFFST_GPIOx_CONFIG_FIELD 1
+#define STV090x_WIDTH_GPIOx_CONFIG_FIELD 6
+#define STV090x_OFFST_GPIOx_XOR_FIELD 0
+#define STV090x_WIDTH_GPIOx_XOR_FIELD 1
+
+#define STV090x_CSxCFG(__x) (0xf14e + __x * 0x1)
+#define STV090x_CS0CFG STV090x_CSxCFG(0)
+#define STV090x_CS1CFG STV090x_CSxCFG(1)
+#define STV090x_OFFST_CSX_OPD_FIELD 7
+#define STV090x_WIDTH_CSX_OPD_FIELD 1
+#define STV090x_OFFST_CSX_CONFIG_FIELD 1
+#define STV090x_WIDTH_CSX_CONFIG_FIELD 6
+#define STV090x_OFFST_CSX_XOR_FIELD 0
+#define STV090x_WIDTH_CSX_XOR_FIELD 1
+
+
+#define STV090x_STDBYCFG 0xf150
+#define STV090x_OFFST_STDBY_OPD_FIELD 7
+#define STV090x_WIDTH_STDBY_OPD_FIELD 1
+#define STV090x_OFFST_STDBY_CONFIG_FIELD 1
+#define STV090x_WIDTH_STDBY_CONFIG_FIELD 6
+#define STV090x_OFFST_STDBY_XOR_FIELD 0
+#define STV090x_WIDTH_STDBY_XOR_FIELD 1
+
+#define STV090x_DIRCLKCFG 0xf151
+#define STV090x_OFFST_DIRCLK_OPD_FIELD 7
+#define STV090x_WIDTH_DIRCLK_OPD_FIELD 1
+#define STV090x_OFFST_DIRCLK_CONFIG_FIELD 1
+#define STV090x_WIDTH_DIRCLK_CONFIG_FIELD 6
+#define STV090x_OFFST_DIRCLK_XOR_FIELD 0
+#define STV090x_WIDTH_DIRCLK_XOR_FIELD 1
+
+
+#define STV090x_AGCRFxCFG(__x) (0xf152 + (__x - 1) * 0x4)
+#define STV090x_AGCRF1CFG STV090x_AGCRFxCFG(1)
+#define STV090x_AGCRF2CFG STV090x_AGCRFxCFG(2)
+#define STV090x_OFFST_AGCRFx_OPD_FIELD 7
+#define STV090x_WIDTH_AGCRFx_OPD_FIELD 1
+#define STV090x_OFFST_AGCRFx_CONFIG_FIELD 1
+#define STV090x_WIDTH_AGCRFx_CONFIG_FIELD 6
+#define STV090x_OFFST_AGCRFx_XOR_FIELD 0
+#define STV090x_WIDTH_AGCRFx_XOR_FIELD 1
+
+#define STV090x_SDATxCFG(__x) (0xf153 + (__x - 1) * 0x4)
+#define STV090x_SDAT1CFG STV090x_SDATxCFG(1)
+#define STV090x_SDAT2CFG STV090x_SDATxCFG(2)
+#define STV090x_OFFST_SDATx_OPD_FIELD 7
+#define STV090x_WIDTH_SDATx_OPD_FIELD 1
+#define STV090x_OFFST_SDATx_CONFIG_FIELD 1
+#define STV090x_WIDTH_SDATx_CONFIG_FIELD 6
+#define STV090x_OFFST_SDATx_XOR_FIELD 0
+#define STV090x_WIDTH_SDATx_XOR_FIELD 1
+
+#define STV090x_SCLTxCFG(__x) (0xf154 + (__x - 1) * 0x4)
+#define STV090x_SCLT1CFG STV090x_SCLTxCFG(1)
+#define STV090x_SCLT2CFG STV090x_SCLTxCFG(2)
+#define STV090x_OFFST_SCLTx_OPD_FIELD 7
+#define STV090x_WIDTH_SCLTx_OPD_FIELD 1
+#define STV090x_OFFST_SCLTx_CONFIG_FIELD 1
+#define STV090x_WIDTH_SCLTx_CONFIG_FIELD 6
+#define STV090x_OFFST_SCLTx_XOR_FIELD 0
+#define STV090x_WIDTH_SCLTx_XOR_FIELD 1
+
+#define STV090x_DISEQCOxCFG(__x) (0xf155 + (__x - 1) * 0x4)
+#define STV090x_DISEQCO1CFG STV090x_DISEQCOxCFG(1)
+#define STV090x_DISEQCO2CFG STV090x_DISEQCOxCFG(2)
+#define STV090x_OFFST_DISEQCOx_OPD_FIELD 7
+#define STV090x_WIDTH_DISEQCOx_OPD_FIELD 1
+#define STV090x_OFFST_DISEQCOx_CONFIG_FIELD 1
+#define STV090x_WIDTH_DISEQCOx_CONFIG_FIELD 6
+#define STV090x_OFFST_DISEQCOx_XOR_FIELD 0
+#define STV090x_WIDTH_DISEQCOx_XOR_FIELD 1
+
+#define STV090x_CLKOUT27CFG 0xf15a
+#define STV090x_OFFST_CLKOUT27_OPD_FIELD 7
+#define STV090x_WIDTH_CLKOUT27_OPD_FIELD 1
+#define STV090x_OFFST_CLKOUT27_CONFIG_FIELD 1
+#define STV090x_WIDTH_CLKOUT27_CONFIG_FIELD 6
+#define STV090x_OFFST_CLKOUT27_XOR_FIELD 0
+#define STV090x_WIDTH_CLKOUT27_XOR_FIELD 1
+
+#define STV090x_ERRORxCFG(__x) (0xf15b + (__x - 1) * 0x5)
+#define STV090x_ERROR1CFG STV090x_ERRORxCFG(1)
+#define STV090x_ERROR2CFG STV090x_ERRORxCFG(2)
+#define STV090x_ERROR3CFG STV090x_ERRORxCFG(3)
+#define STV090x_OFFST_ERRORx_OPD_FIELD 7
+#define STV090x_WIDTH_ERRORx_OPD_FIELD 1
+#define STV090x_OFFST_ERRORx_CONFIG_FIELD 1
+#define STV090x_WIDTH_ERRORx_CONFIG_FIELD 6
+#define STV090x_OFFST_ERRORx_XOR_FIELD 0
+#define STV090x_WIDTH_ERRORx_XOR_FIELD 1
+
+#define STV090x_DPNxCFG(__x) (0xf15c + (__x - 1) * 0x5)
+#define STV090x_DPN1CFG STV090x_DPNxCFG(1)
+#define STV090x_DPN2CFG STV090x_DPNxCFG(2)
+#define STV090x_DPN3CFG STV090x_DPNxCFG(3)
+#define STV090x_OFFST_DPNx_OPD_FIELD 7
+#define STV090x_WIDTH_DPNx_OPD_FIELD 1
+#define STV090x_OFFST_DPNx_CONFIG_FIELD 1
+#define STV090x_WIDTH_DPNx_CONFIG_FIELD 6
+#define STV090x_OFFST_DPNx_XOR_FIELD 0
+#define STV090x_WIDTH_DPNx_XOR_FIELD 1
+
+#define STV090x_STROUTxCFG(__x) (0xf15d + (__x - 1) * 0x5)
+#define STV090x_STROUT1CFG STV090x_STROUTxCFG(1)
+#define STV090x_STROUT2CFG STV090x_STROUTxCFG(2)
+#define STV090x_STROUT3CFG STV090x_STROUTxCFG(3)
+#define STV090x_OFFST_STROUTx_OPD_FIELD 7
+#define STV090x_WIDTH_STROUTx_OPD_FIELD 1
+#define STV090x_OFFST_STROUTx_CONFIG_FIELD 1
+#define STV090x_WIDTH_STROUTx_CONFIG_FIELD 6
+#define STV090x_OFFST_STROUTx_XOR_FIELD 0
+#define STV090x_WIDTH_STROUTx_XOR_FIELD 1
+
+#define STV090x_CLKOUTxCFG(__x) (0xf15e + (__x - 1) * 0x5)
+#define STV090x_CLKOUT1CFG STV090x_CLKOUTxCFG(1)
+#define STV090x_CLKOUT2CFG STV090x_CLKOUTxCFG(2)
+#define STV090x_CLKOUT3CFG STV090x_CLKOUTxCFG(3)
+#define STV090x_OFFST_CLKOUTx_OPD_FIELD 7
+#define STV090x_WIDTH_CLKOUTx_OPD_FIELD 1
+#define STV090x_OFFST_CLKOUTx_CONFIG_FIELD 1
+#define STV090x_WIDTH_CLKOUTx_CONFIG_FIELD 6
+#define STV090x_OFFST_CLKOUTx_XOR_FIELD 0
+#define STV090x_WIDTH_CLKOUTx_XOR_FIELD 1
+
+#define STV090x_DATAxCFG(__x) (0xf15f + (__x - 71) * 0x5)
+#define STV090x_DATA71CFG STV090x_DATAxCFG(71)
+#define STV090x_DATA72CFG STV090x_DATAxCFG(72)
+#define STV090x_DATA73CFG STV090x_DATAxCFG(73)
+#define STV090x_OFFST_DATAx_OPD_FIELD 7
+#define STV090x_WIDTH_DATAx_OPD_FIELD 1
+#define STV090x_OFFST_DATAx_CONFIG_FIELD 1
+#define STV090x_WIDTH_DATAx_CONFIG_FIELD 6
+#define STV090x_OFFST_DATAx_XOR_FIELD 0
+#define STV090x_WIDTH_DATAx_XOR_FIELD 1
+
+#define STV090x_NCOARSE 0xf1b3
+#define STV090x_OFFST_M_DIV_FIELD 0
+#define STV090x_WIDTH_M_DIV_FIELD 8
+
+#define STV090x_SYNTCTRL 0xf1b6
+#define STV090x_OFFST_STANDBY_FIELD 7
+#define STV090x_WIDTH_STANDBY_FIELD 1
+#define STV090x_OFFST_BYPASSPLLCORE_FIELD 6
+#define STV090x_WIDTH_BYPASSPLLCORE_FIELD 1
+#define STV090x_OFFST_SELX1RATIO_FIELD 5
+#define STV090x_WIDTH_SELX1RATIO_FIELD 1
+#define STV090x_OFFST_STOP_PLL_FIELD 3
+#define STV090x_WIDTH_SELX1RATIO_FIELD 1
+#define STV090x_OFFST_BYPASSPLLFSK_FIELD 2
+#define STV090x_WIDTH_BYPASSPLLFSK_FIELD 1
+#define STV090x_OFFST_SELOSCI_FIELD 1
+#define STV090x_WIDTH_SELOSCI_FIELD 1
+#define STV090x_OFFST_BYPASSPLLADC_FIELD 0
+#define STV090x_WIDTH_BYPASSPLLADC_FIELD 1
+
+#define STV090x_FILTCTRL 0xf1b7
+#define STV090x_OFFST_INV_CLK135_FIELD 7
+#define STV090x_WIDTH_INV_CLK135_FIELD 1
+#define STV090x_OFFST_SEL_FSKCKDIV_FIELD 2
+#define STV090x_WIDTH_SEL_FSKCKDIV_FIELD 1
+#define STV090x_OFFST_INV_CLKFSK_FIELD 1
+#define STV090x_WIDTH_INV_CLKFSK_FIELD 1
+#define STV090x_OFFST_BYPASS_APPLI_FIELD 0
+#define STV090x_WIDTH_BYPASS_APPLI_FIELD 1
+
+#define STV090x_PLLSTAT 0xf1b8
+#define STV090x_OFFST_PLLLOCK_FIELD 0
+#define STV090x_WIDTH_PLLLOCK_FIELD 1
+
+#define STV090x_STOPCLK1 0xf1c2
+#define STV090x_OFFST_STOP_CLKPKDT2_FIELD 6
+#define STV090x_WIDTH_STOP_CLKPKDT2_FIELD 1
+#define STV090x_OFFST_STOP_CLKPKDT1_FIELD 5
+#define STV090x_WIDTH_STOP_CLKPKDT1_FIELD 1
+#define STV090x_OFFST_STOP_CLKFEC_FIELD 4
+#define STV090x_WIDTH_STOP_CLKFEC_FIELD 1
+#define STV090x_OFFST_STOP_CLKADCI2_FIELD 3
+#define STV090x_WIDTH_STOP_CLKADCI2_FIELD 1
+#define STV090x_OFFST_INV_CLKADCI2_FIELD 2
+#define STV090x_WIDTH_INV_CLKADCI2_FIELD 1
+#define STV090x_OFFST_STOP_CLKADCI1_FIELD 1
+#define STV090x_WIDTH_STOP_CLKADCI1_FIELD 1
+#define STV090x_OFFST_INV_CLKADCI1_FIELD 0
+#define STV090x_WIDTH_INV_CLKADCI1_FIELD 1
+
+#define STV090x_STOPCLK2 0xf1c3
+#define STV090x_OFFST_STOP_CLKSAMP2_FIELD 4
+#define STV090x_WIDTH_STOP_CLKSAMP2_FIELD 1
+#define STV090x_OFFST_STOP_CLKSAMP1_FIELD 3
+#define STV090x_WIDTH_STOP_CLKSAMP1_FIELD 1
+#define STV090x_OFFST_STOP_CLKVIT2_FIELD 2
+#define STV090x_WIDTH_STOP_CLKVIT2_FIELD 1
+#define STV090x_OFFST_STOP_CLKVIT1_FIELD 1
+#define STV090x_WIDTH_STOP_CLKVIT1_FIELD 1
+#define STV090x_OFFST_STOP_CLKTS_FIELD 0
+#define STV090x_WIDTH_STOP_CLKTS_FIELD 1
+
+#define STV090x_TSTTNR0 0xf1df
+#define STV090x_OFFST_SEL_FSK_FIELD 7
+#define STV090x_WIDTH_SEL_FSK_FIELD 1
+#define STV090x_OFFST_FSK_PON_FIELD 2
+#define STV090x_WIDTH_FSK_PON_FIELD 1
+
+#define STV090x_TSTTNR1 0xf1e0
+#define STV090x_OFFST_ADC1_PON_FIELD 1
+#define STV090x_WIDTH_ADC1_PON_FIELD 1
+#define STV090x_OFFST_ADC1_INMODE_FIELD 0
+#define STV090x_WIDTH_ADC1_INMODE_FIELD 1
+
+#define STV090x_TSTTNR2 0xf1e1
+#define STV090x_OFFST_DISEQC1_PON_FIELD 5
+#define STV090x_WIDTH_DISEQC1_PON_FIELD 1
+
+#define STV090x_TSTTNR3 0xf1e2
+#define STV090x_OFFST_ADC2_PON_FIELD 1
+#define STV090x_WIDTH_ADC2_PON_FIELD 1
+#define STV090x_OFFST_ADC2_INMODE_FIELD 0
+#define STV090x_WIDTH_ADC2_INMODE_FIELD 1
+
+#define STV090x_TSTTNR4 0xf1e3
+#define STV090x_OFFST_DISEQC2_PON_FIELD 5
+#define STV090x_WIDTH_DISEQC2_PON_FIELD 1
+
+#define STV090x_FSKTFC2 0xf170
+#define STV090x_OFFST_FSKT_KMOD_FIELD 2
+#define STV090x_WIDTH_FSKT_KMOD_FIELD 6
+#define STV090x_OFFST_FSKT_CAR_FIELD 0
+#define STV090x_WIDTH_FSKT_CAR_FIELD 2
+
+#define STV090x_FSKTFC1 0xf171
+#define STV090x_OFFST_FSKTC1_CAR_FIELD 0
+#define STV090x_WIDTH_FSKTC1_CAR_FIELD 8
+
+#define STV090x_FSKTFC0 0xf172
+#define STV090x_OFFST_FSKTC0_CAR_FIELD 0
+#define STV090x_WIDTH_FSKTC0_CAR_FIELD 8
+
+#define STV090x_FSKTDELTAF1 0xf173
+#define STV090x_OFFST_FSKTF1_DELTAF_FIELD 0
+#define STV090x_WIDTH_FSKTF1_DELTAF_FIELD 4
+
+#define STV090x_FSKTDELTAF0 0xf174
+#define STV090x_OFFST_FSKTF0_DELTAF_FIELD 0
+#define STV090x_WIDTH_FSKTF0_DELTAF_FIELD 8
+
+#define STV090x_FSKTCTRL 0xf175
+#define STV090x_OFFST_FSKT_EN_SGN_FIELD 6
+#define STV090x_WIDTH_FSKT_EN_SGN_FIELD 1
+#define STV090x_OFFST_FSKT_MOD_SGN_FIELD 5
+#define STV090x_WIDTH_FSKT_MOD_SGN_FIELD 1
+#define STV090x_OFFST_FSKT_MOD_EN_FIELD 2
+#define STV090x_WIDTH_FSKT_MOD_EN_FIELD 3
+#define STV090x_OFFST_FSKT_DACMODE_FIELD 0
+#define STV090x_WIDTH_FSKT_DACMODE_FIELD 2
+
+#define STV090x_FSKRFC2 0xf176
+#define STV090x_OFFST_FSKRC2_DETSGN_FIELD 6
+#define STV090x_WIDTH_FSKRC2_DETSGN_FIELD 1
+#define STV090x_OFFST_FSKRC2_OUTSGN_FIELD 5
+#define STV090x_WIDTH_FSKRC2_OUTSGN_FIELD 1
+#define STV090x_OFFST_FSKRC2_KAGC_FIELD 2
+#define STV090x_WIDTH_FSKRC2_KAGC_FIELD 3
+#define STV090x_OFFST_FSKRC2_CAR_FIELD 0
+#define STV090x_WIDTH_FSKRC2_CAR_FIELD 2
+
+#define STV090x_FSKRFC1 0xf177
+#define STV090x_OFFST_FSKRC1_CAR_FIELD 0
+#define STV090x_WIDTH_FSKRC1_CAR_FIELD 8
+
+#define STV090x_FSKRFC0 0xf178
+#define STV090x_OFFST_FSKRC0_CAR_FIELD 0
+#define STV090x_WIDTH_FSKRC0_CAR_FIELD 8
+
+#define STV090x_FSKRK1 0xf179
+#define STV090x_OFFST_FSKR_K1_EXP_FIELD 5
+#define STV090x_WIDTH_FSKR_K1_EXP_FIELD 3
+#define STV090x_OFFST_FSKR_K1_MANT_FIELD 0
+#define STV090x_WIDTH_FSKR_K1_MANT_FIELD 5
+
+#define STV090x_FSKRK2 0xf17a
+#define STV090x_OFFST_FSKR_K2_EXP_FIELD 5
+#define STV090x_WIDTH_FSKR_K2_EXP_FIELD 3
+#define STV090x_OFFST_FSKR_K2_MANT_FIELD 0
+#define STV090x_WIDTH_FSKR_K2_MANT_FIELD 5
+
+#define STV090x_FSKRAGCR 0xf17b
+#define STV090x_OFFST_FSKR_OUTCTL_FIELD 6
+#define STV090x_WIDTH_FSKR_OUTCTL_FIELD 2
+#define STV090x_OFFST_FSKR_AGC_REF_FIELD 0
+#define STV090x_WIDTH_FSKR_AGC_REF_FIELD 6
+
+#define STV090x_FSKRAGC 0xf17c
+#define STV090x_OFFST_FSKR_AGC_ACCU_FIELD 0
+#define STV090x_WIDTH_FSKR_AGC_ACCU_FIELD 8
+
+#define STV090x_FSKRALPHA 0xf17d
+#define STV090x_OFFST_FSKR_ALPHA_EXP_FIELD 2
+#define STV090x_WIDTH_FSKR_ALPHA_EXP_FIELD 3
+#define STV090x_OFFST_FSKR_ALPHA_M_FIELD 0
+#define STV090x_WIDTH_FSKR_ALPHA_M_FIELD 2
+
+#define STV090x_FSKRPLTH1 0xf17e
+#define STV090x_OFFST_FSKR_BETA_FIELD 4
+#define STV090x_WIDTH_FSKR_BETA_FIELD 4
+#define STV090x_OFFST_FSKR_PLL_TRESH1_FIELD 0
+#define STV090x_WIDTH_FSKR_PLL_TRESH1_FIELD 4
+
+#define STV090x_FSKRPLTH0 0xf17f
+#define STV090x_OFFST_FSKR_PLL_TRESH0_FIELD 0
+#define STV090x_WIDTH_FSKR_PLL_TRESH0_FIELD 8
+
+#define STV090x_FSKRDF1 0xf180
+#define STV090x_OFFST_FSKR_DELTAF1_FIELD 0
+#define STV090x_WIDTH_FSKR_DELTAF1_FIELD 5
+
+#define STV090x_FSKRDF0 0xf181
+#define STV090x_OFFST_FSKR_DELTAF0_FIELD 0
+#define STV090x_WIDTH_FSKR_DELTAF0_FIELD 8
+
+#define STV090x_FSKRSTEPP 0xf182
+#define STV090x_OFFST_FSKR_STEP_PLUS_FIELD 0
+#define STV090x_WIDTH_FSKR_STEP_PLUS_FIELD 8
+
+#define STV090x_FSKRSTEPM 0xf183
+#define STV090x_OFFST_FSKR_STEP_MINUS_FIELD 0
+#define STV090x_WIDTH_FSKR_STEP_MINUS_FIELD 8
+
+#define STV090x_FSKRDET1 0xf184
+#define STV090x_OFFST_FSKR_CARDET1_ACCU_FIELD 0
+#define STV090x_WIDTH_FSKR_CARDET1_ACCU_FIELD 4
+
+#define STV090x_FSKRDET0 0xf185
+#define STV090x_OFFST_FSKR_CARDET0_ACCU_FIELD 0
+#define STV090x_WIDTH_FSKR_CARDET0_ACCU_FIELD 8
+
+#define STV090x_FSKRDTH1 0xf186
+#define STV090x_OFFST_FSKR_CARLOSS_THRESH1_FIELD 4
+#define STV090x_WIDTH_FSKR_CARLOSS_THRESH1_FIELD 4
+#define STV090x_OFFST_FSKR_CARDET_THRESH1_FIELD 0
+#define STV090x_WIDTH_FSKR_CARDET_THRESH1_FIELD 4
+
+#define STV090x_FSKRDTH0 0xf187
+#define STV090x_OFFST_FSKR_CARDET_THRESH0_FIELD 0
+#define STV090x_WIDTH_FSKR_CARDET_THRESH0_FIELD 8
+
+#define STV090x_FSKRLOSS 0xf188
+#define STV090x_OFFST_FSKR_CARLOSS_THRESH_FIELD 0
+#define STV090x_WIDTH_FSKR_CARLOSS_THRESH_FIELD 8
+
+#define STV090x_Px_DISTXCTL(__x) (0xF1A0 - (__x - 1) * 0x10)
+#define STV090x_P1_DISTXCTL STV090x_Px_DISTXCTL(1)
+#define STV090x_P2_DISTXCTL STV090x_Px_DISTXCTL(2)
+#define STV090x_OFFST_Px_TIM_OFF_FIELD 7
+#define STV090x_WIDTH_Px_TIM_OFF_FIELD 1
+#define STV090x_OFFST_Px_DISEQC_RESET_FIELD 6
+#define STV090x_WIDTH_Px_DISEQC_RESET_FIELD 1
+#define STV090x_OFFST_Px_TIM_CMD_FIELD 4
+#define STV090x_WIDTH_Px_TIM_CMD_FIELD 2
+#define STV090x_OFFST_Px_DIS_PRECHARGE_FIELD 3
+#define STV090x_WIDTH_Px_DIS_PRECHARGE_FIELD 1
+#define STV090x_OFFST_Px_DISTX_MODE_FIELD 0
+#define STV090x_WIDTH_Px_DISTX_MODE_FIELD 3
+
+#define STV090x_Px_DISRXCTL(__x) (0xf1a1 - (__x - 1) * 0x10)
+#define STV090x_P1_DISRXCTL STV090x_Px_DISRXCTL(1)
+#define STV090x_P2_DISRXCTL STV090x_Px_DISRXCTL(2)
+#define STV090x_OFFST_Px_RECEIVER_ON_FIELD 7
+#define STV090x_WIDTH_Px_RECEIVER_ON_FIELD 1
+#define STV090x_OFFST_Px_IGNO_SHORT22K_FIELD 6
+#define STV090x_WIDTH_Px_IGNO_SHORT22K_FIELD 1
+#define STV090x_OFFST_Px_ONECHIP_TRX_FIELD 5
+#define STV090x_WIDTH_Px_ONECHIP_TRX_FIELD 1
+#define STV090x_OFFST_Px_EXT_ENVELOP_FIELD 4
+#define STV090x_WIDTH_Px_EXT_ENVELOP_FIELD 1
+#define STV090x_OFFST_Px_PIN_SELECT_FIELD 2
+#define STV090x_WIDTH_Px_PIN_SELECT_FIELD 2
+#define STV090x_OFFST_Px_IRQ_RXEND_FIELD 1
+#define STV090x_WIDTH_Px_IRQ_RXEND_FIELD 1
+#define STV090x_OFFST_Px_IRQ_4NBYTES_FIELD 0
+#define STV090x_WIDTH_Px_IRQ_4NBYTES_FIELD 1
+
+#define STV090x_Px_DISRX_ST0(__x) (0xf1a4 - (__x - 1) * 0x10)
+#define STV090x_P1_DISRX_ST0 STV090x_Px_DISRX_ST0(1)
+#define STV090x_P2_DISRX_ST0 STV090x_Px_DISRX_ST0(2)
+#define STV090x_OFFST_Px_RX_END_FIELD 7
+#define STV090x_WIDTH_Px_RX_END_FIELD 1
+#define STV090x_OFFST_Px_RX_ACTIVE_FIELD 6
+#define STV090x_WIDTH_Px_RX_ACTIVE_FIELD 1
+#define STV090x_OFFST_Px_SHORT_22KHZ_FIELD 5
+#define STV090x_WIDTH_Px_SHORT_22KHZ_FIELD 1
+#define STV090x_OFFST_Px_CONT_TONE_FIELD 4
+#define STV090x_WIDTH_Px_CONT_TONE_FIELD 1
+#define STV090x_OFFST_Px_FIFO_4BREADY_FIELD 3
+#define STV090x_WIDTH_Px_FIFO_4BREADY_FIELD 2
+#define STV090x_OFFST_Px_FIFO_EMPTY_FIELD 2
+#define STV090x_WIDTH_Px_FIFO_EMPTY_FIELD 1
+#define STV090x_OFFST_Px_ABORT_DISRX_FIELD 0
+#define STV090x_WIDTH_Px_ABORT_DISRX_FIELD 1
+
+#define STV090x_Px_DISRX_ST1(__x) (0xf1a5 - (__x - 1) * 0x10)
+#define STV090x_P1_DISRX_ST1 STV090x_Px_DISRX_ST1(1)
+#define STV090x_P2_DISRX_ST1 STV090x_Px_DISRX_ST1(2)
+#define STV090x_OFFST_Px_RX_FAIL_FIELD 7
+#define STV090x_WIDTH_Px_RX_FAIL_FIELD 1
+#define STV090x_OFFST_Px_FIFO_PARITYFAIL_FIELD 6
+#define STV090x_WIDTH_Px_FIFO_PARITYFAIL_FIELD 1
+#define STV090x_OFFST_Px_RX_NONBYTE_FIELD 5
+#define STV090x_WIDTH_Px_RX_NONBYTE_FIELD 1
+#define STV090x_OFFST_Px_FIFO_OVERFLOW_FIELD 4
+#define STV090x_WIDTH_Px_FIFO_OVERFLOW_FIELD 1
+#define STV090x_OFFST_Px_FIFO_BYTENBR_FIELD 0
+#define STV090x_WIDTH_Px_FIFO_BYTENBR_FIELD 4
+
+#define STV090x_Px_DISRXDATA(__x) (0xf1a6 - (__x - 1) * 0x10)
+#define STV090x_P1_DISRXDATA STV090x_Px_DISRXDATA(1)
+#define STV090x_P2_DISRXDATA STV090x_Px_DISRXDATA(2)
+#define STV090x_OFFST_Px_DISRX_DATA_FIELD 0
+#define STV090x_WIDTH_Px_DISRX_DATA_FIELD 8
+
+#define STV090x_Px_DISTXDATA(__x) (0xf1a7 - (__x - 1) * 0x10)
+#define STV090x_P1_DISTXDATA STV090x_Px_DISTXDATA(1)
+#define STV090x_P2_DISTXDATA STV090x_Px_DISTXDATA(2)
+#define STV090x_OFFST_Px_DISEQC_FIFO_FIELD 0
+#define STV090x_WIDTH_Px_DISEQC_FIFO_FIELD 8
+
+#define STV090x_Px_DISTXSTATUS(__x) (0xf1a8 - (__x - 1) * 0x10)
+#define STV090x_P1_DISTXSTATUS STV090x_Px_DISTXSTATUS(1)
+#define STV090x_P2_DISTXSTATUS STV090x_Px_DISTXSTATUS(2)
+#define STV090x_OFFST_Px_TX_FAIL_FIELD 7
+#define STV090x_WIDTH_Px_TX_FAIL_FIELD 1
+#define STV090x_OFFST_Px_FIFO_FULL_FIELD 6
+#define STV090x_WIDTH_Px_FIFO_FULL_FIELD 1
+#define STV090x_OFFST_Px_TX_IDLE_FIELD 5
+#define STV090x_WIDTH_Px_TX_IDLE_FIELD 1
+#define STV090x_OFFST_Px_GAP_BURST_FIELD 4
+#define STV090x_WIDTH_Px_GAP_BURST_FIELD 1
+#define STV090x_OFFST_Px_TXFIFO_BYTES_FIELD 0
+#define STV090x_WIDTH_Px_TXFIFO_BYTES_FIELD 4
+
+#define STV090x_Px_F22TX(__x) (0xf1a9 - (__x - 1) * 0x10)
+#define STV090x_P1_F22TX STV090x_Px_F22TX(1)
+#define STV090x_P2_F22TX STV090x_Px_F22TX(2)
+#define STV090x_OFFST_Px_F22_REG_FIELD 0
+#define STV090x_WIDTH_Px_F22_REG_FIELD 8
+
+#define STV090x_Px_F22RX(__x) (0xf1aa - (__x - 1) * 0x10)
+#define STV090x_P1_F22RX STV090x_Px_F22RX(1)
+#define STV090x_P2_F22RX STV090x_Px_F22RX(2)
+#define STV090x_OFFST_Px_F22RX_REG_FIELD 0
+#define STV090x_WIDTH_Px_F22RX_REG_FIELD 8
+
+#define STV090x_Px_ACRPRESC(__x) (0xf1ac - (__x - 1) * 0x10)
+#define STV090x_P1_ACRPRESC STV090x_Px_ACRPRESC(1)
+#define STV090x_P2_ACRPRESC STV090x_Px_ACRPRESC(2)
+#define STV090x_OFFST_Px_ACR_PRESC_FIELD 0
+#define STV090x_WIDTH_Px_ACR_PRESC_FIELD 3
+
+#define STV090x_Px_ACRDIV(__x) (0xf1ad - (__x - 1) * 0x10)
+#define STV090x_P1_ACRDIV STV090x_Px_ACRDIV(1)
+#define STV090x_P2_ACRDIV STV090x_Px_ACRDIV(2)
+#define STV090x_OFFST_Px_ACR_DIV_FIELD 0
+#define STV090x_WIDTH_Px_ACR_DIV_FIELD 8
+
+#define STV090x_Px_IQCONST(__x) (0xF400 - (__x - 1) * 0x200)
+#define STV090x_P1_IQCONST STV090x_Px_IQCONST(1)
+#define STV090x_P2_IQCONST STV090x_Px_IQCONST(2)
+#define STV090x_OFFST_Px_CONSTEL_SELECT_FIELD 5
+#define STV090x_WIDTH_Px_CONSTEL_SELECT_FIELD 2
+
+#define STV090x_Px_NOSCFG(__x) (0xF401 - (__x - 1) * 0x200)
+#define STV090x_P1_NOSCFG STV090x_Px_NOSCFG(1)
+#define STV090x_P2_NOSCFG STV090x_Px_NOSCFG(2)
+#define STV090x_OFFST_Px_NOSPLH_BETA_FIELD 3
+#define STV090x_WIDTH_Px_NOSPLH_BETA_FIELD 2
+#define STV090x_OFFST_Px_NOSDATA_BETA_FIELD 0
+#define STV090x_WIDTH_Px_NOSDATA_BETA_FIELD 3
+
+#define STV090x_Px_ISYMB(__x) (0xF402 - (__x - 1) * 0x200)
+#define STV090x_P1_ISYMB STV090x_Px_ISYMB(1)
+#define STV090x_P2_ISYMB STV090x_Px_ISYMB(2)
+#define STV090x_OFFST_Px_I_SYMBOL_FIELD 0
+#define STV090x_WIDTH_Px_I_SYMBOL_FIELD 8
+
+#define STV090x_Px_QSYMB(__x) (0xF403 - (__x - 1) * 0x200)
+#define STV090x_P1_QSYMB STV090x_Px_QSYMB(1)
+#define STV090x_P2_QSYMB STV090x_Px_QSYMB(2)
+#define STV090x_OFFST_Px_Q_SYMBOL_FIELD 0
+#define STV090x_WIDTH_Px_Q_SYMBOL_FIELD 8
+
+#define STV090x_Px_AGC1CFG(__x) (0xF404 - (__x - 1) * 0x200)
+#define STV090x_P1_AGC1CFG STV090x_Px_AGC1CFG(1)
+#define STV090x_P2_AGC1CFG STV090x_Px_AGC1CFG(2)
+#define STV090x_OFFST_Px_DC_FROZEN_FIELD 7
+#define STV090x_WIDTH_Px_DC_FROZEN_FIELD 1
+#define STV090x_OFFST_Px_DC_CORRECT_FIELD 6
+#define STV090x_WIDTH_Px_DC_CORRECT_FIELD 1
+#define STV090x_OFFST_Px_AMM_FROZEN_FIELD 5
+#define STV090x_WIDTH_Px_AMM_FROZEN_FIELD 1
+#define STV090x_OFFST_Px_AMM_CORRECT_FIELD 4
+#define STV090x_WIDTH_Px_AMM_CORRECT_FIELD 1
+#define STV090x_OFFST_Px_QUAD_FROZEN_FIELD 3
+#define STV090x_WIDTH_Px_QUAD_FROZEN_FIELD 1
+#define STV090x_OFFST_Px_QUAD_CORRECT_FIELD 2
+#define STV090x_WIDTH_Px_QUAD_CORRECT_FIELD 1
+
+#define STV090x_Px_AGC1CN(__x) (0xF406 - (__x - 1) * 0x200)
+#define STV090x_P1_AGC1CN STV090x_Px_AGC1CN(1)
+#define STV090x_P2_AGC1CN STV090x_Px_AGC1CN(2)
+#define STV090x_WIDTH_Px_AGC1_LOCKED_FIELD 7
+#define STV090x_OFFST_Px_AGC1_LOCKED_FIELD 1
+#define STV090x_OFFST_Px_AGC1_MINPOWER_FIELD 4
+#define STV090x_WIDTH_Px_AGC1_MINPOWER_FIELD 1
+#define STV090x_OFFST_Px_AGCOUT_FAST_FIELD 3
+#define STV090x_WIDTH_Px_AGCOUT_FAST_FIELD 1
+#define STV090x_OFFST_Px_AGCIQ_BETA_FIELD 0
+#define STV090x_WIDTH_Px_AGCIQ_BETA_FIELD 3
+
+#define STV090x_Px_AGC1REF(__x) (0xF407 - (__x - 1) * 0x200)
+#define STV090x_P1_AGC1REF STV090x_Px_AGC1REF(1)
+#define STV090x_P2_AGC1REF STV090x_Px_AGC1REF(2)
+#define STV090x_OFFST_Px_AGCIQ_REF_FIELD 0
+#define STV090x_WIDTH_Px_AGCIQ_REF_FIELD 8
+
+#define STV090x_Px_IDCCOMP(__x) (0xF408 - (__x - 1) * 0x200)
+#define STV090x_P1_IDCCOMP STV090x_Px_IDCCOMP(1)
+#define STV090x_P2_IDCCOMP STV090x_Px_IDCCOMP(2)
+#define STV090x_OFFST_Px_IAVERAGE_ADJ_FIELD 0
+#define STV090x_WIDTH_Px_IAVERAGE_ADJ_FIELD 8
+
+#define STV090x_Px_QDCCOMP(__x) (0xF409 - (__x - 1) * 0x200)
+#define STV090x_P1_QDCCOMP STV090x_Px_QDCCOMP(1)
+#define STV090x_P2_QDCCOMP STV090x_Px_QDCCOMP(2)
+#define STV090x_OFFST_Px_QAVERAGE_ADJ_FIELD 0
+#define STV090x_WIDTH_Px_QAVERAGE_ADJ_FIELD 8
+
+#define STV090x_Px_POWERI(__x) (0xF40A - (__x - 1) * 0x200)
+#define STV090x_P1_POWERI STV090x_Px_POWERI(1)
+#define STV090x_P2_POWERI STV090x_Px_POWERI(2)
+#define STV090x_OFFST_Px_POWER_I_FIELD 0
+#define STV090x_WIDTH_Px_POWER_I_FIELD 8
+
+#define STV090x_Px_POWERQ(__x) (0xF40B - (__x - 1) * 0x200)
+#define STV090x_P1_POWERQ STV090x_Px_POWERQ(1)
+#define STV090x_P2_POWERQ STV090x_Px_POWERQ(2)
+#define STV090x_OFFST_Px_POWER_Q_FIELD 0
+#define STV090x_WIDTH_Px_POWER_Q_FIELD 8
+
+#define STV090x_Px_AGC1AMM(__x) (0xF40C - (__x - 1) * 0x200)
+#define STV090x_P1_AGC1AMM STV090x_Px_AGC1AMM(1)
+#define STV090x_P2_AGC1AMM STV090x_Px_AGC1AMM(2)
+#define STV090x_OFFST_Px_AMM_VALUE_FIELD 0
+#define STV090x_WIDTH_Px_AMM_VALUE_FIELD 8
+
+#define STV090x_Px_AGC1QUAD(__x) (0xF40D - (__x - 1) * 0x200)
+#define STV090x_P1_AGC1QUAD STV090x_Px_AGC1QUAD(1)
+#define STV090x_P2_AGC1QUAD STV090x_Px_AGC1QUAD(2)
+#define STV090x_OFFST_Px_QUAD_VALUE_FIELD 0
+#define STV090x_WIDTH_Px_QUAD_VALUE_FIELD 8
+
+#define STV090x_Px_AGCIQINy(__x, __y) (0xF40F - (__x-1) * 0x200 - __y * 0x1)
+#define STV090x_P1_AGCIQIN0 STV090x_Px_AGCIQINy(1, 0)
+#define STV090x_P1_AGCIQIN1 STV090x_Px_AGCIQINy(1, 1)
+#define STV090x_P2_AGCIQIN0 STV090x_Px_AGCIQINy(2, 0)
+#define STV090x_P2_AGCIQIN1 STV090x_Px_AGCIQINy(2, 1)
+#define STV090x_OFFST_Px_AGCIQ_VALUE_FIELD 0
+#define STV090x_WIDTH_Px_AGCIQ_VALUE_FIELD 8
+
+#define STV090x_Px_DEMOD(__x) (0xF410 - (__x - 1) * 0x200)
+#define STV090x_P1_DEMOD STV090x_Px_DEMOD(1)
+#define STV090x_P2_DEMOD STV090x_Px_DEMOD(2)
+#define STV090x_OFFST_Px_MANUAL_S2ROLLOFF_FIELD 7
+#define STV090x_WIDTH_Px_MANUAL_S2ROLLOFF_FIELD 1
+#define STV090x_OFFST_Px_DEMOD_STOP_FIELD 6
+#define STV090x_WIDTH_Px_DEMOD_STOP_FIELD 1
+#define STV090x_OFFST_Px_SPECINV_CONTROL_FIELD 4
+#define STV090x_WIDTH_Px_SPECINV_CONTROL_FIELD 2
+#define STV090x_OFFST_Px_FORCE_ENASAMP_FIELD 3
+#define STV090x_WIDTH_Px_FORCE_ENASAMP_FIELD 1
+#define STV090x_OFFST_Px_MANUAL_SXROLLOFF_FIELD 2
+#define STV090x_WIDTH_Px_MANUAL_SXROLLOFF_FIELD 1
+#define STV090x_OFFST_Px_ROLLOFF_CONTROL_FIELD 0
+#define STV090x_WIDTH_Px_ROLLOFF_CONTROL_FIELD 2
+
+#define STV090x_Px_DMDMODCOD(__x) (0xF411 - (__x - 1) * 0x200)
+#define STV090x_P1_DMDMODCOD STV090x_Px_DMDMODCOD(1)
+#define STV090x_P2_DMDMODCOD STV090x_Px_DMDMODCOD(2)
+#define STV090x_OFFST_Px_MANUAL_MODCOD_FIELD 7
+#define STV090x_WIDTH_Px_MANUAL_MODCOD_FIELD 1
+#define STV090x_OFFST_Px_DEMOD_MODCOD_FIELD 2
+#define STV090x_WIDTH_Px_DEMOD_MODCOD_FIELD 5
+#define STV090x_OFFST_Px_DEMOD_TYPE_FIELD 0
+#define STV090x_WIDTH_Px_DEMOD_TYPE_FIELD 2
+
+#define STV090x_Px_DSTATUS(__x) (0xF412 - (__x - 1) * 0x200)
+#define STV090x_P1_DSTATUS STV090x_Px_DSTATUS(1)
+#define STV090x_P2_DSTATUS STV090x_Px_DSTATUS(2)
+#define STV090x_OFFST_Px_CAR_LOCK_FIELD 7
+#define STV090x_WIDTH_Px_CAR_LOCK_FIELD 1
+#define STV090x_OFFST_Px_TMGLOCK_QUALITY_FIELD 5
+#define STV090x_WIDTH_Px_TMGLOCK_QUALITY_FIELD 2
+#define STV090x_OFFST_Px_LOCK_DEFINITIF_FIELD 3
+#define STV090x_WIDTH_Px_LOCK_DEFINITIF_FIELD 1
+
+#define STV090x_Px_DSTATUS2(__x) (0xF413 - (__x - 1) * 0x200)
+#define STV090x_P1_DSTATUS2 STV090x_Px_DSTATUS2(1)
+#define STV090x_P2_DSTATUS2 STV090x_Px_DSTATUS2(2)
+#define STV090x_OFFST_Px_DEMOD_DELOCK_FIELD 7
+#define STV090x_WIDTH_Px_DEMOD_DELOCK_FIELD 1
+#define STV090x_OFFST_Px_AGC1_NOSIGNALACK_FIELD 3
+#define STV090x_WIDTH_Px_AGC1_NOSIGNALACK_FIELD 1
+#define STV090x_OFFST_Px_AGC2_OVERFLOW_FIELD 2
+#define STV090x_WIDTH_Px_AGC2_OVERFLOW_FIELD 1
+#define STV090x_OFFST_Px_CFR_OVERFLOW_FIELD 1
+#define STV090x_WIDTH_Px_CFR_OVERFLOW_FIELD 1
+#define STV090x_OFFST_Px_GAMMA_OVERUNDER_FIELD 0
+#define STV090x_WIDTH_Px_GAMMA_OVERUNDER_FIELD 1
+
+#define STV090x_Px_DMDCFGMD(__x) (0xF414 - (__x - 1) * 0x200)
+#define STV090x_P1_DMDCFGMD STV090x_Px_DMDCFGMD(1)
+#define STV090x_P2_DMDCFGMD STV090x_Px_DMDCFGMD(2)
+#define STV090x_OFFST_Px_DVBS2_ENABLE_FIELD 7
+#define STV090x_WIDTH_Px_DVBS2_ENABLE_FIELD 1
+#define STV090x_OFFST_Px_DVBS1_ENABLE_FIELD 6
+#define STV090x_WIDTH_Px_DVBS1_ENABLE_FIELD 1
+#define STV090x_OFFST_Px_CFR_AUTOSCAN_FIELD 5 /* check */
+#define STV090x_WIDTH_Px_CFR_AUTOSCAN_FIELD 1
+#define STV090x_OFFST_Px_SCAN_ENABLE_FIELD 4 /* check */
+#define STV090x_WIDTH_Px_SCAN_ENABLE_FIELD 1
+#define STV090x_OFFST_Px_TUN_AUTOSCAN_FIELD 3
+#define STV090x_WIDTH_Px_TUN_AUTOSCAN_FIELD 1
+#define STV090x_OFFST_Px_NOFORCE_RELOCK_FIELD 2
+#define STV090x_WIDTH_Px_NOFORCE_RELOCK_FIELD 1
+#define STV090x_OFFST_Px_TUN_RNG_FIELD 0
+#define STV090x_WIDTH_Px_TUN_RNG_FIELD 2
+
+#define STV090x_Px_DMDCFG2(__x) (0xF415 - (__x - 1) * 0x200)
+#define STV090x_P1_DMDCFG2 STV090x_Px_DMDCFG2(1)
+#define STV090x_P2_DMDCFG2 STV090x_Px_DMDCFG2(2)
+#define STV090x_OFFST_Px_S1S2_SEQUENTIAL_FIELD 6
+#define STV090x_WIDTH_Px_S1S2_SEQUENTIAL_FIELD 1
+
+#define STV090x_Px_DMDISTATE(__x) (0xF416 - (__x - 1) * 0x200)
+#define STV090x_P1_DMDISTATE STV090x_Px_DMDISTATE(1)
+#define STV090x_P2_DMDISTATE STV090x_Px_DMDISTATE(2)
+#define STV090x_OFFST_Px_I2C_DEMOD_MODE_FIELD 0
+#define STV090x_WIDTH_Px_I2C_DEMOD_MODE_FIELD 5
+
+#define STV090x_Px_DMDTOM(__x) (0xF417 - (__x - 1) * 0x200) /* check */
+#define STV090x_P1_DMDTOM STV090x_Px_DMDTOM(1)
+#define STV090x_P2_DMDTOM STV090x_Px_DMDTOM(2)
+
+#define STV090x_Px_DMDSTATE(__x) (0xF41B - (__x - 1) * 0x200)
+#define STV090x_P1_DMDSTATE STV090x_Px_DMDSTATE(1)
+#define STV090x_P2_DMDSTATE STV090x_Px_DMDSTATE(2)
+#define STV090x_OFFST_Px_HEADER_MODE_FIELD 5
+#define STV090x_WIDTH_Px_HEADER_MODE_FIELD 2
+
+#define STV090x_Px_DMDFLYW(__x) (0xF41C - (__x - 1) * 0x200)
+#define STV090x_P1_DMDFLYW STV090x_Px_DMDFLYW(1)
+#define STV090x_P2_DMDFLYW STV090x_Px_DMDFLYW(2)
+#define STV090x_OFFST_Px_I2C_IRQVAL_FIELD 4
+#define STV090x_WIDTH_Px_I2C_IRQVAL_FIELD 4
+#define STV090x_OFFST_Px_FLYWHEEL_CPT_FIELD 0 /* check */
+#define STV090x_WIDTH_Px_FLYWHEEL_CPT_FIELD 4
+
+#define STV090x_Px_DSTATUS3(__x) (0xF41D - (__x - 1) * 0x200)
+#define STV090x_P1_DSTATUS3 STV090x_Px_DSTATUS3(1)
+#define STV090x_P2_DSTATUS3 STV090x_Px_DSTATUS3(2)
+#define STV090x_OFFST_Px_DEMOD_CFGMODE_FIELD 5
+#define STV090x_WIDTH_Px_DEMOD_CFGMODE_FIELD 2
+
+#define STV090x_Px_DMDCFG3(__x) (0xF41E - (__x - 1) * 0x200)
+#define STV090x_P1_DMDCFG3 STV090x_Px_DMDCFG3(1)
+#define STV090x_P2_DMDCFG3 STV090x_Px_DMDCFG3(2)
+#define STV090x_OFFST_Px_NOSTOP_FIFOFULL_FIELD 3
+#define STV090x_WIDTH_Px_NOSTOP_FIFOFULL_FIELD 1
+
+#define STV090x_Px_DMDCFG4(__x) (0xf41f - (__x - 1) * 0x200)
+#define STV090x_P1_DMDCFG4 STV090x_Px_DMDCFG4(1)
+#define STV090x_P2_DMDCFG4 STV090x_Px_DMDCFG4(2)
+
+#define STV090x_Px_CORRELMANT(__x) (0xF420 - (__x - 1) * 0x200)
+#define STV090x_P1_CORRELMANT STV090x_Px_CORRELMANT(1)
+#define STV090x_P2_CORRELMANT STV090x_Px_CORRELMANT(2)
+#define STV090x_OFFST_Px_CORREL_MANT_FIELD 0
+#define STV090x_WIDTH_Px_CORREL_MANT_FIELD 8
+
+#define STV090x_Px_CORRELABS(__x) (0xF421 - (__x - 1) * 0x200)
+#define STV090x_P1_CORRELABS STV090x_Px_CORRELABS(1)
+#define STV090x_P2_CORRELABS STV090x_Px_CORRELABS(2)
+#define STV090x_OFFST_Px_CORREL_ABS_FIELD 0
+#define STV090x_WIDTH_Px_CORREL_ABS_FIELD 8
+
+#define STV090x_Px_CORRELEXP(__x) (0xF422 - (__x - 1) * 0x200)
+#define STV090x_P1_CORRELEXP STV090x_Px_CORRELEXP(1)
+#define STV090x_P2_CORRELEXP STV090x_Px_CORRELEXP(2)
+#define STV090x_OFFST_Px_CORREL_ABSEXP_FIELD 4
+#define STV090x_WIDTH_Px_CORREL_ABSEXP_FIELD 4
+#define STV090x_OFFST_Px_CORREL_EXP_FIELD 0
+#define STV090x_WIDTH_Px_CORREL_EXP_FIELD 4
+
+#define STV090x_Px_PLHMODCOD(__x) (0xF424 - (__x - 1) * 0x200)
+#define STV090x_P1_PLHMODCOD STV090x_Px_PLHMODCOD(1)
+#define STV090x_P2_PLHMODCOD STV090x_Px_PLHMODCOD(2)
+#define STV090x_OFFST_Px_SPECINV_DEMOD_FIELD 7
+#define STV090x_WIDTH_Px_SPECINV_DEMOD_FIELD 1
+#define STV090x_OFFST_Px_PLH_MODCOD_FIELD 2
+#define STV090x_WIDTH_Px_PLH_MODCOD_FIELD 5
+#define STV090x_OFFST_Px_PLH_TYPE_FIELD 0
+#define STV090x_WIDTH_Px_PLH_TYPE_FIELD 2
+
+#define STV090x_Px_AGCK32(__x) (0xf42b - (__x - 1) * 0x200)
+#define STV090x_P1_AGCK32 STV090x_Px_AGCK32(1)
+#define STV090x_P2_AGCK32 STV090x_Px_AGCK32(2)
+
+#define STV090x_Px_AGC2O(__x) (0xF42C - (__x - 1) * 0x200)
+#define STV090x_P1_AGC2O STV090x_Px_AGC2O(1)
+#define STV090x_P2_AGC2O STV090x_Px_AGC2O(2)
+
+#define STV090x_Px_AGC2REF(__x) (0xF42D - (__x - 1) * 0x200)
+#define STV090x_P1_AGC2REF STV090x_Px_AGC2REF(1)
+#define STV090x_P2_AGC2REF STV090x_Px_AGC2REF(2)
+#define STV090x_OFFST_Px_AGC2_REF_FIELD 0
+#define STV090x_WIDTH_Px_AGC2_REF_FIELD 8
+
+#define STV090x_Px_AGC1ADJ(__x) (0xF42E - (__x - 1) * 0x200)
+#define STV090x_P1_AGC1ADJ STV090x_Px_AGC1ADJ(1)
+#define STV090x_P2_AGC1ADJ STV090x_Px_AGC1ADJ(2)
+#define STV090x_OFFST_Px_AGC1_ADJUSTED_FIELD 0
+#define STV090x_WIDTH_Px_AGC1_ADJUSTED_FIELD 7
+
+#define STV090x_Px_AGC2Iy(__x, __y) (0xF437 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_AGC2I0 STV090x_Px_AGC2Iy(1, 0)
+#define STV090x_P1_AGC2I1 STV090x_Px_AGC2Iy(1, 1)
+#define STV090x_P2_AGC2I0 STV090x_Px_AGC2Iy(2, 0)
+#define STV090x_P2_AGC2I1 STV090x_Px_AGC2Iy(2, 1)
+#define STV090x_OFFST_Px_AGC2_INTEGRATOR_FIELD 0
+#define STV090x_WIDTH_Px_AGC2_INTEGRATOR_FIELD 8
+
+#define STV090x_Px_CARCFG(__x) (0xF438 - (__x - 1) * 0x200)
+#define STV090x_P1_CARCFG STV090x_Px_CARCFG(1)
+#define STV090x_P2_CARCFG STV090x_Px_CARCFG(2)
+#define STV090x_OFFST_Px_EN_CAR2CENTER_FIELD 5
+#define STV090x_WIDTH_Px_EN_CAR2CENTER_FIELD 1
+#define STV090x_OFFST_Px_ROTATON_FIELD 2
+#define STV090x_WIDTH_Px_ROTATON_FIELD 1
+#define STV090x_OFFST_Px_PH_DET_ALGO_FIELD 0
+#define STV090x_WIDTH_Px_PH_DET_ALGO_FIELD 2
+
+#define STV090x_Px_ACLC(__x) (0xF439 - (__x - 1) * 0x200)
+#define STV090x_P1_ACLC STV090x_Px_ACLC(1)
+#define STV090x_P2_ACLC STV090x_Px_ACLC(2)
+#define STV090x_OFFST_Px_CAR_ALPHA_MANT_FIELD 4
+#define STV090x_WIDTH_Px_CAR_ALPHA_MANT_FIELD 2
+#define STV090x_OFFST_Px_CAR_ALPHA_EXP_FIELD 0
+#define STV090x_WIDTH_Px_CAR_ALPHA_EXP_FIELD 4
+
+#define STV090x_Px_BCLC(__x) (0xF43A - (__x - 1) * 0x200)
+#define STV090x_P1_BCLC STV090x_Px_BCLC(1)
+#define STV090x_P2_BCLC STV090x_Px_BCLC(2)
+#define STV090x_OFFST_Px_CAR_BETA_MANT_FIELD 4
+#define STV090x_WIDTH_Px_CAR_BETA_MANT_FIELD 2
+#define STV090x_OFFST_Px_CAR_BETA_EXP_FIELD 0
+#define STV090x_WIDTH_Px_CAR_BETA_EXP_FIELD 4
+
+#define STV090x_Px_CARFREQ(__x) (0xF43D - (__x - 1) * 0x200)
+#define STV090x_P1_CARFREQ STV090x_Px_CARFREQ(1)
+#define STV090x_P2_CARFREQ STV090x_Px_CARFREQ(2)
+#define STV090x_OFFST_Px_KC_COARSE_EXP_FIELD 4
+#define STV090x_WIDTH_Px_KC_COARSE_EXP_FIELD 4
+#define STV090x_OFFST_Px_BETA_FREQ_FIELD 0
+#define STV090x_WIDTH_Px_BETA_FREQ_FIELD 4
+
+#define STV090x_Px_CARHDR(__x) (0xF43E - (__x - 1) * 0x200)
+#define STV090x_P1_CARHDR STV090x_Px_CARHDR(1)
+#define STV090x_P2_CARHDR STV090x_Px_CARHDR(2)
+#define STV090x_OFFST_Px_FREQ_HDR_FIELD 0
+#define STV090x_WIDTH_Px_FREQ_HDR_FIELD 8
+
+#define STV090x_Px_LDT(__x) (0xF43F - (__x - 1) * 0x200)
+#define STV090x_P1_LDT STV090x_Px_LDT(1)
+#define STV090x_P2_LDT STV090x_Px_LDT(2)
+#define STV090x_OFFST_Px_CARLOCK_THRES_FIELD 0
+#define STV090x_WIDTH_Px_CARLOCK_THRES_FIELD 8
+
+#define STV090x_Px_LDT2(__x) (0xF440 - (__x - 1) * 0x200)
+#define STV090x_P1_LDT2 STV090x_Px_LDT2(1)
+#define STV090x_P2_LDT2 STV090x_Px_LDT2(2)
+#define STV090x_OFFST_Px_CARLOCK_THRES2_FIELD 0
+#define STV090x_WIDTH_Px_CARLOCK_THRES2_FIELD 8
+
+#define STV090x_Px_CFRICFG(__x) (0xF441 - (__x - 1) * 0x200)
+#define STV090x_P1_CFRICFG STV090x_Px_CFRICFG(1)
+#define STV090x_P2_CFRICFG STV090x_Px_CFRICFG(2)
+#define STV090x_OFFST_Px_NEG_CFRSTEP_FIELD 0
+#define STV090x_WIDTH_Px_NEG_CFRSTEP_FIELD 1
+
+#define STV090x_Pn_CFRUPy(__x, __y) (0xF443 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_CFRUP0 STV090x_Pn_CFRUPy(1, 0)
+#define STV090x_P1_CFRUP1 STV090x_Pn_CFRUPy(1, 1)
+#define STV090x_P2_CFRUP0 STV090x_Pn_CFRUPy(2, 0)
+#define STV090x_P2_CFRUP1 STV090x_Pn_CFRUPy(2, 1)
+#define STV090x_OFFST_Px_CFR_UP_FIELD 0
+#define STV090x_WIDTH_Px_CFR_UP_FIELD 8
+
+#define STV090x_Pn_CFRLOWy(__x, __y) (0xF447 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_CFRLOW0 STV090x_Pn_CFRLOWy(1, 0)
+#define STV090x_P1_CFRLOW1 STV090x_Pn_CFRLOWy(1, 1)
+#define STV090x_P2_CFRLOW0 STV090x_Pn_CFRLOWy(2, 0)
+#define STV090x_P2_CFRLOW1 STV090x_Pn_CFRLOWy(2, 1)
+#define STV090x_OFFST_Px_CFR_LOW_FIELD 0
+#define STV090x_WIDTH_Px_CFR_LOW_FIELD 8
+
+#define STV090x_Pn_CFRINITy(__x, __y) (0xF449 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_CFRINIT0 STV090x_Pn_CFRINITy(1, 0)
+#define STV090x_P1_CFRINIT1 STV090x_Pn_CFRINITy(1, 1)
+#define STV090x_P2_CFRINIT0 STV090x_Pn_CFRINITy(2, 0)
+#define STV090x_P2_CFRINIT1 STV090x_Pn_CFRINITy(2, 1)
+#define STV090x_OFFST_Px_CFR_INIT_FIELD 0
+#define STV090x_WIDTH_Px_CFR_INIT_FIELD 8
+
+#define STV090x_Px_CFRINC1(__x) (0xF44A - (__x - 1) * 0x200)
+#define STV090x_P1_CFRINC1 STV090x_Px_CFRINC1(1)
+#define STV090x_P2_CFRINC1 STV090x_Px_CFRINC1(2)
+#define STV090x_OFFST_Px_CFR_INC1_FIELD 0
+#define STV090x_WIDTH_Px_CFR_INC1_FIELD 7
+
+#define STV090x_Px_CFRINC0(__x) (0xF44B - (__x - 1) * 0x200)
+#define STV090x_P1_CFRINC0 STV090x_Px_CFRINC0(1)
+#define STV090x_P2_CFRINC0 STV090x_Px_CFRINC0(2)
+#define STV090x_OFFST_Px_CFR_INC0_FIELD 4
+#define STV090x_WIDTH_Px_CFR_INC0_FIELD 4
+
+#define STV090x_Pn_CFRy(__x, __y) (0xF44E - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_CFR0 STV090x_Pn_CFRy(1, 0)
+#define STV090x_P1_CFR1 STV090x_Pn_CFRy(1, 1)
+#define STV090x_P1_CFR2 STV090x_Pn_CFRy(1, 2)
+#define STV090x_P2_CFR0 STV090x_Pn_CFRy(2, 0)
+#define STV090x_P2_CFR1 STV090x_Pn_CFRy(2, 1)
+#define STV090x_P2_CFR2 STV090x_Pn_CFRy(2, 2)
+#define STV090x_OFFST_Px_CAR_FREQ_FIELD 0
+#define STV090x_WIDTH_Px_CAR_FREQ_FIELD 8
+
+#define STV090x_Px_LDI(__x) (0xF44F - (__x - 1) * 0x200)
+#define STV090x_P1_LDI STV090x_Px_LDI(1)
+#define STV090x_P2_LDI STV090x_Px_LDI(2)
+#define STV090x_OFFST_Px_LOCK_DET_INTEGR_FIELD 0
+#define STV090x_WIDTH_Px_LOCK_DET_INTEGR_FIELD 8
+
+#define STV090x_Px_TMGCFG(__x) (0xF450 - (__x - 1) * 0x200)
+#define STV090x_P1_TMGCFG STV090x_Px_TMGCFG(1)
+#define STV090x_P2_TMGCFG STV090x_Px_TMGCFG(2)
+#define STV090x_OFFST_Px_TMGLOCK_BETA_FIELD 6
+#define STV090x_WIDTH_Px_TMGLOCK_BETA_FIELD 2
+#define STV090x_OFFST_Px_DO_TIMING_FIELD 4
+#define STV090x_WIDTH_Px_DO_TIMING_FIELD 1
+#define STV090x_OFFST_Px_TMG_MINFREQ_FIELD 0
+#define STV090x_WIDTH_Px_TMG_MINFREQ_FIELD 2
+
+#define STV090x_Px_RTC(__x) (0xF451 - (__x - 1) * 0x200)
+#define STV090x_P1_RTC STV090x_Px_RTC(1)
+#define STV090x_P2_RTC STV090x_Px_RTC(2)
+#define STV090x_OFFST_Px_TMGALPHA_EXP_FIELD 4
+#define STV090x_WIDTH_Px_TMGALPHA_EXP_FIELD 4
+#define STV090x_OFFST_Px_TMGBETA_EXP_FIELD 0
+#define STV090x_WIDTH_Px_TMGBETA_EXP_FIELD 4
+
+#define STV090x_Px_RTCS2(__x) (0xF452 - (__x - 1) * 0x200)
+#define STV090x_P1_RTCS2 STV090x_Px_RTCS2(1)
+#define STV090x_P2_RTCS2 STV090x_Px_RTCS2(2)
+#define STV090x_OFFST_Px_TMGALPHAS2_EXP_FIELD 4
+#define STV090x_WIDTH_Px_TMGALPHAS2_EXP_FIELD 4
+#define STV090x_OFFST_Px_TMGBETAS2_EXP_FIELD 0
+#define STV090x_WIDTH_Px_TMGBETAS2_EXP_FIELD 4
+
+#define STV090x_Px_TMGTHRISE(__x) (0xF453 - (__x - 1) * 0x200)
+#define STV090x_P1_TMGTHRISE STV090x_Px_TMGTHRISE(1)
+#define STV090x_P2_TMGTHRISE STV090x_Px_TMGTHRISE(2)
+#define STV090x_OFFST_Px_TMGLOCK_THRISE_FIELD 0
+#define STV090x_WIDTH_Px_TMGLOCK_THRISE_FIELD 8
+
+#define STV090x_Px_TMGTHFALL(__x) (0xF454 - (__x - 1) * 0x200)
+#define STV090x_P1_TMGTHFALL STV090x_Px_TMGTHFALL(1)
+#define STV090x_P2_TMGTHFALL STV090x_Px_TMGTHFALL(2)
+#define STV090x_OFFST_Px_TMGLOCK_THFALL_FIELD 0
+#define STV090x_WIDTH_Px_TMGLOCK_THFALL_FIELD 8
+
+#define STV090x_Px_SFRUPRATIO(__x) (0xF455 - (__x - 1) * 0x200)
+#define STV090x_P1_SFRUPRATIO STV090x_Px_SFRUPRATIO(1)
+#define STV090x_P2_SFRUPRATIO STV090x_Px_SFRUPRATIO(2)
+#define STV090x_OFFST_Px_SFR_UPRATIO_FIELD 0
+#define STV090x_WIDTH_Px_SFR_UPRATIO_FIELD 8
+
+#define STV090x_Px_SFRLOWRATIO(__x) (0xF456 - (__x - 1) * 0x200)
+#define STV090x_P1_SFRLOWRATIO STV090x_Px_SFRLOWRATIO(1)
+#define STV090x_P2_SFRLOWRATIO STV090x_Px_SFRLOWRATIO(2)
+#define STV090x_OFFST_Px_SFR_LOWRATIO_FIELD 0
+#define STV090x_WIDTH_Px_SFR_LOWRATIO_FIELD 8
+
+#define STV090x_Px_KREFTMG(__x) (0xF458 - (__x - 1) * 0x200)
+#define STV090x_P1_KREFTMG STV090x_Px_KREFTMG(1)
+#define STV090x_P2_KREFTMG STV090x_Px_KREFTMG(2)
+#define STV090x_OFFST_Px_KREF_TMG_FIELD 0
+#define STV090x_WIDTH_Px_KREF_TMG_FIELD 8
+
+#define STV090x_Px_SFRSTEP(__x) (0xF459 - (__x - 1) * 0x200)
+#define STV090x_P1_SFRSTEP STV090x_Px_SFRSTEP(1)
+#define STV090x_P2_SFRSTEP STV090x_Px_SFRSTEP(2)
+#define STV090x_OFFST_Px_SFR_SCANSTEP_FIELD 4
+#define STV090x_WIDTH_Px_SFR_SCANSTEP_FIELD 4
+#define STV090x_OFFST_Px_SFR_CENTERSTEP_FIELD 0
+#define STV090x_WIDTH_Px_SFR_CENTERSTEP_FIELD 4
+
+#define STV090x_Px_TMGCFG2(__x) (0xF45A - (__x - 1) * 0x200)
+#define STV090x_P1_TMGCFG2 STV090x_Px_TMGCFG2(1)
+#define STV090x_P2_TMGCFG2 STV090x_Px_TMGCFG2(2)
+#define STV090x_OFFST_Px_SFRRATIO_FINE_FIELD 0
+#define STV090x_WIDTH_Px_SFRRATIO_FINE_FIELD 1
+
+#define STV090x_Px_SFRINIT1(__x) (0xF45E - (__x - 1) * 0x200)
+#define STV090x_P1_SFRINIT1 STV090x_Px_SFRINIT1(1)
+#define STV090x_P2_SFRINIT1 STV090x_Px_SFRINIT1(2)
+#define STV090x_OFFST_Px_SFR_INIT_FIELD 0
+#define STV090x_WIDTH_Px_SFR_INIT_FIELD 8
+
+#define STV090x_Px_SFRINIT0(__x) (0xF45F - (__x - 1) * 0x200)
+#define STV090x_P1_SFRINIT0 STV090x_Px_SFRINIT0(1)
+#define STV090x_P2_SFRINIT0 STV090x_Px_SFRINIT0(2)
+#define STV090x_OFFST_Px_SFR_INIT_FIELD 0
+#define STV090x_WIDTH_Px_SFR_INIT_FIELD 8
+
+#define STV090x_Px_SFRUP1(__x) (0xF460 - (__x - 1) * 0x200)
+#define STV090x_P1_SFRUP1 STV090x_Px_SFRUP1(1)
+#define STV090x_P2_SFRUP1 STV090x_Px_SFRUP1(2)
+#define STV090x_OFFST_Px_SYMB_FREQ_UP1_FIELD 0
+#define STV090x_WIDTH_Px_SYMB_FREQ_UP1_FIELD 7
+
+#define STV090x_Px_SFRUP0(__x) (0xF461 - (__x - 1) * 0x200)
+#define STV090x_P1_SFRUP0 STV090x_Px_SFRUP0(1)
+#define STV090x_P2_SFRUP0 STV090x_Px_SFRUP0(2)
+#define STV090x_OFFST_Px_SYMB_FREQ_UP0_FIELD 0
+#define STV090x_WIDTH_Px_SYMB_FREQ_UP0_FIELD 8
+
+#define STV090x_Px_SFRLOW1(__x) (0xF462 - (__x - 1) * 0x200)
+#define STV090x_P1_SFRLOW1 STV090x_Px_SFRLOW1(1)
+#define STV090x_P2_SFRLOW1 STV090x_Px_SFRLOW1(2)
+#define STV090x_OFFST_Px_SYMB_FREQ_LOW1_FIELD 0
+#define STV090x_WIDTH_Px_SYMB_FREQ_LOW1_FIELD 7
+
+#define STV090x_Px_SFRLOW0(__x) (0xF463 - (__x - 1) * 0x200)
+#define STV090x_P1_SFRLOW0 STV090x_Px_SFRLOW0(1)
+#define STV090x_P2_SFRLOW0 STV090x_Px_SFRLOW0(2)
+#define STV090x_OFFST_Px_SYMB_FREQ_LOW0_FIELD 0
+#define STV090x_WIDTH_Px_SYMB_FREQ_LOW0_FIELD 8
+
+#define STV090x_Px_SFRy(__x, __y) (0xF464 - (__x-1) * 0x200 + (3 - __y))
+#define STV090x_P1_SFR0 STV090x_Px_SFRy(1, 0)
+#define STV090x_P1_SFR1 STV090x_Px_SFRy(1, 1)
+#define STV090x_P1_SFR2 STV090x_Px_SFRy(1, 2)
+#define STV090x_P1_SFR3 STV090x_Px_SFRy(1, 3)
+#define STV090x_P2_SFR0 STV090x_Px_SFRy(2, 0)
+#define STV090x_P2_SFR1 STV090x_Px_SFRy(2, 1)
+#define STV090x_P2_SFR2 STV090x_Px_SFRy(2, 2)
+#define STV090x_P2_SFR3 STV090x_Px_SFRy(2, 3)
+#define STV090x_OFFST_Px_SYMB_FREQ_FIELD 0
+#define STV090x_WIDTH_Px_SYMB_FREQ_FIELD 32
+
+#define STV090x_Px_TMGREG2(__x) (0xF468 - (__x - 1) * 0x200)
+#define STV090x_P1_TMGREG2 STV090x_Px_TMGREG2(1)
+#define STV090x_P2_TMGREG2 STV090x_Px_TMGREG2(2)
+#define STV090x_OFFST_Px_TMGREG_FIELD 0
+#define STV090x_WIDTH_Px_TMGREG_FIELD 8
+
+#define STV090x_Px_TMGREG1(__x) (0xF469 - (__x - 1) * 0x200)
+#define STV090x_P1_TMGREG1 STV090x_Px_TMGREG1(1)
+#define STV090x_P2_TMGREG1 STV090x_Px_TMGREG1(2)
+#define STV090x_OFFST_Px_TMGREG_FIELD 0
+#define STV090x_WIDTH_Px_TMGREG_FIELD 8
+
+#define STV090x_Px_TMGREG0(__x) (0xF46A - (__x - 1) * 0x200)
+#define STV090x_P1_TMGREG0 STV090x_Px_TMGREG0(1)
+#define STV090x_P2_TMGREG0 STV090x_Px_TMGREG0(2)
+#define STV090x_OFFST_Px_TMGREG_FIELD 0
+#define STV090x_WIDTH_Px_TMGREG_FIELD 8
+
+#define STV090x_Px_TMGLOCKy(__x, __y) (0xF46C - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_TMGLOCK0 STV090x_Px_TMGLOCKy(1, 0)
+#define STV090x_P1_TMGLOCK1 STV090x_Px_TMGLOCKy(1, 1)
+#define STV090x_P2_TMGLOCK0 STV090x_Px_TMGLOCKy(2, 0)
+#define STV090x_P2_TMGLOCK1 STV090x_Px_TMGLOCKy(2, 1)
+#define STV090x_OFFST_Px_TMGLOCK_LEVEL_FIELD 0
+#define STV090x_WIDTH_Px_TMGLOCK_LEVEL_FIELD 8
+
+#define STV090x_Px_TMGOBS(__x) (0xF46D - (__x - 1) * 0x200)
+#define STV090x_P1_TMGOBS STV090x_Px_TMGOBS(1)
+#define STV090x_P2_TMGOBS STV090x_Px_TMGOBS(2)
+#define STV090x_OFFST_Px_ROLLOFF_STATUS_FIELD 6
+#define STV090x_WIDTH_Px_ROLLOFF_STATUS_FIELD 2
+
+#define STV090x_Px_EQUALCFG(__x) (0xF46F - (__x - 1) * 0x200)
+#define STV090x_P1_EQUALCFG STV090x_Px_EQUALCFG(1)
+#define STV090x_P2_EQUALCFG STV090x_Px_EQUALCFG(2)
+#define STV090x_OFFST_Px_EQUAL_ON_FIELD 6
+#define STV090x_WIDTH_Px_EQUAL_ON_FIELD 1
+#define STV090x_OFFST_Px_MU_EQUALDFE_FIELD 0
+#define STV090x_WIDTH_Px_MU_EQUALDFE_FIELD 3
+
+#define STV090x_Px_EQUAIy(__x, __y) (0xf470 - (__x - 1) * 0x200 + (__y - 1))
+#define STV090x_P1_EQUAI1 STV090x_Px_EQUAIy(1, 1)
+#define STV090x_P1_EQUAI2 STV090x_Px_EQUAIy(1, 2)
+#define STV090x_P1_EQUAI3 STV090x_Px_EQUAIy(1, 3)
+#define STV090x_P1_EQUAI4 STV090x_Px_EQUAIy(1, 4)
+#define STV090x_P1_EQUAI5 STV090x_Px_EQUAIy(1, 5)
+#define STV090x_P1_EQUAI6 STV090x_Px_EQUAIy(1, 6)
+#define STV090x_P1_EQUAI7 STV090x_Px_EQUAIy(1, 7)
+#define STV090x_P1_EQUAI8 STV090x_Px_EQUAIy(1, 8)
+
+#define STV090x_P2_EQUAI1 STV090x_Px_EQUAIy(2, 1)
+#define STV090x_P2_EQUAI2 STV090x_Px_EQUAIy(2, 2)
+#define STV090x_P2_EQUAI3 STV090x_Px_EQUAIy(2, 3)
+#define STV090x_P2_EQUAI4 STV090x_Px_EQUAIy(2, 4)
+#define STV090x_P2_EQUAI5 STV090x_Px_EQUAIy(2, 5)
+#define STV090x_P2_EQUAI6 STV090x_Px_EQUAIy(2, 6)
+#define STV090x_P2_EQUAI7 STV090x_Px_EQUAIy(2, 7)
+#define STV090x_P2_EQUAI8 STV090x_Px_EQUAIy(2, 8)
+#define STV090x_OFFST_Px_EQUA_ACCIy_FIELD 0
+#define STV090x_WIDTH_Px_EQUA_ACCIy_FIELD 8
+
+#define STV090x_Px_EQUAQy(__x, __y) (0xf471 - (__x - 1) * 0x200 + (__y - 1))
+#define STV090x_P1_EQUAQ1 STV090x_Px_EQUAQy(1, 1)
+#define STV090x_P1_EQUAQ2 STV090x_Px_EQUAQy(1, 2)
+#define STV090x_P1_EQUAQ3 STV090x_Px_EQUAQy(1, 3)
+#define STV090x_P1_EQUAQ4 STV090x_Px_EQUAQy(1, 4)
+#define STV090x_P1_EQUAQ5 STV090x_Px_EQUAQy(1, 5)
+#define STV090x_P1_EQUAQ6 STV090x_Px_EQUAQy(1, 6)
+#define STV090x_P1_EQUAQ7 STV090x_Px_EQUAQy(1, 7)
+#define STV090x_P1_EQUAQ8 STV090x_Px_EQUAQy(1, 8)
+
+#define STV090x_P2_EQUAQ1 STV090x_Px_EQUAQy(2, 1)
+#define STV090x_P2_EQUAQ2 STV090x_Px_EQUAQy(2, 2)
+#define STV090x_P2_EQUAQ3 STV090x_Px_EQUAQy(2, 3)
+#define STV090x_P2_EQUAQ4 STV090x_Px_EQUAQy(2, 4)
+#define STV090x_P2_EQUAQ5 STV090x_Px_EQUAQy(2, 5)
+#define STV090x_P2_EQUAQ6 STV090x_Px_EQUAQy(2, 6)
+#define STV090x_P2_EQUAQ7 STV090x_Px_EQUAQy(2, 7)
+#define STV090x_P2_EQUAQ8 STV090x_Px_EQUAQy(2, 8)
+#define STV090x_OFFST_Px_EQUA_ACCQy_FIELD 0
+#define STV090x_WIDTH_Px_EQUA_ACCQy_FIELD 8
+
+#define STV090x_Px_NNOSDATATy(__x, __y) (0xf481 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NNOSDATAT0 STV090x_Px_NNOSDATATy(1, 0)
+#define STV090x_P1_NNOSDATAT1 STV090x_Px_NNOSDATATy(1, 1)
+#define STV090x_P2_NNOSDATAT0 STV090x_Px_NNOSDATATy(2, 0)
+#define STV090x_P2_NNOSDATAT1 STV090x_Px_NNOSDATATy(2, 1)
+#define STV090x_OFFST_Px_NOSDATAT_NORMED_FIELD 0
+#define STV090x_WIDTH_Px_NOSDATAT_NORMED_FIELD 8
+
+#define STV090x_Px_NNOSDATAy(__x, __y) (0xf483 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NNOSDATA0 STV090x_Px_NNOSDATAy(1, 0)
+#define STV090x_P1_NNOSDATA1 STV090x_Px_NNOSDATAy(1, 1)
+#define STV090x_P2_NNOSDATA0 STV090x_Px_NNOSDATAy(2, 0)
+#define STV090x_P2_NNOSDATA1 STV090x_Px_NNOSDATAy(2, 1)
+#define STV090x_OFFST_Px_NOSDATA_NORMED_FIELD 0
+#define STV090x_WIDTH_Px_NOSDATA_NORMED_FIELD 8
+
+#define STV090x_Px_NNOSPLHTy(__x, __y) (0xf485 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NNOSPLHT0 STV090x_Px_NNOSPLHTy(1, 0)
+#define STV090x_P1_NNOSPLHT1 STV090x_Px_NNOSPLHTy(1, 1)
+#define STV090x_P2_NNOSPLHT0 STV090x_Px_NNOSPLHTy(2, 0)
+#define STV090x_P2_NNOSPLHT1 STV090x_Px_NNOSPLHTy(2, 1)
+#define STV090x_OFFST_Px_NOSPLHT_NORMED_FIELD 0
+#define STV090x_WIDTH_Px_NOSPLHT_NORMED_FIELD 8
+
+#define STV090x_Px_NNOSPLHy(__x, __y) (0xf487 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NNOSPLH0 STV090x_Px_NNOSPLHy(1, 0)
+#define STV090x_P1_NNOSPLH1 STV090x_Px_NNOSPLHy(1, 1)
+#define STV090x_P2_NNOSPLH0 STV090x_Px_NNOSPLHy(2, 0)
+#define STV090x_P2_NNOSPLH1 STV090x_Px_NNOSPLHy(2, 1)
+#define STV090x_OFFST_Px_NOSPLH_NORMED_FIELD 0
+#define STV090x_WIDTH_Px_NOSPLH_NORMED_FIELD 8
+
+#define STV090x_Px_NOSDATATy(__x, __y) (0xf489 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NOSDATAT0 STV090x_Px_NOSDATATy(1, 0)
+#define STV090x_P1_NOSDATAT1 STV090x_Px_NOSDATATy(1, 1)
+#define STV090x_P2_NOSDATAT0 STV090x_Px_NOSDATATy(2, 0)
+#define STV090x_P2_NOSDATAT1 STV090x_Px_NOSDATATy(2, 1)
+#define STV090x_OFFST_Px_NOSDATAT_UNNORMED_FIELD 0
+#define STV090x_WIDTH_Px_NOSDATAT_UNNORMED_FIELD 8
+
+#define STV090x_Px_NOSDATAy(__x, __y) (0xf48b - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NOSDATA0 STV090x_Px_NOSDATAy(1, 0)
+#define STV090x_P1_NOSDATA1 STV090x_Px_NOSDATAy(1, 1)
+#define STV090x_P2_NOSDATA0 STV090x_Px_NOSDATAy(2, 0)
+#define STV090x_P2_NOSDATA1 STV090x_Px_NOSDATAy(2, 1)
+#define STV090x_OFFST_Px_NOSDATA_UNNORMED_FIELD 0
+#define STV090x_WIDTH_Px_NOSDATA_UNNORMED_FIELD 8
+
+#define STV090x_Px_NOSPLHTy(__x, __y) (0xf48d - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NOSPLHT0 STV090x_Px_NOSPLHTy(1, 0)
+#define STV090x_P1_NOSPLHT1 STV090x_Px_NOSPLHTy(1, 1)
+#define STV090x_P2_NOSPLHT0 STV090x_Px_NOSPLHTy(2, 0)
+#define STV090x_P2_NOSPLHT1 STV090x_Px_NOSPLHTy(2, 1)
+#define STV090x_OFFST_Px_NOSPLHT_UNNORMED_FIELD 0
+#define STV090x_WIDTH_Px_NOSPLHT_UNNORMED_FIELD 8
+
+#define STV090x_Px_NOSPLHy(__x, __y) (0xf48f - (__x - 1) * 0x200 - __y * 0x1)
+#define STv090x_P1_NOSPLH0 STV090x_Px_NOSPLHy(1, 0)
+#define STv090x_P1_NOSPLH1 STV090x_Px_NOSPLHy(1, 1)
+#define STv090x_P2_NOSPLH0 STV090x_Px_NOSPLHy(2, 0)
+#define STv090x_P2_NOSPLH1 STV090x_Px_NOSPLHy(2, 1)
+#define STV090x_OFFST_Px_NOSPLH_UNNORMED_FIELD 0
+#define STV090x_WIDTH_Px_NOSPLH_UNNORMED_FIELD 8
+
+#define STV090x_Px_CAR2CFG(__x) (0xf490 - (__x - 1) * 0x200)
+#define STV090x_P1_CAR2CFG STV090x_Px_CAR2CFG(1)
+#define STV090x_P2_CAR2CFG STV090x_Px_CAR2CFG(2)
+#define STV090x_OFFST_Px_PN4_SELECT_FIELD 6
+#define STV090x_WIDTH_Px_PN4_SELECT_FIELD 1
+#define STV090x_OFFST_Px_CFR2_STOPDVBS1_FIELD 5
+#define STV090x_WIDTH_Px_CFR2_STOPDVBS1_FIELD 1
+#define STV090x_OFFST_Px_ROTA2ON_FIELD 2
+#define STV090x_WIDTH_Px_ROTA2ON_FIELD 1
+#define STV090x_OFFST_Px_PH_DET_ALGO2_FIELD 0
+#define STV090x_WIDTH_Px_PH_DET_ALGO2_FIELD 2
+
+#define STV090x_Px_ACLC2(__x) (0xf491 - (__x - 1) * 0x200)
+#define STV090x_P1_ACLC2 STV090x_Px_ACLC2(1)
+#define STV090x_P2_ACLC2 STV090x_Px_ACLC2(2)
+#define STV090x_OFFST_Px_CAR2_ALPHA_MANT_FIELD 4
+#define STV090x_WIDTH_Px_CAR2_ALPHA_MANT_FIELD 2
+#define STV090x_OFFST_Px_CAR2_ALPHA_EXP_FIELD 0
+#define STV090x_WIDTH_Px_CAR2_ALPHA_EXP_FIELD 4
+
+#define STV090x_Px_BCLC2(__x) (0xf492 - (__x - 1) * 0x200)
+#define STV090x_P1_BCLC2 STV090x_Px_BCLC2(1)
+#define STV090x_P2_BCLC2 STV090x_Px_BCLC2(2)
+#define STV090x_OFFST_Px_CAR2_BETA_MANT_FIELD 4
+#define STV090x_WIDTH_Px_CAR2_BETA_MANT_FIELD 2
+#define STV090x_OFFST_Px_CAR2_BETA_EXP_FIELD 0
+#define STV090x_WIDTH_Px_CAR2_BETA_EXP_FIELD 4
+
+#define STV090x_Px_ACLC2S2Q(__x) (0xf497 - (__x - 1) * 0x200)
+#define STV090x_P1_ACLC2S2Q STV090x_Px_ACLC2S2Q(1)
+#define STV090x_P2_ACLC2S2Q STV090x_Px_ACLC2S2Q(2)
+#define STV090x_OFFST_Px_ENAB_SPSKSYMB_FIELD 7
+#define STV090x_WIDTH_Px_ENAB_SPSKSYMB_FIELD 1
+#define STV090x_OFFST_Px_CAR2S2_Q_ALPH_M_FIELD 4
+#define STV090x_WIDTH_Px_CAR2S2_Q_ALPH_M_FIELD 2
+#define STV090x_OFFST_Px_CAR2S2_Q_ALPH_E_FIELD 0
+#define STV090x_WIDTH_Px_CAR2S2_Q_ALPH_E_FIELD 4
+
+#define STV090x_Px_ACLC2S28(__x) (0xf498 - (__x - 1) * 0x200)
+#define STV090x_P1_ACLC2S28 STV090x_Px_ACLC2S28(1)
+#define STV090x_P2_ACLC2S28 STV090x_Px_ACLC2S28(2)
+#define STV090x_OFFST_Px_CAR2S2_8_ALPH_M_FIELD 4
+#define STV090x_WIDTH_Px_CAR2S2_8_ALPH_M_FIELD 2
+#define STV090x_OFFST_Px_CAR2S2_8_ALPH_E_FIELD 0
+#define STV090x_WIDTH_Px_CAR2S2_8_ALPH_E_FIELD 4
+
+#define STV090x_Px_ACLC2S216A(__x) (0xf499 - (__x - 1) * 0x200)
+#define STV090x_P1_ACLC2S216A STV090x_Px_ACLC2S216A(1)
+#define STV090x_P2_ACLC2S216A STV090x_Px_ACLC2S216A(2)
+#define STV090x_OFFST_Px_CAR2S2_16A_ALPH_M_FIELD 4
+#define STV090x_WIDTH_Px_CAR2S2_16A_ALPH_M_FIELD 2
+#define STV090x_OFFST_Px_CAR2S2_16A_ALPH_E_FIELD 0
+#define STV090x_WIDTH_Px_CAR2S2_16A_ALPH_E_FIELD 4
+
+#define STV090x_Px_ACLC2S232A(__x) (0xf499 - (__x - 1) * 0x200)
+#define STV090x_P1_ACLC2S232A STV090x_Px_ACLC2S232A(1)
+#define STV090x_P2_ACLC2S232A STV090x_Px_ACLC2S232A(2)
+#define STV090x_OFFST_Px_CAR2S2_32A_ALPH_M_FIELD 4
+#define STV090x_WIDTH_Px_CAR2S2_32A_ALPH_M_FIELD 2
+#define STV090x_OFFST_Px_CAR2S2_32A_ALPH_E_FIELD 0
+#define STV090x_WIDTH_Px_CAR2S2_32A_ALPH_E_FIELD 4
+
+#define STV090x_Px_BCLC2S2Q(__x) (0xf49c - (__x - 1) * 0x200)
+#define STV090x_P1_BCLC2S2Q STV090x_Px_BCLC2S2Q(1)
+#define STV090x_P2_BCLC2S2Q STV090x_Px_BCLC2S2Q(2)
+#define STV090x_OFFST_Px_CAR2S2_Q_BETA_M_FIELD 4
+#define STV090x_WIDTH_Px_CAR2S2_Q_BETA_M_FIELD 2
+#define STV090x_OFFST_Px_CAR2S2_Q_BETA_E_FIELD 0
+#define STV090x_WIDTH_Px_CAR2S2_Q_BETA_E_FIELD 4
+
+#define STV090x_Px_BCLC2S28(__x) (0xf49d - (__x - 1) * 0x200)
+#define STV090x_P1_BCLC2S28 STV090x_Px_BCLC2S28(1)
+#define STV090x_P2_BCLC2S28 STV090x_Px_BCLC2S28(1)
+#define STV090x_OFFST_Px_CAR2S2_8_BETA_M_FIELD 4
+#define STV090x_WIDTH_Px_CAR2S2_8_BETA_M_FIELD 2
+#define STV090x_OFFST_Px_CAR2S2_8_BETA_E_FIELD 0
+#define STV090x_WIDTH_Px_CAR2S2_8_BETA_E_FIELD 4
+
+#define STV090x_Px_BCLC2S216A(__x) (0xf49d - (__x - 1) * 0x200)
+#define STV090x_P1_BCLC2S216A STV090x_Px_BCLC2S216A(1)
+#define STV090x_P2_BCLC2S216A STV090x_Px_BCLC2S216A(1)
+#define STV090x_OFFST_Px_CAR2S2_16A_BETA_M_FIELD 4
+#define STV090x_WIDTH_Px_CAR2S2_16A_BETA_M_FIELD 2
+#define STV090x_OFFST_Px_CAR2S2_16A_BETA_E_FIELD 0
+#define STV090x_WIDTH_Px_CAR2S2_16A_BETA_E_FIELD 4
+
+#define STV090x_Px_BCLC2S232A(__x) (0xf49d - (__x - 1) * 0x200)
+#define STV090x_P1_BCLC2S232A STV090x_Px_BCLC2S232A(1)
+#define STV090x_P2_BCLC2S232A STV090x_Px_BCLC2S232A(1)
+#define STV090x_OFFST_Px_CAR2S2_32A_BETA_M_FIELD 4
+#define STV090x_WIDTH_Px_CAR2S2_32A_BETA_M_FIELD 2
+#define STV090x_OFFST_Px_CAR2S2_32A_BETA_E_FIELD 0
+#define STV090x_WIDTH_Px_CAR2S2_32A_BETA_E_FIELD 4
+
+#define STV090x_Px_PLROOT2(__x) (0xf4ac - (__x - 1) * 0x200)
+#define STV090x_P1_PLROOT2 STV090x_Px_PLROOT2(1)
+#define STV090x_P2_PLROOT2 STV090x_Px_PLROOT2(2)
+#define STV090x_OFFST_Px_PLSCRAMB_MODE_FIELD 2
+#define STV090x_WIDTH_Px_PLSCRAMB_MODE_FIELD 2
+#define STV090x_OFFST_Px_PLSCRAMB_ROOT_FIELD 0
+#define STV090x_WIDTH_Px_PLSCRAMB_ROOT_FIELD 2
+
+#define STV090x_Px_PLROOT1(__x) (0xf4ad - (__x - 1) * 0x200)
+#define STV090x_P1_PLROOT1 STV090x_Px_PLROOT1(1)
+#define STV090x_P2_PLROOT1 STV090x_Px_PLROOT1(2)
+#define STV090x_OFFST_Px_PLSCRAMB_ROOT1_FIELD 0
+#define STV090x_WIDTH_Px_PLSCRAMB_ROOT1_FIELD 8
+
+#define STV090x_Px_PLROOT0(__x) (0xf4ae - (__x - 1) * 0x200)
+#define STV090x_P1_PLROOT0 STV090x_Px_PLROOT0(1)
+#define STV090x_P2_PLROOT0 STV090x_Px_PLROOT0(2)
+#define STV090x_OFFST_Px_PLSCRAMB_ROOT0_FIELD 0
+#define STV090x_WIDTH_Px_PLSCRAMB_ROOT0_FIELD 8
+
+#define STV090x_Px_MODCODLST0(__x) (0xf4b0 - (__x - 1) * 0x200) /* check */
+#define STV090x_P1_MODCODLST0 STV090x_Px_MODCODLST0(1)
+#define STV090x_P2_MODCODLST0 STV090x_Px_MODCODLST0(2)
+
+#define STV090x_Px_MODCODLST1(__x) (0xf4b1 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST1 STV090x_Px_MODCODLST1(1)
+#define STV090x_P2_MODCODLST1 STV090x_Px_MODCODLST1(2)
+#define STV090x_OFFST_Px_DIS_MODCOD29_FIELD 4
+#define STV090x_WIDTH_Px_DIS_MODCOD29T_FIELD 4
+#define STV090x_OFFST_Px_DIS_32PSK_9_10_FIELD 0
+#define STV090x_WIDTH_Px_DIS_32PSK_9_10_FIELD 4
+
+#define STV090x_Px_MODCODLST2(__x) (0xf4b2 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST2 STV090x_Px_MODCODLST2(1)
+#define STV090x_P2_MODCODLST2 STV090x_Px_MODCODLST2(2)
+#define STV090x_OFFST_Px_DIS_32PSK_8_9_FIELD 4
+#define STV090x_WIDTH_Px_DIS_32PSK_8_9_FIELD 4
+#define STV090x_OFFST_Px_DIS_32PSK_5_6_FIELD 0
+#define STV090x_WIDTH_Px_DIS_32PSK_5_6_FIELD 4
+
+#define STV090x_Px_MODCODLST3(__x) (0xf4b3 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST3 STV090x_Px_MODCODLST3(1)
+#define STV090x_P2_MODCODLST3 STV090x_Px_MODCODLST3(2)
+#define STV090x_OFFST_Px_DIS_32PSK_4_5_FIELD 4
+#define STV090x_WIDTH_Px_DIS_32PSK_4_5_FIELD 4
+#define STV090x_OFFST_Px_DIS_32PSK_3_4_FIELD 0
+#define STV090x_WIDTH_Px_DIS_32PSK_3_4_FIELD 4
+
+#define STV090x_Px_MODCODLST4(__x) (0xf4b4 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST4 STV090x_Px_MODCODLST4(1)
+#define STV090x_P2_MODCODLST4 STV090x_Px_MODCODLST4(2)
+#define STV090x_OFFST_Px_DIS_16PSK_9_10_FIELD 4
+#define STV090x_WIDTH_Px_DIS_16PSK_9_10_FIELD 4
+#define STV090x_OFFST_Px_DIS_16PSK_8_9_FIELD 0
+#define STV090x_WIDTH_Px_DIS_16PSK_8_9_FIELD 4
+
+#define STV090x_Px_MODCODLST5(__x) (0xf4b5 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST5 STV090x_Px_MODCODLST5(1)
+#define STV090x_P2_MODCODLST5 STV090x_Px_MODCODLST5(2)
+#define STV090x_OFFST_Px_DIS_16PSK_5_6_FIELD 4
+#define STV090x_WIDTH_Px_DIS_16PSK_5_6_FIELD 4
+#define STV090x_OFFST_Px_DIS_16PSK_4_5_FIELD 0
+#define STV090x_WIDTH_Px_DIS_16PSK_4_5_FIELD 4
+
+#define STV090x_Px_MODCODLST6(__x) (0xf4b6 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST6 STV090x_Px_MODCODLST6(1)
+#define STV090x_P2_MODCODLST6 STV090x_Px_MODCODLST6(2)
+#define STV090x_OFFST_Px_DIS_16PSK_3_4_FIELD 4
+#define STV090x_WIDTH_Px_DIS_16PSK_3_4_FIELD 4
+#define STV090x_OFFST_Px_DIS_16PSK_2_3_FIELD 0
+#define STV090x_WIDTH_Px_DIS_16PSK_2_3_FIELD 4
+
+#define STV090x_Px_MODCODLST7(__x) (0xf4b7 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST7 STV090x_Px_MODCODLST7(1)
+#define STV090x_P2_MODCODLST7 STV090x_Px_MODCODLST7(2)
+#define STV090x_OFFST_Px_DIS_8P_9_10_FIELD 4
+#define STV090x_WIDTH_Px_DIS_8P_9_10_FIELD 4
+#define STV090x_OFFST_Px_DIS_8P_8_9_FIELD 0
+#define STV090x_WIDTH_Px_DIS_8P_8_9_FIELD 4
+
+#define STV090x_Px_MODCODLST8(__x) (0xf4b8 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST8 STV090x_Px_MODCODLST8(1)
+#define STV090x_P2_MODCODLST8 STV090x_Px_MODCODLST8(2)
+#define STV090x_OFFST_Px_DIS_8P_5_6_FIELD 4
+#define STV090x_WIDTH_Px_DIS_8P_5_6_FIELD 4
+#define STV090x_OFFST_Px_DIS_8P_3_4_FIELD 0
+#define STV090x_WIDTH_Px_DIS_8P_3_4_FIELD 4
+
+#define STV090x_Px_MODCODLST9(__x) (0xf4b9 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST9 STV090x_Px_MODCODLST9(1)
+#define STV090x_P2_MODCODLST9 STV090x_Px_MODCODLST9(2)
+#define STV090x_OFFST_Px_DIS_8P_2_3_FIELD 4
+#define STV090x_WIDTH_Px_DIS_8P_2_3_FIELD 4
+#define STV090x_OFFST_Px_DIS_8P_3_5_FIELD 0
+#define STV090x_WIDTH_Px_DIS_8P_3_5_FIELD 4
+
+#define STV090x_Px_MODCODLSTA(__x) (0xf4ba - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLSTA STV090x_Px_MODCODLSTA(1)
+#define STV090x_P2_MODCODLSTA STV090x_Px_MODCODLSTA(2)
+#define STV090x_OFFST_Px_DIS_QP_9_10_FIELD 4
+#define STV090x_WIDTH_Px_DIS_QP_9_10_FIELD 4
+#define STV090x_OFFST_Px_DIS_QP_8_9_FIELD 0
+#define STV090x_WIDTH_Px_DIS_QP_8_9_FIELD 4
+
+#define STV090x_Px_MODCODLSTB(__x) (0xf4bb - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLSTB STV090x_Px_MODCODLSTB(1)
+#define STV090x_P2_MODCODLSTB STV090x_Px_MODCODLSTB(2)
+#define STV090x_OFFST_Px_DIS_QP_5_6_FIELD 4
+#define STV090x_WIDTH_Px_DIS_QP_5_6_FIELD 4
+#define STV090x_OFFST_Px_DIS_QP_4_5_FIELD 0
+#define STV090x_WIDTH_Px_DIS_QP_4_5_FIELD 4
+
+#define STV090x_Px_MODCODLSTC(__x) (0xf4bc - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLSTC STV090x_Px_MODCODLSTC(1)
+#define STV090x_P2_MODCODLSTC STV090x_Px_MODCODLSTC(2)
+#define STV090x_OFFST_Px_DIS_QP_3_4_FIELD 4
+#define STV090x_WIDTH_Px_DIS_QP_3_4_FIELD 4
+#define STV090x_OFFST_Px_DIS_QP_2_3_FIELD 0
+#define STV090x_WIDTH_Px_DIS_QP_2_3_FIELD 4
+
+#define STV090x_Px_MODCODLSTD(__x) (0xf4bd - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLSTD STV090x_Px_MODCODLSTD(1)
+#define STV090x_P2_MODCODLSTD STV090x_Px_MODCODLSTD(2)
+#define STV090x_OFFST_Px_DIS_QP_3_5_FIELD 4
+#define STV090x_WIDTH_Px_DIS_QP_3_5_FIELD 4
+#define STV090x_OFFST_Px_DIS_QP_1_2_FIELD 0
+#define STV090x_WIDTH_Px_DIS_QP_1_2_FIELD 4
+
+#define STV090x_Px_MODCODLSTE(__x) (0xf4be - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLSTE STV090x_Px_MODCODLSTE(1)
+#define STV090x_P2_MODCODLSTE STV090x_Px_MODCODLSTE(2)
+#define STV090x_OFFST_Px_DIS_QP_2_5_FIELD 4
+#define STV090x_WIDTH_Px_DIS_QP_2_5_FIELD 4
+#define STV090x_OFFST_Px_DIS_QP_1_3_FIELD 0
+#define STV090x_WIDTH_Px_DIS_QP_1_3_FIELD 4
+
+#define STV090x_Px_MODCODLSTF(__x) (0xf4bf - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLSTF STV090x_Px_MODCODLSTF(1)
+#define STV090x_P2_MODCODLSTF STV090x_Px_MODCODLSTF(2)
+#define STV090x_OFFST_Px_DIS_QP_1_4_FIELD 4
+#define STV090x_WIDTH_Px_DIS_QP_1_4_FIELD 4
+
+#define STV090x_Px_GAUSSR0(__x) (0xf4c0 - (__x - 1) * 0x200)
+#define STV090x_P1_GAUSSR0 STV090x_Px_GAUSSR0(1)
+#define STV090x_P2_GAUSSR0 STV090x_Px_GAUSSR0(2)
+#define STV090x_OFFST_Px_EN_CCIMODE_FIELD 7
+#define STV090x_WIDTH_Px_EN_CCIMODE_FIELD 1
+#define STV090x_OFFST_Px_R0_GAUSSIEN_FIELD 0
+#define STV090x_WIDTH_Px_R0_GAUSSIEN_FIELD 7
+
+#define STV090x_Px_CCIR0(__x) (0xf4c1 - (__x - 1) * 0x200)
+#define STV090x_P1_CCIR0 STV090x_Px_CCIR0(1)
+#define STV090x_P2_CCIR0 STV090x_Px_CCIR0(2)
+#define STV090x_OFFST_Px_CCIDETECT_PLH_FIELD 7
+#define STV090x_WIDTH_Px_CCIDETECT_PLH_FIELD 1
+#define STV090x_OFFST_Px_R0_CCI_FIELD 0
+#define STV090x_WIDTH_Px_R0_CCI_FIELD 7
+
+#define STV090x_Px_CCIQUANT(__x) (0xf4c2 - (__x - 1) * 0x200)
+#define STV090x_P1_CCIQUANT STV090x_Px_CCIQUANT(1)
+#define STV090x_P2_CCIQUANT STV090x_Px_CCIQUANT(2)
+#define STV090x_OFFST_Px_CCI_BETA_FIELD 5
+#define STV090x_WIDTH_Px_CCI_BETA_FIELD 3
+#define STV090x_OFFST_Px_CCI_QUANT_FIELD 0
+#define STV090x_WIDTH_Px_CCI_QUANT_FIELD 5
+
+#define STV090x_Px_CCITHRESH(__x) (0xf4c3 - (__x - 1) * 0x200)
+#define STV090x_P1_CCITHRESH STV090x_Px_CCITHRESH(1)
+#define STV090x_P2_CCITHRESH STV090x_Px_CCITHRESH(2)
+#define STV090x_OFFST_Px_CCI_THRESHOLD_FIELD 0
+#define STV090x_WIDTH_Px_CCI_THRESHOLD_FIELD 8
+
+#define STV090x_Px_CCIACC(__x) (0xf4c4 - (__x - 1) * 0x200)
+#define STV090x_P1_CCIACC STV090x_Px_CCIACC(1)
+#define STV090x_P2_CCIACC STV090x_Px_CCIACC(1)
+#define STV090x_OFFST_Px_CCI_VALUE_FIELD 0
+#define STV090x_WIDTH_Px_CCI_VALUE_FIELD 8
+
+#define STV090x_Px_DMDRESCFG(__x) (0xF4C6 - (__x - 1) * 0x200)
+#define STV090x_P1_DMDRESCFG STV090x_Px_DMDRESCFG(1)
+#define STV090x_P2_DMDRESCFG STV090x_Px_DMDRESCFG(2)
+#define STV090x_OFFST_Px_DMDRES_RESET_FIELD 7
+#define STV090x_WIDTH_Px_DMDRES_RESET_FIELD 1
+
+#define STV090x_Px_DMDRESADR(__x) (0xF4C7 - (__x - 1) * 0x200)
+#define STV090x_P1_DMDRESADR STV090x_Px_DMDRESADR(1)
+#define STV090x_P2_DMDRESADR STV090x_Px_DMDRESADR(2)
+#define STV090x_OFFST_Px_DMDRES_RESNBR_FIELD 0
+#define STV090x_WIDTH_Px_DMDRES_RESNBR_FIELD 4
+
+#define STV090x_Px_DMDRESDATAy(__x, __y) (0xF4C8 - (__x - 1) * 0x200 + (7 - __y))
+#define STV090x_P1_DMDRESDATA0 STV090x_Px_DMDRESDATAy(1, 0)
+#define STV090x_P1_DMDRESDATA1 STV090x_Px_DMDRESDATAy(1, 1)
+#define STV090x_P1_DMDRESDATA2 STV090x_Px_DMDRESDATAy(1, 2)
+#define STV090x_P1_DMDRESDATA3 STV090x_Px_DMDRESDATAy(1, 3)
+#define STV090x_P1_DMDRESDATA4 STV090x_Px_DMDRESDATAy(1, 4)
+#define STV090x_P1_DMDRESDATA5 STV090x_Px_DMDRESDATAy(1, 5)
+#define STV090x_P1_DMDRESDATA6 STV090x_Px_DMDRESDATAy(1, 6)
+#define STV090x_P1_DMDRESDATA7 STV090x_Px_DMDRESDATAy(1, 7)
+#define STV090x_P2_DMDRESDATA0 STV090x_Px_DMDRESDATAy(2, 0)
+#define STV090x_P2_DMDRESDATA1 STV090x_Px_DMDRESDATAy(2, 1)
+#define STV090x_P2_DMDRESDATA2 STV090x_Px_DMDRESDATAy(2, 2)
+#define STV090x_P2_DMDRESDATA3 STV090x_Px_DMDRESDATAy(2, 3)
+#define STV090x_P2_DMDRESDATA4 STV090x_Px_DMDRESDATAy(2, 4)
+#define STV090x_P2_DMDRESDATA5 STV090x_Px_DMDRESDATAy(2, 5)
+#define STV090x_P2_DMDRESDATA6 STV090x_Px_DMDRESDATAy(2, 6)
+#define STV090x_P2_DMDRESDATA7 STV090x_Px_DMDRESDATAy(2, 7)
+#define STV090x_OFFST_Px_DMDRES_DATA_FIELD 0
+#define STV090x_WIDTH_Px_DMDRES_DATA_FIELD 8
+
+#define STV090x_Px_FFEIy(__x, __y) (0xf4d0 - (__x - 1) * 0x200 + 0x2 * (__y - 1))
+#define STV090x_P1_FFEI1 STV090x_Px_FFEIy(1, 1)
+#define STV090x_P1_FFEI2 STV090x_Px_FFEIy(1, 2)
+#define STV090x_P1_FFEI3 STV090x_Px_FFEIy(1, 3)
+#define STV090x_P1_FFEI4 STV090x_Px_FFEIy(1, 4)
+#define STV090x_P2_FFEI1 STV090x_Px_FFEIy(2, 1)
+#define STV090x_P2_FFEI2 STV090x_Px_FFEIy(2, 2)
+#define STV090x_P2_FFEI3 STV090x_Px_FFEIy(2, 3)
+#define STV090x_P2_FFEI4 STV090x_Px_FFEIy(2, 4)
+#define STV090x_OFFST_Px_FFE_ACCIy_FIELD 0
+#define STV090x_WIDTH_Px_FFE_ACCIy_FIELD 8
+
+#define STV090x_Px_FFEQy(__x, __y) (0xf4d1 - (__x - 1) * 0x200 + 0x2 * (__y - 1))
+#define STV090x_P1_FFEQ1 STV090x_Px_FFEQy(1, 1)
+#define STV090x_P1_FFEQ2 STV090x_Px_FFEQy(1, 2)
+#define STV090x_P1_FFEQ3 STV090x_Px_FFEQy(1, 3)
+#define STV090x_P1_FFEQ4 STV090x_Px_FFEQy(1, 4)
+#define STV090x_P2_FFEQ1 STV090x_Px_FFEQy(2, 1)
+#define STV090x_P2_FFEQ2 STV090x_Px_FFEQy(2, 2)
+#define STV090x_P2_FFEQ3 STV090x_Px_FFEQy(2, 3)
+#define STV090x_P2_FFEQ4 STV090x_Px_FFEQy(2, 4)
+#define STV090x_OFFST_Px_FFE_ACCQy_FIELD 0
+#define STV090x_WIDTH_Px_FFE_ACCQy_FIELD 8
+
+#define STV090x_Px_FFECFG(__x) (0xf4d8 - (__x - 1) * 0x200)
+#define STV090x_P1_FFECFG STV090x_Px_FFECFG(1)
+#define STV090x_P2_FFECFG STV090x_Px_FFECFG(2)
+#define STV090x_OFFST_Px_EQUALFFE_ON_FIELD 6
+#define STV090x_WIDTH_Px_EQUALFFE_ON_FIELD 1
+
+#define STV090x_Px_SMAPCOEF7(__x) (0xf500 - (__x - 1) * 0x200)
+#define STV090x_P1_SMAPCOEF7 STV090x_Px_SMAPCOEF7(1)
+#define STV090x_P2_SMAPCOEF7 STV090x_Px_SMAPCOEF7(2)
+#define STV090x_OFFST_Px_DIS_QSCALE_FIELD 7
+#define STV090x_WIDTH_Px_DIS_QSCALE_FIELD 1
+#define STV090x_OFFST_Px_SMAPCOEF_Q_LLR12_FIELD 0
+#define STV090x_WIDTH_Px_SMAPCOEF_Q_LLR12_FIELD 7
+
+#define STV090x_Px_SMAPCOEF6(__x) (0xf501 - (__x - 1) * 0x200)
+#define STV090x_P1_SMAPCOEF6 STV090x_Px_SMAPCOEF6(1)
+#define STV090x_P2_SMAPCOEF6 STV090x_Px_SMAPCOEF6(2)
+#define STV090x_OFFST_Px_ADJ_8PSKLLR1_FIELD 2
+#define STV090x_WIDTH_Px_ADJ_8PSKLLR1_FIELD 1
+#define STV090x_OFFST_Px_OLD_8PSKLLR1_FIELD 1
+#define STV090x_WIDTH_Px_OLD_8PSKLLR1_FIELD 1
+#define STV090x_OFFST_Px_DIS_AB8PSK_FIELD 0
+#define STV090x_WIDTH_Px_DIS_AB8PSK_FIELD 1
+
+#define STV090x_Px_SMAPCOEF5(__x) (0xf502 - (__x - 1) * 0x200)
+#define STV090x_P1_SMAPCOEF5 STV090x_Px_SMAPCOEF5(1)
+#define STV090x_P2_SMAPCOEF5 STV090x_Px_SMAPCOEF5(2)
+#define STV090x_OFFST_Px_DIS_8SCALE_FIELD 7
+#define STV090x_WIDTH_Px_DIS_8SCALE_FIELD 1
+#define STV090x_OFFST_Px_SMAPCOEF_8P_LLR23_FIELD 0
+#define STV090x_WIDTH_Px_SMAPCOEF_8P_LLR23_FIELD 7
+
+#define STV090x_Px_DMDPLHSTAT(__x) (0xF520 - (__x - 1) * 0x200)
+#define STV090x_P1_DMDPLHSTAT STV090x_Px_DMDPLHSTAT(1)
+#define STV090x_P2_DMDPLHSTAT STV090x_Px_DMDPLHSTAT(2)
+#define STV090x_OFFST_Px_PLH_STATISTIC_FIELD 0
+#define STV090x_WIDTH_Px_PLH_STATISTIC_FIELD 8
+
+#define STV090x_Px_LOCKTIMEy(__x, __y) (0xF525 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_LOCKTIME0 STV090x_Px_LOCKTIMEy(1, 0)
+#define STV090x_P1_LOCKTIME1 STV090x_Px_LOCKTIMEy(1, 1)
+#define STV090x_P1_LOCKTIME2 STV090x_Px_LOCKTIMEy(1, 2)
+#define STV090x_P1_LOCKTIME3 STV090x_Px_LOCKTIMEy(1, 3)
+#define STV090x_P2_LOCKTIME0 STV090x_Px_LOCKTIMEy(2, 0)
+#define STV090x_P2_LOCKTIME1 STV090x_Px_LOCKTIMEy(2, 1)
+#define STV090x_P2_LOCKTIME2 STV090x_Px_LOCKTIMEy(2, 2)
+#define STV090x_P2_LOCKTIME3 STV090x_Px_LOCKTIMEy(2, 3)
+#define STV090x_OFFST_Px_DEMOD_LOCKTIME_FIELD 0
+#define STV090x_WIDTH_Px_DEMOD_LOCKTIME_FIELD 8
+
+#define STV090x_Px_TNRCFG(__x) (0xf4e0 - (__x - 1) * 0x200) /* check */
+#define STV090x_P1_TNRCFG STV090x_Px_TNRCFG(1)
+#define STV090x_P2_TNRCFG STV090x_Px_TNRCFG(2)
+
+#define STV090x_Px_TNRCFG2(__x) (0xf4e1 - (__x - 1) * 0x200)
+#define STV090x_P1_TNRCFG2 STV090x_Px_TNRCFG2(1)
+#define STV090x_P2_TNRCFG2 STV090x_Px_TNRCFG2(2)
+#define STV090x_OFFST_Px_TUN_IQSWAP_FIELD 7
+#define STV090x_WIDTH_Px_TUN_IQSWAP_FIELD 1
+
+#define STV090x_Px_VITSCALE(__x) (0xf532 - (__x - 1) * 0x200)
+#define STV090x_P1_VITSCALE STV090x_Px_VITSCALE(1)
+#define STV090x_P2_VITSCALE STV090x_Px_VITSCALE(2)
+#define STV090x_OFFST_Px_NVTH_NOSRANGE_FIELD 7
+#define STV090x_WIDTH_Px_NVTH_NOSRANGE_FIELD 1
+#define STV090x_OFFST_Px_VERROR_MAXMODE_FIELD 6
+#define STV090x_WIDTH_Px_VERROR_MAXMODE_FIELD 1
+#define STV090x_OFFST_Px_NSLOWSN_LOCKED_FIELD 3
+#define STV090x_WIDTH_Px_NSLOWSN_LOCKED_FIELD 1
+#define STV090x_OFFST_Px_DIS_RSFLOCK_FIELD 1
+#define STV090x_WIDTH_Px_DIS_RSFLOCK_FIELD 1
+
+#define STV090x_Px_FECM(__x) (0xf533 - (__x - 1) * 0x200)
+#define STV090x_P1_FECM STV090x_Px_FECM(1)
+#define STV090x_P2_FECM STV090x_Px_FECM(2)
+#define STV090x_OFFST_Px_DSS_DVB_FIELD 7
+#define STV090x_WIDTH_Px_DSS_DVB_FIELD 1
+#define STV090x_OFFST_Px_DSS_SRCH_FIELD 4
+#define STV090x_WIDTH_Px_DSS_SRCH_FIELD 1
+#define STV090x_OFFST_Px_SYNCVIT_FIELD 1
+#define STV090x_WIDTH_Px_SYNCVIT_FIELD 1
+#define STV090x_OFFST_Px_IQINV_FIELD 0
+#define STV090x_WIDTH_Px_IQINV_FIELD 1
+
+#define STV090x_Px_VTH12(__x) (0xf534 - (__x - 1) * 0x200)
+#define STV090x_P1_VTH12 STV090x_Px_VTH12(1)
+#define STV090x_P2_VTH12 STV090x_Px_VTH12(2)
+#define STV090x_OFFST_Px_VTH12_FIELD 0
+#define STV090x_WIDTH_Px_VTH12_FIELD 8
+
+#define STV090x_Px_VTH23(__x) (0xf535 - (__x - 1) * 0x200)
+#define STV090x_P1_VTH23 STV090x_Px_VTH23(1)
+#define STV090x_P2_VTH23 STV090x_Px_VTH23(2)
+#define STV090x_OFFST_Px_VTH23_FIELD 0
+#define STV090x_WIDTH_Px_VTH23_FIELD 8
+
+#define STV090x_Px_VTH34(__x) (0xf536 - (__x - 1) * 0x200)
+#define STV090x_P1_VTH34 STV090x_Px_VTH34(1)
+#define STV090x_P2_VTH34 STV090x_Px_VTH34(2)
+#define STV090x_OFFST_Px_VTH34_FIELD 0
+#define STV090x_WIDTH_Px_VTH34_FIELD 8
+
+#define STV090x_Px_VTH56(__x) (0xf537 - (__x - 1) * 0x200)
+#define STV090x_P1_VTH56 STV090x_Px_VTH56(1)
+#define STV090x_P2_VTH56 STV090x_Px_VTH56(2)
+#define STV090x_OFFST_Px_VTH56_FIELD 0
+#define STV090x_WIDTH_Px_VTH56_FIELD 8
+
+#define STV090x_Px_VTH67(__x) (0xf538 - (__x - 1) * 0x200)
+#define STV090x_P1_VTH67 STV090x_Px_VTH67(1)
+#define STV090x_P2_VTH67 STV090x_Px_VTH67(2)
+#define STV090x_OFFST_Px_VTH67_FIELD 0
+#define STV090x_WIDTH_Px_VTH67_FIELD 8
+
+#define STV090x_Px_VTH78(__x) (0xf539 - (__x - 1) * 0x200)
+#define STV090x_P1_VTH78 STV090x_Px_VTH78(1)
+#define STV090x_P2_VTH78 STV090x_Px_VTH78(2)
+#define STV090x_OFFST_Px_VTH78_FIELD 0
+#define STV090x_WIDTH_Px_VTH78_FIELD 8
+
+#define STV090x_Px_VITCURPUN(__x) (0xf53a - (__x - 1) * 0x200)
+#define STV090x_P1_VITCURPUN STV090x_Px_VITCURPUN(1)
+#define STV090x_P2_VITCURPUN STV090x_Px_VITCURPUN(2)
+#define STV090x_OFFST_Px_VIT_CURPUN_FIELD 0
+#define STV090x_WIDTH_Px_VIT_CURPUN_FIELD 5
+
+#define STV090x_Px_VERROR(__x) (0xf53b - (__x - 1) * 0x200)
+#define STV090x_P1_VERROR STV090x_Px_VERROR(1)
+#define STV090x_P2_VERROR STV090x_Px_VERROR(2)
+#define STV090x_OFFST_Px_REGERR_VIT_FIELD 0
+#define STV090x_WIDTH_Px_REGERR_VIT_FIELD 8
+
+#define STV090x_Px_PRVIT(__x) (0xf53c - (__x - 1) * 0x200)
+#define STV090x_P1_PRVIT STV090x_Px_PRVIT(1)
+#define STV090x_P2_PRVIT STV090x_Px_PRVIT(2)
+#define STV090x_OFFST_Px_DIS_VTHLOCK_FIELD 6
+#define STV090x_WIDTH_Px_DIS_VTHLOCK_FIELD 1
+#define STV090x_OFFST_Px_E7_8VIT_FIELD 5
+#define STV090x_WIDTH_Px_E7_8VIT_FIELD 1
+#define STV090x_OFFST_Px_E6_7VIT_FIELD 4
+#define STV090x_WIDTH_Px_E6_7VIT_FIELD 1
+#define STV090x_OFFST_Px_E5_6VIT_FIELD 3
+#define STV090x_WIDTH_Px_E5_6VIT_FIELD 1
+#define STV090x_OFFST_Px_E3_4VIT_FIELD 2
+#define STV090x_WIDTH_Px_E3_4VIT_FIELD 1
+#define STV090x_OFFST_Px_E2_3VIT_FIELD 1
+#define STV090x_WIDTH_Px_E2_3VIT_FIELD 1
+#define STV090x_OFFST_Px_E1_2VIT_FIELD 0
+#define STV090x_WIDTH_Px_E1_2VIT_FIELD 1
+
+#define STV090x_Px_VAVSRVIT(__x) (0xf53d - (__x - 1) * 0x200)
+#define STV090x_P1_VAVSRVIT STV090x_Px_VAVSRVIT(1)
+#define STV090x_P2_VAVSRVIT STV090x_Px_VAVSRVIT(2)
+#define STV090x_OFFST_Px_SNVIT_FIELD 4
+#define STV090x_WIDTH_Px_SNVIT_FIELD 2
+#define STV090x_OFFST_Px_TOVVIT_FIELD 2
+#define STV090x_WIDTH_Px_TOVVIT_FIELD 2
+#define STV090x_OFFST_Px_HYPVIT_FIELD 0
+#define STV090x_WIDTH_Px_HYPVIT_FIELD 2
+
+#define STV090x_Px_VSTATUSVIT(__x) (0xf53e - (__x - 1) * 0x200)
+#define STV090x_P1_VSTATUSVIT STV090x_Px_VSTATUSVIT(1)
+#define STV090x_P2_VSTATUSVIT STV090x_Px_VSTATUSVIT(2)
+#define STV090x_OFFST_Px_PRFVIT_FIELD 4
+#define STV090x_WIDTH_Px_PRFVIT_FIELD 1
+#define STV090x_OFFST_Px_LOCKEDVIT_FIELD 3
+#define STV090x_WIDTH_Px_LOCKEDVIT_FIELD 1
+
+#define STV090x_Px_VTHINUSE(__x) (0xf53f - (__x - 1) * 0x200)
+#define STV090x_P1_VTHINUSE STV090x_Px_VTHINUSE(1)
+#define STV090x_P2_VTHINUSE STV090x_Px_VTHINUSE(2)
+#define STV090x_OFFST_Px_VIT_INUSE_FIELD 0
+#define STV090x_WIDTH_Px_VIT_INUSE_FIELD 8
+
+#define STV090x_Px_KDIV12(__x) (0xf540 - (__x - 1) * 0x200)
+#define STV090x_P1_KDIV12 STV090x_Px_KDIV12(1)
+#define STV090x_P2_KDIV12 STV090x_Px_KDIV12(2)
+#define STV090x_OFFST_Px_K_DIVIDER_12_FIELD 0
+#define STV090x_WIDTH_Px_K_DIVIDER_12_FIELD 7
+
+#define STV090x_Px_KDIV23(__x) (0xf541 - (__x - 1) * 0x200)
+#define STV090x_P1_KDIV23 STV090x_Px_KDIV23(1)
+#define STV090x_P2_KDIV23 STV090x_Px_KDIV23(2)
+#define STV090x_OFFST_Px_K_DIVIDER_23_FIELD 0
+#define STV090x_WIDTH_Px_K_DIVIDER_23_FIELD 7
+
+#define STV090x_Px_KDIV34(__x) (0xf542 - (__x - 1) * 0x200)
+#define STV090x_P1_KDIV34 STV090x_Px_KDIV34(1)
+#define STV090x_P2_KDIV34 STV090x_Px_KDIV34(2)
+#define STV090x_OFFST_Px_K_DIVIDER_34_FIELD 0
+#define STV090x_WIDTH_Px_K_DIVIDER_34_FIELD 7
+
+#define STV090x_Px_KDIV56(__x) (0xf543 - (__x - 1) * 0x200)
+#define STV090x_P1_KDIV56 STV090x_Px_KDIV56(1)
+#define STV090x_P2_KDIV56 STV090x_Px_KDIV56(2)
+#define STV090x_OFFST_Px_K_DIVIDER_56_FIELD 0
+#define STV090x_WIDTH_Px_K_DIVIDER_56_FIELD 7
+
+#define STV090x_Px_KDIV67(__x) (0xf544 - (__x - 1) * 0x200)
+#define STV090x_P1_KDIV67 STV090x_Px_KDIV67(1)
+#define STV090x_P2_KDIV67 STV090x_Px_KDIV67(2)
+#define STV090x_OFFST_Px_K_DIVIDER_67_FIELD 0
+#define STV090x_WIDTH_Px_K_DIVIDER_67_FIELD 7
+
+#define STV090x_Px_KDIV78(__x) (0xf545 - (__x - 1) * 0x200)
+#define STV090x_P1_KDIV78 STV090x_Px_KDIV78(1)
+#define STV090x_P2_KDIV78 STV090x_Px_KDIV78(2)
+#define STV090x_OFFST_Px_K_DIVIDER_78_FIELD 0
+#define STV090x_WIDTH_Px_K_DIVIDER_78_FIELD 7
+
+#define STV090x_Px_PDELCTRL1(__x) (0xf550 - (__x - 1) * 0x200)
+#define STV090x_P1_PDELCTRL1 STV090x_Px_PDELCTRL1(1)
+#define STV090x_P2_PDELCTRL1 STV090x_Px_PDELCTRL1(2)
+#define STV090x_OFFST_Px_INV_MISMASK_FIELD 7
+#define STV090x_WIDTH_Px_INV_MISMASK_FIELD 1
+#define STV090x_OFFST_Px_FILTER_EN_FIELD 5
+#define STV090x_WIDTH_Px_FILTER_EN_FIELD 1
+#define STV090x_OFFST_Px_EN_MIS00_FIELD 1
+#define STV090x_WIDTH_Px_EN_MIS00_FIELD 1
+#define STV090x_OFFST_Px_ALGOSWRST_FIELD 0
+#define STV090x_WIDTH_Px_ALGOSWRST_FIELD 1
+
+#define STV090x_Px_PDELCTRL2(__x) (0xf551 - (__x - 1) * 0x200)
+#define STV090x_P1_PDELCTRL2 STV090x_Px_PDELCTRL2(1)
+#define STV090x_P2_PDELCTRL2 STV090x_Px_PDELCTRL2(2)
+#define STV090x_OFFST_Px_FORCE_CONTINUOUS 7
+#define STV090x_WIDTH_Px_FORCE_CONTINUOUS 1
+#define STV090x_OFFST_Px_RESET_UPKO_COUNT 6
+#define STV090x_WIDTH_Px_RESET_UPKO_COUNT 1
+#define STV090x_OFFST_Px_USER_PKTDELIN_NB 5
+#define STV090x_WIDTH_Px_USER_PKTDELIN_NB 1
+#define STV090x_OFFST_Px_FORCE_LOCKED 4
+#define STV090x_WIDTH_Px_FORCE_LOCKED 1
+#define STV090x_OFFST_Px_DATA_UNBBSCRAM 3
+#define STV090x_WIDTH_Px_DATA_UNBBSCRAM 1
+#define STV090x_OFFST_Px_FORCE_LONGPACKET 2
+#define STV090x_WIDTH_Px_FORCE_LONGPACKET 1
+#define STV090x_OFFST_Px_FRAME_MODE_FIELD 1
+#define STV090x_WIDTH_Px_FRAME_MODE_FIELD 1
+
+#define STV090x_Px_HYSTTHRESH(__x) (0xf554 - (__x - 1) * 0x200)
+#define STV090x_P1_HYSTTHRESH STV090x_Px_HYSTTHRESH(1)
+#define STV090x_P2_HYSTTHRESH STV090x_Px_HYSTTHRESH(2)
+#define STV090x_OFFST_Px_UNLCK_THRESH_FIELD 4
+#define STV090x_WIDTH_Px_UNLCK_THRESH_FIELD 4
+#define STV090x_OFFST_Px_DELIN_LCK_THRESH_FIELD 0
+#define STV090x_WIDTH_Px_DELIN_LCK_THRESH_FIELD 4
+
+#define STV090x_Px_ISIENTRY(__x) (0xf55e - (__x - 1) * 0x200)
+#define STV090x_P1_ISIENTRY STV090x_Px_ISIENTRY(1)
+#define STV090x_P2_ISIENTRY STV090x_Px_ISIENTRY(2)
+#define STV090x_OFFST_Px_ISI_ENTRY_FIELD 0
+#define STV090x_WIDTH_Px_ISI_ENTRY_FIELD 8
+
+#define STV090x_Px_ISIBITENA(__x) (0xf55f - (__x - 1) * 0x200)
+#define STV090x_P1_ISIBITENA STV090x_Px_ISIBITENA(1)
+#define STV090x_P2_ISIBITENA STV090x_Px_ISIBITENA(2)
+#define STV090x_OFFST_Px_ISI_BIT_EN_FIELD 0
+#define STV090x_WIDTH_Px_ISI_BIT_EN_FIELD 8
+
+#define STV090x_Px_MATSTRy(__x, __y) (0xf561 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_MATSTR0 STV090x_Px_MATSTRy(1, 0)
+#define STV090x_P1_MATSTR1 STV090x_Px_MATSTRy(1, 1)
+#define STV090x_P2_MATSTR0 STV090x_Px_MATSTRy(2, 0)
+#define STV090x_P2_MATSTR1 STV090x_Px_MATSTRy(2, 1)
+#define STV090x_OFFST_Px_MATYPE_CURRENT_FIELD 0
+#define STV090x_WIDTH_Px_MATYPE_CURRENT_FIELD 8
+
+#define STV090x_Px_UPLSTRy(__x, __y) (0xf563 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_UPLSTR0 STV090x_Px_UPLSTRy(1, 0)
+#define STV090x_P1_UPLSTR1 STV090x_Px_UPLSTRy(1, 1)
+#define STV090x_P2_UPLSTR0 STV090x_Px_UPLSTRy(2, 0)
+#define STV090x_P2_UPLSTR1 STV090x_Px_UPLSTRy(2, 1)
+#define STV090x_OFFST_Px_UPL_CURRENT_FIELD 0
+#define STV090x_WIDTH_Px_UPL_CURRENT_FIELD 8
+
+#define STV090x_Px_DFLSTRy(__x, __y) (0xf565 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_DFLSTR0 STV090x_Px_DFLSTRy(1, 0)
+#define STV090x_P1_DFLSTR1 STV090x_Px_DFLSTRy(1, 1)
+#define STV090x_P2_DFLSTR0 STV090x_Px_DFLSTRy(2, 0)
+#define STV090x_P2_DFLSTR1 STV090x_Px_DFLSTRy(2, 1)
+#define STV090x_OFFST_Px_DFL_CURRENT_FIELD 0
+#define STV090x_WIDTH_Px_DFL_CURRENT_FIELD 8
+
+#define STV090x_Px_SYNCSTR(__x) (0xf566 - (__x - 1) * 0x200)
+#define STV090x_P1_SYNCSTR STV090x_Px_SYNCSTR(1)
+#define STV090x_P2_SYNCSTR STV090x_Px_SYNCSTR(2)
+#define STV090x_OFFST_Px_SYNC_CURRENT_FIELD 0
+#define STV090x_WIDTH_Px_SYNC_CURRENT_FIELD 8
+
+#define STV090x_Px_SYNCDSTRy(__x, __y) (0xf568 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_SYNCDSTR0 STV090x_Px_SYNCDSTRy(1, 0)
+#define STV090x_P1_SYNCDSTR1 STV090x_Px_SYNCDSTRy(1, 1)
+#define STV090x_P2_SYNCDSTR0 STV090x_Px_SYNCDSTRy(2, 0)
+#define STV090x_P2_SYNCDSTR1 STV090x_Px_SYNCDSTRy(2, 1)
+#define STV090x_OFFST_Px_SYNCD_CURRENT_FIELD 0
+#define STV090x_WIDTH_Px_SYNCD_CURRENT_FIELD 8
+
+#define STV090x_Px_PDELSTATUS1(__x) (0xf569 - (__x - 1) * 0x200)
+#define STV090x_P1_PDELSTATUS1 STV090x_Px_PDELSTATUS1(1)
+#define STV090x_P2_PDELSTATUS1 STV090x_Px_PDELSTATUS1(2)
+#define STV090x_OFFST_Px_PKTDELIN_LOCK_FIELD 1
+#define STV090x_WIDTH_Px_PKTDELIN_LOCK_FIELD 1
+#define STV090x_OFFST_Px_FIRST_LOCK_FIELD 0
+#define STV090x_WIDTH_Px_FIRST_LOCK_FIELD 1
+
+#define STV090x_Px_PDELSTATUS2(__x) (0xf56a - (__x - 1) * 0x200)
+#define STV090x_P1_PDELSTATUS2 STV090x_Px_PDELSTATUS2(1)
+#define STV090x_P2_PDELSTATUS2 STV090x_Px_PDELSTATUS2(2)
+#define STV090x_OFFST_Px_FRAME_MODCOD_FIELD 2
+#define STV090x_WIDTH_Px_FRAME_MODCOD_FIELD 5
+#define STV090x_OFFST_Px_FRAME_TYPE_FIELD 0
+#define STV090x_WIDTH_Px_FRAME_TYPE_FIELD 2
+
+#define STV090x_Px_BBFCRCKO1(__x) (0xf56b - (__x - 1) * 0x200)
+#define STV090x_P1_BBFCRCKO1 STV090x_Px_BBFCRCKO1(1)
+#define STV090x_P2_BBFCRCKO1 STV090x_Px_BBFCRCKO1(2)
+#define STV090x_OFFST_Px_BBHCRC_KOCNT_FIELD 0
+#define STV090x_WIDTH_Px_BBHCRC_KOCNT_FIELD 8
+
+#define STV090x_Px_BBFCRCKO0(__x) (0xf56c - (__x - 1) * 0x200)
+#define STV090x_P1_BBFCRCKO0 STV090x_Px_BBFCRCKO0(1)
+#define STV090x_P2_BBFCRCKO0 STV090x_Px_BBFCRCKO0(2)
+#define STV090x_OFFST_Px_BBHCRC_KOCNT_FIELD 0
+#define STV090x_WIDTH_Px_BBHCRC_KOCNT_FIELD 8
+
+#define STV090x_Px_UPCRCKO1(__x) (0xf56d - (__x - 1) * 0x200)
+#define STV090x_P1_UPCRCKO1 STV090x_Px_UPCRCKO1(1)
+#define STV090x_P2_UPCRCKO1 STV090x_Px_UPCRCKO1(2)
+#define STV090x_OFFST_Px_PKTCRC_KOCNT_FIELD 0
+#define STV090x_WIDTH_Px_PKTCRC_KOCNT_FIELD 8
+
+#define STV090x_Px_UPCRCKO0(__x) (0xf56e - (__x - 1) * 0x200)
+#define STV090x_P1_UPCRCKO0 STV090x_Px_UPCRCKO0(1)
+#define STV090x_P2_UPCRCKO0 STV090x_Px_UPCRCKO0(2)
+#define STV090x_OFFST_Px_PKTCRC_KOCNT_FIELD 0
+#define STV090x_WIDTH_Px_PKTCRC_KOCNT_FIELD 8
+
+#define STV090x_NBITER_NFx(__x) (0xFA03 + (__x - 4) * 0x1)
+#define STV090x_NBITER_NF4 STV090x_NBITER_NFx(4)
+#define STV090x_NBITER_NF5 STV090x_NBITER_NFx(5)
+#define STV090x_NBITER_NF6 STV090x_NBITER_NFx(6)
+#define STV090x_NBITER_NF7 STV090x_NBITER_NFx(7)
+#define STV090x_NBITER_NF8 STV090x_NBITER_NFx(8)
+#define STV090x_NBITER_NF9 STV090x_NBITER_NFx(9)
+#define STV090x_NBITER_NF10 STV090x_NBITER_NFx(10)
+#define STV090x_NBITER_NF11 STV090x_NBITER_NFx(11)
+#define STV090x_NBITER_NF12 STV090x_NBITER_NFx(12)
+#define STV090x_NBITER_NF13 STV090x_NBITER_NFx(13)
+#define STV090x_NBITER_NF14 STV090x_NBITER_NFx(14)
+#define STV090x_NBITER_NF15 STV090x_NBITER_NFx(15)
+#define STV090x_NBITER_NF16 STV090x_NBITER_NFx(16)
+#define STV090x_NBITER_NF17 STV090x_NBITER_NFx(17)
+
+#define STV090x_NBITERNOERR 0xFA3F
+#define STV090x_OFFST_NBITER_STOP_CRIT_FIELD 0
+#define STV090x_WIDTH_NBITER_STOP_CRIT_FIELD 4
+
+#define STV090x_GAINLLR_NFx(__x) (0xFA43 + (__x - 4) * 0x1)
+#define STV090x_GAINLLR_NF4 STV090x_GAINLLR_NFx(4)
+#define STV090x_OFFST_GAINLLR_NF_QP_1_2_FIELD 0
+#define STV090x_WIDTH_GAINLLR_NF_QP_1_2_FIELD 7
+
+#define STV090x_GAINLLR_NF5 STV090x_GAINLLR_NFx(5)
+#define STV090x_OFFST_GAINLLR_NF_QP_3_5_FIELD 0
+#define STV090x_WIDTH_GAINLLR_NF_QP_3_5_FIELD 7
+
+#define STV090x_GAINLLR_NF6 STV090x_GAINLLR_NFx(6)
+#define STV090x_OFFST_GAINLLR_NF_QP_2_3_FIELD 0
+#define STV090x_WIDTH_GAINLLR_NF_QP_2_3_FIELD 7
+
+#define STV090x_GAINLLR_NF7 STV090x_GAINLLR_NFx(7)
+#define STV090x_OFFST_GAINLLR_NF_QP_3_4_FIELD 0
+#define STV090x_WIDTH_GAINLLR_NF_QP_3_4_FIELD 7
+
+#define STV090x_GAINLLR_NF8 STV090x_GAINLLR_NFx(8)
+#define STV090x_OFFST_GAINLLR_NF_QP_4_5_FIELD 0
+#define STV090x_WIDTH_GAINLLR_NF_QP_4_5_FIELD 7
+
+#define STV090x_GAINLLR_NF9 STV090x_GAINLLR_NFx(9)
+#define STV090x_OFFST_GAINLLR_NF_QP_5_6_FIELD 0
+#define STV090x_WIDTH_GAINLLR_NF_QP_5_6_FIELD 7
+
+#define STV090x_GAINLLR_NF10 STV090x_GAINLLR_NFx(10)
+#define STV090x_OFFST_GAINLLR_NF_QP_8_9_FIELD 0
+#define STV090x_WIDTH_GAINLLR_NF_QP_8_9_FIELD 7
+
+#define STV090x_GAINLLR_NF11 STV090x_GAINLLR_NFx(11)
+#define STV090x_OFFST_GAINLLR_NF_QP_9_10_FIELD 0
+#define STV090x_WIDTH_GAINLLR_NF_QP_9_10_FIELD 7
+
+#define STV090x_GAINLLR_NF12 STV090x_GAINLLR_NFx(12)
+#define STV090x_OFFST_GAINLLR_NF_8P_3_5_FIELD 0
+#define STV090x_WIDTH_GAINLLR_NF_8P_3_5_FIELD 7
+
+#define STV090x_GAINLLR_NF13 STV090x_GAINLLR_NFx(13)
+#define STV090x_OFFST_GAINLLR_NF_8P_2_3_FIELD 0
+#define STV090x_WIDTH_GAINLLR_NF_8P_2_3_FIELD 7
+
+#define STV090x_GAINLLR_NF14 STV090x_GAINLLR_NFx(14)
+#define STV090x_OFFST_GAINLLR_NF_8P_3_4_FIELD 0
+#define STV090x_WIDTH_GAINLLR_NF_8P_3_4_FIELD 7
+
+#define STV090x_GAINLLR_NF15 STV090x_GAINLLR_NFx(15)
+#define STV090x_OFFST_GAINLLR_NF_8P_5_6_FIELD 0
+#define STV090x_WIDTH_GAINLLR_NF_8P_5_6_FIELD 7
+
+#define STV090x_GAINLLR_NF16 STV090x_GAINLLR_NFx(16)
+#define STV090x_OFFST_GAINLLR_NF_8P_8_9_FIELD 0
+#define STV090x_WIDTH_GAINLLR_NF_8P_8_9_FIELD 7
+
+#define STV090x_GAINLLR_NF17 STV090x_GAINLLR_NFx(17)
+#define STV090x_OFFST_GAINLLR_NF_8P_9_10_FIELD 0
+#define STV090x_WIDTH_GAINLLR_NF_8P_9_10_FIELD 7
+
+#define STV090x_GENCFG 0xFA86
+#define STV090x_OFFST_BROADCAST_FIELD 4
+#define STV090x_WIDTH_BROADCAST_FIELD 1
+#define STV090x_OFFST_PRIORITY_FIELD 1
+#define STV090x_WIDTH_PRIORITY_FIELD 1
+#define STV090x_OFFST_DDEMOD_FIELD 0
+#define STV090x_WIDTH_DDEMOD_FIELD 1
+
+#define STV090x_LDPCERRx(__x) (0xFA97 - (__x * 0x1))
+#define STV090x_LDPCERR0 STV090x_LDPCERRx(0)
+#define STV090x_LDPCERR1 STV090x_LDPCERRx(1)
+#define STV090x_OFFST_Px_LDPC_ERRORS_COUNTER_FIELD 0
+#define STV090x_WIDTH_Px_LDPC_ERRORS_COUNTER_FIELD 8
+
+#define STV090x_BCHERR 0xFA98
+#define STV090x_OFFST_Px_ERRORFLAG_FIELD 4
+#define STV090x_WIDTH_Px_ERRORFLAG_FIELD 1
+#define STV090x_OFFST_Px_BCH_ERRORS_COUNTER_FIELD 0
+#define STV090x_WIDTH_Px_BCH_ERRORS_COUNTER_FIELD 4
+
+#define STV090x_Px_TSSTATEM(__x) (0xF570 - (__x - 1) * 0x200)
+#define STV090x_P1_TSSTATEM STV090x_Px_TSSTATEM(1)
+#define STV090x_P2_TSSTATEM STV090x_Px_TSSTATEM(2)
+#define STV090x_OFFST_Px_TSDIL_ON_FIELD 7
+#define STV090x_WIDTH_Px_TSDIL_ON_FIELD 1
+#define STV090x_OFFST_Px_TSRS_ON_FIELD 5
+#define STV090x_WIDTH_Px_TSRS_ON_FIELD 1
+
+#define STV090x_Px_TSCFGH(__x) (0xF572 - (__x - 1) * 0x200)
+#define STV090x_P1_TSCFGH STV090x_Px_TSCFGH(1)
+#define STV090x_P2_TSCFGH STV090x_Px_TSCFGH(2)
+#define STV090x_OFFST_Px_TSFIFO_DVBCI_FIELD 7
+#define STV090x_WIDTH_Px_TSFIFO_DVBCI_FIELD 1
+#define STV090x_OFFST_Px_TSFIFO_SERIAL_FIELD 6
+#define STV090x_WIDTH_Px_TSFIFO_SERIAL_FIELD 1
+#define STV090x_OFFST_Px_TSFIFO_TEIUPDATE_FIELD 5
+#define STV090x_WIDTH_Px_TSFIFO_TEIUPDATE_FIELD 1
+#define STV090x_OFFST_Px_TSFIFO_DUTY50_FIELD 4
+#define STV090x_WIDTH_Px_TSFIFO_DUTY50_FIELD 1
+#define STV090x_OFFST_Px_TSFIFO_HSGNLOUT_FIELD 3
+#define STV090x_WIDTH_Px_TSFIFO_HSGNLOUT_FIELD 1
+#define STV090x_OFFST_Px_TSFIFO_ERRORMODE_FIELD 1
+#define STV090x_WIDTH_Px_TSFIFO_ERRORMODE_FIELD 2
+#define STV090x_OFFST_Px_RST_HWARE_FIELD 0
+#define STV090x_WIDTH_Px_RST_HWARE_FIELD 1
+
+#define STV090x_Px_TSCFGM(__x) (0xF573 - (__x - 1) * 0x200)
+#define STV090x_P1_TSCFGM STV090x_Px_TSCFGM(1)
+#define STV090x_P2_TSCFGM STV090x_Px_TSCFGM(2)
+#define STV090x_OFFST_Px_TSFIFO_MANSPEED_FIELD 6
+#define STV090x_WIDTH_Px_TSFIFO_MANSPEED_FIELD 2
+#define STV090x_OFFST_Px_TSFIFO_PERMDATA_FIELD 5
+#define STV090x_WIDTH_Px_TSFIFO_PERMDATA_FIELD 1
+#define STV090x_OFFST_Px_TSFIFO_INVDATA_FIELD 0
+#define STV090x_WIDTH_Px_TSFIFO_INVDATA_FIELD 1
+
+#define STV090x_Px_TSCFGL(__x) (0xF574 - (__x - 1) * 0x200)
+#define STV090x_P1_TSCFGL STV090x_Px_TSCFGL(1)
+#define STV090x_P2_TSCFGL STV090x_Px_TSCFGL(2)
+#define STV090x_OFFST_Px_TSFIFO_BCLKDEL1CK_FIELD 6
+#define STV090x_WIDTH_Px_TSFIFO_BCLKDEL1CK_FIELD 2
+#define STV090x_OFFST_Px_BCHERROR_MODE_FIELD 4
+#define STV090x_WIDTH_Px_BCHERROR_MODE_FIELD 2
+#define STV090x_OFFST_Px_TSFIFO_NSGNL2DATA_FIELD 3
+#define STV090x_WIDTH_Px_TSFIFO_NSGNL2DATA_FIELD 1
+#define STV090x_OFFST_Px_TSFIFO_EMBINDVB_FIELD 2
+#define STV090x_WIDTH_Px_TSFIFO_EMBINDVB_FIELD 1
+#define STV090x_OFFST_Px_TSFIFO_DPUNACT_FIELD 1
+#define STV090x_WIDTH_Px_TSFIFO_DPUNACT_FIELD 1
+
+#define STV090x_Px_TSINSDELH(__x) (0xF576 - (__x - 1) * 0x200)
+#define STV090x_P1_TSINSDELH STV090x_Px_TSINSDELH(1)
+#define STV090x_P2_TSINSDELH STV090x_Px_TSINSDELH(2)
+#define STV090x_OFFST_Px_TSDEL_SYNCBYTE_FIELD 7
+#define STV090x_WIDTH_Px_TSDEL_SYNCBYTE_FIELD 1
+#define STV090x_OFFST_Px_TSDEL_XXHEADER_FIELD 6
+#define STV090x_WIDTH_Px_TSDEL_XXHEADER_FIELD 1
+
+#define STV090x_Px_TSSPEED(__x) (0xF580 - (__x - 1) * 0x200)
+#define STV090x_P1_TSSPEED STV090x_Px_TSSPEED(1)
+#define STV090x_P2_TSSPEED STV090x_Px_TSSPEED(2)
+#define STV090x_OFFST_Px_TSFIFO_OUTSPEED_FIELD 0
+#define STV090x_WIDTH_Px_TSFIFO_OUTSPEED_FIELD 8
+
+#define STV090x_Px_TSSTATUS(__x) (0xF581 - (__x - 1) * 0x200)
+#define STV090x_P1_TSSTATUS STV090x_Px_TSSTATUS(1)
+#define STV090x_P2_TSSTATUS STV090x_Px_TSSTATUS(2)
+#define STV090x_OFFST_Px_TSFIFO_LINEOK_FIELD 7
+#define STV090x_WIDTH_Px_TSFIFO_LINEOK_FIELD 1
+#define STV090x_OFFST_Px_TSFIFO_ERROR_FIELD 6
+#define STV090x_WIDTH_Px_TSFIFO_ERROR_FIELD 1
+
+#define STV090x_Px_TSSTATUS2(__x) (0xF582 - (__x - 1) * 0x200)
+#define STV090x_P1_TSSTATUS2 STV090x_Px_TSSTATUS2(1)
+#define STV090x_P2_TSSTATUS2 STV090x_Px_TSSTATUS2(2)
+#define STV090x_OFFST_Px_TSFIFO_DEMODSEL_FIELD 7
+#define STV090x_WIDTH_Px_TSFIFO_DEMODSEL_FIELD 1
+#define STV090x_OFFST_Px_TSFIFOSPEED_STORE_FIELD 6
+#define STV090x_WIDTH_Px_TSFIFOSPEED_STORE_FIELD 1
+#define STV090x_OFFST_Px_DILXX_RESET_FIELD 5
+#define STV090x_WIDTH_Px_DILXX_RESET_FIELD 1
+#define STV090x_OFFST_Px_TSSERIAL_IMPOS_FIELD 5
+#define STV090x_WIDTH_Px_TSSERIAL_IMPOS_FIELD 1
+#define STV090x_OFFST_Px_SCRAMBDETECT_FIELD 1
+#define STV090x_WIDTH_Px_SCRAMBDETECT_FIELD 1
+
+#define STV090x_Px_TSBITRATEy(__x, __y) (0xF584 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_TSBITRATE0 STV090x_Px_TSBITRATEy(1, 0)
+#define STV090x_P1_TSBITRATE1 STV090x_Px_TSBITRATEy(1, 1)
+#define STV090x_P2_TSBITRATE0 STV090x_Px_TSBITRATEy(2, 0)
+#define STV090x_P2_TSBITRATE1 STV090x_Px_TSBITRATEy(2, 1)
+#define STV090x_OFFST_Px_TSFIFO_BITRATE_FIELD 7
+#define STV090x_WIDTH_Px_TSFIFO_BITRATE_FIELD 8
+
+#define STV090x_Px_ERRCTRL1(__x) (0xF598 - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCTRL1 STV090x_Px_ERRCTRL1(1)
+#define STV090x_P2_ERRCTRL1 STV090x_Px_ERRCTRL1(2)
+#define STV090x_OFFST_Px_ERR_SOURCE_FIELD 4
+#define STV090x_WIDTH_Px_ERR_SOURCE_FIELD 4
+#define STV090x_OFFST_Px_NUM_EVENT_FIELD 0
+#define STV090x_WIDTH_Px_NUM_EVENT_FIELD 3
+
+#define STV090x_Px_ERRCNT12(__x) (0xF599 - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCNT12 STV090x_Px_ERRCNT12(1)
+#define STV090x_P2_ERRCNT12 STV090x_Px_ERRCNT12(2)
+#define STV090x_OFFST_Px_ERRCNT1_OLDVALUE_FIELD 7
+#define STV090x_WIDTH_Px_ERRCNT1_OLDVALUE_FIELD 1
+#define STV090x_OFFST_Px_ERR_CNT12_FIELD 0
+#define STV090x_WIDTH_Px_ERR_CNT12_FIELD 7
+
+#define STV090x_Px_ERRCNT11(__x) (0xF59A - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCNT11 STV090x_Px_ERRCNT11(1)
+#define STV090x_P2_ERRCNT11 STV090x_Px_ERRCNT11(2)
+#define STV090x_OFFST_Px_ERR_CNT11_FIELD 0
+#define STV090x_WIDTH_Px_ERR_CNT11_FIELD 8
+
+#define STV090x_Px_ERRCNT10(__x) (0xF59B - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCNT10 STV090x_Px_ERRCNT10(1)
+#define STV090x_P2_ERRCNT10 STV090x_Px_ERRCNT10(2)
+#define STV090x_OFFST_Px_ERR_CNT10_FIELD 0
+#define STV090x_WIDTH_Px_ERR_CNT10_FIELD 8
+
+#define STV090x_Px_ERRCTRL2(__x) (0xF59C - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCTRL2 STV090x_Px_ERRCTRL2(1)
+#define STV090x_P2_ERRCTRL2 STV090x_Px_ERRCTRL2(2)
+#define STV090x_OFFST_Px_ERR_SOURCE2_FIELD 4
+#define STV090x_WIDTH_Px_ERR_SOURCE2_FIELD 4
+#define STV090x_OFFST_Px_NUM_EVENT2_FIELD 0
+#define STV090x_WIDTH_Px_NUM_EVENT2_FIELD 3
+
+#define STV090x_Px_ERRCNT22(__x) (0xF59D - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCNT22 STV090x_Px_ERRCNT22(1)
+#define STV090x_P2_ERRCNT22 STV090x_Px_ERRCNT22(2)
+#define STV090x_OFFST_Px_ERRCNT2_OLDVALUE_FIELD 7
+#define STV090x_WIDTH_Px_ERRCNT2_OLDVALUE_FIELD 1
+#define STV090x_OFFST_Px_ERR_CNT2_FIELD 0
+#define STV090x_WIDTH_Px_ERR_CNT2_FIELD 7
+
+#define STV090x_Px_ERRCNT21(__x) (0xF59E - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCNT21 STV090x_Px_ERRCNT21(1)
+#define STV090x_P2_ERRCNT21 STV090x_Px_ERRCNT21(2)
+#define STV090x_OFFST_Px_ERR_CNT21_FIELD 0
+#define STV090x_WIDTH_Px_ERR_CNT21_FIELD 8
+
+#define STV090x_Px_ERRCNT20(__x) (0xF59F - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCNT20 STV090x_Px_ERRCNT20(1)
+#define STV090x_P2_ERRCNT20 STV090x_Px_ERRCNT20(2)
+#define STV090x_OFFST_Px_ERR_CNT20_FIELD 0
+#define STV090x_WIDTH_Px_ERR_CNT20_FIELD 8
+
+#define STV090x_Px_FECSPY(__x) (0xF5A0 - (__x - 1) * 0x200)
+#define STV090x_P1_FECSPY STV090x_Px_FECSPY(1)
+#define STV090x_P2_FECSPY STV090x_Px_FECSPY(2)
+#define STV090x_OFFST_Px_SPY_ENABLE_FIELD 7
+#define STV090x_WIDTH_Px_SPY_ENABLE_FIELD 1
+#define STV090x_OFFST_Px_BERMETER_DATAMAODE_FIELD 2
+#define STV090x_WIDTH_Px_BERMETER_DATAMAODE_FIELD 2
+
+#define STV090x_Px_FSPYCFG(__x) (0xF5A1 - (__x - 1) * 0x200)
+#define STV090x_P1_FSPYCFG STV090x_Px_FSPYCFG(1)
+#define STV090x_P2_FSPYCFG STV090x_Px_FSPYCFG(2)
+#define STV090x_OFFST_Px_RST_ON_ERROR_FIELD 5
+#define STV090x_WIDTH_Px_RST_ON_ERROR_FIELD 1
+#define STV090x_OFFST_Px_ONE_SHOT_FIELD 4
+#define STV090x_WIDTH_Px_ONE_SHOT_FIELD 1
+#define STV090x_OFFST_Px_I2C_MODE_FIELD 2
+#define STV090x_WIDTH_Px_I2C_MODE_FIELD 2
+
+#define STV090x_Px_FSPYDATA(__x) (0xF5A2 - (__x - 1) * 0x200)
+#define STV090x_P1_FSPYDATA STV090x_Px_FSPYDATA(1)
+#define STV090x_P2_FSPYDATA STV090x_Px_FSPYDATA(2)
+#define STV090x_OFFST_Px_SPY_STUFFING_FIELD 7
+#define STV090x_WIDTH_Px_SPY_STUFFING_FIELD 1
+#define STV090x_OFFST_Px_SPY_CNULLPKT_FIELD 5
+#define STV090x_WIDTH_Px_SPY_CNULLPKT_FIELD 1
+#define STV090x_OFFST_Px_SPY_OUTDATA_MODE_FIELD 0
+#define STV090x_WIDTH_Px_SPY_OUTDATA_MODE_FIELD 5
+
+#define STV090x_Px_FSPYOUT(__x) (0xF5A3 - (__x - 1) * 0x200)
+#define STV090x_P1_FSPYOUT STV090x_Px_FSPYOUT(1)
+#define STV090x_P2_FSPYOUT STV090x_Px_FSPYOUT(2)
+#define STV090x_OFFST_Px_FSPY_DIRECT_FIELD 7
+#define STV090x_WIDTH_Px_FSPY_DIRECT_FIELD 1
+#define STV090x_OFFST_Px_STUFF_MODE_FIELD 0
+#define STV090x_WIDTH_Px_STUFF_MODE_FIELD 3
+
+#define STV090x_Px_FSTATUS(__x) (0xF5A4 - (__x - 1) * 0x200)
+#define STV090x_P1_FSTATUS STV090x_Px_FSTATUS(1)
+#define STV090x_P2_FSTATUS STV090x_Px_FSTATUS(2)
+#define STV090x_OFFST_Px_SPY_ENDSIM_FIELD 7
+#define STV090x_WIDTH_Px_SPY_ENDSIM_FIELD 1
+#define STV090x_OFFST_Px_VALID_SIM_FIELD 6
+#define STV090x_WIDTH_Px_VALID_SIM_FIELD 1
+#define STV090x_OFFST_Px_FOUND_SIGNAL_FIELD 5
+#define STV090x_WIDTH_Px_FOUND_SIGNAL_FIELD 1
+#define STV090x_OFFST_Px_DSS_SYNCBYTE_FIELD 4
+#define STV090x_WIDTH_Px_DSS_SYNCBYTE_FIELD 1
+#define STV090x_OFFST_Px_RESULT_STATE_FIELD 0
+#define STV090x_WIDTH_Px_RESULT_STATE_FIELD 4
+
+#define STV090x_Px_FBERCPT4(__x) (0xF5A8 - (__x - 1) * 0x200)
+#define STV090x_P1_FBERCPT4 STV090x_Px_FBERCPT4(1)
+#define STV090x_P2_FBERCPT4 STV090x_Px_FBERCPT4(2)
+#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD 0
+#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD 8
+
+#define STV090x_Px_FBERCPT3(__x) (0xF5A9 - (__x - 1) * 0x200)
+#define STV090x_P1_FBERCPT3 STV090x_Px_FBERCPT3(1)
+#define STV090x_P2_FBERCPT3 STV090x_Px_FBERCPT3(2)
+#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD 0
+#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD 8
+
+#define STV090x_Px_FBERCPT2(__x) (0xF5AA - (__x - 1) * 0x200)
+#define STV090x_P1_FBERCPT2 STV090x_Px_FBERCPT2(1)
+#define STV090x_P2_FBERCPT2 STV090x_Px_FBERCPT2(2)
+#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD 0
+#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD 8
+
+#define STV090x_Px_FBERCPT1(__x) (0xF5AB - (__x - 1) * 0x200)
+#define STV090x_P1_FBERCPT1 STV090x_Px_FBERCPT1(1)
+#define STV090x_P2_FBERCPT1 STV090x_Px_FBERCPT1(2)
+#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD 0
+#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD 8
+
+#define STV090x_Px_FBERCPT0(__x) (0xF5AC - (__x - 1) * 0x200)
+#define STV090x_P1_FBERCPT0 STV090x_Px_FBERCPT0(1)
+#define STV090x_P2_FBERCPT0 STV090x_Px_FBERCPT0(2)
+#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD 0
+#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD 8
+
+#define STV090x_Px_FBERERRy(__x, __y) (0xF5AF - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_FBERERR0 STV090x_Px_FBERERRy(1, 0)
+#define STV090x_P1_FBERERR1 STV090x_Px_FBERERRy(1, 1)
+#define STV090x_P1_FBERERR2 STV090x_Px_FBERERRy(1, 2)
+#define STV090x_P2_FBERERR0 STV090x_Px_FBERERRy(2, 0)
+#define STV090x_P2_FBERERR1 STV090x_Px_FBERERRy(2, 1)
+#define STV090x_P2_FBERERR2 STV090x_Px_FBERERRy(2, 2)
+#define STV090x_OFFST_Px_FBERMETER_CPT_ERR_FIELD 0
+#define STV090x_WIDTH_Px_FBERMETER_CPT_ERR_FIELD 8
+
+#define STV090x_Px_FSPYBER(__x) (0xF5B2 - (__x - 1) * 0x200)
+#define STV090x_P1_FSPYBER STV090x_Px_FSPYBER(1)
+#define STV090x_P2_FSPYBER STV090x_Px_FSPYBER(2)
+#define STV090x_OFFST_Px_FSPYBER_SYNCBYTE_FIELD 4
+#define STV090x_WIDTH_Px_FSPYBER_SYNCBYTE_FIELD 1
+#define STV090x_OFFST_Px_FSPYBER_UNSYNC_FIELD 3
+#define STV090x_WIDTH_Px_FSPYBER_UNSYNC_FIELD 1
+#define STV090x_OFFST_Px_FSPYBER_CTIME_FIELD 0
+#define STV090x_WIDTH_Px_FSPYBER_CTIME_FIELD 3
+
+#define STV090x_RCCFGH 0xf600
+
+#define STV090x_TSGENERAL 0xF630
+#define STV090x_OFFST_Px_MUXSTREAM_OUT_FIELD 3
+#define STV090x_WIDTH_Px_MUXSTREAM_OUT_FIELD 1
+#define STV090x_OFFST_Px_TSFIFO_PERMPARAL_FIELD 1
+#define STV090x_WIDTH_Px_TSFIFO_PERMPARAL_FIELD 2
+
+#define STV090x_TSGENERAL1X 0xf670
+#define STV090x_CFGEXT 0xfa80
+
+#define STV090x_TSTRES0 0xFF11
+#define STV090x_OFFST_FRESFEC_FIELD 7
+#define STV090x_WIDTH_FRESFEC_FIELD 1
+
+#define STV090x_Px_TSTDISRX(__x) (0xFF67 - (__x - 1) * 0x2)
+#define STV090x_P1_TSTDISRX STV090x_Px_TSTDISRX(1)
+#define STV090x_P2_TSTDISRX STV090x_Px_TSTDISRX(2)
+#define STV090x_OFFST_Px_TSTDISRX_SELECT_FIELD 3
+#define STV090x_WIDTH_Px_TSTDISRX_SELECT_FIELD 1
+
+#endif /* __STV090x_REG_H */
diff --git a/drivers/media/dvb/frontends/stv6110x.c b/drivers/media/dvb/frontends/stv6110x.c
new file mode 100644
index 000000000000..3d8a2e01c9c4
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv6110x.c
@@ -0,0 +1,373 @@
+/*
+ STV6110(A) Silicon tuner driver
+
+ Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+ Copyright (C) ST Microelectronics
+
+ 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.
+*/
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include "dvb_frontend.h"
+
+#include "stv6110x_reg.h"
+#include "stv6110x.h"
+#include "stv6110x_priv.h"
+
+static unsigned int verbose;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "Set Verbosity level");
+
+static u8 stv6110x_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e};
+
+static int stv6110x_read_reg(struct stv6110x_state *stv6110x, u8 reg, u8 *data)
+{
+ int ret;
+ const struct stv6110x_config *config = stv6110x->config;
+ u8 b0[] = { reg };
+ u8 b1[] = { 0 };
+ struct i2c_msg msg[] = {
+ { .addr = config->addr, .flags = 0, .buf = b0, .len = 1 },
+ { .addr = config->addr, .flags = I2C_M_RD, .buf = b1, .len = 1 }
+ };
+
+ ret = i2c_transfer(stv6110x->i2c, msg, 2);
+ if (ret != 2) {
+ dprintk(FE_ERROR, 1, "I/O Error");
+ return -EREMOTEIO;
+ }
+ *data = b1[0];
+
+ return 0;
+}
+
+static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data)
+{
+ int ret;
+ const struct stv6110x_config *config = stv6110x->config;
+ u8 buf[] = { reg, data };
+ struct i2c_msg msg = { .addr = config->addr, .flags = 0, . buf = buf, .len = 2 };
+
+ ret = i2c_transfer(stv6110x->i2c, &msg, 1);
+ if (ret != 1) {
+ dprintk(FE_ERROR, 1, "I/O Error");
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+static int stv6110x_init(struct dvb_frontend *fe)
+{
+ struct stv6110x_state *stv6110x = fe->tuner_priv;
+ int ret;
+ u8 i;
+
+ for (i = 0; i < ARRAY_SIZE(stv6110x_regs); i++) {
+ ret = stv6110x_write_reg(stv6110x, i, stv6110x_regs[i]);
+ if (ret < 0) {
+ dprintk(FE_ERROR, 1, "Initialization failed");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int stv6110x_set_frequency(struct dvb_frontend *fe, u32 frequency)
+{
+ struct stv6110x_state *stv6110x = fe->tuner_priv;
+ u32 rDiv, divider;
+ s32 pVal, pCalc, rDivOpt = 0;
+ u8 i;
+
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_K, (REFCLOCK_MHz - 16));
+
+ if (frequency <= 1023000) {
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
+ pVal = 40;
+ } else if (frequency <= 1300000) {
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
+ pVal = 40;
+ } else if (frequency <= 2046000) {
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
+ pVal = 20;
+ } else {
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
+ pVal = 20;
+ }
+
+ for (rDiv = 0; rDiv <= 3; rDiv++) {
+ pCalc = (REFCLOCK_kHz / 100) / R_DIV(rDiv);
+
+ if ((abs((s32)(pCalc - pVal))) < (abs((s32)(1000 - pVal))))
+ rDivOpt = rDiv;
+ }
+
+ divider = (frequency * R_DIV(rDivOpt) * pVal) / REFCLOCK_kHz;
+ divider = (divider + 5) / 10;
+
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_R_DIV, rDivOpt);
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_N_DIV_11_8, MSB(divider));
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG0], TNG0_N_DIV_7_0, LSB(divider));
+
+ /* VCO Auto calibration */
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_STAT1], STAT1_CALVCO_STRT, 1);
+
+ stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x_regs[STV6110x_CTRL1]);
+ stv6110x_write_reg(stv6110x, STV6110x_TNG1, stv6110x_regs[STV6110x_TNG1]);
+ stv6110x_write_reg(stv6110x, STV6110x_TNG0, stv6110x_regs[STV6110x_TNG0]);
+ stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x_regs[STV6110x_STAT1]);
+
+ for (i = 0; i < TRIALS; i++) {
+ stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]);
+ if (!STV6110x_GETFIELD(STAT1_CALVCO_STRT, stv6110x_regs[STV6110x_STAT1]))
+ break;
+ msleep(1);
+ }
+
+ return 0;
+}
+
+static int stv6110x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ struct stv6110x_state *stv6110x = fe->tuner_priv;
+
+ stv6110x_read_reg(stv6110x, STV6110x_TNG1, &stv6110x_regs[STV6110x_TNG1]);
+ stv6110x_read_reg(stv6110x, STV6110x_TNG0, &stv6110x_regs[STV6110x_TNG0]);
+
+ *frequency = (MAKEWORD16(STV6110x_GETFIELD(TNG1_N_DIV_11_8, stv6110x_regs[STV6110x_TNG1]),
+ STV6110x_GETFIELD(TNG0_N_DIV_7_0, stv6110x_regs[STV6110x_TNG0]))) * REFCLOCK_kHz;
+
+ *frequency /= (1 << (STV6110x_GETFIELD(TNG1_R_DIV, stv6110x_regs[STV6110x_TNG1]) +
+ STV6110x_GETFIELD(TNG1_DIV4SEL, stv6110x_regs[STV6110x_TNG1])));
+
+ *frequency >>= 2;
+
+ return 0;
+}
+
+static int stv6110x_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
+{
+ struct stv6110x_state *stv6110x = fe->tuner_priv;
+ u32 halfbw;
+ u8 i;
+
+ halfbw = bandwidth >> 1;
+
+ if (halfbw > 36000000)
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, 31); /* LPF */
+ else if (halfbw < 5000000)
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, 0); /* LPF */
+ else
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, ((halfbw / 1000000) - 5)); /* LPF */
+
+
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x0); /* cal. clk activated */
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_STAT1], STAT1_CALRC_STRT, 0x1); /* LPF auto cal */
+
+ stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x_regs[STV6110x_CTRL3]);
+ stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x_regs[STV6110x_STAT1]);
+
+ for (i = 0; i < TRIALS; i++) {
+ stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]);
+ if (!STV6110x_GETFIELD(STAT1_CALRC_STRT, stv6110x_regs[STV6110x_STAT1]))
+ break;
+ msleep(1);
+ }
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x1); /* cal. done */
+ stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x_regs[STV6110x_CTRL3]);
+
+ return 0;
+}
+
+static int stv6110x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+ struct stv6110x_state *stv6110x = fe->tuner_priv;
+
+ stv6110x_read_reg(stv6110x, STV6110x_CTRL3, &stv6110x_regs[STV6110x_CTRL3]);
+ *bandwidth = (STV6110x_GETFIELD(CTRL3_CF, stv6110x_regs[STV6110x_CTRL3]) + 5) * 2000000;
+
+ return 0;
+}
+
+static int stv6110x_set_refclock(struct dvb_frontend *fe, u32 refclock)
+{
+ struct stv6110x_state *stv6110x = fe->tuner_priv;
+
+ /* setup divider */
+ switch (refclock) {
+ default:
+ case 1:
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0);
+ break;
+ case 2:
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1);
+ break;
+ case 4:
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2);
+ break;
+ case 8:
+ case 0:
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3);
+ break;
+ }
+ stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x_regs[STV6110x_CTRL2]);
+
+ return 0;
+}
+
+static int stv6110x_get_bbgain(struct dvb_frontend *fe, u32 *gain)
+{
+ struct stv6110x_state *stv6110x = fe->tuner_priv;
+
+ stv6110x_read_reg(stv6110x, STV6110x_CTRL2, &stv6110x_regs[STV6110x_CTRL2]);
+ *gain = 2 * STV6110x_GETFIELD(CTRL2_BBGAIN, stv6110x_regs[STV6110x_CTRL2]);
+
+ return 0;
+}
+
+static int stv6110x_set_bbgain(struct dvb_frontend *fe, u32 gain)
+{
+ struct stv6110x_state *stv6110x = fe->tuner_priv;
+
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_BBGAIN, gain / 2);
+ stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x_regs[STV6110x_CTRL2]);
+
+ return 0;
+}
+
+static int stv6110x_set_mode(struct dvb_frontend *fe, enum tuner_mode mode)
+{
+ struct stv6110x_state *stv6110x = fe->tuner_priv;
+ int ret;
+
+ switch (mode) {
+ case TUNER_SLEEP:
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_SYN, 0);
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_RX, 0);
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_LPT, 0);
+ break;
+
+ case TUNER_WAKE:
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_SYN, 1);
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_RX, 1);
+ STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_LPT, 1);
+ break;
+ }
+
+ ret = stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x_regs[STV6110x_CTRL1]);
+ if (ret < 0) {
+ dprintk(FE_ERROR, 1, "I/O Error");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int stv6110x_sleep(struct dvb_frontend *fe)
+{
+ return stv6110x_set_mode(fe, TUNER_SLEEP);
+}
+
+static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status)
+{
+ struct stv6110x_state *stv6110x = fe->tuner_priv;
+
+ stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]);
+
+ if (STV6110x_GETFIELD(STAT1_LOCK, stv6110x_regs[STV6110x_STAT1]))
+ *status = TUNER_PHASELOCKED;
+ else
+ *status = 0;
+
+ return 0;
+}
+
+
+static int stv6110x_release(struct dvb_frontend *fe)
+{
+ struct stv6110x_state *stv6110x = fe->tuner_priv;
+
+ fe->tuner_priv = NULL;
+ kfree(stv6110x);
+
+ return 0;
+}
+
+static struct dvb_tuner_ops stv6110x_ops = {
+ .info = {
+ .name = "STV6110(A) Silicon Tuner",
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+ .frequency_step = 0,
+ },
+
+ .init = stv6110x_init,
+ .sleep = stv6110x_sleep,
+ .release = stv6110x_release
+};
+
+static struct stv6110x_devctl stv6110x_ctl = {
+ .tuner_init = stv6110x_init,
+ .tuner_set_mode = stv6110x_set_mode,
+ .tuner_set_frequency = stv6110x_set_frequency,
+ .tuner_get_frequency = stv6110x_get_frequency,
+ .tuner_set_bandwidth = stv6110x_set_bandwidth,
+ .tuner_get_bandwidth = stv6110x_get_bandwidth,
+ .tuner_set_bbgain = stv6110x_set_bbgain,
+ .tuner_get_bbgain = stv6110x_get_bbgain,
+ .tuner_set_refclk = stv6110x_set_refclock,
+ .tuner_get_status = stv6110x_get_status,
+};
+
+struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
+ const struct stv6110x_config *config,
+ struct i2c_adapter *i2c)
+{
+ struct stv6110x_state *stv6110x;
+
+ stv6110x = kzalloc(sizeof (struct stv6110x_state), GFP_KERNEL);
+ if (stv6110x == NULL)
+ goto error;
+
+ stv6110x->i2c = i2c;
+ stv6110x->config = config;
+ stv6110x->devctl = &stv6110x_ctl;
+
+ fe->tuner_priv = stv6110x;
+ fe->ops.tuner_ops = stv6110x_ops;
+
+ printk("%s: Attaching STV6110x \n", __func__);
+ return stv6110x->devctl;
+
+error:
+ kfree(stv6110x);
+ return NULL;
+}
+EXPORT_SYMBOL(stv6110x_attach);
+
+MODULE_AUTHOR("Manu Abraham");
+MODULE_DESCRIPTION("STV6110x Silicon tuner");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/stv6110x.h b/drivers/media/dvb/frontends/stv6110x.h
new file mode 100644
index 000000000000..a38257080e01
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv6110x.h
@@ -0,0 +1,71 @@
+/*
+ STV6110(A) Silicon tuner driver
+
+ Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+ Copyright (C) ST Microelectronics
+
+ 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.
+*/
+
+#ifndef __STV6110x_H
+#define __STV6110x_H
+
+struct stv6110x_config {
+ u8 addr;
+ u32 refclk;
+};
+
+enum tuner_mode {
+ TUNER_SLEEP = 1,
+ TUNER_WAKE,
+};
+
+enum tuner_status {
+ TUNER_PHASELOCKED = 1,
+};
+
+struct stv6110x_devctl {
+ int (*tuner_init) (struct dvb_frontend *fe);
+ int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode);
+ int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency);
+ int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency);
+ int (*tuner_set_bandwidth) (struct dvb_frontend *fe, u32 bandwidth);
+ int (*tuner_get_bandwidth) (struct dvb_frontend *fe, u32 *bandwidth);
+ int (*tuner_set_bbgain) (struct dvb_frontend *fe, u32 gain);
+ int (*tuner_get_bbgain) (struct dvb_frontend *fe, u32 *gain);
+ int (*tuner_set_refclk) (struct dvb_frontend *fe, u32 refclk);
+ int (*tuner_get_status) (struct dvb_frontend *fe, u32 *status);
+};
+
+
+#if defined(CONFIG_DVB_STV6110x) || (defined(CONFIG_DVB_STV6110x_MODULE) && defined(MODULE))
+
+extern struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
+ const struct stv6110x_config *config,
+ struct i2c_adapter *i2c);
+
+#else
+static inline struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
+ const struct stv6110x_config *config,
+ struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+
+#endif /* CONFIG_DVB_STV6110x */
+
+#endif /* __STV6110x_H */
diff --git a/drivers/media/dvb/frontends/stv6110x_priv.h b/drivers/media/dvb/frontends/stv6110x_priv.h
new file mode 100644
index 000000000000..7260da633d49
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv6110x_priv.h
@@ -0,0 +1,75 @@
+/*
+ STV6110(A) Silicon tuner driver
+
+ Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+ Copyright (C) ST Microelectronics
+
+ 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.
+*/
+
+#ifndef __STV6110x_PRIV_H
+#define __STV6110x_PRIV_H
+
+#define FE_ERROR 0
+#define FE_NOTICE 1
+#define FE_INFO 2
+#define FE_DEBUG 3
+#define FE_DEBUGREG 4
+
+#define dprintk(__y, __z, format, arg...) do { \
+ if (__z) { \
+ if ((verbose > FE_ERROR) && (verbose > __y)) \
+ printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \
+ else if ((verbose > FE_NOTICE) && (verbose > __y)) \
+ printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \
+ else if ((verbose > FE_INFO) && (verbose > __y)) \
+ printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \
+ else if ((verbose > FE_DEBUG) && (verbose > __y)) \
+ printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \
+ } else { \
+ if (verbose > __y) \
+ printk(format, ##arg); \
+ } \
+} while (0)
+
+
+#define STV6110x_SETFIELD(mask, bitf, val) \
+ (mask = (mask & (~(((1 << STV6110x_WIDTH_##bitf) - 1) << \
+ STV6110x_OFFST_##bitf))) | \
+ (val << STV6110x_OFFST_##bitf))
+
+#define STV6110x_GETFIELD(bitf, val) \
+ ((val >> STV6110x_OFFST_##bitf) & \
+ ((1 << STV6110x_WIDTH_##bitf) - 1))
+
+#define MAKEWORD16(a, b) (((a) << 8) | (b))
+
+#define LSB(x) ((x & 0xff))
+#define MSB(y) ((y >> 8) & 0xff)
+
+#define TRIALS 10
+#define R_DIV(__div) (1 << (__div + 1))
+#define REFCLOCK_kHz (stv6110x->config->refclk / 1000)
+#define REFCLOCK_MHz (stv6110x->config->refclk / 1000000)
+
+struct stv6110x_state {
+ struct i2c_adapter *i2c;
+ const struct stv6110x_config *config;
+
+ struct stv6110x_devctl *devctl;
+};
+
+#endif /* __STV6110x_PRIV_H */
diff --git a/drivers/media/dvb/frontends/stv6110x_reg.h b/drivers/media/dvb/frontends/stv6110x_reg.h
new file mode 100644
index 000000000000..93e5c70e5fd8
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv6110x_reg.h
@@ -0,0 +1,82 @@
+/*
+ STV6110(A) Silicon tuner driver
+
+ Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+ Copyright (C) ST Microelectronics
+
+ 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.
+*/
+
+#ifndef __STV6110x_REG_H
+#define __STV6110x_REG_H
+
+#define STV6110x_CTRL1 0x00
+#define STV6110x_OFFST_CTRL1_K 3
+#define STV6110x_WIDTH_CTRL1_K 5
+#define STV6110x_OFFST_CTRL1_LPT 2
+#define STV6110x_WIDTH_CTRL1_LPT 1
+#define STV6110x_OFFST_CTRL1_RX 1
+#define STV6110x_WIDTH_CTRL1_RX 1
+#define STV6110x_OFFST_CTRL1_SYN 0
+#define STV6110x_WIDTH_CTRL1_SYN 1
+
+#define STV6110x_CTRL2 0x01
+#define STV6110x_OFFST_CTRL2_CO_DIV 6
+#define STV6110x_WIDTH_CTRL2_CO_DIV 2
+#define STV6110x_OFFST_CTRL2_RSVD 5
+#define STV6110x_WIDTH_CTRL2_RSVD 1
+#define STV6110x_OFFST_CTRL2_REFOUT_SEL 4
+#define STV6110x_WIDTH_CTRL2_REFOUT_SEL 1
+#define STV6110x_OFFST_CTRL2_BBGAIN 0
+#define STV6110x_WIDTH_CTRL2_BBGAIN 4
+
+#define STV6110x_TNG0 0x02
+#define STV6110x_OFFST_TNG0_N_DIV_7_0 0
+#define STV6110x_WIDTH_TNG0_N_DIV_7_0 8
+
+#define STV6110x_TNG1 0x03
+#define STV6110x_OFFST_TNG1_R_DIV 6
+#define STV6110x_WIDTH_TNG1_R_DIV 2
+#define STV6110x_OFFST_TNG1_PRESC32_ON 5
+#define STV6110x_WIDTH_TNG1_PRESC32_ON 1
+#define STV6110x_OFFST_TNG1_DIV4SEL 4
+#define STV6110x_WIDTH_TNG1_DIV4SEL 1
+#define STV6110x_OFFST_TNG1_N_DIV_11_8 0
+#define STV6110x_WIDTH_TNG1_N_DIV_11_8 4
+
+
+#define STV6110x_CTRL3 0x04
+#define STV6110x_OFFST_CTRL3_DCLOOP_OFF 7
+#define STV6110x_WIDTH_CTRL3_DCLOOP_OFF 1
+#define STV6110x_OFFST_CTRL3_RCCLK_OFF 6
+#define STV6110x_WIDTH_CTRL3_RCCLK_OFF 1
+#define STV6110x_OFFST_CTRL3_ICP 5
+#define STV6110x_WIDTH_CTRL3_ICP 1
+#define STV6110x_OFFST_CTRL3_CF 0
+#define STV6110x_WIDTH_CTRL3_CF 5
+
+#define STV6110x_STAT1 0x05
+#define STV6110x_OFFST_STAT1_CALVCO_STRT 2
+#define STV6110x_WIDTH_STAT1_CALVCO_STRT 1
+#define STV6110x_OFFST_STAT1_CALRC_STRT 1
+#define STV6110x_WIDTH_STAT1_CALRC_STRT 1
+#define STV6110x_OFFST_STAT1_LOCK 0
+#define STV6110x_WIDTH_STAT1_LOCK 1
+
+#define STV6110x_STAT2 0x06
+#define STV6110x_STAT3 0x07
+
+#endif /* __STV6110x_REG_H */
diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c
index 2a8bbcd44cd0..28f580f858c6 100644
--- a/drivers/media/dvb/frontends/tda10048.c
+++ b/drivers/media/dvb/frontends/tda10048.c
@@ -25,6 +25,7 @@
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/delay.h>
+#include <asm/div64.h>
#include "dvb_frontend.h"
#include "dvb_math.h"
#include "tda10048.h"
@@ -143,6 +144,15 @@ struct tda10048_state {
struct dvb_frontend frontend;
int fwloaded;
+
+ u32 freq_if_hz;
+ u32 xtal_hz;
+ u32 pll_mfactor;
+ u32 pll_nfactor;
+ u32 pll_pfactor;
+ u32 sample_freq;
+
+ enum fe_bandwidth bandwidth;
};
static struct init_tab {
@@ -271,6 +281,199 @@ error:
return ret;
}
+static int tda10048_set_phy2(struct dvb_frontend *fe, u32 sample_freq_hz,
+ u32 if_hz)
+{
+ struct tda10048_state *state = fe->demodulator_priv;
+ u64 t;
+
+ dprintk(1, "%s()\n", __func__);
+
+ if (sample_freq_hz == 0)
+ return -EINVAL;
+
+ if (if_hz < (sample_freq_hz / 2)) {
+ /* PHY2 = (if2/fs) * 2^15 */
+ t = if_hz;
+ t *= 10;
+ t *= 32768;
+ do_div(t, sample_freq_hz);
+ t += 5;
+ do_div(t, 10);
+ } else {
+ /* PHY2 = ((IF1-fs)/fs) * 2^15 */
+ t = sample_freq_hz - if_hz;
+ t *= 10;
+ t *= 32768;
+ do_div(t, sample_freq_hz);
+ t += 5;
+ do_div(t, 10);
+ t = ~t + 1;
+ }
+
+ tda10048_writereg(state, TDA10048_FREQ_PHY2_LSB, (u8)t);
+ tda10048_writereg(state, TDA10048_FREQ_PHY2_MSB, (u8)(t >> 8));
+
+ return 0;
+}
+
+static int tda10048_set_wref(struct dvb_frontend *fe, u32 sample_freq_hz,
+ u32 bw)
+{
+ struct tda10048_state *state = fe->demodulator_priv;
+ u64 t, z;
+ u32 b = 8000000;
+
+ dprintk(1, "%s()\n", __func__);
+
+ if (sample_freq_hz == 0)
+ return -EINVAL;
+
+ if (bw == BANDWIDTH_6_MHZ)
+ b = 6000000;
+ else
+ if (bw == BANDWIDTH_7_MHZ)
+ b = 7000000;
+
+ /* WREF = (B / (7 * fs)) * 2^31 */
+ t = b * 10;
+ /* avoid warning: this decimal constant is unsigned only in ISO C90 */
+ /* t *= 2147483648 on 32bit platforms */
+ t *= (2048 * 1024);
+ t *= 1024;
+ z = 7 * sample_freq_hz;
+ do_div(t, z);
+ t += 5;
+ do_div(t, 10);
+
+ tda10048_writereg(state, TDA10048_TIME_WREF_LSB, (u8)t);
+ tda10048_writereg(state, TDA10048_TIME_WREF_MID1, (u8)(t >> 8));
+ tda10048_writereg(state, TDA10048_TIME_WREF_MID2, (u8)(t >> 16));
+ tda10048_writereg(state, TDA10048_TIME_WREF_MSB, (u8)(t >> 24));
+
+ return 0;
+}
+
+static int tda10048_set_invwref(struct dvb_frontend *fe, u32 sample_freq_hz,
+ u32 bw)
+{
+ struct tda10048_state *state = fe->demodulator_priv;
+ u64 t;
+ u32 b = 8000000;
+
+ dprintk(1, "%s()\n", __func__);
+
+ if (sample_freq_hz == 0)
+ return -EINVAL;
+
+ if (bw == BANDWIDTH_6_MHZ)
+ b = 6000000;
+ else
+ if (bw == BANDWIDTH_7_MHZ)
+ b = 7000000;
+
+ /* INVWREF = ((7 * fs) / B) * 2^5 */
+ t = sample_freq_hz;
+ t *= 7;
+ t *= 32;
+ t *= 10;
+ do_div(t, b);
+ t += 5;
+ do_div(t, 10);
+
+ tda10048_writereg(state, TDA10048_TIME_INVWREF_LSB, (u8)t);
+ tda10048_writereg(state, TDA10048_TIME_INVWREF_MSB, (u8)(t >> 8));
+
+ return 0;
+}
+
+static int tda10048_set_bandwidth(struct dvb_frontend *fe,
+ enum fe_bandwidth bw)
+{
+ struct tda10048_state *state = fe->demodulator_priv;
+ dprintk(1, "%s(bw=%d)\n", __func__, bw);
+
+ /* Bandwidth setting may need to be adjusted */
+ switch (bw) {
+ case BANDWIDTH_6_MHZ:
+ case BANDWIDTH_7_MHZ:
+ case BANDWIDTH_8_MHZ:
+ tda10048_set_wref(fe, state->sample_freq, bw);
+ tda10048_set_invwref(fe, state->sample_freq, bw);
+ break;
+ default:
+ printk(KERN_ERR "%s() invalid bandwidth\n", __func__);
+ return -EINVAL;
+ }
+
+ state->bandwidth = bw;
+
+ return 0;
+}
+
+static int tda10048_set_pll(struct dvb_frontend *fe)
+{
+ struct tda10048_state *state = fe->demodulator_priv;
+ int ret = 0;
+
+ dprintk(1, "%s()\n", __func__);
+
+ if ((state->config->clk_freq_khz == TDA10048_CLK_4000) &&
+ (state->config->if_freq_khz == TDA10048_IF_36130)) {
+ state->freq_if_hz = TDA10048_IF_36130 * 1000;
+ state->xtal_hz = TDA10048_CLK_4000 * 1000;
+ state->pll_mfactor = 10;
+ state->pll_nfactor = 0;
+ state->pll_pfactor = 0;
+ } else
+ if ((state->config->clk_freq_khz == TDA10048_CLK_16000) &&
+ (state->config->if_freq_khz == TDA10048_IF_4300)) {
+ state->freq_if_hz = TDA10048_IF_4300 * 1000;
+ state->xtal_hz = TDA10048_CLK_16000 * 1000;
+ state->pll_mfactor = 10;
+ state->pll_nfactor = 3;
+ state->pll_pfactor = 0;
+ } else
+ if ((state->config->clk_freq_khz == TDA10048_CLK_16000) &&
+ (state->config->if_freq_khz == TDA10048_IF_4000)) {
+ state->freq_if_hz = TDA10048_IF_4000 * 1000;
+ state->xtal_hz = TDA10048_CLK_16000 * 1000;
+ state->pll_mfactor = 10;
+ state->pll_nfactor = 3;
+ state->pll_pfactor = 0;
+ } else
+ if ((state->config->clk_freq_khz == TDA10048_CLK_16000) &&
+ (state->config->if_freq_khz == TDA10048_IF_36130)) {
+ state->freq_if_hz = TDA10048_IF_36130 * 1000;
+ state->xtal_hz = TDA10048_CLK_16000 * 1000;
+ state->pll_mfactor = 10;
+ state->pll_nfactor = 3;
+ state->pll_pfactor = 0;
+ } else {
+ printk(KERN_ERR "%s() Incorrect attach settings\n", __func__);
+ ret = -EINVAL;
+ }
+
+ dprintk(1, "- freq_if_hz = %d\n", state->freq_if_hz);
+ dprintk(1, "- xtal_hz = %d\n", state->xtal_hz);
+ dprintk(1, "- pll_mfactor = %d\n", state->pll_mfactor);
+ dprintk(1, "- pll_nfactor = %d\n", state->pll_nfactor);
+ dprintk(1, "- pll_pfactor = %d\n", state->pll_pfactor);
+
+ /* Calculate the sample frequency */
+ state->sample_freq = state->xtal_hz * (state->pll_mfactor + 45);
+ state->sample_freq /= (state->pll_nfactor + 1);
+ state->sample_freq /= (state->pll_pfactor + 4);
+ dprintk(1, "- sample_freq = %d\n", state->sample_freq);
+
+ tda10048_set_phy2(fe, state->sample_freq,
+ state->config->if_freq_khz * 1000);
+ tda10048_set_wref(fe, state->sample_freq, state->bandwidth);
+ tda10048_set_invwref(fe, state->sample_freq, state->bandwidth);
+
+ return ret;
+}
+
static int tda10048_firmware_upload(struct dvb_frontend *fe)
{
struct tda10048_state *state = fe->demodulator_priv;
@@ -523,6 +726,9 @@ static int tda10048_set_frontend(struct dvb_frontend *fe,
dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency);
+ if (p->u.ofdm.bandwidth != state->bandwidth)
+ tda10048_set_bandwidth(fe, p->u.ofdm.bandwidth);
+
if (fe->ops.tuner_ops.set_params) {
if (fe->ops.i2c_gate_ctrl)
@@ -558,9 +764,15 @@ static int tda10048_init(struct dvb_frontend *fe)
/* Set either serial or parallel */
tda10048_output_mode(fe, state->config->output_mode);
- /* set inversion */
+ /* Set inversion */
tda10048_set_inversion(fe, state->config->inversion);
+ /* Establish default PLL values */
+ tda10048_set_pll(fe);
+
+ /* Establish default bandwidth */
+ tda10048_set_bandwidth(fe, BANDWIDTH_8_MHZ);
+
/* Ensure we leave the gate closed */
tda10048_i2c_gate_ctrl(fe, 0);
@@ -830,6 +1042,7 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
state->config = config;
state->i2c = i2c;
state->fwloaded = 0;
+ state->bandwidth = BANDWIDTH_8_MHZ;
/* check if the demod is present */
if (tda10048_readreg(state, TDA10048_IDENTITY) != 0x048)
@@ -840,6 +1053,10 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
+ /* Set the xtal and freq defaults */
+ if (tda10048_set_pll(&state->frontend) != 0)
+ goto error;
+
/* Leave the gate closed */
tda10048_i2c_gate_ctrl(&state->frontend, 0);
diff --git a/drivers/media/dvb/frontends/tda10048.h b/drivers/media/dvb/frontends/tda10048.h
index 0457b24601fa..ab9cf5bd421e 100644
--- a/drivers/media/dvb/frontends/tda10048.h
+++ b/drivers/media/dvb/frontends/tda10048.h
@@ -43,6 +43,20 @@ struct tda10048_config {
#define TDA10048_INVERSION_OFF 0
#define TDA10048_INVERSION_ON 1
u8 inversion;
+
+#define TDA10048_IF_3300 3300
+#define TDA10048_IF_3500 3500
+#define TDA10048_IF_3800 3800
+#define TDA10048_IF_4000 4000
+#define TDA10048_IF_4300 4300
+#define TDA10048_IF_4500 4500
+#define TDA10048_IF_4750 4750
+#define TDA10048_IF_36130 36130
+ u16 if_freq_khz;
+
+#define TDA10048_CLK_4000 4000
+#define TDA10048_CLK_16000 16000
+ u16 clk_freq_khz;
};
#if defined(CONFIG_DVB_TDA10048) || \
diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c
index 7bd4d1dee2b3..f3e1cc733fe7 100644
--- a/drivers/media/dvb/siano/smscoreapi.c
+++ b/drivers/media/dvb/siano/smscoreapi.c
@@ -58,42 +58,6 @@ struct smscore_client_t {
onremove_t onremove_handler;
};
-struct smscore_device_t {
- struct list_head entry;
-
- struct list_head clients;
- struct list_head subclients;
- spinlock_t clientslock;
-
- struct list_head buffers;
- spinlock_t bufferslock;
- int num_buffers;
-
- void *common_buffer;
- int common_buffer_size;
- dma_addr_t common_buffer_phys;
-
- void *context;
- struct device *device;
-
- char devpath[32];
- unsigned long device_flags;
-
- setmode_t setmode_handler;
- detectmode_t detectmode_handler;
- sendrequest_t sendrequest_handler;
- preload_t preload_handler;
- postload_t postload_handler;
-
- int mode, modes_supported;
-
- struct completion version_ex_done, data_download_done, trigger_done;
- struct completion init_device_done, reload_start_done, resume_done;
-
- int board_id;
- int led_state;
-};
-
void smscore_set_board_id(struct smscore_device_t *core, int id)
{
core->board_id = id;
diff --git a/drivers/media/dvb/siano/smscoreapi.h b/drivers/media/dvb/siano/smscoreapi.h
index 548de9056e8b..d7284482eced 100644
--- a/drivers/media/dvb/siano/smscoreapi.h
+++ b/drivers/media/dvb/siano/smscoreapi.h
@@ -46,13 +46,14 @@
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
-#define SMS_ALLOC_ALIGNMENT 128
-#define SMS_DMA_ALIGNMENT 16
+#define SMS_PROTOCOL_MAX_RAOUNDTRIP_MS (10000)
+#define SMS_ALLOC_ALIGNMENT 128
+#define SMS_DMA_ALIGNMENT 16
#define SMS_ALIGN_ADDRESS(addr) \
((((uintptr_t)(addr)) + (SMS_DMA_ALIGNMENT-1)) & ~(SMS_DMA_ALIGNMENT-1))
-#define SMS_DEVICE_FAMILY2 1
-#define SMS_ROM_NO_RESPONSE 2
+#define SMS_DEVICE_FAMILY2 1
+#define SMS_ROM_NO_RESPONSE 2
#define SMS_DEVICE_NOT_READY 0x8000000
enum sms_device_type_st {
@@ -83,13 +84,13 @@ typedef void (*onremove_t)(void *context);
struct smscore_buffer_t {
/* public members, once passed to clients can be changed freely */
struct list_head entry;
- int size;
- int offset;
+ int size;
+ int offset;
/* private members, read-only for clients */
- void *p;
- dma_addr_t phys;
- unsigned long offset_in_common;
+ void *p;
+ dma_addr_t phys;
+ unsigned long offset_in_common;
};
struct smsdevice_params_t {
@@ -116,10 +117,63 @@ struct smsclient_params_t {
int data_type;
onresponse_t onresponse_handler;
onremove_t onremove_handler;
-
void *context;
};
+struct smscore_device_t {
+ struct list_head entry;
+
+ struct list_head clients;
+ struct list_head subclients;
+ spinlock_t clientslock;
+
+ struct list_head buffers;
+ spinlock_t bufferslock;
+ int num_buffers;
+
+ void *common_buffer;
+ int common_buffer_size;
+ dma_addr_t common_buffer_phys;
+
+ void *context;
+ struct device *device;
+
+ char devpath[32];
+ unsigned long device_flags;
+
+ setmode_t setmode_handler;
+ detectmode_t detectmode_handler;
+ sendrequest_t sendrequest_handler;
+ preload_t preload_handler;
+ postload_t postload_handler;
+
+ int mode, modes_supported;
+
+ /* host <--> device messages */
+ struct completion version_ex_done, data_download_done, trigger_done;
+ struct completion init_device_done, reload_start_done, resume_done;
+ struct completion gpio_configuration_done, gpio_set_level_done;
+ struct completion gpio_get_level_done, ir_init_done;
+
+ /* Buffer management */
+ wait_queue_head_t buffer_mng_waitq;
+
+ /* GPIO */
+ int gpio_get_res;
+
+ /* Target hardware board */
+ int board_id;
+
+ /* Firmware */
+ u8 *fw_buf;
+ u32 fw_buf_size;
+
+ /* Infrared (IR) */
+ /* struct ir_t ir; */
+
+ int led_state;
+};
+
/* GPIO definitions for antenna frequency domain control (SMS8021) */
#define SMS_ANTENNA_GPIO_0 1
#define SMS_ANTENNA_GPIO_1 0
@@ -161,6 +215,7 @@ struct smsclient_params_t {
#define MSG_SMS_GET_PID_FILTER_LIST_RES 609
#define MSG_SMS_GET_STATISTICS_REQ 615
#define MSG_SMS_GET_STATISTICS_RES 616
+#define MSG_SMS_HO_PER_SLICES_IND 630
#define MSG_SMS_SET_ANTENNA_CONFIG_REQ 651
#define MSG_SMS_SET_ANTENNA_CONFIG_RES 652
#define MSG_SMS_GET_STATISTICS_EX_REQ 653
@@ -190,14 +245,31 @@ struct smsclient_params_t {
#define MSG_SMS_GPIO_CONFIG_EX_RES 713
#define MSG_SMS_ISDBT_TUNE_REQ 776
#define MSG_SMS_ISDBT_TUNE_RES 777
+#define MSG_SMS_TRANSMISSION_IND 782
+#define MSG_SMS_START_IR_REQ 800
+#define MSG_SMS_START_IR_RES 801
+#define MSG_SMS_IR_SAMPLES_IND 802
+#define MSG_SMS_SIGNAL_DETECTED_IND 827
+#define MSG_SMS_NO_SIGNAL_IND 828
#define SMS_INIT_MSG_EX(ptr, type, src, dst, len) do { \
(ptr)->msgType = type; (ptr)->msgSrcId = src; (ptr)->msgDstId = dst; \
(ptr)->msgLength = len; (ptr)->msgFlags = 0; \
} while (0)
+
#define SMS_INIT_MSG(ptr, type, len) \
SMS_INIT_MSG_EX(ptr, type, 0, HIF_TASK, len)
+enum SMS_DVB3_EVENTS {
+ DVB3_EVENT_INIT = 0,
+ DVB3_EVENT_SLEEP,
+ DVB3_EVENT_HOTPLUG,
+ DVB3_EVENT_FE_LOCK,
+ DVB3_EVENT_FE_UNLOCK,
+ DVB3_EVENT_UNC_OK,
+ DVB3_EVENT_UNC_ERR
+};
+
enum SMS_DEVICE_MODE {
DEVICE_MODE_NONE = -1,
DEVICE_MODE_DVBT = 0,
@@ -221,8 +293,13 @@ struct SmsMsgHdr_ST {
};
struct SmsMsgData_ST {
- struct SmsMsgHdr_ST xMsgHeader;
- u32 msgData[1];
+ struct SmsMsgHdr_ST xMsgHeader;
+ u32 msgData[1];
+};
+
+struct SmsMsgData_ST2 {
+ struct SmsMsgHdr_ST xMsgHeader;
+ u32 msgData[2];
};
struct SmsDataDownload_ST {
@@ -238,11 +315,12 @@ struct SmsVersionRes_ST {
u8 Step; /* 0 - Step A */
u8 MetalFix; /* 0 - Metal 0 */
- u8 FirmwareId; /* 0xFF � ROM, otherwise the
- * value indicated by
- * SMSHOSTLIB_DEVICE_MODES_E */
- u8 SupportedProtocols; /* Bitwise OR combination of
+ /* FirmwareId 0xFF if ROM, otherwise the
+ * value indicated by SMSHOSTLIB_DEVICE_MODES_E */
+ u8 FirmwareId;
+ /* SupportedProtocols Bitwise OR combination of
* supported protocols */
+ u8 SupportedProtocols;
u8 VersionMajor;
u8 VersionMinor;
@@ -276,10 +354,12 @@ struct SMSHOSTLIB_STATISTICS_ST {
s32 SNR; /* dB */
u32 BER; /* Post Viterbi BER [1E-5] */
u32 FIB_CRC; /* CRC errors percentage, valid only for DAB */
- u32 TS_PER; /* Transport stream PER, 0xFFFFFFFF indicate N/A,
+ /* Transport stream PER, 0xFFFFFFFF indicate N/A,
* valid only for DVB-T/H */
- u32 MFER; /* DVB-H frame error rate in percentage,
+ u32 TS_PER;
+ /* DVB-H frame error rate in percentage,
* 0xFFFFFFFF indicate N/A, valid only for DVB-H */
+ u32 MFER;
s32 RSSI; /* dBm */
s32 InBandPwr; /* In band power in dBM */
s32 CarrierOffset; /* Carrier Offset in bin/1024 */
@@ -287,8 +367,9 @@ struct SMSHOSTLIB_STATISTICS_ST {
/* Transmission parameters, valid only for DVB-T/H */
u32 Frequency; /* Frequency in Hz */
u32 Bandwidth; /* Bandwidth in MHz */
- u32 TransmissionMode; /* Transmission Mode, for DAB modes 1-4,
+ /* Transmission Mode, for DAB modes 1-4,
* for DVB-T/H FFT mode carriers in Kilos */
+ u32 TransmissionMode;
u32 ModemState; /* from SMS_DvbModemState_ET */
u32 GuardInterval; /* Guard Interval, 1 divided by value */
u32 CodeRate; /* Code Rate from SMS_DvbModemState_ET */
diff --git a/drivers/media/dvb/siano/smsendian.c b/drivers/media/dvb/siano/smsendian.c
new file mode 100644
index 000000000000..d79aa051269a
--- /dev/null
+++ b/drivers/media/dvb/siano/smsendian.c
@@ -0,0 +1,100 @@
+/****************************************************************
+
+ Siano Mobile Silicon, Inc.
+ MDTV receiver kernel modules.
+ Copyright (C) 2006-2009, Uri Shkolnik
+
+ 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 <http://www.gnu.org/licenses/>.
+
+ ****************************************************************/
+
+#include <asm/byteorder.h>
+
+#include "smsendian.h"
+#include "smscoreapi.h"
+
+void smsendian_handle_tx_message(void *buffer)
+{
+#ifdef __BIG_ENDIAN
+ struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer;
+ int i;
+ int msgWords;
+
+ switch (msg->xMsgHeader.msgType) {
+ case MSG_SMS_DATA_DOWNLOAD_REQ:
+ {
+ msg->msgData[0] = le32_to_cpu(msg->msgData[0]);
+ break;
+ }
+
+ default:
+ msgWords = (msg->xMsgHeader.msgLength -
+ sizeof(struct SmsMsgHdr_ST))/4;
+
+ for (i = 0; i < msgWords; i++)
+ msg->msgData[i] = le32_to_cpu(msg->msgData[i]);
+
+ break;
+ }
+#endif /* __BIG_ENDIAN */
+}
+
+void smsendian_handle_rx_message(void *buffer)
+{
+#ifdef __BIG_ENDIAN
+ struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer;
+ int i;
+ int msgWords;
+
+ switch (msg->xMsgHeader.msgType) {
+ case MSG_SMS_GET_VERSION_EX_RES:
+ {
+ struct SmsVersionRes_ST *ver =
+ (struct SmsVersionRes_ST *) msg;
+ ver->ChipModel = le16_to_cpu(ver->ChipModel);
+ break;
+ }
+
+ case MSG_SMS_DVBT_BDA_DATA:
+ case MSG_SMS_DAB_CHANNEL:
+ case MSG_SMS_DATA_MSG:
+ {
+ break;
+ }
+
+ default:
+ {
+ msgWords = (msg->xMsgHeader.msgLength -
+ sizeof(struct SmsMsgHdr_ST))/4;
+
+ for (i = 0; i < msgWords; i++)
+ msg->msgData[i] = le32_to_cpu(msg->msgData[i]);
+
+ break;
+ }
+ }
+#endif /* __BIG_ENDIAN */
+}
+
+void smsendian_handle_message_header(void *msg)
+{
+#ifdef __BIG_ENDIAN
+ struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)msg;
+
+ phdr->msgType = le16_to_cpu(phdr->msgType);
+ phdr->msgLength = le16_to_cpu(phdr->msgLength);
+ phdr->msgFlags = le16_to_cpu(phdr->msgFlags);
+#endif /* __BIG_ENDIAN */
+}
+
diff --git a/drivers/media/dvb/siano/smsendian.h b/drivers/media/dvb/siano/smsendian.h
new file mode 100644
index 000000000000..7fbedc6a6527
--- /dev/null
+++ b/drivers/media/dvb/siano/smsendian.h
@@ -0,0 +1,32 @@
+/****************************************************************
+
+Siano Mobile Silicon, Inc.
+MDTV receiver kernel modules.
+Copyright (C) 2006-2009, Uri Shkolnik
+
+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 <http://www.gnu.org/licenses/>.
+
+****************************************************************/
+
+#ifndef __SMS_ENDIAN_H__
+#define __SMS_ENDIAN_H__
+
+#include <asm/byteorder.h>
+
+void smsendian_handle_tx_message(void *buffer);
+void smsendian_handle_rx_message(void *buffer);
+void smsendian_handle_message_header(void *msg);
+
+#endif /* __SMS_ENDIAN_H__ */
+
diff --git a/drivers/media/dvb/siano/smsir.c b/drivers/media/dvb/siano/smsir.c
new file mode 100644
index 000000000000..a5f302c58fdb
--- /dev/null
+++ b/drivers/media/dvb/siano/smsir.c
@@ -0,0 +1,301 @@
+/****************************************************************
+
+ Siano Mobile Silicon, Inc.
+ MDTV receiver kernel modules.
+ Copyright (C) 2006-2009, Uri Shkolnik
+
+ 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 <http://www.gnu.org/licenses/>.
+
+ ****************************************************************/
+
+
+#include <linux/types.h>
+#include <linux/input.h>
+
+#include "smscoreapi.h"
+#include "smsir.h"
+#include "sms-cards.h"
+
+/* In order to add new IR remote control -
+ * 1) Add it to the <enum ir_kb_type> @ smsir,h,
+ * 2) Add its map to keyboard_layout_maps below
+ * 3) Set your board (sms-cards sub-module) to use it
+ */
+
+static struct keyboard_layout_map_t keyboard_layout_maps[] = {
+ [SMS_IR_KB_DEFAULT_TV] = {
+ .ir_protocol = IR_RC5,
+ .rc5_kbd_address = KEYBOARD_ADDRESS_TV1,
+ .keyboard_layout_map = {
+ KEY_0, KEY_1, KEY_2,
+ KEY_3, KEY_4, KEY_5,
+ KEY_6, KEY_7, KEY_8,
+ KEY_9, 0, 0, KEY_POWER,
+ KEY_MUTE, 0, 0,
+ KEY_VOLUMEUP, KEY_VOLUMEDOWN,
+ KEY_BRIGHTNESSUP,
+ KEY_BRIGHTNESSDOWN, KEY_CHANNELUP,
+ KEY_CHANNELDOWN,
+ 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, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ }
+ },
+ [SMS_IR_KB_HCW_SILVER] = {
+ .ir_protocol = IR_RC5,
+ .rc5_kbd_address = KEYBOARD_ADDRESS_LIGHTING1,
+ .keyboard_layout_map = {
+ KEY_0, KEY_1, KEY_2,
+ KEY_3, KEY_4, KEY_5,
+ KEY_6, KEY_7, KEY_8,
+ KEY_9, KEY_TEXT, KEY_RED,
+ KEY_RADIO, KEY_MENU,
+ KEY_SUBTITLE,
+ KEY_MUTE, KEY_VOLUMEUP,
+ KEY_VOLUMEDOWN, KEY_PREVIOUS, 0,
+ KEY_UP, KEY_DOWN, KEY_LEFT,
+ KEY_RIGHT, KEY_VIDEO, KEY_AUDIO,
+ KEY_MHP, KEY_EPG, KEY_TV,
+ 0, KEY_NEXTSONG, KEY_EXIT,
+ KEY_CHANNELUP, KEY_CHANNELDOWN,
+ KEY_CHANNEL, 0,
+ KEY_PREVIOUSSONG, KEY_ENTER,
+ KEY_SLEEP, 0, 0, KEY_BLUE,
+ 0, 0, 0, 0, KEY_GREEN, 0,
+ KEY_PAUSE, 0, KEY_REWIND,
+ 0, KEY_FASTFORWARD, KEY_PLAY,
+ KEY_STOP, KEY_RECORD,
+ KEY_YELLOW, 0, 0, KEY_SELECT,
+ KEY_ZOOM, KEY_POWER, 0, 0
+ }
+ },
+ { } /* Terminating entry */
+};
+
+u32 ir_pos;
+u32 ir_word;
+u32 ir_toggle;
+
+#define RC5_PUSH_BIT(dst, bit, pos) \
+ { dst <<= 1; dst |= bit; pos++; }
+
+
+static void sms_ir_rc5_event(struct smscore_device_t *coredev,
+ u32 toggle, u32 addr, u32 cmd)
+{
+ bool toggle_changed;
+ u16 keycode;
+
+ sms_info("IR RC5 word: address %d, command %d, toggle %d",
+ addr, cmd, toggle);
+
+ toggle_changed = ir_toggle != toggle;
+ /* keep toggle */
+ ir_toggle = toggle;
+
+ if (addr !=
+ keyboard_layout_maps[coredev->ir.ir_kb_type].rc5_kbd_address)
+ return; /* Check for valid address */
+
+ keycode =
+ keyboard_layout_maps
+ [coredev->ir.ir_kb_type].keyboard_layout_map[cmd];
+
+ if (!toggle_changed &&
+ (keycode != KEY_VOLUMEUP && keycode != KEY_VOLUMEDOWN))
+ return; /* accept only repeated volume, reject other keys */
+
+ sms_info("kernel input keycode (from ir) %d", keycode);
+ input_report_key(coredev->ir.input_dev, keycode, 1);
+ input_sync(coredev->ir.input_dev);
+
+}
+
+/* decode raw bit pattern to RC5 code */
+/* taken from ir-functions.c */
+static u32 ir_rc5_decode(unsigned int code)
+{
+/* unsigned int org_code = code;*/
+ unsigned int pair;
+ unsigned int rc5 = 0;
+ int i;
+
+ for (i = 0; i < 14; ++i) {
+ pair = code & 0x3;
+ code >>= 2;
+
+ rc5 <<= 1;
+ switch (pair) {
+ case 0:
+ case 2:
+ break;
+ case 1:
+ rc5 |= 1;
+ break;
+ case 3:
+/* dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code);*/
+ sms_info("bad code");
+ return 0;
+ }
+ }
+/*
+ dprintk(1, "ir-common: code=%x, rc5=%x, start=%x,
+ toggle=%x, address=%x, "
+ "instr=%x\n", rc5, org_code, RC5_START(rc5),
+ RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
+*/
+ return rc5;
+}
+
+static void sms_rc5_parse_word(struct smscore_device_t *coredev)
+{
+ #define RC5_START(x) (((x)>>12)&3)
+ #define RC5_TOGGLE(x) (((x)>>11)&1)
+ #define RC5_ADDR(x) (((x)>>6)&0x1F)
+ #define RC5_INSTR(x) ((x)&0x3F)
+
+ int i, j;
+ u32 rc5_word = 0;
+
+ /* Reverse the IR word direction */
+ for (i = 0 ; i < 28 ; i++)
+ RC5_PUSH_BIT(rc5_word, (ir_word>>i)&1, j)
+
+ rc5_word = ir_rc5_decode(rc5_word);
+ /* sms_info("temp = 0x%x, rc5_code = 0x%x", ir_word, rc5_word); */
+
+ sms_ir_rc5_event(coredev,
+ RC5_TOGGLE(rc5_word),
+ RC5_ADDR(rc5_word),
+ RC5_INSTR(rc5_word));
+}
+
+
+static void sms_rc5_accumulate_bits(struct smscore_device_t *coredev,
+ s32 ir_sample)
+{
+ #define RC5_TIME_GRANULARITY 200
+ #define RC5_DEF_BIT_TIME 889
+ #define RC5_MAX_SAME_BIT_CONT 4
+ #define RC5_WORD_LEN 27 /* 28 bit */
+
+ u32 i, j;
+ s32 delta_time;
+ u32 time = (ir_sample > 0) ? ir_sample : (0-ir_sample);
+ u32 level = (ir_sample < 0) ? 0 : 1;
+
+ for (i = RC5_MAX_SAME_BIT_CONT; i > 0; i--) {
+ delta_time = time - (i*RC5_DEF_BIT_TIME) + RC5_TIME_GRANULARITY;
+ if (delta_time < 0)
+ continue; /* not so many consecutive bits */
+ if (delta_time > (2 * RC5_TIME_GRANULARITY)) {
+ /* timeout */
+ if (ir_pos == (RC5_WORD_LEN-1))
+ /* complete last bit */
+ RC5_PUSH_BIT(ir_word, level, ir_pos)
+
+ if (ir_pos == RC5_WORD_LEN)
+ sms_rc5_parse_word(coredev);
+ else if (ir_pos) /* timeout within a word */
+ sms_info("IR error parsing a word");
+
+ ir_pos = 0;
+ ir_word = 0;
+ /* sms_info("timeout %d", time); */
+ break;
+ }
+ /* The time is within the range of this number of bits */
+ for (j = 0 ; j < i ; j++)
+ RC5_PUSH_BIT(ir_word, level, ir_pos)
+
+ break;
+ }
+}
+
+void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len)
+{
+ #define IR_DATA_RECEIVE_MAX_LEN 520 /* 128*4 + 4 + 4 */
+ u32 i;
+ enum ir_protocol ir_protocol =
+ keyboard_layout_maps[coredev->ir.ir_kb_type]
+ .ir_protocol;
+ s32 *samples;
+ int count = len>>2;
+
+ samples = (s32 *)buf;
+/* sms_info("IR buffer received, length = %d", count);*/
+
+ for (i = 0; i < count; i++)
+ if (ir_protocol == IR_RC5)
+ sms_rc5_accumulate_bits(coredev, samples[i]);
+ /* IR_RCMM not implemented */
+}
+
+int sms_ir_init(struct smscore_device_t *coredev)
+{
+ struct input_dev *input_dev;
+
+ sms_info("Allocating input device");
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ sms_err("Not enough memory");
+ return -ENOMEM;
+ }
+
+ coredev->ir.input_dev = input_dev;
+ coredev->ir.ir_kb_type =
+ sms_get_board(smscore_get_board_id(coredev))->ir_kb_type;
+ coredev->ir.keyboard_layout_map =
+ keyboard_layout_maps[coredev->ir.ir_kb_type].
+ keyboard_layout_map;
+ sms_info("IR remote keyboard type is %d", coredev->ir.ir_kb_type);
+
+ coredev->ir.controller = 0; /* Todo: vega/nova SPI number */
+ coredev->ir.timeout = IR_DEFAULT_TIMEOUT;
+ sms_info("IR port %d, timeout %d ms",
+ coredev->ir.controller, coredev->ir.timeout);
+
+ snprintf(coredev->ir.name,
+ IR_DEV_NAME_MAX_LEN,
+ "SMS IR w/kbd type %d",
+ coredev->ir.ir_kb_type);
+ input_dev->name = coredev->ir.name;
+ input_dev->phys = coredev->ir.name;
+ input_dev->dev.parent = coredev->device;
+
+ /* Key press events only */
+ input_dev->evbit[0] = BIT_MASK(EV_KEY);
+ input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
+
+ sms_info("Input device (IR) %s is set for key events", input_dev->name);
+
+ if (input_register_device(input_dev)) {
+ sms_err("Failed to register device");
+ input_free_device(input_dev);
+ return -EACCES;
+ }
+
+ return 0;
+}
+
+void sms_ir_exit(struct smscore_device_t *coredev)
+{
+ if (coredev->ir.input_dev)
+ input_unregister_device(coredev->ir.input_dev);
+
+ sms_info("");
+}
+
diff --git a/drivers/media/dvb/siano/smsir.h b/drivers/media/dvb/siano/smsir.h
new file mode 100644
index 000000000000..b7d703e2d338
--- /dev/null
+++ b/drivers/media/dvb/siano/smsir.h
@@ -0,0 +1,93 @@
+/****************************************************************
+
+Siano Mobile Silicon, Inc.
+MDTV receiver kernel modules.
+Copyright (C) 2006-2009, Uri Shkolnik
+
+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 <http://www.gnu.org/licenses/>.
+
+****************************************************************/
+
+#ifndef __SMS_IR_H__
+#define __SMS_IR_H__
+
+#include <linux/input.h>
+
+#define IR_DEV_NAME_MAX_LEN 23 /* "SMS IR kbd type nn\0" */
+#define IR_KEYBOARD_LAYOUT_SIZE 64
+#define IR_DEFAULT_TIMEOUT 100
+
+enum ir_kb_type {
+ SMS_IR_KB_DEFAULT_TV,
+ SMS_IR_KB_HCW_SILVER
+};
+
+enum rc5_keyboard_address {
+ KEYBOARD_ADDRESS_TV1 = 0,
+ KEYBOARD_ADDRESS_TV2 = 1,
+ KEYBOARD_ADDRESS_TELETEXT = 2,
+ KEYBOARD_ADDRESS_VIDEO = 3,
+ KEYBOARD_ADDRESS_LV1 = 4,
+ KEYBOARD_ADDRESS_VCR1 = 5,
+ KEYBOARD_ADDRESS_VCR2 = 6,
+ KEYBOARD_ADDRESS_EXPERIMENTAL = 7,
+ KEYBOARD_ADDRESS_SAT1 = 8,
+ KEYBOARD_ADDRESS_CAMERA = 9,
+ KEYBOARD_ADDRESS_SAT2 = 10,
+ KEYBOARD_ADDRESS_CDV = 12,
+ KEYBOARD_ADDRESS_CAMCORDER = 13,
+ KEYBOARD_ADDRESS_PRE_AMP = 16,
+ KEYBOARD_ADDRESS_TUNER = 17,
+ KEYBOARD_ADDRESS_RECORDER1 = 18,
+ KEYBOARD_ADDRESS_PRE_AMP1 = 19,
+ KEYBOARD_ADDRESS_CD_PLAYER = 20,
+ KEYBOARD_ADDRESS_PHONO = 21,
+ KEYBOARD_ADDRESS_SATA = 22,
+ KEYBOARD_ADDRESS_RECORDER2 = 23,
+ KEYBOARD_ADDRESS_CDR = 26,
+ KEYBOARD_ADDRESS_LIGHTING = 29,
+ KEYBOARD_ADDRESS_LIGHTING1 = 30, /* KEYBOARD_ADDRESS_HCW_SILVER */
+ KEYBOARD_ADDRESS_PHONE = 31,
+ KEYBOARD_ADDRESS_NOT_RC5 = 0xFFFF
+};
+
+enum ir_protocol {
+ IR_RC5,
+ IR_RCMM
+};
+
+struct keyboard_layout_map_t {
+ enum ir_protocol ir_protocol;
+ enum rc5_keyboard_address rc5_kbd_address;
+ u16 keyboard_layout_map[IR_KEYBOARD_LAYOUT_SIZE];
+};
+
+struct smscore_device_t;
+
+struct ir_t {
+ struct input_dev *input_dev;
+ enum ir_kb_type ir_kb_type;
+ char name[IR_DEV_NAME_MAX_LEN+1];
+ u16 *keyboard_layout_map;
+ u32 timeout;
+ u32 controller;
+};
+
+int sms_ir_init(struct smscore_device_t *coredev);
+void sms_ir_exit(struct smscore_device_t *coredev);
+void sms_ir_event(struct smscore_device_t *coredev,
+ const char *buf, int len);
+
+#endif /* __SMS_IR_H__ */
+
diff --git a/drivers/media/dvb/siano/smssdio.c b/drivers/media/dvb/siano/smssdio.c
new file mode 100644
index 000000000000..4f8fa59a995a
--- /dev/null
+++ b/drivers/media/dvb/siano/smssdio.c
@@ -0,0 +1,354 @@
+/*
+ * smssdio.c - Siano 1xxx SDIO interface driver
+ *
+ * Copyright 2008 Pierre Ossman
+ *
+ * Based on code by Siano Mobile Silicon, Inc.,
+ * Copyright (C) 2006-2008, Uri Shkolnik
+ *
+ * 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 is a bit odd in that all transfers should be done
+ * to/from the SMSSDIO_DATA register, yet the "increase address" bit
+ * always needs to be set.
+ *
+ * Also, buffers from the card are always aligned to 128 byte
+ * boundaries.
+ */
+
+/*
+ * General cleanup notes:
+ *
+ * - only typedefs should be name *_t
+ *
+ * - use ERR_PTR and friends for smscore_register_device()
+ *
+ * - smscore_getbuffer should zero fields
+ *
+ * Fix stop command
+ */
+
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+
+#include "smscoreapi.h"
+#include "sms-cards.h"
+
+/* Registers */
+
+#define SMSSDIO_DATA 0x00
+#define SMSSDIO_INT 0x04
+
+static const struct sdio_device_id smssdio_ids[] = {
+ {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_STELLAR),
+ .driver_data = SMS1XXX_BOARD_SIANO_STELLAR},
+ {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_A0),
+ .driver_data = SMS1XXX_BOARD_SIANO_NOVA_A},
+ {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_B0),
+ .driver_data = SMS1XXX_BOARD_SIANO_NOVA_B},
+ {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VEGA_A0),
+ .driver_data = SMS1XXX_BOARD_SIANO_VEGA},
+ {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VENICE),
+ .driver_data = SMS1XXX_BOARD_SIANO_VEGA},
+ { /* end: all zeroes */ },
+};
+
+MODULE_DEVICE_TABLE(sdio, smssdio_ids);
+
+struct smssdio_device {
+ struct sdio_func *func;
+
+ struct smscore_device_t *coredev;
+
+ struct smscore_buffer_t *split_cb;
+};
+
+/*******************************************************************/
+/* Siano core callbacks */
+/*******************************************************************/
+
+static int smssdio_sendrequest(void *context, void *buffer, size_t size)
+{
+ int ret;
+ struct smssdio_device *smsdev;
+
+ smsdev = context;
+
+ sdio_claim_host(smsdev->func);
+
+ while (size >= smsdev->func->cur_blksize) {
+ ret = sdio_write_blocks(smsdev->func, SMSSDIO_DATA, buffer, 1);
+ if (ret)
+ goto out;
+
+ buffer += smsdev->func->cur_blksize;
+ size -= smsdev->func->cur_blksize;
+ }
+
+ if (size) {
+ ret = sdio_write_bytes(smsdev->func, SMSSDIO_DATA,
+ buffer, size);
+ }
+
+out:
+ sdio_release_host(smsdev->func);
+
+ return ret;
+}
+
+/*******************************************************************/
+/* SDIO callbacks */
+/*******************************************************************/
+
+static void smssdio_interrupt(struct sdio_func *func)
+{
+ int ret, isr;
+
+ struct smssdio_device *smsdev;
+ struct smscore_buffer_t *cb;
+ struct SmsMsgHdr_ST *hdr;
+ size_t size;
+
+ smsdev = sdio_get_drvdata(func);
+
+ /*
+ * The interrupt register has no defined meaning. It is just
+ * a way of turning of the level triggered interrupt.
+ */
+ isr = sdio_readb(func, SMSSDIO_INT, &ret);
+ if (ret) {
+ dev_err(&smsdev->func->dev,
+ "Unable to read interrupt register!\n");
+ return;
+ }
+
+ if (smsdev->split_cb == NULL) {
+ cb = smscore_getbuffer(smsdev->coredev);
+ if (!cb) {
+ dev_err(&smsdev->func->dev,
+ "Unable to allocate data buffer!\n");
+ return;
+ }
+
+ ret = sdio_read_blocks(smsdev->func, cb->p, SMSSDIO_DATA, 1);
+ if (ret) {
+ dev_err(&smsdev->func->dev,
+ "Error %d reading initial block!\n", ret);
+ return;
+ }
+
+ hdr = cb->p;
+
+ if (hdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG) {
+ smsdev->split_cb = cb;
+ return;
+ }
+
+ size = hdr->msgLength - smsdev->func->cur_blksize;
+ } else {
+ cb = smsdev->split_cb;
+ hdr = cb->p;
+
+ size = hdr->msgLength - sizeof(struct SmsMsgHdr_ST);
+
+ smsdev->split_cb = NULL;
+ }
+
+ if (hdr->msgLength > smsdev->func->cur_blksize) {
+ void *buffer;
+
+ size = ALIGN(size, 128);
+ buffer = cb->p + hdr->msgLength;
+
+ BUG_ON(smsdev->func->cur_blksize != 128);
+
+ /*
+ * First attempt to transfer all of it in one go...
+ */
+ ret = sdio_read_blocks(smsdev->func, buffer,
+ SMSSDIO_DATA, size / 128);
+ if (ret && ret != -EINVAL) {
+ smscore_putbuffer(smsdev->coredev, cb);
+ dev_err(&smsdev->func->dev,
+ "Error %d reading data from card!\n", ret);
+ return;
+ }
+
+ /*
+ * ..then fall back to one block at a time if that is
+ * not possible...
+ *
+ * (we have to do this manually because of the
+ * problem with the "increase address" bit)
+ */
+ if (ret == -EINVAL) {
+ while (size) {
+ ret = sdio_read_blocks(smsdev->func,
+ buffer, SMSSDIO_DATA, 1);
+ if (ret) {
+ smscore_putbuffer(smsdev->coredev, cb);
+ dev_err(&smsdev->func->dev,
+ "Error %d reading "
+ "data from card!\n", ret);
+ return;
+ }
+
+ buffer += smsdev->func->cur_blksize;
+ if (size > smsdev->func->cur_blksize)
+ size -= smsdev->func->cur_blksize;
+ else
+ size = 0;
+ }
+ }
+ }
+
+ cb->size = hdr->msgLength;
+ cb->offset = 0;
+
+ smscore_onresponse(smsdev->coredev, cb);
+}
+
+static int smssdio_probe(struct sdio_func *func,
+ const struct sdio_device_id *id)
+{
+ int ret;
+
+ int board_id;
+ struct smssdio_device *smsdev;
+ struct smsdevice_params_t params;
+
+ board_id = id->driver_data;
+
+ smsdev = kzalloc(sizeof(struct smssdio_device), GFP_KERNEL);
+ if (!smsdev)
+ return -ENOMEM;
+
+ smsdev->func = func;
+
+ memset(&params, 0, sizeof(struct smsdevice_params_t));
+
+ params.device = &func->dev;
+ params.buffer_size = 0x5000; /* ?? */
+ params.num_buffers = 22; /* ?? */
+ params.context = smsdev;
+
+ snprintf(params.devpath, sizeof(params.devpath),
+ "sdio\\%s", sdio_func_id(func));
+
+ params.sendrequest_handler = smssdio_sendrequest;
+
+ params.device_type = sms_get_board(board_id)->type;
+
+ if (params.device_type != SMS_STELLAR)
+ params.flags |= SMS_DEVICE_FAMILY2;
+ else {
+ /*
+ * FIXME: Stellar needs special handling...
+ */
+ ret = -ENODEV;
+ goto free;
+ }
+
+ ret = smscore_register_device(&params, &smsdev->coredev);
+ if (ret < 0)
+ goto free;
+
+ smscore_set_board_id(smsdev->coredev, board_id);
+
+ sdio_claim_host(func);
+
+ ret = sdio_enable_func(func);
+ if (ret)
+ goto release;
+
+ ret = sdio_set_block_size(func, 128);
+ if (ret)
+ goto disable;
+
+ ret = sdio_claim_irq(func, smssdio_interrupt);
+ if (ret)
+ goto disable;
+
+ sdio_set_drvdata(func, smsdev);
+
+ sdio_release_host(func);
+
+ ret = smscore_start_device(smsdev->coredev);
+ if (ret < 0)
+ goto reclaim;
+
+ return 0;
+
+reclaim:
+ sdio_claim_host(func);
+ sdio_release_irq(func);
+disable:
+ sdio_disable_func(func);
+release:
+ sdio_release_host(func);
+ smscore_unregister_device(smsdev->coredev);
+free:
+ kfree(smsdev);
+
+ return ret;
+}
+
+static void smssdio_remove(struct sdio_func *func)
+{
+ struct smssdio_device *smsdev;
+
+ smsdev = sdio_get_drvdata(func);
+
+ /* FIXME: racy! */
+ if (smsdev->split_cb)
+ smscore_putbuffer(smsdev->coredev, smsdev->split_cb);
+
+ smscore_unregister_device(smsdev->coredev);
+
+ sdio_claim_host(func);
+ sdio_release_irq(func);
+ sdio_disable_func(func);
+ sdio_release_host(func);
+
+ kfree(smsdev);
+}
+
+static struct sdio_driver smssdio_driver = {
+ .name = "smssdio",
+ .id_table = smssdio_ids,
+ .probe = smssdio_probe,
+ .remove = smssdio_remove,
+};
+
+/*******************************************************************/
+/* Module functions */
+/*******************************************************************/
+
+int smssdio_register(void)
+{
+ int ret = 0;
+
+ printk(KERN_INFO "smssdio: Siano SMS1xxx SDIO driver\n");
+ printk(KERN_INFO "smssdio: Copyright Pierre Ossman\n");
+
+ ret = sdio_register_driver(&smssdio_driver);
+
+ return ret;
+}
+
+void smssdio_unregister(void)
+{
+ sdio_unregister_driver(&smssdio_driver);
+}
+
+MODULE_DESCRIPTION("Siano SMS1xxx SDIO driver");
+MODULE_AUTHOR("Pierre Ossman");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c
index 5e3f88911a1d..e162691b515d 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.c
+++ b/drivers/media/dvb/ttpci/av7110_hw.c
@@ -1089,7 +1089,7 @@ int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
else {
int i, len = dc->x0-dc->color+1;
u8 __user *colors = (u8 __user *)dc->data;
- u8 r, g, b, blend;
+ u8 r, g = 0, b = 0, blend = 0;
ret = 0;
for (i = 0; i<len; i++) {
if (get_user(r, colors + i * 4) ||
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index 83e9e7750c8c..e48380c48990 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -47,6 +47,9 @@
#include "bsru6.h"
#include "bsbe1.h"
#include "tdhd1.h"
+#include "stv6110x.h"
+#include "stv090x.h"
+#include "isl6423.h"
static int diseqc_method;
module_param(diseqc_method, int, 0444);
@@ -425,6 +428,44 @@ static u8 read_pwm(struct budget* budget)
return pwm;
}
+static struct stv090x_config tt1600_stv090x_config = {
+ .device = STV0903,
+ .demod_mode = STV090x_SINGLE,
+ .clk_mode = STV090x_CLK_EXT,
+
+ .xtal = 27000000,
+ .address = 0x68,
+ .ref_clk = 27000000,
+
+ .ts1_mode = STV090x_TSMODE_DVBCI,
+ .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS,
+
+ .repeater_level = STV090x_RPTLEVEL_16,
+
+ .tuner_init = NULL,
+ .tuner_set_mode = NULL,
+ .tuner_set_frequency = NULL,
+ .tuner_get_frequency = NULL,
+ .tuner_set_bandwidth = NULL,
+ .tuner_get_bandwidth = NULL,
+ .tuner_set_bbgain = NULL,
+ .tuner_get_bbgain = NULL,
+ .tuner_set_refclk = NULL,
+ .tuner_get_status = NULL,
+};
+
+static struct stv6110x_config tt1600_stv6110x_config = {
+ .addr = 0x60,
+ .refclk = 27000000,
+};
+
+static struct isl6423_config tt1600_isl6423_config = {
+ .current_max = SEC_CURRENT_515m,
+ .curlim = SEC_CURRENT_LIM_ON,
+ .mod_extern = 1,
+ .addr = 0x08,
+};
+
static void frontend_init(struct budget *budget)
{
(void)alps_bsbe1_config; /* avoid warning */
@@ -566,6 +607,48 @@ static void frontend_init(struct budget *budget)
}
break;
}
+
+ case 0x101c: { /* TT S2-1600 */
+ struct stv6110x_devctl *ctl;
+ saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO);
+ msleep(50);
+ saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI);
+ msleep(250);
+
+ budget->dvb_frontend = dvb_attach(stv090x_attach,
+ &tt1600_stv090x_config,
+ &budget->i2c_adap,
+ STV090x_DEMODULATOR_0);
+
+ if (budget->dvb_frontend) {
+
+ ctl = dvb_attach(stv6110x_attach,
+ budget->dvb_frontend,
+ &tt1600_stv6110x_config,
+ &budget->i2c_adap);
+
+ tt1600_stv090x_config.tuner_init = ctl->tuner_init;
+ tt1600_stv090x_config.tuner_set_mode = ctl->tuner_set_mode;
+ tt1600_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency;
+ tt1600_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency;
+ tt1600_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth;
+ tt1600_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth;
+ tt1600_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain;
+ tt1600_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain;
+ tt1600_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk;
+ tt1600_stv090x_config.tuner_get_status = ctl->tuner_get_status;
+
+ dvb_attach(isl6423_attach,
+ budget->dvb_frontend,
+ &budget->i2c_adap,
+ &tt1600_isl6423_config);
+
+ } else {
+ dvb_frontend_detach(budget->dvb_frontend);
+ budget->dvb_frontend = NULL;
+ }
+ }
+ break;
}
if (budget->dvb_frontend == NULL) {
@@ -641,6 +724,7 @@ MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT);
MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC);
MAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT);
+MAKE_BUDGET_INFO(tt1600, "TT-Budget S2-1600 PCI", BUDGET_TT);
MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY);
MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
MAKE_BUDGET_INFO(fsact, "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY);
@@ -653,6 +737,7 @@ static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1016),
MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018),
+ MAKE_EXTENSION_PCI(tt1600, 0x13c2, 0x101c),
MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
MAKE_EXTENSION_PCI(fsact1, 0x1131, 0x5f60),
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 1dba8f0832a0..5cf6c45b91fe 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -153,7 +153,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
mult = (fmi->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000;
v->rangelow = RSF16_MINFREQ / mult;
v->rangehigh = RSF16_MAXFREQ / mult;
- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO;
+ v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
v->capability = fmi->flags & V4L2_TUNER_CAP_LOW;
v->audmode = V4L2_TUNER_MODE_STEREO;
v->signal = fmi_getsigstr(fmi);
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index c09ca8600ea1..935ff9bcdfcc 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -233,7 +233,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
mult = (fmr2->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000;
v->rangelow = RSF16_MINFREQ / mult;
v->rangehigh = RSF16_MAXFREQ / mult;
- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO;
+ v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
v->capability = fmr2->flags&V4L2_TUNER_CAP_LOW;
v->audmode = fmr2->stereo ? V4L2_TUNER_MODE_STEREO:
V4L2_TUNER_MODE_MONO;
diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c
index 92c297796a9f..640421ceb24a 100644
--- a/drivers/media/radio/radio-si470x.c
+++ b/drivers/media/radio/radio-si470x.c
@@ -1200,7 +1200,7 @@ static int si470x_fops_release(struct file *file)
video_unregister_device(radio->videodev);
kfree(radio->buffer);
kfree(radio);
- goto unlock;
+ goto done;
}
/* stop rds reception */
@@ -1214,7 +1214,6 @@ static int si470x_fops_release(struct file *file)
usb_autopm_put_interface(radio->intf);
}
-unlock:
mutex_unlock(&radio->disconnect_lock);
done:
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 3f1a0350a569..7aefac64330f 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -134,10 +134,6 @@ obj-$(CONFIG_VIDEO_CX18) += cx18/
obj-$(CONFIG_VIDEO_VIVI) += vivi.o
obj-$(CONFIG_VIDEO_CX23885) += cx23885/
-obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o
-obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o
-obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o
-obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o
obj-$(CONFIG_VIDEO_OMAP2) += omap2cam.o
obj-$(CONFIG_SOC_CAMERA) += soc_camera.o
obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o
@@ -147,6 +143,11 @@ obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o
obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o
obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o
obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o
+# soc-camera host drivers have to be linked after camera drivers
+obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o
+obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o
+obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o
+obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o
obj-$(CONFIG_VIDEO_AU0828) += au0828/
diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c
index 4cee0b92eeee..a1e4c0d769a6 100644
--- a/drivers/media/video/au0828/au0828-core.c
+++ b/drivers/media/video/au0828/au0828-core.c
@@ -192,8 +192,6 @@ static int au0828_usb_probe(struct usb_interface *interface,
dev->usbdev = usbdev;
dev->boardnr = id->driver_info;
- usb_set_intfdata(interface, dev);
-
/* Create the v4l2_device */
retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
if (retval) {
@@ -222,6 +220,10 @@ static int au0828_usb_probe(struct usb_interface *interface,
/* Digital TV */
au0828_dvb_register(dev);
+ /* Store the pointer to the au0828_dev so it can be accessed in
+ au0828_usb_disconnect */
+ usb_set_intfdata(interface, dev);
+
printk(KERN_INFO "Registered device AU0828 [%s]\n",
dev->board.name == NULL ? "Unset" : dev->board.name);
diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c
index a99d92fac3dc..ebd1ee9dc871 100644
--- a/drivers/media/video/bt8xx/bttv-i2c.c
+++ b/drivers/media/video/bt8xx/bttv-i2c.c
@@ -389,6 +389,27 @@ int __devinit init_bttv_i2c(struct bttv *btv)
}
if (0 == btv->i2c_rc && i2c_scan)
do_i2c_scan(btv->c.v4l2_dev.name, &btv->i2c_client);
+
+ /* Instantiate the IR receiver device, if present */
+ if (0 == btv->i2c_rc) {
+ struct i2c_board_info info;
+ /* The external IR receiver is at i2c address 0x34 (0x35 for
+ reads). Future Hauppauge cards will have an internal
+ receiver at 0x30 (0x31 for reads). In theory, both can be
+ fitted, and Hauppauge suggest an external overrides an
+ internal.
+
+ That's why we probe 0x1a (~0x34) first. CB
+ */
+ const unsigned short addr_list[] = {
+ 0x1a, 0x18, 0x4b, 0x64, 0x30,
+ I2C_CLIENT_END
+ };
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+ i2c_new_probed_device(&btv->c.i2c_adap, &info, addr_list);
+ }
return btv->i2c_rc;
}
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
index 5f582726985d..c4d181dde1ca 100644
--- a/drivers/media/video/cafe_ccic.c
+++ b/drivers/media/video/cafe_ccic.c
@@ -774,6 +774,7 @@ static int cafe_cam_init(struct cafe_camera *cam)
ret = __cafe_cam_reset(cam);
if (ret)
goto out;
+ chip.ident = V4L2_IDENT_NONE;
chip.match.type = V4L2_CHIP_MATCH_I2C_ADDR;
chip.match.addr = cam->sensor_addr;
ret = sensor_call(cam, core, g_chip_ident, &chip);
diff --git a/drivers/media/video/cx18/cx18-audio.c b/drivers/media/video/cx18/cx18-audio.c
index 1519e91c677a..35268923911c 100644
--- a/drivers/media/video/cx18/cx18-audio.c
+++ b/drivers/media/video/cx18/cx18-audio.c
@@ -26,14 +26,18 @@
#include "cx18-cards.h"
#include "cx18-audio.h"
-#define CX18_AUDIO_ENABLE 0xc72014
+#define CX18_AUDIO_ENABLE 0xc72014
+#define CX18_AI1_MUX_MASK 0x30
+#define CX18_AI1_MUX_I2S1 0x00
+#define CX18_AI1_MUX_I2S2 0x10
+#define CX18_AI1_MUX_843_I2S 0x20
/* Selects the audio input and output according to the current
settings. */
int cx18_audio_set_io(struct cx18 *cx)
{
const struct cx18_card_audio_input *in;
- u32 val;
+ u32 u, v;
int err;
/* Determine which input to use */
@@ -44,7 +48,7 @@ int cx18_audio_set_io(struct cx18 *cx)
/* handle muxer chips */
v4l2_subdev_call(cx->sd_extmux, audio, s_routing,
- in->audio_input, 0, 0);
+ (u32) in->muxer_input, 0, 0);
err = cx18_call_hw_err(cx, cx->card->hw_audio_ctrl,
audio, s_routing, in->audio_input, 0, 0);
@@ -52,9 +56,37 @@ int cx18_audio_set_io(struct cx18 *cx)
return err;
/* FIXME - this internal mux should be abstracted to a subdev */
- val = cx18_read_reg(cx, CX18_AUDIO_ENABLE) & ~0x30;
- val |= (in->audio_input > CX18_AV_AUDIO_SERIAL2) ? 0x20 :
- (in->audio_input << 4);
- cx18_write_reg_expect(cx, val | 0xb00, CX18_AUDIO_ENABLE, val, 0x30);
+ u = cx18_read_reg(cx, CX18_AUDIO_ENABLE);
+ v = u & ~CX18_AI1_MUX_MASK;
+ switch (in->audio_input) {
+ case CX18_AV_AUDIO_SERIAL1:
+ v |= CX18_AI1_MUX_I2S1;
+ break;
+ case CX18_AV_AUDIO_SERIAL2:
+ v |= CX18_AI1_MUX_I2S2;
+ break;
+ default:
+ v |= CX18_AI1_MUX_843_I2S;
+ break;
+ }
+ if (v == u) {
+ /* force a toggle of some AI1 MUX control bits */
+ u &= ~CX18_AI1_MUX_MASK;
+ switch (in->audio_input) {
+ case CX18_AV_AUDIO_SERIAL1:
+ u |= CX18_AI1_MUX_843_I2S;
+ break;
+ case CX18_AV_AUDIO_SERIAL2:
+ u |= CX18_AI1_MUX_843_I2S;
+ break;
+ default:
+ u |= CX18_AI1_MUX_I2S1;
+ break;
+ }
+ cx18_write_reg_expect(cx, u | 0xb00, CX18_AUDIO_ENABLE,
+ u, CX18_AI1_MUX_MASK);
+ }
+ cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE,
+ v, CX18_AI1_MUX_MASK);
return 0;
}
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c
index cf2bd888a429..2b07b156340b 100644
--- a/drivers/media/video/cx18/cx18-av-core.c
+++ b/drivers/media/video/cx18/cx18-av-core.c
@@ -99,9 +99,39 @@ int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 and_mask,
or_value);
}
-static void cx18_av_initialize(struct cx18 *cx)
+static int cx18_av_init(struct v4l2_subdev *sd, u32 val)
{
- struct cx18_av_state *state = &cx->av_state;
+ struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+ /*
+ * The crystal freq used in calculations in this driver will be
+ * 28.636360 MHz.
+ * Aim to run the PLLs' VCOs near 400 MHz to minimze errors.
+ */
+
+ /*
+ * VDCLK Integer = 0x0f, Post Divider = 0x04
+ * AIMCLK Integer = 0x0e, Post Divider = 0x16
+ */
+ cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f);
+
+ /* VDCLK Fraction = 0x2be2fe */
+ /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz before post divide */
+ cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe);
+
+ /* AIMCLK Fraction = 0x05227ad */
+ /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz pre post-div*/
+ cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad);
+
+ /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */
+ cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56);
+ return 0;
+}
+
+static void cx18_av_initialize(struct v4l2_subdev *sd)
+{
+ struct cx18_av_state *state = to_cx18_av_state(sd);
+ struct cx18 *cx = v4l2_get_subdevdata(sd);
u32 v;
cx18_av_loadfw(cx);
@@ -150,6 +180,26 @@ static void cx18_av_initialize(struct cx18 *cx)
cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0x8000);
cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0);
+ /*
+ * Disable Video Auto-config of the Analog Front End and Video PLL.
+ *
+ * Since we only use BT.656 pixel mode, which works for both 525 and 625
+ * line systems, it's just easier for us to set registers
+ * 0x102 (CXADEC_CHIP_CTRL), 0x104-0x106 (CXADEC_AFE_CTRL),
+ * 0x108-0x109 (CXADEC_PLL_CTRL1), and 0x10c-0x10f (CXADEC_VID_PLL_FRAC)
+ * ourselves, than to run around cleaning up after the auto-config.
+ *
+ * (Note: my CX23418 chip doesn't seem to let the ACFG_DIS bit
+ * get set to 1, but OTOH, it doesn't seem to do AFE and VID PLL
+ * autoconfig either.)
+ *
+ * As a default, also turn off Dual mode for ADC2 and set ADC2 to CH3.
+ */
+ cx18_av_and_or4(cx, CXADEC_CHIP_CTRL, 0xFFFBFFFF, 0x00120000);
+
+ /* Setup the Video and and Aux/Audio PLLs */
+ cx18_av_init(sd, 0);
+
/* set video to auto-detect */
/* Clear bits 11-12 to enable slow locking mode. Set autodetect mode */
/* set the comb notch = 1 */
@@ -176,12 +226,23 @@ static void cx18_av_initialize(struct cx18 *cx)
/* EncSetSignalStd(dwDevNum, pEnc->dwSigStd); */
/* EncSetVideoInput(dwDevNum, pEnc->VidIndSelection); */
- v = cx18_av_read4(cx, CXADEC_AFE_CTRL);
- v &= 0xFFFBFFFF; /* turn OFF bit 18 for droop_comp_ch1 */
- v &= 0xFFFF7FFF; /* turn OFF bit 9 for clamp_sel_ch1 */
- v &= 0xFFFFFFFE; /* turn OFF bit 0 for 12db_ch1 */
- /* v |= 0x00000001;*/ /* turn ON bit 0 for 12db_ch1 */
- cx18_av_write4(cx, CXADEC_AFE_CTRL, v);
+ /*
+ * Analog Front End (AFE)
+ * Default to luma on ch1/ADC1, chroma on ch2/ADC2, SIF on ch3/ADC2
+ * bypass_ch[1-3] use filter
+ * droop_comp_ch[1-3] disable
+ * clamp_en_ch[1-3] disable
+ * aud_in_sel ADC2
+ * luma_in_sel ADC1
+ * chroma_in_sel ADC2
+ * clamp_sel_ch[2-3] midcode
+ * clamp_sel_ch1 video decoder
+ * vga_sel_ch3 audio decoder
+ * vga_sel_ch[1-2] video decoder
+ * half_bw_ch[1-3] disable
+ * +12db_ch[1-3] disable
+ */
+ cx18_av_and_or4(cx, CXADEC_AFE_CTRL, 0xFF000000, 0x00005D00);
/* if(dwEnable && dw3DCombAvailable) { */
/* CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x7728021F); */
@@ -195,50 +256,18 @@ static void cx18_av_initialize(struct cx18 *cx)
static int cx18_av_reset(struct v4l2_subdev *sd, u32 val)
{
- struct cx18 *cx = v4l2_get_subdevdata(sd);
-
- cx18_av_initialize(cx);
- return 0;
-}
-
-static int cx18_av_init(struct v4l2_subdev *sd, u32 val)
-{
- struct cx18 *cx = v4l2_get_subdevdata(sd);
-
- /*
- * The crystal freq used in calculations in this driver will be
- * 28.636360 MHz.
- * Aim to run the PLLs' VCOs near 400 MHz to minimze errors.
- */
-
- /*
- * VDCLK Integer = 0x0f, Post Divider = 0x04
- * AIMCLK Integer = 0x0e, Post Divider = 0x16
- */
- cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f);
-
- /* VDCLK Fraction = 0x2be2fe */
- /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz before post divide */
- cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe);
-
- /* AIMCLK Fraction = 0x05227ad */
- /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz pre post-div*/
- cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad);
-
- /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */
- cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56);
+ cx18_av_initialize(sd);
return 0;
}
static int cx18_av_load_fw(struct v4l2_subdev *sd)
{
struct cx18_av_state *state = to_cx18_av_state(sd);
- struct cx18 *cx = v4l2_get_subdevdata(sd);
if (!state->is_initialized) {
/* initialize on first use */
state->is_initialized = 1;
- cx18_av_initialize(cx);
+ cx18_av_initialize(sd);
}
return 0;
}
@@ -470,16 +499,23 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
{
struct cx18_av_state *state = &cx->av_state;
struct v4l2_subdev *sd = &state->sd;
- u8 is_composite = (vid_input >= CX18_AV_COMPOSITE1 &&
- vid_input <= CX18_AV_COMPOSITE8);
- u8 reg;
- u8 v;
+
+ enum analog_signal_type {
+ NONE, CVBS, Y, C, SIF, Pb, Pr
+ } ch[3] = {NONE, NONE, NONE};
+
+ u8 afe_mux_cfg;
+ u8 adc2_cfg;
+ u32 afe_cfg;
+ int i;
CX18_DEBUG_INFO_DEV(sd, "decoder set video input %d, audio input %d\n",
vid_input, aud_input);
- if (is_composite) {
- reg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1);
+ if (vid_input >= CX18_AV_COMPOSITE1 &&
+ vid_input <= CX18_AV_COMPOSITE8) {
+ afe_mux_cfg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1);
+ ch[0] = CVBS;
} else {
int luma = vid_input & 0xf0;
int chroma = vid_input & 0xf00;
@@ -493,26 +529,45 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
vid_input);
return -EINVAL;
}
- reg = 0xf0 + ((luma - CX18_AV_SVIDEO_LUMA1) >> 4);
+ afe_mux_cfg = 0xf0 + ((luma - CX18_AV_SVIDEO_LUMA1) >> 4);
+ ch[0] = Y;
if (chroma >= CX18_AV_SVIDEO_CHROMA7) {
- reg &= 0x3f;
- reg |= (chroma - CX18_AV_SVIDEO_CHROMA7) >> 2;
+ afe_mux_cfg &= 0x3f;
+ afe_mux_cfg |= (chroma - CX18_AV_SVIDEO_CHROMA7) >> 2;
+ ch[2] = C;
} else {
- reg &= 0xcf;
- reg |= (chroma - CX18_AV_SVIDEO_CHROMA4) >> 4;
+ afe_mux_cfg &= 0xcf;
+ afe_mux_cfg |= (chroma - CX18_AV_SVIDEO_CHROMA4) >> 4;
+ ch[1] = C;
}
}
+ /* TODO: LeadTek WinFast DVR3100 H & WinFast PVR2100 can do Y/Pb/Pr */
switch (aud_input) {
case CX18_AV_AUDIO_SERIAL1:
case CX18_AV_AUDIO_SERIAL2:
/* do nothing, use serial audio input */
break;
- case CX18_AV_AUDIO4: reg &= ~0x30; break;
- case CX18_AV_AUDIO5: reg &= ~0x30; reg |= 0x10; break;
- case CX18_AV_AUDIO6: reg &= ~0x30; reg |= 0x20; break;
- case CX18_AV_AUDIO7: reg &= ~0xc0; break;
- case CX18_AV_AUDIO8: reg &= ~0xc0; reg |= 0x40; break;
+ case CX18_AV_AUDIO4:
+ afe_mux_cfg &= ~0x30;
+ ch[1] = SIF;
+ break;
+ case CX18_AV_AUDIO5:
+ afe_mux_cfg = (afe_mux_cfg & ~0x30) | 0x10;
+ ch[1] = SIF;
+ break;
+ case CX18_AV_AUDIO6:
+ afe_mux_cfg = (afe_mux_cfg & ~0x30) | 0x20;
+ ch[1] = SIF;
+ break;
+ case CX18_AV_AUDIO7:
+ afe_mux_cfg &= ~0xc0;
+ ch[2] = SIF;
+ break;
+ case CX18_AV_AUDIO8:
+ afe_mux_cfg = (afe_mux_cfg & ~0xc0) | 0x40;
+ ch[2] = SIF;
+ break;
default:
CX18_ERR_DEV(sd, "0x%04x is not a valid audio input!\n",
@@ -520,24 +575,65 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
return -EINVAL;
}
- cx18_av_write_expect(cx, 0x103, reg, reg, 0xf7);
+ /* Set up analog front end multiplexers */
+ cx18_av_write_expect(cx, 0x103, afe_mux_cfg, afe_mux_cfg, 0xf7);
/* Set INPUT_MODE to Composite (0) or S-Video (1) */
- cx18_av_and_or(cx, 0x401, ~0x6, is_composite ? 0 : 0x02);
+ cx18_av_and_or(cx, 0x401, ~0x6, ch[0] == CVBS ? 0 : 0x02);
/* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
- v = cx18_av_read(cx, 0x102);
- if (reg & 0x80)
- v &= ~0x2;
+ adc2_cfg = cx18_av_read(cx, 0x102);
+ if (ch[2] == NONE)
+ adc2_cfg &= ~0x2; /* No sig on CH3, set ADC2 to CH2 for input */
else
- v |= 0x2;
+ adc2_cfg |= 0x2; /* Signal on CH3, set ADC2 to CH3 for input */
+
/* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */
- if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30)
- v |= 0x4;
+ if (ch[1] != NONE && ch[2] != NONE)
+ adc2_cfg |= 0x4; /* Set dual mode */
else
- v &= ~0x4;
- cx18_av_write_expect(cx, 0x102, v, v, 0x17);
+ adc2_cfg &= ~0x4; /* Clear dual mode */
+ cx18_av_write_expect(cx, 0x102, adc2_cfg, adc2_cfg, 0x17);
+
+ /* Configure the analog front end */
+ afe_cfg = cx18_av_read4(cx, CXADEC_AFE_CTRL);
+ afe_cfg &= 0xff000000;
+ afe_cfg |= 0x00005000; /* CHROMA_IN, AUD_IN: ADC2; LUMA_IN: ADC1 */
+ if (ch[1] != NONE && ch[2] != NONE)
+ afe_cfg |= 0x00000030; /* half_bw_ch[2-3] since in dual mode */
+
+ for (i = 0; i < 3; i++) {
+ switch (ch[i]) {
+ default:
+ case NONE:
+ /* CLAMP_SEL = Fixed to midcode clamp level */
+ afe_cfg |= (0x00000200 << i);
+ break;
+ case CVBS:
+ case Y:
+ if (i > 0)
+ afe_cfg |= 0x00002000; /* LUMA_IN_SEL: ADC2 */
+ break;
+ case C:
+ case Pb:
+ case Pr:
+ /* CLAMP_SEL = Fixed to midcode clamp level */
+ afe_cfg |= (0x00000200 << i);
+ if (i == 0 && ch[i] == C)
+ afe_cfg &= ~0x00001000; /* CHROMA_IN_SEL ADC1 */
+ break;
+ case SIF:
+ /*
+ * VGA_GAIN_SEL = Audio Decoder
+ * CLAMP_SEL = Fixed to midcode clamp level
+ */
+ afe_cfg |= (0x00000240 << i);
+ if (i == 0)
+ afe_cfg &= ~0x00004000; /* AUD_IN_SEL ADC1 */
+ break;
+ }
+ }
- /*cx18_av_and_or4(cx, 0x104, ~0x001b4180, 0x00004180);*/
+ cx18_av_write4(cx, CXADEC_AFE_CTRL, afe_cfg);
state->vid_input = vid_input;
state->aud_input = aud_input;
diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c
index 49a55cc8d839..b9e8cc5d264a 100644
--- a/drivers/media/video/cx18/cx18-av-firmware.c
+++ b/drivers/media/video/cx18/cx18-av-firmware.c
@@ -24,15 +24,63 @@
#include "cx18-io.h"
#include <linux/firmware.h>
-#define CX18_AUDIO_ENABLE 0xc72014
+#define CX18_AUDIO_ENABLE 0xc72014
+#define CX18_AI1_MUX_MASK 0x30
+#define CX18_AI1_MUX_I2S1 0x00
+#define CX18_AI1_MUX_I2S2 0x10
+#define CX18_AI1_MUX_843_I2S 0x20
+#define CX18_AI1_MUX_INVALID 0x30
+
#define FWFILE "v4l-cx23418-dig.fw"
+static int cx18_av_verifyfw(struct cx18 *cx, const struct firmware *fw)
+{
+ struct v4l2_subdev *sd = &cx->av_state.sd;
+ int ret = 0;
+ const u8 *data;
+ u32 size;
+ int addr;
+ u32 expected, dl_control;
+
+ /* Ensure we put the 8051 in reset and enable firmware upload mode */
+ dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
+ do {
+ dl_control &= 0x00ffffff;
+ dl_control |= 0x0f000000;
+ cx18_av_write4_noretry(cx, CXADEC_DL_CTL, dl_control);
+ dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
+ } while ((dl_control & 0xff000000) != 0x0f000000);
+
+ /* Read and auto increment until at address 0x0000 */
+ while (dl_control & 0x3fff)
+ dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
+
+ data = fw->data;
+ size = fw->size;
+ for (addr = 0; addr < size; addr++) {
+ dl_control &= 0xffff3fff; /* ignore top 2 bits of address */
+ expected = 0x0f000000 | ((u32)data[addr] << 16) | addr;
+ if (expected != dl_control) {
+ CX18_ERR_DEV(sd, "verification of %s firmware load "
+ "failed: expected %#010x got %#010x\n",
+ FWFILE, expected, dl_control);
+ ret = -EIO;
+ break;
+ }
+ dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
+ }
+ if (ret == 0)
+ CX18_INFO_DEV(sd, "verified load of %s firmware (%d bytes)\n",
+ FWFILE, size);
+ return ret;
+}
+
int cx18_av_loadfw(struct cx18 *cx)
{
struct v4l2_subdev *sd = &cx->av_state.sd;
const struct firmware *fw = NULL;
u32 size;
- u32 v;
+ u32 u, v;
const u8 *ptr;
int i;
int retries1 = 0;
@@ -95,6 +143,12 @@ int cx18_av_loadfw(struct cx18 *cx)
}
cx18_av_write4_expect(cx, CXADEC_DL_CTL,
+ 0x03000000 | fw->size, 0x03000000, 0x13000000);
+
+ CX18_INFO_DEV(sd, "loaded %s firmware (%d bytes)\n", FWFILE, size);
+
+ if (cx18_av_verifyfw(cx, fw) == 0)
+ cx18_av_write4_expect(cx, CXADEC_DL_CTL,
0x13000000 | fw->size, 0x13000000, 0x13000000);
/* Output to the 416 */
@@ -135,6 +189,28 @@ int cx18_av_loadfw(struct cx18 *cx)
cx18_write_reg_expect(cx, v & 0xFFFFFBFF, CX18_AUDIO_ENABLE,
0, 0x400);
+ /* Toggle the AI1 MUX */
+ v = cx18_read_reg(cx, CX18_AUDIO_ENABLE);
+ u = v & CX18_AI1_MUX_MASK;
+ v &= ~CX18_AI1_MUX_MASK;
+ if (u == CX18_AI1_MUX_843_I2S || u == CX18_AI1_MUX_INVALID) {
+ /* Switch to I2S1 */
+ v |= CX18_AI1_MUX_I2S1;
+ cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE,
+ v, CX18_AI1_MUX_MASK);
+ /* Switch back to the A/V decoder core I2S output */
+ v = (v & ~CX18_AI1_MUX_MASK) | CX18_AI1_MUX_843_I2S;
+ } else {
+ /* Switch to the A/V decoder core I2S output */
+ v |= CX18_AI1_MUX_843_I2S;
+ cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE,
+ v, CX18_AI1_MUX_MASK);
+ /* Switch back to I2S1 or I2S2 */
+ v = (v & ~CX18_AI1_MUX_MASK) | u;
+ }
+ cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE,
+ v, CX18_AI1_MUX_MASK);
+
/* Enable WW auto audio standard detection */
v = cx18_av_read4(cx, CXADEC_STD_DET_CTL);
v |= 0xFF; /* Auto by default */
@@ -143,7 +219,5 @@ int cx18_av_loadfw(struct cx18 *cx)
cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, v, v, 0x3F00FFFF);
release_firmware(fw);
-
- CX18_INFO_DEV(sd, "loaded %s firmware (%d bytes)\n", FWFILE, size);
return 0;
}
diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c
index 82fc2f9d4021..8e35c3aed544 100644
--- a/drivers/media/video/cx18/cx18-controls.c
+++ b/drivers/media/video/cx18/cx18-controls.c
@@ -176,8 +176,10 @@ static int cx18_setup_vbi_fmt(struct cx18 *cx,
return -EBUSY;
if (fmt != V4L2_MPEG_STREAM_VBI_FMT_IVTV ||
- type != V4L2_MPEG_STREAM_TYPE_MPEG2_PS) {
- /* We don't do VBI insertion aside from IVTV format in a PS */
+ !(type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS ||
+ type == V4L2_MPEG_STREAM_TYPE_MPEG2_DVD ||
+ type == V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD)) {
+ /* Only IVTV fmt VBI insertion & only MPEG-2 PS type streams */
cx->vbi.insert_mpeg = V4L2_MPEG_STREAM_VBI_FMT_NONE;
CX18_DEBUG_INFO("disabled insertion of sliced VBI data into "
"the MPEG stream\n");
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index 49b1c3d7b1a8..f0006edc635d 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -30,6 +30,7 @@
#include "cx18-irq.h"
#include "cx18-gpio.h"
#include "cx18-firmware.h"
+#include "cx18-queue.h"
#include "cx18-streams.h"
#include "cx18-av-core.h"
#include "cx18-scb.h"
@@ -546,6 +547,40 @@ done:
cx->card_i2c = cx->card->i2c;
}
+static int __devinit cx18_create_in_workq(struct cx18 *cx)
+{
+ snprintf(cx->in_workq_name, sizeof(cx->in_workq_name), "%s-in",
+ cx->v4l2_dev.name);
+ cx->in_work_queue = create_singlethread_workqueue(cx->in_workq_name);
+ if (cx->in_work_queue == NULL) {
+ CX18_ERR("Unable to create incoming mailbox handler thread\n");
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static int __devinit cx18_create_out_workq(struct cx18 *cx)
+{
+ snprintf(cx->out_workq_name, sizeof(cx->out_workq_name), "%s-out",
+ cx->v4l2_dev.name);
+ cx->out_work_queue = create_workqueue(cx->out_workq_name);
+ if (cx->out_work_queue == NULL) {
+ CX18_ERR("Unable to create outgoing mailbox handler threads\n");
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static void __devinit cx18_init_in_work_orders(struct cx18 *cx)
+{
+ int i;
+ for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++) {
+ cx->in_work_order[i].cx = cx;
+ cx->in_work_order[i].str = cx->epu_debug_str;
+ INIT_WORK(&cx->in_work_order[i].work, cx18_in_work_handler);
+ }
+}
+
/* Precondition: the cx18 structure has been memset to 0. Only
the dev and instance fields have been filled in.
No assumptions on the card type may be made here (see cx18_init_struct2
@@ -553,7 +588,7 @@ done:
*/
static int __devinit cx18_init_struct1(struct cx18 *cx)
{
- int i;
+ int ret;
cx->base_addr = pci_resource_start(cx->pci_dev, 0);
@@ -562,18 +597,18 @@ static int __devinit cx18_init_struct1(struct cx18 *cx)
mutex_init(&cx->epu2apu_mb_lock);
mutex_init(&cx->epu2cpu_mb_lock);
- cx->work_queue = create_singlethread_workqueue(cx->v4l2_dev.name);
- if (cx->work_queue == NULL) {
- CX18_ERR("Unable to create work hander thread\n");
- return -ENOMEM;
- }
+ ret = cx18_create_out_workq(cx);
+ if (ret)
+ return ret;
- for (i = 0; i < CX18_MAX_EPU_WORK_ORDERS; i++) {
- cx->epu_work_order[i].cx = cx;
- cx->epu_work_order[i].str = cx->epu_debug_str;
- INIT_WORK(&cx->epu_work_order[i].work, cx18_epu_work_handler);
+ ret = cx18_create_in_workq(cx);
+ if (ret) {
+ destroy_workqueue(cx->out_work_queue);
+ return ret;
}
+ cx18_init_in_work_orders(cx);
+
/* start counting open_id at 1 */
cx->open_id = 1;
@@ -759,17 +794,17 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
retval = -ENODEV;
goto err;
}
- if (cx18_init_struct1(cx)) {
- retval = -ENOMEM;
+
+ retval = cx18_init_struct1(cx);
+ if (retval)
goto err;
- }
CX18_DEBUG_INFO("base addr: 0x%08x\n", cx->base_addr);
/* PCI Device Setup */
retval = cx18_setup_pci(cx, pci_dev, pci_id);
if (retval != 0)
- goto free_workqueue;
+ goto free_workqueues;
/* map io memory */
CX18_DEBUG_INFO("attempting ioremap at 0x%08x len 0x%08x\n",
@@ -943,8 +978,9 @@ free_map:
cx18_iounmap(cx);
free_mem:
release_mem_region(cx->base_addr, CX18_MEM_SIZE);
-free_workqueue:
- destroy_workqueue(cx->work_queue);
+free_workqueues:
+ destroy_workqueue(cx->in_work_queue);
+ destroy_workqueue(cx->out_work_queue);
err:
if (retval == 0)
retval = -ENODEV;
@@ -1053,11 +1089,19 @@ int cx18_init_on_first_open(struct cx18 *cx)
return 0;
}
-static void cx18_cancel_epu_work_orders(struct cx18 *cx)
+static void cx18_cancel_in_work_orders(struct cx18 *cx)
{
int i;
- for (i = 0; i < CX18_MAX_EPU_WORK_ORDERS; i++)
- cancel_work_sync(&cx->epu_work_order[i].work);
+ for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++)
+ cancel_work_sync(&cx->in_work_order[i].work);
+}
+
+static void cx18_cancel_out_work_orders(struct cx18 *cx)
+{
+ int i;
+ for (i = 0; i < CX18_MAX_STREAMS; i++)
+ if (&cx->streams[i].video_dev != NULL)
+ cancel_work_sync(&cx->streams[i].out_work_order);
}
static void cx18_remove(struct pci_dev *pci_dev)
@@ -1073,15 +1117,20 @@ static void cx18_remove(struct pci_dev *pci_dev)
if (atomic_read(&cx->tot_capturing) > 0)
cx18_stop_all_captures(cx);
- /* Interrupts */
+ /* Stop interrupts that cause incoming work to be queued */
cx18_sw1_irq_disable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
+
+ /* Incoming work can cause outgoing work, so clean up incoming first */
+ cx18_cancel_in_work_orders(cx);
+ cx18_cancel_out_work_orders(cx);
+
+ /* Stop ack interrupts that may have been needed for work to finish */
cx18_sw2_irq_disable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
cx18_halt_firmware(cx);
- cx18_cancel_epu_work_orders(cx);
-
- destroy_workqueue(cx->work_queue);
+ destroy_workqueue(cx->in_work_queue);
+ destroy_workqueue(cx->out_work_queue);
cx18_streams_cleanup(cx, 1);
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index ece4f281ef42..f89b82367963 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -254,6 +254,7 @@ struct cx18_options {
#define CX18_F_S_INTERNAL_USE 5 /* this stream is used internally (sliced VBI processing) */
#define CX18_F_S_STREAMOFF 7 /* signal end of stream EOS */
#define CX18_F_S_APPL_IO 8 /* this stream is used read/written by an application */
+#define CX18_F_S_STOPPING 9 /* telling the fw to stop capturing */
/* per-cx18, i_flags */
#define CX18_F_I_LOADED_FW 0 /* Loaded firmware 1st time */
@@ -285,6 +286,7 @@ struct cx18_queue {
struct list_head list;
atomic_t buffers;
u32 bytesused;
+ spinlock_t lock;
};
struct cx18_dvb {
@@ -305,7 +307,7 @@ struct cx18_scb; /* forward reference */
#define CX18_MAX_MDL_ACKS 2
-#define CX18_MAX_EPU_WORK_ORDERS (CX18_MAX_FW_MDLS_PER_STREAM + 7)
+#define CX18_MAX_IN_WORK_ORDERS (CX18_MAX_FW_MDLS_PER_STREAM + 7)
/* CPU_DE_RELEASE_MDL can burst CX18_MAX_FW_MDLS_PER_STREAM orders in a group */
#define CX18_F_EWO_MB_STALE_UPON_RECEIPT 0x1
@@ -313,7 +315,7 @@ struct cx18_scb; /* forward reference */
#define CX18_F_EWO_MB_STALE \
(CX18_F_EWO_MB_STALE_UPON_RECEIPT | CX18_F_EWO_MB_STALE_WHILE_PROC)
-struct cx18_epu_work_order {
+struct cx18_in_work_order {
struct work_struct work;
atomic_t pending;
struct cx18 *cx;
@@ -337,7 +339,6 @@ struct cx18_stream {
unsigned mdl_offset;
u32 id;
- struct mutex qlock; /* locks access to the queues */
unsigned long s_flags; /* status flags, see above */
int dma; /* can be PCI_DMA_TODEVICE,
PCI_DMA_FROMDEVICE or
@@ -353,6 +354,8 @@ struct cx18_stream {
struct cx18_queue q_busy; /* busy buffers - in use by firmware */
struct cx18_queue q_full; /* full buffers - data for user apps */
+ struct work_struct out_work_order;
+
/* DVB / Digital Transport */
struct cx18_dvb dvb;
};
@@ -568,10 +571,14 @@ struct cx18 {
u32 sw2_irq_mask;
u32 hw2_irq_mask;
- struct workqueue_struct *work_queue;
- struct cx18_epu_work_order epu_work_order[CX18_MAX_EPU_WORK_ORDERS];
+ struct workqueue_struct *in_work_queue;
+ char in_workq_name[11]; /* "cx18-NN-in" */
+ struct cx18_in_work_order in_work_order[CX18_MAX_IN_WORK_ORDERS];
char epu_debug_str[256]; /* CX18_EPU_DEBUG is rare: use shared space */
+ struct workqueue_struct *out_work_queue;
+ char out_workq_name[12]; /* "cx18-NN-out" */
+
/* i2c */
struct i2c_adapter i2c_adap[2];
struct i2c_algo_bit_data i2c_algo[2];
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c
index 3b86f57cd15a..e7285a1096f2 100644
--- a/drivers/media/video/cx18/cx18-dvb.c
+++ b/drivers/media/video/cx18/cx18-dvb.c
@@ -23,6 +23,7 @@
#include "cx18-version.h"
#include "cx18-dvb.h"
#include "cx18-io.h"
+#include "cx18-queue.h"
#include "cx18-streams.h"
#include "cx18-cards.h"
#include "s5h1409.h"
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
index b3889c0b2697..29969c18949c 100644
--- a/drivers/media/video/cx18/cx18-fileops.c
+++ b/drivers/media/video/cx18/cx18-fileops.c
@@ -265,8 +265,13 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
* an MPEG-2 Program Pack start code, and provide only
* up to that point to the user, so it's easy to insert VBI data
* the next time around.
+ *
+ * This will not work for an MPEG-2 TS and has only been
+ * verified by analysis to work for an MPEG-2 PS. Helen Buus
+ * pointed out this works for the CX23416 MPEG-2 DVD compatible
+ * stream, and research indicates both the MPEG 2 SVCD and DVD
+ * stream types use an MPEG-2 PS container.
*/
- /* FIXME - This only works for an MPEG-2 PS, not a TS */
/*
* An MPEG-2 Program Stream (PS) is a series of
* MPEG-2 Program Packs terminated by an
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c
index b9b7064a2be8..8591e4fc359f 100644
--- a/drivers/media/video/cx18/cx18-i2c.c
+++ b/drivers/media/video/cx18/cx18-i2c.c
@@ -211,7 +211,7 @@ static struct i2c_algo_bit_data cx18_i2c_algo_template = {
/* init + register i2c algo-bit adapter */
int init_cx18_i2c(struct cx18 *cx)
{
- int i;
+ int i, err;
CX18_DEBUG_I2C("i2c init\n");
for (i = 0; i < 2; i++) {
@@ -268,8 +268,18 @@ int init_cx18_i2c(struct cx18 *cx)
cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL,
core, reset, (u32) CX18_GPIO_RESET_I2C);
- return i2c_bit_add_bus(&cx->i2c_adap[0]) ||
- i2c_bit_add_bus(&cx->i2c_adap[1]);
+ err = i2c_bit_add_bus(&cx->i2c_adap[0]);
+ if (err)
+ goto err;
+ err = i2c_bit_add_bus(&cx->i2c_adap[1]);
+ if (err)
+ goto err_del_bus_0;
+ return 0;
+
+ err_del_bus_0:
+ i2c_del_adapter(&cx->i2c_adap[0]);
+ err:
+ return err;
}
void exit_cx18_i2c(struct cx18 *cx)
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c
index 2226e5791e99..afe46c3d4057 100644
--- a/drivers/media/video/cx18/cx18-mailbox.c
+++ b/drivers/media/video/cx18/cx18-mailbox.c
@@ -131,7 +131,7 @@ static void dump_mb(struct cx18 *cx, struct cx18_mailbox *mb, char *name)
* Functions that run in a work_queue work handling context
*/
-static void epu_dma_done(struct cx18 *cx, struct cx18_epu_work_order *order)
+static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order)
{
u32 handle, mdl_ack_count, id;
struct cx18_mailbox *mb;
@@ -191,29 +191,30 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_epu_work_order *order)
if (buf == NULL) {
CX18_WARN("Could not find buf %d for stream %s\n",
id, s->name);
- /* Put as many buffers as possible back into fw use */
- cx18_stream_load_fw_queue(s);
continue;
}
- if (s->type == CX18_ENC_STREAM_TYPE_TS && s->dvb.enabled) {
- CX18_DEBUG_HI_DMA("TS recv bytesused = %d\n",
- buf->bytesused);
- dvb_dmx_swfilter(&s->dvb.demux, buf->buf,
- buf->bytesused);
+ CX18_DEBUG_HI_DMA("%s recv bytesused = %d\n",
+ s->name, buf->bytesused);
+
+ if (s->type != CX18_ENC_STREAM_TYPE_TS)
+ cx18_enqueue(s, buf, &s->q_full);
+ else {
+ if (s->dvb.enabled)
+ dvb_dmx_swfilter(&s->dvb.demux, buf->buf,
+ buf->bytesused);
+ cx18_enqueue(s, buf, &s->q_free);
}
- /* Put as many buffers as possible back into fw use */
- cx18_stream_load_fw_queue(s);
- /* Put back TS buffer, since it was removed from all queues */
- if (s->type == CX18_ENC_STREAM_TYPE_TS)
- cx18_stream_put_buf_fw(s, buf);
}
+ /* Put as many buffers as possible back into fw use */
+ cx18_stream_load_fw_queue(s);
+
wake_up(&cx->dma_waitq);
if (s->id != -1)
wake_up(&s->waitq);
}
-static void epu_debug(struct cx18 *cx, struct cx18_epu_work_order *order)
+static void epu_debug(struct cx18 *cx, struct cx18_in_work_order *order)
{
char *p;
char *str = order->str;
@@ -224,7 +225,7 @@ static void epu_debug(struct cx18 *cx, struct cx18_epu_work_order *order)
CX18_INFO("FW version: %s\n", p - 1);
}
-static void epu_cmd(struct cx18 *cx, struct cx18_epu_work_order *order)
+static void epu_cmd(struct cx18 *cx, struct cx18_in_work_order *order)
{
switch (order->rpu) {
case CPU:
@@ -253,18 +254,18 @@ static void epu_cmd(struct cx18 *cx, struct cx18_epu_work_order *order)
}
static
-void free_epu_work_order(struct cx18 *cx, struct cx18_epu_work_order *order)
+void free_in_work_order(struct cx18 *cx, struct cx18_in_work_order *order)
{
atomic_set(&order->pending, 0);
}
-void cx18_epu_work_handler(struct work_struct *work)
+void cx18_in_work_handler(struct work_struct *work)
{
- struct cx18_epu_work_order *order =
- container_of(work, struct cx18_epu_work_order, work);
+ struct cx18_in_work_order *order =
+ container_of(work, struct cx18_in_work_order, work);
struct cx18 *cx = order->cx;
epu_cmd(cx, order);
- free_epu_work_order(cx, order);
+ free_in_work_order(cx, order);
}
@@ -272,7 +273,7 @@ void cx18_epu_work_handler(struct work_struct *work)
* Functions that run in an interrupt handling context
*/
-static void mb_ack_irq(struct cx18 *cx, struct cx18_epu_work_order *order)
+static void mb_ack_irq(struct cx18 *cx, struct cx18_in_work_order *order)
{
struct cx18_mailbox __iomem *ack_mb;
u32 ack_irq, req;
@@ -308,7 +309,7 @@ static void mb_ack_irq(struct cx18 *cx, struct cx18_epu_work_order *order)
return;
}
-static int epu_dma_done_irq(struct cx18 *cx, struct cx18_epu_work_order *order)
+static int epu_dma_done_irq(struct cx18 *cx, struct cx18_in_work_order *order)
{
u32 handle, mdl_ack_offset, mdl_ack_count;
struct cx18_mailbox *mb;
@@ -334,7 +335,7 @@ static int epu_dma_done_irq(struct cx18 *cx, struct cx18_epu_work_order *order)
}
static
-int epu_debug_irq(struct cx18 *cx, struct cx18_epu_work_order *order)
+int epu_debug_irq(struct cx18 *cx, struct cx18_in_work_order *order)
{
u32 str_offset;
char *str = order->str;
@@ -355,7 +356,7 @@ int epu_debug_irq(struct cx18 *cx, struct cx18_epu_work_order *order)
}
static inline
-int epu_cmd_irq(struct cx18 *cx, struct cx18_epu_work_order *order)
+int epu_cmd_irq(struct cx18 *cx, struct cx18_in_work_order *order)
{
int ret = -1;
@@ -387,12 +388,12 @@ int epu_cmd_irq(struct cx18 *cx, struct cx18_epu_work_order *order)
}
static inline
-struct cx18_epu_work_order *alloc_epu_work_order_irq(struct cx18 *cx)
+struct cx18_in_work_order *alloc_in_work_order_irq(struct cx18 *cx)
{
int i;
- struct cx18_epu_work_order *order = NULL;
+ struct cx18_in_work_order *order = NULL;
- for (i = 0; i < CX18_MAX_EPU_WORK_ORDERS; i++) {
+ for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++) {
/*
* We only need "pending" atomic to inspect its contents,
* and need not do a check and set because:
@@ -401,8 +402,8 @@ struct cx18_epu_work_order *alloc_epu_work_order_irq(struct cx18 *cx)
* 2. "pending" is only set here, and we're serialized because
* we're called in an IRQ handler context.
*/
- if (atomic_read(&cx->epu_work_order[i].pending) == 0) {
- order = &cx->epu_work_order[i];
+ if (atomic_read(&cx->in_work_order[i].pending) == 0) {
+ order = &cx->in_work_order[i];
atomic_set(&order->pending, 1);
break;
}
@@ -414,7 +415,7 @@ void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu)
{
struct cx18_mailbox __iomem *mb;
struct cx18_mailbox *order_mb;
- struct cx18_epu_work_order *order;
+ struct cx18_in_work_order *order;
int submit;
switch (rpu) {
@@ -428,7 +429,7 @@ void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu)
return;
}
- order = alloc_epu_work_order_irq(cx);
+ order = alloc_in_work_order_irq(cx);
if (order == NULL) {
CX18_WARN("Unable to find blank work order form to schedule "
"incoming mailbox command processing\n");
@@ -461,7 +462,7 @@ void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu)
*/
submit = epu_cmd_irq(cx, order);
if (submit > 0) {
- queue_work(cx->work_queue, &order->work);
+ queue_work(cx->in_work_queue, &order->work);
}
}
@@ -478,9 +479,10 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
u32 __iomem *xpu_state;
wait_queue_head_t *waitq;
struct mutex *mb_lock;
- long int timeout, ret;
+ unsigned long int t0, timeout, ret;
int i;
char argstr[MAX_MB_ARGUMENTS*11+1];
+ DEFINE_WAIT(w);
if (info == NULL) {
CX18_WARN("unknown cmd %x\n", cmd);
@@ -562,25 +564,49 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
CX18_DEBUG_HI_IRQ("sending interrupt SW1: %x to send %s\n",
irq, info->name);
+
+ /* So we don't miss the wakeup, prepare to wait before notifying fw */
+ prepare_to_wait(waitq, &w, TASK_UNINTERRUPTIBLE);
cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq);
- ret = wait_event_timeout(
- *waitq,
- cx18_readl(cx, &mb->ack) == cx18_readl(cx, &mb->request),
- timeout);
+ t0 = jiffies;
+ ack = cx18_readl(cx, &mb->ack);
+ if (ack != req) {
+ schedule_timeout(timeout);
+ ret = jiffies - t0;
+ ack = cx18_readl(cx, &mb->ack);
+ } else {
+ ret = jiffies - t0;
+ }
- if (ret == 0) {
- /* Timed out */
+ finish_wait(waitq, &w);
+
+ if (req != ack) {
mutex_unlock(mb_lock);
- CX18_DEBUG_WARN("sending %s timed out waiting %d msecs for RPU "
- "acknowledgement\n",
- info->name, jiffies_to_msecs(timeout));
+ if (ret >= timeout) {
+ /* Timed out */
+ CX18_DEBUG_WARN("sending %s timed out waiting %d msecs "
+ "for RPU acknowledgement\n",
+ info->name, jiffies_to_msecs(ret));
+ } else {
+ CX18_DEBUG_WARN("woken up before mailbox ack was ready "
+ "after submitting %s to RPU. only "
+ "waited %d msecs on req %u but awakened"
+ " with unmatched ack %u\n",
+ info->name,
+ jiffies_to_msecs(ret),
+ req, ack);
+ }
return -EINVAL;
}
- if (ret != timeout)
+ if (ret >= timeout)
+ CX18_DEBUG_WARN("failed to be awakened upon RPU acknowledgment "
+ "sending %s; timed out waiting %d msecs\n",
+ info->name, jiffies_to_msecs(ret));
+ else
CX18_DEBUG_HI_API("waited %u msecs for %s to be acked\n",
- jiffies_to_msecs(timeout-ret), info->name);
+ jiffies_to_msecs(ret), info->name);
/* Collect data returned by the XPU */
for (i = 0; i < MAX_MB_ARGUMENTS; i++)
diff --git a/drivers/media/video/cx18/cx18-mailbox.h b/drivers/media/video/cx18/cx18-mailbox.h
index ce2b6686aa00..e23aaac5b280 100644
--- a/drivers/media/video/cx18/cx18-mailbox.h
+++ b/drivers/media/video/cx18/cx18-mailbox.h
@@ -95,6 +95,6 @@ int cx18_api_func(void *priv, u32 cmd, int in, int out,
void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu);
-void cx18_epu_work_handler(struct work_struct *work);
+void cx18_in_work_handler(struct work_struct *work);
#endif
diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c
index 3046b8e74345..fa1ed7897d97 100644
--- a/drivers/media/video/cx18/cx18-queue.c
+++ b/drivers/media/video/cx18/cx18-queue.c
@@ -23,8 +23,8 @@
*/
#include "cx18-driver.h"
-#include "cx18-streams.h"
#include "cx18-queue.h"
+#include "cx18-streams.h"
#include "cx18-scb.h"
void cx18_buf_swap(struct cx18_buffer *buf)
@@ -53,13 +53,13 @@ struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf,
buf->skipped = 0;
}
- mutex_lock(&s->qlock);
-
/* q_busy is restricted to a max buffer count imposed by firmware */
if (q == &s->q_busy &&
atomic_read(&q->buffers) >= CX18_MAX_FW_MDLS_PER_STREAM)
q = &s->q_free;
+ spin_lock(&q->lock);
+
if (to_front)
list_add(&buf->list, &q->list); /* LIFO */
else
@@ -67,7 +67,7 @@ struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf,
q->bytesused += buf->bytesused - buf->readpos;
atomic_inc(&q->buffers);
- mutex_unlock(&s->qlock);
+ spin_unlock(&q->lock);
return q;
}
@@ -75,7 +75,7 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q)
{
struct cx18_buffer *buf = NULL;
- mutex_lock(&s->qlock);
+ spin_lock(&q->lock);
if (!list_empty(&q->list)) {
buf = list_first_entry(&q->list, struct cx18_buffer, list);
list_del_init(&buf->list);
@@ -83,7 +83,7 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q)
buf->skipped = 0;
atomic_dec(&q->buffers);
}
- mutex_unlock(&s->qlock);
+ spin_unlock(&q->lock);
return buf;
}
@@ -94,9 +94,23 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id,
struct cx18_buffer *buf;
struct cx18_buffer *tmp;
struct cx18_buffer *ret = NULL;
-
- mutex_lock(&s->qlock);
+ LIST_HEAD(sweep_up);
+
+ /*
+ * We don't have to acquire multiple q locks here, because we are
+ * serialized by the single threaded work handler.
+ * Buffers from the firmware will thus remain in order as
+ * they are moved from q_busy to q_full or to the dvb ring buffer.
+ */
+ spin_lock(&s->q_busy.lock);
list_for_each_entry_safe(buf, tmp, &s->q_busy.list, list) {
+ /*
+ * We should find what the firmware told us is done,
+ * right at the front of the queue. If we don't, we likely have
+ * missed a buffer done message from the firmware.
+ * Once we skip a buffer repeatedly, relative to the size of
+ * q_busy, we have high confidence we've missed it.
+ */
if (buf->id != id) {
buf->skipped++;
if (buf->skipped >= atomic_read(&s->q_busy.buffers)-1) {
@@ -105,38 +119,41 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id,
"times - it must have dropped out of "
"rotation\n", s->name, buf->id,
buf->skipped);
- /* move it to q_free */
- list_move_tail(&buf->list, &s->q_free.list);
- buf->bytesused = buf->readpos = buf->b_flags =
- buf->skipped = 0;
+ /* Sweep it up to put it back into rotation */
+ list_move_tail(&buf->list, &sweep_up);
atomic_dec(&s->q_busy.buffers);
- atomic_inc(&s->q_free.buffers);
}
continue;
}
-
- buf->bytesused = bytesused;
- /* Sync the buffer before we release the qlock */
- cx18_buf_sync_for_cpu(s, buf);
- if (s->type == CX18_ENC_STREAM_TYPE_TS) {
- /*
- * TS doesn't use q_full. As we pull the buffer off of
- * the queue here, the caller will have to put it back.
- */
- list_del_init(&buf->list);
- } else {
- /* Move buffer from q_busy to q_full */
- list_move_tail(&buf->list, &s->q_full.list);
- set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags);
- s->q_full.bytesused += buf->bytesused;
- atomic_inc(&s->q_full.buffers);
- }
+ /*
+ * We pull the desired buffer off of the queue here. Something
+ * will have to put it back on a queue later.
+ */
+ list_del_init(&buf->list);
atomic_dec(&s->q_busy.buffers);
-
ret = buf;
break;
}
- mutex_unlock(&s->qlock);
+ spin_unlock(&s->q_busy.lock);
+
+ /*
+ * We found the buffer for which we were looking. Get it ready for
+ * the caller to put on q_full or in the dvb ring buffer.
+ */
+ if (ret != NULL) {
+ ret->bytesused = bytesused;
+ ret->skipped = 0;
+ /* readpos and b_flags were 0'ed when the buf went on q_busy */
+ cx18_buf_sync_for_cpu(s, ret);
+ if (s->type != CX18_ENC_STREAM_TYPE_TS)
+ set_bit(CX18_F_B_NEED_BUF_SWAP, &ret->b_flags);
+ }
+
+ /* Put any buffers the firmware is ignoring back into normal rotation */
+ list_for_each_entry_safe(buf, tmp, &sweep_up, list) {
+ list_del_init(&buf->list);
+ cx18_enqueue(s, buf, &s->q_free);
+ }
return ret;
}
@@ -148,7 +165,7 @@ static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q)
if (q == &s->q_free)
return;
- mutex_lock(&s->qlock);
+ spin_lock(&q->lock);
while (!list_empty(&q->list)) {
buf = list_first_entry(&q->list, struct cx18_buffer, list);
list_move_tail(&buf->list, &s->q_free.list);
@@ -156,7 +173,7 @@ static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q)
atomic_inc(&s->q_free.buffers);
}
cx18_queue_init(q);
- mutex_unlock(&s->qlock);
+ spin_unlock(&q->lock);
}
void cx18_flush_queues(struct cx18_stream *s)
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index 0932b76b2373..41a1b2618aac 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -116,12 +116,16 @@ static void cx18_stream_init(struct cx18 *cx, int type)
s->buffers = cx->stream_buffers[type];
s->buf_size = cx->stream_buf_size[type];
- mutex_init(&s->qlock);
init_waitqueue_head(&s->waitq);
s->id = -1;
+ spin_lock_init(&s->q_free.lock);
cx18_queue_init(&s->q_free);
+ spin_lock_init(&s->q_busy.lock);
cx18_queue_init(&s->q_busy);
+ spin_lock_init(&s->q_full.lock);
cx18_queue_init(&s->q_full);
+
+ INIT_WORK(&s->out_work_order, cx18_out_work_handler);
}
static int cx18_prep_dev(struct cx18 *cx, int type)
@@ -431,14 +435,16 @@ static void cx18_vbi_setup(struct cx18_stream *s)
cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data);
}
-struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s,
- struct cx18_buffer *buf)
+static
+struct cx18_queue *_cx18_stream_put_buf_fw(struct cx18_stream *s,
+ struct cx18_buffer *buf)
{
struct cx18 *cx = s->cx;
struct cx18_queue *q;
/* Don't give it to the firmware, if we're not running a capture */
if (s->handle == CX18_INVALID_TASK_HANDLE ||
+ test_bit(CX18_F_S_STOPPING, &s->s_flags) ||
!test_bit(CX18_F_S_STREAMING, &s->s_flags))
return cx18_enqueue(s, buf, &s->q_free);
@@ -453,7 +459,8 @@ struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s,
return q;
}
-void cx18_stream_load_fw_queue(struct cx18_stream *s)
+static
+void _cx18_stream_load_fw_queue(struct cx18_stream *s)
{
struct cx18_queue *q;
struct cx18_buffer *buf;
@@ -467,11 +474,19 @@ void cx18_stream_load_fw_queue(struct cx18_stream *s)
buf = cx18_dequeue(s, &s->q_free);
if (buf == NULL)
break;
- q = cx18_stream_put_buf_fw(s, buf);
+ q = _cx18_stream_put_buf_fw(s, buf);
} while (atomic_read(&s->q_busy.buffers) < CX18_MAX_FW_MDLS_PER_STREAM
&& q == &s->q_busy);
}
+void cx18_out_work_handler(struct work_struct *work)
+{
+ struct cx18_stream *s =
+ container_of(work, struct cx18_stream, out_work_order);
+
+ _cx18_stream_load_fw_queue(s);
+}
+
int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
{
u32 data[MAX_MB_ARGUMENTS];
@@ -600,19 +615,20 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
/* Init all the cpu_mdls for this stream */
cx18_flush_queues(s);
- mutex_lock(&s->qlock);
+ spin_lock(&s->q_free.lock);
list_for_each_entry(buf, &s->q_free.list, list) {
cx18_writel(cx, buf->dma_handle,
&cx->scb->cpu_mdl[buf->id].paddr);
cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length);
}
- mutex_unlock(&s->qlock);
- cx18_stream_load_fw_queue(s);
+ spin_unlock(&s->q_free.lock);
+ _cx18_stream_load_fw_queue(s);
/* begin_capture */
if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) {
CX18_DEBUG_WARN("Error starting capture!\n");
/* Ensure we're really not capturing before releasing MDLs */
+ set_bit(CX18_F_S_STOPPING, &s->s_flags);
if (s->type == CX18_ENC_STREAM_TYPE_MPG)
cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, 1);
else
@@ -622,6 +638,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle);
cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
s->handle = CX18_INVALID_TASK_HANDLE;
+ clear_bit(CX18_F_S_STOPPING, &s->s_flags);
if (atomic_read(&cx->tot_capturing) == 0) {
set_bit(CX18_F_I_EOS, &cx->i_flags);
cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK);
@@ -666,6 +683,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
if (atomic_read(&cx->tot_capturing) == 0)
return 0;
+ set_bit(CX18_F_S_STOPPING, &s->s_flags);
if (s->type == CX18_ENC_STREAM_TYPE_MPG)
cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, !gop_end);
else
@@ -689,6 +707,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
s->handle = CX18_INVALID_TASK_HANDLE;
+ clear_bit(CX18_F_S_STOPPING, &s->s_flags);
if (atomic_read(&cx->tot_capturing) > 0)
return 0;
diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h
index 420e0a172945..1afc3fd9d822 100644
--- a/drivers/media/video/cx18/cx18-streams.h
+++ b/drivers/media/video/cx18/cx18-streams.h
@@ -28,10 +28,24 @@ int cx18_streams_setup(struct cx18 *cx);
int cx18_streams_register(struct cx18 *cx);
void cx18_streams_cleanup(struct cx18 *cx, int unregister);
+/* Related to submission of buffers to firmware */
+static inline void cx18_stream_load_fw_queue(struct cx18_stream *s)
+{
+ struct cx18 *cx = s->cx;
+ queue_work(cx->out_work_queue, &s->out_work_order);
+}
+
+static inline void cx18_stream_put_buf_fw(struct cx18_stream *s,
+ struct cx18_buffer *buf)
+{
+ /* Put buf on q_free; the out work handler will move buf(s) to q_busy */
+ cx18_enqueue(s, buf, &s->q_free);
+ cx18_stream_load_fw_queue(s);
+}
+
+void cx18_out_work_handler(struct work_struct *work);
+
/* Capture related */
-void cx18_stream_load_fw_queue(struct cx18_stream *s);
-struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s,
- struct cx18_buffer *buf);
int cx18_start_v4l2_encode_stream(struct cx18_stream *s);
int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end);
diff --git a/drivers/media/video/cx18/cx18-version.h b/drivers/media/video/cx18/cx18-version.h
index bd9bd44da791..45494b094e7f 100644
--- a/drivers/media/video/cx18/cx18-version.h
+++ b/drivers/media/video/cx18/cx18-version.h
@@ -24,7 +24,7 @@
#define CX18_DRIVER_NAME "cx18"
#define CX18_DRIVER_VERSION_MAJOR 1
-#define CX18_DRIVER_VERSION_MINOR 1
+#define CX18_DRIVER_VERSION_MINOR 2
#define CX18_DRIVER_VERSION_PATCHLEVEL 0
#define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL)
diff --git a/drivers/media/video/cx231xx/Kconfig b/drivers/media/video/cx231xx/Kconfig
index 91156546a07a..477d4ab5e9ac 100644
--- a/drivers/media/video/cx231xx/Kconfig
+++ b/drivers/media/video/cx231xx/Kconfig
@@ -1,12 +1,11 @@
config VIDEO_CX231XX
- tristate "Conexant cx231xx USB video capture support"
- depends on VIDEO_DEV && I2C && INPUT
- select VIDEO_TUNER
- select VIDEO_TVEEPROM
- select VIDEO_IR
- select VIDEOBUF_VMALLOC
- select VIDEO_CX25840
- select VIDEO_CX231XX_ALSA
+ tristate "Conexant cx231xx USB video capture support"
+ depends on VIDEO_DEV && I2C && INPUT
+ select VIDEO_TUNER
+ select VIDEO_TVEEPROM
+ select VIDEO_IR
+ select VIDEOBUF_VMALLOC
+ select VIDEO_CX25840
---help---
This is a video4linux driver for Conexant 231xx USB based TV cards.
@@ -15,21 +14,22 @@ config VIDEO_CX231XX
module will be called cx231xx
config VIDEO_CX231XX_ALSA
- tristate "Conexant Cx231xx ALSA audio module"
- depends on VIDEO_CX231XX && SND
- select SND_PCM
+ tristate "Conexant Cx231xx ALSA audio module"
+ depends on VIDEO_CX231XX && SND
+ select SND_PCM
- ---help---
- This is an ALSA driver for Cx231xx USB based TV cards.
+ ---help---
+ This is an ALSA driver for Cx231xx USB based TV cards.
- To compile this driver as a module, choose M here: the
- module will be called cx231xx-alsa
+ To compile this driver as a module, choose M here: the
+ module will be called cx231xx-alsa
config VIDEO_CX231XX_DVB
- tristate "DVB/ATSC Support for Cx231xx based TV cards"
- depends on VIDEO_CX231XX && DVB_CORE
- select VIDEOBUF_DVB
- select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE
- ---help---
- This adds support for DVB cards based on the
- Conexant cx231xx chips.
+ tristate "DVB/ATSC Support for Cx231xx based TV cards"
+ depends on VIDEO_CX231XX && DVB_CORE
+ select VIDEOBUF_DVB
+ select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE
+
+ ---help---
+ This adds support for DVB cards based on the
+ Conexant cx231xx chips.
diff --git a/drivers/media/video/cx231xx/cx231xx-avcore.c b/drivers/media/video/cx231xx/cx231xx-avcore.c
index 1be3881be991..6a9464079b4c 100644
--- a/drivers/media/video/cx231xx/cx231xx-avcore.c
+++ b/drivers/media/video/cx231xx/cx231xx-avcore.c
@@ -29,7 +29,6 @@
#include <linux/bitmap.h>
#include <linux/usb.h>
#include <linux/i2c.h>
-#include <linux/version.h>
#include <linux/mm.h>
#include <linux/mutex.h>
diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c
index c8a32b1b5381..63d2239fd324 100644
--- a/drivers/media/video/cx231xx/cx231xx-cards.c
+++ b/drivers/media/video/cx231xx/cx231xx-cards.c
@@ -281,12 +281,12 @@ static void cx231xx_config_tuner(struct cx231xx *dev)
}
/* ----------------------------------------------------------------------- */
-void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir)
+void cx231xx_register_i2c_ir(struct cx231xx *dev)
{
- if (disable_ir) {
- ir->get_key = NULL;
+ if (disable_ir)
return;
- }
+
+ /* REVISIT: instantiate IR device */
/* detect & configure */
switch (dev->model) {
diff --git a/drivers/media/video/cx231xx/cx231xx-i2c.c b/drivers/media/video/cx231xx/cx231xx-i2c.c
index b4a03d813e00..33219dc4d649 100644
--- a/drivers/media/video/cx231xx/cx231xx-i2c.c
+++ b/drivers/media/video/cx231xx/cx231xx-i2c.c
@@ -424,34 +424,6 @@ static u32 functionality(struct i2c_adapter *adap)
return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
}
-/*
- * attach_inform()
- * gets called when a device attaches to the i2c bus
- * does some basic configuration
- */
-static int attach_inform(struct i2c_client *client)
-{
- struct cx231xx_i2c *bus = i2c_get_adapdata(client->adapter);
- struct cx231xx *dev = bus->dev;
-
- switch (client->addr << 1) {
- case 0x8e:
- {
- struct IR_i2c *ir = i2c_get_clientdata(client);
- dprintk1(1, "attach_inform: IR detected (%s).\n",
- ir->phys);
- cx231xx_set_ir(dev, ir);
- break;
- }
- break;
-
- default:
- break;
- }
-
- return 0;
-}
-
static struct i2c_algorithm cx231xx_algo = {
.master_xfer = cx231xx_i2c_xfer,
.functionality = functionality,
@@ -462,7 +434,6 @@ static struct i2c_adapter cx231xx_adap_template = {
.name = "cx231xx",
.id = I2C_HW_B_CX231XX,
.algo = &cx231xx_algo,
- .client_register = attach_inform,
};
static struct i2c_client cx231xx_client_template = {
@@ -537,6 +508,9 @@ int cx231xx_i2c_register(struct cx231xx_i2c *bus)
if (0 == bus->i2c_rc) {
if (i2c_scan)
cx231xx_do_i2c_scan(dev, &bus->i2c_client);
+
+ /* Instantiate the IR receiver device, if present */
+ cx231xx_register_i2c_ir(dev);
} else
cx231xx_warn("%s: i2c bus %d register FAILED\n",
dev->name, bus->nr);
diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c
index 97e304c3c799..48f22fa38e6c 100644
--- a/drivers/media/video/cx231xx/cx231xx-input.c
+++ b/drivers/media/video/cx231xx/cx231xx-input.c
@@ -36,7 +36,7 @@ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
#define i2cdprintk(fmt, arg...) \
if (ir_debug) { \
- printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg); \
+ printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
}
#define dprintk(fmt, arg...) \
diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.c b/drivers/media/video/cx231xx/cx231xx-vbi.c
index 94180526909c..e97b8023a655 100644
--- a/drivers/media/video/cx231xx/cx231xx-vbi.c
+++ b/drivers/media/video/cx231xx/cx231xx-vbi.c
@@ -26,7 +26,6 @@
#include <linux/bitmap.h>
#include <linux/usb.h>
#include <linux/i2c.h>
-#include <linux/version.h>
#include <linux/mm.h>
#include <linux/mutex.h>
diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h
index aa4a23ef491a..e38eb2d425f7 100644
--- a/drivers/media/video/cx231xx/cx231xx.h
+++ b/drivers/media/video/cx231xx/cx231xx.h
@@ -738,7 +738,7 @@ extern void cx231xx_card_setup(struct cx231xx *dev);
extern struct cx231xx_board cx231xx_boards[];
extern struct usb_device_id cx231xx_id_table[];
extern const unsigned int cx231xx_bcount;
-void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir);
+void cx231xx_register_i2c_ir(struct cx231xx *dev);
int cx231xx_tuner_callback(void *ptr, int component, int command, int arg);
/* Provided by cx231xx-input.c */
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
index a3c0565be1a9..6d6293f7d428 100644
--- a/drivers/media/video/cx23885/cx23885-cards.c
+++ b/drivers/media/video/cx23885/cx23885-cards.c
@@ -441,9 +441,9 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg)
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
/* Two identical tuners on two different i2c buses,
* we need to reset the correct gpio. */
- if (port->nr == 0)
+ if (port->nr == 1)
bitmask = 0x01;
- else if (port->nr == 1)
+ else if (port->nr == 2)
bitmask = 0x04;
break;
}
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
index beda42925ce7..9e4d37eb918e 100644
--- a/drivers/media/video/cx23885/cx23885-core.c
+++ b/drivers/media/video/cx23885/cx23885-core.c
@@ -1700,9 +1700,13 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
}
if (cx23885_boards[dev->board].cimax > 0 &&
- ((pci_status & PCI_MSK_GPIO0) || (pci_status & PCI_MSK_GPIO1)))
- /* handled += cx23885_irq_gpio(dev, pci_status); */
- handled += netup_ci_slot_status(dev, pci_status);
+ ((pci_status & PCI_MSK_GPIO0) ||
+ (pci_status & PCI_MSK_GPIO1))) {
+
+ if (cx23885_boards[dev->board].cimax > 0)
+ handled += netup_ci_slot_status(dev, pci_status);
+
+ }
if (ts1_status) {
if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c
index f48454ab3900..07b76053a050 100644
--- a/drivers/media/video/cx23885/cx23885-dvb.c
+++ b/drivers/media/video/cx23885/cx23885-dvb.c
@@ -122,7 +122,9 @@ static struct tda10048_config hauppauge_hvr1200_config = {
.demod_address = 0x10 >> 1,
.output_mode = TDA10048_SERIAL_OUTPUT,
.fwbulkwritelen = TDA10048_BULKWRITE_200,
- .inversion = TDA10048_INVERSION_ON
+ .inversion = TDA10048_INVERSION_ON,
+ .if_freq_khz = TDA10048_IF_4300,
+ .clk_freq_khz = TDA10048_CLK_16000,
};
static struct s5h1409_config hauppauge_ezqam_config = {
@@ -314,6 +316,7 @@ static struct zl10353_config dvico_fusionhdtv_xc3028 = {
.demod_address = 0x0f,
.if2 = 45600,
.no_tuner = 1,
+ .disable_i2c_gate_ctrl = 1,
};
static struct stv0900_config netup_stv0900_config = {
@@ -471,7 +474,7 @@ static int dvb_register(struct cx23885_tsport *port)
static struct xc2028_ctrl ctl = {
.fname = XC2028_DEFAULT_FIRMWARE,
.max_len = 64,
- .scode_table = XC3028_FE_OREN538,
+ .demod = XC3028_FE_OREN538,
};
fe = dvb_attach(xc2028_attach,
diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c
index 3421bd12056a..384dec34134f 100644
--- a/drivers/media/video/cx23885/cx23885-i2c.c
+++ b/drivers/media/video/cx23885/cx23885-i2c.c
@@ -357,6 +357,18 @@ int cx23885_i2c_register(struct cx23885_i2c *bus)
printk(KERN_WARNING "%s: i2c bus %d register FAILED\n",
dev->name, bus->nr);
+ /* Instantiate the IR receiver device, if present */
+ if (0 == bus->i2c_rc) {
+ struct i2c_board_info info;
+ const unsigned short addr_list[] = {
+ 0x6b, I2C_CLIENT_END
+ };
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+ i2c_new_probed_device(&bus->i2c_adap, &info, addr_list);
+ }
+
return bus->i2c_rc;
}
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
index b06b1275a9ec..5b7e26761f0a 100644
--- a/drivers/media/video/cx88/Makefile
+++ b/drivers/media/video/cx88/Makefile
@@ -1,5 +1,5 @@
cx88xx-objs := cx88-cards.o cx88-core.o cx88-i2c.o cx88-tvaudio.o \
- cx88-input.o
+ cx88-dsp.o cx88-input.o
cx8800-objs := cx88-video.o cx88-vbi.o
cx8802-objs := cx88-mpeg.o
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index 6bbbfc66bb4b..1039757e2c4e 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -1969,6 +1969,13 @@ static const struct cx88_board cx88_boards[] = {
},
.mpeg = CX88_MPEG_DVB,
},
+ [CX88_BOARD_HAUPPAUGE_IRONLY] = {
+ .name = "Hauppauge WinTV-IR Only",
+ .tuner_type = UNSET,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ },
};
/* ------------------------------------------------------------------ */
@@ -2382,6 +2389,10 @@ static const struct cx88_subid cx88_subids[] = {
.subvendor = 0x153b,
.subdevice = 0x1177,
.card = CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII,
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0x9290,
+ .card = CX88_BOARD_HAUPPAUGE_IRONLY,
},
};
@@ -2448,6 +2459,7 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
case 90500: /* Nova-T-PCI (oem) */
case 90501: /* Nova-T-PCI (oem/IR) */
case 92000: /* Nova-SE2 (OEM, No Video or IR) */
+ case 92900: /* WinTV-IROnly (No analog or digital Video inputs) */
case 94009: /* WinTV-HVR1100 (Video and IR Retail) */
case 94501: /* WinTV-HVR1100 (Video and IR OEM) */
case 96009: /* WinTV-HVR1300 (PAL Video, MPEG Video and IR RX) */
@@ -2907,6 +2919,7 @@ static void cx88_card_setup(struct cx88_core *core)
case CX88_BOARD_HAUPPAUGE_HVR1300:
case CX88_BOARD_HAUPPAUGE_HVR4000:
case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
+ case CX88_BOARD_HAUPPAUGE_IRONLY:
if (0 == core->i2c_rc)
hauppauge_eeprom(core, eeprom);
break;
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index 0e149b22bd19..a3548c7f9dbb 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -231,7 +231,7 @@ cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
* can use the whole SDRAM for the DMA fifos. To simplify things, we
* use a static memory layout. That surely will waste memory in case
* we don't use all DMA channels at the same time (which will be the
- * case most of the time). But that still gives us enougth FIFO space
+ * case most of the time). But that still gives us enough FIFO space
* to be able to deal with insane long pci latencies ...
*
* FIFO space allocations:
@@ -241,6 +241,7 @@ cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
* channel 24 (vbi) - 4.0k
* channels 25+26 (audio) - 4.0k
* channel 28 (mpeg) - 4.0k
+ * channel 27 (audio rds)- 3.0k
* TOTAL = 29.0k
*
* Every channel has 160 bytes control data (64 bytes instruction
@@ -337,6 +338,18 @@ struct sram_channel cx88_sram_channels[] = {
.cnt1_reg = MO_DMA28_CNT1,
.cnt2_reg = MO_DMA28_CNT2,
},
+ [SRAM_CH27] = {
+ .name = "audio rds",
+ .cmds_start = 0x1801C0,
+ .ctrl_start = 0x180860,
+ .cdt = 0x180860 + 64,
+ .fifo_start = 0x187400,
+ .fifo_size = 0x000C00,
+ .ptr1_reg = MO_DMA27_PTR1,
+ .ptr2_reg = MO_DMA27_PTR2,
+ .cnt1_reg = MO_DMA27_CNT1,
+ .cnt2_reg = MO_DMA27_CNT2,
+ },
};
int cx88_sram_channel_setup(struct cx88_core *core,
@@ -598,6 +611,7 @@ int cx88_reset(struct cx88_core *core)
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0);
+ cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27], 128, 0);
/* misc init ... */
cx_write(MO_INPUT_FORMAT, ((1 << 13) | // agc enable
@@ -796,6 +810,8 @@ int cx88_start_audio_dma(struct cx88_core *core)
/* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
+ int rds_bpl = cx88_sram_channels[SRAM_CH27].fifo_size/AUD_RDS_LINES;
+
/* If downstream RISC is enabled, bail out; ALSA is managing DMA */
if (cx_read(MO_AUD_DMACNTRL) & 0x10)
return 0;
@@ -803,12 +819,14 @@ int cx88_start_audio_dma(struct cx88_core *core)
/* setup fifo + format */
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
+ cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27],
+ rds_bpl, 0);
cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */
- cx_write(MO_AUDR_LNGTH, bpl); /* fifo bpl size */
+ cx_write(MO_AUDR_LNGTH, rds_bpl); /* fifo bpl size */
- /* start dma */
- cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */
+ /* enable Up, Down and Audio RDS fifo */
+ cx_write(MO_AUD_DMACNTRL, 0x0007);
return 0;
}
diff --git a/drivers/media/video/cx88/cx88-dsp.c b/drivers/media/video/cx88/cx88-dsp.c
new file mode 100644
index 000000000000..3e5eaf3fe2a6
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-dsp.c
@@ -0,0 +1,312 @@
+/*
+ *
+ * Stereo and SAP detection for cx88
+ *
+ * Copyright (c) 2009 Marton Balint <cus@fazekas.hu>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <asm/div64.h>
+
+#include "cx88.h"
+#include "cx88-reg.h"
+
+#define INT_PI ((s32)(3.141592653589 * 32768.0))
+
+#define compat_remainder(a, b) \
+ ((float)(((s32)((a)*100))%((s32)((b)*100)))/100.0)
+
+#define baseband_freq(carrier, srate, tone) ((s32)( \
+ (compat_remainder(carrier + tone, srate)) / srate * 2 * INT_PI))
+
+/* We calculate the baseband frequencies of the carrier and the pilot tones
+ * based on the the sampling rate of the audio rds fifo. */
+
+#define FREQ_A2_CARRIER baseband_freq(54687.5, 2689.36, 0.0)
+#define FREQ_A2_DUAL baseband_freq(54687.5, 2689.36, 274.1)
+#define FREQ_A2_STEREO baseband_freq(54687.5, 2689.36, 117.5)
+
+/* The frequencies below are from the reference driver. They probably need
+ * further adjustments, because they are not tested at all. You may even need
+ * to play a bit with the registers of the chip to select the proper signal
+ * for the input of the audio rds fifo, and measure it's sampling rate to
+ * calculate the proper baseband frequencies... */
+
+#define FREQ_A2M_CARRIER ((s32)(2.114516 * 32768.0))
+#define FREQ_A2M_DUAL ((s32)(2.754916 * 32768.0))
+#define FREQ_A2M_STEREO ((s32)(2.462326 * 32768.0))
+
+#define FREQ_EIAJ_CARRIER ((s32)(1.963495 * 32768.0)) /* 5pi/8 */
+#define FREQ_EIAJ_DUAL ((s32)(2.562118 * 32768.0))
+#define FREQ_EIAJ_STEREO ((s32)(2.601053 * 32768.0))
+
+#define FREQ_BTSC_DUAL ((s32)(1.963495 * 32768.0)) /* 5pi/8 */
+#define FREQ_BTSC_DUAL_REF ((s32)(1.374446 * 32768.0)) /* 7pi/16 */
+
+#define FREQ_BTSC_SAP ((s32)(2.471532 * 32768.0))
+#define FREQ_BTSC_SAP_REF ((s32)(1.730072 * 32768.0))
+
+/* The spectrum of the signal should be empty between these frequencies. */
+#define FREQ_NOISE_START ((s32)(0.100000 * 32768.0))
+#define FREQ_NOISE_END ((s32)(1.200000 * 32768.0))
+
+static unsigned int dsp_debug;
+module_param(dsp_debug, int, 0644);
+MODULE_PARM_DESC(dsp_debug, "enable audio dsp debug messages");
+
+#define dprintk(level, fmt, arg...) if (dsp_debug >= level) \
+ printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
+
+static s32 int_cos(u32 x)
+{
+ u32 t2, t4, t6, t8;
+ s32 ret;
+ u16 period = x / INT_PI;
+ if (period % 2)
+ return -int_cos(x - INT_PI);
+ x = x % INT_PI;
+ if (x > INT_PI/2)
+ return -int_cos(INT_PI/2 - (x % (INT_PI/2)));
+ /* Now x is between 0 and INT_PI/2.
+ * To calculate cos(x) we use it's Taylor polinom. */
+ t2 = x*x/32768/2;
+ t4 = t2*x/32768*x/32768/3/4;
+ t6 = t4*x/32768*x/32768/5/6;
+ t8 = t6*x/32768*x/32768/7/8;
+ ret = 32768-t2+t4-t6+t8;
+ return ret;
+}
+
+static u32 int_goertzel(s16 x[], u32 N, u32 freq)
+{
+ /* We use the Goertzel algorithm to determine the power of the
+ * given frequency in the signal */
+ s32 s_prev = 0;
+ s32 s_prev2 = 0;
+ s32 coeff = 2*int_cos(freq);
+ u32 i;
+
+ u64 tmp;
+ u32 divisor;
+
+ for (i = 0; i < N; i++) {
+ s32 s = x[i] + ((s64)coeff*s_prev/32768) - s_prev2;
+ s_prev2 = s_prev;
+ s_prev = s;
+ }
+
+ tmp = (s64)s_prev2 * s_prev2 + (s64)s_prev * s_prev -
+ (s64)coeff * s_prev2 * s_prev / 32768;
+
+ /* XXX: N must be low enough so that N*N fits in s32.
+ * Else we need two divisions. */
+ divisor = N * N;
+ do_div(tmp, divisor);
+
+ return (u32) tmp;
+}
+
+static u32 freq_magnitude(s16 x[], u32 N, u32 freq)
+{
+ u32 sum = int_goertzel(x, N, freq);
+ return (u32)int_sqrt(sum);
+}
+
+static u32 noise_magnitude(s16 x[], u32 N, u32 freq_start, u32 freq_end)
+{
+ int i;
+ u32 sum = 0;
+ u32 freq_step;
+ int samples = 5;
+
+ if (N > 192) {
+ /* The last 192 samples are enough for noise detection */
+ x += (N-192);
+ N = 192;
+ }
+
+ freq_step = (freq_end - freq_start) / (samples - 1);
+
+ for (i = 0; i < samples; i++) {
+ sum += int_goertzel(x, N, freq_start);
+ freq_start += freq_step;
+ }
+
+ return (u32)int_sqrt(sum / samples);
+}
+
+static s32 detect_a2_a2m_eiaj(struct cx88_core *core, s16 x[], u32 N)
+{
+ s32 carrier, stereo, dual, noise;
+ s32 carrier_freq, stereo_freq, dual_freq;
+ s32 ret;
+
+ switch (core->tvaudio) {
+ case WW_BG:
+ case WW_DK:
+ carrier_freq = FREQ_A2_CARRIER;
+ stereo_freq = FREQ_A2_STEREO;
+ dual_freq = FREQ_A2_DUAL;
+ break;
+ case WW_M:
+ carrier_freq = FREQ_A2M_CARRIER;
+ stereo_freq = FREQ_A2M_STEREO;
+ dual_freq = FREQ_A2M_DUAL;
+ break;
+ case WW_EIAJ:
+ carrier_freq = FREQ_EIAJ_CARRIER;
+ stereo_freq = FREQ_EIAJ_STEREO;
+ dual_freq = FREQ_EIAJ_DUAL;
+ break;
+ default:
+ printk(KERN_WARNING "%s/0: unsupported audio mode %d for %s\n",
+ core->name, core->tvaudio, __func__);
+ return UNSET;
+ }
+
+ carrier = freq_magnitude(x, N, carrier_freq);
+ stereo = freq_magnitude(x, N, stereo_freq);
+ dual = freq_magnitude(x, N, dual_freq);
+ noise = noise_magnitude(x, N, FREQ_NOISE_START, FREQ_NOISE_END);
+
+ dprintk(1, "detect a2/a2m/eiaj: carrier=%d, stereo=%d, dual=%d, "
+ "noise=%d\n", carrier, stereo, dual, noise);
+
+ if (stereo > dual)
+ ret = V4L2_TUNER_SUB_STEREO;
+ else
+ ret = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+
+ if (core->tvaudio == WW_EIAJ) {
+ /* EIAJ checks may need adjustments */
+ if ((carrier > max(stereo, dual)*2) &&
+ (carrier < max(stereo, dual)*6) &&
+ (carrier > 20 && carrier < 200) &&
+ (max(stereo, dual) > min(stereo, dual))) {
+ /* For EIAJ the carrier is always present,
+ so we probably don't need noise detection */
+ return ret;
+ }
+ } else {
+ if ((carrier > max(stereo, dual)*2) &&
+ (carrier < max(stereo, dual)*8) &&
+ (carrier > 20 && carrier < 200) &&
+ (noise < 10) &&
+ (max(stereo, dual) > min(stereo, dual)*2)) {
+ return ret;
+ }
+ }
+ return V4L2_TUNER_SUB_MONO;
+}
+
+static s32 detect_btsc(struct cx88_core *core, s16 x[], u32 N)
+{
+ s32 sap_ref = freq_magnitude(x, N, FREQ_BTSC_SAP_REF);
+ s32 sap = freq_magnitude(x, N, FREQ_BTSC_SAP);
+ s32 dual_ref = freq_magnitude(x, N, FREQ_BTSC_DUAL_REF);
+ s32 dual = freq_magnitude(x, N, FREQ_BTSC_DUAL);
+ dprintk(1, "detect btsc: dual_ref=%d, dual=%d, sap_ref=%d, sap=%d"
+ "\n", dual_ref, dual, sap_ref, sap);
+ /* FIXME: Currently not supported */
+ return UNSET;
+}
+
+static s16 *read_rds_samples(struct cx88_core *core, u32 *N)
+{
+ struct sram_channel *srch = &cx88_sram_channels[SRAM_CH27];
+ s16 *samples;
+
+ unsigned int i;
+ unsigned int bpl = srch->fifo_size/AUD_RDS_LINES;
+ unsigned int spl = bpl/4;
+ unsigned int sample_count = spl*(AUD_RDS_LINES-1);
+
+ u32 current_address = cx_read(srch->ptr1_reg);
+ u32 offset = (current_address - srch->fifo_start + bpl);
+
+ dprintk(1, "read RDS samples: current_address=%08x (offset=%08x), "
+ "sample_count=%d, aud_intstat=%08x\n", current_address,
+ current_address - srch->fifo_start, sample_count,
+ cx_read(MO_AUD_INTSTAT));
+
+ samples = kmalloc(sizeof(s16)*sample_count, GFP_KERNEL);
+ if (!samples)
+ return NULL;
+
+ *N = sample_count;
+
+ for (i = 0; i < sample_count; i++) {
+ offset = offset % (AUD_RDS_LINES*bpl);
+ samples[i] = cx_read(srch->fifo_start + offset);
+ offset += 4;
+ }
+
+ if (dsp_debug >= 2) {
+ dprintk(2, "RDS samples dump: ");
+ for (i = 0; i < sample_count; i++)
+ printk("%hd ", samples[i]);
+ printk(".\n");
+ }
+
+ return samples;
+}
+
+s32 cx88_dsp_detect_stereo_sap(struct cx88_core *core)
+{
+ s16 *samples;
+ u32 N = 0;
+ s32 ret = UNSET;
+
+ /* If audio RDS fifo is disabled, we can't read the samples */
+ if (!(cx_read(MO_AUD_DMACNTRL) & 0x04))
+ return ret;
+ if (!(cx_read(AUD_CTL) & EN_FMRADIO_EN_RDS))
+ return ret;
+
+ /* Wait at least 500 ms after an audio standard change */
+ if (time_before(jiffies, core->last_change + msecs_to_jiffies(500)))
+ return ret;
+
+ samples = read_rds_samples(core, &N);
+
+ if (!samples)
+ return ret;
+
+ switch (core->tvaudio) {
+ case WW_BG:
+ case WW_DK:
+ ret = detect_a2_a2m_eiaj(core, samples, N);
+ break;
+ case WW_BTSC:
+ ret = detect_btsc(core, samples, N);
+ break;
+ }
+
+ kfree(samples);
+
+ if (UNSET != ret)
+ dprintk(1, "stereo/sap detection result:%s%s%s\n",
+ (ret & V4L2_TUNER_SUB_MONO) ? " mono" : "",
+ (ret & V4L2_TUNER_SUB_STEREO) ? " stereo" : "",
+ (ret & V4L2_TUNER_SUB_LANG2) ? " dual" : "");
+
+ return ret;
+}
+EXPORT_SYMBOL(cx88_dsp_detect_stereo_sap);
+
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index 996b4ed5a4fc..ee1ca39db06a 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -180,6 +180,19 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci)
do_i2c_scan(core->name,&core->i2c_client);
} else
printk("%s: i2c register FAILED\n", core->name);
+
+ /* Instantiate the IR receiver device, if present */
+ if (0 == core->i2c_rc) {
+ struct i2c_board_info info;
+ const unsigned short addr_list[] = {
+ 0x18, 0x6b, 0x71,
+ I2C_CLIENT_END
+ };
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+ i2c_new_probed_device(&core->i2c_adap, &info, addr_list);
+ }
return core->i2c_rc;
}
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index ec05312a9b62..bd2baa76203f 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -217,6 +217,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
case CX88_BOARD_PCHDTV_HD3000:
case CX88_BOARD_PCHDTV_HD5500:
+ case CX88_BOARD_HAUPPAUGE_IRONLY:
ir_codes = ir_codes_hauppauge_new;
ir_type = IR_TYPE_RC5;
ir->sampling = 1;
@@ -459,6 +460,7 @@ void cx88_ir_irq(struct cx88_core *core)
case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
case CX88_BOARD_PCHDTV_HD3000:
case CX88_BOARD_PCHDTV_HD5500:
+ case CX88_BOARD_HAUPPAUGE_IRONLY:
ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
ir_dprintk("biphase decoded: %x\n", ircode);
/*
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index 7dd506b987fe..e8316cf7f32f 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -163,6 +163,8 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl)
/* unmute */
volume = cx_sread(SHADOW_AUD_VOL_CTL);
cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, volume);
+
+ core->last_change = jiffies;
}
/* ----------------------------------------------------------- */
@@ -745,6 +747,7 @@ void cx88_set_tvaudio(struct cx88_core *core)
break;
case WW_BG:
case WW_DK:
+ case WW_M:
case WW_I:
case WW_L:
/* prepare all dsp registers */
@@ -756,6 +759,7 @@ void cx88_set_tvaudio(struct cx88_core *core)
if (0 == cx88_detect_nicam(core)) {
/* fall back to fm / am mono */
set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
+ core->audiomode_current = V4L2_TUNER_MODE_MONO;
core->use_nicam = 0;
} else {
core->use_nicam = 1;
@@ -787,6 +791,7 @@ void cx88_set_tvaudio(struct cx88_core *core)
void cx88_newstation(struct cx88_core *core)
{
core->audiomode_manual = UNSET;
+ core->last_change = jiffies;
}
void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
@@ -805,12 +810,50 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
aud_ctl_names[cx_read(AUD_CTL) & 63]);
core->astat = reg;
-/* TODO
- Reading from AUD_STATUS is not enough
- for auto-detecting sap/dual-fm/nicam.
- Add some code here later.
-*/
+ t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP |
+ V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
+ t->rxsubchans = UNSET;
+ t->audmode = V4L2_TUNER_MODE_MONO;
+
+ switch (mode) {
+ case 0:
+ t->audmode = V4L2_TUNER_MODE_STEREO;
+ break;
+ case 1:
+ t->audmode = V4L2_TUNER_MODE_LANG2;
+ break;
+ case 2:
+ t->audmode = V4L2_TUNER_MODE_MONO;
+ break;
+ case 3:
+ t->audmode = V4L2_TUNER_MODE_SAP;
+ break;
+ }
+ switch (core->tvaudio) {
+ case WW_BTSC:
+ case WW_BG:
+ case WW_DK:
+ case WW_M:
+ case WW_EIAJ:
+ if (!core->use_nicam) {
+ t->rxsubchans = cx88_dsp_detect_stereo_sap(core);
+ break;
+ }
+ break;
+ default:
+ /* nothing */
+ break;
+ }
+
+ /* If software stereo detection is not supported... */
+ if (UNSET == t->rxsubchans) {
+ t->rxsubchans = V4L2_TUNER_SUB_MONO;
+ /* If the hardware itself detected stereo, also return
+ stereo as an available subchannel */
+ if (V4L2_TUNER_MODE_STEREO == t->audmode)
+ t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
+ }
return;
}
@@ -847,6 +890,7 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
break;
case WW_BG:
case WW_DK:
+ case WW_M:
case WW_I:
case WW_L:
if (1 == core->use_nicam) {
@@ -872,20 +916,18 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
} else {
/* TODO: Add A2 autodection */
+ mask = 0x3f;
switch (mode) {
case V4L2_TUNER_MODE_MONO:
case V4L2_TUNER_MODE_LANG1:
- set_audio_standard_A2(core,
- EN_A2_FORCE_MONO1);
+ ctl = EN_A2_FORCE_MONO1;
break;
case V4L2_TUNER_MODE_LANG2:
- set_audio_standard_A2(core,
- EN_A2_FORCE_MONO2);
+ ctl = EN_A2_FORCE_MONO2;
break;
case V4L2_TUNER_MODE_STEREO:
case V4L2_TUNER_MODE_LANG1_LANG2:
- set_audio_standard_A2(core,
- EN_A2_FORCE_STEREO);
+ ctl = EN_A2_FORCE_STEREO;
break;
}
}
@@ -932,24 +974,39 @@ int cx88_audio_thread(void *data)
break;
try_to_freeze();
- /* just monitor the audio status for now ... */
- memset(&t, 0, sizeof(t));
- cx88_get_stereo(core, &t);
-
- if (UNSET != core->audiomode_manual)
- /* manually set, don't do anything. */
- continue;
-
- /* monitor signal */
- if (t.rxsubchans & V4L2_TUNER_SUB_STEREO)
- mode = V4L2_TUNER_MODE_STEREO;
- else
- mode = V4L2_TUNER_MODE_MONO;
- if (mode == core->audiomode_current)
- continue;
-
- /* automatically switch to best available mode */
- cx88_set_stereo(core, mode, 0);
+ switch (core->tvaudio) {
+ case WW_BG:
+ case WW_DK:
+ case WW_M:
+ case WW_I:
+ case WW_L:
+ if (core->use_nicam)
+ goto hw_autodetect;
+
+ /* just monitor the audio status for now ... */
+ memset(&t, 0, sizeof(t));
+ cx88_get_stereo(core, &t);
+
+ if (UNSET != core->audiomode_manual)
+ /* manually set, don't do anything. */
+ continue;
+
+ /* monitor signal and set stereo if available */
+ if (t.rxsubchans & V4L2_TUNER_SUB_STEREO)
+ mode = V4L2_TUNER_MODE_STEREO;
+ else
+ mode = V4L2_TUNER_MODE_MONO;
+ if (mode == core->audiomode_current)
+ continue;
+ /* automatically switch to best available mode */
+ cx88_set_stereo(core, mode, 0);
+ break;
+ default:
+hw_autodetect:
+ /* stereo autodetection is supported by hardware so
+ we don't need to do it manually. Do nothing. */
+ break;
+ }
}
dprintk("cx88: tvaudio thread exiting\n");
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index 7724d168fc04..cc17272ed3b7 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -65,6 +65,8 @@
#define VBI_LINE_COUNT 17
#define VBI_LINE_LENGTH 2048
+#define AUD_RDS_LINES 4
+
/* need "shadow" registers for some write-only ones ... */
#define SHADOW_AUD_VOL_CTL 1
#define SHADOW_AUD_BAL_CTL 2
@@ -132,6 +134,7 @@ struct cx88_ctrl {
#define SRAM_CH25 4 /* audio */
#define SRAM_CH26 5
#define SRAM_CH28 6 /* mpeg */
+#define SRAM_CH27 7 /* audio rds */
/* more */
struct sram_channel {
@@ -232,6 +235,7 @@ extern struct sram_channel cx88_sram_channels[];
#define CX88_BOARD_TBS_8910 77
#define CX88_BOARD_PROF_6200 78
#define CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII 79
+#define CX88_BOARD_HAUPPAUGE_IRONLY 80
enum cx88_itype {
CX88_VMUX_COMPOSITE1 = 1,
@@ -350,6 +354,7 @@ struct cx88_core {
u32 input;
u32 astat;
u32 use_nicam;
+ unsigned long last_change;
/* IR remote control state */
struct cx88_IR *ir;
@@ -652,6 +657,7 @@ extern void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl);
#define WW_I2SPT 8
#define WW_FM 9
#define WW_I2SADC 10
+#define WW_M 11
void cx88_set_tvaudio(struct cx88_core *core);
void cx88_newstation(struct cx88_core *core);
@@ -665,6 +671,11 @@ struct cx8802_dev *cx8802_get_device(int minor);
struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype);
/* ----------------------------------------------------------- */
+/* cx88-dsp.c */
+
+s32 cx88_dsp_detect_stereo_sap(struct cx88_core *core);
+
+/* ----------------------------------------------------------- */
/* cx88-input.c */
int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci);
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index 7c70738479dd..d4bc862a1a78 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -1095,6 +1095,31 @@ struct em28xx_board em28xx_boards[] = {
.gpio = default_analog,
} },
},
+ [EM2880_BOARD_EMPIRE_DUAL_TV] = {
+ .name = "Empire dual TV",
+ .tuner_type = TUNER_XC2028,
+ .tuner_gpio = default_tuner_gpio,
+ .has_dvb = 1,
+ .dvb_gpio = default_digital,
+ .mts_firmware = 1,
+ .decoder = EM28XX_TVP5150,
+ .input = { {
+ .type = EM28XX_VMUX_TELEVISION,
+ .vmux = TVP5150_COMPOSITE0,
+ .amux = EM28XX_AMUX_VIDEO,
+ .gpio = default_analog,
+ }, {
+ .type = EM28XX_VMUX_COMPOSITE1,
+ .vmux = TVP5150_COMPOSITE1,
+ .amux = EM28XX_AMUX_LINE_IN,
+ .gpio = default_analog,
+ }, {
+ .type = EM28XX_VMUX_SVIDEO,
+ .vmux = TVP5150_SVIDEO,
+ .amux = EM28XX_AMUX_LINE_IN,
+ .gpio = default_analog,
+ } },
+ },
[EM2881_BOARD_DNT_DA2_HYBRID] = {
.name = "DNT DA2 Hybrid",
.valid = EM28XX_BOARD_NOT_VALIDATED,
@@ -1437,6 +1462,7 @@ static struct em28xx_hash_table em28xx_eeprom_hash[] = {
{0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF},
{0x72cc5a8b, EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2, TUNER_YMEC_TVF_5533MF},
{0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028},
+ {0x9567eb1a, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028},
};
/* I2C devicelist hash table for devices with generic USB IDs */
@@ -1664,6 +1690,7 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
ctl->mts = em28xx_boards[dev->model].mts_firmware;
switch (dev->model) {
+ case EM2880_BOARD_EMPIRE_DUAL_TV:
case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
ctl->demod = XC3028_FE_ZARLINK456;
break;
@@ -1835,12 +1862,20 @@ static int em28xx_hint_board(struct em28xx *dev)
}
/* ----------------------------------------------------------------------- */
-void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir)
+void em28xx_register_i2c_ir(struct em28xx *dev)
{
- if (disable_ir) {
- ir->get_key = NULL;
- return ;
- }
+ struct i2c_board_info info;
+ struct IR_i2c_init_data init_data;
+ const unsigned short addr_list[] = {
+ 0x30, 0x47, I2C_CLIENT_END
+ };
+
+ if (disable_ir)
+ return;
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ memset(&init_data, 0, sizeof(struct IR_i2c_init_data));
+ strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
/* detect & configure */
switch (dev->model) {
@@ -1850,22 +1885,19 @@ void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir)
break;
case (EM2800_BOARD_TERRATEC_CINERGY_200):
case (EM2820_BOARD_TERRATEC_CINERGY_250):
- ir->ir_codes = ir_codes_em_terratec;
- ir->get_key = em28xx_get_key_terratec;
- snprintf(ir->c.name, sizeof(ir->c.name),
- "i2c IR (EM28XX Terratec)");
+ init_data.ir_codes = ir_codes_em_terratec;
+ init_data.get_key = em28xx_get_key_terratec;
+ init_data.name = "i2c IR (EM28XX Terratec)";
break;
case (EM2820_BOARD_PINNACLE_USB_2):
- ir->ir_codes = ir_codes_pinnacle_grey;
- ir->get_key = em28xx_get_key_pinnacle_usb_grey;
- snprintf(ir->c.name, sizeof(ir->c.name),
- "i2c IR (EM28XX Pinnacle PCTV)");
+ init_data.ir_codes = ir_codes_pinnacle_grey;
+ init_data.get_key = em28xx_get_key_pinnacle_usb_grey;
+ init_data.name = "i2c IR (EM28XX Pinnacle PCTV)";
break;
case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2):
- ir->ir_codes = ir_codes_hauppauge_new;
- ir->get_key = em28xx_get_key_em_haup;
- snprintf(ir->c.name, sizeof(ir->c.name),
- "i2c IR (EM2840 Hauppauge)");
+ init_data.ir_codes = ir_codes_hauppauge_new;
+ init_data.get_key = em28xx_get_key_em_haup;
+ init_data.name = "i2c IR (EM2840 Hauppauge)";
break;
case (EM2820_BOARD_MSI_VOX_USB_2):
break;
@@ -1876,6 +1908,10 @@ void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir)
case (EM2800_BOARD_GRABBEEX_USB2800):
break;
}
+
+ if (init_data.name)
+ info.platform_data = &init_data;
+ i2c_new_probed_device(&dev->i2c_adap, &info, addr_list);
}
void em28xx_card_setup(struct em28xx *dev)
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index 192b76cdd5d7..7375353c04eb 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -938,7 +938,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets,
dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
GFP_KERNEL);
if (!dev->isoc_ctl.transfer_buffer) {
- em28xx_errdev("cannot allocate memory for usbtransfer\n");
+ em28xx_errdev("cannot allocate memory for usb transfer\n");
kfree(dev->isoc_ctl.urb);
return -ENOMEM;
}
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
index fcd25511209b..c8188dc2b4b5 100644
--- a/drivers/media/video/em28xx/em28xx-dvb.c
+++ b/drivers/media/video/em28xx/em28xx-dvb.c
@@ -431,6 +431,7 @@ static int dvb_init(struct em28xx *dev)
case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
case EM2880_BOARD_TERRATEC_HYBRID_XS:
case EM2880_BOARD_KWORLD_DVB_310U:
+ case EM2880_BOARD_EMPIRE_DUAL_TV:
dvb->frontend = dvb_attach(zl10353_attach,
&em28xx_zl10353_with_xc3028,
&dev->i2c_adap);
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c
index f0bf1d960c75..2c86fcf089f5 100644
--- a/drivers/media/video/em28xx/em28xx-i2c.c
+++ b/drivers/media/video/em28xx/em28xx-i2c.c
@@ -451,27 +451,6 @@ static u32 functionality(struct i2c_adapter *adap)
return I2C_FUNC_SMBUS_EMUL;
}
-/*
- * attach_inform()
- * gets called when a device attaches to the i2c bus
- * does some basic configuration
- */
-static int attach_inform(struct i2c_client *client)
-{
- struct em28xx *dev = client->adapter->algo_data;
- struct IR_i2c *ir = i2c_get_clientdata(client);
-
- switch (client->addr << 1) {
- case 0x60:
- case 0x8e:
- dprintk1(1, "attach_inform: IR detected (%s).\n", ir->phys);
- em28xx_set_ir(dev, ir);
- break;
- }
-
- return 0;
-}
-
static struct i2c_algorithm em28xx_algo = {
.master_xfer = em28xx_i2c_xfer,
.functionality = functionality,
@@ -482,7 +461,6 @@ static struct i2c_adapter em28xx_adap_template = {
.name = "em28xx",
.id = I2C_HW_B_EM28XX,
.algo = &em28xx_algo,
- .client_register = attach_inform,
};
static struct i2c_client em28xx_client_template = {
@@ -575,6 +553,9 @@ int em28xx_i2c_register(struct em28xx *dev)
if (i2c_scan)
em28xx_do_i2c_scan(dev);
+ /* Instantiate the IR receiver device, if present */
+ em28xx_register_i2c_ir(dev);
+
return 0;
}
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c
index a5abfd7a19f5..7a0fe3816e3d 100644
--- a/drivers/media/video/em28xx/em28xx-input.c
+++ b/drivers/media/video/em28xx/em28xx-input.c
@@ -40,7 +40,7 @@ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
#define i2cdprintk(fmt, arg...) \
if (ir_debug) { \
- printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg); \
+ printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
}
#define dprintk(fmt, arg...) \
@@ -85,7 +85,7 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
unsigned char b;
/* poll IR chip */
- if (1 != i2c_master_recv(&ir->c, &b, 1)) {
+ if (1 != i2c_master_recv(ir->c, &b, 1)) {
i2cdprintk("read error\n");
return -EIO;
}
@@ -114,7 +114,7 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
unsigned char code;
/* poll IR chip */
- if (2 != i2c_master_recv(&ir->c, buf, 2))
+ if (2 != i2c_master_recv(ir->c, buf, 2))
return -EIO;
/* Does eliminate repeated parity code */
@@ -147,7 +147,7 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
/* poll IR chip */
- if (3 != i2c_master_recv(&ir->c, buf, 3)) {
+ if (3 != i2c_master_recv(ir->c, buf, 3)) {
i2cdprintk("read error\n");
return -EIO;
}
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index 4c4e58004f54..a8094926ca6a 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -102,6 +102,7 @@
#define EM2860_BOARD_KAIOMY_TVNPC_U2 63
#define EM2860_BOARD_EASYCAP 64
#define EM2820_BOARD_IODATA_GVMVP_SZ 65
+#define EM2880_BOARD_EMPIRE_DUAL_TV 66
/* Limits minimum and default number of buffers */
#define EM28XX_MIN_BUF 4
@@ -639,7 +640,7 @@ extern void em28xx_card_setup(struct em28xx *dev);
extern struct em28xx_board em28xx_boards[];
extern struct usb_device_id em28xx_id_table[];
extern const unsigned int em28xx_bcount;
-void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir);
+void em28xx_register_i2c_ir(struct em28xx *dev);
int em28xx_tuner_callback(void *ptr, int component, int command, int arg);
void em28xx_release_resources(struct em28xx *dev);
diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c
index 00e6863ed666..480ec5c87d0e 100644
--- a/drivers/media/video/gspca/finepix.c
+++ b/drivers/media/video/gspca/finepix.c
@@ -168,6 +168,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam->cam_mode = fpix_mode;
cam->nmodes = 1;
+ cam->bulk = 1;
cam->bulk_size = FPIX_MAX_TRANSFER;
INIT_WORK(&dev->work_struct, dostream);
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index a2741d7dccfe..ae0e14033d66 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -1,7 +1,7 @@
/*
* Main USB camera driver
*
- * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
+ * Copyright (C) 2008-2009 Jean-Francois Moine (http://moinejf.free.fr)
*
* 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
@@ -47,7 +47,7 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
MODULE_DESCRIPTION("GSPCA USB Camera Driver");
MODULE_LICENSE("GPL");
-#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 5, 0)
+#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 6, 0)
#ifdef GSPCA_DEBUG
int gspca_debug = D_ERR | D_PROBE;
@@ -441,7 +441,7 @@ static void destroy_urbs(struct gspca_dev *gspca_dev)
* look for an input transfer endpoint in an alternate setting
*/
static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
- __u8 xfer)
+ int xfer)
{
struct usb_host_endpoint *ep;
int i, attr;
@@ -449,7 +449,8 @@ static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
for (i = 0; i < alt->desc.bNumEndpoints; i++) {
ep = &alt->endpoint[i];
attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
- if (attr == xfer)
+ if (attr == xfer
+ && ep->desc.wMaxPacketSize != 0)
return ep;
}
return NULL;
@@ -467,37 +468,28 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev)
{
struct usb_interface *intf;
struct usb_host_endpoint *ep;
- int i, ret;
+ int xfer, i, ret;
intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
ep = NULL;
+ xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK
+ : USB_ENDPOINT_XFER_ISOC;
i = gspca_dev->alt; /* previous alt setting */
-
- /* try isoc */
while (--i >= 0) {
- ep = alt_xfer(&intf->altsetting[i],
- USB_ENDPOINT_XFER_ISOC);
+ ep = alt_xfer(&intf->altsetting[i], xfer);
if (ep)
break;
}
-
- /* if no isoc, try bulk (alt 0 only) */
if (ep == NULL) {
- ep = alt_xfer(&intf->altsetting[0],
- USB_ENDPOINT_XFER_BULK);
- if (ep == NULL) {
- err("no transfer endpoint found");
- return NULL;
- }
- i = 0;
- gspca_dev->bulk = 1;
+ err("no transfer endpoint found");
+ return NULL;
}
PDEBUG(D_STREAM, "use alt %d ep 0x%02x",
i, ep->desc.bEndpointAddress);
- if (i > 0) {
+ if (gspca_dev->nbalt > 1) {
ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i);
if (ret < 0) {
- err("set interface err %d", ret);
+ err("set alt %d err %d", i, ret);
return NULL;
}
}
@@ -517,13 +509,13 @@ static int create_urbs(struct gspca_dev *gspca_dev,
/* calculate the packet size and the number of packets */
psize = le16_to_cpu(ep->desc.wMaxPacketSize);
- if (!gspca_dev->bulk) { /* isoc */
+ if (!gspca_dev->cam.bulk) { /* isoc */
/* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */
psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
- npkt = ISO_MAX_SIZE / psize;
- if (npkt > ISO_MAX_PKT)
- npkt = ISO_MAX_PKT;
+ npkt = gspca_dev->cam.npkt;
+ if (npkt == 0)
+ npkt = 32; /* default value */
bsize = psize * npkt;
PDEBUG(D_STREAM,
"isoc %d pkts size %d = bsize:%d",
@@ -617,7 +609,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
goto out;
/* clear the bulk endpoint */
- if (gspca_dev->bulk)
+ if (gspca_dev->cam.bulk)
usb_clear_halt(gspca_dev->dev,
gspca_dev->urb[0]->pipe);
@@ -630,7 +622,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
gspca_dev->streaming = 1;
/* some bulk transfers are started by the subdriver */
- if (gspca_dev->bulk && gspca_dev->cam.bulk_nurbs == 0)
+ if (gspca_dev->cam.bulk && gspca_dev->cam.bulk_nurbs == 0)
break;
/* submit the URBs */
@@ -661,6 +653,8 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev)
{
int ret;
+ if (gspca_dev->alt == 0)
+ return 0;
ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0);
if (ret < 0)
PDEBUG(D_ERR|D_STREAM, "set alt 0 err %d", ret);
@@ -1943,7 +1937,7 @@ int gspca_dev_probe(struct usb_interface *intf,
/* init video stuff */
memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template);
- gspca_dev->vdev.parent = &dev->dev;
+ gspca_dev->vdev.parent = &intf->dev;
gspca_dev->module = module;
gspca_dev->present = 1;
ret = video_register_device(&gspca_dev->vdev,
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h
index 58e8ff02136a..bd1faff88644 100644
--- a/drivers/media/video/gspca/gspca.h
+++ b/drivers/media/video/gspca/gspca.h
@@ -44,8 +44,6 @@ extern int gspca_debug;
#define GSPCA_MAX_FRAMES 16 /* maximum number of video frame buffers */
/* image transfers */
#define MAX_NURBS 4 /* max number of URBs */
-#define ISO_MAX_PKT 32 /* max number of packets in an ISOC transfer */
-#define ISO_MAX_SIZE 0x8000 /* max size of one URB buffer (32 Kb) */
/* device information - set at probe time */
struct cam {
@@ -56,6 +54,9 @@ struct cam {
* - cannot be > MAX_NURBS
* - when 0 and bulk_size != 0 means
* 1 URB and submit done by subdriver */
+ u8 bulk; /* image transfer by 0:isoc / 1:bulk */
+ u8 npkt; /* number of packets in an ISOC message
+ * 0 is the default value: 32 packets */
u32 input_flags; /* value for ENUM_INPUT status flags */
};
@@ -168,7 +169,6 @@ struct gspca_dev {
__u8 iface; /* USB interface number */
__u8 alt; /* USB alternate setting */
__u8 nbalt; /* number of USB alternate settings */
- u8 bulk; /* image transfer by 0:isoc / 1:bulk */
};
int gspca_dev_probe(struct usb_interface *intf,
diff --git a/drivers/media/video/gspca/m5602/Makefile b/drivers/media/video/gspca/m5602/Makefile
index 9fa3644f4869..bf7a19a1e6d1 100644
--- a/drivers/media/video/gspca/m5602/Makefile
+++ b/drivers/media/video/gspca/m5602/Makefile
@@ -2,9 +2,10 @@ obj-$(CONFIG_USB_M5602) += gspca_m5602.o
gspca_m5602-objs := m5602_core.o \
m5602_ov9650.o \
+ m5602_ov7660.o \
m5602_mt9m111.o \
m5602_po1030.o \
m5602_s5k83a.o \
m5602_s5k4aa.o
-EXTRA_CFLAGS += -Idrivers/media/video/gspca \ No newline at end of file
+EXTRA_CFLAGS += -Idrivers/media/video/gspca
diff --git a/drivers/media/video/gspca/m5602/m5602_bridge.h b/drivers/media/video/gspca/m5602/m5602_bridge.h
index 8f1cea6fd3bf..1127a405c9b2 100644
--- a/drivers/media/video/gspca/m5602/m5602_bridge.h
+++ b/drivers/media/video/gspca/m5602/m5602_bridge.h
@@ -45,6 +45,15 @@
#define M5602_XB_SEN_CLK_DIV 0x15
#define M5602_XB_AUD_CLK_CTRL 0x16
#define M5602_XB_AUD_CLK_DIV 0x17
+#define M5602_OB_AC_LINK_STATE 0x22
+#define M5602_OB_PCM_SLOT_INDEX 0x24
+#define M5602_OB_GPIO_SLOT_INDEX 0x25
+#define M5602_OB_ACRX_STATUS_ADDRESS_H 0x28
+#define M5602_OB_ACRX_STATUS_DATA_L 0x29
+#define M5602_OB_ACRX_STATUS_DATA_H 0x2a
+#define M5602_OB_ACTX_COMMAND_ADDRESS 0x31
+#define M5602_OB_ACRX_COMMAND_DATA_L 0x32
+#define M5602_OB_ACTX_COMMAND_DATA_H 0X33
#define M5602_XB_DEVCTR1 0x41
#define M5602_XB_EPSETR0 0x42
#define M5602_XB_EPAFCTR 0x47
@@ -77,7 +86,18 @@
#define M5602_XB_GPIO_EN_L 0x75
#define M5602_XB_GPIO_DAT 0x76
#define M5602_XB_GPIO_DIR 0x77
-#define M5602_XB_MISC_CTL 0x70
+#define M5602_XB_SEN_CLK_CONTROL 0x80
+#define M5602_XB_SEN_CLK_DIVISION 0x81
+#define M5602_XB_CPR_CLK_CONTROL 0x82
+#define M5602_XB_CPR_CLK_DIVISION 0x83
+#define M5602_XB_MCU_CLK_CONTROL 0x84
+#define M5602_XB_MCU_CLK_DIVISION 0x85
+#define M5602_XB_DCT_CLK_CONTROL 0x86
+#define M5602_XB_DCT_CLK_DIVISION 0x87
+#define M5602_XB_EC_CLK_CONTROL 0x88
+#define M5602_XB_EC_CLK_DIVISION 0x89
+#define M5602_XB_LBUF_CLK_CONTROL 0x8a
+#define M5602_XB_LBUF_CLK_DIVISION 0x8b
#define I2C_BUSY 0x80
@@ -128,10 +148,10 @@ struct sd {
};
int m5602_read_bridge(
- struct sd *sd, u8 address, u8 *i2c_data);
+ struct sd *sd, const u8 address, u8 *i2c_data);
int m5602_write_bridge(
- struct sd *sd, u8 address, u8 i2c_data);
+ struct sd *sd, const u8 address, const u8 i2c_data);
int m5602_write_sensor(struct sd *sd, const u8 address,
u8 *i2c_data, const u8 len);
diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c
index 1aac2985fee6..8a5bba16ff32 100644
--- a/drivers/media/video/gspca/m5602/m5602_core.c
+++ b/drivers/media/video/gspca/m5602/m5602_core.c
@@ -17,6 +17,7 @@
*/
#include "m5602_ov9650.h"
+#include "m5602_ov7660.h"
#include "m5602_mt9m111.h"
#include "m5602_po1030.h"
#include "m5602_s5k83a.h"
@@ -35,7 +36,7 @@ static const __devinitdata struct usb_device_id m5602_table[] = {
MODULE_DEVICE_TABLE(usb, m5602_table);
/* Reads a byte from the m5602 */
-int m5602_read_bridge(struct sd *sd, u8 address, u8 *i2c_data)
+int m5602_read_bridge(struct sd *sd, const u8 address, u8 *i2c_data)
{
int err;
struct usb_device *udev = sd->gspca_dev.dev;
@@ -56,7 +57,7 @@ int m5602_read_bridge(struct sd *sd, u8 address, u8 *i2c_data)
}
/* Writes a byte to to the m5602 */
-int m5602_write_bridge(struct sd *sd, u8 address, u8 i2c_data)
+int m5602_write_bridge(struct sd *sd, const u8 address, const u8 i2c_data)
{
int err;
struct usb_device *udev = sd->gspca_dev.dev;
@@ -80,6 +81,17 @@ int m5602_write_bridge(struct sd *sd, u8 address, u8 i2c_data)
return (err < 0) ? err : 0;
}
+int m5602_wait_for_i2c(struct sd *sd)
+{
+ int err;
+ u8 data;
+
+ do {
+ err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, &data);
+ } while ((data & I2C_BUSY) && !err);
+ return err;
+}
+
int m5602_read_sensor(struct sd *sd, const u8 address,
u8 *i2c_data, const u8 len)
{
@@ -88,9 +100,7 @@ int m5602_read_sensor(struct sd *sd, const u8 address,
if (!len || len > sd->sensor->i2c_regW)
return -EINVAL;
- do {
- err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
- } while ((*i2c_data & I2C_BUSY) && !err);
+ err = m5602_wait_for_i2c(sd);
if (err < 0)
return err;
@@ -103,21 +113,25 @@ int m5602_read_sensor(struct sd *sd, const u8 address,
if (err < 0)
return err;
+ /* Sensors with registers that are of only
+ one byte width are differently read */
+
+ /* FIXME: This works with the ov9650, but has issues with the po1030 */
if (sd->sensor->i2c_regW == 1) {
- err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, len);
+ err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 1);
if (err < 0)
return err;
err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08);
- if (err < 0)
- return err;
} else {
err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len);
- if (err < 0)
- return err;
}
for (i = 0; (i < len) && !err; i++) {
+ err = m5602_wait_for_i2c(sd);
+ if (err < 0)
+ return err;
+
err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
PDEBUG(D_CONF, "Reading sensor register "
@@ -206,6 +220,11 @@ static int m5602_probe_sensor(struct sd *sd)
if (!sd->sensor->probe(sd))
return 0;
+ /* Try the ov7660 */
+ sd->sensor = &ov7660;
+ if (!sd->sensor->probe(sd))
+ return 0;
+
/* Try the s5k83a */
sd->sensor = &s5k83a;
if (!sd->sensor->probe(sd))
@@ -409,8 +428,9 @@ MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(force_sensor, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(force_sensor,
- "force detection of sensor, "
- "1 = OV9650, 2 = S5K83A, 3 = S5K4AA, 4 = MT9M111, 5 = PO1030");
+ "forces detection of a sensor, "
+ "1 = OV9650, 2 = S5K83A, 3 = S5K4AA, "
+ "4 = MT9M111, 5 = PO1030, 6 = OV7660");
module_param(dump_bridge, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup");
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/drivers/media/video/gspca/m5602/m5602_mt9m111.c
index 7d3f9e348ef4..8d071dff6944 100644
--- a/drivers/media/video/gspca/m5602/m5602_mt9m111.c
+++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.c
@@ -18,6 +18,23 @@
#include "m5602_mt9m111.h"
+static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
+ __s32 val);
+static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev,
+ __s32 *val);
+static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
+
static struct v4l2_pix_format mt9m111_modes[] = {
{
640,
@@ -32,6 +49,7 @@ static struct v4l2_pix_format mt9m111_modes[] = {
};
const static struct ctrl mt9m111_ctrls[] = {
+#define VFLIP_IDX 0
{
{
.id = V4L2_CID_VFLIP,
@@ -44,7 +62,9 @@ const static struct ctrl mt9m111_ctrls[] = {
},
.set = mt9m111_set_vflip,
.get = mt9m111_get_vflip
- }, {
+ },
+#define HFLIP_IDX 1
+ {
{
.id = V4L2_CID_HFLIP,
.type = V4L2_CTRL_TYPE_BOOLEAN,
@@ -56,7 +76,9 @@ const static struct ctrl mt9m111_ctrls[] = {
},
.set = mt9m111_set_hflip,
.get = mt9m111_get_hflip
- }, {
+ },
+#define GAIN_IDX 2
+ {
{
.id = V4L2_CID_GAIN,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -64,21 +86,80 @@ const static struct ctrl mt9m111_ctrls[] = {
.minimum = 0,
.maximum = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2,
.step = 1,
- .default_value = DEFAULT_GAIN,
+ .default_value = MT9M111_DEFAULT_GAIN,
.flags = V4L2_CTRL_FLAG_SLIDER
},
.set = mt9m111_set_gain,
.get = mt9m111_get_gain
- }
+ },
+#define AUTO_WHITE_BALANCE_IDX 3
+ {
+ {
+ .id = V4L2_CID_AUTO_WHITE_BALANCE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "auto white balance",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ .set = mt9m111_set_auto_white_balance,
+ .get = mt9m111_get_auto_white_balance
+ },
+#define GREEN_BALANCE_IDX 4
+ {
+ {
+ .id = M5602_V4L2_CID_GREEN_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "green balance",
+ .minimum = 0x00,
+ .maximum = 0x7ff,
+ .step = 0x1,
+ .default_value = MT9M111_GREEN_GAIN_DEFAULT,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .set = mt9m111_set_green_balance,
+ .get = mt9m111_get_green_balance
+ },
+#define BLUE_BALANCE_IDX 5
+ {
+ {
+ .id = V4L2_CID_BLUE_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "blue balance",
+ .minimum = 0x00,
+ .maximum = 0x7ff,
+ .step = 0x1,
+ .default_value = MT9M111_BLUE_GAIN_DEFAULT,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .set = mt9m111_set_blue_balance,
+ .get = mt9m111_get_blue_balance
+ },
+#define RED_BALANCE_IDX 5
+ {
+ {
+ .id = V4L2_CID_RED_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "red balance",
+ .minimum = 0x00,
+ .maximum = 0x7ff,
+ .step = 0x1,
+ .default_value = MT9M111_RED_GAIN_DEFAULT,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .set = mt9m111_set_red_balance,
+ .get = mt9m111_get_red_balance
+ },
};
-
static void mt9m111_dump_registers(struct sd *sd);
int mt9m111_probe(struct sd *sd)
{
u8 data[2] = {0x00, 0x00};
int i;
+ s32 *sensor_settings;
if (force_sensor) {
if (force_sensor == MT9M111_SENSOR) {
@@ -117,16 +198,27 @@ int mt9m111_probe(struct sd *sd)
return -ENODEV;
sensor_found:
+ sensor_settings = kmalloc(ARRAY_SIZE(mt9m111_ctrls) * sizeof(s32),
+ GFP_KERNEL);
+ if (!sensor_settings)
+ return -ENOMEM;
+
sd->gspca_dev.cam.cam_mode = mt9m111_modes;
sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes);
sd->desc->ctrls = mt9m111_ctrls;
sd->desc->nctrls = ARRAY_SIZE(mt9m111_ctrls);
+
+ for (i = 0; i < ARRAY_SIZE(mt9m111_ctrls); i++)
+ sensor_settings[i] = mt9m111_ctrls[i].qctrl.default_value;
+ sd->sensor_priv = sensor_settings;
+
return 0;
}
int mt9m111_init(struct sd *sd)
{
int i, err = 0;
+ s32 *sensor_settings = sd->sensor_priv;
/* Init the sensor */
for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) {
@@ -147,36 +239,154 @@ int mt9m111_init(struct sd *sd)
if (dump_sensor)
mt9m111_dump_registers(sd);
- return (err < 0) ? err : 0;
+ err = mt9m111_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
+ if (err < 0)
+ return err;
+
+ err = mt9m111_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
+ if (err < 0)
+ return err;
+
+ err = mt9m111_set_green_balance(&sd->gspca_dev,
+ sensor_settings[GREEN_BALANCE_IDX]);
+ if (err < 0)
+ return err;
+
+ err = mt9m111_set_blue_balance(&sd->gspca_dev,
+ sensor_settings[BLUE_BALANCE_IDX]);
+ if (err < 0)
+ return err;
+
+ err = mt9m111_set_red_balance(&sd->gspca_dev,
+ sensor_settings[RED_BALANCE_IDX]);
+ if (err < 0)
+ return err;
+
+ return mt9m111_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
}
-int mt9m111_power_down(struct sd *sd)
+int mt9m111_start(struct sd *sd)
{
- return 0;
+ int i, err = 0;
+ u8 data[2];
+ struct cam *cam = &sd->gspca_dev.cam;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ int width = cam->cam_mode[sd->gspca_dev.curr_mode].width - 1;
+ int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
+
+ for (i = 0; i < ARRAY_SIZE(start_mt9m111) && !err; i++) {
+ if (start_mt9m111[i][0] == BRIDGE) {
+ err = m5602_write_bridge(sd,
+ start_mt9m111[i][1],
+ start_mt9m111[i][2]);
+ } else {
+ data[0] = start_mt9m111[i][2];
+ data[1] = start_mt9m111[i][3];
+ err = m5602_write_sensor(sd,
+ start_mt9m111[i][1], data, 2);
+ }
+ }
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
+ if (err < 0)
+ return err;
+
+ for (i = 0; i < 2 && !err; i++)
+ err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
+ if (err < 0)
+ return err;
+
+ for (i = 0; i < 2 && !err; i++)
+ err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0);
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
+ (width >> 8) & 0xff);
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, width & 0xff);
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
+ if (err < 0)
+ return err;
+
+ switch (width) {
+ case 640:
+ PDEBUG(D_V4L2, "Configuring camera for VGA mode");
+ data[0] = MT9M111_RMB_OVER_SIZED;
+ data[1] = MT9M111_RMB_ROW_SKIP_2X |
+ MT9M111_RMB_COLUMN_SKIP_2X |
+ (sensor_settings[VFLIP_IDX] << 0) |
+ (sensor_settings[HFLIP_IDX] << 1);
+
+ err = m5602_write_sensor(sd,
+ MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
+ break;
+
+ case 320:
+ PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
+ data[0] = MT9M111_RMB_OVER_SIZED;
+ data[1] = MT9M111_RMB_ROW_SKIP_4X |
+ MT9M111_RMB_COLUMN_SKIP_4X |
+ (sensor_settings[VFLIP_IDX] << 0) |
+ (sensor_settings[HFLIP_IDX] << 1);
+ err = m5602_write_sensor(sd,
+ MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
+ break;
+ }
+ return err;
}
-int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+void mt9m111_disconnect(struct sd *sd)
+{
+ sd->sensor = NULL;
+ kfree(sd->sensor_priv);
+}
+
+static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
{
- int err;
- u8 data[2] = {0x00, 0x00};
struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
- err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
- data, 2);
- *val = data[0] & MT9M111_RMB_MIRROR_ROWS;
+ *val = sensor_settings[VFLIP_IDX];
PDEBUG(D_V4L2, "Read vertical flip %d", *val);
- return err;
+ return 0;
}
-int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
{
int err;
u8 data[2] = {0x00, 0x00};
struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
PDEBUG(D_V4L2, "Set vertical flip to %d", val);
+ sensor_settings[VFLIP_IDX] = val;
+
+ /* The mt9m111 is flipped by default */
+ val = !val;
+
/* Set the correct page map */
err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
if (err < 0)
@@ -186,34 +396,37 @@ int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
if (err < 0)
return err;
- data[0] = (data[0] & 0xfe) | val;
+ data[1] = (data[1] & 0xfe) | val;
err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
data, 2);
return err;
}
-int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
{
- int err;
- u8 data[2] = {0x00, 0x00};
struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
- err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
- data, 2);
- *val = data[0] & MT9M111_RMB_MIRROR_COLS;
+ *val = sensor_settings[HFLIP_IDX];
PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
- return err;
+ return 0;
}
-int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
{
int err;
u8 data[2] = {0x00, 0x00};
struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
+ sensor_settings[HFLIP_IDX] = val;
+
+ /* The mt9m111 is flipped by default */
+ val = !val;
+
/* Set the correct page map */
err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
if (err < 0)
@@ -223,36 +436,62 @@ int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
if (err < 0)
return err;
- data[0] = (data[0] & 0xfd) | ((val << 1) & 0x02);
+ data[1] = (data[1] & 0xfd) | ((val << 1) & 0x02);
err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
data, 2);
return err;
}
-int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
{
- int err, tmp;
- u8 data[2] = {0x00, 0x00};
struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
- err = m5602_read_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2);
- tmp = ((data[1] << 8) | data[0]);
+ *val = sensor_settings[GAIN_IDX];
+ PDEBUG(D_V4L2, "Read gain %d", *val);
- *val = ((tmp & (1 << 10)) * 2) |
- ((tmp & (1 << 9)) * 2) |
- ((tmp & (1 << 8)) * 2) |
- (tmp & 0x7f);
+ return 0;
+}
- PDEBUG(D_V4L2, "Read gain %d", *val);
+static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
+ __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+ int err;
+ u8 data[2];
+
+ err = m5602_read_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
+ if (err < 0)
+ return err;
+
+ sensor_settings[AUTO_WHITE_BALANCE_IDX] = val & 0x01;
+ data[1] = ((data[1] & 0xfd) | ((val & 0x01) << 1));
+ err = m5602_write_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
+
+ PDEBUG(D_V4L2, "Set auto white balance %d", val);
return err;
}
-int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev,
+ __s32 *val) {
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
+ PDEBUG(D_V4L2, "Read auto white balance %d", *val);
+ return 0;
+}
+
+static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
{
int err, tmp;
u8 data[2] = {0x00, 0x00};
struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ sensor_settings[GAIN_IDX] = val;
/* Set the correct page map */
err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
@@ -275,8 +514,8 @@ int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
else
tmp = val;
- data[1] = (tmp & 0xff00) >> 8;
- data[0] = (tmp & 0xff);
+ data[1] = (tmp & 0xff);
+ data[0] = (tmp & 0xff00) >> 8;
PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
data[1], data[0]);
@@ -286,6 +525,89 @@ int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
return err;
}
+static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err;
+ u8 data[2];
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ sensor_settings[GREEN_BALANCE_IDX] = val;
+ data[1] = (val & 0xff);
+ data[0] = (val & 0xff00) >> 8;
+
+ PDEBUG(D_V4L2, "Set green balance %d", val);
+ err = m5602_write_sensor(sd, MT9M111_SC_GREEN_1_GAIN,
+ data, 2);
+ if (err < 0)
+ return err;
+
+ return m5602_write_sensor(sd, MT9M111_SC_GREEN_2_GAIN,
+ data, 2);
+}
+
+static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ *val = sensor_settings[GREEN_BALANCE_IDX];
+ PDEBUG(D_V4L2, "Read green balance %d", *val);
+ return 0;
+}
+
+static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+ u8 data[2];
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ sensor_settings[BLUE_BALANCE_IDX] = val;
+ data[1] = (val & 0xff);
+ data[0] = (val & 0xff00) >> 8;
+
+ PDEBUG(D_V4L2, "Set blue balance %d", val);
+
+ return m5602_write_sensor(sd, MT9M111_SC_BLUE_GAIN,
+ data, 2);
+}
+
+static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ *val = sensor_settings[BLUE_BALANCE_IDX];
+ PDEBUG(D_V4L2, "Read blue balance %d", *val);
+ return 0;
+}
+
+static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+ u8 data[2];
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ sensor_settings[RED_BALANCE_IDX] = val;
+ data[1] = (val & 0xff);
+ data[0] = (val & 0xff00) >> 8;
+
+ PDEBUG(D_V4L2, "Set red balance %d", val);
+
+ return m5602_write_sensor(sd, MT9M111_SC_RED_GAIN,
+ data, 2);
+}
+
+static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ *val = sensor_settings[RED_BALANCE_IDX];
+ PDEBUG(D_V4L2, "Read red balance %d", *val);
+ return 0;
+}
+
static void mt9m111_dump_registers(struct sd *sd)
{
u8 address, value[2] = {0x00, 0x00};
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/drivers/media/video/gspca/m5602/m5602_mt9m111.h
index 00c6db02bdb7..b3de77823091 100644
--- a/drivers/media/video/gspca/m5602/m5602_mt9m111.h
+++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.h
@@ -37,7 +37,6 @@
#define MT9M111_SC_VBLANK_CONTEXT_A 0x08
#define MT9M111_SC_SHUTTER_WIDTH 0x09
#define MT9M111_SC_ROW_SPEED 0x0a
-
#define MT9M111_SC_EXTRA_DELAY 0x0b
#define MT9M111_SC_SHUTTER_DELAY 0x0c
#define MT9M111_SC_RESET 0x0d
@@ -50,9 +49,6 @@
#define MT9M111_SC_GREEN_2_GAIN 0x2e
#define MT9M111_SC_GLOBAL_GAIN 0x2f
-#define MT9M111_RMB_MIRROR_ROWS (1 << 0)
-#define MT9M111_RMB_MIRROR_COLS (1 << 1)
-
#define MT9M111_CONTEXT_CONTROL 0xc8
#define MT9M111_PAGE_MAP 0xf0
#define MT9M111_BYTEWISE_ADDRESS 0xf1
@@ -74,8 +70,37 @@
#define MT9M111_COLORPIPE 0x01
#define MT9M111_CAMERA_CONTROL 0x02
+#define MT9M111_RESET (1 << 0)
+#define MT9M111_RESTART (1 << 1)
+#define MT9M111_ANALOG_STANDBY (1 << 2)
+#define MT9M111_CHIP_ENABLE (1 << 3)
+#define MT9M111_CHIP_DISABLE (0 << 3)
+#define MT9M111_OUTPUT_DISABLE (1 << 4)
+#define MT9M111_SHOW_BAD_FRAMES (1 << 0)
+#define MT9M111_RESTART_BAD_FRAMES (1 << 1)
+#define MT9M111_SYNCHRONIZE_CHANGES (1 << 7)
+
+#define MT9M111_RMB_OVER_SIZED (1 << 0)
+#define MT9M111_RMB_MIRROR_ROWS (1 << 0)
+#define MT9M111_RMB_MIRROR_COLS (1 << 1)
+#define MT9M111_RMB_ROW_SKIP_2X (1 << 2)
+#define MT9M111_RMB_COLUMN_SKIP_2X (1 << 3)
+#define MT9M111_RMB_ROW_SKIP_4X (1 << 4)
+#define MT9M111_RMB_COLUMN_SKIP_4X (1 << 5)
+
+#define MT9M111_COLOR_MATRIX_BYPASS (1 << 4)
+#define MT9M111_SEL_CONTEXT_B (1 << 3)
+
+#define MT9M111_TRISTATE_PIN_IN_STANDBY (1 << 1)
+#define MT9M111_SOC_SOFT_STANDBY (1 << 0)
+
+#define MT9M111_2D_DEFECT_CORRECTION_ENABLE (1 << 0)
+
#define INITIAL_MAX_GAIN 64
-#define DEFAULT_GAIN 283
+#define MT9M111_DEFAULT_GAIN 283
+#define MT9M111_GREEN_GAIN_DEFAULT 0x20
+#define MT9M111_BLUE_GAIN_DEFAULT 0x20
+#define MT9M111_RED_GAIN_DEFAULT 0x20
/*****************************************************************************/
@@ -85,16 +110,10 @@ extern int dump_sensor;
int mt9m111_probe(struct sd *sd);
int mt9m111_init(struct sd *sd);
-int mt9m111_power_down(struct sd *sd);
+int mt9m111_start(struct sd *sd);
+void mt9m111_disconnect(struct sd *sd);
-int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
-int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-
-const static struct m5602_sensor mt9m111 = {
+static const struct m5602_sensor mt9m111 = {
.name = "MT9M111",
.i2c_slave_id = 0xba,
@@ -102,7 +121,8 @@ const static struct m5602_sensor mt9m111 = {
.probe = mt9m111_probe,
.init = mt9m111_init,
- .power_down = mt9m111_power_down
+ .disconnect = mt9m111_disconnect,
+ .start = mt9m111_start,
};
static const unsigned char preinit_mt9m111[][4] =
@@ -117,7 +137,14 @@ static const unsigned char preinit_mt9m111[][4] =
{BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0xff, 0xf7},
+ {SENSOR, MT9M111_SC_RESET,
+ MT9M111_RESET |
+ MT9M111_RESTART |
+ MT9M111_ANALOG_STANDBY |
+ MT9M111_CHIP_DISABLE,
+ MT9M111_SHOW_BAD_FRAMES |
+ MT9M111_RESTART_BAD_FRAMES |
+ MT9M111_SYNCHRONIZE_CHANGES},
{BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
{BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
@@ -145,731 +172,42 @@ static const unsigned char init_mt9m111[][4] =
{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
- {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
- {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
- {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
{BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0xff, 0xff},
- {SENSOR, MT9M111_SC_RESET, 0xff, 0xff},
- {SENSOR, MT9M111_SC_RESET, 0xff, 0xde},
- {SENSOR, MT9M111_SC_RESET, 0xff, 0xff},
- {SENSOR, MT9M111_SC_RESET, 0xff, 0xf7},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
-
- {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0xff, 0xff},
-
- {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
- {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
- {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
- {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
{BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
{BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
-
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
- {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
- {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
- {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
- {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
- {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
- {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
- {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
- {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
-
- {SENSOR, 0xcd, 0x00, 0x0e},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
- {SENSOR, 0xd0, 0x00, 0x40},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
- {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
- {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
- {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
- {SENSOR, 0x33, 0x03, 0x49},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
-
- {SENSOR, 0x33, 0x03, 0x49},
- {SENSOR, 0x34, 0xc0, 0x19},
- {SENSOR, 0x3f, 0x20, 0x20},
- {SENSOR, 0x40, 0x20, 0x20},
- {SENSOR, 0x5a, 0xc0, 0x0a},
- {SENSOR, 0x70, 0x7b, 0x0a},
- {SENSOR, 0x71, 0xff, 0x00},
- {SENSOR, 0x72, 0x19, 0x0e},
- {SENSOR, 0x73, 0x18, 0x0f},
- {SENSOR, 0x74, 0x57, 0x32},
- {SENSOR, 0x75, 0x56, 0x34},
- {SENSOR, 0x76, 0x73, 0x35},
- {SENSOR, 0x77, 0x30, 0x12},
- {SENSOR, 0x78, 0x79, 0x02},
- {SENSOR, 0x79, 0x75, 0x06},
- {SENSOR, 0x7a, 0x77, 0x0a},
- {SENSOR, 0x7b, 0x78, 0x09},
- {SENSOR, 0x7c, 0x7d, 0x06},
- {SENSOR, 0x7d, 0x31, 0x10},
- {SENSOR, 0x7e, 0x00, 0x7e},
- {SENSOR, 0x80, 0x59, 0x04},
- {SENSOR, 0x81, 0x59, 0x04},
- {SENSOR, 0x82, 0x57, 0x0a},
- {SENSOR, 0x83, 0x58, 0x0b},
- {SENSOR, 0x84, 0x47, 0x0c},
- {SENSOR, 0x85, 0x48, 0x0e},
- {SENSOR, 0x86, 0x5b, 0x02},
- {SENSOR, 0x87, 0x00, 0x5c},
- {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
- {SENSOR, 0x60, 0x00, 0x80},
- {SENSOR, 0x61, 0x00, 0x00},
- {SENSOR, 0x62, 0x00, 0x00},
- {SENSOR, 0x63, 0x00, 0x00},
- {SENSOR, 0x64, 0x00, 0x00},
-
- {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
- {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18},
- {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04},
- {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08},
- {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38},
- {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
- {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38},
- {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
- {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03},
- {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03},
- {SENSOR, 0x30, 0x04, 0x00},
-
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
- {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
- {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
- {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4},
- {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea},
-
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
- {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
- {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
- {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x09},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x04},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
- {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03},
- {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
{BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
{BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
{BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
- {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
-
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
- {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
- {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
- {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
- {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
- {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
- {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
- {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
- {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
-
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
- {SENSOR, 0xcd, 0x00, 0x0e},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
- {SENSOR, 0xd0, 0x00, 0x40},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
- {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
- {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
- {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
- {SENSOR, 0x33, 0x03, 0x49},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
-
- {SENSOR, 0x33, 0x03, 0x49},
- {SENSOR, 0x34, 0xc0, 0x19},
- {SENSOR, 0x3f, 0x20, 0x20},
- {SENSOR, 0x40, 0x20, 0x20},
- {SENSOR, 0x5a, 0xc0, 0x0a},
- {SENSOR, 0x70, 0x7b, 0x0a},
- {SENSOR, 0x71, 0xff, 0x00},
- {SENSOR, 0x72, 0x19, 0x0e},
- {SENSOR, 0x73, 0x18, 0x0f},
- {SENSOR, 0x74, 0x57, 0x32},
- {SENSOR, 0x75, 0x56, 0x34},
- {SENSOR, 0x76, 0x73, 0x35},
- {SENSOR, 0x77, 0x30, 0x12},
- {SENSOR, 0x78, 0x79, 0x02},
- {SENSOR, 0x79, 0x75, 0x06},
- {SENSOR, 0x7a, 0x77, 0x0a},
- {SENSOR, 0x7b, 0x78, 0x09},
- {SENSOR, 0x7c, 0x7d, 0x06},
- {SENSOR, 0x7d, 0x31, 0x10},
- {SENSOR, 0x7e, 0x00, 0x7e},
- {SENSOR, 0x80, 0x59, 0x04},
- {SENSOR, 0x81, 0x59, 0x04},
- {SENSOR, 0x82, 0x57, 0x0a},
- {SENSOR, 0x83, 0x58, 0x0b},
- {SENSOR, 0x84, 0x47, 0x0c},
- {SENSOR, 0x85, 0x48, 0x0e},
- {SENSOR, 0x86, 0x5b, 0x02},
- {SENSOR, 0x87, 0x00, 0x5c},
- {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
- {SENSOR, 0x60, 0x00, 0x80},
- {SENSOR, 0x61, 0x00, 0x00},
- {SENSOR, 0x62, 0x00, 0x00},
- {SENSOR, 0x63, 0x00, 0x00},
- {SENSOR, 0x64, 0x00, 0x00},
-
- {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
- {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18},
- {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04},
- {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08},
- {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38},
- {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
- {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38},
- {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
- {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03},
- {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03},
- {SENSOR, 0x30, 0x04, 0x00},
-
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
- {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
- {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
- {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4},
- {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x09},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x04},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
-
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
- {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03},
- {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
- {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
{BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
- {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
{BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
- {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
{BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
{BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
{BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
{SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
{SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
- {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
+ {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00,
+ MT9M111_CP_OPERATING_MODE_CTL},
{SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
- {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
- {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
+ {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00,
+ MT9M111_2D_DEFECT_CORRECTION_ENABLE},
+ {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00,
+ MT9M111_2D_DEFECT_CORRECTION_ENABLE},
{SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
{SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
{SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
{SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
-
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
{SENSOR, 0xcd, 0x00, 0x0e},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
{SENSOR, 0xd0, 0x00, 0x40},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
- {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
- {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
- {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
- {SENSOR, 0x33, 0x03, 0x49},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
-
- {SENSOR, 0x33, 0x03, 0x49},
- {SENSOR, 0x34, 0xc0, 0x19},
- {SENSOR, 0x3f, 0x20, 0x20},
- {SENSOR, 0x40, 0x20, 0x20},
- {SENSOR, 0x5a, 0xc0, 0x0a},
- {SENSOR, 0x70, 0x7b, 0x0a},
- {SENSOR, 0x71, 0xff, 0x00},
- {SENSOR, 0x72, 0x19, 0x0e},
- {SENSOR, 0x73, 0x18, 0x0f},
- {SENSOR, 0x74, 0x57, 0x32},
- {SENSOR, 0x75, 0x56, 0x34},
- {SENSOR, 0x76, 0x73, 0x35},
- {SENSOR, 0x77, 0x30, 0x12},
- {SENSOR, 0x78, 0x79, 0x02},
- {SENSOR, 0x79, 0x75, 0x06},
- {SENSOR, 0x7a, 0x77, 0x0a},
- {SENSOR, 0x7b, 0x78, 0x09},
- {SENSOR, 0x7c, 0x7d, 0x06},
- {SENSOR, 0x7d, 0x31, 0x10},
- {SENSOR, 0x7e, 0x00, 0x7e},
- {SENSOR, 0x80, 0x59, 0x04},
- {SENSOR, 0x81, 0x59, 0x04},
- {SENSOR, 0x82, 0x57, 0x0a},
- {SENSOR, 0x83, 0x58, 0x0b},
- {SENSOR, 0x84, 0x47, 0x0c},
- {SENSOR, 0x85, 0x48, 0x0e},
- {SENSOR, 0x86, 0x5b, 0x02},
- {SENSOR, 0x87, 0x00, 0x5c},
- {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
- {SENSOR, 0x60, 0x00, 0x80},
- {SENSOR, 0x61, 0x00, 0x00},
- {SENSOR, 0x62, 0x00, 0x00},
- {SENSOR, 0x63, 0x00, 0x00},
- {SENSOR, 0x64, 0x00, 0x00},
- {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
- {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18},
- {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04},
- {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08},
- {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38},
- {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
- {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38},
- {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
- {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03},
- {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03},
- {SENSOR, 0x30, 0x04, 0x00},
-
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
- {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
- {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
- {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4},
- {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x09},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x04},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03},
- {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
- {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
- {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
- {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
- {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
- {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
- {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
- {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
- {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
- {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
- {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
- {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
-
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, 0xcd, 0x00, 0x0e},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, 0xd0, 0x00, 0x40},
{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
{SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
{SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, 0x33, 0x03, 0x49},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-
- {SENSOR, 0x33, 0x03, 0x49},
- {SENSOR, 0x34, 0xc0, 0x19},
- {SENSOR, 0x3f, 0x20, 0x20},
- {SENSOR, 0x40, 0x20, 0x20},
- {SENSOR, 0x5a, 0xc0, 0x0a},
- {SENSOR, 0x70, 0x7b, 0x0a},
- {SENSOR, 0x71, 0xff, 0x00},
- {SENSOR, 0x72, 0x19, 0x0e},
- {SENSOR, 0x73, 0x18, 0x0f},
- {SENSOR, 0x74, 0x57, 0x32},
- {SENSOR, 0x75, 0x56, 0x34},
- {SENSOR, 0x76, 0x73, 0x35},
- {SENSOR, 0x77, 0x30, 0x12},
- {SENSOR, 0x78, 0x79, 0x02},
- {SENSOR, 0x79, 0x75, 0x06},
- {SENSOR, 0x7a, 0x77, 0x0a},
- {SENSOR, 0x7b, 0x78, 0x09},
- {SENSOR, 0x7c, 0x7d, 0x06},
- {SENSOR, 0x7d, 0x31, 0x10},
- {SENSOR, 0x7e, 0x00, 0x7e},
- {SENSOR, 0x80, 0x59, 0x04},
- {SENSOR, 0x81, 0x59, 0x04},
- {SENSOR, 0x82, 0x57, 0x0a},
- {SENSOR, 0x83, 0x58, 0x0b},
- {SENSOR, 0x84, 0x47, 0x0c},
- {SENSOR, 0x85, 0x48, 0x0e},
- {SENSOR, 0x86, 0x5b, 0x02},
- {SENSOR, 0x87, 0x00, 0x5c},
- {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
- {SENSOR, 0x60, 0x00, 0x80},
- {SENSOR, 0x61, 0x00, 0x00},
- {SENSOR, 0x62, 0x00, 0x00},
- {SENSOR, 0x63, 0x00, 0x00},
- {SENSOR, 0x64, 0x00, 0x00},
- {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
- {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12},
- {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00},
- {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10},
- {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60},
- {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
- {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60},
- {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
- {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x0f},
- {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f},
- {SENSOR, 0x30, 0x04, 0x00},
-
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
- {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
- {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
- {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0xe3, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90},
- {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xe6},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x09},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x04},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03},
- {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
- {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
- {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
- {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
- {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
- {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
- {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
- {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
- {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
- {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
- {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
- {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
-
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, 0xcd, 0x00, 0x0e},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, 0xd0, 0x00, 0x40},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
- {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
- {SENSOR, 0x33, 0x03, 0x49},
- {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
- {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
- {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-
{SENSOR, 0x33, 0x03, 0x49},
{SENSOR, 0x34, 0xc0, 0x19},
{SENSOR, 0x3f, 0x20, 0x20},
@@ -898,25 +236,29 @@ static const unsigned char init_mt9m111[][4] =
{SENSOR, 0x85, 0x48, 0x0e},
{SENSOR, 0x86, 0x5b, 0x02},
{SENSOR, 0x87, 0x00, 0x5c},
- {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
+ {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, MT9M111_SEL_CONTEXT_B},
{SENSOR, 0x60, 0x00, 0x80},
{SENSOR, 0x61, 0x00, 0x00},
{SENSOR, 0x62, 0x00, 0x00},
{SENSOR, 0x63, 0x00, 0x00},
{SENSOR, 0x64, 0x00, 0x00},
- {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
- {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12},
- {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00},
- {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10},
- {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60},
- {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
- {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60},
- {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
- {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x0f},
- {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f},
+ {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, /* 13 */
+ {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12}, /* 18 */
+ {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00}, /* 1024 */
+ {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10}, /* 1296 */
+ {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60}, /* 352 */
+ {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, /* 17 */
+ {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60}, /* 352 */
+ {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, /* 17 */
+ {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, /* 271 */
{SENSOR, 0x30, 0x04, 0x00},
+ /* Set number of blank rows chosen to 400 */
+ {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90},
+};
+static const unsigned char start_mt9m111[][4] =
+{
{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
@@ -928,25 +270,6 @@ static const unsigned char init_mt9m111[][4] =
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, /* 639*/
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-
- {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
- /* Set number of blank rows chosen to 400 */
- {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90},
- /* Set the global gain to 283 (of 512) */
- {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x03, 0x63}
};
#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_ov7660.c b/drivers/media/video/gspca/m5602/m5602_ov7660.c
new file mode 100644
index 000000000000..7aafeb7cfa07
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_ov7660.c
@@ -0,0 +1,227 @@
+/*
+ * Driver for the ov7660 sensor
+ *
+ * Copyright (C) 2009 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * 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 "m5602_ov7660.h"
+
+static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+
+const static struct ctrl ov7660_ctrls[] = {
+#define GAIN_IDX 1
+ {
+ {
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "gain",
+ .minimum = 0x00,
+ .maximum = 0xff,
+ .step = 0x1,
+ .default_value = OV7660_DEFAULT_GAIN,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .set = ov7660_set_gain,
+ .get = ov7660_get_gain
+ },
+};
+
+static struct v4l2_pix_format ov7660_modes[] = {
+ {
+ 640,
+ 480,
+ V4L2_PIX_FMT_SBGGR8,
+ V4L2_FIELD_NONE,
+ .sizeimage =
+ 640 * 480,
+ .bytesperline = 640,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 0
+ }
+};
+
+static void ov7660_dump_registers(struct sd *sd);
+
+int ov7660_probe(struct sd *sd)
+{
+ int err = 0, i;
+ u8 prod_id = 0, ver_id = 0;
+
+ s32 *sensor_settings;
+
+ if (force_sensor) {
+ if (force_sensor == OV7660_SENSOR) {
+ info("Forcing an %s sensor", ov7660.name);
+ goto sensor_found;
+ }
+ /* If we want to force another sensor,
+ don't try to probe this one */
+ return -ENODEV;
+ }
+
+ /* Do the preinit */
+ for (i = 0; i < ARRAY_SIZE(preinit_ov7660) && !err; i++) {
+ u8 data[2];
+
+ if (preinit_ov7660[i][0] == BRIDGE) {
+ err = m5602_write_bridge(sd,
+ preinit_ov7660[i][1],
+ preinit_ov7660[i][2]);
+ } else {
+ data[0] = preinit_ov7660[i][2];
+ err = m5602_write_sensor(sd,
+ preinit_ov7660[i][1], data, 1);
+ }
+ }
+ if (err < 0)
+ return err;
+
+ if (m5602_read_sensor(sd, OV7660_PID, &prod_id, 1))
+ return -ENODEV;
+
+ if (m5602_read_sensor(sd, OV7660_VER, &ver_id, 1))
+ return -ENODEV;
+
+ info("Sensor reported 0x%x%x", prod_id, ver_id);
+
+ if ((prod_id == 0x76) && (ver_id == 0x60)) {
+ info("Detected a ov7660 sensor");
+ goto sensor_found;
+ }
+ return -ENODEV;
+
+sensor_found:
+ sensor_settings = kmalloc(
+ ARRAY_SIZE(ov7660_ctrls) * sizeof(s32), GFP_KERNEL);
+ if (!sensor_settings)
+ return -ENOMEM;
+
+ sd->gspca_dev.cam.cam_mode = ov7660_modes;
+ sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov7660_modes);
+ sd->desc->ctrls = ov7660_ctrls;
+ sd->desc->nctrls = ARRAY_SIZE(ov7660_ctrls);
+
+ for (i = 0; i < ARRAY_SIZE(ov7660_ctrls); i++)
+ sensor_settings[i] = ov7660_ctrls[i].qctrl.default_value;
+ sd->sensor_priv = sensor_settings;
+
+ return 0;
+}
+
+int ov7660_init(struct sd *sd)
+{
+ int i, err = 0;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ /* Init the sensor */
+ for (i = 0; i < ARRAY_SIZE(init_ov7660); i++) {
+ u8 data[2];
+
+ if (init_ov7660[i][0] == BRIDGE) {
+ err = m5602_write_bridge(sd,
+ init_ov7660[i][1],
+ init_ov7660[i][2]);
+ } else {
+ data[0] = init_ov7660[i][2];
+ err = m5602_write_sensor(sd,
+ init_ov7660[i][1], data, 1);
+ }
+ }
+
+ if (dump_sensor)
+ ov7660_dump_registers(sd);
+
+ err = ov7660_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
+ if (err < 0)
+ return err;
+
+ return err;
+}
+
+int ov7660_start(struct sd *sd)
+{
+ return 0;
+}
+
+int ov7660_stop(struct sd *sd)
+{
+ return 0;
+}
+
+void ov7660_disconnect(struct sd *sd)
+{
+ ov7660_stop(sd);
+
+ sd->sensor = NULL;
+ kfree(sd->sensor_priv);
+}
+
+static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ *val = sensor_settings[GAIN_IDX];
+ PDEBUG(D_V4L2, "Read gain %d", *val);
+ return 0;
+}
+
+static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err;
+ u8 i2c_data;
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ PDEBUG(D_V4L2, "Setting gain to %d", val);
+
+ sensor_settings[GAIN_IDX] = val;
+
+ err = m5602_write_sensor(sd, OV7660_GAIN, &i2c_data, 1);
+ return err;
+}
+
+static void ov7660_dump_registers(struct sd *sd)
+{
+ int address;
+ info("Dumping the ov7660 register state");
+ for (address = 0; address < 0xa9; address++) {
+ u8 value;
+ m5602_read_sensor(sd, address, &value, 1);
+ info("register 0x%x contains 0x%x",
+ address, value);
+ }
+
+ info("ov7660 register state dump complete");
+
+ info("Probing for which registers that are read/write");
+ for (address = 0; address < 0xff; address++) {
+ u8 old_value, ctrl_value;
+ u8 test_value[2] = {0xff, 0xff};
+
+ m5602_read_sensor(sd, address, &old_value, 1);
+ m5602_write_sensor(sd, address, test_value, 1);
+ m5602_read_sensor(sd, address, &ctrl_value, 1);
+
+ if (ctrl_value == test_value[0])
+ info("register 0x%x is writeable", address);
+ else
+ info("register 0x%x is read only", address);
+
+ /* Restore original value */
+ m5602_write_sensor(sd, address, &old_value, 1);
+ }
+}
diff --git a/drivers/media/video/gspca/m5602/m5602_ov7660.h b/drivers/media/video/gspca/m5602/m5602_ov7660.h
new file mode 100644
index 000000000000..3f2c169a93ea
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_ov7660.h
@@ -0,0 +1,279 @@
+/*
+ * Driver for the ov7660 sensor
+ *
+ * Copyright (C) 2009 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * 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.
+ *
+ */
+
+#ifndef M5602_OV7660_H_
+#define M5602_OV7660_H_
+
+#include "m5602_sensor.h"
+
+#define OV7660_GAIN 0x00
+#define OV7660_BLUE_GAIN 0x01
+#define OV7660_RED_GAIN 0x02
+#define OV7660_VREF 0x03
+#define OV7660_COM1 0x04
+#define OV7660_BAVE 0x05
+#define OV7660_GEAVE 0x06
+#define OV7660_AECHH 0x07
+#define OV7660_RAVE 0x08
+#define OV7660_COM2 0x09
+#define OV7660_PID 0x0a
+#define OV7660_VER 0x0b
+#define OV7660_COM3 0x0c
+#define OV7660_COM4 0x0d
+#define OV7660_COM5 0x0e
+#define OV7660_COM6 0x0f
+#define OV7660_AECH 0x10
+#define OV7660_CLKRC 0x11
+#define OV7660_COM7 0x12
+#define OV7660_COM8 0x13
+#define OV7660_COM9 0x14
+#define OV7660_COM10 0x15
+#define OV7660_RSVD16 0x16
+#define OV7660_HSTART 0x17
+#define OV7660_HSTOP 0x18
+#define OV7660_VSTART 0x19
+#define OV7660_VSTOP 0x1a
+#define OV7660_PSHFT 0x1b
+#define OV7660_MIDH 0x1c
+#define OV7660_MIDL 0x1d
+#define OV7660_MVFP 0x1e
+#define OV7660_LAEC 0x1f
+#define OV7660_BOS 0x20
+#define OV7660_GBOS 0x21
+#define OV7660_GROS 0x22
+#define OV7660_ROS 0x23
+#define OV7660_AEW 0x24
+#define OV7660_AEB 0x25
+#define OV7660_VPT 0x26
+#define OV7660_BBIAS 0x27
+#define OV7660_GbBIAS 0x28
+#define OV7660_RSVD29 0x29
+#define OV7660_RBIAS 0x2c
+#define OV7660_HREF 0x32
+#define OV7660_ADC 0x37
+#define OV7660_OFON 0x39
+#define OV7660_TSLB 0x3a
+#define OV7660_COM12 0x3c
+#define OV7660_COM13 0x3d
+#define OV7660_LCC1 0x62
+#define OV7660_LCC2 0x63
+#define OV7660_LCC3 0x64
+#define OV7660_LCC4 0x65
+#define OV7660_LCC5 0x66
+#define OV7660_HV 0x69
+#define OV7660_RSVDA1 0xa1
+
+#define OV7660_DEFAULT_GAIN 0x0e
+#define OV7660_DEFAULT_RED_GAIN 0x80
+#define OV7660_DEFAULT_BLUE_GAIN 0x80
+#define OV7660_DEFAULT_SATURATION 0x00
+#define OV7660_DEFAULT_EXPOSURE 0x20
+
+/* Kernel module parameters */
+extern int force_sensor;
+extern int dump_sensor;
+
+int ov7660_probe(struct sd *sd);
+int ov7660_init(struct sd *sd);
+int ov7660_start(struct sd *sd);
+int ov7660_stop(struct sd *sd);
+void ov7660_disconnect(struct sd *sd);
+
+const static struct m5602_sensor ov7660 = {
+ .name = "ov7660",
+ .i2c_slave_id = 0x42,
+ .i2c_regW = 1,
+ .probe = ov7660_probe,
+ .init = ov7660_init,
+ .start = ov7660_start,
+ .stop = ov7660_stop,
+ .disconnect = ov7660_disconnect,
+};
+
+static const unsigned char preinit_ov7660[][4] =
+{
+ {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
+ {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
+ {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x03},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x03},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+
+ {SENSOR, OV7660_OFON, 0x0c},
+ {SENSOR, OV7660_COM2, 0x11},
+ {SENSOR, OV7660_COM7, 0x05},
+
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x01},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}
+};
+
+static const unsigned char init_ov7660[][4] =
+{
+ {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
+ {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
+ {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x03},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x03},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+
+ {SENSOR, OV7660_OFON, 0x0c},
+ {SENSOR, OV7660_COM2, 0x11},
+ {SENSOR, OV7660_COM7, 0x05},
+
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x01},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
+
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x02},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+
+ {SENSOR, OV7660_AECH, OV7660_DEFAULT_EXPOSURE},
+ {SENSOR, OV7660_COM1, 0x00},
+
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x01},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
+
+ {SENSOR, OV7660_COM7, 0x80},
+ {SENSOR, OV7660_CLKRC, 0x80},
+ {SENSOR, OV7660_BLUE_GAIN, 0x80},
+ {SENSOR, OV7660_RED_GAIN, 0x80},
+ {SENSOR, OV7660_COM9, 0x4c},
+ {SENSOR, OV7660_OFON, 0x43},
+ {SENSOR, OV7660_COM12, 0x28},
+ {SENSOR, OV7660_COM8, 0x00},
+ {SENSOR, OV7660_COM10, 0x40},
+ {SENSOR, OV7660_HSTART, 0x0c},
+ {SENSOR, OV7660_HSTOP, 0x61},
+ {SENSOR, OV7660_HREF, 0xa4},
+ {SENSOR, OV7660_PSHFT, 0x0b},
+ {SENSOR, OV7660_VSTART, 0x01},
+ {SENSOR, OV7660_VSTOP, 0x7a},
+ {SENSOR, OV7660_VREF, 0x00},
+ {SENSOR, OV7660_COM7, 0x05},
+ {SENSOR, OV7660_COM6, 0x4b},
+ {SENSOR, OV7660_BBIAS, 0x98},
+ {SENSOR, OV7660_GbBIAS, 0x98},
+ {SENSOR, OV7660_RSVD29, 0x98},
+ {SENSOR, OV7660_RBIAS, 0x98},
+ {SENSOR, OV7660_COM1, 0x00},
+ {SENSOR, OV7660_AECH, 0x00},
+ {SENSOR, OV7660_AECHH, 0x00},
+ {SENSOR, OV7660_ADC, 0x04},
+ {SENSOR, OV7660_COM13, 0x00},
+ {SENSOR, OV7660_RSVDA1, 0x23},
+ {SENSOR, OV7660_TSLB, 0x0d},
+ {SENSOR, OV7660_HV, 0x80},
+ {SENSOR, OV7660_LCC1, 0x00},
+ {SENSOR, OV7660_LCC2, 0x00},
+ {SENSOR, OV7660_LCC3, 0x10},
+ {SENSOR, OV7660_LCC4, 0x40},
+ {SENSOR, OV7660_LCC5, 0x01},
+
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+ {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81},
+ {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
+ {BRIDGE, M5602_XB_SIG_INI, 0x01},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x08},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0}, /* 480 */
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x02},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x27}, /* 39 */
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x02},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0xa7}, /* 679 */
+ {BRIDGE, M5602_XB_SIG_INI, 0x00},
+
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+
+ {SENSOR, OV7660_AECH, 0x20},
+ {SENSOR, OV7660_COM1, 0x00},
+ {SENSOR, OV7660_OFON, 0x0c},
+ {SENSOR, OV7660_COM2, 0x11},
+ {SENSOR, OV7660_COM7, 0x05},
+ {SENSOR, OV7660_BLUE_GAIN, 0x80},
+ {SENSOR, OV7660_RED_GAIN, 0x80},
+
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x01},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}
+};
+
+#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c
index fc4548fd441d..e0ec7a6ffa6c 100644
--- a/drivers/media/video/gspca/m5602/m5602_ov9650.c
+++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c
@@ -18,12 +18,41 @@
#include "m5602_ov9650.h"
+static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev,
+ __s32 *val);
+static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
+ __s32 val);
+static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val);
+
/* Vertically and horizontally flips the image if matched, needed for machines
where the sensor is mounted upside down */
static
const
struct dmi_system_id ov9650_flip_dmi_table[] = {
{
+ .ident = "ASUS A6VA",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "A6VA")
+ }
+ },
+ {
+
.ident = "ASUS A6VC",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
@@ -59,6 +88,13 @@ static
}
},
{
+ .ident = "ASUS A6K",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "A6K")
+ }
+ },
+ {
.ident = "Alienware Aurora m9700",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "alienware"),
@@ -68,7 +104,7 @@ static
{}
};
-const static struct ctrl ov9650_ctrls[] = {
+static const struct ctrl ov9650_ctrls[] = {
#define EXPOSURE_IDX 0
{
{
@@ -102,6 +138,7 @@ const static struct ctrl ov9650_ctrls[] = {
#define RED_BALANCE_IDX 2
{
{
+ .id = V4L2_CID_RED_BALANCE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "red balance",
.minimum = 0x00,
@@ -116,6 +153,7 @@ const static struct ctrl ov9650_ctrls[] = {
#define BLUE_BALANCE_IDX 3
{
{
+ .id = V4L2_CID_BLUE_BALANCE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "blue balance",
.minimum = 0x00,
@@ -182,7 +220,22 @@ const static struct ctrl ov9650_ctrls[] = {
},
.set = ov9650_set_auto_gain,
.get = ov9650_get_auto_gain
+ },
+#define AUTO_EXPOSURE_IDX 8
+ {
+ {
+ .id = V4L2_CID_EXPOSURE_AUTO,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "auto exposure",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1
+ },
+ .set = ov9650_set_auto_exposure,
+ .get = ov9650_get_auto_exposure
}
+
};
static struct v4l2_pix_format ov9650_modes[] = {
@@ -289,12 +342,6 @@ sensor_found:
for (i = 0; i < ARRAY_SIZE(ov9650_ctrls); i++)
sensor_settings[i] = ov9650_ctrls[i].qctrl.default_value;
sd->sensor_priv = sensor_settings;
-
- if (dmi_check_system(ov9650_flip_dmi_table) && !err) {
- info("vflip quirk active");
- sensor_settings[VFLIP_IDX] = 1;
- }
-
return 0;
}
@@ -316,7 +363,8 @@ int ov9650_init(struct sd *sd)
err = m5602_write_bridge(sd, init_ov9650[i][1], data);
}
- err = ov9650_set_exposure(&sd->gspca_dev, sensor_settings[EXPOSURE_IDX]);
+ err = ov9650_set_exposure(&sd->gspca_dev,
+ sensor_settings[EXPOSURE_IDX]);
if (err < 0)
return err;
@@ -324,11 +372,13 @@ int ov9650_init(struct sd *sd)
if (err < 0)
return err;
- err = ov9650_set_red_balance(&sd->gspca_dev, sensor_settings[RED_BALANCE_IDX]);
+ err = ov9650_set_red_balance(&sd->gspca_dev,
+ sensor_settings[RED_BALANCE_IDX]);
if (err < 0)
return err;
- err = ov9650_set_blue_balance(&sd->gspca_dev, sensor_settings[BLUE_BALANCE_IDX]);
+ err = ov9650_set_blue_balance(&sd->gspca_dev,
+ sensor_settings[BLUE_BALANCE_IDX]);
if (err < 0)
return err;
@@ -340,11 +390,18 @@ int ov9650_init(struct sd *sd)
if (err < 0)
return err;
- err = ov9650_set_auto_white_balance(&sd->gspca_dev, sensor_settings[AUTO_WHITE_BALANCE_IDX]);
+ err = ov9650_set_auto_exposure(&sd->gspca_dev,
+ sensor_settings[AUTO_EXPOSURE_IDX]);
if (err < 0)
return err;
- err = ov9650_set_auto_gain(&sd->gspca_dev, sensor_settings[AUTO_GAIN_CTRL_IDX]);
+ err = ov9650_set_auto_white_balance(&sd->gspca_dev,
+ sensor_settings[AUTO_WHITE_BALANCE_IDX]);
+ if (err < 0)
+ return err;
+
+ err = ov9650_set_auto_gain(&sd->gspca_dev,
+ sensor_settings[AUTO_GAIN_CTRL_IDX]);
return err;
}
@@ -360,7 +417,10 @@ int ov9650_start(struct sd *sd)
int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
int hor_offs = OV9650_LEFT_OFFSET;
- if (sensor_settings[VFLIP_IDX])
+ if ((!dmi_check_system(ov9650_flip_dmi_table) &&
+ sensor_settings[VFLIP_IDX]) ||
+ (dmi_check_system(ov9650_flip_dmi_table) &&
+ !sensor_settings[VFLIP_IDX]))
ver_offs--;
if (width <= 320)
@@ -406,6 +466,14 @@ int ov9650_start(struct sd *sd)
if (err < 0)
return err;
+ err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
+ if (err < 0)
+ return err;
+
err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
(hor_offs >> 8) & 0xff);
if (err < 0)
@@ -425,6 +493,10 @@ int ov9650_start(struct sd *sd)
if (err < 0)
return err;
+ err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
+ if (err < 0)
+ return err;
+
switch (width) {
case 640:
PDEBUG(D_V4L2, "Configuring camera for VGA mode");
@@ -467,32 +539,15 @@ int ov9650_stop(struct sd *sd)
return m5602_write_sensor(sd, OV9650_COM2, &data, 1);
}
-int ov9650_power_down(struct sd *sd)
-{
- int i, err = 0;
- for (i = 0; i < ARRAY_SIZE(power_down_ov9650) && !err; i++) {
- u8 data = power_down_ov9650[i][2];
- if (power_down_ov9650[i][0] == SENSOR)
- err = m5602_write_sensor(sd,
- power_down_ov9650[i][1], &data, 1);
- else
- err = m5602_write_bridge(sd, power_down_ov9650[i][1],
- data);
- }
-
- return err;
-}
-
void ov9650_disconnect(struct sd *sd)
{
ov9650_stop(sd);
- ov9650_power_down(sd);
sd->sensor = NULL;
kfree(sd->sensor_priv);
}
-int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
s32 *sensor_settings = sd->sensor_priv;
@@ -502,7 +557,7 @@ int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
-int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
s32 *sensor_settings = sd->sensor_priv;
@@ -532,7 +587,7 @@ int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
return err;
}
-int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
s32 *sensor_settings = sd->sensor_priv;
@@ -542,7 +597,7 @@ int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
-int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
{
int err;
u8 i2c_data;
@@ -573,7 +628,7 @@ int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
return err;
}
-int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
+static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
s32 *sensor_settings = sd->sensor_priv;
@@ -583,7 +638,7 @@ int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
-int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
+static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
{
int err;
u8 i2c_data;
@@ -599,7 +654,7 @@ int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
return err;
}
-int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
+static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
s32 *sensor_settings = sd->sensor_priv;
@@ -610,7 +665,7 @@ int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
-int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
+static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
{
int err;
u8 i2c_data;
@@ -626,7 +681,7 @@ int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
return err;
}
-int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
s32 *sensor_settings = sd->sensor_priv;
@@ -636,7 +691,7 @@ int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
-int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
{
int err;
u8 i2c_data;
@@ -646,13 +701,20 @@ int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
sensor_settings[HFLIP_IDX] = val;
- i2c_data = ((val & 0x01) << 5) | (sensor_settings[VFLIP_IDX] << 4);
+
+ if (!dmi_check_system(ov9650_flip_dmi_table))
+ i2c_data = ((val & 0x01) << 5) |
+ (sensor_settings[VFLIP_IDX] << 4);
+ else
+ i2c_data = ((val & 0x01) << 5) |
+ (!sensor_settings[VFLIP_IDX] << 4);
+
err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
return err;
}
-int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
s32 *sensor_settings = sd->sensor_priv;
@@ -663,7 +725,7 @@ int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
-int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
{
int err;
u8 i2c_data;
@@ -673,6 +735,9 @@ int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
PDEBUG(D_V4L2, "Set vertical flip to %d", val);
sensor_settings[VFLIP_IDX] = val;
+ if (dmi_check_system(ov9650_flip_dmi_table))
+ val = !val;
+
i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5);
err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
if (err < 0)
@@ -685,48 +750,38 @@ int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
return err;
}
-int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
+static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
s32 *sensor_settings = sd->sensor_priv;
- *val = sensor_settings[GAIN_IDX];
- PDEBUG(D_V4L2, "Read gain %d", *val);
-
+ *val = sensor_settings[AUTO_EXPOSURE_IDX];
+ PDEBUG(D_V4L2, "Read auto exposure control %d", *val);
return 0;
}
-int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
+static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev,
+ __s32 val)
{
int err;
u8 i2c_data;
struct sd *sd = (struct sd *) gspca_dev;
s32 *sensor_settings = sd->sensor_priv;
- PDEBUG(D_V4L2, "Set gain to %d", val);
-
- sensor_settings[GAIN_IDX] = val;
+ PDEBUG(D_V4L2, "Set auto exposure control to %d", val);
- /* Read the OV9650_VREF register first to avoid
- corrupting the VREF high and low bits */
- err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
- if (err < 0)
- return err;
-
- /* Mask away all uninteresting bits */
- i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F);
- err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
+ sensor_settings[AUTO_EXPOSURE_IDX] = val;
+ err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
if (err < 0)
return err;
- /* The 8 LSBs */
- i2c_data = val & 0xff;
- err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
+ i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
- return err;
+ return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
}
-int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val)
+static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev,
+ __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
s32 *sensor_settings = sd->sensor_priv;
@@ -735,7 +790,8 @@ int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
-int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val)
+static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
+ __s32 val)
{
int err;
u8 i2c_data;
@@ -755,7 +811,7 @@ int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val)
return err;
}
-int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
+static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
s32 *sensor_settings = sd->sensor_priv;
@@ -765,7 +821,7 @@ int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
-int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
+static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
{
int err;
u8 i2c_data;
@@ -780,9 +836,8 @@ int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
return err;
i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
- err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
- return err;
+ return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
}
static void ov9650_dump_registers(struct sd *sd)
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.h b/drivers/media/video/gspca/m5602/m5602_ov9650.h
index fcc54e4c0f4f..c98c40d69e05 100644
--- a/drivers/media/video/gspca/m5602/m5602_ov9650.h
+++ b/drivers/media/video/gspca/m5602/m5602_ov9650.h
@@ -120,6 +120,10 @@
#define OV9650_SOFT_SLEEP (1 << 4)
#define OV9650_OUTPUT_DRIVE_2X (1 << 0)
+#define OV9650_DENOISE_ENABLE (1 << 5)
+#define OV9650_WHITE_PIXEL_ENABLE (1 << 1)
+#define OV9650_WHITE_PIXEL_OPTION (1 << 0)
+
#define OV9650_LEFT_OFFSET 0x62
#define GAIN_DEFAULT 0x14
@@ -137,29 +141,9 @@ int ov9650_probe(struct sd *sd);
int ov9650_init(struct sd *sd);
int ov9650_start(struct sd *sd);
int ov9650_stop(struct sd *sd);
-int ov9650_power_down(struct sd *sd);
void ov9650_disconnect(struct sd *sd);
-int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
-int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
-int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
-int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
-int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
-int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
-int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
-int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
-int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
-int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val);
-int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val);
-int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
-int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
-
-const static struct m5602_sensor ov9650 = {
+static const struct m5602_sensor ov9650 = {
.name = "OV9650",
.i2c_slave_id = 0x60,
.i2c_regW = 1,
@@ -167,7 +151,6 @@ const static struct m5602_sensor ov9650 = {
.init = ov9650_init,
.start = ov9650_start,
.stop = ov9650_stop,
- .power_down = ov9650_power_down,
.disconnect = ov9650_disconnect,
};
@@ -219,7 +202,7 @@ static const unsigned char init_ov9650[][3] =
/* Reset chip */
{SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
/* One extra reset is needed in order to make the sensor behave
- properly when resuming from ram */
+ properly when resuming from ram, could be a timing issue */
{SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
/* Enable double clock */
@@ -229,8 +212,7 @@ static const unsigned char init_ov9650[][3] =
/* Set fast AGC/AEC algorithm with unlimited step size */
{SENSOR, OV9650_COM8, OV9650_FAST_AGC_AEC |
- OV9650_AEC_UNLIM_STEP_SIZE |
- OV9650_AWB_EN | OV9650_AGC_EN},
+ OV9650_AEC_UNLIM_STEP_SIZE},
{SENSOR, OV9650_CHLF, 0x10},
{SENSOR, OV9650_ARBLM, 0xbf},
@@ -301,8 +283,11 @@ static const unsigned char init_ov9650[][3] =
{SENSOR, OV9650_VREF, 0x10},
{SENSOR, OV9650_ADC, 0x04},
{SENSOR, OV9650_HV, 0x40},
+
/* Enable denoise, and white-pixel erase */
- {SENSOR, OV9650_COM22, 0x23},
+ {SENSOR, OV9650_COM22, OV9650_DENOISE_ENABLE |
+ OV9650_WHITE_PIXEL_ENABLE |
+ OV9650_WHITE_PIXEL_OPTION},
/* Enable VARIOPIXEL */
{SENSOR, OV9650_COM3, OV9650_VARIOPIXEL},
@@ -312,26 +297,6 @@ static const unsigned char init_ov9650[][3] =
{SENSOR, OV9650_COM2, OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X},
};
-static const unsigned char power_down_ov9650[][3] =
-{
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
- {SENSOR, OV9650_COM7, 0x80},
- {SENSOR, OV9650_OFON, 0xf4},
- {SENSOR, OV9650_MVFP, 0x80},
- {SENSOR, OV9650_DBLV, 0x3f},
- {SENSOR, OV9650_RSVD36, 0x49},
- {SENSOR, OV9650_COM7, 0x05},
-
- {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
- {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
- {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
- {BRIDGE, M5602_XB_GPIO_EN_L, 0x06},
- {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-};
-
static const unsigned char res_init_ov9650[][3] =
{
{SENSOR, OV9650_COM2, OV9650_OUTPUT_DRIVE_2X},
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.c b/drivers/media/video/gspca/m5602/m5602_po1030.c
index eaddf488bad1..8d74d8065b79 100644
--- a/drivers/media/video/gspca/m5602/m5602_po1030.c
+++ b/drivers/media/video/gspca/m5602/m5602_po1030.c
@@ -18,6 +18,29 @@
#include "m5602_po1030.h"
+static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
+ __s32 val);
+static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
+ __s32 *val);
+static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
+ __s32 val);
+static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
+ __s32 *val);
+
static struct v4l2_pix_format po1030_modes[] = {
{
640,
@@ -27,11 +50,12 @@ static struct v4l2_pix_format po1030_modes[] = {
.sizeimage = 640 * 480,
.bytesperline = 640,
.colorspace = V4L2_COLORSPACE_SRGB,
- .priv = 0
+ .priv = 2
}
};
-const static struct ctrl po1030_ctrls[] = {
+static const struct ctrl po1030_ctrls[] = {
+#define GAIN_IDX 0
{
{
.id = V4L2_CID_GAIN,
@@ -45,7 +69,9 @@ const static struct ctrl po1030_ctrls[] = {
},
.set = po1030_set_gain,
.get = po1030_get_gain
- }, {
+ },
+#define EXPOSURE_IDX 1
+ {
{
.id = V4L2_CID_EXPOSURE,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -58,7 +84,9 @@ const static struct ctrl po1030_ctrls[] = {
},
.set = po1030_set_exposure,
.get = po1030_get_exposure
- }, {
+ },
+#define RED_BALANCE_IDX 2
+ {
{
.id = V4L2_CID_RED_BALANCE,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -71,7 +99,9 @@ const static struct ctrl po1030_ctrls[] = {
},
.set = po1030_set_red_balance,
.get = po1030_get_red_balance
- }, {
+ },
+#define BLUE_BALANCE_IDX 3
+ {
{
.id = V4L2_CID_BLUE_BALANCE,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -84,7 +114,9 @@ const static struct ctrl po1030_ctrls[] = {
},
.set = po1030_set_blue_balance,
.get = po1030_get_blue_balance
- }, {
+ },
+#define HFLIP_IDX 4
+ {
{
.id = V4L2_CID_HFLIP,
.type = V4L2_CTRL_TYPE_BOOLEAN,
@@ -96,7 +128,9 @@ const static struct ctrl po1030_ctrls[] = {
},
.set = po1030_set_hflip,
.get = po1030_get_hflip
- }, {
+ },
+#define VFLIP_IDX 5
+ {
{
.id = V4L2_CID_VFLIP,
.type = V4L2_CTRL_TYPE_BOOLEAN,
@@ -108,14 +142,58 @@ const static struct ctrl po1030_ctrls[] = {
},
.set = po1030_set_vflip,
.get = po1030_get_vflip
- }
+ },
+#define AUTO_WHITE_BALANCE_IDX 6
+ {
+ {
+ .id = V4L2_CID_AUTO_WHITE_BALANCE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "auto white balance",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ .set = po1030_set_auto_white_balance,
+ .get = po1030_get_auto_white_balance
+ },
+#define AUTO_EXPOSURE_IDX 7
+ {
+ {
+ .id = V4L2_CID_EXPOSURE_AUTO,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "auto exposure",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ .set = po1030_set_auto_exposure,
+ .get = po1030_get_auto_exposure
+ },
+#define GREEN_BALANCE_IDX 8
+ {
+ {
+ .id = M5602_V4L2_CID_GREEN_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "green balance",
+ .minimum = 0x00,
+ .maximum = 0xff,
+ .step = 0x1,
+ .default_value = PO1030_GREEN_GAIN_DEFAULT,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .set = po1030_set_green_balance,
+ .get = po1030_get_green_balance
+ },
};
static void po1030_dump_registers(struct sd *sd);
int po1030_probe(struct sd *sd)
{
- u8 prod_id = 0, ver_id = 0, i;
+ u8 dev_id_h = 0, i;
+ s32 *sensor_settings;
if (force_sensor) {
if (force_sensor == PO1030_SENSOR) {
@@ -139,28 +217,36 @@ int po1030_probe(struct sd *sd)
m5602_write_bridge(sd, preinit_po1030[i][1], data);
}
- if (m5602_read_sensor(sd, 0x3, &prod_id, 1))
+ if (m5602_read_sensor(sd, PO1030_DEVID_H, &dev_id_h, 1))
return -ENODEV;
- if (m5602_read_sensor(sd, 0x4, &ver_id, 1))
- return -ENODEV;
-
- if ((prod_id == 0x02) && (ver_id == 0xef)) {
+ if (dev_id_h == 0x30) {
info("Detected a po1030 sensor");
goto sensor_found;
}
return -ENODEV;
sensor_found:
+ sensor_settings = kmalloc(
+ ARRAY_SIZE(po1030_ctrls) * sizeof(s32), GFP_KERNEL);
+ if (!sensor_settings)
+ return -ENOMEM;
+
sd->gspca_dev.cam.cam_mode = po1030_modes;
sd->gspca_dev.cam.nmodes = ARRAY_SIZE(po1030_modes);
sd->desc->ctrls = po1030_ctrls;
sd->desc->nctrls = ARRAY_SIZE(po1030_ctrls);
+
+ for (i = 0; i < ARRAY_SIZE(po1030_ctrls); i++)
+ sensor_settings[i] = po1030_ctrls[i].qctrl.default_value;
+ sd->sensor_priv = sensor_settings;
+
return 0;
}
int po1030_init(struct sd *sd)
{
+ s32 *sensor_settings = sd->sensor_priv;
int i, err = 0;
/* Init the sensor */
@@ -185,47 +271,206 @@ int po1030_init(struct sd *sd)
return -EINVAL;
}
}
+ if (err < 0)
+ return err;
if (dump_sensor)
po1030_dump_registers(sd);
+ err = po1030_set_exposure(&sd->gspca_dev,
+ sensor_settings[EXPOSURE_IDX]);
+ if (err < 0)
+ return err;
+
+ err = po1030_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
+ if (err < 0)
+ return err;
+
+ err = po1030_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
+ if (err < 0)
+ return err;
+
+ err = po1030_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
+ if (err < 0)
+ return err;
+
+ err = po1030_set_red_balance(&sd->gspca_dev,
+ sensor_settings[RED_BALANCE_IDX]);
+ if (err < 0)
+ return err;
+
+ err = po1030_set_blue_balance(&sd->gspca_dev,
+ sensor_settings[BLUE_BALANCE_IDX]);
+ if (err < 0)
+ return err;
+
+ err = po1030_set_green_balance(&sd->gspca_dev,
+ sensor_settings[GREEN_BALANCE_IDX]);
+ if (err < 0)
+ return err;
+
+ err = po1030_set_auto_white_balance(&sd->gspca_dev,
+ sensor_settings[AUTO_WHITE_BALANCE_IDX]);
+ if (err < 0)
+ return err;
+
+ err = po1030_set_auto_exposure(&sd->gspca_dev,
+ sensor_settings[AUTO_EXPOSURE_IDX]);
return err;
}
-int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+int po1030_start(struct sd *sd)
{
- struct sd *sd = (struct sd *) gspca_dev;
- u8 i2c_data;
- int err;
+ struct cam *cam = &sd->gspca_dev.cam;
+ int i, err = 0;
+ int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
+ int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
+ int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
+ u8 data;
+
+ switch (width) {
+ case 320:
+ data = PO1030_SUBSAMPLING;
+ err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1);
+ if (err < 0)
+ return err;
+
+ data = ((width + 3) >> 8) & 0xff;
+ err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1);
+ if (err < 0)
+ return err;
+
+ data = (width + 3) & 0xff;
+ err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1);
+ if (err < 0)
+ return err;
+
+ data = ((height + 1) >> 8) & 0xff;
+ err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1);
+ if (err < 0)
+ return err;
+
+ data = (height + 1) & 0xff;
+ err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1);
+
+ height += 6;
+ width -= 1;
+ break;
+
+ case 640:
+ data = 0;
+ err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1);
+ if (err < 0)
+ return err;
+
+ data = ((width + 7) >> 8) & 0xff;
+ err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1);
+ if (err < 0)
+ return err;
+
+ data = (width + 7) & 0xff;
+ err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1);
+ if (err < 0)
+ return err;
+
+ data = ((height + 3) >> 8) & 0xff;
+ err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1);
+ if (err < 0)
+ return err;
+
+ data = (height + 3) & 0xff;
+ err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1);
+
+ height += 12;
+ width -= 2;
+ break;
+ }
+ err = m5602_write_bridge(sd, M5602_XB_SENSOR_TYPE, 0x0c);
+ if (err < 0)
+ return err;
- err = m5602_read_sensor(sd, PO1030_REG_INTEGLINES_H,
- &i2c_data, 1);
+ err = m5602_write_bridge(sd, M5602_XB_LINE_OF_FRAME_H, 0x81);
if (err < 0)
return err;
- *val = (i2c_data << 8);
- err = m5602_read_sensor(sd, PO1030_REG_INTEGLINES_M,
- &i2c_data, 1);
- *val |= i2c_data;
+ err = m5602_write_bridge(sd, M5602_XB_PIX_OF_LINE_H, 0x82);
+ if (err < 0)
+ return err;
- PDEBUG(D_V4L2, "Exposure read as %d", *val);
+ err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0x01);
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
+ ((ver_offs >> 8) & 0xff));
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
+ if (err < 0)
+ return err;
+
+ for (i = 0; i < 2 && !err; i++)
+ err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
+ if (err < 0)
+ return err;
+
+ for (i = 0; i < 2 && !err; i++)
+ err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
+
+ for (i = 0; i < 2 && !err; i++)
+ err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
+
+ for (i = 0; i < 2 && !err; i++)
+ err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0);
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width >> 8) & 0xff);
+ if (err < 0)
+ return err;
+ err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width & 0xff));
+ if (err < 0)
+ return err;
+
+ err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
return err;
}
-int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ *val = sensor_settings[EXPOSURE_IDX];
+ PDEBUG(D_V4L2, "Exposure read as %d", *val);
+ return 0;
+}
+
+static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
u8 i2c_data;
int err;
+ sensor_settings[EXPOSURE_IDX] = val;
PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff);
i2c_data = ((val & 0xff00) >> 8);
PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x",
i2c_data);
- err = m5602_write_sensor(sd, PO1030_REG_INTEGLINES_H,
+ err = m5602_write_sensor(sd, PO1030_INTEGLINES_H,
&i2c_data, 1);
if (err < 0)
return err;
@@ -233,167 +478,256 @@ int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
i2c_data = (val & 0xff);
PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x",
i2c_data);
- err = m5602_write_sensor(sd, PO1030_REG_INTEGLINES_M,
+ err = m5602_write_sensor(sd, PO1030_INTEGLINES_M,
&i2c_data, 1);
return err;
}
-int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
- u8 i2c_data;
- int err;
+ s32 *sensor_settings = sd->sensor_priv;
- err = m5602_read_sensor(sd, PO1030_REG_GLOBALGAIN,
- &i2c_data, 1);
- *val = i2c_data;
+ *val = sensor_settings[GAIN_IDX];
PDEBUG(D_V4L2, "Read global gain %d", *val);
-
- return err;
+ return 0;
}
-int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
u8 i2c_data;
int err;
- err = m5602_read_sensor(sd, PO1030_REG_CONTROL2,
+ sensor_settings[GAIN_IDX] = val;
+
+ i2c_data = val & 0xff;
+ PDEBUG(D_V4L2, "Set global gain to %d", i2c_data);
+ err = m5602_write_sensor(sd, PO1030_GLOBALGAIN,
&i2c_data, 1);
+ return err;
+}
- *val = (i2c_data >> 7) & 0x01 ;
+static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+ *val = sensor_settings[HFLIP_IDX];
PDEBUG(D_V4L2, "Read hflip %d", *val);
- return err;
+ return 0;
}
-int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
u8 i2c_data;
int err;
+ sensor_settings[HFLIP_IDX] = val;
+
PDEBUG(D_V4L2, "Set hflip %d", val);
- err = m5602_read_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1);
+ err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
if (err < 0)
return err;
i2c_data = (0x7f & i2c_data) | ((val & 0x01) << 7);
- err = m5602_write_sensor(sd, PO1030_REG_CONTROL2,
+ err = m5602_write_sensor(sd, PO1030_CONTROL2,
&i2c_data, 1);
return err;
}
-int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
- u8 i2c_data;
- int err;
-
- err = m5602_read_sensor(sd, PO1030_REG_GLOBALGAIN,
- &i2c_data, 1);
-
- *val = (i2c_data >> 6) & 0x01;
+ s32 *sensor_settings = sd->sensor_priv;
+ *val = sensor_settings[VFLIP_IDX];
PDEBUG(D_V4L2, "Read vflip %d", *val);
- return err;
+ return 0;
}
-int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
u8 i2c_data;
int err;
+ sensor_settings[VFLIP_IDX] = val;
+
PDEBUG(D_V4L2, "Set vflip %d", val);
- err = m5602_read_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1);
+ err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
if (err < 0)
return err;
i2c_data = (i2c_data & 0xbf) | ((val & 0x01) << 6);
- err = m5602_write_sensor(sd, PO1030_REG_CONTROL2,
+ err = m5602_write_sensor(sd, PO1030_CONTROL2,
&i2c_data, 1);
return err;
}
-int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ *val = sensor_settings[RED_BALANCE_IDX];
+ PDEBUG(D_V4L2, "Read red gain %d", *val);
+ return 0;
+}
+
+static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
u8 i2c_data;
int err;
+ sensor_settings[RED_BALANCE_IDX] = val;
+
i2c_data = val & 0xff;
- PDEBUG(D_V4L2, "Set global gain to %d", i2c_data);
- err = m5602_write_sensor(sd, PO1030_REG_GLOBALGAIN,
+ PDEBUG(D_V4L2, "Set red gain to %d", i2c_data);
+ err = m5602_write_sensor(sd, PO1030_RED_GAIN,
&i2c_data, 1);
return err;
}
-int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
+static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
- u8 i2c_data;
- int err;
+ s32 *sensor_settings = sd->sensor_priv;
- err = m5602_read_sensor(sd, PO1030_REG_RED_GAIN,
- &i2c_data, 1);
- *val = i2c_data;
- PDEBUG(D_V4L2, "Read red gain %d", *val);
- return err;
+ *val = sensor_settings[BLUE_BALANCE_IDX];
+ PDEBUG(D_V4L2, "Read blue gain %d", *val);
+
+ return 0;
}
-int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
+static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
u8 i2c_data;
int err;
+ sensor_settings[BLUE_BALANCE_IDX] = val;
+
i2c_data = val & 0xff;
- PDEBUG(D_V4L2, "Set red gain to %d", i2c_data);
- err = m5602_write_sensor(sd, PO1030_REG_RED_GAIN,
+ PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data);
+ err = m5602_write_sensor(sd, PO1030_BLUE_GAIN,
&i2c_data, 1);
+
return err;
}
-int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
+static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ *val = sensor_settings[GREEN_BALANCE_IDX];
+ PDEBUG(D_V4L2, "Read green gain %d", *val);
+
+ return 0;
+}
+
+static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
u8 i2c_data;
int err;
- err = m5602_read_sensor(sd, PO1030_REG_BLUE_GAIN,
+ sensor_settings[GREEN_BALANCE_IDX] = val;
+ i2c_data = val & 0xff;
+ PDEBUG(D_V4L2, "Set green gain to %d", i2c_data);
+
+ err = m5602_write_sensor(sd, PO1030_GREEN_1_GAIN,
+ &i2c_data, 1);
+ if (err < 0)
+ return err;
+
+ return m5602_write_sensor(sd, PO1030_GREEN_2_GAIN,
&i2c_data, 1);
- *val = i2c_data;
- PDEBUG(D_V4L2, "Read blue gain %d", *val);
+}
- return err;
+static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
+ __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
+ PDEBUG(D_V4L2, "Auto white balancing is %d", *val);
+
+ return 0;
}
-int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
+static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
+ __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
u8 i2c_data;
int err;
- i2c_data = val & 0xff;
- PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data);
- err = m5602_write_sensor(sd, PO1030_REG_BLUE_GAIN,
- &i2c_data, 1);
+ sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
+
+ err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
+ if (err < 0)
+ return err;
+
+ PDEBUG(D_V4L2, "Set auto white balance to %d", val);
+ i2c_data = (i2c_data & 0xfe) | (val & 0x01);
+ err = m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
return err;
}
-int po1030_power_down(struct sd *sd)
+static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
+ __s32 *val)
{
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ *val = sensor_settings[AUTO_EXPOSURE_IDX];
+ PDEBUG(D_V4L2, "Auto exposure is %d", *val);
return 0;
}
+static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
+ __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+ u8 i2c_data;
+ int err;
+
+ sensor_settings[AUTO_EXPOSURE_IDX] = val;
+ err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
+ if (err < 0)
+ return err;
+
+ PDEBUG(D_V4L2, "Set auto exposure to %d", val);
+ i2c_data = (i2c_data & 0xfd) | ((val & 0x01) << 1);
+ return m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
+}
+
+void po1030_disconnect(struct sd *sd)
+{
+ sd->sensor = NULL;
+ kfree(sd->sensor_priv);
+}
+
static void po1030_dump_registers(struct sd *sd)
{
int address;
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.h b/drivers/media/video/gspca/m5602/m5602_po1030.h
index c10b12335818..1ea380b2bbe7 100644
--- a/drivers/media/video/gspca/m5602/m5602_po1030.h
+++ b/drivers/media/video/gspca/m5602/m5602_po1030.h
@@ -25,98 +25,123 @@
/*****************************************************************************/
-#define PO1030_REG_DEVID_H 0x00
-#define PO1030_REG_DEVID_L 0x01
-#define PO1030_REG_FRAMEWIDTH_H 0x04
-#define PO1030_REG_FRAMEWIDTH_L 0x05
-#define PO1030_REG_FRAMEHEIGHT_H 0x06
-#define PO1030_REG_FRAMEHEIGHT_L 0x07
-#define PO1030_REG_WINDOWX_H 0x08
-#define PO1030_REG_WINDOWX_L 0x09
-#define PO1030_REG_WINDOWY_H 0x0a
-#define PO1030_REG_WINDOWY_L 0x0b
-#define PO1030_REG_WINDOWWIDTH_H 0x0c
-#define PO1030_REG_WINDOWWIDTH_L 0x0d
-#define PO1030_REG_WINDOWHEIGHT_H 0x0e
-#define PO1030_REG_WINDOWHEIGHT_L 0x0f
-
-#define PO1030_REG_GLOBALIBIAS 0x12
-#define PO1030_REG_PIXELIBIAS 0x13
-
-#define PO1030_REG_GLOBALGAIN 0x15
-#define PO1030_REG_RED_GAIN 0x16
-#define PO1030_REG_GREEN_1_GAIN 0x17
-#define PO1030_REG_BLUE_GAIN 0x18
-#define PO1030_REG_GREEN_2_GAIN 0x19
-
-#define PO1030_REG_INTEGLINES_H 0x1a
-#define PO1030_REG_INTEGLINES_M 0x1b
-#define PO1030_REG_INTEGLINES_L 0x1c
-
-#define PO1030_REG_CONTROL1 0x1d
-#define PO1030_REG_CONTROL2 0x1e
-#define PO1030_REG_CONTROL3 0x1f
-#define PO1030_REG_CONTROL4 0x20
-
-#define PO1030_REG_PERIOD50_H 0x23
-#define PO1030_REG_PERIOD50_L 0x24
-#define PO1030_REG_PERIOD60_H 0x25
-#define PO1030_REG_PERIOD60_L 0x26
-#define PO1030_REG_REGCLK167 0x27
-#define PO1030_REG_DELTA50 0x28
-#define PO1030_REG_DELTA60 0x29
-
-#define PO1030_REG_ADCOFFSET 0x2c
+#define PO1030_DEVID_H 0x00
+#define PO1030_DEVID_L 0x01
+#define PO1030_FRAMEWIDTH_H 0x04
+#define PO1030_FRAMEWIDTH_L 0x05
+#define PO1030_FRAMEHEIGHT_H 0x06
+#define PO1030_FRAMEHEIGHT_L 0x07
+#define PO1030_WINDOWX_H 0x08
+#define PO1030_WINDOWX_L 0x09
+#define PO1030_WINDOWY_H 0x0a
+#define PO1030_WINDOWY_L 0x0b
+#define PO1030_WINDOWWIDTH_H 0x0c
+#define PO1030_WINDOWWIDTH_L 0x0d
+#define PO1030_WINDOWHEIGHT_H 0x0e
+#define PO1030_WINDOWHEIGHT_L 0x0f
+
+#define PO1030_GLOBALIBIAS 0x12
+#define PO1030_PIXELIBIAS 0x13
+
+#define PO1030_GLOBALGAIN 0x15
+#define PO1030_RED_GAIN 0x16
+#define PO1030_GREEN_1_GAIN 0x17
+#define PO1030_BLUE_GAIN 0x18
+#define PO1030_GREEN_2_GAIN 0x19
+
+#define PO1030_INTEGLINES_H 0x1a
+#define PO1030_INTEGLINES_M 0x1b
+#define PO1030_INTEGLINES_L 0x1c
+
+#define PO1030_CONTROL1 0x1d
+#define PO1030_CONTROL2 0x1e
+#define PO1030_CONTROL3 0x1f
+#define PO1030_CONTROL4 0x20
+
+#define PO1030_PERIOD50_H 0x23
+#define PO1030_PERIOD50_L 0x24
+#define PO1030_PERIOD60_H 0x25
+#define PO1030_PERIOD60_L 0x26
+#define PO1030_REGCLK167 0x27
+#define PO1030_FLICKER_DELTA50 0x28
+#define PO1030_FLICKERDELTA60 0x29
+
+#define PO1030_ADCOFFSET 0x2c
/* Gamma Correction Coeffs */
-#define PO1030_REG_GC0 0x2d
-#define PO1030_REG_GC1 0x2e
-#define PO1030_REG_GC2 0x2f
-#define PO1030_REG_GC3 0x30
-#define PO1030_REG_GC4 0x31
-#define PO1030_REG_GC5 0x32
-#define PO1030_REG_GC6 0x33
-#define PO1030_REG_GC7 0x34
+#define PO1030_GC0 0x2d
+#define PO1030_GC1 0x2e
+#define PO1030_GC2 0x2f
+#define PO1030_GC3 0x30
+#define PO1030_GC4 0x31
+#define PO1030_GC5 0x32
+#define PO1030_GC6 0x33
+#define PO1030_GC7 0x34
/* Color Transform Matrix */
-#define PO1030_REG_CT0 0x35
-#define PO1030_REG_CT1 0x36
-#define PO1030_REG_CT2 0x37
-#define PO1030_REG_CT3 0x38
-#define PO1030_REG_CT4 0x39
-#define PO1030_REG_CT5 0x3a
-#define PO1030_REG_CT6 0x3b
-#define PO1030_REG_CT7 0x3c
-#define PO1030_REG_CT8 0x3d
-
-#define PO1030_REG_AUTOCTRL1 0x3e
-#define PO1030_REG_AUTOCTRL2 0x3f
-
-#define PO1030_REG_YTARGET 0x40
-#define PO1030_REG_GLOBALGAINMIN 0x41
-#define PO1030_REG_GLOBALGAINMAX 0x42
+#define PO1030_CT0 0x35
+#define PO1030_CT1 0x36
+#define PO1030_CT2 0x37
+#define PO1030_CT3 0x38
+#define PO1030_CT4 0x39
+#define PO1030_CT5 0x3a
+#define PO1030_CT6 0x3b
+#define PO1030_CT7 0x3c
+#define PO1030_CT8 0x3d
+
+#define PO1030_AUTOCTRL1 0x3e
+#define PO1030_AUTOCTRL2 0x3f
+
+#define PO1030_YTARGET 0x40
+#define PO1030_GLOBALGAINMIN 0x41
+#define PO1030_GLOBALGAINMAX 0x42
+
+#define PO1030_AWB_RED_TUNING 0x47
+#define PO1030_AWB_BLUE_TUNING 0x48
/* Output format control */
-#define PO1030_REG_OUTFORMCTRL1 0x5a
-#define PO1030_REG_OUTFORMCTRL2 0x5b
-#define PO1030_REG_OUTFORMCTRL3 0x5c
-#define PO1030_REG_OUTFORMCTRL4 0x5d
-#define PO1030_REG_OUTFORMCTRL5 0x5e
+#define PO1030_OUTFORMCTRL1 0x5a
+#define PO1030_OUTFORMCTRL2 0x5b
+#define PO1030_OUTFORMCTRL3 0x5c
+#define PO1030_OUTFORMCTRL4 0x5d
+#define PO1030_OUTFORMCTRL5 0x5e
-/* Imaging coefficients */
-#define PO1030_REG_YBRIGHT 0x73
-#define PO1030_REG_YCONTRAST 0x74
-#define PO1030_REG_YSATURATION 0x75
+#define PO1030_EDGE_ENH_OFF 0x5f
+#define PO1030_EGA 0x60
-#define PO1030_HFLIP (1 << 7)
-#define PO1030_VFLIP (1 << 6)
+#define PO1030_Cb_U_GAIN 0x63
+#define PO1030_Cr_V_GAIN 0x64
+
+#define PO1030_YCONTRAST 0x74
+#define PO1030_YSATURATION 0x75
+
+#define PO1030_HFLIP (1 << 7)
+#define PO1030_VFLIP (1 << 6)
+
+#define PO1030_HREF_ENABLE (1 << 6)
+
+#define PO1030_RAW_RGB_BAYER 0x4
+
+#define PO1030_FRAME_EQUAL (1 << 3)
+#define PO1030_AUTO_SUBSAMPLING (1 << 4)
+
+#define PO1030_WEIGHT_WIN_2X (1 << 3)
+
+#define PO1030_SHUTTER_MODE (1 << 6)
+#define PO1030_AUTO_SUBSAMPLING (1 << 4)
+#define PO1030_FRAME_EQUAL (1 << 3)
+
+#define PO1030_SENSOR_RESET (1 << 5)
+
+#define PO1030_SUBSAMPLING (1 << 6)
/*****************************************************************************/
#define PO1030_GLOBAL_GAIN_DEFAULT 0x12
#define PO1030_EXPOSURE_DEFAULT 0x0085
-#define PO1030_BLUE_GAIN_DEFAULT 0x40
-#define PO1030_RED_GAIN_DEFAULT 0x40
+#define PO1030_BLUE_GAIN_DEFAULT 0x36
+#define PO1030_RED_GAIN_DEFAULT 0x36
+#define PO1030_GREEN_GAIN_DEFAULT 0x40
/*****************************************************************************/
@@ -126,20 +151,8 @@ extern int dump_sensor;
int po1030_probe(struct sd *sd);
int po1030_init(struct sd *sd);
-int po1030_power_down(struct sd *sd);
-
-int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
-int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
-int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
-int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
-int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
-int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
-int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
-int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+int po1030_start(struct sd *sd);
+void po1030_disconnect(struct sd *sd);
static const struct m5602_sensor po1030 = {
.name = "PO1030",
@@ -149,7 +162,8 @@ static const struct m5602_sensor po1030 = {
.probe = po1030_probe,
.init = po1030_init,
- .power_down = po1030_power_down,
+ .start = po1030_start,
+ .disconnect = po1030_disconnect,
};
static const unsigned char preinit_po1030[][3] =
@@ -159,248 +173,103 @@ static const unsigned char preinit_po1030[][3] =
{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
- {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
{BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
- {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
-
- {SENSOR, PO1030_REG_AUTOCTRL2, 0x24},
-
- {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
- {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
- {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
- {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
- {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
- {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
- {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81},
- {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
- {BRIDGE, M5602_XB_SIG_INI, 0x01},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x02},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0xec},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x02},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x87},
- {BRIDGE, M5602_XB_SIG_INI, 0x00},
-
- {SENSOR, PO1030_REG_AUTOCTRL2, 0x24},
-
{BRIDGE, M5602_XB_GPIO_DIR, 0x05},
{BRIDGE, M5602_XB_GPIO_DAT, 0x04},
{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
{BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
{BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
+
+ {SENSOR, PO1030_AUTOCTRL2, PO1030_SENSOR_RESET | (1 << 2)},
+
{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
- {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
{BRIDGE, M5602_XB_GPIO_DIR, 0x05},
{BRIDGE, M5602_XB_GPIO_DAT, 0x00}
};
-static const unsigned char init_po1030[][4] =
+static const unsigned char init_po1030[][3] =
{
{BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
{BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
- /*sequence 1*/
{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
- {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
-
{BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
- {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
- /*end of sequence 1*/
-
- /*sequence 2 (same as stop sequence)*/
- {SENSOR, PO1030_REG_AUTOCTRL2, 0x24},
- {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
- {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
- {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
- {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
- {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
-
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
- /*end of sequence 2*/
- /*sequence 5*/
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
- {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
- {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
- {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81},
- {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
- {BRIDGE, M5602_XB_SIG_INI, 0x01},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x02},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0xec},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x02},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x87},
- {BRIDGE, M5602_XB_SIG_INI, 0x00},
- /*end of sequence 5*/
-
- /*sequence 2 stop */
- {SENSOR, PO1030_REG_AUTOCTRL2, 0x24},
+ {SENSOR, PO1030_AUTOCTRL2, PO1030_SENSOR_RESET | (1 << 2)},
{BRIDGE, M5602_XB_GPIO_DIR, 0x05},
{BRIDGE, M5602_XB_GPIO_DAT, 0x04},
{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
{BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
{BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
- /*end of sequence 2 stop */
-
-/* ---------------------------------
- * end of init - begin of start
- * --------------------------------- */
-
- /*sequence 3*/
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
- {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
- {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
- /*end of sequence 3*/
- /*sequence 4*/
{BRIDGE, M5602_XB_GPIO_DIR, 0x05},
{BRIDGE, M5602_XB_GPIO_DAT, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
- {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
- {SENSOR, PO1030_REG_AUTOCTRL2, 0x04},
+ {SENSOR, PO1030_AUTOCTRL2, 0x04},
+
+ {SENSOR, PO1030_OUTFORMCTRL2, PO1030_RAW_RGB_BAYER},
+ {SENSOR, PO1030_AUTOCTRL1, PO1030_WEIGHT_WIN_2X},
+
+ {SENSOR, PO1030_CONTROL2, 0x03},
+ {SENSOR, 0x21, 0x90},
+ {SENSOR, PO1030_YTARGET, 0x60},
+ {SENSOR, 0x59, 0x13},
+ {SENSOR, PO1030_OUTFORMCTRL1, PO1030_HREF_ENABLE},
+ {SENSOR, PO1030_EDGE_ENH_OFF, 0x00},
+ {SENSOR, PO1030_EGA, 0x80},
+ {SENSOR, 0x78, 0x14},
+ {SENSOR, 0x6f, 0x01},
+ {SENSOR, PO1030_GLOBALGAINMAX, 0x14},
+ {SENSOR, PO1030_Cb_U_GAIN, 0x38},
+ {SENSOR, PO1030_Cr_V_GAIN, 0x38},
+ {SENSOR, PO1030_CONTROL1, PO1030_SHUTTER_MODE |
+ PO1030_AUTO_SUBSAMPLING |
+ PO1030_FRAME_EQUAL},
+ {SENSOR, PO1030_GC0, 0x10},
+ {SENSOR, PO1030_GC1, 0x20},
+ {SENSOR, PO1030_GC2, 0x40},
+ {SENSOR, PO1030_GC3, 0x60},
+ {SENSOR, PO1030_GC4, 0x80},
+ {SENSOR, PO1030_GC5, 0xa0},
+ {SENSOR, PO1030_GC6, 0xc0},
+ {SENSOR, PO1030_GC7, 0xff},
/* Set the width to 751 */
- {SENSOR, PO1030_REG_FRAMEWIDTH_H, 0x02},
- {SENSOR, PO1030_REG_FRAMEWIDTH_L, 0xef},
+ {SENSOR, PO1030_FRAMEWIDTH_H, 0x02},
+ {SENSOR, PO1030_FRAMEWIDTH_L, 0xef},
/* Set the height to 540 */
- {SENSOR, PO1030_REG_FRAMEHEIGHT_H, 0x02},
- {SENSOR, PO1030_REG_FRAMEHEIGHT_L, 0x1c},
+ {SENSOR, PO1030_FRAMEHEIGHT_H, 0x02},
+ {SENSOR, PO1030_FRAMEHEIGHT_L, 0x1c},
/* Set the x window to 1 */
- {SENSOR, PO1030_REG_WINDOWX_H, 0x00},
- {SENSOR, PO1030_REG_WINDOWX_L, 0x01},
+ {SENSOR, PO1030_WINDOWX_H, 0x00},
+ {SENSOR, PO1030_WINDOWX_L, 0x01},
/* Set the y window to 1 */
- {SENSOR, PO1030_REG_WINDOWY_H, 0x00},
- {SENSOR, PO1030_REG_WINDOWY_L, 0x01},
-
- {SENSOR, PO1030_REG_WINDOWWIDTH_H, 0x02},
- {SENSOR, PO1030_REG_WINDOWWIDTH_L, 0x87},
- {SENSOR, PO1030_REG_WINDOWHEIGHT_H, 0x01},
- {SENSOR, PO1030_REG_WINDOWHEIGHT_L, 0xe3},
-
- {SENSOR, PO1030_REG_OUTFORMCTRL2, 0x04},
- {SENSOR, PO1030_REG_OUTFORMCTRL2, 0x04},
- {SENSOR, PO1030_REG_AUTOCTRL1, 0x08},
- {SENSOR, PO1030_REG_CONTROL2, 0x03},
- {SENSOR, 0x21, 0x90},
- {SENSOR, PO1030_REG_YTARGET, 0x60},
- {SENSOR, 0x59, 0x13},
- {SENSOR, PO1030_REG_OUTFORMCTRL1, 0x40},
- {SENSOR, 0x5f, 0x00},
- {SENSOR, 0x60, 0x80},
- {SENSOR, 0x78, 0x14},
- {SENSOR, 0x6f, 0x01},
- {SENSOR, PO1030_REG_CONTROL1, 0x18},
- {SENSOR, PO1030_REG_GLOBALGAINMAX, 0x14},
- {SENSOR, 0x63, 0x38},
- {SENSOR, 0x64, 0x38},
- {SENSOR, PO1030_REG_CONTROL1, 0x58},
- {SENSOR, PO1030_REG_RED_GAIN, 0x30},
- {SENSOR, PO1030_REG_GREEN_1_GAIN, 0x30},
- {SENSOR, PO1030_REG_BLUE_GAIN, 0x30},
- {SENSOR, PO1030_REG_GREEN_2_GAIN, 0x30},
- {SENSOR, PO1030_REG_GC0, 0x10},
- {SENSOR, PO1030_REG_GC1, 0x20},
- {SENSOR, PO1030_REG_GC2, 0x40},
- {SENSOR, PO1030_REG_GC3, 0x60},
- {SENSOR, PO1030_REG_GC4, 0x80},
- {SENSOR, PO1030_REG_GC5, 0xa0},
- {SENSOR, PO1030_REG_GC6, 0xc0},
- {SENSOR, PO1030_REG_GC7, 0xff},
- /*end of sequence 4*/
- /*sequence 5*/
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
- {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
- {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
- {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81},
- {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
- {BRIDGE, M5602_XB_SIG_INI, 0x01},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x02},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0xec},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x7e},
- {BRIDGE, M5602_XB_SIG_INI, 0x00},
- /*end of sequence 5*/
-
- /*sequence 6*/
- /* Changing 40 in f0 the image becomes green in bayer mode and red in
- * rgb mode */
- {SENSOR, PO1030_REG_RED_GAIN, PO1030_RED_GAIN_DEFAULT},
- /* in changing 40 in f0 the image becomes green in bayer mode and red in
- * rgb mode */
- {SENSOR, PO1030_REG_BLUE_GAIN, PO1030_BLUE_GAIN_DEFAULT},
+ {SENSOR, PO1030_WINDOWY_H, 0x00},
+ {SENSOR, PO1030_WINDOWY_L, 0x01},
/* with a very low lighted environment increase the exposure but
* decrease the FPS (Frame Per Second) */
{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
- /* Controls high exposure more than SENSOR_LOW_EXPOSURE, use only in
- * low lighted environment (f0 is more than ff ?)*/
- {SENSOR, PO1030_REG_INTEGLINES_H, ((PO1030_EXPOSURE_DEFAULT >> 2)
- & 0xff)},
-
- /* Controls middle exposure, use only in high lighted environment */
- {SENSOR, PO1030_REG_INTEGLINES_M, PO1030_EXPOSURE_DEFAULT & 0xff},
-
- /* Controls clarity (not sure) */
- {SENSOR, PO1030_REG_INTEGLINES_L, 0x00},
- /* Controls gain (the image is more lighted) */
- {SENSOR, PO1030_REG_GLOBALGAIN, PO1030_GLOBAL_GAIN_DEFAULT},
-
- /* Sets the width */
- {SENSOR, PO1030_REG_FRAMEWIDTH_H, 0x02},
- {SENSOR, PO1030_REG_FRAMEWIDTH_L, 0xef}
- /*end of sequence 6*/
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
};
#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
index 4306d596056d..e5fed5b89ff4 100644
--- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
+++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
@@ -18,6 +18,19 @@
#include "m5602_s5k4aa.h"
+static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
+
static
const
struct dmi_system_id s5k4aa_vflip_dmi_table[] = {
@@ -46,6 +59,12 @@ static
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
DMI_MATCH(DMI_PRODUCT_NAME, "GX700/GX705/EX700")
}
+ }, {
+ .ident = "MSI L735",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MS-1717X")
+ }
},
{ }
};
@@ -61,10 +80,22 @@ static struct v4l2_pix_format s5k4aa_modes[] = {
.bytesperline = 640,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 0
+ },
+ {
+ 1280,
+ 1024,
+ V4L2_PIX_FMT_SBGGR8,
+ V4L2_FIELD_NONE,
+ .sizeimage =
+ 1280 * 1024,
+ .bytesperline = 1280,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 0
}
};
-const static struct ctrl s5k4aa_ctrls[] = {
+static const struct ctrl s5k4aa_ctrls[] = {
+#define VFLIP_IDX 0
{
{
.id = V4L2_CID_VFLIP,
@@ -77,8 +108,9 @@ const static struct ctrl s5k4aa_ctrls[] = {
},
.set = s5k4aa_set_vflip,
.get = s5k4aa_get_vflip
-
- }, {
+ },
+#define HFLIP_IDX 1
+ {
{
.id = V4L2_CID_HFLIP,
.type = V4L2_CTRL_TYPE_BOOLEAN,
@@ -90,8 +122,9 @@ const static struct ctrl s5k4aa_ctrls[] = {
},
.set = s5k4aa_set_hflip,
.get = s5k4aa_get_hflip
-
- }, {
+ },
+#define GAIN_IDX 2
+ {
{
.id = V4L2_CID_GAIN,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -99,12 +132,14 @@ const static struct ctrl s5k4aa_ctrls[] = {
.minimum = 0,
.maximum = 127,
.step = 1,
- .default_value = 0xa0,
+ .default_value = S5K4AA_DEFAULT_GAIN,
.flags = V4L2_CTRL_FLAG_SLIDER
},
.set = s5k4aa_set_gain,
.get = s5k4aa_get_gain
- }, {
+ },
+#define EXPOSURE_IDX 3
+ {
{
.id = V4L2_CID_EXPOSURE,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -117,7 +152,36 @@ const static struct ctrl s5k4aa_ctrls[] = {
},
.set = s5k4aa_set_exposure,
.get = s5k4aa_get_exposure
- }
+ },
+#define NOISE_SUPP_IDX 4
+ {
+ {
+ .id = V4L2_CID_PRIVATE_BASE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Noise suppression (smoothing)",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ },
+ .set = s5k4aa_set_noise,
+ .get = s5k4aa_get_noise
+ },
+#define BRIGHTNESS_IDX 5
+ {
+ {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness",
+ .minimum = 0,
+ .maximum = 0x1f,
+ .step = 1,
+ .default_value = S5K4AA_DEFAULT_BRIGHTNESS,
+ },
+ .set = s5k4aa_set_brightness,
+ .get = s5k4aa_get_brightness
+ },
+
};
static void s5k4aa_dump_registers(struct sd *sd);
@@ -127,6 +191,7 @@ int s5k4aa_probe(struct sd *sd)
u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75};
int i, err = 0;
+ s32 *sensor_settings;
if (force_sensor) {
if (force_sensor == S5K4AA_SENSOR) {
@@ -185,10 +250,20 @@ int s5k4aa_probe(struct sd *sd)
info("Detected a s5k4aa sensor");
sensor_found:
+ sensor_settings = kmalloc(
+ ARRAY_SIZE(s5k4aa_ctrls) * sizeof(s32), GFP_KERNEL);
+ if (!sensor_settings)
+ return -ENOMEM;
+
sd->gspca_dev.cam.cam_mode = s5k4aa_modes;
sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k4aa_modes);
sd->desc->ctrls = s5k4aa_ctrls;
sd->desc->nctrls = ARRAY_SIZE(s5k4aa_ctrls);
+
+ for (i = 0; i < ARRAY_SIZE(s5k4aa_ctrls); i++)
+ sensor_settings[i] = s5k4aa_ctrls[i].qctrl.default_value;
+ sd->sensor_priv = sensor_settings;
+
return 0;
}
@@ -197,9 +272,45 @@ int s5k4aa_start(struct sd *sd)
int i, err = 0;
u8 data[2];
struct cam *cam = &sd->gspca_dev.cam;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) {
+ case 1280:
+ PDEBUG(D_V4L2, "Configuring camera for SXGA mode");
+
+ for (i = 0; i < ARRAY_SIZE(SXGA_s5k4aa); i++) {
+ switch (SXGA_s5k4aa[i][0]) {
+ case BRIDGE:
+ err = m5602_write_bridge(sd,
+ SXGA_s5k4aa[i][1],
+ SXGA_s5k4aa[i][2]);
+ break;
+
+ case SENSOR:
+ data[0] = SXGA_s5k4aa[i][2];
+ err = m5602_write_sensor(sd,
+ SXGA_s5k4aa[i][1],
+ data, 1);
+ break;
+
+ case SENSOR_LONG:
+ data[0] = SXGA_s5k4aa[i][2];
+ data[1] = SXGA_s5k4aa[i][3];
+ err = m5602_write_sensor(sd,
+ SXGA_s5k4aa[i][1],
+ data, 2);
+ break;
+
+ default:
+ err("Invalid stream command, exiting init");
+ return -EINVAL;
+ }
+ }
+ err = s5k4aa_set_noise(&sd->gspca_dev, 0);
+ if (err < 0)
+ return err;
+ break;
- switch (cam->cam_mode[sd->gspca_dev.curr_mode].width)
- {
case 640:
PDEBUG(D_V4L2, "Configuring camera for VGA mode");
@@ -231,8 +342,37 @@ int s5k4aa_start(struct sd *sd)
return -EINVAL;
}
}
+ err = s5k4aa_set_noise(&sd->gspca_dev, 1);
+ if (err < 0)
+ return err;
+ break;
}
- return err;
+ if (err < 0)
+ return err;
+
+ err = s5k4aa_set_exposure(&sd->gspca_dev,
+ sensor_settings[EXPOSURE_IDX]);
+ if (err < 0)
+ return err;
+
+ err = s5k4aa_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
+ if (err < 0)
+ return err;
+
+ err = s5k4aa_set_brightness(&sd->gspca_dev,
+ sensor_settings[BRIGHTNESS_IDX]);
+ if (err < 0)
+ return err;
+
+ err = s5k4aa_set_noise(&sd->gspca_dev, sensor_settings[NOISE_SUPP_IDX]);
+ if (err < 0)
+ return err;
+
+ err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
+ if (err < 0)
+ return err;
+
+ return s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
}
int s5k4aa_init(struct sd *sd)
@@ -270,62 +410,28 @@ int s5k4aa_init(struct sd *sd)
if (dump_sensor)
s5k4aa_dump_registers(sd);
- if (!err && dmi_check_system(s5k4aa_vflip_dmi_table)) {
- u8 data = 0x02;
- info("vertical flip quirk active");
- m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
- m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
- data |= S5K4AA_RM_V_FLIP;
- data &= ~S5K4AA_RM_H_FLIP;
- m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
-
- /* Decrement COLSTART to preserve color order (BGGR) */
- m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
- data--;
- m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
-
- /* Increment ROWSTART to preserve color order (BGGR) */
- m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
- data++;
- m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
- }
-
- return (err < 0) ? err : 0;
-}
-
-int s5k4aa_power_down(struct sd *sd)
-{
- return 0;
+ return err;
}
-int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
- u8 data = S5K4AA_PAGE_MAP_2;
- int err;
-
- err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
- if (err < 0)
- return err;
-
- err = m5602_read_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
- if (err < 0)
- return err;
+ s32 *sensor_settings = sd->sensor_priv;
- *val = data << 8;
- err = m5602_read_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
- *val |= data;
+ *val = sensor_settings[EXPOSURE_IDX];
PDEBUG(D_V4L2, "Read exposure %d", *val);
- return err;
+ return 0;
}
-int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
u8 data = S5K4AA_PAGE_MAP_2;
int err;
+ sensor_settings[EXPOSURE_IDX] = val;
PDEBUG(D_V4L2, "Set exposure to %d", val);
err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
if (err < 0)
@@ -340,29 +446,26 @@ int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
return err;
}
-int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
- u8 data = S5K4AA_PAGE_MAP_2;
- int err;
+ s32 *sensor_settings = sd->sensor_priv;
- err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
- if (err < 0)
- return err;
-
- err = m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
- *val = (data & S5K4AA_RM_V_FLIP) >> 7;
+ *val = sensor_settings[VFLIP_IDX];
PDEBUG(D_V4L2, "Read vertical flip %d", *val);
- return err;
+ return 0;
}
-int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
u8 data = S5K4AA_PAGE_MAP_2;
int err;
+ sensor_settings[VFLIP_IDX] = val;
+
PDEBUG(D_V4L2, "Set vertical flip to %d", val);
err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
if (err < 0)
@@ -370,56 +473,48 @@ int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
if (err < 0)
return err;
- data = ((data & ~S5K4AA_RM_V_FLIP)
- | ((val & 0x01) << 7));
- err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+
+ err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
if (err < 0)
return err;
- if (val) {
- err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
- if (err < 0)
- return err;
-
- data++;
- err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
- } else {
- err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
- if (err < 0)
- return err;
+ if (dmi_check_system(s5k4aa_vflip_dmi_table))
+ val = !val;
- data--;
- err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
- }
+ data = ((data & ~S5K4AA_RM_V_FLIP) | ((val & 0x01) << 7));
+ err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+ if (err < 0)
+ return err;
+ err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+ if (err < 0)
+ return err;
+ data = (data & 0xfe) | !val;
+ err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
return err;
}
-int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
- u8 data = S5K4AA_PAGE_MAP_2;
- int err;
-
- err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
- if (err < 0)
- return err;
+ s32 *sensor_settings = sd->sensor_priv;
- err = m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
- *val = (data & S5K4AA_RM_H_FLIP) >> 6;
+ *val = sensor_settings[HFLIP_IDX];
PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
- return err;
+ return 0;
}
-int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
u8 data = S5K4AA_PAGE_MAP_2;
int err;
- PDEBUG(D_V4L2, "Set horizontal flip to %d",
- val);
+ sensor_settings[HFLIP_IDX] = val;
+
+ PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
if (err < 0)
return err;
@@ -427,62 +522,116 @@ int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
if (err < 0)
return err;
+ err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+ if (err < 0)
+ return err;
+
+ if (dmi_check_system(s5k4aa_vflip_dmi_table))
+ val = !val;
+
data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6));
err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
if (err < 0)
return err;
- if (val) {
- err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
- if (err < 0)
- return err;
- data++;
- err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
- if (err < 0)
- return err;
- } else {
- err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
- if (err < 0)
- return err;
- data--;
- err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
- }
-
+ err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+ if (err < 0)
+ return err;
+ data = (data & 0xfe) | !val;
+ err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
return err;
}
-int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ *val = sensor_settings[GAIN_IDX];
+ PDEBUG(D_V4L2, "Read gain %d", *val);
+ return 0;
+}
+
+static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
u8 data = S5K4AA_PAGE_MAP_2;
int err;
+ sensor_settings[GAIN_IDX] = val;
+
+ PDEBUG(D_V4L2, "Set gain to %d", val);
err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
if (err < 0)
return err;
- err = m5602_read_sensor(sd, S5K4AA_GAIN_2, &data, 1);
- *val = data;
- PDEBUG(D_V4L2, "Read gain %d", *val);
+ data = val & 0xff;
+ err = m5602_write_sensor(sd, S5K4AA_GAIN, &data, 1);
return err;
}
-int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ *val = sensor_settings[BRIGHTNESS_IDX];
+ PDEBUG(D_V4L2, "Read brightness %d", *val);
+ return 0;
+}
+
+static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
u8 data = S5K4AA_PAGE_MAP_2;
int err;
- PDEBUG(D_V4L2, "Set gain to %d", val);
+ sensor_settings[BRIGHTNESS_IDX] = val;
+
+ PDEBUG(D_V4L2, "Set brightness to %d", val);
err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
if (err < 0)
return err;
data = val & 0xff;
- err = m5602_write_sensor(sd, S5K4AA_GAIN_2, &data, 1);
+ return m5602_write_sensor(sd, S5K4AA_BRIGHTNESS, &data, 1);
+}
- return err;
+static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ *val = sensor_settings[NOISE_SUPP_IDX];
+ PDEBUG(D_V4L2, "Read noise %d", *val);
+ return 0;
+}
+
+static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+ u8 data = S5K4AA_PAGE_MAP_2;
+ int err;
+
+ sensor_settings[NOISE_SUPP_IDX] = val;
+
+ PDEBUG(D_V4L2, "Set noise to %d", val);
+ err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ if (err < 0)
+ return err;
+
+ data = val & 0x01;
+ return m5602_write_sensor(sd, S5K4AA_NOISE_SUPP, &data, 1);
+}
+
+void s5k4aa_disconnect(struct sd *sd)
+{
+ sd->sensor = NULL;
+ kfree(sd->sensor_priv);
}
static void s5k4aa_dump_registers(struct sd *sd)
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h
index ca854d4f9475..4440da4e7f0f 100644
--- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.h
+++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h
@@ -47,8 +47,9 @@
#define S5K4AA_H_BLANK_LO__ 0x1e
#define S5K4AA_EXPOSURE_HI 0x17
#define S5K4AA_EXPOSURE_LO 0x18
-#define S5K4AA_GAIN_1 0x1f /* (digital?) gain : 5 bits */
-#define S5K4AA_GAIN_2 0x20 /* (analogue?) gain : 7 bits */
+#define S5K4AA_BRIGHTNESS 0x1f /* (digital?) gain : 5 bits */
+#define S5K4AA_GAIN 0x20 /* (analogue?) gain : 7 bits */
+#define S5K4AA_NOISE_SUPP 0x37
#define S5K4AA_RM_ROW_SKIP_4X 0x08
#define S5K4AA_RM_ROW_SKIP_2X 0x04
@@ -57,6 +58,9 @@
#define S5K4AA_RM_H_FLIP 0x40
#define S5K4AA_RM_V_FLIP 0x80
+#define S5K4AA_DEFAULT_GAIN 0x5f
+#define S5K4AA_DEFAULT_BRIGHTNESS 0x10
+
/*****************************************************************************/
/* Kernel module parameters */
@@ -66,25 +70,17 @@ extern int dump_sensor;
int s5k4aa_probe(struct sd *sd);
int s5k4aa_init(struct sd *sd);
int s5k4aa_start(struct sd *sd);
-int s5k4aa_power_down(struct sd *sd);
-
-int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
-int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
-int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
-int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+void s5k4aa_disconnect(struct sd *sd);
static const struct m5602_sensor s5k4aa = {
.name = "S5K4AA",
+ .i2c_slave_id = 0x5a,
+ .i2c_regW = 2,
+
.probe = s5k4aa_probe,
.init = s5k4aa_init,
.start = s5k4aa_start,
- .power_down = s5k4aa_power_down,
- .i2c_slave_id = 0x5a,
- .i2c_regW = 2,
+ .disconnect = s5k4aa_disconnect,
};
static const unsigned char preinit_s5k4aa[][4] =
@@ -179,30 +175,12 @@ static const unsigned char init_s5k4aa[][4] =
{SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
{SENSOR, 0x0c, 0x05, 0x00},
{SENSOR, 0x02, 0x0e, 0x00},
- {SENSOR, S5K4AA_GAIN_1, 0x0f, 0x00},
- {SENSOR, S5K4AA_GAIN_2, 0x00, 0x00},
- {SENSOR, S5K4AA_GLOBAL_GAIN__, 0x01, 0x00},
- {SENSOR, 0x11, 0x00, 0x00},
- {SENSOR, 0x12, 0x00, 0x00},
- {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
{SENSOR, S5K4AA_READ_MODE, 0xa0, 0x00},
{SENSOR, 0x37, 0x00, 0x00},
- {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00},
- {SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00},
- {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00},
- {SENSOR, S5K4AA_COLSTART_LO, 0x0b, 0x00},
- {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00},
- {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc4, 0x00},
- {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00},
- {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x08, 0x00},
- {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00},
- {SENSOR, S5K4AA_H_BLANK_LO__, 0x48, 0x00},
- {SENSOR, S5K4AA_EXPOSURE_HI, 0x00, 0x00},
- {SENSOR, S5K4AA_EXPOSURE_LO, 0x43, 0x00},
- {SENSOR, 0x11, 0x04, 0x00},
- {SENSOR, 0x12, 0xc3, 0x00},
- {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
+};
+static const unsigned char VGA_s5k4aa[][4] =
+{
{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
@@ -238,7 +216,7 @@ static const unsigned char init_s5k4aa[][4] =
{SENSOR, 0x37, 0x01, 0x00},
/* ROWSTART_HI, ROWSTART_LO : 10 + (1024-960)/2 = 42 = 0x002a */
{SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00},
- {SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00},
+ {SENSOR, S5K4AA_ROWSTART_LO, 0x29, 0x00},
{SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00},
{SENSOR, S5K4AA_COLSTART_LO, 0x0c, 0x00},
/* window_height_hi, window_height_lo : 960 = 0x03c0 */
@@ -255,12 +233,9 @@ static const unsigned char init_s5k4aa[][4] =
{SENSOR, 0x12, 0xc3, 0x00},
{SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
{SENSOR, 0x02, 0x0e, 0x00},
- {SENSOR_LONG, S5K4AA_GLOBAL_GAIN__, 0x0f, 0x00},
- {SENSOR, S5K4AA_GAIN_1, 0x0b, 0x00},
- {SENSOR, S5K4AA_GAIN_2, 0xa0, 0x00}
};
-static const unsigned char VGA_s5k4aa[][4] =
+static const unsigned char SXGA_s5k4aa[][4] =
{
{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
@@ -273,50 +248,42 @@ static const unsigned char VGA_s5k4aa[][4] =
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- /* VSYNC_PARA, VSYNC_PARA : img height 480 = 0x01e0 */
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00},
+ /* VSYNC_PARA, VSYNC_PARA : img height 1024 = 0x0400 */
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
{BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
- /* HSYNC_PARA, HSYNC_PARA : img width 640 = 0x0280 */
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x80, 0x00},
+ /* HSYNC_PARA, HSYNC_PARA : img width 1280 = 0x0500 */
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */
{SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
- {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP | S5K4AA_RM_ROW_SKIP_2X
- | S5K4AA_RM_COL_SKIP_2X, 0x00},
- /* 0x37 : Fix image stability when light is too bright and improves
- * image quality in 640x480, but worsens it in 1280x1024 */
+ {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP, 0x00},
{SENSOR, 0x37, 0x01, 0x00},
- /* ROWSTART_HI, ROWSTART_LO : 10 + (1024-960)/2 = 42 = 0x002a */
{SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00},
- {SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00},
+ {SENSOR, S5K4AA_ROWSTART_LO, 0x09, 0x00},
{SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00},
- {SENSOR, S5K4AA_COLSTART_LO, 0x0c, 0x00},
- /* window_height_hi, window_height_lo : 960 = 0x03c0 */
- {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00},
- {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc0, 0x00},
- /* window_width_hi, window_width_lo : 1280 = 0x0500 */
+ {SENSOR, S5K4AA_COLSTART_LO, 0x0a, 0x00},
+ {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x04, 0x00},
+ {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0x00, 0x00},
{SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00},
{SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00},
- {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00},
- {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00}, /* helps to sync... */
+ {SENSOR, S5K4AA_H_BLANK_HI__, 0x01, 0x00},
+ {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00},
{SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00},
{SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00},
{SENSOR, 0x11, 0x04, 0x00},
{SENSOR, 0x12, 0xc3, 0x00},
{SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
{SENSOR, 0x02, 0x0e, 0x00},
- {SENSOR_LONG, S5K4AA_GLOBAL_GAIN__, 0x0f, 0x00},
- {SENSOR, S5K4AA_GAIN_1, 0x0b, 0x00},
- {SENSOR, S5K4AA_GAIN_2, 0xa0, 0x00}
};
+
#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/drivers/media/video/gspca/m5602/m5602_s5k83a.c
index 42c86aa4dc8d..7127321ace8c 100644
--- a/drivers/media/video/gspca/m5602/m5602_s5k83a.c
+++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.c
@@ -16,8 +16,20 @@
*
*/
+#include <linux/kthread.h>
#include "m5602_s5k83a.h"
+static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+
static struct v4l2_pix_format s5k83a_modes[] = {
{
640,
@@ -32,68 +44,77 @@ static struct v4l2_pix_format s5k83a_modes[] = {
}
};
-const static struct ctrl s5k83a_ctrls[] = {
+static const struct ctrl s5k83a_ctrls[] = {
+#define GAIN_IDX 0
{
{
- .id = V4L2_CID_BRIGHTNESS,
+ .id = V4L2_CID_GAIN,
.type = V4L2_CTRL_TYPE_INTEGER,
- .name = "brightness",
+ .name = "gain",
.minimum = 0x00,
.maximum = 0xff,
.step = 0x01,
- .default_value = S5K83A_DEFAULT_BRIGHTNESS,
+ .default_value = S5K83A_DEFAULT_GAIN,
.flags = V4L2_CTRL_FLAG_SLIDER
},
- .set = s5k83a_set_brightness,
- .get = s5k83a_get_brightness
+ .set = s5k83a_set_gain,
+ .get = s5k83a_get_gain
- }, {
+ },
+#define BRIGHTNESS_IDX 1
+ {
{
- .id = V4L2_CID_WHITENESS,
+ .id = V4L2_CID_BRIGHTNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
- .name = "whiteness",
+ .name = "brightness",
.minimum = 0x00,
.maximum = 0xff,
.step = 0x01,
- .default_value = S5K83A_DEFAULT_WHITENESS,
+ .default_value = S5K83A_DEFAULT_BRIGHTNESS,
.flags = V4L2_CTRL_FLAG_SLIDER
},
- .set = s5k83a_set_whiteness,
- .get = s5k83a_get_whiteness,
- }, {
+ .set = s5k83a_set_brightness,
+ .get = s5k83a_get_brightness,
+ },
+#define EXPOSURE_IDX 2
+ {
{
- .id = V4L2_CID_GAIN,
+ .id = V4L2_CID_EXPOSURE,
.type = V4L2_CTRL_TYPE_INTEGER,
- .name = "gain",
+ .name = "exposure",
.minimum = 0x00,
- .maximum = S5K83A_MAXIMUM_GAIN,
+ .maximum = S5K83A_MAXIMUM_EXPOSURE,
.step = 0x01,
- .default_value = S5K83A_DEFAULT_GAIN,
+ .default_value = S5K83A_DEFAULT_EXPOSURE,
.flags = V4L2_CTRL_FLAG_SLIDER
},
- .set = s5k83a_set_gain,
- .get = s5k83a_get_gain
- }, {
+ .set = s5k83a_set_exposure,
+ .get = s5k83a_get_exposure
+ },
+#define HFLIP_IDX 3
+ {
{
- .id = V4L2_CID_HFLIP,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "horizontal flip",
- .minimum = 0,
- .maximum = 1,
- .step = 1,
- .default_value = 0
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "horizontal flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0
},
.set = s5k83a_set_hflip,
.get = s5k83a_get_hflip
- }, {
+ },
+#define VFLIP_IDX 4
+ {
{
- .id = V4L2_CID_VFLIP,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "vertical flip",
- .minimum = 0,
- .maximum = 1,
- .step = 1,
- .default_value = 0
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "vertical flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0
},
.set = s5k83a_set_vflip,
.get = s5k83a_get_vflip
@@ -101,9 +122,14 @@ const static struct ctrl s5k83a_ctrls[] = {
};
static void s5k83a_dump_registers(struct sd *sd);
+static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data);
+static int s5k83a_set_led_indication(struct sd *sd, u8 val);
+static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
+ __s32 vflip, __s32 hflip);
int s5k83a_probe(struct sd *sd)
{
+ struct s5k83a_priv *sens_priv;
u8 prod_id = 0, ver_id = 0;
int i, err = 0;
@@ -145,16 +171,36 @@ int s5k83a_probe(struct sd *sd)
info("Detected a s5k83a sensor");
sensor_found:
+ sens_priv = kmalloc(
+ sizeof(struct s5k83a_priv), GFP_KERNEL);
+ if (!sens_priv)
+ return -ENOMEM;
+
+ sens_priv->settings =
+ kmalloc(sizeof(s32)*ARRAY_SIZE(s5k83a_ctrls), GFP_KERNEL);
+ if (!sens_priv->settings)
+ return -ENOMEM;
+
sd->gspca_dev.cam.cam_mode = s5k83a_modes;
sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes);
sd->desc->ctrls = s5k83a_ctrls;
sd->desc->nctrls = ARRAY_SIZE(s5k83a_ctrls);
+
+ /* null the pointer! thread is't running now */
+ sens_priv->rotation_thread = NULL;
+
+ for (i = 0; i < ARRAY_SIZE(s5k83a_ctrls); i++)
+ sens_priv->settings[i] = s5k83a_ctrls[i].qctrl.default_value;
+
+ sd->sensor_priv = sens_priv;
return 0;
}
int s5k83a_init(struct sd *sd)
{
int i, err = 0;
+ s32 *sensor_settings =
+ ((struct s5k83a_priv *) sd->sensor_priv)->settings;
for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) {
u8 data[2] = {0x00, 0x00};
@@ -187,87 +233,138 @@ int s5k83a_init(struct sd *sd)
if (dump_sensor)
s5k83a_dump_registers(sd);
- return (err < 0) ? err : 0;
-}
+ err = s5k83a_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
+ if (err < 0)
+ return err;
-int s5k83a_start(struct sd *sd)
-{
- return s5k83a_set_led_indication(sd, 1);
-}
+ err = s5k83a_set_brightness(&sd->gspca_dev,
+ sensor_settings[BRIGHTNESS_IDX]);
+ if (err < 0)
+ return err;
-int s5k83a_stop(struct sd *sd)
-{
- return s5k83a_set_led_indication(sd, 0);
+ err = s5k83a_set_exposure(&sd->gspca_dev,
+ sensor_settings[EXPOSURE_IDX]);
+ if (err < 0)
+ return err;
+
+ err = s5k83a_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
+ if (err < 0)
+ return err;
+
+ err = s5k83a_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
+
+ return err;
}
-int s5k83a_power_down(struct sd *sd)
+static int rotation_thread_function(void *data)
{
+ struct sd *sd = (struct sd *) data;
+ struct s5k83a_priv *sens_priv = sd->sensor_priv;
+ u8 reg, previous_rotation = 0;
+ __s32 vflip, hflip;
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ while (!schedule_timeout(100)) {
+ if (mutex_lock_interruptible(&sd->gspca_dev.usb_lock))
+ break;
+
+ s5k83a_get_rotation(sd, &reg);
+ if (previous_rotation != reg) {
+ previous_rotation = reg;
+ info("Camera was flipped");
+
+ s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
+ s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
+
+ if (reg) {
+ vflip = !vflip;
+ hflip = !hflip;
+ }
+ s5k83a_set_flip_real((struct gspca_dev *) sd,
+ vflip, hflip);
+ }
+
+ mutex_unlock(&sd->gspca_dev.usb_lock);
+ set_current_state(TASK_INTERRUPTIBLE);
+ }
+
+ /* return to "front" flip */
+ if (previous_rotation) {
+ s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
+ s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
+ s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip);
+ }
+
+ sens_priv->rotation_thread = NULL;
return 0;
}
-static void s5k83a_dump_registers(struct sd *sd)
+int s5k83a_start(struct sd *sd)
{
- int address;
- u8 page, old_page;
- m5602_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
+ int i, err = 0;
+ struct s5k83a_priv *sens_priv = sd->sensor_priv;
- for (page = 0; page < 16; page++) {
- m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
- info("Dumping the s5k83a register state for page 0x%x", page);
- for (address = 0; address <= 0xff; address++) {
- u8 val = 0;
- m5602_read_sensor(sd, address, &val, 1);
- info("register 0x%x contains 0x%x",
- address, val);
- }
+ /* Create another thread, polling the GPIO ports of the camera to check
+ if it got rotated. This is how the windows driver does it so we have
+ to assume that there is no better way of accomplishing this */
+ sens_priv->rotation_thread = kthread_create(rotation_thread_function,
+ sd, "rotation thread");
+ wake_up_process(sens_priv->rotation_thread);
+
+ /* Preinit the sensor */
+ for (i = 0; i < ARRAY_SIZE(start_s5k83a) && !err; i++) {
+ u8 data[2] = {start_s5k83a[i][2], start_s5k83a[i][3]};
+ if (start_s5k83a[i][0] == SENSOR)
+ err = m5602_write_sensor(sd, start_s5k83a[i][1],
+ data, 2);
+ else
+ err = m5602_write_bridge(sd, start_s5k83a[i][1],
+ data[0]);
}
- info("s5k83a register state dump complete");
+ if (err < 0)
+ return err;
- for (page = 0; page < 16; page++) {
- m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
- info("Probing for which registers that are read/write "
- "for page 0x%x", page);
- for (address = 0; address <= 0xff; address++) {
- u8 old_val, ctrl_val, test_val = 0xff;
+ return s5k83a_set_led_indication(sd, 1);
+}
- m5602_read_sensor(sd, address, &old_val, 1);
- m5602_write_sensor(sd, address, &test_val, 1);
- m5602_read_sensor(sd, address, &ctrl_val, 1);
+int s5k83a_stop(struct sd *sd)
+{
+ struct s5k83a_priv *sens_priv = sd->sensor_priv;
- if (ctrl_val == test_val)
- info("register 0x%x is writeable", address);
- else
- info("register 0x%x is read only", address);
+ if (sens_priv->rotation_thread)
+ kthread_stop(sens_priv->rotation_thread);
- /* Restore original val */
- m5602_write_sensor(sd, address, &old_val, 1);
- }
- }
- info("Read/write register probing complete");
- m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
+ return s5k83a_set_led_indication(sd, 0);
}
-int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
+void s5k83a_disconnect(struct sd *sd)
{
- int err;
- u8 data[2];
- struct sd *sd = (struct sd *) gspca_dev;
+ struct s5k83a_priv *sens_priv = sd->sensor_priv;
- err = m5602_read_sensor(sd, S5K83A_BRIGHTNESS, data, 2);
- if (err < 0)
- return err;
+ s5k83a_stop(sd);
+
+ sd->sensor = NULL;
+ kfree(sens_priv->settings);
+ kfree(sens_priv);
+}
- data[1] = data[1] << 1;
- *val = data[1];
+static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct s5k83a_priv *sens_priv = sd->sensor_priv;
- return err;
+ *val = sens_priv->settings[GAIN_IDX];
+ return 0;
}
-int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
{
int err;
u8 data[2];
struct sd *sd = (struct sd *) gspca_dev;
+ struct s5k83a_priv *sens_priv = sd->sensor_priv;
+
+ sens_priv->settings[GAIN_IDX] = val;
data[0] = 0x00;
data[1] = 0x20;
@@ -283,89 +380,69 @@ int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
/* FIXME: This is not sane, we need to figure out the composition
of these registers */
- data[0] = val >> 3; /* brightness, high 5 bits */
- data[1] = val >> 1; /* brightness, high 7 bits */
- err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 2);
+ data[0] = val >> 3; /* gain, high 5 bits */
+ data[1] = val >> 1; /* gain, high 7 bits */
+ err = m5602_write_sensor(sd, S5K83A_GAIN, data, 2);
return err;
}
-int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val)
+static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
{
- int err;
- u8 data;
struct sd *sd = (struct sd *) gspca_dev;
+ struct s5k83a_priv *sens_priv = sd->sensor_priv;
- err = m5602_read_sensor(sd, S5K83A_WHITENESS, &data, 1);
- if (err < 0)
- return err;
-
- *val = data;
-
- return err;
+ *val = sens_priv->settings[BRIGHTNESS_IDX];
+ return 0;
}
-int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
{
int err;
u8 data[1];
struct sd *sd = (struct sd *) gspca_dev;
+ struct s5k83a_priv *sens_priv = sd->sensor_priv;
+ sens_priv->settings[BRIGHTNESS_IDX] = val;
data[0] = val;
- err = m5602_write_sensor(sd, S5K83A_WHITENESS, data, 1);
-
+ err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 1);
return err;
}
-int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
{
- int err;
- u8 data[2];
struct sd *sd = (struct sd *) gspca_dev;
+ struct s5k83a_priv *sens_priv = sd->sensor_priv;
- err = m5602_read_sensor(sd, S5K83A_GAIN, data, 2);
- if (err < 0)
- return err;
-
- data[1] = data[1] & 0x3f;
- if (data[1] > S5K83A_MAXIMUM_GAIN)
- data[1] = S5K83A_MAXIMUM_GAIN;
-
- *val = data[1];
-
- return err;
+ *val = sens_priv->settings[EXPOSURE_IDX];
+ return 0;
}
-int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
{
int err;
u8 data[2];
struct sd *sd = (struct sd *) gspca_dev;
+ struct s5k83a_priv *sens_priv = sd->sensor_priv;
+ sens_priv->settings[EXPOSURE_IDX] = val;
data[0] = 0;
data[1] = val;
- err = m5602_write_sensor(sd, S5K83A_GAIN, data, 2);
+ err = m5602_write_sensor(sd, S5K83A_EXPOSURE, data, 2);
return err;
}
-int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
{
- int err;
- u8 data[1];
struct sd *sd = (struct sd *) gspca_dev;
+ struct s5k83a_priv *sens_priv = sd->sensor_priv;
- data[0] = 0x05;
- err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
- if (err < 0)
- return err;
-
- err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1);
- *val = (data[0] | 0x40) ? 1 : 0;
-
- return err;
+ *val = sens_priv->settings[VFLIP_IDX];
+ return 0;
}
-int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
+ __s32 vflip, __s32 hflip)
{
int err;
u8 data[1];
@@ -376,69 +453,83 @@ int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
if (err < 0)
return err;
- err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1);
- if (err < 0)
- return err;
+ /* six bit is vflip, seven is hflip */
+ data[0] = S5K83A_FLIP_MASK;
+ data[0] = (vflip) ? data[0] | 0x40 : data[0];
+ data[0] = (hflip) ? data[0] | 0x80 : data[0];
- /* set or zero six bit, seven is hflip */
- data[0] = (val) ? (data[0] & 0x80) | 0x40 | S5K83A_FLIP_MASK
- : (data[0] & 0x80) | S5K83A_FLIP_MASK;
err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1);
if (err < 0)
return err;
- data[0] = (val) ? 0x0b : 0x0a;
+ data[0] = (vflip) ? 0x0b : 0x0a;
err = m5602_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1);
+ if (err < 0)
+ return err;
+ data[0] = (hflip) ? 0x0a : 0x0b;
+ err = m5602_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1);
return err;
}
-int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
{
int err;
- u8 data[1];
+ u8 reg;
+ __s32 hflip;
struct sd *sd = (struct sd *) gspca_dev;
+ struct s5k83a_priv *sens_priv = sd->sensor_priv;
- data[0] = 0x05;
- err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
+ sens_priv->settings[VFLIP_IDX] = val;
+
+ s5k83a_get_hflip(gspca_dev, &hflip);
+
+ err = s5k83a_get_rotation(sd, &reg);
if (err < 0)
return err;
+ if (reg) {
+ val = !val;
+ hflip = !hflip;
+ }
- err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1);
- *val = (data[0] | 0x80) ? 1 : 0;
-
+ err = s5k83a_set_flip_real(gspca_dev, val, hflip);
return err;
}
-int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct s5k83a_priv *sens_priv = sd->sensor_priv;
+
+ *val = sens_priv->settings[HFLIP_IDX];
+ return 0;
+}
+
+static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
{
int err;
- u8 data[1];
+ u8 reg;
+ __s32 vflip;
struct sd *sd = (struct sd *) gspca_dev;
+ struct s5k83a_priv *sens_priv = sd->sensor_priv;
- data[0] = 0x05;
- err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
- if (err < 0)
- return err;
+ sens_priv->settings[HFLIP_IDX] = val;
- err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1);
- if (err < 0)
- return err;
+ s5k83a_get_vflip(gspca_dev, &vflip);
- /* set or zero seven bit, six is vflip */
- data[0] = (val) ? (data[0] & 0x40) | 0x80 | S5K83A_FLIP_MASK
- : (data[0] & 0x40) | S5K83A_FLIP_MASK;
- err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1);
+ err = s5k83a_get_rotation(sd, &reg);
if (err < 0)
return err;
+ if (reg) {
+ val = !val;
+ vflip = !vflip;
+ }
- data[0] = (val) ? 0x0a : 0x0b;
- err = m5602_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1);
-
+ err = s5k83a_set_flip_real(gspca_dev, vflip, val);
return err;
}
-int s5k83a_set_led_indication(struct sd *sd, u8 val)
+static int s5k83a_set_led_indication(struct sd *sd, u8 val)
{
int err = 0;
u8 data[1];
@@ -454,5 +545,55 @@ int s5k83a_set_led_indication(struct sd *sd, u8 val)
err = m5602_write_bridge(sd, M5602_XB_GPIO_DAT, data[0]);
- return (err < 0) ? err : 0;
+ return err;
+}
+
+/* Get camera rotation on Acer notebooks */
+static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data)
+{
+ int err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, reg_data);
+ *reg_data = (*reg_data & S5K83A_GPIO_ROTATION_MASK) ? 0 : 1;
+ return err;
+}
+
+static void s5k83a_dump_registers(struct sd *sd)
+{
+ int address;
+ u8 page, old_page;
+ m5602_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
+
+ for (page = 0; page < 16; page++) {
+ m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
+ info("Dumping the s5k83a register state for page 0x%x", page);
+ for (address = 0; address <= 0xff; address++) {
+ u8 val = 0;
+ m5602_read_sensor(sd, address, &val, 1);
+ info("register 0x%x contains 0x%x",
+ address, val);
+ }
+ }
+ info("s5k83a register state dump complete");
+
+ for (page = 0; page < 16; page++) {
+ m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
+ info("Probing for which registers that are read/write "
+ "for page 0x%x", page);
+ for (address = 0; address <= 0xff; address++) {
+ u8 old_val, ctrl_val, test_val = 0xff;
+
+ m5602_read_sensor(sd, address, &old_val, 1);
+ m5602_write_sensor(sd, address, &test_val, 1);
+ m5602_read_sensor(sd, address, &ctrl_val, 1);
+
+ if (ctrl_val == test_val)
+ info("register 0x%x is writeable", address);
+ else
+ info("register 0x%x is read only", address);
+
+ /* Restore original val */
+ m5602_write_sensor(sd, address, &old_val, 1);
+ }
+ }
+ info("Read/write register probing complete");
+ m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
}
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/drivers/media/video/gspca/m5602/m5602_s5k83a.h
index 819ab25272be..7814b078acde 100644
--- a/drivers/media/video/gspca/m5602/m5602_s5k83a.h
+++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.h
@@ -21,20 +21,21 @@
#include "m5602_sensor.h"
-#define S5K83A_FLIP 0x01
-#define S5K83A_HFLIP_TUNE 0x03
-#define S5K83A_VFLIP_TUNE 0x05
-#define S5K83A_WHITENESS 0x0a
-#define S5K83A_GAIN 0x18
-#define S5K83A_BRIGHTNESS 0x1b
-#define S5K83A_PAGE_MAP 0xec
-
-#define S5K83A_DEFAULT_BRIGHTNESS 0x71
-#define S5K83A_DEFAULT_WHITENESS 0x7e
-#define S5K83A_DEFAULT_GAIN 0x00
-#define S5K83A_MAXIMUM_GAIN 0x3c
-#define S5K83A_FLIP_MASK 0x10
+#define S5K83A_FLIP 0x01
+#define S5K83A_HFLIP_TUNE 0x03
+#define S5K83A_VFLIP_TUNE 0x05
+#define S5K83A_BRIGHTNESS 0x0a
+#define S5K83A_EXPOSURE 0x18
+#define S5K83A_GAIN 0x1b
+#define S5K83A_PAGE_MAP 0xec
+
+#define S5K83A_DEFAULT_GAIN 0x71
+#define S5K83A_DEFAULT_BRIGHTNESS 0x7e
+#define S5K83A_DEFAULT_EXPOSURE 0x00
+#define S5K83A_MAXIMUM_EXPOSURE 0x3c
+#define S5K83A_FLIP_MASK 0x10
#define S5K83A_GPIO_LED_MASK 0x10
+#define S5K83A_GPIO_ROTATION_MASK 0x40
/*****************************************************************************/
@@ -46,20 +47,7 @@ int s5k83a_probe(struct sd *sd);
int s5k83a_init(struct sd *sd);
int s5k83a_start(struct sd *sd);
int s5k83a_stop(struct sd *sd);
-int s5k83a_power_down(struct sd *sd);
-
-int s5k83a_set_led_indication(struct sd *sd, u8 val);
-
-int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
-int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
-int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val);
-int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val);
-int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+void s5k83a_disconnect(struct sd *sd);
static const struct m5602_sensor s5k83a = {
.name = "S5K83A",
@@ -67,11 +55,18 @@ static const struct m5602_sensor s5k83a = {
.init = s5k83a_init,
.start = s5k83a_start,
.stop = s5k83a_stop,
- .power_down = s5k83a_power_down,
+ .disconnect = s5k83a_disconnect,
.i2c_slave_id = 0x5a,
.i2c_regW = 2,
};
+struct s5k83a_priv {
+ /* We use another thread periodically
+ probing the orientation of the camera */
+ struct task_struct *rotation_thread;
+ s32 *settings;
+};
+
static const unsigned char preinit_s5k83a[][4] =
{
{BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
@@ -108,8 +103,6 @@ static const unsigned char preinit_s5k83a[][4] =
{BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
{BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
{BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
-
- {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00}
};
/* This could probably be considerably shortened.
@@ -117,86 +110,8 @@ static const unsigned char preinit_s5k83a[][4] =
*/
static const unsigned char init_s5k83a[][4] =
{
- {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00},
- {SENSOR, 0xaf, 0x01, 0x00},
- {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00},
- {SENSOR, 0x7b, 0xff, 0x00},
- {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
- {SENSOR, 0x01, 0x50, 0x00},
- {SENSOR, 0x12, 0x20, 0x00},
- {SENSOR, 0x17, 0x40, 0x00},
- {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00},
- {SENSOR, 0x1c, 0x00, 0x00},
- {SENSOR, 0x02, 0x70, 0x00},
- {SENSOR, 0x03, 0x0b, 0x00},
- {SENSOR, 0x04, 0xf0, 0x00},
- {SENSOR, 0x05, 0x0b, 0x00},
- {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
-
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
- {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
- {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
- {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-
- {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
- {SENSOR, 0x06, 0x71, 0x00},
- {SENSOR, 0x07, 0xe8, 0x00},
- {SENSOR, 0x08, 0x02, 0x00},
- {SENSOR, 0x09, 0x88, 0x00},
- {SENSOR, 0x14, 0x00, 0x00},
- {SENSOR, 0x15, 0x20, 0x00},
- {SENSOR, 0x19, 0x00, 0x00},
- {SENSOR, 0x1a, 0x98, 0x00},
- {SENSOR, 0x0f, 0x02, 0x00},
- {SENSOR, 0x10, 0xe5, 0x00},
- {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
- {SENSOR_LONG, 0x14, 0x00, 0x20},
- {SENSOR_LONG, 0x0d, 0x00, 0x7d},
- {SENSOR_LONG, 0x1b, 0x0d, 0x05},
-
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
- {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
- {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
- {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00},
-
- {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ /* The following sequence is useless after a clean boot
+ but is necessary after resume from suspend */
{BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
{BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
{BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
@@ -216,7 +131,7 @@ static const unsigned char init_s5k83a[][4] =
{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
{BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
{BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
{BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
{BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
@@ -225,109 +140,34 @@ static const unsigned char init_s5k83a[][4] =
{SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00},
{SENSOR, 0xaf, 0x01, 0x00},
- {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
- /* ff ( init value )is very dark) || 71 and f0 better */
+ {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00},
{SENSOR, 0x7b, 0xff, 0x00},
{SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
{SENSOR, 0x01, 0x50, 0x00},
{SENSOR, 0x12, 0x20, 0x00},
{SENSOR, 0x17, 0x40, 0x00},
- {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00},
{SENSOR, 0x1c, 0x00, 0x00},
{SENSOR, 0x02, 0x70, 0x00},
- /* some values like 0x10 give a blue-purple image */
{SENSOR, 0x03, 0x0b, 0x00},
{SENSOR, 0x04, 0xf0, 0x00},
{SENSOR, 0x05, 0x0b, 0x00},
- {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
-
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
- /* under 80 don't work, highter depend on value */
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-
- {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
- {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
- {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
- {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00},
-
- {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-
- {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
{SENSOR, 0x06, 0x71, 0x00},
- {SENSOR, 0x07, 0xe8, 0x00},
+ {SENSOR, 0x07, 0xe8, 0x00}, /* 488 */
{SENSOR, 0x08, 0x02, 0x00},
- {SENSOR, 0x09, 0x88, 0x00},
+ {SENSOR, 0x09, 0x88, 0x00}, /* 648 */
{SENSOR, 0x14, 0x00, 0x00},
- {SENSOR, 0x15, 0x20, 0x00},
+ {SENSOR, 0x15, 0x20, 0x00}, /* 32 */
{SENSOR, 0x19, 0x00, 0x00},
- {SENSOR, 0x1a, 0x98, 0x00},
+ {SENSOR, 0x1a, 0x98, 0x00}, /* 152 */
{SENSOR, 0x0f, 0x02, 0x00},
- {SENSOR, 0x10, 0xe5, 0x00},
- {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
- {SENSOR_LONG, 0x14, 0x00, 0x20},
- {SENSOR_LONG, 0x0d, 0x00, 0x7d},
- {SENSOR_LONG, 0x1b, 0x0d, 0x05},
-
- /* The following sequence is useless after a clean boot
- but is necessary after resume from suspend */
- {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
- {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
- {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
- {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
- {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
- {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
- {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
- {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
- {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
- {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
- {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
-
- {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00},
- {SENSOR, 0xaf, 0x01, 0x00},
- {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00},
- {SENSOR, 0x7b, 0xff, 0x00},
- {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
- {SENSOR, 0x01, 0x50, 0x00},
- {SENSOR, 0x12, 0x20, 0x00},
- {SENSOR, 0x17, 0x40, 0x00},
- {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00},
- {SENSOR, 0x1c, 0x00, 0x00},
- {SENSOR, 0x02, 0x70, 0x00},
- {SENSOR, 0x03, 0x0b, 0x00},
- {SENSOR, 0x04, 0xf0, 0x00},
- {SENSOR, 0x05, 0x0b, 0x00},
- {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+ {SENSOR, 0x10, 0xe5, 0x00}, /* 741 */
+ /* normal colors
+ (this is value after boot, but after tries can be different) */
+ {SENSOR, 0x00, 0x06, 0x00},
+};
+static const unsigned char start_s5k83a[][4] =
+{
{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
@@ -340,7 +180,7 @@ static const unsigned char init_s5k83a[][4] =
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, /* 484 */
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
@@ -348,50 +188,10 @@ static const unsigned char init_s5k83a[][4] =
{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
{BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, /* 639 */
{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-
- {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
- {SENSOR, 0x06, 0x71, 0x00},
- {SENSOR, 0x07, 0xe8, 0x00},
- {SENSOR, 0x08, 0x02, 0x00},
- {SENSOR, 0x09, 0x88, 0x00},
- {SENSOR, 0x14, 0x00, 0x00},
- {SENSOR, 0x15, 0x20, 0x00},
- {SENSOR, 0x19, 0x00, 0x00},
- {SENSOR, 0x1a, 0x98, 0x00},
- {SENSOR, 0x0f, 0x02, 0x00},
-
- {SENSOR, 0x10, 0xe5, 0x00},
- {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
- {SENSOR_LONG, 0x14, 0x00, 0x20},
- {SENSOR_LONG, 0x0d, 0x00, 0x7d},
- {SENSOR_LONG, 0x1b, 0x0d, 0x05},
-
- /* normal colors
- (this is value after boot, but after tries can be different) */
- {SENSOR, 0x00, 0x06, 0x00},
-
- /* set default brightness */
- {SENSOR_LONG, 0x14, 0x00, 0x20},
- {SENSOR_LONG, 0x0d, 0x01, 0x00},
- {SENSOR_LONG, 0x1b, S5K83A_DEFAULT_BRIGHTNESS >> 3,
- S5K83A_DEFAULT_BRIGHTNESS >> 1},
-
- /* set default whiteness */
- {SENSOR, S5K83A_WHITENESS, S5K83A_DEFAULT_WHITENESS, 0x00},
-
- /* set default gain */
- {SENSOR_LONG, 0x18, 0x00, S5K83A_DEFAULT_GAIN},
-
- /* set default flip */
- {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
- {SENSOR, S5K83A_FLIP, 0x00 | S5K83A_FLIP_MASK, 0x00},
- {SENSOR, S5K83A_HFLIP_TUNE, 0x0b, 0x00},
- {SENSOR, S5K83A_VFLIP_TUNE, 0x0a, 0x00}
-
};
#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_sensor.h b/drivers/media/video/gspca/m5602/m5602_sensor.h
index 0d3026936f2e..edff4f1f586f 100644
--- a/drivers/media/video/gspca/m5602/m5602_sensor.h
+++ b/drivers/media/video/gspca/m5602/m5602_sensor.h
@@ -21,13 +21,17 @@
#include "m5602_bridge.h"
+#define M5602_V4L2_CID_GREEN_BALANCE (V4L2_CID_PRIVATE_BASE + 0)
+#define M5602_V4L2_CID_NOISE_SUPPRESION (V4L2_CID_PRIVATE_BASE + 1)
+
/* Enumerates all supported sensors */
enum sensors {
OV9650_SENSOR = 1,
S5K83A_SENSOR = 2,
S5K4AA_SENSOR = 3,
MT9M111_SENSOR = 4,
- PO1030_SENSOR = 5
+ PO1030_SENSOR = 5,
+ OV7660_SENSOR = 6,
};
/* Enumerates all possible instruction types */
@@ -61,9 +65,6 @@ struct m5602_sensor {
/* Executed when the device is disconnected */
void (*disconnect)(struct sd *sd);
-
- /* Performs a power down sequence */
- int (*power_down)(struct sd *sd);
};
#endif
diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
index 2a901a4a6f00..30132513400c 100644
--- a/drivers/media/video/gspca/mr97310a.c
+++ b/drivers/media/video/gspca/mr97310a.c
@@ -321,6 +321,7 @@ static const struct sd_desc sd_desc = {
/* -- module initialisation -- */
static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x08ca, 0x0111)},
+ {USB_DEVICE(0x093a, 0x010f)},
{}
};
MODULE_DEVICE_TABLE(usb, device_table);
@@ -347,8 +348,11 @@ static struct usb_driver sd_driver = {
/* -- module insert / remove -- */
static int __init sd_mod_init(void)
{
- if (usb_register(&sd_driver) < 0)
- return -1;
+ int ret;
+
+ ret = usb_register(&sd_driver);
+ if (ret < 0)
+ return ret;
PDEBUG(D_PROBE, "registered");
return 0;
}
diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c
index 19e0bc60de14..6d9b102be70c 100644
--- a/drivers/media/video/gspca/ov534.c
+++ b/drivers/media/video/gspca/ov534.c
@@ -708,8 +708,11 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam->cam_mode = vga_mode;
cam->nmodes = ARRAY_SIZE(vga_mode);
- cam->bulk_size = 16384;
- cam->bulk_nurbs = 2;
+ if (sd->sensor == SENSOR_OV772X) {
+ cam->bulk = 1;
+ cam->bulk_size = 16384;
+ cam->bulk_nurbs = 2;
+ }
return 0;
}
@@ -864,18 +867,16 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame,
/* If PTS or FID has changed, start a new frame. */
if (this_pts != sd->last_pts || this_fid != sd->last_fid) {
- gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
- NULL, 0);
+ if (gspca_dev->last_packet_type == INTER_PACKET)
+ frame = gspca_frame_add(gspca_dev,
+ LAST_PACKET, frame,
+ NULL, 0);
sd->last_pts = this_pts;
sd->last_fid = this_fid;
- }
-
- /* Add the data from this payload */
- gspca_frame_add(gspca_dev, INTER_PACKET, frame,
+ gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
data + 12, len - 12);
-
/* If this packet is marked as EOF, end the frame */
- if (data[1] & UVC_STREAM_EOF) {
+ } else if (data[1] & UVC_STREAM_EOF) {
sd->last_pts = 0;
if (frame->data_end - frame->data !=
@@ -883,11 +884,16 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame,
PDEBUG(D_PACK, "short frame");
goto discard;
}
-
frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
- NULL, 0);
+ data + 12, len - 12);
+ } else {
+
+ /* Add the data from this payload */
+ gspca_frame_add(gspca_dev, INTER_PACKET, frame,
+ data + 12, len - 12);
}
+
/* Done this payload */
goto scan_next;
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
index 153d0a91d4b5..cf3af8de6e97 100644
--- a/drivers/media/video/gspca/sonixb.c
+++ b/drivers/media/video/gspca/sonixb.c
@@ -877,6 +877,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam->cam_mode = sif_mode;
cam->nmodes = ARRAY_SIZE(sif_mode);
}
+ cam->npkt = 36; /* 36 packets per ISOC message */
+
sd->brightness = BRIGHTNESS_DEF;
sd->gain = GAIN_DEF;
sd->exposure = EXPOSURE_DEF;
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
index c72e19d3ac37..dc6a6f11354a 100644
--- a/drivers/media/video/gspca/sonixj.c
+++ b/drivers/media/video/gspca/sonixj.c
@@ -62,7 +62,6 @@ struct sd {
#define BRIDGE_SN9C105 1
#define BRIDGE_SN9C110 2
#define BRIDGE_SN9C120 3
-#define BRIDGE_SN9C325 4
u8 sensor; /* Type of image sensor chip */
#define SENSOR_HV7131R 0
#define SENSOR_MI0360 1
@@ -354,9 +353,9 @@ static const u8 sn_ov7648[0x1c] = {
static const u8 sn_ov7660[0x1c] = {
/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
- 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
+ 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00,
/* reg8 reg9 rega regb regc regd rege regf */
- 0x81, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20,
/* reg18 reg19 reg1a reg1b */
@@ -757,6 +756,7 @@ static const u8 ov7660_sensor_init[][8] = {
{0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
{0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
{0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
+ {0xb1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10},
/****** (some exchanges in the win trace) ******/
{0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
/* bits[3..0]reserved */
@@ -1065,9 +1065,9 @@ static int configure_gpio(struct gspca_dev *gspca_dev,
struct sd *sd = (struct sd *) gspca_dev;
const u8 *reg9a;
static const u8 reg9a_def[] =
- {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
- static const u8 reg9a_sn9c325[] =
- {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
+ {0x00, 0x40, 0x20, 0x00, 0x00, 0x00};
+ static const u8 reg9a_spec[] =
+ {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
static const u8 regd4[] = {0x60, 0x00, 0x00};
reg_w1(gspca_dev, 0xf1, 0x00);
@@ -1077,9 +1077,10 @@ static int configure_gpio(struct gspca_dev *gspca_dev,
reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
- switch (sd->bridge) {
- case BRIDGE_SN9C325:
- reg9a = reg9a_sn9c325;
+ switch (sd->sensor) {
+ case SENSOR_OV7660:
+ case SENSOR_SP80708:
+ reg9a = reg9a_spec;
break;
default:
reg9a = reg9a_def;
@@ -1104,7 +1105,6 @@ static int configure_gpio(struct gspca_dev *gspca_dev,
reg_w1(gspca_dev, 0x17, 0x64);
reg_w1(gspca_dev, 0x01, 0x42);
break;
-/*jfm: from win trace */
case SENSOR_OV7630:
reg_w1(gspca_dev, 0x01, 0x61);
reg_w1(gspca_dev, 0x17, 0xe2);
@@ -1114,18 +1114,15 @@ static int configure_gpio(struct gspca_dev *gspca_dev,
case SENSOR_OV7648:
reg_w1(gspca_dev, 0x01, 0x63);
reg_w1(gspca_dev, 0x17, 0x20);
+ reg_w1(gspca_dev, 0x01, 0x62);
reg_w1(gspca_dev, 0x01, 0x42);
break;
-/*jfm: from win trace */
case SENSOR_OV7660:
- if (sd->bridge == BRIDGE_SN9C120) {
- reg_w1(gspca_dev, 0x01, 0x61);
- reg_w1(gspca_dev, 0x17, 0x20);
- reg_w1(gspca_dev, 0x01, 0x60);
- reg_w1(gspca_dev, 0x01, 0x40);
- break;
- }
- /* fall thru */
+ reg_w1(gspca_dev, 0x01, 0x61);
+ reg_w1(gspca_dev, 0x17, 0x20);
+ reg_w1(gspca_dev, 0x01, 0x60);
+ reg_w1(gspca_dev, 0x01, 0x40);
+ break;
case SENSOR_SP80708:
reg_w1(gspca_dev, 0x01, 0x63);
reg_w1(gspca_dev, 0x17, 0x20);
@@ -1134,6 +1131,9 @@ static int configure_gpio(struct gspca_dev *gspca_dev,
mdelay(100);
reg_w1(gspca_dev, 0x02, 0x62);
break;
+/* case SENSOR_HV7131R: */
+/* case SENSOR_MI0360: */
+/* case SENSOR_MO4000: */
default:
reg_w1(gspca_dev, 0x01, 0x43);
reg_w1(gspca_dev, 0x17, 0x61);
@@ -1280,6 +1280,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam = &gspca_dev->cam;
cam->cam_mode = vga_mode;
cam->nmodes = ARRAY_SIZE(vga_mode);
+ cam->npkt = 24; /* 24 packets per ISOC message */
sd->bridge = id->driver_info >> 16;
sd->sensor = id->driver_info >> 8;
@@ -1683,13 +1684,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
case SENSOR_OV7648:
reg17 = 0x20;
break;
-/*jfm: from win trace */
case SENSOR_OV7660:
- if (sd->bridge == BRIDGE_SN9C120) {
- reg17 = 0xa0;
- break;
- }
- /* fall thru */
+ reg17 = 0xa0;
+ break;
default:
reg17 = 0x60;
break;
@@ -1714,16 +1711,17 @@ static int sd_start(struct gspca_dev *gspca_dev)
reg_w1(gspca_dev, 0x9a, 0x0a);
reg_w1(gspca_dev, 0x99, 0x60);
break;
+ case SENSOR_OV7660:
+ reg_w1(gspca_dev, 0x9a, 0x05);
+ if (sd->bridge == BRIDGE_SN9C105)
+ reg_w1(gspca_dev, 0x99, 0xff);
+ else
+ reg_w1(gspca_dev, 0x99, 0x5b);
+ break;
case SENSOR_SP80708:
reg_w1(gspca_dev, 0x9a, 0x05);
reg_w1(gspca_dev, 0x99, 0x59);
break;
- case SENSOR_OV7660:
- if (sd->bridge == BRIDGE_SN9C120) {
- reg_w1(gspca_dev, 0x9a, 0x05);
- break;
- }
- /* fall thru */
default:
reg_w1(gspca_dev, 0x9a, 0x08);
reg_w1(gspca_dev, 0x99, 0x59);
@@ -2193,6 +2191,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
{USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
{USB_DEVICE(0x06f8, 0x3004), BSI(SN9C105, OV7660, 0x21)},
+ {USB_DEVICE(0x06f8, 0x3008), BSI(SN9C105, OV7660, 0x21)},
{USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
/* bw600.inf:
{USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
@@ -2211,7 +2210,12 @@ static const __devinitdata struct usb_device_id device_table[] = {
#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
{USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)},
#endif
+ {USB_DEVICE(0x0c45, 0x6100), BSI(SN9C120, MI0360, 0x5d)}, /*sn9c128*/
/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
+ {USB_DEVICE(0x0c45, 0x610a), BSI(SN9C120, OV7648, 0x21)}, /*sn9c128*/
+ {USB_DEVICE(0x0c45, 0x610b), BSI(SN9C120, OV7660, 0x21)}, /*sn9c128*/
+ {USB_DEVICE(0x0c45, 0x610c), BSI(SN9C120, HV7131R, 0x11)}, /*sn9c128*/
+ {USB_DEVICE(0x0c45, 0x610e), BSI(SN9C120, OV7630, 0x21)}, /*sn9c128*/
/* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
/* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
{USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/
diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c
index 6f38fa6d86b6..8806b2ff82be 100644
--- a/drivers/media/video/gspca/spca500.c
+++ b/drivers/media/video/gspca/spca500.c
@@ -32,9 +32,6 @@ MODULE_LICENSE("GPL");
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
- __u8 packet[ISO_MAX_SIZE + 128];
- /* !! no more than 128 ff in an ISO packet */
-
unsigned char brightness;
unsigned char contrast;
unsigned char colors;
@@ -906,7 +903,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
{
struct sd *sd = (struct sd *) gspca_dev;
int i;
- __u8 *s, *d;
static __u8 ffd9[] = {0xff, 0xd9};
/* frames are jpeg 4.1.1 without 0xff escape */
@@ -930,22 +926,19 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
}
/* add 0x00 after 0xff */
- for (i = len; --i >= 0; )
- if (data[i] == 0xff)
- break;
- if (i < 0) { /* no 0xff */
- gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
- return;
- }
- s = data;
- d = sd->packet;
- for (i = 0; i < len; i++) {
- *d++ = *s++;
- if (s[-1] == 0xff)
- *d++ = 0x00;
- }
- gspca_frame_add(gspca_dev, INTER_PACKET, frame,
- sd->packet, d - sd->packet);
+ i = 0;
+ do {
+ if (data[i] == 0xff) {
+ gspca_frame_add(gspca_dev, INTER_PACKET, frame,
+ data, i + 1);
+ len -= i;
+ data += i;
+ *data = 0x00;
+ i = 0;
+ }
+ i++;
+ } while (i < len);
+ gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
}
static void setbrightness(struct gspca_dev *gspca_dev)
diff --git a/drivers/media/video/gspca/sq905.c b/drivers/media/video/gspca/sq905.c
index 2e1cdf068fda..715a68f0156e 100644
--- a/drivers/media/video/gspca/sq905.c
+++ b/drivers/media/video/gspca/sq905.c
@@ -309,6 +309,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
struct sd *dev = (struct sd *) gspca_dev;
/* We don't use the buffer gspca allocates so make it small. */
+ cam->bulk = 1;
cam->bulk_size = 64;
INIT_WORK(&dev->work_struct, sq905_dostream);
diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c
index 0bcb74a1b143..916892505432 100644
--- a/drivers/media/video/gspca/sq905c.c
+++ b/drivers/media/video/gspca/sq905c.c
@@ -206,6 +206,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam->nmodes = 1;
/* We don't use the buffer gspca allocates so make it small. */
cam->bulk_size = 32;
+ cam->bulk = 1;
INIT_WORK(&dev->work_struct, sq905c_dostream);
return 0;
}
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c
index 69c77c932fc0..11a0c002f5dc 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c
@@ -80,12 +80,26 @@ static const struct ctrl vv6410_ctrl[] = {
.minimum = 0,
.maximum = 15,
.step = 1,
- .default_value = 0
+ .default_value = 10
},
.set = vv6410_set_analog_gain,
.get = vv6410_get_analog_gain
+ },
+#define EXPOSURE_IDX 3
+ {
+ {
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "exposure",
+ .minimum = 0,
+ .maximum = 32768,
+ .step = 1,
+ .default_value = 20000
+ },
+ .set = vv6410_set_exposure,
+ .get = vv6410_get_exposure
}
-};
+ };
static int vv6410_probe(struct sd *sd)
{
@@ -121,6 +135,7 @@ static int vv6410_probe(struct sd *sd)
static int vv6410_init(struct sd *sd)
{
int err = 0, i;
+ s32 *sensor_settings = sd->sensor_priv;
for (i = 0; i < ARRAY_SIZE(stv_bridge_init); i++) {
/* if NULL then len contains single value */
@@ -142,6 +157,16 @@ static int vv6410_init(struct sd *sd)
err = stv06xx_write_sensor_bytes(sd, (u8 *) vv6410_sensor_init,
ARRAY_SIZE(vv6410_sensor_init));
+ if (err < 0)
+ return err;
+
+ err = vv6410_set_exposure(&sd->gspca_dev,
+ sensor_settings[EXPOSURE_IDX]);
+ if (err < 0)
+ return err;
+
+ err = vv6410_set_analog_gain(&sd->gspca_dev,
+ sensor_settings[GAIN_IDX]);
return (err < 0) ? err : 0;
}
@@ -318,3 +343,50 @@ static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val)
return (err < 0) ? err : 0;
}
+
+static int vv6410_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ *val = sensor_settings[EXPOSURE_IDX];
+
+ PDEBUG(D_V4L2, "Read exposure %d", *val);
+
+ return 0;
+}
+
+static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err;
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+ unsigned int fine, coarse;
+
+ sensor_settings[EXPOSURE_IDX] = val;
+
+ val = (val * val >> 14) + val / 4;
+
+ fine = val % VV6410_CIF_LINELENGTH;
+ coarse = min(512, val / VV6410_CIF_LINELENGTH);
+
+ PDEBUG(D_V4L2, "Set coarse exposure to %d, fine expsure to %d",
+ coarse, fine);
+
+ err = stv06xx_write_sensor(sd, VV6410_FINEH, fine >> 8);
+ if (err < 0)
+ goto out;
+
+ err = stv06xx_write_sensor(sd, VV6410_FINEL, fine & 0xff);
+ if (err < 0)
+ goto out;
+
+ err = stv06xx_write_sensor(sd, VV6410_COARSEH, coarse >> 8);
+ if (err < 0)
+ goto out;
+
+ err = stv06xx_write_sensor(sd, VV6410_COARSEL, coarse & 0xff);
+
+out:
+ return err;
+}
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
index 95ac55891bd4..487d40555343 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
@@ -173,6 +173,8 @@
#define VV6410_SUBSAMPLE 0x01
#define VV6410_CROP_TO_QVGA 0x02
+#define VV6410_CIF_LINELENGTH 415
+
static int vv6410_probe(struct sd *sd);
static int vv6410_start(struct sd *sd);
static int vv6410_init(struct sd *sd);
@@ -187,6 +189,8 @@ static int vv6410_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
static int vv6410_get_analog_gain(struct gspca_dev *gspca_dev, __s32 *val);
static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int vv6410_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
const struct stv06xx_sensor stv06xx_sensor_vv6410 = {
.name = "ST VV6410",
@@ -242,12 +246,6 @@ static const u8 vv6410_sensor_init[][2] = {
/* Pre-clock generator divide off */
{VV6410_DATAFORMAT, BIT(7) | BIT(0)},
- /* Exposure registers */
- {VV6410_FINEH, VV6410_FINE_EXPOSURE >> 8},
- {VV6410_FINEL, VV6410_FINE_EXPOSURE & 0xff},
- {VV6410_COARSEH, VV6410_COARSE_EXPOSURE >> 8},
- {VV6410_COARSEL, VV6410_COARSE_EXPOSURE & 0xff},
- {VV6410_ANALOGGAIN, 0xf0 | VV6410_DEFAULT_GAIN},
{VV6410_CLKDIV, VV6410_CLK_DIV_2},
/* System registers */
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c
index c2b8c10c075a..9623f294bdac 100644
--- a/drivers/media/video/gspca/sunplus.c
+++ b/drivers/media/video/gspca/sunplus.c
@@ -32,9 +32,6 @@ MODULE_LICENSE("GPL");
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
- __u8 packet[ISO_MAX_SIZE + 128];
- /* !! no more than 128 ff in an ISO packet */
-
unsigned char brightness;
unsigned char contrast;
unsigned char colors;
@@ -1103,7 +1100,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
{
struct sd *sd = (struct sd *) gspca_dev;
int i, sof = 0;
- unsigned char *s, *d;
static unsigned char ffd9[] = {0xff, 0xd9};
/* frames are jpeg 4.1.1 without 0xff escape */
@@ -1177,22 +1173,19 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
}
/* add 0x00 after 0xff */
- for (i = len; --i >= 0; )
- if (data[i] == 0xff)
- break;
- if (i < 0) { /* no 0xff */
- gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
- return;
- }
- s = data;
- d = sd->packet;
- for (i = 0; i < len; i++) {
- *d++ = *s++;
- if (s[-1] == 0xff)
- *d++ = 0x00;
- }
- gspca_frame_add(gspca_dev, INTER_PACKET, frame,
- sd->packet, d - sd->packet);
+ i = 0;
+ do {
+ if (data[i] == 0xff) {
+ gspca_frame_add(gspca_dev, INTER_PACKET, frame,
+ data, i + 1);
+ len -= i;
+ data += i;
+ *data = 0x00;
+ i = 0;
+ }
+ i++;
+ } while (i < len);
+ gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
}
static void setbrightness(struct gspca_dev *gspca_dev)
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c
index f63e37e2e4fd..404214b8cd2b 100644
--- a/drivers/media/video/gspca/t613.c
+++ b/drivers/media/video/gspca/t613.c
@@ -697,7 +697,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
return -EINVAL;
}
- if (sd->sensor != SENSOR_OTHER) {
+ if (sd->sensor == SENSOR_OM6802) {
reg_w_buf(gspca_dev, n1, sizeof n1);
i = 5;
while (--i >= 0) {
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c
index e4e933c400bc..26dd155efcc3 100644
--- a/drivers/media/video/gspca/vc032x.c
+++ b/drivers/media/video/gspca/vc032x.c
@@ -42,7 +42,7 @@ struct sd {
char bridge;
#define BRIDGE_VC0321 0
#define BRIDGE_VC0323 1
- char sensor;
+ u8 sensor;
#define SENSOR_HV7131R 0
#define SENSOR_MI0360 1
#define SENSOR_MI1310_SOC 2
@@ -159,17 +159,17 @@ static const struct v4l2_pix_format vc0323_mode[] = {
.priv = 2},
};
static const struct v4l2_pix_format bi_mode[] = {
- {320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
+ {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
.bytesperline = 320,
.sizeimage = 320 * 240 * 2,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 2},
- {640, 480, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
+ {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
.bytesperline = 640,
.sizeimage = 640 * 480 * 2,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 1},
- {1280, 1024, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
+ {1280, 1024, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
.bytesperline = 1280,
.sizeimage = 1280 * 1024 * 2,
.colorspace = V4L2_COLORSPACE_SRGB,
@@ -2453,6 +2453,17 @@ static int sd_config(struct gspca_dev *gspca_dev,
struct usb_device *dev = gspca_dev->dev;
struct cam *cam;
int sensor;
+ static u8 npkt[] = { /* number of packets per ISOC message */
+ 64, /* HV7131R 0 */
+ 32, /* MI0360 1 */
+ 32, /* MI1310_SOC 2 */
+ 64, /* MI1320 3 */
+ 128, /* MI1320_SOC 4 */
+ 32, /* OV7660 5 */
+ 64, /* OV7670 6 */
+ 128, /* PO1200 7 */
+ 128, /* PO3130NC 8 */
+ };
cam = &gspca_dev->cam;
sd->bridge = id->driver_info;
@@ -2508,6 +2519,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
case SENSOR_MI1320_SOC:
cam->cam_mode = bi_mode;
cam->nmodes = ARRAY_SIZE(bi_mode);
+ cam->input_flags = V4L2_IN_ST_VFLIP |
+ V4L2_IN_ST_HFLIP;
break;
default:
cam->cam_mode = vc0323_mode;
@@ -2515,6 +2528,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
break;
}
}
+ cam->npkt = npkt[sd->sensor];
sd->hflip = HFLIP_DEF;
sd->vflip = VFLIP_DEF;
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c
index 4fe01d8b6c87..08422d315e68 100644
--- a/drivers/media/video/gspca/zc3xx.c
+++ b/drivers/media/video/gspca/zc3xx.c
@@ -6307,7 +6307,7 @@ static __u16 i2c_read(struct gspca_dev *gspca_dev,
retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */
retval = reg_r_i(gspca_dev, 0x0095); /* read Lowbyte */
retval |= reg_r_i(gspca_dev, 0x0096) << 8; /* read Hightbyte */
- PDEBUG(D_USBO, "i2c r [%02x] -> %04x (%02x)",
+ PDEBUG(D_USBI, "i2c r [%02x] -> %04x (%02x)",
reg, retval, retbyte);
return retval;
}
@@ -6868,7 +6868,6 @@ static const struct sensor_by_chipset_revision chipset_revision_sensor[] = {
{0x8001, 0x13},
{0x8000, 0x14}, /* CS2102K */
{0x8400, 0x15}, /* TAS5130K */
- {0x4001, 0x16}, /* ADCM2700 */
};
static int vga_3wr_probe(struct gspca_dev *gspca_dev)
@@ -6904,12 +6903,15 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev)
retword |= reg_r(gspca_dev, 0x000a);
PDEBUG(D_PROBE, "probe 3wr vga 1 0x%04x", retword);
reg_r(gspca_dev, 0x0010);
- /* this is tested only once anyway */
- for (i = 0; i < ARRAY_SIZE(chipset_revision_sensor); i++) {
- if (chipset_revision_sensor[i].revision == retword) {
- sd->chip_revision = retword;
- send_unknown(dev, SENSOR_PB0330);
- return chipset_revision_sensor[i].internal_sensor_id;
+ /* value 0x4001 is meaningless */
+ if (retword != 0x4001) {
+ for (i = 0; i < ARRAY_SIZE(chipset_revision_sensor); i++) {
+ if (chipset_revision_sensor[i].revision == retword) {
+ sd->chip_revision = retword;
+ send_unknown(dev, SENSOR_PB0330);
+ return chipset_revision_sensor[i]
+ .internal_sensor_id;
+ }
}
}
@@ -6980,12 +6982,12 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev)
reg_w(dev, 0x01, 0x0001);
reg_w(dev, 0x03, 0x0012);
reg_w(dev, 0x01, 0x0012);
- reg_w(dev, 0x05, 0x0001);
+ reg_w(dev, 0x05, 0x0012);
reg_w(dev, 0xd3, 0x008b);
retword = i2c_read(gspca_dev, 0x01);
if (retword != 0) {
PDEBUG(D_PROBE, "probe 3wr vga type 0a ? ret: %04x", retword);
- return retword;
+ return 0x16; /* adcm2700 (6100/6200) */
}
return -1;
}
diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c
index 3e6ffee8dfed..ccd47f57f42c 100644
--- a/drivers/media/video/hdpvr/hdpvr-video.c
+++ b/drivers/media/video/hdpvr/hdpvr-video.c
@@ -181,7 +181,7 @@ static int hdpvr_submit_buffers(struct hdpvr_device *dev)
buff_list);
if (buf->status != BUFSTAT_AVAILABLE) {
v4l2_err(&dev->v4l2_dev,
- "buffer not marked as availbale\n");
+ "buffer not marked as available\n");
ret = -EFAULT;
goto err;
}
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index 092c7da0f37a..86f2fefe1edf 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -74,7 +74,7 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
int start, range, toggle, dev, code, ircode;
/* poll IR chip */
- if (size != i2c_master_recv(&ir->c,buf,size))
+ if (size != i2c_master_recv(ir->c, buf, size))
return -EIO;
/* split rc5 data block ... */
@@ -137,7 +137,7 @@ static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
unsigned char b;
/* poll IR chip */
- if (1 != i2c_master_recv(&ir->c,&b,1)) {
+ if (1 != i2c_master_recv(ir->c, &b, 1)) {
dprintk(1,"read error\n");
return -EIO;
}
@@ -151,7 +151,7 @@ static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
unsigned char b;
/* poll IR chip */
- if (1 != i2c_master_recv(&ir->c,&b,1)) {
+ if (1 != i2c_master_recv(ir->c, &b, 1)) {
dprintk(1,"read error\n");
return -EIO;
}
@@ -171,7 +171,7 @@ static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
unsigned char buf[4];
/* poll IR chip */
- if (4 != i2c_master_recv(&ir->c,buf,4)) {
+ if (4 != i2c_master_recv(ir->c, buf, 4)) {
dprintk(1,"read error\n");
return -EIO;
}
@@ -195,7 +195,7 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
unsigned char b;
/* poll IR chip */
- if (1 != i2c_master_recv(&ir->c,&b,1)) {
+ if (1 != i2c_master_recv(ir->c, &b, 1)) {
dprintk(1,"read error\n");
return -EIO;
}
@@ -222,12 +222,12 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
u32 *ir_key, u32 *ir_raw)
{
unsigned char subaddr, key, keygroup;
- struct i2c_msg msg[] = { { .addr = ir->c.addr, .flags = 0,
+ struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0,
.buf = &subaddr, .len = 1},
- { .addr = ir->c.addr, .flags = I2C_M_RD,
+ { .addr = ir->c->addr, .flags = I2C_M_RD,
.buf = &key, .len = 1} };
subaddr = 0x0d;
- if (2 != i2c_transfer(ir->c.adapter, msg, 2)) {
+ if (2 != i2c_transfer(ir->c->adapter, msg, 2)) {
dprintk(1, "read error\n");
return -EIO;
}
@@ -237,7 +237,7 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
subaddr = 0x0b;
msg[1].buf = &keygroup;
- if (2 != i2c_transfer(ir->c.adapter, msg, 2)) {
+ if (2 != i2c_transfer(ir->c->adapter, msg, 2)) {
dprintk(1, "read error\n");
return -EIO;
}
@@ -286,7 +286,7 @@ static void ir_work(struct work_struct *work)
/* MSI TV@nywhere Plus requires more frequent polling
otherwise it will miss some keypresses */
- if (ir->c.adapter->id == I2C_HW_SAA7134 && ir->c.addr == 0x30)
+ if (ir->c->adapter->id == I2C_HW_SAA7134 && ir->c->addr == 0x30)
polling_interval = 50;
ir_key_poll(ir);
@@ -295,34 +295,15 @@ static void ir_work(struct work_struct *work)
/* ----------------------------------------------------------------------- */
-static int ir_attach(struct i2c_adapter *adap, int addr,
- unsigned short flags, int kind);
-static int ir_detach(struct i2c_client *client);
-static int ir_probe(struct i2c_adapter *adap);
-
-static struct i2c_driver driver = {
- .driver = {
- .name = "ir-kbd-i2c",
- },
- .id = I2C_DRIVERID_INFRARED,
- .attach_adapter = ir_probe,
- .detach_client = ir_detach,
-};
-
-static struct i2c_client client_template =
-{
- .name = "unset",
- .driver = &driver
-};
-
-static int ir_attach(struct i2c_adapter *adap, int addr,
- unsigned short flags, int kind)
+static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
IR_KEYTAB_TYPE *ir_codes = NULL;
- char *name;
+ const char *name = NULL;
int ir_type;
struct IR_i2c *ir;
struct input_dev *input_dev;
+ struct i2c_adapter *adap = client->adapter;
+ unsigned short addr = client->addr;
int err;
ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL);
@@ -332,13 +313,9 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
goto err_out_free;
}
- ir->c = client_template;
+ ir->c = client;
ir->input = input_dev;
-
- ir->c.adapter = adap;
- ir->c.addr = addr;
-
- i2c_set_clientdata(&ir->c, ir);
+ i2c_set_clientdata(client, ir);
switch(addr) {
case 0x64:
@@ -403,44 +380,46 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
ir_codes = ir_codes_avermedia_cardbus;
break;
default:
- /* shouldn't happen */
- printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n", addr);
+ dprintk(1, DEVNAME ": Unsupported i2c address 0x%02x\n", addr);
err = -ENODEV;
goto err_out_free;
}
- /* Sets name */
- snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name);
- ir->ir_codes = ir_codes;
+ /* Let the caller override settings */
+ if (client->dev.platform_data) {
+ const struct IR_i2c_init_data *init_data =
+ client->dev.platform_data;
- /* register i2c device
- * At device register, IR codes may be changed to be
- * board dependent.
- */
- err = i2c_attach_client(&ir->c);
- if (err)
- goto err_out_free;
+ ir_codes = init_data->ir_codes;
+ name = init_data->name;
+ ir->get_key = init_data->get_key;
+ }
- /* If IR not supported or disabled, unregisters driver */
- if (ir->get_key == NULL) {
+ /* Make sure we are all setup before going on */
+ if (!name || !ir->get_key || !ir_codes) {
+ dprintk(1, DEVNAME ": Unsupported device at address 0x%02x\n",
+ addr);
err = -ENODEV;
- goto err_out_detach;
+ goto err_out_free;
}
- /* Phys addr can only be set after attaching (for ir->c.dev) */
+ /* Sets name */
+ snprintf(ir->name, sizeof(ir->name), "i2c IR (%s)", name);
+ ir->ir_codes = ir_codes;
+
snprintf(ir->phys, sizeof(ir->phys), "%s/%s/ir0",
- dev_name(&ir->c.adapter->dev),
- dev_name(&ir->c.dev));
+ dev_name(&adap->dev),
+ dev_name(&client->dev));
/* init + register input device */
ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes);
input_dev->id.bustype = BUS_I2C;
- input_dev->name = ir->c.name;
+ input_dev->name = ir->name;
input_dev->phys = ir->phys;
err = input_register_device(ir->input);
if (err)
- goto err_out_detach;
+ goto err_out_free;
printk(DEVNAME ": %s detected at %s [%s]\n",
ir->input->name, ir->input->phys, adap->name);
@@ -451,135 +430,42 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
return 0;
- err_out_detach:
- i2c_detach_client(&ir->c);
err_out_free:
input_free_device(input_dev);
kfree(ir);
return err;
}
-static int ir_detach(struct i2c_client *client)
+static int ir_remove(struct i2c_client *client)
{
struct IR_i2c *ir = i2c_get_clientdata(client);
/* kill outstanding polls */
cancel_delayed_work_sync(&ir->work);
- /* unregister devices */
+ /* unregister device */
input_unregister_device(ir->input);
- i2c_detach_client(&ir->c);
/* free memory */
kfree(ir);
return 0;
}
-static int ir_probe(struct i2c_adapter *adap)
-{
-
- /* The external IR receiver is at i2c address 0x34 (0x35 for
- reads). Future Hauppauge cards will have an internal
- receiver at 0x30 (0x31 for reads). In theory, both can be
- fitted, and Hauppauge suggest an external overrides an
- internal.
-
- That's why we probe 0x1a (~0x34) first. CB
- */
-
- static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1};
- static const int probe_saa7134[] = { 0x7a, 0x47, 0x71, 0x2d, -1 };
- static const int probe_em28XX[] = { 0x30, 0x47, -1 };
- static const int probe_cx88[] = { 0x18, 0x6b, 0x71, -1 };
- static const int probe_cx23885[] = { 0x6b, -1 };
- const int *probe;
- struct i2c_msg msg = {
- .flags = I2C_M_RD,
- .len = 0,
- .buf = NULL,
- };
- int i, rc;
-
- switch (adap->id) {
- case I2C_HW_B_BT848:
- probe = probe_bttv;
- break;
- case I2C_HW_B_CX2341X:
- probe = probe_bttv;
- break;
- case I2C_HW_SAA7134:
- probe = probe_saa7134;
- break;
- case I2C_HW_B_EM28XX:
- probe = probe_em28XX;
- break;
- case I2C_HW_B_CX2388x:
- probe = probe_cx88;
- break;
- case I2C_HW_B_CX23885:
- probe = probe_cx23885;
- break;
- default:
- return 0;
- }
-
- for (i = 0; -1 != probe[i]; i++) {
- msg.addr = probe[i];
- rc = i2c_transfer(adap, &msg, 1);
- dprintk(1,"probe 0x%02x @ %s: %s\n",
- probe[i], adap->name,
- (1 == rc) ? "yes" : "no");
- if (1 == rc) {
- ir_attach(adap, probe[i], 0, 0);
- return 0;
- }
- }
-
- /* Special case for MSI TV@nywhere Plus remote */
- if (adap->id == I2C_HW_SAA7134) {
- u8 temp;
-
- /* MSI TV@nywhere Plus controller doesn't seem to
- respond to probes unless we read something from
- an existing device. Weird... */
-
- msg.addr = 0x50;
- rc = i2c_transfer(adap, &msg, 1);
- dprintk(1, "probe 0x%02x @ %s: %s\n",
- msg.addr, adap->name,
- (1 == rc) ? "yes" : "no");
-
- /* Now do the probe. The controller does not respond
- to 0-byte reads, so we use a 1-byte read instead. */
- msg.addr = 0x30;
- msg.len = 1;
- msg.buf = &temp;
- rc = i2c_transfer(adap, &msg, 1);
- dprintk(1, "probe 0x%02x @ %s: %s\n",
- msg.addr, adap->name,
- (1 == rc) ? "yes" : "no");
- if (1 == rc)
- ir_attach(adap, msg.addr, 0, 0);
- }
-
- /* Special case for AVerMedia Cardbus remote */
- if (adap->id == I2C_HW_SAA7134) {
- unsigned char subaddr, data;
- struct i2c_msg msg[] = { { .addr = 0x40, .flags = 0,
- .buf = &subaddr, .len = 1},
- { .addr = 0x40, .flags = I2C_M_RD,
- .buf = &data, .len = 1} };
- subaddr = 0x0d;
- rc = i2c_transfer(adap, msg, 2);
- dprintk(1, "probe 0x%02x/0x%02x @ %s: %s\n",
- msg[0].addr, subaddr, adap->name,
- (2 == rc) ? "yes" : "no");
- if (2 == rc)
- ir_attach(adap, msg[0].addr, 0, 0);
- }
+static const struct i2c_device_id ir_kbd_id[] = {
+ /* Generic entry for any IR receiver */
+ { "ir_video", 0 },
+ /* IR device specific entries could be added here */
+ { }
+};
- return 0;
-}
+static struct i2c_driver driver = {
+ .driver = {
+ .name = "ir-kbd-i2c",
+ },
+ .probe = ir_probe,
+ .remove = ir_remove,
+ .id_table = ir_kbd_id,
+};
/* ----------------------------------------------------------------------- */
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
index b0195e8ee4d1..e9ca9a064ae5 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -305,14 +305,17 @@ int ivtv_waitq(wait_queue_head_t *waitq)
/* Generic utility functions */
int ivtv_msleep_timeout(unsigned int msecs, int intr)
{
- int ret;
int timeout = msecs_to_jiffies(msecs);
do {
set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
timeout = schedule_timeout(timeout);
- if (intr && (ret = signal_pending(current)))
- return ret;
+ if (intr) {
+ int ret = signal_pending(current);
+
+ if (ret)
+ return ret;
+ }
} while (timeout);
return 0;
}
@@ -943,17 +946,14 @@ static int __devinit ivtv_probe(struct pci_dev *pdev,
if (itv == NULL)
return -ENOMEM;
itv->pdev = pdev;
- itv->instance = atomic_inc_return(&ivtv_instance) - 1;
+ itv->instance = v4l2_device_set_name(&itv->v4l2_dev, "ivtv",
+ &ivtv_instance);
retval = v4l2_device_register(&pdev->dev, &itv->v4l2_dev);
if (retval) {
kfree(itv);
return retval;
}
- /* "ivtv + PCI ID" is a bit of a mouthful, so use
- "ivtv + instance" instead. */
- snprintf(itv->v4l2_dev.name, sizeof(itv->v4l2_dev.name),
- "ivtv%d", itv->instance);
IVTV_INFO("Initializing card %d\n", itv->instance);
ivtv_process_options(itv);
diff --git a/drivers/media/video/ivtv/ivtv-gpio.c b/drivers/media/video/ivtv/ivtv-gpio.c
index ceb05bdcaf62..85ac707228e7 100644
--- a/drivers/media/video/ivtv/ivtv-gpio.c
+++ b/drivers/media/video/ivtv/ivtv-gpio.c
@@ -190,8 +190,8 @@ static int subdev_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
mask = itv->card->gpio_audio_detect.mask;
if (mask == 0 || (read_reg(IVTV_REG_GPIO_IN) & mask))
- vt->rxsubchans = V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+ vt->rxsubchans = V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
else
vt->rxsubchans = V4L2_TUNER_SUB_MONO;
return 0;
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c
index 9e3d32b8004c..e52aa322b134 100644
--- a/drivers/media/video/ivtv/ivtv-i2c.c
+++ b/drivers/media/video/ivtv/ivtv-i2c.c
@@ -579,9 +579,11 @@ static struct i2c_client ivtv_i2c_client_template = {
.name = "ivtv internal",
};
-/* init + register i2c algo-bit adapter */
+/* init + register i2c adapter + instantiate IR receiver */
int init_ivtv_i2c(struct ivtv *itv)
{
+ int retval;
+
IVTV_DEBUG_I2C("i2c init\n");
/* Sanity checks for the I2C hardware arrays. They must be the
@@ -619,9 +621,37 @@ int init_ivtv_i2c(struct ivtv *itv)
ivtv_setsda(itv, 1);
if (itv->options.newi2c > 0)
- return i2c_add_adapter(&itv->i2c_adap);
+ retval = i2c_add_adapter(&itv->i2c_adap);
else
- return i2c_bit_add_bus(&itv->i2c_adap);
+ retval = i2c_bit_add_bus(&itv->i2c_adap);
+
+ /* Instantiate the IR receiver device, if present */
+ if (retval == 0) {
+ struct i2c_board_info info;
+ /* The external IR receiver is at i2c address 0x34 (0x35 for
+ reads). Future Hauppauge cards will have an internal
+ receiver at 0x30 (0x31 for reads). In theory, both can be
+ fitted, and Hauppauge suggest an external overrides an
+ internal.
+
+ That's why we probe 0x1a (~0x34) first. CB
+ */
+ const unsigned short addr_list[] = {
+ 0x1a, /* Hauppauge IR external */
+ 0x18, /* Hauppauge IR internal */
+ 0x71, /* Hauppauge IR (PVR150) */
+ 0x64, /* Pixelview IR */
+ 0x30, /* KNC ONE IR */
+ 0x6b, /* Adaptec IR */
+ I2C_CLIENT_END
+ };
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+ i2c_new_probed_device(&itv->i2c_adap, &info, addr_list);
+ }
+
+ return retval;
}
void exit_ivtv_i2c(struct ivtv *itv)
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index 4a2d464f055e..c342a9fe983e 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -180,7 +180,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed)
/* Wait for any DMA to finish */
prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
- while (itv->i_flags & IVTV_F_I_DMA) {
+ while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) {
got_sig = signal_pending(current);
if (got_sig)
break;
@@ -1710,7 +1710,8 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
we are waiting unlock first and later lock again. */
mutex_unlock(&itv->serialize_lock);
prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE);
- if ((itv->i_flags & (IVTV_F_I_EV_DEC_STOPPED|IVTV_F_I_EV_VSYNC)) == 0)
+ if (!test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags) &&
+ !test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags))
schedule();
finish_wait(&itv->event_waitq, &wait);
mutex_lock(&itv->serialize_lock);
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c
index 01c14d2b381a..cd9db0bf33bf 100644
--- a/drivers/media/video/ivtv/ivtv-irq.c
+++ b/drivers/media/video/ivtv/ivtv-irq.c
@@ -196,7 +196,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA
bytes_needed, s->name);
return -1;
}
- if (rc && !s->buffers_stolen && (s->s_flags & IVTV_F_S_APPL_IO)) {
+ if (rc && !s->buffers_stolen && test_bit(IVTV_F_S_APPL_IO, &s->s_flags)) {
IVTV_WARN("All %s stream buffers are full. Dropping data.\n", s->name);
IVTV_WARN("Cause: the application is not reading fast enough.\n");
}
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c
index 7912ed6b72ee..c0875378acc2 100644
--- a/drivers/media/video/ivtv/ivtv-yuv.c
+++ b/drivers/media/video/ivtv/ivtv-yuv.c
@@ -1063,7 +1063,8 @@ static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
/* if no UDMA is pending and no UDMA is in progress, then the DMA
is finished */
- while (itv->i_flags & (IVTV_F_I_UDMA_PENDING | IVTV_F_I_UDMA)) {
+ while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) ||
+ test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
/* don't interrupt if the DMA is in progress but break off
a still pending DMA. */
got_sig = signal_pending(current);
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c
index 66e6eb513076..fa6bb85cb4b0 100644
--- a/drivers/media/video/ivtv/ivtvfb.c
+++ b/drivers/media/video/ivtv/ivtvfb.c
@@ -298,7 +298,8 @@ static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
/* if no UDMA is pending and no UDMA is in progress, then the DMA
is finished */
- while (itv->i_flags & (IVTV_F_I_UDMA_PENDING | IVTV_F_I_UDMA)) {
+ while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) ||
+ test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
/* don't interrupt if the DMA is in progress but break off
a still pending DMA. */
got_sig = signal_pending(current);
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index 684f62fa7897..459c04cbf69d 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -75,53 +75,50 @@ struct mt9m001 {
unsigned char autoexposure;
};
-static int reg_read(struct soc_camera_device *icd, const u8 reg)
+static int reg_read(struct i2c_client *client, const u8 reg)
{
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
- struct i2c_client *client = mt9m001->client;
s32 data = i2c_smbus_read_word_data(client, reg);
return data < 0 ? data : swab16(data);
}
-static int reg_write(struct soc_camera_device *icd, const u8 reg,
+static int reg_write(struct i2c_client *client, const u8 reg,
const u16 data)
{
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
- return i2c_smbus_write_word_data(mt9m001->client, reg, swab16(data));
+ return i2c_smbus_write_word_data(client, reg, swab16(data));
}
-static int reg_set(struct soc_camera_device *icd, const u8 reg,
+static int reg_set(struct i2c_client *client, const u8 reg,
const u16 data)
{
int ret;
- ret = reg_read(icd, reg);
+ ret = reg_read(client, reg);
if (ret < 0)
return ret;
- return reg_write(icd, reg, ret | data);
+ return reg_write(client, reg, ret | data);
}
-static int reg_clear(struct soc_camera_device *icd, const u8 reg,
+static int reg_clear(struct i2c_client *client, const u8 reg,
const u16 data)
{
int ret;
- ret = reg_read(icd, reg);
+ ret = reg_read(client, reg);
if (ret < 0)
return ret;
- return reg_write(icd, reg, ret & ~data);
+ return reg_write(client, reg, ret & ~data);
}
static int mt9m001_init(struct soc_camera_device *icd)
{
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
- struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(icd->control);
+ struct soc_camera_link *icl = client->dev.platform_data;
int ret;
dev_dbg(icd->vdev->parent, "%s\n", __func__);
if (icl->power) {
- ret = icl->power(&mt9m001->client->dev, 1);
+ ret = icl->power(&client->dev, 1);
if (ret < 0) {
dev_err(icd->vdev->parent,
"Platform failed to power-on the camera.\n");
@@ -131,49 +128,53 @@ static int mt9m001_init(struct soc_camera_device *icd)
/* The camera could have been already on, we reset it additionally */
if (icl->reset)
- ret = icl->reset(&mt9m001->client->dev);
+ ret = icl->reset(&client->dev);
else
ret = -ENODEV;
if (ret < 0) {
/* Either no platform reset, or platform reset failed */
- ret = reg_write(icd, MT9M001_RESET, 1);
+ ret = reg_write(client, MT9M001_RESET, 1);
if (!ret)
- ret = reg_write(icd, MT9M001_RESET, 0);
+ ret = reg_write(client, MT9M001_RESET, 0);
}
/* Disable chip, synchronous option update */
if (!ret)
- ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0);
+ ret = reg_write(client, MT9M001_OUTPUT_CONTROL, 0);
return ret;
}
static int mt9m001_release(struct soc_camera_device *icd)
{
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
- struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(icd->control);
+ struct soc_camera_link *icl = client->dev.platform_data;
/* Disable the chip */
- reg_write(icd, MT9M001_OUTPUT_CONTROL, 0);
+ reg_write(client, MT9M001_OUTPUT_CONTROL, 0);
if (icl->power)
- icl->power(&mt9m001->client->dev, 0);
+ icl->power(&client->dev, 0);
return 0;
}
static int mt9m001_start_capture(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
+
/* Switch to master "normal" mode */
- if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 2) < 0)
+ if (reg_write(client, MT9M001_OUTPUT_CONTROL, 2) < 0)
return -EIO;
return 0;
}
static int mt9m001_stop_capture(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
+
/* Stop sensor readout */
- if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 0) < 0)
+ if (reg_write(client, MT9M001_OUTPUT_CONTROL, 0) < 0)
return -EIO;
return 0;
}
@@ -222,28 +223,29 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
static int mt9m001_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
int ret;
const u16 hblank = 9, vblank = 25;
/* Blanking and start values - default... */
- ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank);
+ ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank);
if (!ret)
- ret = reg_write(icd, MT9M001_VERTICAL_BLANKING, vblank);
+ ret = reg_write(client, MT9M001_VERTICAL_BLANKING, vblank);
/* The caller provides a supported format, as verified per
* call to icd->try_fmt() */
if (!ret)
- ret = reg_write(icd, MT9M001_COLUMN_START, rect->left);
+ ret = reg_write(client, MT9M001_COLUMN_START, rect->left);
if (!ret)
- ret = reg_write(icd, MT9M001_ROW_START, rect->top);
+ ret = reg_write(client, MT9M001_ROW_START, rect->top);
if (!ret)
- ret = reg_write(icd, MT9M001_WINDOW_WIDTH, rect->width - 1);
+ ret = reg_write(client, MT9M001_WINDOW_WIDTH, rect->width - 1);
if (!ret)
- ret = reg_write(icd, MT9M001_WINDOW_HEIGHT,
+ ret = reg_write(client, MT9M001_WINDOW_HEIGHT,
rect->height + icd->y_skip_top - 1);
if (!ret && mt9m001->autoexposure) {
- ret = reg_write(icd, MT9M001_SHUTTER_WIDTH,
+ ret = reg_write(client, MT9M001_SHUTTER_WIDTH,
rect->height + icd->y_skip_top + vblank);
if (!ret) {
const struct v4l2_queryctrl *qctrl =
@@ -312,16 +314,16 @@ static int mt9m001_get_chip_id(struct soc_camera_device *icd,
static int mt9m001_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+ struct i2c_client *client = to_i2c_client(icd->control);
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
- if (reg->match.addr != mt9m001->client->addr)
+ if (reg->match.addr != client->addr)
return -ENODEV;
reg->size = 2;
- reg->val = reg_read(icd, reg->reg);
+ reg->val = reg_read(client, reg->reg);
if (reg->val > 0xffff)
return -EIO;
@@ -332,15 +334,15 @@ static int mt9m001_get_register(struct soc_camera_device *icd,
static int mt9m001_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+ struct i2c_client *client = to_i2c_client(icd->control);
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
- if (reg->match.addr != mt9m001->client->addr)
+ if (reg->match.addr != client->addr)
return -ENODEV;
- if (reg_write(icd, reg->reg, reg->val) < 0)
+ if (reg_write(client, reg->reg, reg->val) < 0)
return -EIO;
return 0;
@@ -416,12 +418,13 @@ static struct soc_camera_ops mt9m001_ops = {
static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
int data;
switch (ctrl->id) {
case V4L2_CID_VFLIP:
- data = reg_read(icd, MT9M001_READ_OPTIONS2);
+ data = reg_read(client, MT9M001_READ_OPTIONS2);
if (data < 0)
return -EIO;
ctrl->value = !!(data & 0x8000);
@@ -435,6 +438,7 @@ static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_contro
static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
const struct v4l2_queryctrl *qctrl;
int data;
@@ -447,9 +451,9 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro
switch (ctrl->id) {
case V4L2_CID_VFLIP:
if (ctrl->value)
- data = reg_set(icd, MT9M001_READ_OPTIONS2, 0x8000);
+ data = reg_set(client, MT9M001_READ_OPTIONS2, 0x8000);
else
- data = reg_clear(icd, MT9M001_READ_OPTIONS2, 0x8000);
+ data = reg_clear(client, MT9M001_READ_OPTIONS2, 0x8000);
if (data < 0)
return -EIO;
break;
@@ -463,7 +467,7 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro
data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range;
dev_dbg(&icd->dev, "Setting gain %d\n", data);
- data = reg_write(icd, MT9M001_GLOBAL_GAIN, data);
+ data = reg_write(client, MT9M001_GLOBAL_GAIN, data);
if (data < 0)
return -EIO;
} else {
@@ -481,8 +485,8 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro
data = ((gain - 64) * 7 + 28) / 56 + 96;
dev_dbg(&icd->dev, "Setting gain from %d to %d\n",
- reg_read(icd, MT9M001_GLOBAL_GAIN), data);
- data = reg_write(icd, MT9M001_GLOBAL_GAIN, data);
+ reg_read(client, MT9M001_GLOBAL_GAIN), data);
+ data = reg_write(client, MT9M001_GLOBAL_GAIN, data);
if (data < 0)
return -EIO;
}
@@ -500,8 +504,8 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro
range / 2) / range + 1;
dev_dbg(&icd->dev, "Setting shutter width from %d to %lu\n",
- reg_read(icd, MT9M001_SHUTTER_WIDTH), shutter);
- if (reg_write(icd, MT9M001_SHUTTER_WIDTH, shutter) < 0)
+ reg_read(client, MT9M001_SHUTTER_WIDTH), shutter);
+ if (reg_write(client, MT9M001_SHUTTER_WIDTH, shutter) < 0)
return -EIO;
icd->exposure = ctrl->value;
mt9m001->autoexposure = 0;
@@ -510,7 +514,7 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro
case V4L2_CID_EXPOSURE_AUTO:
if (ctrl->value) {
const u16 vblank = 25;
- if (reg_write(icd, MT9M001_SHUTTER_WIDTH, icd->height +
+ if (reg_write(client, MT9M001_SHUTTER_WIDTH, icd->height +
icd->y_skip_top + vblank) < 0)
return -EIO;
qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
@@ -529,8 +533,9 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro
* this wasn't our capture interface, so, we wait for the right one */
static int mt9m001_video_probe(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
- struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
+ struct soc_camera_link *icl = client->dev.platform_data;
s32 data;
int ret;
unsigned long flags;
@@ -542,11 +547,11 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
return -ENODEV;
/* Enable the chip */
- data = reg_write(icd, MT9M001_CHIP_ENABLE, 1);
+ data = reg_write(client, MT9M001_CHIP_ENABLE, 1);
dev_dbg(&icd->dev, "write: %d\n", data);
/* Read out the chip version register */
- data = reg_read(icd, MT9M001_CHIP_VERSION);
+ data = reg_read(client, MT9M001_CHIP_VERSION);
/* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
switch (data) {
@@ -604,10 +609,13 @@ ei2c:
static void mt9m001_video_remove(struct soc_camera_device *icd)
{
struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+ struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr,
icd->dev.parent, icd->vdev);
soc_camera_video_stop(icd);
+ if (icl->free_bus)
+ icl->free_bus(icl);
}
static int mt9m001_probe(struct i2c_client *client,
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index cdd1ddb51388..fc5e2de03766 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -113,10 +113,10 @@
* mt9m111: Camera control register addresses (0x200..0x2ff not implemented)
*/
-#define reg_read(reg) mt9m111_reg_read(icd, MT9M111_##reg)
-#define reg_write(reg, val) mt9m111_reg_write(icd, MT9M111_##reg, (val))
-#define reg_set(reg, val) mt9m111_reg_set(icd, MT9M111_##reg, (val))
-#define reg_clear(reg, val) mt9m111_reg_clear(icd, MT9M111_##reg, (val))
+#define reg_read(reg) mt9m111_reg_read(client, MT9M111_##reg)
+#define reg_write(reg, val) mt9m111_reg_write(client, MT9M111_##reg, (val))
+#define reg_set(reg, val) mt9m111_reg_set(client, MT9M111_##reg, (val))
+#define reg_clear(reg, val) mt9m111_reg_clear(client, MT9M111_##reg, (val))
#define MT9M111_MIN_DARK_ROWS 8
#define MT9M111_MIN_DARK_COLS 24
@@ -184,58 +184,55 @@ static int reg_page_map_set(struct i2c_client *client, const u16 reg)
return ret;
}
-static int mt9m111_reg_read(struct soc_camera_device *icd, const u16 reg)
+static int mt9m111_reg_read(struct i2c_client *client, const u16 reg)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
- struct i2c_client *client = mt9m111->client;
int ret;
ret = reg_page_map_set(client, reg);
if (!ret)
ret = swab16(i2c_smbus_read_word_data(client, (reg & 0xff)));
- dev_dbg(&icd->dev, "read reg.%03x -> %04x\n", reg, ret);
+ dev_dbg(&client->dev, "read reg.%03x -> %04x\n", reg, ret);
return ret;
}
-static int mt9m111_reg_write(struct soc_camera_device *icd, const u16 reg,
+static int mt9m111_reg_write(struct i2c_client *client, const u16 reg,
const u16 data)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
- struct i2c_client *client = mt9m111->client;
int ret;
ret = reg_page_map_set(client, reg);
if (!ret)
- ret = i2c_smbus_write_word_data(mt9m111->client, (reg & 0xff),
+ ret = i2c_smbus_write_word_data(client, (reg & 0xff),
swab16(data));
- dev_dbg(&icd->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret);
+ dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret);
return ret;
}
-static int mt9m111_reg_set(struct soc_camera_device *icd, const u16 reg,
+static int mt9m111_reg_set(struct i2c_client *client, const u16 reg,
const u16 data)
{
int ret;
- ret = mt9m111_reg_read(icd, reg);
+ ret = mt9m111_reg_read(client, reg);
if (ret >= 0)
- ret = mt9m111_reg_write(icd, reg, ret | data);
+ ret = mt9m111_reg_write(client, reg, ret | data);
return ret;
}
-static int mt9m111_reg_clear(struct soc_camera_device *icd, const u16 reg,
+static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg,
const u16 data)
{
int ret;
- ret = mt9m111_reg_read(icd, reg);
- return mt9m111_reg_write(icd, reg, ret & ~data);
+ ret = mt9m111_reg_read(client, reg);
+ return mt9m111_reg_write(client, reg, ret & ~data);
}
static int mt9m111_set_context(struct soc_camera_device *icd,
enum mt9m111_context ctxt)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B
| MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B
| MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B
@@ -252,6 +249,7 @@ static int mt9m111_set_context(struct soc_camera_device *icd,
static int mt9m111_setup_rect(struct soc_camera_device *icd,
struct v4l2_rect *rect)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
int ret, is_raw_format;
int width = rect->width;
@@ -296,6 +294,7 @@ static int mt9m111_setup_rect(struct soc_camera_device *icd,
static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
int ret;
ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt);
@@ -357,12 +356,13 @@ static int mt9m111_setfmt_yuv(struct soc_camera_device *icd)
static int mt9m111_enable(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
- struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
+ struct soc_camera_link *icl = client->dev.platform_data;
int ret;
if (icl->power) {
- ret = icl->power(&mt9m111->client->dev, 1);
+ ret = icl->power(&client->dev, 1);
if (ret < 0) {
dev_err(icd->vdev->parent,
"Platform failed to power-on the camera.\n");
@@ -378,8 +378,9 @@ static int mt9m111_enable(struct soc_camera_device *icd)
static int mt9m111_disable(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
- struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
+ struct soc_camera_link *icl = client->dev.platform_data;
int ret;
ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE);
@@ -387,15 +388,15 @@ static int mt9m111_disable(struct soc_camera_device *icd)
mt9m111->powered = 0;
if (icl->power)
- icl->power(&mt9m111->client->dev, 0);
+ icl->power(&client->dev, 0);
return ret;
}
static int mt9m111_reset(struct soc_camera_device *icd)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
- struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(icd->control);
+ struct soc_camera_link *icl = client->dev.platform_data;
int ret;
ret = reg_set(RESET, MT9M111_RESET_RESET_MODE);
@@ -406,7 +407,7 @@ static int mt9m111_reset(struct soc_camera_device *icd)
| MT9M111_RESET_RESET_SOC);
if (icl->reset)
- icl->reset(&mt9m111->client->dev);
+ icl->reset(&client->dev);
return ret;
}
@@ -562,15 +563,14 @@ static int mt9m111_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
int val;
-
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(icd->control);
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
return -EINVAL;
- if (reg->match.addr != mt9m111->client->addr)
+ if (reg->match.addr != client->addr)
return -ENODEV;
- val = mt9m111_reg_read(icd, reg->reg);
+ val = mt9m111_reg_read(client, reg->reg);
reg->size = 2;
reg->val = (u64)val;
@@ -583,15 +583,15 @@ static int mt9m111_get_register(struct soc_camera_device *icd,
static int mt9m111_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(icd->control);
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
return -EINVAL;
- if (reg->match.addr != mt9m111->client->addr)
+ if (reg->match.addr != client->addr)
return -ENODEV;
- if (mt9m111_reg_write(icd, reg->reg, reg->val) < 0)
+ if (mt9m111_reg_write(client, reg->reg, reg->val) < 0)
return -EIO;
return 0;
@@ -672,6 +672,7 @@ static struct soc_camera_ops mt9m111_ops = {
static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
int ret;
@@ -692,6 +693,7 @@ static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask)
static int mt9m111_get_global_gain(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
int data;
data = reg_read(GLOBAL_GAIN);
@@ -703,6 +705,7 @@ static int mt9m111_get_global_gain(struct soc_camera_device *icd)
static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
u16 val;
if (gain > 63 * 2 * 2)
@@ -721,6 +724,7 @@ static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain)
static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
int ret;
@@ -737,6 +741,7 @@ static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on)
static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
int ret;
@@ -754,6 +759,7 @@ static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on)
static int mt9m111_get_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
int data;
@@ -898,6 +904,7 @@ static int mt9m111_release(struct soc_camera_device *icd)
*/
static int mt9m111_video_probe(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
s32 data;
int ret;
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c
index 2b0927bfd217..f72aeb7c4deb 100644
--- a/drivers/media/video/mt9t031.c
+++ b/drivers/media/video/mt9t031.c
@@ -76,64 +76,61 @@ struct mt9t031 {
u16 yskip;
};
-static int reg_read(struct soc_camera_device *icd, const u8 reg)
+static int reg_read(struct i2c_client *client, const u8 reg)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
- struct i2c_client *client = mt9t031->client;
s32 data = i2c_smbus_read_word_data(client, reg);
return data < 0 ? data : swab16(data);
}
-static int reg_write(struct soc_camera_device *icd, const u8 reg,
+static int reg_write(struct i2c_client *client, const u8 reg,
const u16 data)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
- return i2c_smbus_write_word_data(mt9t031->client, reg, swab16(data));
+ return i2c_smbus_write_word_data(client, reg, swab16(data));
}
-static int reg_set(struct soc_camera_device *icd, const u8 reg,
+static int reg_set(struct i2c_client *client, const u8 reg,
const u16 data)
{
int ret;
- ret = reg_read(icd, reg);
+ ret = reg_read(client, reg);
if (ret < 0)
return ret;
- return reg_write(icd, reg, ret | data);
+ return reg_write(client, reg, ret | data);
}
-static int reg_clear(struct soc_camera_device *icd, const u8 reg,
+static int reg_clear(struct i2c_client *client, const u8 reg,
const u16 data)
{
int ret;
- ret = reg_read(icd, reg);
+ ret = reg_read(client, reg);
if (ret < 0)
return ret;
- return reg_write(icd, reg, ret & ~data);
+ return reg_write(client, reg, ret & ~data);
}
-static int set_shutter(struct soc_camera_device *icd, const u32 data)
+static int set_shutter(struct i2c_client *client, const u32 data)
{
int ret;
- ret = reg_write(icd, MT9T031_SHUTTER_WIDTH_UPPER, data >> 16);
+ ret = reg_write(client, MT9T031_SHUTTER_WIDTH_UPPER, data >> 16);
if (ret >= 0)
- ret = reg_write(icd, MT9T031_SHUTTER_WIDTH, data & 0xffff);
+ ret = reg_write(client, MT9T031_SHUTTER_WIDTH, data & 0xffff);
return ret;
}
-static int get_shutter(struct soc_camera_device *icd, u32 *data)
+static int get_shutter(struct i2c_client *client, u32 *data)
{
int ret;
- ret = reg_read(icd, MT9T031_SHUTTER_WIDTH_UPPER);
+ ret = reg_read(client, MT9T031_SHUTTER_WIDTH_UPPER);
*data = ret << 16;
if (ret >= 0)
- ret = reg_read(icd, MT9T031_SHUTTER_WIDTH);
+ ret = reg_read(client, MT9T031_SHUTTER_WIDTH);
*data |= ret & 0xffff;
return ret < 0 ? ret : 0;
@@ -141,12 +138,12 @@ static int get_shutter(struct soc_camera_device *icd, u32 *data)
static int mt9t031_init(struct soc_camera_device *icd)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
- struct soc_camera_link *icl = mt9t031->client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(icd->control);
+ struct soc_camera_link *icl = client->dev.platform_data;
int ret;
if (icl->power) {
- ret = icl->power(&mt9t031->client->dev, 1);
+ ret = icl->power(&client->dev, 1);
if (ret < 0) {
dev_err(icd->vdev->parent,
"Platform failed to power-on the camera.\n");
@@ -155,44 +152,48 @@ static int mt9t031_init(struct soc_camera_device *icd)
}
/* Disable chip output, synchronous option update */
- ret = reg_write(icd, MT9T031_RESET, 1);
+ ret = reg_write(client, MT9T031_RESET, 1);
if (ret >= 0)
- ret = reg_write(icd, MT9T031_RESET, 0);
+ ret = reg_write(client, MT9T031_RESET, 0);
if (ret >= 0)
- ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2);
+ ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 2);
if (ret < 0 && icl->power)
- icl->power(&mt9t031->client->dev, 0);
+ icl->power(&client->dev, 0);
return ret >= 0 ? 0 : -EIO;
}
static int mt9t031_release(struct soc_camera_device *icd)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
- struct soc_camera_link *icl = mt9t031->client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(icd->control);
+ struct soc_camera_link *icl = client->dev.platform_data;
/* Disable the chip */
- reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2);
+ reg_clear(client, MT9T031_OUTPUT_CONTROL, 2);
if (icl->power)
- icl->power(&mt9t031->client->dev, 0);
+ icl->power(&client->dev, 0);
return 0;
}
static int mt9t031_start_capture(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
+
/* Switch to master "normal" mode */
- if (reg_set(icd, MT9T031_OUTPUT_CONTROL, 2) < 0)
+ if (reg_set(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
return -EIO;
return 0;
}
static int mt9t031_stop_capture(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
+
/* Stop sensor readout */
- if (reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2) < 0)
+ if (reg_clear(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
return -EIO;
return 0;
}
@@ -200,14 +201,16 @@ static int mt9t031_stop_capture(struct soc_camera_device *icd)
static int mt9t031_set_bus_param(struct soc_camera_device *icd,
unsigned long flags)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
+
/* The caller should have queried our parameters, check anyway */
if (flags & ~MT9T031_BUS_PARAM)
return -EINVAL;
if (flags & SOCAM_PCLK_SAMPLE_FALLING)
- reg_clear(icd, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
+ reg_clear(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
else
- reg_set(icd, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
+ reg_set(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
return 0;
}
@@ -235,6 +238,7 @@ static void recalculate_limits(struct soc_camera_device *icd,
static int mt9t031_set_params(struct soc_camera_device *icd,
struct v4l2_rect *rect, u16 xskip, u16 yskip)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
int ret;
u16 xbin, ybin, width, height, left, top;
@@ -277,22 +281,22 @@ static int mt9t031_set_params(struct soc_camera_device *icd,
}
/* Disable register update, reconfigure atomically */
- ret = reg_set(icd, MT9T031_OUTPUT_CONTROL, 1);
+ ret = reg_set(client, MT9T031_OUTPUT_CONTROL, 1);
if (ret < 0)
return ret;
/* Blanking and start values - default... */
- ret = reg_write(icd, MT9T031_HORIZONTAL_BLANKING, hblank);
+ ret = reg_write(client, MT9T031_HORIZONTAL_BLANKING, hblank);
if (ret >= 0)
- ret = reg_write(icd, MT9T031_VERTICAL_BLANKING, vblank);
+ ret = reg_write(client, MT9T031_VERTICAL_BLANKING, vblank);
if (yskip != mt9t031->yskip || xskip != mt9t031->xskip) {
/* Binning, skipping */
if (ret >= 0)
- ret = reg_write(icd, MT9T031_COLUMN_ADDRESS_MODE,
+ ret = reg_write(client, MT9T031_COLUMN_ADDRESS_MODE,
((xbin - 1) << 4) | (xskip - 1));
if (ret >= 0)
- ret = reg_write(icd, MT9T031_ROW_ADDRESS_MODE,
+ ret = reg_write(client, MT9T031_ROW_ADDRESS_MODE,
((ybin - 1) << 4) | (yskip - 1));
}
dev_dbg(&icd->dev, "new physical left %u, top %u\n", left, top);
@@ -300,16 +304,16 @@ static int mt9t031_set_params(struct soc_camera_device *icd,
/* The caller provides a supported format, as guaranteed by
* icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() */
if (ret >= 0)
- ret = reg_write(icd, MT9T031_COLUMN_START, left);
+ ret = reg_write(client, MT9T031_COLUMN_START, left);
if (ret >= 0)
- ret = reg_write(icd, MT9T031_ROW_START, top);
+ ret = reg_write(client, MT9T031_ROW_START, top);
if (ret >= 0)
- ret = reg_write(icd, MT9T031_WINDOW_WIDTH, width - 1);
+ ret = reg_write(client, MT9T031_WINDOW_WIDTH, width - 1);
if (ret >= 0)
- ret = reg_write(icd, MT9T031_WINDOW_HEIGHT,
+ ret = reg_write(client, MT9T031_WINDOW_HEIGHT,
height + icd->y_skip_top - 1);
if (ret >= 0 && mt9t031->autoexposure) {
- ret = set_shutter(icd, height + icd->y_skip_top + vblank);
+ ret = set_shutter(client, height + icd->y_skip_top + vblank);
if (ret >= 0) {
const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank;
const struct v4l2_queryctrl *qctrl =
@@ -324,7 +328,7 @@ static int mt9t031_set_params(struct soc_camera_device *icd,
/* Re-enable register update, commit all changes */
if (ret >= 0)
- ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 1);
+ ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 1);
return ret < 0 ? ret : 0;
}
@@ -417,15 +421,15 @@ static int mt9t031_get_chip_id(struct soc_camera_device *icd,
static int mt9t031_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+ struct i2c_client *client = to_i2c_client(icd->control);
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
- if (reg->match.addr != mt9t031->client->addr)
+ if (reg->match.addr != client->addr)
return -ENODEV;
- reg->val = reg_read(icd, reg->reg);
+ reg->val = reg_read(client, reg->reg);
if (reg->val > 0xffff)
return -EIO;
@@ -436,15 +440,15 @@ static int mt9t031_get_register(struct soc_camera_device *icd,
static int mt9t031_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+ struct i2c_client *client = to_i2c_client(icd->control);
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
- if (reg->match.addr != mt9t031->client->addr)
+ if (reg->match.addr != client->addr)
return -ENODEV;
- if (reg_write(icd, reg->reg, reg->val) < 0)
+ if (reg_write(client, reg->reg, reg->val) < 0)
return -EIO;
return 0;
@@ -528,18 +532,19 @@ static struct soc_camera_ops mt9t031_ops = {
static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
int data;
switch (ctrl->id) {
case V4L2_CID_VFLIP:
- data = reg_read(icd, MT9T031_READ_MODE_2);
+ data = reg_read(client, MT9T031_READ_MODE_2);
if (data < 0)
return -EIO;
ctrl->value = !!(data & 0x8000);
break;
case V4L2_CID_HFLIP:
- data = reg_read(icd, MT9T031_READ_MODE_2);
+ data = reg_read(client, MT9T031_READ_MODE_2);
if (data < 0)
return -EIO;
ctrl->value = !!(data & 0x4000);
@@ -553,6 +558,7 @@ static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_contro
static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
const struct v4l2_queryctrl *qctrl;
int data;
@@ -565,17 +571,17 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro
switch (ctrl->id) {
case V4L2_CID_VFLIP:
if (ctrl->value)
- data = reg_set(icd, MT9T031_READ_MODE_2, 0x8000);
+ data = reg_set(client, MT9T031_READ_MODE_2, 0x8000);
else
- data = reg_clear(icd, MT9T031_READ_MODE_2, 0x8000);
+ data = reg_clear(client, MT9T031_READ_MODE_2, 0x8000);
if (data < 0)
return -EIO;
break;
case V4L2_CID_HFLIP:
if (ctrl->value)
- data = reg_set(icd, MT9T031_READ_MODE_2, 0x4000);
+ data = reg_set(client, MT9T031_READ_MODE_2, 0x4000);
else
- data = reg_clear(icd, MT9T031_READ_MODE_2, 0x4000);
+ data = reg_clear(client, MT9T031_READ_MODE_2, 0x4000);
if (data < 0)
return -EIO;
break;
@@ -589,7 +595,7 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro
data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range;
dev_dbg(&icd->dev, "Setting gain %d\n", data);
- data = reg_write(icd, MT9T031_GLOBAL_GAIN, data);
+ data = reg_write(client, MT9T031_GLOBAL_GAIN, data);
if (data < 0)
return -EIO;
} else {
@@ -609,8 +615,8 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro
data = (((gain - 64 + 7) * 32) & 0xff00) | 0x60;
dev_dbg(&icd->dev, "Setting gain from 0x%x to 0x%x\n",
- reg_read(icd, MT9T031_GLOBAL_GAIN), data);
- data = reg_write(icd, MT9T031_GLOBAL_GAIN, data);
+ reg_read(client, MT9T031_GLOBAL_GAIN), data);
+ data = reg_write(client, MT9T031_GLOBAL_GAIN, data);
if (data < 0)
return -EIO;
}
@@ -628,10 +634,10 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro
range / 2) / range + 1;
u32 old;
- get_shutter(icd, &old);
+ get_shutter(client, &old);
dev_dbg(&icd->dev, "Setting shutter width from %u to %u\n",
old, shutter);
- if (set_shutter(icd, shutter) < 0)
+ if (set_shutter(client, shutter) < 0)
return -EIO;
icd->exposure = ctrl->value;
mt9t031->autoexposure = 0;
@@ -641,7 +647,7 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro
if (ctrl->value) {
const u16 vblank = MT9T031_VERTICAL_BLANK;
const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank;
- if (set_shutter(icd, icd->height +
+ if (set_shutter(client, icd->height +
icd->y_skip_top + vblank) < 0)
return -EIO;
qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
@@ -661,6 +667,7 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro
* this wasn't our capture interface, so, we wait for the right one */
static int mt9t031_video_probe(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
s32 data;
int ret;
@@ -672,11 +679,11 @@ static int mt9t031_video_probe(struct soc_camera_device *icd)
return -ENODEV;
/* Enable the chip */
- data = reg_write(icd, MT9T031_CHIP_ENABLE, 1);
+ data = reg_write(client, MT9T031_CHIP_ENABLE, 1);
dev_dbg(&icd->dev, "write: %d\n", data);
/* Read out the chip version register */
- data = reg_read(icd, MT9T031_CHIP_VERSION);
+ data = reg_read(client, MT9T031_CHIP_VERSION);
switch (data) {
case 0x1621:
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index 4d3b4813c322..be20d312b1dc 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -91,51 +91,49 @@ struct mt9v022 {
u16 chip_control;
};
-static int reg_read(struct soc_camera_device *icd, const u8 reg)
+static int reg_read(struct i2c_client *client, const u8 reg)
{
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- struct i2c_client *client = mt9v022->client;
s32 data = i2c_smbus_read_word_data(client, reg);
return data < 0 ? data : swab16(data);
}
-static int reg_write(struct soc_camera_device *icd, const u8 reg,
+static int reg_write(struct i2c_client *client, const u8 reg,
const u16 data)
{
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- return i2c_smbus_write_word_data(mt9v022->client, reg, swab16(data));
+ return i2c_smbus_write_word_data(client, reg, swab16(data));
}
-static int reg_set(struct soc_camera_device *icd, const u8 reg,
+static int reg_set(struct i2c_client *client, const u8 reg,
const u16 data)
{
int ret;
- ret = reg_read(icd, reg);
+ ret = reg_read(client, reg);
if (ret < 0)
return ret;
- return reg_write(icd, reg, ret | data);
+ return reg_write(client, reg, ret | data);
}
-static int reg_clear(struct soc_camera_device *icd, const u8 reg,
+static int reg_clear(struct i2c_client *client, const u8 reg,
const u16 data)
{
int ret;
- ret = reg_read(icd, reg);
+ ret = reg_read(client, reg);
if (ret < 0)
return ret;
- return reg_write(icd, reg, ret & ~data);
+ return reg_write(client, reg, ret & ~data);
}
static int mt9v022_init(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
+ struct soc_camera_link *icl = client->dev.platform_data;
int ret;
if (icl->power) {
- ret = icl->power(&mt9v022->client->dev, 1);
+ ret = icl->power(&client->dev, 1);
if (ret < 0) {
dev_err(icd->vdev->parent,
"Platform failed to power-on the camera.\n");
@@ -148,27 +146,27 @@ static int mt9v022_init(struct soc_camera_device *icd)
* if available. Soft reset is done in video_probe().
*/
if (icl->reset)
- icl->reset(&mt9v022->client->dev);
+ icl->reset(&client->dev);
/* Almost the default mode: master, parallel, simultaneous, and an
* undocumented bit 0x200, which is present in table 7, but not in 8,
* plus snapshot mode to disable scan for now */
mt9v022->chip_control |= 0x10;
- ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
+ ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
if (!ret)
- ret = reg_write(icd, MT9V022_READ_MODE, 0x300);
+ ret = reg_write(client, MT9V022_READ_MODE, 0x300);
/* All defaults */
if (!ret)
/* AEC, AGC on */
- ret = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x3);
+ ret = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x3);
if (!ret)
- ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480);
+ ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480);
if (!ret)
/* default - auto */
- ret = reg_clear(icd, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1);
+ ret = reg_clear(client, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1);
if (!ret)
- ret = reg_write(icd, MT9V022_DIGITAL_TEST_PATTERN, 0);
+ ret = reg_write(client, MT9V022_DIGITAL_TEST_PATTERN, 0);
return ret;
}
@@ -186,10 +184,11 @@ static int mt9v022_release(struct soc_camera_device *icd)
static int mt9v022_start_capture(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
/* Switch to master "normal" mode */
mt9v022->chip_control &= ~0x10;
- if (reg_write(icd, MT9V022_CHIP_CONTROL,
+ if (reg_write(client, MT9V022_CHIP_CONTROL,
mt9v022->chip_control) < 0)
return -EIO;
return 0;
@@ -197,10 +196,11 @@ static int mt9v022_start_capture(struct soc_camera_device *icd)
static int mt9v022_stop_capture(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
/* Switch to snapshot mode */
mt9v022->chip_control |= 0x10;
- if (reg_write(icd, MT9V022_CHIP_CONTROL,
+ if (reg_write(client, MT9V022_CHIP_CONTROL,
mt9v022->chip_control) < 0)
return -EIO;
return 0;
@@ -209,8 +209,9 @@ static int mt9v022_stop_capture(struct soc_camera_device *icd)
static int mt9v022_set_bus_param(struct soc_camera_device *icd,
unsigned long flags)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
+ struct soc_camera_link *icl = client->dev.platform_data;
unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
int ret;
u16 pixclk = 0;
@@ -243,14 +244,14 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd,
if (!(flags & SOCAM_VSYNC_ACTIVE_HIGH))
pixclk |= 0x2;
- ret = reg_write(icd, MT9V022_PIXCLK_FV_LV, pixclk);
+ ret = reg_write(client, MT9V022_PIXCLK_FV_LV, pixclk);
if (ret < 0)
return ret;
if (!(flags & SOCAM_MASTER))
mt9v022->chip_control &= ~0x8;
- ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
+ ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
if (ret < 0)
return ret;
@@ -282,35 +283,36 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
static int mt9v022_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
int ret;
/* Like in example app. Contradicts the datasheet though */
- ret = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
+ ret = reg_read(client, MT9V022_AEC_AGC_ENABLE);
if (ret >= 0) {
if (ret & 1) /* Autoexposure */
- ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH,
+ ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH,
rect->height + icd->y_skip_top + 43);
else
- ret = reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH,
+ ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
rect->height + icd->y_skip_top + 43);
}
/* Setup frame format: defaults apart from width and height */
if (!ret)
- ret = reg_write(icd, MT9V022_COLUMN_START, rect->left);
+ ret = reg_write(client, MT9V022_COLUMN_START, rect->left);
if (!ret)
- ret = reg_write(icd, MT9V022_ROW_START, rect->top);
+ ret = reg_write(client, MT9V022_ROW_START, rect->top);
if (!ret)
/* Default 94, Phytec driver says:
* "width + horizontal blank >= 660" */
- ret = reg_write(icd, MT9V022_HORIZONTAL_BLANKING,
+ ret = reg_write(client, MT9V022_HORIZONTAL_BLANKING,
rect->width > 660 - 43 ? 43 :
660 - rect->width);
if (!ret)
- ret = reg_write(icd, MT9V022_VERTICAL_BLANKING, 45);
+ ret = reg_write(client, MT9V022_VERTICAL_BLANKING, 45);
if (!ret)
- ret = reg_write(icd, MT9V022_WINDOW_WIDTH, rect->width);
+ ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect->width);
if (!ret)
- ret = reg_write(icd, MT9V022_WINDOW_HEIGHT,
+ ret = reg_write(client, MT9V022_WINDOW_HEIGHT,
rect->height + icd->y_skip_top);
if (ret < 0)
@@ -396,16 +398,16 @@ static int mt9v022_get_chip_id(struct soc_camera_device *icd,
static int mt9v022_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+ struct i2c_client *client = to_i2c_client(icd->control);
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
- if (reg->match.addr != mt9v022->client->addr)
+ if (reg->match.addr != client->addr)
return -ENODEV;
reg->size = 2;
- reg->val = reg_read(icd, reg->reg);
+ reg->val = reg_read(client, reg->reg);
if (reg->val > 0xffff)
return -EIO;
@@ -416,15 +418,15 @@ static int mt9v022_get_register(struct soc_camera_device *icd,
static int mt9v022_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+ struct i2c_client *client = to_i2c_client(icd->control);
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
- if (reg->match.addr != mt9v022->client->addr)
+ if (reg->match.addr != client->addr)
return -ENODEV;
- if (reg_write(icd, reg->reg, reg->val) < 0)
+ if (reg_write(client, reg->reg, reg->val) < 0)
return -EIO;
return 0;
@@ -517,29 +519,30 @@ static struct soc_camera_ops mt9v022_ops = {
static int mt9v022_get_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
int data;
switch (ctrl->id) {
case V4L2_CID_VFLIP:
- data = reg_read(icd, MT9V022_READ_MODE);
+ data = reg_read(client, MT9V022_READ_MODE);
if (data < 0)
return -EIO;
ctrl->value = !!(data & 0x10);
break;
case V4L2_CID_HFLIP:
- data = reg_read(icd, MT9V022_READ_MODE);
+ data = reg_read(client, MT9V022_READ_MODE);
if (data < 0)
return -EIO;
ctrl->value = !!(data & 0x20);
break;
case V4L2_CID_EXPOSURE_AUTO:
- data = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
+ data = reg_read(client, MT9V022_AEC_AGC_ENABLE);
if (data < 0)
return -EIO;
ctrl->value = !!(data & 0x1);
break;
case V4L2_CID_AUTOGAIN:
- data = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
+ data = reg_read(client, MT9V022_AEC_AGC_ENABLE);
if (data < 0)
return -EIO;
ctrl->value = !!(data & 0x2);
@@ -552,6 +555,7 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl)
{
int data;
+ struct i2c_client *client = to_i2c_client(icd->control);
const struct v4l2_queryctrl *qctrl;
qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
@@ -562,17 +566,17 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
switch (ctrl->id) {
case V4L2_CID_VFLIP:
if (ctrl->value)
- data = reg_set(icd, MT9V022_READ_MODE, 0x10);
+ data = reg_set(client, MT9V022_READ_MODE, 0x10);
else
- data = reg_clear(icd, MT9V022_READ_MODE, 0x10);
+ data = reg_clear(client, MT9V022_READ_MODE, 0x10);
if (data < 0)
return -EIO;
break;
case V4L2_CID_HFLIP:
if (ctrl->value)
- data = reg_set(icd, MT9V022_READ_MODE, 0x20);
+ data = reg_set(client, MT9V022_READ_MODE, 0x20);
else
- data = reg_clear(icd, MT9V022_READ_MODE, 0x20);
+ data = reg_clear(client, MT9V022_READ_MODE, 0x20);
if (data < 0)
return -EIO;
break;
@@ -593,12 +597,12 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
/* The user wants to set gain manually, hope, she
* knows, what she's doing... Switch AGC off. */
- if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2) < 0)
+ if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0)
return -EIO;
dev_info(&icd->dev, "Setting gain from %d to %lu\n",
- reg_read(icd, MT9V022_ANALOG_GAIN), gain);
- if (reg_write(icd, MT9V022_ANALOG_GAIN, gain) < 0)
+ reg_read(client, MT9V022_ANALOG_GAIN), gain);
+ if (reg_write(client, MT9V022_ANALOG_GAIN, gain) < 0)
return -EIO;
icd->gain = ctrl->value;
}
@@ -614,13 +618,13 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
/* The user wants to set shutter width manually, hope,
* she knows, what she's doing... Switch AEC off. */
- if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1) < 0)
+ if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1) < 0)
return -EIO;
dev_dbg(&icd->dev, "Shutter width from %d to %lu\n",
- reg_read(icd, MT9V022_TOTAL_SHUTTER_WIDTH),
+ reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH),
shutter);
- if (reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH,
+ if (reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
shutter) < 0)
return -EIO;
icd->exposure = ctrl->value;
@@ -628,17 +632,17 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
break;
case V4L2_CID_AUTOGAIN:
if (ctrl->value)
- data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x2);
+ data = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x2);
else
- data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2);
+ data = reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2);
if (data < 0)
return -EIO;
break;
case V4L2_CID_EXPOSURE_AUTO:
if (ctrl->value)
- data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x1);
+ data = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x1);
else
- data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1);
+ data = reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1);
if (data < 0)
return -EIO;
break;
@@ -650,8 +654,9 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
* this wasn't our capture interface, so, we wait for the right one */
static int mt9v022_video_probe(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
+ struct soc_camera_link *icl = client->dev.platform_data;
s32 data;
int ret;
unsigned long flags;
@@ -661,7 +666,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
return -ENODEV;
/* Read out the chip version register */
- data = reg_read(icd, MT9V022_CHIP_VERSION);
+ data = reg_read(client, MT9V022_CHIP_VERSION);
/* must be 0x1311 or 0x1313 */
if (data != 0x1311 && data != 0x1313) {
@@ -672,12 +677,12 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
}
/* Soft reset */
- ret = reg_write(icd, MT9V022_RESET, 1);
+ ret = reg_write(client, MT9V022_RESET, 1);
if (ret < 0)
goto ei2c;
/* 15 clock cycles */
udelay(200);
- if (reg_read(icd, MT9V022_RESET)) {
+ if (reg_read(client, MT9V022_RESET)) {
dev_err(&icd->dev, "Resetting MT9V022 failed!\n");
goto ei2c;
}
@@ -685,11 +690,11 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
/* Set monochrome or colour sensor type */
if (sensor_type && (!strcmp("colour", sensor_type) ||
!strcmp("color", sensor_type))) {
- ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11);
+ ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11);
mt9v022->model = V4L2_IDENT_MT9V022IX7ATC;
icd->formats = mt9v022_colour_formats;
} else {
- ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11);
+ ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 0x11);
mt9v022->model = V4L2_IDENT_MT9V022IX7ATM;
icd->formats = mt9v022_monochrome_formats;
}
@@ -735,10 +740,13 @@ ei2c:
static void mt9v022_video_remove(struct soc_camera_device *icd)
{
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+ struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr,
icd->dev.parent, icd->vdev);
soc_camera_video_stop(icd);
+ if (icl->free_bus)
+ icl->free_bus(icl);
}
static int mt9v022_probe(struct i2c_client *client,
diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c
index 86fab56c5a20..2d075205bdfe 100644
--- a/drivers/media/video/mx1_camera.c
+++ b/drivers/media/video/mx1_camera.c
@@ -102,10 +102,10 @@ struct mx1_buffer {
* Interface. If anyone ever builds hardware to enable more than
* one camera, they will have to modify this driver too */
struct mx1_camera_dev {
+ struct soc_camera_host soc_host;
struct soc_camera_device *icd;
struct mx1_camera_pdata *pdata;
struct mx1_buffer *active;
- struct device *dev;
struct resource *res;
struct clk *clk;
struct list_head capture;
@@ -219,7 +219,7 @@ static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev)
int ret;
if (unlikely(!pcdev->active)) {
- dev_err(pcdev->dev, "DMA End IRQ with no active buffer\n");
+ dev_err(pcdev->soc_host.dev, "DMA End IRQ with no active buffer\n");
return -EFAULT;
}
@@ -229,7 +229,7 @@ static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev)
vbuf->size, pcdev->res->start +
CSIRXR, DMA_MODE_READ);
if (unlikely(ret))
- dev_err(pcdev->dev, "Failed to setup DMA sg list\n");
+ dev_err(pcdev->soc_host.dev, "Failed to setup DMA sg list\n");
return ret;
}
@@ -338,14 +338,14 @@ static void mx1_camera_dma_irq(int channel, void *data)
imx_dma_disable(channel);
if (unlikely(!pcdev->active)) {
- dev_err(pcdev->dev, "DMA End IRQ with no active buffer\n");
+ dev_err(pcdev->soc_host.dev, "DMA End IRQ with no active buffer\n");
goto out;
}
vb = &pcdev->active->vb;
buf = container_of(vb, struct mx1_buffer, vb);
WARN_ON(buf->inwork || list_empty(&vb->queue));
- dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+ dev_dbg(pcdev->soc_host.dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
vb, vb->baddr, vb->bsize);
mx1_camera_wakeup(pcdev, vb, buf);
@@ -366,7 +366,7 @@ static void mx1_camera_init_videobuf(struct videobuf_queue *q,
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct mx1_camera_dev *pcdev = ici->priv;
- videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, pcdev->dev,
+ videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, ici->dev,
&pcdev->lock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_NONE,
@@ -385,7 +385,7 @@ static int mclk_get_divisor(struct mx1_camera_dev *pcdev)
* they get a nice Oops */
div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1;
- dev_dbg(pcdev->dev, "System clock %lukHz, target freq %dkHz, "
+ dev_dbg(pcdev->soc_host.dev, "System clock %lukHz, target freq %dkHz, "
"divisor %lu\n", lcdclk / 1000, mclk / 1000, div);
return div;
@@ -395,7 +395,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev)
{
unsigned int csicr1 = CSICR1_EN;
- dev_dbg(pcdev->dev, "Activate device\n");
+ dev_dbg(pcdev->soc_host.dev, "Activate device\n");
clk_enable(pcdev->clk);
@@ -411,7 +411,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev)
static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev)
{
- dev_dbg(pcdev->dev, "Deactivate device\n");
+ dev_dbg(pcdev->soc_host.dev, "Deactivate device\n");
/* Disable all CSI interface */
__raw_writel(0x00, pcdev->base + CSICR1);
@@ -550,7 +550,7 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd,
xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
if (!xlate) {
- dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat);
+ dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat);
return -EINVAL;
}
@@ -633,12 +633,6 @@ static struct soc_camera_host_ops mx1_soc_camera_host_ops = {
.querycap = mx1_camera_querycap,
};
-/* Should be allocated dynamically too, but we have only one. */
-static struct soc_camera_host mx1_soc_camera_host = {
- .drv_name = DRIVER_NAME,
- .ops = &mx1_soc_camera_host_ops,
-};
-
static struct fiq_handler fh = {
.name = "csi_sof"
};
@@ -673,7 +667,6 @@ static int __init mx1_camera_probe(struct platform_device *pdev)
goto exit_put_clk;
}
- dev_set_drvdata(&pdev->dev, pcdev);
pcdev->res = res;
pcdev->clk = clk;
@@ -707,16 +700,15 @@ static int __init mx1_camera_probe(struct platform_device *pdev)
}
pcdev->irq = irq;
pcdev->base = base;
- pcdev->dev = &pdev->dev;
/* request dma */
pcdev->dma_chan = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_HIGH);
if (pcdev->dma_chan < 0) {
- dev_err(pcdev->dev, "Can't request DMA for MX1 CSI\n");
+ dev_err(&pdev->dev, "Can't request DMA for MX1 CSI\n");
err = -EBUSY;
goto exit_iounmap;
}
- dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chan);
+ dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chan);
imx_dma_setup_handlers(pcdev->dma_chan, mx1_camera_dma_irq, NULL,
pcdev);
@@ -729,7 +721,7 @@ static int __init mx1_camera_probe(struct platform_device *pdev)
/* request irq */
err = claim_fiq(&fh);
if (err) {
- dev_err(pcdev->dev, "Camera interrupt register failed \n");
+ dev_err(&pdev->dev, "Camera interrupt register failed \n");
goto exit_free_dma;
}
@@ -746,10 +738,12 @@ static int __init mx1_camera_probe(struct platform_device *pdev)
mxc_set_irq_fiq(irq, 1);
enable_fiq(irq);
- mx1_soc_camera_host.priv = pcdev;
- mx1_soc_camera_host.dev.parent = &pdev->dev;
- mx1_soc_camera_host.nr = pdev->id;
- err = soc_camera_host_register(&mx1_soc_camera_host);
+ pcdev->soc_host.drv_name = DRIVER_NAME;
+ pcdev->soc_host.ops = &mx1_soc_camera_host_ops;
+ pcdev->soc_host.priv = pcdev;
+ pcdev->soc_host.dev = &pdev->dev;
+ pcdev->soc_host.nr = pdev->id;
+ err = soc_camera_host_register(&pcdev->soc_host);
if (err)
goto exit_free_irq;
@@ -777,7 +771,9 @@ exit:
static int __exit mx1_camera_remove(struct platform_device *pdev)
{
- struct mx1_camera_dev *pcdev = platform_get_drvdata(pdev);
+ struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
+ struct mx1_camera_dev *pcdev = container_of(soc_host,
+ struct mx1_camera_dev, soc_host);
struct resource *res;
imx_dma_free(pcdev->dma_chan);
@@ -787,7 +783,7 @@ static int __exit mx1_camera_remove(struct platform_device *pdev)
clk_put(pcdev->clk);
- soc_camera_host_unregister(&mx1_soc_camera_host);
+ soc_camera_host_unregister(soc_host);
iounmap(pcdev->base);
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
index c462b811e994..4d47eeb14452 100644
--- a/drivers/media/video/mx3_camera.c
+++ b/drivers/media/video/mx3_camera.c
@@ -87,7 +87,6 @@ struct mx3_camera_buffer {
* @soc_host: embedded soc_host object
*/
struct mx3_camera_dev {
- struct device *dev;
/*
* i.MX3x is only supposed to handle one camera on its Camera Sensor
* Interface. If anyone ever builds hardware to enable more than one
@@ -431,7 +430,7 @@ static void mx3_camera_init_videobuf(struct videobuf_queue *q,
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct mx3_camera_dev *mx3_cam = ici->priv;
- videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, mx3_cam->dev,
+ videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, ici->dev,
&mx3_cam->lock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_NONE,
@@ -599,7 +598,8 @@ static int test_platform_param(struct mx3_camera_dev *mx3_cam,
*flags |= SOCAM_DATAWIDTH_4;
break;
default:
- dev_info(mx3_cam->dev, "Unsupported bus width %d\n", buswidth);
+ dev_info(mx3_cam->soc_host.dev, "Unsupported bus width %d\n",
+ buswidth);
return -EINVAL;
}
@@ -614,7 +614,7 @@ static int mx3_camera_try_bus_param(struct soc_camera_device *icd,
unsigned long bus_flags, camera_flags;
int ret = test_platform_param(mx3_cam, depth, &bus_flags);
- dev_dbg(&ici->dev, "requested bus width %d bit: %d\n", depth, ret);
+ dev_dbg(ici->dev, "requested bus width %d bit: %d\n", depth, ret);
if (ret < 0)
return ret;
@@ -637,7 +637,7 @@ static bool chan_filter(struct dma_chan *chan, void *arg)
if (!rq)
return false;
- pdata = rq->mx3_cam->dev->platform_data;
+ pdata = rq->mx3_cam->soc_host.dev->platform_data;
return rq->id == chan->chan_id &&
pdata->dma_dev == chan->device->dev;
@@ -697,7 +697,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx,
xlate->cam_fmt = icd->formats + idx;
xlate->buswidth = buswidth;
xlate++;
- dev_dbg(&ici->dev, "Providing format %s using %s\n",
+ dev_dbg(ici->dev, "Providing format %s using %s\n",
mx3_camera_formats[0].name,
icd->formats[idx].name);
}
@@ -709,7 +709,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx,
xlate->cam_fmt = icd->formats + idx;
xlate->buswidth = buswidth;
xlate++;
- dev_dbg(&ici->dev, "Providing format %s using %s\n",
+ dev_dbg(ici->dev, "Providing format %s using %s\n",
mx3_camera_formats[0].name,
icd->formats[idx].name);
}
@@ -722,7 +722,7 @@ passthrough:
xlate->cam_fmt = icd->formats + idx;
xlate->buswidth = buswidth;
xlate++;
- dev_dbg(&ici->dev,
+ dev_dbg(ici->dev,
"Providing format %s in pass-through mode\n",
icd->formats[idx].name);
}
@@ -829,7 +829,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd,
xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
if (!xlate) {
- dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat);
+ dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat);
return -EINVAL;
}
@@ -866,7 +866,7 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd,
xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
if (pixfmt && !xlate) {
- dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
+ dev_warn(ici->dev, "Format %x not found\n", pixfmt);
return -EINVAL;
}
@@ -933,11 +933,11 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
if (!xlate) {
- dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
+ dev_warn(ici->dev, "Format %x not found\n", pixfmt);
return -EINVAL;
}
- dev_dbg(&ici->dev, "requested bus width %d bit: %d\n",
+ dev_dbg(ici->dev, "requested bus width %d bit: %d\n",
icd->buswidth, ret);
if (ret < 0)
@@ -947,7 +947,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
if (!common_flags) {
- dev_dbg(&ici->dev, "no common flags: camera %lx, host %lx\n",
+ dev_dbg(ici->dev, "no common flags: camera %lx, host %lx\n",
camera_flags, bus_flags);
return -EINVAL;
}
@@ -1054,7 +1054,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
csi_reg_write(mx3_cam, sens_conf | dw, CSI_SENS_CONF);
- dev_dbg(&ici->dev, "Set SENS_CONF to %x\n", sens_conf | dw);
+ dev_dbg(ici->dev, "Set SENS_CONF to %x\n", sens_conf | dw);
return 0;
}
@@ -1063,10 +1063,6 @@ static struct soc_camera_host_ops mx3_soc_camera_host_ops = {
.owner = THIS_MODULE,
.add = mx3_camera_add_device,
.remove = mx3_camera_remove_device,
-#ifdef CONFIG_PM
- .suspend = mx3_camera_suspend,
- .resume = mx3_camera_resume,
-#endif
.set_crop = mx3_camera_set_crop,
.set_fmt = mx3_camera_set_fmt,
.try_fmt = mx3_camera_try_fmt,
@@ -1106,8 +1102,6 @@ static int mx3_camera_probe(struct platform_device *pdev)
goto eclkget;
}
- dev_set_drvdata(&pdev->dev, mx3_cam);
-
mx3_cam->pdata = pdev->dev.platform_data;
mx3_cam->platform_flags = mx3_cam->pdata->flags;
if (!(mx3_cam->platform_flags & (MX3_CAMERA_DATAWIDTH_4 |
@@ -1139,14 +1133,14 @@ static int mx3_camera_probe(struct platform_device *pdev)
}
mx3_cam->base = base;
- mx3_cam->dev = &pdev->dev;
soc_host = &mx3_cam->soc_host;
soc_host->drv_name = MX3_CAM_DRV_NAME;
soc_host->ops = &mx3_soc_camera_host_ops;
soc_host->priv = mx3_cam;
- soc_host->dev.parent = &pdev->dev;
+ soc_host->dev = &pdev->dev;
soc_host->nr = pdev->id;
+
err = soc_camera_host_register(soc_host);
if (err)
goto ecamhostreg;
@@ -1169,11 +1163,13 @@ egetres:
static int __devexit mx3_camera_remove(struct platform_device *pdev)
{
- struct mx3_camera_dev *mx3_cam = platform_get_drvdata(pdev);
+ struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
+ struct mx3_camera_dev *mx3_cam = container_of(soc_host,
+ struct mx3_camera_dev, soc_host);
clk_put(mx3_cam->clk);
- soc_camera_host_unregister(&mx3_cam->soc_host);
+ soc_camera_host_unregister(soc_host);
iounmap(mx3_cam->base);
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
index 1cb6a260e8b0..76d42d92e603 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
@@ -284,6 +284,8 @@ static struct tda10048_config hauppauge_tda10048_config = {
.output_mode = TDA10048_PARALLEL_OUTPUT,
.fwbulkwritelen = TDA10048_BULKWRITE_50,
.inversion = TDA10048_INVERSION_ON,
+ .if_freq_khz = TDA10048_IF_4300,
+ .clk_freq_khz = TDA10048_CLK_16000,
};
static struct tda829x_config tda829x_no_probe = {
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index d9d974a8f52a..dcfae62b7f43 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -1461,7 +1461,6 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw)
return ret;
}
- usb_settoggle(hdw->usb_dev, 0 & 0xf, !(0 & USB_DIR_IN), 0);
usb_clear_halt(hdw->usb_dev, usb_sndbulkpipe(hdw->usb_dev, 0 & 0x7f));
pipe = usb_sndctrlpipe(hdw->usb_dev, 0);
@@ -4825,9 +4824,6 @@ static unsigned int pvr2_hdw_report_clients(struct pvr2_hdw *hdw,
struct v4l2_subdev *sd;
unsigned int tcnt = 0;
unsigned int ccnt;
- struct i2c_client *client;
- struct list_head *item;
- void *cd;
const char *p;
unsigned int id;
@@ -4849,42 +4845,6 @@ static unsigned int pvr2_hdw_report_clients(struct pvr2_hdw *hdw,
ccnt = scnprintf(buf + tcnt, acnt - tcnt, "\n");
tcnt += ccnt;
- ccnt = scnprintf(buf + tcnt, acnt - tcnt, "I2C clients:\n");
- tcnt += ccnt;
-
- mutex_lock(&hdw->i2c_adap.clist_lock);
- list_for_each(item, &hdw->i2c_adap.clients) {
- client = list_entry(item, struct i2c_client, list);
- ccnt = scnprintf(buf + tcnt, acnt - tcnt,
- " %s: i2c=%02x", client->name, client->addr);
- tcnt += ccnt;
- cd = i2c_get_clientdata(client);
- v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) {
- if (cd == sd) {
- id = sd->grp_id;
- p = NULL;
- if (id < ARRAY_SIZE(module_names)) {
- p = module_names[id];
- }
- if (p) {
- ccnt = scnprintf(buf + tcnt,
- acnt - tcnt,
- " subdev=%s", p);
- tcnt += ccnt;
- } else {
- ccnt = scnprintf(buf + tcnt,
- acnt - tcnt,
- " subdev= id %u)",
- id);
- tcnt += ccnt;
- }
- break;
- }
- }
- ccnt = scnprintf(buf + tcnt, acnt - tcnt, "\n");
- tcnt += ccnt;
- }
- mutex_unlock(&hdw->i2c_adap.clist_lock);
return tcnt;
}
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
index 9af282f9e765..c3020e1752bf 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
@@ -559,6 +559,27 @@ static void do_i2c_scan(struct pvr2_hdw *hdw)
printk(KERN_INFO "%s: i2c scan done.\n", hdw->name);
}
+static void pvr2_i2c_register_ir(struct i2c_adapter *i2c_adap)
+{
+ struct i2c_board_info info;
+ /* The external IR receiver is at i2c address 0x34 (0x35 for
+ reads). Future Hauppauge cards will have an internal
+ receiver at 0x30 (0x31 for reads). In theory, both can be
+ fitted, and Hauppauge suggest an external overrides an
+ internal.
+
+ That's why we probe 0x1a (~0x34) first. CB
+ */
+ const unsigned short addr_list[] = {
+ 0x1a, 0x18, 0x64, 0x30,
+ I2C_CLIENT_END
+ };
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+ i2c_new_probed_device(i2c_adap, &info, addr_list);
+}
+
void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
{
unsigned int idx;
@@ -606,6 +627,9 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
}
}
if (i2c_scan) do_i2c_scan(hdw);
+
+ /* Instantiate the IR receiver device, if present */
+ pvr2_i2c_register_ir(&hdw->i2c_adap);
}
void pvr2_i2c_core_done(struct pvr2_hdw *hdw)
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c
index f9fbe02e0f69..50b415e07eda 100644
--- a/drivers/media/video/pwc/pwc-ctrl.c
+++ b/drivers/media/video/pwc/pwc-ctrl.c
@@ -159,35 +159,67 @@ static void pwc_set_image_buffer_size(struct pwc_device *pdev);
/****************************************************************************/
+static int _send_control_msg(struct pwc_device *pdev,
+ u8 request, u16 value, int index, void *buf, int buflen, int timeout)
+{
+ int rc;
+ void *kbuf = NULL;
+
+ if (buflen) {
+ kbuf = kmalloc(buflen, GFP_KERNEL); /* not allowed on stack */
+ if (kbuf == NULL)
+ return -ENOMEM;
+ memcpy(kbuf, buf, buflen);
+ }
-#define SendControlMsg(request, value, buflen) \
- usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), \
- request, \
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \
- value, \
- pdev->vcinterface, \
- &buf, buflen, 500)
+ rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ request,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value,
+ index,
+ kbuf, buflen, timeout);
-#define RecvControlMsg(request, value, buflen) \
- usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), \
- request, \
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \
- value, \
- pdev->vcinterface, \
- &buf, buflen, 500)
+ kfree(kbuf);
+ return rc;
+}
+static int recv_control_msg(struct pwc_device *pdev,
+ u8 request, u16 value, void *buf, int buflen)
+{
+ int rc;
+ void *kbuf = kmalloc(buflen, GFP_KERNEL); /* not allowed on stack */
+
+ if (kbuf == NULL)
+ return -ENOMEM;
+
+ rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+ request,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value,
+ pdev->vcinterface,
+ kbuf, buflen, 500);
+ memcpy(buf, kbuf, buflen);
+ kfree(kbuf);
+ return rc;
+}
-static int send_video_command(struct usb_device *udev, int index, void *buf, int buflen)
+static inline int send_video_command(struct pwc_device *pdev,
+ int index, void *buf, int buflen)
{
- return usb_control_msg(udev,
- usb_sndctrlpipe(udev, 0),
+ return _send_control_msg(pdev,
SET_EP_STREAM_CTL,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
VIDEO_OUTPUT_CONTROL_FORMATTER,
index,
buf, buflen, 1000);
}
+static inline int send_control_msg(struct pwc_device *pdev,
+ u8 request, u16 value, void *buf, int buflen)
+{
+ return _send_control_msg(pdev,
+ request, value, pdev->vcinterface, buf, buflen, 500);
+}
+
static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
@@ -224,7 +256,7 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
return -EINVAL;
memcpy(buf, pEntry->mode, 3);
- ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
+ ret = send_video_command(pdev, pdev->vendpoint, buf, 3);
if (ret < 0) {
PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret);
return ret;
@@ -285,7 +317,7 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, i
memcpy(buf, pChoose->mode, 13);
if (snapshot)
buf[0] |= 0x80;
- ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 13);
+ ret = send_video_command(pdev, pdev->vendpoint, buf, 13);
if (ret < 0)
return ret;
@@ -358,7 +390,7 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, i
buf[0] |= 0x80;
/* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */
- ret = send_video_command(pdev->udev, 4 /* pdev->vendpoint */, buf, 12);
+ ret = send_video_command(pdev, 4 /* pdev->vendpoint */, buf, 12);
if (ret < 0)
return ret;
@@ -530,7 +562,8 @@ int pwc_get_brightness(struct pwc_device *pdev)
char buf;
int ret;
- ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1);
+ ret = recv_control_msg(pdev,
+ GET_LUM_CTL, BRIGHTNESS_FORMATTER, &buf, sizeof(buf));
if (ret < 0)
return ret;
return buf;
@@ -545,7 +578,8 @@ int pwc_set_brightness(struct pwc_device *pdev, int value)
if (value > 0xffff)
value = 0xffff;
buf = (value >> 9) & 0x7f;
- return SendControlMsg(SET_LUM_CTL, BRIGHTNESS_FORMATTER, 1);
+ return send_control_msg(pdev,
+ SET_LUM_CTL, BRIGHTNESS_FORMATTER, &buf, sizeof(buf));
}
/* CONTRAST */
@@ -555,7 +589,8 @@ int pwc_get_contrast(struct pwc_device *pdev)
char buf;
int ret;
- ret = RecvControlMsg(GET_LUM_CTL, CONTRAST_FORMATTER, 1);
+ ret = recv_control_msg(pdev,
+ GET_LUM_CTL, CONTRAST_FORMATTER, &buf, sizeof(buf));
if (ret < 0)
return ret;
return buf;
@@ -570,7 +605,8 @@ int pwc_set_contrast(struct pwc_device *pdev, int value)
if (value > 0xffff)
value = 0xffff;
buf = (value >> 10) & 0x3f;
- return SendControlMsg(SET_LUM_CTL, CONTRAST_FORMATTER, 1);
+ return send_control_msg(pdev,
+ SET_LUM_CTL, CONTRAST_FORMATTER, &buf, sizeof(buf));
}
/* GAMMA */
@@ -580,7 +616,8 @@ int pwc_get_gamma(struct pwc_device *pdev)
char buf;
int ret;
- ret = RecvControlMsg(GET_LUM_CTL, GAMMA_FORMATTER, 1);
+ ret = recv_control_msg(pdev,
+ GET_LUM_CTL, GAMMA_FORMATTER, &buf, sizeof(buf));
if (ret < 0)
return ret;
return buf;
@@ -595,7 +632,8 @@ int pwc_set_gamma(struct pwc_device *pdev, int value)
if (value > 0xffff)
value = 0xffff;
buf = (value >> 11) & 0x1f;
- return SendControlMsg(SET_LUM_CTL, GAMMA_FORMATTER, 1);
+ return send_control_msg(pdev,
+ SET_LUM_CTL, GAMMA_FORMATTER, &buf, sizeof(buf));
}
@@ -613,7 +651,8 @@ int pwc_get_saturation(struct pwc_device *pdev, int *value)
saturation_register = SATURATION_MODE_FORMATTER2;
else
saturation_register = SATURATION_MODE_FORMATTER1;
- ret = RecvControlMsg(GET_CHROM_CTL, saturation_register, 1);
+ ret = recv_control_msg(pdev,
+ GET_CHROM_CTL, saturation_register, &buf, sizeof(buf));
if (ret < 0)
return ret;
*value = (signed)buf;
@@ -636,7 +675,8 @@ int pwc_set_saturation(struct pwc_device *pdev, int value)
saturation_register = SATURATION_MODE_FORMATTER2;
else
saturation_register = SATURATION_MODE_FORMATTER1;
- return SendControlMsg(SET_CHROM_CTL, saturation_register, 1);
+ return send_control_msg(pdev,
+ SET_CHROM_CTL, saturation_register, &buf, sizeof(buf));
}
/* AGC */
@@ -651,7 +691,8 @@ int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
else
buf = 0xff; /* fixed */
- ret = SendControlMsg(SET_LUM_CTL, AGC_MODE_FORMATTER, 1);
+ ret = send_control_msg(pdev,
+ SET_LUM_CTL, AGC_MODE_FORMATTER, &buf, sizeof(buf));
if (!mode && ret >= 0) {
if (value < 0)
@@ -659,7 +700,8 @@ int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
if (value > 0xffff)
value = 0xffff;
buf = (value >> 10) & 0x3F;
- ret = SendControlMsg(SET_LUM_CTL, PRESET_AGC_FORMATTER, 1);
+ ret = send_control_msg(pdev,
+ SET_LUM_CTL, PRESET_AGC_FORMATTER, &buf, sizeof(buf));
}
if (ret < 0)
return ret;
@@ -671,12 +713,14 @@ int pwc_get_agc(struct pwc_device *pdev, int *value)
unsigned char buf;
int ret;
- ret = RecvControlMsg(GET_LUM_CTL, AGC_MODE_FORMATTER, 1);
+ ret = recv_control_msg(pdev,
+ GET_LUM_CTL, AGC_MODE_FORMATTER, &buf, sizeof(buf));
if (ret < 0)
return ret;
if (buf != 0) { /* fixed */
- ret = RecvControlMsg(GET_LUM_CTL, PRESET_AGC_FORMATTER, 1);
+ ret = recv_control_msg(pdev,
+ GET_LUM_CTL, PRESET_AGC_FORMATTER, &buf, sizeof(buf));
if (ret < 0)
return ret;
if (buf > 0x3F)
@@ -684,7 +728,8 @@ int pwc_get_agc(struct pwc_device *pdev, int *value)
*value = (buf << 10);
}
else { /* auto */
- ret = RecvControlMsg(GET_STATUS_CTL, READ_AGC_FORMATTER, 1);
+ ret = recv_control_msg(pdev,
+ GET_STATUS_CTL, READ_AGC_FORMATTER, &buf, sizeof(buf));
if (ret < 0)
return ret;
/* Gah... this value ranges from 0x00 ... 0x9F */
@@ -707,7 +752,8 @@ int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value)
else
buf[0] = 0xff; /* fixed */
- ret = SendControlMsg(SET_LUM_CTL, SHUTTER_MODE_FORMATTER, 1);
+ ret = send_control_msg(pdev,
+ SET_LUM_CTL, SHUTTER_MODE_FORMATTER, &buf, sizeof(buf));
if (!mode && ret >= 0) {
if (value < 0)
@@ -726,7 +772,9 @@ int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value)
buf[0] = value >> 8;
}
- ret = SendControlMsg(SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, 2);
+ ret = send_control_msg(pdev,
+ SET_LUM_CTL, PRESET_SHUTTER_FORMATTER,
+ &buf, sizeof(buf));
}
return ret;
}
@@ -737,7 +785,8 @@ int pwc_get_shutter_speed(struct pwc_device *pdev, int *value)
unsigned char buf[2];
int ret;
- ret = RecvControlMsg(GET_STATUS_CTL, READ_SHUTTER_FORMATTER, 2);
+ ret = recv_control_msg(pdev,
+ GET_STATUS_CTL, READ_SHUTTER_FORMATTER, &buf, sizeof(buf));
if (ret < 0)
return ret;
*value = buf[0] + (buf[1] << 8);
@@ -764,7 +813,9 @@ int pwc_camera_power(struct pwc_device *pdev, int power)
buf = 0x00; /* active */
else
buf = 0xFF; /* power save */
- return SendControlMsg(SET_STATUS_CTL, SET_POWER_SAVE_MODE_FORMATTER, 1);
+ return send_control_msg(pdev,
+ SET_STATUS_CTL, SET_POWER_SAVE_MODE_FORMATTER,
+ &buf, sizeof(buf));
}
@@ -773,20 +824,20 @@ int pwc_camera_power(struct pwc_device *pdev, int power)
int pwc_restore_user(struct pwc_device *pdev)
{
- char buf; /* dummy */
- return SendControlMsg(SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, 0);
+ return send_control_msg(pdev,
+ SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, NULL, 0);
}
int pwc_save_user(struct pwc_device *pdev)
{
- char buf; /* dummy */
- return SendControlMsg(SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, 0);
+ return send_control_msg(pdev,
+ SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, NULL, 0);
}
int pwc_restore_factory(struct pwc_device *pdev)
{
- char buf; /* dummy */
- return SendControlMsg(SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, 0);
+ return send_control_msg(pdev,
+ SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, NULL, 0);
}
/* ************************************************* */
@@ -814,7 +865,8 @@ int pwc_set_awb(struct pwc_device *pdev, int mode)
buf = mode & 0x07; /* just the lowest three bits */
- ret = SendControlMsg(SET_CHROM_CTL, WB_MODE_FORMATTER, 1);
+ ret = send_control_msg(pdev,
+ SET_CHROM_CTL, WB_MODE_FORMATTER, &buf, sizeof(buf));
if (ret < 0)
return ret;
@@ -826,7 +878,8 @@ int pwc_get_awb(struct pwc_device *pdev)
unsigned char buf;
int ret;
- ret = RecvControlMsg(GET_CHROM_CTL, WB_MODE_FORMATTER, 1);
+ ret = recv_control_msg(pdev,
+ GET_CHROM_CTL, WB_MODE_FORMATTER, &buf, sizeof(buf));
if (ret < 0)
return ret;
@@ -843,7 +896,9 @@ int pwc_set_red_gain(struct pwc_device *pdev, int value)
value = 0xffff;
/* only the msb is considered */
buf = value >> 8;
- return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1);
+ return send_control_msg(pdev,
+ SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER,
+ &buf, sizeof(buf));
}
int pwc_get_red_gain(struct pwc_device *pdev, int *value)
@@ -851,7 +906,9 @@ int pwc_get_red_gain(struct pwc_device *pdev, int *value)
unsigned char buf;
int ret;
- ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1);
+ ret = recv_control_msg(pdev,
+ GET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER,
+ &buf, sizeof(buf));
if (ret < 0)
return ret;
*value = buf << 8;
@@ -869,7 +926,9 @@ int pwc_set_blue_gain(struct pwc_device *pdev, int value)
value = 0xffff;
/* only the msb is considered */
buf = value >> 8;
- return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1);
+ return send_control_msg(pdev,
+ SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER,
+ &buf, sizeof(buf));
}
int pwc_get_blue_gain(struct pwc_device *pdev, int *value)
@@ -877,7 +936,9 @@ int pwc_get_blue_gain(struct pwc_device *pdev, int *value)
unsigned char buf;
int ret;
- ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1);
+ ret = recv_control_msg(pdev,
+ GET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER,
+ &buf, sizeof(buf));
if (ret < 0)
return ret;
*value = buf << 8;
@@ -894,7 +955,8 @@ static int pwc_read_red_gain(struct pwc_device *pdev, int *value)
unsigned char buf;
int ret;
- ret = RecvControlMsg(GET_STATUS_CTL, READ_RED_GAIN_FORMATTER, 1);
+ ret = recv_control_msg(pdev,
+ GET_STATUS_CTL, READ_RED_GAIN_FORMATTER, &buf, sizeof(buf));
if (ret < 0)
return ret;
*value = buf << 8;
@@ -906,7 +968,8 @@ static int pwc_read_blue_gain(struct pwc_device *pdev, int *value)
unsigned char buf;
int ret;
- ret = RecvControlMsg(GET_STATUS_CTL, READ_BLUE_GAIN_FORMATTER, 1);
+ ret = recv_control_msg(pdev,
+ GET_STATUS_CTL, READ_BLUE_GAIN_FORMATTER, &buf, sizeof(buf));
if (ret < 0)
return ret;
*value = buf << 8;
@@ -920,7 +983,8 @@ static int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
/* useful range is 0x01..0x20 */
buf = speed / 0x7f0;
- return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1);
+ return send_control_msg(pdev,
+ SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, &buf, sizeof(buf));
}
static int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
@@ -928,7 +992,8 @@ static int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
unsigned char buf;
int ret;
- ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1);
+ ret = recv_control_msg(pdev,
+ GET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, &buf, sizeof(buf));
if (ret < 0)
return ret;
*value = buf * 0x7f0;
@@ -942,7 +1007,8 @@ static int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
/* useful range is 0x01..0x3F */
buf = (delay >> 10);
- return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1);
+ return send_control_msg(pdev,
+ SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, &buf, sizeof(buf));
}
static int pwc_get_wb_delay(struct pwc_device *pdev, int *value)
@@ -950,7 +1016,8 @@ static int pwc_get_wb_delay(struct pwc_device *pdev, int *value)
unsigned char buf;
int ret;
- ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1);
+ ret = recv_control_msg(pdev,
+ GET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, &buf, sizeof(buf));
if (ret < 0)
return ret;
*value = buf << 10;
@@ -978,7 +1045,8 @@ int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
buf[0] = on_value;
buf[1] = off_value;
- return SendControlMsg(SET_STATUS_CTL, LED_FORMATTER, 2);
+ return send_control_msg(pdev,
+ SET_STATUS_CTL, LED_FORMATTER, &buf, sizeof(buf));
}
static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
@@ -992,7 +1060,8 @@ static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
return 0;
}
- ret = RecvControlMsg(GET_STATUS_CTL, LED_FORMATTER, 2);
+ ret = recv_control_msg(pdev,
+ GET_STATUS_CTL, LED_FORMATTER, &buf, sizeof(buf));
if (ret < 0)
return ret;
*on_value = buf[0] * 100;
@@ -1009,7 +1078,8 @@ int pwc_set_contour(struct pwc_device *pdev, int contour)
buf = 0xff; /* auto contour on */
else
buf = 0x0; /* auto contour off */
- ret = SendControlMsg(SET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1);
+ ret = send_control_msg(pdev,
+ SET_LUM_CTL, AUTO_CONTOUR_FORMATTER, &buf, sizeof(buf));
if (ret < 0)
return ret;
@@ -1019,7 +1089,8 @@ int pwc_set_contour(struct pwc_device *pdev, int contour)
contour = 0xffff;
buf = (contour >> 10); /* contour preset is [0..3f] */
- ret = SendControlMsg(SET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1);
+ ret = send_control_msg(pdev,
+ SET_LUM_CTL, PRESET_CONTOUR_FORMATTER, &buf, sizeof(buf));
if (ret < 0)
return ret;
return 0;
@@ -1030,13 +1101,16 @@ int pwc_get_contour(struct pwc_device *pdev, int *contour)
unsigned char buf;
int ret;
- ret = RecvControlMsg(GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1);
+ ret = recv_control_msg(pdev,
+ GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, &buf, sizeof(buf));
if (ret < 0)
return ret;
if (buf == 0) {
/* auto mode off, query current preset value */
- ret = RecvControlMsg(GET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1);
+ ret = recv_control_msg(pdev,
+ GET_LUM_CTL, PRESET_CONTOUR_FORMATTER,
+ &buf, sizeof(buf));
if (ret < 0)
return ret;
*contour = buf << 10;
@@ -1055,7 +1129,9 @@ int pwc_set_backlight(struct pwc_device *pdev, int backlight)
buf = 0xff;
else
buf = 0x0;
- return SendControlMsg(SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1);
+ return send_control_msg(pdev,
+ SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER,
+ &buf, sizeof(buf));
}
int pwc_get_backlight(struct pwc_device *pdev, int *backlight)
@@ -1063,7 +1139,9 @@ int pwc_get_backlight(struct pwc_device *pdev, int *backlight)
int ret;
unsigned char buf;
- ret = RecvControlMsg(GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1);
+ ret = recv_control_msg(pdev,
+ GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER,
+ &buf, sizeof(buf));
if (ret < 0)
return ret;
*backlight = !!buf;
@@ -1078,7 +1156,8 @@ int pwc_set_colour_mode(struct pwc_device *pdev, int colour)
buf = 0xff;
else
buf = 0x0;
- return SendControlMsg(SET_CHROM_CTL, COLOUR_MODE_FORMATTER, 1);
+ return send_control_msg(pdev,
+ SET_CHROM_CTL, COLOUR_MODE_FORMATTER, &buf, sizeof(buf));
}
int pwc_get_colour_mode(struct pwc_device *pdev, int *colour)
@@ -1086,7 +1165,8 @@ int pwc_get_colour_mode(struct pwc_device *pdev, int *colour)
int ret;
unsigned char buf;
- ret = RecvControlMsg(GET_CHROM_CTL, COLOUR_MODE_FORMATTER, 1);
+ ret = recv_control_msg(pdev,
+ GET_CHROM_CTL, COLOUR_MODE_FORMATTER, &buf, sizeof(buf));
if (ret < 0)
return ret;
*colour = !!buf;
@@ -1102,7 +1182,8 @@ int pwc_set_flicker(struct pwc_device *pdev, int flicker)
buf = 0xff;
else
buf = 0x0;
- return SendControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
+ return send_control_msg(pdev,
+ SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, &buf, sizeof(buf));
}
int pwc_get_flicker(struct pwc_device *pdev, int *flicker)
@@ -1110,7 +1191,8 @@ int pwc_get_flicker(struct pwc_device *pdev, int *flicker)
int ret;
unsigned char buf;
- ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
+ ret = recv_control_msg(pdev,
+ GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, &buf, sizeof(buf));
if (ret < 0)
return ret;
*flicker = !!buf;
@@ -1126,7 +1208,9 @@ int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
if (noise > 3)
noise = 3;
buf = noise;
- return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
+ return send_control_msg(pdev,
+ SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER,
+ &buf, sizeof(buf));
}
int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
@@ -1134,7 +1218,9 @@ int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
int ret;
unsigned char buf;
- ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
+ ret = recv_control_msg(pdev,
+ GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER,
+ &buf, sizeof(buf));
if (ret < 0)
return ret;
*noise = buf;
@@ -1146,7 +1232,8 @@ static int _pwc_mpt_reset(struct pwc_device *pdev, int flags)
unsigned char buf;
buf = flags & 0x03; // only lower two bits are currently used
- return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1);
+ return send_control_msg(pdev,
+ SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, &buf, sizeof(buf));
}
int pwc_mpt_reset(struct pwc_device *pdev, int flags)
@@ -1175,7 +1262,8 @@ static int _pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
buf[1] = (pan >> 8) & 0xFF;
buf[2] = tilt & 0xFF;
buf[3] = (tilt >> 8) & 0xFF;
- return SendControlMsg(SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, 4);
+ return send_control_msg(pdev,
+ SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, &buf, sizeof(buf));
}
int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
@@ -1211,7 +1299,8 @@ static int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *st
int ret;
unsigned char buf[5];
- ret = RecvControlMsg(GET_MPT_CTL, PT_STATUS_FORMATTER, 5);
+ ret = recv_control_msg(pdev,
+ GET_MPT_CTL, PT_STATUS_FORMATTER, &buf, sizeof(buf));
if (ret < 0)
return ret;
status->status = buf[0] & 0x7; // 3 bits are used for reporting
@@ -1233,7 +1322,8 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
else
request = SENSOR_TYPE_FORMATTER2;
- ret = RecvControlMsg(GET_STATUS_CTL, request, 1);
+ ret = recv_control_msg(pdev,
+ GET_STATUS_CTL, request, &buf, sizeof(buf));
if (ret < 0)
return ret;
if (pdev->type < 675)
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index c639845460ff..2da5eef19b70 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -202,7 +202,7 @@ struct pxa_buffer {
};
struct pxa_camera_dev {
- struct device *dev;
+ struct soc_camera_host soc_host;
/* PXA27x is only supposed to handle one camera on its Quick Capture
* interface. If anyone ever builds hardware to enable more than
* one camera, they will have to modify this driver too */
@@ -261,7 +261,6 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf)
{
struct soc_camera_device *icd = vq->priv_data;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
- struct pxa_camera_dev *pcdev = ici->priv;
struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
int i;
@@ -278,7 +277,7 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf)
for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) {
if (buf->dmas[i].sg_cpu)
- dma_free_coherent(pcdev->dev, buf->dmas[i].sg_size,
+ dma_free_coherent(ici->dev, buf->dmas[i].sg_size,
buf->dmas[i].sg_cpu,
buf->dmas[i].sg_dma);
buf->dmas[i].sg_cpu = NULL;
@@ -338,14 +337,14 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev,
int dma_len = 0, xfer_len = 0;
if (pxa_dma->sg_cpu)
- dma_free_coherent(pcdev->dev, pxa_dma->sg_size,
+ dma_free_coherent(pcdev->soc_host.dev, pxa_dma->sg_size,
pxa_dma->sg_cpu, pxa_dma->sg_dma);
sglen = calculate_dma_sglen(*sg_first, dma->sglen,
*sg_first_ofs, size);
pxa_dma->sg_size = (sglen + 1) * sizeof(struct pxa_dma_desc);
- pxa_dma->sg_cpu = dma_alloc_coherent(pcdev->dev, pxa_dma->sg_size,
+ pxa_dma->sg_cpu = dma_alloc_coherent(pcdev->soc_host.dev, pxa_dma->sg_size,
&pxa_dma->sg_dma, GFP_KERNEL);
if (!pxa_dma->sg_cpu)
return -ENOMEM;
@@ -353,7 +352,7 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev,
pxa_dma->sglen = sglen;
offset = *sg_first_ofs;
- dev_dbg(pcdev->dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n",
+ dev_dbg(pcdev->soc_host.dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n",
*sg_first, sglen, *sg_first_ofs, pxa_dma->sg_dma);
@@ -376,7 +375,7 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev,
pxa_dma->sg_cpu[i].ddadr =
pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc);
- dev_vdbg(pcdev->dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n",
+ dev_vdbg(pcdev->soc_host.dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n",
pxa_dma->sg_dma + i * sizeof(struct pxa_dma_desc),
sg_dma_address(sg) + offset, xfer_len);
offset = 0;
@@ -488,7 +487,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
ret = pxa_init_dma_channel(pcdev, buf, dma, 0, CIBR0, size_y,
&sg, &next_ofs);
if (ret) {
- dev_err(pcdev->dev,
+ dev_err(pcdev->soc_host.dev,
"DMA initialization for Y/RGB failed\n");
goto fail;
}
@@ -498,7 +497,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
ret = pxa_init_dma_channel(pcdev, buf, dma, 1, CIBR1,
size_u, &sg, &next_ofs);
if (ret) {
- dev_err(pcdev->dev,
+ dev_err(pcdev->soc_host.dev,
"DMA initialization for U failed\n");
goto fail_u;
}
@@ -508,7 +507,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
ret = pxa_init_dma_channel(pcdev, buf, dma, 2, CIBR2,
size_v, &sg, &next_ofs);
if (ret) {
- dev_err(pcdev->dev,
+ dev_err(pcdev->soc_host.dev,
"DMA initialization for V failed\n");
goto fail_v;
}
@@ -522,10 +521,10 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
return 0;
fail_v:
- dma_free_coherent(pcdev->dev, buf->dmas[1].sg_size,
+ dma_free_coherent(pcdev->soc_host.dev, buf->dmas[1].sg_size,
buf->dmas[1].sg_cpu, buf->dmas[1].sg_dma);
fail_u:
- dma_free_coherent(pcdev->dev, buf->dmas[0].sg_size,
+ dma_free_coherent(pcdev->soc_host.dev, buf->dmas[0].sg_size,
buf->dmas[0].sg_cpu, buf->dmas[0].sg_dma);
fail:
free_buffer(vq, buf);
@@ -549,7 +548,7 @@ static void pxa_dma_start_channels(struct pxa_camera_dev *pcdev)
active = pcdev->active;
for (i = 0; i < pcdev->channels; i++) {
- dev_dbg(pcdev->dev, "%s (channel=%d) ddadr=%08x\n", __func__,
+ dev_dbg(pcdev->soc_host.dev, "%s (channel=%d) ddadr=%08x\n", __func__,
i, active->dmas[i].sg_dma);
DDADR(pcdev->dma_chans[i]) = active->dmas[i].sg_dma;
DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
@@ -561,7 +560,7 @@ static void pxa_dma_stop_channels(struct pxa_camera_dev *pcdev)
int i;
for (i = 0; i < pcdev->channels; i++) {
- dev_dbg(pcdev->dev, "%s (channel=%d)\n", __func__, i);
+ dev_dbg(pcdev->soc_host.dev, "%s (channel=%d)\n", __func__, i);
DCSR(pcdev->dma_chans[i]) = 0;
}
}
@@ -597,7 +596,7 @@ static void pxa_camera_start_capture(struct pxa_camera_dev *pcdev)
{
unsigned long cicr0, cifr;
- dev_dbg(pcdev->dev, "%s\n", __func__);
+ dev_dbg(pcdev->soc_host.dev, "%s\n", __func__);
/* Reset the FIFOs */
cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F;
__raw_writel(cifr, pcdev->base + CIFR);
@@ -617,7 +616,7 @@ static void pxa_camera_stop_capture(struct pxa_camera_dev *pcdev)
__raw_writel(cicr0, pcdev->base + CICR0);
pcdev->active = NULL;
- dev_dbg(pcdev->dev, "%s\n", __func__);
+ dev_dbg(pcdev->soc_host.dev, "%s\n", __func__);
}
static void pxa_videobuf_queue(struct videobuf_queue *vq,
@@ -686,7 +685,7 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev,
do_gettimeofday(&vb->ts);
vb->field_count++;
wake_up(&vb->done);
- dev_dbg(pcdev->dev, "%s dequeud buffer (vb=0x%p)\n", __func__, vb);
+ dev_dbg(pcdev->soc_host.dev, "%s dequeud buffer (vb=0x%p)\n", __func__, vb);
if (list_empty(&pcdev->capture)) {
pxa_camera_stop_capture(pcdev);
@@ -722,7 +721,7 @@ static void pxa_camera_check_link_miss(struct pxa_camera_dev *pcdev)
for (i = 0; i < pcdev->channels; i++)
if (DDADR(pcdev->dma_chans[i]) != DDADR_STOP)
is_dma_stopped = 0;
- dev_dbg(pcdev->dev, "%s : top queued buffer=%p, dma_stopped=%d\n",
+ dev_dbg(pcdev->soc_host.dev, "%s : top queued buffer=%p, dma_stopped=%d\n",
__func__, pcdev->active, is_dma_stopped);
if (pcdev->active && is_dma_stopped)
pxa_camera_start_capture(pcdev);
@@ -747,12 +746,12 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
overrun |= CISR_IFO_1 | CISR_IFO_2;
if (status & DCSR_BUSERR) {
- dev_err(pcdev->dev, "DMA Bus Error IRQ!\n");
+ dev_err(pcdev->soc_host.dev, "DMA Bus Error IRQ!\n");
goto out;
}
if (!(status & (DCSR_ENDINTR | DCSR_STARTINTR))) {
- dev_err(pcdev->dev, "Unknown DMA IRQ source, "
+ dev_err(pcdev->soc_host.dev, "Unknown DMA IRQ source, "
"status: 0x%08x\n", status);
goto out;
}
@@ -776,7 +775,7 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
buf = container_of(vb, struct pxa_buffer, vb);
WARN_ON(buf->inwork || list_empty(&vb->queue));
- dev_dbg(pcdev->dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n",
+ dev_dbg(pcdev->soc_host.dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n",
__func__, channel, status & DCSR_STARTINTR ? "SOF " : "",
status & DCSR_ENDINTR ? "EOF " : "", vb, DDADR(channel));
@@ -787,7 +786,7 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
*/
if (camera_status & overrun &&
!list_is_last(pcdev->capture.next, &pcdev->capture)) {
- dev_dbg(pcdev->dev, "FIFO overrun! CISR: %x\n",
+ dev_dbg(pcdev->soc_host.dev, "FIFO overrun! CISR: %x\n",
camera_status);
pxa_camera_stop_capture(pcdev);
pxa_camera_start_capture(pcdev);
@@ -854,7 +853,7 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
/* mclk <= ciclk / 4 (27.4.2) */
if (mclk > lcdclk / 4) {
mclk = lcdclk / 4;
- dev_warn(pcdev->dev, "Limiting master clock to %lu\n", mclk);
+ dev_warn(pcdev->soc_host.dev, "Limiting master clock to %lu\n", mclk);
}
/* We verify mclk != 0, so if anyone breaks it, here comes their Oops */
@@ -864,7 +863,7 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
pcdev->mclk = lcdclk / (2 * (div + 1));
- dev_dbg(pcdev->dev, "LCD clock %luHz, target freq %luHz, "
+ dev_dbg(pcdev->soc_host.dev, "LCD clock %luHz, target freq %luHz, "
"divisor %u\n", lcdclk, mclk, div);
return div;
@@ -884,12 +883,12 @@ static void pxa_camera_activate(struct pxa_camera_dev *pcdev)
struct pxacamera_platform_data *pdata = pcdev->pdata;
u32 cicr4 = 0;
- dev_dbg(pcdev->dev, "Registered platform device at %p data %p\n",
+ dev_dbg(pcdev->soc_host.dev, "Registered platform device at %p data %p\n",
pcdev, pdata);
if (pdata && pdata->init) {
- dev_dbg(pcdev->dev, "%s: Init gpios\n", __func__);
- pdata->init(pcdev->dev);
+ dev_dbg(pcdev->soc_host.dev, "%s: Init gpios\n", __func__);
+ pdata->init(pcdev->soc_host.dev);
}
/* disable all interrupts */
@@ -931,7 +930,7 @@ static irqreturn_t pxa_camera_irq(int irq, void *data)
struct videobuf_buffer *vb;
status = __raw_readl(pcdev->base + CISR);
- dev_dbg(pcdev->dev, "Camera interrupt status 0x%lx\n", status);
+ dev_dbg(pcdev->soc_host.dev, "Camera interrupt status 0x%lx\n", status);
if (!status)
return IRQ_NONE;
@@ -1259,7 +1258,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx,
xlate->cam_fmt = icd->formats + idx;
xlate->buswidth = buswidth;
xlate++;
- dev_dbg(&ici->dev, "Providing format %s using %s\n",
+ dev_dbg(ici->dev, "Providing format %s using %s\n",
pxa_camera_formats[0].name,
icd->formats[idx].name);
}
@@ -1274,7 +1273,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx,
xlate->cam_fmt = icd->formats + idx;
xlate->buswidth = buswidth;
xlate++;
- dev_dbg(&ici->dev, "Providing format %s packed\n",
+ dev_dbg(ici->dev, "Providing format %s packed\n",
icd->formats[idx].name);
}
break;
@@ -1286,7 +1285,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx,
xlate->cam_fmt = icd->formats + idx;
xlate->buswidth = icd->formats[idx].depth;
xlate++;
- dev_dbg(&ici->dev,
+ dev_dbg(ici->dev,
"Providing format %s in pass-through mode\n",
icd->formats[idx].name);
}
@@ -1315,11 +1314,11 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd,
icd->sense = NULL;
if (ret < 0) {
- dev_warn(&ici->dev, "Failed to crop to %ux%u@%u:%u\n",
+ dev_warn(ici->dev, "Failed to crop to %ux%u@%u:%u\n",
rect->width, rect->height, rect->left, rect->top);
} else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) {
if (sense.pixel_clock > sense.pixel_clock_max) {
- dev_err(&ici->dev,
+ dev_err(ici->dev,
"pixel clock %lu set by the camera too high!",
sense.pixel_clock);
return -EIO;
@@ -1347,7 +1346,7 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd,
xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
if (!xlate) {
- dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat);
+ dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat);
return -EINVAL;
}
@@ -1363,11 +1362,11 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd,
icd->sense = NULL;
if (ret < 0) {
- dev_warn(&ici->dev, "Failed to configure for format %x\n",
+ dev_warn(ici->dev, "Failed to configure for format %x\n",
pix->pixelformat);
} else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) {
if (sense.pixel_clock > sense.pixel_clock_max) {
- dev_err(&ici->dev,
+ dev_err(ici->dev,
"pixel clock %lu set by the camera too high!",
sense.pixel_clock);
return -EIO;
@@ -1395,7 +1394,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd,
xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
if (!xlate) {
- dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
+ dev_warn(ici->dev, "Format %x not found\n", pixfmt);
return -EINVAL;
}
@@ -1552,12 +1551,6 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
.set_bus_param = pxa_camera_set_bus_param,
};
-/* Should be allocated dynamically too, but we have only one. */
-static struct soc_camera_host pxa_soc_camera_host = {
- .drv_name = PXA_CAM_DRV_NAME,
- .ops = &pxa_soc_camera_host_ops,
-};
-
static int pxa_camera_probe(struct platform_device *pdev)
{
struct pxa_camera_dev *pcdev;
@@ -1586,7 +1579,6 @@ static int pxa_camera_probe(struct platform_device *pdev)
goto exit_kfree;
}
- dev_set_drvdata(&pdev->dev, pcdev);
pcdev->res = res;
pcdev->pdata = pdev->dev.platform_data;
@@ -1607,7 +1599,6 @@ static int pxa_camera_probe(struct platform_device *pdev)
pcdev->mclk = 20000000;
}
- pcdev->dev = &pdev->dev;
pcdev->mclk_divisor = mclk_get_divisor(pcdev);
INIT_LIST_HEAD(&pcdev->capture);
@@ -1616,13 +1607,13 @@ static int pxa_camera_probe(struct platform_device *pdev)
/*
* Request the regions.
*/
- if (!request_mem_region(res->start, res->end - res->start + 1,
+ if (!request_mem_region(res->start, resource_size(res),
PXA_CAM_DRV_NAME)) {
err = -EBUSY;
goto exit_clk;
}
- base = ioremap(res->start, res->end - res->start + 1);
+ base = ioremap(res->start, resource_size(res));
if (!base) {
err = -ENOMEM;
goto exit_release;
@@ -1634,29 +1625,29 @@ static int pxa_camera_probe(struct platform_device *pdev)
err = pxa_request_dma("CI_Y", DMA_PRIO_HIGH,
pxa_camera_dma_irq_y, pcdev);
if (err < 0) {
- dev_err(pcdev->dev, "Can't request DMA for Y\n");
+ dev_err(&pdev->dev, "Can't request DMA for Y\n");
goto exit_iounmap;
}
pcdev->dma_chans[0] = err;
- dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]);
+ dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]);
err = pxa_request_dma("CI_U", DMA_PRIO_HIGH,
pxa_camera_dma_irq_u, pcdev);
if (err < 0) {
- dev_err(pcdev->dev, "Can't request DMA for U\n");
+ dev_err(&pdev->dev, "Can't request DMA for U\n");
goto exit_free_dma_y;
}
pcdev->dma_chans[1] = err;
- dev_dbg(pcdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]);
+ dev_dbg(&pdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]);
err = pxa_request_dma("CI_V", DMA_PRIO_HIGH,
pxa_camera_dma_irq_v, pcdev);
if (err < 0) {
- dev_err(pcdev->dev, "Can't request DMA for V\n");
+ dev_err(&pdev->dev, "Can't request DMA for V\n");
goto exit_free_dma_u;
}
pcdev->dma_chans[2] = err;
- dev_dbg(pcdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]);
+ dev_dbg(&pdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]);
DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD;
DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD;
@@ -1666,14 +1657,17 @@ static int pxa_camera_probe(struct platform_device *pdev)
err = request_irq(pcdev->irq, pxa_camera_irq, 0, PXA_CAM_DRV_NAME,
pcdev);
if (err) {
- dev_err(pcdev->dev, "Camera interrupt register failed \n");
+ dev_err(&pdev->dev, "Camera interrupt register failed \n");
goto exit_free_dma;
}
- pxa_soc_camera_host.priv = pcdev;
- pxa_soc_camera_host.dev.parent = &pdev->dev;
- pxa_soc_camera_host.nr = pdev->id;
- err = soc_camera_host_register(&pxa_soc_camera_host);
+ pcdev->soc_host.drv_name = PXA_CAM_DRV_NAME;
+ pcdev->soc_host.ops = &pxa_soc_camera_host_ops;
+ pcdev->soc_host.priv = pcdev;
+ pcdev->soc_host.dev = &pdev->dev;
+ pcdev->soc_host.nr = pdev->id;
+
+ err = soc_camera_host_register(&pcdev->soc_host);
if (err)
goto exit_free_irq;
@@ -1690,7 +1684,7 @@ exit_free_dma_y:
exit_iounmap:
iounmap(base);
exit_release:
- release_mem_region(res->start, res->end - res->start + 1);
+ release_mem_region(res->start, resource_size(res));
exit_clk:
clk_put(pcdev->clk);
exit_kfree:
@@ -1701,7 +1695,9 @@ exit:
static int __devexit pxa_camera_remove(struct platform_device *pdev)
{
- struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev);
+ struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
+ struct pxa_camera_dev *pcdev = container_of(soc_host,
+ struct pxa_camera_dev, soc_host);
struct resource *res;
clk_put(pcdev->clk);
@@ -1711,12 +1707,12 @@ static int __devexit pxa_camera_remove(struct platform_device *pdev)
pxa_free_dma(pcdev->dma_chans[2]);
free_irq(pcdev->irq, pcdev);
- soc_camera_host_unregister(&pxa_soc_camera_host);
+ soc_camera_host_unregister(soc_host);
iounmap(pcdev->base);
res = pcdev->res;
- release_mem_region(res->start, res->end - res->start + 1);
+ release_mem_region(res->start, resource_size(res));
kfree(pcdev);
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c
index 5202cadb2aae..90e1dbc1aa89 100644
--- a/drivers/media/video/s2255drv.c
+++ b/drivers/media/video/s2255drv.c
@@ -77,6 +77,8 @@
#define MAX_CHANNELS 4
#define S2255_MARKER_FRAME 0x2255DA4AL
#define S2255_MARKER_RESPONSE 0x2255ACACL
+#define S2255_RESPONSE_SETMODE 0x01
+#define S2255_RESPONSE_FW 0x10
#define S2255_USB_XFER_SIZE (16 * 1024)
#define MAX_CHANNELS 4
#define MAX_PIPE_BUFFERS 1
@@ -178,9 +180,6 @@ struct s2255_bufferi {
struct s2255_dmaqueue {
struct list_head active;
- /* thread for acquisition */
- struct task_struct *kthread;
- int frame;
struct s2255_dev *dev;
int channel;
};
@@ -210,16 +209,11 @@ struct s2255_pipeinfo {
u32 max_transfer_size;
u32 cur_transfer_size;
u8 *transfer_buffer;
- u32 transfer_flags;;
u32 state;
- u32 prev_state;
- u32 urb_size;
void *stream_urb;
void *dev; /* back pointer to s2255_dev struct*/
u32 err_count;
- u32 buf_index;
u32 idx;
- u32 priority_set;
};
struct s2255_fmt; /*forward declaration */
@@ -239,8 +233,6 @@ struct s2255_dev {
struct list_head s2255_devlist;
struct timer_list timer;
struct s2255_fw *fw_data;
- int board_num;
- int is_open;
struct s2255_pipeinfo pipes[MAX_PIPE_BUFFERS];
struct s2255_bufferi buffer[MAX_CHANNELS];
struct s2255_mode mode[MAX_CHANNELS];
@@ -297,9 +289,10 @@ struct s2255_fh {
int resources[MAX_CHANNELS];
};
-#define CUR_USB_FWVER 774 /* current cypress EEPROM firmware version */
+/* current cypress EEPROM firmware version */
+#define S2255_CUR_USB_FWVER ((3 << 8) | 6)
#define S2255_MAJOR_VERSION 1
-#define S2255_MINOR_VERSION 13
+#define S2255_MINOR_VERSION 14
#define S2255_RELEASE 0
#define S2255_VERSION KERNEL_VERSION(S2255_MAJOR_VERSION, \
S2255_MINOR_VERSION, \
@@ -1237,6 +1230,7 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
buffer[1] = (u32) chn_rev;
buffer[2] = CMD_SET_MODE;
memcpy(&buffer[3], &dev->mode[chn], sizeof(struct s2255_mode));
+ dev->setmode_ready[chn] = 0;
res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
if (debug)
dump_verify_mode(dev, mode);
@@ -1245,7 +1239,6 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
/* wait at least 3 frames before continuing */
if (mode->restart) {
- dev->setmode_ready[chn] = 0;
wait_event_timeout(dev->wait_setmode[chn],
(dev->setmode_ready[chn] != 0),
msecs_to_jiffies(S2255_SETMODE_TIMEOUT));
@@ -1818,7 +1811,6 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
INIT_LIST_HEAD(&dev->vidq[i].active);
dev->vidq[i].dev = dev;
dev->vidq[i].channel = i;
- dev->vidq[i].kthread = NULL;
/* register 4 video devices */
dev->vdev[i] = video_device_alloc();
memcpy(dev->vdev[i], &template, sizeof(struct video_device));
@@ -1839,7 +1831,9 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
return ret;
}
}
- printk(KERN_INFO "Sensoray 2255 V4L driver\n");
+ printk(KERN_INFO "Sensoray 2255 V4L driver Revision: %d.%d\n",
+ S2255_MAJOR_VERSION,
+ S2255_MINOR_VERSION);
return ret;
}
@@ -1929,14 +1923,14 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
if (!(cc >= 0 && cc < MAX_CHANNELS))
break;
switch (pdword[2]) {
- case 0x01:
+ case S2255_RESPONSE_SETMODE:
/* check if channel valid */
/* set mode ready */
dev->setmode_ready[cc] = 1;
wake_up(&dev->wait_setmode[cc]);
dprintk(5, "setmode ready %d\n", cc);
break;
- case 0x10:
+ case S2255_RESPONSE_FW:
dev->chn_ready |= (1 << cc);
if ((dev->chn_ready & 0x0f) != 0x0f)
@@ -2172,10 +2166,15 @@ static int s2255_board_init(struct s2255_dev *dev)
/* query the firmware */
fw_ver = s2255_get_fx2fw(dev);
- printk(KERN_INFO "2255 usb firmware version %d \n", fw_ver);
- if (fw_ver < CUR_USB_FWVER)
+ printk(KERN_INFO "2255 usb firmware version %d.%d\n",
+ (fw_ver >> 8) & 0xff,
+ fw_ver & 0xff);
+
+ if (fw_ver < S2255_CUR_USB_FWVER)
dev_err(&dev->udev->dev,
- "usb firmware not up to date %d\n", fw_ver);
+ "usb firmware not up to date %d.%d\n",
+ (fw_ver >> 8) & 0xff,
+ fw_ver & 0xff);
for (j = 0; j < MAX_CHANNELS; j++) {
dev->b_acquire[j] = 0;
@@ -2283,8 +2282,7 @@ static int s2255_start_readpipe(struct s2255_dev *dev)
for (i = 0; i < MAX_PIPE_BUFFERS; i++) {
pipe_info->state = 1;
- pipe_info->buf_index = (u32) i;
- pipe_info->priority_set = 0;
+ pipe_info->err_count = 0;
pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!pipe_info->stream_urb) {
dev_err(&dev->udev->dev,
@@ -2298,7 +2296,6 @@ static int s2255_start_readpipe(struct s2255_dev *dev)
pipe_info->cur_transfer_size,
read_pipe_completion, pipe_info);
- pipe_info->urb_size = sizeof(pipe_info->stream_urb);
dprintk(4, "submitting URB %p\n", pipe_info->stream_urb);
retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL);
if (retval) {
@@ -2403,8 +2400,6 @@ static void s2255_stop_readpipe(struct s2255_dev *dev)
if (pipe_info->state == 0)
continue;
pipe_info->state = 0;
- pipe_info->prev_state = 1;
-
}
}
@@ -2542,7 +2537,9 @@ static int s2255_probe(struct usb_interface *interface,
s2255_probe_v4l(dev);
usb_reset_device(dev->udev);
/* load 2255 board specific */
- s2255_board_init(dev);
+ retval = s2255_board_init(dev);
+ if (retval)
+ goto error;
dprintk(4, "before probe done %p\n", dev);
spin_lock_init(&dev->slock);
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c
index da47b2f05288..155804b061e9 100644
--- a/drivers/media/video/saa5246a.c
+++ b/drivers/media/video/saa5246a.c
@@ -1092,9 +1092,8 @@ static int saa5246a_probe(struct i2c_client *client,
/* Register it */
err = video_register_device(t->vdev, VFL_TYPE_VTX, -1);
if (err < 0) {
- kfree(t);
video_device_release(t->vdev);
- t->vdev = NULL;
+ kfree(t);
return err;
}
return 0;
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
index 48b27fe48087..271d6e931b75 100644
--- a/drivers/media/video/saa5249.c
+++ b/drivers/media/video/saa5249.c
@@ -598,6 +598,7 @@ static int saa5249_probe(struct i2c_client *client,
/* Now create a video4linux device */
t->vdev = video_device_alloc();
if (t->vdev == NULL) {
+ kfree(t);
kfree(client);
return -ENOMEM;
}
@@ -617,9 +618,8 @@ static int saa5249_probe(struct i2c_client *client,
/* Register it */
err = video_register_device(t->vdev, VFL_TYPE_VTX, -1);
if (err < 0) {
- kfree(t);
video_device_release(t->vdev);
- t->vdev = NULL;
+ kfree(t);
return err;
}
return 0;
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index fdb19449d269..40e620284f56 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -1669,6 +1669,39 @@ struct saa7134_board saa7134_boards[] = {
.amux = LINE1,
},
},
+ [SAA7134_BOARD_AVERMEDIA_CARDBUS_501] = {
+ /* Oldrich Jedlicka <oldium.pro@seznam.cz> */
+ .name = "AVerMedia Cardbus TV/Radio (E501R)",
+ .audio_clock = 0x187de7,
+ .tuner_type = TUNER_ALPS_TSBE5_PAL,
+ .radio_type = TUNER_TEA5767,
+ .tuner_addr = 0x61,
+ .radio_addr = 0x60,
+ .tda9887_conf = TDA9887_PRESENT,
+ .gpiomask = 0x08000000,
+ .inputs = { {
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ .gpio = 0x08000000,
+ }, {
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = LINE1,
+ .gpio = 0x08000000,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ .gpio = 0x08000000,
+ } },
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ .gpio = 0x00000000,
+ },
+ },
[SAA7134_BOARD_CINERGY400_CARDBUS] = {
.name = "Terratec Cinergy 400 mobile",
.audio_clock = 0x187de7,
@@ -4006,7 +4039,7 @@ struct saa7134_board saa7134_boards[] = {
[SAA7134_BOARD_BEHOLD_505FM] = {
/* Beholder Intl. Ltd. 2008 */
/*Dmitry Belimov <d.belimov@gmail.com> */
- .name = "Beholder BeholdTV 505 FM/RDS",
+ .name = "Beholder BeholdTV 505 FM",
.audio_clock = 0x00200000,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
.radio_type = UNSET,
@@ -4019,6 +4052,40 @@ struct saa7134_board saa7134_boards[] = {
.vmux = 3,
.amux = LINE2,
.tv = 1,
+ }, {
+ .name = name_comp1,
+ .vmux = 1,
+ .amux = LINE1,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ } },
+ .mute = {
+ .name = name_mute,
+ .amux = LINE1,
+ },
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ },
+ },
+ [SAA7134_BOARD_BEHOLD_505RDS] = {
+ /* Beholder Intl. Ltd. 2008 */
+ /*Dmitry Belimov <d.belimov@gmail.com> */
+ .name = "Beholder BeholdTV 505 RDS",
+ .audio_clock = 0x00200000,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .gpiomask = 0x00008000,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+ .amux = LINE2,
+ .tv = 1,
},{
.name = name_comp1,
.vmux = 1,
@@ -4040,7 +4107,7 @@ struct saa7134_board saa7134_boards[] = {
[SAA7134_BOARD_BEHOLD_507_9FM] = {
/* Beholder Intl. Ltd. 2008 */
/*Dmitry Belimov <d.belimov@gmail.com> */
- .name = "Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM",
+ .name = "Beholder BeholdTV 507 FM / BeholdTV 509 FM",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
.radio_type = UNSET,
@@ -4067,6 +4134,66 @@ struct saa7134_board saa7134_boards[] = {
.amux = LINE2,
},
},
+ [SAA7134_BOARD_BEHOLD_507RDS_MK5] = {
+ /* Beholder Intl. Ltd. 2008 */
+ /*Dmitry Belimov <d.belimov@gmail.com> */
+ .name = "Beholder BeholdTV 507 RDS",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .gpiomask = 0x00008000,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+ .amux = TV,
+ .tv = 1,
+ }, {
+ .name = name_comp1,
+ .vmux = 1,
+ .amux = LINE1,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ } },
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ },
+ },
+ [SAA7134_BOARD_BEHOLD_507RDS_MK3] = {
+ /* Beholder Intl. Ltd. 2008 */
+ /*Dmitry Belimov <d.belimov@gmail.com> */
+ .name = "Beholder BeholdTV 507 RDS",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .gpiomask = 0x00008000,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+ .amux = TV,
+ .tv = 1,
+ }, {
+ .name = name_comp1,
+ .vmux = 1,
+ .amux = LINE1,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ } },
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ },
+ },
[SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = {
/* Beholder Intl. Ltd. 2008 */
/*Dmitry Belimov <d.belimov@gmail.com> */
@@ -4101,9 +4228,121 @@ struct saa7134_board saa7134_boards[] = {
.gpio = 0x000A8000,
},
},
- [SAA7134_BOARD_BEHOLD_607_9FM] = {
+ [SAA7134_BOARD_BEHOLD_607FM_MK3] = {
+ /* Andrey Melnikoff <temnota@kmv.ru> */
+ .name = "Beholder BeholdTV 607 FM",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+ .amux = TV,
+ .tv = 1,
+ }, {
+ .name = name_comp1,
+ .vmux = 1,
+ .amux = LINE1,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ } },
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ },
+ },
+ [SAA7134_BOARD_BEHOLD_609FM_MK3] = {
+ /* Andrey Melnikoff <temnota@kmv.ru> */
+ .name = "Beholder BeholdTV 609 FM",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+ .amux = TV,
+ .tv = 1,
+ }, {
+ .name = name_comp1,
+ .vmux = 1,
+ .amux = LINE1,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ } },
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ },
+ },
+ [SAA7134_BOARD_BEHOLD_607FM_MK5] = {
+ /* Andrey Melnikoff <temnota@kmv.ru> */
+ .name = "Beholder BeholdTV 607 FM",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+ .amux = TV,
+ .tv = 1,
+ }, {
+ .name = name_comp1,
+ .vmux = 1,
+ .amux = LINE1,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ } },
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ },
+ },
+ [SAA7134_BOARD_BEHOLD_609FM_MK5] = {
+ /* Andrey Melnikoff <temnota@kmv.ru> */
+ .name = "Beholder BeholdTV 609 FM",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+ .amux = TV,
+ .tv = 1,
+ }, {
+ .name = name_comp1,
+ .vmux = 1,
+ .amux = LINE1,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ } },
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ },
+ },
+ [SAA7134_BOARD_BEHOLD_607RDS_MK3] = {
/* Andrey Melnikoff <temnota@kmv.ru> */
- .name = "Beholder BeholdTV 607 / BeholdTV 609",
+ .name = "Beholder BeholdTV 607 RDS",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
.radio_type = UNSET,
@@ -4115,6 +4354,90 @@ struct saa7134_board saa7134_boards[] = {
.vmux = 3,
.amux = TV,
.tv = 1,
+ }, {
+ .name = name_comp1,
+ .vmux = 1,
+ .amux = LINE1,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ } },
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ },
+ },
+ [SAA7134_BOARD_BEHOLD_609RDS_MK3] = {
+ /* Andrey Melnikoff <temnota@kmv.ru> */
+ .name = "Beholder BeholdTV 609 RDS",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+ .amux = TV,
+ .tv = 1,
+ }, {
+ .name = name_comp1,
+ .vmux = 1,
+ .amux = LINE1,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ } },
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ },
+ },
+ [SAA7134_BOARD_BEHOLD_607RDS_MK5] = {
+ /* Andrey Melnikoff <temnota@kmv.ru> */
+ .name = "Beholder BeholdTV 607 RDS",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+ .amux = TV,
+ .tv = 1,
+ }, {
+ .name = name_comp1,
+ .vmux = 1,
+ .amux = LINE1,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ } },
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ },
+ },
+ [SAA7134_BOARD_BEHOLD_609RDS_MK5] = {
+ /* Andrey Melnikoff <temnota@kmv.ru> */
+ .name = "Beholder BeholdTV 609 RDS",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+ .amux = TV,
+ .tv = 1,
},{
.name = name_comp1,
.vmux = 1,
@@ -4209,8 +4532,7 @@ struct saa7134_board saa7134_boards[] = {
/* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
.name = "Beholder BeholdTV M6 Extra",
.audio_clock = 0x00187de7,
- /* FIXME: Must be PHILIPS_FM1216ME_MK5*/
- .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -4753,6 +5075,44 @@ struct saa7134_board saa7134_boards[] = {
.gpio = 0x01,
},
},
+ [SAA7134_BOARD_AVERMEDIA_STUDIO_507UA] = {
+ /* Andy Shevchenko <andy@smile.org.ua> */
+ .name = "Avermedia AVerTV Studio 507UA",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* Should be MK5 */
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .gpiomask = 0x03,
+ .inputs = { {
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ .gpio = 0x00,
+ }, {
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = LINE1,
+ .gpio = 0x00,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ .gpio = 0x00,
+ } },
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ .gpio = 0x01,
+ },
+ .mute = {
+ .name = name_mute,
+ .amux = LINE1,
+ .gpio = 0x00,
+ },
+ },
};
const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -5027,6 +5387,13 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subdevice = 0xd6ee,
.driver_data = SAA7134_BOARD_AVERMEDIA_CARDBUS,
},{
+ /* AVerMedia CardBus */
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
+ .subvendor = 0x1461, /* Avermedia Technologies Inc */
+ .subdevice = 0xb7e9,
+ .driver_data = SAA7134_BOARD_AVERMEDIA_CARDBUS_501,
+ }, {
/* TransGear 3000TV */
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7130,
@@ -5441,6 +5808,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_507,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
+ .subvendor = 0x1461, /* Avermedia Technologies Inc */
+ .subdevice = 0xa11b,
+ .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_507UA,
+ }, {
+ .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x1043,
.subdevice = 0x4876,
@@ -5647,14 +6020,8 @@ struct pci_device_id saa7134_pci_tbl[] = {
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7130,
.subvendor = 0x0000,
- .subdevice = 0x5051,
- .driver_data = SAA7134_BOARD_BEHOLD_505FM,
- },{
- .vendor = PCI_VENDOR_ID_PHILIPS,
- .device = PCI_DEVICE_ID_PHILIPS_SAA7130,
- .subvendor = 0x0000,
.subdevice = 0x505B,
- .driver_data = SAA7134_BOARD_BEHOLD_505FM,
+ .driver_data = SAA7134_BOARD_BEHOLD_505RDS,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7130,
@@ -5666,13 +6033,13 @@ struct pci_device_id saa7134_pci_tbl[] = {
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x0000,
.subdevice = 0x5071,
- .driver_data = SAA7134_BOARD_BEHOLD_507_9FM,
+ .driver_data = SAA7134_BOARD_BEHOLD_507RDS_MK3,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x0000,
.subdevice = 0x507B,
- .driver_data = SAA7134_BOARD_BEHOLD_507_9FM,
+ .driver_data = SAA7134_BOARD_BEHOLD_507RDS_MK5,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -5696,49 +6063,49 @@ struct pci_device_id saa7134_pci_tbl[] = {
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
.subvendor = 0x5ace,
.subdevice = 0x6070,
- .driver_data = SAA7134_BOARD_BEHOLD_607_9FM,
+ .driver_data = SAA7134_BOARD_BEHOLD_607FM_MK3,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
.subvendor = 0x5ace,
.subdevice = 0x6071,
- .driver_data = SAA7134_BOARD_BEHOLD_607_9FM,
+ .driver_data = SAA7134_BOARD_BEHOLD_607FM_MK5,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
.subvendor = 0x5ace,
.subdevice = 0x6072,
- .driver_data = SAA7134_BOARD_BEHOLD_607_9FM,
+ .driver_data = SAA7134_BOARD_BEHOLD_607RDS_MK3,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
.subvendor = 0x5ace,
.subdevice = 0x6073,
- .driver_data = SAA7134_BOARD_BEHOLD_607_9FM,
+ .driver_data = SAA7134_BOARD_BEHOLD_607RDS_MK5,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x5ace,
.subdevice = 0x6090,
- .driver_data = SAA7134_BOARD_BEHOLD_607_9FM,
+ .driver_data = SAA7134_BOARD_BEHOLD_609FM_MK3,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x5ace,
.subdevice = 0x6091,
- .driver_data = SAA7134_BOARD_BEHOLD_607_9FM,
+ .driver_data = SAA7134_BOARD_BEHOLD_609FM_MK5,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x5ace,
.subdevice = 0x6092,
- .driver_data = SAA7134_BOARD_BEHOLD_607_9FM,
+ .driver_data = SAA7134_BOARD_BEHOLD_609RDS_MK3,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x5ace,
.subdevice = 0x6093,
- .driver_data = SAA7134_BOARD_BEHOLD_607_9FM,
+ .driver_data = SAA7134_BOARD_BEHOLD_609RDS_MK5,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
@@ -6142,7 +6509,10 @@ int saa7134_board_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_BEHOLD_407FM:
case SAA7134_BOARD_BEHOLD_409:
case SAA7134_BOARD_BEHOLD_505FM:
+ case SAA7134_BOARD_BEHOLD_505RDS:
case SAA7134_BOARD_BEHOLD_507_9FM:
+ case SAA7134_BOARD_BEHOLD_507RDS_MK3:
+ case SAA7134_BOARD_BEHOLD_507RDS_MK5:
case SAA7134_BOARD_GENIUS_TVGO_A11MCE:
case SAA7134_BOARD_REAL_ANGEL_220:
case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG:
@@ -6196,6 +6566,16 @@ int saa7134_board_init1(struct saa7134_dev *dev)
saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff);
msleep(10);
break;
+ case SAA7134_BOARD_AVERMEDIA_CARDBUS_501:
+ /* power-down tuner chip */
+ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x08400000, 0x08400000);
+ saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08400000, 0);
+ msleep(10);
+ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x08400000, 0x08400000);
+ saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08400000, 0x08400000);
+ msleep(10);
+ dev->has_remote = SAA7134_REMOTE_I2C;
+ break;
case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
saa7134_set_gpio(dev, 23, 0);
msleep(10);
@@ -6253,7 +6633,14 @@ int saa7134_board_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_UPMOST_PURPLE_TV:
case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS:
case SAA7134_BOARD_HAUPPAUGE_HVR1110:
- case SAA7134_BOARD_BEHOLD_607_9FM:
+ case SAA7134_BOARD_BEHOLD_607FM_MK3:
+ case SAA7134_BOARD_BEHOLD_607FM_MK5:
+ case SAA7134_BOARD_BEHOLD_609FM_MK3:
+ case SAA7134_BOARD_BEHOLD_609FM_MK5:
+ case SAA7134_BOARD_BEHOLD_607RDS_MK3:
+ case SAA7134_BOARD_BEHOLD_607RDS_MK5:
+ case SAA7134_BOARD_BEHOLD_609RDS_MK3:
+ case SAA7134_BOARD_BEHOLD_609RDS_MK5:
case SAA7134_BOARD_BEHOLD_M6:
case SAA7134_BOARD_BEHOLD_M63:
case SAA7134_BOARD_BEHOLD_M6_EXTRA:
@@ -6635,6 +7022,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
switch (dev->board) {
case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
+ case SAA7134_BOARD_AVERMEDIA_CARDBUS_501:
{
struct v4l2_priv_tun_config tea5767_cfg;
struct tea5767_ctrl ctl;
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
index f3e285aa2fb4..a8a355e28799 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -321,33 +321,6 @@ static u32 functionality(struct i2c_adapter *adap)
return I2C_FUNC_SMBUS_EMUL;
}
-static int attach_inform(struct i2c_client *client)
-{
- struct saa7134_dev *dev = client->adapter->algo_data;
-
- d1printk( "%s i2c attach [addr=0x%x,client=%s]\n",
- client->driver->driver.name, client->addr, client->name);
-
- /* Am I an i2c remote control? */
-
- switch (client->addr) {
- case 0x7a:
- case 0x47:
- case 0x71:
- case 0x2d:
- case 0x30:
- {
- struct IR_i2c *ir = i2c_get_clientdata(client);
- d1printk("%s i2c IR detected (%s).\n",
- client->driver->driver.name, ir->phys);
- saa7134_set_i2c_ir(dev,ir);
- break;
- }
- }
-
- return 0;
-}
-
static struct i2c_algorithm saa7134_algo = {
.master_xfer = saa7134_i2c_xfer,
.functionality = functionality,
@@ -358,7 +331,6 @@ static struct i2c_adapter saa7134_adap_template = {
.name = "saa7134",
.id = I2C_HW_SAA7134,
.algo = &saa7134_algo,
- .client_register = attach_inform,
};
static struct i2c_client saa7134_client_template = {
@@ -433,6 +405,9 @@ int saa7134_i2c_register(struct saa7134_dev *dev)
saa7134_i2c_eeprom(dev,dev->eedata,sizeof(dev->eedata));
if (i2c_scan)
do_i2c_scan(dev->name,&dev->i2c_client);
+
+ /* Instantiate the IR receiver device, if present */
+ saa7134_probe_i2c_ir(dev);
return 0;
}
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index 8a106d36e723..02705c9879fc 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -60,7 +60,7 @@ MODULE_PARM_DESC(disable_other_ir, "disable full codes of "
#define dprintk(fmt, arg...) if (ir_debug) \
printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg)
#define i2cdprintk(fmt, arg...) if (ir_debug) \
- printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg)
+ printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg)
/* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */
static int saa7134_rc5_irq(struct saa7134_dev *dev);
@@ -134,10 +134,10 @@ static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key,
int gpio;
/* <dev> is needed to access GPIO. Used by the saa_readl macro. */
- struct saa7134_dev *dev = ir->c.adapter->algo_data;
+ struct saa7134_dev *dev = ir->c->adapter->algo_data;
if (dev == NULL) {
dprintk("get_key_msi_tvanywhere_plus: "
- "gir->c.adapter->algo_data is NULL!\n");
+ "gir->c->adapter->algo_data is NULL!\n");
return -EIO;
}
@@ -156,7 +156,7 @@ static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key,
/* GPIO says there is a button press. Get it. */
- if (1 != i2c_master_recv(&ir->c, &b, 1)) {
+ if (1 != i2c_master_recv(ir->c, &b, 1)) {
i2cdprintk("read error\n");
return -EIO;
}
@@ -179,7 +179,7 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
unsigned char b;
/* poll IR chip */
- if (1 != i2c_master_recv(&ir->c,&b,1)) {
+ if (1 != i2c_master_recv(ir->c, &b, 1)) {
i2cdprintk("read error\n");
return -EIO;
}
@@ -202,7 +202,7 @@ static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
unsigned char buf[5], cod4, code3, code4;
/* poll IR chip */
- if (5 != i2c_master_recv(&ir->c,buf,5))
+ if (5 != i2c_master_recv(ir->c, buf, 5))
return -EIO;
cod4 = buf[4];
@@ -224,7 +224,7 @@ static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
unsigned char data[12];
u32 gpio;
- struct saa7134_dev *dev = ir->c.adapter->algo_data;
+ struct saa7134_dev *dev = ir->c->adapter->algo_data;
/* rising SAA7134_GPIO_GPRESCAN reads the status */
saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
@@ -235,9 +235,9 @@ static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
if (0x400000 & ~gpio)
return 0; /* No button press */
- ir->c.addr = 0x5a >> 1;
+ ir->c->addr = 0x5a >> 1;
- if (12 != i2c_master_recv(&ir->c, data, 12)) {
+ if (12 != i2c_master_recv(ir->c, data, 12)) {
i2cdprintk("read error\n");
return -EIO;
}
@@ -267,7 +267,7 @@ static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
unsigned int start = 0,parity = 0,code = 0;
/* poll IR chip */
- if (4 != i2c_master_recv(&ir->c, b, 4)) {
+ if (4 != i2c_master_recv(ir->c, b, 4)) {
i2cdprintk("read error\n");
return -EIO;
}
@@ -447,6 +447,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
+ case SAA7134_BOARD_AVERMEDIA_STUDIO_507UA:
case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
case SAA7134_BOARD_AVERMEDIA_M102:
case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS:
@@ -506,7 +507,10 @@ int saa7134_input_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_BEHOLD_407FM:
case SAA7134_BOARD_BEHOLD_409:
case SAA7134_BOARD_BEHOLD_505FM:
+ case SAA7134_BOARD_BEHOLD_505RDS:
case SAA7134_BOARD_BEHOLD_507_9FM:
+ case SAA7134_BOARD_BEHOLD_507RDS_MK3:
+ case SAA7134_BOARD_BEHOLD_507RDS_MK5:
ir_codes = ir_codes_manli;
mask_keycode = 0x003f00;
mask_keyup = 0x004000;
@@ -678,55 +682,100 @@ void saa7134_input_fini(struct saa7134_dev *dev)
dev->remote = NULL;
}
-void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
+void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
{
+ struct i2c_board_info info;
+ struct IR_i2c_init_data init_data;
+ const unsigned short addr_list[] = {
+ 0x7a, 0x47, 0x71, 0x2d,
+ I2C_CLIENT_END
+ };
+
+ struct i2c_msg msg_msi = {
+ .addr = 0x50,
+ .flags = I2C_M_RD,
+ .len = 0,
+ .buf = NULL,
+ };
+
+ int rc;
+
if (disable_ir) {
- dprintk("Found supported i2c remote, but IR has been disabled\n");
- ir->get_key=NULL;
+ dprintk("IR has been disabled, not probing for i2c remote\n");
return;
}
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ memset(&init_data, 0, sizeof(struct IR_i2c_init_data));
+ strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+
switch (dev->board) {
case SAA7134_BOARD_PINNACLE_PCTV_110i:
case SAA7134_BOARD_PINNACLE_PCTV_310i:
- snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV");
+ init_data.name = "Pinnacle PCTV";
if (pinnacle_remote == 0) {
- ir->get_key = get_key_pinnacle_color;
- ir->ir_codes = ir_codes_pinnacle_color;
+ init_data.get_key = get_key_pinnacle_color;
+ init_data.ir_codes = ir_codes_pinnacle_color;
} else {
- ir->get_key = get_key_pinnacle_grey;
- ir->ir_codes = ir_codes_pinnacle_grey;
+ init_data.get_key = get_key_pinnacle_grey;
+ init_data.ir_codes = ir_codes_pinnacle_grey;
}
break;
case SAA7134_BOARD_UPMOST_PURPLE_TV:
- snprintf(ir->c.name, sizeof(ir->c.name), "Purple TV");
- ir->get_key = get_key_purpletv;
- ir->ir_codes = ir_codes_purpletv;
+ init_data.name = "Purple TV";
+ init_data.get_key = get_key_purpletv;
+ init_data.ir_codes = ir_codes_purpletv;
break;
case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS:
- snprintf(ir->c.name, sizeof(ir->c.name), "MSI TV@nywhere Plus");
- ir->get_key = get_key_msi_tvanywhere_plus;
- ir->ir_codes = ir_codes_msi_tvanywhere_plus;
+ init_data.name = "MSI TV@nywhere Plus";
+ init_data.get_key = get_key_msi_tvanywhere_plus;
+ init_data.ir_codes = ir_codes_msi_tvanywhere_plus;
+ info.addr = 0x30;
+ /* MSI TV@nywhere Plus controller doesn't seem to
+ respond to probes unless we read something from
+ an existing device. Weird...
+ REVISIT: might no longer be needed */
+ rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1);
+ dprintk(KERN_DEBUG "probe 0x%02x @ %s: %s\n",
+ msg_msi.addr, dev->i2c_adap.name,
+ (1 == rc) ? "yes" : "no");
break;
case SAA7134_BOARD_HAUPPAUGE_HVR1110:
- snprintf(ir->c.name, sizeof(ir->c.name), "HVR 1110");
- ir->get_key = get_key_hvr1110;
- ir->ir_codes = ir_codes_hauppauge_new;
- break;
- case SAA7134_BOARD_BEHOLD_607_9FM:
+ init_data.name = "HVR 1110";
+ init_data.get_key = get_key_hvr1110;
+ init_data.ir_codes = ir_codes_hauppauge_new;
+ break;
+ case SAA7134_BOARD_BEHOLD_607FM_MK3:
+ case SAA7134_BOARD_BEHOLD_607FM_MK5:
+ case SAA7134_BOARD_BEHOLD_609FM_MK3:
+ case SAA7134_BOARD_BEHOLD_609FM_MK5:
+ case SAA7134_BOARD_BEHOLD_607RDS_MK3:
+ case SAA7134_BOARD_BEHOLD_607RDS_MK5:
+ case SAA7134_BOARD_BEHOLD_609RDS_MK3:
+ case SAA7134_BOARD_BEHOLD_609RDS_MK5:
case SAA7134_BOARD_BEHOLD_M6:
case SAA7134_BOARD_BEHOLD_M63:
case SAA7134_BOARD_BEHOLD_M6_EXTRA:
case SAA7134_BOARD_BEHOLD_H6:
- snprintf(ir->c.name, sizeof(ir->c.name), "BeholdTV");
- ir->get_key = get_key_beholdm6xx;
- ir->ir_codes = ir_codes_behold;
+ init_data.name = "BeholdTV";
+ init_data.get_key = get_key_beholdm6xx;
+ init_data.ir_codes = ir_codes_behold;
break;
- default:
- dprintk("Shouldn't get here: Unknown board %x for I2C IR?\n",dev->board);
+ case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+ info.addr = 0x40;
break;
}
+ if (init_data.name)
+ info.platform_data = &init_data;
+ /* No need to probe if address is known */
+ if (info.addr) {
+ i2c_new_device(&dev->i2c_adap, &info);
+ return;
+ }
+
+ /* Address not known, fallback to probing */
+ i2c_new_probed_device(&dev->i2c_adap, &info, addr_list);
}
static int saa7134_rc5_irq(struct saa7134_dev *dev)
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 0cbaf90d4874..87b9cd996178 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -252,7 +252,7 @@ struct saa7134_format {
#define SAA7134_BOARD_BEHOLD_505FM 126
#define SAA7134_BOARD_BEHOLD_507_9FM 127
#define SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM 128
-#define SAA7134_BOARD_BEHOLD_607_9FM 129
+#define SAA7134_BOARD_BEHOLD_607FM_MK3 129
#define SAA7134_BOARD_BEHOLD_M6 130
#define SAA7134_BOARD_TWINHAN_DTV_DVB_3056 131
#define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132
@@ -280,6 +280,18 @@ struct saa7134_format {
#define SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS 154
#define SAA7134_BOARD_HAUPPAUGE_HVR1120 155
#define SAA7134_BOARD_HAUPPAUGE_HVR1110R3 156
+#define SAA7134_BOARD_AVERMEDIA_STUDIO_507UA 157
+#define SAA7134_BOARD_AVERMEDIA_CARDBUS_501 158
+#define SAA7134_BOARD_BEHOLD_505RDS 159
+#define SAA7134_BOARD_BEHOLD_507RDS_MK3 160
+#define SAA7134_BOARD_BEHOLD_507RDS_MK5 161
+#define SAA7134_BOARD_BEHOLD_607FM_MK5 162
+#define SAA7134_BOARD_BEHOLD_609FM_MK3 163
+#define SAA7134_BOARD_BEHOLD_609FM_MK5 164
+#define SAA7134_BOARD_BEHOLD_607RDS_MK3 165
+#define SAA7134_BOARD_BEHOLD_607RDS_MK5 166
+#define SAA7134_BOARD_BEHOLD_609RDS_MK3 167
+#define SAA7134_BOARD_BEHOLD_609RDS_MK5 168
#define SAA7134_MAXBOARDS 32
#define SAA7134_INPUT_MAX 8
@@ -786,7 +798,7 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status);
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_probe_i2c_ir(struct saa7134_dev *dev);
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/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index b5e37a530c62..d369e8409ab8 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -81,7 +81,6 @@ struct sh_mobile_ceu_buffer {
};
struct sh_mobile_ceu_dev {
- struct device *dev;
struct soc_camera_host ici;
struct soc_camera_device *icd;
@@ -617,7 +616,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx,
xlate->cam_fmt = icd->formats + idx;
xlate->buswidth = icd->formats[idx].depth;
xlate++;
- dev_dbg(&ici->dev, "Providing format %s using %s\n",
+ dev_dbg(ici->dev, "Providing format %s using %s\n",
sh_mobile_ceu_formats[k].name,
icd->formats[idx].name);
}
@@ -630,7 +629,7 @@ add_single_format:
xlate->cam_fmt = icd->formats + idx;
xlate->buswidth = icd->formats[idx].depth;
xlate++;
- dev_dbg(&ici->dev,
+ dev_dbg(ici->dev,
"Providing format %s in pass-through mode\n",
icd->formats[idx].name);
}
@@ -657,7 +656,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
if (!xlate) {
- dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
+ dev_warn(ici->dev, "Format %x not found\n", pixfmt);
return -EINVAL;
}
@@ -684,7 +683,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
if (!xlate) {
- dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
+ dev_warn(ici->dev, "Format %x not found\n", pixfmt);
return -EINVAL;
}
@@ -782,7 +781,7 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q,
videobuf_queue_dma_contig_init(q,
&sh_mobile_ceu_videobuf_ops,
- &ici->dev, &pcdev->lock,
+ ici->dev, &pcdev->lock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
pcdev->is_interlaced ?
V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE,
@@ -829,7 +828,6 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
goto exit;
}
- platform_set_drvdata(pdev, pcdev);
INIT_LIST_HEAD(&pcdev->capture);
spin_lock_init(&pcdev->lock);
@@ -840,7 +838,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
goto exit_kfree;
}
- base = ioremap_nocache(res->start, res->end - res->start + 1);
+ base = ioremap_nocache(res->start, resource_size(res));
if (!base) {
err = -ENXIO;
dev_err(&pdev->dev, "Unable to ioremap CEU registers.\n");
@@ -850,13 +848,12 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
pcdev->irq = irq;
pcdev->base = base;
pcdev->video_limit = 0; /* only enabled if second resource exists */
- pcdev->dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (res) {
err = dma_declare_coherent_memory(&pdev->dev, res->start,
res->start,
- (res->end - res->start) + 1,
+ resource_size(res),
DMA_MEMORY_MAP |
DMA_MEMORY_EXCLUSIVE);
if (!err) {
@@ -865,7 +862,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
goto exit_iounmap;
}
- pcdev->video_limit = (res->end - res->start) + 1;
+ pcdev->video_limit = resource_size(res);
}
/* request irq */
@@ -885,7 +882,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
}
pcdev->ici.priv = pcdev;
- pcdev->ici.dev.parent = &pdev->dev;
+ pcdev->ici.dev = &pdev->dev;
pcdev->ici.nr = pdev->id;
pcdev->ici.drv_name = dev_name(&pdev->dev);
pcdev->ici.ops = &sh_mobile_ceu_host_ops;
@@ -913,9 +910,11 @@ exit:
static int sh_mobile_ceu_remove(struct platform_device *pdev)
{
- struct sh_mobile_ceu_dev *pcdev = platform_get_drvdata(pdev);
+ struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
+ struct sh_mobile_ceu_dev *pcdev = container_of(soc_host,
+ struct sh_mobile_ceu_dev, ici);
- soc_camera_host_unregister(&pcdev->ici);
+ soc_camera_host_unregister(soc_host);
clk_put(pcdev->clk);
free_irq(pcdev->irq, pcdev);
if (platform_get_resource(pdev, IORESOURCE_MEM, 1))
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index 0e890cc23377..2014e9e32b35 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -16,19 +16,21 @@
* published by the Free Software Foundation.
*/
-#include <linux/module.h>
-#include <linux/init.h>
#include <linux/device.h>
-#include <linux/list.h>
#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/platform_device.h>
#include <linux/vmalloc.h>
+#include <media/soc_camera.h>
#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
#include <media/v4l2-dev.h>
+#include <media/v4l2-ioctl.h>
#include <media/videobuf-core.h>
-#include <media/soc_camera.h>
/* Default to VGA resolution */
#define DEFAULT_WIDTH 640
@@ -279,7 +281,7 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf,
return ret;
} else if (!icd->current_fmt ||
icd->current_fmt->fourcc != pix->pixelformat) {
- dev_err(&ici->dev,
+ dev_err(ici->dev,
"Host driver hasn't set up current format correctly!\n");
return -EINVAL;
}
@@ -794,7 +796,7 @@ static void scan_add_host(struct soc_camera_host *ici)
list_for_each_entry(icd, &devices, list) {
if (icd->iface == ici->nr) {
- icd->dev.parent = &ici->dev;
+ icd->dev.parent = ici->dev;
device_register_link(icd);
}
}
@@ -818,7 +820,7 @@ static int scan_add_device(struct soc_camera_device *icd)
list_for_each_entry(ici, &hosts, list) {
if (icd->iface == ici->nr) {
ret = 1;
- icd->dev.parent = &ici->dev;
+ icd->dev.parent = ici->dev;
break;
}
}
@@ -952,7 +954,6 @@ static void dummy_release(struct device *dev)
int soc_camera_host_register(struct soc_camera_host *ici)
{
- int ret;
struct soc_camera_host *ix;
if (!ici || !ici->ops ||
@@ -965,12 +966,10 @@ int soc_camera_host_register(struct soc_camera_host *ici)
!ici->ops->reqbufs ||
!ici->ops->add ||
!ici->ops->remove ||
- !ici->ops->poll)
+ !ici->ops->poll ||
+ !ici->dev)
return -EINVAL;
- /* Number might be equal to the platform device ID */
- dev_set_name(&ici->dev, "camera_host%d", ici->nr);
-
mutex_lock(&list_lock);
list_for_each_entry(ix, &hosts, list) {
if (ix->nr == ici->nr) {
@@ -979,26 +978,14 @@ int soc_camera_host_register(struct soc_camera_host *ici)
}
}
+ dev_set_drvdata(ici->dev, ici);
+
list_add_tail(&ici->list, &hosts);
mutex_unlock(&list_lock);
- ici->dev.release = dummy_release;
-
- ret = device_register(&ici->dev);
-
- if (ret)
- goto edevr;
-
scan_add_host(ici);
return 0;
-
-edevr:
- mutex_lock(&list_lock);
- list_del(&ici->list);
- mutex_unlock(&list_lock);
-
- return ret;
}
EXPORT_SYMBOL(soc_camera_host_register);
@@ -1012,7 +999,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
list_del(&ici->list);
list_for_each_entry(icd, &devices, list) {
- if (icd->dev.parent == &ici->dev) {
+ if (icd->dev.parent == ici->dev) {
device_unregister(&icd->dev);
/* Not before device_unregister(), .remove
* needs parent to call ici->ops->remove() */
@@ -1023,7 +1010,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
mutex_unlock(&list_lock);
- device_unregister(&ici->dev);
+ dev_set_drvdata(ici->dev, NULL);
}
EXPORT_SYMBOL(soc_camera_host_unregister);
@@ -1130,7 +1117,7 @@ int soc_camera_video_start(struct soc_camera_device *icd)
vdev = video_device_alloc();
if (!vdev)
goto evidallocd;
- dev_dbg(&ici->dev, "Allocated video_device %p\n", vdev);
+ dev_dbg(ici->dev, "Allocated video_device %p\n", vdev);
strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));
@@ -1174,6 +1161,57 @@ void soc_camera_video_stop(struct soc_camera_device *icd)
}
EXPORT_SYMBOL(soc_camera_video_stop);
+static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev)
+{
+ struct soc_camera_link *icl = pdev->dev.platform_data;
+ struct i2c_adapter *adap;
+ struct i2c_client *client;
+
+ if (!icl)
+ return -EINVAL;
+
+ adap = i2c_get_adapter(icl->i2c_adapter_id);
+ if (!adap) {
+ dev_warn(&pdev->dev, "Cannot get adapter #%d. No driver?\n",
+ icl->i2c_adapter_id);
+ /* -ENODEV and -ENXIO do not produce an error on probe()... */
+ return -ENOENT;
+ }
+
+ icl->board_info->platform_data = icl;
+ client = i2c_new_device(adap, icl->board_info);
+ if (!client) {
+ i2c_put_adapter(adap);
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(pdev, client);
+
+ return 0;
+}
+
+static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev)
+{
+ struct i2c_client *client = platform_get_drvdata(pdev);
+
+ if (!client)
+ return -ENODEV;
+
+ i2c_unregister_device(client);
+ i2c_put_adapter(client->adapter);
+
+ return 0;
+}
+
+static struct platform_driver __refdata soc_camera_pdrv = {
+ .probe = soc_camera_pdrv_probe,
+ .remove = __exit_p(soc_camera_pdrv_remove),
+ .driver = {
+ .name = "soc-camera-pdrv",
+ .owner = THIS_MODULE,
+ },
+};
+
static int __init soc_camera_init(void)
{
int ret = bus_register(&soc_camera_bus_type);
@@ -1183,8 +1221,14 @@ static int __init soc_camera_init(void)
if (ret)
goto edrvr;
+ ret = platform_driver_register(&soc_camera_pdrv);
+ if (ret)
+ goto epdr;
+
return 0;
+epdr:
+ driver_unregister(&ic_drv);
edrvr:
bus_unregister(&soc_camera_bus_type);
return ret;
@@ -1192,6 +1236,7 @@ edrvr:
static void __exit soc_camera_exit(void)
{
+ platform_driver_unregister(&soc_camera_pdrv);
driver_unregister(&ic_drv);
bus_unregister(&soc_camera_bus_type);
}
@@ -1202,3 +1247,4 @@ module_exit(soc_camera_exit);
MODULE_DESCRIPTION("Image capture bus driver");
MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:soc-camera-pdrv");
diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c
index 005f8a468031..80f1cee23fa5 100644
--- a/drivers/media/video/tda7432.c
+++ b/drivers/media/video/tda7432.c
@@ -20,20 +20,6 @@
* loudness - set between 0 and 15 for varying degrees of loudness effect
*
* maxvol - set maximium volume to +20db (1), default is 0db(0)
- *
- *
- * Revision: 0.7 - maxvol module parm to set maximium volume 0db or +20db
- * store if muted so we can return it
- * change balance only if flaged to
- * Revision: 0.6 - added tone controls
- * Revision: 0.5 - Fixed odd balance problem
- * Revision: 0.4 - added muting
- * Revision: 0.3 - Fixed silly reversed volume controls. :)
- * Revision: 0.2 - Cleaned up #defines
- * fixed volume control
- * Added I2C_DRIVERID_TDA7432
- * added loudness insmod control
- * Revision: 0.1 - initial version
*/
#include <linux/module.h>
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index 78c377a399cb..1dac524fc8f1 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -309,32 +309,6 @@ static void set_freq(struct i2c_client *c, unsigned long freq)
}
}
-static void tuner_i2c_address_check(struct tuner *t)
-{
- if ((t->type == UNSET || t->type == TUNER_ABSENT) ||
- ((t->i2c->addr < 0x64) || (t->i2c->addr > 0x6f)))
- return;
-
- /* We already know that the XC5000 can only be located at
- * i2c address 0x61, 0x62, 0x63 or 0x64 */
- if ((t->type == TUNER_XC5000) &&
- ((t->i2c->addr <= 0x64)) && (t->i2c->addr >= 0x61))
- return;
-
- tuner_warn("====================== WARNING! ======================\n");
- tuner_warn("Support for tuners in i2c address range 0x64 thru 0x6f\n");
- tuner_warn("will soon be dropped. This message indicates that your\n");
- tuner_warn("hardware has a %s tuner at i2c address 0x%02x.\n",
- t->name, t->i2c->addr);
- tuner_warn("To ensure continued support for your device, please\n");
- tuner_warn("send a copy of this message, along with full dmesg\n");
- tuner_warn("output to v4l-dvb-maintainer@linuxtv.org\n");
- tuner_warn("Please use subject line: \"obsolete tuner i2c address.\"\n");
- tuner_warn("driver: %s, addr: 0x%02x, type: %d (%s)\n",
- t->i2c->adapter->name, t->i2c->addr, t->type, t->name);
- tuner_warn("====================== WARNING! ======================\n");
-}
-
static struct xc5000_config xc5000_cfg;
static void set_type(struct i2c_client *c, unsigned int type,
@@ -490,7 +464,6 @@ static void set_type(struct i2c_client *c, unsigned int type,
tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
c->adapter->name, c->driver->driver.name, c->addr << 1, type,
t->mode_mask);
- tuner_i2c_address_check(t);
return;
attach_failed:
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
index 399412d7f020..507dc85646b2 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -1726,14 +1726,17 @@ static int uvc_suspend(struct usb_interface *intf, pm_message_t message)
static int __uvc_resume(struct usb_interface *intf, int reset)
{
struct uvc_device *dev = usb_get_intfdata(intf);
- int ret;
uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n",
intf->cur_altsetting->desc.bInterfaceNumber);
if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) {
- if (reset && (ret = uvc_ctrl_resume_device(dev)) < 0)
- return ret;
+ if (reset) {
+ int ret = uvc_ctrl_resume_device(dev);
+
+ if (ret < 0)
+ return ret;
+ }
return uvc_status_resume(dev);
}
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index 2a80caa54fb4..ad7e64ff3add 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -46,6 +46,8 @@ static int uvc_v4l2_query_menu(struct uvc_video_device *video,
struct uvc_menu_info *menu_info;
struct uvc_control_mapping *mapping;
struct uvc_control *ctrl;
+ u32 index = query_menu->index;
+ u32 id = query_menu->id;
ctrl = uvc_find_control(video, query_menu->id, &mapping);
if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU)
@@ -54,6 +56,10 @@ static int uvc_v4l2_query_menu(struct uvc_video_device *video,
if (query_menu->index >= mapping->menu_count)
return -EINVAL;
+ memset(query_menu, 0, sizeof(*query_menu));
+ query_menu->id = id;
+ query_menu->index = index;
+
menu_info = &mapping->menu_info[query_menu->index];
strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name);
return 0;
@@ -648,7 +654,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_S_INPUT:
{
- u8 input = *(u32 *)arg + 1;
+ u32 input = *(u32 *)arg + 1;
if ((ret = uvc_acquire_privileges(handle)) < 0)
return ret;
@@ -660,7 +666,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
break;
}
- if (input > video->selector->selector.bNrInPins)
+ if (input == 0 || input > video->selector->selector.bNrInPins)
return -EINVAL;
return uvc_query_ctrl(video->dev, SET_CUR, video->selector->id,
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index a95e17329c5b..6ce974d7362f 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -742,7 +742,7 @@ static int uvc_alloc_urb_buffers(struct uvc_video_device *video,
/* Buffers are already allocated, bail out. */
if (video->urb_size)
- return 0;
+ return video->urb_size / psize;
/* Compute the number of packets. Bulk endpoints might transfer UVC
* payloads accross multiple URBs.
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index f576ef66b807..f96475626da7 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -746,6 +746,7 @@ void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client,
const struct v4l2_subdev_ops *ops)
{
v4l2_subdev_init(sd, ops);
+ sd->flags |= V4L2_SUBDEV_FL_IS_I2C;
/* the owner is the same as the i2c_client's driver owner */
sd->owner = client->driver->driver.owner;
/* i2c_client and v4l2_subdev point to one another */
@@ -897,8 +898,7 @@ const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type)
};
static const unsigned short tv_addrs[] = {
0x42, 0x43, 0x4a, 0x4b, /* tda8290 */
- 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
- 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x60, 0x61, 0x62, 0x63, 0x64,
I2C_CLIENT_END
};
diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c
index 94aa485ade52..e1520bc84f71 100644
--- a/drivers/media/video/v4l2-device.c
+++ b/drivers/media/video/v4l2-device.c
@@ -49,6 +49,22 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
}
EXPORT_SYMBOL_GPL(v4l2_device_register);
+int v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename,
+ atomic_t *instance)
+{
+ int num = atomic_inc_return(instance) - 1;
+ int len = strlen(basename);
+
+ if (basename[len - 1] >= '0' && basename[len - 1] <= '9')
+ snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
+ "%s-%d", basename, num);
+ else
+ snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
+ "%s%d", basename, num);
+ return num;
+}
+EXPORT_SYMBOL_GPL(v4l2_device_set_name);
+
void v4l2_device_disconnect(struct v4l2_device *v4l2_dev)
{
if (v4l2_dev->dev) {
@@ -67,8 +83,19 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev)
v4l2_device_disconnect(v4l2_dev);
/* Unregister subdevs */
- list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list)
+ list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) {
v4l2_device_unregister_subdev(sd);
+ if (sd->flags & V4L2_SUBDEV_FL_IS_I2C) {
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ /* We need to unregister the i2c client explicitly.
+ We cannot rely on i2c_del_adapter to always
+ unregister clients for us, since if the i2c bus
+ is a platform bus, then it is never deleted. */
+ if (client)
+ i2c_unregister_device(client);
+ }
+ }
}
EXPORT_SYMBOL_GPL(v4l2_device_unregister);
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index 88f10d6cbc92..be64a502ea27 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -42,6 +42,12 @@
printk(KERN_DEBUG "%s: " fmt, vfd->name, ## arg);\
} while (0)
+/* Zero out the end of the struct pointed to by p. Everthing after, but
+ * not including, the specified field is cleared. */
+#define CLEAR_AFTER_FIELD(p, field) \
+ memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \
+ 0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field))
+
struct std_descr {
v4l2_std_id std;
const char *descr;
@@ -544,39 +550,39 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type)
switch (type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- if (ops->vidioc_try_fmt_vid_cap)
+ if (ops->vidioc_g_fmt_vid_cap)
return 0;
break;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- if (ops->vidioc_try_fmt_vid_overlay)
+ if (ops->vidioc_g_fmt_vid_overlay)
return 0;
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- if (ops->vidioc_try_fmt_vid_out)
+ if (ops->vidioc_g_fmt_vid_out)
return 0;
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
- if (ops->vidioc_try_fmt_vid_out_overlay)
+ if (ops->vidioc_g_fmt_vid_out_overlay)
return 0;
break;
case V4L2_BUF_TYPE_VBI_CAPTURE:
- if (ops->vidioc_try_fmt_vbi_cap)
+ if (ops->vidioc_g_fmt_vbi_cap)
return 0;
break;
case V4L2_BUF_TYPE_VBI_OUTPUT:
- if (ops->vidioc_try_fmt_vbi_out)
+ if (ops->vidioc_g_fmt_vbi_out)
return 0;
break;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
- if (ops->vidioc_try_fmt_sliced_vbi_cap)
+ if (ops->vidioc_g_fmt_sliced_vbi_cap)
return 0;
break;
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
- if (ops->vidioc_try_fmt_sliced_vbi_out)
+ if (ops->vidioc_g_fmt_sliced_vbi_out)
return 0;
break;
case V4L2_BUF_TYPE_PRIVATE:
- if (ops->vidioc_try_fmt_type_private)
+ if (ops->vidioc_g_fmt_type_private)
return 0;
break;
}
@@ -782,44 +788,53 @@ static long __video_do_ioctl(struct file *file,
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ CLEAR_AFTER_FIELD(f, fmt.pix);
v4l_print_pix_fmt(vfd, &f->fmt.pix);
if (ops->vidioc_s_fmt_vid_cap)
ret = ops->vidioc_s_fmt_vid_cap(file, fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ CLEAR_AFTER_FIELD(f, fmt.win);
if (ops->vidioc_s_fmt_vid_overlay)
ret = ops->vidioc_s_fmt_vid_overlay(file,
fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ CLEAR_AFTER_FIELD(f, fmt.pix);
v4l_print_pix_fmt(vfd, &f->fmt.pix);
if (ops->vidioc_s_fmt_vid_out)
ret = ops->vidioc_s_fmt_vid_out(file, fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ CLEAR_AFTER_FIELD(f, fmt.win);
if (ops->vidioc_s_fmt_vid_out_overlay)
ret = ops->vidioc_s_fmt_vid_out_overlay(file,
fh, f);
break;
case V4L2_BUF_TYPE_VBI_CAPTURE:
+ CLEAR_AFTER_FIELD(f, fmt.vbi);
if (ops->vidioc_s_fmt_vbi_cap)
ret = ops->vidioc_s_fmt_vbi_cap(file, fh, f);
break;
case V4L2_BUF_TYPE_VBI_OUTPUT:
+ CLEAR_AFTER_FIELD(f, fmt.vbi);
if (ops->vidioc_s_fmt_vbi_out)
ret = ops->vidioc_s_fmt_vbi_out(file, fh, f);
break;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ CLEAR_AFTER_FIELD(f, fmt.sliced);
if (ops->vidioc_s_fmt_sliced_vbi_cap)
ret = ops->vidioc_s_fmt_sliced_vbi_cap(file,
fh, f);
break;
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ CLEAR_AFTER_FIELD(f, fmt.sliced);
if (ops->vidioc_s_fmt_sliced_vbi_out)
ret = ops->vidioc_s_fmt_sliced_vbi_out(file,
fh, f);
break;
case V4L2_BUF_TYPE_PRIVATE:
+ /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */
if (ops->vidioc_s_fmt_type_private)
ret = ops->vidioc_s_fmt_type_private(file,
fh, f);
@@ -836,46 +851,55 @@ static long __video_do_ioctl(struct file *file,
v4l2_type_names));
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ CLEAR_AFTER_FIELD(f, fmt.pix);
if (ops->vidioc_try_fmt_vid_cap)
ret = ops->vidioc_try_fmt_vid_cap(file, fh, f);
if (!ret)
v4l_print_pix_fmt(vfd, &f->fmt.pix);
break;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ CLEAR_AFTER_FIELD(f, fmt.win);
if (ops->vidioc_try_fmt_vid_overlay)
ret = ops->vidioc_try_fmt_vid_overlay(file,
fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ CLEAR_AFTER_FIELD(f, fmt.pix);
if (ops->vidioc_try_fmt_vid_out)
ret = ops->vidioc_try_fmt_vid_out(file, fh, f);
if (!ret)
v4l_print_pix_fmt(vfd, &f->fmt.pix);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ CLEAR_AFTER_FIELD(f, fmt.win);
if (ops->vidioc_try_fmt_vid_out_overlay)
ret = ops->vidioc_try_fmt_vid_out_overlay(file,
fh, f);
break;
case V4L2_BUF_TYPE_VBI_CAPTURE:
+ CLEAR_AFTER_FIELD(f, fmt.vbi);
if (ops->vidioc_try_fmt_vbi_cap)
ret = ops->vidioc_try_fmt_vbi_cap(file, fh, f);
break;
case V4L2_BUF_TYPE_VBI_OUTPUT:
+ CLEAR_AFTER_FIELD(f, fmt.vbi);
if (ops->vidioc_try_fmt_vbi_out)
ret = ops->vidioc_try_fmt_vbi_out(file, fh, f);
break;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ CLEAR_AFTER_FIELD(f, fmt.sliced);
if (ops->vidioc_try_fmt_sliced_vbi_cap)
ret = ops->vidioc_try_fmt_sliced_vbi_cap(file,
fh, f);
break;
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ CLEAR_AFTER_FIELD(f, fmt.sliced);
if (ops->vidioc_try_fmt_sliced_vbi_out)
ret = ops->vidioc_try_fmt_sliced_vbi_out(file,
fh, f);
break;
case V4L2_BUF_TYPE_PRIVATE:
+ /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */
if (ops->vidioc_try_fmt_type_private)
ret = ops->vidioc_try_fmt_type_private(file,
fh, f);
@@ -898,6 +922,9 @@ static long __video_do_ioctl(struct file *file,
if (ret)
break;
+ if (p->type < V4L2_BUF_TYPE_PRIVATE)
+ CLEAR_AFTER_FIELD(p, memory);
+
ret = ops->vidioc_reqbufs(file, fh, p);
dbgarg(cmd, "count=%d, type=%s, memory=%s\n",
p->count,
diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c
index 092333b1c34f..643cccaa1aab 100644
--- a/drivers/media/video/zoran/zoran_driver.c
+++ b/drivers/media/video/zoran/zoran_driver.c
@@ -1863,22 +1863,20 @@ static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability
static int zoran_enum_fmt(struct zoran *zr, struct v4l2_fmtdesc *fmt, int flag)
{
- int num = -1, i;
-
- for (i = 0; i < NUM_FORMATS; i++) {
- if (zoran_formats[i].flags & flag)
- num++;
- if (num == fmt->index)
- break;
+ unsigned int num, i;
+
+ for (num = i = 0; i < NUM_FORMATS; i++) {
+ if (zoran_formats[i].flags & flag && num++ == fmt->index) {
+ strncpy(fmt->description, zoran_formats[i].name,
+ sizeof(fmt->description) - 1);
+ /* fmt struct pre-zeroed, so adding '\0' not neeed */
+ fmt->pixelformat = zoran_formats[i].fourcc;
+ if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED)
+ fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
+ return 0;
+ }
}
- if (fmt->index < 0 /* late, but not too late */ || i == NUM_FORMATS)
- return -EINVAL;
-
- strncpy(fmt->description, zoran_formats[i].name, sizeof(fmt->description)-1);
- fmt->pixelformat = zoran_formats[i].fourcc;
- if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED)
- fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
- return 0;
+ return -EINVAL;
}
static int zoran_enum_fmt_vid_cap(struct file *file, void *__fh,
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
index de143deb06f0..a41634699f84 100644
--- a/drivers/memstick/core/mspro_block.c
+++ b/drivers/memstick/core/mspro_block.c
@@ -826,7 +826,7 @@ static void mspro_block_submit_req(struct request_queue *q)
if (msb->eject) {
while ((req = elv_next_request(q)) != NULL)
- __blk_end_request(req, -ENODEV, blk_rq_bytes(req));
+ __blk_end_request_all(req, -ENODEV);
return;
}
diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt
index 693e4b511354..fa9249b4971a 100644
--- a/drivers/message/fusion/lsi/mpi_history.txt
+++ b/drivers/message/fusion/lsi/mpi_history.txt
@@ -130,7 +130,7 @@ mpi_ioc.h
* 08-08-01 01.02.01 Original release for v1.2 work.
* New format for FWVersion and ProductId in
* MSG_IOC_FACTS_REPLY and MPI_FW_HEADER.
- * 08-31-01 01.02.02 Addded event MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE and
+ * 08-31-01 01.02.02 Added event MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE and
* related structure and defines.
* Added event MPI_EVENT_ON_BUS_TIMER_EXPIRED.
* Added MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE.
@@ -190,7 +190,7 @@ mpi_ioc.h
* 10-11-06 01.05.12 Added MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED.
* Added MaxInitiators field to PortFacts reply.
* Added SAS Device Status Change ReasonCode for
- * asynchronous notificaiton.
+ * asynchronous notification.
* Added MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE and event
* data structure.
* Added new ImageType values for FWDownload and FWUpload
@@ -623,7 +623,7 @@ mpi_fc.h
* 11-02-00 01.01.01 Original release for post 1.0 work
* 12-04-00 01.01.02 Added messages for Common Transport Send and
* Primitive Send.
- * 01-09-01 01.01.03 Modifed some of the new flags to have an MPI prefix
+ * 01-09-01 01.01.03 Modified some of the new flags to have an MPI prefix
* and modified the FcPrimitiveSend flags.
* 01-25-01 01.01.04 Move InitiatorIndex in LinkServiceRsp reply to a larger
* field.
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index d0d126c69354..5d496a99e034 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -5934,7 +5934,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
/* Initalize the timer
*/
- init_timer(&pCfg->timer);
+ init_timer_on_stack(&pCfg->timer);
pCfg->timer.data = (unsigned long) ioc;
pCfg->timer.function = mpt_timer_expired;
pCfg->wait_done = 0;
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index a443e136dc41..221317e6a006 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -923,7 +923,7 @@ static void i2o_block_request_fn(struct request_queue *q)
break;
}
} else
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
}
};
diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c
index 386da1566fcc..cb73051e43db 100644
--- a/drivers/mfd/htc-pasic3.c
+++ b/drivers/mfd/htc-pasic3.c
@@ -35,7 +35,7 @@ struct pasic3_data {
*/
void pasic3_write_register(struct device *dev, u32 reg, u8 val)
{
- struct pasic3_data *asic = dev->driver_data;
+ struct pasic3_data *asic = dev_get_drvdata(dev);
int bus_shift = asic->bus_shift;
void __iomem *addr = asic->mapping + (REG_ADDR << bus_shift);
void __iomem *data = asic->mapping + (REG_DATA << bus_shift);
@@ -50,7 +50,7 @@ EXPORT_SYMBOL(pasic3_write_register); /* for leds-pasic3 */
*/
u8 pasic3_read_register(struct device *dev, u32 reg)
{
- struct pasic3_data *asic = dev->driver_data;
+ struct pasic3_data *asic = dev_get_drvdata(dev);
int bus_shift = asic->bus_shift;
void __iomem *addr = asic->mapping + (REG_ADDR << bus_shift);
void __iomem *data = asic->mapping + (REG_DATA << bus_shift);
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
index 7793932a513b..8d25a8ba3910 100644
--- a/drivers/mfd/pcf50633-core.c
+++ b/drivers/mfd/pcf50633-core.c
@@ -618,7 +618,7 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
pdev->dev.parent = pcf->dev;
pdev->dev.platform_data = &pdata->reg_init_data[i];
- pdev->dev.driver_data = pcf;
+ dev_set_drvdata(&pdev->dev, pcf);
pcf->regulator_pdev[i] = pdev;
platform_device_add(pdev);
diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl4030-core.c
index ec90e953adce..cd1008c19cd7 100644
--- a/drivers/mfd/twl4030-core.c
+++ b/drivers/mfd/twl4030-core.c
@@ -647,7 +647,7 @@ static inline int __init unprotect_pm_master(void)
return e;
}
-static void __init clocks_init(struct device *dev)
+static void clocks_init(struct device *dev)
{
int e = 0;
struct clk *osc;
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c
index c2be3088e2e1..fe24079387c5 100644
--- a/drivers/mfd/wm8350-core.c
+++ b/drivers/mfd/wm8350-core.c
@@ -79,10 +79,6 @@ static int wm8350_phys_read(struct wm8350 *wm8350, u8 reg, int num_regs,
/* Cache is CPU endian */
dest[i - reg] = be16_to_cpu(dest[i - reg]);
- /* Satisfy non-volatile bits from cache */
- dest[i - reg] &= wm8350_reg_io_map[i].vol;
- dest[i - reg] |= wm8350->reg_cache[i];
-
/* Mask out non-readable bits */
dest[i - reg] &= wm8350_reg_io_map[i].readable;
}
@@ -182,9 +178,6 @@ static int wm8350_write(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *src)
(wm8350->reg_cache[i] & ~wm8350_reg_io_map[i].writable)
| src[i - reg];
- /* Don't store volatile bits */
- wm8350->reg_cache[i] &= ~wm8350_reg_io_map[i].vol;
-
src[i - reg] = cpu_to_be16(src[i - reg]);
}
@@ -1261,7 +1254,6 @@ static int wm8350_create_cache(struct wm8350 *wm8350, int type, int mode)
(i < WM8350_CLOCK_CONTROL_1 || i > WM8350_AIF_TEST)) {
value = be16_to_cpu(wm8350->reg_cache[i]);
value &= wm8350_reg_io_map[i].readable;
- value &= ~wm8350_reg_io_map[i].vol;
wm8350->reg_cache[i] = value;
} else
wm8350->reg_cache[i] = reg_map[i];
diff --git a/drivers/mfd/wm8350-regmap.c b/drivers/mfd/wm8350-regmap.c
index 9a4cc954cb7c..7ccc1eab98ab 100644
--- a/drivers/mfd/wm8350-regmap.c
+++ b/drivers/mfd/wm8350-regmap.c
@@ -3186,7 +3186,7 @@ const struct wm8350_reg_access wm8350_reg_io_map[] = {
/* read write volatile */
{ 0xFFFF, 0xFFFF, 0xFFFF }, /* R0 - Reset/ID */
{ 0x7CFF, 0x0C00, 0x7FFF }, /* R1 - ID */
- { 0x0000, 0x0000, 0x0000 }, /* R2 */
+ { 0x007F, 0x0000, 0x0000 }, /* R2 - ROM Mask ID */
{ 0xBE3B, 0xBE3B, 0x8000 }, /* R3 - System Control 1 */
{ 0xFEF7, 0xFEF7, 0xF800 }, /* R4 - System Control 2 */
{ 0x80FF, 0x80FF, 0x8000 }, /* R5 - System Hibernate */
@@ -3411,7 +3411,7 @@ const struct wm8350_reg_access wm8350_reg_io_map[] = {
{ 0x0000, 0x0000, 0x0000 }, /* R224 */
{ 0x8F3F, 0x0000, 0xFFFF }, /* R225 - DCDC/LDO status */
{ 0x0000, 0x0000, 0xFFFF }, /* R226 - Charger status */
- { 0x0000, 0x0000, 0xFFFF }, /* R227 */
+ { 0x34FE, 0x0000, 0xFFFF }, /* R227 */
{ 0x0000, 0x0000, 0x0000 }, /* R228 */
{ 0x0000, 0x0000, 0x0000 }, /* R229 */
{ 0xFFFF, 0x1FFF, 0xFFFF }, /* R230 - GPIO Pin Status */
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c
index cf30d06a0104..7c21bf791569 100644
--- a/drivers/mfd/wm8400-core.c
+++ b/drivers/mfd/wm8400-core.c
@@ -265,7 +265,7 @@ static int wm8400_init(struct wm8400 *wm8400,
mutex_init(&wm8400->io_lock);
- wm8400->dev->driver_data = wm8400;
+ dev_set_drvdata(wm8400->dev, wm8400);
/* Check that this is actually a WM8400 */
ret = wm8400->read_dev(wm8400->io_data, WM8400_RESET_ID, 1, &reg);
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 89fec052f3b4..9118613af321 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -48,6 +48,20 @@ config EEPROM_LEGACY
This driver can also be built as a module. If so, the module
will be called eeprom.
+config EEPROM_MAX6875
+ tristate "Maxim MAX6874/5 power supply supervisor"
+ depends on I2C && EXPERIMENTAL
+ help
+ If you say yes here you get read-only support for the user EEPROM of
+ the Maxim MAX6874/5 EEPROM-programmable, quad power-supply
+ sequencer/supervisor.
+
+ All other features of this chip should be accessed via i2c-dev.
+
+ This driver can also be built as a module. If so, the module
+ will be called max6875.
+
+
config EEPROM_93CX6
tristate "EEPROM 93CX6 support"
help
diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile
index 539dd8f88128..df3d68ffa9d1 100644
--- a/drivers/misc/eeprom/Makefile
+++ b/drivers/misc/eeprom/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_EEPROM_AT24) += at24.o
obj-$(CONFIG_EEPROM_AT25) += at25.o
obj-$(CONFIG_EEPROM_LEGACY) += eeprom.o
+obj-$(CONFIG_EEPROM_MAX6875) += max6875.o
obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index d184dfab9631..db39f4a52f53 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -278,7 +278,7 @@ static ssize_t at24_bin_read(struct kobject *kobj, struct bin_attribute *attr,
* We only use page mode writes; the alternative is sloooow. This routine
* writes at most one page.
*/
-static ssize_t at24_eeprom_write(struct at24_data *at24, char *buf,
+static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf,
unsigned offset, size_t count)
{
struct i2c_client *client;
@@ -347,8 +347,8 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, char *buf,
return -ETIMEDOUT;
}
-static ssize_t at24_write(struct at24_data *at24,
- char *buf, loff_t off, size_t count)
+static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off,
+ size_t count)
{
ssize_t retval = 0;
@@ -406,7 +406,7 @@ static ssize_t at24_macc_read(struct memory_accessor *macc, char *buf,
return at24_read(at24, buf, offset, count);
}
-static ssize_t at24_macc_write(struct memory_accessor *macc, char *buf,
+static ssize_t at24_macc_write(struct memory_accessor *macc, const char *buf,
off_t offset, size_t count)
{
struct at24_data *at24 = container_of(macc, struct at24_data, macc);
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index 6bc0dac5c1e8..b34cb5f79eea 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -140,7 +140,8 @@ at25_bin_read(struct kobject *kobj, struct bin_attribute *bin_attr,
static ssize_t
-at25_ee_write(struct at25_data *at25, char *buf, loff_t off, size_t count)
+at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
+ size_t count)
{
ssize_t status = 0;
unsigned written = 0;
@@ -276,7 +277,7 @@ static ssize_t at25_mem_read(struct memory_accessor *mem, char *buf,
return at25_ee_read(at25, buf, offset, count);
}
-static ssize_t at25_mem_write(struct memory_accessor *mem, char *buf,
+static ssize_t at25_mem_write(struct memory_accessor *mem, const char *buf,
off_t offset, size_t count)
{
struct at25_data *at25 = container_of(mem, struct at25_data, mem);
diff --git a/drivers/i2c/chips/max6875.c b/drivers/misc/eeprom/max6875.c
index 033d9d81ec8a..3c0c58eed347 100644
--- a/drivers/i2c/chips/max6875.c
+++ b/drivers/misc/eeprom/max6875.c
@@ -3,7 +3,7 @@
Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
- Based on i2c/chips/eeprom.c
+ Based on eeprom.c
The MAX6875 has a bank of registers and two banks of EEPROM.
Address ranges are defined as follows:
diff --git a/drivers/misc/isl29003.c b/drivers/misc/isl29003.c
index 2e2a5923d4c2..a71e245801ee 100644
--- a/drivers/misc/isl29003.c
+++ b/drivers/misc/isl29003.c
@@ -64,6 +64,7 @@ struct isl29003_data {
struct i2c_client *client;
struct mutex lock;
u8 reg_cache[ISL29003_NUM_CACHABLE_REGS];
+ u8 power_state_before_suspend;
};
static int gain_range[] = {
@@ -411,6 +412,9 @@ static int __devexit isl29003_remove(struct i2c_client *client)
#ifdef CONFIG_PM
static int isl29003_suspend(struct i2c_client *client, pm_message_t mesg)
{
+ struct isl29003_data *data = i2c_get_clientdata(client);
+
+ data->power_state_before_suspend = isl29003_get_power_state(client);
return isl29003_set_power_state(client, 0);
}
@@ -421,10 +425,11 @@ static int isl29003_resume(struct i2c_client *client)
/* restore registers from cache */
for (i = 0; i < ARRAY_SIZE(data->reg_cache); i++)
- if (!i2c_smbus_write_byte_data(client, i, data->reg_cache[i]))
+ if (i2c_smbus_write_byte_data(client, i, data->reg_cache[i]))
return -EIO;
- return 0;
+ return isl29003_set_power_state(client,
+ data->power_state_before_suspend);
}
#else
diff --git a/drivers/misc/sgi-gru/grufile.c b/drivers/misc/sgi-gru/grufile.c
index 3e6e42d2f01b..bbefe77c67a9 100644
--- a/drivers/misc/sgi-gru/grufile.c
+++ b/drivers/misc/sgi-gru/grufile.c
@@ -375,7 +375,7 @@ static int __init gru_init(void)
void *gru_start_vaddr;
if (!is_uv_system())
- return -ENODEV;
+ return 0;
#if defined CONFIG_IA64
gru_start_paddr = 0xd000000000UL; /* ZZZZZZZZZZZZZZZZZZZ fixme */
diff --git a/drivers/misc/sgi-xp/xp_main.c b/drivers/misc/sgi-xp/xp_main.c
index 16f8dcab2da4..7896849b16dc 100644
--- a/drivers/misc/sgi-xp/xp_main.c
+++ b/drivers/misc/sgi-xp/xp_main.c
@@ -248,19 +248,19 @@ xp_init(void)
enum xp_retval ret;
int ch_number;
+ /* initialize the connection registration mutex */
+ for (ch_number = 0; ch_number < XPC_MAX_NCHANNELS; ch_number++)
+ mutex_init(&xpc_registrations[ch_number].mutex);
+
if (is_shub())
ret = xp_init_sn2();
else if (is_uv())
ret = xp_init_uv();
else
- ret = xpUnsupported;
+ ret = 0;
if (ret != xpSuccess)
- return -ENODEV;
-
- /* initialize the connection registration mutex */
- for (ch_number = 0; ch_number < XPC_MAX_NCHANNELS; ch_number++)
- mutex_init(&xpc_registrations[ch_number].mutex);
+ return ret;
return 0;
}
diff --git a/drivers/misc/sgi-xp/xpc.h b/drivers/misc/sgi-xp/xpc.h
index 114444cfd496..b94d5f767703 100644
--- a/drivers/misc/sgi-xp/xpc.h
+++ b/drivers/misc/sgi-xp/xpc.h
@@ -90,18 +90,21 @@ struct xpc_rsvd_page {
short max_npartitions; /* value of XPC_MAX_PARTITIONS */
u8 version;
u8 pad1[3]; /* align to next u64 in 1st 64-byte cacheline */
+ unsigned long ts_jiffies; /* timestamp when rsvd pg was setup by XPC */
union {
- unsigned long vars_pa; /* phys address of struct xpc_vars */
- unsigned long activate_gru_mq_desc_gpa; /* phys addr of */
- /* activate mq's */
- /* gru mq descriptor */
+ struct {
+ unsigned long vars_pa; /* phys addr */
+ } sn2;
+ struct {
+ unsigned long heartbeat_gpa; /* phys addr */
+ unsigned long activate_gru_mq_desc_gpa; /* phys addr */
+ } uv;
} sn;
- unsigned long ts_jiffies; /* timestamp when rsvd pg was setup by XPC */
- u64 pad2[10]; /* align to last u64 in 2nd 64-byte cacheline */
+ u64 pad2[9]; /* align to last u64 in 2nd 64-byte cacheline */
u64 SAL_nasids_size; /* SAL: size of each nasid mask in bytes */
};
-#define XPC_RP_VERSION _XPC_VERSION(2, 0) /* version 2.0 of the reserved page */
+#define XPC_RP_VERSION _XPC_VERSION(3, 0) /* version 3.0 of the reserved page */
/*
* Define the structures by which XPC variables can be exported to other
@@ -182,6 +185,17 @@ struct xpc_vars_part_sn2 {
(XPC_RP_MACH_NASIDS(_rp) + \
xpc_nasid_mask_nlongs))
+
+/*
+ * The following structure describes the partition's heartbeat info which
+ * will be periodically read by other partitions to determine whether this
+ * XPC is still 'alive'.
+ */
+struct xpc_heartbeat_uv {
+ unsigned long value;
+ unsigned long offline; /* if 0, heartbeat should be changing */
+};
+
/*
* Info pertinent to a GRU message queue using a watch list for irq generation.
*/
@@ -198,7 +212,7 @@ struct xpc_gru_mq_uv {
/*
* The activate_mq is used to send/receive GRU messages that affect XPC's
- * heartbeat, partition active state, and channel state. This is UV only.
+ * partition active state and channel state. This is uv only.
*/
struct xpc_activate_mq_msghdr_uv {
unsigned int gru_msg_hdr; /* FOR GRU INTERNAL USE ONLY */
@@ -210,33 +224,27 @@ struct xpc_activate_mq_msghdr_uv {
/* activate_mq defined message types */
#define XPC_ACTIVATE_MQ_MSG_SYNC_ACT_STATE_UV 0
-#define XPC_ACTIVATE_MQ_MSG_INC_HEARTBEAT_UV 1
-#define XPC_ACTIVATE_MQ_MSG_OFFLINE_HEARTBEAT_UV 2
-#define XPC_ACTIVATE_MQ_MSG_ONLINE_HEARTBEAT_UV 3
-#define XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV 4
-#define XPC_ACTIVATE_MQ_MSG_DEACTIVATE_REQ_UV 5
+#define XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV 1
+#define XPC_ACTIVATE_MQ_MSG_DEACTIVATE_REQ_UV 2
-#define XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV 6
-#define XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV 7
-#define XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV 8
-#define XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV 9
+#define XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV 3
+#define XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV 4
+#define XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV 5
+#define XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV 6
+#define XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV 7
-#define XPC_ACTIVATE_MQ_MSG_MARK_ENGAGED_UV 10
-#define XPC_ACTIVATE_MQ_MSG_MARK_DISENGAGED_UV 11
+#define XPC_ACTIVATE_MQ_MSG_MARK_ENGAGED_UV 8
+#define XPC_ACTIVATE_MQ_MSG_MARK_DISENGAGED_UV 9
struct xpc_activate_mq_msg_uv {
struct xpc_activate_mq_msghdr_uv hdr;
};
-struct xpc_activate_mq_msg_heartbeat_req_uv {
- struct xpc_activate_mq_msghdr_uv hdr;
- u64 heartbeat;
-};
-
struct xpc_activate_mq_msg_activate_req_uv {
struct xpc_activate_mq_msghdr_uv hdr;
unsigned long rp_gpa;
+ unsigned long heartbeat_gpa;
unsigned long activate_gru_mq_desc_gpa;
};
@@ -271,6 +279,11 @@ struct xpc_activate_mq_msg_chctl_openreply_uv {
unsigned long notify_gru_mq_desc_gpa;
};
+struct xpc_activate_mq_msg_chctl_opencomplete_uv {
+ struct xpc_activate_mq_msghdr_uv hdr;
+ short ch_number;
+};
+
/*
* Functions registered by add_timer() or called by kernel_thread() only
* allow for a single 64-bit argument. The following macros can be used to
@@ -576,30 +589,32 @@ struct xpc_channel {
#define XPC_C_WASCONNECTED 0x00000001 /* channel was connected */
-#define XPC_C_ROPENREPLY 0x00000002 /* remote open channel reply */
-#define XPC_C_OPENREPLY 0x00000004 /* local open channel reply */
-#define XPC_C_ROPENREQUEST 0x00000008 /* remote open channel request */
-#define XPC_C_OPENREQUEST 0x00000010 /* local open channel request */
+#define XPC_C_ROPENCOMPLETE 0x00000002 /* remote open channel complete */
+#define XPC_C_OPENCOMPLETE 0x00000004 /* local open channel complete */
+#define XPC_C_ROPENREPLY 0x00000008 /* remote open channel reply */
+#define XPC_C_OPENREPLY 0x00000010 /* local open channel reply */
+#define XPC_C_ROPENREQUEST 0x00000020 /* remote open channel request */
+#define XPC_C_OPENREQUEST 0x00000040 /* local open channel request */
-#define XPC_C_SETUP 0x00000020 /* channel's msgqueues are alloc'd */
-#define XPC_C_CONNECTEDCALLOUT 0x00000040 /* connected callout initiated */
+#define XPC_C_SETUP 0x00000080 /* channel's msgqueues are alloc'd */
+#define XPC_C_CONNECTEDCALLOUT 0x00000100 /* connected callout initiated */
#define XPC_C_CONNECTEDCALLOUT_MADE \
- 0x00000080 /* connected callout completed */
-#define XPC_C_CONNECTED 0x00000100 /* local channel is connected */
-#define XPC_C_CONNECTING 0x00000200 /* channel is being connected */
+ 0x00000200 /* connected callout completed */
+#define XPC_C_CONNECTED 0x00000400 /* local channel is connected */
+#define XPC_C_CONNECTING 0x00000800 /* channel is being connected */
-#define XPC_C_RCLOSEREPLY 0x00000400 /* remote close channel reply */
-#define XPC_C_CLOSEREPLY 0x00000800 /* local close channel reply */
-#define XPC_C_RCLOSEREQUEST 0x00001000 /* remote close channel request */
-#define XPC_C_CLOSEREQUEST 0x00002000 /* local close channel request */
+#define XPC_C_RCLOSEREPLY 0x00001000 /* remote close channel reply */
+#define XPC_C_CLOSEREPLY 0x00002000 /* local close channel reply */
+#define XPC_C_RCLOSEREQUEST 0x00004000 /* remote close channel request */
+#define XPC_C_CLOSEREQUEST 0x00008000 /* local close channel request */
-#define XPC_C_DISCONNECTED 0x00004000 /* channel is disconnected */
-#define XPC_C_DISCONNECTING 0x00008000 /* channel is being disconnected */
+#define XPC_C_DISCONNECTED 0x00010000 /* channel is disconnected */
+#define XPC_C_DISCONNECTING 0x00020000 /* channel is being disconnected */
#define XPC_C_DISCONNECTINGCALLOUT \
- 0x00010000 /* disconnecting callout initiated */
+ 0x00040000 /* disconnecting callout initiated */
#define XPC_C_DISCONNECTINGCALLOUT_MADE \
- 0x00020000 /* disconnecting callout completed */
-#define XPC_C_WDISCONNECT 0x00040000 /* waiting for channel disconnect */
+ 0x00080000 /* disconnecting callout completed */
+#define XPC_C_WDISCONNECT 0x00100000 /* waiting for channel disconnect */
/*
* The channel control flags (chctl) union consists of a 64-bit variable which
@@ -618,11 +633,13 @@ union xpc_channel_ctl_flags {
#define XPC_CHCTL_CLOSEREPLY 0x02
#define XPC_CHCTL_OPENREQUEST 0x04
#define XPC_CHCTL_OPENREPLY 0x08
-#define XPC_CHCTL_MSGREQUEST 0x10
+#define XPC_CHCTL_OPENCOMPLETE 0x10
+#define XPC_CHCTL_MSGREQUEST 0x20
#define XPC_OPENCLOSE_CHCTL_FLAGS \
(XPC_CHCTL_CLOSEREQUEST | XPC_CHCTL_CLOSEREPLY | \
- XPC_CHCTL_OPENREQUEST | XPC_CHCTL_OPENREPLY)
+ XPC_CHCTL_OPENREQUEST | XPC_CHCTL_OPENREPLY | \
+ XPC_CHCTL_OPENCOMPLETE)
#define XPC_MSG_CHCTL_FLAGS XPC_CHCTL_MSGREQUEST
static inline int
@@ -687,6 +704,9 @@ struct xpc_partition_sn2 {
};
struct xpc_partition_uv {
+ unsigned long heartbeat_gpa; /* phys addr of partition's heartbeat */
+ struct xpc_heartbeat_uv cached_heartbeat; /* cached copy of */
+ /* partition's heartbeat */
unsigned long activate_gru_mq_desc_gpa; /* phys addr of parititon's */
/* activate mq's gru mq */
/* descriptor */
@@ -698,14 +718,12 @@ struct xpc_partition_uv {
u8 remote_act_state; /* remote partition's act_state */
u8 act_state_req; /* act_state request from remote partition */
enum xp_retval reason; /* reason for deactivate act_state request */
- u64 heartbeat; /* incremented by remote partition */
};
/* struct xpc_partition_uv flags */
-#define XPC_P_HEARTBEAT_OFFLINE_UV 0x00000001
+#define XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV 0x00000001
#define XPC_P_ENGAGED_UV 0x00000002
-#define XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV 0x00000004
/* struct xpc_partition_uv act_state change requests */
@@ -762,6 +780,62 @@ struct xpc_partition {
} ____cacheline_aligned;
+struct xpc_arch_operations {
+ int (*setup_partitions) (void);
+ void (*teardown_partitions) (void);
+ void (*process_activate_IRQ_rcvd) (void);
+ enum xp_retval (*get_partition_rsvd_page_pa)
+ (void *, u64 *, unsigned long *, size_t *);
+ int (*setup_rsvd_page) (struct xpc_rsvd_page *);
+
+ void (*allow_hb) (short);
+ void (*disallow_hb) (short);
+ void (*disallow_all_hbs) (void);
+ void (*increment_heartbeat) (void);
+ void (*offline_heartbeat) (void);
+ void (*online_heartbeat) (void);
+ void (*heartbeat_init) (void);
+ void (*heartbeat_exit) (void);
+ enum xp_retval (*get_remote_heartbeat) (struct xpc_partition *);
+
+ void (*request_partition_activation) (struct xpc_rsvd_page *,
+ unsigned long, int);
+ void (*request_partition_reactivation) (struct xpc_partition *);
+ void (*request_partition_deactivation) (struct xpc_partition *);
+ void (*cancel_partition_deactivation_request) (struct xpc_partition *);
+ enum xp_retval (*setup_ch_structures) (struct xpc_partition *);
+ void (*teardown_ch_structures) (struct xpc_partition *);
+
+ enum xp_retval (*make_first_contact) (struct xpc_partition *);
+
+ u64 (*get_chctl_all_flags) (struct xpc_partition *);
+ void (*send_chctl_closerequest) (struct xpc_channel *, unsigned long *);
+ void (*send_chctl_closereply) (struct xpc_channel *, unsigned long *);
+ void (*send_chctl_openrequest) (struct xpc_channel *, unsigned long *);
+ void (*send_chctl_openreply) (struct xpc_channel *, unsigned long *);
+ void (*send_chctl_opencomplete) (struct xpc_channel *, unsigned long *);
+ void (*process_msg_chctl_flags) (struct xpc_partition *, int);
+
+ enum xp_retval (*save_remote_msgqueue_pa) (struct xpc_channel *,
+ unsigned long);
+
+ enum xp_retval (*setup_msg_structures) (struct xpc_channel *);
+ void (*teardown_msg_structures) (struct xpc_channel *);
+
+ void (*indicate_partition_engaged) (struct xpc_partition *);
+ void (*indicate_partition_disengaged) (struct xpc_partition *);
+ void (*assume_partition_disengaged) (short);
+ int (*partition_engaged) (short);
+ int (*any_partition_engaged) (void);
+
+ int (*n_of_deliverable_payloads) (struct xpc_channel *);
+ enum xp_retval (*send_payload) (struct xpc_channel *, u32, void *,
+ u16, u8, xpc_notify_func, void *);
+ void *(*get_deliverable_payload) (struct xpc_channel *);
+ void (*received_payload) (struct xpc_channel *, void *);
+ void (*notify_senders_of_disconnect) (struct xpc_channel *);
+};
+
/* struct xpc_partition act_state values (for XPC HB) */
#define XPC_P_AS_INACTIVE 0x00 /* partition is not active */
@@ -802,67 +876,17 @@ extern struct xpc_registration xpc_registrations[];
/* found in xpc_main.c */
extern struct device *xpc_part;
extern struct device *xpc_chan;
+extern struct xpc_arch_operations xpc_arch_ops;
extern int xpc_disengage_timelimit;
extern int xpc_disengage_timedout;
extern int xpc_activate_IRQ_rcvd;
extern spinlock_t xpc_activate_IRQ_rcvd_lock;
extern wait_queue_head_t xpc_activate_IRQ_wq;
-extern void *xpc_heartbeating_to_mask;
extern void *xpc_kzalloc_cacheline_aligned(size_t, gfp_t, void **);
extern void xpc_activate_partition(struct xpc_partition *);
extern void xpc_activate_kthreads(struct xpc_channel *, int);
extern void xpc_create_kthreads(struct xpc_channel *, int, int);
extern void xpc_disconnect_wait(int);
-extern int (*xpc_setup_partitions_sn) (void);
-extern void (*xpc_teardown_partitions_sn) (void);
-extern enum xp_retval (*xpc_get_partition_rsvd_page_pa) (void *, u64 *,
- unsigned long *,
- size_t *);
-extern int (*xpc_setup_rsvd_page_sn) (struct xpc_rsvd_page *);
-extern void (*xpc_heartbeat_init) (void);
-extern void (*xpc_heartbeat_exit) (void);
-extern void (*xpc_increment_heartbeat) (void);
-extern void (*xpc_offline_heartbeat) (void);
-extern void (*xpc_online_heartbeat) (void);
-extern enum xp_retval (*xpc_get_remote_heartbeat) (struct xpc_partition *);
-extern enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *);
-extern u64 (*xpc_get_chctl_all_flags) (struct xpc_partition *);
-extern enum xp_retval (*xpc_setup_msg_structures) (struct xpc_channel *);
-extern void (*xpc_teardown_msg_structures) (struct xpc_channel *);
-extern void (*xpc_notify_senders_of_disconnect) (struct xpc_channel *);
-extern void (*xpc_process_msg_chctl_flags) (struct xpc_partition *, int);
-extern int (*xpc_n_of_deliverable_payloads) (struct xpc_channel *);
-extern void *(*xpc_get_deliverable_payload) (struct xpc_channel *);
-extern void (*xpc_request_partition_activation) (struct xpc_rsvd_page *,
- unsigned long, int);
-extern void (*xpc_request_partition_reactivation) (struct xpc_partition *);
-extern void (*xpc_request_partition_deactivation) (struct xpc_partition *);
-extern void (*xpc_cancel_partition_deactivation_request) (
- struct xpc_partition *);
-extern void (*xpc_process_activate_IRQ_rcvd) (void);
-extern enum xp_retval (*xpc_setup_ch_structures_sn) (struct xpc_partition *);
-extern void (*xpc_teardown_ch_structures_sn) (struct xpc_partition *);
-
-extern void (*xpc_indicate_partition_engaged) (struct xpc_partition *);
-extern int (*xpc_partition_engaged) (short);
-extern int (*xpc_any_partition_engaged) (void);
-extern void (*xpc_indicate_partition_disengaged) (struct xpc_partition *);
-extern void (*xpc_assume_partition_disengaged) (short);
-
-extern void (*xpc_send_chctl_closerequest) (struct xpc_channel *,
- unsigned long *);
-extern void (*xpc_send_chctl_closereply) (struct xpc_channel *,
- unsigned long *);
-extern void (*xpc_send_chctl_openrequest) (struct xpc_channel *,
- unsigned long *);
-extern void (*xpc_send_chctl_openreply) (struct xpc_channel *, unsigned long *);
-
-extern enum xp_retval (*xpc_save_remote_msgqueue_pa) (struct xpc_channel *,
- unsigned long);
-
-extern enum xp_retval (*xpc_send_payload) (struct xpc_channel *, u32, void *,
- u16, u8, xpc_notify_func, void *);
-extern void (*xpc_received_payload) (struct xpc_channel *, void *);
/* found in xpc_sn2.c */
extern int xpc_init_sn2(void);
@@ -909,40 +933,6 @@ extern void xpc_disconnect_channel(const int, struct xpc_channel *,
extern void xpc_disconnect_callout(struct xpc_channel *, enum xp_retval);
extern void xpc_partition_going_down(struct xpc_partition *, enum xp_retval);
-static inline int
-xpc_hb_allowed(short partid, void *heartbeating_to_mask)
-{
- return test_bit(partid, heartbeating_to_mask);
-}
-
-static inline int
-xpc_any_hbs_allowed(void)
-{
- DBUG_ON(xpc_heartbeating_to_mask == NULL);
- return !bitmap_empty(xpc_heartbeating_to_mask, xp_max_npartitions);
-}
-
-static inline void
-xpc_allow_hb(short partid)
-{
- DBUG_ON(xpc_heartbeating_to_mask == NULL);
- set_bit(partid, xpc_heartbeating_to_mask);
-}
-
-static inline void
-xpc_disallow_hb(short partid)
-{
- DBUG_ON(xpc_heartbeating_to_mask == NULL);
- clear_bit(partid, xpc_heartbeating_to_mask);
-}
-
-static inline void
-xpc_disallow_all_hbs(void)
-{
- DBUG_ON(xpc_heartbeating_to_mask == NULL);
- bitmap_zero(xpc_heartbeating_to_mask, xp_max_npartitions);
-}
-
static inline void
xpc_wakeup_channel_mgr(struct xpc_partition *part)
{
diff --git a/drivers/misc/sgi-xp/xpc_channel.c b/drivers/misc/sgi-xp/xpc_channel.c
index 99a2534c38a1..652593fc486d 100644
--- a/drivers/misc/sgi-xp/xpc_channel.c
+++ b/drivers/misc/sgi-xp/xpc_channel.c
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (c) 2004-2008 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2004-2009 Silicon Graphics, Inc. All Rights Reserved.
*/
/*
@@ -39,34 +39,38 @@ xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags)
if (!(ch->flags & XPC_C_SETUP)) {
spin_unlock_irqrestore(&ch->lock, *irq_flags);
- ret = xpc_setup_msg_structures(ch);
+ ret = xpc_arch_ops.setup_msg_structures(ch);
spin_lock_irqsave(&ch->lock, *irq_flags);
if (ret != xpSuccess)
XPC_DISCONNECT_CHANNEL(ch, ret, irq_flags);
+ else
+ ch->flags |= XPC_C_SETUP;
- ch->flags |= XPC_C_SETUP;
-
- if (ch->flags & (XPC_C_CONNECTED | XPC_C_DISCONNECTING))
+ if (ch->flags & XPC_C_DISCONNECTING)
return;
}
if (!(ch->flags & XPC_C_OPENREPLY)) {
ch->flags |= XPC_C_OPENREPLY;
- xpc_send_chctl_openreply(ch, irq_flags);
+ xpc_arch_ops.send_chctl_openreply(ch, irq_flags);
}
if (!(ch->flags & XPC_C_ROPENREPLY))
return;
- ch->flags = (XPC_C_CONNECTED | XPC_C_SETUP); /* clear all else */
+ if (!(ch->flags & XPC_C_OPENCOMPLETE)) {
+ ch->flags |= (XPC_C_OPENCOMPLETE | XPC_C_CONNECTED);
+ xpc_arch_ops.send_chctl_opencomplete(ch, irq_flags);
+ }
+
+ if (!(ch->flags & XPC_C_ROPENCOMPLETE))
+ return;
dev_info(xpc_chan, "channel %d to partition %d connected\n",
ch->number, ch->partid);
- spin_unlock_irqrestore(&ch->lock, *irq_flags);
- xpc_create_kthreads(ch, 1, 0);
- spin_lock_irqsave(&ch->lock, *irq_flags);
+ ch->flags = (XPC_C_CONNECTED | XPC_C_SETUP); /* clear all else */
}
/*
@@ -96,7 +100,7 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
if (part->act_state == XPC_P_AS_DEACTIVATING) {
/* can't proceed until the other side disengages from us */
- if (xpc_partition_engaged(ch->partid))
+ if (xpc_arch_ops.partition_engaged(ch->partid))
return;
} else {
@@ -108,7 +112,7 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
if (!(ch->flags & XPC_C_CLOSEREPLY)) {
ch->flags |= XPC_C_CLOSEREPLY;
- xpc_send_chctl_closereply(ch, irq_flags);
+ xpc_arch_ops.send_chctl_closereply(ch, irq_flags);
}
if (!(ch->flags & XPC_C_RCLOSEREPLY))
@@ -118,7 +122,7 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
/* wake those waiting for notify completion */
if (atomic_read(&ch->n_to_notify) > 0) {
/* we do callout while holding ch->lock, callout can't block */
- xpc_notify_senders_of_disconnect(ch);
+ xpc_arch_ops.notify_senders_of_disconnect(ch);
}
/* both sides are disconnected now */
@@ -132,7 +136,7 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
DBUG_ON(atomic_read(&ch->n_to_notify) != 0);
/* it's now safe to free the channel's message queues */
- xpc_teardown_msg_structures(ch);
+ xpc_arch_ops.teardown_msg_structures(ch);
ch->func = NULL;
ch->key = NULL;
@@ -144,8 +148,9 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
/*
* Mark the channel disconnected and clear all other flags, including
- * XPC_C_SETUP (because of call to xpc_teardown_msg_structures()) but
- * not including XPC_C_WDISCONNECT (if it was set).
+ * XPC_C_SETUP (because of call to
+ * xpc_arch_ops.teardown_msg_structures()) but not including
+ * XPC_C_WDISCONNECT (if it was set).
*/
ch->flags = (XPC_C_DISCONNECTED | (ch->flags & XPC_C_WDISCONNECT));
@@ -184,6 +189,7 @@ xpc_process_openclose_chctl_flags(struct xpc_partition *part, int ch_number,
struct xpc_channel *ch = &part->channels[ch_number];
enum xp_retval reason;
enum xp_retval ret;
+ int create_kthread = 0;
spin_lock_irqsave(&ch->lock, irq_flags);
@@ -196,8 +202,7 @@ again:
* has had a chance to see that the channel is disconnected.
*/
ch->delayed_chctl_flags |= chctl_flags;
- spin_unlock_irqrestore(&ch->lock, irq_flags);
- return;
+ goto out;
}
if (chctl_flags & XPC_CHCTL_CLOSEREQUEST) {
@@ -239,8 +244,7 @@ again:
XPC_CHCTL_CLOSEREQUEST;
spin_unlock(&part->chctl_lock);
}
- spin_unlock_irqrestore(&ch->lock, irq_flags);
- return;
+ goto out;
}
XPC_SET_REASON(ch, 0, 0);
@@ -250,7 +254,8 @@ again:
ch->flags |= (XPC_C_CONNECTING | XPC_C_ROPENREQUEST);
}
- chctl_flags &= ~(XPC_CHCTL_OPENREQUEST | XPC_CHCTL_OPENREPLY);
+ chctl_flags &= ~(XPC_CHCTL_OPENREQUEST | XPC_CHCTL_OPENREPLY |
+ XPC_CHCTL_OPENCOMPLETE);
/*
* The meaningful CLOSEREQUEST connection state fields are:
@@ -269,8 +274,7 @@ again:
XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);
DBUG_ON(chctl_flags & XPC_CHCTL_CLOSEREPLY);
- spin_unlock_irqrestore(&ch->lock, irq_flags);
- return;
+ goto out;
}
xpc_process_disconnect(ch, &irq_flags);
@@ -283,8 +287,7 @@ again:
if (ch->flags & XPC_C_DISCONNECTED) {
DBUG_ON(part->act_state != XPC_P_AS_DEACTIVATING);
- spin_unlock_irqrestore(&ch->lock, irq_flags);
- return;
+ goto out;
}
DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
@@ -299,8 +302,7 @@ again:
XPC_CHCTL_CLOSEREPLY;
spin_unlock(&part->chctl_lock);
}
- spin_unlock_irqrestore(&ch->lock, irq_flags);
- return;
+ goto out;
}
ch->flags |= XPC_C_RCLOSEREPLY;
@@ -320,14 +322,12 @@ again:
if (part->act_state == XPC_P_AS_DEACTIVATING ||
(ch->flags & XPC_C_ROPENREQUEST)) {
- spin_unlock_irqrestore(&ch->lock, irq_flags);
- return;
+ goto out;
}
if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_WDISCONNECT)) {
ch->delayed_chctl_flags |= XPC_CHCTL_OPENREQUEST;
- spin_unlock_irqrestore(&ch->lock, irq_flags);
- return;
+ goto out;
}
DBUG_ON(!(ch->flags & (XPC_C_DISCONNECTED |
XPC_C_OPENREQUEST)));
@@ -341,8 +341,7 @@ again:
*/
if (args->entry_size == 0 || args->local_nentries == 0) {
/* assume OPENREQUEST was delayed by mistake */
- spin_unlock_irqrestore(&ch->lock, irq_flags);
- return;
+ goto out;
}
ch->flags |= (XPC_C_ROPENREQUEST | XPC_C_CONNECTING);
@@ -352,8 +351,7 @@ again:
if (args->entry_size != ch->entry_size) {
XPC_DISCONNECT_CHANNEL(ch, xpUnequalMsgSizes,
&irq_flags);
- spin_unlock_irqrestore(&ch->lock, irq_flags);
- return;
+ goto out;
}
} else {
ch->entry_size = args->entry_size;
@@ -375,15 +373,13 @@ again:
args->local_msgqueue_pa, args->local_nentries,
args->remote_nentries, ch->partid, ch->number);
- if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED)) {
- spin_unlock_irqrestore(&ch->lock, irq_flags);
- return;
- }
+ if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED))
+ goto out;
+
if (!(ch->flags & XPC_C_OPENREQUEST)) {
XPC_DISCONNECT_CHANNEL(ch, xpOpenCloseError,
&irq_flags);
- spin_unlock_irqrestore(&ch->lock, irq_flags);
- return;
+ goto out;
}
DBUG_ON(!(ch->flags & XPC_C_ROPENREQUEST));
@@ -400,11 +396,11 @@ again:
DBUG_ON(args->local_nentries == 0);
DBUG_ON(args->remote_nentries == 0);
- ret = xpc_save_remote_msgqueue_pa(ch, args->local_msgqueue_pa);
+ ret = xpc_arch_ops.save_remote_msgqueue_pa(ch,
+ args->local_msgqueue_pa);
if (ret != xpSuccess) {
XPC_DISCONNECT_CHANNEL(ch, ret, &irq_flags);
- spin_unlock_irqrestore(&ch->lock, irq_flags);
- return;
+ goto out;
}
ch->flags |= XPC_C_ROPENREPLY;
@@ -430,7 +426,36 @@ again:
xpc_process_connect(ch, &irq_flags);
}
+ if (chctl_flags & XPC_CHCTL_OPENCOMPLETE) {
+
+ dev_dbg(xpc_chan, "XPC_CHCTL_OPENCOMPLETE received from "
+ "partid=%d, channel=%d\n", ch->partid, ch->number);
+
+ if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED))
+ goto out;
+
+ if (!(ch->flags & XPC_C_OPENREQUEST) ||
+ !(ch->flags & XPC_C_OPENREPLY)) {
+ XPC_DISCONNECT_CHANNEL(ch, xpOpenCloseError,
+ &irq_flags);
+ goto out;
+ }
+
+ DBUG_ON(!(ch->flags & XPC_C_ROPENREQUEST));
+ DBUG_ON(!(ch->flags & XPC_C_ROPENREPLY));
+ DBUG_ON(!(ch->flags & XPC_C_CONNECTED));
+
+ ch->flags |= XPC_C_ROPENCOMPLETE;
+
+ xpc_process_connect(ch, &irq_flags);
+ create_kthread = 1;
+ }
+
+out:
spin_unlock_irqrestore(&ch->lock, irq_flags);
+
+ if (create_kthread)
+ xpc_create_kthreads(ch, 1, 0);
}
/*
@@ -508,7 +533,7 @@ xpc_connect_channel(struct xpc_channel *ch)
/* initiate the connection */
ch->flags |= (XPC_C_OPENREQUEST | XPC_C_CONNECTING);
- xpc_send_chctl_openrequest(ch, &irq_flags);
+ xpc_arch_ops.send_chctl_openrequest(ch, &irq_flags);
xpc_process_connect(ch, &irq_flags);
@@ -526,7 +551,7 @@ xpc_process_sent_chctl_flags(struct xpc_partition *part)
int ch_number;
u32 ch_flags;
- chctl.all_flags = xpc_get_chctl_all_flags(part);
+ chctl.all_flags = xpc_arch_ops.get_chctl_all_flags(part);
/*
* Initiate channel connections for registered channels.
@@ -564,10 +589,6 @@ xpc_process_sent_chctl_flags(struct xpc_partition *part)
if (!(ch_flags & XPC_C_OPENREQUEST)) {
DBUG_ON(ch_flags & XPC_C_SETUP);
(void)xpc_connect_channel(ch);
- } else {
- spin_lock_irqsave(&ch->lock, irq_flags);
- xpc_process_connect(ch, &irq_flags);
- spin_unlock_irqrestore(&ch->lock, irq_flags);
}
continue;
}
@@ -579,7 +600,7 @@ xpc_process_sent_chctl_flags(struct xpc_partition *part)
*/
if (chctl.flags[ch_number] & XPC_MSG_CHCTL_FLAGS)
- xpc_process_msg_chctl_flags(part, ch_number);
+ xpc_arch_ops.process_msg_chctl_flags(part, ch_number);
}
}
@@ -755,7 +776,7 @@ xpc_disconnect_channel(const int line, struct xpc_channel *ch,
XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |
XPC_C_CONNECTING | XPC_C_CONNECTED);
- xpc_send_chctl_closerequest(ch, irq_flags);
+ xpc_arch_ops.send_chctl_closerequest(ch, irq_flags);
if (channel_was_connected)
ch->flags |= XPC_C_WASCONNECTED;
@@ -862,8 +883,8 @@ xpc_initiate_send(short partid, int ch_number, u32 flags, void *payload,
DBUG_ON(payload == NULL);
if (xpc_part_ref(part)) {
- ret = xpc_send_payload(&part->channels[ch_number], flags,
- payload, payload_size, 0, NULL, NULL);
+ ret = xpc_arch_ops.send_payload(&part->channels[ch_number],
+ flags, payload, payload_size, 0, NULL, NULL);
xpc_part_deref(part);
}
@@ -914,9 +935,8 @@ xpc_initiate_send_notify(short partid, int ch_number, u32 flags, void *payload,
DBUG_ON(func == NULL);
if (xpc_part_ref(part)) {
- ret = xpc_send_payload(&part->channels[ch_number], flags,
- payload, payload_size, XPC_N_CALL, func,
- key);
+ ret = xpc_arch_ops.send_payload(&part->channels[ch_number],
+ flags, payload, payload_size, XPC_N_CALL, func, key);
xpc_part_deref(part);
}
return ret;
@@ -930,7 +950,7 @@ xpc_deliver_payload(struct xpc_channel *ch)
{
void *payload;
- payload = xpc_get_deliverable_payload(ch);
+ payload = xpc_arch_ops.get_deliverable_payload(ch);
if (payload != NULL) {
/*
@@ -984,7 +1004,7 @@ xpc_initiate_received(short partid, int ch_number, void *payload)
DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
ch = &part->channels[ch_number];
- xpc_received_payload(ch, payload);
+ xpc_arch_ops.received_payload(ch, payload);
/* the call to xpc_msgqueue_ref() was done by xpc_deliver_payload() */
xpc_msgqueue_deref(ch);
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c
index 1ab9fda87fab..fd3688a3e23f 100644
--- a/drivers/misc/sgi-xp/xpc_main.c
+++ b/drivers/misc/sgi-xp/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-2008 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2004-2009 Silicon Graphics, Inc. All Rights Reserved.
*/
/*
@@ -150,7 +150,6 @@ DECLARE_WAIT_QUEUE_HEAD(xpc_activate_IRQ_wq);
static unsigned long xpc_hb_check_timeout;
static struct timer_list xpc_hb_timer;
-void *xpc_heartbeating_to_mask;
/* notification that the xpc_hb_checker thread has exited */
static DECLARE_COMPLETION(xpc_hb_checker_exited);
@@ -170,62 +169,7 @@ static struct notifier_block xpc_die_notifier = {
.notifier_call = xpc_system_die,
};
-int (*xpc_setup_partitions_sn) (void);
-void (*xpc_teardown_partitions_sn) (void);
-enum xp_retval (*xpc_get_partition_rsvd_page_pa) (void *buf, u64 *cookie,
- unsigned long *rp_pa,
- size_t *len);
-int (*xpc_setup_rsvd_page_sn) (struct xpc_rsvd_page *rp);
-void (*xpc_heartbeat_init) (void);
-void (*xpc_heartbeat_exit) (void);
-void (*xpc_increment_heartbeat) (void);
-void (*xpc_offline_heartbeat) (void);
-void (*xpc_online_heartbeat) (void);
-enum xp_retval (*xpc_get_remote_heartbeat) (struct xpc_partition *part);
-
-enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *part);
-void (*xpc_notify_senders_of_disconnect) (struct xpc_channel *ch);
-u64 (*xpc_get_chctl_all_flags) (struct xpc_partition *part);
-enum xp_retval (*xpc_setup_msg_structures) (struct xpc_channel *ch);
-void (*xpc_teardown_msg_structures) (struct xpc_channel *ch);
-void (*xpc_process_msg_chctl_flags) (struct xpc_partition *part, int ch_number);
-int (*xpc_n_of_deliverable_payloads) (struct xpc_channel *ch);
-void *(*xpc_get_deliverable_payload) (struct xpc_channel *ch);
-
-void (*xpc_request_partition_activation) (struct xpc_rsvd_page *remote_rp,
- unsigned long remote_rp_pa,
- int nasid);
-void (*xpc_request_partition_reactivation) (struct xpc_partition *part);
-void (*xpc_request_partition_deactivation) (struct xpc_partition *part);
-void (*xpc_cancel_partition_deactivation_request) (struct xpc_partition *part);
-
-void (*xpc_process_activate_IRQ_rcvd) (void);
-enum xp_retval (*xpc_setup_ch_structures_sn) (struct xpc_partition *part);
-void (*xpc_teardown_ch_structures_sn) (struct xpc_partition *part);
-
-void (*xpc_indicate_partition_engaged) (struct xpc_partition *part);
-int (*xpc_partition_engaged) (short partid);
-int (*xpc_any_partition_engaged) (void);
-void (*xpc_indicate_partition_disengaged) (struct xpc_partition *part);
-void (*xpc_assume_partition_disengaged) (short partid);
-
-void (*xpc_send_chctl_closerequest) (struct xpc_channel *ch,
- unsigned long *irq_flags);
-void (*xpc_send_chctl_closereply) (struct xpc_channel *ch,
- unsigned long *irq_flags);
-void (*xpc_send_chctl_openrequest) (struct xpc_channel *ch,
- unsigned long *irq_flags);
-void (*xpc_send_chctl_openreply) (struct xpc_channel *ch,
- unsigned long *irq_flags);
-
-enum xp_retval (*xpc_save_remote_msgqueue_pa) (struct xpc_channel *ch,
- unsigned long msgqueue_pa);
-
-enum xp_retval (*xpc_send_payload) (struct xpc_channel *ch, u32 flags,
- void *payload, u16 payload_size,
- u8 notify_type, xpc_notify_func func,
- void *key);
-void (*xpc_received_payload) (struct xpc_channel *ch, void *payload);
+struct xpc_arch_operations xpc_arch_ops;
/*
* Timer function to enforce the timelimit on the partition disengage.
@@ -240,7 +184,7 @@ xpc_timeout_partition_disengage(unsigned long data)
(void)xpc_partition_disengaged(part);
DBUG_ON(part->disengage_timeout != 0);
- DBUG_ON(xpc_partition_engaged(XPC_PARTID(part)));
+ DBUG_ON(xpc_arch_ops.partition_engaged(XPC_PARTID(part)));
}
/*
@@ -251,7 +195,7 @@ xpc_timeout_partition_disengage(unsigned long data)
static void
xpc_hb_beater(unsigned long dummy)
{
- xpc_increment_heartbeat();
+ xpc_arch_ops.increment_heartbeat();
if (time_is_before_eq_jiffies(xpc_hb_check_timeout))
wake_up_interruptible(&xpc_activate_IRQ_wq);
@@ -263,7 +207,7 @@ xpc_hb_beater(unsigned long dummy)
static void
xpc_start_hb_beater(void)
{
- xpc_heartbeat_init();
+ xpc_arch_ops.heartbeat_init();
init_timer(&xpc_hb_timer);
xpc_hb_timer.function = xpc_hb_beater;
xpc_hb_beater(0);
@@ -273,7 +217,7 @@ static void
xpc_stop_hb_beater(void)
{
del_timer_sync(&xpc_hb_timer);
- xpc_heartbeat_exit();
+ xpc_arch_ops.heartbeat_exit();
}
/*
@@ -302,7 +246,7 @@ xpc_check_remote_hb(void)
continue;
}
- ret = xpc_get_remote_heartbeat(part);
+ ret = xpc_arch_ops.get_remote_heartbeat(part);
if (ret != xpSuccess)
XPC_DEACTIVATE_PARTITION(part, ret);
}
@@ -353,7 +297,7 @@ xpc_hb_checker(void *ignore)
force_IRQ = 0;
dev_dbg(xpc_part, "processing activate IRQs "
"received\n");
- xpc_process_activate_IRQ_rcvd();
+ xpc_arch_ops.process_activate_IRQ_rcvd();
}
/* wait for IRQ or timeout */
@@ -528,7 +472,7 @@ xpc_setup_ch_structures(struct xpc_partition *part)
init_waitqueue_head(&ch->idle_wq);
}
- ret = xpc_setup_ch_structures_sn(part);
+ ret = xpc_arch_ops.setup_ch_structures(part);
if (ret != xpSuccess)
goto out_2;
@@ -572,7 +516,7 @@ xpc_teardown_ch_structures(struct xpc_partition *part)
/* now we can begin tearing down the infrastructure */
- xpc_teardown_ch_structures_sn(part);
+ xpc_arch_ops.teardown_ch_structures(part);
kfree(part->remote_openclose_args_base);
part->remote_openclose_args = NULL;
@@ -620,12 +564,12 @@ xpc_activating(void *__partid)
dev_dbg(xpc_part, "activating partition %d\n", partid);
- xpc_allow_hb(partid);
+ xpc_arch_ops.allow_hb(partid);
if (xpc_setup_ch_structures(part) == xpSuccess) {
(void)xpc_part_ref(part); /* this will always succeed */
- if (xpc_make_first_contact(part) == xpSuccess) {
+ if (xpc_arch_ops.make_first_contact(part) == xpSuccess) {
xpc_mark_partition_active(part);
xpc_channel_mgr(part);
/* won't return until partition is deactivating */
@@ -635,12 +579,12 @@ xpc_activating(void *__partid)
xpc_teardown_ch_structures(part);
}
- xpc_disallow_hb(partid);
+ xpc_arch_ops.disallow_hb(partid);
xpc_mark_partition_inactive(part);
if (part->reason == xpReactivating) {
/* interrupting ourselves results in activating partition */
- xpc_request_partition_reactivation(part);
+ xpc_arch_ops.request_partition_reactivation(part);
}
return 0;
@@ -713,10 +657,13 @@ xpc_activate_kthreads(struct xpc_channel *ch, int needed)
static void
xpc_kthread_waitmsgs(struct xpc_partition *part, struct xpc_channel *ch)
{
+ int (*n_of_deliverable_payloads) (struct xpc_channel *) =
+ xpc_arch_ops.n_of_deliverable_payloads;
+
do {
/* deliver messages to their intended recipients */
- while (xpc_n_of_deliverable_payloads(ch) > 0 &&
+ while (n_of_deliverable_payloads(ch) > 0 &&
!(ch->flags & XPC_C_DISCONNECTING)) {
xpc_deliver_payload(ch);
}
@@ -732,7 +679,7 @@ xpc_kthread_waitmsgs(struct xpc_partition *part, struct xpc_channel *ch)
"wait_event_interruptible_exclusive()\n");
(void)wait_event_interruptible_exclusive(ch->idle_wq,
- (xpc_n_of_deliverable_payloads(ch) > 0 ||
+ (n_of_deliverable_payloads(ch) > 0 ||
(ch->flags & XPC_C_DISCONNECTING)));
atomic_dec(&ch->kthreads_idle);
@@ -749,6 +696,8 @@ xpc_kthread_start(void *args)
struct xpc_channel *ch;
int n_needed;
unsigned long irq_flags;
+ int (*n_of_deliverable_payloads) (struct xpc_channel *) =
+ xpc_arch_ops.n_of_deliverable_payloads;
dev_dbg(xpc_chan, "kthread starting, partid=%d, channel=%d\n",
partid, ch_number);
@@ -777,7 +726,7 @@ xpc_kthread_start(void *args)
* additional kthreads to help deliver them. We only
* need one less than total #of messages to deliver.
*/
- n_needed = xpc_n_of_deliverable_payloads(ch) - 1;
+ n_needed = n_of_deliverable_payloads(ch) - 1;
if (n_needed > 0 && !(ch->flags & XPC_C_DISCONNECTING))
xpc_activate_kthreads(ch, n_needed);
@@ -805,7 +754,7 @@ xpc_kthread_start(void *args)
if (atomic_dec_return(&ch->kthreads_assigned) == 0 &&
atomic_dec_return(&part->nchannels_engaged) == 0) {
- xpc_indicate_partition_disengaged(part);
+ xpc_arch_ops.indicate_partition_disengaged(part);
}
xpc_msgqueue_deref(ch);
@@ -837,6 +786,8 @@ xpc_create_kthreads(struct xpc_channel *ch, int needed,
u64 args = XPC_PACK_ARGS(ch->partid, ch->number);
struct xpc_partition *part = &xpc_partitions[ch->partid];
struct task_struct *kthread;
+ void (*indicate_partition_disengaged) (struct xpc_partition *) =
+ xpc_arch_ops.indicate_partition_disengaged;
while (needed-- > 0) {
@@ -858,7 +809,7 @@ xpc_create_kthreads(struct xpc_channel *ch, int needed,
} else if (atomic_inc_return(&ch->kthreads_assigned) == 1 &&
atomic_inc_return(&part->nchannels_engaged) == 1) {
- xpc_indicate_partition_engaged(part);
+ xpc_arch_ops.indicate_partition_engaged(part);
}
(void)xpc_part_ref(part);
xpc_msgqueue_ref(ch);
@@ -880,7 +831,7 @@ xpc_create_kthreads(struct xpc_channel *ch, int needed,
if (atomic_dec_return(&ch->kthreads_assigned) == 0 &&
atomic_dec_return(&part->nchannels_engaged) == 0) {
- xpc_indicate_partition_disengaged(part);
+ indicate_partition_disengaged(part);
}
xpc_msgqueue_deref(ch);
xpc_part_deref(part);
@@ -993,13 +944,13 @@ xpc_setup_partitions(void)
atomic_set(&part->references, 0);
}
- return xpc_setup_partitions_sn();
+ return xpc_arch_ops.setup_partitions();
}
static void
xpc_teardown_partitions(void)
{
- xpc_teardown_partitions_sn();
+ xpc_arch_ops.teardown_partitions();
kfree(xpc_partitions);
}
@@ -1055,7 +1006,7 @@ xpc_do_exit(enum xp_retval reason)
disengage_timeout = part->disengage_timeout;
}
- if (xpc_any_partition_engaged()) {
+ if (xpc_arch_ops.any_partition_engaged()) {
if (time_is_before_jiffies(printmsg_time)) {
dev_info(xpc_part, "waiting for remote "
"partitions to deactivate, timeout in "
@@ -1086,8 +1037,7 @@ xpc_do_exit(enum xp_retval reason)
} while (1);
- DBUG_ON(xpc_any_partition_engaged());
- DBUG_ON(xpc_any_hbs_allowed() != 0);
+ DBUG_ON(xpc_arch_ops.any_partition_engaged());
xpc_teardown_rsvd_page();
@@ -1152,15 +1102,15 @@ xpc_die_deactivate(void)
/* keep xpc_hb_checker thread from doing anything (just in case) */
xpc_exiting = 1;
- xpc_disallow_all_hbs(); /*indicate we're deactivated */
+ xpc_arch_ops.disallow_all_hbs(); /*indicate we're deactivated */
for (partid = 0; partid < xp_max_npartitions; partid++) {
part = &xpc_partitions[partid];
- if (xpc_partition_engaged(partid) ||
+ if (xpc_arch_ops.partition_engaged(partid) ||
part->act_state != XPC_P_AS_INACTIVE) {
- xpc_request_partition_deactivation(part);
- xpc_indicate_partition_disengaged(part);
+ xpc_arch_ops.request_partition_deactivation(part);
+ xpc_arch_ops.indicate_partition_disengaged(part);
}
}
@@ -1177,7 +1127,7 @@ xpc_die_deactivate(void)
wait_to_print = XPC_DEACTIVATE_PRINTMSG_INTERVAL * 1000 * 5;
while (1) {
- any_engaged = xpc_any_partition_engaged();
+ any_engaged = xpc_arch_ops.any_partition_engaged();
if (!any_engaged) {
dev_info(xpc_part, "all partitions have deactivated\n");
break;
@@ -1186,7 +1136,7 @@ xpc_die_deactivate(void)
if (!keep_waiting--) {
for (partid = 0; partid < xp_max_npartitions;
partid++) {
- if (xpc_partition_engaged(partid)) {
+ if (xpc_arch_ops.partition_engaged(partid)) {
dev_info(xpc_part, "deactivate from "
"remote partition %d timed "
"out\n", partid);
@@ -1233,7 +1183,7 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused)
/* fall through */
case DIE_MCA_MONARCH_ENTER:
case DIE_INIT_MONARCH_ENTER:
- xpc_offline_heartbeat();
+ xpc_arch_ops.offline_heartbeat();
break;
case DIE_KDEBUG_LEAVE:
@@ -1244,7 +1194,7 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused)
/* fall through */
case DIE_MCA_MONARCH_LEAVE:
case DIE_INIT_MONARCH_LEAVE:
- xpc_online_heartbeat();
+ xpc_arch_ops.online_heartbeat();
break;
}
#else
diff --git a/drivers/misc/sgi-xp/xpc_partition.c b/drivers/misc/sgi-xp/xpc_partition.c
index 6722f6fe4dc7..65877bc5edaa 100644
--- a/drivers/misc/sgi-xp/xpc_partition.c
+++ b/drivers/misc/sgi-xp/xpc_partition.c
@@ -70,6 +70,9 @@ xpc_get_rsvd_page_pa(int nasid)
size_t buf_len = 0;
void *buf = buf;
void *buf_base = NULL;
+ enum xp_retval (*get_partition_rsvd_page_pa)
+ (void *, u64 *, unsigned long *, size_t *) =
+ xpc_arch_ops.get_partition_rsvd_page_pa;
while (1) {
@@ -79,8 +82,7 @@ xpc_get_rsvd_page_pa(int nasid)
* ??? function or have two versions? Rename rp_pa for UV to
* ??? rp_gpa?
*/
- ret = xpc_get_partition_rsvd_page_pa(buf, &cookie, &rp_pa,
- &len);
+ ret = get_partition_rsvd_page_pa(buf, &cookie, &rp_pa, &len);
dev_dbg(xpc_part, "SAL returned with ret=%d, cookie=0x%016lx, "
"address=0x%016lx, len=0x%016lx\n", ret,
@@ -172,7 +174,7 @@ xpc_setup_rsvd_page(void)
xpc_part_nasids = XPC_RP_PART_NASIDS(rp);
xpc_mach_nasids = XPC_RP_MACH_NASIDS(rp);
- ret = xpc_setup_rsvd_page_sn(rp);
+ ret = xpc_arch_ops.setup_rsvd_page(rp);
if (ret != 0)
return ret;
@@ -264,7 +266,7 @@ xpc_partition_disengaged(struct xpc_partition *part)
short partid = XPC_PARTID(part);
int disengaged;
- disengaged = !xpc_partition_engaged(partid);
+ disengaged = !xpc_arch_ops.partition_engaged(partid);
if (part->disengage_timeout) {
if (!disengaged) {
if (time_is_after_jiffies(part->disengage_timeout)) {
@@ -280,7 +282,7 @@ xpc_partition_disengaged(struct xpc_partition *part)
dev_info(xpc_part, "deactivate request to remote "
"partition %d timed out\n", partid);
xpc_disengage_timedout = 1;
- xpc_assume_partition_disengaged(partid);
+ xpc_arch_ops.assume_partition_disengaged(partid);
disengaged = 1;
}
part->disengage_timeout = 0;
@@ -294,7 +296,7 @@ xpc_partition_disengaged(struct xpc_partition *part)
if (part->act_state != XPC_P_AS_INACTIVE)
xpc_wakeup_channel_mgr(part);
- xpc_cancel_partition_deactivation_request(part);
+ xpc_arch_ops.cancel_partition_deactivation_request(part);
}
return disengaged;
}
@@ -339,7 +341,7 @@ xpc_deactivate_partition(const int line, struct xpc_partition *part,
spin_unlock_irqrestore(&part->act_lock, irq_flags);
if (reason == xpReactivating) {
/* we interrupt ourselves to reactivate partition */
- xpc_request_partition_reactivation(part);
+ xpc_arch_ops.request_partition_reactivation(part);
}
return;
}
@@ -358,7 +360,7 @@ xpc_deactivate_partition(const int line, struct xpc_partition *part,
spin_unlock_irqrestore(&part->act_lock, irq_flags);
/* ask remote partition to deactivate with regard to us */
- xpc_request_partition_deactivation(part);
+ xpc_arch_ops.request_partition_deactivation(part);
/* set a timelimit on the disengage phase of the deactivation request */
part->disengage_timeout = jiffies + (xpc_disengage_timelimit * HZ);
@@ -496,7 +498,7 @@ xpc_discovery(void)
continue;
}
- xpc_request_partition_activation(remote_rp,
+ xpc_arch_ops.request_partition_activation(remote_rp,
remote_rp_pa, nasid);
}
}
diff --git a/drivers/misc/sgi-xp/xpc_sn2.c b/drivers/misc/sgi-xp/xpc_sn2.c
index eaaa964942de..915a3b495da5 100644
--- a/drivers/misc/sgi-xp/xpc_sn2.c
+++ b/drivers/misc/sgi-xp/xpc_sn2.c
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2008-2009 Silicon Graphics, Inc. All Rights Reserved.
*/
/*
@@ -60,14 +60,14 @@ static struct xpc_vars_sn2 *xpc_vars_sn2;
static struct xpc_vars_part_sn2 *xpc_vars_part_sn2;
static int
-xpc_setup_partitions_sn_sn2(void)
+xpc_setup_partitions_sn2(void)
{
/* nothing needs to be done */
return 0;
}
static void
-xpc_teardown_partitions_sn_sn2(void)
+xpc_teardown_partitions_sn2(void)
{
/* nothing needs to be done */
}
@@ -431,6 +431,13 @@ xpc_send_chctl_openreply_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
}
static void
+xpc_send_chctl_opencomplete_sn2(struct xpc_channel *ch,
+ unsigned long *irq_flags)
+{
+ XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_OPENCOMPLETE, irq_flags);
+}
+
+static void
xpc_send_chctl_msgrequest_sn2(struct xpc_channel *ch)
{
XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_MSGREQUEST, NULL);
@@ -621,7 +628,7 @@ xpc_get_partition_rsvd_page_pa_sn2(void *buf, u64 *cookie, unsigned long *rp_pa,
static int
-xpc_setup_rsvd_page_sn_sn2(struct xpc_rsvd_page *rp)
+xpc_setup_rsvd_page_sn2(struct xpc_rsvd_page *rp)
{
struct amo *amos_page;
int i;
@@ -629,7 +636,7 @@ xpc_setup_rsvd_page_sn_sn2(struct xpc_rsvd_page *rp)
xpc_vars_sn2 = XPC_RP_VARS(rp);
- rp->sn.vars_pa = xp_pa(xpc_vars_sn2);
+ rp->sn.sn2.vars_pa = xp_pa(xpc_vars_sn2);
/* vars_part array follows immediately after vars */
xpc_vars_part_sn2 = (struct xpc_vars_part_sn2 *)((u8 *)XPC_RP_VARS(rp) +
@@ -693,6 +700,33 @@ xpc_setup_rsvd_page_sn_sn2(struct xpc_rsvd_page *rp)
return 0;
}
+static int
+xpc_hb_allowed_sn2(short partid, void *heartbeating_to_mask)
+{
+ return test_bit(partid, heartbeating_to_mask);
+}
+
+static void
+xpc_allow_hb_sn2(short partid)
+{
+ DBUG_ON(xpc_vars_sn2 == NULL);
+ set_bit(partid, xpc_vars_sn2->heartbeating_to_mask);
+}
+
+static void
+xpc_disallow_hb_sn2(short partid)
+{
+ DBUG_ON(xpc_vars_sn2 == NULL);
+ clear_bit(partid, xpc_vars_sn2->heartbeating_to_mask);
+}
+
+static void
+xpc_disallow_all_hbs_sn2(void)
+{
+ DBUG_ON(xpc_vars_sn2 == NULL);
+ bitmap_zero(xpc_vars_sn2->heartbeating_to_mask, xp_max_npartitions);
+}
+
static void
xpc_increment_heartbeat_sn2(void)
{
@@ -719,7 +753,6 @@ xpc_heartbeat_init_sn2(void)
DBUG_ON(xpc_vars_sn2 == NULL);
bitmap_zero(xpc_vars_sn2->heartbeating_to_mask, XP_MAX_NPARTITIONS_SN2);
- xpc_heartbeating_to_mask = &xpc_vars_sn2->heartbeating_to_mask[0];
xpc_online_heartbeat_sn2();
}
@@ -751,9 +784,9 @@ xpc_get_remote_heartbeat_sn2(struct xpc_partition *part)
remote_vars->heartbeating_to_mask[0]);
if ((remote_vars->heartbeat == part->last_heartbeat &&
- remote_vars->heartbeat_offline == 0) ||
- !xpc_hb_allowed(sn_partition_id,
- &remote_vars->heartbeating_to_mask)) {
+ !remote_vars->heartbeat_offline) ||
+ !xpc_hb_allowed_sn2(sn_partition_id,
+ remote_vars->heartbeating_to_mask)) {
ret = xpNoHeartbeat;
} else {
part->last_heartbeat = remote_vars->heartbeat;
@@ -972,7 +1005,7 @@ xpc_identify_activate_IRQ_req_sn2(int nasid)
return;
}
- remote_vars_pa = remote_rp->sn.vars_pa;
+ remote_vars_pa = remote_rp->sn.sn2.vars_pa;
remote_rp_version = remote_rp->version;
remote_rp_ts_jiffies = remote_rp->ts_jiffies;
@@ -1129,7 +1162,7 @@ xpc_process_activate_IRQ_rcvd_sn2(void)
* Setup the channel structures that are sn2 specific.
*/
static enum xp_retval
-xpc_setup_ch_structures_sn_sn2(struct xpc_partition *part)
+xpc_setup_ch_structures_sn2(struct xpc_partition *part)
{
struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
struct xpc_channel_sn2 *ch_sn2;
@@ -1251,7 +1284,7 @@ out_1:
* Teardown the channel structures that are sn2 specific.
*/
static void
-xpc_teardown_ch_structures_sn_sn2(struct xpc_partition *part)
+xpc_teardown_ch_structures_sn2(struct xpc_partition *part)
{
struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
short partid = XPC_PARTID(part);
@@ -2315,61 +2348,70 @@ xpc_received_payload_sn2(struct xpc_channel *ch, void *payload)
xpc_acknowledge_msgs_sn2(ch, get, msg->flags);
}
+static struct xpc_arch_operations xpc_arch_ops_sn2 = {
+ .setup_partitions = xpc_setup_partitions_sn2,
+ .teardown_partitions = xpc_teardown_partitions_sn2,
+ .process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_sn2,
+ .get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_sn2,
+ .setup_rsvd_page = xpc_setup_rsvd_page_sn2,
+
+ .allow_hb = xpc_allow_hb_sn2,
+ .disallow_hb = xpc_disallow_hb_sn2,
+ .disallow_all_hbs = xpc_disallow_all_hbs_sn2,
+ .increment_heartbeat = xpc_increment_heartbeat_sn2,
+ .offline_heartbeat = xpc_offline_heartbeat_sn2,
+ .online_heartbeat = xpc_online_heartbeat_sn2,
+ .heartbeat_init = xpc_heartbeat_init_sn2,
+ .heartbeat_exit = xpc_heartbeat_exit_sn2,
+ .get_remote_heartbeat = xpc_get_remote_heartbeat_sn2,
+
+ .request_partition_activation =
+ xpc_request_partition_activation_sn2,
+ .request_partition_reactivation =
+ xpc_request_partition_reactivation_sn2,
+ .request_partition_deactivation =
+ xpc_request_partition_deactivation_sn2,
+ .cancel_partition_deactivation_request =
+ xpc_cancel_partition_deactivation_request_sn2,
+
+ .setup_ch_structures = xpc_setup_ch_structures_sn2,
+ .teardown_ch_structures = xpc_teardown_ch_structures_sn2,
+
+ .make_first_contact = xpc_make_first_contact_sn2,
+
+ .get_chctl_all_flags = xpc_get_chctl_all_flags_sn2,
+ .send_chctl_closerequest = xpc_send_chctl_closerequest_sn2,
+ .send_chctl_closereply = xpc_send_chctl_closereply_sn2,
+ .send_chctl_openrequest = xpc_send_chctl_openrequest_sn2,
+ .send_chctl_openreply = xpc_send_chctl_openreply_sn2,
+ .send_chctl_opencomplete = xpc_send_chctl_opencomplete_sn2,
+ .process_msg_chctl_flags = xpc_process_msg_chctl_flags_sn2,
+
+ .save_remote_msgqueue_pa = xpc_save_remote_msgqueue_pa_sn2,
+
+ .setup_msg_structures = xpc_setup_msg_structures_sn2,
+ .teardown_msg_structures = xpc_teardown_msg_structures_sn2,
+
+ .indicate_partition_engaged = xpc_indicate_partition_engaged_sn2,
+ .indicate_partition_disengaged = xpc_indicate_partition_disengaged_sn2,
+ .partition_engaged = xpc_partition_engaged_sn2,
+ .any_partition_engaged = xpc_any_partition_engaged_sn2,
+ .assume_partition_disengaged = xpc_assume_partition_disengaged_sn2,
+
+ .n_of_deliverable_payloads = xpc_n_of_deliverable_payloads_sn2,
+ .send_payload = xpc_send_payload_sn2,
+ .get_deliverable_payload = xpc_get_deliverable_payload_sn2,
+ .received_payload = xpc_received_payload_sn2,
+ .notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_sn2,
+};
+
int
xpc_init_sn2(void)
{
int ret;
size_t buf_size;
- xpc_setup_partitions_sn = xpc_setup_partitions_sn_sn2;
- xpc_teardown_partitions_sn = xpc_teardown_partitions_sn_sn2;
- xpc_get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_sn2;
- xpc_setup_rsvd_page_sn = xpc_setup_rsvd_page_sn_sn2;
- xpc_increment_heartbeat = xpc_increment_heartbeat_sn2;
- xpc_offline_heartbeat = xpc_offline_heartbeat_sn2;
- xpc_online_heartbeat = xpc_online_heartbeat_sn2;
- xpc_heartbeat_init = xpc_heartbeat_init_sn2;
- xpc_heartbeat_exit = xpc_heartbeat_exit_sn2;
- xpc_get_remote_heartbeat = xpc_get_remote_heartbeat_sn2;
-
- xpc_request_partition_activation = xpc_request_partition_activation_sn2;
- xpc_request_partition_reactivation =
- xpc_request_partition_reactivation_sn2;
- xpc_request_partition_deactivation =
- xpc_request_partition_deactivation_sn2;
- xpc_cancel_partition_deactivation_request =
- xpc_cancel_partition_deactivation_request_sn2;
-
- xpc_process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_sn2;
- xpc_setup_ch_structures_sn = xpc_setup_ch_structures_sn_sn2;
- xpc_teardown_ch_structures_sn = xpc_teardown_ch_structures_sn_sn2;
- xpc_make_first_contact = xpc_make_first_contact_sn2;
-
- xpc_get_chctl_all_flags = xpc_get_chctl_all_flags_sn2;
- xpc_send_chctl_closerequest = xpc_send_chctl_closerequest_sn2;
- xpc_send_chctl_closereply = xpc_send_chctl_closereply_sn2;
- xpc_send_chctl_openrequest = xpc_send_chctl_openrequest_sn2;
- xpc_send_chctl_openreply = xpc_send_chctl_openreply_sn2;
-
- xpc_save_remote_msgqueue_pa = xpc_save_remote_msgqueue_pa_sn2;
-
- xpc_setup_msg_structures = xpc_setup_msg_structures_sn2;
- xpc_teardown_msg_structures = xpc_teardown_msg_structures_sn2;
-
- xpc_notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_sn2;
- xpc_process_msg_chctl_flags = xpc_process_msg_chctl_flags_sn2;
- xpc_n_of_deliverable_payloads = xpc_n_of_deliverable_payloads_sn2;
- xpc_get_deliverable_payload = xpc_get_deliverable_payload_sn2;
-
- xpc_indicate_partition_engaged = xpc_indicate_partition_engaged_sn2;
- xpc_indicate_partition_disengaged =
- xpc_indicate_partition_disengaged_sn2;
- xpc_partition_engaged = xpc_partition_engaged_sn2;
- xpc_any_partition_engaged = xpc_any_partition_engaged_sn2;
- xpc_assume_partition_disengaged = xpc_assume_partition_disengaged_sn2;
-
- xpc_send_payload = xpc_send_payload_sn2;
- xpc_received_payload = xpc_received_payload_sn2;
+ xpc_arch_ops = xpc_arch_ops_sn2;
if (offsetof(struct xpc_msg_sn2, payload) > XPC_MSG_HDR_MAX_SIZE) {
dev_err(xpc_part, "header portion of struct xpc_msg_sn2 is "
diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c
index f7fff4727edb..9172fcdee4e2 100644
--- a/drivers/misc/sgi-xp/xpc_uv.c
+++ b/drivers/misc/sgi-xp/xpc_uv.c
@@ -46,8 +46,7 @@ struct uv_IO_APIC_route_entry {
};
#endif
-static atomic64_t xpc_heartbeat_uv;
-static DECLARE_BITMAP(xpc_heartbeating_to_mask_uv, XP_MAX_NPARTITIONS_UV);
+static struct xpc_heartbeat_uv *xpc_heartbeat_uv;
#define XPC_ACTIVATE_MSG_SIZE_UV (1 * GRU_CACHE_LINE_BYTES)
#define XPC_ACTIVATE_MQ_SIZE_UV (4 * XP_MAX_NPARTITIONS_UV * \
@@ -63,7 +62,7 @@ static struct xpc_gru_mq_uv *xpc_activate_mq_uv;
static struct xpc_gru_mq_uv *xpc_notify_mq_uv;
static int
-xpc_setup_partitions_sn_uv(void)
+xpc_setup_partitions_uv(void)
{
short partid;
struct xpc_partition_uv *part_uv;
@@ -79,7 +78,7 @@ xpc_setup_partitions_sn_uv(void)
}
static void
-xpc_teardown_partitions_sn_uv(void)
+xpc_teardown_partitions_uv(void)
{
short partid;
struct xpc_partition_uv *part_uv;
@@ -423,41 +422,6 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part,
/* syncing of remote_act_state was just done above */
break;
- case XPC_ACTIVATE_MQ_MSG_INC_HEARTBEAT_UV: {
- struct xpc_activate_mq_msg_heartbeat_req_uv *msg;
-
- msg = container_of(msg_hdr,
- struct xpc_activate_mq_msg_heartbeat_req_uv,
- hdr);
- part_uv->heartbeat = msg->heartbeat;
- break;
- }
- case XPC_ACTIVATE_MQ_MSG_OFFLINE_HEARTBEAT_UV: {
- struct xpc_activate_mq_msg_heartbeat_req_uv *msg;
-
- msg = container_of(msg_hdr,
- struct xpc_activate_mq_msg_heartbeat_req_uv,
- hdr);
- part_uv->heartbeat = msg->heartbeat;
-
- spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
- part_uv->flags |= XPC_P_HEARTBEAT_OFFLINE_UV;
- spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
- break;
- }
- case XPC_ACTIVATE_MQ_MSG_ONLINE_HEARTBEAT_UV: {
- struct xpc_activate_mq_msg_heartbeat_req_uv *msg;
-
- msg = container_of(msg_hdr,
- struct xpc_activate_mq_msg_heartbeat_req_uv,
- hdr);
- part_uv->heartbeat = msg->heartbeat;
-
- spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
- part_uv->flags &= ~XPC_P_HEARTBEAT_OFFLINE_UV;
- spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
- break;
- }
case XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV: {
struct xpc_activate_mq_msg_activate_req_uv *msg;
@@ -475,6 +439,7 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part,
part_uv->act_state_req = XPC_P_ASR_ACTIVATE_UV;
part->remote_rp_pa = msg->rp_gpa; /* !!! _pa is _gpa */
part->remote_rp_ts_jiffies = msg_hdr->rp_ts_jiffies;
+ part_uv->heartbeat_gpa = msg->heartbeat_gpa;
if (msg->activate_gru_mq_desc_gpa !=
part_uv->activate_gru_mq_desc_gpa) {
@@ -569,6 +534,17 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part,
xpc_wakeup_channel_mgr(part);
break;
}
+ case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV: {
+ struct xpc_activate_mq_msg_chctl_opencomplete_uv *msg;
+
+ msg = container_of(msg_hdr, struct
+ xpc_activate_mq_msg_chctl_opencomplete_uv, hdr);
+ spin_lock_irqsave(&part->chctl_lock, irq_flags);
+ part->chctl.flags[msg->ch_number] |= XPC_CHCTL_OPENCOMPLETE;
+ spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
+
+ xpc_wakeup_channel_mgr(part);
+ }
case XPC_ACTIVATE_MQ_MSG_MARK_ENGAGED_UV:
spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
part_uv->flags |= XPC_P_ENGAGED_UV;
@@ -759,7 +735,7 @@ xpc_send_local_activate_IRQ_uv(struct xpc_partition *part, int act_state_req)
/*
* !!! Make our side think that the remote partition sent an activate
- * !!! message our way by doing what the activate IRQ handler would
+ * !!! mq message our way by doing what the activate IRQ handler would
* !!! do had one really been sent.
*/
@@ -806,90 +782,82 @@ xpc_get_partition_rsvd_page_pa_uv(void *buf, u64 *cookie, unsigned long *rp_pa,
}
static int
-xpc_setup_rsvd_page_sn_uv(struct xpc_rsvd_page *rp)
+xpc_setup_rsvd_page_uv(struct xpc_rsvd_page *rp)
{
- rp->sn.activate_gru_mq_desc_gpa =
+ xpc_heartbeat_uv =
+ &xpc_partitions[sn_partition_id].sn.uv.cached_heartbeat;
+ rp->sn.uv.heartbeat_gpa = uv_gpa(xpc_heartbeat_uv);
+ rp->sn.uv.activate_gru_mq_desc_gpa =
uv_gpa(xpc_activate_mq_uv->gru_mq_desc);
return 0;
}
static void
-xpc_send_heartbeat_uv(int msg_type)
+xpc_allow_hb_uv(short partid)
{
- short partid;
- struct xpc_partition *part;
- struct xpc_activate_mq_msg_heartbeat_req_uv msg;
-
- /*
- * !!! On uv we're broadcasting a heartbeat message every 5 seconds.
- * !!! Whereas on sn2 we're bte_copy'ng the heartbeat info every 20
- * !!! seconds. This is an increase in numalink traffic.
- * ??? Is this good?
- */
-
- msg.heartbeat = atomic64_inc_return(&xpc_heartbeat_uv);
-
- partid = find_first_bit(xpc_heartbeating_to_mask_uv,
- XP_MAX_NPARTITIONS_UV);
-
- while (partid < XP_MAX_NPARTITIONS_UV) {
- part = &xpc_partitions[partid];
+}
- xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
- msg_type);
+static void
+xpc_disallow_hb_uv(short partid)
+{
+}
- partid = find_next_bit(xpc_heartbeating_to_mask_uv,
- XP_MAX_NPARTITIONS_UV, partid + 1);
- }
+static void
+xpc_disallow_all_hbs_uv(void)
+{
}
static void
xpc_increment_heartbeat_uv(void)
{
- xpc_send_heartbeat_uv(XPC_ACTIVATE_MQ_MSG_INC_HEARTBEAT_UV);
+ xpc_heartbeat_uv->value++;
}
static void
xpc_offline_heartbeat_uv(void)
{
- xpc_send_heartbeat_uv(XPC_ACTIVATE_MQ_MSG_OFFLINE_HEARTBEAT_UV);
+ xpc_increment_heartbeat_uv();
+ xpc_heartbeat_uv->offline = 1;
}
static void
xpc_online_heartbeat_uv(void)
{
- xpc_send_heartbeat_uv(XPC_ACTIVATE_MQ_MSG_ONLINE_HEARTBEAT_UV);
+ xpc_increment_heartbeat_uv();
+ xpc_heartbeat_uv->offline = 0;
}
static void
xpc_heartbeat_init_uv(void)
{
- atomic64_set(&xpc_heartbeat_uv, 0);
- bitmap_zero(xpc_heartbeating_to_mask_uv, XP_MAX_NPARTITIONS_UV);
- xpc_heartbeating_to_mask = &xpc_heartbeating_to_mask_uv[0];
+ xpc_heartbeat_uv->value = 1;
+ xpc_heartbeat_uv->offline = 0;
}
static void
xpc_heartbeat_exit_uv(void)
{
- xpc_send_heartbeat_uv(XPC_ACTIVATE_MQ_MSG_OFFLINE_HEARTBEAT_UV);
+ xpc_offline_heartbeat_uv();
}
static enum xp_retval
xpc_get_remote_heartbeat_uv(struct xpc_partition *part)
{
struct xpc_partition_uv *part_uv = &part->sn.uv;
- enum xp_retval ret = xpNoHeartbeat;
+ enum xp_retval ret;
- if (part_uv->remote_act_state != XPC_P_AS_INACTIVE &&
- part_uv->remote_act_state != XPC_P_AS_DEACTIVATING) {
+ ret = xp_remote_memcpy(uv_gpa(&part_uv->cached_heartbeat),
+ part_uv->heartbeat_gpa,
+ sizeof(struct xpc_heartbeat_uv));
+ if (ret != xpSuccess)
+ return ret;
- if (part_uv->heartbeat != part->last_heartbeat ||
- (part_uv->flags & XPC_P_HEARTBEAT_OFFLINE_UV)) {
+ if (part_uv->cached_heartbeat.value == part->last_heartbeat &&
+ !part_uv->cached_heartbeat.offline) {
- part->last_heartbeat = part_uv->heartbeat;
- ret = xpSuccess;
- }
+ ret = xpNoHeartbeat;
+ } else {
+ part->last_heartbeat = part_uv->cached_heartbeat.value;
}
return ret;
}
@@ -904,8 +872,9 @@ xpc_request_partition_activation_uv(struct xpc_rsvd_page *remote_rp,
part->remote_rp_pa = remote_rp_gpa; /* !!! _pa here is really _gpa */
part->remote_rp_ts_jiffies = remote_rp->ts_jiffies;
+ part->sn.uv.heartbeat_gpa = remote_rp->sn.uv.heartbeat_gpa;
part->sn.uv.activate_gru_mq_desc_gpa =
- remote_rp->sn.activate_gru_mq_desc_gpa;
+ remote_rp->sn.uv.activate_gru_mq_desc_gpa;
/*
* ??? Is it a good idea to make this conditional on what is
@@ -913,8 +882,9 @@ xpc_request_partition_activation_uv(struct xpc_rsvd_page *remote_rp,
*/
if (part->sn.uv.remote_act_state == XPC_P_AS_INACTIVE) {
msg.rp_gpa = uv_gpa(xpc_rsvd_page);
+ msg.heartbeat_gpa = xpc_rsvd_page->sn.uv.heartbeat_gpa;
msg.activate_gru_mq_desc_gpa =
- xpc_rsvd_page->sn.activate_gru_mq_desc_gpa;
+ xpc_rsvd_page->sn.uv.activate_gru_mq_desc_gpa;
xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV);
}
@@ -1010,7 +980,7 @@ xpc_n_of_fifo_entries_uv(struct xpc_fifo_head_uv *head)
* Setup the channel structures that are uv specific.
*/
static enum xp_retval
-xpc_setup_ch_structures_sn_uv(struct xpc_partition *part)
+xpc_setup_ch_structures_uv(struct xpc_partition *part)
{
struct xpc_channel_uv *ch_uv;
int ch_number;
@@ -1029,7 +999,7 @@ xpc_setup_ch_structures_sn_uv(struct xpc_partition *part)
* Teardown the channel structures that are uv specific.
*/
static void
-xpc_teardown_ch_structures_sn_uv(struct xpc_partition *part)
+xpc_teardown_ch_structures_uv(struct xpc_partition *part)
{
/* nothing needs to be done */
return;
@@ -1243,6 +1213,16 @@ xpc_send_chctl_openreply_uv(struct xpc_channel *ch, unsigned long *irq_flags)
}
static void
+xpc_send_chctl_opencomplete_uv(struct xpc_channel *ch, unsigned long *irq_flags)
+{
+ struct xpc_activate_mq_msg_chctl_opencomplete_uv msg;
+
+ msg.ch_number = ch->number;
+ xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg),
+ XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV);
+}
+
+static void
xpc_send_chctl_local_msgrequest_uv(struct xpc_partition *part, int ch_number)
{
unsigned long irq_flags;
@@ -1669,58 +1649,67 @@ xpc_received_payload_uv(struct xpc_channel *ch, void *payload)
msg->hdr.msg_slot_number += ch->remote_nentries;
}
+static struct xpc_arch_operations xpc_arch_ops_uv = {
+ .setup_partitions = xpc_setup_partitions_uv,
+ .teardown_partitions = xpc_teardown_partitions_uv,
+ .process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_uv,
+ .get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_uv,
+ .setup_rsvd_page = xpc_setup_rsvd_page_uv,
+
+ .allow_hb = xpc_allow_hb_uv,
+ .disallow_hb = xpc_disallow_hb_uv,
+ .disallow_all_hbs = xpc_disallow_all_hbs_uv,
+ .increment_heartbeat = xpc_increment_heartbeat_uv,
+ .offline_heartbeat = xpc_offline_heartbeat_uv,
+ .online_heartbeat = xpc_online_heartbeat_uv,
+ .heartbeat_init = xpc_heartbeat_init_uv,
+ .heartbeat_exit = xpc_heartbeat_exit_uv,
+ .get_remote_heartbeat = xpc_get_remote_heartbeat_uv,
+
+ .request_partition_activation =
+ xpc_request_partition_activation_uv,
+ .request_partition_reactivation =
+ xpc_request_partition_reactivation_uv,
+ .request_partition_deactivation =
+ xpc_request_partition_deactivation_uv,
+ .cancel_partition_deactivation_request =
+ xpc_cancel_partition_deactivation_request_uv,
+
+ .setup_ch_structures = xpc_setup_ch_structures_uv,
+ .teardown_ch_structures = xpc_teardown_ch_structures_uv,
+
+ .make_first_contact = xpc_make_first_contact_uv,
+
+ .get_chctl_all_flags = xpc_get_chctl_all_flags_uv,
+ .send_chctl_closerequest = xpc_send_chctl_closerequest_uv,
+ .send_chctl_closereply = xpc_send_chctl_closereply_uv,
+ .send_chctl_openrequest = xpc_send_chctl_openrequest_uv,
+ .send_chctl_openreply = xpc_send_chctl_openreply_uv,
+ .send_chctl_opencomplete = xpc_send_chctl_opencomplete_uv,
+ .process_msg_chctl_flags = xpc_process_msg_chctl_flags_uv,
+
+ .save_remote_msgqueue_pa = xpc_save_remote_msgqueue_pa_uv,
+
+ .setup_msg_structures = xpc_setup_msg_structures_uv,
+ .teardown_msg_structures = xpc_teardown_msg_structures_uv,
+
+ .indicate_partition_engaged = xpc_indicate_partition_engaged_uv,
+ .indicate_partition_disengaged = xpc_indicate_partition_disengaged_uv,
+ .assume_partition_disengaged = xpc_assume_partition_disengaged_uv,
+ .partition_engaged = xpc_partition_engaged_uv,
+ .any_partition_engaged = xpc_any_partition_engaged_uv,
+
+ .n_of_deliverable_payloads = xpc_n_of_deliverable_payloads_uv,
+ .send_payload = xpc_send_payload_uv,
+ .get_deliverable_payload = xpc_get_deliverable_payload_uv,
+ .received_payload = xpc_received_payload_uv,
+ .notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_uv,
+};
+
int
xpc_init_uv(void)
{
- xpc_setup_partitions_sn = xpc_setup_partitions_sn_uv;
- xpc_teardown_partitions_sn = xpc_teardown_partitions_sn_uv;
- xpc_process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_uv;
- xpc_get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_uv;
- xpc_setup_rsvd_page_sn = xpc_setup_rsvd_page_sn_uv;
- xpc_increment_heartbeat = xpc_increment_heartbeat_uv;
- xpc_offline_heartbeat = xpc_offline_heartbeat_uv;
- xpc_online_heartbeat = xpc_online_heartbeat_uv;
- xpc_heartbeat_init = xpc_heartbeat_init_uv;
- xpc_heartbeat_exit = xpc_heartbeat_exit_uv;
- xpc_get_remote_heartbeat = xpc_get_remote_heartbeat_uv;
-
- xpc_request_partition_activation = xpc_request_partition_activation_uv;
- xpc_request_partition_reactivation =
- xpc_request_partition_reactivation_uv;
- xpc_request_partition_deactivation =
- xpc_request_partition_deactivation_uv;
- xpc_cancel_partition_deactivation_request =
- xpc_cancel_partition_deactivation_request_uv;
-
- xpc_setup_ch_structures_sn = xpc_setup_ch_structures_sn_uv;
- xpc_teardown_ch_structures_sn = xpc_teardown_ch_structures_sn_uv;
-
- xpc_make_first_contact = xpc_make_first_contact_uv;
-
- xpc_get_chctl_all_flags = xpc_get_chctl_all_flags_uv;
- xpc_send_chctl_closerequest = xpc_send_chctl_closerequest_uv;
- xpc_send_chctl_closereply = xpc_send_chctl_closereply_uv;
- xpc_send_chctl_openrequest = xpc_send_chctl_openrequest_uv;
- xpc_send_chctl_openreply = xpc_send_chctl_openreply_uv;
-
- xpc_save_remote_msgqueue_pa = xpc_save_remote_msgqueue_pa_uv;
-
- xpc_setup_msg_structures = xpc_setup_msg_structures_uv;
- xpc_teardown_msg_structures = xpc_teardown_msg_structures_uv;
-
- xpc_indicate_partition_engaged = xpc_indicate_partition_engaged_uv;
- xpc_indicate_partition_disengaged =
- xpc_indicate_partition_disengaged_uv;
- xpc_assume_partition_disengaged = xpc_assume_partition_disengaged_uv;
- xpc_partition_engaged = xpc_partition_engaged_uv;
- xpc_any_partition_engaged = xpc_any_partition_engaged_uv;
-
- xpc_n_of_deliverable_payloads = xpc_n_of_deliverable_payloads_uv;
- xpc_process_msg_chctl_flags = xpc_process_msg_chctl_flags_uv;
- xpc_send_payload = xpc_send_payload_uv;
- xpc_notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_uv;
- xpc_get_deliverable_payload = xpc_get_deliverable_payload_uv;
- xpc_received_payload = xpc_received_payload_uv;
+ xpc_arch_ops = xpc_arch_ops_uv;
if (sizeof(struct xpc_notify_mq_msghdr_uv) > XPC_MSG_HDR_MAX_SIZE) {
dev_err(xpc_part, "xpc_notify_mq_msghdr_uv is larger than %d\n",
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index fe8041e619ea..b25e9b6516ae 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -254,6 +254,14 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
brq.data.blocks = req->nr_sectors;
/*
+ * The block layer doesn't support all sector count
+ * restrictions, so we need to be prepared for too big
+ * requests.
+ */
+ if (brq.data.blocks > card->host->max_blk_count)
+ brq.data.blocks = card->host->max_blk_count;
+
+ /*
* After a read error, we redo the request one sector at a time
* in order to accurately determine which sectors can be read
* successfully.
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index fa073ab3fa34..23fb2c39d9ed 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -706,7 +706,7 @@ static void mmc_power_up(struct mmc_host *host)
* This delay should be sufficient to allow the power supply
* to reach the minimum voltage.
*/
- mmc_delay(2);
+ mmc_delay(10);
host->ios.clock = host->f_min;
host->ios.power_mode = MMC_POWER_ON;
@@ -716,7 +716,7 @@ static void mmc_power_up(struct mmc_host *host)
* This delay must be at least 74 clock sizes, or 1 ms, or the
* time required to reach a stable voltage.
*/
- mmc_delay(2);
+ mmc_delay(10);
}
static void mmc_power_off(struct mmc_host *host)
@@ -855,61 +855,72 @@ void mmc_rescan(struct work_struct *work)
mmc_bus_get(host);
- if (host->bus_ops == NULL) {
- /*
- * Only we can add a new handler, so it's safe to
- * release the lock here.
- */
+ /* if there is a card registered, check whether it is still present */
+ if ((host->bus_ops != NULL) && host->bus_ops->detect && !host->bus_dead)
+ host->bus_ops->detect(host);
+
+ mmc_bus_put(host);
+
+
+ mmc_bus_get(host);
+
+ /* if there still is a card present, stop here */
+ if (host->bus_ops != NULL) {
mmc_bus_put(host);
+ goto out;
+ }
- if (host->ops->get_cd && host->ops->get_cd(host) == 0)
- goto out;
+ /* detect a newly inserted card */
- mmc_claim_host(host);
+ /*
+ * Only we can add a new handler, so it's safe to
+ * release the lock here.
+ */
+ mmc_bus_put(host);
- mmc_power_up(host);
- mmc_go_idle(host);
+ if (host->ops->get_cd && host->ops->get_cd(host) == 0)
+ goto out;
- mmc_send_if_cond(host, host->ocr_avail);
+ mmc_claim_host(host);
- /*
- * First we search for SDIO...
- */
- err = mmc_send_io_op_cond(host, 0, &ocr);
- if (!err) {
- if (mmc_attach_sdio(host, ocr))
- mmc_power_off(host);
- goto out;
- }
+ mmc_power_up(host);
+ mmc_go_idle(host);
- /*
- * ...then normal SD...
- */
- err = mmc_send_app_op_cond(host, 0, &ocr);
- if (!err) {
- if (mmc_attach_sd(host, ocr))
- mmc_power_off(host);
- goto out;
- }
+ mmc_send_if_cond(host, host->ocr_avail);
- /*
- * ...and finally MMC.
- */
- err = mmc_send_op_cond(host, 0, &ocr);
- if (!err) {
- if (mmc_attach_mmc(host, ocr))
- mmc_power_off(host);
- goto out;
- }
+ /*
+ * First we search for SDIO...
+ */
+ err = mmc_send_io_op_cond(host, 0, &ocr);
+ if (!err) {
+ if (mmc_attach_sdio(host, ocr))
+ mmc_power_off(host);
+ goto out;
+ }
- mmc_release_host(host);
- mmc_power_off(host);
- } else {
- if (host->bus_ops->detect && !host->bus_dead)
- host->bus_ops->detect(host);
+ /*
+ * ...then normal SD...
+ */
+ err = mmc_send_app_op_cond(host, 0, &ocr);
+ if (!err) {
+ if (mmc_attach_sd(host, ocr))
+ mmc_power_off(host);
+ goto out;
+ }
- mmc_bus_put(host);
+ /*
+ * ...and finally MMC.
+ */
+ err = mmc_send_op_cond(host, 0, &ocr);
+ if (!err) {
+ if (mmc_attach_mmc(host, ocr))
+ mmc_power_off(host);
+ goto out;
}
+
+ mmc_release_host(host);
+ mmc_power_off(host);
+
out:
if (host->caps & MMC_CAP_NEEDS_POLL)
mmc_schedule_delayed_work(&host->detect, HZ);
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index cf6a100bb38f..7b603e4b41db 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -177,6 +177,7 @@ struct atmel_mci {
* available.
* @wp_pin: GPIO pin used for card write protect sending, or negative
* if not available.
+ * @detect_is_active_high: The state of the detect pin when it is active.
* @detect_timer: Timer used for debouncing @detect_pin interrupts.
*/
struct atmel_mci_slot {
@@ -196,6 +197,7 @@ struct atmel_mci_slot {
int detect_pin;
int wp_pin;
+ bool detect_is_active_high;
struct timer_list detect_timer;
};
@@ -924,7 +926,8 @@ static int atmci_get_cd(struct mmc_host *mmc)
struct atmel_mci_slot *slot = mmc_priv(mmc);
if (gpio_is_valid(slot->detect_pin)) {
- present = !gpio_get_value(slot->detect_pin);
+ present = !(gpio_get_value(slot->detect_pin) ^
+ slot->detect_is_active_high);
dev_dbg(&mmc->class_dev, "card is %spresent\n",
present ? "" : "not ");
}
@@ -1028,7 +1031,8 @@ static void atmci_detect_change(unsigned long data)
return;
enable_irq(gpio_to_irq(slot->detect_pin));
- present = !gpio_get_value(slot->detect_pin);
+ present = !(gpio_get_value(slot->detect_pin) ^
+ slot->detect_is_active_high);
present_old = test_bit(ATMCI_CARD_PRESENT, &slot->flags);
dev_vdbg(&slot->mmc->class_dev, "detect change: %d (was %d)\n",
@@ -1456,6 +1460,7 @@ static int __init atmci_init_slot(struct atmel_mci *host,
slot->host = host;
slot->detect_pin = slot_data->detect_pin;
slot->wp_pin = slot_data->wp_pin;
+ slot->detect_is_active_high = slot_data->detect_is_active_high;
slot->sdc_reg = sdc_reg;
mmc->ops = &atmci_ops;
@@ -1477,7 +1482,8 @@ static int __init atmci_init_slot(struct atmel_mci *host,
if (gpio_request(slot->detect_pin, "mmc_detect")) {
dev_dbg(&mmc->class_dev, "no detect pin available\n");
slot->detect_pin = -EBUSY;
- } else if (gpio_get_value(slot->detect_pin)) {
+ } else if (gpio_get_value(slot->detect_pin) ^
+ slot->detect_is_active_high) {
clear_bit(ATMCI_CARD_PRESENT, &slot->flags);
}
}
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index f48349d18c92..a789db8eed28 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -97,6 +97,14 @@
*/
#define r1b_timeout (HZ * 3)
+/* One of the critical speed parameters is the amount of data which may
+ * be transfered in one command. If this value is too low, the SD card
+ * controller has to do multiple partial block writes (argggh!). With
+ * today (2008) SD cards there is little speed gain if we transfer more
+ * than 64 KBytes at a time. So use this value until there is any indication
+ * that we should do more here.
+ */
+#define MMC_SPI_BLOCKSATONCE 128
/****************************************************************************/
@@ -1366,6 +1374,10 @@ static int mmc_spi_probe(struct spi_device *spi)
mmc->ops = &mmc_spi_ops;
mmc->max_blk_size = MMC_SPI_BLOCKSIZE;
+ mmc->max_hw_segs = MMC_SPI_BLOCKSATONCE;
+ mmc->max_phys_segs = MMC_SPI_BLOCKSATONCE;
+ mmc->max_req_size = MMC_SPI_BLOCKSATONCE * MMC_SPI_BLOCKSIZE;
+ mmc->max_blk_count = MMC_SPI_BLOCKSATONCE;
mmc->caps = MMC_CAP_SPI;
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index a663429b3d55..36875dcfa492 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -514,6 +514,7 @@ static int __devinit mmci_probe(struct amba_device *dev, void *id)
}
host = mmc_priv(mmc);
+ host->mmc = mmc;
/* Bits 12 thru 19 is the designer */
host->hw_designer = (dev->periphid >> 12) & 0xff;
/* Bits 20 thru 23 is the revison */
@@ -545,7 +546,6 @@ static int __devinit mmci_probe(struct amba_device *dev, void *id)
host->mclk = clk_get_rate(host->clk);
DBG(host, "eventual mclk rate: %u Hz\n", host->mclk);
}
- host->mmc = mmc;
host->base = ioremap(dev->res.start, SZ_4K);
if (!host->base) {
ret = -ENOMEM;
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index b5c375d94ab3..c643d0fe118f 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -825,24 +825,23 @@ static int __exit mvsd_remove(struct platform_device *pdev)
}
#ifdef CONFIG_PM
-static int mvsd_suspend(struct platform_device *dev, pm_message_t state,
- u32 level)
+static int mvsd_suspend(struct platform_device *dev, pm_message_t state)
{
struct mmc_host *mmc = platform_get_drvdata(dev);
int ret = 0;
- if (mmc && level == SUSPEND_DISABLE)
+ if (mmc)
ret = mmc_suspend_host(mmc, state);
return ret;
}
-static int mvsd_resume(struct platform_device *dev, u32 level)
+static int mvsd_resume(struct platform_device *dev)
{
- struct mmc_host *mmc = platform_dev_get_drvdata(dev);
+ struct mmc_host *mmc = platform_get_drvdata(dev);
int ret = 0;
- if (mmc && level == RESUME_ENABLE)
+ if (mmc)
ret = mmc_resume_host(mmc);
return ret;
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 5570849188cc..c80437928700 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -157,8 +157,6 @@ struct mmc_omap_host {
struct timer_list dma_timer;
unsigned dma_len;
- short power_pin;
-
struct mmc_omap_slot *slots[OMAP_MMC_MAX_SLOTS];
struct mmc_omap_slot *current_slot;
spinlock_t slot_lock;
@@ -1595,7 +1593,6 @@ static int mmc_omap_resume(struct platform_device *pdev)
#endif
static struct platform_driver mmc_omap_driver = {
- .probe = mmc_omap_probe,
.remove = mmc_omap_remove,
.suspend = mmc_omap_suspend,
.resume = mmc_omap_resume,
@@ -1607,7 +1604,7 @@ static struct platform_driver mmc_omap_driver = {
static int __init mmc_omap_init(void)
{
- return platform_driver_register(&mmc_omap_driver);
+ return platform_driver_probe(&mmc_omap_driver, mmc_omap_probe);
}
static void __exit mmc_omap_exit(void)
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index e62a22a7f00c..c40cb96255a2 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -680,7 +680,7 @@ static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data)
host->dma_ch = -1;
/*
* DMA Callback: run in interrupt context.
- * mutex_unlock will through a kernel warning if used.
+ * mutex_unlock will throw a kernel warning if used.
*/
up(&host->sem);
}
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index cd37962ec44f..65be27995d5c 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -522,8 +522,8 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pci_slot));
if (IS_ERR(host)) {
- ret = PTR_ERR(host);
- goto unmap;
+ dev_err(&pdev->dev, "cannot allocate host\n");
+ return ERR_PTR(PTR_ERR(host));
}
slot = sdhci_priv(host);
@@ -541,7 +541,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
ret = pci_request_region(pdev, bar, mmc_hostname(host->mmc));
if (ret) {
dev_err(&pdev->dev, "cannot request region\n");
- return ERR_PTR(ret);
+ goto free;
}
addr = pci_resource_start(pdev, bar);
@@ -572,6 +572,8 @@ unmap:
release:
pci_release_region(pdev, bar);
+
+free:
sdhci_free_host(host);
return ERR_PTR(ret);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 9234be2226e7..1432a35690dd 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1005,12 +1005,34 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
{
u8 pwr;
- if (host->power == power)
+ if (power == (unsigned short)-1)
+ pwr = 0;
+ else {
+ switch (1 << power) {
+ case MMC_VDD_165_195:
+ pwr = SDHCI_POWER_180;
+ break;
+ case MMC_VDD_29_30:
+ case MMC_VDD_30_31:
+ pwr = SDHCI_POWER_300;
+ break;
+ case MMC_VDD_32_33:
+ case MMC_VDD_33_34:
+ pwr = SDHCI_POWER_330;
+ break;
+ default:
+ BUG();
+ }
+ }
+
+ if (host->pwr == pwr)
return;
- if (power == (unsigned short)-1) {
+ host->pwr = pwr;
+
+ if (pwr == 0) {
sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
- goto out;
+ return;
}
/*
@@ -1020,35 +1042,16 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
- pwr = SDHCI_POWER_ON;
-
- switch (1 << power) {
- case MMC_VDD_165_195:
- pwr |= SDHCI_POWER_180;
- break;
- case MMC_VDD_29_30:
- case MMC_VDD_30_31:
- pwr |= SDHCI_POWER_300;
- break;
- case MMC_VDD_32_33:
- case MMC_VDD_33_34:
- pwr |= SDHCI_POWER_330;
- break;
- default:
- BUG();
- }
-
/*
* At least the Marvell CaFe chip gets confused if we set the voltage
* and set turn on power at the same time, so set the voltage first.
*/
if ((host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER))
- sdhci_writeb(host, pwr & ~SDHCI_POWER_ON, SDHCI_POWER_CONTROL);
+ sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
- sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+ pwr |= SDHCI_POWER_ON;
-out:
- host->power = power;
+ sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
}
/*****************************************************************************\
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index f20a834f4309..2de08349c3ca 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -125,7 +125,7 @@
#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \
SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \
SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \
- SDHCI_INT_DATA_END_BIT)
+ SDHCI_INT_DATA_END_BIT | SDHCI_ADMA_ERROR)
#define SDHCI_INT_ALL_MASK ((unsigned int)-1)
#define SDHCI_ACMD12_ERR 0x3C
@@ -255,7 +255,7 @@ struct sdhci_host {
unsigned int timeout_clk; /* Timeout freq (KHz) */
unsigned int clock; /* Current clock (MHz) */
- unsigned short power; /* Current voltage */
+ u8 pwr; /* Current voltage */
struct mmc_request *mrq; /* Current request */
struct mmc_command *cmd; /* Current command */
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 7d04fb9ddcaa..b8e35a0b4d72 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -154,7 +154,8 @@ config MTD_AFS_PARTS
You will still need the parsing functions to be called by the driver
for your particular device. It won't happen automatically. The
- 'armflash' map driver (CONFIG_MTD_ARMFLASH) does this, for example.
+ 'armflash' map driver (CONFIG_MTD_ARM_INTEGRATOR) does this, for
+ example.
config MTD_OF_PARTS
tristate "Flash partition map based on OF description"
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 8185b1f3e5e6..cc6369ea67dd 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -54,7 +54,7 @@
#define SR_SRWD 0x80 /* SR write protect */
/* Define max times to check status register before we give up. */
-#define MAX_READY_WAIT_COUNT 100000
+#define MAX_READY_WAIT_JIFFIES (10 * HZ) /* eg. M25P128 specs 6s max sector erase */
#define CMD_SIZE 4
#ifdef CONFIG_M25PXX_USE_FAST_READ
@@ -139,20 +139,20 @@ static inline int write_enable(struct m25p *flash)
*/
static int wait_till_ready(struct m25p *flash)
{
- int count;
+ unsigned long deadline;
int sr;
- /* one chip guarantees max 5 msec wait here after page writes,
- * but potentially three seconds (!) after page erase.
- */
- for (count = 0; count < MAX_READY_WAIT_COUNT; count++) {
+ deadline = jiffies + MAX_READY_WAIT_JIFFIES;
+
+ do {
if ((sr = read_sr(flash)) < 0)
break;
else if (!(sr & SR_WIP))
return 0;
- /* REVISIT sometimes sleeping would be best */
- }
+ cond_resched();
+
+ } while (!time_after_eq(jiffies, deadline));
return 1;
}
@@ -246,10 +246,12 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
mutex_lock(&flash->lock);
/* whole-chip erase? */
- if (len == flash->mtd.size && erase_chip(flash)) {
- instr->state = MTD_ERASE_FAILED;
- mutex_unlock(&flash->lock);
- return -EIO;
+ if (len == flash->mtd.size) {
+ if (erase_chip(flash)) {
+ instr->state = MTD_ERASE_FAILED;
+ mutex_unlock(&flash->lock);
+ return -EIO;
+ }
/* REVISIT in some cases we could speed up erasing large regions
* by using OPCODE_SE instead of OPCODE_BE_4K. We may have set up
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index a49a9c8f2cb1..76c4c8d13073 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -54,33 +54,33 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr,
if (req->cmd_type == REQ_TYPE_LINUX_BLOCK &&
req->cmd[0] == REQ_LB_OP_DISCARD)
- return !tr->discard(dev, block, nsect);
+ return tr->discard(dev, block, nsect);
if (!blk_fs_request(req))
- return 0;
+ return -EIO;
if (req->sector + req->current_nr_sectors > get_capacity(req->rq_disk))
- return 0;
+ return -EIO;
switch(rq_data_dir(req)) {
case READ:
for (; nsect > 0; nsect--, block++, buf += tr->blksize)
if (tr->readsect(dev, block, buf))
- return 0;
- return 1;
+ return -EIO;
+ return 0;
case WRITE:
if (!tr->writesect)
- return 0;
+ return -EIO;
for (; nsect > 0; nsect--, block++, buf += tr->blksize)
if (tr->writesect(dev, block, buf))
- return 0;
- return 1;
+ return -EIO;
+ return 0;
default:
printk(KERN_NOTICE "Unknown request %u\n", rq_data_dir(req));
- return 0;
+ return -EIO;
}
}
@@ -96,7 +96,7 @@ static int mtd_blktrans_thread(void *arg)
while (!kthread_should_stop()) {
struct request *req;
struct mtd_blktrans_dev *dev;
- int res = 0;
+ int res;
req = elv_next_request(rq);
@@ -119,7 +119,7 @@ static int mtd_blktrans_thread(void *arg)
spin_lock_irq(rq->queue_lock);
- end_request(req, res);
+ __blk_end_request_cur(req, res);
}
spin_unlock_irq(rq->queue_lock);
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index fdd6ae859397..bccb4b1ffc46 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -48,11 +48,11 @@ static LIST_HEAD(mtd_notifiers);
*/
static void mtd_release(struct device *dev)
{
- struct mtd_info *mtd = dev_to_mtd(dev);
+ dev_t index = MTD_DEVT(dev_to_mtd(dev)->index);
/* remove /dev/mtdXro node if needed */
- if (MTD_DEVT(mtd->index))
- device_destroy(mtd_class, MTD_DEVT(mtd->index) + 1);
+ if (index)
+ device_destroy(mtd_class, index + 1);
}
static ssize_t mtd_type_show(struct device *dev,
@@ -132,6 +132,17 @@ static ssize_t mtd_writesize_show(struct device *dev,
}
static DEVICE_ATTR(writesize, S_IRUGO, mtd_writesize_show, NULL);
+static ssize_t mtd_subpagesize_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mtd_info *mtd = dev_to_mtd(dev);
+ unsigned int subpagesize = mtd->writesize >> mtd->subpage_sft;
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", subpagesize);
+
+}
+static DEVICE_ATTR(subpagesize, S_IRUGO, mtd_subpagesize_show, NULL);
+
static ssize_t mtd_oobsize_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -169,6 +180,7 @@ static struct attribute *mtd_attrs[] = {
&dev_attr_size.attr,
&dev_attr_erasesize.attr,
&dev_attr_writesize.attr,
+ &dev_attr_subpagesize.attr,
&dev_attr_oobsize.attr,
&dev_attr_numeraseregions.attr,
&dev_attr_name.attr,
diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c
index 92285d0089c2..af8b42e0a55b 100644
--- a/drivers/mtd/mtdsuper.c
+++ b/drivers/mtd/mtdsuper.c
@@ -74,8 +74,7 @@ static int get_sb_mtd_aux(struct file_system_type *fs_type, int flags,
ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
if (ret < 0) {
- up_write(&sb->s_umount);
- deactivate_super(sb);
+ deactivate_locked_super(sb);
return ret;
}
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index 7c5b257ce8e4..29acd06b1c39 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -332,7 +332,7 @@ static void cafe_select_chip(struct mtd_info *mtd, int chipnr)
cafe->ctl1 &= ~CTRL1_CHIPSELECT;
}
-static int cafe_nand_interrupt(int irq, void *id)
+static irqreturn_t cafe_nand_interrupt(int irq, void *id)
{
struct mtd_info *mtd = id;
struct cafe_priv *cafe = mtd->priv;
diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
index 78cc71469136..b642647170be 100644
--- a/drivers/net/appletalk/ltpc.c
+++ b/drivers/net/appletalk/ltpc.c
@@ -1220,7 +1220,7 @@ static int __init ltpc_setup(char *str)
if (ints[0] > 2) {
dma = ints[3];
}
- /* ignore any other paramters */
+ /* ignore any other parameters */
}
return 1;
}
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
index 41736772c1dd..b72b3d639f6e 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -153,7 +153,7 @@ struct ep93xx_descs
struct ep93xx_priv
{
struct resource *res;
- void *base_addr;
+ void __iomem *base_addr;
int irq;
struct ep93xx_descs *descs;
diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c
index 448487e22fa3..a740053d3af3 100644
--- a/drivers/net/arm/ixp4xx_eth.c
+++ b/drivers/net/arm/ixp4xx_eth.c
@@ -338,12 +338,12 @@ static int ixp4xx_mdio_register(void)
if (cpu_is_ixp43x()) {
/* IXP43x lacks NPE-B and uses NPE-C for MII PHY access */
if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEC_ETH))
- return -ENOSYS;
+ return -ENODEV;
mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthC_BASE_VIRT;
} else {
/* All MII PHY accesses use NPE-B Ethernet registers */
if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEB_ETH0))
- return -ENOSYS;
+ return -ENODEV;
mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT;
}
@@ -1174,7 +1174,7 @@ static int __devinit eth_init_one(struct platform_device *pdev)
regs_phys = IXP4XX_EthC_BASE_PHYS;
break;
default:
- err = -ENOSYS;
+ err = -ENODEV;
goto err_free;
}
@@ -1189,15 +1189,10 @@ static int __devinit eth_init_one(struct platform_device *pdev)
goto err_free;
}
- if (register_netdev(dev)) {
- err = -EIO;
- goto err_npe_rel;
- }
-
port->mem_res = request_mem_region(regs_phys, REGS_SIZE, dev->name);
if (!port->mem_res) {
err = -EBUSY;
- goto err_unreg;
+ goto err_npe_rel;
}
port->plat = plat;
@@ -1215,20 +1210,25 @@ static int __devinit eth_init_one(struct platform_device *pdev)
snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, "0", plat->phy);
port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0,
PHY_INTERFACE_MODE_MII);
- if (IS_ERR(port->phydev)) {
- printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
- return PTR_ERR(port->phydev);
- }
+ if ((err = IS_ERR(port->phydev)))
+ goto err_free_mem;
port->phydev->irq = PHY_POLL;
+ if ((err = register_netdev(dev)))
+ goto err_phy_dis;
+
printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy,
npe_name(port->npe));
return 0;
-err_unreg:
- unregister_netdev(dev);
+err_phy_dis:
+ phy_disconnect(port->phydev);
+err_free_mem:
+ npe_port_tab[NPE_ID(port->id)] = NULL;
+ platform_set_drvdata(pdev, NULL);
+ release_resource(port->mem_res);
err_npe_rel:
npe_release(port->npe);
err_free:
@@ -1242,6 +1242,7 @@ static int __devexit eth_remove_one(struct platform_device *pdev)
struct port *port = netdev_priv(dev);
unregister_netdev(dev);
+ phy_disconnect(port->phydev);
npe_port_tab[NPE_ID(port->id)] = NULL;
platform_set_drvdata(pdev, NULL);
npe_release(port->npe);
diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c
index 8b17278c4a58..fc1092b835d2 100644
--- a/drivers/net/atl1c/atl1c_main.c
+++ b/drivers/net/atl1c/atl1c_main.c
@@ -2522,8 +2522,8 @@ static int __devinit atl1c_probe(struct pci_dev *pdev,
* various kernel subsystems to support the mechanics required by a
* fixed-high-32-bit system.
*/
- if ((pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) ||
- (pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK) != 0)) {
+ if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) ||
+ (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)) {
dev_err(&pdev->dev, "No usable DMA configuration,aborting\n");
goto err_dma;
}
diff --git a/drivers/net/b44.h b/drivers/net/b44.h
index e678498de6db..d24158e7f309 100644
--- a/drivers/net/b44.h
+++ b/drivers/net/b44.h
@@ -97,7 +97,7 @@
#define B44_DMARX_STAT 0x021CUL /* DMA RX Current Active Desc. + Status */
#define DMARX_STAT_CDMASK 0x00000fff /* Current Descriptor Mask */
#define DMARX_STAT_SMASK 0x0000f000 /* State Mask */
-#define DMARX_STAT_SDISABLED 0x00000000 /* State Disbaled */
+#define DMARX_STAT_SDISABLED 0x00000000 /* State Disabled */
#define DMARX_STAT_SACTIVE 0x00001000 /* State Active */
#define DMARX_STAT_SIDLE 0x00002000 /* State Idle Wait */
#define DMARX_STAT_SSTOPPED 0x00003000 /* State Stopped */
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index 8994b03d80ac..c23ea16135ca 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -1837,11 +1837,11 @@ static int __devinit be_probe(struct pci_dev *pdev,
be_msix_enable(adapter);
- status = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+ status = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
if (!status) {
netdev->features |= NETIF_F_HIGHDMA;
} else {
- status = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ status = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (status) {
dev_err(&pdev->dev, "Could not set PCI DMA Mask\n");
goto free_netdev;
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index a306230381c8..2c46a154f2c6 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -26,10 +26,10 @@
#include <asm/byteorder.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
+#include <linux/if_ether.h>
// General definitions
-#define BOND_ETH_P_LACPDU 0x8809
-#define PKT_TYPE_LACPDU cpu_to_be16(BOND_ETH_P_LACPDU)
+#define PKT_TYPE_LACPDU cpu_to_be16(ETH_P_SLOW)
#define AD_TIMER_INTERVAL 100 /*msec*/
#define MULTICAST_LACPDU_ADDR {0x01, 0x80, 0xC2, 0x00, 0x00, 0x02}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 815191dd03c3..56830a456c59 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -5199,7 +5199,6 @@ static int __init bonding_init(void)
{
int i;
int res;
- struct bonding *bond;
printk(KERN_INFO "%s", version);
@@ -5228,13 +5227,6 @@ static int __init bonding_init(void)
goto out;
err:
- list_for_each_entry(bond, &bond_dev_list, bond_list) {
- bond_work_cancel_all(bond);
- destroy_workqueue(bond->wq);
- }
-
- bond_destroy_sysfs();
-
rtnl_lock();
bond_free_all();
rtnl_unlock();
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 0f9ee1348552..af5364f49550 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -2785,7 +2785,7 @@ static int e100_resume(struct pci_dev *pdev)
/* ack any pending wake events, disable PME */
pci_enable_wake(pdev, 0, 0);
- /* disbale reverse auto-negotiation */
+ /* disable reverse auto-negotiation */
if (nic->phy == phy_82552_v) {
u16 smartspeed = mdio_read(netdev, nic->mii.phy_id,
E100_82552_SMARTSPEED);
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index f37360aa12a8..44f0bf23dafc 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -62,7 +62,7 @@ struct e1000_info;
e_printk(KERN_NOTICE, adapter, format, ## arg)
-/* Interrupt modes, as used by the IntMode paramter */
+/* Interrupt modes, as used by the IntMode parameter */
#define E1000E_INT_MODE_LEGACY 0
#define E1000E_INT_MODE_MSI 1
#define E1000E_INT_MODE_MSIX 2
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 16a41389575a..78952f8324e2 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -268,7 +268,7 @@ struct ehea_qp_init_attr {
};
/*
- * Event Queue attributes, passed as paramter
+ * Event Queue attributes, passed as parameter
*/
struct ehea_eq_attr {
u32 type;
diff --git a/drivers/net/igbvf/igbvf.h b/drivers/net/igbvf/igbvf.h
index 2ad6cd756539..8e9b67ebbf8b 100644
--- a/drivers/net/igbvf/igbvf.h
+++ b/drivers/net/igbvf/igbvf.h
@@ -45,7 +45,7 @@ struct igbvf_adapter;
/* Interrupt defines */
#define IGBVF_START_ITR 648 /* ~6000 ints/sec */
-/* Interrupt modes, as used by the IntMode paramter */
+/* Interrupt modes, as used by the IntMode parameter */
#define IGBVF_INT_MODE_LEGACY 0
#define IGBVF_INT_MODE_MSI 1
#define IGBVF_INT_MODE_MSIX 2
diff --git a/drivers/net/ipg.h b/drivers/net/ipg.h
index dd9318f19497..dfc2541bb556 100644
--- a/drivers/net/ipg.h
+++ b/drivers/net/ipg.h
@@ -514,7 +514,7 @@ enum ipg_regs {
#define IPG_DMALIST_ALIGN_PAD 0x07
#define IPG_MULTICAST_HASHTABLE_SIZE 0x40
-/* Number of miliseconds to wait after issuing a software reset.
+/* Number of milliseconds to wait after issuing a software reset.
* 0x05 <= IPG_AC_RESETWAIT to account for proper 10Mbps operation.
*/
#define IPG_AC_RESETWAIT 0x05
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index ece35040288c..621a7c0c46ba 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -2591,13 +2591,13 @@ static int
jme_pci_dma64(struct pci_dev *pdev)
{
if (pdev->device == PCI_DEVICE_ID_JMICRON_JMC250 &&
- !pci_set_dma_mask(pdev, DMA_64BIT_MASK))
- if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
+ !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)))
+ if (!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)))
return 1;
if (pdev->device == PCI_DEVICE_ID_JMICRON_JMC250 &&
- !pci_set_dma_mask(pdev, DMA_40BIT_MASK))
- if (!pci_set_consistent_dma_mask(pdev, DMA_40BIT_MASK))
+ !pci_set_dma_mask(pdev, DMA_BIT_MASK(40)))
+ if (!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(40)))
return 1;
if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 7bcc49de1637..e8eeef0c9c9a 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -371,7 +371,7 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
int i;
/* If we haven't received a specific coalescing setting
- * (module param), we set the moderation paramters as follows:
+ * (module param), we set the moderation parameters as follows:
* - moder_cnt is set to the number of mtu sized packets to
* satisfy our coelsing target.
* - moder_time is set to a fixed value.
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 102bac90a302..30bea9689694 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -976,7 +976,7 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
nreq = err;
goto retry;
}
-
+ kfree(entries);
goto no_msi;
}
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 9350c8663fd8..ab11c2b3f0fe 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -1257,6 +1257,9 @@ struct netxen_adapter {
u32 irq;
u32 temp;
+ u32 msi_tgt_status;
+ u32 resv4;
+
struct netxen_adapter_stats stats;
struct netxen_recv_context recv_ctx;
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index 86c9e78ec39e..42ffb825ebf1 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -914,17 +914,15 @@ netxen_nic_pci_change_crbwindow_128M(struct netxen_adapter *adapter, u32 wndw)
* In: 'off' is offset from base in 128M pci map
*/
static int
-netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter,
- ulong *off, int len)
+netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter, ulong *off)
{
- unsigned long end = *off + len;
crb_128M_2M_sub_block_map_t *m;
if (*off >= NETXEN_CRB_MAX)
return -1;
- if (*off >= NETXEN_PCI_CAMQM && (end <= NETXEN_PCI_CAMQM_2M_END)) {
+ if (*off >= NETXEN_PCI_CAMQM && (*off < NETXEN_PCI_CAMQM_2M_END)) {
*off = (*off - NETXEN_PCI_CAMQM) + NETXEN_PCI_CAMQM_2M_BASE +
(ulong)adapter->ahw.pci_base0;
return 0;
@@ -934,14 +932,13 @@ netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter,
return -1;
*off -= NETXEN_PCI_CRBSPACE;
- end = *off + len;
/*
* Try direct map
*/
m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)];
- if (m->valid && (m->start_128M <= *off) && (m->end_128M >= end)) {
+ if (m->valid && (m->start_128M <= *off) && (m->end_128M > *off)) {
*off = *off + m->start_2M - m->start_128M +
(ulong)adapter->ahw.pci_base0;
return 0;
@@ -1036,7 +1033,7 @@ netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, ulong off, u32 data)
unsigned long flags = 0;
int rv;
- rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, 4);
+ rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off);
if (rv == -1) {
printk(KERN_ERR "%s: invalid offset: 0x%016lx\n",
@@ -1066,7 +1063,7 @@ netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, ulong off)
int rv;
u32 data;
- rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, 4);
+ rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off);
if (rv == -1) {
printk(KERN_ERR "%s: invalid offset: 0x%016lx\n",
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 83dadfd78c3c..86ca0812dd48 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -175,12 +175,6 @@ netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev)
struct nx_host_sds_ring *sds_ring;
struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
- if ((adapter->flags & NETXEN_NIC_MSIX_ENABLED) &&
- adapter->rss_supported)
- adapter->max_sds_rings = (num_online_cpus() >= 4) ? 4 : 2;
- else
- adapter->max_sds_rings = 1;
-
if (netxen_alloc_sds_rings(recv_ctx, adapter->max_sds_rings))
return 1;
@@ -216,8 +210,9 @@ netxen_napi_disable(struct netxen_adapter *adapter)
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
sds_ring = &recv_ctx->sds_rings[ring];
- netxen_nic_disable_int(sds_ring);
napi_disable(&sds_ring->napi);
+ netxen_nic_disable_int(sds_ring);
+ synchronize_irq(sds_ring->irq);
}
}
@@ -297,7 +292,6 @@ static void netxen_check_options(struct netxen_adapter *adapter)
switch (adapter->ahw.board_type) {
case NETXEN_BRDTYPE_P2_SB31_10G:
case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
- case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
adapter->msix_supported = !!use_msi_x;
adapter->rss_supported = !!use_msi_x;
break;
@@ -407,11 +401,11 @@ static void netxen_set_msix_bit(struct pci_dev *pdev, int enable)
}
}
-static void netxen_init_msix_entries(struct netxen_adapter *adapter)
+static void netxen_init_msix_entries(struct netxen_adapter *adapter, int count)
{
int i;
- for (i = 0; i < MSIX_ENTRIES_PER_ADAPTER; i++)
+ for (i = 0; i < count; i++)
adapter->msix_entries[i].entry = i;
}
@@ -496,6 +490,15 @@ netxen_setup_intr(struct netxen_adapter *adapter)
{
struct netxen_legacy_intr_set *legacy_intrp;
struct pci_dev *pdev = adapter->pdev;
+ int err, num_msix;
+
+ if (adapter->rss_supported) {
+ num_msix = (num_online_cpus() >= MSIX_ENTRIES_PER_ADAPTER) ?
+ MSIX_ENTRIES_PER_ADAPTER : 2;
+ } else
+ num_msix = 1;
+
+ adapter->max_sds_rings = 1;
adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED);
@@ -512,24 +515,35 @@ netxen_setup_intr(struct netxen_adapter *adapter)
if (adapter->msix_supported) {
- netxen_init_msix_entries(adapter);
- if (pci_enable_msix(pdev, adapter->msix_entries,
- MSIX_ENTRIES_PER_ADAPTER))
- goto request_msi;
+ netxen_init_msix_entries(adapter, num_msix);
+ err = pci_enable_msix(pdev, adapter->msix_entries, num_msix);
+ if (err == 0) {
+ adapter->flags |= NETXEN_NIC_MSIX_ENABLED;
+ netxen_set_msix_bit(pdev, 1);
- adapter->flags |= NETXEN_NIC_MSIX_ENABLED;
- netxen_set_msix_bit(pdev, 1);
- dev_info(&pdev->dev, "using msi-x interrupts\n");
+ if (adapter->rss_supported)
+ adapter->max_sds_rings = num_msix;
- } else {
-request_msi:
- if (use_msi && !pci_enable_msi(pdev)) {
- adapter->flags |= NETXEN_NIC_MSI_ENABLED;
- dev_info(&pdev->dev, "using msi interrupts\n");
- } else
- dev_info(&pdev->dev, "using legacy interrupts\n");
- adapter->msix_entries[0].vector = pdev->irq;
+ dev_info(&pdev->dev, "using msi-x interrupts\n");
+ return;
+ }
+
+ if (err > 0)
+ pci_disable_msix(pdev);
+
+ /* fall through for msi */
}
+
+ if (use_msi && !pci_enable_msi(pdev)) {
+ adapter->flags |= NETXEN_NIC_MSI_ENABLED;
+ adapter->msi_tgt_status =
+ msi_tgt_status[adapter->ahw.pci_func];
+ dev_info(&pdev->dev, "using msi interrupts\n");
+ return;
+ }
+
+ dev_info(&pdev->dev, "using legacy interrupts\n");
+ adapter->msix_entries[0].vector = pdev->irq;
}
static void
@@ -765,7 +779,7 @@ netxen_nic_request_irq(struct netxen_adapter *adapter)
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
sds_ring = &recv_ctx->sds_rings[ring];
- sprintf(sds_ring->name, "%16s[%d]", netdev->name, ring);
+ sprintf(sds_ring->name, "%s[%d]", netdev->name, ring);
err = request_irq(sds_ring->irq, handler,
flags, sds_ring->name, sds_ring);
if (err)
@@ -828,8 +842,6 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
{
netif_carrier_off(netdev);
netif_stop_queue(netdev);
- smp_mb();
- netxen_napi_disable(adapter);
if (adapter->stop_port)
adapter->stop_port(adapter);
@@ -837,6 +849,8 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
netxen_p3_free_mac_list(adapter);
+ netxen_napi_disable(adapter);
+
netxen_release_tx_buffers(adapter);
FLUSH_SCHEDULED_WORK();
@@ -915,10 +929,9 @@ err_out_free_sw:
static void
netxen_nic_detach(struct netxen_adapter *adapter)
{
- netxen_nic_free_irq(adapter);
-
netxen_release_rx_buffers(adapter);
netxen_free_hw_resources(adapter);
+ netxen_nic_free_irq(adapter);
netxen_free_sw_resources(adapter);
adapter->is_up = 0;
@@ -1701,7 +1714,7 @@ static irqreturn_t netxen_msi_intr(int irq, void *data)
/* clear interrupt */
adapter->pci_write_immediate(adapter,
- msi_tgt_status[adapter->ahw.pci_func], 0xffffffff);
+ adapter->msi_tgt_status, 0xffffffff);
napi_schedule(&sds_ring->napi);
return IRQ_HANDLED;
diff --git a/drivers/net/niu.h b/drivers/net/niu.h
index 8754e44cadae..3bd0b5933d59 100644
--- a/drivers/net/niu.h
+++ b/drivers/net/niu.h
@@ -3242,8 +3242,8 @@ struct niu {
struct niu_parent *parent;
u32 flags;
-#define NIU_FLAGS_HOTPLUG_PHY_PRESENT 0x02000000 /* Removebale PHY detected*/
-#define NIU_FLAGS_HOTPLUG_PHY 0x01000000 /* Removebale PHY */
+#define NIU_FLAGS_HOTPLUG_PHY_PRESENT 0x02000000 /* Removeable PHY detected*/
+#define NIU_FLAGS_HOTPLUG_PHY 0x01000000 /* Removeable PHY */
#define NIU_FLAGS_VPD_VALID 0x00800000 /* VPD has valid version */
#define NIU_FLAGS_MSIX 0x00400000 /* MSI-X in use */
#define NIU_FLAGS_MCAST 0x00200000 /* multicast filter enabled */
diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c
index 9f81b797f10b..ac9493f6c1a1 100644
--- a/drivers/net/qlge/qlge_mpi.c
+++ b/drivers/net/qlge/qlge_mpi.c
@@ -141,7 +141,7 @@ end:
/* We are being asked by firmware to accept
* a change to the port. This is only
* a change to max frame sizes (Tx/Rx), pause
- * paramters, or loopback mode. We wake up a worker
+ * parameters, or loopback mode. We wake up a worker
* to handler processing this since a mailbox command
* will need to be sent to ACK the request.
*/
@@ -371,7 +371,7 @@ static int ql_mpi_handler(struct ql_adapter *qdev, struct mbox_params *mbcp)
/* We are being asked by firmware to accept
* a change to the port. This is only
* a change to max frame sizes (Tx/Rx), pause
- * paramters, or loopback mode.
+ * parameters, or loopback mode.
*/
case AEN_IDC_REQ:
status = ql_idc_req_aen(qdev);
@@ -380,7 +380,7 @@ static int ql_mpi_handler(struct ql_adapter *qdev, struct mbox_params *mbcp)
/* Process and inbound IDC event.
* This will happen when we're trying to
* change tx/rx max frame size, change pause
- * paramters or loopback mode.
+ * parameters or loopback mode.
*/
case AEN_IDC_CMPLT:
case AEN_IDC_EXT:
diff --git a/drivers/net/skfp/h/smt.h b/drivers/net/skfp/h/smt.h
index 1ff589988d10..2976757a36fb 100644
--- a/drivers/net/skfp/h/smt.h
+++ b/drivers/net/skfp/h/smt.h
@@ -413,7 +413,7 @@ struct smt_p_reason {
#define SMT_RDF_SUCCESS 0x00000003 /* success (PMF) */
#define SMT_RDF_BADSET 0x00000004 /* bad set count (PMF) */
#define SMT_RDF_ILLEGAL 0x00000005 /* read only (PMF) */
-#define SMT_RDF_NOPARAM 0x6 /* paramter not supported (PMF) */
+#define SMT_RDF_NOPARAM 0x6 /* parameter not supported (PMF) */
#define SMT_RDF_RANGE 0x8 /* out of range */
#define SMT_RDF_AUTHOR 0x9 /* not autohorized */
#define SMT_RDF_LENGTH 0x0a /* length error */
diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
index 534c0f38483c..0337b9d673f4 100644
--- a/drivers/net/tokenring/3c359.c
+++ b/drivers/net/tokenring/3c359.c
@@ -79,7 +79,7 @@ MODULE_AUTHOR("Mike Phillips <mikep@linuxtr.net>") ;
MODULE_DESCRIPTION("3Com 3C359 Velocity XL Token Ring Adapter Driver \n") ;
MODULE_FIRMWARE(FW_NAME);
-/* Module paramters */
+/* Module parameters */
/* Ring Speed 0,4,16
* 0 = Autosense
diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c
index 2e70ee8f1459..46a2cc92d979 100644
--- a/drivers/net/tokenring/lanstreamer.c
+++ b/drivers/net/tokenring/lanstreamer.c
@@ -169,7 +169,7 @@ static char *open_min_error[] = {
"Monitor Contention failer for RPL", "FDX Protocol Error"
};
-/* Module paramters */
+/* Module parameters */
/* Ring Speed 0,4,16
* 0 = Autosense
diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
index d068a9d36883..2d819fc85589 100644
--- a/drivers/net/tokenring/olympic.c
+++ b/drivers/net/tokenring/olympic.c
@@ -132,7 +132,7 @@ static char *open_min_error[] = {"No error", "Function Failure", "Signal Lost",
"Reserved", "Reserved", "No Monitor Detected for RPL",
"Monitor Contention failer for RPL", "FDX Protocol Error"};
-/* Module paramters */
+/* Module parameters */
MODULE_AUTHOR("Mike Phillips <mikep@linuxtr.net>") ;
MODULE_DESCRIPTION("Olympic PCI/Cardbus Chipset Driver") ;
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index f18017dc0255..33d4e4c0e8f2 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -271,7 +271,7 @@ static int fill_init_enet_entries(struct ucc_geth_private *ugeth,
u8 num_entries,
u32 thread_size,
u32 thread_alignment,
- enum qe_risc_allocation risc,
+ unsigned int risc,
int skip_page_for_first_entry)
{
u32 init_enet_offset;
@@ -308,7 +308,7 @@ static int fill_init_enet_entries(struct ucc_geth_private *ugeth,
static int return_init_enet_entries(struct ucc_geth_private *ugeth,
u32 *p_start,
u8 num_entries,
- enum qe_risc_allocation risc,
+ unsigned int risc,
int skip_page_for_first_entry)
{
u32 init_enet_offset;
@@ -343,7 +343,7 @@ static int dump_init_enet_entries(struct ucc_geth_private *ugeth,
u32 __iomem *p_start,
u8 num_entries,
u32 thread_size,
- enum qe_risc_allocation risc,
+ unsigned int risc,
int skip_page_for_first_entry)
{
u32 init_enet_offset;
@@ -2138,6 +2138,14 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
return -ENOMEM;
}
+ /* read the number of risc engines, update the riscTx and riscRx
+ * if there are 4 riscs in QE
+ */
+ if (qe_get_num_of_risc() == 4) {
+ ug_info->riscTx = QE_RISC_ALLOCATION_FOUR_RISCS;
+ ug_info->riscRx = QE_RISC_ALLOCATION_FOUR_RISCS;
+ }
+
ugeth->ug_regs = ioremap(uf_info->regs, sizeof(*ugeth->ug_regs));
if (!ugeth->ug_regs) {
if (netif_msg_probe(ugeth))
@@ -3667,7 +3675,15 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
ug_info->uf_info.utfet = UCC_GETH_UTFET_GIGA_INIT;
ug_info->uf_info.utftt = UCC_GETH_UTFTT_GIGA_INIT;
ug_info->numThreadsTx = UCC_GETH_NUM_OF_THREADS_4;
- ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_4;
+
+ /* If QE's snum number is 46 which means we need to support
+ * 4 UECs at 1000Base-T simultaneously, we need to allocate
+ * more Threads to Rx.
+ */
+ if (qe_get_num_of_snums() == 46)
+ ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_6;
+ else
+ ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_4;
}
if (netif_msg_probe(&debug))
diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h
index dca628a922ba..816027656c06 100644
--- a/drivers/net/ucc_geth.h
+++ b/drivers/net/ucc_geth.h
@@ -1119,8 +1119,8 @@ struct ucc_geth_info {
enum ucc_geth_maccfg2_pad_and_crc_mode padAndCrc;
enum ucc_geth_num_of_threads numThreadsTx;
enum ucc_geth_num_of_threads numThreadsRx;
- enum qe_risc_allocation riscTx;
- enum qe_risc_allocation riscRx;
+ unsigned int riscTx;
+ unsigned int riscRx;
};
/* structure representing UCC GETH */
diff --git a/drivers/net/ucc_geth_ethtool.c b/drivers/net/ucc_geth_ethtool.c
index 6fcb500257bc..61fe80dda3e3 100644
--- a/drivers/net/ucc_geth_ethtool.c
+++ b/drivers/net/ucc_geth_ethtool.c
@@ -7,7 +7,7 @@
*
* Limitation:
* Can only get/set setttings of the first queue.
- * Need to re-open the interface manually after changing some paramters.
+ * Need to re-open the interface manually after changing some parameters.
*
* 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
diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index 3bf7d3f447db..765a7f5d6aa4 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -1249,7 +1249,7 @@ static int __devinit hss_init_one(struct platform_device *pdev)
return -ENOMEM;
if ((port->npe = npe_request(0)) == NULL) {
- err = -ENOSYS;
+ err = -ENODEV;
goto err_free;
}
@@ -1311,7 +1311,7 @@ static int __init hss_init_module(void)
if ((ixp4xx_read_feature_bits() &
(IXP4XX_FEATURE_HDLC | IXP4XX_FEATURE_HSS)) !=
(IXP4XX_FEATURE_HDLC | IXP4XX_FEATURE_HSS))
- return -ENOSYS;
+ return -ENODEV;
spin_lock_init(&npe_lock);
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index c36d3a3d655f..d73475739127 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -6501,7 +6501,10 @@ static int airo_get_encode(struct net_device *dev,
/* Copy the key to the user buffer */
dwrq->length = get_wep_key(local, index, &buf[0], sizeof(buf));
- memcpy(extra, buf, dwrq->length);
+ if (dwrq->length != -1)
+ memcpy(extra, buf, dwrq->length);
+ else
+ dwrq->length = 0;
return 0;
}
@@ -6659,7 +6662,10 @@ static int airo_get_encodeext(struct net_device *dev,
/* Copy the key to the user buffer */
ext->key_len = get_wep_key(local, idx, &buf[0], sizeof(buf));
- memcpy(extra, buf, ext->key_len);
+ if (ext->key_len != -1)
+ memcpy(extra, buf, ext->key_len);
+ else
+ ext->key_len = 0;
return 0;
}
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 6789c5dfcc76..dbfe9f45050e 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -218,7 +218,7 @@ static struct pci_driver ath5k_pci_driver = {
* Prototypes - MAC 802.11 stack related functions
*/
static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
-static int ath5k_reset(struct ath5k_softc *sc, bool stop, bool change_channel);
+static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan);
static int ath5k_reset_wake(struct ath5k_softc *sc);
static int ath5k_start(struct ieee80211_hw *hw);
static void ath5k_stop(struct ieee80211_hw *hw);
@@ -1076,16 +1076,13 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
if (chan->center_freq != sc->curchan->center_freq ||
chan->hw_value != sc->curchan->hw_value) {
- sc->curchan = chan;
- sc->curband = &sc->sbands[chan->band];
-
/*
* To switch channels clear any pending DMA operations;
* wait long enough for the RX fifo to drain, reset the
* hardware at the new frequency, and then re-enable
* the relevant bits of the h/w.
*/
- return ath5k_reset(sc, true, true);
+ return ath5k_reset(sc, chan);
}
return 0;
@@ -2350,7 +2347,7 @@ ath5k_init(struct ath5k_softc *sc)
sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
AR5K_INT_FATAL | AR5K_INT_GLOBAL;
- ret = ath5k_reset(sc, false, false);
+ ret = ath5k_reset(sc, NULL);
if (ret)
goto done;
@@ -2635,18 +2632,25 @@ drop_packet:
return NETDEV_TX_OK;
}
+/*
+ * Reset the hardware. If chan is not NULL, then also pause rx/tx
+ * and change to the given channel.
+ */
static int
-ath5k_reset(struct ath5k_softc *sc, bool stop, bool change_channel)
+ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
{
struct ath5k_hw *ah = sc->ah;
int ret;
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
- if (stop) {
+ if (chan) {
ath5k_hw_set_imr(ah, 0);
ath5k_txq_cleanup(sc);
ath5k_rx_stop(sc);
+
+ sc->curchan = chan;
+ sc->curband = &sc->sbands[chan->band];
}
ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, true);
if (ret) {
@@ -2684,7 +2688,7 @@ ath5k_reset_wake(struct ath5k_softc *sc)
{
int ret;
- ret = ath5k_reset(sc, true, true);
+ ret = ath5k_reset(sc, sc->curchan);
if (!ret)
ieee80211_wake_queues(sc->hw);
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c
index 44fee5ae8925..a2fda702b620 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom.c
@@ -694,7 +694,7 @@ static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah,
#undef TMP_VAL_VPD_TABLE
}
-static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
+static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
struct ath9k_channel *chan,
int16_t *pTxPowerIndexOffset)
{
@@ -805,11 +805,9 @@ static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
}
*pTxPowerIndexOffset = 0;
-
- return true;
}
-static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
+static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
struct ath9k_channel *chan,
int16_t *ratesArray,
u16 cfgCtl,
@@ -1041,10 +1039,9 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
}
- return true;
}
-static int ath9k_hw_4k_set_txpower(struct ath_hw *ah,
+static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
struct ath9k_channel *chan,
u16 cfgCtl,
u8 twiceAntennaReduction,
@@ -1065,22 +1062,13 @@ static int ath9k_hw_4k_set_txpower(struct ath_hw *ah,
ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
}
- if (!ath9k_hw_set_4k_power_per_rate_table(ah, chan,
+ ath9k_hw_set_4k_power_per_rate_table(ah, chan,
&ratesArray[0], cfgCtl,
twiceAntennaReduction,
twiceMaxRegulatoryPower,
- powerLimit)) {
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "ath9k_hw_set_txpower: unable to set "
- "tx power per rate table\n");
- return -EIO;
- }
+ powerLimit);
- if (!ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset)) {
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "ath9k_hw_set_txpower: unable to set power table\n");
- return -EIO;
- }
+ ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset);
for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
@@ -1168,7 +1156,6 @@ static int ath9k_hw_4k_set_txpower(struct ath_hw *ah,
else
ah->regulatory.max_power_level = ratesArray[i];
- return 0;
}
static void ath9k_hw_4k_set_addac(struct ath_hw *ah,
@@ -2103,7 +2090,7 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah,
return;
}
-static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
+static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
struct ath9k_channel *chan,
int16_t *pTxPowerIndexOffset)
{
@@ -2255,13 +2242,11 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
}
*pTxPowerIndexOffset = 0;
-
- return true;
#undef SM_PD_GAIN
#undef SM_PDGAIN_B
}
-static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
+static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
struct ath9k_channel *chan,
int16_t *ratesArray,
u16 cfgCtl,
@@ -2549,10 +2534,9 @@ static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
targetPowerCckExt.tPow2x[0];
}
}
- return true;
}
-static int ath9k_hw_def_set_txpower(struct ath_hw *ah,
+static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
struct ath9k_channel *chan,
u16 cfgCtl,
u8 twiceAntennaReduction,
@@ -2575,22 +2559,13 @@ static int ath9k_hw_def_set_txpower(struct ath_hw *ah,
ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
}
- if (!ath9k_hw_set_def_power_per_rate_table(ah, chan,
+ ath9k_hw_set_def_power_per_rate_table(ah, chan,
&ratesArray[0], cfgCtl,
twiceAntennaReduction,
twiceMaxRegulatoryPower,
- powerLimit)) {
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "ath9k_hw_set_txpower: unable to set "
- "tx power per rate table\n");
- return -EIO;
- }
+ powerLimit);
- if (!ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset)) {
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "ath9k_hw_set_txpower: unable to set power table\n");
- return -EIO;
- }
+ ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset);
for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
@@ -2717,8 +2692,6 @@ static int ath9k_hw_def_set_txpower(struct ath_hw *ah,
"Invalid chainmask configuration\n");
break;
}
-
- return 0;
}
static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
index 7c59dc47f912..67b8bd12941a 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -494,7 +494,7 @@ struct eeprom_ops {
struct ath9k_channel *chan);
void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan);
void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
- int (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
+ void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
u16 cfgCtl, u8 twiceAntennaReduction,
u8 twiceMaxRegulatoryPower, u8 powerLimit);
u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 5879c731e9e7..4acfab514916 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1274,7 +1274,6 @@ static int ath9k_hw_process_ini(struct ath_hw *ah,
int i, regWrites = 0;
struct ieee80211_channel *channel = chan->chan;
u32 modesIndex, freqIndex;
- int status;
switch (chan->chanmode) {
case CHANNEL_A:
@@ -1376,17 +1375,12 @@ static int ath9k_hw_process_ini(struct ath_hw *ah,
if (OLC_FOR_AR9280_20_LATER)
ath9k_olc_init(ah);
- status = ah->eep_ops->set_txpower(ah, chan,
- ath9k_regd_get_ctl(&ah->regulatory, chan),
- channel->max_antenna_gain * 2,
- channel->max_power * 2,
- min((u32) MAX_RATE_POWER,
- (u32) ah->regulatory.power_limit));
- if (status != 0) {
- DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
- "Error initializing transmit power\n");
- return -EIO;
- }
+ ah->eep_ops->set_txpower(ah, chan,
+ ath9k_regd_get_ctl(&ah->regulatory, chan),
+ channel->max_antenna_gain * 2,
+ channel->max_power * 2,
+ min((u32) MAX_RATE_POWER,
+ (u32) ah->regulatory.power_limit));
if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
@@ -1617,11 +1611,9 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
switch (type) {
case ATH9K_RESET_POWER_ON:
return ath9k_hw_set_reset_power_on(ah);
- break;
case ATH9K_RESET_WARM:
case ATH9K_RESET_COLD:
return ath9k_hw_set_reset(ah, type);
- break;
default:
return false;
}
@@ -1703,11 +1695,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
ath9k_hw_set_regs(ah, chan, macmode);
if (AR_SREV_9280_10_OR_LATER(ah)) {
- if (!(ath9k_hw_ar9280_set_channel(ah, chan))) {
- DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
- "Failed to set channel\n");
- return false;
- }
+ ath9k_hw_ar9280_set_channel(ah, chan);
} else {
if (!(ath9k_hw_set_channel(ah, chan))) {
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
@@ -1716,16 +1704,12 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
}
}
- if (ah->eep_ops->set_txpower(ah, chan,
+ ah->eep_ops->set_txpower(ah, chan,
ath9k_regd_get_ctl(&ah->regulatory, chan),
channel->max_antenna_gain * 2,
channel->max_power * 2,
min((u32) MAX_RATE_POWER,
- (u32) ah->regulatory.power_limit)) != 0) {
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "Error initializing transmit power\n");
- return false;
- }
+ (u32) ah->regulatory.power_limit));
synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
if (IS_CHAN_B(chan))
@@ -2313,13 +2297,11 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
- if (AR_SREV_9280_10_OR_LATER(ah)) {
- if (!(ath9k_hw_ar9280_set_channel(ah, chan)))
- return -EIO;
- } else {
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ ath9k_hw_ar9280_set_channel(ah, chan);
+ else
if (!(ath9k_hw_set_channel(ah, chan)))
return -EIO;
- }
for (i = 0; i < AR_NUM_DCU; i++)
REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
@@ -3750,22 +3732,19 @@ bool ath9k_hw_disable(struct ath_hw *ah)
return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD);
}
-bool ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
+void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
{
struct ath9k_channel *chan = ah->curchan;
struct ieee80211_channel *channel = chan->chan;
ah->regulatory.power_limit = min(limit, (u32) MAX_RATE_POWER);
- if (ah->eep_ops->set_txpower(ah, chan,
- ath9k_regd_get_ctl(&ah->regulatory, chan),
- channel->max_antenna_gain * 2,
- channel->max_power * 2,
- min((u32) MAX_RATE_POWER,
- (u32) ah->regulatory.power_limit)) != 0)
- return false;
-
- return true;
+ ah->eep_ops->set_txpower(ah, chan,
+ ath9k_regd_get_ctl(&ah->regulatory, chan),
+ channel->max_antenna_gain * 2,
+ channel->max_power * 2,
+ min((u32) MAX_RATE_POWER,
+ (u32) ah->regulatory.power_limit));
}
void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac)
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index ddb24c47ebcf..dd8508ef6e05 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -590,7 +590,7 @@ u32 ath9k_hw_getrxfilter(struct ath_hw *ah);
void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits);
bool ath9k_hw_phy_disable(struct ath_hw *ah);
bool ath9k_hw_disable(struct ath_hw *ah);
-bool ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit);
+void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit);
void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac);
void ath9k_hw_setopmode(struct ath_hw *ah);
void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index bbbfdcde2727..175ed5358baf 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1257,6 +1257,7 @@ static int ath_init_sw_rfkill(struct ath_softc *sc)
sc->rf_kill.rfkill->data = sc;
sc->rf_kill.rfkill->toggle_radio = ath_sw_toggle_radio;
sc->rf_kill.rfkill->state = RFKILL_STATE_UNBLOCKED;
+ sc->rf_kill.rfkill->user_claim_unsupported = 1;
return 0;
}
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 6dbc58580abb..168411d322a2 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -93,14 +93,14 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (pci_enable_device(pdev))
return -EIO;
- ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (ret) {
printk(KERN_ERR "ath9k: 32-bit DMA not available\n");
goto bad;
}
- ret = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
if (ret) {
printk(KERN_ERR "ath9k: 32-bit DMA consistent "
diff --git a/drivers/net/wireless/ath/ath9k/phy.c b/drivers/net/wireless/ath/ath9k/phy.c
index 5ec9ce91d979..aaa941561c36 100644
--- a/drivers/net/wireless/ath/ath9k/phy.c
+++ b/drivers/net/wireless/ath/ath9k/phy.c
@@ -96,9 +96,8 @@ ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
return true;
}
-bool
-ath9k_hw_ar9280_set_channel(struct ath_hw *ah,
- struct ath9k_channel *chan)
+void ath9k_hw_ar9280_set_channel(struct ath_hw *ah,
+ struct ath9k_channel *chan)
{
u16 bMode, fracMode, aModeRefSel = 0;
u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0;
@@ -169,8 +168,6 @@ ath9k_hw_ar9280_set_channel(struct ath_hw *ah,
ah->curchan = chan;
ah->curchan_rad_index = -1;
-
- return true;
}
static void
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h
index 296d0e985f25..c70f530642f6 100644
--- a/drivers/net/wireless/ath/ath9k/phy.h
+++ b/drivers/net/wireless/ath/ath9k/phy.h
@@ -17,7 +17,7 @@
#ifndef PHY_H
#define PHY_H
-bool ath9k_hw_ar9280_set_channel(struct ath_hw *ah,
+void ath9k_hw_ar9280_set_channel(struct ath_hw *ah,
struct ath9k_channel
*chan);
bool ath9k_hw_set_channel(struct ath_hw *ah,
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c
index 9e1d00bc24d3..afad42358693 100644
--- a/drivers/net/wireless/b43/rfkill.c
+++ b/drivers/net/wireless/b43/rfkill.c
@@ -139,6 +139,7 @@ void b43_rfkill_init(struct b43_wldev *dev)
rfk->rfkill->state = RFKILL_STATE_UNBLOCKED;
rfk->rfkill->data = dev;
rfk->rfkill->toggle_radio = b43_rfkill_soft_toggle;
+ rfk->rfkill->user_claim_unsupported = 1;
rfk->poll_dev = input_allocate_polled_device();
if (!rfk->poll_dev) {
diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c
index 4b0c7d27a51f..b32bf6a94f19 100644
--- a/drivers/net/wireless/b43legacy/rfkill.c
+++ b/drivers/net/wireless/b43legacy/rfkill.c
@@ -142,6 +142,7 @@ void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
rfk->rfkill->state = RFKILL_STATE_UNBLOCKED;
rfk->rfkill->data = dev;
rfk->rfkill->toggle_radio = b43legacy_rfkill_soft_toggle;
+ rfk->rfkill->user_claim_unsupported = 1;
rfk->poll_dev = input_allocate_polled_device();
if (!rfk->poll_dev) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 41f1d66cfeba..5b0c6e5bda92 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -1110,6 +1110,11 @@ static void iwl3945_nic_config(struct iwl_priv *priv)
spin_lock_irqsave(&priv->lock, flags);
+ /* Determine HW type */
+ pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id);
+
+ IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id);
+
if (rev_id & PCI_CFG_REV_ID_BIT_RTP)
IWL_DEBUG_INFO(priv, "RTP type \n");
else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) {
@@ -1163,7 +1168,6 @@ static void iwl3945_nic_config(struct iwl_priv *priv)
int iwl3945_hw_nic_init(struct iwl_priv *priv)
{
- u8 rev_id;
int rc;
unsigned long flags;
struct iwl_rx_queue *rxq = &priv->rxq;
@@ -1172,12 +1176,6 @@ int iwl3945_hw_nic_init(struct iwl_priv *priv)
priv->cfg->ops->lib->apm_ops.init(priv);
spin_unlock_irqrestore(&priv->lock, flags);
- /* Determine HW type */
- rc = pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id);
- if (rc)
- return rc;
- IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id);
-
rc = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN);
if (rc)
return rc;
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index ee271d7f6120..7236382aeaa6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -102,8 +102,8 @@ struct iwl_cfg iwl6000_2agn_cfg = {
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params,
- .valid_tx_ant = ANT_BC,
- .valid_rx_ant = ANT_BC,
+ .valid_tx_ant = ANT_AB,
+ .valid_rx_ant = ANT_AB,
.need_pll_cfg = false,
};
@@ -118,8 +118,8 @@ struct iwl_cfg iwl6050_2agn_cfg = {
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params,
- .valid_tx_ant = ANT_BC,
- .valid_rx_ant = ANT_BC,
+ .valid_tx_ant = ANT_AB,
+ .valid_rx_ant = ANT_AB,
.need_pll_cfg = false,
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 0a71bb55d0ee..4c88e8715df2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -100,6 +100,7 @@ struct iwl_scale_tbl_info {
u8 is_fat; /* 1 = 40 MHz channel width */
u8 is_dup; /* 1 = duplicated data streams */
u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */
+ u8 max_search; /* maximun number of tables we can search */
s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */
u32 current_rate; /* rate_n_flags, uCode API format */
struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */
@@ -160,6 +161,7 @@ struct iwl_lq_sta {
#ifdef CONFIG_MAC80211_DEBUGFS
struct dentry *rs_sta_dbgfs_scale_table_file;
struct dentry *rs_sta_dbgfs_stats_table_file;
+ struct dentry *rs_sta_dbgfs_rate_scale_data_file;
struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file;
u32 dbg_fixed_rate;
#endif
@@ -579,6 +581,7 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags,
tbl->is_dup = 0;
tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS);
tbl->lq_type = LQ_NONE;
+ tbl->max_search = IWL_MAX_SEARCH;
/* legacy rate format */
if (!(rate_n_flags & RATE_MCS_HT_MSK)) {
@@ -612,8 +615,10 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags,
tbl->lq_type = LQ_MIMO2;
/* MIMO3 */
} else {
- if (num_of_ant == 3)
+ if (num_of_ant == 3) {
+ tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH;
tbl->lq_type = LQ_MIMO3;
+ }
}
}
return 0;
@@ -771,6 +776,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta,
tbl->is_fat = 0;
tbl->is_SGI = 0;
+ tbl->max_search = IWL_MAX_SEARCH;
}
rate_mask = rs_get_supported_rates(lq_sta, NULL, tbl->lq_type);
@@ -1026,6 +1032,7 @@ static void rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy,
lq_sta->total_failed = 0;
lq_sta->total_success = 0;
lq_sta->flush_timer = jiffies;
+ lq_sta->action_counter = 0;
}
/*
@@ -1205,6 +1212,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
tbl->lq_type = LQ_MIMO2;
tbl->is_dup = lq_sta->is_dup;
tbl->action = 0;
+ tbl->max_search = IWL_MAX_SEARCH;
rate_mask = lq_sta->active_mimo2_rate;
if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap))
@@ -1270,6 +1278,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv,
tbl->lq_type = LQ_MIMO3;
tbl->is_dup = lq_sta->is_dup;
tbl->action = 0;
+ tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH;
rate_mask = lq_sta->active_mimo3_rate;
if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap))
@@ -1328,6 +1337,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
tbl->is_dup = lq_sta->is_dup;
tbl->lq_type = LQ_SISO;
tbl->action = 0;
+ tbl->max_search = IWL_MAX_SEARCH;
rate_mask = lq_sta->active_siso_rate;
if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap))
@@ -1384,15 +1394,15 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
u8 tx_chains_num = priv->hw_params.tx_chains_num;
int ret = 0;
+ u8 update_search_tbl_counter = 0;
for (; ;) {
+ lq_sta->action_counter++;
switch (tbl->action) {
case IWL_LEGACY_SWITCH_ANTENNA1:
case IWL_LEGACY_SWITCH_ANTENNA2:
IWL_DEBUG_RATE(priv, "LQ: Legacy toggle Antenna\n");
- lq_sta->action_counter++;
-
if ((tbl->action == IWL_LEGACY_SWITCH_ANTENNA1 &&
tx_chains_num <= 1) ||
(tbl->action == IWL_LEGACY_SWITCH_ANTENNA2 &&
@@ -1408,6 +1418,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
if (rs_toggle_antenna(valid_tx_ant,
&search_tbl->current_rate, search_tbl)) {
+ update_search_tbl_counter = 1;
rs_set_expected_tpt_table(lq_sta, search_tbl);
goto out;
}
@@ -1489,6 +1500,8 @@ out:
tbl->action++;
if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC)
tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
+ if (update_search_tbl_counter)
+ search_tbl->action = tbl->action;
return 0;
}
@@ -1511,6 +1524,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
u8 start_action = tbl->action;
u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
u8 tx_chains_num = priv->hw_params.tx_chains_num;
+ u8 update_search_tbl_counter = 0;
int ret;
for (;;) {
@@ -1531,8 +1545,10 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
memcpy(search_tbl, tbl, sz);
if (rs_toggle_antenna(valid_tx_ant,
- &search_tbl->current_rate, search_tbl))
+ &search_tbl->current_rate, search_tbl)) {
+ update_search_tbl_counter = 1;
goto out;
+ }
break;
case IWL_SISO_SWITCH_MIMO2_AB:
case IWL_SISO_SWITCH_MIMO2_AC:
@@ -1586,6 +1602,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
search_tbl->current_rate =
rate_n_flags_from_tbl(priv, search_tbl,
index, is_green);
+ update_search_tbl_counter = 1;
goto out;
case IWL_SISO_SWITCH_MIMO3_ABC:
IWL_DEBUG_RATE(priv, "LQ: SISO switch to MIMO3\n");
@@ -1617,6 +1634,9 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
tbl->action++;
if (tbl->action > IWL_SISO_SWITCH_MIMO3_ABC)
tbl->action = IWL_SISO_SWITCH_ANTENNA1;
+ if (update_search_tbl_counter)
+ search_tbl->action = tbl->action;
+
return 0;
}
@@ -1638,6 +1658,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
u8 start_action = tbl->action;
u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
u8 tx_chains_num = priv->hw_params.tx_chains_num;
+ u8 update_search_tbl_counter = 0;
int ret;
for (;;) {
@@ -1655,8 +1676,10 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
memcpy(search_tbl, tbl, sz);
if (rs_toggle_antenna(valid_tx_ant,
- &search_tbl->current_rate, search_tbl))
+ &search_tbl->current_rate, search_tbl)) {
+ update_search_tbl_counter = 1;
goto out;
+ }
break;
case IWL_MIMO2_SWITCH_SISO_A:
case IWL_MIMO2_SWITCH_SISO_B:
@@ -1713,6 +1736,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
search_tbl->current_rate =
rate_n_flags_from_tbl(priv, search_tbl,
index, is_green);
+ update_search_tbl_counter = 1;
goto out;
case IWL_MIMO2_SWITCH_MIMO3_ABC:
@@ -1745,6 +1769,9 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
tbl->action++;
if (tbl->action > IWL_MIMO2_SWITCH_MIMO3_ABC)
tbl->action = IWL_MIMO2_SWITCH_ANTENNA1;
+ if (update_search_tbl_counter)
+ search_tbl->action = tbl->action;
+
return 0;
}
@@ -1768,6 +1795,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
u8 tx_chains_num = priv->hw_params.tx_chains_num;
int ret;
+ u8 update_search_tbl_counter = 0;
for (;;) {
lq_sta->action_counter++;
@@ -1866,6 +1894,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
search_tbl->current_rate =
rate_n_flags_from_tbl(priv, search_tbl,
index, is_green);
+ update_search_tbl_counter = 1;
goto out;
}
tbl->action++;
@@ -1882,6 +1911,9 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
tbl->action++;
if (tbl->action > IWL_MIMO3_SWITCH_GI)
tbl->action = IWL_MIMO3_SWITCH_ANTENNA1;
+ if (update_search_tbl_counter)
+ search_tbl->action = tbl->action;
+
return 0;
}
@@ -2326,8 +2358,7 @@ lq_update:
* before next round of mode comparisons. */
tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]);
if (is_legacy(tbl1->lq_type) && !conf_is_ht(conf) &&
- lq_sta->action_counter >= 1) {
- lq_sta->action_counter = 0;
+ lq_sta->action_counter > tbl1->max_search) {
IWL_DEBUG_RATE(priv, "LQ: STAY in legacy table\n");
rs_set_stay_in_table(priv, 1, lq_sta);
}
@@ -2336,7 +2367,7 @@ lq_update:
* have been tried and compared, stay in this best modulation
* mode for a while before next round of mode comparisons. */
if (lq_sta->enable_counter &&
- (lq_sta->action_counter >= IWL_ACTION_LIMIT)) {
+ (lq_sta->action_counter >= tbl1->max_search)) {
if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) &&
(lq_sta->tx_agg_tid_en & (1 << tid)) &&
(tid != MAX_TID_COUNT)) {
@@ -2350,7 +2381,6 @@ lq_update:
lq_sta, sta);
}
}
- lq_sta->action_counter = 0;
rs_set_stay_in_table(priv, 0, lq_sta);
}
}
@@ -2955,6 +2985,43 @@ static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
.open = open_file_generic,
};
+static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file,
+ char __user *user_buf, size_t count, loff_t *ppos)
+{
+ char buff[120];
+ int desc = 0;
+ ssize_t ret;
+
+ struct iwl_lq_sta *lq_sta = file->private_data;
+ struct iwl_priv *priv;
+ struct iwl_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl];
+
+ priv = lq_sta->drv;
+
+ if (is_Ht(tbl->lq_type))
+ desc += sprintf(buff+desc,
+ "Bit Rate= %d Mb/s\n",
+ tbl->expected_tpt[lq_sta->last_txrate_idx]);
+ else
+ desc += sprintf(buff+desc,
+ "Bit Rate= %d Mb/s\n",
+ iwl_rates[lq_sta->last_txrate_idx].ieee >> 1);
+ desc += sprintf(buff+desc,
+ "Signal Level= %d dBm\tNoise Level= %d dBm\n",
+ priv->last_rx_rssi, priv->last_rx_noise);
+ desc += sprintf(buff+desc,
+ "Tsf= 0x%llx\tBeacon time= 0x%08X\n",
+ priv->last_tsf, priv->last_beacon_time);
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
+ return ret;
+}
+
+static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = {
+ .read = rs_sta_dbgfs_rate_scale_data_read,
+ .open = open_file_generic,
+};
+
static void rs_add_debugfs(void *priv, void *priv_sta,
struct dentry *dir)
{
@@ -2965,6 +3032,9 @@ static void rs_add_debugfs(void *priv, void *priv_sta,
lq_sta->rs_sta_dbgfs_stats_table_file =
debugfs_create_file("rate_stats_table", 0600, dir,
lq_sta, &rs_sta_dbgfs_stats_table_ops);
+ lq_sta->rs_sta_dbgfs_rate_scale_data_file =
+ debugfs_create_file("rate_scale_data", 0600, dir,
+ lq_sta, &rs_sta_dbgfs_rate_scale_data_ops);
lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file =
debugfs_create_u8("tx_agg_tid_enable", 0600, dir,
&lq_sta->tx_agg_tid_en);
@@ -2976,6 +3046,7 @@ static void rs_remove_debugfs(void *priv, void *priv_sta)
struct iwl_lq_sta *lq_sta = priv_sta;
debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file);
debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
+ debugfs_remove(lq_sta->rs_sta_dbgfs_rate_scale_data_file);
debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file);
}
#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
index f875136bc5dc..25050bf315a2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
@@ -275,6 +275,8 @@ enum {
#define IWL_MIMO3_SWITCH_GI 8
+#define IWL_MAX_11N_MIMO3_SEARCH IWL_MIMO3_SWITCH_GI
+#define IWL_MAX_SEARCH IWL_MIMO2_SWITCH_MIMO3_ABC
/*FIXME:RS:add possible actions for MIMO3*/
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 6cdee0b4b486..596977d71c94 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -190,8 +190,7 @@ int iwl_commit_rxon(struct iwl_priv *priv)
priv->cfg->ops->smgmt->clear_station_table(priv);
- if (!priv->error_recovering)
- priv->start_calib = 0;
+ priv->start_calib = 0;
/* Add the broadcast address so we can send broadcast frames */
if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) ==
@@ -967,23 +966,6 @@ static inline void iwl_synchronize_irq(struct iwl_priv *priv)
tasklet_kill(&priv->irq_tasklet);
}
-static void iwl_error_recovery(struct iwl_priv *priv)
-{
- unsigned long flags;
-
- memcpy(&priv->staging_rxon, &priv->recovery_rxon,
- sizeof(priv->staging_rxon));
- priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwlcore_commit_rxon(priv);
-
- iwl_rxon_add_station(priv, priv->bssid, 1);
-
- spin_lock_irqsave(&priv->lock, flags);
- priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id);
- priv->error_recovering = 0;
- spin_unlock_irqrestore(&priv->lock, flags);
-}
-
static void iwl_irq_tasklet(struct iwl_priv *priv)
{
u32 inta, handled = 0;
@@ -1514,9 +1496,6 @@ static void iwl_alive_start(struct iwl_priv *priv)
set_bit(STATUS_READY, &priv->status);
wake_up_interruptible(&priv->wait_command_queue);
- if (priv->error_recovering)
- iwl_error_recovery(priv);
-
iwl_power_update_mode(priv, 1);
/* reassociate for ADHOC mode */
@@ -1715,9 +1694,6 @@ static int __iwl_up(struct iwl_priv *priv)
continue;
}
- /* Clear out the uCode error bit if it is set */
- clear_bit(STATUS_FW_ERROR, &priv->status);
-
/* start card; "initialize" will load runtime ucode */
iwl_nic_start(priv);
@@ -1812,8 +1788,17 @@ static void iwl_bg_restart(struct work_struct *data)
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- iwl_down(priv);
- queue_work(priv->workqueue, &priv->up);
+ if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
+ mutex_lock(&priv->mutex);
+ priv->vif = NULL;
+ priv->is_open = 0;
+ mutex_unlock(&priv->mutex);
+ iwl_down(priv);
+ ieee80211_restart_hw(priv->hw);
+ } else {
+ iwl_down(priv);
+ queue_work(priv->workqueue, &priv->up);
+ }
}
static void iwl_bg_rx_replenish(struct work_struct *data)
@@ -1853,7 +1838,6 @@ void iwl_post_associate(struct iwl_priv *priv)
if (!priv->vif || !priv->is_open)
return;
- iwl_power_cancel_timeout(priv);
iwl_scan_cancel_timeout(priv, 200);
conf = ieee80211_get_hw_conf(priv->hw);
@@ -1929,7 +1913,7 @@ void iwl_post_associate(struct iwl_priv *priv)
* If chain noise has already been run, then we need to enable
* power management here */
if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
- iwl_power_enable_management(priv);
+ iwl_power_update_mode(priv, 0);
/* Enable Rx differential gain and sensitivity calibrations */
iwl_chain_noise_reset(priv);
@@ -2007,10 +1991,8 @@ static void iwl_mac_stop(struct ieee80211_hw *hw)
IWL_DEBUG_MAC80211(priv, "enter\n");
- if (!priv->is_open) {
- IWL_DEBUG_MAC80211(priv, "leave - skip\n");
+ if (!priv->is_open)
return;
- }
priv->is_open = 0;
@@ -2482,32 +2464,37 @@ static ssize_t show_power_level(struct device *d,
{
struct iwl_priv *priv = dev_get_drvdata(d);
int mode = priv->power_data.user_power_setting;
- int system = priv->power_data.system_power_setting;
int level = priv->power_data.power_mode;
char *p = buf;
- switch (system) {
- case IWL_POWER_SYS_AUTO:
- p += sprintf(p, "SYSTEM:auto");
- break;
- case IWL_POWER_SYS_AC:
- p += sprintf(p, "SYSTEM:ac");
- break;
- case IWL_POWER_SYS_BATTERY:
- p += sprintf(p, "SYSTEM:battery");
- break;
- }
-
- p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO) ?
- "fixed" : "auto");
- p += sprintf(p, "\tINDEX:%d", level);
- p += sprintf(p, "\n");
+ p += sprintf(p, "INDEX:%d\t", level);
+ p += sprintf(p, "USER:%d\n", mode);
return p - buf + 1;
}
static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
store_power_level);
+static ssize_t show_qos(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ char *p = buf;
+ int q;
+
+ for (q = 0; q < AC_NUM; q++) {
+ p += sprintf(p, "\tcw_min\tcw_max\taifsn\ttxop\n");
+ p += sprintf(p, "AC[%d]\t%u\t%u\t%u\t%u\n", q,
+ priv->qos_data.def_qos_parm.ac[q].cw_min,
+ priv->qos_data.def_qos_parm.ac[q].cw_max,
+ priv->qos_data.def_qos_parm.ac[q].aifsn,
+ priv->qos_data.def_qos_parm.ac[q].edca_txop);
+ }
+
+ return p - buf + 1;
+}
+
+static DEVICE_ATTR(qos, S_IRUGO, show_qos, NULL);
static ssize_t show_statistics(struct device *d,
struct device_attribute *attr, char *buf)
@@ -2570,7 +2557,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
iwl_setup_scan_deferred_work(priv);
- iwl_setup_power_deferred_work(priv);
if (priv->cfg->ops->lib->setup_deferred_work)
priv->cfg->ops->lib->setup_deferred_work(priv);
@@ -2590,7 +2576,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
cancel_delayed_work_sync(&priv->init_alive_start);
cancel_delayed_work(&priv->scan_check);
- cancel_delayed_work_sync(&priv->set_power_save);
cancel_delayed_work(&priv->alive_start);
cancel_work_sync(&priv->beacon_update);
del_timer_sync(&priv->statistics_periodic);
@@ -2607,7 +2592,7 @@ static struct attribute *iwl_sysfs_entries[] = {
&dev_attr_debug_level.attr,
#endif
&dev_attr_version.attr,
-
+ &dev_attr_qos.attr,
NULL
};
@@ -2959,7 +2944,9 @@ static struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x0085, 0x1112, iwl6000_2ag_cfg)},
{IWL_PCI_DEVICE(0x0082, 0x1122, iwl6000_2ag_cfg)},
{IWL_PCI_DEVICE(0x422B, PCI_ANY_ID, iwl6000_3agn_cfg)},
+ {IWL_PCI_DEVICE(0x422C, PCI_ANY_ID, iwl6000_2agn_cfg)},
{IWL_PCI_DEVICE(0x4238, PCI_ANY_ID, iwl6000_3agn_cfg)},
+ {IWL_PCI_DEVICE(0x4239, PCI_ANY_ID, iwl6000_2agn_cfg)},
{IWL_PCI_DEVICE(0x0082, PCI_ANY_ID, iwl6000_2agn_cfg)},
{IWL_PCI_DEVICE(0x0085, PCI_ANY_ID, iwl6000_3agn_cfg)},
{IWL_PCI_DEVICE(0x0086, PCI_ANY_ID, iwl6050_3agn_cfg)},
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c
index 735f3f19928c..a5d63672ad39 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.c
@@ -857,7 +857,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
priv->cfg->ops->lib->update_chain_flags(priv);
data->state = IWL_CHAIN_NOISE_DONE;
- iwl_power_enable_management(priv);
+ iwl_power_update_mode(priv, 0);
}
EXPORT_SYMBOL(iwl_chain_noise_calibration);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 1366222bb50a..5393fb3f452c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -273,6 +273,14 @@ void iwl_activate_qos(struct iwl_priv *priv, u8 force)
}
EXPORT_SYMBOL(iwl_activate_qos);
+/*
+ * AC CWmin CW max AIFSN TXOP Limit TXOP Limit
+ * (802.11b) (802.11a/g)
+ * AC_BK 15 1023 7 0 0
+ * AC_BE 15 1023 3 0 0
+ * AC_VI 7 15 2 6.016ms 3.008ms
+ * AC_VO 3 7 2 3.264ms 1.504ms
+ */
void iwl_reset_qos(struct iwl_priv *priv)
{
u16 cw_min = 15;
@@ -304,6 +312,7 @@ void iwl_reset_qos(struct iwl_priv *priv)
if (priv->qos_data.qos_active)
aifs = 3;
+ /* AC_BE */
priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min);
priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max);
priv->qos_data.def_qos_parm.ac[0].aifsn = aifs;
@@ -311,6 +320,7 @@ void iwl_reset_qos(struct iwl_priv *priv)
priv->qos_data.def_qos_parm.ac[0].reserved1 = 0;
if (priv->qos_data.qos_active) {
+ /* AC_BK */
i = 1;
priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min);
priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max);
@@ -318,11 +328,12 @@ void iwl_reset_qos(struct iwl_priv *priv)
priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
+ /* AC_VI */
i = 2;
priv->qos_data.def_qos_parm.ac[i].cw_min =
cpu_to_le16((cw_min + 1) / 2 - 1);
priv->qos_data.def_qos_parm.ac[i].cw_max =
- cpu_to_le16(cw_max);
+ cpu_to_le16(cw_min);
priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
if (is_legacy)
priv->qos_data.def_qos_parm.ac[i].edca_txop =
@@ -332,11 +343,12 @@ void iwl_reset_qos(struct iwl_priv *priv)
cpu_to_le16(3008);
priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
+ /* AC_VO */
i = 3;
priv->qos_data.def_qos_parm.ac[i].cw_min =
cpu_to_le16((cw_min + 1) / 4 - 1);
priv->qos_data.def_qos_parm.ac[i].cw_max =
- cpu_to_le16((cw_max + 1) / 2 - 1);
+ cpu_to_le16((cw_min + 1) / 2 - 1);
priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
if (is_legacy)
@@ -960,10 +972,10 @@ void iwl_set_rxon_chain(struct iwl_priv *priv)
if (iwl_is_monitor_mode(priv) &&
!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) &&
((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)) {
- rx_chain = 0x07 << RXON_RX_CHAIN_VALID_POS;
- rx_chain |= 0x06 << RXON_RX_CHAIN_FORCE_SEL_POS;
- rx_chain |= 0x07 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
- rx_chain |= 0x01 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
+ rx_chain = ANT_ABC << RXON_RX_CHAIN_VALID_POS;
+ rx_chain |= ANT_BC << RXON_RX_CHAIN_FORCE_SEL_POS;
+ rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
+ rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
}
priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain);
@@ -1120,7 +1132,7 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode)
}
EXPORT_SYMBOL(iwl_connection_init_rx_config);
-void iwl_set_rate(struct iwl_priv *priv)
+static void iwl_set_rate(struct iwl_priv *priv)
{
const struct ieee80211_supported_band *hw = NULL;
struct ieee80211_rate *rate;
@@ -1166,7 +1178,6 @@ void iwl_set_rate(struct iwl_priv *priv)
priv->staging_rxon.ofdm_basic_rates =
(IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
}
-EXPORT_SYMBOL(iwl_set_rate);
void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
{
@@ -1230,11 +1241,6 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
IWL_DEBUG(priv, IWL_DL_FW_ERRORS,
"Restarting adapter due to uCode error.\n");
- if (iwl_is_associated(priv)) {
- memcpy(&priv->recovery_rxon, &priv->active_rxon,
- sizeof(priv->recovery_rxon));
- priv->error_recovering = 1;
- }
if (priv->cfg->mod_params->restart_fw)
queue_work(priv->workqueue, &priv->restart);
}
@@ -1358,7 +1364,6 @@ int iwl_init_drv(struct iwl_priv *priv)
priv->ibss_beacon = NULL;
spin_lock_init(&priv->lock);
- spin_lock_init(&priv->power_data.lock);
spin_lock_init(&priv->sta_lock);
spin_lock_init(&priv->hcmd_lock);
@@ -2226,9 +2231,9 @@ static void iwl_ht_conf(struct iwl_priv *priv,
iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0;
iwl_conf->ht_protection =
- bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
+ bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
iwl_conf->non_GF_STA_present =
- !!(bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
+ !!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
rcu_read_unlock();
@@ -2582,14 +2587,13 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
iwl_set_rate(priv);
}
- if (changed & IEEE80211_CONF_CHANGE_PS) {
- if (conf->flags & IEEE80211_CONF_PS)
- ret = iwl_power_set_user_mode(priv, IWL_POWER_INDEX_3);
- else
- ret = iwl_power_set_user_mode(priv, IWL_POWER_MODE_CAM);
+ if (changed & IEEE80211_CONF_CHANGE_PS &&
+ priv->iw_mode == NL80211_IFTYPE_STATION) {
+ priv->power_data.power_disabled =
+ !(conf->flags & IEEE80211_CONF_PS);
+ ret = iwl_power_update_mode(priv, 0);
if (ret)
IWL_DEBUG_MAC80211(priv, "Error setting power level\n");
-
}
if (changed & IEEE80211_CONF_CHANGE_POWER) {
@@ -2725,21 +2729,7 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
iwlcore_commit_rxon(priv);
}
- iwl_power_update_mode(priv, 0);
-
- /* Per mac80211.h: This is only used in IBSS mode... */
if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
-
- /* switch to CAM during association period.
- * the ucode will block any association/authentication
- * frome during assiciation period if it can not hear
- * the AP because of PM. the timer enable PM back is
- * association do not complete
- */
- if (priv->hw->conf.channel->flags &
- (IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_RADAR))
- iwl_power_disable_management(priv, 3000);
-
IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n");
mutex_unlock(&priv->mutex);
return;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index bd7f9d9616bc..f3544ea559a2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -363,8 +363,6 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags);
u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv);
-void iwl_set_rate(struct iwl_priv *priv);
-
u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx);
static inline u32 iwl_ant_idx_to_flags(u8 ant_idx)
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 5aa76a706320..3049ba25c3fc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -933,7 +933,6 @@ struct iwl_priv {
const struct iwl_rxon_cmd active_rxon;
struct iwl_rxon_cmd staging_rxon;
- int error_recovering;
struct iwl_rxon_cmd recovery_rxon;
/* 1st responses from initialize and runtime uCode images.
@@ -1076,7 +1075,6 @@ struct iwl_priv {
struct tasklet_struct irq_tasklet;
- struct delayed_work set_power_save;
struct delayed_work init_alive_start;
struct delayed_work alive_start;
struct delayed_work scan_check;
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 75517d05df08..401438aec19c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -285,7 +285,7 @@ int iwl_eeprom_check_version(struct iwl_priv *priv)
return 0;
err:
- IWL_ERR(priv, "Unsupported EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n",
+ IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n",
eeprom_ver, priv->cfg->eeprom_ver,
calib_ver, priv->cfg->eeprom_calib_ver);
return -EINVAL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index 47c894530eb5..f2ea3f05f6e1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -41,38 +41,33 @@
#include "iwl-power.h"
/*
- * Setting power level allow the card to go to sleep when not busy
- * there are three factor that decide the power level to go to, they
- * are list here with its priority
- * 1- critical_power_setting this will be set according to card temperature.
- * 2- system_power_setting this will be set by system PM manager.
- * 3- user_power_setting this will be set by user either by writing to sys or
- * mac80211
+ * Setting power level allow the card to go to sleep when not busy.
*
- * if system_power_setting and user_power_setting is set to auto
- * the power level will be decided according to association status and battery
- * status.
+ * The power level is set to INDEX_1 (the least deep state) by
+ * default, and will, in the future, be the deepest state unless
+ * otherwise required by pm_qos network latency requirements.
*
+ * Using INDEX_1 without pm_qos is ok because mac80211 will disable
+ * PS when even checking every beacon for the TIM bit would exceed
+ * the required latency.
*/
-#define MSEC_TO_USEC 1024
#define IWL_POWER_RANGE_0_MAX (2)
#define IWL_POWER_RANGE_1_MAX (10)
-
-#define IWL_POWER_ON_BATTERY IWL_POWER_INDEX_5
-#define IWL_POWER_ON_AC_DISASSOC IWL_POWER_MODE_CAM
-#define IWL_POWER_ON_AC_ASSOC IWL_POWER_MODE_CAM
-
-
-#define IWL_CT_KILL_TEMPERATURE 110
-#define IWL_MIN_POWER_TEMPERATURE 100
-#define IWL_REDUCED_POWER_TEMPERATURE 95
-
+#define NOSLP cpu_to_le16(0), 0, 0
+#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0
+#define TU_TO_USEC 1024
+#define SLP_TOUT(T) cpu_to_le32((T) * TU_TO_USEC)
+#define SLP_VEC(X0, X1, X2, X3, X4) {cpu_to_le32(X0), \
+ cpu_to_le32(X1), \
+ cpu_to_le32(X2), \
+ cpu_to_le32(X3), \
+ cpu_to_le32(X4)}
/* default power management (not Tx power) table values */
-/* for TIM 0-10 */
-static struct iwl_power_vec_entry range_0[IWL_POWER_MAX] = {
+/* for DTIM period 0 through IWL_POWER_RANGE_0_MAX */
+static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = {
{{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
@@ -82,8 +77,8 @@ static struct iwl_power_vec_entry range_0[IWL_POWER_MAX] = {
};
-/* for TIM = 3-10 */
-static struct iwl_power_vec_entry range_1[IWL_POWER_MAX] = {
+/* for DTIM period IWL_POWER_RANGE_0_MAX + 1 through IWL_POWER_RANGE_1_MAX */
+static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = {
{{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0},
@@ -92,8 +87,8 @@ static struct iwl_power_vec_entry range_1[IWL_POWER_MAX] = {
{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2}
};
-/* for TIM > 11 */
-static struct iwl_power_vec_entry range_2[IWL_POWER_MAX] = {
+/* for DTIM period > IWL_POWER_RANGE_1_MAX */
+static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
{{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0},
@@ -106,39 +101,15 @@ static struct iwl_power_vec_entry range_2[IWL_POWER_MAX] = {
/* set card power command */
static int iwl_set_power(struct iwl_priv *priv, void *cmd)
{
- return iwl_send_cmd_pdu_async(priv, POWER_TABLE_CMD,
- sizeof(struct iwl_powertable_cmd),
- cmd, NULL);
-}
-/* decide the right power level according to association status
- * and battery status
- */
-static u16 iwl_get_auto_power_mode(struct iwl_priv *priv)
-{
- u16 mode;
-
- switch (priv->power_data.user_power_setting) {
- case IWL_POWER_AUTO:
- /* if running on battery */
- if (priv->power_data.is_battery_active)
- mode = IWL_POWER_ON_BATTERY;
- else if (iwl_is_associated(priv))
- mode = IWL_POWER_ON_AC_ASSOC;
- else
- mode = IWL_POWER_ON_AC_DISASSOC;
- break;
- default:
- mode = priv->power_data.user_power_setting;
- break;
- }
- return mode;
+ return iwl_send_cmd_pdu(priv, POWER_TABLE_CMD,
+ sizeof(struct iwl_powertable_cmd), cmd);
}
/* initialize to default */
static void iwl_power_init_handle(struct iwl_priv *priv)
{
struct iwl_power_mgr *pow_data;
- int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_MAX;
+ int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_NUM;
struct iwl_powertable_cmd *cmd;
int i;
u16 lctl;
@@ -157,7 +128,7 @@ static void iwl_power_init_handle(struct iwl_priv *priv)
IWL_DEBUG_POWER(priv, "adjust power command flags\n");
- for (i = 0; i < IWL_POWER_MAX; i++) {
+ for (i = 0; i < IWL_POWER_NUM; i++) {
cmd = &pow_data->pwr_range_0[i].cmd;
if (lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN)
@@ -247,33 +218,12 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
- /* If on battery, set to 3,
- * if plugged into AC power, set to CAM ("continuously aware mode"),
- * else user level */
-
- switch (setting->system_power_setting) {
- case IWL_POWER_SYS_AUTO:
- final_mode = iwl_get_auto_power_mode(priv);
- break;
- case IWL_POWER_SYS_BATTERY:
- final_mode = IWL_POWER_INDEX_3;
- break;
- case IWL_POWER_SYS_AC:
- final_mode = IWL_POWER_MODE_CAM;
- break;
- default:
- final_mode = IWL_POWER_INDEX_3;
- WARN_ON(1);
- }
-
- if (setting->critical_power_setting > final_mode)
- final_mode = setting->critical_power_setting;
+ final_mode = priv->power_data.user_power_setting;
- /* driver only support CAM for non STA network */
- if (priv->iw_mode != NL80211_IFTYPE_STATION)
+ if (setting->power_disabled)
final_mode = IWL_POWER_MODE_CAM;
- if (iwl_is_ready_rf(priv) && !setting->power_disabled &&
+ if (iwl_is_ready_rf(priv) &&
((setting->power_mode != final_mode) || force)) {
struct iwl_powertable_cmd cmd;
@@ -290,8 +240,6 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
if (final_mode == IWL_POWER_MODE_CAM)
clear_bit(STATUS_POWER_PMI, &priv->status);
- else
- set_bit(STATUS_POWER_PMI, &priv->status);
if (priv->cfg->ops->lib->update_chain_flags && update_chains)
priv->cfg->ops->lib->update_chain_flags(priv);
@@ -307,51 +255,10 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
}
EXPORT_SYMBOL(iwl_power_update_mode);
-/* Allow other iwl code to disable/enable power management active
- * this will be useful for rate scale to disable PM during heavy
- * Tx/Rx activities
- */
-int iwl_power_disable_management(struct iwl_priv *priv, u32 ms)
-{
- u16 prev_mode;
- int ret = 0;
-
- if (priv->power_data.power_disabled)
- return -EBUSY;
-
- prev_mode = priv->power_data.user_power_setting;
- priv->power_data.user_power_setting = IWL_POWER_MODE_CAM;
- ret = iwl_power_update_mode(priv, 0);
- priv->power_data.power_disabled = 1;
- priv->power_data.user_power_setting = prev_mode;
- cancel_delayed_work(&priv->set_power_save);
- if (ms)
- queue_delayed_work(priv->workqueue, &priv->set_power_save,
- msecs_to_jiffies(ms));
-
-
- return ret;
-}
-EXPORT_SYMBOL(iwl_power_disable_management);
-
-/* Allow other iwl code to disable/enable power management active
- * this will be useful for rate scale to disable PM during high
- * volume activities
- */
-int iwl_power_enable_management(struct iwl_priv *priv)
-{
- int ret = 0;
-
- priv->power_data.power_disabled = 0;
- ret = iwl_power_update_mode(priv, 0);
- return ret;
-}
-EXPORT_SYMBOL(iwl_power_enable_management);
-
/* set user_power_setting */
int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode)
{
- if (mode > IWL_POWER_MAX)
+ if (mode >= IWL_POWER_NUM)
return -EINVAL;
priv->power_data.user_power_setting = mode;
@@ -360,86 +267,12 @@ int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode)
}
EXPORT_SYMBOL(iwl_power_set_user_mode);
-/* set system_power_setting. This should be set by over all
- * PM application.
- */
-int iwl_power_set_system_mode(struct iwl_priv *priv, u16 mode)
-{
- if (mode < IWL_POWER_SYS_MAX)
- priv->power_data.system_power_setting = mode;
- else
- return -EINVAL;
- return iwl_power_update_mode(priv, 0);
-}
-EXPORT_SYMBOL(iwl_power_set_system_mode);
-
/* initialize to default */
void iwl_power_initialize(struct iwl_priv *priv)
{
iwl_power_init_handle(priv);
- priv->power_data.user_power_setting = IWL_POWER_AUTO;
- priv->power_data.system_power_setting = IWL_POWER_SYS_AUTO;
- priv->power_data.power_disabled = 0;
- priv->power_data.is_battery_active = 0;
- priv->power_data.critical_power_setting = 0;
+ priv->power_data.user_power_setting = IWL_POWER_INDEX_1;
+ /* default to disabled until mac80211 says otherwise */
+ priv->power_data.power_disabled = 1;
}
EXPORT_SYMBOL(iwl_power_initialize);
-
-/* set critical_power_setting according to temperature value */
-int iwl_power_temperature_change(struct iwl_priv *priv)
-{
- int ret = 0;
- s32 temperature = KELVIN_TO_CELSIUS(priv->last_temperature);
- u16 new_critical = priv->power_data.critical_power_setting;
-
- if (temperature > IWL_CT_KILL_TEMPERATURE)
- return 0;
- else if (temperature > IWL_MIN_POWER_TEMPERATURE)
- new_critical = IWL_POWER_INDEX_5;
- else if (temperature > IWL_REDUCED_POWER_TEMPERATURE)
- new_critical = IWL_POWER_INDEX_3;
- else
- new_critical = IWL_POWER_MODE_CAM;
-
- if (new_critical != priv->power_data.critical_power_setting)
- priv->power_data.critical_power_setting = new_critical;
-
- if (priv->power_data.critical_power_setting >
- priv->power_data.power_mode)
- ret = iwl_power_update_mode(priv, 0);
-
- return ret;
-}
-EXPORT_SYMBOL(iwl_power_temperature_change);
-
-static void iwl_bg_set_power_save(struct work_struct *work)
-{
- struct iwl_priv *priv = container_of(work,
- struct iwl_priv, set_power_save.work);
- IWL_DEBUG_POWER(priv, "update power\n");
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- mutex_lock(&priv->mutex);
-
- /* on starting association we disable power management
- * until association, if association failed then this
- * timer will expire and enable PM again.
- */
- if (!iwl_is_associated(priv))
- iwl_power_enable_management(priv);
-
- mutex_unlock(&priv->mutex);
-}
-void iwl_setup_power_deferred_work(struct iwl_priv *priv)
-{
- INIT_DELAYED_WORK(&priv->set_power_save, iwl_bg_set_power_save);
-}
-EXPORT_SYMBOL(iwl_setup_power_deferred_work);
-
-void iwl_power_cancel_timeout(struct iwl_priv *priv)
-{
- cancel_delayed_work(&priv->set_power_save);
-}
-EXPORT_SYMBOL(iwl_power_cancel_timeout);
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h
index 18963392121e..37ba3bb7a25a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.h
+++ b/drivers/net/wireless/iwlwifi/iwl-power.h
@@ -40,56 +40,29 @@ enum {
IWL_POWER_INDEX_3,
IWL_POWER_INDEX_4,
IWL_POWER_INDEX_5,
- IWL_POWER_AUTO,
- IWL_POWER_MAX = IWL_POWER_AUTO,
+ IWL_POWER_NUM
};
-enum {
- IWL_POWER_SYS_AUTO,
- IWL_POWER_SYS_AC,
- IWL_POWER_SYS_BATTERY,
- IWL_POWER_SYS_MAX,
-};
-
-
/* Power management (not Tx power) structures */
-#define NOSLP cpu_to_le16(0), 0, 0
-#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0
-#define SLP_TOUT(T) cpu_to_le32((T) * MSEC_TO_USEC)
-#define SLP_VEC(X0, X1, X2, X3, X4) {cpu_to_le32(X0), \
- cpu_to_le32(X1), \
- cpu_to_le32(X2), \
- cpu_to_le32(X3), \
- cpu_to_le32(X4)}
struct iwl_power_vec_entry {
struct iwl_powertable_cmd cmd;
u8 no_dtim;
};
struct iwl_power_mgr {
- spinlock_t lock;
- struct iwl_power_vec_entry pwr_range_0[IWL_POWER_MAX];
- struct iwl_power_vec_entry pwr_range_1[IWL_POWER_MAX];
- struct iwl_power_vec_entry pwr_range_2[IWL_POWER_MAX];
+ struct iwl_power_vec_entry pwr_range_0[IWL_POWER_NUM];
+ struct iwl_power_vec_entry pwr_range_1[IWL_POWER_NUM];
+ struct iwl_power_vec_entry pwr_range_2[IWL_POWER_NUM];
u32 dtim_period;
/* final power level that used to calculate final power command */
u8 power_mode;
- u8 user_power_setting; /* set by user through mac80211 or sysfs */
- u8 system_power_setting; /* set by kernel system tools */
- u8 critical_power_setting; /* set if driver over heated */
- u8 is_battery_active; /* DC/AC power */
- u8 power_disabled; /* flag to disable using power saving level */
+ u8 user_power_setting; /* set by user through sysfs */
+ u8 power_disabled; /* set by mac80211's CONF_PS */
};
-void iwl_setup_power_deferred_work(struct iwl_priv *priv);
-void iwl_power_cancel_timeout(struct iwl_priv *priv);
int iwl_power_update_mode(struct iwl_priv *priv, bool force);
-int iwl_power_disable_management(struct iwl_priv *priv, u32 ms);
-int iwl_power_enable_management(struct iwl_priv *priv);
int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode);
-int iwl_power_set_system_mode(struct iwl_priv *priv, u16 mode);
void iwl_power_initialize(struct iwl_priv *priv);
-int iwl_power_temperature_change(struct iwl_priv *priv);
#endif /* __iwl_power_setting_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
index 65605ad44e4b..2ad9faf1508a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
@@ -91,6 +91,7 @@ int iwl_rfkill_init(struct iwl_priv *priv)
priv->rfkill->data = priv;
priv->rfkill->state = RFKILL_STATE_UNBLOCKED;
priv->rfkill->toggle_radio = iwl_rfkill_soft_rf_kill;
+ priv->rfkill->user_claim_unsupported = 1;
priv->rfkill->dev.class->suspend = NULL;
priv->rfkill->dev.class->resume = NULL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index dd8766b80b34..065214b55895 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -580,9 +580,10 @@ static void iwl_bg_request_scan(struct work_struct *data)
int ret = 0;
u32 rate_flags = 0;
u16 cmd_len;
+ u16 rx_chain = 0;
enum ieee80211_band band;
u8 n_probes = 0;
- u8 rx_chain = priv->hw_params.valid_rx_ant;
+ u8 rx_ant = priv->hw_params.valid_rx_ant;
u8 rate;
bool is_active = false;
@@ -723,7 +724,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
* Avoid A (0x1) because of its off-channel reception on A-band.
*/
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)
- rx_chain = 0x6;
+ rx_ant = ANT_BC;
} else {
IWL_WARN(priv, "Invalid scan band count\n");
goto done;
@@ -735,10 +736,11 @@ static void iwl_bg_request_scan(struct work_struct *data)
scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags);
/* MIMO is not used here, but value is required */
- scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK |
- cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) |
- (rx_chain << RXON_RX_CHAIN_FORCE_SEL_POS) |
- (0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS));
+ rx_chain |= ANT_ABC << RXON_RX_CHAIN_VALID_POS;
+ rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
+ rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
+ rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
+ scan->rx_chain = cpu_to_le16(rx_chain);
cmd_len = iwl_fill_probe_req(priv,
(struct ieee80211_mgmt *)scan->data,
priv->scan_request->ie,
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index f6c1489a0c4a..c32ec809053f 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -1837,23 +1837,6 @@ static void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
iwl_release_nic_access(priv);
}
-static void iwl3945_error_recovery(struct iwl_priv *priv)
-{
- unsigned long flags;
-
- memcpy(&priv->staging_rxon, &priv->recovery_rxon,
- sizeof(priv->staging_rxon));
- priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwlcore_commit_rxon(priv);
-
- priv->cfg->ops->smgmt->add_station(priv, priv->bssid, 1, 0, NULL);
-
- spin_lock_irqsave(&priv->lock, flags);
- priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id);
- priv->error_recovering = 0;
- spin_unlock_irqrestore(&priv->lock, flags);
-}
-
static void iwl3945_irq_tasklet(struct iwl_priv *priv)
{
u32 inta, handled = 0;
@@ -2683,9 +2666,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
/* After the ALIVE response, we can send commands to 3945 uCode */
set_bit(STATUS_ALIVE, &priv->status);
- /* Clear out the uCode error bit if it is set */
- clear_bit(STATUS_FW_ERROR, &priv->status);
-
if (iwl_is_rfkill(priv))
return;
@@ -2722,9 +2702,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
set_bit(STATUS_READY, &priv->status);
wake_up_interruptible(&priv->wait_command_queue);
- if (priv->error_recovering)
- iwl3945_error_recovery(priv);
-
/* reassociate for ADHOC mode */
if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) {
struct sk_buff *beacon = ieee80211_beacon_get(priv->hw,
@@ -3231,8 +3208,17 @@ static void iwl3945_bg_restart(struct work_struct *data)
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- iwl3945_down(priv);
- queue_work(priv->workqueue, &priv->up);
+ if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
+ mutex_lock(&priv->mutex);
+ priv->vif = NULL;
+ priv->is_open = 0;
+ mutex_unlock(&priv->mutex);
+ iwl3945_down(priv);
+ ieee80211_restart_hw(priv->hw);
+ } else {
+ iwl3945_down(priv);
+ queue_work(priv->workqueue, &priv->up);
+ }
}
static void iwl3945_bg_rx_replenish(struct work_struct *data)
@@ -3859,26 +3845,11 @@ static ssize_t show_power_level(struct device *d,
{
struct iwl_priv *priv = dev_get_drvdata(d);
int mode = priv->power_data.user_power_setting;
- int system = priv->power_data.system_power_setting;
int level = priv->power_data.power_mode;
char *p = buf;
- switch (system) {
- case IWL_POWER_SYS_AUTO:
- p += sprintf(p, "SYSTEM:auto");
- break;
- case IWL_POWER_SYS_AC:
- p += sprintf(p, "SYSTEM:ac");
- break;
- case IWL_POWER_SYS_BATTERY:
- p += sprintf(p, "SYSTEM:battery");
- break;
- }
-
- p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO) ?
- "fixed" : "auto");
- p += sprintf(p, "\tINDEX:%d", level);
- p += sprintf(p, "\n");
+ p += sprintf(p, "INDEX:%d\t", level);
+ p += sprintf(p, "USER:%d\n", mode);
return p - buf + 1;
}
@@ -4122,7 +4093,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
priv->ibss_beacon = NULL;
spin_lock_init(&priv->lock);
- spin_lock_init(&priv->power_data.lock);
spin_lock_init(&priv->sta_lock);
spin_lock_init(&priv->hcmd_lock);
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index b1213b6a6b9f..61a4ad7cc1c2 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -642,7 +642,7 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_HT) {
printk(KERN_DEBUG " %s: HT: op_mode=0x%x\n",
wiphy_name(hw->wiphy),
- info->ht.operation_mode);
+ info->ht_operation_mode);
}
if (changed & BSS_CHANGED_BASIC_RATES) {
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 46b288dc8f4d..a263d5c84c08 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -2369,7 +2369,7 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
if (info->use_cts_prot) {
prot_mode = MWL8K_FRAME_PROT_11G;
} else {
- switch (info->ht.operation_mode &
+ switch (info->ht_operation_mode &
IEEE80211_HT_OP_MODE_PROTECTION) {
case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY;
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
index e3569a0a952d..b1610ea4bb3d 100644
--- a/drivers/net/wireless/p54/p54pci.c
+++ b/drivers/net/wireless/p54/p54pci.c
@@ -492,8 +492,8 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
goto err_disable_dev;
}
- if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) ||
- pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
+ if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) ||
+ pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
dev_err(&pdev->dev, "No suitable DMA available\n");
goto err_free_reg;
}
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 52fc647e6cb6..ab7fe02230ca 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -635,7 +635,7 @@ static int rndis_set_config_parameter(struct usbnet *dev, char *param,
ret = rndis_set_oid(dev, OID_GEN_RNDIS_CONFIG_PARAMETER,
infobuf, info_len);
if (ret != 0)
- devdbg(dev, "setting rndis config paramater failed, %d.", ret);
+ devdbg(dev, "setting rndis config parameter failed, %d.", ret);
kfree(infobuf);
return ret;
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 39e00b3d7811..0bf2715fa93a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -261,7 +261,7 @@ void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna);
* @rt2x00dev: Pointer to &struct rt2x00_dev.
*
* Initialize work structure and all link tuning related
- * paramters. This will not start the link tuning process itself.
+ * parameters. This will not start the link tuning process itself.
*/
void rt2x00link_register(struct rt2x00_dev *rt2x00dev);
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index d10af3687a8e..270dd4e59f7f 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -1847,7 +1847,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_chip(rt2x00dev, RT2571, value, reg);
if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0x25730) ||
- !rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) {
+ rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) {
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
return -ENODEV;
}
diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h
index 622196dc078e..c09bfefc70f3 100644
--- a/drivers/net/wireless/rtl818x/rtl8187.h
+++ b/drivers/net/wireless/rtl818x/rtl8187.h
@@ -127,6 +127,12 @@ struct rtl8187_priv {
__le64 buf;
struct sk_buff_head queue;
} b_tx_status; /* This queue is used by both -b and non-b devices */
+ struct mutex io_mutex;
+ union {
+ u8 bits8;
+ __le16 bits16;
+ __le32 bits32;
+ } *io_dmabuf;
};
void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
@@ -136,10 +142,14 @@ static inline u8 rtl818x_ioread8_idx(struct rtl8187_priv *priv,
{
u8 val;
+ mutex_lock(&priv->io_mutex);
usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
- (unsigned long)addr, idx & 0x03, &val,
- sizeof(val), HZ / 2);
+ (unsigned long)addr, idx & 0x03,
+ &priv->io_dmabuf->bits8, sizeof(val), HZ / 2);
+
+ val = priv->io_dmabuf->bits8;
+ mutex_unlock(&priv->io_mutex);
return val;
}
@@ -154,10 +164,14 @@ static inline u16 rtl818x_ioread16_idx(struct rtl8187_priv *priv,
{
__le16 val;
+ mutex_lock(&priv->io_mutex);
usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
- (unsigned long)addr, idx & 0x03, &val,
- sizeof(val), HZ / 2);
+ (unsigned long)addr, idx & 0x03,
+ &priv->io_dmabuf->bits16, sizeof(val), HZ / 2);
+
+ val = priv->io_dmabuf->bits16;
+ mutex_unlock(&priv->io_mutex);
return le16_to_cpu(val);
}
@@ -172,10 +186,14 @@ static inline u32 rtl818x_ioread32_idx(struct rtl8187_priv *priv,
{
__le32 val;
+ mutex_lock(&priv->io_mutex);
usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
- (unsigned long)addr, idx & 0x03, &val,
- sizeof(val), HZ / 2);
+ (unsigned long)addr, idx & 0x03,
+ &priv->io_dmabuf->bits32, sizeof(val), HZ / 2);
+
+ val = priv->io_dmabuf->bits32;
+ mutex_unlock(&priv->io_mutex);
return le32_to_cpu(val);
}
@@ -188,10 +206,15 @@ static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr)
static inline void rtl818x_iowrite8_idx(struct rtl8187_priv *priv,
u8 *addr, u8 val, u8 idx)
{
+ mutex_lock(&priv->io_mutex);
+
+ priv->io_dmabuf->bits8 = val;
usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
- (unsigned long)addr, idx & 0x03, &val,
- sizeof(val), HZ / 2);
+ (unsigned long)addr, idx & 0x03,
+ &priv->io_dmabuf->bits8, sizeof(val), HZ / 2);
+
+ mutex_unlock(&priv->io_mutex);
}
static inline void rtl818x_iowrite8(struct rtl8187_priv *priv, u8 *addr, u8 val)
@@ -202,12 +225,15 @@ static inline void rtl818x_iowrite8(struct rtl8187_priv *priv, u8 *addr, u8 val)
static inline void rtl818x_iowrite16_idx(struct rtl8187_priv *priv,
__le16 *addr, u16 val, u8 idx)
{
- __le16 buf = cpu_to_le16(val);
+ mutex_lock(&priv->io_mutex);
+ priv->io_dmabuf->bits16 = cpu_to_le16(val);
usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
- (unsigned long)addr, idx & 0x03, &buf, sizeof(buf),
- HZ / 2);
+ (unsigned long)addr, idx & 0x03,
+ &priv->io_dmabuf->bits16, sizeof(val), HZ / 2);
+
+ mutex_unlock(&priv->io_mutex);
}
static inline void rtl818x_iowrite16(struct rtl8187_priv *priv, __le16 *addr,
@@ -219,12 +245,15 @@ static inline void rtl818x_iowrite16(struct rtl8187_priv *priv, __le16 *addr,
static inline void rtl818x_iowrite32_idx(struct rtl8187_priv *priv,
__le32 *addr, u32 val, u8 idx)
{
- __le32 buf = cpu_to_le32(val);
+ mutex_lock(&priv->io_mutex);
+ priv->io_dmabuf->bits32 = cpu_to_le32(val);
usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
- (unsigned long)addr, idx & 0x03, &buf, sizeof(buf),
- HZ / 2);
+ (unsigned long)addr, idx & 0x03,
+ &priv->io_dmabuf->bits32, sizeof(val), HZ / 2);
+
+ mutex_unlock(&priv->io_mutex);
}
static inline void rtl818x_iowrite32(struct rtl8187_priv *priv, __le32 *addr,
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
index 158827e50c55..6499ccc34c94 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -1326,6 +1326,14 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
priv = dev->priv;
priv->is_rtl8187b = (id->driver_info == DEVICE_RTL8187B);
+ /* allocate "DMA aware" buffer for register accesses */
+ priv->io_dmabuf = kmalloc(sizeof(*priv->io_dmabuf), GFP_KERNEL);
+ if (!priv->io_dmabuf) {
+ err = -ENOMEM;
+ goto err_free_dev;
+ }
+ mutex_init(&priv->io_mutex);
+
SET_IEEE80211_DEV(dev, &intf->dev);
usb_set_intfdata(intf, dev);
priv->udev = udev;
@@ -1489,7 +1497,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
err = ieee80211_register_hw(dev);
if (err) {
printk(KERN_ERR "rtl8187: Cannot register device\n");
- goto err_free_dev;
+ goto err_free_dmabuf;
}
mutex_init(&priv->conf_mutex);
skb_queue_head_init(&priv->b_tx_status.queue);
@@ -1506,6 +1514,8 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
return 0;
+ err_free_dmabuf:
+ kfree(priv->io_dmabuf);
err_free_dev:
ieee80211_free_hw(dev);
usb_set_intfdata(intf, NULL);
@@ -1529,6 +1539,7 @@ static void __devexit rtl8187_disconnect(struct usb_interface *intf)
priv = dev->priv;
usb_reset_device(priv->udev);
usb_put_dev(interface_to_usbdev(intf));
+ kfree(priv->io_dmabuf);
ieee80211_free_hw(dev);
}
diff --git a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
index 78df281b297a..a09819386a1e 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
@@ -88,9 +88,15 @@ static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data)
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
udelay(10);
+ mutex_lock(&priv->io_mutex);
+
+ priv->io_dmabuf->bits16 = data;
usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
- addr, 0x8225, &data, sizeof(data), HZ / 2);
+ addr, 0x8225, &priv->io_dmabuf->bits16, sizeof(data),
+ HZ / 2);
+
+ mutex_unlock(&priv->io_mutex);
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
udelay(10);
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index e55b33961aeb..fa2821be44c2 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -138,7 +138,7 @@ psa_read(struct net_device * dev,
/*------------------------------------------------------------------*/
/*
- * Write the Paramter Storage Area to the WaveLAN card's memory
+ * Write the Parameter Storage Area to the WaveLAN card's memory
*/
static void
psa_write(struct net_device * dev,
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig
index 20a9633569f2..a82c4cd436d8 100644
--- a/drivers/net/wireless/wl12xx/Kconfig
+++ b/drivers/net/wireless/wl12xx/Kconfig
@@ -1,6 +1,6 @@
config WL12XX
tristate "TI wl1251/wl1271 support"
- depends on MAC80211 && WLAN_80211 && SPI_MASTER && EXPERIMENTAL
+ depends on MAC80211 && WLAN_80211 && SPI_MASTER && GENERIC_HARDIRQS && EXPERIMENTAL
select FW_LOADER
select CRC7
---help---
diff --git a/drivers/of/base.c b/drivers/of/base.c
index ddf224d456b2..69f85c07d17f 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -447,6 +447,7 @@ struct of_modalias_table {
static struct of_modalias_table of_modalias_table[] = {
{ "fsl,mcu-mpc8349emitx", "mcu-mpc8349emitx" },
{ "mmc-spi-slot", "mmc_spi" },
+ { "stm,m25p40", "m25p80" },
};
/**
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index 73348c4047e9..4a9cc92d4d18 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -702,7 +702,7 @@ static unsigned int iosapic_startup_irq(unsigned int irq)
}
#ifdef CONFIG_SMP
-static void iosapic_set_affinity_irq(unsigned int irq,
+static int iosapic_set_affinity_irq(unsigned int irq,
const struct cpumask *dest)
{
struct vector_info *vi = iosapic_get_vector(irq);
@@ -712,7 +712,7 @@ static void iosapic_set_affinity_irq(unsigned int irq,
dest_cpu = cpu_check_affinity(irq, dest);
if (dest_cpu < 0)
- return;
+ return -1;
cpumask_copy(irq_desc[irq].affinity, cpumask_of(dest_cpu));
vi->txn_addr = txn_affinity_addr(irq, dest_cpu);
@@ -724,6 +724,8 @@ static void iosapic_set_affinity_irq(unsigned int irq,
iosapic_set_irt_data(vi, &dummy_d0, &d1);
iosapic_wr_irt_entry(vi, d0, d1);
spin_unlock_irqrestore(&iosapic_lock, flags);
+
+ return 0;
}
#endif
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index 4fa3bb2ddfe4..33e5ade774ca 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -434,7 +434,8 @@ static void __init superio_parport_init(void)
0 /*base_hi*/,
PAR_IRQ,
PARPORT_DMA_NONE /* dma */,
- NULL /*struct pci_dev* */) )
+ NULL /*struct pci_dev* */),
+ 0 /* shared irq flags */ )
printk(KERN_WARNING PFX "Probing parallel port failed.\n");
#endif /* CONFIG_PARPORT_PC */
diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index 64dd7df90e62..0f3706512686 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -87,8 +87,8 @@ EXPORT_SYMBOL(pci_read_vpd);
* pci_write_vpd - Write entry to Vital Product Data
* @dev: pci device struct
* @pos: offset in vpd space
- * @count: number of bytes to read
- * @val: value to write
+ * @count: number of bytes to write
+ * @buf: buffer containing write data
*
*/
ssize_t pci_write_vpd(struct pci_dev *dev, loff_t pos, size_t count, const void *buf)
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 97a8194063b5..40af27f31043 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -41,9 +41,14 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
void *alignf_data)
{
int i, ret = -ENOMEM;
+ resource_size_t max = -1;
type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
+ /* don't allocate too high if the pref mem doesn't support 64bit*/
+ if (!(res->flags & IORESOURCE_MEM_64))
+ max = PCIBIOS_MAX_MEM_32;
+
for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
struct resource *r = bus->resource[i];
if (!r)
@@ -62,7 +67,7 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
/* Ok, try it out.. */
ret = allocate_resource(r, res, size,
r->start ? : min,
- -1, align,
+ max, align,
alignf, alignf_data);
if (ret == 0)
break;
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index fa3a11365ec3..faf77a00cafe 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -515,6 +515,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
u32 ver;
static int iommu_allocated = 0;
int agaw = 0;
+ int msagaw = 0;
iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
if (!iommu)
@@ -535,12 +536,20 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
agaw = iommu_calculate_agaw(iommu);
if (agaw < 0) {
printk(KERN_ERR
- "Cannot get a valid agaw for iommu (seq_id = %d)\n",
+ "Cannot get a valid agaw for iommu (seq_id = %d)\n",
+ iommu->seq_id);
+ goto error;
+ }
+ msagaw = iommu_calculate_max_sagaw(iommu);
+ if (msagaw < 0) {
+ printk(KERN_ERR
+ "Cannot get a valid max agaw for iommu (seq_id = %d)\n",
iommu->seq_id);
goto error;
}
#endif
iommu->agaw = agaw;
+ iommu->msagaw = msagaw;
/* the registers might be more than one page */
map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
@@ -714,41 +723,26 @@ void qi_global_iec(struct intel_iommu *iommu)
qi_submit_sync(&desc, iommu);
}
-int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, u8 fm,
- u64 type, int non_present_entry_flush)
+void qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, u8 fm,
+ u64 type)
{
struct qi_desc desc;
- if (non_present_entry_flush) {
- if (!cap_caching_mode(iommu->cap))
- return 1;
- else
- did = 0;
- }
-
desc.low = QI_CC_FM(fm) | QI_CC_SID(sid) | QI_CC_DID(did)
| QI_CC_GRAN(type) | QI_CC_TYPE;
desc.high = 0;
- return qi_submit_sync(&desc, iommu);
+ qi_submit_sync(&desc, iommu);
}
-int qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
- unsigned int size_order, u64 type,
- int non_present_entry_flush)
+void qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
+ unsigned int size_order, u64 type)
{
u8 dw = 0, dr = 0;
struct qi_desc desc;
int ih = 0;
- if (non_present_entry_flush) {
- if (!cap_caching_mode(iommu->cap))
- return 1;
- else
- did = 0;
- }
-
if (cap_write_drain(iommu->cap))
dw = 1;
@@ -760,7 +754,7 @@ int qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
desc.high = QI_IOTLB_ADDR(addr) | QI_IOTLB_IH(ih)
| QI_IOTLB_AM(size_order);
- return qi_submit_sync(&desc, iommu);
+ qi_submit_sync(&desc, iommu);
}
/*
@@ -790,7 +784,6 @@ void dmar_disable_qi(struct intel_iommu *iommu)
cpu_relax();
iommu->gcmd &= ~DMA_GCMD_QIE;
-
writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl,
@@ -804,7 +797,7 @@ end:
*/
static void __dmar_enable_qi(struct intel_iommu *iommu)
{
- u32 cmd, sts;
+ u32 sts;
unsigned long flags;
struct q_inval *qi = iommu->qi;
@@ -818,9 +811,8 @@ static void __dmar_enable_qi(struct intel_iommu *iommu)
dmar_writeq(iommu->reg + DMAR_IQA_REG, virt_to_phys(qi->desc));
- cmd = iommu->gcmd | DMA_GCMD_QIE;
iommu->gcmd |= DMA_GCMD_QIE;
- writel(cmd, iommu->reg + DMAR_GCMD_REG);
+ writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
/* Make sure hardware complete it */
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl, (sts & DMA_GSTS_QIES), sts);
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index 9aa4fe100a0d..ac888ccfa161 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 && PCI_LEGACY
+ depends on X86 && PCI_BIOS
help
Say Y here if you have a motherboard with a Compaq PCI Hotplug
controller.
diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h
index afaf8f69f73e..53836001d511 100644
--- a/drivers/pci/hotplug/cpqphp.h
+++ b/drivers/pci/hotplug/cpqphp.h
@@ -150,25 +150,25 @@ struct ctrl_reg { /* offset */
/* offsets to the controller registers based on the above structure layout */
enum ctrl_offsets {
- SLOT_RST = offsetof(struct ctrl_reg, slot_RST),
+ SLOT_RST = offsetof(struct ctrl_reg, slot_RST),
SLOT_ENABLE = offsetof(struct ctrl_reg, slot_enable),
MISC = offsetof(struct ctrl_reg, misc),
LED_CONTROL = offsetof(struct ctrl_reg, led_control),
INT_INPUT_CLEAR = offsetof(struct ctrl_reg, int_input_clear),
- INT_MASK = offsetof(struct ctrl_reg, int_mask),
- CTRL_RESERVED0 = offsetof(struct ctrl_reg, reserved0),
+ INT_MASK = offsetof(struct ctrl_reg, int_mask),
+ CTRL_RESERVED0 = offsetof(struct ctrl_reg, reserved0),
CTRL_RESERVED1 = offsetof(struct ctrl_reg, reserved1),
CTRL_RESERVED2 = offsetof(struct ctrl_reg, reserved1),
- GEN_OUTPUT_AB = offsetof(struct ctrl_reg, gen_output_AB),
- NON_INT_INPUT = offsetof(struct ctrl_reg, non_int_input),
+ GEN_OUTPUT_AB = offsetof(struct ctrl_reg, gen_output_AB),
+ NON_INT_INPUT = offsetof(struct ctrl_reg, non_int_input),
CTRL_RESERVED3 = offsetof(struct ctrl_reg, reserved3),
CTRL_RESERVED4 = offsetof(struct ctrl_reg, reserved4),
CTRL_RESERVED5 = offsetof(struct ctrl_reg, reserved5),
CTRL_RESERVED6 = offsetof(struct ctrl_reg, reserved6),
CTRL_RESERVED7 = offsetof(struct ctrl_reg, reserved7),
CTRL_RESERVED8 = offsetof(struct ctrl_reg, reserved8),
- SLOT_MASK = offsetof(struct ctrl_reg, slot_mask),
- CTRL_RESERVED9 = offsetof(struct ctrl_reg, reserved9),
+ SLOT_MASK = offsetof(struct ctrl_reg, slot_mask),
+ CTRL_RESERVED9 = offsetof(struct ctrl_reg, reserved9),
CTRL_RESERVED10 = offsetof(struct ctrl_reg, reserved10),
CTRL_RESERVED11 = offsetof(struct ctrl_reg, reserved11),
SLOT_SERR = offsetof(struct ctrl_reg, slot_SERR),
@@ -190,7 +190,9 @@ struct hrt {
u32 reserved2;
} __attribute__ ((packed));
-/* offsets to the hotplug resource table registers based on the above structure layout */
+/* offsets to the hotplug resource table registers based on the above
+ * structure layout
+ */
enum hrt_offsets {
SIG0 = offsetof(struct hrt, sig0),
SIG1 = offsetof(struct hrt, sig1),
@@ -217,18 +219,20 @@ struct slot_rt {
u16 pre_mem_length;
} __attribute__ ((packed));
-/* offsets to the hotplug slot resource table registers based on the above structure layout */
+/* offsets to the hotplug slot resource table registers based on the above
+ * structure layout
+ */
enum slot_rt_offsets {
DEV_FUNC = offsetof(struct slot_rt, dev_func),
- PRIMARY_BUS = offsetof(struct slot_rt, primary_bus),
- SECONDARY_BUS = offsetof(struct slot_rt, secondary_bus),
- MAX_BUS = offsetof(struct slot_rt, max_bus),
- IO_BASE = offsetof(struct slot_rt, io_base),
- IO_LENGTH = offsetof(struct slot_rt, io_length),
- MEM_BASE = offsetof(struct slot_rt, mem_base),
- MEM_LENGTH = offsetof(struct slot_rt, mem_length),
- PRE_MEM_BASE = offsetof(struct slot_rt, pre_mem_base),
- PRE_MEM_LENGTH = offsetof(struct slot_rt, pre_mem_length),
+ PRIMARY_BUS = offsetof(struct slot_rt, primary_bus),
+ SECONDARY_BUS = offsetof(struct slot_rt, secondary_bus),
+ MAX_BUS = offsetof(struct slot_rt, max_bus),
+ IO_BASE = offsetof(struct slot_rt, io_base),
+ IO_LENGTH = offsetof(struct slot_rt, io_length),
+ MEM_BASE = offsetof(struct slot_rt, mem_base),
+ MEM_LENGTH = offsetof(struct slot_rt, mem_length),
+ PRE_MEM_BASE = offsetof(struct slot_rt, pre_mem_base),
+ PRE_MEM_LENGTH = offsetof(struct slot_rt, pre_mem_length),
};
struct pci_func {
@@ -286,8 +290,8 @@ struct event_info {
struct controller {
struct controller *next;
u32 ctrl_int_comp;
- struct mutex crit_sect; /* critical section mutex */
- void __iomem *hpc_reg; /* cookie for our pci controller location */
+ struct mutex crit_sect; /* critical section mutex */
+ void __iomem *hpc_reg; /* cookie for our pci controller location */
struct pci_resource *mem_head;
struct pci_resource *p_mem_head;
struct pci_resource *io_head;
@@ -299,7 +303,7 @@ struct controller {
u8 next_event;
u8 interrupt;
u8 cfgspc_irq;
- u8 bus; /* bus number for the pci hotplug controller */
+ u8 bus; /* bus number for the pci hotplug controller */
u8 rev;
u8 slot_device_offset;
u8 first_slot;
@@ -401,46 +405,57 @@ struct resource_lists {
/* debugfs functions for the hotplug controller info */
-extern void cpqhp_initialize_debugfs (void);
-extern void cpqhp_shutdown_debugfs (void);
-extern void cpqhp_create_debugfs_files (struct controller *ctrl);
-extern void cpqhp_remove_debugfs_files (struct controller *ctrl);
+extern void cpqhp_initialize_debugfs(void);
+extern void cpqhp_shutdown_debugfs(void);
+extern void cpqhp_create_debugfs_files(struct controller *ctrl);
+extern void cpqhp_remove_debugfs_files(struct controller *ctrl);
/* controller functions */
-extern void cpqhp_pushbutton_thread (unsigned long event_pointer);
-extern irqreturn_t cpqhp_ctrl_intr (int IRQ, void *data);
-extern int cpqhp_find_available_resources (struct controller *ctrl, void __iomem *rom_start);
-extern int cpqhp_event_start_thread (void);
-extern void cpqhp_event_stop_thread (void);
-extern struct pci_func *cpqhp_slot_create (unsigned char busnumber);
-extern struct pci_func *cpqhp_slot_find (unsigned char bus, unsigned char device, unsigned char index);
-extern int cpqhp_process_SI (struct controller *ctrl, struct pci_func *func);
-extern int cpqhp_process_SS (struct controller *ctrl, struct pci_func *func);
-extern int cpqhp_hardware_test (struct controller *ctrl, int test_num);
+extern void cpqhp_pushbutton_thread(unsigned long event_pointer);
+extern irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data);
+extern int cpqhp_find_available_resources(struct controller *ctrl,
+ void __iomem *rom_start);
+extern int cpqhp_event_start_thread(void);
+extern void cpqhp_event_stop_thread(void);
+extern struct pci_func *cpqhp_slot_create(unsigned char busnumber);
+extern struct pci_func *cpqhp_slot_find(unsigned char bus, unsigned char device,
+ unsigned char index);
+extern int cpqhp_process_SI(struct controller *ctrl, struct pci_func *func);
+extern int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func);
+extern int cpqhp_hardware_test(struct controller *ctrl, int test_num);
/* resource functions */
extern int cpqhp_resource_sort_and_combine (struct pci_resource **head);
/* pci functions */
-extern int cpqhp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
-extern int cpqhp_get_bus_dev (struct controller *ctrl, u8 *bus_num, u8 *dev_num, u8 slot);
-extern int cpqhp_save_config (struct controller *ctrl, int busnumber, int is_hot_plug);
-extern int cpqhp_save_base_addr_length (struct controller *ctrl, struct pci_func * func);
-extern int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func);
-extern int cpqhp_configure_board (struct controller *ctrl, struct pci_func * func);
-extern int cpqhp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot);
-extern int cpqhp_valid_replace (struct controller *ctrl, struct pci_func * func);
-extern void cpqhp_destroy_board_resources (struct pci_func * func);
-extern int cpqhp_return_board_resources (struct pci_func * func, struct resource_lists * resources);
-extern void cpqhp_destroy_resource_list (struct resource_lists * resources);
-extern int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func);
-extern int cpqhp_unconfigure_device (struct pci_func* func);
+extern int cpqhp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
+extern int cpqhp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num,
+ u8 slot);
+extern int cpqhp_save_config(struct controller *ctrl, int busnumber,
+ int is_hot_plug);
+extern int cpqhp_save_base_addr_length(struct controller *ctrl,
+ struct pci_func *func);
+extern int cpqhp_save_used_resources(struct controller *ctrl,
+ struct pci_func *func);
+extern int cpqhp_configure_board(struct controller *ctrl,
+ struct pci_func *func);
+extern int cpqhp_save_slot_config(struct controller *ctrl,
+ struct pci_func *new_slot);
+extern int cpqhp_valid_replace(struct controller *ctrl, struct pci_func *func);
+extern void cpqhp_destroy_board_resources(struct pci_func *func);
+extern int cpqhp_return_board_resources (struct pci_func *func,
+ struct resource_lists *resources);
+extern void cpqhp_destroy_resource_list(struct resource_lists *resources);
+extern int cpqhp_configure_device(struct controller *ctrl,
+ struct pci_func *func);
+extern int cpqhp_unconfigure_device(struct pci_func *func);
/* Global variables */
extern int cpqhp_debug;
extern int cpqhp_legacy_mode;
extern struct controller *cpqhp_ctrl_list;
extern struct pci_func *cpqhp_slot_list[256];
+extern struct irq_routing_table *cpqhp_routing_table;
/* these can be gotten rid of, but for debugging they are purty */
extern u8 cpqhp_nic_irq;
@@ -449,7 +464,7 @@ extern u8 cpqhp_disk_irq;
/* inline functions */
-static inline char *slot_name(struct slot *slot)
+static inline const char *slot_name(struct slot *slot)
{
return hotplug_slot_name(slot->hotplug_slot);
}
@@ -458,9 +473,9 @@ static inline char *slot_name(struct slot *slot)
* return_resource
*
* Puts node back in the resource list pointed to by head
- *
*/
-static inline void return_resource(struct pci_resource **head, struct pci_resource *node)
+static inline void return_resource(struct pci_resource **head,
+ struct pci_resource *node)
{
if (!node || !head)
return;
@@ -471,7 +486,7 @@ static inline void return_resource(struct pci_resource **head, struct pci_resour
static inline void set_SOGO(struct controller *ctrl)
{
u16 misc;
-
+
misc = readw(ctrl->hpc_reg + MISC);
misc = (misc | 0x0001) & 0xFFFB;
writew(misc, ctrl->hpc_reg + MISC);
@@ -481,7 +496,7 @@ static inline void set_SOGO(struct controller *ctrl)
static inline void amber_LED_on(struct controller *ctrl, u8 slot)
{
u32 led_control;
-
+
led_control = readl(ctrl->hpc_reg + LED_CONTROL);
led_control |= (0x01010000L << slot);
writel(led_control, ctrl->hpc_reg + LED_CONTROL);
@@ -491,7 +506,7 @@ static inline void amber_LED_on(struct controller *ctrl, u8 slot)
static inline void amber_LED_off(struct controller *ctrl, u8 slot)
{
u32 led_control;
-
+
led_control = readl(ctrl->hpc_reg + LED_CONTROL);
led_control &= ~(0x01010000L << slot);
writel(led_control, ctrl->hpc_reg + LED_CONTROL);
@@ -504,7 +519,7 @@ static inline int read_amber_LED(struct controller *ctrl, u8 slot)
led_control = readl(ctrl->hpc_reg + LED_CONTROL);
led_control &= (0x01010000L << slot);
-
+
return led_control ? 1 : 0;
}
@@ -512,7 +527,7 @@ static inline int read_amber_LED(struct controller *ctrl, u8 slot)
static inline void green_LED_on(struct controller *ctrl, u8 slot)
{
u32 led_control;
-
+
led_control = readl(ctrl->hpc_reg + LED_CONTROL);
led_control |= 0x0101L << slot;
writel(led_control, ctrl->hpc_reg + LED_CONTROL);
@@ -521,7 +536,7 @@ static inline void green_LED_on(struct controller *ctrl, u8 slot)
static inline void green_LED_off(struct controller *ctrl, u8 slot)
{
u32 led_control;
-
+
led_control = readl(ctrl->hpc_reg + LED_CONTROL);
led_control &= ~(0x0101L << slot);
writel(led_control, ctrl->hpc_reg + LED_CONTROL);
@@ -531,7 +546,7 @@ static inline void green_LED_off(struct controller *ctrl, u8 slot)
static inline void green_LED_blink(struct controller *ctrl, u8 slot)
{
u32 led_control;
-
+
led_control = readl(ctrl->hpc_reg + LED_CONTROL);
led_control &= ~(0x0101L << slot);
led_control |= (0x0001L << slot);
@@ -575,22 +590,21 @@ static inline u8 read_slot_enable(struct controller *ctrl)
}
-/*
+/**
* get_controller_speed - find the current frequency/mode of controller.
*
* @ctrl: controller to get frequency/mode for.
*
* Returns controller speed.
- *
*/
static inline u8 get_controller_speed(struct controller *ctrl)
{
u8 curr_freq;
- u16 misc;
-
+ u16 misc;
+
if (ctrl->pcix_support) {
curr_freq = readb(ctrl->hpc_reg + NEXT_CURR_FREQ);
- if ((curr_freq & 0xB0) == 0xB0)
+ if ((curr_freq & 0xB0) == 0xB0)
return PCI_SPEED_133MHz_PCIX;
if ((curr_freq & 0xA0) == 0xA0)
return PCI_SPEED_100MHz_PCIX;
@@ -602,19 +616,18 @@ static inline u8 get_controller_speed(struct controller *ctrl)
return PCI_SPEED_33MHz;
}
- misc = readw(ctrl->hpc_reg + MISC);
- return (misc & 0x0800) ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
+ misc = readw(ctrl->hpc_reg + MISC);
+ return (misc & 0x0800) ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
}
-
-/*
+
+/**
* get_adapter_speed - find the max supported frequency/mode of adapter.
*
* @ctrl: hotplug controller.
* @hp_slot: hotplug slot where adapter is installed.
*
* Returns adapter speed.
- *
*/
static inline u8 get_adapter_speed(struct controller *ctrl, u8 hp_slot)
{
@@ -672,7 +685,8 @@ static inline int get_slot_enabled(struct controller *ctrl, struct slot *slot)
}
-static inline int cpq_get_latch_status(struct controller *ctrl, struct slot *slot)
+static inline int cpq_get_latch_status(struct controller *ctrl,
+ struct slot *slot)
{
u32 status;
u8 hp_slot;
@@ -687,7 +701,8 @@ static inline int cpq_get_latch_status(struct controller *ctrl, struct slot *slo
}
-static inline int get_presence_status(struct controller *ctrl, struct slot *slot)
+static inline int get_presence_status(struct controller *ctrl,
+ struct slot *slot)
{
int presence_save = 0;
u8 hp_slot;
@@ -696,7 +711,8 @@ static inline int get_presence_status(struct controller *ctrl, struct slot *slot
hp_slot = slot->device - ctrl->slot_device_offset;
tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
- presence_save = (int) ((((~tempdword) >> 23) | ((~tempdword) >> 15)) >> hp_slot) & 0x02;
+ presence_save = (int) ((((~tempdword) >> 23) | ((~tempdword) >> 15))
+ >> hp_slot) & 0x02;
return presence_save;
}
@@ -718,5 +734,12 @@ static inline int wait_for_ctrl_irq(struct controller *ctrl)
return retval;
}
-#endif
+#include <asm/pci_x86.h>
+static inline int cpqhp_routing_table_length(void)
+{
+ BUG_ON(cpqhp_routing_table == NULL);
+ return ((cpqhp_routing_table->size - sizeof(struct irq_routing_table)) /
+ sizeof(struct irq_info));
+}
+#endif
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index c2e1bcbb28a7..7888b37c6c8e 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -25,8 +25,7 @@
* Send feedback to <greg@kroah.com>
*
* Jan 12, 2003 - Added 66/100/133MHz PCI-X support,
- * Torben Mathiasen <torben.mathiasen@hp.com>
- *
+ * Torben Mathiasen <torben.mathiasen@hp.com>
*/
#include <linux/module.h>
@@ -45,7 +44,6 @@
#include "cpqphp.h"
#include "cpqphp_nvram.h"
-#include <asm/pci_x86.h>
/* Global variables */
@@ -53,6 +51,7 @@ int cpqhp_debug;
int cpqhp_legacy_mode;
struct controller *cpqhp_ctrl_list; /* = NULL */
struct pci_func *cpqhp_slot_list[256];
+struct irq_routing_table *cpqhp_routing_table;
/* local variables */
static void __iomem *smbios_table;
@@ -78,33 +77,6 @@ MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
#define CPQHPC_MODULE_MINOR 208
-static int one_time_init (void);
-static int set_attention_status (struct hotplug_slot *slot, u8 value);
-static int process_SI (struct hotplug_slot *slot);
-static int process_SS (struct hotplug_slot *slot);
-static int hardware_test (struct hotplug_slot *slot, u32 value);
-static int get_power_status (struct hotplug_slot *slot, u8 *value);
-static int get_attention_status (struct hotplug_slot *slot, u8 *value);
-static int get_latch_status (struct hotplug_slot *slot, u8 *value);
-static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
-static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
-static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
-
-static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = {
- .owner = THIS_MODULE,
- .set_attention_status = set_attention_status,
- .enable_slot = process_SI,
- .disable_slot = process_SS,
- .hardware_test = hardware_test,
- .get_power_status = get_power_status,
- .get_attention_status = get_attention_status,
- .get_latch_status = get_latch_status,
- .get_adapter_status = get_adapter_status,
- .get_max_bus_speed = get_max_bus_speed,
- .get_cur_bus_speed = get_cur_bus_speed,
-};
-
-
static inline int is_slot64bit(struct slot *slot)
{
return (readb(slot->p_sm_slot + SMBIOS_SLOT_WIDTH) == 0x06) ? 1 : 0;
@@ -144,7 +116,7 @@ static void __iomem * detect_SMBIOS_pointer(void __iomem *begin, void __iomem *e
break;
}
}
-
+
if (!status)
fp = NULL;
@@ -171,7 +143,7 @@ static int init_SERR(struct controller * ctrl)
tempdword = ctrl->first_slot;
number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
- // Loop through slots
+ /* Loop through slots */
while (number_of_slots) {
physical_slot = tempdword;
writeb(0, ctrl->hpc_reg + SLOT_SERR);
@@ -182,41 +154,42 @@ static int init_SERR(struct controller * ctrl)
return 0;
}
-
-/* nice debugging output */
-static int pci_print_IRQ_route (void)
+static int init_cpqhp_routing_table(void)
{
- struct irq_routing_table *routing_table;
int len;
- int loop;
- u8 tbus, tdevice, tslot;
-
- routing_table = pcibios_get_irq_routing_table();
- if (routing_table == NULL) {
- err("No BIOS Routing Table??? Not good\n");
+ cpqhp_routing_table = pcibios_get_irq_routing_table();
+ if (cpqhp_routing_table == NULL)
return -ENOMEM;
- }
- len = (routing_table->size - sizeof(struct irq_routing_table)) /
- sizeof(struct irq_info);
- // Make sure I got at least one entry
+ len = cpqhp_routing_table_length();
if (len == 0) {
- kfree(routing_table);
+ kfree(cpqhp_routing_table);
+ cpqhp_routing_table = NULL;
return -1;
}
- dbg("bus dev func slot\n");
+ return 0;
+}
+/* nice debugging output */
+static void pci_print_IRQ_route(void)
+{
+ int len;
+ int loop;
+ u8 tbus, tdevice, tslot;
+
+ len = cpqhp_routing_table_length();
+
+ dbg("bus dev func slot\n");
for (loop = 0; loop < len; ++loop) {
- tbus = routing_table->slots[loop].bus;
- tdevice = routing_table->slots[loop].devfn;
- tslot = routing_table->slots[loop].slot;
+ tbus = cpqhp_routing_table->slots[loop].bus;
+ tdevice = cpqhp_routing_table->slots[loop].devfn;
+ tslot = cpqhp_routing_table->slots[loop].slot;
dbg("%d %d %d %d\n", tbus, tdevice >> 3, tdevice & 0x7, tslot);
}
- kfree(routing_table);
- return 0;
+ return;
}
@@ -242,9 +215,9 @@ static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start,
void __iomem *p_max;
if (!smbios_table || !curr)
- return(NULL);
+ return NULL;
- // set p_max to the end of the table
+ /* set p_max to the end of the table */
p_max = smbios_start + readw(smbios_table + ST_LENGTH);
p_temp = curr;
@@ -253,20 +226,19 @@ static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start,
while ((p_temp < p_max) && !bail) {
/* Look for the double NULL terminator
* The first condition is the previous byte
- * and the second is the curr */
- if (!previous_byte && !(readb(p_temp))) {
+ * and the second is the curr
+ */
+ if (!previous_byte && !(readb(p_temp)))
bail = 1;
- }
previous_byte = readb(p_temp);
p_temp++;
}
- if (p_temp < p_max) {
+ if (p_temp < p_max)
return p_temp;
- } else {
+ else
return NULL;
- }
}
@@ -292,21 +264,18 @@ static void __iomem *get_SMBIOS_entry(void __iomem *smbios_start,
if (!smbios_table)
return NULL;
- if (!previous) {
+ if (!previous)
previous = smbios_start;
- } else {
+ else
previous = get_subsequent_smbios_entry(smbios_start,
smbios_table, previous);
- }
- while (previous) {
- if (readb(previous + SMBIOS_GENERIC_TYPE) != type) {
+ while (previous)
+ if (readb(previous + SMBIOS_GENERIC_TYPE) != type)
previous = get_subsequent_smbios_entry(smbios_start,
smbios_table, previous);
- } else {
+ else
break;
- }
- }
return previous;
}
@@ -322,144 +291,6 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
kfree(slot);
}
-#define SLOT_NAME_SIZE 10
-
-static int ctrl_slot_setup(struct controller *ctrl,
- void __iomem *smbios_start,
- void __iomem *smbios_table)
-{
- struct slot *slot;
- struct hotplug_slot *hotplug_slot;
- struct hotplug_slot_info *hotplug_slot_info;
- u8 number_of_slots;
- u8 slot_device;
- u8 slot_number;
- u8 ctrl_slot;
- u32 tempdword;
- char name[SLOT_NAME_SIZE];
- void __iomem *slot_entry= NULL;
- int result = -ENOMEM;
-
- dbg("%s\n", __func__);
-
- tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
-
- number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
- slot_device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4;
- slot_number = ctrl->first_slot;
-
- while (number_of_slots) {
- slot = kzalloc(sizeof(*slot), GFP_KERNEL);
- if (!slot)
- goto error;
-
- slot->hotplug_slot = kzalloc(sizeof(*(slot->hotplug_slot)),
- GFP_KERNEL);
- if (!slot->hotplug_slot)
- goto error_slot;
- hotplug_slot = slot->hotplug_slot;
-
- hotplug_slot->info =
- kzalloc(sizeof(*(hotplug_slot->info)),
- GFP_KERNEL);
- if (!hotplug_slot->info)
- goto error_hpslot;
- hotplug_slot_info = hotplug_slot->info;
-
- slot->ctrl = ctrl;
- slot->bus = ctrl->bus;
- slot->device = slot_device;
- slot->number = slot_number;
- dbg("slot->number = %u\n", slot->number);
-
- slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9,
- slot_entry);
-
- while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) !=
- slot->number)) {
- slot_entry = get_SMBIOS_entry(smbios_start,
- smbios_table, 9, slot_entry);
- }
-
- slot->p_sm_slot = slot_entry;
-
- init_timer(&slot->task_event);
- slot->task_event.expires = jiffies + 5 * HZ;
- slot->task_event.function = cpqhp_pushbutton_thread;
-
- //FIXME: these capabilities aren't used but if they are
- // they need to be correctly implemented
- slot->capabilities |= PCISLOT_REPLACE_SUPPORTED;
- slot->capabilities |= PCISLOT_INTERLOCK_SUPPORTED;
-
- if (is_slot64bit(slot))
- slot->capabilities |= PCISLOT_64_BIT_SUPPORTED;
- if (is_slot66mhz(slot))
- slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED;
- if (ctrl->speed == PCI_SPEED_66MHz)
- slot->capabilities |= PCISLOT_66_MHZ_OPERATION;
-
- ctrl_slot =
- slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4);
-
- // Check presence
- slot->capabilities |=
- ((((~tempdword) >> 23) |
- ((~tempdword) >> 15)) >> ctrl_slot) & 0x02;
- // Check the switch state
- slot->capabilities |=
- ((~tempdword & 0xFF) >> ctrl_slot) & 0x01;
- // Check the slot enable
- slot->capabilities |=
- ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04;
-
- /* register this slot with the hotplug pci core */
- hotplug_slot->release = &release_slot;
- hotplug_slot->private = slot;
- snprintf(name, SLOT_NAME_SIZE, "%u", slot->number);
- hotplug_slot->ops = &cpqphp_hotplug_slot_ops;
-
- hotplug_slot_info->power_status = get_slot_enabled(ctrl, slot);
- hotplug_slot_info->attention_status =
- cpq_get_attention_status(ctrl, slot);
- hotplug_slot_info->latch_status =
- cpq_get_latch_status(ctrl, slot);
- hotplug_slot_info->adapter_status =
- get_presence_status(ctrl, slot);
-
- dbg("registering bus %d, dev %d, number %d, "
- "ctrl->slot_device_offset %d, slot %d\n",
- slot->bus, slot->device,
- slot->number, ctrl->slot_device_offset,
- slot_number);
- result = pci_hp_register(hotplug_slot,
- ctrl->pci_dev->bus,
- slot->device,
- name);
- if (result) {
- err("pci_hp_register failed with error %d\n", result);
- goto error_info;
- }
-
- slot->next = ctrl->slot;
- ctrl->slot = slot;
-
- number_of_slots--;
- slot_device++;
- slot_number++;
- }
-
- return 0;
-error_info:
- kfree(hotplug_slot_info);
-error_hpslot:
- kfree(hotplug_slot);
-error_slot:
- kfree(slot);
-error:
- return result;
-}
-
static int ctrl_slot_cleanup (struct controller * ctrl)
{
struct slot *old_slot, *next_slot;
@@ -476,36 +307,32 @@ static int ctrl_slot_cleanup (struct controller * ctrl)
cpqhp_remove_debugfs_files(ctrl);
- //Free IRQ associated with hot plug device
+ /* Free IRQ associated with hot plug device */
free_irq(ctrl->interrupt, ctrl);
- //Unmap the memory
+ /* Unmap the memory */
iounmap(ctrl->hpc_reg);
- //Finally reclaim PCI mem
+ /* Finally reclaim PCI mem */
release_mem_region(pci_resource_start(ctrl->pci_dev, 0),
pci_resource_len(ctrl->pci_dev, 0));
- return(0);
+ return 0;
}
-//============================================================================
-// function: get_slot_mapping
-//
-// Description: Attempts to determine a logical slot mapping for a PCI
-// device. Won't work for more than one PCI-PCI bridge
-// in a slot.
-//
-// Input: u8 bus_num - bus number of PCI device
-// u8 dev_num - device number of PCI device
-// u8 *slot - Pointer to u8 where slot number will
-// be returned
-//
-// Output: SUCCESS or FAILURE
-//=============================================================================
+/**
+ * get_slot_mapping - determine logical slot mapping for PCI device
+ *
+ * Won't work for more than one PCI-PCI bridge in a slot.
+ *
+ * @bus_num - bus number of PCI device
+ * @dev_num - device number of PCI device
+ * @slot - Pointer to u8 where slot number will be returned
+ *
+ * Output: SUCCESS or FAILURE
+ */
static int
get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot)
{
- struct irq_routing_table *PCIIRQRoutingInfoLength;
u32 work;
long len;
long loop;
@@ -516,36 +343,25 @@ get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot)
bridgeSlot = 0xFF;
- PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table();
- if (!PCIIRQRoutingInfoLength)
- return -1;
-
- len = (PCIIRQRoutingInfoLength->size -
- sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
- // Make sure I got at least one entry
- if (len == 0) {
- kfree(PCIIRQRoutingInfoLength);
- return -1;
- }
-
+ len = cpqhp_routing_table_length();
for (loop = 0; loop < len; ++loop) {
- tbus = PCIIRQRoutingInfoLength->slots[loop].bus;
- tdevice = PCIIRQRoutingInfoLength->slots[loop].devfn >> 3;
- tslot = PCIIRQRoutingInfoLength->slots[loop].slot;
+ tbus = cpqhp_routing_table->slots[loop].bus;
+ tdevice = cpqhp_routing_table->slots[loop].devfn >> 3;
+ tslot = cpqhp_routing_table->slots[loop].slot;
if ((tbus == bus_num) && (tdevice == dev_num)) {
*slot = tslot;
- kfree(PCIIRQRoutingInfoLength);
return 0;
} else {
/* Did not get a match on the target PCI device. Check
- * if the current IRQ table entry is a PCI-to-PCI bridge
- * device. If so, and it's secondary bus matches the
- * bus number for the target device, I need to save the
- * bridge's slot number. If I can not find an entry for
- * the target device, I will have to assume it's on the
- * other side of the bridge, and assign it the bridge's
- * slot. */
+ * if the current IRQ table entry is a PCI-to-PCI
+ * bridge device. If so, and it's secondary bus
+ * matches the bus number for the target device, I need
+ * to save the bridge's slot number. If I can not find
+ * an entry for the target device, I will have to
+ * assume it's on the other side of the bridge, and
+ * assign it the bridge's slot.
+ */
bus->number = tbus;
pci_bus_read_config_dword(bus, PCI_DEVFN(tdevice, 0),
PCI_CLASS_REVISION, &work);
@@ -555,25 +371,23 @@ get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot)
PCI_DEVFN(tdevice, 0),
PCI_PRIMARY_BUS, &work);
// See if bridge's secondary bus matches target bus.
- if (((work >> 8) & 0x000000FF) == (long) bus_num) {
+ if (((work >> 8) & 0x000000FF) == (long) bus_num)
bridgeSlot = tslot;
- }
}
}
}
- // If we got here, we didn't find an entry in the IRQ mapping table
- // for the target PCI device. If we did determine that the target
- // device is on the other side of a PCI-to-PCI bridge, return the
- // slot number for the bridge.
+ /* If we got here, we didn't find an entry in the IRQ mapping table for
+ * the target PCI device. If we did determine that the target device
+ * is on the other side of a PCI-to-PCI bridge, return the slot number
+ * for the bridge.
+ */
if (bridgeSlot != 0xFF) {
*slot = bridgeSlot;
- kfree(PCIIRQRoutingInfoLength);
return 0;
}
- kfree(PCIIRQRoutingInfoLength);
- // Couldn't find an entry in the routing table for this PCI device
+ /* Couldn't find an entry in the routing table for this PCI device */
return -1;
}
@@ -591,32 +405,32 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func,
u8 hp_slot;
if (func == NULL)
- return(1);
+ return 1;
hp_slot = func->device - ctrl->slot_device_offset;
- // Wait for exclusive access to hardware
+ /* Wait for exclusive access to hardware */
mutex_lock(&ctrl->crit_sect);
- if (status == 1) {
+ if (status == 1)
amber_LED_on (ctrl, hp_slot);
- } else if (status == 0) {
+ else if (status == 0)
amber_LED_off (ctrl, hp_slot);
- } else {
- // Done with exclusive hardware access
+ else {
+ /* Done with exclusive hardware access */
mutex_unlock(&ctrl->crit_sect);
- return(1);
+ return 1;
}
set_SOGO(ctrl);
- // Wait for SOBS to be unset
+ /* Wait for SOBS to be unset */
wait_for_ctrl_irq (ctrl);
- // Done with exclusive hardware access
+ /* Done with exclusive hardware access */
mutex_unlock(&ctrl->crit_sect);
- return(0);
+ return 0;
}
@@ -719,7 +533,7 @@ static int hardware_test(struct hotplug_slot *hotplug_slot, u32 value)
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
- return cpqhp_hardware_test(ctrl, value);
+ return cpqhp_hardware_test(ctrl, value);
}
@@ -738,7 +552,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
struct slot *slot = hotplug_slot->private;
struct controller *ctrl = slot->ctrl;
-
+
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
*value = cpq_get_attention_status(ctrl, slot);
@@ -793,6 +607,231 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
return 0;
}
+static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = {
+ .owner = THIS_MODULE,
+ .set_attention_status = set_attention_status,
+ .enable_slot = process_SI,
+ .disable_slot = process_SS,
+ .hardware_test = hardware_test,
+ .get_power_status = get_power_status,
+ .get_attention_status = get_attention_status,
+ .get_latch_status = get_latch_status,
+ .get_adapter_status = get_adapter_status,
+ .get_max_bus_speed = get_max_bus_speed,
+ .get_cur_bus_speed = get_cur_bus_speed,
+};
+
+#define SLOT_NAME_SIZE 10
+
+static int ctrl_slot_setup(struct controller *ctrl,
+ void __iomem *smbios_start,
+ void __iomem *smbios_table)
+{
+ struct slot *slot;
+ struct hotplug_slot *hotplug_slot;
+ struct hotplug_slot_info *hotplug_slot_info;
+ u8 number_of_slots;
+ u8 slot_device;
+ u8 slot_number;
+ u8 ctrl_slot;
+ u32 tempdword;
+ char name[SLOT_NAME_SIZE];
+ void __iomem *slot_entry= NULL;
+ int result = -ENOMEM;
+
+ dbg("%s\n", __func__);
+
+ tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
+
+ number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
+ slot_device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4;
+ slot_number = ctrl->first_slot;
+
+ while (number_of_slots) {
+ slot = kzalloc(sizeof(*slot), GFP_KERNEL);
+ if (!slot)
+ goto error;
+
+ slot->hotplug_slot = kzalloc(sizeof(*(slot->hotplug_slot)),
+ GFP_KERNEL);
+ if (!slot->hotplug_slot)
+ goto error_slot;
+ hotplug_slot = slot->hotplug_slot;
+
+ hotplug_slot->info = kzalloc(sizeof(*(hotplug_slot->info)),
+ GFP_KERNEL);
+ if (!hotplug_slot->info)
+ goto error_hpslot;
+ hotplug_slot_info = hotplug_slot->info;
+
+ slot->ctrl = ctrl;
+ slot->bus = ctrl->bus;
+ slot->device = slot_device;
+ slot->number = slot_number;
+ dbg("slot->number = %u\n", slot->number);
+
+ slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9,
+ slot_entry);
+
+ while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) !=
+ slot->number)) {
+ slot_entry = get_SMBIOS_entry(smbios_start,
+ smbios_table, 9, slot_entry);
+ }
+
+ slot->p_sm_slot = slot_entry;
+
+ init_timer(&slot->task_event);
+ slot->task_event.expires = jiffies + 5 * HZ;
+ slot->task_event.function = cpqhp_pushbutton_thread;
+
+ /*FIXME: these capabilities aren't used but if they are
+ * they need to be correctly implemented
+ */
+ slot->capabilities |= PCISLOT_REPLACE_SUPPORTED;
+ slot->capabilities |= PCISLOT_INTERLOCK_SUPPORTED;
+
+ if (is_slot64bit(slot))
+ slot->capabilities |= PCISLOT_64_BIT_SUPPORTED;
+ if (is_slot66mhz(slot))
+ slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED;
+ if (ctrl->speed == PCI_SPEED_66MHz)
+ slot->capabilities |= PCISLOT_66_MHZ_OPERATION;
+
+ ctrl_slot =
+ slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4);
+
+ /* Check presence */
+ slot->capabilities |=
+ ((((~tempdword) >> 23) |
+ ((~tempdword) >> 15)) >> ctrl_slot) & 0x02;
+ /* Check the switch state */
+ slot->capabilities |=
+ ((~tempdword & 0xFF) >> ctrl_slot) & 0x01;
+ /* Check the slot enable */
+ slot->capabilities |=
+ ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04;
+
+ /* register this slot with the hotplug pci core */
+ hotplug_slot->release = &release_slot;
+ hotplug_slot->private = slot;
+ snprintf(name, SLOT_NAME_SIZE, "%u", slot->number);
+ hotplug_slot->ops = &cpqphp_hotplug_slot_ops;
+
+ hotplug_slot_info->power_status = get_slot_enabled(ctrl, slot);
+ hotplug_slot_info->attention_status =
+ cpq_get_attention_status(ctrl, slot);
+ hotplug_slot_info->latch_status =
+ cpq_get_latch_status(ctrl, slot);
+ hotplug_slot_info->adapter_status =
+ get_presence_status(ctrl, slot);
+
+ dbg("registering bus %d, dev %d, number %d, "
+ "ctrl->slot_device_offset %d, slot %d\n",
+ slot->bus, slot->device,
+ slot->number, ctrl->slot_device_offset,
+ slot_number);
+ result = pci_hp_register(hotplug_slot,
+ ctrl->pci_dev->bus,
+ slot->device,
+ name);
+ if (result) {
+ err("pci_hp_register failed with error %d\n", result);
+ goto error_info;
+ }
+
+ slot->next = ctrl->slot;
+ ctrl->slot = slot;
+
+ number_of_slots--;
+ slot_device++;
+ slot_number++;
+ }
+
+ return 0;
+error_info:
+ kfree(hotplug_slot_info);
+error_hpslot:
+ kfree(hotplug_slot);
+error_slot:
+ kfree(slot);
+error:
+ return result;
+}
+
+static int one_time_init(void)
+{
+ int loop;
+ int retval = 0;
+
+ if (initialized)
+ return 0;
+
+ power_mode = 0;
+
+ retval = init_cpqhp_routing_table();
+ if (retval)
+ goto error;
+
+ if (cpqhp_debug)
+ pci_print_IRQ_route();
+
+ dbg("Initialize + Start the notification mechanism \n");
+
+ retval = cpqhp_event_start_thread();
+ if (retval)
+ goto error;
+
+ dbg("Initialize slot lists\n");
+ for (loop = 0; loop < 256; loop++)
+ cpqhp_slot_list[loop] = NULL;
+
+ /* FIXME: We also need to hook the NMI handler eventually.
+ * this also needs to be worked with Christoph
+ * register_NMI_handler();
+ */
+ /* Map rom address */
+ cpqhp_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN);
+ if (!cpqhp_rom_start) {
+ err ("Could not ioremap memory region for ROM\n");
+ retval = -EIO;
+ goto error;
+ }
+
+ /* Now, map the int15 entry point if we are on compaq specific
+ * hardware
+ */
+ compaq_nvram_init(cpqhp_rom_start);
+
+ /* Map smbios table entry point structure */
+ smbios_table = detect_SMBIOS_pointer(cpqhp_rom_start,
+ cpqhp_rom_start + ROM_PHY_LEN);
+ if (!smbios_table) {
+ err ("Could not find the SMBIOS pointer in memory\n");
+ retval = -EIO;
+ goto error_rom_start;
+ }
+
+ smbios_start = ioremap(readl(smbios_table + ST_ADDRESS),
+ readw(smbios_table + ST_LENGTH));
+ if (!smbios_start) {
+ err ("Could not ioremap memory region taken from SMBIOS values\n");
+ retval = -EIO;
+ goto error_smbios_start;
+ }
+
+ initialized = 1;
+
+ return retval;
+
+error_smbios_start:
+ iounmap(smbios_start);
+error_rom_start:
+ iounmap(cpqhp_rom_start);
+error:
+ return retval;
+}
+
static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
u8 num_of_slots = 0;
@@ -815,7 +854,9 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return err;
}
- // Need to read VID early b/c it's used to differentiate CPQ and INTC discovery
+ /* Need to read VID early b/c it's used to differentiate CPQ and INTC
+ * discovery
+ */
rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
if (rc || ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL))) {
err(msg_HPC_non_compaq_or_intel);
@@ -832,217 +873,209 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
/* Check for the proper subsytem ID's
- * Intel uses a different SSID programming model than Compaq.
+ * Intel uses a different SSID programming model than Compaq.
* For Intel, each SSID bit identifies a PHP capability.
* Also Intel HPC's may have RID=0.
*/
- if ((pdev->revision > 2) || (vendor_id == PCI_VENDOR_ID_INTEL)) {
- // TODO: This code can be made to support non-Compaq or Intel subsystem IDs
- rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
- if (rc) {
- err("%s : pci_read_config_word failed\n", __func__);
- goto err_disable_device;
- }
- dbg("Subsystem Vendor ID: %x\n", subsystem_vid);
- if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) {
- err(msg_HPC_non_compaq_or_intel);
- rc = -ENODEV;
- goto err_disable_device;
- }
+ if ((pdev->revision <= 2) && (vendor_id != PCI_VENDOR_ID_INTEL)) {
+ err(msg_HPC_not_supported);
+ return -ENODEV;
+ }
- ctrl = kzalloc(sizeof(struct controller), GFP_KERNEL);
- if (!ctrl) {
- err("%s : out of memory\n", __func__);
- rc = -ENOMEM;
- goto err_disable_device;
- }
+ /* TODO: This code can be made to support non-Compaq or Intel
+ * subsystem IDs
+ */
+ rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
+ if (rc) {
+ err("%s : pci_read_config_word failed\n", __func__);
+ goto err_disable_device;
+ }
+ dbg("Subsystem Vendor ID: %x\n", subsystem_vid);
+ if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) {
+ err(msg_HPC_non_compaq_or_intel);
+ rc = -ENODEV;
+ goto err_disable_device;
+ }
- rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid);
- if (rc) {
- err("%s : pci_read_config_word failed\n", __func__);
- goto err_free_ctrl;
- }
+ ctrl = kzalloc(sizeof(struct controller), GFP_KERNEL);
+ if (!ctrl) {
+ err("%s : out of memory\n", __func__);
+ rc = -ENOMEM;
+ goto err_disable_device;
+ }
- info("Hot Plug Subsystem Device ID: %x\n", subsystem_deviceid);
-
- /* Set Vendor ID, so it can be accessed later from other functions */
- ctrl->vendor_id = vendor_id;
-
- switch (subsystem_vid) {
- case PCI_VENDOR_ID_COMPAQ:
- if (pdev->revision >= 0x13) { /* CIOBX */
- ctrl->push_flag = 1;
- ctrl->slot_switch_type = 1;
- ctrl->push_button = 1;
- ctrl->pci_config_space = 1;
- ctrl->defeature_PHP = 1;
- ctrl->pcix_support = 1;
- ctrl->pcix_speed_capability = 1;
- pci_read_config_byte(pdev, 0x41, &bus_cap);
- if (bus_cap & 0x80) {
- dbg("bus max supports 133MHz PCI-X\n");
- ctrl->speed_capability = PCI_SPEED_133MHz_PCIX;
- break;
- }
- if (bus_cap & 0x40) {
- dbg("bus max supports 100MHz PCI-X\n");
- ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
- break;
- }
- if (bus_cap & 20) {
- dbg("bus max supports 66MHz PCI-X\n");
- ctrl->speed_capability = PCI_SPEED_66MHz_PCIX;
- break;
- }
- if (bus_cap & 10) {
- dbg("bus max supports 66MHz PCI\n");
- ctrl->speed_capability = PCI_SPEED_66MHz;
- break;
- }
-
- break;
- }
-
- switch (subsystem_deviceid) {
- case PCI_SUB_HPC_ID:
- /* Original 6500/7000 implementation */
- ctrl->slot_switch_type = 1;
- ctrl->speed_capability = PCI_SPEED_33MHz;
- ctrl->push_button = 0;
- ctrl->pci_config_space = 1;
- ctrl->defeature_PHP = 1;
- ctrl->pcix_support = 0;
- ctrl->pcix_speed_capability = 0;
- break;
- case PCI_SUB_HPC_ID2:
- /* First Pushbutton implementation */
- ctrl->push_flag = 1;
- ctrl->slot_switch_type = 1;
- ctrl->speed_capability = PCI_SPEED_33MHz;
- ctrl->push_button = 1;
- ctrl->pci_config_space = 1;
- ctrl->defeature_PHP = 1;
- ctrl->pcix_support = 0;
- ctrl->pcix_speed_capability = 0;
- break;
- case PCI_SUB_HPC_ID_INTC:
- /* Third party (6500/7000) */
- ctrl->slot_switch_type = 1;
- ctrl->speed_capability = PCI_SPEED_33MHz;
- ctrl->push_button = 0;
- ctrl->pci_config_space = 1;
- ctrl->defeature_PHP = 1;
- ctrl->pcix_support = 0;
- ctrl->pcix_speed_capability = 0;
- break;
- case PCI_SUB_HPC_ID3:
- /* First 66 Mhz implementation */
- ctrl->push_flag = 1;
- ctrl->slot_switch_type = 1;
- ctrl->speed_capability = PCI_SPEED_66MHz;
- ctrl->push_button = 1;
- ctrl->pci_config_space = 1;
- ctrl->defeature_PHP = 1;
- ctrl->pcix_support = 0;
- ctrl->pcix_speed_capability = 0;
- break;
- case PCI_SUB_HPC_ID4:
- /* First PCI-X implementation, 100MHz */
- ctrl->push_flag = 1;
- ctrl->slot_switch_type = 1;
- ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
- ctrl->push_button = 1;
- ctrl->pci_config_space = 1;
- ctrl->defeature_PHP = 1;
- ctrl->pcix_support = 1;
- ctrl->pcix_speed_capability = 0;
- break;
- default:
- err(msg_HPC_not_supported);
- rc = -ENODEV;
- goto err_free_ctrl;
- }
- break;
+ rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid);
+ if (rc) {
+ err("%s : pci_read_config_word failed\n", __func__);
+ goto err_free_ctrl;
+ }
- case PCI_VENDOR_ID_INTEL:
- /* Check for speed capability (0=33, 1=66) */
- if (subsystem_deviceid & 0x0001) {
- ctrl->speed_capability = PCI_SPEED_66MHz;
- } else {
- ctrl->speed_capability = PCI_SPEED_33MHz;
- }
-
- /* Check for push button */
- if (subsystem_deviceid & 0x0002) {
- /* no push button */
- ctrl->push_button = 0;
- } else {
- /* push button supported */
- ctrl->push_button = 1;
- }
-
- /* Check for slot switch type (0=mechanical, 1=not mechanical) */
- if (subsystem_deviceid & 0x0004) {
- /* no switch */
- ctrl->slot_switch_type = 0;
- } else {
- /* switch */
- ctrl->slot_switch_type = 1;
- }
-
- /* PHP Status (0=De-feature PHP, 1=Normal operation) */
- if (subsystem_deviceid & 0x0008) {
- ctrl->defeature_PHP = 1; // PHP supported
- } else {
- ctrl->defeature_PHP = 0; // PHP not supported
- }
-
- /* Alternate Base Address Register Interface (0=not supported, 1=supported) */
- if (subsystem_deviceid & 0x0010) {
- ctrl->alternate_base_address = 1; // supported
- } else {
- ctrl->alternate_base_address = 0; // not supported
- }
-
- /* PCI Config Space Index (0=not supported, 1=supported) */
- if (subsystem_deviceid & 0x0020) {
- ctrl->pci_config_space = 1; // supported
- } else {
- ctrl->pci_config_space = 0; // not supported
- }
-
- /* PCI-X support */
- if (subsystem_deviceid & 0x0080) {
- /* PCI-X capable */
- ctrl->pcix_support = 1;
- /* Frequency of operation in PCI-X mode */
- if (subsystem_deviceid & 0x0040) {
- /* 133MHz PCI-X if bit 7 is 1 */
- ctrl->pcix_speed_capability = 1;
- } else {
- /* 100MHz PCI-X if bit 7 is 1 and bit 0 is 0, */
- /* 66MHz PCI-X if bit 7 is 1 and bit 0 is 1 */
- ctrl->pcix_speed_capability = 0;
- }
- } else {
- /* Conventional PCI */
- ctrl->pcix_support = 0;
- ctrl->pcix_speed_capability = 0;
- }
+ info("Hot Plug Subsystem Device ID: %x\n", subsystem_deviceid);
+
+ /* Set Vendor ID, so it can be accessed later from other
+ * functions
+ */
+ ctrl->vendor_id = vendor_id;
+
+ switch (subsystem_vid) {
+ case PCI_VENDOR_ID_COMPAQ:
+ if (pdev->revision >= 0x13) { /* CIOBX */
+ ctrl->push_flag = 1;
+ ctrl->slot_switch_type = 1;
+ ctrl->push_button = 1;
+ ctrl->pci_config_space = 1;
+ ctrl->defeature_PHP = 1;
+ ctrl->pcix_support = 1;
+ ctrl->pcix_speed_capability = 1;
+ pci_read_config_byte(pdev, 0x41, &bus_cap);
+ if (bus_cap & 0x80) {
+ dbg("bus max supports 133MHz PCI-X\n");
+ ctrl->speed_capability = PCI_SPEED_133MHz_PCIX;
break;
+ }
+ if (bus_cap & 0x40) {
+ dbg("bus max supports 100MHz PCI-X\n");
+ ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
+ break;
+ }
+ if (bus_cap & 20) {
+ dbg("bus max supports 66MHz PCI-X\n");
+ ctrl->speed_capability = PCI_SPEED_66MHz_PCIX;
+ break;
+ }
+ if (bus_cap & 10) {
+ dbg("bus max supports 66MHz PCI\n");
+ ctrl->speed_capability = PCI_SPEED_66MHz;
+ break;
+ }
+
+ break;
+ }
- default:
- err(msg_HPC_not_supported);
- rc = -ENODEV;
- goto err_free_ctrl;
+ switch (subsystem_deviceid) {
+ case PCI_SUB_HPC_ID:
+ /* Original 6500/7000 implementation */
+ ctrl->slot_switch_type = 1;
+ ctrl->speed_capability = PCI_SPEED_33MHz;
+ ctrl->push_button = 0;
+ ctrl->pci_config_space = 1;
+ ctrl->defeature_PHP = 1;
+ ctrl->pcix_support = 0;
+ ctrl->pcix_speed_capability = 0;
+ break;
+ case PCI_SUB_HPC_ID2:
+ /* First Pushbutton implementation */
+ ctrl->push_flag = 1;
+ ctrl->slot_switch_type = 1;
+ ctrl->speed_capability = PCI_SPEED_33MHz;
+ ctrl->push_button = 1;
+ ctrl->pci_config_space = 1;
+ ctrl->defeature_PHP = 1;
+ ctrl->pcix_support = 0;
+ ctrl->pcix_speed_capability = 0;
+ break;
+ case PCI_SUB_HPC_ID_INTC:
+ /* Third party (6500/7000) */
+ ctrl->slot_switch_type = 1;
+ ctrl->speed_capability = PCI_SPEED_33MHz;
+ ctrl->push_button = 0;
+ ctrl->pci_config_space = 1;
+ ctrl->defeature_PHP = 1;
+ ctrl->pcix_support = 0;
+ ctrl->pcix_speed_capability = 0;
+ break;
+ case PCI_SUB_HPC_ID3:
+ /* First 66 Mhz implementation */
+ ctrl->push_flag = 1;
+ ctrl->slot_switch_type = 1;
+ ctrl->speed_capability = PCI_SPEED_66MHz;
+ ctrl->push_button = 1;
+ ctrl->pci_config_space = 1;
+ ctrl->defeature_PHP = 1;
+ ctrl->pcix_support = 0;
+ ctrl->pcix_speed_capability = 0;
+ break;
+ case PCI_SUB_HPC_ID4:
+ /* First PCI-X implementation, 100MHz */
+ ctrl->push_flag = 1;
+ ctrl->slot_switch_type = 1;
+ ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
+ ctrl->push_button = 1;
+ ctrl->pci_config_space = 1;
+ ctrl->defeature_PHP = 1;
+ ctrl->pcix_support = 1;
+ ctrl->pcix_speed_capability = 0;
+ break;
+ default:
+ err(msg_HPC_not_supported);
+ rc = -ENODEV;
+ goto err_free_ctrl;
}
+ break;
+
+ case PCI_VENDOR_ID_INTEL:
+ /* Check for speed capability (0=33, 1=66) */
+ if (subsystem_deviceid & 0x0001)
+ ctrl->speed_capability = PCI_SPEED_66MHz;
+ else
+ ctrl->speed_capability = PCI_SPEED_33MHz;
+
+ /* Check for push button */
+ if (subsystem_deviceid & 0x0002)
+ ctrl->push_button = 0;
+ else
+ ctrl->push_button = 1;
+
+ /* Check for slot switch type (0=mechanical, 1=not mechanical) */
+ if (subsystem_deviceid & 0x0004)
+ ctrl->slot_switch_type = 0;
+ else
+ ctrl->slot_switch_type = 1;
+
+ /* PHP Status (0=De-feature PHP, 1=Normal operation) */
+ if (subsystem_deviceid & 0x0008)
+ ctrl->defeature_PHP = 1; /* PHP supported */
+ else
+ ctrl->defeature_PHP = 0; /* PHP not supported */
+
+ /* Alternate Base Address Register Interface
+ * (0=not supported, 1=supported)
+ */
+ if (subsystem_deviceid & 0x0010)
+ ctrl->alternate_base_address = 1;
+ else
+ ctrl->alternate_base_address = 0;
+
+ /* PCI Config Space Index (0=not supported, 1=supported) */
+ if (subsystem_deviceid & 0x0020)
+ ctrl->pci_config_space = 1;
+ else
+ ctrl->pci_config_space = 0;
+
+ /* PCI-X support */
+ if (subsystem_deviceid & 0x0080) {
+ ctrl->pcix_support = 1;
+ if (subsystem_deviceid & 0x0040)
+ /* 133MHz PCI-X if bit 7 is 1 */
+ ctrl->pcix_speed_capability = 1;
+ else
+ /* 100MHz PCI-X if bit 7 is 1 and bit 0 is 0, */
+ /* 66MHz PCI-X if bit 7 is 1 and bit 0 is 1 */
+ ctrl->pcix_speed_capability = 0;
+ } else {
+ /* Conventional PCI */
+ ctrl->pcix_support = 0;
+ ctrl->pcix_speed_capability = 0;
+ }
+ break;
- } else {
+ default:
err(msg_HPC_not_supported);
- return -ENODEV;
+ rc = -ENODEV;
+ goto err_free_ctrl;
}
- // Tell the user that we found one.
+ /* Tell the user that we found one. */
info("Initializing the PCI hot plug controller residing on PCI bus %d\n",
pdev->bus->number);
@@ -1087,7 +1120,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc) {
goto err_free_bus;
}
-
+
dbg("pdev = %p\n", pdev);
dbg("pci resource start %llx\n", (unsigned long long)pci_resource_start(pdev, 0));
dbg("pci resource len %llx\n", (unsigned long long)pci_resource_len(pdev, 0));
@@ -1109,7 +1142,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_free_mem_region;
}
- // Check for 66Mhz operation
+ /* Check for 66Mhz operation */
ctrl->speed = get_controller_speed(ctrl);
@@ -1120,7 +1153,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
*
********************************************************/
- // find the physical slot number of the first hot plug slot
+ /* find the physical slot number of the first hot plug slot */
/* Get slot won't work for devices behind bridges, but
* in this case it will always be called for the "base"
@@ -1137,7 +1170,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_iounmap;
}
- // Store PCI Config Space for all devices on this bus
+ /* Store PCI Config Space for all devices on this bus */
rc = cpqhp_save_config(ctrl, ctrl->bus, readb(ctrl->hpc_reg + SLOT_MASK));
if (rc) {
err("%s: unable to save PCI configuration data, error %d\n",
@@ -1148,7 +1181,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/*
* Get IO, memory, and IRQ resources for new devices
*/
- // The next line is required for cpqhp_find_available_resources
+ /* The next line is required for cpqhp_find_available_resources */
ctrl->interrupt = pdev->irq;
if (ctrl->interrupt < 0x10) {
cpqhp_legacy_mode = 1;
@@ -1182,7 +1215,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
__func__, rc);
goto err_iounmap;
}
-
+
/* Mask all general input interrupts */
writel(0xFFFFFFFFL, ctrl->hpc_reg + INT_MASK);
@@ -1196,12 +1229,14 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_iounmap;
}
- /* Enable Shift Out interrupt and clear it, also enable SERR on power fault */
+ /* Enable Shift Out interrupt and clear it, also enable SERR on power
+ * fault
+ */
temp_word = readw(ctrl->hpc_reg + MISC);
temp_word |= 0x4006;
writew(temp_word, ctrl->hpc_reg + MISC);
- // Changed 05/05/97 to clear all interrupts at start
+ /* Changed 05/05/97 to clear all interrupts at start */
writel(0xFFFFFFFFL, ctrl->hpc_reg + INT_INPUT_CLEAR);
ctrl->ctrl_int_comp = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
@@ -1216,13 +1251,14 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
cpqhp_ctrl_list = ctrl;
}
- // turn off empty slots here unless command line option "ON" set
- // Wait for exclusive access to hardware
+ /* turn off empty slots here unless command line option "ON" set
+ * Wait for exclusive access to hardware
+ */
mutex_lock(&ctrl->crit_sect);
num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
- // find first device number for the ctrl
+ /* find first device number for the ctrl */
device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4;
while (num_of_slots) {
@@ -1234,23 +1270,21 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
hp_slot = func->device - ctrl->slot_device_offset;
dbg("hp_slot: %d\n", hp_slot);
- // We have to save the presence info for these slots
+ /* We have to save the presence info for these slots */
temp_word = ctrl->ctrl_int_comp >> 16;
func->presence_save = (temp_word >> hp_slot) & 0x01;
func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02;
- if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) {
+ if (ctrl->ctrl_int_comp & (0x1L << hp_slot))
func->switch_save = 0;
- } else {
+ else
func->switch_save = 0x10;
- }
- if (!power_mode) {
+ if (!power_mode)
if (!func->is_a_board) {
green_LED_off(ctrl, hp_slot);
slot_disable(ctrl, hp_slot);
}
- }
device++;
num_of_slots--;
@@ -1258,7 +1292,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!power_mode) {
set_SOGO(ctrl);
- // Wait for SOBS to be unset
+ /* Wait for SOBS to be unset */
wait_for_ctrl_irq(ctrl);
}
@@ -1269,7 +1303,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_free_irq;
}
- // Done with exclusive hardware access
+ /* Done with exclusive hardware access */
mutex_unlock(&ctrl->crit_sect);
cpqhp_create_debugfs_files(ctrl);
@@ -1291,77 +1325,6 @@ err_disable_device:
return rc;
}
-
-static int one_time_init(void)
-{
- int loop;
- int retval = 0;
-
- if (initialized)
- return 0;
-
- power_mode = 0;
-
- retval = pci_print_IRQ_route();
- if (retval)
- goto error;
-
- dbg("Initialize + Start the notification mechanism \n");
-
- retval = cpqhp_event_start_thread();
- if (retval)
- goto error;
-
- dbg("Initialize slot lists\n");
- for (loop = 0; loop < 256; loop++) {
- cpqhp_slot_list[loop] = NULL;
- }
-
- // FIXME: We also need to hook the NMI handler eventually.
- // this also needs to be worked with Christoph
- // register_NMI_handler();
-
- // Map rom address
- cpqhp_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN);
- if (!cpqhp_rom_start) {
- err ("Could not ioremap memory region for ROM\n");
- retval = -EIO;
- goto error;
- }
-
- /* Now, map the int15 entry point if we are on compaq specific hardware */
- compaq_nvram_init(cpqhp_rom_start);
-
- /* Map smbios table entry point structure */
- smbios_table = detect_SMBIOS_pointer(cpqhp_rom_start,
- cpqhp_rom_start + ROM_PHY_LEN);
- if (!smbios_table) {
- err ("Could not find the SMBIOS pointer in memory\n");
- retval = -EIO;
- goto error_rom_start;
- }
-
- smbios_start = ioremap(readl(smbios_table + ST_ADDRESS),
- readw(smbios_table + ST_LENGTH));
- if (!smbios_start) {
- err ("Could not ioremap memory region taken from SMBIOS values\n");
- retval = -EIO;
- goto error_smbios_start;
- }
-
- initialized = 1;
-
- return retval;
-
-error_smbios_start:
- iounmap(smbios_start);
-error_rom_start:
- iounmap(cpqhp_rom_start);
-error:
- return retval;
-}
-
-
static void __exit unload_cpqphpd(void)
{
struct pci_func *next;
@@ -1381,10 +1344,10 @@ static void __exit unload_cpqphpd(void)
if (ctrl->hpc_reg) {
u16 misc;
rc = read_slot_enable (ctrl);
-
+
writeb(0, ctrl->hpc_reg + SLOT_SERR);
writel(0xFFFFFFC0L | ~rc, ctrl->hpc_reg + INT_MASK);
-
+
misc = readw(ctrl->hpc_reg + MISC);
misc &= 0xFFFD;
writew(misc, ctrl->hpc_reg + MISC);
@@ -1464,38 +1427,34 @@ static void __exit unload_cpqphpd(void)
}
}
- // Stop the notification mechanism
+ /* Stop the notification mechanism */
if (initialized)
cpqhp_event_stop_thread();
- //unmap the rom address
+ /* unmap the rom address */
if (cpqhp_rom_start)
iounmap(cpqhp_rom_start);
if (smbios_start)
iounmap(smbios_start);
}
-
-
static struct pci_device_id hpcd_pci_tbl[] = {
{
/* handle any PCI Hotplug controller */
.class = ((PCI_CLASS_SYSTEM_PCI_HOTPLUG << 8) | 0x00),
.class_mask = ~0,
-
+
/* no matter who makes it */
.vendor = PCI_ANY_ID,
.device = PCI_ANY_ID,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
-
+
}, { /* end: all zeroes */ }
};
MODULE_DEVICE_TABLE(pci, hpcd_pci_tbl);
-
-
static struct pci_driver cpqhpc_driver = {
.name = "compaq_pci_hotplug",
.id_table = hpcd_pci_tbl,
@@ -1503,8 +1462,6 @@ static struct pci_driver cpqhpc_driver = {
/* remove: cpqhpc_remove_one, */
};
-
-
static int __init cpqhpc_init(void)
{
int result;
@@ -1518,7 +1475,6 @@ static int __init cpqhpc_init(void)
return result;
}
-
static void __exit cpqhpc_cleanup(void)
{
dbg("unload_cpqphpd()\n");
@@ -1529,8 +1485,5 @@ static void __exit cpqhpc_cleanup(void)
cpqhp_shutdown_debugfs();
}
-
module_init(cpqhpc_init);
module_exit(cpqhpc_cleanup);
-
-
diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c
index cc227a8c4b11..2fa47af992a8 100644
--- a/drivers/pci/hotplug/cpqphp_ctrl.c
+++ b/drivers/pci/hotplug/cpqphp_ctrl.c
@@ -81,14 +81,15 @@ static u8 handle_switch_change(u8 change, struct controller * ctrl)
for (hp_slot = 0; hp_slot < 6; hp_slot++) {
if (change & (0x1L << hp_slot)) {
- /**********************************
+ /*
* this one changed.
- **********************************/
+ */
func = cpqhp_slot_find(ctrl->bus,
(hp_slot + ctrl->slot_device_offset), 0);
/* this is the structure that tells the worker thread
- *what to do */
+ * what to do
+ */
taskInfo = &(ctrl->event_queue[ctrl->next_event]);
ctrl->next_event = (ctrl->next_event + 1) % 10;
taskInfo->hp_slot = hp_slot;
@@ -100,17 +101,17 @@ static u8 handle_switch_change(u8 change, struct controller * ctrl)
func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02;
if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) {
- /**********************************
+ /*
* Switch opened
- **********************************/
+ */
func->switch_save = 0;
taskInfo->event_type = INT_SWITCH_OPEN;
} else {
- /**********************************
+ /*
* Switch closed
- **********************************/
+ */
func->switch_save = 0x10;
@@ -131,9 +132,8 @@ static struct slot *cpqhp_find_slot(struct controller *ctrl, u8 device)
{
struct slot *slot = ctrl->slot;
- while (slot && (slot->device != device)) {
+ while (slot && (slot->device != device))
slot = slot->next;
- }
return slot;
}
@@ -152,17 +152,17 @@ static u8 handle_presence_change(u16 change, struct controller * ctrl)
if (!change)
return 0;
- /**********************************
+ /*
* Presence Change
- **********************************/
+ */
dbg("cpqsbd: Presence/Notify input change.\n");
dbg(" Changed bits are 0x%4.4x\n", change );
for (hp_slot = 0; hp_slot < 6; hp_slot++) {
if (change & (0x0101 << hp_slot)) {
- /**********************************
+ /*
* this one changed.
- **********************************/
+ */
func = cpqhp_slot_find(ctrl->bus,
(hp_slot + ctrl->slot_device_offset), 0);
@@ -177,22 +177,23 @@ static u8 handle_presence_change(u16 change, struct controller * ctrl)
return 0;
/* If the switch closed, must be a button
- * If not in button mode, nevermind */
+ * If not in button mode, nevermind
+ */
if (func->switch_save && (ctrl->push_button == 1)) {
temp_word = ctrl->ctrl_int_comp >> 16;
temp_byte = (temp_word >> hp_slot) & 0x01;
temp_byte |= (temp_word >> (hp_slot + 7)) & 0x02;
if (temp_byte != func->presence_save) {
- /**************************************
+ /*
* button Pressed (doesn't do anything)
- **************************************/
+ */
dbg("hp_slot %d button pressed\n", hp_slot);
taskInfo->event_type = INT_BUTTON_PRESS;
} else {
- /**********************************
+ /*
* button Released - TAKE ACTION!!!!
- **********************************/
+ */
dbg("hp_slot %d button released\n", hp_slot);
taskInfo->event_type = INT_BUTTON_RELEASE;
@@ -210,7 +211,8 @@ static u8 handle_presence_change(u16 change, struct controller * ctrl)
}
} else {
/* Switch is open, assume a presence change
- * Save the presence state */
+ * Save the presence state
+ */
temp_word = ctrl->ctrl_int_comp >> 16;
func->presence_save = (temp_word >> hp_slot) & 0x01;
func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02;
@@ -241,17 +243,17 @@ static u8 handle_power_fault(u8 change, struct controller * ctrl)
if (!change)
return 0;
- /**********************************
+ /*
* power fault
- **********************************/
+ */
info("power fault interrupt\n");
for (hp_slot = 0; hp_slot < 6; hp_slot++) {
if (change & (0x01 << hp_slot)) {
- /**********************************
+ /*
* this one changed.
- **********************************/
+ */
func = cpqhp_slot_find(ctrl->bus,
(hp_slot + ctrl->slot_device_offset), 0);
@@ -262,16 +264,16 @@ static u8 handle_power_fault(u8 change, struct controller * ctrl)
rc++;
if (ctrl->ctrl_int_comp & (0x00000100 << hp_slot)) {
- /**********************************
+ /*
* power fault Cleared
- **********************************/
+ */
func->status = 0x00;
taskInfo->event_type = INT_POWER_FAULT_CLEAR;
} else {
- /**********************************
+ /*
* power fault
- **********************************/
+ */
taskInfo->event_type = INT_POWER_FAULT;
if (ctrl->rev < 4) {
@@ -432,13 +434,15 @@ static struct pci_resource *do_pre_bridge_resource_split(struct pci_resource **h
/* If we got here, there the bridge requires some of the resource, but
- * we may be able to split some off of the front */
+ * we may be able to split some off of the front
+ */
node = *head;
if (node->length & (alignment -1)) {
/* this one isn't an aligned length, so we'll make a new entry
- * and split it up. */
+ * and split it up.
+ */
split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
if (!split_node)
@@ -544,10 +548,10 @@ static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size
if (!(*head))
return NULL;
- if ( cpqhp_resource_sort_and_combine(head) )
+ if (cpqhp_resource_sort_and_combine(head))
return NULL;
- if ( sort_by_size(head) )
+ if (sort_by_size(head))
return NULL;
for (node = *head; node; node = node->next) {
@@ -556,7 +560,8 @@ static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size
if (node->base & (size - 1)) {
/* this one isn't base aligned properly
- * so we'll make a new entry and split it up */
+ * so we'll make a new entry and split it up
+ */
temp_dword = (node->base | (size-1)) + 1;
/* Short circuit if adjusted size is too small */
@@ -581,7 +586,8 @@ static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size
/* Don't need to check if too small since we already did */
if (node->length > size) {
/* this one is longer than we need
- * so we'll make a new entry and split it up */
+ * so we'll make a new entry and split it up
+ */
split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
if (!split_node)
@@ -601,7 +607,8 @@ static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size
continue;
/* If we got here, then it is the right size
- * Now take it out of the list and break */
+ * Now take it out of the list and break
+ */
if (*head == node) {
*head = node->next;
} else {
@@ -642,14 +649,16 @@ static struct pci_resource *get_max_resource(struct pci_resource **head, u32 siz
return NULL;
for (max = *head; max; max = max->next) {
- /* If not big enough we could probably just bail,
- * instead we'll continue to the next. */
+ /* If not big enough we could probably just bail,
+ * instead we'll continue to the next.
+ */
if (max->length < size)
continue;
if (max->base & (size - 1)) {
/* this one isn't base aligned properly
- * so we'll make a new entry and split it up */
+ * so we'll make a new entry and split it up
+ */
temp_dword = (max->base | (size-1)) + 1;
/* Short circuit if adjusted size is too small */
@@ -672,7 +681,8 @@ static struct pci_resource *get_max_resource(struct pci_resource **head, u32 siz
if ((max->base + max->length) & (size - 1)) {
/* this one isn't end aligned properly at the top
- * so we'll make a new entry and split it up */
+ * so we'll make a new entry and split it up
+ */
split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
if (!split_node)
@@ -744,7 +754,8 @@ static struct pci_resource *get_resource(struct pci_resource **head, u32 size)
if (node->base & (size - 1)) {
dbg("%s: not aligned\n", __func__);
/* this one isn't base aligned properly
- * so we'll make a new entry and split it up */
+ * so we'll make a new entry and split it up
+ */
temp_dword = (node->base | (size-1)) + 1;
/* Short circuit if adjusted size is too small */
@@ -769,7 +780,8 @@ static struct pci_resource *get_resource(struct pci_resource **head, u32 size)
if (node->length > size) {
dbg("%s: too big\n", __func__);
/* this one is longer than we need
- * so we'll make a new entry and split it up */
+ * so we'll make a new entry and split it up
+ */
split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
if (!split_node)
@@ -886,19 +898,19 @@ irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data)
u32 Diff;
u32 temp_dword;
-
+
misc = readw(ctrl->hpc_reg + MISC);
- /***************************************
+ /*
* Check to see if it was our interrupt
- ***************************************/
+ */
if (!(misc & 0x000C)) {
return IRQ_NONE;
}
if (misc & 0x0004) {
- /**********************************
+ /*
* Serial Output interrupt Pending
- **********************************/
+ */
/* Clear the interrupt */
misc |= 0x0004;
@@ -961,11 +973,8 @@ struct pci_func *cpqhp_slot_create(u8 busnumber)
struct pci_func *next;
new_slot = kzalloc(sizeof(*new_slot), GFP_KERNEL);
- if (new_slot == NULL) {
- /* I'm not dead yet!
- * You will be. */
+ if (new_slot == NULL)
return new_slot;
- }
new_slot->next = NULL;
new_slot->configured = 1;
@@ -996,10 +1005,8 @@ static int slot_remove(struct pci_func * old_slot)
return 1;
next = cpqhp_slot_list[old_slot->bus];
-
- if (next == NULL) {
+ if (next == NULL)
return 1;
- }
if (next == old_slot) {
cpqhp_slot_list[old_slot->bus] = old_slot->next;
@@ -1008,9 +1015,8 @@ static int slot_remove(struct pci_func * old_slot)
return 0;
}
- while ((next->next != old_slot) && (next->next != NULL)) {
+ while ((next->next != old_slot) && (next->next != NULL))
next = next->next;
- }
if (next->next == old_slot) {
next->next = old_slot->next;
@@ -1040,9 +1046,8 @@ static int bridge_slot_remove(struct pci_func *bridge)
for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) {
next = cpqhp_slot_list[tempBus];
- while (!slot_remove(next)) {
+ while (!slot_remove(next))
next = cpqhp_slot_list[tempBus];
- }
}
next = cpqhp_slot_list[bridge->bus];
@@ -1130,39 +1135,43 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_
u8 slot_power = readb(ctrl->hpc_reg + SLOT_POWER);
u16 reg16;
u32 leds = readl(ctrl->hpc_reg + LED_CONTROL);
-
+
if (ctrl->speed == adapter_speed)
return 0;
-
+
/* We don't allow freq/mode changes if we find another adapter running
- * in another slot on this controller */
+ * in another slot on this controller
+ */
for(slot = ctrl->slot; slot; slot = slot->next) {
- if (slot->device == (hp_slot + ctrl->slot_device_offset))
+ if (slot->device == (hp_slot + ctrl->slot_device_offset))
continue;
if (!slot->hotplug_slot || !slot->hotplug_slot->info)
continue;
- if (slot->hotplug_slot->info->adapter_status == 0)
+ if (slot->hotplug_slot->info->adapter_status == 0)
continue;
/* If another adapter is running on the same segment but at a
* lower speed/mode, we allow the new adapter to function at
- * this rate if supported */
- if (ctrl->speed < adapter_speed)
+ * this rate if supported
+ */
+ if (ctrl->speed < adapter_speed)
return 0;
return 1;
}
-
+
/* If the controller doesn't support freq/mode changes and the
- * controller is running at a higher mode, we bail */
+ * controller is running at a higher mode, we bail
+ */
if ((ctrl->speed > adapter_speed) && (!ctrl->pcix_speed_capability))
return 1;
-
+
/* But we allow the adapter to run at a lower rate if possible */
if ((ctrl->speed < adapter_speed) && (!ctrl->pcix_speed_capability))
return 0;
/* We try to set the max speed supported by both the adapter and
- * controller */
+ * controller
+ */
if (ctrl->speed_capability < adapter_speed) {
if (ctrl->speed == ctrl->speed_capability)
return 0;
@@ -1171,22 +1180,22 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_
writel(0x0L, ctrl->hpc_reg + LED_CONTROL);
writeb(0x00, ctrl->hpc_reg + SLOT_ENABLE);
-
- set_SOGO(ctrl);
+
+ set_SOGO(ctrl);
wait_for_ctrl_irq(ctrl);
-
+
if (adapter_speed != PCI_SPEED_133MHz_PCIX)
reg = 0xF5;
else
- reg = 0xF4;
+ reg = 0xF4;
pci_write_config_byte(ctrl->pci_dev, 0x41, reg);
-
+
reg16 = readw(ctrl->hpc_reg + NEXT_CURR_FREQ);
reg16 &= ~0x000F;
switch(adapter_speed) {
- case(PCI_SPEED_133MHz_PCIX):
+ case(PCI_SPEED_133MHz_PCIX):
reg = 0x75;
- reg16 |= 0xB;
+ reg16 |= 0xB;
break;
case(PCI_SPEED_100MHz_PCIX):
reg = 0x74;
@@ -1203,48 +1212,48 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_
default: /* 33MHz PCI 2.2 */
reg = 0x71;
break;
-
+
}
reg16 |= 0xB << 12;
writew(reg16, ctrl->hpc_reg + NEXT_CURR_FREQ);
-
- mdelay(5);
-
+
+ mdelay(5);
+
/* Reenable interrupts */
writel(0, ctrl->hpc_reg + INT_MASK);
- pci_write_config_byte(ctrl->pci_dev, 0x41, reg);
-
+ pci_write_config_byte(ctrl->pci_dev, 0x41, reg);
+
/* Restart state machine */
reg = ~0xF;
pci_read_config_byte(ctrl->pci_dev, 0x43, &reg);
pci_write_config_byte(ctrl->pci_dev, 0x43, reg);
-
+
/* Only if mode change...*/
if (((ctrl->speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) ||
((ctrl->speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz)))
set_SOGO(ctrl);
-
+
wait_for_ctrl_irq(ctrl);
mdelay(1100);
-
+
/* Restore LED/Slot state */
writel(leds, ctrl->hpc_reg + LED_CONTROL);
writeb(slot_power, ctrl->hpc_reg + SLOT_ENABLE);
-
+
set_SOGO(ctrl);
wait_for_ctrl_irq(ctrl);
ctrl->speed = adapter_speed;
slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
- info("Successfully changed frequency/mode for adapter in slot %d\n",
+ info("Successfully changed frequency/mode for adapter in slot %d\n",
slot->number);
return 0;
}
-/* the following routines constitute the bulk of the
- hotplug controller logic
+/* the following routines constitute the bulk of the
+ * hotplug controller logic
*/
@@ -1268,17 +1277,17 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
hp_slot = func->device - ctrl->slot_device_offset;
- if (readl(ctrl->hpc_reg + INT_INPUT_CLEAR) & (0x01L << hp_slot)) {
- /**********************************
- * The switch is open.
- **********************************/
+ /*
+ * The switch is open.
+ */
+ if (readl(ctrl->hpc_reg + INT_INPUT_CLEAR) & (0x01L << hp_slot))
rc = INTERLOCK_OPEN;
- } else if (is_slot_enabled (ctrl, hp_slot)) {
- /**********************************
- * The board is already on
- **********************************/
+ /*
+ * The board is already on
+ */
+ else if (is_slot_enabled (ctrl, hp_slot))
rc = CARD_FUNCTIONING;
- } else {
+ else {
mutex_lock(&ctrl->crit_sect);
/* turn on board without attaching to the bus */
@@ -1299,7 +1308,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
/* Wait for SOBS to be unset */
wait_for_ctrl_irq (ctrl);
-
+
adapter_speed = get_adapter_speed(ctrl, hp_slot);
if (ctrl->speed != adapter_speed)
if (set_controller_speed(ctrl, adapter_speed, hp_slot))
@@ -1352,7 +1361,8 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
* Get slot won't work for devices behind
* bridges, but in this case it will always be
* called for the "base" bus/dev/func of an
- * adapter. */
+ * adapter.
+ */
mutex_lock(&ctrl->crit_sect);
@@ -1377,7 +1387,8 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
* Get slot won't work for devices behind bridges, but
* in this case it will always be called for the "base"
- * bus/dev/func of an adapter. */
+ * bus/dev/func of an adapter.
+ */
mutex_lock(&ctrl->crit_sect);
@@ -1434,7 +1445,8 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
wait_for_ctrl_irq (ctrl);
/* Change bits in slot power register to force another shift out
- * NOTE: this is to work around the timer bug */
+ * NOTE: this is to work around the timer bug
+ */
temp_byte = readb(ctrl->hpc_reg + SLOT_POWER);
writeb(0x00, ctrl->hpc_reg + SLOT_POWER);
writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER);
@@ -1443,12 +1455,12 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
/* Wait for SOBS to be unset */
wait_for_ctrl_irq (ctrl);
-
+
adapter_speed = get_adapter_speed(ctrl, hp_slot);
if (ctrl->speed != adapter_speed)
if (set_controller_speed(ctrl, adapter_speed, hp_slot))
rc = WRONG_BUS_FREQUENCY;
-
+
/* turn off board without attaching to the bus */
disable_slot_power (ctrl, hp_slot);
@@ -1461,7 +1473,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
if (rc)
return rc;
-
+
p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
/* turn on board and blink green LED */
@@ -1521,7 +1533,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
}
/* All F's is an empty slot or an invalid board */
- if (temp_register != 0xFFFFFFFF) { /* Check for a board in the slot */
+ if (temp_register != 0xFFFFFFFF) {
res_lists.io_head = ctrl->io_head;
res_lists.mem_head = ctrl->mem_head;
res_lists.p_mem_head = ctrl->p_mem_head;
@@ -1570,9 +1582,8 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
index = 0;
do {
new_slot = cpqhp_slot_find(ctrl->bus, func->device, index++);
- if (new_slot && !new_slot->pci_dev) {
+ if (new_slot && !new_slot->pci_dev)
cpqhp_configure_device(ctrl, new_slot);
- }
} while (new_slot);
mutex_lock(&ctrl->crit_sect);
@@ -1859,12 +1870,12 @@ static void interrupt_event_handler(struct controller *ctrl)
info(msg_button_on, p_slot->number);
}
mutex_lock(&ctrl->crit_sect);
-
+
dbg("blink green LED and turn off amber\n");
-
+
amber_LED_off (ctrl, hp_slot);
green_LED_blink (ctrl, hp_slot);
-
+
set_SOGO(ctrl);
/* Wait for SOBS to be unset */
@@ -1958,7 +1969,7 @@ void cpqhp_pushbutton_thread(unsigned long slot)
if (cpqhp_process_SI(ctrl, func) != 0) {
amber_LED_on(ctrl, hp_slot);
green_LED_off(ctrl, hp_slot);
-
+
set_SOGO(ctrl);
/* Wait for SOBS to be unset */
@@ -2079,7 +2090,7 @@ int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func)
struct pci_bus *pci_bus = ctrl->pci_bus;
int physical_slot=0;
- device = func->device;
+ device = func->device;
func = cpqhp_slot_find(ctrl->bus, device, index++);
p_slot = cpqhp_find_slot(ctrl, device);
if (p_slot) {
@@ -2113,9 +2124,8 @@ int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func)
/* If the VGA Enable bit is set, remove isn't
* supported */
- if (BCR & PCI_BRIDGE_CTL_VGA) {
+ if (BCR & PCI_BRIDGE_CTL_VGA)
rc = REMOVE_NOT_SUPPORTED;
- }
}
}
@@ -2183,67 +2193,67 @@ int cpqhp_hardware_test(struct controller *ctrl, int test_num)
num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0f;
switch (test_num) {
- case 1:
- /* Do stuff here! */
-
- /* Do that funky LED thing */
- /* so we can restore them later */
- save_LED = readl(ctrl->hpc_reg + LED_CONTROL);
- work_LED = 0x01010101;
- switch_leds(ctrl, num_of_slots, &work_LED, 0);
- switch_leds(ctrl, num_of_slots, &work_LED, 1);
- switch_leds(ctrl, num_of_slots, &work_LED, 0);
- switch_leds(ctrl, num_of_slots, &work_LED, 1);
-
- work_LED = 0x01010000;
- writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
- switch_leds(ctrl, num_of_slots, &work_LED, 0);
- switch_leds(ctrl, num_of_slots, &work_LED, 1);
- work_LED = 0x00000101;
- writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
- switch_leds(ctrl, num_of_slots, &work_LED, 0);
- switch_leds(ctrl, num_of_slots, &work_LED, 1);
+ case 1:
+ /* Do stuff here! */
+
+ /* Do that funky LED thing */
+ /* so we can restore them later */
+ save_LED = readl(ctrl->hpc_reg + LED_CONTROL);
+ work_LED = 0x01010101;
+ switch_leds(ctrl, num_of_slots, &work_LED, 0);
+ switch_leds(ctrl, num_of_slots, &work_LED, 1);
+ switch_leds(ctrl, num_of_slots, &work_LED, 0);
+ switch_leds(ctrl, num_of_slots, &work_LED, 1);
+
+ work_LED = 0x01010000;
+ writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+ switch_leds(ctrl, num_of_slots, &work_LED, 0);
+ switch_leds(ctrl, num_of_slots, &work_LED, 1);
+ work_LED = 0x00000101;
+ writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+ switch_leds(ctrl, num_of_slots, &work_LED, 0);
+ switch_leds(ctrl, num_of_slots, &work_LED, 1);
+
+ work_LED = 0x01010000;
+ writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+ for (loop = 0; loop < num_of_slots; loop++) {
+ set_SOGO(ctrl);
- work_LED = 0x01010000;
- writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
- for (loop = 0; loop < num_of_slots; loop++) {
- set_SOGO(ctrl);
+ /* Wait for SOGO interrupt */
+ wait_for_ctrl_irq (ctrl);
- /* Wait for SOGO interrupt */
- wait_for_ctrl_irq (ctrl);
+ /* Get ready for next iteration */
+ long_delay((3*HZ)/10);
+ work_LED = work_LED >> 16;
+ writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
- /* Get ready for next iteration */
- long_delay((3*HZ)/10);
- work_LED = work_LED >> 16;
- writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
-
- set_SOGO(ctrl);
+ set_SOGO(ctrl);
- /* Wait for SOGO interrupt */
- wait_for_ctrl_irq (ctrl);
+ /* Wait for SOGO interrupt */
+ wait_for_ctrl_irq (ctrl);
- /* Get ready for next iteration */
- long_delay((3*HZ)/10);
- work_LED = work_LED << 16;
- writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
- work_LED = work_LED << 1;
- writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
- }
+ /* Get ready for next iteration */
+ long_delay((3*HZ)/10);
+ work_LED = work_LED << 16;
+ writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+ work_LED = work_LED << 1;
+ writel(work_LED, ctrl->hpc_reg + LED_CONTROL);
+ }
- /* put it back the way it was */
- writel(save_LED, ctrl->hpc_reg + LED_CONTROL);
+ /* put it back the way it was */
+ writel(save_LED, ctrl->hpc_reg + LED_CONTROL);
- set_SOGO(ctrl);
+ set_SOGO(ctrl);
- /* Wait for SOBS to be unset */
- wait_for_ctrl_irq (ctrl);
- break;
- case 2:
- /* Do other stuff here! */
- break;
- case 3:
- /* and more... */
- break;
+ /* Wait for SOBS to be unset */
+ wait_for_ctrl_irq (ctrl);
+ break;
+ case 2:
+ /* Do other stuff here! */
+ break;
+ case 3:
+ /* and more... */
+ break;
}
return 0;
}
@@ -2312,9 +2322,9 @@ static u32 configure_new_device(struct controller * ctrl, struct pci_func * func
while ((function < max_functions) && (!stop_it)) {
pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID);
- if (ID == 0xFFFFFFFF) { /* There's nothing there. */
+ if (ID == 0xFFFFFFFF) {
function++;
- } else { /* There's something there */
+ } else {
/* Setup slot structure. */
new_slot = cpqhp_slot_create(func->bus);
@@ -2339,8 +2349,8 @@ static u32 configure_new_device(struct controller * ctrl, struct pci_func * func
/*
- Configuration logic that involves the hotplug data structures and
- their bookkeeping
+ * Configuration logic that involves the hotplug data structures and
+ * their bookkeeping
*/
@@ -2393,7 +2403,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
if (rc)
return rc;
- if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
+ if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
/* set Primary bus */
dbg("set Primary bus = %d\n", func->bus);
rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus);
@@ -2484,7 +2494,8 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
temp_resources.irqs = &irqs;
/* Make copies of the nodes we are going to pass down so that
- * if there is a problem,we can just use these to free resources */
+ * if there is a problem,we can just use these to free resources
+ */
hold_bus_node = kmalloc(sizeof(*hold_bus_node), GFP_KERNEL);
hold_IO_node = kmalloc(sizeof(*hold_IO_node), GFP_KERNEL);
hold_mem_node = kmalloc(sizeof(*hold_mem_node), GFP_KERNEL);
@@ -2556,7 +2567,8 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
temp_word = (p_mem_node->base + p_mem_node->length - 1) >> 16;
rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
- /* Adjust this to compensate for extra adjustment in first loop */
+ /* Adjust this to compensate for extra adjustment in first loop
+ */
irqs.barber_pole--;
rc = 0;
@@ -2917,27 +2929,26 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
} /* End of base register loop */
if (cpqhp_legacy_mode) {
/* Figure out which interrupt pin this function uses */
- rc = pci_bus_read_config_byte (pci_bus, devfn,
+ rc = pci_bus_read_config_byte (pci_bus, devfn,
PCI_INTERRUPT_PIN, &temp_byte);
/* If this function needs an interrupt and we are behind
* a bridge and the pin is tied to something that's
* alread mapped, set this one the same */
- if (temp_byte && resources->irqs &&
- (resources->irqs->valid_INT &
+ if (temp_byte && resources->irqs &&
+ (resources->irqs->valid_INT &
(0x01 << ((temp_byte + resources->irqs->barber_pole - 1) & 0x03)))) {
/* We have to share with something already set up */
- IRQ = resources->irqs->interrupt[(temp_byte +
+ IRQ = resources->irqs->interrupt[(temp_byte +
resources->irqs->barber_pole - 1) & 0x03];
} else {
/* Program IRQ based on card type */
rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
- if (class_code == PCI_BASE_CLASS_STORAGE) {
+ if (class_code == PCI_BASE_CLASS_STORAGE)
IRQ = cpqhp_disk_irq;
- } else {
+ else
IRQ = cpqhp_nic_irq;
- }
}
/* IRQ Line */
diff --git a/drivers/pci/hotplug/cpqphp_nvram.c b/drivers/pci/hotplug/cpqphp_nvram.c
index cb174888002b..76ba8a1c774d 100644
--- a/drivers/pci/hotplug/cpqphp_nvram.c
+++ b/drivers/pci/hotplug/cpqphp_nvram.c
@@ -94,12 +94,13 @@ static u8 evbuffer[1024];
static void __iomem *compaq_int15_entry_point;
-static spinlock_t int15_lock; /* lock for ordering int15_bios_call() */
+/* lock for ordering int15_bios_call() */
+static spinlock_t int15_lock;
/* This is a series of function that deals with
- setting & getting the hotplug resource table in some environment variable.
-*/
+ * setting & getting the hotplug resource table in some environment variable.
+ */
/*
* We really shouldn't be doing this unless there is a _very_ good reason to!!!
@@ -113,7 +114,7 @@ static u32 add_byte( u32 **p_buffer, u8 value, u32 *used, u32 *avail)
if ((*used + 1) > *avail)
return(1);
-
+
*((u8*)*p_buffer) = value;
tByte = (u8**)p_buffer;
(*tByte)++;
@@ -170,10 +171,10 @@ static u32 access_EV (u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size)
unsigned long flags;
int op = operation;
int ret_val;
-
+
if (!compaq_int15_entry_point)
return -ENODEV;
-
+
spin_lock_irqsave(&int15_lock, flags);
__asm__ (
"xorl %%ebx,%%ebx\n" \
@@ -187,7 +188,7 @@ static u32 access_EV (u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size)
"D" (buffer), "m" (compaq_int15_entry_point)
: "%ebx", "%edx");
spin_unlock_irqrestore(&int15_lock, flags);
-
+
return((ret_val & 0xFF00) >> 8);
}
@@ -210,14 +211,16 @@ static int load_HRT (void __iomem *rom_start)
available = 1024;
- // Now load the EV
+ /* Now load the EV */
temp_dword = available;
rc = access_EV(READ_EV, "CQTHPS", evbuffer, &temp_dword);
evbuffer_length = temp_dword;
- // We're maintaining the resource lists so write FF to invalidate old info
+ /* We're maintaining the resource lists so write FF to invalidate old
+ * info
+ */
temp_dword = 1;
rc = access_EV(WRITE_EV, "CQTHPS", &temp_byte, &temp_dword);
@@ -263,13 +266,13 @@ static u32 store_HRT (void __iomem *rom_start)
p_EV_header = (struct ev_hrt_header *) pFill;
ctrl = cpqhp_ctrl_list;
-
- // The revision of this structure
+
+ /* The revision of this structure */
rc = add_byte( &pFill, 1 + ctrl->push_flag, &usedbytes, &available);
if (rc)
return(rc);
- // The number of controllers
+ /* The number of controllers */
rc = add_byte( &pFill, 1, &usedbytes, &available);
if (rc)
return(rc);
@@ -279,27 +282,27 @@ static u32 store_HRT (void __iomem *rom_start)
numCtrl++;
- // The bus number
+ /* The bus number */
rc = add_byte( &pFill, ctrl->bus, &usedbytes, &available);
if (rc)
return(rc);
- // The device Number
+ /* The device Number */
rc = add_byte( &pFill, PCI_SLOT(ctrl->pci_dev->devfn), &usedbytes, &available);
if (rc)
return(rc);
- // The function Number
+ /* The function Number */
rc = add_byte( &pFill, PCI_FUNC(ctrl->pci_dev->devfn), &usedbytes, &available);
if (rc)
return(rc);
- // Skip the number of available entries
+ /* Skip the number of available entries */
rc = add_dword( &pFill, 0, &usedbytes, &available);
if (rc)
return(rc);
- // Figure out memory Available
+ /* Figure out memory Available */
resNode = ctrl->mem_head;
@@ -308,12 +311,12 @@ static u32 store_HRT (void __iomem *rom_start)
while (resNode) {
loop ++;
- // base
+ /* base */
rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
if (rc)
return(rc);
- // length
+ /* length */
rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
if (rc)
return(rc);
@@ -321,10 +324,10 @@ static u32 store_HRT (void __iomem *rom_start)
resNode = resNode->next;
}
- // Fill in the number of entries
+ /* Fill in the number of entries */
p_ev_ctrl->mem_avail = loop;
- // Figure out prefetchable memory Available
+ /* Figure out prefetchable memory Available */
resNode = ctrl->p_mem_head;
@@ -333,12 +336,12 @@ static u32 store_HRT (void __iomem *rom_start)
while (resNode) {
loop ++;
- // base
+ /* base */
rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
if (rc)
return(rc);
- // length
+ /* length */
rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
if (rc)
return(rc);
@@ -346,10 +349,10 @@ static u32 store_HRT (void __iomem *rom_start)
resNode = resNode->next;
}
- // Fill in the number of entries
+ /* Fill in the number of entries */
p_ev_ctrl->p_mem_avail = loop;
- // Figure out IO Available
+ /* Figure out IO Available */
resNode = ctrl->io_head;
@@ -358,12 +361,12 @@ static u32 store_HRT (void __iomem *rom_start)
while (resNode) {
loop ++;
- // base
+ /* base */
rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
if (rc)
return(rc);
- // length
+ /* length */
rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
if (rc)
return(rc);
@@ -371,10 +374,10 @@ static u32 store_HRT (void __iomem *rom_start)
resNode = resNode->next;
}
- // Fill in the number of entries
+ /* Fill in the number of entries */
p_ev_ctrl->io_avail = loop;
- // Figure out bus Available
+ /* Figure out bus Available */
resNode = ctrl->bus_head;
@@ -383,12 +386,12 @@ static u32 store_HRT (void __iomem *rom_start)
while (resNode) {
loop ++;
- // base
+ /* base */
rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
if (rc)
return(rc);
- // length
+ /* length */
rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
if (rc)
return(rc);
@@ -396,15 +399,15 @@ static u32 store_HRT (void __iomem *rom_start)
resNode = resNode->next;
}
- // Fill in the number of entries
+ /* Fill in the number of entries */
p_ev_ctrl->bus_avail = loop;
ctrl = ctrl->next;
}
-
+
p_EV_header->num_of_ctrl = numCtrl;
- // Now store the EV
+ /* Now store the EV */
temp_dword = usedbytes;
@@ -449,20 +452,21 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
struct ev_hrt_header *p_EV_header;
if (!evbuffer_init) {
- // Read the resource list information in from NVRAM
+ /* Read the resource list information in from NVRAM */
if (load_HRT(rom_start))
memset (evbuffer, 0, 1024);
evbuffer_init = 1;
}
- // If we saved information in NVRAM, use it now
+ /* If we saved information in NVRAM, use it now */
p_EV_header = (struct ev_hrt_header *) evbuffer;
- // The following code is for systems where version 1.0 of this
- // driver has been loaded, but doesn't support the hardware.
- // In that case, the driver would incorrectly store something
- // in NVRAM.
+ /* The following code is for systems where version 1.0 of this
+ * driver has been loaded, but doesn't support the hardware.
+ * In that case, the driver would incorrectly store something
+ * in NVRAM.
+ */
if ((p_EV_header->Version == 2) ||
((p_EV_header->Version == 1) && !ctrl->push_flag)) {
p_byte = &(p_EV_header->next);
@@ -479,7 +483,7 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
function = p_ev_ctrl->function;
while ((bus != ctrl->bus) ||
- (device != PCI_SLOT(ctrl->pci_dev->devfn)) ||
+ (device != PCI_SLOT(ctrl->pci_dev->devfn)) ||
(function != PCI_FUNC(ctrl->pci_dev->devfn))) {
nummem = p_ev_ctrl->mem_avail;
numpmem = p_ev_ctrl->p_mem_avail;
@@ -491,7 +495,7 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
if (p_byte > ((u8*)p_EV_header + evbuffer_length))
return 2;
- // Skip forward to the next entry
+ /* Skip forward to the next entry */
p_byte += (nummem + numpmem + numio + numbus) * 8;
if (p_byte > ((u8*)p_EV_header + evbuffer_length))
@@ -629,8 +633,9 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
ctrl->bus_head = bus_node;
}
- // If all of the following fail, we don't have any resources for
- // hot plug add
+ /* If all of the following fail, we don't have any resources for
+ * hot plug add
+ */
rc = 1;
rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
@@ -640,14 +645,14 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
if (rc)
return(rc);
} else {
- if ((evbuffer[0] != 0) && (!ctrl->push_flag))
+ if ((evbuffer[0] != 0) && (!ctrl->push_flag))
return 1;
}
return 0;
}
-
+
int compaq_nvram_store (void __iomem *rom_start)
{
int rc = 1;
diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c
index 6c0ed0fcb8ee..6173b9a4544e 100644
--- a/drivers/pci/hotplug/cpqphp_pci.c
+++ b/drivers/pci/hotplug/cpqphp_pci.c
@@ -37,7 +37,6 @@
#include "../pci.h"
#include "cpqphp.h"
#include "cpqphp_nvram.h"
-#include <asm/pci_x86.h>
u8 cpqhp_nic_irq;
@@ -82,14 +81,14 @@ static void __iomem *detect_HRT_floating_pointer(void __iomem *begin, void __iom
}
-int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)
+int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)
{
unsigned char bus;
struct pci_bus *child;
int num;
if (func->pci_dev == NULL)
- func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
+ func->pci_dev = pci_get_bus_and_slot(func->bus,PCI_DEVFN(func->device, func->function));
/* No pci device, we need to create it then */
if (func->pci_dev == NULL) {
@@ -99,7 +98,7 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)
if (num)
pci_bus_add_devices(ctrl->pci_dev->bus);
- func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
+ func->pci_dev = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, func->function));
if (func->pci_dev == NULL) {
dbg("ERROR: pci_dev still null\n");
return 0;
@@ -112,20 +111,24 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)
pci_do_scan_bus(child);
}
+ pci_dev_put(func->pci_dev);
+
return 0;
}
-int cpqhp_unconfigure_device(struct pci_func* func)
+int cpqhp_unconfigure_device(struct pci_func* func)
{
int j;
-
+
dbg("%s: bus/dev/func = %x/%x/%x\n", __func__, func->bus, func->device, func->function);
for (j=0; j<8 ; j++) {
- struct pci_dev* temp = pci_find_slot(func->bus, PCI_DEVFN(func->device, j));
- if (temp)
+ struct pci_dev* temp = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, j));
+ if (temp) {
+ pci_dev_put(temp);
pci_remove_bus_device(temp);
+ }
}
return 0;
}
@@ -178,32 +181,22 @@ int cpqhp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
if (!rc)
return !rc;
- // set the Edge Level Control Register (ELCR)
+ /* set the Edge Level Control Register (ELCR) */
temp_word = inb(0x4d0);
temp_word |= inb(0x4d1) << 8;
temp_word |= 0x01 << irq_num;
- // This should only be for x86 as it sets the Edge Level Control Register
- outb((u8) (temp_word & 0xFF), 0x4d0);
- outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1);
- rc = 0;
- }
+ /* This should only be for x86 as it sets the Edge Level
+ * Control Register
+ */
+ outb((u8) (temp_word & 0xFF), 0x4d0); outb((u8) ((temp_word &
+ 0xFF00) >> 8), 0x4d1); rc = 0; }
return rc;
}
-/*
- * WTF??? This function isn't in the code, yet a function calls it, but the
- * compiler optimizes it away? strange. Here as a placeholder to keep the
- * compiler happy.
- */
-static int PCI_ScanBusNonBridge (u8 bus, u8 device)
-{
- return 0;
-}
-
static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 * dev_num)
{
u16 tdevice;
@@ -213,11 +206,11 @@ static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 * dev
ctrl->pci_bus->number = bus_num;
for (tdevice = 0; tdevice < 0xFF; tdevice++) {
- //Scan for access first
+ /* Scan for access first */
if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1)
continue;
dbg("Looking for nonbridge bus_num %d dev_num %d\n", bus_num, tdevice);
- //Yep we got one. Not a bridge ?
+ /* Yep we got one. Not a bridge ? */
if ((work >> 8) != PCI_TO_PCI_BRIDGE_CLASS) {
*dev_num = tdevice;
dbg("found it !\n");
@@ -225,16 +218,16 @@ static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 * dev
}
}
for (tdevice = 0; tdevice < 0xFF; tdevice++) {
- //Scan for access first
+ /* Scan for access first */
if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1)
continue;
dbg("Looking for bridge bus_num %d dev_num %d\n", bus_num, tdevice);
- //Yep we got one. bridge ?
+ /* Yep we got one. bridge ? */
if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(tdevice, 0), PCI_SECONDARY_BUS, &tbus);
+ /* XXX: no recursion, wtf? */
dbg("Recurse on bus_num %d tdevice %d\n", tbus, tdevice);
- if (PCI_ScanBusNonBridge(tbus, tdevice) == 0)
- return 0;
+ return 0;
}
}
@@ -244,39 +237,23 @@ static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 * dev
static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num, u8 slot, u8 nobridge)
{
- struct irq_routing_table *PCIIRQRoutingInfoLength;
- long len;
- long loop;
+ int loop, len;
u32 work;
-
u8 tbus, tdevice, tslot;
- PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table();
- if (!PCIIRQRoutingInfoLength)
- return -1;
-
- len = (PCIIRQRoutingInfoLength->size -
- sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
- // Make sure I got at least one entry
- if (len == 0) {
- kfree(PCIIRQRoutingInfoLength );
- return -1;
- }
-
+ len = cpqhp_routing_table_length();
for (loop = 0; loop < len; ++loop) {
- tbus = PCIIRQRoutingInfoLength->slots[loop].bus;
- tdevice = PCIIRQRoutingInfoLength->slots[loop].devfn;
- tslot = PCIIRQRoutingInfoLength->slots[loop].slot;
+ tbus = cpqhp_routing_table->slots[loop].bus;
+ tdevice = cpqhp_routing_table->slots[loop].devfn;
+ tslot = cpqhp_routing_table->slots[loop].slot;
if (tslot == slot) {
*bus_num = tbus;
*dev_num = tdevice;
ctrl->pci_bus->number = tbus;
pci_bus_read_config_dword (ctrl->pci_bus, *dev_num, PCI_VENDOR_ID, &work);
- if (!nobridge || (work == 0xffffffff)) {
- kfree(PCIIRQRoutingInfoLength );
+ if (!nobridge || (work == 0xffffffff))
return 0;
- }
dbg("bus_num %d devfn %d\n", *bus_num, *dev_num);
pci_bus_read_config_dword (ctrl->pci_bus, *dev_num, PCI_CLASS_REVISION, &work);
@@ -287,28 +264,26 @@ static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num
dbg("Scan bus for Non Bridge: bus %d\n", tbus);
if (PCI_ScanBusForNonBridge(ctrl, tbus, dev_num) == 0) {
*bus_num = tbus;
- kfree(PCIIRQRoutingInfoLength );
return 0;
}
- } else {
- kfree(PCIIRQRoutingInfoLength );
+ } else
return 0;
- }
-
}
}
- kfree(PCIIRQRoutingInfoLength );
return -1;
}
int cpqhp_get_bus_dev (struct controller *ctrl, u8 * bus_num, u8 * dev_num, u8 slot)
{
- return PCI_GetBusDevHelper(ctrl, bus_num, dev_num, slot, 0); //plain (bridges allowed)
+ /* plain (bridges allowed) */
+ return PCI_GetBusDevHelper(ctrl, bus_num, dev_num, slot, 0);
}
-/* More PCI configuration routines; this time centered around hotplug controller */
+/* More PCI configuration routines; this time centered around hotplug
+ * controller
+ */
/*
@@ -339,12 +314,12 @@ int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug)
int stop_it;
int index;
- // Decide which slots are supported
+ /* Decide which slots are supported */
if (is_hot_plug) {
- //*********************************
- // is_hot_plug is the slot mask
- //*********************************
+ /*
+ * is_hot_plug is the slot mask
+ */
FirstSupported = is_hot_plug >> 4;
LastSupported = FirstSupported + (is_hot_plug & 0x0F) - 1;
} else {
@@ -352,123 +327,127 @@ int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug)
LastSupported = 0x1F;
}
- // Save PCI configuration space for all devices in supported slots
+ /* Save PCI configuration space for all devices in supported slots */
ctrl->pci_bus->number = busnumber;
for (device = FirstSupported; device <= LastSupported; device++) {
ID = 0xFFFFFFFF;
- rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID);
+ rc = pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID);
+
+ if (ID == 0xFFFFFFFF) {
+ if (is_hot_plug) {
+ /* Setup slot structure with entry for empty
+ * slot
+ */
+ new_slot = cpqhp_slot_create(busnumber);
+ if (new_slot == NULL)
+ return 1;
- if (ID != 0xFFFFFFFF) { // device in slot
- rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, 0), 0x0B, &class_code);
- if (rc)
- return rc;
+ new_slot->bus = (u8) busnumber;
+ new_slot->device = (u8) device;
+ new_slot->function = 0;
+ new_slot->is_a_board = 0;
+ new_slot->presence_save = 0;
+ new_slot->switch_save = 0;
+ }
+ continue;
+ }
- rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, 0), PCI_HEADER_TYPE, &header_type);
- if (rc)
- return rc;
+ rc = pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(device, 0), 0x0B, &class_code);
+ if (rc)
+ return rc;
- // If multi-function device, set max_functions to 8
- if (header_type & 0x80)
- max_functions = 8;
- else
- max_functions = 1;
+ rc = pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(device, 0), PCI_HEADER_TYPE, &header_type);
+ if (rc)
+ return rc;
- function = 0;
+ /* If multi-function device, set max_functions to 8 */
+ if (header_type & 0x80)
+ max_functions = 8;
+ else
+ max_functions = 1;
- do {
- DevError = 0;
+ function = 0;
- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // P-P Bridge
- // Recurse the subordinate bus
- // get the subordinate bus number
- rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, function), PCI_SECONDARY_BUS, &secondary_bus);
- if (rc) {
+ do {
+ DevError = 0;
+ if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+ /* Recurse the subordinate bus
+ * get the subordinate bus number
+ */
+ rc = pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(device, function), PCI_SECONDARY_BUS, &secondary_bus);
+ if (rc) {
+ return rc;
+ } else {
+ sub_bus = (int) secondary_bus;
+
+ /* Save secondary bus cfg spc
+ * with this recursive call.
+ */
+ rc = cpqhp_save_config(ctrl, sub_bus, 0);
+ if (rc)
return rc;
- } else {
- sub_bus = (int) secondary_bus;
-
- // Save secondary bus cfg spc
- // with this recursive call.
- rc = cpqhp_save_config(ctrl, sub_bus, 0);
- if (rc)
- return rc;
- ctrl->pci_bus->number = busnumber;
- }
+ ctrl->pci_bus->number = busnumber;
}
+ }
- index = 0;
+ index = 0;
+ new_slot = cpqhp_slot_find(busnumber, device, index++);
+ while (new_slot &&
+ (new_slot->function != (u8) function))
new_slot = cpqhp_slot_find(busnumber, device, index++);
- while (new_slot &&
- (new_slot->function != (u8) function))
- new_slot = cpqhp_slot_find(busnumber, device, index++);
- if (!new_slot) {
- // Setup slot structure.
- new_slot = cpqhp_slot_create(busnumber);
-
- if (new_slot == NULL)
- return(1);
- }
-
- new_slot->bus = (u8) busnumber;
- new_slot->device = (u8) device;
- new_slot->function = (u8) function;
- new_slot->is_a_board = 1;
- new_slot->switch_save = 0x10;
- // In case of unsupported board
- new_slot->status = DevError;
- new_slot->pci_dev = pci_find_slot(new_slot->bus, (new_slot->device << 3) | new_slot->function);
-
- for (cloop = 0; cloop < 0x20; cloop++) {
- rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(device, function), cloop << 2, (u32 *) & (new_slot-> config_space [cloop]));
- if (rc)
- return rc;
- }
+ if (!new_slot) {
+ /* Setup slot structure. */
+ new_slot = cpqhp_slot_create(busnumber);
+ if (new_slot == NULL)
+ return 1;
+ }
- function++;
+ new_slot->bus = (u8) busnumber;
+ new_slot->device = (u8) device;
+ new_slot->function = (u8) function;
+ new_slot->is_a_board = 1;
+ new_slot->switch_save = 0x10;
+ /* In case of unsupported board */
+ new_slot->status = DevError;
+ new_slot->pci_dev = pci_get_bus_and_slot(new_slot->bus, (new_slot->device << 3) | new_slot->function);
- stop_it = 0;
+ for (cloop = 0; cloop < 0x20; cloop++) {
+ rc = pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(device, function), cloop << 2, (u32 *) & (new_slot-> config_space [cloop]));
+ if (rc)
+ return rc;
+ }
- // this loop skips to the next present function
- // reading in Class Code and Header type.
+ pci_dev_put(new_slot->pci_dev);
- while ((function < max_functions)&&(!stop_it)) {
- rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(device, function), PCI_VENDOR_ID, &ID);
- if (ID == 0xFFFFFFFF) { // nothing there.
- function++;
- } else { // Something there
- rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, function), 0x0B, &class_code);
- if (rc)
- return rc;
+ function++;
- rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, function), PCI_HEADER_TYPE, &header_type);
- if (rc)
- return rc;
+ stop_it = 0;
- stop_it++;
- }
+ /* this loop skips to the next present function
+ * reading in Class Code and Header type.
+ */
+ while ((function < max_functions) && (!stop_it)) {
+ rc = pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(device, function), PCI_VENDOR_ID, &ID);
+ if (ID == 0xFFFFFFFF) {
+ function++;
+ continue;
}
+ rc = pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(device, function), 0x0B, &class_code);
+ if (rc)
+ return rc;
- } while (function < max_functions);
- } // End of IF (device in slot?)
- else if (is_hot_plug) {
- // Setup slot structure with entry for empty slot
- new_slot = cpqhp_slot_create(busnumber);
+ rc = pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(device, function), PCI_HEADER_TYPE, &header_type);
+ if (rc)
+ return rc;
- if (new_slot == NULL) {
- return(1);
+ stop_it++;
}
- new_slot->bus = (u8) busnumber;
- new_slot->device = (u8) device;
- new_slot->function = 0;
- new_slot->is_a_board = 0;
- new_slot->presence_save = 0;
- new_slot->switch_save = 0;
- }
- } // End of FOR loop
+ } while (function < max_functions);
+ } /* End of FOR loop */
- return(0);
+ return 0;
}
@@ -489,7 +468,7 @@ int cpqhp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot)
u8 secondary_bus;
int sub_bus;
int max_functions;
- int function;
+ int function = 0;
int cloop = 0;
int stop_it;
@@ -498,63 +477,58 @@ int cpqhp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot)
ctrl->pci_bus->number = new_slot->bus;
pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_VENDOR_ID, &ID);
- if (ID != 0xFFFFFFFF) { // device in slot
- pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), 0x0B, &class_code);
- pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_HEADER_TYPE, &header_type);
-
- if (header_type & 0x80) // Multi-function device
- max_functions = 8;
- else
- max_functions = 1;
-
- function = 0;
-
- do {
- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge
- // Recurse the subordinate bus
- pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_SECONDARY_BUS, &secondary_bus);
+ if (ID == 0xFFFFFFFF)
+ return 2;
- sub_bus = (int) secondary_bus;
+ pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), 0x0B, &class_code);
+ pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_HEADER_TYPE, &header_type);
- // Save the config headers for the secondary bus.
- rc = cpqhp_save_config(ctrl, sub_bus, 0);
- if (rc)
- return(rc);
- ctrl->pci_bus->number = new_slot->bus;
+ if (header_type & 0x80) /* Multi-function device */
+ max_functions = 8;
+ else
+ max_functions = 1;
- } // End of IF
+ while (function < max_functions) {
+ if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+ /* Recurse the subordinate bus */
+ pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_SECONDARY_BUS, &secondary_bus);
- new_slot->status = 0;
+ sub_bus = (int) secondary_bus;
- for (cloop = 0; cloop < 0x20; cloop++) {
- pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), cloop << 2, (u32 *) & (new_slot-> config_space [cloop]));
- }
+ /* Save the config headers for the secondary
+ * bus.
+ */
+ rc = cpqhp_save_config(ctrl, sub_bus, 0);
+ if (rc)
+ return(rc);
+ ctrl->pci_bus->number = new_slot->bus;
- function++;
+ }
- stop_it = 0;
+ new_slot->status = 0;
- // this loop skips to the next present function
- // reading in the Class Code and the Header type.
+ for (cloop = 0; cloop < 0x20; cloop++)
+ pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), cloop << 2, (u32 *) & (new_slot-> config_space [cloop]));
- while ((function < max_functions) && (!stop_it)) {
- pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_VENDOR_ID, &ID);
+ function++;
- if (ID == 0xFFFFFFFF) { // nothing there.
- function++;
- } else { // Something there
- pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), 0x0B, &class_code);
+ stop_it = 0;
- pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_HEADER_TYPE, &header_type);
+ /* this loop skips to the next present function
+ * reading in the Class Code and the Header type.
+ */
+ while ((function < max_functions) && (!stop_it)) {
+ pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_VENDOR_ID, &ID);
- stop_it++;
- }
+ if (ID == 0xFFFFFFFF)
+ function++;
+ else {
+ pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), 0x0B, &class_code);
+ pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_HEADER_TYPE, &header_type);
+ stop_it++;
}
+ }
- } while (function < max_functions);
- } // End of IF (device in slot?)
- else {
- return 2;
}
return 0;
@@ -590,11 +564,10 @@ int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func * func)
pci_bus->number = func->bus;
devfn = PCI_DEVFN(func->device, func->function);
- // Check for Bridge
+ /* Check for Bridge */
pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
- // PCI-PCI Bridge
pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
sub_bus = (int) secondary_bus;
@@ -610,23 +583,27 @@ int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func * func)
}
pci_bus->number = func->bus;
- //FIXME: this loop is duplicated in the non-bridge case. The two could be rolled together
- // Figure out IO and memory base lengths
+ /* FIXME: this loop is duplicated in the non-bridge
+ * case. The two could be rolled together Figure out
+ * IO and memory base lengths
+ */
for (cloop = 0x10; cloop <= 0x14; cloop += 4) {
temp_register = 0xFFFFFFFF;
pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
-
- if (base) { // If this register is implemented
+ /* If this register is implemented */
+ if (base) {
if (base & 0x01L) {
- // IO base
- // set base = amount of IO space requested
+ /* IO base
+ * set base = amount of IO space
+ * requested
+ */
base = base & 0xFFFFFFFE;
base = (~base) + 1;
type = 1;
} else {
- // memory base
+ /* memory base */
base = base & 0xFFFFFFF0;
base = (~base) + 1;
@@ -637,32 +614,36 @@ int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func * func)
type = 0;
}
- // Save information in slot structure
+ /* Save information in slot structure */
func->base_length[(cloop - 0x10) >> 2] =
base;
func->base_type[(cloop - 0x10) >> 2] = type;
- } // End of base register loop
+ } /* End of base register loop */
-
- } else if ((header_type & 0x7F) == 0x00) { // PCI-PCI Bridge
- // Figure out IO and memory base lengths
+ } else if ((header_type & 0x7F) == 0x00) {
+ /* Figure out IO and memory base lengths */
for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
temp_register = 0xFFFFFFFF;
pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
- if (base) { // If this register is implemented
+ /* If this register is implemented */
+ if (base) {
if (base & 0x01L) {
- // IO base
- // base = amount of IO space requested
+ /* IO base
+ * base = amount of IO space
+ * requested
+ */
base = base & 0xFFFFFFFE;
base = (~base) + 1;
type = 1;
} else {
- // memory base
- // base = amount of memory space requested
+ /* memory base
+ * base = amount of memory
+ * space requested
+ */
base = base & 0xFFFFFFF0;
base = (~base) + 1;
@@ -673,16 +654,16 @@ int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func * func)
type = 0;
}
- // Save information in slot structure
+ /* Save information in slot structure */
func->base_length[(cloop - 0x10) >> 2] = base;
func->base_type[(cloop - 0x10) >> 2] = type;
- } // End of base register loop
+ } /* End of base register loop */
- } else { // Some other unknown header type
+ } else { /* Some other unknown header type */
}
- // find the next device in this slot
+ /* find the next device in this slot */
func = cpqhp_slot_find(func->bus, func->device, index++);
}
@@ -728,18 +709,18 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
pci_bus->number = func->bus;
devfn = PCI_DEVFN(func->device, func->function);
- // Save the command register
+ /* Save the command register */
pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &save_command);
- // disable card
+ /* disable card */
command = 0x00;
pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
- // Check for Bridge
+ /* Check for Bridge */
pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge
- // Clear Bridge Control Register
+ if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+ /* Clear Bridge Control Register */
command = 0x00;
pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
@@ -755,7 +736,7 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
bus_node->next = func->bus_head;
func->bus_head = bus_node;
- // Save IO base and Limit registers
+ /* Save IO base and Limit registers */
pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_BASE, &b_base);
pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_LIMIT, &b_length);
@@ -771,7 +752,7 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
func->io_head = io_node;
}
- // Save memory base and Limit registers
+ /* Save memory base and Limit registers */
pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_BASE, &w_base);
pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length);
@@ -787,7 +768,7 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
func->mem_head = mem_node;
}
- // Save prefetchable memory base and Limit registers
+ /* Save prefetchable memory base and Limit registers */
pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base);
pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length);
@@ -802,7 +783,7 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
p_mem_node->next = func->p_mem_head;
func->p_mem_head = p_mem_node;
}
- // Figure out IO and memory base lengths
+ /* Figure out IO and memory base lengths */
for (cloop = 0x10; cloop <= 0x14; cloop += 4) {
pci_bus_read_config_dword (pci_bus, devfn, cloop, &save_base);
@@ -812,11 +793,14 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
temp_register = base;
- if (base) { // If this register is implemented
+ /* If this register is implemented */
+ if (base) {
if (((base & 0x03L) == 0x01)
&& (save_command & 0x01)) {
- // IO base
- // set temp_register = amount of IO space requested
+ /* IO base
+ * set temp_register = amount
+ * of IO space requested
+ */
temp_register = base & 0xFFFFFFFE;
temp_register = (~temp_register) + 1;
@@ -834,7 +818,7 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
} else
if (((base & 0x0BL) == 0x08)
&& (save_command & 0x02)) {
- // prefetchable memory base
+ /* prefetchable memory base */
temp_register = base & 0xFFFFFFF0;
temp_register = (~temp_register) + 1;
@@ -851,7 +835,7 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
} else
if (((base & 0x0BL) == 0x00)
&& (save_command & 0x02)) {
- // prefetchable memory base
+ /* prefetchable memory base */
temp_register = base & 0xFFFFFFF0;
temp_register = (~temp_register) + 1;
@@ -868,9 +852,10 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
} else
return(1);
}
- } // End of base register loop
- } else if ((header_type & 0x7F) == 0x00) { // Standard header
- // Figure out IO and memory base lengths
+ } /* End of base register loop */
+ /* Standard header */
+ } else if ((header_type & 0x7F) == 0x00) {
+ /* Figure out IO and memory base lengths */
for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base);
@@ -880,11 +865,14 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
temp_register = base;
- if (base) { // If this register is implemented
+ /* If this register is implemented */
+ if (base) {
if (((base & 0x03L) == 0x01)
&& (save_command & 0x01)) {
- // IO base
- // set temp_register = amount of IO space requested
+ /* IO base
+ * set temp_register = amount
+ * of IO space requested
+ */
temp_register = base & 0xFFFFFFFE;
temp_register = (~temp_register) + 1;
@@ -901,7 +889,7 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
} else
if (((base & 0x0BL) == 0x08)
&& (save_command & 0x02)) {
- // prefetchable memory base
+ /* prefetchable memory base */
temp_register = base & 0xFFFFFFF0;
temp_register = (~temp_register) + 1;
@@ -918,7 +906,7 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
} else
if (((base & 0x0BL) == 0x00)
&& (save_command & 0x02)) {
- // prefetchable memory base
+ /* prefetchable memory base */
temp_register = base & 0xFFFFFFF0;
temp_register = (~temp_register) + 1;
@@ -935,15 +923,14 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
} else
return(1);
}
- } // End of base register loop
- } else { // Some other unknown header type
+ } /* End of base register loop */
}
- // find the next device in this slot
+ /* find the next device in this slot */
func = cpqhp_slot_find(func->bus, func->device, index++);
}
- return(0);
+ return 0;
}
@@ -975,16 +962,16 @@ int cpqhp_configure_board(struct controller *ctrl, struct pci_func * func)
pci_bus->number = func->bus;
devfn = PCI_DEVFN(func->device, func->function);
- // Start at the top of config space so that the control
- // registers are programmed last
- for (cloop = 0x3C; cloop > 0; cloop -= 4) {
+ /* Start at the top of config space so that the control
+ * registers are programmed last
+ */
+ for (cloop = 0x3C; cloop > 0; cloop -= 4)
pci_bus_write_config_dword (pci_bus, devfn, cloop, func->config_space[cloop >> 2]);
- }
pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
- // If this is a bridge device, restore subordinate devices
- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge
+ /* If this is a bridge device, restore subordinate devices */
+ if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
sub_bus = (int) secondary_bus;
@@ -1000,8 +987,9 @@ int cpqhp_configure_board(struct controller *ctrl, struct pci_func * func)
}
} else {
- // Check all the base Address Registers to make sure
- // they are the same. If not, the board is different.
+ /* Check all the base Address Registers to make sure
+ * they are the same. If not, the board is different.
+ */
for (cloop = 16; cloop < 40; cloop += 4) {
pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp);
@@ -1058,27 +1046,28 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func)
pci_bus_read_config_dword (pci_bus, devfn, PCI_VENDOR_ID, &temp_register);
- // No adapter present
+ /* No adapter present */
if (temp_register == 0xFFFFFFFF)
return(NO_ADAPTER_PRESENT);
if (temp_register != func->config_space[0])
return(ADAPTER_NOT_SAME);
- // Check for same revision number and class code
+ /* Check for same revision number and class code */
pci_bus_read_config_dword (pci_bus, devfn, PCI_CLASS_REVISION, &temp_register);
- // Adapter not the same
+ /* Adapter not the same */
if (temp_register != func->config_space[0x08 >> 2])
return(ADAPTER_NOT_SAME);
- // Check for Bridge
+ /* Check for Bridge */
pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge
- // In order to continue checking, we must program the
- // bus registers in the bridge to respond to accesses
- // for it's subordinate bus(es)
+ if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+ /* In order to continue checking, we must program the
+ * bus registers in the bridge to respond to accesses
+ * for its subordinate bus(es)
+ */
temp_register = func->config_space[0x18 >> 2];
pci_bus_write_config_dword (pci_bus, devfn, PCI_PRIMARY_BUS, temp_register);
@@ -1096,35 +1085,39 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func)
}
}
- // Check to see if it is a standard config header
+ /* Check to see if it is a standard config header */
else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
- // Check subsystem vendor and ID
+ /* Check subsystem vendor and ID */
pci_bus_read_config_dword (pci_bus, devfn, PCI_SUBSYSTEM_VENDOR_ID, &temp_register);
if (temp_register != func->config_space[0x2C >> 2]) {
- // If it's a SMART-2 and the register isn't filled
- // in, ignore the difference because
- // they just have an old rev of the firmware
-
+ /* If it's a SMART-2 and the register isn't
+ * filled in, ignore the difference because
+ * they just have an old rev of the firmware
+ */
if (!((func->config_space[0] == 0xAE100E11)
&& (temp_register == 0x00L)))
return(ADAPTER_NOT_SAME);
}
- // Figure out IO and memory base lengths
+ /* Figure out IO and memory base lengths */
for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
temp_register = 0xFFFFFFFF;
pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
- if (base) { // If this register is implemented
+
+ /* If this register is implemented */
+ if (base) {
if (base & 0x01L) {
- // IO base
- // set base = amount of IO space requested
+ /* IO base
+ * set base = amount of IO
+ * space requested
+ */
base = base & 0xFFFFFFFE;
base = (~base) + 1;
type = 1;
} else {
- // memory base
+ /* memory base */
base = base & 0xFFFFFFF0;
base = (~base) + 1;
@@ -1135,23 +1128,24 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func)
type = 0;
}
- // Check information in slot structure
+ /* Check information in slot structure */
if (func->base_length[(cloop - 0x10) >> 2] != base)
return(ADAPTER_NOT_SAME);
if (func->base_type[(cloop - 0x10) >> 2] != type)
return(ADAPTER_NOT_SAME);
- } // End of base register loop
+ } /* End of base register loop */
- } // End of (type 0 config space) else
+ } /* End of (type 0 config space) else */
else {
- // this is not a type 0 or 1 config space header so
- // we don't know how to do it
+ /* this is not a type 0 or 1 config space header so
+ * we don't know how to do it
+ */
return(DEVICE_TYPE_NOT_SUPPORTED);
}
- // Get the next function
+ /* Get the next function */
func = cpqhp_slot_find(func->bus, func->device, index++);
}
@@ -1168,7 +1162,7 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func)
* this function is for hot plug ADD!
*
* returns 0 if success
- */
+ */
int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_start)
{
u8 temp;
@@ -1187,10 +1181,10 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
rom_resource_table = detect_HRT_floating_pointer(rom_start, rom_start+0xffff);
dbg("rom_resource_table = %p\n", rom_resource_table);
- if (rom_resource_table == NULL) {
+ if (rom_resource_table == NULL)
return -ENODEV;
- }
- // Sum all resources and setup resource maps
+
+ /* Sum all resources and setup resource maps */
unused_IRQ = readl(rom_resource_table + UNUSED_IRQ);
dbg("unused_IRQ = %x\n", unused_IRQ);
@@ -1222,13 +1216,11 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
temp = 0;
- if (!cpqhp_nic_irq) {
+ if (!cpqhp_nic_irq)
cpqhp_nic_irq = ctrl->cfgspc_irq;
- }
- if (!cpqhp_disk_irq) {
+ if (!cpqhp_disk_irq)
cpqhp_disk_irq = ctrl->cfgspc_irq;
- }
dbg("cpqhp_disk_irq, cpqhp_nic_irq= %d, %d\n", cpqhp_disk_irq, cpqhp_nic_irq);
@@ -1262,13 +1254,13 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
dev_func, io_base, io_length, mem_base, mem_length, pre_mem_base, pre_mem_length,
primary_bus, secondary_bus, max_bus);
- // If this entry isn't for our controller's bus, ignore it
+ /* If this entry isn't for our controller's bus, ignore it */
if (primary_bus != ctrl->bus) {
i--;
one_slot += sizeof (struct slot_rt);
continue;
}
- // find out if this entry is for an occupied slot
+ /* find out if this entry is for an occupied slot */
ctrl->pci_bus->number = primary_bus;
pci_bus_read_config_dword (ctrl->pci_bus, dev_func, PCI_VENDOR_ID, &temp_dword);
dbg("temp_D_word = %x\n", temp_dword);
@@ -1282,13 +1274,13 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
func = cpqhp_slot_find(primary_bus, dev_func >> 3, index++);
}
- // If we can't find a match, skip this table entry
+ /* If we can't find a match, skip this table entry */
if (!func) {
i--;
one_slot += sizeof (struct slot_rt);
continue;
}
- // this may not work and shouldn't be used
+ /* this may not work and shouldn't be used */
if (secondary_bus != primary_bus)
bridged_slot = 1;
else
@@ -1301,7 +1293,7 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
}
- // If we've got a valid IO base, use it
+ /* If we've got a valid IO base, use it */
temp_dword = io_base + io_length;
@@ -1325,7 +1317,7 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
}
}
- // If we've got a valid memory base, use it
+ /* If we've got a valid memory base, use it */
temp_dword = mem_base + mem_length;
if ((mem_base) && (temp_dword < 0x10000)) {
mem_node = kmalloc(sizeof(*mem_node), GFP_KERNEL);
@@ -1348,8 +1340,9 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
}
}
- // If we've got a valid prefetchable memory base, and
- // the base + length isn't greater than 0xFFFF
+ /* If we've got a valid prefetchable memory base, and
+ * the base + length isn't greater than 0xFFFF
+ */
temp_dword = pre_mem_base + pre_mem_length;
if ((pre_mem_base) && (temp_dword < 0x10000)) {
p_mem_node = kmalloc(sizeof(*p_mem_node), GFP_KERNEL);
@@ -1372,9 +1365,10 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
}
}
- // If we've got a valid bus number, use it
- // The second condition is to ignore bus numbers on
- // populated slots that don't have PCI-PCI bridges
+ /* If we've got a valid bus number, use it
+ * The second condition is to ignore bus numbers on
+ * populated slots that don't have PCI-PCI bridges
+ */
if (secondary_bus && (secondary_bus != primary_bus)) {
bus_node = kmalloc(sizeof(*bus_node), GFP_KERNEL);
if (!bus_node)
@@ -1398,8 +1392,9 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
one_slot += sizeof (struct slot_rt);
}
- // If all of the following fail, we don't have any resources for
- // hot plug add
+ /* If all of the following fail, we don't have any resources for
+ * hot plug add
+ */
rc = 1;
rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index dd18f857dfb0..29ccb8a6da8a 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -1419,3 +1419,4 @@ static void __exit ibmphp_exit(void)
}
module_init(ibmphp_init);
+module_exit(ibmphp_exit);
diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c
index bf7d6ce9bbb3..737a1c44b07a 100644
--- a/drivers/pci/htirq.c
+++ b/drivers/pci/htirq.c
@@ -98,6 +98,7 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)
int max_irq;
int pos;
int irq;
+ int node;
pos = pci_find_ht_capability(dev, HT_CAPTYPE_IRQ);
if (!pos)
@@ -125,7 +126,8 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)
cfg->msg.address_lo = 0xffffffff;
cfg->msg.address_hi = 0xffffffff;
- irq = create_irq();
+ node = dev_to_node(&dev->dev);
+ irq = create_irq_nr(0, node);
if (irq <= 0) {
kfree(cfg);
@@ -158,6 +160,7 @@ int ht_create_irq(struct pci_dev *dev, int idx)
/**
* ht_destroy_irq - destroy an irq created with ht_create_irq
+ * @irq: irq to be destroyed
*
* This reverses ht_create_irq removing the specified irq from
* existence. The irq should be free before this happens.
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 001b328adf80..8cd4aacd0711 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -53,12 +53,18 @@
#define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
+#define MAX_AGAW_WIDTH 64
+
#define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1)
#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT)
#define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32))
#define DMA_64BIT_PFN IOVA_PFN(DMA_BIT_MASK(64))
+#ifndef PHYSICAL_PAGE_MASK
+#define PHYSICAL_PAGE_MASK PAGE_MASK
+#endif
+
/* global iommu list, set NULL for ignored DMAR units */
static struct intel_iommu **g_iommus;
@@ -127,8 +133,6 @@ static inline void context_set_fault_enable(struct context_entry *context)
context->lo &= (((u64)-1) << 2) | 1;
}
-#define CONTEXT_TT_MULTI_LEVEL 0
-
static inline void context_set_translation_type(struct context_entry *context,
unsigned long value)
{
@@ -397,17 +401,13 @@ void free_iova_mem(struct iova *iova)
static inline int width_to_agaw(int width);
-/* calculate agaw for each iommu.
- * "SAGAW" may be different across iommus, use a default agaw, and
- * get a supported less agaw for iommus that don't support the default agaw.
- */
-int iommu_calculate_agaw(struct intel_iommu *iommu)
+static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw)
{
unsigned long sagaw;
int agaw = -1;
sagaw = cap_sagaw(iommu->cap);
- for (agaw = width_to_agaw(DEFAULT_DOMAIN_ADDRESS_WIDTH);
+ for (agaw = width_to_agaw(max_gaw);
agaw >= 0; agaw--) {
if (test_bit(agaw, &sagaw))
break;
@@ -416,6 +416,24 @@ int iommu_calculate_agaw(struct intel_iommu *iommu)
return agaw;
}
+/*
+ * Calculate max SAGAW for each iommu.
+ */
+int iommu_calculate_max_sagaw(struct intel_iommu *iommu)
+{
+ return __iommu_calculate_agaw(iommu, MAX_AGAW_WIDTH);
+}
+
+/*
+ * calculate agaw for each iommu.
+ * "SAGAW" may be different across iommus, use a default agaw, and
+ * get a supported less agaw for iommus that don't support the default agaw.
+ */
+int iommu_calculate_agaw(struct intel_iommu *iommu)
+{
+ return __iommu_calculate_agaw(iommu, DEFAULT_DOMAIN_ADDRESS_WIDTH);
+}
+
/* in native case, each domain is related to only one iommu */
static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
{
@@ -805,7 +823,7 @@ static int iommu_alloc_root_entry(struct intel_iommu *iommu)
static void iommu_set_root_entry(struct intel_iommu *iommu)
{
void *addr;
- u32 cmd, sts;
+ u32 sts;
unsigned long flag;
addr = iommu->root_entry;
@@ -813,12 +831,11 @@ static void iommu_set_root_entry(struct intel_iommu *iommu)
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);
+ writel(iommu->gcmd | DMA_GCMD_SRTP, iommu->reg + DMAR_GCMD_REG);
/* Make sure hardware complete it */
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
- readl, (sts & DMA_GSTS_RTPS), sts);
+ readl, (sts & DMA_GSTS_RTPS), sts);
spin_unlock_irqrestore(&iommu->register_lock, flag);
}
@@ -830,39 +847,25 @@ static void iommu_flush_write_buffer(struct intel_iommu *iommu)
if (!rwbf_quirk && !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);
+ writel(iommu->gcmd | DMA_GCMD_WBF, iommu->reg + DMAR_GCMD_REG);
/* Make sure hardware complete it */
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
- readl, (!(val & DMA_GSTS_WBFS)), val);
+ 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)
+static void __iommu_flush_context(struct intel_iommu *iommu,
+ u16 did, u16 source_id, u8 function_mask,
+ u64 type)
{
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;
@@ -887,33 +890,16 @@ static int __iommu_flush_context(struct intel_iommu *iommu,
dmar_readq, (!(val & DMA_CCMD_ICC)), val);
spin_unlock_irqrestore(&iommu->register_lock, flag);
-
- /* flush context entry will implicitly flush write buffer */
- return 0;
}
/* 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)
+static void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
+ u64 addr, unsigned int size_order, u64 type)
{
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 */
@@ -961,12 +947,10 @@ static int __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
pr_debug("IOMMU: tlb flush request %Lx, actual %Lx\n",
(unsigned long long)DMA_TLB_IIRG(type),
(unsigned long long)DMA_TLB_IAIG(val));
- /* flush iotlb entry will implicitly flush write buffer */
- return 0;
}
-static int iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did,
- u64 addr, unsigned int pages, int non_present_entry_flush)
+static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did,
+ u64 addr, unsigned int pages)
{
unsigned int mask;
@@ -976,8 +960,7 @@ static int iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did,
/* Fallback to domain selective flush if no PSI support */
if (!cap_pgsel_inv(iommu->cap))
return iommu->flush.flush_iotlb(iommu, did, 0, 0,
- DMA_TLB_DSI_FLUSH,
- non_present_entry_flush);
+ DMA_TLB_DSI_FLUSH);
/*
* PSI requires page size to be 2 ^ x, and the base address is naturally
@@ -987,11 +970,10 @@ static int iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did,
/* Fallback to domain selective flush if size is too big */
if (mask > cap_max_amask_val(iommu->cap))
return iommu->flush.flush_iotlb(iommu, did, 0, 0,
- DMA_TLB_DSI_FLUSH, non_present_entry_flush);
+ DMA_TLB_DSI_FLUSH);
return iommu->flush.flush_iotlb(iommu, did, addr, mask,
- DMA_TLB_PSI_FLUSH,
- non_present_entry_flush);
+ DMA_TLB_PSI_FLUSH);
}
static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu)
@@ -1017,13 +999,13 @@ static int iommu_enable_translation(struct intel_iommu *iommu)
unsigned long flags;
spin_lock_irqsave(&iommu->register_lock, flags);
- writel(iommu->gcmd|DMA_GCMD_TE, iommu->reg + DMAR_GCMD_REG);
+ 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);
+ readl, (sts & DMA_GSTS_TES), sts);
- iommu->gcmd |= DMA_GCMD_TE;
spin_unlock_irqrestore(&iommu->register_lock, flags);
return 0;
}
@@ -1039,7 +1021,7 @@ static int iommu_disable_translation(struct intel_iommu *iommu)
/* Make sure hardware complete it */
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
- readl, (!(sts & DMA_GSTS_TES)), sts);
+ readl, (!(sts & DMA_GSTS_TES)), sts);
spin_unlock_irqrestore(&iommu->register_lock, flag);
return 0;
@@ -1216,7 +1198,7 @@ static void dmar_init_reserved_ranges(void)
if (!r->flags || !(r->flags & IORESOURCE_MEM))
continue;
addr = r->start;
- addr &= PAGE_MASK;
+ addr &= PHYSICAL_PAGE_MASK;
size = r->end - addr;
size = PAGE_ALIGN(size);
iova = reserve_iova(&reserved_iova_list, IOVA_PFN(addr),
@@ -1321,8 +1303,8 @@ static void domain_exit(struct dmar_domain *domain)
free_domain_mem(domain);
}
-static int domain_context_mapping_one(struct dmar_domain *domain,
- int segment, u8 bus, u8 devfn)
+static int domain_context_mapping_one(struct dmar_domain *domain, int segment,
+ u8 bus, u8 devfn, int translation)
{
struct context_entry *context;
unsigned long flags;
@@ -1335,7 +1317,10 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
pr_debug("Set context mapping for %02x:%02x.%d\n",
bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+
BUG_ON(!domain->pgd);
+ BUG_ON(translation != CONTEXT_TT_PASS_THROUGH &&
+ translation != CONTEXT_TT_MULTI_LEVEL);
iommu = device_to_iommu(segment, bus, devfn);
if (!iommu)
@@ -1395,21 +1380,37 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
}
context_set_domain_id(context, id);
- context_set_address_width(context, iommu->agaw);
- context_set_address_root(context, virt_to_phys(pgd));
- context_set_translation_type(context, CONTEXT_TT_MULTI_LEVEL);
+
+ /*
+ * In pass through mode, AW must be programmed to indicate the largest
+ * AGAW value supported by hardware. And ASR is ignored by hardware.
+ */
+ if (likely(translation == CONTEXT_TT_MULTI_LEVEL)) {
+ context_set_address_width(context, iommu->agaw);
+ context_set_address_root(context, virt_to_phys(pgd));
+ } else
+ context_set_address_width(context, iommu->msagaw);
+
+ context_set_translation_type(context, translation);
context_set_fault_enable(context);
context_set_present(context);
domain_flush_cache(domain, context, sizeof(*context));
- /* it's a non-present to present mapping */
- if (iommu->flush.flush_context(iommu, domain->id,
- (((u16)bus) << 8) | devfn, DMA_CCMD_MASK_NOBIT,
- DMA_CCMD_DEVICE_INVL, 1))
+ /*
+ * It's a non-present to present mapping. If hardware doesn't cache
+ * non-present entry we only need to flush the write-buffer. If the
+ * _does_ cache non-present entries, then it does so in the special
+ * domain #0, which we have to flush:
+ */
+ if (cap_caching_mode(iommu->cap)) {
+ iommu->flush.flush_context(iommu, 0,
+ (((u16)bus) << 8) | devfn,
+ DMA_CCMD_MASK_NOBIT,
+ DMA_CCMD_DEVICE_INVL);
+ iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_DSI_FLUSH);
+ } else {
iommu_flush_write_buffer(iommu);
- else
- iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_DSI_FLUSH, 0);
-
+ }
spin_unlock_irqrestore(&iommu->lock, flags);
spin_lock_irqsave(&domain->iommu_lock, flags);
@@ -1422,13 +1423,15 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
}
static int
-domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev)
+domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev,
+ int translation)
{
int ret;
struct pci_dev *tmp, *parent;
ret = domain_context_mapping_one(domain, pci_domain_nr(pdev->bus),
- pdev->bus->number, pdev->devfn);
+ pdev->bus->number, pdev->devfn,
+ translation);
if (ret)
return ret;
@@ -1442,7 +1445,7 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev)
ret = domain_context_mapping_one(domain,
pci_domain_nr(parent->bus),
parent->bus->number,
- parent->devfn);
+ parent->devfn, translation);
if (ret)
return ret;
parent = parent->bus->self;
@@ -1450,12 +1453,14 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev)
if (tmp->is_pcie) /* this is a PCIE-to-PCI bridge */
return domain_context_mapping_one(domain,
pci_domain_nr(tmp->subordinate),
- tmp->subordinate->number, 0);
+ tmp->subordinate->number, 0,
+ translation);
else /* this is a legacy PCI bridge */
return domain_context_mapping_one(domain,
pci_domain_nr(tmp->bus),
tmp->bus->number,
- tmp->devfn);
+ tmp->devfn,
+ translation);
}
static int domain_context_mapped(struct pci_dev *pdev)
@@ -1536,9 +1541,8 @@ static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn)
clear_context_table(iommu, bus, devfn);
iommu->flush.flush_context(iommu, 0, 0, 0,
- DMA_CCMD_GLOBAL_INVL, 0);
- iommu->flush.flush_iotlb(iommu, 0, 0, 0,
- DMA_TLB_GLOBAL_FLUSH, 0);
+ DMA_CCMD_GLOBAL_INVL);
+ iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
}
static void domain_remove_dev_info(struct dmar_domain *domain)
@@ -1752,7 +1756,7 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev,
goto error;
/* context entry init */
- ret = domain_context_mapping(domain, pdev);
+ ret = domain_context_mapping(domain, pdev, CONTEXT_TT_MULTI_LEVEL);
if (!ret)
return 0;
error:
@@ -1853,6 +1857,23 @@ static inline void iommu_prepare_isa(void)
}
#endif /* !CONFIG_DMAR_FLPY_WA */
+/* Initialize each context entry as pass through.*/
+static int __init init_context_pass_through(void)
+{
+ struct pci_dev *pdev = NULL;
+ struct dmar_domain *domain;
+ int ret;
+
+ for_each_pci_dev(pdev) {
+ domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
+ ret = domain_context_mapping(domain, pdev,
+ CONTEXT_TT_PASS_THROUGH);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
static int __init init_dmars(void)
{
struct dmar_drhd_unit *drhd;
@@ -1860,6 +1881,7 @@ static int __init init_dmars(void)
struct pci_dev *pdev;
struct intel_iommu *iommu;
int i, ret;
+ int pass_through = 1;
/*
* for each drhd
@@ -1913,7 +1935,15 @@ static int __init init_dmars(void)
printk(KERN_ERR "IOMMU: allocate root entry failed\n");
goto error;
}
+ if (!ecap_pass_through(iommu->ecap))
+ pass_through = 0;
}
+ if (iommu_pass_through)
+ if (!pass_through) {
+ printk(KERN_INFO
+ "Pass Through is not supported by hardware.\n");
+ iommu_pass_through = 0;
+ }
/*
* Start from the sane iommu hardware state.
@@ -1968,45 +1998,57 @@ static int __init init_dmars(void)
}
}
-#ifdef CONFIG_INTR_REMAP
- if (!intr_remapping_enabled) {
- ret = enable_intr_remapping(0);
- if (ret)
- printk(KERN_ERR
- "IOMMU: enable interrupt remapping failed\n");
+ /*
+ * If pass through is set and enabled, context entries of all pci
+ * devices are intialized by pass through translation type.
+ */
+ if (iommu_pass_through) {
+ ret = init_context_pass_through();
+ if (ret) {
+ printk(KERN_ERR "IOMMU: Pass through init failed.\n");
+ iommu_pass_through = 0;
+ }
}
-#endif
/*
- * 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
+ * If pass through is not set or not enabled, setup context entries for
+ * identity mappings for rmrr, gfx, and isa.
*/
- for_each_rmrr_units(rmrr) {
- 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
+ if (!iommu_pass_through) {
+ /*
+ * 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) {
+ 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_gfx_mapping();
- iommu_prepare_isa();
+ iommu_prepare_isa();
+ }
/*
* for each drhd
@@ -2028,10 +2070,8 @@ static int __init init_dmars(void)
iommu_set_root_entry(iommu);
- iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL,
- 0);
- iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH,
- 0);
+ iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
+ iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
iommu_disable_protect_mem_regions(iommu);
ret = iommu_enable_translation(iommu);
@@ -2117,7 +2157,8 @@ get_valid_domain_for_dev(struct pci_dev *pdev)
/* make sure context mapping is ok */
if (unlikely(!domain_context_mapped(pdev))) {
- ret = domain_context_mapping(domain, pdev);
+ ret = domain_context_mapping(domain, pdev,
+ CONTEXT_TT_MULTI_LEVEL);
if (ret) {
printk(KERN_ERR
"Domain context map for %s failed",
@@ -2173,14 +2214,16 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
* is not a big problem
*/
ret = domain_page_mapping(domain, start_paddr,
- ((u64)paddr) & PAGE_MASK, size, prot);
+ ((u64)paddr) & PHYSICAL_PAGE_MASK,
+ size, prot);
if (ret)
goto error;
- /* it's a non-present to present mapping */
- ret = iommu_flush_iotlb_psi(iommu, domain->id,
- start_paddr, size >> VTD_PAGE_SHIFT, 1);
- if (ret)
+ /* it's a non-present to present mapping. Only flush if caching mode */
+ if (cap_caching_mode(iommu->cap))
+ iommu_flush_iotlb_psi(iommu, 0, start_paddr,
+ size >> VTD_PAGE_SHIFT);
+ else
iommu_flush_write_buffer(iommu);
return start_paddr + ((u64)paddr & (~PAGE_MASK));
@@ -2216,7 +2259,7 @@ static void flush_unmaps(void)
if (deferred_flush[i].next) {
iommu->flush.flush_iotlb(iommu, 0, 0, 0,
- DMA_TLB_GLOBAL_FLUSH, 0);
+ DMA_TLB_GLOBAL_FLUSH);
for (j = 0; j < deferred_flush[i].next; j++) {
__free_iova(&deferred_flush[i].domain[j]->iovad,
deferred_flush[i].iova[j]);
@@ -2295,9 +2338,8 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
/* free page tables */
dma_pte_free_pagetable(domain, start_addr, start_addr + size);
if (intel_iommu_strict) {
- if (iommu_flush_iotlb_psi(iommu,
- domain->id, start_addr, size >> VTD_PAGE_SHIFT, 0))
- iommu_flush_write_buffer(iommu);
+ iommu_flush_iotlb_psi(iommu, domain->id, start_addr,
+ size >> VTD_PAGE_SHIFT);
/* free iova */
__free_iova(&domain->iovad, iova);
} else {
@@ -2388,9 +2430,8 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
/* free page tables */
dma_pte_free_pagetable(domain, start_addr, start_addr + size);
- if (iommu_flush_iotlb_psi(iommu, domain->id, start_addr,
- size >> VTD_PAGE_SHIFT, 0))
- iommu_flush_write_buffer(iommu);
+ iommu_flush_iotlb_psi(iommu, domain->id, start_addr,
+ size >> VTD_PAGE_SHIFT);
/* free iova */
__free_iova(&domain->iovad, iova);
@@ -2463,8 +2504,8 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne
addr = page_to_phys(sg_page(sg)) + sg->offset;
size = aligned_size((u64)addr, sg->length);
ret = domain_page_mapping(domain, start_addr + offset,
- ((u64)addr) & PAGE_MASK,
- size, prot);
+ ((u64)addr) & PHYSICAL_PAGE_MASK,
+ size, prot);
if (ret) {
/* clear the page */
dma_pte_clear_range(domain, start_addr,
@@ -2482,10 +2523,13 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne
offset += size;
}
- /* it's a non-present to present mapping */
- if (iommu_flush_iotlb_psi(iommu, domain->id,
- start_addr, offset >> VTD_PAGE_SHIFT, 1))
+ /* it's a non-present to present mapping. Only flush if caching mode */
+ if (cap_caching_mode(iommu->cap))
+ iommu_flush_iotlb_psi(iommu, 0, start_addr,
+ offset >> VTD_PAGE_SHIFT);
+ else
iommu_flush_write_buffer(iommu);
+
return nelems;
}
@@ -2644,9 +2688,9 @@ static int init_iommu_hw(void)
iommu_set_root_entry(iommu);
iommu->flush.flush_context(iommu, 0, 0, 0,
- DMA_CCMD_GLOBAL_INVL, 0);
+ DMA_CCMD_GLOBAL_INVL);
iommu->flush.flush_iotlb(iommu, 0, 0, 0,
- DMA_TLB_GLOBAL_FLUSH, 0);
+ DMA_TLB_GLOBAL_FLUSH);
iommu_disable_protect_mem_regions(iommu);
iommu_enable_translation(iommu);
}
@@ -2661,9 +2705,9 @@ static void iommu_flush_all(void)
for_each_active_iommu(iommu, drhd) {
iommu->flush.flush_context(iommu, 0, 0, 0,
- DMA_CCMD_GLOBAL_INVL, 0);
+ DMA_CCMD_GLOBAL_INVL);
iommu->flush.flush_iotlb(iommu, 0, 0, 0,
- DMA_TLB_GLOBAL_FLUSH, 0);
+ DMA_TLB_GLOBAL_FLUSH);
}
}
@@ -2786,7 +2830,7 @@ int __init intel_iommu_init(void)
* Check the need for DMA-remapping initialization now.
* Above initialization will also be used by Interrupt-remapping.
*/
- if (no_iommu || swiotlb || dmar_disabled)
+ if (no_iommu || (swiotlb && !iommu_pass_through) || dmar_disabled)
return -ENODEV;
iommu_init_mempool();
@@ -2806,7 +2850,15 @@ int __init intel_iommu_init(void)
init_timer(&unmap_timer);
force_iommu = 1;
- dma_ops = &intel_dma_ops;
+
+ if (!iommu_pass_through) {
+ printk(KERN_INFO
+ "Multi-level page-table translation for DMAR.\n");
+ dma_ops = &intel_dma_ops;
+ } else
+ printk(KERN_INFO
+ "DMAR: Pass through translation for DMAR.\n");
+
init_iommu_sysfs();
register_iommu(&intel_iommu_ops);
@@ -3146,7 +3198,7 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
return -EFAULT;
}
- ret = domain_context_mapping(dmar_domain, pdev);
+ ret = domain_context_mapping(dmar_domain, pdev, CONTEXT_TT_MULTI_LEVEL);
if (ret)
return ret;
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
index f5e0ea724a6f..1e83c8c5f985 100644
--- a/drivers/pci/intr_remapping.c
+++ b/drivers/pci/intr_remapping.c
@@ -15,6 +15,14 @@ static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
static int ir_ioapic_num;
int intr_remapping_enabled;
+static int disable_intremap;
+static __init int setup_nointremap(char *str)
+{
+ disable_intremap = 1;
+ return 0;
+}
+early_param("nointremap", setup_nointremap);
+
struct irq_2_iommu {
struct intel_iommu *iommu;
u16 irte_index;
@@ -23,15 +31,12 @@ struct irq_2_iommu {
};
#ifdef CONFIG_GENERIC_HARDIRQS
-static struct irq_2_iommu *get_one_free_irq_2_iommu(int cpu)
+static struct irq_2_iommu *get_one_free_irq_2_iommu(int node)
{
struct irq_2_iommu *iommu;
- int node;
-
- node = cpu_to_node(cpu);
iommu = kzalloc_node(sizeof(*iommu), GFP_ATOMIC, node);
- printk(KERN_DEBUG "alloc irq_2_iommu on cpu %d node %d\n", cpu, node);
+ printk(KERN_DEBUG "alloc irq_2_iommu on node %d\n", node);
return iommu;
}
@@ -48,7 +53,7 @@ static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
return desc->irq_2_iommu;
}
-static struct irq_2_iommu *irq_2_iommu_alloc_cpu(unsigned int irq, int cpu)
+static struct irq_2_iommu *irq_2_iommu_alloc_node(unsigned int irq, int node)
{
struct irq_desc *desc;
struct irq_2_iommu *irq_iommu;
@@ -56,7 +61,7 @@ static struct irq_2_iommu *irq_2_iommu_alloc_cpu(unsigned int irq, int cpu)
/*
* alloc irq desc if not allocated already.
*/
- desc = irq_to_desc_alloc_cpu(irq, cpu);
+ desc = irq_to_desc_alloc_node(irq, node);
if (!desc) {
printk(KERN_INFO "can not get irq_desc for %d\n", irq);
return NULL;
@@ -65,14 +70,14 @@ static struct irq_2_iommu *irq_2_iommu_alloc_cpu(unsigned int irq, int cpu)
irq_iommu = desc->irq_2_iommu;
if (!irq_iommu)
- desc->irq_2_iommu = get_one_free_irq_2_iommu(cpu);
+ desc->irq_2_iommu = get_one_free_irq_2_iommu(node);
return desc->irq_2_iommu;
}
static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
{
- return irq_2_iommu_alloc_cpu(irq, boot_cpu_id);
+ return irq_2_iommu_alloc_node(irq, cpu_to_node(boot_cpu_id));
}
#else /* !CONFIG_SPARSE_IRQ */
@@ -404,7 +409,7 @@ int free_irte(int irq)
static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
{
u64 addr;
- u32 cmd, sts;
+ u32 sts;
unsigned long flags;
addr = virt_to_phys((void *)iommu->ir_table->base);
@@ -415,28 +420,13 @@ static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
(addr) | IR_X2APIC_MODE(mode) | INTR_REMAP_TABLE_REG_SIZE);
/* Set interrupt-remapping table pointer */
- cmd = iommu->gcmd | DMA_GCMD_SIRTP;
iommu->gcmd |= DMA_GCMD_SIRTP;
- writel(cmd, iommu->reg + DMAR_GCMD_REG);
+ writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
readl, (sts & DMA_GSTS_IRTPS), sts);
spin_unlock_irqrestore(&iommu->register_lock, flags);
- if (mode == 0) {
- spin_lock_irqsave(&iommu->register_lock, flags);
-
- /* enable comaptiblity format interrupt pass through */
- cmd = iommu->gcmd | DMA_GCMD_CFI;
- iommu->gcmd |= DMA_GCMD_CFI;
- writel(cmd, iommu->reg + DMAR_GCMD_REG);
-
- IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
- readl, (sts & DMA_GSTS_CFIS), sts);
-
- spin_unlock_irqrestore(&iommu->register_lock, flags);
- }
-
/*
* global invalidation of interrupt entry cache before enabling
* interrupt-remapping.
@@ -446,9 +436,8 @@ static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
spin_lock_irqsave(&iommu->register_lock, flags);
/* Enable interrupt-remapping */
- cmd = iommu->gcmd | DMA_GCMD_IRE;
iommu->gcmd |= DMA_GCMD_IRE;
- writel(cmd, iommu->reg + DMAR_GCMD_REG);
+ writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
readl, (sts & DMA_GSTS_IRES), sts);
@@ -516,6 +505,23 @@ end:
spin_unlock_irqrestore(&iommu->register_lock, flags);
}
+int __init intr_remapping_supported(void)
+{
+ struct dmar_drhd_unit *drhd;
+
+ if (disable_intremap)
+ return 0;
+
+ for_each_drhd_unit(drhd) {
+ struct intel_iommu *iommu = drhd->iommu;
+
+ if (!ecap_ir_support(iommu->ecap))
+ return 0;
+ }
+
+ return 1;
+}
+
int __init enable_intr_remapping(int eim)
{
struct dmar_drhd_unit *drhd;
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 6f2e6295e773..0f4d51b11e5b 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -381,7 +381,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */
entry->msi_attrib.pos = pos;
- entry->mask_pos = msi_mask_bits_reg(pos, entry->msi_attrib.is_64);
+ entry->mask_pos = msi_mask_reg(pos, entry->msi_attrib.is_64);
/* All MSIs are unmasked by default, Mask them all */
if (entry->msi_attrib.maskbit)
pci_read_config_dword(dev, entry->mask_pos, &entry->masked);
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h
index 71f4df2ef654..a0662842550b 100644
--- a/drivers/pci/msi.h
+++ b/drivers/pci/msi.h
@@ -16,21 +16,15 @@
#define msi_lower_address_reg(base) (base + PCI_MSI_ADDRESS_LO)
#define msi_upper_address_reg(base) (base + PCI_MSI_ADDRESS_HI)
#define msi_data_reg(base, is64bit) \
- ( (is64bit == 1) ? base+PCI_MSI_DATA_64 : base+PCI_MSI_DATA_32 )
-#define msi_mask_bits_reg(base, is64bit) \
- ( (is64bit == 1) ? base+PCI_MSI_MASK_BIT : base+PCI_MSI_MASK_BIT-4)
-#define msi_disable(control) control &= ~PCI_MSI_FLAGS_ENABLE
+ (base + ((is64bit == 1) ? PCI_MSI_DATA_64 : PCI_MSI_DATA_32))
+#define msi_mask_reg(base, is64bit) \
+ (base + ((is64bit == 1) ? PCI_MSI_MASK_64 : PCI_MSI_MASK_32))
#define is_64bit_address(control) (!!(control & PCI_MSI_FLAGS_64BIT))
#define is_mask_bit_support(control) (!!(control & PCI_MSI_FLAGS_MASKBIT))
#define msix_table_offset_reg(base) (base + 0x04)
#define msix_pba_offset_reg(base) (base + 0x08)
-#define msix_enable(control) control |= PCI_MSIX_FLAGS_ENABLE
-#define msix_disable(control) control &= ~PCI_MSIX_FLAGS_ENABLE
#define msix_table_size(control) ((control & PCI_MSIX_FLAGS_QSIZE)+1)
-#define multi_msix_capable msix_table_size
-#define msix_unmask(address) (address & ~PCI_MSIX_FLAGS_BITMASK)
-#define msix_mask(address) (address | PCI_MSIX_FLAGS_BITMASK)
-#define msix_is_pending(address) (address & PCI_MSIX_FLAGS_PENDMASK)
+#define multi_msix_capable(control) msix_table_size((control))
#endif /* MSI_H */
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index a7eb1b46a5a8..85ebd02a64a7 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -492,6 +492,7 @@ write_vpd_attr(struct kobject *kobj, struct bin_attribute *bin_attr,
/**
* pci_read_legacy_io - read byte(s) from legacy I/O port space
* @kobj: kobject corresponding to file to read from
+ * @bin_attr: struct bin_attribute for this file
* @buf: buffer to store results
* @off: offset into legacy I/O port space
* @count: number of bytes to read
@@ -517,6 +518,7 @@ pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
/**
* pci_write_legacy_io - write byte(s) to legacy I/O port space
* @kobj: kobject corresponding to file to read from
+ * @bin_attr: struct bin_attribute for this file
* @buf: buffer containing value to be written
* @off: offset into legacy I/O port space
* @count: number of bytes to write
@@ -733,9 +735,9 @@ pci_mmap_resource_wc(struct kobject *kobj, struct bin_attribute *attr,
/**
* pci_remove_resource_files - cleanup resource files
- * @dev: dev to cleanup
+ * @pdev: dev to cleanup
*
- * If we created resource files for @dev, remove them from sysfs and
+ * If we created resource files for @pdev, remove them from sysfs and
* free their resources.
*/
static void
@@ -793,9 +795,9 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine)
/**
* pci_create_resource_files - create resource files in sysfs for @dev
- * @dev: dev in question
+ * @pdev: dev in question
*
- * Walk the resources in @dev creating files for each resource available.
+ * Walk the resources in @pdev creating files for each resource available.
*/
static int pci_create_resource_files(struct pci_dev *pdev)
{
@@ -829,6 +831,7 @@ void __weak pci_remove_resource_files(struct pci_dev *dev) { return; }
/**
* pci_write_rom - used to enable access to the PCI ROM display
* @kobj: kernel object handle
+ * @bin_attr: struct bin_attribute for this file
* @buf: user input
* @off: file offset
* @count: number of byte in input
@@ -852,6 +855,7 @@ pci_write_rom(struct kobject *kobj, struct bin_attribute *bin_attr,
/**
* pci_read_rom - read a PCI ROM
* @kobj: kernel object handle
+ * @bin_attr: struct bin_attribute for this file
* @buf: where to put the data we read from the ROM
* @off: file offset
* @count: number of bytes to read
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 16fd0d4c3166..34bf0fdf5047 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -681,11 +681,34 @@ EXPORT_SYMBOL(pci_choose_state);
#define PCI_EXP_SAVE_REGS 7
+#define pcie_cap_has_devctl(type, flags) 1
+#define pcie_cap_has_lnkctl(type, flags) \
+ ((flags & PCI_EXP_FLAGS_VERS) > 1 || \
+ (type == PCI_EXP_TYPE_ROOT_PORT || \
+ type == PCI_EXP_TYPE_ENDPOINT || \
+ type == PCI_EXP_TYPE_LEG_END))
+#define pcie_cap_has_sltctl(type, flags) \
+ ((flags & PCI_EXP_FLAGS_VERS) > 1 || \
+ ((type == PCI_EXP_TYPE_ROOT_PORT) || \
+ (type == PCI_EXP_TYPE_DOWNSTREAM && \
+ (flags & PCI_EXP_FLAGS_SLOT))))
+#define pcie_cap_has_rtctl(type, flags) \
+ ((flags & PCI_EXP_FLAGS_VERS) > 1 || \
+ (type == PCI_EXP_TYPE_ROOT_PORT || \
+ type == PCI_EXP_TYPE_RC_EC))
+#define pcie_cap_has_devctl2(type, flags) \
+ ((flags & PCI_EXP_FLAGS_VERS) > 1)
+#define pcie_cap_has_lnkctl2(type, flags) \
+ ((flags & PCI_EXP_FLAGS_VERS) > 1)
+#define pcie_cap_has_sltctl2(type, flags) \
+ ((flags & PCI_EXP_FLAGS_VERS) > 1)
+
static int pci_save_pcie_state(struct pci_dev *dev)
{
int pos, i = 0;
struct pci_cap_saved_state *save_state;
u16 *cap;
+ u16 flags;
pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
if (pos <= 0)
@@ -698,13 +721,22 @@ static int pci_save_pcie_state(struct pci_dev *dev)
}
cap = (u16 *)&save_state->data[0];
- pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &cap[i++]);
- pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]);
- pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
- pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
- pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &cap[i++]);
- pci_read_config_word(dev, pos + PCI_EXP_LNKCTL2, &cap[i++]);
- pci_read_config_word(dev, pos + PCI_EXP_SLTCTL2, &cap[i++]);
+ pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags);
+
+ if (pcie_cap_has_devctl(dev->pcie_type, flags))
+ pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &cap[i++]);
+ if (pcie_cap_has_lnkctl(dev->pcie_type, flags))
+ pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]);
+ if (pcie_cap_has_sltctl(dev->pcie_type, flags))
+ pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
+ if (pcie_cap_has_rtctl(dev->pcie_type, flags))
+ pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
+ if (pcie_cap_has_devctl2(dev->pcie_type, flags))
+ pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &cap[i++]);
+ if (pcie_cap_has_lnkctl2(dev->pcie_type, flags))
+ pci_read_config_word(dev, pos + PCI_EXP_LNKCTL2, &cap[i++]);
+ if (pcie_cap_has_sltctl2(dev->pcie_type, flags))
+ pci_read_config_word(dev, pos + PCI_EXP_SLTCTL2, &cap[i++]);
return 0;
}
@@ -714,6 +746,7 @@ static void pci_restore_pcie_state(struct pci_dev *dev)
int i = 0, pos;
struct pci_cap_saved_state *save_state;
u16 *cap;
+ u16 flags;
save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
@@ -721,13 +754,22 @@ static void pci_restore_pcie_state(struct pci_dev *dev)
return;
cap = (u16 *)&save_state->data[0];
- pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, cap[i++]);
- pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, cap[i++]);
- pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]);
- pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]);
- pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, cap[i++]);
- pci_write_config_word(dev, pos + PCI_EXP_LNKCTL2, cap[i++]);
- pci_write_config_word(dev, pos + PCI_EXP_SLTCTL2, cap[i++]);
+ pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags);
+
+ if (pcie_cap_has_devctl(dev->pcie_type, flags))
+ pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, cap[i++]);
+ if (pcie_cap_has_lnkctl(dev->pcie_type, flags))
+ pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, cap[i++]);
+ if (pcie_cap_has_sltctl(dev->pcie_type, flags))
+ pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]);
+ if (pcie_cap_has_rtctl(dev->pcie_type, flags))
+ pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]);
+ if (pcie_cap_has_devctl2(dev->pcie_type, flags))
+ pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, cap[i++]);
+ if (pcie_cap_has_lnkctl2(dev->pcie_type, flags))
+ pci_write_config_word(dev, pos + PCI_EXP_LNKCTL2, cap[i++]);
+ if (pcie_cap_has_sltctl2(dev->pcie_type, flags))
+ pci_write_config_word(dev, pos + PCI_EXP_SLTCTL2, cap[i++]);
}
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h
index c7ad68b6c6d6..aa14482a4779 100644
--- a/drivers/pci/pcie/aer/aerdrv.h
+++ b/drivers/pci/pcie/aer/aerdrv.h
@@ -95,6 +95,9 @@ struct aer_broadcast_data {
static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
enum pci_ers_result new)
{
+ if (new == PCI_ERS_RESULT_NONE)
+ return orig;
+
switch (orig) {
case PCI_ERS_RESULT_CAN_RECOVER:
case PCI_ERS_RESULT_RECOVERED:
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index e39982503863..13ffdc35ea0e 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -275,7 +275,7 @@ static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev,
memset(device, 0, sizeof(struct device));
device->bus = &pcie_port_bus_type;
device->driver = NULL;
- device->driver_data = NULL;
+ dev_set_drvdata(device, NULL);
device->release = release_pcie_device; /* callback to free pcie dev */
dev_set_name(device, "%s:pcie%02x",
pci_name(parent), get_descriptor_id(port_type, service_type));
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index b924e2463f85..091ce70051e0 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -200,7 +200,7 @@ static int slot_reset_iter(struct device *device, void *data)
static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)
{
- pci_ers_result_t status = PCI_ERS_RESULT_NONE;
+ pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
int retval;
/* If fatal, restore cfg space for possible link reset at upstream */
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 8eb50dffb78a..3daa7f824da1 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -193,7 +193,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN;
if (type == pci_bar_io) {
l &= PCI_BASE_ADDRESS_IO_MASK;
- mask = PCI_BASE_ADDRESS_IO_MASK & 0xffff;
+ mask = PCI_BASE_ADDRESS_IO_MASK & IO_SPACE_LIMIT;
} else {
l &= PCI_BASE_ADDRESS_MEM_MASK;
mask = (u32)PCI_BASE_ADDRESS_MEM_MASK;
@@ -237,6 +237,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
dev_printk(KERN_DEBUG, &dev->dev,
"reg %x 64bit mmio: %pR\n", pos, res);
}
+
+ res->flags |= IORESOURCE_MEM_64;
} else {
sz = pci_size(l, sz, mask);
@@ -362,7 +364,10 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
}
}
if (base <= limit) {
- res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH;
+ res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) |
+ IORESOURCE_MEM | IORESOURCE_PREFETCH;
+ if (res->flags & PCI_PREF_RANGE_TYPE_64)
+ res->flags |= IORESOURCE_MEM_64;
res->start = base;
res->end = limit + 0xfffff;
dev_printk(KERN_DEBUG, &dev->dev, "bridge %sbit mmio pref: %pR\n",
@@ -1118,10 +1123,6 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
return max;
}
-void __attribute__((weak)) set_pci_bus_resources_arch_default(struct pci_bus *b)
-{
-}
-
struct pci_bus * pci_create_bus(struct device *parent,
int bus, struct pci_ops *ops, void *sysdata)
{
@@ -1180,8 +1181,6 @@ struct pci_bus * pci_create_bus(struct device *parent,
b->resource[0] = &ioport_resource;
b->resource[1] = &iomem_resource;
- set_pci_bus_resources_arch_default(b);
-
return b;
dev_create_file_err:
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index c01c1196d45e..bd4253f93d5a 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2033,6 +2033,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS400_200, quirk_di
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS480, quirk_disable_all_msi);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3336, quirk_disable_all_msi);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disable_all_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3364, quirk_disable_all_msi);
/* Disable MSI on chipsets that are known to not support it */
static void __devinit quirk_disable_msi(struct pci_dev *dev)
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index 710d4ea69568..650bc0a538dc 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -115,36 +115,6 @@ pci_find_next_bus(const struct pci_bus *from)
#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
- * @devfn: encodes number of PCI slot in which the desired PCI
- * device resides and the logical device number within that slot
- * in case of multi-function devices.
- *
- * Given a PCI bus and slot/function number, the desired PCI device
- * is located in system global list of PCI devices. If the device
- * is found, a pointer to its data structure is returned. If no
- * device is found, %NULL is returned.
- *
- * NOTE: Do not use this function any more; use pci_get_slot() instead, as
- * the PCI device returned by this function can disappear at any moment in
- * time.
- */
-struct pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn)
-{
- struct pci_dev *dev = NULL;
-
- while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
- if (dev->bus->number == bus && dev->devfn == devfn) {
- pci_dev_put(dev);
- return dev;
- }
- }
- return NULL;
-}
-EXPORT_SYMBOL(pci_find_slot);
-
-/**
* pci_find_device - begin or continue searching for a PCI device by vendor/device id
* @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
* @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 8d9da9d30a61..b636e245445d 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -58,7 +58,6 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus)
res = list->res;
idx = res - &list->dev->resource[0];
if (pci_assign_resource(list->dev, idx)) {
- /* FIXME: get rid of this */
res->start = 0;
res->end = 0;
res->flags = 0;
@@ -143,6 +142,7 @@ static void pci_setup_bridge(struct pci_bus *bus)
struct pci_dev *bridge = bus->self;
struct pci_bus_region region;
u32 l, bu, lu, io_upper16;
+ int pref_mem64;
if (pci_is_enabled(bridge))
return;
@@ -198,16 +198,22 @@ static void pci_setup_bridge(struct pci_bus *bus)
pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
/* Set up PREF base/limit. */
+ pref_mem64 = 0;
bu = lu = 0;
pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
if (bus->resource[2]->flags & IORESOURCE_PREFETCH) {
+ int width = 8;
l = (region.start >> 16) & 0xfff0;
l |= region.end & 0xfff00000;
- bu = upper_32_bits(region.start);
- lu = upper_32_bits(region.end);
- dev_info(&bridge->dev, " PREFETCH window: %#016llx-%#016llx\n",
- (unsigned long long)region.start,
- (unsigned long long)region.end);
+ if (bus->resource[2]->flags & IORESOURCE_MEM_64) {
+ pref_mem64 = 1;
+ bu = upper_32_bits(region.start);
+ lu = upper_32_bits(region.end);
+ width = 16;
+ }
+ dev_info(&bridge->dev, " PREFETCH window: %#0*llx-%#0*llx\n",
+ width, (unsigned long long)region.start,
+ width, (unsigned long long)region.end);
}
else {
l = 0x0000fff0;
@@ -215,9 +221,11 @@ static void pci_setup_bridge(struct pci_bus *bus)
}
pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
- /* Set the upper 32 bits of PREF base & limit. */
- pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu);
- pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
+ if (pref_mem64) {
+ /* Set the upper 32 bits of PREF base & limit. */
+ pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu);
+ pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
+ }
pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
}
@@ -255,8 +263,25 @@ static void pci_bridge_check_ranges(struct pci_bus *bus)
pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem);
pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0);
}
- if (pmem)
+ if (pmem) {
b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
+ if ((pmem & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64)
+ b_res[2].flags |= IORESOURCE_MEM_64;
+ }
+
+ /* double check if bridge does support 64 bit pref */
+ if (b_res[2].flags & IORESOURCE_MEM_64) {
+ u32 mem_base_hi, tmp;
+ pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32,
+ &mem_base_hi);
+ pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32,
+ 0xffffffff);
+ pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32, &tmp);
+ if (!tmp)
+ b_res[2].flags &= ~IORESOURCE_MEM_64;
+ pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32,
+ mem_base_hi);
+ }
}
/* Helper function for sizing routines: find first available
@@ -336,6 +361,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */
int order, max_order;
struct resource *b_res = find_free_bus_resource(bus, type);
+ unsigned int mem64_mask = 0;
if (!b_res)
return 0;
@@ -344,9 +370,12 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
max_order = 0;
size = 0;
+ mem64_mask = b_res->flags & IORESOURCE_MEM_64;
+ b_res->flags &= ~IORESOURCE_MEM_64;
+
list_for_each_entry(dev, &bus->devices, bus_list) {
int i;
-
+
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *r = &dev->resource[i];
resource_size_t r_size;
@@ -372,6 +401,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
aligns[order] += align;
if (order > max_order)
max_order = order;
+ mem64_mask &= r->flags & IORESOURCE_MEM_64;
}
}
@@ -396,6 +426,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
b_res->start = min_align;
b_res->end = size + min_align - 1;
b_res->flags |= IORESOURCE_STARTALIGN;
+ b_res->flags |= mem64_mask;
return 1;
}
@@ -536,11 +567,13 @@ static void pci_bus_dump_res(struct pci_bus *bus)
for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
struct resource *res = bus->resource[i];
- if (!res)
+ if (!res || !res->end)
continue;
dev_printk(KERN_DEBUG, &bus->dev, "resource %d %s %pR\n", i,
- (res->flags & IORESOURCE_IO) ? "io: " : "mem:", res);
+ (res->flags & IORESOURCE_IO) ? "io: " :
+ ((res->flags & IORESOURCE_PREFETCH)? "pref mem":"mem:"),
+ res);
}
}
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 3039fcb86afc..0b6908b48935 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -135,23 +135,16 @@ void pci_disable_bridge_window(struct pci_dev *dev)
}
#endif /* CONFIG_PCI_QUIRKS */
-int pci_assign_resource(struct pci_dev *dev, int resno)
+static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
+ int resno)
{
- struct pci_bus *bus = dev->bus;
struct resource *res = dev->resource + resno;
resource_size_t size, min, align;
int ret;
size = resource_size(res);
min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
-
align = resource_alignment(res);
- if (!align) {
- dev_info(&dev->dev, "BAR %d: can't allocate resource (bogus "
- "alignment) %pR flags %#lx\n",
- resno, res, res->flags);
- return -EINVAL;
- }
/* First, try exact prefetching match.. */
ret = pci_bus_alloc_resource(bus, res, size, align, min,
@@ -169,10 +162,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
pcibios_align_resource, dev);
}
- if (ret) {
- dev_info(&dev->dev, "BAR %d: can't allocate %s resource %pR\n",
- resno, res->flags & IORESOURCE_IO ? "I/O" : "mem", res);
- } else {
+ if (!ret) {
res->flags &= ~IORESOURCE_STARTALIGN;
if (resno < PCI_BRIDGE_RESOURCES)
pci_update_resource(dev, resno);
@@ -181,6 +171,39 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
return ret;
}
+int pci_assign_resource(struct pci_dev *dev, int resno)
+{
+ struct resource *res = dev->resource + resno;
+ resource_size_t align;
+ struct pci_bus *bus;
+ int ret;
+
+ align = resource_alignment(res);
+ if (!align) {
+ dev_info(&dev->dev, "BAR %d: can't allocate resource (bogus "
+ "alignment) %pR flags %#lx\n",
+ resno, res, res->flags);
+ return -EINVAL;
+ }
+
+ bus = dev->bus;
+ while ((ret = __pci_assign_resource(bus, dev, resno))) {
+ if (bus->parent && bus->self->transparent)
+ bus = bus->parent;
+ else
+ bus = NULL;
+ if (bus)
+ continue;
+ break;
+ }
+
+ if (ret)
+ dev_info(&dev->dev, "BAR %d: can't allocate %s resource %pR\n",
+ resno, res->flags & IORESOURCE_IO ? "I/O" : "mem", res);
+
+ return ret;
+}
+
#if 0
int pci_assign_resource_fixed(struct pci_dev *dev, int resno)
{
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c
index 21189447e545..fe95ce20bcbd 100644
--- a/drivers/pci/slot.c
+++ b/drivers/pci/slot.c
@@ -264,8 +264,8 @@ EXPORT_SYMBOL_GPL(pci_create_slot);
/**
* pci_renumber_slot - update %struct pci_slot -> number
- * @slot - %struct pci_slot to update
- * @slot_nr - new number for slot
+ * @slot: &struct pci_slot to update
+ * @slot_nr: new number for slot
*
* The primary purpose of this interface is to allow callers who earlier
* created a placeholder slot in pci_create_slot() by passing a -1 as
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index 1cd02f5a23a0..bc43f78f6f0b 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -255,6 +255,9 @@ static int __init sharpsl_pcmcia_init(void)
{
int ret;
+ if (!platform_scoop_config)
+ return -ENODEV;
+
sharpsl_pcmcia_ops.nr = platform_scoop_config->num_devs;
sharpsl_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 284ebaca6e45..075791fe663c 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -143,6 +143,19 @@ config MSI_LAPTOP
If you have an MSI S270 laptop, say Y or M here.
+config OQO_WMI
+ tristate "OQO WMI extras"
+ depends on ACPI_WMI
+ depends on INPUT && INPUT_POLLDEV
+ depends on RFKILL
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ Say Y here if you want to support rfkill and backlight control on
+ series 2 OQO handheld devices.
+
+ To compile this driver as a module, choose M here: the module will
+ be called oqo-wmi.
+
config PANASONIC_LAPTOP
tristate "Panasonic Laptop Extras"
depends on INPUT && ACPI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index e40c7bd1b87e..1637378ad3f4 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o
obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o
+obj-$(CONFIG_OQO_WMI) += oqo-wmi.o
obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o
obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
obj-$(CONFIG_ACPI_WMI) += wmi.o
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 62d02b3c998e..0f6e43bf4fc2 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -1005,6 +1005,7 @@ enum rfkill_type type, char *name, u32 cap)
*data = cap;
rfkill_dev->data = data;
rfkill_dev->toggle_radio = acer_rfkill_set;
+ rfkill_dev->user_claim_unsupported = 1;
err = rfkill_register(rfkill_dev);
if (err) {
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index fe171fad12cf..50d9019de2be 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -434,6 +434,7 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
wifi_rfkill->name = "hp-wifi";
wifi_rfkill->state = hp_wmi_wifi_state();
wifi_rfkill->toggle_radio = hp_wmi_wifi_set;
+ wifi_rfkill->user_claim_unsupported = 1;
err = rfkill_register(wifi_rfkill);
if (err)
goto add_sysfs_error;
@@ -445,6 +446,7 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
bluetooth_rfkill->name = "hp-bluetooth";
bluetooth_rfkill->state = hp_wmi_bluetooth_state();
bluetooth_rfkill->toggle_radio = hp_wmi_bluetooth_set;
+ bluetooth_rfkill->user_claim_unsupported = 1;
err = rfkill_register(bluetooth_rfkill);
if (err)
goto register_bluetooth_error;
@@ -455,6 +457,7 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
wwan_rfkill->name = "hp-wwan";
wwan_rfkill->state = hp_wmi_wwan_state();
wwan_rfkill->toggle_radio = hp_wmi_wwan_set;
+ wwan_rfkill->user_claim_unsupported = 1;
err = rfkill_register(wwan_rfkill);
if (err)
goto register_wwan_err;
diff --git a/drivers/platform/x86/oqo-wmi.c b/drivers/platform/x86/oqo-wmi.c
new file mode 100644
index 000000000000..0a88af82f127
--- /dev/null
+++ b/drivers/platform/x86/oqo-wmi.c
@@ -0,0 +1,941 @@
+/*
+ * OQO WMI UPMC Extras
+ *
+ * Copyright (C) 2008 Brian S. Julin <bri@abrij.org>
+ *
+ * Based on acer-wmi:
+ * Copyright (C) 2007-2008 Carlos Corbacho <cathectic@gmail.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
+ */
+
+/*
+ * NOTE: You need to turn SMI on in BIOS (if dmidecode works, you already have)
+ * NOTE: acpi-wmi support mandatory
+ * NOTE: backlight and inputdev support a must, ifdefs will come later
+ */
+
+/*
+ *
+ * 0.3: added WLAN enable switch, restore settings on unload,
+ * resume/suspend handling
+ * 0.2: Still not production-ready, but added ambient light sensor,
+ * backlight, and it prints the unit serial number to dmesg (do
+ * not know where to make that available to userspace yet.)
+ * 0.1: This is a first cut. Plan to reboot after playing with this.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/dmi.h>
+#include <linux/backlight.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/acpi.h>
+#include <linux/i8042.h>
+#include <linux/input-polldev.h>
+#include <linux/rfkill.h>
+
+#include <acpi/acpi_drivers.h>
+
+MODULE_AUTHOR("Brian Julin");
+MODULE_DESCRIPTION("OQO UPMC WMI Extras Driver");
+MODULE_LICENSE("GPL");
+
+#define OQO_LOGPREFIX "oqo-wmi: "
+#define OQO_ERR KERN_ERR OQO_LOGPREFIX
+#define OQO_NOTICE KERN_NOTICE OQO_LOGPREFIX
+#define OQO_INFO KERN_INFO OQO_LOGPREFIX
+
+#define OQO_KINE_MAXTRY 3
+
+/* Store defined devices globally since we only have one instance. */
+static struct platform_device *oqo_platform_device;
+static struct backlight_device *oqo_backlight_device;
+static struct rfkill *oqo_rfkill;
+static struct input_dev *oqo_kine;
+static struct input_polled_dev *oqo_kine_polled;
+
+/* Likewise store current and original settings globally. */
+struct oqo_settings {
+ int lid_wakes; /* not sure if ACPI handles/needs help here */
+ int kine_itvl;
+ int bl_bright;
+};
+
+static struct oqo_settings orig, curr;
+
+/* Some of this code is left like in acer-wmi so we can add the older
+ Model 01 and any future models more easily, but we should not expect
+ it to be as complicated as Acer given each model is a leap rather than
+ a subtle variant on the last, so we aren't using "quirks" perse. Not
+ sure if there is any real difference for our purposes between the o2
+ and e2.
+*/
+struct oqo_model {
+ const char *model;
+ u16 model_subs;
+};
+#define MODEL_SUB_OQO_O2_SMB0 3
+
+static struct oqo_model oqo_models[] = {
+ {
+ .model = "Model 2",
+ .model_subs = MODEL_SUB_OQO_O2_SMB0,
+ },
+ {}
+};
+
+static struct oqo_model *model;
+
+static int force;
+module_param(force, bool, 0644);
+MODULE_PARM_DESC(force, "Force WMI detection even if DMI detection failed");
+
+/*
+ * OQO Model 2 SMBUS registers
+ * We are just using WMI to read the Cx700 smbus, to share the
+ * ACPI mutex (what may also eventually work in VMs/win32)
+ * Using i2c-viapro directly could interfere with PM.
+ */
+
+#define OQO_O2_SMB0_WWAN_DSBL_ADDR 0x19
+#define OQO_O2_SMB0_WWAN_DSBL_MASK 0x02
+#define OQO_O2_SMB0_LUMIN_LO 0x20
+#define OQO_O2_SMB0_LUMIN_HI 0x21
+#define OQO_O2_SMB0_BL_LO 0x26
+#define OQO_O2_SMB0_BL_HI 0x27
+#define OQO_O2_SMB0_ACCEL_POLL_ITVL 0x45
+#define OQO_O2_SMB0_ACCEL_XLO 0x50
+#define OQO_O2_SMB0_ACCEL_XHI 0x51
+#define OQO_O2_SMB0_ACCEL_YLO 0x52
+#define OQO_O2_SMB0_ACCEL_YHI 0x53
+#define OQO_O2_SMB0_ACCEL_ZLO 0x54
+#define OQO_O2_SMB0_ACCEL_ZHI 0x55
+/* These may be handled by ACPI not sure yet. */
+#define OQO_O2_SMB0_LID_WAKES_ADDR 0x58
+#define OQO_O2_SMB0_LID_WAKES_MASK 0x08
+
+#define OQO_O2_SMB0_SERIAL_START 0x70
+#define OQO_O2_SMB0_SERIAL_LEN 11
+
+static char oqo_sn[OQO_O2_SMB0_SERIAL_LEN + 1];
+
+/* Other addresses I have noticed used on the 02 SMBUS (from DSDT and whatnot)
+ *
+ * These are not used because the linux ACPI drivers work fine on them
+ *
+ * 0x0A -- processor sleep mode?
+ * 0x0C -- ACPI events, probably clears when read.
+ * 0x30 -- thermal zone
+ * There is something going on at 0x31 through 0x34 which is likely
+ * also thermal. The values change over time. Have not figured that
+ * out yet.
+ * 0x41 -- AC detect
+ * 0x42 -- LID button ACTUALLY THIS DOES NOT WORK AND NEEDS TO BE FIXED
+ * 0xa0 and 0xa1 -- battery something (presence? state?)
+ * 0xa4 to 0xcf -- battery info (0xc8-0xca contains "OQO")
+ * 0xd4 to 0xef -- other battery stats
+ */
+
+/*
+ * OQO method GUIDs
+ */
+#define OQO_O2_AMW0_GUID "ABBC0F6D-8EA1-11D1-00A0-C90629100000"
+MODULE_ALIAS("wmi:ABBC0F6D-8EA1-11D1-00A0-C90629100000");
+
+/*
+ * Interface type flags
+ */
+enum interface_type {
+ OQO_O2_AMW0,
+};
+
+/* Each low-level interface must define at least some of the following */
+struct wmi_interface {
+ /* The WMI device type */
+ u32 type;
+};
+
+static struct wmi_interface AMW0_interface = {
+ .type = OQO_O2_AMW0,
+};
+
+/* The detected/chosen interface */
+static struct wmi_interface *interface;
+
+static int dmi_matched(const struct dmi_system_id *dmi)
+{
+ model = dmi->driver_data;
+ /*
+ * Detect which ACPI-WMI interface we're using.
+ */
+ if (wmi_has_guid(OQO_O2_AMW0_GUID))
+ interface = &AMW0_interface;
+
+ return 0;
+}
+
+static struct dmi_system_id oqo_dmis[] = {
+ {
+ .callback = dmi_matched,
+ .ident = "OQO 02",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "OQO Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "OQO Model 2"),
+ },
+ .driver_data = oqo_models + 0,
+ },
+ {}
+};
+
+/*
+ * AMW0 (V1) interface on OQO Model 2
+ *
+ * wmba: has four functions selected by int arg 1. arg2 is 3 byte buffer.
+ * 1: performs GETB method on the SMBUS using bytes 0, 1 of Arg2
+ * returns a buffer object containing a single byte
+ * 2: performs SETB on SMBUS using bytes 0, 1, 2 of Arg2
+ * returns 0 as int.
+ * 3: dumps 256 values into a given SMBUS register (not used here)
+ * returns 0 as int.
+ * 4: puts byte 0 of arg2 into some sort of busy flag. Some ACPI
+ * funcs check this (==0) to decide if SMBUS operations are safe.
+ * returns 0 as int.
+ * wmbb: simply returns the busy flag set by wmba #4
+ */
+static acpi_status oqo_smbus_getb(u8 addr, u8 *result)
+{
+ struct acpi_buffer input, res;
+ acpi_status status;
+ union acpi_object *obj;
+ u32 arg2;
+
+ input.length = 4;
+ input.pointer = &arg2;
+ res.length = ACPI_ALLOCATE_BUFFER;
+ res.pointer = NULL;
+
+ arg2 = addr;
+ arg2 <<= 8;
+ arg2 |= 0x12; /* HOSTCMD */
+
+ status = wmi_evaluate_method(OQO_O2_AMW0_GUID, 1, 1, &input, &res);
+
+ if (status != AE_OK)
+ return status;
+
+ obj = (union acpi_object *)res.pointer;
+ if (!obj)
+ return AE_NULL_OBJECT;
+
+ if (obj->type != ACPI_TYPE_BUFFER
+ || obj->buffer.length != 1 || obj->buffer.pointer == NULL) {
+ kfree(obj);
+ return AE_TYPE;
+ }
+ *result = ((u8 *) (obj->buffer.pointer))[0];
+ kfree(obj);
+ return status;
+}
+
+static acpi_status oqo_smbus_setb(u8 addr, u8 val)
+{
+ struct acpi_buffer input, res;
+ acpi_status status;
+ union acpi_object *obj;
+ u32 arg2;
+
+ input.length = 4;
+ input.pointer = &arg2;
+ res.length = ACPI_ALLOCATE_BUFFER;
+ res.pointer = NULL;
+
+ arg2 = val;
+ arg2 <<= 8;
+ arg2 |= addr;
+ arg2 <<= 8;
+ arg2 |= 0x12; /* HOSTCMD */
+
+ status = wmi_evaluate_method(OQO_O2_AMW0_GUID, 1, 2, &input, &res);
+
+ if (status != AE_OK)
+ return status;
+
+ obj = (union acpi_object *)res.pointer;
+ if (!obj)
+ return AE_NULL_OBJECT;
+
+ if (obj->type != ACPI_TYPE_INTEGER) {
+ kfree(obj);
+ return AE_TYPE;
+ }
+ kfree(obj);
+ return status;
+}
+
+/*
+ * We assume we are the only one using this ...ahem... "lock" on
+ * the SMBUS because it would be pathetically noneffective otherwise.
+ *
+ * Nonzero silly_lock will keep certain ACPI routines away from the
+ * SMBUS (if they aren't already on it when you call it.) Zero
+ * silly_lock will let them back on
+ *
+ * This is probably useful before sleeping the system, and one
+ * waits until any ACPI funcs would have long finished before
+ * proceeding. It seems harmless enough and will work to wrap
+ * more accesses with it.
+ */
+static acpi_status oqo_lock_smbus(int silly_lock)
+{
+ struct acpi_buffer input, res;
+ acpi_status status;
+ union acpi_object *obj;
+ u32 arg2;
+
+ input.length = 4;
+ input.pointer = &arg2;
+ res.length = ACPI_ALLOCATE_BUFFER;
+ res.pointer = NULL;
+
+ arg2 = !!silly_lock;
+
+ status = wmi_evaluate_method(OQO_O2_AMW0_GUID, 1, 4, &input, &res);
+
+ if (status != AE_OK)
+ return status;
+
+ obj = (union acpi_object *)res.pointer;
+ if (!obj)
+ return AE_NULL_OBJECT;
+
+ if (obj->type != ACPI_TYPE_INTEGER) {
+ kfree(obj);
+ return AE_TYPE;
+ }
+ kfree(obj);
+ return status;
+}
+
+static int smread_s16(u8 hi_addr, u8 lo_addr)
+{
+ s16 ret = -1;
+ acpi_status status;
+ u8 r;
+
+ /* Keep some ACPI routines off the SMBUS */
+ status = oqo_lock_smbus(1);
+ if (ACPI_FAILURE(status))
+ goto skip;
+
+ status = oqo_smbus_getb(hi_addr, &r);
+ if (ACPI_FAILURE(status))
+ goto skip;
+
+ ret = r;
+ ret <<= 8;
+
+ status = oqo_smbus_getb(lo_addr, &r);
+ if (ACPI_FAILURE(status)) {
+ ret = -1;
+ goto skip;
+ }
+
+ ret |= r;
+ ret &= 0x7fff;
+skip:
+ /* Let ACPI routines back on the SMBUS */
+ status = oqo_lock_smbus(0);
+ if (ACPI_FAILURE(status))
+ return -1;
+ return (int)ret;
+}
+
+static int smwrite_s16(u8 hi_addr, u8 lo_addr, s16 val)
+{
+ acpi_status status;
+ u8 r;
+ int ret = -1;
+
+ status = oqo_lock_smbus(1);
+ if (ACPI_FAILURE(status))
+ goto skip;
+
+ r = (val >> 8) & 0x7f;
+ status = oqo_smbus_setb(hi_addr, r);
+ if (ACPI_FAILURE(status))
+ goto skip;
+
+ r = val & 0xff;
+ status = oqo_smbus_setb(lo_addr, r);
+ if (ACPI_FAILURE(status))
+ goto skip;
+
+ ret = 0;
+skip:
+ status = oqo_lock_smbus(0);
+ if (ACPI_FAILURE(status))
+ return -1;
+ return ret;
+}
+
+static int smread_u8(u8 addr)
+{
+ int ret = -1;
+ acpi_status status;
+ u8 r;
+
+ status = oqo_lock_smbus(1);
+ if (ACPI_FAILURE(status))
+ goto skip;
+
+ status = oqo_smbus_getb(addr, &r);
+ if (ACPI_FAILURE(status))
+ goto skip;
+
+ ret = r;
+skip:
+ status = oqo_lock_smbus(0);
+ if (ACPI_FAILURE(status))
+ return -1;
+ return (int)ret;
+}
+
+static int smwrite_u8(u8 addr, u8 val)
+{
+ acpi_status status;
+ int ret = -1;
+
+ status = oqo_lock_smbus(1);
+ if (ACPI_FAILURE(status))
+ goto skip;
+
+ status = oqo_smbus_setb(addr, val);
+ if (ACPI_FAILURE(status))
+ goto skip;
+
+ ret = 0;
+skip:
+ status = oqo_lock_smbus(0);
+ if (ACPI_FAILURE(status))
+ return -1;
+ return ret;
+}
+
+/*
+ * Accelerometer inputdev
+ */
+
+/*
+ * Get a reading of the accelerometer from the firwmware and push
+ * it to an inputdev.
+ *
+ * Also the ambient light detector hitch-hikes on the inputdev, since
+ * it could be useful in some of the same applications for accelerometers.
+ *
+ * Available information and a bit of poking have not found a
+ * way to freeze a snapshot of the accelerometer data, so we have
+ * to do consistency checks to reduce the odds that we mix low
+ * and high bytes from different updates.
+ *
+ * Unfortunately SMBUS access is very slow (11ms) and the firmware API
+ * does not provide 2-byte transfers, so mixed readings happen and
+ * have to be corrected a lot. (Do not know why; it should be a
+ * multi-kHz.. bus and the reads take only a hundred-ish cycles/byte.
+ * It is not the ACPI function -- it is slow on i2c-viapro as well.)
+ *
+ * Since there is such a big time lag between readings, the axis
+ * are decoupled and reported separately on different timelines as
+ * different events rather than as a set.
+ */
+static acpi_status oqo_read_kine(int *good, s16 *x, s16 *y, s16 *z,
+ u16 *lumin)
+{
+ u8 hiregs[4] = { OQO_O2_SMB0_ACCEL_XHI,
+ OQO_O2_SMB0_ACCEL_YHI,
+ OQO_O2_SMB0_ACCEL_ZHI,
+ OQO_O2_SMB0_LUMIN_HI
+ };
+ u8 loregs[4] = { OQO_O2_SMB0_ACCEL_XLO,
+ OQO_O2_SMB0_ACCEL_YLO,
+ OQO_O2_SMB0_ACCEL_ZLO,
+ OQO_O2_SMB0_LUMIN_LO
+ };
+
+ short ax[4] = { ABS_X, ABS_Y, ABS_Z, ABS_MISC };
+ u8 realgood = 0;
+ u16 res[4];
+ acpi_status status;
+ int i;
+
+ *good = 0;
+
+ /* Routine: Starting with the lo byte, read lo/hi bytes
+ alternately until two lo byte readings, match. Then
+ take that reading and combine it with the hi reading
+ sandwiched between. Errors can still happen when
+ jittering at wrap boundaries, but should be rare.
+
+ Don't use this for missile guidance.
+
+ Userspace post-processing error detection encouraged.
+ */
+ for (i = 0; i < 4; i++) {
+ int maxtry;
+ u32 log;
+ u8 r, lo, hi;
+
+ lo = loregs[i];
+ hi = hiregs[i];
+ log = 0;
+
+#define LOGRES(reg) do { \
+ status = oqo_smbus_getb(reg, &r); \
+ log <<= 8; log |= r; log &= 0xffffff; \
+ if (ACPI_FAILURE(status)) \
+ goto leave; \
+ } while (0)
+
+ maxtry = OQO_KINE_MAXTRY + 1;
+ while (maxtry) {
+ LOGRES(lo);
+ if (maxtry <= OQO_KINE_MAXTRY &&
+ (log >> 16) == (log & 0xff)) {
+ *(res + i) = log & 0xffff;
+ break;
+ }
+ LOGRES(hi);
+ maxtry--;
+ }
+
+ if (maxtry == OQO_KINE_MAXTRY)
+ realgood |= 1 << i;
+
+ if (maxtry) {
+ *good |= 1 << i;
+ /* JIC CYA: this bit may be reserved */
+ res[3] &= 0x7fff;
+ input_report_abs(oqo_kine, ax[i], (s16) res[i]);
+ }
+ /* else we had trouble getting the reading to lock
+ and we skip reporting this axis.
+ */
+ }
+
+ *x = (u16) res[0];
+ *y = (u16) res[1];
+ *z = (u16) res[2];
+ *lumin = (u16) res[3];
+ return status;
+leave:
+ return status;
+}
+
+/*
+ * Generic Device (interface-independent)
+ */
+
+static void oqo_kine_poll(struct input_polled_dev *dev)
+{
+ s16 x, y, z;
+ u16 lumin;
+ int good;
+ /* struct timeval tv1, tv2; */
+
+ if (dev != oqo_kine_polled)
+ return;
+ if (orig.kine_itvl < 0)
+ return;
+
+ x = y = z = 0;
+ oqo_read_kine(&good, &x, &y, &z, &lumin);
+}
+
+static int __devinit oqo_kine_init(void)
+{
+ int err;
+
+ oqo_kine = input_allocate_device();
+ if (!oqo_kine)
+ return -ENOMEM;
+
+ oqo_kine->name = "OQO embedded accelerometer";
+ oqo_kine->phys = "platform:oqo-wmi:kine";
+ oqo_kine->id.bustype = 0;
+ oqo_kine->id.vendor = 0;
+ oqo_kine->id.product = 2;
+ oqo_kine->id.version = 0;
+ oqo_kine->evbit[0] = BIT_MASK(EV_ABS);
+ set_bit(ABS_X, oqo_kine->absbit);
+ set_bit(ABS_Y, oqo_kine->absbit);
+ set_bit(ABS_Z, oqo_kine->absbit);
+ set_bit(ABS_MISC, oqo_kine->absbit);
+ oqo_kine->absmin[ABS_X] =
+ oqo_kine->absmin[ABS_Y] =
+ oqo_kine->absmin[ABS_Z] = oqo_kine->absmin[ABS_MISC] = -32768;
+ oqo_kine->absmax[ABS_X] =
+ oqo_kine->absmax[ABS_Y] =
+ oqo_kine->absmax[ABS_Z] = oqo_kine->absmax[ABS_MISC] = 32767;
+
+ dev_set_name(&oqo_kine->dev, "kine");
+
+ oqo_kine_polled = input_allocate_polled_device();
+ if (!oqo_kine_polled) {
+ err = -ENOMEM;
+ goto bail0;
+ }
+
+ oqo_kine_polled->poll = oqo_kine_poll;
+ oqo_kine_polled->poll_interval = 250;
+ oqo_kine_polled->input = oqo_kine;
+
+ orig.kine_itvl = -1; /* prevent callback from running */
+ err = input_register_polled_device(oqo_kine_polled);
+ if (err) {
+ printk(OQO_ERR "Failed to register OQO kine input\n");
+ goto bail1;
+ }
+
+ /* This will allow the callback to run now if successful. */
+ orig.kine_itvl = smread_u8(OQO_O2_SMB0_ACCEL_POLL_ITVL);
+ smwrite_u8(OQO_O2_SMB0_ACCEL_POLL_ITVL, 250);
+ curr.kine_itvl = smread_u8(OQO_O2_SMB0_ACCEL_POLL_ITVL);
+ if (orig.kine_itvl < 0 || curr.kine_itvl != 250) {
+ printk(OQO_ERR "Test communication with kine sensor failed\n");
+ err = -ENODEV;
+ goto bail2;
+ }
+
+ printk(OQO_INFO "Created OQO kine input.\n");
+ printk(OQO_INFO "Firmware interval %ims, driver interval %ims\n",
+ curr.kine_itvl, oqo_kine_polled->poll_interval);
+ return 0;
+bail2:
+ input_unregister_polled_device(oqo_kine_polled);
+bail1:
+ input_free_polled_device(oqo_kine_polled); /* frees oqo_kine */
+ return err;
+bail0:
+ input_free_device(oqo_kine);
+ return err;
+}
+
+static void __devexit oqo_kine_fini(void)
+{
+ smwrite_u8(OQO_O2_SMB0_ACCEL_POLL_ITVL, orig.kine_itvl);
+ input_unregister_polled_device(oqo_kine_polled);
+ input_free_polled_device(oqo_kine_polled);
+}
+
+/*
+ * Backlight device
+ */
+static int read_brightness(struct backlight_device *bd)
+{
+ return (int)smread_s16(OQO_O2_SMB0_BL_HI, OQO_O2_SMB0_BL_LO);
+}
+
+static int update_bl_status(struct backlight_device *bd)
+{
+ return smwrite_s16(OQO_O2_SMB0_BL_HI,
+ OQO_O2_SMB0_BL_LO, (s16) bd->props.brightness);
+}
+
+static struct backlight_ops oqo_bl_ops = {
+ .get_brightness = read_brightness,
+ .update_status = update_bl_status,
+};
+
+static int __devinit oqo_backlight_init(struct device *dev)
+{
+ struct backlight_device *bd;
+
+ /*
+ * It would be nice if someone would figure out how backlights
+ * like these, which are not driven through the video hardware,
+ * are supposed to find their associated fb and bind to it (and
+ * rebind when fb drivers change.
+ *
+ * Most extras backlights just shove a junk name in like we do here,
+ * and don't end up integrated with fbcon sysfs as a result.
+ */
+ bd = backlight_device_register("oqo-bl", dev, NULL, &oqo_bl_ops);
+
+ if (IS_ERR(bd)) {
+ printk(OQO_ERR "Could not register OQO backlight device\n");
+ oqo_backlight_device = NULL;
+ return PTR_ERR(bd);
+ }
+
+ oqo_backlight_device = bd;
+ bd->props.max_brightness = 0x7fff;
+ curr.bl_bright = orig.bl_bright = bd->props.brightness =
+ read_brightness(NULL);
+
+ if (bd->props.brightness < 0)
+ goto fail;
+
+ backlight_update_status(bd);
+ printk(OQO_INFO "Found backlight set at %i\n", bd->props.brightness);
+ return 0;
+
+fail:
+ backlight_device_unregister(oqo_backlight_device);
+ oqo_backlight_device = NULL;
+ return -ENODEV;
+}
+
+static void __devexit oqo_backlight_fini(void)
+{
+ if (!oqo_backlight_device)
+ return;
+ oqo_backlight_device->props.brightness = orig.bl_bright;
+ backlight_update_status(oqo_backlight_device);
+ backlight_device_unregister(oqo_backlight_device);
+}
+
+/*
+ * RFKill device
+ */
+
+static int oqo_rfkill_get(void *data, enum rfkill_state *state)
+{
+ int res;
+
+ res = smread_u8(OQO_O2_SMB0_WWAN_DSBL_ADDR);
+ if (res < 0)
+ return res;
+
+ res &= OQO_O2_SMB0_WWAN_DSBL_MASK;
+
+ if (res)
+ *state = RFKILL_STATE_SOFT_BLOCKED;
+ else
+ *state = RFKILL_STATE_UNBLOCKED;
+
+ return 0;
+}
+
+static int oqo_rfkill_toggle(void *data, enum rfkill_state state)
+{
+ int res;
+
+ res = smread_u8(OQO_O2_SMB0_WWAN_DSBL_ADDR);
+
+ if (state == RFKILL_STATE_UNBLOCKED)
+ res &= ~OQO_O2_SMB0_WWAN_DSBL_MASK;
+ else
+ res |= OQO_O2_SMB0_WWAN_DSBL_MASK;
+
+ return smwrite_u8(OQO_O2_SMB0_WWAN_DSBL_ADDR, res);
+}
+
+static int __devinit oqo_rfkill_init(struct device *dev)
+{
+ int res;
+
+ oqo_rfkill = rfkill_allocate(dev, RFKILL_TYPE_WWAN);
+ if (!oqo_rfkill)
+ return -ENODEV;
+
+ res = smread_u8(OQO_O2_SMB0_WWAN_DSBL_ADDR);
+ res &= OQO_O2_SMB0_WWAN_DSBL_MASK;
+
+ oqo_rfkill->name = "oqo-wwan";
+ if (res)
+ oqo_rfkill->state = RFKILL_STATE_SOFT_BLOCKED;
+ else
+ oqo_rfkill->state = RFKILL_STATE_UNBLOCKED;
+
+ oqo_rfkill->get_state = oqo_rfkill_get;
+ oqo_rfkill->toggle_radio = oqo_rfkill_toggle;
+ oqo_rfkill->user_claim_unsupported = 1;
+
+ res = rfkill_register(oqo_rfkill);
+
+ if (res)
+ rfkill_free(oqo_rfkill);
+
+ return res;
+}
+
+static void __devexit oqo_rfkill_fini(void)
+{
+ if (!oqo_rfkill)
+ return;
+ rfkill_unregister(oqo_rfkill);
+}
+
+/*
+ * Platform device
+ */
+
+static int __devinit oqo_platform_probe(struct platform_device *device)
+{
+ int err;
+ int i;
+ char *troubleok = "trouble, but continuing.\n";
+
+ memset(oqo_sn, 0, OQO_O2_SMB0_SERIAL_LEN + 1);
+ for (i = 0; i < OQO_O2_SMB0_SERIAL_LEN; i++) {
+ err = oqo_smbus_getb(OQO_O2_SMB0_SERIAL_START + i, oqo_sn + i);
+ if (err) {
+ printk(OQO_ERR "Serial number check failed.\n");
+ return err;
+ }
+ }
+ printk(OQO_INFO "Found OQO with serial number %s.\n", oqo_sn);
+
+ err = oqo_backlight_init(&device->dev);
+ if (err)
+ printk(OQO_ERR "Backlight init %s", troubleok);
+
+ err = oqo_rfkill_init(&device->dev);
+ if (err)
+ printk(OQO_ERR "RFKill init %s", troubleok);
+
+ /* LID does not work at all yet, and this may be taken
+ care of by ACPI.
+ */
+ orig.lid_wakes = smread_u8(OQO_O2_SMB0_LID_WAKES_ADDR);
+ orig.lid_wakes &= OQO_O2_SMB0_LID_WAKES_MASK;
+ orig.lid_wakes = curr.lid_wakes = !!orig.lid_wakes;
+ if (orig.lid_wakes < 0) {
+ printk(OQO_ERR "Wake on LID event %s", troubleok);
+ } else {
+ printk(OQO_INFO "Wake on LID is %s.\n",
+ (orig.lid_wakes ? "on" : "off"));
+ }
+
+ err = oqo_kine_init();
+ return err;
+}
+
+static int oqo_platform_remove(struct platform_device *device)
+{
+ oqo_backlight_fini();
+ oqo_rfkill_fini();
+ oqo_kine_fini();
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int oqo_platform_suspend(struct platform_device *dev, pm_message_t state)
+{
+ if (!interface)
+ return -ENOMEM;
+
+ /* This sticks during boot so do not turn it entirely off */
+ if (oqo_backlight_device) {
+ curr.bl_bright = read_brightness(oqo_backlight_device);
+ smwrite_s16(OQO_O2_SMB0_BL_HI, OQO_O2_SMB0_BL_LO, 256);
+ }
+ return 0;
+}
+
+static int oqo_platform_resume(struct platform_device *device)
+{
+ if (!interface)
+ return -ENOMEM;
+
+ if (oqo_backlight_device) {
+ smwrite_s16(OQO_O2_SMB0_BL_HI,
+ OQO_O2_SMB0_BL_LO, curr.bl_bright);
+ }
+
+ return 0;
+}
+
+#else
+#define oqo_platform_suspend NULL
+#define oqo_platform_resume NULL
+#endif
+
+static struct platform_driver oqo_platform_driver = {
+ .driver = {
+ .name = "oqo-wmi",
+ .owner = THIS_MODULE,
+ },
+ .probe = oqo_platform_probe,
+ .remove = oqo_platform_remove,
+ .suspend = oqo_platform_suspend,
+ .resume = oqo_platform_resume,
+};
+
+static int __init oqo_wmi_init(void)
+{
+ int err;
+
+ dmi_check_system(oqo_dmis);
+
+ if (!interface && force) {
+ model = oqo_models;
+ if (wmi_has_guid(OQO_O2_AMW0_GUID))
+ interface = &AMW0_interface;
+ }
+
+ if (!interface) {
+ printk(OQO_ERR "No or unsupported WMI interface. Aborting.\n");
+ printk(OQO_ERR "Hint: Get dmidecode working and try again.\n");
+ printk(OQO_ERR "(Check \"System Management BIOS\" in BIOS)\n");
+ if (!force)
+ printk(OQO_ERR "Use the force option to skip DMI"
+ " checking\n");
+ return -ENODEV;
+ }
+
+ err = platform_driver_register(&oqo_platform_driver);
+ if (err) {
+ printk(OQO_ERR "platform_driver_register gave %d.\n", err);
+ goto bail0;
+ }
+
+ oqo_platform_device = platform_device_alloc("oqo-wmi", -1);
+ if (!oqo_platform_device) {
+ printk(OQO_ERR "Could not allocate platform device.\n");
+ err = -ENOMEM;
+ goto bail1;
+ }
+
+ err = platform_device_add(oqo_platform_device);
+ if (err) {
+ printk(OQO_ERR "platform_device_add gave %d.\n", err);
+ platform_device_put(oqo_platform_device);
+ goto bail1;
+ }
+
+ return 0;
+
+bail1:
+ platform_driver_unregister(&oqo_platform_driver);
+bail0:
+ return err;
+}
+
+static void __exit oqo_wmi_fini(void)
+{
+ platform_device_del(oqo_platform_device);
+ platform_driver_unregister(&oqo_platform_driver);
+
+ return;
+}
+
+module_init(oqo_wmi_init);
+module_exit(oqo_wmi_fini);
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index 184e99e72684..552958545f94 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -317,7 +317,8 @@ static void sony_laptop_report_input_event(u8 event)
struct input_dev *key_dev = sony_laptop_input.key_dev;
struct sony_laptop_keypress kp = { NULL };
- if (event == SONYPI_EVENT_FNKEY_RELEASED) {
+ if (event == SONYPI_EVENT_FNKEY_RELEASED ||
+ event == SONYPI_EVENT_ANYBUTTON_RELEASED) {
/* Nothing, not all VAIOs generate this event */
return;
}
@@ -905,7 +906,6 @@ static struct sony_nc_event sony_127_events[] = {
{ 0x05, SONYPI_EVENT_ANYBUTTON_RELEASED },
{ 0x86, SONYPI_EVENT_PKEY_P5 },
{ 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED },
- { 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED },
{ 0x87, SONYPI_EVENT_SETTINGKEY_PRESSED },
{ 0x07, SONYPI_EVENT_ANYBUTTON_RELEASED },
{ 0, 0 },
@@ -1004,6 +1004,7 @@ static int sony_nc_function_setup(struct acpi_device *device)
sony_call_snc_handle(0x0100, 0, &result);
sony_call_snc_handle(0x0101, 0, &result);
sony_call_snc_handle(0x0102, 0x100, &result);
+ sony_call_snc_handle(0x0127, 0, &result);
return 0;
}
@@ -1040,7 +1041,7 @@ static int sony_nc_resume(struct acpi_device *device)
/* set the last requested brightness level */
if (sony_backlight_device &&
- !sony_backlight_update_status(sony_backlight_device))
+ sony_backlight_update_status(sony_backlight_device) < 0)
printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n");
return 0;
@@ -1097,12 +1098,16 @@ static int sony_nc_setup_wifi_rfkill(struct acpi_device *device)
sony_wifi_rfkill->name = "sony-wifi";
sony_wifi_rfkill->toggle_radio = sony_nc_rfkill_set;
sony_wifi_rfkill->get_state = sony_nc_rfkill_get;
+ sony_wifi_rfkill->user_claim_unsupported = 1;
sony_wifi_rfkill->data = (void *)SONY_WIFI;
err = rfkill_register(sony_wifi_rfkill);
if (err)
rfkill_free(sony_wifi_rfkill);
- else
+ else {
sony_rfkill_devices[SONY_WIFI] = sony_wifi_rfkill;
+ sony_nc_rfkill_set(sony_wifi_rfkill->data,
+ RFKILL_STATE_UNBLOCKED);
+ }
return err;
}
@@ -1118,12 +1123,16 @@ static int sony_nc_setup_bluetooth_rfkill(struct acpi_device *device)
sony_bluetooth_rfkill->name = "sony-bluetooth";
sony_bluetooth_rfkill->toggle_radio = sony_nc_rfkill_set;
sony_bluetooth_rfkill->get_state = sony_nc_rfkill_get;
+ sony_bluetooth_rfkill->user_claim_unsupported = 1;
sony_bluetooth_rfkill->data = (void *)SONY_BLUETOOTH;
err = rfkill_register(sony_bluetooth_rfkill);
if (err)
rfkill_free(sony_bluetooth_rfkill);
- else
+ else {
sony_rfkill_devices[SONY_BLUETOOTH] = sony_bluetooth_rfkill;
+ sony_nc_rfkill_set(sony_bluetooth_rfkill->data,
+ RFKILL_STATE_UNBLOCKED);
+ }
return err;
}
@@ -1138,12 +1147,16 @@ static int sony_nc_setup_wwan_rfkill(struct acpi_device *device)
sony_wwan_rfkill->name = "sony-wwan";
sony_wwan_rfkill->toggle_radio = sony_nc_rfkill_set;
sony_wwan_rfkill->get_state = sony_nc_rfkill_get;
+ sony_wwan_rfkill->user_claim_unsupported = 1;
sony_wwan_rfkill->data = (void *)SONY_WWAN;
err = rfkill_register(sony_wwan_rfkill);
if (err)
rfkill_free(sony_wwan_rfkill);
- else
+ else {
sony_rfkill_devices[SONY_WWAN] = sony_wwan_rfkill;
+ sony_nc_rfkill_set(sony_wwan_rfkill->data,
+ RFKILL_STATE_UNBLOCKED);
+ }
return err;
}
@@ -1158,12 +1171,16 @@ static int sony_nc_setup_wimax_rfkill(struct acpi_device *device)
sony_wimax_rfkill->name = "sony-wimax";
sony_wimax_rfkill->toggle_radio = sony_nc_rfkill_set;
sony_wimax_rfkill->get_state = sony_nc_rfkill_get;
+ sony_wimax_rfkill->user_claim_unsupported = 1;
sony_wimax_rfkill->data = (void *)SONY_WIMAX;
err = rfkill_register(sony_wimax_rfkill);
if (err)
rfkill_free(sony_wimax_rfkill);
- else
+ else {
sony_rfkill_devices[SONY_WIMAX] = sony_wimax_rfkill;
+ sony_nc_rfkill_set(sony_wimax_rfkill->data,
+ RFKILL_STATE_UNBLOCKED);
+ }
return err;
}
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index a40b075743d9..912be65b6261 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -21,7 +21,7 @@
* 02110-1301, USA.
*/
-#define TPACPI_VERSION "0.22"
+#define TPACPI_VERSION "0.23"
#define TPACPI_SYSFS_VERSION 0x020300
/*
@@ -303,11 +303,17 @@ static u32 dbg_level;
static struct workqueue_struct *tpacpi_wq;
+enum led_status_t {
+ TPACPI_LED_OFF = 0,
+ TPACPI_LED_ON,
+ TPACPI_LED_BLINK,
+};
+
/* Special LED class that can defer work */
struct tpacpi_led_classdev {
struct led_classdev led_classdev;
struct work_struct work;
- enum led_brightness new_brightness;
+ enum led_status_t new_state;
unsigned int led;
};
@@ -2946,12 +2952,18 @@ static int hotkey_read(char *p)
return len;
}
-static void hotkey_enabledisable_warn(void)
+static void hotkey_enabledisable_warn(bool enable)
{
tpacpi_log_usertask("procfs hotkey enable/disable");
- WARN(1, TPACPI_WARN
- "hotkey enable/disable functionality has been "
- "removed from the driver. Hotkeys are always enabled.\n");
+ if (!WARN((tpacpi_lifecycle == TPACPI_LIFE_RUNNING || !enable),
+ TPACPI_WARN
+ "hotkey enable/disable functionality has been "
+ "removed from the driver. Hotkeys are always "
+ "enabled\n"))
+ printk(TPACPI_ERR
+ "Please remove the hotkey=enable module "
+ "parameter, it is deprecated. Hotkeys are always "
+ "enabled\n");
}
static int hotkey_write(char *buf)
@@ -2971,9 +2983,9 @@ static int hotkey_write(char *buf)
res = 0;
while ((cmd = next_cmd(&buf))) {
if (strlencmp(cmd, "enable") == 0) {
- hotkey_enabledisable_warn();
+ hotkey_enabledisable_warn(1);
} else if (strlencmp(cmd, "disable") == 0) {
- hotkey_enabledisable_warn();
+ hotkey_enabledisable_warn(0);
res = -EPERM;
} else if (strlencmp(cmd, "reset") == 0) {
mask = hotkey_orig_mask;
@@ -4207,7 +4219,7 @@ static void light_set_status_worker(struct work_struct *work)
container_of(work, struct tpacpi_led_classdev, work);
if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING))
- light_set_status((data->new_brightness != LED_OFF));
+ light_set_status((data->new_state != TPACPI_LED_OFF));
}
static void light_sysfs_set(struct led_classdev *led_cdev,
@@ -4217,7 +4229,8 @@ static void light_sysfs_set(struct led_classdev *led_cdev,
container_of(led_cdev,
struct tpacpi_led_classdev,
led_classdev);
- data->new_brightness = brightness;
+ data->new_state = (brightness != LED_OFF) ?
+ TPACPI_LED_ON : TPACPI_LED_OFF;
queue_work(tpacpi_wq, &data->work);
}
@@ -4724,12 +4737,6 @@ enum { /* For TPACPI_LED_OLD */
TPACPI_LED_EC_HLMS = 0x0e, /* EC reg to select led to command */
};
-enum led_status_t {
- TPACPI_LED_OFF = 0,
- TPACPI_LED_ON,
- TPACPI_LED_BLINK,
-};
-
static enum led_access_mode led_supported;
TPACPI_HANDLE(led, ec, "SLED", /* 570 */
@@ -4841,23 +4848,13 @@ static int led_set_status(const unsigned int led,
return rc;
}
-static void led_sysfs_set_status(unsigned int led,
- enum led_brightness brightness)
-{
- led_set_status(led,
- (brightness == LED_OFF) ?
- TPACPI_LED_OFF :
- (tpacpi_led_state_cache[led] == TPACPI_LED_BLINK) ?
- TPACPI_LED_BLINK : TPACPI_LED_ON);
-}
-
static void led_set_status_worker(struct work_struct *work)
{
struct tpacpi_led_classdev *data =
container_of(work, struct tpacpi_led_classdev, work);
if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING))
- led_sysfs_set_status(data->led, data->new_brightness);
+ led_set_status(data->led, data->new_state);
}
static void led_sysfs_set(struct led_classdev *led_cdev,
@@ -4866,7 +4863,13 @@ static void led_sysfs_set(struct led_classdev *led_cdev,
struct tpacpi_led_classdev *data = container_of(led_cdev,
struct tpacpi_led_classdev, led_classdev);
- data->new_brightness = brightness;
+ if (brightness == LED_OFF)
+ data->new_state = TPACPI_LED_OFF;
+ else if (tpacpi_led_state_cache[data->led] != TPACPI_LED_BLINK)
+ data->new_state = TPACPI_LED_ON;
+ else
+ data->new_state = TPACPI_LED_BLINK;
+
queue_work(tpacpi_wq, &data->work);
}
@@ -4884,7 +4887,7 @@ static int led_sysfs_blink_set(struct led_classdev *led_cdev,
} else if ((*delay_on != 500) || (*delay_off != 500))
return -EINVAL;
- data->new_brightness = TPACPI_LED_BLINK;
+ data->new_state = TPACPI_LED_BLINK;
queue_work(tpacpi_wq, &data->work);
return 0;
@@ -7858,6 +7861,15 @@ static int __init thinkpad_acpi_module_init(void)
MODULE_ALIAS(TPACPI_DRVR_SHORTNAME);
/*
+ * This will autoload the driver in almost every ThinkPad
+ * in widespread use.
+ *
+ * Only _VERY_ old models, like the 240, 240x and 570 lack
+ * the HKEY event interface.
+ */
+MODULE_DEVICE_TABLE(acpi, ibm_htk_device_ids);
+
+/*
* DMI matching for module autoloading
*
* See http://thinkwiki.org/wiki/List_of_DMI_IDs
@@ -7869,18 +7881,13 @@ MODULE_ALIAS(TPACPI_DRVR_SHORTNAME);
#define IBM_BIOS_MODULE_ALIAS(__type) \
MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW*")
-/* Non-ancient thinkpads */
-MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*");
-MODULE_ALIAS("dmi:bvnLENOVO:*:svnLENOVO:*:pvrThinkPad*:rvnLENOVO:*");
-
/* Ancient thinkpad BIOSes have to be identified by
* BIOS type or model number, and there are far less
* BIOS types than model numbers... */
-IBM_BIOS_MODULE_ALIAS("I[BDHIMNOTWVYZ]");
-IBM_BIOS_MODULE_ALIAS("1[0368A-GIKM-PST]");
-IBM_BIOS_MODULE_ALIAS("K[UX-Z]");
+IBM_BIOS_MODULE_ALIAS("I[MU]"); /* 570, 570e */
-MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh");
+MODULE_AUTHOR("Borislav Deianov <borislav@users.sf.net>");
+MODULE_AUTHOR("Henrique de Moraes Holschuh <hmh@hmh.eng.br>");
MODULE_DESCRIPTION(TPACPI_DESC);
MODULE_VERSION(TPACPI_VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 4345089f5171..0c6cd7c654da 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -46,6 +46,7 @@
#include <linux/platform_device.h>
#include <linux/rfkill.h>
#include <linux/input-polldev.h>
+#include <linux/input.h>
#include <asm/uaccess.h>
@@ -62,9 +63,10 @@ MODULE_LICENSE("GPL");
/* Toshiba ACPI method paths */
#define METHOD_LCD_BRIGHTNESS "\\_SB_.PCI0.VGA_.LCD_._BCM"
-#define METHOD_HCI_1 "\\_SB_.VALD.GHCI"
-#define METHOD_HCI_2 "\\_SB_.VALZ.GHCI"
+#define TOSH_INTERFACE_1 "\\_SB_.VALD"
+#define TOSH_INTERFACE_2 "\\_SB_.VALZ"
#define METHOD_VIDEO_OUT "\\_SB_.VALX.DSSX"
+#define GHCI_METHOD ".GHCI"
/* Toshiba HCI interface definitions
*
@@ -116,6 +118,36 @@ static const struct acpi_device_id toshiba_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, toshiba_device_ids);
+struct key_entry {
+ char type;
+ u16 code;
+ u16 keycode;
+};
+
+enum {KE_KEY, KE_END};
+
+static struct key_entry toshiba_acpi_keymap[] = {
+ {KE_KEY, 0x101, KEY_MUTE},
+ {KE_KEY, 0x13b, KEY_COFFEE},
+ {KE_KEY, 0x13c, KEY_BATTERY},
+ {KE_KEY, 0x13d, KEY_SLEEP},
+ {KE_KEY, 0x13e, KEY_SUSPEND},
+ {KE_KEY, 0x13f, KEY_SWITCHVIDEOMODE},
+ {KE_KEY, 0x140, KEY_BRIGHTNESSDOWN},
+ {KE_KEY, 0x141, KEY_BRIGHTNESSUP},
+ {KE_KEY, 0x142, KEY_WLAN},
+ {KE_KEY, 0x143, KEY_PROG1},
+ {KE_KEY, 0xb05, KEY_PROG2},
+ {KE_KEY, 0xb06, KEY_WWW},
+ {KE_KEY, 0xb07, KEY_MAIL},
+ {KE_KEY, 0xb30, KEY_STOP},
+ {KE_KEY, 0xb31, KEY_PREVIOUSSONG},
+ {KE_KEY, 0xb32, KEY_NEXTSONG},
+ {KE_KEY, 0xb33, KEY_PLAYPAUSE},
+ {KE_KEY, 0xb5a, KEY_MEDIA},
+ {KE_END, 0, 0},
+};
+
/* utility
*/
@@ -252,6 +284,8 @@ struct toshiba_acpi_dev {
struct platform_device *p_dev;
struct rfkill *rfk_dev;
struct input_polled_dev *poll_dev;
+ struct input_dev *hotkey_dev;
+ acpi_handle handle;
const char *bt_name;
const char *rfk_name;
@@ -700,6 +734,154 @@ static struct backlight_ops toshiba_backlight_data = {
.update_status = set_lcd_status,
};
+static struct key_entry *toshiba_acpi_get_entry_by_scancode(int code)
+{
+ struct key_entry *key;
+
+ for (key = toshiba_acpi_keymap; key->type != KE_END; key++)
+ if (code == key->code)
+ return key;
+
+ return NULL;
+}
+
+static struct key_entry *toshiba_acpi_get_entry_by_keycode(int code)
+{
+ struct key_entry *key;
+
+ for (key = toshiba_acpi_keymap; key->type != KE_END; key++)
+ if (code == key->keycode && key->type == KE_KEY)
+ return key;
+
+ return NULL;
+}
+
+static int toshiba_acpi_getkeycode(struct input_dev *dev, int scancode,
+ int *keycode)
+{
+ struct key_entry *key = toshiba_acpi_get_entry_by_scancode(scancode);
+
+ if (key && key->type == KE_KEY) {
+ *keycode = key->keycode;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int toshiba_acpi_setkeycode(struct input_dev *dev, int scancode,
+ int keycode)
+{
+ struct key_entry *key;
+ int old_keycode;
+
+ if (keycode < 0 || keycode > KEY_MAX)
+ return -EINVAL;
+
+ key = toshiba_acpi_get_entry_by_scancode(scancode);
+ if (key && key->type == KE_KEY) {
+ old_keycode = key->keycode;
+ key->keycode = keycode;
+ set_bit(keycode, dev->keybit);
+ if (!toshiba_acpi_get_entry_by_keycode(old_keycode))
+ clear_bit(old_keycode, dev->keybit);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
+{
+ u32 hci_result, value;
+ struct key_entry *key;
+
+ if (event != 0x80)
+ return;
+ do {
+ hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
+ if (hci_result == HCI_SUCCESS) {
+ if (value == 0x100)
+ continue;
+ else if (value & 0x80) {
+ key = toshiba_acpi_get_entry_by_scancode
+ (value & ~0x80);
+ if (!key) {
+ printk(MY_INFO "Unknown key %x\n",
+ value & ~0x80);
+ continue;
+ }
+ input_report_key(toshiba_acpi.hotkey_dev,
+ key->keycode, 1);
+ input_sync(toshiba_acpi.hotkey_dev);
+ input_report_key(toshiba_acpi.hotkey_dev,
+ key->keycode, 0);
+ input_sync(toshiba_acpi.hotkey_dev);
+ }
+ } else if (hci_result == HCI_NOT_SUPPORTED) {
+ /* This is a workaround for an unresolved issue on
+ * some machines where system events sporadically
+ * become disabled. */
+ hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
+ printk(MY_NOTICE "Re-enabled hotkeys\n");
+ }
+ } while (hci_result != HCI_EMPTY);
+}
+
+static int toshiba_acpi_setup_keyboard(char *device)
+{
+ acpi_status status;
+ acpi_handle handle;
+ int result;
+ const struct key_entry *key;
+
+ status = acpi_get_handle(NULL, device, &handle);
+ if (ACPI_FAILURE(status)) {
+ printk(MY_INFO "Unable to get notification device\n");
+ return -ENODEV;
+ }
+
+ toshiba_acpi.handle = handle;
+
+ status = acpi_evaluate_object(handle, "ENAB", NULL, NULL);
+ if (ACPI_FAILURE(status)) {
+ printk(MY_INFO "Unable to enable hotkeys\n");
+ return -ENODEV;
+ }
+
+ status = acpi_install_notify_handler(handle, ACPI_DEVICE_NOTIFY,
+ toshiba_acpi_notify, NULL);
+ if (ACPI_FAILURE(status)) {
+ printk(MY_INFO "Unable to install hotkey notification\n");
+ return -ENODEV;
+ }
+
+ toshiba_acpi.hotkey_dev = input_allocate_device();
+ if (!toshiba_acpi.hotkey_dev) {
+ printk(MY_INFO "Unable to register input device\n");
+ return -ENOMEM;
+ }
+
+ toshiba_acpi.hotkey_dev->name = "Toshiba input device";
+ toshiba_acpi.hotkey_dev->phys = device;
+ toshiba_acpi.hotkey_dev->id.bustype = BUS_HOST;
+ toshiba_acpi.hotkey_dev->getkeycode = toshiba_acpi_getkeycode;
+ toshiba_acpi.hotkey_dev->setkeycode = toshiba_acpi_setkeycode;
+
+ for (key = toshiba_acpi_keymap; key->type != KE_END; key++) {
+ set_bit(EV_KEY, toshiba_acpi.hotkey_dev->evbit);
+ set_bit(key->keycode, toshiba_acpi.hotkey_dev->keybit);
+ }
+
+ result = input_register_device(toshiba_acpi.hotkey_dev);
+ if (result) {
+ printk(MY_INFO "Unable to register input device\n");
+ return result;
+ }
+
+ return 0;
+}
+
static void toshiba_acpi_exit(void)
{
if (toshiba_acpi.poll_dev) {
@@ -707,12 +889,18 @@ static void toshiba_acpi_exit(void)
input_free_polled_device(toshiba_acpi.poll_dev);
}
+ if (toshiba_acpi.hotkey_dev)
+ input_unregister_device(toshiba_acpi.hotkey_dev);
+
if (toshiba_acpi.rfk_dev)
rfkill_unregister(toshiba_acpi.rfk_dev);
if (toshiba_backlight_device)
backlight_device_unregister(toshiba_backlight_device);
+ acpi_remove_notify_handler(toshiba_acpi.handle, ACPI_DEVICE_NOTIFY,
+ toshiba_acpi_notify);
+
remove_device();
if (toshiba_proc_dir)
@@ -736,11 +924,15 @@ static int __init toshiba_acpi_init(void)
return -ENODEV;
/* simple device detection: look for HCI method */
- if (is_valid_acpi_path(METHOD_HCI_1))
- method_hci = METHOD_HCI_1;
- else if (is_valid_acpi_path(METHOD_HCI_2))
- method_hci = METHOD_HCI_2;
- else
+ if (is_valid_acpi_path(TOSH_INTERFACE_1 GHCI_METHOD)) {
+ method_hci = TOSH_INTERFACE_1 GHCI_METHOD;
+ if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_1))
+ printk(MY_INFO "Unable to activate hotkeys\n");
+ } else if (is_valid_acpi_path(TOSH_INTERFACE_2 GHCI_METHOD)) {
+ method_hci = TOSH_INTERFACE_2 GHCI_METHOD;
+ if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_2))
+ printk(MY_INFO "Unable to activate hotkeys\n");
+ } else
return -ENODEV;
printk(MY_INFO "Toshiba Laptop ACPI Extras version %s\n",
@@ -803,6 +995,7 @@ static int __init toshiba_acpi_init(void)
toshiba_acpi.rfk_dev->name = toshiba_acpi.bt_name;
toshiba_acpi.rfk_dev->toggle_radio = bt_rfkill_toggle_radio;
+ toshiba_acpi.rfk_dev->user_claim_unsupported = 1;
toshiba_acpi.rfk_dev->data = &toshiba_acpi;
if (hci_get_bt_on(&bt_on) == HCI_SUCCESS && bt_on) {
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 9a3a682c6981..9496494f340e 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -110,11 +110,9 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev)
/* acpi_unregister_gsi(pnp_irq(dev, 0)); */
ret = 0;
- if (acpi_bus_power_manageable(handle)) {
- ret = acpi_bus_set_power(handle, ACPI_STATE_D3);
- if (ret)
- return ret;
- }
+ if (acpi_bus_power_manageable(handle))
+ acpi_bus_set_power(handle, ACPI_STATE_D3);
+ /* continue even if acpi_bus_set_power() fails */
if (ACPI_FAILURE(acpi_evaluate_object(handle, "_DIS", NULL, NULL)))
ret = -ENODEV;
return ret;
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index adf17856bacc..7f207f335bec 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -123,7 +123,7 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
}
flags = irq_flags(triggering, polarity, shareable);
- irq = acpi_register_gsi(gsi, triggering, polarity);
+ irq = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
if (irq >= 0)
pcibios_penalize_isa_irq(irq, 1);
else
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index e58c0ce65aa6..5bec17cf1d5c 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -47,6 +47,16 @@ config REGULATOR_VIRTUAL_CONSUMER
If unsure, say no.
+config REGULATOR_USERSPACE_CONSUMER
+ tristate "Userspace regulator consumer support"
+ default n
+ help
+ There are some classes of devices that are controlled entirely
+ from user space. Usersapce consumer driver provides ability to
+ control power supplies for such devices.
+
+ If unsure, say no.
+
config REGULATOR_BQ24022
tristate "TI bq24022 Dual Input 1-Cell Li-Ion Charger IC"
default n
@@ -56,6 +66,15 @@ config REGULATOR_BQ24022
charging select between 100 mA and 500 mA charging current
limit.
+config REGULATOR_MAX1586
+ tristate "Maxim 1586/1587 voltage regulator"
+ depends on I2C
+ default n
+ help
+ This driver controls a Maxim 1586 or 1587 voltage output
+ regulator via I2C bus. The provided regulator is suitable
+ for PXA27x chips to control VCC_CORE and VCC_USIM voltages.
+
config REGULATOR_TWL4030
bool "TI TWL4030/TWL5030/TPS695x0 PMIC"
depends on TWL4030_CORE
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index bac133afc061..faf7bcc1af98 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -6,8 +6,10 @@
obj-$(CONFIG_REGULATOR) += core.o
obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
+obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o
obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o
+obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
obj-$(CONFIG_REGULATOR_TWL4030) += twl4030-regulator.o
obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
diff --git a/drivers/regulator/bq24022.c b/drivers/regulator/bq24022.c
index 7ecb820ceebc..d08cd9b66c6d 100644
--- a/drivers/regulator/bq24022.c
+++ b/drivers/regulator/bq24022.c
@@ -61,8 +61,7 @@ static int bq24022_disable(struct regulator_dev *rdev)
static int bq24022_is_enabled(struct regulator_dev *rdev)
{
- struct platform_device *pdev = rdev_get_drvdata(rdev);
- struct bq24022_mach_info *pdata = pdev->dev.platform_data;
+ struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev);
return !gpio_get_value(pdata->gpio_nce);
}
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 01f7702a805d..98c3a74e9949 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -540,8 +540,8 @@ static void drms_uA_update(struct regulator_dev *rdev)
err = regulator_check_drms(rdev);
if (err < 0 || !rdev->desc->ops->get_optimum_mode ||
- !rdev->desc->ops->get_voltage || !rdev->desc->ops->set_mode);
- return;
+ !rdev->desc->ops->get_voltage || !rdev->desc->ops->set_mode)
+ return;
/* get output voltage */
output_uV = rdev->desc->ops->get_voltage(rdev);
@@ -703,10 +703,13 @@ static int set_machine_constraints(struct regulator_dev *rdev,
int cmin = constraints->min_uV;
int cmax = constraints->max_uV;
- /* it's safe to autoconfigure fixed-voltage supplies */
+ /* it's safe to autoconfigure fixed-voltage supplies
+ and the constraints are used by list_voltage. */
if (count == 1 && !cmin) {
- cmin = INT_MIN;
+ cmin = 1;
cmax = INT_MAX;
+ constraints->min_uV = cmin;
+ constraints->max_uV = cmax;
}
/* voltage constraints are optional */
@@ -2001,8 +2004,8 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
if (regulator_desc->name == NULL || regulator_desc->ops == NULL)
return ERR_PTR(-EINVAL);
- if (!regulator_desc->type == REGULATOR_VOLTAGE &&
- !regulator_desc->type == REGULATOR_CURRENT)
+ if (regulator_desc->type != REGULATOR_VOLTAGE &&
+ regulator_desc->type != REGULATOR_CURRENT)
return ERR_PTR(-EINVAL);
if (!init_data)
@@ -2080,6 +2083,10 @@ out:
scrub:
device_unregister(&rdev->dev);
+ /* device core frees rdev */
+ rdev = ERR_PTR(ret);
+ goto out;
+
clean:
kfree(rdev);
rdev = ERR_PTR(ret);
diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c
index 72b15495183c..2a491bf15865 100644
--- a/drivers/regulator/da903x.c
+++ b/drivers/regulator/da903x.c
@@ -504,7 +504,7 @@ static int __init da903x_regulator_init(void)
{
return platform_driver_register(&da903x_regulator_driver);
}
-module_init(da903x_regulator_init);
+subsys_initcall(da903x_regulator_init);
static void __exit da903x_regulator_exit(void)
{
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index 23d554628a76..cdc674fb46c3 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -44,10 +44,22 @@ static int fixed_voltage_get_voltage(struct regulator_dev *dev)
return data->microvolts;
}
+static int fixed_voltage_list_voltage(struct regulator_dev *dev,
+ unsigned selector)
+{
+ struct fixed_voltage_data *data = rdev_get_drvdata(dev);
+
+ if (selector != 0)
+ return -EINVAL;
+
+ return data->microvolts;
+}
+
static struct regulator_ops fixed_voltage_ops = {
.is_enabled = fixed_voltage_is_enabled,
.enable = fixed_voltage_enable,
.get_voltage = fixed_voltage_get_voltage,
+ .list_voltage = fixed_voltage_list_voltage,
};
static int regulator_fixed_voltage_probe(struct platform_device *pdev)
@@ -69,7 +81,8 @@ static int regulator_fixed_voltage_probe(struct platform_device *pdev)
}
drvdata->desc.type = REGULATOR_VOLTAGE;
drvdata->desc.owner = THIS_MODULE;
- drvdata->desc.ops = &fixed_voltage_ops,
+ drvdata->desc.ops = &fixed_voltage_ops;
+ drvdata->desc.n_voltages = 1;
drvdata->microvolts = config->microvolts;
@@ -117,7 +130,7 @@ static int __init regulator_fixed_voltage_init(void)
{
return platform_driver_register(&regulator_fixed_voltage_driver);
}
-module_init(regulator_fixed_voltage_init);
+subsys_initcall(regulator_fixed_voltage_init);
static void __exit regulator_fixed_voltage_exit(void)
{
@@ -128,3 +141,4 @@ module_exit(regulator_fixed_voltage_exit);
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_DESCRIPTION("Fixed voltage regulator");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:reg-fixed-voltage");
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c
new file mode 100644
index 000000000000..bbbb55fcfe8c
--- /dev/null
+++ b/drivers/regulator/max1586.c
@@ -0,0 +1,249 @@
+/*
+ * max1586.c -- Voltage and current regulation for the Maxim 1586
+ *
+ * Copyright (C) 2008 Robert Jarzmik
+ *
+ * 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/err.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/max1586.h>
+
+#define MAX1586_V3_MAX_VSEL 31
+#define MAX1586_V6_MAX_VSEL 3
+
+#define MAX1586_V3_MIN_UV 700000
+#define MAX1586_V3_MAX_UV 1475000
+#define MAX1586_V3_STEP_UV 25000
+
+#define MAX1586_V6_MIN_UV 0
+#define MAX1586_V6_MAX_UV 3000000
+
+#define I2C_V3_SELECT (0 << 5)
+#define I2C_V6_SELECT (1 << 5)
+
+/*
+ * V3 voltage
+ * On I2C bus, sending a "x" byte to the max1586 means :
+ * set V3 to 0.700V + (x & 0x1f) * 0.025V
+ */
+static int max1586_v3_calc_voltage(unsigned selector)
+{
+ return MAX1586_V3_MIN_UV + (MAX1586_V3_STEP_UV * selector);
+}
+
+static int max1586_v3_set(struct regulator_dev *rdev, int min_uV, int max_uV)
+{
+ struct i2c_client *client = rdev_get_drvdata(rdev);
+ unsigned selector;
+ u8 v3_prog;
+
+ if (min_uV < MAX1586_V3_MIN_UV || min_uV > MAX1586_V3_MAX_UV)
+ return -EINVAL;
+ if (max_uV < MAX1586_V3_MIN_UV || max_uV > MAX1586_V3_MAX_UV)
+ return -EINVAL;
+
+ selector = (min_uV - MAX1586_V3_MIN_UV) / MAX1586_V3_STEP_UV;
+ if (max1586_v3_calc_voltage(selector) > max_uV)
+ return -EINVAL;
+
+ dev_dbg(&client->dev, "changing voltage v3 to %dmv\n",
+ max1586_v3_calc_voltage(selector) / 1000);
+
+ v3_prog = I2C_V3_SELECT | (u8) selector;
+ return i2c_smbus_write_byte(client, v3_prog);
+}
+
+static int max1586_v3_list(struct regulator_dev *rdev, unsigned selector)
+{
+ if (selector > MAX1586_V3_MAX_VSEL)
+ return -EINVAL;
+ return max1586_v3_calc_voltage(selector);
+}
+
+/*
+ * V6 voltage
+ * On I2C bus, sending a "x" byte to the max1586 means :
+ * set V6 to either 0V, 1.8V, 2.5V, 3V depending on (x & 0x3)
+ * As regulator framework doesn't accept voltages to be 0V, we use 1uV.
+ */
+static int max1586_v6_calc_voltage(unsigned selector)
+{
+ static int voltages_uv[] = { 1, 1800000, 2500000, 3000000 };
+
+ return voltages_uv[selector];
+}
+
+static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV)
+{
+ struct i2c_client *client = rdev_get_drvdata(rdev);
+ unsigned selector;
+ u8 v6_prog;
+
+ if (min_uV < MAX1586_V6_MIN_UV || min_uV > MAX1586_V6_MAX_UV)
+ return -EINVAL;
+ if (max_uV < MAX1586_V6_MIN_UV || max_uV > MAX1586_V6_MAX_UV)
+ return -EINVAL;
+
+ if (min_uV >= 3000000)
+ selector = 3;
+ if (min_uV < 3000000)
+ selector = 2;
+ if (min_uV < 2500000)
+ selector = 1;
+ if (min_uV < 1800000)
+ selector = 0;
+
+ if (max1586_v6_calc_voltage(selector) > max_uV)
+ return -EINVAL;
+
+ dev_dbg(&client->dev, "changing voltage v6 to %dmv\n",
+ max1586_v6_calc_voltage(selector) / 1000);
+
+ v6_prog = I2C_V6_SELECT | (u8) selector;
+ return i2c_smbus_write_byte(client, v6_prog);
+}
+
+static int max1586_v6_list(struct regulator_dev *rdev, unsigned selector)
+{
+ if (selector > MAX1586_V6_MAX_VSEL)
+ return -EINVAL;
+ return max1586_v6_calc_voltage(selector);
+}
+
+/*
+ * The Maxim 1586 controls V3 and V6 voltages, but offers no way of reading back
+ * the set up value.
+ */
+static struct regulator_ops max1586_v3_ops = {
+ .set_voltage = max1586_v3_set,
+ .list_voltage = max1586_v3_list,
+};
+
+static struct regulator_ops max1586_v6_ops = {
+ .set_voltage = max1586_v6_set,
+ .list_voltage = max1586_v6_list,
+};
+
+static struct regulator_desc max1586_reg[] = {
+ {
+ .name = "Output_V3",
+ .id = MAX1586_V3,
+ .ops = &max1586_v3_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = MAX1586_V3_MAX_VSEL + 1,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "Output_V6",
+ .id = MAX1586_V6,
+ .ops = &max1586_v6_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = MAX1586_V6_MAX_VSEL + 1,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int max1586_pmic_probe(struct i2c_client *client,
+ const struct i2c_device_id *i2c_id)
+{
+ struct regulator_dev **rdev;
+ struct max1586_platform_data *pdata = client->dev.platform_data;
+ int i, id, ret = 0;
+
+ rdev = kzalloc(sizeof(struct regulator_dev *) * (MAX1586_V6 + 1),
+ GFP_KERNEL);
+ if (!rdev)
+ return -ENOMEM;
+
+ ret = -EINVAL;
+ for (i = 0; i < pdata->num_subdevs && i <= MAX1586_V6; i++) {
+ id = pdata->subdevs[i].id;
+ if (!pdata->subdevs[i].platform_data)
+ continue;
+ if (id < MAX1586_V3 || id > MAX1586_V6) {
+ dev_err(&client->dev, "invalid regulator id %d\n", id);
+ goto err;
+ }
+ rdev[i] = regulator_register(&max1586_reg[id], &client->dev,
+ pdata->subdevs[i].platform_data,
+ client);
+ if (IS_ERR(rdev[i])) {
+ ret = PTR_ERR(rdev[i]);
+ dev_err(&client->dev, "failed to register %s\n",
+ max1586_reg[id].name);
+ goto err;
+ }
+ }
+
+ i2c_set_clientdata(client, rdev);
+ dev_info(&client->dev, "Maxim 1586 regulator driver loaded\n");
+ return 0;
+
+err:
+ while (--i >= 0)
+ regulator_unregister(rdev[i]);
+ kfree(rdev);
+ return ret;
+}
+
+static int max1586_pmic_remove(struct i2c_client *client)
+{
+ struct regulator_dev **rdev = i2c_get_clientdata(client);
+ int i;
+
+ for (i = 0; i <= MAX1586_V6; i++)
+ if (rdev[i])
+ regulator_unregister(rdev[i]);
+ kfree(rdev);
+ i2c_set_clientdata(client, NULL);
+
+ return 0;
+}
+
+static const struct i2c_device_id max1586_id[] = {
+ { "max1586", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, max1586_id);
+
+static struct i2c_driver max1586_pmic_driver = {
+ .probe = max1586_pmic_probe,
+ .remove = max1586_pmic_remove,
+ .driver = {
+ .name = "max1586",
+ },
+ .id_table = max1586_id,
+};
+
+static int __init max1586_pmic_init(void)
+{
+ return i2c_add_driver(&max1586_pmic_driver);
+}
+subsys_initcall(max1586_pmic_init);
+
+static void __exit max1586_pmic_exit(void)
+{
+ i2c_del_driver(&max1586_pmic_driver);
+}
+module_exit(max1586_pmic_exit);
+
+/* Module information */
+MODULE_DESCRIPTION("MAXIM 1586 voltage regulator driver");
+MODULE_AUTHOR("Robert Jarzmik");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c
index cd761d85c8fd..8e14900eb686 100644
--- a/drivers/regulator/pcf50633-regulator.c
+++ b/drivers/regulator/pcf50633-regulator.c
@@ -316,7 +316,7 @@ static int __init pcf50633_regulator_init(void)
{
return platform_driver_register(&pcf50633_regulator_driver);
}
-module_init(pcf50633_regulator_init);
+subsys_initcall(pcf50633_regulator_init);
static void __exit pcf50633_regulator_exit(void)
{
diff --git a/drivers/regulator/userspace-consumer.c b/drivers/regulator/userspace-consumer.c
new file mode 100644
index 000000000000..06d2fa96a8b4
--- /dev/null
+++ b/drivers/regulator/userspace-consumer.c
@@ -0,0 +1,200 @@
+/*
+ * userspace-consumer.c
+ *
+ * Copyright 2009 CompuLab, Ltd.
+ *
+ * Author: Mike Rapoport <mike@compulab.co.il>
+ *
+ * Based of virtual consumer driver:
+ * Copyright 2008 Wolfson Microelectronics PLC.
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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/err.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/userspace-consumer.h>
+
+struct userspace_consumer_data {
+ const char *name;
+
+ struct mutex lock;
+ bool enabled;
+
+ int num_supplies;
+ struct regulator_bulk_data *supplies;
+};
+
+static ssize_t reg_show_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct userspace_consumer_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s\n", data->name);
+}
+
+static ssize_t reg_show_state(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct userspace_consumer_data *data = dev_get_drvdata(dev);
+
+ if (data->enabled)
+ return sprintf(buf, "enabled\n");
+
+ return sprintf(buf, "disabled\n");
+}
+
+static ssize_t reg_set_state(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct userspace_consumer_data *data = dev_get_drvdata(dev);
+ bool enabled;
+ int ret;
+
+ /*
+ * sysfs_streq() doesn't need the \n's, but we add them so the strings
+ * will be shared with show_state(), above.
+ */
+ if (sysfs_streq(buf, "enabled\n") || sysfs_streq(buf, "1"))
+ enabled = true;
+ else if (sysfs_streq(buf, "disabled\n") || sysfs_streq(buf, "0"))
+ enabled = false;
+ else {
+ dev_err(dev, "Configuring invalid mode\n");
+ return count;
+ }
+
+ mutex_lock(&data->lock);
+ if (enabled != data->enabled) {
+ if (enabled)
+ ret = regulator_bulk_enable(data->num_supplies,
+ data->supplies);
+ else
+ ret = regulator_bulk_disable(data->num_supplies,
+ data->supplies);
+
+ if (ret == 0)
+ data->enabled = enabled;
+ else
+ dev_err(dev, "Failed to configure state: %d\n", ret);
+ }
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static DEVICE_ATTR(name, 0444, reg_show_name, NULL);
+static DEVICE_ATTR(state, 0644, reg_show_state, reg_set_state);
+
+static struct device_attribute *attributes[] = {
+ &dev_attr_name,
+ &dev_attr_state,
+};
+
+static int regulator_userspace_consumer_probe(struct platform_device *pdev)
+{
+ struct regulator_userspace_consumer_data *pdata;
+ struct userspace_consumer_data *drvdata;
+ int ret, i;
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata)
+ return -EINVAL;
+
+ drvdata = kzalloc(sizeof(struct userspace_consumer_data), GFP_KERNEL);
+ if (drvdata == NULL)
+ return -ENOMEM;
+
+ drvdata->name = pdata->name;
+ drvdata->num_supplies = pdata->num_supplies;
+ drvdata->supplies = pdata->supplies;
+
+ mutex_init(&drvdata->lock);
+
+ ret = regulator_bulk_get(&pdev->dev, drvdata->num_supplies,
+ drvdata->supplies);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to get supplies: %d\n", ret);
+ goto err_alloc_supplies;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(attributes); i++) {
+ ret = device_create_file(&pdev->dev, attributes[i]);
+ if (ret != 0)
+ goto err_create_attrs;
+ }
+
+ if (pdata->init_on)
+ ret = regulator_bulk_enable(drvdata->num_supplies,
+ drvdata->supplies);
+
+ drvdata->enabled = pdata->init_on;
+
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to set initial state: %d\n", ret);
+ goto err_create_attrs;
+ }
+
+ platform_set_drvdata(pdev, drvdata);
+
+ return 0;
+
+err_create_attrs:
+ for (i = 0; i < ARRAY_SIZE(attributes); i++)
+ device_remove_file(&pdev->dev, attributes[i]);
+
+ regulator_bulk_free(drvdata->num_supplies, drvdata->supplies);
+
+err_alloc_supplies:
+ kfree(drvdata);
+ return ret;
+}
+
+static int regulator_userspace_consumer_remove(struct platform_device *pdev)
+{
+ struct userspace_consumer_data *data = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(attributes); i++)
+ device_remove_file(&pdev->dev, attributes[i]);
+
+ if (data->enabled)
+ regulator_bulk_disable(data->num_supplies, data->supplies);
+
+ regulator_bulk_free(data->num_supplies, data->supplies);
+ kfree(data);
+
+ return 0;
+}
+
+static struct platform_driver regulator_userspace_consumer_driver = {
+ .probe = regulator_userspace_consumer_probe,
+ .remove = regulator_userspace_consumer_remove,
+ .driver = {
+ .name = "reg-userspace-consumer",
+ },
+};
+
+
+static int __init regulator_userspace_consumer_init(void)
+{
+ return platform_driver_register(&regulator_userspace_consumer_driver);
+}
+module_init(regulator_userspace_consumer_init);
+
+static void __exit regulator_userspace_consumer_exit(void)
+{
+ platform_driver_unregister(&regulator_userspace_consumer_driver);
+}
+module_exit(regulator_userspace_consumer_exit);
+
+MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
+MODULE_DESCRIPTION("Userspace consumer for voltage and current regulators");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/virtual.c b/drivers/regulator/virtual.c
index 3d08348584e1..e7db5664722e 100644
--- a/drivers/regulator/virtual.c
+++ b/drivers/regulator/virtual.c
@@ -230,13 +230,13 @@ static ssize_t set_mode(struct device *dev, struct device_attribute *attr,
* sysfs_streq() doesn't need the \n's, but we add them so the strings
* will be shared with show_mode(), above.
*/
- if (sysfs_streq(buf, "fast\n") == 0)
+ if (sysfs_streq(buf, "fast\n"))
mode = REGULATOR_MODE_FAST;
- else if (sysfs_streq(buf, "normal\n") == 0)
+ else if (sysfs_streq(buf, "normal\n"))
mode = REGULATOR_MODE_NORMAL;
- else if (sysfs_streq(buf, "idle\n") == 0)
+ else if (sysfs_streq(buf, "idle\n"))
mode = REGULATOR_MODE_IDLE;
- else if (sysfs_streq(buf, "standby\n") == 0)
+ else if (sysfs_streq(buf, "standby\n"))
mode = REGULATOR_MODE_STANDBY;
else {
dev_err(dev, "Configuring invalid mode\n");
@@ -347,3 +347,4 @@ module_exit(regulator_virtual_consumer_exit);
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_DESCRIPTION("Virtual regulator consumer");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:reg-virt-consumer");
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c
index 771eca1066b5..17a00b0fafd1 100644
--- a/drivers/regulator/wm8350-regulator.c
+++ b/drivers/regulator/wm8350-regulator.c
@@ -1570,3 +1570,4 @@ module_exit(wm8350_regulator_exit);
MODULE_AUTHOR("Liam Girdwood");
MODULE_DESCRIPTION("WM8350 voltage and current regulator driver");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm8350-regulator");
diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c
index 157426029071..d9a2c988c6e7 100644
--- a/drivers/regulator/wm8400-regulator.c
+++ b/drivers/regulator/wm8400-regulator.c
@@ -320,7 +320,7 @@ static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
struct regulator_dev *rdev;
rdev = regulator_register(&regulators[pdev->id], &pdev->dev,
- pdev->dev.platform_data, pdev->dev.driver_data);
+ pdev->dev.platform_data, dev_get_drvdata(&pdev->dev));
if (IS_ERR(rdev))
return PTR_ERR(rdev);
@@ -359,7 +359,7 @@ static struct platform_driver wm8400_regulator_driver = {
int wm8400_register_regulator(struct device *dev, int reg,
struct regulator_init_data *initdata)
{
- struct wm8400 *wm8400 = dev->driver_data;
+ struct wm8400 *wm8400 = dev_get_drvdata(dev);
if (wm8400->regulators[reg].name)
return -EBUSY;
@@ -369,8 +369,8 @@ int wm8400_register_regulator(struct device *dev, int reg,
wm8400->regulators[reg].name = "wm8400-regulator";
wm8400->regulators[reg].id = reg;
wm8400->regulators[reg].dev.parent = dev;
- wm8400->regulators[reg].dev.driver_data = wm8400;
wm8400->regulators[reg].dev.platform_data = initdata;
+ dev_set_drvdata(&wm8400->regulators[reg].dev, wm8400);
return platform_device_register(&wm8400->regulators[reg]);
}
@@ -380,7 +380,7 @@ static int __init wm8400_regulator_init(void)
{
return platform_driver_register(&wm8400_regulator_driver);
}
-module_init(wm8400_regulator_init);
+subsys_initcall(wm8400_regulator_init);
static void __exit wm8400_regulator_exit(void)
{
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index ffe34a12f446..1f27cedc452c 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -491,6 +491,15 @@ config RTC_DRV_M48T59
This driver can also be built as a module, if so, the module
will be called "rtc-m48t59".
+config RTC_DRV_MSM6242
+ tristate "Oki MSM6242"
+ help
+ If you say yes here you get support for the Oki MSM6242
+ timekeeping chip. It is used in some Amiga models (e.g. A2000).
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-msm6242.
+
config RTC_DRV_BQ4802
tristate "TI BQ4802"
help
@@ -500,6 +509,16 @@ config RTC_DRV_BQ4802
This driver can also be built as a module. If so, the module
will be called rtc-bq4802.
+config RTC_DRV_RP5C01
+ tristate "Ricoh RP5C01"
+ help
+ If you say yes here you get support for the Ricoh RP5C01
+ timekeeping chip. It is used in some Amiga models (e.g. A3000
+ and A4000).
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-rp5c01.
+
config RTC_DRV_V3020
tristate "EM Microelectronic V3020"
help
@@ -573,7 +592,7 @@ config RTC_DRV_SA1100
config RTC_DRV_SH
tristate "SuperH On-Chip RTC"
- depends on RTC_CLASS && SUPERH
+ depends on RTC_CLASS && SUPERH && HAVE_CLK
help
Say Y here to enable support for the on-chip RTC found in
most SuperH processors.
@@ -692,7 +711,7 @@ config RTC_DRV_GENERIC
tristate "Generic RTC support"
# Please consider writing a new RTC driver instead of using the generic
# RTC abstraction
- depends on PARISC || M68K || PPC
+ depends on PARISC || M68K || PPC || SUPERH32
help
Say Y or M here to enable RTC support on systems using the generic
RTC abstraction. If you do not know what you are doing, you should
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 6c0639a14f09..ab0275cae87f 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o
obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o
obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
+obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o
obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o
obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o
obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o
@@ -59,6 +60,7 @@ obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o
obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o
obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o
obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o
+obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o
obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o
obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o
obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index b6d35f50e404..23e10b6263d6 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -797,17 +797,15 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
goto cleanup2;
}
- pr_info("%s: alarms up to one %s%s, %zd bytes nvram%s\n",
- dev_name(&cmos_rtc.rtc->dev),
- is_valid_irq(rtc_irq)
- ? (cmos_rtc.mon_alrm
- ? "year"
- : (cmos_rtc.day_alrm
- ? "month" : "day"))
- : "no",
- cmos_rtc.century ? ", y3k" : "",
- nvram.size,
- is_hpet_enabled() ? ", hpet irqs" : "");
+ pr_info("%s: %s%s, %zd bytes nvram%s\n",
+ dev_name(&cmos_rtc.rtc->dev),
+ !is_valid_irq(rtc_irq) ? "no alarms" :
+ cmos_rtc.mon_alrm ? "alarms up to one year" :
+ cmos_rtc.day_alrm ? "alarms up to one month" :
+ "alarms up to one day",
+ cmos_rtc.century ? ", y3k" : "",
+ nvram.size,
+ is_hpet_enabled() ? ", hpet irqs" : "");
return 0;
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c
index f7a3283dd029..551332e4ed02 100644
--- a/drivers/rtc/rtc-ep93xx.c
+++ b/drivers/rtc/rtc-ep93xx.c
@@ -12,32 +12,56 @@
#include <linux/module.h>
#include <linux/rtc.h>
#include <linux/platform_device.h>
-#include <mach/hardware.h>
+#include <linux/io.h>
+
+#define EP93XX_RTC_DATA 0x000
+#define EP93XX_RTC_MATCH 0x004
+#define EP93XX_RTC_STATUS 0x008
+#define EP93XX_RTC_STATUS_INTR (1<<0)
+#define EP93XX_RTC_LOAD 0x00C
+#define EP93XX_RTC_CONTROL 0x010
+#define EP93XX_RTC_CONTROL_MIE (1<<0)
+#define EP93XX_RTC_SWCOMP 0x108
+#define EP93XX_RTC_SWCOMP_DEL_MASK 0x001f0000
+#define EP93XX_RTC_SWCOMP_DEL_SHIFT 16
+#define EP93XX_RTC_SWCOMP_INT_MASK 0x0000ffff
+#define EP93XX_RTC_SWCOMP_INT_SHIFT 0
+
+#define DRV_VERSION "0.3"
-#define EP93XX_RTC_REG(x) (EP93XX_RTC_BASE + (x))
-#define EP93XX_RTC_DATA EP93XX_RTC_REG(0x0000)
-#define EP93XX_RTC_LOAD EP93XX_RTC_REG(0x000C)
-#define EP93XX_RTC_SWCOMP EP93XX_RTC_REG(0x0108)
-
-#define DRV_VERSION "0.2"
+/*
+ * struct device dev.platform_data is used to store our private data
+ * because struct rtc_device does not have a variable to hold it.
+ */
+struct ep93xx_rtc {
+ void __iomem *mmio_base;
+};
-static int ep93xx_get_swcomp(struct device *dev, unsigned short *preload,
+static int ep93xx_rtc_get_swcomp(struct device *dev, unsigned short *preload,
unsigned short *delete)
{
- unsigned short comp = __raw_readl(EP93XX_RTC_SWCOMP);
+ struct ep93xx_rtc *ep93xx_rtc = dev->platform_data;
+ unsigned long comp;
+
+ comp = __raw_readl(ep93xx_rtc->mmio_base + EP93XX_RTC_SWCOMP);
if (preload)
- *preload = comp & 0xffff;
+ *preload = (comp & EP93XX_RTC_SWCOMP_INT_MASK)
+ >> EP93XX_RTC_SWCOMP_INT_SHIFT;
if (delete)
- *delete = (comp >> 16) & 0x1f;
+ *delete = (comp & EP93XX_RTC_SWCOMP_DEL_MASK)
+ >> EP93XX_RTC_SWCOMP_DEL_SHIFT;
return 0;
}
static int ep93xx_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- unsigned long time = __raw_readl(EP93XX_RTC_DATA);
+ struct ep93xx_rtc *ep93xx_rtc = dev->platform_data;
+ unsigned long time;
+
+ time = __raw_readl(ep93xx_rtc->mmio_base + EP93XX_RTC_DATA);
rtc_time_to_tm(time, tm);
return 0;
@@ -45,7 +69,9 @@ static int ep93xx_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int ep93xx_rtc_set_mmss(struct device *dev, unsigned long secs)
{
- __raw_writel(secs + 1, EP93XX_RTC_LOAD);
+ struct ep93xx_rtc *ep93xx_rtc = dev->platform_data;
+
+ __raw_writel(secs + 1, ep93xx_rtc->mmio_base + EP93XX_RTC_LOAD);
return 0;
}
@@ -53,7 +79,7 @@ static int ep93xx_rtc_proc(struct device *dev, struct seq_file *seq)
{
unsigned short preload, delete;
- ep93xx_get_swcomp(dev, &preload, &delete);
+ ep93xx_rtc_get_swcomp(dev, &preload, &delete);
seq_printf(seq, "preload\t\t: %d\n", preload);
seq_printf(seq, "delete\t\t: %d\n", delete);
@@ -67,54 +93,104 @@ static const struct rtc_class_ops ep93xx_rtc_ops = {
.proc = ep93xx_rtc_proc,
};
-static ssize_t ep93xx_sysfs_show_comp_preload(struct device *dev,
+static ssize_t ep93xx_rtc_show_comp_preload(struct device *dev,
struct device_attribute *attr, char *buf)
{
unsigned short preload;
- ep93xx_get_swcomp(dev, &preload, NULL);
+ ep93xx_rtc_get_swcomp(dev, &preload, NULL);
return sprintf(buf, "%d\n", preload);
}
-static DEVICE_ATTR(comp_preload, S_IRUGO, ep93xx_sysfs_show_comp_preload, NULL);
+static DEVICE_ATTR(comp_preload, S_IRUGO, ep93xx_rtc_show_comp_preload, NULL);
-static ssize_t ep93xx_sysfs_show_comp_delete(struct device *dev,
+static ssize_t ep93xx_rtc_show_comp_delete(struct device *dev,
struct device_attribute *attr, char *buf)
{
unsigned short delete;
- ep93xx_get_swcomp(dev, NULL, &delete);
+ ep93xx_rtc_get_swcomp(dev, NULL, &delete);
return sprintf(buf, "%d\n", delete);
}
-static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_sysfs_show_comp_delete, NULL);
+static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_rtc_show_comp_delete, NULL);
-static int __devinit ep93xx_rtc_probe(struct platform_device *dev)
+static int __init ep93xx_rtc_probe(struct platform_device *pdev)
{
- struct rtc_device *rtc = rtc_device_register("ep93xx",
- &dev->dev, &ep93xx_rtc_ops, THIS_MODULE);
+ struct ep93xx_rtc *ep93xx_rtc;
+ struct resource *res;
+ struct rtc_device *rtc;
+ int err;
+
+ ep93xx_rtc = kzalloc(sizeof(struct ep93xx_rtc), GFP_KERNEL);
+ if (ep93xx_rtc == NULL)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL)
+ return -ENXIO;
+
+ res = request_mem_region(res->start, resource_size(res), pdev->name);
+ if (res == NULL)
+ return -EBUSY;
+
+ ep93xx_rtc->mmio_base = ioremap(res->start, resource_size(res));
+ if (ep93xx_rtc->mmio_base == NULL) {
+ err = -ENXIO;
+ goto fail;
+ }
+ pdev->dev.platform_data = ep93xx_rtc;
+
+ rtc = rtc_device_register(pdev->name,
+ &pdev->dev, &ep93xx_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc)) {
- return PTR_ERR(rtc);
+ err = PTR_ERR(rtc);
+ goto fail;
}
- platform_set_drvdata(dev, rtc);
+ platform_set_drvdata(pdev, rtc);
- device_create_file(&dev->dev, &dev_attr_comp_preload);
- device_create_file(&dev->dev, &dev_attr_comp_delete);
+ err = device_create_file(&pdev->dev, &dev_attr_comp_preload);
+ if (err)
+ goto fail;
+ err = device_create_file(&pdev->dev, &dev_attr_comp_delete);
+ if (err) {
+ device_remove_file(&pdev->dev, &dev_attr_comp_preload);
+ goto fail;
+ }
return 0;
+
+fail:
+ if (ep93xx_rtc->mmio_base) {
+ iounmap(ep93xx_rtc->mmio_base);
+ pdev->dev.platform_data = NULL;
+ }
+ release_mem_region(res->start, resource_size(res));
+ return err;
}
-static int __devexit ep93xx_rtc_remove(struct platform_device *dev)
+static int __exit ep93xx_rtc_remove(struct platform_device *pdev)
{
- struct rtc_device *rtc = platform_get_drvdata(dev);
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
+ struct ep93xx_rtc *ep93xx_rtc = pdev->dev.platform_data;
+ struct resource *res;
+
+ /* cleanup sysfs */
+ device_remove_file(&pdev->dev, &dev_attr_comp_delete);
+ device_remove_file(&pdev->dev, &dev_attr_comp_preload);
+
+ rtc_device_unregister(rtc);
+
+ iounmap(ep93xx_rtc->mmio_base);
+ pdev->dev.platform_data = NULL;
- if (rtc)
- rtc_device_unregister(rtc);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, resource_size(res));
- platform_set_drvdata(dev, NULL);
+ platform_set_drvdata(pdev, NULL);
return 0;
}
@@ -122,23 +198,22 @@ static int __devexit ep93xx_rtc_remove(struct platform_device *dev)
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:ep93xx-rtc");
-static struct platform_driver ep93xx_rtc_platform_driver = {
+static struct platform_driver ep93xx_rtc_driver = {
.driver = {
.name = "ep93xx-rtc",
.owner = THIS_MODULE,
},
- .probe = ep93xx_rtc_probe,
- .remove = __devexit_p(ep93xx_rtc_remove),
+ .remove = __exit_p(ep93xx_rtc_remove),
};
static int __init ep93xx_rtc_init(void)
{
- return platform_driver_register(&ep93xx_rtc_platform_driver);
+ return platform_driver_probe(&ep93xx_rtc_driver, ep93xx_rtc_probe);
}
static void __exit ep93xx_rtc_exit(void)
{
- platform_driver_unregister(&ep93xx_rtc_platform_driver);
+ platform_driver_unregister(&ep93xx_rtc_driver);
}
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
diff --git a/drivers/rtc/rtc-msm6242.c b/drivers/rtc/rtc-msm6242.c
new file mode 100644
index 000000000000..10b9b7fb4700
--- /dev/null
+++ b/drivers/rtc/rtc-msm6242.c
@@ -0,0 +1,268 @@
+/*
+ * Oki MSM6242 RTC Driver
+ *
+ * Copyright 2009 Geert Uytterhoeven
+ *
+ * Based on the A2000 TOD code in arch/m68k/amiga/config.c
+ * Copyright (C) 1993 Hamish Macdonald
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+
+
+enum {
+ MSM6242_SECOND1 = 0x0, /* 1-second digit register */
+ MSM6242_SECOND10 = 0x1, /* 10-second digit register */
+ MSM6242_MINUTE1 = 0x2, /* 1-minute digit register */
+ MSM6242_MINUTE10 = 0x3, /* 10-minute digit register */
+ MSM6242_HOUR1 = 0x4, /* 1-hour digit register */
+ MSM6242_HOUR10 = 0x5, /* PM/AM, 10-hour digit register */
+ MSM6242_DAY1 = 0x6, /* 1-day digit register */
+ MSM6242_DAY10 = 0x7, /* 10-day digit register */
+ MSM6242_MONTH1 = 0x8, /* 1-month digit register */
+ MSM6242_MONTH10 = 0x9, /* 10-month digit register */
+ MSM6242_YEAR1 = 0xa, /* 1-year digit register */
+ MSM6242_YEAR10 = 0xb, /* 10-year digit register */
+ MSM6242_WEEK = 0xc, /* Week register */
+ MSM6242_CD = 0xd, /* Control Register D */
+ MSM6242_CE = 0xe, /* Control Register E */
+ MSM6242_CF = 0xf, /* Control Register F */
+};
+
+#define MSM6242_HOUR10_AM (0 << 2)
+#define MSM6242_HOUR10_PM (1 << 2)
+#define MSM6242_HOUR10_HR_MASK (3 << 0)
+
+#define MSM6242_WEEK_SUNDAY 0
+#define MSM6242_WEEK_MONDAY 1
+#define MSM6242_WEEK_TUESDAY 2
+#define MSM6242_WEEK_WEDNESDAY 3
+#define MSM6242_WEEK_THURSDAY 4
+#define MSM6242_WEEK_FRIDAY 5
+#define MSM6242_WEEK_SATURDAY 6
+
+#define MSM6242_CD_30_S_ADJ (1 << 3) /* 30-second adjustment */
+#define MSM6242_CD_IRQ_FLAG (1 << 2)
+#define MSM6242_CD_BUSY (1 << 1)
+#define MSM6242_CD_HOLD (1 << 0)
+
+#define MSM6242_CE_T_MASK (3 << 2)
+#define MSM6242_CE_T_64HZ (0 << 2) /* period 1/64 second */
+#define MSM6242_CE_T_1HZ (1 << 2) /* period 1 second */
+#define MSM6242_CE_T_1MINUTE (2 << 2) /* period 1 minute */
+#define MSM6242_CE_T_1HOUR (3 << 2) /* period 1 hour */
+
+#define MSM6242_CE_ITRPT_STND (1 << 1)
+#define MSM6242_CE_MASK (1 << 0) /* STD.P output control */
+
+#define MSM6242_CF_TEST (1 << 3)
+#define MSM6242_CF_12H (0 << 2)
+#define MSM6242_CF_24H (1 << 2)
+#define MSM6242_CF_STOP (1 << 1)
+#define MSM6242_CF_REST (1 << 0) /* reset */
+
+
+struct msm6242_priv {
+ u32 __iomem *regs;
+ struct rtc_device *rtc;
+};
+
+static inline unsigned int msm6242_read(struct msm6242_priv *priv,
+ unsigned int reg)
+{
+ return __raw_readl(&priv->regs[reg]) & 0xf;
+}
+
+static inline void msm6242_write(struct msm6242_priv *priv, unsigned int val,
+ unsigned int reg)
+{
+ return __raw_writel(val, &priv->regs[reg]);
+}
+
+static inline void msm6242_set(struct msm6242_priv *priv, unsigned int val,
+ unsigned int reg)
+{
+ msm6242_write(priv, msm6242_read(priv, reg) | val, reg);
+}
+
+static inline void msm6242_clear(struct msm6242_priv *priv, unsigned int val,
+ unsigned int reg)
+{
+ msm6242_write(priv, msm6242_read(priv, reg) & ~val, reg);
+}
+
+static void msm6242_lock(struct msm6242_priv *priv)
+{
+ int cnt = 5;
+
+ msm6242_set(priv, MSM6242_CD_HOLD, MSM6242_CD);
+
+ while ((msm6242_read(priv, MSM6242_CD) & MSM6242_CD_BUSY) && cnt--) {
+ msm6242_clear(priv, MSM6242_CD_HOLD, MSM6242_CD);
+ udelay(70);
+ msm6242_set(priv, MSM6242_CD_HOLD, MSM6242_CD);
+ }
+
+ if (!cnt)
+ pr_warning("msm6242: timed out waiting for RTC (0x%x)\n",
+ msm6242_read(priv, MSM6242_CD));
+}
+
+static void msm6242_unlock(struct msm6242_priv *priv)
+{
+ msm6242_clear(priv, MSM6242_CD_HOLD, MSM6242_CD);
+}
+
+static int msm6242_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct msm6242_priv *priv = dev_get_drvdata(dev);
+
+ msm6242_lock(priv);
+
+ tm->tm_sec = msm6242_read(priv, MSM6242_SECOND10) * 10 +
+ msm6242_read(priv, MSM6242_SECOND1);
+ tm->tm_min = msm6242_read(priv, MSM6242_MINUTE10) * 10 +
+ msm6242_read(priv, MSM6242_MINUTE1);
+ tm->tm_hour = (msm6242_read(priv, MSM6242_HOUR10 & 3)) * 10 +
+ msm6242_read(priv, MSM6242_HOUR1);
+ tm->tm_mday = msm6242_read(priv, MSM6242_DAY10) * 10 +
+ msm6242_read(priv, MSM6242_DAY1);
+ tm->tm_wday = msm6242_read(priv, MSM6242_WEEK);
+ tm->tm_mon = msm6242_read(priv, MSM6242_MONTH10) * 10 +
+ msm6242_read(priv, MSM6242_MONTH1) - 1;
+ tm->tm_year = msm6242_read(priv, MSM6242_YEAR10) * 10 +
+ msm6242_read(priv, MSM6242_YEAR1);
+ if (tm->tm_year <= 69)
+ tm->tm_year += 100;
+
+ if (!(msm6242_read(priv, MSM6242_CF) & MSM6242_CF_24H)) {
+ unsigned int pm = msm6242_read(priv, MSM6242_HOUR10) &
+ MSM6242_HOUR10_PM;
+ if (!pm && tm->tm_hour == 12)
+ tm->tm_hour = 0;
+ else if (pm && tm->tm_hour != 12)
+ tm->tm_hour += 12;
+ }
+
+ msm6242_unlock(priv);
+
+ return rtc_valid_tm(tm);
+}
+
+static int msm6242_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct msm6242_priv *priv = dev_get_drvdata(dev);
+
+ msm6242_lock(priv);
+
+ msm6242_write(priv, tm->tm_sec / 10, MSM6242_SECOND10);
+ msm6242_write(priv, tm->tm_sec % 10, MSM6242_SECOND1);
+ msm6242_write(priv, tm->tm_min / 10, MSM6242_MINUTE10);
+ msm6242_write(priv, tm->tm_min % 10, MSM6242_MINUTE1);
+ if (msm6242_read(priv, MSM6242_CF) & MSM6242_CF_24H)
+ msm6242_write(priv, tm->tm_hour / 10, MSM6242_HOUR10);
+ else if (tm->tm_hour >= 12)
+ msm6242_write(priv, MSM6242_HOUR10_PM + (tm->tm_hour - 12) / 10,
+ MSM6242_HOUR10);
+ else
+ msm6242_write(priv, tm->tm_hour / 10, MSM6242_HOUR10);
+ msm6242_write(priv, tm->tm_hour % 10, MSM6242_HOUR1);
+ msm6242_write(priv, tm->tm_mday / 10, MSM6242_DAY10);
+ msm6242_write(priv, tm->tm_mday % 10, MSM6242_DAY1);
+ if (tm->tm_wday != -1)
+ msm6242_write(priv, tm->tm_wday, MSM6242_WEEK);
+ msm6242_write(priv, (tm->tm_mon + 1) / 10, MSM6242_MONTH10);
+ msm6242_write(priv, (tm->tm_mon + 1) % 10, MSM6242_MONTH1);
+ if (tm->tm_year >= 100)
+ tm->tm_year -= 100;
+ msm6242_write(priv, tm->tm_year / 10, MSM6242_YEAR10);
+ msm6242_write(priv, tm->tm_year % 10, MSM6242_YEAR1);
+
+ msm6242_unlock(priv);
+ return 0;
+}
+
+static const struct rtc_class_ops msm6242_rtc_ops = {
+ .read_time = msm6242_read_time,
+ .set_time = msm6242_set_time,
+};
+
+static int __init msm6242_rtc_probe(struct platform_device *dev)
+{
+ struct resource *res;
+ struct msm6242_priv *priv;
+ struct rtc_device *rtc;
+ int error;
+
+ res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->regs = ioremap(res->start, resource_size(res));
+ if (!priv->regs) {
+ error = -ENOMEM;
+ goto out_free_priv;
+ }
+
+ rtc = rtc_device_register("rtc-msm6242", &dev->dev, &msm6242_rtc_ops,
+ THIS_MODULE);
+ if (IS_ERR(rtc)) {
+ error = PTR_ERR(rtc);
+ goto out_unmap;
+ }
+
+ priv->rtc = rtc;
+ platform_set_drvdata(dev, priv);
+ return 0;
+
+out_unmap:
+ iounmap(priv->regs);
+out_free_priv:
+ kfree(priv);
+ return error;
+}
+
+static int __exit msm6242_rtc_remove(struct platform_device *dev)
+{
+ struct msm6242_priv *priv = platform_get_drvdata(dev);
+
+ rtc_device_unregister(priv->rtc);
+ iounmap(priv->regs);
+ kfree(priv);
+ return 0;
+}
+
+static struct platform_driver msm6242_rtc_driver = {
+ .driver = {
+ .name = "rtc-msm6242",
+ .owner = THIS_MODULE,
+ },
+ .remove = __exit_p(msm6242_rtc_remove),
+};
+
+static int __init msm6242_rtc_init(void)
+{
+ return platform_driver_probe(&msm6242_rtc_driver, msm6242_rtc_probe);
+}
+
+static void __exit msm6242_rtc_fini(void)
+{
+ platform_driver_unregister(&msm6242_rtc_driver);
+}
+
+module_init(msm6242_rtc_init);
+module_exit(msm6242_rtc_fini);
+
+MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Oki MSM6242 RTC driver");
+MODULE_ALIAS("platform:rtc-msm6242");
diff --git a/drivers/rtc/rtc-rp5c01.c b/drivers/rtc/rtc-rp5c01.c
new file mode 100644
index 000000000000..e1313feb060f
--- /dev/null
+++ b/drivers/rtc/rtc-rp5c01.c
@@ -0,0 +1,222 @@
+/*
+ * Ricoh RP5C01 RTC Driver
+ *
+ * Copyright 2009 Geert Uytterhoeven
+ *
+ * Based on the A3000 TOD code in arch/m68k/amiga/config.c
+ * Copyright (C) 1993 Hamish Macdonald
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+
+
+enum {
+ RP5C01_1_SECOND = 0x0, /* MODE 00 */
+ RP5C01_10_SECOND = 0x1, /* MODE 00 */
+ RP5C01_1_MINUTE = 0x2, /* MODE 00 and MODE 01 */
+ RP5C01_10_MINUTE = 0x3, /* MODE 00 and MODE 01 */
+ RP5C01_1_HOUR = 0x4, /* MODE 00 and MODE 01 */
+ RP5C01_10_HOUR = 0x5, /* MODE 00 and MODE 01 */
+ RP5C01_DAY_OF_WEEK = 0x6, /* MODE 00 and MODE 01 */
+ RP5C01_1_DAY = 0x7, /* MODE 00 and MODE 01 */
+ RP5C01_10_DAY = 0x8, /* MODE 00 and MODE 01 */
+ RP5C01_1_MONTH = 0x9, /* MODE 00 */
+ RP5C01_10_MONTH = 0xa, /* MODE 00 */
+ RP5C01_1_YEAR = 0xb, /* MODE 00 */
+ RP5C01_10_YEAR = 0xc, /* MODE 00 */
+
+ RP5C01_12_24_SELECT = 0xa, /* MODE 01 */
+ RP5C01_LEAP_YEAR = 0xb, /* MODE 01 */
+
+ RP5C01_MODE = 0xd, /* all modes */
+ RP5C01_TEST = 0xe, /* all modes */
+ RP5C01_RESET = 0xf, /* all modes */
+};
+
+#define RP5C01_12_24_SELECT_12 (0 << 0)
+#define RP5C01_12_24_SELECT_24 (1 << 0)
+
+#define RP5C01_10_HOUR_AM (0 << 1)
+#define RP5C01_10_HOUR_PM (1 << 1)
+
+#define RP5C01_MODE_TIMER_EN (1 << 3) /* timer enable */
+#define RP5C01_MODE_ALARM_EN (1 << 2) /* alarm enable */
+
+#define RP5C01_MODE_MODE_MASK (3 << 0)
+#define RP5C01_MODE_MODE00 (0 << 0) /* time */
+#define RP5C01_MODE_MODE01 (1 << 0) /* alarm, 12h/24h, leap year */
+#define RP5C01_MODE_RAM_BLOCK10 (2 << 0) /* RAM 4 bits x 13 */
+#define RP5C01_MODE_RAM_BLOCK11 (3 << 0) /* RAM 4 bits x 13 */
+
+#define RP5C01_RESET_1HZ_PULSE (1 << 3)
+#define RP5C01_RESET_16HZ_PULSE (1 << 2)
+#define RP5C01_RESET_SECOND (1 << 1) /* reset divider stages for */
+ /* seconds or smaller units */
+#define RP5C01_RESET_ALARM (1 << 0) /* reset all alarm registers */
+
+
+struct rp5c01_priv {
+ u32 __iomem *regs;
+ struct rtc_device *rtc;
+};
+
+static inline unsigned int rp5c01_read(struct rp5c01_priv *priv,
+ unsigned int reg)
+{
+ return __raw_readl(&priv->regs[reg]) & 0xf;
+}
+
+static inline void rp5c01_write(struct rp5c01_priv *priv, unsigned int val,
+ unsigned int reg)
+{
+ return __raw_writel(val, &priv->regs[reg]);
+}
+
+static void rp5c01_lock(struct rp5c01_priv *priv)
+{
+ rp5c01_write(priv, RP5C01_MODE_MODE00, RP5C01_MODE);
+}
+
+static void rp5c01_unlock(struct rp5c01_priv *priv)
+{
+ rp5c01_write(priv, RP5C01_MODE_TIMER_EN | RP5C01_MODE_MODE01,
+ RP5C01_MODE);
+}
+
+static int rp5c01_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct rp5c01_priv *priv = dev_get_drvdata(dev);
+
+ rp5c01_lock(priv);
+
+ tm->tm_sec = rp5c01_read(priv, RP5C01_10_SECOND) * 10 +
+ rp5c01_read(priv, RP5C01_1_SECOND);
+ tm->tm_min = rp5c01_read(priv, RP5C01_10_MINUTE) * 10 +
+ rp5c01_read(priv, RP5C01_1_MINUTE);
+ tm->tm_hour = rp5c01_read(priv, RP5C01_10_HOUR) * 10 +
+ rp5c01_read(priv, RP5C01_1_HOUR);
+ tm->tm_mday = rp5c01_read(priv, RP5C01_10_DAY) * 10 +
+ rp5c01_read(priv, RP5C01_1_DAY);
+ tm->tm_wday = rp5c01_read(priv, RP5C01_DAY_OF_WEEK);
+ tm->tm_mon = rp5c01_read(priv, RP5C01_10_MONTH) * 10 +
+ rp5c01_read(priv, RP5C01_1_MONTH) - 1;
+ tm->tm_year = rp5c01_read(priv, RP5C01_10_YEAR) * 10 +
+ rp5c01_read(priv, RP5C01_1_YEAR);
+ if (tm->tm_year <= 69)
+ tm->tm_year += 100;
+
+ rp5c01_unlock(priv);
+
+ return rtc_valid_tm(tm);
+}
+
+static int rp5c01_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct rp5c01_priv *priv = dev_get_drvdata(dev);
+
+ rp5c01_lock(priv);
+
+ rp5c01_write(priv, tm->tm_sec / 10, RP5C01_10_SECOND);
+ rp5c01_write(priv, tm->tm_sec % 10, RP5C01_1_SECOND);
+ rp5c01_write(priv, tm->tm_min / 10, RP5C01_10_MINUTE);
+ rp5c01_write(priv, tm->tm_min % 10, RP5C01_1_MINUTE);
+ rp5c01_write(priv, tm->tm_hour / 10, RP5C01_10_HOUR);
+ rp5c01_write(priv, tm->tm_hour % 10, RP5C01_1_HOUR);
+ rp5c01_write(priv, tm->tm_mday / 10, RP5C01_10_DAY);
+ rp5c01_write(priv, tm->tm_mday % 10, RP5C01_1_DAY);
+ if (tm->tm_wday != -1)
+ rp5c01_write(priv, tm->tm_wday, RP5C01_DAY_OF_WEEK);
+ rp5c01_write(priv, (tm->tm_mon + 1) / 10, RP5C01_10_MONTH);
+ rp5c01_write(priv, (tm->tm_mon + 1) % 10, RP5C01_1_MONTH);
+ if (tm->tm_year >= 100)
+ tm->tm_year -= 100;
+ rp5c01_write(priv, tm->tm_year / 10, RP5C01_10_YEAR);
+ rp5c01_write(priv, tm->tm_year % 10, RP5C01_1_YEAR);
+
+ rp5c01_unlock(priv);
+ return 0;
+}
+
+static const struct rtc_class_ops rp5c01_rtc_ops = {
+ .read_time = rp5c01_read_time,
+ .set_time = rp5c01_set_time,
+};
+
+static int __init rp5c01_rtc_probe(struct platform_device *dev)
+{
+ struct resource *res;
+ struct rp5c01_priv *priv;
+ struct rtc_device *rtc;
+ int error;
+
+ res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->regs = ioremap(res->start, resource_size(res));
+ if (!priv->regs) {
+ error = -ENOMEM;
+ goto out_free_priv;
+ }
+
+ rtc = rtc_device_register("rtc-rp5c01", &dev->dev, &rp5c01_rtc_ops,
+ THIS_MODULE);
+ if (IS_ERR(rtc)) {
+ error = PTR_ERR(rtc);
+ goto out_unmap;
+ }
+
+ priv->rtc = rtc;
+ platform_set_drvdata(dev, priv);
+ return 0;
+
+out_unmap:
+ iounmap(priv->regs);
+out_free_priv:
+ kfree(priv);
+ return error;
+}
+
+static int __exit rp5c01_rtc_remove(struct platform_device *dev)
+{
+ struct rp5c01_priv *priv = platform_get_drvdata(dev);
+
+ rtc_device_unregister(priv->rtc);
+ iounmap(priv->regs);
+ kfree(priv);
+ return 0;
+}
+
+static struct platform_driver rp5c01_rtc_driver = {
+ .driver = {
+ .name = "rtc-rp5c01",
+ .owner = THIS_MODULE,
+ },
+ .remove = __exit_p(rp5c01_rtc_remove),
+};
+
+static int __init rp5c01_rtc_init(void)
+{
+ return platform_driver_probe(&rp5c01_rtc_driver, rp5c01_rtc_probe);
+}
+
+static void __exit rp5c01_rtc_fini(void)
+{
+ platform_driver_unregister(&rp5c01_rtc_driver);
+}
+
+module_init(rp5c01_rtc_init);
+module_exit(rp5c01_rtc_fini);
+
+MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Ricoh RP5C01 RTC driver");
+MODULE_ALIAS("platform:rtc-rp5c01");
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index 9b1ff12bf947..d7310adb7152 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -1,7 +1,7 @@
/*
* SuperH On-Chip RTC Support
*
- * Copyright (C) 2006, 2007, 2008 Paul Mundt
+ * Copyright (C) 2006 - 2009 Paul Mundt
* Copyright (C) 2006 Jamie Lenehan
* Copyright (C) 2008 Angelo Castello
*
@@ -25,10 +25,11 @@
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/log2.h>
+#include <linux/clk.h>
#include <asm/rtc.h>
#define DRV_NAME "sh-rtc"
-#define DRV_VERSION "0.2.1"
+#define DRV_VERSION "0.2.2"
#define RTC_REG(r) ((r) * rtc_reg_size)
@@ -87,16 +88,17 @@
#define RCR2_START 0x01 /* Start bit */
struct sh_rtc {
- void __iomem *regbase;
- unsigned long regsize;
- struct resource *res;
- int alarm_irq;
- int periodic_irq;
- int carry_irq;
- struct rtc_device *rtc_dev;
- spinlock_t lock;
- unsigned long capabilities; /* See asm-sh/rtc.h for cap bits */
- unsigned short periodic_freq;
+ void __iomem *regbase;
+ unsigned long regsize;
+ struct resource *res;
+ int alarm_irq;
+ int periodic_irq;
+ int carry_irq;
+ struct clk *clk;
+ struct rtc_device *rtc_dev;
+ spinlock_t lock;
+ unsigned long capabilities; /* See asm/rtc.h for cap bits */
+ unsigned short periodic_freq;
};
static int __sh_rtc_interrupt(struct sh_rtc *rtc)
@@ -294,10 +296,10 @@ static inline void sh_rtc_setaie(struct device *dev, unsigned int enable)
tmp = readb(rtc->regbase + RCR1);
- if (!enable)
- tmp &= ~RCR1_AIE;
- else
+ if (enable)
tmp |= RCR1_AIE;
+ else
+ tmp &= ~RCR1_AIE;
writeb(tmp, rtc->regbase + RCR1);
@@ -618,6 +620,7 @@ static int sh_rtc_irq_set_freq(struct device *dev, int freq)
{
if (!is_power_of_2(freq))
return -EINVAL;
+
return sh_rtc_ioctl(dev, RTC_IRQP_SET, freq);
}
@@ -637,7 +640,8 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
struct sh_rtc *rtc;
struct resource *res;
struct rtc_time r;
- int ret;
+ char clk_name[6];
+ int clk_id, ret;
rtc = kzalloc(sizeof(struct sh_rtc), GFP_KERNEL);
if (unlikely(!rtc))
@@ -652,6 +656,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "No IRQ resource\n");
goto err_badres;
}
+
rtc->periodic_irq = ret;
rtc->carry_irq = platform_get_irq(pdev, 1);
rtc->alarm_irq = platform_get_irq(pdev, 2);
@@ -663,7 +668,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
goto err_badres;
}
- rtc->regsize = res->end - res->start + 1;
+ rtc->regsize = resource_size(res);
rtc->res = request_mem_region(res->start, rtc->regsize, pdev->name);
if (unlikely(!rtc->res)) {
@@ -677,6 +682,26 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
goto err_badmap;
}
+ clk_id = pdev->id;
+ /* With a single device, the clock id is still "rtc0" */
+ if (clk_id < 0)
+ clk_id = 0;
+
+ snprintf(clk_name, sizeof(clk_name), "rtc%d", clk_id);
+
+ rtc->clk = clk_get(&pdev->dev, clk_name);
+ if (IS_ERR(rtc->clk)) {
+ /*
+ * No error handling for rtc->clk intentionally, not all
+ * platforms will have a unique clock for the RTC, and
+ * the clk API can handle the struct clk pointer being
+ * NULL.
+ */
+ rtc->clk = NULL;
+ }
+
+ clk_enable(rtc->clk);
+
rtc->rtc_dev = rtc_device_register("sh", &pdev->dev,
&sh_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc->rtc_dev)) {
@@ -759,6 +784,8 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
return 0;
err_unmap:
+ clk_disable(rtc->clk);
+ clk_put(rtc->clk);
iounmap(rtc->regbase);
err_badmap:
release_resource(rtc->res);
@@ -780,6 +807,7 @@ static int __devexit sh_rtc_remove(struct platform_device *pdev)
sh_rtc_setcie(&pdev->dev, 0);
free_irq(rtc->periodic_irq, rtc);
+
if (rtc->carry_irq > 0) {
free_irq(rtc->carry_irq, rtc);
free_irq(rtc->alarm_irq, rtc);
@@ -789,6 +817,9 @@ static int __devexit sh_rtc_remove(struct platform_device *pdev)
iounmap(rtc->regbase);
+ clk_disable(rtc->clk);
+ clk_put(rtc->clk);
+
platform_set_drvdata(pdev, NULL);
kfree(rtc);
@@ -802,11 +833,11 @@ static void sh_rtc_set_irq_wake(struct device *dev, int enabled)
struct sh_rtc *rtc = platform_get_drvdata(pdev);
set_irq_wake(rtc->periodic_irq, enabled);
+
if (rtc->carry_irq > 0) {
set_irq_wake(rtc->carry_irq, enabled);
set_irq_wake(rtc->alarm_irq, enabled);
}
-
}
static int sh_rtc_suspend(struct device *dev)
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 0570794ccf1c..fabec95686b0 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -20,6 +20,7 @@
#include <linux/slab.h>
#include <linux/buffer_head.h>
#include <linux/hdreg.h>
+#include <linux/async.h>
#include <asm/ccwdev.h>
#include <asm/ebcdic.h>
@@ -480,8 +481,10 @@ static void dasd_change_state(struct dasd_device *device)
if (rc && rc != -EAGAIN)
device->target = device->state;
- if (device->state == device->target)
+ if (device->state == device->target) {
wake_up(&dasd_init_waitq);
+ dasd_put_device(device);
+ }
/* let user-space know that the device status changed */
kobject_uevent(&device->cdev->dev.kobj, KOBJ_CHANGE);
@@ -513,12 +516,15 @@ void dasd_kick_device(struct dasd_device *device)
*/
void dasd_set_target_state(struct dasd_device *device, int target)
{
+ dasd_get_device(device);
/* If we are in probeonly mode stop at DASD_STATE_READY. */
if (dasd_probeonly && target > DASD_STATE_READY)
target = DASD_STATE_READY;
if (device->target != target) {
- if (device->state == target)
+ if (device->state == target) {
wake_up(&dasd_init_waitq);
+ dasd_put_device(device);
+ }
device->target = target;
}
if (device->state != device->target)
@@ -1608,15 +1614,6 @@ void dasd_block_clear_timer(struct dasd_block *block)
}
/*
- * posts the buffer_cache about a finalized request
- */
-static inline void dasd_end_request(struct request *req, int error)
-{
- if (__blk_end_request(req, error, blk_rq_bytes(req)))
- BUG();
-}
-
-/*
* Process finished error recovery ccw.
*/
static inline void __dasd_block_process_erp(struct dasd_block *block,
@@ -1670,7 +1667,7 @@ static void __dasd_process_request_queue(struct dasd_block *block)
"Rejecting write request %p",
req);
blkdev_dequeue_request(req);
- dasd_end_request(req, -EIO);
+ __blk_end_request_all(req, -EIO);
continue;
}
cqr = basedev->discipline->build_cp(basedev, block, req);
@@ -1699,7 +1696,7 @@ static void __dasd_process_request_queue(struct dasd_block *block)
"on request %p",
PTR_ERR(cqr), req);
blkdev_dequeue_request(req);
- dasd_end_request(req, -EIO);
+ __blk_end_request_all(req, -EIO);
continue;
}
/*
@@ -1725,7 +1722,7 @@ static void __dasd_cleanup_cqr(struct dasd_ccw_req *cqr)
status = cqr->block->base->discipline->free_cp(cqr, req);
if (status <= 0)
error = status ? status : -EIO;
- dasd_end_request(req, error);
+ __blk_end_request_all(req, error);
}
/*
@@ -2034,7 +2031,7 @@ static void dasd_flush_request_queue(struct dasd_block *block)
spin_lock_irq(&block->request_queue_lock);
while ((req = elv_next_request(block->request_queue))) {
blkdev_dequeue_request(req);
- dasd_end_request(req, -EIO);
+ __blk_end_request_all(req, -EIO);
}
spin_unlock_irq(&block->request_queue_lock);
}
@@ -2148,6 +2145,22 @@ dasd_exit(void)
* SECTION: common functions for ccw_driver use
*/
+static void dasd_generic_auto_online(void *data, async_cookie_t cookie)
+{
+ struct ccw_device *cdev = data;
+ int ret;
+
+ ret = ccw_device_set_online(cdev);
+ if (ret)
+ pr_warning("%s: Setting the DASD online failed with rc=%d\n",
+ dev_name(&cdev->dev), ret);
+ else {
+ struct dasd_device *device = dasd_device_from_cdev(cdev);
+ wait_event(dasd_init_waitq, _wait_for_device(device));
+ dasd_put_device(device);
+ }
+}
+
/*
* Initial attempt at a probe function. this can be simplified once
* the other detection code is gone.
@@ -2180,10 +2193,7 @@ int dasd_generic_probe(struct ccw_device *cdev,
*/
if ((dasd_get_feature(cdev, DASD_FEATURE_INITIAL_ONLINE) > 0 ) ||
(dasd_autodetect && dasd_busid_known(dev_name(&cdev->dev)) != 0))
- ret = ccw_device_set_online(cdev);
- if (ret)
- pr_warning("%s: Setting the DASD online failed with rc=%d\n",
- dev_name(&cdev->dev), ret);
+ async_schedule(dasd_generic_auto_online, cdev);
return 0;
}
@@ -2290,13 +2300,7 @@ int dasd_generic_set_online(struct ccw_device *cdev,
} else
pr_debug("dasd_generic device %s found\n",
dev_name(&cdev->dev));
-
- /* FIXME: we have to wait for the root device but we don't want
- * to wait for each single device but for all at once. */
- wait_event(dasd_init_waitq, _wait_for_device(device));
-
dasd_put_device(device);
-
return rc;
}
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 21254793c604..cb52da033f06 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -2019,15 +2019,23 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track(
ccw++;
recid += count;
new_track = 0;
+ /* first idaw for a ccw may start anywhere */
+ if (!idaw_dst)
+ idaw_dst = dst;
}
- /* If we start a new idaw, everything is fine and the
- * start of the new idaw is the start of this segment.
+ /* If we start a new idaw, we must make sure that it
+ * starts on an IDA_BLOCK_SIZE boundary.
* If we continue an idaw, we must make sure that the
* current segment begins where the so far accumulated
* idaw ends
*/
- if (!idaw_dst)
- idaw_dst = dst;
+ if (!idaw_dst) {
+ if (__pa(dst) & (IDA_BLOCK_SIZE-1)) {
+ dasd_sfree_request(cqr, startdev);
+ return ERR_PTR(-ERANGE);
+ } else
+ idaw_dst = dst;
+ }
if ((idaw_dst + idaw_len) != dst) {
dasd_sfree_request(cqr, startdev);
return ERR_PTR(-ERANGE);
diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h
index c07809c8016a..5469e099597e 100644
--- a/drivers/s390/char/tape.h
+++ b/drivers/s390/char/tape.h
@@ -285,7 +285,7 @@ extern int tape_mtop(struct tape_device *, int, int);
extern void tape_state_set(struct tape_device *, enum tape_state);
extern int tape_generic_online(struct tape_device *, struct tape_discipline *);
-extern int tape_generic_offline(struct tape_device *device);
+extern int tape_generic_offline(struct ccw_device *);
/* Externals from tape_devmap.c */
extern int tape_generic_probe(struct ccw_device *);
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
index 807ded5eb049..5f8e8ef43dd3 100644
--- a/drivers/s390/char/tape_34xx.c
+++ b/drivers/s390/char/tape_34xx.c
@@ -1294,12 +1294,6 @@ tape_34xx_online(struct ccw_device *cdev)
);
}
-static int
-tape_34xx_offline(struct ccw_device *cdev)
-{
- return tape_generic_offline(cdev->dev.driver_data);
-}
-
static struct ccw_driver tape_34xx_driver = {
.name = "tape_34xx",
.owner = THIS_MODULE,
@@ -1307,7 +1301,7 @@ static struct ccw_driver tape_34xx_driver = {
.probe = tape_generic_probe,
.remove = tape_generic_remove,
.set_online = tape_34xx_online,
- .set_offline = tape_34xx_offline,
+ .set_offline = tape_generic_offline,
};
static int
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index fc1d91294143..823b05bd0dd7 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -1707,19 +1707,13 @@ tape_3590_online(struct ccw_device *cdev)
&tape_discipline_3590);
}
-static int
-tape_3590_offline(struct ccw_device *cdev)
-{
- return tape_generic_offline(cdev->dev.driver_data);
-}
-
static struct ccw_driver tape_3590_driver = {
.name = "tape_3590",
.owner = THIS_MODULE,
.ids = tape_3590_ids,
.probe = tape_generic_probe,
.remove = tape_generic_remove,
- .set_offline = tape_3590_offline,
+ .set_offline = tape_generic_offline,
.set_online = tape_3590_online,
};
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index f32e89e7c4f2..86596d3813b5 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -74,13 +74,6 @@ tapeblock_trigger_requeue(struct tape_device *device)
* Post finished request.
*/
static void
-tapeblock_end_request(struct request *req, int error)
-{
- if (blk_end_request(req, error, blk_rq_bytes(req)))
- BUG();
-}
-
-static void
__tapeblock_end_request(struct tape_request *ccw_req, void *data)
{
struct tape_device *device;
@@ -90,7 +83,7 @@ __tapeblock_end_request(struct tape_request *ccw_req, void *data)
device = ccw_req->device;
req = (struct request *) data;
- tapeblock_end_request(req, (ccw_req->rc == 0) ? 0 : -EIO);
+ blk_end_request_all(req, (ccw_req->rc == 0) ? 0 : -EIO);
if (ccw_req->rc == 0)
/* Update position. */
device->blk_data.block_position =
@@ -118,7 +111,7 @@ tapeblock_start_request(struct tape_device *device, struct request *req)
ccw_req = device->discipline->bread(device, req);
if (IS_ERR(ccw_req)) {
DBF_EVENT(1, "TBLOCK: bread failed\n");
- tapeblock_end_request(req, -EIO);
+ blk_end_request_all(req, -EIO);
return PTR_ERR(ccw_req);
}
ccw_req->callback = __tapeblock_end_request;
@@ -131,7 +124,7 @@ tapeblock_start_request(struct tape_device *device, struct request *req)
* Start/enqueueing failed. No retries in
* this case.
*/
- tapeblock_end_request(req, -EIO);
+ blk_end_request_all(req, -EIO);
device->discipline->free_bread(ccw_req);
}
@@ -177,7 +170,7 @@ tapeblock_requeue(struct work_struct *work) {
DBF_EVENT(1, "TBLOCK: Rejecting write request\n");
blkdev_dequeue_request(req);
spin_unlock_irq(&device->blk_data.request_queue_lock);
- tapeblock_end_request(req, -EIO);
+ blk_end_request_all(req, -EIO);
spin_lock_irq(&device->blk_data.request_queue_lock);
continue;
}
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 08c09d3503cf..8a109f3b69c6 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -387,8 +387,11 @@ tape_cleanup_device(struct tape_device *device)
* Manual offline is only allowed while the drive is not in use.
*/
int
-tape_generic_offline(struct tape_device *device)
+tape_generic_offline(struct ccw_device *cdev)
{
+ struct tape_device *device;
+
+ device = cdev->dev.driver_data;
if (!device) {
return -ENODEV;
}
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 2aebb9823044..9889f188c7c5 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -28,7 +28,7 @@
#include <asm/chpid.h>
#include <asm/airq.h>
#include <asm/isc.h>
-#include <asm/cpu.h>
+#include <asm/cputime.h>
#include <asm/fcx.h>
#include <asm/nmi.h>
#include <asm/crw.h>
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 151754d54745..bf0a24af39a0 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -114,7 +114,7 @@ int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
struct subchannel *sch;
int ret;
- if (!cdev)
+ if (!cdev || !cdev->dev.parent)
return -ENODEV;
if (cdev->private->state == DEV_STATE_NOT_OPER)
return -ENODEV;
@@ -122,8 +122,6 @@ int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
cdev->private->state != DEV_STATE_W4SENSE)
return -EINVAL;
sch = to_subchannel(cdev->dev.parent);
- if (!sch)
- return -ENODEV;
ret = cio_clear(sch);
if (ret == 0)
cdev->private->intparm = intparm;
@@ -161,11 +159,9 @@ int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
struct subchannel *sch;
int ret;
- if (!cdev)
+ if (!cdev || !cdev->dev.parent)
return -ENODEV;
sch = to_subchannel(cdev->dev.parent);
- if (!sch)
- return -ENODEV;
if (cdev->private->state == DEV_STATE_NOT_OPER)
return -ENODEV;
if (cdev->private->state == DEV_STATE_VERIFY ||
@@ -339,7 +335,7 @@ int ccw_device_halt(struct ccw_device *cdev, unsigned long intparm)
struct subchannel *sch;
int ret;
- if (!cdev)
+ if (!cdev || !cdev->dev.parent)
return -ENODEV;
if (cdev->private->state == DEV_STATE_NOT_OPER)
return -ENODEV;
@@ -347,8 +343,6 @@ int ccw_device_halt(struct ccw_device *cdev, unsigned long intparm)
cdev->private->state != DEV_STATE_W4SENSE)
return -EINVAL;
sch = to_subchannel(cdev->dev.parent);
- if (!sch)
- return -ENODEV;
ret = cio_halt(sch);
if (ret == 0)
cdev->private->intparm = intparm;
@@ -372,11 +366,9 @@ int ccw_device_resume(struct ccw_device *cdev)
{
struct subchannel *sch;
- if (!cdev)
+ if (!cdev || !cdev->dev.parent)
return -ENODEV;
sch = to_subchannel(cdev->dev.parent);
- if (!sch)
- return -ENODEV;
if (cdev->private->state == DEV_STATE_NOT_OPER)
return -ENODEV;
if (cdev->private->state != DEV_STATE_ONLINE ||
@@ -471,11 +463,11 @@ __u8 ccw_device_get_path_mask(struct ccw_device *cdev)
{
struct subchannel *sch;
- sch = to_subchannel(cdev->dev.parent);
- if (!sch)
+ if (!cdev->dev.parent)
return 0;
- else
- return sch->lpm;
+
+ sch = to_subchannel(cdev->dev.parent);
+ return sch->lpm;
}
/*
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 9e8a2914259b..ba4facc37011 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -881,78 +881,26 @@ no_handler:
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED);
}
-static void qdio_call_shutdown(struct work_struct *work)
-{
- struct ccw_device_private *priv;
- struct ccw_device *cdev;
-
- priv = container_of(work, struct ccw_device_private, kick_work);
- cdev = priv->cdev;
- qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR);
- put_device(&cdev->dev);
-}
-
-static void qdio_int_error(struct ccw_device *cdev)
+static void qdio_establish_handle_irq(struct ccw_device *cdev, int cstat,
+ int dstat)
{
struct qdio_irq *irq_ptr = cdev->private->qdio_data;
- switch (irq_ptr->state) {
- case QDIO_IRQ_STATE_INACTIVE:
- case QDIO_IRQ_STATE_CLEANUP:
- qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
- break;
- case QDIO_IRQ_STATE_ESTABLISHED:
- case QDIO_IRQ_STATE_ACTIVE:
- qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED);
- if (get_device(&cdev->dev)) {
- /* Can't call shutdown from interrupt context. */
- PREPARE_WORK(&cdev->private->kick_work,
- qdio_call_shutdown);
- queue_work(ccw_device_work, &cdev->private->kick_work);
- }
- break;
- default:
- WARN_ON(1);
- }
- wake_up(&cdev->private->wait_q);
-}
-
-static int qdio_establish_check_errors(struct ccw_device *cdev, int cstat,
- int dstat)
-{
- struct qdio_irq *irq_ptr = cdev->private->qdio_data;
+ DBF_DEV_EVENT(DBF_INFO, irq_ptr, "qest irq");
- if (cstat || (dstat & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END))) {
- DBF_ERROR("EQ:ck con");
+ if (cstat)
goto error;
- }
-
- if (!(dstat & DEV_STAT_DEV_END)) {
- DBF_ERROR("EQ:no dev");
+ if (dstat & ~(DEV_STAT_DEV_END | DEV_STAT_CHN_END))
goto error;
- }
-
- if (dstat & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) {
- DBF_ERROR("EQ: bad io");
+ if (!(dstat & DEV_STAT_DEV_END))
goto error;
- }
- return 0;
+ qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ESTABLISHED);
+ return;
+
error:
DBF_ERROR("%4x EQ:error", irq_ptr->schid.sch_no);
DBF_ERROR("ds: %2x cs:%2x", dstat, cstat);
-
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
- return 1;
-}
-
-static void qdio_establish_handle_irq(struct ccw_device *cdev, int cstat,
- int dstat)
-{
- struct qdio_irq *irq_ptr = cdev->private->qdio_data;
-
- DBF_DEV_EVENT(DBF_INFO, irq_ptr, "qest irq");
- if (!qdio_establish_check_errors(cdev, cstat, dstat))
- qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ESTABLISHED);
}
/* qdio interrupt handler */
@@ -973,10 +921,8 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
switch (PTR_ERR(irb)) {
case -EIO:
DBF_ERROR("%4x IO error", irq_ptr->schid.sch_no);
- return;
- case -ETIMEDOUT:
- DBF_ERROR("%4x IO timeout", irq_ptr->schid.sch_no);
- qdio_int_error(cdev);
+ qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
+ wake_up(&cdev->private->wait_q);
return;
default:
WARN_ON(1);
@@ -984,7 +930,6 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
}
}
qdio_irq_check_sense(irq_ptr, irb);
-
cstat = irb->scsw.cmd.cstat;
dstat = irb->scsw.cmd.dstat;
@@ -992,23 +937,19 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
case QDIO_IRQ_STATE_INACTIVE:
qdio_establish_handle_irq(cdev, cstat, dstat);
break;
-
case QDIO_IRQ_STATE_CLEANUP:
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE);
break;
-
case QDIO_IRQ_STATE_ESTABLISHED:
case QDIO_IRQ_STATE_ACTIVE:
if (cstat & SCHN_STAT_PCI) {
qdio_int_handler_pci(irq_ptr);
- /* no state change so no need to wake up wait_q */
return;
}
- if ((cstat & ~SCHN_STAT_PCI) || dstat) {
+ if (cstat || dstat)
qdio_handle_activate_check(cdev, intparm, cstat,
dstat);
- break;
- }
+ break;
default:
WARN_ON(1);
}
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 616c60ffcf2c..3ac27ee47396 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -97,9 +97,7 @@ static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun)
ccw_device_set_online(adapter->ccw_device);
zfcp_erp_wait(adapter);
- wait_event(adapter->erp_done_wqh,
- !(atomic_read(&unit->status) &
- ZFCP_STATUS_UNIT_SCSI_WORK_PENDING));
+ flush_work(&unit->scsi_work);
down(&zfcp_data.config_sema);
zfcp_unit_put(unit);
@@ -279,6 +277,7 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
atomic_set(&unit->refcount, 0);
init_waitqueue_head(&unit->remove_wq);
+ INIT_WORK(&unit->scsi_work, zfcp_scsi_scan);
unit->port = port;
unit->fcp_lun = fcp_lun;
@@ -525,6 +524,8 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
+ zfcp_fc_nameserver_init(adapter);
+
if (!zfcp_adapter_scsi_register(adapter))
return 0;
@@ -553,7 +554,6 @@ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
cancel_work_sync(&adapter->scan_work);
cancel_work_sync(&adapter->stat_work);
- cancel_delayed_work_sync(&adapter->nsp.work);
zfcp_adapter_scsi_unregister(adapter);
sysfs_remove_group(&adapter->ccw_device->dev.kobj,
&zfcp_sysfs_adapter_attrs);
@@ -671,8 +671,7 @@ void zfcp_port_dequeue(struct zfcp_port *port)
list_del(&port->list);
write_unlock_irq(&zfcp_data.config_lock);
if (port->rport)
- fc_remote_port_delete(port->rport);
- port->rport = NULL;
+ port->rport->dd_data = NULL;
zfcp_adapter_put(port->adapter);
sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs);
device_unregister(&port->sysfs_device);
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index cfb0dcb6e3ff..733fe3bf6285 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -108,7 +108,6 @@ static int zfcp_ccw_set_online(struct ccw_device *ccw_device)
/* initialize request counter */
BUG_ON(!zfcp_reqlist_isempty(adapter));
adapter->req_no = 0;
- zfcp_fc_nameserver_init(adapter);
zfcp_erp_modify_adapter_status(adapter, "ccsonl1", NULL,
ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c
index 10cbfd172a28..8305c874e86f 100644
--- a/drivers/s390/scsi/zfcp_cfdc.c
+++ b/drivers/s390/scsi/zfcp_cfdc.c
@@ -4,7 +4,7 @@
* Userspace interface for accessing the
* Access Control Lists / Control File Data Channel
*
- * Copyright IBM Corporation 2008
+ * Copyright IBM Corporation 2008, 2009
*/
#define KMSG_COMPONENT "zfcp"
@@ -197,6 +197,7 @@ static long zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command,
retval = -ENXIO;
goto free_buffer;
}
+ zfcp_adapter_get(adapter);
retval = zfcp_cfdc_sg_setup(data->command, fsf_cfdc->sg,
data_user->control_file);
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index a0318630f047..4c362a9069f0 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -255,7 +255,6 @@ enum zfcp_wka_status {
/* logical unit status */
#define ZFCP_STATUS_UNIT_SHARED 0x00000004
#define ZFCP_STATUS_UNIT_READONLY 0x00000008
-#define ZFCP_STATUS_UNIT_SCSI_WORK_PENDING 0x00000020
/* FSF request status (this does not have a common part) */
#define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT 0x00000002
@@ -530,6 +529,7 @@ struct zfcp_unit {
struct zfcp_erp_action erp_action; /* pending error recovery */
atomic_t erp_counter;
struct zfcp_latencies latencies;
+ struct work_struct scsi_work;
};
/* FSF request */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 631bdb1dfd6c..fdc9b4352a64 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -719,6 +719,7 @@ static void zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *act)
zfcp_qdio_close(adapter);
zfcp_fsf_req_dismiss_all(adapter);
adapter->fsf_req_seq_no = 0;
+ zfcp_fc_wka_port_force_offline(&adapter->nsp);
/* all ports and units are closed */
zfcp_erp_modify_adapter_status(adapter, "erascl1", NULL,
ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
@@ -1176,48 +1177,6 @@ static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
}
}
-struct zfcp_erp_add_work {
- struct zfcp_unit *unit;
- struct work_struct work;
-};
-
-static void zfcp_erp_scsi_scan(struct work_struct *work)
-{
- struct zfcp_erp_add_work *p =
- container_of(work, struct zfcp_erp_add_work, work);
- struct zfcp_unit *unit = p->unit;
- struct fc_rport *rport = unit->port->rport;
-
- if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
- scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
- scsilun_to_int((struct scsi_lun *)&unit->fcp_lun), 0);
- atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
- zfcp_unit_put(unit);
- wake_up(&unit->port->adapter->erp_done_wqh);
- kfree(p);
-}
-
-static void zfcp_erp_schedule_work(struct zfcp_unit *unit)
-{
- struct zfcp_erp_add_work *p;
-
- p = kzalloc(sizeof(*p), GFP_KERNEL);
- if (!p) {
- dev_err(&unit->port->adapter->ccw_device->dev,
- "Registering unit 0x%016Lx on port 0x%016Lx failed\n",
- (unsigned long long)unit->fcp_lun,
- (unsigned long long)unit->port->wwpn);
- return;
- }
-
- zfcp_unit_get(unit);
- atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
- INIT_WORK(&p->work, zfcp_erp_scsi_scan);
- p->unit = unit;
- if (!queue_work(zfcp_data.work_queue, &p->work))
- zfcp_unit_put(unit);
-}
-
static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
{
struct zfcp_adapter *adapter = act->adapter;
@@ -1226,11 +1185,11 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
switch (act->action) {
case ZFCP_ERP_ACTION_REOPEN_UNIT:
- flush_work(&port->rport_work);
if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) {
- if (!(atomic_read(&unit->status) &
- ZFCP_STATUS_UNIT_SCSI_WORK_PENDING))
- zfcp_erp_schedule_work(unit);
+ zfcp_unit_get(unit);
+ if (scsi_queue_work(unit->port->adapter->scsi_host,
+ &unit->scsi_work) <= 0)
+ zfcp_unit_put(unit);
}
zfcp_unit_put(unit);
break;
@@ -1352,6 +1311,11 @@ static int zfcp_erp_thread(void *data)
while (!(atomic_read(&adapter->status) &
ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL)) {
+
+ zfcp_rec_dbf_event_thread_lock("erthrd1", adapter);
+ ignore = down_interruptible(&adapter->erp_ready_sem);
+ zfcp_rec_dbf_event_thread_lock("erthrd2", adapter);
+
write_lock_irqsave(&adapter->erp_lock, flags);
next = adapter->erp_ready_head.next;
write_unlock_irqrestore(&adapter->erp_lock, flags);
@@ -1363,10 +1327,6 @@ static int zfcp_erp_thread(void *data)
if (zfcp_erp_strategy(act) != ZFCP_ERP_DISMISSED)
zfcp_erp_wakeup(adapter);
}
-
- zfcp_rec_dbf_event_thread_lock("erthrd1", adapter);
- ignore = down_interruptible(&adapter->erp_ready_sem);
- zfcp_rec_dbf_event_thread_lock("erthrd2", adapter);
}
atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index f6399ca97bcb..2e31b536548c 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -106,6 +106,7 @@ extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *);
extern void zfcp_test_link(struct zfcp_port *);
extern void zfcp_fc_link_test_work(struct work_struct *);
extern void zfcp_fc_nameserver_init(struct zfcp_adapter *);
+extern void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *);
/* zfcp_fsf.c */
extern int zfcp_fsf_open_port(struct zfcp_erp_action *);
@@ -158,6 +159,7 @@ extern void zfcp_scsi_rport_work(struct work_struct *);
extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *);
extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *);
extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *);
+extern void zfcp_scsi_scan(struct work_struct *);
/* zfcp_sysfs.c */
extern struct attribute_group zfcp_sysfs_unit_attrs;
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index e8d032b9dfbd..18fd975412d3 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -98,13 +98,6 @@ static void zfcp_wka_port_offline(struct work_struct *work)
struct zfcp_wka_port *wka_port =
container_of(dw, struct zfcp_wka_port, work);
- /* Don't wait forvever. If the wka_port is too busy take it offline
- through a new call later */
- if (!wait_event_timeout(wka_port->completion_wq,
- atomic_read(&wka_port->refcount) == 0,
- HZ >> 1))
- return;
-
mutex_lock(&wka_port->mutex);
if ((atomic_read(&wka_port->refcount) != 0) ||
(wka_port->status != ZFCP_WKA_PORT_ONLINE))
@@ -123,7 +116,7 @@ static void zfcp_wka_port_put(struct zfcp_wka_port *wka_port)
{
if (atomic_dec_return(&wka_port->refcount) != 0)
return;
- /* wait 10 miliseconds, other reqs might pop in */
+ /* wait 10 milliseconds, other reqs might pop in */
schedule_delayed_work(&wka_port->work, HZ / 100);
}
@@ -142,6 +135,14 @@ void zfcp_fc_nameserver_init(struct zfcp_adapter *adapter)
INIT_DELAYED_WORK(&wka_port->work, zfcp_wka_port_offline);
}
+void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *wka)
+{
+ cancel_delayed_work_sync(&wka->work);
+ mutex_lock(&wka->mutex);
+ wka->status = ZFCP_WKA_PORT_OFFLINE;
+ mutex_unlock(&wka->mutex);
+}
+
static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range,
struct fcp_rscn_element *elem)
{
@@ -372,7 +373,8 @@ static void zfcp_fc_adisc_handler(unsigned long data)
if (adisc->els.status) {
/* request rejected or timed out */
- zfcp_erp_port_forced_reopen(port, 0, "fcadh_1", NULL);
+ zfcp_erp_port_forced_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED,
+ "fcadh_1", NULL);
goto out;
}
@@ -431,11 +433,6 @@ void zfcp_fc_link_test_work(struct work_struct *work)
container_of(work, struct zfcp_port, test_link_work);
int retval;
- if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_UNBLOCKED)) {
- zfcp_port_put(port);
- return; /* port erp is running and will update rport status */
- }
-
zfcp_port_get(port);
port->rport_task = RPORT_DEL;
zfcp_scsi_rport_work(&port->rport_work);
@@ -542,6 +539,9 @@ static void zfcp_validate_port(struct zfcp_port *port)
{
struct zfcp_adapter *adapter = port->adapter;
+ if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC))
+ return;
+
atomic_clear_mask(ZFCP_STATUS_COMMON_NOESC, &port->status);
if ((port->supported_classes != 0) ||
@@ -602,10 +602,8 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries)
if (acc->wwpn == fc_host_port_name(adapter->scsi_host))
continue;
port = zfcp_get_port_by_wwpn(adapter, acc->wwpn);
- if (port) {
- zfcp_port_get(port);
+ if (port)
continue;
- }
port = zfcp_port_enqueue(adapter, acc->wwpn,
ZFCP_STATUS_COMMON_NOESC, d_id);
@@ -637,7 +635,8 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter)
max_entries = chain ? ZFCP_GPN_FT_MAX_ENTRIES : ZFCP_GPN_FT_ENTRIES;
max_bytes = chain ? ZFCP_GPN_FT_MAX_SIZE : ZFCP_CT_SIZE_ONE_PAGE;
- if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT)
+ if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT &&
+ fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV)
return 0;
ret = zfcp_wka_port_get(&adapter->nsp);
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index b29f3121b666..74dee32afba8 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -172,12 +172,16 @@ static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id,
struct fsf_link_down_info *link_down)
{
struct zfcp_adapter *adapter = req->adapter;
+ unsigned long flags;
if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED)
return;
atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
+
+ read_lock_irqsave(&zfcp_data.config_lock, flags);
zfcp_scsi_schedule_rports_block(adapter);
+ read_unlock_irqrestore(&zfcp_data.config_lock, flags);
if (!link_down)
goto out;
@@ -645,30 +649,30 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req)
}
}
-static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter)
- __releases(&adapter->req_q_lock)
- __acquires(&adapter->req_q_lock)
+static int zfcp_fsf_sbal_check(struct zfcp_adapter *adapter)
{
struct zfcp_qdio_queue *req_q = &adapter->req_q;
- long ret;
- if (atomic_read(&req_q->count) <= -REQUEST_LIST_SIZE)
- return -EIO;
- if (atomic_read(&req_q->count) > 0)
- return 0;
+ spin_lock_bh(&adapter->req_q_lock);
+ if (atomic_read(&req_q->count))
+ return 1;
+ spin_unlock_bh(&adapter->req_q_lock);
+ return 0;
+}
+
+static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter)
+{
+ long ret;
- atomic_dec(&req_q->count);
spin_unlock_bh(&adapter->req_q_lock);
ret = wait_event_interruptible_timeout(adapter->request_wq,
- atomic_read(&req_q->count) >= 0,
- 5 * HZ);
- spin_lock_bh(&adapter->req_q_lock);
- atomic_inc(&req_q->count);
-
+ zfcp_fsf_sbal_check(adapter), 5 * HZ);
if (ret > 0)
return 0;
if (!ret)
atomic_inc(&adapter->qdio_outb_full);
+
+ spin_lock_bh(&adapter->req_q_lock);
return -EIO;
}
@@ -766,8 +770,9 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter,
static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
{
struct zfcp_adapter *adapter = req->adapter;
- unsigned long flags;
- int idx;
+ unsigned long flags;
+ int idx;
+ int with_qtcb = (req->qtcb != NULL);
/* put allocated FSF request into hash table */
spin_lock_irqsave(&adapter->req_list_lock, flags);
@@ -789,7 +794,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
}
/* Don't increase for unsolicited status */
- if (req->qtcb)
+ if (with_qtcb)
adapter->fsf_req_seq_no++;
adapter->req_no++;
@@ -1253,13 +1258,13 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter,
spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
- goto out;
+ goto out_unlock;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA,
0, NULL);
if (IS_ERR(req)) {
retval = PTR_ERR(req);
- goto out;
+ goto out_unlock;
}
sbale = zfcp_qdio_sbale_req(req);
@@ -1278,14 +1283,16 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter,
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req);
-out:
spin_unlock_bh(&adapter->req_q_lock);
if (!retval)
wait_event(req->completion_wq,
req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
zfcp_fsf_req_free(req);
+ return retval;
+out_unlock:
+ spin_unlock_bh(&adapter->req_q_lock);
return retval;
}
@@ -1352,13 +1359,13 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter,
spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
- goto out;
+ goto out_unlock;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 0,
NULL);
if (IS_ERR(req)) {
retval = PTR_ERR(req);
- goto out;
+ goto out_unlock;
}
if (data)
@@ -1371,14 +1378,18 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter,
req->handler = zfcp_fsf_exchange_port_data_handler;
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req);
-out:
spin_unlock_bh(&adapter->req_q_lock);
+
if (!retval)
wait_event(req->completion_wq,
req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
zfcp_fsf_req_free(req);
return retval;
+
+out_unlock:
+ spin_unlock_bh(&adapter->req_q_lock);
+ return retval;
}
static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
@@ -2472,8 +2483,6 @@ out:
static void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *req)
{
- if (req->qtcb->header.fsf_status != FSF_GOOD)
- req->status |= ZFCP_STATUS_FSFREQ_ERROR;
}
/**
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 58201e1ae478..e8fbeaeb5fbf 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -171,7 +171,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
write_unlock_irqrestore(&adapter->abort_lock, flags);
zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL,
old_req_id);
- return SUCCESS;
+ return FAILED; /* completion could be in progress */
}
old_req->data = NULL;
@@ -486,10 +486,12 @@ static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
*/
static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport)
{
- struct zfcp_port *port = rport->dd_data;
+ struct zfcp_port *port;
write_lock_irq(&zfcp_data.config_lock);
- port->rport = NULL;
+ port = rport->dd_data;
+ if (port)
+ port->rport = NULL;
write_unlock_irq(&zfcp_data.config_lock);
}
@@ -503,9 +505,18 @@ static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport)
*/
static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
{
- struct zfcp_port *port = rport->dd_data;
+ struct zfcp_port *port;
+
+ write_lock_irq(&zfcp_data.config_lock);
+ port = rport->dd_data;
+ if (port)
+ zfcp_port_get(port);
+ write_unlock_irq(&zfcp_data.config_lock);
- zfcp_erp_port_reopen(port, 0, "sctrpi1", NULL);
+ if (port) {
+ zfcp_erp_port_reopen(port, 0, "sctrpi1", NULL);
+ zfcp_port_put(port);
+ }
}
static void zfcp_scsi_rport_register(struct zfcp_port *port)
@@ -534,8 +545,10 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port)
static void zfcp_scsi_rport_block(struct zfcp_port *port)
{
- if (port->rport)
- fc_remote_port_delete(port->rport);
+ struct fc_rport *rport = port->rport;
+
+ if (rport)
+ fc_remote_port_delete(rport);
}
void zfcp_scsi_schedule_rport_register(struct zfcp_port *port)
@@ -583,6 +596,23 @@ void zfcp_scsi_rport_work(struct work_struct *work)
}
+void zfcp_scsi_scan(struct work_struct *work)
+{
+ struct zfcp_unit *unit = container_of(work, struct zfcp_unit,
+ scsi_work);
+ struct fc_rport *rport;
+
+ flush_work(&unit->port->rport_work);
+ rport = unit->port->rport;
+
+ if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
+ scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
+ scsilun_to_int((struct scsi_lun *)
+ &unit->fcp_lun), 0);
+
+ zfcp_unit_put(unit);
+}
+
struct fc_function_template zfcp_transport_functions = {
.show_starget_port_id = 1,
.show_starget_port_name = 1,
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
index 9a3b8e261c0a..3e51e64d1108 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -254,12 +254,21 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
write_lock_irq(&zfcp_data.config_lock);
unit = zfcp_get_unit_by_lun(port, fcp_lun);
- if (unit && (atomic_read(&unit->refcount) == 0)) {
- zfcp_unit_get(unit);
- atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
- list_move(&unit->list, &unit_remove_lh);
- } else
- unit = NULL;
+ if (unit) {
+ write_unlock_irq(&zfcp_data.config_lock);
+ /* wait for possible timeout during SCSI probe */
+ flush_work(&unit->scsi_work);
+ write_lock_irq(&zfcp_data.config_lock);
+
+ if (atomic_read(&unit->refcount) == 0) {
+ zfcp_unit_get(unit);
+ atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE,
+ &unit->status);
+ list_move(&unit->list, &unit_remove_lh);
+ } else {
+ unit = NULL;
+ }
+ }
write_unlock_irq(&zfcp_data.config_lock);
diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c
index e6d1fc8c54f1..09617884a50b 100644
--- a/drivers/sbus/char/jsflash.c
+++ b/drivers/sbus/char/jsflash.c
@@ -192,25 +192,25 @@ static void jsfd_do_request(struct request_queue *q)
size_t len = req->current_nr_sectors << 9;
if ((offset + len) > jdp->dsize) {
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
continue;
}
if (rq_data_dir(req) != READ) {
printk(KERN_ERR "jsfd: write\n");
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
continue;
}
if ((jdp->dbase & 0xff000000) != 0x20000000) {
printk(KERN_ERR "jsfd: bad base %x\n", (int)jdp->dbase);
- end_request(req, 0);
+ __blk_end_request_cur(req, -EIO);
continue;
}
jsfd_read(req->buffer, jdp->dbase + offset, len);
- end_request(req, 1);
+ __blk_end_request_cur(req, 0);
}
}
@@ -383,18 +383,22 @@ static int jsf_ioctl_program(void __user *arg)
return 0;
}
-static int jsf_ioctl(struct inode *inode, struct file *f, unsigned int cmd,
- unsigned long arg)
+static long jsf_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
{
+ lock_kernel();
int error = -ENOTTY;
void __user *argp = (void __user *)arg;
- if (!capable(CAP_SYS_ADMIN))
+ if (!capable(CAP_SYS_ADMIN)) {
+ unlock_kernel();
return -EPERM;
+ }
switch (cmd) {
case JSFLASH_IDENT:
- if (copy_to_user(argp, &jsf0.id, JSFIDSZ))
+ if (copy_to_user(argp, &jsf0.id, JSFIDSZ)) {
+ unlock_kernel();
return -EFAULT;
+ }
break;
case JSFLASH_ERASE:
error = jsf_ioctl_erase(arg);
@@ -404,6 +408,7 @@ static int jsf_ioctl(struct inode *inode, struct file *f, unsigned int cmd,
break;
}
+ unlock_kernel();
return error;
}
@@ -439,7 +444,7 @@ static const struct file_operations jsf_fops = {
.llseek = jsf_lseek,
.read = jsf_read,
.write = jsf_write,
- .ioctl = jsf_ioctl,
+ .unlocked_ioctl = jsf_ioctl,
.mmap = jsf_mmap,
.open = jsf_open,
.release = jsf_release,
diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c
index 27993c37775d..2c56fd56ec63 100644
--- a/drivers/sbus/char/uctrl.c
+++ b/drivers/sbus/char/uctrl.c
@@ -197,9 +197,8 @@ static struct uctrl_driver {
static void uctrl_get_event_status(struct uctrl_driver *);
static void uctrl_get_external_status(struct uctrl_driver *);
-static int
-uctrl_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long
+uctrl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
switch (cmd) {
default:
@@ -226,7 +225,7 @@ static irqreturn_t uctrl_interrupt(int irq, void *dev_id)
static const struct file_operations uctrl_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
- .ioctl = uctrl_ioctl,
+ .unlocked_ioctl = uctrl_ioctl,
.open = uctrl_open,
};
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index fdb14ec4fd47..8b7983aba8f7 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -2234,10 +2234,10 @@ static int twa_resume(struct pci_dev *pdev)
pci_set_master(pdev);
pci_try_set_mwi(pdev);
- if (pci_set_dma_mask(pdev, DMA_64BIT_MASK)
- || pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
- if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)
- || pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
+ if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
+ || pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)))
+ if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
+ || pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
TW_PRINTK(host, TW_DRIVER, 0x40, "Failed to set dma mask during resume");
retval = -ENODEV;
goto out_disable_device;
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 8ed2990c826e..c915e5c31b8c 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -508,6 +508,7 @@ config SCSI_AIC7XXX_OLD
source "drivers/scsi/aic7xxx/Kconfig.aic79xx"
source "drivers/scsi/aic94xx/Kconfig"
+source "drivers/scsi/mvsas/Kconfig"
config SCSI_DPT_I2O
tristate "Adaptec I2O RAID support "
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index e7c861ac417d..56007f66fa50 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -125,7 +125,7 @@ obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvscsi/
obj-$(CONFIG_SCSI_IBMVFC) += ibmvscsi/
obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o
obj-$(CONFIG_SCSI_STEX) += stex.o
-obj-$(CONFIG_SCSI_MVSAS) += mvsas.o
+obj-$(CONFIG_SCSI_MVSAS) += mvsas/
obj-$(CONFIG_PS3_ROM) += ps3rom.o
obj-$(CONFIG_SCSI_CXGB3_ISCSI) += libiscsi.o libiscsi_tcp.o cxgb3i/
diff --git a/drivers/scsi/a4000t.c b/drivers/scsi/a4000t.c
index 61af3d91ac8a..e3519fa5a3ba 100644
--- a/drivers/scsi/a4000t.c
+++ b/drivers/scsi/a4000t.c
@@ -129,7 +129,7 @@ static int __init a4000t_scsi_init(void)
a4000t_scsi_device = platform_device_register_simple("a4000t-scsi",
-1, NULL, 0);
if (IS_ERR(a4000t_scsi_device)) {
- platform_driver_register(&a4000t_scsi_driver);
+ platform_driver_unregister(&a4000t_scsi_driver);
return PTR_ERR(a4000t_scsi_device);
}
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 280261c451d6..2a889853a106 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -1378,7 +1378,7 @@ int aac_get_adapter_info(struct aac_dev* dev)
if (dev->nondasd_support && !dev->in_reset)
printk(KERN_INFO "%s%d: Non-DASD support enabled.\n",dev->name, dev->id);
- if (dma_get_required_mask(&dev->pdev->dev) > DMA_32BIT_MASK)
+ if (dma_get_required_mask(&dev->pdev->dev) > DMA_BIT_MASK(32))
dev->needs_dac = 1;
dev->dac_support = 0;
if ((sizeof(dma_addr_t) > 4) && dev->needs_dac &&
diff --git a/drivers/scsi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgb3i/cxgb3i.h
index d362860e7504..59b0958d2d11 100644
--- a/drivers/scsi/cxgb3i/cxgb3i.h
+++ b/drivers/scsi/cxgb3i/cxgb3i.h
@@ -34,7 +34,7 @@
#include "cxgb3i_offload.h"
#include "cxgb3i_ddp.h"
-#define CXGB3I_SCSI_QDEPTH_DFLT 128
+#define CXGB3I_SCSI_HOST_QDEPTH 1024
#define CXGB3I_MAX_TARGET CXGB3I_MAX_CONN
#define CXGB3I_MAX_LUN 512
#define ISCSI_PDU_NONPAYLOAD_MAX \
diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.c b/drivers/scsi/cxgb3i/cxgb3i_ddp.c
index d06a661c209f..99c912547902 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_ddp.c
+++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.c
@@ -120,20 +120,26 @@ static void clear_ddp_map(struct cxgb3i_ddp_info *ddp, unsigned int tag,
}
static inline int ddp_find_unused_entries(struct cxgb3i_ddp_info *ddp,
- int start, int max, int count,
+ unsigned int start, unsigned int max,
+ unsigned int count,
struct cxgb3i_gather_list *gl)
{
- unsigned int i, j;
+ unsigned int i, j, k;
+ /* not enough entries */
+ if ((max - start) < count)
+ return -EBUSY;
+
+ max -= count;
spin_lock(&ddp->map_lock);
- for (i = start; i <= max;) {
- for (j = 0; j < count; j++) {
- if (ddp->gl_map[i + j])
+ for (i = start; i < max;) {
+ for (j = 0, k = i; j < count; j++, k++) {
+ if (ddp->gl_map[k])
break;
}
if (j == count) {
- for (j = 0; j < count; j++)
- ddp->gl_map[i + j] = gl;
+ for (j = 0, k = i; j < count; j++, k++)
+ ddp->gl_map[k] = gl;
spin_unlock(&ddp->map_lock);
return i;
}
@@ -354,7 +360,7 @@ int cxgb3i_ddp_tag_reserve(struct t3cdev *tdev, unsigned int tid,
struct cxgb3i_ddp_info *ddp = tdev->ulp_iscsi;
struct pagepod_hdr hdr;
unsigned int npods;
- int idx = -1, idx_max;
+ int idx = -1;
int err = -ENOMEM;
u32 sw_tag = *tagp;
u32 tag;
@@ -367,17 +373,17 @@ int cxgb3i_ddp_tag_reserve(struct t3cdev *tdev, unsigned int tid,
}
npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT;
- idx_max = ddp->nppods - npods + 1;
if (ddp->idx_last == ddp->nppods)
- idx = ddp_find_unused_entries(ddp, 0, idx_max, npods, gl);
+ idx = ddp_find_unused_entries(ddp, 0, ddp->nppods, npods, gl);
else {
idx = ddp_find_unused_entries(ddp, ddp->idx_last + 1,
- idx_max, npods, gl);
- if (idx < 0 && ddp->idx_last >= npods)
+ ddp->nppods, npods, gl);
+ if (idx < 0 && ddp->idx_last >= npods) {
idx = ddp_find_unused_entries(ddp, 0,
- ddp->idx_last - npods + 1,
+ min(ddp->idx_last + npods, ddp->nppods),
npods, gl);
+ }
}
if (idx < 0) {
ddp_log_debug("xferlen %u, gl %u, npods %u NO DDP.\n",
diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
index fff8e4327644..9212400b9b13 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
@@ -876,13 +876,14 @@ static struct scsi_host_template cxgb3i_host_template = {
.proc_name = "cxgb3i",
.queuecommand = iscsi_queuecommand,
.change_queue_depth = iscsi_change_queue_depth,
- .can_queue = CXGB3I_SCSI_QDEPTH_DFLT - 1,
+ .can_queue = CXGB3I_SCSI_HOST_QDEPTH,
.sg_tablesize = SG_ALL,
.max_sectors = 0xFFFF,
- .cmd_per_lun = CXGB3I_SCSI_QDEPTH_DFLT,
+ .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
.eh_abort_handler = iscsi_eh_abort,
.eh_device_reset_handler = iscsi_eh_device_reset,
.eh_target_reset_handler = iscsi_eh_target_reset,
+ .target_alloc = iscsi_target_alloc,
.use_clustering = DISABLE_CLUSTERING,
.this_id = -1,
};
diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.c b/drivers/scsi/cxgb3i/cxgb3i_offload.c
index 4d8654cdbdae..e11c9c180f39 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_offload.c
+++ b/drivers/scsi/cxgb3i/cxgb3i_offload.c
@@ -1737,7 +1737,7 @@ int cxgb3i_c3cn_send_pdus(struct s3_conn *c3cn, struct sk_buff *skb)
c3cn_tx_debug("c3cn 0x%p, snd %u - %u > %u.\n",
c3cn, c3cn->write_seq, c3cn->snd_una,
cxgb3_snd_win);
- err = -EAGAIN;
+ err = -ENOBUFS;
goto out_err;
}
@@ -1775,6 +1775,8 @@ done:
out_err:
if (copied == 0 && err == -EPIPE)
copied = c3cn->err ? c3cn->err : -EPIPE;
+ else
+ copied = err;
goto done;
}
diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.c b/drivers/scsi/cxgb3i/cxgb3i_pdu.c
index 7eebc9a7cb35..709105071177 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_pdu.c
+++ b/drivers/scsi/cxgb3i/cxgb3i_pdu.c
@@ -400,17 +400,18 @@ int cxgb3i_conn_xmit_pdu(struct iscsi_task *task)
return 0;
}
- if (err < 0 && err != -EAGAIN) {
- kfree_skb(skb);
- cxgb3i_tx_debug("itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
- task->itt, skb, skb->len, skb->data_len, err);
- iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
- iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
+ if (err == -EAGAIN || err == -ENOBUFS) {
+ /* reset skb to send when we are called again */
+ tdata->skb = skb;
return err;
}
- /* reset skb to send when we are called again */
- tdata->skb = skb;
- return -EAGAIN;
+
+ kfree_skb(skb);
+ cxgb3i_tx_debug("itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
+ task->itt, skb, skb->len, skb->data_len, err);
+ iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
+ iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
+ return err;
}
int cxgb3i_pdu_init(void)
diff --git a/drivers/scsi/dpt/osd_util.h b/drivers/scsi/dpt/osd_util.h
index 4b56c0436ba2..b2613c2eaac7 100644
--- a/drivers/scsi/dpt/osd_util.h
+++ b/drivers/scsi/dpt/osd_util.h
@@ -342,7 +342,7 @@ uLONG osdGetThreadID(void);
/* wakes up the specifed thread */
void osdWakeThread(uLONG);
-/* osd sleep for x miliseconds */
+/* osd sleep for x milliseconds */
void osdSleep(uLONG);
#define DPT_THREAD_PRIORITY_LOWEST 0x00
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 94e1e3189773..03e1926f40b5 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -57,7 +57,7 @@ DEFINE_RWLOCK(fcoe_hostlist_lock);
DEFINE_TIMER(fcoe_timer, NULL, 0, 0);
DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu);
-/* Function Prototyes */
+/* Function Prototypes */
static int fcoe_reset(struct Scsi_Host *shost);
static int fcoe_xmit(struct fc_lport *, struct fc_frame *);
static int fcoe_rcv(struct sk_buff *, struct net_device *,
@@ -138,7 +138,6 @@ static struct scsi_host_template fcoe_shost_template = {
/**
* fcoe_lport_config() - sets up the fc_lport
* @lp: ptr to the fc_lport
- * @shost: ptr to the parent scsi host
*
* Returns: 0 for success
*/
@@ -256,6 +255,7 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
rtnl_lock();
memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
dev_unicast_add(fc->real_dev, flogi_maddr, ETH_ALEN);
+ dev_mc_add(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
rtnl_unlock();
/*
@@ -380,7 +380,7 @@ static int fcoe_if_destroy(struct net_device *netdev)
dev_mc_delete(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
rtnl_unlock();
- /* Free the per-CPU revieve threads */
+ /* Free the per-CPU receive threads */
fcoe_percpu_clean(lp);
/* Free existing skbs */
@@ -720,7 +720,7 @@ static void fcoe_percpu_thread_destroy(unsigned int cpu)
}
#else
/*
- * This a non-SMP scenario where the singluar Rx thread is
+ * This a non-SMP scenario where the singular Rx thread is
* being removed. Free all skbs and stop the thread.
*/
spin_lock_bh(&p->fcoe_rx_list.lock);
@@ -777,7 +777,7 @@ static struct notifier_block fcoe_cpu_notifier = {
* @skb: the receive skb
* @dev: associated net device
* @ptype: context
- * @odldev: last device
+ * @olddev: last device
*
* this function will receive the packet and build fc frame and pass it up
*
@@ -884,7 +884,6 @@ err2:
kfree_skb(skb);
return -1;
}
-EXPORT_SYMBOL_GPL(fcoe_rcv);
/**
* fcoe_start_io() - pass to netdev to start xmit for fcoe
@@ -905,7 +904,7 @@ static inline int fcoe_start_io(struct sk_buff *skb)
}
/**
- * fcoe_get_paged_crc_eof() - in case we need alloc a page for crc_eof
+ * fcoe_get_paged_crc_eof() - in case we need to alloc a page for crc_eof
* @skb: the skb to be xmitted
* @tlen: total len
*
@@ -947,7 +946,7 @@ static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen)
/**
* fcoe_fc_crc() - calculates FC CRC in this fcoe skb
- * @fp: the fc_frame containg data to be checksummed
+ * @fp: the fc_frame containing data to be checksummed
*
* This uses crc32() to calculate the crc for fc frame
* Return : 32 bit crc
@@ -1011,7 +1010,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
wlen = skb->len / FCOE_WORD_TO_BYTE;
if (!lp->link_up) {
- kfree(skb);
+ kfree_skb(skb);
return 0;
}
@@ -1062,7 +1061,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
cp = NULL;
}
- /* adjust skb netowrk/transport offsets to match mac/fcoe/fc */
+ /* adjust skb network/transport offsets to match mac/fcoe/fc */
skb_push(skb, elen + hlen);
skb_reset_mac_header(skb);
skb_reset_network_header(skb);
@@ -1123,7 +1122,6 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
return 0;
}
-EXPORT_SYMBOL_GPL(fcoe_xmit);
/**
* fcoe_percpu_receive_thread() - recv thread per cpu
@@ -1296,17 +1294,16 @@ void fcoe_watchdog(ulong vp)
/**
- * fcoe_check_wait_queue() - put the skb into fcoe pending xmit queue
- * @lp: the fc_port for this skb
- * @skb: the associated skb to be xmitted
+ * fcoe_check_wait_queue() - attempt to clear the transmit backlog
+ * @lp: the fc_lport
*
* This empties the wait_queue, dequeue the head of the wait_queue queue
* and calls fcoe_start_io() for each packet, if all skb have been
* transmitted, return qlen or -1 if a error occurs, then restore
- * wait_queue and try again later.
+ * wait_queue and try again later.
*
* The wait_queue is used when the skb transmit fails. skb will go
- * in the wait_queue which will be emptied by the time function OR
+ * in the wait_queue which will be emptied by the timer function or
* by the next skb transmit.
*
* Returns: 0 for success
@@ -1355,10 +1352,6 @@ out:
*/
static void fcoe_dev_setup()
{
- /*
- * here setup a interface specific wd time to
- * monitor the link state
- */
register_netdevice_notifier(&fcoe_notifier);
}
@@ -1437,10 +1430,9 @@ out:
/**
* fcoe_if_to_netdev() - parse a name buffer to get netdev
- * @ifname: fixed array for output parsed ifname
* @buffer: incoming buffer to be copied
*
- * Returns: NULL or ptr to netdeive
+ * Returns: NULL or ptr to net_device
*/
static struct net_device *fcoe_if_to_netdev(const char *buffer)
{
@@ -1458,7 +1450,7 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer)
}
/**
- * fcoe_netdev_to_module_owner() - finds out the nic drive moddule of the netdev
+ * fcoe_netdev_to_module_owner() - finds out the driver module of the netdev
* @netdev: the target netdev
*
* Returns: ptr to the struct module, NULL for failure
@@ -1488,7 +1480,7 @@ fcoe_netdev_to_module_owner(const struct net_device *netdev)
* Holds the Ethernet driver module by try_module_get() for
* the corresponding netdev.
*
- * Returns: 0 for succsss
+ * Returns: 0 for success
*/
static int fcoe_ethdrv_get(const struct net_device *netdev)
{
@@ -1510,7 +1502,7 @@ static int fcoe_ethdrv_get(const struct net_device *netdev)
* Releases the Ethernet driver module by module_put for
* the corresponding netdev.
*
- * Returns: 0 for succsss
+ * Returns: 0 for success
*/
static int fcoe_ethdrv_put(const struct net_device *netdev)
{
@@ -1528,7 +1520,7 @@ static int fcoe_ethdrv_put(const struct net_device *netdev)
/**
* fcoe_destroy() - handles the destroy from sysfs
- * @buffer: expcted to be a eth if name
+ * @buffer: expected to be an eth if name
* @kp: associated kernel param
*
* Returns: 0 for success
@@ -1565,7 +1557,7 @@ out_nodev:
/**
* fcoe_create() - Handles the create call from sysfs
- * @buffer: expcted to be a eth if name
+ * @buffer: expected to be an eth if name
* @kp: associated kernel param
*
* Returns: 0 for success
@@ -1652,7 +1644,6 @@ int fcoe_link_ok(struct fc_lport *lp)
return rc;
}
-EXPORT_SYMBOL_GPL(fcoe_link_ok);
/**
* fcoe_percpu_clean() - Clear the pending skbs for an lport
@@ -1684,7 +1675,6 @@ void fcoe_percpu_clean(struct fc_lport *lp)
spin_unlock_bh(&pp->fcoe_rx_list.lock);
}
}
-EXPORT_SYMBOL_GPL(fcoe_percpu_clean);
/**
* fcoe_clean_pending_queue() - Dequeue a skb and free it
@@ -1705,7 +1695,6 @@ void fcoe_clean_pending_queue(struct fc_lport *lp)
}
spin_unlock_bh(&fc->fcoe_pending_queue.lock);
}
-EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue);
/**
* fcoe_reset() - Resets the fcoe
@@ -1719,11 +1708,10 @@ int fcoe_reset(struct Scsi_Host *shost)
fc_lport_reset(lport);
return 0;
}
-EXPORT_SYMBOL_GPL(fcoe_reset);
/**
* fcoe_hostlist_lookup_softc() - find the corresponding lport by a given device
- * @device: this is currently ptr to net_device
+ * @dev: this is currently ptr to net_device
*
* Returns: NULL or the located fcoe_softc
*/
@@ -1757,11 +1745,10 @@ struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev)
return (fc) ? fc->ctlr.lp : NULL;
}
-EXPORT_SYMBOL_GPL(fcoe_hostlist_lookup);
/**
* fcoe_hostlist_add() - Add a lport to lports list
- * @lp: ptr to the fc_lport to badded
+ * @lp: ptr to the fc_lport to be added
*
* Returns: 0 for success
*/
@@ -1778,11 +1765,10 @@ int fcoe_hostlist_add(const struct fc_lport *lp)
}
return 0;
}
-EXPORT_SYMBOL_GPL(fcoe_hostlist_add);
/**
* fcoe_hostlist_remove() - remove a lport from lports list
- * @lp: ptr to the fc_lport to badded
+ * @lp: ptr to the fc_lport to be removed
*
* Returns: 0 for success
*/
@@ -1798,7 +1784,6 @@ int fcoe_hostlist_remove(const struct fc_lport *lp)
return 0;
}
-EXPORT_SYMBOL_GPL(fcoe_hostlist_remove);
/**
* fcoe_init() - fcoe module loading initialization
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index f410f4abb548..62ba0f39c6bd 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -122,7 +122,7 @@ static void fcoe_ctlr_reset_fcfs(struct fcoe_ctlr *fip)
}
/**
- * fcoe_ctrl_destroy() - Disable and tear-down the FCoE controller.
+ * fcoe_ctlr_destroy() - Disable and tear-down the FCoE controller.
* @fip: FCoE controller.
*
* This is called by FCoE drivers before freeing the &fcoe_ctlr.
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index c09d77591f92..dd689ded8609 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -3654,6 +3654,7 @@ static int ipr_slave_configure(struct scsi_device *sdev)
{
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *) sdev->host->hostdata;
struct ipr_resource_entry *res;
+ struct ata_port *ap = NULL;
unsigned long lock_flags = 0;
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
@@ -3672,12 +3673,16 @@ static int ipr_slave_configure(struct scsi_device *sdev)
}
if (ipr_is_vset_device(res) || ipr_is_scsi_disk(res))
sdev->allow_restart = 1;
- if (ipr_is_gata(res) && res->sata_port) {
+ if (ipr_is_gata(res) && res->sata_port)
+ ap = res->sata_port->ap;
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+
+ if (ap) {
scsi_adjust_queue_depth(sdev, 0, IPR_MAX_CMD_PER_ATA_LUN);
- ata_sas_slave_configure(sdev, res->sata_port->ap);
- } else {
+ ata_sas_slave_configure(sdev, ap);
+ } else
scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
- }
+ return 0;
}
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
return 0;
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index b3e5e08e44ab..b7c092d63bbe 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -463,7 +463,7 @@ static int iscsi_sw_tcp_pdu_init(struct iscsi_task *task,
}
if (err) {
- iscsi_conn_failure(conn, err);
+ /* got invalid offset/len */
return -EIO;
}
return 0;
@@ -851,6 +851,7 @@ static struct scsi_host_template iscsi_sw_tcp_sht = {
.use_clustering = DISABLE_CLUSTERING,
.slave_alloc = iscsi_sw_tcp_slave_alloc,
.slave_configure = iscsi_sw_tcp_slave_configure,
+ .target_alloc = iscsi_target_alloc,
.proc_name = "iscsi_tcp",
.this_id = -1,
};
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index e57556ea5b48..4c880656990b 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -113,6 +113,11 @@ void fc_disc_stop_rports(struct fc_disc *disc)
lport->tt.rport_logoff(rport);
}
+ list_for_each_entry_safe(rdata, next, &disc->rogue_rports, peers) {
+ rport = PRIV_TO_RPORT(rdata);
+ lport->tt.rport_logoff(rport);
+ }
+
mutex_unlock(&disc->disc_mutex);
}
@@ -131,23 +136,32 @@ static void fc_disc_rport_callback(struct fc_lport *lport,
{
struct fc_rport_libfc_priv *rdata = rport->dd_data;
struct fc_disc *disc = &lport->disc;
- int found = 0;
FC_DEBUG_DISC("Received a %d event for port (%6x)\n", event,
rport->port_id);
- if (event == RPORT_EV_CREATED) {
+ switch (event) {
+ case RPORT_EV_CREATED:
if (disc) {
- found = 1;
mutex_lock(&disc->disc_mutex);
list_add_tail(&rdata->peers, &disc->rports);
mutex_unlock(&disc->disc_mutex);
}
+ break;
+ case RPORT_EV_LOGO:
+ case RPORT_EV_FAILED:
+ case RPORT_EV_STOP:
+ mutex_lock(&disc->disc_mutex);
+ mutex_lock(&rdata->rp_mutex);
+ if (rdata->trans_state == FC_PORTSTATE_ROGUE)
+ list_del(&rdata->peers);
+ mutex_unlock(&rdata->rp_mutex);
+ mutex_unlock(&disc->disc_mutex);
+ break;
+ default:
+ break;
}
- if (!found)
- FC_DEBUG_DISC("The rport (%6x) is not maintained "
- "by the discovery layer\n", rport->port_id);
}
/**
@@ -439,6 +453,7 @@ static int fc_disc_new_target(struct fc_disc *disc,
rdata = rport->dd_data;
rdata->ops = &fc_disc_rport_ops;
rdata->rp_state = RPORT_ST_INIT;
+ list_add_tail(&rdata->peers, &disc->rogue_rports);
lport->tt.rport_login(rport);
}
}
@@ -461,21 +476,29 @@ static void fc_disc_del_target(struct fc_disc *disc, struct fc_rport *rport)
/**
* fc_disc_done() - Discovery has been completed
* @disc: FC discovery context
+ * Locking Note: This function expects that the disc mutex is locked before
+ * it is called. The discovery callback is then made with the lock released,
+ * and the lock is re-taken before returning from this function
*/
static void fc_disc_done(struct fc_disc *disc)
{
struct fc_lport *lport = disc->lport;
+ enum fc_disc_event event;
FC_DEBUG_DISC("Discovery complete for port (%6x)\n",
fc_host_port_id(lport->host));
- disc->disc_callback(lport, disc->event);
+ event = disc->event;
disc->event = DISC_EV_NONE;
if (disc->requested)
fc_disc_gpn_ft_req(disc);
else
disc->pending = 0;
+
+ mutex_unlock(&disc->disc_mutex);
+ disc->disc_callback(lport, event);
+ mutex_lock(&disc->disc_mutex);
}
/**
@@ -622,6 +645,8 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
rdata = rport->dd_data;
rdata->ops = &fc_disc_rport_ops;
rdata->local_port = lport;
+ list_add_tail(&rdata->peers,
+ &disc->rogue_rports);
lport->tt.rport_login(rport);
} else
FC_DBG("Failed to allocate memory for "
@@ -681,8 +706,8 @@ static void fc_disc_timeout(struct work_struct *work)
* @fp: response frame
* @lp_arg: Fibre Channel host port instance
*
- * Locking Note: This function expects that the disc_mutex is locked
- * before it is called.
+ * Locking Note: This function is called without disc mutex held, and
+ * should do all its processing with the mutex held
*/
static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
void *disc_arg)
@@ -695,11 +720,13 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
unsigned int len;
int error;
+ mutex_lock(&disc->disc_mutex);
FC_DEBUG_DISC("Received a GPN_FT response on port (%6x)\n",
fc_host_port_id(disc->lport->host));
if (IS_ERR(fp)) {
fc_disc_error(disc, fp);
+ mutex_unlock(&disc->disc_mutex);
return;
}
@@ -744,6 +771,8 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
disc->seq_count++;
}
fc_frame_free(fp);
+
+ mutex_unlock(&disc->disc_mutex);
}
/**
@@ -757,7 +786,6 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp)
{
struct fc_lport *lport;
- struct fc_rport *rport;
struct fc_rport *new_rport;
struct fc_rport_libfc_priv *rdata;
@@ -766,15 +794,12 @@ static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp)
if (dp->ids.port_id == fc_host_port_id(lport->host))
goto out;
- rport = lport->tt.rport_lookup(lport, dp->ids.port_id);
- if (rport)
- fc_disc_del_target(disc, rport);
-
new_rport = lport->tt.rport_create(dp);
if (new_rport) {
rdata = new_rport->dd_data;
rdata->ops = &fc_disc_rport_ops;
kfree(dp);
+ list_add_tail(&rdata->peers, &disc->rogue_rports);
lport->tt.rport_login(new_rport);
}
return;
@@ -836,6 +861,7 @@ int fc_disc_init(struct fc_lport *lport)
INIT_DELAYED_WORK(&disc->disc_work, fc_disc_timeout);
mutex_init(&disc->disc_mutex);
INIT_LIST_HEAD(&disc->rports);
+ INIT_LIST_HEAD(&disc->rogue_rports);
disc->lport = lport;
disc->delay = FC_DISC_DELAY;
diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c
index dd47fe619d1e..5878b34bff18 100644
--- a/drivers/scsi/libfc/fc_elsct.c
+++ b/drivers/scsi/libfc/fc_elsct.c
@@ -41,7 +41,7 @@ static struct fc_seq *fc_elsct_send(struct fc_lport *lport,
void *arg, u32 timer_msec)
{
enum fc_rctl r_ctl;
- u32 did;
+ u32 did = FC_FID_NONE;
enum fc_fh_type fh_type;
int rc;
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index f555ae99ad40..521f996f9b13 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -713,7 +713,7 @@ done:
static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg)
{
struct fc_fcp_pkt *fsp = (struct fc_fcp_pkt *)arg;
- struct fc_lport *lp;
+ struct fc_lport *lport = fsp->lp;
struct fc_frame_header *fh;
struct fcp_txrdy *dd;
u8 r_ctl;
@@ -724,9 +724,8 @@ static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg)
fh = fc_frame_header_get(fp);
r_ctl = fh->fh_r_ctl;
- lp = fsp->lp;
- if (!(lp->state & LPORT_ST_READY))
+ if (!(lport->state & LPORT_ST_READY))
goto out;
if (fc_fcp_lock_pkt(fsp))
goto out;
@@ -779,7 +778,7 @@ errout:
if (IS_ERR(fp))
fc_fcp_error(fsp, fp);
else if (rc == -ENOMEM)
- fc_fcp_reduce_can_queue(lp);
+ fc_fcp_reduce_can_queue(lport);
}
static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index b8178ef398d7..e0c247724d2b 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -618,6 +618,11 @@ int fc_fabric_logoff(struct fc_lport *lport)
{
lport->tt.disc_stop_final(lport);
mutex_lock(&lport->lp_mutex);
+ if (lport->dns_rp)
+ lport->tt.rport_logoff(lport->dns_rp);
+ mutex_unlock(&lport->lp_mutex);
+ lport->tt.rport_flush_queue();
+ mutex_lock(&lport->lp_mutex);
fc_lport_enter_logo(lport);
mutex_unlock(&lport->lp_mutex);
cancel_delayed_work_sync(&lport->retry_work);
@@ -639,7 +644,12 @@ EXPORT_SYMBOL(fc_fabric_logoff);
*/
int fc_lport_destroy(struct fc_lport *lport)
{
+ mutex_lock(&lport->lp_mutex);
+ lport->state = LPORT_ST_NONE;
+ lport->link_up = 0;
lport->tt.frame_send = fc_frame_drop;
+ mutex_unlock(&lport->lp_mutex);
+
lport->tt.fcp_abort_io(lport);
lport->tt.exch_mgr_reset(lport, 0, 0);
return 0;
@@ -1032,17 +1042,19 @@ static void fc_lport_rft_id_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_LPORT("Received a RFT_ID response\n");
- if (IS_ERR(fp)) {
- fc_lport_error(lport, fp);
- goto err;
- }
-
if (lport->state != LPORT_ST_RFT_ID) {
FC_DBG("Received a RFT_ID response, but in state %s\n",
fc_lport_state(lport));
+ if (IS_ERR(fp))
+ goto err;
goto out;
}
+ if (IS_ERR(fp)) {
+ fc_lport_error(lport, fp);
+ goto err;
+ }
+
fh = fc_frame_header_get(fp);
ct = fc_frame_payload_get(fp, sizeof(*ct));
@@ -1084,17 +1096,19 @@ static void fc_lport_rpn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_LPORT("Received a RPN_ID response\n");
- if (IS_ERR(fp)) {
- fc_lport_error(lport, fp);
- goto err;
- }
-
if (lport->state != LPORT_ST_RPN_ID) {
FC_DBG("Received a RPN_ID response, but in state %s\n",
fc_lport_state(lport));
+ if (IS_ERR(fp))
+ goto err;
goto out;
}
+ if (IS_ERR(fp)) {
+ fc_lport_error(lport, fp);
+ goto err;
+ }
+
fh = fc_frame_header_get(fp);
ct = fc_frame_payload_get(fp, sizeof(*ct));
if (fh && ct && fh->fh_type == FC_TYPE_CT &&
@@ -1134,17 +1148,19 @@ static void fc_lport_scr_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_LPORT("Received a SCR response\n");
- if (IS_ERR(fp)) {
- fc_lport_error(lport, fp);
- goto err;
- }
-
if (lport->state != LPORT_ST_SCR) {
FC_DBG("Received a SCR response, but in state %s\n",
fc_lport_state(lport));
+ if (IS_ERR(fp))
+ goto err;
goto out;
}
+ if (IS_ERR(fp)) {
+ fc_lport_error(lport, fp);
+ goto err;
+ }
+
op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC)
fc_lport_enter_ready(lport);
@@ -1360,17 +1376,19 @@ static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_LPORT("Received a LOGO response\n");
- if (IS_ERR(fp)) {
- fc_lport_error(lport, fp);
- goto err;
- }
-
if (lport->state != LPORT_ST_LOGO) {
FC_DBG("Received a LOGO response, but in state %s\n",
fc_lport_state(lport));
+ if (IS_ERR(fp))
+ goto err;
goto out;
}
+ if (IS_ERR(fp)) {
+ fc_lport_error(lport, fp);
+ goto err;
+ }
+
op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC)
fc_lport_enter_reset(lport);
@@ -1400,10 +1418,6 @@ static void fc_lport_enter_logo(struct fc_lport *lport)
fc_lport_state_enter(lport, LPORT_ST_LOGO);
- /* DNS session should be closed so we can release it here */
- if (lport->dns_rp)
- lport->tt.rport_logoff(lport->dns_rp);
-
fp = fc_frame_alloc(lport, sizeof(*logo));
if (!fp) {
fc_lport_error(lport, fp);
@@ -1444,17 +1458,19 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_LPORT("Received a FLOGI response\n");
- if (IS_ERR(fp)) {
- fc_lport_error(lport, fp);
- goto err;
- }
-
if (lport->state != LPORT_ST_FLOGI) {
FC_DBG("Received a FLOGI response, but in state %s\n",
fc_lport_state(lport));
+ if (IS_ERR(fp))
+ goto err;
goto out;
}
+ if (IS_ERR(fp)) {
+ fc_lport_error(lport, fp);
+ goto err;
+ }
+
fh = fc_frame_header_get(fp);
did = ntoh24(fh->fh_d_id);
if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) {
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 0472bb73221e..747d73c5c8af 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -267,6 +267,10 @@ static void fc_rport_work(struct work_struct *work)
"(%6x).\n", ids.port_id);
event = RPORT_EV_FAILED;
}
+ if (rport->port_id != FC_FID_DIR_SERV)
+ if (rport_ops->event_callback)
+ rport_ops->event_callback(lport, rport,
+ RPORT_EV_FAILED);
put_device(&rport->dev);
rport = new_rport;
rdata = new_rport->dd_data;
@@ -325,11 +329,20 @@ int fc_rport_login(struct fc_rport *rport)
int fc_rport_logoff(struct fc_rport *rport)
{
struct fc_rport_libfc_priv *rdata = rport->dd_data;
+ struct fc_lport *lport = rdata->local_port;
mutex_lock(&rdata->rp_mutex);
FC_DEBUG_RPORT("Remove port (%6x)\n", rport->port_id);
+ if (rdata->rp_state == RPORT_ST_NONE) {
+ FC_DEBUG_RPORT("(%6x): Port (%6x) in NONE state,"
+ " not removing", fc_host_port_id(lport->host),
+ rport->port_id);
+ mutex_unlock(&rdata->rp_mutex);
+ goto out;
+ }
+
fc_rport_enter_logo(rport);
/*
@@ -349,6 +362,7 @@ int fc_rport_logoff(struct fc_rport *rport)
mutex_unlock(&rdata->rp_mutex);
+out:
return 0;
}
@@ -430,6 +444,7 @@ static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp)
case RPORT_ST_PRLI:
case RPORT_ST_LOGO:
rdata->event = RPORT_EV_FAILED;
+ fc_rport_state_enter(rport, RPORT_ST_NONE);
queue_work(rport_event_queue,
&rdata->event_work);
break;
@@ -494,7 +509,7 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
struct fc_rport *rport = rp_arg;
struct fc_rport_libfc_priv *rdata = rport->dd_data;
struct fc_lport *lport = rdata->local_port;
- struct fc_els_flogi *plp;
+ struct fc_els_flogi *plp = NULL;
unsigned int tov;
u16 csp_seq;
u16 cssp_seq;
@@ -505,17 +520,19 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_RPORT("Received a PLOGI response from port (%6x)\n",
rport->port_id);
- if (IS_ERR(fp)) {
- fc_rport_error_retry(rport, fp);
- goto err;
- }
-
if (rdata->rp_state != RPORT_ST_PLOGI) {
FC_DBG("Received a PLOGI response, but in state %s\n",
fc_rport_state(rport));
+ if (IS_ERR(fp))
+ goto err;
goto out;
}
+ if (IS_ERR(fp)) {
+ fc_rport_error_retry(rport, fp);
+ goto err;
+ }
+
op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC &&
(plp = fc_frame_payload_get(fp, sizeof(*plp))) != NULL) {
@@ -614,17 +631,19 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_RPORT("Received a PRLI response from port (%6x)\n",
rport->port_id);
- if (IS_ERR(fp)) {
- fc_rport_error_retry(rport, fp);
- goto err;
- }
-
if (rdata->rp_state != RPORT_ST_PRLI) {
FC_DBG("Received a PRLI response, but in state %s\n",
fc_rport_state(rport));
+ if (IS_ERR(fp))
+ goto err;
goto out;
}
+ if (IS_ERR(fp)) {
+ fc_rport_error_retry(rport, fp);
+ goto err;
+ }
+
op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC) {
pp = fc_frame_payload_get(fp, sizeof(*pp));
@@ -646,6 +665,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
} else {
FC_DBG("Bad ELS response\n");
rdata->event = RPORT_EV_FAILED;
+ fc_rport_state_enter(rport, RPORT_ST_NONE);
queue_work(rport_event_queue, &rdata->event_work);
}
@@ -678,23 +698,26 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_RPORT("Received a LOGO response from port (%6x)\n",
rport->port_id);
- if (IS_ERR(fp)) {
- fc_rport_error_retry(rport, fp);
- goto err;
- }
-
if (rdata->rp_state != RPORT_ST_LOGO) {
FC_DEBUG_RPORT("Received a LOGO response, but in state %s\n",
fc_rport_state(rport));
+ if (IS_ERR(fp))
+ goto err;
goto out;
}
+ if (IS_ERR(fp)) {
+ fc_rport_error_retry(rport, fp);
+ goto err;
+ }
+
op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC) {
fc_rport_enter_rtv(rport);
} else {
FC_DBG("Bad ELS response\n");
rdata->event = RPORT_EV_LOGO;
+ fc_rport_state_enter(rport, RPORT_ST_NONE);
queue_work(rport_event_queue, &rdata->event_work);
}
@@ -764,17 +787,19 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_RPORT("Received a RTV response from port (%6x)\n",
rport->port_id);
- if (IS_ERR(fp)) {
- fc_rport_error(rport, fp);
- goto err;
- }
-
if (rdata->rp_state != RPORT_ST_RTV) {
FC_DBG("Received a RTV response, but in state %s\n",
fc_rport_state(rport));
+ if (IS_ERR(fp))
+ goto err;
goto out;
}
+ if (IS_ERR(fp)) {
+ fc_rport_error(rport, fp);
+ goto err;
+ }
+
op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC) {
struct fc_els_rtv_acc *rtv;
@@ -1007,6 +1032,8 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport,
default:
FC_DEBUG_RPORT("incoming PLOGI from %x in unexpected "
"state %d\n", sid, rdata->rp_state);
+ fc_frame_free(fp);
+ return;
break;
}
@@ -1098,6 +1125,8 @@ static void fc_rport_recv_prli_req(struct fc_rport *rport,
reason = ELS_RJT_NONE;
break;
default:
+ fc_frame_free(rx_fp);
+ return;
break;
}
len = fr_len(rx_fp) - sizeof(*fh);
@@ -1227,6 +1256,11 @@ static void fc_rport_recv_prlo_req(struct fc_rport *rport, struct fc_seq *sp,
"while in state %s\n", ntoh24(fh->fh_s_id),
fc_rport_state(rport));
+ if (rdata->rp_state == RPORT_ST_NONE) {
+ fc_frame_free(fp);
+ return;
+ }
+
rjt_data.fp = NULL;
rjt_data.reason = ELS_RJT_UNAB;
rjt_data.explan = ELS_EXPL_NONE;
@@ -1256,7 +1290,13 @@ static void fc_rport_recv_logo_req(struct fc_rport *rport, struct fc_seq *sp,
"while in state %s\n", ntoh24(fh->fh_s_id),
fc_rport_state(rport));
+ if (rdata->rp_state == RPORT_ST_NONE) {
+ fc_frame_free(fp);
+ return;
+ }
+
rdata->event = RPORT_EV_LOGO;
+ fc_rport_state_enter(rport, RPORT_ST_NONE);
queue_work(rport_event_queue, &rdata->event_work);
lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 689628359169..e72b4ad47d35 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1463,6 +1463,16 @@ int iscsi_change_queue_depth(struct scsi_device *sdev, int depth)
}
EXPORT_SYMBOL_GPL(iscsi_change_queue_depth);
+int iscsi_target_alloc(struct scsi_target *starget)
+{
+ struct iscsi_cls_session *cls_session = starget_to_session(starget);
+ struct iscsi_session *session = cls_session->dd_data;
+
+ starget->can_queue = session->scsi_cmds_max;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(iscsi_target_alloc);
+
void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session)
{
struct iscsi_session *session = cls_session->dd_data;
diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
index 91f8ce4d8d08..b579ca9f4836 100644
--- a/drivers/scsi/libiscsi_tcp.c
+++ b/drivers/scsi/libiscsi_tcp.c
@@ -1036,8 +1036,11 @@ flush:
rc = conn->session->tt->init_pdu(task, r2t->data_offset + r2t->sent,
r2t->data_count);
- if (rc)
+ if (rc) {
+ iscsi_conn_failure(conn, ISCSI_ERR_XMIT_FAILED);
return rc;
+ }
+
r2t->sent += r2t->data_count;
goto flush;
}
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index dcba267db711..1105f9a111ba 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -443,6 +443,7 @@ struct lpfc_hba {
uint32_t hba_flag; /* hba generic flags */
#define HBA_ERATT_HANDLED 0x1 /* This flag is set when eratt handled */
+#define DEFER_ERATT 0x4 /* Deferred error attention in progress */
struct lpfc_dmabuf slim2p;
MAILBOX_t *mbox;
@@ -723,4 +724,3 @@ lpfc_sli_read_hs(struct lpfc_hba *phba)
return;
}
-
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 40cf0f4f327f..c14f0cbdb125 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -51,7 +51,7 @@
#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8"
/**
- * lpfc_jedec_to_ascii: Hex to ascii convertor according to JEDEC rules.
+ * lpfc_jedec_to_ascii - Hex to ascii convertor according to JEDEC rules
* @incr: integer to convert.
* @hdw: ascii string holding converted integer plus a string terminator.
*
@@ -82,7 +82,7 @@ lpfc_jedec_to_ascii(int incr, char hdw[])
}
/**
- * lpfc_drvr_version_show: Return the Emulex driver string with version number.
+ * lpfc_drvr_version_show - Return the Emulex driver string with version number
* @dev: class unused variable.
* @attr: device attribute, not used.
* @buf: on return contains the module description text.
@@ -152,7 +152,7 @@ lpfc_bg_reftag_err_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_info_show: Return some pci info about the host in ascii.
+ * lpfc_info_show - Return some pci info about the host in ascii
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the formatted text from lpfc_info().
@@ -169,7 +169,7 @@ lpfc_info_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_serialnum_show: Return the hba serial number in ascii.
+ * lpfc_serialnum_show - Return the hba serial number in ascii
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the formatted text serial number.
@@ -188,7 +188,7 @@ lpfc_serialnum_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_temp_sensor_show: Return the temperature sensor level.
+ * lpfc_temp_sensor_show - Return the temperature sensor level
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the formatted support level.
@@ -210,7 +210,7 @@ lpfc_temp_sensor_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_modeldesc_show: Return the model description of the hba.
+ * lpfc_modeldesc_show - Return the model description of the hba
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the scsi vpd model description.
@@ -229,7 +229,7 @@ lpfc_modeldesc_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_modelname_show: Return the model name of the hba.
+ * lpfc_modelname_show - Return the model name of the hba
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the scsi vpd model name.
@@ -248,7 +248,7 @@ lpfc_modelname_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_programtype_show: Return the program type of the hba.
+ * lpfc_programtype_show - Return the program type of the hba
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the scsi vpd program type.
@@ -267,7 +267,7 @@ lpfc_programtype_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_mlomgmt_show: Return the Menlo Maintenance sli flag.
+ * lpfc_mlomgmt_show - Return the Menlo Maintenance sli flag
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the Menlo Maintenance sli flag.
@@ -286,7 +286,7 @@ lpfc_mlomgmt_show(struct device *dev, struct device_attribute *attr, char *buf)
}
/**
- * lpfc_vportnum_show: Return the port number in ascii of the hba.
+ * lpfc_vportnum_show - Return the port number in ascii of the hba
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains scsi vpd program type.
@@ -305,7 +305,7 @@ lpfc_vportnum_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_fwrev_show: Return the firmware rev running in the hba.
+ * lpfc_fwrev_show - Return the firmware rev running in the hba
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the scsi vpd program type.
@@ -326,7 +326,7 @@ lpfc_fwrev_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_hdw_show: Return the jedec information about the hba.
+ * lpfc_hdw_show - Return the jedec information about the hba
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the scsi vpd program type.
@@ -347,7 +347,7 @@ lpfc_hdw_show(struct device *dev, struct device_attribute *attr, char *buf)
}
/**
- * lpfc_option_rom_version_show: Return the adapter ROM FCode version.
+ * lpfc_option_rom_version_show - Return the adapter ROM FCode version
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the ROM and FCode ascii strings.
@@ -366,7 +366,7 @@ lpfc_option_rom_version_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_state_show: Return the link state of the port.
+ * lpfc_state_show - Return the link state of the port
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains text describing the state of the link.
@@ -451,7 +451,7 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_num_discovered_ports_show: Return sum of mapped and unmapped vports.
+ * lpfc_num_discovered_ports_show - Return sum of mapped and unmapped vports
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the sum of fc mapped and unmapped.
@@ -474,7 +474,7 @@ lpfc_num_discovered_ports_show(struct device *dev,
}
/**
- * lpfc_issue_lip: Misnomer, name carried over from long ago.
+ * lpfc_issue_lip - Misnomer, name carried over from long ago
* @shost: Scsi_Host pointer.
*
* Description:
@@ -529,7 +529,7 @@ lpfc_issue_lip(struct Scsi_Host *shost)
}
/**
- * lpfc_do_offline: Issues a mailbox command to bring the link down.
+ * lpfc_do_offline - Issues a mailbox command to bring the link down
* @phba: lpfc_hba pointer.
* @type: LPFC_EVT_OFFLINE, LPFC_EVT_WARM_START, LPFC_EVT_KILL.
*
@@ -537,7 +537,7 @@ lpfc_issue_lip(struct Scsi_Host *shost)
* Assumes any error from lpfc_do_offline() will be negative.
* Can wait up to 5 seconds for the port ring buffers count
* to reach zero, prints a warning if it is not zero and continues.
- * lpfc_workq_post_event() returns a non-zero return coce if call fails.
+ * lpfc_workq_post_event() returns a non-zero return code if call fails.
*
* Returns:
* -EIO error posting the event
@@ -591,7 +591,7 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
}
/**
- * lpfc_selective_reset: Offline then onlines the port.
+ * lpfc_selective_reset - Offline then onlines the port
* @phba: lpfc_hba pointer.
*
* Description:
@@ -632,7 +632,7 @@ lpfc_selective_reset(struct lpfc_hba *phba)
}
/**
- * lpfc_issue_reset: Selectively resets an adapter.
+ * lpfc_issue_reset - Selectively resets an adapter
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: containing the string "selective".
@@ -672,7 +672,7 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_nport_evt_cnt_show: Return the number of nport events.
+ * lpfc_nport_evt_cnt_show - Return the number of nport events
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the ascii number of nport events.
@@ -691,7 +691,7 @@ lpfc_nport_evt_cnt_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_board_mode_show: Return the state of the board.
+ * lpfc_board_mode_show - Return the state of the board
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the state of the adapter.
@@ -720,7 +720,7 @@ lpfc_board_mode_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_board_mode_store: Puts the hba in online, offline, warm or error state.
+ * lpfc_board_mode_store - Puts the hba in online, offline, warm or error state
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: containing one of the strings "online", "offline", "warm" or "error".
@@ -766,14 +766,14 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_get_hba_info: Return various bits of informaton about the adapter.
+ * lpfc_get_hba_info - Return various bits of informaton about the adapter
* @phba: pointer to the adapter structure.
- * @mxri max xri count.
- * @axri available xri count.
- * @mrpi max rpi count.
- * @arpi available rpi count.
- * @mvpi max vpi count.
- * @avpi available vpi count.
+ * @mxri: max xri count.
+ * @axri: available xri count.
+ * @mrpi: max rpi count.
+ * @arpi: available rpi count.
+ * @mvpi: max vpi count.
+ * @avpi: available vpi count.
*
* Description:
* If an integer pointer for an count is not null then the value for the
@@ -846,7 +846,7 @@ lpfc_get_hba_info(struct lpfc_hba *phba,
}
/**
- * lpfc_max_rpi_show: Return maximum rpi.
+ * lpfc_max_rpi_show - Return maximum rpi
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the maximum rpi count in decimal or "Unknown".
@@ -874,7 +874,7 @@ lpfc_max_rpi_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_used_rpi_show: Return maximum rpi minus available rpi.
+ * lpfc_used_rpi_show - Return maximum rpi minus available rpi
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: containing the used rpi count in decimal or "Unknown".
@@ -902,7 +902,7 @@ lpfc_used_rpi_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_max_xri_show: Return maximum xri.
+ * lpfc_max_xri_show - Return maximum xri
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the maximum xri count in decimal or "Unknown".
@@ -930,7 +930,7 @@ lpfc_max_xri_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_used_xri_show: Return maximum xpi minus the available xpi.
+ * lpfc_used_xri_show - Return maximum xpi minus the available xpi
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the used xri count in decimal or "Unknown".
@@ -958,7 +958,7 @@ lpfc_used_xri_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_max_vpi_show: Return maximum vpi.
+ * lpfc_max_vpi_show - Return maximum vpi
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the maximum vpi count in decimal or "Unknown".
@@ -986,7 +986,7 @@ lpfc_max_vpi_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_used_vpi_show: Return maximum vpi minus the available vpi.
+ * lpfc_used_vpi_show - Return maximum vpi minus the available vpi
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the used vpi count in decimal or "Unknown".
@@ -1014,7 +1014,7 @@ lpfc_used_vpi_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_npiv_info_show: Return text about NPIV support for the adapter.
+ * lpfc_npiv_info_show - Return text about NPIV support for the adapter
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: text that must be interpreted to determine if npiv is supported.
@@ -1042,7 +1042,7 @@ lpfc_npiv_info_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_poll_show: Return text about poll support for the adapter.
+ * lpfc_poll_show - Return text about poll support for the adapter
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the cfg_poll in hex.
@@ -1064,7 +1064,7 @@ lpfc_poll_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_poll_store: Set the value of cfg_poll for the adapter.
+ * lpfc_poll_store - Set the value of cfg_poll for the adapter
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: one or more lpfc_polling_flags values.
@@ -1136,7 +1136,7 @@ lpfc_poll_store(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_param_show: Return a cfg attribute value in decimal.
+ * lpfc_param_show - Return a cfg attribute value in decimal
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
@@ -1164,7 +1164,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
}
/**
- * lpfc_param_hex_show: Return a cfg attribute value in hex.
+ * lpfc_param_hex_show - Return a cfg attribute value in hex
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
@@ -1173,7 +1173,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
* lpfc_##attr##_show: Return the hex value of an adapters cfg_xxx field.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
- * @buf: on return contains the attribute value in hexidecimal.
+ * @buf: on return contains the attribute value in hexadecimal.
*
* Returns: size of formatted string.
**/
@@ -1192,7 +1192,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
}
/**
- * lpfc_param_init: Intializes a cfg attribute.
+ * lpfc_param_init - Intializes a cfg attribute
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
@@ -1226,7 +1226,7 @@ lpfc_##attr##_init(struct lpfc_hba *phba, int val) \
}
/**
- * lpfc_param_set: Set a cfg attribute value.
+ * lpfc_param_set - Set a cfg attribute value
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
@@ -1260,7 +1260,7 @@ lpfc_##attr##_set(struct lpfc_hba *phba, int val) \
}
/**
- * lpfc_param_store: Set a vport attribute value.
+ * lpfc_param_store - Set a vport attribute value
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
@@ -1300,7 +1300,7 @@ lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \
}
/**
- * lpfc_vport_param_show: Return decimal formatted cfg attribute value.
+ * lpfc_vport_param_show - Return decimal formatted cfg attribute value
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
@@ -1326,17 +1326,17 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
}
/**
- * lpfc_vport_param_hex_show: Return hex formatted attribute value.
+ * lpfc_vport_param_hex_show - Return hex formatted attribute value
*
* Description:
* Macro that given an attr e.g.
* hba_queue_depth expands into a function with the name
* lpfc_hba_queue_depth_show
*
- * lpfc_##attr##_show: prints the attribute value in hexidecimal.
+ * lpfc_##attr##_show: prints the attribute value in hexadecimal.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
- * @buf: on return contains the attribute value in hexidecimal.
+ * @buf: on return contains the attribute value in hexadecimal.
*
* Returns: length of formatted string.
**/
@@ -1353,7 +1353,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
}
/**
- * lpfc_vport_param_init: Initialize a vport cfg attribute.
+ * lpfc_vport_param_init - Initialize a vport cfg attribute
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
@@ -1386,7 +1386,7 @@ lpfc_##attr##_init(struct lpfc_vport *vport, int val) \
}
/**
- * lpfc_vport_param_set: Set a vport cfg attribute.
+ * lpfc_vport_param_set - Set a vport cfg attribute
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
@@ -1417,7 +1417,7 @@ lpfc_##attr##_set(struct lpfc_vport *vport, int val) \
}
/**
- * lpfc_vport_param_store: Set a vport attribute.
+ * lpfc_vport_param_store - Set a vport attribute
*
* Description:
* Macro that given an attr e.g. hba_queue_depth
@@ -1576,7 +1576,7 @@ static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL);
static char *lpfc_soft_wwn_key = "C99G71SL8032A";
/**
- * lpfc_soft_wwn_enable_store: Allows setting of the wwn if the key is valid.
+ * lpfc_soft_wwn_enable_store - Allows setting of the wwn if the key is valid
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: containing the string lpfc_soft_wwn_key.
@@ -1623,10 +1623,10 @@ static DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL,
lpfc_soft_wwn_enable_store);
/**
- * lpfc_soft_wwpn_show: Return the cfg soft ww port name of the adapter.
+ * lpfc_soft_wwpn_show - Return the cfg soft ww port name of the adapter
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
- * @buf: on return contains the wwpn in hexidecimal.
+ * @buf: on return contains the wwpn in hexadecimal.
*
* Returns: size of formatted string.
**/
@@ -1643,10 +1643,10 @@ lpfc_soft_wwpn_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_soft_wwpn_store: Set the ww port name of the adapter.
+ * lpfc_soft_wwpn_store - Set the ww port name of the adapter
* @dev class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
- * @buf: contains the wwpn in hexidecimal.
+ * @buf: contains the wwpn in hexadecimal.
* @count: number of wwpn bytes in buf
*
* Returns:
@@ -1729,10 +1729,10 @@ static DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\
lpfc_soft_wwpn_show, lpfc_soft_wwpn_store);
/**
- * lpfc_soft_wwnn_show: Return the cfg soft ww node name for the adapter.
+ * lpfc_soft_wwnn_show - Return the cfg soft ww node name for the adapter
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
- * @buf: on return contains the wwnn in hexidecimal.
+ * @buf: on return contains the wwnn in hexadecimal.
*
* Returns: size of formatted string.
**/
@@ -1747,9 +1747,9 @@ lpfc_soft_wwnn_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_soft_wwnn_store: sets the ww node name of the adapter.
+ * lpfc_soft_wwnn_store - sets the ww node name of the adapter
* @cdev: class device that is converted into a Scsi_host.
- * @buf: contains the ww node name in hexidecimal.
+ * @buf: contains the ww node name in hexadecimal.
* @count: number of wwnn bytes in buf.
*
* Returns:
@@ -1845,7 +1845,7 @@ MODULE_PARM_DESC(lpfc_nodev_tmo,
"for a device to come back");
/**
- * lpfc_nodev_tmo_show: Return the hba dev loss timeout value.
+ * lpfc_nodev_tmo_show - Return the hba dev loss timeout value
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the dev loss timeout in decimal.
@@ -1864,7 +1864,7 @@ lpfc_nodev_tmo_show(struct device *dev, struct device_attribute *attr,
}
/**
- * lpfc_nodev_tmo_init: Set the hba nodev timeout value.
+ * lpfc_nodev_tmo_init - Set the hba nodev timeout value
* @vport: lpfc vport structure pointer.
* @val: contains the nodev timeout value.
*
@@ -1905,7 +1905,7 @@ lpfc_nodev_tmo_init(struct lpfc_vport *vport, int val)
}
/**
- * lpfc_update_rport_devloss_tmo: Update dev loss tmo value.
+ * lpfc_update_rport_devloss_tmo - Update dev loss tmo value
* @vport: lpfc vport structure pointer.
*
* Description:
@@ -1926,7 +1926,7 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport)
}
/**
- * lpfc_nodev_tmo_set: Set the vport nodev tmo and devloss tmo values.
+ * lpfc_nodev_tmo_set - Set the vport nodev tmo and devloss tmo values
* @vport: lpfc vport structure pointer.
* @val: contains the tmo value.
*
@@ -1982,7 +1982,7 @@ lpfc_vport_param_init(devloss_tmo, LPFC_DEF_DEVLOSS_TMO,
lpfc_vport_param_show(devloss_tmo)
/**
- * lpfc_devloss_tmo_set: Sets vport nodev tmo, devloss tmo values, changed bit.
+ * lpfc_devloss_tmo_set - Sets vport nodev tmo, devloss tmo values, changed bit
* @vport: lpfc vport structure pointer.
* @val: contains the tmo value.
*
@@ -2094,7 +2094,7 @@ MODULE_PARM_DESC(lpfc_restrict_login,
lpfc_vport_param_show(restrict_login);
/**
- * lpfc_restrict_login_init: Set the vport restrict login flag.
+ * lpfc_restrict_login_init - Set the vport restrict login flag
* @vport: lpfc vport structure pointer.
* @val: contains the restrict login value.
*
@@ -2128,7 +2128,7 @@ lpfc_restrict_login_init(struct lpfc_vport *vport, int val)
}
/**
- * lpfc_restrict_login_set: Set the vport restrict login flag.
+ * lpfc_restrict_login_set - Set the vport restrict login flag
* @vport: lpfc vport structure pointer.
* @val: contains the restrict login value.
*
@@ -2201,7 +2201,7 @@ LPFC_VPORT_ATTR_R(scan_down, 1, 0, 1,
*/
/**
- * lpfc_topology_set: Set the adapters topology field.
+ * lpfc_topology_set - Set the adapters topology field
* @phba: lpfc_hba pointer.
* @val: topology value.
*
@@ -2216,18 +2216,41 @@ LPFC_VPORT_ATTR_R(scan_down, 1, 0, 1,
* non-zero return value from lpfc_issue_lip()
* -EINVAL val out of range
**/
-static int
-lpfc_topology_set(struct lpfc_hba *phba, int val)
+static ssize_t
+lpfc_topology_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ int val = 0;
+ int nolip = 0;
+ const char *val_buf = buf;
int err;
uint32_t prev_val;
+
+ if (!strncmp(buf, "nolip ", strlen("nolip "))) {
+ nolip = 1;
+ val_buf = &buf[strlen("nolip ")];
+ }
+
+ if (!isdigit(val_buf[0]))
+ return -EINVAL;
+ if (sscanf(val_buf, "%i", &val) != 1)
+ return -EINVAL;
+
if (val >= 0 && val <= 6) {
prev_val = phba->cfg_topology;
phba->cfg_topology = val;
+ if (nolip)
+ return strlen(buf);
+
err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport));
- if (err)
+ if (err) {
phba->cfg_topology = prev_val;
- return err;
+ return -EINVAL;
+ } else
+ return strlen(buf);
}
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"%d:0467 lpfc_topology attribute cannot be set to %d, "
@@ -2240,14 +2263,12 @@ module_param(lpfc_topology, int, 0);
MODULE_PARM_DESC(lpfc_topology, "Select Fibre Channel topology");
lpfc_param_show(topology)
lpfc_param_init(topology, 0, 0, 6)
-lpfc_param_store(topology)
static DEVICE_ATTR(lpfc_topology, S_IRUGO | S_IWUSR,
lpfc_topology_show, lpfc_topology_store);
/**
- * lpfc_stat_data_ctrl_store: write call back for lpfc_stat_data_ctrl
- * sysfs file.
+ * lpfc_stat_data_ctrl_store - write call back for lpfc_stat_data_ctrl sysfs file
* @dev: Pointer to class device.
* @buf: Data buffer.
* @count: Size of the data buffer.
@@ -2282,7 +2303,7 @@ lpfc_stat_data_ctrl_store(struct device *dev, struct device_attribute *attr,
unsigned long base, step, bucket_type;
if (!strncmp(buf, "setbucket", strlen("setbucket"))) {
- if (strlen(buf) > LPFC_MAX_DATA_CTRL_LEN)
+ if (strlen(buf) > (LPFC_MAX_DATA_CTRL_LEN - 1))
return -EINVAL;
strcpy(bucket_data, buf);
@@ -2411,8 +2432,7 @@ lpfc_stat_data_ctrl_store(struct device *dev, struct device_attribute *attr,
/**
- * lpfc_stat_data_ctrl_show: Read callback function for
- * lpfc_stat_data_ctrl sysfs file.
+ * lpfc_stat_data_ctrl_show - Read function for lpfc_stat_data_ctrl sysfs file
* @dev: Pointer to class device object.
* @buf: Data buffer.
*
@@ -2489,8 +2509,7 @@ static DEVICE_ATTR(lpfc_stat_data_ctrl, S_IRUGO | S_IWUSR,
/**
- * sysfs_drvr_stat_data_read: Read callback function for lpfc_drvr_stat_data
- * sysfs attribute.
+ * sysfs_drvr_stat_data_read - Read function for lpfc_drvr_stat_data attribute
* @kobj: Pointer to the kernel object
* @bin_attr: Attribute object
* @buff: Buffer pointer
@@ -2585,7 +2604,7 @@ static struct bin_attribute sysfs_drvr_stat_data_attr = {
*/
/**
- * lpfc_link_speed_set: Set the adapters link speed.
+ * lpfc_link_speed_set - Set the adapters link speed
* @phba: lpfc_hba pointer.
* @val: link speed value.
*
@@ -2601,12 +2620,29 @@ static struct bin_attribute sysfs_drvr_stat_data_attr = {
* non-zero return value from lpfc_issue_lip()
* -EINVAL val out of range
**/
-static int
-lpfc_link_speed_set(struct lpfc_hba *phba, int val)
+static ssize_t
+lpfc_link_speed_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ int val = 0;
+ int nolip = 0;
+ const char *val_buf = buf;
int err;
uint32_t prev_val;
+ if (!strncmp(buf, "nolip ", strlen("nolip "))) {
+ nolip = 1;
+ val_buf = &buf[strlen("nolip ")];
+ }
+
+ if (!isdigit(val_buf[0]))
+ return -EINVAL;
+ if (sscanf(val_buf, "%i", &val) != 1)
+ return -EINVAL;
+
if (((val == LINK_SPEED_1G) && !(phba->lmt & LMT_1Gb)) ||
((val == LINK_SPEED_2G) && !(phba->lmt & LMT_2Gb)) ||
((val == LINK_SPEED_4G) && !(phba->lmt & LMT_4Gb)) ||
@@ -2614,14 +2650,19 @@ lpfc_link_speed_set(struct lpfc_hba *phba, int val)
((val == LINK_SPEED_10G) && !(phba->lmt & LMT_10Gb)))
return -EINVAL;
- if ((val >= 0 && val <= LPFC_MAX_LINK_SPEED)
+ if ((val >= 0 && val <= 8)
&& (LPFC_LINK_SPEED_BITMAP & (1 << val))) {
prev_val = phba->cfg_link_speed;
phba->cfg_link_speed = val;
+ if (nolip)
+ return strlen(buf);
+
err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport));
- if (err)
+ if (err) {
phba->cfg_link_speed = prev_val;
- return err;
+ return -EINVAL;
+ } else
+ return strlen(buf);
}
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@@ -2637,7 +2678,7 @@ MODULE_PARM_DESC(lpfc_link_speed, "Select link speed");
lpfc_param_show(link_speed)
/**
- * lpfc_link_speed_init: Set the adapters link speed.
+ * lpfc_link_speed_init - Set the adapters link speed
* @phba: lpfc_hba pointer.
* @val: link speed value.
*
@@ -2668,7 +2709,6 @@ lpfc_link_speed_init(struct lpfc_hba *phba, int val)
return -EINVAL;
}
-lpfc_param_store(link_speed)
static DEVICE_ATTR(lpfc_link_speed, S_IRUGO | S_IWUSR,
lpfc_link_speed_show, lpfc_link_speed_store);
@@ -2865,7 +2905,7 @@ MODULE_PARM_DESC(lpfc_prot_guard, "host protection guard type");
/*
- * lpfc_sg_seg_cnt: Initial Maximum DMA Segment Count
+ * lpfc_sg_seg_cnt - Initial Maximum DMA Segment Count
* This value can be set to values between 64 and 256. The default value is
* 64, but may be increased to allow for larger Max I/O sizes. The scsi layer
* will be allowed to request I/Os of sizes up to (MAX_SEG_COUNT * SEG_SIZE).
@@ -2967,7 +3007,7 @@ struct device_attribute *lpfc_vport_attrs[] = {
};
/**
- * sysfs_ctlreg_write: Write method for writing to ctlreg.
+ * sysfs_ctlreg_write - Write method for writing to ctlreg
* @kobj: kernel kobject that contains the kernel class device.
* @bin_attr: kernel attributes passed to us.
* @buf: contains the data to be written to the adapter IOREG space.
@@ -3017,7 +3057,7 @@ sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr,
}
/**
- * sysfs_ctlreg_read: Read method for reading from ctlreg.
+ * sysfs_ctlreg_read - Read method for reading from ctlreg
* @kobj: kernel kobject that contains the kernel class device.
* @bin_attr: kernel attributes passed to us.
* @buf: if succesful contains the data from the adapter IOREG space.
@@ -3078,7 +3118,7 @@ static struct bin_attribute sysfs_ctlreg_attr = {
};
/**
- * sysfs_mbox_idle: frees the sysfs mailbox.
+ * sysfs_mbox_idle - frees the sysfs mailbox
* @phba: lpfc_hba pointer
**/
static void
@@ -3095,7 +3135,7 @@ sysfs_mbox_idle(struct lpfc_hba *phba)
}
/**
- * sysfs_mbox_write: Write method for writing information via mbox.
+ * sysfs_mbox_write - Write method for writing information via mbox
* @kobj: kernel kobject that contains the kernel class device.
* @bin_attr: kernel attributes passed to us.
* @buf: contains the data to be written to sysfs mbox.
@@ -3170,7 +3210,7 @@ sysfs_mbox_write(struct kobject *kobj, struct bin_attribute *bin_attr,
}
/**
- * sysfs_mbox_read: Read method for reading information via mbox.
+ * sysfs_mbox_read - Read method for reading information via mbox
* @kobj: kernel kobject that contains the kernel class device.
* @bin_attr: kernel attributes passed to us.
* @buf: contains the data to be read from sysfs mbox.
@@ -3374,7 +3414,7 @@ static struct bin_attribute sysfs_mbox_attr = {
};
/**
- * lpfc_alloc_sysfs_attr: Creates the ctlreg and mbox entries.
+ * lpfc_alloc_sysfs_attr - Creates the ctlreg and mbox entries
* @vport: address of lpfc vport structure.
*
* Return codes:
@@ -3415,7 +3455,7 @@ out:
}
/**
- * lpfc_free_sysfs_attr: Removes the ctlreg and mbox entries.
+ * lpfc_free_sysfs_attr - Removes the ctlreg and mbox entries
* @vport: address of lpfc vport structure.
**/
void
@@ -3437,7 +3477,7 @@ lpfc_free_sysfs_attr(struct lpfc_vport *vport)
*/
/**
- * lpfc_get_host_port_id: Copy the vport DID into the scsi host port id.
+ * lpfc_get_host_port_id - Copy the vport DID into the scsi host port id
* @shost: kernel scsi host pointer.
**/
static void
@@ -3450,7 +3490,7 @@ lpfc_get_host_port_id(struct Scsi_Host *shost)
}
/**
- * lpfc_get_host_port_type: Set the value of the scsi host port type.
+ * lpfc_get_host_port_type - Set the value of the scsi host port type
* @shost: kernel scsi host pointer.
**/
static void
@@ -3482,7 +3522,7 @@ lpfc_get_host_port_type(struct Scsi_Host *shost)
}
/**
- * lpfc_get_host_port_state: Set the value of the scsi host port state.
+ * lpfc_get_host_port_state - Set the value of the scsi host port state
* @shost: kernel scsi host pointer.
**/
static void
@@ -3520,7 +3560,7 @@ lpfc_get_host_port_state(struct Scsi_Host *shost)
}
/**
- * lpfc_get_host_speed: Set the value of the scsi host speed.
+ * lpfc_get_host_speed - Set the value of the scsi host speed
* @shost: kernel scsi host pointer.
**/
static void
@@ -3556,7 +3596,7 @@ lpfc_get_host_speed(struct Scsi_Host *shost)
}
/**
- * lpfc_get_host_fabric_name: Set the value of the scsi host fabric name.
+ * lpfc_get_host_fabric_name - Set the value of the scsi host fabric name
* @shost: kernel scsi host pointer.
**/
static void
@@ -3582,7 +3622,7 @@ lpfc_get_host_fabric_name (struct Scsi_Host *shost)
}
/**
- * lpfc_get_stats: Return statistical information about the adapter.
+ * lpfc_get_stats - Return statistical information about the adapter
* @shost: kernel scsi host pointer.
*
* Notes:
@@ -3707,7 +3747,7 @@ lpfc_get_stats(struct Scsi_Host *shost)
}
/**
- * lpfc_reset_stats: Copy the adapter link stats information.
+ * lpfc_reset_stats - Copy the adapter link stats information
* @shost: kernel scsi host pointer.
**/
static void
@@ -3788,7 +3828,7 @@ lpfc_reset_stats(struct Scsi_Host *shost)
*/
/**
- * lpfc_get_node_by_target: Return the nodelist for a target.
+ * lpfc_get_node_by_target - Return the nodelist for a target
* @starget: kernel scsi target pointer.
*
* Returns:
@@ -3817,7 +3857,7 @@ lpfc_get_node_by_target(struct scsi_target *starget)
}
/**
- * lpfc_get_starget_port_id: Set the target port id to the ndlp DID or -1.
+ * lpfc_get_starget_port_id - Set the target port id to the ndlp DID or -1
* @starget: kernel scsi target pointer.
**/
static void
@@ -3829,7 +3869,7 @@ lpfc_get_starget_port_id(struct scsi_target *starget)
}
/**
- * lpfc_get_starget_node_name: Set the target node name.
+ * lpfc_get_starget_node_name - Set the target node name
* @starget: kernel scsi target pointer.
*
* Description: Set the target node name to the ndlp node name wwn or zero.
@@ -3844,7 +3884,7 @@ lpfc_get_starget_node_name(struct scsi_target *starget)
}
/**
- * lpfc_get_starget_port_name: Set the target port name.
+ * lpfc_get_starget_port_name - Set the target port name
* @starget: kernel scsi target pointer.
*
* Description: set the target port name to the ndlp port name wwn or zero.
@@ -3859,7 +3899,7 @@ lpfc_get_starget_port_name(struct scsi_target *starget)
}
/**
- * lpfc_set_rport_loss_tmo: Set the rport dev loss tmo.
+ * lpfc_set_rport_loss_tmo - Set the rport dev loss tmo
* @rport: fc rport address.
* @timeout: new value for dev loss tmo.
*
@@ -3877,7 +3917,7 @@ lpfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
}
/**
- * lpfc_rport_show_function: Return rport target information.
+ * lpfc_rport_show_function - Return rport target information
*
* Description:
* Macro that uses field to generate a function with the name lpfc_show_rport_
@@ -3905,7 +3945,7 @@ lpfc_show_rport_##field (struct device *dev, \
static FC_RPORT_ATTR(field, S_IRUGO, lpfc_show_rport_##field, NULL)
/**
- * lpfc_set_vport_symbolic_name: Set the vport's symbolic name.
+ * lpfc_set_vport_symbolic_name - Set the vport's symbolic name
* @fc_vport: The fc_vport who's symbolic name has been changed.
*
* Description:
@@ -4048,7 +4088,7 @@ struct fc_function_template lpfc_vport_transport_functions = {
};
/**
- * lpfc_get_cfgparam: Used during probe_one to init the adapter structure.
+ * lpfc_get_cfgparam - Used during probe_one to init the adapter structure
* @phba: lpfc_hba pointer.
**/
void
@@ -4097,7 +4137,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
}
/**
- * lpfc_get_vport_cfgparam: Used during port create, init the vport structure.
+ * lpfc_get_vport_cfgparam - Used during port create, init the vport structure
* @vport: lpfc_vport pointer.
**/
void
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 07f4976319a5..f88ce3f26190 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -184,6 +184,8 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *);
struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *);
void lpfc_sli_release_iocbq(struct lpfc_hba *, struct lpfc_iocbq *);
uint16_t lpfc_sli_next_iotag(struct lpfc_hba *, struct lpfc_iocbq *);
+void lpfc_sli_cancel_iocbs(struct lpfc_hba *, struct list_head *, uint32_t,
+ uint32_t);
void lpfc_reset_barrier(struct lpfc_hba * phba);
int lpfc_sli_brdready(struct lpfc_hba *, uint32_t);
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index 81cdcf46c471..52be5644e07a 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -47,7 +47,7 @@
#include "lpfc_debugfs.h"
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
-/**
+/*
* debugfs interface
*
* To access this interface the user should:
@@ -95,7 +95,7 @@ module_param(lpfc_debugfs_max_slow_ring_trc, int, 0);
MODULE_PARM_DESC(lpfc_debugfs_max_slow_ring_trc,
"Set debugfs slow ring trace depth");
-int lpfc_debugfs_mask_disc_trc;
+static int lpfc_debugfs_mask_disc_trc;
module_param(lpfc_debugfs_mask_disc_trc, int, 0);
MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc,
"Set debugfs discovery trace mask");
@@ -127,7 +127,7 @@ static atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0);
static unsigned long lpfc_debugfs_start_time = 0L;
/**
- * lpfc_debugfs_disc_trc_data - Dump discovery logging to a buffer.
+ * lpfc_debugfs_disc_trc_data - Dump discovery logging to a buffer
* @vport: The vport to gather the log info from.
* @buf: The buffer to dump log into.
* @size: The maximum amount of data to process.
@@ -187,7 +187,7 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
}
/**
- * lpfc_debugfs_slow_ring_trc_data - Dump slow ring logging to a buffer.
+ * lpfc_debugfs_slow_ring_trc_data - Dump slow ring logging to a buffer
* @phba: The HBA to gather the log info from.
* @buf: The buffer to dump log into.
* @size: The maximum amount of data to process.
@@ -250,7 +250,7 @@ lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size)
static int lpfc_debugfs_last_hbq = -1;
/**
- * lpfc_debugfs_hbqinfo_data - Dump host buffer queue info to a buffer.
+ * lpfc_debugfs_hbqinfo_data - Dump host buffer queue info to a buffer
* @phba: The HBA to gather host buffer info from.
* @buf: The buffer to dump log into.
* @size: The maximum amount of data to process.
@@ -369,7 +369,7 @@ skipit:
static int lpfc_debugfs_last_hba_slim_off;
/**
- * lpfc_debugfs_dumpHBASlim_data - Dump HBA SLIM info to a buffer.
+ * lpfc_debugfs_dumpHBASlim_data - Dump HBA SLIM info to a buffer
* @phba: The HBA to gather SLIM info from.
* @buf: The buffer to dump log into.
* @size: The maximum amount of data to process.
@@ -399,8 +399,7 @@ lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size)
len += snprintf(buf+len, size-len, "HBA SLIM\n");
lpfc_memcpy_from_slim(buffer,
- ((uint8_t *)phba->MBslimaddr) + lpfc_debugfs_last_hba_slim_off,
- 1024);
+ phba->MBslimaddr + lpfc_debugfs_last_hba_slim_off, 1024);
ptr = (uint32_t *)&buffer[0];
off = lpfc_debugfs_last_hba_slim_off;
@@ -426,7 +425,7 @@ lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size)
}
/**
- * lpfc_debugfs_dumpHostSlim_data - Dump host SLIM info to a buffer.
+ * lpfc_debugfs_dumpHostSlim_data - Dump host SLIM info to a buffer
* @phba: The HBA to gather Host SLIM info from.
* @buf: The buffer to dump log into.
* @size: The maximum amount of data to process.
@@ -501,7 +500,7 @@ lpfc_debugfs_dumpHostSlim_data(struct lpfc_hba *phba, char *buf, int size)
}
/**
- * lpfc_debugfs_nodelist_data - Dump target node list to a buffer.
+ * lpfc_debugfs_nodelist_data - Dump target node list to a buffer
* @vport: The vport to gather target node info from.
* @buf: The buffer to dump log into.
* @size: The maximum amount of data to process.
@@ -599,7 +598,7 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
#endif
/**
- * lpfc_debugfs_disc_trc - Store discovery trace log.
+ * lpfc_debugfs_disc_trc - Store discovery trace log
* @vport: The vport to associate this trace string with for retrieval.
* @mask: Log entry classification.
* @fmt: Format string to be displayed when dumping the log.
@@ -643,7 +642,7 @@ lpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt,
}
/**
- * lpfc_debugfs_slow_ring_trc - Store slow ring trace log.
+ * lpfc_debugfs_slow_ring_trc - Store slow ring trace log
* @phba: The phba to associate this trace string with for retrieval.
* @fmt: Format string to be displayed when dumping the log.
* @data1: 1st data parameter to be applied to @fmt.
@@ -682,7 +681,7 @@ lpfc_debugfs_slow_ring_trc(struct lpfc_hba *phba, char *fmt,
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
/**
- * lpfc_debugfs_disc_trc_open - Open the discovery trace log.
+ * lpfc_debugfs_disc_trc_open - Open the discovery trace log
* @inode: The inode pointer that contains a vport pointer.
* @file: The file pointer to attach the log output.
*
@@ -732,7 +731,7 @@ out:
}
/**
- * lpfc_debugfs_slow_ring_trc_open - Open the Slow Ring trace log.
+ * lpfc_debugfs_slow_ring_trc_open - Open the Slow Ring trace log
* @inode: The inode pointer that contains a vport pointer.
* @file: The file pointer to attach the log output.
*
@@ -782,7 +781,7 @@ out:
}
/**
- * lpfc_debugfs_hbqinfo_open - Open the hbqinfo debugfs buffer.
+ * lpfc_debugfs_hbqinfo_open - Open the hbqinfo debugfs buffer
* @inode: The inode pointer that contains a vport pointer.
* @file: The file pointer to attach the log output.
*
@@ -824,7 +823,7 @@ out:
}
/**
- * lpfc_debugfs_dumpHBASlim_open - Open the Dump HBA SLIM debugfs buffer.
+ * lpfc_debugfs_dumpHBASlim_open - Open the Dump HBA SLIM debugfs buffer
* @inode: The inode pointer that contains a vport pointer.
* @file: The file pointer to attach the log output.
*
@@ -866,7 +865,7 @@ out:
}
/**
- * lpfc_debugfs_dumpHostSlim_open - Open the Dump Host SLIM debugfs buffer.
+ * lpfc_debugfs_dumpHostSlim_open - Open the Dump Host SLIM debugfs buffer
* @inode: The inode pointer that contains a vport pointer.
* @file: The file pointer to attach the log output.
*
@@ -993,7 +992,7 @@ lpfc_debugfs_dumpDataDif_write(struct file *file, const char __user *buf,
/**
- * lpfc_debugfs_nodelist_open - Open the nodelist debugfs file.
+ * lpfc_debugfs_nodelist_open - Open the nodelist debugfs file
* @inode: The inode pointer that contains a vport pointer.
* @file: The file pointer to attach the log output.
*
@@ -1035,7 +1034,7 @@ out:
}
/**
- * lpfc_debugfs_lseek - Seek through a debugfs file.
+ * lpfc_debugfs_lseek - Seek through a debugfs file
* @file: The file pointer to seek through.
* @off: The offset to seek to or the amount to seek by.
* @whence: Indicates how to seek.
@@ -1073,7 +1072,7 @@ lpfc_debugfs_lseek(struct file *file, loff_t off, int whence)
}
/**
- * lpfc_debugfs_read - Read a debugfs file.
+ * lpfc_debugfs_read - Read a debugfs file
* @file: The file pointer to read from.
* @buf: The buffer to copy the data to.
* @nbytes: The number of bytes to read.
@@ -1098,7 +1097,7 @@ lpfc_debugfs_read(struct file *file, char __user *buf,
}
/**
- * lpfc_debugfs_release - Release the buffer used to store debugfs file data.
+ * lpfc_debugfs_release - Release the buffer used to store debugfs file data
* @inode: The inode pointer that contains a vport pointer. (unused)
* @file: The file pointer that contains the buffer to release.
*
@@ -1210,7 +1209,7 @@ static atomic_t lpfc_debugfs_hba_count;
#endif
/**
- * lpfc_debugfs_initialize - Initialize debugfs for a vport.
+ * lpfc_debugfs_initialize - Initialize debugfs for a vport
* @vport: The vport pointer to initialize.
*
* Description:
@@ -1434,7 +1433,7 @@ debug_failed:
}
/**
- * lpfc_debugfs_terminate - Tear down debugfs infrastructure for this vport.
+ * lpfc_debugfs_terminate - Tear down debugfs infrastructure for this vport
* @vport: The vport pointer to remove from debugfs.
*
* Description:
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index f29e548a90d1..ffd108972072 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -99,6 +99,7 @@ struct lpfc_nodelist {
#define NLP_USG_FREE_ACK_BIT 0x8 /* Indicate ndlp memory free invoked */
struct timer_list nlp_delayfunc; /* Used for delayed ELS cmds */
+ struct lpfc_hba *phba;
struct fc_rport *rport; /* Corresponding FC transport
port structure */
struct lpfc_vport *vport;
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index a7302480bc4a..b8b34cf5c3d2 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -55,7 +55,7 @@ static void lpfc_register_new_vport(struct lpfc_hba *phba,
static int lpfc_max_els_tries = 3;
/**
- * lpfc_els_chk_latt: Check host link attention event for a vport.
+ * lpfc_els_chk_latt - Check host link attention event for a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine checks whether there is an outstanding host link
@@ -116,7 +116,7 @@ lpfc_els_chk_latt(struct lpfc_vport *vport)
}
/**
- * lpfc_prep_els_iocb: Allocate and prepare a lpfc iocb data structure.
+ * lpfc_prep_els_iocb - Allocate and prepare a lpfc iocb data structure
* @vport: pointer to a host virtual N_Port data structure.
* @expectRsp: flag indicating whether response is expected.
* @cmdSize: size of the ELS command.
@@ -290,7 +290,7 @@ els_iocb_free_pcmb_exit:
}
/**
- * lpfc_issue_fabric_reglogin: Issue fabric registration login for a vport.
+ * lpfc_issue_fabric_reglogin - Issue fabric registration login for a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine issues a fabric registration login for a @vport. An
@@ -386,7 +386,7 @@ fail:
}
/**
- * lpfc_cmpl_els_flogi_fabric: Completion function for flogi to a fabric port.
+ * lpfc_cmpl_els_flogi_fabric - Completion function for flogi to a fabric port
* @vport: pointer to a host virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @sp: pointer to service parameter data structure.
@@ -509,7 +509,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
}
/**
- * lpfc_cmpl_els_flogi_nport: Completion function for flogi to an N_Port.
+ * lpfc_cmpl_els_flogi_nport - Completion function for flogi to an N_Port
* @vport: pointer to a host virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @sp: pointer to service parameter data structure.
@@ -626,7 +626,7 @@ fail:
}
/**
- * lpfc_cmpl_els_flogi: Completion callback function for flogi.
+ * lpfc_cmpl_els_flogi - Completion callback function for flogi
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
@@ -751,7 +751,7 @@ out:
}
/**
- * lpfc_issue_els_flogi: Issue an flogi iocb command for a vport.
+ * lpfc_issue_els_flogi - Issue an flogi iocb command for a vport
* @vport: pointer to a host virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @retry: number of retries to the command IOCB.
@@ -849,7 +849,7 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
}
/**
- * lpfc_els_abort_flogi: Abort all outstanding flogi iocbs.
+ * lpfc_els_abort_flogi - Abort all outstanding flogi iocbs
* @phba: pointer to lpfc hba data structure.
*
* This routine aborts all the outstanding Fabric Login (FLOGI) IOCBs
@@ -898,7 +898,7 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba)
}
/**
- * lpfc_initial_flogi: Issue an initial fabric login for a vport.
+ * lpfc_initial_flogi - Issue an initial fabric login for a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine issues an initial Fabric Login (FLOGI) for the @vport
@@ -949,7 +949,7 @@ lpfc_initial_flogi(struct lpfc_vport *vport)
}
/**
- * lpfc_initial_fdisc: Issue an initial fabric discovery for a vport.
+ * lpfc_initial_fdisc - Issue an initial fabric discovery for a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine issues an initial Fabric Discover (FDISC) for the @vport
@@ -998,7 +998,7 @@ lpfc_initial_fdisc(struct lpfc_vport *vport)
}
/**
- * lpfc_more_plogi: Check and issue remaining plogis for a vport.
+ * lpfc_more_plogi - Check and issue remaining plogis for a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine checks whether there are more remaining Port Logins
@@ -1031,7 +1031,7 @@ lpfc_more_plogi(struct lpfc_vport *vport)
}
/**
- * lpfc_plogi_confirm_nport: Confirm pologi wwpn matches stored ndlp.
+ * lpfc_plogi_confirm_nport - Confirm pologi wwpn matches stored ndlp
* @phba: pointer to lpfc hba data structure.
* @prsp: pointer to response IOCB payload.
* @ndlp: pointer to a node-list data structure.
@@ -1165,7 +1165,7 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
}
/**
- * lpfc_end_rscn: Check and handle more rscn for a vport.
+ * lpfc_end_rscn - Check and handle more rscn for a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine checks whether more Registration State Change
@@ -1197,7 +1197,7 @@ lpfc_end_rscn(struct lpfc_vport *vport)
}
/**
- * lpfc_cmpl_els_plogi: Completion callback function for plogi.
+ * lpfc_cmpl_els_plogi - Completion callback function for plogi
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
@@ -1322,7 +1322,7 @@ out:
}
/**
- * lpfc_issue_els_plogi: Issue an plogi iocb command for a vport.
+ * lpfc_issue_els_plogi - Issue an plogi iocb command for a vport
* @vport: pointer to a host virtual N_Port data structure.
* @did: destination port identifier.
* @retry: number of retries to the command IOCB.
@@ -1401,7 +1401,7 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
}
/**
- * lpfc_cmpl_els_prli: Completion callback function for prli.
+ * lpfc_cmpl_els_prli - Completion callback function for prli
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
@@ -1472,7 +1472,7 @@ out:
}
/**
- * lpfc_issue_els_prli: Issue a prli iocb command for a vport.
+ * lpfc_issue_els_prli - Issue a prli iocb command for a vport
* @vport: pointer to a host virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @retry: number of retries to the command IOCB.
@@ -1562,7 +1562,7 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
}
/**
- * lpfc_rscn_disc: Perform rscn discovery for a vport.
+ * lpfc_rscn_disc - Perform rscn discovery for a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine performs Registration State Change Notification (RSCN)
@@ -1588,7 +1588,7 @@ lpfc_rscn_disc(struct lpfc_vport *vport)
}
/**
- * lpfc_adisc_done: Complete the adisc phase of discovery.
+ * lpfc_adisc_done - Complete the adisc phase of discovery
* @vport: pointer to lpfc_vport hba data structure that finished all ADISCs.
*
* This function is called when the final ADISC is completed during discovery.
@@ -1639,7 +1639,7 @@ lpfc_adisc_done(struct lpfc_vport *vport)
}
/**
- * lpfc_more_adisc: Issue more adisc as needed.
+ * lpfc_more_adisc - Issue more adisc as needed
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine determines whether there are more ndlps on a @vport
@@ -1672,7 +1672,7 @@ lpfc_more_adisc(struct lpfc_vport *vport)
}
/**
- * lpfc_cmpl_els_adisc: Completion callback function for adisc.
+ * lpfc_cmpl_els_adisc - Completion callback function for adisc
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
@@ -1760,7 +1760,7 @@ out:
}
/**
- * lpfc_issue_els_adisc: Issue an address discover iocb to an node on a vport.
+ * lpfc_issue_els_adisc - Issue an address discover iocb to an node on a vport
* @vport: pointer to a virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @retry: number of retries to the command IOCB.
@@ -1833,7 +1833,7 @@ lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
}
/**
- * lpfc_cmpl_els_logo: Completion callback function for logo.
+ * lpfc_cmpl_els_logo - Completion callback function for logo
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
@@ -1910,7 +1910,7 @@ out:
}
/**
- * lpfc_issue_els_logo: Issue a logo to an node on a vport.
+ * lpfc_issue_els_logo - Issue a logo to an node on a vport
* @vport: pointer to a virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @retry: number of retries to the command IOCB.
@@ -1991,7 +1991,7 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
}
/**
- * lpfc_cmpl_els_cmd: Completion callback function for generic els command.
+ * lpfc_cmpl_els_cmd - Completion callback function for generic els command
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
@@ -2031,7 +2031,7 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
}
/**
- * lpfc_issue_els_scr: Issue a scr to an node on a vport.
+ * lpfc_issue_els_scr - Issue a scr to an node on a vport
* @vport: pointer to a host virtual N_Port data structure.
* @nportid: N_Port identifier to the remote node.
* @retry: number of retries to the command IOCB.
@@ -2125,7 +2125,7 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
}
/**
- * lpfc_issue_els_farpr: Issue a farp to an node on a vport.
+ * lpfc_issue_els_farpr - Issue a farp to an node on a vport
* @vport: pointer to a host virtual N_Port data structure.
* @nportid: N_Port identifier to the remote node.
* @retry: number of retries to the command IOCB.
@@ -2236,7 +2236,7 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
}
/**
- * lpfc_cancel_retry_delay_tmo: Cancel the timer with delayed iocb-cmd retry.
+ * lpfc_cancel_retry_delay_tmo - Cancel the timer with delayed iocb-cmd retry
* @vport: pointer to a host virtual N_Port data structure.
* @nlp: pointer to a node-list data structure.
*
@@ -2291,7 +2291,7 @@ lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp)
}
/**
- * lpfc_els_retry_delay: Timer function with a ndlp delayed function timer.
+ * lpfc_els_retry_delay - Timer function with a ndlp delayed function timer
* @ptr: holder for the pointer to the timer function associated data (ndlp).
*
* This routine is invoked by the ndlp delayed-function timer to check
@@ -2333,7 +2333,7 @@ lpfc_els_retry_delay(unsigned long ptr)
}
/**
- * lpfc_els_retry_delay_handler: Work thread handler for ndlp delayed function.
+ * lpfc_els_retry_delay_handler - Work thread handler for ndlp delayed function
* @ndlp: pointer to a node-list data structure.
*
* This routine is the worker-thread handler for processing the @ndlp delayed
@@ -2404,7 +2404,7 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp)
}
/**
- * lpfc_els_retry: Make retry decision on an els command iocb.
+ * lpfc_els_retry - Make retry decision on an els command iocb
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
@@ -2732,7 +2732,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
}
/**
- * lpfc_els_free_data: Free lpfc dma buffer and data structure with an iocb.
+ * lpfc_els_free_data - Free lpfc dma buffer and data structure with an iocb
* @phba: pointer to lpfc hba data structure.
* @buf_ptr1: pointer to the lpfc DMA buffer data structure.
*
@@ -2764,7 +2764,7 @@ lpfc_els_free_data(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr1)
}
/**
- * lpfc_els_free_bpl: Free lpfc dma buffer and data structure with bpl.
+ * lpfc_els_free_bpl - Free lpfc dma buffer and data structure with bpl
* @phba: pointer to lpfc hba data structure.
* @buf_ptr: pointer to the lpfc dma buffer data structure.
*
@@ -2784,7 +2784,7 @@ lpfc_els_free_bpl(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr)
}
/**
- * lpfc_els_free_iocb: Free a command iocb and its associated resources.
+ * lpfc_els_free_iocb - Free a command iocb and its associated resources
* @phba: pointer to lpfc hba data structure.
* @elsiocb: pointer to lpfc els command iocb data structure.
*
@@ -2877,7 +2877,7 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
}
/**
- * lpfc_cmpl_els_logo_acc: Completion callback function to logo acc response.
+ * lpfc_cmpl_els_logo_acc - Completion callback function to logo acc response
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
@@ -2931,7 +2931,7 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
}
/**
- * lpfc_mbx_cmpl_dflt_rpi: Completion callbk func for unreg dflt rpi mbox cmd.
+ * lpfc_mbx_cmpl_dflt_rpi - Completion callbk func for unreg dflt rpi mbox cmd
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
@@ -2965,7 +2965,7 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
}
/**
- * lpfc_cmpl_els_rsp: Completion callback function for els response iocb cmd.
+ * lpfc_cmpl_els_rsp - Completion callback function for els response iocb cmd
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
@@ -3136,7 +3136,7 @@ out:
}
/**
- * lpfc_els_rsp_acc: Prepare and issue an acc response iocb command.
+ * lpfc_els_rsp_acc - Prepare and issue an acc response iocb command
* @vport: pointer to a host virtual N_Port data structure.
* @flag: the els command code to be accepted.
* @oldiocb: pointer to the original lpfc command iocb data structure.
@@ -3275,7 +3275,7 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
}
/**
- * lpfc_els_rsp_reject: Propare and issue a rjt response iocb command.
+ * lpfc_els_rsp_reject - Propare and issue a rjt response iocb command
* @vport: pointer to a virtual N_Port data structure.
* @rejectError:
* @oldiocb: pointer to the original lpfc command iocb data structure.
@@ -3356,7 +3356,7 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
}
/**
- * lpfc_els_rsp_adisc_acc: Prepare and issue acc response to adisc iocb cmd.
+ * lpfc_els_rsp_adisc_acc - Prepare and issue acc response to adisc iocb cmd
* @vport: pointer to a virtual N_Port data structure.
* @oldiocb: pointer to the original lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
@@ -3431,7 +3431,7 @@ lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
}
/**
- * lpfc_els_rsp_prli_acc: Prepare and issue acc response to prli iocb cmd.
+ * lpfc_els_rsp_prli_acc - Prepare and issue acc response to prli iocb cmd
* @vport: pointer to a virtual N_Port data structure.
* @oldiocb: pointer to the original lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
@@ -3529,7 +3529,7 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
}
/**
- * lpfc_els_rsp_rnid_acc: Issue rnid acc response iocb command.
+ * lpfc_els_rsp_rnid_acc - Issue rnid acc response iocb command
* @vport: pointer to a virtual N_Port data structure.
* @format: rnid command format.
* @oldiocb: pointer to the original lpfc command iocb data structure.
@@ -3635,7 +3635,7 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format,
}
/**
- * lpfc_els_disc_adisc: Issue remaining adisc iocbs to npr nodes of a vport.
+ * lpfc_els_disc_adisc - Issue remaining adisc iocbs to npr nodes of a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine issues Address Discover (ADISC) ELS commands to those
@@ -3693,7 +3693,7 @@ lpfc_els_disc_adisc(struct lpfc_vport *vport)
}
/**
- * lpfc_els_disc_plogi: Issue plogi for all npr nodes of a vport before adisc.
+ * lpfc_els_disc_plogi - Issue plogi for all npr nodes of a vport before adisc
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine issues Port Login (PLOGI) ELS commands to all the N_Ports
@@ -3752,7 +3752,7 @@ lpfc_els_disc_plogi(struct lpfc_vport *vport)
}
/**
- * lpfc_els_flush_rscn: Clean up any rscn activities with a vport.
+ * lpfc_els_flush_rscn - Clean up any rscn activities with a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine cleans up any Registration State Change Notification
@@ -3791,7 +3791,7 @@ lpfc_els_flush_rscn(struct lpfc_vport *vport)
}
/**
- * lpfc_rscn_payload_check: Check whether there is a pending rscn to a did.
+ * lpfc_rscn_payload_check - Check whether there is a pending rscn to a did
* @vport: pointer to a host virtual N_Port data structure.
* @did: remote destination port identifier.
*
@@ -3866,7 +3866,7 @@ return_did_out:
}
/**
- * lpfc_rscn_recovery_check: Send recovery event to vport nodes matching rscn
+ * lpfc_rscn_recovery_check - Send recovery event to vport nodes matching rscn
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine sends recovery (NLP_EVT_DEVICE_RECOVERY) event to the
@@ -3895,7 +3895,7 @@ lpfc_rscn_recovery_check(struct lpfc_vport *vport)
}
/**
- * lpfc_send_rscn_event: Send an RSCN event to management application.
+ * lpfc_send_rscn_event - Send an RSCN event to management application
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
*
@@ -3938,7 +3938,7 @@ lpfc_send_rscn_event(struct lpfc_vport *vport,
}
/**
- * lpfc_els_rcv_rscn: Process an unsolicited rscn iocb.
+ * lpfc_els_rcv_rscn - Process an unsolicited rscn iocb
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
@@ -4134,7 +4134,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
}
/**
- * lpfc_els_handle_rscn: Handle rscn for a vport.
+ * lpfc_els_handle_rscn - Handle rscn for a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine handles the Registration State Configuration Notification
@@ -4222,7 +4222,7 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport)
}
/**
- * lpfc_els_rcv_flogi: Process an unsolicited flogi iocb.
+ * lpfc_els_rcv_flogi - Process an unsolicited flogi iocb
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
@@ -4336,7 +4336,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
}
/**
- * lpfc_els_rcv_rnid: Process an unsolicited rnid iocb.
+ * lpfc_els_rcv_rnid - Process an unsolicited rnid iocb
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
@@ -4391,7 +4391,7 @@ lpfc_els_rcv_rnid(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
}
/**
- * lpfc_els_rcv_lirr: Process an unsolicited lirr iocb.
+ * lpfc_els_rcv_lirr - Process an unsolicited lirr iocb
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
@@ -4419,7 +4419,7 @@ lpfc_els_rcv_lirr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
}
/**
- * lpfc_els_rsp_rps_acc: Completion callbk func for MBX_READ_LNK_STAT mbox cmd.
+ * lpfc_els_rsp_rps_acc - Completion callbk func for MBX_READ_LNK_STAT mbox cmd
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
@@ -4513,7 +4513,7 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
}
/**
- * lpfc_els_rcv_rps: Process an unsolicited rps iocb.
+ * lpfc_els_rcv_rps - Process an unsolicited rps iocb
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
@@ -4590,7 +4590,7 @@ reject_out:
}
/**
- * lpfc_els_rsp_rpl_acc: Issue an accept rpl els command.
+ * lpfc_els_rsp_rpl_acc - Issue an accept rpl els command
* @vport: pointer to a host virtual N_Port data structure.
* @cmdsize: size of the ELS command.
* @oldiocb: pointer to the original lpfc command iocb data structure.
@@ -4662,7 +4662,7 @@ lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize,
}
/**
- * lpfc_els_rcv_rpl: Process an unsolicited rpl iocb.
+ * lpfc_els_rcv_rpl - Process an unsolicited rpl iocb
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
@@ -4721,7 +4721,7 @@ lpfc_els_rcv_rpl(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
}
/**
- * lpfc_els_rcv_farp: Process an unsolicited farp request els command.
+ * lpfc_els_rcv_farp - Process an unsolicited farp request els command
* @vport: pointer to a virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
@@ -4804,7 +4804,7 @@ lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
}
/**
- * lpfc_els_rcv_farpr: Process an unsolicited farp response iocb.
+ * lpfc_els_rcv_farpr - Process an unsolicited farp response iocb
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
@@ -4842,7 +4842,7 @@ lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
}
/**
- * lpfc_els_rcv_fan: Process an unsolicited fan iocb command.
+ * lpfc_els_rcv_fan - Process an unsolicited fan iocb command
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @fan_ndlp: pointer to a node-list data structure.
@@ -4890,7 +4890,7 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
}
/**
- * lpfc_els_timeout: Handler funciton to the els timer.
+ * lpfc_els_timeout - Handler funciton to the els timer
* @ptr: holder for the timer function associated data.
*
* This routine is invoked by the ELS timer after timeout. It posts the ELS
@@ -4919,7 +4919,7 @@ lpfc_els_timeout(unsigned long ptr)
}
/**
- * lpfc_els_timeout_handler: Process an els timeout event.
+ * lpfc_els_timeout_handler - Process an els timeout event
* @vport: pointer to a virtual N_Port data structure.
*
* This routine is the actual handler function that processes an ELS timeout
@@ -4994,7 +4994,7 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
}
/**
- * lpfc_els_flush_cmd: Clean up the outstanding els commands to a vport.
+ * lpfc_els_flush_cmd - Clean up the outstanding els commands to a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine is used to clean up all the outstanding ELS commands on a
@@ -5058,25 +5058,15 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
}
spin_unlock_irq(&phba->hbalock);
- while (!list_empty(&completions)) {
- piocb = list_get_first(&completions, struct lpfc_iocbq, list);
- cmd = &piocb->iocb;
- list_del_init(&piocb->list);
-
- if (!piocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, piocb);
- else {
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
- (piocb->iocb_cmpl) (phba, piocb, piocb);
- }
- }
+ /* Cancell all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
return;
}
/**
- * lpfc_els_flush_all_cmd: Clean up all the outstanding els commands to a HBA.
+ * lpfc_els_flush_all_cmd - Clean up all the outstanding els commands to a HBA
* @phba: pointer to lpfc hba data structure.
*
* This routine is used to clean up all the outstanding ELS commands on a
@@ -5121,23 +5111,16 @@ lpfc_els_flush_all_cmd(struct lpfc_hba *phba)
lpfc_sli_issue_abort_iotag(phba, pring, piocb);
}
spin_unlock_irq(&phba->hbalock);
- while (!list_empty(&completions)) {
- piocb = list_get_first(&completions, struct lpfc_iocbq, list);
- cmd = &piocb->iocb;
- list_del_init(&piocb->list);
- if (!piocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, piocb);
- else {
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
- (piocb->iocb_cmpl) (phba, piocb, piocb);
- }
- }
+
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
+
return;
}
/**
- * lpfc_send_els_failure_event: Posts an ELS command failure event.
+ * lpfc_send_els_failure_event - Posts an ELS command failure event
* @phba: Pointer to hba context object.
* @cmdiocbp: Pointer to command iocb which reported error.
* @rspiocbp: Pointer to response iocb which reported error.
@@ -5204,7 +5187,7 @@ lpfc_send_els_failure_event(struct lpfc_hba *phba,
}
/**
- * lpfc_send_els_event: Posts unsolicited els event.
+ * lpfc_send_els_event - Posts unsolicited els event
* @vport: Pointer to vport object.
* @ndlp: Pointer FC node object.
* @cmd: ELS command code.
@@ -5284,7 +5267,7 @@ lpfc_send_els_event(struct lpfc_vport *vport,
/**
- * lpfc_els_unsol_buffer: Process an unsolicited event data buffer.
+ * lpfc_els_unsol_buffer - Process an unsolicited event data buffer
* @phba: pointer to lpfc hba data structure.
* @pring: pointer to a SLI ring.
* @vport: pointer to a host virtual N_Port data structure.
@@ -5592,7 +5575,7 @@ dropit:
}
/**
- * lpfc_find_vport_by_vpid: Find a vport on a HBA through vport identifier.
+ * lpfc_find_vport_by_vpid - Find a vport on a HBA through vport identifier
* @phba: pointer to lpfc hba data structure.
* @vpi: host virtual N_Port identifier.
*
@@ -5622,7 +5605,7 @@ lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi)
}
/**
- * lpfc_els_unsol_event: Process an unsolicited event from an els sli ring.
+ * lpfc_els_unsol_event - Process an unsolicited event from an els sli ring
* @phba: pointer to lpfc hba data structure.
* @pring: pointer to a SLI ring.
* @elsiocb: pointer to lpfc els iocb data structure.
@@ -5710,7 +5693,7 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
/**
- * lpfc_do_scr_ns_plogi: Issue a plogi to the name server for scr.
+ * lpfc_do_scr_ns_plogi - Issue a plogi to the name server for scr
* @phba: pointer to lpfc hba data structure.
* @vport: pointer to a virtual N_Port data structure.
*
@@ -5781,7 +5764,7 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
}
/**
- * lpfc_cmpl_reg_new_vport: Completion callback function to register new vport.
+ * lpfc_cmpl_reg_new_vport - Completion callback function to register new vport
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
@@ -5850,7 +5833,7 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
}
/**
- * lpfc_register_new_vport: Register a new vport with a HBA.
+ * lpfc_register_new_vport - Register a new vport with a HBA
* @phba: pointer to lpfc hba data structure.
* @vport: pointer to a host virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
@@ -5899,7 +5882,7 @@ mbox_err_exit:
}
/**
- * lpfc_cmpl_els_fdisc: Completion function for fdisc iocb command.
+ * lpfc_cmpl_els_fdisc - Completion function for fdisc iocb command
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
@@ -6007,7 +5990,7 @@ out:
}
/**
- * lpfc_issue_els_fdisc: Issue a fdisc iocb command.
+ * lpfc_issue_els_fdisc - Issue a fdisc iocb command
* @vport: pointer to a virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @retry: number of retries to the command IOCB.
@@ -6101,7 +6084,7 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
}
/**
- * lpfc_cmpl_els_npiv_logo: Completion function with vport logo.
+ * lpfc_cmpl_els_npiv_logo - Completion function with vport logo
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
@@ -6136,7 +6119,7 @@ lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
}
/**
- * lpfc_issue_els_npiv_logo: Issue a logo off a vport.
+ * lpfc_issue_els_npiv_logo - Issue a logo off a vport
* @vport: pointer to a virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
*
@@ -6197,7 +6180,7 @@ lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
}
/**
- * lpfc_fabric_block_timeout: Handler function to the fabric block timer.
+ * lpfc_fabric_block_timeout - Handler function to the fabric block timer
* @ptr: holder for the timer function associated data.
*
* This routine is invoked by the fabric iocb block timer after
@@ -6226,7 +6209,7 @@ lpfc_fabric_block_timeout(unsigned long ptr)
}
/**
- * lpfc_resume_fabric_iocbs: Issue a fabric iocb from driver internal list.
+ * lpfc_resume_fabric_iocbs - Issue a fabric iocb from driver internal list
* @phba: pointer to lpfc hba data structure.
*
* This routine issues one fabric iocb from the driver internal list to
@@ -6285,7 +6268,7 @@ repeat:
}
/**
- * lpfc_unblock_fabric_iocbs: Unblock issuing fabric iocb command.
+ * lpfc_unblock_fabric_iocbs - Unblock issuing fabric iocb command
* @phba: pointer to lpfc hba data structure.
*
* This routine unblocks the issuing fabric iocb command. The function
@@ -6303,7 +6286,7 @@ lpfc_unblock_fabric_iocbs(struct lpfc_hba *phba)
}
/**
- * lpfc_block_fabric_iocbs: Block issuing fabric iocb command.
+ * lpfc_block_fabric_iocbs - Block issuing fabric iocb command
* @phba: pointer to lpfc hba data structure.
*
* This routine blocks the issuing fabric iocb for a specified amount of
@@ -6325,7 +6308,7 @@ lpfc_block_fabric_iocbs(struct lpfc_hba *phba)
}
/**
- * lpfc_cmpl_fabric_iocb: Completion callback function for fabric iocb.
+ * lpfc_cmpl_fabric_iocb - Completion callback function for fabric iocb
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
@@ -6384,7 +6367,7 @@ lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
}
/**
- * lpfc_issue_fabric_iocb: Issue a fabric iocb command.
+ * lpfc_issue_fabric_iocb - Issue a fabric iocb command
* @phba: pointer to lpfc hba data structure.
* @iocb: pointer to lpfc command iocb data structure.
*
@@ -6453,7 +6436,7 @@ lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb)
}
/**
- * lpfc_fabric_abort_vport: Abort a vport's iocbs from driver fabric iocb list.
+ * lpfc_fabric_abort_vport - Abort a vport's iocbs from driver fabric iocb list
* @vport: pointer to a virtual N_Port data structure.
*
* This routine aborts all the IOCBs associated with a @vport from the
@@ -6468,7 +6451,6 @@ static void lpfc_fabric_abort_vport(struct lpfc_vport *vport)
LIST_HEAD(completions);
struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *tmp_iocb, *piocb;
- IOCB_t *cmd;
spin_lock_irq(&phba->hbalock);
list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
@@ -6481,19 +6463,13 @@ static void lpfc_fabric_abort_vport(struct lpfc_vport *vport)
}
spin_unlock_irq(&phba->hbalock);
- while (!list_empty(&completions)) {
- piocb = list_get_first(&completions, struct lpfc_iocbq, list);
- list_del_init(&piocb->list);
-
- cmd = &piocb->iocb;
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
- (piocb->iocb_cmpl) (phba, piocb, piocb);
- }
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
}
/**
- * lpfc_fabric_abort_nport: Abort a ndlp's iocbs from driver fabric iocb list.
+ * lpfc_fabric_abort_nport - Abort a ndlp's iocbs from driver fabric iocb list
* @ndlp: pointer to a node-list data structure.
*
* This routine aborts all the IOCBs associated with an @ndlp from the
@@ -6506,10 +6482,9 @@ static void lpfc_fabric_abort_vport(struct lpfc_vport *vport)
void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp)
{
LIST_HEAD(completions);
- struct lpfc_hba *phba = ndlp->vport->phba;
+ struct lpfc_hba *phba = ndlp->phba;
struct lpfc_iocbq *tmp_iocb, *piocb;
struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
- IOCB_t *cmd;
spin_lock_irq(&phba->hbalock);
list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
@@ -6521,19 +6496,13 @@ void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp)
}
spin_unlock_irq(&phba->hbalock);
- while (!list_empty(&completions)) {
- piocb = list_get_first(&completions, struct lpfc_iocbq, list);
- list_del_init(&piocb->list);
-
- cmd = &piocb->iocb;
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
- (piocb->iocb_cmpl) (phba, piocb, piocb);
- }
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
}
/**
- * lpfc_fabric_abort_hba: Abort all iocbs on driver fabric iocb list.
+ * lpfc_fabric_abort_hba - Abort all iocbs on driver fabric iocb list
* @phba: pointer to lpfc hba data structure.
*
* This routine aborts all the IOCBs currently on the driver internal
@@ -6546,20 +6515,12 @@ void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp)
void lpfc_fabric_abort_hba(struct lpfc_hba *phba)
{
LIST_HEAD(completions);
- struct lpfc_iocbq *piocb;
- IOCB_t *cmd;
spin_lock_irq(&phba->hbalock);
list_splice_init(&phba->fabric_iocb_list, &completions);
spin_unlock_irq(&phba->hbalock);
- while (!list_empty(&completions)) {
- piocb = list_get_first(&completions, struct lpfc_iocbq, list);
- list_del_init(&piocb->list);
-
- cmd = &piocb->iocb;
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
- (piocb->iocb_cmpl) (phba, piocb, piocb);
- }
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
}
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 311ed6dea726..e764ce0bf704 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -78,7 +78,7 @@ lpfc_terminate_rport_io(struct fc_rport *rport)
return;
}
- phba = ndlp->vport->phba;
+ phba = ndlp->phba;
lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_RPORT,
"rport terminate: sid:x%x did:x%x flg:x%x",
@@ -276,7 +276,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
}
/**
- * lpfc_alloc_fast_evt: Allocates data structure for posting event.
+ * lpfc_alloc_fast_evt - Allocates data structure for posting event
* @phba: Pointer to hba context object.
*
* This function is called from the functions which need to post
@@ -303,7 +303,7 @@ lpfc_alloc_fast_evt(struct lpfc_hba *phba) {
}
/**
- * lpfc_free_fast_evt: Frees event data structure.
+ * lpfc_free_fast_evt - Frees event data structure
* @phba: Pointer to hba context object.
* @evt: Event object which need to be freed.
*
@@ -319,7 +319,7 @@ lpfc_free_fast_evt(struct lpfc_hba *phba,
}
/**
- * lpfc_send_fastpath_evt: Posts events generated from fast path.
+ * lpfc_send_fastpath_evt - Posts events generated from fast path
* @phba: Pointer to hba context object.
* @evtp: Event data structure.
*
@@ -1858,13 +1858,18 @@ lpfc_disable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
NLP_STE_UNUSED_NODE);
}
/**
- * lpfc_initialize_node: Initialize all fields of node object.
+ * lpfc_initialize_node - Initialize all fields of node object
* @vport: Pointer to Virtual Port object.
* @ndlp: Pointer to FC node object.
* @did: FC_ID of the node.
- * This function is always called when node object need to
- * be initialized. It initializes all the fields of the node
- * object.
+ *
+ * This function is always called when node object need to be initialized.
+ * It initializes all the fields of the node object. Although the reference
+ * to phba from @ndlp can be obtained indirectly through it's reference to
+ * @vport, a direct reference to phba is taken here by @ndlp. This is due
+ * to the life-span of the @ndlp might go beyond the existence of @vport as
+ * the final release of ndlp is determined by its reference count. And, the
+ * operation on @ndlp needs the reference to phba.
**/
static inline void
lpfc_initialize_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
@@ -1877,6 +1882,7 @@ lpfc_initialize_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
ndlp->nlp_delayfunc.data = (unsigned long)ndlp;
ndlp->nlp_DID = did;
ndlp->vport = vport;
+ ndlp->phba = vport->phba;
ndlp->nlp_sid = NLP_NO_SID;
kref_init(&ndlp->kref);
NLP_INT_NODE_ACT(ndlp);
@@ -2086,7 +2092,6 @@ lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
struct lpfc_sli *psli;
struct lpfc_sli_ring *pring;
struct lpfc_iocbq *iocb, *next_iocb;
- IOCB_t *icmd;
uint32_t rpi, i;
lpfc_fabric_abort_nport(ndlp);
@@ -2122,19 +2127,9 @@ lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
}
}
- while (!list_empty(&completions)) {
- iocb = list_get_first(&completions, struct lpfc_iocbq, list);
- list_del_init(&iocb->list);
-
- if (!iocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, iocb);
- else {
- icmd = &iocb->iocb;
- icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
- (iocb->iocb_cmpl)(phba, iocb, iocb);
- }
- }
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
return 0;
}
@@ -2186,9 +2181,13 @@ lpfc_unreg_all_rpis(struct lpfc_vport *vport)
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
mbox->context1 = NULL;
rc = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
- if (rc == MBX_NOT_FINISHED) {
+ if (rc != MBX_TIMEOUT)
mempool_free(mbox, phba->mbox_mem_pool);
- }
+
+ if ((rc == MBX_TIMEOUT) || (rc == MBX_NOT_FINISHED))
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX | LOG_VPORT,
+ "1836 Could not issue "
+ "unreg_login(all_rpis) status %d\n", rc);
}
}
@@ -2206,12 +2205,14 @@ lpfc_unreg_default_rpis(struct lpfc_vport *vport)
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
mbox->context1 = NULL;
rc = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
- if (rc == MBX_NOT_FINISHED) {
+ if (rc != MBX_TIMEOUT)
+ mempool_free(mbox, phba->mbox_mem_pool);
+
+ if ((rc == MBX_TIMEOUT) || (rc == MBX_NOT_FINISHED))
lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX | LOG_VPORT,
"1815 Could not issue "
- "unreg_did (default rpis)\n");
- mempool_free(mbox, phba->mbox_mem_pool);
- }
+ "unreg_did (default rpis) status %d\n",
+ rc);
}
}
@@ -2470,14 +2471,13 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did)
if (ndlp->nlp_flag & NLP_RCV_PLOGI)
return NULL;
- spin_lock_irq(shost->host_lock);
- ndlp->nlp_flag |= NLP_NPR_2B_DISC;
- spin_unlock_irq(shost->host_lock);
-
/* Since this node is marked for discovery,
* delay timeout is not needed.
*/
lpfc_cancel_retry_delay_tmo(vport, ndlp);
+ spin_lock_irq(shost->host_lock);
+ ndlp->nlp_flag |= NLP_NPR_2B_DISC;
+ spin_unlock_irq(shost->host_lock);
} else
ndlp = NULL;
} else {
@@ -2740,19 +2740,9 @@ lpfc_free_tx(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
}
spin_unlock_irq(&phba->hbalock);
- while (!list_empty(&completions)) {
- iocb = list_get_first(&completions, struct lpfc_iocbq, list);
- list_del_init(&iocb->list);
-
- if (!iocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, iocb);
- else {
- icmd = &iocb->iocb;
- icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
- (iocb->iocb_cmpl) (phba, iocb, iocb);
- }
- }
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
}
static void
@@ -3173,7 +3163,7 @@ lpfc_nlp_release(struct kref *kref)
lpfc_nlp_remove(ndlp->vport, ndlp);
/* clear the ndlp active flag for all release cases */
- phba = ndlp->vport->phba;
+ phba = ndlp->phba;
spin_lock_irqsave(&phba->ndlp_lock, flags);
NLP_CLR_NODE_ACT(ndlp);
spin_unlock_irqrestore(&phba->ndlp_lock, flags);
@@ -3181,7 +3171,7 @@ lpfc_nlp_release(struct kref *kref)
/* free ndlp memory for final ndlp release */
if (NLP_CHK_FREE_REQ(ndlp)) {
kfree(ndlp->lat_data);
- mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool);
+ mempool_free(ndlp, ndlp->phba->nlp_mem_pool);
}
}
@@ -3204,7 +3194,7 @@ lpfc_nlp_get(struct lpfc_nodelist *ndlp)
* ndlp reference count that is in the process of being
* released.
*/
- phba = ndlp->vport->phba;
+ phba = ndlp->phba;
spin_lock_irqsave(&phba->ndlp_lock, flags);
if (!NLP_CHK_NODE_ACT(ndlp) || NLP_CHK_FREE_ACK(ndlp)) {
spin_unlock_irqrestore(&phba->ndlp_lock, flags);
@@ -3240,7 +3230,7 @@ lpfc_nlp_put(struct lpfc_nodelist *ndlp)
"node put: did:x%x flg:x%x refcnt:x%x",
ndlp->nlp_DID, ndlp->nlp_flag,
atomic_read(&ndlp->kref.refcount));
- phba = ndlp->vport->phba;
+ phba = ndlp->phba;
spin_lock_irqsave(&phba->ndlp_lock, flags);
/* Check the ndlp memory free acknowledge flag to avoid the
* possible race condition that kref_put got invoked again
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 06874e6009ea..86d1bdcbf2d8 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -60,7 +60,7 @@ static struct scsi_transport_template *lpfc_vport_transport_template = NULL;
static DEFINE_IDR(lpfc_hba_index);
/**
- * lpfc_config_port_prep: Perform lpfc initialization prior to config port.
+ * lpfc_config_port_prep - Perform lpfc initialization prior to config port
* @phba: pointer to lpfc hba data structure.
*
* This routine will do LPFC initialization prior to issuing the CONFIG_PORT
@@ -221,7 +221,7 @@ out_free_mbox:
}
/**
- * lpfc_config_async_cmpl: Completion handler for config async event mbox cmd.
+ * lpfc_config_async_cmpl - Completion handler for config async event mbox cmd
* @phba: pointer to lpfc hba data structure.
* @pmboxq: pointer to the driver internal queue element for mailbox command.
*
@@ -242,8 +242,7 @@ lpfc_config_async_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
}
/**
- * lpfc_dump_wakeup_param_cmpl: Completion handler for dump memory mailbox
- * command used for getting wake up parameters.
+ * lpfc_dump_wakeup_param_cmpl - dump memory mailbox command completion handler
* @phba: pointer to lpfc hba data structure.
* @pmboxq: pointer to the driver internal queue element for mailbox command.
*
@@ -287,7 +286,7 @@ lpfc_dump_wakeup_param_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
}
/**
- * lpfc_config_port_post: Perform lpfc initialization after config port.
+ * lpfc_config_port_post - Perform lpfc initialization after config port
* @phba: pointer to lpfc hba data structure.
*
* This routine will do LPFC initialization after the CONFIG_PORT mailbox
@@ -303,6 +302,7 @@ int
lpfc_config_port_post(struct lpfc_hba *phba)
{
struct lpfc_vport *vport = phba->pport;
+ struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
LPFC_MBOXQ_t *pmb;
MAILBOX_t *mb;
struct lpfc_dmabuf *mp;
@@ -360,6 +360,11 @@ lpfc_config_port_post(struct lpfc_hba *phba)
sizeof (struct lpfc_name));
memcpy(&vport->fc_portname, &vport->fc_sparam.portName,
sizeof (struct lpfc_name));
+
+ /* Update the fc_host data structures with new wwn. */
+ fc_host_node_name(shost) = wwn_to_u64(vport->fc_nodename.u.wwn);
+ fc_host_port_name(shost) = wwn_to_u64(vport->fc_portname.u.wwn);
+
/* If no serial number in VPD data, use low 6 bytes of WWNN */
/* This should be consolidated into parse_vpd ? - mr */
if (phba->SerialNumber[0] == 0) {
@@ -551,7 +556,7 @@ lpfc_config_port_post(struct lpfc_hba *phba)
}
/**
- * lpfc_hba_down_prep: Perform lpfc uninitialization prior to HBA reset.
+ * lpfc_hba_down_prep - Perform lpfc uninitialization prior to HBA reset
* @phba: pointer to lpfc HBA data structure.
*
* This routine will do LPFC uninitialization before the HBA is reset when
@@ -583,7 +588,7 @@ lpfc_hba_down_prep(struct lpfc_hba *phba)
}
/**
- * lpfc_hba_down_post: Perform lpfc uninitialization after HBA reset.
+ * lpfc_hba_down_post - Perform lpfc uninitialization after HBA reset
* @phba: pointer to lpfc HBA data structure.
*
* This routine will do uninitialization after the HBA is reset when bring
@@ -599,8 +604,6 @@ lpfc_hba_down_post(struct lpfc_hba *phba)
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring;
struct lpfc_dmabuf *mp, *next_mp;
- struct lpfc_iocbq *iocb;
- IOCB_t *cmd = NULL;
LIST_HEAD(completions);
int i;
@@ -628,20 +631,9 @@ lpfc_hba_down_post(struct lpfc_hba *phba)
pring->txcmplq_cnt = 0;
spin_unlock_irq(&phba->hbalock);
- while (!list_empty(&completions)) {
- iocb = list_get_first(&completions, struct lpfc_iocbq,
- list);
- cmd = &iocb->iocb;
- list_del_init(&iocb->list);
-
- if (!iocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, iocb);
- else {
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
- (iocb->iocb_cmpl) (phba, iocb, iocb);
- }
- }
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
lpfc_sli_abort_iocb_ring(phba, pring);
spin_lock_irq(&phba->hbalock);
@@ -652,7 +644,7 @@ lpfc_hba_down_post(struct lpfc_hba *phba)
}
/**
- * lpfc_hb_timeout: The HBA-timer timeout handler.
+ * lpfc_hb_timeout - The HBA-timer timeout handler
* @ptr: unsigned long holds the pointer to lpfc hba data structure.
*
* This is the HBA-timer timeout handler registered to the lpfc driver. When
@@ -686,7 +678,7 @@ lpfc_hb_timeout(unsigned long ptr)
}
/**
- * lpfc_hb_mbox_cmpl: The lpfc heart-beat mailbox command callback function.
+ * lpfc_hb_mbox_cmpl - The lpfc heart-beat mailbox command callback function
* @phba: pointer to lpfc hba data structure.
* @pmboxq: pointer to the driver internal queue element for mailbox command.
*
@@ -721,7 +713,7 @@ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
}
/**
- * lpfc_hb_timeout_handler: The HBA-timer timeout handler.
+ * lpfc_hb_timeout_handler - The HBA-timer timeout handler
* @phba: pointer to lpfc hba data structure.
*
* This is the actual HBA-timer timeout handler to be invoked by the worker
@@ -830,7 +822,7 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
}
/**
- * lpfc_offline_eratt: Bring lpfc offline on hardware error attention.
+ * lpfc_offline_eratt - Bring lpfc offline on hardware error attention
* @phba: pointer to lpfc hba data structure.
*
* This routine is called to bring the HBA offline when HBA hardware error
@@ -857,7 +849,73 @@ lpfc_offline_eratt(struct lpfc_hba *phba)
}
/**
- * lpfc_handle_eratt: The HBA hardware error handler.
+ * lpfc_handle_deferred_eratt - The HBA hardware deferred error handler
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is invoked to handle the deferred HBA hardware error
+ * conditions. This type of error is indicated by HBA by setting ER1
+ * and another ER bit in the host status register. The driver will
+ * wait until the ER1 bit clears before handling the error condition.
+ **/
+static void
+lpfc_handle_deferred_eratt(struct lpfc_hba *phba)
+{
+ uint32_t old_host_status = phba->work_hs;
+ struct lpfc_sli_ring *pring;
+ struct lpfc_sli *psli = &phba->sli;
+
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "0479 Deferred Adapter Hardware Error "
+ "Data: x%x x%x x%x\n",
+ phba->work_hs,
+ phba->work_status[0], phba->work_status[1]);
+
+ spin_lock_irq(&phba->hbalock);
+ psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+ spin_unlock_irq(&phba->hbalock);
+
+
+ /*
+ * Firmware stops when it triggred erratt. That could cause the I/Os
+ * dropped by the firmware. Error iocb (I/O) on txcmplq and let the
+ * SCSI layer retry it after re-establishing link.
+ */
+ pring = &psli->ring[psli->fcp_ring];
+ lpfc_sli_abort_iocb_ring(phba, pring);
+
+ /*
+ * There was a firmware error. Take the hba offline and then
+ * attempt to restart it.
+ */
+ lpfc_offline_prep(phba);
+ lpfc_offline(phba);
+
+ /* Wait for the ER1 bit to clear.*/
+ while (phba->work_hs & HS_FFER1) {
+ msleep(100);
+ phba->work_hs = readl(phba->HSregaddr);
+ /* If driver is unloading let the worker thread continue */
+ if (phba->pport->load_flag & FC_UNLOADING) {
+ phba->work_hs = 0;
+ break;
+ }
+ }
+
+ /*
+ * This is to ptrotect against a race condition in which
+ * first write to the host attention register clear the
+ * host status register.
+ */
+ if ((!phba->work_hs) && (!(phba->pport->load_flag & FC_UNLOADING)))
+ phba->work_hs = old_host_status & ~HS_FFER1;
+
+ phba->hba_flag &= ~DEFER_ERATT;
+ phba->work_status[0] = readl(phba->MBslimaddr + 0xa8);
+ phba->work_status[1] = readl(phba->MBslimaddr + 0xac);
+}
+
+/**
+ * lpfc_handle_eratt - The HBA hardware error handler
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked to handle the following HBA hardware error
@@ -895,6 +953,9 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
(char *) &board_event,
LPFC_NL_VENDOR_ID);
+ if (phba->hba_flag & DEFER_ERATT)
+ lpfc_handle_deferred_eratt(phba);
+
if (phba->work_hs & HS_FFER6) {
/* Re-establishing Link */
lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
@@ -976,7 +1037,7 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
}
/**
- * lpfc_handle_latt: The HBA link event handler.
+ * lpfc_handle_latt - The HBA link event handler
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked from the worker thread to handle a HBA host
@@ -1063,7 +1124,7 @@ lpfc_handle_latt_err_exit:
}
/**
- * lpfc_parse_vpd: Parse VPD (Vital Product Data).
+ * lpfc_parse_vpd - Parse VPD (Vital Product Data)
* @phba: pointer to lpfc hba data structure.
* @vpd: pointer to the vital product data.
* @len: length of the vital product data in bytes.
@@ -1213,7 +1274,7 @@ lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len)
}
/**
- * lpfc_get_hba_model_desc: Retrieve HBA device model name and description.
+ * lpfc_get_hba_model_desc - Retrieve HBA device model name and description
* @phba: pointer to lpfc hba data structure.
* @mdp: pointer to the data structure to hold the derived model name.
* @descp: pointer to the data structure to hold the derived description.
@@ -1322,7 +1383,8 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
m = (typeof(m)){"LPe11000", max_speed, "PCIe"};
break;
case PCI_DEVICE_ID_ZEPHYR_DCSP:
- m = (typeof(m)){"LPe11002-SP", max_speed, "PCIe"};
+ m = (typeof(m)){"LP2105", max_speed, "PCIe"};
+ GE = 1;
break;
case PCI_DEVICE_ID_ZMID:
m = (typeof(m)){"LPe1150", max_speed, "PCIe"};
@@ -1392,7 +1454,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
}
/**
- * lpfc_post_buffer: Post IOCB(s) with DMA buffer descriptor(s) to a IOCB ring.
+ * lpfc_post_buffer - Post IOCB(s) with DMA buffer descriptor(s) to a IOCB ring
* @phba: pointer to lpfc hba data structure.
* @pring: pointer to a IOCB ring.
* @cnt: the number of IOCBs to be posted to the IOCB ring.
@@ -1493,7 +1555,7 @@ lpfc_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt)
}
/**
- * lpfc_post_rcv_buf: Post the initial receive IOCB buffers to ELS ring.
+ * lpfc_post_rcv_buf - Post the initial receive IOCB buffers to ELS ring
* @phba: pointer to lpfc hba data structure.
*
* This routine posts initial receive IOCB buffers to the ELS ring. The
@@ -1518,7 +1580,7 @@ lpfc_post_rcv_buf(struct lpfc_hba *phba)
#define S(N,V) (((V)<<(N))|((V)>>(32-(N))))
/**
- * lpfc_sha_init: Set up initial array of hash table entries.
+ * lpfc_sha_init - Set up initial array of hash table entries
* @HashResultPointer: pointer to an array as hash table.
*
* This routine sets up the initial values to the array of hash table entries
@@ -1535,7 +1597,7 @@ lpfc_sha_init(uint32_t * HashResultPointer)
}
/**
- * lpfc_sha_iterate: Iterate initial hash table with the working hash table.
+ * lpfc_sha_iterate - Iterate initial hash table with the working hash table
* @HashResultPointer: pointer to an initial/result hash table.
* @HashWorkingPointer: pointer to an working hash table.
*
@@ -1592,7 +1654,7 @@ lpfc_sha_iterate(uint32_t * HashResultPointer, uint32_t * HashWorkingPointer)
}
/**
- * lpfc_challenge_key: Create challenge key based on WWPN of the HBA.
+ * lpfc_challenge_key - Create challenge key based on WWPN of the HBA
* @RandomChallenge: pointer to the entry of host challenge random number array.
* @HashWorking: pointer to the entry of the working hash array.
*
@@ -1608,7 +1670,7 @@ lpfc_challenge_key(uint32_t * RandomChallenge, uint32_t * HashWorking)
}
/**
- * lpfc_hba_init: Perform special handling for LC HBA initialization.
+ * lpfc_hba_init - Perform special handling for LC HBA initialization
* @phba: pointer to lpfc hba data structure.
* @hbainit: pointer to an array of unsigned 32-bit integers.
*
@@ -1637,7 +1699,7 @@ lpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit)
}
/**
- * lpfc_cleanup: Performs vport cleanups before deleting a vport.
+ * lpfc_cleanup - Performs vport cleanups before deleting a vport
* @vport: pointer to a virtual N_Port data structure.
*
* This routine performs the necessary cleanups before deleting the @vport.
@@ -1724,7 +1786,7 @@ lpfc_cleanup(struct lpfc_vport *vport)
}
/**
- * lpfc_stop_vport_timers: Stop all the timers associated with a vport.
+ * lpfc_stop_vport_timers - Stop all the timers associated with a vport
* @vport: pointer to a virtual N_Port data structure.
*
* This routine stops all the timers associated with a @vport. This function
@@ -1741,7 +1803,7 @@ lpfc_stop_vport_timers(struct lpfc_vport *vport)
}
/**
- * lpfc_stop_phba_timers: Stop all the timers associated with an HBA.
+ * lpfc_stop_phba_timers - Stop all the timers associated with an HBA
* @phba: pointer to lpfc hba data structure.
*
* This routine stops all the timers associated with a HBA. This function is
@@ -1761,7 +1823,7 @@ lpfc_stop_phba_timers(struct lpfc_hba *phba)
}
/**
- * lpfc_block_mgmt_io: Mark a HBA's management interface as blocked.
+ * lpfc_block_mgmt_io - Mark a HBA's management interface as blocked
* @phba: pointer to lpfc hba data structure.
*
* This routine marks a HBA's management interface as blocked. Once the HBA's
@@ -1781,7 +1843,7 @@ lpfc_block_mgmt_io(struct lpfc_hba * phba)
}
/**
- * lpfc_online: Initialize and bring a HBA online.
+ * lpfc_online - Initialize and bring a HBA online
* @phba: pointer to lpfc hba data structure.
*
* This routine initializes the HBA and brings a HBA online. During this
@@ -1839,7 +1901,7 @@ lpfc_online(struct lpfc_hba *phba)
}
/**
- * lpfc_unblock_mgmt_io: Mark a HBA's management interface to be not blocked.
+ * lpfc_unblock_mgmt_io - Mark a HBA's management interface to be not blocked
* @phba: pointer to lpfc hba data structure.
*
* This routine marks a HBA's management interface as not blocked. Once the
@@ -1860,7 +1922,7 @@ lpfc_unblock_mgmt_io(struct lpfc_hba * phba)
}
/**
- * lpfc_offline_prep: Prepare a HBA to be brought offline.
+ * lpfc_offline_prep - Prepare a HBA to be brought offline
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked to prepare a HBA to be brought offline. It performs
@@ -1917,7 +1979,7 @@ lpfc_offline_prep(struct lpfc_hba * phba)
}
/**
- * lpfc_offline: Bring a HBA offline.
+ * lpfc_offline - Bring a HBA offline
* @phba: pointer to lpfc hba data structure.
*
* This routine actually brings a HBA offline. It stops all the timers
@@ -1962,7 +2024,7 @@ lpfc_offline(struct lpfc_hba *phba)
}
/**
- * lpfc_scsi_free: Free all the SCSI buffers and IOCBs from driver lists.
+ * lpfc_scsi_free - Free all the SCSI buffers and IOCBs from driver lists
* @phba: pointer to lpfc hba data structure.
*
* This routine is to free all the SCSI buffers and IOCBs from the driver
@@ -2001,7 +2063,7 @@ lpfc_scsi_free(struct lpfc_hba *phba)
}
/**
- * lpfc_create_port: Create an FC port.
+ * lpfc_create_port - Create an FC port
* @phba: pointer to lpfc hba data structure.
* @instance: a unique integer ID to this FC port.
* @dev: pointer to the device data structure.
@@ -2091,7 +2153,7 @@ out:
}
/**
- * destroy_port: Destroy an FC port.
+ * destroy_port - destroy an FC port
* @vport: pointer to an lpfc virtual N_Port data structure.
*
* This routine destroys a FC port from the upper layer protocol. All the
@@ -2116,7 +2178,7 @@ destroy_port(struct lpfc_vport *vport)
}
/**
- * lpfc_get_instance: Get a unique integer ID.
+ * lpfc_get_instance - Get a unique integer ID
*
* This routine allocates a unique integer ID from lpfc_hba_index pool. It
* uses the kernel idr facility to perform the task.
@@ -2139,7 +2201,7 @@ lpfc_get_instance(void)
}
/**
- * lpfc_scan_finished: method for SCSI layer to detect whether scan is done.
+ * lpfc_scan_finished - method for SCSI layer to detect whether scan is done
* @shost: pointer to SCSI host data structure.
* @time: elapsed time of the scan in jiffies.
*
@@ -2197,7 +2259,7 @@ finished:
}
/**
- * lpfc_host_attrib_init: Initialize SCSI host attributes on a FC port.
+ * lpfc_host_attrib_init - Initialize SCSI host attributes on a FC port
* @shost: pointer to SCSI host data structure.
*
* This routine initializes a given SCSI host attributes on a FC port. The
@@ -2252,7 +2314,7 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost)
}
/**
- * lpfc_enable_msix: Enable MSI-X interrupt mode.
+ * lpfc_enable_msix - Enable MSI-X interrupt mode
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked to enable the MSI-X interrupt vectors. The kernel
@@ -2366,7 +2428,7 @@ msi_fail_out:
}
/**
- * lpfc_disable_msix: Disable MSI-X interrupt mode.
+ * lpfc_disable_msix - Disable MSI-X interrupt mode
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked to release the MSI-X vectors and then disable the
@@ -2385,7 +2447,7 @@ lpfc_disable_msix(struct lpfc_hba *phba)
}
/**
- * lpfc_enable_msi: Enable MSI interrupt mode.
+ * lpfc_enable_msi - Enable MSI interrupt mode
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked to enable the MSI interrupt mode. The kernel
@@ -2423,7 +2485,7 @@ lpfc_enable_msi(struct lpfc_hba *phba)
}
/**
- * lpfc_disable_msi: Disable MSI interrupt mode.
+ * lpfc_disable_msi - Disable MSI interrupt mode
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked to disable the MSI interrupt mode. The driver
@@ -2441,7 +2503,7 @@ lpfc_disable_msi(struct lpfc_hba *phba)
}
/**
- * lpfc_log_intr_mode: Log the active interrupt mode
+ * lpfc_log_intr_mode - Log the active interrupt mode
* @phba: pointer to lpfc hba data structure.
* @intr_mode: active interrupt mode adopted.
*
@@ -2490,7 +2552,7 @@ lpfc_stop_port(struct lpfc_hba *phba)
}
/**
- * lpfc_enable_intr: Enable device interrupt.
+ * lpfc_enable_intr - Enable device interrupt
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked to enable device interrupt and associate driver's
@@ -2547,7 +2609,7 @@ lpfc_enable_intr(struct lpfc_hba *phba, uint32_t cfg_mode)
}
/**
- * lpfc_disable_intr: Disable device interrupt.
+ * lpfc_disable_intr - Disable device interrupt
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked to disable device interrupt and disassociate the
@@ -2574,7 +2636,7 @@ lpfc_disable_intr(struct lpfc_hba *phba)
}
/**
- * lpfc_pci_probe_one: lpfc PCI probe func to register device to PCI subsystem.
+ * lpfc_pci_probe_one - lpfc PCI probe func to register device to PCI subsystem
* @pdev: pointer to PCI device
* @pid: pointer to PCI device identifier
*
@@ -3010,7 +3072,7 @@ out:
}
/**
- * lpfc_pci_remove_one: lpfc PCI func to unregister device from PCI subsystem.
+ * lpfc_pci_remove_one - lpfc PCI func to unregister device from PCI subsystem
* @pdev: pointer to PCI device
*
* This routine is to be registered to the kernel's PCI subsystem. When an
@@ -3033,8 +3095,6 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
lpfc_free_sysfs_attr(vport);
- kthread_stop(phba->worker_thread);
-
/* Release all the vports against this physical port */
vports = lpfc_create_vport_work_array(phba);
if (vports != NULL)
@@ -3052,7 +3112,12 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
* clears the rings, discards all mailbox commands, and resets
* the HBA.
*/
+
+ /* HBA interrupt will be diabled after this call */
lpfc_sli_hba_down(phba);
+ /* Stop kthread signal shall trigger work_done one more time */
+ kthread_stop(phba->worker_thread);
+ /* Final cleanup of txcmplq and reset the HBA */
lpfc_sli_brdrestart(phba);
lpfc_stop_phba_timers(phba);
@@ -3095,7 +3160,7 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
}
/**
- * lpfc_pci_suspend_one: lpfc PCI func to suspend device for power management.
+ * lpfc_pci_suspend_one - lpfc PCI func to suspend device for power management
* @pdev: pointer to PCI device
* @msg: power management message
*
@@ -3139,7 +3204,7 @@ lpfc_pci_suspend_one(struct pci_dev *pdev, pm_message_t msg)
}
/**
- * lpfc_pci_resume_one: lpfc PCI func to resume device for power management.
+ * lpfc_pci_resume_one - lpfc PCI func to resume device for power management
* @pdev: pointer to PCI device
*
* This routine is to be registered to the kernel's PCI subsystem to support
@@ -3204,7 +3269,7 @@ lpfc_pci_resume_one(struct pci_dev *pdev)
}
/**
- * lpfc_io_error_detected: Driver method for handling PCI I/O error detected.
+ * lpfc_io_error_detected - Driver method for handling PCI I/O error detected
* @pdev: pointer to PCI device.
* @state: the current PCI connection state.
*
@@ -3254,7 +3319,7 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev,
}
/**
- * lpfc_io_slot_reset: Restart a PCI device from scratch.
+ * lpfc_io_slot_reset - Restart a PCI device from scratch
* @pdev: pointer to PCI device.
*
* This routine is registered to the PCI subsystem for error handling. This is
@@ -3313,7 +3378,7 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
}
/**
- * lpfc_io_resume: Resume PCI I/O operation.
+ * lpfc_io_resume - Resume PCI I/O operation
* @pdev: pointer to PCI device
*
* This routine is registered to the PCI subsystem for error handling. It is
@@ -3426,7 +3491,7 @@ static struct pci_driver lpfc_driver = {
};
/**
- * lpfc_init: lpfc module initialization routine.
+ * lpfc_init - lpfc module initialization routine
*
* This routine is to be invoked when the lpfc module is loaded into the
* kernel. The special kernel macro module_init() is used to indicate the
@@ -3472,7 +3537,7 @@ lpfc_init(void)
}
/**
- * lpfc_exit: lpfc module removal routine.
+ * lpfc_exit - lpfc module removal routine
*
* This routine is invoked when the lpfc module is removed from the kernel.
* The special kernel macro module_exit() is used to indicate the role of
diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h
index a85b7c196bbc..1aa85709b012 100644
--- a/drivers/scsi/lpfc/lpfc_logmsg.h
+++ b/drivers/scsi/lpfc/lpfc_logmsg.h
@@ -27,7 +27,7 @@
#define LOG_FCP 0x40 /* FCP traffic history */
#define LOG_NODE 0x80 /* Node table events */
#define LOG_TEMP 0x100 /* Temperature sensor events */
-#define LOG_BG 0x200 /* BlockBuard events */
+#define LOG_BG 0x200 /* BlockGuard events */
#define LOG_MISC 0x400 /* Miscellaneous events */
#define LOG_SLI 0x800 /* SLI events */
#define LOG_FCP_ERROR 0x1000 /* log errors, not underruns */
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index 34eeb086a667..134fc7fc2127 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -39,7 +39,7 @@
#include "lpfc_compat.h"
/**
- * lpfc_dump_mem: Prepare a mailbox command for retrieving HBA's VPD memory.
+ * lpfc_dump_mem - Prepare a mailbox command for retrieving HBA's VPD memory
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
* @offset: offset for dumping VPD memory mailbox command.
@@ -77,9 +77,10 @@ lpfc_dump_mem(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint16_t offset)
}
/**
- * lpfc_dump_mem: Prepare a mailbox command for retrieving wakeup params.
+ * lpfc_dump_wakeup_param - Prepare mailbox command for retrieving wakeup params
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
+ *
* This function create a dump memory mailbox command to dump wake up
* parameters.
*/
@@ -109,7 +110,7 @@ lpfc_dump_wakeup_param(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
}
/**
- * lpfc_read_nv: Prepare a mailbox command for reading HBA's NVRAM param.
+ * lpfc_read_nv - Prepare a mailbox command for reading HBA's NVRAM param
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
@@ -132,7 +133,7 @@ lpfc_read_nv(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
}
/**
- * lpfc_config_async: Prepare a mailbox command for enabling HBA async event.
+ * lpfc_config_async - Prepare a mailbox command for enabling HBA async event
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
* @ring: ring number for the asynchronous event to be configured.
@@ -159,7 +160,7 @@ lpfc_config_async(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb,
}
/**
- * lpfc_heart_beat: Prepare a mailbox command for heart beat.
+ * lpfc_heart_beat - Prepare a mailbox command for heart beat
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
@@ -184,7 +185,7 @@ lpfc_heart_beat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
}
/**
- * lpfc_read_la: Prepare a mailbox command for reading HBA link attention.
+ * lpfc_read_la - Prepare a mailbox command for reading HBA link attention
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
* @mp: DMA buffer memory for reading the link attention information into.
@@ -228,7 +229,7 @@ lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp)
}
/**
- * lpfc_clear_la: Prepare a mailbox command for clearing HBA link attention.
+ * lpfc_clear_la - Prepare a mailbox command for clearing HBA link attention
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
@@ -257,7 +258,7 @@ lpfc_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
}
/**
- * lpfc_config_link: Prepare a mailbox command for configuring link on a HBA.
+ * lpfc_config_link - Prepare a mailbox command for configuring link on a HBA
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
@@ -305,7 +306,7 @@ lpfc_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
}
/**
- * lpfc_config_msi: Prepare a mailbox command for configuring msi-x.
+ * lpfc_config_msi - Prepare a mailbox command for configuring msi-x
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
@@ -383,7 +384,7 @@ lpfc_config_msi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
}
/**
- * lpfc_init_link: Prepare a mailbox command for initialize link on a HBA.
+ * lpfc_init_link - Prepare a mailbox command for initialize link on a HBA
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
* @topology: the link topology for the link to be initialized to.
@@ -463,7 +464,7 @@ lpfc_init_link(struct lpfc_hba * phba,
}
/**
- * lpfc_read_sparam: Prepare a mailbox command for reading HBA parameters.
+ * lpfc_read_sparam - Prepare a mailbox command for reading HBA parameters
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
* @vpi: virtual N_Port identifier.
@@ -523,7 +524,7 @@ lpfc_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, int vpi)
}
/**
- * lpfc_unreg_did: Prepare a mailbox command for unregistering DID.
+ * lpfc_unreg_did - Prepare a mailbox command for unregistering DID
* @phba: pointer to lpfc hba data structure.
* @vpi: virtual N_Port identifier.
* @did: remote port identifier.
@@ -555,7 +556,7 @@ lpfc_unreg_did(struct lpfc_hba * phba, uint16_t vpi, uint32_t did,
}
/**
- * lpfc_read_config: Prepare a mailbox command for reading HBA configuration.
+ * lpfc_read_config - Prepare a mailbox command for reading HBA configuration
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
@@ -581,7 +582,7 @@ lpfc_read_config(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
}
/**
- * lpfc_read_lnk_stat: Prepare a mailbox command for reading HBA link stats.
+ * lpfc_read_lnk_stat - Prepare a mailbox command for reading HBA link stats
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
@@ -606,7 +607,7 @@ lpfc_read_lnk_stat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
}
/**
- * lpfc_reg_login: Prepare a mailbox command for registering remote login.
+ * lpfc_reg_login - Prepare a mailbox command for registering remote login
* @phba: pointer to lpfc hba data structure.
* @vpi: virtual N_Port identifier.
* @did: remote port identifier.
@@ -677,7 +678,7 @@ lpfc_reg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t did,
}
/**
- * lpfc_unreg_login: Prepare a mailbox command for unregistering remote login.
+ * lpfc_unreg_login - Prepare a mailbox command for unregistering remote login
* @phba: pointer to lpfc hba data structure.
* @vpi: virtual N_Port identifier.
* @rpi: remote port identifier
@@ -709,7 +710,7 @@ lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi,
}
/**
- * lpfc_reg_vpi: Prepare a mailbox command for registering vport identifier.
+ * lpfc_reg_vpi - Prepare a mailbox command for registering vport identifier
* @phba: pointer to lpfc hba data structure.
* @vpi: virtual N_Port identifier.
* @sid: Fibre Channel S_ID (N_Port_ID assigned to a virtual N_Port).
@@ -741,7 +742,7 @@ lpfc_reg_vpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t sid,
}
/**
- * lpfc_unreg_vpi: Prepare a mailbox command for unregistering vport id.
+ * lpfc_unreg_vpi - Prepare a mailbox command for unregistering vport id
* @phba: pointer to lpfc hba data structure.
* @vpi: virtual N_Port identifier.
* @pmb: pointer to the driver internal queue element for mailbox command.
@@ -771,7 +772,7 @@ lpfc_unreg_vpi(struct lpfc_hba *phba, uint16_t vpi, LPFC_MBOXQ_t *pmb)
}
/**
- * lpfc_config_pcb_setup: Set up IOCB rings in the Port Control Block (PCB)
+ * lpfc_config_pcb_setup - Set up IOCB rings in the Port Control Block (PCB)
* @phba: pointer to lpfc hba data structure.
*
* This routine sets up and initializes the IOCB rings in the Port Control
@@ -835,7 +836,7 @@ lpfc_config_pcb_setup(struct lpfc_hba * phba)
}
/**
- * lpfc_read_rev: Prepare a mailbox command for reading HBA revision.
+ * lpfc_read_rev - Prepare a mailbox command for reading HBA revision
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
@@ -861,7 +862,7 @@ lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
}
/**
- * lpfc_build_hbq_profile2: Set up the HBQ Selection Profile 2.
+ * lpfc_build_hbq_profile2 - Set up the HBQ Selection Profile 2
* @hbqmb: pointer to the HBQ configuration data structure in mailbox command.
* @hbq_desc: pointer to the HBQ selection profile descriptor.
*
@@ -880,7 +881,7 @@ lpfc_build_hbq_profile2(struct config_hbq_var *hbqmb,
}
/**
- * lpfc_build_hbq_profile3: Set up the HBQ Selection Profile 3.
+ * lpfc_build_hbq_profile3 - Set up the HBQ Selection Profile 3
* @hbqmb: pointer to the HBQ configuration data structure in mailbox command.
* @hbq_desc: pointer to the HBQ selection profile descriptor.
*
@@ -902,7 +903,7 @@ lpfc_build_hbq_profile3(struct config_hbq_var *hbqmb,
}
/**
- * lpfc_build_hbq_profile5: Set up the HBQ Selection Profile 5.
+ * lpfc_build_hbq_profile5 - Set up the HBQ Selection Profile 5
* @hbqmb: pointer to the HBQ configuration data structure in mailbox command.
* @hbq_desc: pointer to the HBQ selection profile descriptor.
*
@@ -925,7 +926,7 @@ lpfc_build_hbq_profile5(struct config_hbq_var *hbqmb,
}
/**
- * lpfc_config_hbq: Prepare a mailbox command for configuring an HBQ.
+ * lpfc_config_hbq - Prepare a mailbox command for configuring an HBQ
* @phba: pointer to lpfc hba data structure.
* @id: HBQ identifier.
* @hbq_desc: pointer to the HBA descriptor data structure.
@@ -999,7 +1000,7 @@ lpfc_config_hbq(struct lpfc_hba *phba, uint32_t id,
}
/**
- * lpfc_config_ring: Prepare a mailbox command for configuring an IOCB ring.
+ * lpfc_config_ring - Prepare a mailbox command for configuring an IOCB ring
* @phba: pointer to lpfc hba data structure.
* @ring:
* @pmb: pointer to the driver internal queue element for mailbox command.
@@ -1057,7 +1058,7 @@ lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb)
}
/**
- * lpfc_config_port: Prepare a mailbox command for configuring port.
+ * lpfc_config_port - Prepare a mailbox command for configuring port
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
@@ -1227,7 +1228,7 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
}
/**
- * lpfc_kill_board: Prepare a mailbox command for killing board.
+ * lpfc_kill_board - Prepare a mailbox command for killing board
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
@@ -1253,7 +1254,7 @@ lpfc_kill_board(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
}
/**
- * lpfc_mbox_put: Put a mailbox cmd into the tail of driver's mailbox queue.
+ * lpfc_mbox_put - Put a mailbox cmd into the tail of driver's mailbox queue
* @phba: pointer to lpfc hba data structure.
* @mbq: pointer to the driver internal queue element for mailbox command.
*
@@ -1277,7 +1278,7 @@ lpfc_mbox_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
}
/**
- * lpfc_mbox_get: Remove a mailbox cmd from the head of driver's mailbox queue.
+ * lpfc_mbox_get - Remove a mailbox cmd from the head of driver's mailbox queue
* @phba: pointer to lpfc hba data structure.
*
* Driver maintains a internal mailbox command queue implemented as a linked
@@ -1304,7 +1305,7 @@ lpfc_mbox_get(struct lpfc_hba * phba)
}
/**
- * lpfc_mbox_cmpl_put: Put mailbox command into mailbox command complete list.
+ * lpfc_mbox_cmpl_put - Put mailbox command into mailbox command complete list
* @phba: pointer to lpfc hba data structure.
* @mbq: pointer to the driver internal queue element for mailbox command.
*
@@ -1327,7 +1328,7 @@ lpfc_mbox_cmpl_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
}
/**
- * lpfc_mbox_tmo_val: Retrieve mailbox command timeout value.
+ * lpfc_mbox_tmo_val - Retrieve mailbox command timeout value
* @phba: pointer to lpfc hba data structure.
* @cmd: mailbox command code.
*
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
index a4bba2069248..35a976733398 100644
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -41,7 +41,7 @@
/**
- * lpfc_mem_alloc: create and allocate all PCI and memory pools
+ * lpfc_mem_alloc - create and allocate all PCI and memory pools
* @phba: HBA to allocate pools for
*
* Description: Creates and allocates PCI pools lpfc_scsi_dma_buf_pool,
@@ -136,12 +136,12 @@ lpfc_mem_alloc(struct lpfc_hba * phba)
}
/**
- * lpfc_mem_free: Frees all PCI and memory allocated by lpfc_mem_alloc
+ * lpfc_mem_free - Frees all PCI and memory allocated by lpfc_mem_alloc
* @phba: HBA to free memory for
*
* Description: Frees PCI pools lpfc_scsi_dma_buf_pool, lpfc_mbuf_pool,
* lpfc_hbq_pool. Frees kmalloc-backed mempools for LPFC_MBOXQ_t and
- * lpfc_nodelist. Also frees the VPI bitmask.
+ * lpfc_nodelist. Also frees the VPI bitmask
*
* Returns: None
**/
@@ -212,7 +212,7 @@ lpfc_mem_free(struct lpfc_hba * phba)
}
/**
- * lpfc_mbuf_alloc: Allocate an mbuf from the lpfc_mbuf_pool PCI pool
+ * lpfc_mbuf_alloc - Allocate an mbuf from the lpfc_mbuf_pool PCI pool
* @phba: HBA which owns the pool to allocate from
* @mem_flags: indicates if this is a priority (MEM_PRI) allocation
* @handle: used to return the DMA-mapped address of the mbuf
@@ -249,7 +249,7 @@ lpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle)
}
/**
- * __lpfc_mem_free: Free an mbuf from the lpfc_mbuf_pool PCI pool (locked)
+ * __lpfc_mbuf_free - Free an mbuf from the lpfc_mbuf_pool PCI pool (locked)
* @phba: HBA which owns the pool to return to
* @virt: mbuf to free
* @dma: the DMA-mapped address of the lpfc_mbuf_pool to be freed
@@ -278,7 +278,7 @@ __lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
}
/**
- * lpfc_mem_free: Free an mbuf from the lpfc_mbuf_pool PCI pool (unlocked)
+ * lpfc_mbuf_free - Free an mbuf from the lpfc_mbuf_pool PCI pool (unlocked)
* @phba: HBA which owns the pool to return to
* @virt: mbuf to free
* @dma: the DMA-mapped address of the lpfc_mbuf_pool to be freed
@@ -291,7 +291,6 @@ __lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
* Returns: None
**/
void
-
lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
{
unsigned long iflags;
@@ -303,7 +302,7 @@ lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
}
/**
- * lpfc_els_hbq_alloc: Allocate an HBQ buffer
+ * lpfc_els_hbq_alloc - Allocate an HBQ buffer
* @phba: HBA to allocate HBQ buffer for
*
* Description: Allocates a DMA-mapped HBQ buffer from the lpfc_hbq_pool PCI
@@ -335,7 +334,7 @@ lpfc_els_hbq_alloc(struct lpfc_hba *phba)
}
/**
- * lpfc_mem_hbq_free: Frees an HBQ buffer allocated with lpfc_els_hbq_alloc
+ * lpfc_mem_hbq_free - Frees an HBQ buffer allocated with lpfc_els_hbq_alloc
* @phba: HBA buffer was allocated for
* @hbqbp: HBQ container returned by lpfc_els_hbq_alloc
*
@@ -355,7 +354,7 @@ lpfc_els_hbq_free(struct lpfc_hba *phba, struct hbq_dmabuf *hbqbp)
}
/**
- * lpfc_in_buf_free: Free a DMA buffer
+ * lpfc_in_buf_free - Free a DMA buffer
* @phba: HBA buffer is associated with
* @mp: Buffer to free
*
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 8f548adae9cc..08cdc77af41c 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -192,7 +192,6 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
struct lpfc_iocbq *iocb, *next_iocb;
- IOCB_t *cmd;
/* Abort outstanding I/O on NPort <nlp_DID> */
lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_DISCOVERY,
@@ -223,19 +222,10 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
}
spin_unlock_irq(&phba->hbalock);
- while (!list_empty(&completions)) {
- iocb = list_get_first(&completions, struct lpfc_iocbq, list);
- cmd = &iocb->iocb;
- list_del_init(&iocb->list);
-
- if (!iocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, iocb);
- else {
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
- (iocb->iocb_cmpl) (phba, iocb, iocb);
- }
- }
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
+
lpfc_cancel_retry_delay_tmo(phba->pport, ndlp);
return 0;
}
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index b1bd3fc7bae8..6ce8880fa9aa 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -112,7 +112,7 @@ lpfc_debug_save_dif(struct scsi_cmnd *cmnd)
}
/**
- * lpfc_update_stats: Update statistical data for the command completion.
+ * lpfc_update_stats - Update statistical data for the command completion
* @phba: Pointer to HBA object.
* @lpfc_cmd: lpfc scsi command object pointer.
*
@@ -165,8 +165,7 @@ lpfc_update_stats(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
}
/**
- * lpfc_send_sdev_queuedepth_change_event: Posts a queuedepth change
- * event.
+ * lpfc_send_sdev_queuedepth_change_event - Posts a queuedepth change event
* @phba: Pointer to HBA context object.
* @vport: Pointer to vport object.
* @ndlp: Pointer to FC node associated with the target.
@@ -220,7 +219,7 @@ lpfc_send_sdev_queuedepth_change_event(struct lpfc_hba *phba,
}
/**
- * lpfc_rampdown_queue_depth: Post RAMP_DOWN_QUEUE event to worker thread.
+ * lpfc_rampdown_queue_depth - Post RAMP_DOWN_QUEUE event to worker thread
* @phba: The Hba for which this call is being executed.
*
* This routine is called when there is resource error in driver or firmware.
@@ -261,7 +260,7 @@ lpfc_rampdown_queue_depth(struct lpfc_hba *phba)
}
/**
- * lpfc_rampup_queue_depth: Post RAMP_UP_QUEUE event for worker thread.
+ * lpfc_rampup_queue_depth - Post RAMP_UP_QUEUE event for worker thread
* @phba: The Hba for which this call is being executed.
*
* This routine post WORKER_RAMP_UP_QUEUE event for @phba vport. This routine
@@ -273,14 +272,14 @@ lpfc_rampdown_queue_depth(struct lpfc_hba *phba)
**/
static inline void
lpfc_rampup_queue_depth(struct lpfc_vport *vport,
- struct scsi_device *sdev)
+ uint32_t queue_depth)
{
unsigned long flags;
struct lpfc_hba *phba = vport->phba;
uint32_t evt_posted;
atomic_inc(&phba->num_cmd_success);
- if (vport->cfg_lun_queue_depth <= sdev->queue_depth)
+ if (vport->cfg_lun_queue_depth <= queue_depth)
return;
spin_lock_irqsave(&phba->hbalock, flags);
if (((phba->last_ramp_up_time + QUEUE_RAMP_UP_INTERVAL) > jiffies) ||
@@ -303,7 +302,7 @@ lpfc_rampup_queue_depth(struct lpfc_vport *vport,
}
/**
- * lpfc_ramp_down_queue_handler: WORKER_RAMP_DOWN_QUEUE event handler.
+ * lpfc_ramp_down_queue_handler - WORKER_RAMP_DOWN_QUEUE event handler
* @phba: The Hba for which this call is being executed.
*
* This routine is called to process WORKER_RAMP_DOWN_QUEUE event for worker
@@ -361,7 +360,7 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
}
/**
- * lpfc_ramp_up_queue_handler: WORKER_RAMP_UP_QUEUE event handler.
+ * lpfc_ramp_up_queue_handler - WORKER_RAMP_UP_QUEUE event handler
* @phba: The Hba for which this call is being executed.
*
* This routine is called to process WORKER_RAMP_UP_QUEUE event for worker
@@ -410,7 +409,7 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba)
}
/**
- * lpfc_scsi_dev_block: set all scsi hosts to block state.
+ * lpfc_scsi_dev_block - set all scsi hosts to block state
* @phba: Pointer to HBA context object.
*
* This function walks vport list and set each SCSI host to block state
@@ -439,7 +438,7 @@ lpfc_scsi_dev_block(struct lpfc_hba *phba)
}
/**
- * lpfc_new_scsi_buf: Scsi buffer allocator.
+ * lpfc_new_scsi_buf - Scsi buffer allocator
* @vport: The virtual port for which this call being executed.
*
* This routine allocates a scsi buffer, which contains all the necessary
@@ -563,7 +562,7 @@ lpfc_new_scsi_buf(struct lpfc_vport *vport)
}
/**
- * lpfc_get_scsi_buf: Get a scsi buffer from lpfc_scsi_buf_list list of Hba.
+ * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list list of Hba
* @phba: The Hba for which this call is being executed.
*
* This routine removes a scsi buffer from head of @phba lpfc_scsi_buf_list list
@@ -592,7 +591,7 @@ lpfc_get_scsi_buf(struct lpfc_hba * phba)
}
/**
- * lpfc_release_scsi_buf: Return a scsi buffer back to hba lpfc_scsi_buf_list list.
+ * lpfc_release_scsi_buf - Return a scsi buffer back to hba's lpfc_scsi_buf_list
* @phba: The Hba for which this call is being executed.
* @psb: The scsi buffer which is being released.
*
@@ -611,7 +610,7 @@ lpfc_release_scsi_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
}
/**
- * lpfc_scsi_prep_dma_buf: Routine to do DMA mapping for scsi buffer.
+ * lpfc_scsi_prep_dma_buf - Routine to do DMA mapping for scsi buffer
* @phba: The Hba for which this call is being executed.
* @lpfc_cmd: The scsi buffer which is going to be mapped.
*
@@ -738,7 +737,7 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
* Due to difference in data length between DIF/non-DIF paths,
* we need to set word 4 of IOCB here
*/
- iocb_cmd->un.fcpi.fcpi_parm = le32_to_cpu(scsi_bufflen(scsi_cmnd));
+ iocb_cmd->un.fcpi.fcpi_parm = scsi_bufflen(scsi_cmnd);
return 0;
}
@@ -823,13 +822,13 @@ lpfc_cmd_blksize(struct scsi_cmnd *sc)
/**
* lpfc_get_cmd_dif_parms - Extract DIF parameters from SCSI command
* @sc: in: SCSI command
- * @apptagmask out: app tag mask
- * @apptagval out: app tag value
- * @reftag out: ref tag (reference tag)
+ * @apptagmask: out: app tag mask
+ * @apptagval: out: app tag value
+ * @reftag: out: ref tag (reference tag)
*
* Description:
- * Extract DIF paramters from the command if possible. Otherwise,
- * use default paratmers.
+ * Extract DIF parameters from the command if possible. Otherwise,
+ * use default parameters.
*
**/
static inline void
@@ -1394,7 +1393,7 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd,
*/
cmd->sense_buffer[8] = 0; /* Information */
cmd->sense_buffer[9] = 0xa; /* Add. length */
- do_div(bghm, cmd->device->sector_size);
+ bghm /= cmd->device->sector_size;
failing_sector = scsi_get_lba(cmd);
failing_sector += bghm;
@@ -1413,7 +1412,7 @@ out:
}
/**
- * lpfc_send_scsi_error_event: Posts an event when there is SCSI error.
+ * lpfc_send_scsi_error_event - Posts an event when there is SCSI error
* @phba: Pointer to hba context object.
* @vport: Pointer to vport object.
* @lpfc_cmd: Pointer to lpfc scsi command which reported the error.
@@ -1505,7 +1504,7 @@ lpfc_send_scsi_error_event(struct lpfc_hba *phba, struct lpfc_vport *vport,
}
/**
- * lpfc_scsi_unprep_dma_buf: Routine to un-map DMA mapping of scatter gather.
+ * lpfc_scsi_unprep_dma_buf - Routine to un-map DMA mapping of scatter gather
* @phba: The Hba for which this call is being executed.
* @psb: The scsi buffer which is going to be un-mapped.
*
@@ -1530,7 +1529,7 @@ lpfc_scsi_unprep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
}
/**
- * lpfc_handler_fcp_err: FCP response handler.
+ * lpfc_handler_fcp_err - FCP response handler
* @vport: The virtual port for which this call is being executed.
* @lpfc_cmd: Pointer to lpfc_scsi_buf data structure.
* @rsp_iocb: The response IOCB which contains FCP error.
@@ -1674,7 +1673,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
}
/**
- * lpfc_scsi_cmd_iocb_cmpl: Scsi cmnd IOCB completion routine.
+ * lpfc_scsi_cmd_iocb_cmpl - Scsi cmnd IOCB completion routine
* @phba: The Hba for which this call is being executed.
* @pIocbIn: The command IOCBQ for the scsi cmnd.
* @pIocbOut: The response IOCBQ for the scsi cmnd .
@@ -1694,10 +1693,12 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
struct lpfc_nodelist *pnode = rdata->pnode;
struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
int result;
- struct scsi_device *sdev, *tmp_sdev;
+ struct scsi_device *tmp_sdev;
int depth = 0;
unsigned long flags;
struct lpfc_fast_path_event *fast_path_evt;
+ struct Scsi_Host *shost = cmd->device->host;
+ uint32_t queue_depth, scsi_id;
lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4];
lpfc_cmd->status = pIocbOut->iocb.ulpStatus;
@@ -1808,11 +1809,10 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
lpfc_update_stats(phba, lpfc_cmd);
result = cmd->result;
- sdev = cmd->device;
if (vport->cfg_max_scsicmpl_time &&
time_after(jiffies, lpfc_cmd->start_time +
msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) {
- spin_lock_irqsave(sdev->host->host_lock, flags);
+ spin_lock_irqsave(shost->host_lock, flags);
if (pnode && NLP_CHK_NODE_ACT(pnode)) {
if (pnode->cmd_qdepth >
atomic_read(&pnode->cmd_pending) &&
@@ -1825,22 +1825,26 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
pnode->last_change_time = jiffies;
}
- spin_unlock_irqrestore(sdev->host->host_lock, flags);
+ spin_unlock_irqrestore(shost->host_lock, flags);
} else if (pnode && NLP_CHK_NODE_ACT(pnode)) {
if ((pnode->cmd_qdepth < LPFC_MAX_TGT_QDEPTH) &&
time_after(jiffies, pnode->last_change_time +
msecs_to_jiffies(LPFC_TGTQ_INTERVAL))) {
- spin_lock_irqsave(sdev->host->host_lock, flags);
+ spin_lock_irqsave(shost->host_lock, flags);
pnode->cmd_qdepth += pnode->cmd_qdepth *
LPFC_TGTQ_RAMPUP_PCENT / 100;
if (pnode->cmd_qdepth > LPFC_MAX_TGT_QDEPTH)
pnode->cmd_qdepth = LPFC_MAX_TGT_QDEPTH;
pnode->last_change_time = jiffies;
- spin_unlock_irqrestore(sdev->host->host_lock, flags);
+ spin_unlock_irqrestore(shost->host_lock, flags);
}
}
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
+
+ /* The sdev is not guaranteed to be valid post scsi_done upcall. */
+ queue_depth = cmd->device->queue_depth;
+ scsi_id = cmd->device->id;
cmd->scsi_done(cmd);
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
@@ -1848,28 +1852,28 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
* If there is a thread waiting for command completion
* wake up the thread.
*/
- spin_lock_irqsave(sdev->host->host_lock, flags);
+ spin_lock_irqsave(shost->host_lock, flags);
lpfc_cmd->pCmd = NULL;
if (lpfc_cmd->waitq)
wake_up(lpfc_cmd->waitq);
- spin_unlock_irqrestore(sdev->host->host_lock, flags);
+ spin_unlock_irqrestore(shost->host_lock, flags);
lpfc_release_scsi_buf(phba, lpfc_cmd);
return;
}
if (!result)
- lpfc_rampup_queue_depth(vport, sdev);
+ lpfc_rampup_queue_depth(vport, queue_depth);
if (!result && pnode && NLP_CHK_NODE_ACT(pnode) &&
((jiffies - pnode->last_ramp_up_time) >
LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
((jiffies - pnode->last_q_full_time) >
LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
- (vport->cfg_lun_queue_depth > sdev->queue_depth)) {
- shost_for_each_device(tmp_sdev, sdev->host) {
+ (vport->cfg_lun_queue_depth > queue_depth)) {
+ shost_for_each_device(tmp_sdev, shost) {
if (vport->cfg_lun_queue_depth > tmp_sdev->queue_depth){
- if (tmp_sdev->id != sdev->id)
+ if (tmp_sdev->id != scsi_id)
continue;
if (tmp_sdev->ordered_tags)
scsi_adjust_queue_depth(tmp_sdev,
@@ -1885,7 +1889,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
}
lpfc_send_sdev_queuedepth_change_event(phba, vport, pnode,
0xFFFFFFFF,
- sdev->queue_depth - 1, sdev->queue_depth);
+ queue_depth , queue_depth + 1);
}
/*
@@ -1896,8 +1900,8 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
NLP_CHK_NODE_ACT(pnode)) {
pnode->last_q_full_time = jiffies;
- shost_for_each_device(tmp_sdev, sdev->host) {
- if (tmp_sdev->id != sdev->id)
+ shost_for_each_device(tmp_sdev, shost) {
+ if (tmp_sdev->id != scsi_id)
continue;
depth = scsi_track_queue_full(tmp_sdev,
tmp_sdev->queue_depth - 1);
@@ -1909,7 +1913,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
* scsi_track_queue_full.
*/
if (depth == -1)
- depth = sdev->host->cmd_per_lun;
+ depth = shost->cmd_per_lun;
if (depth) {
lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
@@ -1925,17 +1929,17 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
* If there is a thread waiting for command completion
* wake up the thread.
*/
- spin_lock_irqsave(sdev->host->host_lock, flags);
+ spin_lock_irqsave(shost->host_lock, flags);
lpfc_cmd->pCmd = NULL;
if (lpfc_cmd->waitq)
wake_up(lpfc_cmd->waitq);
- spin_unlock_irqrestore(sdev->host->host_lock, flags);
+ spin_unlock_irqrestore(shost->host_lock, flags);
lpfc_release_scsi_buf(phba, lpfc_cmd);
}
/**
- * lpfc_fcpcmd_to_iocb - copy the fcp_cmd data into the IOCB.
+ * lpfc_fcpcmd_to_iocb - copy the fcp_cmd data into the IOCB
* @data: A pointer to the immediate command data portion of the IOCB.
* @fcp_cmnd: The FCP Command that is provided by the SCSI layer.
*
@@ -1953,7 +1957,7 @@ lpfc_fcpcmd_to_iocb(uint8_t *data, struct fcp_cmnd *fcp_cmnd)
}
/**
- * lpfc_scsi_prep_cmnd: Routine to convert scsi cmnd to FCP information unit.
+ * lpfc_scsi_prep_cmnd - Routine to convert scsi cmnd to FCP information unit
* @vport: The virtual port for which this call is being executed.
* @lpfc_cmd: The scsi command which needs to send.
* @pnode: Pointer to lpfc_nodelist.
@@ -2047,7 +2051,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
}
/**
- * lpfc_scsi_prep_task_mgmt_cmnd: Convert scsi TM cmnd to FCP information unit.
+ * lpfc_scsi_prep_task_mgmt_cmnd - Convert scsi TM cmnd to FCP information unit
* @vport: The virtual port for which this call is being executed.
* @lpfc_cmd: Pointer to lpfc_scsi_buf data structure.
* @lun: Logical unit number.
@@ -2110,7 +2114,7 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport,
}
/**
- * lpc_taskmgmt_def_cmpl: IOCB completion routine for task management command.
+ * lpfc_taskmgmt_def_cmpl - IOCB completion routine for task management command
* @phba: The Hba for which this call is being executed.
* @cmdiocbq: Pointer to lpfc_iocbq data structure.
* @rspiocbq: Pointer to lpfc_iocbq data structure.
@@ -2131,7 +2135,7 @@ lpfc_tskmgmt_def_cmpl(struct lpfc_hba *phba,
}
/**
- * lpfc_scsi_tgt_reset: Target reset handler.
+ * lpfc_scsi_tgt_reset - Target reset handler
* @lpfc_cmd: Pointer to lpfc_scsi_buf data structure
* @vport: The virtual port for which this call is being executed.
* @tgt_id: Target ID.
@@ -2198,7 +2202,7 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_vport *vport,
}
/**
- * lpfc_info: Info entry point of scsi_host_template data structure.
+ * lpfc_info - Info entry point of scsi_host_template data structure
* @host: The scsi host for which this call is being executed.
*
* This routine provides module information about hba.
@@ -2236,7 +2240,7 @@ lpfc_info(struct Scsi_Host *host)
}
/**
- * lpfc_poll_rearm_time: Routine to modify fcp_poll timer of hba.
+ * lpfc_poll_rearm_time - Routine to modify fcp_poll timer of hba
* @phba: The Hba for which this call is being executed.
*
* This routine modifies fcp_poll_timer field of @phba by cfg_poll_tmo.
@@ -2253,7 +2257,7 @@ static __inline__ void lpfc_poll_rearm_timer(struct lpfc_hba * phba)
}
/**
- * lpfc_poll_start_timer: Routine to start fcp_poll_timer of HBA.
+ * lpfc_poll_start_timer - Routine to start fcp_poll_timer of HBA
* @phba: The Hba for which this call is being executed.
*
* This routine starts the fcp_poll_timer of @phba.
@@ -2264,7 +2268,7 @@ void lpfc_poll_start_timer(struct lpfc_hba * phba)
}
/**
- * lpfc_poll_timeout: Restart polling timer.
+ * lpfc_poll_timeout - Restart polling timer
* @ptr: Map to lpfc_hba data structure pointer.
*
* This routine restarts fcp_poll timer, when FCP ring polling is enable
@@ -2283,8 +2287,7 @@ void lpfc_poll_timeout(unsigned long ptr)
}
/**
- * lpfc_queuecommand: Queuecommand entry point of Scsi Host Templater data
- * structure.
+ * lpfc_queuecommand - scsi_host_template queuecommand entry point
* @cmnd: Pointer to scsi_cmnd data structure.
* @done: Pointer to done routine.
*
@@ -2450,7 +2453,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
}
/**
- * lpfc_block_error_handler: Routine to block error handler.
+ * lpfc_block_error_handler - Routine to block error handler
* @cmnd: Pointer to scsi_cmnd data structure.
*
* This routine blocks execution till fc_rport state is not FC_PORSTAT_BLCOEKD.
@@ -2472,8 +2475,7 @@ lpfc_block_error_handler(struct scsi_cmnd *cmnd)
}
/**
- * lpfc_abort_handler: Eh_abort_handler entry point of Scsi Host Template data
- *structure.
+ * lpfc_abort_handler - scsi_host_template eh_abort_handler entry point
* @cmnd: Pointer to scsi_cmnd data structure.
*
* This routine aborts @cmnd pending in base driver.
@@ -2578,8 +2580,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
}
/**
- * lpfc_device_reset_handler: eh_device_reset entry point of Scsi Host Template
- *data structure.
+ * lpfc_device_reset_handler - scsi_host_template eh_device_reset entry point
* @cmnd: Pointer to scsi_cmnd data structure.
*
* This routine does a device reset by sending a TARGET_RESET task management
@@ -2587,7 +2588,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
*
* Return code :
* 0x2003 - Error
- * 0ex2002 - Success
+ * 0x2002 - Success
**/
static int
lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
@@ -2707,8 +2708,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
}
/**
- * lpfc_bus_reset_handler: eh_bus_reset_handler entry point of Scsi Host
- * Template data structure.
+ * lpfc_bus_reset_handler - scsi_host_template eh_bus_reset_handler entry point
* @cmnd: Pointer to scsi_cmnd data structure.
*
* This routine does target reset to all target on @cmnd->device->host.
@@ -2808,8 +2808,7 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
}
/**
- * lpfc_slave_alloc: slave_alloc entry point of Scsi Host Template data
- * structure.
+ * lpfc_slave_alloc - scsi_host_template slave_alloc entry point
* @sdev: Pointer to scsi_device.
*
* This routine populates the cmds_per_lun count + 2 scsi_bufs into this host's
@@ -2883,8 +2882,7 @@ lpfc_slave_alloc(struct scsi_device *sdev)
}
/**
- * lpfc_slave_configure: slave_configure entry point of Scsi Host Templater data
- * structure.
+ * lpfc_slave_configure - scsi_host_template slave_configure entry point
* @sdev: Pointer to scsi_device.
*
* This routine configures following items
@@ -2925,7 +2923,7 @@ lpfc_slave_configure(struct scsi_device *sdev)
}
/**
- * lpfc_slave_destroy: slave_destroy entry point of SHT data structure.
+ * lpfc_slave_destroy - slave_destroy entry point of SHT data structure
* @sdev: Pointer to scsi_device.
*
* This routine sets @sdev hostatdata filed to null.
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index a36a120561e2..eb5c75c45ba4 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -68,7 +68,7 @@ typedef enum _lpfc_iocb_type {
} lpfc_iocb_type;
/**
- * lpfc_cmd_iocb: Get next command iocb entry in the ring.
+ * lpfc_cmd_iocb - Get next command iocb entry in the ring
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
@@ -85,7 +85,7 @@ lpfc_cmd_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
}
/**
- * lpfc_resp_iocb: Get next response iocb entry in the ring.
+ * lpfc_resp_iocb - Get next response iocb entry in the ring
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
@@ -102,7 +102,7 @@ lpfc_resp_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
}
/**
- * __lpfc_sli_get_iocbq: Allocates an iocb object from iocb pool.
+ * __lpfc_sli_get_iocbq - Allocates an iocb object from iocb pool
* @phba: Pointer to HBA context object.
*
* This function is called with hbalock held. This function
@@ -121,7 +121,7 @@ __lpfc_sli_get_iocbq(struct lpfc_hba *phba)
}
/**
- * lpfc_sli_get_iocbq: Allocates an iocb object from iocb pool.
+ * lpfc_sli_get_iocbq - Allocates an iocb object from iocb pool
* @phba: Pointer to HBA context object.
*
* This function is called with no lock held. This function
@@ -142,7 +142,7 @@ lpfc_sli_get_iocbq(struct lpfc_hba *phba)
}
/**
- * __lpfc_sli_release_iocbq: Release iocb to the iocb pool.
+ * __lpfc_sli_release_iocbq - Release iocb to the iocb pool
* @phba: Pointer to HBA context object.
* @iocbq: Pointer to driver iocb object.
*
@@ -164,7 +164,7 @@ __lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
}
/**
- * lpfc_sli_release_iocbq: Release iocb to the iocb pool.
+ * lpfc_sli_release_iocbq - Release iocb to the iocb pool
* @phba: Pointer to HBA context object.
* @iocbq: Pointer to driver iocb object.
*
@@ -185,8 +185,40 @@ lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
}
/**
- * lpfc_sli_iocb_cmd_type: Get the iocb type.
- * @iocb_cmnd : iocb command code.
+ * lpfc_sli_cancel_iocbs - Cancel all iocbs from a list.
+ * @phba: Pointer to HBA context object.
+ * @iocblist: List of IOCBs.
+ * @ulpstatus: ULP status in IOCB command field.
+ * @ulpWord4: ULP word-4 in IOCB command field.
+ *
+ * This function is called with a list of IOCBs to cancel. It cancels the IOCB
+ * on the list by invoking the complete callback function associated with the
+ * IOCB with the provided @ulpstatus and @ulpword4 set to the IOCB commond
+ * fields.
+ **/
+void
+lpfc_sli_cancel_iocbs(struct lpfc_hba *phba, struct list_head *iocblist,
+ uint32_t ulpstatus, uint32_t ulpWord4)
+{
+ struct lpfc_iocbq *piocb;
+
+ while (!list_empty(iocblist)) {
+ list_remove_head(iocblist, piocb, struct lpfc_iocbq, list);
+
+ if (!piocb->iocb_cmpl)
+ lpfc_sli_release_iocbq(phba, piocb);
+ else {
+ piocb->iocb.ulpStatus = ulpstatus;
+ piocb->iocb.un.ulpWord[4] = ulpWord4;
+ (piocb->iocb_cmpl) (phba, piocb, piocb);
+ }
+ }
+ return;
+}
+
+/**
+ * lpfc_sli_iocb_cmd_type - Get the iocb type
+ * @iocb_cmnd: iocb command code.
*
* This function is called by ring event handler function to get the iocb type.
* This function translates the iocb command to an iocb command type used to
@@ -295,7 +327,7 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd)
}
/**
- * lpfc_sli_ring_map: Issue config_ring mbox for all rings.
+ * lpfc_sli_ring_map - Issue config_ring mbox for all rings
* @phba: Pointer to HBA context object.
*
* This function is called from SLI initialization code
@@ -338,7 +370,7 @@ lpfc_sli_ring_map(struct lpfc_hba *phba)
}
/**
- * lpfc_sli_ringtxcmpl_put: Adds new iocb to the txcmplq.
+ * lpfc_sli_ringtxcmpl_put - Adds new iocb to the txcmplq
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @piocb: Pointer to the driver iocb object.
@@ -370,7 +402,7 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
/**
- * lpfc_sli_ringtx_get: Get first element of the txq.
+ * lpfc_sli_ringtx_get - Get first element of the txq
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
@@ -391,7 +423,7 @@ lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
}
/**
- * lpfc_sli_next_iocb_slot: Get next iocb slot in the ring.
+ * lpfc_sli_next_iocb_slot - Get next iocb slot in the ring
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
@@ -445,7 +477,7 @@ lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
}
/**
- * lpfc_sli_next_iotag: Get an iotag for the iocb.
+ * lpfc_sli_next_iotag - Get an iotag for the iocb
* @phba: Pointer to HBA context object.
* @iocbq: Pointer to driver iocb object.
*
@@ -520,7 +552,7 @@ lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
}
/**
- * lpfc_sli_submit_iocb: Submit an iocb to the firmware.
+ * lpfc_sli_submit_iocb - Submit an iocb to the firmware
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @iocb: Pointer to iocb slot in the ring.
@@ -577,7 +609,7 @@ lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
/**
- * lpfc_sli_update_full_ring: Update the chip attention register.
+ * lpfc_sli_update_full_ring - Update the chip attention register
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
@@ -608,7 +640,7 @@ lpfc_sli_update_full_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
}
/**
- * lpfc_sli_update_ring: Update chip attention register.
+ * lpfc_sli_update_ring - Update chip attention register
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
@@ -632,7 +664,7 @@ lpfc_sli_update_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
}
/**
- * lpfc_sli_resume_iocb: Process iocbs in the txq.
+ * lpfc_sli_resume_iocb - Process iocbs in the txq
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
@@ -672,7 +704,7 @@ lpfc_sli_resume_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
}
/**
- * lpfc_sli_next_hbq_slot: Get next hbq entry for the HBQ.
+ * lpfc_sli_next_hbq_slot - Get next hbq entry for the HBQ
* @phba: Pointer to HBA context object.
* @hbqno: HBQ number.
*
@@ -717,7 +749,7 @@ lpfc_sli_next_hbq_slot(struct lpfc_hba *phba, uint32_t hbqno)
}
/**
- * lpfc_sli_hbqbuf_free_all: Free all the hbq buffers.
+ * lpfc_sli_hbqbuf_free_all - Free all the hbq buffers
* @phba: Pointer to HBA context object.
*
* This function is called with no lock held to free all the
@@ -771,7 +803,7 @@ lpfc_sli_hbqbuf_free_all(struct lpfc_hba *phba)
}
/**
- * lpfc_sli_hbq_to_firmware: Post the hbq buffer to firmware.
+ * lpfc_sli_hbq_to_firmware - Post the hbq buffer to firmware
* @phba: Pointer to HBA context object.
* @hbqno: HBQ number.
* @hbq_buf: Pointer to HBQ buffer.
@@ -818,8 +850,8 @@ static struct lpfc_hbq_init lpfc_els_hbq = {
.profile = 0,
.ring_mask = (1 << LPFC_ELS_RING),
.buffer_count = 0,
- .init_count = 20,
- .add_count = 5,
+ .init_count = 40,
+ .add_count = 40,
};
/* HBQ for the extra ring if needed */
@@ -841,7 +873,7 @@ struct lpfc_hbq_init *lpfc_hbq_defs[] = {
};
/**
- * lpfc_sli_hbqbuf_fill_hbqs: Post more hbq buffers to HBQ.
+ * lpfc_sli_hbqbuf_fill_hbqs - Post more hbq buffers to HBQ
* @phba: Pointer to HBA context object.
* @hbqno: HBQ number.
* @count: Number of HBQ buffers to be posted.
@@ -901,7 +933,7 @@ err:
}
/**
- * lpfc_sli_hbqbuf_add_hbqs: Post more HBQ buffers to firmware.
+ * lpfc_sli_hbqbuf_add_hbqs - Post more HBQ buffers to firmware
* @phba: Pointer to HBA context object.
* @qno: HBQ number.
*
@@ -917,7 +949,7 @@ lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *phba, uint32_t qno)
}
/**
- * lpfc_sli_hbqbuf_init_hbqs: Post initial buffers to the HBQ.
+ * lpfc_sli_hbqbuf_init_hbqs - Post initial buffers to the HBQ
* @phba: Pointer to HBA context object.
* @qno: HBQ queue number.
*
@@ -933,7 +965,7 @@ lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *phba, uint32_t qno)
}
/**
- * lpfc_sli_hbqbuf_find: Find the hbq buffer associated with a tag.
+ * lpfc_sli_hbqbuf_find - Find the hbq buffer associated with a tag
* @phba: Pointer to HBA context object.
* @tag: Tag of the hbq buffer.
*
@@ -966,7 +998,7 @@ lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag)
}
/**
- * lpfc_sli_free_hbq: Give back the hbq buffer to firmware.
+ * lpfc_sli_free_hbq - Give back the hbq buffer to firmware
* @phba: Pointer to HBA context object.
* @hbq_buffer: Pointer to HBQ buffer.
*
@@ -988,7 +1020,7 @@ lpfc_sli_free_hbq(struct lpfc_hba *phba, struct hbq_dmabuf *hbq_buffer)
}
/**
- * lpfc_sli_chk_mbx_command: Check if the mailbox is a legitimate mailbox.
+ * lpfc_sli_chk_mbx_command - Check if the mailbox is a legitimate mailbox
* @mbxCommand: mailbox command code.
*
* This function is called by the mailbox event handler function to verify
@@ -1064,8 +1096,7 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand)
}
/**
- * lpfc_sli_wake_mbox_wait: Completion handler for mbox issued from
- * lpfc_sli_issue_mbox_wait.
+ * lpfc_sli_wake_mbox_wait - lpfc_sli_issue_mbox_wait mbox completion handler
* @phba: Pointer to HBA context object.
* @pmboxq: Pointer to mailbox command.
*
@@ -1096,7 +1127,7 @@ lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
/**
- * lpfc_sli_def_mbox_cmpl: Default mailbox completion handler.
+ * lpfc_sli_def_mbox_cmpl - Default mailbox completion handler
* @phba: Pointer to HBA context object.
* @pmb: Pointer to mailbox object.
*
@@ -1140,7 +1171,7 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
}
/**
- * lpfc_sli_handle_mb_event: Handle mailbox completions from firmware.
+ * lpfc_sli_handle_mb_event - Handle mailbox completions from firmware
* @phba: Pointer to HBA context object.
*
* This function is called with no lock held. This function processes all
@@ -1260,7 +1291,7 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
}
/**
- * lpfc_sli_get_buff: Get the buffer associated with the buffer tag.
+ * lpfc_sli_get_buff - Get the buffer associated with the buffer tag
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @tag: buffer tag.
@@ -1288,7 +1319,7 @@ lpfc_sli_get_buff(struct lpfc_hba *phba,
/**
- * lpfc_sli_process_unsol_iocb: Unsolicited iocb handler.
+ * lpfc_sli_process_unsol_iocb - Unsolicited iocb handler
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @saveq: Pointer to the unsolicited iocb.
@@ -1484,7 +1515,7 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
/**
- * lpfc_sli_iocbq_lookup: Find command iocb for the given response iocb.
+ * lpfc_sli_iocbq_lookup - Find command iocb for the given response iocb
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @prspiocb: Pointer to response iocb object.
@@ -1521,7 +1552,7 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba,
}
/**
- * lpfc_sli_process_sol_iocb: process solicited iocb completion.
+ * lpfc_sli_process_sol_iocb - process solicited iocb completion
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @saveq: Pointer to the response iocb to be processed.
@@ -1597,7 +1628,7 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
* Ring <ringno> handler: unexpected completion IoTag
* <IoTag>
*/
- lpfc_printf_vlog(cmdiocbp->vport, KERN_WARNING, LOG_SLI,
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
"0322 Ring %d handler: "
"unexpected completion IoTag x%x "
"Data: x%x x%x x%x x%x\n",
@@ -1614,7 +1645,7 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
/**
- * lpfc_sli_rsp_pointers_error: Response ring pointer error handler.
+ * lpfc_sli_rsp_pointers_error - Response ring pointer error handler
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
@@ -1652,7 +1683,7 @@ lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
}
/**
- * lpfc_poll_eratt: Error attention polling timer timeout handler.
+ * lpfc_poll_eratt - Error attention polling timer timeout handler
* @ptr: Pointer to address of HBA context object.
*
* This function is invoked by the Error Attention polling timer when the
@@ -1682,7 +1713,7 @@ void lpfc_poll_eratt(unsigned long ptr)
}
/**
- * lpfc_sli_poll_fcp_ring: Handle FCP ring completion in polling mode.
+ * lpfc_sli_poll_fcp_ring - Handle FCP ring completion in polling mode
* @phba: Pointer to HBA context object.
*
* This function is called from lpfc_queuecommand, lpfc_poll_timeout,
@@ -1845,7 +1876,7 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba)
}
/**
- * lpfc_sli_handle_fast_ring_event: Handle ring events on FCP ring.
+ * lpfc_sli_handle_fast_ring_event - Handle ring events on FCP ring
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @mask: Host attention register mask for this ring.
@@ -2037,7 +2068,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba,
}
/**
- * lpfc_sli_handle_slow_ring_event: Handle ring events for non-FCP rings.
+ * lpfc_sli_handle_slow_ring_event - Handle ring events for non-FCP rings
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @mask: Host attention register mask for this ring.
@@ -2311,7 +2342,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
}
/**
- * lpfc_sli_abort_iocb_ring: Abort all iocbs in the ring.
+ * lpfc_sli_abort_iocb_ring - Abort all iocbs in the ring
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
@@ -2325,7 +2356,6 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
LIST_HEAD(completions);
struct lpfc_iocbq *iocb, *next_iocb;
- IOCB_t *cmd = NULL;
if (pring->ringno == LPFC_ELS_RING) {
lpfc_fabric_abort_hba(phba);
@@ -2344,23 +2374,13 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
spin_unlock_irq(&phba->hbalock);
- while (!list_empty(&completions)) {
- iocb = list_get_first(&completions, struct lpfc_iocbq, list);
- cmd = &iocb->iocb;
- list_del_init(&iocb->list);
-
- if (!iocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, iocb);
- else {
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
- (iocb->iocb_cmpl) (phba, iocb, iocb);
- }
- }
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
}
/**
- * lpfc_sli_flush_fcp_rings: flush all iocbs in the fcp ring.
+ * lpfc_sli_flush_fcp_rings - flush all iocbs in the fcp ring
* @phba: Pointer to HBA context object.
*
* This function flushes all iocbs in the fcp ring and frees all the iocb
@@ -2374,8 +2394,6 @@ lpfc_sli_flush_fcp_rings(struct lpfc_hba *phba)
{
LIST_HEAD(txq);
LIST_HEAD(txcmplq);
- struct lpfc_iocbq *iocb;
- IOCB_t *cmd = NULL;
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring;
@@ -2393,38 +2411,16 @@ lpfc_sli_flush_fcp_rings(struct lpfc_hba *phba)
spin_unlock_irq(&phba->hbalock);
/* Flush the txq */
- while (!list_empty(&txq)) {
- iocb = list_get_first(&txq, struct lpfc_iocbq, list);
- cmd = &iocb->iocb;
- list_del_init(&iocb->list);
-
- if (!iocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, iocb);
- else {
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_DOWN;
- (iocb->iocb_cmpl) (phba, iocb, iocb);
- }
- }
+ lpfc_sli_cancel_iocbs(phba, &txq, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_DOWN);
/* Flush the txcmpq */
- while (!list_empty(&txcmplq)) {
- iocb = list_get_first(&txcmplq, struct lpfc_iocbq, list);
- cmd = &iocb->iocb;
- list_del_init(&iocb->list);
-
- if (!iocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, iocb);
- else {
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_DOWN;
- (iocb->iocb_cmpl) (phba, iocb, iocb);
- }
- }
+ lpfc_sli_cancel_iocbs(phba, &txcmplq, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_DOWN);
}
/**
- * lpfc_sli_brdready: Check for host status bits.
+ * lpfc_sli_brdready - Check for host status bits
* @phba: Pointer to HBA context object.
* @mask: Bit mask to be checked.
*
@@ -2484,7 +2480,7 @@ lpfc_sli_brdready(struct lpfc_hba *phba, uint32_t mask)
#define BARRIER_TEST_PATTERN (0xdeadbeef)
/**
- * lpfc_reset_barrier: Make HBA ready for HBA reset.
+ * lpfc_reset_barrier - Make HBA ready for HBA reset
* @phba: Pointer to HBA context object.
*
* This function is called before resetting an HBA. This
@@ -2564,7 +2560,7 @@ restore_hc:
}
/**
- * lpfc_sli_brdkill: Issue a kill_board mailbox command.
+ * lpfc_sli_brdkill - Issue a kill_board mailbox command
* @phba: Pointer to HBA context object.
*
* This function issues a kill_board mailbox command and waits for
@@ -2651,7 +2647,7 @@ lpfc_sli_brdkill(struct lpfc_hba *phba)
}
/**
- * lpfc_sli_brdreset: Reset the HBA.
+ * lpfc_sli_brdreset - Reset the HBA
* @phba: Pointer to HBA context object.
*
* This function resets the HBA by writing HC_INITFF to the control
@@ -2714,7 +2710,7 @@ lpfc_sli_brdreset(struct lpfc_hba *phba)
}
/**
- * lpfc_sli_brdrestart: Restart the HBA.
+ * lpfc_sli_brdrestart - Restart the HBA
* @phba: Pointer to HBA context object.
*
* This function is called in the SLI initialization code path to
@@ -2781,7 +2777,7 @@ lpfc_sli_brdrestart(struct lpfc_hba *phba)
}
/**
- * lpfc_sli_chipset_init: Wait for the restart of the HBA after a restart.
+ * lpfc_sli_chipset_init - Wait for the restart of the HBA after a restart
* @phba: Pointer to HBA context object.
*
* This function is called after a HBA restart to wait for successful
@@ -2876,7 +2872,7 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
}
/**
- * lpfc_sli_hbq_count: Get the number of HBQs to be configured.
+ * lpfc_sli_hbq_count - Get the number of HBQs to be configured
*
* This function calculates and returns the number of HBQs required to be
* configured.
@@ -2888,7 +2884,7 @@ lpfc_sli_hbq_count(void)
}
/**
- * lpfc_sli_hbq_entry_count: Calculate total number of hbq entries.
+ * lpfc_sli_hbq_entry_count - Calculate total number of hbq entries
*
* This function adds the number of hbq entries in every HBQ to get
* the total number of hbq entries required for the HBA and returns
@@ -2907,7 +2903,7 @@ lpfc_sli_hbq_entry_count(void)
}
/**
- * lpfc_sli_hbq_size: Calculate memory required for all hbq entries.
+ * lpfc_sli_hbq_size - Calculate memory required for all hbq entries
*
* This function calculates amount of memory required for all hbq entries
* to be configured and returns the total memory required.
@@ -2919,7 +2915,7 @@ lpfc_sli_hbq_size(void)
}
/**
- * lpfc_sli_hbq_setup: configure and initialize HBQs.
+ * lpfc_sli_hbq_setup - configure and initialize HBQs
* @phba: Pointer to HBA context object.
*
* This function is called during the SLI initialization to configure
@@ -2988,7 +2984,7 @@ lpfc_sli_hbq_setup(struct lpfc_hba *phba)
}
/**
- * lpfc_sli_config_port: Issue config port mailbox command.
+ * lpfc_sli_config_port - Issue config port mailbox command
* @phba: Pointer to HBA context object.
* @sli_mode: sli mode - 2/3
*
@@ -3114,7 +3110,7 @@ do_prep_failed:
/**
- * lpfc_sli_hba_setup: SLI intialization function.
+ * lpfc_sli_hba_setup - SLI intialization function
* @phba: Pointer to HBA context object.
*
* This function is the main SLI intialization function. This function
@@ -3206,7 +3202,7 @@ lpfc_sli_hba_setup_error:
/**
- * lpfc_mbox_timeout: Timeout call back function for mbox timer.
+ * lpfc_mbox_timeout - Timeout call back function for mbox timer
* @ptr: context object - pointer to hba structure.
*
* This is the callback function for mailbox timer. The mailbox
@@ -3237,7 +3233,7 @@ lpfc_mbox_timeout(unsigned long ptr)
/**
- * lpfc_mbox_timeout_handler: Worker thread function to handle mailbox timeout.
+ * lpfc_mbox_timeout_handler - Worker thread function to handle mailbox timeout
* @phba: Pointer to HBA context object.
*
* This function is called from worker thread when a mailbox command times out.
@@ -3252,6 +3248,21 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring;
+ /* Check the pmbox pointer first. There is a race condition
+ * between the mbox timeout handler getting executed in the
+ * worklist and the mailbox actually completing. When this
+ * race condition occurs, the mbox_active will be NULL.
+ */
+ spin_lock_irq(&phba->hbalock);
+ if (pmbox == NULL) {
+ lpfc_printf_log(phba, KERN_WARNING,
+ LOG_MBOX | LOG_SLI,
+ "0353 Active Mailbox cleared - mailbox timeout "
+ "exiting\n");
+ spin_unlock_irq(&phba->hbalock);
+ return;
+ }
+
/* Mbox cmd <mbxCommand> timeout */
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
"0310 Mailbox command x%x timeout Data: x%x x%x x%p\n",
@@ -3259,6 +3270,7 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
phba->pport->port_state,
phba->sli.sli_flag,
phba->sli.mbox_active);
+ spin_unlock_irq(&phba->hbalock);
/* Setting state unknown so lpfc_sli_abort_iocb_ring
* would get IOCB_ERROR from lpfc_sli_issue_iocb, allowing
@@ -3295,7 +3307,7 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
}
/**
- * lpfc_sli_issue_mbox: Issue a mailbox command to firmware.
+ * lpfc_sli_issue_mbox - Issue a mailbox command to firmware
* @phba: Pointer to HBA context object.
* @pmbox: Pointer to mailbox object.
* @flag: Flag indicating how the mailbox need to be processed.
@@ -3365,6 +3377,12 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
goto out_not_finished;
}
+ /* If HBA has a deferred error attention, fail the iocb. */
+ if (unlikely(phba->hba_flag & DEFER_ERATT)) {
+ spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+ goto out_not_finished;
+ }
+
psli = &phba->sli;
mb = &pmbox->mb;
@@ -3632,7 +3650,7 @@ out_not_finished:
}
/**
- * __lpfc_sli_ringtx_put: Add an iocb to the txq.
+ * __lpfc_sli_ringtx_put - Add an iocb to the txq
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @piocb: Pointer to address of newly added command iocb.
@@ -3651,7 +3669,7 @@ __lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
/**
- * lpfc_sli_next_iocb: Get the next iocb in the txq.
+ * lpfc_sli_next_iocb - Get the next iocb in the txq
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @piocb: Pointer to address of newly added command iocb.
@@ -3683,7 +3701,7 @@ lpfc_sli_next_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
/**
- * __lpfc_sli_issue_iocb: Lockless version of lpfc_sli_issue_iocb.
+ * __lpfc_sli_issue_iocb - Lockless version of lpfc_sli_issue_iocb
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @piocb: Pointer to command iocb.
@@ -3729,6 +3747,10 @@ __lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
if (unlikely(pci_channel_offline(phba->pcidev)))
return IOCB_ERROR;
+ /* If HBA has a deferred error attention, fail the iocb. */
+ if (unlikely(phba->hba_flag & DEFER_ERATT))
+ return IOCB_ERROR;
+
/*
* We should never get an IOCB if we are in a < LINK_DOWN state
*/
@@ -3813,7 +3835,7 @@ __lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
/**
- * lpfc_sli_issue_iocb: Wrapper function for __lpfc_sli_issue_iocb.
+ * lpfc_sli_issue_iocb - Wrapper function for __lpfc_sli_issue_iocb
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @piocb: Pointer to command iocb.
@@ -3840,7 +3862,7 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
/**
- * lpfc_extra_ring_setup: Extra ring setup function.
+ * lpfc_extra_ring_setup - Extra ring setup function
* @phba: Pointer to HBA context object.
*
* This function is called while driver attaches with the
@@ -3886,7 +3908,7 @@ lpfc_extra_ring_setup( struct lpfc_hba *phba)
}
/**
- * lpfc_sli_async_event_handler: ASYNC iocb handler function.
+ * lpfc_sli_async_event_handler - ASYNC iocb handler function
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @iocbq: Pointer to iocb object.
@@ -3907,6 +3929,7 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba,
uint16_t temp;
struct temp_event temp_event_data;
struct Scsi_Host *shost;
+ uint32_t *iocb_w;
icmd = &iocbq->iocb;
evt_code = icmd->un.asyncstat.evt_code;
@@ -3914,13 +3937,23 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba,
if ((evt_code != ASYNC_TEMP_WARN) &&
(evt_code != ASYNC_TEMP_SAFE)) {
+ iocb_w = (uint32_t *) icmd;
lpfc_printf_log(phba,
KERN_ERR,
LOG_SLI,
"0346 Ring %d handler: unexpected ASYNC_STATUS"
- " evt_code 0x%x\n",
+ " evt_code 0x%x \n"
+ "W0 0x%08x W1 0x%08x W2 0x%08x W3 0x%08x\n"
+ "W4 0x%08x W5 0x%08x W6 0x%08x W7 0x%08x\n"
+ "W8 0x%08x W9 0x%08x W10 0x%08x W11 0x%08x\n"
+ "W12 0x%08x W13 0x%08x W14 0x%08x W15 0x%08x\n",
pring->ringno,
- icmd->un.asyncstat.evt_code);
+ icmd->un.asyncstat.evt_code,
+ iocb_w[0], iocb_w[1], iocb_w[2], iocb_w[3],
+ iocb_w[4], iocb_w[5], iocb_w[6], iocb_w[7],
+ iocb_w[8], iocb_w[9], iocb_w[10], iocb_w[11],
+ iocb_w[12], iocb_w[13], iocb_w[14], iocb_w[15]);
+
return;
}
temp_event_data.data = (uint32_t)temp;
@@ -3954,7 +3987,7 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba,
/**
- * lpfc_sli_setup: SLI ring setup function.
+ * lpfc_sli_setup - SLI ring setup function
* @phba: Pointer to HBA context object.
*
* lpfc_sli_setup sets up rings of the SLI interface with
@@ -4076,7 +4109,7 @@ lpfc_sli_setup(struct lpfc_hba *phba)
}
/**
- * lpfc_sli_queue_setup: Queue initialization function.
+ * lpfc_sli_queue_setup - Queue initialization function
* @phba: Pointer to HBA context object.
*
* lpfc_sli_queue_setup sets up mailbox queues and iocb queues for each
@@ -4115,7 +4148,7 @@ lpfc_sli_queue_setup(struct lpfc_hba *phba)
}
/**
- * lpfc_sli_host_down: Vport cleanup function.
+ * lpfc_sli_host_down - Vport cleanup function
* @vport: Pointer to virtual port object.
*
* lpfc_sli_host_down is called to clean up the resources
@@ -4179,22 +4212,14 @@ lpfc_sli_host_down(struct lpfc_vport *vport)
spin_unlock_irqrestore(&phba->hbalock, flags);
- while (!list_empty(&completions)) {
- list_remove_head(&completions, iocb, struct lpfc_iocbq, list);
-
- if (!iocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, iocb);
- else {
- iocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT;
- iocb->iocb.un.ulpWord[4] = IOERR_SLI_DOWN;
- (iocb->iocb_cmpl) (phba, iocb, iocb);
- }
- }
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_DOWN);
return 1;
}
/**
- * lpfc_sli_hba_down: Resource cleanup function for the HBA.
+ * lpfc_sli_hba_down - Resource cleanup function for the HBA
* @phba: Pointer to HBA context object.
*
* This function cleans up all iocb, buffers, mailbox commands
@@ -4216,8 +4241,6 @@ lpfc_sli_hba_down(struct lpfc_hba *phba)
struct lpfc_sli_ring *pring;
struct lpfc_dmabuf *buf_ptr;
LPFC_MBOXQ_t *pmb;
- struct lpfc_iocbq *iocb;
- IOCB_t *cmd = NULL;
int i;
unsigned long flags = 0;
@@ -4245,18 +4268,9 @@ lpfc_sli_hba_down(struct lpfc_hba *phba)
}
spin_unlock_irqrestore(&phba->hbalock, flags);
- while (!list_empty(&completions)) {
- list_remove_head(&completions, iocb, struct lpfc_iocbq, list);
- cmd = &iocb->iocb;
-
- if (!iocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, iocb);
- else {
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_DOWN;
- (iocb->iocb_cmpl) (phba, iocb, iocb);
- }
- }
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_DOWN);
spin_lock_irqsave(&phba->hbalock, flags);
list_splice_init(&phba->elsbuf, &completions);
@@ -4299,7 +4313,7 @@ lpfc_sli_hba_down(struct lpfc_hba *phba)
}
/**
- * lpfc_sli_pcimem_bcopy: SLI memory copy function.
+ * lpfc_sli_pcimem_bcopy - SLI memory copy function
* @srcp: Source memory pointer.
* @destp: Destination memory pointer.
* @cnt: Number of words required to be copied.
@@ -4329,7 +4343,7 @@ lpfc_sli_pcimem_bcopy(void *srcp, void *destp, uint32_t cnt)
/**
- * lpfc_sli_ringpostbuf_put: Function to add a buffer to postbufq.
+ * lpfc_sli_ringpostbuf_put - Function to add a buffer to postbufq
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @mp: Pointer to driver buffer object.
@@ -4352,8 +4366,7 @@ lpfc_sli_ringpostbuf_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
/**
- * lpfc_sli_get_buffer_tag: Tag allocation function for a buffer posted
- * using CMD_QUE_XRI64_CX iocb.
+ * lpfc_sli_get_buffer_tag - allocates a tag for a CMD_QUE_XRI64_CX buffer
* @phba: Pointer to HBA context object.
*
* When HBQ is enabled, buffers are searched based on tags. This function
@@ -4378,8 +4391,7 @@ lpfc_sli_get_buffer_tag(struct lpfc_hba *phba)
}
/**
- * lpfc_sli_ring_taggedbuf_get: Search HBQ buffer associated with
- * posted using CMD_QUE_XRI64_CX iocb.
+ * lpfc_sli_ring_taggedbuf_get - find HBQ buffer associated with given tag
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @tag: Buffer tag.
@@ -4422,8 +4434,7 @@ lpfc_sli_ring_taggedbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
/**
- * lpfc_sli_ringpostbuf_get: SLI2 buffer search function for
- * unsolicited ct and els events.
+ * lpfc_sli_ringpostbuf_get - search buffers for unsolicited CT and ELS events
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @phys: DMA address of the buffer.
@@ -4466,7 +4477,7 @@ lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
/**
- * lpfc_sli_abort_els_cmpl: Completion handler for the els abort iocbs.
+ * lpfc_sli_abort_els_cmpl - Completion handler for the els abort iocbs
* @phba: Pointer to HBA context object.
* @cmdiocb: Pointer to driver command iocb object.
* @rspiocb: Pointer to driver response iocb object.
@@ -4542,7 +4553,7 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
}
/**
- * lpfc_ignore_els_cmpl: Completion handler for aborted ELS command.
+ * lpfc_ignore_els_cmpl - Completion handler for aborted ELS command
* @phba: Pointer to HBA context object.
* @cmdiocb: Pointer to driver command iocb object.
* @rspiocb: Pointer to driver response iocb object.
@@ -4572,7 +4583,7 @@ lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
}
/**
- * lpfc_sli_issue_abort_iotag: Abort function for a command iocb.
+ * lpfc_sli_issue_abort_iotag - Abort function for a command iocb
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @cmdiocb: Pointer to driver command iocb object.
@@ -4658,15 +4669,14 @@ abort_iotag_exit:
}
/**
- * lpfc_sli_validate_fcp_iocb: Filtering function, used to find commands
- * associated with a vport/SCSI target/lun.
+ * lpfc_sli_validate_fcp_iocb - find commands associated with a vport or LUN
* @iocbq: Pointer to driver iocb object.
* @vport: Pointer to driver virtual port object.
* @tgt_id: SCSI ID of the target.
* @lun_id: LUN ID of the scsi device.
* @ctx_cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST
*
- * This function acts as iocb filter for functions which abort or count
+ * This function acts as an iocb filter for functions which abort or count
* all FCP iocbs pending on a lun/SCSI target/SCSI host. It will return
* 0 if the filtering criteria is met for the given iocb and will return
* 1 if the filtering criteria is not met.
@@ -4724,7 +4734,7 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport,
}
/**
- * lpfc_sli_sum_iocb: Function to count the number of FCP iocbs pending.
+ * lpfc_sli_sum_iocb - Function to count the number of FCP iocbs pending
* @vport: Pointer to virtual port.
* @tgt_id: SCSI ID of the target.
* @lun_id: LUN ID of the scsi device.
@@ -4762,8 +4772,7 @@ lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id,
}
/**
- * lpfc_sli_abort_fcp_cmpl: Completion handler function for an aborted
- * FCP iocb.
+ * lpfc_sli_abort_fcp_cmpl - Completion handler function for aborted FCP IOCBs
* @phba: Pointer to HBA context object
* @cmdiocb: Pointer to command iocb object.
* @rspiocb: Pointer to response iocb object.
@@ -4781,8 +4790,7 @@ lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
}
/**
- * lpfc_sli_abort_iocb: This function issue abort for all SCSI commands
- * pending on a SCSI host(vport)/target/lun.
+ * lpfc_sli_abort_iocb - issue abort for all commands on a host/target/LUN
* @vport: Pointer to virtual port.
* @pring: Pointer to driver SLI ring object.
* @tgt_id: SCSI ID of the target.
@@ -4854,8 +4862,7 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
}
/**
- * lpfc_sli_wake_iocb_wait: iocb completion handler for iocb issued using
- * lpfc_sli_issue_iocb_wait.
+ * lpfc_sli_wake_iocb_wait - lpfc_sli_issue_iocb_wait's completion handler
* @phba: Pointer to HBA context object.
* @cmdiocbq: Pointer to command iocb.
* @rspiocbq: Pointer to response iocb.
@@ -4893,7 +4900,7 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba,
}
/**
- * lpfc_sli_issue_iocb_wait: Synchronous function to issue iocb commands.
+ * lpfc_sli_issue_iocb_wait - Synchronous function to issue iocb commands
* @phba: Pointer to HBA context object..
* @pring: Pointer to sli ring.
* @piocb: Pointer to command iocb.
@@ -5000,7 +5007,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
}
/**
- * lpfc_sli_issue_mbox_wait: Synchronous function to issue mailbox.
+ * lpfc_sli_issue_mbox_wait - Synchronous function to issue mailbox
* @phba: Pointer to HBA context object.
* @pmboxq: Pointer to driver mailbox object.
* @timeout: Timeout in number of seconds.
@@ -5070,7 +5077,7 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
}
/**
- * lpfc_sli_flush_mbox_queue: mailbox queue cleanup function.
+ * lpfc_sli_flush_mbox_queue - mailbox queue cleanup function
* @phba: Pointer to HBA context.
*
* This function is called to cleanup any pending mailbox
@@ -5113,7 +5120,7 @@ lpfc_sli_flush_mbox_queue(struct lpfc_hba * phba)
}
/**
- * lpfc_sli_check_eratt: check error attention events
+ * lpfc_sli_check_eratt - check error attention events
* @phba: Pointer to HBA context.
*
* This function is called form timer soft interrupt context to check HBA's
@@ -5145,11 +5152,31 @@ lpfc_sli_check_eratt(struct lpfc_hba *phba)
return 0;
}
+ /*
+ * If there is deferred error attention, do not check for error
+ * attention
+ */
+ if (unlikely(phba->hba_flag & DEFER_ERATT)) {
+ spin_unlock_irq(&phba->hbalock);
+ return 0;
+ }
+
/* Read chip Host Attention (HA) register */
ha_copy = readl(phba->HAregaddr);
if (ha_copy & HA_ERATT) {
/* Read host status register to retrieve error event */
lpfc_sli_read_hs(phba);
+
+ /* Check if there is a deferred error condition is active */
+ if ((HS_FFER1 & phba->work_hs) &&
+ ((HS_FFER2 | HS_FFER3 | HS_FFER4 | HS_FFER5 |
+ HS_FFER6 | HS_FFER7) & phba->work_hs)) {
+ phba->hba_flag |= DEFER_ERATT;
+ /* Clear all interrupt enable conditions */
+ writel(0, phba->HCregaddr);
+ readl(phba->HCregaddr);
+ }
+
/* Set the driver HA work bitmap */
phba->work_ha |= HA_ERATT;
/* Indicate polling handles this ERATT */
@@ -5162,7 +5189,7 @@ lpfc_sli_check_eratt(struct lpfc_hba *phba)
}
/**
- * lpfc_sp_intr_handler: The slow-path interrupt handler of lpfc driver.
+ * lpfc_sp_intr_handler - The slow-path interrupt handler of lpfc driver
* @irq: Interrupt number.
* @dev_id: The device context pointer.
*
@@ -5238,6 +5265,16 @@ lpfc_sp_intr_handler(int irq, void *dev_id)
/* Indicate interrupt handler handles ERATT */
phba->hba_flag |= HBA_ERATT_HANDLED;
}
+
+ /*
+ * If there is deferred error attention, do not check for any
+ * interrupt.
+ */
+ if (unlikely(phba->hba_flag & DEFER_ERATT)) {
+ spin_unlock_irq(&phba->hbalock);
+ return IRQ_NONE;
+ }
+
/* Clear up only attention source related to slow-path */
writel((ha_copy & (HA_MBATT | HA_R2_CLR_MSK)),
phba->HAregaddr);
@@ -5309,8 +5346,22 @@ lpfc_sp_intr_handler(int irq, void *dev_id)
}
}
spin_lock_irqsave(&phba->hbalock, iflag);
- if (work_ha_copy & HA_ERATT)
+ if (work_ha_copy & HA_ERATT) {
lpfc_sli_read_hs(phba);
+ /*
+ * Check if there is a deferred error condition
+ * is active
+ */
+ if ((HS_FFER1 & phba->work_hs) &&
+ ((HS_FFER2 | HS_FFER3 | HS_FFER4 | HS_FFER5 |
+ HS_FFER6 | HS_FFER7) & phba->work_hs)) {
+ phba->hba_flag |= DEFER_ERATT;
+ /* Clear all interrupt enable conditions */
+ writel(0, phba->HCregaddr);
+ readl(phba->HCregaddr);
+ }
+ }
+
if ((work_ha_copy & HA_MBATT) && (phba->sli.mbox_active)) {
pmb = phba->sli.mbox_active;
pmbox = &pmb->mb;
@@ -5423,7 +5474,7 @@ send_current_mbox:
} /* lpfc_sp_intr_handler */
/**
- * lpfc_fp_intr_handler: The fast-path interrupt handler of lpfc driver.
+ * lpfc_fp_intr_handler - The fast-path interrupt handler of lpfc driver
* @irq: Interrupt number.
* @dev_id: The device context pointer.
*
@@ -5474,6 +5525,14 @@ lpfc_fp_intr_handler(int irq, void *dev_id)
ha_copy = readl(phba->HAregaddr);
/* Clear up only attention source related to fast-path */
spin_lock_irqsave(&phba->hbalock, iflag);
+ /*
+ * If there is deferred error attention, do not check for
+ * any interrupt.
+ */
+ if (unlikely(phba->hba_flag & DEFER_ERATT)) {
+ spin_unlock_irq(&phba->hbalock);
+ return IRQ_NONE;
+ }
writel((ha_copy & (HA_R0_CLR_MSK | HA_R1_CLR_MSK)),
phba->HAregaddr);
readl(phba->HAregaddr); /* flush */
@@ -5510,7 +5569,7 @@ lpfc_fp_intr_handler(int irq, void *dev_id)
} /* lpfc_fp_intr_handler */
/**
- * lpfc_intr_handler: The device-level interrupt handler of lpfc driver.
+ * lpfc_intr_handler - The device-level interrupt handler of lpfc driver
* @irq: Interrupt number.
* @dev_id: The device context pointer.
*
@@ -5566,6 +5625,14 @@ lpfc_intr_handler(int irq, void *dev_id)
phba->hba_flag |= HBA_ERATT_HANDLED;
}
+ /*
+ * If there is deferred error attention, do not check for any interrupt.
+ */
+ if (unlikely(phba->hba_flag & DEFER_ERATT)) {
+ spin_unlock_irq(&phba->hbalock);
+ return IRQ_NONE;
+ }
+
/* Clear attention sources except link and error attentions */
writel((phba->ha_copy & ~(HA_LATT | HA_ERATT)), phba->HAregaddr);
readl(phba->HAregaddr); /* flush */
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 7e32e95c5392..e599519e3078 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2008 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2009 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
@@ -18,7 +18,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "8.3.0"
+#define LPFC_DRIVER_VERSION "8.3.1"
#define LPFC_DRIVER_NAME "lpfc"
#define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp"
@@ -26,4 +26,4 @@
#define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \
LPFC_DRIVER_VERSION
-#define LPFC_COPYRIGHT "Copyright(c) 2004-2008 Emulex. All rights reserved."
+#define LPFC_COPYRIGHT "Copyright(c) 2004-2009 Emulex. All rights reserved."
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
index 63b54c66756c..917ad56b0aff 100644
--- a/drivers/scsi/lpfc/lpfc_vport.c
+++ b/drivers/scsi/lpfc/lpfc_vport.c
@@ -206,7 +206,7 @@ lpfc_unique_wwpn(struct lpfc_hba *phba, struct lpfc_vport *new_vport)
}
/**
- * lpfc_discovery_wait: Wait for driver discovery to quiesce.
+ * lpfc_discovery_wait - Wait for driver discovery to quiesce
* @vport: The virtual port for which this call is being executed.
*
* This driver calls this routine specifically from lpfc_vport_delete
@@ -741,7 +741,7 @@ lpfc_destroy_vport_work_array(struct lpfc_hba *phba, struct lpfc_vport **vports)
/**
- * lpfc_vport_reset_stat_data: Reset the statistical data for the vport.
+ * lpfc_vport_reset_stat_data - Reset the statistical data for the vport
* @vport: Pointer to vport object.
*
* This function resets the statistical data for the vport. This function
@@ -763,8 +763,7 @@ lpfc_vport_reset_stat_data(struct lpfc_vport *vport)
/**
- * lpfc_alloc_bucket: Allocate data buffer required for collecting
- * statistical data.
+ * lpfc_alloc_bucket - Allocate data buffer required for statistical data
* @vport: Pointer to vport object.
*
* This function allocates data buffer required for all the FC
@@ -797,8 +796,7 @@ lpfc_alloc_bucket(struct lpfc_vport *vport)
}
/**
- * lpfc_free_bucket: Free data buffer required for collecting
- * statistical data.
+ * lpfc_free_bucket - Free data buffer required for statistical data
* @vport: Pointer to vport object.
*
* Th function frees statistical data buffer of all the FC
diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h
index 795201fa0b48..512c2cc1a33f 100644
--- a/drivers/scsi/megaraid.h
+++ b/drivers/scsi/megaraid.h
@@ -469,7 +469,7 @@ typedef struct {
u8 type; /* Type of the device */
u8 cur_status; /* current status of the device */
u8 tag_depth; /* Level of tagging */
- u8 sync_neg; /* sync negotiation - ENABLE or DISBALE */
+ u8 sync_neg; /* sync negotiation - ENABLE or DISABLE */
u32 size; /* configurable size in terms of 512 byte
blocks */
}__attribute__ ((packed)) phys_drv;
diff --git a/drivers/scsi/megaraid/mbox_defs.h b/drivers/scsi/megaraid/mbox_defs.h
index 170399ef06f4..b25b74764ec3 100644
--- a/drivers/scsi/megaraid/mbox_defs.h
+++ b/drivers/scsi/megaraid/mbox_defs.h
@@ -686,7 +686,7 @@ typedef struct {
* @type : Type of the device
* @cur_status : current status of the device
* @tag_depth : Level of tagging
- * @sync_neg : sync negotiation - ENABLE or DISBALE
+ * @sync_neg : sync negotiation - ENABLE or DISABLE
* @size : configurable size in terms of 512 byte
*/
typedef struct {
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 52427a8324f5..f3da592f7bcc 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -636,6 +636,14 @@ _base_unmask_interrupts(struct MPT2SAS_ADAPTER *ioc)
static irqreturn_t
_base_interrupt(int irq, void *bus_id)
{
+ union reply_descriptor {
+ u64 word;
+ struct {
+ u32 low;
+ u32 high;
+ } u;
+ };
+ union reply_descriptor rd;
u32 post_index, post_index_next, completed_cmds;
u8 request_desript_type;
u16 smid;
@@ -656,7 +664,8 @@ _base_interrupt(int irq, void *bus_id)
completed_cmds = 0;
do {
- if (ioc->reply_post_free[post_index].Words == ~0ULL)
+ rd.word = ioc->reply_post_free[post_index].Words;
+ if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX)
goto out;
reply = 0;
cb_idx = 0xFF;
@@ -721,7 +730,7 @@ _base_interrupt(int irq, void *bus_id)
for (i = 0 ; i < completed_cmds; i++) {
post_index = post_index_next;
/* poison the reply post descriptor */
- ioc->reply_post_free[post_index_next].Words = ~0ULL;
+ ioc->reply_post_free[post_index_next].Words = ULLONG_MAX;
post_index_next = (post_index ==
(ioc->reply_post_queue_depth - 1))
? 0 : post_index + 1;
@@ -855,9 +864,9 @@ _base_config_dma_addressing(struct MPT2SAS_ADAPTER *ioc, struct pci_dev *pdev)
if (sizeof(dma_addr_t) > 4) {
const uint64_t required_mask =
dma_get_required_mask(&pdev->dev);
- if ((required_mask > DMA_32BIT_MASK) && !pci_set_dma_mask(pdev,
- DMA_64BIT_MASK) && !pci_set_consistent_dma_mask(pdev,
- DMA_64BIT_MASK)) {
+ if ((required_mask > DMA_BIT_MASK(32)) && !pci_set_dma_mask(pdev,
+ DMA_BIT_MASK(64)) && !pci_set_consistent_dma_mask(pdev,
+ DMA_BIT_MASK(64))) {
ioc->base_add_sg_single = &_base_add_sg_single_64;
ioc->sge_size = sizeof(Mpi2SGESimple64_t);
desc = "64";
@@ -865,8 +874,8 @@ _base_config_dma_addressing(struct MPT2SAS_ADAPTER *ioc, struct pci_dev *pdev)
}
}
- if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)
- && !pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
+ if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
+ && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
ioc->base_add_sg_single = &_base_add_sg_single_32;
ioc->sge_size = sizeof(Mpi2SGESimple32_t);
desc = "32";
@@ -1387,6 +1396,64 @@ mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid,
}
/**
+ * _base_display_dell_branding - Disply branding string
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+static void
+_base_display_dell_branding(struct MPT2SAS_ADAPTER *ioc)
+{
+ char dell_branding[MPT2SAS_DELL_BRANDING_SIZE];
+
+ if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_DELL)
+ return;
+
+ memset(dell_branding, 0, MPT2SAS_DELL_BRANDING_SIZE);
+ switch (ioc->pdev->subsystem_device) {
+ case MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID:
+ strncpy(dell_branding, MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING,
+ MPT2SAS_DELL_BRANDING_SIZE - 1);
+ break;
+ case MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID:
+ strncpy(dell_branding, MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING,
+ MPT2SAS_DELL_BRANDING_SIZE - 1);
+ break;
+ case MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID:
+ strncpy(dell_branding,
+ MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING,
+ MPT2SAS_DELL_BRANDING_SIZE - 1);
+ break;
+ case MPT2SAS_DELL_PERC_H200_MODULAR_SSDID:
+ strncpy(dell_branding,
+ MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING,
+ MPT2SAS_DELL_BRANDING_SIZE - 1);
+ break;
+ case MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID:
+ strncpy(dell_branding,
+ MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING,
+ MPT2SAS_DELL_BRANDING_SIZE - 1);
+ break;
+ case MPT2SAS_DELL_PERC_H200_SSDID:
+ strncpy(dell_branding, MPT2SAS_DELL_PERC_H200_BRANDING,
+ MPT2SAS_DELL_BRANDING_SIZE - 1);
+ break;
+ case MPT2SAS_DELL_6GBPS_SAS_SSDID:
+ strncpy(dell_branding, MPT2SAS_DELL_6GBPS_SAS_BRANDING,
+ MPT2SAS_DELL_BRANDING_SIZE - 1);
+ break;
+ default:
+ sprintf(dell_branding, "0x%4X", ioc->pdev->subsystem_device);
+ break;
+ }
+
+ printk(MPT2SAS_INFO_FMT "%s: Vendor(0x%04X), Device(0x%04X),"
+ " SSVID(0x%04X), SSDID(0x%04X)\n", ioc->name, dell_branding,
+ ioc->pdev->vendor, ioc->pdev->device, ioc->pdev->subsystem_vendor,
+ ioc->pdev->subsystem_device);
+}
+
+/**
* _base_display_ioc_capabilities - Disply IOC's capabilities.
* @ioc: per adapter object
*
@@ -1427,6 +1494,8 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
i++;
}
+ _base_display_dell_branding(ioc);
+
i = 0;
printk("), ");
printk("Capabilities=(");
@@ -3068,7 +3137,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
/* initialize Reply Post Free Queue */
for (i = 0; i < ioc->reply_post_queue_depth; i++)
- ioc->reply_post_free[i].Words = ~0ULL;
+ ioc->reply_post_free[i].Words = ULLONG_MAX;
r = _base_send_ioc_init(ioc, VF_ID, sleep_flag);
if (r)
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index 6945ff4d382e..babd4cc0cb25 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -68,11 +68,11 @@
#define MPT2SAS_DRIVER_NAME "mpt2sas"
#define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>"
#define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver"
-#define MPT2SAS_DRIVER_VERSION "00.100.11.16"
+#define MPT2SAS_DRIVER_VERSION "01.100.02.00"
#define MPT2SAS_MAJOR_VERSION 00
#define MPT2SAS_MINOR_VERSION 100
-#define MPT2SAS_BUILD_VERSION 11
-#define MPT2SAS_RELEASE_VERSION 16
+#define MPT2SAS_BUILD_VERSION 02
+#define MPT2SAS_RELEASE_VERSION 00
/*
* Set MPT2SAS_SG_DEPTH value based on user input.
@@ -130,6 +130,30 @@
#define MPT2SAS_ERR_FMT KERN_ERR MPT2SAS_FMT
/*
+ * Dell HBA branding
+ */
+#define MPT2SAS_DELL_BRANDING_SIZE 32
+
+#define MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING "Dell 6Gbps SAS HBA"
+#define MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING "Dell PERC H200 Adapter"
+#define MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING "Dell PERC H200 Integrated"
+#define MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING "Dell PERC H200 Modular"
+#define MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING "Dell PERC H200 Embedded"
+#define MPT2SAS_DELL_PERC_H200_BRANDING "Dell PERC H200"
+#define MPT2SAS_DELL_6GBPS_SAS_BRANDING "Dell 6Gbps SAS"
+
+/*
+ * Dell HBA SSDIDs
+ */
+#define MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID 0x1F1C
+#define MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID 0x1F1D
+#define MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID 0x1F1E
+#define MPT2SAS_DELL_PERC_H200_MODULAR_SSDID 0x1F1F
+#define MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID 0x1F20
+#define MPT2SAS_DELL_PERC_H200_SSDID 0x1F21
+#define MPT2SAS_DELL_6GBPS_SAS_SSDID 0x1F22
+
+/*
* per target private data
*/
#define MPT_TARGET_FLAGS_RAID_COMPONENT 0x01
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
index 2d4f85c9d7a1..ba6ab170bdf0 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -64,6 +64,9 @@
static struct fasync_struct *async_queue;
static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait);
+static int _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type,
+ u8 *issue_reset);
+
/**
* enum block_state - blocking state
* @NON_BLOCKING: non blocking
@@ -378,10 +381,22 @@ _ctl_verify_adapter(int ioc_number, struct MPT2SAS_ADAPTER **iocpp)
void
mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
{
+ int i;
+ u8 issue_reset;
+
switch (reset_phase) {
case MPT2_IOC_PRE_RESET:
dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
"MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
+ for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
+ if (!(ioc->diag_buffer_status[i] &
+ MPT2_DIAG_BUFFER_IS_REGISTERED))
+ continue;
+ if ((ioc->diag_buffer_status[i] &
+ MPT2_DIAG_BUFFER_IS_RELEASED))
+ continue;
+ _ctl_send_release(ioc, i, &issue_reset);
+ }
break;
case MPT2_IOC_AFTER_RESET:
dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
@@ -395,6 +410,17 @@ mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
case MPT2_IOC_DONE_RESET:
dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
"MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
+
+ for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
+ if (!(ioc->diag_buffer_status[i] &
+ MPT2_DIAG_BUFFER_IS_REGISTERED))
+ continue;
+ if ((ioc->diag_buffer_status[i] &
+ MPT2_DIAG_BUFFER_IS_RELEASED))
+ continue;
+ ioc->diag_buffer_status[i] |=
+ MPT2_DIAG_BUFFER_IS_DIAG_RESET;
+ }
break;
}
}
@@ -714,8 +740,10 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
if (tm_request->TaskType ==
MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
- if (_ctl_do_task_abort(ioc, &karg, tm_request))
+ if (_ctl_do_task_abort(ioc, &karg, tm_request)) {
+ mpt2sas_base_free_smid(ioc, smid);
goto out;
+ }
}
mutex_lock(&ioc->tm_cmds.mutex);
@@ -915,9 +943,9 @@ _ctl_getiocinfo(void __user *arg)
karg.pci_information.u.bits.function = PCI_FUNC(ioc->pdev->devfn);
karg.pci_information.segment_id = pci_domain_nr(ioc->pdev->bus);
karg.firmware_version = ioc->facts.FWVersion.Word;
- strncpy(karg.driver_version, MPT2SAS_DRIVER_VERSION,
- MPT2_IOCTL_VERSION_LENGTH);
- karg.driver_version[MPT2_IOCTL_VERSION_LENGTH - 1] = '\0';
+ strcpy(karg.driver_version, MPT2SAS_DRIVER_NAME);
+ strcat(karg.driver_version, "-");
+ strcat(karg.driver_version, MPT2SAS_DRIVER_VERSION);
karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
if (copy_to_user(arg, &karg, sizeof(karg))) {
@@ -1551,81 +1579,38 @@ _ctl_diag_query(void __user *arg)
}
/**
- * _ctl_diag_release - request to send Diag Release Message to firmware
- * @arg - user space buffer containing ioctl content
- * @state - NON_BLOCKING or BLOCKING
+ * _ctl_send_release - Diag Release Message
+ * @ioc: per adapter object
+ * @buffer_type - specifies either TRACE or SNAPSHOT
+ * @issue_reset - specifies whether host reset is required.
*
- * This allows ownership of the specified buffer to returned to the driver,
- * allowing an application to read the buffer without fear that firmware is
- * overwritting information in the buffer.
*/
-static long
-_ctl_diag_release(void __user *arg, enum block_state state)
+static int
+_ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset)
{
- struct mpt2_diag_release karg;
- struct MPT2SAS_ADAPTER *ioc;
- void *request_data;
- int rc;
Mpi2DiagReleaseRequest_t *mpi_request;
Mpi2DiagReleaseReply_t *mpi_reply;
- u8 buffer_type;
- unsigned long timeleft;
u16 smid;
u16 ioc_status;
- u8 issue_reset = 0;
-
- if (copy_from_user(&karg, arg, sizeof(karg))) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -EFAULT;
- }
- if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
- return -ENODEV;
+ u32 ioc_state;
+ int rc;
+ unsigned long timeleft;
dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
__func__));
- buffer_type = karg.unique_id & 0x000000ff;
- if (!_ctl_diag_capability(ioc, buffer_type)) {
- printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
- "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
- return -EPERM;
- }
-
- if ((ioc->diag_buffer_status[buffer_type] &
- MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
- printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not "
- "registered\n", ioc->name, __func__, buffer_type);
- return -EINVAL;
- }
-
- if (karg.unique_id != ioc->unique_id[buffer_type]) {
- printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
- "registered\n", ioc->name, __func__, karg.unique_id);
- return -EINVAL;
- }
-
- if (ioc->diag_buffer_status[buffer_type] &
- MPT2_DIAG_BUFFER_IS_RELEASED) {
- printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) "
- "is already released\n", ioc->name, __func__,
- buffer_type);
- return 0;
- }
-
- request_data = ioc->diag_buffer[buffer_type];
+ rc = 0;
+ *issue_reset = 0;
- if (!request_data) {
- printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for "
- "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
- return -ENOMEM;
+ ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
+ if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+ "skipping due to FAULT state\n", ioc->name,
+ __func__));
+ rc = -EAGAIN;
+ goto out;
}
- if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
- return -EAGAIN;
- else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
- return -ERESTARTSYS;
-
if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
ioc->name, __func__);
@@ -1641,7 +1626,6 @@ _ctl_diag_release(void __user *arg, enum block_state state)
goto out;
}
- rc = 0;
ioc->ctl_cmds.status = MPT2_CMD_PENDING;
memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
@@ -1660,8 +1644,9 @@ _ctl_diag_release(void __user *arg, enum block_state state)
_debug_dump_mf(mpi_request,
sizeof(Mpi2DiagReleaseRequest_t)/4);
if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
- issue_reset = 1;
- goto issue_host_reset;
+ *issue_reset = 1;
+ rc = -EFAULT;
+ goto out;
}
/* process the completed Reply Message Frame */
@@ -1687,14 +1672,101 @@ _ctl_diag_release(void __user *arg, enum block_state state)
rc = -EFAULT;
}
- issue_host_reset:
+ out:
+ ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
+ return rc;
+}
+
+/**
+ * _ctl_diag_release - request to send Diag Release Message to firmware
+ * @arg - user space buffer containing ioctl content
+ * @state - NON_BLOCKING or BLOCKING
+ *
+ * This allows ownership of the specified buffer to returned to the driver,
+ * allowing an application to read the buffer without fear that firmware is
+ * overwritting information in the buffer.
+ */
+static long
+_ctl_diag_release(void __user *arg, enum block_state state)
+{
+ struct mpt2_diag_release karg;
+ struct MPT2SAS_ADAPTER *ioc;
+ void *request_data;
+ int rc;
+ u8 buffer_type;
+ u8 issue_reset = 0;
+
+ if (copy_from_user(&karg, arg, sizeof(karg))) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+ if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
+ return -ENODEV;
+
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+ __func__));
+
+ buffer_type = karg.unique_id & 0x000000ff;
+ if (!_ctl_diag_capability(ioc, buffer_type)) {
+ printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
+ "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
+ return -EPERM;
+ }
+
+ if ((ioc->diag_buffer_status[buffer_type] &
+ MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
+ printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not "
+ "registered\n", ioc->name, __func__, buffer_type);
+ return -EINVAL;
+ }
+
+ if (karg.unique_id != ioc->unique_id[buffer_type]) {
+ printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
+ "registered\n", ioc->name, __func__, karg.unique_id);
+ return -EINVAL;
+ }
+
+ if (ioc->diag_buffer_status[buffer_type] &
+ MPT2_DIAG_BUFFER_IS_RELEASED) {
+ printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) "
+ "is already released\n", ioc->name, __func__,
+ buffer_type);
+ return 0;
+ }
+
+ request_data = ioc->diag_buffer[buffer_type];
+
+ if (!request_data) {
+ printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for "
+ "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
+ return -ENOMEM;
+ }
+
+ /* buffers were released by due to host reset */
+ if ((ioc->diag_buffer_status[buffer_type] &
+ MPT2_DIAG_BUFFER_IS_DIAG_RESET)) {
+ ioc->diag_buffer_status[buffer_type] |=
+ MPT2_DIAG_BUFFER_IS_RELEASED;
+ ioc->diag_buffer_status[buffer_type] &=
+ ~MPT2_DIAG_BUFFER_IS_DIAG_RESET;
+ printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) "
+ "was released due to host reset\n", ioc->name, __func__,
+ buffer_type);
+ return 0;
+ }
+
+ if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
+ return -EAGAIN;
+ else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
+ return -ERESTARTSYS;
+
+ rc = _ctl_send_release(ioc, buffer_type, &issue_reset);
+
if (issue_reset)
mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
FORCE_BIG_HAMMER);
- out:
-
- ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
mutex_unlock(&ioc->ctl_cmds.mutex);
return rc;
}
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.h b/drivers/scsi/mpt2sas/mpt2sas_ctl.h
index dbb6c0cf8889..4da11435533f 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.h
@@ -50,7 +50,7 @@
#endif
#define MPT2SAS_DEV_NAME "mpt2ctl"
-#define MPT2_MAGIC_NUMBER 'm'
+#define MPT2_MAGIC_NUMBER 'L'
#define MPT2_IOCTL_DEFAULT_TIMEOUT (10) /* in seconds */
/**
@@ -295,8 +295,9 @@ struct mpt2_ioctl_btdh_mapping {
/* status bits for ioc->diag_buffer_status */
-#define MPT2_DIAG_BUFFER_IS_REGISTERED (0x01)
-#define MPT2_DIAG_BUFFER_IS_RELEASED (0x02)
+#define MPT2_DIAG_BUFFER_IS_REGISTERED (0x01)
+#define MPT2_DIAG_BUFFER_IS_RELEASED (0x02)
+#define MPT2_DIAG_BUFFER_IS_DIAG_RESET (0x04)
/* application flags for mpt2_diag_register, mpt2_diag_query */
#define MPT2_APP_FLAGS_APP_OWNED (0x0001)
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 0c463c483c02..e3a7967259e7 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -119,7 +119,7 @@ struct sense_info {
*/
struct fw_event_work {
struct list_head list;
- struct delayed_work work;
+ struct work_struct work;
struct MPT2SAS_ADAPTER *ioc;
u8 VF_ID;
u8 host_reset_handling;
@@ -516,12 +516,8 @@ _scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc,
handle = sas_device->handle;
parent_handle = sas_device->parent_handle;
sas_address = sas_device->sas_address;
- if (!mpt2sas_transport_port_add(ioc, handle, parent_handle)) {
+ if (!mpt2sas_transport_port_add(ioc, handle, parent_handle))
_scsih_sas_device_remove(ioc, sas_device);
- } else if (!sas_device->starget) {
- mpt2sas_transport_port_remove(ioc, sas_address, parent_handle);
- _scsih_sas_device_remove(ioc, sas_device);
- }
}
/**
@@ -1203,7 +1199,9 @@ scsih_target_destroy(struct scsi_target *starget)
rphy = dev_to_rphy(starget->dev.parent);
sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
rphy->identify.sas_address);
- if (sas_device)
+ if (sas_device && (sas_device->starget == starget) &&
+ (sas_device->id == starget->id) &&
+ (sas_device->channel == starget->channel))
sas_device->starget = NULL;
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
@@ -2009,8 +2007,8 @@ _scsih_fw_event_add(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
spin_lock_irqsave(&ioc->fw_event_lock, flags);
list_add_tail(&fw_event->list, &ioc->fw_event_list);
- INIT_DELAYED_WORK(&fw_event->work, _firmware_event_work);
- queue_delayed_work(ioc->firmware_event_thread, &fw_event->work, 1);
+ INIT_WORK(&fw_event->work, _firmware_event_work);
+ queue_work(ioc->firmware_event_thread, &fw_event->work);
spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
}
@@ -2054,7 +2052,7 @@ _scsih_fw_event_requeue(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work
return;
spin_lock_irqsave(&ioc->fw_event_lock, flags);
- queue_delayed_work(ioc->firmware_event_thread, &fw_event->work, delay);
+ queue_work(ioc->firmware_event_thread, &fw_event->work);
spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
}
@@ -2863,8 +2861,9 @@ scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
struct sense_info data;
const void *sense_data = mpt2sas_base_get_sense_buffer(ioc,
smid);
- memcpy(scmd->sense_buffer, sense_data,
+ u32 sz = min_t(u32, SCSI_SENSE_BUFFERSIZE,
le32_to_cpu(mpi_reply->SenseCount));
+ memcpy(scmd->sense_buffer, sense_data, sz);
_scsih_normalize_sense(scmd->sense_buffer, &data);
/* failure prediction threshold exceeded */
if (data.asc == 0x5D)
@@ -3923,7 +3922,7 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
mpt2sas_scsih_issue_tm(ioc, handle, lun,
MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30);
- termination_count += le32_to_cpu(mpi_reply->TerminationCount);
+ ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
if ((mpi_reply->IOCStatus == MPI2_IOCSTATUS_SUCCESS) &&
(mpi_reply->ResponseCode ==
@@ -3933,10 +3932,10 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
continue;
mpt2sas_scsih_issue_tm(ioc, handle, lun,
- MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET, smid, 30);
+ MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET, 0, 30);
+ ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
termination_count += le32_to_cpu(mpi_reply->TerminationCount);
}
- ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
ioc->broadcast_aen_busy = 0;
mutex_unlock(&ioc->tm_cmds.mutex);
@@ -4962,7 +4961,7 @@ static void
_firmware_event_work(struct work_struct *work)
{
struct fw_event_work *fw_event = container_of(work,
- struct fw_event_work, work.work);
+ struct fw_event_work, work);
unsigned long flags;
struct MPT2SAS_ADAPTER *ioc = fw_event->ioc;
diff --git a/drivers/scsi/mvsas.c b/drivers/scsi/mvsas.c
deleted file mode 100644
index e4acebd10d1b..000000000000
--- a/drivers/scsi/mvsas.c
+++ /dev/null
@@ -1,3222 +0,0 @@
-/*
- mvsas.c - Marvell 88SE6440 SAS/SATA support
-
- Copyright 2007 Red Hat, Inc.
- Copyright 2008 Marvell. <kewei@marvell.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,
- 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, 675 Mass Ave, Cambridge,
- MA 02139, USA.
-
- ---------------------------------------------------------------
-
- Random notes:
- * hardware supports controlling the endian-ness of data
- structures. this permits elimination of all the le32_to_cpu()
- and cpu_to_le32() conversions.
-
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/ctype.h>
-#include <scsi/libsas.h>
-#include <scsi/scsi_tcq.h>
-#include <scsi/sas_ata.h>
-#include <asm/io.h>
-
-#define DRV_NAME "mvsas"
-#define DRV_VERSION "0.5.2"
-#define _MV_DUMP 0
-#define MVS_DISABLE_NVRAM
-#define MVS_DISABLE_MSI
-
-#define mr32(reg) readl(regs + MVS_##reg)
-#define mw32(reg,val) writel((val), regs + MVS_##reg)
-#define mw32_f(reg,val) do { \
- writel((val), regs + MVS_##reg); \
- readl(regs + MVS_##reg); \
- } while (0)
-
-#define MVS_ID_NOT_MAPPED 0x7f
-#define MVS_CHIP_SLOT_SZ (1U << mvi->chip->slot_width)
-
-/* offset for D2H FIS in the Received FIS List Structure */
-#define SATA_RECEIVED_D2H_FIS(reg_set) \
- ((void *) mvi->rx_fis + 0x400 + 0x100 * reg_set + 0x40)
-#define SATA_RECEIVED_PIO_FIS(reg_set) \
- ((void *) mvi->rx_fis + 0x400 + 0x100 * reg_set + 0x20)
-#define UNASSOC_D2H_FIS(id) \
- ((void *) mvi->rx_fis + 0x100 * id)
-
-#define for_each_phy(__lseq_mask, __mc, __lseq, __rest) \
- for ((__mc) = (__lseq_mask), (__lseq) = 0; \
- (__mc) != 0 && __rest; \
- (++__lseq), (__mc) >>= 1)
-
-/* driver compile-time configuration */
-enum driver_configuration {
- MVS_TX_RING_SZ = 1024, /* TX ring size (12-bit) */
- MVS_RX_RING_SZ = 1024, /* RX ring size (12-bit) */
- /* software requires power-of-2
- ring size */
-
- MVS_SLOTS = 512, /* command slots */
- MVS_SLOT_BUF_SZ = 8192, /* cmd tbl + IU + status + PRD */
- MVS_SSP_CMD_SZ = 64, /* SSP command table buffer size */
- MVS_ATA_CMD_SZ = 96, /* SATA command table buffer size */
- MVS_OAF_SZ = 64, /* Open address frame buffer size */
-
- MVS_RX_FIS_COUNT = 17, /* Optional rx'd FISs (max 17) */
-
- MVS_QUEUE_SIZE = 30, /* Support Queue depth */
- MVS_CAN_QUEUE = MVS_SLOTS - 1, /* SCSI Queue depth */
-};
-
-/* unchangeable hardware details */
-enum hardware_details {
- MVS_MAX_PHYS = 8, /* max. possible phys */
- MVS_MAX_PORTS = 8, /* max. possible ports */
- MVS_RX_FISL_SZ = 0x400 + (MVS_RX_FIS_COUNT * 0x100),
-};
-
-/* peripheral registers (BAR2) */
-enum peripheral_registers {
- SPI_CTL = 0x10, /* EEPROM control */
- SPI_CMD = 0x14, /* EEPROM command */
- SPI_DATA = 0x18, /* EEPROM data */
-};
-
-enum peripheral_register_bits {
- TWSI_RDY = (1U << 7), /* EEPROM interface ready */
- TWSI_RD = (1U << 4), /* EEPROM read access */
-
- SPI_ADDR_MASK = 0x3ffff, /* bits 17:0 */
-};
-
-/* enhanced mode registers (BAR4) */
-enum hw_registers {
- MVS_GBL_CTL = 0x04, /* global control */
- MVS_GBL_INT_STAT = 0x08, /* global irq status */
- MVS_GBL_PI = 0x0C, /* ports implemented bitmask */
- MVS_GBL_PORT_TYPE = 0xa0, /* port type */
-
- MVS_CTL = 0x100, /* SAS/SATA port configuration */
- MVS_PCS = 0x104, /* SAS/SATA port control/status */
- MVS_CMD_LIST_LO = 0x108, /* cmd list addr */
- MVS_CMD_LIST_HI = 0x10C,
- MVS_RX_FIS_LO = 0x110, /* RX FIS list addr */
- MVS_RX_FIS_HI = 0x114,
-
- MVS_TX_CFG = 0x120, /* TX configuration */
- MVS_TX_LO = 0x124, /* TX (delivery) ring addr */
- MVS_TX_HI = 0x128,
-
- MVS_TX_PROD_IDX = 0x12C, /* TX producer pointer */
- MVS_TX_CONS_IDX = 0x130, /* TX consumer pointer (RO) */
- MVS_RX_CFG = 0x134, /* RX configuration */
- MVS_RX_LO = 0x138, /* RX (completion) ring addr */
- MVS_RX_HI = 0x13C,
- MVS_RX_CONS_IDX = 0x140, /* RX consumer pointer (RO) */
-
- MVS_INT_COAL = 0x148, /* Int coalescing config */
- MVS_INT_COAL_TMOUT = 0x14C, /* Int coalescing timeout */
- MVS_INT_STAT = 0x150, /* Central int status */
- MVS_INT_MASK = 0x154, /* Central int enable */
- MVS_INT_STAT_SRS = 0x158, /* SATA register set status */
- MVS_INT_MASK_SRS = 0x15C,
-
- /* ports 1-3 follow after this */
- MVS_P0_INT_STAT = 0x160, /* port0 interrupt status */
- MVS_P0_INT_MASK = 0x164, /* port0 interrupt mask */
- MVS_P4_INT_STAT = 0x200, /* Port 4 interrupt status */
- MVS_P4_INT_MASK = 0x204, /* Port 4 interrupt enable mask */
-
- /* ports 1-3 follow after this */
- MVS_P0_SER_CTLSTAT = 0x180, /* port0 serial control/status */
- MVS_P4_SER_CTLSTAT = 0x220, /* port4 serial control/status */
-
- MVS_CMD_ADDR = 0x1B8, /* Command register port (addr) */
- MVS_CMD_DATA = 0x1BC, /* Command register port (data) */
-
- /* ports 1-3 follow after this */
- MVS_P0_CFG_ADDR = 0x1C0, /* port0 phy register address */
- MVS_P0_CFG_DATA = 0x1C4, /* port0 phy register data */
- MVS_P4_CFG_ADDR = 0x230, /* Port 4 config address */
- MVS_P4_CFG_DATA = 0x234, /* Port 4 config data */
-
- /* ports 1-3 follow after this */
- MVS_P0_VSR_ADDR = 0x1E0, /* port0 VSR address */
- MVS_P0_VSR_DATA = 0x1E4, /* port0 VSR data */
- MVS_P4_VSR_ADDR = 0x250, /* port 4 VSR addr */
- MVS_P4_VSR_DATA = 0x254, /* port 4 VSR data */
-};
-
-enum hw_register_bits {
- /* MVS_GBL_CTL */
- INT_EN = (1U << 1), /* Global int enable */
- HBA_RST = (1U << 0), /* HBA reset */
-
- /* MVS_GBL_INT_STAT */
- INT_XOR = (1U << 4), /* XOR engine event */
- INT_SAS_SATA = (1U << 0), /* SAS/SATA event */
-
- /* MVS_GBL_PORT_TYPE */ /* shl for ports 1-3 */
- SATA_TARGET = (1U << 16), /* port0 SATA target enable */
- MODE_AUTO_DET_PORT7 = (1U << 15), /* port0 SAS/SATA autodetect */
- MODE_AUTO_DET_PORT6 = (1U << 14),
- MODE_AUTO_DET_PORT5 = (1U << 13),
- MODE_AUTO_DET_PORT4 = (1U << 12),
- MODE_AUTO_DET_PORT3 = (1U << 11),
- MODE_AUTO_DET_PORT2 = (1U << 10),
- MODE_AUTO_DET_PORT1 = (1U << 9),
- MODE_AUTO_DET_PORT0 = (1U << 8),
- MODE_AUTO_DET_EN = MODE_AUTO_DET_PORT0 | MODE_AUTO_DET_PORT1 |
- MODE_AUTO_DET_PORT2 | MODE_AUTO_DET_PORT3 |
- MODE_AUTO_DET_PORT4 | MODE_AUTO_DET_PORT5 |
- MODE_AUTO_DET_PORT6 | MODE_AUTO_DET_PORT7,
- MODE_SAS_PORT7_MASK = (1U << 7), /* port0 SAS(1), SATA(0) mode */
- MODE_SAS_PORT6_MASK = (1U << 6),
- MODE_SAS_PORT5_MASK = (1U << 5),
- MODE_SAS_PORT4_MASK = (1U << 4),
- MODE_SAS_PORT3_MASK = (1U << 3),
- MODE_SAS_PORT2_MASK = (1U << 2),
- MODE_SAS_PORT1_MASK = (1U << 1),
- MODE_SAS_PORT0_MASK = (1U << 0),
- MODE_SAS_SATA = MODE_SAS_PORT0_MASK | MODE_SAS_PORT1_MASK |
- MODE_SAS_PORT2_MASK | MODE_SAS_PORT3_MASK |
- MODE_SAS_PORT4_MASK | MODE_SAS_PORT5_MASK |
- MODE_SAS_PORT6_MASK | MODE_SAS_PORT7_MASK,
-
- /* SAS_MODE value may be
- * dictated (in hw) by values
- * of SATA_TARGET & AUTO_DET
- */
-
- /* MVS_TX_CFG */
- TX_EN = (1U << 16), /* Enable TX */
- TX_RING_SZ_MASK = 0xfff, /* TX ring size, bits 11:0 */
-
- /* MVS_RX_CFG */
- RX_EN = (1U << 16), /* Enable RX */
- RX_RING_SZ_MASK = 0xfff, /* RX ring size, bits 11:0 */
-
- /* MVS_INT_COAL */
- COAL_EN = (1U << 16), /* Enable int coalescing */
-
- /* MVS_INT_STAT, MVS_INT_MASK */
- CINT_I2C = (1U << 31), /* I2C event */
- CINT_SW0 = (1U << 30), /* software event 0 */
- CINT_SW1 = (1U << 29), /* software event 1 */
- CINT_PRD_BC = (1U << 28), /* PRD BC err for read cmd */
- CINT_DMA_PCIE = (1U << 27), /* DMA to PCIE timeout */
- CINT_MEM = (1U << 26), /* int mem parity err */
- CINT_I2C_SLAVE = (1U << 25), /* slave I2C event */
- CINT_SRS = (1U << 3), /* SRS event */
- CINT_CI_STOP = (1U << 1), /* cmd issue stopped */
- CINT_DONE = (1U << 0), /* cmd completion */
-
- /* shl for ports 1-3 */
- CINT_PORT_STOPPED = (1U << 16), /* port0 stopped */
- CINT_PORT = (1U << 8), /* port0 event */
- CINT_PORT_MASK_OFFSET = 8,
- CINT_PORT_MASK = (0xFF << CINT_PORT_MASK_OFFSET),
-
- /* TX (delivery) ring bits */
- TXQ_CMD_SHIFT = 29,
- TXQ_CMD_SSP = 1, /* SSP protocol */
- TXQ_CMD_SMP = 2, /* SMP protocol */
- TXQ_CMD_STP = 3, /* STP/SATA protocol */
- TXQ_CMD_SSP_FREE_LIST = 4, /* add to SSP targ free list */
- TXQ_CMD_SLOT_RESET = 7, /* reset command slot */
- TXQ_MODE_I = (1U << 28), /* mode: 0=target,1=initiator */
- TXQ_PRIO_HI = (1U << 27), /* priority: 0=normal, 1=high */
- TXQ_SRS_SHIFT = 20, /* SATA register set */
- TXQ_SRS_MASK = 0x7f,
- TXQ_PHY_SHIFT = 12, /* PHY bitmap */
- TXQ_PHY_MASK = 0xff,
- TXQ_SLOT_MASK = 0xfff, /* slot number */
-
- /* RX (completion) ring bits */
- RXQ_GOOD = (1U << 23), /* Response good */
- RXQ_SLOT_RESET = (1U << 21), /* Slot reset complete */
- RXQ_CMD_RX = (1U << 20), /* target cmd received */
- RXQ_ATTN = (1U << 19), /* attention */
- RXQ_RSP = (1U << 18), /* response frame xfer'd */
- RXQ_ERR = (1U << 17), /* err info rec xfer'd */
- RXQ_DONE = (1U << 16), /* cmd complete */
- RXQ_SLOT_MASK = 0xfff, /* slot number */
-
- /* mvs_cmd_hdr bits */
- MCH_PRD_LEN_SHIFT = 16, /* 16-bit PRD table len */
- MCH_SSP_FR_TYPE_SHIFT = 13, /* SSP frame type */
-
- /* SSP initiator only */
- MCH_SSP_FR_CMD = 0x0, /* COMMAND frame */
-
- /* SSP initiator or target */
- MCH_SSP_FR_TASK = 0x1, /* TASK frame */
-
- /* SSP target only */
- MCH_SSP_FR_XFER_RDY = 0x4, /* XFER_RDY frame */
- MCH_SSP_FR_RESP = 0x5, /* RESPONSE frame */
- MCH_SSP_FR_READ = 0x6, /* Read DATA frame(s) */
- MCH_SSP_FR_READ_RESP = 0x7, /* ditto, plus RESPONSE */
-
- MCH_PASSTHRU = (1U << 12), /* pass-through (SSP) */
- MCH_FBURST = (1U << 11), /* first burst (SSP) */
- MCH_CHK_LEN = (1U << 10), /* chk xfer len (SSP) */
- MCH_RETRY = (1U << 9), /* tport layer retry (SSP) */
- MCH_PROTECTION = (1U << 8), /* protection info rec (SSP) */
- MCH_RESET = (1U << 7), /* Reset (STP/SATA) */
- MCH_FPDMA = (1U << 6), /* First party DMA (STP/SATA) */
- MCH_ATAPI = (1U << 5), /* ATAPI (STP/SATA) */
- MCH_BIST = (1U << 4), /* BIST activate (STP/SATA) */
- MCH_PMP_MASK = 0xf, /* PMP from cmd FIS (STP/SATA)*/
-
- CCTL_RST = (1U << 5), /* port logic reset */
-
- /* 0(LSB first), 1(MSB first) */
- CCTL_ENDIAN_DATA = (1U << 3), /* PRD data */
- CCTL_ENDIAN_RSP = (1U << 2), /* response frame */
- CCTL_ENDIAN_OPEN = (1U << 1), /* open address frame */
- CCTL_ENDIAN_CMD = (1U << 0), /* command table */
-
- /* MVS_Px_SER_CTLSTAT (per-phy control) */
- PHY_SSP_RST = (1U << 3), /* reset SSP link layer */
- PHY_BCAST_CHG = (1U << 2), /* broadcast(change) notif */
- PHY_RST_HARD = (1U << 1), /* hard reset + phy reset */
- PHY_RST = (1U << 0), /* phy reset */
- PHY_MIN_SPP_PHYS_LINK_RATE_MASK = (0xF << 8),
- PHY_MAX_SPP_PHYS_LINK_RATE_MASK = (0xF << 12),
- PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET = (16),
- PHY_NEG_SPP_PHYS_LINK_RATE_MASK =
- (0xF << PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET),
- PHY_READY_MASK = (1U << 20),
-
- /* MVS_Px_INT_STAT, MVS_Px_INT_MASK (per-phy events) */
- PHYEV_DEC_ERR = (1U << 24), /* Phy Decoding Error */
- PHYEV_UNASSOC_FIS = (1U << 19), /* unassociated FIS rx'd */
- PHYEV_AN = (1U << 18), /* SATA async notification */
- PHYEV_BIST_ACT = (1U << 17), /* BIST activate FIS */
- PHYEV_SIG_FIS = (1U << 16), /* signature FIS */
- PHYEV_POOF = (1U << 12), /* phy ready from 1 -> 0 */
- PHYEV_IU_BIG = (1U << 11), /* IU too long err */
- PHYEV_IU_SMALL = (1U << 10), /* IU too short err */
- PHYEV_UNK_TAG = (1U << 9), /* unknown tag */
- PHYEV_BROAD_CH = (1U << 8), /* broadcast(CHANGE) */
- PHYEV_COMWAKE = (1U << 7), /* COMWAKE rx'd */
- PHYEV_PORT_SEL = (1U << 6), /* port selector present */
- PHYEV_HARD_RST = (1U << 5), /* hard reset rx'd */
- PHYEV_ID_TMOUT = (1U << 4), /* identify timeout */
- PHYEV_ID_FAIL = (1U << 3), /* identify failed */
- PHYEV_ID_DONE = (1U << 2), /* identify done */
- PHYEV_HARD_RST_DONE = (1U << 1), /* hard reset done */
- PHYEV_RDY_CH = (1U << 0), /* phy ready changed state */
-
- /* MVS_PCS */
- PCS_EN_SATA_REG_SHIFT = (16), /* Enable SATA Register Set */
- PCS_EN_PORT_XMT_SHIFT = (12), /* Enable Port Transmit */
- PCS_EN_PORT_XMT_SHIFT2 = (8), /* For 6480 */
- PCS_SATA_RETRY = (1U << 8), /* retry ctl FIS on R_ERR */
- PCS_RSP_RX_EN = (1U << 7), /* raw response rx */
- PCS_SELF_CLEAR = (1U << 5), /* self-clearing int mode */
- PCS_FIS_RX_EN = (1U << 4), /* FIS rx enable */
- PCS_CMD_STOP_ERR = (1U << 3), /* cmd stop-on-err enable */
- PCS_CMD_RST = (1U << 1), /* reset cmd issue */
- PCS_CMD_EN = (1U << 0), /* enable cmd issue */
-
- /* Port n Attached Device Info */
- PORT_DEV_SSP_TRGT = (1U << 19),
- PORT_DEV_SMP_TRGT = (1U << 18),
- PORT_DEV_STP_TRGT = (1U << 17),
- PORT_DEV_SSP_INIT = (1U << 11),
- PORT_DEV_SMP_INIT = (1U << 10),
- PORT_DEV_STP_INIT = (1U << 9),
- PORT_PHY_ID_MASK = (0xFFU << 24),
- PORT_DEV_TRGT_MASK = (0x7U << 17),
- PORT_DEV_INIT_MASK = (0x7U << 9),
- PORT_DEV_TYPE_MASK = (0x7U << 0),
-
- /* Port n PHY Status */
- PHY_RDY = (1U << 2),
- PHY_DW_SYNC = (1U << 1),
- PHY_OOB_DTCTD = (1U << 0),
-
- /* VSR */
- /* PHYMODE 6 (CDB) */
- PHY_MODE6_LATECLK = (1U << 29), /* Lock Clock */
- PHY_MODE6_DTL_SPEED = (1U << 27), /* Digital Loop Speed */
- PHY_MODE6_FC_ORDER = (1U << 26), /* Fibre Channel Mode Order*/
- PHY_MODE6_MUCNT_EN = (1U << 24), /* u Count Enable */
- PHY_MODE6_SEL_MUCNT_LEN = (1U << 22), /* Training Length Select */
- PHY_MODE6_SELMUPI = (1U << 20), /* Phase Multi Select (init) */
- PHY_MODE6_SELMUPF = (1U << 18), /* Phase Multi Select (final) */
- PHY_MODE6_SELMUFF = (1U << 16), /* Freq Loop Multi Sel(final) */
- PHY_MODE6_SELMUFI = (1U << 14), /* Freq Loop Multi Sel(init) */
- PHY_MODE6_FREEZE_LOOP = (1U << 12), /* Freeze Rx CDR Loop */
- PHY_MODE6_INT_RXFOFFS = (1U << 3), /* Rx CDR Freq Loop Enable */
- PHY_MODE6_FRC_RXFOFFS = (1U << 2), /* Initial Rx CDR Offset */
- PHY_MODE6_STAU_0D8 = (1U << 1), /* Rx CDR Freq Loop Saturate */
- PHY_MODE6_RXSAT_DIS = (1U << 0), /* Saturate Ctl */
-};
-
-enum mvs_info_flags {
- MVF_MSI = (1U << 0), /* MSI is enabled */
- MVF_PHY_PWR_FIX = (1U << 1), /* bug workaround */
-};
-
-enum sas_cmd_port_registers {
- CMD_CMRST_OOB_DET = 0x100, /* COMRESET OOB detect register */
- CMD_CMWK_OOB_DET = 0x104, /* COMWAKE OOB detect register */
- CMD_CMSAS_OOB_DET = 0x108, /* COMSAS OOB detect register */
- CMD_BRST_OOB_DET = 0x10c, /* burst OOB detect register */
- CMD_OOB_SPACE = 0x110, /* OOB space control register */
- CMD_OOB_BURST = 0x114, /* OOB burst control register */
- CMD_PHY_TIMER = 0x118, /* PHY timer control register */
- CMD_PHY_CONFIG0 = 0x11c, /* PHY config register 0 */
- CMD_PHY_CONFIG1 = 0x120, /* PHY config register 1 */
- CMD_SAS_CTL0 = 0x124, /* SAS control register 0 */
- CMD_SAS_CTL1 = 0x128, /* SAS control register 1 */
- CMD_SAS_CTL2 = 0x12c, /* SAS control register 2 */
- CMD_SAS_CTL3 = 0x130, /* SAS control register 3 */
- CMD_ID_TEST = 0x134, /* ID test register */
- CMD_PL_TIMER = 0x138, /* PL timer register */
- CMD_WD_TIMER = 0x13c, /* WD timer register */
- CMD_PORT_SEL_COUNT = 0x140, /* port selector count register */
- CMD_APP_MEM_CTL = 0x144, /* Application Memory Control */
- CMD_XOR_MEM_CTL = 0x148, /* XOR Block Memory Control */
- CMD_DMA_MEM_CTL = 0x14c, /* DMA Block Memory Control */
- CMD_PORT_MEM_CTL0 = 0x150, /* Port Memory Control 0 */
- CMD_PORT_MEM_CTL1 = 0x154, /* Port Memory Control 1 */
- CMD_SATA_PORT_MEM_CTL0 = 0x158, /* SATA Port Memory Control 0 */
- CMD_SATA_PORT_MEM_CTL1 = 0x15c, /* SATA Port Memory Control 1 */
- CMD_XOR_MEM_BIST_CTL = 0x160, /* XOR Memory BIST Control */
- CMD_XOR_MEM_BIST_STAT = 0x164, /* XOR Memroy BIST Status */
- CMD_DMA_MEM_BIST_CTL = 0x168, /* DMA Memory BIST Control */
- CMD_DMA_MEM_BIST_STAT = 0x16c, /* DMA Memory BIST Status */
- CMD_PORT_MEM_BIST_CTL = 0x170, /* Port Memory BIST Control */
- CMD_PORT_MEM_BIST_STAT0 = 0x174, /* Port Memory BIST Status 0 */
- CMD_PORT_MEM_BIST_STAT1 = 0x178, /* Port Memory BIST Status 1 */
- CMD_STP_MEM_BIST_CTL = 0x17c, /* STP Memory BIST Control */
- CMD_STP_MEM_BIST_STAT0 = 0x180, /* STP Memory BIST Status 0 */
- CMD_STP_MEM_BIST_STAT1 = 0x184, /* STP Memory BIST Status 1 */
- CMD_RESET_COUNT = 0x188, /* Reset Count */
- CMD_MONTR_DATA_SEL = 0x18C, /* Monitor Data/Select */
- CMD_PLL_PHY_CONFIG = 0x190, /* PLL/PHY Configuration */
- CMD_PHY_CTL = 0x194, /* PHY Control and Status */
- CMD_PHY_TEST_COUNT0 = 0x198, /* Phy Test Count 0 */
- CMD_PHY_TEST_COUNT1 = 0x19C, /* Phy Test Count 1 */
- CMD_PHY_TEST_COUNT2 = 0x1A0, /* Phy Test Count 2 */
- CMD_APP_ERR_CONFIG = 0x1A4, /* Application Error Configuration */
- CMD_PND_FIFO_CTL0 = 0x1A8, /* Pending FIFO Control 0 */
- CMD_HOST_CTL = 0x1AC, /* Host Control Status */
- CMD_HOST_WR_DATA = 0x1B0, /* Host Write Data */
- CMD_HOST_RD_DATA = 0x1B4, /* Host Read Data */
- CMD_PHY_MODE_21 = 0x1B8, /* Phy Mode 21 */
- CMD_SL_MODE0 = 0x1BC, /* SL Mode 0 */
- CMD_SL_MODE1 = 0x1C0, /* SL Mode 1 */
- CMD_PND_FIFO_CTL1 = 0x1C4, /* Pending FIFO Control 1 */
-};
-
-/* SAS/SATA configuration port registers, aka phy registers */
-enum sas_sata_config_port_regs {
- PHYR_IDENTIFY = 0x00, /* info for IDENTIFY frame */
- PHYR_ADDR_LO = 0x04, /* my SAS address (low) */
- PHYR_ADDR_HI = 0x08, /* my SAS address (high) */
- PHYR_ATT_DEV_INFO = 0x0C, /* attached device info */
- PHYR_ATT_ADDR_LO = 0x10, /* attached dev SAS addr (low) */
- PHYR_ATT_ADDR_HI = 0x14, /* attached dev SAS addr (high) */
- PHYR_SATA_CTL = 0x18, /* SATA control */
- PHYR_PHY_STAT = 0x1C, /* PHY status */
- PHYR_SATA_SIG0 = 0x20, /*port SATA signature FIS(Byte 0-3) */
- PHYR_SATA_SIG1 = 0x24, /*port SATA signature FIS(Byte 4-7) */
- PHYR_SATA_SIG2 = 0x28, /*port SATA signature FIS(Byte 8-11) */
- PHYR_SATA_SIG3 = 0x2c, /*port SATA signature FIS(Byte 12-15) */
- PHYR_R_ERR_COUNT = 0x30, /* port R_ERR count register */
- PHYR_CRC_ERR_COUNT = 0x34, /* port CRC error count register */
- PHYR_WIDE_PORT = 0x38, /* wide port participating */
- PHYR_CURRENT0 = 0x80, /* current connection info 0 */
- PHYR_CURRENT1 = 0x84, /* current connection info 1 */
- PHYR_CURRENT2 = 0x88, /* current connection info 2 */
-};
-
-/* SAS/SATA Vendor Specific Port Registers */
-enum sas_sata_vsp_regs {
- VSR_PHY_STAT = 0x00, /* Phy Status */
- VSR_PHY_MODE1 = 0x01, /* phy tx */
- VSR_PHY_MODE2 = 0x02, /* tx scc */
- VSR_PHY_MODE3 = 0x03, /* pll */
- VSR_PHY_MODE4 = 0x04, /* VCO */
- VSR_PHY_MODE5 = 0x05, /* Rx */
- VSR_PHY_MODE6 = 0x06, /* CDR */
- VSR_PHY_MODE7 = 0x07, /* Impedance */
- VSR_PHY_MODE8 = 0x08, /* Voltage */
- VSR_PHY_MODE9 = 0x09, /* Test */
- VSR_PHY_MODE10 = 0x0A, /* Power */
- VSR_PHY_MODE11 = 0x0B, /* Phy Mode */
- VSR_PHY_VS0 = 0x0C, /* Vednor Specific 0 */
- VSR_PHY_VS1 = 0x0D, /* Vednor Specific 1 */
-};
-
-enum pci_cfg_registers {
- PCR_PHY_CTL = 0x40,
- PCR_PHY_CTL2 = 0x90,
- PCR_DEV_CTRL = 0xE8,
-};
-
-enum pci_cfg_register_bits {
- PCTL_PWR_ON = (0xFU << 24),
- PCTL_OFF = (0xFU << 12),
- PRD_REQ_SIZE = (0x4000),
- PRD_REQ_MASK = (0x00007000),
-};
-
-enum nvram_layout_offsets {
- NVR_SIG = 0x00, /* 0xAA, 0x55 */
- NVR_SAS_ADDR = 0x02, /* 8-byte SAS address */
-};
-
-enum chip_flavors {
- chip_6320,
- chip_6440,
- chip_6480,
-};
-
-enum port_type {
- PORT_TYPE_SAS = (1L << 1),
- PORT_TYPE_SATA = (1L << 0),
-};
-
-/* Command Table Format */
-enum ct_format {
- /* SSP */
- SSP_F_H = 0x00,
- SSP_F_IU = 0x18,
- SSP_F_MAX = 0x4D,
- /* STP */
- STP_CMD_FIS = 0x00,
- STP_ATAPI_CMD = 0x40,
- STP_F_MAX = 0x10,
- /* SMP */
- SMP_F_T = 0x00,
- SMP_F_DEP = 0x01,
- SMP_F_MAX = 0x101,
-};
-
-enum status_buffer {
- SB_EIR_OFF = 0x00, /* Error Information Record */
- SB_RFB_OFF = 0x08, /* Response Frame Buffer */
- SB_RFB_MAX = 0x400, /* RFB size*/
-};
-
-enum error_info_rec {
- CMD_ISS_STPD = (1U << 31), /* Cmd Issue Stopped */
- CMD_PI_ERR = (1U << 30), /* Protection info error. see flags2 */
- RSP_OVER = (1U << 29), /* rsp buffer overflow */
- RETRY_LIM = (1U << 28), /* FIS/frame retry limit exceeded */
- UNK_FIS = (1U << 27), /* unknown FIS */
- DMA_TERM = (1U << 26), /* DMA terminate primitive rx'd */
- SYNC_ERR = (1U << 25), /* SYNC rx'd during frame xmit */
- TFILE_ERR = (1U << 24), /* SATA taskfile Error bit set */
- R_ERR = (1U << 23), /* SATA returned R_ERR prim */
- RD_OFS = (1U << 20), /* Read DATA frame invalid offset */
- XFER_RDY_OFS = (1U << 19), /* XFER_RDY offset error */
- UNEXP_XFER_RDY = (1U << 18), /* unexpected XFER_RDY error */
- DATA_OVER_UNDER = (1U << 16), /* data overflow/underflow */
- INTERLOCK = (1U << 15), /* interlock error */
- NAK = (1U << 14), /* NAK rx'd */
- ACK_NAK_TO = (1U << 13), /* ACK/NAK timeout */
- CXN_CLOSED = (1U << 12), /* cxn closed w/out ack/nak */
- OPEN_TO = (1U << 11), /* I_T nexus lost, open cxn timeout */
- PATH_BLOCKED = (1U << 10), /* I_T nexus lost, pathway blocked */
- NO_DEST = (1U << 9), /* I_T nexus lost, no destination */
- STP_RES_BSY = (1U << 8), /* STP resources busy */
- BREAK = (1U << 7), /* break received */
- BAD_DEST = (1U << 6), /* bad destination */
- BAD_PROTO = (1U << 5), /* protocol not supported */
- BAD_RATE = (1U << 4), /* cxn rate not supported */
- WRONG_DEST = (1U << 3), /* wrong destination error */
- CREDIT_TO = (1U << 2), /* credit timeout */
- WDOG_TO = (1U << 1), /* watchdog timeout */
- BUF_PAR = (1U << 0), /* buffer parity error */
-};
-
-enum error_info_rec_2 {
- SLOT_BSY_ERR = (1U << 31), /* Slot Busy Error */
- GRD_CHK_ERR = (1U << 14), /* Guard Check Error */
- APP_CHK_ERR = (1U << 13), /* Application Check error */
- REF_CHK_ERR = (1U << 12), /* Reference Check Error */
- USR_BLK_NM = (1U << 0), /* User Block Number */
-};
-
-struct mvs_chip_info {
- u32 n_phy;
- u32 srs_sz;
- u32 slot_width;
-};
-
-struct mvs_err_info {
- __le32 flags;
- __le32 flags2;
-};
-
-struct mvs_prd {
- __le64 addr; /* 64-bit buffer address */
- __le32 reserved;
- __le32 len; /* 16-bit length */
-};
-
-struct mvs_cmd_hdr {
- __le32 flags; /* PRD tbl len; SAS, SATA ctl */
- __le32 lens; /* cmd, max resp frame len */
- __le32 tags; /* targ port xfer tag; tag */
- __le32 data_len; /* data xfer len */
- __le64 cmd_tbl; /* command table address */
- __le64 open_frame; /* open addr frame address */
- __le64 status_buf; /* status buffer address */
- __le64 prd_tbl; /* PRD tbl address */
- __le32 reserved[4];
-};
-
-struct mvs_port {
- struct asd_sas_port sas_port;
- u8 port_attached;
- u8 taskfileset;
- u8 wide_port_phymap;
- struct list_head list;
-};
-
-struct mvs_phy {
- struct mvs_port *port;
- struct asd_sas_phy sas_phy;
- struct sas_identify identify;
- struct scsi_device *sdev;
- u64 dev_sas_addr;
- u64 att_dev_sas_addr;
- u32 att_dev_info;
- u32 dev_info;
- u32 phy_type;
- u32 phy_status;
- u32 irq_status;
- u32 frame_rcvd_size;
- u8 frame_rcvd[32];
- u8 phy_attached;
- enum sas_linkrate minimum_linkrate;
- enum sas_linkrate maximum_linkrate;
-};
-
-struct mvs_slot_info {
- struct list_head list;
- struct sas_task *task;
- u32 n_elem;
- u32 tx;
-
- /* DMA buffer for storing cmd tbl, open addr frame, status buffer,
- * and PRD table
- */
- void *buf;
- dma_addr_t buf_dma;
-#if _MV_DUMP
- u32 cmd_size;
-#endif
-
- void *response;
- struct mvs_port *port;
-};
-
-struct mvs_info {
- unsigned long flags;
-
- spinlock_t lock; /* host-wide lock */
- struct pci_dev *pdev; /* our device */
- void __iomem *regs; /* enhanced mode registers */
- void __iomem *peri_regs; /* peripheral registers */
-
- u8 sas_addr[SAS_ADDR_SIZE];
- struct sas_ha_struct sas; /* SCSI/SAS glue */
- struct Scsi_Host *shost;
-
- __le32 *tx; /* TX (delivery) DMA ring */
- dma_addr_t tx_dma;
- u32 tx_prod; /* cached next-producer idx */
-
- __le32 *rx; /* RX (completion) DMA ring */
- dma_addr_t rx_dma;
- u32 rx_cons; /* RX consumer idx */
-
- __le32 *rx_fis; /* RX'd FIS area */
- dma_addr_t rx_fis_dma;
-
- struct mvs_cmd_hdr *slot; /* DMA command header slots */
- dma_addr_t slot_dma;
-
- const struct mvs_chip_info *chip;
-
- u8 tags[MVS_SLOTS];
- struct mvs_slot_info slot_info[MVS_SLOTS];
- /* further per-slot information */
- struct mvs_phy phy[MVS_MAX_PHYS];
- struct mvs_port port[MVS_MAX_PHYS];
-#ifdef MVS_USE_TASKLET
- struct tasklet_struct tasklet;
-#endif
-};
-
-static int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
- void *funcdata);
-static u32 mvs_read_phy_ctl(struct mvs_info *mvi, u32 port);
-static void mvs_write_phy_ctl(struct mvs_info *mvi, u32 port, u32 val);
-static u32 mvs_read_port_irq_stat(struct mvs_info *mvi, u32 port);
-static void mvs_write_port_irq_stat(struct mvs_info *mvi, u32 port, u32 val);
-static void mvs_write_port_irq_mask(struct mvs_info *mvi, u32 port, u32 val);
-static u32 mvs_read_port_irq_mask(struct mvs_info *mvi, u32 port);
-
-static u32 mvs_is_phy_ready(struct mvs_info *mvi, int i);
-static void mvs_detect_porttype(struct mvs_info *mvi, int i);
-static void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st);
-static void mvs_release_task(struct mvs_info *mvi, int phy_no);
-
-static int mvs_scan_finished(struct Scsi_Host *, unsigned long);
-static void mvs_scan_start(struct Scsi_Host *);
-static int mvs_slave_configure(struct scsi_device *sdev);
-
-static struct scsi_transport_template *mvs_stt;
-
-static const struct mvs_chip_info mvs_chips[] = {
- [chip_6320] = { 2, 16, 9 },
- [chip_6440] = { 4, 16, 9 },
- [chip_6480] = { 8, 32, 10 },
-};
-
-static struct scsi_host_template mvs_sht = {
- .module = THIS_MODULE,
- .name = DRV_NAME,
- .queuecommand = sas_queuecommand,
- .target_alloc = sas_target_alloc,
- .slave_configure = mvs_slave_configure,
- .slave_destroy = sas_slave_destroy,
- .scan_finished = mvs_scan_finished,
- .scan_start = mvs_scan_start,
- .change_queue_depth = sas_change_queue_depth,
- .change_queue_type = sas_change_queue_type,
- .bios_param = sas_bios_param,
- .can_queue = 1,
- .cmd_per_lun = 1,
- .this_id = -1,
- .sg_tablesize = SG_ALL,
- .max_sectors = SCSI_DEFAULT_MAX_SECTORS,
- .use_clustering = ENABLE_CLUSTERING,
- .eh_device_reset_handler = sas_eh_device_reset_handler,
- .eh_bus_reset_handler = sas_eh_bus_reset_handler,
- .slave_alloc = sas_slave_alloc,
- .target_destroy = sas_target_destroy,
- .ioctl = sas_ioctl,
-};
-
-static void mvs_hexdump(u32 size, u8 *data, u32 baseaddr)
-{
- u32 i;
- u32 run;
- u32 offset;
-
- offset = 0;
- while (size) {
- printk("%08X : ", baseaddr + offset);
- if (size >= 16)
- run = 16;
- else
- run = size;
- size -= run;
- for (i = 0; i < 16; i++) {
- if (i < run)
- printk("%02X ", (u32)data[i]);
- else
- printk(" ");
- }
- printk(": ");
- for (i = 0; i < run; i++)
- printk("%c", isalnum(data[i]) ? data[i] : '.');
- printk("\n");
- data = &data[16];
- offset += run;
- }
- printk("\n");
-}
-
-#if _MV_DUMP
-static void mvs_hba_sb_dump(struct mvs_info *mvi, u32 tag,
- enum sas_protocol proto)
-{
- u32 offset;
- struct pci_dev *pdev = mvi->pdev;
- struct mvs_slot_info *slot = &mvi->slot_info[tag];
-
- offset = slot->cmd_size + MVS_OAF_SZ +
- sizeof(struct mvs_prd) * slot->n_elem;
- dev_printk(KERN_DEBUG, &pdev->dev, "+---->Status buffer[%d] :\n",
- tag);
- mvs_hexdump(32, (u8 *) slot->response,
- (u32) slot->buf_dma + offset);
-}
-#endif
-
-static void mvs_hba_memory_dump(struct mvs_info *mvi, u32 tag,
- enum sas_protocol proto)
-{
-#if _MV_DUMP
- u32 sz, w_ptr;
- u64 addr;
- void __iomem *regs = mvi->regs;
- struct pci_dev *pdev = mvi->pdev;
- struct mvs_slot_info *slot = &mvi->slot_info[tag];
-
- /*Delivery Queue */
- sz = mr32(TX_CFG) & TX_RING_SZ_MASK;
- w_ptr = slot->tx;
- addr = mr32(TX_HI) << 16 << 16 | mr32(TX_LO);
- dev_printk(KERN_DEBUG, &pdev->dev,
- "Delivery Queue Size=%04d , WRT_PTR=%04X\n", sz, w_ptr);
- dev_printk(KERN_DEBUG, &pdev->dev,
- "Delivery Queue Base Address=0x%llX (PA)"
- "(tx_dma=0x%llX), Entry=%04d\n",
- addr, mvi->tx_dma, w_ptr);
- mvs_hexdump(sizeof(u32), (u8 *)(&mvi->tx[mvi->tx_prod]),
- (u32) mvi->tx_dma + sizeof(u32) * w_ptr);
- /*Command List */
- addr = mvi->slot_dma;
- dev_printk(KERN_DEBUG, &pdev->dev,
- "Command List Base Address=0x%llX (PA)"
- "(slot_dma=0x%llX), Header=%03d\n",
- addr, slot->buf_dma, tag);
- dev_printk(KERN_DEBUG, &pdev->dev, "Command Header[%03d]:\n", tag);
- /*mvs_cmd_hdr */
- mvs_hexdump(sizeof(struct mvs_cmd_hdr), (u8 *)(&mvi->slot[tag]),
- (u32) mvi->slot_dma + tag * sizeof(struct mvs_cmd_hdr));
- /*1.command table area */
- dev_printk(KERN_DEBUG, &pdev->dev, "+---->Command Table :\n");
- mvs_hexdump(slot->cmd_size, (u8 *) slot->buf, (u32) slot->buf_dma);
- /*2.open address frame area */
- dev_printk(KERN_DEBUG, &pdev->dev, "+---->Open Address Frame :\n");
- mvs_hexdump(MVS_OAF_SZ, (u8 *) slot->buf + slot->cmd_size,
- (u32) slot->buf_dma + slot->cmd_size);
- /*3.status buffer */
- mvs_hba_sb_dump(mvi, tag, proto);
- /*4.PRD table */
- dev_printk(KERN_DEBUG, &pdev->dev, "+---->PRD table :\n");
- mvs_hexdump(sizeof(struct mvs_prd) * slot->n_elem,
- (u8 *) slot->buf + slot->cmd_size + MVS_OAF_SZ,
- (u32) slot->buf_dma + slot->cmd_size + MVS_OAF_SZ);
-#endif
-}
-
-static void mvs_hba_cq_dump(struct mvs_info *mvi)
-{
-#if (_MV_DUMP > 2)
- u64 addr;
- void __iomem *regs = mvi->regs;
- struct pci_dev *pdev = mvi->pdev;
- u32 entry = mvi->rx_cons + 1;
- u32 rx_desc = le32_to_cpu(mvi->rx[entry]);
-
- /*Completion Queue */
- addr = mr32(RX_HI) << 16 << 16 | mr32(RX_LO);
- dev_printk(KERN_DEBUG, &pdev->dev, "Completion Task = 0x%p\n",
- mvi->slot_info[rx_desc & RXQ_SLOT_MASK].task);
- dev_printk(KERN_DEBUG, &pdev->dev,
- "Completion List Base Address=0x%llX (PA), "
- "CQ_Entry=%04d, CQ_WP=0x%08X\n",
- addr, entry - 1, mvi->rx[0]);
- mvs_hexdump(sizeof(u32), (u8 *)(&rx_desc),
- mvi->rx_dma + sizeof(u32) * entry);
-#endif
-}
-
-static void mvs_hba_interrupt_enable(struct mvs_info *mvi)
-{
- void __iomem *regs = mvi->regs;
- u32 tmp;
-
- tmp = mr32(GBL_CTL);
-
- mw32(GBL_CTL, tmp | INT_EN);
-}
-
-static void mvs_hba_interrupt_disable(struct mvs_info *mvi)
-{
- void __iomem *regs = mvi->regs;
- u32 tmp;
-
- tmp = mr32(GBL_CTL);
-
- mw32(GBL_CTL, tmp & ~INT_EN);
-}
-
-static int mvs_int_rx(struct mvs_info *mvi, bool self_clear);
-
-/* move to PCI layer or libata core? */
-static int pci_go_64(struct pci_dev *pdev)
-{
- int rc;
-
- if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
- rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
- if (rc) {
- rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
- if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "64-bit DMA enable failed\n");
- return rc;
- }
- }
- } else {
- rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
- if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "32-bit DMA enable failed\n");
- return rc;
- }
- rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
- if (rc) {
- dev_printk(KERN_ERR, &pdev->dev,
- "32-bit consistent DMA enable failed\n");
- return rc;
- }
- }
-
- return rc;
-}
-
-static int mvs_find_tag(struct mvs_info *mvi, struct sas_task *task, u32 *tag)
-{
- if (task->lldd_task) {
- struct mvs_slot_info *slot;
- slot = (struct mvs_slot_info *) task->lldd_task;
- *tag = slot - mvi->slot_info;
- return 1;
- }
- return 0;
-}
-
-static void mvs_tag_clear(struct mvs_info *mvi, u32 tag)
-{
- void *bitmap = (void *) &mvi->tags;
- clear_bit(tag, bitmap);
-}
-
-static void mvs_tag_free(struct mvs_info *mvi, u32 tag)
-{
- mvs_tag_clear(mvi, tag);
-}
-
-static void mvs_tag_set(struct mvs_info *mvi, unsigned int tag)
-{
- void *bitmap = (void *) &mvi->tags;
- set_bit(tag, bitmap);
-}
-
-static int mvs_tag_alloc(struct mvs_info *mvi, u32 *tag_out)
-{
- unsigned int index, tag;
- void *bitmap = (void *) &mvi->tags;
-
- index = find_first_zero_bit(bitmap, MVS_SLOTS);
- tag = index;
- if (tag >= MVS_SLOTS)
- return -SAS_QUEUE_FULL;
- mvs_tag_set(mvi, tag);
- *tag_out = tag;
- return 0;
-}
-
-static void mvs_tag_init(struct mvs_info *mvi)
-{
- int i;
- for (i = 0; i < MVS_SLOTS; ++i)
- mvs_tag_clear(mvi, i);
-}
-
-#ifndef MVS_DISABLE_NVRAM
-static int mvs_eep_read(void __iomem *regs, u32 addr, u32 *data)
-{
- int timeout = 1000;
-
- if (addr & ~SPI_ADDR_MASK)
- return -EINVAL;
-
- writel(addr, regs + SPI_CMD);
- writel(TWSI_RD, regs + SPI_CTL);
-
- while (timeout-- > 0) {
- if (readl(regs + SPI_CTL) & TWSI_RDY) {
- *data = readl(regs + SPI_DATA);
- return 0;
- }
-
- udelay(10);
- }
-
- return -EBUSY;
-}
-
-static int mvs_eep_read_buf(void __iomem *regs, u32 addr,
- void *buf, u32 buflen)
-{
- u32 addr_end, tmp_addr, i, j;
- u32 tmp = 0;
- int rc;
- u8 *tmp8, *buf8 = buf;
-
- addr_end = addr + buflen;
- tmp_addr = ALIGN(addr, 4);
- if (addr > 0xff)
- return -EINVAL;
-
- j = addr & 0x3;
- if (j) {
- rc = mvs_eep_read(regs, tmp_addr, &tmp);
- if (rc)
- return rc;
-
- tmp8 = (u8 *)&tmp;
- for (i = j; i < 4; i++)
- *buf8++ = tmp8[i];
-
- tmp_addr += 4;
- }
-
- for (j = ALIGN(addr_end, 4); tmp_addr < j; tmp_addr += 4) {
- rc = mvs_eep_read(regs, tmp_addr, &tmp);
- if (rc)
- return rc;
-
- memcpy(buf8, &tmp, 4);
- buf8 += 4;
- }
-
- if (tmp_addr < addr_end) {
- rc = mvs_eep_read(regs, tmp_addr, &tmp);
- if (rc)
- return rc;
-
- tmp8 = (u8 *)&tmp;
- j = addr_end - tmp_addr;
- for (i = 0; i < j; i++)
- *buf8++ = tmp8[i];
-
- tmp_addr += 4;
- }
-
- return 0;
-}
-#endif
-
-static int mvs_nvram_read(struct mvs_info *mvi, u32 addr,
- void *buf, u32 buflen)
-{
-#ifndef MVS_DISABLE_NVRAM
- void __iomem *regs = mvi->regs;
- int rc, i;
- u32 sum;
- u8 hdr[2], *tmp;
- const char *msg;
-
- rc = mvs_eep_read_buf(regs, addr, &hdr, 2);
- if (rc) {
- msg = "nvram hdr read failed";
- goto err_out;
- }
- rc = mvs_eep_read_buf(regs, addr + 2, buf, buflen);
- if (rc) {
- msg = "nvram read failed";
- goto err_out;
- }
-
- if (hdr[0] != 0x5A) {
- /* entry id */
- msg = "invalid nvram entry id";
- rc = -ENOENT;
- goto err_out;
- }
-
- tmp = buf;
- sum = ((u32)hdr[0]) + ((u32)hdr[1]);
- for (i = 0; i < buflen; i++)
- sum += ((u32)tmp[i]);
-
- if (sum) {
- msg = "nvram checksum failure";
- rc = -EILSEQ;
- goto err_out;
- }
-
- return 0;
-
-err_out:
- dev_printk(KERN_ERR, &mvi->pdev->dev, "%s", msg);
- return rc;
-#else
- /* FIXME , For SAS target mode */
- memcpy(buf, "\x50\x05\x04\x30\x11\xab\x00\x00", 8);
- return 0;
-#endif
-}
-
-static void mvs_bytes_dmaed(struct mvs_info *mvi, int i)
-{
- struct mvs_phy *phy = &mvi->phy[i];
- struct asd_sas_phy *sas_phy = mvi->sas.sas_phy[i];
-
- if (!phy->phy_attached)
- return;
-
- if (sas_phy->phy) {
- struct sas_phy *sphy = sas_phy->phy;
-
- sphy->negotiated_linkrate = sas_phy->linkrate;
- sphy->minimum_linkrate = phy->minimum_linkrate;
- sphy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
- sphy->maximum_linkrate = phy->maximum_linkrate;
- sphy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
- }
-
- if (phy->phy_type & PORT_TYPE_SAS) {
- struct sas_identify_frame *id;
-
- id = (struct sas_identify_frame *)phy->frame_rcvd;
- id->dev_type = phy->identify.device_type;
- id->initiator_bits = SAS_PROTOCOL_ALL;
- id->target_bits = phy->identify.target_port_protocols;
- } else if (phy->phy_type & PORT_TYPE_SATA) {
- /* TODO */
- }
- mvi->sas.sas_phy[i]->frame_rcvd_size = phy->frame_rcvd_size;
- mvi->sas.notify_port_event(mvi->sas.sas_phy[i],
- PORTE_BYTES_DMAED);
-}
-
-static int mvs_scan_finished(struct Scsi_Host *shost, unsigned long time)
-{
- /* give the phy enabling interrupt event time to come in (1s
- * is empirically about all it takes) */
- if (time < HZ)
- return 0;
- /* Wait for discovery to finish */
- scsi_flush_work(shost);
- return 1;
-}
-
-static void mvs_scan_start(struct Scsi_Host *shost)
-{
- int i;
- struct mvs_info *mvi = SHOST_TO_SAS_HA(shost)->lldd_ha;
-
- for (i = 0; i < mvi->chip->n_phy; ++i) {
- mvs_bytes_dmaed(mvi, i);
- }
-}
-
-static int mvs_slave_configure(struct scsi_device *sdev)
-{
- struct domain_device *dev = sdev_to_domain_dev(sdev);
- int ret = sas_slave_configure(sdev);
-
- if (ret)
- return ret;
-
- if (dev_is_sata(dev)) {
- /* struct ata_port *ap = dev->sata_dev.ap; */
- /* struct ata_device *adev = ap->link.device; */
-
- /* clamp at no NCQ for the time being */
- /* adev->flags |= ATA_DFLAG_NCQ_OFF; */
- scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, 1);
- }
- return 0;
-}
-
-static void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
-{
- struct pci_dev *pdev = mvi->pdev;
- struct sas_ha_struct *sas_ha = &mvi->sas;
- struct mvs_phy *phy = &mvi->phy[phy_no];
- struct asd_sas_phy *sas_phy = &phy->sas_phy;
-
- phy->irq_status = mvs_read_port_irq_stat(mvi, phy_no);
- /*
- * events is port event now ,
- * we need check the interrupt status which belongs to per port.
- */
- dev_printk(KERN_DEBUG, &pdev->dev,
- "Port %d Event = %X\n",
- phy_no, phy->irq_status);
-
- if (phy->irq_status & (PHYEV_POOF | PHYEV_DEC_ERR)) {
- mvs_release_task(mvi, phy_no);
- if (!mvs_is_phy_ready(mvi, phy_no)) {
- sas_phy_disconnected(sas_phy);
- sas_ha->notify_phy_event(sas_phy, PHYE_LOSS_OF_SIGNAL);
- dev_printk(KERN_INFO, &pdev->dev,
- "Port %d Unplug Notice\n", phy_no);
-
- } else
- mvs_phy_control(sas_phy, PHY_FUNC_LINK_RESET, NULL);
- }
- if (!(phy->irq_status & PHYEV_DEC_ERR)) {
- if (phy->irq_status & PHYEV_COMWAKE) {
- u32 tmp = mvs_read_port_irq_mask(mvi, phy_no);
- mvs_write_port_irq_mask(mvi, phy_no,
- tmp | PHYEV_SIG_FIS);
- }
- if (phy->irq_status & (PHYEV_SIG_FIS | PHYEV_ID_DONE)) {
- phy->phy_status = mvs_is_phy_ready(mvi, phy_no);
- if (phy->phy_status) {
- mvs_detect_porttype(mvi, phy_no);
-
- if (phy->phy_type & PORT_TYPE_SATA) {
- u32 tmp = mvs_read_port_irq_mask(mvi,
- phy_no);
- tmp &= ~PHYEV_SIG_FIS;
- mvs_write_port_irq_mask(mvi,
- phy_no, tmp);
- }
-
- mvs_update_phyinfo(mvi, phy_no, 0);
- sas_ha->notify_phy_event(sas_phy,
- PHYE_OOB_DONE);
- mvs_bytes_dmaed(mvi, phy_no);
- } else {
- dev_printk(KERN_DEBUG, &pdev->dev,
- "plugin interrupt but phy is gone\n");
- mvs_phy_control(sas_phy, PHY_FUNC_LINK_RESET,
- NULL);
- }
- } else if (phy->irq_status & PHYEV_BROAD_CH) {
- mvs_release_task(mvi, phy_no);
- sas_ha->notify_port_event(sas_phy,
- PORTE_BROADCAST_RCVD);
- }
- }
- mvs_write_port_irq_stat(mvi, phy_no, phy->irq_status);
-}
-
-static void mvs_int_sata(struct mvs_info *mvi)
-{
- u32 tmp;
- void __iomem *regs = mvi->regs;
- tmp = mr32(INT_STAT_SRS);
- mw32(INT_STAT_SRS, tmp & 0xFFFF);
-}
-
-static void mvs_slot_reset(struct mvs_info *mvi, struct sas_task *task,
- u32 slot_idx)
-{
- void __iomem *regs = mvi->regs;
- struct domain_device *dev = task->dev;
- struct asd_sas_port *sas_port = dev->port;
- struct mvs_port *port = mvi->slot_info[slot_idx].port;
- u32 reg_set, phy_mask;
-
- if (!sas_protocol_ata(task->task_proto)) {
- reg_set = 0;
- phy_mask = (port->wide_port_phymap) ? port->wide_port_phymap :
- sas_port->phy_mask;
- } else {
- reg_set = port->taskfileset;
- phy_mask = sas_port->phy_mask;
- }
- mvi->tx[mvi->tx_prod] = cpu_to_le32(TXQ_MODE_I | slot_idx |
- (TXQ_CMD_SLOT_RESET << TXQ_CMD_SHIFT) |
- (phy_mask << TXQ_PHY_SHIFT) |
- (reg_set << TXQ_SRS_SHIFT));
-
- mw32(TX_PROD_IDX, mvi->tx_prod);
- mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1);
-}
-
-static int mvs_sata_done(struct mvs_info *mvi, struct sas_task *task,
- u32 slot_idx, int err)
-{
- struct mvs_port *port = mvi->slot_info[slot_idx].port;
- struct task_status_struct *tstat = &task->task_status;
- struct ata_task_resp *resp = (struct ata_task_resp *)tstat->buf;
- int stat = SAM_GOOD;
-
- resp->frame_len = sizeof(struct dev_to_host_fis);
- memcpy(&resp->ending_fis[0],
- SATA_RECEIVED_D2H_FIS(port->taskfileset),
- sizeof(struct dev_to_host_fis));
- tstat->buf_valid_size = sizeof(*resp);
- if (unlikely(err))
- stat = SAS_PROTO_RESPONSE;
- return stat;
-}
-
-static void mvs_slot_free(struct mvs_info *mvi, u32 rx_desc)
-{
- u32 slot_idx = rx_desc & RXQ_SLOT_MASK;
- mvs_tag_clear(mvi, slot_idx);
-}
-
-static void mvs_slot_task_free(struct mvs_info *mvi, struct sas_task *task,
- struct mvs_slot_info *slot, u32 slot_idx)
-{
- if (!sas_protocol_ata(task->task_proto))
- if (slot->n_elem)
- pci_unmap_sg(mvi->pdev, task->scatter,
- slot->n_elem, task->data_dir);
-
- switch (task->task_proto) {
- case SAS_PROTOCOL_SMP:
- pci_unmap_sg(mvi->pdev, &task->smp_task.smp_resp, 1,
- PCI_DMA_FROMDEVICE);
- pci_unmap_sg(mvi->pdev, &task->smp_task.smp_req, 1,
- PCI_DMA_TODEVICE);
- break;
-
- case SAS_PROTOCOL_SATA:
- case SAS_PROTOCOL_STP:
- case SAS_PROTOCOL_SSP:
- default:
- /* do nothing */
- break;
- }
- list_del(&slot->list);
- task->lldd_task = NULL;
- slot->task = NULL;
- slot->port = NULL;
-}
-
-static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,
- u32 slot_idx)
-{
- struct mvs_slot_info *slot = &mvi->slot_info[slot_idx];
- u32 err_dw0 = le32_to_cpu(*(u32 *) (slot->response));
- u32 err_dw1 = le32_to_cpu(*(u32 *) (slot->response + 4));
- int stat = SAM_CHECK_COND;
-
- if (err_dw1 & SLOT_BSY_ERR) {
- stat = SAS_QUEUE_FULL;
- mvs_slot_reset(mvi, task, slot_idx);
- }
- switch (task->task_proto) {
- case SAS_PROTOCOL_SSP:
- break;
- case SAS_PROTOCOL_SMP:
- break;
- case SAS_PROTOCOL_SATA:
- case SAS_PROTOCOL_STP:
- case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
- if (err_dw0 & TFILE_ERR)
- stat = mvs_sata_done(mvi, task, slot_idx, 1);
- break;
- default:
- break;
- }
-
- mvs_hexdump(16, (u8 *) slot->response, 0);
- return stat;
-}
-
-static int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
-{
- u32 slot_idx = rx_desc & RXQ_SLOT_MASK;
- struct mvs_slot_info *slot = &mvi->slot_info[slot_idx];
- struct sas_task *task = slot->task;
- struct task_status_struct *tstat;
- struct mvs_port *port;
- bool aborted;
- void *to;
-
- if (unlikely(!task || !task->lldd_task))
- return -1;
-
- mvs_hba_cq_dump(mvi);
-
- spin_lock(&task->task_state_lock);
- aborted = task->task_state_flags & SAS_TASK_STATE_ABORTED;
- if (!aborted) {
- task->task_state_flags &=
- ~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR);
- task->task_state_flags |= SAS_TASK_STATE_DONE;
- }
- spin_unlock(&task->task_state_lock);
-
- if (aborted) {
- mvs_slot_task_free(mvi, task, slot, slot_idx);
- mvs_slot_free(mvi, rx_desc);
- return -1;
- }
-
- port = slot->port;
- tstat = &task->task_status;
- memset(tstat, 0, sizeof(*tstat));
- tstat->resp = SAS_TASK_COMPLETE;
-
- if (unlikely(!port->port_attached || flags)) {
- mvs_slot_err(mvi, task, slot_idx);
- if (!sas_protocol_ata(task->task_proto))
- tstat->stat = SAS_PHY_DOWN;
- goto out;
- }
-
- /* error info record present */
- if (unlikely((rx_desc & RXQ_ERR) && (*(u64 *) slot->response))) {
- tstat->stat = mvs_slot_err(mvi, task, slot_idx);
- goto out;
- }
-
- switch (task->task_proto) {
- case SAS_PROTOCOL_SSP:
- /* hw says status == 0, datapres == 0 */
- if (rx_desc & RXQ_GOOD) {
- tstat->stat = SAM_GOOD;
- tstat->resp = SAS_TASK_COMPLETE;
- }
- /* response frame present */
- else if (rx_desc & RXQ_RSP) {
- struct ssp_response_iu *iu =
- slot->response + sizeof(struct mvs_err_info);
- sas_ssp_task_response(&mvi->pdev->dev, task, iu);
- }
-
- /* should never happen? */
- else
- tstat->stat = SAM_CHECK_COND;
- break;
-
- case SAS_PROTOCOL_SMP: {
- struct scatterlist *sg_resp = &task->smp_task.smp_resp;
- tstat->stat = SAM_GOOD;
- to = kmap_atomic(sg_page(sg_resp), KM_IRQ0);
- memcpy(to + sg_resp->offset,
- slot->response + sizeof(struct mvs_err_info),
- sg_dma_len(sg_resp));
- kunmap_atomic(to, KM_IRQ0);
- break;
- }
-
- case SAS_PROTOCOL_SATA:
- case SAS_PROTOCOL_STP:
- case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: {
- tstat->stat = mvs_sata_done(mvi, task, slot_idx, 0);
- break;
- }
-
- default:
- tstat->stat = SAM_CHECK_COND;
- break;
- }
-
-out:
- mvs_slot_task_free(mvi, task, slot, slot_idx);
- if (unlikely(tstat->stat != SAS_QUEUE_FULL))
- mvs_slot_free(mvi, rx_desc);
-
- spin_unlock(&mvi->lock);
- task->task_done(task);
- spin_lock(&mvi->lock);
- return tstat->stat;
-}
-
-static void mvs_release_task(struct mvs_info *mvi, int phy_no)
-{
- struct list_head *pos, *n;
- struct mvs_slot_info *slot;
- struct mvs_phy *phy = &mvi->phy[phy_no];
- struct mvs_port *port = phy->port;
- u32 rx_desc;
-
- if (!port)
- return;
-
- list_for_each_safe(pos, n, &port->list) {
- slot = container_of(pos, struct mvs_slot_info, list);
- rx_desc = (u32) (slot - mvi->slot_info);
- mvs_slot_complete(mvi, rx_desc, 1);
- }
-}
-
-static void mvs_int_full(struct mvs_info *mvi)
-{
- void __iomem *regs = mvi->regs;
- u32 tmp, stat;
- int i;
-
- stat = mr32(INT_STAT);
-
- mvs_int_rx(mvi, false);
-
- for (i = 0; i < MVS_MAX_PORTS; i++) {
- tmp = (stat >> i) & (CINT_PORT | CINT_PORT_STOPPED);
- if (tmp)
- mvs_int_port(mvi, i, tmp);
- }
-
- if (stat & CINT_SRS)
- mvs_int_sata(mvi);
-
- mw32(INT_STAT, stat);
-}
-
-static int mvs_int_rx(struct mvs_info *mvi, bool self_clear)
-{
- void __iomem *regs = mvi->regs;
- u32 rx_prod_idx, rx_desc;
- bool attn = false;
- struct pci_dev *pdev = mvi->pdev;
-
- /* the first dword in the RX ring is special: it contains
- * a mirror of the hardware's RX producer index, so that
- * we don't have to stall the CPU reading that register.
- * The actual RX ring is offset by one dword, due to this.
- */
- rx_prod_idx = mvi->rx_cons;
- mvi->rx_cons = le32_to_cpu(mvi->rx[0]);
- if (mvi->rx_cons == 0xfff) /* h/w hasn't touched RX ring yet */
- return 0;
-
- /* The CMPL_Q may come late, read from register and try again
- * note: if coalescing is enabled,
- * it will need to read from register every time for sure
- */
- if (mvi->rx_cons == rx_prod_idx)
- mvi->rx_cons = mr32(RX_CONS_IDX) & RX_RING_SZ_MASK;
-
- if (mvi->rx_cons == rx_prod_idx)
- return 0;
-
- while (mvi->rx_cons != rx_prod_idx) {
-
- /* increment our internal RX consumer pointer */
- rx_prod_idx = (rx_prod_idx + 1) & (MVS_RX_RING_SZ - 1);
-
- rx_desc = le32_to_cpu(mvi->rx[rx_prod_idx + 1]);
-
- if (likely(rx_desc & RXQ_DONE))
- mvs_slot_complete(mvi, rx_desc, 0);
- if (rx_desc & RXQ_ATTN) {
- attn = true;
- dev_printk(KERN_DEBUG, &pdev->dev, "ATTN %X\n",
- rx_desc);
- } else if (rx_desc & RXQ_ERR) {
- if (!(rx_desc & RXQ_DONE))
- mvs_slot_complete(mvi, rx_desc, 0);
- dev_printk(KERN_DEBUG, &pdev->dev, "RXQ_ERR %X\n",
- rx_desc);
- } else if (rx_desc & RXQ_SLOT_RESET) {
- dev_printk(KERN_DEBUG, &pdev->dev, "Slot reset[%X]\n",
- rx_desc);
- mvs_slot_free(mvi, rx_desc);
- }
- }
-
- if (attn && self_clear)
- mvs_int_full(mvi);
-
- return 0;
-}
-
-#ifdef MVS_USE_TASKLET
-static void mvs_tasklet(unsigned long data)
-{
- struct mvs_info *mvi = (struct mvs_info *) data;
- unsigned long flags;
-
- spin_lock_irqsave(&mvi->lock, flags);
-
-#ifdef MVS_DISABLE_MSI
- mvs_int_full(mvi);
-#else
- mvs_int_rx(mvi, true);
-#endif
- spin_unlock_irqrestore(&mvi->lock, flags);
-}
-#endif
-
-static irqreturn_t mvs_interrupt(int irq, void *opaque)
-{
- struct mvs_info *mvi = opaque;
- void __iomem *regs = mvi->regs;
- u32 stat;
-
- stat = mr32(GBL_INT_STAT);
-
- if (stat == 0 || stat == 0xffffffff)
- return IRQ_NONE;
-
- /* clear CMD_CMPLT ASAP */
- mw32_f(INT_STAT, CINT_DONE);
-
-#ifndef MVS_USE_TASKLET
- spin_lock(&mvi->lock);
-
- mvs_int_full(mvi);
-
- spin_unlock(&mvi->lock);
-#else
- tasklet_schedule(&mvi->tasklet);
-#endif
- return IRQ_HANDLED;
-}
-
-#ifndef MVS_DISABLE_MSI
-static irqreturn_t mvs_msi_interrupt(int irq, void *opaque)
-{
- struct mvs_info *mvi = opaque;
-
-#ifndef MVS_USE_TASKLET
- spin_lock(&mvi->lock);
-
- mvs_int_rx(mvi, true);
-
- spin_unlock(&mvi->lock);
-#else
- tasklet_schedule(&mvi->tasklet);
-#endif
- return IRQ_HANDLED;
-}
-#endif
-
-struct mvs_task_exec_info {
- struct sas_task *task;
- struct mvs_cmd_hdr *hdr;
- struct mvs_port *port;
- u32 tag;
- int n_elem;
-};
-
-static int mvs_task_prep_smp(struct mvs_info *mvi,
- struct mvs_task_exec_info *tei)
-{
- int elem, rc, i;
- struct sas_task *task = tei->task;
- struct mvs_cmd_hdr *hdr = tei->hdr;
- struct scatterlist *sg_req, *sg_resp;
- u32 req_len, resp_len, tag = tei->tag;
- void *buf_tmp;
- u8 *buf_oaf;
- dma_addr_t buf_tmp_dma;
- struct mvs_prd *buf_prd;
- struct scatterlist *sg;
- struct mvs_slot_info *slot = &mvi->slot_info[tag];
- struct asd_sas_port *sas_port = task->dev->port;
- u32 flags = (tei->n_elem << MCH_PRD_LEN_SHIFT);
-#if _MV_DUMP
- u8 *buf_cmd;
- void *from;
-#endif
- /*
- * DMA-map SMP request, response buffers
- */
- sg_req = &task->smp_task.smp_req;
- elem = pci_map_sg(mvi->pdev, sg_req, 1, PCI_DMA_TODEVICE);
- if (!elem)
- return -ENOMEM;
- req_len = sg_dma_len(sg_req);
-
- sg_resp = &task->smp_task.smp_resp;
- elem = pci_map_sg(mvi->pdev, sg_resp, 1, PCI_DMA_FROMDEVICE);
- if (!elem) {
- rc = -ENOMEM;
- goto err_out;
- }
- resp_len = sg_dma_len(sg_resp);
-
- /* must be in dwords */
- if ((req_len & 0x3) || (resp_len & 0x3)) {
- rc = -EINVAL;
- goto err_out_2;
- }
-
- /*
- * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs
- */
-
- /* region 1: command table area (MVS_SSP_CMD_SZ bytes) ************** */
- buf_tmp = slot->buf;
- buf_tmp_dma = slot->buf_dma;
-
-#if _MV_DUMP
- buf_cmd = buf_tmp;
- hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma);
- buf_tmp += req_len;
- buf_tmp_dma += req_len;
- slot->cmd_size = req_len;
-#else
- hdr->cmd_tbl = cpu_to_le64(sg_dma_address(sg_req));
-#endif
-
- /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */
- buf_oaf = buf_tmp;
- hdr->open_frame = cpu_to_le64(buf_tmp_dma);
-
- buf_tmp += MVS_OAF_SZ;
- buf_tmp_dma += MVS_OAF_SZ;
-
- /* region 3: PRD table ********************************************* */
- buf_prd = buf_tmp;
- if (tei->n_elem)
- hdr->prd_tbl = cpu_to_le64(buf_tmp_dma);
- else
- hdr->prd_tbl = 0;
-
- i = sizeof(struct mvs_prd) * tei->n_elem;
- buf_tmp += i;
- buf_tmp_dma += i;
-
- /* region 4: status buffer (larger the PRD, smaller this buf) ****** */
- slot->response = buf_tmp;
- hdr->status_buf = cpu_to_le64(buf_tmp_dma);
-
- /*
- * Fill in TX ring and command slot header
- */
- slot->tx = mvi->tx_prod;
- mvi->tx[mvi->tx_prod] = cpu_to_le32((TXQ_CMD_SMP << TXQ_CMD_SHIFT) |
- TXQ_MODE_I | tag |
- (sas_port->phy_mask << TXQ_PHY_SHIFT));
-
- hdr->flags |= flags;
- hdr->lens = cpu_to_le32(((resp_len / 4) << 16) | ((req_len - 4) / 4));
- hdr->tags = cpu_to_le32(tag);
- hdr->data_len = 0;
-
- /* generate open address frame hdr (first 12 bytes) */
- buf_oaf[0] = (1 << 7) | (0 << 4) | 0x01; /* initiator, SMP, ftype 1h */
- buf_oaf[1] = task->dev->linkrate & 0xf;
- *(u16 *)(buf_oaf + 2) = 0xFFFF; /* SAS SPEC */
- memcpy(buf_oaf + 4, task->dev->sas_addr, SAS_ADDR_SIZE);
-
- /* fill in PRD (scatter/gather) table, if any */
- for_each_sg(task->scatter, sg, tei->n_elem, i) {
- buf_prd->addr = cpu_to_le64(sg_dma_address(sg));
- buf_prd->len = cpu_to_le32(sg_dma_len(sg));
- buf_prd++;
- }
-
-#if _MV_DUMP
- /* copy cmd table */
- from = kmap_atomic(sg_page(sg_req), KM_IRQ0);
- memcpy(buf_cmd, from + sg_req->offset, req_len);
- kunmap_atomic(from, KM_IRQ0);
-#endif
- return 0;
-
-err_out_2:
- pci_unmap_sg(mvi->pdev, &tei->task->smp_task.smp_resp, 1,
- PCI_DMA_FROMDEVICE);
-err_out:
- pci_unmap_sg(mvi->pdev, &tei->task->smp_task.smp_req, 1,
- PCI_DMA_TODEVICE);
- return rc;
-}
-
-static void mvs_free_reg_set(struct mvs_info *mvi, struct mvs_port *port)
-{
- void __iomem *regs = mvi->regs;
- u32 tmp, offs;
- u8 *tfs = &port->taskfileset;
-
- if (*tfs == MVS_ID_NOT_MAPPED)
- return;
-
- offs = 1U << ((*tfs & 0x0f) + PCS_EN_SATA_REG_SHIFT);
- if (*tfs < 16) {
- tmp = mr32(PCS);
- mw32(PCS, tmp & ~offs);
- } else {
- tmp = mr32(CTL);
- mw32(CTL, tmp & ~offs);
- }
-
- tmp = mr32(INT_STAT_SRS) & (1U << *tfs);
- if (tmp)
- mw32(INT_STAT_SRS, tmp);
-
- *tfs = MVS_ID_NOT_MAPPED;
-}
-
-static u8 mvs_assign_reg_set(struct mvs_info *mvi, struct mvs_port *port)
-{
- int i;
- u32 tmp, offs;
- void __iomem *regs = mvi->regs;
-
- if (port->taskfileset != MVS_ID_NOT_MAPPED)
- return 0;
-
- tmp = mr32(PCS);
-
- for (i = 0; i < mvi->chip->srs_sz; i++) {
- if (i == 16)
- tmp = mr32(CTL);
- offs = 1U << ((i & 0x0f) + PCS_EN_SATA_REG_SHIFT);
- if (!(tmp & offs)) {
- port->taskfileset = i;
-
- if (i < 16)
- mw32(PCS, tmp | offs);
- else
- mw32(CTL, tmp | offs);
- tmp = mr32(INT_STAT_SRS) & (1U << i);
- if (tmp)
- mw32(INT_STAT_SRS, tmp);
- return 0;
- }
- }
- return MVS_ID_NOT_MAPPED;
-}
-
-static u32 mvs_get_ncq_tag(struct sas_task *task, u32 *tag)
-{
- struct ata_queued_cmd *qc = task->uldd_task;
-
- if (qc) {
- if (qc->tf.command == ATA_CMD_FPDMA_WRITE ||
- qc->tf.command == ATA_CMD_FPDMA_READ) {
- *tag = qc->tag;
- return 1;
- }
- }
-
- return 0;
-}
-
-static int mvs_task_prep_ata(struct mvs_info *mvi,
- struct mvs_task_exec_info *tei)
-{
- struct sas_task *task = tei->task;
- struct domain_device *dev = task->dev;
- struct mvs_cmd_hdr *hdr = tei->hdr;
- struct asd_sas_port *sas_port = dev->port;
- struct mvs_slot_info *slot;
- struct scatterlist *sg;
- struct mvs_prd *buf_prd;
- struct mvs_port *port = tei->port;
- u32 tag = tei->tag;
- u32 flags = (tei->n_elem << MCH_PRD_LEN_SHIFT);
- void *buf_tmp;
- u8 *buf_cmd, *buf_oaf;
- dma_addr_t buf_tmp_dma;
- u32 i, req_len, resp_len;
- const u32 max_resp_len = SB_RFB_MAX;
-
- if (mvs_assign_reg_set(mvi, port) == MVS_ID_NOT_MAPPED)
- return -EBUSY;
-
- slot = &mvi->slot_info[tag];
- slot->tx = mvi->tx_prod;
- mvi->tx[mvi->tx_prod] = cpu_to_le32(TXQ_MODE_I | tag |
- (TXQ_CMD_STP << TXQ_CMD_SHIFT) |
- (sas_port->phy_mask << TXQ_PHY_SHIFT) |
- (port->taskfileset << TXQ_SRS_SHIFT));
-
- if (task->ata_task.use_ncq)
- flags |= MCH_FPDMA;
- if (dev->sata_dev.command_set == ATAPI_COMMAND_SET) {
- if (task->ata_task.fis.command != ATA_CMD_ID_ATAPI)
- flags |= MCH_ATAPI;
- }
-
- /* FIXME: fill in port multiplier number */
-
- hdr->flags = cpu_to_le32(flags);
-
- /* FIXME: the low order order 5 bits for the TAG if enable NCQ */
- if (task->ata_task.use_ncq && mvs_get_ncq_tag(task, &hdr->tags))
- task->ata_task.fis.sector_count |= hdr->tags << 3;
- else
- hdr->tags = cpu_to_le32(tag);
- hdr->data_len = cpu_to_le32(task->total_xfer_len);
-
- /*
- * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs
- */
-
- /* region 1: command table area (MVS_ATA_CMD_SZ bytes) ************** */
- buf_cmd = buf_tmp = slot->buf;
- buf_tmp_dma = slot->buf_dma;
-
- hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma);
-
- buf_tmp += MVS_ATA_CMD_SZ;
- buf_tmp_dma += MVS_ATA_CMD_SZ;
-#if _MV_DUMP
- slot->cmd_size = MVS_ATA_CMD_SZ;
-#endif
-
- /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */
- /* used for STP. unused for SATA? */
- buf_oaf = buf_tmp;
- hdr->open_frame = cpu_to_le64(buf_tmp_dma);
-
- buf_tmp += MVS_OAF_SZ;
- buf_tmp_dma += MVS_OAF_SZ;
-
- /* region 3: PRD table ********************************************* */
- buf_prd = buf_tmp;
- if (tei->n_elem)
- hdr->prd_tbl = cpu_to_le64(buf_tmp_dma);
- else
- hdr->prd_tbl = 0;
-
- i = sizeof(struct mvs_prd) * tei->n_elem;
- buf_tmp += i;
- buf_tmp_dma += i;
-
- /* region 4: status buffer (larger the PRD, smaller this buf) ****** */
- /* FIXME: probably unused, for SATA. kept here just in case
- * we get a STP/SATA error information record
- */
- slot->response = buf_tmp;
- hdr->status_buf = cpu_to_le64(buf_tmp_dma);
-
- req_len = sizeof(struct host_to_dev_fis);
- resp_len = MVS_SLOT_BUF_SZ - MVS_ATA_CMD_SZ -
- sizeof(struct mvs_err_info) - i;
-
- /* request, response lengths */
- resp_len = min(resp_len, max_resp_len);
- hdr->lens = cpu_to_le32(((resp_len / 4) << 16) | (req_len / 4));
-
- task->ata_task.fis.flags |= 0x80; /* C=1: update ATA cmd reg */
- /* fill in command FIS and ATAPI CDB */
- memcpy(buf_cmd, &task->ata_task.fis, sizeof(struct host_to_dev_fis));
- if (dev->sata_dev.command_set == ATAPI_COMMAND_SET)
- memcpy(buf_cmd + STP_ATAPI_CMD,
- task->ata_task.atapi_packet, 16);
-
- /* generate open address frame hdr (first 12 bytes) */
- buf_oaf[0] = (1 << 7) | (2 << 4) | 0x1; /* initiator, STP, ftype 1h */
- buf_oaf[1] = task->dev->linkrate & 0xf;
- *(u16 *)(buf_oaf + 2) = cpu_to_be16(tag);
- memcpy(buf_oaf + 4, task->dev->sas_addr, SAS_ADDR_SIZE);
-
- /* fill in PRD (scatter/gather) table, if any */
- for_each_sg(task->scatter, sg, tei->n_elem, i) {
- buf_prd->addr = cpu_to_le64(sg_dma_address(sg));
- buf_prd->len = cpu_to_le32(sg_dma_len(sg));
- buf_prd++;
- }
-
- return 0;
-}
-
-static int mvs_task_prep_ssp(struct mvs_info *mvi,
- struct mvs_task_exec_info *tei)
-{
- struct sas_task *task = tei->task;
- struct mvs_cmd_hdr *hdr = tei->hdr;
- struct mvs_port *port = tei->port;
- struct mvs_slot_info *slot;
- struct scatterlist *sg;
- struct mvs_prd *buf_prd;
- struct ssp_frame_hdr *ssp_hdr;
- void *buf_tmp;
- u8 *buf_cmd, *buf_oaf, fburst = 0;
- dma_addr_t buf_tmp_dma;
- u32 flags;
- u32 resp_len, req_len, i, tag = tei->tag;
- const u32 max_resp_len = SB_RFB_MAX;
- u8 phy_mask;
-
- slot = &mvi->slot_info[tag];
-
- phy_mask = (port->wide_port_phymap) ? port->wide_port_phymap :
- task->dev->port->phy_mask;
- slot->tx = mvi->tx_prod;
- mvi->tx[mvi->tx_prod] = cpu_to_le32(TXQ_MODE_I | tag |
- (TXQ_CMD_SSP << TXQ_CMD_SHIFT) |
- (phy_mask << TXQ_PHY_SHIFT));
-
- flags = MCH_RETRY;
- if (task->ssp_task.enable_first_burst) {
- flags |= MCH_FBURST;
- fburst = (1 << 7);
- }
- hdr->flags = cpu_to_le32(flags |
- (tei->n_elem << MCH_PRD_LEN_SHIFT) |
- (MCH_SSP_FR_CMD << MCH_SSP_FR_TYPE_SHIFT));
-
- hdr->tags = cpu_to_le32(tag);
- hdr->data_len = cpu_to_le32(task->total_xfer_len);
-
- /*
- * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs
- */
-
- /* region 1: command table area (MVS_SSP_CMD_SZ bytes) ************** */
- buf_cmd = buf_tmp = slot->buf;
- buf_tmp_dma = slot->buf_dma;
-
- hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma);
-
- buf_tmp += MVS_SSP_CMD_SZ;
- buf_tmp_dma += MVS_SSP_CMD_SZ;
-#if _MV_DUMP
- slot->cmd_size = MVS_SSP_CMD_SZ;
-#endif
-
- /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */
- buf_oaf = buf_tmp;
- hdr->open_frame = cpu_to_le64(buf_tmp_dma);
-
- buf_tmp += MVS_OAF_SZ;
- buf_tmp_dma += MVS_OAF_SZ;
-
- /* region 3: PRD table ********************************************* */
- buf_prd = buf_tmp;
- if (tei->n_elem)
- hdr->prd_tbl = cpu_to_le64(buf_tmp_dma);
- else
- hdr->prd_tbl = 0;
-
- i = sizeof(struct mvs_prd) * tei->n_elem;
- buf_tmp += i;
- buf_tmp_dma += i;
-
- /* region 4: status buffer (larger the PRD, smaller this buf) ****** */
- slot->response = buf_tmp;
- hdr->status_buf = cpu_to_le64(buf_tmp_dma);
-
- resp_len = MVS_SLOT_BUF_SZ - MVS_SSP_CMD_SZ - MVS_OAF_SZ -
- sizeof(struct mvs_err_info) - i;
- resp_len = min(resp_len, max_resp_len);
-
- req_len = sizeof(struct ssp_frame_hdr) + 28;
-
- /* request, response lengths */
- hdr->lens = cpu_to_le32(((resp_len / 4) << 16) | (req_len / 4));
-
- /* generate open address frame hdr (first 12 bytes) */
- buf_oaf[0] = (1 << 7) | (1 << 4) | 0x1; /* initiator, SSP, ftype 1h */
- buf_oaf[1] = task->dev->linkrate & 0xf;
- *(u16 *)(buf_oaf + 2) = cpu_to_be16(tag);
- memcpy(buf_oaf + 4, task->dev->sas_addr, SAS_ADDR_SIZE);
-
- /* fill in SSP frame header (Command Table.SSP frame header) */
- ssp_hdr = (struct ssp_frame_hdr *)buf_cmd;
- ssp_hdr->frame_type = SSP_COMMAND;
- memcpy(ssp_hdr->hashed_dest_addr, task->dev->hashed_sas_addr,
- HASHED_SAS_ADDR_SIZE);
- memcpy(ssp_hdr->hashed_src_addr,
- task->dev->port->ha->hashed_sas_addr, HASHED_SAS_ADDR_SIZE);
- ssp_hdr->tag = cpu_to_be16(tag);
-
- /* fill in command frame IU */
- buf_cmd += sizeof(*ssp_hdr);
- memcpy(buf_cmd, &task->ssp_task.LUN, 8);
- buf_cmd[9] = fburst | task->ssp_task.task_attr |
- (task->ssp_task.task_prio << 3);
- memcpy(buf_cmd + 12, &task->ssp_task.cdb, 16);
-
- /* fill in PRD (scatter/gather) table, if any */
- for_each_sg(task->scatter, sg, tei->n_elem, i) {
- buf_prd->addr = cpu_to_le64(sg_dma_address(sg));
- buf_prd->len = cpu_to_le32(sg_dma_len(sg));
- buf_prd++;
- }
-
- return 0;
-}
-
-static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags)
-{
- struct domain_device *dev = task->dev;
- struct mvs_info *mvi = dev->port->ha->lldd_ha;
- struct pci_dev *pdev = mvi->pdev;
- void __iomem *regs = mvi->regs;
- struct mvs_task_exec_info tei;
- struct sas_task *t = task;
- struct mvs_slot_info *slot;
- u32 tag = 0xdeadbeef, rc, n_elem = 0;
- unsigned long flags;
- u32 n = num, pass = 0;
-
- spin_lock_irqsave(&mvi->lock, flags);
- do {
- dev = t->dev;
- tei.port = &mvi->port[dev->port->id];
-
- if (!tei.port->port_attached) {
- if (sas_protocol_ata(t->task_proto)) {
- rc = SAS_PHY_DOWN;
- goto out_done;
- } else {
- struct task_status_struct *ts = &t->task_status;
- ts->resp = SAS_TASK_UNDELIVERED;
- ts->stat = SAS_PHY_DOWN;
- t->task_done(t);
- if (n > 1)
- t = list_entry(t->list.next,
- struct sas_task, list);
- continue;
- }
- }
-
- if (!sas_protocol_ata(t->task_proto)) {
- if (t->num_scatter) {
- n_elem = pci_map_sg(mvi->pdev, t->scatter,
- t->num_scatter,
- t->data_dir);
- if (!n_elem) {
- rc = -ENOMEM;
- goto err_out;
- }
- }
- } else {
- n_elem = t->num_scatter;
- }
-
- rc = mvs_tag_alloc(mvi, &tag);
- if (rc)
- goto err_out;
-
- slot = &mvi->slot_info[tag];
- t->lldd_task = NULL;
- slot->n_elem = n_elem;
- memset(slot->buf, 0, MVS_SLOT_BUF_SZ);
- tei.task = t;
- tei.hdr = &mvi->slot[tag];
- tei.tag = tag;
- tei.n_elem = n_elem;
-
- switch (t->task_proto) {
- case SAS_PROTOCOL_SMP:
- rc = mvs_task_prep_smp(mvi, &tei);
- break;
- case SAS_PROTOCOL_SSP:
- rc = mvs_task_prep_ssp(mvi, &tei);
- break;
- case SAS_PROTOCOL_SATA:
- case SAS_PROTOCOL_STP:
- case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
- rc = mvs_task_prep_ata(mvi, &tei);
- break;
- default:
- dev_printk(KERN_ERR, &pdev->dev,
- "unknown sas_task proto: 0x%x\n",
- t->task_proto);
- rc = -EINVAL;
- break;
- }
-
- if (rc)
- goto err_out_tag;
-
- slot->task = t;
- slot->port = tei.port;
- t->lldd_task = (void *) slot;
- list_add_tail(&slot->list, &slot->port->list);
- /* TODO: select normal or high priority */
-
- spin_lock(&t->task_state_lock);
- t->task_state_flags |= SAS_TASK_AT_INITIATOR;
- spin_unlock(&t->task_state_lock);
-
- mvs_hba_memory_dump(mvi, tag, t->task_proto);
-
- ++pass;
- mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1);
- if (n > 1)
- t = list_entry(t->list.next, struct sas_task, list);
- } while (--n);
-
- rc = 0;
- goto out_done;
-
-err_out_tag:
- mvs_tag_free(mvi, tag);
-err_out:
- dev_printk(KERN_ERR, &pdev->dev, "mvsas exec failed[%d]!\n", rc);
- if (!sas_protocol_ata(t->task_proto))
- if (n_elem)
- pci_unmap_sg(mvi->pdev, t->scatter, n_elem,
- t->data_dir);
-out_done:
- if (pass)
- mw32(TX_PROD_IDX, (mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1));
- spin_unlock_irqrestore(&mvi->lock, flags);
- return rc;
-}
-
-static int mvs_task_abort(struct sas_task *task)
-{
- int rc;
- unsigned long flags;
- struct mvs_info *mvi = task->dev->port->ha->lldd_ha;
- struct pci_dev *pdev = mvi->pdev;
- int tag;
-
- spin_lock_irqsave(&task->task_state_lock, flags);
- if (task->task_state_flags & SAS_TASK_STATE_DONE) {
- rc = TMF_RESP_FUNC_COMPLETE;
- spin_unlock_irqrestore(&task->task_state_lock, flags);
- goto out_done;
- }
- spin_unlock_irqrestore(&task->task_state_lock, flags);
-
- switch (task->task_proto) {
- case SAS_PROTOCOL_SMP:
- dev_printk(KERN_DEBUG, &pdev->dev, "SMP Abort! \n");
- break;
- case SAS_PROTOCOL_SSP:
- dev_printk(KERN_DEBUG, &pdev->dev, "SSP Abort! \n");
- break;
- case SAS_PROTOCOL_SATA:
- case SAS_PROTOCOL_STP:
- case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:{
- dev_printk(KERN_DEBUG, &pdev->dev, "STP Abort! \n");
-#if _MV_DUMP
- dev_printk(KERN_DEBUG, &pdev->dev, "Dump D2H FIS: \n");
- mvs_hexdump(sizeof(struct host_to_dev_fis),
- (void *)&task->ata_task.fis, 0);
- dev_printk(KERN_DEBUG, &pdev->dev, "Dump ATAPI Cmd : \n");
- mvs_hexdump(16, task->ata_task.atapi_packet, 0);
-#endif
- spin_lock_irqsave(&task->task_state_lock, flags);
- if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET) {
- /* TODO */
- ;
- }
- spin_unlock_irqrestore(&task->task_state_lock, flags);
- break;
- }
- default:
- break;
- }
-
- if (mvs_find_tag(mvi, task, &tag)) {
- spin_lock_irqsave(&mvi->lock, flags);
- mvs_slot_task_free(mvi, task, &mvi->slot_info[tag], tag);
- spin_unlock_irqrestore(&mvi->lock, flags);
- }
- if (!mvs_task_exec(task, 1, GFP_ATOMIC))
- rc = TMF_RESP_FUNC_COMPLETE;
- else
- rc = TMF_RESP_FUNC_FAILED;
-out_done:
- return rc;
-}
-
-static void mvs_free(struct mvs_info *mvi)
-{
- int i;
-
- if (!mvi)
- return;
-
- for (i = 0; i < MVS_SLOTS; i++) {
- struct mvs_slot_info *slot = &mvi->slot_info[i];
-
- if (slot->buf)
- dma_free_coherent(&mvi->pdev->dev, MVS_SLOT_BUF_SZ,
- slot->buf, slot->buf_dma);
- }
-
- if (mvi->tx)
- dma_free_coherent(&mvi->pdev->dev,
- sizeof(*mvi->tx) * MVS_CHIP_SLOT_SZ,
- mvi->tx, mvi->tx_dma);
- if (mvi->rx_fis)
- dma_free_coherent(&mvi->pdev->dev, MVS_RX_FISL_SZ,
- mvi->rx_fis, mvi->rx_fis_dma);
- if (mvi->rx)
- dma_free_coherent(&mvi->pdev->dev,
- sizeof(*mvi->rx) * (MVS_RX_RING_SZ + 1),
- mvi->rx, mvi->rx_dma);
- if (mvi->slot)
- dma_free_coherent(&mvi->pdev->dev,
- sizeof(*mvi->slot) * MVS_SLOTS,
- mvi->slot, mvi->slot_dma);
-#ifdef MVS_ENABLE_PERI
- if (mvi->peri_regs)
- iounmap(mvi->peri_regs);
-#endif
- if (mvi->regs)
- iounmap(mvi->regs);
- if (mvi->shost)
- scsi_host_put(mvi->shost);
- kfree(mvi->sas.sas_port);
- kfree(mvi->sas.sas_phy);
- kfree(mvi);
-}
-
-/* FIXME: locking? */
-static int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
- void *funcdata)
-{
- struct mvs_info *mvi = sas_phy->ha->lldd_ha;
- int rc = 0, phy_id = sas_phy->id;
- u32 tmp;
-
- tmp = mvs_read_phy_ctl(mvi, phy_id);
-
- switch (func) {
- case PHY_FUNC_SET_LINK_RATE:{
- struct sas_phy_linkrates *rates = funcdata;
- u32 lrmin = 0, lrmax = 0;
-
- lrmin = (rates->minimum_linkrate << 8);
- lrmax = (rates->maximum_linkrate << 12);
-
- if (lrmin) {
- tmp &= ~(0xf << 8);
- tmp |= lrmin;
- }
- if (lrmax) {
- tmp &= ~(0xf << 12);
- tmp |= lrmax;
- }
- mvs_write_phy_ctl(mvi, phy_id, tmp);
- break;
- }
-
- case PHY_FUNC_HARD_RESET:
- if (tmp & PHY_RST_HARD)
- break;
- mvs_write_phy_ctl(mvi, phy_id, tmp | PHY_RST_HARD);
- break;
-
- case PHY_FUNC_LINK_RESET:
- mvs_write_phy_ctl(mvi, phy_id, tmp | PHY_RST);
- break;
-
- case PHY_FUNC_DISABLE:
- case PHY_FUNC_RELEASE_SPINUP_HOLD:
- default:
- rc = -EOPNOTSUPP;
- }
-
- return rc;
-}
-
-static void __devinit mvs_phy_init(struct mvs_info *mvi, int phy_id)
-{
- struct mvs_phy *phy = &mvi->phy[phy_id];
- struct asd_sas_phy *sas_phy = &phy->sas_phy;
-
- sas_phy->enabled = (phy_id < mvi->chip->n_phy) ? 1 : 0;
- sas_phy->class = SAS;
- sas_phy->iproto = SAS_PROTOCOL_ALL;
- sas_phy->tproto = 0;
- sas_phy->type = PHY_TYPE_PHYSICAL;
- sas_phy->role = PHY_ROLE_INITIATOR;
- sas_phy->oob_mode = OOB_NOT_CONNECTED;
- sas_phy->linkrate = SAS_LINK_RATE_UNKNOWN;
-
- sas_phy->id = phy_id;
- sas_phy->sas_addr = &mvi->sas_addr[0];
- sas_phy->frame_rcvd = &phy->frame_rcvd[0];
- sas_phy->ha = &mvi->sas;
- sas_phy->lldd_phy = phy;
-}
-
-static struct mvs_info *__devinit mvs_alloc(struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- struct mvs_info *mvi;
- unsigned long res_start, res_len, res_flag;
- struct asd_sas_phy **arr_phy;
- struct asd_sas_port **arr_port;
- const struct mvs_chip_info *chip = &mvs_chips[ent->driver_data];
- int i;
-
- /*
- * alloc and init our per-HBA mvs_info struct
- */
-
- mvi = kzalloc(sizeof(*mvi), GFP_KERNEL);
- if (!mvi)
- return NULL;
-
- spin_lock_init(&mvi->lock);
-#ifdef MVS_USE_TASKLET
- tasklet_init(&mvi->tasklet, mvs_tasklet, (unsigned long)mvi);
-#endif
- mvi->pdev = pdev;
- mvi->chip = chip;
-
- if (pdev->device == 0x6440 && pdev->revision == 0)
- mvi->flags |= MVF_PHY_PWR_FIX;
-
- /*
- * alloc and init SCSI, SAS glue
- */
-
- mvi->shost = scsi_host_alloc(&mvs_sht, sizeof(void *));
- if (!mvi->shost)
- goto err_out;
-
- arr_phy = kcalloc(MVS_MAX_PHYS, sizeof(void *), GFP_KERNEL);
- arr_port = kcalloc(MVS_MAX_PHYS, sizeof(void *), GFP_KERNEL);
- if (!arr_phy || !arr_port)
- goto err_out;
-
- for (i = 0; i < MVS_MAX_PHYS; i++) {
- mvs_phy_init(mvi, i);
- arr_phy[i] = &mvi->phy[i].sas_phy;
- arr_port[i] = &mvi->port[i].sas_port;
- mvi->port[i].taskfileset = MVS_ID_NOT_MAPPED;
- mvi->port[i].wide_port_phymap = 0;
- mvi->port[i].port_attached = 0;
- INIT_LIST_HEAD(&mvi->port[i].list);
- }
-
- SHOST_TO_SAS_HA(mvi->shost) = &mvi->sas;
- mvi->shost->transportt = mvs_stt;
- mvi->shost->max_id = 21;
- mvi->shost->max_lun = ~0;
- mvi->shost->max_channel = 0;
- mvi->shost->max_cmd_len = 16;
-
- mvi->sas.sas_ha_name = DRV_NAME;
- mvi->sas.dev = &pdev->dev;
- mvi->sas.lldd_module = THIS_MODULE;
- mvi->sas.sas_addr = &mvi->sas_addr[0];
- mvi->sas.sas_phy = arr_phy;
- mvi->sas.sas_port = arr_port;
- mvi->sas.num_phys = chip->n_phy;
- mvi->sas.lldd_max_execute_num = 1;
- mvi->sas.lldd_queue_size = MVS_QUEUE_SIZE;
- mvi->shost->can_queue = MVS_CAN_QUEUE;
- mvi->shost->cmd_per_lun = MVS_SLOTS / mvi->sas.num_phys;
- mvi->sas.lldd_ha = mvi;
- mvi->sas.core.shost = mvi->shost;
-
- mvs_tag_init(mvi);
-
- /*
- * ioremap main and peripheral registers
- */
-
-#ifdef MVS_ENABLE_PERI
- res_start = pci_resource_start(pdev, 2);
- res_len = pci_resource_len(pdev, 2);
- if (!res_start || !res_len)
- goto err_out;
-
- mvi->peri_regs = ioremap_nocache(res_start, res_len);
- if (!mvi->peri_regs)
- goto err_out;
-#endif
-
- res_start = pci_resource_start(pdev, 4);
- res_len = pci_resource_len(pdev, 4);
- if (!res_start || !res_len)
- goto err_out;
-
- res_flag = pci_resource_flags(pdev, 4);
- if (res_flag & IORESOURCE_CACHEABLE)
- mvi->regs = ioremap(res_start, res_len);
- else
- mvi->regs = ioremap_nocache(res_start, res_len);
-
- if (!mvi->regs)
- goto err_out;
-
- /*
- * alloc and init our DMA areas
- */
-
- mvi->tx = dma_alloc_coherent(&pdev->dev,
- sizeof(*mvi->tx) * MVS_CHIP_SLOT_SZ,
- &mvi->tx_dma, GFP_KERNEL);
- if (!mvi->tx)
- goto err_out;
- memset(mvi->tx, 0, sizeof(*mvi->tx) * MVS_CHIP_SLOT_SZ);
-
- mvi->rx_fis = dma_alloc_coherent(&pdev->dev, MVS_RX_FISL_SZ,
- &mvi->rx_fis_dma, GFP_KERNEL);
- if (!mvi->rx_fis)
- goto err_out;
- memset(mvi->rx_fis, 0, MVS_RX_FISL_SZ);
-
- mvi->rx = dma_alloc_coherent(&pdev->dev,
- sizeof(*mvi->rx) * (MVS_RX_RING_SZ + 1),
- &mvi->rx_dma, GFP_KERNEL);
- if (!mvi->rx)
- goto err_out;
- memset(mvi->rx, 0, sizeof(*mvi->rx) * (MVS_RX_RING_SZ + 1));
-
- mvi->rx[0] = cpu_to_le32(0xfff);
- mvi->rx_cons = 0xfff;
-
- mvi->slot = dma_alloc_coherent(&pdev->dev,
- sizeof(*mvi->slot) * MVS_SLOTS,
- &mvi->slot_dma, GFP_KERNEL);
- if (!mvi->slot)
- goto err_out;
- memset(mvi->slot, 0, sizeof(*mvi->slot) * MVS_SLOTS);
-
- for (i = 0; i < MVS_SLOTS; i++) {
- struct mvs_slot_info *slot = &mvi->slot_info[i];
-
- slot->buf = dma_alloc_coherent(&pdev->dev, MVS_SLOT_BUF_SZ,
- &slot->buf_dma, GFP_KERNEL);
- if (!slot->buf)
- goto err_out;
- memset(slot->buf, 0, MVS_SLOT_BUF_SZ);
- }
-
- /* finally, read NVRAM to get our SAS address */
- if (mvs_nvram_read(mvi, NVR_SAS_ADDR, &mvi->sas_addr, 8))
- goto err_out;
- return mvi;
-
-err_out:
- mvs_free(mvi);
- return NULL;
-}
-
-static u32 mvs_cr32(void __iomem *regs, u32 addr)
-{
- mw32(CMD_ADDR, addr);
- return mr32(CMD_DATA);
-}
-
-static void mvs_cw32(void __iomem *regs, u32 addr, u32 val)
-{
- mw32(CMD_ADDR, addr);
- mw32(CMD_DATA, val);
-}
-
-static u32 mvs_read_phy_ctl(struct mvs_info *mvi, u32 port)
-{
- void __iomem *regs = mvi->regs;
- return (port < 4)?mr32(P0_SER_CTLSTAT + port * 4):
- mr32(P4_SER_CTLSTAT + (port - 4) * 4);
-}
-
-static void mvs_write_phy_ctl(struct mvs_info *mvi, u32 port, u32 val)
-{
- void __iomem *regs = mvi->regs;
- if (port < 4)
- mw32(P0_SER_CTLSTAT + port * 4, val);
- else
- mw32(P4_SER_CTLSTAT + (port - 4) * 4, val);
-}
-
-static u32 mvs_read_port(struct mvs_info *mvi, u32 off, u32 off2, u32 port)
-{
- void __iomem *regs = mvi->regs + off;
- void __iomem *regs2 = mvi->regs + off2;
- return (port < 4)?readl(regs + port * 8):
- readl(regs2 + (port - 4) * 8);
-}
-
-static void mvs_write_port(struct mvs_info *mvi, u32 off, u32 off2,
- u32 port, u32 val)
-{
- void __iomem *regs = mvi->regs + off;
- void __iomem *regs2 = mvi->regs + off2;
- if (port < 4)
- writel(val, regs + port * 8);
- else
- writel(val, regs2 + (port - 4) * 8);
-}
-
-static u32 mvs_read_port_cfg_data(struct mvs_info *mvi, u32 port)
-{
- return mvs_read_port(mvi, MVS_P0_CFG_DATA, MVS_P4_CFG_DATA, port);
-}
-
-static void mvs_write_port_cfg_data(struct mvs_info *mvi, u32 port, u32 val)
-{
- mvs_write_port(mvi, MVS_P0_CFG_DATA, MVS_P4_CFG_DATA, port, val);
-}
-
-static void mvs_write_port_cfg_addr(struct mvs_info *mvi, u32 port, u32 addr)
-{
- mvs_write_port(mvi, MVS_P0_CFG_ADDR, MVS_P4_CFG_ADDR, port, addr);
-}
-
-static u32 mvs_read_port_vsr_data(struct mvs_info *mvi, u32 port)
-{
- return mvs_read_port(mvi, MVS_P0_VSR_DATA, MVS_P4_VSR_DATA, port);
-}
-
-static void mvs_write_port_vsr_data(struct mvs_info *mvi, u32 port, u32 val)
-{
- mvs_write_port(mvi, MVS_P0_VSR_DATA, MVS_P4_VSR_DATA, port, val);
-}
-
-static void mvs_write_port_vsr_addr(struct mvs_info *mvi, u32 port, u32 addr)
-{
- mvs_write_port(mvi, MVS_P0_VSR_ADDR, MVS_P4_VSR_ADDR, port, addr);
-}
-
-static u32 mvs_read_port_irq_stat(struct mvs_info *mvi, u32 port)
-{
- return mvs_read_port(mvi, MVS_P0_INT_STAT, MVS_P4_INT_STAT, port);
-}
-
-static void mvs_write_port_irq_stat(struct mvs_info *mvi, u32 port, u32 val)
-{
- mvs_write_port(mvi, MVS_P0_INT_STAT, MVS_P4_INT_STAT, port, val);
-}
-
-static u32 mvs_read_port_irq_mask(struct mvs_info *mvi, u32 port)
-{
- return mvs_read_port(mvi, MVS_P0_INT_MASK, MVS_P4_INT_MASK, port);
-}
-
-static void mvs_write_port_irq_mask(struct mvs_info *mvi, u32 port, u32 val)
-{
- mvs_write_port(mvi, MVS_P0_INT_MASK, MVS_P4_INT_MASK, port, val);
-}
-
-static void __devinit mvs_phy_hacks(struct mvs_info *mvi)
-{
- void __iomem *regs = mvi->regs;
- u32 tmp;
-
- /* workaround for SATA R-ERR, to ignore phy glitch */
- tmp = mvs_cr32(regs, CMD_PHY_TIMER);
- tmp &= ~(1 << 9);
- tmp |= (1 << 10);
- mvs_cw32(regs, CMD_PHY_TIMER, tmp);
-
- /* enable retry 127 times */
- mvs_cw32(regs, CMD_SAS_CTL1, 0x7f7f);
-
- /* extend open frame timeout to max */
- tmp = mvs_cr32(regs, CMD_SAS_CTL0);
- tmp &= ~0xffff;
- tmp |= 0x3fff;
- mvs_cw32(regs, CMD_SAS_CTL0, tmp);
-
- /* workaround for WDTIMEOUT , set to 550 ms */
- mvs_cw32(regs, CMD_WD_TIMER, 0x86470);
-
- /* not to halt for different port op during wideport link change */
- mvs_cw32(regs, CMD_APP_ERR_CONFIG, 0xffefbf7d);
-
- /* workaround for Seagate disk not-found OOB sequence, recv
- * COMINIT before sending out COMWAKE */
- tmp = mvs_cr32(regs, CMD_PHY_MODE_21);
- tmp &= 0x0000ffff;
- tmp |= 0x00fa0000;
- mvs_cw32(regs, CMD_PHY_MODE_21, tmp);
-
- tmp = mvs_cr32(regs, CMD_PHY_TIMER);
- tmp &= 0x1fffffff;
- tmp |= (2U << 29); /* 8 ms retry */
- mvs_cw32(regs, CMD_PHY_TIMER, tmp);
-
- /* TEST - for phy decoding error, adjust voltage levels */
- mw32(P0_VSR_ADDR + 0, 0x8);
- mw32(P0_VSR_DATA + 0, 0x2F0);
-
- mw32(P0_VSR_ADDR + 8, 0x8);
- mw32(P0_VSR_DATA + 8, 0x2F0);
-
- mw32(P0_VSR_ADDR + 16, 0x8);
- mw32(P0_VSR_DATA + 16, 0x2F0);
-
- mw32(P0_VSR_ADDR + 24, 0x8);
- mw32(P0_VSR_DATA + 24, 0x2F0);
-
-}
-
-static void mvs_enable_xmt(struct mvs_info *mvi, int PhyId)
-{
- void __iomem *regs = mvi->regs;
- u32 tmp;
-
- tmp = mr32(PCS);
- if (mvi->chip->n_phy <= 4)
- tmp |= 1 << (PhyId + PCS_EN_PORT_XMT_SHIFT);
- else
- tmp |= 1 << (PhyId + PCS_EN_PORT_XMT_SHIFT2);
- mw32(PCS, tmp);
-}
-
-static void mvs_detect_porttype(struct mvs_info *mvi, int i)
-{
- void __iomem *regs = mvi->regs;
- u32 reg;
- struct mvs_phy *phy = &mvi->phy[i];
-
- /* TODO check & save device type */
- reg = mr32(GBL_PORT_TYPE);
-
- if (reg & MODE_SAS_SATA & (1 << i))
- phy->phy_type |= PORT_TYPE_SAS;
- else
- phy->phy_type |= PORT_TYPE_SATA;
-}
-
-static void *mvs_get_d2h_reg(struct mvs_info *mvi, int i, void *buf)
-{
- u32 *s = (u32 *) buf;
-
- if (!s)
- return NULL;
-
- mvs_write_port_cfg_addr(mvi, i, PHYR_SATA_SIG3);
- s[3] = mvs_read_port_cfg_data(mvi, i);
-
- mvs_write_port_cfg_addr(mvi, i, PHYR_SATA_SIG2);
- s[2] = mvs_read_port_cfg_data(mvi, i);
-
- mvs_write_port_cfg_addr(mvi, i, PHYR_SATA_SIG1);
- s[1] = mvs_read_port_cfg_data(mvi, i);
-
- mvs_write_port_cfg_addr(mvi, i, PHYR_SATA_SIG0);
- s[0] = mvs_read_port_cfg_data(mvi, i);
-
- return (void *)s;
-}
-
-static u32 mvs_is_sig_fis_received(u32 irq_status)
-{
- return irq_status & PHYEV_SIG_FIS;
-}
-
-static void mvs_update_wideport(struct mvs_info *mvi, int i)
-{
- struct mvs_phy *phy = &mvi->phy[i];
- struct mvs_port *port = phy->port;
- int j, no;
-
- for_each_phy(port->wide_port_phymap, no, j, mvi->chip->n_phy)
- if (no & 1) {
- mvs_write_port_cfg_addr(mvi, no, PHYR_WIDE_PORT);
- mvs_write_port_cfg_data(mvi, no,
- port->wide_port_phymap);
- } else {
- mvs_write_port_cfg_addr(mvi, no, PHYR_WIDE_PORT);
- mvs_write_port_cfg_data(mvi, no, 0);
- }
-}
-
-static u32 mvs_is_phy_ready(struct mvs_info *mvi, int i)
-{
- u32 tmp;
- struct mvs_phy *phy = &mvi->phy[i];
- struct mvs_port *port = phy->port;;
-
- tmp = mvs_read_phy_ctl(mvi, i);
-
- if ((tmp & PHY_READY_MASK) && !(phy->irq_status & PHYEV_POOF)) {
- if (!port)
- phy->phy_attached = 1;
- return tmp;
- }
-
- if (port) {
- if (phy->phy_type & PORT_TYPE_SAS) {
- port->wide_port_phymap &= ~(1U << i);
- if (!port->wide_port_phymap)
- port->port_attached = 0;
- mvs_update_wideport(mvi, i);
- } else if (phy->phy_type & PORT_TYPE_SATA)
- port->port_attached = 0;
- mvs_free_reg_set(mvi, phy->port);
- phy->port = NULL;
- phy->phy_attached = 0;
- phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA);
- }
- return 0;
-}
-
-static void mvs_update_phyinfo(struct mvs_info *mvi, int i,
- int get_st)
-{
- struct mvs_phy *phy = &mvi->phy[i];
- struct pci_dev *pdev = mvi->pdev;
- u32 tmp;
- u64 tmp64;
-
- mvs_write_port_cfg_addr(mvi, i, PHYR_IDENTIFY);
- phy->dev_info = mvs_read_port_cfg_data(mvi, i);
-
- mvs_write_port_cfg_addr(mvi, i, PHYR_ADDR_HI);
- phy->dev_sas_addr = (u64) mvs_read_port_cfg_data(mvi, i) << 32;
-
- mvs_write_port_cfg_addr(mvi, i, PHYR_ADDR_LO);
- phy->dev_sas_addr |= mvs_read_port_cfg_data(mvi, i);
-
- if (get_st) {
- phy->irq_status = mvs_read_port_irq_stat(mvi, i);
- phy->phy_status = mvs_is_phy_ready(mvi, i);
- }
-
- if (phy->phy_status) {
- u32 phy_st;
- struct asd_sas_phy *sas_phy = mvi->sas.sas_phy[i];
-
- mvs_write_port_cfg_addr(mvi, i, PHYR_PHY_STAT);
- phy_st = mvs_read_port_cfg_data(mvi, i);
-
- sas_phy->linkrate =
- (phy->phy_status & PHY_NEG_SPP_PHYS_LINK_RATE_MASK) >>
- PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET;
- phy->minimum_linkrate =
- (phy->phy_status &
- PHY_MIN_SPP_PHYS_LINK_RATE_MASK) >> 8;
- phy->maximum_linkrate =
- (phy->phy_status &
- PHY_MAX_SPP_PHYS_LINK_RATE_MASK) >> 12;
-
- if (phy->phy_type & PORT_TYPE_SAS) {
- /* Updated attached_sas_addr */
- mvs_write_port_cfg_addr(mvi, i, PHYR_ATT_ADDR_HI);
- phy->att_dev_sas_addr =
- (u64) mvs_read_port_cfg_data(mvi, i) << 32;
- mvs_write_port_cfg_addr(mvi, i, PHYR_ATT_ADDR_LO);
- phy->att_dev_sas_addr |= mvs_read_port_cfg_data(mvi, i);
- mvs_write_port_cfg_addr(mvi, i, PHYR_ATT_DEV_INFO);
- phy->att_dev_info = mvs_read_port_cfg_data(mvi, i);
- phy->identify.device_type =
- phy->att_dev_info & PORT_DEV_TYPE_MASK;
-
- if (phy->identify.device_type == SAS_END_DEV)
- phy->identify.target_port_protocols =
- SAS_PROTOCOL_SSP;
- else if (phy->identify.device_type != NO_DEVICE)
- phy->identify.target_port_protocols =
- SAS_PROTOCOL_SMP;
- if (phy_st & PHY_OOB_DTCTD)
- sas_phy->oob_mode = SAS_OOB_MODE;
- phy->frame_rcvd_size =
- sizeof(struct sas_identify_frame);
- } else if (phy->phy_type & PORT_TYPE_SATA) {
- phy->identify.target_port_protocols = SAS_PROTOCOL_STP;
- if (mvs_is_sig_fis_received(phy->irq_status)) {
- phy->att_dev_sas_addr = i; /* temp */
- if (phy_st & PHY_OOB_DTCTD)
- sas_phy->oob_mode = SATA_OOB_MODE;
- phy->frame_rcvd_size =
- sizeof(struct dev_to_host_fis);
- mvs_get_d2h_reg(mvi, i,
- (void *)sas_phy->frame_rcvd);
- } else {
- dev_printk(KERN_DEBUG, &pdev->dev,
- "No sig fis\n");
- phy->phy_type &= ~(PORT_TYPE_SATA);
- goto out_done;
- }
- }
- tmp64 = cpu_to_be64(phy->att_dev_sas_addr);
- memcpy(sas_phy->attached_sas_addr, &tmp64, SAS_ADDR_SIZE);
-
- dev_printk(KERN_DEBUG, &pdev->dev,
- "phy[%d] Get Attached Address 0x%llX ,"
- " SAS Address 0x%llX\n",
- i,
- (unsigned long long)phy->att_dev_sas_addr,
- (unsigned long long)phy->dev_sas_addr);
- dev_printk(KERN_DEBUG, &pdev->dev,
- "Rate = %x , type = %d\n",
- sas_phy->linkrate, phy->phy_type);
-
- /* workaround for HW phy decoding error on 1.5g disk drive */
- mvs_write_port_vsr_addr(mvi, i, VSR_PHY_MODE6);
- tmp = mvs_read_port_vsr_data(mvi, i);
- if (((phy->phy_status & PHY_NEG_SPP_PHYS_LINK_RATE_MASK) >>
- PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET) ==
- SAS_LINK_RATE_1_5_GBPS)
- tmp &= ~PHY_MODE6_LATECLK;
- else
- tmp |= PHY_MODE6_LATECLK;
- mvs_write_port_vsr_data(mvi, i, tmp);
-
- }
-out_done:
- if (get_st)
- mvs_write_port_irq_stat(mvi, i, phy->irq_status);
-}
-
-static void mvs_port_formed(struct asd_sas_phy *sas_phy)
-{
- struct sas_ha_struct *sas_ha = sas_phy->ha;
- struct mvs_info *mvi = sas_ha->lldd_ha;
- struct asd_sas_port *sas_port = sas_phy->port;
- struct mvs_phy *phy = sas_phy->lldd_phy;
- struct mvs_port *port = &mvi->port[sas_port->id];
- unsigned long flags;
-
- spin_lock_irqsave(&mvi->lock, flags);
- port->port_attached = 1;
- phy->port = port;
- port->taskfileset = MVS_ID_NOT_MAPPED;
- if (phy->phy_type & PORT_TYPE_SAS) {
- port->wide_port_phymap = sas_port->phy_mask;
- mvs_update_wideport(mvi, sas_phy->id);
- }
- spin_unlock_irqrestore(&mvi->lock, flags);
-}
-
-static int mvs_I_T_nexus_reset(struct domain_device *dev)
-{
- return TMF_RESP_FUNC_FAILED;
-}
-
-static int __devinit mvs_hw_init(struct mvs_info *mvi)
-{
- void __iomem *regs = mvi->regs;
- int i;
- u32 tmp, cctl;
-
- /* make sure interrupts are masked immediately (paranoia) */
- mw32(GBL_CTL, 0);
- tmp = mr32(GBL_CTL);
-
- /* Reset Controller */
- if (!(tmp & HBA_RST)) {
- if (mvi->flags & MVF_PHY_PWR_FIX) {
- pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, &tmp);
- tmp &= ~PCTL_PWR_ON;
- tmp |= PCTL_OFF;
- pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, tmp);
-
- pci_read_config_dword(mvi->pdev, PCR_PHY_CTL2, &tmp);
- tmp &= ~PCTL_PWR_ON;
- tmp |= PCTL_OFF;
- pci_write_config_dword(mvi->pdev, PCR_PHY_CTL2, tmp);
- }
-
- /* global reset, incl. COMRESET/H_RESET_N (self-clearing) */
- mw32_f(GBL_CTL, HBA_RST);
- }
-
- /* wait for reset to finish; timeout is just a guess */
- i = 1000;
- while (i-- > 0) {
- msleep(10);
-
- if (!(mr32(GBL_CTL) & HBA_RST))
- break;
- }
- if (mr32(GBL_CTL) & HBA_RST) {
- dev_printk(KERN_ERR, &mvi->pdev->dev, "HBA reset failed\n");
- return -EBUSY;
- }
-
- /* Init Chip */
- /* make sure RST is set; HBA_RST /should/ have done that for us */
- cctl = mr32(CTL);
- if (cctl & CCTL_RST)
- cctl &= ~CCTL_RST;
- else
- mw32_f(CTL, cctl | CCTL_RST);
-
- /* write to device control _AND_ device status register? - A.C. */
- pci_read_config_dword(mvi->pdev, PCR_DEV_CTRL, &tmp);
- tmp &= ~PRD_REQ_MASK;
- tmp |= PRD_REQ_SIZE;
- pci_write_config_dword(mvi->pdev, PCR_DEV_CTRL, tmp);
-
- pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, &tmp);
- tmp |= PCTL_PWR_ON;
- tmp &= ~PCTL_OFF;
- pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, tmp);
-
- pci_read_config_dword(mvi->pdev, PCR_PHY_CTL2, &tmp);
- tmp |= PCTL_PWR_ON;
- tmp &= ~PCTL_OFF;
- pci_write_config_dword(mvi->pdev, PCR_PHY_CTL2, tmp);
-
- mw32_f(CTL, cctl);
-
- /* reset control */
- mw32(PCS, 0); /*MVS_PCS */
-
- mvs_phy_hacks(mvi);
-
- mw32(CMD_LIST_LO, mvi->slot_dma);
- mw32(CMD_LIST_HI, (mvi->slot_dma >> 16) >> 16);
-
- mw32(RX_FIS_LO, mvi->rx_fis_dma);
- mw32(RX_FIS_HI, (mvi->rx_fis_dma >> 16) >> 16);
-
- mw32(TX_CFG, MVS_CHIP_SLOT_SZ);
- mw32(TX_LO, mvi->tx_dma);
- mw32(TX_HI, (mvi->tx_dma >> 16) >> 16);
-
- mw32(RX_CFG, MVS_RX_RING_SZ);
- mw32(RX_LO, mvi->rx_dma);
- mw32(RX_HI, (mvi->rx_dma >> 16) >> 16);
-
- /* enable auto port detection */
- mw32(GBL_PORT_TYPE, MODE_AUTO_DET_EN);
- msleep(1100);
- /* init and reset phys */
- for (i = 0; i < mvi->chip->n_phy; i++) {
- u32 lo = be32_to_cpu(*(u32 *)&mvi->sas_addr[4]);
- u32 hi = be32_to_cpu(*(u32 *)&mvi->sas_addr[0]);
-
- mvs_detect_porttype(mvi, i);
-
- /* set phy local SAS address */
- mvs_write_port_cfg_addr(mvi, i, PHYR_ADDR_LO);
- mvs_write_port_cfg_data(mvi, i, lo);
- mvs_write_port_cfg_addr(mvi, i, PHYR_ADDR_HI);
- mvs_write_port_cfg_data(mvi, i, hi);
-
- /* reset phy */
- tmp = mvs_read_phy_ctl(mvi, i);
- tmp |= PHY_RST;
- mvs_write_phy_ctl(mvi, i, tmp);
- }
-
- msleep(100);
-
- for (i = 0; i < mvi->chip->n_phy; i++) {
- /* clear phy int status */
- tmp = mvs_read_port_irq_stat(mvi, i);
- tmp &= ~PHYEV_SIG_FIS;
- mvs_write_port_irq_stat(mvi, i, tmp);
-
- /* set phy int mask */
- tmp = PHYEV_RDY_CH | PHYEV_BROAD_CH | PHYEV_UNASSOC_FIS |
- PHYEV_ID_DONE | PHYEV_DEC_ERR;
- mvs_write_port_irq_mask(mvi, i, tmp);
-
- msleep(100);
- mvs_update_phyinfo(mvi, i, 1);
- mvs_enable_xmt(mvi, i);
- }
-
- /* FIXME: update wide port bitmaps */
-
- /* little endian for open address and command table, etc. */
- /* A.C.
- * it seems that ( from the spec ) turning on big-endian won't
- * do us any good on big-endian machines, need further confirmation
- */
- cctl = mr32(CTL);
- cctl |= CCTL_ENDIAN_CMD;
- cctl |= CCTL_ENDIAN_DATA;
- cctl &= ~CCTL_ENDIAN_OPEN;
- cctl |= CCTL_ENDIAN_RSP;
- mw32_f(CTL, cctl);
-
- /* reset CMD queue */
- tmp = mr32(PCS);
- tmp |= PCS_CMD_RST;
- mw32(PCS, tmp);
- /* interrupt coalescing may cause missing HW interrput in some case,
- * and the max count is 0x1ff, while our max slot is 0x200,
- * it will make count 0.
- */
- tmp = 0;
- mw32(INT_COAL, tmp);
-
- tmp = 0x100;
- mw32(INT_COAL_TMOUT, tmp);
-
- /* ladies and gentlemen, start your engines */
- mw32(TX_CFG, 0);
- mw32(TX_CFG, MVS_CHIP_SLOT_SZ | TX_EN);
- mw32(RX_CFG, MVS_RX_RING_SZ | RX_EN);
- /* enable CMD/CMPL_Q/RESP mode */
- mw32(PCS, PCS_SATA_RETRY | PCS_FIS_RX_EN | PCS_CMD_EN);
-
- /* enable completion queue interrupt */
- tmp = (CINT_PORT_MASK | CINT_DONE | CINT_MEM | CINT_SRS);
- mw32(INT_MASK, tmp);
-
- /* Enable SRS interrupt */
- mw32(INT_MASK_SRS, 0xFF);
- return 0;
-}
-
-static void __devinit mvs_print_info(struct mvs_info *mvi)
-{
- struct pci_dev *pdev = mvi->pdev;
- static int printed_version;
-
- if (!printed_version++)
- dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
-
- dev_printk(KERN_INFO, &pdev->dev, "%u phys, addr %llx\n",
- mvi->chip->n_phy, SAS_ADDR(mvi->sas_addr));
-}
-
-static int __devinit mvs_pci_init(struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- int rc;
- struct mvs_info *mvi;
- irq_handler_t irq_handler = mvs_interrupt;
-
- rc = pci_enable_device(pdev);
- if (rc)
- return rc;
-
- pci_set_master(pdev);
-
- rc = pci_request_regions(pdev, DRV_NAME);
- if (rc)
- goto err_out_disable;
-
- rc = pci_go_64(pdev);
- if (rc)
- goto err_out_regions;
-
- mvi = mvs_alloc(pdev, ent);
- if (!mvi) {
- rc = -ENOMEM;
- goto err_out_regions;
- }
-
- rc = mvs_hw_init(mvi);
- if (rc)
- goto err_out_mvi;
-
-#ifndef MVS_DISABLE_MSI
- if (!pci_enable_msi(pdev)) {
- u32 tmp;
- void __iomem *regs = mvi->regs;
- mvi->flags |= MVF_MSI;
- irq_handler = mvs_msi_interrupt;
- tmp = mr32(PCS);
- mw32(PCS, tmp | PCS_SELF_CLEAR);
- }
-#endif
-
- rc = request_irq(pdev->irq, irq_handler, IRQF_SHARED, DRV_NAME, mvi);
- if (rc)
- goto err_out_msi;
-
- rc = scsi_add_host(mvi->shost, &pdev->dev);
- if (rc)
- goto err_out_irq;
-
- rc = sas_register_ha(&mvi->sas);
- if (rc)
- goto err_out_shost;
-
- pci_set_drvdata(pdev, mvi);
-
- mvs_print_info(mvi);
-
- mvs_hba_interrupt_enable(mvi);
-
- scsi_scan_host(mvi->shost);
-
- return 0;
-
-err_out_shost:
- scsi_remove_host(mvi->shost);
-err_out_irq:
- free_irq(pdev->irq, mvi);
-err_out_msi:
- if (mvi->flags |= MVF_MSI)
- pci_disable_msi(pdev);
-err_out_mvi:
- mvs_free(mvi);
-err_out_regions:
- pci_release_regions(pdev);
-err_out_disable:
- pci_disable_device(pdev);
- return rc;
-}
-
-static void __devexit mvs_pci_remove(struct pci_dev *pdev)
-{
- struct mvs_info *mvi = pci_get_drvdata(pdev);
-
- pci_set_drvdata(pdev, NULL);
-
- if (mvi) {
- sas_unregister_ha(&mvi->sas);
- mvs_hba_interrupt_disable(mvi);
- sas_remove_host(mvi->shost);
- scsi_remove_host(mvi->shost);
-
- free_irq(pdev->irq, mvi);
- if (mvi->flags & MVF_MSI)
- pci_disable_msi(pdev);
- mvs_free(mvi);
- pci_release_regions(pdev);
- }
- pci_disable_device(pdev);
-}
-
-static struct sas_domain_function_template mvs_transport_ops = {
- .lldd_execute_task = mvs_task_exec,
- .lldd_control_phy = mvs_phy_control,
- .lldd_abort_task = mvs_task_abort,
- .lldd_port_formed = mvs_port_formed,
- .lldd_I_T_nexus_reset = mvs_I_T_nexus_reset,
-};
-
-static struct pci_device_id __devinitdata mvs_pci_table[] = {
- { PCI_VDEVICE(MARVELL, 0x6320), chip_6320 },
- { PCI_VDEVICE(MARVELL, 0x6340), chip_6440 },
- {
- .vendor = PCI_VENDOR_ID_MARVELL,
- .device = 0x6440,
- .subvendor = PCI_ANY_ID,
- .subdevice = 0x6480,
- .class = 0,
- .class_mask = 0,
- .driver_data = chip_6480,
- },
- { PCI_VDEVICE(MARVELL, 0x6440), chip_6440 },
- { PCI_VDEVICE(MARVELL, 0x6480), chip_6480 },
-
- { } /* terminate list */
-};
-
-static struct pci_driver mvs_pci_driver = {
- .name = DRV_NAME,
- .id_table = mvs_pci_table,
- .probe = mvs_pci_init,
- .remove = __devexit_p(mvs_pci_remove),
-};
-
-static int __init mvs_init(void)
-{
- int rc;
-
- mvs_stt = sas_domain_attach_transport(&mvs_transport_ops);
- if (!mvs_stt)
- return -ENOMEM;
-
- rc = pci_register_driver(&mvs_pci_driver);
- if (rc)
- goto err_out;
-
- return 0;
-
-err_out:
- sas_release_transport(mvs_stt);
- return rc;
-}
-
-static void __exit mvs_exit(void)
-{
- pci_unregister_driver(&mvs_pci_driver);
- sas_release_transport(mvs_stt);
-}
-
-module_init(mvs_init);
-module_exit(mvs_exit);
-
-MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>");
-MODULE_DESCRIPTION("Marvell 88SE6440 SAS/SATA controller driver");
-MODULE_VERSION(DRV_VERSION);
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, mvs_pci_table);
diff --git a/drivers/scsi/mvsas/Kconfig b/drivers/scsi/mvsas/Kconfig
new file mode 100644
index 000000000000..6de7af27e507
--- /dev/null
+++ b/drivers/scsi/mvsas/Kconfig
@@ -0,0 +1,42 @@
+#
+# Kernel configuration file for 88SE64XX/88SE94XX SAS/SATA driver.
+#
+# Copyright 2007 Red Hat, Inc.
+# Copyright 2008 Marvell. <kewei@marvell.com>
+#
+# This file is licensed under GPLv2.
+#
+# This file is part of the 88SE64XX/88SE94XX driver.
+#
+# The 88SE64XX/88SE94XX 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; version 2 of the
+# License.
+#
+# The 88SE64XX/88SE94XX 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 88SE64XX/88SE94XX Driver; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+#
+
+config SCSI_MVSAS
+ tristate "Marvell 88SE64XX/88SE94XX SAS/SATA support"
+ depends on PCI
+ select SCSI_SAS_LIBSAS
+ select FW_LOADER
+ help
+ This driver supports Marvell's SAS/SATA 3Gb/s PCI-E 88SE64XX and 6Gb/s
+ PCI-E 88SE94XX chip based host adapters.
+
+config SCSI_MVSAS_DEBUG
+ bool "Compile in debug mode"
+ default y
+ depends on SCSI_MVSAS
+ help
+ Compiles the 88SE64XX/88SE94XX driver in debug mode. In debug mode,
+ the driver prints some messages to the console.
diff --git a/drivers/scsi/mvsas/Makefile b/drivers/scsi/mvsas/Makefile
new file mode 100644
index 000000000000..52ac4264677d
--- /dev/null
+++ b/drivers/scsi/mvsas/Makefile
@@ -0,0 +1,32 @@
+#
+# Makefile for Marvell 88SE64xx/88SE84xx SAS/SATA driver.
+#
+# Copyright 2007 Red Hat, Inc.
+# Copyright 2008 Marvell. <kewei@marvell.com>
+#
+# This file is licensed under GPLv2.
+#
+# 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
+
+ifeq ($(CONFIG_SCSI_MVSAS_DEBUG),y)
+ EXTRA_CFLAGS += -DMV_DEBUG
+endif
+
+obj-$(CONFIG_SCSI_MVSAS) += mvsas.o
+mvsas-y += mv_init.o \
+ mv_sas.o \
+ mv_64xx.o \
+ mv_94xx.o
diff --git a/drivers/scsi/mvsas/mv_64xx.c b/drivers/scsi/mvsas/mv_64xx.c
new file mode 100644
index 000000000000..10a5077b6aed
--- /dev/null
+++ b/drivers/scsi/mvsas/mv_64xx.c
@@ -0,0 +1,793 @@
+/*
+ * Marvell 88SE64xx hardware specific
+ *
+ * Copyright 2007 Red Hat, Inc.
+ * Copyright 2008 Marvell. <kewei@marvell.com>
+ *
+ * This file is licensed under GPLv2.
+ *
+ * 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
+*/
+
+#include "mv_sas.h"
+#include "mv_64xx.h"
+#include "mv_chips.h"
+
+static void mvs_64xx_detect_porttype(struct mvs_info *mvi, int i)
+{
+ void __iomem *regs = mvi->regs;
+ u32 reg;
+ struct mvs_phy *phy = &mvi->phy[i];
+
+ /* TODO check & save device type */
+ reg = mr32(MVS_GBL_PORT_TYPE);
+ phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA);
+ if (reg & MODE_SAS_SATA & (1 << i))
+ phy->phy_type |= PORT_TYPE_SAS;
+ else
+ phy->phy_type |= PORT_TYPE_SATA;
+}
+
+static void __devinit mvs_64xx_enable_xmt(struct mvs_info *mvi, int phy_id)
+{
+ void __iomem *regs = mvi->regs;
+ u32 tmp;
+
+ tmp = mr32(MVS_PCS);
+ if (mvi->chip->n_phy <= 4)
+ tmp |= 1 << (phy_id + PCS_EN_PORT_XMT_SHIFT);
+ else
+ tmp |= 1 << (phy_id + PCS_EN_PORT_XMT_SHIFT2);
+ mw32(MVS_PCS, tmp);
+}
+
+static void __devinit mvs_64xx_phy_hacks(struct mvs_info *mvi)
+{
+ void __iomem *regs = mvi->regs;
+
+ mvs_phy_hacks(mvi);
+
+ if (!(mvi->flags & MVF_FLAG_SOC)) {
+ /* TEST - for phy decoding error, adjust voltage levels */
+ mw32(MVS_P0_VSR_ADDR + 0, 0x8);
+ mw32(MVS_P0_VSR_DATA + 0, 0x2F0);
+
+ mw32(MVS_P0_VSR_ADDR + 8, 0x8);
+ mw32(MVS_P0_VSR_DATA + 8, 0x2F0);
+
+ mw32(MVS_P0_VSR_ADDR + 16, 0x8);
+ mw32(MVS_P0_VSR_DATA + 16, 0x2F0);
+
+ mw32(MVS_P0_VSR_ADDR + 24, 0x8);
+ mw32(MVS_P0_VSR_DATA + 24, 0x2F0);
+ } else {
+ int i;
+ /* disable auto port detection */
+ mw32(MVS_GBL_PORT_TYPE, 0);
+ for (i = 0; i < mvi->chip->n_phy; i++) {
+ mvs_write_port_vsr_addr(mvi, i, VSR_PHY_MODE7);
+ mvs_write_port_vsr_data(mvi, i, 0x90000000);
+ mvs_write_port_vsr_addr(mvi, i, VSR_PHY_MODE9);
+ mvs_write_port_vsr_data(mvi, i, 0x50f2);
+ mvs_write_port_vsr_addr(mvi, i, VSR_PHY_MODE11);
+ mvs_write_port_vsr_data(mvi, i, 0x0e);
+ }
+ }
+}
+
+static void mvs_64xx_stp_reset(struct mvs_info *mvi, u32 phy_id)
+{
+ void __iomem *regs = mvi->regs;
+ u32 reg, tmp;
+
+ if (!(mvi->flags & MVF_FLAG_SOC)) {
+ if (phy_id < 4)
+ pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, &reg);
+ else
+ pci_read_config_dword(mvi->pdev, PCR_PHY_CTL2, &reg);
+
+ } else
+ reg = mr32(MVS_PHY_CTL);
+
+ tmp = reg;
+ if (phy_id < 4)
+ tmp |= (1U << phy_id) << PCTL_LINK_OFFS;
+ else
+ tmp |= (1U << (phy_id - 4)) << PCTL_LINK_OFFS;
+
+ if (!(mvi->flags & MVF_FLAG_SOC)) {
+ if (phy_id < 4) {
+ pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, tmp);
+ mdelay(10);
+ pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, reg);
+ } else {
+ pci_write_config_dword(mvi->pdev, PCR_PHY_CTL2, tmp);
+ mdelay(10);
+ pci_write_config_dword(mvi->pdev, PCR_PHY_CTL2, reg);
+ }
+ } else {
+ mw32(MVS_PHY_CTL, tmp);
+ mdelay(10);
+ mw32(MVS_PHY_CTL, reg);
+ }
+}
+
+static void mvs_64xx_phy_reset(struct mvs_info *mvi, u32 phy_id, int hard)
+{
+ u32 tmp;
+ tmp = mvs_read_port_irq_stat(mvi, phy_id);
+ tmp &= ~PHYEV_RDY_CH;
+ mvs_write_port_irq_stat(mvi, phy_id, tmp);
+ tmp = mvs_read_phy_ctl(mvi, phy_id);
+ if (hard)
+ tmp |= PHY_RST_HARD;
+ else
+ tmp |= PHY_RST;
+ mvs_write_phy_ctl(mvi, phy_id, tmp);
+ if (hard) {
+ do {
+ tmp = mvs_read_phy_ctl(mvi, phy_id);
+ } while (tmp & PHY_RST_HARD);
+ }
+}
+
+static int __devinit mvs_64xx_chip_reset(struct mvs_info *mvi)
+{
+ void __iomem *regs = mvi->regs;
+ u32 tmp;
+ int i;
+
+ /* make sure interrupts are masked immediately (paranoia) */
+ mw32(MVS_GBL_CTL, 0);
+ tmp = mr32(MVS_GBL_CTL);
+
+ /* Reset Controller */
+ if (!(tmp & HBA_RST)) {
+ if (mvi->flags & MVF_PHY_PWR_FIX) {
+ pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, &tmp);
+ tmp &= ~PCTL_PWR_OFF;
+ tmp |= PCTL_PHY_DSBL;
+ pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, tmp);
+
+ pci_read_config_dword(mvi->pdev, PCR_PHY_CTL2, &tmp);
+ tmp &= ~PCTL_PWR_OFF;
+ tmp |= PCTL_PHY_DSBL;
+ pci_write_config_dword(mvi->pdev, PCR_PHY_CTL2, tmp);
+ }
+ }
+
+ /* make sure interrupts are masked immediately (paranoia) */
+ mw32(MVS_GBL_CTL, 0);
+ tmp = mr32(MVS_GBL_CTL);
+
+ /* Reset Controller */
+ if (!(tmp & HBA_RST)) {
+ /* global reset, incl. COMRESET/H_RESET_N (self-clearing) */
+ mw32_f(MVS_GBL_CTL, HBA_RST);
+ }
+
+ /* wait for reset to finish; timeout is just a guess */
+ i = 1000;
+ while (i-- > 0) {
+ msleep(10);
+
+ if (!(mr32(MVS_GBL_CTL) & HBA_RST))
+ break;
+ }
+ if (mr32(MVS_GBL_CTL) & HBA_RST) {
+ dev_printk(KERN_ERR, mvi->dev, "HBA reset failed\n");
+ return -EBUSY;
+ }
+ return 0;
+}
+
+static void mvs_64xx_phy_disable(struct mvs_info *mvi, u32 phy_id)
+{
+ void __iomem *regs = mvi->regs;
+ u32 tmp;
+ if (!(mvi->flags & MVF_FLAG_SOC)) {
+ u32 offs;
+ if (phy_id < 4)
+ offs = PCR_PHY_CTL;
+ else {
+ offs = PCR_PHY_CTL2;
+ phy_id -= 4;
+ }
+ pci_read_config_dword(mvi->pdev, offs, &tmp);
+ tmp |= 1U << (PCTL_PHY_DSBL_OFFS + phy_id);
+ pci_write_config_dword(mvi->pdev, offs, tmp);
+ } else {
+ tmp = mr32(MVS_PHY_CTL);
+ tmp |= 1U << (PCTL_PHY_DSBL_OFFS + phy_id);
+ mw32(MVS_PHY_CTL, tmp);
+ }
+}
+
+static void mvs_64xx_phy_enable(struct mvs_info *mvi, u32 phy_id)
+{
+ void __iomem *regs = mvi->regs;
+ u32 tmp;
+ if (!(mvi->flags & MVF_FLAG_SOC)) {
+ u32 offs;
+ if (phy_id < 4)
+ offs = PCR_PHY_CTL;
+ else {
+ offs = PCR_PHY_CTL2;
+ phy_id -= 4;
+ }
+ pci_read_config_dword(mvi->pdev, offs, &tmp);
+ tmp &= ~(1U << (PCTL_PHY_DSBL_OFFS + phy_id));
+ pci_write_config_dword(mvi->pdev, offs, tmp);
+ } else {
+ tmp = mr32(MVS_PHY_CTL);
+ tmp &= ~(1U << (PCTL_PHY_DSBL_OFFS + phy_id));
+ mw32(MVS_PHY_CTL, tmp);
+ }
+}
+
+static int __devinit mvs_64xx_init(struct mvs_info *mvi)
+{
+ void __iomem *regs = mvi->regs;
+ int i;
+ u32 tmp, cctl;
+
+ if (mvi->pdev && mvi->pdev->revision == 0)
+ mvi->flags |= MVF_PHY_PWR_FIX;
+ if (!(mvi->flags & MVF_FLAG_SOC)) {
+ mvs_show_pcie_usage(mvi);
+ tmp = mvs_64xx_chip_reset(mvi);
+ if (tmp)
+ return tmp;
+ } else {
+ tmp = mr32(MVS_PHY_CTL);
+ tmp &= ~PCTL_PWR_OFF;
+ tmp |= PCTL_PHY_DSBL;
+ mw32(MVS_PHY_CTL, tmp);
+ }
+
+ /* Init Chip */
+ /* make sure RST is set; HBA_RST /should/ have done that for us */
+ cctl = mr32(MVS_CTL) & 0xFFFF;
+ if (cctl & CCTL_RST)
+ cctl &= ~CCTL_RST;
+ else
+ mw32_f(MVS_CTL, cctl | CCTL_RST);
+
+ if (!(mvi->flags & MVF_FLAG_SOC)) {
+ /* write to device control _AND_ device status register */
+ pci_read_config_dword(mvi->pdev, PCR_DEV_CTRL, &tmp);
+ tmp &= ~PRD_REQ_MASK;
+ tmp |= PRD_REQ_SIZE;
+ pci_write_config_dword(mvi->pdev, PCR_DEV_CTRL, tmp);
+
+ pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, &tmp);
+ tmp &= ~PCTL_PWR_OFF;
+ tmp &= ~PCTL_PHY_DSBL;
+ pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, tmp);
+
+ pci_read_config_dword(mvi->pdev, PCR_PHY_CTL2, &tmp);
+ tmp &= PCTL_PWR_OFF;
+ tmp &= ~PCTL_PHY_DSBL;
+ pci_write_config_dword(mvi->pdev, PCR_PHY_CTL2, tmp);
+ } else {
+ tmp = mr32(MVS_PHY_CTL);
+ tmp &= ~PCTL_PWR_OFF;
+ tmp |= PCTL_COM_ON;
+ tmp &= ~PCTL_PHY_DSBL;
+ tmp |= PCTL_LINK_RST;
+ mw32(MVS_PHY_CTL, tmp);
+ msleep(100);
+ tmp &= ~PCTL_LINK_RST;
+ mw32(MVS_PHY_CTL, tmp);
+ msleep(100);
+ }
+
+ /* reset control */
+ mw32(MVS_PCS, 0); /* MVS_PCS */
+ /* init phys */
+ mvs_64xx_phy_hacks(mvi);
+
+ /* enable auto port detection */
+ mw32(MVS_GBL_PORT_TYPE, MODE_AUTO_DET_EN);
+
+ mw32(MVS_CMD_LIST_LO, mvi->slot_dma);
+ mw32(MVS_CMD_LIST_HI, (mvi->slot_dma >> 16) >> 16);
+
+ mw32(MVS_RX_FIS_LO, mvi->rx_fis_dma);
+ mw32(MVS_RX_FIS_HI, (mvi->rx_fis_dma >> 16) >> 16);
+
+ mw32(MVS_TX_CFG, MVS_CHIP_SLOT_SZ);
+ mw32(MVS_TX_LO, mvi->tx_dma);
+ mw32(MVS_TX_HI, (mvi->tx_dma >> 16) >> 16);
+
+ mw32(MVS_RX_CFG, MVS_RX_RING_SZ);
+ mw32(MVS_RX_LO, mvi->rx_dma);
+ mw32(MVS_RX_HI, (mvi->rx_dma >> 16) >> 16);
+
+ for (i = 0; i < mvi->chip->n_phy; i++) {
+ /* set phy local SAS address */
+ /* should set little endian SAS address to 64xx chip */
+ mvs_set_sas_addr(mvi, i, PHYR_ADDR_LO, PHYR_ADDR_HI,
+ cpu_to_be64(mvi->phy[i].dev_sas_addr));
+
+ mvs_64xx_enable_xmt(mvi, i);
+
+ mvs_64xx_phy_reset(mvi, i, 1);
+ msleep(500);
+ mvs_64xx_detect_porttype(mvi, i);
+ }
+ if (mvi->flags & MVF_FLAG_SOC) {
+ /* set select registers */
+ writel(0x0E008000, regs + 0x000);
+ writel(0x59000008, regs + 0x004);
+ writel(0x20, regs + 0x008);
+ writel(0x20, regs + 0x00c);
+ writel(0x20, regs + 0x010);
+ writel(0x20, regs + 0x014);
+ writel(0x20, regs + 0x018);
+ writel(0x20, regs + 0x01c);
+ }
+ for (i = 0; i < mvi->chip->n_phy; i++) {
+ /* clear phy int status */
+ tmp = mvs_read_port_irq_stat(mvi, i);
+ tmp &= ~PHYEV_SIG_FIS;
+ mvs_write_port_irq_stat(mvi, i, tmp);
+
+ /* set phy int mask */
+ tmp = PHYEV_RDY_CH | PHYEV_BROAD_CH | PHYEV_UNASSOC_FIS |
+ PHYEV_ID_DONE | PHYEV_DCDR_ERR | PHYEV_CRC_ERR |
+ PHYEV_DEC_ERR;
+ mvs_write_port_irq_mask(mvi, i, tmp);
+
+ msleep(100);
+ mvs_update_phyinfo(mvi, i, 1);
+ }
+
+ /* FIXME: update wide port bitmaps */
+
+ /* little endian for open address and command table, etc. */
+ /*
+ * it seems that ( from the spec ) turning on big-endian won't
+ * do us any good on big-endian machines, need further confirmation
+ */
+ cctl = mr32(MVS_CTL);
+ cctl |= CCTL_ENDIAN_CMD;
+ cctl |= CCTL_ENDIAN_DATA;
+ cctl &= ~CCTL_ENDIAN_OPEN;
+ cctl |= CCTL_ENDIAN_RSP;
+ mw32_f(MVS_CTL, cctl);
+
+ /* reset CMD queue */
+ tmp = mr32(MVS_PCS);
+ tmp |= PCS_CMD_RST;
+ mw32(MVS_PCS, tmp);
+ /* interrupt coalescing may cause missing HW interrput in some case,
+ * and the max count is 0x1ff, while our max slot is 0x200,
+ * it will make count 0.
+ */
+ tmp = 0;
+ mw32(MVS_INT_COAL, tmp);
+
+ tmp = 0x100;
+ mw32(MVS_INT_COAL_TMOUT, tmp);
+
+ /* ladies and gentlemen, start your engines */
+ mw32(MVS_TX_CFG, 0);
+ mw32(MVS_TX_CFG, MVS_CHIP_SLOT_SZ | TX_EN);
+ mw32(MVS_RX_CFG, MVS_RX_RING_SZ | RX_EN);
+ /* enable CMD/CMPL_Q/RESP mode */
+ mw32(MVS_PCS, PCS_SATA_RETRY | PCS_FIS_RX_EN |
+ PCS_CMD_EN | PCS_CMD_STOP_ERR);
+
+ /* enable completion queue interrupt */
+ tmp = (CINT_PORT_MASK | CINT_DONE | CINT_MEM | CINT_SRS | CINT_CI_STOP |
+ CINT_DMA_PCIE);
+
+ mw32(MVS_INT_MASK, tmp);
+
+ /* Enable SRS interrupt */
+ mw32(MVS_INT_MASK_SRS_0, 0xFFFF);
+
+ return 0;
+}
+
+static int mvs_64xx_ioremap(struct mvs_info *mvi)
+{
+ if (!mvs_ioremap(mvi, 4, 2))
+ return 0;
+ return -1;
+}
+
+static void mvs_64xx_iounmap(struct mvs_info *mvi)
+{
+ mvs_iounmap(mvi->regs);
+ mvs_iounmap(mvi->regs_ex);
+}
+
+static void mvs_64xx_interrupt_enable(struct mvs_info *mvi)
+{
+ void __iomem *regs = mvi->regs;
+ u32 tmp;
+
+ tmp = mr32(MVS_GBL_CTL);
+ mw32(MVS_GBL_CTL, tmp | INT_EN);
+}
+
+static void mvs_64xx_interrupt_disable(struct mvs_info *mvi)
+{
+ void __iomem *regs = mvi->regs;
+ u32 tmp;
+
+ tmp = mr32(MVS_GBL_CTL);
+ mw32(MVS_GBL_CTL, tmp & ~INT_EN);
+}
+
+static u32 mvs_64xx_isr_status(struct mvs_info *mvi, int irq)
+{
+ void __iomem *regs = mvi->regs;
+ u32 stat;
+
+ if (!(mvi->flags & MVF_FLAG_SOC)) {
+ stat = mr32(MVS_GBL_INT_STAT);
+
+ if (stat == 0 || stat == 0xffffffff)
+ return 0;
+ } else
+ stat = 1;
+ return stat;
+}
+
+static irqreturn_t mvs_64xx_isr(struct mvs_info *mvi, int irq, u32 stat)
+{
+ void __iomem *regs = mvi->regs;
+
+ /* clear CMD_CMPLT ASAP */
+ mw32_f(MVS_INT_STAT, CINT_DONE);
+#ifndef MVS_USE_TASKLET
+ spin_lock(&mvi->lock);
+#endif
+ mvs_int_full(mvi);
+#ifndef MVS_USE_TASKLET
+ spin_unlock(&mvi->lock);
+#endif
+ return IRQ_HANDLED;
+}
+
+static void mvs_64xx_command_active(struct mvs_info *mvi, u32 slot_idx)
+{
+ u32 tmp;
+ mvs_cw32(mvi, 0x40 + (slot_idx >> 3), 1 << (slot_idx % 32));
+ mvs_cw32(mvi, 0x00 + (slot_idx >> 3), 1 << (slot_idx % 32));
+ do {
+ tmp = mvs_cr32(mvi, 0x00 + (slot_idx >> 3));
+ } while (tmp & 1 << (slot_idx % 32));
+ do {
+ tmp = mvs_cr32(mvi, 0x40 + (slot_idx >> 3));
+ } while (tmp & 1 << (slot_idx % 32));
+}
+
+static void mvs_64xx_issue_stop(struct mvs_info *mvi, enum mvs_port_type type,
+ u32 tfs)
+{
+ void __iomem *regs = mvi->regs;
+ u32 tmp;
+
+ if (type == PORT_TYPE_SATA) {
+ tmp = mr32(MVS_INT_STAT_SRS_0) | (1U << tfs);
+ mw32(MVS_INT_STAT_SRS_0, tmp);
+ }
+ mw32(MVS_INT_STAT, CINT_CI_STOP);
+ tmp = mr32(MVS_PCS) | 0xFF00;
+ mw32(MVS_PCS, tmp);
+}
+
+static void mvs_64xx_free_reg_set(struct mvs_info *mvi, u8 *tfs)
+{
+ void __iomem *regs = mvi->regs;
+ u32 tmp, offs;
+
+ if (*tfs == MVS_ID_NOT_MAPPED)
+ return;
+
+ offs = 1U << ((*tfs & 0x0f) + PCS_EN_SATA_REG_SHIFT);
+ if (*tfs < 16) {
+ tmp = mr32(MVS_PCS);
+ mw32(MVS_PCS, tmp & ~offs);
+ } else {
+ tmp = mr32(MVS_CTL);
+ mw32(MVS_CTL, tmp & ~offs);
+ }
+
+ tmp = mr32(MVS_INT_STAT_SRS_0) & (1U << *tfs);
+ if (tmp)
+ mw32(MVS_INT_STAT_SRS_0, tmp);
+
+ *tfs = MVS_ID_NOT_MAPPED;
+ return;
+}
+
+static u8 mvs_64xx_assign_reg_set(struct mvs_info *mvi, u8 *tfs)
+{
+ int i;
+ u32 tmp, offs;
+ void __iomem *regs = mvi->regs;
+
+ if (*tfs != MVS_ID_NOT_MAPPED)
+ return 0;
+
+ tmp = mr32(MVS_PCS);
+
+ for (i = 0; i < mvi->chip->srs_sz; i++) {
+ if (i == 16)
+ tmp = mr32(MVS_CTL);
+ offs = 1U << ((i & 0x0f) + PCS_EN_SATA_REG_SHIFT);
+ if (!(tmp & offs)) {
+ *tfs = i;
+
+ if (i < 16)
+ mw32(MVS_PCS, tmp | offs);
+ else
+ mw32(MVS_CTL, tmp | offs);
+ tmp = mr32(MVS_INT_STAT_SRS_0) & (1U << i);
+ if (tmp)
+ mw32(MVS_INT_STAT_SRS_0, tmp);
+ return 0;
+ }
+ }
+ return MVS_ID_NOT_MAPPED;
+}
+
+void mvs_64xx_make_prd(struct scatterlist *scatter, int nr, void *prd)
+{
+ int i;
+ struct scatterlist *sg;
+ struct mvs_prd *buf_prd = prd;
+ for_each_sg(scatter, sg, nr, i) {
+ buf_prd->addr = cpu_to_le64(sg_dma_address(sg));
+ buf_prd->len = cpu_to_le32(sg_dma_len(sg));
+ buf_prd++;
+ }
+}
+
+static int mvs_64xx_oob_done(struct mvs_info *mvi, int i)
+{
+ u32 phy_st;
+ mvs_write_port_cfg_addr(mvi, i,
+ PHYR_PHY_STAT);
+ phy_st = mvs_read_port_cfg_data(mvi, i);
+ if (phy_st & PHY_OOB_DTCTD)
+ return 1;
+ return 0;
+}
+
+static void mvs_64xx_fix_phy_info(struct mvs_info *mvi, int i,
+ struct sas_identify_frame *id)
+
+{
+ struct mvs_phy *phy = &mvi->phy[i];
+ struct asd_sas_phy *sas_phy = &phy->sas_phy;
+
+ sas_phy->linkrate =
+ (phy->phy_status & PHY_NEG_SPP_PHYS_LINK_RATE_MASK) >>
+ PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET;
+
+ phy->minimum_linkrate =
+ (phy->phy_status &
+ PHY_MIN_SPP_PHYS_LINK_RATE_MASK) >> 8;
+ phy->maximum_linkrate =
+ (phy->phy_status &
+ PHY_MAX_SPP_PHYS_LINK_RATE_MASK) >> 12;
+
+ mvs_write_port_cfg_addr(mvi, i, PHYR_IDENTIFY);
+ phy->dev_info = mvs_read_port_cfg_data(mvi, i);
+
+ mvs_write_port_cfg_addr(mvi, i, PHYR_ATT_DEV_INFO);
+ phy->att_dev_info = mvs_read_port_cfg_data(mvi, i);
+
+ mvs_write_port_cfg_addr(mvi, i, PHYR_ATT_ADDR_HI);
+ phy->att_dev_sas_addr =
+ (u64) mvs_read_port_cfg_data(mvi, i) << 32;
+ mvs_write_port_cfg_addr(mvi, i, PHYR_ATT_ADDR_LO);
+ phy->att_dev_sas_addr |= mvs_read_port_cfg_data(mvi, i);
+ phy->att_dev_sas_addr = SAS_ADDR(&phy->att_dev_sas_addr);
+}
+
+static void mvs_64xx_phy_work_around(struct mvs_info *mvi, int i)
+{
+ u32 tmp;
+ struct mvs_phy *phy = &mvi->phy[i];
+ /* workaround for HW phy decoding error on 1.5g disk drive */
+ mvs_write_port_vsr_addr(mvi, i, VSR_PHY_MODE6);
+ tmp = mvs_read_port_vsr_data(mvi, i);
+ if (((phy->phy_status & PHY_NEG_SPP_PHYS_LINK_RATE_MASK) >>
+ PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET) ==
+ SAS_LINK_RATE_1_5_GBPS)
+ tmp &= ~PHY_MODE6_LATECLK;
+ else
+ tmp |= PHY_MODE6_LATECLK;
+ mvs_write_port_vsr_data(mvi, i, tmp);
+}
+
+void mvs_64xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id,
+ struct sas_phy_linkrates *rates)
+{
+ u32 lrmin = 0, lrmax = 0;
+ u32 tmp;
+
+ tmp = mvs_read_phy_ctl(mvi, phy_id);
+ lrmin = (rates->minimum_linkrate << 8);
+ lrmax = (rates->maximum_linkrate << 12);
+
+ if (lrmin) {
+ tmp &= ~(0xf << 8);
+ tmp |= lrmin;
+ }
+ if (lrmax) {
+ tmp &= ~(0xf << 12);
+ tmp |= lrmax;
+ }
+ mvs_write_phy_ctl(mvi, phy_id, tmp);
+ mvs_64xx_phy_reset(mvi, phy_id, 1);
+}
+
+static void mvs_64xx_clear_active_cmds(struct mvs_info *mvi)
+{
+ u32 tmp;
+ void __iomem *regs = mvi->regs;
+ tmp = mr32(MVS_PCS);
+ mw32(MVS_PCS, tmp & 0xFFFF);
+ mw32(MVS_PCS, tmp);
+ tmp = mr32(MVS_CTL);
+ mw32(MVS_CTL, tmp & 0xFFFF);
+ mw32(MVS_CTL, tmp);
+}
+
+
+u32 mvs_64xx_spi_read_data(struct mvs_info *mvi)
+{
+ void __iomem *regs = mvi->regs_ex;
+ return ior32(SPI_DATA_REG_64XX);
+}
+
+void mvs_64xx_spi_write_data(struct mvs_info *mvi, u32 data)
+{
+ void __iomem *regs = mvi->regs_ex;
+ iow32(SPI_DATA_REG_64XX, data);
+}
+
+
+int mvs_64xx_spi_buildcmd(struct mvs_info *mvi,
+ u32 *dwCmd,
+ u8 cmd,
+ u8 read,
+ u8 length,
+ u32 addr
+ )
+{
+ u32 dwTmp;
+
+ dwTmp = ((u32)cmd << 24) | ((u32)length << 19);
+ if (read)
+ dwTmp |= 1U<<23;
+
+ if (addr != MV_MAX_U32) {
+ dwTmp |= 1U<<22;
+ dwTmp |= (addr & 0x0003FFFF);
+ }
+
+ *dwCmd = dwTmp;
+ return 0;
+}
+
+
+int mvs_64xx_spi_issuecmd(struct mvs_info *mvi, u32 cmd)
+{
+ void __iomem *regs = mvi->regs_ex;
+ int retry;
+
+ for (retry = 0; retry < 1; retry++) {
+ iow32(SPI_CTRL_REG_64XX, SPI_CTRL_VENDOR_ENABLE);
+ iow32(SPI_CMD_REG_64XX, cmd);
+ iow32(SPI_CTRL_REG_64XX,
+ SPI_CTRL_VENDOR_ENABLE | SPI_CTRL_SPISTART);
+ }
+
+ return 0;
+}
+
+int mvs_64xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout)
+{
+ void __iomem *regs = mvi->regs_ex;
+ u32 i, dwTmp;
+
+ for (i = 0; i < timeout; i++) {
+ dwTmp = ior32(SPI_CTRL_REG_64XX);
+ if (!(dwTmp & SPI_CTRL_SPISTART))
+ return 0;
+ msleep(10);
+ }
+
+ return -1;
+}
+
+#ifndef DISABLE_HOTPLUG_DMA_FIX
+void mvs_64xx_fix_dma(dma_addr_t buf_dma, int buf_len, int from, void *prd)
+{
+ int i;
+ struct mvs_prd *buf_prd = prd;
+ buf_prd += from;
+ for (i = 0; i < MAX_SG_ENTRY - from; i++) {
+ buf_prd->addr = cpu_to_le64(buf_dma);
+ buf_prd->len = cpu_to_le32(buf_len);
+ ++buf_prd;
+ }
+}
+#endif
+
+const struct mvs_dispatch mvs_64xx_dispatch = {
+ "mv64xx",
+ mvs_64xx_init,
+ NULL,
+ mvs_64xx_ioremap,
+ mvs_64xx_iounmap,
+ mvs_64xx_isr,
+ mvs_64xx_isr_status,
+ mvs_64xx_interrupt_enable,
+ mvs_64xx_interrupt_disable,
+ mvs_read_phy_ctl,
+ mvs_write_phy_ctl,
+ mvs_read_port_cfg_data,
+ mvs_write_port_cfg_data,
+ mvs_write_port_cfg_addr,
+ mvs_read_port_vsr_data,
+ mvs_write_port_vsr_data,
+ mvs_write_port_vsr_addr,
+ mvs_read_port_irq_stat,
+ mvs_write_port_irq_stat,
+ mvs_read_port_irq_mask,
+ mvs_write_port_irq_mask,
+ mvs_get_sas_addr,
+ mvs_64xx_command_active,
+ mvs_64xx_issue_stop,
+ mvs_start_delivery,
+ mvs_rx_update,
+ mvs_int_full,
+ mvs_64xx_assign_reg_set,
+ mvs_64xx_free_reg_set,
+ mvs_get_prd_size,
+ mvs_get_prd_count,
+ mvs_64xx_make_prd,
+ mvs_64xx_detect_porttype,
+ mvs_64xx_oob_done,
+ mvs_64xx_fix_phy_info,
+ mvs_64xx_phy_work_around,
+ mvs_64xx_phy_set_link_rate,
+ mvs_hw_max_link_rate,
+ mvs_64xx_phy_disable,
+ mvs_64xx_phy_enable,
+ mvs_64xx_phy_reset,
+ mvs_64xx_stp_reset,
+ mvs_64xx_clear_active_cmds,
+ mvs_64xx_spi_read_data,
+ mvs_64xx_spi_write_data,
+ mvs_64xx_spi_buildcmd,
+ mvs_64xx_spi_issuecmd,
+ mvs_64xx_spi_waitdataready,
+#ifndef DISABLE_HOTPLUG_DMA_FIX
+ mvs_64xx_fix_dma,
+#endif
+};
+
diff --git a/drivers/scsi/mvsas/mv_64xx.h b/drivers/scsi/mvsas/mv_64xx.h
new file mode 100644
index 000000000000..42e947d9795e
--- /dev/null
+++ b/drivers/scsi/mvsas/mv_64xx.h
@@ -0,0 +1,151 @@
+/*
+ * Marvell 88SE64xx hardware specific head file
+ *
+ * Copyright 2007 Red Hat, Inc.
+ * Copyright 2008 Marvell. <kewei@marvell.com>
+ *
+ * This file is licensed under GPLv2.
+ *
+ * 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
+*/
+
+#ifndef _MVS64XX_REG_H_
+#define _MVS64XX_REG_H_
+
+#include <linux/types.h>
+
+#define MAX_LINK_RATE SAS_LINK_RATE_3_0_GBPS
+
+/* enhanced mode registers (BAR4) */
+enum hw_registers {
+ MVS_GBL_CTL = 0x04, /* global control */
+ MVS_GBL_INT_STAT = 0x08, /* global irq status */
+ MVS_GBL_PI = 0x0C, /* ports implemented bitmask */
+
+ MVS_PHY_CTL = 0x40, /* SOC PHY Control */
+ MVS_PORTS_IMP = 0x9C, /* SOC Port Implemented */
+
+ MVS_GBL_PORT_TYPE = 0xa0, /* port type */
+
+ MVS_CTL = 0x100, /* SAS/SATA port configuration */
+ MVS_PCS = 0x104, /* SAS/SATA port control/status */
+ MVS_CMD_LIST_LO = 0x108, /* cmd list addr */
+ MVS_CMD_LIST_HI = 0x10C,
+ MVS_RX_FIS_LO = 0x110, /* RX FIS list addr */
+ MVS_RX_FIS_HI = 0x114,
+
+ MVS_TX_CFG = 0x120, /* TX configuration */
+ MVS_TX_LO = 0x124, /* TX (delivery) ring addr */
+ MVS_TX_HI = 0x128,
+
+ MVS_TX_PROD_IDX = 0x12C, /* TX producer pointer */
+ MVS_TX_CONS_IDX = 0x130, /* TX consumer pointer (RO) */
+ MVS_RX_CFG = 0x134, /* RX configuration */
+ MVS_RX_LO = 0x138, /* RX (completion) ring addr */
+ MVS_RX_HI = 0x13C,
+ MVS_RX_CONS_IDX = 0x140, /* RX consumer pointer (RO) */
+
+ MVS_INT_COAL = 0x148, /* Int coalescing config */
+ MVS_INT_COAL_TMOUT = 0x14C, /* Int coalescing timeout */
+ MVS_INT_STAT = 0x150, /* Central int status */
+ MVS_INT_MASK = 0x154, /* Central int enable */
+ MVS_INT_STAT_SRS_0 = 0x158, /* SATA register set status */
+ MVS_INT_MASK_SRS_0 = 0x15C,
+
+ /* ports 1-3 follow after this */
+ MVS_P0_INT_STAT = 0x160, /* port0 interrupt status */
+ MVS_P0_INT_MASK = 0x164, /* port0 interrupt mask */
+ /* ports 5-7 follow after this */
+ MVS_P4_INT_STAT = 0x200, /* Port4 interrupt status */
+ MVS_P4_INT_MASK = 0x204, /* Port4 interrupt enable mask */
+
+ /* ports 1-3 follow after this */
+ MVS_P0_SER_CTLSTAT = 0x180, /* port0 serial control/status */
+ /* ports 5-7 follow after this */
+ MVS_P4_SER_CTLSTAT = 0x220, /* port4 serial control/status */
+
+ MVS_CMD_ADDR = 0x1B8, /* Command register port (addr) */
+ MVS_CMD_DATA = 0x1BC, /* Command register port (data) */
+
+ /* ports 1-3 follow after this */
+ MVS_P0_CFG_ADDR = 0x1C0, /* port0 phy register address */
+ MVS_P0_CFG_DATA = 0x1C4, /* port0 phy register data */
+ /* ports 5-7 follow after this */
+ MVS_P4_CFG_ADDR = 0x230, /* Port4 config address */
+ MVS_P4_CFG_DATA = 0x234, /* Port4 config data */
+
+ /* ports 1-3 follow after this */
+ MVS_P0_VSR_ADDR = 0x1E0, /* port0 VSR address */
+ MVS_P0_VSR_DATA = 0x1E4, /* port0 VSR data */
+ /* ports 5-7 follow after this */
+ MVS_P4_VSR_ADDR = 0x250, /* port4 VSR addr */
+ MVS_P4_VSR_DATA = 0x254, /* port4 VSR data */
+};
+
+enum pci_cfg_registers {
+ PCR_PHY_CTL = 0x40,
+ PCR_PHY_CTL2 = 0x90,
+ PCR_DEV_CTRL = 0xE8,
+ PCR_LINK_STAT = 0xF2,
+};
+
+/* SAS/SATA Vendor Specific Port Registers */
+enum sas_sata_vsp_regs {
+ VSR_PHY_STAT = 0x00, /* Phy Status */
+ VSR_PHY_MODE1 = 0x01, /* phy tx */
+ VSR_PHY_MODE2 = 0x02, /* tx scc */
+ VSR_PHY_MODE3 = 0x03, /* pll */
+ VSR_PHY_MODE4 = 0x04, /* VCO */
+ VSR_PHY_MODE5 = 0x05, /* Rx */
+ VSR_PHY_MODE6 = 0x06, /* CDR */
+ VSR_PHY_MODE7 = 0x07, /* Impedance */
+ VSR_PHY_MODE8 = 0x08, /* Voltage */
+ VSR_PHY_MODE9 = 0x09, /* Test */
+ VSR_PHY_MODE10 = 0x0A, /* Power */
+ VSR_PHY_MODE11 = 0x0B, /* Phy Mode */
+ VSR_PHY_VS0 = 0x0C, /* Vednor Specific 0 */
+ VSR_PHY_VS1 = 0x0D, /* Vednor Specific 1 */
+};
+
+enum chip_register_bits {
+ PHY_MIN_SPP_PHYS_LINK_RATE_MASK = (0xF << 8),
+ PHY_MAX_SPP_PHYS_LINK_RATE_MASK = (0xF << 12),
+ PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET = (16),
+ PHY_NEG_SPP_PHYS_LINK_RATE_MASK =
+ (0xF << PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET),
+};
+
+#define MAX_SG_ENTRY 64
+
+struct mvs_prd {
+ __le64 addr; /* 64-bit buffer address */
+ __le32 reserved;
+ __le32 len; /* 16-bit length */
+};
+
+#define SPI_CTRL_REG 0xc0
+#define SPI_CTRL_VENDOR_ENABLE (1U<<29)
+#define SPI_CTRL_SPIRDY (1U<<22)
+#define SPI_CTRL_SPISTART (1U<<20)
+
+#define SPI_CMD_REG 0xc4
+#define SPI_DATA_REG 0xc8
+
+#define SPI_CTRL_REG_64XX 0x10
+#define SPI_CMD_REG_64XX 0x14
+#define SPI_DATA_REG_64XX 0x18
+
+#endif
diff --git a/drivers/scsi/mvsas/mv_94xx.c b/drivers/scsi/mvsas/mv_94xx.c
new file mode 100644
index 000000000000..0940fae19d20
--- /dev/null
+++ b/drivers/scsi/mvsas/mv_94xx.c
@@ -0,0 +1,672 @@
+/*
+ * Marvell 88SE94xx hardware specific
+ *
+ * Copyright 2007 Red Hat, Inc.
+ * Copyright 2008 Marvell. <kewei@marvell.com>
+ *
+ * This file is licensed under GPLv2.
+ *
+ * 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
+*/
+
+#include "mv_sas.h"
+#include "mv_94xx.h"
+#include "mv_chips.h"
+
+static void mvs_94xx_detect_porttype(struct mvs_info *mvi, int i)
+{
+ u32 reg;
+ struct mvs_phy *phy = &mvi->phy[i];
+ u32 phy_status;
+
+ mvs_write_port_vsr_addr(mvi, i, VSR_PHY_MODE3);
+ reg = mvs_read_port_vsr_data(mvi, i);
+ phy_status = ((reg & 0x3f0000) >> 16) & 0xff;
+ phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA);
+ switch (phy_status) {
+ case 0x10:
+ phy->phy_type |= PORT_TYPE_SAS;
+ break;
+ case 0x1d:
+ default:
+ phy->phy_type |= PORT_TYPE_SATA;
+ break;
+ }
+}
+
+static void __devinit mvs_94xx_enable_xmt(struct mvs_info *mvi, int phy_id)
+{
+ void __iomem *regs = mvi->regs;
+ u32 tmp;
+
+ tmp = mr32(MVS_PCS);
+ tmp |= 1 << (phy_id + PCS_EN_PORT_XMT_SHIFT2);
+ mw32(MVS_PCS, tmp);
+}
+
+static void mvs_94xx_phy_reset(struct mvs_info *mvi, u32 phy_id, int hard)
+{
+ u32 tmp;
+
+ tmp = mvs_read_port_irq_stat(mvi, phy_id);
+ tmp &= ~PHYEV_RDY_CH;
+ mvs_write_port_irq_stat(mvi, phy_id, tmp);
+ if (hard) {
+ tmp = mvs_read_phy_ctl(mvi, phy_id);
+ tmp |= PHY_RST_HARD;
+ mvs_write_phy_ctl(mvi, phy_id, tmp);
+ do {
+ tmp = mvs_read_phy_ctl(mvi, phy_id);
+ } while (tmp & PHY_RST_HARD);
+ } else {
+ mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_STAT);
+ tmp = mvs_read_port_vsr_data(mvi, phy_id);
+ tmp |= PHY_RST;
+ mvs_write_port_vsr_data(mvi, phy_id, tmp);
+ }
+}
+
+static void mvs_94xx_phy_disable(struct mvs_info *mvi, u32 phy_id)
+{
+ u32 tmp;
+ mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_MODE2);
+ tmp = mvs_read_port_vsr_data(mvi, phy_id);
+ mvs_write_port_vsr_data(mvi, phy_id, tmp | 0x00800000);
+}
+
+static void mvs_94xx_phy_enable(struct mvs_info *mvi, u32 phy_id)
+{
+ mvs_write_port_vsr_addr(mvi, phy_id, 0x1B4);
+ mvs_write_port_vsr_data(mvi, phy_id, 0x8300ffc1);
+ mvs_write_port_vsr_addr(mvi, phy_id, 0x104);
+ mvs_write_port_vsr_data(mvi, phy_id, 0x00018080);
+ mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_MODE2);
+ mvs_write_port_vsr_data(mvi, phy_id, 0x00207fff);
+}
+
+static int __devinit mvs_94xx_init(struct mvs_info *mvi)
+{
+ void __iomem *regs = mvi->regs;
+ int i;
+ u32 tmp, cctl;
+
+ mvs_show_pcie_usage(mvi);
+ if (mvi->flags & MVF_FLAG_SOC) {
+ tmp = mr32(MVS_PHY_CTL);
+ tmp &= ~PCTL_PWR_OFF;
+ tmp |= PCTL_PHY_DSBL;
+ mw32(MVS_PHY_CTL, tmp);
+ }
+
+ /* Init Chip */
+ /* make sure RST is set; HBA_RST /should/ have done that for us */
+ cctl = mr32(MVS_CTL) & 0xFFFF;
+ if (cctl & CCTL_RST)
+ cctl &= ~CCTL_RST;
+ else
+ mw32_f(MVS_CTL, cctl | CCTL_RST);
+
+ if (mvi->flags & MVF_FLAG_SOC) {
+ tmp = mr32(MVS_PHY_CTL);
+ tmp &= ~PCTL_PWR_OFF;
+ tmp |= PCTL_COM_ON;
+ tmp &= ~PCTL_PHY_DSBL;
+ tmp |= PCTL_LINK_RST;
+ mw32(MVS_PHY_CTL, tmp);
+ msleep(100);
+ tmp &= ~PCTL_LINK_RST;
+ mw32(MVS_PHY_CTL, tmp);
+ msleep(100);
+ }
+
+ /* reset control */
+ mw32(MVS_PCS, 0); /* MVS_PCS */
+ mw32(MVS_STP_REG_SET_0, 0);
+ mw32(MVS_STP_REG_SET_1, 0);
+
+ /* init phys */
+ mvs_phy_hacks(mvi);
+
+ /* disable Multiplexing, enable phy implemented */
+ mw32(MVS_PORTS_IMP, 0xFF);
+
+
+ mw32(MVS_PA_VSR_ADDR, 0x00000104);
+ mw32(MVS_PA_VSR_PORT, 0x00018080);
+ mw32(MVS_PA_VSR_ADDR, VSR_PHY_MODE8);
+ mw32(MVS_PA_VSR_PORT, 0x0084ffff);
+
+ /* set LED blink when IO*/
+ mw32(MVS_PA_VSR_ADDR, 0x00000030);
+ tmp = mr32(MVS_PA_VSR_PORT);
+ tmp &= 0xFFFF00FF;
+ tmp |= 0x00003300;
+ mw32(MVS_PA_VSR_PORT, tmp);
+
+ mw32(MVS_CMD_LIST_LO, mvi->slot_dma);
+ mw32(MVS_CMD_LIST_HI, (mvi->slot_dma >> 16) >> 16);
+
+ mw32(MVS_RX_FIS_LO, mvi->rx_fis_dma);
+ mw32(MVS_RX_FIS_HI, (mvi->rx_fis_dma >> 16) >> 16);
+
+ mw32(MVS_TX_CFG, MVS_CHIP_SLOT_SZ);
+ mw32(MVS_TX_LO, mvi->tx_dma);
+ mw32(MVS_TX_HI, (mvi->tx_dma >> 16) >> 16);
+
+ mw32(MVS_RX_CFG, MVS_RX_RING_SZ);
+ mw32(MVS_RX_LO, mvi->rx_dma);
+ mw32(MVS_RX_HI, (mvi->rx_dma >> 16) >> 16);
+
+ for (i = 0; i < mvi->chip->n_phy; i++) {
+ mvs_94xx_phy_disable(mvi, i);
+ /* set phy local SAS address */
+ mvs_set_sas_addr(mvi, i, CONFIG_ID_FRAME3, CONFIG_ID_FRAME4,
+ (mvi->phy[i].dev_sas_addr));
+
+ mvs_94xx_enable_xmt(mvi, i);
+ mvs_94xx_phy_enable(mvi, i);
+
+ mvs_94xx_phy_reset(mvi, i, 1);
+ msleep(500);
+ mvs_94xx_detect_porttype(mvi, i);
+ }
+
+ if (mvi->flags & MVF_FLAG_SOC) {
+ /* set select registers */
+ writel(0x0E008000, regs + 0x000);
+ writel(0x59000008, regs + 0x004);
+ writel(0x20, regs + 0x008);
+ writel(0x20, regs + 0x00c);
+ writel(0x20, regs + 0x010);
+ writel(0x20, regs + 0x014);
+ writel(0x20, regs + 0x018);
+ writel(0x20, regs + 0x01c);
+ }
+ for (i = 0; i < mvi->chip->n_phy; i++) {
+ /* clear phy int status */
+ tmp = mvs_read_port_irq_stat(mvi, i);
+ tmp &= ~PHYEV_SIG_FIS;
+ mvs_write_port_irq_stat(mvi, i, tmp);
+
+ /* set phy int mask */
+ tmp = PHYEV_RDY_CH | PHYEV_BROAD_CH |
+ PHYEV_ID_DONE | PHYEV_DCDR_ERR | PHYEV_CRC_ERR ;
+ mvs_write_port_irq_mask(mvi, i, tmp);
+
+ msleep(100);
+ mvs_update_phyinfo(mvi, i, 1);
+ }
+
+ /* FIXME: update wide port bitmaps */
+
+ /* little endian for open address and command table, etc. */
+ /*
+ * it seems that ( from the spec ) turning on big-endian won't
+ * do us any good on big-endian machines, need further confirmation
+ */
+ cctl = mr32(MVS_CTL);
+ cctl |= CCTL_ENDIAN_CMD;
+ cctl |= CCTL_ENDIAN_DATA;
+ cctl &= ~CCTL_ENDIAN_OPEN;
+ cctl |= CCTL_ENDIAN_RSP;
+ mw32_f(MVS_CTL, cctl);
+
+ /* reset CMD queue */
+ tmp = mr32(MVS_PCS);
+ tmp |= PCS_CMD_RST;
+ mw32(MVS_PCS, tmp);
+ /* interrupt coalescing may cause missing HW interrput in some case,
+ * and the max count is 0x1ff, while our max slot is 0x200,
+ * it will make count 0.
+ */
+ tmp = 0;
+ mw32(MVS_INT_COAL, tmp);
+
+ tmp = 0x100;
+ mw32(MVS_INT_COAL_TMOUT, tmp);
+
+ /* ladies and gentlemen, start your engines */
+ mw32(MVS_TX_CFG, 0);
+ mw32(MVS_TX_CFG, MVS_CHIP_SLOT_SZ | TX_EN);
+ mw32(MVS_RX_CFG, MVS_RX_RING_SZ | RX_EN);
+ /* enable CMD/CMPL_Q/RESP mode */
+ mw32(MVS_PCS, PCS_SATA_RETRY_2 | PCS_FIS_RX_EN |
+ PCS_CMD_EN | PCS_CMD_STOP_ERR);
+
+ /* enable completion queue interrupt */
+ tmp = (CINT_PORT_MASK | CINT_DONE | CINT_MEM | CINT_SRS | CINT_CI_STOP |
+ CINT_DMA_PCIE);
+ tmp |= CINT_PHY_MASK;
+ mw32(MVS_INT_MASK, tmp);
+
+ /* Enable SRS interrupt */
+ mw32(MVS_INT_MASK_SRS_0, 0xFFFF);
+
+ return 0;
+}
+
+static int mvs_94xx_ioremap(struct mvs_info *mvi)
+{
+ if (!mvs_ioremap(mvi, 2, -1)) {
+ mvi->regs_ex = mvi->regs + 0x10200;
+ mvi->regs += 0x20000;
+ if (mvi->id == 1)
+ mvi->regs += 0x4000;
+ return 0;
+ }
+ return -1;
+}
+
+static void mvs_94xx_iounmap(struct mvs_info *mvi)
+{
+ if (mvi->regs) {
+ mvi->regs -= 0x20000;
+ if (mvi->id == 1)
+ mvi->regs -= 0x4000;
+ mvs_iounmap(mvi->regs);
+ }
+}
+
+static void mvs_94xx_interrupt_enable(struct mvs_info *mvi)
+{
+ void __iomem *regs = mvi->regs_ex;
+ u32 tmp;
+
+ tmp = mr32(MVS_GBL_CTL);
+ tmp |= (IRQ_SAS_A | IRQ_SAS_B);
+ mw32(MVS_GBL_INT_STAT, tmp);
+ writel(tmp, regs + 0x0C);
+ writel(tmp, regs + 0x10);
+ writel(tmp, regs + 0x14);
+ writel(tmp, regs + 0x18);
+ mw32(MVS_GBL_CTL, tmp);
+}
+
+static void mvs_94xx_interrupt_disable(struct mvs_info *mvi)
+{
+ void __iomem *regs = mvi->regs_ex;
+ u32 tmp;
+
+ tmp = mr32(MVS_GBL_CTL);
+
+ tmp &= ~(IRQ_SAS_A | IRQ_SAS_B);
+ mw32(MVS_GBL_INT_STAT, tmp);
+ writel(tmp, regs + 0x0C);
+ writel(tmp, regs + 0x10);
+ writel(tmp, regs + 0x14);
+ writel(tmp, regs + 0x18);
+ mw32(MVS_GBL_CTL, tmp);
+}
+
+static u32 mvs_94xx_isr_status(struct mvs_info *mvi, int irq)
+{
+ void __iomem *regs = mvi->regs_ex;
+ u32 stat = 0;
+ if (!(mvi->flags & MVF_FLAG_SOC)) {
+ stat = mr32(MVS_GBL_INT_STAT);
+
+ if (!(stat & (IRQ_SAS_A | IRQ_SAS_B)))
+ return 0;
+ }
+ return stat;
+}
+
+static irqreturn_t mvs_94xx_isr(struct mvs_info *mvi, int irq, u32 stat)
+{
+ void __iomem *regs = mvi->regs;
+
+ if (((stat & IRQ_SAS_A) && mvi->id == 0) ||
+ ((stat & IRQ_SAS_B) && mvi->id == 1)) {
+ mw32_f(MVS_INT_STAT, CINT_DONE);
+ #ifndef MVS_USE_TASKLET
+ spin_lock(&mvi->lock);
+ #endif
+ mvs_int_full(mvi);
+ #ifndef MVS_USE_TASKLET
+ spin_unlock(&mvi->lock);
+ #endif
+ }
+ return IRQ_HANDLED;
+}
+
+static void mvs_94xx_command_active(struct mvs_info *mvi, u32 slot_idx)
+{
+ u32 tmp;
+ mvs_cw32(mvi, 0x300 + (slot_idx >> 3), 1 << (slot_idx % 32));
+ do {
+ tmp = mvs_cr32(mvi, 0x300 + (slot_idx >> 3));
+ } while (tmp & 1 << (slot_idx % 32));
+}
+
+static void mvs_94xx_issue_stop(struct mvs_info *mvi, enum mvs_port_type type,
+ u32 tfs)
+{
+ void __iomem *regs = mvi->regs;
+ u32 tmp;
+
+ if (type == PORT_TYPE_SATA) {
+ tmp = mr32(MVS_INT_STAT_SRS_0) | (1U << tfs);
+ mw32(MVS_INT_STAT_SRS_0, tmp);
+ }
+ mw32(MVS_INT_STAT, CINT_CI_STOP);
+ tmp = mr32(MVS_PCS) | 0xFF00;
+ mw32(MVS_PCS, tmp);
+}
+
+static void mvs_94xx_free_reg_set(struct mvs_info *mvi, u8 *tfs)
+{
+ void __iomem *regs = mvi->regs;
+ u32 tmp;
+ u8 reg_set = *tfs;
+
+ if (*tfs == MVS_ID_NOT_MAPPED)
+ return;
+
+ mvi->sata_reg_set &= ~bit(reg_set);
+ if (reg_set < 32) {
+ w_reg_set_enable(reg_set, (u32)mvi->sata_reg_set);
+ tmp = mr32(MVS_INT_STAT_SRS_0) & (u32)mvi->sata_reg_set;
+ if (tmp)
+ mw32(MVS_INT_STAT_SRS_0, tmp);
+ } else {
+ w_reg_set_enable(reg_set, mvi->sata_reg_set);
+ tmp = mr32(MVS_INT_STAT_SRS_1) & mvi->sata_reg_set;
+ if (tmp)
+ mw32(MVS_INT_STAT_SRS_1, tmp);
+ }
+
+ *tfs = MVS_ID_NOT_MAPPED;
+
+ return;
+}
+
+static u8 mvs_94xx_assign_reg_set(struct mvs_info *mvi, u8 *tfs)
+{
+ int i;
+ void __iomem *regs = mvi->regs;
+
+ if (*tfs != MVS_ID_NOT_MAPPED)
+ return 0;
+
+ i = mv_ffc64(mvi->sata_reg_set);
+ if (i > 32) {
+ mvi->sata_reg_set |= bit(i);
+ w_reg_set_enable(i, (u32)(mvi->sata_reg_set >> 32));
+ *tfs = i;
+ return 0;
+ } else if (i >= 0) {
+ mvi->sata_reg_set |= bit(i);
+ w_reg_set_enable(i, (u32)mvi->sata_reg_set);
+ *tfs = i;
+ return 0;
+ }
+ return MVS_ID_NOT_MAPPED;
+}
+
+static void mvs_94xx_make_prd(struct scatterlist *scatter, int nr, void *prd)
+{
+ int i;
+ struct scatterlist *sg;
+ struct mvs_prd *buf_prd = prd;
+ for_each_sg(scatter, sg, nr, i) {
+ buf_prd->addr = cpu_to_le64(sg_dma_address(sg));
+ buf_prd->im_len.len = cpu_to_le32(sg_dma_len(sg));
+ buf_prd++;
+ }
+}
+
+static int mvs_94xx_oob_done(struct mvs_info *mvi, int i)
+{
+ u32 phy_st;
+ phy_st = mvs_read_phy_ctl(mvi, i);
+ if (phy_st & PHY_READY_MASK) /* phy ready */
+ return 1;
+ return 0;
+}
+
+static void mvs_94xx_get_dev_identify_frame(struct mvs_info *mvi, int port_id,
+ struct sas_identify_frame *id)
+{
+ int i;
+ u32 id_frame[7];
+
+ for (i = 0; i < 7; i++) {
+ mvs_write_port_cfg_addr(mvi, port_id,
+ CONFIG_ID_FRAME0 + i * 4);
+ id_frame[i] = mvs_read_port_cfg_data(mvi, port_id);
+ }
+ memcpy(id, id_frame, 28);
+}
+
+static void mvs_94xx_get_att_identify_frame(struct mvs_info *mvi, int port_id,
+ struct sas_identify_frame *id)
+{
+ int i;
+ u32 id_frame[7];
+
+ /* mvs_hexdump(28, (u8 *)id_frame, 0); */
+ for (i = 0; i < 7; i++) {
+ mvs_write_port_cfg_addr(mvi, port_id,
+ CONFIG_ATT_ID_FRAME0 + i * 4);
+ id_frame[i] = mvs_read_port_cfg_data(mvi, port_id);
+ mv_dprintk("94xx phy %d atta frame %d %x.\n",
+ port_id + mvi->id * mvi->chip->n_phy, i, id_frame[i]);
+ }
+ /* mvs_hexdump(28, (u8 *)id_frame, 0); */
+ memcpy(id, id_frame, 28);
+}
+
+static u32 mvs_94xx_make_dev_info(struct sas_identify_frame *id)
+{
+ u32 att_dev_info = 0;
+
+ att_dev_info |= id->dev_type;
+ if (id->stp_iport)
+ att_dev_info |= PORT_DEV_STP_INIT;
+ if (id->smp_iport)
+ att_dev_info |= PORT_DEV_SMP_INIT;
+ if (id->ssp_iport)
+ att_dev_info |= PORT_DEV_SSP_INIT;
+ if (id->stp_tport)
+ att_dev_info |= PORT_DEV_STP_TRGT;
+ if (id->smp_tport)
+ att_dev_info |= PORT_DEV_SMP_TRGT;
+ if (id->ssp_tport)
+ att_dev_info |= PORT_DEV_SSP_TRGT;
+
+ att_dev_info |= (u32)id->phy_id<<24;
+ return att_dev_info;
+}
+
+static u32 mvs_94xx_make_att_info(struct sas_identify_frame *id)
+{
+ return mvs_94xx_make_dev_info(id);
+}
+
+static void mvs_94xx_fix_phy_info(struct mvs_info *mvi, int i,
+ struct sas_identify_frame *id)
+{
+ struct mvs_phy *phy = &mvi->phy[i];
+ struct asd_sas_phy *sas_phy = &phy->sas_phy;
+ mv_dprintk("get all reg link rate is 0x%x\n", phy->phy_status);
+ sas_phy->linkrate =
+ (phy->phy_status & PHY_NEG_SPP_PHYS_LINK_RATE_MASK) >>
+ PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET;
+ sas_phy->linkrate += 0x8;
+ mv_dprintk("get link rate is %d\n", sas_phy->linkrate);
+ phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
+ phy->maximum_linkrate = SAS_LINK_RATE_6_0_GBPS;
+ mvs_94xx_get_dev_identify_frame(mvi, i, id);
+ phy->dev_info = mvs_94xx_make_dev_info(id);
+
+ if (phy->phy_type & PORT_TYPE_SAS) {
+ mvs_94xx_get_att_identify_frame(mvi, i, id);
+ phy->att_dev_info = mvs_94xx_make_att_info(id);
+ phy->att_dev_sas_addr = *(u64 *)id->sas_addr;
+ } else {
+ phy->att_dev_info = PORT_DEV_STP_TRGT | 1;
+ }
+
+}
+
+void mvs_94xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id,
+ struct sas_phy_linkrates *rates)
+{
+ /* TODO */
+}
+
+static void mvs_94xx_clear_active_cmds(struct mvs_info *mvi)
+{
+ u32 tmp;
+ void __iomem *regs = mvi->regs;
+ tmp = mr32(MVS_STP_REG_SET_0);
+ mw32(MVS_STP_REG_SET_0, 0);
+ mw32(MVS_STP_REG_SET_0, tmp);
+ tmp = mr32(MVS_STP_REG_SET_1);
+ mw32(MVS_STP_REG_SET_1, 0);
+ mw32(MVS_STP_REG_SET_1, tmp);
+}
+
+
+u32 mvs_94xx_spi_read_data(struct mvs_info *mvi)
+{
+ void __iomem *regs = mvi->regs_ex - 0x10200;
+ return mr32(SPI_RD_DATA_REG_94XX);
+}
+
+void mvs_94xx_spi_write_data(struct mvs_info *mvi, u32 data)
+{
+ void __iomem *regs = mvi->regs_ex - 0x10200;
+ mw32(SPI_RD_DATA_REG_94XX, data);
+}
+
+
+int mvs_94xx_spi_buildcmd(struct mvs_info *mvi,
+ u32 *dwCmd,
+ u8 cmd,
+ u8 read,
+ u8 length,
+ u32 addr
+ )
+{
+ void __iomem *regs = mvi->regs_ex - 0x10200;
+ u32 dwTmp;
+
+ dwTmp = ((u32)cmd << 8) | ((u32)length << 4);
+ if (read)
+ dwTmp |= SPI_CTRL_READ_94XX;
+
+ if (addr != MV_MAX_U32) {
+ mw32(SPI_ADDR_REG_94XX, (addr & 0x0003FFFFL));
+ dwTmp |= SPI_ADDR_VLD_94XX;
+ }
+
+ *dwCmd = dwTmp;
+ return 0;
+}
+
+
+int mvs_94xx_spi_issuecmd(struct mvs_info *mvi, u32 cmd)
+{
+ void __iomem *regs = mvi->regs_ex - 0x10200;
+ mw32(SPI_CTRL_REG_94XX, cmd | SPI_CTRL_SpiStart_94XX);
+
+ return 0;
+}
+
+int mvs_94xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout)
+{
+ void __iomem *regs = mvi->regs_ex - 0x10200;
+ u32 i, dwTmp;
+
+ for (i = 0; i < timeout; i++) {
+ dwTmp = mr32(SPI_CTRL_REG_94XX);
+ if (!(dwTmp & SPI_CTRL_SpiStart_94XX))
+ return 0;
+ msleep(10);
+ }
+
+ return -1;
+}
+
+#ifndef DISABLE_HOTPLUG_DMA_FIX
+void mvs_94xx_fix_dma(dma_addr_t buf_dma, int buf_len, int from, void *prd)
+{
+ int i;
+ struct mvs_prd *buf_prd = prd;
+ buf_prd += from;
+ for (i = 0; i < MAX_SG_ENTRY - from; i++) {
+ buf_prd->addr = cpu_to_le64(buf_dma);
+ buf_prd->im_len.len = cpu_to_le32(buf_len);
+ ++buf_prd;
+ }
+}
+#endif
+
+const struct mvs_dispatch mvs_94xx_dispatch = {
+ "mv94xx",
+ mvs_94xx_init,
+ NULL,
+ mvs_94xx_ioremap,
+ mvs_94xx_iounmap,
+ mvs_94xx_isr,
+ mvs_94xx_isr_status,
+ mvs_94xx_interrupt_enable,
+ mvs_94xx_interrupt_disable,
+ mvs_read_phy_ctl,
+ mvs_write_phy_ctl,
+ mvs_read_port_cfg_data,
+ mvs_write_port_cfg_data,
+ mvs_write_port_cfg_addr,
+ mvs_read_port_vsr_data,
+ mvs_write_port_vsr_data,
+ mvs_write_port_vsr_addr,
+ mvs_read_port_irq_stat,
+ mvs_write_port_irq_stat,
+ mvs_read_port_irq_mask,
+ mvs_write_port_irq_mask,
+ mvs_get_sas_addr,
+ mvs_94xx_command_active,
+ mvs_94xx_issue_stop,
+ mvs_start_delivery,
+ mvs_rx_update,
+ mvs_int_full,
+ mvs_94xx_assign_reg_set,
+ mvs_94xx_free_reg_set,
+ mvs_get_prd_size,
+ mvs_get_prd_count,
+ mvs_94xx_make_prd,
+ mvs_94xx_detect_porttype,
+ mvs_94xx_oob_done,
+ mvs_94xx_fix_phy_info,
+ NULL,
+ mvs_94xx_phy_set_link_rate,
+ mvs_hw_max_link_rate,
+ mvs_94xx_phy_disable,
+ mvs_94xx_phy_enable,
+ mvs_94xx_phy_reset,
+ NULL,
+ mvs_94xx_clear_active_cmds,
+ mvs_94xx_spi_read_data,
+ mvs_94xx_spi_write_data,
+ mvs_94xx_spi_buildcmd,
+ mvs_94xx_spi_issuecmd,
+ mvs_94xx_spi_waitdataready,
+#ifndef DISABLE_HOTPLUG_DMA_FIX
+ mvs_94xx_fix_dma,
+#endif
+};
+
diff --git a/drivers/scsi/mvsas/mv_94xx.h b/drivers/scsi/mvsas/mv_94xx.h
new file mode 100644
index 000000000000..23ed9b164669
--- /dev/null
+++ b/drivers/scsi/mvsas/mv_94xx.h
@@ -0,0 +1,222 @@
+/*
+ * Marvell 88SE94xx hardware specific head file
+ *
+ * Copyright 2007 Red Hat, Inc.
+ * Copyright 2008 Marvell. <kewei@marvell.com>
+ *
+ * This file is licensed under GPLv2.
+ *
+ * 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
+*/
+
+#ifndef _MVS94XX_REG_H_
+#define _MVS94XX_REG_H_
+
+#include <linux/types.h>
+
+#define MAX_LINK_RATE SAS_LINK_RATE_6_0_GBPS
+
+enum hw_registers {
+ MVS_GBL_CTL = 0x04, /* global control */
+ MVS_GBL_INT_STAT = 0x00, /* global irq status */
+ MVS_GBL_PI = 0x0C, /* ports implemented bitmask */
+
+ MVS_PHY_CTL = 0x40, /* SOC PHY Control */
+ MVS_PORTS_IMP = 0x9C, /* SOC Port Implemented */
+
+ MVS_GBL_PORT_TYPE = 0xa0, /* port type */
+
+ MVS_CTL = 0x100, /* SAS/SATA port configuration */
+ MVS_PCS = 0x104, /* SAS/SATA port control/status */
+ MVS_CMD_LIST_LO = 0x108, /* cmd list addr */
+ MVS_CMD_LIST_HI = 0x10C,
+ MVS_RX_FIS_LO = 0x110, /* RX FIS list addr */
+ MVS_RX_FIS_HI = 0x114,
+ MVS_STP_REG_SET_0 = 0x118, /* STP/SATA Register Set Enable */
+ MVS_STP_REG_SET_1 = 0x11C,
+ MVS_TX_CFG = 0x120, /* TX configuration */
+ MVS_TX_LO = 0x124, /* TX (delivery) ring addr */
+ MVS_TX_HI = 0x128,
+
+ MVS_TX_PROD_IDX = 0x12C, /* TX producer pointer */
+ MVS_TX_CONS_IDX = 0x130, /* TX consumer pointer (RO) */
+ MVS_RX_CFG = 0x134, /* RX configuration */
+ MVS_RX_LO = 0x138, /* RX (completion) ring addr */
+ MVS_RX_HI = 0x13C,
+ MVS_RX_CONS_IDX = 0x140, /* RX consumer pointer (RO) */
+
+ MVS_INT_COAL = 0x148, /* Int coalescing config */
+ MVS_INT_COAL_TMOUT = 0x14C, /* Int coalescing timeout */
+ MVS_INT_STAT = 0x150, /* Central int status */
+ MVS_INT_MASK = 0x154, /* Central int enable */
+ MVS_INT_STAT_SRS_0 = 0x158, /* SATA register set status */
+ MVS_INT_MASK_SRS_0 = 0x15C,
+ MVS_INT_STAT_SRS_1 = 0x160,
+ MVS_INT_MASK_SRS_1 = 0x164,
+ MVS_NON_NCQ_ERR_0 = 0x168, /* SRS Non-specific NCQ Error */
+ MVS_NON_NCQ_ERR_1 = 0x16C,
+ MVS_CMD_ADDR = 0x170, /* Command register port (addr) */
+ MVS_CMD_DATA = 0x174, /* Command register port (data) */
+ MVS_MEM_PARITY_ERR = 0x178, /* Memory parity error */
+
+ /* ports 1-3 follow after this */
+ MVS_P0_INT_STAT = 0x180, /* port0 interrupt status */
+ MVS_P0_INT_MASK = 0x184, /* port0 interrupt mask */
+ /* ports 5-7 follow after this */
+ MVS_P4_INT_STAT = 0x1A0, /* Port4 interrupt status */
+ MVS_P4_INT_MASK = 0x1A4, /* Port4 interrupt enable mask */
+
+ /* ports 1-3 follow after this */
+ MVS_P0_SER_CTLSTAT = 0x1D0, /* port0 serial control/status */
+ /* ports 5-7 follow after this */
+ MVS_P4_SER_CTLSTAT = 0x1E0, /* port4 serial control/status */
+
+ /* ports 1-3 follow after this */
+ MVS_P0_CFG_ADDR = 0x200, /* port0 phy register address */
+ MVS_P0_CFG_DATA = 0x204, /* port0 phy register data */
+ /* ports 5-7 follow after this */
+ MVS_P4_CFG_ADDR = 0x220, /* Port4 config address */
+ MVS_P4_CFG_DATA = 0x224, /* Port4 config data */
+
+ /* phys 1-3 follow after this */
+ MVS_P0_VSR_ADDR = 0x250, /* phy0 VSR address */
+ MVS_P0_VSR_DATA = 0x254, /* phy0 VSR data */
+ /* phys 1-3 follow after this */
+ /* multiplexing */
+ MVS_P4_VSR_ADDR = 0x250, /* phy4 VSR address */
+ MVS_P4_VSR_DATA = 0x254, /* phy4 VSR data */
+ MVS_PA_VSR_ADDR = 0x290, /* All port VSR addr */
+ MVS_PA_VSR_PORT = 0x294, /* All port VSR data */
+};
+
+enum pci_cfg_registers {
+ PCR_PHY_CTL = 0x40,
+ PCR_PHY_CTL2 = 0x90,
+ PCR_DEV_CTRL = 0x78,
+ PCR_LINK_STAT = 0x82,
+};
+
+/* SAS/SATA Vendor Specific Port Registers */
+enum sas_sata_vsp_regs {
+ VSR_PHY_STAT = 0x00 * 4, /* Phy Status */
+ VSR_PHY_MODE1 = 0x01 * 4, /* phy tx */
+ VSR_PHY_MODE2 = 0x02 * 4, /* tx scc */
+ VSR_PHY_MODE3 = 0x03 * 4, /* pll */
+ VSR_PHY_MODE4 = 0x04 * 4, /* VCO */
+ VSR_PHY_MODE5 = 0x05 * 4, /* Rx */
+ VSR_PHY_MODE6 = 0x06 * 4, /* CDR */
+ VSR_PHY_MODE7 = 0x07 * 4, /* Impedance */
+ VSR_PHY_MODE8 = 0x08 * 4, /* Voltage */
+ VSR_PHY_MODE9 = 0x09 * 4, /* Test */
+ VSR_PHY_MODE10 = 0x0A * 4, /* Power */
+ VSR_PHY_MODE11 = 0x0B * 4, /* Phy Mode */
+ VSR_PHY_VS0 = 0x0C * 4, /* Vednor Specific 0 */
+ VSR_PHY_VS1 = 0x0D * 4, /* Vednor Specific 1 */
+};
+
+enum chip_register_bits {
+ PHY_MIN_SPP_PHYS_LINK_RATE_MASK = (0x7 << 8),
+ PHY_MAX_SPP_PHYS_LINK_RATE_MASK = (0x7 << 8),
+ PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET = (12),
+ PHY_NEG_SPP_PHYS_LINK_RATE_MASK =
+ (0x3 << PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET),
+};
+
+enum pci_interrupt_cause {
+ /* MAIN_IRQ_CAUSE (R10200) Bits*/
+ IRQ_COM_IN_I2O_IOP0 = (1 << 0),
+ IRQ_COM_IN_I2O_IOP1 = (1 << 1),
+ IRQ_COM_IN_I2O_IOP2 = (1 << 2),
+ IRQ_COM_IN_I2O_IOP3 = (1 << 3),
+ IRQ_COM_OUT_I2O_HOS0 = (1 << 4),
+ IRQ_COM_OUT_I2O_HOS1 = (1 << 5),
+ IRQ_COM_OUT_I2O_HOS2 = (1 << 6),
+ IRQ_COM_OUT_I2O_HOS3 = (1 << 7),
+ IRQ_PCIF_TO_CPU_DRBL0 = (1 << 8),
+ IRQ_PCIF_TO_CPU_DRBL1 = (1 << 9),
+ IRQ_PCIF_TO_CPU_DRBL2 = (1 << 10),
+ IRQ_PCIF_TO_CPU_DRBL3 = (1 << 11),
+ IRQ_PCIF_DRBL0 = (1 << 12),
+ IRQ_PCIF_DRBL1 = (1 << 13),
+ IRQ_PCIF_DRBL2 = (1 << 14),
+ IRQ_PCIF_DRBL3 = (1 << 15),
+ IRQ_XOR_A = (1 << 16),
+ IRQ_XOR_B = (1 << 17),
+ IRQ_SAS_A = (1 << 18),
+ IRQ_SAS_B = (1 << 19),
+ IRQ_CPU_CNTRL = (1 << 20),
+ IRQ_GPIO = (1 << 21),
+ IRQ_UART = (1 << 22),
+ IRQ_SPI = (1 << 23),
+ IRQ_I2C = (1 << 24),
+ IRQ_SGPIO = (1 << 25),
+ IRQ_COM_ERR = (1 << 29),
+ IRQ_I2O_ERR = (1 << 30),
+ IRQ_PCIE_ERR = (1 << 31),
+};
+
+#define MAX_SG_ENTRY 255
+
+struct mvs_prd_imt {
+ __le32 len:22;
+ u8 _r_a:2;
+ u8 misc_ctl:4;
+ u8 inter_sel:4;
+};
+
+struct mvs_prd {
+ /* 64-bit buffer address */
+ __le64 addr;
+ /* 22-bit length */
+ struct mvs_prd_imt im_len;
+} __attribute__ ((packed));
+
+#define SPI_CTRL_REG_94XX 0xc800
+#define SPI_ADDR_REG_94XX 0xc804
+#define SPI_WR_DATA_REG_94XX 0xc808
+#define SPI_RD_DATA_REG_94XX 0xc80c
+#define SPI_CTRL_READ_94XX (1U << 2)
+#define SPI_ADDR_VLD_94XX (1U << 1)
+#define SPI_CTRL_SpiStart_94XX (1U << 0)
+
+#define mv_ffc(x) ffz(x)
+
+static inline int
+mv_ffc64(u64 v)
+{
+ int i;
+ i = mv_ffc((u32)v);
+ if (i >= 0)
+ return i;
+ i = mv_ffc((u32)(v>>32));
+
+ if (i != 0)
+ return 32 + i;
+
+ return -1;
+}
+
+#define r_reg_set_enable(i) \
+ (((i) > 31) ? mr32(MVS_STP_REG_SET_1) : \
+ mr32(MVS_STP_REG_SET_0))
+
+#define w_reg_set_enable(i, tmp) \
+ (((i) > 31) ? mw32(MVS_STP_REG_SET_1, tmp) : \
+ mw32(MVS_STP_REG_SET_0, tmp))
+
+extern const struct mvs_dispatch mvs_94xx_dispatch;
+#endif
+
diff --git a/drivers/scsi/mvsas/mv_chips.h b/drivers/scsi/mvsas/mv_chips.h
new file mode 100644
index 000000000000..a67e1c4172f9
--- /dev/null
+++ b/drivers/scsi/mvsas/mv_chips.h
@@ -0,0 +1,280 @@
+/*
+ * Marvell 88SE64xx/88SE94xx register IO interface
+ *
+ * Copyright 2007 Red Hat, Inc.
+ * Copyright 2008 Marvell. <kewei@marvell.com>
+ *
+ * This file is licensed under GPLv2.
+ *
+ * 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
+*/
+
+
+#ifndef _MV_CHIPS_H_
+#define _MV_CHIPS_H_
+
+#define mr32(reg) readl(regs + reg)
+#define mw32(reg, val) writel((val), regs + reg)
+#define mw32_f(reg, val) do { \
+ mw32(reg, val); \
+ mr32(reg); \
+ } while (0)
+
+#define iow32(reg, val) outl(val, (unsigned long)(regs + reg))
+#define ior32(reg) inl((unsigned long)(regs + reg))
+#define iow16(reg, val) outw((unsigned long)(val, regs + reg))
+#define ior16(reg) inw((unsigned long)(regs + reg))
+#define iow8(reg, val) outb((unsigned long)(val, regs + reg))
+#define ior8(reg) inb((unsigned long)(regs + reg))
+
+static inline u32 mvs_cr32(struct mvs_info *mvi, u32 addr)
+{
+ void __iomem *regs = mvi->regs;
+ mw32(MVS_CMD_ADDR, addr);
+ return mr32(MVS_CMD_DATA);
+}
+
+static inline void mvs_cw32(struct mvs_info *mvi, u32 addr, u32 val)
+{
+ void __iomem *regs = mvi->regs;
+ mw32(MVS_CMD_ADDR, addr);
+ mw32(MVS_CMD_DATA, val);
+}
+
+static inline u32 mvs_read_phy_ctl(struct mvs_info *mvi, u32 port)
+{
+ void __iomem *regs = mvi->regs;
+ return (port < 4) ? mr32(MVS_P0_SER_CTLSTAT + port * 4) :
+ mr32(MVS_P4_SER_CTLSTAT + (port - 4) * 4);
+}
+
+static inline void mvs_write_phy_ctl(struct mvs_info *mvi, u32 port, u32 val)
+{
+ void __iomem *regs = mvi->regs;
+ if (port < 4)
+ mw32(MVS_P0_SER_CTLSTAT + port * 4, val);
+ else
+ mw32(MVS_P4_SER_CTLSTAT + (port - 4) * 4, val);
+}
+
+static inline u32 mvs_read_port(struct mvs_info *mvi, u32 off,
+ u32 off2, u32 port)
+{
+ void __iomem *regs = mvi->regs + off;
+ void __iomem *regs2 = mvi->regs + off2;
+ return (port < 4) ? readl(regs + port * 8) :
+ readl(regs2 + (port - 4) * 8);
+}
+
+static inline void mvs_write_port(struct mvs_info *mvi, u32 off, u32 off2,
+ u32 port, u32 val)
+{
+ void __iomem *regs = mvi->regs + off;
+ void __iomem *regs2 = mvi->regs + off2;
+ if (port < 4)
+ writel(val, regs + port * 8);
+ else
+ writel(val, regs2 + (port - 4) * 8);
+}
+
+static inline u32 mvs_read_port_cfg_data(struct mvs_info *mvi, u32 port)
+{
+ return mvs_read_port(mvi, MVS_P0_CFG_DATA,
+ MVS_P4_CFG_DATA, port);
+}
+
+static inline void mvs_write_port_cfg_data(struct mvs_info *mvi,
+ u32 port, u32 val)
+{
+ mvs_write_port(mvi, MVS_P0_CFG_DATA,
+ MVS_P4_CFG_DATA, port, val);
+}
+
+static inline void mvs_write_port_cfg_addr(struct mvs_info *mvi,
+ u32 port, u32 addr)
+{
+ mvs_write_port(mvi, MVS_P0_CFG_ADDR,
+ MVS_P4_CFG_ADDR, port, addr);
+ mdelay(10);
+}
+
+static inline u32 mvs_read_port_vsr_data(struct mvs_info *mvi, u32 port)
+{
+ return mvs_read_port(mvi, MVS_P0_VSR_DATA,
+ MVS_P4_VSR_DATA, port);
+}
+
+static inline void mvs_write_port_vsr_data(struct mvs_info *mvi,
+ u32 port, u32 val)
+{
+ mvs_write_port(mvi, MVS_P0_VSR_DATA,
+ MVS_P4_VSR_DATA, port, val);
+}
+
+static inline void mvs_write_port_vsr_addr(struct mvs_info *mvi,
+ u32 port, u32 addr)
+{
+ mvs_write_port(mvi, MVS_P0_VSR_ADDR,
+ MVS_P4_VSR_ADDR, port, addr);
+ mdelay(10);
+}
+
+static inline u32 mvs_read_port_irq_stat(struct mvs_info *mvi, u32 port)
+{
+ return mvs_read_port(mvi, MVS_P0_INT_STAT,
+ MVS_P4_INT_STAT, port);
+}
+
+static inline void mvs_write_port_irq_stat(struct mvs_info *mvi,
+ u32 port, u32 val)
+{
+ mvs_write_port(mvi, MVS_P0_INT_STAT,
+ MVS_P4_INT_STAT, port, val);
+}
+
+static inline u32 mvs_read_port_irq_mask(struct mvs_info *mvi, u32 port)
+{
+ return mvs_read_port(mvi, MVS_P0_INT_MASK,
+ MVS_P4_INT_MASK, port);
+
+}
+
+static inline void mvs_write_port_irq_mask(struct mvs_info *mvi,
+ u32 port, u32 val)
+{
+ mvs_write_port(mvi, MVS_P0_INT_MASK,
+ MVS_P4_INT_MASK, port, val);
+}
+
+static inline void __devinit mvs_phy_hacks(struct mvs_info *mvi)
+{
+ u32 tmp;
+
+ /* workaround for SATA R-ERR, to ignore phy glitch */
+ tmp = mvs_cr32(mvi, CMD_PHY_TIMER);
+ tmp &= ~(1 << 9);
+ tmp |= (1 << 10);
+ mvs_cw32(mvi, CMD_PHY_TIMER, tmp);
+
+ /* enable retry 127 times */
+ mvs_cw32(mvi, CMD_SAS_CTL1, 0x7f7f);
+
+ /* extend open frame timeout to max */
+ tmp = mvs_cr32(mvi, CMD_SAS_CTL0);
+ tmp &= ~0xffff;
+ tmp |= 0x3fff;
+ mvs_cw32(mvi, CMD_SAS_CTL0, tmp);
+
+ /* workaround for WDTIMEOUT , set to 550 ms */
+ mvs_cw32(mvi, CMD_WD_TIMER, 0x7a0000);
+
+ /* not to halt for different port op during wideport link change */
+ mvs_cw32(mvi, CMD_APP_ERR_CONFIG, 0xffefbf7d);
+
+ /* workaround for Seagate disk not-found OOB sequence, recv
+ * COMINIT before sending out COMWAKE */
+ tmp = mvs_cr32(mvi, CMD_PHY_MODE_21);
+ tmp &= 0x0000ffff;
+ tmp |= 0x00fa0000;
+ mvs_cw32(mvi, CMD_PHY_MODE_21, tmp);
+
+ tmp = mvs_cr32(mvi, CMD_PHY_TIMER);
+ tmp &= 0x1fffffff;
+ tmp |= (2U << 29); /* 8 ms retry */
+ mvs_cw32(mvi, CMD_PHY_TIMER, tmp);
+}
+
+static inline void mvs_int_sata(struct mvs_info *mvi)
+{
+ u32 tmp;
+ void __iomem *regs = mvi->regs;
+ tmp = mr32(MVS_INT_STAT_SRS_0);
+ if (tmp)
+ mw32(MVS_INT_STAT_SRS_0, tmp);
+ MVS_CHIP_DISP->clear_active_cmds(mvi);
+}
+
+static inline void mvs_int_full(struct mvs_info *mvi)
+{
+ void __iomem *regs = mvi->regs;
+ u32 tmp, stat;
+ int i;
+
+ stat = mr32(MVS_INT_STAT);
+ mvs_int_rx(mvi, false);
+
+ for (i = 0; i < mvi->chip->n_phy; i++) {
+ tmp = (stat >> i) & (CINT_PORT | CINT_PORT_STOPPED);
+ if (tmp)
+ mvs_int_port(mvi, i, tmp);
+ }
+
+ if (stat & CINT_SRS)
+ mvs_int_sata(mvi);
+
+ mw32(MVS_INT_STAT, stat);
+}
+
+static inline void mvs_start_delivery(struct mvs_info *mvi, u32 tx)
+{
+ void __iomem *regs = mvi->regs;
+ mw32(MVS_TX_PROD_IDX, tx);
+}
+
+static inline u32 mvs_rx_update(struct mvs_info *mvi)
+{
+ void __iomem *regs = mvi->regs;
+ return mr32(MVS_RX_CONS_IDX);
+}
+
+static inline u32 mvs_get_prd_size(void)
+{
+ return sizeof(struct mvs_prd);
+}
+
+static inline u32 mvs_get_prd_count(void)
+{
+ return MAX_SG_ENTRY;
+}
+
+static inline void mvs_show_pcie_usage(struct mvs_info *mvi)
+{
+ u16 link_stat, link_spd;
+ const char *spd[] = {
+ "UnKnown",
+ "2.5",
+ "5.0",
+ };
+ if (mvi->flags & MVF_FLAG_SOC || mvi->id > 0)
+ return;
+
+ pci_read_config_word(mvi->pdev, PCR_LINK_STAT, &link_stat);
+ link_spd = (link_stat & PLS_LINK_SPD) >> PLS_LINK_SPD_OFFS;
+ if (link_spd >= 3)
+ link_spd = 0;
+ dev_printk(KERN_INFO, mvi->dev,
+ "mvsas: PCI-E x%u, Bandwidth Usage: %s Gbps\n",
+ (link_stat & PLS_NEG_LINK_WD) >> PLS_NEG_LINK_WD_OFFS,
+ spd[link_spd]);
+}
+
+static inline u32 mvs_hw_max_link_rate(void)
+{
+ return MAX_LINK_RATE;
+}
+
+#endif /* _MV_CHIPS_H_ */
+
diff --git a/drivers/scsi/mvsas/mv_defs.h b/drivers/scsi/mvsas/mv_defs.h
new file mode 100644
index 000000000000..f8cb9defb961
--- /dev/null
+++ b/drivers/scsi/mvsas/mv_defs.h
@@ -0,0 +1,502 @@
+/*
+ * Marvell 88SE64xx/88SE94xx const head file
+ *
+ * Copyright 2007 Red Hat, Inc.
+ * Copyright 2008 Marvell. <kewei@marvell.com>
+ *
+ * This file is licensed under GPLv2.
+ *
+ * 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
+*/
+
+#ifndef _MV_DEFS_H_
+#define _MV_DEFS_H_
+
+
+enum chip_flavors {
+ chip_6320,
+ chip_6440,
+ chip_6485,
+ chip_9480,
+ chip_9180,
+};
+
+/* driver compile-time configuration */
+enum driver_configuration {
+ MVS_SLOTS = 512, /* command slots */
+ MVS_TX_RING_SZ = 1024, /* TX ring size (12-bit) */
+ MVS_RX_RING_SZ = 1024, /* RX ring size (12-bit) */
+ /* software requires power-of-2
+ ring size */
+ MVS_SOC_SLOTS = 64,
+ MVS_SOC_TX_RING_SZ = MVS_SOC_SLOTS * 2,
+ MVS_SOC_RX_RING_SZ = MVS_SOC_SLOTS * 2,
+
+ MVS_SLOT_BUF_SZ = 8192, /* cmd tbl + IU + status + PRD */
+ MVS_SSP_CMD_SZ = 64, /* SSP command table buffer size */
+ MVS_ATA_CMD_SZ = 96, /* SATA command table buffer size */
+ MVS_OAF_SZ = 64, /* Open address frame buffer size */
+ MVS_QUEUE_SIZE = 32, /* Support Queue depth */
+ MVS_CAN_QUEUE = MVS_SLOTS - 2, /* SCSI Queue depth */
+ MVS_SOC_CAN_QUEUE = MVS_SOC_SLOTS - 2,
+};
+
+/* unchangeable hardware details */
+enum hardware_details {
+ MVS_MAX_PHYS = 8, /* max. possible phys */
+ MVS_MAX_PORTS = 8, /* max. possible ports */
+ MVS_SOC_PHYS = 4, /* soc phys */
+ MVS_SOC_PORTS = 4, /* soc phys */
+ MVS_MAX_DEVICES = 1024, /* max supported device */
+};
+
+/* peripheral registers (BAR2) */
+enum peripheral_registers {
+ SPI_CTL = 0x10, /* EEPROM control */
+ SPI_CMD = 0x14, /* EEPROM command */
+ SPI_DATA = 0x18, /* EEPROM data */
+};
+
+enum peripheral_register_bits {
+ TWSI_RDY = (1U << 7), /* EEPROM interface ready */
+ TWSI_RD = (1U << 4), /* EEPROM read access */
+
+ SPI_ADDR_MASK = 0x3ffff, /* bits 17:0 */
+};
+
+enum hw_register_bits {
+ /* MVS_GBL_CTL */
+ INT_EN = (1U << 1), /* Global int enable */
+ HBA_RST = (1U << 0), /* HBA reset */
+
+ /* MVS_GBL_INT_STAT */
+ INT_XOR = (1U << 4), /* XOR engine event */
+ INT_SAS_SATA = (1U << 0), /* SAS/SATA event */
+
+ /* MVS_GBL_PORT_TYPE */ /* shl for ports 1-3 */
+ SATA_TARGET = (1U << 16), /* port0 SATA target enable */
+ MODE_AUTO_DET_PORT7 = (1U << 15), /* port0 SAS/SATA autodetect */
+ MODE_AUTO_DET_PORT6 = (1U << 14),
+ MODE_AUTO_DET_PORT5 = (1U << 13),
+ MODE_AUTO_DET_PORT4 = (1U << 12),
+ MODE_AUTO_DET_PORT3 = (1U << 11),
+ MODE_AUTO_DET_PORT2 = (1U << 10),
+ MODE_AUTO_DET_PORT1 = (1U << 9),
+ MODE_AUTO_DET_PORT0 = (1U << 8),
+ MODE_AUTO_DET_EN = MODE_AUTO_DET_PORT0 | MODE_AUTO_DET_PORT1 |
+ MODE_AUTO_DET_PORT2 | MODE_AUTO_DET_PORT3 |
+ MODE_AUTO_DET_PORT4 | MODE_AUTO_DET_PORT5 |
+ MODE_AUTO_DET_PORT6 | MODE_AUTO_DET_PORT7,
+ MODE_SAS_PORT7_MASK = (1U << 7), /* port0 SAS(1), SATA(0) mode */
+ MODE_SAS_PORT6_MASK = (1U << 6),
+ MODE_SAS_PORT5_MASK = (1U << 5),
+ MODE_SAS_PORT4_MASK = (1U << 4),
+ MODE_SAS_PORT3_MASK = (1U << 3),
+ MODE_SAS_PORT2_MASK = (1U << 2),
+ MODE_SAS_PORT1_MASK = (1U << 1),
+ MODE_SAS_PORT0_MASK = (1U << 0),
+ MODE_SAS_SATA = MODE_SAS_PORT0_MASK | MODE_SAS_PORT1_MASK |
+ MODE_SAS_PORT2_MASK | MODE_SAS_PORT3_MASK |
+ MODE_SAS_PORT4_MASK | MODE_SAS_PORT5_MASK |
+ MODE_SAS_PORT6_MASK | MODE_SAS_PORT7_MASK,
+
+ /* SAS_MODE value may be
+ * dictated (in hw) by values
+ * of SATA_TARGET & AUTO_DET
+ */
+
+ /* MVS_TX_CFG */
+ TX_EN = (1U << 16), /* Enable TX */
+ TX_RING_SZ_MASK = 0xfff, /* TX ring size, bits 11:0 */
+
+ /* MVS_RX_CFG */
+ RX_EN = (1U << 16), /* Enable RX */
+ RX_RING_SZ_MASK = 0xfff, /* RX ring size, bits 11:0 */
+
+ /* MVS_INT_COAL */
+ COAL_EN = (1U << 16), /* Enable int coalescing */
+
+ /* MVS_INT_STAT, MVS_INT_MASK */
+ CINT_I2C = (1U << 31), /* I2C event */
+ CINT_SW0 = (1U << 30), /* software event 0 */
+ CINT_SW1 = (1U << 29), /* software event 1 */
+ CINT_PRD_BC = (1U << 28), /* PRD BC err for read cmd */
+ CINT_DMA_PCIE = (1U << 27), /* DMA to PCIE timeout */
+ CINT_MEM = (1U << 26), /* int mem parity err */
+ CINT_I2C_SLAVE = (1U << 25), /* slave I2C event */
+ CINT_SRS = (1U << 3), /* SRS event */
+ CINT_CI_STOP = (1U << 1), /* cmd issue stopped */
+ CINT_DONE = (1U << 0), /* cmd completion */
+
+ /* shl for ports 1-3 */
+ CINT_PORT_STOPPED = (1U << 16), /* port0 stopped */
+ CINT_PORT = (1U << 8), /* port0 event */
+ CINT_PORT_MASK_OFFSET = 8,
+ CINT_PORT_MASK = (0xFF << CINT_PORT_MASK_OFFSET),
+ CINT_PHY_MASK_OFFSET = 4,
+ CINT_PHY_MASK = (0x0F << CINT_PHY_MASK_OFFSET),
+
+ /* TX (delivery) ring bits */
+ TXQ_CMD_SHIFT = 29,
+ TXQ_CMD_SSP = 1, /* SSP protocol */
+ TXQ_CMD_SMP = 2, /* SMP protocol */
+ TXQ_CMD_STP = 3, /* STP/SATA protocol */
+ TXQ_CMD_SSP_FREE_LIST = 4, /* add to SSP targ free list */
+ TXQ_CMD_SLOT_RESET = 7, /* reset command slot */
+ TXQ_MODE_I = (1U << 28), /* mode: 0=target,1=initiator */
+ TXQ_MODE_TARGET = 0,
+ TXQ_MODE_INITIATOR = 1,
+ TXQ_PRIO_HI = (1U << 27), /* priority: 0=normal, 1=high */
+ TXQ_PRI_NORMAL = 0,
+ TXQ_PRI_HIGH = 1,
+ TXQ_SRS_SHIFT = 20, /* SATA register set */
+ TXQ_SRS_MASK = 0x7f,
+ TXQ_PHY_SHIFT = 12, /* PHY bitmap */
+ TXQ_PHY_MASK = 0xff,
+ TXQ_SLOT_MASK = 0xfff, /* slot number */
+
+ /* RX (completion) ring bits */
+ RXQ_GOOD = (1U << 23), /* Response good */
+ RXQ_SLOT_RESET = (1U << 21), /* Slot reset complete */
+ RXQ_CMD_RX = (1U << 20), /* target cmd received */
+ RXQ_ATTN = (1U << 19), /* attention */
+ RXQ_RSP = (1U << 18), /* response frame xfer'd */
+ RXQ_ERR = (1U << 17), /* err info rec xfer'd */
+ RXQ_DONE = (1U << 16), /* cmd complete */
+ RXQ_SLOT_MASK = 0xfff, /* slot number */
+
+ /* mvs_cmd_hdr bits */
+ MCH_PRD_LEN_SHIFT = 16, /* 16-bit PRD table len */
+ MCH_SSP_FR_TYPE_SHIFT = 13, /* SSP frame type */
+
+ /* SSP initiator only */
+ MCH_SSP_FR_CMD = 0x0, /* COMMAND frame */
+
+ /* SSP initiator or target */
+ MCH_SSP_FR_TASK = 0x1, /* TASK frame */
+
+ /* SSP target only */
+ MCH_SSP_FR_XFER_RDY = 0x4, /* XFER_RDY frame */
+ MCH_SSP_FR_RESP = 0x5, /* RESPONSE frame */
+ MCH_SSP_FR_READ = 0x6, /* Read DATA frame(s) */
+ MCH_SSP_FR_READ_RESP = 0x7, /* ditto, plus RESPONSE */
+
+ MCH_SSP_MODE_PASSTHRU = 1,
+ MCH_SSP_MODE_NORMAL = 0,
+ MCH_PASSTHRU = (1U << 12), /* pass-through (SSP) */
+ MCH_FBURST = (1U << 11), /* first burst (SSP) */
+ MCH_CHK_LEN = (1U << 10), /* chk xfer len (SSP) */
+ MCH_RETRY = (1U << 9), /* tport layer retry (SSP) */
+ MCH_PROTECTION = (1U << 8), /* protection info rec (SSP) */
+ MCH_RESET = (1U << 7), /* Reset (STP/SATA) */
+ MCH_FPDMA = (1U << 6), /* First party DMA (STP/SATA) */
+ MCH_ATAPI = (1U << 5), /* ATAPI (STP/SATA) */
+ MCH_BIST = (1U << 4), /* BIST activate (STP/SATA) */
+ MCH_PMP_MASK = 0xf, /* PMP from cmd FIS (STP/SATA)*/
+
+ CCTL_RST = (1U << 5), /* port logic reset */
+
+ /* 0(LSB first), 1(MSB first) */
+ CCTL_ENDIAN_DATA = (1U << 3), /* PRD data */
+ CCTL_ENDIAN_RSP = (1U << 2), /* response frame */
+ CCTL_ENDIAN_OPEN = (1U << 1), /* open address frame */
+ CCTL_ENDIAN_CMD = (1U << 0), /* command table */
+
+ /* MVS_Px_SER_CTLSTAT (per-phy control) */
+ PHY_SSP_RST = (1U << 3), /* reset SSP link layer */
+ PHY_BCAST_CHG = (1U << 2), /* broadcast(change) notif */
+ PHY_RST_HARD = (1U << 1), /* hard reset + phy reset */
+ PHY_RST = (1U << 0), /* phy reset */
+ PHY_READY_MASK = (1U << 20),
+
+ /* MVS_Px_INT_STAT, MVS_Px_INT_MASK (per-phy events) */
+ PHYEV_DEC_ERR = (1U << 24), /* Phy Decoding Error */
+ PHYEV_DCDR_ERR = (1U << 23), /* STP Deocder Error */
+ PHYEV_CRC_ERR = (1U << 22), /* STP CRC Error */
+ PHYEV_UNASSOC_FIS = (1U << 19), /* unassociated FIS rx'd */
+ PHYEV_AN = (1U << 18), /* SATA async notification */
+ PHYEV_BIST_ACT = (1U << 17), /* BIST activate FIS */
+ PHYEV_SIG_FIS = (1U << 16), /* signature FIS */
+ PHYEV_POOF = (1U << 12), /* phy ready from 1 -> 0 */
+ PHYEV_IU_BIG = (1U << 11), /* IU too long err */
+ PHYEV_IU_SMALL = (1U << 10), /* IU too short err */
+ PHYEV_UNK_TAG = (1U << 9), /* unknown tag */
+ PHYEV_BROAD_CH = (1U << 8), /* broadcast(CHANGE) */
+ PHYEV_COMWAKE = (1U << 7), /* COMWAKE rx'd */
+ PHYEV_PORT_SEL = (1U << 6), /* port selector present */
+ PHYEV_HARD_RST = (1U << 5), /* hard reset rx'd */
+ PHYEV_ID_TMOUT = (1U << 4), /* identify timeout */
+ PHYEV_ID_FAIL = (1U << 3), /* identify failed */
+ PHYEV_ID_DONE = (1U << 2), /* identify done */
+ PHYEV_HARD_RST_DONE = (1U << 1), /* hard reset done */
+ PHYEV_RDY_CH = (1U << 0), /* phy ready changed state */
+
+ /* MVS_PCS */
+ PCS_EN_SATA_REG_SHIFT = (16), /* Enable SATA Register Set */
+ PCS_EN_PORT_XMT_SHIFT = (12), /* Enable Port Transmit */
+ PCS_EN_PORT_XMT_SHIFT2 = (8), /* For 6485 */
+ PCS_SATA_RETRY = (1U << 8), /* retry ctl FIS on R_ERR */
+ PCS_RSP_RX_EN = (1U << 7), /* raw response rx */
+ PCS_SATA_RETRY_2 = (1U << 6), /* For 9180 */
+ PCS_SELF_CLEAR = (1U << 5), /* self-clearing int mode */
+ PCS_FIS_RX_EN = (1U << 4), /* FIS rx enable */
+ PCS_CMD_STOP_ERR = (1U << 3), /* cmd stop-on-err enable */
+ PCS_CMD_RST = (1U << 1), /* reset cmd issue */
+ PCS_CMD_EN = (1U << 0), /* enable cmd issue */
+
+ /* Port n Attached Device Info */
+ PORT_DEV_SSP_TRGT = (1U << 19),
+ PORT_DEV_SMP_TRGT = (1U << 18),
+ PORT_DEV_STP_TRGT = (1U << 17),
+ PORT_DEV_SSP_INIT = (1U << 11),
+ PORT_DEV_SMP_INIT = (1U << 10),
+ PORT_DEV_STP_INIT = (1U << 9),
+ PORT_PHY_ID_MASK = (0xFFU << 24),
+ PORT_SSP_TRGT_MASK = (0x1U << 19),
+ PORT_SSP_INIT_MASK = (0x1U << 11),
+ PORT_DEV_TRGT_MASK = (0x7U << 17),
+ PORT_DEV_INIT_MASK = (0x7U << 9),
+ PORT_DEV_TYPE_MASK = (0x7U << 0),
+
+ /* Port n PHY Status */
+ PHY_RDY = (1U << 2),
+ PHY_DW_SYNC = (1U << 1),
+ PHY_OOB_DTCTD = (1U << 0),
+
+ /* VSR */
+ /* PHYMODE 6 (CDB) */
+ PHY_MODE6_LATECLK = (1U << 29), /* Lock Clock */
+ PHY_MODE6_DTL_SPEED = (1U << 27), /* Digital Loop Speed */
+ PHY_MODE6_FC_ORDER = (1U << 26), /* Fibre Channel Mode Order*/
+ PHY_MODE6_MUCNT_EN = (1U << 24), /* u Count Enable */
+ PHY_MODE6_SEL_MUCNT_LEN = (1U << 22), /* Training Length Select */
+ PHY_MODE6_SELMUPI = (1U << 20), /* Phase Multi Select (init) */
+ PHY_MODE6_SELMUPF = (1U << 18), /* Phase Multi Select (final) */
+ PHY_MODE6_SELMUFF = (1U << 16), /* Freq Loop Multi Sel(final) */
+ PHY_MODE6_SELMUFI = (1U << 14), /* Freq Loop Multi Sel(init) */
+ PHY_MODE6_FREEZE_LOOP = (1U << 12), /* Freeze Rx CDR Loop */
+ PHY_MODE6_INT_RXFOFFS = (1U << 3), /* Rx CDR Freq Loop Enable */
+ PHY_MODE6_FRC_RXFOFFS = (1U << 2), /* Initial Rx CDR Offset */
+ PHY_MODE6_STAU_0D8 = (1U << 1), /* Rx CDR Freq Loop Saturate */
+ PHY_MODE6_RXSAT_DIS = (1U << 0), /* Saturate Ctl */
+};
+
+/* SAS/SATA configuration port registers, aka phy registers */
+enum sas_sata_config_port_regs {
+ PHYR_IDENTIFY = 0x00, /* info for IDENTIFY frame */
+ PHYR_ADDR_LO = 0x04, /* my SAS address (low) */
+ PHYR_ADDR_HI = 0x08, /* my SAS address (high) */
+ PHYR_ATT_DEV_INFO = 0x0C, /* attached device info */
+ PHYR_ATT_ADDR_LO = 0x10, /* attached dev SAS addr (low) */
+ PHYR_ATT_ADDR_HI = 0x14, /* attached dev SAS addr (high) */
+ PHYR_SATA_CTL = 0x18, /* SATA control */
+ PHYR_PHY_STAT = 0x1C, /* PHY status */
+ PHYR_SATA_SIG0 = 0x20, /*port SATA signature FIS(Byte 0-3) */
+ PHYR_SATA_SIG1 = 0x24, /*port SATA signature FIS(Byte 4-7) */
+ PHYR_SATA_SIG2 = 0x28, /*port SATA signature FIS(Byte 8-11) */
+ PHYR_SATA_SIG3 = 0x2c, /*port SATA signature FIS(Byte 12-15) */
+ PHYR_R_ERR_COUNT = 0x30, /* port R_ERR count register */
+ PHYR_CRC_ERR_COUNT = 0x34, /* port CRC error count register */
+ PHYR_WIDE_PORT = 0x38, /* wide port participating */
+ PHYR_CURRENT0 = 0x80, /* current connection info 0 */
+ PHYR_CURRENT1 = 0x84, /* current connection info 1 */
+ PHYR_CURRENT2 = 0x88, /* current connection info 2 */
+ CONFIG_ID_FRAME0 = 0x100, /* Port device ID frame register 0 */
+ CONFIG_ID_FRAME1 = 0x104, /* Port device ID frame register 1 */
+ CONFIG_ID_FRAME2 = 0x108, /* Port device ID frame register 2 */
+ CONFIG_ID_FRAME3 = 0x10c, /* Port device ID frame register 3 */
+ CONFIG_ID_FRAME4 = 0x110, /* Port device ID frame register 4 */
+ CONFIG_ID_FRAME5 = 0x114, /* Port device ID frame register 5 */
+ CONFIG_ID_FRAME6 = 0x118, /* Port device ID frame register 6 */
+ CONFIG_ATT_ID_FRAME0 = 0x11c, /* attached ID frame register 0 */
+ CONFIG_ATT_ID_FRAME1 = 0x120, /* attached ID frame register 1 */
+ CONFIG_ATT_ID_FRAME2 = 0x124, /* attached ID frame register 2 */
+ CONFIG_ATT_ID_FRAME3 = 0x128, /* attached ID frame register 3 */
+ CONFIG_ATT_ID_FRAME4 = 0x12c, /* attached ID frame register 4 */
+ CONFIG_ATT_ID_FRAME5 = 0x130, /* attached ID frame register 5 */
+ CONFIG_ATT_ID_FRAME6 = 0x134, /* attached ID frame register 6 */
+};
+
+enum sas_cmd_port_registers {
+ CMD_CMRST_OOB_DET = 0x100, /* COMRESET OOB detect register */
+ CMD_CMWK_OOB_DET = 0x104, /* COMWAKE OOB detect register */
+ CMD_CMSAS_OOB_DET = 0x108, /* COMSAS OOB detect register */
+ CMD_BRST_OOB_DET = 0x10c, /* burst OOB detect register */
+ CMD_OOB_SPACE = 0x110, /* OOB space control register */
+ CMD_OOB_BURST = 0x114, /* OOB burst control register */
+ CMD_PHY_TIMER = 0x118, /* PHY timer control register */
+ CMD_PHY_CONFIG0 = 0x11c, /* PHY config register 0 */
+ CMD_PHY_CONFIG1 = 0x120, /* PHY config register 1 */
+ CMD_SAS_CTL0 = 0x124, /* SAS control register 0 */
+ CMD_SAS_CTL1 = 0x128, /* SAS control register 1 */
+ CMD_SAS_CTL2 = 0x12c, /* SAS control register 2 */
+ CMD_SAS_CTL3 = 0x130, /* SAS control register 3 */
+ CMD_ID_TEST = 0x134, /* ID test register */
+ CMD_PL_TIMER = 0x138, /* PL timer register */
+ CMD_WD_TIMER = 0x13c, /* WD timer register */
+ CMD_PORT_SEL_COUNT = 0x140, /* port selector count register */
+ CMD_APP_MEM_CTL = 0x144, /* Application Memory Control */
+ CMD_XOR_MEM_CTL = 0x148, /* XOR Block Memory Control */
+ CMD_DMA_MEM_CTL = 0x14c, /* DMA Block Memory Control */
+ CMD_PORT_MEM_CTL0 = 0x150, /* Port Memory Control 0 */
+ CMD_PORT_MEM_CTL1 = 0x154, /* Port Memory Control 1 */
+ CMD_SATA_PORT_MEM_CTL0 = 0x158, /* SATA Port Memory Control 0 */
+ CMD_SATA_PORT_MEM_CTL1 = 0x15c, /* SATA Port Memory Control 1 */
+ CMD_XOR_MEM_BIST_CTL = 0x160, /* XOR Memory BIST Control */
+ CMD_XOR_MEM_BIST_STAT = 0x164, /* XOR Memroy BIST Status */
+ CMD_DMA_MEM_BIST_CTL = 0x168, /* DMA Memory BIST Control */
+ CMD_DMA_MEM_BIST_STAT = 0x16c, /* DMA Memory BIST Status */
+ CMD_PORT_MEM_BIST_CTL = 0x170, /* Port Memory BIST Control */
+ CMD_PORT_MEM_BIST_STAT0 = 0x174, /* Port Memory BIST Status 0 */
+ CMD_PORT_MEM_BIST_STAT1 = 0x178, /* Port Memory BIST Status 1 */
+ CMD_STP_MEM_BIST_CTL = 0x17c, /* STP Memory BIST Control */
+ CMD_STP_MEM_BIST_STAT0 = 0x180, /* STP Memory BIST Status 0 */
+ CMD_STP_MEM_BIST_STAT1 = 0x184, /* STP Memory BIST Status 1 */
+ CMD_RESET_COUNT = 0x188, /* Reset Count */
+ CMD_MONTR_DATA_SEL = 0x18C, /* Monitor Data/Select */
+ CMD_PLL_PHY_CONFIG = 0x190, /* PLL/PHY Configuration */
+ CMD_PHY_CTL = 0x194, /* PHY Control and Status */
+ CMD_PHY_TEST_COUNT0 = 0x198, /* Phy Test Count 0 */
+ CMD_PHY_TEST_COUNT1 = 0x19C, /* Phy Test Count 1 */
+ CMD_PHY_TEST_COUNT2 = 0x1A0, /* Phy Test Count 2 */
+ CMD_APP_ERR_CONFIG = 0x1A4, /* Application Error Configuration */
+ CMD_PND_FIFO_CTL0 = 0x1A8, /* Pending FIFO Control 0 */
+ CMD_HOST_CTL = 0x1AC, /* Host Control Status */
+ CMD_HOST_WR_DATA = 0x1B0, /* Host Write Data */
+ CMD_HOST_RD_DATA = 0x1B4, /* Host Read Data */
+ CMD_PHY_MODE_21 = 0x1B8, /* Phy Mode 21 */
+ CMD_SL_MODE0 = 0x1BC, /* SL Mode 0 */
+ CMD_SL_MODE1 = 0x1C0, /* SL Mode 1 */
+ CMD_PND_FIFO_CTL1 = 0x1C4, /* Pending FIFO Control 1 */
+};
+
+enum mvs_info_flags {
+ MVF_MSI = (1U << 0), /* MSI is enabled */
+ MVF_PHY_PWR_FIX = (1U << 1), /* bug workaround */
+ MVF_FLAG_SOC = (1U << 2), /* SoC integrated controllers */
+};
+
+enum mvs_event_flags {
+ PHY_PLUG_EVENT = (3U),
+ PHY_PLUG_IN = (1U << 0), /* phy plug in */
+ PHY_PLUG_OUT = (1U << 1), /* phy plug out */
+};
+
+enum mvs_port_type {
+ PORT_TGT_MASK = (1U << 5),
+ PORT_INIT_PORT = (1U << 4),
+ PORT_TGT_PORT = (1U << 3),
+ PORT_INIT_TGT_PORT = (PORT_INIT_PORT | PORT_TGT_PORT),
+ PORT_TYPE_SAS = (1U << 1),
+ PORT_TYPE_SATA = (1U << 0),
+};
+
+/* Command Table Format */
+enum ct_format {
+ /* SSP */
+ SSP_F_H = 0x00,
+ SSP_F_IU = 0x18,
+ SSP_F_MAX = 0x4D,
+ /* STP */
+ STP_CMD_FIS = 0x00,
+ STP_ATAPI_CMD = 0x40,
+ STP_F_MAX = 0x10,
+ /* SMP */
+ SMP_F_T = 0x00,
+ SMP_F_DEP = 0x01,
+ SMP_F_MAX = 0x101,
+};
+
+enum status_buffer {
+ SB_EIR_OFF = 0x00, /* Error Information Record */
+ SB_RFB_OFF = 0x08, /* Response Frame Buffer */
+ SB_RFB_MAX = 0x400, /* RFB size*/
+};
+
+enum error_info_rec {
+ CMD_ISS_STPD = (1U << 31), /* Cmd Issue Stopped */
+ CMD_PI_ERR = (1U << 30), /* Protection info error. see flags2 */
+ RSP_OVER = (1U << 29), /* rsp buffer overflow */
+ RETRY_LIM = (1U << 28), /* FIS/frame retry limit exceeded */
+ UNK_FIS = (1U << 27), /* unknown FIS */
+ DMA_TERM = (1U << 26), /* DMA terminate primitive rx'd */
+ SYNC_ERR = (1U << 25), /* SYNC rx'd during frame xmit */
+ TFILE_ERR = (1U << 24), /* SATA taskfile Error bit set */
+ R_ERR = (1U << 23), /* SATA returned R_ERR prim */
+ RD_OFS = (1U << 20), /* Read DATA frame invalid offset */
+ XFER_RDY_OFS = (1U << 19), /* XFER_RDY offset error */
+ UNEXP_XFER_RDY = (1U << 18), /* unexpected XFER_RDY error */
+ DATA_OVER_UNDER = (1U << 16), /* data overflow/underflow */
+ INTERLOCK = (1U << 15), /* interlock error */
+ NAK = (1U << 14), /* NAK rx'd */
+ ACK_NAK_TO = (1U << 13), /* ACK/NAK timeout */
+ CXN_CLOSED = (1U << 12), /* cxn closed w/out ack/nak */
+ OPEN_TO = (1U << 11), /* I_T nexus lost, open cxn timeout */
+ PATH_BLOCKED = (1U << 10), /* I_T nexus lost, pathway blocked */
+ NO_DEST = (1U << 9), /* I_T nexus lost, no destination */
+ STP_RES_BSY = (1U << 8), /* STP resources busy */
+ BREAK = (1U << 7), /* break received */
+ BAD_DEST = (1U << 6), /* bad destination */
+ BAD_PROTO = (1U << 5), /* protocol not supported */
+ BAD_RATE = (1U << 4), /* cxn rate not supported */
+ WRONG_DEST = (1U << 3), /* wrong destination error */
+ CREDIT_TO = (1U << 2), /* credit timeout */
+ WDOG_TO = (1U << 1), /* watchdog timeout */
+ BUF_PAR = (1U << 0), /* buffer parity error */
+};
+
+enum error_info_rec_2 {
+ SLOT_BSY_ERR = (1U << 31), /* Slot Busy Error */
+ GRD_CHK_ERR = (1U << 14), /* Guard Check Error */
+ APP_CHK_ERR = (1U << 13), /* Application Check error */
+ REF_CHK_ERR = (1U << 12), /* Reference Check Error */
+ USR_BLK_NM = (1U << 0), /* User Block Number */
+};
+
+enum pci_cfg_register_bits {
+ PCTL_PWR_OFF = (0xFU << 24),
+ PCTL_COM_ON = (0xFU << 20),
+ PCTL_LINK_RST = (0xFU << 16),
+ PCTL_LINK_OFFS = (16),
+ PCTL_PHY_DSBL = (0xFU << 12),
+ PCTL_PHY_DSBL_OFFS = (12),
+ PRD_REQ_SIZE = (0x4000),
+ PRD_REQ_MASK = (0x00007000),
+ PLS_NEG_LINK_WD = (0x3FU << 4),
+ PLS_NEG_LINK_WD_OFFS = 4,
+ PLS_LINK_SPD = (0x0FU << 0),
+ PLS_LINK_SPD_OFFS = 0,
+};
+
+enum open_frame_protocol {
+ PROTOCOL_SMP = 0x0,
+ PROTOCOL_SSP = 0x1,
+ PROTOCOL_STP = 0x2,
+};
+
+/* define for response frame datapres field */
+enum datapres_field {
+ NO_DATA = 0,
+ RESPONSE_DATA = 1,
+ SENSE_DATA = 2,
+};
+
+/* define task management IU */
+struct mvs_tmf_task{
+ u8 tmf;
+ u16 tag_of_task_to_be_managed;
+};
+#endif
diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c
new file mode 100644
index 000000000000..ac5a74f08be7
--- /dev/null
+++ b/drivers/scsi/mvsas/mv_init.c
@@ -0,0 +1,703 @@
+/*
+ * Marvell 88SE64xx/88SE94xx pci init
+ *
+ * Copyright 2007 Red Hat, Inc.
+ * Copyright 2008 Marvell. <kewei@marvell.com>
+ *
+ * This file is licensed under GPLv2.
+ *
+ * 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
+*/
+
+
+#include "mv_sas.h"
+
+static struct scsi_transport_template *mvs_stt;
+static const struct mvs_chip_info mvs_chips[] = {
+ [chip_6320] = { 1, 2, 0x400, 17, 16, 9, &mvs_64xx_dispatch, },
+ [chip_6440] = { 1, 4, 0x400, 17, 16, 9, &mvs_64xx_dispatch, },
+ [chip_6485] = { 1, 8, 0x800, 33, 32, 10, &mvs_64xx_dispatch, },
+ [chip_9180] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, },
+ [chip_9480] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, },
+};
+
+#define SOC_SAS_NUM 2
+
+static struct scsi_host_template mvs_sht = {
+ .module = THIS_MODULE,
+ .name = DRV_NAME,
+ .queuecommand = sas_queuecommand,
+ .target_alloc = sas_target_alloc,
+ .slave_configure = mvs_slave_configure,
+ .slave_destroy = sas_slave_destroy,
+ .scan_finished = mvs_scan_finished,
+ .scan_start = mvs_scan_start,
+ .change_queue_depth = sas_change_queue_depth,
+ .change_queue_type = sas_change_queue_type,
+ .bios_param = sas_bios_param,
+ .can_queue = 1,
+ .cmd_per_lun = 1,
+ .this_id = -1,
+ .sg_tablesize = SG_ALL,
+ .max_sectors = SCSI_DEFAULT_MAX_SECTORS,
+ .use_clustering = ENABLE_CLUSTERING,
+ .eh_device_reset_handler = sas_eh_device_reset_handler,
+ .eh_bus_reset_handler = sas_eh_bus_reset_handler,
+ .slave_alloc = mvs_slave_alloc,
+ .target_destroy = sas_target_destroy,
+ .ioctl = sas_ioctl,
+};
+
+static struct sas_domain_function_template mvs_transport_ops = {
+ .lldd_dev_found = mvs_dev_found,
+ .lldd_dev_gone = mvs_dev_gone,
+
+ .lldd_execute_task = mvs_queue_command,
+ .lldd_control_phy = mvs_phy_control,
+
+ .lldd_abort_task = mvs_abort_task,
+ .lldd_abort_task_set = mvs_abort_task_set,
+ .lldd_clear_aca = mvs_clear_aca,
+ .lldd_clear_task_set = mvs_clear_task_set,
+ .lldd_I_T_nexus_reset = mvs_I_T_nexus_reset,
+ .lldd_lu_reset = mvs_lu_reset,
+ .lldd_query_task = mvs_query_task,
+
+ .lldd_port_formed = mvs_port_formed,
+ .lldd_port_deformed = mvs_port_deformed,
+
+};
+
+static void __devinit mvs_phy_init(struct mvs_info *mvi, int phy_id)
+{
+ struct mvs_phy *phy = &mvi->phy[phy_id];
+ struct asd_sas_phy *sas_phy = &phy->sas_phy;
+
+ phy->mvi = mvi;
+ init_timer(&phy->timer);
+ sas_phy->enabled = (phy_id < mvi->chip->n_phy) ? 1 : 0;
+ sas_phy->class = SAS;
+ sas_phy->iproto = SAS_PROTOCOL_ALL;
+ sas_phy->tproto = 0;
+ sas_phy->type = PHY_TYPE_PHYSICAL;
+ sas_phy->role = PHY_ROLE_INITIATOR;
+ sas_phy->oob_mode = OOB_NOT_CONNECTED;
+ sas_phy->linkrate = SAS_LINK_RATE_UNKNOWN;
+
+ sas_phy->id = phy_id;
+ sas_phy->sas_addr = &mvi->sas_addr[0];
+ sas_phy->frame_rcvd = &phy->frame_rcvd[0];
+ sas_phy->ha = (struct sas_ha_struct *)mvi->shost->hostdata;
+ sas_phy->lldd_phy = phy;
+}
+
+static void mvs_free(struct mvs_info *mvi)
+{
+ int i;
+ struct mvs_wq *mwq;
+ int slot_nr;
+
+ if (!mvi)
+ return;
+
+ if (mvi->flags & MVF_FLAG_SOC)
+ slot_nr = MVS_SOC_SLOTS;
+ else
+ slot_nr = MVS_SLOTS;
+
+ for (i = 0; i < mvi->tags_num; i++) {
+ struct mvs_slot_info *slot = &mvi->slot_info[i];
+ if (slot->buf)
+ dma_free_coherent(mvi->dev, MVS_SLOT_BUF_SZ,
+ slot->buf, slot->buf_dma);
+ }
+
+ if (mvi->tx)
+ dma_free_coherent(mvi->dev,
+ sizeof(*mvi->tx) * MVS_CHIP_SLOT_SZ,
+ mvi->tx, mvi->tx_dma);
+ if (mvi->rx_fis)
+ dma_free_coherent(mvi->dev, MVS_RX_FISL_SZ,
+ mvi->rx_fis, mvi->rx_fis_dma);
+ if (mvi->rx)
+ dma_free_coherent(mvi->dev,
+ sizeof(*mvi->rx) * (MVS_RX_RING_SZ + 1),
+ mvi->rx, mvi->rx_dma);
+ if (mvi->slot)
+ dma_free_coherent(mvi->dev,
+ sizeof(*mvi->slot) * slot_nr,
+ mvi->slot, mvi->slot_dma);
+#ifndef DISABLE_HOTPLUG_DMA_FIX
+ if (mvi->bulk_buffer)
+ dma_free_coherent(mvi->dev, TRASH_BUCKET_SIZE,
+ mvi->bulk_buffer, mvi->bulk_buffer_dma);
+#endif
+
+ MVS_CHIP_DISP->chip_iounmap(mvi);
+ if (mvi->shost)
+ scsi_host_put(mvi->shost);
+ list_for_each_entry(mwq, &mvi->wq_list, entry)
+ cancel_delayed_work(&mwq->work_q);
+ kfree(mvi);
+}
+
+#ifdef MVS_USE_TASKLET
+struct tasklet_struct mv_tasklet;
+static void mvs_tasklet(unsigned long opaque)
+{
+ unsigned long flags;
+ u32 stat;
+ u16 core_nr, i = 0;
+
+ struct mvs_info *mvi;
+ struct sas_ha_struct *sha = (struct sas_ha_struct *)opaque;
+
+ core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
+ mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0];
+
+ if (unlikely(!mvi))
+ BUG_ON(1);
+
+ for (i = 0; i < core_nr; i++) {
+ mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i];
+ stat = MVS_CHIP_DISP->isr_status(mvi, mvi->irq);
+ if (stat)
+ MVS_CHIP_DISP->isr(mvi, mvi->irq, stat);
+ }
+
+}
+#endif
+
+static irqreturn_t mvs_interrupt(int irq, void *opaque)
+{
+ u32 core_nr, i = 0;
+ u32 stat;
+ struct mvs_info *mvi;
+ struct sas_ha_struct *sha = opaque;
+
+ core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
+ mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0];
+
+ if (unlikely(!mvi))
+ return IRQ_NONE;
+
+ stat = MVS_CHIP_DISP->isr_status(mvi, irq);
+ if (!stat)
+ return IRQ_NONE;
+
+#ifdef MVS_USE_TASKLET
+ tasklet_schedule(&mv_tasklet);
+#else
+ for (i = 0; i < core_nr; i++) {
+ mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i];
+ MVS_CHIP_DISP->isr(mvi, irq, stat);
+ }
+#endif
+ return IRQ_HANDLED;
+}
+
+static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
+{
+ int i, slot_nr;
+
+ if (mvi->flags & MVF_FLAG_SOC)
+ slot_nr = MVS_SOC_SLOTS;
+ else
+ slot_nr = MVS_SLOTS;
+
+ spin_lock_init(&mvi->lock);
+ for (i = 0; i < mvi->chip->n_phy; i++) {
+ mvs_phy_init(mvi, i);
+ mvi->port[i].wide_port_phymap = 0;
+ mvi->port[i].port_attached = 0;
+ INIT_LIST_HEAD(&mvi->port[i].list);
+ }
+ for (i = 0; i < MVS_MAX_DEVICES; i++) {
+ mvi->devices[i].taskfileset = MVS_ID_NOT_MAPPED;
+ mvi->devices[i].dev_type = NO_DEVICE;
+ mvi->devices[i].device_id = i;
+ mvi->devices[i].dev_status = MVS_DEV_NORMAL;
+ }
+
+ /*
+ * alloc and init our DMA areas
+ */
+ mvi->tx = dma_alloc_coherent(mvi->dev,
+ sizeof(*mvi->tx) * MVS_CHIP_SLOT_SZ,
+ &mvi->tx_dma, GFP_KERNEL);
+ if (!mvi->tx)
+ goto err_out;
+ memset(mvi->tx, 0, sizeof(*mvi->tx) * MVS_CHIP_SLOT_SZ);
+ mvi->rx_fis = dma_alloc_coherent(mvi->dev, MVS_RX_FISL_SZ,
+ &mvi->rx_fis_dma, GFP_KERNEL);
+ if (!mvi->rx_fis)
+ goto err_out;
+ memset(mvi->rx_fis, 0, MVS_RX_FISL_SZ);
+
+ mvi->rx = dma_alloc_coherent(mvi->dev,
+ sizeof(*mvi->rx) * (MVS_RX_RING_SZ + 1),
+ &mvi->rx_dma, GFP_KERNEL);
+ if (!mvi->rx)
+ goto err_out;
+ memset(mvi->rx, 0, sizeof(*mvi->rx) * (MVS_RX_RING_SZ + 1));
+ mvi->rx[0] = cpu_to_le32(0xfff);
+ mvi->rx_cons = 0xfff;
+
+ mvi->slot = dma_alloc_coherent(mvi->dev,
+ sizeof(*mvi->slot) * slot_nr,
+ &mvi->slot_dma, GFP_KERNEL);
+ if (!mvi->slot)
+ goto err_out;
+ memset(mvi->slot, 0, sizeof(*mvi->slot) * slot_nr);
+
+#ifndef DISABLE_HOTPLUG_DMA_FIX
+ mvi->bulk_buffer = dma_alloc_coherent(mvi->dev,
+ TRASH_BUCKET_SIZE,
+ &mvi->bulk_buffer_dma, GFP_KERNEL);
+ if (!mvi->bulk_buffer)
+ goto err_out;
+#endif
+ for (i = 0; i < slot_nr; i++) {
+ struct mvs_slot_info *slot = &mvi->slot_info[i];
+
+ slot->buf = dma_alloc_coherent(mvi->dev, MVS_SLOT_BUF_SZ,
+ &slot->buf_dma, GFP_KERNEL);
+ if (!slot->buf) {
+ printk(KERN_DEBUG"failed to allocate slot->buf.\n");
+ goto err_out;
+ }
+ memset(slot->buf, 0, MVS_SLOT_BUF_SZ);
+ ++mvi->tags_num;
+ }
+ /* Initialize tags */
+ mvs_tag_init(mvi);
+ return 0;
+err_out:
+ return 1;
+}
+
+
+int mvs_ioremap(struct mvs_info *mvi, int bar, int bar_ex)
+{
+ unsigned long res_start, res_len, res_flag, res_flag_ex = 0;
+ struct pci_dev *pdev = mvi->pdev;
+ if (bar_ex != -1) {
+ /*
+ * ioremap main and peripheral registers
+ */
+ res_start = pci_resource_start(pdev, bar_ex);
+ res_len = pci_resource_len(pdev, bar_ex);
+ if (!res_start || !res_len)
+ goto err_out;
+
+ res_flag_ex = pci_resource_flags(pdev, bar_ex);
+ if (res_flag_ex & IORESOURCE_MEM) {
+ if (res_flag_ex & IORESOURCE_CACHEABLE)
+ mvi->regs_ex = ioremap(res_start, res_len);
+ else
+ mvi->regs_ex = ioremap_nocache(res_start,
+ res_len);
+ } else
+ mvi->regs_ex = (void *)res_start;
+ if (!mvi->regs_ex)
+ goto err_out;
+ }
+
+ res_start = pci_resource_start(pdev, bar);
+ res_len = pci_resource_len(pdev, bar);
+ if (!res_start || !res_len)
+ goto err_out;
+
+ res_flag = pci_resource_flags(pdev, bar);
+ if (res_flag & IORESOURCE_CACHEABLE)
+ mvi->regs = ioremap(res_start, res_len);
+ else
+ mvi->regs = ioremap_nocache(res_start, res_len);
+
+ if (!mvi->regs) {
+ if (mvi->regs_ex && (res_flag_ex & IORESOURCE_MEM))
+ iounmap(mvi->regs_ex);
+ mvi->regs_ex = NULL;
+ goto err_out;
+ }
+
+ return 0;
+err_out:
+ return -1;
+}
+
+void mvs_iounmap(void __iomem *regs)
+{
+ iounmap(regs);
+}
+
+static struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev,
+ const struct pci_device_id *ent,
+ struct Scsi_Host *shost, unsigned int id)
+{
+ struct mvs_info *mvi;
+ struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+
+ mvi = kzalloc(sizeof(*mvi) + MVS_SLOTS * sizeof(struct mvs_slot_info),
+ GFP_KERNEL);
+ if (!mvi)
+ return NULL;
+
+ mvi->pdev = pdev;
+ mvi->dev = &pdev->dev;
+ mvi->chip_id = ent->driver_data;
+ mvi->chip = &mvs_chips[mvi->chip_id];
+ INIT_LIST_HEAD(&mvi->wq_list);
+ mvi->irq = pdev->irq;
+
+ ((struct mvs_prv_info *)sha->lldd_ha)->mvi[id] = mvi;
+ ((struct mvs_prv_info *)sha->lldd_ha)->n_phy = mvi->chip->n_phy;
+
+ mvi->id = id;
+ mvi->sas = sha;
+ mvi->shost = shost;
+#ifdef MVS_USE_TASKLET
+ tasklet_init(&mv_tasklet, mvs_tasklet, (unsigned long)sha);
+#endif
+
+ if (MVS_CHIP_DISP->chip_ioremap(mvi))
+ goto err_out;
+ if (!mvs_alloc(mvi, shost))
+ return mvi;
+err_out:
+ mvs_free(mvi);
+ return NULL;
+}
+
+/* move to PCI layer or libata core? */
+static int pci_go_64(struct pci_dev *pdev)
+{
+ int rc;
+
+ if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+ rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+ if (rc) {
+ rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ if (rc) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "64-bit DMA enable failed\n");
+ return rc;
+ }
+ }
+ } else {
+ rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (rc) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "32-bit DMA enable failed\n");
+ return rc;
+ }
+ rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ if (rc) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "32-bit consistent DMA enable failed\n");
+ return rc;
+ }
+ }
+
+ return rc;
+}
+
+static int __devinit mvs_prep_sas_ha_init(struct Scsi_Host *shost,
+ const struct mvs_chip_info *chip_info)
+{
+ int phy_nr, port_nr; unsigned short core_nr;
+ struct asd_sas_phy **arr_phy;
+ struct asd_sas_port **arr_port;
+ struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+
+ core_nr = chip_info->n_host;
+ phy_nr = core_nr * chip_info->n_phy;
+ port_nr = phy_nr;
+
+ memset(sha, 0x00, sizeof(struct sas_ha_struct));
+ arr_phy = kcalloc(phy_nr, sizeof(void *), GFP_KERNEL);
+ arr_port = kcalloc(port_nr, sizeof(void *), GFP_KERNEL);
+ if (!arr_phy || !arr_port)
+ goto exit_free;
+
+ sha->sas_phy = arr_phy;
+ sha->sas_port = arr_port;
+
+ sha->lldd_ha = kzalloc(sizeof(struct mvs_prv_info), GFP_KERNEL);
+ if (!sha->lldd_ha)
+ goto exit_free;
+
+ ((struct mvs_prv_info *)sha->lldd_ha)->n_host = core_nr;
+
+ shost->transportt = mvs_stt;
+ shost->max_id = 128;
+ shost->max_lun = ~0;
+ shost->max_channel = 1;
+ shost->max_cmd_len = 16;
+
+ return 0;
+exit_free:
+ kfree(arr_phy);
+ kfree(arr_port);
+ return -1;
+
+}
+
+static void __devinit mvs_post_sas_ha_init(struct Scsi_Host *shost,
+ const struct mvs_chip_info *chip_info)
+{
+ int can_queue, i = 0, j = 0;
+ struct mvs_info *mvi = NULL;
+ struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+ unsigned short nr_core = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
+
+ for (j = 0; j < nr_core; j++) {
+ mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[j];
+ for (i = 0; i < chip_info->n_phy; i++) {
+ sha->sas_phy[j * chip_info->n_phy + i] =
+ &mvi->phy[i].sas_phy;
+ sha->sas_port[j * chip_info->n_phy + i] =
+ &mvi->port[i].sas_port;
+ }
+ }
+
+ sha->sas_ha_name = DRV_NAME;
+ sha->dev = mvi->dev;
+ sha->lldd_module = THIS_MODULE;
+ sha->sas_addr = &mvi->sas_addr[0];
+
+ sha->num_phys = nr_core * chip_info->n_phy;
+
+ sha->lldd_max_execute_num = 1;
+
+ if (mvi->flags & MVF_FLAG_SOC)
+ can_queue = MVS_SOC_CAN_QUEUE;
+ else
+ can_queue = MVS_CAN_QUEUE;
+
+ sha->lldd_queue_size = can_queue;
+ shost->can_queue = can_queue;
+ mvi->shost->cmd_per_lun = MVS_SLOTS/sha->num_phys;
+ sha->core.shost = mvi->shost;
+}
+
+static void mvs_init_sas_add(struct mvs_info *mvi)
+{
+ u8 i;
+ for (i = 0; i < mvi->chip->n_phy; i++) {
+ mvi->phy[i].dev_sas_addr = 0x5005043011ab0000ULL;
+ mvi->phy[i].dev_sas_addr =
+ cpu_to_be64((u64)(*(u64 *)&mvi->phy[i].dev_sas_addr));
+ }
+
+ memcpy(mvi->sas_addr, &mvi->phy[0].dev_sas_addr, SAS_ADDR_SIZE);
+}
+
+static int __devinit mvs_pci_init(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ unsigned int rc, nhost = 0;
+ struct mvs_info *mvi;
+ irq_handler_t irq_handler = mvs_interrupt;
+ struct Scsi_Host *shost = NULL;
+ const struct mvs_chip_info *chip;
+
+ dev_printk(KERN_INFO, &pdev->dev,
+ "mvsas: driver version %s\n", DRV_VERSION);
+ rc = pci_enable_device(pdev);
+ if (rc)
+ goto err_out_enable;
+
+ pci_set_master(pdev);
+
+ rc = pci_request_regions(pdev, DRV_NAME);
+ if (rc)
+ goto err_out_disable;
+
+ rc = pci_go_64(pdev);
+ if (rc)
+ goto err_out_regions;
+
+ shost = scsi_host_alloc(&mvs_sht, sizeof(void *));
+ if (!shost) {
+ rc = -ENOMEM;
+ goto err_out_regions;
+ }
+
+ chip = &mvs_chips[ent->driver_data];
+ SHOST_TO_SAS_HA(shost) =
+ kcalloc(1, sizeof(struct sas_ha_struct), GFP_KERNEL);
+ if (!SHOST_TO_SAS_HA(shost)) {
+ kfree(shost);
+ rc = -ENOMEM;
+ goto err_out_regions;
+ }
+
+ rc = mvs_prep_sas_ha_init(shost, chip);
+ if (rc) {
+ kfree(shost);
+ rc = -ENOMEM;
+ goto err_out_regions;
+ }
+
+ pci_set_drvdata(pdev, SHOST_TO_SAS_HA(shost));
+
+ do {
+ mvi = mvs_pci_alloc(pdev, ent, shost, nhost);
+ if (!mvi) {
+ rc = -ENOMEM;
+ goto err_out_regions;
+ }
+
+ mvs_init_sas_add(mvi);
+
+ mvi->instance = nhost;
+ rc = MVS_CHIP_DISP->chip_init(mvi);
+ if (rc) {
+ mvs_free(mvi);
+ goto err_out_regions;
+ }
+ nhost++;
+ } while (nhost < chip->n_host);
+
+ mvs_post_sas_ha_init(shost, chip);
+
+ rc = scsi_add_host(shost, &pdev->dev);
+ if (rc)
+ goto err_out_shost;
+
+ rc = sas_register_ha(SHOST_TO_SAS_HA(shost));
+ if (rc)
+ goto err_out_shost;
+ rc = request_irq(pdev->irq, irq_handler, IRQF_SHARED,
+ DRV_NAME, SHOST_TO_SAS_HA(shost));
+ if (rc)
+ goto err_not_sas;
+
+ MVS_CHIP_DISP->interrupt_enable(mvi);
+
+ scsi_scan_host(mvi->shost);
+
+ return 0;
+
+err_not_sas:
+ sas_unregister_ha(SHOST_TO_SAS_HA(shost));
+err_out_shost:
+ scsi_remove_host(mvi->shost);
+err_out_regions:
+ pci_release_regions(pdev);
+err_out_disable:
+ pci_disable_device(pdev);
+err_out_enable:
+ return rc;
+}
+
+static void __devexit mvs_pci_remove(struct pci_dev *pdev)
+{
+ unsigned short core_nr, i = 0;
+ struct sas_ha_struct *sha = pci_get_drvdata(pdev);
+ struct mvs_info *mvi = NULL;
+
+ core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
+ mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0];
+
+#ifdef MVS_USE_TASKLET
+ tasklet_kill(&mv_tasklet);
+#endif
+
+ pci_set_drvdata(pdev, NULL);
+ sas_unregister_ha(sha);
+ sas_remove_host(mvi->shost);
+ scsi_remove_host(mvi->shost);
+
+ MVS_CHIP_DISP->interrupt_disable(mvi);
+ free_irq(mvi->irq, sha);
+ for (i = 0; i < core_nr; i++) {
+ mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i];
+ mvs_free(mvi);
+ }
+ kfree(sha->sas_phy);
+ kfree(sha->sas_port);
+ kfree(sha);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ return;
+}
+
+static struct pci_device_id __devinitdata mvs_pci_table[] = {
+ { PCI_VDEVICE(MARVELL, 0x6320), chip_6320 },
+ { PCI_VDEVICE(MARVELL, 0x6340), chip_6440 },
+ {
+ .vendor = PCI_VENDOR_ID_MARVELL,
+ .device = 0x6440,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = 0x6480,
+ .class = 0,
+ .class_mask = 0,
+ .driver_data = chip_6485,
+ },
+ { PCI_VDEVICE(MARVELL, 0x6440), chip_6440 },
+ { PCI_VDEVICE(MARVELL, 0x6485), chip_6485 },
+ { PCI_VDEVICE(MARVELL, 0x9480), chip_9480 },
+ { PCI_VDEVICE(MARVELL, 0x9180), chip_9180 },
+
+ { } /* terminate list */
+};
+
+static struct pci_driver mvs_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = mvs_pci_table,
+ .probe = mvs_pci_init,
+ .remove = __devexit_p(mvs_pci_remove),
+};
+
+/* task handler */
+struct task_struct *mvs_th;
+static int __init mvs_init(void)
+{
+ int rc;
+ mvs_stt = sas_domain_attach_transport(&mvs_transport_ops);
+ if (!mvs_stt)
+ return -ENOMEM;
+
+ rc = pci_register_driver(&mvs_pci_driver);
+
+ if (rc)
+ goto err_out;
+
+ return 0;
+
+err_out:
+ sas_release_transport(mvs_stt);
+ return rc;
+}
+
+static void __exit mvs_exit(void)
+{
+ pci_unregister_driver(&mvs_pci_driver);
+ sas_release_transport(mvs_stt);
+}
+
+module_init(mvs_init);
+module_exit(mvs_exit);
+
+MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>");
+MODULE_DESCRIPTION("Marvell 88SE6440 SAS/SATA controller driver");
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL");
+#ifdef CONFIG_PCI
+MODULE_DEVICE_TABLE(pci, mvs_pci_table);
+#endif
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
new file mode 100644
index 000000000000..d79ac179eaff
--- /dev/null
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -0,0 +1,2157 @@
+/*
+ * Marvell 88SE64xx/88SE94xx main function
+ *
+ * Copyright 2007 Red Hat, Inc.
+ * Copyright 2008 Marvell. <kewei@marvell.com>
+ *
+ * This file is licensed under GPLv2.
+ *
+ * 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
+*/
+
+#include "mv_sas.h"
+
+static int mvs_find_tag(struct mvs_info *mvi, struct sas_task *task, u32 *tag)
+{
+ if (task->lldd_task) {
+ struct mvs_slot_info *slot;
+ slot = (struct mvs_slot_info *) task->lldd_task;
+ *tag = slot->slot_tag;
+ return 1;
+ }
+ return 0;
+}
+
+void mvs_tag_clear(struct mvs_info *mvi, u32 tag)
+{
+ void *bitmap = (void *) &mvi->tags;
+ clear_bit(tag, bitmap);
+}
+
+void mvs_tag_free(struct mvs_info *mvi, u32 tag)
+{
+ mvs_tag_clear(mvi, tag);
+}
+
+void mvs_tag_set(struct mvs_info *mvi, unsigned int tag)
+{
+ void *bitmap = (void *) &mvi->tags;
+ set_bit(tag, bitmap);
+}
+
+inline int mvs_tag_alloc(struct mvs_info *mvi, u32 *tag_out)
+{
+ unsigned int index, tag;
+ void *bitmap = (void *) &mvi->tags;
+
+ index = find_first_zero_bit(bitmap, mvi->tags_num);
+ tag = index;
+ if (tag >= mvi->tags_num)
+ return -SAS_QUEUE_FULL;
+ mvs_tag_set(mvi, tag);
+ *tag_out = tag;
+ return 0;
+}
+
+void mvs_tag_init(struct mvs_info *mvi)
+{
+ int i;
+ for (i = 0; i < mvi->tags_num; ++i)
+ mvs_tag_clear(mvi, i);
+}
+
+void mvs_hexdump(u32 size, u8 *data, u32 baseaddr)
+{
+ u32 i;
+ u32 run;
+ u32 offset;
+
+ offset = 0;
+ while (size) {
+ printk(KERN_DEBUG"%08X : ", baseaddr + offset);
+ if (size >= 16)
+ run = 16;
+ else
+ run = size;
+ size -= run;
+ for (i = 0; i < 16; i++) {
+ if (i < run)
+ printk(KERN_DEBUG"%02X ", (u32)data[i]);
+ else
+ printk(KERN_DEBUG" ");
+ }
+ printk(KERN_DEBUG": ");
+ for (i = 0; i < run; i++)
+ printk(KERN_DEBUG"%c",
+ isalnum(data[i]) ? data[i] : '.');
+ printk(KERN_DEBUG"\n");
+ data = &data[16];
+ offset += run;
+ }
+ printk(KERN_DEBUG"\n");
+}
+
+#if (_MV_DUMP > 1)
+static void mvs_hba_sb_dump(struct mvs_info *mvi, u32 tag,
+ enum sas_protocol proto)
+{
+ u32 offset;
+ struct mvs_slot_info *slot = &mvi->slot_info[tag];
+
+ offset = slot->cmd_size + MVS_OAF_SZ +
+ MVS_CHIP_DISP->prd_size() * slot->n_elem;
+ dev_printk(KERN_DEBUG, mvi->dev, "+---->Status buffer[%d] :\n",
+ tag);
+ mvs_hexdump(32, (u8 *) slot->response,
+ (u32) slot->buf_dma + offset);
+}
+#endif
+
+static void mvs_hba_memory_dump(struct mvs_info *mvi, u32 tag,
+ enum sas_protocol proto)
+{
+#if (_MV_DUMP > 1)
+ u32 sz, w_ptr;
+ u64 addr;
+ struct mvs_slot_info *slot = &mvi->slot_info[tag];
+
+ /*Delivery Queue */
+ sz = MVS_CHIP_SLOT_SZ;
+ w_ptr = slot->tx;
+ addr = mvi->tx_dma;
+ dev_printk(KERN_DEBUG, mvi->dev,
+ "Delivery Queue Size=%04d , WRT_PTR=%04X\n", sz, w_ptr);
+ dev_printk(KERN_DEBUG, mvi->dev,
+ "Delivery Queue Base Address=0x%llX (PA)"
+ "(tx_dma=0x%llX), Entry=%04d\n",
+ addr, (unsigned long long)mvi->tx_dma, w_ptr);
+ mvs_hexdump(sizeof(u32), (u8 *)(&mvi->tx[mvi->tx_prod]),
+ (u32) mvi->tx_dma + sizeof(u32) * w_ptr);
+ /*Command List */
+ addr = mvi->slot_dma;
+ dev_printk(KERN_DEBUG, mvi->dev,
+ "Command List Base Address=0x%llX (PA)"
+ "(slot_dma=0x%llX), Header=%03d\n",
+ addr, (unsigned long long)slot->buf_dma, tag);
+ dev_printk(KERN_DEBUG, mvi->dev, "Command Header[%03d]:\n", tag);
+ /*mvs_cmd_hdr */
+ mvs_hexdump(sizeof(struct mvs_cmd_hdr), (u8 *)(&mvi->slot[tag]),
+ (u32) mvi->slot_dma + tag * sizeof(struct mvs_cmd_hdr));
+ /*1.command table area */
+ dev_printk(KERN_DEBUG, mvi->dev, "+---->Command Table :\n");
+ mvs_hexdump(slot->cmd_size, (u8 *) slot->buf, (u32) slot->buf_dma);
+ /*2.open address frame area */
+ dev_printk(KERN_DEBUG, mvi->dev, "+---->Open Address Frame :\n");
+ mvs_hexdump(MVS_OAF_SZ, (u8 *) slot->buf + slot->cmd_size,
+ (u32) slot->buf_dma + slot->cmd_size);
+ /*3.status buffer */
+ mvs_hba_sb_dump(mvi, tag, proto);
+ /*4.PRD table */
+ dev_printk(KERN_DEBUG, mvi->dev, "+---->PRD table :\n");
+ mvs_hexdump(MVS_CHIP_DISP->prd_size() * slot->n_elem,
+ (u8 *) slot->buf + slot->cmd_size + MVS_OAF_SZ,
+ (u32) slot->buf_dma + slot->cmd_size + MVS_OAF_SZ);
+#endif
+}
+
+static void mvs_hba_cq_dump(struct mvs_info *mvi)
+{
+#if (_MV_DUMP > 2)
+ u64 addr;
+ void __iomem *regs = mvi->regs;
+ u32 entry = mvi->rx_cons + 1;
+ u32 rx_desc = le32_to_cpu(mvi->rx[entry]);
+
+ /*Completion Queue */
+ addr = mr32(RX_HI) << 16 << 16 | mr32(RX_LO);
+ dev_printk(KERN_DEBUG, mvi->dev, "Completion Task = 0x%p\n",
+ mvi->slot_info[rx_desc & RXQ_SLOT_MASK].task);
+ dev_printk(KERN_DEBUG, mvi->dev,
+ "Completion List Base Address=0x%llX (PA), "
+ "CQ_Entry=%04d, CQ_WP=0x%08X\n",
+ addr, entry - 1, mvi->rx[0]);
+ mvs_hexdump(sizeof(u32), (u8 *)(&rx_desc),
+ mvi->rx_dma + sizeof(u32) * entry);
+#endif
+}
+
+void mvs_get_sas_addr(void *buf, u32 buflen)
+{
+ /*memcpy(buf, "\x50\x05\x04\x30\x11\xab\x64\x40", 8);*/
+}
+
+struct mvs_info *mvs_find_dev_mvi(struct domain_device *dev)
+{
+ unsigned long i = 0, j = 0, hi = 0;
+ struct sas_ha_struct *sha = dev->port->ha;
+ struct mvs_info *mvi = NULL;
+ struct asd_sas_phy *phy;
+
+ while (sha->sas_port[i]) {
+ if (sha->sas_port[i] == dev->port) {
+ phy = container_of(sha->sas_port[i]->phy_list.next,
+ struct asd_sas_phy, port_phy_el);
+ j = 0;
+ while (sha->sas_phy[j]) {
+ if (sha->sas_phy[j] == phy)
+ break;
+ j++;
+ }
+ break;
+ }
+ i++;
+ }
+ hi = j/((struct mvs_prv_info *)sha->lldd_ha)->n_phy;
+ mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[hi];
+
+ return mvi;
+
+}
+
+/* FIXME */
+int mvs_find_dev_phyno(struct domain_device *dev, int *phyno)
+{
+ unsigned long i = 0, j = 0, n = 0, num = 0;
+ struct mvs_info *mvi = mvs_find_dev_mvi(dev);
+ struct sas_ha_struct *sha = dev->port->ha;
+
+ while (sha->sas_port[i]) {
+ if (sha->sas_port[i] == dev->port) {
+ struct asd_sas_phy *phy;
+ list_for_each_entry(phy,
+ &sha->sas_port[i]->phy_list, port_phy_el) {
+ j = 0;
+ while (sha->sas_phy[j]) {
+ if (sha->sas_phy[j] == phy)
+ break;
+ j++;
+ }
+ phyno[n] = (j >= mvi->chip->n_phy) ?
+ (j - mvi->chip->n_phy) : j;
+ num++;
+ n++;
+ }
+ break;
+ }
+ i++;
+ }
+ return num;
+}
+
+static inline void mvs_free_reg_set(struct mvs_info *mvi,
+ struct mvs_device *dev)
+{
+ if (!dev) {
+ mv_printk("device has been free.\n");
+ return;
+ }
+ if (dev->runing_req != 0)
+ return;
+ if (dev->taskfileset == MVS_ID_NOT_MAPPED)
+ return;
+ MVS_CHIP_DISP->free_reg_set(mvi, &dev->taskfileset);
+}
+
+static inline u8 mvs_assign_reg_set(struct mvs_info *mvi,
+ struct mvs_device *dev)
+{
+ if (dev->taskfileset != MVS_ID_NOT_MAPPED)
+ return 0;
+ return MVS_CHIP_DISP->assign_reg_set(mvi, &dev->taskfileset);
+}
+
+void mvs_phys_reset(struct mvs_info *mvi, u32 phy_mask, int hard)
+{
+ u32 no;
+ for_each_phy(phy_mask, phy_mask, no) {
+ if (!(phy_mask & 1))
+ continue;
+ MVS_CHIP_DISP->phy_reset(mvi, no, hard);
+ }
+}
+
+/* FIXME: locking? */
+int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
+ void *funcdata)
+{
+ int rc = 0, phy_id = sas_phy->id;
+ u32 tmp, i = 0, hi;
+ struct sas_ha_struct *sha = sas_phy->ha;
+ struct mvs_info *mvi = NULL;
+
+ while (sha->sas_phy[i]) {
+ if (sha->sas_phy[i] == sas_phy)
+ break;
+ i++;
+ }
+ hi = i/((struct mvs_prv_info *)sha->lldd_ha)->n_phy;
+ mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[hi];
+
+ switch (func) {
+ case PHY_FUNC_SET_LINK_RATE:
+ MVS_CHIP_DISP->phy_set_link_rate(mvi, phy_id, funcdata);
+ break;
+
+ case PHY_FUNC_HARD_RESET:
+ tmp = MVS_CHIP_DISP->read_phy_ctl(mvi, phy_id);
+ if (tmp & PHY_RST_HARD)
+ break;
+ MVS_CHIP_DISP->phy_reset(mvi, phy_id, 1);
+ break;
+
+ case PHY_FUNC_LINK_RESET:
+ MVS_CHIP_DISP->phy_enable(mvi, phy_id);
+ MVS_CHIP_DISP->phy_reset(mvi, phy_id, 0);
+ break;
+
+ case PHY_FUNC_DISABLE:
+ MVS_CHIP_DISP->phy_disable(mvi, phy_id);
+ break;
+ case PHY_FUNC_RELEASE_SPINUP_HOLD:
+ default:
+ rc = -EOPNOTSUPP;
+ }
+ msleep(200);
+ return rc;
+}
+
+void __devinit mvs_set_sas_addr(struct mvs_info *mvi, int port_id,
+ u32 off_lo, u32 off_hi, u64 sas_addr)
+{
+ u32 lo = (u32)sas_addr;
+ u32 hi = (u32)(sas_addr>>32);
+
+ MVS_CHIP_DISP->write_port_cfg_addr(mvi, port_id, off_lo);
+ MVS_CHIP_DISP->write_port_cfg_data(mvi, port_id, lo);
+ MVS_CHIP_DISP->write_port_cfg_addr(mvi, port_id, off_hi);
+ MVS_CHIP_DISP->write_port_cfg_data(mvi, port_id, hi);
+}
+
+static void mvs_bytes_dmaed(struct mvs_info *mvi, int i)
+{
+ struct mvs_phy *phy = &mvi->phy[i];
+ struct asd_sas_phy *sas_phy = &phy->sas_phy;
+ struct sas_ha_struct *sas_ha;
+ if (!phy->phy_attached)
+ return;
+
+ if (!(phy->att_dev_info & PORT_DEV_TRGT_MASK)
+ && phy->phy_type & PORT_TYPE_SAS) {
+ return;
+ }
+
+ sas_ha = mvi->sas;
+ sas_ha->notify_phy_event(sas_phy, PHYE_OOB_DONE);
+
+ if (sas_phy->phy) {
+ struct sas_phy *sphy = sas_phy->phy;
+
+ sphy->negotiated_linkrate = sas_phy->linkrate;
+ sphy->minimum_linkrate = phy->minimum_linkrate;
+ sphy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
+ sphy->maximum_linkrate = phy->maximum_linkrate;
+ sphy->maximum_linkrate_hw = MVS_CHIP_DISP->phy_max_link_rate();
+ }
+
+ if (phy->phy_type & PORT_TYPE_SAS) {
+ struct sas_identify_frame *id;
+
+ id = (struct sas_identify_frame *)phy->frame_rcvd;
+ id->dev_type = phy->identify.device_type;
+ id->initiator_bits = SAS_PROTOCOL_ALL;
+ id->target_bits = phy->identify.target_port_protocols;
+ } else if (phy->phy_type & PORT_TYPE_SATA) {
+ /*Nothing*/
+ }
+ mv_dprintk("phy %d byte dmaded.\n", i + mvi->id * mvi->chip->n_phy);
+
+ sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
+
+ mvi->sas->notify_port_event(sas_phy,
+ PORTE_BYTES_DMAED);
+}
+
+int mvs_slave_alloc(struct scsi_device *scsi_dev)
+{
+ struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
+ if (dev_is_sata(dev)) {
+ /* We don't need to rescan targets
+ * if REPORT_LUNS request is failed
+ */
+ if (scsi_dev->lun > 0)
+ return -ENXIO;
+ scsi_dev->tagged_supported = 1;
+ }
+
+ return sas_slave_alloc(scsi_dev);
+}
+
+int mvs_slave_configure(struct scsi_device *sdev)
+{
+ struct domain_device *dev = sdev_to_domain_dev(sdev);
+ int ret = sas_slave_configure(sdev);
+
+ if (ret)
+ return ret;
+ if (dev_is_sata(dev)) {
+ /* may set PIO mode */
+ #if MV_DISABLE_NCQ
+ struct ata_port *ap = dev->sata_dev.ap;
+ struct ata_device *adev = ap->link.device;
+ adev->flags |= ATA_DFLAG_NCQ_OFF;
+ scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, 1);
+ #endif
+ }
+ return 0;
+}
+
+void mvs_scan_start(struct Scsi_Host *shost)
+{
+ int i, j;
+ unsigned short core_nr;
+ struct mvs_info *mvi;
+ struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+
+ core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
+
+ for (j = 0; j < core_nr; j++) {
+ mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[j];
+ for (i = 0; i < mvi->chip->n_phy; ++i)
+ mvs_bytes_dmaed(mvi, i);
+ }
+}
+
+int mvs_scan_finished(struct Scsi_Host *shost, unsigned long time)
+{
+ /* give the phy enabling interrupt event time to come in (1s
+ * is empirically about all it takes) */
+ if (time < HZ)
+ return 0;
+ /* Wait for discovery to finish */
+ scsi_flush_work(shost);
+ return 1;
+}
+
+static int mvs_task_prep_smp(struct mvs_info *mvi,
+ struct mvs_task_exec_info *tei)
+{
+ int elem, rc, i;
+ struct sas_task *task = tei->task;
+ struct mvs_cmd_hdr *hdr = tei->hdr;
+ struct domain_device *dev = task->dev;
+ struct asd_sas_port *sas_port = dev->port;
+ struct scatterlist *sg_req, *sg_resp;
+ u32 req_len, resp_len, tag = tei->tag;
+ void *buf_tmp;
+ u8 *buf_oaf;
+ dma_addr_t buf_tmp_dma;
+ void *buf_prd;
+ struct mvs_slot_info *slot = &mvi->slot_info[tag];
+ u32 flags = (tei->n_elem << MCH_PRD_LEN_SHIFT);
+#if _MV_DUMP
+ u8 *buf_cmd;
+ void *from;
+#endif
+ /*
+ * DMA-map SMP request, response buffers
+ */
+ sg_req = &task->smp_task.smp_req;
+ elem = dma_map_sg(mvi->dev, sg_req, 1, PCI_DMA_TODEVICE);
+ if (!elem)
+ return -ENOMEM;
+ req_len = sg_dma_len(sg_req);
+
+ sg_resp = &task->smp_task.smp_resp;
+ elem = dma_map_sg(mvi->dev, sg_resp, 1, PCI_DMA_FROMDEVICE);
+ if (!elem) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+ resp_len = SB_RFB_MAX;
+
+ /* must be in dwords */
+ if ((req_len & 0x3) || (resp_len & 0x3)) {
+ rc = -EINVAL;
+ goto err_out_2;
+ }
+
+ /*
+ * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs
+ */
+
+ /* region 1: command table area (MVS_SSP_CMD_SZ bytes) ***** */
+ buf_tmp = slot->buf;
+ buf_tmp_dma = slot->buf_dma;
+
+#if _MV_DUMP
+ buf_cmd = buf_tmp;
+ hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma);
+ buf_tmp += req_len;
+ buf_tmp_dma += req_len;
+ slot->cmd_size = req_len;
+#else
+ hdr->cmd_tbl = cpu_to_le64(sg_dma_address(sg_req));
+#endif
+
+ /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */
+ buf_oaf = buf_tmp;
+ hdr->open_frame = cpu_to_le64(buf_tmp_dma);
+
+ buf_tmp += MVS_OAF_SZ;
+ buf_tmp_dma += MVS_OAF_SZ;
+
+ /* region 3: PRD table *********************************** */
+ buf_prd = buf_tmp;
+ if (tei->n_elem)
+ hdr->prd_tbl = cpu_to_le64(buf_tmp_dma);
+ else
+ hdr->prd_tbl = 0;
+
+ i = MVS_CHIP_DISP->prd_size() * tei->n_elem;
+ buf_tmp += i;
+ buf_tmp_dma += i;
+
+ /* region 4: status buffer (larger the PRD, smaller this buf) ****** */
+ slot->response = buf_tmp;
+ hdr->status_buf = cpu_to_le64(buf_tmp_dma);
+ if (mvi->flags & MVF_FLAG_SOC)
+ hdr->reserved[0] = 0;
+
+ /*
+ * Fill in TX ring and command slot header
+ */
+ slot->tx = mvi->tx_prod;
+ mvi->tx[mvi->tx_prod] = cpu_to_le32((TXQ_CMD_SMP << TXQ_CMD_SHIFT) |
+ TXQ_MODE_I | tag |
+ (sas_port->phy_mask << TXQ_PHY_SHIFT));
+
+ hdr->flags |= flags;
+ hdr->lens = cpu_to_le32(((resp_len / 4) << 16) | ((req_len - 4) / 4));
+ hdr->tags = cpu_to_le32(tag);
+ hdr->data_len = 0;
+
+ /* generate open address frame hdr (first 12 bytes) */
+ /* initiator, SMP, ftype 1h */
+ buf_oaf[0] = (1 << 7) | (PROTOCOL_SMP << 4) | 0x01;
+ buf_oaf[1] = dev->linkrate & 0xf;
+ *(u16 *)(buf_oaf + 2) = 0xFFFF; /* SAS SPEC */
+ memcpy(buf_oaf + 4, dev->sas_addr, SAS_ADDR_SIZE);
+
+ /* fill in PRD (scatter/gather) table, if any */
+ MVS_CHIP_DISP->make_prd(task->scatter, tei->n_elem, buf_prd);
+
+#if _MV_DUMP
+ /* copy cmd table */
+ from = kmap_atomic(sg_page(sg_req), KM_IRQ0);
+ memcpy(buf_cmd, from + sg_req->offset, req_len);
+ kunmap_atomic(from, KM_IRQ0);
+#endif
+ return 0;
+
+err_out_2:
+ dma_unmap_sg(mvi->dev, &tei->task->smp_task.smp_resp, 1,
+ PCI_DMA_FROMDEVICE);
+err_out:
+ dma_unmap_sg(mvi->dev, &tei->task->smp_task.smp_req, 1,
+ PCI_DMA_TODEVICE);
+ return rc;
+}
+
+static u32 mvs_get_ncq_tag(struct sas_task *task, u32 *tag)
+{
+ struct ata_queued_cmd *qc = task->uldd_task;
+
+ if (qc) {
+ if (qc->tf.command == ATA_CMD_FPDMA_WRITE ||
+ qc->tf.command == ATA_CMD_FPDMA_READ) {
+ *tag = qc->tag;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int mvs_task_prep_ata(struct mvs_info *mvi,
+ struct mvs_task_exec_info *tei)
+{
+ struct sas_task *task = tei->task;
+ struct domain_device *dev = task->dev;
+ struct mvs_device *mvi_dev =
+ (struct mvs_device *)dev->lldd_dev;
+ struct mvs_cmd_hdr *hdr = tei->hdr;
+ struct asd_sas_port *sas_port = dev->port;
+ struct mvs_slot_info *slot;
+ void *buf_prd;
+ u32 tag = tei->tag, hdr_tag;
+ u32 flags, del_q;
+ void *buf_tmp;
+ u8 *buf_cmd, *buf_oaf;
+ dma_addr_t buf_tmp_dma;
+ u32 i, req_len, resp_len;
+ const u32 max_resp_len = SB_RFB_MAX;
+
+ if (mvs_assign_reg_set(mvi, mvi_dev) == MVS_ID_NOT_MAPPED) {
+ mv_dprintk("Have not enough regiset for dev %d.\n",
+ mvi_dev->device_id);
+ return -EBUSY;
+ }
+ slot = &mvi->slot_info[tag];
+ slot->tx = mvi->tx_prod;
+ del_q = TXQ_MODE_I | tag |
+ (TXQ_CMD_STP << TXQ_CMD_SHIFT) |
+ (sas_port->phy_mask << TXQ_PHY_SHIFT) |
+ (mvi_dev->taskfileset << TXQ_SRS_SHIFT);
+ mvi->tx[mvi->tx_prod] = cpu_to_le32(del_q);
+
+#ifndef DISABLE_HOTPLUG_DMA_FIX
+ if (task->data_dir == DMA_FROM_DEVICE)
+ flags = (MVS_CHIP_DISP->prd_count() << MCH_PRD_LEN_SHIFT);
+ else
+ flags = (tei->n_elem << MCH_PRD_LEN_SHIFT);
+#else
+ flags = (tei->n_elem << MCH_PRD_LEN_SHIFT);
+#endif
+ if (task->ata_task.use_ncq)
+ flags |= MCH_FPDMA;
+ if (dev->sata_dev.command_set == ATAPI_COMMAND_SET) {
+ if (task->ata_task.fis.command != ATA_CMD_ID_ATAPI)
+ flags |= MCH_ATAPI;
+ }
+
+ /* FIXME: fill in port multiplier number */
+
+ hdr->flags = cpu_to_le32(flags);
+
+ /* FIXME: the low order order 5 bits for the TAG if enable NCQ */
+ if (task->ata_task.use_ncq && mvs_get_ncq_tag(task, &hdr_tag))
+ task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);
+ else
+ hdr_tag = tag;
+
+ hdr->tags = cpu_to_le32(hdr_tag);
+
+ hdr->data_len = cpu_to_le32(task->total_xfer_len);
+
+ /*
+ * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs
+ */
+
+ /* region 1: command table area (MVS_ATA_CMD_SZ bytes) ************** */
+ buf_cmd = buf_tmp = slot->buf;
+ buf_tmp_dma = slot->buf_dma;
+
+ hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma);
+
+ buf_tmp += MVS_ATA_CMD_SZ;
+ buf_tmp_dma += MVS_ATA_CMD_SZ;
+#if _MV_DUMP
+ slot->cmd_size = MVS_ATA_CMD_SZ;
+#endif
+
+ /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */
+ /* used for STP. unused for SATA? */
+ buf_oaf = buf_tmp;
+ hdr->open_frame = cpu_to_le64(buf_tmp_dma);
+
+ buf_tmp += MVS_OAF_SZ;
+ buf_tmp_dma += MVS_OAF_SZ;
+
+ /* region 3: PRD table ********************************************* */
+ buf_prd = buf_tmp;
+
+ if (tei->n_elem)
+ hdr->prd_tbl = cpu_to_le64(buf_tmp_dma);
+ else
+ hdr->prd_tbl = 0;
+ i = MVS_CHIP_DISP->prd_size() * MVS_CHIP_DISP->prd_count();
+
+ buf_tmp += i;
+ buf_tmp_dma += i;
+
+ /* region 4: status buffer (larger the PRD, smaller this buf) ****** */
+ /* FIXME: probably unused, for SATA. kept here just in case
+ * we get a STP/SATA error information record
+ */
+ slot->response = buf_tmp;
+ hdr->status_buf = cpu_to_le64(buf_tmp_dma);
+ if (mvi->flags & MVF_FLAG_SOC)
+ hdr->reserved[0] = 0;
+
+ req_len = sizeof(struct host_to_dev_fis);
+ resp_len = MVS_SLOT_BUF_SZ - MVS_ATA_CMD_SZ -
+ sizeof(struct mvs_err_info) - i;
+
+ /* request, response lengths */
+ resp_len = min(resp_len, max_resp_len);
+ hdr->lens = cpu_to_le32(((resp_len / 4) << 16) | (req_len / 4));
+
+ if (likely(!task->ata_task.device_control_reg_update))
+ task->ata_task.fis.flags |= 0x80; /* C=1: update ATA cmd reg */
+ /* fill in command FIS and ATAPI CDB */
+ memcpy(buf_cmd, &task->ata_task.fis, sizeof(struct host_to_dev_fis));
+ if (dev->sata_dev.command_set == ATAPI_COMMAND_SET)
+ memcpy(buf_cmd + STP_ATAPI_CMD,
+ task->ata_task.atapi_packet, 16);
+
+ /* generate open address frame hdr (first 12 bytes) */
+ /* initiator, STP, ftype 1h */
+ buf_oaf[0] = (1 << 7) | (PROTOCOL_STP << 4) | 0x1;
+ buf_oaf[1] = dev->linkrate & 0xf;
+ *(u16 *)(buf_oaf + 2) = cpu_to_be16(mvi_dev->device_id + 1);
+ memcpy(buf_oaf + 4, dev->sas_addr, SAS_ADDR_SIZE);
+
+ /* fill in PRD (scatter/gather) table, if any */
+ MVS_CHIP_DISP->make_prd(task->scatter, tei->n_elem, buf_prd);
+#ifndef DISABLE_HOTPLUG_DMA_FIX
+ if (task->data_dir == DMA_FROM_DEVICE)
+ MVS_CHIP_DISP->dma_fix(mvi->bulk_buffer_dma,
+ TRASH_BUCKET_SIZE, tei->n_elem, buf_prd);
+#endif
+ return 0;
+}
+
+static int mvs_task_prep_ssp(struct mvs_info *mvi,
+ struct mvs_task_exec_info *tei, int is_tmf,
+ struct mvs_tmf_task *tmf)
+{
+ struct sas_task *task = tei->task;
+ struct mvs_cmd_hdr *hdr = tei->hdr;
+ struct mvs_port *port = tei->port;
+ struct domain_device *dev = task->dev;
+ struct mvs_device *mvi_dev =
+ (struct mvs_device *)dev->lldd_dev;
+ struct asd_sas_port *sas_port = dev->port;
+ struct mvs_slot_info *slot;
+ void *buf_prd;
+ struct ssp_frame_hdr *ssp_hdr;
+ void *buf_tmp;
+ u8 *buf_cmd, *buf_oaf, fburst = 0;
+ dma_addr_t buf_tmp_dma;
+ u32 flags;
+ u32 resp_len, req_len, i, tag = tei->tag;
+ const u32 max_resp_len = SB_RFB_MAX;
+ u32 phy_mask;
+
+ slot = &mvi->slot_info[tag];
+
+ phy_mask = ((port->wide_port_phymap) ? port->wide_port_phymap :
+ sas_port->phy_mask) & TXQ_PHY_MASK;
+
+ slot->tx = mvi->tx_prod;
+ mvi->tx[mvi->tx_prod] = cpu_to_le32(TXQ_MODE_I | tag |
+ (TXQ_CMD_SSP << TXQ_CMD_SHIFT) |
+ (phy_mask << TXQ_PHY_SHIFT));
+
+ flags = MCH_RETRY;
+ if (task->ssp_task.enable_first_burst) {
+ flags |= MCH_FBURST;
+ fburst = (1 << 7);
+ }
+ hdr->flags = cpu_to_le32(flags |
+ (tei->n_elem << MCH_PRD_LEN_SHIFT) |
+ (MCH_SSP_FR_CMD << MCH_SSP_FR_TYPE_SHIFT));
+ hdr->tags = cpu_to_le32(tag);
+ hdr->data_len = cpu_to_le32(task->total_xfer_len);
+
+ /*
+ * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs
+ */
+
+ /* region 1: command table area (MVS_SSP_CMD_SZ bytes) ************** */
+ buf_cmd = buf_tmp = slot->buf;
+ buf_tmp_dma = slot->buf_dma;
+
+ hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma);
+
+ buf_tmp += MVS_SSP_CMD_SZ;
+ buf_tmp_dma += MVS_SSP_CMD_SZ;
+#if _MV_DUMP
+ slot->cmd_size = MVS_SSP_CMD_SZ;
+#endif
+
+ /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */
+ buf_oaf = buf_tmp;
+ hdr->open_frame = cpu_to_le64(buf_tmp_dma);
+
+ buf_tmp += MVS_OAF_SZ;
+ buf_tmp_dma += MVS_OAF_SZ;
+
+ /* region 3: PRD table ********************************************* */
+ buf_prd = buf_tmp;
+ if (tei->n_elem)
+ hdr->prd_tbl = cpu_to_le64(buf_tmp_dma);
+ else
+ hdr->prd_tbl = 0;
+
+ i = MVS_CHIP_DISP->prd_size() * tei->n_elem;
+ buf_tmp += i;
+ buf_tmp_dma += i;
+
+ /* region 4: status buffer (larger the PRD, smaller this buf) ****** */
+ slot->response = buf_tmp;
+ hdr->status_buf = cpu_to_le64(buf_tmp_dma);
+ if (mvi->flags & MVF_FLAG_SOC)
+ hdr->reserved[0] = 0;
+
+ resp_len = MVS_SLOT_BUF_SZ - MVS_SSP_CMD_SZ - MVS_OAF_SZ -
+ sizeof(struct mvs_err_info) - i;
+ resp_len = min(resp_len, max_resp_len);
+
+ req_len = sizeof(struct ssp_frame_hdr) + 28;
+
+ /* request, response lengths */
+ hdr->lens = cpu_to_le32(((resp_len / 4) << 16) | (req_len / 4));
+
+ /* generate open address frame hdr (first 12 bytes) */
+ /* initiator, SSP, ftype 1h */
+ buf_oaf[0] = (1 << 7) | (PROTOCOL_SSP << 4) | 0x1;
+ buf_oaf[1] = dev->linkrate & 0xf;
+ *(u16 *)(buf_oaf + 2) = cpu_to_be16(mvi_dev->device_id + 1);
+ memcpy(buf_oaf + 4, dev->sas_addr, SAS_ADDR_SIZE);
+
+ /* fill in SSP frame header (Command Table.SSP frame header) */
+ ssp_hdr = (struct ssp_frame_hdr *)buf_cmd;
+
+ if (is_tmf)
+ ssp_hdr->frame_type = SSP_TASK;
+ else
+ ssp_hdr->frame_type = SSP_COMMAND;
+
+ memcpy(ssp_hdr->hashed_dest_addr, dev->hashed_sas_addr,
+ HASHED_SAS_ADDR_SIZE);
+ memcpy(ssp_hdr->hashed_src_addr,
+ dev->hashed_sas_addr, HASHED_SAS_ADDR_SIZE);
+ ssp_hdr->tag = cpu_to_be16(tag);
+
+ /* fill in IU for TASK and Command Frame */
+ buf_cmd += sizeof(*ssp_hdr);
+ memcpy(buf_cmd, &task->ssp_task.LUN, 8);
+
+ if (ssp_hdr->frame_type != SSP_TASK) {
+ buf_cmd[9] = fburst | task->ssp_task.task_attr |
+ (task->ssp_task.task_prio << 3);
+ memcpy(buf_cmd + 12, &task->ssp_task.cdb, 16);
+ } else{
+ buf_cmd[10] = tmf->tmf;
+ switch (tmf->tmf) {
+ case TMF_ABORT_TASK:
+ case TMF_QUERY_TASK:
+ buf_cmd[12] =
+ (tmf->tag_of_task_to_be_managed >> 8) & 0xff;
+ buf_cmd[13] =
+ tmf->tag_of_task_to_be_managed & 0xff;
+ break;
+ default:
+ break;
+ }
+ }
+ /* fill in PRD (scatter/gather) table, if any */
+ MVS_CHIP_DISP->make_prd(task->scatter, tei->n_elem, buf_prd);
+ return 0;
+}
+
+#define DEV_IS_GONE(mvi_dev) ((!mvi_dev || (mvi_dev->dev_type == NO_DEVICE)))
+static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
+ struct completion *completion, int lock,
+ int is_tmf, struct mvs_tmf_task *tmf)
+{
+ struct domain_device *dev = task->dev;
+ struct mvs_info *mvi;
+ struct mvs_device *mvi_dev;
+ struct mvs_task_exec_info tei;
+ struct sas_task *t = task;
+ struct mvs_slot_info *slot;
+ u32 tag = 0xdeadbeef, rc, n_elem = 0;
+ u32 n = num, pass = 0;
+ unsigned long flags = 0;
+
+ if (!dev->port) {
+ struct task_status_struct *tsm = &t->task_status;
+
+ tsm->resp = SAS_TASK_UNDELIVERED;
+ tsm->stat = SAS_PHY_DOWN;
+ t->task_done(t);
+ return 0;
+ }
+
+ mvi = mvs_find_dev_mvi(task->dev);
+
+ if (lock)
+ spin_lock_irqsave(&mvi->lock, flags);
+ do {
+ dev = t->dev;
+ mvi_dev = (struct mvs_device *)dev->lldd_dev;
+ if (DEV_IS_GONE(mvi_dev)) {
+ if (mvi_dev)
+ mv_dprintk("device %d not ready.\n",
+ mvi_dev->device_id);
+ else
+ mv_dprintk("device %016llx not ready.\n",
+ SAS_ADDR(dev->sas_addr));
+
+ rc = SAS_PHY_DOWN;
+ goto out_done;
+ }
+
+ if (dev->port->id >= mvi->chip->n_phy)
+ tei.port = &mvi->port[dev->port->id - mvi->chip->n_phy];
+ else
+ tei.port = &mvi->port[dev->port->id];
+
+ if (!tei.port->port_attached) {
+ if (sas_protocol_ata(t->task_proto)) {
+ mv_dprintk("port %d does not"
+ "attached device.\n", dev->port->id);
+ rc = SAS_PHY_DOWN;
+ goto out_done;
+ } else {
+ struct task_status_struct *ts = &t->task_status;
+ ts->resp = SAS_TASK_UNDELIVERED;
+ ts->stat = SAS_PHY_DOWN;
+ t->task_done(t);
+ if (n > 1)
+ t = list_entry(t->list.next,
+ struct sas_task, list);
+ continue;
+ }
+ }
+
+ if (!sas_protocol_ata(t->task_proto)) {
+ if (t->num_scatter) {
+ n_elem = dma_map_sg(mvi->dev,
+ t->scatter,
+ t->num_scatter,
+ t->data_dir);
+ if (!n_elem) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+ }
+ } else {
+ n_elem = t->num_scatter;
+ }
+
+ rc = mvs_tag_alloc(mvi, &tag);
+ if (rc)
+ goto err_out;
+
+ slot = &mvi->slot_info[tag];
+
+
+ t->lldd_task = NULL;
+ slot->n_elem = n_elem;
+ slot->slot_tag = tag;
+ memset(slot->buf, 0, MVS_SLOT_BUF_SZ);
+
+ tei.task = t;
+ tei.hdr = &mvi->slot[tag];
+ tei.tag = tag;
+ tei.n_elem = n_elem;
+ switch (t->task_proto) {
+ case SAS_PROTOCOL_SMP:
+ rc = mvs_task_prep_smp(mvi, &tei);
+ break;
+ case SAS_PROTOCOL_SSP:
+ rc = mvs_task_prep_ssp(mvi, &tei, is_tmf, tmf);
+ break;
+ case SAS_PROTOCOL_SATA:
+ case SAS_PROTOCOL_STP:
+ case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
+ rc = mvs_task_prep_ata(mvi, &tei);
+ break;
+ default:
+ dev_printk(KERN_ERR, mvi->dev,
+ "unknown sas_task proto: 0x%x\n",
+ t->task_proto);
+ rc = -EINVAL;
+ break;
+ }
+
+ if (rc) {
+ mv_dprintk("rc is %x\n", rc);
+ goto err_out_tag;
+ }
+ slot->task = t;
+ slot->port = tei.port;
+ t->lldd_task = (void *) slot;
+ list_add_tail(&slot->entry, &tei.port->list);
+ /* TODO: select normal or high priority */
+ spin_lock(&t->task_state_lock);
+ t->task_state_flags |= SAS_TASK_AT_INITIATOR;
+ spin_unlock(&t->task_state_lock);
+
+ mvs_hba_memory_dump(mvi, tag, t->task_proto);
+ mvi_dev->runing_req++;
+ ++pass;
+ mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1);
+ if (n > 1)
+ t = list_entry(t->list.next, struct sas_task, list);
+ } while (--n);
+ rc = 0;
+ goto out_done;
+
+err_out_tag:
+ mvs_tag_free(mvi, tag);
+err_out:
+
+ dev_printk(KERN_ERR, mvi->dev, "mvsas exec failed[%d]!\n", rc);
+ if (!sas_protocol_ata(t->task_proto))
+ if (n_elem)
+ dma_unmap_sg(mvi->dev, t->scatter, n_elem,
+ t->data_dir);
+out_done:
+ if (likely(pass)) {
+ MVS_CHIP_DISP->start_delivery(mvi,
+ (mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1));
+ }
+ if (lock)
+ spin_unlock_irqrestore(&mvi->lock, flags);
+ return rc;
+}
+
+int mvs_queue_command(struct sas_task *task, const int num,
+ gfp_t gfp_flags)
+{
+ return mvs_task_exec(task, num, gfp_flags, NULL, 1, 0, NULL);
+}
+
+static void mvs_slot_free(struct mvs_info *mvi, u32 rx_desc)
+{
+ u32 slot_idx = rx_desc & RXQ_SLOT_MASK;
+ mvs_tag_clear(mvi, slot_idx);
+}
+
+static void mvs_slot_task_free(struct mvs_info *mvi, struct sas_task *task,
+ struct mvs_slot_info *slot, u32 slot_idx)
+{
+ if (!slot->task)
+ return;
+ if (!sas_protocol_ata(task->task_proto))
+ if (slot->n_elem)
+ dma_unmap_sg(mvi->dev, task->scatter,
+ slot->n_elem, task->data_dir);
+
+ switch (task->task_proto) {
+ case SAS_PROTOCOL_SMP:
+ dma_unmap_sg(mvi->dev, &task->smp_task.smp_resp, 1,
+ PCI_DMA_FROMDEVICE);
+ dma_unmap_sg(mvi->dev, &task->smp_task.smp_req, 1,
+ PCI_DMA_TODEVICE);
+ break;
+
+ case SAS_PROTOCOL_SATA:
+ case SAS_PROTOCOL_STP:
+ case SAS_PROTOCOL_SSP:
+ default:
+ /* do nothing */
+ break;
+ }
+ list_del_init(&slot->entry);
+ task->lldd_task = NULL;
+ slot->task = NULL;
+ slot->port = NULL;
+ slot->slot_tag = 0xFFFFFFFF;
+ mvs_slot_free(mvi, slot_idx);
+}
+
+static void mvs_update_wideport(struct mvs_info *mvi, int i)
+{
+ struct mvs_phy *phy = &mvi->phy[i];
+ struct mvs_port *port = phy->port;
+ int j, no;
+
+ for_each_phy(port->wide_port_phymap, j, no) {
+ if (j & 1) {
+ MVS_CHIP_DISP->write_port_cfg_addr(mvi, no,
+ PHYR_WIDE_PORT);
+ MVS_CHIP_DISP->write_port_cfg_data(mvi, no,
+ port->wide_port_phymap);
+ } else {
+ MVS_CHIP_DISP->write_port_cfg_addr(mvi, no,
+ PHYR_WIDE_PORT);
+ MVS_CHIP_DISP->write_port_cfg_data(mvi, no,
+ 0);
+ }
+ }
+}
+
+static u32 mvs_is_phy_ready(struct mvs_info *mvi, int i)
+{
+ u32 tmp;
+ struct mvs_phy *phy = &mvi->phy[i];
+ struct mvs_port *port = phy->port;
+
+ tmp = MVS_CHIP_DISP->read_phy_ctl(mvi, i);
+ if ((tmp & PHY_READY_MASK) && !(phy->irq_status & PHYEV_POOF)) {
+ if (!port)
+ phy->phy_attached = 1;
+ return tmp;
+ }
+
+ if (port) {
+ if (phy->phy_type & PORT_TYPE_SAS) {
+ port->wide_port_phymap &= ~(1U << i);
+ if (!port->wide_port_phymap)
+ port->port_attached = 0;
+ mvs_update_wideport(mvi, i);
+ } else if (phy->phy_type & PORT_TYPE_SATA)
+ port->port_attached = 0;
+ phy->port = NULL;
+ phy->phy_attached = 0;
+ phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA);
+ }
+ return 0;
+}
+
+static void *mvs_get_d2h_reg(struct mvs_info *mvi, int i, void *buf)
+{
+ u32 *s = (u32 *) buf;
+
+ if (!s)
+ return NULL;
+
+ MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG3);
+ s[3] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i);
+
+ MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG2);
+ s[2] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i);
+
+ MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG1);
+ s[1] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i);
+
+ MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG0);
+ s[0] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i);
+
+ /* Workaround: take some ATAPI devices for ATA */
+ if (((s[1] & 0x00FFFFFF) == 0x00EB1401) && (*(u8 *)&s[3] == 0x01))
+ s[1] = 0x00EB1401 | (*((u8 *)&s[1] + 3) & 0x10);
+
+ return (void *)s;
+}
+
+static u32 mvs_is_sig_fis_received(u32 irq_status)
+{
+ return irq_status & PHYEV_SIG_FIS;
+}
+
+void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st)
+{
+ struct mvs_phy *phy = &mvi->phy[i];
+ struct sas_identify_frame *id;
+
+ id = (struct sas_identify_frame *)phy->frame_rcvd;
+
+ if (get_st) {
+ phy->irq_status = MVS_CHIP_DISP->read_port_irq_stat(mvi, i);
+ phy->phy_status = mvs_is_phy_ready(mvi, i);
+ }
+
+ if (phy->phy_status) {
+ int oob_done = 0;
+ struct asd_sas_phy *sas_phy = &mvi->phy[i].sas_phy;
+
+ oob_done = MVS_CHIP_DISP->oob_done(mvi, i);
+
+ MVS_CHIP_DISP->fix_phy_info(mvi, i, id);
+ if (phy->phy_type & PORT_TYPE_SATA) {
+ phy->identify.target_port_protocols = SAS_PROTOCOL_STP;
+ if (mvs_is_sig_fis_received(phy->irq_status)) {
+ phy->phy_attached = 1;
+ phy->att_dev_sas_addr =
+ i + mvi->id * mvi->chip->n_phy;
+ if (oob_done)
+ sas_phy->oob_mode = SATA_OOB_MODE;
+ phy->frame_rcvd_size =
+ sizeof(struct dev_to_host_fis);
+ mvs_get_d2h_reg(mvi, i, (void *)id);
+ } else {
+ u32 tmp;
+ dev_printk(KERN_DEBUG, mvi->dev,
+ "Phy%d : No sig fis\n", i);
+ tmp = MVS_CHIP_DISP->read_port_irq_mask(mvi, i);
+ MVS_CHIP_DISP->write_port_irq_mask(mvi, i,
+ tmp | PHYEV_SIG_FIS);
+ phy->phy_attached = 0;
+ phy->phy_type &= ~PORT_TYPE_SATA;
+ MVS_CHIP_DISP->phy_reset(mvi, i, 0);
+ goto out_done;
+ }
+ } else if (phy->phy_type & PORT_TYPE_SAS
+ || phy->att_dev_info & PORT_SSP_INIT_MASK) {
+ phy->phy_attached = 1;
+ phy->identify.device_type =
+ phy->att_dev_info & PORT_DEV_TYPE_MASK;
+
+ if (phy->identify.device_type == SAS_END_DEV)
+ phy->identify.target_port_protocols =
+ SAS_PROTOCOL_SSP;
+ else if (phy->identify.device_type != NO_DEVICE)
+ phy->identify.target_port_protocols =
+ SAS_PROTOCOL_SMP;
+ if (oob_done)
+ sas_phy->oob_mode = SAS_OOB_MODE;
+ phy->frame_rcvd_size =
+ sizeof(struct sas_identify_frame);
+ }
+ memcpy(sas_phy->attached_sas_addr,
+ &phy->att_dev_sas_addr, SAS_ADDR_SIZE);
+
+ if (MVS_CHIP_DISP->phy_work_around)
+ MVS_CHIP_DISP->phy_work_around(mvi, i);
+ }
+ mv_dprintk("port %d attach dev info is %x\n",
+ i + mvi->id * mvi->chip->n_phy, phy->att_dev_info);
+ mv_dprintk("port %d attach sas addr is %llx\n",
+ i + mvi->id * mvi->chip->n_phy, phy->att_dev_sas_addr);
+out_done:
+ if (get_st)
+ MVS_CHIP_DISP->write_port_irq_stat(mvi, i, phy->irq_status);
+}
+
+static void mvs_port_notify_formed(struct asd_sas_phy *sas_phy, int lock)
+{
+ struct sas_ha_struct *sas_ha = sas_phy->ha;
+ struct mvs_info *mvi = NULL; int i = 0, hi;
+ struct mvs_phy *phy = sas_phy->lldd_phy;
+ struct asd_sas_port *sas_port = sas_phy->port;
+ struct mvs_port *port;
+ unsigned long flags = 0;
+ if (!sas_port)
+ return;
+
+ while (sas_ha->sas_phy[i]) {
+ if (sas_ha->sas_phy[i] == sas_phy)
+ break;
+ i++;
+ }
+ hi = i/((struct mvs_prv_info *)sas_ha->lldd_ha)->n_phy;
+ mvi = ((struct mvs_prv_info *)sas_ha->lldd_ha)->mvi[hi];
+ if (sas_port->id >= mvi->chip->n_phy)
+ port = &mvi->port[sas_port->id - mvi->chip->n_phy];
+ else
+ port = &mvi->port[sas_port->id];
+ if (lock)
+ spin_lock_irqsave(&mvi->lock, flags);
+ port->port_attached = 1;
+ phy->port = port;
+ if (phy->phy_type & PORT_TYPE_SAS) {
+ port->wide_port_phymap = sas_port->phy_mask;
+ mv_printk("set wide port phy map %x\n", sas_port->phy_mask);
+ mvs_update_wideport(mvi, sas_phy->id);
+ }
+ if (lock)
+ spin_unlock_irqrestore(&mvi->lock, flags);
+}
+
+static void mvs_port_notify_deformed(struct asd_sas_phy *sas_phy, int lock)
+{
+ /*Nothing*/
+}
+
+
+void mvs_port_formed(struct asd_sas_phy *sas_phy)
+{
+ mvs_port_notify_formed(sas_phy, 1);
+}
+
+void mvs_port_deformed(struct asd_sas_phy *sas_phy)
+{
+ mvs_port_notify_deformed(sas_phy, 1);
+}
+
+struct mvs_device *mvs_alloc_dev(struct mvs_info *mvi)
+{
+ u32 dev;
+ for (dev = 0; dev < MVS_MAX_DEVICES; dev++) {
+ if (mvi->devices[dev].dev_type == NO_DEVICE) {
+ mvi->devices[dev].device_id = dev;
+ return &mvi->devices[dev];
+ }
+ }
+
+ if (dev == MVS_MAX_DEVICES)
+ mv_printk("max support %d devices, ignore ..\n",
+ MVS_MAX_DEVICES);
+
+ return NULL;
+}
+
+void mvs_free_dev(struct mvs_device *mvi_dev)
+{
+ u32 id = mvi_dev->device_id;
+ memset(mvi_dev, 0, sizeof(*mvi_dev));
+ mvi_dev->device_id = id;
+ mvi_dev->dev_type = NO_DEVICE;
+ mvi_dev->dev_status = MVS_DEV_NORMAL;
+ mvi_dev->taskfileset = MVS_ID_NOT_MAPPED;
+}
+
+int mvs_dev_found_notify(struct domain_device *dev, int lock)
+{
+ unsigned long flags = 0;
+ int res = 0;
+ struct mvs_info *mvi = NULL;
+ struct domain_device *parent_dev = dev->parent;
+ struct mvs_device *mvi_device;
+
+ mvi = mvs_find_dev_mvi(dev);
+
+ if (lock)
+ spin_lock_irqsave(&mvi->lock, flags);
+
+ mvi_device = mvs_alloc_dev(mvi);
+ if (!mvi_device) {
+ res = -1;
+ goto found_out;
+ }
+ dev->lldd_dev = (void *)mvi_device;
+ mvi_device->dev_type = dev->dev_type;
+
+ if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) {
+ int phy_id;
+ u8 phy_num = parent_dev->ex_dev.num_phys;
+ struct ex_phy *phy;
+ for (phy_id = 0; phy_id < phy_num; phy_id++) {
+ phy = &parent_dev->ex_dev.ex_phy[phy_id];
+ if (SAS_ADDR(phy->attached_sas_addr) ==
+ SAS_ADDR(dev->sas_addr)) {
+ mvi_device->attached_phy = phy_id;
+ break;
+ }
+ }
+
+ if (phy_id == phy_num) {
+ mv_printk("Error: no attached dev:%016llx"
+ "at ex:%016llx.\n",
+ SAS_ADDR(dev->sas_addr),
+ SAS_ADDR(parent_dev->sas_addr));
+ res = -1;
+ }
+ }
+
+found_out:
+ if (lock)
+ spin_unlock_irqrestore(&mvi->lock, flags);
+ return res;
+}
+
+int mvs_dev_found(struct domain_device *dev)
+{
+ return mvs_dev_found_notify(dev, 1);
+}
+
+void mvs_dev_gone_notify(struct domain_device *dev, int lock)
+{
+ unsigned long flags = 0;
+ struct mvs_info *mvi;
+ struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev;
+
+ mvi = mvs_find_dev_mvi(dev);
+
+ if (lock)
+ spin_lock_irqsave(&mvi->lock, flags);
+
+ if (mvi_dev) {
+ mv_dprintk("found dev[%d:%x] is gone.\n",
+ mvi_dev->device_id, mvi_dev->dev_type);
+ mvs_free_reg_set(mvi, mvi_dev);
+ mvs_free_dev(mvi_dev);
+ } else {
+ mv_dprintk("found dev has gone.\n");
+ }
+ dev->lldd_dev = NULL;
+
+ if (lock)
+ spin_unlock_irqrestore(&mvi->lock, flags);
+}
+
+
+void mvs_dev_gone(struct domain_device *dev)
+{
+ mvs_dev_gone_notify(dev, 1);
+}
+
+static struct sas_task *mvs_alloc_task(void)
+{
+ struct sas_task *task = kzalloc(sizeof(struct sas_task), GFP_KERNEL);
+
+ if (task) {
+ INIT_LIST_HEAD(&task->list);
+ spin_lock_init(&task->task_state_lock);
+ task->task_state_flags = SAS_TASK_STATE_PENDING;
+ init_timer(&task->timer);
+ init_completion(&task->completion);
+ }
+ return task;
+}
+
+static void mvs_free_task(struct sas_task *task)
+{
+ if (task) {
+ BUG_ON(!list_empty(&task->list));
+ kfree(task);
+ }
+}
+
+static void mvs_task_done(struct sas_task *task)
+{
+ if (!del_timer(&task->timer))
+ return;
+ complete(&task->completion);
+}
+
+static void mvs_tmf_timedout(unsigned long data)
+{
+ struct sas_task *task = (struct sas_task *)data;
+
+ task->task_state_flags |= SAS_TASK_STATE_ABORTED;
+ complete(&task->completion);
+}
+
+/* XXX */
+#define MVS_TASK_TIMEOUT 20
+static int mvs_exec_internal_tmf_task(struct domain_device *dev,
+ void *parameter, u32 para_len, struct mvs_tmf_task *tmf)
+{
+ int res, retry;
+ struct sas_task *task = NULL;
+
+ for (retry = 0; retry < 3; retry++) {
+ task = mvs_alloc_task();
+ if (!task)
+ return -ENOMEM;
+
+ task->dev = dev;
+ task->task_proto = dev->tproto;
+
+ memcpy(&task->ssp_task, parameter, para_len);
+ task->task_done = mvs_task_done;
+
+ task->timer.data = (unsigned long) task;
+ task->timer.function = mvs_tmf_timedout;
+ task->timer.expires = jiffies + MVS_TASK_TIMEOUT*HZ;
+ add_timer(&task->timer);
+
+ res = mvs_task_exec(task, 1, GFP_KERNEL, NULL, 0, 1, tmf);
+
+ if (res) {
+ del_timer(&task->timer);
+ mv_printk("executing internel task failed:%d\n", res);
+ goto ex_err;
+ }
+
+ wait_for_completion(&task->completion);
+ res = -TMF_RESP_FUNC_FAILED;
+ /* Even TMF timed out, return direct. */
+ if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
+ if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
+ mv_printk("TMF task[%x] timeout.\n", tmf->tmf);
+ goto ex_err;
+ }
+ }
+
+ if (task->task_status.resp == SAS_TASK_COMPLETE &&
+ task->task_status.stat == SAM_GOOD) {
+ res = TMF_RESP_FUNC_COMPLETE;
+ break;
+ }
+
+ if (task->task_status.resp == SAS_TASK_COMPLETE &&
+ task->task_status.stat == SAS_DATA_UNDERRUN) {
+ /* no error, but return the number of bytes of
+ * underrun */
+ res = task->task_status.residual;
+ break;
+ }
+
+ if (task->task_status.resp == SAS_TASK_COMPLETE &&
+ task->task_status.stat == SAS_DATA_OVERRUN) {
+ mv_dprintk("blocked task error.\n");
+ res = -EMSGSIZE;
+ break;
+ } else {
+ mv_dprintk(" task to dev %016llx response: 0x%x "
+ "status 0x%x\n",
+ SAS_ADDR(dev->sas_addr),
+ task->task_status.resp,
+ task->task_status.stat);
+ mvs_free_task(task);
+ task = NULL;
+
+ }
+ }
+ex_err:
+ BUG_ON(retry == 3 && task != NULL);
+ if (task != NULL)
+ mvs_free_task(task);
+ return res;
+}
+
+static int mvs_debug_issue_ssp_tmf(struct domain_device *dev,
+ u8 *lun, struct mvs_tmf_task *tmf)
+{
+ struct sas_ssp_task ssp_task;
+ DECLARE_COMPLETION_ONSTACK(completion);
+ if (!(dev->tproto & SAS_PROTOCOL_SSP))
+ return TMF_RESP_FUNC_ESUPP;
+
+ strncpy((u8 *)&ssp_task.LUN, lun, 8);
+
+ return mvs_exec_internal_tmf_task(dev, &ssp_task,
+ sizeof(ssp_task), tmf);
+}
+
+
+/* Standard mandates link reset for ATA (type 0)
+ and hard reset for SSP (type 1) , only for RECOVERY */
+static int mvs_debug_I_T_nexus_reset(struct domain_device *dev)
+{
+ int rc;
+ struct sas_phy *phy = sas_find_local_phy(dev);
+ int reset_type = (dev->dev_type == SATA_DEV ||
+ (dev->tproto & SAS_PROTOCOL_STP)) ? 0 : 1;
+ rc = sas_phy_reset(phy, reset_type);
+ msleep(2000);
+ return rc;
+}
+
+/* mandatory SAM-3 */
+int mvs_lu_reset(struct domain_device *dev, u8 *lun)
+{
+ unsigned long flags;
+ int i, phyno[WIDE_PORT_MAX_PHY], num , rc = TMF_RESP_FUNC_FAILED;
+ struct mvs_tmf_task tmf_task;
+ struct mvs_info *mvi = mvs_find_dev_mvi(dev);
+ struct mvs_device * mvi_dev = (struct mvs_device *)dev->lldd_dev;
+
+ tmf_task.tmf = TMF_LU_RESET;
+ mvi_dev->dev_status = MVS_DEV_EH;
+ rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task);
+ if (rc == TMF_RESP_FUNC_COMPLETE) {
+ num = mvs_find_dev_phyno(dev, phyno);
+ spin_lock_irqsave(&mvi->lock, flags);
+ for (i = 0; i < num; i++)
+ mvs_release_task(mvi, phyno[i], dev);
+ spin_unlock_irqrestore(&mvi->lock, flags);
+ }
+ /* If failed, fall-through I_T_Nexus reset */
+ mv_printk("%s for device[%x]:rc= %d\n", __func__,
+ mvi_dev->device_id, rc);
+ return rc;
+}
+
+int mvs_I_T_nexus_reset(struct domain_device *dev)
+{
+ unsigned long flags;
+ int i, phyno[WIDE_PORT_MAX_PHY], num , rc = TMF_RESP_FUNC_FAILED;
+ struct mvs_info *mvi = mvs_find_dev_mvi(dev);
+ struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev;
+
+ if (mvi_dev->dev_status != MVS_DEV_EH)
+ return TMF_RESP_FUNC_COMPLETE;
+ rc = mvs_debug_I_T_nexus_reset(dev);
+ mv_printk("%s for device[%x]:rc= %d\n",
+ __func__, mvi_dev->device_id, rc);
+
+ /* housekeeper */
+ num = mvs_find_dev_phyno(dev, phyno);
+ spin_lock_irqsave(&mvi->lock, flags);
+ for (i = 0; i < num; i++)
+ mvs_release_task(mvi, phyno[i], dev);
+ spin_unlock_irqrestore(&mvi->lock, flags);
+
+ return rc;
+}
+/* optional SAM-3 */
+int mvs_query_task(struct sas_task *task)
+{
+ u32 tag;
+ struct scsi_lun lun;
+ struct mvs_tmf_task tmf_task;
+ int rc = TMF_RESP_FUNC_FAILED;
+
+ if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) {
+ struct scsi_cmnd * cmnd = (struct scsi_cmnd *)task->uldd_task;
+ struct domain_device *dev = task->dev;
+ struct mvs_info *mvi = mvs_find_dev_mvi(dev);
+
+ int_to_scsilun(cmnd->device->lun, &lun);
+ rc = mvs_find_tag(mvi, task, &tag);
+ if (rc == 0) {
+ rc = TMF_RESP_FUNC_FAILED;
+ return rc;
+ }
+
+ tmf_task.tmf = TMF_QUERY_TASK;
+ tmf_task.tag_of_task_to_be_managed = cpu_to_le16(tag);
+
+ rc = mvs_debug_issue_ssp_tmf(dev, lun.scsi_lun, &tmf_task);
+ switch (rc) {
+ /* The task is still in Lun, release it then */
+ case TMF_RESP_FUNC_SUCC:
+ /* The task is not in Lun or failed, reset the phy */
+ case TMF_RESP_FUNC_FAILED:
+ case TMF_RESP_FUNC_COMPLETE:
+ break;
+ }
+ }
+ mv_printk("%s:rc= %d\n", __func__, rc);
+ return rc;
+}
+
+/* mandatory SAM-3, still need free task/slot info */
+int mvs_abort_task(struct sas_task *task)
+{
+ struct scsi_lun lun;
+ struct mvs_tmf_task tmf_task;
+ struct domain_device *dev = task->dev;
+ struct mvs_info *mvi = mvs_find_dev_mvi(dev);
+ int rc = TMF_RESP_FUNC_FAILED;
+ unsigned long flags;
+ u32 tag;
+ if (mvi->exp_req)
+ mvi->exp_req--;
+ spin_lock_irqsave(&task->task_state_lock, flags);
+ if (task->task_state_flags & SAS_TASK_STATE_DONE) {
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+ rc = TMF_RESP_FUNC_COMPLETE;
+ goto out;
+ }
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+ if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) {
+ struct scsi_cmnd * cmnd = (struct scsi_cmnd *)task->uldd_task;
+
+ int_to_scsilun(cmnd->device->lun, &lun);
+ rc = mvs_find_tag(mvi, task, &tag);
+ if (rc == 0) {
+ mv_printk("No such tag in %s\n", __func__);
+ rc = TMF_RESP_FUNC_FAILED;
+ return rc;
+ }
+
+ tmf_task.tmf = TMF_ABORT_TASK;
+ tmf_task.tag_of_task_to_be_managed = cpu_to_le16(tag);
+
+ rc = mvs_debug_issue_ssp_tmf(dev, lun.scsi_lun, &tmf_task);
+
+ /* if successful, clear the task and callback forwards.*/
+ if (rc == TMF_RESP_FUNC_COMPLETE) {
+ u32 slot_no;
+ struct mvs_slot_info *slot;
+ struct mvs_info *mvi = mvs_find_dev_mvi(dev);
+
+ if (task->lldd_task) {
+ slot = (struct mvs_slot_info *)task->lldd_task;
+ slot_no = (u32) (slot - mvi->slot_info);
+ mvs_slot_complete(mvi, slot_no, 1);
+ }
+ }
+ } else if (task->task_proto & SAS_PROTOCOL_SATA ||
+ task->task_proto & SAS_PROTOCOL_STP) {
+ /* to do free register_set */
+ } else {
+ /* SMP */
+
+ }
+out:
+ if (rc != TMF_RESP_FUNC_COMPLETE)
+ mv_printk("%s:rc= %d\n", __func__, rc);
+ return rc;
+}
+
+int mvs_abort_task_set(struct domain_device *dev, u8 *lun)
+{
+ int rc = TMF_RESP_FUNC_FAILED;
+ struct mvs_tmf_task tmf_task;
+
+ tmf_task.tmf = TMF_ABORT_TASK_SET;
+ rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task);
+
+ return rc;
+}
+
+int mvs_clear_aca(struct domain_device *dev, u8 *lun)
+{
+ int rc = TMF_RESP_FUNC_FAILED;
+ struct mvs_tmf_task tmf_task;
+
+ tmf_task.tmf = TMF_CLEAR_ACA;
+ rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task);
+
+ return rc;
+}
+
+int mvs_clear_task_set(struct domain_device *dev, u8 *lun)
+{
+ int rc = TMF_RESP_FUNC_FAILED;
+ struct mvs_tmf_task tmf_task;
+
+ tmf_task.tmf = TMF_CLEAR_TASK_SET;
+ rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task);
+
+ return rc;
+}
+
+static int mvs_sata_done(struct mvs_info *mvi, struct sas_task *task,
+ u32 slot_idx, int err)
+{
+ struct mvs_device *mvi_dev = (struct mvs_device *)task->dev->lldd_dev;
+ struct task_status_struct *tstat = &task->task_status;
+ struct ata_task_resp *resp = (struct ata_task_resp *)tstat->buf;
+ int stat = SAM_GOOD;
+
+
+ resp->frame_len = sizeof(struct dev_to_host_fis);
+ memcpy(&resp->ending_fis[0],
+ SATA_RECEIVED_D2H_FIS(mvi_dev->taskfileset),
+ sizeof(struct dev_to_host_fis));
+ tstat->buf_valid_size = sizeof(*resp);
+ if (unlikely(err))
+ stat = SAS_PROTO_RESPONSE;
+ return stat;
+}
+
+static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,
+ u32 slot_idx)
+{
+ struct mvs_slot_info *slot = &mvi->slot_info[slot_idx];
+ int stat;
+ u32 err_dw0 = le32_to_cpu(*(u32 *) (slot->response));
+ u32 tfs = 0;
+ enum mvs_port_type type = PORT_TYPE_SAS;
+
+ if (err_dw0 & CMD_ISS_STPD)
+ MVS_CHIP_DISP->issue_stop(mvi, type, tfs);
+
+ MVS_CHIP_DISP->command_active(mvi, slot_idx);
+
+ stat = SAM_CHECK_COND;
+ switch (task->task_proto) {
+ case SAS_PROTOCOL_SSP:
+ stat = SAS_ABORTED_TASK;
+ break;
+ case SAS_PROTOCOL_SMP:
+ stat = SAM_CHECK_COND;
+ break;
+
+ case SAS_PROTOCOL_SATA:
+ case SAS_PROTOCOL_STP:
+ case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
+ {
+ if (err_dw0 == 0x80400002)
+ mv_printk("find reserved error, why?\n");
+
+ task->ata_task.use_ncq = 0;
+ stat = SAS_PROTO_RESPONSE;
+ mvs_sata_done(mvi, task, slot_idx, 1);
+
+ }
+ break;
+ default:
+ break;
+ }
+
+ return stat;
+}
+
+int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
+{
+ u32 slot_idx = rx_desc & RXQ_SLOT_MASK;
+ struct mvs_slot_info *slot = &mvi->slot_info[slot_idx];
+ struct sas_task *task = slot->task;
+ struct mvs_device *mvi_dev = NULL;
+ struct task_status_struct *tstat;
+
+ bool aborted;
+ void *to;
+ enum exec_status sts;
+
+ if (mvi->exp_req)
+ mvi->exp_req--;
+ if (unlikely(!task || !task->lldd_task))
+ return -1;
+
+ tstat = &task->task_status;
+ mvi_dev = (struct mvs_device *)task->dev->lldd_dev;
+
+ mvs_hba_cq_dump(mvi);
+
+ spin_lock(&task->task_state_lock);
+ task->task_state_flags &=
+ ~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR);
+ task->task_state_flags |= SAS_TASK_STATE_DONE;
+ /* race condition*/
+ aborted = task->task_state_flags & SAS_TASK_STATE_ABORTED;
+ spin_unlock(&task->task_state_lock);
+
+ memset(tstat, 0, sizeof(*tstat));
+ tstat->resp = SAS_TASK_COMPLETE;
+
+ if (unlikely(aborted)) {
+ tstat->stat = SAS_ABORTED_TASK;
+ if (mvi_dev)
+ mvi_dev->runing_req--;
+ if (sas_protocol_ata(task->task_proto))
+ mvs_free_reg_set(mvi, mvi_dev);
+
+ mvs_slot_task_free(mvi, task, slot, slot_idx);
+ return -1;
+ }
+
+ if (unlikely(!mvi_dev || !slot->port->port_attached || flags)) {
+ mv_dprintk("port has not device.\n");
+ tstat->stat = SAS_PHY_DOWN;
+ goto out;
+ }
+
+ /*
+ if (unlikely((rx_desc & RXQ_ERR) || (*(u64 *) slot->response))) {
+ mv_dprintk("Find device[%016llx] RXQ_ERR %X,
+ err info:%016llx\n",
+ SAS_ADDR(task->dev->sas_addr),
+ rx_desc, (u64)(*(u64 *) slot->response));
+ }
+ */
+
+ /* error info record present */
+ if (unlikely((rx_desc & RXQ_ERR) && (*(u64 *) slot->response))) {
+ tstat->stat = mvs_slot_err(mvi, task, slot_idx);
+ goto out;
+ }
+
+ switch (task->task_proto) {
+ case SAS_PROTOCOL_SSP:
+ /* hw says status == 0, datapres == 0 */
+ if (rx_desc & RXQ_GOOD) {
+ tstat->stat = SAM_GOOD;
+ tstat->resp = SAS_TASK_COMPLETE;
+ }
+ /* response frame present */
+ else if (rx_desc & RXQ_RSP) {
+ struct ssp_response_iu *iu = slot->response +
+ sizeof(struct mvs_err_info);
+ sas_ssp_task_response(mvi->dev, task, iu);
+ } else
+ tstat->stat = SAM_CHECK_COND;
+ break;
+
+ case SAS_PROTOCOL_SMP: {
+ struct scatterlist *sg_resp = &task->smp_task.smp_resp;
+ tstat->stat = SAM_GOOD;
+ to = kmap_atomic(sg_page(sg_resp), KM_IRQ0);
+ memcpy(to + sg_resp->offset,
+ slot->response + sizeof(struct mvs_err_info),
+ sg_dma_len(sg_resp));
+ kunmap_atomic(to, KM_IRQ0);
+ break;
+ }
+
+ case SAS_PROTOCOL_SATA:
+ case SAS_PROTOCOL_STP:
+ case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: {
+ tstat->stat = mvs_sata_done(mvi, task, slot_idx, 0);
+ break;
+ }
+
+ default:
+ tstat->stat = SAM_CHECK_COND;
+ break;
+ }
+
+out:
+ if (mvi_dev)
+ mvi_dev->runing_req--;
+ if (sas_protocol_ata(task->task_proto))
+ mvs_free_reg_set(mvi, mvi_dev);
+
+ mvs_slot_task_free(mvi, task, slot, slot_idx);
+ sts = tstat->stat;
+
+ spin_unlock(&mvi->lock);
+ if (task->task_done)
+ task->task_done(task);
+ else
+ mv_dprintk("why has not task_done.\n");
+ spin_lock(&mvi->lock);
+
+ return sts;
+}
+
+void mvs_release_task(struct mvs_info *mvi,
+ int phy_no, struct domain_device *dev)
+{
+ int i = 0; u32 slot_idx;
+ struct mvs_phy *phy;
+ struct mvs_port *port;
+ struct mvs_slot_info *slot, *slot2;
+
+ phy = &mvi->phy[phy_no];
+ port = phy->port;
+ if (!port)
+ return;
+
+ list_for_each_entry_safe(slot, slot2, &port->list, entry) {
+ struct sas_task *task;
+ slot_idx = (u32) (slot - mvi->slot_info);
+ task = slot->task;
+
+ if (dev && task->dev != dev)
+ continue;
+
+ mv_printk("Release slot [%x] tag[%x], task [%p]:\n",
+ slot_idx, slot->slot_tag, task);
+
+ if (task->task_proto & SAS_PROTOCOL_SSP) {
+ mv_printk("attached with SSP task CDB[");
+ for (i = 0; i < 16; i++)
+ mv_printk(" %02x", task->ssp_task.cdb[i]);
+ mv_printk(" ]\n");
+ }
+
+ mvs_slot_complete(mvi, slot_idx, 1);
+ }
+}
+
+static void mvs_phy_disconnected(struct mvs_phy *phy)
+{
+ phy->phy_attached = 0;
+ phy->att_dev_info = 0;
+ phy->att_dev_sas_addr = 0;
+}
+
+static void mvs_work_queue(struct work_struct *work)
+{
+ struct delayed_work *dw = container_of(work, struct delayed_work, work);
+ struct mvs_wq *mwq = container_of(dw, struct mvs_wq, work_q);
+ struct mvs_info *mvi = mwq->mvi;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mvi->lock, flags);
+ if (mwq->handler & PHY_PLUG_EVENT) {
+ u32 phy_no = (unsigned long) mwq->data;
+ struct sas_ha_struct *sas_ha = mvi->sas;
+ struct mvs_phy *phy = &mvi->phy[phy_no];
+ struct asd_sas_phy *sas_phy = &phy->sas_phy;
+
+ if (phy->phy_event & PHY_PLUG_OUT) {
+ u32 tmp;
+ struct sas_identify_frame *id;
+ id = (struct sas_identify_frame *)phy->frame_rcvd;
+ tmp = MVS_CHIP_DISP->read_phy_ctl(mvi, phy_no);
+ phy->phy_event &= ~PHY_PLUG_OUT;
+ if (!(tmp & PHY_READY_MASK)) {
+ sas_phy_disconnected(sas_phy);
+ mvs_phy_disconnected(phy);
+ sas_ha->notify_phy_event(sas_phy,
+ PHYE_LOSS_OF_SIGNAL);
+ mv_dprintk("phy%d Removed Device\n", phy_no);
+ } else {
+ MVS_CHIP_DISP->detect_porttype(mvi, phy_no);
+ mvs_update_phyinfo(mvi, phy_no, 1);
+ mvs_bytes_dmaed(mvi, phy_no);
+ mvs_port_notify_formed(sas_phy, 0);
+ mv_dprintk("phy%d Attached Device\n", phy_no);
+ }
+ }
+ }
+ list_del(&mwq->entry);
+ spin_unlock_irqrestore(&mvi->lock, flags);
+ kfree(mwq);
+}
+
+static int mvs_handle_event(struct mvs_info *mvi, void *data, int handler)
+{
+ struct mvs_wq *mwq;
+ int ret = 0;
+
+ mwq = kmalloc(sizeof(struct mvs_wq), GFP_ATOMIC);
+ if (mwq) {
+ mwq->mvi = mvi;
+ mwq->data = data;
+ mwq->handler = handler;
+ MV_INIT_DELAYED_WORK(&mwq->work_q, mvs_work_queue, mwq);
+ list_add_tail(&mwq->entry, &mvi->wq_list);
+ schedule_delayed_work(&mwq->work_q, HZ * 2);
+ } else
+ ret = -ENOMEM;
+
+ return ret;
+}
+
+static void mvs_sig_time_out(unsigned long tphy)
+{
+ struct mvs_phy *phy = (struct mvs_phy *)tphy;
+ struct mvs_info *mvi = phy->mvi;
+ u8 phy_no;
+
+ for (phy_no = 0; phy_no < mvi->chip->n_phy; phy_no++) {
+ if (&mvi->phy[phy_no] == phy) {
+ mv_dprintk("Get signature time out, reset phy %d\n",
+ phy_no+mvi->id*mvi->chip->n_phy);
+ MVS_CHIP_DISP->phy_reset(mvi, phy_no, 1);
+ }
+ }
+}
+
+static void mvs_sig_remove_timer(struct mvs_phy *phy)
+{
+ if (phy->timer.function)
+ del_timer(&phy->timer);
+ phy->timer.function = NULL;
+}
+
+void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
+{
+ u32 tmp;
+ struct sas_ha_struct *sas_ha = mvi->sas;
+ struct mvs_phy *phy = &mvi->phy[phy_no];
+ struct asd_sas_phy *sas_phy = &phy->sas_phy;
+
+ phy->irq_status = MVS_CHIP_DISP->read_port_irq_stat(mvi, phy_no);
+ mv_dprintk("port %d ctrl sts=0x%X.\n", phy_no+mvi->id*mvi->chip->n_phy,
+ MVS_CHIP_DISP->read_phy_ctl(mvi, phy_no));
+ mv_dprintk("Port %d irq sts = 0x%X\n", phy_no+mvi->id*mvi->chip->n_phy,
+ phy->irq_status);
+
+ /*
+ * events is port event now ,
+ * we need check the interrupt status which belongs to per port.
+ */
+
+ if (phy->irq_status & PHYEV_DCDR_ERR)
+ mv_dprintk("port %d STP decoding error.\n",
+ phy_no+mvi->id*mvi->chip->n_phy);
+
+ if (phy->irq_status & PHYEV_POOF) {
+ if (!(phy->phy_event & PHY_PLUG_OUT)) {
+ int dev_sata = phy->phy_type & PORT_TYPE_SATA;
+ int ready;
+ mvs_release_task(mvi, phy_no, NULL);
+ phy->phy_event |= PHY_PLUG_OUT;
+ mvs_handle_event(mvi,
+ (void *)(unsigned long)phy_no,
+ PHY_PLUG_EVENT);
+ ready = mvs_is_phy_ready(mvi, phy_no);
+ if (!ready)
+ mv_dprintk("phy%d Unplug Notice\n",
+ phy_no +
+ mvi->id * mvi->chip->n_phy);
+ if (ready || dev_sata) {
+ if (MVS_CHIP_DISP->stp_reset)
+ MVS_CHIP_DISP->stp_reset(mvi,
+ phy_no);
+ else
+ MVS_CHIP_DISP->phy_reset(mvi,
+ phy_no, 0);
+ return;
+ }
+ }
+ }
+
+ if (phy->irq_status & PHYEV_COMWAKE) {
+ tmp = MVS_CHIP_DISP->read_port_irq_mask(mvi, phy_no);
+ MVS_CHIP_DISP->write_port_irq_mask(mvi, phy_no,
+ tmp | PHYEV_SIG_FIS);
+ if (phy->timer.function == NULL) {
+ phy->timer.data = (unsigned long)phy;
+ phy->timer.function = mvs_sig_time_out;
+ phy->timer.expires = jiffies + 10*HZ;
+ add_timer(&phy->timer);
+ }
+ }
+ if (phy->irq_status & (PHYEV_SIG_FIS | PHYEV_ID_DONE)) {
+ phy->phy_status = mvs_is_phy_ready(mvi, phy_no);
+ mvs_sig_remove_timer(phy);
+ mv_dprintk("notify plug in on phy[%d]\n", phy_no);
+ if (phy->phy_status) {
+ mdelay(10);
+ MVS_CHIP_DISP->detect_porttype(mvi, phy_no);
+ if (phy->phy_type & PORT_TYPE_SATA) {
+ tmp = MVS_CHIP_DISP->read_port_irq_mask(
+ mvi, phy_no);
+ tmp &= ~PHYEV_SIG_FIS;
+ MVS_CHIP_DISP->write_port_irq_mask(mvi,
+ phy_no, tmp);
+ }
+ mvs_update_phyinfo(mvi, phy_no, 0);
+ mvs_bytes_dmaed(mvi, phy_no);
+ /* whether driver is going to handle hot plug */
+ if (phy->phy_event & PHY_PLUG_OUT) {
+ mvs_port_notify_formed(sas_phy, 0);
+ phy->phy_event &= ~PHY_PLUG_OUT;
+ }
+ } else {
+ mv_dprintk("plugin interrupt but phy%d is gone\n",
+ phy_no + mvi->id*mvi->chip->n_phy);
+ }
+ } else if (phy->irq_status & PHYEV_BROAD_CH) {
+ mv_dprintk("port %d broadcast change.\n",
+ phy_no + mvi->id*mvi->chip->n_phy);
+ /* exception for Samsung disk drive*/
+ mdelay(1000);
+ sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+ }
+ MVS_CHIP_DISP->write_port_irq_stat(mvi, phy_no, phy->irq_status);
+}
+
+int mvs_int_rx(struct mvs_info *mvi, bool self_clear)
+{
+ u32 rx_prod_idx, rx_desc;
+ bool attn = false;
+
+ /* the first dword in the RX ring is special: it contains
+ * a mirror of the hardware's RX producer index, so that
+ * we don't have to stall the CPU reading that register.
+ * The actual RX ring is offset by one dword, due to this.
+ */
+ rx_prod_idx = mvi->rx_cons;
+ mvi->rx_cons = le32_to_cpu(mvi->rx[0]);
+ if (mvi->rx_cons == 0xfff) /* h/w hasn't touched RX ring yet */
+ return 0;
+
+ /* The CMPL_Q may come late, read from register and try again
+ * note: if coalescing is enabled,
+ * it will need to read from register every time for sure
+ */
+ if (unlikely(mvi->rx_cons == rx_prod_idx))
+ mvi->rx_cons = MVS_CHIP_DISP->rx_update(mvi) & RX_RING_SZ_MASK;
+
+ if (mvi->rx_cons == rx_prod_idx)
+ return 0;
+
+ while (mvi->rx_cons != rx_prod_idx) {
+ /* increment our internal RX consumer pointer */
+ rx_prod_idx = (rx_prod_idx + 1) & (MVS_RX_RING_SZ - 1);
+ rx_desc = le32_to_cpu(mvi->rx[rx_prod_idx + 1]);
+
+ if (likely(rx_desc & RXQ_DONE))
+ mvs_slot_complete(mvi, rx_desc, 0);
+ if (rx_desc & RXQ_ATTN) {
+ attn = true;
+ } else if (rx_desc & RXQ_ERR) {
+ if (!(rx_desc & RXQ_DONE))
+ mvs_slot_complete(mvi, rx_desc, 0);
+ } else if (rx_desc & RXQ_SLOT_RESET) {
+ mvs_slot_free(mvi, rx_desc);
+ }
+ }
+
+ if (attn && self_clear)
+ MVS_CHIP_DISP->int_full(mvi);
+ return 0;
+}
+
diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h
new file mode 100644
index 000000000000..75b9748ae7cc
--- /dev/null
+++ b/drivers/scsi/mvsas/mv_sas.h
@@ -0,0 +1,406 @@
+/*
+ * Marvell 88SE64xx/88SE94xx main function head file
+ *
+ * Copyright 2007 Red Hat, Inc.
+ * Copyright 2008 Marvell. <kewei@marvell.com>
+ *
+ * This file is licensed under GPLv2.
+ *
+ * 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
+*/
+
+#ifndef _MV_SAS_H_
+#define _MV_SAS_H_
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/ctype.h>
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/vmalloc.h>
+#include <scsi/libsas.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/sas_ata.h>
+#include <linux/version.h>
+#include "mv_defs.h"
+
+#define DRV_NAME "mvsas"
+#define DRV_VERSION "0.8.2"
+#define _MV_DUMP 0
+#define MVS_ID_NOT_MAPPED 0x7f
+/* #define DISABLE_HOTPLUG_DMA_FIX */
+#define MAX_EXP_RUNNING_REQ 2
+#define WIDE_PORT_MAX_PHY 4
+#define MV_DISABLE_NCQ 0
+#define mv_printk(fmt, arg ...) \
+ printk(KERN_DEBUG"%s %d:" fmt, __FILE__, __LINE__, ## arg)
+#ifdef MV_DEBUG
+#define mv_dprintk(format, arg...) \
+ printk(KERN_DEBUG"%s %d:" format, __FILE__, __LINE__, ## arg)
+#else
+#define mv_dprintk(format, arg...)
+#endif
+#define MV_MAX_U32 0xffffffff
+
+extern struct mvs_tgt_initiator mvs_tgt;
+extern struct mvs_info *tgt_mvi;
+extern const struct mvs_dispatch mvs_64xx_dispatch;
+extern const struct mvs_dispatch mvs_94xx_dispatch;
+
+#define DEV_IS_EXPANDER(type) \
+ ((type == EDGE_DEV) || (type == FANOUT_DEV))
+
+#define bit(n) ((u32)1 << n)
+
+#define for_each_phy(__lseq_mask, __mc, __lseq) \
+ for ((__mc) = (__lseq_mask), (__lseq) = 0; \
+ (__mc) != 0 ; \
+ (++__lseq), (__mc) >>= 1)
+
+#define MV_INIT_DELAYED_WORK(w, f, d) INIT_DELAYED_WORK(w, f)
+#define UNASSOC_D2H_FIS(id) \
+ ((void *) mvi->rx_fis + 0x100 * id)
+#define SATA_RECEIVED_FIS_LIST(reg_set) \
+ ((void *) mvi->rx_fis + mvi->chip->fis_offs + 0x100 * reg_set)
+#define SATA_RECEIVED_SDB_FIS(reg_set) \
+ (SATA_RECEIVED_FIS_LIST(reg_set) + 0x58)
+#define SATA_RECEIVED_D2H_FIS(reg_set) \
+ (SATA_RECEIVED_FIS_LIST(reg_set) + 0x40)
+#define SATA_RECEIVED_PIO_FIS(reg_set) \
+ (SATA_RECEIVED_FIS_LIST(reg_set) + 0x20)
+#define SATA_RECEIVED_DMA_FIS(reg_set) \
+ (SATA_RECEIVED_FIS_LIST(reg_set) + 0x00)
+
+enum dev_status {
+ MVS_DEV_NORMAL = 0x0,
+ MVS_DEV_EH = 0x1,
+};
+
+
+struct mvs_info;
+
+struct mvs_dispatch {
+ char *name;
+ int (*chip_init)(struct mvs_info *mvi);
+ int (*spi_init)(struct mvs_info *mvi);
+ int (*chip_ioremap)(struct mvs_info *mvi);
+ void (*chip_iounmap)(struct mvs_info *mvi);
+ irqreturn_t (*isr)(struct mvs_info *mvi, int irq, u32 stat);
+ u32 (*isr_status)(struct mvs_info *mvi, int irq);
+ void (*interrupt_enable)(struct mvs_info *mvi);
+ void (*interrupt_disable)(struct mvs_info *mvi);
+
+ u32 (*read_phy_ctl)(struct mvs_info *mvi, u32 port);
+ void (*write_phy_ctl)(struct mvs_info *mvi, u32 port, u32 val);
+
+ u32 (*read_port_cfg_data)(struct mvs_info *mvi, u32 port);
+ void (*write_port_cfg_data)(struct mvs_info *mvi, u32 port, u32 val);
+ void (*write_port_cfg_addr)(struct mvs_info *mvi, u32 port, u32 addr);
+
+ u32 (*read_port_vsr_data)(struct mvs_info *mvi, u32 port);
+ void (*write_port_vsr_data)(struct mvs_info *mvi, u32 port, u32 val);
+ void (*write_port_vsr_addr)(struct mvs_info *mvi, u32 port, u32 addr);
+
+ u32 (*read_port_irq_stat)(struct mvs_info *mvi, u32 port);
+ void (*write_port_irq_stat)(struct mvs_info *mvi, u32 port, u32 val);
+
+ u32 (*read_port_irq_mask)(struct mvs_info *mvi, u32 port);
+ void (*write_port_irq_mask)(struct mvs_info *mvi, u32 port, u32 val);
+
+ void (*get_sas_addr)(void *buf, u32 buflen);
+ void (*command_active)(struct mvs_info *mvi, u32 slot_idx);
+ void (*issue_stop)(struct mvs_info *mvi, enum mvs_port_type type,
+ u32 tfs);
+ void (*start_delivery)(struct mvs_info *mvi, u32 tx);
+ u32 (*rx_update)(struct mvs_info *mvi);
+ void (*int_full)(struct mvs_info *mvi);
+ u8 (*assign_reg_set)(struct mvs_info *mvi, u8 *tfs);
+ void (*free_reg_set)(struct mvs_info *mvi, u8 *tfs);
+ u32 (*prd_size)(void);
+ u32 (*prd_count)(void);
+ void (*make_prd)(struct scatterlist *scatter, int nr, void *prd);
+ void (*detect_porttype)(struct mvs_info *mvi, int i);
+ int (*oob_done)(struct mvs_info *mvi, int i);
+ void (*fix_phy_info)(struct mvs_info *mvi, int i,
+ struct sas_identify_frame *id);
+ void (*phy_work_around)(struct mvs_info *mvi, int i);
+ void (*phy_set_link_rate)(struct mvs_info *mvi, u32 phy_id,
+ struct sas_phy_linkrates *rates);
+ u32 (*phy_max_link_rate)(void);
+ void (*phy_disable)(struct mvs_info *mvi, u32 phy_id);
+ void (*phy_enable)(struct mvs_info *mvi, u32 phy_id);
+ void (*phy_reset)(struct mvs_info *mvi, u32 phy_id, int hard);
+ void (*stp_reset)(struct mvs_info *mvi, u32 phy_id);
+ void (*clear_active_cmds)(struct mvs_info *mvi);
+ u32 (*spi_read_data)(struct mvs_info *mvi);
+ void (*spi_write_data)(struct mvs_info *mvi, u32 data);
+ int (*spi_buildcmd)(struct mvs_info *mvi,
+ u32 *dwCmd,
+ u8 cmd,
+ u8 read,
+ u8 length,
+ u32 addr
+ );
+ int (*spi_issuecmd)(struct mvs_info *mvi, u32 cmd);
+ int (*spi_waitdataready)(struct mvs_info *mvi, u32 timeout);
+#ifndef DISABLE_HOTPLUG_DMA_FIX
+ void (*dma_fix)(dma_addr_t buf_dma, int buf_len, int from, void *prd);
+#endif
+
+};
+
+struct mvs_chip_info {
+ u32 n_host;
+ u32 n_phy;
+ u32 fis_offs;
+ u32 fis_count;
+ u32 srs_sz;
+ u32 slot_width;
+ const struct mvs_dispatch *dispatch;
+};
+#define MVS_CHIP_SLOT_SZ (1U << mvi->chip->slot_width)
+#define MVS_RX_FISL_SZ \
+ (mvi->chip->fis_offs + (mvi->chip->fis_count * 0x100))
+#define MVS_CHIP_DISP (mvi->chip->dispatch)
+
+struct mvs_err_info {
+ __le32 flags;
+ __le32 flags2;
+};
+
+struct mvs_cmd_hdr {
+ __le32 flags; /* PRD tbl len; SAS, SATA ctl */
+ __le32 lens; /* cmd, max resp frame len */
+ __le32 tags; /* targ port xfer tag; tag */
+ __le32 data_len; /* data xfer len */
+ __le64 cmd_tbl; /* command table address */
+ __le64 open_frame; /* open addr frame address */
+ __le64 status_buf; /* status buffer address */
+ __le64 prd_tbl; /* PRD tbl address */
+ __le32 reserved[4];
+};
+
+struct mvs_port {
+ struct asd_sas_port sas_port;
+ u8 port_attached;
+ u8 wide_port_phymap;
+ struct list_head list;
+};
+
+struct mvs_phy {
+ struct mvs_info *mvi;
+ struct mvs_port *port;
+ struct asd_sas_phy sas_phy;
+ struct sas_identify identify;
+ struct scsi_device *sdev;
+ struct timer_list timer;
+ u64 dev_sas_addr;
+ u64 att_dev_sas_addr;
+ u32 att_dev_info;
+ u32 dev_info;
+ u32 phy_type;
+ u32 phy_status;
+ u32 irq_status;
+ u32 frame_rcvd_size;
+ u8 frame_rcvd[32];
+ u8 phy_attached;
+ u8 phy_mode;
+ u8 reserved[2];
+ u32 phy_event;
+ enum sas_linkrate minimum_linkrate;
+ enum sas_linkrate maximum_linkrate;
+};
+
+struct mvs_device {
+ enum sas_dev_type dev_type;
+ struct domain_device *sas_device;
+ u32 attached_phy;
+ u32 device_id;
+ u32 runing_req;
+ u8 taskfileset;
+ u8 dev_status;
+ u16 reserved;
+ struct list_head dev_entry;
+};
+
+struct mvs_slot_info {
+ struct list_head entry;
+ union {
+ struct sas_task *task;
+ void *tdata;
+ };
+ u32 n_elem;
+ u32 tx;
+ u32 slot_tag;
+
+ /* DMA buffer for storing cmd tbl, open addr frame, status buffer,
+ * and PRD table
+ */
+ void *buf;
+ dma_addr_t buf_dma;
+#if _MV_DUMP
+ u32 cmd_size;
+#endif
+ void *response;
+ struct mvs_port *port;
+ struct mvs_device *device;
+ void *open_frame;
+};
+
+struct mvs_info {
+ unsigned long flags;
+
+ /* host-wide lock */
+ spinlock_t lock;
+
+ /* our device */
+ struct pci_dev *pdev;
+ struct device *dev;
+
+ /* enhanced mode registers */
+ void __iomem *regs;
+
+ /* peripheral or soc registers */
+ void __iomem *regs_ex;
+ u8 sas_addr[SAS_ADDR_SIZE];
+
+ /* SCSI/SAS glue */
+ struct sas_ha_struct *sas;
+ struct Scsi_Host *shost;
+
+ /* TX (delivery) DMA ring */
+ __le32 *tx;
+ dma_addr_t tx_dma;
+
+ /* cached next-producer idx */
+ u32 tx_prod;
+
+ /* RX (completion) DMA ring */
+ __le32 *rx;
+ dma_addr_t rx_dma;
+
+ /* RX consumer idx */
+ u32 rx_cons;
+
+ /* RX'd FIS area */
+ __le32 *rx_fis;
+ dma_addr_t rx_fis_dma;
+
+ /* DMA command header slots */
+ struct mvs_cmd_hdr *slot;
+ dma_addr_t slot_dma;
+
+ u32 chip_id;
+ const struct mvs_chip_info *chip;
+
+ int tags_num;
+ u8 tags[MVS_SLOTS >> 3];
+
+ /* further per-slot information */
+ struct mvs_phy phy[MVS_MAX_PHYS];
+ struct mvs_port port[MVS_MAX_PHYS];
+ u32 irq;
+ u32 exp_req;
+ u32 id;
+ u64 sata_reg_set;
+ struct list_head *hba_list;
+ struct list_head soc_entry;
+ struct list_head wq_list;
+ unsigned long instance;
+ u16 flashid;
+ u32 flashsize;
+ u32 flashsectSize;
+
+ void *addon;
+ struct mvs_device devices[MVS_MAX_DEVICES];
+#ifndef DISABLE_HOTPLUG_DMA_FIX
+ void *bulk_buffer;
+ dma_addr_t bulk_buffer_dma;
+#define TRASH_BUCKET_SIZE 0x20000
+#endif
+ struct mvs_slot_info slot_info[0];
+};
+
+struct mvs_prv_info{
+ u8 n_host;
+ u8 n_phy;
+ u16 reserve;
+ struct mvs_info *mvi[2];
+};
+
+struct mvs_wq {
+ struct delayed_work work_q;
+ struct mvs_info *mvi;
+ void *data;
+ int handler;
+ struct list_head entry;
+};
+
+struct mvs_task_exec_info {
+ struct sas_task *task;
+ struct mvs_cmd_hdr *hdr;
+ struct mvs_port *port;
+ u32 tag;
+ int n_elem;
+};
+
+
+/******************** function prototype *********************/
+void mvs_get_sas_addr(void *buf, u32 buflen);
+void mvs_tag_clear(struct mvs_info *mvi, u32 tag);
+void mvs_tag_free(struct mvs_info *mvi, u32 tag);
+void mvs_tag_set(struct mvs_info *mvi, unsigned int tag);
+int mvs_tag_alloc(struct mvs_info *mvi, u32 *tag_out);
+void mvs_tag_init(struct mvs_info *mvi);
+void mvs_iounmap(void __iomem *regs);
+int mvs_ioremap(struct mvs_info *mvi, int bar, int bar_ex);
+void mvs_phys_reset(struct mvs_info *mvi, u32 phy_mask, int hard);
+int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
+ void *funcdata);
+void __devinit mvs_set_sas_addr(struct mvs_info *mvi, int port_id,
+ u32 off_lo, u32 off_hi, u64 sas_addr);
+int mvs_slave_alloc(struct scsi_device *scsi_dev);
+int mvs_slave_configure(struct scsi_device *sdev);
+void mvs_scan_start(struct Scsi_Host *shost);
+int mvs_scan_finished(struct Scsi_Host *shost, unsigned long time);
+int mvs_queue_command(struct sas_task *task, const int num,
+ gfp_t gfp_flags);
+int mvs_abort_task(struct sas_task *task);
+int mvs_abort_task_set(struct domain_device *dev, u8 *lun);
+int mvs_clear_aca(struct domain_device *dev, u8 *lun);
+int mvs_clear_task_set(struct domain_device *dev, u8 * lun);
+void mvs_port_formed(struct asd_sas_phy *sas_phy);
+void mvs_port_deformed(struct asd_sas_phy *sas_phy);
+int mvs_dev_found(struct domain_device *dev);
+void mvs_dev_gone(struct domain_device *dev);
+int mvs_lu_reset(struct domain_device *dev, u8 *lun);
+int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags);
+int mvs_I_T_nexus_reset(struct domain_device *dev);
+int mvs_query_task(struct sas_task *task);
+void mvs_release_task(struct mvs_info *mvi, int phy_no,
+ struct domain_device *dev);
+void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events);
+void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st);
+int mvs_int_rx(struct mvs_info *mvi, bool self_clear);
+void mvs_hexdump(u32 size, u8 *data, u32 baseaddr);
+#endif
+
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 2a5f0777148d..1ce6b24abab2 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -205,6 +205,74 @@ static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
osdv2_attr_list_elem_size(len);
}
+static void _osd_req_alist_elem_encode(struct osd_request *or,
+ void *attr_last, const struct osd_attr *oa)
+{
+ if (osd_req_is_ver1(or)) {
+ struct osdv1_attributes_list_element *attr = attr_last;
+
+ attr->attr_page = cpu_to_be32(oa->attr_page);
+ attr->attr_id = cpu_to_be32(oa->attr_id);
+ attr->attr_bytes = cpu_to_be16(oa->len);
+ memcpy(attr->attr_val, oa->val_ptr, oa->len);
+ } else {
+ struct osdv2_attributes_list_element *attr = attr_last;
+
+ attr->attr_page = cpu_to_be32(oa->attr_page);
+ attr->attr_id = cpu_to_be32(oa->attr_id);
+ attr->attr_bytes = cpu_to_be16(oa->len);
+ memcpy(attr->attr_val, oa->val_ptr, oa->len);
+ }
+}
+
+static int _osd_req_alist_elem_decode(struct osd_request *or,
+ void *cur_p, struct osd_attr *oa, unsigned max_bytes)
+{
+ unsigned inc;
+ if (osd_req_is_ver1(or)) {
+ struct osdv1_attributes_list_element *attr = cur_p;
+
+ if (max_bytes < sizeof(*attr))
+ return -1;
+
+ oa->len = be16_to_cpu(attr->attr_bytes);
+ inc = _osd_req_alist_elem_size(or, oa->len);
+ if (inc > max_bytes)
+ return -1;
+
+ oa->attr_page = be32_to_cpu(attr->attr_page);
+ oa->attr_id = be32_to_cpu(attr->attr_id);
+
+ /* OSD1: On empty attributes we return a pointer to 2 bytes
+ * of zeros. This keeps similar behaviour with OSD2.
+ * (See below)
+ */
+ oa->val_ptr = likely(oa->len) ? attr->attr_val :
+ (u8 *)&attr->attr_bytes;
+ } else {
+ struct osdv2_attributes_list_element *attr = cur_p;
+
+ if (max_bytes < sizeof(*attr))
+ return -1;
+
+ oa->len = be16_to_cpu(attr->attr_bytes);
+ inc = _osd_req_alist_elem_size(or, oa->len);
+ if (inc > max_bytes)
+ return -1;
+
+ oa->attr_page = be32_to_cpu(attr->attr_page);
+ oa->attr_id = be32_to_cpu(attr->attr_id);
+
+ /* OSD2: For convenience, on empty attributes, we return 8 bytes
+ * of zeros here. This keeps the same behaviour with OSD2r04,
+ * and is nice with null terminating ASCII fields.
+ * oa->val_ptr == NULL marks the end-of-list, or error.
+ */
+ oa->val_ptr = likely(oa->len) ? attr->attr_val : attr->reserved;
+ }
+ return inc;
+}
+
static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
{
return osd_req_is_ver1(or) ?
@@ -282,9 +350,9 @@ _osd_req_sec_params(struct osd_request *or)
struct osd_cdb *ocdb = &or->cdb;
if (osd_req_is_ver1(or))
- return &ocdb->v1.sec_params;
+ return (struct osd_security_parameters *)&ocdb->v1.sec_params;
else
- return &ocdb->v2.sec_params;
+ return (struct osd_security_parameters *)&ocdb->v2.sec_params;
}
void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
@@ -612,9 +680,9 @@ static int _osd_req_list_objects(struct osd_request *or,
WARN_ON(or->in.bio);
bio = bio_map_kern(q, list, len, or->alloc_flags);
- if (!bio) {
+ if (IS_ERR(bio)) {
OSD_ERR("!!! Failed to allocate list_objects BIO\n");
- return -ENOMEM;
+ return PTR_ERR(bio);
}
bio->bi_rw &= ~(1 << BIO_RW);
@@ -798,7 +866,6 @@ int osd_req_add_set_attr_list(struct osd_request *or,
attr_last = or->set_attr.buff + total_bytes;
for (; nelem; --nelem) {
- struct osd_attributes_list_element *attr;
unsigned elem_size = _osd_req_alist_elem_size(or, oa->len);
total_bytes += elem_size;
@@ -811,11 +878,7 @@ int osd_req_add_set_attr_list(struct osd_request *or,
or->set_attr.buff + or->set_attr.total_bytes;
}
- attr = attr_last;
- attr->attr_page = cpu_to_be32(oa->attr_page);
- attr->attr_id = cpu_to_be32(oa->attr_id);
- attr->attr_bytes = cpu_to_be16(oa->len);
- memcpy(attr->attr_val, oa->val_ptr, oa->len);
+ _osd_req_alist_elem_encode(or, attr_last, oa);
attr_last += elem_size;
++oa;
@@ -1070,15 +1133,10 @@ int osd_req_decode_get_attr_list(struct osd_request *or,
}
for (n = 0; (n < *nelem) && (cur_bytes < returned_bytes); ++n) {
- struct osd_attributes_list_element *attr = cur_p;
- unsigned inc;
+ int inc = _osd_req_alist_elem_decode(or, cur_p, oa,
+ returned_bytes - cur_bytes);
- oa->len = be16_to_cpu(attr->attr_bytes);
- inc = _osd_req_alist_elem_size(or, oa->len);
- OSD_DEBUG("oa->len=%d inc=%d cur_bytes=%d\n",
- oa->len, inc, cur_bytes);
- cur_bytes += inc;
- if (cur_bytes > returned_bytes) {
+ if (inc < 0) {
OSD_ERR("BAD FOOD from target. list not valid!"
"c=%d r=%d n=%d\n",
cur_bytes, returned_bytes, n);
@@ -1086,10 +1144,7 @@ int osd_req_decode_get_attr_list(struct osd_request *or,
break;
}
- oa->attr_page = be32_to_cpu(attr->attr_page);
- oa->attr_id = be32_to_cpu(attr->attr_id);
- oa->val_ptr = attr->attr_val;
-
+ cur_bytes += inc;
cur_p += inc;
++oa;
}
@@ -1159,6 +1214,24 @@ static int _osd_req_finalize_attr_page(struct osd_request *or)
return ret;
}
+static inline void osd_sec_parms_set_out_offset(bool is_v1,
+ struct osd_security_parameters *sec_parms, osd_cdb_offset offset)
+{
+ if (is_v1)
+ sec_parms->v1.data_out_integrity_check_offset = offset;
+ else
+ sec_parms->v2.data_out_integrity_check_offset = offset;
+}
+
+static inline void osd_sec_parms_set_in_offset(bool is_v1,
+ struct osd_security_parameters *sec_parms, osd_cdb_offset offset)
+{
+ if (is_v1)
+ sec_parms->v1.data_in_integrity_check_offset = offset;
+ else
+ sec_parms->v2.data_in_integrity_check_offset = offset;
+}
+
static int _osd_req_finalize_data_integrity(struct osd_request *or,
bool has_in, bool has_out, const u8 *cap_key)
{
@@ -1182,8 +1255,8 @@ static int _osd_req_finalize_data_integrity(struct osd_request *or,
or->out_data_integ.get_attributes_bytes = cpu_to_be64(
or->enc_get_attr.total_bytes);
- sec_parms->data_out_integrity_check_offset =
- osd_req_encode_offset(or, or->out.total_bytes, &pad);
+ osd_sec_parms_set_out_offset(osd_req_is_ver1(or), sec_parms,
+ osd_req_encode_offset(or, or->out.total_bytes, &pad));
ret = _req_append_segment(or, pad, &seg, or->out.last_seg,
&or->out);
@@ -1203,8 +1276,8 @@ static int _osd_req_finalize_data_integrity(struct osd_request *or,
};
unsigned pad;
- sec_parms->data_in_integrity_check_offset =
- osd_req_encode_offset(or, or->in.total_bytes, &pad);
+ osd_sec_parms_set_in_offset(osd_req_is_ver1(or), sec_parms,
+ osd_req_encode_offset(or, or->in.total_bytes, &pad));
ret = _req_append_segment(or, pad, &seg, or->in.last_seg,
&or->in);
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index f644c9571eab..22b59e13ba83 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -173,26 +173,26 @@ static const struct file_operations osd_fops = {
.unlocked_ioctl = osd_uld_ioctl,
};
-struct osd_dev *osduld_path_lookup(const char *path)
+struct osd_dev *osduld_path_lookup(const char *name)
{
- struct nameidata nd;
+ struct path path;
struct inode *inode;
struct cdev *cdev;
struct osd_uld_device *uninitialized_var(oud);
int error;
- if (!path || !*path) {
+ if (!name || !*name) {
OSD_ERR("Mount with !path || !*path\n");
return ERR_PTR(-EINVAL);
}
- error = path_lookup(path, LOOKUP_FOLLOW, &nd);
+ error = kern_path(name, LOOKUP_FOLLOW, &path);
if (error) {
- OSD_ERR("path_lookup of %s faild=>%d\n", path, error);
+ OSD_ERR("path_lookup of %s failed=>%d\n", name, error);
return ERR_PTR(error);
}
- inode = nd.path.dentry->d_inode;
+ inode = path.dentry->d_inode;
error = -EINVAL; /* Not the right device e.g osd_uld_device */
if (!S_ISCHR(inode->i_mode)) {
OSD_DEBUG("!S_ISCHR()\n");
@@ -202,15 +202,15 @@ struct osd_dev *osduld_path_lookup(const char *path)
cdev = inode->i_cdev;
if (!cdev) {
OSD_ERR("Before mounting an OSD Based filesystem\n");
- OSD_ERR(" user-mode must open+close the %s device\n", path);
- OSD_ERR(" Example: bash: echo < %s\n", path);
+ OSD_ERR(" user-mode must open+close the %s device\n", name);
+ OSD_ERR(" Example: bash: echo < %s\n", name);
goto out;
}
/* The Magic wand. Is it our char-dev */
/* TODO: Support sg devices */
if (cdev->owner != THIS_MODULE) {
- OSD_ERR("Error mounting %s - is not an OSD device\n", path);
+ OSD_ERR("Error mounting %s - is not an OSD device\n", name);
goto out;
}
@@ -220,7 +220,7 @@ struct osd_dev *osduld_path_lookup(const char *path)
error = 0;
out:
- path_put(&nd.path);
+ path_put(&path);
return error ? ERR_PTR(error) : &oud->od;
}
EXPORT_SYMBOL(osduld_path_lookup);
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index b09993a06576..fc30f8e2f467 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -97,7 +97,7 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj,
return 0;
if (IS_NOCACHE_VPD_TYPE(ha))
- ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_nvram << 2,
+ ha->isp_ops->read_optrom(vha, ha->nvram, ha->flt_region_nvram << 2,
ha->nvram_size);
return memory_read_from_buffer(buf, count, &off, ha->nvram,
ha->nvram_size);
@@ -1088,6 +1088,33 @@ qla2x00_flash_block_size_show(struct device *dev,
return snprintf(buf, PAGE_SIZE, "0x%x\n", ha->fdt_block_size);
}
+static ssize_t
+qla2x00_vlan_id_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+
+ if (!IS_QLA81XX(vha->hw))
+ return snprintf(buf, PAGE_SIZE, "\n");
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", vha->fcoe_vlan_id);
+}
+
+static ssize_t
+qla2x00_vn_port_mac_address_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+
+ if (!IS_QLA81XX(vha->hw))
+ return snprintf(buf, PAGE_SIZE, "\n");
+
+ return snprintf(buf, PAGE_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ vha->fcoe_vn_port_mac[5], vha->fcoe_vn_port_mac[4],
+ vha->fcoe_vn_port_mac[3], vha->fcoe_vn_port_mac[2],
+ vha->fcoe_vn_port_mac[1], vha->fcoe_vn_port_mac[0]);
+}
+
static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL);
static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
@@ -1116,6 +1143,9 @@ static DEVICE_ATTR(mpi_version, S_IRUGO, qla2x00_mpi_version_show, NULL);
static DEVICE_ATTR(phy_version, S_IRUGO, qla2x00_phy_version_show, NULL);
static DEVICE_ATTR(flash_block_size, S_IRUGO, qla2x00_flash_block_size_show,
NULL);
+static DEVICE_ATTR(vlan_id, S_IRUGO, qla2x00_vlan_id_show, NULL);
+static DEVICE_ATTR(vn_port_mac_address, S_IRUGO,
+ qla2x00_vn_port_mac_address_show, NULL);
struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_driver_version,
@@ -1138,6 +1168,8 @@ struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_mpi_version,
&dev_attr_phy_version,
&dev_attr_flash_block_size,
+ &dev_attr_vlan_id,
+ &dev_attr_vn_port_mac_address,
NULL,
};
@@ -1437,11 +1469,12 @@ static int
qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
{
int ret = 0;
- int cnt = 0;
- uint8_t qos = QLA_DEFAULT_QUE_QOS;
+ uint8_t qos = 0;
scsi_qla_host_t *base_vha = shost_priv(fc_vport->shost);
scsi_qla_host_t *vha = NULL;
struct qla_hw_data *ha = base_vha->hw;
+ uint16_t options = 0;
+ int cnt;
ret = qla24xx_vport_create_req_sanity_check(fc_vport);
if (ret) {
@@ -1497,23 +1530,35 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
qla24xx_vport_disable(fc_vport, disable);
- /* Create a queue pair for the vport */
- if (ha->mqenable) {
- if (ha->npiv_info) {
- for (; cnt < ha->nvram_npiv_size; cnt++) {
- if (ha->npiv_info[cnt].port_name ==
- vha->port_name &&
- ha->npiv_info[cnt].node_name ==
- vha->node_name) {
- qos = ha->npiv_info[cnt].q_qos;
- break;
- }
- }
+ ret = 0;
+ if (ha->cur_vport_count <= ha->flex_port_count || ql2xmultique_tag
+ || ha->max_req_queues == 1 || !ha->npiv_info)
+ goto vport_queue;
+ /* Create a request queue in QoS mode for the vport */
+ for (cnt = ha->flex_port_count; cnt < ha->nvram_npiv_size; cnt++) {
+ if (ha->npiv_info[cnt].port_name == vha->port_name &&
+ ha->npiv_info[cnt].node_name == vha->node_name) {
+ qos = ha->npiv_info[cnt].q_qos;
+ break;
}
- qla25xx_create_queues(vha, qos);
+ }
+ if (qos) {
+ ret = qla25xx_create_req_que(ha, options, vha->vp_idx, 0, 0,
+ qos);
+ if (!ret)
+ qla_printk(KERN_WARNING, ha,
+ "Can't create request queue for vp_idx:%d\n",
+ vha->vp_idx);
+ else
+ DEBUG2(qla_printk(KERN_INFO, ha,
+ "Request Que:%d created for vp_idx:%d\n",
+ ret, vha->vp_idx));
}
+vport_queue:
+ vha->req = ha->req_q_map[ret];
return 0;
+
vport_create_failed_2:
qla24xx_disable_vp(vha);
qla24xx_deallocate_vp_id(vha);
@@ -1554,8 +1599,8 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
vha->host_no, vha->vp_idx, vha));
}
- if (ha->mqenable) {
- if (qla25xx_delete_queues(vha, 0) != QLA_SUCCESS)
+ if (vha->req->id && !ql2xmultique_tag) {
+ if (qla25xx_delete_req_que(vha, vha->req) != QLA_SUCCESS)
qla_printk(KERN_WARNING, ha,
"Queue delete failed.\n");
}
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 34760f8d4f17..68671a2b8b7f 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -351,7 +351,7 @@ static inline void *
qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
{
uint32_t cnt, que_idx;
- uint8_t req_cnt, rsp_cnt, que_cnt;
+ uint8_t que_cnt;
struct qla2xxx_mq_chain *mq = ptr;
struct device_reg_25xxmq __iomem *reg;
@@ -363,9 +363,8 @@ qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
mq->type = __constant_htonl(DUMP_CHAIN_MQ);
mq->chain_size = __constant_htonl(sizeof(struct qla2xxx_mq_chain));
- req_cnt = find_first_zero_bit(ha->req_qid_map, ha->max_queues);
- rsp_cnt = find_first_zero_bit(ha->rsp_qid_map, ha->max_queues);
- que_cnt = req_cnt > rsp_cnt ? req_cnt : rsp_cnt;
+ que_cnt = ha->max_req_queues > ha->max_rsp_queues ?
+ ha->max_req_queues : ha->max_rsp_queues;
mq->count = htonl(que_cnt);
for (cnt = 0; cnt < que_cnt; cnt++) {
reg = (struct device_reg_25xxmq *) ((void *)
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 714ee67567e1..721bae94e437 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -93,6 +93,7 @@
#define LSD(x) ((uint32_t)((uint64_t)(x)))
#define MSD(x) ((uint32_t)((((uint64_t)(x)) >> 16) >> 16))
+#define MAKE_HANDLE(x, y) ((uint32_t)((((uint32_t)(x)) << 16) | (uint32_t)(y)))
/*
* I/O register
@@ -179,6 +180,7 @@
#define REQUEST_ENTRY_CNT_24XX 2048 /* Number of request entries. */
#define RESPONSE_ENTRY_CNT_2100 64 /* Number of response entries.*/
#define RESPONSE_ENTRY_CNT_2300 512 /* Number of response entries.*/
+#define RESPONSE_ENTRY_CNT_MQ 128 /* Number of response entries.*/
struct req_que;
@@ -186,7 +188,6 @@ struct req_que;
* SCSI Request Block
*/
typedef struct srb {
- struct req_que *que;
struct fc_port *fcport;
struct scsi_cmnd *cmd; /* Linux SCSI command pkt */
@@ -2008,7 +2009,7 @@ typedef struct vport_params {
#define VP_RET_CODE_NOT_FOUND 6
struct qla_hw_data;
-
+struct rsp_que;
/*
* ISP operations
*/
@@ -2030,10 +2031,9 @@ struct isp_operations {
void (*enable_intrs) (struct qla_hw_data *);
void (*disable_intrs) (struct qla_hw_data *);
- int (*abort_command) (struct scsi_qla_host *, srb_t *,
- struct req_que *);
- int (*target_reset) (struct fc_port *, unsigned int);
- int (*lun_reset) (struct fc_port *, unsigned int);
+ int (*abort_command) (srb_t *);
+ int (*target_reset) (struct fc_port *, unsigned int, int);
+ int (*lun_reset) (struct fc_port *, unsigned int, int);
int (*fabric_login) (struct scsi_qla_host *, uint16_t, uint8_t,
uint8_t, uint8_t, uint16_t *, uint8_t);
int (*fabric_logout) (struct scsi_qla_host *, uint16_t, uint8_t,
@@ -2079,7 +2079,6 @@ struct isp_operations {
#define QLA_PCI_MSIX_CONTROL 0xa2
struct scsi_qla_host;
-struct rsp_que;
struct qla_msix_entry {
int have_irq;
@@ -2140,7 +2139,6 @@ struct qla_statistics {
#define MBC_INITIALIZE_MULTIQ 0x1f
#define QLA_QUE_PAGE 0X1000
#define QLA_MQ_SIZE 32
-#define QLA_MAX_HOST_QUES 16
#define QLA_MAX_QUEUES 256
#define ISP_QUE_REG(ha, id) \
((ha->mqenable) ? \
@@ -2170,6 +2168,8 @@ struct rsp_que {
struct qla_hw_data *hw;
struct qla_msix_entry *msix;
struct req_que *req;
+ srb_t *status_srb; /* status continuation entry */
+ struct work_struct q_work;
};
/* Request queue data structure */
@@ -2222,6 +2222,7 @@ struct qla_hw_data {
uint32_t fce_enabled :1;
uint32_t fac_supported :1;
uint32_t chip_reset_done :1;
+ uint32_t port0 :1;
} flags;
/* This spinlock is used to protect "io transactions", you must
@@ -2246,7 +2247,8 @@ struct qla_hw_data {
struct rsp_que **rsp_q_map;
unsigned long req_qid_map[(QLA_MAX_QUEUES / 8) / sizeof(unsigned long)];
unsigned long rsp_qid_map[(QLA_MAX_QUEUES / 8) / sizeof(unsigned long)];
- uint16_t max_queues;
+ uint8_t max_req_queues;
+ uint8_t max_rsp_queues;
struct qla_npiv_entry *npiv_info;
uint16_t nvram_npiv_size;
@@ -2255,6 +2257,9 @@ struct qla_hw_data {
#define FLOGI_MID_SUPPORT BIT_10
#define FLOGI_VSAN_SUPPORT BIT_12
#define FLOGI_SP_SUPPORT BIT_13
+
+ uint8_t port_no; /* Physical port of adapter */
+
/* Timeout timers. */
uint8_t loop_down_abort_time; /* port down timer */
atomic_t loop_down_timer; /* loop down timer */
@@ -2532,10 +2537,12 @@ struct qla_hw_data {
uint16_t num_vsans; /* number of vsan created */
uint16_t max_npiv_vports; /* 63 or 125 per topoloty */
int cur_vport_count;
+ uint16_t flex_port_count;
struct qla_chip_state_84xx *cs84xx;
struct qla_statistics qla_stats;
struct isp_operations *isp_ops;
+ struct workqueue_struct *wq;
};
/*
@@ -2591,8 +2598,6 @@ typedef struct scsi_qla_host {
#define SWITCH_FOUND BIT_0
#define DFLG_NO_CABLE BIT_1
- srb_t *status_srb; /* Status continuation entry. */
-
/* ISP configuration data. */
uint16_t loop_id; /* Host adapter loop id */
@@ -2618,6 +2623,11 @@ typedef struct scsi_qla_host {
uint8_t node_name[WWN_SIZE];
uint8_t port_name[WWN_SIZE];
uint8_t fabric_node_name[WWN_SIZE];
+
+ uint16_t fcoe_vlan_id;
+ uint16_t fcoe_fcf_idx;
+ uint8_t fcoe_vn_port_mac[6];
+
uint32_t vp_abort_cnt;
struct fc_vport *fc_vport; /* holds fc_vport * for each vport */
@@ -2643,7 +2653,7 @@ typedef struct scsi_qla_host {
#define VP_ERR_FAB_LOGOUT 4
#define VP_ERR_ADAP_NORESOURCES 5
struct qla_hw_data *hw;
- int req_ques[QLA_MAX_HOST_QUES];
+ struct req_que *req;
} scsi_qla_host_t;
/*
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 96ccb9642ba0..f389f3da0bab 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -1711,7 +1711,7 @@ struct ex_init_cb_81xx {
#define FA_VPD0_ADDR_81 0xD0000
#define FA_VPD1_ADDR_81 0xD0400
#define FA_NVRAM0_ADDR_81 0xD0080
-#define FA_NVRAM1_ADDR_81 0xD0480
+#define FA_NVRAM1_ADDR_81 0xD0180
#define FA_FEATURE_ADDR_81 0xD4000
#define FA_FLASH_DESCR_ADDR_81 0xD8000
#define FA_FLASH_LAYOUT_ADDR_81 0xD8400
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 528913f6bed9..f17d525897a0 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -65,8 +65,11 @@ extern int ql2xfdmienable;
extern int ql2xallocfwdump;
extern int ql2xextended_error_logging;
extern int ql2xqfullrampup;
+extern int ql2xqfulltracking;
extern int ql2xiidmaenable;
extern int ql2xmaxqueues;
+extern int ql2xmultique_tag;
+extern int ql2xfwloadbin;
extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
@@ -165,13 +168,13 @@ extern int
qla2x00_issue_iocb(scsi_qla_host_t *, void *, dma_addr_t, size_t);
extern int
-qla2x00_abort_command(scsi_qla_host_t *, srb_t *, struct req_que *);
+qla2x00_abort_command(srb_t *);
extern int
-qla2x00_abort_target(struct fc_port *, unsigned int);
+qla2x00_abort_target(struct fc_port *, unsigned int, int);
extern int
-qla2x00_lun_reset(struct fc_port *, unsigned int);
+qla2x00_lun_reset(struct fc_port *, unsigned int, int);
extern int
qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *,
@@ -236,9 +239,11 @@ extern int
qla24xx_get_isp_stats(scsi_qla_host_t *, struct link_statistics *,
dma_addr_t);
-extern int qla24xx_abort_command(scsi_qla_host_t *, srb_t *, struct req_que *);
-extern int qla24xx_abort_target(struct fc_port *, unsigned int);
-extern int qla24xx_lun_reset(struct fc_port *, unsigned int);
+extern int qla24xx_abort_command(srb_t *);
+extern int
+qla24xx_abort_target(struct fc_port *, unsigned int, int);
+extern int
+qla24xx_lun_reset(struct fc_port *, unsigned int, int);
extern int
qla2x00_system_error(scsi_qla_host_t *);
@@ -295,8 +300,8 @@ extern irqreturn_t qla2100_intr_handler(int, void *);
extern irqreturn_t qla2300_intr_handler(int, void *);
extern irqreturn_t qla24xx_intr_handler(int, void *);
extern void qla2x00_process_response_queue(struct rsp_que *);
-extern void qla24xx_process_response_queue(struct rsp_que *);
-
+extern void
+qla24xx_process_response_queue(struct scsi_qla_host *, struct rsp_que *);
extern int qla2x00_request_irqs(struct qla_hw_data *, struct rsp_que *);
extern void qla2x00_free_irqs(scsi_qla_host_t *);
@@ -401,19 +406,21 @@ extern int qla25xx_request_irq(struct rsp_que *);
extern int qla25xx_init_req_que(struct scsi_qla_host *, struct req_que *);
extern int qla25xx_init_rsp_que(struct scsi_qla_host *, struct rsp_que *);
extern int qla25xx_create_req_que(struct qla_hw_data *, uint16_t, uint8_t,
- uint16_t, uint8_t, uint8_t);
+ uint16_t, int, uint8_t);
extern int qla25xx_create_rsp_que(struct qla_hw_data *, uint16_t, uint8_t,
- uint16_t);
+ uint16_t, int);
extern int qla25xx_update_req_que(struct scsi_qla_host *, uint8_t, uint8_t);
extern void qla2x00_init_response_q_entries(struct rsp_que *);
extern int qla25xx_delete_req_que(struct scsi_qla_host *, struct req_que *);
extern int qla25xx_delete_rsp_que(struct scsi_qla_host *, struct rsp_que *);
extern int qla25xx_create_queues(struct scsi_qla_host *, uint8_t);
-extern int qla25xx_delete_queues(struct scsi_qla_host *, uint8_t);
+extern int qla25xx_delete_queues(struct scsi_qla_host *);
extern uint16_t qla24xx_rd_req_reg(struct qla_hw_data *, uint16_t);
extern uint16_t qla25xx_rd_req_reg(struct qla_hw_data *, uint16_t);
extern void qla24xx_wrt_req_reg(struct qla_hw_data *, uint16_t, uint16_t);
extern void qla25xx_wrt_req_reg(struct qla_hw_data *, uint16_t, uint16_t);
extern void qla25xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t);
extern void qla24xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t);
+extern struct scsi_qla_host * qla25xx_get_host(struct rsp_que *);
+
#endif /* _QLA_GBL_H */
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 557f58d5bf88..3dbb9e73e80a 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -1107,7 +1107,7 @@ qla2x00_mgmt_svr_login(scsi_qla_host_t *vha)
return ret;
ha->isp_ops->fabric_login(vha, vha->mgmt_svr_loop_id, 0xff, 0xff, 0xfa,
- mb, BIT_1);
+ mb, BIT_1|BIT_0);
if (mb[0] != MBS_COMMAND_COMPLETE) {
DEBUG2_13(printk("%s(%ld): Failed MANAGEMENT_SERVER login: "
"loop_id=%x mb[0]=%x mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x\n",
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index bd7dd84c0648..33e924810666 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -634,7 +634,7 @@ qla2x00_chip_diag(scsi_qla_host_t *vha)
goto chip_diag_failed;
DEBUG3(printk("scsi(%ld): Reset register cleared by chip reset\n",
- ha->host_no));
+ vha->host_no));
/* Reset RISC processor. */
WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
@@ -655,7 +655,7 @@ qla2x00_chip_diag(scsi_qla_host_t *vha)
goto chip_diag_failed;
/* Check product ID of chip */
- DEBUG3(printk("scsi(%ld): Checking product ID of chip\n", ha->host_no));
+ DEBUG3(printk("scsi(%ld): Checking product ID of chip\n", vha->host_no));
mb[1] = RD_MAILBOX_REG(ha, reg, 1);
mb[2] = RD_MAILBOX_REG(ha, reg, 2);
@@ -786,7 +786,6 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
sizeof(uint32_t);
if (ha->mqenable)
mq_size = sizeof(struct qla2xxx_mq_chain);
-
/* Allocate memory for Fibre Channel Event Buffer. */
if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha))
goto try_eft;
@@ -850,8 +849,7 @@ cont_alloc:
rsp_q_size = rsp->length * sizeof(response_t);
dump_size = offsetof(struct qla2xxx_fw_dump, isp);
- dump_size += fixed_size + mem_size + req_q_size + rsp_q_size +
- eft_size;
+ dump_size += fixed_size + mem_size + req_q_size + rsp_q_size + eft_size;
ha->chain_offset = dump_size;
dump_size += mq_size + fce_size;
@@ -1013,12 +1011,14 @@ qla2x00_init_response_q_entries(struct rsp_que *rsp)
uint16_t cnt;
response_t *pkt;
+ rsp->ring_ptr = rsp->ring;
+ rsp->ring_index = 0;
+ rsp->status_srb = NULL;
pkt = rsp->ring_ptr;
for (cnt = 0; cnt < rsp->length; cnt++) {
pkt->signature = RESPONSE_PROCESSED;
pkt++;
}
-
}
/**
@@ -1176,7 +1176,7 @@ qla24xx_config_rings(struct scsi_qla_host *vha)
if (ha->flags.msix_enabled) {
msix = &ha->msix_entries[1];
DEBUG2_17(printk(KERN_INFO
- "Reistering vector 0x%x for base que\n", msix->entry));
+ "Registering vector 0x%x for base que\n", msix->entry));
icb->msix = cpu_to_le16(msix->entry);
}
/* Use alternate PCI bus number */
@@ -1230,14 +1230,14 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
spin_lock_irqsave(&ha->hardware_lock, flags);
/* Clear outstanding commands array. */
- for (que = 0; que < ha->max_queues; que++) {
+ for (que = 0; que < ha->max_req_queues; que++) {
req = ha->req_q_map[que];
if (!req)
continue;
- for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)
+ for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)
req->outstanding_cmds[cnt] = NULL;
- req->current_outstanding_cmd = 0;
+ req->current_outstanding_cmd = 1;
/* Initialize firmware. */
req->ring_ptr = req->ring;
@@ -1245,13 +1245,10 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
req->cnt = req->length;
}
- for (que = 0; que < ha->max_queues; que++) {
+ for (que = 0; que < ha->max_rsp_queues; que++) {
rsp = ha->rsp_q_map[que];
if (!rsp)
continue;
- rsp->ring_ptr = rsp->ring;
- rsp->ring_index = 0;
-
/* Initialize response queue entries */
qla2x00_init_response_q_entries(rsp);
}
@@ -1541,6 +1538,7 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len,
char *st, *en;
uint16_t index;
struct qla_hw_data *ha = vha->hw;
+ int use_tbl = !IS_QLA25XX(ha) && IS_QLA81XX(ha);
if (memcmp(model, BINZERO, len) != 0) {
strncpy(ha->model_number, model, len);
@@ -1553,14 +1551,16 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len,
}
index = (ha->pdev->subsystem_device & 0xff);
- if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
+ if (use_tbl &&
+ ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
index < QLA_MODEL_NAMES)
strncpy(ha->model_desc,
qla2x00_model_name[index * 2 + 1],
sizeof(ha->model_desc) - 1);
} else {
index = (ha->pdev->subsystem_device & 0xff);
- if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
+ if (use_tbl &&
+ ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
index < QLA_MODEL_NAMES) {
strcpy(ha->model_number,
qla2x00_model_name[index * 2]);
@@ -2110,7 +2110,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
goto cleanup_allocation;
DEBUG3(printk("scsi(%ld): Entries in ID list (%d)\n",
- ha->host_no, entries));
+ vha->host_no, entries));
DEBUG3(qla2x00_dump_buffer((uint8_t *)ha->gid_list,
entries * sizeof(struct gid_list_info)));
@@ -3180,9 +3180,14 @@ qla2x00_loop_resync(scsi_qla_host_t *vha)
{
int rval = QLA_SUCCESS;
uint32_t wait_time;
- struct qla_hw_data *ha = vha->hw;
- struct req_que *req = ha->req_q_map[vha->req_ques[0]];
- struct rsp_que *rsp = req->rsp;
+ struct req_que *req;
+ struct rsp_que *rsp;
+
+ if (ql2xmultique_tag)
+ req = vha->hw->req_q_map[0];
+ else
+ req = vha->req;
+ rsp = req->rsp;
atomic_set(&vha->loop_state, LOOP_UPDATE);
clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
@@ -3448,7 +3453,7 @@ qla25xx_init_queues(struct qla_hw_data *ha)
int ret = -1;
int i;
- for (i = 1; i < ha->max_queues; i++) {
+ for (i = 1; i < ha->max_rsp_queues; i++) {
rsp = ha->rsp_q_map[i];
if (rsp) {
rsp->options &= ~BIT_0;
@@ -3462,6 +3467,8 @@ qla25xx_init_queues(struct qla_hw_data *ha)
"%s Rsp que:%d inited\n", __func__,
rsp->id));
}
+ }
+ for (i = 1; i < ha->max_req_queues; i++) {
req = ha->req_q_map[i];
if (req) {
/* Clear outstanding commands array. */
@@ -3566,14 +3573,15 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
nv = ha->nvram;
/* Determine NVRAM starting address. */
- ha->nvram_size = sizeof(struct nvram_24xx);
- ha->nvram_base = FA_NVRAM_FUNC0_ADDR;
- ha->vpd_size = FA_NVRAM_VPD_SIZE;
- ha->vpd_base = FA_NVRAM_VPD0_ADDR;
- if (PCI_FUNC(ha->pdev->devfn)) {
+ if (ha->flags.port0) {
+ ha->nvram_base = FA_NVRAM_FUNC0_ADDR;
+ ha->vpd_base = FA_NVRAM_VPD0_ADDR;
+ } else {
ha->nvram_base = FA_NVRAM_FUNC1_ADDR;
ha->vpd_base = FA_NVRAM_VPD1_ADDR;
}
+ ha->nvram_size = sizeof(struct nvram_24xx);
+ ha->vpd_size = FA_NVRAM_VPD_SIZE;
/* Get VPD data into cache */
ha->vpd = ha->nvram + VPD_OFFSET;
@@ -3587,7 +3595,7 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++)
chksum += le32_to_cpu(*dptr++);
- DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", ha->host_no));
+ DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", vha->host_no));
DEBUG5(qla2x00_dump_buffer((uint8_t *)nv, ha->nvram_size));
/* Bad NVRAM data, set defaults parameters. */
@@ -3612,7 +3620,7 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
nv->exchange_count = __constant_cpu_to_le16(0);
nv->hard_address = __constant_cpu_to_le16(124);
nv->port_name[0] = 0x21;
- nv->port_name[1] = 0x00 + PCI_FUNC(ha->pdev->devfn);
+ nv->port_name[1] = 0x00 + ha->port_no;
nv->port_name[2] = 0x00;
nv->port_name[3] = 0xe0;
nv->port_name[4] = 0x8b;
@@ -4104,6 +4112,9 @@ qla24xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
{
int rval;
+ if (ql2xfwloadbin == 1)
+ return qla81xx_load_risc(vha, srisc_addr);
+
/*
* FW Load priority:
* 1) Firmware via request-firmware interface (.bin file).
@@ -4121,6 +4132,9 @@ qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
{
int rval;
+ if (ql2xfwloadbin == 2)
+ return qla24xx_load_risc(vha, srisc_addr);
+
/*
* FW Load priority:
* 1) Firmware residing in flash.
@@ -4146,7 +4160,7 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *vha)
ret = qla2x00_stop_firmware(vha);
for (retries = 5; ret != QLA_SUCCESS && ret != QLA_FUNCTION_TIMEOUT &&
- retries ; retries--) {
+ ret != QLA_INVALID_COMMAND && retries ; retries--) {
ha->isp_ops->reset_chip(vha);
if (ha->isp_ops->chip_diag(vha) != QLA_SUCCESS)
continue;
@@ -4165,13 +4179,19 @@ qla24xx_configure_vhba(scsi_qla_host_t *vha)
uint16_t mb[MAILBOX_REGISTER_COUNT];
struct qla_hw_data *ha = vha->hw;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
- struct req_que *req = ha->req_q_map[vha->req_ques[0]];
- struct rsp_que *rsp = req->rsp;
+ struct req_que *req;
+ struct rsp_que *rsp;
if (!vha->vp_idx)
return -EINVAL;
rval = qla2x00_fw_ready(base_vha);
+ if (ql2xmultique_tag)
+ req = ha->req_q_map[0];
+ else
+ req = vha->req;
+ rsp = req->rsp;
+
if (rval == QLA_SUCCESS) {
clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
@@ -4305,7 +4325,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++)
chksum += le32_to_cpu(*dptr++);
- DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", ha->host_no));
+ DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", vha->host_no));
DEBUG5(qla2x00_dump_buffer((uint8_t *)nv, ha->nvram_size));
/* Bad NVRAM data, set defaults parameters. */
@@ -4329,7 +4349,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
nv->execution_throttle = __constant_cpu_to_le16(0xFFFF);
nv->exchange_count = __constant_cpu_to_le16(0);
nv->port_name[0] = 0x21;
- nv->port_name[1] = 0x00 + PCI_FUNC(ha->pdev->devfn);
+ nv->port_name[1] = 0x00 + ha->port_no;
nv->port_name[2] = 0x00;
nv->port_name[3] = 0xe0;
nv->port_name[4] = 0x8b;
@@ -4363,7 +4383,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
nv->enode_mac[2] = 0x03;
nv->enode_mac[3] = 0x04;
nv->enode_mac[4] = 0x05;
- nv->enode_mac[5] = 0x06 + PCI_FUNC(ha->pdev->devfn);
+ nv->enode_mac[5] = 0x06 + ha->port_no;
rval = 1;
}
@@ -4396,7 +4416,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
icb->enode_mac[2] = 0x03;
icb->enode_mac[3] = 0x04;
icb->enode_mac[4] = 0x05;
- icb->enode_mac[5] = 0x06 + PCI_FUNC(ha->pdev->devfn);
+ icb->enode_mac[5] = 0x06 + ha->port_no;
}
/* Use extended-initialization control block. */
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index a8abbb95730d..b4c6010ee5fa 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -15,6 +15,7 @@ static request_t *qla2x00_req_pkt(struct scsi_qla_host *, struct req_que *,
struct rsp_que *rsp);
static void qla2x00_isp_cmd(struct scsi_qla_host *, struct req_que *);
+static void qla25xx_set_que(srb_t *, struct req_que **, struct rsp_que **);
/**
* qla2x00_get_cmd_direction() - Determine control_flag data direction.
* @cmd: SCSI command
@@ -92,9 +93,10 @@ qla2x00_calc_iocbs_64(uint16_t dsds)
* Returns a pointer to the Continuation Type 0 IOCB packet.
*/
static inline cont_entry_t *
-qla2x00_prep_cont_type0_iocb(struct req_que *req, struct scsi_qla_host *vha)
+qla2x00_prep_cont_type0_iocb(struct scsi_qla_host *vha)
{
cont_entry_t *cont_pkt;
+ struct req_que *req = vha->req;
/* Adjust ring index. */
req->ring_index++;
if (req->ring_index == req->length) {
@@ -120,10 +122,11 @@ qla2x00_prep_cont_type0_iocb(struct req_que *req, struct scsi_qla_host *vha)
* Returns a pointer to the continuation type 1 IOCB packet.
*/
static inline cont_a64_entry_t *
-qla2x00_prep_cont_type1_iocb(struct req_que *req, scsi_qla_host_t *vha)
+qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *vha)
{
cont_a64_entry_t *cont_pkt;
+ struct req_que *req = vha->req;
/* Adjust ring index. */
req->ring_index++;
if (req->ring_index == req->length) {
@@ -159,7 +162,6 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt,
struct scsi_cmnd *cmd;
struct scatterlist *sg;
int i;
- struct req_que *req;
cmd = sp->cmd;
@@ -174,8 +176,6 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt,
}
vha = sp->fcport->vha;
- req = sp->que;
-
cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(sp));
/* Three DSDs are available in the Command Type 2 IOCB */
@@ -192,7 +192,7 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt,
* Seven DSDs are available in the Continuation
* Type 0 IOCB.
*/
- cont_pkt = qla2x00_prep_cont_type0_iocb(req, vha);
+ cont_pkt = qla2x00_prep_cont_type0_iocb(vha);
cur_dsd = (uint32_t *)&cont_pkt->dseg_0_address;
avail_dsds = 7;
}
@@ -220,7 +220,6 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt,
struct scsi_cmnd *cmd;
struct scatterlist *sg;
int i;
- struct req_que *req;
cmd = sp->cmd;
@@ -235,8 +234,6 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt,
}
vha = sp->fcport->vha;
- req = sp->que;
-
cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(sp));
/* Two DSDs are available in the Command Type 3 IOCB */
@@ -254,7 +251,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt,
* Five DSDs are available in the Continuation
* Type 1 IOCB.
*/
- cont_pkt = qla2x00_prep_cont_type1_iocb(req, vha);
+ cont_pkt = qla2x00_prep_cont_type1_iocb(vha);
cur_dsd = (uint32_t *)cont_pkt->dseg_0_address;
avail_dsds = 5;
}
@@ -353,7 +350,6 @@ qla2x00_start_scsi(srb_t *sp)
/* Build command packet */
req->current_outstanding_cmd = handle;
req->outstanding_cmds[handle] = sp;
- sp->que = req;
sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle;
req->cnt -= req_cnt;
@@ -453,6 +449,7 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req,
mrk24->lun[2] = MSB(lun);
host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun));
mrk24->vp_index = vha->vp_idx;
+ mrk24->handle = MAKE_HANDLE(req->id, mrk24->handle);
} else {
SET_TARGET_ID(ha, mrk->target, loop_id);
mrk->lun = cpu_to_le16(lun);
@@ -531,9 +528,6 @@ qla2x00_req_pkt(struct scsi_qla_host *vha, struct req_que *req,
for (cnt = 0; cnt < REQUEST_ENTRY_SIZE / 4; cnt++)
*dword_ptr++ = 0;
- /* Set system defined field. */
- pkt->sys_define = (uint8_t)req->ring_index;
-
/* Set entry count. */
pkt->entry_count = 1;
@@ -656,7 +650,7 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt,
}
vha = sp->fcport->vha;
- req = sp->que;
+ req = vha->req;
/* Set transfer direction */
if (cmd->sc_data_direction == DMA_TO_DEVICE) {
@@ -687,7 +681,7 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt,
* Five DSDs are available in the Continuation
* Type 1 IOCB.
*/
- cont_pkt = qla2x00_prep_cont_type1_iocb(req, vha);
+ cont_pkt = qla2x00_prep_cont_type1_iocb(vha);
cur_dsd = (uint32_t *)cont_pkt->dseg_0_address;
avail_dsds = 5;
}
@@ -724,19 +718,12 @@ qla24xx_start_scsi(srb_t *sp)
struct scsi_cmnd *cmd = sp->cmd;
struct scsi_qla_host *vha = sp->fcport->vha;
struct qla_hw_data *ha = vha->hw;
- uint16_t que_id;
/* Setup device pointers. */
ret = 0;
- que_id = vha->req_ques[0];
- req = ha->req_q_map[que_id];
- sp->que = req;
+ qla25xx_set_que(sp, &req, &rsp);
- if (req->rsp)
- rsp = req->rsp;
- else
- rsp = ha->rsp_q_map[que_id];
/* So we know we haven't pci_map'ed anything yet */
tot_dsds = 0;
@@ -794,7 +781,7 @@ qla24xx_start_scsi(srb_t *sp)
req->cnt -= req_cnt;
cmd_pkt = (struct cmd_type_7 *)req->ring_ptr;
- cmd_pkt->handle = handle;
+ cmd_pkt->handle = MAKE_HANDLE(req->id, handle);
/* Zero out remaining portion of packet. */
/* tagged queuing modifier -- default is TSK_SIMPLE (0). */
@@ -823,6 +810,8 @@ qla24xx_start_scsi(srb_t *sp)
/* Set total data segment count. */
cmd_pkt->entry_count = (uint8_t)req_cnt;
+ /* Specify response queue number where completion should happen */
+ cmd_pkt->entry_status = (uint8_t) rsp->id;
wmb();
/* Adjust ring index. */
@@ -842,7 +831,7 @@ qla24xx_start_scsi(srb_t *sp)
/* Manage unprocessed RIO/ZIO commands in response queue. */
if (vha->flags.process_response_queue &&
rsp->ring_ptr->signature != RESPONSE_PROCESSED)
- qla24xx_process_response_queue(rsp);
+ qla24xx_process_response_queue(vha, rsp);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return QLA_SUCCESS;
@@ -855,3 +844,21 @@ queuing_error:
return QLA_FUNCTION_FAILED;
}
+
+static void qla25xx_set_que(srb_t *sp, struct req_que **req,
+ struct rsp_que **rsp)
+{
+ struct scsi_cmnd *cmd = sp->cmd;
+ struct scsi_qla_host *vha = sp->fcport->vha;
+ struct qla_hw_data *ha = sp->fcport->vha->hw;
+ int affinity = cmd->request->cpu;
+
+ if (ql2xmultique_tag && affinity >= 0 &&
+ affinity < ha->max_rsp_queues - 1) {
+ *rsp = ha->rsp_q_map[affinity + 1];
+ *req = ha->req_q_map[1];
+ } else {
+ *req = vha->req;
+ *rsp = ha->rsp_q_map[0];
+ }
+}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index d04981848e56..eb35d2050f7a 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -13,10 +13,9 @@ static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t);
static void qla2x00_process_completed_request(struct scsi_qla_host *,
struct req_que *, uint32_t);
static void qla2x00_status_entry(scsi_qla_host_t *, struct rsp_que *, void *);
-static void qla2x00_status_cont_entry(scsi_qla_host_t *, sts_cont_entry_t *);
+static void qla2x00_status_cont_entry(struct rsp_que *, sts_cont_entry_t *);
static void qla2x00_error_entry(scsi_qla_host_t *, struct rsp_que *,
sts_entry_t *);
-static struct scsi_qla_host *qla2x00_get_rsp_host(struct rsp_que *);
/**
* qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200.
@@ -51,7 +50,7 @@ qla2100_intr_handler(int irq, void *dev_id)
status = 0;
spin_lock(&ha->hardware_lock);
- vha = qla2x00_get_rsp_host(rsp);
+ vha = pci_get_drvdata(ha->pdev);
for (iter = 50; iter--; ) {
hccr = RD_REG_WORD(&reg->hccr);
if (hccr & HCCR_RISC_PAUSE) {
@@ -147,7 +146,7 @@ qla2300_intr_handler(int irq, void *dev_id)
status = 0;
spin_lock(&ha->hardware_lock);
- vha = qla2x00_get_rsp_host(rsp);
+ vha = pci_get_drvdata(ha->pdev);
for (iter = 50; iter--; ) {
stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
if (stat & HSR_RISC_PAUSED) {
@@ -685,7 +684,7 @@ skip_rio:
vha->host_no));
if (IS_FWI2_CAPABLE(ha))
- qla24xx_process_response_queue(rsp);
+ qla24xx_process_response_queue(vha, rsp);
else
qla2x00_process_response_queue(rsp);
break;
@@ -766,7 +765,10 @@ qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, void *data)
struct qla_hw_data *ha = vha->hw;
struct req_que *req = NULL;
- req = ha->req_q_map[vha->req_ques[0]];
+ if (!ql2xqfulltracking)
+ return;
+
+ req = vha->req;
if (!req)
return;
if (req->max_q_depth <= sdev->queue_depth)
@@ -808,6 +810,9 @@ qla2x00_ramp_up_queue_depth(scsi_qla_host_t *vha, struct req_que *req,
fc_port_t *fcport;
struct scsi_device *sdev;
+ if (!ql2xqfulltracking)
+ return;
+
sdev = sp->cmd->device;
if (sdev->queue_depth >= req->max_q_depth)
return;
@@ -858,8 +863,8 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha,
qla2x00_ramp_up_queue_depth(vha, req, sp);
qla2x00_sp_compl(ha, sp);
} else {
- DEBUG2(printk("scsi(%ld): Invalid ISP SCSI completion handle\n",
- vha->host_no));
+ DEBUG2(printk("scsi(%ld) Req:%d: Invalid ISP SCSI completion"
+ " handle(%d)\n", vha->host_no, req->id, index));
qla_printk(KERN_WARNING, ha,
"Invalid ISP SCSI completion handle\n");
@@ -881,7 +886,7 @@ qla2x00_process_response_queue(struct rsp_que *rsp)
uint16_t handle_cnt;
uint16_t cnt;
- vha = qla2x00_get_rsp_host(rsp);
+ vha = pci_get_drvdata(ha->pdev);
if (!vha->flags.online)
return;
@@ -926,7 +931,7 @@ qla2x00_process_response_queue(struct rsp_que *rsp)
}
break;
case STATUS_CONT_TYPE:
- qla2x00_status_cont_entry(vha, (sts_cont_entry_t *)pkt);
+ qla2x00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt);
break;
default:
/* Type Not Supported. */
@@ -945,7 +950,8 @@ qla2x00_process_response_queue(struct rsp_que *rsp)
}
static inline void
-qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len)
+qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len,
+ struct rsp_que *rsp)
{
struct scsi_cmnd *cp = sp->cmd;
@@ -962,7 +968,7 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len)
sp->request_sense_ptr += sense_len;
sp->request_sense_length -= sense_len;
if (sp->request_sense_length != 0)
- sp->fcport->vha->status_srb = sp;
+ rsp->status_srb = sp;
DEBUG5(printk("%s(): Check condition Sense data, scsi(%ld:%d:%d:%d) "
"cmd=%p pid=%ld\n", __func__, sp->fcport->vha->host_no,
@@ -992,7 +998,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
uint32_t sense_len, rsp_info_len, resid_len, fw_resid_len;
uint8_t *rsp_info, *sense_data;
struct qla_hw_data *ha = vha->hw;
- struct req_que *req = rsp->req;
+ uint32_t handle;
+ uint16_t que;
+ struct req_que *req;
sts = (sts_entry_t *) pkt;
sts24 = (struct sts_entry_24xx *) pkt;
@@ -1003,18 +1011,20 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
comp_status = le16_to_cpu(sts->comp_status);
scsi_status = le16_to_cpu(sts->scsi_status) & SS_MASK;
}
-
+ handle = (uint32_t) LSW(sts->handle);
+ que = MSW(sts->handle);
+ req = ha->req_q_map[que];
/* Fast path completion. */
if (comp_status == CS_COMPLETE && scsi_status == 0) {
- qla2x00_process_completed_request(vha, req, sts->handle);
+ qla2x00_process_completed_request(vha, req, handle);
return;
}
/* Validate handle. */
- if (sts->handle < MAX_OUTSTANDING_COMMANDS) {
- sp = req->outstanding_cmds[sts->handle];
- req->outstanding_cmds[sts->handle] = NULL;
+ if (handle < MAX_OUTSTANDING_COMMANDS) {
+ sp = req->outstanding_cmds[handle];
+ req->outstanding_cmds[handle] = NULL;
} else
sp = NULL;
@@ -1030,7 +1040,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
cp = sp->cmd;
if (cp == NULL) {
DEBUG2(printk("scsi(%ld): Command already returned back to OS "
- "pkt->handle=%d sp=%p.\n", vha->host_no, sts->handle, sp));
+ "pkt->handle=%d sp=%p.\n", vha->host_no, handle, sp));
qla_printk(KERN_WARNING, ha,
"Command is NULL: already returned to OS (sp=%p)\n", sp);
@@ -1121,6 +1131,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
scsi_status));
/* Adjust queue depth for all luns on the port. */
+ if (!ql2xqfulltracking)
+ break;
fcport->last_queue_full = jiffies;
starget_for_each_device(cp->device->sdev_target,
fcport, qla2x00_adjust_sdev_qdepth_down);
@@ -1133,7 +1145,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
if (!(scsi_status & SS_SENSE_LEN_VALID))
break;
- qla2x00_handle_sense(sp, sense_data, sense_len);
+ qla2x00_handle_sense(sp, sense_data, sense_len, rsp);
break;
case CS_DATA_UNDERRUN:
@@ -1179,6 +1191,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
* Adjust queue depth for all luns on the
* port.
*/
+ if (!ql2xqfulltracking)
+ break;
fcport->last_queue_full = jiffies;
starget_for_each_device(
cp->device->sdev_target, fcport,
@@ -1192,7 +1206,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
if (!(scsi_status & SS_SENSE_LEN_VALID))
break;
- qla2x00_handle_sense(sp, sense_data, sense_len);
+ qla2x00_handle_sense(sp, sense_data, sense_len, rsp);
} else {
/*
* If RISC reports underrun and target does not report
@@ -1334,7 +1348,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
}
/* Place command on done queue. */
- if (vha->status_srb == NULL)
+ if (rsp->status_srb == NULL)
qla2x00_sp_compl(ha, sp);
}
@@ -1346,11 +1360,11 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
* Extended sense data.
*/
static void
-qla2x00_status_cont_entry(scsi_qla_host_t *vha, sts_cont_entry_t *pkt)
+qla2x00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt)
{
uint8_t sense_sz = 0;
- struct qla_hw_data *ha = vha->hw;
- srb_t *sp = vha->status_srb;
+ struct qla_hw_data *ha = rsp->hw;
+ srb_t *sp = rsp->status_srb;
struct scsi_cmnd *cp;
if (sp != NULL && sp->request_sense_length != 0) {
@@ -1362,7 +1376,7 @@ qla2x00_status_cont_entry(scsi_qla_host_t *vha, sts_cont_entry_t *pkt)
"cmd is NULL: already returned to OS (sp=%p)\n",
sp);
- vha->status_srb = NULL;
+ rsp->status_srb = NULL;
return;
}
@@ -1383,7 +1397,7 @@ qla2x00_status_cont_entry(scsi_qla_host_t *vha, sts_cont_entry_t *pkt)
/* Place command on done queue. */
if (sp->request_sense_length == 0) {
- vha->status_srb = NULL;
+ rsp->status_srb = NULL;
qla2x00_sp_compl(ha, sp);
}
}
@@ -1399,7 +1413,9 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
{
srb_t *sp;
struct qla_hw_data *ha = vha->hw;
- struct req_que *req = rsp->req;
+ uint32_t handle = LSW(pkt->handle);
+ uint16_t que = MSW(pkt->handle);
+ struct req_que *req = ha->req_q_map[que];
#if defined(QL_DEBUG_LEVEL_2)
if (pkt->entry_status & RF_INV_E_ORDER)
qla_printk(KERN_ERR, ha, "%s: Invalid Entry Order\n", __func__);
@@ -1417,14 +1433,14 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
#endif
/* Validate handle. */
- if (pkt->handle < MAX_OUTSTANDING_COMMANDS)
- sp = req->outstanding_cmds[pkt->handle];
+ if (handle < MAX_OUTSTANDING_COMMANDS)
+ sp = req->outstanding_cmds[handle];
else
sp = NULL;
if (sp) {
/* Free outstanding command slot. */
- req->outstanding_cmds[pkt->handle] = NULL;
+ req->outstanding_cmds[handle] = NULL;
/* Bad payload or header */
if (pkt->entry_status &
@@ -1486,13 +1502,10 @@ qla24xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
* qla24xx_process_response_queue() - Process response queue entries.
* @ha: SCSI driver HA context
*/
-void
-qla24xx_process_response_queue(struct rsp_que *rsp)
+void qla24xx_process_response_queue(struct scsi_qla_host *vha,
+ struct rsp_que *rsp)
{
struct sts_entry_24xx *pkt;
- struct scsi_qla_host *vha;
-
- vha = qla2x00_get_rsp_host(rsp);
if (!vha->flags.online)
return;
@@ -1523,7 +1536,7 @@ qla24xx_process_response_queue(struct rsp_que *rsp)
qla2x00_status_entry(vha, rsp, pkt);
break;
case STATUS_CONT_TYPE:
- qla2x00_status_cont_entry(vha, (sts_cont_entry_t *)pkt);
+ qla2x00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt);
break;
case VP_RPT_ID_IOCB_TYPE:
qla24xx_report_id_acquisition(vha,
@@ -1626,7 +1639,7 @@ qla24xx_intr_handler(int irq, void *dev_id)
status = 0;
spin_lock(&ha->hardware_lock);
- vha = qla2x00_get_rsp_host(rsp);
+ vha = pci_get_drvdata(ha->pdev);
for (iter = 50; iter--; ) {
stat = RD_REG_DWORD(&reg->host_status);
if (stat & HSRX_RISC_PAUSED) {
@@ -1664,7 +1677,7 @@ qla24xx_intr_handler(int irq, void *dev_id)
break;
case 0x13:
case 0x14:
- qla24xx_process_response_queue(rsp);
+ qla24xx_process_response_queue(vha, rsp);
break;
default:
DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
@@ -1692,6 +1705,7 @@ qla24xx_msix_rsp_q(int irq, void *dev_id)
struct qla_hw_data *ha;
struct rsp_que *rsp;
struct device_reg_24xx __iomem *reg;
+ struct scsi_qla_host *vha;
rsp = (struct rsp_que *) dev_id;
if (!rsp) {
@@ -1704,7 +1718,8 @@ qla24xx_msix_rsp_q(int irq, void *dev_id)
spin_lock_irq(&ha->hardware_lock);
- qla24xx_process_response_queue(rsp);
+ vha = qla25xx_get_host(rsp);
+ qla24xx_process_response_queue(vha, rsp);
WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
spin_unlock_irq(&ha->hardware_lock);
@@ -1717,7 +1732,6 @@ qla25xx_msix_rsp_q(int irq, void *dev_id)
{
struct qla_hw_data *ha;
struct rsp_que *rsp;
- struct device_reg_24xx __iomem *reg;
rsp = (struct rsp_que *) dev_id;
if (!rsp) {
@@ -1726,13 +1740,8 @@ qla25xx_msix_rsp_q(int irq, void *dev_id)
return IRQ_NONE;
}
ha = rsp->hw;
- reg = &ha->iobase->isp24;
- spin_lock_irq(&ha->hardware_lock);
-
- qla24xx_process_response_queue(rsp);
-
- spin_unlock_irq(&ha->hardware_lock);
+ queue_work_on((int) (rsp->id - 1), ha->wq, &rsp->q_work);
return IRQ_HANDLED;
}
@@ -1760,7 +1769,7 @@ qla24xx_msix_default(int irq, void *dev_id)
status = 0;
spin_lock_irq(&ha->hardware_lock);
- vha = qla2x00_get_rsp_host(rsp);
+ vha = pci_get_drvdata(ha->pdev);
do {
stat = RD_REG_DWORD(&reg->host_status);
if (stat & HSRX_RISC_PAUSED) {
@@ -1798,7 +1807,7 @@ qla24xx_msix_default(int irq, void *dev_id)
break;
case 0x13:
case 0x14:
- qla24xx_process_response_queue(rsp);
+ qla24xx_process_response_queue(vha, rsp);
break;
default:
DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
@@ -1822,31 +1831,14 @@ qla24xx_msix_default(int irq, void *dev_id)
/* Interrupt handling helpers. */
struct qla_init_msix_entry {
- uint16_t entry;
- uint16_t index;
const char *name;
irq_handler_t handler;
};
-static struct qla_init_msix_entry base_queue = {
- .entry = 0,
- .index = 0,
- .name = "qla2xxx (default)",
- .handler = qla24xx_msix_default,
-};
-
-static struct qla_init_msix_entry base_rsp_queue = {
- .entry = 1,
- .index = 1,
- .name = "qla2xxx (rsp_q)",
- .handler = qla24xx_msix_rsp_q,
-};
-
-static struct qla_init_msix_entry multi_rsp_queue = {
- .entry = 1,
- .index = 1,
- .name = "qla2xxx (multi_q)",
- .handler = qla25xx_msix_rsp_q,
+static struct qla_init_msix_entry msix_entries[3] = {
+ { "qla2xxx (default)", qla24xx_msix_default },
+ { "qla2xxx (rsp_q)", qla24xx_msix_rsp_q },
+ { "qla2xxx (multiq)", qla25xx_msix_rsp_q },
};
static void
@@ -1873,7 +1865,6 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
int i, ret;
struct msix_entry *entries;
struct qla_msix_entry *qentry;
- struct qla_init_msix_entry *msix_queue;
entries = kzalloc(sizeof(struct msix_entry) * ha->msix_count,
GFP_KERNEL);
@@ -1900,7 +1891,7 @@ msix_failed:
ha->msix_count, ret);
goto msix_out;
}
- ha->max_queues = ha->msix_count - 1;
+ ha->max_rsp_queues = ha->msix_count - 1;
}
ha->msix_entries = kzalloc(sizeof(struct qla_msix_entry) *
ha->msix_count, GFP_KERNEL);
@@ -1918,45 +1909,27 @@ msix_failed:
qentry->rsp = NULL;
}
- /* Enable MSI-X for AENs for queue 0 */
- qentry = &ha->msix_entries[0];
- ret = request_irq(qentry->vector, base_queue.handler, 0,
- base_queue.name, rsp);
- if (ret) {
- qla_printk(KERN_WARNING, ha,
+ /* Enable MSI-X vectors for the base queue */
+ for (i = 0; i < 2; i++) {
+ qentry = &ha->msix_entries[i];
+ ret = request_irq(qentry->vector, msix_entries[i].handler,
+ 0, msix_entries[i].name, rsp);
+ if (ret) {
+ qla_printk(KERN_WARNING, ha,
"MSI-X: Unable to register handler -- %x/%d.\n",
qentry->vector, ret);
- qla24xx_disable_msix(ha);
- goto msix_out;
+ qla24xx_disable_msix(ha);
+ ha->mqenable = 0;
+ goto msix_out;
+ }
+ qentry->have_irq = 1;
+ qentry->rsp = rsp;
+ rsp->msix = qentry;
}
- qentry->have_irq = 1;
- qentry->rsp = rsp;
/* Enable MSI-X vector for response queue update for queue 0 */
- if (ha->max_queues > 1 && ha->mqiobase) {
+ if (ha->mqiobase && (ha->max_rsp_queues > 1 || ha->max_req_queues > 1))
ha->mqenable = 1;
- msix_queue = &multi_rsp_queue;
- qla_printk(KERN_INFO, ha,
- "MQ enabled, Number of Queue Resources: %d \n",
- ha->max_queues);
- } else {
- ha->mqenable = 0;
- msix_queue = &base_rsp_queue;
- }
-
- qentry = &ha->msix_entries[1];
- ret = request_irq(qentry->vector, msix_queue->handler, 0,
- msix_queue->name, rsp);
- if (ret) {
- qla_printk(KERN_WARNING, ha,
- "MSI-X: Unable to register handler -- %x/%d.\n",
- qentry->vector, ret);
- qla24xx_disable_msix(ha);
- ha->mqenable = 0;
- goto msix_out;
- }
- qentry->have_irq = 1;
- qentry->rsp = rsp;
msix_out:
kfree(entries);
@@ -2063,35 +2036,11 @@ qla2x00_free_irqs(scsi_qla_host_t *vha)
}
}
-static struct scsi_qla_host *
-qla2x00_get_rsp_host(struct rsp_que *rsp)
-{
- srb_t *sp;
- struct qla_hw_data *ha = rsp->hw;
- struct scsi_qla_host *vha = NULL;
- struct sts_entry_24xx *pkt;
- struct req_que *req;
-
- if (rsp->id) {
- pkt = (struct sts_entry_24xx *) rsp->ring_ptr;
- req = rsp->req;
- if (pkt && pkt->handle < MAX_OUTSTANDING_COMMANDS) {
- sp = req->outstanding_cmds[pkt->handle];
- if (sp)
- vha = sp->fcport->vha;
- }
- }
- if (!vha)
- /* handle it in base queue */
- vha = pci_get_drvdata(ha->pdev);
-
- return vha;
-}
int qla25xx_request_irq(struct rsp_que *rsp)
{
struct qla_hw_data *ha = rsp->hw;
- struct qla_init_msix_entry *intr = &multi_rsp_queue;
+ struct qla_init_msix_entry *intr = &msix_entries[2];
struct qla_msix_entry *msix = rsp->msix;
int ret;
@@ -2106,3 +2055,30 @@ int qla25xx_request_irq(struct rsp_que *rsp)
msix->rsp = rsp;
return ret;
}
+
+struct scsi_qla_host *
+qla25xx_get_host(struct rsp_que *rsp)
+{
+ srb_t *sp;
+ struct qla_hw_data *ha = rsp->hw;
+ struct scsi_qla_host *vha = NULL;
+ struct sts_entry_24xx *pkt;
+ struct req_que *req;
+ uint16_t que;
+ uint32_t handle;
+
+ pkt = (struct sts_entry_24xx *) rsp->ring_ptr;
+ que = MSW(pkt->handle);
+ handle = (uint32_t) LSW(pkt->handle);
+ req = ha->req_q_map[que];
+ if (handle < MAX_OUTSTANDING_COMMANDS) {
+ sp = req->outstanding_cmds[handle];
+ if (sp)
+ return sp->fcport->vha;
+ else
+ goto base_que;
+ }
+base_que:
+ vha = pci_get_drvdata(ha->pdev);
+ return vha;
+}
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index e67c1660bf46..7d0eeec9ba57 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -748,20 +748,20 @@ qla2x00_issue_iocb(scsi_qla_host_t *vha, void *buffer, dma_addr_t phys_addr,
* Kernel context.
*/
int
-qla2x00_abort_command(scsi_qla_host_t *vha, srb_t *sp, struct req_que *req)
+qla2x00_abort_command(srb_t *sp)
{
unsigned long flags = 0;
- fc_port_t *fcport;
int rval;
uint32_t handle = 0;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
+ fc_port_t *fcport = sp->fcport;
+ scsi_qla_host_t *vha = fcport->vha;
struct qla_hw_data *ha = vha->hw;
+ struct req_que *req = vha->req;
DEBUG11(printk("qla2x00_abort_command(%ld): entered.\n", vha->host_no));
- fcport = sp->fcport;
-
spin_lock_irqsave(&ha->hardware_lock, flags);
for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) {
if (req->outstanding_cmds[handle] == sp)
@@ -800,7 +800,7 @@ qla2x00_abort_command(scsi_qla_host_t *vha, srb_t *sp, struct req_que *req)
}
int
-qla2x00_abort_target(struct fc_port *fcport, unsigned int l)
+qla2x00_abort_target(struct fc_port *fcport, unsigned int l, int tag)
{
int rval, rval2;
mbx_cmd_t mc;
@@ -813,8 +813,8 @@ qla2x00_abort_target(struct fc_port *fcport, unsigned int l)
l = l;
vha = fcport->vha;
- req = vha->hw->req_q_map[0];
- rsp = vha->hw->rsp_q_map[0];
+ req = vha->hw->req_q_map[tag];
+ rsp = vha->hw->rsp_q_map[tag];
mcp->mb[0] = MBC_ABORT_TARGET;
mcp->out_mb = MBX_9|MBX_2|MBX_1|MBX_0;
if (HAS_EXTENDED_IDS(vha->hw)) {
@@ -850,7 +850,7 @@ qla2x00_abort_target(struct fc_port *fcport, unsigned int l)
}
int
-qla2x00_lun_reset(struct fc_port *fcport, unsigned int l)
+qla2x00_lun_reset(struct fc_port *fcport, unsigned int l, int tag)
{
int rval, rval2;
mbx_cmd_t mc;
@@ -862,8 +862,8 @@ qla2x00_lun_reset(struct fc_port *fcport, unsigned int l)
DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->vha->host_no));
vha = fcport->vha;
- req = vha->hw->req_q_map[0];
- rsp = vha->hw->rsp_q_map[0];
+ req = vha->hw->req_q_map[tag];
+ rsp = vha->hw->rsp_q_map[tag];
mcp->mb[0] = MBC_LUN_RESET;
mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0;
if (HAS_EXTENDED_IDS(vha->hw))
@@ -931,6 +931,8 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa,
mcp->mb[9] = vha->vp_idx;
mcp->out_mb = MBX_9|MBX_0;
mcp->in_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+ if (IS_QLA81XX(vha->hw))
+ mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
@@ -952,9 +954,19 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa,
DEBUG2_3_11(printk("qla2x00_get_adapter_id(%ld): failed=%x.\n",
vha->host_no, rval));
} else {
- /*EMPTY*/
DEBUG11(printk("qla2x00_get_adapter_id(%ld): done.\n",
vha->host_no));
+
+ if (IS_QLA81XX(vha->hw)) {
+ vha->fcoe_vlan_id = mcp->mb[9] & 0xfff;
+ vha->fcoe_fcf_idx = mcp->mb[10];
+ vha->fcoe_vn_port_mac[5] = mcp->mb[11] >> 8;
+ vha->fcoe_vn_port_mac[4] = mcp->mb[11] & 0xff;
+ vha->fcoe_vn_port_mac[3] = mcp->mb[12] >> 8;
+ vha->fcoe_vn_port_mac[2] = mcp->mb[12] & 0xff;
+ vha->fcoe_vn_port_mac[1] = mcp->mb[13] >> 8;
+ vha->fcoe_vn_port_mac[0] = mcp->mb[13] & 0xff;
+ }
}
return rval;
@@ -1480,9 +1492,17 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
dma_addr_t lg_dma;
uint32_t iop[2];
struct qla_hw_data *ha = vha->hw;
+ struct req_que *req;
+ struct rsp_que *rsp;
DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+ if (ql2xmultique_tag)
+ req = ha->req_q_map[0];
+ else
+ req = vha->req;
+ rsp = req->rsp;
+
lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma);
if (lg == NULL) {
DEBUG2_3(printk("%s(%ld): failed to allocate Login IOCB.\n",
@@ -1493,6 +1513,7 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
lg->entry_type = LOGINOUT_PORT_IOCB_TYPE;
lg->entry_count = 1;
+ lg->handle = MAKE_HANDLE(req->id, lg->handle);
lg->nport_handle = cpu_to_le16(loop_id);
lg->control_flags = __constant_cpu_to_le16(LCF_COMMAND_PLOGI);
if (opt & BIT_0)
@@ -1741,6 +1762,8 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
struct logio_entry_24xx *lg;
dma_addr_t lg_dma;
struct qla_hw_data *ha = vha->hw;
+ struct req_que *req;
+ struct rsp_que *rsp;
DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
@@ -1752,8 +1775,14 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
}
memset(lg, 0, sizeof(struct logio_entry_24xx));
+ if (ql2xmaxqueues > 1)
+ req = ha->req_q_map[0];
+ else
+ req = vha->req;
+ rsp = req->rsp;
lg->entry_type = LOGINOUT_PORT_IOCB_TYPE;
lg->entry_count = 1;
+ lg->handle = MAKE_HANDLE(req->id, lg->handle);
lg->nport_handle = cpu_to_le16(loop_id);
lg->control_flags =
__constant_cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO);
@@ -1864,9 +1893,6 @@ qla2x00_full_login_lip(scsi_qla_host_t *vha)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- if (IS_QLA81XX(vha->hw))
- return QLA_SUCCESS;
-
DEBUG11(printk("qla2x00_full_login_lip(%ld): entered.\n",
vha->host_no));
@@ -2195,21 +2221,21 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats,
}
int
-qla24xx_abort_command(scsi_qla_host_t *vha, srb_t *sp, struct req_que *req)
+qla24xx_abort_command(srb_t *sp)
{
int rval;
- fc_port_t *fcport;
unsigned long flags = 0;
struct abort_entry_24xx *abt;
dma_addr_t abt_dma;
uint32_t handle;
+ fc_port_t *fcport = sp->fcport;
+ struct scsi_qla_host *vha = fcport->vha;
struct qla_hw_data *ha = vha->hw;
+ struct req_que *req = vha->req;
DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
- fcport = sp->fcport;
-
spin_lock_irqsave(&ha->hardware_lock, flags);
for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) {
if (req->outstanding_cmds[handle] == sp)
@@ -2231,6 +2257,7 @@ qla24xx_abort_command(scsi_qla_host_t *vha, srb_t *sp, struct req_que *req)
abt->entry_type = ABORT_IOCB_TYPE;
abt->entry_count = 1;
+ abt->handle = MAKE_HANDLE(req->id, abt->handle);
abt->nport_handle = cpu_to_le16(fcport->loop_id);
abt->handle_to_abort = handle;
abt->port_id[0] = fcport->d_id.b.al_pa;
@@ -2272,7 +2299,7 @@ struct tsk_mgmt_cmd {
static int
__qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
- unsigned int l)
+ unsigned int l, int tag)
{
int rval, rval2;
struct tsk_mgmt_cmd *tsk;
@@ -2286,8 +2313,11 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
vha = fcport->vha;
ha = vha->hw;
- req = ha->req_q_map[0];
- rsp = ha->rsp_q_map[0];
+ req = vha->req;
+ if (ql2xmultique_tag)
+ rsp = ha->rsp_q_map[tag + 1];
+ else
+ rsp = req->rsp;
tsk = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma);
if (tsk == NULL) {
DEBUG2_3(printk("%s(%ld): failed to allocate Task Management "
@@ -2298,6 +2328,7 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
tsk->p.tsk.entry_type = TSK_MGMT_IOCB_TYPE;
tsk->p.tsk.entry_count = 1;
+ tsk->p.tsk.handle = MAKE_HANDLE(req->id, tsk->p.tsk.handle);
tsk->p.tsk.nport_handle = cpu_to_le16(fcport->loop_id);
tsk->p.tsk.timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
tsk->p.tsk.control_flags = cpu_to_le32(type);
@@ -2344,15 +2375,15 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
}
int
-qla24xx_abort_target(struct fc_port *fcport, unsigned int l)
+qla24xx_abort_target(struct fc_port *fcport, unsigned int l, int tag)
{
- return __qla24xx_issue_tmf("Target", TCF_TARGET_RESET, fcport, l);
+ return __qla24xx_issue_tmf("Target", TCF_TARGET_RESET, fcport, l, tag);
}
int
-qla24xx_lun_reset(struct fc_port *fcport, unsigned int l)
+qla24xx_lun_reset(struct fc_port *fcport, unsigned int l, int tag)
{
- return __qla24xx_issue_tmf("Lun", TCF_LUN_RESET, fcport, l);
+ return __qla24xx_issue_tmf("Lun", TCF_LUN_RESET, fcport, l, tag);
}
int
@@ -2446,6 +2477,8 @@ qla2x00_stop_firmware(scsi_qla_host_t *vha)
if (rval != QLA_SUCCESS) {
DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
vha->host_no, rval));
+ if (mcp->mb[0] == MBS_INVALID_COMMAND)
+ rval = QLA_INVALID_COMMAND;
} else {
DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
}
@@ -3141,6 +3174,8 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req)
WRT_REG_DWORD(&reg->req_q_in, 0);
WRT_REG_DWORD(&reg->req_q_out, 0);
}
+ req->req_q_in = &reg->req_q_in;
+ req->req_q_out = &reg->req_q_out;
spin_unlock_irqrestore(&ha->hardware_lock, flags);
rval = qla2x00_mailbox_command(vha, mcp);
@@ -3167,7 +3202,6 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp)
mcp->mb[6] = MSW(MSD(rsp->dma));
mcp->mb[7] = LSW(MSD(rsp->dma));
mcp->mb[5] = rsp->length;
- mcp->mb[11] = rsp->vp_idx;
mcp->mb[14] = rsp->msix->entry;
mcp->mb[13] = rsp->rid;
@@ -3179,7 +3213,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp)
mcp->mb[8] = 0;
/* que out ptr index */
mcp->mb[9] = 0;
- mcp->out_mb = MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|MBX_7
+ mcp->out_mb = MBX_14|MBX_13|MBX_9|MBX_8|MBX_7
|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_0;
mcp->flags = MBX_DMA_OUT;
@@ -3384,7 +3418,7 @@ qla2x00_read_edc(scsi_qla_host_t *vha, uint16_t dev, uint16_t adr,
DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
vha->host_no, rval, mcp->mb[0]));
} else {
- DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
+ DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
}
return rval;
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index 51716c7e3008..650bcef08f2a 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -398,9 +398,8 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
qla2x00_start_timer(vha, qla2x00_timer, WATCH_INTERVAL);
- memset(vha->req_ques, 0, sizeof(vha->req_ques));
- vha->req_ques[0] = ha->req_q_map[0]->id;
- host->can_queue = ha->req_q_map[0]->length + 128;
+ vha->req = base_vha->req;
+ host->can_queue = base_vha->req->length + 128;
host->this_id = 255;
host->cmd_per_lun = 3;
host->max_cmd_len = MAX_CMDSZ;
@@ -515,76 +514,53 @@ int qla25xx_update_req_que(struct scsi_qla_host *vha, uint8_t que, uint8_t qos)
/* Delete all queues for a given vhost */
int
-qla25xx_delete_queues(struct scsi_qla_host *vha, uint8_t que_no)
+qla25xx_delete_queues(struct scsi_qla_host *vha)
{
int cnt, ret = 0;
struct req_que *req = NULL;
struct rsp_que *rsp = NULL;
struct qla_hw_data *ha = vha->hw;
- if (que_no) {
- /* Delete request queue */
- req = ha->req_q_map[que_no];
+ /* Delete request queues */
+ for (cnt = 1; cnt < ha->max_req_queues; cnt++) {
+ req = ha->req_q_map[cnt];
if (req) {
- rsp = req->rsp;
ret = qla25xx_delete_req_que(vha, req);
if (ret != QLA_SUCCESS) {
qla_printk(KERN_WARNING, ha,
- "Couldn't delete req que %d\n", req->id);
+ "Couldn't delete req que %d\n",
+ req->id);
return ret;
}
- /* Delete associated response queue */
- if (rsp) {
- ret = qla25xx_delete_rsp_que(vha, rsp);
- if (ret != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
- "Couldn't delete rsp que %d\n",
- rsp->id);
- return ret;
- }
- }
}
- } else { /* delete all queues of this host */
- for (cnt = 0; cnt < QLA_MAX_HOST_QUES; cnt++) {
- /* Delete request queues */
- req = ha->req_q_map[vha->req_ques[cnt]];
- if (req && req->id) {
- rsp = req->rsp;
- ret = qla25xx_delete_req_que(vha, req);
- if (ret != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
- "Couldn't delete req que %d\n",
- vha->req_ques[cnt]);
- return ret;
- }
- vha->req_ques[cnt] = ha->req_q_map[0]->id;
- /* Delete associated response queue */
- if (rsp && rsp->id) {
- ret = qla25xx_delete_rsp_que(vha, rsp);
- if (ret != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
- "Couldn't delete rsp que %d\n",
- rsp->id);
- return ret;
- }
- }
+ }
+
+ /* Delete response queues */
+ for (cnt = 1; cnt < ha->max_rsp_queues; cnt++) {
+ rsp = ha->rsp_q_map[cnt];
+ if (rsp) {
+ ret = qla25xx_delete_rsp_que(vha, rsp);
+ if (ret != QLA_SUCCESS) {
+ qla_printk(KERN_WARNING, ha,
+ "Couldn't delete rsp que %d\n",
+ rsp->id);
+ return ret;
}
}
}
- qla_printk(KERN_INFO, ha, "Queues deleted for vport:%d\n",
- vha->vp_idx);
return ret;
}
int
qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
- uint8_t vp_idx, uint16_t rid, uint8_t rsp_que, uint8_t qos)
+ uint8_t vp_idx, uint16_t rid, int rsp_que, uint8_t qos)
{
int ret = 0;
struct req_que *req = NULL;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
uint16_t que_id = 0;
device_reg_t __iomem *reg;
+ uint32_t cnt;
req = kzalloc(sizeof(struct req_que), GFP_KERNEL);
if (req == NULL) {
@@ -604,8 +580,8 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
}
mutex_lock(&ha->vport_lock);
- que_id = find_first_zero_bit(ha->req_qid_map, ha->max_queues);
- if (que_id >= ha->max_queues) {
+ que_id = find_first_zero_bit(ha->req_qid_map, ha->max_req_queues);
+ if (que_id >= ha->max_req_queues) {
mutex_unlock(&ha->vport_lock);
qla_printk(KERN_INFO, ha, "No resources to create "
"additional request queue\n");
@@ -617,10 +593,10 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
req->vp_idx = vp_idx;
req->qos = qos;
- if (ha->rsp_q_map[rsp_que]) {
+ if (rsp_que < 0)
+ req->rsp = NULL;
+ else
req->rsp = ha->rsp_q_map[rsp_que];
- req->rsp->req = req;
- }
/* Use alternate PCI bus number */
if (MSB(req->rid))
options |= BIT_4;
@@ -628,13 +604,16 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
if (LSB(req->rid))
options |= BIT_5;
req->options = options;
+
+ for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)
+ req->outstanding_cmds[cnt] = NULL;
+ req->current_outstanding_cmd = 1;
+
req->ring_ptr = req->ring;
req->ring_index = 0;
req->cnt = req->length;
req->id = que_id;
reg = ISP_QUE_REG(ha, que_id);
- req->req_q_in = &reg->isp25mq.req_q_in;
- req->req_q_out = &reg->isp25mq.req_q_out;
req->max_q_depth = ha->req_q_map[0]->max_q_depth;
mutex_unlock(&ha->vport_lock);
@@ -654,10 +633,19 @@ que_failed:
return 0;
}
+static void qla_do_work(struct work_struct *work)
+{
+ struct rsp_que *rsp = container_of(work, struct rsp_que, q_work);
+ struct scsi_qla_host *vha;
+
+ vha = qla25xx_get_host(rsp);
+ qla24xx_process_response_queue(vha, rsp);
+}
+
/* create response queue */
int
qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
- uint8_t vp_idx, uint16_t rid)
+ uint8_t vp_idx, uint16_t rid, int req)
{
int ret = 0;
struct rsp_que *rsp = NULL;
@@ -672,7 +660,7 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
goto que_failed;
}
- rsp->length = RESPONSE_ENTRY_CNT_2300;
+ rsp->length = RESPONSE_ENTRY_CNT_MQ;
rsp->ring = dma_alloc_coherent(&ha->pdev->dev,
(rsp->length + 1) * sizeof(response_t),
&rsp->dma, GFP_KERNEL);
@@ -683,8 +671,8 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
}
mutex_lock(&ha->vport_lock);
- que_id = find_first_zero_bit(ha->rsp_qid_map, ha->max_queues);
- if (que_id >= ha->max_queues) {
+ que_id = find_first_zero_bit(ha->rsp_qid_map, ha->max_rsp_queues);
+ if (que_id >= ha->max_rsp_queues) {
mutex_unlock(&ha->vport_lock);
qla_printk(KERN_INFO, ha, "No resources to create "
"additional response queue\n");
@@ -708,8 +696,6 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
if (LSB(rsp->rid))
options |= BIT_5;
rsp->options = options;
- rsp->ring_ptr = rsp->ring;
- rsp->ring_index = 0;
rsp->id = que_id;
reg = ISP_QUE_REG(ha, que_id);
rsp->rsp_q_in = &reg->isp25mq.rsp_q_in;
@@ -728,9 +714,14 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
mutex_unlock(&ha->vport_lock);
goto que_failed;
}
+ if (req >= 0)
+ rsp->req = ha->req_q_map[req];
+ else
+ rsp->req = NULL;
qla2x00_init_response_q_entries(rsp);
-
+ if (rsp->hw->wq)
+ INIT_WORK(&rsp->q_work, qla_do_work);
return rsp->id;
que_failed:
@@ -744,14 +735,16 @@ qla25xx_create_queues(struct scsi_qla_host *vha, uint8_t qos)
uint16_t options = 0;
uint8_t ret = 0;
struct qla_hw_data *ha = vha->hw;
+ struct rsp_que *rsp;
options |= BIT_1;
- ret = qla25xx_create_rsp_que(ha, options, vha->vp_idx, 0);
+ ret = qla25xx_create_rsp_que(ha, options, vha->vp_idx, 0, -1);
if (!ret) {
qla_printk(KERN_WARNING, ha, "Response Que create failed\n");
return ret;
} else
qla_printk(KERN_INFO, ha, "Response Que:%d created.\n", ret);
+ rsp = ha->rsp_q_map[ret];
options = 0;
if (qos & BIT_7)
@@ -759,10 +752,11 @@ qla25xx_create_queues(struct scsi_qla_host *vha, uint8_t qos)
ret = qla25xx_create_req_que(ha, options, vha->vp_idx, 0, ret,
qos & ~BIT_7);
if (ret) {
- vha->req_ques[0] = ret;
+ vha->req = ha->req_q_map[ret];
qla_printk(KERN_INFO, ha, "Request Que:%d created.\n", ret);
} else
qla_printk(KERN_WARNING, ha, "Request Que create failed\n");
+ rsp->req = ha->req_q_map[ret];
return ret;
}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index e4fdcdad80d0..f4f535536952 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -77,6 +77,14 @@ module_param(ql2xmaxqdepth, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xmaxqdepth,
"Maximum queue depth to report for target devices.");
+int ql2xqfulltracking = 1;
+module_param(ql2xqfulltracking, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(ql2xqfulltracking,
+ "Controls whether the driver tracks queue full status "
+ "returns and dynamically adjusts a scsi device's queue "
+ "depth. Default is 1, perform tracking. Set to 0 to "
+ "disable dynamic tracking and adjustment of queue depth.");
+
int ql2xqfullrampup = 120;
module_param(ql2xqfullrampup, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xqfullrampup,
@@ -96,6 +104,23 @@ MODULE_PARM_DESC(ql2xmaxqueues,
"Enables MQ settings "
"Default is 1 for single queue. Set it to number \
of queues in MQ mode.");
+
+int ql2xmultique_tag;
+module_param(ql2xmultique_tag, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xmultique_tag,
+ "Enables CPU affinity settings for the driver "
+ "Default is 0 for no affinity of request and response IO. "
+ "Set it to 1 to turn on the cpu affinity.");
+
+int ql2xfwloadbin;
+module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xfwloadbin,
+ "Option to specify location from which to load ISP firmware:\n"
+ " 2 -- load firmware via the request_firmware() (hotplug)\n"
+ " interface.\n"
+ " 1 -- load firmware from flash.\n"
+ " 0 -- use default semantics.\n");
+
/*
* SCSI host template entry points
*/
@@ -187,7 +212,7 @@ static void qla2x00_sp_free_dma(srb_t *);
/* -------------------------------------------------------------------------- */
static int qla2x00_alloc_queues(struct qla_hw_data *ha)
{
- ha->req_q_map = kzalloc(sizeof(struct req_que *) * ha->max_queues,
+ ha->req_q_map = kzalloc(sizeof(struct req_que *) * ha->max_req_queues,
GFP_KERNEL);
if (!ha->req_q_map) {
qla_printk(KERN_WARNING, ha,
@@ -195,7 +220,7 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha)
goto fail_req_map;
}
- ha->rsp_q_map = kzalloc(sizeof(struct rsp_que *) * ha->max_queues,
+ ha->rsp_q_map = kzalloc(sizeof(struct rsp_que *) * ha->max_rsp_queues,
GFP_KERNEL);
if (!ha->rsp_q_map) {
qla_printk(KERN_WARNING, ha,
@@ -213,16 +238,8 @@ fail_req_map:
return -ENOMEM;
}
-static void qla2x00_free_que(struct qla_hw_data *ha, struct req_que *req,
- struct rsp_que *rsp)
+static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req)
{
- if (rsp && rsp->ring)
- dma_free_coherent(&ha->pdev->dev,
- (rsp->length + 1) * sizeof(response_t),
- rsp->ring, rsp->dma);
-
- kfree(rsp);
- rsp = NULL;
if (req && req->ring)
dma_free_coherent(&ha->pdev->dev,
(req->length + 1) * sizeof(request_t),
@@ -232,22 +249,77 @@ static void qla2x00_free_que(struct qla_hw_data *ha, struct req_que *req,
req = NULL;
}
+static void qla2x00_free_rsp_que(struct qla_hw_data *ha, struct rsp_que *rsp)
+{
+ if (rsp && rsp->ring)
+ dma_free_coherent(&ha->pdev->dev,
+ (rsp->length + 1) * sizeof(response_t),
+ rsp->ring, rsp->dma);
+
+ kfree(rsp);
+ rsp = NULL;
+}
+
static void qla2x00_free_queues(struct qla_hw_data *ha)
{
struct req_que *req;
struct rsp_que *rsp;
int cnt;
- for (cnt = 0; cnt < ha->max_queues; cnt++) {
- rsp = ha->rsp_q_map[cnt];
+ for (cnt = 0; cnt < ha->max_req_queues; cnt++) {
req = ha->req_q_map[cnt];
- qla2x00_free_que(ha, req, rsp);
+ qla2x00_free_req_que(ha, req);
+ }
+ kfree(ha->req_q_map);
+ ha->req_q_map = NULL;
+
+ for (cnt = 0; cnt < ha->max_rsp_queues; cnt++) {
+ rsp = ha->rsp_q_map[cnt];
+ qla2x00_free_rsp_que(ha, rsp);
}
kfree(ha->rsp_q_map);
ha->rsp_q_map = NULL;
+}
- kfree(ha->req_q_map);
- ha->req_q_map = NULL;
+static int qla25xx_setup_mode(struct scsi_qla_host *vha)
+{
+ uint16_t options = 0;
+ int ques, req, ret;
+ struct qla_hw_data *ha = vha->hw;
+
+ if (ql2xmultique_tag) {
+ /* CPU affinity mode */
+ ha->wq = create_workqueue("qla2xxx_wq");
+ /* create a request queue for IO */
+ options |= BIT_7;
+ req = qla25xx_create_req_que(ha, options, 0, 0, -1,
+ QLA_DEFAULT_QUE_QOS);
+ if (!req) {
+ qla_printk(KERN_WARNING, ha,
+ "Can't create request queue\n");
+ goto fail;
+ }
+ vha->req = ha->req_q_map[req];
+ options |= BIT_1;
+ for (ques = 1; ques < ha->max_rsp_queues; ques++) {
+ ret = qla25xx_create_rsp_que(ha, options, 0, 0, req);
+ if (!ret) {
+ qla_printk(KERN_WARNING, ha,
+ "Response Queue create failed\n");
+ goto fail2;
+ }
+ }
+ DEBUG2(qla_printk(KERN_INFO, ha,
+ "CPU affinity mode enabled, no. of response"
+ " queues:%d, no. of request queues:%d\n",
+ ha->max_rsp_queues, ha->max_req_queues));
+ }
+ return 0;
+fail2:
+ qla25xx_delete_queues(vha);
+fail:
+ ha->mqenable = 0;
+ return 1;
}
static char *
@@ -387,7 +459,6 @@ qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport,
sp->fcport = fcport;
sp->cmd = cmd;
- sp->que = ha->req_q_map[0];
sp->flags = 0;
CMD_SP(cmd) = (void *)sp;
cmd->scsi_done = done;
@@ -612,7 +683,7 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *vha)
void
qla2x00_abort_fcport_cmds(fc_port_t *fcport)
{
- int cnt, que, id;
+ int cnt;
unsigned long flags;
srb_t *sp;
scsi_qla_host_t *vha = fcport->vha;
@@ -620,32 +691,27 @@ qla2x00_abort_fcport_cmds(fc_port_t *fcport)
struct req_que *req;
spin_lock_irqsave(&ha->hardware_lock, flags);
- for (que = 0; que < QLA_MAX_HOST_QUES; que++) {
- id = vha->req_ques[que];
- req = ha->req_q_map[id];
- if (!req)
+ req = vha->req;
+ for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
+ sp = req->outstanding_cmds[cnt];
+ if (!sp)
+ continue;
+ if (sp->fcport != fcport)
continue;
- for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
- sp = req->outstanding_cmds[cnt];
- if (!sp)
- continue;
- if (sp->fcport != fcport)
- continue;
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
- if (ha->isp_ops->abort_command(vha, sp, req)) {
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ if (ha->isp_ops->abort_command(sp)) {
+ DEBUG2(qla_printk(KERN_WARNING, ha,
+ "Abort failed -- %lx\n",
+ sp->cmd->serial_number));
+ } else {
+ if (qla2x00_eh_wait_on_command(sp->cmd) !=
+ QLA_SUCCESS)
DEBUG2(qla_printk(KERN_WARNING, ha,
- "Abort failed -- %lx\n",
+ "Abort failed while waiting -- %lx\n",
sp->cmd->serial_number));
- } else {
- if (qla2x00_eh_wait_on_command(sp->cmd) !=
- QLA_SUCCESS)
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "Abort failed while waiting -- %lx\n",
- sp->cmd->serial_number));
- }
- spin_lock_irqsave(&ha->hardware_lock, flags);
}
+ spin_lock_irqsave(&ha->hardware_lock, flags);
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
@@ -693,7 +759,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
unsigned long flags;
int wait = 0;
struct qla_hw_data *ha = vha->hw;
- struct req_que *req;
+ struct req_que *req = vha->req;
srb_t *spt;
qla2x00_block_error_handler(cmd);
@@ -709,7 +775,6 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
spt = (srb_t *) CMD_SP(cmd);
if (!spt)
return SUCCESS;
- req = spt->que;
/* Check active list for command command. */
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -726,7 +791,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
" pid=%ld.\n", __func__, vha->host_no, sp, serial));
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- if (ha->isp_ops->abort_command(vha, sp, req)) {
+ if (ha->isp_ops->abort_command(sp)) {
DEBUG2(printk("%s(%ld): abort_command "
"mbx failed.\n", __func__, vha->host_no));
ret = FAILED;
@@ -777,7 +842,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
return status;
spin_lock_irqsave(&ha->hardware_lock, flags);
- req = sp->que;
+ req = vha->req;
for (cnt = 1; status == QLA_SUCCESS &&
cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
sp = req->outstanding_cmds[cnt];
@@ -820,7 +885,7 @@ static char *reset_errors[] = {
static int
__qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
- struct scsi_cmnd *cmd, int (*do_reset)(struct fc_port *, unsigned int))
+ struct scsi_cmnd *cmd, int (*do_reset)(struct fc_port *, unsigned int, int))
{
scsi_qla_host_t *vha = shost_priv(cmd->device->host);
fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
@@ -841,7 +906,8 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
if (qla2x00_wait_for_loop_ready(vha) != QLA_SUCCESS)
goto eh_reset_failed;
err = 2;
- if (do_reset(fcport, cmd->device->lun) != QLA_SUCCESS)
+ if (do_reset(fcport, cmd->device->lun, cmd->request->cpu + 1)
+ != QLA_SUCCESS)
goto eh_reset_failed;
err = 3;
if (qla2x00_eh_wait_for_pending_commands(vha, cmd->device->id,
@@ -996,6 +1062,9 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
if (qla2x00_vp_abort_isp(vha))
goto eh_host_reset_lock;
} else {
+ if (ha->wq)
+ flush_workqueue(ha->wq);
+
set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
if (qla2x00_abort_isp(base_vha)) {
clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
@@ -1037,7 +1106,8 @@ qla2x00_loop_reset(scsi_qla_host_t *vha)
struct fc_port *fcport;
struct qla_hw_data *ha = vha->hw;
- if (ha->flags.enable_lip_full_login && !vha->vp_idx) {
+ if (ha->flags.enable_lip_full_login && !vha->vp_idx &&
+ !IS_QLA81XX(ha)) {
ret = qla2x00_full_login_lip(vha);
if (ret != QLA_SUCCESS) {
DEBUG2_3(printk("%s(%ld): failed: "
@@ -1064,7 +1134,7 @@ qla2x00_loop_reset(scsi_qla_host_t *vha)
if (fcport->port_type != FCT_TARGET)
continue;
- ret = ha->isp_ops->target_reset(fcport, 0);
+ ret = ha->isp_ops->target_reset(fcport, 0, 0);
if (ret != QLA_SUCCESS) {
DEBUG2_3(printk("%s(%ld): bus_reset failed: "
"target_reset=%d d_id=%x.\n", __func__,
@@ -1088,7 +1158,7 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
struct req_que *req;
spin_lock_irqsave(&ha->hardware_lock, flags);
- for (que = 0; que < ha->max_queues; que++) {
+ for (que = 0; que < ha->max_req_queues; que++) {
req = ha->req_q_map[que];
if (!req)
continue;
@@ -1123,7 +1193,7 @@ qla2xxx_slave_configure(struct scsi_device *sdev)
scsi_qla_host_t *vha = shost_priv(sdev->host);
struct qla_hw_data *ha = vha->hw;
struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
- struct req_que *req = ha->req_q_map[vha->req_ques[0]];
+ struct req_que *req = vha->req;
if (sdev->tagged_supported)
scsi_activate_tcq(sdev, req->max_q_depth);
@@ -1511,6 +1581,13 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha)
ha->fw_srisc_address = RISC_START_ADDRESS_2400;
break;
}
+
+ /* Get adapter physical port no from interrupt pin register. */
+ pci_read_config_byte(ha->pdev, PCI_INTERRUPT_PIN, &ha->port_no);
+ if (ha->port_no & 1)
+ ha->flags.port0 = 1;
+ else
+ ha->flags.port0 = 0;
}
static int
@@ -1518,6 +1595,7 @@ qla2x00_iospace_config(struct qla_hw_data *ha)
{
resource_size_t pio;
uint16_t msix;
+ int cpus;
if (pci_request_selected_regions(ha->pdev, ha->bars,
QLA2XXX_DRIVER_NAME)) {
@@ -1571,8 +1649,9 @@ skip_pio:
}
/* Determine queue resources */
- ha->max_queues = 1;
- if (ql2xmaxqueues <= 1 || (!IS_QLA25XX(ha) && !IS_QLA81XX(ha)))
+ ha->max_req_queues = ha->max_rsp_queues = 1;
+ if ((ql2xmaxqueues <= 1 || ql2xmultique_tag < 1) &&
+ (!IS_QLA25XX(ha) && !IS_QLA81XX(ha)))
goto mqiobase_exit;
ha->mqiobase = ioremap(pci_resource_start(ha->pdev, 3),
pci_resource_len(ha->pdev, 3));
@@ -1582,18 +1661,24 @@ skip_pio:
ha->msix_count = msix;
/* Max queues are bounded by available msix vectors */
/* queue 0 uses two msix vectors */
- if (ha->msix_count - 1 < ql2xmaxqueues)
- ha->max_queues = ha->msix_count - 1;
- else if (ql2xmaxqueues > QLA_MQ_SIZE)
- ha->max_queues = QLA_MQ_SIZE;
- else
- ha->max_queues = ql2xmaxqueues;
+ if (ql2xmultique_tag) {
+ cpus = num_online_cpus();
+ ha->max_rsp_queues = (ha->msix_count - 1 - cpus) ?
+ (cpus + 1) : (ha->msix_count - 1);
+ ha->max_req_queues = 2;
+ } else if (ql2xmaxqueues > 1) {
+ ha->max_req_queues = ql2xmaxqueues > QLA_MQ_SIZE ?
+ QLA_MQ_SIZE : ql2xmaxqueues;
+ DEBUG2(qla_printk(KERN_INFO, ha, "QoS mode set, max no"
+ " of request queues:%d\n", ha->max_req_queues));
+ }
qla_printk(KERN_INFO, ha,
"MSI-X vector count: %d\n", msix);
- }
+ } else
+ qla_printk(KERN_INFO, ha, "BAR 3 not enabled\n");
mqiobase_exit:
- ha->msix_count = ha->max_queues + 1;
+ ha->msix_count = ha->max_rsp_queues + 1;
return (0);
iospace_error_exit:
@@ -1803,14 +1888,15 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ret = -ENOMEM;
qla2x00_mem_free(ha);
- qla2x00_free_que(ha, req, rsp);
+ qla2x00_free_req_que(ha, req);
+ qla2x00_free_rsp_que(ha, rsp);
goto probe_hw_failed;
}
pci_set_drvdata(pdev, base_vha);
host = base_vha->host;
- base_vha->req_ques[0] = req->id;
+ base_vha->req = req;
host->can_queue = req->length + 128;
if (IS_QLA2XXX_MIDTYPE(ha))
base_vha->mgmt_svr_loop_id = 10 + base_vha->vp_idx;
@@ -1841,7 +1927,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
}
ha->rsp_q_map[0] = rsp;
ha->req_q_map[0] = req;
-
+ rsp->req = req;
+ req->rsp = rsp;
+ set_bit(0, ha->req_qid_map);
+ set_bit(0, ha->rsp_qid_map);
/* FWI2-capable only. */
req->req_q_in = &ha->iobase->isp24.req_q_in;
req->req_q_out = &ha->iobase->isp24.req_q_out;
@@ -1866,6 +1955,12 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
goto probe_failed;
}
+ if (ha->mqenable)
+ if (qla25xx_setup_mode(base_vha))
+ qla_printk(KERN_WARNING, ha,
+ "Can't create queues, falling back to single"
+ " queue mode\n");
+
/*
* Startup the kernel thread for this host adapter
*/
@@ -1917,8 +2012,9 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
return 0;
probe_init_failed:
- qla2x00_free_que(ha, req, rsp);
- ha->max_queues = 0;
+ qla2x00_free_req_que(ha, req);
+ qla2x00_free_rsp_que(ha, rsp);
+ ha->max_req_queues = ha->max_rsp_queues = 0;
probe_failed:
if (base_vha->timer_active)
@@ -1976,6 +2072,13 @@ qla2x00_remove_one(struct pci_dev *pdev)
base_vha->flags.online = 0;
+ /* Flush the work queue and remove it */
+ if (ha->wq) {
+ flush_workqueue(ha->wq);
+ destroy_workqueue(ha->wq);
+ ha->wq = NULL;
+ }
+
/* Kill the kernel thread for this host */
if (ha->dpc_thread) {
struct task_struct *t = ha->dpc_thread;
@@ -2017,6 +2120,8 @@ qla2x00_free_device(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
+ qla25xx_delete_queues(vha);
+
if (ha->flags.fce_enabled)
qla2x00_disable_fce_trace(vha, NULL, NULL);
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 152ecfc26cd2..22f97eb50cf9 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -219,8 +219,8 @@ qla2x00_write_nvram_word(struct qla_hw_data *ha, uint32_t addr, uint16_t data)
wait_cnt = NVR_WAIT_CNT;
do {
if (!--wait_cnt) {
- DEBUG9_10(printk("%s(%ld): NVRAM didn't go ready...\n",
- __func__, vha->host_no));
+ DEBUG9_10(qla_printk(KERN_WARNING, ha,
+ "NVRAM didn't go ready...\n"));
break;
}
NVRAM_DELAY();
@@ -349,7 +349,7 @@ qla2x00_clear_nvram_protection(struct qla_hw_data *ha)
wait_cnt = NVR_WAIT_CNT;
do {
if (!--wait_cnt) {
- DEBUG9_10(qla_printk(
+ DEBUG9_10(qla_printk(KERN_WARNING, ha,
"NVRAM didn't go ready...\n"));
break;
}
@@ -408,7 +408,8 @@ qla2x00_set_nvram_protection(struct qla_hw_data *ha, int stat)
wait_cnt = NVR_WAIT_CNT;
do {
if (!--wait_cnt) {
- DEBUG9_10(qla_printk("NVRAM didn't go ready...\n"));
+ DEBUG9_10(qla_printk(KERN_WARNING, ha,
+ "NVRAM didn't go ready...\n"));
break;
}
NVRAM_DELAY();
@@ -701,30 +702,30 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
break;
case FLT_REG_VPD_0:
ha->flt_region_vpd_nvram = start;
- if (!(PCI_FUNC(ha->pdev->devfn) & 1))
+ if (ha->flags.port0)
ha->flt_region_vpd = start;
break;
case FLT_REG_VPD_1:
- if (PCI_FUNC(ha->pdev->devfn) & 1)
+ if (!ha->flags.port0)
ha->flt_region_vpd = start;
break;
case FLT_REG_NVRAM_0:
- if (!(PCI_FUNC(ha->pdev->devfn) & 1))
+ if (ha->flags.port0)
ha->flt_region_nvram = start;
break;
case FLT_REG_NVRAM_1:
- if (PCI_FUNC(ha->pdev->devfn) & 1)
+ if (!ha->flags.port0)
ha->flt_region_nvram = start;
break;
case FLT_REG_FDT:
ha->flt_region_fdt = start;
break;
case FLT_REG_NPIV_CONF_0:
- if (!(PCI_FUNC(ha->pdev->devfn) & 1))
+ if (ha->flags.port0)
ha->flt_region_npiv_conf = start;
break;
case FLT_REG_NPIV_CONF_1:
- if (PCI_FUNC(ha->pdev->devfn) & 1)
+ if (!ha->flags.port0)
ha->flt_region_npiv_conf = start;
break;
}
@@ -744,12 +745,12 @@ no_flash_data:
ha->flt_region_fw = def_fw[def];
ha->flt_region_boot = def_boot[def];
ha->flt_region_vpd_nvram = def_vpd_nvram[def];
- ha->flt_region_vpd = !(PCI_FUNC(ha->pdev->devfn) & 1) ?
+ ha->flt_region_vpd = ha->flags.port0 ?
def_vpd0[def]: def_vpd1[def];
- ha->flt_region_nvram = !(PCI_FUNC(ha->pdev->devfn) & 1) ?
+ ha->flt_region_nvram = ha->flags.port0 ?
def_nvram0[def]: def_nvram1[def];
ha->flt_region_fdt = def_fdt[def];
- ha->flt_region_npiv_conf = !(PCI_FUNC(ha->pdev->devfn) & 1) ?
+ ha->flt_region_npiv_conf = ha->flags.port0 ?
def_npiv_conf0[def]: def_npiv_conf1[def];
done:
DEBUG2(qla_printk(KERN_DEBUG, ha, "FLT[%s]: boot=0x%x fw=0x%x "
@@ -919,6 +920,7 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha)
entry = data + sizeof(struct qla_npiv_header);
cnt = le16_to_cpu(hdr.entries);
+ ha->flex_port_count = cnt;
for (i = 0; cnt; cnt--, entry++, i++) {
uint16_t flags;
struct fc_vport_identifiers vid;
@@ -1079,8 +1081,9 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
0xff0000) | ((fdata >> 16) & 0xff));
ret = qla24xx_erase_sector(vha, fdata);
if (ret != QLA_SUCCESS) {
- DEBUG9(qla_printk("Unable to erase sector: "
- "address=%x.\n", faddr));
+ DEBUG9(qla_printk(KERN_WARNING, ha,
+ "Unable to erase sector: address=%x.\n",
+ faddr));
break;
}
}
@@ -1240,8 +1243,9 @@ qla24xx_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr,
ret = qla24xx_write_flash_dword(ha,
nvram_data_addr(ha, naddr), cpu_to_le32(*dwptr));
if (ret != QLA_SUCCESS) {
- DEBUG9(qla_printk("Unable to program nvram address=%x "
- "data=%x.\n", naddr, *dwptr));
+ DEBUG9(qla_printk(KERN_WARNING, ha,
+ "Unable to program nvram address=%x data=%x.\n",
+ naddr, *dwptr));
break;
}
}
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 19d1afc3a343..a1094e7d2b44 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,7 +7,7 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "8.03.01-k1"
+#define QLA2XXX_VERSION "8.03.01-k2"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 3
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index d1cb64ad1a3f..fcb374eb0dbc 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -922,7 +922,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
if (driver_byte(result) & DRIVER_SENSE)
scsi_print_sense("", cmd);
}
- blk_end_request(req, -EIO, blk_rq_bytes(req));
+ blk_end_request_all(req, -EIO);
scsi_next_command(cmd);
break;
case ACTION_REPREP:
@@ -1088,7 +1088,6 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
return ret;
} else {
BUG_ON(req->data_len);
- BUG_ON(req->data);
memset(&cmd->sdb, 0, sizeof(cmd->sdb));
req->buffer = NULL;
@@ -1291,10 +1290,8 @@ static inline int scsi_target_queue_ready(struct Scsi_Host *shost,
if (--starget->target_blocked == 0) {
SCSI_LOG_MLQUEUE(3, starget_printk(KERN_INFO, starget,
"unblocking target at zero depth\n"));
- } else {
- blk_plug_device(sdev->request_queue);
+ } else
return 0;
- }
}
if (scsi_target_is_busy(starget)) {
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index a14d245a66b8..6f51ca485f35 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -180,8 +180,6 @@ int scsi_complete_async_scans(void)
spin_unlock(&async_scan_lock);
kfree(data);
- /* Synchronize async operations globally */
- async_synchronize_full();
return 0;
}
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index a152f89ae51c..4df8c3c806f6 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -35,6 +35,7 @@
#include <linux/netlink.h>
#include <net/netlink.h>
#include <scsi/scsi_netlink_fc.h>
+#include <scsi/scsi_bsg_fc.h>
#include "scsi_priv.h"
#include "scsi_transport_fc_internal.h"
@@ -43,6 +44,10 @@ static void fc_vport_sched_delete(struct work_struct *work);
static int fc_vport_setup(struct Scsi_Host *shost, int channel,
struct device *pdev, struct fc_vport_identifiers *ids,
struct fc_vport **vport);
+static int fc_bsg_hostadd(struct Scsi_Host *, struct fc_host_attrs *);
+static int fc_bsg_rportadd(struct Scsi_Host *, struct fc_rport *);
+static void fc_bsg_remove(struct request_queue *);
+static void fc_bsg_goose_queue(struct fc_rport *);
/*
* Redefine so that we can have same named attributes in the
@@ -411,13 +416,26 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
return -ENOMEM;
}
+ fc_bsg_hostadd(shost, fc_host);
+ /* ignore any bsg add error - we just can't do sgio */
+
+ return 0;
+}
+
+static int fc_host_remove(struct transport_container *tc, struct device *dev,
+ struct device *cdev)
+{
+ struct Scsi_Host *shost = dev_to_shost(dev);
+ struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+
+ fc_bsg_remove(fc_host->rqst_q);
return 0;
}
static DECLARE_TRANSPORT_CLASS(fc_host_class,
"fc_host",
fc_host_setup,
- NULL,
+ fc_host_remove,
NULL);
/*
@@ -2375,6 +2393,7 @@ fc_rport_final_delete(struct work_struct *work)
scsi_flush_work(shost);
fc_terminate_rport_io(rport);
+
/*
* Cancel any outstanding timers. These should really exist
* only when rmmod'ing the LLDD and we're asking for
@@ -2407,6 +2426,8 @@ fc_rport_final_delete(struct work_struct *work)
(i->f->dev_loss_tmo_callbk))
i->f->dev_loss_tmo_callbk(rport);
+ fc_bsg_remove(rport->rqst_q);
+
transport_remove_device(dev);
device_del(dev);
transport_destroy_device(dev);
@@ -2494,6 +2515,9 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
transport_add_device(dev);
transport_configure_device(dev);
+ fc_bsg_rportadd(shost, rport);
+ /* ignore any bsg add error - we just can't do sgio */
+
if (rport->roles & FC_PORT_ROLE_FCP_TARGET) {
/* initiate a scan of the target */
rport->flags |= FC_RPORT_SCAN_PENDING;
@@ -2658,6 +2682,8 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
spin_unlock_irqrestore(shost->host_lock,
flags);
+ fc_bsg_goose_queue(rport);
+
return rport;
}
}
@@ -3343,6 +3369,594 @@ fc_vport_sched_delete(struct work_struct *work)
}
+/*
+ * BSG support
+ */
+
+
+/**
+ * fc_destroy_bsgjob - routine to teardown/delete a fc bsg job
+ * @job: fc_bsg_job that is to be torn down
+ */
+static void
+fc_destroy_bsgjob(struct fc_bsg_job *job)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&job->job_lock, flags);
+ if (job->ref_cnt) {
+ spin_unlock_irqrestore(&job->job_lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&job->job_lock, flags);
+
+ put_device(job->dev); /* release reference for the request */
+
+ kfree(job->request_payload.sg_list);
+ kfree(job->reply_payload.sg_list);
+ kfree(job);
+}
+
+
+/**
+ * fc_bsg_jobdone - completion routine for bsg requests that the LLD has
+ * completed
+ * @job: fc_bsg_job that is complete
+ */
+static void
+fc_bsg_jobdone(struct fc_bsg_job *job)
+{
+ struct request *req = job->req;
+ struct request *rsp = req->next_rq;
+ unsigned long flags;
+ unsigned rsp_len = 0, req_len = blk_rq_bytes(req);
+ int err;
+
+ spin_lock_irqsave(&job->job_lock, flags);
+ job->state_flags |= FC_RQST_STATE_DONE;
+ job->ref_cnt--;
+ spin_unlock_irqrestore(&job->job_lock, flags);
+
+ err = job->req->errors = job->reply->result;
+ if (err < 0)
+ /* we're only returning the result field in the reply */
+ job->req->sense_len = sizeof(uint32_t);
+ else
+ job->req->sense_len = job->reply_len;
+
+ /* we assume all request payload was transferred, residual == 0 */
+ req->data_len = 0;
+
+ if (rsp) {
+ rsp_len = blk_rq_bytes(rsp);
+ BUG_ON(job->reply->reply_payload_rcv_len > rsp_len);
+ /* set reply (bidi) residual */
+ rsp->data_len = (rsp_len - job->reply->reply_payload_rcv_len);
+ }
+
+ blk_end_bidi_request(req, err, req_len, rsp_len);
+
+ fc_destroy_bsgjob(job);
+}
+
+
+/**
+ * fc_bsg_job_timeout - handler for when a bsg request timesout
+ * @req: request that timed out
+ */
+static enum blk_eh_timer_return
+fc_bsg_job_timeout(struct request *req)
+{
+ struct fc_bsg_job *job = (void *) req->special;
+ struct Scsi_Host *shost = job->shost;
+ struct fc_internal *i = to_fc_internal(shost->transportt);
+ unsigned long flags;
+ int err = 0, done = 0;
+
+ if (job->rport && job->rport->port_state == FC_PORTSTATE_BLOCKED)
+ return BLK_EH_RESET_TIMER;
+
+ spin_lock_irqsave(&job->job_lock, flags);
+ if (job->state_flags & FC_RQST_STATE_DONE)
+ done = 1;
+ else
+ job->ref_cnt++;
+ spin_unlock_irqrestore(&job->job_lock, flags);
+
+ if (!done && i->f->bsg_timeout) {
+ /* call LLDD to abort the i/o as it has timed out */
+ err = i->f->bsg_timeout(job);
+ if (err)
+ printk(KERN_ERR "ERROR: FC BSG request timeout - LLD "
+ "abort failed with status %d\n", err);
+ }
+
+ if (!done) {
+ spin_lock_irqsave(&job->job_lock, flags);
+ job->ref_cnt--;
+ spin_unlock_irqrestore(&job->job_lock, flags);
+ fc_destroy_bsgjob(job);
+ }
+
+ /* the blk_end_sync_io() doesn't check the error */
+ return BLK_EH_HANDLED;
+}
+
+
+
+static int
+fc_bsg_map_buffer(struct fc_bsg_buffer *buf, struct request *req)
+{
+ size_t sz = (sizeof(struct scatterlist) * req->nr_phys_segments);
+
+ BUG_ON(!req->nr_phys_segments);
+
+ buf->sg_list = kzalloc(sz, GFP_KERNEL);
+ if (!buf->sg_list)
+ return -ENOMEM;
+ sg_init_table(buf->sg_list, req->nr_phys_segments);
+ buf->sg_cnt = blk_rq_map_sg(req->q, req, buf->sg_list);
+ buf->payload_len = req->data_len;
+ return 0;
+}
+
+
+/**
+ * fc_req_to_bsgjob - Allocate/create the fc_bsg_job structure for the
+ * bsg request
+ * @shost: SCSI Host corresponding to the bsg object
+ * @rport: (optional) FC Remote Port corresponding to the bsg object
+ * @req: BSG request that needs a job structure
+ */
+static int
+fc_req_to_bsgjob(struct Scsi_Host *shost, struct fc_rport *rport,
+ struct request *req)
+{
+ struct fc_internal *i = to_fc_internal(shost->transportt);
+ struct request *rsp = req->next_rq;
+ struct fc_bsg_job *job;
+ int ret;
+
+ BUG_ON(req->special);
+
+ job = kzalloc(sizeof(struct fc_bsg_job) + i->f->dd_bsg_size,
+ GFP_KERNEL);
+ if (!job)
+ return -ENOMEM;
+
+ /*
+ * Note: this is a bit silly.
+ * The request gets formatted as a SGIO v4 ioctl request, which
+ * then gets reformatted as a blk request, which then gets
+ * reformatted as a fc bsg request. And on completion, we have
+ * to wrap return results such that SGIO v4 thinks it was a scsi
+ * status. I hope this was all worth it.
+ */
+
+ req->special = job;
+ job->shost = shost;
+ job->rport = rport;
+ job->req = req;
+ if (i->f->dd_bsg_size)
+ job->dd_data = (void *)&job[1];
+ spin_lock_init(&job->job_lock);
+ job->request = (struct fc_bsg_request *)req->cmd;
+ job->request_len = req->cmd_len;
+ job->reply = req->sense;
+ job->reply_len = SCSI_SENSE_BUFFERSIZE; /* Size of sense buffer
+ * allocated */
+ if (req->bio) {
+ ret = fc_bsg_map_buffer(&job->request_payload, req);
+ if (ret)
+ goto failjob_rls_job;
+ }
+ if (rsp && rsp->bio) {
+ ret = fc_bsg_map_buffer(&job->reply_payload, rsp);
+ if (ret)
+ goto failjob_rls_rqst_payload;
+ }
+ job->job_done = fc_bsg_jobdone;
+ if (rport)
+ job->dev = &rport->dev;
+ else
+ job->dev = &shost->shost_gendev;
+ get_device(job->dev); /* take a reference for the request */
+
+ job->ref_cnt = 1;
+
+ return 0;
+
+
+failjob_rls_rqst_payload:
+ kfree(job->request_payload.sg_list);
+failjob_rls_job:
+ kfree(job);
+ return -ENOMEM;
+}
+
+
+enum fc_dispatch_result {
+ FC_DISPATCH_BREAK, /* on return, q is locked, break from q loop */
+ FC_DISPATCH_LOCKED, /* on return, q is locked, continue on */
+ FC_DISPATCH_UNLOCKED, /* on return, q is unlocked, continue on */
+};
+
+
+/**
+ * fc_bsg_host_dispatch - process fc host bsg requests and dispatch to LLDD
+ * @shost: scsi host rport attached to
+ * @job: bsg job to be processed
+ */
+static enum fc_dispatch_result
+fc_bsg_host_dispatch(struct request_queue *q, struct Scsi_Host *shost,
+ struct fc_bsg_job *job)
+{
+ struct fc_internal *i = to_fc_internal(shost->transportt);
+ int cmdlen = sizeof(uint32_t); /* start with length of msgcode */
+ int ret;
+
+ /* Validate the host command */
+ switch (job->request->msgcode) {
+ case FC_BSG_HST_ADD_RPORT:
+ cmdlen += sizeof(struct fc_bsg_host_add_rport);
+ break;
+
+ case FC_BSG_HST_DEL_RPORT:
+ cmdlen += sizeof(struct fc_bsg_host_del_rport);
+ break;
+
+ case FC_BSG_HST_ELS_NOLOGIN:
+ cmdlen += sizeof(struct fc_bsg_host_els);
+ /* there better be a xmt and rcv payloads */
+ if ((!job->request_payload.payload_len) ||
+ (!job->reply_payload.payload_len)) {
+ ret = -EINVAL;
+ goto fail_host_msg;
+ }
+ break;
+
+ case FC_BSG_HST_CT:
+ cmdlen += sizeof(struct fc_bsg_host_ct);
+ /* there better be xmt and rcv payloads */
+ if ((!job->request_payload.payload_len) ||
+ (!job->reply_payload.payload_len)) {
+ ret = -EINVAL;
+ goto fail_host_msg;
+ }
+ break;
+
+ case FC_BSG_HST_VENDOR:
+ cmdlen += sizeof(struct fc_bsg_host_vendor);
+ if ((shost->hostt->vendor_id == 0L) ||
+ (job->request->rqst_data.h_vendor.vendor_id !=
+ shost->hostt->vendor_id)) {
+ ret = -ESRCH;
+ goto fail_host_msg;
+ }
+ break;
+
+ default:
+ ret = -EBADR;
+ goto fail_host_msg;
+ }
+
+ /* check if we really have all the request data needed */
+ if (job->request_len < cmdlen) {
+ ret = -ENOMSG;
+ goto fail_host_msg;
+ }
+
+ ret = i->f->bsg_request(job);
+ if (!ret)
+ return FC_DISPATCH_UNLOCKED;
+
+fail_host_msg:
+ /* return the errno failure code as the only status */
+ BUG_ON(job->reply_len < sizeof(uint32_t));
+ job->reply->result = ret;
+ job->reply_len = sizeof(uint32_t);
+ fc_bsg_jobdone(job);
+ return FC_DISPATCH_UNLOCKED;
+}
+
+
+/*
+ * fc_bsg_goose_queue - restart rport queue in case it was stopped
+ * @rport: rport to be restarted
+ */
+static void
+fc_bsg_goose_queue(struct fc_rport *rport)
+{
+ int flagset;
+
+ if (!rport->rqst_q)
+ return;
+
+ get_device(&rport->dev);
+
+ spin_lock(rport->rqst_q->queue_lock);
+ flagset = test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags) &&
+ !test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags);
+ if (flagset)
+ queue_flag_set(QUEUE_FLAG_REENTER, rport->rqst_q);
+ __blk_run_queue(rport->rqst_q);
+ if (flagset)
+ queue_flag_clear(QUEUE_FLAG_REENTER, rport->rqst_q);
+ spin_unlock(rport->rqst_q->queue_lock);
+
+ put_device(&rport->dev);
+}
+
+
+/**
+ * fc_bsg_rport_dispatch - process rport bsg requests and dispatch to LLDD
+ * @shost: scsi host rport attached to
+ * @rport: rport request destined to
+ * @job: bsg job to be processed
+ */
+static enum fc_dispatch_result
+fc_bsg_rport_dispatch(struct request_queue *q, struct Scsi_Host *shost,
+ struct fc_rport *rport, struct fc_bsg_job *job)
+{
+ struct fc_internal *i = to_fc_internal(shost->transportt);
+ int cmdlen = sizeof(uint32_t); /* start with length of msgcode */
+ int ret;
+
+ /* Validate the rport command */
+ switch (job->request->msgcode) {
+ case FC_BSG_RPT_ELS:
+ cmdlen += sizeof(struct fc_bsg_rport_els);
+ goto check_bidi;
+
+ case FC_BSG_RPT_CT:
+ cmdlen += sizeof(struct fc_bsg_rport_ct);
+check_bidi:
+ /* there better be xmt and rcv payloads */
+ if ((!job->request_payload.payload_len) ||
+ (!job->reply_payload.payload_len)) {
+ ret = -EINVAL;
+ goto fail_rport_msg;
+ }
+ break;
+ default:
+ ret = -EBADR;
+ goto fail_rport_msg;
+ }
+
+ /* check if we really have all the request data needed */
+ if (job->request_len < cmdlen) {
+ ret = -ENOMSG;
+ goto fail_rport_msg;
+ }
+
+ ret = i->f->bsg_request(job);
+ if (!ret)
+ return FC_DISPATCH_UNLOCKED;
+
+fail_rport_msg:
+ /* return the errno failure code as the only status */
+ BUG_ON(job->reply_len < sizeof(uint32_t));
+ job->reply->result = ret;
+ job->reply_len = sizeof(uint32_t);
+ fc_bsg_jobdone(job);
+ return FC_DISPATCH_UNLOCKED;
+}
+
+
+/**
+ * fc_bsg_request_handler - generic handler for bsg requests
+ * @q: request queue to manage
+ * @shost: Scsi_Host related to the bsg object
+ * @rport: FC remote port related to the bsg object (optional)
+ * @dev: device structure for bsg object
+ */
+static void
+fc_bsg_request_handler(struct request_queue *q, struct Scsi_Host *shost,
+ struct fc_rport *rport, struct device *dev)
+{
+ struct request *req;
+ struct fc_bsg_job *job;
+ enum fc_dispatch_result ret;
+
+ if (!get_device(dev))
+ return;
+
+ while (!blk_queue_plugged(q)) {
+ req = elv_next_request(q);
+ if (!req)
+ break;
+
+ if (rport && (rport->port_state == FC_PORTSTATE_BLOCKED))
+ break;
+
+ blkdev_dequeue_request(req);
+
+ if (rport && (rport->port_state != FC_PORTSTATE_ONLINE)) {
+ req->errors = -ENXIO;
+ spin_unlock_irq(q->queue_lock);
+ blk_end_request(req, -ENXIO, blk_rq_bytes(req));
+ spin_lock_irq(q->queue_lock);
+ continue;
+ }
+
+ spin_unlock_irq(q->queue_lock);
+
+ ret = fc_req_to_bsgjob(shost, rport, req);
+ if (ret) {
+ req->errors = ret;
+ blk_end_request(req, ret, blk_rq_bytes(req));
+ spin_lock_irq(q->queue_lock);
+ continue;
+ }
+
+ job = req->special;
+
+ /* check if we have the msgcode value at least */
+ if (job->request_len < sizeof(uint32_t)) {
+ BUG_ON(job->reply_len < sizeof(uint32_t));
+ job->reply->result = -ENOMSG;
+ job->reply_len = sizeof(uint32_t);
+ fc_bsg_jobdone(job);
+ spin_lock_irq(q->queue_lock);
+ continue;
+ }
+
+ /* the dispatch routines will unlock the queue_lock */
+ if (rport)
+ ret = fc_bsg_rport_dispatch(q, shost, rport, job);
+ else
+ ret = fc_bsg_host_dispatch(q, shost, job);
+
+ /* did dispatcher hit state that can't process any more */
+ if (ret == FC_DISPATCH_BREAK)
+ break;
+
+ /* did dispatcher had released the lock */
+ if (ret == FC_DISPATCH_UNLOCKED)
+ spin_lock_irq(q->queue_lock);
+ }
+
+ spin_unlock_irq(q->queue_lock);
+ put_device(dev);
+ spin_lock_irq(q->queue_lock);
+}
+
+
+/**
+ * fc_bsg_host_handler - handler for bsg requests for a fc host
+ * @q: fc host request queue
+ */
+static void
+fc_bsg_host_handler(struct request_queue *q)
+{
+ struct Scsi_Host *shost = q->queuedata;
+
+ fc_bsg_request_handler(q, shost, NULL, &shost->shost_gendev);
+}
+
+
+/**
+ * fc_bsg_rport_handler - handler for bsg requests for a fc rport
+ * @q: rport request queue
+ */
+static void
+fc_bsg_rport_handler(struct request_queue *q)
+{
+ struct fc_rport *rport = q->queuedata;
+ struct Scsi_Host *shost = rport_to_shost(rport);
+
+ fc_bsg_request_handler(q, shost, rport, &rport->dev);
+}
+
+
+/**
+ * fc_bsg_hostadd - Create and add the bsg hooks so we can receive requests
+ * @shost: shost for fc_host
+ * @fc_host: fc_host adding the structures to
+ */
+static int
+fc_bsg_hostadd(struct Scsi_Host *shost, struct fc_host_attrs *fc_host)
+{
+ struct device *dev = &shost->shost_gendev;
+ struct fc_internal *i = to_fc_internal(shost->transportt);
+ struct request_queue *q;
+ int err;
+ char bsg_name[BUS_ID_SIZE]; /*20*/
+
+ fc_host->rqst_q = NULL;
+
+ if (!i->f->bsg_request)
+ return -ENOTSUPP;
+
+ snprintf(bsg_name, sizeof(bsg_name),
+ "fc_host%d", shost->host_no);
+
+ q = __scsi_alloc_queue(shost, fc_bsg_host_handler);
+ if (!q) {
+ printk(KERN_ERR "fc_host%d: bsg interface failed to "
+ "initialize - no request queue\n",
+ shost->host_no);
+ return -ENOMEM;
+ }
+
+ q->queuedata = shost;
+ queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q);
+ blk_queue_rq_timed_out(q, fc_bsg_job_timeout);
+ blk_queue_rq_timeout(q, FC_DEFAULT_BSG_TIMEOUT);
+
+ err = bsg_register_queue(q, dev, bsg_name, NULL);
+ if (err) {
+ printk(KERN_ERR "fc_host%d: bsg interface failed to "
+ "initialize - register queue\n",
+ shost->host_no);
+ blk_cleanup_queue(q);
+ return err;
+ }
+
+ fc_host->rqst_q = q;
+ return 0;
+}
+
+
+/**
+ * fc_bsg_rportadd - Create and add the bsg hooks so we can receive requests
+ * @shost: shost that rport is attached to
+ * @rport: rport that the bsg hooks are being attached to
+ */
+static int
+fc_bsg_rportadd(struct Scsi_Host *shost, struct fc_rport *rport)
+{
+ struct device *dev = &rport->dev;
+ struct fc_internal *i = to_fc_internal(shost->transportt);
+ struct request_queue *q;
+ int err;
+
+ rport->rqst_q = NULL;
+
+ if (!i->f->bsg_request)
+ return -ENOTSUPP;
+
+ q = __scsi_alloc_queue(shost, fc_bsg_rport_handler);
+ if (!q) {
+ printk(KERN_ERR "%s: bsg interface failed to "
+ "initialize - no request queue\n",
+ dev->kobj.name);
+ return -ENOMEM;
+ }
+
+ q->queuedata = rport;
+ queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q);
+ blk_queue_rq_timed_out(q, fc_bsg_job_timeout);
+ blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT);
+
+ err = bsg_register_queue(q, dev, NULL, NULL);
+ if (err) {
+ printk(KERN_ERR "%s: bsg interface failed to "
+ "initialize - register queue\n",
+ dev->kobj.name);
+ blk_cleanup_queue(q);
+ return err;
+ }
+
+ rport->rqst_q = q;
+ return 0;
+}
+
+
+/**
+ * fc_bsg_remove - Deletes the bsg hooks on fchosts/rports
+ * @q: the request_queue that is to be torn down.
+ */
+static void
+fc_bsg_remove(struct request_queue *q)
+{
+ if (q) {
+ bsg_unregister_queue(q);
+ blk_cleanup_queue(q);
+ }
+}
+
+
/* Original Author: Martin Hicks */
MODULE_AUTHOR("James Smart");
MODULE_DESCRIPTION("FC Transport Attributes");
diff --git a/drivers/scsi/scsi_wait_scan.c b/drivers/scsi/scsi_wait_scan.c
index 2f21af21269a..74708fcaf82f 100644
--- a/drivers/scsi/scsi_wait_scan.c
+++ b/drivers/scsi/scsi_wait_scan.c
@@ -11,10 +11,21 @@
*/
#include <linux/module.h>
+#include <linux/device.h>
#include <scsi/scsi_scan.h>
static int __init wait_scan_init(void)
{
+ /*
+ * First we need to wait for device probing to finish;
+ * the drivers we just loaded might just still be probing
+ * and might not yet have reached the scsi async scanning
+ */
+ wait_for_device_probe();
+ /*
+ * and then we wait for the actual asynchronous scsi scan
+ * to finish.
+ */
scsi_complete_async_scans();
return 0;
}
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 3fcb64b91c43..84044233b637 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -50,6 +50,7 @@
#include <linux/string_helpers.h>
#include <linux/async.h>
#include <asm/uaccess.h>
+#include <asm/unaligned.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -1344,12 +1345,8 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
return -EINVAL;
}
- sector_size = (buffer[8] << 24) | (buffer[9] << 16) |
- (buffer[10] << 8) | buffer[11];
- lba = (((u64)buffer[0] << 56) | ((u64)buffer[1] << 48) |
- ((u64)buffer[2] << 40) | ((u64)buffer[3] << 32) |
- ((u64)buffer[4] << 24) | ((u64)buffer[5] << 16) |
- ((u64)buffer[6] << 8) | (u64)buffer[7]);
+ sector_size = get_unaligned_be32(&buffer[8]);
+ lba = get_unaligned_be64(&buffer[0]);
sd_read_protection_type(sdkp, buffer);
@@ -1400,10 +1397,8 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp,
return -EINVAL;
}
- sector_size = (buffer[4] << 24) | (buffer[5] << 16) |
- (buffer[6] << 8) | buffer[7];
- lba = (buffer[0] << 24) | (buffer[1] << 16) |
- (buffer[2] << 8) | buffer[3];
+ sector_size = get_unaligned_be32(&buffer[4]);
+ lba = get_unaligned_be32(&buffer[0]);
if ((sizeof(sdkp->capacity) == 4) && (lba == 0xffffffff)) {
sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a "
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 82312df9b0bf..91e316fe6522 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -179,7 +179,7 @@ typedef struct sg_device { /* holds the state of each scsi generic device */
/* tasklet or soft irq callback */
static void sg_rq_end_io(struct request *rq, int uptodate);
static int sg_start_req(Sg_request *srp, unsigned char *cmd);
-static void sg_finish_rem_req(Sg_request * srp);
+static int sg_finish_rem_req(Sg_request * srp);
static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size);
static ssize_t sg_new_read(Sg_fd * sfp, char __user *buf, size_t count,
Sg_request * srp);
@@ -518,7 +518,7 @@ sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp)
goto err_out;
}
err_out:
- sg_finish_rem_req(srp);
+ err = sg_finish_rem_req(srp);
return (0 == err) ? count : err;
}
@@ -1065,6 +1065,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
return blk_trace_setup(sdp->device->request_queue,
sdp->disk->disk_name,
MKDEV(SCSI_GENERIC_MAJOR, sdp->index),
+ NULL,
(char *)arg);
case BLKTRACESTART:
return blk_trace_startstop(sdp->device->request_queue, 1);
@@ -1696,9 +1697,10 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd)
return res;
}
-static void
-sg_finish_rem_req(Sg_request * srp)
+static int sg_finish_rem_req(Sg_request * srp)
{
+ int ret = 0;
+
Sg_fd *sfp = srp->parentfp;
Sg_scatter_hold *req_schp = &srp->data;
@@ -1710,12 +1712,14 @@ sg_finish_rem_req(Sg_request * srp)
if (srp->rq) {
if (srp->bio)
- blk_rq_unmap_user(srp->bio);
+ ret = blk_rq_unmap_user(srp->bio);
blk_put_request(srp->rq);
}
sg_remove_request(sfp, srp);
+
+ return ret;
}
static int
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
index d92ff512d213..291236e6e435 100644
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -309,6 +309,11 @@ int sr_drive_status(struct cdrom_device_info *cdi, int slot)
if (0 == sr_test_unit_ready(cd->device, &sshdr))
return CDS_DISC_OK;
+ /* SK/ASC/ASCQ of 2/4/1 means "unit is becoming ready" */
+ if (scsi_sense_valid(&sshdr) && sshdr.sense_key == NOT_READY
+ && sshdr.asc == 0x04 && sshdr.ascq == 0x01)
+ return CDS_DRIVE_NOT_READY;
+
if (!cdrom_get_media_event(cdi, &med)) {
if (med.media_present)
return CDS_DISC_OK;
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 7ddff3f55087..938bc1b6c3fa 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -771,8 +771,6 @@ static int pci_netmos_init(struct pci_dev *dev)
}
/*
- * ITE support by Niels de Vos <niels.devos@wincor-nixdorf.com>
- *
* These chips are available with optionally one parallel port and up to
* two serial ports. Unfortunately they all have the same product id.
*
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index 18ba812a4f84..d86123e03391 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -166,7 +166,7 @@ static void bfin_serial_start_tx(struct uart_port *port)
struct tty_struct *tty = uart->port.info->port.tty;
#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
- if (uart->scts && (!bfin_serial_get_mctrl(&uart->port)&TIOCM_CTS)) {
+ if (uart->scts && !(bfin_serial_get_mctrl(&uart->port) & TIOCM_CTS)) {
uart->scts = 0;
uart_handle_cts_change(&uart->port, uart->scts);
}
@@ -368,7 +368,7 @@ static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id)
struct bfin_serial_port *uart = dev_id;
#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
- if (uart->scts && (!bfin_serial_get_mctrl(&uart->port)&TIOCM_CTS)) {
+ if (uart->scts && !(bfin_serial_get_mctrl(&uart->port) & TIOCM_CTS)) {
uart->scts = 0;
uart_handle_cts_change(&uart->port, uart->scts);
}
@@ -504,7 +504,7 @@ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)
struct circ_buf *xmit = &uart->port.info->xmit;
#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
- if (uart->scts && (!bfin_serial_get_mctrl(&uart->port)&TIOCM_CTS)) {
+ if (uart->scts && !(bfin_serial_get_mctrl(&uart->port)&TIOCM_CTS)) {
uart->scts = 0;
uart_handle_cts_change(&uart->port, uart->scts);
}
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
index 7ba7d70f04d6..7be52fe288eb 100644
--- a/drivers/serial/crisv10.c
+++ b/drivers/serial/crisv10.c
@@ -23,16 +23,18 @@ static char *serial_version = "$Revision: 1.25 $";
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/init.h>
-#include <asm/uaccess.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/bitops.h>
+#include <linux/seq_file.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
-#include <asm/io.h>
#include <asm/irq.h>
#include <asm/dma.h>
#include <asm/system.h>
-#include <linux/delay.h>
#include <arch/svinto.h>
@@ -456,7 +458,6 @@ static struct e100_serial rs_table[] = {
#define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial))
-static struct ktermios *serial_termios[NR_PORTS];
#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
static struct fast_timer fast_timers[NR_PORTS];
#endif
@@ -4257,151 +4258,132 @@ rs_open(struct tty_struct *tty, struct file * filp)
return 0;
}
+#ifdef CONFIG_PROC_FS
/*
* /proc fs routines....
*/
-static int line_info(char *buf, struct e100_serial *info)
+static void seq_line_info(struct seq_file *m, struct e100_serial *info)
{
- char stat_buf[30];
- int ret;
unsigned long tmp;
- ret = sprintf(buf, "%d: uart:E100 port:%lX irq:%d",
- info->line, (unsigned long)info->ioport, info->irq);
+ seq_printf(m, "%d: uart:E100 port:%lX irq:%d",
+ info->line, (unsigned long)info->ioport, info->irq);
if (!info->ioport || (info->type == PORT_UNKNOWN)) {
- ret += sprintf(buf+ret, "\n");
- return ret;
+ seq_printf(m, "\n");
+ return;
}
- stat_buf[0] = 0;
- stat_buf[1] = 0;
- if (!E100_RTS_GET(info))
- strcat(stat_buf, "|RTS");
- if (!E100_CTS_GET(info))
- strcat(stat_buf, "|CTS");
- if (!E100_DTR_GET(info))
- strcat(stat_buf, "|DTR");
- if (!E100_DSR_GET(info))
- strcat(stat_buf, "|DSR");
- if (!E100_CD_GET(info))
- strcat(stat_buf, "|CD");
- if (!E100_RI_GET(info))
- strcat(stat_buf, "|RI");
-
- ret += sprintf(buf+ret, " baud:%d", info->baud);
-
- ret += sprintf(buf+ret, " tx:%lu rx:%lu",
+ seq_printf(m, " baud:%d", info->baud);
+ seq_printf(m, " tx:%lu rx:%lu",
(unsigned long)info->icount.tx,
(unsigned long)info->icount.rx);
tmp = CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
- if (tmp) {
- ret += sprintf(buf+ret, " tx_pend:%lu/%lu",
- (unsigned long)tmp,
- (unsigned long)SERIAL_XMIT_SIZE);
- }
+ if (tmp)
+ seq_printf(m, " tx_pend:%lu/%lu",
+ (unsigned long)tmp,
+ (unsigned long)SERIAL_XMIT_SIZE);
- ret += sprintf(buf+ret, " rx_pend:%lu/%lu",
- (unsigned long)info->recv_cnt,
- (unsigned long)info->max_recv_cnt);
+ seq_printf(m, " rx_pend:%lu/%lu",
+ (unsigned long)info->recv_cnt,
+ (unsigned long)info->max_recv_cnt);
#if 1
if (info->port.tty) {
-
if (info->port.tty->stopped)
- ret += sprintf(buf+ret, " stopped:%i",
- (int)info->port.tty->stopped);
+ seq_printf(m, " stopped:%i",
+ (int)info->port.tty->stopped);
if (info->port.tty->hw_stopped)
- ret += sprintf(buf+ret, " hw_stopped:%i",
- (int)info->port.tty->hw_stopped);
+ seq_printf(m, " hw_stopped:%i",
+ (int)info->port.tty->hw_stopped);
}
{
unsigned char rstat = info->ioport[REG_STATUS];
- if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect) )
- ret += sprintf(buf+ret, " xoff_detect:1");
+ if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect))
+ seq_printf(m, " xoff_detect:1");
}
#endif
-
-
-
if (info->icount.frame)
- ret += sprintf(buf+ret, " fe:%lu",
- (unsigned long)info->icount.frame);
+ seq_printf(m, " fe:%lu", (unsigned long)info->icount.frame);
if (info->icount.parity)
- ret += sprintf(buf+ret, " pe:%lu",
- (unsigned long)info->icount.parity);
+ seq_printf(m, " pe:%lu", (unsigned long)info->icount.parity);
if (info->icount.brk)
- ret += sprintf(buf+ret, " brk:%lu",
- (unsigned long)info->icount.brk);
+ seq_printf(m, " brk:%lu", (unsigned long)info->icount.brk);
if (info->icount.overrun)
- ret += sprintf(buf+ret, " oe:%lu",
- (unsigned long)info->icount.overrun);
+ seq_printf(m, " oe:%lu", (unsigned long)info->icount.overrun);
/*
* Last thing is the RS-232 status lines
*/
- ret += sprintf(buf+ret, " %s\n", stat_buf+1);
- return ret;
+ if (!E100_RTS_GET(info))
+ seq_puts(m, "|RTS");
+ if (!E100_CTS_GET(info))
+ seq_puts(m, "|CTS");
+ if (!E100_DTR_GET(info))
+ seq_puts(m, "|DTR");
+ if (!E100_DSR_GET(info))
+ seq_puts(m, "|DSR");
+ if (!E100_CD_GET(info))
+ seq_puts(m, "|CD");
+ if (!E100_RI_GET(info))
+ seq_puts(m, "|RI");
+ seq_puts(m, "\n");
}
-int rs_read_proc(char *page, char **start, off_t off, int count,
- int *eof, void *data)
+
+static int crisv10_proc_show(struct seq_file *m, void *v)
{
- int i, len = 0, l;
- off_t begin = 0;
+ int i;
- len += sprintf(page, "serinfo:1.0 driver:%s\n",
- serial_version);
- for (i = 0; i < NR_PORTS && len < 4000; i++) {
+ seq_printf(m, "serinfo:1.0 driver:%s\n", serial_version);
+
+ for (i = 0; i < NR_PORTS; i++) {
if (!rs_table[i].enabled)
continue;
- l = line_info(page + len, &rs_table[i]);
- len += l;
- if (len+begin > off+count)
- goto done;
- if (len+begin < off) {
- begin += len;
- len = 0;
- }
+ seq_line_info(m, &rs_table[i]);
}
#ifdef DEBUG_LOG_INCLUDED
for (i = 0; i < debug_log_pos; i++) {
- len += sprintf(page + len, "%-4i %lu.%lu ", i, debug_log[i].time, timer_data_to_ns(debug_log[i].timer_data));
- len += sprintf(page + len, debug_log[i].string, debug_log[i].value);
- if (len+begin > off+count)
- goto done;
- if (len+begin < off) {
- begin += len;
- len = 0;
- }
+ seq_printf(m, "%-4i %lu.%lu ",
+ i, debug_log[i].time,
+ timer_data_to_ns(debug_log[i].timer_data));
+ seq_printf(m, debug_log[i].string, debug_log[i].value);
}
- len += sprintf(page + len, "debug_log %i/%i %li bytes\n",
- i, DEBUG_LOG_SIZE, begin+len);
+ seq_printf(m, "debug_log %i/%i\n", i, DEBUG_LOG_SIZE);
debug_log_pos = 0;
#endif
+ return 0;
+}
- *eof = 1;
-done:
- if (off >= len+begin)
- return 0;
- *start = page + (off-begin);
- return ((count < begin+len-off) ? count : begin+len-off);
+static int crisv10_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, crisv10_proc_show, NULL);
}
+static const struct file_operations crisv10_proc_fops = {
+ .owner = THIS_MODULE,
+ .open = crisv10_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+#endif
+
+
/* Finally, routines used to initialize the serial driver. */
-static void
-show_serial_version(void)
+static void show_serial_version(void)
{
printk(KERN_INFO
- "ETRAX 100LX serial-driver %s, (c) 2000-2004 Axis Communications AB\r\n",
+ "ETRAX 100LX serial-driver %s, "
+ "(c) 2000-2004 Axis Communications AB\r\n",
&serial_version[11]); /* "$Revision: x.yy" */
}
@@ -4425,13 +4407,14 @@ static const struct tty_operations rs_ops = {
.break_ctl = rs_break,
.send_xchar = rs_send_xchar,
.wait_until_sent = rs_wait_until_sent,
- .read_proc = rs_read_proc,
.tiocmget = rs_tiocmget,
- .tiocmset = rs_tiocmset
+ .tiocmset = rs_tiocmset,
+#ifdef CONFIG_PROC_FS
+ .proc_fops = &crisv10_proc_fops,
+#endif
};
-static int __init
-rs_init(void)
+static int __init rs_init(void)
{
int i;
struct e100_serial *info;
diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h
index 8871aaa3dba6..c0a3e2734e24 100644
--- a/drivers/serial/jsm/jsm.h
+++ b/drivers/serial/jsm/jsm.h
@@ -130,8 +130,6 @@ struct jsm_board
struct pci_dev *pci_dev;
u32 maxports; /* MAX ports this board can handle */
- spinlock_t bd_lock; /* Used to protect board */
-
spinlock_t bd_intr_lock; /* Used to protect the poller tasklet and
* the interrupt routine from each other.
*/
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c
index d2d32a198629..b3604aa322a4 100644
--- a/drivers/serial/jsm/jsm_driver.c
+++ b/drivers/serial/jsm/jsm_driver.c
@@ -88,7 +88,6 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device
else
brd->maxports = 2;
- spin_lock_init(&brd->bd_lock);
spin_lock_init(&brd->bd_intr_lock);
/* store which revision we have */
diff --git a/drivers/serial/s3c6400.c b/drivers/serial/s3c6400.c
index 06936d13393f..3e3785233682 100644
--- a/drivers/serial/s3c6400.c
+++ b/drivers/serial/s3c6400.c
@@ -102,6 +102,7 @@ static struct s3c24xx_uart_info s3c6400_uart_inf = {
.name = "Samsung S3C6400 UART",
.type = PORT_S3C6400,
.fifosize = 64,
+ .has_divslot = 1,
.rx_fifomask = S3C2440_UFSTAT_RXMASK,
.rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
.rx_fifofull = S3C2440_UFSTAT_RXFULL,
diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c
index 41ac94872b8d..93b5d75db126 100644
--- a/drivers/serial/samsung.c
+++ b/drivers/serial/samsung.c
@@ -127,7 +127,7 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port)
struct s3c24xx_uart_port *ourport = to_ourport(port);
if (tx_enabled(port)) {
- disable_irq(ourport->tx_irq);
+ disable_irq_nosync(ourport->tx_irq);
tx_enabled(port) = 0;
if (port->flags & UPF_CONS_FLOW)
s3c24xx_serial_rx_enable(port);
@@ -154,7 +154,7 @@ static void s3c24xx_serial_stop_rx(struct uart_port *port)
if (rx_enabled(port)) {
dbg("s3c24xx_serial_stop_rx: port=%p\n", port);
- disable_irq(ourport->rx_irq);
+ disable_irq_nosync(ourport->rx_irq);
rx_enabled(port) = 0;
}
}
@@ -508,6 +508,7 @@ s3c24xx_serial_setsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c)
struct baud_calc {
struct s3c24xx_uart_clksrc *clksrc;
unsigned int calc;
+ unsigned int divslot;
unsigned int quot;
struct clk *src;
};
@@ -517,6 +518,7 @@ static int s3c24xx_serial_calcbaud(struct baud_calc *calc,
struct s3c24xx_uart_clksrc *clksrc,
unsigned int baud)
{
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
unsigned long rate;
calc->src = clk_get(port->dev, clksrc->name);
@@ -527,8 +529,24 @@ static int s3c24xx_serial_calcbaud(struct baud_calc *calc,
rate /= clksrc->divisor;
calc->clksrc = clksrc;
- calc->quot = (rate + (8 * baud)) / (16 * baud);
- calc->calc = (rate / (calc->quot * 16));
+
+ if (ourport->info->has_divslot) {
+ unsigned long div = rate / baud;
+
+ /* The UDIVSLOT register on the newer UARTs allows us to
+ * get a divisor adjustment of 1/16th on the baud clock.
+ *
+ * We don't keep the UDIVSLOT value (the 16ths we calculated
+ * by not multiplying the baud by 16) as it is easy enough
+ * to recalculate.
+ */
+
+ calc->quot = div / 16;
+ calc->calc = rate / div;
+ } else {
+ calc->quot = (rate + (8 * baud)) / (16 * baud);
+ calc->calc = (rate / (calc->quot * 16));
+ }
calc->quot--;
return 1;
@@ -611,6 +629,30 @@ static unsigned int s3c24xx_serial_getclk(struct uart_port *port,
return best->quot;
}
+/* udivslot_table[]
+ *
+ * This table takes the fractional value of the baud divisor and gives
+ * the recommended setting for the UDIVSLOT register.
+ */
+static u16 udivslot_table[16] = {
+ [0] = 0x0000,
+ [1] = 0x0080,
+ [2] = 0x0808,
+ [3] = 0x0888,
+ [4] = 0x2222,
+ [5] = 0x4924,
+ [6] = 0x4A52,
+ [7] = 0x54AA,
+ [8] = 0x5555,
+ [9] = 0xD555,
+ [10] = 0xD5D5,
+ [11] = 0xDDD5,
+ [12] = 0xDDDD,
+ [13] = 0xDFDD,
+ [14] = 0xDFDF,
+ [15] = 0xFFDF,
+};
+
static void s3c24xx_serial_set_termios(struct uart_port *port,
struct ktermios *termios,
struct ktermios *old)
@@ -623,6 +665,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
unsigned int baud, quot;
unsigned int ulcon;
unsigned int umcon;
+ unsigned int udivslot = 0;
/*
* We don't support modem control lines.
@@ -644,6 +687,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
/* check to see if we need to change clock source */
if (ourport->clksrc != clksrc || ourport->baudclk != clk) {
+ dbg("selecting clock %p\n", clk);
s3c24xx_serial_setsource(port, clksrc);
if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
@@ -658,6 +702,13 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0;
}
+ if (ourport->info->has_divslot) {
+ unsigned int div = ourport->baudclk_rate / baud;
+
+ udivslot = udivslot_table[div & 15];
+ dbg("udivslot = %04x (div %d)\n", udivslot, div & 15);
+ }
+
switch (termios->c_cflag & CSIZE) {
case CS5:
dbg("config: 5bits/char\n");
@@ -697,12 +748,16 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
spin_lock_irqsave(&port->lock, flags);
- dbg("setting ulcon to %08x, brddiv to %d\n", ulcon, quot);
+ dbg("setting ulcon to %08x, brddiv to %d, udivslot %08x\n",
+ ulcon, quot, udivslot);
wr_regl(port, S3C2410_ULCON, ulcon);
wr_regl(port, S3C2410_UBRDIV, quot);
wr_regl(port, S3C2410_UMCON, umcon);
+ if (ourport->info->has_divslot)
+ wr_regl(port, S3C2443_DIVSLOT, udivslot);
+
dbg("uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n",
rd_regl(port, S3C2410_ULCON),
rd_regl(port, S3C2410_UCON),
diff --git a/drivers/serial/samsung.h b/drivers/serial/samsung.h
index 571d6b90d206..7afb94843a08 100644
--- a/drivers/serial/samsung.h
+++ b/drivers/serial/samsung.h
@@ -21,6 +21,10 @@ struct s3c24xx_uart_info {
unsigned long tx_fifoshift;
unsigned long tx_fifofull;
+ /* uart port features */
+
+ unsigned int has_divslot:1;
+
/* clock source control */
int (*get_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk);
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index dbf5357a77b3..4e3248d58602 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -47,12 +47,17 @@
#include <linux/clk.h>
#include <linux/ctype.h>
#include <linux/err.h>
+#include <linux/list.h>
#ifdef CONFIG_SUPERH
#include <asm/clock.h>
#include <asm/sh_bios.h>
#endif
+#ifdef CONFIG_H8300
+#include <asm/gpio.h>
+#endif
+
#include "sh-sci.h"
struct sci_port {
@@ -75,14 +80,22 @@ struct sci_port {
int break_flag;
#ifdef CONFIG_HAVE_CLK
- /* Port clock */
- struct clk *clk;
+ /* Interface clock */
+ struct clk *iclk;
+ /* Data clock */
+ struct clk *dclk;
#endif
+ struct list_head node;
};
-#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
-static struct sci_port *serial_console_port;
+struct sh_sci_priv {
+ spinlock_t lock;
+ struct list_head ports;
+
+#ifdef CONFIG_HAVE_CLK
+ struct notifier_block clk_nb;
#endif
+};
/* Function prototypes */
static void sci_stop_tx(struct uart_port *port);
@@ -159,12 +172,12 @@ static void h8300_sci_config(struct uart_port *port, unsigned int ctrl)
*mstpcrl &= ~mask;
}
-static inline void h8300_sci_enable(struct uart_port *port)
+static void h8300_sci_enable(struct uart_port *port)
{
h8300_sci_config(port, sci_enable);
}
-static inline void h8300_sci_disable(struct uart_port *port)
+static void h8300_sci_disable(struct uart_port *port)
{
h8300_sci_config(port, sci_disable);
}
@@ -611,7 +624,7 @@ static inline int sci_handle_breaks(struct uart_port *port)
int copied = 0;
unsigned short status = sci_in(port, SCxSR);
struct tty_struct *tty = port->info->port.tty;
- struct sci_port *s = &sci_ports[port->line];
+ struct sci_port *s = to_sci_port(port);
if (uart_handle_break(port))
return 0;
@@ -726,19 +739,43 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
static int sci_notifier(struct notifier_block *self,
unsigned long phase, void *p)
{
- int i;
+ struct sh_sci_priv *priv = container_of(self,
+ struct sh_sci_priv, clk_nb);
+ struct sci_port *sci_port;
+ unsigned long flags;
if ((phase == CPUFREQ_POSTCHANGE) ||
- (phase == CPUFREQ_RESUMECHANGE))
- for (i = 0; i < SCI_NPORTS; i++) {
- struct sci_port *s = &sci_ports[i];
- s->port.uartclk = clk_get_rate(s->clk);
- }
+ (phase == CPUFREQ_RESUMECHANGE)) {
+ spin_lock_irqsave(&priv->lock, flags);
+ list_for_each_entry(sci_port, &priv->ports, node)
+ sci_port->port.uartclk = clk_get_rate(sci_port->dclk);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
return NOTIFY_OK;
}
-static struct notifier_block sci_nb = { &sci_notifier, NULL, 0 };
+static void sci_clk_enable(struct uart_port *port)
+{
+ struct sci_port *sci_port = to_sci_port(port);
+
+ clk_enable(sci_port->dclk);
+ sci_port->port.uartclk = clk_get_rate(sci_port->dclk);
+
+ if (sci_port->iclk)
+ clk_enable(sci_port->iclk);
+}
+
+static void sci_clk_disable(struct uart_port *port)
+{
+ struct sci_port *sci_port = to_sci_port(port);
+
+ if (sci_port->iclk)
+ clk_disable(sci_port->iclk);
+
+ clk_disable(sci_port->dclk);
+}
#endif
static int sci_request_irq(struct sci_port *port)
@@ -865,15 +902,11 @@ static void sci_break_ctl(struct uart_port *port, int break_state)
static int sci_startup(struct uart_port *port)
{
- struct sci_port *s = &sci_ports[port->line];
+ struct sci_port *s = to_sci_port(port);
if (s->enable)
s->enable(port);
-#ifdef CONFIG_HAVE_CLK
- s->clk = clk_get(NULL, "module_clk");
-#endif
-
sci_request_irq(s);
sci_start_tx(port);
sci_start_rx(port, 1);
@@ -883,7 +916,7 @@ static int sci_startup(struct uart_port *port)
static void sci_shutdown(struct uart_port *port)
{
- struct sci_port *s = &sci_ports[port->line];
+ struct sci_port *s = to_sci_port(port);
sci_stop_rx(port);
sci_stop_tx(port);
@@ -891,11 +924,6 @@ static void sci_shutdown(struct uart_port *port)
if (s->disable)
s->disable(port);
-
-#ifdef CONFIG_HAVE_CLK
- clk_put(s->clk);
- s->clk = NULL;
-#endif
}
static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
@@ -980,25 +1008,31 @@ static int sci_request_port(struct uart_port *port)
static void sci_config_port(struct uart_port *port, int flags)
{
- struct sci_port *s = &sci_ports[port->line];
+ struct sci_port *s = to_sci_port(port);
port->type = s->type;
- if (port->flags & UPF_IOREMAP && !port->membase) {
-#if defined(CONFIG_SUPERH64)
- port->mapbase = onchip_remap(SCIF_ADDR_SH5, 1024, "SCIF");
- port->membase = (void __iomem *)port->mapbase;
-#else
+ if (port->membase)
+ return;
+
+ if (port->flags & UPF_IOREMAP) {
port->membase = ioremap_nocache(port->mapbase, 0x40);
-#endif
- dev_err(port->dev, "can't remap port#%d\n", port->line);
+ if (IS_ERR(port->membase))
+ dev_err(port->dev, "can't remap port#%d\n", port->line);
+ } else {
+ /*
+ * For the simple (and majority of) cases where we don't
+ * need to do any remapping, just cast the cookie
+ * directly.
+ */
+ port->membase = (void __iomem *)port->mapbase;
}
}
static int sci_verify_port(struct uart_port *port, struct serial_struct *ser)
{
- struct sci_port *s = &sci_ports[port->line];
+ struct sci_port *s = to_sci_port(port);
if (ser->irq != s->irqs[SCIx_TXI_IRQ] || ser->irq > nr_irqs)
return -EINVAL;
@@ -1032,63 +1066,60 @@ static struct uart_ops sci_uart_ops = {
#endif
};
-static void __init sci_init_ports(void)
+static void __devinit sci_init_single(struct platform_device *dev,
+ struct sci_port *sci_port,
+ unsigned int index,
+ struct plat_sci_port *p)
{
- static int first = 1;
- int i;
-
- if (!first)
- return;
-
- first = 0;
-
- for (i = 0; i < SCI_NPORTS; i++) {
- sci_ports[i].port.ops = &sci_uart_ops;
- sci_ports[i].port.iotype = UPIO_MEM;
- sci_ports[i].port.line = i;
- sci_ports[i].port.fifosize = 1;
+ sci_port->port.ops = &sci_uart_ops;
+ sci_port->port.iotype = UPIO_MEM;
+ sci_port->port.line = index;
+ sci_port->port.fifosize = 1;
#if defined(__H8300H__) || defined(__H8300S__)
#ifdef __H8300S__
- sci_ports[i].enable = h8300_sci_enable;
- sci_ports[i].disable = h8300_sci_disable;
+ sci_port->enable = h8300_sci_enable;
+ sci_port->disable = h8300_sci_disable;
#endif
- sci_ports[i].port.uartclk = CONFIG_CPU_CLOCK;
+ sci_port->port.uartclk = CONFIG_CPU_CLOCK;
#elif defined(CONFIG_HAVE_CLK)
- /*
- * XXX: We should use a proper SCI/SCIF clock
- */
- {
- struct clk *clk = clk_get(NULL, "module_clk");
- sci_ports[i].port.uartclk = clk_get_rate(clk);
- clk_put(clk);
- }
+ sci_port->iclk = p->clk ? clk_get(&dev->dev, p->clk) : NULL;
+ sci_port->dclk = clk_get(&dev->dev, "module_clk");
+ sci_port->enable = sci_clk_enable;
+ sci_port->disable = sci_clk_disable;
#else
#error "Need a valid uartclk"
#endif
- sci_ports[i].break_timer.data = (unsigned long)&sci_ports[i];
- sci_ports[i].break_timer.function = sci_break_timer;
-
- init_timer(&sci_ports[i].break_timer);
- }
-}
+ sci_port->break_timer.data = (unsigned long)sci_port;
+ sci_port->break_timer.function = sci_break_timer;
+ init_timer(&sci_port->break_timer);
-int __init early_sci_setup(struct uart_port *port)
-{
- if (unlikely(port->line > SCI_NPORTS))
- return -ENODEV;
+ sci_port->port.mapbase = p->mapbase;
+ sci_port->port.membase = p->membase;
- sci_init_ports();
+ sci_port->port.irq = p->irqs[SCIx_TXI_IRQ];
+ sci_port->port.flags = p->flags;
+ sci_port->port.dev = &dev->dev;
+ sci_port->type = sci_port->port.type = p->type;
- sci_ports[port->line].port.membase = port->membase;
- sci_ports[port->line].port.mapbase = port->mapbase;
- sci_ports[port->line].port.type = port->type;
+ memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs));
- return 0;
}
#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
+static struct tty_driver *serial_console_device(struct console *co, int *index)
+{
+ struct uart_driver *p = &sci_uart_driver;
+ *index = co->index;
+ return p->tty_driver;
+}
+
+static void serial_console_putchar(struct uart_port *port, int ch)
+{
+ sci_poll_put_char(port, ch);
+}
+
/*
* Print a string to the serial port trying not to disturb
* any possible real use of the port...
@@ -1096,25 +1127,27 @@ int __init early_sci_setup(struct uart_port *port)
static void serial_console_write(struct console *co, const char *s,
unsigned count)
{
- struct uart_port *port = &serial_console_port->port;
+ struct uart_port *port = co->data;
+ struct sci_port *sci_port = to_sci_port(port);
unsigned short bits;
- int i;
- for (i = 0; i < count; i++) {
- if (*s == 10)
- sci_poll_put_char(port, '\r');
+ if (sci_port->enable)
+ sci_port->enable(port);
- sci_poll_put_char(port, *s++);
- }
+ uart_console_write(port, s, count, serial_console_putchar);
/* wait until fifo is empty and last bit has been transmitted */
bits = SCxSR_TDxE(port) | SCxSR_TEND(port);
while ((sci_in(port, SCxSR) & bits) != bits)
cpu_relax();
+
+ if (sci_port->disable);
+ sci_port->disable(port);
}
static int __init serial_console_setup(struct console *co, char *options)
{
+ struct sci_port *sci_port;
struct uart_port *port;
int baud = 115200;
int bits = 8;
@@ -1130,8 +1163,9 @@ static int __init serial_console_setup(struct console *co, char *options)
if (co->index >= SCI_NPORTS)
co->index = 0;
- serial_console_port = &sci_ports[co->index];
- port = &serial_console_port->port;
+ sci_port = &sci_ports[co->index];
+ port = &sci_port->port;
+ co->data = port;
/*
* Also need to check port->type, we don't actually have any
@@ -1141,21 +1175,11 @@ static int __init serial_console_setup(struct console *co, char *options)
*/
if (!port->type)
return -ENODEV;
- if (!port->membase || !port->mapbase)
- return -ENODEV;
-
- port->type = serial_console_port->type;
-
-#ifdef CONFIG_HAVE_CLK
- if (!serial_console_port->clk)
- serial_console_port->clk = clk_get(NULL, "module_clk");
-#endif
- if (port->flags & UPF_IOREMAP)
- sci_config_port(port, 0);
+ sci_config_port(port, 0);
- if (serial_console_port->enable)
- serial_console_port->enable(port);
+ if (sci_port->enable)
+ sci_port->enable(port);
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -1166,22 +1190,21 @@ static int __init serial_console_setup(struct console *co, char *options)
if (ret == 0)
sci_stop_rx(port);
#endif
+ /* TODO: disable clock */
return ret;
}
static struct console serial_console = {
.name = "ttySC",
- .device = uart_console_device,
+ .device = serial_console_device,
.write = serial_console_write,
.setup = serial_console_setup,
.flags = CON_PRINTBUFFER,
.index = -1,
- .data = &sci_uart_driver,
};
static int __init sci_console_init(void)
{
- sci_init_ports();
register_console(&serial_console);
return 0;
}
@@ -1207,6 +1230,61 @@ static struct uart_driver sci_uart_driver = {
.cons = SCI_CONSOLE,
};
+
+static int sci_remove(struct platform_device *dev)
+{
+ struct sh_sci_priv *priv = platform_get_drvdata(dev);
+ struct sci_port *p;
+ unsigned long flags;
+
+#ifdef CONFIG_HAVE_CLK
+ cpufreq_unregister_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER);
+#endif
+
+ spin_lock_irqsave(&priv->lock, flags);
+ list_for_each_entry(p, &priv->ports, node)
+ uart_remove_one_port(&sci_uart_driver, &p->port);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ kfree(priv);
+ return 0;
+}
+
+static int __devinit sci_probe_single(struct platform_device *dev,
+ unsigned int index,
+ struct plat_sci_port *p,
+ struct sci_port *sciport)
+{
+ struct sh_sci_priv *priv = platform_get_drvdata(dev);
+ unsigned long flags;
+ int ret;
+
+ /* Sanity check */
+ if (unlikely(index >= SCI_NPORTS)) {
+ dev_notice(&dev->dev, "Attempting to register port "
+ "%d when only %d are available.\n",
+ index+1, SCI_NPORTS);
+ dev_notice(&dev->dev, "Consider bumping "
+ "CONFIG_SERIAL_SH_SCI_NR_UARTS!\n");
+ return 0;
+ }
+
+ sci_init_single(dev, sciport, index, p);
+
+ ret = uart_add_one_port(&sci_uart_driver, &sciport->port);
+ if (ret)
+ return ret;
+
+ INIT_LIST_HEAD(&sciport->node);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ list_add(&sciport->node, &priv->ports);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
/*
* Register a set of serial devices attached to a platform device. The
* list is terminated with a zero flags entry, which means we expect
@@ -1216,57 +1294,34 @@ static struct uart_driver sci_uart_driver = {
static int __devinit sci_probe(struct platform_device *dev)
{
struct plat_sci_port *p = dev->dev.platform_data;
+ struct sh_sci_priv *priv;
int i, ret = -EINVAL;
- for (i = 0; p && p->flags != 0; p++, i++) {
- struct sci_port *sciport = &sci_ports[i];
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
- /* Sanity check */
- if (unlikely(i == SCI_NPORTS)) {
- dev_notice(&dev->dev, "Attempting to register port "
- "%d when only %d are available.\n",
- i+1, SCI_NPORTS);
- dev_notice(&dev->dev, "Consider bumping "
- "CONFIG_SERIAL_SH_SCI_NR_UARTS!\n");
- break;
- }
+ INIT_LIST_HEAD(&priv->ports);
+ spin_lock_init(&priv->lock);
+ platform_set_drvdata(dev, priv);
- sciport->port.mapbase = p->mapbase;
+#ifdef CONFIG_HAVE_CLK
+ priv->clk_nb.notifier_call = sci_notifier;
+ cpufreq_register_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER);
+#endif
- if (p->mapbase && !p->membase) {
- if (p->flags & UPF_IOREMAP) {
- p->membase = ioremap_nocache(p->mapbase, 0x40);
- if (IS_ERR(p->membase)) {
- ret = PTR_ERR(p->membase);
- goto err_unreg;
- }
- } else {
- /*
- * For the simple (and majority of) cases
- * where we don't need to do any remapping,
- * just cast the cookie directly.
- */
- p->membase = (void __iomem *)p->mapbase;
- }
+ if (dev->id != -1) {
+ ret = sci_probe_single(dev, dev->id, p, &sci_ports[dev->id]);
+ if (ret)
+ goto err_unreg;
+ } else {
+ for (i = 0; p && p->flags != 0; p++, i++) {
+ ret = sci_probe_single(dev, i, p, &sci_ports[i]);
+ if (ret)
+ goto err_unreg;
}
-
- sciport->port.membase = p->membase;
-
- sciport->port.irq = p->irqs[SCIx_TXI_IRQ];
- sciport->port.flags = p->flags;
- sciport->port.dev = &dev->dev;
-
- sciport->type = sciport->port.type = p->type;
-
- memcpy(&sciport->irqs, &p->irqs, sizeof(p->irqs));
-
- uart_add_one_port(&sci_uart_driver, &sciport->port);
}
-#ifdef CONFIG_HAVE_CLK
- cpufreq_register_notifier(&sci_nb, CPUFREQ_TRANSITION_NOTIFIER);
-#endif
-
#ifdef CONFIG_SH_STANDARD_BIOS
sh_bios_gdb_detach();
#endif
@@ -1274,50 +1329,36 @@ static int __devinit sci_probe(struct platform_device *dev)
return 0;
err_unreg:
- for (i = i - 1; i >= 0; i--)
- uart_remove_one_port(&sci_uart_driver, &sci_ports[i].port);
-
+ sci_remove(dev);
return ret;
}
-static int __devexit sci_remove(struct platform_device *dev)
-{
- int i;
-
-#ifdef CONFIG_HAVE_CLK
- cpufreq_unregister_notifier(&sci_nb, CPUFREQ_TRANSITION_NOTIFIER);
-#endif
-
- for (i = 0; i < SCI_NPORTS; i++)
- uart_remove_one_port(&sci_uart_driver, &sci_ports[i].port);
-
- return 0;
-}
-
static int sci_suspend(struct platform_device *dev, pm_message_t state)
{
- int i;
+ struct sh_sci_priv *priv = platform_get_drvdata(dev);
+ struct sci_port *p;
+ unsigned long flags;
- for (i = 0; i < SCI_NPORTS; i++) {
- struct sci_port *p = &sci_ports[i];
+ spin_lock_irqsave(&priv->lock, flags);
+ list_for_each_entry(p, &priv->ports, node)
+ uart_suspend_port(&sci_uart_driver, &p->port);
- if (p->type != PORT_UNKNOWN && p->port.dev == &dev->dev)
- uart_suspend_port(&sci_uart_driver, &p->port);
- }
+ spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
static int sci_resume(struct platform_device *dev)
{
- int i;
+ struct sh_sci_priv *priv = platform_get_drvdata(dev);
+ struct sci_port *p;
+ unsigned long flags;
- for (i = 0; i < SCI_NPORTS; i++) {
- struct sci_port *p = &sci_ports[i];
+ spin_lock_irqsave(&priv->lock, flags);
+ list_for_each_entry(p, &priv->ports, node)
+ uart_resume_port(&sci_uart_driver, &p->port);
- if (p->type != PORT_UNKNOWN && p->port.dev == &dev->dev)
- uart_resume_port(&sci_uart_driver, &p->port);
- }
+ spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
@@ -1339,8 +1380,6 @@ static int __init sci_init(void)
printk(banner);
- sci_init_ports();
-
ret = uart_register_driver(&sci_uart_driver);
if (likely(ret == 0)) {
ret = platform_driver_register(&sci_driver);
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index d0aa82d7fce0..38072c15b845 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -91,6 +91,9 @@
# define SCSPTR5 0xa4050128
# define SCIF_ORER 0x0001 /* overrun error bit */
# define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+#elif defined(CONFIG_CPU_SUBTYPE_SH7724)
+# define SCIF_ORER 0x0001 /* overrun error bit */
+# define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
#elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
# define SCSPTR2 0xffe80020 /* 16 bit SCIF */
# define SCIF_ORER 0x0001 /* overrun error bit */
@@ -314,7 +317,18 @@
} \
}
-#define CPU_SCIF_FNS(name, scif_offset, scif_size) \
+#ifdef CONFIG_H8300
+/* h8300 don't have SCIF */
+#define CPU_SCIF_FNS(name) \
+ static inline unsigned int sci_##name##_in(struct uart_port *port) \
+ { \
+ return 0; \
+ } \
+ static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \
+ { \
+ }
+#else
+#define CPU_SCIF_FNS(name, scif_offset, scif_size) \
static inline unsigned int sci_##name##_in(struct uart_port *port) \
{ \
SCI_IN(scif_size, scif_offset); \
@@ -323,6 +337,7 @@
{ \
SCI_OUT(scif_size, scif_offset, value); \
}
+#endif
#define CPU_SCI_FNS(name, sci_offset, sci_size) \
static inline unsigned int sci_##name##_in(struct uart_port* port) \
@@ -360,8 +375,10 @@
sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
h8_sci_offset, h8_sci_size) \
CPU_SCI_FNS(name, h8_sci_offset, h8_sci_size)
-#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
+#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \
+ CPU_SCIF_FNS(name)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\
+ defined(CONFIG_CPU_SUBTYPE_SH7724)
#define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size) \
CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size)
#define SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) \
@@ -390,7 +407,8 @@ SCIF_FNS(SCFDR, 0x1c, 16)
SCIF_FNS(SCxTDR, 0x20, 8)
SCIF_FNS(SCxRDR, 0x24, 8)
SCIF_FNS(SCLSR, 0x24, 16)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\
+ defined(CONFIG_CPU_SUBTYPE_SH7724)
SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16)
SCIx_FNS(SCBRR, 0x04, 8, 0x04, 8)
SCIx_FNS(SCSCR, 0x08, 16, 0x08, 16)
@@ -604,10 +622,21 @@ static inline int sci_rxd_in(struct uart_port *port)
return ctrl_inb(SCSPTR5) & 0x0008 ? 1 : 0; /* SCIF5 */
return 1;
}
+#elif defined(CONFIG_CPU_SUBTYPE_SH7724)
+# define SCFSR 0x0010
+# define SCASSR 0x0014
+static inline int sci_rxd_in(struct uart_port *port)
+{
+ if (port->type == PORT_SCIF)
+ return ctrl_inw((port->mapbase + SCFSR)) & SCIF_BRK ? 1 : 0;
+ if (port->type == PORT_SCIFA)
+ return ctrl_inw((port->mapbase + SCASSR)) & SCIF_BRK ? 1 : 0;
+ return 1;
+}
#elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
static inline int sci_rxd_in(struct uart_port *port)
{
- return sci_in(port, SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */
+ return sci_in(port, SCSPTR)&0x0001 ? 1 : 0; /* SCIF */
}
#elif defined(__H8300H__) || defined(__H8300S__)
static inline int sci_rxd_in(struct uart_port *port)
@@ -757,7 +786,8 @@ static inline int sci_rxd_in(struct uart_port *port)
defined(CONFIG_CPU_SUBTYPE_SH7720) || \
defined(CONFIG_CPU_SUBTYPE_SH7721)
#define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\
+ defined(CONFIG_CPU_SUBTYPE_SH7724)
static inline int scbrr_calc(struct uart_port *port, int bps, int clk)
{
if (port->type == PORT_SCIF)
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
index 7fb9b5c4669a..12d13d99b6f0 100644
--- a/drivers/sh/intc.c
+++ b/drivers/sh/intc.c
@@ -44,6 +44,7 @@ struct intc_handle_int {
struct intc_desc_int {
struct list_head list;
struct sys_device sysdev;
+ pm_message_t state;
unsigned long *reg;
#ifdef CONFIG_SMP
unsigned long *smp;
@@ -786,18 +787,44 @@ static int intc_suspend(struct sys_device *dev, pm_message_t state)
/* get intc controller associated with this sysdev */
d = container_of(dev, struct intc_desc_int, sysdev);
- /* enable wakeup irqs belonging to this intc controller */
- for_each_irq_desc(irq, desc) {
- if ((desc->status & IRQ_WAKEUP) && (desc->chip == &d->chip))
- intc_enable(irq);
+ switch (state.event) {
+ case PM_EVENT_ON:
+ if (d->state.event != PM_EVENT_FREEZE)
+ break;
+ for_each_irq_desc(irq, desc) {
+ if (desc->chip != &d->chip)
+ continue;
+ if (desc->status & IRQ_DISABLED)
+ intc_disable(irq);
+ else
+ intc_enable(irq);
+ }
+ break;
+ case PM_EVENT_FREEZE:
+ /* nothing has to be done */
+ break;
+ case PM_EVENT_SUSPEND:
+ /* enable wakeup irqs belonging to this intc controller */
+ for_each_irq_desc(irq, desc) {
+ if ((desc->status & IRQ_WAKEUP) && (desc->chip == &d->chip))
+ intc_enable(irq);
+ }
+ break;
}
+ d->state = state;
return 0;
}
+static int intc_resume(struct sys_device *dev)
+{
+ return intc_suspend(dev, PMSG_ON);
+}
+
static struct sysdev_class intc_sysdev_class = {
.name = "intc",
.suspend = intc_suspend,
+ .resume = intc_resume,
};
/* register this intc as sysdev to allow suspend/resume */
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index c1688c71f052..885194a07418 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -195,7 +195,7 @@ static void cs_deassert(struct driver_data *drv_data)
struct chip_data *chip = drv_data->cur_chip;
if (chip->cs_control) {
- chip->cs_control(PXA2XX_CS_ASSERT);
+ chip->cs_control(PXA2XX_CS_DEASSERT);
return;
}
@@ -213,7 +213,7 @@ static int flush(struct driver_data *drv_data)
while (read_SSSR(reg) & SSSR_RNE) {
read_SSDR(reg);
}
- } while ((read_SSSR(reg) & SSSR_BSY) && limit--);
+ } while ((read_SSSR(reg) & SSSR_BSY) && --limit);
write_SSSR(SSSR_ROR, reg);
return limit;
@@ -484,7 +484,7 @@ static int wait_ssp_rx_stall(void const __iomem *ioaddr)
{
unsigned long limit = loops_per_jiffy << 1;
- while ((read_SSSR(ioaddr) & SSSR_BSY) && limit--)
+ while ((read_SSSR(ioaddr) & SSSR_BSY) && --limit)
cpu_relax();
return limit;
@@ -494,7 +494,7 @@ static int wait_dma_channel_stop(int channel)
{
unsigned long limit = loops_per_jiffy << 1;
- while (!(DCSR(channel) & DCSR_STOPSTATE) && limit--)
+ while (!(DCSR(channel) & DCSR_STOPSTATE) && --limit)
cpu_relax();
return limit;
@@ -1700,6 +1700,13 @@ static int pxa2xx_spi_resume(struct platform_device *pdev)
struct ssp_device *ssp = drv_data->ssp;
int status = 0;
+ if (drv_data->rx_channel != -1)
+ DRCMR(drv_data->ssp->drcmr_rx) =
+ DRCMR_MAPVLD | drv_data->rx_channel;
+ if (drv_data->tx_channel != -1)
+ DRCMR(drv_data->ssp->drcmr_tx) =
+ DRCMR_MAPVLD | drv_data->tx_channel;
+
/* Enable the SSP clock */
clk_enable(ssp->clk);
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 643908b74bc0..8eba98c8ed1e 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -658,7 +658,7 @@ int spi_write_then_read(struct spi_device *spi,
int status;
struct spi_message message;
- struct spi_transfer x;
+ struct spi_transfer x[2];
u8 *local_buf;
/* Use preallocated DMA-safe buffer. We can't avoid copying here,
@@ -669,9 +669,15 @@ int spi_write_then_read(struct spi_device *spi,
return -EINVAL;
spi_message_init(&message);
- memset(&x, 0, sizeof x);
- x.len = n_tx + n_rx;
- spi_message_add_tail(&x, &message);
+ memset(x, 0, sizeof x);
+ if (n_tx) {
+ x[0].len = n_tx;
+ spi_message_add_tail(&x[0], &message);
+ }
+ if (n_rx) {
+ x[1].len = n_rx;
+ spi_message_add_tail(&x[1], &message);
+ }
/* ... unless someone else is using the pre-allocated buffer */
if (!mutex_trylock(&lock)) {
@@ -682,15 +688,15 @@ int spi_write_then_read(struct spi_device *spi,
local_buf = buf;
memcpy(local_buf, txbuf, n_tx);
- x.tx_buf = local_buf;
- x.rx_buf = local_buf;
+ x[0].tx_buf = local_buf;
+ x[1].rx_buf = local_buf + n_tx;
/* do the i/o */
status = spi_sync(spi, &message);
if (status == 0)
- memcpy(rxbuf, x.rx_buf + n_tx, n_rx);
+ memcpy(rxbuf, x[1].rx_buf, n_rx);
- if (x.tx_buf == buf)
+ if (x[0].tx_buf == buf)
mutex_unlock(&lock);
else
kfree(local_buf);
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
index 79e90fed27d3..299d29d1dadb 100644
--- a/drivers/staging/android/binder.c
+++ b/drivers/staging/android/binder.c
@@ -41,6 +41,8 @@ static int binder_last_id;
static struct proc_dir_entry *binder_proc_dir_entry_root;
static struct proc_dir_entry *binder_proc_dir_entry_proc;
static struct hlist_head binder_dead_nodes;
+static HLIST_HEAD(binder_deferred_list);
+static DEFINE_MUTEX(binder_deferred_lock);
static int binder_read_proc_proc(
char *page, char **start, off_t off, int count, int *eof, void *data);
@@ -54,11 +56,7 @@ static int binder_read_proc_proc(
#define SZ_4M 0x400000
#endif
-#ifndef __i386__
-#define FORBIDDEN_MMAP_FLAGS (VM_WRITE | VM_EXEC)
-#else
#define FORBIDDEN_MMAP_FLAGS (VM_WRITE)
-#endif
#define BINDER_SMALL_BUF_SIZE (PAGE_SIZE * 64)
@@ -236,6 +234,12 @@ struct binder_buffer {
uint8_t data[0];
};
+enum {
+ BINDER_DEFERRED_PUT_FILES = 0x01,
+ BINDER_DEFERRED_FLUSH = 0x02,
+ BINDER_DEFERRED_RELEASE = 0x04,
+};
+
struct binder_proc {
struct hlist_node proc_node;
struct rb_root threads;
@@ -245,8 +249,11 @@ struct binder_proc {
int pid;
struct vm_area_struct *vma;
struct task_struct *tsk;
+ struct files_struct *files;
+ struct hlist_node deferred_work_node;
+ int deferred_work;
void *buffer;
- size_t user_buffer_offset;
+ ptrdiff_t user_buffer_offset;
struct list_head buffers;
struct rb_root free_buffers;
@@ -310,12 +317,14 @@ struct binder_transaction {
uid_t sender_euid;
};
+static void binder_defer_work(struct binder_proc *proc, int defer);
+
/*
* copied from get_unused_fd_flags
*/
-int task_get_unused_fd_flags(struct task_struct *tsk, int flags)
+int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
{
- struct files_struct *files = get_files_struct(tsk);
+ struct files_struct *files = proc->files;
int fd, error;
struct fdtable *fdt;
unsigned long rlim_cur;
@@ -337,9 +346,9 @@ repeat:
* will limit the total number of files that can be opened.
*/
rlim_cur = 0;
- if (lock_task_sighand(tsk, &irqs)) {
- rlim_cur = tsk->signal->rlim[RLIMIT_NOFILE].rlim_cur;
- unlock_task_sighand(tsk, &irqs);
+ if (lock_task_sighand(proc->tsk, &irqs)) {
+ rlim_cur = proc->tsk->signal->rlim[RLIMIT_NOFILE].rlim_cur;
+ unlock_task_sighand(proc->tsk, &irqs);
}
if (fd >= rlim_cur)
goto out;
@@ -375,7 +384,6 @@ repeat:
out:
spin_unlock(&files->file_lock);
- put_files_struct(files);
return error;
}
@@ -383,9 +391,9 @@ out:
* copied from fd_install
*/
static void task_fd_install(
- struct task_struct *tsk, unsigned int fd, struct file *file)
+ struct binder_proc *proc, unsigned int fd, struct file *file)
{
- struct files_struct *files = get_files_struct(tsk);
+ struct files_struct *files = proc->files;
struct fdtable *fdt;
if (files == NULL)
@@ -396,7 +404,6 @@ static void task_fd_install(
BUG_ON(fdt->fd[fd] != NULL);
rcu_assign_pointer(fdt->fd[fd], file);
spin_unlock(&files->file_lock);
- put_files_struct(files);
}
/*
@@ -413,10 +420,10 @@ static void __put_unused_fd(struct files_struct *files, unsigned int fd)
/*
* copied from sys_close
*/
-static long task_close_fd(struct task_struct *tsk, unsigned int fd)
+static long task_close_fd(struct binder_proc *proc, unsigned int fd)
{
struct file *filp;
- struct files_struct *files = get_files_struct(tsk);
+ struct files_struct *files = proc->files;
struct fdtable *fdt;
int retval;
@@ -443,12 +450,10 @@ static long task_close_fd(struct task_struct *tsk, unsigned int fd)
retval == -ERESTART_RESTARTBLOCK))
retval = -EINTR;
- put_files_struct(files);
return retval;
out_unlock:
spin_unlock(&files->file_lock);
- put_files_struct(files);
return -EBADF;
}
@@ -618,7 +623,8 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
proc->pid, page_addr);
goto err_map_kernel_failed;
}
- user_page_addr = (size_t)page_addr + proc->user_buffer_offset;
+ user_page_addr =
+ (uintptr_t)page_addr + proc->user_buffer_offset;
ret = vm_insert_page(vma, user_page_addr, page[0]);
if (ret) {
printk(KERN_ERR "binder: %d: binder_alloc_buf failed "
@@ -639,7 +645,7 @@ free_range:
page_addr -= PAGE_SIZE) {
page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
if (vma)
- zap_page_range(vma, (size_t)page_addr +
+ zap_page_range(vma, (uintptr_t)page_addr +
proc->user_buffer_offset, PAGE_SIZE, NULL);
err_vm_insert_page_failed:
unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
@@ -720,18 +726,19 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
"er %p size %zd\n", proc->pid, size, buffer, buffer_size);
has_page_addr =
- (void *)(((size_t)buffer->data + buffer_size) & PAGE_MASK);
+ (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK);
if (n == NULL) {
if (size + sizeof(struct binder_buffer) + 4 >= buffer_size)
buffer_size = size; /* no room for other buffers */
else
buffer_size = size + sizeof(struct binder_buffer);
}
- end_page_addr = (void *)PAGE_ALIGN((size_t)buffer->data + buffer_size);
+ end_page_addr =
+ (void *)PAGE_ALIGN((uintptr_t)buffer->data + buffer_size);
if (end_page_addr > has_page_addr)
end_page_addr = has_page_addr;
if (binder_update_page_range(proc, 1,
- (void *)PAGE_ALIGN((size_t)buffer->data), end_page_addr, NULL))
+ (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr, NULL))
return NULL;
rb_erase(best_fit, &proc->free_buffers);
@@ -762,12 +769,12 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
static void *buffer_start_page(struct binder_buffer *buffer)
{
- return (void *)((size_t)buffer & PAGE_MASK);
+ return (void *)((uintptr_t)buffer & PAGE_MASK);
}
static void *buffer_end_page(struct binder_buffer *buffer)
{
- return (void *)(((size_t)(buffer + 1) - 1) & PAGE_MASK);
+ return (void *)(((uintptr_t)(buffer + 1) - 1) & PAGE_MASK);
}
static void binder_delete_free_buffer(
@@ -845,8 +852,8 @@ static void binder_free_buf(
}
binder_update_page_range(proc, 0,
- (void *)PAGE_ALIGN((size_t)buffer->data),
- (void *)(((size_t)buffer->data + buffer_size) & PAGE_MASK),
+ (void *)PAGE_ALIGN((uintptr_t)buffer->data),
+ (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK),
NULL);
rb_erase(&buffer->rb_node, &proc->allocated_buffers);
buffer->free = 1;
@@ -1345,6 +1352,17 @@ binder_transaction(struct binder_proc *proc, struct binder_thread *thread,
if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) {
struct binder_transaction *tmp;
tmp = thread->transaction_stack;
+ if (tmp->to_thread != thread) {
+ binder_user_error("binder: %d:%d got new "
+ "transaction with bad transaction stack"
+ ", transaction %d has target %d:%d\n",
+ proc->pid, thread->pid, tmp->debug_id,
+ tmp->to_proc ? tmp->to_proc->pid : 0,
+ tmp->to_thread ?
+ tmp->to_thread->pid : 0);
+ return_error = BR_FAILED_REPLY;
+ goto err_bad_call_stack;
+ }
while (tmp) {
if (tmp->from && tmp->from->proc == target_proc)
target_thread = tmp->from;
@@ -1434,10 +1452,19 @@ binder_transaction(struct binder_proc *proc, struct binder_thread *thread,
return_error = BR_FAILED_REPLY;
goto err_copy_data_failed;
}
+ if (!IS_ALIGNED(tr->offsets_size, sizeof(size_t))) {
+ binder_user_error("binder: %d:%d got transaction with "
+ "invalid offsets size, %zd\n",
+ proc->pid, thread->pid, tr->offsets_size);
+ return_error = BR_FAILED_REPLY;
+ goto err_bad_offset;
+ }
off_end = (void *)offp + tr->offsets_size;
for (; offp < off_end; offp++) {
struct flat_binder_object *fp;
- if (*offp > t->buffer->data_size - sizeof(*fp)) {
+ if (*offp > t->buffer->data_size - sizeof(*fp) ||
+ t->buffer->data_size < sizeof(*fp) ||
+ !IS_ALIGNED(*offp, sizeof(void *))) {
binder_user_error("binder: %d:%d got transaction with "
"invalid offset, %zd\n",
proc->pid, thread->pid, *offp);
@@ -1544,13 +1571,13 @@ binder_transaction(struct binder_proc *proc, struct binder_thread *thread,
return_error = BR_FAILED_REPLY;
goto err_fget_failed;
}
- target_fd = task_get_unused_fd_flags(target_proc->tsk, O_CLOEXEC);
+ target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);
if (target_fd < 0) {
fput(file);
return_error = BR_FAILED_REPLY;
goto err_get_unused_fd_failed;
}
- task_fd_install(target_proc->tsk, target_fd, file);
+ task_fd_install(target_proc, target_fd, file);
if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)
printk(KERN_INFO " fd %ld -> %d\n", fp->handle, target_fd);
/* TODO: fput? */
@@ -1655,7 +1682,9 @@ binder_transaction_buffer_release(struct binder_proc *proc, struct binder_buffer
off_end = (void *)offp + buffer->offsets_size;
for (; offp < off_end; offp++) {
struct flat_binder_object *fp;
- if (*offp > buffer->data_size - sizeof(*fp)) {
+ if (*offp > buffer->data_size - sizeof(*fp) ||
+ buffer->data_size < sizeof(*fp) ||
+ !IS_ALIGNED(*offp, sizeof(void *))) {
printk(KERN_ERR "binder: transaction release %d bad"
"offset %zd, size %zd\n", debug_id, *offp, buffer->data_size);
continue;
@@ -1691,7 +1720,7 @@ binder_transaction_buffer_release(struct binder_proc *proc, struct binder_buffer
if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)
printk(KERN_INFO " fd %ld\n", fp->handle);
if (failed_at)
- task_close_fd(proc->tsk, fp->handle);
+ task_close_fd(proc, fp->handle);
break;
default:
@@ -2340,7 +2369,7 @@ retry:
tr.data_size = t->buffer->data_size;
tr.offsets_size = t->buffer->offsets_size;
- tr.data.ptr.buffer = (void *)((void *)t->buffer->data + proc->user_buffer_offset);
+ tr.data.ptr.buffer = (void *)t->buffer->data + proc->user_buffer_offset;
tr.data.ptr.offsets = tr.data.ptr.buffer + ALIGN(t->buffer->data_size, sizeof(void *));
if (put_user(cmd, (uint32_t __user *)ptr))
@@ -2656,6 +2685,7 @@ static void binder_vma_open(struct vm_area_struct *vma)
(unsigned long)pgprot_val(vma->vm_page_prot));
dump_stack();
}
+
static void binder_vma_close(struct vm_area_struct *vma)
{
struct binder_proc *proc = vma->vm_private_data;
@@ -2666,6 +2696,7 @@ static void binder_vma_close(struct vm_area_struct *vma)
(vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
(unsigned long)pgprot_val(vma->vm_page_prot));
proc->vma = NULL;
+ binder_defer_work(proc, BINDER_DEFERRED_PUT_FILES);
}
static struct vm_operations_struct binder_vm_ops = {
@@ -2698,6 +2729,12 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
}
vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE;
+ if (proc->buffer) {
+ ret = -EBUSY;
+ failure_string = "already mapped";
+ goto err_already_mapped;
+ }
+
area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP);
if (area == NULL) {
ret = -ENOMEM;
@@ -2705,7 +2742,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
goto err_get_vm_area_failed;
}
proc->buffer = area->addr;
- proc->user_buffer_offset = vma->vm_start - (size_t)proc->buffer;
+ proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;
#ifdef CONFIG_CPU_CACHE_VIPT
if (cache_is_vipt_aliasing()) {
@@ -2738,6 +2775,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
binder_insert_free_buffer(proc, buffer);
proc->free_async_space = proc->buffer_size / 2;
barrier();
+ proc->files = get_files_struct(current);
proc->vma = vma;
/*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/
@@ -2745,10 +2783,12 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
err_alloc_small_buf_failed:
kfree(proc->pages);
+ proc->pages = NULL;
err_alloc_pages_failed:
vfree(proc->buffer);
+ proc->buffer = NULL;
err_get_vm_area_failed:
- mutex_unlock(&binder_lock);
+err_already_mapped:
err_bad_arg:
printk(KERN_ERR "binder_mmap: %d %lx-%lx %s failed %d\n", proc->pid, vma->vm_start, vma->vm_end, failure_string, ret);
return ret;
@@ -2780,6 +2820,7 @@ static int binder_open(struct inode *nodp, struct file *filp)
if (binder_proc_dir_entry_proc) {
char strbuf[11];
snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
+ remove_proc_entry(strbuf, binder_proc_dir_entry_proc);
create_proc_read_entry(strbuf, S_IRUGO, binder_proc_dir_entry_proc, binder_read_proc_proc, proc);
}
@@ -2788,11 +2829,17 @@ static int binder_open(struct inode *nodp, struct file *filp)
static int binder_flush(struct file *filp, fl_owner_t id)
{
- struct rb_node *n;
struct binder_proc *proc = filp->private_data;
- int wake_count = 0;
- mutex_lock(&binder_lock);
+ binder_defer_work(proc, BINDER_DEFERRED_FLUSH);
+
+ return 0;
+}
+
+static void binder_deferred_flush(struct binder_proc *proc)
+{
+ struct rb_node *n;
+ int wake_count = 0;
for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) {
struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node);
thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN;
@@ -2802,28 +2849,35 @@ static int binder_flush(struct file *filp, fl_owner_t id)
}
}
wake_up_interruptible_all(&proc->wait);
- mutex_unlock(&binder_lock);
if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)
printk(KERN_INFO "binder_flush: %d woke %d threads\n", proc->pid, wake_count);
-
- return 0;
}
static int binder_release(struct inode *nodp, struct file *filp)
{
- struct hlist_node *pos;
- struct binder_transaction *t;
- struct rb_node *n;
struct binder_proc *proc = filp->private_data;
- int threads, nodes, incoming_refs, outgoing_refs, buffers, active_transactions, page_count;
-
if (binder_proc_dir_entry_proc) {
char strbuf[11];
snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
remove_proc_entry(strbuf, binder_proc_dir_entry_proc);
}
- mutex_lock(&binder_lock);
+
+ binder_defer_work(proc, BINDER_DEFERRED_RELEASE);
+
+ return 0;
+}
+
+static void binder_deferred_release(struct binder_proc *proc)
+{
+ struct hlist_node *pos;
+ struct binder_transaction *t;
+ struct rb_node *n;
+ int threads, nodes, incoming_refs, outgoing_refs, buffers, active_transactions, page_count;
+
+ BUG_ON(proc->vma);
+ BUG_ON(proc->files);
+
hlist_del(&proc->proc_node);
if (binder_context_mgr_node && binder_context_mgr_node->proc == proc) {
if (binder_debug_mask & BINDER_DEBUG_DEAD_BINDER)
@@ -2897,7 +2951,6 @@ static int binder_release(struct inode *nodp, struct file *filp)
}
binder_stats.obj_deleted[BINDER_STAT_PROC]++;
- mutex_unlock(&binder_lock);
page_count = 0;
if (proc->pages) {
@@ -2921,7 +2974,57 @@ static int binder_release(struct inode *nodp, struct file *filp)
proc->pid, threads, nodes, incoming_refs, outgoing_refs, active_transactions, buffers, page_count);
kfree(proc);
- return 0;
+}
+
+static void binder_deferred_func(struct work_struct *work)
+{
+ struct binder_proc *proc;
+ struct files_struct *files;
+
+ int defer;
+ do {
+ mutex_lock(&binder_lock);
+ mutex_lock(&binder_deferred_lock);
+ if (!hlist_empty(&binder_deferred_list)) {
+ proc = hlist_entry(binder_deferred_list.first,
+ struct binder_proc, deferred_work_node);
+ hlist_del_init(&proc->deferred_work_node);
+ defer = proc->deferred_work;
+ proc->deferred_work = 0;
+ } else {
+ proc = NULL;
+ defer = 0;
+ }
+ mutex_unlock(&binder_deferred_lock);
+
+ files = NULL;
+ if (defer & BINDER_DEFERRED_PUT_FILES)
+ if ((files = proc->files))
+ proc->files = NULL;
+
+ if (defer & BINDER_DEFERRED_FLUSH)
+ binder_deferred_flush(proc);
+
+ if (defer & BINDER_DEFERRED_RELEASE)
+ binder_deferred_release(proc); /* frees proc */
+
+ mutex_unlock(&binder_lock);
+ if (files)
+ put_files_struct(files);
+ } while (proc);
+}
+static DECLARE_WORK(binder_deferred_work, binder_deferred_func);
+
+static void binder_defer_work(struct binder_proc *proc, int defer)
+{
+ mutex_lock(&binder_deferred_lock);
+ proc->deferred_work |= defer;
+ if (hlist_unhashed(&proc->deferred_work_node)) {
+ hlist_add_head(&proc->deferred_work_node,
+ &binder_deferred_list);
+ schedule_work(&binder_deferred_work);
+ }
+ mutex_unlock(&binder_deferred_lock);
}
static char *print_binder_transaction(char *buf, char *end, const char *prefix, struct binder_transaction *t)
diff --git a/drivers/staging/at76_usb/at76_usb.c b/drivers/staging/at76_usb/at76_usb.c
index 6f6e36a3bd9f..c8af9a868d62 100644
--- a/drivers/staging/at76_usb/at76_usb.c
+++ b/drivers/staging/at76_usb/at76_usb.c
@@ -5259,6 +5259,18 @@ static int at76_alloc_urbs(struct at76_priv *priv,
return 0;
}
+static const struct net_device_ops at76_netdev_ops = {
+ .ndo_open = at76_open,
+ .ndo_stop = at76_stop,
+ .ndo_get_stats = at76_get_stats,
+ .ndo_start_xmit = at76_tx,
+ .ndo_tx_timeout = at76_tx_timeout,
+ .ndo_set_multicast_list = at76_set_multicast,
+ .ndo_set_mac_address = at76_set_mac_address,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+};
+
/* Register network device and initialize the hardware */
static int at76_init_new_device(struct at76_priv *priv,
struct usb_interface *interface)
@@ -5303,21 +5315,15 @@ static int at76_init_new_device(struct at76_priv *priv,
priv->scan_mode = SCAN_TYPE_ACTIVE;
netdev->flags &= ~IFF_MULTICAST; /* not yet or never */
- netdev->open = at76_open;
- netdev->stop = at76_stop;
- netdev->get_stats = at76_get_stats;
+ netdev->netdev_ops = &at76_netdev_ops;
netdev->ethtool_ops = &at76_ethtool_ops;
/* Add pointers to enable iwspy support. */
priv->wireless_data.spy_data = &priv->spy_data;
netdev->wireless_data = &priv->wireless_data;
- netdev->hard_start_xmit = at76_tx;
- netdev->tx_timeout = at76_tx_timeout;
netdev->watchdog_timeo = 2 * HZ;
netdev->wireless_handlers = &at76_handler_def;
- netdev->set_multicast_list = at76_set_multicast;
- netdev->set_mac_address = at76_set_mac_address;
dev_alloc_name(netdev, "wlan%d");
ret = register_netdev(priv->netdev);
diff --git a/drivers/staging/b3dfg/b3dfg.c b/drivers/staging/b3dfg/b3dfg.c
index 0348072b3ab5..75ebe338c6f2 100644
--- a/drivers/staging/b3dfg/b3dfg.c
+++ b/drivers/staging/b3dfg/b3dfg.c
@@ -1000,7 +1000,7 @@ static int __devinit b3dfg_probe(struct pci_dev *pdev,
pci_set_master(pdev);
- r = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ r = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (r) {
dev_err(&pdev->dev, "no usable DMA configuration\n");
goto err_free_res;
diff --git a/drivers/staging/comedi/TODO b/drivers/staging/comedi/TODO
index 557812958464..15c9348fb938 100644
--- a/drivers/staging/comedi/TODO
+++ b/drivers/staging/comedi/TODO
@@ -11,4 +11,3 @@ Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
copy:
Ian Abbott <abbotti@mev.co.uk>
Frank Mori Hess <fmhess@users.sourceforge.net>
- David Schleef <ds@schleef.org>
diff --git a/drivers/staging/epl/VirtualEthernetLinux.c b/drivers/staging/epl/VirtualEthernetLinux.c
index 21206c4d22ff..077724a556cc 100644
--- a/drivers/staging/epl/VirtualEthernetLinux.c
+++ b/drivers/staging/epl/VirtualEthernetLinux.c
@@ -284,6 +284,17 @@ static tEplKernel VEthRecvFrame(tEplFrameInfo * pFrameInfo_p)
return Ret;
}
+static const struct net_device_ops epl_netdev_ops = {
+ .ndo_open = VEthOpen,
+ .ndo_stop = VEthClose,
+ .ndo_get_stats = VEthGetStats,
+ .ndo_start_xmit = VEthXmit,
+ .ndo_tx_timeout = VEthTimeout,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
tEplKernel VEthAddInstance(tEplDllkInitParam *pInitParam_p)
{
tEplKernel Ret = kEplSuccessful;
@@ -299,11 +310,7 @@ tEplKernel VEthAddInstance(tEplDllkInitParam *pInitParam_p)
goto Exit;
}
- pVEthNetDevice_g->open = VEthOpen;
- pVEthNetDevice_g->stop = VEthClose;
- pVEthNetDevice_g->get_stats = VEthGetStats;
- pVEthNetDevice_g->hard_start_xmit = VEthXmit;
- pVEthNetDevice_g->tx_timeout = VEthTimeout;
+ pVEthNetDevice_g->netdev_ops = &epl_netdev_ops;
pVEthNetDevice_g->watchdog_timeo = EPL_VETH_TX_TIMEOUT;
pVEthNetDevice_g->destructor = free_netdev;
diff --git a/drivers/staging/et131x/et131x_netdev.c b/drivers/staging/et131x/et131x_netdev.c
index de65972ff362..951c73d5db20 100644
--- a/drivers/staging/et131x/et131x_netdev.c
+++ b/drivers/staging/et131x/et131x_netdev.c
@@ -112,6 +112,19 @@ void et131x_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
void et131x_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
void et131x_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
+static const struct net_device_ops et131x_netdev_ops = {
+ .ndo_open = et131x_open,
+ .ndo_stop = et131x_close,
+ .ndo_start_xmit = et131x_tx,
+ .ndo_set_multicast_list = et131x_multicast,
+ .ndo_tx_timeout = et131x_tx_timeout,
+ .ndo_change_mtu = et131x_change_mtu,
+ .ndo_set_mac_address = et131x_set_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_get_stats = et131x_stats,
+ .ndo_do_ioctl = et131x_ioctl,
+};
+
/**
* et131x_device_alloc
*
@@ -142,16 +155,8 @@ struct net_device *et131x_device_alloc(void)
*/
//netdev->init = &et131x_init;
//netdev->set_config = &et131x_config;
- netdev->get_stats = &et131x_stats;
- netdev->open = &et131x_open;
- netdev->stop = &et131x_close;
- netdev->do_ioctl = &et131x_ioctl;
- netdev->set_multicast_list = &et131x_multicast;
- netdev->hard_start_xmit = &et131x_tx;
- netdev->tx_timeout = &et131x_tx_timeout;
netdev->watchdog_timeo = ET131X_TX_TIMEOUT;
- netdev->change_mtu = &et131x_change_mtu;
- netdev->set_mac_address = &et131x_set_mac_addr;
+ netdev->netdev_ops = &et131x_netdev_ops;
//netdev->ethtool_ops = &et131x_ethtool_ops;
diff --git a/drivers/staging/go7007/go7007-driver.c b/drivers/staging/go7007/go7007-driver.c
index 58bfc8d81b3b..77b1e769ac92 100644
--- a/drivers/staging/go7007/go7007-driver.c
+++ b/drivers/staging/go7007/go7007-driver.c
@@ -191,8 +191,10 @@ int go7007_reset_encoder(struct go7007 *go)
/*
* Attempt to instantiate an I2C client by ID, probably loading a module.
*/
-static int init_i2c_module(struct i2c_adapter *adapter, int id, int addr)
+static int init_i2c_module(struct i2c_adapter *adapter, const char *type,
+ int id, int addr)
{
+ struct i2c_board_info info;
char *modname;
switch (id) {
@@ -226,7 +228,11 @@ static int init_i2c_module(struct i2c_adapter *adapter, int id, int addr)
}
if (modname != NULL)
request_module(modname);
- if (wis_i2c_probe_device(adapter, id, addr) == 1)
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ info.addr = addr;
+ strlcpy(info.type, type, I2C_NAME_SIZE);
+ if (!i2c_new_device(adapter, &info))
return 0;
if (modname != NULL)
printk(KERN_INFO
@@ -266,23 +272,9 @@ int go7007_register_encoder(struct go7007 *go)
if (go->i2c_adapter_online) {
for (i = 0; i < go->board_info->num_i2c_devs; ++i)
init_i2c_module(&go->i2c_adapter,
+ go->board_info->i2c_devs[i].type,
go->board_info->i2c_devs[i].id,
go->board_info->i2c_devs[i].addr);
-#ifdef TUNER_SET_TYPE_ADDR
- if (go->tuner_type >= 0) {
- struct tuner_setup tun_setup = {
- .mode_mask = T_ANALOG_TV,
- .addr = ADDR_UNSET,
- .type = go->tuner_type
- };
- i2c_clients_command(&go->i2c_adapter,
- TUNER_SET_TYPE_ADDR, &tun_setup);
- }
-#else
- if (go->tuner_type >= 0)
- i2c_clients_command(&go->i2c_adapter,
- TUNER_SET_TYPE, &go->tuner_type);
-#endif
if (go->board_id == GO7007_BOARDID_ADLINK_MPG24)
i2c_clients_command(&go->i2c_adapter,
DECODER_SET_CHANNEL, &go->channel_number);
diff --git a/drivers/staging/go7007/go7007-i2c.c b/drivers/staging/go7007/go7007-i2c.c
index cd55b76eabc7..c82867fdd28d 100644
--- a/drivers/staging/go7007/go7007-i2c.c
+++ b/drivers/staging/go7007/go7007-i2c.c
@@ -31,87 +31,6 @@
#include "go7007-priv.h"
#include "wis-i2c.h"
-/************** Registration interface for I2C client drivers **************/
-
-/* Since there's no way to auto-probe the I2C devices connected to the I2C
- * bus on the go7007, we have this silly little registration system that
- * client drivers can use to register their I2C driver ID and their
- * detect_client function (the one that's normally passed to i2c_probe).
- *
- * When a new go7007 device is connected, we can look up in a board info
- * table by the USB or PCI vendor/product/revision ID to determine
- * which I2C client module to load. The client driver module will register
- * itself here, and then we can call the registered detect_client function
- * to force-load a new client at the address listed in the board info table.
- *
- * Really the I2C subsystem should have a way to force-load I2C client
- * drivers when we have a priori knowledge of what's on the bus, especially
- * since the existing I2C auto-probe mechanism is so hokey, but we'll use
- * our own mechanism for the time being. */
-
-struct wis_i2c_client_driver {
- unsigned int id;
- found_proc found_proc;
- struct list_head list;
-};
-
-static LIST_HEAD(i2c_client_drivers);
-static DECLARE_MUTEX(i2c_client_driver_list_lock);
-
-/* Client drivers register here by their I2C driver ID */
-int wis_i2c_add_driver(unsigned int id, found_proc found_proc)
-{
- struct wis_i2c_client_driver *driver;
-
- driver = kmalloc(sizeof(struct wis_i2c_client_driver), GFP_KERNEL);
- if (driver == NULL)
- return -ENOMEM;
- driver->id = id;
- driver->found_proc = found_proc;
-
- down(&i2c_client_driver_list_lock);
- list_add_tail(&driver->list, &i2c_client_drivers);
- up(&i2c_client_driver_list_lock);
-
- return 0;
-}
-EXPORT_SYMBOL(wis_i2c_add_driver);
-
-void wis_i2c_del_driver(found_proc found_proc)
-{
- struct wis_i2c_client_driver *driver, *next;
-
- down(&i2c_client_driver_list_lock);
- list_for_each_entry_safe(driver, next, &i2c_client_drivers, list)
- if (driver->found_proc == found_proc) {
- list_del(&driver->list);
- kfree(driver);
- }
- up(&i2c_client_driver_list_lock);
-}
-EXPORT_SYMBOL(wis_i2c_del_driver);
-
-/* The main go7007 driver calls this to instantiate a client by driver
- * ID and bus address, which are both stored in the board info table */
-int wis_i2c_probe_device(struct i2c_adapter *adapter,
- unsigned int id, int addr)
-{
- struct wis_i2c_client_driver *driver;
- int found = 0;
-
- if (addr < 0 || addr > 0x7f)
- return -1;
- down(&i2c_client_driver_list_lock);
- list_for_each_entry(driver, &i2c_client_drivers, list)
- if (driver->id == id) {
- if (driver->found_proc(adapter, addr, 0) == 0)
- found = 1;
- break;
- }
- up(&i2c_client_driver_list_lock);
- return found;
-}
-
/********************* Driver for on-board I2C adapter *********************/
/* #define GO7007_I2C_DEBUG */
@@ -287,9 +206,7 @@ static struct i2c_algorithm go7007_algo = {
static struct i2c_adapter go7007_adap_templ = {
.owner = THIS_MODULE,
- .class = I2C_CLASS_TV_ANALOG,
.name = "WIS GO7007SB",
- .id = I2C_ALGO_GO7007,
.algo = &go7007_algo,
};
diff --git a/drivers/staging/go7007/go7007-priv.h b/drivers/staging/go7007/go7007-priv.h
index 372f1f1c09b2..178d18119faa 100644
--- a/drivers/staging/go7007/go7007-priv.h
+++ b/drivers/staging/go7007/go7007-priv.h
@@ -87,6 +87,7 @@ struct go7007_board_info {
int audio_main_div;
int num_i2c_devs;
struct {
+ const char *type;
int id;
int addr;
} i2c_devs[4];
diff --git a/drivers/staging/go7007/go7007-usb.c b/drivers/staging/go7007/go7007-usb.c
index 83eec920c7d3..aa4a9e0b9954 100644
--- a/drivers/staging/go7007/go7007-usb.c
+++ b/drivers/staging/go7007/go7007-usb.c
@@ -91,6 +91,7 @@ static struct go7007_usb_board board_matrix_ii = {
.num_i2c_devs = 1,
.i2c_devs = {
{
+ .type = "wis_saa7115",
.id = I2C_DRIVERID_WIS_SAA7115,
.addr = 0x20,
},
@@ -127,6 +128,7 @@ static struct go7007_usb_board board_matrix_reload = {
.num_i2c_devs = 1,
.i2c_devs = {
{
+ .type = "wis_saa7113",
.id = I2C_DRIVERID_WIS_SAA7113,
.addr = 0x25,
},
@@ -164,6 +166,7 @@ static struct go7007_usb_board board_star_trek = {
.num_i2c_devs = 1,
.i2c_devs = {
{
+ .type = "wis_saa7115",
.id = I2C_DRIVERID_WIS_SAA7115,
.addr = 0x20,
},
@@ -209,14 +212,17 @@ static struct go7007_usb_board board_px_tv402u = {
.num_i2c_devs = 3,
.i2c_devs = {
{
+ .type = "wis_saa7115",
.id = I2C_DRIVERID_WIS_SAA7115,
.addr = 0x20,
},
{
+ .type = "wis_uda1342",
.id = I2C_DRIVERID_WIS_UDA1342,
.addr = 0x1a,
},
{
+ .type = "wis_sony_tuner",
.id = I2C_DRIVERID_WIS_SONY_TUNER,
.addr = 0x60,
},
@@ -264,6 +270,7 @@ static struct go7007_usb_board board_xmen = {
.num_i2c_devs = 1,
.i2c_devs = {
{
+ .type = "wis_ov7640",
.id = I2C_DRIVERID_WIS_OV7640,
.addr = 0x21,
},
@@ -296,6 +303,7 @@ static struct go7007_usb_board board_matrix_revolution = {
.num_i2c_devs = 1,
.i2c_devs = {
{
+ .type = "wis_tw9903",
.id = I2C_DRIVERID_WIS_TW9903,
.addr = 0x44,
},
@@ -385,6 +393,7 @@ static struct go7007_usb_board board_adlink_mpg24 = {
.num_i2c_devs = 1,
.i2c_devs = {
{
+ .type = "wis_twTW2804",
.id = I2C_DRIVERID_WIS_TW2804,
.addr = 0x00, /* yes, really */
},
@@ -415,8 +424,9 @@ static struct go7007_usb_board board_sensoray_2250 = {
.num_i2c_devs = 1,
.i2c_devs = {
{
+ .type = "s2250_board",
.id = I2C_DRIVERID_S2250,
- .addr = 0x34,
+ .addr = 0x43,
},
},
.num_inputs = 2,
@@ -943,9 +953,7 @@ static struct i2c_algorithm go7007_usb_algo = {
static struct i2c_adapter go7007_usb_adap_templ = {
.owner = THIS_MODULE,
- .class = I2C_CLASS_TV_ANALOG,
.name = "WIS GO7007SB EZ-USB",
- .id = I2C_ALGO_GO7007_USB,
.algo = &go7007_usb_algo,
};
diff --git a/drivers/staging/go7007/go7007.txt b/drivers/staging/go7007/go7007.txt
index 9f6772bc68c2..1c2907c1dc81 100644
--- a/drivers/staging/go7007/go7007.txt
+++ b/drivers/staging/go7007/go7007.txt
@@ -2,7 +2,7 @@ This is a driver for the WIS GO7007SB multi-format video encoder.
Pete Eberlein <pete@sensoray.com>
-The driver was orignally released under the GPL and is currently hosted at:
+The driver was originally released under the GPL and is currently hosted at:
http://nikosapi.org/wiki/index.php/WIS_Go7007_Linux_driver
The go7007 firmware can be acquired from the package on the site above.
@@ -24,7 +24,7 @@ These should be used instead of the non-standard GO7007 ioctls described
below.
-The README files from the orignal package appear below:
+The README files from the original package appears below:
---------------------------------------------------------------------------
WIS GO7007SB Public Linux Driver
diff --git a/drivers/staging/go7007/s2250-board.c b/drivers/staging/go7007/s2250-board.c
index d333ea2cd774..1706fbf06847 100644
--- a/drivers/staging/go7007/s2250-board.c
+++ b/drivers/staging/go7007/s2250-board.c
@@ -28,7 +28,6 @@ extern int s2250loader_init(void);
extern void s2250loader_cleanup(void);
#define TLV320_ADDRESS 0x34
-#define S2250_VIDDEC 0x86
#define VPX322_ADDR_ANALOGCONTROL1 0x02
#define VPX322_ADDR_BRIGHTNESS0 0x0127
#define VPX322_ADDR_BRIGHTNESS1 0x0131
@@ -123,6 +122,7 @@ struct s2250 {
int hue;
int reg12b_val;
int audio_input;
+ struct i2c_client *audio;
};
/* from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/
@@ -452,16 +452,15 @@ static int s2250_command(struct i2c_client *client,
{
struct v4l2_audio *audio = arg;
- client->addr = TLV320_ADDRESS;
switch (audio->index) {
case 0:
- write_reg(client, 0x08, 0x02); /* Line In */
+ write_reg(dec->audio, 0x08, 0x02); /* Line In */
break;
case 1:
- write_reg(client, 0x08, 0x04); /* Mic */
+ write_reg(dec->audio, 0x08, 0x04); /* Mic */
break;
case 2:
- write_reg(client, 0x08, 0x05); /* Mic Boost */
+ write_reg(dec->audio, 0x08, 0x05); /* Mic Boost */
break;
default:
return -EINVAL;
@@ -477,31 +476,23 @@ static int s2250_command(struct i2c_client *client,
return 0;
}
-static struct i2c_driver s2250_driver;
-
-static struct i2c_client s2250_client_templ = {
- .name = "Sensoray 2250",
- .driver = &s2250_driver,
-};
-
-static int s2250_detect(struct i2c_adapter *adapter, int addr, int kind)
+static int s2250_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct i2c_client *client;
+ struct i2c_client *audio;
+ struct i2c_adapter *adapter = client->adapter;
struct s2250 *dec;
u8 *data;
struct go7007 *go = i2c_get_adapdata(adapter);
struct go7007_usb *usb = go->hpi_context;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == NULL)
+ audio = i2c_new_dummy(adapter, TLV320_ADDRESS >> 1);
+ if (audio == NULL)
return -ENOMEM;
- memcpy(client, &s2250_client_templ,
- sizeof(s2250_client_templ));
- client->adapter = adapter;
dec = kmalloc(sizeof(struct s2250), GFP_KERNEL);
if (dec == NULL) {
- kfree(client);
+ i2c_unregister_device(audio);
return -ENOMEM;
}
@@ -510,7 +501,7 @@ static int s2250_detect(struct i2c_adapter *adapter, int addr, int kind)
dec->contrast = 50;
dec->saturation = 50;
dec->hue = 0;
- client->addr = TLV320_ADDRESS;
+ dec->audio = audio;
i2c_set_clientdata(client, dec);
printk(KERN_DEBUG
@@ -518,28 +509,25 @@ static int s2250_detect(struct i2c_adapter *adapter, int addr, int kind)
adapter->name);
/* initialize the audio */
- client->addr = TLV320_ADDRESS;
- if (write_regs(client, aud_regs) < 0) {
+ if (write_regs(audio, aud_regs) < 0) {
printk(KERN_ERR
"s2250: error initializing audio\n");
- kfree(client);
+ i2c_unregister_device(audio);
kfree(dec);
return 0;
}
- client->addr = S2250_VIDDEC;
- i2c_set_clientdata(client, dec);
if (write_regs(client, vid_regs) < 0) {
printk(KERN_ERR
"s2250: error initializing decoder\n");
- kfree(client);
+ i2c_unregister_device(audio);
kfree(dec);
return 0;
}
if (write_regs_fp(client, vid_regs_fp) < 0) {
printk(KERN_ERR
"s2250: error initializing decoder\n");
- kfree(client);
+ i2c_unregister_device(audio);
kfree(dec);
return 0;
}
@@ -575,32 +563,33 @@ static int s2250_detect(struct i2c_adapter *adapter, int addr, int kind)
up(&usb->i2c_lock);
}
- i2c_attach_client(client);
printk("s2250: initialized successfully\n");
return 0;
}
-static int s2250_detach(struct i2c_client *client)
+static int s2250_remove(struct i2c_client *client)
{
struct s2250 *dec = i2c_get_clientdata(client);
- int r;
-
- r = i2c_detach_client(client);
- if (r < 0)
- return r;
- kfree(client);
+ i2c_set_clientdata(client, NULL);
+ i2c_unregister_device(dec->audio);
kfree(dec);
return 0;
}
+static struct i2c_device_id s2250_id[] = {
+ { "s2250_board", 0 },
+ { }
+};
+
static struct i2c_driver s2250_driver = {
.driver = {
.name = "Sensoray 2250 board driver",
},
- .id = I2C_DRIVERID_S2250,
- .detach_client = s2250_detach,
+ .probe = s2250_probe,
+ .remove = s2250_remove,
.command = s2250_command,
+ .id_table = s2250_id,
};
static int __init s2250_init(void)
@@ -613,13 +602,13 @@ static int __init s2250_init(void)
r = i2c_add_driver(&s2250_driver);
if (r < 0)
- return r;
- return wis_i2c_add_driver(s2250_driver.id, s2250_detect);
+ s2250loader_cleanup();
+
+ return r;
}
static void __exit s2250_cleanup(void)
{
- wis_i2c_del_driver(s2250_detect);
i2c_del_driver(&s2250_driver);
s2250loader_cleanup();
diff --git a/drivers/staging/go7007/wis-i2c.h b/drivers/staging/go7007/wis-i2c.h
index 431f41dd3966..3c2b9be455df 100644
--- a/drivers/staging/go7007/wis-i2c.h
+++ b/drivers/staging/go7007/wis-i2c.h
@@ -24,21 +24,12 @@
#define I2C_DRIVERID_WIS_OV7640 0xf0f5
#define I2C_DRIVERID_WIS_TW2804 0xf0f6
#define I2C_DRIVERID_S2250 0xf0f7
-#define I2C_ALGO_GO7007 0xf00000
-#define I2C_ALGO_GO7007_USB 0xf10000
/* Flag to indicate that the client needs to be accessed with SCCB semantics */
/* We re-use the I2C_M_TEN value so the flag passes through the masks in the
* core I2C code. Major kludge, but the I2C layer ain't exactly flexible. */
#define I2C_CLIENT_SCCB 0x10
-typedef int (*found_proc) (struct i2c_adapter *, int, int);
-int wis_i2c_add_driver(unsigned int id, found_proc found_proc);
-void wis_i2c_del_driver(found_proc found_proc);
-
-int wis_i2c_probe_device(struct i2c_adapter *adapter,
- unsigned int id, int addr);
-
/* Definitions for new video decoder commands */
struct video_decoder_resolution {
diff --git a/drivers/staging/go7007/wis-ov7640.c b/drivers/staging/go7007/wis-ov7640.c
index 2f9efca04606..04d6d3a498a3 100644
--- a/drivers/staging/go7007/wis-ov7640.c
+++ b/drivers/staging/go7007/wis-ov7640.c
@@ -50,76 +50,54 @@ static int write_regs(struct i2c_client *client, u8 *regs)
return 0;
}
-static struct i2c_driver wis_ov7640_driver;
-
-static struct i2c_client wis_ov7640_client_templ = {
- .name = "OV7640 (WIS)",
- .driver = &wis_ov7640_driver,
-};
-
-static int wis_ov7640_detect(struct i2c_adapter *adapter, int addr, int kind)
+static int wis_ov7640_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct i2c_client *client;
+ struct i2c_adapter *adapter = client->adapter;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return 0;
-
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == NULL)
- return -ENOMEM;
- memcpy(client, &wis_ov7640_client_templ,
- sizeof(wis_ov7640_client_templ));
- client->adapter = adapter;
- client->addr = addr;
+ return -ENODEV;
+
client->flags = I2C_CLIENT_SCCB;
printk(KERN_DEBUG
"wis-ov7640: initializing OV7640 at address %d on %s\n",
- addr, adapter->name);
+ client->addr, adapter->name);
if (write_regs(client, initial_registers) < 0) {
printk(KERN_ERR "wis-ov7640: error initializing OV7640\n");
- kfree(client);
- return 0;
+ return -ENODEV;
}
- i2c_attach_client(client);
return 0;
}
-static int wis_ov7640_detach(struct i2c_client *client)
+static int wis_ov7640_remove(struct i2c_client *client)
{
- int r;
-
- r = i2c_detach_client(client);
- if (r < 0)
- return r;
-
- kfree(client);
return 0;
}
+static struct i2c_device_id wis_ov7640_id[] = {
+ { "wis_ov7640", 0 },
+ { }
+};
+
static struct i2c_driver wis_ov7640_driver = {
.driver = {
.name = "WIS OV7640 I2C driver",
},
- .id = I2C_DRIVERID_WIS_OV7640,
- .detach_client = wis_ov7640_detach,
+ .probe = wis_ov7640_probe,
+ .remove = wis_ov7640_remove,
+ .id_table = wis_ov7640_id,
};
static int __init wis_ov7640_init(void)
{
- int r;
-
- r = i2c_add_driver(&wis_ov7640_driver);
- if (r < 0)
- return r;
- return wis_i2c_add_driver(wis_ov7640_driver.id, wis_ov7640_detect);
+ return i2c_add_driver(&wis_ov7640_driver);
}
static void __exit wis_ov7640_cleanup(void)
{
- wis_i2c_del_driver(wis_ov7640_detect);
i2c_del_driver(&wis_ov7640_driver);
}
diff --git a/drivers/staging/go7007/wis-saa7113.c b/drivers/staging/go7007/wis-saa7113.c
index 11689723945e..9ab893bd204e 100644
--- a/drivers/staging/go7007/wis-saa7113.c
+++ b/drivers/staging/go7007/wis-saa7113.c
@@ -261,34 +261,19 @@ static int wis_saa7113_command(struct i2c_client *client,
return 0;
}
-static struct i2c_driver wis_saa7113_driver;
-
-static struct i2c_client wis_saa7113_client_templ = {
- .name = "SAA7113 (WIS)",
- .driver = &wis_saa7113_driver,
-};
-
-static int wis_saa7113_detect(struct i2c_adapter *adapter, int addr, int kind)
+static int wis_saa7113_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct i2c_client *client;
+ struct i2c_adapter *adapter = client->adapter;
struct wis_saa7113 *dec;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return 0;
-
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == NULL)
- return -ENOMEM;
- memcpy(client, &wis_saa7113_client_templ,
- sizeof(wis_saa7113_client_templ));
- client->adapter = adapter;
- client->addr = addr;
+ return -ENODEV;
dec = kmalloc(sizeof(struct wis_saa7113), GFP_KERNEL);
- if (dec == NULL) {
- kfree(client);
+ if (dec == NULL)
return -ENOMEM;
- }
+
dec->norm = V4L2_STD_NTSC;
dec->brightness = 128;
dec->contrast = 71;
@@ -298,56 +283,49 @@ static int wis_saa7113_detect(struct i2c_adapter *adapter, int addr, int kind)
printk(KERN_DEBUG
"wis-saa7113: initializing SAA7113 at address %d on %s\n",
- addr, adapter->name);
+ client->addr, adapter->name);
if (write_regs(client, initial_registers) < 0) {
printk(KERN_ERR
"wis-saa7113: error initializing SAA7113\n");
- kfree(client);
kfree(dec);
- return 0;
+ return -ENODEV;
}
- i2c_attach_client(client);
return 0;
}
-static int wis_saa7113_detach(struct i2c_client *client)
+static int wis_saa7113_remove(struct i2c_client *client)
{
struct wis_saa7113 *dec = i2c_get_clientdata(client);
- int r;
-
- r = i2c_detach_client(client);
- if (r < 0)
- return r;
- kfree(client);
+ i2c_set_clientdata(client, NULL);
kfree(dec);
return 0;
}
+static struct i2c_device_id wis_saa7113_id[] = {
+ { "wis_saa7113", 0 },
+ { }
+};
+
static struct i2c_driver wis_saa7113_driver = {
.driver = {
.name = "WIS SAA7113 I2C driver",
},
- .id = I2C_DRIVERID_WIS_SAA7113,
- .detach_client = wis_saa7113_detach,
+ .probe = wis_saa7113_probe,
+ .remove = wis_saa7113_remove,
.command = wis_saa7113_command,
+ .id_table = wis_saa7113_id,
};
static int __init wis_saa7113_init(void)
{
- int r;
-
- r = i2c_add_driver(&wis_saa7113_driver);
- if (r < 0)
- return r;
- return wis_i2c_add_driver(wis_saa7113_driver.id, wis_saa7113_detect);
+ return i2c_add_driver(&wis_saa7113_driver);
}
static void __exit wis_saa7113_cleanup(void)
{
- wis_i2c_del_driver(wis_saa7113_detect);
i2c_del_driver(&wis_saa7113_driver);
}
diff --git a/drivers/staging/go7007/wis-saa7115.c b/drivers/staging/go7007/wis-saa7115.c
index 59417a7174d7..8687ad2de761 100644
--- a/drivers/staging/go7007/wis-saa7115.c
+++ b/drivers/staging/go7007/wis-saa7115.c
@@ -394,34 +394,19 @@ static int wis_saa7115_command(struct i2c_client *client,
return 0;
}
-static struct i2c_driver wis_saa7115_driver;
-
-static struct i2c_client wis_saa7115_client_templ = {
- .name = "SAA7115 (WIS)",
- .driver = &wis_saa7115_driver,
-};
-
-static int wis_saa7115_detect(struct i2c_adapter *adapter, int addr, int kind)
+static int wis_saa7115_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct i2c_client *client;
+ struct i2c_adapter *adapter = client->adapter;
struct wis_saa7115 *dec;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return 0;
-
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == NULL)
- return -ENOMEM;
- memcpy(client, &wis_saa7115_client_templ,
- sizeof(wis_saa7115_client_templ));
- client->adapter = adapter;
- client->addr = addr;
+ return -ENODEV;
dec = kmalloc(sizeof(struct wis_saa7115), GFP_KERNEL);
- if (dec == NULL) {
- kfree(client);
+ if (dec == NULL)
return -ENOMEM;
- }
+
dec->norm = V4L2_STD_NTSC;
dec->brightness = 128;
dec->contrast = 64;
@@ -431,56 +416,49 @@ static int wis_saa7115_detect(struct i2c_adapter *adapter, int addr, int kind)
printk(KERN_DEBUG
"wis-saa7115: initializing SAA7115 at address %d on %s\n",
- addr, adapter->name);
+ client->addr, adapter->name);
if (write_regs(client, initial_registers) < 0) {
printk(KERN_ERR
"wis-saa7115: error initializing SAA7115\n");
- kfree(client);
kfree(dec);
- return 0;
+ return -ENODEV;
}
- i2c_attach_client(client);
return 0;
}
-static int wis_saa7115_detach(struct i2c_client *client)
+static int wis_saa7115_remove(struct i2c_client *client)
{
struct wis_saa7115 *dec = i2c_get_clientdata(client);
- int r;
-
- r = i2c_detach_client(client);
- if (r < 0)
- return r;
- kfree(client);
+ i2c_set_clientdata(client, NULL);
kfree(dec);
return 0;
}
+static struct i2c_device_id wis_saa7115_id[] = {
+ { "wis_saa7115", 0 },
+ { }
+};
+
static struct i2c_driver wis_saa7115_driver = {
.driver = {
.name = "WIS SAA7115 I2C driver",
},
- .id = I2C_DRIVERID_WIS_SAA7115,
- .detach_client = wis_saa7115_detach,
+ .probe = wis_saa7115_probe,
+ .remove = wis_saa7115_remove,
.command = wis_saa7115_command,
+ .id_table = wis_saa7115_id,
};
static int __init wis_saa7115_init(void)
{
- int r;
-
- r = i2c_add_driver(&wis_saa7115_driver);
- if (r < 0)
- return r;
- return wis_i2c_add_driver(wis_saa7115_driver.id, wis_saa7115_detect);
+ return i2c_add_driver(&wis_saa7115_driver);
}
static void __exit wis_saa7115_cleanup(void)
{
- wis_i2c_del_driver(wis_saa7115_detect);
i2c_del_driver(&wis_saa7115_driver);
}
diff --git a/drivers/staging/go7007/wis-sony-tuner.c b/drivers/staging/go7007/wis-sony-tuner.c
index 58fddb122372..c965c601ac90 100644
--- a/drivers/staging/go7007/wis-sony-tuner.c
+++ b/drivers/staging/go7007/wis-sony-tuner.c
@@ -386,6 +386,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
struct wis_sony_tuner *t = i2c_get_clientdata(client);
switch (cmd) {
+#if 0
#ifdef TUNER_SET_TYPE_ADDR
case TUNER_SET_TYPE_ADDR:
{
@@ -463,6 +464,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
t->type, sony_tuners[t->type - 200].name);
break;
}
+#endif
case VIDIOC_G_FREQUENCY:
{
struct v4l2_frequency *f = arg;
@@ -651,35 +653,19 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
}
-static struct i2c_driver wis_sony_tuner_driver;
-
-static struct i2c_client wis_sony_tuner_client_templ = {
- .name = "Sony TV Tuner (WIS)",
- .driver = &wis_sony_tuner_driver,
-};
-
-static int wis_sony_tuner_detect(struct i2c_adapter *adapter,
- int addr, int kind)
+static int wis_sony_tuner_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct i2c_client *client;
+ struct i2c_adapter *adapter = client->adapter;
struct wis_sony_tuner *t;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
- return 0;
-
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == NULL)
- return -ENOMEM;
- memcpy(client, &wis_sony_tuner_client_templ,
- sizeof(wis_sony_tuner_client_templ));
- client->adapter = adapter;
- client->addr = addr;
+ return -ENODEV;
t = kmalloc(sizeof(struct wis_sony_tuner), GFP_KERNEL);
- if (t == NULL) {
- kfree(client);
+ if (t == NULL)
return -ENOMEM;
- }
+
t->type = -1;
t->freq = 0;
t->mpxmode = 0;
@@ -688,50 +674,42 @@ static int wis_sony_tuner_detect(struct i2c_adapter *adapter,
printk(KERN_DEBUG
"wis-sony-tuner: initializing tuner at address %d on %s\n",
- addr, adapter->name);
-
- i2c_attach_client(client);
+ client->addr, adapter->name);
return 0;
}
-static int wis_sony_tuner_detach(struct i2c_client *client)
+static int wis_sony_tuner_remove(struct i2c_client *client)
{
struct wis_sony_tuner *t = i2c_get_clientdata(client);
- int r;
-
- r = i2c_detach_client(client);
- if (r < 0)
- return r;
+ i2c_set_clientdata(client, NULL);
kfree(t);
- kfree(client);
return 0;
}
+static struct i2c_device_id wis_sony_tuner_id[] = {
+ { "wis_sony_tuner", 0 },
+ { }
+};
+
static struct i2c_driver wis_sony_tuner_driver = {
.driver = {
.name = "WIS Sony TV Tuner I2C driver",
},
- .id = I2C_DRIVERID_WIS_SONY_TUNER,
- .detach_client = wis_sony_tuner_detach,
+ .probe = wis_sony_tuner_probe,
+ .remove = wis_sony_tuner_remove,
.command = tuner_command,
+ .id_table = wis_sony_tuner_id,
};
static int __init wis_sony_tuner_init(void)
{
- int r;
-
- r = i2c_add_driver(&wis_sony_tuner_driver);
- if (r < 0)
- return r;
- return wis_i2c_add_driver(wis_sony_tuner_driver.id,
- wis_sony_tuner_detect);
+ return i2c_add_driver(&wis_sony_tuner_driver);
}
static void __exit wis_sony_tuner_cleanup(void)
{
- wis_i2c_del_driver(wis_sony_tuner_detect);
i2c_del_driver(&wis_sony_tuner_driver);
}
diff --git a/drivers/staging/go7007/wis-tw2804.c b/drivers/staging/go7007/wis-tw2804.c
index 57b8f2b1caa3..e15794a2a0ae 100644
--- a/drivers/staging/go7007/wis-tw2804.c
+++ b/drivers/staging/go7007/wis-tw2804.c
@@ -291,34 +291,19 @@ static int wis_tw2804_command(struct i2c_client *client,
return 0;
}
-static struct i2c_driver wis_tw2804_driver;
-
-static struct i2c_client wis_tw2804_client_templ = {
- .name = "TW2804 (WIS)",
- .driver = &wis_tw2804_driver,
-};
-
-static int wis_tw2804_detect(struct i2c_adapter *adapter, int addr, int kind)
+static int wis_tw2804_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct i2c_client *client;
+ struct i2c_adapter *adapter = client->adapter;
struct wis_tw2804 *dec;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return 0;
-
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == NULL)
- return -ENOMEM;
- memcpy(client, &wis_tw2804_client_templ,
- sizeof(wis_tw2804_client_templ));
- client->adapter = adapter;
- client->addr = addr;
+ return -ENODEV;
dec = kmalloc(sizeof(struct wis_tw2804), GFP_KERNEL);
- if (dec == NULL) {
- kfree(client);
+ if (dec == NULL)
return -ENOMEM;
- }
+
dec->channel = -1;
dec->norm = V4L2_STD_NTSC;
dec->brightness = 128;
@@ -328,48 +313,42 @@ static int wis_tw2804_detect(struct i2c_adapter *adapter, int addr, int kind)
i2c_set_clientdata(client, dec);
printk(KERN_DEBUG "wis-tw2804: creating TW2804 at address %d on %s\n",
- addr, adapter->name);
+ client->addr, adapter->name);
- i2c_attach_client(client);
return 0;
}
-static int wis_tw2804_detach(struct i2c_client *client)
+static int wis_tw2804_remove(struct i2c_client *client)
{
struct wis_tw2804 *dec = i2c_get_clientdata(client);
- int r;
-
- r = i2c_detach_client(client);
- if (r < 0)
- return r;
- kfree(client);
+ i2c_set_clientdata(client, NULL);
kfree(dec);
return 0;
}
+static struct i2c_device_id wis_tw2804_id[] = {
+ { "wis_tw2804", 0 },
+ { }
+};
+
static struct i2c_driver wis_tw2804_driver = {
.driver = {
.name = "WIS TW2804 I2C driver",
},
- .id = I2C_DRIVERID_WIS_TW2804,
- .detach_client = wis_tw2804_detach,
+ .probe = wis_tw2804_probe,
+ .remove = wis_tw2804_remove,
.command = wis_tw2804_command,
+ .id_table = wis_tw2804_id,
};
static int __init wis_tw2804_init(void)
{
- int r;
-
- r = i2c_add_driver(&wis_tw2804_driver);
- if (r < 0)
- return r;
- return wis_i2c_add_driver(wis_tw2804_driver.id, wis_tw2804_detect);
+ return i2c_add_driver(&wis_tw2804_driver);
}
static void __exit wis_tw2804_cleanup(void)
{
- wis_i2c_del_driver(wis_tw2804_detect);
i2c_del_driver(&wis_tw2804_driver);
}
diff --git a/drivers/staging/go7007/wis-tw9903.c b/drivers/staging/go7007/wis-tw9903.c
index 40627b282cb4..6c3427bb6f4c 100644
--- a/drivers/staging/go7007/wis-tw9903.c
+++ b/drivers/staging/go7007/wis-tw9903.c
@@ -267,34 +267,19 @@ static int wis_tw9903_command(struct i2c_client *client,
return 0;
}
-static struct i2c_driver wis_tw9903_driver;
-
-static struct i2c_client wis_tw9903_client_templ = {
- .name = "TW9903 (WIS)",
- .driver = &wis_tw9903_driver,
-};
-
-static int wis_tw9903_detect(struct i2c_adapter *adapter, int addr, int kind)
+static int wis_tw9903_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct i2c_client *client;
+ struct i2c_adapter *adapter = client->adapter;
struct wis_tw9903 *dec;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return 0;
-
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == NULL)
- return -ENOMEM;
- memcpy(client, &wis_tw9903_client_templ,
- sizeof(wis_tw9903_client_templ));
- client->adapter = adapter;
- client->addr = addr;
+ return -ENODEV;
dec = kmalloc(sizeof(struct wis_tw9903), GFP_KERNEL);
- if (dec == NULL) {
- kfree(client);
+ if (dec == NULL)
return -ENOMEM;
- }
+
dec->norm = V4L2_STD_NTSC;
dec->brightness = 0;
dec->contrast = 0x60;
@@ -303,55 +288,48 @@ static int wis_tw9903_detect(struct i2c_adapter *adapter, int addr, int kind)
printk(KERN_DEBUG
"wis-tw9903: initializing TW9903 at address %d on %s\n",
- addr, adapter->name);
+ client->addr, adapter->name);
if (write_regs(client, initial_registers) < 0) {
printk(KERN_ERR "wis-tw9903: error initializing TW9903\n");
- kfree(client);
kfree(dec);
- return 0;
+ return -ENODEV;
}
- i2c_attach_client(client);
return 0;
}
-static int wis_tw9903_detach(struct i2c_client *client)
+static int wis_tw9903_remove(struct i2c_client *client)
{
struct wis_tw9903 *dec = i2c_get_clientdata(client);
- int r;
-
- r = i2c_detach_client(client);
- if (r < 0)
- return r;
- kfree(client);
+ i2c_set_clientdata(client, NULL);
kfree(dec);
return 0;
}
+static struct i2c_device_id wis_tw9903_id[] = {
+ { "wis_tw9903", 0 },
+ { }
+};
+
static struct i2c_driver wis_tw9903_driver = {
.driver = {
.name = "WIS TW9903 I2C driver",
},
- .id = I2C_DRIVERID_WIS_TW9903,
- .detach_client = wis_tw9903_detach,
+ .probe = wis_tw9903_probe,
+ .remove = wis_tw9903_remove,
.command = wis_tw9903_command,
+ .id_table = wis_tw9903_id,
};
static int __init wis_tw9903_init(void)
{
- int r;
-
- r = i2c_add_driver(&wis_tw9903_driver);
- if (r < 0)
- return r;
- return wis_i2c_add_driver(wis_tw9903_driver.id, wis_tw9903_detect);
+ return i2c_add_driver(&wis_tw9903_driver);
}
static void __exit wis_tw9903_cleanup(void)
{
- wis_i2c_del_driver(wis_tw9903_detect);
i2c_del_driver(&wis_tw9903_driver);
}
diff --git a/drivers/staging/go7007/wis-uda1342.c b/drivers/staging/go7007/wis-uda1342.c
index 555645c0cc1a..739c7ae8913f 100644
--- a/drivers/staging/go7007/wis-uda1342.c
+++ b/drivers/staging/go7007/wis-uda1342.c
@@ -59,73 +59,51 @@ static int wis_uda1342_command(struct i2c_client *client,
return 0;
}
-static struct i2c_driver wis_uda1342_driver;
-
-static struct i2c_client wis_uda1342_client_templ = {
- .name = "UDA1342 (WIS)",
- .driver = &wis_uda1342_driver,
-};
-
-static int wis_uda1342_detect(struct i2c_adapter *adapter, int addr, int kind)
+static int wis_uda1342_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct i2c_client *client;
+ struct i2c_adapter *adapter = client->adapter;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
- return 0;
-
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == NULL)
- return -ENOMEM;
- memcpy(client, &wis_uda1342_client_templ,
- sizeof(wis_uda1342_client_templ));
- client->adapter = adapter;
- client->addr = addr;
+ return -ENODEV;
printk(KERN_DEBUG
"wis-uda1342: initializing UDA1342 at address %d on %s\n",
- addr, adapter->name);
+ client->addr, adapter->name);
write_reg(client, 0x00, 0x8000); /* reset registers */
write_reg(client, 0x00, 0x1241); /* select input 1 */
- i2c_attach_client(client);
return 0;
}
-static int wis_uda1342_detach(struct i2c_client *client)
+static int wis_uda1342_remove(struct i2c_client *client)
{
- int r;
-
- r = i2c_detach_client(client);
- if (r < 0)
- return r;
-
- kfree(client);
return 0;
}
+static struct i2c_device_id wis_uda1342_id[] = {
+ { "wis_uda1342", 0 },
+ { }
+};
+
static struct i2c_driver wis_uda1342_driver = {
.driver = {
.name = "WIS UDA1342 I2C driver",
},
- .id = I2C_DRIVERID_WIS_UDA1342,
- .detach_client = wis_uda1342_detach,
+ .probe = wis_uda1342_probe,
+ .remove = wis_uda1342_remove,
.command = wis_uda1342_command,
+ .id_table = wis_uda1342_id,
};
static int __init wis_uda1342_init(void)
{
- int r;
-
- r = i2c_add_driver(&wis_uda1342_driver);
- if (r < 0)
- return r;
- return wis_i2c_add_driver(wis_uda1342_driver.id, wis_uda1342_detect);
+ return i2c_add_driver(&wis_uda1342_driver);
}
static void __exit wis_uda1342_cleanup(void)
{
- wis_i2c_del_driver(wis_uda1342_detect);
i2c_del_driver(&wis_uda1342_driver);
}
diff --git a/drivers/staging/line6/audio.c b/drivers/staging/line6/audio.c
index 3aa946899ced..e2ac8d60f8c2 100644
--- a/drivers/staging/line6/audio.c
+++ b/drivers/staging/line6/audio.c
@@ -27,11 +27,12 @@ int line6_init_audio(struct usb_line6 *line6)
{
static int dev;
struct snd_card *card;
+ int err;
- card = snd_card_new(line6_index[dev], line6_id[dev], THIS_MODULE, 0);
-
- if (card == NULL)
- return -ENOMEM;
+ err = snd_card_create(line6_index[dev], line6_id[dev], THIS_MODULE, 0,
+ &card);
+ if (err < 0)
+ return err;
line6->card = card;
diff --git a/drivers/staging/otus/usbdrv.c b/drivers/staging/otus/usbdrv.c
index 565a839589f5..540cbbb826f9 100644
--- a/drivers/staging/otus/usbdrv.c
+++ b/drivers/staging/otus/usbdrv.c
@@ -822,6 +822,21 @@ int zfLnxVapXmitFrame(struct sk_buff *skb, struct net_device *dev)
return 0;
}
+static const struct net_device_ops vap_netdev_ops = {
+ .ndo_open = zfLnxVapOpen,
+ .ndo_stop = zfLnxVapClose,
+ .ndo_start_xmit = zfLnxVapXmitFrame,
+ .ndo_get_stats = usbdrv_get_stats,
+ .ndo_change_mtu = usbdrv_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
+#ifdef ZM_HOSTAPD_SUPPORT
+ .ndo_do_ioctl = usbdrv_ioctl,
+#else
+ .ndo_do_ioctl = NULL,
+#endif
+};
+
int zfLnxRegisterVapDev(struct net_device* parentDev, u16_t vapId)
{
/* Allocate net device structure */
@@ -846,16 +861,7 @@ int zfLnxRegisterVapDev(struct net_device* parentDev, u16_t vapId)
vap[vapId].dev->ml_priv = parentDev->ml_priv;
//dev->hard_start_xmit = &zd1212_wds_xmit_frame;
- vap[vapId].dev->hard_start_xmit = &zfLnxVapXmitFrame;
- vap[vapId].dev->open = &zfLnxVapOpen;
- vap[vapId].dev->stop = &zfLnxVapClose;
- vap[vapId].dev->get_stats = &usbdrv_get_stats;
- vap[vapId].dev->change_mtu = &usbdrv_change_mtu;
-#ifdef ZM_HOSTAPD_SUPPORT
- vap[vapId].dev->do_ioctl = usbdrv_ioctl;
-#else
- vap[vapId].dev->do_ioctl = NULL;
-#endif
+ vap[vapId].dev->netdev_ops = &vap_netdev_ops;
vap[vapId].dev->destructor = free_netdev;
vap[vapId].dev->tx_queue_len = 0;
@@ -1068,6 +1074,18 @@ void zfLnxUnlinkAllUrbs(struct usbdrv_private *macp)
usb_unlink_urb(macp->RegInUrb);
}
+static const struct net_device_ops otus_netdev_ops = {
+ .ndo_open = usbdrv_open,
+ .ndo_stop = usbdrv_close,
+ .ndo_start_xmit = usbdrv_xmit_frame,
+ .ndo_change_mtu = usbdrv_change_mtu,
+ .ndo_get_stats = usbdrv_get_stats,
+ .ndo_set_multicast_list = usbdrv_set_multi,
+ .ndo_set_mac_address = usbdrv_set_mac,
+ .ndo_do_ioctl = usbdrv_ioctl,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
u8_t zfLnxInitSetup(struct net_device *dev, struct usbdrv_private *macp)
{
//unsigned char addr[6];
@@ -1092,14 +1110,7 @@ u8_t zfLnxInitSetup(struct net_device *dev, struct usbdrv_private *macp)
dev->wireless_handlers = (struct iw_handler_def *)&p80211wext_handler_def;
#endif
- dev->open = usbdrv_open;
- dev->hard_start_xmit = usbdrv_xmit_frame;
- dev->stop = usbdrv_close;
- dev->change_mtu = &usbdrv_change_mtu;
- dev->get_stats = usbdrv_get_stats;
- dev->set_multicast_list = usbdrv_set_multi;
- dev->set_mac_address = usbdrv_set_mac;
- dev->do_ioctl = usbdrv_ioctl;
+ dev->netdev_ops = &otus_netdev_ops;
dev->flags |= IFF_MULTICAST;
diff --git a/drivers/staging/otus/zdusb.c b/drivers/staging/otus/zdusb.c
index 78f1d2224fa1..2a6d937ba5e8 100644
--- a/drivers/staging/otus/zdusb.c
+++ b/drivers/staging/otus/zdusb.c
@@ -48,7 +48,8 @@ static const char driver_name[] = "Otus";
static struct usb_device_id zd1221_ids [] = {
{ USB_DEVICE(VENDOR_ATHR, PRODUCT_AR9170) },
{ USB_DEVICE(VENDOR_DLINK, PRODUCT_DWA160A) },
- { USB_DEVICE(0x0846, 0x9010) },
+ { USB_DEVICE(VENDOR_NETGEAR, PRODUCT_WNDA3100) },
+ { USB_DEVICE(VENDOR_NETGEAR, PRODUCT_WN111v2) },
{ } /* Terminating entry */
};
diff --git a/drivers/staging/otus/zdusb.h b/drivers/staging/otus/zdusb.h
index 656dc212ade5..9f8ab2e96169 100644
--- a/drivers/staging/otus/zdusb.h
+++ b/drivers/staging/otus/zdusb.h
@@ -40,4 +40,8 @@
#define VENDOR_DLINK 0x07D1 //Dlink
#define PRODUCT_DWA160A 0x3C10
+#define VENDOR_NETGEAR 0x0846 /* NetGear */
+#define PRODUCT_WNDA3100 0x9010
+#define PRODUCT_WN111v2 0x9001
+
#endif
diff --git a/drivers/staging/panel/lcd-panel-cgram.txt b/drivers/staging/panel/lcd-panel-cgram.txt
index f9ceef4322a3..7f82c905763d 100644
--- a/drivers/staging/panel/lcd-panel-cgram.txt
+++ b/drivers/staging/panel/lcd-panel-cgram.txt
@@ -3,7 +3,7 @@ characters 0 to 7. The escape code to define a new character is
'\e[LG' followed by one digit from 0 to 7, representing the character
number, and up to 8 couples of hex digits terminated by a semi-colon
(';'). Each couple of digits represents a line, with 1-bits for each
-illuminated pixel with LSB on the right. Lines are numberred from the
+illuminated pixel with LSB on the right. Lines are numbered from the
top of the character to the bottom. On a 5x7 matrix, only the 5 lower
bits of the 7 first bytes are used for each character. If the string
is incomplete, only complete lines will be redefined. Here are some
diff --git a/drivers/staging/pohmelfs/config.c b/drivers/staging/pohmelfs/config.c
index 3e67da9ea381..a6eaa42fb669 100644
--- a/drivers/staging/pohmelfs/config.c
+++ b/drivers/staging/pohmelfs/config.c
@@ -81,6 +81,45 @@ static struct pohmelfs_config_group *pohmelfs_find_create_config_group(unsigned
return g;
}
+static inline void pohmelfs_insert_config_entry(struct pohmelfs_sb *psb, struct pohmelfs_config *dst)
+{
+ struct pohmelfs_config *tmp;
+
+ INIT_LIST_HEAD(&dst->config_entry);
+
+ list_for_each_entry(tmp, &psb->state_list, config_entry) {
+ if (dst->state.ctl.prio > tmp->state.ctl.prio)
+ list_add_tail(&dst->config_entry, &tmp->config_entry);
+ }
+ if (list_empty(&dst->config_entry))
+ list_add_tail(&dst->config_entry, &psb->state_list);
+}
+
+static int pohmelfs_move_config_entry(struct pohmelfs_sb *psb,
+ struct pohmelfs_config *dst, struct pohmelfs_config *new)
+{
+ if ((dst->state.ctl.prio == new->state.ctl.prio) &&
+ (dst->state.ctl.perm == new->state.ctl.perm))
+ return 0;
+
+ dprintk("%s: dst: prio: %d, perm: %x, new: prio: %d, perm: %d.\n",
+ __func__, dst->state.ctl.prio, dst->state.ctl.perm,
+ new->state.ctl.prio, new->state.ctl.perm);
+ dst->state.ctl.prio = new->state.ctl.prio;
+ dst->state.ctl.perm = new->state.ctl.perm;
+
+ list_del_init(&dst->config_entry);
+ pohmelfs_insert_config_entry(psb, dst);
+ return 0;
+}
+
+/*
+ * pohmelfs_copy_config() is used to copy new state configs from the
+ * config group (controlled by the netlink messages) into the superblock.
+ * This happens either at startup time where no transactions can access
+ * the list of the configs (and thus list of the network states), or at
+ * run-time, where it is protected by the psb->state_lock.
+ */
int pohmelfs_copy_config(struct pohmelfs_sb *psb)
{
struct pohmelfs_config_group *g;
@@ -103,7 +142,9 @@ int pohmelfs_copy_config(struct pohmelfs_sb *psb)
err = 0;
list_for_each_entry(dst, &psb->state_list, config_entry) {
if (pohmelfs_config_eql(&dst->state.ctl, &c->state.ctl)) {
- err = -EEXIST;
+ err = pohmelfs_move_config_entry(psb, dst, c);
+ if (!err)
+ err = -EEXIST;
break;
}
}
@@ -119,7 +160,7 @@ int pohmelfs_copy_config(struct pohmelfs_sb *psb)
memcpy(&dst->state.ctl, &c->state.ctl, sizeof(struct pohmelfs_ctl));
- list_add_tail(&dst->config_entry, &psb->state_list);
+ pohmelfs_insert_config_entry(psb, dst);
err = pohmelfs_state_init_one(psb, dst);
if (err) {
@@ -248,6 +289,13 @@ out_unlock:
return err;
}
+static int pohmelfs_modify_config(struct pohmelfs_ctl *old, struct pohmelfs_ctl *new)
+{
+ old->perm = new->perm;
+ old->prio = new->prio;
+ return 0;
+}
+
static int pohmelfs_cn_ctl(struct cn_msg *msg, int action)
{
struct pohmelfs_config_group *g;
@@ -278,6 +326,9 @@ static int pohmelfs_cn_ctl(struct cn_msg *msg, int action)
g->num_entry--;
kfree(c);
goto out_unlock;
+ } else if (action == POHMELFS_FLAGS_MODIFY) {
+ err = pohmelfs_modify_config(sc, ctl);
+ goto out_unlock;
} else {
err = -EEXIST;
goto out_unlock;
@@ -296,6 +347,7 @@ static int pohmelfs_cn_ctl(struct cn_msg *msg, int action)
}
memcpy(&c->state.ctl, ctl, sizeof(struct pohmelfs_ctl));
g->num_entry++;
+
list_add_tail(&c->config_entry, &g->config_list);
out_unlock:
@@ -401,10 +453,9 @@ static void pohmelfs_cn_callback(void *data)
switch (msg->flags) {
case POHMELFS_FLAGS_ADD:
- err = pohmelfs_cn_ctl(msg, POHMELFS_FLAGS_ADD);
- break;
case POHMELFS_FLAGS_DEL:
- err = pohmelfs_cn_ctl(msg, POHMELFS_FLAGS_DEL);
+ case POHMELFS_FLAGS_MODIFY:
+ err = pohmelfs_cn_ctl(msg, msg->flags);
break;
case POHMELFS_FLAGS_SHOW:
err = pohmelfs_cn_disp(msg);
diff --git a/drivers/staging/pohmelfs/dir.c b/drivers/staging/pohmelfs/dir.c
index 7a41183a32e1..b5799842fb84 100644
--- a/drivers/staging/pohmelfs/dir.c
+++ b/drivers/staging/pohmelfs/dir.c
@@ -328,7 +328,7 @@ static int pohmelfs_sync_remote_dir(struct pohmelfs_inode *pi)
{
struct inode *inode = &pi->vfs_inode;
struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
- long ret = msecs_to_jiffies(25000);
+ long ret = psb->wait_on_page_timeout;
int err;
dprintk("%s: dir: %llu, state: %lx: remote_synced: %d.\n",
@@ -389,11 +389,11 @@ static int pohmelfs_readdir(struct file *file, void *dirent, filldir_t filldir)
dprintk("%s: parent: %llu, fpos: %llu, hash: %08lx.\n",
__func__, pi->ino, (u64)file->f_pos,
(unsigned long)file->private_data);
-
+#if 0
err = pohmelfs_data_lock(pi, 0, ~0, POHMELFS_READ_LOCK);
if (err)
return err;
-
+#endif
err = pohmelfs_sync_remote_dir(pi);
if (err)
return err;
@@ -513,10 +513,6 @@ struct dentry *pohmelfs_lookup(struct inode *dir, struct dentry *dentry, struct
need_lock = pohmelfs_need_lock(parent, lock_type);
- err = pohmelfs_data_lock(parent, 0, ~0, lock_type);
- if (err)
- goto out;
-
str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
mutex_lock(&parent->offset_lock);
@@ -525,8 +521,8 @@ struct dentry *pohmelfs_lookup(struct inode *dir, struct dentry *dentry, struct
ino = n->ino;
mutex_unlock(&parent->offset_lock);
- dprintk("%s: 1 ino: %lu, inode: %p, name: '%s', hash: %x, parent_state: %lx.\n",
- __func__, ino, inode, str.name, str.hash, parent->state);
+ dprintk("%s: start ino: %lu, inode: %p, name: '%s', hash: %x, parent_state: %lx, need_lock: %d.\n",
+ __func__, ino, inode, str.name, str.hash, parent->state, need_lock);
if (ino) {
inode = ilookup(dir->i_sb, ino);
@@ -534,7 +530,7 @@ struct dentry *pohmelfs_lookup(struct inode *dir, struct dentry *dentry, struct
goto out;
}
- dprintk("%s: dir: %p, dir_ino: %llu, name: '%s', len: %u, dir_state: %lx, ino: %lu.\n",
+ dprintk("%s: no inode dir: %p, dir_ino: %llu, name: '%s', len: %u, dir_state: %lx, ino: %lu.\n",
__func__, dir, parent->ino,
str.name, str.len, parent->state, ino);
@@ -543,6 +539,10 @@ struct dentry *pohmelfs_lookup(struct inode *dir, struct dentry *dentry, struct
goto out;
}
+ err = pohmelfs_data_lock(parent, 0, ~0, lock_type);
+ if (err)
+ goto out;
+
err = pohmelfs_lookup_single(parent, &str, ino);
if (err)
goto out;
@@ -557,10 +557,10 @@ struct dentry *pohmelfs_lookup(struct inode *dir, struct dentry *dentry, struct
if (ino) {
inode = ilookup(dir->i_sb, ino);
- printk("%s: second lookup ino: %lu, inode: %p, name: '%s', hash: %x.\n",
+ dprintk("%s: second lookup ino: %lu, inode: %p, name: '%s', hash: %x.\n",
__func__, ino, inode, str.name, str.hash);
if (!inode) {
- printk("%s: No inode for ino: %lu, name: '%s', hash: %x.\n",
+ dprintk("%s: No inode for ino: %lu, name: '%s', hash: %x.\n",
__func__, ino, str.name, str.hash);
//return NULL;
return ERR_PTR(-EACCES);
diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c
index 5bf16504cd6f..b2eaf9047266 100644
--- a/drivers/staging/pohmelfs/inode.c
+++ b/drivers/staging/pohmelfs/inode.c
@@ -1169,16 +1169,17 @@ err_out_put:
static int pohmelfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
{
struct inode *inode = dentry->d_inode;
+#if 0
struct pohmelfs_inode *pi = POHMELFS_I(inode);
int err;
err = pohmelfs_data_lock(pi, 0, ~0, POHMELFS_READ_LOCK);
if (err)
return err;
-
dprintk("%s: ino: %llu, mode: %o, uid: %u, gid: %u, size: %llu.\n",
__func__, pi->ino, inode->i_mode, inode->i_uid,
inode->i_gid, inode->i_size);
+#endif
generic_fillattr(inode, stat);
return 0;
@@ -1342,14 +1343,6 @@ static void pohmelfs_put_super(struct super_block *sb)
kfree(psb);
sb->s_fs_info = NULL;
-
- pohmelfs_ftrans_exit();
-}
-
-static int pohmelfs_remount(struct super_block *sb, int *flags, char *data)
-{
- *flags |= MS_RDONLY;
- return 0;
}
static int pohmelfs_statfs(struct dentry *dentry, struct kstatfs *buf)
@@ -1394,42 +1387,33 @@ static int pohmelfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
return 0;
}
-static const struct super_operations pohmelfs_sb_ops = {
- .alloc_inode = pohmelfs_alloc_inode,
- .destroy_inode = pohmelfs_destroy_inode,
- .drop_inode = pohmelfs_drop_inode,
- .write_inode = pohmelfs_write_inode,
- .put_super = pohmelfs_put_super,
- .remount_fs = pohmelfs_remount,
- .statfs = pohmelfs_statfs,
- .show_options = pohmelfs_show_options,
-};
-
enum {
pohmelfs_opt_idx,
+ pohmelfs_opt_crypto_thread_num,
+ pohmelfs_opt_trans_max_pages,
+ pohmelfs_opt_crypto_fail_unsupported,
+
+ /* Remountable options */
pohmelfs_opt_trans_scan_timeout,
pohmelfs_opt_drop_scan_timeout,
pohmelfs_opt_wait_on_page_timeout,
pohmelfs_opt_trans_retries,
- pohmelfs_opt_crypto_thread_num,
- pohmelfs_opt_trans_max_pages,
- pohmelfs_opt_crypto_fail_unsupported,
pohmelfs_opt_mcache_timeout,
};
static struct match_token pohmelfs_tokens[] = {
{pohmelfs_opt_idx, "idx=%u"},
+ {pohmelfs_opt_crypto_thread_num, "crypto_thread_num=%u"},
+ {pohmelfs_opt_trans_max_pages, "trans_max_pages=%u"},
+ {pohmelfs_opt_crypto_fail_unsupported, "crypto_fail_unsupported"},
{pohmelfs_opt_trans_scan_timeout, "trans_scan_timeout=%u"},
{pohmelfs_opt_drop_scan_timeout, "drop_scan_timeout=%u"},
{pohmelfs_opt_wait_on_page_timeout, "wait_on_page_timeout=%u"},
{pohmelfs_opt_trans_retries, "trans_retries=%u"},
- {pohmelfs_opt_crypto_thread_num, "crypto_thread_num=%u"},
- {pohmelfs_opt_trans_max_pages, "trans_max_pages=%u"},
- {pohmelfs_opt_crypto_fail_unsupported, "crypto_fail_unsupported"},
{pohmelfs_opt_mcache_timeout, "mcache_timeout=%u"},
};
-static int pohmelfs_parse_options(char *options, struct pohmelfs_sb *psb)
+static int pohmelfs_parse_options(char *options, struct pohmelfs_sb *psb, int remount)
{
char *p;
substring_t args[MAX_OPT_ARGS];
@@ -1449,6 +1433,9 @@ static int pohmelfs_parse_options(char *options, struct pohmelfs_sb *psb)
if (err)
return err;
+ if (remount && token <= pohmelfs_opt_crypto_fail_unsupported)
+ continue;
+
switch (token) {
case pohmelfs_opt_idx:
psb->idx = option;
@@ -1485,6 +1472,25 @@ static int pohmelfs_parse_options(char *options, struct pohmelfs_sb *psb)
return 0;
}
+static int pohmelfs_remount(struct super_block *sb, int *flags, char *data)
+{
+ int err;
+ struct pohmelfs_sb *psb = POHMELFS_SB(sb);
+ unsigned long old_sb_flags = sb->s_flags;
+
+ err = pohmelfs_parse_options(data, psb, 1);
+ if (err)
+ goto err_out_restore;
+
+ if (!(*flags & MS_RDONLY))
+ sb->s_flags &= ~MS_RDONLY;
+ return 0;
+
+err_out_restore:
+ sb->s_flags = old_sb_flags;
+ return err;
+}
+
static void pohmelfs_flush_inode(struct pohmelfs_inode *pi, unsigned int count)
{
struct inode *inode = &pi->vfs_inode;
@@ -1753,6 +1759,57 @@ err_out_exit:
return err;
}
+static int pohmelfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
+{
+ struct netfs_state *st;
+ struct pohmelfs_ctl *ctl;
+ struct pohmelfs_sb *psb = POHMELFS_SB(mnt->mnt_sb);
+ struct pohmelfs_config *c;
+
+ mutex_lock(&psb->state_lock);
+
+ seq_printf(m, "\nidx addr(:port) socket_type protocol active priority permissions\n");
+
+ list_for_each_entry(c, &psb->state_list, config_entry) {
+ st = &c->state;
+ ctl = &st->ctl;
+
+ seq_printf(m, "%u ", ctl->idx);
+ if (ctl->addr.sa_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *)&st->ctl.addr;
+ //seq_printf(m, "%pi4:%u", &sin->sin_addr.s_addr, ntohs(sin->sin_port));
+ seq_printf(m, "%u.%u.%u.%u:%u", NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port));
+ } else if (ctl->addr.sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&st->ctl.addr;
+ seq_printf(m, "%pi6:%u", &sin->sin6_addr, ntohs(sin->sin6_port));
+ } else {
+ unsigned int i;
+ for (i=0; i<ctl->addrlen; ++i)
+ seq_printf(m, "%02x.", ctl->addr.addr[i]);
+ }
+
+ seq_printf(m, " %u %u %d %u %x\n",
+ ctl->type, ctl->proto,
+ st->socket != NULL,
+ ctl->prio, ctl->perm);
+ }
+ mutex_unlock(&psb->state_lock);
+
+ return 0;
+}
+
+static const struct super_operations pohmelfs_sb_ops = {
+ .alloc_inode = pohmelfs_alloc_inode,
+ .destroy_inode = pohmelfs_destroy_inode,
+ .drop_inode = pohmelfs_drop_inode,
+ .write_inode = pohmelfs_write_inode,
+ .put_super = pohmelfs_put_super,
+ .remount_fs = pohmelfs_remount,
+ .statfs = pohmelfs_statfs,
+ .show_options = pohmelfs_show_options,
+ .show_stats = pohmelfs_show_stats,
+};
+
/*
* Allocate private superblock and create root dir.
*/
@@ -1764,8 +1821,6 @@ static int pohmelfs_fill_super(struct super_block *sb, void *data, int silent)
struct pohmelfs_inode *npi;
struct qstr str;
- pohmelfs_ftrans_init();
-
psb = kzalloc(sizeof(struct pohmelfs_sb), GFP_KERNEL);
if (!psb)
goto err_out_exit;
@@ -1816,7 +1871,7 @@ static int pohmelfs_fill_super(struct super_block *sb, void *data, int silent)
mutex_init(&psb->state_lock);
INIT_LIST_HEAD(&psb->state_list);
- err = pohmelfs_parse_options((char *) data, psb);
+ err = pohmelfs_parse_options((char *) data, psb, 0);
if (err)
goto err_out_free_sb;
@@ -1845,6 +1900,8 @@ static int pohmelfs_fill_super(struct super_block *sb, void *data, int silent)
err = PTR_ERR(npi);
goto err_out_crypto_exit;
}
+ set_bit(NETFS_INODE_REMOTE_SYNCED, &npi->state);
+ clear_bit(NETFS_INODE_OWNED, &npi->state);
root = &npi->vfs_inode;
@@ -1887,11 +1944,29 @@ static int pohmelfs_get_sb(struct file_system_type *fs_type,
mnt);
}
+/*
+ * We need this to sync all inodes earlier, since when writeback
+ * is invoked from the umount/mntput path dcache is already shrunk,
+ * see generic_shutdown_super(), and no inodes can access the path.
+ */
+static void pohmelfs_kill_super(struct super_block *sb)
+{
+ struct writeback_control wbc = {
+ .sync_mode = WB_SYNC_ALL,
+ .range_start = 0,
+ .range_end = LLONG_MAX,
+ .nr_to_write = LONG_MAX,
+ };
+ generic_sync_sb_inodes(sb, &wbc);
+
+ kill_anon_super(sb);
+}
+
static struct file_system_type pohmel_fs_type = {
.owner = THIS_MODULE,
.name = "pohmel",
.get_sb = pohmelfs_get_sb,
- .kill_sb = kill_anon_super,
+ .kill_sb = pohmelfs_kill_super,
};
/*
diff --git a/drivers/staging/pohmelfs/lock.c b/drivers/staging/pohmelfs/lock.c
index ad4a18559bdd..22fef18cae90 100644
--- a/drivers/staging/pohmelfs/lock.c
+++ b/drivers/staging/pohmelfs/lock.c
@@ -41,7 +41,8 @@ static int pohmelfs_send_lock_trans(struct pohmelfs_inode *pi,
path_len = err;
err = -ENOMEM;
- t = netfs_trans_alloc(psb, path_len + sizeof(struct netfs_lock) + isize, 0, 0);
+ t = netfs_trans_alloc(psb, path_len + sizeof(struct netfs_lock) + isize,
+ NETFS_TRANS_SINGLE_DST, 0);
if (!t)
goto err_out_exit;
diff --git a/drivers/staging/pohmelfs/net.c b/drivers/staging/pohmelfs/net.c
index c9b8540c1efe..11ecac026ca7 100644
--- a/drivers/staging/pohmelfs/net.c
+++ b/drivers/staging/pohmelfs/net.c
@@ -26,55 +26,6 @@
#include "netfs.h"
-static int pohmelfs_ftrans_size = 10240;
-static u32 *pohmelfs_ftrans;
-
-int pohmelfs_ftrans_init(void)
-{
- pohmelfs_ftrans = vmalloc(pohmelfs_ftrans_size * 4);
- if (!pohmelfs_ftrans)
- return -ENOMEM;
-
- return 0;
-}
-
-void pohmelfs_ftrans_exit(void)
-{
- vfree(pohmelfs_ftrans);
-}
-
-void pohmelfs_ftrans_clean(u64 id)
-{
- if (pohmelfs_ftrans) {
- u32 i = id & 0xffffffff;
- int idx = i % pohmelfs_ftrans_size;
-
- pohmelfs_ftrans[idx] = 0;
- }
-}
-
-void pohmelfs_ftrans_update(u64 id)
-{
- if (pohmelfs_ftrans) {
- u32 i = id & 0xffffffff;
- int idx = i % pohmelfs_ftrans_size;
-
- pohmelfs_ftrans[idx] = i;
- }
-}
-
-int pohmelfs_ftrans_check(u64 id)
-{
- if (pohmelfs_ftrans) {
- u32 i = id & 0xffffffff;
- int idx = i % pohmelfs_ftrans_size;
-
- return (pohmelfs_ftrans[idx] == i);
- }
-
- return -1;
-}
-
/*
* Async machinery lives here.
* All commands being sent to server do _not_ require sync reply,
@@ -450,8 +401,24 @@ static int pohmelfs_readdir_response(struct netfs_state *st)
if (err != -EEXIST)
goto err_out_put;
} else {
+ struct dentry *dentry, *alias, *pd;
+
set_bit(NETFS_INODE_REMOTE_SYNCED, &npi->state);
clear_bit(NETFS_INODE_OWNED, &npi->state);
+
+ pd = d_find_alias(&parent->vfs_inode);
+ if (pd) {
+ str.hash = full_name_hash(str.name, str.len);
+ dentry = d_alloc(pd, &str);
+ if (dentry) {
+ alias = d_materialise_unique(dentry, &npi->vfs_inode);
+ if (alias)
+ dput(dentry);
+ }
+
+ dput(dentry);
+ dput(pd);
+ }
}
}
out:
@@ -638,15 +605,12 @@ static int pohmelfs_transaction_response(struct netfs_state *st)
if (dst) {
netfs_trans_remove_nolock(dst, st);
t = dst->trans;
-
- pohmelfs_ftrans_update(cmd->start);
}
mutex_unlock(&st->trans_lock);
if (!t) {
- int check = pohmelfs_ftrans_check(cmd->start);
- printk("%s: failed to find transaction: start: %llu: id: %llu, size: %u, ext: %u, double: %d.\n",
- __func__, cmd->start, cmd->id, cmd->size, cmd->ext, check);
+ printk("%s: failed to find transaction: start: %llu: id: %llu, size: %u, ext: %u.\n",
+ __func__, cmd->start, cmd->id, cmd->size, cmd->ext);
err = -EINVAL;
goto out;
}
diff --git a/drivers/staging/pohmelfs/netfs.h b/drivers/staging/pohmelfs/netfs.h
index 2ff21ae5bb12..c78cfcb042fb 100644
--- a/drivers/staging/pohmelfs/netfs.h
+++ b/drivers/staging/pohmelfs/netfs.h
@@ -87,6 +87,7 @@ enum {
POHMELFS_FLAGS_DEL, /* Network state control message for DEL */
POHMELFS_FLAGS_SHOW, /* Network state control message for SHOW */
POHMELFS_FLAGS_CRYPTO, /* Crypto data control message */
+ POHMELFS_FLAGS_MODIFY, /* Network state modification message */
};
/*
@@ -116,16 +117,20 @@ struct pohmelfs_crypto
unsigned char data[0]; /* Algorithm string, key and IV */
};
+#define POHMELFS_IO_PERM_READ (1<<0)
+#define POHMELFS_IO_PERM_WRITE (1<<1)
+
/*
* Configuration command used to create table of different remote servers.
*/
struct pohmelfs_ctl
{
- unsigned int idx; /* Config index */
- unsigned int type; /* Socket type */
- unsigned int proto; /* Socket protocol */
- unsigned int addrlen; /* Size of the address */
- unsigned short unused; /* Align structure by 4 bytes */
+ __u32 idx; /* Config index */
+ __u32 type; /* Socket type */
+ __u32 proto; /* Socket protocol */
+ __u16 addrlen; /* Size of the address */
+ __u16 perm; /* IO permission */
+ __u16 prio; /* IO priority */
struct saddr addr; /* Remote server address */
};
@@ -921,12 +926,6 @@ static inline void pohmelfs_mcache_put(struct pohmelfs_sb *psb,
pohmelfs_mcache_free(psb, m);
}
-int pohmelfs_ftrans_init(void);
-void pohmelfs_ftrans_exit(void);
-void pohmelfs_ftrans_update(u64 id);
-int pohmelfs_ftrans_check(u64 id);
-void pohmelfs_ftrans_clean(u64 id);
-
#endif /* __KERNEL__*/
#endif /* __NETFS_H */
diff --git a/drivers/staging/pohmelfs/trans.c b/drivers/staging/pohmelfs/trans.c
index bcb59425a21c..fef5f9bd6920 100644
--- a/drivers/staging/pohmelfs/trans.c
+++ b/drivers/staging/pohmelfs/trans.c
@@ -456,34 +456,25 @@ int netfs_trans_finish_send(struct netfs_trans *t, struct pohmelfs_sb *psb)
__func__, t, t->gen, t->iovec.iov_len, t->page_num, psb->active_state);
#endif
mutex_lock(&psb->state_lock);
+ list_for_each_entry(c, &psb->state_list, config_entry) {
+ st = &c->state;
- if ((t->flags & NETFS_TRANS_SINGLE_DST) && psb->active_state) {
- st = &psb->active_state->state;
-
- err = -EPIPE;
- if (netfs_state_poll(st) & POLLOUT) {
- err = netfs_trans_push_dst(t, st);
- if (!err) {
- err = netfs_trans_send(t, st);
- if (err) {
- netfs_trans_drop_last(t, st);
- } else {
- pohmelfs_switch_active(psb);
- goto out;
- }
- }
+ if (t->flags & NETFS_TRANS_SINGLE_DST) {
+ if (!(st->ctl.perm & POHMELFS_IO_PERM_READ))
+ continue;
+ } else {
+ if (!(st->ctl.perm & POHMELFS_IO_PERM_WRITE))
+ continue;
}
- pohmelfs_switch_active(psb);
- }
- list_for_each_entry(c, &psb->state_list, config_entry) {
- st = &c->state;
+ if (psb->active_state && (psb->active_state->state.ctl.prio >= st->ctl.prio))
+ st = &psb->active_state->state;
err = netfs_trans_push(t, st);
if (!err && (t->flags & NETFS_TRANS_SINGLE_DST))
break;
}
-out:
+
mutex_unlock(&psb->state_lock);
#if 0
dprintk("%s: fully sent t: %p, gen: %u, size: %u, page_num: %u, err: %d.\n",
@@ -501,8 +492,6 @@ int netfs_trans_finish(struct netfs_trans *t, struct pohmelfs_sb *psb)
t->gen = atomic_inc_return(&psb->trans_gen);
- pohmelfs_ftrans_clean(t->gen);
-
cmd->size = t->iovec.iov_len - sizeof(struct netfs_cmd) +
t->attached_size + t->attached_pages * sizeof(struct netfs_cmd);
cmd->cmd = NETFS_TRANS;
diff --git a/drivers/staging/rt2860/common/mlme.c b/drivers/staging/rt2860/common/mlme.c
index c00f9ab9c46c..2edf2999f5c8 100644
--- a/drivers/staging/rt2860/common/mlme.c
+++ b/drivers/staging/rt2860/common/mlme.c
@@ -5664,7 +5664,7 @@ VOID AsicUpdateProtect(
#if 0
MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
#else
- // If the user want disable RtsThreshold and enbale Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
+ // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
if ((
#ifdef DOT11_N_SUPPORT
(pAd->CommonCfg.BACapability.field.AmsduEnable) ||
diff --git a/drivers/staging/rt2860/rt_main_dev.c b/drivers/staging/rt2860/rt_main_dev.c
index cf17bcdd7333..6c4396f0903b 100644
--- a/drivers/staging/rt2860/rt_main_dev.c
+++ b/drivers/staging/rt2860/rt_main_dev.c
@@ -722,6 +722,20 @@ err:
return (-1);
} /* End of rt28xx_open */
+static const struct net_device_ops rt2860_netdev_ops = {
+ .ndo_open = MainVirtualIF_open,
+ .ndo_stop = MainVirtualIF_close,
+ .ndo_do_ioctl = rt28xx_ioctl,
+ .ndo_get_stats = RT28xx_get_ether_stats,
+ .ndo_validate_addr = NULL,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_change_mtu = eth_change_mtu,
+#ifdef IKANOS_VX_1X0
+ .ndo_start_xmit = IKANOS_DataFramesTx,
+#else
+ .ndo_start_xmit = rt28xx_send_packets,
+#endif
+};
/* Must not be called for mdev and apdev */
static NDIS_STATUS rt_ieee80211_if_setup(struct net_device *dev, PRTMP_ADAPTER pAd)
@@ -733,11 +747,6 @@ static NDIS_STATUS rt_ieee80211_if_setup(struct net_device *dev, PRTMP_ADAPTER p
//ether_setup(dev);
- dev->hard_start_xmit = rt28xx_send_packets;
-
-#ifdef IKANOS_VX_1X0
- dev->hard_start_xmit = IKANOS_DataFramesTx;
-#endif // IKANOS_VX_1X0 //
#ifdef CONFIG_STA_SUPPORT
#if WIRELESS_EXT >= 12
@@ -760,12 +769,8 @@ static NDIS_STATUS rt_ieee80211_if_setup(struct net_device *dev, PRTMP_ADAPTER p
#if WIRELESS_EXT < 21
dev->get_wireless_stats = rt28xx_get_wireless_stats;
#endif
- dev->get_stats = RT28xx_get_ether_stats;
- dev->open = MainVirtualIF_open; //rt28xx_open;
- dev->stop = MainVirtualIF_close; //rt28xx_close;
dev->priv_flags = INT_MAIN;
- dev->do_ioctl = rt28xx_ioctl;
- dev->validate_addr = NULL;
+ dev->netdev_ops = &rt2860_netdev_ops;
// find available device name
for (i = 0; i < 8; i++)
{
diff --git a/drivers/staging/rt2870/common/mlme.c b/drivers/staging/rt2870/common/mlme.c
index 8a82cee8bf26..a26bc033337d 100644
--- a/drivers/staging/rt2870/common/mlme.c
+++ b/drivers/staging/rt2870/common/mlme.c
@@ -5561,7 +5561,7 @@ VOID AsicUpdateProtect(
#if 0
MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
#else
- // If the user want disable RtsThreshold and enbale Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
+ // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
if ((
#ifdef DOT11_N_SUPPORT
(pAd->CommonCfg.BACapability.field.AmsduEnable) ||
diff --git a/drivers/staging/rt2870/rt2870.h b/drivers/staging/rt2870/rt2870.h
index 5dd15aac9ce7..a69cf338e498 100644
--- a/drivers/staging/rt2870/rt2870.h
+++ b/drivers/staging/rt2870/rt2870.h
@@ -96,6 +96,7 @@
{USB_DEVICE(0x0DF6,0x002B)}, /* Sitecom */ \
{USB_DEVICE(0x0DF6,0x002C)}, /* Sitecom */ \
{USB_DEVICE(0x0DF6,0x002D)}, /* Sitecom */ \
+ {USB_DEVICE(0x0DF6,0x0039)}, /* Sitecom */ \
{USB_DEVICE(0x14B2,0x3C06)}, /* Conceptronic */ \
{USB_DEVICE(0x14B2,0x3C28)}, /* Conceptronic */ \
{USB_DEVICE(0x2019,0xED06)}, /* Planex Communications, Inc. */ \
@@ -144,6 +145,7 @@
{USB_DEVICE(0x0789,0x0162)}, /* Logitec */ \
{USB_DEVICE(0x0789,0x0163)}, /* Logitec */ \
{USB_DEVICE(0x0789,0x0164)}, /* Logitec */ \
+ {USB_DEVICE(0x7392,0x7717)}, /* Edimax */ \
{ }/* Terminating entry */ \
}
diff --git a/drivers/staging/rt2870/rt_main_dev.c b/drivers/staging/rt2870/rt_main_dev.c
index 313ecea0bfa8..48ad41136d0f 100644
--- a/drivers/staging/rt2870/rt_main_dev.c
+++ b/drivers/staging/rt2870/rt_main_dev.c
@@ -855,6 +855,20 @@ err:
return (-1);
} /* End of rt28xx_open */
+static const struct net_device_ops rt2870_netdev_ops = {
+ .ndo_open = MainVirtualIF_open,
+ .ndo_stop = MainVirtualIF_close,
+ .ndo_do_ioctl = rt28xx_ioctl,
+ .ndo_get_stats = RT28xx_get_ether_stats,
+ .ndo_validate_addr = NULL,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_change_mtu = eth_change_mtu,
+#ifdef IKANOS_VX_1X0
+ .ndo_start_xmit = IKANOS_DataFramesTx,
+#else
+ .ndo_start_xmit = rt28xx_send_packets,
+#endif
+};
/* Must not be called for mdev and apdev */
static NDIS_STATUS rt_ieee80211_if_setup(struct net_device *dev, PRTMP_ADAPTER pAd)
@@ -866,12 +880,6 @@ static NDIS_STATUS rt_ieee80211_if_setup(struct net_device *dev, PRTMP_ADAPTER p
//ether_setup(dev);
- dev->hard_start_xmit = rt28xx_send_packets;
-
-#ifdef IKANOS_VX_1X0
- dev->hard_start_xmit = IKANOS_DataFramesTx;
-#endif // IKANOS_VX_1X0 //
-
// dev->set_multicast_list = ieee80211_set_multicast_list;
// dev->change_mtu = ieee80211_change_mtu;
#ifdef CONFIG_STA_SUPPORT
@@ -895,16 +903,10 @@ static NDIS_STATUS rt_ieee80211_if_setup(struct net_device *dev, PRTMP_ADAPTER p
#if WIRELESS_EXT < 21
dev->get_wireless_stats = rt28xx_get_wireless_stats;
#endif
- dev->get_stats = RT28xx_get_ether_stats;
- dev->open = MainVirtualIF_open; //rt28xx_open;
- dev->stop = MainVirtualIF_close; //rt28xx_close;
// dev->uninit = ieee80211_if_reinit;
// dev->destructor = ieee80211_if_free;
dev->priv_flags = INT_MAIN;
- dev->do_ioctl = rt28xx_ioctl;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
- dev->validate_addr = NULL;
-#endif
+ dev->netdev_ops = &rt2870_netdev_ops;
// find available device name
for (i = 0; i < 8; i++)
{
diff --git a/drivers/staging/rt3070/common/mlme.c b/drivers/staging/rt3070/common/mlme.c
index 0ffbfa36699e..0189bab013cf 100644
--- a/drivers/staging/rt3070/common/mlme.c
+++ b/drivers/staging/rt3070/common/mlme.c
@@ -5575,7 +5575,7 @@ VOID AsicUpdateProtect(
RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
MacReg &= 0xFF0000FF;
- // If the user want disable RtsThreshold and enbale Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
+ // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
if ((
#ifdef DOT11_N_SUPPORT
(pAd->CommonCfg.BACapability.field.AmsduEnable) ||
diff --git a/drivers/staging/rt3070/rt_main_dev.c b/drivers/staging/rt3070/rt_main_dev.c
index c000646286e6..81f769cf1096 100644
--- a/drivers/staging/rt3070/rt_main_dev.c
+++ b/drivers/staging/rt3070/rt_main_dev.c
@@ -436,7 +436,6 @@ static int rt28xx_init(IN struct net_device *net_dev)
// OID_SET_HT_PHYMODE SetHT;
// WPDMA_GLO_CFG_STRUC GloCfg;
UINT32 MacCsr0 = 0;
- UINT32 MacValue = 0;
#ifdef RT2870
#ifdef INF_AMAZON_SE
@@ -849,6 +848,20 @@ err:
return (-1);
} /* End of rt28xx_open */
+static const struct net_device_ops rt3070_netdev_ops = {
+ .ndo_open = MainVirtualIF_open,
+ .ndo_stop = MainVirtualIF_close,
+ .ndo_do_ioctl = rt28xx_ioctl,
+ .ndo_get_stats = RT28xx_get_ether_stats,
+ .ndo_validate_addr = NULL,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_change_mtu = eth_change_mtu,
+#ifdef IKANOS_VX_1X0
+ .ndo_start_xmit = IKANOS_DataFramesTx,
+#else
+ .ndo_start_xmit = rt28xx_send_packets,
+#endif
+};
/* Must not be called for mdev and apdev */
static NDIS_STATUS rt_ieee80211_if_setup(struct net_device *dev, PRTMP_ADAPTER pAd)
@@ -860,12 +873,6 @@ static NDIS_STATUS rt_ieee80211_if_setup(struct net_device *dev, PRTMP_ADAPTER p
//ether_setup(dev);
- dev->hard_start_xmit = rt28xx_send_packets;
-
-#ifdef IKANOS_VX_1X0
- dev->hard_start_xmit = IKANOS_DataFramesTx;
-#endif // IKANOS_VX_1X0 //
-
// dev->set_multicast_list = ieee80211_set_multicast_list;
// dev->change_mtu = ieee80211_change_mtu;
#ifdef CONFIG_STA_SUPPORT
@@ -889,16 +896,10 @@ static NDIS_STATUS rt_ieee80211_if_setup(struct net_device *dev, PRTMP_ADAPTER p
#if WIRELESS_EXT < 21
dev->get_wireless_stats = rt28xx_get_wireless_stats;
#endif
- dev->get_stats = RT28xx_get_ether_stats;
- dev->open = MainVirtualIF_open; //rt28xx_open;
- dev->stop = MainVirtualIF_close; //rt28xx_close;
// dev->uninit = ieee80211_if_reinit;
// dev->destructor = ieee80211_if_free;
dev->priv_flags = INT_MAIN;
- dev->do_ioctl = rt28xx_ioctl;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
- dev->validate_addr = NULL;
-#endif
+ dev->netdev_ops = &rt3070_netdev_ops;
// find available device name
for (i = 0; i < 8; i++)
{
diff --git a/drivers/staging/rtl8187se/r8180.h b/drivers/staging/rtl8187se/r8180.h
index 12215fc61ddc..db446b7e2e08 100644
--- a/drivers/staging/rtl8187se/r8180.h
+++ b/drivers/staging/rtl8187se/r8180.h
@@ -19,7 +19,7 @@
#define R8180H
-#define RTL8180_MODULE_NAME "rtl8180"
+#define RTL8180_MODULE_NAME "r8180"
#define DMESG(x,a...) printk(KERN_INFO RTL8180_MODULE_NAME ": " x "\n", ## a)
#define DMESGW(x,a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": WW:" x "\n", ## a)
#define DMESGE(x,a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": EE:" x "\n", ## a)
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
index 6ecd12de4296..e10413cee0df 100644
--- a/drivers/staging/rtl8187se/r8180_core.c
+++ b/drivers/staging/rtl8187se/r8180_core.c
@@ -640,11 +640,9 @@ void rtl8180_proc_init_one(struct net_device *dev)
{
struct proc_dir_entry *e;
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- priv->dir_dev = create_proc_entry(dev->name,
- S_IFDIR | S_IRUGO | S_IXUGO,
- rtl8180_proc);
+ priv->dir_dev = rtl8180_proc;
if (!priv->dir_dev) {
- DMESGE("Unable to initialize /proc/net/rtl8180/%s\n",
+ DMESGE("Unable to initialize /proc/net/r8180/%s\n",
dev->name);
return;
}
@@ -654,7 +652,7 @@ void rtl8180_proc_init_one(struct net_device *dev)
if (!e) {
DMESGE("Unable to initialize "
- "/proc/net/rtl8180/%s/stats-hw\n",
+ "/proc/net/r8180/%s/stats-hw\n",
dev->name);
}
@@ -663,7 +661,7 @@ void rtl8180_proc_init_one(struct net_device *dev)
if (!e) {
DMESGE("Unable to initialize "
- "/proc/net/rtl8180/%s/stats-rx\n",
+ "/proc/net/r8180/%s/stats-rx\n",
dev->name);
}
@@ -673,7 +671,7 @@ void rtl8180_proc_init_one(struct net_device *dev)
if (!e) {
DMESGE("Unable to initialize "
- "/proc/net/rtl8180/%s/stats-tx\n",
+ "/proc/net/r8180/%s/stats-tx\n",
dev->name);
}
#if 0
@@ -702,7 +700,7 @@ void rtl8180_proc_init_one(struct net_device *dev)
if (!e) {
DMESGE("Unable to initialize "
- "/proc/net/rtl8180/%s/registers\n",
+ "/proc/net/r8180/%s/registers\n",
dev->name);
}
}
@@ -977,13 +975,6 @@ void check_tx_ring(struct net_device *dev, int pri)
*tmp & (1<<15)? "ok": "err", *(tmp+4));
}
- DMESG("nic at %d",
- (nic-nicbegin) / 8 /4);
- DMESG("tail at %d", ((int)tail - (int)begin) /8 /4);
- DMESG("head at %d", ((int)head - (int)begin) /8 /4);
- DMESG("check free desc returns %d", check_nic_enought_desc(dev,pri));
- DMESG("free desc is %d\n", get_curr_tx_free_desc(dev,pri));
- //rtl8180_reset(dev);
return;
}
@@ -1736,17 +1727,7 @@ short alloc_tx_desc_ring(struct net_device *dev, int bufsize, int count,
* descriptor's buffer must be 256 byte aligned
* we shouldn't be here, since we set DMA mask !
*/
- DMESGW("Fixing TX alignment");
- desc = (u32*)((u8*)desc + 256);
-#if (defined(CONFIG_HIGHMEM64G) || defined(CONFIG_64BIT_PHYS_ADDR))
- desc = (u32*)((u64)desc &~ 0xff);
- dma_desc = (dma_addr_t)((u8*)dma_desc + 256);
- dma_desc = (dma_addr_t)((u64)dma_desc &~ 0xff);
-#else
- desc = (u32*)((u32)desc &~ 0xff);
- dma_desc = (dma_addr_t)((u8*)dma_desc + 256);
- dma_desc = (dma_addr_t)((u32)dma_desc &~ 0xff);
-#endif
+ WARN(1, "DMA buffer is not aligned\n");
}
tmp=desc;
for (i=0;i<count;i++)
@@ -1984,18 +1965,7 @@ short alloc_rx_desc_ring(struct net_device *dev, u16 bufsize, int count)
* descriptor's buffer must be 256 byte aligned
* should never happen since we specify the DMA mask
*/
-
- DMESGW("Fixing RX alignment");
- desc = (u32*)((u8*)desc + 256);
-#if (defined(CONFIG_HIGHMEM64G) || defined(CONFIG_64BIT_PHYS_ADDR))
- desc = (u32*)((u64)desc &~ 0xff);
- dma_desc = (dma_addr_t)((u8*)dma_desc + 256);
- dma_desc = (dma_addr_t)((u64)dma_desc &~ 0xff);
-#else
- desc = (u32*)((u32)desc &~ 0xff);
- dma_desc = (dma_addr_t)((u8*)dma_desc + 256);
- dma_desc = (dma_addr_t)((u32)dma_desc &~ 0xff);
-#endif
+ WARN(1, "DMA buffer is not aligned\n");
}
priv->rxring=desc;
diff --git a/drivers/staging/slicoss/README b/drivers/staging/slicoss/README
index 2d5b1127ce51..70f49099c065 100644
--- a/drivers/staging/slicoss/README
+++ b/drivers/staging/slicoss/README
@@ -10,7 +10,36 @@ TODO:
- move firmware loading to request_firmware()
- remove direct memory access of structures
- any remaining sparse and checkpatch.pl warnings
- - any netdev recommended changes
+
+ - use net_device_ops
+ - use dev->stats rather than adapter->stats
+ - don't cast netdev_priv it is already void
+ - use compare_ether_addr
+ - GET RID OF MACROS
+ - work on all architectures
+ - without CONFIG_X86_64 confusion
+ - do 64 bit correctly
+ - don't depend on order of union
+ - get rid of ASSERT(), use BUG() instead but only where necessary
+ looks like most aren't really useful
+ - no new SIOCDEVPRIVATE ioctl allowed
+ - don't use module_param for configuring interrupt mitigation
+ use ethtool instead
+ - reorder code to elminate use of forward declarations
+ - don't keep private linked list of drivers.
+ - remove all the gratiutous debug infrastructure
+ - use PCI_DEVICE()
+ - do ethtool correctly using ethtool_ops
+ - NAPI?
+ - wasted overhead of extra stats
+ - state variables for things that are
+ easily availble and shouldn't be kept in card structure, cardnum, ...
+ slotnumber, events, ...
+ - get rid of slic_spinlock wrapper
+ - volatile == bad design => bad code
+ - locking too fine grained, not designed just throw more locks
+ at problem
+
Please send patches to:
Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c
index 948156348478..6f5d0bff4358 100644
--- a/drivers/staging/slicoss/slicoss.c
+++ b/drivers/staging/slicoss/slicoss.c
@@ -345,6 +345,19 @@ static void slic_init_adapter(struct net_device *netdev,
return;
}
+static const struct net_device_ops slic_netdev_ops = {
+ .ndo_open = slic_entry_open,
+ .ndo_stop = slic_entry_halt,
+ .ndo_start_xmit = slic_xmit_start,
+ .ndo_do_ioctl = slic_ioctl,
+ .ndo_set_mac_address = slic_mac_set_address,
+ .ndo_get_stats = slic_get_stats,
+ .ndo_set_multicast_list = slic_mcast_set_list,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_change_mtu = eth_change_mtu,
+};
+
static int __devinit slic_entry_probe(struct pci_dev *pcidev,
const struct pci_device_id *pci_tbl_entry)
{
@@ -442,13 +455,7 @@ static int __devinit slic_entry_probe(struct pci_dev *pcidev,
netdev->base_addr = (unsigned long)adapter->memorybase;
netdev->irq = adapter->irq;
- netdev->open = slic_entry_open;
- netdev->stop = slic_entry_halt;
- netdev->hard_start_xmit = slic_xmit_start;
- netdev->do_ioctl = slic_ioctl;
- netdev->set_mac_address = slic_mac_set_address;
- netdev->get_stats = slic_get_stats;
- netdev->set_multicast_list = slic_mcast_set_list;
+ netdev->netdev_ops = &slic_netdev_ops;
slic_debug_adapter_create(adapter);
@@ -1260,7 +1267,7 @@ static int slic_mcast_add_list(struct adapter *adapter, char *address)
}
/* Doesn't already exist. Allocate a structure to hold it */
- mcaddr = kmalloc(sizeof(struct mcast_address), GFP_KERNEL);
+ mcaddr = kmalloc(sizeof(struct mcast_address), GFP_ATOMIC);
if (mcaddr == NULL)
return 1;
@@ -2284,7 +2291,7 @@ static u32 slic_card_locate(struct adapter *adapter)
}
if (!physcard) {
/* no structure allocated for this physical card yet */
- physcard = kzalloc(sizeof(struct physcard), GFP_KERNEL);
+ physcard = kzalloc(sizeof(struct physcard), GFP_ATOMIC);
ASSERT(physcard);
physcard->next = slic_global.phys_card;
diff --git a/drivers/staging/stlc45xx/Kconfig b/drivers/staging/stlc45xx/Kconfig
index 8d3f46f190e8..947fb75a9c68 100644
--- a/drivers/staging/stlc45xx/Kconfig
+++ b/drivers/staging/stlc45xx/Kconfig
@@ -1,6 +1,6 @@
config STLC45XX
tristate "stlc4550/4560 support"
- depends on MAC80211 && WLAN_80211 && SPI_MASTER
+ depends on MAC80211 && WLAN_80211 && SPI_MASTER && GENERIC_HARDIRQS
---help---
This is a driver for stlc4550 and stlc4560 chipsets.
diff --git a/drivers/staging/sxg/sxg.c b/drivers/staging/sxg/sxg.c
index 891f6e334672..076b3f7d39eb 100644
--- a/drivers/staging/sxg/sxg.c
+++ b/drivers/staging/sxg/sxg.c
@@ -322,6 +322,8 @@ int sxg_add_msi_isr(struct adapter_t *adapter)
int ret,i;
if (!adapter->intrregistered) {
+ spin_unlock_irqrestore(&sxg_global.driver_lock,
+ sxg_global.flags);
for (i=0; i<adapter->nr_msix_entries; i++) {
ret = request_irq (adapter->msi_entries[i].vector,
sxg_isr,
@@ -329,6 +331,8 @@ int sxg_add_msi_isr(struct adapter_t *adapter)
adapter->netdev->name,
adapter->netdev);
if (ret) {
+ spin_lock_irqsave(&sxg_global.driver_lock,
+ sxg_global.flags);
DBG_ERROR("sxg: MSI-X request_irq (%s) "
"FAILED [%x]\n", adapter->netdev->name,
ret);
@@ -336,6 +340,7 @@ int sxg_add_msi_isr(struct adapter_t *adapter)
}
}
}
+ spin_lock_irqsave(&sxg_global.driver_lock, sxg_global.flags);
adapter->msi_enabled = TRUE;
adapter->intrregistered = 1;
adapter->IntRegistered = TRUE;
@@ -896,6 +901,22 @@ static inline int sxg_read_config(struct adapter_t *adapter)
return status;
}
+static const struct net_device_ops sxg_netdev_ops = {
+ .ndo_open = sxg_entry_open,
+ .ndo_stop = sxg_entry_halt,
+ .ndo_start_xmit = sxg_send_packets,
+ .ndo_do_ioctl = sxg_ioctl,
+ .ndo_change_mtu = sxg_change_mtu,
+ .ndo_get_stats = sxg_get_stats,
+ .ndo_set_multicast_list = sxg_mcast_set_list,
+ .ndo_validate_addr = eth_validate_addr,
+#if XXXTODO
+ .ndo_set_mac_address = sxg_mac_set_address,
+#else
+ .ndo_set_mac_address = eth_mac_addr,
+#endif
+};
+
static int sxg_entry_probe(struct pci_dev *pcidev,
const struct pci_device_id *pci_tbl_entry)
{
@@ -1095,16 +1116,7 @@ static int sxg_entry_probe(struct pci_dev *pcidev,
netdev->base_addr = (unsigned long)adapter->base_addr;
netdev->irq = adapter->irq;
- netdev->open = sxg_entry_open;
- netdev->stop = sxg_entry_halt;
- netdev->hard_start_xmit = sxg_send_packets;
- netdev->do_ioctl = sxg_ioctl;
- netdev->change_mtu = sxg_change_mtu;
-#if XXXTODO
- netdev->set_mac_address = sxg_mac_set_address;
-#endif
- netdev->get_stats = sxg_get_stats;
- netdev->set_multicast_list = sxg_mcast_set_list;
+ netdev->netdev_ops = &sxg_netdev_ops;
SET_ETHTOOL_OPS(netdev, &sxg_nic_ethtool_ops);
netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
err = sxg_set_interrupt_capability(adapter);
@@ -2247,6 +2259,8 @@ static int sxg_entry_open(struct net_device *dev)
DBG_ERROR("sxg: %s EXIT\n", __func__);
spin_unlock_irqrestore(&sxg_global.driver_lock, sxg_global.flags);
+ mod_timer(&adapter->watchdog_timer, jiffies);
+
return STATUS_SUCCESS;
}
@@ -2568,6 +2582,7 @@ static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
u64 phys_addr;
unsigned long flags;
unsigned long queue_id=0;
+ int offload_cksum = 0;
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbSgl",
pSgl, SxgSgl, 0, 0);
@@ -2606,7 +2621,11 @@ static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
struct iphdr *ip;
ip = ip_hdr(skb);
- if ((ip->protocol == IPPROTO_TCP)&&(DataLength >= sizeof(
+ if (ip->protocol == IPPROTO_TCP)
+ offload_cksum = 1;
+ if (!offload_cksum || !tcp_hdr(skb))
+ queue_id = 0;
+ else if (offload_cksum && (DataLength >= sizeof(
struct tcphdr))){
queue_id = ((ntohs(tcp_hdr(skb)->dest) == ISCSI_PORT) ?
(ntohs (tcp_hdr(skb)->source) &
@@ -2615,8 +2634,11 @@ static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
SXG_LARGE_SEND_QUEUE_MASK));
}
} else if (skb->protocol == htons(ETH_P_IPV6)) {
- if ((ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) && (DataLength >=
- sizeof(struct tcphdr)) ) {
+ if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
+ offload_cksum = 1;
+ if (!offload_cksum || !tcp_hdr(skb))
+ queue_id = 0;
+ else if (offload_cksum && (DataLength>=sizeof(struct tcphdr))){
queue_id = ((ntohs(tcp_hdr(skb)->dest) == ISCSI_PORT) ?
(ntohs (tcp_hdr(skb)->source) &
SXG_LARGE_SEND_QUEUE_MASK):
@@ -2645,23 +2667,38 @@ static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
}
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbCmd",
XmtCmd, XmtRingInfo->Head, XmtRingInfo->Tail, 0);
- /* Update stats */
- adapter->stats.tx_packets++;
- adapter->stats.tx_bytes += DataLength;
-#if XXXTODO /* Stats stuff */
- if (SXG_MULTICAST_PACKET(EtherHdr)) {
- if (SXG_BROADCAST_PACKET(EtherHdr)) {
- adapter->Stats.DumbXmtBcastPkts++;
- adapter->Stats.DumbXmtBcastBytes += DataLength;
+ memset(XmtCmd, '\0', sizeof(*XmtCmd));
+ XmtCmd->SgEntries = 1;
+ XmtCmd->Flags = 0;
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ /*
+ * We need to set the Checkum in IP header to 0. This is
+ * required by hardware.
+ */
+ if (offload_cksum) {
+ ip_hdr(skb)->check = 0x0;
+ XmtCmd->CsumFlags.Flags |= SXG_SLOWCMD_CSUM_IP;
+ XmtCmd->CsumFlags.Flags |= SXG_SLOWCMD_CSUM_TCP;
+ /*
+ * Dont know if length will require a change in
+ * case of VLAN
+ */
+ XmtCmd->CsumFlags.MacLen = ETH_HLEN;
+ XmtCmd->CsumFlags.IpHl = skb_network_header_len(skb) >>
+ SXG_NW_HDR_LEN_SHIFT;
} else {
- adapter->Stats.DumbXmtMcastPkts++;
- adapter->Stats.DumbXmtMcastBytes += DataLength;
+ if (skb_checksum_help(skb)){
+ printk(KERN_EMERG "Dropped UDP packet for"
+ " incorrect checksum calculation\n");
+ if (XmtCmd)
+ SXG_ABORT_CMD(XmtRingInfo);
+ spin_unlock_irqrestore(&adapter->XmtZeroLock,
+ flags);
+ return STATUS_SUCCESS;
+ }
}
- } else {
- adapter->Stats.DumbXmtUcastPkts++;
- adapter->Stats.DumbXmtUcastBytes += DataLength;
}
-#endif
+
/*
* Fill in the command
* Copy out the first SGE to the command and adjust for offset
@@ -2679,31 +2716,17 @@ static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
(SXG_INVALID_SGL(phys_addr,skb->data_len)))
{
spin_unlock_irqrestore(&adapter->XmtZeroLock, flags);
+ if (XmtCmd)
+ SXG_ABORT_CMD(XmtRingInfo);
/* Silently drop this packet */
printk(KERN_EMERG"Dropped a packet for 64k boundary problem\n");
return STATUS_SUCCESS;
}
- memset(XmtCmd, '\0', sizeof(*XmtCmd));
XmtCmd->Buffer.FirstSgeAddress = phys_addr;
XmtCmd->Buffer.FirstSgeLength = DataLength;
XmtCmd->Buffer.SgeOffset = 0;
XmtCmd->Buffer.TotalLength = DataLength;
- XmtCmd->SgEntries = 1;
- XmtCmd->Flags = 0;
- if (skb->ip_summed == CHECKSUM_PARTIAL) {
- /*
- * We need to set the Checkum in IP header to 0. This is
- * required by hardware.
- */
- ip_hdr(skb)->check = 0x0;
- XmtCmd->CsumFlags.Flags |= SXG_SLOWCMD_CSUM_IP;
- XmtCmd->CsumFlags.Flags |= SXG_SLOWCMD_CSUM_TCP;
- /* Dont know if length will require a change in case of VLAN */
- XmtCmd->CsumFlags.MacLen = ETH_HLEN;
- XmtCmd->CsumFlags.IpHl = skb_network_header_len(skb) >>
- SXG_NW_HDR_LEN_SHIFT;
- }
/*
* Advance transmit cmd descripter by 1.
* NOTE - See comments in SxgTcpOutput where we write
@@ -2715,6 +2738,24 @@ static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
ASSERT((queue_id & ~SXG_LARGE_SEND_QUEUE_MASK) == 0);
WRITE_REG(adapter->UcodeRegs[0].XmtCmd, ((queue_id << 16) | 1), TRUE);
adapter->Stats.XmtQLen++; /* Stats within lock */
+ /* Update stats */
+ adapter->stats.tx_packets++;
+ adapter->stats.tx_bytes += DataLength;
+#if XXXTODO /* Stats stuff */
+ if (SXG_MULTICAST_PACKET(EtherHdr)) {
+ if (SXG_BROADCAST_PACKET(EtherHdr)) {
+ adapter->Stats.DumbXmtBcastPkts++;
+ adapter->Stats.DumbXmtBcastBytes += DataLength;
+ } else {
+ adapter->Stats.DumbXmtMcastPkts++;
+ adapter->Stats.DumbXmtMcastBytes += DataLength;
+ }
+ } else {
+ adapter->Stats.DumbXmtUcastPkts++;
+ adapter->Stats.DumbXmtUcastBytes += DataLength;
+ }
+#endif
+
spin_unlock_irqrestore(&adapter->XmtZeroLock, flags);
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XDumSgl2",
XmtCmd, pSgl, SxgSgl, 0);
diff --git a/drivers/staging/uc2322/aten2011.c b/drivers/staging/uc2322/aten2011.c
index 85b705453066..9c62f787cc9c 100644
--- a/drivers/staging/uc2322/aten2011.c
+++ b/drivers/staging/uc2322/aten2011.c
@@ -603,10 +603,9 @@ static void ATEN2011_bulk_out_data_callback(struct urb *urb)
tty = tty_port_tty_get(&ATEN2011_port->port->port);
- if (tty && ATEN2011_port->open) {
+ if (tty && ATEN2011_port->open)
/* tell the tty driver that something has changed */
- wake_up_interruptible(&tty->write_wait);
- }
+ tty_wakeup(tty);
/* schedule_work(&ATEN2011_port->port->work); */
tty_kref_put(tty);
@@ -825,12 +824,6 @@ static int ATEN2011_open(struct tty_struct *tty, struct usb_serial_port *port,
status = 0;
status = set_reg_sync(port, ATEN2011_port->ControlRegOffset, Data);
- /* force low_latency on so that our tty_push actually forces *
- * the data through,otherwise it is scheduled, and with *
- * high data rates (like with OHCI) data can get lost. */
-
- if (tty)
- tty->low_latency = 1;
/*
* Check to see if we've set up our endpoint info yet
* (can't set it up in ATEN2011_startup as the structures
@@ -1473,22 +1466,7 @@ static void ATEN2011_set_termios(struct tty_struct *tty,
cflag = tty->termios->c_cflag;
- if (!cflag) {
- dbg("%s %s", __func__, "cflag is NULL");
- return;
- }
-
- /* check that they really want us to change something */
- if (old_termios) {
- if ((cflag == old_termios->c_cflag) &&
- (RELEVANT_IFLAG(tty->termios->c_iflag) ==
- RELEVANT_IFLAG(old_termios->c_iflag))) {
- dbg("%s", "Nothing to change");
- return;
- }
- }
-
- dbg("%s - clfag %08x iflag %08x", __func__,
+ dbg("%s - cflag %08x iflag %08x", __func__,
tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag));
if (old_termios) {
diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c
index 9c3f9439f35e..3b2d52819b4c 100644
--- a/drivers/staging/winbond/wbusb.c
+++ b/drivers/staging/winbond/wbusb.c
@@ -386,7 +386,7 @@ static int wb35_probe(struct usb_interface *intf, const struct usb_device_id *id
if (err)
goto error_free_hw;
- usb_set_intfdata(intf, priv);
+ usb_set_intfdata(intf, dev);
return 0;
@@ -415,10 +415,15 @@ static void wb35_hw_halt(struct wbsoft_priv *adapter)
static void wb35_disconnect(struct usb_interface *intf)
{
- struct wbsoft_priv *priv = usb_get_intfdata(intf);
+ struct ieee80211_hw *hw = usb_get_intfdata(intf);
+ struct wbsoft_priv *priv = hw->priv;
wb35_hw_halt(priv);
+ ieee80211_stop_queues(hw);
+ ieee80211_unregister_hw(hw);
+ ieee80211_free_hw(hw);
+
usb_set_intfdata(intf, NULL);
usb_put_dev(interface_to_usbdev(intf));
}
diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c
index b2a606a36936..393e4df70dfd 100644
--- a/drivers/staging/wlan-ng/p80211netdev.c
+++ b/drivers/staging/wlan-ng/p80211netdev.c
@@ -711,6 +711,20 @@ static int wlan_change_mtu(netdevice_t *dev, int new_mtu)
return 0;
}
+static const struct net_device_ops p80211_netdev_ops = {
+ .ndo_init = p80211knetdev_init,
+ .ndo_open = p80211knetdev_open,
+ .ndo_stop = p80211knetdev_stop,
+ .ndo_get_stats = p80211knetdev_get_stats,
+ .ndo_start_xmit = p80211knetdev_hard_start_xmit,
+ .ndo_set_multicast_list = p80211knetdev_set_multicast_list,
+ .ndo_do_ioctl = p80211knetdev_do_ioctl,
+ .ndo_set_mac_address = p80211knetdev_set_mac_address,
+ .ndo_tx_timeout = p80211knetdev_tx_timeout,
+ .ndo_change_mtu = wlan_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
/*----------------------------------------------------------------
* wlan_setup
*
@@ -756,11 +770,7 @@ int wlan_setup(wlandevice_t *wlandev)
} else {
wlandev->netdev = dev;
dev->ml_priv = wlandev;
- dev->hard_start_xmit = p80211knetdev_hard_start_xmit;
- dev->get_stats = p80211knetdev_get_stats;
- dev->init = p80211knetdev_init;
- dev->open = p80211knetdev_open;
- dev->stop = p80211knetdev_stop;
+ dev->netdev_ops = &p80211_netdev_ops;
mutex_init(&wlandev->ioctl_lock);
/* block ioctls until fully initialised. Don't forget to call
diff --git a/drivers/uio/uio_cif.c b/drivers/uio/uio_cif.c
index c60b8fcf0e3e..28034c812914 100644
--- a/drivers/uio/uio_cif.c
+++ b/drivers/uio/uio_cif.c
@@ -147,5 +147,6 @@ static void __exit hilscher_exit_module(void)
module_init(hilscher_init_module);
module_exit(hilscher_exit_module);
+MODULE_DEVICE_TABLE(pci, hilscher_pci_ids);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Hans J. Koch, Benedikt Spranger");
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 89299a5ce168..0716cdb44cd8 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -27,6 +27,8 @@ obj-$(CONFIG_USB_WUSB) += wusbcore/
obj-$(CONFIG_USB_ACM) += class/
obj-$(CONFIG_USB_PRINTER) += class/
+obj-$(CONFIG_USB_WDM) += class/
+obj-$(CONFIG_USB_TMC) += class/
obj-$(CONFIG_USB_STORAGE) += storage/
obj-$(CONFIG_USB) += storage/
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 869d47cb6db3..719e13ae4ad9 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -16,7 +16,8 @@
* v0.9 - thorough cleaning, URBification, almost a rewrite
* v0.10 - some more cleanups
* v0.11 - fixed flow control, read error doesn't stop reads
- * v0.12 - added TIOCM ioctls, added break handling, made struct acm kmalloced
+ * v0.12 - added TIOCM ioctls, added break handling, made struct acm
+ * kmalloced
* v0.13 - added termios, added hangup
* v0.14 - sized down struct acm
* v0.15 - fixed flow control again - characters could be lost
@@ -62,7 +63,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/mutex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/cdc.h>
#include <asm/byteorder.h>
@@ -87,7 +88,10 @@ static struct acm *acm_table[ACM_TTY_MINORS];
static DEFINE_MUTEX(open_mutex);
-#define ACM_READY(acm) (acm && acm->dev && acm->used)
+#define ACM_READY(acm) (acm && acm->dev && acm->port.count)
+
+static const struct tty_port_operations acm_port_ops = {
+};
#ifdef VERBOSE_DEBUG
#define verbose 1
@@ -99,13 +103,15 @@ static DEFINE_MUTEX(open_mutex);
* Functions for ACM control messages.
*/
-static int acm_ctrl_msg(struct acm *acm, int request, int value, void *buf, int len)
+static int acm_ctrl_msg(struct acm *acm, int request, int value,
+ void *buf, int len)
{
int retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0),
request, USB_RT_ACM, value,
acm->control->altsetting[0].desc.bInterfaceNumber,
buf, len, 5000);
- dbg("acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d", request, value, len, retval);
+ dbg("acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d",
+ request, value, len, retval);
return retval < 0 ? retval : 0;
}
@@ -150,9 +156,8 @@ static int acm_wb_is_avail(struct acm *acm)
n = ACM_NW;
spin_lock_irqsave(&acm->write_lock, flags);
- for (i = 0; i < ACM_NW; i++) {
+ for (i = 0; i < ACM_NW; i++)
n -= acm->wb[i].use;
- }
spin_unlock_irqrestore(&acm->write_lock, flags);
return n;
}
@@ -183,7 +188,8 @@ static int acm_start_wb(struct acm *acm, struct acm_wb *wb)
wb->urb->transfer_buffer_length = wb->len;
wb->urb->dev = acm->dev;
- if ((rc = usb_submit_urb(wb->urb, GFP_ATOMIC)) < 0) {
+ rc = usb_submit_urb(wb->urb, GFP_ATOMIC);
+ if (rc < 0) {
dbg("usb_submit_urb(write bulk) failed: %d", rc);
acm_write_done(acm, wb);
}
@@ -262,6 +268,7 @@ static void acm_ctrl_irq(struct urb *urb)
{
struct acm *acm = urb->context;
struct usb_cdc_notification *dr = urb->transfer_buffer;
+ struct tty_struct *tty;
unsigned char *data;
int newctrl;
int retval;
@@ -287,40 +294,45 @@ static void acm_ctrl_irq(struct urb *urb)
data = (unsigned char *)(dr + 1);
switch (dr->bNotificationType) {
+ case USB_CDC_NOTIFY_NETWORK_CONNECTION:
+ dbg("%s network", dr->wValue ?
+ "connected to" : "disconnected from");
+ break;
- case USB_CDC_NOTIFY_NETWORK_CONNECTION:
-
- dbg("%s network", dr->wValue ? "connected to" : "disconnected from");
- break;
-
- case USB_CDC_NOTIFY_SERIAL_STATE:
-
- newctrl = get_unaligned_le16(data);
+ case USB_CDC_NOTIFY_SERIAL_STATE:
+ tty = tty_port_tty_get(&acm->port);
+ newctrl = get_unaligned_le16(data);
- if (acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
+ if (tty) {
+ if (!acm->clocal &&
+ (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
dbg("calling hangup");
- tty_hangup(acm->tty);
+ tty_hangup(tty);
}
+ tty_kref_put(tty);
+ }
- acm->ctrlin = newctrl;
-
- dbg("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c",
- acm->ctrlin & ACM_CTRL_DCD ? '+' : '-', acm->ctrlin & ACM_CTRL_DSR ? '+' : '-',
- acm->ctrlin & ACM_CTRL_BRK ? '+' : '-', acm->ctrlin & ACM_CTRL_RI ? '+' : '-',
- acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-', acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-',
- acm->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-');
+ acm->ctrlin = newctrl;
+ dbg("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c",
+ acm->ctrlin & ACM_CTRL_DCD ? '+' : '-',
+ acm->ctrlin & ACM_CTRL_DSR ? '+' : '-',
+ acm->ctrlin & ACM_CTRL_BRK ? '+' : '-',
+ acm->ctrlin & ACM_CTRL_RI ? '+' : '-',
+ acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-',
+ acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-',
+ acm->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-');
break;
- default:
- dbg("unknown notification %d received: index %d len %d data0 %d data1 %d",
- dr->bNotificationType, dr->wIndex,
- dr->wLength, data[0], data[1]);
- break;
+ default:
+ dbg("unknown notification %d received: index %d len %d data0 %d data1 %d",
+ dr->bNotificationType, dr->wIndex,
+ dr->wLength, data[0], data[1]);
+ break;
}
exit:
usb_mark_last_busy(acm->dev);
- retval = usb_submit_urb (urb, GFP_ATOMIC);
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
dev_err(&urb->dev->dev, "%s - usb_submit_urb failed with "
"result %d", __func__, retval);
@@ -371,15 +383,14 @@ static void acm_rx_tasklet(unsigned long _acm)
{
struct acm *acm = (void *)_acm;
struct acm_rb *buf;
- struct tty_struct *tty = acm->tty;
+ struct tty_struct *tty;
struct acm_ru *rcv;
unsigned long flags;
unsigned char throttled;
dbg("Entering acm_rx_tasklet");
- if (!ACM_READY(acm))
- {
+ if (!ACM_READY(acm)) {
dbg("acm_rx_tasklet: ACM not ready");
return;
}
@@ -387,12 +398,13 @@ static void acm_rx_tasklet(unsigned long _acm)
spin_lock_irqsave(&acm->throttle_lock, flags);
throttled = acm->throttle;
spin_unlock_irqrestore(&acm->throttle_lock, flags);
- if (throttled)
- {
+ if (throttled) {
dbg("acm_rx_tasklet: throttled");
return;
}
+ tty = tty_port_tty_get(&acm->port);
+
next_buffer:
spin_lock_irqsave(&acm->read_lock, flags);
if (list_empty(&acm->filled_read_bufs)) {
@@ -406,20 +418,22 @@ next_buffer:
dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size);
- tty_buffer_request_room(tty, buf->size);
- spin_lock_irqsave(&acm->throttle_lock, flags);
- throttled = acm->throttle;
- spin_unlock_irqrestore(&acm->throttle_lock, flags);
- if (!throttled)
- tty_insert_flip_string(tty, buf->base, buf->size);
- tty_flip_buffer_push(tty);
-
- if (throttled) {
- dbg("Throttling noticed");
- spin_lock_irqsave(&acm->read_lock, flags);
- list_add(&buf->list, &acm->filled_read_bufs);
- spin_unlock_irqrestore(&acm->read_lock, flags);
- return;
+ if (tty) {
+ spin_lock_irqsave(&acm->throttle_lock, flags);
+ throttled = acm->throttle;
+ spin_unlock_irqrestore(&acm->throttle_lock, flags);
+ if (!throttled) {
+ tty_buffer_request_room(tty, buf->size);
+ tty_insert_flip_string(tty, buf->base, buf->size);
+ tty_flip_buffer_push(tty);
+ } else {
+ tty_kref_put(tty);
+ dbg("Throttling noticed");
+ spin_lock_irqsave(&acm->read_lock, flags);
+ list_add(&buf->list, &acm->filled_read_bufs);
+ spin_unlock_irqrestore(&acm->read_lock, flags);
+ return;
+ }
}
spin_lock_irqsave(&acm->read_lock, flags);
@@ -428,6 +442,8 @@ next_buffer:
goto next_buffer;
urbs:
+ tty_kref_put(tty);
+
while (!list_empty(&acm->spare_read_bufs)) {
spin_lock_irqsave(&acm->read_lock, flags);
if (list_empty(&acm->spare_read_urbs)) {
@@ -454,10 +470,11 @@ urbs:
rcv->urb->transfer_dma = buf->dma;
rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- /* This shouldn't kill the driver as unsuccessful URBs are returned to the
- free-urbs-pool and resubmited ASAP */
+ /* This shouldn't kill the driver as unsuccessful URBs are
+ returned to the free-urbs-pool and resubmited ASAP */
spin_lock_irqsave(&acm->read_lock, flags);
- if (acm->susp_count || usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) {
+ if (acm->susp_count ||
+ usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) {
list_add(&buf->list, &acm->spare_read_bufs);
list_add(&rcv->list, &acm->spare_read_urbs);
acm->processing = 0;
@@ -499,11 +516,14 @@ static void acm_write_bulk(struct urb *urb)
static void acm_softint(struct work_struct *work)
{
struct acm *acm = container_of(work, struct acm, work);
+ struct tty_struct *tty;
dev_vdbg(&acm->data->dev, "tx work\n");
if (!ACM_READY(acm))
return;
- tty_wakeup(acm->tty);
+ tty = tty_port_tty_get(&acm->port);
+ tty_wakeup(tty);
+ tty_kref_put(tty);
}
static void acm_waker(struct work_struct *waker)
@@ -543,12 +563,9 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
rv = 0;
set_bit(TTY_NO_WRITE_SPLIT, &tty->flags);
- tty->driver_data = acm;
- acm->tty = tty;
- /* force low_latency on so that our tty_push actually forces the data through,
- otherwise it is scheduled, and with high data rates data can get lost. */
- tty->low_latency = 1;
+ tty->driver_data = acm;
+ tty_port_tty_set(&acm->port, tty);
if (usb_autopm_get_interface(acm->control) < 0)
goto early_bail;
@@ -556,11 +573,10 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
acm->control->needs_remote_wakeup = 1;
mutex_lock(&acm->mutex);
- if (acm->used++) {
+ if (acm->port.count++) {
usb_autopm_put_interface(acm->control);
goto done;
- }
-
+ }
acm->ctrlurb->dev = acm->dev;
if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
@@ -571,22 +587,22 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) &&
(acm->ctrl_caps & USB_CDC_CAP_LINE))
goto full_bailout;
+
usb_autopm_put_interface(acm->control);
INIT_LIST_HEAD(&acm->spare_read_urbs);
INIT_LIST_HEAD(&acm->spare_read_bufs);
INIT_LIST_HEAD(&acm->filled_read_bufs);
- for (i = 0; i < acm->rx_buflimit; i++) {
+
+ for (i = 0; i < acm->rx_buflimit; i++)
list_add(&(acm->ru[i].list), &acm->spare_read_urbs);
- }
- for (i = 0; i < acm->rx_buflimit; i++) {
+ for (i = 0; i < acm->rx_buflimit; i++)
list_add(&(acm->rb[i].list), &acm->spare_read_bufs);
- }
acm->throttle = 0;
tasklet_schedule(&acm->urb_task);
-
+ rv = tty_port_block_til_ready(&acm->port, tty, filp);
done:
mutex_unlock(&acm->mutex);
err_out:
@@ -597,16 +613,17 @@ full_bailout:
usb_kill_urb(acm->ctrlurb);
bail_out:
usb_autopm_put_interface(acm->control);
- acm->used--;
+ acm->port.count--;
mutex_unlock(&acm->mutex);
early_bail:
mutex_unlock(&open_mutex);
+ tty_port_tty_set(&acm->port, NULL);
return -EIO;
}
static void acm_tty_unregister(struct acm *acm)
{
- int i,nr;
+ int i, nr;
nr = acm->rx_buflimit;
tty_unregister_device(acm_tty_driver, acm->minor);
@@ -623,41 +640,56 @@ static void acm_tty_unregister(struct acm *acm)
static int acm_tty_chars_in_buffer(struct tty_struct *tty);
+static void acm_port_down(struct acm *acm, int drain)
+{
+ int i, nr = acm->rx_buflimit;
+ mutex_lock(&open_mutex);
+ if (acm->dev) {
+ usb_autopm_get_interface(acm->control);
+ acm_set_control(acm, acm->ctrlout = 0);
+ /* try letting the last writes drain naturally */
+ if (drain) {
+ wait_event_interruptible_timeout(acm->drain_wait,
+ (ACM_NW == acm_wb_is_avail(acm)) || !acm->dev,
+ ACM_CLOSE_TIMEOUT * HZ);
+ }
+ usb_kill_urb(acm->ctrlurb);
+ for (i = 0; i < ACM_NW; i++)
+ usb_kill_urb(acm->wb[i].urb);
+ for (i = 0; i < nr; i++)
+ usb_kill_urb(acm->ru[i].urb);
+ acm->control->needs_remote_wakeup = 0;
+ usb_autopm_put_interface(acm->control);
+ }
+ mutex_unlock(&open_mutex);
+}
+
+static void acm_tty_hangup(struct tty_struct *tty)
+{
+ struct acm *acm = tty->driver_data;
+ tty_port_hangup(&acm->port);
+ acm_port_down(acm, 0);
+}
+
static void acm_tty_close(struct tty_struct *tty, struct file *filp)
{
struct acm *acm = tty->driver_data;
- int i,nr;
- if (!acm || !acm->used)
+ /* Perform the closing process and see if we need to do the hardware
+ shutdown */
+ if (tty_port_close_start(&acm->port, tty, filp) == 0)
return;
-
- nr = acm->rx_buflimit;
+ acm_port_down(acm, 0);
+ tty_port_close_end(&acm->port, tty);
mutex_lock(&open_mutex);
- if (!--acm->used) {
- if (acm->dev) {
- usb_autopm_get_interface(acm->control);
- acm_set_control(acm, acm->ctrlout = 0);
-
- /* try letting the last writes drain naturally */
- wait_event_interruptible_timeout(acm->drain_wait,
- (ACM_NW == acm_wb_is_avail(acm))
- || !acm->dev,
- ACM_CLOSE_TIMEOUT * HZ);
-
- usb_kill_urb(acm->ctrlurb);
- for (i = 0; i < ACM_NW; i++)
- usb_kill_urb(acm->wb[i].urb);
- for (i = 0; i < nr; i++)
- usb_kill_urb(acm->ru[i].urb);
- acm->control->needs_remote_wakeup = 0;
- usb_autopm_put_interface(acm->control);
- } else
- acm_tty_unregister(acm);
- }
+ tty_port_tty_set(&acm->port, NULL);
+ if (!acm->dev)
+ acm_tty_unregister(acm);
mutex_unlock(&open_mutex);
}
-static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
+static int acm_tty_write(struct tty_struct *tty,
+ const unsigned char *buf, int count)
{
struct acm *acm = tty->driver_data;
int stat;
@@ -673,7 +705,8 @@ static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int c
return 0;
spin_lock_irqsave(&acm->write_lock, flags);
- if ((wbn = acm_wb_alloc(acm)) < 0) {
+ wbn = acm_wb_alloc(acm);
+ if (wbn < 0) {
spin_unlock_irqrestore(&acm->write_lock, flags);
return 0;
}
@@ -685,7 +718,8 @@ static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int c
wb->len = count;
spin_unlock_irqrestore(&acm->write_lock, flags);
- if ((stat = acm_write_start(acm, wbn)) < 0)
+ stat = acm_write_start(acm, wbn);
+ if (stat < 0)
return stat;
return count;
}
@@ -771,8 +805,10 @@ static int acm_tty_tiocmset(struct tty_struct *tty, struct file *file,
return -EINVAL;
newctrl = acm->ctrlout;
- set = (set & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (set & TIOCM_RTS ? ACM_CTRL_RTS : 0);
- clear = (clear & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (clear & TIOCM_RTS ? ACM_CTRL_RTS : 0);
+ set = (set & TIOCM_DTR ? ACM_CTRL_DTR : 0) |
+ (set & TIOCM_RTS ? ACM_CTRL_RTS : 0);
+ clear = (clear & TIOCM_DTR ? ACM_CTRL_DTR : 0) |
+ (clear & TIOCM_RTS ? ACM_CTRL_RTS : 0);
newctrl = (newctrl & ~clear) | set;
@@ -781,7 +817,8 @@ static int acm_tty_tiocmset(struct tty_struct *tty, struct file *file,
return acm_set_control(acm, acm->ctrlout = newctrl);
}
-static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
+static int acm_tty_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
struct acm *acm = tty->driver_data;
@@ -803,7 +840,8 @@ static const __u8 acm_tty_size[] = {
5, 6, 7, 8
};
-static void acm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios_old)
+static void acm_tty_set_termios(struct tty_struct *tty,
+ struct ktermios *termios_old)
{
struct acm *acm = tty->driver_data;
struct ktermios *termios = tty->termios;
@@ -813,19 +851,23 @@ static void acm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios
if (!ACM_READY(acm))
return;
+ /* FIXME: Needs to support the tty_baud interface */
+ /* FIXME: Broken on sparc */
newline.dwDTERate = cpu_to_le32p(acm_tty_speed +
(termios->c_cflag & CBAUD & ~CBAUDEX) + (termios->c_cflag & CBAUDEX ? 15 : 0));
newline.bCharFormat = termios->c_cflag & CSTOPB ? 2 : 0;
newline.bParityType = termios->c_cflag & PARENB ?
- (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0;
+ (termios->c_cflag & PARODD ? 1 : 2) +
+ (termios->c_cflag & CMSPAR ? 2 : 0) : 0;
newline.bDataBits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4];
-
+ /* FIXME: Needs to clear unsupported bits in the termios */
acm->clocal = ((termios->c_cflag & CLOCAL) != 0);
if (!newline.dwDTERate) {
newline.dwDTERate = acm->line.dwDTERate;
newctrl &= ~ACM_CTRL_DTR;
- } else newctrl |= ACM_CTRL_DTR;
+ } else
+ newctrl |= ACM_CTRL_DTR;
if (newctrl != acm->ctrlout)
acm_set_control(acm, acm->ctrlout = newctrl);
@@ -850,9 +892,8 @@ static void acm_write_buffers_free(struct acm *acm)
struct acm_wb *wb;
struct usb_device *usb_dev = interface_to_usbdev(acm->control);
- for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) {
+ for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++)
usb_buffer_free(usb_dev, acm->writesize, wb->buf, wb->dmah);
- }
}
static void acm_read_buffers_free(struct acm *acm)
@@ -861,7 +902,8 @@ static void acm_read_buffers_free(struct acm *acm)
int i, n = acm->rx_buflimit;
for (i = 0; i < n; i++)
- usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
+ usb_buffer_free(usb_dev, acm->readsize,
+ acm->rb[i].base, acm->rb[i].dma);
}
/* Little helper: write buffers allocate */
@@ -886,8 +928,8 @@ static int acm_write_buffers_alloc(struct acm *acm)
return 0;
}
-static int acm_probe (struct usb_interface *intf,
- const struct usb_device_id *id)
+static int acm_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
{
struct usb_cdc_union_desc *union_header = NULL;
struct usb_cdc_country_functional_desc *cfd = NULL;
@@ -901,7 +943,7 @@ static int acm_probe (struct usb_interface *intf,
struct usb_device *usb_dev = interface_to_usbdev(intf);
struct acm *acm;
int minor;
- int ctrlsize,readsize;
+ int ctrlsize, readsize;
u8 *buf;
u8 ac_management_function = 0;
u8 call_management_function = 0;
@@ -921,7 +963,7 @@ static int acm_probe (struct usb_interface *intf,
control_interface = usb_ifnum_to_if(usb_dev, 0);
goto skip_normal_probe;
}
-
+
/* normal probing*/
if (!buffer) {
dev_err(&intf->dev, "Weird descriptor references\n");
@@ -929,8 +971,10 @@ static int acm_probe (struct usb_interface *intf,
}
if (!buflen) {
- if (intf->cur_altsetting->endpoint->extralen && intf->cur_altsetting->endpoint->extra) {
- dev_dbg(&intf->dev,"Seeking extra descriptors on endpoint\n");
+ if (intf->cur_altsetting->endpoint->extralen &&
+ intf->cur_altsetting->endpoint->extra) {
+ dev_dbg(&intf->dev,
+ "Seeking extra descriptors on endpoint\n");
buflen = intf->cur_altsetting->endpoint->extralen;
buffer = intf->cur_altsetting->endpoint->extra;
} else {
@@ -941,47 +985,43 @@ static int acm_probe (struct usb_interface *intf,
}
while (buflen > 0) {
- if (buffer [1] != USB_DT_CS_INTERFACE) {
+ if (buffer[1] != USB_DT_CS_INTERFACE) {
dev_err(&intf->dev, "skipping garbage\n");
goto next_desc;
}
- switch (buffer [2]) {
- case USB_CDC_UNION_TYPE: /* we've found it */
- if (union_header) {
- dev_err(&intf->dev, "More than one "
- "union descriptor, "
- "skipping ...\n");
- goto next_desc;
- }
- union_header = (struct usb_cdc_union_desc *)
- buffer;
- break;
- case USB_CDC_COUNTRY_TYPE: /* export through sysfs*/
- cfd = (struct usb_cdc_country_functional_desc *)buffer;
- break;
- case USB_CDC_HEADER_TYPE: /* maybe check version */
- break; /* for now we ignore it */
- case USB_CDC_ACM_TYPE:
- ac_management_function = buffer[3];
- break;
- case USB_CDC_CALL_MANAGEMENT_TYPE:
- call_management_function = buffer[3];
- call_interface_num = buffer[4];
- if ((call_management_function & 3) != 3)
- dev_err(&intf->dev, "This device "
- "cannot do calls on its own. "
- "It is no modem.\n");
- break;
- default:
- /* there are LOTS more CDC descriptors that
- * could legitimately be found here.
- */
- dev_dbg(&intf->dev, "Ignoring descriptor: "
- "type %02x, length %d\n",
- buffer[2], buffer[0]);
- break;
+ switch (buffer[2]) {
+ case USB_CDC_UNION_TYPE: /* we've found it */
+ if (union_header) {
+ dev_err(&intf->dev, "More than one "
+ "union descriptor, skipping ...\n");
+ goto next_desc;
}
+ union_header = (struct usb_cdc_union_desc *)buffer;
+ break;
+ case USB_CDC_COUNTRY_TYPE: /* export through sysfs*/
+ cfd = (struct usb_cdc_country_functional_desc *)buffer;
+ break;
+ case USB_CDC_HEADER_TYPE: /* maybe check version */
+ break; /* for now we ignore it */
+ case USB_CDC_ACM_TYPE:
+ ac_management_function = buffer[3];
+ break;
+ case USB_CDC_CALL_MANAGEMENT_TYPE:
+ call_management_function = buffer[3];
+ call_interface_num = buffer[4];
+ if ((call_management_function & 3) != 3)
+ dev_err(&intf->dev, "This device cannot do calls on its own. It is not a modem.\n");
+ break;
+ default:
+ /* there are LOTS more CDC descriptors that
+ * could legitimately be found here.
+ */
+ dev_dbg(&intf->dev, "Ignoring descriptor: "
+ "type %02x, length %d\n",
+ buffer[2], buffer[0]);
+ break;
+ }
next_desc:
buflen -= buffer[0];
buffer += buffer[0];
@@ -989,33 +1029,36 @@ next_desc:
if (!union_header) {
if (call_interface_num > 0) {
- dev_dbg(&intf->dev,"No union descriptor, using call management descriptor\n");
+ 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\n");
+ 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\n");
+ dev_dbg(&intf->dev, "no interfaces\n");
return -ENODEV;
}
}
-
+
if (data_interface_num != call_interface_num)
- dev_dbg(&intf->dev,"Separate call control interface. That is not fully supported.\n");
+ dev_dbg(&intf->dev, "Separate call control interface. That is not fully supported.\n");
skip_normal_probe:
/*workaround for switched interfaces */
- if (data_interface->cur_altsetting->desc.bInterfaceClass != CDC_DATA_INTERFACE_TYPE) {
- if (control_interface->cur_altsetting->desc.bInterfaceClass == CDC_DATA_INTERFACE_TYPE) {
+ 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.\n");
-
+ dev_dbg(&intf->dev,
+ "Your device has switched interfaces.\n");
t = control_interface;
control_interface = data_interface;
data_interface = t;
@@ -1027,9 +1070,9 @@ skip_normal_probe:
/* Accept probe requests only for the control interface */
if (intf != control_interface)
return -ENODEV;
-
+
if (usb_interface_claimed(data_interface)) { /* valid in this context */
- dev_dbg(&intf->dev,"The data interface isn't available\n");
+ dev_dbg(&intf->dev, "The data interface isn't available\n");
return -EBUSY;
}
@@ -1046,8 +1089,8 @@ 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\n");
-
+ dev_dbg(&intf->dev,
+ "The data interface has switched endpoints\n");
t = epread;
epread = epwrite;
epwrite = t;
@@ -1060,13 +1103,15 @@ skip_normal_probe:
return -ENODEV;
}
- if (!(acm = kzalloc(sizeof(struct acm), GFP_KERNEL))) {
+ acm = kzalloc(sizeof(struct acm), GFP_KERNEL);
+ if (acm == NULL) {
dev_dbg(&intf->dev, "out of memory (acm kzalloc)\n");
goto alloc_fail;
}
ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize);
- readsize = le16_to_cpu(epread->wMaxPacketSize)* ( quirks == SINGLE_RX_URB ? 1 : 2);
+ readsize = le16_to_cpu(epread->wMaxPacketSize) *
+ (quirks == SINGLE_RX_URB ? 1 : 2);
acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize) * 20;
acm->control = control_interface;
acm->data = data_interface;
@@ -1086,6 +1131,8 @@ skip_normal_probe:
spin_lock_init(&acm->read_lock);
mutex_init(&acm->mutex);
acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress);
+ tty_port_init(&acm->port);
+ acm->port.ops = &acm_port_ops;
buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
if (!buf) {
@@ -1107,8 +1154,10 @@ skip_normal_probe:
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)\n");
+ rcv->urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (rcv->urb == NULL) {
+ dev_dbg(&intf->dev,
+ "out of memory (read urbs usb_alloc_urb)\n");
goto alloc_fail7;
}
@@ -1121,26 +1170,29 @@ skip_normal_probe:
rb->base = usb_buffer_alloc(acm->dev, readsize,
GFP_KERNEL, &rb->dma);
if (!rb->base) {
- dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n");
+ dev_dbg(&intf->dev,
+ "out of memory (read bufs usb_buffer_alloc)\n");
goto alloc_fail7;
}
}
- for(i = 0; i < ACM_NW; i++)
- {
+ for (i = 0; i < ACM_NW; i++) {
struct acm_wb *snd = &(acm->wb[i]);
- if (!(snd->urb = usb_alloc_urb(0, GFP_KERNEL))) {
- dev_dbg(&intf->dev, "out of memory (write urbs usb_alloc_urb)");
+ snd->urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (snd->urb == NULL) {
+ dev_dbg(&intf->dev,
+ "out of memory (write urbs usb_alloc_urb)");
goto alloc_fail7;
}
- usb_fill_bulk_urb(snd->urb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
- NULL, acm->writesize, acm_write_bulk, snd);
+ usb_fill_bulk_urb(snd->urb, usb_dev,
+ usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
+ NULL, acm->writesize, acm_write_bulk, snd);
snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
snd->instance = acm;
}
- usb_set_intfdata (intf, acm);
+ usb_set_intfdata(intf, acm);
i = device_create_file(&intf->dev, &dev_attr_bmCapabilities);
if (i < 0)
@@ -1151,7 +1203,8 @@ skip_normal_probe:
if (!acm->country_codes)
goto skip_countries;
acm->country_code_size = cfd->bLength - 4;
- memcpy(acm->country_codes, (u8 *)&cfd->wCountyCode0, cfd->bLength - 4);
+ memcpy(acm->country_codes, (u8 *)&cfd->wCountyCode0,
+ cfd->bLength - 4);
acm->country_rel_date = cfd->iCountryCodeRelDate;
i = device_create_file(&intf->dev, &dev_attr_wCountryCodes);
@@ -1160,7 +1213,8 @@ skip_normal_probe:
goto skip_countries;
}
- i = device_create_file(&intf->dev, &dev_attr_iCountryCodeRelDate);
+ i = device_create_file(&intf->dev,
+ &dev_attr_iCountryCodeRelDate);
if (i < 0) {
kfree(acm->country_codes);
goto skip_countries;
@@ -1168,8 +1222,10 @@ skip_normal_probe:
}
skip_countries:
- usb_fill_int_urb(acm->ctrlurb, usb_dev, usb_rcvintpipe(usb_dev, epctrl->bEndpointAddress),
- acm->ctrl_buffer, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
+ usb_fill_int_urb(acm->ctrlurb, usb_dev,
+ usb_rcvintpipe(usb_dev, epctrl->bEndpointAddress),
+ acm->ctrl_buffer, ctrlsize, acm_ctrl_irq, acm,
+ epctrl->bInterval);
acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
acm->ctrlurb->transfer_dma = acm->ctrl_dma;
@@ -1216,7 +1272,7 @@ static void stop_data_traffic(struct acm *acm)
tasklet_disable(&acm->urb_task);
usb_kill_urb(acm->ctrlurb);
- for(i = 0; i < ACM_NW; i++)
+ for (i = 0; i < ACM_NW; i++)
usb_kill_urb(acm->wb[i].urb);
for (i = 0; i < acm->rx_buflimit; i++)
usb_kill_urb(acm->ru[i].urb);
@@ -1231,13 +1287,14 @@ static void acm_disconnect(struct usb_interface *intf)
{
struct acm *acm = usb_get_intfdata(intf);
struct usb_device *usb_dev = interface_to_usbdev(intf);
+ struct tty_struct *tty;
/* sibling interface is already cleaning up */
if (!acm)
return;
mutex_lock(&open_mutex);
- if (acm->country_codes){
+ if (acm->country_codes) {
device_remove_file(&acm->control->dev,
&dev_attr_wCountryCodes);
device_remove_file(&acm->control->dev,
@@ -1251,22 +1308,25 @@ static void acm_disconnect(struct usb_interface *intf)
stop_data_traffic(acm);
acm_write_buffers_free(acm);
- usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
+ usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer,
+ acm->ctrl_dma);
acm_read_buffers_free(acm);
usb_driver_release_interface(&acm_driver, intf == acm->control ?
acm->data : acm->control);
- if (!acm->used) {
+ if (acm->port.count == 0) {
acm_tty_unregister(acm);
mutex_unlock(&open_mutex);
return;
}
mutex_unlock(&open_mutex);
-
- if (acm->tty)
- tty_hangup(acm->tty);
+ tty = tty_port_tty_get(&acm->port);
+ if (tty) {
+ tty_hangup(tty);
+ tty_kref_put(tty);
+ }
}
#ifdef CONFIG_PM
@@ -1301,7 +1361,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message)
*/
mutex_lock(&acm->mutex);
- if (acm->used)
+ if (acm->port.count)
stop_data_traffic(acm);
mutex_unlock(&acm->mutex);
@@ -1323,7 +1383,7 @@ static int acm_resume(struct usb_interface *intf)
return 0;
mutex_lock(&acm->mutex);
- if (acm->used) {
+ if (acm->port.count) {
rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO);
if (rv < 0)
goto err_out;
@@ -1399,7 +1459,7 @@ static struct usb_device_id acm_ids[] = {
{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
USB_CDC_ACM_PROTO_AT_GSM) },
{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
- USB_CDC_ACM_PROTO_AT_3G ) },
+ USB_CDC_ACM_PROTO_AT_3G) },
{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
USB_CDC_ACM_PROTO_AT_CDMA) },
@@ -1407,7 +1467,7 @@ static struct usb_device_id acm_ids[] = {
{ }
};
-MODULE_DEVICE_TABLE (usb, acm_ids);
+MODULE_DEVICE_TABLE(usb, acm_ids);
static struct usb_driver acm_driver = {
.name = "cdc_acm",
@@ -1430,6 +1490,7 @@ static struct usb_driver acm_driver = {
static const struct tty_operations acm_ops = {
.open = acm_tty_open,
.close = acm_tty_close,
+ .hangup = acm_tty_hangup,
.write = acm_tty_write,
.write_room = acm_tty_write_room,
.ioctl = acm_tty_ioctl,
@@ -1461,7 +1522,8 @@ static int __init acm_init(void)
acm_tty_driver->subtype = SERIAL_TYPE_NORMAL,
acm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
acm_tty_driver->init_termios = tty_std_termios;
- acm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ acm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD |
+ HUPCL | CLOCAL;
tty_set_operations(acm_tty_driver, &acm_ops);
retval = tty_register_driver(acm_tty_driver);
@@ -1493,7 +1555,7 @@ static void __exit acm_exit(void)
module_init(acm_init);
module_exit(acm_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_ALIAS_CHARDEV_MAJOR(ACM_TTY_MAJOR);
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index 1f95e7aa1b66..4c3856420add 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -89,8 +89,8 @@ struct acm {
struct usb_device *dev; /* the corresponding usb device */
struct usb_interface *control; /* control interface */
struct usb_interface *data; /* data interface */
- struct tty_struct *tty; /* the corresponding tty */
- struct urb *ctrlurb; /* urbs */
+ struct tty_port port; /* our tty port data */
+ struct urb *ctrlurb; /* urbs */
u8 *ctrl_buffer; /* buffers of urbs */
dma_addr_t ctrl_dma; /* dma handles of buffers */
u8 *country_codes; /* country codes from device */
@@ -120,7 +120,6 @@ struct acm {
unsigned int ctrlout; /* output control lines (DTR, RTS) */
unsigned int writesize; /* max packet size for the output bulk endpoint */
unsigned int readsize,ctrlsize; /* buffer sizes for freeing */
- unsigned int used; /* someone has this acm's device open */
unsigned int minor; /* acm minor number */
unsigned char throttle; /* throttled by tty layer */
unsigned char clocal; /* termios CLOCAL */
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 3771d6e6d0cc..0fe434505ac4 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -3,7 +3,7 @@
*
* This driver supports USB CDC WCM Device Management.
*
- * Copyright (c) 2007-2008 Oliver Neukum
+ * Copyright (c) 2007-2009 Oliver Neukum
*
* Some code taken from cdc-acm.c
*
@@ -610,7 +610,7 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
if (!buffer)
goto out;
- while (buflen > 0) {
+ while (buflen > 2) {
if (buffer [1] != USB_DT_CS_INTERFACE) {
dev_err(&intf->dev, "skipping garbage\n");
goto next_desc;
@@ -646,16 +646,18 @@ next_desc:
spin_lock_init(&desc->iuspin);
init_waitqueue_head(&desc->wait);
desc->wMaxCommand = maxcom;
+ /* this will be expanded and needed in hardware endianness */
desc->inum = cpu_to_le16((u16)intf->cur_altsetting->desc.bInterfaceNumber);
desc->intf = intf;
INIT_WORK(&desc->rxwork, wdm_rxwork);
- iface = &intf->altsetting[0];
+ rv = -EINVAL;
+ iface = intf->cur_altsetting;
+ if (iface->desc.bNumEndpoints != 1)
+ goto err;
ep = &iface->endpoint[0].desc;
- if (!usb_endpoint_is_int_in(ep)) {
- rv = -EINVAL;
+ if (!ep || !usb_endpoint_is_int_in(ep))
goto err;
- }
desc->wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize);
desc->bMaxPacketSize0 = udev->descriptor.bMaxPacketSize0;
@@ -711,12 +713,19 @@ next_desc:
usb_set_intfdata(intf, desc);
rv = usb_register_dev(intf, &wdm_class);
- dev_info(&intf->dev, "cdc-wdm%d: USB WDM device\n",
- intf->minor - WDM_MINOR_BASE);
if (rv < 0)
- goto err;
+ goto err3;
+ else
+ dev_info(&intf->dev, "cdc-wdm%d: USB WDM device\n",
+ intf->minor - WDM_MINOR_BASE);
out:
return rv;
+err3:
+ usb_set_intfdata(intf, NULL);
+ usb_buffer_free(interface_to_usbdev(desc->intf),
+ desc->bMaxPacketSize0,
+ desc->inbuf,
+ desc->response->transfer_dma);
err2:
usb_buffer_free(interface_to_usbdev(desc->intf),
desc->wMaxPacketSize,
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index cadb2dc1d28a..3ba2fff71490 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -119,7 +119,7 @@ void *hcd_buffer_alloc(
if (size <= pool_max [i])
return dma_pool_alloc(hcd->pool [i], mem_flags, dma);
}
- return dma_alloc_coherent(hcd->self.controller, size, dma, 0);
+ return dma_alloc_coherent(hcd->self.controller, size, dma, mem_flags);
}
void hcd_buffer_free(
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index df3c539f652a..308609039c73 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -841,7 +841,7 @@ static int proc_resetep(struct dev_state *ps, void __user *arg)
ret = checkintf(ps, ret);
if (ret)
return ret;
- usb_settoggle(ps->dev, ep & 0xf, !(ep & USB_DIR_IN), 0);
+ usb_reset_endpoint(ps->dev, ep);
return 0;
}
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 81fa8506825d..42b93da1085d 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1539,6 +1539,32 @@ void usb_hcd_disable_endpoint(struct usb_device *udev,
hcd->driver->endpoint_disable(hcd, ep);
}
+/**
+ * usb_hcd_reset_endpoint - reset host endpoint state
+ * @udev: USB device.
+ * @ep: the endpoint to reset.
+ *
+ * Resets any host endpoint state such as the toggle bit, sequence
+ * number and current window.
+ */
+void usb_hcd_reset_endpoint(struct usb_device *udev,
+ struct usb_host_endpoint *ep)
+{
+ struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+
+ if (hcd->driver->endpoint_reset)
+ hcd->driver->endpoint_reset(hcd, ep);
+ else {
+ int epnum = usb_endpoint_num(&ep->desc);
+ int is_out = usb_endpoint_dir_out(&ep->desc);
+ int is_control = usb_endpoint_xfer_control(&ep->desc);
+
+ usb_settoggle(udev, epnum, is_out, 0);
+ if (is_control)
+ usb_settoggle(udev, epnum, !is_out, 0);
+ }
+}
+
/* Protect against drivers that try to unlink URBs after the device
* is gone, by waiting until all unlinks for @udev are finished.
* Since we don't currently track URBs by device, simply wait until
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index f750eb1ab595..e7d4479de41c 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -206,6 +206,11 @@ struct hc_driver {
void (*endpoint_disable)(struct usb_hcd *hcd,
struct usb_host_endpoint *ep);
+ /* (optional) reset any endpoint state such as sequence number
+ and current window */
+ void (*endpoint_reset)(struct usb_hcd *hcd,
+ struct usb_host_endpoint *ep);
+
/* root hub support */
int (*hub_status_data) (struct usb_hcd *hcd, char *buf);
int (*hub_control) (struct usb_hcd *hcd,
@@ -234,6 +239,8 @@ extern void usb_hcd_flush_endpoint(struct usb_device *udev,
struct usb_host_endpoint *ep);
extern void usb_hcd_disable_endpoint(struct usb_device *udev,
struct usb_host_endpoint *ep);
+extern void usb_hcd_reset_endpoint(struct usb_device *udev,
+ struct usb_host_endpoint *ep);
extern void usb_hcd_synchronize_unlinks(struct usb_device *udev);
extern int usb_hcd_get_frame_number(struct usb_device *udev);
@@ -279,6 +286,13 @@ extern irqreturn_t usb_hcd_irq(int irq, void *__hcd);
extern void usb_hc_died(struct usb_hcd *hcd);
extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd);
+/* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */
+#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1)
+#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << (ep)))
+#define usb_settoggle(dev, ep, out, bit) \
+ ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | \
+ ((bit) << (ep)))
+
/* -------------------------------------------------------------------------- */
/* Enumeration is only for the hub driver, or HCD virtual root hubs */
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 30a0690f3683..b62628377654 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1002,8 +1002,7 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
* the copy in usb-storage, for as long as we need two copies.
*/
- /* toggle was reset by the clear */
- usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
+ usb_reset_endpoint(dev, endp);
return 0;
}
@@ -1076,6 +1075,30 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr,
}
/**
+ * usb_reset_endpoint - Reset an endpoint's state.
+ * @dev: the device whose endpoint is to be reset
+ * @epaddr: the endpoint's address. Endpoint number for output,
+ * endpoint number + USB_DIR_IN for input
+ *
+ * Resets any host-side endpoint state such as the toggle bit,
+ * sequence number or current window.
+ */
+void usb_reset_endpoint(struct usb_device *dev, unsigned int epaddr)
+{
+ unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
+ struct usb_host_endpoint *ep;
+
+ if (usb_endpoint_out(epaddr))
+ ep = dev->ep_out[epnum];
+ else
+ ep = dev->ep_in[epnum];
+ if (ep)
+ usb_hcd_reset_endpoint(dev, ep);
+}
+EXPORT_SYMBOL_GPL(usb_reset_endpoint);
+
+
+/**
* usb_disable_interface -- Disable all endpoints for an interface
* @dev: the device whose interface is being disabled
* @intf: pointer to the interface descriptor
@@ -1117,7 +1140,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
usb_disable_endpoint(dev, i, true);
usb_disable_endpoint(dev, i + USB_DIR_IN, true);
}
- dev->toggle[0] = dev->toggle[1] = 0;
/* getting rid of interfaces will disconnect
* any drivers bound to them (a key side effect)
@@ -1154,28 +1176,24 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
* usb_enable_endpoint - Enable an endpoint for USB communications
* @dev: the device whose interface is being enabled
* @ep: the endpoint
- * @reset_toggle: flag to set the endpoint's toggle back to 0
+ * @reset_ep: flag to reset the endpoint state
*
- * Resets the endpoint toggle if asked, and sets dev->ep_{in,out} pointers.
+ * Resets the endpoint state if asked, and sets dev->ep_{in,out} pointers.
* For control endpoints, both the input and output sides are handled.
*/
void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep,
- bool reset_toggle)
+ bool reset_ep)
{
int epnum = usb_endpoint_num(&ep->desc);
int is_out = usb_endpoint_dir_out(&ep->desc);
int is_control = usb_endpoint_xfer_control(&ep->desc);
- if (is_out || is_control) {
- if (reset_toggle)
- usb_settoggle(dev, epnum, 1, 0);
+ if (reset_ep)
+ usb_hcd_reset_endpoint(dev, ep);
+ if (is_out || is_control)
dev->ep_out[epnum] = ep;
- }
- if (!is_out || is_control) {
- if (reset_toggle)
- usb_settoggle(dev, epnum, 0, 0);
+ if (!is_out || is_control)
dev->ep_in[epnum] = ep;
- }
ep->enabled = 1;
}
@@ -1183,18 +1201,18 @@ void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep,
* usb_enable_interface - Enable all the endpoints for an interface
* @dev: the device whose interface is being enabled
* @intf: pointer to the interface descriptor
- * @reset_toggles: flag to set the endpoints' toggles back to 0
+ * @reset_eps: flag to reset the endpoints' state
*
* Enables all the endpoints for the interface's current altsetting.
*/
void usb_enable_interface(struct usb_device *dev,
- struct usb_interface *intf, bool reset_toggles)
+ struct usb_interface *intf, bool reset_eps)
{
struct usb_host_interface *alt = intf->cur_altsetting;
int i;
for (i = 0; i < alt->desc.bNumEndpoints; ++i)
- usb_enable_endpoint(dev, &alt->endpoint[i], reset_toggles);
+ usb_enable_endpoint(dev, &alt->endpoint[i], reset_eps);
}
/**
@@ -1335,7 +1353,7 @@ EXPORT_SYMBOL_GPL(usb_set_interface);
* This issues a standard SET_CONFIGURATION request to the device using
* the current configuration. The effect is to reset most USB-related
* state in the device, including interface altsettings (reset to zero),
- * endpoint halts (cleared), and data toggle (only for bulk and interrupt
+ * endpoint halts (cleared), and endpoint state (only for bulk and interrupt
* endpoints). Other usbcore state is unchanged, including bindings of
* usb device drivers to interfaces.
*
@@ -1343,7 +1361,7 @@ EXPORT_SYMBOL_GPL(usb_set_interface);
* (multi-interface) devices. Instead, the driver for each interface may
* use usb_set_interface() on the interfaces it claims. Be careful though;
* some devices don't support the SET_INTERFACE request, and others won't
- * reset all the interface state (notably data toggles). Resetting the whole
+ * reset all the interface state (notably endpoint state). Resetting the whole
* configuration would affect other drivers' interfaces.
*
* The caller must own the device lock.
@@ -1376,8 +1394,6 @@ int usb_reset_configuration(struct usb_device *dev)
if (retval < 0)
return retval;
- dev->toggle[0] = dev->toggle[1] = 0;
-
/* re-init hc/hcd interface/endpoint state */
for (i = 0; i < config->desc.bNumInterfaces; i++) {
struct usb_interface *intf = config->interface[i];
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index dcfc072630c1..7eee400d3e32 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -362,7 +362,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
/* ep0 maxpacket comes later, from device descriptor */
- usb_enable_endpoint(dev, &dev->ep0, true);
+ usb_enable_endpoint(dev, &dev->ep0, false);
dev->can_submit = 1;
/* Save readable and stable topology id, distinguishing devices
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 22c65960c429..38e531ecae4d 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -51,6 +51,7 @@
* - Gadget API (majority of optional features)
* - Suspend & Remote Wakeup
*/
+#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dmapool.h>
#include <linux/dma-mapping.h>
@@ -142,7 +143,7 @@ static struct {
#define CAP_DEVICEADDR (0x014UL)
#define CAP_ENDPTLISTADDR (0x018UL)
#define CAP_PORTSC (0x044UL)
-#define CAP_DEVLC (0x0B4UL)
+#define CAP_DEVLC (0x084UL)
#define CAP_USBMODE (hw_bank.lpm ? 0x0C8UL : 0x068UL)
#define CAP_ENDPTSETUPSTAT (hw_bank.lpm ? 0x0D8UL : 0x06CUL)
#define CAP_ENDPTPRIME (hw_bank.lpm ? 0x0DCUL : 0x070UL)
@@ -1986,6 +1987,8 @@ static int ep_enable(struct usb_ep *ep,
do {
dbg_event(_usb_addr(mEp), "ENABLE", 0);
+ mEp->qh[mEp->dir].ptr->cap = 0;
+
if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
mEp->qh[mEp->dir].ptr->cap |= QH_IOS;
else if (mEp->type == USB_ENDPOINT_XFER_ISOC)
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 5c030b080d4c..381a53b3e11c 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -738,7 +738,6 @@ static struct fsg_dev *the_fsg;
static struct usb_gadget_driver fsg_driver;
static void close_backing_file(struct lun *curlun);
-static void close_all_backing_files(struct fsg_dev *fsg);
/*-------------------------------------------------------------------------*/
@@ -3593,12 +3592,10 @@ static int fsg_main_thread(void *fsg_)
fsg->thread_task = NULL;
spin_unlock_irq(&fsg->lock);
- /* In case we are exiting because of a signal, unregister the
- * gadget driver and close the backing file. */
- if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags)) {
+ /* If we are exiting because of a signal, unregister the
+ * gadget driver. */
+ if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
usb_gadget_unregister_driver(&fsg_driver);
- close_all_backing_files(fsg);
- }
/* Let the unbind and cleanup routines know the thread has exited */
complete_and_exit(&fsg->thread_notifier, 0);
@@ -3703,14 +3700,6 @@ static void close_backing_file(struct lun *curlun)
}
}
-static void close_all_backing_files(struct fsg_dev *fsg)
-{
- int i;
-
- for (i = 0; i < fsg->nluns; ++i)
- close_backing_file(&fsg->luns[i]);
-}
-
static ssize_t show_ro(struct device *dev, struct device_attribute *attr, char *buf)
{
@@ -3845,6 +3834,7 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
if (curlun->registered) {
device_remove_file(&curlun->dev, &dev_attr_ro);
device_remove_file(&curlun->dev, &dev_attr_file);
+ close_backing_file(curlun);
device_unregister(&curlun->dev);
curlun->registered = 0;
}
@@ -4190,7 +4180,6 @@ autoconf_fail:
out:
fsg->state = FSG_STATE_TERMINATED; // The thread is dead
fsg_unbind(gadget);
- close_all_backing_files(fsg);
complete(&fsg->thread_notifier);
return rc;
}
@@ -4284,7 +4273,6 @@ static void __exit fsg_cleanup(void)
/* Wait for the thread to finish up */
wait_for_completion(&fsg->thread_notifier);
- close_all_backing_files(fsg);
kref_put(&fsg->ref, fsg_release);
}
module_exit(fsg_cleanup);
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 57d9641c6bf8..a2db0e174f2c 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -3104,7 +3104,6 @@ static int omap_udc_resume(struct platform_device *dev)
/*-------------------------------------------------------------------------*/
static struct platform_driver udc_driver = {
- .probe = omap_udc_probe,
.remove = __exit_p(omap_udc_remove),
.suspend = omap_udc_suspend,
.resume = omap_udc_resume,
@@ -3122,7 +3121,7 @@ static int __init udc_init(void)
#endif
"%s\n", driver_desc,
use_dma ? " (dma)" : "");
- return platform_driver_register(&udc_driver);
+ return platform_driver_probe(&udc_driver, omap_udc_probe);
}
module_init(udc_init);
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 96d65ca06ecd..4007770f7ed2 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -175,12 +175,6 @@ static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p)
strlcpy(p->bus_info, dev_name(&dev->gadget->dev), sizeof p->bus_info);
}
-static u32 eth_get_link(struct net_device *net)
-{
- struct eth_dev *dev = netdev_priv(net);
- return dev->gadget->speed != USB_SPEED_UNKNOWN;
-}
-
/* REVISIT can also support:
* - WOL (by tracking suspends and issuing remote wakeup)
* - msglevel (implies updated messaging)
@@ -189,7 +183,7 @@ static u32 eth_get_link(struct net_device *net)
static struct ethtool_ops ops = {
.get_drvinfo = eth_get_drvinfo,
- .get_link = eth_get_link
+ .get_link = ethtool_op_get_link,
};
static void defer_kevent(struct eth_dev *dev, int flag)
diff --git a/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c
index 4154be375c7a..58c4d37d312a 100644
--- a/drivers/usb/gadget/usbstring.c
+++ b/drivers/usb/gadget/usbstring.c
@@ -38,7 +38,7 @@ static int utf8_to_utf16le(const char *s, __le16 *cp, unsigned len)
uchar = (c & 0x1f) << 6;
c = (u8) *s++;
- if ((c & 0xc0) != 0xc0)
+ if ((c & 0xc0) != 0x80)
goto fail;
c &= 0x3f;
uchar |= c;
@@ -49,13 +49,13 @@ static int utf8_to_utf16le(const char *s, __le16 *cp, unsigned len)
uchar = (c & 0x0f) << 12;
c = (u8) *s++;
- if ((c & 0xc0) != 0xc0)
+ if ((c & 0xc0) != 0x80)
goto fail;
c &= 0x3f;
uchar |= c << 6;
c = (u8) *s++;
- if ((c & 0xc0) != 0xc0)
+ if ((c & 0xc0) != 0x80)
goto fail;
c &= 0x3f;
uchar |= c;
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index ada5d2ba297b..556d0ec0c1f8 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -323,7 +323,7 @@ static int tt_available (
* already scheduled transactions
*/
if (125 < usecs) {
- int ufs = (usecs / 125) - 1;
+ int ufs = (usecs / 125);
int i;
for (i = uframe; i < (uframe + ufs) && i < 8; i++)
if (0 < tt_usecs[i]) {
diff --git a/drivers/usb/host/whci/asl.c b/drivers/usb/host/whci/asl.c
index 958751ccea43..c2050785a819 100644
--- a/drivers/usb/host/whci/asl.c
+++ b/drivers/usb/host/whci/asl.c
@@ -122,7 +122,8 @@ static uint32_t process_qset(struct whc *whc, struct whc_qset *qset)
process_inactive_qtd(whc, qset, td);
}
- update |= qset_add_qtds(whc, qset);
+ if (!qset->remove)
+ update |= qset_add_qtds(whc, qset);
done:
/*
@@ -254,23 +255,29 @@ int asl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags)
spin_lock_irqsave(&whc->lock, flags);
+ err = usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb);
+ if (err < 0) {
+ spin_unlock_irqrestore(&whc->lock, flags);
+ return err;
+ }
+
qset = get_qset(whc, urb, GFP_ATOMIC);
if (qset == NULL)
err = -ENOMEM;
else
err = qset_add_urb(whc, qset, urb, GFP_ATOMIC);
if (!err) {
- usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb);
if (!qset->in_sw_list)
asl_qset_insert_begin(whc, qset);
- }
+ } else
+ usb_hcd_unlink_urb_from_ep(&whc->wusbhc.usb_hcd, urb);
spin_unlock_irqrestore(&whc->lock, flags);
if (!err)
queue_work(whc->workqueue, &whc->async_work);
- return 0;
+ return err;
}
/**
diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c
index 1569afd6245b..e019a5058ab8 100644
--- a/drivers/usb/host/whci/hcd.c
+++ b/drivers/usb/host/whci/hcd.c
@@ -186,6 +186,28 @@ static void whc_endpoint_disable(struct usb_hcd *usb_hcd,
}
}
+static void whc_endpoint_reset(struct usb_hcd *usb_hcd,
+ struct usb_host_endpoint *ep)
+{
+ struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd);
+ struct whc *whc = wusbhc_to_whc(wusbhc);
+ struct whc_qset *qset;
+
+ qset = ep->hcpriv;
+ if (qset) {
+ qset->remove = 1;
+
+ if (usb_endpoint_xfer_bulk(&ep->desc)
+ || usb_endpoint_xfer_control(&ep->desc))
+ queue_work(whc->workqueue, &whc->async_work);
+ else
+ queue_work(whc->workqueue, &whc->periodic_work);
+
+ qset_reset(whc, qset);
+ }
+}
+
+
static struct hc_driver whc_hc_driver = {
.description = "whci-hcd",
.product_desc = "Wireless host controller",
@@ -200,6 +222,7 @@ static struct hc_driver whc_hc_driver = {
.urb_enqueue = whc_urb_enqueue,
.urb_dequeue = whc_urb_dequeue,
.endpoint_disable = whc_endpoint_disable,
+ .endpoint_reset = whc_endpoint_reset,
.hub_status_data = wusbhc_rh_status_data,
.hub_control = wusbhc_rh_control,
diff --git a/drivers/usb/host/whci/pzl.c b/drivers/usb/host/whci/pzl.c
index df8b85f07092..ff4ef9e910d9 100644
--- a/drivers/usb/host/whci/pzl.c
+++ b/drivers/usb/host/whci/pzl.c
@@ -128,7 +128,8 @@ static enum whc_update pzl_process_qset(struct whc *whc, struct whc_qset *qset)
process_inactive_qtd(whc, qset, td);
}
- update |= qset_add_qtds(whc, qset);
+ if (!qset->remove)
+ update |= qset_add_qtds(whc, qset);
done:
/*
@@ -282,23 +283,29 @@ int pzl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags)
spin_lock_irqsave(&whc->lock, flags);
+ err = usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb);
+ if (err < 0) {
+ spin_unlock_irqrestore(&whc->lock, flags);
+ return err;
+ }
+
qset = get_qset(whc, urb, GFP_ATOMIC);
if (qset == NULL)
err = -ENOMEM;
else
err = qset_add_urb(whc, qset, urb, GFP_ATOMIC);
if (!err) {
- usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb);
if (!qset->in_sw_list)
qset_insert_in_sw_list(whc, qset);
- }
+ } else
+ usb_hcd_unlink_urb_from_ep(&whc->wusbhc.usb_hcd, urb);
spin_unlock_irqrestore(&whc->lock, flags);
if (!err)
queue_work(whc->workqueue, &whc->periodic_work);
- return 0;
+ return err;
}
/**
@@ -353,7 +360,6 @@ void pzl_qset_delete(struct whc *whc, struct whc_qset *qset)
qset_delete(whc, qset);
}
-
/**
* pzl_init - initialize the periodic zone list
* @whc: the WHCI host controller
diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c
index 7be74314ee12..640b38fbd051 100644
--- a/drivers/usb/host/whci/qset.c
+++ b/drivers/usb/host/whci/qset.c
@@ -89,11 +89,16 @@ static void qset_fill_qh(struct whc_qset *qset, struct urb *urb)
QH_INFO3_TX_RATE_53_3
| QH_INFO3_TX_PWR(0) /* 0 == max power */
);
+
+ qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1);
}
/**
* qset_clear - clear fields in a qset so it may be reinserted into a
- * schedule
+ * schedule.
+ *
+ * The sequence number and current window are not cleared (see
+ * qset_reset()).
*/
void qset_clear(struct whc *whc, struct whc_qset *qset)
{
@@ -101,9 +106,8 @@ void qset_clear(struct whc *whc, struct whc_qset *qset)
qset->remove = 0;
qset->qh.link = cpu_to_le32(QH_LINK_NTDS(8) | QH_LINK_T);
- qset->qh.status = cpu_to_le16(QH_STATUS_ICUR(qset->td_start));
+ qset->qh.status = qset->qh.status & QH_STATUS_SEQ_MASK;
qset->qh.err_count = 0;
- qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1);
qset->qh.scratch[0] = 0;
qset->qh.scratch[1] = 0;
qset->qh.scratch[2] = 0;
@@ -114,6 +118,20 @@ void qset_clear(struct whc *whc, struct whc_qset *qset)
}
/**
+ * qset_reset - reset endpoint state in a qset.
+ *
+ * Clears the sequence number and current window. This qset must not
+ * be in the ASL or PZL.
+ */
+void qset_reset(struct whc *whc, struct whc_qset *qset)
+{
+ wait_for_completion(&qset->remove_complete);
+
+ qset->qh.status &= ~QH_STATUS_SEQ_MASK;
+ qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1);
+}
+
+/**
* get_qset - get the qset for an async endpoint
*
* A new qset is created if one does not already exist.
diff --git a/drivers/usb/host/whci/whcd.h b/drivers/usb/host/whci/whcd.h
index d3543a181dc9..24e94d983c5e 100644
--- a/drivers/usb/host/whci/whcd.h
+++ b/drivers/usb/host/whci/whcd.h
@@ -184,6 +184,7 @@ void qset_free(struct whc *whc, struct whc_qset *qset);
struct whc_qset *get_qset(struct whc *whc, struct urb *urb, gfp_t mem_flags);
void qset_delete(struct whc *whc, struct whc_qset *qset);
void qset_clear(struct whc *whc, struct whc_qset *qset);
+void qset_reset(struct whc *whc, struct whc_qset *qset);
int qset_add_urb(struct whc *whc, struct whc_qset *qset, struct urb *urb,
gfp_t mem_flags);
void qset_free_std(struct whc *whc, struct whc_std *std);
diff --git a/drivers/usb/host/whci/whci-hc.h b/drivers/usb/host/whci/whci-hc.h
index 51df7e313b38..794dba0d0f0a 100644
--- a/drivers/usb/host/whci/whci-hc.h
+++ b/drivers/usb/host/whci/whci-hc.h
@@ -185,6 +185,7 @@ struct whc_qhead {
#define QH_STATUS_FLOW_CTRL (1 << 15)
#define QH_STATUS_ICUR(i) ((i) << 5)
#define QH_STATUS_TO_ICUR(s) (((s) >> 5) & 0x7)
+#define QH_STATUS_SEQ_MASK 0x1f
/**
* usb_pipe_to_qh_type - USB core pipe type to QH transfer type
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
index 569ef0fed0f6..1976e9b41800 100644
--- a/drivers/usb/musb/cppi_dma.c
+++ b/drivers/usb/musb/cppi_dma.c
@@ -579,6 +579,7 @@ cppi_next_tx_segment(struct musb *musb, struct cppi_channel *tx)
* trigger the "send a ZLP?" confusion.
*/
rndis = (maxpacket & 0x3f) == 0
+ && length > maxpacket
&& length < 0xffff
&& (length % maxpacket) != 0;
@@ -1228,27 +1229,7 @@ void cppi_completion(struct musb *musb, u32 rx, u32 tx)
hw_ep = tx_ch->hw_ep;
- /* Peripheral role never repurposes the
- * endpoint, so immediate completion is
- * safe. Host role waits for the fifo
- * to empty (TXPKTRDY irq) before going
- * to the next queued bulk transfer.
- */
- if (is_host_active(cppi->musb)) {
-#if 0
- /* WORKAROUND because we may
- * not always get TXKPTRDY ...
- */
- int csr;
-
- csr = musb_readw(hw_ep->regs,
- MUSB_TXCSR);
- if (csr & MUSB_TXCSR_TXPKTRDY)
-#endif
- completed = false;
- }
- if (completed)
- musb_dma_completion(musb, index + 1, 1);
+ musb_dma_completion(musb, index + 1, 1);
} else {
/* Bigger transfer than we could fit in
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 338cd1611ab3..4000cf6d1e81 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -2170,32 +2170,28 @@ static int musb_suspend(struct platform_device *pdev, pm_message_t message)
return 0;
}
-static int musb_resume(struct platform_device *pdev)
+static int musb_resume_early(struct platform_device *pdev)
{
- unsigned long flags;
struct musb *musb = dev_to_musb(&pdev->dev);
if (!musb->clock)
return 0;
- spin_lock_irqsave(&musb->lock, flags);
-
if (musb->set_clock)
musb->set_clock(musb->clock, 1);
else
clk_enable(musb->clock);
/* for static cmos like DaVinci, register values were preserved
- * unless for some reason the whole soc powered down and we're
- * not treating that as a whole-system restart (e.g. swsusp)
+ * unless for some reason the whole soc powered down or the USB
+ * module got reset through the PSC (vs just being disabled).
*/
- spin_unlock_irqrestore(&musb->lock, flags);
return 0;
}
#else
#define musb_suspend NULL
-#define musb_resume NULL
+#define musb_resume_early NULL
#endif
static struct platform_driver musb_driver = {
@@ -2207,7 +2203,7 @@ static struct platform_driver musb_driver = {
.remove = __devexit_p(musb_remove),
.shutdown = musb_shutdown,
.suspend = musb_suspend,
- .resume = musb_resume,
+ .resume_early = musb_resume_early,
};
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index c7ebd0867fcc..f79440cdfe7e 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -165,9 +165,15 @@ static void nuke(struct musb_ep *ep, const int status)
if (is_dma_capable() && ep->dma) {
struct dma_controller *c = ep->musb->dma_controller;
int value;
+
if (ep->is_in) {
+ /*
+ * The programming guide says that we must not clear
+ * the DMAMODE bit before DMAENAB, so we only
+ * clear it in the second write...
+ */
musb_writew(epio, MUSB_TXCSR,
- 0 | MUSB_TXCSR_FLUSHFIFO);
+ MUSB_TXCSR_DMAMODE | MUSB_TXCSR_FLUSHFIFO);
musb_writew(epio, MUSB_TXCSR,
0 | MUSB_TXCSR_FLUSHFIFO);
} else {
@@ -230,7 +236,7 @@ static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep)
| IN token(s) are recd from Host.
| -> DMA interrupt on completion
| calls TxAvail.
- | -> stop DMA, ~DmaEenab,
+ | -> stop DMA, ~DMAENAB,
| -> set TxPktRdy for last short pkt or zlp
| -> Complete Request
| -> Continue next request (call txstate)
@@ -315,9 +321,17 @@ static void txstate(struct musb *musb, struct musb_request *req)
request->dma, request_size);
if (use_dma) {
if (musb_ep->dma->desired_mode == 0) {
- /* ASSERT: DMAENAB is clear */
- csr &= ~(MUSB_TXCSR_AUTOSET |
- MUSB_TXCSR_DMAMODE);
+ /*
+ * We must not clear the DMAMODE bit
+ * before the DMAENAB bit -- and the
+ * latter doesn't always get cleared
+ * before we get here...
+ */
+ csr &= ~(MUSB_TXCSR_AUTOSET
+ | MUSB_TXCSR_DMAENAB);
+ musb_writew(epio, MUSB_TXCSR, csr
+ | MUSB_TXCSR_P_WZC_BITS);
+ csr &= ~MUSB_TXCSR_DMAMODE;
csr |= (MUSB_TXCSR_DMAENAB |
MUSB_TXCSR_MODE);
/* against programming guide */
@@ -334,10 +348,7 @@ static void txstate(struct musb *musb, struct musb_request *req)
#elif defined(CONFIG_USB_TI_CPPI_DMA)
/* program endpoint CSR first, then setup DMA */
- csr &= ~(MUSB_TXCSR_AUTOSET
- | MUSB_TXCSR_DMAMODE
- | MUSB_TXCSR_P_UNDERRUN
- | MUSB_TXCSR_TXPKTRDY);
+ csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY);
csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_DMAENAB;
musb_writew(epio, MUSB_TXCSR,
(MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN)
@@ -364,8 +375,8 @@ static void txstate(struct musb *musb, struct musb_request *req)
if (!use_dma) {
c->channel_release(musb_ep->dma);
musb_ep->dma = NULL;
- /* ASSERT: DMAENAB clear */
- csr &= ~(MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE);
+ csr &= ~MUSB_TXCSR_DMAENAB;
+ musb_writew(epio, MUSB_TXCSR, csr);
/* invariant: prequest->buf is non-null */
}
#elif defined(CONFIG_USB_TUSB_OMAP_DMA)
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 499c431a6d62..db1b57415ec7 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -4,6 +4,7 @@
* Copyright 2005 Mentor Graphics Corporation
* Copyright (C) 2005-2006 by Texas Instruments
* Copyright (C) 2006-2007 Nokia Corporation
+ * Copyright (C) 2008-2009 MontaVista Software, Inc. <source@mvista.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -96,8 +97,8 @@
static void musb_ep_program(struct musb *musb, u8 epnum,
- struct urb *urb, unsigned int nOut,
- u8 *buf, u32 len);
+ struct urb *urb, int is_out,
+ u8 *buf, u32 offset, u32 len);
/*
* Clear TX fifo. Needed to avoid BABBLE errors.
@@ -125,6 +126,29 @@ static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep)
}
}
+static void musb_h_ep0_flush_fifo(struct musb_hw_ep *ep)
+{
+ void __iomem *epio = ep->regs;
+ u16 csr;
+ int retries = 5;
+
+ /* scrub any data left in the fifo */
+ do {
+ csr = musb_readw(epio, MUSB_TXCSR);
+ if (!(csr & (MUSB_CSR0_TXPKTRDY | MUSB_CSR0_RXPKTRDY)))
+ break;
+ musb_writew(epio, MUSB_TXCSR, MUSB_CSR0_FLUSHFIFO);
+ csr = musb_readw(epio, MUSB_TXCSR);
+ udelay(10);
+ } while (--retries);
+
+ WARN(!retries, "Could not flush host TX%d fifo: csr: %04x\n",
+ ep->epnum, csr);
+
+ /* and reset for the next transfer */
+ musb_writew(epio, MUSB_TXCSR, 0);
+}
+
/*
* Start transmit. Caller is responsible for locking shared resources.
* musb must be locked.
@@ -145,13 +169,15 @@ static inline void musb_h_tx_start(struct musb_hw_ep *ep)
}
-static inline void cppi_host_txdma_start(struct musb_hw_ep *ep)
+static inline void musb_h_tx_dma_start(struct musb_hw_ep *ep)
{
u16 txcsr;
/* NOTE: no locks here; caller should lock and select EP */
txcsr = musb_readw(ep->regs, MUSB_TXCSR);
txcsr |= MUSB_TXCSR_DMAENAB | MUSB_TXCSR_H_WZC_BITS;
+ if (is_cppi_enabled())
+ txcsr |= MUSB_TXCSR_DMAMODE;
musb_writew(ep->regs, MUSB_TXCSR, txcsr);
}
@@ -166,9 +192,10 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
{
u16 frame;
u32 len;
- void *buf;
void __iomem *mbase = musb->mregs;
struct urb *urb = next_urb(qh);
+ void *buf = urb->transfer_buffer;
+ u32 offset = 0;
struct musb_hw_ep *hw_ep = qh->hw_ep;
unsigned pipe = urb->pipe;
u8 address = usb_pipedevice(pipe);
@@ -191,7 +218,7 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
case USB_ENDPOINT_XFER_ISOC:
qh->iso_idx = 0;
qh->frame = 0;
- buf = urb->transfer_buffer + urb->iso_frame_desc[0].offset;
+ offset = urb->iso_frame_desc[0].offset;
len = urb->iso_frame_desc[0].length;
break;
default: /* bulk, interrupt */
@@ -209,14 +236,14 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
case USB_ENDPOINT_XFER_ISOC: s = "-iso"; break;
default: s = "-intr"; break;
}; s; }),
- epnum, buf, len);
+ epnum, buf + offset, len);
/* Configure endpoint */
if (is_in || hw_ep->is_shared_fifo)
hw_ep->in_qh = qh;
else
hw_ep->out_qh = qh;
- musb_ep_program(musb, epnum, urb, !is_in, buf, len);
+ musb_ep_program(musb, epnum, urb, !is_in, buf, offset, len);
/* transmit may have more work: start it when it is time */
if (is_in)
@@ -227,7 +254,6 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
case USB_ENDPOINT_XFER_ISOC:
case USB_ENDPOINT_XFER_INT:
DBG(3, "check whether there's still time for periodic Tx\n");
- qh->iso_idx = 0;
frame = musb_readw(mbase, MUSB_FRAME);
/* FIXME this doesn't implement that scheduling policy ...
* or handle framecounter wrapping
@@ -256,7 +282,7 @@ start:
if (!hw_ep->tx_channel)
musb_h_tx_start(hw_ep);
else if (is_cppi_enabled() || tusb_dma_omap())
- cppi_host_txdma_start(hw_ep);
+ musb_h_tx_dma_start(hw_ep);
}
}
@@ -567,10 +593,17 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep)
csr = musb_readw(ep->regs, MUSB_TXCSR);
if (csr & MUSB_TXCSR_MODE) {
musb_h_tx_flush_fifo(ep);
+ csr = musb_readw(ep->regs, MUSB_TXCSR);
musb_writew(ep->regs, MUSB_TXCSR,
- MUSB_TXCSR_FRCDATATOG);
+ csr | MUSB_TXCSR_FRCDATATOG);
}
- /* clear mode (and everything else) to enable Rx */
+
+ /*
+ * Clear the MODE bit (and everything else) to enable Rx.
+ * NOTE: we mustn't clear the DMAMODE bit before DMAENAB.
+ */
+ if (csr & MUSB_TXCSR_DMAMODE)
+ musb_writew(ep->regs, MUSB_TXCSR, MUSB_TXCSR_DMAMODE);
musb_writew(ep->regs, MUSB_TXCSR, 0);
/* scrub all previous state, clearing toggle */
@@ -601,14 +634,68 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep)
ep->rx_reinit = 0;
}
+static bool musb_tx_dma_program(struct dma_controller *dma,
+ struct musb_hw_ep *hw_ep, struct musb_qh *qh,
+ struct urb *urb, u32 offset, u32 length)
+{
+ struct dma_channel *channel = hw_ep->tx_channel;
+ void __iomem *epio = hw_ep->regs;
+ u16 pkt_size = qh->maxpacket;
+ u16 csr;
+ u8 mode;
+
+#ifdef CONFIG_USB_INVENTRA_DMA
+ if (length > channel->max_len)
+ length = channel->max_len;
+
+ csr = musb_readw(epio, MUSB_TXCSR);
+ if (length > pkt_size) {
+ mode = 1;
+ csr |= MUSB_TXCSR_AUTOSET
+ | MUSB_TXCSR_DMAMODE
+ | MUSB_TXCSR_DMAENAB;
+ } else {
+ mode = 0;
+ csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAMODE);
+ csr |= MUSB_TXCSR_DMAENAB; /* against programmer's guide */
+ }
+ channel->desired_mode = mode;
+ musb_writew(epio, MUSB_TXCSR, csr);
+#else
+ if (!is_cppi_enabled() && !tusb_dma_omap())
+ return false;
+
+ channel->actual_len = 0;
+
+ /*
+ * TX uses "RNDIS" mode automatically but needs help
+ * to identify the zero-length-final-packet case.
+ */
+ mode = (urb->transfer_flags & URB_ZERO_PACKET) ? 1 : 0;
+#endif
+
+ qh->segsize = length;
+
+ if (!dma->channel_program(channel, pkt_size, mode,
+ urb->transfer_dma + offset, length)) {
+ dma->channel_release(channel);
+ hw_ep->tx_channel = NULL;
+
+ csr = musb_readw(epio, MUSB_TXCSR);
+ csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB);
+ musb_writew(epio, MUSB_TXCSR, csr | MUSB_TXCSR_H_WZC_BITS);
+ return false;
+ }
+ return true;
+}
/*
* Program an HDRC endpoint as per the given URB
* Context: irqs blocked, controller lock held
*/
static void musb_ep_program(struct musb *musb, u8 epnum,
- struct urb *urb, unsigned int is_out,
- u8 *buf, u32 len)
+ struct urb *urb, int is_out,
+ u8 *buf, u32 offset, u32 len)
{
struct dma_controller *dma_controller;
struct dma_channel *dma_channel;
@@ -667,12 +754,17 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
/* general endpoint setup */
if (epnum) {
- /* ASSERT: TXCSR_DMAENAB was already cleared */
-
/* flush all old state, set default */
musb_h_tx_flush_fifo(hw_ep);
+
+ /*
+ * We must not clear the DMAMODE bit before or in
+ * the same cycle with the DMAENAB bit, so we clear
+ * the latter first...
+ */
csr &= ~(MUSB_TXCSR_H_NAKTIMEOUT
- | MUSB_TXCSR_DMAMODE
+ | MUSB_TXCSR_AUTOSET
+ | MUSB_TXCSR_DMAENAB
| MUSB_TXCSR_FRCDATATOG
| MUSB_TXCSR_H_RXSTALL
| MUSB_TXCSR_H_ERROR
@@ -680,24 +772,20 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
);
csr |= MUSB_TXCSR_MODE;
- if (usb_gettoggle(urb->dev,
- qh->epnum, 1))
+ if (usb_gettoggle(urb->dev, qh->epnum, 1))
csr |= MUSB_TXCSR_H_WR_DATATOGGLE
| MUSB_TXCSR_H_DATATOGGLE;
else
csr |= MUSB_TXCSR_CLRDATATOG;
- /* twice in case of double packet buffering */
musb_writew(epio, MUSB_TXCSR, csr);
/* REVISIT may need to clear FLUSHFIFO ... */
+ csr &= ~MUSB_TXCSR_DMAMODE;
musb_writew(epio, MUSB_TXCSR, csr);
csr = musb_readw(epio, MUSB_TXCSR);
} else {
/* endpoint 0: just flush */
- musb_writew(epio, MUSB_CSR0,
- csr | MUSB_CSR0_FLUSHFIFO);
- musb_writew(epio, MUSB_CSR0,
- csr | MUSB_CSR0_FLUSHFIFO);
+ musb_h_ep0_flush_fifo(hw_ep);
}
/* target addr and (for multipoint) hub addr/port */
@@ -734,113 +822,14 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
else
load_count = min((u32) packet_sz, len);
-#ifdef CONFIG_USB_INVENTRA_DMA
- if (dma_channel) {
-
- /* clear previous state */
- csr = musb_readw(epio, MUSB_TXCSR);
- csr &= ~(MUSB_TXCSR_AUTOSET
- | MUSB_TXCSR_DMAMODE
- | MUSB_TXCSR_DMAENAB);
- csr |= MUSB_TXCSR_MODE;
- musb_writew(epio, MUSB_TXCSR,
- csr | MUSB_TXCSR_MODE);
-
- qh->segsize = min(len, dma_channel->max_len);
-
- if (qh->segsize <= packet_sz)
- dma_channel->desired_mode = 0;
- else
- dma_channel->desired_mode = 1;
-
-
- if (dma_channel->desired_mode == 0) {
- csr &= ~(MUSB_TXCSR_AUTOSET
- | MUSB_TXCSR_DMAMODE);
- csr |= (MUSB_TXCSR_DMAENAB);
- /* against programming guide */
- } else
- csr |= (MUSB_TXCSR_AUTOSET
- | MUSB_TXCSR_DMAENAB
- | MUSB_TXCSR_DMAMODE);
-
- musb_writew(epio, MUSB_TXCSR, csr);
-
- dma_ok = dma_controller->channel_program(
- dma_channel, packet_sz,
- dma_channel->desired_mode,
- urb->transfer_dma,
- qh->segsize);
- if (dma_ok) {
- load_count = 0;
- } else {
- dma_controller->channel_release(dma_channel);
- if (is_out)
- hw_ep->tx_channel = NULL;
- else
- hw_ep->rx_channel = NULL;
- dma_channel = NULL;
- }
- }
-#endif
-
- /* candidate for DMA */
- if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) {
-
- /* program endpoint CSRs first, then setup DMA.
- * assume CPPI setup succeeds.
- * defer enabling dma.
- */
- csr = musb_readw(epio, MUSB_TXCSR);
- csr &= ~(MUSB_TXCSR_AUTOSET
- | MUSB_TXCSR_DMAMODE
- | MUSB_TXCSR_DMAENAB);
- csr |= MUSB_TXCSR_MODE;
- musb_writew(epio, MUSB_TXCSR,
- csr | MUSB_TXCSR_MODE);
-
- dma_channel->actual_len = 0L;
- qh->segsize = len;
-
- /* TX uses "rndis" mode automatically, but needs help
- * to identify the zero-length-final-packet case.
- */
- dma_ok = dma_controller->channel_program(
- dma_channel, packet_sz,
- (urb->transfer_flags
- & URB_ZERO_PACKET)
- == URB_ZERO_PACKET,
- urb->transfer_dma,
- qh->segsize);
- if (dma_ok) {
- load_count = 0;
- } else {
- dma_controller->channel_release(dma_channel);
- hw_ep->tx_channel = NULL;
- dma_channel = NULL;
-
- /* REVISIT there's an error path here that
- * needs handling: can't do dma, but
- * there's no pio buffer address...
- */
- }
- }
+ if (dma_channel && musb_tx_dma_program(dma_controller,
+ hw_ep, qh, urb, offset, len))
+ load_count = 0;
if (load_count) {
- /* ASSERT: TXCSR_DMAENAB was already cleared */
-
/* PIO to load FIFO */
qh->segsize = load_count;
musb_write_fifo(hw_ep, load_count, buf);
- csr = musb_readw(epio, MUSB_TXCSR);
- csr &= ~(MUSB_TXCSR_DMAENAB
- | MUSB_TXCSR_DMAMODE
- | MUSB_TXCSR_AUTOSET);
- /* write CSR */
- csr |= MUSB_TXCSR_MODE;
-
- if (epnum)
- musb_writew(epio, MUSB_TXCSR, csr);
}
/* re-enable interrupt */
@@ -895,7 +884,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
dma_channel, packet_sz,
!(urb->transfer_flags
& URB_SHORT_NOT_OK),
- urb->transfer_dma,
+ urb->transfer_dma + offset,
qh->segsize);
if (!dma_ok) {
dma_controller->channel_release(
@@ -1063,11 +1052,7 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb)
csr &= ~MUSB_CSR0_H_NAKTIMEOUT;
musb_writew(epio, MUSB_CSR0, csr);
} else {
- csr |= MUSB_CSR0_FLUSHFIFO;
- musb_writew(epio, MUSB_CSR0, csr);
- musb_writew(epio, MUSB_CSR0, csr);
- csr &= ~MUSB_CSR0_H_NAKTIMEOUT;
- musb_writew(epio, MUSB_CSR0, csr);
+ musb_h_ep0_flush_fifo(hw_ep);
}
musb_writeb(epio, MUSB_NAKLIMIT0, 0);
@@ -1081,10 +1066,7 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb)
* SHOULD NEVER HAPPEN! */
ERR("no URB for end 0\n");
- musb_writew(epio, MUSB_CSR0, MUSB_CSR0_FLUSHFIFO);
- musb_writew(epio, MUSB_CSR0, MUSB_CSR0_FLUSHFIFO);
- musb_writew(epio, MUSB_CSR0, 0);
-
+ musb_h_ep0_flush_fifo(hw_ep);
goto done;
}
@@ -1145,8 +1127,8 @@ void musb_host_tx(struct musb *musb, u8 epnum)
int pipe;
bool done = false;
u16 tx_csr;
- size_t wLength = 0;
- u8 *buf = NULL;
+ size_t length = 0;
+ size_t offset = 0;
struct urb *urb;
struct musb_hw_ep *hw_ep = musb->endpoints + epnum;
void __iomem *epio = hw_ep->regs;
@@ -1164,7 +1146,7 @@ void musb_host_tx(struct musb *musb, u8 epnum)
/* with CPPI, DMA sometimes triggers "extra" irqs */
if (!urb) {
DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr);
- goto finish;
+ return;
}
pipe = urb->pipe;
@@ -1201,7 +1183,7 @@ void musb_host_tx(struct musb *musb, u8 epnum)
musb_writew(epio, MUSB_TXCSR,
MUSB_TXCSR_H_WZC_BITS
| MUSB_TXCSR_TXPKTRDY);
- goto finish;
+ return;
}
if (status) {
@@ -1233,29 +1215,89 @@ void musb_host_tx(struct musb *musb, u8 epnum)
/* second cppi case */
if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr);
- goto finish;
+ return;
+ }
+
+ if (is_dma_capable() && dma && !status) {
+ /*
+ * DMA has completed. But if we're using DMA mode 1 (multi
+ * packet DMA), we need a terminal TXPKTRDY interrupt before
+ * we can consider this transfer completed, lest we trash
+ * its last packet when writing the next URB's data. So we
+ * switch back to mode 0 to get that interrupt; we'll come
+ * back here once it happens.
+ */
+ if (tx_csr & MUSB_TXCSR_DMAMODE) {
+ /*
+ * We shouldn't clear DMAMODE with DMAENAB set; so
+ * clear them in a safe order. That should be OK
+ * once TXPKTRDY has been set (and I've never seen
+ * it being 0 at this moment -- DMA interrupt latency
+ * is significant) but if it hasn't been then we have
+ * no choice but to stop being polite and ignore the
+ * programmer's guide... :-)
+ *
+ * Note that we must write TXCSR with TXPKTRDY cleared
+ * in order not to re-trigger the packet send (this bit
+ * can't be cleared by CPU), and there's another caveat:
+ * TXPKTRDY may be set shortly and then cleared in the
+ * double-buffered FIFO mode, so we do an extra TXCSR
+ * read for debouncing...
+ */
+ tx_csr &= musb_readw(epio, MUSB_TXCSR);
+ if (tx_csr & MUSB_TXCSR_TXPKTRDY) {
+ tx_csr &= ~(MUSB_TXCSR_DMAENAB |
+ MUSB_TXCSR_TXPKTRDY);
+ musb_writew(epio, MUSB_TXCSR,
+ tx_csr | MUSB_TXCSR_H_WZC_BITS);
+ }
+ tx_csr &= ~(MUSB_TXCSR_DMAMODE |
+ MUSB_TXCSR_TXPKTRDY);
+ musb_writew(epio, MUSB_TXCSR,
+ tx_csr | MUSB_TXCSR_H_WZC_BITS);
+
+ /*
+ * There is no guarantee that we'll get an interrupt
+ * after clearing DMAMODE as we might have done this
+ * too late (after TXPKTRDY was cleared by controller).
+ * Re-read TXCSR as we have spoiled its previous value.
+ */
+ tx_csr = musb_readw(epio, MUSB_TXCSR);
+ }
+ /*
+ * We may get here from a DMA completion or TXPKTRDY interrupt.
+ * In any case, we must check the FIFO status here and bail out
+ * only if the FIFO still has data -- that should prevent the
+ * "missed" TXPKTRDY interrupts and deal with double-buffered
+ * FIFO mode too...
+ */
+ if (tx_csr & (MUSB_TXCSR_FIFONOTEMPTY | MUSB_TXCSR_TXPKTRDY)) {
+ DBG(2, "DMA complete but packet still in FIFO, "
+ "CSR %04x\n", tx_csr);
+ return;
+ }
}
- /* REVISIT this looks wrong... */
if (!status || dma || usb_pipeisoc(pipe)) {
if (dma)
- wLength = dma->actual_len;
+ length = dma->actual_len;
else
- wLength = qh->segsize;
- qh->offset += wLength;
+ length = qh->segsize;
+ qh->offset += length;
if (usb_pipeisoc(pipe)) {
struct usb_iso_packet_descriptor *d;
d = urb->iso_frame_desc + qh->iso_idx;
- d->actual_length = qh->segsize;
+ d->actual_length = length;
+ d->status = status;
if (++qh->iso_idx >= urb->number_of_packets) {
done = true;
} else {
d++;
- buf = urb->transfer_buffer + d->offset;
- wLength = d->length;
+ offset = d->offset;
+ length = d->length;
}
} else if (dma) {
done = true;
@@ -1268,10 +1310,8 @@ void musb_host_tx(struct musb *musb, u8 epnum)
& URB_ZERO_PACKET))
done = true;
if (!done) {
- buf = urb->transfer_buffer
- + qh->offset;
- wLength = urb->transfer_buffer_length
- - qh->offset;
+ offset = qh->offset;
+ length = urb->transfer_buffer_length - offset;
}
}
}
@@ -1290,28 +1330,31 @@ void musb_host_tx(struct musb *musb, u8 epnum)
urb->status = status;
urb->actual_length = qh->offset;
musb_advance_schedule(musb, urb, hw_ep, USB_DIR_OUT);
+ return;
+ } else if (usb_pipeisoc(pipe) && dma) {
+ if (musb_tx_dma_program(musb->dma_controller, hw_ep, qh, urb,
+ offset, length))
+ return;
+ } else if (tx_csr & MUSB_TXCSR_DMAENAB) {
+ DBG(1, "not complete, but DMA enabled?\n");
+ return;
+ }
- } else if (!(tx_csr & MUSB_TXCSR_DMAENAB)) {
- /* WARN_ON(!buf); */
-
- /* REVISIT: some docs say that when hw_ep->tx_double_buffered,
- * (and presumably, fifo is not half-full) we should write TWO
- * packets before updating TXCSR ... other docs disagree ...
- */
- /* PIO: start next packet in this URB */
- if (wLength > qh->maxpacket)
- wLength = qh->maxpacket;
- musb_write_fifo(hw_ep, wLength, buf);
- qh->segsize = wLength;
-
- musb_ep_select(mbase, epnum);
- musb_writew(epio, MUSB_TXCSR,
- MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
- } else
- DBG(1, "not complete, but dma enabled?\n");
+ /*
+ * PIO: start next packet in this URB.
+ *
+ * REVISIT: some docs say that when hw_ep->tx_double_buffered,
+ * (and presumably, FIFO is not half-full) we should write *two*
+ * packets before updating TXCSR; other docs disagree...
+ */
+ if (length > qh->maxpacket)
+ length = qh->maxpacket;
+ musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset);
+ qh->segsize = length;
-finish:
- return;
+ musb_ep_select(mbase, epnum);
+ musb_writew(epio, MUSB_TXCSR,
+ MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
}
@@ -1841,7 +1884,7 @@ static int musb_urb_enqueue(
unsigned long flags;
struct musb *musb = hcd_to_musb(hcd);
struct usb_host_endpoint *hep = urb->ep;
- struct musb_qh *qh = hep->hcpriv;
+ struct musb_qh *qh;
struct usb_endpoint_descriptor *epd = &hep->desc;
int ret;
unsigned type_reg;
@@ -1853,22 +1896,21 @@ static int musb_urb_enqueue(
spin_lock_irqsave(&musb->lock, flags);
ret = usb_hcd_link_urb_to_ep(hcd, urb);
+ qh = ret ? NULL : hep->hcpriv;
+ if (qh)
+ urb->hcpriv = qh;
spin_unlock_irqrestore(&musb->lock, flags);
- if (ret)
- return ret;
/* DMA mapping was already done, if needed, and this urb is on
- * hep->urb_list ... so there's little to do unless hep wasn't
- * yet scheduled onto a live qh.
+ * hep->urb_list now ... so we're done, unless hep wasn't yet
+ * scheduled onto a live qh.
*
* REVISIT best to keep hep->hcpriv valid until the endpoint gets
* disabled, testing for empty qh->ring and avoiding qh setup costs
* except for the first urb queued after a config change.
*/
- if (qh) {
- urb->hcpriv = qh;
- return 0;
- }
+ if (qh || ret)
+ return ret;
/* Allocate and initialize qh, minimizing the work done each time
* hw_ep gets reprogrammed, or with irqs blocked. Then schedule it.
@@ -2044,7 +2086,7 @@ static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh, int is_in)
* endpoint's irq status here to avoid bogus irqs.
* clearing that status is platform-specific...
*/
- } else {
+ } else if (ep->epnum) {
musb_h_tx_flush_fifo(ep);
csr = musb_readw(epio, MUSB_TXCSR);
csr &= ~(MUSB_TXCSR_AUTOSET
@@ -2058,6 +2100,8 @@ static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh, int is_in)
musb_writew(epio, MUSB_TXCSR, csr);
/* flush cpu writebuffer */
csr = musb_readw(epio, MUSB_TXCSR);
+ } else {
+ musb_h_ep0_flush_fifo(ep);
}
if (status == 0)
musb_advance_schedule(ep->musb, urb, ep, is_in);
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index 8662e9e159c3..5e83f96d6b77 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -195,30 +195,32 @@ static int dma_channel_abort(struct dma_channel *channel)
void __iomem *mbase = musb_channel->controller->base;
u8 bchannel = musb_channel->idx;
+ int offset;
u16 csr;
if (channel->status == MUSB_DMA_STATUS_BUSY) {
if (musb_channel->transmit) {
-
- csr = musb_readw(mbase,
- MUSB_EP_OFFSET(musb_channel->epnum,
- MUSB_TXCSR));
- csr &= ~(MUSB_TXCSR_AUTOSET |
- MUSB_TXCSR_DMAENAB |
- MUSB_TXCSR_DMAMODE);
- musb_writew(mbase,
- MUSB_EP_OFFSET(musb_channel->epnum, MUSB_TXCSR),
- csr);
+ offset = MUSB_EP_OFFSET(musb_channel->epnum,
+ MUSB_TXCSR);
+
+ /*
+ * The programming guide says that we must clear
+ * the DMAENAB bit before the DMAMODE bit...
+ */
+ csr = musb_readw(mbase, offset);
+ csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB);
+ musb_writew(mbase, offset, csr);
+ csr &= ~MUSB_TXCSR_DMAMODE;
+ musb_writew(mbase, offset, csr);
} else {
- csr = musb_readw(mbase,
- MUSB_EP_OFFSET(musb_channel->epnum,
- MUSB_RXCSR));
+ offset = MUSB_EP_OFFSET(musb_channel->epnum,
+ MUSB_RXCSR);
+
+ csr = musb_readw(mbase, offset);
csr &= ~(MUSB_RXCSR_AUTOCLEAR |
MUSB_RXCSR_DMAENAB |
MUSB_RXCSR_DMAMODE);
- musb_writew(mbase,
- MUSB_EP_OFFSET(musb_channel->epnum, MUSB_RXCSR),
- csr);
+ musb_writew(mbase, offset, csr);
}
musb_writew(mbase,
@@ -296,20 +298,28 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
&& ((channel->desired_mode == 0)
|| (channel->actual_len &
(musb_channel->max_packet_sz - 1)))
- ) {
+ ) {
+ u8 epnum = musb_channel->epnum;
+ int offset = MUSB_EP_OFFSET(epnum,
+ MUSB_TXCSR);
+ u16 txcsr;
+
+ /*
+ * The programming guide says that we
+ * must clear DMAENAB before DMAMODE.
+ */
+ musb_ep_select(mbase, epnum);
+ txcsr = musb_readw(mbase, offset);
+ txcsr &= ~(MUSB_TXCSR_DMAENAB
+ | MUSB_TXCSR_AUTOSET);
+ musb_writew(mbase, offset, txcsr);
/* Send out the packet */
- musb_ep_select(mbase,
- musb_channel->epnum);
- musb_writew(mbase, MUSB_EP_OFFSET(
- musb_channel->epnum,
- MUSB_TXCSR),
- MUSB_TXCSR_TXPKTRDY);
- } else {
- musb_dma_completion(
- musb,
- musb_channel->epnum,
- musb_channel->transmit);
+ txcsr &= ~MUSB_TXCSR_DMAMODE;
+ txcsr |= MUSB_TXCSR_TXPKTRDY;
+ musb_writew(mbase, offset, txcsr);
}
+ musb_dma_completion(musb, musb_channel->epnum,
+ musb_channel->transmit);
}
}
}
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 901dffdf23b1..60924ce08493 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -3,7 +3,6 @@
* Some code has been taken from tusb6010.c
* Copyrights for that are attributable to:
* Copyright (C) 2006 Nokia Corporation
- * Jarkko Nikula <jarkko.nikula@nokia.com>
* Tony Lindgren <tony@atomide.com>
*
* This file is part of the Inventra Controller Driver for Linux.
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 9e20fd070d71..4ac1477d3569 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -2,7 +2,6 @@
* TUSB6010 USB 2.0 OTG Dual Role controller
*
* Copyright (C) 2006 Nokia Corporation
- * Jarkko Nikula <jarkko.nikula@nokia.com>
* Tony Lindgren <tony@atomide.com>
*
* This program is free software; you can redistribute it and/or modify
diff --git a/drivers/usb/musb/tusb6010.h b/drivers/usb/musb/tusb6010.h
index ab8c96286ce6..35c933a5d991 100644
--- a/drivers/usb/musb/tusb6010.h
+++ b/drivers/usb/musb/tusb6010.h
@@ -2,7 +2,6 @@
* Definitions for TUSB6010 USB 2.0 OTG Dual Role controller
*
* Copyright (C) 2006 Nokia Corporation
- * Jarkko Nikula <jarkko.nikula@nokia.com>
* Tony Lindgren <tony@atomide.com>
*
* This program is free software; you can redistribute it and/or modify
diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c
index 4b933f646f2e..c567168f89af 100644
--- a/drivers/usb/otg/nop-usb-xceiv.c
+++ b/drivers/usb/otg/nop-usb-xceiv.c
@@ -36,14 +36,14 @@ struct nop_usb_xceiv {
struct device *dev;
};
-static u64 nop_xceiv_dmamask = DMA_32BIT_MASK;
+static u64 nop_xceiv_dmamask = DMA_BIT_MASK(32);
static struct platform_device nop_xceiv_device = {
.name = "nop_usb_xceiv",
.id = -1,
.dev = {
.dma_mask = &nop_xceiv_dmamask,
- .coherent_dma_mask = DMA_32BIT_MASK,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = NULL,
},
};
diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c
index ff318fae7d4d..0a43a7db750f 100644
--- a/drivers/usb/otg/otg.c
+++ b/drivers/usb/otg/otg.c
@@ -43,7 +43,8 @@ EXPORT_SYMBOL(otg_get_transceiver);
*/
void otg_put_transceiver(struct otg_transceiver *x)
{
- put_device(x->dev);
+ if (x)
+ put_device(x->dev);
}
EXPORT_SYMBOL(otg_put_transceiver);
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index b7eacad4d48c..2bfd6dd85b5a 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -93,8 +93,7 @@ static int belkin_sa_startup(struct usb_serial *serial);
static void belkin_sa_shutdown(struct usb_serial *serial);
static int belkin_sa_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
-static void belkin_sa_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp);
+static void belkin_sa_close(struct usb_serial_port *port);
static void belkin_sa_read_int_callback(struct urb *urb);
static void belkin_sa_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios * old);
@@ -244,8 +243,7 @@ exit:
} /* belkin_sa_open */
-static void belkin_sa_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void belkin_sa_close(struct usb_serial_port *port)
{
dbg("%s port %d", __func__, port->number);
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index ab4cc277aa65..2830766f5b39 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -262,32 +262,40 @@ error: kfree(priv);
return r;
}
-static void ch341_close(struct tty_struct *tty, struct usb_serial_port *port,
- struct file *filp)
+static int ch341_carrier_raised(struct usb_serial_port *port)
+{
+ struct ch341_private *priv = usb_get_serial_port_data(port);
+ if (priv->line_status & CH341_BIT_DCD)
+ return 1;
+ return 0;
+}
+
+static void ch341_dtr_rts(struct usb_serial_port *port, int on)
{
struct ch341_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- unsigned int c_cflag;
dbg("%s - port %d", __func__, port->number);
+ /* drop DTR and RTS */
+ spin_lock_irqsave(&priv->lock, flags);
+ if (on)
+ priv->line_control |= CH341_BIT_RTS | CH341_BIT_DTR;
+ else
+ priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ ch341_set_handshake(port->serial->dev, priv->line_control);
+ wake_up_interruptible(&priv->delta_msr_wait);
+}
+
+static void ch341_close(struct usb_serial_port *port)
+{
+ dbg("%s - port %d", __func__, port->number);
/* shutdown our urbs */
dbg("%s - shutting down urbs", __func__);
usb_kill_urb(port->write_urb);
usb_kill_urb(port->read_urb);
usb_kill_urb(port->interrupt_in_urb);
-
- if (tty) {
- c_cflag = tty->termios->c_cflag;
- if (c_cflag & HUPCL) {
- /* drop DTR and RTS */
- spin_lock_irqsave(&priv->lock, flags);
- priv->line_control = 0;
- spin_unlock_irqrestore(&priv->lock, flags);
- ch341_set_handshake(port->serial->dev, 0);
- }
- }
- wake_up_interruptible(&priv->delta_msr_wait);
}
@@ -302,7 +310,6 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port,
dbg("ch341_open()");
priv->baud_rate = DEFAULT_BAUD_RATE;
- priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
r = ch341_configure(serial->dev, priv);
if (r)
@@ -322,7 +329,7 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port,
if (r) {
dev_err(&port->dev, "%s - failed submitting interrupt urb,"
" error %d\n", __func__, r);
- ch341_close(tty, port, NULL);
+ ch341_close(port);
return -EPROTO;
}
@@ -343,9 +350,6 @@ static void ch341_set_termios(struct tty_struct *tty,
dbg("ch341_set_termios()");
- if (!tty || !tty->termios)
- return;
-
baud_rate = tty_get_baud_rate(tty);
priv->baud_rate = baud_rate;
@@ -568,6 +572,8 @@ static struct usb_serial_driver ch341_device = {
.usb_driver = &ch341_driver,
.num_ports = 1,
.open = ch341_open,
+ .dtr_rts = ch341_dtr_rts,
+ .carrier_raised = ch341_carrier_raised,
.close = ch341_close,
.ioctl = ch341_ioctl,
.set_termios = ch341_set_termios,
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 19e24045b137..247b61bfb7f4 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -169,7 +169,9 @@ static int usb_console_setup(struct console *co, char *options)
kfree(tty);
}
}
-
+ /* So we know not to kill the hardware on a hangup on this
+ port. We have also bumped the use count by one so it won't go
+ idle */
port->console = 1;
retval = 0;
@@ -182,7 +184,7 @@ free_tty:
kfree(tty);
reset_open_count:
port->port.count = 0;
-goto out;
+ goto out;
}
static void usb_console_write(struct console *co,
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index e8d5133ce9c8..d9f586dc6ecc 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -36,8 +36,7 @@
static int cp2101_open(struct tty_struct *, struct usb_serial_port *,
struct file *);
static void cp2101_cleanup(struct usb_serial_port *);
-static void cp2101_close(struct tty_struct *, struct usb_serial_port *,
- struct file*);
+static void cp2101_close(struct usb_serial_port *);
static void cp2101_get_termios(struct tty_struct *,
struct usb_serial_port *port);
static void cp2101_get_termios_port(struct usb_serial_port *port,
@@ -398,8 +397,7 @@ static void cp2101_cleanup(struct usb_serial_port *port)
}
}
-static void cp2101_close(struct tty_struct *tty, struct usb_serial_port *port,
- struct file *filp)
+static void cp2101_close(struct usb_serial_port *port)
{
dbg("%s - port %d", __func__, port->number);
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 858bdd038fbc..933ba913e66c 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -61,8 +61,7 @@ static int cyberjack_startup(struct usb_serial *serial);
static void cyberjack_shutdown(struct usb_serial *serial);
static int cyberjack_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
-static void cyberjack_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp);
+static void cyberjack_close(struct usb_serial_port *port);
static int cyberjack_write(struct tty_struct *tty,
struct usb_serial_port *port, const unsigned char *buf, int count);
static int cyberjack_write_room(struct tty_struct *tty);
@@ -175,13 +174,6 @@ static int cyberjack_open(struct tty_struct *tty,
dbg("%s - usb_clear_halt", __func__);
usb_clear_halt(port->serial->dev, port->write_urb->pipe);
- /* force low_latency on so that our tty_push actually forces
- * the data through, otherwise it is scheduled, and with high
- * data rates (like with OHCI) data can get lost.
- */
- if (tty)
- tty->low_latency = 1;
-
priv = usb_get_serial_port_data(port);
spin_lock_irqsave(&priv->lock, flags);
priv->rdtodo = 0;
@@ -192,8 +184,7 @@ static int cyberjack_open(struct tty_struct *tty,
return result;
}
-static void cyberjack_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void cyberjack_close(struct usb_serial_port *port)
{
dbg("%s - port %d", __func__, port->number);
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index eae4740d448c..669f93848539 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -174,8 +174,8 @@ static int cypress_ca42v2_startup(struct usb_serial *serial);
static void cypress_shutdown(struct usb_serial *serial);
static int cypress_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
-static void cypress_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp);
+static void cypress_close(struct usb_serial_port *port);
+static void cypress_dtr_rts(struct usb_serial_port *port, int on);
static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
static void cypress_send(struct usb_serial_port *port);
@@ -218,6 +218,7 @@ static struct usb_serial_driver cypress_earthmate_device = {
.shutdown = cypress_shutdown,
.open = cypress_open,
.close = cypress_close,
+ .dtr_rts = cypress_dtr_rts,
.write = cypress_write,
.write_room = cypress_write_room,
.ioctl = cypress_ioctl,
@@ -244,6 +245,7 @@ static struct usb_serial_driver cypress_hidcom_device = {
.shutdown = cypress_shutdown,
.open = cypress_open,
.close = cypress_close,
+ .dtr_rts = cypress_dtr_rts,
.write = cypress_write,
.write_room = cypress_write_room,
.ioctl = cypress_ioctl,
@@ -270,6 +272,7 @@ static struct usb_serial_driver cypress_ca42v2_device = {
.shutdown = cypress_shutdown,
.open = cypress_open,
.close = cypress_close,
+ .dtr_rts = cypress_dtr_rts,
.write = cypress_write,
.write_room = cypress_write_room,
.ioctl = cypress_ioctl,
@@ -656,15 +659,7 @@ static int cypress_open(struct tty_struct *tty,
priv->rx_flags = 0;
spin_unlock_irqrestore(&priv->lock, flags);
- /* setting to zero could cause data loss */
- if (tty)
- tty->low_latency = 1;
-
- /* raise both lines and set termios */
- spin_lock_irqsave(&priv->lock, flags);
- priv->line_control = CONTROL_DTR | CONTROL_RTS;
- priv->cmd_ctrl = 1;
- spin_unlock_irqrestore(&priv->lock, flags);
+ /* Set termios */
result = cypress_write(tty, port, NULL, 0);
if (result) {
@@ -698,76 +693,42 @@ static int cypress_open(struct tty_struct *tty,
__func__, result);
cypress_set_dead(port);
}
-
+ port->port.drain_delay = 256;
return result;
} /* cypress_open */
+static void cypress_dtr_rts(struct usb_serial_port *port, int on)
+{
+ struct cypress_private *priv = usb_get_serial_port_data(port);
+ /* drop dtr and rts */
+ priv = usb_get_serial_port_data(port);
+ spin_lock_irq(&priv->lock);
+ if (on == 0)
+ priv->line_control = 0;
+ else
+ priv->line_control = CONTROL_DTR | CONTROL_RTS;
+ priv->cmd_ctrl = 1;
+ spin_unlock_irq(&priv->lock);
+ cypress_write(NULL, port, NULL, 0);
+}
-static void cypress_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void cypress_close(struct usb_serial_port *port)
{
struct cypress_private *priv = usb_get_serial_port_data(port);
- unsigned int c_cflag;
- int bps;
- long timeout;
- wait_queue_t wait;
dbg("%s - port %d", __func__, port->number);
- /* wait for data to drain from buffer */
- spin_lock_irq(&priv->lock);
- timeout = CYPRESS_CLOSING_WAIT;
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&tty->write_wait, &wait);
- for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
- if (cypress_buf_data_avail(priv->buf) == 0
- || timeout == 0 || signal_pending(current)
- /* without mutex, allowed due to harmless failure mode */
- || port->serial->disconnected)
- break;
- spin_unlock_irq(&priv->lock);
- timeout = schedule_timeout(timeout);
- spin_lock_irq(&priv->lock);
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&tty->write_wait, &wait);
- /* clear out any remaining data in the buffer */
- cypress_buf_clear(priv->buf);
- spin_unlock_irq(&priv->lock);
-
/* writing is potentially harmful, lock must be taken */
mutex_lock(&port->serial->disc_mutex);
if (port->serial->disconnected) {
mutex_unlock(&port->serial->disc_mutex);
return;
}
- /* wait for characters to drain from device */
- if (tty) {
- bps = tty_get_baud_rate(tty);
- if (bps > 1200)
- timeout = max((HZ * 2560) / bps, HZ / 10);
- else
- timeout = 2 * HZ;
- schedule_timeout_interruptible(timeout);
- }
-
+ cypress_buf_clear(priv->buf);
dbg("%s - stopping urbs", __func__);
usb_kill_urb(port->interrupt_in_urb);
usb_kill_urb(port->interrupt_out_urb);
- if (tty) {
- c_cflag = tty->termios->c_cflag;
- if (c_cflag & HUPCL) {
- /* drop dtr and rts */
- priv = usb_get_serial_port_data(port);
- spin_lock_irq(&priv->lock);
- priv->line_control = 0;
- priv->cmd_ctrl = 1;
- spin_unlock_irq(&priv->lock);
- cypress_write(tty, port, NULL, 0);
- }
- }
if (stats)
dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 38ba4ea8b6bf..30f5140eff03 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -422,7 +422,6 @@ struct digi_port {
int dp_throttled;
int dp_throttle_restart;
wait_queue_head_t dp_flush_wait;
- int dp_in_close; /* close in progress */
wait_queue_head_t dp_close_wait; /* wait queue for close */
struct work_struct dp_wakeup_work;
struct usb_serial_port *dp_port;
@@ -456,8 +455,9 @@ static int digi_write_room(struct tty_struct *tty);
static int digi_chars_in_buffer(struct tty_struct *tty);
static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
struct file *filp);
-static void digi_close(struct tty_struct *tty, struct usb_serial_port *port,
- struct file *filp);
+static void digi_close(struct usb_serial_port *port);
+static int digi_carrier_raised(struct usb_serial_port *port);
+static void digi_dtr_rts(struct usb_serial_port *port, int on);
static int digi_startup_device(struct usb_serial *serial);
static int digi_startup(struct usb_serial *serial);
static void digi_shutdown(struct usb_serial *serial);
@@ -510,6 +510,8 @@ static struct usb_serial_driver digi_acceleport_2_device = {
.num_ports = 3,
.open = digi_open,
.close = digi_close,
+ .dtr_rts = digi_dtr_rts,
+ .carrier_raised = digi_carrier_raised,
.write = digi_write,
.write_room = digi_write_room,
.write_bulk_callback = digi_write_bulk_callback,
@@ -1328,6 +1330,19 @@ static int digi_chars_in_buffer(struct tty_struct *tty)
}
+static void digi_dtr_rts(struct usb_serial_port *port, int on)
+{
+ /* Adjust DTR and RTS */
+ digi_set_modem_signals(port, on * (TIOCM_DTR|TIOCM_RTS), 1);
+}
+
+static int digi_carrier_raised(struct usb_serial_port *port)
+{
+ struct digi_port *priv = usb_get_serial_port_data(port);
+ if (priv->dp_modem_signals & TIOCM_CD)
+ return 1;
+ return 0;
+}
static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
struct file *filp)
@@ -1336,7 +1351,6 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
unsigned char buf[32];
struct digi_port *priv = usb_get_serial_port_data(port);
struct ktermios not_termios;
- unsigned long flags = 0;
dbg("digi_open: TOP: port=%d, open_count=%d",
priv->dp_port_num, port->port.count);
@@ -1345,26 +1359,6 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
if (digi_startup_device(port->serial) != 0)
return -ENXIO;
- spin_lock_irqsave(&priv->dp_port_lock, flags);
-
- /* don't wait on a close in progress for non-blocking opens */
- if (priv->dp_in_close && (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0) {
- spin_unlock_irqrestore(&priv->dp_port_lock, flags);
- return -EAGAIN;
- }
-
- /* wait for a close in progress to finish */
- while (priv->dp_in_close) {
- cond_wait_interruptible_timeout_irqrestore(
- &priv->dp_close_wait, DIGI_RETRY_TIMEOUT,
- &priv->dp_port_lock, flags);
- if (signal_pending(current))
- return -EINTR;
- spin_lock_irqsave(&priv->dp_port_lock, flags);
- }
-
- spin_unlock_irqrestore(&priv->dp_port_lock, flags);
-
/* read modem signals automatically whenever they change */
buf[0] = DIGI_CMD_READ_INPUT_SIGNALS;
buf[1] = priv->dp_port_num;
@@ -1387,16 +1381,11 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
not_termios.c_iflag = ~tty->termios->c_iflag;
digi_set_termios(tty, port, &not_termios);
}
-
- /* set DTR and RTS */
- digi_set_modem_signals(port, TIOCM_DTR|TIOCM_RTS, 1);
-
return 0;
}
-static void digi_close(struct tty_struct *tty, struct usb_serial_port *port,
- struct file *filp)
+static void digi_close(struct usb_serial_port *port)
{
DEFINE_WAIT(wait);
int ret;
@@ -1411,28 +1400,9 @@ static void digi_close(struct tty_struct *tty, struct usb_serial_port *port,
if (port->serial->disconnected)
goto exit;
- /* do cleanup only after final close on this port */
- spin_lock_irq(&priv->dp_port_lock);
- priv->dp_in_close = 1;
- spin_unlock_irq(&priv->dp_port_lock);
-
- /* tell line discipline to process only XON/XOFF */
- tty->closing = 1;
-
- /* wait for output to drain */
- if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0)
- tty_wait_until_sent(tty, DIGI_CLOSE_TIMEOUT);
-
- /* flush driver and line discipline buffers */
- tty_driver_flush_buffer(tty);
- tty_ldisc_flush(tty);
-
if (port->serial->dev) {
- /* wait for transmit idle */
- if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0)
- digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
- /* drop DTR and RTS */
- digi_set_modem_signals(port, 0, 0);
+ /* FIXME: Transmit idle belongs in the wait_unti_sent path */
+ digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
/* disable input flow control */
buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
@@ -1477,11 +1447,9 @@ static void digi_close(struct tty_struct *tty, struct usb_serial_port *port,
/* shutdown any outstanding bulk writes */
usb_kill_urb(port->write_urb);
}
- tty->closing = 0;
exit:
spin_lock_irq(&priv->dp_port_lock);
priv->dp_write_urb_in_use = 0;
- priv->dp_in_close = 0;
wake_up_interruptible(&priv->dp_close_wait);
spin_unlock_irq(&priv->dp_port_lock);
mutex_unlock(&port->serial->disc_mutex);
@@ -1560,7 +1528,6 @@ static int digi_startup(struct usb_serial *serial)
priv->dp_throttled = 0;
priv->dp_throttle_restart = 0;
init_waitqueue_head(&priv->dp_flush_wait);
- priv->dp_in_close = 0;
init_waitqueue_head(&priv->dp_close_wait);
INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
priv->dp_port = serial->port[i];
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 8a69cce40b6d..2b141ccb0cd9 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -81,8 +81,7 @@ static int debug;
/* function prototypes for an empeg-car player */
static int empeg_open(struct tty_struct *tty, struct usb_serial_port *port,
struct file *filp);
-static void empeg_close(struct tty_struct *tty, struct usb_serial_port *port,
- struct file *filp);
+static void empeg_close(struct usb_serial_port *port);
static int empeg_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf,
int count);
@@ -181,8 +180,7 @@ static int empeg_open(struct tty_struct *tty, struct usb_serial_port *port,
}
-static void empeg_close(struct tty_struct *tty, struct usb_serial_port *port,
- struct file *filp)
+static void empeg_close(struct usb_serial_port *port)
{
dbg("%s - port %d", __func__, port->number);
@@ -478,12 +476,6 @@ static void empeg_set_termios(struct tty_struct *tty,
termios->c_cflag
|= CS8; /* character size 8 bits */
- /*
- * Force low_latency on; otherwise the pushes are scheduled;
- * this is bad as it opens up the possibility of dropping bytes
- * on the floor. We don't want to drop bytes on the floor. :)
- */
- tty->low_latency = 1;
tty_encode_baud_rate(tty, 115200, 115200);
}
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index dcc87aaa8628..7d935d1e2ab9 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -56,6 +56,7 @@ static __u16 vendor = FTDI_VID;
static __u16 product;
struct ftdi_private {
+ struct kref kref;
ftdi_chip_type_t chip_type;
/* type of device, either SIO or FT8U232AM */
int baud_base; /* baud base clock for divisor setting */
@@ -668,6 +669,9 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(DE_VID, WHT_PID) },
{ USB_DEVICE(ADI_VID, ADI_GNICE_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
+ { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ }, /* Optional parameter entry */
{ } /* Terminating entry */
};
@@ -715,8 +719,8 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port);
static int ftdi_sio_port_remove(struct usb_serial_port *port);
static int ftdi_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
-static void ftdi_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp);
+static void ftdi_close(struct usb_serial_port *port);
+static void ftdi_dtr_rts(struct usb_serial_port *port, int on);
static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
static int ftdi_write_room(struct tty_struct *tty);
@@ -754,6 +758,7 @@ static struct usb_serial_driver ftdi_sio_device = {
.port_remove = ftdi_sio_port_remove,
.open = ftdi_open,
.close = ftdi_close,
+ .dtr_rts = ftdi_dtr_rts,
.throttle = ftdi_throttle,
.unthrottle = ftdi_unthrottle,
.write = ftdi_write,
@@ -1351,6 +1356,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
return -ENOMEM;
}
+ kref_init(&priv->kref);
spin_lock_init(&priv->rx_lock);
spin_lock_init(&priv->tx_lock);
init_waitqueue_head(&priv->delta_msr_wait);
@@ -1467,6 +1473,13 @@ static void ftdi_shutdown(struct usb_serial *serial)
dbg("%s", __func__);
}
+static void ftdi_sio_priv_release(struct kref *k)
+{
+ struct ftdi_private *priv = container_of(k, struct ftdi_private, kref);
+
+ kfree(priv);
+}
+
static int ftdi_sio_port_remove(struct usb_serial_port *port)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1481,7 +1494,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)
if (priv) {
usb_set_serial_port_data(port, NULL);
- kfree(priv);
+ kref_put(&priv->kref, ftdi_sio_priv_release);
}
return 0;
@@ -1546,12 +1559,37 @@ static int ftdi_open(struct tty_struct *tty,
dev_err(&port->dev,
"%s - failed submitting read urb, error %d\n",
__func__, result);
-
+ else
+ kref_get(&priv->kref);
return result;
} /* ftdi_open */
+static void ftdi_dtr_rts(struct usb_serial_port *port, int on)
+{
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ char buf[1];
+
+ mutex_lock(&port->serial->disc_mutex);
+ if (!port->serial->disconnected) {
+ /* Disable flow control */
+ if (!on && usb_control_msg(port->serial->dev,
+ usb_sndctrlpipe(port->serial->dev, 0),
+ FTDI_SIO_SET_FLOW_CTRL_REQUEST,
+ FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
+ 0, priv->interface, buf, 0,
+ WDR_TIMEOUT) < 0) {
+ dev_err(&port->dev, "error from flowcontrol urb\n");
+ }
+ /* drop RTS and DTR */
+ if (on)
+ set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+ else
+ clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+ }
+ mutex_unlock(&port->serial->disc_mutex);
+}
/*
* usbserial:__serial_close only calls ftdi_close if the point is open
@@ -1561,38 +1599,19 @@ static int ftdi_open(struct tty_struct *tty,
*
*/
-static void ftdi_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void ftdi_close(struct usb_serial_port *port)
{ /* ftdi_close */
- unsigned int c_cflag = tty->termios->c_cflag;
struct ftdi_private *priv = usb_get_serial_port_data(port);
- char buf[1];
dbg("%s", __func__);
- mutex_lock(&port->serial->disc_mutex);
- if (c_cflag & HUPCL && !port->serial->disconnected) {
- /* Disable flow control */
- if (usb_control_msg(port->serial->dev,
- usb_sndctrlpipe(port->serial->dev, 0),
- FTDI_SIO_SET_FLOW_CTRL_REQUEST,
- FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
- 0, priv->interface, buf, 0,
- WDR_TIMEOUT) < 0) {
- dev_err(&port->dev, "error from flowcontrol urb\n");
- }
-
- /* drop RTS and DTR */
- clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
- } /* Note change no line if hupcl is off */
- mutex_unlock(&port->serial->disc_mutex);
/* cancel any scheduled reading */
- cancel_delayed_work(&priv->rx_work);
- flush_scheduled_work();
+ cancel_delayed_work_sync(&priv->rx_work);
/* shutdown our bulk read */
usb_kill_urb(port->read_urb);
+ kref_put(&priv->kref, ftdi_sio_priv_release);
} /* ftdi_close */
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index daaf63db0b50..12330fa1c095 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -913,6 +913,19 @@
#define ADI_GNICE_PID 0xF000
/*
+ * JETI SPECTROMETER SPECBOS 1201
+ * http://www.jeti.com/products/sys/scb/scb1201.php
+ */
+#define JETI_VID 0x0c6c
+#define JETI_SPC1201_PID 0x04b2
+
+/*
+ * Marvell SheevaPlug
+ */
+#define MARVELL_VID 0x9e88
+#define MARVELL_SHEEVAPLUG_PID 0x9e8f
+
+/*
* BmRequestType: 1100 0000b
* bRequest: FTDI_E2_READ
* wValue: 0
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index a26a0e2cdb4a..ee25a3fe3b09 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -973,14 +973,6 @@ static int garmin_open(struct tty_struct *tty,
dbg("%s - port %d", __func__, port->number);
- /*
- * Force low_latency on so that our tty_push actually forces the data
- * through, otherwise it is scheduled, and with high data rates (like
- * with OHCI) data can get lost.
- */
- if (tty)
- tty->low_latency = 1;
-
spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->mode = initial_mode;
garmin_data_p->count = 0;
@@ -1001,8 +993,7 @@ static int garmin_open(struct tty_struct *tty,
}
-static void garmin_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void garmin_close(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 9d57cace3731..be82ea956720 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -122,12 +122,6 @@ int usb_serial_generic_open(struct tty_struct *tty,
dbg("%s - port %d", __func__, port->number);
- /* force low_latency on so that our tty_push actually forces the data
- through, otherwise it is scheduled, and with high data rates (like
- with OHCI) data can get lost. */
- if (tty)
- tty->low_latency = 1;
-
/* clear the throttle flags */
spin_lock_irqsave(&port->lock, flags);
port->throttled = 0;
@@ -190,8 +184,7 @@ int usb_serial_generic_resume(struct usb_serial *serial)
}
EXPORT_SYMBOL_GPL(usb_serial_generic_resume);
-void usb_serial_generic_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+void usb_serial_generic_close(struct usb_serial_port *port)
{
dbg("%s - port %d", __func__, port->number);
generic_cleanup(port);
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index e85c8c0d1ad9..53ef5996e33d 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -193,8 +193,6 @@ static const struct divisor_table_entry divisor_table[] = {
/* local variables */
static int debug;
-static int low_latency = 1; /* tty low latency flag, on by default */
-
static atomic_t CmdUrbs; /* Number of outstanding Command Write Urbs */
@@ -209,8 +207,7 @@ static void edge_bulk_out_cmd_callback(struct urb *urb);
/* function prototypes for the usbserial callbacks */
static int edge_open(struct tty_struct *tty, struct usb_serial_port *port,
struct file *filp);
-static void edge_close(struct tty_struct *tty, struct usb_serial_port *port,
- struct file *filp);
+static void edge_close(struct usb_serial_port *port);
static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
static int edge_write_room(struct tty_struct *tty);
@@ -867,9 +864,6 @@ static int edge_open(struct tty_struct *tty,
if (edge_port == NULL)
return -ENODEV;
- if (tty)
- tty->low_latency = low_latency;
-
/* see if we've set up our endpoint info yet (can't set it up
in edge_startup as the structures were not set up at that time.) */
serial = port->serial;
@@ -970,7 +964,7 @@ static int edge_open(struct tty_struct *tty,
if (!edge_port->txfifo.fifo) {
dbg("%s - no memory", __func__);
- edge_close(tty, port, filp);
+ edge_close(port);
return -ENOMEM;
}
@@ -980,7 +974,7 @@ static int edge_open(struct tty_struct *tty,
if (!edge_port->write_urb) {
dbg("%s - no memory", __func__);
- edge_close(tty, port, filp);
+ edge_close(port);
return -ENOMEM;
}
@@ -1104,8 +1098,7 @@ static void block_until_tx_empty(struct edgeport_port *edge_port)
* edge_close
* this function is called by the tty driver when a port is closed
*****************************************************************************/
-static void edge_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void edge_close(struct usb_serial_port *port)
{
struct edgeport_serial *edge_serial;
struct edgeport_port *edge_port;
@@ -3299,6 +3292,3 @@ MODULE_FIRMWARE("edgeport/down2.fw");
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");
-
-module_param(low_latency, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(low_latency, "Low latency enabled or not");
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index c3cdd00ddc41..db964db42d3c 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -76,7 +76,6 @@ struct edgeport_uart_buf_desc {
#define EDGE_READ_URB_STOPPING 1
#define EDGE_READ_URB_STOPPED 2
-#define EDGE_LOW_LATENCY 1
#define EDGE_CLOSING_WAIT 4000 /* in .01 sec */
#define EDGE_OUT_BUF_SIZE 1024
@@ -103,7 +102,7 @@ struct edgeport_port {
__u8 shadow_mcr;
__u8 shadow_lsr;
__u8 lsr_mask;
- __u32 ump_read_timeout; /* Number of miliseconds the UMP will
+ __u32 ump_read_timeout; /* Number of milliseconds the UMP will
wait without data before completing
a read short */
int baud_rate;
@@ -232,7 +231,6 @@ static unsigned short OperationalBuildNumber;
static int debug;
-static int low_latency = EDGE_LOW_LATENCY;
static int closing_wait = EDGE_CLOSING_WAIT;
static int ignore_cpu_rev;
static int default_uart_mode; /* RS232 */
@@ -1850,9 +1848,6 @@ static int edge_open(struct tty_struct *tty,
if (edge_port == NULL)
return -ENODEV;
- if (tty)
- tty->low_latency = low_latency;
-
port_number = port->number - port->serial->minor;
switch (port_number) {
case 0:
@@ -2014,8 +2009,7 @@ release_es_lock:
return status;
}
-static void edge_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void edge_close(struct usb_serial_port *port)
{
struct edgeport_serial *edge_serial;
struct edgeport_port *edge_port;
@@ -3008,9 +3002,6 @@ MODULE_FIRMWARE("edgeport/down3.bin");
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");
-module_param(low_latency, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(low_latency, "Low latency enabled or not");
-
module_param(closing_wait, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain, in .01 secs");
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index ef92095b0732..c610a99fa477 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -76,8 +76,7 @@ static int initial_wait;
/* Function prototypes for an ipaq */
static int ipaq_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
-static void ipaq_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp);
+static void ipaq_close(struct usb_serial_port *port);
static int ipaq_calc_num_ports(struct usb_serial *serial);
static int ipaq_startup(struct usb_serial *serial);
static void ipaq_shutdown(struct usb_serial *serial);
@@ -631,13 +630,7 @@ static int ipaq_open(struct tty_struct *tty,
priv->free_len += PACKET_SIZE;
}
- /*
- * Force low latency on. This will immediately push data to the line
- * discipline instead of queueing.
- */
-
if (tty) {
- tty->low_latency = 1;
/* FIXME: These two are bogus */
tty->raw = 1;
tty->real_raw = 1;
@@ -720,8 +713,7 @@ error:
}
-static void ipaq_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void ipaq_close(struct usb_serial_port *port)
{
struct ipaq_private *priv = usb_get_serial_port_data(port);
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index f530032ed93d..29ad038b9c8d 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -207,9 +207,6 @@ static int ipw_open(struct tty_struct *tty,
if (!buf_flow_init)
return -ENOMEM;
- if (tty)
- tty->low_latency = 1;
-
/* --1: Tell the modem to initialize (we think) From sniffs this is
* always the first thing that gets sent to the modem during
* opening of the device */
@@ -305,23 +302,17 @@ static int ipw_open(struct tty_struct *tty,
return 0;
}
-static void ipw_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void ipw_dtr_rts(struct usb_serial_port *port, int on)
{
struct usb_device *dev = port->serial->dev;
int result;
- if (tty_hung_up_p(filp)) {
- dbg("%s: tty_hung_up_p ...", __func__);
- return;
- }
-
/*--1: drop the dtr */
dbg("%s:dropping dtr", __func__);
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
IPW_SIO_SET_PIN,
USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- IPW_PIN_CLRDTR,
+ on ? IPW_PIN_SETDTR : IPW_PIN_CLRDTR,
0,
NULL,
0,
@@ -335,7 +326,7 @@ static void ipw_close(struct tty_struct *tty,
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
IPW_SIO_SET_PIN, USB_TYPE_VENDOR |
USB_RECIP_INTERFACE | USB_DIR_OUT,
- IPW_PIN_CLRRTS,
+ on ? IPW_PIN_SETRTS : IPW_PIN_CLRRTS,
0,
NULL,
0,
@@ -343,7 +334,12 @@ static void ipw_close(struct tty_struct *tty,
if (result < 0)
dev_err(&port->dev,
"dropping rts failed (error = %d)\n", result);
+}
+static void ipw_close(struct usb_serial_port *port)
+{
+ struct usb_device *dev = port->serial->dev;
+ int result;
/*--3: purge */
dbg("%s:sending purge", __func__);
@@ -464,6 +460,7 @@ static struct usb_serial_driver ipw_device = {
.num_ports = 1,
.open = ipw_open,
.close = ipw_close,
+ .dtr_rts = ipw_dtr_rts,
.port_probe = ipw_probe,
.port_remove = ipw_disconnect,
.write = ipw_write,
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 4e2cda93da59..66009b6b763a 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -88,8 +88,7 @@ static int xbof = -1;
static int ir_startup (struct usb_serial *serial);
static int ir_open(struct tty_struct *tty, struct usb_serial_port *port,
struct file *filep);
-static void ir_close(struct tty_struct *tty, struct usb_serial_port *port,
- struct file *filep);
+static void ir_close(struct usb_serial_port *port);
static int ir_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
static void ir_write_bulk_callback (struct urb *urb);
@@ -346,8 +345,7 @@ static int ir_open(struct tty_struct *tty,
return result;
}
-static void ir_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file * filp)
+static void ir_close(struct usb_serial_port *port)
{
dbg("%s - port %d", __func__, port->number);
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index 2314c6ae4fc2..bb572cee6ecd 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -70,7 +70,6 @@ static void read_rxcmd_callback(struct urb *urb);
struct iuu_private {
spinlock_t lock; /* store irq state */
wait_queue_head_t delta_msr_wait;
- u8 line_control;
u8 line_status;
u8 termios_initialized;
int tiostatus; /* store IUART SIGNAL for tiocmget call */
@@ -946,19 +945,10 @@ static int iuu_uart_baud(struct usb_serial_port *port, u32 baud,
return status;
}
-static int set_control_lines(struct usb_device *dev, u8 value)
-{
- return 0;
-}
-
-static void iuu_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void iuu_close(struct usb_serial_port *port)
{
/* iuu_led (port,255,0,0,0); */
struct usb_serial *serial;
- struct iuu_private *priv = usb_get_serial_port_data(port);
- unsigned long flags;
- unsigned int c_cflag;
serial = port->serial;
if (!serial)
@@ -968,17 +958,6 @@ static void iuu_close(struct tty_struct *tty,
iuu_uart_off(port);
if (serial->dev) {
- if (tty) {
- c_cflag = tty->termios->c_cflag;
- if (c_cflag & HUPCL) {
- /* drop DTR and RTS */
- priv = usb_get_serial_port_data(port);
- spin_lock_irqsave(&priv->lock, flags);
- priv->line_control = 0;
- spin_unlock_irqrestore(&priv->lock, flags);
- set_control_lines(port->serial->dev, 0);
- }
- }
/* free writebuf */
/* shutdown our urbs */
dbg("%s - shutting down urbs", __func__);
@@ -1051,7 +1030,6 @@ static int iuu_open(struct tty_struct *tty,
tty->termios->c_oflag = 0;
tty->termios->c_iflag = 0;
priv->termios_initialized = 1;
- tty->low_latency = 1;
priv->poll = 0;
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -1155,7 +1133,7 @@ static int iuu_open(struct tty_struct *tty,
if (result) {
dev_err(&port->dev, "%s - failed submitting read urb,"
" error %d\n", __func__, result);
- iuu_close(tty, port, NULL);
+ iuu_close(port);
return -EPROTO;
} else {
dbg("%s - rxcmd OK", __func__);
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 00daa8f7759a..f1195a98f316 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -1298,8 +1298,16 @@ static inline void stop_urb(struct urb *urb)
usb_kill_urb(urb);
}
-static void keyspan_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
+{
+ struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
+
+ p_priv->rts_state = on;
+ p_priv->dtr_state = on;
+ keyspan_send_setup(port, 0);
+}
+
+static void keyspan_close(struct usb_serial_port *port)
{
int i;
struct usb_serial *serial = port->serial;
@@ -1336,7 +1344,6 @@ static void keyspan_close(struct tty_struct *tty,
stop_urb(p_priv->out_urbs[i]);
}
}
- tty_port_tty_set(&port->port, NULL);
}
/* download the firmware to a pre-renumeration device */
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index 38b4582e0734..0d4569b60768 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -38,9 +38,8 @@
static int keyspan_open (struct tty_struct *tty,
struct usb_serial_port *port,
struct file *filp);
-static void keyspan_close (struct tty_struct *tty,
- struct usb_serial_port *port,
- struct file *filp);
+static void keyspan_close (struct usb_serial_port *port);
+static void keyspan_dtr_rts (struct usb_serial_port *port, int on);
static int keyspan_startup (struct usb_serial *serial);
static void keyspan_shutdown (struct usb_serial *serial);
static int keyspan_write_room (struct tty_struct *tty);
@@ -562,6 +561,7 @@ static struct usb_serial_driver keyspan_1port_device = {
.num_ports = 1,
.open = keyspan_open,
.close = keyspan_close,
+ .dtr_rts = keyspan_dtr_rts,
.write = keyspan_write,
.write_room = keyspan_write_room,
.set_termios = keyspan_set_termios,
@@ -582,6 +582,7 @@ static struct usb_serial_driver keyspan_2port_device = {
.num_ports = 2,
.open = keyspan_open,
.close = keyspan_close,
+ .dtr_rts = keyspan_dtr_rts,
.write = keyspan_write,
.write_room = keyspan_write_room,
.set_termios = keyspan_set_termios,
@@ -602,6 +603,7 @@ static struct usb_serial_driver keyspan_4port_device = {
.num_ports = 4,
.open = keyspan_open,
.close = keyspan_close,
+ .dtr_rts = keyspan_dtr_rts,
.write = keyspan_write,
.write_room = keyspan_write_room,
.set_termios = keyspan_set_termios,
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index bf1ae247da66..ab769dbea1b3 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -651,6 +651,35 @@ static int keyspan_pda_chars_in_buffer(struct tty_struct *tty)
}
+static void keyspan_pda_dtr_rts(struct usb_serial_port *port, int on)
+{
+ struct usb_serial *serial = port->serial;
+
+ if (serial->dev) {
+ if (on)
+ keyspan_pda_set_modem_info(serial, (1<<7) | (1<< 2));
+ else
+ keyspan_pda_set_modem_info(serial, 0);
+ }
+}
+
+static int keyspan_pda_carrier_raised(struct usb_serial_port *port)
+{
+ struct usb_serial *serial = port->serial;
+ unsigned char modembits;
+
+ /* If we can read the modem status and the DCD is low then
+ carrier is not raised yet */
+ if (keyspan_pda_get_modem_info(serial, &modembits) >= 0) {
+ if (!(modembits & (1>>6)))
+ return 0;
+ }
+ /* Carrier raised, or we failed (eg disconnected) so
+ progress accordingly */
+ return 1;
+}
+
+
static int keyspan_pda_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp)
{
@@ -682,13 +711,6 @@ static int keyspan_pda_open(struct tty_struct *tty,
priv->tx_room = room;
priv->tx_throttled = room ? 0 : 1;
- /* the normal serial device seems to always turn on DTR and RTS here,
- so do the same */
- if (tty && (tty->termios->c_cflag & CBAUD))
- keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2));
- else
- keyspan_pda_set_modem_info(serial, 0);
-
/*Start reading from the device*/
port->interrupt_in_urb->dev = serial->dev;
rc = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
@@ -700,19 +722,11 @@ static int keyspan_pda_open(struct tty_struct *tty,
error:
return rc;
}
-
-
-static void keyspan_pda_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void keyspan_pda_close(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
if (serial->dev) {
- /* the normal serial device seems to always shut
- off DTR and RTS now */
- if (tty->termios->c_cflag & HUPCL)
- keyspan_pda_set_modem_info(serial, 0);
-
/* shutdown our bulk reads and writes */
usb_kill_urb(port->write_urb);
usb_kill_urb(port->interrupt_in_urb);
@@ -839,6 +853,8 @@ static struct usb_serial_driver keyspan_pda_device = {
.usb_driver = &keyspan_pda_driver,
.id_table = id_table_std,
.num_ports = 1,
+ .dtr_rts = keyspan_pda_dtr_rts,
+ .carrier_raised = keyspan_pda_carrier_raised,
.open = keyspan_pda_open,
.close = keyspan_pda_close,
.write = keyspan_pda_write,
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index fcd9082f3e7f..fa817c66b3e8 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -76,8 +76,7 @@ static int klsi_105_startup(struct usb_serial *serial);
static void klsi_105_shutdown(struct usb_serial *serial);
static int klsi_105_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
-static void klsi_105_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp);
+static void klsi_105_close(struct usb_serial_port *port);
static int klsi_105_write(struct tty_struct *tty,
struct usb_serial_port *port, const unsigned char *buf, int count);
static void klsi_105_write_bulk_callback(struct urb *urb);
@@ -447,8 +446,7 @@ exit:
} /* klsi_105_open */
-static void klsi_105_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void klsi_105_close(struct usb_serial_port *port)
{
struct klsi_105_private *priv = usb_get_serial_port_data(port);
int rc;
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 6286baad9392..6b570498287f 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -72,8 +72,7 @@ static int kobil_startup(struct usb_serial *serial);
static void kobil_shutdown(struct usb_serial *serial);
static int kobil_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
-static void kobil_close(struct tty_struct *tty, struct usb_serial_port *port,
- struct file *filp);
+static void kobil_close(struct usb_serial_port *port);
static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
static int kobil_write_room(struct tty_struct *tty);
@@ -209,7 +208,7 @@ static void kobil_shutdown(struct usb_serial *serial)
for (i = 0; i < serial->num_ports; ++i) {
while (serial->port[i]->port.count > 0)
- kobil_close(NULL, serial->port[i], NULL);
+ kobil_close(serial->port[i]);
kfree(usb_get_serial_port_data(serial->port[i]));
usb_set_serial_port_data(serial->port[i], NULL);
}
@@ -231,13 +230,7 @@ static int kobil_open(struct tty_struct *tty,
/* someone sets the dev to 0 if the close method has been called */
port->interrupt_in_urb->dev = port->serial->dev;
-
- /* force low_latency on so that our tty_push actually forces
- * the data through, otherwise it is scheduled, and with high
- * data rates (like with OHCI) data can get lost.
- */
if (tty) {
- tty->low_latency = 1;
/* Default to echo off and other sane device settings */
tty->termios->c_lflag = 0;
@@ -352,11 +345,11 @@ static int kobil_open(struct tty_struct *tty,
}
-static void kobil_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void kobil_close(struct usb_serial_port *port)
{
dbg("%s - port %d", __func__, port->number);
+ /* FIXME: Add rts/dtr methods */
if (port->write_urb) {
usb_kill_urb(port->write_urb);
usb_free_urb(port->write_urb);
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 82930a7d5093..873795548fc0 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -95,8 +95,8 @@ static int mct_u232_startup(struct usb_serial *serial);
static void mct_u232_shutdown(struct usb_serial *serial);
static int mct_u232_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
-static void mct_u232_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp);
+static void mct_u232_close(struct usb_serial_port *port);
+static void mct_u232_dtr_rts(struct usb_serial_port *port, int on);
static void mct_u232_read_int_callback(struct urb *urb);
static void mct_u232_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
@@ -140,6 +140,7 @@ static struct usb_serial_driver mct_u232_device = {
.num_ports = 1,
.open = mct_u232_open,
.close = mct_u232_close,
+ .dtr_rts = mct_u232_dtr_rts,
.throttle = mct_u232_throttle,
.unthrottle = mct_u232_unthrottle,
.read_int_callback = mct_u232_read_int_callback,
@@ -496,29 +497,29 @@ error:
return retval;
} /* mct_u232_open */
-
-static void mct_u232_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)
{
- unsigned int c_cflag;
unsigned int control_state;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
- dbg("%s port %d", __func__, port->number);
- if (tty) {
- c_cflag = tty->termios->c_cflag;
- mutex_lock(&port->serial->disc_mutex);
- if (c_cflag & HUPCL && !port->serial->disconnected) {
- /* drop DTR and RTS */
- spin_lock_irq(&priv->lock);
+ mutex_lock(&port->serial->disc_mutex);
+ if (!port->serial->disconnected) {
+ /* drop DTR and RTS */
+ spin_lock_irq(&priv->lock);
+ if (on)
+ priv->control_state |= TIOCM_DTR | TIOCM_RTS;
+ else
priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
- control_state = priv->control_state;
- spin_unlock_irq(&priv->lock);
- mct_u232_set_modem_ctrl(port->serial, control_state);
- }
- mutex_unlock(&port->serial->disc_mutex);
+ control_state = priv->control_state;
+ spin_unlock_irq(&priv->lock);
+ mct_u232_set_modem_ctrl(port->serial, control_state);
}
+ mutex_unlock(&port->serial->disc_mutex);
+}
+static void mct_u232_close(struct usb_serial_port *port)
+{
+ dbg("%s port %d", __func__, port->number);
if (port->serial->dev) {
/* shutdown our urbs */
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index e772cc0a97fd..9e1a013ee7f6 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -446,13 +446,6 @@ static int mos7720_open(struct tty_struct *tty,
data = 0x0c;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
- /* force low_latency on so that our tty_push actually forces *
- * the data through,otherwise it is scheduled, and with *
- * high data rates (like with OHCI) data can get lost. */
-
- if (tty)
- tty->low_latency = 1;
-
/* see if we've set up our endpoint info yet *
* (can't set it up in mos7720_startup as the *
* structures were not set up at that time.) */
@@ -540,8 +533,7 @@ static int mos7720_chars_in_buffer(struct tty_struct *tty)
return chars;
}
-static void mos7720_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void mos7720_close(struct usb_serial_port *port)
{
struct usb_serial *serial;
struct moschip_port *mos7720_port;
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 2c20e88a91b3..10b78a37214f 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -38,7 +38,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "1.3.1"
+#define DRIVER_VERSION "1.3.2"
#define DRIVER_DESC "Moschip 7840/7820 USB Serial Driver"
/*
@@ -123,6 +123,11 @@
#define BANDB_DEVICE_ID_USOPTL4_4 0xAC44
#define BANDB_DEVICE_ID_USOPTL4_2 0xAC42
+/* This driver also supports the ATEN UC2324 device since it is mos7840 based
+ * - if I knew the device id it would also support the ATEN UC2322 */
+#define USB_VENDOR_ID_ATENINTL 0x0557
+#define ATENINTL_DEVICE_ID_UC2324 0x2011
+
/* Interrupt Routine Defines */
#define SERIAL_IIR_RLS 0x06
@@ -170,6 +175,7 @@ static struct usb_device_id moschip_port_id_table[] = {
{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
+ {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)},
{} /* terminating entry */
};
@@ -178,6 +184,7 @@ static __devinitdata struct usb_device_id moschip_id_table_combined[] = {
{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
+ {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)},
{} /* terminating entry */
};
@@ -1000,12 +1007,6 @@ static int mos7840_open(struct tty_struct *tty,
status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset,
Data);
- /* force low_latency on so that our tty_push actually forces *
- * the data through,otherwise it is scheduled, and with *
- * high data rates (like with OHCI) data can get lost. */
- if (tty)
- tty->low_latency = 1;
-
/* Check to see if we've set up our endpoint info yet *
* (can't set it up in mos7840_startup as the structures *
* were not set up at that time.) */
@@ -1134,54 +1135,12 @@ static int mos7840_chars_in_buffer(struct tty_struct *tty)
}
-/************************************************************************
- *
- * mos7840_block_until_tx_empty
- *
- * This function will block the close until one of the following:
- * 1. TX count are 0
- * 2. The mos7840 has stopped
- * 3. A timeout of 3 seconds without activity has expired
- *
- ************************************************************************/
-static void mos7840_block_until_tx_empty(struct tty_struct *tty,
- struct moschip_port *mos7840_port)
-{
- int timeout = HZ / 10;
- int wait = 30;
- int count;
-
- while (1) {
-
- count = mos7840_chars_in_buffer(tty);
-
- /* Check for Buffer status */
- if (count <= 0)
- return;
-
- /* Block the thread for a while */
- interruptible_sleep_on_timeout(&mos7840_port->wait_chase,
- timeout);
-
- /* No activity.. count down section */
- wait--;
- if (wait == 0) {
- dbg("%s - TIMEOUT", __func__);
- return;
- } else {
- /* Reset timeout value back to seconds */
- wait = 30;
- }
- }
-}
-
/*****************************************************************************
* mos7840_close
* this function is called by the tty driver when a port is closed
*****************************************************************************/
-static void mos7840_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void mos7840_close(struct usb_serial_port *port)
{
struct usb_serial *serial;
struct moschip_port *mos7840_port;
@@ -1222,10 +1181,6 @@ static void mos7840_close(struct tty_struct *tty,
}
}
- if (serial->dev)
- /* flush and block until tx is empty */
- mos7840_block_until_tx_empty(tty, mos7840_port);
-
/* While closing port, shutdown all bulk read, write *
* and interrupt read if they exists */
if (serial->dev) {
@@ -2477,9 +2432,14 @@ static int mos7840_startup(struct usb_serial *serial)
mos7840_set_port_private(serial->port[i], mos7840_port);
spin_lock_init(&mos7840_port->pool_lock);
- mos7840_port->port_num = ((serial->port[i]->number -
- (serial->port[i]->serial->minor)) +
- 1);
+ /* minor is not initialised until later by
+ * usb-serial.c:get_free_serial() and cannot therefore be used
+ * to index device instances */
+ mos7840_port->port_num = i + 1;
+ dbg ("serial->port[i]->number = %d", serial->port[i]->number);
+ dbg ("serial->port[i]->serial->minor = %d", serial->port[i]->serial->minor);
+ dbg ("mos7840_port->port_num = %d", mos7840_port->port_num);
+ dbg ("serial->minor = %d", serial->minor);
if (mos7840_port->port_num == 1) {
mos7840_port->SpRegOffset = 0x0;
@@ -2690,13 +2650,16 @@ static void mos7840_shutdown(struct usb_serial *serial)
for (i = 0; i < serial->num_ports; ++i) {
mos7840_port = mos7840_get_port_private(serial->port[i]);
- spin_lock_irqsave(&mos7840_port->pool_lock, flags);
- mos7840_port->zombie = 1;
- spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
- usb_kill_urb(mos7840_port->control_urb);
- kfree(mos7840_port->ctrl_buf);
- kfree(mos7840_port->dr);
- kfree(mos7840_port);
+ dbg ("mos7840_port %d = %p", i, mos7840_port);
+ if (mos7840_port) {
+ spin_lock_irqsave(&mos7840_port->pool_lock, flags);
+ mos7840_port->zombie = 1;
+ spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
+ usb_kill_urb(mos7840_port->control_urb);
+ kfree(mos7840_port->ctrl_buf);
+ kfree(mos7840_port->dr);
+ kfree(mos7840_port);
+ }
mos7840_set_port_private(serial->port[i], NULL);
}
diff --git a/drivers/usb/serial/moto_modem.c b/drivers/usb/serial/moto_modem.c
index 2e8e05462ef7..b66b71ccd12b 100644
--- a/drivers/usb/serial/moto_modem.c
+++ b/drivers/usb/serial/moto_modem.c
@@ -25,6 +25,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x05c6, 0x3197) }, /* unknown Motorola phone */
{ USB_DEVICE(0x0c44, 0x0022) }, /* unknown Mororola phone */
{ USB_DEVICE(0x22b8, 0x2a64) }, /* Motorola KRZR K1m */
+ { USB_DEVICE(0x22b8, 0x2c64) }, /* Motorola V950 phone */
{ },
};
MODULE_DEVICE_TABLE(usb, id_table);
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
index bcdcbb822705..f5f3751a888c 100644
--- a/drivers/usb/serial/navman.c
+++ b/drivers/usb/serial/navman.c
@@ -98,8 +98,7 @@ static int navman_open(struct tty_struct *tty,
return result;
}
-static void navman_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void navman_close(struct usb_serial_port *port)
{
dbg("%s - port %d", __func__, port->number);
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index df6539712726..1104617334f5 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -66,8 +66,7 @@ static int debug;
/* function prototypes */
static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port,
struct file *filp);
-static void omninet_close(struct tty_struct *tty, struct usb_serial_port *port,
- struct file *filp);
+static void omninet_close(struct usb_serial_port *port);
static void omninet_read_bulk_callback(struct urb *urb);
static void omninet_write_bulk_callback(struct urb *urb);
static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
@@ -189,8 +188,7 @@ static int omninet_open(struct tty_struct *tty,
return result;
}
-static void omninet_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void omninet_close(struct usb_serial_port *port)
{
dbg("%s - port %d", __func__, port->number);
usb_kill_urb(port->read_urb);
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
index 839583dc8b6a..c20480aa9755 100644
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -159,14 +159,6 @@ static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port,
priv->port = port;
spin_unlock_irqrestore(&priv->lock, flags);
- /*
- * Force low_latency on so that our tty_push actually forces the data
- * through, otherwise it is scheduled, and with high data rates (like
- * with OHCI) data can get lost.
- */
- if (tty)
- tty->low_latency = 1;
-
/* Start reading from the device */
usb_fill_bulk_urb(priv->bulk_read_urb, priv->udev,
usb_rcvbulkpipe(priv->udev,
@@ -181,8 +173,7 @@ static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port,
return result;
}
-static void opticon_close(struct tty_struct *tty, struct usb_serial_port *port,
- struct file *filp)
+static void opticon_close(struct usb_serial_port *port)
{
struct opticon_private *priv = usb_get_serial_data(port->serial);
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index d560c0b54e6e..a16d69fadba1 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -45,8 +45,9 @@
/* Function prototypes */
static int option_open(struct tty_struct *tty, struct usb_serial_port *port,
struct file *filp);
-static void option_close(struct tty_struct *tty, struct usb_serial_port *port,
- struct file *filp);
+static void option_close(struct usb_serial_port *port);
+static void option_dtr_rts(struct usb_serial_port *port, int on);
+
static int option_startup(struct usb_serial *serial);
static void option_shutdown(struct usb_serial *serial);
static int option_write_room(struct tty_struct *tty);
@@ -61,7 +62,7 @@ static void option_set_termios(struct tty_struct *tty,
static int option_tiocmget(struct tty_struct *tty, struct file *file);
static int option_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
-static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *port);
+static int option_send_setup(struct usb_serial_port *port);
static int option_suspend(struct usb_serial *serial, pm_message_t message);
static int option_resume(struct usb_serial *serial);
@@ -300,6 +301,10 @@ static int option_resume(struct usb_serial *serial);
#define BENQ_VENDOR_ID 0x04a5
#define BENQ_PRODUCT_H10 0x4068
+#define DLINK_VENDOR_ID 0x1186
+#define DLINK_PRODUCT_DWM_652 0x3e04
+
+
static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -516,6 +521,7 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) },
{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) },
{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
+ { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
{ USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */
{ } /* Terminating entry */
};
@@ -546,6 +552,7 @@ static struct usb_serial_driver option_1port_device = {
.num_ports = 1,
.open = option_open,
.close = option_close,
+ .dtr_rts = option_dtr_rts,
.write = option_write,
.write_room = option_write_room,
.chars_in_buffer = option_chars_in_buffer,
@@ -625,7 +632,7 @@ static void option_set_termios(struct tty_struct *tty,
dbg("%s", __func__);
/* Doesn't support option setting */
tty_termios_copy_hw(tty->termios, old_termios);
- option_send_setup(tty, port);
+ option_send_setup(port);
}
static int option_tiocmget(struct tty_struct *tty, struct file *file)
@@ -664,7 +671,7 @@ static int option_tiocmset(struct tty_struct *tty, struct file *file,
portdata->rts_state = 0;
if (clear & TIOCM_DTR)
portdata->dtr_state = 0;
- return option_send_setup(tty, port);
+ return option_send_setup(port);
}
/* Write */
@@ -892,10 +899,6 @@ static int option_open(struct tty_struct *tty,
dbg("%s", __func__);
- /* Set some sane defaults */
- portdata->rts_state = 1;
- portdata->dtr_state = 1;
-
/* Reset low level data toggle and start reading from endpoints */
for (i = 0; i < N_IN_URB; i++) {
urb = portdata->in_urbs[i];
@@ -931,40 +934,43 @@ static int option_open(struct tty_struct *tty,
usb_pipeout(urb->pipe), 0); */
}
- if (tty)
- tty->low_latency = 1;
-
- option_send_setup(tty, port);
+ option_send_setup(port);
return 0;
}
-static void option_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void option_dtr_rts(struct usb_serial_port *port, int on)
{
- int i;
struct usb_serial *serial = port->serial;
struct option_port_private *portdata;
dbg("%s", __func__);
portdata = usb_get_serial_port_data(port);
+ mutex_lock(&serial->disc_mutex);
+ portdata->rts_state = on;
+ portdata->dtr_state = on;
+ if (serial->dev)
+ option_send_setup(port);
+ mutex_unlock(&serial->disc_mutex);
+}
- portdata->rts_state = 0;
- portdata->dtr_state = 0;
- if (serial->dev) {
- mutex_lock(&serial->disc_mutex);
- if (!serial->disconnected)
- option_send_setup(tty, port);
- mutex_unlock(&serial->disc_mutex);
+static void option_close(struct usb_serial_port *port)
+{
+ int i;
+ struct usb_serial *serial = port->serial;
+ struct option_port_private *portdata;
+
+ dbg("%s", __func__);
+ portdata = usb_get_serial_port_data(port);
+ if (serial->dev) {
/* Stop reading/writing urbs */
for (i = 0; i < N_IN_URB; i++)
usb_kill_urb(portdata->in_urbs[i]);
for (i = 0; i < N_OUT_URB; i++)
usb_kill_urb(portdata->out_urbs[i]);
}
- tty_port_tty_set(&port->port, NULL);
}
/* Helper functions used by option_setup_urbs */
@@ -1030,28 +1036,24 @@ static void option_setup_urbs(struct usb_serial *serial)
* This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN
* CDC.
*/
-static int option_send_setup(struct tty_struct *tty,
- struct usb_serial_port *port)
+static int option_send_setup(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct option_port_private *portdata;
int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+ int val = 0;
dbg("%s", __func__);
portdata = usb_get_serial_port_data(port);
- if (tty) {
- int val = 0;
- if (portdata->dtr_state)
- val |= 0x01;
- if (portdata->rts_state)
- val |= 0x02;
+ if (portdata->dtr_state)
+ val |= 0x01;
+ if (portdata->rts_state)
+ val |= 0x02;
- return usb_control_msg(serial->dev,
- usb_rcvctrlpipe(serial->dev, 0),
- 0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT);
- }
- return 0;
+ return usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ 0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT);
}
static int option_startup(struct usb_serial *serial)
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index ba551f00f16f..7de54781fe61 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -143,8 +143,7 @@ struct oti6858_control_pkt {
/* function prototypes */
static int oti6858_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
-static void oti6858_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp);
+static void oti6858_close(struct usb_serial_port *port);
static void oti6858_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
static int oti6858_ioctl(struct tty_struct *tty, struct file *file,
@@ -622,67 +621,30 @@ static int oti6858_open(struct tty_struct *tty,
if (result != 0) {
dev_err(&port->dev, "%s(): usb_submit_urb() failed"
" with error %d\n", __func__, result);
- oti6858_close(tty, port, NULL);
+ oti6858_close(port);
return -EPROTO;
}
/* setup termios */
if (tty)
oti6858_set_termios(tty, port, &tmp_termios);
-
+ port->port.drain_delay = 256; /* FIXME: check the FIFO length */
return 0;
}
-static void oti6858_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void oti6858_close(struct usb_serial_port *port)
{
struct oti6858_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- long timeout;
- wait_queue_t wait;
dbg("%s(port = %d)", __func__, port->number);
- /* wait for data to drain from the buffer */
spin_lock_irqsave(&priv->lock, flags);
- timeout = 30 * HZ; /* PL2303_CLOSING_WAIT */
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&tty->write_wait, &wait);
- dbg("%s(): entering wait loop", __func__);
- for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
- if (oti6858_buf_data_avail(priv->buf) == 0
- || timeout == 0 || signal_pending(current)
- || port->serial->disconnected)
- break;
- spin_unlock_irqrestore(&priv->lock, flags);
- timeout = schedule_timeout(timeout);
- spin_lock_irqsave(&priv->lock, flags);
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&tty->write_wait, &wait);
- dbg("%s(): after wait loop", __func__);
-
/* clear out any remaining data in the buffer */
oti6858_buf_clear(priv->buf);
spin_unlock_irqrestore(&priv->lock, flags);
- /* wait for characters to drain from the device */
- /* (this is long enough for the entire 256 byte */
- /* pl2303 hardware buffer to drain with no flow */
- /* control for data rates of 1200 bps or more, */
- /* for lower rates we should really know how much */
- /* data is in the buffer to compute a delay */
- /* that is not unnecessarily long) */
- /* FIXME
- bps = tty_get_baud_rate(tty);
- if (bps > 1200)
- timeout = max((HZ*2560)/bps,HZ/10);
- else
- */
- timeout = 2*HZ;
- schedule_timeout_interruptible(timeout);
- dbg("%s(): after schedule_timeout_interruptible()", __func__);
+ dbg("%s(): after buf_clear()", __func__);
/* cancel scheduled setup */
cancel_delayed_work(&priv->delayed_setup_work);
@@ -694,15 +656,6 @@ static void oti6858_close(struct tty_struct *tty,
usb_kill_urb(port->write_urb);
usb_kill_urb(port->read_urb);
usb_kill_urb(port->interrupt_in_urb);
-
- /*
- if (tty && (tty->termios->c_cflag) & HUPCL) {
- // drop DTR and RTS
- spin_lock_irqsave(&priv->lock, flags);
- priv->pending_setup.control &= ~CONTROL_MASK;
- spin_unlock_irqrestore(&priv->lock, flags);
- }
- */
}
static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 751a533a4347..e02dc3d643c7 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -652,69 +652,41 @@ static void pl2303_set_termios(struct tty_struct *tty,
kfree(buf);
}
-static void pl2303_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void pl2303_dtr_rts(struct usb_serial_port *port, int on)
+{
+ struct pl2303_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+ u8 control;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ /* Change DTR and RTS */
+ if (on)
+ priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
+ else
+ priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
+ control = priv->line_control;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ set_control_lines(port->serial->dev, control);
+}
+
+static void pl2303_close(struct usb_serial_port *port)
{
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- unsigned int c_cflag;
- int bps;
- long timeout;
- wait_queue_t wait;
dbg("%s - port %d", __func__, port->number);
- /* wait for data to drain from the buffer */
spin_lock_irqsave(&priv->lock, flags);
- timeout = PL2303_CLOSING_WAIT;
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&tty->write_wait, &wait);
- for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
- if (pl2303_buf_data_avail(priv->buf) == 0 ||
- timeout == 0 || signal_pending(current) ||
- port->serial->disconnected)
- break;
- spin_unlock_irqrestore(&priv->lock, flags);
- timeout = schedule_timeout(timeout);
- spin_lock_irqsave(&priv->lock, flags);
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&tty->write_wait, &wait);
/* clear out any remaining data in the buffer */
pl2303_buf_clear(priv->buf);
spin_unlock_irqrestore(&priv->lock, flags);
- /* wait for characters to drain from the device */
- /* (this is long enough for the entire 256 byte */
- /* pl2303 hardware buffer to drain with no flow */
- /* control for data rates of 1200 bps or more, */
- /* for lower rates we should really know how much */
- /* data is in the buffer to compute a delay */
- /* that is not unnecessarily long) */
- bps = tty_get_baud_rate(tty);
- if (bps > 1200)
- timeout = max((HZ*2560)/bps, HZ/10);
- else
- timeout = 2*HZ;
- schedule_timeout_interruptible(timeout);
-
/* shutdown our urbs */
dbg("%s - shutting down urbs", __func__);
usb_kill_urb(port->write_urb);
usb_kill_urb(port->read_urb);
usb_kill_urb(port->interrupt_in_urb);
- if (tty) {
- c_cflag = tty->termios->c_cflag;
- if (c_cflag & HUPCL) {
- /* drop DTR and RTS */
- spin_lock_irqsave(&priv->lock, flags);
- priv->line_control = 0;
- spin_unlock_irqrestore(&priv->lock, flags);
- set_control_lines(port->serial->dev, 0);
- }
- }
}
static int pl2303_open(struct tty_struct *tty,
@@ -748,7 +720,7 @@ static int pl2303_open(struct tty_struct *tty,
if (result) {
dev_err(&port->dev, "%s - failed submitting read urb,"
" error %d\n", __func__, result);
- pl2303_close(tty, port, NULL);
+ pl2303_close(port);
return -EPROTO;
}
@@ -758,9 +730,10 @@ static int pl2303_open(struct tty_struct *tty,
if (result) {
dev_err(&port->dev, "%s - failed submitting interrupt urb,"
" error %d\n", __func__, result);
- pl2303_close(tty, port, NULL);
+ pl2303_close(port);
return -EPROTO;
}
+ port->port.drain_delay = 256;
return 0;
}
@@ -821,6 +794,14 @@ static int pl2303_tiocmget(struct tty_struct *tty, struct file *file)
return result;
}
+static int pl2303_carrier_raised(struct usb_serial_port *port)
+{
+ struct pl2303_private *priv = usb_get_serial_port_data(port);
+ if (priv->line_status & UART_DCD)
+ return 1;
+ return 0;
+}
+
static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
{
struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -1125,6 +1106,8 @@ static struct usb_serial_driver pl2303_device = {
.num_ports = 1,
.open = pl2303_open,
.close = pl2303_close,
+ .dtr_rts = pl2303_dtr_rts,
+ .carrier_raised = pl2303_carrier_raised,
.write = pl2303_write,
.ioctl = pl2303_ioctl,
.break_ctl = pl2303_break_ctl,
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index e6d6b0c17fd9..7528b8d57f1c 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -26,6 +26,27 @@ static struct usb_device_id id_table[] = {
{USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
{USB_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */
{USB_DEVICE(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */
+ {USB_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */
+ {USB_DEVICE(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */
+ {USB_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */
+ {USB_DEVICE(0x413c, 0x8171)}, /* Dell Gobi QDL device */
+ {USB_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */
+ {USB_DEVICE(0x1410, 0xa008)}, /* Novatel Gobi QDL device */
+ {USB_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */
+ {USB_DEVICE(0x0b05, 0x1774)}, /* Asus Gobi QDL device */
+ {USB_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */
+ {USB_DEVICE(0x19d2, 0xfff2)}, /* ONDA Gobi QDL device */
+ {USB_DEVICE(0x1557, 0x0a80)}, /* OQO Gobi QDL device */
+ {USB_DEVICE(0x05c6, 0x9001)}, /* Generic Gobi Modem device */
+ {USB_DEVICE(0x05c6, 0x9002)}, /* Generic Gobi Modem device */
+ {USB_DEVICE(0x05c6, 0x9202)}, /* Generic Gobi Modem device */
+ {USB_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */
+ {USB_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */
+ {USB_DEVICE(0x05c6, 0x9008)}, /* Generic Gobi QDL device */
+ {USB_DEVICE(0x05c6, 0x9201)}, /* Generic Gobi QDL device */
+ {USB_DEVICE(0x05c6, 0x9221)}, /* Generic Gobi QDL device */
+ {USB_DEVICE(0x05c6, 0x9231)}, /* Generic Gobi QDL device */
+ {USB_DEVICE(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, id_table);
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index d9bf9a5c20ec..1319b8968d82 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -14,7 +14,7 @@
Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org>
*/
-#define DRIVER_VERSION "v.1.3.2"
+#define DRIVER_VERSION "v.1.3.3"
#define DRIVER_AUTHOR "Kevin Lloyd <klloyd@sierrawireless.com>"
#define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
@@ -240,44 +240,39 @@ struct sierra_port_private {
int ri_state;
};
-static int sierra_send_setup(struct tty_struct *tty,
- struct usb_serial_port *port)
+static int sierra_send_setup(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct sierra_port_private *portdata;
__u16 interface = 0;
+ int val = 0;
dev_dbg(&port->dev, "%s", __func__);
portdata = usb_get_serial_port_data(port);
- if (tty) {
- int val = 0;
- if (portdata->dtr_state)
- val |= 0x01;
- if (portdata->rts_state)
- val |= 0x02;
-
- /* If composite device then properly report interface */
- if (serial->num_ports == 1)
- interface = sierra_calc_interface(serial);
-
- /* Otherwise the need to do non-composite mapping */
- else {
- if (port->bulk_out_endpointAddress == 2)
- interface = 0;
- else if (port->bulk_out_endpointAddress == 4)
- interface = 1;
- else if (port->bulk_out_endpointAddress == 5)
- interface = 2;
- }
-
- return usb_control_msg(serial->dev,
- usb_rcvctrlpipe(serial->dev, 0),
- 0x22, 0x21, val, interface,
- NULL, 0, USB_CTRL_SET_TIMEOUT);
+ if (portdata->dtr_state)
+ val |= 0x01;
+ if (portdata->rts_state)
+ val |= 0x02;
+
+ /* If composite device then properly report interface */
+ if (serial->num_ports == 1)
+ interface = sierra_calc_interface(serial);
+
+ /* Otherwise the need to do non-composite mapping */
+ else {
+ if (port->bulk_out_endpointAddress == 2)
+ interface = 0;
+ else if (port->bulk_out_endpointAddress == 4)
+ interface = 1;
+ else if (port->bulk_out_endpointAddress == 5)
+ interface = 2;
}
-
+ return usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ 0x22, 0x21, val, interface,
+ NULL, 0, USB_CTRL_SET_TIMEOUT);
return 0;
}
@@ -286,7 +281,7 @@ static void sierra_set_termios(struct tty_struct *tty,
{
dev_dbg(&port->dev, "%s", __func__);
tty_termios_copy_hw(tty->termios, old_termios);
- sierra_send_setup(tty, port);
+ sierra_send_setup(port);
}
static int sierra_tiocmget(struct tty_struct *tty, struct file *file)
@@ -325,7 +320,7 @@ static int sierra_tiocmset(struct tty_struct *tty, struct file *file,
portdata->rts_state = 0;
if (clear & TIOCM_DTR)
portdata->dtr_state = 0;
- return sierra_send_setup(tty, port);
+ return sierra_send_setup(port);
}
static void sierra_outdat_callback(struct urb *urb)
@@ -585,10 +580,7 @@ static int sierra_open(struct tty_struct *tty,
}
}
- if (tty)
- tty->low_latency = 1;
-
- sierra_send_setup(tty, port);
+ sierra_send_setup(port);
/* start up the interrupt endpoint if we have one */
if (port->interrupt_in_urb) {
@@ -600,32 +592,38 @@ static int sierra_open(struct tty_struct *tty,
return 0;
}
-static void sierra_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void sierra_dtr_rts(struct usb_serial_port *port, int on)
{
- int i;
struct usb_serial *serial = port->serial;
struct sierra_port_private *portdata;
- dev_dbg(&port->dev, "%s", __func__);
portdata = usb_get_serial_port_data(port);
-
- portdata->rts_state = 0;
- portdata->dtr_state = 0;
+ portdata->rts_state = on;
+ portdata->dtr_state = on;
if (serial->dev) {
mutex_lock(&serial->disc_mutex);
if (!serial->disconnected)
- sierra_send_setup(tty, port);
+ sierra_send_setup(port);
mutex_unlock(&serial->disc_mutex);
+ }
+}
+static void sierra_close(struct usb_serial_port *port)
+{
+ int i;
+ struct usb_serial *serial = port->serial;
+ struct sierra_port_private *portdata;
+
+ dev_dbg(&port->dev, "%s", __func__);
+ portdata = usb_get_serial_port_data(port);
+
+ if (serial->dev) {
/* Stop reading/writing urbs */
for (i = 0; i < N_IN_URB; i++)
usb_kill_urb(portdata->in_urbs[i]);
}
-
usb_kill_urb(port->interrupt_in_urb);
- tty_port_tty_set(&port->port, NULL);
}
static int sierra_startup(struct usb_serial *serial)
@@ -727,6 +725,7 @@ static struct usb_serial_driver sierra_device = {
.probe = sierra_probe,
.open = sierra_open,
.close = sierra_close,
+ .dtr_rts = sierra_dtr_rts,
.write = sierra_write,
.write_room = sierra_write_room,
.set_termios = sierra_set_termios,
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index 5e7528cc81a8..8f7ed8f13996 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -446,66 +446,47 @@ static void spcp8x5_set_workMode(struct usb_device *dev, u16 value,
"RTSCTS usb_control_msg(enable flowctrl) = %d\n", ret);
}
+static int spcp8x5_carrier_raised(struct usb_serial_port *port)
+{
+ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+ if (priv->line_status & MSR_STATUS_LINE_DCD)
+ return 1;
+ return 0;
+}
+
+static void spcp8x5_dtr_rts(struct usb_serial_port *port, int on)
+{
+ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+ u8 control;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (on)
+ priv->line_control = MCR_CONTROL_LINE_DTR
+ | MCR_CONTROL_LINE_RTS;
+ else
+ priv->line_control &= ~ (MCR_CONTROL_LINE_DTR
+ | MCR_CONTROL_LINE_RTS);
+ control = priv->line_control;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
+}
+
/* close the serial port. We should wait for data sending to device 1st and
* then kill all urb. */
-static void spcp8x5_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void spcp8x5_close(struct usb_serial_port *port)
{
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- unsigned int c_cflag;
- int bps;
- long timeout;
- wait_queue_t wait;
int result;
dbg("%s - port %d", __func__, port->number);
- /* wait for data to drain from the buffer */
spin_lock_irqsave(&priv->lock, flags);
- timeout = SPCP8x5_CLOSING_WAIT;
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&tty->write_wait, &wait);
- for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
- if (ringbuf_avail_data(priv->buf) == 0 ||
- timeout == 0 || signal_pending(current))
- break;
- spin_unlock_irqrestore(&priv->lock, flags);
- timeout = schedule_timeout(timeout);
- spin_lock_irqsave(&priv->lock, flags);
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&tty->write_wait, &wait);
-
/* clear out any remaining data in the buffer */
clear_ringbuf(priv->buf);
spin_unlock_irqrestore(&priv->lock, flags);
- /* wait for characters to drain from the device (this is long enough
- * for the entire all byte spcp8x5 hardware buffer to drain with no
- * flow control for data rates of 1200 bps or more, for lower rates we
- * should really know how much data is in the buffer to compute a delay
- * that is not unnecessarily long) */
- bps = tty_get_baud_rate(tty);
- if (bps > 1200)
- timeout = max((HZ*2560) / bps, HZ/10);
- else
- timeout = 2*HZ;
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(timeout);
-
- /* clear control lines */
- if (tty) {
- c_cflag = tty->termios->c_cflag;
- if (c_cflag & HUPCL) {
- spin_lock_irqsave(&priv->lock, flags);
- priv->line_control = 0;
- spin_unlock_irqrestore(&priv->lock, flags);
- spcp8x5_set_ctrlLine(port->serial->dev, 0 , priv->type);
- }
- }
-
/* kill urb */
if (port->write_urb != NULL) {
result = usb_unlink_urb(port->write_urb);
@@ -665,13 +646,6 @@ static int spcp8x5_open(struct tty_struct *tty,
if (ret)
return ret;
- spin_lock_irqsave(&priv->lock, flags);
- if (tty && (tty->termios->c_cflag & CBAUD))
- priv->line_control = MCR_DTR | MCR_RTS;
- else
- priv->line_control = 0;
- spin_unlock_irqrestore(&priv->lock, flags);
-
spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type);
/* Setup termios */
@@ -691,9 +665,10 @@ static int spcp8x5_open(struct tty_struct *tty,
port->read_urb->dev = serial->dev;
ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (ret) {
- spcp8x5_close(tty, port, NULL);
+ spcp8x5_close(port);
return -EPROTO;
}
+ port->port.drain_delay = 256;
return 0;
}
@@ -1033,6 +1008,8 @@ static struct usb_serial_driver spcp8x5_device = {
.num_ports = 1,
.open = spcp8x5_open,
.close = spcp8x5_close,
+ .dtr_rts = spcp8x5_dtr_rts,
+ .carrier_raised = spcp8x5_carrier_raised,
.write = spcp8x5_write,
.set_termios = spcp8x5_set_termios,
.ioctl = spcp8x5_ioctl,
diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c
index 69879e437940..8b07ebc6baeb 100644
--- a/drivers/usb/serial/symbolserial.c
+++ b/drivers/usb/serial/symbolserial.c
@@ -152,8 +152,7 @@ static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port,
return result;
}
-static void symbol_close(struct tty_struct *tty, struct usb_serial_port *port,
- struct file *filp)
+static void symbol_close(struct usb_serial_port *port)
{
struct symbol_private *priv = usb_get_serial_data(port->serial);
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 2620bf6fe5e1..42cb04c403be 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -50,11 +50,10 @@
#define TI_TRANSFER_TIMEOUT 2
-#define TI_DEFAULT_LOW_LATENCY 0
#define TI_DEFAULT_CLOSING_WAIT 4000 /* in .01 secs */
/* supported setserial flags */
-#define TI_SET_SERIAL_FLAGS (ASYNC_LOW_LATENCY)
+#define TI_SET_SERIAL_FLAGS 0
/* read urb states */
#define TI_READ_URB_RUNNING 0
@@ -101,8 +100,7 @@ static int ti_startup(struct usb_serial *serial);
static void ti_shutdown(struct usb_serial *serial);
static int ti_open(struct tty_struct *tty, struct usb_serial_port *port,
struct file *file);
-static void ti_close(struct tty_struct *tty, struct usb_serial_port *port,
- struct file *file);
+static void ti_close(struct usb_serial_port *port);
static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *data, int count);
static int ti_write_room(struct tty_struct *tty);
@@ -161,7 +159,6 @@ static int ti_buf_get(struct circ_buf *cb, char *buf, int count);
/* module parameters */
static int debug;
-static int low_latency = TI_DEFAULT_LOW_LATENCY;
static int closing_wait = TI_DEFAULT_CLOSING_WAIT;
static ushort vendor_3410[TI_EXTRA_VID_PID_COUNT];
static unsigned int vendor_3410_count;
@@ -296,10 +293,6 @@ MODULE_FIRMWARE("mts_edge.fw");
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Enable debugging, 0=no, 1=yes");
-module_param(low_latency, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(low_latency,
- "TTY low_latency flag, 0=off, 1=on, default is off");
-
module_param(closing_wait, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(closing_wait,
"Maximum wait for data to drain in close, in .01 secs, default is 4000");
@@ -448,7 +441,6 @@ static int ti_startup(struct usb_serial *serial)
spin_lock_init(&tport->tp_lock);
tport->tp_uart_base_addr = (i == 0 ?
TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
- tport->tp_flags = low_latency ? ASYNC_LOW_LATENCY : 0;
tport->tp_closing_wait = closing_wait;
init_waitqueue_head(&tport->tp_msr_wait);
init_waitqueue_head(&tport->tp_write_wait);
@@ -528,10 +520,6 @@ static int ti_open(struct tty_struct *tty,
if (mutex_lock_interruptible(&tdev->td_open_close_lock))
return -ERESTARTSYS;
- if (tty)
- tty->low_latency =
- (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
port_number = port->number - port->serial->minor;
memset(&(tport->tp_icount), 0x00, sizeof(tport->tp_icount));
@@ -658,8 +646,7 @@ release_lock:
}
-static void ti_close(struct tty_struct *tty, struct usb_serial_port *port,
- struct file *file)
+static void ti_close(struct usb_serial_port *port)
{
struct ti_device *tdev;
struct ti_port *tport;
@@ -1215,20 +1202,22 @@ static void ti_bulk_in_callback(struct urb *urb)
}
tty = tty_port_tty_get(&port->port);
- if (tty && urb->actual_length) {
- usb_serial_debug_data(debug, dev, __func__,
- urb->actual_length, urb->transfer_buffer);
-
- if (!tport->tp_is_open)
- dbg("%s - port closed, dropping data", __func__);
- else
- ti_recv(&urb->dev->dev, tty,
+ if (tty) {
+ if (urb->actual_length) {
+ usb_serial_debug_data(debug, dev, __func__,
+ urb->actual_length, urb->transfer_buffer);
+
+ if (!tport->tp_is_open)
+ dbg("%s - port closed, dropping data",
+ __func__);
+ else
+ ti_recv(&urb->dev->dev, tty,
urb->transfer_buffer,
urb->actual_length);
-
- spin_lock(&tport->tp_lock);
- tport->tp_icount.rx += urb->actual_length;
- spin_unlock(&tport->tp_lock);
+ spin_lock(&tport->tp_lock);
+ tport->tp_icount.rx += urb->actual_length;
+ spin_unlock(&tport->tp_lock);
+ }
tty_kref_put(tty);
}
@@ -1452,7 +1441,6 @@ static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport,
return -EFAULT;
tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS;
- tty->low_latency = (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0;
tport->tp_closing_wait = new_serial.closing_wait;
return 0;
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 2a70563bbee1..f1eb80537d8d 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -137,22 +137,10 @@ static void destroy_serial(struct kref *kref)
dbg("%s - %s", __func__, serial->type->description);
- serial->type->shutdown(serial);
-
/* return the minor range that this device had */
if (serial->minor != SERIAL_TTY_NO_MINOR)
return_serial(serial);
- for (i = 0; i < serial->num_ports; ++i)
- serial->port[i]->port.count = 0;
-
- /* the ports are cleaned up and released in port_release() */
- for (i = 0; i < serial->num_ports; ++i)
- if (serial->port[i]->dev.parent != NULL) {
- device_unregister(&serial->port[i]->dev);
- serial->port[i] = NULL;
- }
-
/* If this is a "fake" port, we have to clean it up here, as it will
* not get cleaned up in port_release() as it was never registered with
* the driver core */
@@ -187,7 +175,7 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
struct usb_serial *serial;
struct usb_serial_port *port;
unsigned int portNumber;
- int retval;
+ int retval = 0;
dbg("%s", __func__);
@@ -198,21 +186,24 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
return -ENODEV;
}
+ mutex_lock(&serial->disc_mutex);
portNumber = tty->index - serial->minor;
port = serial->port[portNumber];
- if (!port) {
+ if (!port || serial->disconnected)
retval = -ENODEV;
- goto bailout_kref_put;
- }
-
- if (port->serial->disconnected) {
- retval = -ENODEV;
- goto bailout_kref_put;
- }
+ else
+ get_device(&port->dev);
+ /*
+ * Note: Our locking order requirement does not allow port->mutex
+ * to be acquired while serial->disc_mutex is held.
+ */
+ mutex_unlock(&serial->disc_mutex);
+ if (retval)
+ goto bailout_serial_put;
if (mutex_lock_interruptible(&port->mutex)) {
retval = -ERESTARTSYS;
- goto bailout_kref_put;
+ goto bailout_port_put;
}
++port->port.count;
@@ -232,80 +223,127 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
goto bailout_mutex_unlock;
}
- retval = usb_autopm_get_interface(serial->interface);
+ mutex_lock(&serial->disc_mutex);
+ if (serial->disconnected)
+ retval = -ENODEV;
+ else
+ retval = usb_autopm_get_interface(serial->interface);
if (retval)
goto bailout_module_put;
+
/* only call the device specific open if this
* is the first time the port is opened */
retval = serial->type->open(tty, port, filp);
if (retval)
goto bailout_interface_put;
+ mutex_unlock(&serial->disc_mutex);
}
-
mutex_unlock(&port->mutex);
- return 0;
+ /* Now do the correct tty layer semantics */
+ retval = tty_port_block_til_ready(&port->port, tty, filp);
+ if (retval == 0)
+ return 0;
bailout_interface_put:
usb_autopm_put_interface(serial->interface);
bailout_module_put:
+ mutex_unlock(&serial->disc_mutex);
module_put(serial->type->driver.owner);
bailout_mutex_unlock:
port->port.count = 0;
tty->driver_data = NULL;
tty_port_tty_set(&port->port, NULL);
mutex_unlock(&port->mutex);
-bailout_kref_put:
+bailout_port_put:
+ put_device(&port->dev);
+bailout_serial_put:
usb_serial_put(serial);
return retval;
}
-static void serial_close(struct tty_struct *tty, struct file *filp)
+/**
+ * serial_do_down - shut down hardware
+ * @port: port to shut down
+ *
+ * Shut down a USB port unless it is the console. We never shut down the
+ * console hardware as it will always be in use.
+ *
+ * Don't free any resources at this point
+ */
+static void serial_do_down(struct usb_serial_port *port)
{
- struct usb_serial_port *port = tty->driver_data;
+ struct usb_serial_driver *drv = port->serial->type;
+ struct usb_serial *serial;
+ struct module *owner;
- if (!port)
+ /* The console is magical, do not hang up the console hardware
+ or there will be tears */
+ if (port->console)
return;
- dbg("%s - port %d", __func__, port->number);
-
mutex_lock(&port->mutex);
+ serial = port->serial;
+ owner = serial->type->driver.owner;
+
+ if (drv->close)
+ drv->close(port);
+
+ mutex_unlock(&port->mutex);
+}
+
+/**
+ * serial_do_free - free resources post close/hangup
+ * @port: port to free up
+ *
+ * Do the resource freeing and refcount dropping for the port. We must
+ * be careful about ordering and we must avoid freeing up the console.
+ */
- if (port->port.count == 0) {
- mutex_unlock(&port->mutex);
+static void serial_do_free(struct usb_serial_port *port)
+{
+ struct usb_serial *serial;
+ struct module *owner;
+
+ /* The console is magical, do not hang up the console hardware
+ or there will be tears */
+ if (port->console)
return;
- }
- if (port->port.count == 1)
- /* only call the device specific close if this
- * port is being closed by the last owner. Ensure we do
- * this before we drop the port count. The call is protected
- * by the port mutex
- */
- port->serial->type->close(tty, port, filp);
-
- if (port->port.count == (port->console ? 2 : 1)) {
- struct tty_struct *tty = tty_port_tty_get(&port->port);
- if (tty) {
- /* We must do this before we drop the port count to
- zero. */
- if (tty->driver_data)
- tty->driver_data = NULL;
- tty_port_tty_set(&port->port, NULL);
- tty_kref_put(tty);
- }
- }
+ serial = port->serial;
+ owner = serial->type->driver.owner;
+ put_device(&port->dev);
+ /* Mustn't dereference port any more */
+ mutex_lock(&serial->disc_mutex);
+ if (!serial->disconnected)
+ usb_autopm_put_interface(serial->interface);
+ mutex_unlock(&serial->disc_mutex);
+ usb_serial_put(serial);
+ /* Mustn't dereference serial any more */
+ module_put(owner);
+}
- if (port->port.count == 1) {
- mutex_lock(&port->serial->disc_mutex);
- if (!port->serial->disconnected)
- usb_autopm_put_interface(port->serial->interface);
- mutex_unlock(&port->serial->disc_mutex);
- module_put(port->serial->type->driver.owner);
- }
- --port->port.count;
+static void serial_close(struct tty_struct *tty, struct file *filp)
+{
+ struct usb_serial_port *port = tty->driver_data;
- mutex_unlock(&port->mutex);
- usb_serial_put(port->serial);
+ dbg("%s - port %d", __func__, port->number);
+
+
+ if (tty_port_close_start(&port->port, tty, filp) == 0)
+ return;
+
+ serial_do_down(port);
+ tty_port_close_end(&port->port, tty);
+ tty_port_tty_set(&port->port, NULL);
+ serial_do_free(port);
+}
+
+static void serial_hangup(struct tty_struct *tty)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ serial_do_down(port);
+ tty_port_hangup(&port->port);
+ serial_do_free(port);
}
static int serial_write(struct tty_struct *tty, const unsigned char *buf,
@@ -549,7 +587,13 @@ static void kill_traffic(struct usb_serial_port *port)
static void port_free(struct usb_serial_port *port)
{
+ /*
+ * Stop all the traffic before cancelling the work, so that
+ * nobody will restart it by calling usb_serial_port_softint.
+ */
kill_traffic(port);
+ cancel_work_sync(&port->work);
+
usb_free_urb(port->read_urb);
usb_free_urb(port->write_urb);
usb_free_urb(port->interrupt_in_urb);
@@ -558,7 +602,6 @@ static void port_free(struct usb_serial_port *port)
kfree(port->bulk_out_buffer);
kfree(port->interrupt_in_buffer);
kfree(port->interrupt_out_buffer);
- flush_scheduled_work(); /* port->work */
kfree(port);
}
@@ -632,6 +675,29 @@ static struct usb_serial_driver *search_serial_device(
return NULL;
}
+static int serial_carrier_raised(struct tty_port *port)
+{
+ struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
+ struct usb_serial_driver *drv = p->serial->type;
+ if (drv->carrier_raised)
+ return drv->carrier_raised(p);
+ /* No carrier control - don't block */
+ return 1;
+}
+
+static void serial_dtr_rts(struct tty_port *port, int on)
+{
+ struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
+ struct usb_serial_driver *drv = p->serial->type;
+ if (drv->dtr_rts)
+ drv->dtr_rts(p, on);
+}
+
+static const struct tty_port_operations serial_port_ops = {
+ .carrier_raised = serial_carrier_raised,
+ .dtr_rts = serial_dtr_rts,
+};
+
int usb_serial_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
@@ -825,6 +891,7 @@ int usb_serial_probe(struct usb_interface *interface,
if (!port)
goto probe_error;
tty_port_init(&port->port);
+ port->port.ops = &serial_port_ops;
port->serial = serial;
spin_lock_init(&port->lock);
mutex_init(&port->mutex);
@@ -1043,20 +1110,39 @@ void usb_serial_disconnect(struct usb_interface *interface)
usb_set_intfdata(interface, NULL);
/* must set a flag, to signal subdrivers */
serial->disconnected = 1;
+ mutex_unlock(&serial->disc_mutex);
+
+ /* Unfortunately, many of the sub-drivers expect the port structures
+ * to exist when their shutdown method is called, so we have to go
+ * through this awkward two-step unregistration procedure.
+ */
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
if (port) {
struct tty_struct *tty = tty_port_tty_get(&port->port);
if (tty) {
+ /* The hangup will occur asynchronously but
+ the object refcounts will sort out all the
+ cleanup */
tty_hangup(tty);
tty_kref_put(tty);
}
kill_traffic(port);
+ cancel_work_sync(&port->work);
+ device_del(&port->dev);
}
}
+ serial->type->shutdown(serial);
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = serial->port[i];
+ if (port) {
+ put_device(&port->dev);
+ serial->port[i] = NULL;
+ }
+ }
+
/* let the last holder of this object
* cause it to be cleaned up */
- mutex_unlock(&serial->disc_mutex);
usb_serial_put(serial);
dev_info(dev, "device disconnected\n");
}
@@ -1102,6 +1188,7 @@ static const struct tty_operations serial_ops = {
.open = serial_open,
.close = serial_close,
.write = serial_write,
+ .hangup = serial_hangup,
.write_room = serial_write_room,
.ioctl = serial_ioctl,
.set_termios = serial_set_termios,
@@ -1114,6 +1201,7 @@ static const struct tty_operations serial_ops = {
.proc_fops = &serial_proc_fops,
};
+
struct tty_driver *usb_serial_tty_driver;
static int __init usb_serial_init(void)
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 4facce3d9364..b15f1c0e1d4a 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -38,8 +38,7 @@
/* function prototypes for a handspring visor */
static int visor_open(struct tty_struct *tty, struct usb_serial_port *port,
struct file *filp);
-static void visor_close(struct tty_struct *tty, struct usb_serial_port *port,
- struct file *filp);
+static void visor_close(struct usb_serial_port *port);
static int visor_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
static int visor_write_room(struct tty_struct *tty);
@@ -296,14 +295,6 @@ static int visor_open(struct tty_struct *tty, struct usb_serial_port *port,
priv->throttled = 0;
spin_unlock_irqrestore(&priv->lock, flags);
- /*
- * Force low_latency on so that our tty_push actually forces the data
- * through, otherwise it is scheduled, and with high data rates (like
- * with OHCI) data can get lost.
- */
- if (tty)
- tty->low_latency = 1;
-
/* Start reading from the device */
usb_fill_bulk_urb(port->read_urb, serial->dev,
usb_rcvbulkpipe(serial->dev,
@@ -332,8 +323,7 @@ exit:
}
-static void visor_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void visor_close(struct usb_serial_port *port)
{
struct visor_private *priv = usb_get_serial_port_data(port);
unsigned char *transfer_buffer;
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 5335d3211c07..7c7295d09f34 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -147,8 +147,7 @@ static int whiteheat_attach(struct usb_serial *serial);
static void whiteheat_shutdown(struct usb_serial *serial);
static int whiteheat_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
-static void whiteheat_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp);
+static void whiteheat_close(struct usb_serial_port *port);
static int whiteheat_write(struct tty_struct *tty,
struct usb_serial_port *port,
const unsigned char *buf, int count);
@@ -712,8 +711,7 @@ exit:
}
-static void whiteheat_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void whiteheat_close(struct usb_serial_port *port)
{
struct whiteheat_private *info = usb_get_serial_port_data(port);
struct whiteheat_urb_wrap *wrap;
@@ -723,31 +721,7 @@ static void whiteheat_close(struct tty_struct *tty,
dbg("%s - port %d", __func__, port->number);
- mutex_lock(&port->serial->disc_mutex);
- /* filp is NULL when called from usb_serial_disconnect */
- if ((filp && (tty_hung_up_p(filp))) || port->serial->disconnected) {
- mutex_unlock(&port->serial->disc_mutex);
- return;
- }
- mutex_unlock(&port->serial->disc_mutex);
-
- tty->closing = 1;
-
-/*
- * Not currently in use; tty_wait_until_sent() calls
- * serial_chars_in_buffer() which deadlocks on the second semaphore
- * acquisition. This should be fixed at some point. Greg's been
- * notified.
- if ((filp->f_flags & (O_NDELAY | O_NONBLOCK)) == 0) {
- tty_wait_until_sent(tty, CLOSING_DELAY);
- }
-*/
-
- tty_driver_flush_buffer(tty);
- tty_ldisc_flush(tty);
-
firm_report_tx_done(port);
-
firm_close(port);
/* shutdown our bulk reads and writes */
@@ -775,10 +749,7 @@ static void whiteheat_close(struct tty_struct *tty,
}
spin_unlock_irq(&info->lock);
mutex_unlock(&info->deathwarrant);
-
stop_command_port(port->serial);
-
- tty->closing = 0;
}
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
index 5be54c019662..ef7e5a8ceab5 100644
--- a/drivers/usb/storage/Makefile
+++ b/drivers/usb/storage/Makefile
@@ -17,7 +17,8 @@ usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \
ifeq ($(CONFIG_USB_LIBUSUAL),)
usb-storage-objs += usual-tables.o
else
- obj-$(CONFIG_USB) += libusual.o usual-tables.o
+ obj-$(CONFIG_USB) += usb-libusual.o
+ usb-libusual-objs := libusual.o usual-tables.o
endif
obj-$(CONFIG_USB_STORAGE_ALAUDA) += ums-alauda.o
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 49aedb36dc19..fcb320217218 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -247,10 +247,8 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
USB_ENDPOINT_HALT, endp,
NULL, 0, 3*HZ);
- /* reset the endpoint toggle */
if (result >= 0)
- usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe),
- usb_pipeout(pipe), 0);
+ usb_reset_endpoint(us->pusb_dev, endp);
US_DEBUGP("%s: result = %d\n", __func__, result);
return result;
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 1c1f643e8a78..4b8b69045fe6 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -160,8 +160,9 @@ UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
-/* Reported by Andrew Nayenko <relan@bk.ru> */
-UNUSUAL_DEV( 0x0421, 0x0019, 0x0592, 0x0592,
+/* Reported by Andrew Nayenko <relan@bk.ru>
+ * Updated for new firmware by Phillip Potter <phillipinda@hotmail.com> */
+UNUSUAL_DEV( 0x0421, 0x0019, 0x0592, 0x0610,
"Nokia",
"Nokia 6288",
US_SC_DEVICE, US_PR_DEVICE, NULL,
@@ -975,12 +976,14 @@ UNUSUAL_DEV( 0x07c4, 0xa400, 0x0000, 0xffff,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY | US_FL_FIX_CAPACITY ),
-/* Reported by Rauch Wolke <rauchwolke@gmx.net> */
+/* Reported by Rauch Wolke <rauchwolke@gmx.net>
+ * and augmented by binbin <binbinsh@gmail.com> (Bugzilla #12882)
+ */
UNUSUAL_DEV( 0x07c4, 0xa4a5, 0x0000, 0xffff,
"Simple Tech/Datafab",
"CF+SM Reader",
US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_IGNORE_RESIDUE ),
+ US_FL_IGNORE_RESIDUE | US_FL_MAX_SECTORS_64 ),
/* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant
* to the USB storage specification in two ways:
@@ -1376,6 +1379,14 @@ UNUSUAL_DEV( 0x10d6, 0x2200, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL,
0),
+/* Reported by Pascal Terjan <pterjan@mandriva.com>
+ * Ignore driver CD mode and force into modem mode by default.
+ */
+UNUSUAL_DEV( 0x1186, 0x3e04, 0x0000, 0x0000,
+ "D-Link",
+ "USB Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, option_ms_init, 0),
+
/* Reported by Kevin Lloyd <linux@sierrawireless.com>
* Entry is needed for the initializer function override,
* which instructs the device to load as a modem
@@ -1841,6 +1852,12 @@ UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_CAPACITY_HEURISTICS),
+/* Reported by Alessio Treglia <quadrispro@ubuntu.com> */
+UNUSUAL_DEV( 0xed10, 0x7636, 0x0001, 0x0001,
+ "TGE",
+ "Digital MP3 Audio Player",
+ US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
+
/* Control/Bulk transport for all SubClass values */
USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR),
diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c
index 386eaa22d215..4ac4300a3f9a 100644
--- a/drivers/usb/wusbcore/devconnect.c
+++ b/drivers/usb/wusbcore/devconnect.c
@@ -267,6 +267,8 @@ static void wusbhc_devconnect_acked_work(struct work_struct *work)
mutex_lock(&wusbhc->mutex);
wusbhc_devconnect_acked(wusbhc, wusb_dev);
mutex_unlock(&wusbhc->mutex);
+
+ wusb_dev_put(wusb_dev);
}
/*
@@ -396,7 +398,8 @@ static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc,
/* After a device disconnects, change the GTK (see [WUSB]
* section 6.2.11.2). */
- wusbhc_gtk_rekey(wusbhc);
+ if (wusbhc->active)
+ wusbhc_gtk_rekey(wusbhc);
/* The Wireless USB part has forgotten about the device already; now
* khubd's timer will pick up the disconnection and remove the USB
@@ -1084,15 +1087,21 @@ error_mmcie_set:
* wusbhc_devconnect_stop - stop managing connected devices
* @wusbhc: the WUSB HC
*
- * Removes the Host Info IE and stops the keep alives.
- *
- * FIXME: should this disconnect all devices?
+ * Disconnects any devices still connected, stops the keep alives and
+ * removes the Host Info IE.
*/
void wusbhc_devconnect_stop(struct wusbhc *wusbhc)
{
- cancel_delayed_work_sync(&wusbhc->keep_alive_timer);
- WARN_ON(!list_empty(&wusbhc->cack_list));
+ int i;
+ mutex_lock(&wusbhc->mutex);
+ for (i = 0; i < wusbhc->ports_max; i++) {
+ if (wusbhc->port[i].wusb_dev)
+ __wusbhc_dev_disconnect(wusbhc, &wusbhc->port[i]);
+ }
+ mutex_unlock(&wusbhc->mutex);
+
+ cancel_delayed_work_sync(&wusbhc->keep_alive_timer);
wusbhc_mmcie_rm(wusbhc, &wusbhc->wuie_host_info->hdr);
kfree(wusbhc->wuie_host_info);
wusbhc->wuie_host_info = NULL;
diff --git a/drivers/usb/wusbcore/wusbhc.c b/drivers/usb/wusbcore/wusbhc.c
index 07c63a31c799..ee6256f23636 100644
--- a/drivers/usb/wusbcore/wusbhc.c
+++ b/drivers/usb/wusbcore/wusbhc.c
@@ -88,33 +88,31 @@ static DEVICE_ATTR(wusb_trust_timeout, 0644, wusb_trust_timeout_show,
wusb_trust_timeout_store);
/*
- * Show & store the current WUSB CHID
+ * Show the current WUSB CHID.
*/
static ssize_t wusb_chid_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct wusbhc *wusbhc = usbhc_dev_to_wusbhc(dev);
+ const struct wusb_ckhdid *chid;
ssize_t result = 0;
if (wusbhc->wuie_host_info != NULL)
- result += ckhdid_printf(buf, PAGE_SIZE,
- &wusbhc->wuie_host_info->CHID);
+ chid = &wusbhc->wuie_host_info->CHID;
+ else
+ chid = &wusb_ckhdid_zero;
+
+ result += ckhdid_printf(buf, PAGE_SIZE, chid);
+ result += sprintf(buf + result, "\n");
+
return result;
}
/*
- * Store a new CHID
- *
- * This will (FIXME) trigger many changes.
- *
- * - Send an all zeros CHID and it will stop the controller
- * - Send a non-zero CHID and it will start it
- * (unless it was started, it will just change the CHID,
- * diconnecting all devices first).
+ * Store a new CHID.
*
- * So first we scan the MMC we are sent and then we act on it. We
- * read it in the same format as we print it, an ASCII string of 16
- * hex bytes.
+ * - Write an all zeros CHID and it will stop the controller
+ * - Write a non-zero CHID and it will start it.
*
* See wusbhc_chid_set() for more info.
*/
@@ -339,13 +337,15 @@ void wusbhc_giveback_urb(struct wusbhc *wusbhc, struct urb *urb, int status)
{
struct wusb_dev *wusb_dev = __wusb_dev_get_by_usb_dev(wusbhc, urb->dev);
- if (status == 0) {
+ if (status == 0 && wusb_dev) {
wusb_dev->entry_ts = jiffies;
- /* wusbhc_devconnect_acked() can't be called from from
+ /* wusbhc_devconnect_acked() can't be called from
atomic context so defer it to a work queue. */
if (!list_empty(&wusb_dev->cack_node))
queue_work(wusbd, &wusb_dev->devconnect_acked_work);
+ else
+ wusb_dev_put(wusb_dev);
}
usb_hcd_giveback_urb(&wusbhc->usb_hcd, urb, status);
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 0dbd6c68d76b..d8d0be5151e3 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -56,7 +56,6 @@ obj-$(CONFIG_FB_CT65550) += chipsfb.o
obj-$(CONFIG_FB_IMSTT) += imsttfb.o
obj-$(CONFIG_FB_FM2) += fm2fb.o
obj-$(CONFIG_FB_VT8623) += vt8623fb.o
-obj-$(CONFIG_FB_CYBLA) += cyblafb.o
obj-$(CONFIG_FB_TRIDENT) += tridentfb.o
obj-$(CONFIG_FB_LE80578) += vermilion/
obj-$(CONFIG_FB_S3) += s3fb.o
diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c
index 1a1f946d8fef..9fe90ce928fb 100644
--- a/drivers/video/asiliantfb.c
+++ b/drivers/video/asiliantfb.c
@@ -533,6 +533,7 @@ static int __devinit init_asiliant(struct fb_info *p, unsigned long addr)
writeb(0xff, mmio_base + 0x78c);
chips_hw_init(p);
+ return 0;
}
static int __devinit
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 35e8eb02b9e9..e4e4d433b007 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -354,7 +354,7 @@ static int default_crt_on __devinitdata = 0;
static int default_lcd_on __devinitdata = 1;
#ifdef CONFIG_MTRR
-static int mtrr = 1;
+static bool mtrr = true;
#endif
#ifdef CONFIG_PMAC_BACKLIGHT
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 16bb7e3c0310..6c37e8ee5efe 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -698,8 +698,8 @@ static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo)
found:
/*
* Some methods fail to retrieve SCLK and MCLK values, we apply default
- * settings in this case (200Mhz). If that really happne often, we could
- * fetch from registers instead...
+ * settings in this case (200Mhz). If that really happens often, we
+ * could fetch from registers instead...
*/
if (rinfo->pll.mclk == 0)
rinfo->pll.mclk = 20000;
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index dd37cbcaf8ce..157057c79ca3 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -35,8 +35,6 @@ static int fb_notifier_callback(struct notifier_block *self,
return 0;
bd = container_of(self, struct backlight_device, fb_notif);
- if (!lock_fb_info(evdata->info))
- return -ENODEV;
mutex_lock(&bd->ops_lock);
if (bd->ops)
if (!bd->ops->check_fb ||
@@ -49,7 +47,6 @@ static int fb_notifier_callback(struct notifier_block *self,
backlight_update_status(bd);
}
mutex_unlock(&bd->ops_lock);
- unlock_fb_info(evdata->info);
return 0;
}
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index 0bb13df0fa89..b6449470106c 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -40,8 +40,6 @@ static int fb_notifier_callback(struct notifier_block *self,
if (!ld->ops)
return 0;
- if (!lock_fb_info(evdata->info))
- return -ENODEV;
mutex_lock(&ld->ops_lock);
if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info)) {
if (event == FB_EVENT_BLANK) {
@@ -53,7 +51,6 @@ static int fb_notifier_callback(struct notifier_block *self,
}
}
mutex_unlock(&ld->ops_lock);
- unlock_fb_info(evdata->info);
return 0;
}
diff --git a/drivers/video/cfbfillrect.c b/drivers/video/cfbfillrect.c
index 64b35766b2a2..ba9f58b2a5e8 100644
--- a/drivers/video/cfbfillrect.c
+++ b/drivers/video/cfbfillrect.c
@@ -9,10 +9,6 @@
*
* NOTES:
*
- * The code for depths like 24 that don't have integer number of pixels per
- * long is broken and needs to be fixed. For now I turned these types of
- * mode off.
- *
* Also need to add code to deal with cards endians that are different than
* the native cpu endians. I also need to deal with MSB position in the word.
*
@@ -139,7 +135,7 @@ bitfill_unaligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
// Trailing bits
if (last)
- FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
+ FB_WRITEL(comp(pat, FB_READL(dst), last), dst);
}
}
@@ -281,7 +277,7 @@ bitfill_unaligned_rev(struct fb_info *p, unsigned long __iomem *dst,
void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
{
- unsigned long pat, fg;
+ unsigned long pat, pat2, fg;
unsigned long width = rect->width, height = rect->height;
int bits = BITS_PER_LONG, bytes = bits >> 3;
u32 bpp = p->var.bits_per_pixel;
@@ -297,7 +293,7 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
else
fg = rect->color;
- pat = pixel_to_pat( bpp, fg);
+ pat = pixel_to_pat(bpp, fg);
dst = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1));
dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;
@@ -333,17 +329,16 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
dst_idx += p->fix.line_length*8;
}
} else {
- int right;
- int r;
- int rot = (left-dst_idx) % bpp;
+ int right, r;
void (*fill_op)(struct fb_info *p, unsigned long __iomem *dst,
int dst_idx, unsigned long pat, int left,
int right, unsigned n, int bits) = NULL;
-
- /* rotate pattern to correct start position */
- pat = pat << rot | pat >> (bpp-rot);
-
- right = bpp-left;
+#ifdef __LITTLE_ENDIAN
+ right = left;
+ left = bpp - right;
+#else
+ right = bpp - left;
+#endif
switch (rect->rop) {
case ROP_XOR:
fill_op = bitfill_unaligned_rev;
@@ -352,17 +347,18 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
fill_op = bitfill_unaligned;
break;
default:
- printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
+ printk(KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
fill_op = bitfill_unaligned;
break;
}
while (height--) {
- dst += dst_idx >> (ffs(bits) - 1);
+ dst += dst_idx / bits;
dst_idx &= (bits - 1);
- fill_op(p, dst, dst_idx, pat, left, right,
+ r = dst_idx % bpp;
+ /* rotate pattern to the correct start position */
+ pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp));
+ fill_op(p, dst, dst_idx, pat2, left, right,
width*bpp, bits);
- r = (p->fix.line_length*8) % bpp;
- pat = pat << (bpp-r) | pat >> r;
dst_idx += p->fix.line_length*8;
}
}
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index d42e385f091c..4c2bf923418c 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -567,9 +567,7 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
default:
dev_dbg(info->device,
"Unsupported bpp size: %d\n", var->bits_per_pixel);
- assert(false);
- /* should never occur */
- break;
+ return -EINVAL;
}
if (var->xres_virtual < var->xres)
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 2cd500a304f2..471a9a60376a 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -2263,9 +2263,12 @@ static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
}
+ if (!lock_fb_info(info))
+ return;
event.info = info;
event.data = &blank;
fb_notifier_call_chain(FB_EVENT_CONBLANK, &event);
+ unlock_fb_info(info);
}
static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
@@ -2956,8 +2959,6 @@ static int fbcon_fb_unregistered(struct fb_info *info)
{
int i, idx;
- if (!lock_fb_info(info))
- return -ENODEV;
idx = info->node;
for (i = first_fb_vc; i <= last_fb_vc; i++) {
if (con2fb_map[i] == idx)
@@ -2985,8 +2986,6 @@ static int fbcon_fb_unregistered(struct fb_info *info)
if (primary_device == idx)
primary_device = -1;
- unlock_fb_info(info);
-
if (!num_registered_fb)
unregister_con_driver(&fb_con);
@@ -3027,11 +3026,8 @@ static int fbcon_fb_registered(struct fb_info *info)
{
int ret = 0, i, idx;
- if (!lock_fb_info(info))
- return -ENODEV;
idx = info->node;
fbcon_select_primary(info);
- unlock_fb_info(info);
if (info_idx == -1) {
for (i = first_fb_vc; i <= last_fb_vc; i++) {
@@ -3152,53 +3148,23 @@ static int fbcon_event_notify(struct notifier_block *self,
switch(action) {
case FB_EVENT_SUSPEND:
- if (!lock_fb_info(info)) {
- ret = -ENODEV;
- goto done;
- }
fbcon_suspended(info);
- unlock_fb_info(info);
break;
case FB_EVENT_RESUME:
- if (!lock_fb_info(info)) {
- ret = -ENODEV;
- goto done;
- }
fbcon_resumed(info);
- unlock_fb_info(info);
break;
case FB_EVENT_MODE_CHANGE:
- if (!lock_fb_info(info)) {
- ret = -ENODEV;
- goto done;
- }
fbcon_modechanged(info);
- unlock_fb_info(info);
break;
case FB_EVENT_MODE_CHANGE_ALL:
- if (!lock_fb_info(info)) {
- ret = -ENODEV;
- goto done;
- }
fbcon_set_all_vcs(info);
- unlock_fb_info(info);
break;
case FB_EVENT_MODE_DELETE:
mode = event->data;
- if (!lock_fb_info(info)) {
- ret = -ENODEV;
- goto done;
- }
ret = fbcon_mode_deleted(info, mode);
- unlock_fb_info(info);
break;
case FB_EVENT_FB_UNBIND:
- if (!lock_fb_info(info)) {
- ret = -ENODEV;
- goto done;
- }
idx = info->node;
- unlock_fb_info(info);
ret = fbcon_fb_unbind(idx);
break;
case FB_EVENT_FB_REGISTERED:
@@ -3217,29 +3183,14 @@ static int fbcon_event_notify(struct notifier_block *self,
con2fb->framebuffer = con2fb_map[con2fb->console - 1];
break;
case FB_EVENT_BLANK:
- if (!lock_fb_info(info)) {
- ret = -ENODEV;
- goto done;
- }
fbcon_fb_blanked(info, *(int *)event->data);
- unlock_fb_info(info);
break;
case FB_EVENT_NEW_MODELIST:
- if (!lock_fb_info(info)) {
- ret = -ENODEV;
- goto done;
- }
fbcon_new_modelist(info);
- unlock_fb_info(info);
break;
case FB_EVENT_GET_REQ:
caps = event->data;
- if (!lock_fb_info(info)) {
- ret = -ENODEV;
- goto done;
- }
fbcon_get_requirement(info, caps);
- unlock_fb_info(info);
break;
}
done:
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index d012edda6d11..38e86b84dce0 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -1282,7 +1282,7 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font)
font->charcount = vga_512_chars ? 512 : 256;
if (!font->data)
return 0;
- return vgacon_do_font_op(&state, font->data, 0, 0);
+ return vgacon_do_font_op(&state, font->data, 0, vga_512_chars);
}
#else
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index 83c5cefc266c..da7c01b39be2 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -1736,10 +1736,8 @@ static int __init cyber2000fb_init(void)
#ifdef CONFIG_ARCH_SHARK
err = cyberpro_vl_probe();
- if (!err) {
+ if (!err)
ret = 0;
- __module_get(THIS_MODULE);
- }
#endif
#ifdef CONFIG_PCI
err = pci_register_driver(&cyberpro_driver);
@@ -1749,14 +1747,15 @@ static int __init cyber2000fb_init(void)
return ret ? err : 0;
}
+module_init(cyber2000fb_init);
+#ifndef CONFIG_ARCH_SHARK
static void __exit cyberpro_exit(void)
{
pci_unregister_driver(&cyberpro_driver);
}
-
-module_init(cyber2000fb_init);
module_exit(cyberpro_exit);
+#endif
MODULE_AUTHOR("Russell King");
MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver");
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
index 0c5b9a9fd56f..8dea2bc92705 100644
--- a/drivers/video/efifb.c
+++ b/drivers/video/efifb.c
@@ -210,12 +210,15 @@ static int __init efifb_probe(struct platform_device *dev)
unsigned int size_total;
int request_succeeded = 0;
- printk(KERN_INFO "efifb: probing for efifb\n");
-
if (!screen_info.lfb_depth)
screen_info.lfb_depth = 32;
if (!screen_info.pages)
screen_info.pages = 1;
+ if (!screen_info.lfb_base) {
+ printk(KERN_DEBUG "efifb: invalid framebuffer address\n");
+ return -ENODEV;
+ }
+ printk(KERN_INFO "efifb: probing for efifb\n");
/* just assume they're all unset if any are */
if (!screen_info.blue_size) {
diff --git a/drivers/video/fb_draw.h b/drivers/video/fb_draw.h
index 1db622192bde..04c01faaf772 100644
--- a/drivers/video/fb_draw.h
+++ b/drivers/video/fb_draw.h
@@ -33,11 +33,11 @@ pixel_to_pat( u32 bpp, u32 pixel)
case 8:
return 0x0101010101010101ul*pixel;
case 12:
- return 0x0001001001001001ul*pixel;
+ return 0x1001001001001001ul*pixel;
case 16:
return 0x0001000100010001ul*pixel;
case 24:
- return 0x0000000001000001ul*pixel;
+ return 0x0001000001000001ul*pixel;
case 32:
return 0x0000000100000001ul*pixel;
default:
@@ -58,11 +58,11 @@ pixel_to_pat( u32 bpp, u32 pixel)
case 8:
return 0x01010101ul*pixel;
case 12:
- return 0x00001001ul*pixel;
+ return 0x01001001ul*pixel;
case 16:
return 0x00010001ul*pixel;
case 24:
- return 0x00000001ul*pixel;
+ return 0x01000001ul*pixel;
case 32:
return 0x00000001ul*pixel;
default:
@@ -167,4 +167,17 @@ static inline unsigned long fb_rev_pixels_in_long(unsigned long val,
#endif /* CONFIG_FB_CFB_REV_PIXELS_IN_BYTE */
+#define cpu_to_le_long _cpu_to_le_long(BITS_PER_LONG)
+#define _cpu_to_le_long(x) __cpu_to_le_long(x)
+#define __cpu_to_le_long(x) cpu_to_le##x
+
+#define le_long_to_cpu _le_long_to_cpu(BITS_PER_LONG)
+#define _le_long_to_cpu(x) __le_long_to_cpu(x)
+#define __le_long_to_cpu(x) le##x##_to_cpu
+
+static inline unsigned long rolx(unsigned long word, unsigned int shift, unsigned int x)
+{
+ return (word << shift) | (word >> (x - shift));
+}
+
#endif /* FB_DRAW_H */
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 2ac32e6b5953..d412a1ddc12f 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1097,8 +1097,11 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
return -EINVAL;
con2fb.framebuffer = -1;
event.data = &con2fb;
+ if (!lock_fb_info(info))
+ return -ENODEV;
event.info = info;
fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event);
+ unlock_fb_info(info);
ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0;
break;
case FBIOPUT_CON2FBMAP:
@@ -1115,8 +1118,11 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
break;
}
event.data = &con2fb;
+ if (!lock_fb_info(info))
+ return -ENODEV;
event.info = info;
ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event);
+ unlock_fb_info(info);
break;
case FBIOBLANK:
if (!lock_fb_info(info))
@@ -1521,7 +1527,10 @@ register_framebuffer(struct fb_info *fb_info)
registered_fb[i] = fb_info;
event.info = fb_info;
+ if (!lock_fb_info(fb_info))
+ return -ENODEV;
fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
+ unlock_fb_info(fb_info);
return 0;
}
@@ -1555,8 +1564,12 @@ unregister_framebuffer(struct fb_info *fb_info)
goto done;
}
+
+ if (!lock_fb_info(fb_info))
+ return -ENODEV;
event.info = fb_info;
ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event);
+ unlock_fb_info(fb_info);
if (ret) {
ret = -EINVAL;
@@ -1590,6 +1603,8 @@ void fb_set_suspend(struct fb_info *info, int state)
{
struct fb_event event;
+ if (!lock_fb_info(info))
+ return;
event.info = info;
if (state) {
fb_notifier_call_chain(FB_EVENT_SUSPEND, &event);
@@ -1598,6 +1613,7 @@ void fb_set_suspend(struct fb_info *info, int state)
info->state = FBINFO_STATE_RUNNING;
fb_notifier_call_chain(FB_EVENT_RESUME, &event);
}
+ unlock_fb_info(info);
}
/**
@@ -1667,8 +1683,11 @@ int fb_new_modelist(struct fb_info *info)
err = 1;
if (!list_empty(&info->modelist)) {
+ if (!lock_fb_info(info))
+ return -ENODEV;
event.info = info;
err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event);
+ unlock_fb_info(info);
}
return err;
diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
index a50bea614804..40984551c927 100644
--- a/drivers/video/intelfb/intelfb.h
+++ b/drivers/video/intelfb/intelfb.h
@@ -53,6 +53,7 @@
#define PCI_DEVICE_ID_INTEL_830M 0x3577
#define PCI_DEVICE_ID_INTEL_845G 0x2562
#define PCI_DEVICE_ID_INTEL_85XGM 0x3582
+#define PCI_DEVICE_ID_INTEL_854 0x358E
#define PCI_DEVICE_ID_INTEL_865G 0x2572
#define PCI_DEVICE_ID_INTEL_915G 0x2582
#define PCI_DEVICE_ID_INTEL_915GM 0x2592
@@ -154,6 +155,7 @@ enum intel_chips {
INTEL_85XGM,
INTEL_852GM,
INTEL_852GME,
+ INTEL_854,
INTEL_855GM,
INTEL_855GME,
INTEL_865G,
diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c
index b3065492bb20..487f2be47460 100644
--- a/drivers/video/intelfb/intelfb_i2c.c
+++ b/drivers/video/intelfb/intelfb_i2c.c
@@ -156,6 +156,7 @@ void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
switch(dinfo->chipset) {
case INTEL_830M:
case INTEL_845G:
+ case INTEL_854:
case INTEL_855GM:
case INTEL_865G:
dinfo->output[i].type = INTELFB_OUTPUT_DVO;
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 6d8e5415c809..ace14fe02fc4 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -182,6 +182,7 @@ static struct pci_device_id intelfb_pci_table[] __devinitdata = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_845G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_845G },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_85XGM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_85XGM },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_865G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_865G },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_854, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_854 },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915G },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945G },
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index 8b26b27c2db6..0689f97c5238 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -84,6 +84,11 @@ int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo)
dinfo->mobile = 0;
dinfo->pll_index = PLLS_I8xx;
return 0;
+ case PCI_DEVICE_ID_INTEL_854:
+ dinfo->mobile = 1;
+ dinfo->name = "Intel(R) 854";
+ dinfo->chipset = INTEL_854;
+ return 0;
case PCI_DEVICE_ID_INTEL_85XGM:
tmp = 0;
dinfo->mobile = 1;
diff --git a/drivers/video/logo/logo_linux_clut224.ppm b/drivers/video/logo/logo_linux_clut224.ppm
index de93ff3fc1ad..3c14e43b82fe 100644
--- a/drivers/video/logo/logo_linux_clut224.ppm
+++ b/drivers/video/logo/logo_linux_clut224.ppm
@@ -1,2828 +1,1604 @@
P3
-145 113
+# Standard 224-color Linux logo
+80 80
255
-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 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 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 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 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 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
-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 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 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 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 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 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
-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 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 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 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 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
-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 3 4 4 6 7 7
-8 10 10 8 10 10 6 8 8 6 7 7 3 4 4 2 2 2
-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 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 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 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 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 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
-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 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 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 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 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
-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 4 5 5 17 18 17
-27 29 28 35 37 36 40 43 41 43 45 43 40 43 41 37 39 37
-32 34 33 27 30 29 23 25 24 17 21 21 15 18 18 12 15 15
-11 13 13 8 10 10 6 7 7 3 4 4 1 1 1 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 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 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 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 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
-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 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 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 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 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
-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 0 0 0
-0 0 0 13 13 13 32 34 33 49 51 48 60 60 56 58 59 55
-55 57 54 55 56 53 49 51 48 43 45 43 39 40 39 33 37 35
-28 31 30 23 27 26 20 23 23 17 20 20 14 17 17 13 16 16
-11 14 14 10 13 13 10 12 12 9 11 11 8 10 10 6 7 7
-2 3 3 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
-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 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 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 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 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 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
-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 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 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 0 0 0 0 0 0 6 7 7 12 15 15
-12 15 15 8 9 9 2 3 3 0 0 0 1 1 1 25 27 26
-55 56 53 68 70 65 65 66 61 65 66 61 63 64 60 63 64 60
-58 59 55 51 52 50 47 48 46 41 42 42 35 37 36 30 32 31
-26 28 27 20 24 24 18 22 22 16 19 19 14 17 17 13 16 16
-12 15 15 11 14 14 10 13 13 10 12 12 9 11 11 8 10 10
-8 9 9 6 8 8 3 3 3 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 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 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
-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 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 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 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 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
-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 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 6 7 7 20 24 24 23 27 26
-23 27 26 18 22 22 11 13 13 23 24 24 61 63 57 72 73 67
-72 73 67 68 70 65 68 70 65 68 70 65 63 64 60 58 59 55
-55 56 53 47 48 46 41 42 42 35 37 36 30 32 31 26 28 27
-20 24 24 18 22 22 16 20 20 15 19 19 14 17 17 13 16 16
-12 15 15 12 15 15 11 14 14 10 13 13 10 12 12 9 11 11
-8 10 10 8 9 9 7 9 9 6 7 7 1 2 2 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 1 1 1 4 5 5 5 6 5 4 5 5
-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 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 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 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 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 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 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 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 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 15 19 19 40 41 39 53 55 47
-33 36 34 27 30 29 51 52 50 72 73 67 72 73 67 72 73 67
-72 73 67 68 70 65 68 70 65 63 64 60 58 59 55 51 52 50
-47 48 46 40 43 41 33 37 35 30 32 31 26 28 27 20 24 24
-18 22 22 17 21 21 16 19 19 14 18 18 14 17 17 13 17 17
-13 16 16 12 15 15 12 15 15 11 14 14 10 13 13 10 12 12
-9 11 11 8 10 10 8 9 9 7 9 9 6 8 8 3 4 4
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-2 2 2 6 8 8 10 12 12 10 12 12 10 12 12 10 12 12
-6 8 8 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
-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 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 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 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 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
-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 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 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 20 23 23 71 71 57 131 127 93
-115 113 82 63 64 60 72 73 67 72 73 67 72 73 67 72 73 67
-68 70 65 65 66 61 61 63 57 55 57 54 49 51 48 43 45 43
-39 40 39 33 36 34 28 31 30 23 27 26 20 24 24 20 23 23
-17 21 21 16 20 20 15 19 19 15 18 18 14 18 18 14 17 17
-13 17 17 13 16 16 12 15 15 12 15 15 11 14 14 10 13 13
-10 12 12 9 11 11 8 10 10 7 9 9 7 9 9 6 8 8
-4 5 5 0 0 0 0 0 0 0 0 0 1 1 1 6 7 7
-10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 10 12 12
-10 12 12 3 4 4 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 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
-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 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 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 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 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
-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 0 0 0
-0 0 0 0 0 0 0 0 0 18 22 22 71 71 57 144 139 99
-84 83 72 68 70 65 72 73 67 72 73 67 68 70 65 65 66 61
-63 64 60 55 57 54 51 52 50 47 48 46 40 43 41 35 37 36
-30 32 31 27 29 28 23 27 26 20 24 24 18 22 22 17 21 21
-16 20 20 15 19 19 15 19 19 15 19 19 15 18 18 14 18 18
-14 17 17 13 17 17 13 16 16 12 15 15 12 15 15 11 14 14
-10 13 13 9 12 12 9 11 11 8 10 10 7 9 9 6 8 8
-6 8 8 3 4 4 0 0 0 2 2 2 8 10 10 10 12 12
-10 12 12 10 12 12 11 13 13 36 38 35 61 61 53 48 49 45
-10 12 12 7 9 9 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 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
-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 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 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 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 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
-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 0 0 0
-0 0 0 0 0 0 0 0 0 15 19 19 61 61 53 84 83 72
-68 70 65 72 73 67 68 70 65 68 70 65 63 64 60 58 59 55
-51 52 50 47 48 46 41 42 42 37 39 37 32 35 33 28 31 30
-23 27 26 20 24 24 20 23 23 18 22 22 17 21 21 17 21 21
-17 21 21 17 21 21 17 20 20 16 20 20 16 20 20 16 19 19
-15 18 18 14 18 18 13 17 17 13 16 16 12 15 15 12 15 15
-11 14 14 10 13 13 9 12 12 9 11 11 8 10 10 7 9 9
-6 8 8 6 8 8 5 6 5 9 11 11 10 12 12 10 12 12
-19 20 18 82 81 62 149 145 103 160 154 106 142 137 94 96 95 69
-10 12 12 10 12 12 1 1 1 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 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 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
-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 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 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 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 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
-0 0 0 0 0 0 0 0 0 10 12 12 44 46 43 68 70 65
-72 73 67 68 70 65 68 70 65 63 64 60 55 57 54 49 51 48
-43 45 43 39 40 39 33 37 35 30 32 31 26 28 27 23 27 26
-20 24 24 18 22 22 18 22 22 18 22 22 18 22 22 20 23 23
-20 24 24 23 25 24 23 25 24 22 24 23 20 23 23 18 22 22
-17 20 20 15 19 19 15 18 18 14 17 17 13 16 16 12 15 15
-11 14 14 11 13 13 10 12 12 9 11 11 8 10 10 8 9 9
-7 9 9 7 9 9 10 12 12 10 12 12 10 12 12 71 71 57
-164 159 111 186 182 128 186 182 128 171 165 117 151 147 98 96 95 69
-10 12 12 10 12 12 3 3 3 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 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 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
-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 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 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 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 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
-0 0 0 0 0 0 0 0 0 8 10 10 63 64 60 68 70 65
-72 73 67 68 70 65 63 64 60 55 57 54 47 48 46 40 43 41
-33 37 35 30 32 31 27 29 28 23 27 26 20 24 24 20 23 23
-18 22 22 18 22 22 20 23 22 21 25 23 23 27 26 27 29 28
-28 31 30 31 33 31 31 33 31 31 33 31 28 31 30 26 28 27
-23 25 24 20 23 22 16 20 20 15 18 18 14 17 17 13 16 16
-12 15 15 11 14 14 10 13 13 10 12 12 9 11 11 8 10 10
-10 12 12 10 13 13 10 12 12 12 14 14 96 95 69 165 161 109
-186 182 128 192 187 134 192 187 134 176 171 126 160 154 106 103 101 77
-10 12 12 10 12 12 5 6 5 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 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 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
-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 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 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 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 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
-0 0 0 0 0 0 0 0 0 35 37 36 68 70 65 72 73 67
-68 70 65 65 66 61 58 59 55 49 51 48 40 43 41 33 37 35
-28 31 30 23 27 26 20 24 24 20 23 23 18 22 22 18 22 22
-18 22 22 20 23 23 23 27 26 27 30 29 32 35 33 37 39 37
-40 43 41 44 46 43 46 47 43 44 46 43 40 43 41 36 38 35
-31 33 31 27 29 28 22 24 23 17 21 21 15 18 18 14 17 17
-13 16 16 12 15 15 11 14 14 11 14 14 11 13 13 13 16 16
-13 16 16 11 14 14 10 12 12 79 78 62 142 137 94 164 159 111
-178 174 128 192 187 134 192 187 134 176 171 126 160 154 106 96 95 69
-10 12 12 10 12 12 6 7 7 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 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 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
-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 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 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 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 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
-0 0 0 0 0 0 0 0 0 55 57 54 68 70 65 72 73 67
-68 70 65 63 64 60 55 56 53 43 45 43 35 37 36 28 31 30
-23 27 26 20 24 24 18 22 22 17 21 21 17 21 21 17 21 21
-20 24 24 25 27 26 31 33 31 38 39 37 46 47 43 53 55 47
-61 61 53 66 65 55 66 65 55 66 65 55 61 61 53 53 55 47
-46 47 43 37 39 37 30 33 30 24 26 24 17 21 21 15 18 18
-13 17 17 12 15 15 12 15 15 13 16 16 14 18 18 14 18 18
-14 17 17 12 15 15 30 31 28 118 116 76 134 131 96 160 154 106
-174 170 121 178 174 128 178 174 128 171 165 117 151 147 98 96 95 69
-10 12 12 10 12 12 6 8 8 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 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 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
-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 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 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 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 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
-0 0 0 0 0 0 0 0 0 63 64 60 68 70 65 68 70 65
-65 66 61 58 59 55 49 51 48 39 40 39 30 32 31 23 27 26
-20 24 24 18 22 22 17 21 21 16 20 20 17 21 21 20 23 23
-25 27 26 32 35 33 43 44 41 53 55 47 66 65 55 75 75 61
-82 81 62 84 83 72 87 86 72 87 86 72 82 81 62 75 75 61
-66 65 55 53 55 47 40 41 39 31 33 31 23 25 24 17 20 20
-14 18 18 13 16 16 12 15 15 12 15 15 13 17 17 14 18 18
-14 18 18 13 16 16 46 47 43 96 95 69 125 122 87 142 137 94
-160 154 106 165 161 109 164 159 111 155 149 109 142 137 94 75 75 61
-10 12 12 10 12 12 6 8 8 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 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 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
-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 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 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 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 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
-0 0 0 0 0 0 0 0 0 60 60 56 68 70 65 68 70 65
-63 64 60 55 57 54 46 47 45 35 37 36 27 30 29 23 25 24
-18 22 22 17 21 21 16 20 20 17 21 21 18 22 22 23 27 26
-31 33 31 43 44 41 55 56 53 71 71 57 84 83 72 92 91 72
-103 101 77 92 91 72 82 81 62 82 81 62 87 86 72 92 91 72
-84 83 72 71 71 57 55 56 53 43 44 41 30 33 30 22 24 23
-16 19 19 14 17 17 12 15 15 12 15 15 13 16 16 14 18 18
-14 18 18 14 17 17 43 44 41 82 81 62 118 116 76 125 122 87
-142 137 94 144 139 99 144 139 99 134 131 96 118 116 76 53 55 47
-10 12 12 10 12 12 6 8 8 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 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 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
-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 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 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 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 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
-0 0 0 0 0 0 0 0 0 47 48 46 63 64 60 63 64 60
-55 57 54 49 51 48 40 43 41 32 34 33 26 28 27 20 24 24
-18 22 22 16 20 20 16 20 20 17 21 21 20 24 24 28 31 30
-40 41 39 53 55 47 75 75 61 90 89 73 87 86 72 48 49 45
-14 14 13 2 2 2 1 2 2 1 1 1 1 1 1 2 2 2
-19 20 18 43 44 41 66 65 55 53 55 47 38 39 37 26 28 27
-18 22 22 14 18 18 13 16 16 12 15 15 12 15 15 13 17 17
-14 18 18 14 18 18 30 31 28 66 65 55 96 95 69 103 101 77
-118 116 76 118 116 76 118 116 76 118 116 76 103 101 77 36 38 35
-10 12 12 10 12 12 6 7 7 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 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 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
-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 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 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 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 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
-0 0 0 0 0 0 0 0 0 28 31 30 55 57 54 51 52 50
-49 51 48 41 42 42 35 37 36 28 31 30 23 27 26 20 23 23
-17 21 21 16 20 20 16 20 20 18 22 22 23 27 26 33 36 34
-48 49 45 71 71 57 82 81 62 43 44 41 8 9 9 6 7 7
-6 7 7 6 7 7 6 7 7 5 6 5 4 5 5 3 4 4
-2 3 3 1 2 2 4 5 4 36 38 35 48 49 45 32 35 33
-21 25 23 16 19 19 13 17 17 12 15 15 12 15 15 13 16 16
-14 18 18 14 18 18 16 18 16 36 38 35 61 61 53 82 81 62
-96 95 69 96 95 69 96 95 69 96 95 69 79 78 62 19 20 18
-10 12 12 10 12 12 4 5 5 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 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 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
-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 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 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 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 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
-0 0 0 0 0 0 0 0 0 13 13 13 46 47 45 43 45 43
-40 43 41 35 37 36 30 32 31 23 27 26 20 24 24 18 22 22
-17 21 21 16 20 20 17 21 21 20 23 23 27 30 29 40 41 39
-61 61 53 53 55 47 16 17 16 9 11 11 10 12 12 10 12 12
-10 12 12 10 12 12 10 12 12 9 11 11 8 10 10 8 9 9
-6 8 8 5 6 5 4 5 5 2 3 3 19 20 18 38 39 37
-26 28 27 17 21 21 14 17 17 13 16 16 12 15 15 12 15 15
-13 17 17 14 18 18 12 15 15 13 12 7 30 31 28 46 47 43
-53 55 47 66 65 55 66 65 55 53 55 47 36 38 35 10 12 12
-10 12 12 10 12 12 2 3 3 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 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 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
-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 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 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 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 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
-0 0 0 0 0 0 0 0 0 1 1 1 33 37 35 35 37 36
-32 35 33 28 31 30 23 27 26 20 24 24 18 22 22 17 21 21
-16 20 20 16 20 20 17 21 21 21 25 23 31 33 31 44 46 43
-31 33 31 11 13 13 12 14 14 12 15 15 13 16 16 14 17 17
-14 17 17 14 17 17 14 17 17 13 16 16 12 15 15 12 14 14
-11 13 13 9 11 11 8 10 10 6 8 8 4 5 5 17 18 17
-30 33 30 20 23 22 15 18 18 13 16 16 12 15 15 12 14 14
-13 16 16 14 17 17 14 18 18 11 12 11 7 7 5 16 17 12
-21 22 20 30 31 28 25 27 25 21 22 20 14 14 13 10 12 12
-10 12 12 9 11 11 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 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
-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 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 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 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 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
-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 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 18 22 22 27 30 29
-27 29 28 40 41 39 53 55 47 53 55 47 53 55 47 46 47 43
-25 27 25 16 20 20 17 21 21 23 25 24 31 33 31 20 20 20
-12 15 15 14 17 17 15 19 19 16 20 20 17 21 21 18 22 22
-18 22 22 18 22 22 18 22 22 17 21 21 17 21 21 16 19 19
-15 18 18 13 16 16 12 15 15 10 12 12 8 10 10 6 8 8
-21 22 21 22 24 23 15 19 19 13 17 17 13 16 16 12 15 15
-12 15 15 13 17 17 14 18 18 14 18 18 13 15 14 10 9 6
-7 7 5 7 7 5 7 7 5 9 11 11 10 12 12 10 12 12
-10 12 12 6 7 7 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 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
-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 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 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 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 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
-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 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 16 17 12 82 81 62
-118 116 76 118 116 76 161 156 96 161 156 96 161 156 96 118 116 76
-118 116 76 96 95 69 53 55 47 22 24 23 14 17 17 13 16 16
-15 19 19 17 21 21 18 22 22 20 24 24 20 24 24 23 27 26
-23 27 26 23 27 26 23 27 26 23 27 26 23 27 26 20 24 24
-20 23 23 17 21 21 16 19 19 14 17 17 12 15 15 10 12 12
-9 11 11 20 23 22 16 19 19 14 17 17 13 16 16 12 15 15
-11 14 14 13 16 16 14 17 17 14 18 18 14 17 17 12 15 15
-10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 10 12 12
-9 11 11 1 1 1 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 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
-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 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 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 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 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
-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 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 53 55 47 161 156 96
-161 156 96 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 161 156 96 118 116 76 96 95 69 21 22 20 16 19 19
-18 22 22 20 24 24 23 27 26 23 27 26 26 28 27 27 30 29
-27 30 29 18 22 22 12 14 14 8 10 10 9 11 11 17 21 21
-23 27 26 23 27 26 20 24 24 18 22 22 16 20 20 14 17 17
-12 14 14 14 17 17 16 20 20 14 17 17 13 17 17 13 16 16
-12 15 15 12 15 15 13 17 17 14 18 18 14 17 17 13 16 16
-11 13 13 10 12 12 10 12 12 10 12 12 10 12 12 10 12 12
-4 5 5 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
-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 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 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 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 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
-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 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 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 13 12 7 118 116 76 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 161 156 96 118 116 76 30 31 28
-20 24 24 23 27 26 27 30 29 28 31 30 30 32 31 23 27 26
-16 19 19 17 21 21 12 15 15 9 11 11 10 12 12 9 11 11
-20 24 24 28 31 30 26 28 27 23 27 26 20 24 24 17 21 21
-15 19 19 13 16 16 16 19 19 14 18 18 14 17 17 13 16 16
-12 15 15 11 14 14 13 16 16 14 17 17 14 18 18 14 17 17
-12 15 15 10 12 12 10 12 12 10 12 12 10 12 12 8 9 9
-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 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 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 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 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 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 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 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 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 82 81 62 161 156 96 230 229 82
-230 229 82 233 233 100 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 118 116 76
-27 29 28 27 30 29 30 32 31 30 32 31 23 27 26 20 24 24
-26 28 27 17 21 21 6 7 7 72 73 67 145 141 105 15 15 15
-14 17 17 33 37 35 30 32 31 28 31 30 26 28 27 23 27 26
-20 23 23 16 20 20 15 19 19 14 18 18 14 17 17 13 16 16
-12 15 15 11 14 14 12 15 15 13 17 17 14 18 18 14 17 17
-13 16 16 11 13 13 10 12 12 10 12 12 9 11 11 1 1 1
-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 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 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 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 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 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 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 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 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 16 17 12 161 156 96 230 229 82 230 229 82
-243 242 120 235 234 117 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 161 156 96
-82 81 62 28 31 30 28 31 30 27 30 29 28 31 30 30 32 31
-33 37 35 13 16 16 3 3 3 105 104 92 210 208 158 12 14 14
-17 21 21 33 37 35 33 37 35 32 35 33 30 32 31 27 30 29
-23 27 26 20 23 23 17 20 20 15 18 18 14 18 18 13 17 17
-13 16 16 12 15 15 11 14 14 13 16 16 14 17 17 14 18 18
-13 17 17 12 15 15 10 12 12 10 12 12 3 4 4 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 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 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 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 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
-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 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 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 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 96 95 69 230 229 82 230 229 82 244 244 132
-241 241 143 243 242 120 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-161 156 96 46 47 43 32 35 33 33 37 35 33 37 35 33 37 35
-40 43 41 23 27 26 1 1 1 2 2 2 24 26 24 14 17 17
-23 27 26 33 37 35 33 37 35 33 37 35 33 37 35 30 32 31
-27 30 29 23 27 26 20 23 23 15 18 18 14 18 18 14 17 17
-13 16 16 12 15 15 11 14 14 12 15 15 13 17 17 14 17 17
-14 17 17 13 16 16 11 13 13 6 8 8 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 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 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 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
-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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 16 17 12 161 156 96 230 229 82 235 234 117 239 239 170
-239 239 170 236 236 101 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 118 116 76 33 37 35 33 37 35 37 39 37 37 39 37
-43 45 43 49 51 48 20 24 24 8 10 10 17 20 20 35 37 36
-33 37 35 40 43 41 37 39 37 35 37 36 33 37 35 33 37 35
-30 32 31 27 30 29 23 27 26 15 19 19 14 18 18 14 17 17
-13 17 17 13 16 16 12 15 15 11 14 14 13 16 16 14 17 17
-14 17 17 13 17 17 11 14 14 4 5 5 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 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 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 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
-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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 96 95 69 230 229 82 230 229 82 239 239 170 251 251 187
-241 241 143 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 161 156 96 36 38 35 33 37 35 33 37 35 33 37 35
-37 39 37 47 48 46 55 57 54 55 57 54 49 51 48 43 45 43
-43 45 43 43 45 43 40 43 41 40 43 41 37 39 37 33 37 35
-33 37 35 28 31 30 26 28 27 16 20 20 15 18 18 14 18 18
-14 17 17 13 16 16 12 15 15 11 14 14 12 15 15 13 17 17
-14 17 17 14 17 17 8 10 10 5 7 7 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 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 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 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
-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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-16 17 12 230 229 82 230 229 82 243 242 120 251 251 187 251 251 187
-246 246 123 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 66 65 55 30 32 31 32 35 33 33 37 35
-33 37 35 37 39 37 40 43 41 47 48 46 49 51 48 51 52 50
-55 57 54 55 57 54 51 52 50 47 48 46 43 45 43 39 40 39
-33 37 35 30 32 31 26 28 27 17 21 21 15 19 19 14 18 18
-14 17 17 13 16 16 12 15 15 12 14 14 11 14 14 13 16 16
-14 17 17 12 15 15 7 9 9 6 8 8 1 1 1 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 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 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 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 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
-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 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 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 0 0 0 0 0 0 0 0 0 0 0 0
-96 95 69 230 229 82 230 229 82 239 239 170 251 251 187 239 239 170
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 96 95 69 27 30 29 28 31 30 30 32 31
-33 37 35 40 43 41 46 47 45 55 57 54 63 64 60 72 73 67
-72 73 67 72 73 67 72 73 67 65 66 61 55 57 54 47 48 46
-39 40 39 32 35 33 27 30 29 17 21 21 15 19 19 15 18 18
-14 18 18 13 17 17 13 16 16 12 15 15 11 14 14 12 14 14
-13 16 16 9 11 11 7 9 9 9 11 11 66 65 55 115 113 82
-21 22 20 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
-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 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 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 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 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
-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 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 0 0 0 13 12 7
-230 229 82 230 229 82 236 236 101 251 251 187 251 251 187 246 246 123
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 118 116 76 23 27 26 26 28 27 32 35 33
-51 52 50 90 89 73 110 109 94 145 141 105 168 163 120 177 172 135
-177 172 135 188 184 146 188 184 146 181 176 137 194 191 148 188 184 146
-184 179 149 188 184 146 188 184 146 156 151 111 177 172 135 181 176 137
-177 172 135 168 163 120 168 163 120 158 153 112 156 151 111 158 153 112
-156 151 111 158 153 112 177 172 135 188 184 146 188 184 146 194 189 146
-36 38 35 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
-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 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 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 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 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
-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 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 0 0 0 82 81 62
-230 229 82 230 229 82 244 244 132 251 251 187 244 244 132 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 82 81 62
-96 95 69 230 229 82 181 178 103 110 109 94 156 151 111 188 184 146
-188 184 146 197 193 154 188 184 146 184 181 136 188 184 146 168 163 120
-168 163 120 178 174 128 156 151 111 158 153 112 174 170 121 156 151 111
-156 151 111 158 153 112 156 151 111 168 163 120 178 174 128 181 176 137
-176 171 126 178 174 128 184 181 136 176 171 126 178 174 128 184 181 136
-176 171 126 178 174 128 184 181 136 164 159 111 155 149 109 96 95 69
-1 1 1 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
-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 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 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 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 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
-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 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 2 2 1 161 156 96
-230 229 82 230 229 82 244 244 132 244 244 132 236 236 101 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 46 47 43 82 81 62
-158 153 112 197 193 154 194 189 146 184 181 136 188 184 146 168 163 120
-156 151 111 137 133 100 131 127 93 137 133 100 137 133 100 158 153 112
-121 119 87 137 133 100 156 151 111 145 141 105 99 98 80 84 83 72
-63 64 60 52 53 49 40 43 41 33 36 34 36 38 35 36 38 35
-38 39 37 43 44 41 43 44 41 46 47 43 48 49 45 48 49 45
-46 47 43 36 38 35 30 31 28 19 20 18 6 7 7 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 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 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 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 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
-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 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 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 0 0 0 0 0 0 36 38 35 230 229 82
-230 229 82 230 229 82 246 246 123 236 236 101 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 53 55 47 121 119 87
-176 171 126 171 165 117 161 156 96 82 81 62 53 55 47 33 37 35
-39 40 39 63 64 60 99 98 80 121 119 87 137 133 100 177 172 135
-176 171 126 184 181 136 131 127 93 131 127 93 110 109 94 84 83 72
-51 52 50 39 40 39 27 29 28 18 22 22 16 19 19 15 19 19
-15 19 19 14 18 18 14 17 17 13 16 16 12 15 15 11 14 14
-10 13 13 9 12 12 9 11 11 8 9 9 7 9 9 1 1 1
-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 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 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 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 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 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 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 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 0 0 0 118 116 76 230 229 82
-230 229 82 230 229 82 236 236 101 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 96 95 69 71 71 57
-36 38 35 118 116 76 118 116 76 12 15 15 15 18 18 20 24 24
-33 37 35 55 56 53 84 83 72 110 109 94 145 141 105 110 109 94
-168 163 120 121 119 87 156 151 111 131 127 93 87 86 72 61 63 57
-47 48 46 28 31 30 18 22 22 15 19 19 15 18 18 15 19 19
-15 19 19 14 18 18 14 17 17 13 17 17 13 16 16 12 15 15
-11 13 13 10 12 12 9 11 11 8 10 10 7 9 9 3 3 3
-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 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 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 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 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 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 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 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 1 1 0 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 161 156 96
-161 156 96 230 229 82 118 116 76 11 14 14 14 17 17 18 22 22
-27 30 29 40 43 41 60 60 56 84 83 72 105 104 92 110 109 94
-110 109 94 110 109 94 99 98 80 90 89 73 68 70 65 47 48 46
-32 34 33 23 25 24 20 23 23 17 21 21 15 19 19 14 17 17
-15 19 19 15 18 18 14 18 18 13 17 17 13 16 16 12 15 15
-11 14 14 10 12 12 9 11 11 8 10 10 7 9 9 4 5 5
-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 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 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 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 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 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 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 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 16 17 12 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 161 156 96 118 116 76 11 13 13 13 16 16 15 19 19
-20 24 24 30 32 31 40 43 41 51 52 50 63 64 60 72 73 67
-65 66 61 65 66 61 65 66 61 55 57 54 46 47 45 33 37 35
-27 29 28 20 24 24 17 21 21 16 20 20 16 20 20 15 19 19
-15 19 19 15 19 19 14 18 18 14 17 17 13 16 16 12 15 15
-11 14 14 10 13 13 9 12 12 8 10 10 7 9 9 6 7 7
-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 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 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 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 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 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 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 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 53 55 47 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-161 156 96 118 116 76 53 55 47 10 13 13 12 15 15 14 17 17
-17 20 20 20 24 24 27 29 28 32 34 33 37 39 37 40 43 41
-43 45 43 41 42 42 35 37 36 30 32 31 28 31 30 23 27 26
-20 23 23 17 21 21 16 20 20 16 20 20 16 20 20 16 19 19
-15 19 19 15 19 19 14 18 18 14 17 17 13 16 16 12 15 15
-11 14 14 10 13 13 9 12 12 9 11 11 8 10 10 10 12 12
-1 1 1 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
-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 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 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 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 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
-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 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 82 81 62 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 161 156 96
-118 116 76 82 81 62 13 14 12 10 13 13 12 15 15 13 17 17
-15 19 19 16 20 20 20 23 23 20 24 24 23 27 26 26 28 27
-26 28 27 26 28 27 23 27 26 18 22 22 20 23 23 17 21 21
-17 21 21 16 20 20 16 20 20 16 20 20 16 20 20 16 19 19
-15 19 19 15 19 19 15 18 18 14 17 17 13 17 17 13 16 16
-12 15 15 12 14 14 12 14 14 12 14 14 12 14 14 23 24 24
-6 8 8 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
-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 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 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 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 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
-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 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 118 116 76 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 161 156 96 161 156 96 118 116 76
-71 71 57 13 14 12 9 12 12 10 13 13 12 15 15 13 17 17
-15 18 18 15 19 19 16 20 20 17 21 21 17 21 21 18 22 22
-18 22 22 18 22 22 17 21 21 16 19 19 15 18 18 14 18 18
-16 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20
-15 19 19 15 19 19 15 18 18 14 18 18 16 20 20 23 25 24
-17 21 21 25 27 26 47 48 46 47 48 46 51 52 50 72 73 67
-33 36 34 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
-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 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 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 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 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
-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 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 118 116 76 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 161 156 96 118 116 76 118 116 76 46 47 43
-9 11 11 9 11 11 10 12 12 11 13 13 12 15 15 14 17 17
-15 18 18 15 19 19 16 20 20 16 20 20 16 20 20 16 20 20
-16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20
-15 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20
-15 19 19 16 20 20 20 24 24 55 56 53 32 34 33 84 83 72
-90 89 73 110 109 94 110 109 94 105 104 92 110 109 94 110 109 94
-72 73 67 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
-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 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 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 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 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
-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 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 96 95 69 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 161 156 96 118 116 76 82 81 62 16 17 12 9 11 11
-9 11 11 9 12 12 10 13 13 12 14 14 13 16 16 14 18 18
-15 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20
-16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20
-16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20
-16 19 19 33 36 34 99 98 80 156 151 111 145 141 105 184 179 149
-168 163 120 184 179 149 177 172 135 156 151 111 145 141 105 110 109 94
-90 89 73 2 2 2 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 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
-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 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 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 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 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
-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 71 71 57 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82
-230 229 82 161 156 96 230 229 82 230 229 82 230 229 82 161 156 96
-118 116 76 82 81 62 30 31 28 9 11 11 9 11 11 9 11 11
-10 12 12 10 13 13 11 14 14 13 16 16 14 17 17 15 18 18
-15 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20
-16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20
-16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20
-18 22 22 58 59 55 137 133 100 197 193 154 214 212 158 210 208 158
-197 193 154 184 179 149 184 179 149 137 133 100 110 109 94 99 98 80
-84 83 72 10 10 9 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 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
-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 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 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 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 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
-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 16 17 12 230 229 82 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 161 156 96
-161 156 96 161 156 96 161 156 96 161 156 96 118 116 76 71 71 57
-21 22 20 12 14 14 11 13 13 10 12 12 10 12 12 10 13 13
-11 13 13 12 15 15 13 16 16 14 17 17 14 18 18 15 19 19
-16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20
-16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20
-16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 17 21 21
-23 27 26 84 83 72 184 179 149 251 251 187 210 208 158 184 179 149
-184 179 149 156 151 111 110 109 94 84 83 72 63 64 60 51 52 50
-18 22 22 6 8 8 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 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
-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 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 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 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 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
-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 118 116 76 230 229 82
-230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 161 156 96
-161 156 96 161 156 96 118 116 76 53 55 47 20 23 22 16 19 19
-13 16 16 12 15 15 12 14 14 11 14 14 11 14 14 11 14 14
-12 15 15 13 16 16 14 17 17 15 19 19 16 20 20 17 21 21
-23 27 26 18 22 22 20 24 24 23 27 26 30 32 31 17 21 21
-16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20
-16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20
-23 27 26 33 37 35 137 133 100 156 151 111 158 153 112 105 104 92
-105 104 92 68 70 65 39 40 39 18 22 22 12 14 14 12 15 15
-9 11 11 4 5 5 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 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
-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 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 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 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 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
-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 16 17 12 230 229 82
-230 229 82 230 229 82 230 229 82 161 156 96 118 116 76 118 116 76
-118 116 76 66 65 55 43 45 43 32 34 33 25 27 26 20 23 22
-17 20 20 15 18 18 14 17 17 15 18 18 13 16 16 14 17 17
-14 18 18 16 20 20 32 34 33 55 57 54 58 59 55 72 73 67
-105 104 92 55 57 54 65 66 61 63 64 60 40 43 41 33 37 35
-41 42 42 20 24 24 16 20 20 16 20 20 16 20 20 16 20 20
-16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20
-17 21 21 26 28 27 30 32 31 35 37 36 68 70 65 39 40 39
-23 27 26 15 18 18 13 16 16 11 14 14 9 12 12 8 10 10
-7 9 9 6 7 7 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 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
-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 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 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 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 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
-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 36 38 35
-230 229 82 230 229 82 230 229 82 96 95 69 30 31 28 49 51 48
-90 89 73 68 70 65 55 57 54 47 48 46 47 48 46 43 45 43
-32 34 33 43 45 43 43 45 43 23 27 26 25 27 26 40 43 41
-40 43 41 90 89 73 110 109 94 145 141 105 156 151 111 156 151 111
-184 179 149 184 179 149 177 172 135 184 179 149 137 133 100 84 83 72
-105 104 92 63 64 60 49 51 48 47 48 46 28 31 30 18 22 22
-16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20
-16 20 20 15 19 19 15 19 19 15 19 19 18 22 22 15 19 19
-13 16 16 12 15 15 11 14 14 10 13 13 9 12 12 9 11 11
-8 10 10 6 8 8 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 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
-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 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 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 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 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
-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 0 0 0
-30 31 28 230 229 82 71 71 57 2 2 1 0 0 0 58 59 55
-105 104 92 84 83 72 65 66 61 84 83 72 110 109 94 110 109 94
-145 141 105 105 104 92 110 109 94 110 109 94 84 83 72 110 109 94
-158 153 112 197 193 154 197 193 154 239 239 170 251 251 187 251 251 187
-251 251 187 251 251 187 251 251 187 251 251 187 210 208 158 197 193 154
-197 193 154 184 179 149 145 141 105 137 133 100 105 104 92 47 48 46
-20 23 23 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20
-16 20 20 16 19 19 15 19 19 15 19 19 14 18 18 14 17 17
-13 17 17 13 16 16 12 14 14 12 14 14 13 13 13 13 13 13
-13 13 13 12 12 12 10 10 9 6 7 7 2 2 2 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 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 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 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 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
-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 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 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 1 1 0 0 0 0 0 0 0 65 66 61
-105 104 92 84 83 72 84 83 72 110 109 94 184 179 149 210 208 158
-210 208 158 210 208 158 214 212 158 197 193 154 214 212 158 210 208 158
-251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187
-251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187
-251 251 187 251 251 187 239 239 170 251 251 187 184 179 149 84 83 72
-26 28 27 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20
-16 20 20 16 20 20 15 19 19 15 19 19 15 18 18 14 18 18
-13 17 17 13 16 16 15 15 15 14 14 13 14 14 13 14 14 13
-13 13 13 13 13 13 12 12 12 12 12 12 12 12 12 3 4 4
-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 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 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 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 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
-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 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 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 0 0 0 0 0 0 72 73 67
-105 104 92 99 98 80 84 83 72 99 98 80 177 172 135 197 193 154
-251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187
-251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187
-251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187
-251 251 187 251 251 187 251 251 187 214 212 158 197 193 154 99 98 80
-23 27 26 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20
-16 20 20 16 20 20 15 19 19 15 19 19 15 18 18 14 18 18
-14 17 17 16 16 16 16 16 16 16 16 16 15 15 15 14 14 13
-14 14 13 13 13 13 13 13 13 12 12 12 12 12 12 12 12 12
-3 3 3 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
-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 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 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 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 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
-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 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 0 0 0 84 83 72
-110 109 94 99 98 80 72 73 67 63 64 60 99 98 80 177 172 135
-184 179 149 210 208 158 251 251 187 251 251 187 251 251 187 251 251 187
-251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187
-251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187
-251 251 187 210 208 158 184 179 149 177 172 135 110 109 94 33 37 35
-17 21 21 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20
-16 20 20 16 20 20 15 19 19 15 19 19 15 19 19 14 18 18
-15 18 18 18 19 18 18 19 18 17 17 17 16 16 16 15 15 15
-14 14 13 13 13 13 13 13 13 12 12 12 12 12 12 12 12 12
-10 10 9 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
-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 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 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 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 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
-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 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 2 2 2 105 104 92
-108 107 93 99 98 80 72 73 67 63 64 60 51 52 50 87 86 72
-105 104 92 110 109 94 108 107 93 156 151 111 184 179 149 184 179 149
-197 193 154 197 193 154 197 193 154 184 179 149 184 179 149 177 172 135
-197 193 154 156 151 111 177 172 135 184 179 149 168 163 120 137 133 100
-145 141 105 110 109 94 99 98 80 47 48 46 55 57 54 15 19 19
-16 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20
-17 20 20 17 21 21 16 20 20 16 19 19 15 19 19 16 19 19
-20 20 20 21 22 21 20 20 20 19 20 19 18 19 18 16 16 16
-15 15 15 14 14 13 13 13 13 13 13 13 12 12 12 12 12 12
-12 12 12 4 5 5 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 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
-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 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 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 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 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
-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 58 59 55 110 109 94
-105 104 92 90 89 73 72 73 67 55 57 54 43 45 43 39 40 39
-43 45 43 46 47 45 43 45 43 68 70 65 65 66 61 63 64 60
-108 107 93 72 73 67 105 104 92 90 89 73 72 73 67 40 43 41
-72 73 67 68 70 65 68 70 65 58 59 55 63 64 60 49 51 48
-43 45 43 33 36 34 27 30 29 20 24 24 16 20 20 15 19 19
-15 19 19 15 19 19 15 19 19 16 19 19 16 20 20 16 20 20
-17 21 21 20 24 24 20 23 22 17 21 21 17 20 20 20 20 20
-21 22 21 21 22 21 21 22 21 21 22 21 20 20 20 18 19 18
-16 16 16 15 15 15 13 13 13 13 13 13 12 12 12 12 12 12
-12 12 12 10 10 9 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 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
-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 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 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 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 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
-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 21 22 21 110 109 94 110 109 94
-105 104 92 84 83 72 68 70 65 51 52 50 41 42 42 33 37 35
-28 31 30 23 27 26 20 23 23 18 22 22 17 20 20 25 27 26
-26 28 27 27 30 29 25 27 26 20 23 23 23 27 26 30 32 31
-20 24 24 17 21 21 18 22 22 15 19 19 26 28 27 20 23 23
-14 18 18 15 19 19 15 18 18 15 19 19 15 19 19 15 19 19
-15 19 19 15 19 19 15 19 19 15 19 19 15 19 19 16 19 19
-16 20 20 22 24 23 24 26 24 22 24 23 20 23 22 22 24 23
-24 26 24 24 26 24 23 24 24 22 24 23 21 22 21 19 20 19
-17 17 17 15 15 15 14 14 13 13 13 13 12 12 12 12 12 12
-12 12 12 12 12 12 2 2 2 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 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 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
-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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 2 2 2 99 98 80 110 109 94 108 107 93
-105 104 92 84 83 72 63 64 60 49 51 48 39 40 39 32 34 33
-27 30 29 23 25 24 20 23 23 17 20 20 15 19 19 14 18 18
-14 17 17 13 17 17 13 17 17 13 17 17 13 17 17 13 17 17
-14 17 17 14 17 17 14 17 17 14 17 17 14 17 17 14 17 17
-14 18 18 14 18 18 14 18 18 14 18 18 15 18 18 15 19 19
-15 19 19 15 19 19 15 19 19 15 19 19 15 19 19 15 19 19
-15 19 19 17 21 21 27 29 28 26 28 27 25 27 26 25 27 26
-27 29 28 27 29 28 26 28 27 24 26 24 21 22 21 20 20 20
-18 19 18 16 16 16 14 14 13 13 13 13 12 12 12 12 12 12
-12 12 12 12 12 12 4 5 5 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 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 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
-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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 51 52 50 110 109 94 110 109 94 105 104 92
-90 89 73 72 73 67 55 57 54 43 45 43 35 37 36 30 32 31
-26 28 27 20 24 24 17 21 21 16 19 19 15 18 18 14 17 17
-13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 13 16 16
-13 16 16 13 16 16 13 16 16 13 17 17 13 17 17 14 17 17
-14 17 17 14 17 17 14 17 17 14 18 18 14 18 18 14 18 18
-15 18 18 15 18 18 15 19 19 15 19 19 15 19 19 15 19 19
-15 19 19 15 19 19 27 29 28 32 34 33 28 31 30 27 29 28
-30 32 31 30 32 31 30 31 28 26 28 27 23 24 24 21 22 21
-19 20 19 16 16 16 14 14 13 13 13 13 12 12 12 12 12 12
-12 12 12 12 12 12 6 7 7 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 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 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
-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 0 0 0
-0 0 0 0 0 0 0 0 0 3 3 3 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 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 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
-0 0 0 10 10 9 108 107 93 110 109 94 108 107 93 99 98 80
-84 83 72 63 64 60 49 51 48 40 43 41 33 36 34 27 30 29
-23 27 26 18 22 22 17 20 20 15 18 18 14 17 17 13 16 16
-13 16 16 13 16 16 12 15 15 12 15 15 12 15 15 12 15 15
-13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 13 16 16
-13 17 17 13 17 17 14 17 17 14 17 17 14 17 17 14 18 18
-14 18 18 14 18 18 15 18 18 15 18 18 15 19 19 15 19 19
-15 19 19 15 19 19 17 21 21 33 36 34 32 34 33 31 33 31
-33 36 34 33 36 34 31 33 31 27 29 28 25 27 26 21 22 21
-19 20 19 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12
-12 12 12 12 12 12 8 8 7 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 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 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
-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 0 0 0
-0 0 0 0 0 0 63 64 60 137 133 100 43 45 43 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 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 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 68 70 65 110 109 94 110 109 94 105 104 92 84 83 72
-68 70 65 55 57 54 43 45 43 35 37 36 30 32 31 26 28 27
-20 24 24 17 21 21 16 19 19 14 17 17 13 16 16 12 15 15
-12 15 15 12 15 15 12 15 15 12 15 15 12 15 15 12 15 15
-12 15 15 12 15 15 12 15 15 12 15 15 12 15 15 13 16 16
-13 16 16 13 16 16 13 16 16 13 17 17 13 17 17 14 17 17
-14 17 17 14 17 17 14 18 18 14 18 18 14 18 18 15 18 18
-15 19 19 15 19 19 15 19 19 20 24 24 32 34 33 35 37 36
-37 39 37 35 37 36 33 36 34 30 32 31 26 28 27 22 24 23
-20 20 20 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12
-12 12 12 12 12 12 8 8 7 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 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 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
-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 0 0 0
-1 1 1 99 98 80 184 179 149 184 179 149 68 70 65 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 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 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
-15 15 15 110 109 94 110 109 94 108 107 93 99 98 80 72 73 67
-61 63 57 49 51 48 39 40 39 33 36 34 27 30 29 23 25 24
-18 22 22 16 19 19 14 17 17 13 16 16 12 15 15 12 15 15
-11 14 14 11 14 14 11 14 14 11 14 14 11 14 14 11 14 14
-11 14 14 11 14 14 12 14 14 12 15 15 12 15 15 12 15 15
-12 15 15 13 16 16 13 16 16 13 16 16 13 16 16 13 16 16
-13 17 17 14 17 17 14 17 17 14 17 17 14 18 18 14 18 18
-14 18 18 15 18 18 15 19 19 15 19 19 30 32 31 38 39 37
-39 40 39 39 40 39 35 37 36 31 33 31 27 29 28 22 24 23
-20 20 20 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12
-12 12 12 12 12 12 8 8 7 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 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 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
-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 3 3 3
-110 109 94 197 193 154 210 208 158 184 179 149 68 70 65 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 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 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
-68 70 65 110 109 94 110 109 94 105 104 92 84 83 72 65 66 61
-51 52 50 43 45 43 35 37 36 30 32 31 25 27 26 20 23 23
-17 20 20 15 18 18 13 16 16 12 15 15 12 15 15 11 14 14
-11 14 14 11 14 14 11 13 13 11 13 13 11 13 13 11 13 13
-11 14 14 11 14 14 11 14 14 11 14 14 11 14 14 11 14 14
-12 15 15 12 15 15 12 15 15 12 15 15 13 16 16 13 16 16
-13 16 16 13 16 16 13 17 17 13 17 17 14 17 17 14 17 17
-14 18 18 14 18 18 14 18 18 16 19 19 37 39 37 41 42 42
-41 42 42 41 42 42 38 39 37 32 34 33 27 29 28 23 24 24
-21 22 21 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12
-12 12 12 12 12 12 8 8 7 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 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 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
-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 11 11 11 137 133 100
-197 193 154 251 251 187 239 239 170 184 179 149 31 33 31 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 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 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 12 12 12
-110 109 94 110 109 94 105 104 92 90 89 73 72 73 67 58 59 55
-46 47 45 37 39 37 31 33 31 26 28 27 20 24 24 17 21 21
-15 18 18 13 16 16 12 15 15 12 14 14 11 13 13 11 13 13
-10 13 13 10 13 13 10 13 13 10 13 13 10 13 13 10 13 13
-10 13 13 10 13 13 11 13 13 11 13 13 11 14 14 11 14 14
-11 14 14 11 14 14 12 14 14 12 15 15 12 15 15 12 15 15
-13 16 16 13 16 16 13 16 16 13 16 16 13 17 17 13 17 17
-14 17 17 14 17 17 14 18 18 23 27 26 41 42 42 41 42 42
-43 45 43 41 42 42 39 40 39 33 36 34 27 29 28 23 24 24
-21 22 21 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12
-12 12 12 12 12 12 6 7 7 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 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 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
-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 27 29 28 168 163 120 210 208 158
-251 251 187 251 251 187 210 208 158 137 133 100 1 1 1 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 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 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 60 60 56
-110 109 94 105 104 92 105 104 92 84 83 72 65 66 61 51 52 50
-40 43 41 33 36 34 27 30 29 23 25 24 18 22 22 16 19 19
-14 17 17 12 15 15 11 14 14 11 14 14 10 13 13 10 13 13
-10 13 13 10 12 12 10 12 12 10 12 12 10 12 12 10 12 12
-10 12 12 10 12 12 10 13 13 10 13 13 10 13 13 11 13 13
-11 13 13 11 14 14 11 14 14 11 14 14 11 14 14 12 15 15
-12 15 15 12 15 15 12 15 15 13 16 16 13 16 16 13 16 16
-13 17 17 13 17 17 14 17 17 32 34 33 43 45 43 43 45 43
-43 45 43 43 45 43 39 40 39 33 36 34 27 29 28 23 24 24
-21 22 21 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12
-12 12 12 12 12 12 6 7 7 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 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 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
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 1 1 1 68 70 65 184 179 149 210 208 158 251 251 187
-251 251 187 214 212 158 184 179 149 37 39 37 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 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 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 6 7 7 105 104 92
-105 104 92 105 104 92 99 98 80 72 73 67 58 59 55 46 47 45
-35 37 36 30 32 31 25 27 26 20 23 23 16 19 19 14 17 17
-12 15 15 12 14 14 11 13 13 10 13 13 10 12 12 10 12 12
-10 12 12 10 12 12 9 12 12 9 12 12 9 12 12 9 12 12
-10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 10 13 13
-10 13 13 10 13 13 11 13 13 11 13 13 11 14 14 11 14 14
-11 14 14 12 15 15 12 15 15 12 15 15 12 15 15 13 16 16
-13 16 16 13 16 16 17 20 20 41 42 42 46 47 45 46 47 45
-46 47 45 43 45 43 40 41 39 33 36 34 27 29 28 23 24 24
-20 20 20 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12
-12 12 12 12 12 12 4 5 5 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 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 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
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-15 15 15 110 109 94 197 193 154 214 212 158 251 251 187 251 251 187
-239 239 170 184 179 149 84 83 72 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 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
-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 47 48 46 105 104 92
-105 104 92 99 98 80 84 83 72 68 70 65 51 52 50 40 43 41
-32 34 33 27 29 28 22 24 23 17 21 21 15 18 18 13 16 16
-12 15 15 11 13 13 10 13 13 10 12 12 9 12 12 9 12 12
-9 12 12 9 12 12 9 11 11 9 11 11 9 11 11 9 11 11
-9 12 12 9 12 12 9 12 12 9 12 12 10 12 12 10 12 12
-10 12 12 10 12 12 10 13 13 10 13 13 10 13 13 11 13 13
-11 14 14 11 14 14 11 14 14 12 14 14 12 15 15 12 15 15
-12 15 15 13 16 16 28 31 30 43 45 43 47 48 46 47 48 46
-47 48 46 43 45 43 40 41 39 33 36 34 27 29 28 22 24 23
-20 20 20 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12
-12 12 12 12 12 12 3 4 4 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 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 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
-0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 60 60 56
-177 172 135 197 193 154 251 251 187 251 251 187 251 251 187 251 251 187
-184 179 149 110 109 94 3 4 4 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 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
-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 1 1 1 99 98 80 105 104 92
-99 98 80 87 86 72 84 83 72 63 64 60 46 47 45 35 37 36
-30 32 31 25 27 26 18 22 22 16 19 19 14 17 17 12 15 15
-11 14 14 10 13 13 9 12 12 9 12 12 9 11 11 9 11 11
-9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11
-9 11 11 9 11 11 9 11 11 9 11 11 9 12 12 9 12 12
-9 12 12 10 12 12 10 12 12 10 12 12 10 13 13 10 13 13
-10 13 13 11 13 13 11 14 14 11 14 14 11 14 14 12 15 15
-12 15 15 14 17 17 41 42 42 47 48 46 49 51 48 51 52 50
-47 48 46 43 45 43 40 41 39 33 36 34 27 29 28 22 24 23
-19 20 19 16 16 16 14 14 13 13 13 13 12 12 12 12 12 12
-12 12 12 12 12 12 2 2 2 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 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 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
-0 0 0 0 0 0 0 0 0 23 24 24 137 133 100 184 179 149
-210 208 158 251 251 187 251 251 187 251 251 187 251 251 187 184 179 149
-110 109 94 13 13 13 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
-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 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 30 32 31 105 104 92 99 98 80
-84 83 72 84 83 72 72 73 67 55 57 54 41 42 42 32 34 33
-27 29 28 20 24 24 17 20 20 14 17 17 13 16 16 12 14 14
-10 13 13 10 12 12 9 11 11 9 11 11 9 11 11 9 11 11
-9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11
-9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11
-9 11 11 9 12 12 9 12 12 10 12 12 10 12 12 10 12 12
-10 13 13 10 13 13 10 13 13 11 13 13 11 14 14 11 14 14
-11 14 14 27 29 28 55 56 53 72 73 67 51 52 50 51 52 50
-49 51 48 43 45 43 39 40 39 32 34 33 26 28 27 21 22 21
-19 20 19 16 16 16 18 19 17 13 13 13 12 12 12 12 12 12
-12 12 12 12 12 12 1 1 1 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 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 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
-0 0 0 8 8 7 84 83 72 184 179 149 197 193 154 251 251 187
-251 251 187 251 251 187 251 251 187 251 251 187 184 179 149 145 141 105
-19 20 19 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 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 0 0 0 0 0 0
-0 0 0 14 14 13 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 72 73 67 105 104 92 84 83 72
-72 73 67 84 83 72 68 70 65 49 51 48 39 40 39 30 32 31
-25 27 26 18 22 22 15 18 18 13 16 16 12 15 15 11 13 13
-10 12 12 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11
-9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11
-9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11
-9 11 11 9 11 11 9 11 11 9 12 12 9 12 12 9 12 12
-10 12 12 10 12 12 10 12 12 10 13 13 10 13 13 11 13 13
-13 16 16 41 42 42 99 98 80 158 153 112 65 66 61 51 52 50
-49 51 48 43 45 43 39 40 39 31 33 31 25 27 26 21 22 21
-21 22 21 68 70 65 55 56 53 13 13 13 12 12 12 12 12 12
-12 12 12 11 11 11 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 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
-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 3 3 3
-63 64 60 158 153 112 184 179 149 210 208 158 251 251 187 251 251 187
-251 251 187 251 251 187 251 251 187 184 179 149 137 133 100 27 29 28
-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 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 0 0 0 0 0 0 0 0 0
-21 22 21 110 109 94 5 6 5 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 13 13 13 105 104 92 90 89 73 72 73 67
-68 70 65 84 83 72 63 64 60 46 47 45 35 37 36 27 29 28
-22 24 23 17 20 20 14 17 17 12 15 15 11 14 14 10 12 12
-10 12 12 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11
-9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11
-9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11
-9 12 12 9 12 12 10 12 12 10 12 12 10 13 13 10 13 13
-30 32 31 47 48 46 177 172 135 210 208 158 137 133 100 55 56 53
-49 51 48 43 45 43 38 39 37 31 33 31 25 27 26 22 24 23
-110 109 94 184 179 149 63 64 60 13 13 13 12 12 12 12 12 12
-12 12 12 8 9 9 0 0 0 1 1 1 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 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 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 21 22 21 105 104 92
-184 179 149 210 208 158 251 251 187 251 251 187 251 251 187 251 251 187
-251 251 187 251 251 187 184 179 149 145 141 105 23 24 24 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 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 0 0 0 0 0 0 0 0 0 0 0 0
-68 70 65 184 179 149 105 104 92 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 51 52 50 99 98 80 84 83 72 63 64 60
-68 70 65 72 73 67 55 57 54 41 42 42 32 34 33 25 27 26
-20 23 23 16 19 19 13 16 16 12 14 14 10 13 13 10 12 12
-9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 9 11 11 9 11 11
-9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11
-9 11 11 9 11 11 9 12 12 9 12 12 10 12 12 17 20 20
-46 47 45 72 73 67 210 208 158 251 251 187 210 208 158 63 64 60
-49 51 48 43 45 43 37 39 37 30 32 31 24 26 24 105 104 92
-210 208 158 197 193 154 47 48 46 13 13 13 12 12 12 12 12 12
-12 12 12 6 7 7 33 36 34 48 49 45 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 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 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 8 8 7 23 24 24 55 56 53 110 109 94
-210 208 158 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187
-251 251 187 184 179 149 110 109 94 20 20 20 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 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-110 109 94 251 251 187 210 208 158 47 48 46 0 0 0 0 0 0
-0 0 0 1 1 1 90 89 73 90 89 73 72 73 67 55 56 53
-72 73 67 68 70 65 51 52 50 37 39 37 28 31 30 23 25 24
-17 21 21 15 18 18 12 15 15 11 14 14 10 13 13 9 12 12
-9 11 11 9 11 11 9 11 11 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11
-9 11 11 9 11 11 9 11 11 9 12 12 13 16 16 41 42 42
-49 51 48 110 109 94 251 251 187 251 251 187 251 251 187 105 104 92
-49 51 48 43 45 43 35 37 36 30 31 28 47 48 46 197 193 154
-251 251 187 197 193 154 31 33 31 12 12 12 12 12 12 12 12 12
-12 12 12 51 52 50 184 179 149 72 73 67 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 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 0 0 0 0 0 0 0 0 0 2 2 2
-11 11 11 21 22 21 30 32 31 40 41 39 60 60 56 145 141 105
-251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 214 212 158
-184 179 149 110 109 94 13 13 13 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 4 5 4 61 61 53 48 49 45 3 4 3
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-156 151 111 251 251 187 251 251 187 184 179 149 11 11 11 0 0 0
-0 0 0 26 28 27 99 98 80 84 83 72 60 60 56 43 45 43
-72 73 67 65 66 61 49 51 48 35 37 36 27 29 28 20 24 24
-17 20 20 14 17 17 12 15 15 11 13 13 10 12 12 9 11 11
-9 11 11 9 11 11 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 9 11 11 9 11 11
-9 11 11 9 11 11 9 11 11 11 13 13 37 39 37 47 48 46
-51 52 50 184 179 149 251 251 187 251 251 187 251 251 187 145 141 105
-47 48 46 41 42 42 35 37 36 27 29 28 137 133 100 251 251 187
-251 251 187 197 193 154 19 20 19 12 12 12 12 12 12 12 12 12
-27 29 28 184 179 149 214 212 158 63 64 60 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 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 1 1 1 6 7 7 16 16 16 24 26 24
-30 32 31 38 39 37 47 48 46 55 57 54 68 70 65 110 109 94
-197 193 154 251 251 187 251 251 187 251 251 187 210 208 158 184 179 149
-105 104 92 8 8 7 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
-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 65 66 61 184 179 149 156 151 111
-30 32 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-168 163 120 251 251 187 251 251 187 251 251 187 110 109 94 0 0 0
-0 0 0 60 60 56 84 83 72 68 70 65 51 52 50 38 39 37
-84 83 72 63 64 60 43 45 43 33 36 34 25 27 26 20 23 22
-15 18 18 13 16 16 12 14 14 10 13 13 9 12 12 9 11 11
-9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-9 11 11 9 11 11 10 12 12 33 36 34 46 47 45 51 52 50
-72 73 67 210 208 158 251 251 187 251 251 187 251 251 187 177 172 135
-47 48 46 41 42 42 35 37 36 37 39 37 184 179 149 251 251 187
-251 251 187 197 193 154 13 13 13 12 12 12 12 12 12 12 12 12
-110 109 94 251 251 187 251 251 187 37 39 37 0 0 0 0 0 0
-0 0 0 21 22 20 2 2 1 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 0 0 0 0 0 0 0 0 0 0 0 0
-4 5 5 12 12 12 21 22 21 25 27 26 30 32 31 38 39 37
-46 47 45 55 56 53 60 60 56 65 66 61 68 70 65 105 104 92
-110 109 94 197 193 154 210 208 158 197 193 154 184 179 149 84 83 72
-2 2 2 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
-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 13 13 13 184 179 149 251 251 187
-197 193 154 43 44 41 0 0 0 0 0 0 0 0 0 0 0 0
-145 141 105 251 251 187 251 251 187 251 251 187 214 212 158 43 45 43
-2 2 2 84 83 72 72 73 67 58 59 55 41 42 42 38 39 37
-72 73 67 58 59 55 41 42 42 31 33 31 25 27 26 18 22 22
-14 17 17 12 15 15 12 14 14 10 12 12 9 12 12 9 11 11
-9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 9 12 12 31 33 31 43 45 43 49 51 48 55 56 53
-110 109 94 251 251 187 251 251 187 251 251 187 251 251 187 168 163 120
-47 48 46 41 42 42 33 36 34 63 64 60 197 193 154 251 251 187
-251 251 187 184 179 149 13 13 13 12 12 12 12 12 12 16 16 16
-197 193 154 251 251 187 239 239 170 20 20 20 0 0 0 2 2 1
-108 107 93 110 109 94 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 0 0 0 1 1 1 4 5 5 11 11 11 18 19 18
-22 24 23 26 28 27 32 34 33 39 40 39 46 47 45 51 52 50
-55 57 54 60 60 56 63 64 60 63 64 60 63 64 60 58 59 55
-63 64 60 99 98 80 145 141 105 137 133 100 43 45 43 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 0 0 0 0 0 0
-0 0 0
-0 0 0 0 0 0 0 0 0 3 4 3 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 110 109 94 251 251 187
-251 251 187 184 179 149 25 27 26 0 0 0 0 0 0 0 0 0
-99 98 80 251 251 187 251 251 187 251 251 187 251 251 187 156 151 111
-25 27 26 84 83 72 65 66 61 47 48 46 32 34 33 39 40 39
-72 73 67 55 57 54 40 41 39 30 32 31 23 25 24 18 22 22
-14 17 17 12 15 15 11 13 13 10 12 12 9 11 11 9 11 11
-9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-9 11 11 28 31 30 41 42 42 47 48 46 55 56 53 58 59 55
-137 133 100 251 251 187 251 251 187 251 251 187 210 208 158 137 133 100
-47 48 46 40 41 39 32 34 33 75 75 61 184 179 149 239 239 170
-251 251 187 177 172 135 13 13 13 12 12 12 12 12 12 43 44 41
-197 193 154 251 251 187 210 208 158 10 10 9 0 0 0 84 83 72
-251 251 187 84 83 72 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 1 1 1
-6 7 7 11 11 11 17 17 17 20 20 20 23 24 24 27 29 28
-32 34 33 38 39 37 43 45 43 47 48 46 51 52 50 55 56 53
-58 59 55 58 59 55 55 57 54 55 56 53 47 48 46 41 42 42
-35 37 36 31 33 31 47 48 46 14 14 13 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 0 0 0 0 0 0 0 0 0
-0 0 0
-0 0 0 0 0 0 0 0 0 66 65 55 99 98 80 20 20 20
-0 0 0 0 0 0 0 0 0 0 0 0 43 45 43 214 212 158
-251 251 187 251 251 187 145 141 105 3 3 3 0 0 0 0 0 0
-48 49 45 184 179 149 239 239 170 251 251 187 239 239 170 177 172 135
-84 83 72 72 73 67 55 56 53 39 40 39 26 28 27 39 40 39
-68 70 65 51 52 50 39 40 39 28 31 30 22 24 23 17 20 20
-14 17 17 12 14 14 10 13 13 9 11 11 9 11 11 9 11 11
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-27 29 28 40 41 39 46 47 45 51 52 50 55 57 54 63 64 60
-131 127 93 197 193 154 210 208 158 197 193 154 168 163 120 96 95 69
-47 48 46 40 41 39 32 34 33 71 71 57 145 141 105 184 179 149
-184 179 149 131 127 93 13 13 13 12 12 12 12 12 12 48 49 45
-168 163 120 184 179 149 156 151 111 6 7 7 14 14 13 177 172 135
-239 239 170 40 41 39 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 3 3 3 6 7 7 11 11 11 16 16 16
-18 19 18 21 22 21 23 24 24 27 29 28 32 34 33 37 39 37
-41 42 42 43 45 43 47 48 46 51 52 50 51 52 50 51 52 50
-51 52 50 49 51 48 46 47 45 40 41 39 32 34 33 25 27 26
-20 20 20 14 14 13 2 2 2 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 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0
-0 0 0 0 0 0 0 0 0 33 36 34 197 193 154 184 179 149
-41 42 42 0 0 0 0 0 0 0 0 0 3 3 3 184 179 149
-251 251 187 251 251 187 184 179 149 48 49 45 0 0 0 0 0 0
-16 17 12 121 119 87 177 172 135 194 189 146 188 184 146 145 141 105
-82 81 62 63 64 60 46 47 45 31 33 31 21 22 21 35 37 36
-68 70 65 51 52 50 37 39 37 27 30 29 22 24 23 17 20 20
-13 16 16 12 14 14 10 13 13 9 11 11 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 25 27 26
-38 39 37 43 45 43 51 52 50 55 56 53 60 60 56 63 64 60
-92 91 72 158 153 112 176 171 126 171 165 117 149 143 98 82 81 62
-44 46 43 38 39 37 30 32 31 71 71 57 131 127 93 160 154 106
-149 143 98 82 81 62 13 13 13 12 12 12 12 12 12 46 47 43
-121 119 87 134 131 96 96 95 69 7 7 6 38 39 37 131 127 93
-145 141 105 12 13 12 0 0 0 1 1 1 3 3 3 6 7 7
-10 10 9 12 12 12 14 14 13 16 16 16 18 19 18 21 22 21
-22 24 23 26 28 27 30 31 28 33 36 34 37 39 37 40 41 39
-41 42 42 43 45 43 46 47 45 46 47 45 46 47 45 43 45 43
-41 42 42 37 39 37 31 33 31 26 28 27 21 22 21 16 16 16
-6 7 7 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
-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 177 172 135 251 251 187
-197 193 154 27 29 28 0 0 0 0 0 0 0 0 0 110 109 94
-239 239 170 239 239 170 184 179 149 87 86 72 2 2 1 0 0 0
-1 1 1 82 81 62 142 137 94 165 161 109 165 161 109 131 127 93
-75 75 61 55 56 53 37 39 37 25 27 26 19 20 19 32 34 33
-65 66 61 49 51 48 35 37 36 27 29 28 20 23 23 16 19 19
-13 16 16 13 13 13 10 12 12 9 11 11 8 10 10 8 10 10
-8 9 9 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 22 24 23 35 37 36
-41 42 42 47 48 46 55 56 53 58 59 55 63 64 60 65 66 61
-71 71 57 131 127 93 160 154 106 160 154 106 142 137 94 82 81 62
-46 47 43 40 41 39 33 36 34 66 65 55 125 122 87 149 143 98
-142 137 94 82 81 62 17 17 17 18 19 17 14 14 13 46 47 43
-118 116 76 125 122 87 96 95 69 16 17 12 71 71 57 103 101 77
-82 81 62 11 11 11 11 11 11 13 13 13 14 14 13 14 14 13
-15 15 15 16 16 16 17 17 17 19 20 19 21 22 21 23 24 24
-26 28 27 27 29 28 31 33 31 33 36 34 35 37 36 38 39 37
-39 40 39 39 40 39 38 39 37 37 39 37 35 37 36 31 33 31
-27 29 28 24 26 24 21 22 21 17 17 17 12 12 12 2 2 2
-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 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 0 0 0 68 70 65 251 251 187
-251 251 187 156 151 111 2 2 1 0 0 0 0 0 0 43 44 41
-177 172 135 184 179 149 158 153 112 103 101 77 19 20 18 0 0 0
-0 0 0 46 47 43 131 127 93 160 154 106 160 154 106 131 127 93
-71 71 57 43 45 43 30 32 31 21 22 21 16 16 16 26 28 27
-63 64 60 47 48 46 35 37 36 26 28 27 20 23 23 16 19 19
-13 16 16 13 13 13 10 12 12 9 11 11 8 10 10 8 10 10
-7 9 9 7 9 9 8 9 9 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 20 20 20 33 36 34 40 41 39
-46 47 45 51 52 50 55 57 54 60 60 56 63 64 60 65 66 61
-66 65 55 118 116 76 151 147 98 165 161 109 151 147 98 121 119 87
-96 95 69 96 95 69 96 95 69 103 101 77 142 137 94 151 147 98
-142 137 94 103 101 77 82 81 62 82 81 62 82 81 62 96 95 69
-131 127 93 142 137 94 103 101 77 46 47 43 96 95 69 118 116 76
-71 71 57 14 14 13 14 14 13 15 15 15 15 15 15 16 16 16
-16 16 16 17 17 17 18 19 18 20 20 20 21 22 21 23 24 24
-25 27 26 27 29 28 30 31 28 30 32 31 31 33 31 31 33 31
-31 33 31 31 33 31 30 31 28 27 29 28 25 27 26 22 24 23
-20 20 20 16 16 16 13 13 13 6 7 7 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 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
-58 59 55 68 70 65 8 8 7 0 0 0 10 10 9 210 208 158
-251 251 187 184 179 149 38 39 37 0 0 0 0 0 0 8 8 7
-103 101 77 149 143 98 149 143 98 118 116 76 40 41 39 25 27 25
-53 55 47 82 81 62 144 139 99 165 161 109 165 161 109 142 137 94
-71 71 57 35 37 36 24 26 24 18 19 18 15 15 15 22 24 23
-63 64 60 46 47 45 33 36 34 26 28 27 20 23 22 17 18 17
-12 15 15 11 13 13 10 12 12 9 11 11 8 10 10 8 10 10
-7 9 9 7 9 9 7 9 9 7 9 9 8 9 9 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 16 16 16 30 31 28 35 37 36 41 42 42
-47 48 46 55 56 53 58 59 55 63 64 60 65 66 61 65 66 61
-61 61 53 103 101 77 151 147 98 171 165 117 171 165 117 168 163 120
-158 153 112 158 153 112 155 149 109 151 147 98 151 147 98 160 154 106
-151 147 98 149 143 98 142 137 94 149 143 98 149 143 98 149 143 98
-155 149 109 151 147 98 131 127 93 103 101 77 125 122 87 118 116 76
-71 71 57 16 16 16 16 16 16 16 16 16 17 17 17 17 17 17
-17 17 17 17 17 17 18 19 18 19 20 19 20 20 20 21 22 21
-23 24 24 24 26 24 25 27 26 26 28 27 26 28 27 26 28 27
-25 27 26 24 26 24 22 24 23 21 22 21 19 20 19 16 16 16
-14 14 13 8 8 7 1 1 1 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 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
-20 20 20 184 179 149 168 163 120 21 22 21 0 0 0 105 104 92
-177 172 135 145 141 105 71 71 57 0 0 0 0 0 0 0 0 0
-66 65 55 131 127 93 151 147 98 142 137 94 118 116 76 121 119 87
-145 141 105 158 153 112 176 171 126 178 174 128 176 171 126 149 145 103
-96 95 69 31 33 31 21 22 21 16 16 16 14 14 13 18 19 18
-60 60 56 46 47 45 33 36 34 25 27 26 21 22 21 15 18 18
-12 15 15 11 13 13 9 11 11 8 10 10 8 10 10 8 9 9
-7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 8 9 9
-8 9 9 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 10 12 12 26 28 27 31 33 31 38 39 37 43 45 43
-51 52 50 55 56 53 60 60 56 63 64 60 65 66 61 68 70 65
-63 64 60 96 95 69 158 153 112 178 174 128 188 184 146 194 189 146
-194 189 146 188 184 146 184 181 136 176 171 126 171 165 117 173 167 111
-173 167 111 165 161 109 171 165 117 174 170 121 176 171 126 178 174 128
-178 174 128 174 170 121 160 154 106 149 143 98 149 143 98 125 122 87
-71 71 57 16 16 16 16 16 16 17 17 17 17 17 17 17 17 17
-17 17 17 17 17 17 17 17 17 18 19 18 19 20 19 20 20 20
-21 22 21 21 22 21 21 22 21 22 24 23 21 22 21 21 22 21
-21 22 21 19 20 19 18 19 18 16 16 16 14 14 13 11 11 11
-3 3 3 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
-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 0 0 0
-0 0 0
-0 0 0 105 104 92 197 193 154 110 109 94 9 9 8 36 38 35
-121 119 87 131 127 93 96 95 69 18 19 17 30 31 28 66 65 55
-96 95 69 142 137 94 160 154 106 160 154 106 160 154 106 168 163 120
-184 181 136 194 191 148 197 193 154 197 193 154 194 189 146 168 163 120
-125 122 87 46 47 43 18 19 18 15 15 15 13 13 13 14 14 13
-55 57 54 43 45 43 32 34 33 25 27 26 18 22 22 17 17 17
-12 14 14 10 12 12 9 11 11 8 10 10 8 9 9 7 9 9
-6 8 8 7 9 9 7 9 9 7 9 9 7 9 9 7 9 9
-7 9 9 8 9 9 8 9 9 8 10 10 8 10 10 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 32 34 33 41 42 42 35 37 36 39 40 39 37 39 37
-35 37 36 55 57 54 60 60 56 63 64 60 65 66 61 65 66 61
-61 63 57 115 113 82 168 163 120 194 191 148 204 201 155 210 208 158
-210 208 158 210 208 158 197 193 154 194 189 146 186 182 128 176 171 126
-174 170 121 176 171 126 186 182 128 190 186 136 194 191 148 197 193 154
-197 193 154 188 184 146 181 176 137 174 170 121 165 161 109 142 137 94
-82 81 62 24 26 24 16 16 16 16 16 16 16 16 16 16 16 16
-17 17 17 17 17 17 17 17 17 17 17 17 18 19 18 19 20 19
-19 20 19 19 20 19 20 20 20 19 20 19 19 20 19 18 19 18
-17 17 17 15 15 15 13 13 13 12 12 12 6 7 7 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 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 0 0 0 0 0 0 0 0 0
-0 0 0
-0 0 0 17 18 17 137 133 100 115 113 82 53 55 47 19 20 18
-103 101 77 144 139 99 137 133 100 115 113 82 137 133 100 156 151 111
-158 153 112 164 159 111 171 165 117 174 170 121 178 174 128 194 189 146
-204 201 155 214 212 158 214 212 158 214 212 158 210 208 158 188 184 146
-158 153 112 87 86 72 17 17 17 13 13 13 13 13 13 15 15 15
-55 56 53 43 45 43 32 34 33 24 26 24 17 20 20 16 16 16
-12 14 14 10 12 12 8 10 10 8 10 10 7 9 9 6 8 8
-6 8 8 6 8 8 6 8 8 7 9 9 7 9 9 7 9 9
-7 9 9 7 9 9 7 9 9 7 9 9 8 9 9 8 10 10
-8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10
-8 10 10 110 109 94 84 83 72 49 51 48 26 28 27 8 10 10
-8 9 9 51 52 50 58 59 55 63 64 60 63 64 60 63 64 60
-66 65 55 134 131 96 181 176 137 210 208 158 214 212 158 239 239 170
-239 239 170 224 223 159 210 208 158 204 201 155 194 189 146 186 182 128
-186 182 128 184 181 136 194 189 146 204 201 155 210 208 158 210 208 158
-210 208 158 210 208 158 197 193 154 190 186 136 176 171 126 155 149 109
-118 116 76 36 38 35 15 15 15 16 16 16 16 16 16 16 16 16
-16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 17 17 17
-17 17 17 17 17 17 17 17 17 16 16 16 16 16 16 15 15 15
-13 13 13 12 12 12 8 8 7 2 2 2 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 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 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0
-0 0 0 0 0 0 53 55 47 103 101 77 96 95 69 53 55 47
-103 101 77 158 153 112 177 172 135 184 179 149 188 184 146 197 193 154
-194 189 146 190 186 136 184 181 136 184 181 136 194 189 146 210 208 158
-214 212 158 239 239 170 251 251 187 251 251 187 224 223 159 204 201 155
-177 172 135 121 119 87 30 31 28 13 13 13 12 12 12 39 40 39
-60 60 56 43 45 43 32 34 33 23 25 24 18 19 18 13 16 16
-13 13 13 9 11 11 8 10 10 8 9 9 6 8 8 6 8 8
-6 8 8 6 8 8 6 8 8 6 8 8 6 8 8 7 9 9
-7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 7 9 9
-7 9 9 8 9 9 8 9 9 8 10 10 8 10 10 8 10 10
-14 17 17 197 193 154 158 153 112 55 57 54 7 9 9 7 9 9
-8 10 10 51 52 50 58 59 55 60 60 56 63 64 60 63 64 60
-71 71 57 155 149 109 194 191 148 214 212 158 251 251 187 251 251 187
-251 251 187 251 251 187 239 239 170 210 208 158 197 193 154 190 186 136
-190 186 136 194 189 146 204 201 155 210 208 158 224 223 159 239 239 170
-239 239 170 224 223 159 210 208 158 204 201 155 190 186 136 164 159 111
-125 122 87 40 41 39 15 15 15 15 15 15 15 15 15 15 15 15
-16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16
-16 16 16 16 16 16 15 15 15 14 14 13 13 13 13 12 12 12
-8 9 9 3 3 3 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 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
-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 21 22 20 96 95 69 125 122 87 121 119 87
-144 139 99 177 172 135 197 193 154 210 208 158 214 212 158 214 212 158
-210 208 158 204 201 155 194 191 148 194 189 146 204 201 155 214 212 158
-239 239 170 251 251 187 251 251 187 251 251 187 251 251 187 214 212 158
-188 184 146 145 141 105 53 55 47 12 12 12 15 15 15 63 64 60
-63 64 60 41 42 42 31 33 31 23 24 24 17 18 17 12 15 15
-11 13 13 9 11 11 8 9 9 7 9 9 6 8 8 6 8 8
-6 7 7 6 7 7 6 8 8 6 8 8 6 8 8 6 8 8
-6 8 8 7 9 9 7 9 9 7 9 9 7 9 9 7 9 9
-7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 8 8 7
-43 45 43 251 251 187 156 151 111 8 10 10 7 9 9 7 9 9
-21 22 21 51 52 50 55 56 53 55 57 54 58 59 55 58 59 55
-75 75 61 158 153 112 197 193 154 224 223 159 251 251 187 251 251 187
-251 251 187 251 251 187 251 251 187 214 212 158 204 201 155 194 189 146
-190 186 136 197 193 154 210 208 158 224 223 159 251 251 187 251 251 187
-251 251 187 251 251 187 239 239 170 210 208 158 197 193 154 176 171 126
-125 122 87 36 38 35 14 14 13 14 14 13 15 15 15 15 15 15
-15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15
-15 15 15 14 14 13 13 13 13 12 12 12 10 10 9 3 4 4
-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 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 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 7 7 5 71 71 57 131 127 93 158 153 112
-177 172 135 197 193 154 214 212 158 239 239 170 251 251 187 251 251 187
-238 237 168 210 208 158 204 201 155 197 193 154 204 201 155 214 212 158
-251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 214 212 158
-197 193 154 156 151 111 66 65 55 12 12 12 37 39 37 58 59 55
-58 59 55 41 42 42 31 33 31 22 24 23 17 17 17 12 14 14
-10 12 12 8 10 10 6 8 8 6 8 8 6 7 7 6 7 7
-6 7 7 5 7 7 6 7 7 6 7 7 6 8 8 6 8 8
-6 8 8 6 8 8 6 8 8 7 9 9 7 9 9 7 9 9
-7 9 9 6 8 8 6 8 8 6 8 8 6 8 8 6 8 8
-61 63 57 197 193 154 16 19 19 6 8 8 6 8 8 8 9 9
-41 42 42 47 48 46 51 52 50 51 52 50 55 56 53 55 56 53
-71 71 57 158 153 112 197 193 154 224 223 159 251 251 187 251 251 187
-251 251 187 251 251 187 239 239 170 214 212 158 204 201 155 194 189 146
-190 186 136 197 193 154 210 208 158 239 239 170 251 251 187 251 251 187
-251 251 187 251 251 187 251 251 187 224 223 159 204 201 155 177 172 135
-121 119 87 30 31 28 13 13 13 14 14 13 14 14 13 14 14 13
-14 14 13 14 14 13 15 15 15 15 15 15 14 14 13 13 13 13
-12 12 12 12 12 12 10 10 9 4 5 5 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 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 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
-0 0 0 0 0 0 0 0 0 48 49 45 131 127 93 174 170 121
-194 189 146 210 208 158 239 239 170 251 251 187 251 251 187 251 251 187
-251 251 187 214 212 158 204 201 155 197 193 154 204 201 155 210 208 158
-239 239 170 251 251 187 251 251 187 251 251 187 239 239 170 214 212 158
-194 191 148 156 151 111 71 71 57 19 20 19 51 52 50 51 52 50
-51 52 50 41 42 42 30 32 31 21 22 21 17 17 17 13 13 13
-9 11 11 8 9 9 6 8 8 6 7 7 6 7 7 5 7 7
-5 6 5 5 6 5 5 7 7 5 7 7 6 7 7 6 7 7
-6 8 8 6 8 8 6 8 8 6 7 7 6 7 7 6 7 7
-6 7 7 6 8 8 6 8 8 6 8 8 6 8 8 6 8 8
-55 56 53 43 45 43 6 8 8 6 8 8 6 8 8 47 48 46
-60 60 56 47 48 46 46 47 45 47 48 46 38 39 37 10 12 12
-66 65 55 145 141 105 197 193 154 214 212 158 251 251 187 251 251 187
-251 251 187 251 251 187 224 223 159 210 208 158 194 191 148 184 181 136
-184 181 136 194 189 146 204 201 155 224 223 159 251 251 187 251 251 187
-251 251 187 251 251 187 251 251 187 239 239 170 210 208 158 181 176 137
-115 113 82 21 22 20 13 13 13 13 13 13 13 13 13 13 13 13
-14 14 13 13 13 13 13 13 13 13 13 13 12 12 12 11 11 11
-10 10 9 6 7 7 1 1 1 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 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 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
-0 0 0
-0 0 0 0 0 0 2 2 1 66 65 55 144 139 99 178 174 128
-204 201 155 214 212 158 251 251 187 251 251 187 251 251 187 251 251 187
-251 251 187 214 212 158 204 201 155 194 191 148 197 193 154 204 201 155
-214 212 158 239 239 170 239 239 170 239 239 170 214 212 158 210 208 158
-184 181 136 149 145 103 66 65 55 41 42 42 47 48 46 46 47 45
-43 45 43 39 40 39 28 31 30 21 22 21 16 16 16 10 12 12
-8 10 10 6 8 8 6 7 7 6 7 7 5 6 5 5 6 5
-5 6 5 5 6 5 5 6 5 5 6 5 5 7 7 5 7 7
-6 7 7 6 7 7 6 7 7 5 7 7 5 7 7 5 7 7
-5 7 7 6 7 7 6 7 7 6 7 7 6 7 7 6 8 8
-6 8 8 6 8 8 6 7 7 6 7 7 46 47 45 156 151 111
-105 104 92 58 59 55 43 45 43 32 34 33 6 8 8 6 8 8
-49 51 48 125 122 87 181 176 137 204 201 155 214 212 158 239 239 170
-239 239 170 214 212 158 210 208 158 197 193 154 181 176 137 176 171 126
-176 171 126 184 181 136 197 193 154 210 208 158 239 239 170 251 251 187
-251 251 187 251 251 187 251 251 187 251 251 187 210 208 158 177 172 135
-99 98 80 13 13 13 12 12 12 12 12 12 13 13 13 12 12 12
-12 12 12 12 12 12 11 11 11 11 11 11 8 9 9 4 5 5
-1 1 1 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
-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 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 0 0 0 0 0 0
-0 0 0
-0 0 0 0 0 0 1 1 0 61 61 53 142 137 94 181 176 137
-204 201 155 224 223 159 251 251 187 251 251 187 251 251 187 251 251 187
-251 251 187 214 212 158 197 193 154 190 186 136 184 181 136 188 184 146
-197 193 154 204 201 155 210 208 158 210 208 158 204 201 155 194 189 146
-176 171 126 134 131 96 66 65 55 43 45 43 41 42 42 39 40 39
-35 37 36 33 36 34 27 29 28 20 20 20 15 15 15 9 11 11
-8 9 9 6 7 7 5 6 5 5 6 5 4 5 5 4 5 5
-4 5 5 4 5 5 4 5 5 4 5 5 5 6 5 4 5 5
-4 5 5 5 6 5 4 5 5 5 6 5 5 6 5 5 6 5
-5 7 7 5 7 7 5 7 7 5 7 7 5 7 7 5 7 7
-6 7 7 6 7 7 6 7 7 28 31 30 184 179 149 184 179 149
-145 141 105 84 83 72 27 29 28 5 7 7 5 6 5 16 16 16
-43 44 41 96 95 69 158 153 112 188 184 146 204 201 155 210 208 158
-204 201 155 197 193 154 184 179 149 177 172 135 168 163 120 164 159 111
-164 159 111 174 170 121 184 181 136 197 193 154 214 212 158 251 251 187
-251 251 187 251 251 187 251 251 187 251 251 187 210 208 158 177 172 135
-71 71 57 11 11 11 12 12 12 11 11 11 11 11 11 11 11 11
-10 10 9 10 10 9 8 8 7 3 4 4 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 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 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 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 31 33 31 121 119 87 176 171 126
-197 193 154 214 212 158 251 251 187 251 251 187 251 251 187 251 251 187
-239 239 170 210 208 158 194 189 146 178 174 128 174 170 121 176 171 126
-177 172 135 181 176 137 184 179 149 184 179 149 181 176 137 178 174 128
-158 153 112 121 119 87 53 55 47 37 39 37 33 36 34 30 32 31
-27 29 28 25 27 26 24 26 24 19 20 19 13 13 13 8 10 10
-6 8 8 6 7 7 5 6 5 4 5 5 4 5 5 4 5 5
-4 5 5 4 5 5 4 5 5 3 4 4 3 4 4 4 5 5
-4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 4 5 5
-5 6 5 5 6 5 5 6 5 5 6 5 5 6 5 5 6 5
-5 6 5 5 6 5 12 14 14 145 141 105 184 179 149 177 172 135
-90 89 73 21 22 21 5 6 5 5 6 5 4 5 5 37 39 37
-38 39 37 61 61 53 134 131 96 168 163 120 184 181 136 188 184 146
-184 179 149 177 172 135 168 163 120 164 159 111 155 149 109 151 147 98
-151 147 98 164 159 111 176 171 126 184 179 149 210 208 158 239 239 170
-251 251 187 251 251 187 251 251 187 239 239 170 210 208 158 158 153 112
-46 47 43 10 10 9 10 10 9 10 10 9 8 9 9 8 9 9
-6 7 7 3 3 3 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 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
-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 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 13 12 7 82 81 62 158 153 112
-188 184 146 210 208 158 239 239 170 251 251 187 251 251 187 251 251 187
-224 223 159 204 201 155 184 181 136 171 165 117 164 159 111 160 154 106
-158 153 112 164 159 111 168 163 120 168 163 120 168 163 120 164 159 111
-142 137 94 96 95 69 43 44 41 27 29 28 26 28 27 23 24 24
-21 22 21 18 19 18 17 17 17 18 19 18 13 13 13 8 8 7
-6 7 7 5 6 5 4 5 5 3 4 4 3 4 4 3 4 4
-3 4 4 3 4 4 3 3 3 3 3 3 3 4 4 3 4 4
-3 4 4 3 4 4 4 5 5 4 5 5 4 5 5 4 5 5
-4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 4 5 5
-4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 4 5 5
-4 5 5 4 5 5 4 5 5 4 5 5 31 33 31 65 66 61
-37 39 37 38 39 37 96 95 69 144 139 99 168 163 120 174 170 121
-168 163 120 164 159 111 155 149 109 149 145 103 149 143 98 142 137 94
-149 143 98 151 147 98 164 159 111 177 172 135 197 193 154 210 208 158
-251 251 187 251 251 187 251 251 187 239 239 170 197 193 154 137 133 100
-24 26 24 8 9 9 8 9 9 8 8 7 6 7 7 2 2 2
-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 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 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 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 0 0 0 0 0 0 0 0 0 46 47 43 125 122 87
-176 171 126 197 193 154 210 208 158 239 239 170 251 251 187 239 239 170
-214 212 158 197 193 154 181 176 137 164 159 111 151 147 98 149 143 98
-149 143 98 149 143 98 149 145 103 155 149 109 160 154 106 149 143 98
-118 116 76 82 81 62 30 31 28 21 22 21 19 20 19 17 17 17
-14 14 13 12 12 12 10 10 9 12 12 12 10 12 12 6 8 8
-4 5 5 3 4 4 3 4 4 3 4 4 3 3 3 3 3 3
-3 3 3 3 3 3 3 3 3 3 3 3 2 3 3 2 3 3
-3 4 4 3 4 4 3 4 4 3 4 4 3 4 4 4 5 5
-4 5 5 3 4 4 3 4 4 3 4 4 3 4 4 3 4 4
-4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 4 5 5
-4 5 5 3 4 4 3 4 4 23 24 24 110 109 94 72 73 67
-39 40 39 22 24 23 46 47 43 103 101 77 142 137 94 155 149 109
-160 154 106 155 149 109 149 143 98 142 137 94 142 137 94 142 137 94
-142 137 94 149 143 98 155 149 109 176 171 126 184 179 149 210 208 158
-239 239 170 251 251 187 251 251 187 214 212 158 184 179 149 105 104 92
-10 10 9 6 7 7 3 4 4 1 1 1 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 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 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 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
-0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 12 12 9 82 81 62
-149 145 103 181 176 137 197 193 154 210 208 158 214 212 158 214 212 158
-210 208 158 197 193 154 177 172 135 158 153 112 149 143 98 142 137 94
-142 137 94 142 137 94 149 143 98 151 147 98 151 147 98 131 127 93
-103 101 77 71 71 57 22 24 23 15 15 15 13 13 13 11 11 11
-8 9 9 6 7 7 6 7 7 4 5 5 8 9 9 6 7 7
-4 5 5 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2
-2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3
-2 3 3 2 3 3 2 3 3 3 4 4 3 4 4 3 4 4
-3 4 4 3 4 4 3 3 3 3 4 4 3 4 4 3 4 4
-3 4 4 3 4 4 3 4 4 3 4 4 3 4 4 3 4 4
-3 4 4 3 4 4 21 22 21 145 141 105 145 141 105 72 73 67
-17 18 17 3 4 4 21 22 20 66 65 55 118 116 76 142 137 94
-149 143 98 151 147 98 149 143 98 142 137 94 142 137 94 142 137 94
-142 137 94 149 143 98 155 149 109 168 163 120 184 179 149 210 208 158
-239 239 170 251 251 187 251 251 187 210 208 158 177 172 135 71 71 57
-3 3 3 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
-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 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 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 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 36 38 35
-115 113 82 158 153 112 181 176 137 197 193 154 204 201 155 210 208 158
-204 201 155 188 184 146 177 172 135 164 159 111 149 145 103 142 137 94
-142 137 94 142 137 94 149 143 98 151 147 98 149 143 98 125 122 87
-96 95 69 61 61 53 16 17 12 8 9 9 8 8 7 6 7 7
-4 5 5 3 4 4 3 3 3 3 3 3 3 3 3 5 6 5
-3 4 4 2 3 3 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 1 2 2
-2 2 2 2 2 2 2 3 3 2 3 3 2 3 3 2 3 3
-3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
-3 3 3 2 3 3 2 3 3 3 4 4 3 4 4 3 4 4
-3 4 4 3 4 4 3 4 4 8 9 9 8 8 7 3 3 3
-3 3 3 3 3 3 9 9 8 36 38 35 82 81 62 118 116 76
-142 137 94 151 147 98 151 147 98 151 147 98 149 143 98 149 143 98
-149 143 98 151 147 98 160 154 106 176 171 126 188 184 146 210 208 158
-239 239 170 251 251 187 239 239 170 210 208 158 156 151 111 31 33 31
-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 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 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 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 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 7 7 5
-66 65 55 125 122 87 158 153 112 181 176 137 194 189 146 197 193 154
-197 193 154 184 179 149 177 172 135 168 163 120 156 151 111 151 147 98
-151 147 98 151 147 98 151 147 98 161 156 96 149 143 98 118 116 76
-82 81 62 53 55 47 12 12 9 4 5 5 3 4 4 3 3 3
-3 3 3 3 3 3 2 2 2 2 2 2 1 1 1 1 2 2
-3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
-1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 1 2 2
-1 2 2 1 2 2 1 2 2 2 2 2 2 2 2 2 3 3
-2 3 3 2 3 3 2 3 3 2 3 3 2 2 2 2 2 2
-2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 2 3 3
-2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 3 3 3
-3 3 3 3 3 3 72 73 67 61 61 53 53 55 47 96 95 69
-131 127 93 151 147 98 161 156 96 161 156 96 151 147 98 151 147 98
-161 156 96 160 154 106 164 159 111 177 172 135 197 193 154 210 208 158
-239 239 170 251 251 187 224 223 159 197 193 154 131 127 93 9 9 8
-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 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 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 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 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
-24 26 24 82 81 62 131 127 93 164 159 111 178 174 128 188 184 146
-188 184 146 188 184 146 181 176 137 176 171 126 168 163 120 164 159 111
-160 154 106 160 154 106 160 154 106 160 154 106 151 147 98 125 122 87
-82 81 62 61 61 53 12 12 9 3 3 3 3 3 3 2 2 2
-2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0
-0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 2 2 1 2 2 1 2 2 1 2 2
-1 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 3 3 2 3 3 2 3 3 2 3 3 2 3 3 2 3 3
-2 3 3 30 32 31 72 73 67 31 33 31 36 38 35 82 81 62
-118 116 76 149 143 98 161 156 96 161 156 96 161 156 96 160 154 106
-165 161 109 165 161 109 176 171 126 188 184 146 204 201 155 214 212 158
-239 239 170 239 239 170 214 212 158 184 179 149 82 81 62 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 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 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 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 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 0 0 0
-2 2 2 43 44 41 96 95 69 131 127 93 160 154 106 176 171 126
-184 181 136 184 181 136 184 181 136 181 176 137 178 174 128 174 170 121
-171 165 117 173 167 111 173 167 111 173 167 111 160 154 106 131 127 93
-96 95 69 66 65 55 16 17 12 2 2 2 1 1 1 1 1 1
-1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 2 2 1 2 2 1 2 2 1 2 2 1 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 10 9 6 30 31 28 71 71 57
-118 116 76 149 143 98 165 161 109 165 161 109 165 161 109 173 167 111
-173 167 111 176 171 126 184 181 136 197 193 154 210 208 158 224 223 159
-251 251 187 239 239 170 210 208 158 168 163 120 40 41 39 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 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 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 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 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 0 0 0
-0 0 0 13 12 7 61 61 53 96 95 69 131 127 93 160 154 106
-176 171 126 184 181 136 184 181 136 188 184 146 184 181 136 184 181 136
-184 181 136 186 182 128 186 182 128 178 174 128 174 170 121 149 145 103
-118 116 76 82 81 62 21 22 20 1 1 1 1 1 1 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 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2
-1 2 2 1 2 2 1 2 2 1 2 2 1 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 3 3 3 30 31 28 66 65 55
-118 116 76 149 143 98 165 161 109 173 167 111 173 167 111 174 170 121
-186 182 128 190 186 136 197 193 154 210 208 158 224 223 159 251 251 187
-251 251 187 239 239 170 197 193 154 137 133 100 12 12 9 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 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 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 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 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 0 0 0
-0 0 0 0 0 0 30 31 28 71 71 57 103 101 77 134 131 96
-164 159 111 176 171 126 184 181 136 188 184 146 194 189 146 197 193 154
-197 193 154 197 193 154 194 191 148 194 189 146 190 186 136 176 171 126
-145 141 105 103 101 77 40 41 39 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 0 0 0 0 0 0 0 0 0 0 0 0
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 1 2 2
-1 2 2 1 2 2 1 2 2 1 2 2 1 2 2 1 2 2
-1 2 2 1 2 2 1 2 2 1 2 2 30 31 28 71 71 57
-118 116 76 160 154 106 173 167 111 178 174 128 186 182 128 190 186 136
-194 191 148 204 201 155 210 208 158 224 223 159 251 251 187 251 251 187
-251 251 187 214 212 158 184 179 149 84 83 72 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 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 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 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
-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 0 0 0 0 0 0
-0 0 0 0 0 0 5 5 3 43 44 41 82 81 62 103 101 77
-142 137 94 165 161 109 178 174 128 190 186 136 197 193 154 204 201 155
-210 208 158 210 208 158 210 208 158 210 208 158 210 208 158 197 193 154
-177 172 135 145 141 105 79 78 62 5 4 3 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 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 2 2 1 2 2 30 31 28 82 81 62
-142 137 94 165 161 109 178 174 128 190 186 136 194 191 148 204 201 155
-210 208 158 214 212 158 239 239 170 251 251 187 251 251 187 251 251 187
-251 251 187 210 208 158 168 163 120 36 38 35 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 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 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 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
-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 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 16 17 12 53 55 47 82 81 62
-118 116 76 151 147 98 171 165 117 184 181 136 194 191 148 210 208 158
-214 212 158 224 223 159 239 239 170 239 239 170 224 223 159 214 212 158
-197 193 154 176 171 126 115 113 82 24 26 24 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 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 40 41 39 103 101 77
-151 147 98 176 171 126 190 186 136 197 193 154 210 208 158 214 212 158
-239 239 170 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187
-239 239 170 197 193 154 110 109 94 3 4 3 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 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 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 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
-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 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 30 31 28 66 65 55
-96 95 69 125 122 87 160 154 106 178 174 128 194 189 146 204 201 155
-214 212 158 239 239 170 251 251 187 251 251 187 251 251 187 239 239 170
-210 208 158 188 184 146 149 145 103 61 61 53 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 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 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 61 61 53 131 127 93
-164 159 111 184 181 136 197 193 154 210 208 158 224 223 159 251 251 187
-251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187
-210 208 158 168 163 120 43 44 41 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 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 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
-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 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 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 4 3 2 36 38 35
-71 71 57 96 95 69 142 137 94 165 161 109 184 181 136 197 193 154
-210 208 158 239 239 170 251 251 187 251 251 187 251 251 187 251 251 187
-214 212 158 197 193 154 168 163 120 103 101 77 7 7 5 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 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 0 0 0 0 0 0 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 0 0 0 0 0 0 0 0 0 82 81 62 142 137 94
-174 170 121 194 189 146 210 208 158 224 223 159 251 251 187 251 251 187
-251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 224 223 159
-184 179 149 99 98 80 3 3 3 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 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 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
-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 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 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 7 5
-43 44 41 82 81 62 118 116 76 142 137 94 171 165 117 190 186 136
-204 201 155 224 223 159 251 251 187 251 251 187 251 251 187 251 251 187
-214 212 158 197 193 154 174 170 121 125 122 87 30 31 28 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 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 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-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 3 4 3 82 81 62 149 143 98
-176 171 126 194 191 148 210 208 158 239 239 170 251 251 187 251 251 187
-251 251 187 251 251 187 251 251 187 251 251 187 239 239 170 204 201 155
-145 141 105 30 31 28 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 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
-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 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 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 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
-10 9 6 46 47 43 82 81 62 118 116 76 149 143 98 174 170 121
-194 189 146 210 208 158 224 223 159 251 251 187 251 251 187 224 223 159
-210 208 158 194 191 148 174 170 121 134 131 96 53 55 47 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 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 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 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 0 0 0 0 0 0 7 7 5 96 95 69 149 143 98
-176 171 126 194 191 148 210 208 158 239 239 170 251 251 187 251 251 187
-251 251 187 251 251 187 251 251 187 239 239 170 210 208 158 177 172 135
-75 75 61 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
-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 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 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 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 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
-0 0 0 10 9 6 46 47 43 82 81 62 118 116 76 149 143 98
-176 171 126 194 191 148 210 208 158 214 212 158 214 212 158 210 208 158
-197 193 154 184 181 136 164 159 111 131 127 93 53 55 47 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 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 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 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 0 0 0 0 0 0 7 7 5 96 95 69 149 143 98
-174 170 121 194 189 146 204 201 155 214 212 158 239 239 170 251 251 187
-251 251 187 251 251 187 239 239 170 210 208 158 184 179 149 110 109 94
-12 12 9 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
-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 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 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 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 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
-0 0 0 0 0 0 10 9 6 43 44 41 82 81 62 115 113 82
-144 139 99 168 163 120 188 184 146 197 193 154 197 193 154 194 189 146
-184 181 136 174 170 121 151 147 98 118 116 76 36 38 35 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 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 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 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 0 0 0 0 0 0 4 3 2 82 81 62 142 137 94
-171 165 117 186 182 128 194 191 148 210 208 158 214 212 158 224 223 159
-239 239 170 224 223 159 210 208 158 184 179 149 137 133 100 36 38 35
-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 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 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 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 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
-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 0 0 0
-0 0 0 0 0 0 0 0 0 7 7 5 36 38 35 71 71 57
-103 101 77 131 127 93 155 149 109 168 163 120 168 163 120 168 163 120
-164 159 111 149 143 98 125 122 87 82 81 62 13 12 7 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 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 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 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 0 0 0 0 0 0 0 0 0 61 61 53 125 122 87
-160 154 106 174 170 121 184 181 136 194 189 146 204 201 155 210 208 158
-210 208 158 204 201 155 184 179 149 145 141 105 61 61 53 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 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 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 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 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
-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 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 3 3 2 30 31 28
-61 61 53 82 81 62 103 101 77 121 119 87 125 122 87 125 122 87
-118 116 76 103 101 77 79 78 62 24 26 24 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 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 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 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
-0 0 0 0 0 0 0 0 0 0 0 0 25 27 25 96 95 69
-142 137 94 160 154 106 171 165 117 178 174 128 184 181 136 184 181 136
-181 176 137 177 172 135 145 141 105 75 75 61 5 5 3 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 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 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 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 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
-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 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-16 17 12 40 41 39 61 61 53 71 71 57 71 71 57 71 71 57
-66 65 55 43 44 41 12 12 9 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 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 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
-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 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 46 47 43
-96 95 69 125 122 87 142 137 94 149 145 103 155 149 109 155 149 109
-145 141 105 121 119 87 66 65 55 7 7 5 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 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 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 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
-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 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 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 1 1 1 16 17 12 24 26 24 25 27 25 19 20 18
-7 7 5 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
-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 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 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 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1
-25 27 25 61 61 53 82 81 62 96 95 69 96 95 69 82 81 62
-61 61 53 25 27 25 2 2 1 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 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 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
-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 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 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 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 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
-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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 5 6 5 13 12 7 10 9 6 3 4 3
-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 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 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 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 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 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 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 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 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 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 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
-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 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 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 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 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 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
-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 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 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 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 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
+ 6 6 6 6 6 6 10 10 10 10 10 10
+ 10 10 10 6 6 6 6 6 6 6 6 6
+ 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 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 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 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
+ 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 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 0 0 0 0 0 0
+ 0 0 0 6 6 6 10 10 10 14 14 14
+ 22 22 22 26 26 26 30 30 30 34 34 34
+ 30 30 30 30 30 30 26 26 26 18 18 18
+ 14 14 14 10 10 10 6 6 6 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 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 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
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 1 0 0 1 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 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 0 0 0 0 0 0 0 0 0
+ 6 6 6 14 14 14 26 26 26 42 42 42
+ 54 54 54 66 66 66 78 78 78 78 78 78
+ 78 78 78 74 74 74 66 66 66 54 54 54
+ 42 42 42 26 26 26 18 18 18 10 10 10
+ 6 6 6 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
+ 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 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 0 0 0 0 0 0
+ 0 0 1 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
+ 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 0 0 0
+ 0 0 0 0 0 0 0 0 0 10 10 10
+ 22 22 22 42 42 42 66 66 66 86 86 86
+ 66 66 66 38 38 38 38 38 38 22 22 22
+ 26 26 26 34 34 34 54 54 54 66 66 66
+ 86 86 86 70 70 70 46 46 46 26 26 26
+ 14 14 14 6 6 6 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 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
+ 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 0 0 0
+ 0 0 1 0 0 1 0 0 1 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 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 0 0 0 10 10 10 26 26 26
+ 50 50 50 82 82 82 58 58 58 6 6 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 6 6 6 54 54 54 86 86 86 66 66 66
+ 38 38 38 18 18 18 6 6 6 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 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 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
+ 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 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 0 0 0 0 0 0
+ 0 0 0 6 6 6 22 22 22 50 50 50
+ 78 78 78 34 34 34 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 6 6 6 70 70 70
+ 78 78 78 46 46 46 22 22 22 6 6 6
+ 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 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 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 1 0 0 1 0 0 1 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 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
+ 6 6 6 18 18 18 42 42 42 82 82 82
+ 26 26 26 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 14 14 14
+ 46 46 46 34 34 34 6 6 6 2 2 6
+ 42 42 42 78 78 78 42 42 42 18 18 18
+ 6 6 6 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
+ 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 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 1 0 0 0 0 0 1 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 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
+ 10 10 10 30 30 30 66 66 66 58 58 58
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 26 26 26
+ 86 86 86 101 101 101 46 46 46 10 10 10
+ 2 2 6 58 58 58 70 70 70 34 34 34
+ 10 10 10 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
+ 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 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 1 0 0 1 0 0 1 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 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
+ 14 14 14 42 42 42 86 86 86 10 10 10
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 30 30 30
+ 94 94 94 94 94 94 58 58 58 26 26 26
+ 2 2 6 6 6 6 78 78 78 54 54 54
+ 22 22 22 6 6 6 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 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
+ 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 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 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 6 6 6
+ 22 22 22 62 62 62 62 62 62 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 26 26 26
+ 54 54 54 38 38 38 18 18 18 10 10 10
+ 2 2 6 2 2 6 34 34 34 82 82 82
+ 38 38 38 14 14 14 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 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
+ 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 1 0 0 1 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 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 6 6 6
+ 30 30 30 78 78 78 30 30 30 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 10 10 10
+ 10 10 10 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 78 78 78
+ 50 50 50 18 18 18 6 6 6 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 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 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 1 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
+ 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 10 10 10
+ 38 38 38 86 86 86 14 14 14 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 54 54 54
+ 66 66 66 26 26 26 6 6 6 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 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 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 1 0 0 1 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 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 14 14 14
+ 42 42 42 82 82 82 2 2 6 2 2 6
+ 2 2 6 6 6 6 10 10 10 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 6 6 6
+ 14 14 14 10 10 10 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 18 18 18
+ 82 82 82 34 34 34 10 10 10 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 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 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 1 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
+ 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 14 14 14
+ 46 46 46 86 86 86 2 2 6 2 2 6
+ 6 6 6 6 6 6 22 22 22 34 34 34
+ 6 6 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 18 18 18 34 34 34
+ 10 10 10 50 50 50 22 22 22 2 2 6
+ 2 2 6 2 2 6 2 2 6 10 10 10
+ 86 86 86 42 42 42 14 14 14 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 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 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 1 0 0 1 0 0 1 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 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 14 14 14
+ 46 46 46 86 86 86 2 2 6 2 2 6
+ 38 38 38 116 116 116 94 94 94 22 22 22
+ 22 22 22 2 2 6 2 2 6 2 2 6
+ 14 14 14 86 86 86 138 138 138 162 162 162
+154 154 154 38 38 38 26 26 26 6 6 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 86 86 86 46 46 46 14 14 14 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 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 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
+ 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 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 14 14 14
+ 46 46 46 86 86 86 2 2 6 14 14 14
+134 134 134 198 198 198 195 195 195 116 116 116
+ 10 10 10 2 2 6 2 2 6 6 6 6
+101 98 89 187 187 187 210 210 210 218 218 218
+214 214 214 134 134 134 14 14 14 6 6 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 86 86 86 50 50 50 18 18 18 6 6 6
+ 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 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 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 1 0 0 0
+ 0 0 1 0 0 1 0 0 1 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 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 14 14 14
+ 46 46 46 86 86 86 2 2 6 54 54 54
+218 218 218 195 195 195 226 226 226 246 246 246
+ 58 58 58 2 2 6 2 2 6 30 30 30
+210 210 210 253 253 253 174 174 174 123 123 123
+221 221 221 234 234 234 74 74 74 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 70 70 70 58 58 58 22 22 22 6 6 6
+ 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 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 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 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
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 14 14 14
+ 46 46 46 82 82 82 2 2 6 106 106 106
+170 170 170 26 26 26 86 86 86 226 226 226
+123 123 123 10 10 10 14 14 14 46 46 46
+231 231 231 190 190 190 6 6 6 70 70 70
+ 90 90 90 238 238 238 158 158 158 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 70 70 70 58 58 58 22 22 22 6 6 6
+ 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 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 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 1 0 0 0
+ 0 0 1 0 0 1 0 0 1 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 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 14 14 14
+ 42 42 42 86 86 86 6 6 6 116 116 116
+106 106 106 6 6 6 70 70 70 149 149 149
+128 128 128 18 18 18 38 38 38 54 54 54
+221 221 221 106 106 106 2 2 6 14 14 14
+ 46 46 46 190 190 190 198 198 198 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 74 74 74 62 62 62 22 22 22 6 6 6
+ 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 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 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 1 0 0 0
+ 0 0 1 0 0 0 0 0 1 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 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 14 14 14
+ 42 42 42 94 94 94 14 14 14 101 101 101
+128 128 128 2 2 6 18 18 18 116 116 116
+118 98 46 121 92 8 121 92 8 98 78 10
+162 162 162 106 106 106 2 2 6 2 2 6
+ 2 2 6 195 195 195 195 195 195 6 6 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 74 74 74 62 62 62 22 22 22 6 6 6
+ 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 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 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 1 0 0 1
+ 0 0 1 0 0 0 0 0 1 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 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 10 10 10
+ 38 38 38 90 90 90 14 14 14 58 58 58
+210 210 210 26 26 26 54 38 6 154 114 10
+226 170 11 236 186 11 225 175 15 184 144 12
+215 174 15 175 146 61 37 26 9 2 2 6
+ 70 70 70 246 246 246 138 138 138 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 70 70 70 66 66 66 26 26 26 6 6 6
+ 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 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 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 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
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 10 10 10
+ 38 38 38 86 86 86 14 14 14 10 10 10
+195 195 195 188 164 115 192 133 9 225 175 15
+239 182 13 234 190 10 232 195 16 232 200 30
+245 207 45 241 208 19 232 195 16 184 144 12
+218 194 134 211 206 186 42 42 42 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 50 50 50 74 74 74 30 30 30 6 6 6
+ 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 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 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 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
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 10 10 10
+ 34 34 34 86 86 86 14 14 14 2 2 6
+121 87 25 192 133 9 219 162 10 239 182 13
+236 186 11 232 195 16 241 208 19 244 214 54
+246 218 60 246 218 38 246 215 20 241 208 19
+241 208 19 226 184 13 121 87 25 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 50 50 50 82 82 82 34 34 34 10 10 10
+ 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 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 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 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
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 10 10 10
+ 34 34 34 82 82 82 30 30 30 61 42 6
+180 123 7 206 145 10 230 174 11 239 182 13
+234 190 10 238 202 15 241 208 19 246 218 74
+246 218 38 246 215 20 246 215 20 246 215 20
+226 184 13 215 174 15 184 144 12 6 6 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 26 26 26 94 94 94 42 42 42 14 14 14
+ 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 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 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 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
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 10 10 10
+ 30 30 30 78 78 78 50 50 50 104 69 6
+192 133 9 216 158 10 236 178 12 236 186 11
+232 195 16 241 208 19 244 214 54 245 215 43
+246 215 20 246 215 20 241 208 19 198 155 10
+200 144 11 216 158 10 156 118 10 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 6 6 6 90 90 90 54 54 54 18 18 18
+ 6 6 6 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
+ 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 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 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 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 10 10 10
+ 30 30 30 78 78 78 46 46 46 22 22 22
+137 92 6 210 162 10 239 182 13 238 190 10
+238 202 15 241 208 19 246 215 20 246 215 20
+241 208 19 203 166 17 185 133 11 210 150 10
+216 158 10 210 150 10 102 78 10 2 2 6
+ 6 6 6 54 54 54 14 14 14 2 2 6
+ 2 2 6 62 62 62 74 74 74 30 30 30
+ 10 10 10 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
+ 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 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 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 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 10 10 10
+ 34 34 34 78 78 78 50 50 50 6 6 6
+ 94 70 30 139 102 15 190 146 13 226 184 13
+232 200 30 232 195 16 215 174 15 190 146 13
+168 122 10 192 133 9 210 150 10 213 154 11
+202 150 34 182 157 106 101 98 89 2 2 6
+ 2 2 6 78 78 78 116 116 116 58 58 58
+ 2 2 6 22 22 22 90 90 90 46 46 46
+ 18 18 18 6 6 6 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 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
+ 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 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 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 10 10 10
+ 38 38 38 86 86 86 50 50 50 6 6 6
+128 128 128 174 154 114 156 107 11 168 122 10
+198 155 10 184 144 12 197 138 11 200 144 11
+206 145 10 206 145 10 197 138 11 188 164 115
+195 195 195 198 198 198 174 174 174 14 14 14
+ 2 2 6 22 22 22 116 116 116 116 116 116
+ 22 22 22 2 2 6 74 74 74 70 70 70
+ 30 30 30 10 10 10 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 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
+ 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 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 0 0 0 0 0 0
+ 0 0 0 0 0 0 6 6 6 18 18 18
+ 50 50 50 101 101 101 26 26 26 10 10 10
+138 138 138 190 190 190 174 154 114 156 107 11
+197 138 11 200 144 11 197 138 11 192 133 9
+180 123 7 190 142 34 190 178 144 187 187 187
+202 202 202 221 221 221 214 214 214 66 66 66
+ 2 2 6 2 2 6 50 50 50 62 62 62
+ 6 6 6 2 2 6 10 10 10 90 90 90
+ 50 50 50 18 18 18 6 6 6 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 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 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
+ 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 0 0 0
+ 0 0 0 0 0 0 10 10 10 34 34 34
+ 74 74 74 74 74 74 2 2 6 6 6 6
+144 144 144 198 198 198 190 190 190 178 166 146
+154 121 60 156 107 11 156 107 11 168 124 44
+174 154 114 187 187 187 190 190 190 210 210 210
+246 246 246 253 253 253 253 253 253 182 182 182
+ 6 6 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 62 62 62
+ 74 74 74 34 34 34 14 14 14 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 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 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
+ 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 0 0 0
+ 0 0 0 10 10 10 22 22 22 54 54 54
+ 94 94 94 18 18 18 2 2 6 46 46 46
+234 234 234 221 221 221 190 190 190 190 190 190
+190 190 190 187 187 187 187 187 187 190 190 190
+190 190 190 195 195 195 214 214 214 242 242 242
+253 253 253 253 253 253 253 253 253 253 253 253
+ 82 82 82 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 14 14 14
+ 86 86 86 54 54 54 22 22 22 6 6 6
+ 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 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 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 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
+ 6 6 6 18 18 18 46 46 46 90 90 90
+ 46 46 46 18 18 18 6 6 6 182 182 182
+253 253 253 246 246 246 206 206 206 190 190 190
+190 190 190 190 190 190 190 190 190 190 190 190
+206 206 206 231 231 231 250 250 250 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+202 202 202 14 14 14 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 42 42 42 86 86 86 42 42 42 18 18 18
+ 6 6 6 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
+ 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 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 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 6 6 6
+ 14 14 14 38 38 38 74 74 74 66 66 66
+ 2 2 6 6 6 6 90 90 90 250 250 250
+253 253 253 253 253 253 238 238 238 198 198 198
+190 190 190 190 190 190 195 195 195 221 221 221
+246 246 246 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 82 82 82 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 78 78 78 70 70 70 34 34 34
+ 14 14 14 6 6 6 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 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
+ 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 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 14 14 14
+ 34 34 34 66 66 66 78 78 78 6 6 6
+ 2 2 6 18 18 18 218 218 218 253 253 253
+253 253 253 253 253 253 253 253 253 246 246 246
+226 226 226 231 231 231 246 246 246 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 178 178 178 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 18 18 18 90 90 90 62 62 62
+ 30 30 30 10 10 10 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 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
+ 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 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 10 10 10 26 26 26
+ 58 58 58 90 90 90 18 18 18 2 2 6
+ 2 2 6 110 110 110 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+250 250 250 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 231 231 231 18 18 18 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 18 18 18 94 94 94
+ 54 54 54 26 26 26 10 10 10 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 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 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
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 6 6 6 22 22 22 50 50 50
+ 90 90 90 26 26 26 2 2 6 2 2 6
+ 14 14 14 195 195 195 250 250 250 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+250 250 250 242 242 242 54 54 54 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 38 38 38
+ 86 86 86 50 50 50 22 22 22 6 6 6
+ 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 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 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 0 0 0 0 0 0 0 0 0
+ 6 6 6 14 14 14 38 38 38 82 82 82
+ 34 34 34 2 2 6 2 2 6 2 2 6
+ 42 42 42 195 195 195 246 246 246 253 253 253
+253 253 253 253 253 253 253 253 253 250 250 250
+242 242 242 242 242 242 250 250 250 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 250 250 250 246 246 246 238 238 238
+226 226 226 231 231 231 101 101 101 6 6 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 38 38 38 82 82 82 42 42 42 14 14 14
+ 6 6 6 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
+ 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 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 0 0 0 0 0 0
+ 10 10 10 26 26 26 62 62 62 66 66 66
+ 2 2 6 2 2 6 2 2 6 6 6 6
+ 70 70 70 170 170 170 206 206 206 234 234 234
+246 246 246 250 250 250 250 250 250 238 238 238
+226 226 226 231 231 231 238 238 238 250 250 250
+250 250 250 250 250 250 246 246 246 231 231 231
+214 214 214 206 206 206 202 202 202 202 202 202
+198 198 198 202 202 202 182 182 182 18 18 18
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 62 62 62 66 66 66 30 30 30
+ 10 10 10 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
+ 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 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 0 0 0 0 0 0
+ 14 14 14 42 42 42 82 82 82 18 18 18
+ 2 2 6 2 2 6 2 2 6 10 10 10
+ 94 94 94 182 182 182 218 218 218 242 242 242
+250 250 250 253 253 253 253 253 253 250 250 250
+234 234 234 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 246 246 246
+238 238 238 226 226 226 210 210 210 202 202 202
+195 195 195 195 195 195 210 210 210 158 158 158
+ 6 6 6 14 14 14 50 50 50 14 14 14
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 6 6 6 86 86 86 46 46 46
+ 18 18 18 6 6 6 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 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
+ 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 6 6 6
+ 22 22 22 54 54 54 70 70 70 2 2 6
+ 2 2 6 10 10 10 2 2 6 22 22 22
+166 166 166 231 231 231 250 250 250 253 253 253
+253 253 253 253 253 253 253 253 253 250 250 250
+242 242 242 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 246 246 246
+231 231 231 206 206 206 198 198 198 226 226 226
+ 94 94 94 2 2 6 6 6 6 38 38 38
+ 30 30 30 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 62 62 62 66 66 66
+ 26 26 26 10 10 10 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 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
+ 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 10 10 10
+ 30 30 30 74 74 74 50 50 50 2 2 6
+ 26 26 26 26 26 26 2 2 6 106 106 106
+238 238 238 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 246 246 246 218 218 218 202 202 202
+210 210 210 14 14 14 2 2 6 2 2 6
+ 30 30 30 22 22 22 2 2 6 2 2 6
+ 2 2 6 2 2 6 18 18 18 86 86 86
+ 42 42 42 14 14 14 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 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
+ 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 14 14 14
+ 42 42 42 90 90 90 22 22 22 2 2 6
+ 42 42 42 2 2 6 18 18 18 218 218 218
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 250 250 250 221 221 221
+218 218 218 101 101 101 2 2 6 14 14 14
+ 18 18 18 38 38 38 10 10 10 2 2 6
+ 2 2 6 2 2 6 2 2 6 78 78 78
+ 58 58 58 22 22 22 6 6 6 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 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 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 6 6 6 18 18 18
+ 54 54 54 82 82 82 2 2 6 26 26 26
+ 22 22 22 2 2 6 123 123 123 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 250 250 250
+238 238 238 198 198 198 6 6 6 38 38 38
+ 58 58 58 26 26 26 38 38 38 2 2 6
+ 2 2 6 2 2 6 2 2 6 46 46 46
+ 78 78 78 30 30 30 10 10 10 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 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 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 10 10 10 30 30 30
+ 74 74 74 58 58 58 2 2 6 42 42 42
+ 2 2 6 22 22 22 231 231 231 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 250 250 250
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 246 246 246 46 46 46 38 38 38
+ 42 42 42 14 14 14 38 38 38 14 14 14
+ 2 2 6 2 2 6 2 2 6 6 6 6
+ 86 86 86 46 46 46 14 14 14 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 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 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 6 6 6 14 14 14 42 42 42
+ 90 90 90 18 18 18 18 18 18 26 26 26
+ 2 2 6 116 116 116 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 250 250 250 238 238 238
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 94 94 94 6 6 6
+ 2 2 6 2 2 6 10 10 10 34 34 34
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 74 74 74 58 58 58 22 22 22 6 6 6
+ 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 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 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 10 10 10 26 26 26 66 66 66
+ 82 82 82 2 2 6 38 38 38 6 6 6
+ 14 14 14 210 210 210 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 246 246 246 242 242 242
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 144 144 144 2 2 6
+ 2 2 6 2 2 6 2 2 6 46 46 46
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 42 42 42 74 74 74 30 30 30 10 10 10
+ 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 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 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 6 6 6 14 14 14 42 42 42 90 90 90
+ 26 26 26 6 6 6 42 42 42 2 2 6
+ 74 74 74 250 250 250 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 242 242 242 242 242 242
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 182 182 182 2 2 6
+ 2 2 6 2 2 6 2 2 6 46 46 46
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 10 10 10 86 86 86 38 38 38 10 10 10
+ 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 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 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 10 10 10 26 26 26 66 66 66 82 82 82
+ 2 2 6 22 22 22 18 18 18 2 2 6
+149 149 149 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 234 234 234 242 242 242
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 206 206 206 2 2 6
+ 2 2 6 2 2 6 2 2 6 38 38 38
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 6 6 6 86 86 86 46 46 46 14 14 14
+ 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 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 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 6 6 6
+ 18 18 18 46 46 46 86 86 86 18 18 18
+ 2 2 6 34 34 34 10 10 10 6 6 6
+210 210 210 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 234 234 234 242 242 242
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 221 221 221 6 6 6
+ 2 2 6 2 2 6 6 6 6 30 30 30
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 82 82 82 54 54 54 18 18 18
+ 6 6 6 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
+ 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 0 0 0
+ 0 0 0 0 0 0 0 0 0 10 10 10
+ 26 26 26 66 66 66 62 62 62 2 2 6
+ 2 2 6 38 38 38 10 10 10 26 26 26
+238 238 238 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 231 231 231 238 238 238
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 231 231 231 6 6 6
+ 2 2 6 2 2 6 10 10 10 30 30 30
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 66 66 66 58 58 58 22 22 22
+ 6 6 6 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
+ 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 0 0 0
+ 0 0 0 0 0 0 0 0 0 10 10 10
+ 38 38 38 78 78 78 6 6 6 2 2 6
+ 2 2 6 46 46 46 14 14 14 42 42 42
+246 246 246 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 231 231 231 242 242 242
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 234 234 234 10 10 10
+ 2 2 6 2 2 6 22 22 22 14 14 14
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 66 66 66 62 62 62 22 22 22
+ 6 6 6 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
+ 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 0 0 0
+ 0 0 0 0 0 0 6 6 6 18 18 18
+ 50 50 50 74 74 74 2 2 6 2 2 6
+ 14 14 14 70 70 70 34 34 34 62 62 62
+250 250 250 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 231 231 231 246 246 246
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 234 234 234 14 14 14
+ 2 2 6 2 2 6 30 30 30 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 66 66 66 62 62 62 22 22 22
+ 6 6 6 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
+ 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 0 0 0
+ 0 0 0 0 0 0 6 6 6 18 18 18
+ 54 54 54 62 62 62 2 2 6 2 2 6
+ 2 2 6 30 30 30 46 46 46 70 70 70
+250 250 250 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 231 231 231 246 246 246
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 226 226 226 10 10 10
+ 2 2 6 6 6 6 30 30 30 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 66 66 66 58 58 58 22 22 22
+ 6 6 6 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
+ 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 0 0 0
+ 0 0 0 0 0 0 6 6 6 22 22 22
+ 58 58 58 62 62 62 2 2 6 2 2 6
+ 2 2 6 2 2 6 30 30 30 78 78 78
+250 250 250 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 231 231 231 246 246 246
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 206 206 206 2 2 6
+ 22 22 22 34 34 34 18 14 6 22 22 22
+ 26 26 26 18 18 18 6 6 6 2 2 6
+ 2 2 6 82 82 82 54 54 54 18 18 18
+ 6 6 6 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
+ 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 0 0 0
+ 0 0 0 0 0 0 6 6 6 26 26 26
+ 62 62 62 106 106 106 74 54 14 185 133 11
+210 162 10 121 92 8 6 6 6 62 62 62
+238 238 238 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 231 231 231 246 246 246
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 158 158 158 18 18 18
+ 14 14 14 2 2 6 2 2 6 2 2 6
+ 6 6 6 18 18 18 66 66 66 38 38 38
+ 6 6 6 94 94 94 50 50 50 18 18 18
+ 6 6 6 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
+ 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 6 6 6
+ 10 10 10 10 10 10 18 18 18 38 38 38
+ 78 78 78 142 134 106 216 158 10 242 186 14
+246 190 14 246 190 14 156 118 10 10 10 10
+ 90 90 90 238 238 238 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 231 231 231 250 250 250
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 246 230 190
+238 204 91 238 204 91 181 142 44 37 26 9
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 38 38 38 46 46 46
+ 26 26 26 106 106 106 54 54 54 18 18 18
+ 6 6 6 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
+ 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 6 6 6 14 14 14 22 22 22
+ 30 30 30 38 38 38 50 50 50 70 70 70
+106 106 106 190 142 34 226 170 11 242 186 14
+246 190 14 246 190 14 246 190 14 154 114 10
+ 6 6 6 74 74 74 226 226 226 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 231 231 231 250 250 250
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 228 184 62
+241 196 14 241 208 19 232 195 16 38 30 10
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 6 6 6 30 30 30 26 26 26
+203 166 17 154 142 90 66 66 66 26 26 26
+ 6 6 6 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
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 6 6 6 18 18 18 38 38 38 58 58 58
+ 78 78 78 86 86 86 101 101 101 123 123 123
+175 146 61 210 150 10 234 174 13 246 186 14
+246 190 14 246 190 14 246 190 14 238 190 10
+102 78 10 2 2 6 46 46 46 198 198 198
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 234 234 234 242 242 242
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 224 178 62
+242 186 14 241 196 14 210 166 10 22 18 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 6 6 6 121 92 8
+238 202 15 232 195 16 82 82 82 34 34 34
+ 10 10 10 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
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 14 14 14 38 38 38 70 70 70 154 122 46
+190 142 34 200 144 11 197 138 11 197 138 11
+213 154 11 226 170 11 242 186 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+225 175 15 46 32 6 2 2 6 22 22 22
+158 158 158 250 250 250 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 250 250 250 242 242 242 224 178 62
+239 182 13 236 186 11 213 154 11 46 32 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 61 42 6 225 175 15
+238 190 10 236 186 11 112 100 78 42 42 42
+ 14 14 14 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
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 6 6 6
+ 22 22 22 54 54 54 154 122 46 213 154 11
+226 170 11 230 174 11 226 170 11 226 170 11
+236 178 12 242 186 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+241 196 14 184 144 12 10 10 10 2 2 6
+ 6 6 6 116 116 116 242 242 242 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 231 231 231 198 198 198 214 170 54
+236 178 12 236 178 12 210 150 10 137 92 6
+ 18 14 6 2 2 6 2 2 6 2 2 6
+ 6 6 6 70 47 6 200 144 11 236 178 12
+239 182 13 239 182 13 124 112 88 58 58 58
+ 22 22 22 6 6 6 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 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 10 10 10
+ 30 30 30 70 70 70 180 133 36 226 170 11
+239 182 13 242 186 14 242 186 14 246 186 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 232 195 16 98 70 6 2 2 6
+ 2 2 6 2 2 6 66 66 66 221 221 221
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 206 206 206 198 198 198 214 166 58
+230 174 11 230 174 11 216 158 10 192 133 9
+163 110 8 116 81 8 102 78 10 116 81 8
+167 114 7 197 138 11 226 170 11 239 182 13
+242 186 14 242 186 14 162 146 94 78 78 78
+ 34 34 34 14 14 14 6 6 6 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 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 6 6 6
+ 30 30 30 78 78 78 190 142 34 226 170 11
+239 182 13 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 241 196 14 203 166 17 22 18 6
+ 2 2 6 2 2 6 2 2 6 38 38 38
+218 218 218 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+250 250 250 206 206 206 198 198 198 202 162 69
+226 170 11 236 178 12 224 166 10 210 150 10
+200 144 11 197 138 11 192 133 9 197 138 11
+210 150 10 226 170 11 242 186 14 246 190 14
+246 190 14 246 186 14 225 175 15 124 112 88
+ 62 62 62 30 30 30 14 14 14 6 6 6
+ 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 0 0 0
+ 0 0 0 0 0 0 0 0 0 10 10 10
+ 30 30 30 78 78 78 174 135 50 224 166 10
+239 182 13 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 241 196 14 139 102 15
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 78 78 78 250 250 250 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+250 250 250 214 214 214 198 198 198 190 150 46
+219 162 10 236 178 12 234 174 13 224 166 10
+216 158 10 213 154 11 213 154 11 216 158 10
+226 170 11 239 182 13 246 190 14 246 190 14
+246 190 14 246 190 14 242 186 14 206 162 42
+101 101 101 58 58 58 30 30 30 14 14 14
+ 6 6 6 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
+ 0 0 0 0 0 0 0 0 0 10 10 10
+ 30 30 30 74 74 74 174 135 50 216 158 10
+236 178 12 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 241 196 14 226 184 13
+ 61 42 6 2 2 6 2 2 6 2 2 6
+ 22 22 22 238 238 238 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 226 226 226 187 187 187 180 133 36
+216 158 10 236 178 12 239 182 13 236 178 12
+230 174 11 226 170 11 226 170 11 230 174 11
+236 178 12 242 186 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 186 14 239 182 13
+206 162 42 106 106 106 66 66 66 34 34 34
+ 14 14 14 6 6 6 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 0 0 0 0 0 0 6 6 6
+ 26 26 26 70 70 70 163 133 67 213 154 11
+236 178 12 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 241 196 14
+190 146 13 18 14 6 2 2 6 2 2 6
+ 46 46 46 246 246 246 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 221 221 221 86 86 86 156 107 11
+216 158 10 236 178 12 242 186 14 246 186 14
+242 186 14 239 182 13 239 182 13 242 186 14
+242 186 14 246 186 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+242 186 14 225 175 15 142 122 72 66 66 66
+ 30 30 30 10 10 10 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 0 0 0 0 0 0 6 6 6
+ 26 26 26 70 70 70 163 133 67 210 150 10
+236 178 12 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+232 195 16 121 92 8 34 34 34 106 106 106
+221 221 221 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+242 242 242 82 82 82 18 14 6 163 110 8
+216 158 10 236 178 12 242 186 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 242 186 14 163 133 67
+ 46 46 46 18 18 18 6 6 6 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 0 0 0 10 10 10
+ 30 30 30 78 78 78 163 133 67 210 150 10
+236 178 12 246 186 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+241 196 14 215 174 15 190 178 144 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 218 218 218
+ 58 58 58 2 2 6 22 18 6 167 114 7
+216 158 10 236 178 12 246 186 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 186 14 242 186 14 190 150 46
+ 54 54 54 22 22 22 6 6 6 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 0 0 0 14 14 14
+ 38 38 38 86 86 86 180 133 36 213 154 11
+236 178 12 246 186 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 232 195 16 190 146 13 214 214 214
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 250 250 250 170 170 170 26 26 26
+ 2 2 6 2 2 6 37 26 9 163 110 8
+219 162 10 239 182 13 246 186 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 186 14 236 178 12 224 166 10 142 122 72
+ 46 46 46 18 18 18 6 6 6 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 6 6 6 18 18 18
+ 50 50 50 109 106 95 192 133 9 224 166 10
+242 186 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+242 186 14 226 184 13 210 162 10 142 110 46
+226 226 226 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253
+198 198 198 66 66 66 2 2 6 2 2 6
+ 2 2 6 2 2 6 50 34 6 156 107 11
+219 162 10 239 182 13 246 186 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 242 186 14
+234 174 13 213 154 11 154 122 46 66 66 66
+ 30 30 30 10 10 10 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 0 0 0 6 6 6 22 22 22
+ 58 58 58 154 121 60 206 145 10 234 174 13
+242 186 14 246 186 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 186 14 236 178 12 210 162 10 163 110 8
+ 61 42 6 138 138 138 218 218 218 250 250 250
+253 253 253 253 253 253 253 253 253 250 250 250
+242 242 242 210 210 210 144 144 144 66 66 66
+ 6 6 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 61 42 6 163 110 8
+216 158 10 236 178 12 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 239 182 13 230 174 11 216 158 10
+190 142 34 124 112 88 70 70 70 38 38 38
+ 18 18 18 6 6 6 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 0 0 0 6 6 6 22 22 22
+ 62 62 62 168 124 44 206 145 10 224 166 10
+236 178 12 239 182 13 242 186 14 242 186 14
+246 186 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 236 178 12 216 158 10 175 118 6
+ 80 54 7 2 2 6 6 6 6 30 30 30
+ 54 54 54 62 62 62 50 50 50 38 38 38
+ 14 14 14 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 6 6 6 80 54 7 167 114 7
+213 154 11 236 178 12 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 242 186 14 239 182 13 239 182 13
+230 174 11 210 150 10 174 135 50 124 112 88
+ 82 82 82 54 54 54 34 34 34 18 18 18
+ 6 6 6 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
+ 0 0 0 0 0 0 6 6 6 18 18 18
+ 50 50 50 158 118 36 192 133 9 200 144 11
+216 158 10 219 162 10 224 166 10 226 170 11
+230 174 11 236 178 12 239 182 13 239 182 13
+242 186 14 246 186 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14
+246 186 14 230 174 11 210 150 10 163 110 8
+104 69 6 10 10 10 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 6 6 6 91 60 6 167 114 7
+206 145 10 230 174 11 242 186 14 246 190 14
+246 190 14 246 190 14 246 186 14 242 186 14
+239 182 13 230 174 11 224 166 10 213 154 11
+180 133 36 124 112 88 86 86 86 58 58 58
+ 38 38 38 22 22 22 10 10 10 6 6 6
+ 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 0 0 0
+ 0 0 0 0 0 0 0 0 0 14 14 14
+ 34 34 34 70 70 70 138 110 50 158 118 36
+167 114 7 180 123 7 192 133 9 197 138 11
+200 144 11 206 145 10 213 154 11 219 162 10
+224 166 10 230 174 11 239 182 13 242 186 14
+246 186 14 246 186 14 246 186 14 246 186 14
+239 182 13 216 158 10 185 133 11 152 99 6
+104 69 6 18 14 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 2 2 6 2 2 6 2 2 6
+ 2 2 6 6 6 6 80 54 7 152 99 6
+192 133 9 219 162 10 236 178 12 239 182 13
+246 186 14 242 186 14 239 182 13 236 178 12
+224 166 10 206 145 10 192 133 9 154 121 60
+ 94 94 94 62 62 62 42 42 42 22 22 22
+ 14 14 14 6 6 6 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 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 6 6 6
+ 18 18 18 34 34 34 58 58 58 78 78 78
+101 98 89 124 112 88 142 110 46 156 107 11
+163 110 8 167 114 7 175 118 6 180 123 7
+185 133 11 197 138 11 210 150 10 219 162 10
+226 170 11 236 178 12 236 178 12 234 174 13
+219 162 10 197 138 11 163 110 8 130 83 6
+ 91 60 6 10 10 10 2 2 6 2 2 6
+ 18 18 18 38 38 38 38 38 38 38 38 38
+ 38 38 38 38 38 38 38 38 38 38 38 38
+ 38 38 38 38 38 38 26 26 26 2 2 6
+ 2 2 6 6 6 6 70 47 6 137 92 6
+175 118 6 200 144 11 219 162 10 230 174 11
+234 174 13 230 174 11 219 162 10 210 150 10
+192 133 9 163 110 8 124 112 88 82 82 82
+ 50 50 50 30 30 30 14 14 14 6 6 6
+ 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 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
+ 6 6 6 14 14 14 22 22 22 34 34 34
+ 42 42 42 58 58 58 74 74 74 86 86 86
+101 98 89 122 102 70 130 98 46 121 87 25
+137 92 6 152 99 6 163 110 8 180 123 7
+185 133 11 197 138 11 206 145 10 200 144 11
+180 123 7 156 107 11 130 83 6 104 69 6
+ 50 34 6 54 54 54 110 110 110 101 98 89
+ 86 86 86 82 82 82 78 78 78 78 78 78
+ 78 78 78 78 78 78 78 78 78 78 78 78
+ 78 78 78 82 82 82 86 86 86 94 94 94
+106 106 106 101 101 101 86 66 34 124 80 6
+156 107 11 180 123 7 192 133 9 200 144 11
+206 145 10 200 144 11 192 133 9 175 118 6
+139 102 15 109 106 95 70 70 70 42 42 42
+ 22 22 22 10 10 10 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 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
+ 0 0 0 0 0 0 6 6 6 10 10 10
+ 14 14 14 22 22 22 30 30 30 38 38 38
+ 50 50 50 62 62 62 74 74 74 90 90 90
+101 98 89 112 100 78 121 87 25 124 80 6
+137 92 6 152 99 6 152 99 6 152 99 6
+138 86 6 124 80 6 98 70 6 86 66 30
+101 98 89 82 82 82 58 58 58 46 46 46
+ 38 38 38 34 34 34 34 34 34 34 34 34
+ 34 34 34 34 34 34 34 34 34 34 34 34
+ 34 34 34 34 34 34 38 38 38 42 42 42
+ 54 54 54 82 82 82 94 86 76 91 60 6
+134 86 6 156 107 11 167 114 7 175 118 6
+175 118 6 167 114 7 152 99 6 121 87 25
+101 98 89 62 62 62 34 34 34 18 18 18
+ 6 6 6 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
+ 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 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 6 6 6 6 6 6 10 10 10
+ 18 18 18 22 22 22 30 30 30 42 42 42
+ 50 50 50 66 66 66 86 86 86 101 98 89
+106 86 58 98 70 6 104 69 6 104 69 6
+104 69 6 91 60 6 82 62 34 90 90 90
+ 62 62 62 38 38 38 22 22 22 14 14 14
+ 10 10 10 10 10 10 10 10 10 10 10 10
+ 10 10 10 10 10 10 6 6 6 10 10 10
+ 10 10 10 10 10 10 10 10 10 14 14 14
+ 22 22 22 42 42 42 70 70 70 89 81 66
+ 80 54 7 104 69 6 124 80 6 137 92 6
+134 86 6 116 81 8 100 82 52 86 86 86
+ 58 58 58 30 30 30 14 14 14 6 6 6
+ 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 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 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 6 6 6 10 10 10 14 14 14
+ 18 18 18 26 26 26 38 38 38 54 54 54
+ 70 70 70 86 86 86 94 86 76 89 81 66
+ 89 81 66 86 86 86 74 74 74 50 50 50
+ 30 30 30 14 14 14 6 6 6 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 0 0 0 0 0 0
+ 6 6 6 18 18 18 34 34 34 58 58 58
+ 82 82 82 89 81 66 89 81 66 89 81 66
+ 94 86 66 94 86 76 74 74 74 50 50 50
+ 26 26 26 14 14 14 6 6 6 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 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 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
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 6 6 6 6 6 6 14 14 14 18 18 18
+ 30 30 30 38 38 38 46 46 46 54 54 54
+ 50 50 50 42 42 42 30 30 30 18 18 18
+ 10 10 10 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
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 6 6 6 14 14 14 26 26 26
+ 38 38 38 50 50 50 58 58 58 58 58 58
+ 54 54 54 42 42 42 30 30 30 18 18 18
+ 10 10 10 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
+ 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 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 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 6 6 6
+ 6 6 6 10 10 10 14 14 14 18 18 18
+ 18 18 18 14 14 14 10 10 10 6 6 6
+ 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 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 6 6 6
+ 14 14 14 18 18 18 22 22 22 22 22 22
+ 18 18 18 14 14 14 10 10 10 6 6 6
+ 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 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
diff --git a/drivers/video/logo/logo_linux_vga16.ppm b/drivers/video/logo/logo_linux_vga16.ppm
index 12ac3a5454c0..1850c15e6feb 100644
--- a/drivers/video/logo/logo_linux_vga16.ppm
+++ b/drivers/video/logo/logo_linux_vga16.ppm
@@ -1,2739 +1,1604 @@
P3
-142 114
+# Standard 16-color Linux logo
+80 80
255
-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 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 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 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 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 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
-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 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 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 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 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 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
-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 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
-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 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 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 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 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 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
-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 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 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 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 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 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 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 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
-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 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 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 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 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 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
-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 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 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 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 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 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 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 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
-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 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 85 85 85 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 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 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
-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 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 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 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 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 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 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 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
-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 85 85 85 85 85 85 85 85 85
-85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 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 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 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 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 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
-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 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 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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 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 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 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
-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 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 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 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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0
-85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-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 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 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 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 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 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
-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 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
-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 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 85 85 85 0 0 0
-85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85
-0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 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 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 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
-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 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 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 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 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 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 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 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85
-85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 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 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
-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 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 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 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 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 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 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 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
-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 85 85 85 170 170 170
-85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85
-0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 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 85 85 85 85 85 85 85 85 85
-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 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 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 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 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 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 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 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
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85
-85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 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 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 85 85 85 170 170 170 170 85 0 170 170 170 85 85 85
-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 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 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 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 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 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 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 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
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 85 85 85
-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 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 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 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 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 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 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 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
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170
-255 255 85 170 170 170 170 170 170 170 85 0 85 255 85 170 85 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 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 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 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 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 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 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 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 0
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 170 170 170 170 85 0
-170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 85 85 85
-0 0 0 85 85 85 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 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
-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 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 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 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 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 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 0 0 0 85 85 85 85 85 85 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 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 85 85 85 85 85 85 170 85 0 170 170 170
-170 170 170 170 85 0 170 170 170 170 170 170 170 85 0 85 85 85
-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 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 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 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 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 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 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 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
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85
-85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 255 85
-255 85 85 85 255 85 170 170 170 170 85 0 170 170 170 85 85 85
-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 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 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 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 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 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 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 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
-0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85
-85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 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 85 85 85 170 85 0 85 85 85 85 85 85
-170 170 170 170 85 0 170 170 170 85 85 85 170 85 0 85 85 85
-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 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 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 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 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 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 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 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
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 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 85 85 85 85 85 85 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 85 85 85 170 85 0
-85 85 85 85 85 85 170 85 0 85 255 85 85 85 85 85 85 85
-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 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 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 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 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 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 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 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
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85
-0 0 0 85 85 85 85 85 85 85 85 85 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 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 170 85 0 0 0 0
-0 0 0 85 85 85 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 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
-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 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 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 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 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 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 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85
-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 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 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 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 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 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
-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 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
-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 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 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 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 0 0 0 0 0 0 0 0 0 85 85 85
-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 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 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 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 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 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 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 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
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 0 170 0 85 85 85 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 85 85 85 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 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 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
-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 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 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 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 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 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-170 85 0 85 255 85 170 85 0 170 85 0 170 85 0 85 255 85
-170 85 0 170 85 0 0 170 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 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
-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 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 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 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 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 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 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 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 170 0 170 85 0
-255 255 85 170 85 0 255 255 85 255 255 85 255 255 85 170 85 0
-255 255 85 85 255 85 170 85 0 170 85 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-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 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 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 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 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 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 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 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
-0 0 0 0 0 0 0 0 0 0 0 0 170 85 0 255 255 85
-85 255 85 255 255 85 255 255 85 170 85 0 255 255 85 255 255 85
-255 255 85 170 85 0 255 255 85 85 255 85 170 85 0 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-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 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 85 85 85 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 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 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 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
-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 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
-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 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 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 255 255 85 170 85 0
-255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 170 85 0
-255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 85 255 85
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 0 0 0
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 85 85 85 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 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 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 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
-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 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
-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 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 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 170 85 0 255 255 85 255 255 85
-255 255 85 255 255 85 170 85 0 255 255 85 85 255 85 255 255 85
-255 255 85 170 85 0 255 255 85 170 85 0 255 255 85 170 85 0
-170 85 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 170 170 170 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 85 85 85 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 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
-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 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 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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 170 85 0 255 255 85 85 255 85 255 255 85
-170 170 170 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85
-255 255 85 255 255 85 85 255 85 255 255 85 255 255 85 255 255 85
-85 255 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85
-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 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 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 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 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 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
-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 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
-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 0 0 0
-0 0 0 0 0 0 170 85 0 255 255 85 255 255 85 255 255 85
-255 255 255 255 255 85 255 255 85 170 85 0 255 255 85 170 85 0
-255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 255 255 85
-170 85 0 170 85 0 0 170 0 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-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 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 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 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 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 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 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 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
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 170 85 0 85 255 85 255 255 85 170 170 170 255 255 255
-255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85
-255 255 85 255 255 85 170 85 0 255 255 85 85 255 85 255 255 85
-255 255 85 85 255 85 0 0 0 85 85 85 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 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 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 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
-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 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 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 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 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 0 0 0 0 0 0 0 0 0
-0 0 0 255 255 85 255 255 85 255 255 85 255 255 255 255 255 85
-255 255 85 255 255 85 85 255 85 255 255 85 255 255 85 85 255 85
-255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 170 85 0
-255 255 85 170 85 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85
-85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 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
-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 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 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 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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-170 85 0 170 85 0 255 255 85 255 255 85 255 255 255 170 170 170
-255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85
-170 85 0 255 255 85 255 255 85 170 85 0 255 255 85 255 255 85
-255 255 85 85 255 85 170 85 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85
-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 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 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 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 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 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 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 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
-255 255 85 85 255 85 255 255 85 170 170 170 255 255 255 255 255 85
-255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 255 255 85
-255 255 85 255 255 85 255 255 85 255 255 85 85 255 85 170 85 0
-255 255 85 170 85 0 170 85 0 0 0 0 85 85 85 0 0 0
-85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 170 170 170
-85 255 85 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170
-170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170
-170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170
-170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170
-85 85 85 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
-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 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 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 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 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 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 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 170 0
-170 85 0 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85
-255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85
-255 255 85 255 255 85 85 255 85 255 255 85 170 85 0 170 85 0
-170 85 0 85 255 85 255 255 85 85 85 85 170 170 170 170 170 170
-170 170 170 170 170 170 170 170 170 85 255 85 170 170 170 170 170 170
-85 85 85 170 170 170 170 170 170 170 85 0 170 170 170 170 170 170
-85 255 85 170 170 170 170 85 0 170 170 170 85 255 85 255 85 85
-85 255 85 170 170 170 255 255 85 85 85 85 255 255 85 170 170 170
-85 255 85 170 170 170 255 255 85 170 170 170 170 170 170 85 85 85
-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 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 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 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 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 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 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 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 255 255 85
-255 255 85 255 255 85 255 255 85 255 255 255 255 255 85 255 255 85
-255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 170 85 0
-255 255 85 255 255 85 255 255 85 170 85 0 0 170 0 85 85 85
-170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 85 255 85
-255 85 85 85 255 85 85 85 85 255 85 85 85 85 85 170 170 170
-170 85 0 170 170 170 85 85 85 85 255 85 85 85 85 85 85 85
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-170 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 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 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 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 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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 85
-170 85 0 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85
-255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85
-255 255 85 255 255 85 170 85 0 255 255 85 85 85 85 85 85 85
-255 255 85 170 170 170 85 85 85 85 85 85 0 0 0 85 85 85
-0 0 0 85 85 85 85 85 85 170 170 170 170 85 0 170 170 170
-170 170 170 255 255 85 170 170 170 85 85 85 85 85 85 85 85 85
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 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
-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 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 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 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 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 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 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 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 170 85 0 255 255 85
-255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85
-255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85
-255 255 85 255 255 85 255 255 85 170 85 0 170 85 0 0 170 0
-0 0 0 170 85 0 170 85 0 0 170 0 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 85 85 85 170 170 170 85 85 85
-170 170 170 85 85 85 85 85 85 170 170 170 170 85 0 85 85 85
-85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-85 85 85 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
-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 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 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 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 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 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 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 0 0 0 0 0 0 0 0 0 255 255 85 170 85 0
-255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 170 85 0
-255 255 85 255 255 85 255 255 85 170 85 0 255 255 85 255 255 85
-170 85 0 255 255 85 85 255 85 255 255 85 255 255 85 170 85 0
-170 85 0 255 255 85 170 85 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 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 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 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 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 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
-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 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
-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 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 255 255 85 255 255 85
-255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 255 255 85
-255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85
-255 255 85 255 255 85 255 255 85 170 85 0 255 255 85 255 255 85
-85 255 85 170 85 0 0 170 0 85 85 85 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 85 85 85 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 85 85 85 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 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
-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 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 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 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 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 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 0 0 0 0 170 0 170 85 0 255 255 85
-85 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85
-255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85
-170 85 0 255 255 85 85 255 85 255 255 85 255 255 85 170 85 0
-85 255 85 170 85 0 170 85 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 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 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 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 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 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
-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 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
-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 170 85 0 255 255 85 255 255 85
-255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85
-255 255 85 170 85 0 255 255 85 85 255 85 255 255 85 170 85 0
-255 255 85 255 255 85 170 85 0 255 255 85 170 85 0 85 255 85
-170 85 0 170 85 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 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
-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 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 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 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 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 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 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 0 0 0 0 0 0 85 85 85 255 255 85 170 85 0
-255 255 85 170 85 0 255 255 85 170 85 0 255 255 85 85 255 85
-255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85
-255 255 85 170 85 0 255 255 85 85 255 85 170 85 0 170 85 0
-0 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85
-85 85 85 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
-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 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 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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 170 85 0 255 255 85 255 255 85
-255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85
-255 255 85 255 255 85 170 85 0 255 255 85 170 85 0 85 255 85
-255 255 85 85 255 85 170 85 0 170 85 0 85 255 85 170 85 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85
-85 85 85 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
-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 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 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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 255 255 85 85 255 85
-255 255 85 255 255 85 85 255 85 255 255 85 255 255 85 255 255 85
-255 255 85 170 85 0 255 255 85 85 255 85 255 255 85 255 255 85
-170 85 0 170 85 0 85 255 85 170 85 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 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 85 85 85 170 170 170 170 170 170 170 170 170
-170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 85 85 85
-85 85 85 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
-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 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 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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 255 255 85 255 255 85
-170 85 0 255 255 85 255 255 85 170 85 0 255 255 85 170 85 0
-255 255 85 85 255 85 170 85 0 255 255 85 170 85 0 85 255 85
-170 85 0 170 85 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 170 170 170 170 170 170 170 170 170 170 170 170
-170 170 170 170 170 170 170 170 170 85 85 85 85 85 85 85 85 85
-85 85 85 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
-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 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 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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 170 85 0 255 255 85
-255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 85 255 85
-170 85 0 255 255 85 170 85 0 85 255 85 170 85 0 170 85 0
-0 170 0 0 0 0 0 0 0 0 0 0 85 85 85 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 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 170 170 170 170 170 170 255 255 255 170 170 170
-170 170 170 170 170 170 85 85 85 85 85 85 85 85 85 85 85 85
-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 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 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 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 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 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 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 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 85 255 85 255 255 85
-170 85 0 255 255 85 255 255 85 170 85 0 85 255 85 170 85 0
-255 255 85 170 85 0 0 170 0 170 85 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 170 170 170 170 170 170 170 170 170 85 85 85
-85 85 85 85 85 85 85 85 85 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 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 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
-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 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 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 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 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 0 0 0 0 0 0 255 255 85
-255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 170 85 0
-0 170 0 85 85 85 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-85 85 85 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
-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 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 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 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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-255 255 85 255 255 85 170 85 0 0 170 0 85 85 85 85 85 85
-85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0
-85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 85 85 85
-170 170 170 170 170 170 170 170 170 170 170 170 85 85 85 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 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
-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 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 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 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 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 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 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 170 85 0 85 85 85 0 0 0 0 0 0 0 0 0
-85 85 85 85 85 85 85 85 85 85 85 85 170 170 170 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85
-170 170 170 170 170 170 170 170 170 170 170 170 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 170 170 170
-170 170 170 170 170 170 170 170 170 85 85 85 85 85 85 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 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 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
-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 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 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 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 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 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 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 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 170 170 170 170 170 170
-255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 170 170 170
-255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 170 170 170 255 255 255 170 170 170 85 85 85
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 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 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 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 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 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
-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 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
-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 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 170 170 170 170 170 170
-255 255 255 170 170 170 255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 170 170 170
-255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 85 85 85
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 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 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 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 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
-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 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
-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 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 0 0 0 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 170 170 170
-170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170
-255 255 255 170 170 170 255 255 255 170 170 170 255 255 255 255 255 255
-255 255 255 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170
-170 170 170 170 170 170 170 170 170 170 170 170 85 85 85 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 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 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 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
-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 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 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 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 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 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85
-85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 170 170 170
-170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170
-170 170 170 170 170 170 170 170 170 170 170 170 85 85 85 170 170 170
-170 170 170 170 170 170 85 85 85 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-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 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 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 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 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 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 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 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 85 85 85 85 85 85
-170 170 170 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85
-0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0
-85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 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 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 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
-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 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 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 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 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 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 85 85 85
-85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 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 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 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 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
-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 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
-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 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 85 85 85 85 85 85 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0
-0 0 0 85 85 85 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 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-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 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 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 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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 85 85 85 170 170 170 85 85 85
-85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 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 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 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
-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 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
-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 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 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 85 85 85 85 85 85 85 85 85 85 85 85
-85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 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 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 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
-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 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 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 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 85 85 85
-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 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 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 85 85 85 85 85 85 170 170 170 85 85 85 85 85 85
-85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 170 170 170 170 170 170
-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 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 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 85 85 85 170 170 170 85 85 85 85 85 85 85 85 85
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 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 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 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
-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 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 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 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
-85 85 85 170 170 170 255 255 255 170 170 170
-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 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 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 85 85 85 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 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
-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 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 0 0 0 170 170 170
-170 170 170 255 255 255 170 170 170 170 170 170
-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 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 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 170 170 170 85 85 85 85 85 85 85 85 85 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 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 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 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 85 85 85 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 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
-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 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 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 170 170 170
-255 255 255 255 255 255 170 170 170 170 170 170
-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 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 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 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
-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 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 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 85 85 85 170 170 170 170 170 170 255 255 255
-255 255 255 170 170 170 170 170 170 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 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 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-170 170 170 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 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
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 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 85 85 85 0 0 0 0 0 0 85 85 85 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 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 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 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 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
-0 0 0 85 85 85 170 170 170 255 255 255 255 255 255 255 255 255
-170 170 170 170 170 170 85 85 85 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 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 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 170 170 170
-170 170 170 170 170 170 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 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 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 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 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 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 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 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 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
-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 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 170 170 170
-170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170
-170 170 170 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 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85
-85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 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 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 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 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
-0 0 0 0 0 0 85 85 85 170 170 170 170 170 170 170 170 170
-255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170
-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 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
-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 85 85 85 85 85 85 85 85 85
-85 85 85 85 85 85 85 85 85 85 85 85 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 85 85 85 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 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 85 85 85 85 85 85 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 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 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
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 170 170 170 170 170 170 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 170 170 170 170 170 170 85 85 85 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
-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 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85
-85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 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 85 85 85 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 170 170 170 255 255 255 85 85 85 85 85 85
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-85 85 85 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0
-85 85 85 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
-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 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 0 0 0 85 85 85
-170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 255 255 255
-255 255 255 255 255 255 170 170 170 170 170 170 85 85 85 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
-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 0 0 0
-85 85 85 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85
-85 85 85 85 85 85 0 0 0 85 85 85 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 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 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 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 85 85 85 170 170 170 255 255 255 170 170 170 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85
-255 255 255 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 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 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 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 85 85 85 85 85 85
-255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
-170 170 170 170 170 170 85 85 85 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 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 0 0 0 0 0 0 0 0 0
-85 85 85 255 255 255 170 170 170 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 0 0 0
-85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 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 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 85 85 85 255 255 255 255 255 255 255 255 255 85 85 85
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 170 170 170
-255 255 255 170 170 170 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 170 170 170 85 85 85 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 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 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 170 170 170
-170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 170 170 170
-170 170 170 170 170 170 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 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-170 170 170 255 255 255 255 255 255 170 170 170 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 0 0 0
-85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-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 85 85 85 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 85 85 85 0 0 0 85 85 85
-85 85 85 170 170 170 255 255 255 255 255 255 255 255 255 85 85 85
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 255 255 255
-255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 170 170 170 170 170 170 85 85 85 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 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 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85
-170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170
-85 85 85 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 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 170 170 170
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-170 170 170 255 255 255 255 255 255 255 255 255 85 85 85 0 0 0
-0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0
-85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85
-0 0 0 85 85 85 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 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-85 85 85 170 170 170 255 255 255 255 255 255 255 255 255 170 170 170
-0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 255 255 255
-255 255 255 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0
-85 85 85 255 255 255 255 255 255 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 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 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85
-0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85
-170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 85 85 85
-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 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 170 170 170 255 255 255
-170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 255 255 255 255 255 255 255 255 255 255 255 255 0 0 0
-0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 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 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 85 85 85
-0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85
-85 85 85 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170
-85 85 85 0 0 0 0 0 0 85 85 85 170 170 170 255 255 255
-255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0
-170 170 170 255 255 255 170 170 170 0 0 0 0 0 0 0 0 0
-85 85 85 170 170 170 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0
-85 85 85 85 85 85 170 170 170 85 85 85 85 85 85 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
-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 85 85 85 170 170 170
-255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 170 170 170 255 255 255 255 255 255 255 255 255 170 170 170
-0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0
-85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 85 85 85 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 85 85 85
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 255 255 255
-170 170 170 170 170 170 0 0 0 0 0 0 0 0 0 85 85 85
-170 170 170 255 255 255 255 255 255 0 0 0 0 0 0 85 85 85
-255 255 255 85 85 85 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 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85
-85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 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 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 255 255 255
-255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 0 0 0
-85 85 85 170 170 170 255 255 255 170 170 170 170 170 170 170 170 170
-85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 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 0 0 0 85 85 85
-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 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85
-85 85 85 170 170 170 255 255 255 170 170 170 170 170 170 85 85 85
-85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 170 170 170
-170 170 170 85 85 85 85 85 85 0 0 0 0 0 0 85 85 85
-170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 170 170 170
-170 170 170 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
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 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
-0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 170 170 170
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 170 170 170
-255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0
-0 0 0 85 85 85 170 170 170 170 170 170 255 255 85 85 85 85
-85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0
-85 85 85 85 85 85 0 0 0 85 85 85 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 85 85 85 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 85 85 85 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
-85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 85 85 85
-85 85 85 170 170 170 170 170 170 170 170 170 170 85 0 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 170 85 0
-170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-170 85 0 170 170 170 85 85 85 0 0 0 85 85 85 85 85 85
-170 170 170 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 85 85 85
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 85 85 85 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 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 0 0 0 170 170 170 255 255 255
-170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0
-0 0 0 85 85 85 170 85 0 170 170 170 170 170 170 85 85 85
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85
-85 85 85 170 85 0 85 255 85 170 85 0 170 170 170 85 85 85
-85 85 85 0 0 0 0 0 0 85 85 85 170 85 0 85 255 85
-170 85 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85
-85 85 85 85 85 85 170 85 0 0 0 0 85 85 85 85 85 85
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 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 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 85 85 85 255 255 255
-255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0
-170 170 170 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 170 170 170 170 85 0 170 170 170 170 85 0
-85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 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
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 0 0 0
-85 85 85 85 85 85 255 85 85 170 170 170 85 255 85 170 85 0
-85 85 85 85 85 85 170 85 0 85 85 85 170 170 170 85 85 85
-170 170 170 170 85 0 85 85 85 85 85 85 85 85 85 85 85 85
-170 85 0 85 255 85 85 85 85 85 85 85 85 85 85 170 85 0
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 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 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
-85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 170 170 170
-255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 170 85 0 170 170 170 170 85 0 85 85 85 0 0 0
-85 85 85 85 85 85 85 255 85 170 170 170 170 170 170 170 85 0
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85
-0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85
-85 85 85 85 85 85 85 255 85 255 85 85 170 170 170 170 170 170
-170 170 170 85 255 85 170 170 170 170 85 0 170 170 170 170 85 0
-170 170 170 85 85 85 85 255 85 170 85 0 170 170 170 170 85 0
-170 170 170 170 170 170 170 85 0 85 85 85 85 85 85 85 255 85
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 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 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 0 0 0
-0 0 0 170 170 170 170 170 170 0 0 0 0 0 0 85 85 85
-170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0
-85 85 85 85 85 85 255 255 85 85 85 85 85 85 85 85 85 85
-85 255 85 255 85 85 170 170 170 170 85 0 170 170 170 85 255 85
-85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 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 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 0 0 0
-85 85 85 85 85 85 170 85 0 170 170 170 170 170 170 255 255 85
-170 170 170 255 85 85 170 170 170 170 170 170 255 255 85 170 170 170
-85 255 85 170 170 170 255 85 85 170 170 170 170 170 170 170 170 170
-170 170 170 170 170 170 170 170 170 170 85 0 170 170 170 170 85 0
-85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 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 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 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 85 85 85 170 170 170 85 85 85 0 0 0 85 85 85
-85 85 85 170 85 0 85 85 85 0 0 0 85 85 85 85 85 85
-85 85 85 170 85 0 170 170 170 170 170 170 255 255 85 170 170 170
-170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 255 85 85
-85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-85 85 85 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
-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 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 85 85 85
-85 85 85 85 85 85 170 170 170 255 255 85 170 170 170 170 170 170
-170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 170 85 0
-170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 255 255 85
-170 170 170 255 255 85 170 170 170 170 170 170 85 255 85 170 85 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 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 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 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 170 170 170 85 85 85 85 85 85 0 0 0
-85 85 85 85 85 85 170 170 170 85 85 85 170 170 170 170 85 0
-170 170 170 85 255 85 170 170 170 170 85 0 170 170 170 170 170 170
-255 255 85 170 170 170 170 170 170 255 255 255 255 255 85 170 170 170
-255 255 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 170 85 0 170 170 170 170 170 170 170 170 170 255 255 255
-170 170 170 255 255 255 255 255 85 170 170 170 255 255 85 170 170 170
-255 255 85 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170
-170 170 170 170 170 170 170 170 170 255 85 85 170 170 170 170 170 170
-85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 85 85 85 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 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 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 85 85 85 85 85 85 170 85 0 85 85 85
-85 85 85 255 255 85 170 170 170 170 170 170 170 170 170 170 170 170
-255 255 85 170 170 170 170 170 170 255 255 85 170 170 170 170 170 170
-170 170 170 255 255 255 255 255 255 170 170 170 255 255 255 170 170 170
-170 170 170 85 85 85 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 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 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 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0
-0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85
-85 85 85 85 255 85 170 170 170 255 255 85 255 255 255 255 255 255
-255 255 255 170 170 170 255 255 255 170 170 170 170 170 170 170 170 170
-170 170 170 170 170 170 255 255 85 170 170 170 255 255 85 255 255 255
-255 255 85 255 255 255 255 255 85 170 170 170 170 170 170 170 85 0
-170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 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 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 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 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85
-85 85 85 170 170 170 255 255 85 170 170 170 255 255 85 170 170 170
-170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 255 255 85
-255 255 255 255 255 255 255 255 85 255 255 255 255 255 255 170 170 170
-255 255 85 85 85 85 85 85 85 0 0 0 0 0 0 85 85 85
-85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-85 85 85 170 170 170 170 170 170 0 0 0 0 0 0 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 170 170 170 170 170 170 170 170 170 255 255 255 170 170 170
-255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 255 255 85
-170 170 170 255 255 85 170 170 170 255 255 255 170 170 170 255 255 255
-255 255 255 255 255 255 170 170 170 255 255 85 170 170 170 255 255 85
-85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 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 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
-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 0 0 0 0 0 0 85 85 85 170 85 0 170 170 170
-255 255 85 170 170 170 170 170 170 255 255 255 255 255 255 255 255 255
-170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 170 170 170
-255 255 255 170 170 170 255 255 255 255 255 255 170 170 170 255 255 255
-170 170 170 170 170 170 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 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 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0
-85 85 85 170 85 0 255 255 255 170 170 170 255 255 255 255 255 255
-255 255 85 255 255 255 170 170 170 255 255 85 170 170 170 170 170 170
-170 170 170 170 170 170 170 170 170 255 255 85 255 255 255 255 255 255
-170 170 170 255 255 255 255 255 255 170 170 170 170 170 170 170 170 170
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 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 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
-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 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 85 255 85 170 170 170
-170 170 170 255 255 85 170 170 170 255 255 255 170 170 170 255 255 255
-255 255 255 255 255 255 255 255 85 170 170 170 170 170 170 255 255 255
-170 170 170 255 255 255 255 255 255 170 170 170 255 255 255 255 255 85
-170 170 170 170 85 0 85 85 85 0 0 0 0 0 0 85 85 85
-0 0 0 85 85 85 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 0 0 0 0 0 0 0 0 0 85 85 85 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 0 0 0 0 0 0
-85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85
-85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 170 170 170 170 170 170 255 255 85 170 170 170 255 255 255
-255 255 255 170 170 170 255 255 255 170 170 170 170 170 170 255 255 85
-170 170 170 255 255 85 170 170 170 255 255 255 170 170 170 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 255 255 85
-85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-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 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 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 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 170 170 170
-170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
-170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170
-255 255 85 255 255 255 170 170 170 255 255 255 170 170 170 170 170 170
-170 170 170 170 170 170 85 85 85 0 0 0 85 85 85 85 85 85
-0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 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
-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 85 85 85 85 85 85
-85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-85 85 85 85 85 85 170 170 170 170 170 170 255 255 255 170 170 170
-255 255 255 170 170 170 255 255 85 170 170 170 170 170 170 170 170 170
-255 85 85 170 170 170 170 170 170 170 170 170 255 255 255 255 255 255
-170 170 170 255 255 255 255 255 255 170 170 170 255 255 255 170 170 170
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 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 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
-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 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 170 170 170
-255 255 85 170 170 170 255 255 255 170 170 170 255 255 255 255 255 255
-255 255 85 255 255 255 170 170 170 255 255 85 170 170 170 170 170 170
-170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 255 255 85
-170 170 170 170 85 0 85 85 85 0 0 0 85 85 85 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 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
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 170 170 170
-170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 170 170 170 255 255 85 170 170 170 170 170 170
-255 255 85 170 170 170 170 170 170 170 170 170 170 170 170 255 85 85
-85 255 85 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170
-255 255 255 255 255 255 255 255 255 255 255 85 170 170 170 170 170 170
-85 85 85 0 0 0 0 0 0 85 85 85 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 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 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 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 0 0 0 0 0 0 85 85 85 255 255 85
-170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 170 170 170
-255 255 255 170 170 170 170 170 170 170 170 170 170 170 170 255 85 85
-170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170
-170 170 170 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0
-85 85 85 0 0 0 0 0 0 85 85 85 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 0 0 0 0 0 0 0 0 0
-85 85 85 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
-0 0 0 0 0 0 0 0 0 170 170 170 170 170 170 170 170 170
-85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 85 85 85 170 85 0 170 170 170 170 170 170 170 170 170
-170 170 170 170 170 170 170 170 170 170 85 0 170 170 170 85 255 85
-255 85 85 170 170 170 255 255 85 170 170 170 170 170 170 255 255 255
-255 255 255 170 170 170 255 255 255 255 255 255 170 170 170 170 170 170
-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 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 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 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 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170
-170 170 170 255 255 85 170 170 170 255 255 85 255 255 255 255 255 255
-170 170 170 170 170 170 255 255 85 170 170 170 255 85 85 85 255 85
-170 170 170 170 85 0 170 170 170 170 170 170 255 255 85 170 170 170
-170 85 0 85 85 85 0 0 0 85 85 85 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 85 85 85 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 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 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 85 85 85
-0 0 0 85 85 85 85 85 85 85 85 85 170 170 170 255 255 85
-170 170 170 170 85 0 170 170 170 170 170 170 170 85 0 85 85 85
-170 170 170 170 85 0 85 85 85 170 170 170 170 170 170 170 170 170
-170 170 170 255 255 255 255 255 255 255 255 85 170 170 170 170 170 170
-0 0 0 85 85 85 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 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
-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 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
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 85 0
-170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170
-255 255 255 170 170 170 170 170 170 170 85 0 170 170 170 85 85 85
-170 170 170 170 170 170 170 85 0 170 170 170 170 85 0 85 85 85
-85 255 85 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85
-0 0 0 0 0 0 85 85 85 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 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
-85 85 85 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
-0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85
-85 85 85 0 0 0 85 85 85 170 85 0 85 85 85 170 170 170
-170 85 0 170 170 170 85 255 85 170 85 0 170 170 170 85 85 85
-170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 255 255 255
-255 255 85 255 255 255 170 170 170 170 170 170 170 170 170 170 85 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 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 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 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 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 255 255 85
-170 170 170 255 255 85 170 170 170 170 170 170 85 255 85 170 170 170
-170 85 0 170 85 0 170 170 170 85 255 85 85 85 85 170 170 170
-170 85 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 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 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 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 85 85 85
-0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 85 85 85
-170 170 170 170 85 0 170 170 170 85 85 85 170 170 170 170 85 0
-170 170 170 85 255 85 170 85 0 170 170 170 170 170 170 170 170 170
-255 255 255 170 170 170 255 255 255 255 255 255 170 170 170 85 85 85
-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 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 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 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 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-170 85 0 170 170 170 255 255 85 170 170 170 255 255 255 170 170 170
-170 170 170 170 170 170 170 170 170 170 85 0 170 170 170 170 85 0
-170 170 170 85 255 85 170 85 0 170 170 170 170 85 0 85 85 85
-85 85 85 85 85 85 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 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 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 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85
-85 255 85 170 170 170 170 85 0 170 170 170 170 85 0 85 255 85
-170 170 170 170 85 0 170 170 170 170 170 170 170 170 170 255 255 85
-170 170 170 255 255 255 170 170 170 170 170 170 170 170 170 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 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 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 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 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
-85 85 85 170 85 0 85 85 85 170 170 170 255 255 85 170 170 170
-170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 170 85 0
-170 170 170 85 85 85 170 170 170 170 85 0 170 170 170 85 85 85
-170 85 0 85 85 85 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 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
-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 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 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 170 85 0
-85 85 85 255 85 85 85 255 85 170 85 0 170 170 170 170 170 170
-170 85 0 170 170 170 85 85 85 255 255 85 170 170 170 170 170 170
-255 255 255 170 170 170 255 255 255 255 255 85 85 85 85 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 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 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 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 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 85 85 85 170 170 170 170 85 0 170 170 170 170 170 170
-170 170 170 170 170 170 170 170 170 255 255 85 85 85 85 170 170 170
-85 255 85 255 85 85 170 170 170 85 255 85 255 85 85 85 255 85
-85 85 85 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
-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 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 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 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 85 85 85
-85 85 85 85 255 85 255 85 85 170 170 170 85 255 85 170 85 0
-170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 255 255 255
-170 170 170 255 255 255 170 170 170 170 170 170 85 85 85 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 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 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 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 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 85 85 85 170 170 170 85 85 85 255 255 85
-170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 255 255 85
-85 85 85 255 255 85 170 170 170 170 85 0 170 170 170 85 85 85
-170 85 0 85 85 85 85 85 85 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 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 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
-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 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-170 170 170 170 85 0 170 170 170 170 85 0 170 170 170 170 170 170
-170 85 0 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170
-255 255 85 255 255 255 170 170 170 170 170 170 85 85 85 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 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 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 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 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 85 85 85 170 85 0 85 85 85 170 170 170
-170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 170 170 170
-170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 170 85 0
-85 85 85 85 85 85 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 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
-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 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 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85
-170 85 0 85 255 85 170 170 170 170 170 170 255 255 85 170 170 170
-255 255 85 170 170 170 170 170 170 170 170 170 255 255 255 255 255 255
-255 255 255 170 170 170 255 255 85 85 85 85 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 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 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 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
-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 0 0 0 0 0 0 85 85 85 85 85 85 170 85 0
-170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 255 255 85
-170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 170 170 170
-170 170 170 85 85 85 85 85 85 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 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 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
-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 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-85 85 85 170 85 0 170 170 170 170 85 0 170 170 170 170 170 170
-170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 255 255 255
-170 170 170 255 255 255 170 170 170 85 85 85 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 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 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 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
-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 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85
-170 85 0 170 170 170 170 85 0 255 255 85 170 170 170 170 170 170
-170 170 170 170 170 170 255 255 85 170 170 170 255 255 85 170 170 170
-255 255 85 85 85 85 85 85 85 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 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 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
-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 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85
-85 85 85 170 170 170 255 255 85 170 170 170 255 255 85 170 170 170
-170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
-170 170 170 170 170 170 170 170 170 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 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 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
-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 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
-0 0 0 0 0 0 0 0 0 0 0 0 0 170 0 85 85 85
-170 85 0 85 255 85 170 170 170 170 170 170 170 170 170 255 255 85
-255 255 255 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170
-170 170 170 255 255 85 85 85 85 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 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 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
-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 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-170 85 0 170 170 170 170 170 170 170 170 170 170 170 170 255 255 85
-170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 255 255 255
-255 255 255 255 255 85 85 85 85 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 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 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
-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 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
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-85 85 85 170 85 0 170 170 170 170 170 170 255 255 85 170 170 170
-170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 255 255 255
-170 170 170 170 170 170 170 170 170 85 85 85 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 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 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 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
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 255 85
-170 170 170 255 255 85 170 170 170 255 255 85 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 170 170 170
-170 170 170 170 170 170 85 85 85 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 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 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
-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 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
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 85 85 85 85 85 85 170 85 0 170 170 170 170 170 170
-255 255 85 170 170 170 255 255 255 255 255 85 255 255 255 255 255 255
-170 170 170 255 255 85 170 170 170 85 85 85 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 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 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 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
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 85 0
-170 170 170 170 170 170 170 170 170 255 255 255 170 170 170 255 255 255
-170 170 170 255 255 255 170 170 170 255 255 255 255 255 85 255 255 255
-170 170 170 85 85 85 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 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
-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 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 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 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 170 85 0 85 85 85 170 170 170 170 170 170 170 170 170
-170 170 170 255 255 255 170 170 170 255 255 255 255 255 255 170 170 170
-255 255 85 170 170 170 170 170 170 170 85 0 85 85 85 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 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 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 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 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170
-255 255 85 170 170 170 255 255 85 170 170 170 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170
-170 170 170 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
-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 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 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 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 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 85 85 85 85 85 85 85 85 85 170 85 0 170 170 170
-255 255 85 170 170 170 255 255 85 255 255 255 170 170 170 255 255 255
-170 170 170 170 170 170 170 170 170 170 170 170 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 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 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 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
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170
-170 85 0 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170
-255 255 255 255 255 255 170 170 170 255 255 255 255 255 85 170 170 170
-85 85 85 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
-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 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 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 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 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 85 85 85 170 85 0 85 85 85 170 170 170
-170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170
-255 255 85 170 170 170 170 85 0 85 255 85 85 85 85 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 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 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 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 0 0 0 0 0 0 0 0 0 85 85 85 170 85 0
-170 170 170 170 170 170 255 255 85 170 170 170 255 255 255 255 255 255
-255 255 85 255 255 255 170 170 170 255 255 255 170 170 170 85 85 85
-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 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 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 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 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 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 0 0 0 0 0 0 85 85 85 85 85 85
-170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 170 170 170
-170 170 170 170 170 170 170 170 170 170 85 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 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 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 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 0
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85
-255 255 85 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170
-255 255 255 170 170 170 255 255 85 170 170 170 85 85 85 85 85 85
-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 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 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 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 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 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 0 0 0 0 0 0 85 85 85 85 85 85
-85 85 85 170 85 0 170 170 170 170 170 170 170 170 170 170 170 170
-170 85 0 170 170 170 170 85 0 85 85 85 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 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 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 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
-0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85
-170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 170 170 170
-170 170 170 255 255 255 170 170 170 170 170 170 85 85 85 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 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 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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-85 85 85 85 85 85 85 85 85 170 85 0 85 85 85 170 85 0
-85 85 85 85 85 85 85 85 85 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 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 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
-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 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 85 0
-85 85 85 170 85 0 170 170 170 170 170 170 170 170 170 255 255 85
-170 170 170 170 170 170 170 85 0 85 85 85 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 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 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 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
-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 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
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85
-85 85 85 85 85 85 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 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
-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 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 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85
-85 85 85 85 255 85 170 85 0 170 170 170 170 85 0 170 170 170
-85 85 85 85 85 85 85 85 85 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 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 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
-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 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
-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 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 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 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 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 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
-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 0 0 0
-0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85
-85 85 85 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
-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 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 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 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 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 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 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 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
-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 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 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 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 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 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
-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 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 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 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 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 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 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 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
-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 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 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 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 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 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
-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 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
+ 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 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 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 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
+ 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 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 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 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
+ 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 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 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 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
+ 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 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 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 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
+ 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 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
+ 85 85 85 85 85 85 85 85 85 85 85 85
+ 85 85 85 85 85 85 85 85 85 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 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 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
+ 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 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 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 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 85 85 85 85 85 85
+ 85 85 85 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 85 85 85 85 85 85 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 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
+ 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 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 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 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
+ 0 0 0 85 85 85 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 0 0 0 85 85 85 85 85 85
+ 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 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 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 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
+ 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 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
+ 85 85 85 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
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 85 85 85 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
+ 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 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 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 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
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 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 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 85 85 85 85 85 85 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 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
+ 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 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 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 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 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 0 0 0
+ 85 85 85 170 170 170 0 0 0 0 0 0
+ 0 0 0 85 85 85 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 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
+ 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 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 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 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 85 85 85 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 0 0 0 0 0 0
+170 170 170 170 170 170 85 85 85 0 0 0
+ 0 0 0 0 0 0 85 85 85 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 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 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
+ 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 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 0 0 0 0 0 0
+ 0 0 0 0 0 0 85 85 85 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 0 0 0 0 0 0
+ 0 0 0 85 85 85 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 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 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 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 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
+ 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 0 0 0
+ 0 0 0 0 0 0 85 85 85 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 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 85 85 85
+ 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 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 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 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
+ 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 0 0 0
+ 0 0 0 85 85 85 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 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 85 85 85
+ 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 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 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 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
+ 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 0 0 0
+ 0 0 0 85 85 85 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 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
+ 85 85 85 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
+ 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 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 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 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
+ 0 0 0 85 85 85 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 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
+ 85 85 85 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
+ 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 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 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 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
+ 0 0 0 85 85 85 0 0 0 0 0 0
+ 0 0 0 85 85 85 170 170 170 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 170 170 170 170 170 170
+170 170 170 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 85 85 85 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
+ 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 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 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 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
+ 0 0 0 85 85 85 0 0 0 0 0 0
+ 85 85 85 170 170 170 170 170 170 170 170 170
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 170 170 170 255 255 255 255 255 255
+255 255 255 170 170 170 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 85 85 85 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
+ 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 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 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 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
+ 0 0 0 85 85 85 0 0 0 85 85 85
+170 170 170 170 170 170 255 255 255 255 255 255
+ 0 0 0 0 0 0 0 0 0 0 0 0
+170 170 170 255 255 255 170 170 170 170 170 170
+255 255 255 170 170 170 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 85 85 85 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
+ 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 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 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 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
+ 0 0 0 85 85 85 0 0 0 85 85 85
+170 170 170 0 0 0 0 0 0 255 255 255
+ 85 85 85 0 0 0 0 0 0 0 0 0
+255 255 255 170 170 170 0 0 0 85 85 85
+170 170 170 255 255 255 170 170 170 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 85 85 85 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
+ 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 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 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 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
+ 0 0 0 85 85 85 0 0 0 85 85 85
+ 85 85 85 0 0 0 0 0 0 170 170 170
+ 85 85 85 0 0 0 0 0 0 0 0 0
+255 255 255 85 85 85 0 0 0 0 0 0
+ 85 85 85 255 255 255 170 170 170 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 85 85 85 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
+ 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 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 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 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
+ 0 0 0 85 85 85 0 0 0 85 85 85
+170 170 170 0 0 0 0 0 0 170 170 170
+ 85 85 85 85 85 85 85 85 85 85 85 85
+255 255 255 85 85 85 0 0 0 0 0 0
+ 85 85 85 255 255 255 170 170 170 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 85 85 85 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
+ 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 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 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 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
+ 0 0 0 85 85 85 0 0 0 0 0 0
+255 255 255 0 0 0 0 0 0 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 0 0 0 0 0 0
+ 85 85 85 255 255 255 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 85 85 85 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
+ 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 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 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 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
+ 0 0 0 85 85 85 0 0 0 0 0 0
+170 170 170 170 170 170 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 170 170 170 170 170 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 85 85 85 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
+ 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 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 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 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
+ 0 0 0 85 85 85 0 0 0 0 0 0
+ 0 0 0 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 85 85 85 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
+ 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 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 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 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
+ 0 0 0 85 85 85 0 0 0 0 0 0
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 85 85 85 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 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
+ 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 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 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 85 85 85 85 85 85 0 0 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 170 85 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 85 85 85 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 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
+ 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 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 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 85 85 85 85 85 85 0 0 0
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 170 85 0
+170 85 0 170 85 0 85 85 85 0 0 0
+ 0 0 0 85 85 85 0 0 0 0 0 0
+ 0 0 0 0 0 0 85 85 85 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 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 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
+ 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 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 85 85 85 85 85 85 0 0 0
+ 85 85 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+170 85 0 170 85 0 170 85 0 170 85 0
+170 85 0 170 85 0 85 85 85 0 0 0
+ 0 0 0 85 85 85 170 170 170 85 85 85
+ 0 0 0 0 0 0 85 85 85 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 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 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
+ 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 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 85 85 85 85 85 85 0 0 0
+ 85 85 85 170 85 0 170 85 0 170 85 0
+170 85 0 170 85 0 170 85 0 170 85 0
+170 85 0 170 85 0 170 85 0 170 85 0
+170 170 170 170 170 170 170 170 170 0 0 0
+ 0 0 0 0 0 0 170 170 170 170 170 170
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 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 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 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 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
+ 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 85 85 85 0 0 0 0 0 0
+ 85 85 85 170 170 170 170 85 0 170 85 0
+170 85 0 170 85 0 170 85 0 170 85 0
+170 85 0 170 85 0 170 170 170 170 170 170
+170 170 170 170 170 170 170 170 170 85 85 85
+ 0 0 0 0 0 0 85 85 85 85 85 85
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 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 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 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 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
+ 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 85 85 85 0 0 0 0 0 0
+ 85 85 85 170 170 170 170 170 170 170 85 0
+170 85 0 170 85 0 170 85 0 170 85 0
+170 170 170 170 170 170 170 170 170 170 170 170
+255 255 255 255 255 255 255 255 255 170 170 170
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 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 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 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 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
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 85 85 85 0 0 0 0 0 0 85 85 85
+255 255 255 255 255 255 170 170 170 170 170 170
+170 170 170 170 170 170 170 170 170 170 170 170
+170 170 170 170 170 170 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+ 85 85 85 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 85 85 85 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
+ 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 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 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 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 85 85 85 0 0 0 0 0 0 170 170 170
+255 255 255 255 255 255 170 170 170 170 170 170
+170 170 170 170 170 170 170 170 170 170 170 170
+170 170 170 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+170 170 170 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 85 85 85 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
+ 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 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 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 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 0 0 0 0 0 0 85 85 85 255 255 255
+255 255 255 255 255 255 255 255 255 170 170 170
+170 170 170 170 170 170 170 170 170 170 170 170
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 85 85 85 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 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
+ 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 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 0 0 0 0 0 0
+ 0 0 0 0 0 0 85 85 85 0 0 0
+ 0 0 0 85 85 85 170 170 170 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 85 85 85 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 85 85 85 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 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 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
+ 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 0 0 0
+ 0 0 0 85 85 85 0 0 0 0 0 0
+ 0 0 0 85 85 85 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 170 170 170 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 85 85 85
+ 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 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 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 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
+ 0 0 0 85 85 85 0 0 0 0 0 0
+ 0 0 0 85 85 85 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 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
+ 85 85 85 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
+ 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 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 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
+ 85 85 85 0 0 0 0 0 0 0 0 0
+ 85 85 85 170 170 170 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 85 85 85 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 85 85 85 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 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
+ 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 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 85 85 85 170 170 170 170 170 170 170 170 170
+255 255 255 255 255 255 255 255 255 170 170 170
+170 170 170 170 170 170 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+170 170 170 170 170 170 170 170 170 170 170 170
+170 170 170 170 170 170 170 170 170 85 85 85
+ 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 85 85 85 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 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
+ 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 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 0 0 0 0 0 0 0 0 0 0 0 0
+170 170 170 170 170 170 170 170 170 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+170 170 170 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 170 170 170 170 170 170
+170 170 170 170 170 170 170 170 170 85 85 85
+ 0 0 0 0 0 0 85 85 85 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 85 85 85 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 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 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
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 85 85 85 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+170 170 170 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 170 170 170 170 170 170 170 170 170
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 85 85 85 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 85 85 85 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 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 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
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 85 85 85 0 0 0
+ 85 85 85 0 0 0 0 0 0 85 85 85
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 170 170 170 170 170 170
+ 85 85 85 0 0 0 0 0 0 0 0 0
+ 0 0 0 85 85 85 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 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 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 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 0 0 0 0 0 0 0 0 0
+ 0 0 0 85 85 85 0 0 0 0 0 0
+ 85 85 85 0 0 0 0 0 0 170 170 170
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+170 170 170 85 85 85 0 0 0 0 0 0
+ 0 0 0 85 85 85 85 85 85 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 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 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 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 0 0 0 0 0 0 0 0 0
+ 0 0 0 85 85 85 0 0 0 85 85 85
+ 0 0 0 0 0 0 85 85 85 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 170 170 170 0 0 0 85 85 85
+ 85 85 85 0 0 0 85 85 85 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 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 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 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 0 0 0 0 0 0 0 0 0
+ 0 0 0 85 85 85 0 0 0 85 85 85
+ 0 0 0 85 85 85 170 170 170 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 170 170 170 0 0 0 85 85 85
+ 85 85 85 0 0 0 85 85 85 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 85 85 85 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
+ 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 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 0 0 0 0 0 0
+ 85 85 85 0 0 0 0 0 0 85 85 85
+ 0 0 0 170 170 170 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 85 85 85 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 85 85 85 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
+ 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 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 0 0 0 0 0 0
+ 85 85 85 0 0 0 85 85 85 0 0 0
+ 0 0 0 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 170 170 170 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 85 85 85 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
+ 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 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 0 0 0 85 85 85
+ 0 0 0 0 0 0 85 85 85 0 0 0
+ 85 85 85 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 170 170 170 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 85 85 85 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
+ 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 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 0 0 0 85 85 85
+ 0 0 0 85 85 85 0 0 0 0 0 0
+170 170 170 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 170 170 170 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 85 85 85 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 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
+ 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 85 85 85 0 0 0
+ 0 0 0 85 85 85 0 0 0 0 0 0
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 170 170 170 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 85 85 85 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 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
+ 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 85 85 85 0 0 0 0 0 0
+ 0 0 0 85 85 85 0 0 0 0 0 0
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 170 170 170 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 85 85 85 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 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
+ 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 85 85 85 0 0 0 0 0 0
+ 0 0 0 85 85 85 0 0 0 85 85 85
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 170 170 170 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 85 85 85 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 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
+ 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 85 85 85 0 0 0 0 0 0
+ 0 0 0 85 85 85 0 0 0 85 85 85
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 170 170 170 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 85 85 85 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 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
+ 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 85 85 85 0 0 0 0 0 0
+ 0 0 0 0 0 0 85 85 85 85 85 85
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 170 170 170 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 85 85 85 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 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
+ 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 85 85 85 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 170 170 170 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 0 0 0
+ 85 85 85 85 85 85 85 85 85 85 85 85
+ 85 85 85 0 0 0 0 0 0 0 0 0
+ 0 0 0 85 85 85 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 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
+ 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 85 85 85 0 0 0 170 85 0
+255 255 85 170 85 0 0 0 0 0 0 0
+ 85 85 85 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 170 170 170 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 85 85 85
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 85 85 85 85 85 85 0 0 0
+ 0 0 0 85 85 85 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 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
+ 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 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 0 0 0
+ 0 0 0 85 85 85 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 170 170 170 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 85 170 85 0 255 255 85 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 85 85 85 85 85 85
+ 85 85 85 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
+ 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 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 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+ 0 0 0 0 0 0 85 85 85 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 85
+170 85 0 255 255 85 170 85 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
+170 85 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 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 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
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 0 0 0 0 0 0 85 85 85
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 170 85 0
+255 255 85 170 85 0 255 255 85 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 170 85 0
+255 255 85 170 85 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 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 0
+ 0 0 0 0 0 0 0 0 0 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 0 0 0 0 0 0 0 0 0
+ 85 85 85 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 85
+170 85 0 255 255 85 170 85 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 255 255 85
+170 85 0 255 255 85 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 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
+ 0 0 0 0 0 0 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 0 0 0 0 0 0
+ 0 0 0 85 85 85 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 170 170 170 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 255 255 85 170 85 0
+255 255 85 170 85 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 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 0
+ 0 0 0 0 0 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 0 0 0
+ 0 0 0 0 0 0 85 85 85 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 170 170 170 170 170 170 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 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 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
+ 0 0 0 0 0 0 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 85 85 85
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 170 170 170 170 170 170 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 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 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 0 0 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 170 170 170 170 170 170 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+ 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 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 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 170 170 170 170 170 170 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 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
+ 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 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 0 0 0 0 0 0 0 0 0
+ 85 85 85 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 170 170 170 85 85 85 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 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 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 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 85 85 85 85 85 85
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+170 170 170 85 85 85 85 85 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 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 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 170 170 170
+ 85 85 85 0 0 0 0 0 0 170 85 0
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+ 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 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 170 170 170 85 85 85
+ 0 0 0 0 0 0 0 0 0 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 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 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+170 170 170 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+170 170 170 85 85 85 85 85 85 0 0 0
+ 0 0 0 0 0 0 0 0 0 170 85 0
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 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 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 170 85 0
+170 85 0 170 170 170 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 170 170 170 85 85 85
+ 85 85 85 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 85 85 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 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
+ 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 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+170 85 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 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 85 85 85 170 85 0
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 170 85 0 170 85 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 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 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 170 85 0
+170 85 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 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 85 85 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+170 85 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 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 0 0 0 0
+ 0 0 0 0 0 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+170 85 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 0
+ 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 85 85 85 170 85 0
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 170 85 0 170 85 0 170 85 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 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 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 170 85 0 170 85 0
+170 85 0 170 85 0 170 85 0 170 85 0
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 170 85 0
+170 85 0 0 0 0 0 0 0 0 0 0
+ 85 85 85 85 85 85 85 85 85 85 85 85
+ 85 85 85 85 85 85 85 85 85 85 85 85
+ 85 85 85 85 85 85 85 85 85 0 0 0
+ 0 0 0 0 0 0 0 0 0 170 85 0
+170 85 0 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 255 255 85 170 85 0
+170 85 0 170 85 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 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 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 0 0 0 0
+ 0 0 0 0 0 0 170 85 0 170 85 0
+170 85 0 170 85 0 170 85 0 170 85 0
+170 85 0 170 85 0 255 255 85 170 85 0
+255 255 85 170 85 0 170 85 0 170 85 0
+ 85 85 85 85 85 85 85 85 85 85 85 85
+ 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 85 85 85
+ 85 85 85 85 85 85 85 85 85 170 85 0
+170 85 0 170 85 0 170 85 0 255 255 85
+170 85 0 255 255 85 170 85 0 170 85 0
+170 85 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 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 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 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 170 85 0
+170 85 0 170 85 0 170 85 0 170 85 0
+170 85 0 170 85 0 170 85 0 170 85 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 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 170 85 0
+170 85 0 170 85 0 170 85 0 170 85 0
+170 85 0 170 85 0 170 85 0 170 85 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 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 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 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 0
+ 0 0 0 170 85 0 170 85 0 170 85 0
+170 85 0 170 85 0 170 85 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 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
+170 85 0 170 85 0 170 85 0 170 85 0
+170 85 0 170 85 0 170 85 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index 21b3692092f2..9894de1c9b9f 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -1152,11 +1152,11 @@ static struct fb_ops mx3fb_ops = {
*/
static int mx3fb_suspend(struct platform_device *pdev, pm_message_t state)
{
- struct mx3fb_data *drv_data = platform_get_drvdata(pdev);
- struct mx3fb_info *mx3_fbi = drv_data->fbi->par;
+ struct mx3fb_data *mx3fb = platform_get_drvdata(pdev);
+ struct mx3fb_info *mx3_fbi = mx3fb->fbi->par;
acquire_console_sem();
- fb_set_suspend(drv_data->fbi, 1);
+ fb_set_suspend(mx3fb->fbi, 1);
release_console_sem();
if (mx3_fbi->blank == FB_BLANK_UNBLANK) {
@@ -1172,16 +1172,16 @@ static int mx3fb_suspend(struct platform_device *pdev, pm_message_t state)
*/
static int mx3fb_resume(struct platform_device *pdev)
{
- struct mx3fb_data *drv_data = platform_get_drvdata(pdev);
- struct mx3fb_info *mx3_fbi = drv_data->fbi->par;
+ struct mx3fb_data *mx3fb = platform_get_drvdata(pdev);
+ struct mx3fb_info *mx3_fbi = mx3fb->fbi->par;
if (mx3_fbi->blank == FB_BLANK_UNBLANK) {
sdc_enable_channel(mx3_fbi);
- sdc_set_brightness(mx3fb, drv_data->backlight_level);
+ sdc_set_brightness(mx3fb, mx3fb->backlight_level);
}
acquire_console_sem();
- fb_set_suspend(drv_data->fbi, 0);
+ fb_set_suspend(mx3fb->fbi, 0);
release_console_sem();
return 0;
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 84f63205c46d..0889d50c3288 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -1439,7 +1439,7 @@ static void pxafb_disable_controller(struct pxafb_info *fbi)
static irqreturn_t pxafb_handle_irq(int irq, void *dev_id)
{
struct pxafb_info *fbi = dev_id;
- unsigned int lccr0, lcsr, lcsr1;
+ unsigned int lccr0, lcsr;
lcsr = lcd_readl(fbi, LCSR);
if (lcsr & LCSR_LDD) {
@@ -1455,14 +1455,16 @@ static irqreturn_t pxafb_handle_irq(int irq, void *dev_id)
lcd_writel(fbi, LCSR, lcsr);
#ifdef CONFIG_FB_PXA_OVERLAY
- lcsr1 = lcd_readl(fbi, LCSR1);
- if (lcsr1 & LCSR1_BS(1))
- complete(&fbi->overlay[0].branch_done);
+ {
+ unsigned int lcsr1 = lcd_readl(fbi, LCSR1);
+ if (lcsr1 & LCSR1_BS(1))
+ complete(&fbi->overlay[0].branch_done);
- if (lcsr1 & LCSR1_BS(2))
- complete(&fbi->overlay[1].branch_done);
+ if (lcsr1 & LCSR1_BS(2))
+ complete(&fbi->overlay[1].branch_done);
- lcd_writel(fbi, LCSR1, lcsr1);
+ lcd_writel(fbi, LCSR1, lcsr1);
+ }
#endif
return IRQ_HANDLED;
}
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c
index 4dcec48a1d78..c3fad34309ed 100644
--- a/drivers/video/s3fb.c
+++ b/drivers/video/s3fb.c
@@ -45,11 +45,11 @@ struct s3fb_info {
static const struct svga_fb_format s3fb_formats[] = {
{ 0, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0,
FB_TYPE_TEXT, FB_AUX_TEXT_SVGA_STEP4, FB_VISUAL_PSEUDOCOLOR, 8, 16},
- { 4, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0,
+ { 4, {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0}, 0,
FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_PSEUDOCOLOR, 8, 16},
- { 4, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 1,
+ { 4, {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0}, 1,
FB_TYPE_INTERLEAVED_PLANES, 1, FB_VISUAL_PSEUDOCOLOR, 8, 16},
- { 8, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0,
+ { 8, {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0,
FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_PSEUDOCOLOR, 4, 8},
{16, {10, 5, 0}, {5, 5, 0}, {0, 5, 0}, {0, 0, 0}, 0,
FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_TRUECOLOR, 2, 4},
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index fad58cf9ef73..10ddad8e17d6 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -199,16 +199,20 @@
extern void (*sa1100fb_backlight_power)(int on);
extern void (*sa1100fb_lcd_power)(int on);
-/*
- * IMHO this looks wrong. In 8BPP, length should be 8.
- */
-static struct sa1100fb_rgb rgb_8 = {
+static struct sa1100fb_rgb rgb_4 = {
.red = { .offset = 0, .length = 4, },
.green = { .offset = 0, .length = 4, },
.blue = { .offset = 0, .length = 4, },
.transp = { .offset = 0, .length = 0, },
};
+static struct sa1100fb_rgb rgb_8 = {
+ .red = { .offset = 0, .length = 8, },
+ .green = { .offset = 0, .length = 8, },
+ .blue = { .offset = 0, .length = 8, },
+ .transp = { .offset = 0, .length = 0, },
+};
+
static struct sa1100fb_rgb def_rgb_16 = {
.red = { .offset = 11, .length = 5, },
.green = { .offset = 5, .length = 6, },
@@ -613,7 +617,7 @@ sa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel);
switch (var->bits_per_pixel) {
case 4:
- rgbidx = RGB_8;
+ rgbidx = RGB_4;
break;
case 8:
rgbidx = RGB_8;
@@ -1382,6 +1386,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
fbi->fb.monspecs = monspecs;
fbi->fb.pseudo_palette = (fbi + 1);
+ fbi->rgb[RGB_4] = &rgb_4;
fbi->rgb[RGB_8] = &rgb_8;
fbi->rgb[RGB_16] = &def_rgb_16;
diff --git a/drivers/video/sa1100fb.h b/drivers/video/sa1100fb.h
index 86831db9a042..1c3b459865d8 100644
--- a/drivers/video/sa1100fb.h
+++ b/drivers/video/sa1100fb.h
@@ -57,9 +57,10 @@ struct sa1100fb_lcd_reg {
unsigned long lccr3;
};
-#define RGB_8 (0)
-#define RGB_16 (1)
-#define NR_RGB 2
+#define RGB_4 (0)
+#define RGB_8 (1)
+#define RGB_16 (2)
+#define NR_RGB 3
struct sa1100fb_info {
struct fb_info fb;
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 346d6458cf76..7e17ee95a97a 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -1129,7 +1129,7 @@ sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
switch(var->bits_per_pixel) {
case 8:
var->red.offset = var->green.offset = var->blue.offset = 0;
- var->red.length = var->green.length = var->blue.length = 6;
+ var->red.length = var->green.length = var->blue.length = 8;
break;
case 16:
var->red.offset = 11;
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
index a439159204a8..89158bc71da2 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/skeletonfb.c
@@ -308,9 +308,11 @@ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
* color depth = SUM(var->{color}.length)
*
* Pseudocolor:
- * var->{color}.offset is 0
- * var->{color}.length contains width of DAC or the number of unique
- * colors available (color depth)
+ * var->{color}.offset is 0 unless the palette index takes less than
+ * bits_per_pixel bits and is stored in the upper
+ * bits of the pixel value
+ * var->{color}.length is set so that 1 << length is the number of
+ * available palette entries
* pseudo_palette is not used
* RAMDAC[X] is programmed to (red, green, blue)
* color depth = var->{color}.length
diff --git a/drivers/video/sysfillrect.c b/drivers/video/sysfillrect.c
index f94d6b6e29ee..33ee3d34f9d2 100644
--- a/drivers/video/sysfillrect.c
+++ b/drivers/video/sysfillrect.c
@@ -124,7 +124,7 @@ bitfill_unaligned(struct fb_info *p, unsigned long *dst, int dst_idx,
/* Trailing bits */
if (last)
- *dst = comp(pat, *dst, first);
+ *dst = comp(pat, *dst, last);
}
}
@@ -242,7 +242,7 @@ bitfill_unaligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx,
void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
{
- unsigned long pat, fg;
+ unsigned long pat, pat2, fg;
unsigned long width = rect->width, height = rect->height;
int bits = BITS_PER_LONG, bytes = bits >> 3;
u32 bpp = p->var.bits_per_pixel;
@@ -292,17 +292,16 @@ void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
dst_idx += p->fix.line_length*8;
}
} else {
- int right;
- int r;
- int rot = (left-dst_idx) % bpp;
+ int right, r;
void (*fill_op)(struct fb_info *p, unsigned long *dst,
int dst_idx, unsigned long pat, int left,
int right, unsigned n, int bits) = NULL;
-
- /* rotate pattern to correct start position */
- pat = pat << rot | pat >> (bpp-rot);
-
- right = bpp-left;
+#ifdef __LITTLE_ENDIAN
+ right = left;
+ left = bpp - right;
+#else
+ right = bpp - left;
+#endif
switch (rect->rop) {
case ROP_XOR:
fill_op = bitfill_unaligned_rev;
@@ -311,18 +310,19 @@ void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
fill_op = bitfill_unaligned;
break;
default:
- printk(KERN_ERR "cfb_fillrect(): unknown rop, "
+ printk(KERN_ERR "sys_fillrect(): unknown rop, "
"defaulting to ROP_COPY\n");
fill_op = bitfill_unaligned;
break;
}
while (height--) {
- dst += dst_idx >> (ffs(bits) - 1);
+ dst += dst_idx / bits;
dst_idx &= (bits - 1);
- fill_op(p, dst, dst_idx, pat, left, right,
+ r = dst_idx % bpp;
+ /* rotate pattern to the correct start position */
+ pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp));
+ fill_op(p, dst, dst_idx, pat2, left, right,
width*bpp, bits);
- r = (p->fix.line_length*8) % bpp;
- pat = pat << (bpp-r) | pat >> r;
dst_idx += p->fix.line_length*8;
}
}
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index 89f231dc443f..ff43c8885028 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -1315,7 +1315,6 @@ static int __devinit tdfxfb_setup_i2c_bus(struct tdfxfb_i2c_chan *chan,
strlcpy(chan->adapter.name, name, sizeof(chan->adapter.name));
chan->adapter.owner = THIS_MODULE;
- chan->adapter.class = I2C_CLASS_TV_ANALOG;
chan->adapter.algo_data = &chan->algo;
chan->adapter.dev.parent = dev;
chan->algo.setsda = tdfxfb_i2c_setsda;
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index 0b370aebdbfd..ca5b4643a401 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -45,7 +45,7 @@ static struct fb_fix_screeninfo uvesafb_fix __devinitdata = {
static int mtrr __devinitdata = 3; /* enable mtrr by default */
static int blank = 1; /* enable blanking by default */
static int ypan = 1; /* 0: scroll, 1: ypan, 2: ywrap */
-static int pmi_setpal __devinitdata = 1; /* use PMI for palette changes */
+static bool pmi_setpal __devinitdata = true; /* 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 */
@@ -55,6 +55,7 @@ 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 u8 dac_width = 6;
static struct uvesafb_ktask *uvfb_tasks[UVESAFB_TASKS_MAX];
static DEFINE_MUTEX(uvfb_lock);
@@ -303,22 +304,10 @@ static void uvesafb_setup_var(struct fb_var_screeninfo *var,
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;
- }
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
+ var->transp.length = 0;
}
}
@@ -1006,7 +995,7 @@ static int uvesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
struct fb_info *info)
{
struct uvesafb_pal_entry entry;
- int shift = 16 - info->var.green.length;
+ int shift = 16 - dac_width;
int err = 0;
if (regno >= info->cmap.len)
@@ -1055,7 +1044,7 @@ static int uvesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
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 shift = 16 - dac_width;
int i, err = 0;
if (info->var.bits_per_pixel == 8) {
@@ -1317,13 +1306,9 @@ setmode:
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;
+ dac_width = 6;
+ } else {
+ dac_width = 8;
}
}
@@ -2017,11 +2002,7 @@ static void __devexit uvesafb_exit(void)
module_exit(uvesafb_exit);
-static int param_get_scroll(char *buffer, struct kernel_param *kp)
-{
- return 0;
-}
-
+#define param_get_scroll NULL
static int param_set_scroll(const char *val, struct kernel_param *kp)
{
ypan = 0;
@@ -2032,6 +2013,8 @@ static int param_set_scroll(const char *val, struct kernel_param *kp)
ypan = 1;
else if (!strcmp(val, "ywrap"))
ypan = 2;
+ else
+ return -EINVAL;
return 0;
}
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index cc919ae46571..050d432c7d95 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -318,13 +318,16 @@ static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
* {hardwarespecific} contains width of RAMDAC
* cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
* RAMDAC[X] is programmed to (red, green, blue)
- *
+ *
* Pseudocolor:
- * uses offset = 0 && length = RAMDAC register width.
- * var->{color}.offset is 0
- * var->{color}.length contains widht of DAC
+ * var->{color}.offset is 0 unless the palette index takes less than
+ * bits_per_pixel bits and is stored in the upper
+ * bits of the pixel value
+ * var->{color}.length is set so that 1 << length is the number of available
+ * palette entries
* cmap is not used
* RAMDAC[X] is programmed to (red, green, blue)
+ *
* Truecolor:
* does not use DAC. Usually 3 are present.
* var->{color}.offset contains start of bitfield
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 59268266b79a..9c76a061a04d 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -190,7 +190,8 @@ static int balloon(void *_vballoon)
try_to_freeze();
wait_event_interruptible(vb->config_change,
(diff = towards_target(vb)) != 0
- || kthread_should_stop());
+ || kthread_should_stop()
+ || freezing(current));
if (diff > 0)
fill_balloon(vb, diff);
else if (diff < 0)
diff --git a/drivers/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c
index 90f98df5f106..f90afdb1b255 100644
--- a/drivers/watchdog/alim7101_wdt.c
+++ b/drivers/watchdog/alim7101_wdt.c
@@ -322,7 +322,8 @@ static int wdt_notify_sys(struct notifier_block *this,
* watchdog on reboot with no heartbeat
*/
wdt_change(WDT_ENABLE);
- printk(KERN_INFO PFX "Watchdog timer is now enabled with no heartbeat - should reboot in ~1 second.\n");
+ printk(KERN_INFO PFX "Watchdog timer is now enabled "
+ "with no heartbeat - should reboot in ~1 second.\n");
}
return NOTIFY_DONE;
}
@@ -374,12 +375,17 @@ static int __init alim7101_wdt_init(void)
pci_dev_put(ali1543_south);
if ((tmp & 0x1e) == 0x00) {
if (!use_gpio) {
- printk(KERN_INFO PFX "Detected old alim7101 revision 'a1d'. If this is a cobalt board, set the 'use_gpio' module parameter.\n");
+ printk(KERN_INFO PFX
+ "Detected old alim7101 revision 'a1d'. "
+ "If this is a cobalt board, set the 'use_gpio' "
+ "module parameter.\n");
goto err_out;
}
nowayout = 1;
} else if ((tmp & 0x1e) != 0x12 && (tmp & 0x1e) != 0x00) {
- printk(KERN_INFO PFX "ALi 1543 South-Bridge does not have the correct revision number (???1001?) - WDT not set\n");
+ printk(KERN_INFO PFX
+ "ALi 1543 South-Bridge does not have the correct "
+ "revision number (???1001?) - WDT not set\n");
goto err_out;
}
@@ -409,7 +415,8 @@ static int __init alim7101_wdt_init(void)
if (nowayout)
__module_get(THIS_MODULE);
- printk(KERN_INFO PFX "WDT driver for ALi M7101 initialised. timeout=%d sec (nowayout=%d)\n",
+ printk(KERN_INFO PFX "WDT driver for ALi M7101 initialised. "
+ "timeout=%d sec (nowayout=%d)\n",
timeout, nowayout);
return 0;
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c
index 55dcbfe2bb72..3fe9742c23ca 100644
--- a/drivers/watchdog/ar7_wdt.c
+++ b/drivers/watchdog/ar7_wdt.c
@@ -246,7 +246,8 @@ static long ar7_wdt_ioctl(struct file *file,
static struct watchdog_info ident = {
.identity = LONGNAME,
.firmware_version = 1,
- .options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING),
+ .options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE),
};
int new_margin;
diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c
index 29e52c237a3b..b185dafe1494 100644
--- a/drivers/watchdog/at91rm9200_wdt.c
+++ b/drivers/watchdog/at91rm9200_wdt.c
@@ -268,7 +268,8 @@ static int __init at91_wdt_init(void)
if not reset to the default */
if (at91_wdt_settimeout(wdt_time)) {
at91_wdt_settimeout(WDT_DEFAULT_TIME);
- pr_info("at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time);
+ pr_info("at91_wdt: wdt_time value must be 1 <= wdt_time <= 256"
+ ", using %d\n", wdt_time);
}
return platform_driver_register(&at91wdt_driver);
diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c
index 435b0573fb0a..eac26021e8da 100644
--- a/drivers/watchdog/at91sam9_wdt.c
+++ b/drivers/watchdog/at91sam9_wdt.c
@@ -156,7 +156,8 @@ static int at91_wdt_settimeout(unsigned int timeout)
static const struct watchdog_info at91_wdt_info = {
.identity = DRV_NAME,
- .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE,
};
/*
diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c
index 067a57cb3f82..c7b3f9df2317 100644
--- a/drivers/watchdog/bfin_wdt.c
+++ b/drivers/watchdog/bfin_wdt.c
@@ -27,10 +27,15 @@
#include <linux/uaccess.h>
#include <asm/blackfin.h>
-#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
+#define stamp(fmt, args...) \
+ pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
#define stampit() stamp("here i am")
-#define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); })
-#define pr_init(fmt, args...) ({ static const __initconst char __fmt[] = fmt; printk(__fmt, ## args); })
+#define pr_devinit(fmt, args...) \
+ ({ static const __devinitconst char __fmt[] = fmt; \
+ printk(__fmt, ## args); })
+#define pr_init(fmt, args...) \
+ ({ static const __initconst char __fmt[] = fmt; \
+ printk(__fmt, ## args); })
#define WATCHDOG_NAME "bfin-wdt"
#define PFX WATCHDOG_NAME ": "
@@ -476,7 +481,8 @@ static int __init bfin_wdt_init(void)
return ret;
}
- bfin_wdt_device = platform_device_register_simple(WATCHDOG_NAME, -1, NULL, 0);
+ bfin_wdt_device = platform_device_register_simple(WATCHDOG_NAME,
+ -1, NULL, 0);
if (IS_ERR(bfin_wdt_device)) {
pr_init(KERN_ERR PFX "unable to register device\n");
platform_driver_unregister(&bfin_wdt_driver);
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c
index 41070e4771a0..081f2955419e 100644
--- a/drivers/watchdog/cpwd.c
+++ b/drivers/watchdog/cpwd.c
@@ -154,9 +154,9 @@ static struct cpwd *cpwd_device;
static struct timer_list cpwd_timer;
-static int wd0_timeout = 0;
-static int wd1_timeout = 0;
-static int wd2_timeout = 0;
+static int wd0_timeout;
+static int wd1_timeout;
+static int wd2_timeout;
module_param(wd0_timeout, int, 0);
MODULE_PARM_DESC(wd0_timeout, "Default watchdog0 timeout in 1/10secs");
diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c
index c51d0b0ea0c4..83e22e7ea4a2 100644
--- a/drivers/watchdog/davinci_wdt.c
+++ b/drivers/watchdog/davinci_wdt.c
@@ -193,7 +193,7 @@ static struct miscdevice davinci_wdt_miscdev = {
.fops = &davinci_wdt_fops,
};
-static int davinci_wdt_probe(struct platform_device *pdev)
+static int __devinit davinci_wdt_probe(struct platform_device *pdev)
{
int ret = 0, size;
struct resource *res;
@@ -237,7 +237,7 @@ static int davinci_wdt_probe(struct platform_device *pdev)
return ret;
}
-static int davinci_wdt_remove(struct platform_device *pdev)
+static int __devexit davinci_wdt_remove(struct platform_device *pdev)
{
misc_deregister(&davinci_wdt_miscdev);
if (wdt_mem) {
@@ -254,7 +254,7 @@ static struct platform_driver platform_wdt_driver = {
.owner = THIS_MODULE,
},
.probe = davinci_wdt_probe,
- .remove = davinci_wdt_remove,
+ .remove = __devexit_p(davinci_wdt_remove),
};
static int __init davinci_wdt_init(void)
diff --git a/drivers/watchdog/iTCO_vendor_support.c b/drivers/watchdog/iTCO_vendor_support.c
index d3c0f6de5523..843ef626bc50 100644
--- a/drivers/watchdog/iTCO_vendor_support.c
+++ b/drivers/watchdog/iTCO_vendor_support.c
@@ -35,9 +35,9 @@
#include "iTCO_vendor.h"
/* iTCO defines */
-#define SMI_EN acpibase + 0x30 /* SMI Control and Enable Register */
-#define TCOBASE acpibase + 0x60 /* TCO base address */
-#define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */
+#define SMI_EN (acpibase + 0x30) /* SMI Control and Enable Register */
+#define TCOBASE (acpibase + 0x60) /* TCO base address */
+#define TCO1_STS (TCOBASE + 0x04) /* TCO1 Status Register */
/* List of vendor support modes */
/* SuperMicro Pentium 3 Era 370SSE+-OEM1/P3TSSE */
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index 648250b998c4..6284961eff5b 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -236,19 +236,19 @@ MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl);
/* Address definitions for the TCO */
/* TCO base address */
-#define TCOBASE iTCO_wdt_private.ACPIBASE + 0x60
+#define TCOBASE (iTCO_wdt_private.ACPIBASE + 0x60)
/* SMI Control and Enable Register */
-#define SMI_EN iTCO_wdt_private.ACPIBASE + 0x30
-
-#define TCO_RLD TCOBASE + 0x00 /* TCO Timer Reload and Curr. Value */
-#define TCOv1_TMR TCOBASE + 0x01 /* TCOv1 Timer Initial Value */
-#define TCO_DAT_IN TCOBASE + 0x02 /* TCO Data In Register */
-#define TCO_DAT_OUT TCOBASE + 0x03 /* TCO Data Out Register */
-#define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */
-#define TCO2_STS TCOBASE + 0x06 /* TCO2 Status Register */
-#define TCO1_CNT TCOBASE + 0x08 /* TCO1 Control Register */
-#define TCO2_CNT TCOBASE + 0x0a /* TCO2 Control Register */
-#define TCOv2_TMR TCOBASE + 0x12 /* TCOv2 Timer Initial Value */
+#define SMI_EN (iTCO_wdt_private.ACPIBASE + 0x30)
+
+#define TCO_RLD (TCOBASE + 0x00) /* TCO Timer Reload and Curr. Value */
+#define TCOv1_TMR (TCOBASE + 0x01) /* TCOv1 Timer Initial Value */
+#define TCO_DAT_IN (TCOBASE + 0x02) /* TCO Data In Register */
+#define TCO_DAT_OUT (TCOBASE + 0x03) /* TCO Data Out Register */
+#define TCO1_STS (TCOBASE + 0x04) /* TCO1 Status Register */
+#define TCO2_STS (TCOBASE + 0x06) /* TCO2 Status Register */
+#define TCO1_CNT (TCOBASE + 0x08) /* TCO1 Control Register */
+#define TCO2_CNT (TCOBASE + 0x0a) /* TCO2 Control Register */
+#define TCOv2_TMR (TCOBASE + 0x12) /* TCOv2 Timer Initial Value */
/* internal variables */
static unsigned long is_active;
diff --git a/drivers/watchdog/indydog.c b/drivers/watchdog/indydog.c
index 0f761db9a27c..bea8a124a559 100644
--- a/drivers/watchdog/indydog.c
+++ b/drivers/watchdog/indydog.c
@@ -83,7 +83,6 @@ static int indydog_open(struct inode *inode, struct file *file)
indydog_start();
indydog_ping();
- indydog_alive = 1;
printk(KERN_INFO "Started watchdog timer.\n");
return nonseekable_open(inode, file);
@@ -113,8 +112,7 @@ static long indydog_ioctl(struct file *file, unsigned int cmd,
{
int options, retval = -EINVAL;
static struct watchdog_info ident = {
- .options = WDIOF_KEEPALIVEPING |
- WDIOF_MAGICCLOSE,
+ .options = WDIOF_KEEPALIVEPING,
.firmware_version = 0,
.identity = "Hardware Watchdog for SGI IP22",
};
diff --git a/drivers/watchdog/iop_wdt.c b/drivers/watchdog/iop_wdt.c
index 96eb2cbe5874..0c9059676690 100644
--- a/drivers/watchdog/iop_wdt.c
+++ b/drivers/watchdog/iop_wdt.c
@@ -192,7 +192,7 @@ static int iop_wdt_release(struct inode *inode, struct file *file)
if (test_bit(WDT_ENABLED, &wdt_status))
state = wdt_disable();
- /* if the timer is not disbaled reload and notify that we are still
+ /* if the timer is not disabled reload and notify that we are still
* going down
*/
if (state != 0) {
diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c
index 2270ee07c01b..daed48ded7fe 100644
--- a/drivers/watchdog/it8712f_wdt.c
+++ b/drivers/watchdog/it8712f_wdt.c
@@ -239,7 +239,8 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd,
static struct watchdog_info ident = {
.identity = "IT8712F Watchdog",
.firmware_version = 1,
- .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE,
};
int value;
diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c
index ae3832110acb..00b03eb43bf0 100644
--- a/drivers/watchdog/ks8695_wdt.c
+++ b/drivers/watchdog/ks8695_wdt.c
@@ -293,8 +293,8 @@ static int __init ks8695_wdt_init(void)
if not reset to the default */
if (ks8695_wdt_settimeout(wdt_time)) {
ks8695_wdt_settimeout(WDT_DEFAULT_TIME);
- pr_info("ks8695_wdt: wdt_time value must be 1 <= wdt_time <= %i, using %d\n",
- wdt_time, WDT_MAX_TIME);
+ pr_info("ks8695_wdt: wdt_time value must be 1 <= wdt_time <= %i"
+ ", using %d\n", wdt_time, WDT_MAX_TIME);
}
return platform_driver_register(&ks8695wdt_driver);
}
diff --git a/drivers/watchdog/machzwd.c b/drivers/watchdog/machzwd.c
index 2dfc27559bf7..b6b3f59ab446 100644
--- a/drivers/watchdog/machzwd.c
+++ b/drivers/watchdog/machzwd.c
@@ -118,7 +118,8 @@ static struct watchdog_info zf_info = {
*/
static int action;
module_param(action, int, 0);
-MODULE_PARM_DESC(action, "after watchdog resets, generate: 0 = RESET(*) 1 = SMI 2 = NMI 3 = SCI");
+MODULE_PARM_DESC(action, "after watchdog resets, generate: "
+ "0 = RESET(*) 1 = SMI 2 = NMI 3 = SCI");
static void zf_ping(unsigned long data);
@@ -142,7 +143,8 @@ static unsigned long next_heartbeat;
#ifndef ZF_DEBUG
# define dprintk(format, args...)
#else
-# define dprintk(format, args...) printk(KERN_DEBUG PFX ":%s:%d: " format, __func__, __LINE__ , ## args)
+# define dprintk(format, args...) printk(KERN_DEBUG PFX
+ ":%s:%d: " format, __func__, __LINE__ , ## args)
#endif
@@ -340,7 +342,8 @@ static int zf_close(struct inode *inode, struct file *file)
zf_timer_off();
else {
del_timer(&zf_timer);
- printk(KERN_ERR PFX ": device file closed unexpectedly. Will not stop the WDT!\n");
+ printk(KERN_ERR PFX ": device file closed unexpectedly. "
+ "Will not stop the WDT!\n");
}
clear_bit(0, &zf_is_open);
zf_expect_close = 0;
diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c
index 1512ab8b175b..83fa34b214b4 100644
--- a/drivers/watchdog/mpcore_wdt.c
+++ b/drivers/watchdog/mpcore_wdt.c
@@ -61,7 +61,9 @@ MODULE_PARM_DESC(nowayout,
#define ONLY_TESTING 0
static int mpcore_noboot = ONLY_TESTING;
module_param(mpcore_noboot, int, 0);
-MODULE_PARM_DESC(mpcore_noboot, "MPcore watchdog action, set to 1 to ignore reboots, 0 to reboot (default=" __MODULE_STRING(ONLY_TESTING) ")");
+MODULE_PARM_DESC(mpcore_noboot, "MPcore watchdog action, "
+ "set to 1 to ignore reboots, 0 to reboot (default="
+ __MODULE_STRING(ONLY_TESTING) ")");
/*
* This is the interrupt handler. Note that we only use this
@@ -416,7 +418,8 @@ static struct platform_driver mpcore_wdt_driver = {
},
};
-static char banner[] __initdata = KERN_INFO "MPcore Watchdog Timer: 0.1. mpcore_noboot=%d mpcore_margin=%d sec (nowayout= %d)\n";
+static char banner[] __initdata = KERN_INFO "MPcore Watchdog Timer: 0.1. "
+ "mpcore_noboot=%d mpcore_margin=%d sec (nowayout= %d)\n";
static int __init mpcore_wdt_init(void)
{
diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c
index 539b6f6ba7f1..08e8a6ab74e1 100644
--- a/drivers/watchdog/mtx-1_wdt.c
+++ b/drivers/watchdog/mtx-1_wdt.c
@@ -206,7 +206,7 @@ static struct miscdevice mtx1_wdt_misc = {
};
-static int mtx1_wdt_probe(struct platform_device *pdev)
+static int __devinit mtx1_wdt_probe(struct platform_device *pdev)
{
int ret;
@@ -229,7 +229,7 @@ static int mtx1_wdt_probe(struct platform_device *pdev)
return 0;
}
-static int mtx1_wdt_remove(struct platform_device *pdev)
+static int __devexit mtx1_wdt_remove(struct platform_device *pdev)
{
/* FIXME: do we need to lock this test ? */
if (mtx1_wdt_device.queue) {
@@ -242,7 +242,7 @@ static int mtx1_wdt_remove(struct platform_device *pdev)
static struct platform_driver mtx1_wdt = {
.probe = mtx1_wdt_probe,
- .remove = mtx1_wdt_remove,
+ .remove = __devexit_p(mtx1_wdt_remove),
.driver.name = "mtx1-wdt",
.driver.owner = THIS_MODULE,
};
diff --git a/drivers/watchdog/orion5x_wdt.c b/drivers/watchdog/orion5x_wdt.c
index 7529616739d2..2cde568e4fb0 100644
--- a/drivers/watchdog/orion5x_wdt.c
+++ b/drivers/watchdog/orion5x_wdt.c
@@ -22,6 +22,7 @@
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/spinlock.h>
+#include <mach/bridge-regs.h>
#include <plat/orion5x_wdt.h>
/*
diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c
index 64135195f827..f24d04132eda 100644
--- a/drivers/watchdog/pnx4008_wdt.c
+++ b/drivers/watchdog/pnx4008_wdt.c
@@ -246,7 +246,7 @@ static struct miscdevice pnx4008_wdt_miscdev = {
.fops = &pnx4008_wdt_fops,
};
-static int pnx4008_wdt_probe(struct platform_device *pdev)
+static int __devinit pnx4008_wdt_probe(struct platform_device *pdev)
{
int ret = 0, size;
struct resource *res;
@@ -299,7 +299,7 @@ out:
return ret;
}
-static int pnx4008_wdt_remove(struct platform_device *pdev)
+static int __devexit pnx4008_wdt_remove(struct platform_device *pdev)
{
misc_deregister(&pnx4008_wdt_miscdev);
if (wdt_clk) {
@@ -321,7 +321,7 @@ static struct platform_driver platform_wdt_driver = {
.owner = THIS_MODULE,
},
.probe = pnx4008_wdt_probe,
- .remove = pnx4008_wdt_remove,
+ .remove = __devexit_p(pnx4008_wdt_remove),
};
static int __init pnx4008_wdt_init(void)
diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c
index 36e221beedcd..4976bfd1fce6 100644
--- a/drivers/watchdog/rdc321x_wdt.c
+++ b/drivers/watchdog/rdc321x_wdt.c
@@ -245,7 +245,7 @@ static int __devinit rdc321x_wdt_probe(struct platform_device *pdev)
return 0;
}
-static int rdc321x_wdt_remove(struct platform_device *pdev)
+static int __devexit rdc321x_wdt_remove(struct platform_device *pdev)
{
if (rdc321x_wdt_device.queue) {
rdc321x_wdt_device.queue = 0;
@@ -259,7 +259,7 @@ static int rdc321x_wdt_remove(struct platform_device *pdev)
static struct platform_driver rdc321x_wdt_driver = {
.probe = rdc321x_wdt_probe,
- .remove = rdc321x_wdt_remove,
+ .remove = __devexit_p(rdc321x_wdt_remove),
.driver = {
.owner = THIS_MODULE,
.name = "rdc321x-wdt",
diff --git a/drivers/watchdog/rm9k_wdt.c b/drivers/watchdog/rm9k_wdt.c
index cce1982a1b58..2e4442642262 100644
--- a/drivers/watchdog/rm9k_wdt.c
+++ b/drivers/watchdog/rm9k_wdt.c
@@ -345,8 +345,8 @@ static const struct resource *wdt_gpi_get_resource(struct platform_device *pdv,
return platform_get_resource_byname(pdv, type, buf);
}
-/* No hotplugging on the platform bus - use __init */
-static int __init wdt_gpi_probe(struct platform_device *pdv)
+/* No hotplugging on the platform bus - use __devinit */
+static int __devinit wdt_gpi_probe(struct platform_device *pdv)
{
int res;
const struct resource
@@ -373,7 +373,7 @@ static int __init wdt_gpi_probe(struct platform_device *pdv)
return res;
}
-static int __exit wdt_gpi_remove(struct platform_device *dev)
+static int __devexit wdt_gpi_remove(struct platform_device *dev)
{
int res;
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
index e31925ee8346..b57ac6b49147 100644
--- a/drivers/watchdog/s3c2410_wdt.c
+++ b/drivers/watchdog/s3c2410_wdt.c
@@ -68,15 +68,10 @@ MODULE_PARM_DESC(tmr_atboot,
__MODULE_STRING(CONFIG_S3C2410_WATCHDOG_ATBOOT));
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
-MODULE_PARM_DESC(soft_noboot, "Watchdog action, set to 1 to ignore reboots, 0 to reboot (default depends on ONLY_TESTING)");
+MODULE_PARM_DESC(soft_noboot, "Watchdog action, set to 1 to ignore reboots, "
+ "0 to reboot (default depends on ONLY_TESTING)");
MODULE_PARM_DESC(debug, "Watchdog debug, set to >1 for debug, (default 0)");
-
-typedef enum close_state {
- CLOSE_STATE_NOT,
- CLOSE_STATE_ALLOW = 0x4021
-} close_state_t;
-
static unsigned long open_lock;
static struct device *wdt_dev; /* platform device attached to */
static struct resource *wdt_mem;
@@ -84,7 +79,7 @@ static struct resource *wdt_irq;
static struct clk *wdt_clock;
static void __iomem *wdt_base;
static unsigned int wdt_count;
-static close_state_t allow_close;
+static char expect_close;
static DEFINE_SPINLOCK(wdt_lock);
/* watchdog control routines */
@@ -211,7 +206,7 @@ static int s3c2410wdt_open(struct inode *inode, struct file *file)
if (nowayout)
__module_get(THIS_MODULE);
- allow_close = CLOSE_STATE_NOT;
+ expect_close = 0;
/* start the timer */
s3c2410wdt_start();
@@ -225,13 +220,13 @@ static int s3c2410wdt_release(struct inode *inode, struct file *file)
* Lock it in if it's a module and we set nowayout
*/
- if (allow_close == CLOSE_STATE_ALLOW)
+ if (expect_close == 42)
s3c2410wdt_stop();
else {
dev_err(wdt_dev, "Unexpected close, not stopping watchdog\n");
s3c2410wdt_keepalive();
}
- allow_close = CLOSE_STATE_NOT;
+ expect_close = 0;
clear_bit(0, &open_lock);
return 0;
}
@@ -247,7 +242,7 @@ static ssize_t s3c2410wdt_write(struct file *file, const char __user *data,
size_t i;
/* In case it was set long ago */
- allow_close = CLOSE_STATE_NOT;
+ expect_close = 0;
for (i = 0; i != len; i++) {
char c;
@@ -255,7 +250,7 @@ static ssize_t s3c2410wdt_write(struct file *file, const char __user *data,
if (get_user(c, data + i))
return -EFAULT;
if (c == 'V')
- allow_close = CLOSE_STATE_ALLOW;
+ expect_close = 42;
}
}
s3c2410wdt_keepalive();
@@ -263,7 +258,7 @@ static ssize_t s3c2410wdt_write(struct file *file, const char __user *data,
return len;
}
-#define OPTIONS WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE
+#define OPTIONS (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE)
static const struct watchdog_info s3c2410_wdt_ident = {
.options = OPTIONS,
@@ -331,7 +326,7 @@ static irqreturn_t s3c2410wdt_irq(int irqno, void *param)
}
/* device interface */
-static int s3c2410wdt_probe(struct platform_device *pdev)
+static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
{
struct resource *res;
struct device *dev;
@@ -404,7 +399,8 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
"tmr_margin value out of range, default %d used\n",
CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME);
else
- dev_info(dev, "default timer value is out of range, cannot start\n");
+ dev_info(dev, "default timer value is out of range, "
+ "cannot start\n");
}
ret = misc_register(&s3c2410wdt_miscdev);
@@ -453,7 +449,7 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
return ret;
}
-static int s3c2410wdt_remove(struct platform_device *dev)
+static int __devexit s3c2410wdt_remove(struct platform_device *dev)
{
release_resource(wdt_mem);
kfree(wdt_mem);
@@ -515,7 +511,7 @@ static int s3c2410wdt_resume(struct platform_device *dev)
static struct platform_driver s3c2410wdt_driver = {
.probe = s3c2410wdt_probe,
- .remove = s3c2410wdt_remove,
+ .remove = __devexit_p(s3c2410wdt_remove),
.shutdown = s3c2410wdt_shutdown,
.suspend = s3c2410wdt_suspend,
.resume = s3c2410wdt_resume,
diff --git a/drivers/watchdog/sb_wdog.c b/drivers/watchdog/sb_wdog.c
index 38f5831c9291..9748eed73196 100644
--- a/drivers/watchdog/sb_wdog.c
+++ b/drivers/watchdog/sb_wdog.c
@@ -93,7 +93,7 @@ static int expect_close;
static const struct watchdog_info ident = {
.options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT |
- WDIOF_KEEPALIVEPING,
+ WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
.identity = "SiByte Watchdog",
};
@@ -269,9 +269,10 @@ irqreturn_t sbwdog_interrupt(int irq, void *addr)
* if it's the second watchdog timer, it's for those users
*/
if (wd_cfg_reg == user_dog)
- printk(KERN_CRIT
- "%s in danger of initiating system reset in %ld.%01ld seconds\n",
- ident.identity, wd_init / 1000000, (wd_init / 100000) % 10);
+ printk(KERN_CRIT "%s in danger of initiating system reset "
+ "in %ld.%01ld seconds\n",
+ ident.identity,
+ wd_init / 1000000, (wd_init / 100000) % 10);
else
cfg |= 1;
diff --git a/drivers/watchdog/sbc60xxwdt.c b/drivers/watchdog/sbc60xxwdt.c
index d1c390c7155c..626d0e8e56c3 100644
--- a/drivers/watchdog/sbc60xxwdt.c
+++ b/drivers/watchdog/sbc60xxwdt.c
@@ -372,8 +372,9 @@ static int __init sbc60xxwdt_init(void)
wdt_miscdev.minor, rc);
goto err_out_reboot;
}
- printk(KERN_INFO PFX "WDT driver for 60XX single board computer initialised. timeout=%d sec (nowayout=%d)\n",
- timeout, nowayout);
+ printk(KERN_INFO PFX
+ "WDT driver for 60XX single board computer initialised. "
+ "timeout=%d sec (nowayout=%d)\n", timeout, nowayout);
return 0;
diff --git a/drivers/watchdog/sbc8360.c b/drivers/watchdog/sbc8360.c
index b6e6799ec45d..68e2e2d6f73d 100644
--- a/drivers/watchdog/sbc8360.c
+++ b/drivers/watchdog/sbc8360.c
@@ -280,8 +280,8 @@ static int sbc8360_close(struct inode *inode, struct file *file)
if (expect_close == 42)
sbc8360_stop();
else
- printk(KERN_CRIT PFX
- "SBC8360 device closed unexpectedly. SBC8360 will not stop!\n");
+ printk(KERN_CRIT PFX "SBC8360 device closed unexpectedly. "
+ "SBC8360 will not stop!\n");
clear_bit(0, &sbc8360_is_open);
expect_close = 0;
diff --git a/drivers/watchdog/sbc_epx_c3.c b/drivers/watchdog/sbc_epx_c3.c
index e467ddcf796a..28f1214457bd 100644
--- a/drivers/watchdog/sbc_epx_c3.c
+++ b/drivers/watchdog/sbc_epx_c3.c
@@ -107,8 +107,7 @@ static long epx_c3_ioctl(struct file *file, unsigned int cmd,
int options, retval = -EINVAL;
int __user *argp = (void __user *)arg;
static const struct watchdog_info ident = {
- .options = WDIOF_KEEPALIVEPING |
- WDIOF_MAGICCLOSE,
+ .options = WDIOF_KEEPALIVEPING,
.firmware_version = 0,
.identity = "Winsystems EPX-C3 H/W Watchdog",
};
@@ -174,8 +173,8 @@ static struct notifier_block epx_c3_notifier = {
.notifier_call = epx_c3_notify_sys,
};
-static const char banner[] __initdata =
- KERN_INFO PFX "Hardware Watchdog Timer for Winsystems EPX-C3 SBC: 0.1\n";
+static const char banner[] __initdata = KERN_INFO PFX
+ "Hardware Watchdog Timer for Winsystems EPX-C3 SBC: 0.1\n";
static int __init watchdog_init(void)
{
@@ -219,6 +218,9 @@ module_init(watchdog_init);
module_exit(watchdog_exit);
MODULE_AUTHOR("Calin A. Culianu <calin@ajvar.org>");
-MODULE_DESCRIPTION("Hardware Watchdog Device for Winsystems EPX-C3 SBC. Note that there is no way to probe for this device -- so only use it if you are *sure* you are runnning on this specific SBC system from Winsystems! It writes to IO ports 0x1ee and 0x1ef!");
+MODULE_DESCRIPTION("Hardware Watchdog Device for Winsystems EPX-C3 SBC. "
+ "Note that there is no way to probe for this device -- "
+ "so only use it if you are *sure* you are runnning on this specific "
+ "SBC system from Winsystems! It writes to IO ports 0x1ee and 0x1ef!");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/scx200_wdt.c b/drivers/watchdog/scx200_wdt.c
index 9e19a10a5bb9..e67b76c0526c 100644
--- a/drivers/watchdog/scx200_wdt.c
+++ b/drivers/watchdog/scx200_wdt.c
@@ -108,7 +108,9 @@ static int scx200_wdt_open(struct inode *inode, struct file *file)
static int scx200_wdt_release(struct inode *inode, struct file *file)
{
if (expect_close != 42)
- printk(KERN_WARNING NAME ": watchdog device closed unexpectedly, will not disable the watchdog timer\n");
+ printk(KERN_WARNING NAME
+ ": watchdog device closed unexpectedly, "
+ "will not disable the watchdog timer\n");
else if (!nowayout)
scx200_wdt_disable();
expect_close = 0;
@@ -163,7 +165,8 @@ static long scx200_wdt_ioctl(struct file *file, unsigned int cmd,
static const struct watchdog_info ident = {
.identity = "NatSemi SCx200 Watchdog",
.firmware_version = 1,
- .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE,
};
int new_margin;
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c
index cdc7138be301..a03f84e5ee1f 100644
--- a/drivers/watchdog/shwdt.c
+++ b/drivers/watchdog/shwdt.c
@@ -494,7 +494,9 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
module_param(clock_division_ratio, int, 0);
-MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). (default=" __MODULE_STRING(clock_division_ratio) ")");
+MODULE_PARM_DESC(clock_division_ratio,
+ "Clock division ratio. Valid ranges are from 0x5 (1.31ms) "
+ "to 0x7 (5.25ms). (default=" __MODULE_STRING(clock_division_ratio) ")");
module_param(heartbeat, int, 0);
MODULE_PARM_DESC(heartbeat,
diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c
index ebcc9cea5e99..833f49f43d43 100644
--- a/drivers/watchdog/softdog.c
+++ b/drivers/watchdog/softdog.c
@@ -71,7 +71,9 @@ static int soft_noboot = 0;
#endif /* ONLY_TESTING */
module_param(soft_noboot, int, 0);
-MODULE_PARM_DESC(soft_noboot, "Softdog action, set to 1 to ignore reboots, 0 to reboot (default depends on ONLY_TESTING)");
+MODULE_PARM_DESC(soft_noboot,
+ "Softdog action, set to 1 to ignore reboots, 0 to reboot "
+ "(default depends on ONLY_TESTING)");
/*
* Our timer
@@ -264,7 +266,8 @@ static struct notifier_block softdog_notifier = {
.notifier_call = softdog_notify_sys,
};
-static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.07 initialized. soft_noboot=%d soft_margin=%d sec (nowayout= %d)\n";
+static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.07 "
+ "initialized. soft_noboot=%d soft_margin=%d sec (nowayout= %d)\n";
static int __init watchdog_init(void)
{
diff --git a/drivers/watchdog/w83697hf_wdt.c b/drivers/watchdog/w83697hf_wdt.c
index a9c7f352fcbf..af08972de506 100644
--- a/drivers/watchdog/w83697hf_wdt.c
+++ b/drivers/watchdog/w83697hf_wdt.c
@@ -413,7 +413,8 @@ static int __init wdt_init(void)
w83697hf_init();
if (early_disable) {
if (wdt_running())
- printk(KERN_WARNING PFX "Stopping previously enabled watchdog until userland kicks in\n");
+ printk(KERN_WARNING PFX "Stopping previously enabled "
+ "watchdog until userland kicks in\n");
wdt_disable();
}
diff --git a/drivers/watchdog/wdrtas.c b/drivers/watchdog/wdrtas.c
index a38fa4907c92..a4fe7a38d9b0 100644
--- a/drivers/watchdog/wdrtas.c
+++ b/drivers/watchdog/wdrtas.c
@@ -49,12 +49,7 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
MODULE_ALIAS_MISCDEV(TEMP_MINOR);
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
-static int wdrtas_nowayout = 1;
-#else
-static int wdrtas_nowayout = 0;
-#endif
-
+static int wdrtas_nowayout = WATCHDOG_NOWAYOUT;
static atomic_t wdrtas_miscdev_open = ATOMIC_INIT(0);
static char wdrtas_expect_close;
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
index 8ac9cddac575..cab100acf983 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -18,6 +18,16 @@ config XEN_SCRUB_PAGES
secure, but slightly less efficient.
If in doubt, say yes.
+config XEN_DEV_EVTCHN
+ tristate "Xen /dev/xen/evtchn device"
+ depends on XEN
+ default y
+ help
+ The evtchn driver allows a userspace process to triger event
+ channels and to receive notification of an event channel
+ firing.
+ If in doubt, say yes.
+
config XENFS
tristate "Xen filesystem"
depends on XEN
@@ -41,3 +51,13 @@ config XEN_COMPAT_XENFS
a xen platform.
If in doubt, say yes.
+config XEN_SYS_HYPERVISOR
+ bool "Create xen entries under /sys/hypervisor"
+ depends on XEN && SYSFS
+ select SYS_HYPERVISOR
+ default y
+ help
+ Create entries under /sys/hypervisor describing the Xen
+ hypervisor environment. When running native or in another
+ virtual environment, /sys/hypervisor will still be present,
+ but will have no xen contents. \ No newline at end of file
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index ff8accc9e103..ec2a39b1e26f 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -4,4 +4,6 @@ obj-y += xenbus/
obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o
obj-$(CONFIG_XEN_XENCOMM) += xencomm.o
obj-$(CONFIG_XEN_BALLOON) += balloon.o
-obj-$(CONFIG_XENFS) += xenfs/ \ No newline at end of file
+obj-$(CONFIG_XEN_DEV_EVTCHN) += evtchn.o
+obj-$(CONFIG_XENFS) += xenfs/
+obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o \ No newline at end of file
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index efa4b363ce72..f5bbd9e83416 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -513,7 +513,8 @@ static ssize_t show_target(struct sys_device *dev, struct sysdev_attribute *attr
char *buf)
{
return sprintf(buf, "%llu\n",
- (u64)balloon_stats.target_pages << PAGE_SHIFT);
+ (unsigned long long)balloon_stats.target_pages
+ << PAGE_SHIFT);
}
static ssize_t store_target(struct sys_device *dev,
diff --git a/drivers/xen/cpu_hotplug.c b/drivers/xen/cpu_hotplug.c
index 5f54c01c1568..bdfd584ad853 100644
--- a/drivers/xen/cpu_hotplug.c
+++ b/drivers/xen/cpu_hotplug.c
@@ -21,29 +21,41 @@ static void disable_hotplug_cpu(int cpu)
set_cpu_present(cpu, false);
}
-static void vcpu_hotplug(unsigned int cpu)
+static int vcpu_online(unsigned int cpu)
{
int err;
char dir[32], state[32];
- if (!cpu_possible(cpu))
- return;
-
sprintf(dir, "cpu/%u", cpu);
err = xenbus_scanf(XBT_NIL, dir, "availability", "%s", state);
if (err != 1) {
printk(KERN_ERR "XENBUS: Unable to read cpu state\n");
- return;
+ return err;
}
- if (strcmp(state, "online") == 0) {
+ if (strcmp(state, "online") == 0)
+ return 1;
+ else if (strcmp(state, "offline") == 0)
+ return 0;
+
+ printk(KERN_ERR "XENBUS: unknown state(%s) on CPU%d\n", state, cpu);
+ return -EINVAL;
+}
+static void vcpu_hotplug(unsigned int cpu)
+{
+ if (!cpu_possible(cpu))
+ return;
+
+ switch (vcpu_online(cpu)) {
+ case 1:
enable_hotplug_cpu(cpu);
- } else if (strcmp(state, "offline") == 0) {
+ break;
+ case 0:
(void)cpu_down(cpu);
disable_hotplug_cpu(cpu);
- } else {
- printk(KERN_ERR "XENBUS: unknown state(%s) on CPU%d\n",
- state, cpu);
+ break;
+ default:
+ break;
}
}
@@ -64,12 +76,20 @@ static void handle_vcpu_hotplug_event(struct xenbus_watch *watch,
static int setup_cpu_watcher(struct notifier_block *notifier,
unsigned long event, void *data)
{
+ int cpu;
static struct xenbus_watch cpu_watch = {
.node = "cpu",
.callback = handle_vcpu_hotplug_event};
(void)register_xenbus_watch(&cpu_watch);
+ for_each_possible_cpu(cpu) {
+ if (vcpu_online(cpu) == 0) {
+ (void)cpu_down(cpu);
+ cpu_clear(cpu, cpu_present_map);
+ }
+ }
+
return NOTIFY_DONE;
}
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 30963af5dba0..891d2e90753a 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -151,6 +151,12 @@ static unsigned int evtchn_from_irq(unsigned irq)
return info_for_irq(irq)->evtchn;
}
+unsigned irq_from_evtchn(unsigned int evtchn)
+{
+ return evtchn_to_irq[evtchn];
+}
+EXPORT_SYMBOL_GPL(irq_from_evtchn);
+
static enum ipi_vector ipi_from_irq(unsigned irq)
{
struct irq_info *info = info_for_irq(irq);
@@ -335,7 +341,7 @@ static int find_unbound_irq(void)
if (irq == nr_irqs)
panic("No available IRQ to bind to: increase nr_irqs!\n");
- desc = irq_to_desc_alloc_cpu(irq, 0);
+ desc = irq_to_desc_alloc_node(irq, 0);
if (WARN_ON(desc == NULL))
return -1;
@@ -688,13 +694,13 @@ void rebind_evtchn_irq(int evtchn, int irq)
}
/* Rebind an evtchn so that it gets delivered to a specific cpu */
-static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
+static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
{
struct evtchn_bind_vcpu bind_vcpu;
int evtchn = evtchn_from_irq(irq);
if (!VALID_EVTCHN(evtchn))
- return;
+ return -1;
/* Send future instances of this interrupt to other vcpu. */
bind_vcpu.port = evtchn;
@@ -707,13 +713,15 @@ static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
*/
if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0)
bind_evtchn_to_cpu(evtchn, tcpu);
-}
+ return 0;
+}
-static void set_affinity_irq(unsigned irq, const struct cpumask *dest)
+static int set_affinity_irq(unsigned irq, const struct cpumask *dest)
{
unsigned tcpu = cpumask_first(dest);
- rebind_irq_to_cpu(irq, tcpu);
+
+ return rebind_irq_to_cpu(irq, tcpu);
}
int resend_irq_on_evtchn(unsigned int irq)
diff --git a/drivers/xen/evtchn.c b/drivers/xen/evtchn.c
new file mode 100644
index 000000000000..af031950f9b1
--- /dev/null
+++ b/drivers/xen/evtchn.c
@@ -0,0 +1,507 @@
+/******************************************************************************
+ * evtchn.c
+ *
+ * Driver for receiving and demuxing event-channel signals.
+ *
+ * Copyright (c) 2004-2005, K A Fraser
+ * Multi-process extensions Copyright (c) 2004, Steven Smith
+ *
+ * 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; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/major.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <linux/poll.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/gfp.h>
+#include <linux/mutex.h>
+#include <linux/cpu.h>
+#include <xen/events.h>
+#include <xen/evtchn.h>
+#include <asm/xen/hypervisor.h>
+
+struct per_user_data {
+ struct mutex bind_mutex; /* serialize bind/unbind operations */
+
+ /* Notification ring, accessed via /dev/xen/evtchn. */
+#define EVTCHN_RING_SIZE (PAGE_SIZE / sizeof(evtchn_port_t))
+#define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1))
+ evtchn_port_t *ring;
+ unsigned int ring_cons, ring_prod, ring_overflow;
+ struct mutex ring_cons_mutex; /* protect against concurrent readers */
+
+ /* Processes wait on this queue when ring is empty. */
+ wait_queue_head_t evtchn_wait;
+ struct fasync_struct *evtchn_async_queue;
+ const char *name;
+};
+
+/* Who's bound to each port? */
+static struct per_user_data *port_user[NR_EVENT_CHANNELS];
+static DEFINE_SPINLOCK(port_user_lock); /* protects port_user[] and ring_prod */
+
+irqreturn_t evtchn_interrupt(int irq, void *data)
+{
+ unsigned int port = (unsigned long)data;
+ struct per_user_data *u;
+
+ spin_lock(&port_user_lock);
+
+ u = port_user[port];
+
+ disable_irq_nosync(irq);
+
+ if ((u->ring_prod - u->ring_cons) < EVTCHN_RING_SIZE) {
+ u->ring[EVTCHN_RING_MASK(u->ring_prod)] = port;
+ wmb(); /* Ensure ring contents visible */
+ if (u->ring_cons == u->ring_prod++) {
+ wake_up_interruptible(&u->evtchn_wait);
+ kill_fasync(&u->evtchn_async_queue,
+ SIGIO, POLL_IN);
+ }
+ } else {
+ u->ring_overflow = 1;
+ }
+
+ spin_unlock(&port_user_lock);
+
+ return IRQ_HANDLED;
+}
+
+static ssize_t evtchn_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ int rc;
+ unsigned int c, p, bytes1 = 0, bytes2 = 0;
+ struct per_user_data *u = file->private_data;
+
+ /* Whole number of ports. */
+ count &= ~(sizeof(evtchn_port_t)-1);
+
+ if (count == 0)
+ return 0;
+
+ if (count > PAGE_SIZE)
+ count = PAGE_SIZE;
+
+ for (;;) {
+ mutex_lock(&u->ring_cons_mutex);
+
+ rc = -EFBIG;
+ if (u->ring_overflow)
+ goto unlock_out;
+
+ c = u->ring_cons;
+ p = u->ring_prod;
+ if (c != p)
+ break;
+
+ mutex_unlock(&u->ring_cons_mutex);
+
+ if (file->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+
+ rc = wait_event_interruptible(u->evtchn_wait,
+ u->ring_cons != u->ring_prod);
+ if (rc)
+ return rc;
+ }
+
+ /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
+ if (((c ^ p) & EVTCHN_RING_SIZE) != 0) {
+ bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) *
+ sizeof(evtchn_port_t);
+ bytes2 = EVTCHN_RING_MASK(p) * sizeof(evtchn_port_t);
+ } else {
+ bytes1 = (p - c) * sizeof(evtchn_port_t);
+ bytes2 = 0;
+ }
+
+ /* Truncate chunks according to caller's maximum byte count. */
+ if (bytes1 > count) {
+ bytes1 = count;
+ bytes2 = 0;
+ } else if ((bytes1 + bytes2) > count) {
+ bytes2 = count - bytes1;
+ }
+
+ rc = -EFAULT;
+ rmb(); /* Ensure that we see the port before we copy it. */
+ if (copy_to_user(buf, &u->ring[EVTCHN_RING_MASK(c)], bytes1) ||
+ ((bytes2 != 0) &&
+ copy_to_user(&buf[bytes1], &u->ring[0], bytes2)))
+ goto unlock_out;
+
+ u->ring_cons += (bytes1 + bytes2) / sizeof(evtchn_port_t);
+ rc = bytes1 + bytes2;
+
+ unlock_out:
+ mutex_unlock(&u->ring_cons_mutex);
+ return rc;
+}
+
+static ssize_t evtchn_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ int rc, i;
+ evtchn_port_t *kbuf = (evtchn_port_t *)__get_free_page(GFP_KERNEL);
+ struct per_user_data *u = file->private_data;
+
+ if (kbuf == NULL)
+ return -ENOMEM;
+
+ /* Whole number of ports. */
+ count &= ~(sizeof(evtchn_port_t)-1);
+
+ rc = 0;
+ if (count == 0)
+ goto out;
+
+ if (count > PAGE_SIZE)
+ count = PAGE_SIZE;
+
+ rc = -EFAULT;
+ if (copy_from_user(kbuf, buf, count) != 0)
+ goto out;
+
+ spin_lock_irq(&port_user_lock);
+ for (i = 0; i < (count/sizeof(evtchn_port_t)); i++)
+ if ((kbuf[i] < NR_EVENT_CHANNELS) && (port_user[kbuf[i]] == u))
+ enable_irq(irq_from_evtchn(kbuf[i]));
+ spin_unlock_irq(&port_user_lock);
+
+ rc = count;
+
+ out:
+ free_page((unsigned long)kbuf);
+ return rc;
+}
+
+static int evtchn_bind_to_user(struct per_user_data *u, int port)
+{
+ int rc = 0;
+
+ /*
+ * Ports are never reused, so every caller should pass in a
+ * unique port.
+ *
+ * (Locking not necessary because we haven't registered the
+ * interrupt handler yet, and our caller has already
+ * serialized bind operations.)
+ */
+ BUG_ON(port_user[port] != NULL);
+ port_user[port] = u;
+
+ rc = bind_evtchn_to_irqhandler(port, evtchn_interrupt, IRQF_DISABLED,
+ u->name, (void *)(unsigned long)port);
+ if (rc >= 0)
+ rc = 0;
+
+ return rc;
+}
+
+static void evtchn_unbind_from_user(struct per_user_data *u, int port)
+{
+ int irq = irq_from_evtchn(port);
+
+ unbind_from_irqhandler(irq, (void *)(unsigned long)port);
+
+ /* make sure we unbind the irq handler before clearing the port */
+ barrier();
+
+ port_user[port] = NULL;
+}
+
+static long evtchn_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int rc;
+ struct per_user_data *u = file->private_data;
+ void __user *uarg = (void __user *) arg;
+
+ /* Prevent bind from racing with unbind */
+ mutex_lock(&u->bind_mutex);
+
+ switch (cmd) {
+ case IOCTL_EVTCHN_BIND_VIRQ: {
+ struct ioctl_evtchn_bind_virq bind;
+ struct evtchn_bind_virq bind_virq;
+
+ rc = -EFAULT;
+ if (copy_from_user(&bind, uarg, sizeof(bind)))
+ break;
+
+ bind_virq.virq = bind.virq;
+ bind_virq.vcpu = 0;
+ rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
+ &bind_virq);
+ if (rc != 0)
+ break;
+
+ rc = evtchn_bind_to_user(u, bind_virq.port);
+ if (rc == 0)
+ rc = bind_virq.port;
+ break;
+ }
+
+ case IOCTL_EVTCHN_BIND_INTERDOMAIN: {
+ struct ioctl_evtchn_bind_interdomain bind;
+ struct evtchn_bind_interdomain bind_interdomain;
+
+ rc = -EFAULT;
+ if (copy_from_user(&bind, uarg, sizeof(bind)))
+ break;
+
+ bind_interdomain.remote_dom = bind.remote_domain;
+ bind_interdomain.remote_port = bind.remote_port;
+ rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain,
+ &bind_interdomain);
+ if (rc != 0)
+ break;
+
+ rc = evtchn_bind_to_user(u, bind_interdomain.local_port);
+ if (rc == 0)
+ rc = bind_interdomain.local_port;
+ break;
+ }
+
+ case IOCTL_EVTCHN_BIND_UNBOUND_PORT: {
+ struct ioctl_evtchn_bind_unbound_port bind;
+ struct evtchn_alloc_unbound alloc_unbound;
+
+ rc = -EFAULT;
+ if (copy_from_user(&bind, uarg, sizeof(bind)))
+ break;
+
+ alloc_unbound.dom = DOMID_SELF;
+ alloc_unbound.remote_dom = bind.remote_domain;
+ rc = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
+ &alloc_unbound);
+ if (rc != 0)
+ break;
+
+ rc = evtchn_bind_to_user(u, alloc_unbound.port);
+ if (rc == 0)
+ rc = alloc_unbound.port;
+ break;
+ }
+
+ case IOCTL_EVTCHN_UNBIND: {
+ struct ioctl_evtchn_unbind unbind;
+
+ rc = -EFAULT;
+ if (copy_from_user(&unbind, uarg, sizeof(unbind)))
+ break;
+
+ rc = -EINVAL;
+ if (unbind.port >= NR_EVENT_CHANNELS)
+ break;
+
+ spin_lock_irq(&port_user_lock);
+
+ rc = -ENOTCONN;
+ if (port_user[unbind.port] != u) {
+ spin_unlock_irq(&port_user_lock);
+ break;
+ }
+
+ evtchn_unbind_from_user(u, unbind.port);
+
+ spin_unlock_irq(&port_user_lock);
+
+ rc = 0;
+ break;
+ }
+
+ case IOCTL_EVTCHN_NOTIFY: {
+ struct ioctl_evtchn_notify notify;
+
+ rc = -EFAULT;
+ if (copy_from_user(&notify, uarg, sizeof(notify)))
+ break;
+
+ if (notify.port >= NR_EVENT_CHANNELS) {
+ rc = -EINVAL;
+ } else if (port_user[notify.port] != u) {
+ rc = -ENOTCONN;
+ } else {
+ notify_remote_via_evtchn(notify.port);
+ rc = 0;
+ }
+ break;
+ }
+
+ case IOCTL_EVTCHN_RESET: {
+ /* Initialise the ring to empty. Clear errors. */
+ mutex_lock(&u->ring_cons_mutex);
+ spin_lock_irq(&port_user_lock);
+ u->ring_cons = u->ring_prod = u->ring_overflow = 0;
+ spin_unlock_irq(&port_user_lock);
+ mutex_unlock(&u->ring_cons_mutex);
+ rc = 0;
+ break;
+ }
+
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+ mutex_unlock(&u->bind_mutex);
+
+ return rc;
+}
+
+static unsigned int evtchn_poll(struct file *file, poll_table *wait)
+{
+ unsigned int mask = POLLOUT | POLLWRNORM;
+ struct per_user_data *u = file->private_data;
+
+ poll_wait(file, &u->evtchn_wait, wait);
+ if (u->ring_cons != u->ring_prod)
+ mask |= POLLIN | POLLRDNORM;
+ if (u->ring_overflow)
+ mask = POLLERR;
+ return mask;
+}
+
+static int evtchn_fasync(int fd, struct file *filp, int on)
+{
+ struct per_user_data *u = filp->private_data;
+ return fasync_helper(fd, filp, on, &u->evtchn_async_queue);
+}
+
+static int evtchn_open(struct inode *inode, struct file *filp)
+{
+ struct per_user_data *u;
+
+ u = kzalloc(sizeof(*u), GFP_KERNEL);
+ if (u == NULL)
+ return -ENOMEM;
+
+ u->name = kasprintf(GFP_KERNEL, "evtchn:%s", current->comm);
+ if (u->name == NULL) {
+ kfree(u);
+ return -ENOMEM;
+ }
+
+ init_waitqueue_head(&u->evtchn_wait);
+
+ u->ring = (evtchn_port_t *)__get_free_page(GFP_KERNEL);
+ if (u->ring == NULL) {
+ kfree(u->name);
+ kfree(u);
+ return -ENOMEM;
+ }
+
+ mutex_init(&u->bind_mutex);
+ mutex_init(&u->ring_cons_mutex);
+
+ filp->private_data = u;
+
+ return 0;
+}
+
+static int evtchn_release(struct inode *inode, struct file *filp)
+{
+ int i;
+ struct per_user_data *u = filp->private_data;
+
+ spin_lock_irq(&port_user_lock);
+
+ free_page((unsigned long)u->ring);
+
+ for (i = 0; i < NR_EVENT_CHANNELS; i++) {
+ if (port_user[i] != u)
+ continue;
+
+ evtchn_unbind_from_user(port_user[i], i);
+ }
+
+ spin_unlock_irq(&port_user_lock);
+
+ kfree(u->name);
+ kfree(u);
+
+ return 0;
+}
+
+static const struct file_operations evtchn_fops = {
+ .owner = THIS_MODULE,
+ .read = evtchn_read,
+ .write = evtchn_write,
+ .unlocked_ioctl = evtchn_ioctl,
+ .poll = evtchn_poll,
+ .fasync = evtchn_fasync,
+ .open = evtchn_open,
+ .release = evtchn_release,
+};
+
+static struct miscdevice evtchn_miscdev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "evtchn",
+ .fops = &evtchn_fops,
+};
+static int __init evtchn_init(void)
+{
+ int err;
+
+ if (!xen_domain())
+ return -ENODEV;
+
+ spin_lock_init(&port_user_lock);
+ memset(port_user, 0, sizeof(port_user));
+
+ /* Create '/dev/misc/evtchn'. */
+ err = misc_register(&evtchn_miscdev);
+ if (err != 0) {
+ printk(KERN_ALERT "Could not register /dev/misc/evtchn\n");
+ return err;
+ }
+
+ printk(KERN_INFO "Event-channel device installed.\n");
+
+ return 0;
+}
+
+static void __exit evtchn_cleanup(void)
+{
+ misc_deregister(&evtchn_miscdev);
+}
+
+module_init(evtchn_init);
+module_exit(evtchn_cleanup);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index 0d61db1e7b49..fddc2025dece 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -62,14 +62,15 @@ static int xen_suspend(void *data)
gnttab_resume();
xen_mm_unpin_all();
- sysdev_resume();
-
if (!*cancelled) {
xen_irq_resume();
xen_console_resume();
xen_timer_resume();
}
+ sysdev_resume();
+ device_power_up(PMSG_RESUME);
+
return 0;
}
@@ -97,9 +98,8 @@ static void do_suspend(void)
goto out;
}
- printk("suspending xenbus...\n");
- /* XXX use normal device tree? */
- xenbus_suspend();
+ printk(KERN_DEBUG "suspending xenstore...\n");
+ xs_suspend();
err = device_power_down(PMSG_SUSPEND);
if (err) {
@@ -115,9 +115,9 @@ static void do_suspend(void)
if (!cancelled) {
xen_arch_resume();
- xenbus_resume();
+ xs_resume();
} else
- xenbus_suspend_cancel();
+ xs_suspend_cancel();
device_power_up(PMSG_RESUME);
diff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c
new file mode 100644
index 000000000000..88a60e03ccf0
--- /dev/null
+++ b/drivers/xen/sys-hypervisor.c
@@ -0,0 +1,445 @@
+/*
+ * copyright (c) 2006 IBM Corporation
+ * Authored by: Mike D. Day <ncmike@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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kobject.h>
+
+#include <asm/xen/hypervisor.h>
+#include <asm/xen/hypercall.h>
+
+#include <xen/xenbus.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/version.h>
+
+#define HYPERVISOR_ATTR_RO(_name) \
+static struct hyp_sysfs_attr _name##_attr = __ATTR_RO(_name)
+
+#define HYPERVISOR_ATTR_RW(_name) \
+static struct hyp_sysfs_attr _name##_attr = \
+ __ATTR(_name, 0644, _name##_show, _name##_store)
+
+struct hyp_sysfs_attr {
+ struct attribute attr;
+ ssize_t (*show)(struct hyp_sysfs_attr *, char *);
+ ssize_t (*store)(struct hyp_sysfs_attr *, const char *, size_t);
+ void *hyp_attr_data;
+};
+
+static ssize_t type_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+ return sprintf(buffer, "xen\n");
+}
+
+HYPERVISOR_ATTR_RO(type);
+
+static int __init xen_sysfs_type_init(void)
+{
+ return sysfs_create_file(hypervisor_kobj, &type_attr.attr);
+}
+
+static void xen_sysfs_type_destroy(void)
+{
+ sysfs_remove_file(hypervisor_kobj, &type_attr.attr);
+}
+
+/* xen version attributes */
+static ssize_t major_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+ int version = HYPERVISOR_xen_version(XENVER_version, NULL);
+ if (version)
+ return sprintf(buffer, "%d\n", version >> 16);
+ return -ENODEV;
+}
+
+HYPERVISOR_ATTR_RO(major);
+
+static ssize_t minor_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+ int version = HYPERVISOR_xen_version(XENVER_version, NULL);
+ if (version)
+ return sprintf(buffer, "%d\n", version & 0xff);
+ return -ENODEV;
+}
+
+HYPERVISOR_ATTR_RO(minor);
+
+static ssize_t extra_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+ int ret = -ENOMEM;
+ char *extra;
+
+ extra = kmalloc(XEN_EXTRAVERSION_LEN, GFP_KERNEL);
+ if (extra) {
+ ret = HYPERVISOR_xen_version(XENVER_extraversion, extra);
+ if (!ret)
+ ret = sprintf(buffer, "%s\n", extra);
+ kfree(extra);
+ }
+
+ return ret;
+}
+
+HYPERVISOR_ATTR_RO(extra);
+
+static struct attribute *version_attrs[] = {
+ &major_attr.attr,
+ &minor_attr.attr,
+ &extra_attr.attr,
+ NULL
+};
+
+static struct attribute_group version_group = {
+ .name = "version",
+ .attrs = version_attrs,
+};
+
+static int __init xen_sysfs_version_init(void)
+{
+ return sysfs_create_group(hypervisor_kobj, &version_group);
+}
+
+static void xen_sysfs_version_destroy(void)
+{
+ sysfs_remove_group(hypervisor_kobj, &version_group);
+}
+
+/* UUID */
+
+static ssize_t uuid_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+ char *vm, *val;
+ int ret;
+ extern int xenstored_ready;
+
+ if (!xenstored_ready)
+ return -EBUSY;
+
+ vm = xenbus_read(XBT_NIL, "vm", "", NULL);
+ if (IS_ERR(vm))
+ return PTR_ERR(vm);
+ val = xenbus_read(XBT_NIL, vm, "uuid", NULL);
+ kfree(vm);
+ if (IS_ERR(val))
+ return PTR_ERR(val);
+ ret = sprintf(buffer, "%s\n", val);
+ kfree(val);
+ return ret;
+}
+
+HYPERVISOR_ATTR_RO(uuid);
+
+static int __init xen_sysfs_uuid_init(void)
+{
+ return sysfs_create_file(hypervisor_kobj, &uuid_attr.attr);
+}
+
+static void xen_sysfs_uuid_destroy(void)
+{
+ sysfs_remove_file(hypervisor_kobj, &uuid_attr.attr);
+}
+
+/* xen compilation attributes */
+
+static ssize_t compiler_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+ int ret = -ENOMEM;
+ struct xen_compile_info *info;
+
+ info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL);
+ if (info) {
+ ret = HYPERVISOR_xen_version(XENVER_compile_info, info);
+ if (!ret)
+ ret = sprintf(buffer, "%s\n", info->compiler);
+ kfree(info);
+ }
+
+ return ret;
+}
+
+HYPERVISOR_ATTR_RO(compiler);
+
+static ssize_t compiled_by_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+ int ret = -ENOMEM;
+ struct xen_compile_info *info;
+
+ info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL);
+ if (info) {
+ ret = HYPERVISOR_xen_version(XENVER_compile_info, info);
+ if (!ret)
+ ret = sprintf(buffer, "%s\n", info->compile_by);
+ kfree(info);
+ }
+
+ return ret;
+}
+
+HYPERVISOR_ATTR_RO(compiled_by);
+
+static ssize_t compile_date_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+ int ret = -ENOMEM;
+ struct xen_compile_info *info;
+
+ info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL);
+ if (info) {
+ ret = HYPERVISOR_xen_version(XENVER_compile_info, info);
+ if (!ret)
+ ret = sprintf(buffer, "%s\n", info->compile_date);
+ kfree(info);
+ }
+
+ return ret;
+}
+
+HYPERVISOR_ATTR_RO(compile_date);
+
+static struct attribute *xen_compile_attrs[] = {
+ &compiler_attr.attr,
+ &compiled_by_attr.attr,
+ &compile_date_attr.attr,
+ NULL
+};
+
+static struct attribute_group xen_compilation_group = {
+ .name = "compilation",
+ .attrs = xen_compile_attrs,
+};
+
+int __init static xen_compilation_init(void)
+{
+ return sysfs_create_group(hypervisor_kobj, &xen_compilation_group);
+}
+
+static void xen_compilation_destroy(void)
+{
+ sysfs_remove_group(hypervisor_kobj, &xen_compilation_group);
+}
+
+/* xen properties info */
+
+static ssize_t capabilities_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+ int ret = -ENOMEM;
+ char *caps;
+
+ caps = kmalloc(XEN_CAPABILITIES_INFO_LEN, GFP_KERNEL);
+ if (caps) {
+ ret = HYPERVISOR_xen_version(XENVER_capabilities, caps);
+ if (!ret)
+ ret = sprintf(buffer, "%s\n", caps);
+ kfree(caps);
+ }
+
+ return ret;
+}
+
+HYPERVISOR_ATTR_RO(capabilities);
+
+static ssize_t changeset_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+ int ret = -ENOMEM;
+ char *cset;
+
+ cset = kmalloc(XEN_CHANGESET_INFO_LEN, GFP_KERNEL);
+ if (cset) {
+ ret = HYPERVISOR_xen_version(XENVER_changeset, cset);
+ if (!ret)
+ ret = sprintf(buffer, "%s\n", cset);
+ kfree(cset);
+ }
+
+ return ret;
+}
+
+HYPERVISOR_ATTR_RO(changeset);
+
+static ssize_t virtual_start_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+ int ret = -ENOMEM;
+ struct xen_platform_parameters *parms;
+
+ parms = kmalloc(sizeof(struct xen_platform_parameters), GFP_KERNEL);
+ if (parms) {
+ ret = HYPERVISOR_xen_version(XENVER_platform_parameters,
+ parms);
+ if (!ret)
+ ret = sprintf(buffer, "%lx\n", parms->virt_start);
+ kfree(parms);
+ }
+
+ return ret;
+}
+
+HYPERVISOR_ATTR_RO(virtual_start);
+
+static ssize_t pagesize_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+ int ret;
+
+ ret = HYPERVISOR_xen_version(XENVER_pagesize, NULL);
+ if (ret > 0)
+ ret = sprintf(buffer, "%x\n", ret);
+
+ return ret;
+}
+
+HYPERVISOR_ATTR_RO(pagesize);
+
+static ssize_t xen_feature_show(int index, char *buffer)
+{
+ ssize_t ret;
+ struct xen_feature_info info;
+
+ info.submap_idx = index;
+ ret = HYPERVISOR_xen_version(XENVER_get_features, &info);
+ if (!ret)
+ ret = sprintf(buffer, "%08x", info.submap);
+
+ return ret;
+}
+
+static ssize_t features_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+ ssize_t len;
+ int i;
+
+ len = 0;
+ for (i = XENFEAT_NR_SUBMAPS-1; i >= 0; i--) {
+ int ret = xen_feature_show(i, buffer + len);
+ if (ret < 0) {
+ if (len == 0)
+ len = ret;
+ break;
+ }
+ len += ret;
+ }
+ if (len > 0)
+ buffer[len++] = '\n';
+
+ return len;
+}
+
+HYPERVISOR_ATTR_RO(features);
+
+static struct attribute *xen_properties_attrs[] = {
+ &capabilities_attr.attr,
+ &changeset_attr.attr,
+ &virtual_start_attr.attr,
+ &pagesize_attr.attr,
+ &features_attr.attr,
+ NULL
+};
+
+static struct attribute_group xen_properties_group = {
+ .name = "properties",
+ .attrs = xen_properties_attrs,
+};
+
+static int __init xen_properties_init(void)
+{
+ return sysfs_create_group(hypervisor_kobj, &xen_properties_group);
+}
+
+static void xen_properties_destroy(void)
+{
+ sysfs_remove_group(hypervisor_kobj, &xen_properties_group);
+}
+
+static int __init hyper_sysfs_init(void)
+{
+ int ret;
+
+ if (!xen_domain())
+ return -ENODEV;
+
+ ret = xen_sysfs_type_init();
+ if (ret)
+ goto out;
+ ret = xen_sysfs_version_init();
+ if (ret)
+ goto version_out;
+ ret = xen_compilation_init();
+ if (ret)
+ goto comp_out;
+ ret = xen_sysfs_uuid_init();
+ if (ret)
+ goto uuid_out;
+ ret = xen_properties_init();
+ if (ret)
+ goto prop_out;
+
+ goto out;
+
+prop_out:
+ xen_sysfs_uuid_destroy();
+uuid_out:
+ xen_compilation_destroy();
+comp_out:
+ xen_sysfs_version_destroy();
+version_out:
+ xen_sysfs_type_destroy();
+out:
+ return ret;
+}
+
+static void __exit hyper_sysfs_exit(void)
+{
+ xen_properties_destroy();
+ xen_compilation_destroy();
+ xen_sysfs_uuid_destroy();
+ xen_sysfs_version_destroy();
+ xen_sysfs_type_destroy();
+
+}
+module_init(hyper_sysfs_init);
+module_exit(hyper_sysfs_exit);
+
+static ssize_t hyp_sysfs_show(struct kobject *kobj,
+ struct attribute *attr,
+ char *buffer)
+{
+ struct hyp_sysfs_attr *hyp_attr;
+ hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr);
+ if (hyp_attr->show)
+ return hyp_attr->show(hyp_attr, buffer);
+ return 0;
+}
+
+static ssize_t hyp_sysfs_store(struct kobject *kobj,
+ struct attribute *attr,
+ const char *buffer,
+ size_t len)
+{
+ struct hyp_sysfs_attr *hyp_attr;
+ hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr);
+ if (hyp_attr->store)
+ return hyp_attr->store(hyp_attr, buffer, len);
+ return 0;
+}
+
+static struct sysfs_ops hyp_sysfs_ops = {
+ .show = hyp_sysfs_show,
+ .store = hyp_sysfs_store,
+};
+
+static struct kobj_type hyp_sysfs_kobj_type = {
+ .sysfs_ops = &hyp_sysfs_ops,
+};
+
+static int __init hypervisor_subsys_init(void)
+{
+ if (!xen_domain())
+ return -ENODEV;
+
+ hypervisor_kobj->ktype = &hyp_sysfs_kobj_type;
+ return 0;
+}
+device_initcall(hypervisor_subsys_init);
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
index 773d1cf23283..d42e25d5968d 100644
--- a/drivers/xen/xenbus/xenbus_probe.c
+++ b/drivers/xen/xenbus/xenbus_probe.c
@@ -71,6 +71,9 @@ static int xenbus_probe_frontend(const char *type, const char *name);
static void xenbus_dev_shutdown(struct device *_dev);
+static int xenbus_dev_suspend(struct device *dev, pm_message_t state);
+static int xenbus_dev_resume(struct device *dev);
+
/* If something in array of ids matches this device, return it. */
static const struct xenbus_device_id *
match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev)
@@ -188,6 +191,9 @@ static struct xen_bus_type xenbus_frontend = {
.remove = xenbus_dev_remove,
.shutdown = xenbus_dev_shutdown,
.dev_attrs = xenbus_dev_attrs,
+
+ .suspend = xenbus_dev_suspend,
+ .resume = xenbus_dev_resume,
},
};
@@ -654,6 +660,7 @@ void xenbus_dev_changed(const char *node, struct xen_bus_type *bus)
kfree(root);
}
+EXPORT_SYMBOL_GPL(xenbus_dev_changed);
static void frontend_changed(struct xenbus_watch *watch,
const char **vec, unsigned int len)
@@ -669,7 +676,7 @@ static struct xenbus_watch fe_watch = {
.callback = frontend_changed,
};
-static int suspend_dev(struct device *dev, void *data)
+static int xenbus_dev_suspend(struct device *dev, pm_message_t state)
{
int err = 0;
struct xenbus_driver *drv;
@@ -682,35 +689,14 @@ static int suspend_dev(struct device *dev, void *data)
drv = to_xenbus_driver(dev->driver);
xdev = container_of(dev, struct xenbus_device, dev);
if (drv->suspend)
- err = drv->suspend(xdev);
+ err = drv->suspend(xdev, state);
if (err)
printk(KERN_WARNING
"xenbus: suspend %s failed: %i\n", dev_name(dev), err);
return 0;
}
-static int suspend_cancel_dev(struct device *dev, void *data)
-{
- int err = 0;
- struct xenbus_driver *drv;
- struct xenbus_device *xdev;
-
- DPRINTK("");
-
- if (dev->driver == NULL)
- return 0;
- drv = to_xenbus_driver(dev->driver);
- xdev = container_of(dev, struct xenbus_device, dev);
- if (drv->suspend_cancel)
- err = drv->suspend_cancel(xdev);
- if (err)
- printk(KERN_WARNING
- "xenbus: suspend_cancel %s failed: %i\n",
- dev_name(dev), err);
- return 0;
-}
-
-static int resume_dev(struct device *dev, void *data)
+static int xenbus_dev_resume(struct device *dev)
{
int err;
struct xenbus_driver *drv;
@@ -755,33 +741,6 @@ static int resume_dev(struct device *dev, void *data)
return 0;
}
-void xenbus_suspend(void)
-{
- DPRINTK("");
-
- bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev);
- xenbus_backend_suspend(suspend_dev);
- xs_suspend();
-}
-EXPORT_SYMBOL_GPL(xenbus_suspend);
-
-void xenbus_resume(void)
-{
- xb_init_comms();
- xs_resume();
- bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev);
- xenbus_backend_resume(resume_dev);
-}
-EXPORT_SYMBOL_GPL(xenbus_resume);
-
-void xenbus_suspend_cancel(void)
-{
- xs_suspend_cancel();
- bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_cancel_dev);
- xenbus_backend_resume(suspend_cancel_dev);
-}
-EXPORT_SYMBOL_GPL(xenbus_suspend_cancel);
-
/* A flag to determine if xenstored is 'ready' (i.e. has started) */
int xenstored_ready = 0;
diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c
index e325eab4724d..eab33f1dbdf7 100644
--- a/drivers/xen/xenbus/xenbus_xs.c
+++ b/drivers/xen/xenbus/xenbus_xs.c
@@ -673,6 +673,8 @@ void xs_resume(void)
struct xenbus_watch *watch;
char token[sizeof(watch) * 2 + 1];
+ xb_init_comms();
+
mutex_unlock(&xs_state.response_mutex);
mutex_unlock(&xs_state.request_mutex);
up_write(&xs_state.transaction_mutex);
diff --git a/drivers/xen/xenfs/super.c b/drivers/xen/xenfs/super.c
index 515741a8e6b8..6559e0c752ce 100644
--- a/drivers/xen/xenfs/super.c
+++ b/drivers/xen/xenfs/super.c
@@ -20,10 +20,27 @@
MODULE_DESCRIPTION("Xen filesystem");
MODULE_LICENSE("GPL");
+static ssize_t capabilities_read(struct file *file, char __user *buf,
+ size_t size, loff_t *off)
+{
+ char *tmp = "";
+
+ if (xen_initial_domain())
+ tmp = "control_d\n";
+
+ return simple_read_from_buffer(buf, size, off, tmp, strlen(tmp));
+}
+
+static const struct file_operations capabilities_file_ops = {
+ .read = capabilities_read,
+};
+
static int xenfs_fill_super(struct super_block *sb, void *data, int silent)
{
static struct tree_descr xenfs_files[] = {
- [2] = {"xenbus", &xenbus_file_ops, S_IRUSR|S_IWUSR},
+ [1] = {},
+ { "xenbus", &xenbus_file_ops, S_IRUSR|S_IWUSR },
+ { "capabilities", &capabilities_file_ops, S_IRUGO },
{""},
};
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 5f8ab8adb5f5..ab5547ff29a1 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -37,6 +37,7 @@
#include <linux/mount.h>
#include <linux/idr.h>
#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <net/9p/9p.h>
#include <net/9p/client.h>
@@ -155,6 +156,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
root = d_alloc_root(inode);
if (!root) {
+ iput(inode);
retval = -ENOMEM;
goto release_sb;
}
@@ -173,10 +175,7 @@ P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n");
return 0;
release_sb:
- if (sb) {
- up_write(&sb->s_umount);
- deactivate_super(sb);
- }
+ deactivate_locked_super(sb);
free_stat:
kfree(st);
@@ -230,9 +229,12 @@ static int v9fs_show_options(struct seq_file *m, struct vfsmount *mnt)
static void
v9fs_umount_begin(struct super_block *sb)
{
- struct v9fs_session_info *v9ses = sb->s_fs_info;
+ struct v9fs_session_info *v9ses;
+ lock_kernel();
+ v9ses = sb->s_fs_info;
v9fs_session_cancel(v9ses);
+ unlock_kernel();
}
static const struct super_operations v9fs_super_ops = {
diff --git a/fs/Kconfig b/fs/Kconfig
index 9f7270f36b2a..525da2e8f73b 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -62,6 +62,16 @@ source "fs/autofs/Kconfig"
source "fs/autofs4/Kconfig"
source "fs/fuse/Kconfig"
+config CUSE
+ tristate "Character device in Userpace support"
+ depends on FUSE_FS
+ help
+ This FUSE extension allows character devices to be
+ implemented in userspace.
+
+ If you want to develop or use userspace character device
+ based on CUSE, answer Y or M.
+
config GENERIC_ACL
bool
select FS_POSIX_ACL
diff --git a/fs/adfs/super.c b/fs/adfs/super.c
index dd9becca4241..0ec5aaf47aa7 100644
--- a/fs/adfs/super.c
+++ b/fs/adfs/super.c
@@ -132,11 +132,15 @@ static void adfs_put_super(struct super_block *sb)
int i;
struct adfs_sb_info *asb = ADFS_SB(sb);
+ lock_kernel();
+
for (i = 0; i < asb->s_map_size; i++)
brelse(asb->s_map[i].dm_bh);
kfree(asb->s_map);
kfree(asb);
sb->s_fs_info = NULL;
+
+ unlock_kernel();
}
static int adfs_show_options(struct seq_file *seq, struct vfsmount *mnt)
diff --git a/fs/affs/super.c b/fs/affs/super.c
index 5ce695e707fe..d7386462a8e7 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -29,6 +29,8 @@ affs_put_super(struct super_block *sb)
struct affs_sb_info *sbi = AFFS_SB(sb);
pr_debug("AFFS: put_super()\n");
+ lock_kernel();
+
if (!(sb->s_flags & MS_RDONLY)) {
AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->bm_flag = cpu_to_be32(1);
secs_to_datestamp(get_seconds(),
@@ -42,7 +44,8 @@ affs_put_super(struct super_block *sb)
affs_brelse(sbi->s_root_bh);
kfree(sbi);
sb->s_fs_info = NULL;
- return;
+
+ unlock_kernel();
}
static void
@@ -507,8 +510,7 @@ affs_remount(struct super_block *sb, int *flags, char *data)
kfree(new_opts);
return -EINVAL;
}
- kfree(sb->s_options);
- sb->s_options = new_opts;
+ replace_mount_options(sb, new_opts);
sbi->s_flags = mount_flags;
sbi->s_mode = mode;
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 7a1d942ef68d..0149dab365e7 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -102,6 +102,7 @@ int afs_release(struct inode *inode, struct file *file)
return 0;
}
+#ifdef CONFIG_AFS_FSCACHE
/*
* deal with notification that a page was read from the cache
*/
@@ -117,6 +118,7 @@ static void afs_file_readpage_read_complete(struct page *page,
SetPageUptodate(page);
unlock_page(page);
}
+#endif
/*
* AFS read page from file, directory or symlink
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index 2b9e2d03a390..c52be53f6946 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -244,7 +244,7 @@ static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd)
case -EBUSY:
/* someone else made a mount here whilst we were busy */
while (d_mountpoint(nd->path.dentry) &&
- follow_down(&nd->path.mnt, &nd->path.dentry))
+ follow_down(&nd->path))
;
err = 0;
default:
diff --git a/fs/afs/super.c b/fs/afs/super.c
index aee239a048cb..ad0514d0115f 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -405,21 +405,20 @@ static int afs_get_sb(struct file_system_type *fs_type,
sb->s_flags = flags;
ret = afs_fill_super(sb, &params);
if (ret < 0) {
- up_write(&sb->s_umount);
- deactivate_super(sb);
+ deactivate_locked_super(sb);
goto error;
}
- sb->s_options = new_opts;
+ save_mount_options(sb, new_opts);
sb->s_flags |= MS_ACTIVE;
} else {
_debug("reuse");
- kfree(new_opts);
ASSERTCMP(sb->s_flags, &, MS_ACTIVE);
}
simple_set_mnt(mnt, sb);
afs_put_volume(params.volume);
afs_put_cell(params.cell);
+ kfree(new_opts);
_leave(" = 0 [%p]", sb);
return 0;
@@ -441,8 +440,12 @@ static void afs_put_super(struct super_block *sb)
_enter("");
+ lock_kernel();
+
afs_put_volume(as->volume);
+ unlock_kernel();
+
_leave("");
}
diff --git a/fs/autofs/dirhash.c b/fs/autofs/dirhash.c
index bf8c8af98004..2316e944a109 100644
--- a/fs/autofs/dirhash.c
+++ b/fs/autofs/dirhash.c
@@ -39,10 +39,12 @@ struct autofs_dir_ent *autofs_expire(struct super_block *sb,
{
struct autofs_dirhash *dh = &sbi->dirhash;
struct autofs_dir_ent *ent;
- struct dentry *dentry;
unsigned long timeout = sbi->exp_timeout;
while (1) {
+ struct path path;
+ int umount_ok;
+
if ( list_empty(&dh->expiry_head) || sbi->catatonic )
return NULL; /* No entries */
/* We keep the list sorted by last_usage and want old stuff */
@@ -57,17 +59,17 @@ struct autofs_dir_ent *autofs_expire(struct super_block *sb,
return ent; /* Symlinks are always expirable */
/* Get the dentry for the autofs subdirectory */
- dentry = ent->dentry;
+ path.dentry = ent->dentry;
- if ( !dentry ) {
+ if (!path.dentry) {
/* Should only happen in catatonic mode */
printk("autofs: dentry == NULL but inode range is directory, entry %s\n", ent->name);
autofs_delete_usage(ent);
continue;
}
- if ( !dentry->d_inode ) {
- dput(dentry);
+ if (!path.dentry->d_inode) {
+ dput(path.dentry);
printk("autofs: negative dentry on expiry queue: %s\n",
ent->name);
autofs_delete_usage(ent);
@@ -76,29 +78,28 @@ struct autofs_dir_ent *autofs_expire(struct super_block *sb,
/* Make sure entry is mounted and unused; note that dentry will
point to the mounted-on-top root. */
- if (!S_ISDIR(dentry->d_inode->i_mode)||!d_mountpoint(dentry)) {
+ if (!S_ISDIR(path.dentry->d_inode->i_mode) ||
+ !d_mountpoint(path.dentry)) {
DPRINTK(("autofs: not expirable (not a mounted directory): %s\n", ent->name));
continue;
}
- mntget(mnt);
- dget(dentry);
- if (!follow_down(&mnt, &dentry)) {
- dput(dentry);
- mntput(mnt);
+ path.mnt = mnt;
+ path_get(&path);
+ if (!follow_down(&path)) {
+ path_put(&path);
DPRINTK(("autofs: not expirable (not a mounted directory): %s\n", ent->name));
continue;
}
- while (d_mountpoint(dentry) && follow_down(&mnt, &dentry))
+ while (d_mountpoint(path.dentry) && follow_down(&path));
;
- dput(dentry);
+ umount_ok = may_umount(path.mnt);
+ path_put(&path);
- if ( may_umount(mnt) ) {
- mntput(mnt);
+ if (umount_ok) {
DPRINTK(("autofs: signaling expire on %s\n", ent->name));
return ent; /* Expirable! */
}
DPRINTK(("autofs: didn't expire due to may_umount: %s\n", ent->name));
- mntput(mnt);
}
return NULL; /* No expirable entries */
}
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index b7ff33c63101..8f7cdde41733 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -223,12 +223,12 @@ int autofs4_wait(struct autofs_sb_info *,struct dentry *, enum autofs_notify);
int autofs4_wait_release(struct autofs_sb_info *,autofs_wqt_t,int);
void autofs4_catatonic_mode(struct autofs_sb_info *);
-static inline int autofs4_follow_mount(struct vfsmount **mnt, struct dentry **dentry)
+static inline int autofs4_follow_mount(struct path *path)
{
int res = 0;
- while (d_mountpoint(*dentry)) {
- int followed = follow_down(mnt, dentry);
+ while (d_mountpoint(path->dentry)) {
+ int followed = follow_down(path);
if (!followed)
break;
res = 1;
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c
index 9e5ae8a4f5c8..f3da2eb51f56 100644
--- a/fs/autofs4/dev-ioctl.c
+++ b/fs/autofs4/dev-ioctl.c
@@ -54,11 +54,10 @@ static int check_name(const char *name)
* Check a string doesn't overrun the chunk of
* memory we copied from user land.
*/
-static int invalid_str(char *str, void *end)
+static int invalid_str(char *str, size_t size)
{
- while ((void *) str <= end)
- if (!*str++)
- return 0;
+ if (memchr(str, 0, size))
+ return 0;
return -EINVAL;
}
@@ -138,8 +137,7 @@ static int validate_dev_ioctl(int cmd, struct autofs_dev_ioctl *param)
}
if (param->size > sizeof(*param)) {
- err = invalid_str(param->path,
- (void *) ((size_t) param + param->size));
+ err = invalid_str(param->path, param->size - sizeof(*param));
if (err) {
AUTOFS_WARN(
"path string terminator missing for cmd(0x%08x)",
@@ -194,77 +192,42 @@ static int autofs_dev_ioctl_protosubver(struct file *fp,
return 0;
}
-/*
- * Walk down the mount stack looking for an autofs mount that
- * has the requested device number (aka. new_encode_dev(sb->s_dev).
- */
-static int autofs_dev_ioctl_find_super(struct nameidata *nd, dev_t devno)
+static int find_autofs_mount(const char *pathname,
+ struct path *res,
+ int test(struct path *path, void *data),
+ void *data)
{
- struct dentry *dentry;
- struct inode *inode;
- struct super_block *sb;
- dev_t s_dev;
- unsigned int err;
-
+ struct path path;
+ int err = kern_path(pathname, 0, &path);
+ if (err)
+ return err;
err = -ENOENT;
-
- /* Lookup the dentry name at the base of our mount point */
- dentry = d_lookup(nd->path.dentry, &nd->last);
- if (!dentry)
- goto out;
-
- dput(nd->path.dentry);
- nd->path.dentry = dentry;
-
- /* And follow the mount stack looking for our autofs mount */
- while (follow_down(&nd->path.mnt, &nd->path.dentry)) {
- inode = nd->path.dentry->d_inode;
- if (!inode)
- break;
-
- sb = inode->i_sb;
- s_dev = new_encode_dev(sb->s_dev);
- if (devno == s_dev) {
- if (sb->s_magic == AUTOFS_SUPER_MAGIC) {
+ while (path.dentry == path.mnt->mnt_root) {
+ if (path.mnt->mnt_sb->s_magic == AUTOFS_SUPER_MAGIC) {
+ if (test(&path, data)) {
+ path_get(&path);
+ if (!err) /* already found some */
+ path_put(res);
+ *res = path;
err = 0;
- break;
}
}
+ if (!follow_up(&path))
+ break;
}
-out:
+ path_put(&path);
return err;
}
-/*
- * Walk down the mount stack looking for an autofs mount that
- * has the requested mount type (ie. indirect, direct or offset).
- */
-static int autofs_dev_ioctl_find_sbi_type(struct nameidata *nd, unsigned int type)
+static int test_by_dev(struct path *path, void *p)
{
- struct dentry *dentry;
- struct autofs_info *ino;
- unsigned int err;
-
- err = -ENOENT;
-
- /* Lookup the dentry name at the base of our mount point */
- dentry = d_lookup(nd->path.dentry, &nd->last);
- if (!dentry)
- goto out;
-
- dput(nd->path.dentry);
- nd->path.dentry = dentry;
+ return path->mnt->mnt_sb->s_dev == *(dev_t *)p;
+}
- /* And follow the mount stack looking for our autofs mount */
- while (follow_down(&nd->path.mnt, &nd->path.dentry)) {
- ino = autofs4_dentry_ino(nd->path.dentry);
- if (ino && ino->sbi->type & type) {
- err = 0;
- break;
- }
- }
-out:
- return err;
+static int test_by_type(struct path *path, void *p)
+{
+ struct autofs_info *ino = autofs4_dentry_ino(path->dentry);
+ return ino && ino->sbi->type & *(unsigned *)p;
}
static void autofs_dev_ioctl_fd_install(unsigned int fd, struct file *file)
@@ -285,31 +248,25 @@ static void autofs_dev_ioctl_fd_install(unsigned int fd, struct file *file)
* Open a file descriptor on the autofs mount point corresponding
* to the given path and device number (aka. new_encode_dev(sb->s_dev)).
*/
-static int autofs_dev_ioctl_open_mountpoint(const char *path, dev_t devid)
+static int autofs_dev_ioctl_open_mountpoint(const char *name, dev_t devid)
{
- struct file *filp;
- struct nameidata nd;
int err, fd;
fd = get_unused_fd();
if (likely(fd >= 0)) {
- /* Get nameidata of the parent directory */
- err = path_lookup(path, LOOKUP_PARENT, &nd);
+ struct file *filp;
+ struct path path;
+
+ err = find_autofs_mount(name, &path, test_by_dev, &devid);
if (err)
goto out;
/*
- * Search down, within the parent, looking for an
- * autofs super block that has the device number
+ * Find autofs super block that has the device number
* corresponding to the autofs fs we want to open.
*/
- err = autofs_dev_ioctl_find_super(&nd, devid);
- if (err) {
- path_put(&nd.path);
- goto out;
- }
- filp = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY,
+ filp = dentry_open(path.dentry, path.mnt, O_RDONLY,
current_cred());
if (IS_ERR(filp)) {
err = PTR_ERR(filp);
@@ -342,7 +299,7 @@ static int autofs_dev_ioctl_openmount(struct file *fp,
param->ioctlfd = -1;
path = param->path;
- devid = param->openmount.devid;
+ devid = new_decode_dev(param->openmount.devid);
err = 0;
fd = autofs_dev_ioctl_open_mountpoint(path, devid);
@@ -477,8 +434,7 @@ static int autofs_dev_ioctl_requester(struct file *fp,
struct autofs_dev_ioctl *param)
{
struct autofs_info *ino;
- struct nameidata nd;
- const char *path;
+ struct path path;
dev_t devid;
int err = -ENOENT;
@@ -487,32 +443,24 @@ static int autofs_dev_ioctl_requester(struct file *fp,
goto out;
}
- path = param->path;
devid = sbi->sb->s_dev;
param->requester.uid = param->requester.gid = -1;
- /* Get nameidata of the parent directory */
- err = path_lookup(path, LOOKUP_PARENT, &nd);
+ err = find_autofs_mount(param->path, &path, test_by_dev, &devid);
if (err)
goto out;
- err = autofs_dev_ioctl_find_super(&nd, devid);
- if (err)
- goto out_release;
-
- ino = autofs4_dentry_ino(nd.path.dentry);
+ ino = autofs4_dentry_ino(path.dentry);
if (ino) {
err = 0;
- autofs4_expire_wait(nd.path.dentry);
+ autofs4_expire_wait(path.dentry);
spin_lock(&sbi->fs_lock);
param->requester.uid = ino->uid;
param->requester.gid = ino->gid;
spin_unlock(&sbi->fs_lock);
}
-
-out_release:
- path_put(&nd.path);
+ path_put(&path);
out:
return err;
}
@@ -571,8 +519,8 @@ static int autofs_dev_ioctl_ismountpoint(struct file *fp,
struct autofs_sb_info *sbi,
struct autofs_dev_ioctl *param)
{
- struct nameidata nd;
- const char *path;
+ struct path path;
+ const char *name;
unsigned int type;
unsigned int devid, magic;
int err = -ENOENT;
@@ -582,71 +530,46 @@ static int autofs_dev_ioctl_ismountpoint(struct file *fp,
goto out;
}
- path = param->path;
+ name = param->path;
type = param->ismountpoint.in.type;
param->ismountpoint.out.devid = devid = 0;
param->ismountpoint.out.magic = magic = 0;
if (!fp || param->ioctlfd == -1) {
- if (autofs_type_any(type)) {
- struct super_block *sb;
-
- err = path_lookup(path, LOOKUP_FOLLOW, &nd);
- if (err)
- goto out;
-
- sb = nd.path.dentry->d_sb;
- devid = new_encode_dev(sb->s_dev);
- } else {
- struct autofs_info *ino;
-
- err = path_lookup(path, LOOKUP_PARENT, &nd);
- if (err)
- goto out;
-
- err = autofs_dev_ioctl_find_sbi_type(&nd, type);
- if (err)
- goto out_release;
-
- ino = autofs4_dentry_ino(nd.path.dentry);
- devid = autofs4_get_dev(ino->sbi);
- }
-
+ if (autofs_type_any(type))
+ err = kern_path(name, LOOKUP_FOLLOW, &path);
+ else
+ err = find_autofs_mount(name, &path, test_by_type, &type);
+ if (err)
+ goto out;
+ devid = new_encode_dev(path.mnt->mnt_sb->s_dev);
err = 0;
- if (nd.path.dentry->d_inode &&
- nd.path.mnt->mnt_root == nd.path.dentry) {
+ if (path.dentry->d_inode &&
+ path.mnt->mnt_root == path.dentry) {
err = 1;
- magic = nd.path.dentry->d_inode->i_sb->s_magic;
+ magic = path.dentry->d_inode->i_sb->s_magic;
}
} else {
- dev_t dev = autofs4_get_dev(sbi);
+ dev_t dev = sbi->sb->s_dev;
- err = path_lookup(path, LOOKUP_PARENT, &nd);
+ err = find_autofs_mount(name, &path, test_by_dev, &dev);
if (err)
goto out;
- err = autofs_dev_ioctl_find_super(&nd, dev);
- if (err)
- goto out_release;
-
- devid = dev;
+ devid = new_encode_dev(dev);
- err = have_submounts(nd.path.dentry);
+ err = have_submounts(path.dentry);
- if (nd.path.mnt->mnt_mountpoint != nd.path.mnt->mnt_root) {
- if (follow_down(&nd.path.mnt, &nd.path.dentry)) {
- struct inode *inode = nd.path.dentry->d_inode;
- magic = inode->i_sb->s_magic;
- }
+ if (path.mnt->mnt_mountpoint != path.mnt->mnt_root) {
+ if (follow_down(&path))
+ magic = path.mnt->mnt_sb->s_magic;
}
}
param->ismountpoint.out.devid = devid;
param->ismountpoint.out.magic = magic;
-
-out_release:
- path_put(&nd.path);
+ path_put(&path);
out:
return err;
}
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 75f7ddacf7d6..aa39ae83f019 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -48,19 +48,19 @@ static inline int autofs4_can_expire(struct dentry *dentry,
static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
{
struct dentry *top = dentry;
+ struct path path = {.mnt = mnt, .dentry = dentry};
int status = 1;
DPRINTK("dentry %p %.*s",
dentry, (int)dentry->d_name.len, dentry->d_name.name);
- mntget(mnt);
- dget(dentry);
+ path_get(&path);
- if (!follow_down(&mnt, &dentry))
+ if (!follow_down(&path))
goto done;
- if (is_autofs4_dentry(dentry)) {
- struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+ if (is_autofs4_dentry(path.dentry)) {
+ struct autofs_sb_info *sbi = autofs4_sbi(path.dentry->d_sb);
/* This is an autofs submount, we can't expire it */
if (autofs_type_indirect(sbi->type))
@@ -70,8 +70,10 @@ static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
* Otherwise it's an offset mount and we need to check
* if we can umount its mount, if there is one.
*/
- if (!d_mountpoint(dentry))
+ if (!d_mountpoint(path.dentry)) {
+ status = 0;
goto done;
+ }
}
/* Update the expiry counter if fs is busy */
@@ -84,8 +86,7 @@ static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
status = 0;
done:
DPRINTK("returning = %d", status);
- dput(dentry);
- mntput(mnt);
+ path_put(&path);
return status;
}
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index e383bf0334f1..b96a3c57359d 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -181,7 +181,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
nd->flags);
/*
* For an expire of a covered direct or offset mount we need
- * to beeak out of follow_down() at the autofs mount trigger
+ * to break out of follow_down() at the autofs mount trigger
* (d_mounted--), so we can see the expiring flag, and manage
* the blocking and following here until the expire is completed.
*/
@@ -190,7 +190,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
if (ino->flags & AUTOFS_INF_EXPIRING) {
spin_unlock(&sbi->fs_lock);
/* Follow down to our covering mount. */
- if (!follow_down(&nd->path.mnt, &nd->path.dentry))
+ if (!follow_down(&nd->path))
goto done;
goto follow;
}
@@ -230,8 +230,7 @@ follow:
* to follow it.
*/
if (d_mountpoint(dentry)) {
- if (!autofs4_follow_mount(&nd->path.mnt,
- &nd->path.dentry)) {
+ if (!autofs4_follow_mount(&nd->path)) {
status = -ENOENT;
goto out_error;
}
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index 76afd0d6b86c..9367b6297d84 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -737,6 +737,8 @@ parse_options(char *options, befs_mount_options * opts)
static void
befs_put_super(struct super_block *sb)
{
+ lock_kernel();
+
kfree(BEFS_SB(sb)->mount_opts.iocharset);
BEFS_SB(sb)->mount_opts.iocharset = NULL;
@@ -747,7 +749,8 @@ befs_put_super(struct super_block *sb)
kfree(sb->s_fs_info);
sb->s_fs_info = NULL;
- return;
+
+ unlock_kernel();
}
/* Allocate private field of the superblock, fill it.
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index cc4062d12ca2..3a9a1361fdc1 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -30,6 +30,7 @@ MODULE_LICENSE("GPL");
#define dprintf(x...)
#endif
+static void bfs_write_super(struct super_block *s);
void dump_imap(const char *prefix, struct super_block *s);
struct inode *bfs_iget(struct super_block *sb, unsigned long ino)
@@ -216,11 +217,18 @@ static void bfs_put_super(struct super_block *s)
if (!info)
return;
+ lock_kernel();
+
+ if (s->s_dirt)
+ bfs_write_super(s);
+
brelse(info->si_sbh);
mutex_destroy(&info->bfs_lock);
kfree(info->si_imap);
kfree(info);
s->s_fs_info = NULL;
+
+ unlock_kernel();
}
static int bfs_statfs(struct dentry *dentry, struct kstatfs *buf)
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 70cfc4b84ae0..fdb66faa24f1 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -1388,7 +1388,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
prstatus->pr_sigpend = p->pending.signal.sig[0];
prstatus->pr_sighold = p->blocked.sig[0];
prstatus->pr_pid = task_pid_vnr(p);
- prstatus->pr_ppid = task_pid_vnr(p->parent);
+ prstatus->pr_ppid = task_pid_vnr(p->real_parent);
prstatus->pr_pgrp = task_pgrp_vnr(p);
prstatus->pr_sid = task_session_vnr(p);
if (thread_group_leader(p)) {
@@ -1433,7 +1433,7 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
psinfo->pr_psargs[len] = 0;
psinfo->pr_pid = task_pid_vnr(p);
- psinfo->pr_ppid = task_pid_vnr(p->parent);
+ psinfo->pr_ppid = task_pid_vnr(p->real_parent);
psinfo->pr_pgrp = task_pgrp_vnr(p);
psinfo->pr_sid = task_session_vnr(p);
diff --git a/fs/bio.c b/fs/bio.c
index e0c9e545bbfa..577e8a253f69 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -175,14 +175,6 @@ struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx,
struct bio_vec *bvl;
/*
- * If 'bs' is given, lookup the pool and do the mempool alloc.
- * If not, this is a bio_kmalloc() allocation and just do a
- * kzalloc() for the exact number of vecs right away.
- */
- if (!bs)
- bvl = kmalloc(nr * sizeof(struct bio_vec), gfp_mask);
-
- /*
* see comment near bvec_array define!
*/
switch (nr) {
@@ -260,21 +252,6 @@ void bio_free(struct bio *bio, struct bio_set *bs)
mempool_free(p, bs->bio_pool);
}
-/*
- * default destructor for a bio allocated with bio_alloc_bioset()
- */
-static void bio_fs_destructor(struct bio *bio)
-{
- bio_free(bio, fs_bio_set);
-}
-
-static void bio_kmalloc_destructor(struct bio *bio)
-{
- if (bio_has_allocated_vec(bio))
- kfree(bio->bi_io_vec);
- kfree(bio);
-}
-
void bio_init(struct bio *bio)
{
memset(bio, 0, sizeof(*bio));
@@ -301,21 +278,15 @@ void bio_init(struct bio *bio)
**/
struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
{
+ unsigned long idx = BIO_POOL_NONE;
struct bio_vec *bvl = NULL;
- struct bio *bio = NULL;
- unsigned long idx = 0;
- void *p = NULL;
-
- if (bs) {
- p = mempool_alloc(bs->bio_pool, gfp_mask);
- if (!p)
- goto err;
- bio = p + bs->front_pad;
- } else {
- bio = kmalloc(sizeof(*bio), gfp_mask);
- if (!bio)
- goto err;
- }
+ struct bio *bio;
+ void *p;
+
+ p = mempool_alloc(bs->bio_pool, gfp_mask);
+ if (unlikely(!p))
+ return NULL;
+ bio = p + bs->front_pad;
bio_init(bio);
@@ -332,22 +303,33 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
nr_iovecs = bvec_nr_vecs(idx);
}
+out_set:
bio->bi_flags |= idx << BIO_POOL_OFFSET;
bio->bi_max_vecs = nr_iovecs;
-out_set:
bio->bi_io_vec = bvl;
-
return bio;
err_free:
- if (bs)
- mempool_free(p, bs->bio_pool);
- else
- kfree(bio);
-err:
+ mempool_free(p, bs->bio_pool);
return NULL;
}
+static void bio_fs_destructor(struct bio *bio)
+{
+ bio_free(bio, fs_bio_set);
+}
+
+/**
+ * bio_alloc - allocate a new bio, memory pool backed
+ * @gfp_mask: allocation mask to use
+ * @nr_iovecs: number of iovecs
+ *
+ * Allocate a new bio with @nr_iovecs bvecs. If @gfp_mask
+ * contains __GFP_WAIT, the allocation is guaranteed to succeed.
+ *
+ * RETURNS:
+ * Pointer to new bio on success, NULL on failure.
+ */
struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs)
{
struct bio *bio = bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set);
@@ -358,19 +340,45 @@ struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs)
return bio;
}
-/*
- * Like bio_alloc(), but doesn't use a mempool backing. This means that
- * it CAN fail, but while bio_alloc() can only be used for allocations
- * that have a short (finite) life span, bio_kmalloc() should be used
- * for more permanent bio allocations (like allocating some bio's for
- * initalization or setup purposes).
- */
+static void bio_kmalloc_destructor(struct bio *bio)
+{
+ if (bio_integrity(bio))
+ bio_integrity_free(bio);
+ kfree(bio);
+}
+
+/**
+ * bio_alloc - allocate a bio for I/O
+ * @gfp_mask: the GFP_ mask given to the slab allocator
+ * @nr_iovecs: number of iovecs to pre-allocate
+ *
+ * Description:
+ * bio_alloc will allocate a bio and associated bio_vec array that can hold
+ * at least @nr_iovecs entries. Allocations will be done from the
+ * fs_bio_set. Also see @bio_alloc_bioset.
+ *
+ * If %__GFP_WAIT is set, then bio_alloc will always be able to allocate
+ * a bio. This is due to the mempool guarantees. To make this work, callers
+ * must never allocate more than 1 bio at a time from this pool. Callers
+ * that need to allocate more than 1 bio must always submit the previously
+ * allocated bio for IO before attempting to allocate a new one. Failure to
+ * do so can cause livelocks under memory pressure.
+ *
+ **/
struct bio *bio_kmalloc(gfp_t gfp_mask, int nr_iovecs)
{
- struct bio *bio = bio_alloc_bioset(gfp_mask, nr_iovecs, NULL);
+ struct bio *bio;
- if (bio)
- bio->bi_destructor = bio_kmalloc_destructor;
+ bio = kmalloc(sizeof(struct bio) + nr_iovecs * sizeof(struct bio_vec),
+ gfp_mask);
+ if (unlikely(!bio))
+ return NULL;
+
+ bio_init(bio);
+ bio->bi_flags |= BIO_POOL_NONE << BIO_POOL_OFFSET;
+ bio->bi_max_vecs = nr_iovecs;
+ bio->bi_io_vec = bio->bi_inline_vecs;
+ bio->bi_destructor = bio_kmalloc_destructor;
return bio;
}
@@ -809,12 +817,15 @@ struct bio *bio_copy_user_iov(struct request_queue *q,
len += iov[i].iov_len;
}
+ if (offset)
+ nr_pages++;
+
bmd = bio_alloc_map_data(nr_pages, iov_count, gfp_mask);
if (!bmd)
return ERR_PTR(-ENOMEM);
ret = -ENOMEM;
- bio = bio_alloc(gfp_mask, nr_pages);
+ bio = bio_kmalloc(gfp_mask, nr_pages);
if (!bio)
goto out_bmd;
@@ -938,7 +949,7 @@ static struct bio *__bio_map_user_iov(struct request_queue *q,
if (!nr_pages)
return ERR_PTR(-EINVAL);
- bio = bio_alloc(gfp_mask, nr_pages);
+ bio = bio_kmalloc(gfp_mask, nr_pages);
if (!bio)
return ERR_PTR(-ENOMEM);
@@ -1122,7 +1133,7 @@ static struct bio *__bio_map_kern(struct request_queue *q, void *data,
int offset, i;
struct bio *bio;
- bio = bio_alloc(gfp_mask, nr_pages);
+ bio = bio_kmalloc(gfp_mask, nr_pages);
if (!bio)
return ERR_PTR(-ENOMEM);
diff --git a/fs/block_dev.c b/fs/block_dev.c
index f45dbc18dd17..44383dcce7af 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -25,6 +25,7 @@
#include <linux/uio.h>
#include <linux/namei.h>
#include <linux/log2.h>
+#include <linux/kmemleak.h>
#include <asm/uaccess.h>
#include "internal.h"
@@ -175,17 +176,22 @@ blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
iov, offset, nr_segs, blkdev_get_blocks, NULL);
}
+int __sync_blockdev(struct block_device *bdev, int wait)
+{
+ if (!bdev)
+ return 0;
+ if (!wait)
+ return filemap_flush(bdev->bd_inode->i_mapping);
+ return filemap_write_and_wait(bdev->bd_inode->i_mapping);
+}
+
/*
* Write out and wait upon all the dirty data associated with a block
* device via its mapping. Does not take the superblock lock.
*/
int sync_blockdev(struct block_device *bdev)
{
- int ret = 0;
-
- if (bdev)
- ret = filemap_write_and_wait(bdev->bd_inode->i_mapping);
- return ret;
+ return __sync_blockdev(bdev, 1);
}
EXPORT_SYMBOL(sync_blockdev);
@@ -198,7 +204,7 @@ int fsync_bdev(struct block_device *bdev)
{
struct super_block *sb = get_super(bdev);
if (sb) {
- int res = fsync_super(sb);
+ int res = sync_filesystem(sb);
drop_super(sb);
return res;
}
@@ -240,7 +246,7 @@ struct super_block *freeze_bdev(struct block_device *bdev)
sb->s_frozen = SB_FREEZE_WRITE;
smp_wmb();
- __fsync_super(sb);
+ sync_filesystem(sb);
sb->s_frozen = SB_FREEZE_TRANS;
smp_wmb();
@@ -331,6 +337,12 @@ static int blkdev_readpage(struct file * file, struct page * page)
return block_read_full_page(page, blkdev_get_block);
}
+static int blkdev_readpages(struct file *file, struct address_space *mapping,
+ struct list_head *pages, unsigned nr_pages)
+{
+ return mpage_readpages(mapping, pages, nr_pages, blkdev_get_block);
+}
+
static int blkdev_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata)
@@ -492,6 +504,11 @@ void __init bdev_cache_init(void)
bd_mnt = kern_mount(&bd_type);
if (IS_ERR(bd_mnt))
panic("Cannot create bdev pseudo-fs");
+ /*
+ * This vfsmount structure is only used to obtain the
+ * blockdev_superblock, so tell kmemleak not to report it.
+ */
+ kmemleak_not_leak(bd_mnt);
blockdev_superblock = bd_mnt->mnt_sb; /* For writeback */
}
@@ -1399,6 +1416,7 @@ static int blkdev_releasepage(struct page *page, gfp_t wait)
static const struct address_space_operations def_blk_aops = {
.readpage = blkdev_readpage,
+ .readpages = blkdev_readpages,
.writepage = blkdev_writepage,
.sync_page = block_sync_page,
.write_begin = blkdev_write_begin,
diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile
index 9adf5e4f7e96..94212844a9bc 100644
--- a/fs/btrfs/Makefile
+++ b/fs/btrfs/Makefile
@@ -1,25 +1,10 @@
-ifneq ($(KERNELRELEASE),)
-# kbuild part of makefile
obj-$(CONFIG_BTRFS_FS) := btrfs.o
-btrfs-y := super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \
+
+btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \
file-item.o inode-item.o inode-map.o disk-io.o \
transaction.o inode.o file.o tree-defrag.o \
extent_map.o sysfs.o struct-funcs.o xattr.o ordered-data.o \
extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o \
ref-cache.o export.o tree-log.o acl.o free-space-cache.o zlib.o \
compression.o delayed-ref.o
-else
-
-# Normal Makefile
-
-KERNELDIR := /lib/modules/`uname -r`/build
-all:
- $(MAKE) -C $(KERNELDIR) M=`pwd` CONFIG_BTRFS_FS=m modules
-
-modules_install:
- $(MAKE) -C $(KERNELDIR) M=`pwd` modules_install
-clean:
- $(MAKE) -C $(KERNELDIR) M=`pwd` clean
-
-endif
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c
index 7fdd184a528d..cbba000dccbe 100644
--- a/fs/btrfs/acl.c
+++ b/fs/btrfs/acl.c
@@ -60,15 +60,20 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
return ERR_PTR(-EINVAL);
}
+ /* Handle the cached NULL acl case without locking */
+ acl = ACCESS_ONCE(*p_acl);
+ if (!acl)
+ return acl;
+
spin_lock(&inode->i_lock);
- if (*p_acl != BTRFS_ACL_NOT_CACHED)
- acl = posix_acl_dup(*p_acl);
+ acl = *p_acl;
+ if (acl != BTRFS_ACL_NOT_CACHED)
+ acl = posix_acl_dup(acl);
spin_unlock(&inode->i_lock);
- if (acl)
+ if (acl != BTRFS_ACL_NOT_CACHED)
return acl;
-
size = __btrfs_getxattr(inode, name, "", 0);
if (size > 0) {
value = kzalloc(size, GFP_NOFS);
@@ -80,9 +85,12 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
btrfs_update_cached_acl(inode, p_acl, acl);
}
kfree(value);
- } else if (size == -ENOENT) {
+ } else if (size == -ENOENT || size == -ENODATA || size == 0) {
+ /* FIXME, who returns -ENOENT? I think nobody */
acl = NULL;
btrfs_update_cached_acl(inode, p_acl, acl);
+ } else {
+ acl = ERR_PTR(-EIO);
}
return acl;
diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c
index 51bfdfc8fcda..502c3d61de62 100644
--- a/fs/btrfs/async-thread.c
+++ b/fs/btrfs/async-thread.c
@@ -25,6 +25,7 @@
#define WORK_QUEUED_BIT 0
#define WORK_DONE_BIT 1
#define WORK_ORDER_DONE_BIT 2
+#define WORK_HIGH_PRIO_BIT 3
/*
* container for the kthread task pointer and the list of pending work
@@ -36,6 +37,7 @@ struct btrfs_worker_thread {
/* list of struct btrfs_work that are waiting for service */
struct list_head pending;
+ struct list_head prio_pending;
/* list of worker threads from struct btrfs_workers */
struct list_head worker_list;
@@ -103,10 +105,16 @@ static noinline int run_ordered_completions(struct btrfs_workers *workers,
spin_lock_irqsave(&workers->lock, flags);
- while (!list_empty(&workers->order_list)) {
- work = list_entry(workers->order_list.next,
- struct btrfs_work, order_list);
-
+ while (1) {
+ if (!list_empty(&workers->prio_order_list)) {
+ work = list_entry(workers->prio_order_list.next,
+ struct btrfs_work, order_list);
+ } else if (!list_empty(&workers->order_list)) {
+ work = list_entry(workers->order_list.next,
+ struct btrfs_work, order_list);
+ } else {
+ break;
+ }
if (!test_bit(WORK_DONE_BIT, &work->flags))
break;
@@ -143,8 +151,14 @@ static int worker_loop(void *arg)
do {
spin_lock_irq(&worker->lock);
again_locked:
- while (!list_empty(&worker->pending)) {
- cur = worker->pending.next;
+ while (1) {
+ if (!list_empty(&worker->prio_pending))
+ cur = worker->prio_pending.next;
+ else if (!list_empty(&worker->pending))
+ cur = worker->pending.next;
+ else
+ break;
+
work = list_entry(cur, struct btrfs_work, list);
list_del(&work->list);
clear_bit(WORK_QUEUED_BIT, &work->flags);
@@ -163,7 +177,6 @@ again_locked:
spin_lock_irq(&worker->lock);
check_idle_worker(worker);
-
}
if (freezing(current)) {
worker->working = 0;
@@ -178,7 +191,8 @@ again_locked:
* jump_in?
*/
smp_mb();
- if (!list_empty(&worker->pending))
+ if (!list_empty(&worker->pending) ||
+ !list_empty(&worker->prio_pending))
continue;
/*
@@ -191,7 +205,8 @@ again_locked:
*/
schedule_timeout(1);
smp_mb();
- if (!list_empty(&worker->pending))
+ if (!list_empty(&worker->pending) ||
+ !list_empty(&worker->prio_pending))
continue;
if (kthread_should_stop())
@@ -200,7 +215,8 @@ again_locked:
/* still no more work?, sleep for real */
spin_lock_irq(&worker->lock);
set_current_state(TASK_INTERRUPTIBLE);
- if (!list_empty(&worker->pending))
+ if (!list_empty(&worker->pending) ||
+ !list_empty(&worker->prio_pending))
goto again_locked;
/*
@@ -248,6 +264,7 @@ void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max)
INIT_LIST_HEAD(&workers->worker_list);
INIT_LIST_HEAD(&workers->idle_list);
INIT_LIST_HEAD(&workers->order_list);
+ INIT_LIST_HEAD(&workers->prio_order_list);
spin_lock_init(&workers->lock);
workers->max_workers = max;
workers->idle_thresh = 32;
@@ -273,6 +290,7 @@ int btrfs_start_workers(struct btrfs_workers *workers, int num_workers)
}
INIT_LIST_HEAD(&worker->pending);
+ INIT_LIST_HEAD(&worker->prio_pending);
INIT_LIST_HEAD(&worker->worker_list);
spin_lock_init(&worker->lock);
atomic_set(&worker->num_pending, 0);
@@ -396,7 +414,10 @@ int btrfs_requeue_work(struct btrfs_work *work)
goto out;
spin_lock_irqsave(&worker->lock, flags);
- list_add_tail(&work->list, &worker->pending);
+ if (test_bit(WORK_HIGH_PRIO_BIT, &work->flags))
+ list_add_tail(&work->list, &worker->prio_pending);
+ else
+ list_add_tail(&work->list, &worker->pending);
atomic_inc(&worker->num_pending);
/* by definition we're busy, take ourselves off the idle
@@ -422,6 +443,11 @@ out:
return 0;
}
+void btrfs_set_work_high_prio(struct btrfs_work *work)
+{
+ set_bit(WORK_HIGH_PRIO_BIT, &work->flags);
+}
+
/*
* places a struct btrfs_work into the pending queue of one of the kthreads
*/
@@ -438,7 +464,12 @@ int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work)
worker = find_worker(workers);
if (workers->ordered) {
spin_lock_irqsave(&workers->lock, flags);
- list_add_tail(&work->order_list, &workers->order_list);
+ if (test_bit(WORK_HIGH_PRIO_BIT, &work->flags)) {
+ list_add_tail(&work->order_list,
+ &workers->prio_order_list);
+ } else {
+ list_add_tail(&work->order_list, &workers->order_list);
+ }
spin_unlock_irqrestore(&workers->lock, flags);
} else {
INIT_LIST_HEAD(&work->order_list);
@@ -446,7 +477,10 @@ int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work)
spin_lock_irqsave(&worker->lock, flags);
- list_add_tail(&work->list, &worker->pending);
+ if (test_bit(WORK_HIGH_PRIO_BIT, &work->flags))
+ list_add_tail(&work->list, &worker->prio_pending);
+ else
+ list_add_tail(&work->list, &worker->pending);
atomic_inc(&worker->num_pending);
check_busy_worker(worker);
diff --git a/fs/btrfs/async-thread.h b/fs/btrfs/async-thread.h
index 31be4ed8b63e..1b511c109db6 100644
--- a/fs/btrfs/async-thread.h
+++ b/fs/btrfs/async-thread.h
@@ -85,6 +85,7 @@ struct btrfs_workers {
* of work items waiting for completion
*/
struct list_head order_list;
+ struct list_head prio_order_list;
/* lock for finding the next worker thread to queue on */
spinlock_t lock;
@@ -98,4 +99,5 @@ int btrfs_start_workers(struct btrfs_workers *workers, int num_workers);
int btrfs_stop_workers(struct btrfs_workers *workers);
void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max);
int btrfs_requeue_work(struct btrfs_work *work);
+void btrfs_set_work_high_prio(struct btrfs_work *work);
#endif
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index e5b2533b691a..a99f1c2a710d 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1325,12 +1325,12 @@ static noinline int reada_for_balance(struct btrfs_root *root,
int ret = 0;
int blocksize;
- parent = path->nodes[level - 1];
+ parent = path->nodes[level + 1];
if (!parent)
return 0;
nritems = btrfs_header_nritems(parent);
- slot = path->slots[level];
+ slot = path->slots[level + 1];
blocksize = btrfs_level_size(root, level);
if (slot > 0) {
@@ -1341,7 +1341,7 @@ static noinline int reada_for_balance(struct btrfs_root *root,
block1 = 0;
free_extent_buffer(eb);
}
- if (slot < nritems) {
+ if (slot + 1 < nritems) {
block2 = btrfs_node_blockptr(parent, slot + 1);
gen = btrfs_node_ptr_generation(parent, slot + 1);
eb = btrfs_find_tree_block(root, block2, blocksize);
@@ -1351,7 +1351,11 @@ static noinline int reada_for_balance(struct btrfs_root *root,
}
if (block1 || block2) {
ret = -EAGAIN;
+
+ /* release the whole path */
btrfs_release_path(root, path);
+
+ /* read the blocks */
if (block1)
readahead_tree_block(root, block1, blocksize, 0);
if (block2)
@@ -1361,7 +1365,7 @@ static noinline int reada_for_balance(struct btrfs_root *root,
eb = read_tree_block(root, block1, blocksize, 0);
free_extent_buffer(eb);
}
- if (block1) {
+ if (block2) {
eb = read_tree_block(root, block2, blocksize, 0);
free_extent_buffer(eb);
}
@@ -1481,12 +1485,15 @@ read_block_for_search(struct btrfs_trans_handle *trans,
* of the btree by dropping locks before
* we read.
*/
- btrfs_release_path(NULL, p);
+ btrfs_unlock_up_safe(p, level + 1);
+ btrfs_set_path_blocking(p);
+
if (tmp)
free_extent_buffer(tmp);
if (p->reada)
reada_for_search(root, p, level, slot, key->objectid);
+ btrfs_release_path(NULL, p);
tmp = read_tree_block(root, blocknr, blocksize, gen);
if (tmp)
free_extent_buffer(tmp);
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index ad96495dedc5..4414a5d9983a 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -881,6 +881,9 @@ struct btrfs_fs_info {
u64 metadata_alloc_profile;
u64 system_alloc_profile;
+ unsigned data_chunk_allocations;
+ unsigned metadata_ratio;
+
void *bdev_holder;
};
@@ -2174,7 +2177,8 @@ int btrfs_check_file(struct btrfs_root *root, struct inode *inode);
extern struct file_operations btrfs_file_operations;
int btrfs_drop_extents(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct inode *inode,
- u64 start, u64 end, u64 inline_limit, u64 *hint_block);
+ u64 start, u64 end, u64 locked_end,
+ u64 inline_limit, u64 *hint_block);
int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct inode *inode, u64 start, u64 end);
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 92caa8035f36..0ff16d3331da 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -232,10 +232,14 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
memcpy(&found, result, csum_size);
read_extent_buffer(buf, &val, 0, csum_size);
- printk(KERN_INFO "btrfs: %s checksum verify failed "
- "on %llu wanted %X found %X level %d\n",
- root->fs_info->sb->s_id,
- buf->start, val, found, btrfs_header_level(buf));
+ if (printk_ratelimit()) {
+ printk(KERN_INFO "btrfs: %s checksum verify "
+ "failed on %llu wanted %X found %X "
+ "level %d\n",
+ root->fs_info->sb->s_id,
+ (unsigned long long)buf->start, val, found,
+ btrfs_header_level(buf));
+ }
if (result != (char *)&inline_result)
kfree(result);
return 1;
@@ -268,10 +272,13 @@ static int verify_parent_transid(struct extent_io_tree *io_tree,
ret = 0;
goto out;
}
- printk("parent transid verify failed on %llu wanted %llu found %llu\n",
- (unsigned long long)eb->start,
- (unsigned long long)parent_transid,
- (unsigned long long)btrfs_header_generation(eb));
+ if (printk_ratelimit()) {
+ printk("parent transid verify failed on %llu wanted %llu "
+ "found %llu\n",
+ (unsigned long long)eb->start,
+ (unsigned long long)parent_transid,
+ (unsigned long long)btrfs_header_generation(eb));
+ }
ret = 1;
clear_extent_buffer_uptodate(io_tree, eb);
out:
@@ -415,9 +422,12 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
found_start = btrfs_header_bytenr(eb);
if (found_start != start) {
- printk(KERN_INFO "btrfs bad tree block start %llu %llu\n",
- (unsigned long long)found_start,
- (unsigned long long)eb->start);
+ if (printk_ratelimit()) {
+ printk(KERN_INFO "btrfs bad tree block start "
+ "%llu %llu\n",
+ (unsigned long long)found_start,
+ (unsigned long long)eb->start);
+ }
ret = -EIO;
goto err;
}
@@ -429,8 +439,10 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
goto err;
}
if (check_tree_block_fsid(root, eb)) {
- printk(KERN_INFO "btrfs bad fsid on block %llu\n",
- (unsigned long long)eb->start);
+ if (printk_ratelimit()) {
+ printk(KERN_INFO "btrfs bad fsid on block %llu\n",
+ (unsigned long long)eb->start);
+ }
ret = -EIO;
goto err;
}
@@ -579,19 +591,12 @@ int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode,
async->bio_flags = bio_flags;
atomic_inc(&fs_info->nr_async_submits);
+
+ if (rw & (1 << BIO_RW_SYNCIO))
+ btrfs_set_work_high_prio(&async->work);
+
btrfs_queue_worker(&fs_info->workers, &async->work);
-#if 0
- int limit = btrfs_async_submit_limit(fs_info);
- if (atomic_read(&fs_info->nr_async_submits) > limit) {
- wait_event_timeout(fs_info->async_submit_wait,
- (atomic_read(&fs_info->nr_async_submits) < limit),
- HZ/10);
- wait_event_timeout(fs_info->async_submit_wait,
- (atomic_read(&fs_info->nr_async_bios) < limit),
- HZ/10);
- }
-#endif
while (atomic_read(&fs_info->async_submit_draining) &&
atomic_read(&fs_info->nr_async_submits)) {
wait_event(fs_info->async_submit_wait,
@@ -656,6 +661,7 @@ static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio,
return btrfs_map_bio(BTRFS_I(inode)->root, rw, bio,
mirror_num, 0);
}
+
/*
* kthread helpers are used to submit writes so that checksumming
* can happen in parallel across all CPUs
@@ -765,27 +771,6 @@ static void btree_invalidatepage(struct page *page, unsigned long offset)
}
}
-#if 0
-static int btree_writepage(struct page *page, struct writeback_control *wbc)
-{
- struct buffer_head *bh;
- struct btrfs_root *root = BTRFS_I(page->mapping->host)->root;
- struct buffer_head *head;
- if (!page_has_buffers(page)) {
- create_empty_buffers(page, root->fs_info->sb->s_blocksize,
- (1 << BH_Dirty)|(1 << BH_Uptodate));
- }
- head = page_buffers(page);
- bh = head;
- do {
- if (buffer_dirty(bh))
- csum_tree_block(root, bh, 0);
- bh = bh->b_this_page;
- } while (bh != head);
- return block_write_full_page(page, btree_get_block, wbc);
-}
-#endif
-
static struct address_space_operations btree_aops = {
.readpage = btree_readpage,
.writepage = btree_writepage,
@@ -1273,11 +1258,7 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits)
int ret = 0;
struct btrfs_device *device;
struct backing_dev_info *bdi;
-#if 0
- if ((bdi_bits & (1 << BDI_write_congested)) &&
- btrfs_congested_async(info, 0))
- return 1;
-#endif
+
list_for_each_entry(device, &info->fs_devices->devices, dev_list) {
if (!device->bdev)
continue;
@@ -1599,6 +1580,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
fs_info->btree_inode = new_inode(sb);
fs_info->btree_inode->i_ino = 1;
fs_info->btree_inode->i_nlink = 1;
+ fs_info->metadata_ratio = 8;
fs_info->thread_pool_size = min_t(unsigned long,
num_online_cpus() + 2, 8);
@@ -1689,7 +1671,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
if (features) {
printk(KERN_ERR "BTRFS: couldn't mount because of "
"unsupported optional features (%Lx).\n",
- features);
+ (unsigned long long)features);
err = -EINVAL;
goto fail_iput;
}
@@ -1699,7 +1681,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
if (!(sb->s_flags & MS_RDONLY) && features) {
printk(KERN_ERR "BTRFS: couldn't mount RDWR because of "
"unsupported option features (%Lx).\n",
- features);
+ (unsigned long long)features);
err = -EINVAL;
goto fail_iput;
}
@@ -2095,10 +2077,10 @@ static int write_dev_supers(struct btrfs_device *device,
device->barriers = 0;
get_bh(bh);
lock_buffer(bh);
- ret = submit_bh(WRITE, bh);
+ ret = submit_bh(WRITE_SYNC, bh);
}
} else {
- ret = submit_bh(WRITE, bh);
+ ret = submit_bh(WRITE_SYNC, bh);
}
if (!ret && wait) {
@@ -2291,7 +2273,7 @@ int close_ctree(struct btrfs_root *root)
if (fs_info->delalloc_bytes) {
printk(KERN_INFO "btrfs: at unmount delalloc count %llu\n",
- fs_info->delalloc_bytes);
+ (unsigned long long)fs_info->delalloc_bytes);
}
if (fs_info->total_ref_cache_size) {
printk(KERN_INFO "btrfs: at umount reference cache size %llu\n",
@@ -2328,16 +2310,6 @@ int close_ctree(struct btrfs_root *root)
btrfs_stop_workers(&fs_info->endio_write_workers);
btrfs_stop_workers(&fs_info->submit_workers);
-#if 0
- while (!list_empty(&fs_info->hashers)) {
- struct btrfs_hasher *hasher;
- hasher = list_entry(fs_info->hashers.next, struct btrfs_hasher,
- hashers);
- list_del(&hasher->hashers);
- crypto_free_hash(&fs_info->hash_tfm);
- kfree(hasher);
- }
-#endif
btrfs_close_devices(fs_info->fs_devices);
btrfs_mapping_tree_free(&fs_info->mapping_tree);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 178df4c67de4..3e2c7c738f23 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -312,7 +312,7 @@ btrfs_lookup_first_block_group(struct btrfs_fs_info *info, u64 bytenr)
}
/*
- * return the block group that contains teh given bytenr
+ * return the block group that contains the given bytenr
*/
struct btrfs_block_group_cache *btrfs_lookup_block_group(
struct btrfs_fs_info *info,
@@ -1844,10 +1844,14 @@ again:
printk(KERN_ERR "no space left, need %llu, %llu delalloc bytes"
", %llu bytes_used, %llu bytes_reserved, "
"%llu bytes_pinned, %llu bytes_readonly, %llu may use"
- "%llu total\n", bytes, data_sinfo->bytes_delalloc,
- data_sinfo->bytes_used, data_sinfo->bytes_reserved,
- data_sinfo->bytes_pinned, data_sinfo->bytes_readonly,
- data_sinfo->bytes_may_use, data_sinfo->total_bytes);
+ "%llu total\n", (unsigned long long)bytes,
+ (unsigned long long)data_sinfo->bytes_delalloc,
+ (unsigned long long)data_sinfo->bytes_used,
+ (unsigned long long)data_sinfo->bytes_reserved,
+ (unsigned long long)data_sinfo->bytes_pinned,
+ (unsigned long long)data_sinfo->bytes_readonly,
+ (unsigned long long)data_sinfo->bytes_may_use,
+ (unsigned long long)data_sinfo->total_bytes);
return -ENOSPC;
}
data_sinfo->bytes_may_use += bytes;
@@ -1918,15 +1922,29 @@ void btrfs_delalloc_free_space(struct btrfs_root *root, struct inode *inode,
spin_unlock(&info->lock);
}
+static void force_metadata_allocation(struct btrfs_fs_info *info)
+{
+ struct list_head *head = &info->space_info;
+ struct btrfs_space_info *found;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(found, head, list) {
+ if (found->flags & BTRFS_BLOCK_GROUP_METADATA)
+ found->force_alloc = 1;
+ }
+ rcu_read_unlock();
+}
+
static int do_chunk_alloc(struct btrfs_trans_handle *trans,
struct btrfs_root *extent_root, u64 alloc_bytes,
u64 flags, int force)
{
struct btrfs_space_info *space_info;
+ struct btrfs_fs_info *fs_info = extent_root->fs_info;
u64 thresh;
int ret = 0;
- mutex_lock(&extent_root->fs_info->chunk_mutex);
+ mutex_lock(&fs_info->chunk_mutex);
flags = btrfs_reduce_alloc_profile(extent_root, flags);
@@ -1958,6 +1976,18 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
}
spin_unlock(&space_info->lock);
+ /*
+ * if we're doing a data chunk, go ahead and make sure that
+ * we keep a reasonable number of metadata chunks allocated in the
+ * FS as well.
+ */
+ if (flags & BTRFS_BLOCK_GROUP_DATA) {
+ fs_info->data_chunk_allocations++;
+ if (!(fs_info->data_chunk_allocations %
+ fs_info->metadata_ratio))
+ force_metadata_allocation(fs_info);
+ }
+
ret = btrfs_alloc_chunk(trans, extent_root, flags);
if (ret)
space_info->full = 1;
@@ -2798,9 +2828,12 @@ static void dump_space_info(struct btrfs_space_info *info, u64 bytes)
info->bytes_pinned - info->bytes_reserved),
(info->full) ? "" : "not ");
printk(KERN_INFO "space_info total=%llu, pinned=%llu, delalloc=%llu,"
- " may_use=%llu, used=%llu\n", info->total_bytes,
- info->bytes_pinned, info->bytes_delalloc, info->bytes_may_use,
- info->bytes_used);
+ " may_use=%llu, used=%llu\n",
+ (unsigned long long)info->total_bytes,
+ (unsigned long long)info->bytes_pinned,
+ (unsigned long long)info->bytes_delalloc,
+ (unsigned long long)info->bytes_may_use,
+ (unsigned long long)info->bytes_used);
down_read(&info->groups_sem);
list_for_each_entry(cache, &info->block_groups, list) {
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index eb2bee8b7fbf..fe9eb990e443 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -17,12 +17,6 @@
#include "ctree.h"
#include "btrfs_inode.h"
-/* temporary define until extent_map moves out of btrfs */
-struct kmem_cache *btrfs_cache_create(const char *name, size_t size,
- unsigned long extra_flags,
- void (*ctor)(void *, struct kmem_cache *,
- unsigned long));
-
static struct kmem_cache *extent_state_cache;
static struct kmem_cache *extent_buffer_cache;
@@ -50,20 +44,23 @@ struct extent_page_data {
/* tells writepage not to lock the state bits for this range
* it still does the unlocking
*/
- int extent_locked;
+ unsigned int extent_locked:1;
+
+ /* tells the submit_bio code to use a WRITE_SYNC */
+ unsigned int sync_io:1;
};
int __init extent_io_init(void)
{
- extent_state_cache = btrfs_cache_create("extent_state",
- sizeof(struct extent_state), 0,
- NULL);
+ extent_state_cache = kmem_cache_create("extent_state",
+ sizeof(struct extent_state), 0,
+ SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
if (!extent_state_cache)
return -ENOMEM;
- extent_buffer_cache = btrfs_cache_create("extent_buffers",
- sizeof(struct extent_buffer), 0,
- NULL);
+ extent_buffer_cache = kmem_cache_create("extent_buffers",
+ sizeof(struct extent_buffer), 0,
+ SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
if (!extent_buffer_cache)
goto free_state_cache;
return 0;
@@ -1404,69 +1401,6 @@ out:
return total_bytes;
}
-#if 0
-/*
- * helper function to lock both pages and extents in the tree.
- * pages must be locked first.
- */
-static int lock_range(struct extent_io_tree *tree, u64 start, u64 end)
-{
- unsigned long index = start >> PAGE_CACHE_SHIFT;
- unsigned long end_index = end >> PAGE_CACHE_SHIFT;
- struct page *page;
- int err;
-
- while (index <= end_index) {
- page = grab_cache_page(tree->mapping, index);
- if (!page) {
- err = -ENOMEM;
- goto failed;
- }
- if (IS_ERR(page)) {
- err = PTR_ERR(page);
- goto failed;
- }
- index++;
- }
- lock_extent(tree, start, end, GFP_NOFS);
- return 0;
-
-failed:
- /*
- * we failed above in getting the page at 'index', so we undo here
- * up to but not including the page at 'index'
- */
- end_index = index;
- index = start >> PAGE_CACHE_SHIFT;
- while (index < end_index) {
- page = find_get_page(tree->mapping, index);
- unlock_page(page);
- page_cache_release(page);
- index++;
- }
- return err;
-}
-
-/*
- * helper function to unlock both pages and extents in the tree.
- */
-static int unlock_range(struct extent_io_tree *tree, u64 start, u64 end)
-{
- unsigned long index = start >> PAGE_CACHE_SHIFT;
- unsigned long end_index = end >> PAGE_CACHE_SHIFT;
- struct page *page;
-
- while (index <= end_index) {
- page = find_get_page(tree->mapping, index);
- unlock_page(page);
- page_cache_release(page);
- index++;
- }
- unlock_extent(tree, start, end, GFP_NOFS);
- return 0;
-}
-#endif
-
/*
* set the private field for a given byte offset in the tree. If there isn't
* an extent_state there already, this does nothing.
@@ -2101,6 +2035,16 @@ int extent_read_full_page(struct extent_io_tree *tree, struct page *page,
return ret;
}
+static noinline void update_nr_written(struct page *page,
+ struct writeback_control *wbc,
+ unsigned long nr_written)
+{
+ wbc->nr_to_write -= nr_written;
+ if (wbc->range_cyclic || (wbc->nr_to_write > 0 &&
+ wbc->range_start == 0 && wbc->range_end == LLONG_MAX))
+ page->mapping->writeback_index = page->index + nr_written;
+}
+
/*
* the writepage semantics are similar to regular writepage. extent
* records are inserted to lock ranges in the tree, and as dirty areas
@@ -2136,8 +2080,14 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,
u64 delalloc_end;
int page_started;
int compressed;
+ int write_flags;
unsigned long nr_written = 0;
+ if (wbc->sync_mode == WB_SYNC_ALL)
+ write_flags = WRITE_SYNC_PLUG;
+ else
+ write_flags = WRITE;
+
WARN_ON(!PageLocked(page));
pg_offset = i_size & (PAGE_CACHE_SIZE - 1);
if (page->index > end_index ||
@@ -2164,6 +2114,12 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,
delalloc_end = 0;
page_started = 0;
if (!epd->extent_locked) {
+ /*
+ * make sure the wbc mapping index is at least updated
+ * to this page.
+ */
+ update_nr_written(page, wbc, 0);
+
while (delalloc_end < page_end) {
nr_delalloc = find_lock_delalloc_range(inode, tree,
page,
@@ -2185,7 +2141,13 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,
*/
if (page_started) {
ret = 0;
- goto update_nr_written;
+ /*
+ * we've unlocked the page, so we can't update
+ * the mapping's writeback index, just update
+ * nr_to_write.
+ */
+ wbc->nr_to_write -= nr_written;
+ goto done_unlocked;
}
}
lock_extent(tree, start, page_end, GFP_NOFS);
@@ -2198,13 +2160,18 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,
if (ret == -EAGAIN) {
unlock_extent(tree, start, page_end, GFP_NOFS);
redirty_page_for_writepage(wbc, page);
+ update_nr_written(page, wbc, nr_written);
unlock_page(page);
ret = 0;
- goto update_nr_written;
+ goto done_unlocked;
}
}
- nr_written++;
+ /*
+ * we don't want to touch the inode after unlocking the page,
+ * so we update the mapping writeback index now
+ */
+ update_nr_written(page, wbc, nr_written + 1);
end = page_end;
if (test_range_bit(tree, start, page_end, EXTENT_DELALLOC, 0))
@@ -2314,9 +2281,9 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,
(unsigned long long)end);
}
- ret = submit_extent_page(WRITE, tree, page, sector,
- iosize, pg_offset, bdev,
- &epd->bio, max_nr,
+ ret = submit_extent_page(write_flags, tree, page,
+ sector, iosize, pg_offset,
+ bdev, &epd->bio, max_nr,
end_bio_extent_writepage,
0, 0, 0);
if (ret)
@@ -2336,11 +2303,8 @@ done:
unlock_extent(tree, unlock_start, page_end, GFP_NOFS);
unlock_page(page);
-update_nr_written:
- wbc->nr_to_write -= nr_written;
- if (wbc->range_cyclic || (wbc->nr_to_write > 0 &&
- wbc->range_start == 0 && wbc->range_end == LLONG_MAX))
- page->mapping->writeback_index = page->index + nr_written;
+done_unlocked:
+
return 0;
}
@@ -2460,15 +2424,23 @@ retry:
return ret;
}
-static noinline void flush_write_bio(void *data)
+static void flush_epd_write_bio(struct extent_page_data *epd)
{
- struct extent_page_data *epd = data;
if (epd->bio) {
- submit_one_bio(WRITE, epd->bio, 0, 0);
+ if (epd->sync_io)
+ submit_one_bio(WRITE_SYNC, epd->bio, 0, 0);
+ else
+ submit_one_bio(WRITE, epd->bio, 0, 0);
epd->bio = NULL;
}
}
+static noinline void flush_write_bio(void *data)
+{
+ struct extent_page_data *epd = data;
+ flush_epd_write_bio(epd);
+}
+
int extent_write_full_page(struct extent_io_tree *tree, struct page *page,
get_extent_t *get_extent,
struct writeback_control *wbc)
@@ -2480,23 +2452,22 @@ int extent_write_full_page(struct extent_io_tree *tree, struct page *page,
.tree = tree,
.get_extent = get_extent,
.extent_locked = 0,
+ .sync_io = wbc->sync_mode == WB_SYNC_ALL,
};
struct writeback_control wbc_writepages = {
.bdi = wbc->bdi,
- .sync_mode = WB_SYNC_NONE,
+ .sync_mode = wbc->sync_mode,
.older_than_this = NULL,
.nr_to_write = 64,
.range_start = page_offset(page) + PAGE_CACHE_SIZE,
.range_end = (loff_t)-1,
};
-
ret = __extent_writepage(page, wbc, &epd);
extent_write_cache_pages(tree, mapping, &wbc_writepages,
__extent_writepage, &epd, flush_write_bio);
- if (epd.bio)
- submit_one_bio(WRITE, epd.bio, 0, 0);
+ flush_epd_write_bio(&epd);
return ret;
}
@@ -2515,6 +2486,7 @@ int extent_write_locked_range(struct extent_io_tree *tree, struct inode *inode,
.tree = tree,
.get_extent = get_extent,
.extent_locked = 1,
+ .sync_io = mode == WB_SYNC_ALL,
};
struct writeback_control wbc_writepages = {
.bdi = inode->i_mapping->backing_dev_info,
@@ -2540,8 +2512,7 @@ int extent_write_locked_range(struct extent_io_tree *tree, struct inode *inode,
start += PAGE_CACHE_SIZE;
}
- if (epd.bio)
- submit_one_bio(WRITE, epd.bio, 0, 0);
+ flush_epd_write_bio(&epd);
return ret;
}
@@ -2556,13 +2527,13 @@ int extent_writepages(struct extent_io_tree *tree,
.tree = tree,
.get_extent = get_extent,
.extent_locked = 0,
+ .sync_io = wbc->sync_mode == WB_SYNC_ALL,
};
ret = extent_write_cache_pages(tree, mapping, wbc,
__extent_writepage, &epd,
flush_write_bio);
- if (epd.bio)
- submit_one_bio(WRITE, epd.bio, 0, 0);
+ flush_epd_write_bio(&epd);
return ret;
}
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index b187917b36fa..30c9365861e6 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -6,19 +6,14 @@
#include <linux/hardirq.h>
#include "extent_map.h"
-/* temporary define until extent_map moves out of btrfs */
-struct kmem_cache *btrfs_cache_create(const char *name, size_t size,
- unsigned long extra_flags,
- void (*ctor)(void *, struct kmem_cache *,
- unsigned long));
static struct kmem_cache *extent_map_cache;
int __init extent_map_init(void)
{
- extent_map_cache = btrfs_cache_create("extent_map",
- sizeof(struct extent_map), 0,
- NULL);
+ extent_map_cache = kmem_cache_create("extent_map",
+ sizeof(struct extent_map), 0,
+ SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
if (!extent_map_cache)
return -ENOMEM;
return 0;
@@ -43,7 +38,6 @@ void extent_map_tree_init(struct extent_map_tree *tree, gfp_t mask)
tree->map.rb_node = NULL;
spin_lock_init(&tree->lock);
}
-EXPORT_SYMBOL(extent_map_tree_init);
/**
* alloc_extent_map - allocate new extent map structure
@@ -64,7 +58,6 @@ struct extent_map *alloc_extent_map(gfp_t mask)
atomic_set(&em->refs, 1);
return em;
}
-EXPORT_SYMBOL(alloc_extent_map);
/**
* free_extent_map - drop reference count of an extent_map
@@ -83,7 +76,6 @@ void free_extent_map(struct extent_map *em)
kmem_cache_free(extent_map_cache, em);
}
}
-EXPORT_SYMBOL(free_extent_map);
static struct rb_node *tree_insert(struct rb_root *root, u64 offset,
struct rb_node *node)
@@ -264,7 +256,6 @@ int add_extent_mapping(struct extent_map_tree *tree,
out:
return ret;
}
-EXPORT_SYMBOL(add_extent_mapping);
/* simple helper to do math around the end of an extent, handling wrap */
static u64 range_end(u64 start, u64 len)
@@ -326,7 +317,6 @@ found:
out:
return em;
}
-EXPORT_SYMBOL(lookup_extent_mapping);
/**
* remove_extent_mapping - removes an extent_map from the extent tree
@@ -346,4 +336,3 @@ int remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em)
em->in_tree = 0;
return ret;
}
-EXPORT_SYMBOL(remove_extent_mapping);
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 9c9fb46ccd08..1d51dc38bb49 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -272,83 +272,6 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
return 0;
}
-int btrfs_check_file(struct btrfs_root *root, struct inode *inode)
-{
- return 0;
-#if 0
- struct btrfs_path *path;
- struct btrfs_key found_key;
- struct extent_buffer *leaf;
- struct btrfs_file_extent_item *extent;
- u64 last_offset = 0;
- int nritems;
- int slot;
- int found_type;
- int ret;
- int err = 0;
- u64 extent_end = 0;
-
- path = btrfs_alloc_path();
- ret = btrfs_lookup_file_extent(NULL, root, path, inode->i_ino,
- last_offset, 0);
- while (1) {
- nritems = btrfs_header_nritems(path->nodes[0]);
- if (path->slots[0] >= nritems) {
- ret = btrfs_next_leaf(root, path);
- if (ret)
- goto out;
- nritems = btrfs_header_nritems(path->nodes[0]);
- }
- slot = path->slots[0];
- leaf = path->nodes[0];
- btrfs_item_key_to_cpu(leaf, &found_key, slot);
- if (found_key.objectid != inode->i_ino)
- break;
- if (found_key.type != BTRFS_EXTENT_DATA_KEY)
- goto out;
-
- if (found_key.offset < last_offset) {
- WARN_ON(1);
- btrfs_print_leaf(root, leaf);
- printk(KERN_ERR "inode %lu found offset %llu "
- "expected %llu\n", inode->i_ino,
- (unsigned long long)found_key.offset,
- (unsigned long long)last_offset);
- err = 1;
- goto out;
- }
- extent = btrfs_item_ptr(leaf, slot,
- struct btrfs_file_extent_item);
- found_type = btrfs_file_extent_type(leaf, extent);
- if (found_type == BTRFS_FILE_EXTENT_REG) {
- extent_end = found_key.offset +
- btrfs_file_extent_num_bytes(leaf, extent);
- } else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
- struct btrfs_item *item;
- item = btrfs_item_nr(leaf, slot);
- extent_end = found_key.offset +
- btrfs_file_extent_inline_len(leaf, extent);
- extent_end = (extent_end + root->sectorsize - 1) &
- ~((u64)root->sectorsize - 1);
- }
- last_offset = extent_end;
- path->slots[0]++;
- }
- if (0 && last_offset < inode->i_size) {
- WARN_ON(1);
- btrfs_print_leaf(root, leaf);
- printk(KERN_ERR "inode %lu found offset %llu size %llu\n",
- inode->i_ino, (unsigned long long)last_offset,
- (unsigned long long)inode->i_size);
- err = 1;
-
- }
-out:
- btrfs_free_path(path);
- return err;
-#endif
-}
-
/*
* this is very complex, but the basic idea is to drop all extents
* in the range start - end. hint_block is filled in with a block number
@@ -363,15 +286,16 @@ out:
*/
noinline int btrfs_drop_extents(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct inode *inode,
- u64 start, u64 end, u64 inline_limit, u64 *hint_byte)
+ u64 start, u64 end, u64 locked_end,
+ u64 inline_limit, u64 *hint_byte)
{
u64 extent_end = 0;
- u64 locked_end = end;
u64 search_start = start;
u64 leaf_start;
u64 ram_bytes = 0;
u64 orig_parent = 0;
u64 disk_bytenr = 0;
+ u64 orig_locked_end = locked_end;
u8 compression;
u8 encryption;
u16 other_encoding = 0;
@@ -684,11 +608,10 @@ next_slot:
}
out:
btrfs_free_path(path);
- if (locked_end > end) {
- unlock_extent(&BTRFS_I(inode)->io_tree, end, locked_end - 1,
- GFP_NOFS);
+ if (locked_end > orig_locked_end) {
+ unlock_extent(&BTRFS_I(inode)->io_tree, orig_locked_end,
+ locked_end - 1, GFP_NOFS);
}
- btrfs_check_file(root, inode);
return ret;
}
@@ -830,7 +753,7 @@ again:
ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
BUG_ON(ret);
- goto done;
+ goto release;
} else if (split == start) {
if (locked_end < extent_end) {
ret = try_lock_extent(&BTRFS_I(inode)->io_tree,
@@ -926,6 +849,8 @@ again:
}
done:
btrfs_mark_buffer_dirty(leaf);
+
+release:
btrfs_release_path(root, path);
if (split_end && split == start) {
split = end;
@@ -1131,7 +1056,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
if (will_write) {
btrfs_fdatawrite_range(inode->i_mapping, pos,
pos + write_bytes - 1,
- WB_SYNC_NONE);
+ WB_SYNC_ALL);
} else {
balance_dirty_pages_ratelimited_nr(inode->i_mapping,
num_pages);
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index 768b9523662d..0bc93657b460 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -332,13 +332,17 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
printk(KERN_ERR "couldn't find space %llu to free\n",
(unsigned long long)offset);
printk(KERN_ERR "cached is %d, offset %llu bytes %llu\n",
- block_group->cached, block_group->key.objectid,
- block_group->key.offset);
+ block_group->cached,
+ (unsigned long long)block_group->key.objectid,
+ (unsigned long long)block_group->key.offset);
btrfs_dump_free_space(block_group, bytes);
} else if (info) {
printk(KERN_ERR "hmm, found offset=%llu bytes=%llu, "
"but wanted offset=%llu bytes=%llu\n",
- info->offset, info->bytes, offset, bytes);
+ (unsigned long long)info->offset,
+ (unsigned long long)info->bytes,
+ (unsigned long long)offset,
+ (unsigned long long)bytes);
}
WARN_ON(1);
}
@@ -357,8 +361,9 @@ void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group,
info = rb_entry(n, struct btrfs_free_space, offset_index);
if (info->bytes >= bytes)
count++;
- printk(KERN_ERR "entry offset %llu, bytes %llu\n", info->offset,
- info->bytes);
+ printk(KERN_ERR "entry offset %llu, bytes %llu\n",
+ (unsigned long long)info->offset,
+ (unsigned long long)info->bytes);
}
printk(KERN_INFO "%d blocks of free space at or bigger than bytes is"
"\n", count);
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c
index cc7334d833c9..9abbced1123d 100644
--- a/fs/btrfs/inode-map.c
+++ b/fs/btrfs/inode-map.c
@@ -79,7 +79,7 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
}
path = btrfs_alloc_path();
BUG_ON(!path);
- search_start = max(search_start, BTRFS_FIRST_FREE_OBJECTID);
+ search_start = max(search_start, (u64)BTRFS_FIRST_FREE_OBJECTID);
search_key.objectid = search_start;
search_key.type = 0;
search_key.offset = 0;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index a0d1dd492a58..6bd6a8c9fd3b 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -70,7 +70,6 @@ static struct extent_io_ops btrfs_extent_io_ops;
static struct kmem_cache *btrfs_inode_cachep;
struct kmem_cache *btrfs_trans_handle_cachep;
struct kmem_cache *btrfs_transaction_cachep;
-struct kmem_cache *btrfs_bit_radix_cachep;
struct kmem_cache *btrfs_path_cachep;
#define S_SHIFT 12
@@ -234,7 +233,7 @@ static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans,
}
ret = btrfs_drop_extents(trans, root, inode, start,
- aligned_end, start, &hint_byte);
+ aligned_end, aligned_end, start, &hint_byte);
BUG_ON(ret);
if (isize > actual_end)
@@ -1439,6 +1438,7 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
struct inode *inode, u64 file_pos,
u64 disk_bytenr, u64 disk_num_bytes,
u64 num_bytes, u64 ram_bytes,
+ u64 locked_end,
u8 compression, u8 encryption,
u16 other_encoding, int extent_type)
{
@@ -1455,7 +1455,8 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
path->leave_spinning = 1;
ret = btrfs_drop_extents(trans, root, inode, file_pos,
- file_pos + num_bytes, file_pos, &hint);
+ file_pos + num_bytes, locked_end,
+ file_pos, &hint);
BUG_ON(ret);
ins.objectid = inode->i_ino;
@@ -1590,6 +1591,8 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
ordered_extent->disk_len,
ordered_extent->len,
ordered_extent->len,
+ ordered_extent->file_offset +
+ ordered_extent->len,
compressed, 0, 0,
BTRFS_FILE_EXTENT_REG);
BUG_ON(ret);
@@ -1819,10 +1822,12 @@ good:
return 0;
zeroit:
- printk(KERN_INFO "btrfs csum failed ino %lu off %llu csum %u "
- "private %llu\n", page->mapping->host->i_ino,
- (unsigned long long)start, csum,
- (unsigned long long)private);
+ if (printk_ratelimit()) {
+ printk(KERN_INFO "btrfs csum failed ino %lu off %llu csum %u "
+ "private %llu\n", page->mapping->host->i_ino,
+ (unsigned long long)start, csum,
+ (unsigned long long)private);
+ }
memset(kaddr + offset, 1, end - start + 1);
flush_dcache_page(page);
kunmap_atomic(kaddr, KM_USER0);
@@ -2011,6 +2016,57 @@ void btrfs_orphan_cleanup(struct btrfs_root *root)
}
/*
+ * very simple check to peek ahead in the leaf looking for xattrs. If we
+ * don't find any xattrs, we know there can't be any acls.
+ *
+ * slot is the slot the inode is in, objectid is the objectid of the inode
+ */
+static noinline int acls_after_inode_item(struct extent_buffer *leaf,
+ int slot, u64 objectid)
+{
+ u32 nritems = btrfs_header_nritems(leaf);
+ struct btrfs_key found_key;
+ int scanned = 0;
+
+ slot++;
+ while (slot < nritems) {
+ btrfs_item_key_to_cpu(leaf, &found_key, slot);
+
+ /* we found a different objectid, there must not be acls */
+ if (found_key.objectid != objectid)
+ return 0;
+
+ /* we found an xattr, assume we've got an acl */
+ if (found_key.type == BTRFS_XATTR_ITEM_KEY)
+ return 1;
+
+ /*
+ * we found a key greater than an xattr key, there can't
+ * be any acls later on
+ */
+ if (found_key.type > BTRFS_XATTR_ITEM_KEY)
+ return 0;
+
+ slot++;
+ scanned++;
+
+ /*
+ * it goes inode, inode backrefs, xattrs, extents,
+ * so if there are a ton of hard links to an inode there can
+ * be a lot of backrefs. Don't waste time searching too hard,
+ * this is just an optimization
+ */
+ if (scanned >= 8)
+ break;
+ }
+ /* we hit the end of the leaf before we found an xattr or
+ * something larger than an xattr. We have to assume the inode
+ * has acls
+ */
+ return 1;
+}
+
+/*
* read an inode from the btree into the in-memory inode
*/
void btrfs_read_locked_inode(struct inode *inode)
@@ -2021,6 +2077,7 @@ void btrfs_read_locked_inode(struct inode *inode)
struct btrfs_timespec *tspec;
struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_key location;
+ int maybe_acls;
u64 alloc_group_block;
u32 rdev;
int ret;
@@ -2067,6 +2124,16 @@ void btrfs_read_locked_inode(struct inode *inode)
alloc_group_block = btrfs_inode_block_group(leaf, inode_item);
+ /*
+ * try to precache a NULL acl entry for files that don't have
+ * any xattrs or acls
+ */
+ maybe_acls = acls_after_inode_item(leaf, path->slots[0], inode->i_ino);
+ if (!maybe_acls) {
+ BTRFS_I(inode)->i_acl = NULL;
+ BTRFS_I(inode)->i_default_acl = NULL;
+ }
+
BTRFS_I(inode)->block_group = btrfs_find_block_group(root, 0,
alloc_group_block, 0);
btrfs_free_path(path);
@@ -2260,7 +2327,6 @@ err:
btrfs_update_inode(trans, root, dir);
btrfs_drop_nlink(inode);
ret = btrfs_update_inode(trans, root, inode);
- dir->i_sb->s_dirt = 1;
out:
return ret;
}
@@ -2744,7 +2810,6 @@ error:
pending_del_nr);
}
btrfs_free_path(path);
- inode->i_sb->s_dirt = 1;
return ret;
}
@@ -2877,6 +2942,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t size)
err = btrfs_drop_extents(trans, root, inode,
cur_offset,
cur_offset + hole_size,
+ block_end,
cur_offset, &hint_byte);
if (err)
break;
@@ -3041,8 +3107,8 @@ static noinline void init_btrfs_i(struct inode *inode)
{
struct btrfs_inode *bi = BTRFS_I(inode);
- bi->i_acl = NULL;
- bi->i_default_acl = NULL;
+ bi->i_acl = BTRFS_ACL_NOT_CACHED;
+ bi->i_default_acl = BTRFS_ACL_NOT_CACHED;
bi->generation = 0;
bi->sequence = 0;
@@ -3681,7 +3747,6 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
init_special_inode(inode, inode->i_mode, rdev);
btrfs_update_inode(trans, root, inode);
}
- dir->i_sb->s_dirt = 1;
btrfs_update_inode_block_group(trans, inode);
btrfs_update_inode_block_group(trans, dir);
out_unlock:
@@ -3746,7 +3811,6 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
inode->i_op = &btrfs_file_inode_operations;
BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
}
- dir->i_sb->s_dirt = 1;
btrfs_update_inode_block_group(trans, inode);
btrfs_update_inode_block_group(trans, dir);
out_unlock:
@@ -3793,7 +3857,6 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
if (err)
drop_inode = 1;
- dir->i_sb->s_dirt = 1;
btrfs_update_inode_block_group(trans, dir);
err = btrfs_update_inode(trans, root, inode);
@@ -3875,7 +3938,6 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
d_instantiate(dentry, inode);
drop_on_err = 0;
- dir->i_sb->s_dirt = 1;
btrfs_update_inode_block_group(trans, inode);
btrfs_update_inode_block_group(trans, dir);
@@ -4634,47 +4696,36 @@ void btrfs_destroy_cachep(void)
kmem_cache_destroy(btrfs_trans_handle_cachep);
if (btrfs_transaction_cachep)
kmem_cache_destroy(btrfs_transaction_cachep);
- if (btrfs_bit_radix_cachep)
- kmem_cache_destroy(btrfs_bit_radix_cachep);
if (btrfs_path_cachep)
kmem_cache_destroy(btrfs_path_cachep);
}
-struct kmem_cache *btrfs_cache_create(const char *name, size_t size,
- unsigned long extra_flags,
- void (*ctor)(void *))
-{
- return kmem_cache_create(name, size, 0, (SLAB_RECLAIM_ACCOUNT |
- SLAB_MEM_SPREAD | extra_flags), ctor);
-}
-
int btrfs_init_cachep(void)
{
- btrfs_inode_cachep = btrfs_cache_create("btrfs_inode_cache",
- sizeof(struct btrfs_inode),
- 0, init_once);
+ btrfs_inode_cachep = kmem_cache_create("btrfs_inode_cache",
+ sizeof(struct btrfs_inode), 0,
+ SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, init_once);
if (!btrfs_inode_cachep)
goto fail;
- btrfs_trans_handle_cachep =
- btrfs_cache_create("btrfs_trans_handle_cache",
- sizeof(struct btrfs_trans_handle),
- 0, NULL);
+
+ btrfs_trans_handle_cachep = kmem_cache_create("btrfs_trans_handle_cache",
+ sizeof(struct btrfs_trans_handle), 0,
+ SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
if (!btrfs_trans_handle_cachep)
goto fail;
- btrfs_transaction_cachep = btrfs_cache_create("btrfs_transaction_cache",
- sizeof(struct btrfs_transaction),
- 0, NULL);
+
+ btrfs_transaction_cachep = kmem_cache_create("btrfs_transaction_cache",
+ sizeof(struct btrfs_transaction), 0,
+ SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
if (!btrfs_transaction_cachep)
goto fail;
- btrfs_path_cachep = btrfs_cache_create("btrfs_path_cache",
- sizeof(struct btrfs_path),
- 0, NULL);
+
+ btrfs_path_cachep = kmem_cache_create("btrfs_path_cache",
+ sizeof(struct btrfs_path), 0,
+ SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
if (!btrfs_path_cachep)
goto fail;
- btrfs_bit_radix_cachep = btrfs_cache_create("btrfs_radix", 256,
- SLAB_DESTROY_BY_RCU, NULL);
- if (!btrfs_bit_radix_cachep)
- goto fail;
+
return 0;
fail:
btrfs_destroy_cachep();
@@ -4915,7 +4966,6 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
inode->i_op = &btrfs_file_inode_operations;
BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
}
- dir->i_sb->s_dirt = 1;
btrfs_update_inode_block_group(trans, inode);
btrfs_update_inode_block_group(trans, dir);
if (drop_inode)
@@ -4970,10 +5020,10 @@ out_fail:
return err;
}
-static int prealloc_file_range(struct inode *inode, u64 start, u64 end,
- u64 alloc_hint, int mode)
+static int prealloc_file_range(struct btrfs_trans_handle *trans,
+ struct inode *inode, u64 start, u64 end,
+ u64 locked_end, u64 alloc_hint, int mode)
{
- struct btrfs_trans_handle *trans;
struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_key ins;
u64 alloc_size;
@@ -4981,10 +5031,6 @@ static int prealloc_file_range(struct inode *inode, u64 start, u64 end,
u64 num_bytes = end - start;
int ret = 0;
- trans = btrfs_join_transaction(root, 1);
- BUG_ON(!trans);
- btrfs_set_trans_block_group(trans, inode);
-
while (num_bytes > 0) {
alloc_size = min(num_bytes, root->fs_info->max_extent);
ret = btrfs_reserve_extent(trans, root, alloc_size,
@@ -4997,7 +5043,8 @@ static int prealloc_file_range(struct inode *inode, u64 start, u64 end,
ret = insert_reserved_file_extent(trans, inode,
cur_offset, ins.objectid,
ins.offset, ins.offset,
- ins.offset, 0, 0, 0,
+ ins.offset, locked_end,
+ 0, 0, 0,
BTRFS_FILE_EXTENT_PREALLOC);
BUG_ON(ret);
num_bytes -= ins.offset;
@@ -5015,7 +5062,6 @@ out:
BUG_ON(ret);
}
- btrfs_end_transaction(trans, root);
return ret;
}
@@ -5027,13 +5073,21 @@ static long btrfs_fallocate(struct inode *inode, int mode,
u64 alloc_start;
u64 alloc_end;
u64 alloc_hint = 0;
+ u64 locked_end;
u64 mask = BTRFS_I(inode)->root->sectorsize - 1;
struct extent_map *em;
+ struct btrfs_trans_handle *trans;
int ret;
alloc_start = offset & ~mask;
alloc_end = (offset + len + mask) & ~mask;
+ /*
+ * wait for ordered IO before we have any locks. We'll loop again
+ * below with the locks held.
+ */
+ btrfs_wait_ordered_range(inode, alloc_start, alloc_end - alloc_start);
+
mutex_lock(&inode->i_mutex);
if (alloc_start > inode->i_size) {
ret = btrfs_cont_expand(inode, alloc_start);
@@ -5041,10 +5095,21 @@ static long btrfs_fallocate(struct inode *inode, int mode,
goto out;
}
+ locked_end = alloc_end - 1;
while (1) {
struct btrfs_ordered_extent *ordered;
- lock_extent(&BTRFS_I(inode)->io_tree, alloc_start,
- alloc_end - 1, GFP_NOFS);
+
+ trans = btrfs_start_transaction(BTRFS_I(inode)->root, 1);
+ if (!trans) {
+ ret = -EIO;
+ goto out;
+ }
+
+ /* the extent lock is ordered inside the running
+ * transaction
+ */
+ lock_extent(&BTRFS_I(inode)->io_tree, alloc_start, locked_end,
+ GFP_NOFS);
ordered = btrfs_lookup_first_ordered_extent(inode,
alloc_end - 1);
if (ordered &&
@@ -5052,7 +5117,13 @@ static long btrfs_fallocate(struct inode *inode, int mode,
ordered->file_offset < alloc_end) {
btrfs_put_ordered_extent(ordered);
unlock_extent(&BTRFS_I(inode)->io_tree,
- alloc_start, alloc_end - 1, GFP_NOFS);
+ alloc_start, locked_end, GFP_NOFS);
+ btrfs_end_transaction(trans, BTRFS_I(inode)->root);
+
+ /*
+ * we can't wait on the range with the transaction
+ * running or with the extent lock held
+ */
btrfs_wait_ordered_range(inode, alloc_start,
alloc_end - alloc_start);
} else {
@@ -5070,8 +5141,9 @@ static long btrfs_fallocate(struct inode *inode, int mode,
last_byte = min(extent_map_end(em), alloc_end);
last_byte = (last_byte + mask) & ~mask;
if (em->block_start == EXTENT_MAP_HOLE) {
- ret = prealloc_file_range(inode, cur_offset,
- last_byte, alloc_hint, mode);
+ ret = prealloc_file_range(trans, inode, cur_offset,
+ last_byte, locked_end + 1,
+ alloc_hint, mode);
if (ret < 0) {
free_extent_map(em);
break;
@@ -5087,8 +5159,10 @@ static long btrfs_fallocate(struct inode *inode, int mode,
break;
}
}
- unlock_extent(&BTRFS_I(inode)->io_tree, alloc_start, alloc_end - 1,
+ unlock_extent(&BTRFS_I(inode)->io_tree, alloc_start, locked_end,
GFP_NOFS);
+
+ btrfs_end_transaction(trans, BTRFS_I(inode)->root);
out:
mutex_unlock(&inode->i_mutex);
return ret;
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 7594bec1be10..5e94ea6e1cbe 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -461,15 +461,9 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg)
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS);
-
- if (!vol_args)
- return -ENOMEM;
-
- if (copy_from_user(vol_args, arg, sizeof(*vol_args))) {
- ret = -EFAULT;
- goto out;
- }
+ vol_args = memdup_user(arg, sizeof(*vol_args));
+ if (IS_ERR(vol_args))
+ return PTR_ERR(vol_args);
vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
namelen = strlen(vol_args->name);
@@ -483,11 +477,13 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg)
*devstr = '\0';
devstr = vol_args->name;
devid = simple_strtoull(devstr, &end, 10);
- printk(KERN_INFO "resizing devid %llu\n", devid);
+ printk(KERN_INFO "resizing devid %llu\n",
+ (unsigned long long)devid);
}
device = btrfs_find_device(root, devid, NULL, NULL);
if (!device) {
- printk(KERN_INFO "resizer unable to find device %llu\n", devid);
+ printk(KERN_INFO "resizer unable to find device %llu\n",
+ (unsigned long long)devid);
ret = -EINVAL;
goto out_unlock;
}
@@ -545,7 +541,6 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg)
out_unlock:
mutex_unlock(&root->fs_info->volume_mutex);
-out:
kfree(vol_args);
return ret;
}
@@ -565,15 +560,9 @@ static noinline int btrfs_ioctl_snap_create(struct file *file,
if (root->fs_info->sb->s_flags & MS_RDONLY)
return -EROFS;
- vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS);
-
- if (!vol_args)
- return -ENOMEM;
-
- if (copy_from_user(vol_args, arg, sizeof(*vol_args))) {
- ret = -EFAULT;
- goto out;
- }
+ vol_args = memdup_user(arg, sizeof(*vol_args));
+ if (IS_ERR(vol_args))
+ return PTR_ERR(vol_args);
vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
namelen = strlen(vol_args->name);
@@ -675,19 +664,13 @@ static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg)
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS);
+ vol_args = memdup_user(arg, sizeof(*vol_args));
+ if (IS_ERR(vol_args))
+ return PTR_ERR(vol_args);
- if (!vol_args)
- return -ENOMEM;
-
- if (copy_from_user(vol_args, arg, sizeof(*vol_args))) {
- ret = -EFAULT;
- goto out;
- }
vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
ret = btrfs_init_new_device(root, vol_args->name);
-out:
kfree(vol_args);
return ret;
}
@@ -703,19 +686,13 @@ static long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg)
if (root->fs_info->sb->s_flags & MS_RDONLY)
return -EROFS;
- vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS);
+ vol_args = memdup_user(arg, sizeof(*vol_args));
+ if (IS_ERR(vol_args))
+ return PTR_ERR(vol_args);
- if (!vol_args)
- return -ENOMEM;
-
- if (copy_from_user(vol_args, arg, sizeof(*vol_args))) {
- ret = -EFAULT;
- goto out;
- }
vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
ret = btrfs_rm_device(root, vol_args->name);
-out:
kfree(vol_args);
return ret;
}
@@ -830,7 +807,8 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
BUG_ON(!trans);
/* punch hole in destination first */
- btrfs_drop_extents(trans, root, inode, off, off+len, 0, &hint_byte);
+ btrfs_drop_extents(trans, root, inode, off, off + len,
+ off + len, 0, &hint_byte);
/* clone data */
key.objectid = src->i_ino;
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
index 53c87b197d70..d6f0806c682f 100644
--- a/fs/btrfs/ordered-data.c
+++ b/fs/btrfs/ordered-data.c
@@ -489,7 +489,7 @@ again:
/* start IO across the range first to instantiate any delalloc
* extents
*/
- btrfs_fdatawrite_range(inode->i_mapping, start, orig_end, WB_SYNC_NONE);
+ btrfs_fdatawrite_range(inode->i_mapping, start, orig_end, WB_SYNC_ALL);
/* The compression code will leave pages locked but return from
* writepage without setting the page writeback. Starting again
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 9744af9d71e9..d455dfe1c178 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -60,15 +60,19 @@ static void btrfs_put_super(struct super_block *sb)
struct btrfs_root *root = btrfs_sb(sb);
int ret;
+ lock_kernel();
+
ret = close_ctree(root);
sb->s_fs_info = NULL;
+
+ unlock_kernel();
}
enum {
Opt_degraded, Opt_subvol, Opt_device, Opt_nodatasum, Opt_nodatacow,
Opt_max_extent, Opt_max_inline, Opt_alloc_start, Opt_nobarrier,
Opt_ssd, Opt_thread_pool, Opt_noacl, Opt_compress, Opt_notreelog,
- Opt_flushoncommit, Opt_err,
+ Opt_ratio, Opt_flushoncommit, Opt_err,
};
static match_table_t tokens = {
@@ -87,6 +91,7 @@ static match_table_t tokens = {
{Opt_noacl, "noacl"},
{Opt_notreelog, "notreelog"},
{Opt_flushoncommit, "flushoncommit"},
+ {Opt_ratio, "metadata_ratio=%d"},
{Opt_err, NULL},
};
@@ -195,7 +200,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
info->max_extent = max_t(u64,
info->max_extent, root->sectorsize);
printk(KERN_INFO "btrfs: max_extent at %llu\n",
- info->max_extent);
+ (unsigned long long)info->max_extent);
}
break;
case Opt_max_inline:
@@ -210,7 +215,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
root->sectorsize);
}
printk(KERN_INFO "btrfs: max_inline at %llu\n",
- info->max_inline);
+ (unsigned long long)info->max_inline);
}
break;
case Opt_alloc_start:
@@ -220,7 +225,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
kfree(num);
printk(KERN_INFO
"btrfs: allocations start at %llu\n",
- info->alloc_start);
+ (unsigned long long)info->alloc_start);
}
break;
case Opt_noacl:
@@ -234,6 +239,15 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
printk(KERN_INFO "btrfs: turning on flush-on-commit\n");
btrfs_set_opt(info->mount_opt, FLUSHONCOMMIT);
break;
+ case Opt_ratio:
+ intarg = 0;
+ match_int(&args[0], &intarg);
+ if (intarg) {
+ info->metadata_ratio = intarg;
+ printk(KERN_INFO "btrfs: metadata ratio %d\n",
+ info->metadata_ratio);
+ }
+ break;
default:
break;
}
@@ -378,10 +392,6 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
struct btrfs_root *root = btrfs_sb(sb);
int ret;
- if (sb->s_flags & MS_RDONLY)
- return 0;
-
- sb->s_dirt = 0;
if (!wait) {
filemap_flush(root->fs_info->btree_inode->i_mapping);
return 0;
@@ -392,7 +402,6 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
trans = btrfs_start_transaction(root, 1);
ret = btrfs_commit_transaction(trans, root);
- sb->s_dirt = 0;
return ret;
}
@@ -410,11 +419,14 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
if (btrfs_test_opt(root, NOBARRIER))
seq_puts(seq, ",nobarrier");
if (info->max_extent != (u64)-1)
- seq_printf(seq, ",max_extent=%llu", info->max_extent);
+ seq_printf(seq, ",max_extent=%llu",
+ (unsigned long long)info->max_extent);
if (info->max_inline != 8192 * 1024)
- seq_printf(seq, ",max_inline=%llu", info->max_inline);
+ seq_printf(seq, ",max_inline=%llu",
+ (unsigned long long)info->max_inline);
if (info->alloc_start != 0)
- seq_printf(seq, ",alloc_start=%llu", info->alloc_start);
+ seq_printf(seq, ",alloc_start=%llu",
+ (unsigned long long)info->alloc_start);
if (info->thread_pool_size != min_t(unsigned long,
num_online_cpus() + 2, 8))
seq_printf(seq, ",thread_pool=%d", info->thread_pool_size);
@@ -431,11 +443,6 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
return 0;
}
-static void btrfs_write_super(struct super_block *sb)
-{
- sb->s_dirt = 0;
-}
-
static int btrfs_test_super(struct super_block *s, void *data)
{
struct btrfs_fs_devices *test_fs_devices = data;
@@ -489,8 +496,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags,
if (s->s_root) {
if ((flags ^ s->s_flags) & MS_RDONLY) {
- up_write(&s->s_umount);
- deactivate_super(s);
+ deactivate_locked_super(s);
error = -EBUSY;
goto error_close_devices;
}
@@ -504,8 +510,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags,
error = btrfs_fill_super(s, fs_devices, data,
flags & MS_SILENT ? 1 : 0);
if (error) {
- up_write(&s->s_umount);
- deactivate_super(s);
+ deactivate_locked_super(s);
goto error_free_subvol_name;
}
@@ -522,15 +527,13 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags,
mutex_unlock(&s->s_root->d_inode->i_mutex);
if (IS_ERR(root)) {
- up_write(&s->s_umount);
- deactivate_super(s);
+ deactivate_locked_super(s);
error = PTR_ERR(root);
goto error_free_subvol_name;
}
if (!root->d_inode) {
dput(root);
- up_write(&s->s_umount);
- deactivate_super(s);
+ deactivate_locked_super(s);
error = -ENXIO;
goto error_free_subvol_name;
}
@@ -635,14 +638,9 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd,
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- vol = kmalloc(sizeof(*vol), GFP_KERNEL);
- if (!vol)
- return -ENOMEM;
-
- if (copy_from_user(vol, (void __user *)arg, sizeof(*vol))) {
- ret = -EFAULT;
- goto out;
- }
+ vol = memdup_user((void __user *)arg, sizeof(*vol));
+ if (IS_ERR(vol))
+ return PTR_ERR(vol);
switch (cmd) {
case BTRFS_IOC_SCAN_DEV:
@@ -650,7 +648,7 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd,
&btrfs_fs_type, &fs_devices);
break;
}
-out:
+
kfree(vol);
return ret;
}
@@ -674,7 +672,6 @@ static int btrfs_unfreeze(struct super_block *sb)
static struct super_operations btrfs_super_ops = {
.delete_inode = btrfs_delete_inode,
.put_super = btrfs_put_super,
- .write_super = btrfs_write_super,
.sync_fs = btrfs_sync_fs,
.show_options = btrfs_show_options,
.write_inode = btrfs_write_inode,
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 2869b3361eb6..01b143605ec1 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -687,7 +687,13 @@ static noinline int wait_transaction_pre_flush(struct btrfs_fs_info *info)
prepare_to_wait(&info->transaction_wait, &wait,
TASK_UNINTERRUPTIBLE);
mutex_unlock(&info->trans_mutex);
+
+ atomic_dec(&info->throttles);
+ wake_up(&info->transaction_throttle);
+
schedule();
+
+ atomic_inc(&info->throttles);
mutex_lock(&info->trans_mutex);
finish_wait(&info->transaction_wait, &wait);
}
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 25f20ea11f27..db5e212e8445 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -536,7 +536,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
saved_nbytes = inode_get_bytes(inode);
/* drop any overlapping extents */
ret = btrfs_drop_extents(trans, root, inode,
- start, extent_end, start, &alloc_hint);
+ start, extent_end, extent_end, start, &alloc_hint);
BUG_ON(ret);
if (found_type == BTRFS_FILE_EXTENT_REG ||
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index e0913e469728..5f01dad4b696 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -125,6 +125,20 @@ static noinline struct btrfs_fs_devices *find_fsid(u8 *fsid)
return NULL;
}
+static void requeue_list(struct btrfs_pending_bios *pending_bios,
+ struct bio *head, struct bio *tail)
+{
+
+ struct bio *old_head;
+
+ old_head = pending_bios->head;
+ pending_bios->head = head;
+ if (pending_bios->tail)
+ tail->bi_next = old_head;
+ else
+ pending_bios->tail = tail;
+}
+
/*
* we try to collect pending bios for a device so we don't get a large
* number of procs sending bios down to the same device. This greatly
@@ -141,10 +155,12 @@ static noinline int run_scheduled_bios(struct btrfs_device *device)
struct bio *pending;
struct backing_dev_info *bdi;
struct btrfs_fs_info *fs_info;
+ struct btrfs_pending_bios *pending_bios;
struct bio *tail;
struct bio *cur;
int again = 0;
- unsigned long num_run = 0;
+ unsigned long num_run;
+ unsigned long num_sync_run;
unsigned long limit;
unsigned long last_waited = 0;
@@ -153,20 +169,30 @@ static noinline int run_scheduled_bios(struct btrfs_device *device)
limit = btrfs_async_submit_limit(fs_info);
limit = limit * 2 / 3;
+ /* we want to make sure that every time we switch from the sync
+ * list to the normal list, we unplug
+ */
+ num_sync_run = 0;
+
loop:
spin_lock(&device->io_lock);
+ num_run = 0;
loop_lock:
+
/* take all the bios off the list at once and process them
* later on (without the lock held). But, remember the
* tail and other pointers so the bios can be properly reinserted
* into the list if we hit congestion
*/
- pending = device->pending_bios;
- tail = device->pending_bio_tail;
+ if (device->pending_sync_bios.head)
+ pending_bios = &device->pending_sync_bios;
+ else
+ pending_bios = &device->pending_bios;
+
+ pending = pending_bios->head;
+ tail = pending_bios->tail;
WARN_ON(pending && !tail);
- device->pending_bios = NULL;
- device->pending_bio_tail = NULL;
/*
* if pending was null this time around, no bios need processing
@@ -176,16 +202,41 @@ loop_lock:
* device->running_pending is used to synchronize with the
* schedule_bio code.
*/
- if (pending) {
- again = 1;
- device->running_pending = 1;
- } else {
+ if (device->pending_sync_bios.head == NULL &&
+ device->pending_bios.head == NULL) {
again = 0;
device->running_pending = 0;
+ } else {
+ again = 1;
+ device->running_pending = 1;
}
+
+ pending_bios->head = NULL;
+ pending_bios->tail = NULL;
+
spin_unlock(&device->io_lock);
+ /*
+ * if we're doing the regular priority list, make sure we unplug
+ * for any high prio bios we've sent down
+ */
+ if (pending_bios == &device->pending_bios && num_sync_run > 0) {
+ num_sync_run = 0;
+ blk_run_backing_dev(bdi, NULL);
+ }
+
while (pending) {
+
+ rmb();
+ if (pending_bios != &device->pending_sync_bios &&
+ device->pending_sync_bios.head &&
+ num_run > 16) {
+ cond_resched();
+ spin_lock(&device->io_lock);
+ requeue_list(pending_bios, pending, tail);
+ goto loop_lock;
+ }
+
cur = pending;
pending = pending->bi_next;
cur->bi_next = NULL;
@@ -196,10 +247,18 @@ loop_lock:
wake_up(&fs_info->async_submit_wait);
BUG_ON(atomic_read(&cur->bi_cnt) == 0);
- bio_get(cur);
submit_bio(cur->bi_rw, cur);
- bio_put(cur);
num_run++;
+ if (bio_sync(cur))
+ num_sync_run++;
+
+ if (need_resched()) {
+ if (num_sync_run) {
+ blk_run_backing_dev(bdi, NULL);
+ num_sync_run = 0;
+ }
+ cond_resched();
+ }
/*
* we made progress, there is more work to do and the bdi
@@ -208,7 +267,6 @@ loop_lock:
*/
if (pending && bdi_write_congested(bdi) && num_run > 16 &&
fs_info->fs_devices->open_devices > 1) {
- struct bio *old_head;
struct io_context *ioc;
ioc = current->io_context;
@@ -233,17 +291,17 @@ loop_lock:
* against it before looping
*/
last_waited = ioc->last_waited;
+ if (need_resched()) {
+ if (num_sync_run) {
+ blk_run_backing_dev(bdi, NULL);
+ num_sync_run = 0;
+ }
+ cond_resched();
+ }
continue;
}
spin_lock(&device->io_lock);
-
- old_head = device->pending_bios;
- device->pending_bios = pending;
- if (device->pending_bio_tail)
- tail->bi_next = old_head;
- else
- device->pending_bio_tail = tail;
-
+ requeue_list(pending_bios, pending, tail);
device->running_pending = 1;
spin_unlock(&device->io_lock);
@@ -251,11 +309,18 @@ loop_lock:
goto done;
}
}
+
+ if (num_sync_run) {
+ num_sync_run = 0;
+ blk_run_backing_dev(bdi, NULL);
+ }
+
+ cond_resched();
if (again)
goto loop;
spin_lock(&device->io_lock);
- if (device->pending_bios)
+ if (device->pending_bios.head || device->pending_sync_bios.head)
goto loop_lock;
spin_unlock(&device->io_lock);
@@ -1478,7 +1543,7 @@ static noinline int btrfs_update_device(struct btrfs_trans_handle *trans,
btrfs_set_device_io_align(leaf, dev_item, device->io_align);
btrfs_set_device_io_width(leaf, dev_item, device->io_width);
btrfs_set_device_sector_size(leaf, dev_item, device->sector_size);
- btrfs_set_device_total_bytes(leaf, dev_item, device->total_bytes);
+ btrfs_set_device_total_bytes(leaf, dev_item, device->disk_total_bytes);
btrfs_set_device_bytes_used(leaf, dev_item, device->bytes_used);
btrfs_mark_buffer_dirty(leaf);
@@ -1875,14 +1940,6 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size)
device->total_bytes = new_size;
if (device->writeable)
device->fs_devices->total_rw_bytes -= diff;
- ret = btrfs_update_device(trans, device);
- if (ret) {
- unlock_chunks(root);
- btrfs_end_transaction(trans, root);
- goto done;
- }
- WARN_ON(diff > old_total);
- btrfs_set_super_total_bytes(super_copy, old_total - diff);
unlock_chunks(root);
btrfs_end_transaction(trans, root);
@@ -1914,7 +1971,7 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size)
length = btrfs_dev_extent_length(l, dev_extent);
if (key.offset + length <= new_size)
- goto done;
+ break;
chunk_tree = btrfs_dev_extent_chunk_tree(l, dev_extent);
chunk_objectid = btrfs_dev_extent_chunk_objectid(l, dev_extent);
@@ -1927,6 +1984,26 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size)
goto done;
}
+ /* Shrinking succeeded, else we would be at "done". */
+ trans = btrfs_start_transaction(root, 1);
+ if (!trans) {
+ ret = -ENOMEM;
+ goto done;
+ }
+ lock_chunks(root);
+
+ device->disk_total_bytes = new_size;
+ /* Now btrfs_update_device() will change the on-disk size. */
+ ret = btrfs_update_device(trans, device);
+ if (ret) {
+ unlock_chunks(root);
+ btrfs_end_transaction(trans, root);
+ goto done;
+ }
+ WARN_ON(diff > old_total);
+ btrfs_set_super_total_bytes(super_copy, old_total - diff);
+ unlock_chunks(root);
+ btrfs_end_transaction(trans, root);
done:
btrfs_free_path(path);
return ret;
@@ -2497,7 +2574,7 @@ again:
max_errors = 1;
}
}
- if (multi_ret && rw == WRITE &&
+ if (multi_ret && (rw & (1 << BIO_RW)) &&
stripes_allocated < stripes_required) {
stripes_allocated = map->num_stripes;
free_extent_map(em);
@@ -2762,6 +2839,7 @@ static noinline int schedule_bio(struct btrfs_root *root,
int rw, struct bio *bio)
{
int should_queue = 1;
+ struct btrfs_pending_bios *pending_bios;
/* don't bother with additional async steps for reads, right now */
if (!(rw & (1 << BIO_RW))) {
@@ -2783,13 +2861,17 @@ static noinline int schedule_bio(struct btrfs_root *root,
bio->bi_rw |= rw;
spin_lock(&device->io_lock);
+ if (bio_sync(bio))
+ pending_bios = &device->pending_sync_bios;
+ else
+ pending_bios = &device->pending_bios;
- if (device->pending_bio_tail)
- device->pending_bio_tail->bi_next = bio;
+ if (pending_bios->tail)
+ pending_bios->tail->bi_next = bio;
- device->pending_bio_tail = bio;
- if (!device->pending_bios)
- device->pending_bios = bio;
+ pending_bios->tail = bio;
+ if (!pending_bios->head)
+ pending_bios->head = bio;
if (device->running_pending)
should_queue = 0;
@@ -3006,7 +3088,8 @@ static int fill_device_from_item(struct extent_buffer *leaf,
unsigned long ptr;
device->devid = btrfs_device_id(leaf, dev_item);
- device->total_bytes = btrfs_device_total_bytes(leaf, dev_item);
+ device->disk_total_bytes = btrfs_device_total_bytes(leaf, dev_item);
+ device->total_bytes = device->disk_total_bytes;
device->bytes_used = btrfs_device_bytes_used(leaf, dev_item);
device->type = btrfs_device_type(leaf, dev_item);
device->io_align = btrfs_device_io_align(leaf, dev_item);
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 2185de72ff7d..5c3ff6d02fd7 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -23,13 +23,22 @@
#include "async-thread.h"
struct buffer_head;
+struct btrfs_pending_bios {
+ struct bio *head;
+ struct bio *tail;
+};
+
struct btrfs_device {
struct list_head dev_list;
struct list_head dev_alloc_list;
struct btrfs_fs_devices *fs_devices;
struct btrfs_root *dev_root;
- struct bio *pending_bios;
- struct bio *pending_bio_tail;
+
+ /* regular prio bios */
+ struct btrfs_pending_bios pending_bios;
+ /* WRITE_SYNC bios */
+ struct btrfs_pending_bios pending_sync_bios;
+
int running_pending;
u64 generation;
@@ -52,6 +61,9 @@ struct btrfs_device {
/* size of the device */
u64 total_bytes;
+ /* size of the disk */
+ u64 disk_total_bytes;
+
/* bytes used */
u64 bytes_used;
diff --git a/fs/buffer.c b/fs/buffer.c
index 13edf7ad3ff1..aed297739eb0 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -360,7 +360,7 @@ still_busy:
* Completion handler for block_write_full_page() - pages which are unlocked
* during I/O, and which have PageWriteback cleared upon I/O completion.
*/
-static void end_buffer_async_write(struct buffer_head *bh, int uptodate)
+void end_buffer_async_write(struct buffer_head *bh, int uptodate)
{
char b[BDEVNAME_SIZE];
unsigned long flags;
@@ -438,11 +438,17 @@ static void mark_buffer_async_read(struct buffer_head *bh)
set_buffer_async_read(bh);
}
-void mark_buffer_async_write(struct buffer_head *bh)
+void mark_buffer_async_write_endio(struct buffer_head *bh,
+ bh_end_io_t *handler)
{
- bh->b_end_io = end_buffer_async_write;
+ bh->b_end_io = handler;
set_buffer_async_write(bh);
}
+
+void mark_buffer_async_write(struct buffer_head *bh)
+{
+ mark_buffer_async_write_endio(bh, end_buffer_async_write);
+}
EXPORT_SYMBOL(mark_buffer_async_write);
@@ -547,7 +553,7 @@ repeat:
return err;
}
-void do_thaw_all(unsigned long unused)
+void do_thaw_all(struct work_struct *work)
{
struct super_block *sb;
char b[BDEVNAME_SIZE];
@@ -567,6 +573,7 @@ restart:
goto restart;
}
spin_unlock(&sb_lock);
+ kfree(work);
printk(KERN_WARNING "Emergency Thaw complete\n");
}
@@ -577,7 +584,13 @@ restart:
*/
void emergency_thaw_all(void)
{
- pdflush_operation(do_thaw_all, 0);
+ struct work_struct *work;
+
+ work = kmalloc(sizeof(*work), GFP_ATOMIC);
+ if (work) {
+ INIT_WORK(work, do_thaw_all);
+ schedule_work(work);
+ }
}
/**
@@ -1608,7 +1621,8 @@ EXPORT_SYMBOL(unmap_underlying_metadata);
* unplugging the device queue.
*/
static int __block_write_full_page(struct inode *inode, struct page *page,
- get_block_t *get_block, struct writeback_control *wbc)
+ get_block_t *get_block, struct writeback_control *wbc,
+ bh_end_io_t *handler)
{
int err;
sector_t block;
@@ -1693,7 +1707,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
continue;
}
if (test_clear_buffer_dirty(bh)) {
- mark_buffer_async_write(bh);
+ mark_buffer_async_write_endio(bh, handler);
} else {
unlock_buffer(bh);
}
@@ -1746,7 +1760,7 @@ recover:
if (buffer_mapped(bh) && buffer_dirty(bh) &&
!buffer_delay(bh)) {
lock_buffer(bh);
- mark_buffer_async_write(bh);
+ mark_buffer_async_write_endio(bh, handler);
} else {
/*
* The buffer may have been set dirty during
@@ -2383,7 +2397,8 @@ block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
if ((page->mapping != inode->i_mapping) ||
(page_offset(page) > size)) {
/* page got truncated out from underneath us */
- goto out_unlock;
+ unlock_page(page);
+ goto out;
}
/* page is wholly or partially inside EOF */
@@ -2397,14 +2412,15 @@ block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
ret = block_commit_write(page, 0, end);
if (unlikely(ret)) {
+ unlock_page(page);
if (ret == -ENOMEM)
ret = VM_FAULT_OOM;
else /* -ENOSPC, -EIO, etc */
ret = VM_FAULT_SIGBUS;
- }
+ } else
+ ret = VM_FAULT_LOCKED;
-out_unlock:
- unlock_page(page);
+out:
return ret;
}
@@ -2672,7 +2688,8 @@ int nobh_writepage(struct page *page, get_block_t *get_block,
out:
ret = mpage_writepage(page, get_block, wbc);
if (ret == -EAGAIN)
- ret = __block_write_full_page(inode, page, get_block, wbc);
+ ret = __block_write_full_page(inode, page, get_block, wbc,
+ end_buffer_async_write);
return ret;
}
EXPORT_SYMBOL(nobh_writepage);
@@ -2830,9 +2847,10 @@ out:
/*
* The generic ->writepage function for buffer-backed address_spaces
+ * this form passes in the end_io handler used to finish the IO.
*/
-int block_write_full_page(struct page *page, get_block_t *get_block,
- struct writeback_control *wbc)
+int block_write_full_page_endio(struct page *page, get_block_t *get_block,
+ struct writeback_control *wbc, bh_end_io_t *handler)
{
struct inode * const inode = page->mapping->host;
loff_t i_size = i_size_read(inode);
@@ -2841,7 +2859,8 @@ int block_write_full_page(struct page *page, get_block_t *get_block,
/* Is the page fully inside i_size? */
if (page->index < end_index)
- return __block_write_full_page(inode, page, get_block, wbc);
+ return __block_write_full_page(inode, page, get_block, wbc,
+ handler);
/* Is the page fully outside i_size? (truncate in progress) */
offset = i_size & (PAGE_CACHE_SIZE-1);
@@ -2864,9 +2883,20 @@ int block_write_full_page(struct page *page, get_block_t *get_block,
* writes to that region are not written out to the file."
*/
zero_user_segment(page, offset, PAGE_CACHE_SIZE);
- return __block_write_full_page(inode, page, get_block, wbc);
+ return __block_write_full_page(inode, page, get_block, wbc, handler);
+}
+
+/*
+ * The generic ->writepage function for buffer-backed address_spaces
+ */
+int block_write_full_page(struct page *page, get_block_t *get_block,
+ struct writeback_control *wbc)
+{
+ return block_write_full_page_endio(page, get_block, wbc,
+ end_buffer_async_write);
}
+
sector_t generic_block_bmap(struct address_space *mapping, sector_t block,
get_block_t *get_block)
{
@@ -3335,9 +3365,11 @@ EXPORT_SYMBOL(block_read_full_page);
EXPORT_SYMBOL(block_sync_page);
EXPORT_SYMBOL(block_truncate_page);
EXPORT_SYMBOL(block_write_full_page);
+EXPORT_SYMBOL(block_write_full_page_endio);
EXPORT_SYMBOL(cont_write_begin);
EXPORT_SYMBOL(end_buffer_read_sync);
EXPORT_SYMBOL(end_buffer_write_sync);
+EXPORT_SYMBOL(end_buffer_async_write);
EXPORT_SYMBOL(file_fsync);
EXPORT_SYMBOL(generic_block_bmap);
EXPORT_SYMBOL(generic_cont_expand_simple);
diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c
index 1e962348d111..431accd475a7 100644
--- a/fs/cachefiles/interface.c
+++ b/fs/cachefiles/interface.c
@@ -354,7 +354,9 @@ static void cachefiles_sync_cache(struct fscache_cache *_cache)
/* make sure all pages pinned by operations on behalf of the netfs are
* written to disc */
cachefiles_begin_secure(cache, &saved_cred);
- ret = fsync_super(cache->mnt->mnt_sb);
+ down_read(&cache->mnt->mnt_sb->s_umount);
+ ret = sync_filesystem(cache->mnt->mnt_sb);
+ up_read(&cache->mnt->mnt_sb->s_umount);
cachefiles_end_secure(cache, saved_cred);
if (ret == -EIO)
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 65984006192c..f20c4069c220 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,16 @@
+Version 1.58
+------------
+Guard against buffer overruns in various UCS-2 to UTF-8 string conversions
+when the UTF-8 string is composed of unusually long (more than 4 byte) converted
+characters. Add support for mounting root of a share which redirects immediately
+to DFS target. Convert string conversion functions from Unicode to more
+accurately mark string length before allocating memory (which may help the
+rare cases where a UTF-8 string is much larger than the UCS2 string that
+we converted from). Fix endianness of the vcnum field used during
+session setup to distinguish multiple mounts to same server from different
+userids. Raw NTLMSSP fixed (it requires /proc/fs/cifs/experimental
+flag to be set to 2, and mount must enable krb5 to turn on extended security).
+
Version 1.57
------------
Improve support for multiple security contexts to the same server. We
@@ -15,7 +28,8 @@ Posix file open support added (turned off after one attempt if server
fails to support it properly, as with Samba server versions prior to 3.3.2)
Fix "redzone overwritten" bug in cifs_put_tcon (CIFSTcon may allocate too
little memory for the "nativeFileSystem" field returned by the server
-during mount).
+during mount). Endian convert inode numbers if necessary (makes it easier
+to compare inode numbers on network files from big endian systems).
Version 1.56
------------
diff --git a/fs/cifs/README b/fs/cifs/README
index 07434181623b..db208ddb9899 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -651,7 +651,15 @@ Experimental When set to 1 used to enable certain experimental
signing turned on in case buffer was modified
just before it was sent, also this flag will
be used to use the new experimental directory change
- notification code).
+ notification code). When set to 2 enables
+ an additional experimental feature, "raw ntlmssp"
+ session establishment support (which allows
+ specifying "sec=ntlmssp" on mount). The Linux cifs
+ module will use ntlmv2 authentication encapsulated
+ in "raw ntlmssp" (not using SPNEGO) when
+ "sec=ntlmssp" is specified on mount.
+ This support also requires building cifs with
+ the CONFIG_CIFS_EXPERIMENTAL configuration flag.
These experimental features and tracing can be enabled by changing flags in
/proc/fs/cifs (after the cifs module has been installed or built into the
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index 5fdbf8a14472..3bb11be8b6a8 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -275,7 +275,7 @@ static int add_mount_helper(struct vfsmount *newmnt, struct nameidata *nd,
case -EBUSY:
/* someone else made a mount here whilst we were busy */
while (d_mountpoint(nd->path.dentry) &&
- follow_down(&nd->path.mnt, &nd->path.dentry))
+ follow_down(&nd->path))
;
err = 0;
default:
@@ -340,28 +340,24 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
for (i = 0; i < num_referrals; i++) {
+ int len;
dump_referral(referrals+i);
- /* connect to a storage node */
- if (referrals[i].flags & DFSREF_STORAGE_SERVER) {
- int len;
- len = strlen(referrals[i].node_name);
- if (len < 2) {
- cERROR(1, ("%s: Net Address path too short: %s",
+ /* connect to a node */
+ len = strlen(referrals[i].node_name);
+ if (len < 2) {
+ cERROR(1, ("%s: Net Address path too short: %s",
__func__, referrals[i].node_name));
- rc = -EINVAL;
- goto out_err;
- }
- mnt = cifs_dfs_do_refmount(nd->path.mnt,
- nd->path.dentry,
- referrals + i);
- cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p",
- __func__,
+ rc = -EINVAL;
+ goto out_err;
+ }
+ mnt = cifs_dfs_do_refmount(nd->path.mnt,
+ nd->path.dentry, referrals + i);
+ cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p", __func__,
referrals[i].node_name, mnt));
- /* complete mount procedure if we accured submount */
- if (!IS_ERR(mnt))
- break;
- }
+ /* complete mount procedure if we accured submount */
+ if (!IS_ERR(mnt))
+ break;
}
/* we need it cause for() above could exit without valid submount */
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
index 3fd3a9df043a..67bf93a40d2e 100644
--- a/fs/cifs/cifs_spnego.c
+++ b/fs/cifs/cifs_spnego.c
@@ -41,7 +41,7 @@ cifs_spnego_key_instantiate(struct key *key, const void *data, size_t datalen)
/* attach the data */
memcpy(payload, data, datalen);
- rcu_assign_pointer(key->payload.data, payload);
+ key->payload.data = payload;
ret = 0;
error:
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 7d75272a6b3f..60e3c4253de0 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -1,7 +1,7 @@
/*
* fs/cifs/cifs_unicode.c
*
- * Copyright (c) International Business Machines Corp., 2000,2005
+ * Copyright (c) International Business Machines Corp., 2000,2009
* Modified by Steve French (sfrench@us.ibm.com)
*
* This program is free software; you can redistribute it and/or modify
@@ -26,31 +26,157 @@
#include "cifs_debug.h"
/*
- * NAME: cifs_strfromUCS()
- *
- * FUNCTION: Convert little-endian unicode string to character string
+ * cifs_ucs2_bytes - how long will a string be after conversion?
+ * @ucs - pointer to input string
+ * @maxbytes - don't go past this many bytes of input string
+ * @codepage - destination codepage
*
+ * Walk a ucs2le string and return the number of bytes that the string will
+ * be after being converted to the given charset, not including any null
+ * termination required. Don't walk past maxbytes in the source buffer.
*/
int
-cifs_strfromUCS_le(char *to, const __le16 *from,
- int len, const struct nls_table *codepage)
+cifs_ucs2_bytes(const __le16 *from, int maxbytes,
+ const struct nls_table *codepage)
{
int i;
- int outlen = 0;
+ int charlen, outlen = 0;
+ int maxwords = maxbytes / 2;
+ char tmp[NLS_MAX_CHARSET_SIZE];
- for (i = 0; (i < len) && from[i]; i++) {
- int charlen;
- /* 2.4.0 kernel or greater */
- charlen =
- codepage->uni2char(le16_to_cpu(from[i]), &to[outlen],
- NLS_MAX_CHARSET_SIZE);
- if (charlen > 0) {
+ for (i = 0; from[i] && i < maxwords; i++) {
+ charlen = codepage->uni2char(le16_to_cpu(from[i]), tmp,
+ NLS_MAX_CHARSET_SIZE);
+ if (charlen > 0)
outlen += charlen;
- } else {
- to[outlen++] = '?';
+ else
+ outlen++;
+ }
+
+ return outlen;
+}
+
+/*
+ * cifs_mapchar - convert a little-endian char to proper char in codepage
+ * @target - where converted character should be copied
+ * @src_char - 2 byte little-endian source character
+ * @cp - codepage to which character should be converted
+ * @mapchar - should character be mapped according to mapchars mount option?
+ *
+ * This function handles the conversion of a single character. It is the
+ * responsibility of the caller to ensure that the target buffer is large
+ * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE).
+ */
+static int
+cifs_mapchar(char *target, const __le16 src_char, const struct nls_table *cp,
+ bool mapchar)
+{
+ int len = 1;
+
+ if (!mapchar)
+ goto cp_convert;
+
+ /*
+ * BB: Cannot handle remapping UNI_SLASH until all the calls to
+ * build_path_from_dentry are modified, as they use slash as
+ * separator.
+ */
+ switch (le16_to_cpu(src_char)) {
+ case UNI_COLON:
+ *target = ':';
+ break;
+ case UNI_ASTERIK:
+ *target = '*';
+ break;
+ case UNI_QUESTION:
+ *target = '?';
+ break;
+ case UNI_PIPE:
+ *target = '|';
+ break;
+ case UNI_GRTRTHAN:
+ *target = '>';
+ break;
+ case UNI_LESSTHAN:
+ *target = '<';
+ break;
+ default:
+ goto cp_convert;
+ }
+
+out:
+ return len;
+
+cp_convert:
+ len = cp->uni2char(le16_to_cpu(src_char), target,
+ NLS_MAX_CHARSET_SIZE);
+ if (len <= 0) {
+ *target = '?';
+ len = 1;
+ }
+ goto out;
+}
+
+/*
+ * cifs_from_ucs2 - convert utf16le string to local charset
+ * @to - destination buffer
+ * @from - source buffer
+ * @tolen - destination buffer size (in bytes)
+ * @fromlen - source buffer size (in bytes)
+ * @codepage - codepage to which characters should be converted
+ * @mapchar - should characters be remapped according to the mapchars option?
+ *
+ * Convert a little-endian ucs2le string (as sent by the server) to a string
+ * in the provided codepage. The tolen and fromlen parameters are to ensure
+ * that the code doesn't walk off of the end of the buffer (which is always
+ * a danger if the alignment of the source buffer is off). The destination
+ * string is always properly null terminated and fits in the destination
+ * buffer. Returns the length of the destination string in bytes (including
+ * null terminator).
+ *
+ * Note that some windows versions actually send multiword UTF-16 characters
+ * instead of straight UCS-2. The linux nls routines however aren't able to
+ * deal with those characters properly. In the event that we get some of
+ * those characters, they won't be translated properly.
+ */
+int
+cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen,
+ const struct nls_table *codepage, bool mapchar)
+{
+ int i, charlen, safelen;
+ int outlen = 0;
+ int nullsize = nls_nullsize(codepage);
+ int fromwords = fromlen / 2;
+ char tmp[NLS_MAX_CHARSET_SIZE];
+
+ /*
+ * because the chars can be of varying widths, we need to take care
+ * not to overflow the destination buffer when we get close to the
+ * end of it. Until we get to this offset, we don't need to check
+ * for overflow however.
+ */
+ safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize);
+
+ for (i = 0; i < fromwords && from[i]; i++) {
+ /*
+ * check to see if converting this character might make the
+ * conversion bleed into the null terminator
+ */
+ if (outlen >= safelen) {
+ charlen = cifs_mapchar(tmp, from[i], codepage, mapchar);
+ if ((outlen + charlen) > (tolen - nullsize))
+ break;
}
+
+ /* put converted char into 'to' buffer */
+ charlen = cifs_mapchar(&to[outlen], from[i], codepage, mapchar);
+ outlen += charlen;
}
- to[outlen] = 0;
+
+ /* properly null-terminate string */
+ for (i = 0; i < nullsize; i++)
+ to[outlen++] = 0;
+
return outlen;
}
@@ -88,3 +214,41 @@ cifs_strtoUCS(__le16 *to, const char *from, int len,
return i;
}
+/*
+ * cifs_strndup_from_ucs - copy a string from wire format to the local codepage
+ * @src - source string
+ * @maxlen - don't walk past this many bytes in the source string
+ * @is_unicode - is this a unicode string?
+ * @codepage - destination codepage
+ *
+ * Take a string given by the server, convert it to the local codepage and
+ * put it in a new buffer. Returns a pointer to the new string or NULL on
+ * error.
+ */
+char *
+cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode,
+ const struct nls_table *codepage)
+{
+ int len;
+ char *dst;
+
+ if (is_unicode) {
+ len = cifs_ucs2_bytes((__le16 *) src, maxlen, codepage);
+ len += nls_nullsize(codepage);
+ dst = kmalloc(len, GFP_KERNEL);
+ if (!dst)
+ return NULL;
+ cifs_from_ucs2(dst, (__le16 *) src, len, maxlen, codepage,
+ false);
+ } else {
+ len = strnlen(src, maxlen);
+ len++;
+ dst = kmalloc(len, GFP_KERNEL);
+ if (!dst)
+ return NULL;
+ strlcpy(dst, src, len);
+ }
+
+ return dst;
+}
+
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h
index 14eb9a2395d3..650638275a6f 100644
--- a/fs/cifs/cifs_unicode.h
+++ b/fs/cifs/cifs_unicode.h
@@ -5,7 +5,7 @@
* Convert a unicode character to upper or lower case using
* compressed tables.
*
- * Copyright (c) International Business Machines Corp., 2000,2007
+ * Copyright (c) International Business Machines Corp., 2000,2009
*
* 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
@@ -37,6 +37,19 @@
#define UNIUPR_NOLOWER /* Example to not expand lower case tables */
+/*
+ * Windows maps these to the user defined 16 bit Unicode range since they are
+ * reserved symbols (along with \ and /), otherwise illegal to store
+ * in filenames in NTFS
+ */
+#define UNI_ASTERIK (__u16) ('*' + 0xF000)
+#define UNI_QUESTION (__u16) ('?' + 0xF000)
+#define UNI_COLON (__u16) (':' + 0xF000)
+#define UNI_GRTRTHAN (__u16) ('>' + 0xF000)
+#define UNI_LESSTHAN (__u16) ('<' + 0xF000)
+#define UNI_PIPE (__u16) ('|' + 0xF000)
+#define UNI_SLASH (__u16) ('\\' + 0xF000)
+
/* Just define what we want from uniupr.h. We don't want to define the tables
* in each source file.
*/
@@ -59,8 +72,14 @@ extern struct UniCaseRange UniLowerRange[];
#endif /* UNIUPR_NOLOWER */
#ifdef __KERNEL__
-int cifs_strfromUCS_le(char *, const __le16 *, int, const struct nls_table *);
+int cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen,
+ const struct nls_table *codepage, bool mapchar);
+int cifs_ucs2_bytes(const __le16 *from, int maxbytes,
+ const struct nls_table *codepage);
int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *);
+char *cifs_strndup_from_ucs(const char *src, const int maxlen,
+ const bool is_unicode,
+ const struct nls_table *codepage);
#endif
/*
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 38491fd3871d..116105c53335 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -35,6 +35,7 @@
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
+#include <linux/smp_lock.h>
#include "cifsfs.h"
#include "cifspdu.h"
#define DECLARE_GLOBALS_HERE
@@ -66,9 +67,6 @@ unsigned int sign_CIFS_PDUs = 1;
extern struct task_struct *oplockThread; /* remove sparse warning */
struct task_struct *oplockThread = NULL;
/* extern struct task_struct * dnotifyThread; remove sparse warning */
-#ifdef CONFIG_CIFS_EXPERIMENTAL
-static struct task_struct *dnotifyThread = NULL;
-#endif
static const struct super_operations cifs_super_ops;
unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
module_param(CIFSMaxBufSize, int, 0);
@@ -206,6 +204,9 @@ cifs_put_super(struct super_block *sb)
cFYI(1, ("Empty cifs superblock info passed to unmount"));
return;
}
+
+ lock_kernel();
+
rc = cifs_umount(sb, cifs_sb);
if (rc)
cERROR(1, ("cifs_umount failed with return code %d", rc));
@@ -218,7 +219,8 @@ cifs_put_super(struct super_block *sb)
unload_nls(cifs_sb->local_nls);
kfree(cifs_sb);
- return;
+
+ unlock_kernel();
}
static int
@@ -316,6 +318,7 @@ cifs_alloc_inode(struct super_block *sb)
cifs_inode->clientCanCacheAll = false;
cifs_inode->delete_pending = false;
cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
+ cifs_inode->server_eof = 0;
/* Can not set i_flags here - they get immediately overwritten
to zero by the VFS */
@@ -532,6 +535,7 @@ static void cifs_umount_begin(struct super_block *sb)
if (tcon == NULL)
return;
+ lock_kernel();
read_lock(&cifs_tcp_ses_lock);
if (tcon->tc_count == 1)
tcon->tidStatus = CifsExiting;
@@ -550,6 +554,7 @@ static void cifs_umount_begin(struct super_block *sb)
}
/* BB FIXME - finish add checks for tidStatus BB */
+ unlock_kernel();
return;
}
@@ -601,8 +606,7 @@ cifs_get_sb(struct file_system_type *fs_type,
rc = cifs_read_super(sb, data, dev_name, flags & MS_SILENT ? 1 : 0);
if (rc) {
- up_write(&sb->s_umount);
- deactivate_super(sb);
+ deactivate_locked_super(sb);
return rc;
}
sb->s_flags |= MS_ACTIVE;
@@ -1040,34 +1044,6 @@ static int cifs_oplock_thread(void *dummyarg)
return 0;
}
-#ifdef CONFIG_CIFS_EXPERIMENTAL
-static int cifs_dnotify_thread(void *dummyarg)
-{
- struct list_head *tmp;
- struct TCP_Server_Info *server;
-
- do {
- if (try_to_freeze())
- continue;
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(15*HZ);
- /* check if any stuck requests that need
- to be woken up and wakeq so the
- thread can wake up and error out */
- read_lock(&cifs_tcp_ses_lock);
- list_for_each(tmp, &cifs_tcp_ses_list) {
- server = list_entry(tmp, struct TCP_Server_Info,
- tcp_ses_list);
- if (atomic_read(&server->inFlight))
- wake_up_all(&server->response_q);
- }
- read_unlock(&cifs_tcp_ses_lock);
- } while (!kthread_should_stop());
-
- return 0;
-}
-#endif
-
static int __init
init_cifs(void)
{
@@ -1144,21 +1120,8 @@ init_cifs(void)
goto out_unregister_dfs_key_type;
}
-#ifdef CONFIG_CIFS_EXPERIMENTAL
- dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd");
- if (IS_ERR(dnotifyThread)) {
- rc = PTR_ERR(dnotifyThread);
- cERROR(1, ("error %d create dnotify thread", rc));
- goto out_stop_oplock_thread;
- }
-#endif
-
return 0;
-#ifdef CONFIG_CIFS_EXPERIMENTAL
- out_stop_oplock_thread:
-#endif
- kthread_stop(oplockThread);
out_unregister_dfs_key_type:
#ifdef CONFIG_CIFS_DFS_UPCALL
unregister_key_type(&key_type_dns_resolver);
@@ -1196,9 +1159,6 @@ exit_cifs(void)
cifs_destroy_inodecache();
cifs_destroy_mids();
cifs_destroy_request_bufs();
-#ifdef CONFIG_CIFS_EXPERIMENTAL
- kthread_stop(dnotifyThread);
-#endif
kthread_stop(oplockThread);
}
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 77e190dc2883..051b71cfdea9 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -100,5 +100,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
extern const struct export_operations cifs_export_ops;
#endif /* EXPERIMENTAL */
-#define CIFS_VERSION "1.57"
+#define CIFS_VERSION "1.58"
#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 9fbf4dff5da6..a61ab772c6f6 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -82,8 +82,8 @@ enum securityEnum {
LANMAN, /* Legacy LANMAN auth */
NTLM, /* Legacy NTLM012 auth with NTLM hash */
NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
- RawNTLMSSP, /* NTLMSSP without SPNEGO */
- NTLMSSP, /* NTLMSSP via SPNEGO */
+ RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */
+ NTLMSSP, /* NTLMSSP via SPNEGO, NTLMv2 hash */
Kerberos, /* Kerberos via SPNEGO */
MSKerberos, /* MS Kerberos via SPNEGO */
};
@@ -350,7 +350,7 @@ struct cifsFileInfo {
bool invalidHandle:1; /* file closed via session abend */
bool 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*/
+ struct mutex fh_mutex; /* prevents reopen race after dead ses*/
struct cifs_search_info srch_inf;
};
@@ -370,6 +370,7 @@ struct cifsInodeInfo {
bool clientCanCacheAll:1; /* read and writebehind oplock */
bool oplockPending:1;
bool delete_pending:1; /* DELETE_ON_CLOSE is set */
+ u64 server_eof; /* current file size on server */
struct inode vfs_inode;
};
@@ -530,6 +531,7 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
#define CIFSSEC_MAY_PLNTXT 0
#endif /* weak passwords */
#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */
+#define CIFSSEC_MAY_NTLMSSP 0x00080 /* raw ntlmssp with ntlmv2 */
#define CIFSSEC_MUST_SIGN 0x01001
/* note that only one of the following can be set so the
@@ -542,22 +544,23 @@ require use of the stronger protocol */
#define CIFSSEC_MUST_LANMAN 0x10010
#define CIFSSEC_MUST_PLNTXT 0x20020
#ifdef CONFIG_CIFS_UPCALL
-#define CIFSSEC_MASK 0x3F03F /* allows weak security but also krb5 */
+#define CIFSSEC_MASK 0xAF0AF /* allows weak security but also krb5 */
#else
-#define CIFSSEC_MASK 0x37037 /* current flags supported if weak */
+#define CIFSSEC_MASK 0xA70A7 /* 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 */
+#define CIFSSEC_MASK 0x8F08F /* flags supported if no weak allowed */
#else
-#define CIFSSEC_MASK 0x07007 /* flags supported if no weak allowed */
+#define CIFSSEC_MASK 0x87087 /* flags supported if no weak allowed */
#endif /* UPCALL */
#endif /* WEAK_PW_HASH */
#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
+#define CIFSSEC_MUST_NTLMSSP 0x80080 /* raw ntlmssp with ntlmv2 */
#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)
+#define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP)
/*
*****************************************************************
* All constants go here
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index b370489c8da5..a785f69dbc9f 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -2163,7 +2163,7 @@ typedef struct {
__le32 Type;
__le64 DevMajor;
__le64 DevMinor;
- __u64 UniqueId;
+ __le64 UniqueId;
__le64 Permissions;
__le64 Nlinks;
} __attribute__((packed)) FILE_UNIX_BASIC_INFO; /* level 0x200 QPathInfo */
@@ -2308,7 +2308,7 @@ struct unlink_psx_rq { /* level 0x20a SetPathInfo */
} __attribute__((packed));
struct file_internal_info {
- __u64 UniqueId; /* inode number */
+ __le64 UniqueId; /* inode number */
} __attribute__((packed)); /* level 0x3ee */
struct file_mode_info {
@@ -2338,7 +2338,7 @@ typedef struct {
__le32 Type;
__le64 DevMajor;
__le64 DevMinor;
- __u64 UniqueId;
+ __le64 UniqueId;
__le64 Permissions;
__le64 Nlinks;
char FileName[1];
@@ -2386,7 +2386,7 @@ typedef struct {
__le32 FileNameLength;
__le32 EaSize; /* EA size */
__le32 Reserved;
- __u64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/
+ __le64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/
char FileName[1];
} __attribute__((packed)) SEARCH_ID_FULL_DIR_INFO; /* level 0x105 FF rsp data */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 4167716d32f2..fae083930eee 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -260,8 +260,7 @@ extern int CIFSUnixCreateSymLink(const int xid,
const struct nls_table *nls_codepage);
extern int CIFSSMBUnixQuerySymLink(const int xid,
struct cifsTconInfo *tcon,
- const unsigned char *searchName,
- char *syminfo, const int buflen,
+ const unsigned char *searchName, char **syminfo,
const struct nls_table *nls_codepage);
extern int CIFSSMBQueryReparseLinkInfo(const int xid,
struct cifsTconInfo *tcon,
@@ -307,8 +306,6 @@ extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName, __u64 *inode_number,
const struct nls_table *nls_codepage,
int remap_special_chars);
-extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen,
- const struct nls_table *codepage);
extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
const struct nls_table *cp, int mapChars);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index bc09c998631f..75e6623a8635 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1,7 +1,7 @@
/*
* fs/cifs/cifssmb.c
*
- * Copyright (C) International Business Machines Corp., 2002,2008
+ * Copyright (C) International Business Machines Corp., 2002,2009
* Author(s): Steve French (sfrench@us.ibm.com)
*
* Contains the routines for constructing the SMB PDUs themselves
@@ -81,41 +81,6 @@ static struct {
#endif /* CONFIG_CIFS_WEAK_PW_HASH */
#endif /* CIFS_POSIX */
-/* Allocates buffer into dst and copies smb string from src to it.
- * caller is responsible for freeing dst if function returned 0.
- * returns:
- * on success - 0
- * on failure - errno
- */
-static int
-cifs_strncpy_to_host(char **dst, const char *src, const int maxlen,
- const bool is_unicode, const struct nls_table *nls_codepage)
-{
- int plen;
-
- if (is_unicode) {
- plen = UniStrnlen((wchar_t *)src, maxlen);
- *dst = kmalloc(plen + 2, GFP_KERNEL);
- if (!*dst)
- goto cifs_strncpy_to_host_ErrExit;
- cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage);
- } else {
- plen = strnlen(src, maxlen);
- *dst = kmalloc(plen + 2, GFP_KERNEL);
- if (!*dst)
- goto cifs_strncpy_to_host_ErrExit;
- strncpy(*dst, src, plen);
- }
- (*dst)[plen] = 0;
- (*dst)[plen+1] = 0; /* harmless for ASCII case, needed for Unicode */
- return 0;
-
-cifs_strncpy_to_host_ErrExit:
- cERROR(1, ("Failed to allocate buffer for string\n"));
- return -ENOMEM;
-}
-
-
/* Mark as invalid, all open files on tree connections since they
were closed when session to server was lost */
static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
@@ -484,6 +449,14 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
cFYI(1, ("Kerberos only mechanism, enable extended security"));
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
}
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+ else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
+ pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
+ else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
+ cFYI(1, ("NTLMSSP only mechanism, enable extended security"));
+ pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
+ }
+#endif
count = 0;
for (i = 0; i < CIFS_NUM_PROT; i++) {
@@ -620,6 +593,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
server->secType = NTLMv2;
else if (secFlags & CIFSSEC_MAY_KRB5)
server->secType = Kerberos;
+ else if (secFlags & CIFSSEC_MAY_NTLMSSP)
+ server->secType = NTLMSSP;
else if (secFlags & CIFSSEC_MAY_LANMAN)
server->secType = LANMAN;
/* #ifdef CONFIG_CIFS_EXPERIMENTAL
@@ -1626,6 +1601,8 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
int smb_hdr_len;
int resp_buf_type = 0;
+ *nbytes = 0;
+
cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
if (tcon->ses->capabilities & CAP_LARGE_FILES) {
@@ -1682,11 +1659,9 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
cifs_stats_inc(&tcon->num_writes);
if (rc) {
cFYI(1, ("Send error Write2 = %d", rc));
- *nbytes = 0;
} else if (resp_buf_type == 0) {
/* presumably this can not happen, but best to be safe */
rc = -EIO;
- *nbytes = 0;
} else {
WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
*nbytes = le16_to_cpu(pSMBr->CountHigh);
@@ -2417,8 +2392,7 @@ winCreateHardLinkRetry:
int
CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
- const unsigned char *searchName,
- char *symlinkinfo, const int buflen,
+ const unsigned char *searchName, char **symlinkinfo,
const struct nls_table *nls_codepage)
{
/* SMB_QUERY_FILE_UNIX_LINK */
@@ -2428,6 +2402,7 @@ CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
int bytes_returned;
int name_len;
__u16 params, byte_count;
+ char *data_start;
cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
@@ -2482,30 +2457,26 @@ querySymLinkRetry:
/* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
- if (rc || (pSMBr->ByteCount < 2))
/* BB also check enough total bytes returned */
- rc = -EIO; /* bad smb */
+ if (rc || (pSMBr->ByteCount < 2))
+ rc = -EIO;
else {
- __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
- __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+ bool is_unicode;
+ u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+
+ data_start = ((char *) &pSMBr->hdr.Protocol) +
+ le16_to_cpu(pSMBr->t2.DataOffset);
+
+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
+ is_unicode = true;
+ else
+ is_unicode = false;
- if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = UniStrnlen((wchar_t *) ((char *)
- &pSMBr->hdr.Protocol + data_offset),
- min_t(const int, buflen, count) / 2);
/* BB FIXME investigate remapping reserved chars here */
- cifs_strfromUCS_le(symlinkinfo,
- (__le16 *) ((char *)&pSMBr->hdr.Protocol
- + data_offset),
- name_len, nls_codepage);
- } else {
- strncpy(symlinkinfo,
- (char *) &pSMBr->hdr.Protocol +
- data_offset,
- min_t(const int, buflen, count));
- }
- symlinkinfo[buflen] = 0;
- /* just in case so calling code does not go off the end of buffer */
+ *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
+ is_unicode, nls_codepage);
+ if (!symlinkinfo)
+ rc = -ENOMEM;
}
}
cifs_buf_release(pSMB);
@@ -2603,7 +2574,6 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata,
*pparmlen = parm_count;
return 0;
}
-#endif /* CIFS_EXPERIMENTAL */
int
CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
@@ -2613,7 +2583,6 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
{
int rc = 0;
int bytes_returned;
- int name_len;
struct smb_com_transaction_ioctl_req *pSMB;
struct smb_com_transaction_ioctl_rsp *pSMBr;
@@ -2650,59 +2619,55 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
} else { /* decode response */
__u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
__u32 data_count = le32_to_cpu(pSMBr->DataCount);
- if ((pSMBr->ByteCount < 2) || (data_offset > 512))
+ if ((pSMBr->ByteCount < 2) || (data_offset > 512)) {
/* BB also check enough total bytes returned */
rc = -EIO; /* bad smb */
- else {
- if (data_count && (data_count < 2048)) {
- char *end_of_smb = 2 /* sizeof byte count */ +
- pSMBr->ByteCount +
- (char *)&pSMBr->ByteCount;
+ goto qreparse_out;
+ }
+ if (data_count && (data_count < 2048)) {
+ char *end_of_smb = 2 /* sizeof byte count */ +
+ pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
- struct reparse_data *reparse_buf =
+ struct reparse_data *reparse_buf =
(struct reparse_data *)
((char *)&pSMBr->hdr.Protocol
+ data_offset);
- if ((char *)reparse_buf >= end_of_smb) {
- rc = -EIO;
- goto qreparse_out;
- }
- if ((reparse_buf->LinkNamesBuf +
- reparse_buf->TargetNameOffset +
- reparse_buf->TargetNameLen) >
- end_of_smb) {
- cFYI(1, ("reparse buf beyond SMB"));
- rc = -EIO;
- goto qreparse_out;
- }
+ if ((char *)reparse_buf >= end_of_smb) {
+ rc = -EIO;
+ goto qreparse_out;
+ }
+ if ((reparse_buf->LinkNamesBuf +
+ reparse_buf->TargetNameOffset +
+ reparse_buf->TargetNameLen) > end_of_smb) {
+ cFYI(1, ("reparse buf beyond SMB"));
+ rc = -EIO;
+ goto qreparse_out;
+ }
- if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = UniStrnlen((wchar_t *)
+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
+ cifs_from_ucs2(symlinkinfo, (__le16 *)
(reparse_buf->LinkNamesBuf +
reparse_buf->TargetNameOffset),
- min(buflen/2,
- reparse_buf->TargetNameLen / 2));
- cifs_strfromUCS_le(symlinkinfo,
- (__le16 *) (reparse_buf->LinkNamesBuf +
- reparse_buf->TargetNameOffset),
- name_len, nls_codepage);
- } else { /* ASCII names */
- strncpy(symlinkinfo,
- reparse_buf->LinkNamesBuf +
- reparse_buf->TargetNameOffset,
- min_t(const int, buflen,
- reparse_buf->TargetNameLen));
- }
- } else {
- rc = -EIO;
- cFYI(1, ("Invalid return data count on "
- "get reparse info ioctl"));
+ buflen,
+ reparse_buf->TargetNameLen,
+ nls_codepage, 0);
+ } else { /* ASCII names */
+ strncpy(symlinkinfo,
+ reparse_buf->LinkNamesBuf +
+ reparse_buf->TargetNameOffset,
+ min_t(const int, buflen,
+ reparse_buf->TargetNameLen));
}
- symlinkinfo[buflen] = 0; /* just in case so the caller
- does not go off the end of the buffer */
- cFYI(1, ("readlink result - %s", symlinkinfo));
+ } else {
+ rc = -EIO;
+ cFYI(1, ("Invalid return data count on "
+ "get reparse info ioctl"));
}
+ symlinkinfo[buflen] = 0; /* just in case so the caller
+ does not go off the end of the buffer */
+ cFYI(1, ("readlink result - %s", symlinkinfo));
}
+
qreparse_out:
cifs_buf_release(pSMB);
@@ -2711,6 +2676,7 @@ qreparse_out:
return rc;
}
+#endif /* CIFS_EXPERIMENTAL */
#ifdef CONFIG_CIFS_POSIX
@@ -3918,7 +3884,7 @@ GetInodeNumberRetry:
}
pfinfo = (struct file_internal_info *)
(data_offset + (char *) &pSMBr->hdr.Protocol);
- *inode_number = pfinfo->UniqueId;
+ *inode_number = le64_to_cpu(pfinfo->UniqueId);
}
}
GetInodeNumOut:
@@ -3928,27 +3894,6 @@ GetInodeNumOut:
return rc;
}
-/* computes length of UCS string converted to host codepage
- * @src: UCS string
- * @maxlen: length of the input string in UCS characters
- * (not in bytes)
- *
- * return: size of input string in host codepage
- */
-static int hostlen_fromUCS(const __le16 *src, const int maxlen,
- const struct nls_table *nls_codepage) {
- int i;
- int hostlen = 0;
- char to[4];
- int charlen;
- for (i = 0; (i < maxlen) && src[i]; ++i) {
- charlen = nls_codepage->uni2char(le16_to_cpu(src[i]),
- to, NLS_MAX_CHARSET_SIZE);
- hostlen += charlen > 0 ? charlen : 1;
- }
- return hostlen;
-}
-
/* parses DFS refferal V3 structure
* caller is responsible for freeing target_nodes
* returns:
@@ -3994,7 +3939,7 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
*num_of_nodes,
- le16_to_cpu(pSMBr->DFSFlags)));
+ le32_to_cpu(pSMBr->DFSFlags)));
*target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
*num_of_nodes, GFP_KERNEL);
@@ -4010,14 +3955,14 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
int max_len;
struct dfs_info3_param *node = (*target_nodes)+i;
- node->flags = le16_to_cpu(pSMBr->DFSFlags);
+ node->flags = le32_to_cpu(pSMBr->DFSFlags);
if (is_unicode) {
__le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
GFP_KERNEL);
cifsConvertToUCS((__le16 *) tmp, searchName,
PATH_MAX, nls_codepage, remap);
- node->path_consumed = hostlen_fromUCS(tmp,
- le16_to_cpu(pSMBr->PathConsumed)/2,
+ node->path_consumed = cifs_ucs2_bytes(tmp,
+ le16_to_cpu(pSMBr->PathConsumed),
nls_codepage);
kfree(tmp);
} else
@@ -4029,20 +3974,24 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
/* copy DfsPath */
temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
max_len = data_end - temp;
- rc = cifs_strncpy_to_host(&(node->path_name), temp,
- max_len, is_unicode, nls_codepage);
- if (rc)
+ node->path_name = cifs_strndup_from_ucs(temp, max_len,
+ is_unicode, nls_codepage);
+ if (IS_ERR(node->path_name)) {
+ rc = PTR_ERR(node->path_name);
+ node->path_name = NULL;
goto parse_DFS_referrals_exit;
+ }
/* copy link target UNC */
temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
max_len = data_end - temp;
- rc = cifs_strncpy_to_host(&(node->node_name), temp,
- max_len, is_unicode, nls_codepage);
- if (rc)
+ node->node_name = cifs_strndup_from_ucs(temp, max_len,
+ is_unicode, nls_codepage);
+ if (IS_ERR(node->node_name)) {
+ rc = PTR_ERR(node->node_name);
+ node->node_name = NULL;
goto parse_DFS_referrals_exit;
-
- ref += le16_to_cpu(ref->Size);
+ }
}
parse_DFS_referrals_exit:
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 0de3b5615a22..4aa81a507b74 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1,7 +1,7 @@
/*
* fs/cifs/connect.c
*
- * Copyright (C) International Business Machines Corp., 2002,2008
+ * Copyright (C) International Business Machines Corp., 2002,2009
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
@@ -32,6 +32,7 @@
#include <linux/kthread.h>
#include <linux/pagevec.h>
#include <linux/freezer.h>
+#include <linux/namei.h>
#include <asm/uaccess.h>
#include <asm/processor.h>
#include <net/ipv6.h>
@@ -978,6 +979,13 @@ cifs_parse_mount_options(char *options, const char *devname,
return 1;
} else if (strnicmp(value, "krb5", 4) == 0) {
vol->secFlg |= CIFSSEC_MAY_KRB5;
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+ } else if (strnicmp(value, "ntlmsspi", 8) == 0) {
+ vol->secFlg |= CIFSSEC_MAY_NTLMSSP |
+ CIFSSEC_MUST_SIGN;
+ } else if (strnicmp(value, "ntlmssp", 7) == 0) {
+ vol->secFlg |= CIFSSEC_MAY_NTLMSSP;
+#endif
} else if (strnicmp(value, "ntlmv2i", 7) == 0) {
vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
CIFSSEC_MUST_SIGN;
@@ -2214,9 +2222,58 @@ is_path_accessible(int xid, struct cifsTconInfo *tcon,
return rc;
}
+static void
+cleanup_volume_info(struct smb_vol **pvolume_info)
+{
+ struct smb_vol *volume_info;
+
+ if (!pvolume_info && !*pvolume_info)
+ return;
+
+ volume_info = *pvolume_info;
+ kzfree(volume_info->password);
+ kfree(volume_info->UNC);
+ kfree(volume_info->prepath);
+ kfree(volume_info);
+ *pvolume_info = NULL;
+ return;
+}
+
+#ifdef CONFIG_CIFS_DFS_UPCALL
+/* build_path_to_root returns full path to root when
+ * we do not have an exiting connection (tcon) */
+static char *
+build_unc_path_to_root(const struct smb_vol *volume_info,
+ const struct cifs_sb_info *cifs_sb)
+{
+ char *full_path;
+
+ int unc_len = strnlen(volume_info->UNC, MAX_TREE_SIZE + 1);
+ full_path = kmalloc(unc_len + cifs_sb->prepathlen + 1, GFP_KERNEL);
+ if (full_path == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ strncpy(full_path, volume_info->UNC, unc_len);
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
+ int i;
+ for (i = 0; i < unc_len; i++) {
+ if (full_path[i] == '\\')
+ full_path[i] = '/';
+ }
+ }
+
+ if (cifs_sb->prepathlen)
+ strncpy(full_path + unc_len, cifs_sb->prepath,
+ cifs_sb->prepathlen);
+
+ full_path[unc_len + cifs_sb->prepathlen] = 0; /* add trailing null */
+ return full_path;
+}
+#endif
+
int
cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
- char *mount_data, const char *devname)
+ char *mount_data_global, const char *devname)
{
int rc = 0;
int xid;
@@ -2225,6 +2282,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
struct cifsTconInfo *tcon = NULL;
struct TCP_Server_Info *srvTcp = NULL;
char *full_path;
+ char *mount_data = mount_data_global;
+#ifdef CONFIG_CIFS_DFS_UPCALL
+ struct dfs_info3_param *referrals = NULL;
+ unsigned int num_referrals = 0;
+ int referral_walks_count = 0;
+try_mount_again:
+#endif
+ full_path = NULL;
xid = GetXid();
@@ -2371,11 +2436,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
}
}
- /* check for null share name ie connect to dfs root */
if ((strchr(volume_info->UNC + 3, '\\') == NULL)
&& (strchr(volume_info->UNC + 3, '/') == NULL)) {
- /* rc = connect_to_dfs_path(...) */
- cFYI(1, ("DFS root not supported"));
+ cERROR(1, ("Missing share name"));
rc = -ENODEV;
goto mount_fail_check;
} else {
@@ -2392,7 +2455,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
}
}
if (rc)
- goto mount_fail_check;
+ goto remote_path_check;
tcon->seal = volume_info->seal;
write_lock(&cifs_tcp_ses_lock);
list_add(&tcon->tcon_list, &pSesInfo->tcon_list);
@@ -2417,19 +2480,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
/* BB FIXME fix time_gran to be larger for LANMAN sessions */
sb->s_time_gran = 100;
-mount_fail_check:
- /* on error free sesinfo and tcon struct if needed */
- if (rc) {
- /* If find_unc succeeded then rc == 0 so we can not end */
- /* up accidently freeing someone elses tcon struct */
- if (tcon)
- cifs_put_tcon(tcon);
- else if (pSesInfo)
- cifs_put_smb_ses(pSesInfo);
- else
- cifs_put_tcp_session(srvTcp);
- goto out;
- }
+ if (rc)
+ goto remote_path_check;
+
cifs_sb->tcon = tcon;
/* do not care if following two calls succeed - informational */
@@ -2461,7 +2514,9 @@ mount_fail_check:
cifs_sb->rsize = min(cifs_sb->rsize,
(tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
- if (!rc && cifs_sb->prepathlen) {
+remote_path_check:
+ /* check if a whole path (including prepath) is not remote */
+ if (!rc && cifs_sb->prepathlen && tcon) {
/* build_path_to_root works only when we have a valid tcon */
full_path = cifs_build_path_to_root(cifs_sb);
if (full_path == NULL) {
@@ -2469,1079 +2524,91 @@ mount_fail_check:
goto mount_fail_check;
}
rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
- if (rc) {
- cERROR(1, ("Path %s in not accessible: %d",
- full_path, rc));
+ if (rc != -EREMOTE) {
kfree(full_path);
goto mount_fail_check;
}
kfree(full_path);
}
- /* volume_info->password is freed above when existing session found
- (in which case it is not needed anymore) but when new sesion is created
- the password ptr is put in the new session structure (in which case the
- password will be freed at unmount time) */
-out:
- /* zero out password before freeing */
- if (volume_info) {
- if (volume_info->password != NULL) {
- memset(volume_info->password, 0,
- strlen(volume_info->password));
- kfree(volume_info->password);
- }
- kfree(volume_info->UNC);
- kfree(volume_info->prepath);
- kfree(volume_info);
- }
- FreeXid(xid);
- return rc;
-}
-
-static int
-CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
- char session_key[CIFS_SESS_KEY_SIZE],
- const struct nls_table *nls_codepage)
-{
- struct smb_hdr *smb_buffer;
- struct smb_hdr *smb_buffer_response;
- SESSION_SETUP_ANDX *pSMB;
- SESSION_SETUP_ANDX *pSMBr;
- char *bcc_ptr;
- char *user;
- char *domain;
- int rc = 0;
- int remaining_words = 0;
- int bytes_returned = 0;
- int len;
- __u32 capabilities;
- __u16 count;
-
- cFYI(1, ("In sesssetup"));
- if (ses == NULL)
- return -EINVAL;
- user = ses->userName;
- domain = ses->domainName;
- smb_buffer = cifs_buf_get();
-
- if (smb_buffer == NULL)
- return -ENOMEM;
-
- smb_buffer_response = smb_buffer;
- pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
-
- /* send SMBsessionSetup here */
- header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
- NULL /* no tCon exists yet */ , 13 /* wct */ );
-
- smb_buffer->Mid = GetNextMid(ses->server);
- pSMB->req_no_secext.AndXCommand = 0xFF;
- pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
- pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
-
- if (ses->server->secMode &
- (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
- smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
-
- capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
- CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
- if (ses->capabilities & CAP_UNICODE) {
- smb_buffer->Flags2 |= SMBFLG2_UNICODE;
- capabilities |= CAP_UNICODE;
- }
- if (ses->capabilities & CAP_STATUS32) {
- smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
- capabilities |= CAP_STATUS32;
- }
- if (ses->capabilities & CAP_DFS) {
- smb_buffer->Flags2 |= SMBFLG2_DFS;
- capabilities |= CAP_DFS;
- }
- pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
-
- pSMB->req_no_secext.CaseInsensitivePasswordLength =
- cpu_to_le16(CIFS_SESS_KEY_SIZE);
-
- pSMB->req_no_secext.CaseSensitivePasswordLength =
- cpu_to_le16(CIFS_SESS_KEY_SIZE);
- bcc_ptr = pByteArea(smb_buffer);
- memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
- bcc_ptr += CIFS_SESS_KEY_SIZE;
- memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
- bcc_ptr += CIFS_SESS_KEY_SIZE;
-
- if (ses->capabilities & CAP_UNICODE) {
- if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
- *bcc_ptr = 0;
- bcc_ptr++;
- }
- if (user == NULL)
- bytes_returned = 0; /* skip null user */
- else
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
- nls_codepage);
- /* convert number of 16 bit words to bytes */
- bcc_ptr += 2 * bytes_returned;
- bcc_ptr += 2; /* trailing null */
- if (domain == NULL)
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr,
- "CIFS_LINUX_DOM", 32, nls_codepage);
- else
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
- nls_codepage);
- bcc_ptr += 2 * bytes_returned;
- bcc_ptr += 2;
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
- 32, nls_codepage);
- bcc_ptr += 2 * bytes_returned;
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release,
- 32, nls_codepage);
- bcc_ptr += 2 * bytes_returned;
- bcc_ptr += 2;
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
- 64, nls_codepage);
- bcc_ptr += 2 * bytes_returned;
- bcc_ptr += 2;
- } else {
- if (user != NULL) {
- strncpy(bcc_ptr, user, 200);
- bcc_ptr += strnlen(user, 200);
- }
- *bcc_ptr = 0;
- bcc_ptr++;
- if (domain == NULL) {
- strcpy(bcc_ptr, "CIFS_LINUX_DOM");
- bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
- } else {
- strncpy(bcc_ptr, domain, 64);
- bcc_ptr += strnlen(domain, 64);
- *bcc_ptr = 0;
- bcc_ptr++;
- }
- strcpy(bcc_ptr, "Linux version ");
- bcc_ptr += strlen("Linux version ");
- strcpy(bcc_ptr, utsname()->release);
- bcc_ptr += strlen(utsname()->release) + 1;
- strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
- bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
- }
- count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
- smb_buffer->smb_buf_length += count;
- pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
-
- rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
- &bytes_returned, CIFS_LONG_OP);
- if (rc) {
-/* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
- } 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);
- if (action & GUEST_LOGIN)
- cFYI(1, ("Guest login")); /* BB mark SesInfo struct? */
- ses->Suid = smb_buffer_response->Uid; /* UID left in wire format
- (little endian) */
- cFYI(1, ("UID = %d ", ses->Suid));
- /* response can have either 3 or 4 word count - Samba sends 3 */
- bcc_ptr = pByteArea(smb_buffer_response);
- if ((pSMBr->resp.hdr.WordCount == 3)
- || ((pSMBr->resp.hdr.WordCount == 4)
- && (blob_len < pSMBr->resp.ByteCount))) {
- if (pSMBr->resp.hdr.WordCount == 4)
- bcc_ptr += blob_len;
-
- if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
- if ((long) (bcc_ptr) % 2) {
- remaining_words =
- (BCC(smb_buffer_response) - 1) / 2;
- /* Unicode strings must be word
- aligned */
- bcc_ptr++;
- } else {
- remaining_words =
- BCC(smb_buffer_response) / 2;
- }
- 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 */
- if (ses->serverOS)
- kfree(ses->serverOS);
- ses->serverOS = kzalloc(2 * (len + 1),
- GFP_KERNEL);
- if (ses->serverOS == NULL)
- goto sesssetup_nomem;
- cifs_strfromUCS_le(ses->serverOS,
- (__le16 *)bcc_ptr,
- len, nls_codepage);
- bcc_ptr += 2 * (len + 1);
- remaining_words -= len + 1;
- ses->serverOS[2 * len] = 0;
- ses->serverOS[1 + (2 * len)] = 0;
- if (remaining_words > 0) {
- len = UniStrnlen((wchar_t *)bcc_ptr,
- remaining_words-1);
- kfree(ses->serverNOS);
- ses->serverNOS = kzalloc(2 * (len + 1),
- GFP_KERNEL);
- if (ses->serverNOS == NULL)
- goto sesssetup_nomem;
- cifs_strfromUCS_le(ses->serverNOS,
- (__le16 *)bcc_ptr,
- len, nls_codepage);
- bcc_ptr += 2 * (len + 1);
- ses->serverNOS[2 * len] = 0;
- ses->serverNOS[1 + (2 * len)] = 0;
- if (strncmp(ses->serverNOS,
- "NT LAN Manager 4", 16) == 0) {
- cFYI(1, ("NT4 server"));
- ses->flags |= CIFS_SES_NT4;
- }
- remaining_words -= len + 1;
- if (remaining_words > 0) {
- len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
- /* last string is not always null terminated
- (for e.g. for Windows XP & 2000) */
- if (ses->serverDomain)
- kfree(ses->serverDomain);
- ses->serverDomain =
- kzalloc(2*(len+1),
- GFP_KERNEL);
- if (ses->serverDomain == NULL)
- goto sesssetup_nomem;
- cifs_strfromUCS_le(ses->serverDomain,
- (__le16 *)bcc_ptr,
- len, nls_codepage);
- bcc_ptr += 2 * (len + 1);
- ses->serverDomain[2*len] = 0;
- ses->serverDomain[1+(2*len)] = 0;
- } else { /* else no more room so create
- dummy domain string */
- if (ses->serverDomain)
- kfree(ses->serverDomain);
- ses->serverDomain =
- kzalloc(2, GFP_KERNEL);
- }
- } else { /* no room so create dummy domain
- and NOS string */
-
- /* if these kcallocs fail not much we
- can do, but better to not fail the
- sesssetup itself */
- kfree(ses->serverDomain);
- ses->serverDomain =
- kzalloc(2, GFP_KERNEL);
- kfree(ses->serverNOS);
- ses->serverNOS =
- kzalloc(2, GFP_KERNEL);
- }
- } else { /* ASCII */
- len = strnlen(bcc_ptr, 1024);
- if (((long) bcc_ptr + len) - (long)
- pByteArea(smb_buffer_response)
- <= BCC(smb_buffer_response)) {
- kfree(ses->serverOS);
- ses->serverOS = kzalloc(len + 1,
- GFP_KERNEL);
- if (ses->serverOS == NULL)
- goto sesssetup_nomem;
- strncpy(ses->serverOS, bcc_ptr, len);
-
- bcc_ptr += len;
- /* null terminate the string */
- bcc_ptr[0] = 0;
- bcc_ptr++;
-
- len = strnlen(bcc_ptr, 1024);
- kfree(ses->serverNOS);
- ses->serverNOS = kzalloc(len + 1,
- GFP_KERNEL);
- if (ses->serverNOS == NULL)
- goto sesssetup_nomem;
- strncpy(ses->serverNOS, bcc_ptr, len);
- bcc_ptr += len;
- bcc_ptr[0] = 0;
- bcc_ptr++;
-
- len = strnlen(bcc_ptr, 1024);
- if (ses->serverDomain)
- kfree(ses->serverDomain);
- ses->serverDomain = kzalloc(len + 1,
- GFP_KERNEL);
- if (ses->serverDomain == NULL)
- goto sesssetup_nomem;
- strncpy(ses->serverDomain, bcc_ptr,
- len);
- bcc_ptr += len;
- bcc_ptr[0] = 0;
- bcc_ptr++;
- } else
- cFYI(1,
- ("Variable field of length %d "
- "extends beyond end of smb ",
- len));
- }
- } else {
- cERROR(1, ("Security Blob Length extends beyond "
- "end of SMB"));
+ /* get referral if needed */
+ if (rc == -EREMOTE) {
+#ifdef CONFIG_CIFS_DFS_UPCALL
+ if (referral_walks_count > MAX_NESTED_LINKS) {
+ /*
+ * BB: when we implement proper loop detection,
+ * we will remove this check. But now we need it
+ * to prevent an indefinite loop if 'DFS tree' is
+ * misconfigured (i.e. has loops).
+ */
+ rc = -ELOOP;
+ goto mount_fail_check;
}
- } else {
- cERROR(1, ("Invalid Word count %d: ",
- smb_buffer_response->WordCount));
- rc = -EIO;
- }
-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 */
- cifs_buf_release(smb_buffer);
-
- return rc;
-}
-
-static int
-CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
- struct cifsSesInfo *ses, bool *pNTLMv2_flag,
- const struct nls_table *nls_codepage)
-{
- struct smb_hdr *smb_buffer;
- struct smb_hdr *smb_buffer_response;
- SESSION_SETUP_ANDX *pSMB;
- SESSION_SETUP_ANDX *pSMBr;
- char *bcc_ptr;
- char *domain;
- int rc = 0;
- int remaining_words = 0;
- int bytes_returned = 0;
- int len;
- int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE);
- PNEGOTIATE_MESSAGE SecurityBlob;
- PCHALLENGE_MESSAGE SecurityBlob2;
- __u32 negotiate_flags, capabilities;
- __u16 count;
-
- cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
- if (ses == NULL)
- return -EINVAL;
- domain = ses->domainName;
- *pNTLMv2_flag = false;
- smb_buffer = cifs_buf_get();
- if (smb_buffer == NULL) {
- return -ENOMEM;
- }
- smb_buffer_response = smb_buffer;
- 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,
- NULL /* no tCon exists yet */ , 12 /* wct */ );
-
- smb_buffer->Mid = GetNextMid(ses->server);
- pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
- pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
-
- pSMB->req.AndXCommand = 0xFF;
- pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
- pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
-
- if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
- smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
-
- capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
- CAP_EXTENDED_SECURITY;
- if (ses->capabilities & CAP_UNICODE) {
- smb_buffer->Flags2 |= SMBFLG2_UNICODE;
- capabilities |= CAP_UNICODE;
- }
- if (ses->capabilities & CAP_STATUS32) {
- smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
- capabilities |= CAP_STATUS32;
- }
- if (ses->capabilities & CAP_DFS) {
- smb_buffer->Flags2 |= SMBFLG2_DFS;
- capabilities |= CAP_DFS;
- }
- pSMB->req.Capabilities = cpu_to_le32(capabilities);
-
- bcc_ptr = (char *) &pSMB->req.SecurityBlob;
- SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
- strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
- SecurityBlob->MessageType = NtLmNegotiate;
- negotiate_flags =
- NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
- NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
- NTLMSSP_NEGOTIATE_56 |
- /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
- if (sign_CIFS_PDUs)
- negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
-/* if (ntlmv2_support)
- negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
- /* setup pointers to domain name and workstation name */
- bcc_ptr += SecurityBlobLength;
-
- SecurityBlob->WorkstationName.Buffer = 0;
- SecurityBlob->WorkstationName.Length = 0;
- SecurityBlob->WorkstationName.MaximumLength = 0;
-
- /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent
- along with username on auth request (ie the response to challenge) */
- SecurityBlob->DomainName.Buffer = 0;
- SecurityBlob->DomainName.Length = 0;
- SecurityBlob->DomainName.MaximumLength = 0;
- if (ses->capabilities & CAP_UNICODE) {
- if ((long) bcc_ptr % 2) {
- *bcc_ptr = 0;
- bcc_ptr++;
+ /* convert forward to back slashes in prepath here if needed */
+ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
+ convert_delimiter(cifs_sb->prepath,
+ CIFS_DIR_SEP(cifs_sb));
+ full_path = build_unc_path_to_root(volume_info, cifs_sb);
+ if (IS_ERR(full_path)) {
+ rc = PTR_ERR(full_path);
+ goto mount_fail_check;
}
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
- 32, nls_codepage);
- bcc_ptr += 2 * bytes_returned;
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
- nls_codepage);
- bcc_ptr += 2 * bytes_returned;
- bcc_ptr += 2; /* null terminate Linux version */
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
- 64, nls_codepage);
- bcc_ptr += 2 * bytes_returned;
- *(bcc_ptr + 1) = 0;
- *(bcc_ptr + 2) = 0;
- bcc_ptr += 2; /* null terminate network opsys string */
- *(bcc_ptr + 1) = 0;
- *(bcc_ptr + 2) = 0;
- bcc_ptr += 2; /* null domain */
- } else { /* ASCII */
- strcpy(bcc_ptr, "Linux version ");
- bcc_ptr += strlen("Linux version ");
- strcpy(bcc_ptr, utsname()->release);
- bcc_ptr += strlen(utsname()->release) + 1;
- strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
- bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
- bcc_ptr++; /* empty domain field */
- *bcc_ptr = 0;
- }
- SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
- pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
- count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
- smb_buffer->smb_buf_length += count;
- pSMB->req.ByteCount = cpu_to_le16(count);
-
- rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
- &bytes_returned, CIFS_LONG_OP);
-
- if (smb_buffer_response->Status.CifsError ==
- cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
- rc = 0;
-
- 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)) {
- __u16 action = le16_to_cpu(pSMBr->resp.Action);
- __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
-
- if (action & GUEST_LOGIN)
- cFYI(1, ("Guest login"));
- /* Do we want to set anything in SesInfo struct when guest login? */
-
- bcc_ptr = pByteArea(smb_buffer_response);
- /* response can have either 3 or 4 word count - Samba sends 3 */
-
- SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
- if (SecurityBlob2->MessageType != NtLmChallenge) {
- cFYI(1, ("Unexpected NTLMSSP message type received %d",
- SecurityBlob2->MessageType));
- } else if (ses) {
- ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
- cFYI(1, ("UID = %d", ses->Suid));
- if ((pSMBr->resp.hdr.WordCount == 3)
- || ((pSMBr->resp.hdr.WordCount == 4)
- && (blob_len <
- pSMBr->resp.ByteCount))) {
-
- if (pSMBr->resp.hdr.WordCount == 4) {
- bcc_ptr += blob_len;
- cFYI(1, ("Security Blob Length %d",
- blob_len));
- }
-
- cFYI(1, ("NTLMSSP Challenge rcvd"));
-
- memcpy(ses->server->cryptKey,
- SecurityBlob2->Challenge,
- CIFS_CRYPTO_KEY_SIZE);
- if (SecurityBlob2->NegotiateFlags &
- cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
- *pNTLMv2_flag = true;
-
- if ((SecurityBlob2->NegotiateFlags &
- cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
- || (sign_CIFS_PDUs > 1))
- ses->server->secMode |=
- SECMODE_SIGN_REQUIRED;
- if ((SecurityBlob2->NegotiateFlags &
- cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
- ses->server->secMode |=
- SECMODE_SIGN_ENABLED;
-
- if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
- if ((long) (bcc_ptr) % 2) {
- remaining_words =
- (BCC(smb_buffer_response)
- - 1) / 2;
- /* Must word align unicode strings */
- bcc_ptr++;
- } else {
- remaining_words =
- BCC
- (smb_buffer_response) / 2;
- }
- 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 */
- if (ses->serverOS)
- kfree(ses->serverOS);
- ses->serverOS =
- kzalloc(2 * (len + 1), GFP_KERNEL);
- cifs_strfromUCS_le(ses->serverOS,
- (__le16 *)
- bcc_ptr, len,
- nls_codepage);
- bcc_ptr += 2 * (len + 1);
- remaining_words -= len + 1;
- ses->serverOS[2 * len] = 0;
- ses->serverOS[1 + (2 * len)] = 0;
- if (remaining_words > 0) {
- len = UniStrnlen((wchar_t *)
- bcc_ptr,
- remaining_words
- - 1);
- kfree(ses->serverNOS);
- ses->serverNOS =
- kzalloc(2 * (len + 1),
- GFP_KERNEL);
- cifs_strfromUCS_le(ses->
- serverNOS,
- (__le16 *)
- bcc_ptr,
- len,
- nls_codepage);
- bcc_ptr += 2 * (len + 1);
- ses->serverNOS[2 * len] = 0;
- ses->serverNOS[1 +
- (2 * len)] = 0;
- remaining_words -= len + 1;
- if (remaining_words > 0) {
- len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
- /* last string not always null terminated
- (for e.g. for Windows XP & 2000) */
- kfree(ses->serverDomain);
- ses->serverDomain =
- kzalloc(2 *
- (len +
- 1),
- GFP_KERNEL);
- cifs_strfromUCS_le
- (ses->serverDomain,
- (__le16 *)bcc_ptr,
- len, nls_codepage);
- bcc_ptr +=
- 2 * (len + 1);
- ses->serverDomain[2*len]
- = 0;
- ses->serverDomain
- [1 + (2 * len)]
- = 0;
- } /* else no more room so create dummy domain string */
- else {
- kfree(ses->serverDomain);
- ses->serverDomain =
- kzalloc(2,
- GFP_KERNEL);
- }
- } else { /* no room so create dummy domain and NOS string */
- kfree(ses->serverDomain);
- ses->serverDomain =
- kzalloc(2, GFP_KERNEL);
- kfree(ses->serverNOS);
- ses->serverNOS =
- kzalloc(2, GFP_KERNEL);
- }
- } else { /* ASCII */
- len = strnlen(bcc_ptr, 1024);
- if (((long) bcc_ptr + len) - (long)
- pByteArea(smb_buffer_response)
- <= BCC(smb_buffer_response)) {
- if (ses->serverOS)
- kfree(ses->serverOS);
- ses->serverOS =
- kzalloc(len + 1,
- GFP_KERNEL);
- strncpy(ses->serverOS,
- bcc_ptr, len);
-
- bcc_ptr += len;
- bcc_ptr[0] = 0; /* null terminate string */
- bcc_ptr++;
-
- len = strnlen(bcc_ptr, 1024);
- kfree(ses->serverNOS);
- ses->serverNOS =
- kzalloc(len + 1,
- GFP_KERNEL);
- strncpy(ses->serverNOS, bcc_ptr, len);
- bcc_ptr += len;
- bcc_ptr[0] = 0;
- bcc_ptr++;
-
- len = strnlen(bcc_ptr, 1024);
- kfree(ses->serverDomain);
- ses->serverDomain =
- kzalloc(len + 1,
- GFP_KERNEL);
- strncpy(ses->serverDomain,
- bcc_ptr, len);
- bcc_ptr += len;
- bcc_ptr[0] = 0;
- bcc_ptr++;
- } else
- cFYI(1,
- ("field of length %d "
- "extends beyond end of smb",
- len));
- }
- } else {
- cERROR(1, ("Security Blob Length extends beyond"
- " end of SMB"));
- }
- } else {
- cERROR(1, ("No session structure passed in."));
+ cFYI(1, ("Getting referral for: %s", full_path));
+ rc = get_dfs_path(xid, pSesInfo , full_path + 1,
+ cifs_sb->local_nls, &num_referrals, &referrals,
+ cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+ if (!rc && num_referrals > 0) {
+ char *fake_devname = NULL;
+
+ if (mount_data != mount_data_global)
+ kfree(mount_data);
+ mount_data = cifs_compose_mount_options(
+ cifs_sb->mountdata, full_path + 1,
+ referrals, &fake_devname);
+ kfree(fake_devname);
+ free_dfs_info_array(referrals, num_referrals);
+
+ if (tcon)
+ cifs_put_tcon(tcon);
+ else if (pSesInfo)
+ cifs_put_smb_ses(pSesInfo);
+
+ cleanup_volume_info(&volume_info);
+ FreeXid(xid);
+ kfree(full_path);
+ referral_walks_count++;
+ goto try_mount_again;
}
- } else {
- cERROR(1, ("Invalid Word count %d:",
- smb_buffer_response->WordCount));
- rc = -EIO;
- }
-
- cifs_buf_release(smb_buffer);
-
- return rc;
-}
-static int
-CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
- char *ntlm_session_key, bool ntlmv2_flag,
- const struct nls_table *nls_codepage)
-{
- struct smb_hdr *smb_buffer;
- struct smb_hdr *smb_buffer_response;
- SESSION_SETUP_ANDX *pSMB;
- SESSION_SETUP_ANDX *pSMBr;
- char *bcc_ptr;
- char *user;
- char *domain;
- int rc = 0;
- int remaining_words = 0;
- int bytes_returned = 0;
- int len;
- int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE);
- PAUTHENTICATE_MESSAGE SecurityBlob;
- __u32 negotiate_flags, capabilities;
- __u16 count;
-
- cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
- if (ses == NULL)
- return -EINVAL;
- user = ses->userName;
- domain = ses->domainName;
- smb_buffer = cifs_buf_get();
- if (smb_buffer == NULL) {
- return -ENOMEM;
- }
- smb_buffer_response = smb_buffer;
- 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,
- NULL /* no tCon exists yet */ , 12 /* wct */ );
-
- smb_buffer->Mid = GetNextMid(ses->server);
- pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
- pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
- pSMB->req.AndXCommand = 0xFF;
- pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
- pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
-
- pSMB->req.hdr.Uid = ses->Suid;
-
- if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
- smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
-
- capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
- CAP_EXTENDED_SECURITY;
- if (ses->capabilities & CAP_UNICODE) {
- smb_buffer->Flags2 |= SMBFLG2_UNICODE;
- capabilities |= CAP_UNICODE;
- }
- if (ses->capabilities & CAP_STATUS32) {
- smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
- capabilities |= CAP_STATUS32;
+#else /* No DFS support, return error on mount */
+ rc = -EOPNOTSUPP;
+#endif
}
- if (ses->capabilities & CAP_DFS) {
- smb_buffer->Flags2 |= SMBFLG2_DFS;
- capabilities |= CAP_DFS;
- }
- pSMB->req.Capabilities = cpu_to_le32(capabilities);
-
- 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;
- if (sign_CIFS_PDUs)
- negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
- if (ntlmv2_flag)
- negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
-
-/* setup pointers to domain name and workstation name */
-
- SecurityBlob->WorkstationName.Buffer = 0;
- SecurityBlob->WorkstationName.Length = 0;
- SecurityBlob->WorkstationName.MaximumLength = 0;
- SecurityBlob->SessionKey.Length = 0;
- SecurityBlob->SessionKey.MaximumLength = 0;
- SecurityBlob->SessionKey.Buffer = 0;
-
- SecurityBlob->LmChallengeResponse.Length = 0;
- SecurityBlob->LmChallengeResponse.MaximumLength = 0;
- SecurityBlob->LmChallengeResponse.Buffer = 0;
-
- SecurityBlob->NtChallengeResponse.Length =
- cpu_to_le16(CIFS_SESS_KEY_SIZE);
- SecurityBlob->NtChallengeResponse.MaximumLength =
- cpu_to_le16(CIFS_SESS_KEY_SIZE);
- memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
- SecurityBlob->NtChallengeResponse.Buffer =
- cpu_to_le32(SecurityBlobLength);
- SecurityBlobLength += CIFS_SESS_KEY_SIZE;
- bcc_ptr += CIFS_SESS_KEY_SIZE;
- if (ses->capabilities & CAP_UNICODE) {
- if (domain == NULL) {
- SecurityBlob->DomainName.Buffer = 0;
- SecurityBlob->DomainName.Length = 0;
- SecurityBlob->DomainName.MaximumLength = 0;
- } else {
- __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
- nls_codepage);
- ln *= 2;
- SecurityBlob->DomainName.MaximumLength =
- cpu_to_le16(ln);
- SecurityBlob->DomainName.Buffer =
- cpu_to_le32(SecurityBlobLength);
- 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 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
- nls_codepage);
- ln *= 2;
- SecurityBlob->UserName.MaximumLength =
- cpu_to_le16(ln);
- SecurityBlob->UserName.Buffer =
- cpu_to_le32(SecurityBlobLength);
- bcc_ptr += ln;
- SecurityBlobLength += ln;
- SecurityBlob->UserName.Length = cpu_to_le16(ln);
- }
-
- /* SecurityBlob->WorkstationName.Length =
- cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
- SecurityBlob->WorkstationName.Length *= 2;
- SecurityBlob->WorkstationName.MaximumLength =
- cpu_to_le16(SecurityBlob->WorkstationName.Length);
- SecurityBlob->WorkstationName.Buffer =
- cpu_to_le32(SecurityBlobLength);
- bcc_ptr += SecurityBlob->WorkstationName.Length;
- SecurityBlobLength += SecurityBlob->WorkstationName.Length;
- SecurityBlob->WorkstationName.Length =
- cpu_to_le16(SecurityBlob->WorkstationName.Length); */
-
- if ((long) bcc_ptr % 2) {
- *bcc_ptr = 0;
- bcc_ptr++;
- }
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
- 32, nls_codepage);
- bcc_ptr += 2 * bytes_returned;
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
- nls_codepage);
- bcc_ptr += 2 * bytes_returned;
- bcc_ptr += 2; /* null term version string */
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
- 64, nls_codepage);
- bcc_ptr += 2 * bytes_returned;
- *(bcc_ptr + 1) = 0;
- *(bcc_ptr + 2) = 0;
- bcc_ptr += 2; /* null terminate network opsys string */
- *(bcc_ptr + 1) = 0;
- *(bcc_ptr + 2) = 0;
- bcc_ptr += 2; /* null domain */
- } else { /* ASCII */
- if (domain == NULL) {
- SecurityBlob->DomainName.Buffer = 0;
- SecurityBlob->DomainName.Length = 0;
- SecurityBlob->DomainName.MaximumLength = 0;
- } else {
- __u16 ln;
- negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
- strncpy(bcc_ptr, domain, 63);
- ln = strnlen(domain, 64);
- SecurityBlob->DomainName.MaximumLength =
- cpu_to_le16(ln);
- SecurityBlob->DomainName.Buffer =
- cpu_to_le32(SecurityBlobLength);
- 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 ln;
- strncpy(bcc_ptr, user, 63);
- ln = strnlen(user, 64);
- SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln);
- SecurityBlob->UserName.Buffer =
- 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 */
-
- strcpy(bcc_ptr, "Linux version ");
- bcc_ptr += strlen("Linux version ");
- strcpy(bcc_ptr, utsname()->release);
- bcc_ptr += strlen(utsname()->release) + 1;
- strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
- bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
- bcc_ptr++; /* null domain */
- *bcc_ptr = 0;
- }
- SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
- pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
- count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
- smb_buffer->smb_buf_length += count;
- pSMB->req.ByteCount = cpu_to_le16(count);
-
- rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
- &bytes_returned, CIFS_LONG_OP);
+mount_fail_check:
+ /* on error free sesinfo and tcon struct if needed */
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)) {
- __u16 action = le16_to_cpu(pSMBr->resp.Action);
- __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 ? */
-/* if (SecurityBlob2->MessageType != NtLm??) {
- cFYI("Unexpected message type on auth response is %d"));
- } */
-
- if (ses) {
- cFYI(1,
- ("Check challenge UID %d vs auth response UID %d",
- ses->Suid, smb_buffer_response->Uid));
- /* UID left in wire format */
- ses->Suid = smb_buffer_response->Uid;
- bcc_ptr = pByteArea(smb_buffer_response);
- /* response can have either 3 or 4 word count - Samba sends 3 */
- if ((pSMBr->resp.hdr.WordCount == 3)
- || ((pSMBr->resp.hdr.WordCount == 4)
- && (blob_len <
- pSMBr->resp.ByteCount))) {
- if (pSMBr->resp.hdr.WordCount == 4) {
- bcc_ptr +=
- blob_len;
- cFYI(1,
- ("Security Blob Length %d ",
- blob_len));
- }
-
- cFYI(1,
- ("NTLMSSP response to Authenticate "));
-
- if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
- if ((long) (bcc_ptr) % 2) {
- remaining_words =
- (BCC(smb_buffer_response)
- - 1) / 2;
- bcc_ptr++; /* Unicode strings must be word aligned */
- } else {
- remaining_words = BCC(smb_buffer_response) / 2;
- }
- 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 */
- if (ses->serverOS)
- kfree(ses->serverOS);
- ses->serverOS =
- kzalloc(2 * (len + 1), GFP_KERNEL);
- cifs_strfromUCS_le(ses->serverOS,
- (__le16 *)
- bcc_ptr, len,
- nls_codepage);
- bcc_ptr += 2 * (len + 1);
- remaining_words -= len + 1;
- ses->serverOS[2 * len] = 0;
- ses->serverOS[1 + (2 * len)] = 0;
- if (remaining_words > 0) {
- len = UniStrnlen((wchar_t *)
- bcc_ptr,
- remaining_words
- - 1);
- kfree(ses->serverNOS);
- ses->serverNOS =
- kzalloc(2 * (len + 1),
- GFP_KERNEL);
- cifs_strfromUCS_le(ses->
- serverNOS,
- (__le16 *)
- bcc_ptr,
- len,
- nls_codepage);
- bcc_ptr += 2 * (len + 1);
- ses->serverNOS[2 * len] = 0;
- ses->serverNOS[1+(2*len)] = 0;
- remaining_words -= len + 1;
- if (remaining_words > 0) {
- len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
- /* last string not always null terminated (e.g. for Windows XP & 2000) */
- if (ses->serverDomain)
- kfree(ses->serverDomain);
- ses->serverDomain =
- kzalloc(2 *
- (len +
- 1),
- GFP_KERNEL);
- cifs_strfromUCS_le
- (ses->
- serverDomain,
- (__le16 *)
- bcc_ptr, len,
- nls_codepage);
- bcc_ptr +=
- 2 * (len + 1);
- ses->
- serverDomain[2
- * len]
- = 0;
- ses->
- serverDomain[1
- +
- (2
- *
- len)]
- = 0;
- } /* else no more room so create dummy domain string */
- else {
- if (ses->serverDomain)
- kfree(ses->serverDomain);
- ses->serverDomain = kzalloc(2,GFP_KERNEL);
- }
- } else { /* no room so create dummy domain and NOS string */
- if (ses->serverDomain)
- kfree(ses->serverDomain);
- ses->serverDomain = kzalloc(2, GFP_KERNEL);
- kfree(ses->serverNOS);
- ses->serverNOS = kzalloc(2, GFP_KERNEL);
- }
- } else { /* ASCII */
- len = strnlen(bcc_ptr, 1024);
- if (((long) bcc_ptr + len) -
- (long) pByteArea(smb_buffer_response)
- <= BCC(smb_buffer_response)) {
- if (ses->serverOS)
- kfree(ses->serverOS);
- ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
- strncpy(ses->serverOS,bcc_ptr, len);
-
- bcc_ptr += len;
- bcc_ptr[0] = 0; /* null terminate the string */
- bcc_ptr++;
-
- len = strnlen(bcc_ptr, 1024);
- kfree(ses->serverNOS);
- ses->serverNOS = kzalloc(len+1,
- GFP_KERNEL);
- strncpy(ses->serverNOS,
- bcc_ptr, len);
- bcc_ptr += len;
- bcc_ptr[0] = 0;
- bcc_ptr++;
-
- len = strnlen(bcc_ptr, 1024);
- if (ses->serverDomain)
- kfree(ses->serverDomain);
- ses->serverDomain =
- kzalloc(len+1,
- GFP_KERNEL);
- strncpy(ses->serverDomain,
- bcc_ptr, len);
- bcc_ptr += len;
- bcc_ptr[0] = 0;
- bcc_ptr++;
- } else
- cFYI(1, ("field of length %d "
- "extends beyond end of smb ",
- len));
- }
- } else {
- cERROR(1, ("Security Blob extends beyond end "
- "of SMB"));
- }
- } else {
- cERROR(1, ("No session structure passed in."));
- }
- } else {
- cERROR(1, ("Invalid Word count %d: ",
- smb_buffer_response->WordCount));
- rc = -EIO;
+ if (mount_data != mount_data_global)
+ kfree(mount_data);
+ /* If find_unc succeeded then rc == 0 so we can not end */
+ /* up accidently freeing someone elses tcon struct */
+ if (tcon)
+ cifs_put_tcon(tcon);
+ else if (pSesInfo)
+ cifs_put_smb_ses(pSesInfo);
+ else
+ cifs_put_tcp_session(srvTcp);
+ goto out;
}
- cifs_buf_release(smb_buffer);
-
+ /* volume_info->password is freed above when existing session found
+ (in which case it is not needed anymore) but when new sesion is created
+ the password ptr is put in the new session structure (in which case the
+ password will be freed at unmount time) */
+out:
+ /* zero out password before freeing */
+ cleanup_volume_info(&volume_info);
+ FreeXid(xid);
return rc;
}
@@ -3556,7 +2623,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
TCONX_RSP *pSMBr;
unsigned char *bcc_ptr;
int rc = 0;
- int length;
+ int length, bytes_left;
__u16 count;
if (ses == NULL)
@@ -3644,14 +2711,22 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
CIFS_STD_OP);
- /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
/* above now done in SendReceive */
if ((rc == 0) && (tcon != NULL)) {
+ bool is_unicode;
+
tcon->tidStatus = CifsGood;
tcon->need_reconnect = false;
tcon->tid = smb_buffer_response->Tid;
bcc_ptr = pByteArea(smb_buffer_response);
- length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
+ bytes_left = BCC(smb_buffer_response);
+ length = strnlen(bcc_ptr, bytes_left - 2);
+ if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
+ is_unicode = true;
+ else
+ is_unicode = false;
+
+
/* skip service field (NB: this field is always ASCII) */
if (length == 3) {
if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
@@ -3666,40 +2741,16 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
}
}
bcc_ptr += length + 1;
+ bytes_left -= (length + 1);
strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
- if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
- length = UniStrnlen((wchar_t *) bcc_ptr, 512);
- if ((bcc_ptr + (2 * length)) -
- pByteArea(smb_buffer_response) <=
- BCC(smb_buffer_response)) {
- kfree(tcon->nativeFileSystem);
- tcon->nativeFileSystem =
- kzalloc(2*(length + 1), GFP_KERNEL);
- 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;
- bcc_ptr += 2;
- }
- /* else do not bother copying these information fields*/
- } else {
- length = strnlen(bcc_ptr, 1024);
- if ((bcc_ptr + length) -
- pByteArea(smb_buffer_response) <=
- BCC(smb_buffer_response)) {
- kfree(tcon->nativeFileSystem);
- tcon->nativeFileSystem =
- kzalloc(length + 1, GFP_KERNEL);
- if (tcon->nativeFileSystem)
- strncpy(tcon->nativeFileSystem, bcc_ptr,
- length);
- }
- /* else do not bother copying these information fields*/
- }
+
+ /* mostly informational -- no need to fail on error here */
+ tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr,
+ bytes_left, is_unicode,
+ nls_codepage);
+
+ cFYI(1, ("nativeFileSystem=%s", tcon->nativeFileSystem));
+
if ((smb_buffer_response->WordCount == 3) ||
(smb_buffer_response->WordCount == 7))
/* field is in same location */
@@ -3738,8 +2789,6 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
struct nls_table *nls_info)
{
int rc = 0;
- char ntlm_session_key[CIFS_SESS_KEY_SIZE];
- bool ntlmv2_flag = false;
int first_time = 0;
struct TCP_Server_Info *server = pSesInfo->server;
@@ -3771,83 +2820,19 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
pSesInfo->capabilities = server->capabilities;
if (linuxExtEnabled == 0)
pSesInfo->capabilities &= (~CAP_UNIX);
- /* pSesInfo->sequence_number = 0;*/
+
cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
server->secMode, server->capabilities, server->timeAdj));
- if (experimEnabled < 2)
- rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info);
- else if (extended_security
- && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
- && (server->secType == NTLMSSP)) {
- rc = -EOPNOTSUPP;
- } else if (extended_security
- && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
- && (server->secType == RawNTLMSSP)) {
- cFYI(1, ("NTLMSSP sesssetup"));
- rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag,
- nls_info);
- if (!rc) {
- if (ntlmv2_flag) {
- char *v2_response;
- cFYI(1, ("more secure NTLM ver2 hash"));
- if (CalcNTLMv2_partial_mac_key(pSesInfo,
- nls_info)) {
- rc = -ENOMEM;
- goto ss_err_exit;
- } else
- v2_response = kmalloc(16 + 64 /* blob*/,
- GFP_KERNEL);
- if (v2_response) {
- CalcNTLMv2_response(pSesInfo,
- v2_response);
- /* if (first_time)
- cifs_calculate_ntlmv2_mac_key */
- kfree(v2_response);
- /* BB Put dummy sig in SessSetup PDU? */
- } else {
- rc = -ENOMEM;
- goto ss_err_exit;
- }
-
- } else {
- SMBNTencrypt(pSesInfo->password,
- server->cryptKey,
- ntlm_session_key);
-
- if (first_time)
- cifs_calculate_mac_key(
- &server->mac_signing_key,
- ntlm_session_key,
- pSesInfo->password);
- }
- /* for better security the weaker lanman hash not sent
- in AuthSessSetup so we no longer calculate it */
-
- rc = CIFSNTLMSSPAuthSessSetup(xid, pSesInfo,
- ntlm_session_key,
- ntlmv2_flag,
- nls_info);
- }
- } else { /* old style NTLM 0.12 session setup */
- SMBNTencrypt(pSesInfo->password, server->cryptKey,
- ntlm_session_key);
-
- if (first_time)
- cifs_calculate_mac_key(&server->mac_signing_key,
- ntlm_session_key,
- pSesInfo->password);
-
- rc = CIFSSessSetup(xid, pSesInfo, ntlm_session_key, nls_info);
- }
+ rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info);
if (rc) {
cERROR(1, ("Send error in SessSetup = %d", rc));
} else {
cFYI(1, ("CIFS Session Established successfully"));
- spin_lock(&GlobalMid_Lock);
- pSesInfo->status = CifsGood;
- pSesInfo->need_reconnect = false;
- spin_unlock(&GlobalMid_Lock);
+ spin_lock(&GlobalMid_Lock);
+ pSesInfo->status = CifsGood;
+ pSesInfo->need_reconnect = false;
+ spin_unlock(&GlobalMid_Lock);
}
ss_err_exit:
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 54dce78fbb73..11431ed72a7f 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -129,12 +129,62 @@ cifs_bp_rename_retry:
return full_path;
}
+static void
+cifs_fill_fileinfo(struct inode *newinode, __u16 fileHandle,
+ struct cifsTconInfo *tcon, bool write_only)
+{
+ int oplock = 0;
+ struct cifsFileInfo *pCifsFile;
+ struct cifsInodeInfo *pCifsInode;
+
+ pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
+
+ if (pCifsFile == NULL)
+ return;
+
+ if (oplockEnabled)
+ oplock = REQ_OPLOCK;
+
+ pCifsFile->netfid = fileHandle;
+ pCifsFile->pid = current->tgid;
+ pCifsFile->pInode = newinode;
+ pCifsFile->invalidHandle = false;
+ pCifsFile->closePend = false;
+ mutex_init(&pCifsFile->fh_mutex);
+ mutex_init(&pCifsFile->lock_mutex);
+ INIT_LIST_HEAD(&pCifsFile->llist);
+ atomic_set(&pCifsFile->wrtPending, 0);
+
+ /* set the following in open now
+ pCifsFile->pfile = file; */
+ write_lock(&GlobalSMBSeslock);
+ list_add(&pCifsFile->tlist, &tcon->openFileList);
+ pCifsInode = CIFS_I(newinode);
+ if (pCifsInode) {
+ /* if readable file instance put first in list*/
+ if (write_only)
+ list_add_tail(&pCifsFile->flist,
+ &pCifsInode->openFileList);
+ else
+ list_add(&pCifsFile->flist, &pCifsInode->openFileList);
+
+ if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+ pCifsInode->clientCanCacheAll = true;
+ pCifsInode->clientCanCacheRead = true;
+ cFYI(1, ("Exclusive Oplock inode %p", newinode));
+ } else if ((oplock & 0xF) == OPLOCK_READ)
+ pCifsInode->clientCanCacheRead = true;
+ }
+ write_unlock(&GlobalSMBSeslock);
+}
+
int cifs_posix_open(char *full_path, struct inode **pinode,
struct super_block *sb, int mode, int oflags,
int *poplock, __u16 *pnetfid, int xid)
{
int rc;
__u32 oplock;
+ bool write_only = false;
FILE_UNIX_BASIC_INFO *presp_data;
__u32 posix_flags = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
@@ -172,6 +222,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
if (oflags & O_DIRECT)
posix_flags |= SMB_O_DIRECT;
+ if (!(oflags & FMODE_READ))
+ write_only = true;
rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
pnetfid, presp_data, &oplock, full_path,
@@ -187,8 +239,10 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
if (!pinode)
goto posix_open_ret; /* caller does not need info */
- if (*pinode == NULL)
- *pinode = cifs_new_inode(sb, &presp_data->UniqueId);
+ if (*pinode == NULL) {
+ __u64 unique_id = le64_to_cpu(presp_data->UniqueId);
+ *pinode = cifs_new_inode(sb, &unique_id);
+ }
/* else an inode was passed in. Update its info, don't create one */
/* We do not need to close the file if new_inode fails since
@@ -198,6 +252,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
posix_fill_in_inode(*pinode, presp_data, 1);
+ cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only);
+
posix_open_ret:
kfree(presp_data);
return rc;
@@ -225,6 +281,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
int create_options = CREATE_NOT_DIR;
int oplock = 0;
int oflags;
+ bool posix_create = false;
/*
* BB below access is probably too much for mknod to request
* but we have to do query and setpathinfo so requesting
@@ -239,7 +296,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
char *full_path = NULL;
FILE_ALL_INFO *buf = NULL;
struct inode *newinode = NULL;
- struct cifsInodeInfo *pCifsInode;
int disposition = FILE_OVERWRITE_IF;
bool write_only = false;
@@ -273,11 +329,13 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
negotation. EREMOTE indicates DFS junction, which is not
handled in posix open */
- if ((rc == 0) && (newinode == NULL))
- goto cifs_create_get_file_info; /* query inode info */
- else if (rc == 0) /* success, no need to query */
- goto cifs_create_set_dentry;
- else if ((rc != -EIO) && (rc != -EREMOTE) &&
+ if (rc == 0) {
+ posix_create = true;
+ if (newinode == NULL) /* query inode info */
+ goto cifs_create_get_file_info;
+ else /* success, no need to query */
+ goto cifs_create_set_dentry;
+ } else if ((rc != -EIO) && (rc != -EREMOTE) &&
(rc != -EOPNOTSUPP)) /* path not found or net err */
goto cifs_create_out;
/* else fallthrough to retry, using older open call, this is
@@ -409,45 +467,9 @@ cifs_create_set_dentry:
if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
/* mknod case - do not leave file open */
CIFSSMBClose(xid, tcon, fileHandle);
- } else if (newinode) {
- struct cifsFileInfo *pCifsFile =
- kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
-
- if (pCifsFile == NULL)
- goto cifs_create_out;
- pCifsFile->netfid = fileHandle;
- pCifsFile->pid = current->tgid;
- pCifsFile->pInode = newinode;
- pCifsFile->invalidHandle = false;
- pCifsFile->closePend = false;
- init_MUTEX(&pCifsFile->fh_sem);
- mutex_init(&pCifsFile->lock_mutex);
- INIT_LIST_HEAD(&pCifsFile->llist);
- atomic_set(&pCifsFile->wrtPending, 0);
-
- /* set the following in open now
- pCifsFile->pfile = file; */
- write_lock(&GlobalSMBSeslock);
- list_add(&pCifsFile->tlist, &tcon->openFileList);
- pCifsInode = CIFS_I(newinode);
- if (pCifsInode) {
- /* if readable file instance put first in list*/
- if (write_only) {
- list_add_tail(&pCifsFile->flist,
- &pCifsInode->openFileList);
- } else {
- list_add(&pCifsFile->flist,
- &pCifsInode->openFileList);
- }
- if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
- pCifsInode->clientCanCacheAll = true;
- pCifsInode->clientCanCacheRead = true;
- cFYI(1, ("Exclusive Oplock inode %p",
- newinode));
- } else if ((oplock & 0xF) == OPLOCK_READ)
- pCifsInode->clientCanCacheRead = true;
- }
- write_unlock(&GlobalSMBSeslock);
+ } else if (!(posix_create) && (newinode)) {
+ cifs_fill_fileinfo(newinode, fileHandle,
+ cifs_sb->tcon, write_only);
}
cifs_create_out:
kfree(buf);
@@ -580,17 +602,21 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
return rc;
}
-
struct dentry *
cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
struct nameidata *nd)
{
int xid;
int rc = 0; /* to get around spurious gcc warning, set to zero here */
+ int oplock = 0;
+ int mode;
+ __u16 fileHandle = 0;
+ bool posix_open = false;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
struct inode *newInode = NULL;
char *full_path = NULL;
+ struct file *filp;
xid = GetXid();
@@ -632,12 +658,37 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
}
cFYI(1, ("Full path: %s inode = 0x%p", full_path, direntry->d_inode));
- if (pTcon->unix_ext)
- rc = cifs_get_inode_info_unix(&newInode, full_path,
- parent_dir_inode->i_sb, xid);
- else
+ if (pTcon->unix_ext) {
+ if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
+ (nd->flags & LOOKUP_OPEN)) {
+ if (!((nd->intent.open.flags & O_CREAT) &&
+ (nd->intent.open.flags & O_EXCL))) {
+ mode = nd->intent.open.create_mode &
+ ~current_umask();
+ rc = cifs_posix_open(full_path, &newInode,
+ parent_dir_inode->i_sb, mode,
+ nd->intent.open.flags, &oplock,
+ &fileHandle, xid);
+ /*
+ * This code works around a bug in
+ * samba posix open in samba versions 3.3.1
+ * and earlier where create works
+ * but open fails with invalid parameter.
+ * If either of these error codes are
+ * returned, follow the normal lookup.
+ * Otherwise, the error during posix open
+ * is handled.
+ */
+ if ((rc != -EINVAL) && (rc != -EOPNOTSUPP))
+ posix_open = true;
+ }
+ }
+ if (!posix_open)
+ rc = cifs_get_inode_info_unix(&newInode, full_path,
+ parent_dir_inode->i_sb, xid);
+ } else
rc = cifs_get_inode_info(&newInode, full_path, NULL,
- parent_dir_inode->i_sb, xid, NULL);
+ parent_dir_inode->i_sb, xid, NULL);
if ((rc == 0) && (newInode != NULL)) {
if (pTcon->nocase)
@@ -645,7 +696,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
else
direntry->d_op = &cifs_dentry_ops;
d_add(direntry, newInode);
-
+ if (posix_open)
+ filp = lookup_instantiate_filp(nd, direntry, NULL);
/* since paths are not looked up by component - the parent
directories are presumed to be good here */
renew_parental_timestamps(direntry);
diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c
index 1e0c1bd8f2e4..df4a306f697e 100644
--- a/fs/cifs/dns_resolve.c
+++ b/fs/cifs/dns_resolve.c
@@ -78,7 +78,7 @@ dns_resolver_instantiate(struct key *key, const void *data,
}
key->type_data.x[0] = datalen;
- rcu_assign_pointer(key->payload.data, ip);
+ key->payload.data = ip;
return rc;
}
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 81747acca4c4..38c06f826575 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -46,7 +46,7 @@ static inline struct cifsFileInfo *cifs_init_private(
memset(private_data, 0, sizeof(struct cifsFileInfo));
private_data->netfid = netfid;
private_data->pid = current->tgid;
- init_MUTEX(&private_data->fh_sem);
+ mutex_init(&private_data->fh_mutex);
mutex_init(&private_data->lock_mutex);
INIT_LIST_HEAD(&private_data->llist);
private_data->pfile = file; /* needed for writepage */
@@ -129,15 +129,12 @@ static inline int cifs_posix_open_inode_helper(struct inode *inode,
struct file *file, struct cifsInodeInfo *pCifsInode,
struct cifsFileInfo *pCifsFile, int oplock, u16 netfid)
{
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-/* struct timespec temp; */ /* BB REMOVEME BB */
file->private_data = kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
if (file->private_data == NULL)
return -ENOMEM;
pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
write_lock(&GlobalSMBSeslock);
- list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList);
pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
if (pCifsInode == NULL) {
@@ -145,17 +142,6 @@ static inline int cifs_posix_open_inode_helper(struct inode *inode,
return -EINVAL;
}
- /* want handles we can use to read with first
- in the list so we do not have to walk the
- list to search for one in write_begin */
- if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
- list_add_tail(&pCifsFile->flist,
- &pCifsInode->openFileList);
- } else {
- list_add(&pCifsFile->flist,
- &pCifsInode->openFileList);
- }
-
if (pCifsInode->clientCanCacheRead) {
/* we have the inode open somewhere else
no need to discard cache data */
@@ -284,35 +270,32 @@ int cifs_open(struct inode *inode, struct file *file)
cifs_sb = CIFS_SB(inode->i_sb);
tcon = cifs_sb->tcon;
- if (file->f_flags & O_CREAT) {
- /* search inode for this file and fill in file->private_data */
- pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
- read_lock(&GlobalSMBSeslock);
- list_for_each(tmp, &pCifsInode->openFileList) {
- pCifsFile = list_entry(tmp, struct cifsFileInfo,
- flist);
- if ((pCifsFile->pfile == NULL) &&
- (pCifsFile->pid == current->tgid)) {
- /* mode set in cifs_create */
-
- /* needed for writepage */
- pCifsFile->pfile = file;
-
- file->private_data = pCifsFile;
- break;
- }
- }
- read_unlock(&GlobalSMBSeslock);
- if (file->private_data != NULL) {
- rc = 0;
- FreeXid(xid);
- return rc;
- } else {
- if (file->f_flags & O_EXCL)
- cERROR(1, ("could not find file instance for "
- "new file %p", file));
+ /* search inode for this file and fill in file->private_data */
+ pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
+ read_lock(&GlobalSMBSeslock);
+ list_for_each(tmp, &pCifsInode->openFileList) {
+ pCifsFile = list_entry(tmp, struct cifsFileInfo,
+ flist);
+ if ((pCifsFile->pfile == NULL) &&
+ (pCifsFile->pid == current->tgid)) {
+ /* mode set in cifs_create */
+
+ /* needed for writepage */
+ pCifsFile->pfile = file;
+
+ file->private_data = pCifsFile;
+ break;
}
}
+ read_unlock(&GlobalSMBSeslock);
+
+ if (file->private_data != NULL) {
+ rc = 0;
+ FreeXid(xid);
+ return rc;
+ } else if ((file->f_flags & O_CREAT) && (file->f_flags & O_EXCL))
+ cERROR(1, ("could not find file instance for "
+ "new file %p", file));
full_path = build_path_from_dentry(file->f_path.dentry);
if (full_path == NULL) {
@@ -500,9 +483,9 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
return -EBADF;
xid = GetXid();
- down(&pCifsFile->fh_sem);
+ mutex_unlock(&pCifsFile->fh_mutex);
if (!pCifsFile->invalidHandle) {
- up(&pCifsFile->fh_sem);
+ mutex_lock(&pCifsFile->fh_mutex);
FreeXid(xid);
return 0;
}
@@ -533,7 +516,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
if (full_path == NULL) {
rc = -ENOMEM;
reopen_error_exit:
- up(&pCifsFile->fh_sem);
+ mutex_lock(&pCifsFile->fh_mutex);
FreeXid(xid);
return rc;
}
@@ -575,14 +558,14 @@ reopen_error_exit:
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) {
- up(&pCifsFile->fh_sem);
+ mutex_lock(&pCifsFile->fh_mutex);
cFYI(1, ("cifs_open returned 0x%x", rc));
cFYI(1, ("oplock: %d", oplock));
} else {
reopen_success:
pCifsFile->netfid = netfid;
pCifsFile->invalidHandle = false;
- up(&pCifsFile->fh_sem);
+ mutex_lock(&pCifsFile->fh_mutex);
pCifsInode = CIFS_I(inode);
if (pCifsInode) {
if (can_flush) {
@@ -971,6 +954,40 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
return rc;
}
+/*
+ * Set the timeout on write requests past EOF. For some servers (Windows)
+ * these calls can be very long.
+ *
+ * If we're writing >10M past the EOF we give a 180s timeout. Anything less
+ * than that gets a 45s timeout. Writes not past EOF get 15s timeouts.
+ * The 10M cutoff is totally arbitrary. A better scheme for this would be
+ * welcome if someone wants to suggest one.
+ *
+ * We may be able to do a better job with this if there were some way to
+ * declare that a file should be sparse.
+ */
+static int
+cifs_write_timeout(struct cifsInodeInfo *cifsi, loff_t offset)
+{
+ if (offset <= cifsi->server_eof)
+ return CIFS_STD_OP;
+ else if (offset > (cifsi->server_eof + (10 * 1024 * 1024)))
+ return CIFS_VLONG_OP;
+ else
+ return CIFS_LONG_OP;
+}
+
+/* update the file size (if needed) after a write */
+static void
+cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
+ unsigned int bytes_written)
+{
+ loff_t end_of_write = offset + bytes_written;
+
+ if (end_of_write > cifsi->server_eof)
+ cifsi->server_eof = end_of_write;
+}
+
ssize_t cifs_user_write(struct file *file, const char __user *write_data,
size_t write_size, loff_t *poffset)
{
@@ -981,6 +998,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
struct cifsTconInfo *pTcon;
int xid, long_op;
struct cifsFileInfo *open_file;
+ struct cifsInodeInfo *cifsi = CIFS_I(file->f_path.dentry->d_inode);
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
@@ -1000,11 +1018,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
xid = GetXid();
- if (*poffset > file->f_path.dentry->d_inode->i_size)
- long_op = CIFS_VLONG_OP; /* writes past EOF take long time */
- else
- long_op = CIFS_LONG_OP;
-
+ long_op = cifs_write_timeout(cifsi, *poffset);
for (total_written = 0; write_size > total_written;
total_written += bytes_written) {
rc = -EAGAIN;
@@ -1048,8 +1062,10 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
FreeXid(xid);
return rc;
}
- } else
+ } else {
+ cifs_update_eof(cifsi, *poffset, bytes_written);
*poffset += bytes_written;
+ }
long_op = CIFS_STD_OP; /* subsequent writes fast -
15 seconds is plenty */
}
@@ -1085,6 +1101,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
struct cifsTconInfo *pTcon;
int xid, long_op;
struct cifsFileInfo *open_file;
+ struct cifsInodeInfo *cifsi = CIFS_I(file->f_path.dentry->d_inode);
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
@@ -1099,11 +1116,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
xid = GetXid();
- if (*poffset > file->f_path.dentry->d_inode->i_size)
- long_op = CIFS_VLONG_OP; /* writes past EOF can be slow */
- else
- long_op = CIFS_LONG_OP;
-
+ long_op = cifs_write_timeout(cifsi, *poffset);
for (total_written = 0; write_size > total_written;
total_written += bytes_written) {
rc = -EAGAIN;
@@ -1166,8 +1179,10 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
FreeXid(xid);
return rc;
}
- } else
+ } else {
+ cifs_update_eof(cifsi, *poffset, bytes_written);
*poffset += bytes_written;
+ }
long_op = CIFS_STD_OP; /* subsequent writes fast -
15 seconds is plenty */
}
@@ -1380,11 +1395,12 @@ static int cifs_writepages(struct address_space *mapping,
int nr_pages;
__u64 offset = 0;
struct cifsFileInfo *open_file;
+ struct cifsInodeInfo *cifsi = CIFS_I(mapping->host);
struct page *page;
struct pagevec pvec;
int rc = 0;
int scanned = 0;
- int xid;
+ int xid, long_op;
cifs_sb = CIFS_SB(mapping->host->i_sb);
@@ -1528,12 +1544,15 @@ retry:
cERROR(1, ("No writable handles for inode"));
rc = -EBADF;
} else {
+ long_op = cifs_write_timeout(cifsi, offset);
rc = CIFSSMBWrite2(xid, cifs_sb->tcon,
open_file->netfid,
bytes_to_write, offset,
&bytes_written, iov, n_iov,
- CIFS_LONG_OP);
+ long_op);
atomic_dec(&open_file->wrtPending);
+ cifs_update_eof(cifsi, offset, bytes_written);
+
if (rc || bytes_written < bytes_to_write) {
cERROR(1, ("Write2 ret %d, wrote %d",
rc, bytes_written));
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index f121a80fdd6f..9c869a6dcba1 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -143,6 +143,7 @@ static void cifs_unix_info_to_inode(struct inode *inode,
inode->i_nlink = le64_to_cpu(info->Nlinks);
+ cifsInfo->server_eof = end_of_file;
spin_lock(&inode->i_lock);
if (is_size_safe_to_change(cifsInfo, end_of_file)) {
/*
@@ -276,7 +277,8 @@ int cifs_get_inode_info_unix(struct inode **pinode,
/* get new inode */
if (*pinode == NULL) {
- *pinode = cifs_new_inode(sb, &find_data.UniqueId);
+ __u64 unique_id = le64_to_cpu(find_data.UniqueId);
+ *pinode = cifs_new_inode(sb, &unique_id);
if (*pinode == NULL) {
rc = -ENOMEM;
goto cgiiu_exit;
@@ -605,12 +607,12 @@ int cifs_get_inode_info(struct inode **pinode,
inode->i_mode |= S_IFREG;
}
+ cifsInfo->server_eof = le64_to_cpu(pfindData->EndOfFile);
spin_lock(&inode->i_lock);
- if (is_size_safe_to_change(cifsInfo,
- le64_to_cpu(pfindData->EndOfFile))) {
+ if (is_size_safe_to_change(cifsInfo, cifsInfo->server_eof)) {
/* can not safely shrink the file size here if the
client is writing to it due to potential races */
- i_size_write(inode, le64_to_cpu(pfindData->EndOfFile));
+ i_size_write(inode, cifsInfo->server_eof);
/* 512 bytes (2**9) is the fake blocksize that must be
used for this calculation */
@@ -960,13 +962,21 @@ undo_setattr:
goto out_close;
}
+
+/*
+ * If dentry->d_inode is null (usually meaning the cached dentry
+ * is a negative dentry) then we would attempt a standard SMB delete, but
+ * if that fails we can not attempt the fall back mechanisms on EACESS
+ * but will return the EACESS to the caller. Note that the VFS does not call
+ * unlink on negative dentries currently.
+ */
int cifs_unlink(struct inode *dir, struct dentry *dentry)
{
int rc = 0;
int xid;
char *full_path = NULL;
struct inode *inode = dentry->d_inode;
- struct cifsInodeInfo *cifsInode = CIFS_I(inode);
+ struct cifsInodeInfo *cifs_inode;
struct super_block *sb = dir->i_sb;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifsTconInfo *tcon = cifs_sb->tcon;
@@ -1010,7 +1020,7 @@ psx_del_no_retry:
rc = cifs_rename_pending_delete(full_path, dentry, xid);
if (rc == 0)
drop_nlink(inode);
- } else if (rc == -EACCES && dosattr == 0) {
+ } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
if (attrs == NULL) {
rc = -ENOMEM;
@@ -1018,7 +1028,8 @@ psx_del_no_retry:
}
/* try to reset dos attributes */
- origattr = cifsInode->cifsAttrs;
+ cifs_inode = CIFS_I(inode);
+ origattr = cifs_inode->cifsAttrs;
if (origattr == 0)
origattr |= ATTR_NORMAL;
dosattr = origattr & ~ATTR_READONLY;
@@ -1039,13 +1050,13 @@ psx_del_no_retry:
out_reval:
if (inode) {
- cifsInode = CIFS_I(inode);
- cifsInode->time = 0; /* will force revalidate to get info
+ cifs_inode = CIFS_I(inode);
+ cifs_inode->time = 0; /* will force revalidate to get info
when needed */
inode->i_ctime = current_fs_time(sb);
}
dir->i_ctime = dir->i_mtime = current_fs_time(sb);
- cifsInode = CIFS_I(dir);
+ cifs_inode = CIFS_I(dir);
CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
kfree(full_path);
@@ -1138,6 +1149,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
cFYI(1, ("posix mkdir returned 0x%x", rc));
d_drop(direntry);
} else {
+ __u64 unique_id;
if (pInfo->Type == cpu_to_le32(-1)) {
/* no return info, go query for it */
kfree(pInfo);
@@ -1151,8 +1163,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
else
direntry->d_op = &cifs_dentry_ops;
- newinode = cifs_new_inode(inode->i_sb,
- &pInfo->UniqueId);
+ unique_id = le64_to_cpu(pInfo->UniqueId);
+ newinode = cifs_new_inode(inode->i_sb, &unique_id);
if (newinode == NULL) {
kfree(pInfo);
goto mkdir_get_info;
@@ -1450,7 +1462,8 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
checking the UniqueId via FILE_INTERNAL_INFO */
unlink_target:
- if ((rc == -EACCES) || (rc == -EEXIST)) {
+ /* Try unlinking the target dentry if it's not negative */
+ if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
tmprc = cifs_unlink(target_dir, target_dentry);
if (tmprc)
goto cifs_rename_exit;
@@ -1753,6 +1766,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
}
if (rc == 0) {
+ cifsInode->server_eof = attrs->ia_size;
rc = cifs_vmtruncate(inode, attrs->ia_size);
cifs_truncate_page(inode->i_mapping, inode->i_size);
}
@@ -1792,20 +1806,21 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
goto out;
}
- if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) {
- /*
- Flush data before changing file size or changing the last
- write time of the file on the server. If the
- flush returns error, store it to report later and continue.
- BB: This should be smarter. Why bother flushing pages that
- will be truncated anyway? Also, should we error out here if
- the flush returns error?
- */
- rc = filemap_write_and_wait(inode->i_mapping);
- if (rc != 0) {
- cifsInode->write_behind_rc = rc;
- rc = 0;
- }
+ /*
+ * Attempt to flush data before changing attributes. We need to do
+ * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
+ * ownership or mode then we may also need to do this. Here, we take
+ * the safe way out and just do the flush on all setattr requests. If
+ * the flush returns error, store it to report later and continue.
+ *
+ * BB: This should be smarter. Why bother flushing pages that
+ * will be truncated anyway? Also, should we error out here if
+ * the flush returns error?
+ */
+ rc = filemap_write_and_wait(inode->i_mapping);
+ if (rc != 0) {
+ cifsInode->write_behind_rc = rc;
+ rc = 0;
}
if (attrs->ia_valid & ATTR_SIZE) {
@@ -1903,20 +1918,21 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
return -ENOMEM;
}
- if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) {
- /*
- Flush data before changing file size or changing the last
- write time of the file on the server. If the
- flush returns error, store it to report later and continue.
- BB: This should be smarter. Why bother flushing pages that
- will be truncated anyway? Also, should we error out here if
- the flush returns error?
- */
- rc = filemap_write_and_wait(inode->i_mapping);
- if (rc != 0) {
- cifsInode->write_behind_rc = rc;
- rc = 0;
- }
+ /*
+ * Attempt to flush data before changing attributes. We need to do
+ * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
+ * ownership or mode then we may also need to do this. Here, we take
+ * the safe way out and just do the flush on all setattr requests. If
+ * the flush returns error, store it to report later and continue.
+ *
+ * BB: This should be smarter. Why bother flushing pages that
+ * will be truncated anyway? Also, should we error out here if
+ * the flush returns error?
+ */
+ rc = filemap_write_and_wait(inode->i_mapping);
+ if (rc != 0) {
+ cifsInode->write_behind_rc = rc;
+ rc = 0;
}
if (attrs->ia_valid & ATTR_SIZE) {
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 63f644000ce5..ea9d11e3dcbb 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -119,16 +119,11 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
full_path = build_path_from_dentry(direntry);
if (!full_path)
- goto out_no_free;
+ goto out;
cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
- target_path = kmalloc(PATH_MAX, GFP_KERNEL);
- if (!target_path) {
- target_path = ERR_PTR(-ENOMEM);
- goto out;
- }
/* We could change this to:
if (pTcon->unix_ext)
@@ -138,8 +133,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
if (pTcon->ses->capabilities & CAP_UNIX)
rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
- target_path,
- PATH_MAX-1,
+ &target_path,
cifs_sb->local_nls);
else {
/* BB add read reparse point symlink code here */
@@ -148,22 +142,16 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
/* BB Add MAC style xsymlink check here if enabled */
}
- if (rc == 0) {
-
-/* BB Add special case check for Samba DFS symlinks */
-
- target_path[PATH_MAX-1] = 0;
- } else {
+ if (rc != 0) {
kfree(target_path);
target_path = ERR_PTR(rc);
}
-out:
kfree(full_path);
-out_no_free:
+out:
FreeXid(xid);
nd_set_link(nd, target_path);
- return NULL; /* No cookie */
+ return NULL;
}
int
@@ -224,98 +212,6 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
return rc;
}
-int
-cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
-{
- struct inode *inode = direntry->d_inode;
- int rc = -EACCES;
- int xid;
- int oplock = 0;
- struct cifs_sb_info *cifs_sb;
- struct cifsTconInfo *pTcon;
- char *full_path = NULL;
- char *tmpbuffer;
- int len;
- __u16 fid;
-
- xid = GetXid();
- cifs_sb = CIFS_SB(inode->i_sb);
- pTcon = cifs_sb->tcon;
-
-/* BB would it be safe against deadlock to grab this sem
- even though rename itself grabs the sem and calls lookup? */
-/* mutex_lock(&inode->i_sb->s_vfs_rename_mutex);*/
- full_path = build_path_from_dentry(direntry);
-/* mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);*/
-
- if (full_path == NULL) {
- FreeXid(xid);
- return -ENOMEM;
- }
-
- cFYI(1,
- ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
- full_path, inode, pBuffer, buflen));
- if (buflen > PATH_MAX)
- len = PATH_MAX;
- else
- len = buflen;
- tmpbuffer = kmalloc(len, GFP_KERNEL);
- if (tmpbuffer == NULL) {
- kfree(full_path);
- FreeXid(xid);
- return -ENOMEM;
- }
-
-/* BB add read reparse point symlink code and
- Unix extensions symlink code here BB */
-/* We could disable this based on pTcon->unix_ext flag instead ... but why? */
- if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
- rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
- tmpbuffer,
- len - 1,
- cifs_sb->local_nls);
- else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
- cERROR(1, ("SFU style symlinks not implemented yet"));
- /* add open and read as in fs/cifs/inode.c */
- } else {
- rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
- OPEN_REPARSE_POINT, &fid, &oplock, NULL,
- cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
- CIFS_MOUNT_MAP_SPECIAL_CHR);
- if (!rc) {
- rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
- tmpbuffer,
- len - 1,
- fid,
- cifs_sb->local_nls);
- if (CIFSSMBClose(xid, pTcon, fid)) {
- cFYI(1, ("Error closing junction point "
- "(open for ioctl)"));
- }
- /* If it is a DFS junction earlier we would have gotten
- PATH_NOT_COVERED returned from server so we do
- not need to request the DFS info here */
- }
- }
- /* BB Anything else to do to handle recursive links? */
- /* BB Should we be using page ops here? */
-
- /* BB null terminate returned string in pBuffer? BB */
- if (rc == 0) {
- rc = vfs_readlink(direntry, pBuffer, len, tmpbuffer);
- cFYI(1,
- ("vfs_readlink called from cifs_readlink returned %d",
- rc));
- }
-
- kfree(tmpbuffer);
- kfree(full_path);
- FreeXid(xid);
- return rc;
-}
-
void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie)
{
char *p = nd_get_link(nd);
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 4c89c572891a..e079a9190ec4 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -635,77 +635,6 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
return;
}
-/* Windows maps these to the user defined 16 bit Unicode range since they are
- reserved symbols (along with \ and /), otherwise illegal to store
- in filenames in NTFS */
-#define UNI_ASTERIK (__u16) ('*' + 0xF000)
-#define UNI_QUESTION (__u16) ('?' + 0xF000)
-#define UNI_COLON (__u16) (':' + 0xF000)
-#define UNI_GRTRTHAN (__u16) ('>' + 0xF000)
-#define UNI_LESSTHAN (__u16) ('<' + 0xF000)
-#define UNI_PIPE (__u16) ('|' + 0xF000)
-#define UNI_SLASH (__u16) ('\\' + 0xF000)
-
-/* Convert 16 bit Unicode pathname from wire format to string in current code
- page. Conversion may involve remapping up the seven characters that are
- only legal in POSIX-like OS (if they are present in the string). Path
- names are little endian 16 bit Unicode on the wire */
-int
-cifs_convertUCSpath(char *target, const __le16 *source, int maxlen,
- const struct nls_table *cp)
-{
- int i, j, len;
- __u16 src_char;
-
- for (i = 0, j = 0; i < maxlen; i++) {
- src_char = le16_to_cpu(source[i]);
- switch (src_char) {
- case 0:
- goto cUCS_out; /* BB check this BB */
- case UNI_COLON:
- target[j] = ':';
- break;
- case UNI_ASTERIK:
- target[j] = '*';
- break;
- case UNI_QUESTION:
- target[j] = '?';
- break;
- /* BB We can not handle remapping slash until
- all the calls to build_path_from_dentry
- are modified, as they use slash as separator BB */
- /* case UNI_SLASH:
- target[j] = '\\';
- break;*/
- case UNI_PIPE:
- target[j] = '|';
- break;
- case UNI_GRTRTHAN:
- target[j] = '>';
- break;
- case UNI_LESSTHAN:
- target[j] = '<';
- break;
- default:
- len = cp->uni2char(src_char, &target[j],
- NLS_MAX_CHARSET_SIZE);
- if (len > 0) {
- j += len;
- continue;
- } else {
- target[j] = '?';
- }
- }
- j++;
- /* make sure we do not overrun callers allocated temp buffer */
- if (j >= (2 * NAME_MAX))
- break;
- }
-cUCS_out:
- target[j] = 0;
- return j;
-}
-
/* Convert 16 bit Unicode pathname to wire format from string in current code
page. Conversion may involve remapping up the seven characters that are
only legal in POSIX-like OS (if they are present in the string). Path
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index 8703d68f5b20..e2fe998989a3 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -79,6 +79,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
{ErrQuota, -EDQUOT},
{ErrNotALink, -ENOLINK},
{ERRnetlogonNotStarted, -ENOPROTOOPT},
+ {ERRsymlink, -EOPNOTSUPP},
{ErrTooManyLinks, -EMLINK},
{0, 0}
};
@@ -714,6 +715,7 @@ static const struct {
ERRDOS, ERRnoaccess, 0xc000028f}, {
ERRDOS, ERRnoaccess, 0xc0000290}, {
ERRDOS, ERRbadfunc, 0xc000029c}, {
+ ERRDOS, ERRsymlink, NT_STATUS_STOPPED_ON_SYMLINK}, {
ERRDOS, ERRinvlevel, 0x007c0001}, };
/*****************************************************************************
diff --git a/fs/cifs/nterr.h b/fs/cifs/nterr.h
index 588abbb9d08c..257267367d41 100644
--- a/fs/cifs/nterr.h
+++ b/fs/cifs/nterr.h
@@ -35,8 +35,6 @@ struct nt_err_code_struct {
extern const struct nt_err_code_struct nt_errs[];
/* Win32 Status codes. */
-
-#define STATUS_BUFFER_OVERFLOW 0x80000005
#define STATUS_MORE_ENTRIES 0x0105
#define ERROR_INVALID_PARAMETER 0x0057
#define ERROR_INSUFFICIENT_BUFFER 0x007a
@@ -50,6 +48,13 @@ extern const struct nt_err_code_struct nt_errs[];
#define STATUS_SOME_UNMAPPED 0x0107
#define STATUS_BUFFER_OVERFLOW 0x80000005
#define NT_STATUS_NO_MORE_ENTRIES 0x8000001a
+#define NT_STATUS_MEDIA_CHANGED 0x8000001c
+#define NT_STATUS_END_OF_MEDIA 0x8000001e
+#define NT_STATUS_MEDIA_CHECK 0x80000020
+#define NT_STATUS_NO_DATA_DETECTED 0x8000001c
+#define NT_STATUS_STOPPED_ON_SYMLINK 0x8000002d
+#define NT_STATUS_DEVICE_REQUIRES_CLEANING 0x80000288
+#define NT_STATUS_DEVICE_DOOR_OPEN 0x80000288
#define NT_STATUS_UNSUCCESSFUL 0xC0000000 | 0x0001
#define NT_STATUS_NOT_IMPLEMENTED 0xC0000000 | 0x0002
#define NT_STATUS_INVALID_INFO_CLASS 0xC0000000 | 0x0003
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h
index c377d8065d99..49c9a4e75319 100644
--- a/fs/cifs/ntlmssp.h
+++ b/fs/cifs/ntlmssp.h
@@ -27,29 +27,39 @@
#define UnknownMessage cpu_to_le32(8)
/* Negotiate Flags */
-#define NTLMSSP_NEGOTIATE_UNICODE 0x01 /* Text strings are in unicode */
-#define NTLMSSP_NEGOTIATE_OEM 0x02 /* Text strings are in OEM */
-#define NTLMSSP_REQUEST_TARGET 0x04 /* Server return its auth realm */
-#define NTLMSSP_NEGOTIATE_SIGN 0x0010 /* Request signature capability */
-#define NTLMSSP_NEGOTIATE_SEAL 0x0020 /* Request confidentiality */
-#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
-#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 /* Sign/seal use LM session key */
-#define NTLMSSP_NEGOTIATE_NTLM 0x0200 /* NTLM authentication */
-#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000
+#define NTLMSSP_NEGOTIATE_UNICODE 0x01 /* Text strings are unicode */
+#define NTLMSSP_NEGOTIATE_OEM 0x02 /* Text strings are in OEM */
+#define NTLMSSP_REQUEST_TARGET 0x04 /* Srv returns its auth realm */
+/* define reserved9 0x08 */
+#define NTLMSSP_NEGOTIATE_SIGN 0x0010 /* Request signing capability */
+#define NTLMSSP_NEGOTIATE_SEAL 0x0020 /* Request confidentiality */
+#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
+#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 /* Use LM session key */
+/* defined reserved 8 0x0100 */
+#define NTLMSSP_NEGOTIATE_NTLM 0x0200 /* NTLM authentication */
+#define NTLMSSP_NEGOTIATE_NT_ONLY 0x0400 /* Lanman not allowed */
+#define NTLMSSP_ANONYMOUS 0x0800
+#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000 /* reserved6 */
#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
-#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 /* client/server on same machine */
-#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 /* Sign for all security levels */
-#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
-#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
-#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
-#define NTLMSSP_NEGOTIATE_NTLMV2 0x80000
-#define NTLMSSP_REQUEST_INIT_RESP 0x100000
-#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000
-#define NTLMSSP_REQUEST_NOT_NT_KEY 0x400000
+#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 /* client/server same machine */
+#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 /* Sign. All security levels */
+#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
+#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
+#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
+#define NTLMSSP_NEGOTIATE_EXTENDED_SEC 0x80000 /* NB:not related to NTLMv2 pwd*/
+/* #define NTLMSSP_REQUEST_INIT_RESP 0x100000 */
+#define NTLMSSP_NEGOTIATE_IDENTIFY 0x100000
+#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000 /* reserved5 */
+#define NTLMSSP_REQUEST_NON_NT_KEY 0x400000
#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000
-#define NTLMSSP_NEGOTIATE_128 0x20000000
-#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
-#define NTLMSSP_NEGOTIATE_56 0x80000000
+/* #define reserved4 0x1000000 */
+#define NTLMSSP_NEGOTIATE_VERSION 0x2000000 /* we do not set */
+/* #define reserved3 0x4000000 */
+/* #define reserved2 0x8000000 */
+/* #define reserved1 0x10000000 */
+#define NTLMSSP_NEGOTIATE_128 0x20000000
+#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
+#define NTLMSSP_NEGOTIATE_56 0x80000000
/* Although typedefs are not commonly used for structure definitions */
/* in the Linux kernel, in this particular case they are useful */
@@ -60,32 +70,36 @@
typedef struct _SECURITY_BUFFER {
__le16 Length;
__le16 MaximumLength;
- __le32 Buffer; /* offset to buffer */
+ __le32 BufferOffset; /* offset to buffer */
} __attribute__((packed)) SECURITY_BUFFER;
typedef struct _NEGOTIATE_MESSAGE {
__u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
- __le32 MessageType; /* 1 */
+ __le32 MessageType; /* NtLmNegotiate = 1 */
__le32 NegotiateFlags;
SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */
SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */
+ /* SECURITY_BUFFER for version info not present since we
+ do not set the version is present flag */
char DomainString[0];
/* followed by WorkstationString */
} __attribute__((packed)) NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE;
typedef struct _CHALLENGE_MESSAGE {
__u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
- __le32 MessageType; /* 2 */
+ __le32 MessageType; /* NtLmChallenge = 2 */
SECURITY_BUFFER TargetName;
__le32 NegotiateFlags;
__u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
__u8 Reserved[8];
SECURITY_BUFFER TargetInfoArray;
+ /* SECURITY_BUFFER for version info not present since we
+ do not set the version is present flag */
} __attribute__((packed)) CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE;
typedef struct _AUTHENTICATE_MESSAGE {
- __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
- __le32 MessageType; /* 3 */
+ __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
+ __le32 MessageType; /* NtLmsAuthenticate = 3 */
SECURITY_BUFFER LmChallengeResponse;
SECURITY_BUFFER NtChallengeResponse;
SECURITY_BUFFER DomainName;
@@ -93,5 +107,7 @@ typedef struct _AUTHENTICATE_MESSAGE {
SECURITY_BUFFER WorkstationName;
SECURITY_BUFFER SessionKey;
__le32 NegotiateFlags;
+ /* SECURITY_BUFFER for version info not present since we
+ do not set the version is present flag */
char UserString[0];
} __attribute__((packed)) AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index c2c01ff4c32c..964e097c8203 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -31,6 +31,13 @@
#include "cifs_fs_sb.h"
#include "cifsfs.h"
+/*
+ * To be safe - for UCS to UTF-8 with strings loaded with the rare long
+ * characters alloc more to account for such multibyte target UTF-8
+ * characters.
+ */
+#define UNICODE_NAME_MAX ((4 * NAME_MAX) + 2)
+
#ifdef CONFIG_CIFS_DEBUG2
static void dump_cifs_file_struct(struct file *file, char *label)
{
@@ -239,6 +246,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
if (atomic_read(&cifsInfo->inUse) == 0)
atomic_set(&cifsInfo->inUse, 1);
+ cifsInfo->server_eof = end_of_file;
spin_lock(&tmp_inode->i_lock);
if (is_size_safe_to_change(cifsInfo, end_of_file)) {
/* can not safely change the file size here if the
@@ -375,6 +383,7 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
+ cifsInfo->server_eof = end_of_file;
spin_lock(&tmp_inode->i_lock);
if (is_size_safe_to_change(cifsInfo, end_of_file)) {
/* can not safely change the file size here if the
@@ -436,6 +445,38 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
}
}
+/* BB eventually need to add the following helper function to
+ resolve NT_STATUS_STOPPED_ON_SYMLINK return code when
+ we try to do FindFirst on (NTFS) directory symlinks */
+/*
+int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
+ int xid)
+{
+ __u16 fid;
+ int len;
+ int oplock = 0;
+ int rc;
+ struct cifsTconInfo *ptcon = cifs_sb->tcon;
+ char *tmpbuffer;
+
+ rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ,
+ OPEN_REPARSE_POINT, &fid, &oplock, NULL,
+ cifs_sb->local_nls,
+ cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+ if (!rc) {
+ tmpbuffer = kmalloc(maxpath);
+ rc = CIFSSMBQueryReparseLinkInfo(xid, ptcon, full_path,
+ tmpbuffer,
+ maxpath -1,
+ fid,
+ cifs_sb->local_nls);
+ if (CIFSSMBClose(xid, ptcon, fid)) {
+ cFYI(1, ("Error closing temporary reparsepoint open)"));
+ }
+ }
+}
+ */
+
static int initiate_cifs_search(const int xid, struct file *file)
{
int rc = 0;
@@ -491,7 +532,10 @@ ffirst_retry:
CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
if (rc == 0)
cifsFile->invalidHandle = false;
- if ((rc == -EOPNOTSUPP) &&
+ /* BB add following call to handle readdir on new NTFS symlink errors
+ else if STATUS_STOPPED_ON_SYMLINK
+ call get_symlink_reparse_path and retry with new path */
+ else if ((rc == -EOPNOTSUPP) &&
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
goto ffirst_retry;
@@ -820,7 +864,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
/* inode num, inode type and filename returned */
static int cifs_get_name_from_search_buf(struct qstr *pqst,
char *current_entry, __u16 level, unsigned int unicode,
- struct cifs_sb_info *cifs_sb, int max_len, __u64 *pinum)
+ struct cifs_sb_info *cifs_sb, unsigned int max_len, __u64 *pinum)
{
int rc = 0;
unsigned int len = 0;
@@ -840,7 +884,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
len = strnlen(filename, PATH_MAX);
}
- *pinum = pFindData->UniqueId;
+ *pinum = le64_to_cpu(pFindData->UniqueId);
} else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
FILE_DIRECTORY_INFO *pFindData =
(FILE_DIRECTORY_INFO *)current_entry;
@@ -856,7 +900,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
(SEARCH_ID_FULL_DIR_INFO *)current_entry;
filename = &pFindData->FileName[0];
len = le32_to_cpu(pFindData->FileNameLength);
- *pinum = pFindData->UniqueId;
+ *pinum = le64_to_cpu(pFindData->UniqueId);
} else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
FILE_BOTH_DIRECTORY_INFO *pFindData =
(FILE_BOTH_DIRECTORY_INFO *)current_entry;
@@ -879,14 +923,12 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
}
if (unicode) {
- /* BB fixme - test with long names */
- /* Note converted filename can be longer than in unicode */
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
- pqst->len = cifs_convertUCSpath((char *)pqst->name,
- (__le16 *)filename, len/2, nlt);
- else
- pqst->len = cifs_strfromUCS_le((char *)pqst->name,
- (__le16 *)filename, len/2, nlt);
+ pqst->len = cifs_from_ucs2((char *) pqst->name,
+ (__le16 *) filename,
+ UNICODE_NAME_MAX,
+ min(len, max_len), nlt,
+ cifs_sb->mnt_cifs_flags &
+ CIFS_MOUNT_MAP_SPECIAL_CHR);
} else {
pqst->name = filename;
pqst->len = len;
@@ -896,8 +938,8 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
return rc;
}
-static int cifs_filldir(char *pfindEntry, struct file *file,
- filldir_t filldir, void *direntry, char *scratch_buf, int max_len)
+static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
+ void *direntry, char *scratch_buf, unsigned int max_len)
{
int rc = 0;
struct qstr qstring;
@@ -994,7 +1036,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
int num_to_fill = 0;
char *tmp_buf = NULL;
char *end_of_smb;
- int max_len;
+ unsigned int max_len;
xid = GetXid();
@@ -1068,11 +1110,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
cifsFile->srch_inf.ntwrk_buf_start);
end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
- /* To be safe - for UCS to UTF-8 with strings loaded
- with the rare long characters alloc more to account for
- such multibyte target UTF-8 characters. cifs_unicode.c,
- which actually does the conversion, has the same limit */
- tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL);
+ tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL);
for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
if (current_entry == NULL) {
/* evaluate whether this case is an error */
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 5c68b4282be9..897a052270f9 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -3,7 +3,7 @@
*
* SMB/CIFS session setup handling routines
*
- * Copyright (c) International Business Machines Corp., 2006, 2007
+ * Copyright (c) International Business Machines Corp., 2006, 2009
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
@@ -111,7 +111,7 @@ static __le16 get_next_vcnum(struct cifsSesInfo *ses)
get_vc_num_exit:
write_unlock(&cifs_tcp_ses_lock);
- return le16_to_cpu(vcnum);
+ return cpu_to_le16(vcnum);
}
static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
@@ -277,85 +277,51 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
*pbcc_area = bcc_ptr;
}
-static int decode_unicode_ssetup(char **pbcc_area, int bleft,
- struct cifsSesInfo *ses,
- const struct nls_table *nls_cp)
+static void
+decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses,
+ const struct nls_table *nls_cp)
{
- int rc = 0;
- int words_left, len;
+ int len;
char *data = *pbcc_area;
-
-
cFYI(1, ("bleft %d", bleft));
-
- /* SMB header is unaligned, so cifs servers word align start of
- Unicode strings */
- data++;
- bleft--; /* Windows servers do not always double null terminate
- their final Unicode string - in which case we
- now will not attempt to decode the byte of junk
- which follows it */
-
- words_left = bleft / 2;
-
- /* save off server operating system */
- len = UniStrnlen((wchar_t *) data, words_left);
-
-/* 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 */
- if (len >= words_left)
- return rc;
+ /*
+ * Windows servers do not always double null terminate their final
+ * Unicode string. Check to see if there are an uneven number of bytes
+ * left. If so, then add an extra NULL pad byte to the end of the
+ * response.
+ *
+ * See section 2.7.2 in "Implementing CIFS" for details
+ */
+ if (bleft % 2) {
+ data[bleft] = 0;
+ ++bleft;
+ }
kfree(ses->serverOS);
- /* UTF-8 string will not grow more than four times as big as UCS-16 */
- ses->serverOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL);
- if (ses->serverOS != NULL)
- cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp);
- data += 2 * (len + 1);
- words_left -= len + 1;
-
- /* save off server network operating system */
- len = UniStrnlen((wchar_t *) data, words_left);
-
- if (len >= words_left)
- return rc;
+ ses->serverOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
+ cFYI(1, ("serverOS=%s", ses->serverOS));
+ len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
+ data += len;
+ bleft -= len;
+ if (bleft <= 0)
+ return;
kfree(ses->serverNOS);
- ses->serverNOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL);
- if (ses->serverNOS != NULL) {
- cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
- nls_cp);
- if (strncmp(ses->serverNOS, "NT LAN Manager 4", 16) == 0) {
- cFYI(1, ("NT4 server"));
- ses->flags |= CIFS_SES_NT4;
- }
- }
- data += 2 * (len + 1);
- words_left -= len + 1;
-
- /* save off server domain */
- len = UniStrnlen((wchar_t *) data, words_left);
-
- if (len > words_left)
- return rc;
+ ses->serverNOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
+ cFYI(1, ("serverNOS=%s", ses->serverNOS));
+ len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
+ data += len;
+ bleft -= len;
+ if (bleft <= 0)
+ return;
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,
- nls_cp);
- ses->serverDomain[2*len] = 0;
- ses->serverDomain[(2*len) + 1] = 0;
- }
- data += 2 * (len + 1);
- words_left -= len + 1;
+ ses->serverDomain = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
+ cFYI(1, ("serverDomain=%s", ses->serverDomain));
- cFYI(1, ("words left: %d", words_left));
-
- return rc;
+ return;
}
static int decode_ascii_ssetup(char **pbcc_area, int bleft,
@@ -412,6 +378,186 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft,
return rc;
}
+static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
+ struct cifsSesInfo *ses)
+{
+ CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr;
+
+ if (blob_len < sizeof(CHALLENGE_MESSAGE)) {
+ cERROR(1, ("challenge blob len %d too small", blob_len));
+ return -EINVAL;
+ }
+
+ if (memcmp(pblob->Signature, "NTLMSSP", 8)) {
+ cERROR(1, ("blob signature incorrect %s", pblob->Signature));
+ return -EINVAL;
+ }
+ if (pblob->MessageType != NtLmChallenge) {
+ cERROR(1, ("Incorrect message type %d", pblob->MessageType));
+ return -EINVAL;
+ }
+
+ memcpy(ses->server->cryptKey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE);
+ /* BB we could decode pblob->NegotiateFlags; some may be useful */
+ /* In particular we can examine sign flags */
+ /* BB spec says that if AvId field of MsvAvTimestamp is populated then
+ we must set the MIC field of the AUTHENTICATE_MESSAGE */
+
+ return 0;
+}
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+/* BB Move to ntlmssp.c eventually */
+
+/* We do not malloc the blob, it is passed in pbuffer, because
+ it is fixed size, and small, making this approach cleaner */
+static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
+ struct cifsSesInfo *ses)
+{
+ NEGOTIATE_MESSAGE *sec_blob = (NEGOTIATE_MESSAGE *)pbuffer;
+ __u32 flags;
+
+ memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
+ sec_blob->MessageType = NtLmNegotiate;
+
+ /* BB is NTLMV2 session security format easier to use here? */
+ flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
+ NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
+ NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM;
+ if (ses->server->secMode &
+ (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+ flags |= NTLMSSP_NEGOTIATE_SIGN;
+ if (ses->server->secMode & SECMODE_SIGN_REQUIRED)
+ flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
+
+ sec_blob->NegotiateFlags |= cpu_to_le32(flags);
+
+ sec_blob->WorkstationName.BufferOffset = 0;
+ sec_blob->WorkstationName.Length = 0;
+ sec_blob->WorkstationName.MaximumLength = 0;
+
+ /* Domain name is sent on the Challenge not Negotiate NTLMSSP request */
+ sec_blob->DomainName.BufferOffset = 0;
+ sec_blob->DomainName.Length = 0;
+ sec_blob->DomainName.MaximumLength = 0;
+}
+
+/* We do not malloc the blob, it is passed in pbuffer, because its
+ maximum possible size is fixed and small, making this approach cleaner.
+ This function returns the length of the data in the blob */
+static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
+ struct cifsSesInfo *ses,
+ const struct nls_table *nls_cp, int first)
+{
+ AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer;
+ __u32 flags;
+ unsigned char *tmp;
+ char ntlm_session_key[CIFS_SESS_KEY_SIZE];
+
+ memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
+ sec_blob->MessageType = NtLmAuthenticate;
+
+ flags = NTLMSSP_NEGOTIATE_56 |
+ NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO |
+ NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
+ NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM;
+ if (ses->server->secMode &
+ (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+ flags |= NTLMSSP_NEGOTIATE_SIGN;
+ if (ses->server->secMode & SECMODE_SIGN_REQUIRED)
+ flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
+
+ tmp = pbuffer + sizeof(AUTHENTICATE_MESSAGE);
+ sec_blob->NegotiateFlags |= cpu_to_le32(flags);
+
+ sec_blob->LmChallengeResponse.BufferOffset =
+ cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE));
+ sec_blob->LmChallengeResponse.Length = 0;
+ sec_blob->LmChallengeResponse.MaximumLength = 0;
+
+ /* calculate session key, BB what about adding similar ntlmv2 path? */
+ SMBNTencrypt(ses->password, ses->server->cryptKey, ntlm_session_key);
+ if (first)
+ cifs_calculate_mac_key(&ses->server->mac_signing_key,
+ ntlm_session_key, ses->password);
+
+ memcpy(tmp, ntlm_session_key, CIFS_SESS_KEY_SIZE);
+ sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer);
+ sec_blob->NtChallengeResponse.Length = cpu_to_le16(CIFS_SESS_KEY_SIZE);
+ sec_blob->NtChallengeResponse.MaximumLength =
+ cpu_to_le16(CIFS_SESS_KEY_SIZE);
+
+ tmp += CIFS_SESS_KEY_SIZE;
+
+ if (ses->domainName == NULL) {
+ sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
+ sec_blob->DomainName.Length = 0;
+ sec_blob->DomainName.MaximumLength = 0;
+ tmp += 2;
+ } else {
+ int len;
+ len = cifs_strtoUCS((__le16 *)tmp, ses->domainName,
+ MAX_USERNAME_SIZE, nls_cp);
+ len *= 2; /* unicode is 2 bytes each */
+ len += 2; /* trailing null */
+ sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
+ sec_blob->DomainName.Length = cpu_to_le16(len);
+ sec_blob->DomainName.MaximumLength = cpu_to_le16(len);
+ tmp += len;
+ }
+
+ if (ses->userName == NULL) {
+ sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
+ sec_blob->UserName.Length = 0;
+ sec_blob->UserName.MaximumLength = 0;
+ tmp += 2;
+ } else {
+ int len;
+ len = cifs_strtoUCS((__le16 *)tmp, ses->userName,
+ MAX_USERNAME_SIZE, nls_cp);
+ len *= 2; /* unicode is 2 bytes each */
+ len += 2; /* trailing null */
+ sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
+ sec_blob->UserName.Length = cpu_to_le16(len);
+ sec_blob->UserName.MaximumLength = cpu_to_le16(len);
+ tmp += len;
+ }
+
+ sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - pbuffer);
+ sec_blob->WorkstationName.Length = 0;
+ sec_blob->WorkstationName.MaximumLength = 0;
+ tmp += 2;
+
+ sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
+ sec_blob->SessionKey.Length = 0;
+ sec_blob->SessionKey.MaximumLength = 0;
+ return tmp - pbuffer;
+}
+
+
+static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB,
+ struct cifsSesInfo *ses)
+{
+ build_ntlmssp_negotiate_blob(&pSMB->req.SecurityBlob[0], ses);
+ pSMB->req.SecurityBlobLength = cpu_to_le16(sizeof(NEGOTIATE_MESSAGE));
+
+ return;
+}
+
+static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB,
+ struct cifsSesInfo *ses,
+ const struct nls_table *nls, int first_time)
+{
+ int bloblen;
+
+ bloblen = build_ntlmssp_auth_blob(&pSMB->req.SecurityBlob[0], ses, nls,
+ first_time);
+ pSMB->req.SecurityBlobLength = cpu_to_le16(bloblen);
+
+ return bloblen;
+}
+#endif
+
int
CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
const struct nls_table *nls_cp)
@@ -430,6 +576,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
__u16 action;
int bytes_remaining;
struct key *spnego_key = NULL;
+ __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
if (ses == NULL)
return -EINVAL;
@@ -437,6 +584,10 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
type = ses->server->secType;
cFYI(1, ("sess setup type %d", type));
+ssetup_ntlmssp_authenticate:
+ if (phase == NtLmChallenge)
+ phase = NtLmAuthenticate; /* if ntlmssp, now final phase */
+
if (type == LANMAN) {
#ifndef CONFIG_CIFS_WEAK_PW_HASH
/* LANMAN and plaintext are less secure and off by default.
@@ -650,9 +801,53 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
goto ssetup_exit;
#endif /* CONFIG_CIFS_UPCALL */
} else {
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+ if ((experimEnabled > 1) && (type == RawNTLMSSP)) {
+ if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) {
+ cERROR(1, ("NTLMSSP requires Unicode support"));
+ rc = -ENOSYS;
+ goto ssetup_exit;
+ }
+
+ cFYI(1, ("ntlmssp session setup phase %d", phase));
+ pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
+ capabilities |= CAP_EXTENDED_SECURITY;
+ pSMB->req.Capabilities |= cpu_to_le32(capabilities);
+ if (phase == NtLmNegotiate) {
+ setup_ntlmssp_neg_req(pSMB, ses);
+ iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
+ } else if (phase == NtLmAuthenticate) {
+ int blob_len;
+ blob_len = setup_ntlmssp_auth_req(pSMB, ses,
+ nls_cp,
+ first_time);
+ iov[1].iov_len = blob_len;
+ /* Make sure that we tell the server that we
+ are using the uid that it just gave us back
+ on the response (challenge) */
+ smb_buf->Uid = ses->Suid;
+ } else {
+ cERROR(1, ("invalid phase %d", phase));
+ rc = -ENOSYS;
+ goto ssetup_exit;
+ }
+ iov[1].iov_base = &pSMB->req.SecurityBlob[0];
+ /* unicode strings must be word aligned */
+ if ((iov[0].iov_len + iov[1].iov_len) % 2) {
+ *bcc_ptr = 0;
+ bcc_ptr++;
+ }
+ unicode_oslm_strings(&bcc_ptr, nls_cp);
+ } else {
+ cERROR(1, ("secType %d not supported!", type));
+ rc = -ENOSYS;
+ goto ssetup_exit;
+ }
+#else
cERROR(1, ("secType %d not supported!", type));
rc = -ENOSYS;
goto ssetup_exit;
+#endif
}
iov[2].iov_base = str_area;
@@ -668,12 +863,23 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
/* SMB request buf freed in SendReceive2 */
cFYI(1, ("ssetup rc from sendrecv2 is %d", rc));
- if (rc)
- goto ssetup_exit;
pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
smb_buf = (struct smb_hdr *)iov[0].iov_base;
+ if ((type == RawNTLMSSP) && (smb_buf->Status.CifsError ==
+ cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))) {
+ if (phase != NtLmNegotiate) {
+ cERROR(1, ("Unexpected more processing error"));
+ goto ssetup_exit;
+ }
+ /* NTLMSSP Negotiate sent now processing challenge (response) */
+ phase = NtLmChallenge; /* process ntlmssp challenge */
+ rc = 0; /* MORE_PROC rc is not an error here, but expected */
+ }
+ if (rc)
+ goto ssetup_exit;
+
if ((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
rc = -EIO;
cERROR(1, ("bad word count %d", smb_buf->WordCount));
@@ -692,22 +898,33 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
if (smb_buf->WordCount == 4) {
__u16 blob_len;
blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
- bcc_ptr += blob_len;
if (blob_len > bytes_remaining) {
cERROR(1, ("bad security blob length %d", blob_len));
rc = -EINVAL;
goto ssetup_exit;
}
+ if (phase == NtLmChallenge) {
+ rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses);
+ /* now goto beginning for ntlmssp authenticate phase */
+ if (rc)
+ goto ssetup_exit;
+ }
+ bcc_ptr += blob_len;
bytes_remaining -= blob_len;
}
/* BB check if Unicode and decode strings */
- if (smb_buf->Flags2 & SMBFLG2_UNICODE)
- rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
- ses, nls_cp);
- else
+ if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
+ /* unicode string area must be word-aligned */
+ if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
+ ++bcc_ptr;
+ --bytes_remaining;
+ }
+ decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses, nls_cp);
+ } else {
rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining,
ses, nls_cp);
+ }
ssetup_exit:
if (spnego_key) {
@@ -721,5 +938,9 @@ ssetup_exit:
} else if (resp_buf_type == CIFS_LARGE_BUFFER)
cifs_buf_release(iov[0].iov_base);
+ /* if ntlmssp, and negotiate succeeded, proceed to authenticate phase */
+ if ((phase == NtLmChallenge) && (rc == 0))
+ goto ssetup_ntlmssp_authenticate;
+
return rc;
}
diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h
index 7f50e8577c1c..c5084d27db7c 100644
--- a/fs/cifs/smberr.h
+++ b/fs/cifs/smberr.h
@@ -110,6 +110,7 @@
/* Below errors are used internally (do not come over the wire) for passthrough
from STATUS codes to POSIX only */
+#define ERRsymlink 0xFFFD
#define ErrTooManyLinks 0xFFFE
/* Following error codes may be generated with the ERRSRV error class.*/
diff --git a/fs/compat.c b/fs/compat.c
index 3f84d5f15889..cdd51a3a7c53 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -181,22 +181,24 @@ asmlinkage long compat_sys_newstat(char __user * filename,
struct compat_stat __user *statbuf)
{
struct kstat stat;
- int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
+ int error;
- if (!error)
- error = cp_compat_stat(&stat, statbuf);
- return error;
+ error = vfs_stat(filename, &stat);
+ if (error)
+ return error;
+ return cp_compat_stat(&stat, statbuf);
}
asmlinkage long compat_sys_newlstat(char __user * filename,
struct compat_stat __user *statbuf)
{
struct kstat stat;
- int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
+ int error;
- if (!error)
- error = cp_compat_stat(&stat, statbuf);
- return error;
+ error = vfs_lstat(filename, &stat);
+ if (error)
+ return error;
+ return cp_compat_stat(&stat, statbuf);
}
#ifndef __ARCH_WANT_STAT64
@@ -204,21 +206,12 @@ asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user *filename,
struct compat_stat __user *statbuf, int flag)
{
struct kstat stat;
- int error = -EINVAL;
-
- if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
- goto out;
-
- if (flag & AT_SYMLINK_NOFOLLOW)
- error = vfs_lstat_fd(dfd, filename, &stat);
- else
- error = vfs_stat_fd(dfd, filename, &stat);
-
- if (!error)
- error = cp_compat_stat(&stat, statbuf);
+ int error;
-out:
- return error;
+ error = vfs_fstatat(dfd, filename, &stat, flag);
+ if (error)
+ return error;
+ return cp_compat_stat(&stat, statbuf);
}
#endif
@@ -478,7 +471,7 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
ret = sys_fcntl(fd, cmd, (unsigned long)&f);
set_fs(old_fs);
if (cmd == F_GETLK && ret == 0) {
- /* GETLK was successfule and we need to return the data...
+ /* GETLK was successful and we need to return the data...
* but it needs to fit in the compat structure.
* l_start shouldn't be too big, unless the original
* start + end is greater than COMPAT_OFF_T_MAX, in which
@@ -819,10 +812,8 @@ asmlinkage long compat_sys_mount(char __user * dev_name, char __user * dir_name,
}
}
- lock_kernel();
retval = do_mount((char*)dev_page, dir_page, (char*)type_page,
flags, (void*)data_page);
- unlock_kernel();
out4:
free_page(data_page);
@@ -1483,6 +1474,7 @@ int compat_do_execve(char * filename,
struct linux_binprm *bprm;
struct file *file;
struct files_struct *displaced;
+ bool clear_in_exec;
int retval;
retval = unshare_files(&displaced);
@@ -1494,7 +1486,7 @@ int compat_do_execve(char * filename,
if (!bprm)
goto out_files;
- retval = mutex_lock_interruptible(&current->cred_exec_mutex);
+ retval = mutex_lock_interruptible(&current->cred_guard_mutex);
if (retval < 0)
goto out_free;
current->in_execve = 1;
@@ -1505,8 +1497,9 @@ int compat_do_execve(char * filename,
goto out_unlock;
retval = check_unsafe_exec(bprm);
- if (retval)
+ if (retval < 0)
goto out_unlock;
+ clear_in_exec = retval;
file = open_exec(filename);
retval = PTR_ERR(file);
@@ -1553,11 +1546,9 @@ int compat_do_execve(char * filename,
goto out;
/* execve succeeded */
- write_lock(&current->fs->lock);
current->fs->in_exec = 0;
- write_unlock(&current->fs->lock);
current->in_execve = 0;
- mutex_unlock(&current->cred_exec_mutex);
+ mutex_unlock(&current->cred_guard_mutex);
acct_update_integrals(current);
free_bprm(bprm);
if (displaced)
@@ -1575,13 +1566,12 @@ out_file:
}
out_unmark:
- write_lock(&current->fs->lock);
- current->fs->in_exec = 0;
- write_unlock(&current->fs->lock);
+ if (clear_in_exec)
+ current->fs->in_exec = 0;
out_unlock:
current->in_execve = 0;
- mutex_unlock(&current->cred_exec_mutex);
+ mutex_unlock(&current->cred_guard_mutex);
out_free:
free_bprm(bprm);
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 3e87ce443ea2..0aac371bff0b 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -58,7 +58,6 @@
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/atalk.h>
-#include <linux/loop.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci.h>
@@ -68,6 +67,7 @@
#include <linux/gigaset_dev.h>
#ifdef CONFIG_BLOCK
+#include <linux/loop.h>
#include <scsi/scsi.h>
#include <scsi/scsi_ioctl.h>
#include <scsi/sg.h>
@@ -1765,7 +1765,7 @@ static int do_i2c_smbus_ioctl(unsigned int fd, unsigned int cmd, unsigned long a
/* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
* for some operations; this forces use of the newer bridge-utils that
- * use compatiable ioctls
+ * use compatible ioctls
*/
static int old_bridge_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
@@ -2660,6 +2660,8 @@ HANDLE_IOCTL(SONET_GETFRAMING, do_atm_ioctl)
HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl)
/* block stuff */
#ifdef CONFIG_BLOCK
+/* loop */
+IGNORE_IOCTL(LOOP_CLR_FD)
/* Raw devices */
HANDLE_IOCTL(RAW_SETBIND, raw_ioctl)
HANDLE_IOCTL(RAW_GETBIND, raw_ioctl)
@@ -2728,9 +2730,6 @@ HANDLE_IOCTL(LPSETTIMEOUT, lp_timeout_trans)
IGNORE_IOCTL(VFAT_IOCTL_READDIR_BOTH32)
IGNORE_IOCTL(VFAT_IOCTL_READDIR_SHORT32)
-/* loop */
-IGNORE_IOCTL(LOOP_CLR_FD)
-
#ifdef CONFIG_SPARC
/* Sparc framebuffers, handled in sbusfb_compat_ioctl() */
IGNORE_IOCTL(FBIOGTYPE)
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h
index 762d287123ca..da6061a6df40 100644
--- a/fs/configfs/configfs_internal.h
+++ b/fs/configfs/configfs_internal.h
@@ -39,6 +39,9 @@ struct configfs_dirent {
umode_t s_mode;
struct dentry * s_dentry;
struct iattr * s_iattr;
+#ifdef CONFIG_LOCKDEP
+ int s_depth;
+#endif
};
#define CONFIGFS_ROOT 0x0001
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 05373db21a4e..63d88156db15 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -78,6 +78,92 @@ static const struct dentry_operations configfs_dentry_ops = {
.d_delete = configfs_d_delete,
};
+#ifdef CONFIG_LOCKDEP
+
+/*
+ * Helpers to make lockdep happy with our recursive locking of default groups'
+ * inodes (see configfs_attach_group() and configfs_detach_group()).
+ * We put default groups i_mutexes in separate classes according to their depth
+ * from the youngest non-default group ancestor.
+ *
+ * For a non-default group A having default groups A/B, A/C, and A/C/D, default
+ * groups A/B and A/C will have their inode's mutex in class
+ * default_group_class[0], and default group A/C/D will be in
+ * default_group_class[1].
+ *
+ * The lock classes are declared and assigned in inode.c, according to the
+ * s_depth value.
+ * The s_depth value is initialized to -1, adjusted to >= 0 when attaching
+ * default groups, and reset to -1 when all default groups are attached. During
+ * attachment, if configfs_create() sees s_depth > 0, the lock class of the new
+ * inode's mutex is set to default_group_class[s_depth - 1].
+ */
+
+static void configfs_init_dirent_depth(struct configfs_dirent *sd)
+{
+ sd->s_depth = -1;
+}
+
+static void configfs_set_dir_dirent_depth(struct configfs_dirent *parent_sd,
+ struct configfs_dirent *sd)
+{
+ int parent_depth = parent_sd->s_depth;
+
+ if (parent_depth >= 0)
+ sd->s_depth = parent_depth + 1;
+}
+
+static void
+configfs_adjust_dir_dirent_depth_before_populate(struct configfs_dirent *sd)
+{
+ /*
+ * item's i_mutex class is already setup, so s_depth is now only
+ * used to set new sub-directories s_depth, which is always done
+ * with item's i_mutex locked.
+ */
+ /*
+ * sd->s_depth == -1 iff we are a non default group.
+ * else (we are a default group) sd->s_depth > 0 (see
+ * create_dir()).
+ */
+ if (sd->s_depth == -1)
+ /*
+ * We are a non default group and we are going to create
+ * default groups.
+ */
+ sd->s_depth = 0;
+}
+
+static void
+configfs_adjust_dir_dirent_depth_after_populate(struct configfs_dirent *sd)
+{
+ /* We will not create default groups anymore. */
+ sd->s_depth = -1;
+}
+
+#else /* CONFIG_LOCKDEP */
+
+static void configfs_init_dirent_depth(struct configfs_dirent *sd)
+{
+}
+
+static void configfs_set_dir_dirent_depth(struct configfs_dirent *parent_sd,
+ struct configfs_dirent *sd)
+{
+}
+
+static void
+configfs_adjust_dir_dirent_depth_before_populate(struct configfs_dirent *sd)
+{
+}
+
+static void
+configfs_adjust_dir_dirent_depth_after_populate(struct configfs_dirent *sd)
+{
+}
+
+#endif /* CONFIG_LOCKDEP */
+
/*
* Allocates a new configfs_dirent and links it to the parent configfs_dirent
*/
@@ -94,6 +180,7 @@ static struct configfs_dirent *configfs_new_dirent(struct configfs_dirent * pare
INIT_LIST_HEAD(&sd->s_links);
INIT_LIST_HEAD(&sd->s_children);
sd->s_element = element;
+ configfs_init_dirent_depth(sd);
spin_lock(&configfs_dirent_lock);
if (parent_sd->s_type & CONFIGFS_USET_DROPPING) {
spin_unlock(&configfs_dirent_lock);
@@ -142,9 +229,15 @@ int configfs_make_dirent(struct configfs_dirent * parent_sd,
if (IS_ERR(sd))
return PTR_ERR(sd);
+ /*
+ * We need configfs_dirent_lock so that configfs_depend_prep()
+ * can see s_type accurately on other CPUs.
+ */
+ spin_lock(&configfs_dirent_lock);
sd->s_mode = mode;
sd->s_type = type;
sd->s_dentry = dentry;
+ spin_unlock(&configfs_dirent_lock);
if (dentry) {
dentry->d_fsdata = configfs_get(sd);
dentry->d_op = &configfs_dentry_ops;
@@ -187,6 +280,7 @@ static int create_dir(struct config_item * k, struct dentry * p,
error = configfs_make_dirent(p->d_fsdata, d, k, mode,
CONFIGFS_DIR | CONFIGFS_USET_CREATING);
if (!error) {
+ configfs_set_dir_dirent_depth(p->d_fsdata, d->d_fsdata);
error = configfs_create(d, mode, init_dir);
if (!error) {
inc_nlink(p->d_inode);
@@ -789,11 +883,13 @@ static int configfs_attach_group(struct config_item *parent_item,
* error, as rmdir() would.
*/
mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
+ configfs_adjust_dir_dirent_depth_before_populate(sd);
ret = populate_groups(to_config_group(item));
if (ret) {
configfs_detach_item(item);
dentry->d_inode->i_flags |= S_DEAD;
}
+ configfs_adjust_dir_dirent_depth_after_populate(sd);
mutex_unlock(&dentry->d_inode->i_mutex);
if (ret)
d_delete(dentry);
@@ -916,11 +1012,11 @@ static int configfs_dump(struct configfs_dirent *sd, int level)
* Note, btw, that this can be called at *any* time, even when a configfs
* subsystem isn't registered, or when configfs is loading or unloading.
* Just like configfs_register_subsystem(). So we take the same
- * precautions. We pin the filesystem. We lock each i_mutex _in_order_
- * on our way down the tree. If we can find the target item in the
+ * precautions. We pin the filesystem. We lock configfs_dirent_lock.
+ * If we can find the target item in the
* configfs tree, it must be part of the subsystem tree as well, so we
- * do not need the subsystem semaphore. Holding the i_mutex chain locks
- * out mkdir() and rmdir(), who might be racing us.
+ * do not need the subsystem semaphore. Holding configfs_dirent_lock helps
+ * locking out mkdir() and rmdir(), who might be racing us.
*/
/*
@@ -933,17 +1029,22 @@ static int configfs_dump(struct configfs_dirent *sd, int level)
* do that so we can unlock it if we find nothing.
*
* Here we do a depth-first search of the dentry hierarchy looking for
- * our object. We take i_mutex on each step of the way down. IT IS
- * ESSENTIAL THAT i_mutex LOCKING IS ORDERED. If we come back up a branch,
- * we'll drop the i_mutex.
+ * our object.
+ * We deliberately ignore items tagged as dropping since they are virtually
+ * dead, as well as items in the middle of attachment since they virtually
+ * do not exist yet. This completes the locking out of racing mkdir() and
+ * rmdir().
+ * Note: items in the middle of attachment start with s_type = 0
+ * (configfs_new_dirent()), and configfs_make_dirent() (called from
+ * create_dir()) sets s_type = CONFIGFS_DIR|CONFIGFS_USET_CREATING. In both
+ * cases the item is ignored. configfs_make_dirent() is locked out from
+ * updating s_type by configfs_dirent_lock.
*
- * If the target is not found, -ENOENT is bubbled up and we have released
- * all locks. If the target was found, the locks will be cleared by
- * configfs_depend_rollback().
+ * If the target is not found, -ENOENT is bubbled up.
*
* This adds a requirement that all config_items be unique!
*
- * This is recursive because the locking traversal is tricky. There isn't
+ * This is recursive. There isn't
* much on the stack, though, so folks that need this function - be careful
* about your stack! Patches will be accepted to make it iterative.
*/
@@ -955,13 +1056,13 @@ static int configfs_depend_prep(struct dentry *origin,
BUG_ON(!origin || !sd);
- /* Lock this guy on the way down */
- mutex_lock(&sd->s_dentry->d_inode->i_mutex);
if (sd->s_element == target) /* Boo-yah */
goto out;
list_for_each_entry(child_sd, &sd->s_children, s_sibling) {
- if (child_sd->s_type & CONFIGFS_DIR) {
+ if ((child_sd->s_type & CONFIGFS_DIR) &&
+ !(child_sd->s_type & CONFIGFS_USET_DROPPING) &&
+ !(child_sd->s_type & CONFIGFS_USET_CREATING)) {
ret = configfs_depend_prep(child_sd->s_dentry,
target);
if (!ret)
@@ -970,33 +1071,12 @@ static int configfs_depend_prep(struct dentry *origin,
}
/* We looped all our children and didn't find target */
- mutex_unlock(&sd->s_dentry->d_inode->i_mutex);
ret = -ENOENT;
out:
return ret;
}
-/*
- * This is ONLY called if configfs_depend_prep() did its job. So we can
- * trust the entire path from item back up to origin.
- *
- * We walk backwards from item, unlocking each i_mutex. We finish by
- * unlocking origin.
- */
-static void configfs_depend_rollback(struct dentry *origin,
- struct config_item *item)
-{
- struct dentry *dentry = item->ci_dentry;
-
- while (dentry != origin) {
- mutex_unlock(&dentry->d_inode->i_mutex);
- dentry = dentry->d_parent;
- }
-
- mutex_unlock(&origin->d_inode->i_mutex);
-}
-
int configfs_depend_item(struct configfs_subsystem *subsys,
struct config_item *target)
{
@@ -1037,17 +1117,21 @@ int configfs_depend_item(struct configfs_subsystem *subsys,
/* Ok, now we can trust subsys/s_item */
- /* Scan the tree, locking i_mutex recursively, return 0 if found */
+ spin_lock(&configfs_dirent_lock);
+ /* Scan the tree, return 0 if found */
ret = configfs_depend_prep(subsys_sd->s_dentry, target);
if (ret)
- goto out_unlock_fs;
+ goto out_unlock_dirent_lock;
- /* We hold all i_mutexes from the subsystem down to the target */
+ /*
+ * We are sure that the item is not about to be removed by rmdir(), and
+ * not in the middle of attachment by mkdir().
+ */
p = target->ci_dentry->d_fsdata;
p->s_dependent_count += 1;
- configfs_depend_rollback(subsys_sd->s_dentry, target);
-
+out_unlock_dirent_lock:
+ spin_unlock(&configfs_dirent_lock);
out_unlock_fs:
mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex);
@@ -1072,10 +1156,10 @@ void configfs_undepend_item(struct configfs_subsystem *subsys,
struct configfs_dirent *sd;
/*
- * Since we can trust everything is pinned, we just need i_mutex
- * on the item.
+ * Since we can trust everything is pinned, we just need
+ * configfs_dirent_lock.
*/
- mutex_lock(&target->ci_dentry->d_inode->i_mutex);
+ spin_lock(&configfs_dirent_lock);
sd = target->ci_dentry->d_fsdata;
BUG_ON(sd->s_dependent_count < 1);
@@ -1086,7 +1170,7 @@ void configfs_undepend_item(struct configfs_subsystem *subsys,
* After this unlock, we cannot trust the item to stay alive!
* DO NOT REFERENCE item after this unlock.
*/
- mutex_unlock(&target->ci_dentry->d_inode->i_mutex);
+ spin_unlock(&configfs_dirent_lock);
}
EXPORT_SYMBOL(configfs_undepend_item);
@@ -1286,13 +1370,6 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
if (sd->s_type & CONFIGFS_USET_DEFAULT)
return -EPERM;
- /*
- * Here's where we check for dependents. We're protected by
- * i_mutex.
- */
- if (sd->s_dependent_count)
- return -EBUSY;
-
/* Get a working ref until we have the child */
parent_item = configfs_get_config_item(dentry->d_parent);
subsys = to_config_group(parent_item)->cg_subsys;
@@ -1316,9 +1393,17 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
mutex_lock(&configfs_symlink_mutex);
spin_lock(&configfs_dirent_lock);
- ret = configfs_detach_prep(dentry, &wait_mutex);
- if (ret)
- configfs_detach_rollback(dentry);
+ /*
+ * Here's where we check for dependents. We're protected by
+ * configfs_dirent_lock.
+ * If no dependent, atomically tag the item as dropping.
+ */
+ ret = sd->s_dependent_count ? -EBUSY : 0;
+ if (!ret) {
+ ret = configfs_detach_prep(dentry, &wait_mutex);
+ if (ret)
+ configfs_detach_rollback(dentry);
+ }
spin_unlock(&configfs_dirent_lock);
mutex_unlock(&configfs_symlink_mutex);
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
index 5d349d38e056..4921e7426d95 100644
--- a/fs/configfs/inode.c
+++ b/fs/configfs/inode.c
@@ -33,10 +33,15 @@
#include <linux/backing-dev.h>
#include <linux/capability.h>
#include <linux/sched.h>
+#include <linux/lockdep.h>
#include <linux/configfs.h>
#include "configfs_internal.h"
+#ifdef CONFIG_LOCKDEP
+static struct lock_class_key default_group_class[MAX_LOCK_DEPTH];
+#endif
+
extern struct super_block * configfs_sb;
static const struct address_space_operations configfs_aops = {
@@ -150,6 +155,38 @@ struct inode * configfs_new_inode(mode_t mode, struct configfs_dirent * sd)
return inode;
}
+#ifdef CONFIG_LOCKDEP
+
+static void configfs_set_inode_lock_class(struct configfs_dirent *sd,
+ struct inode *inode)
+{
+ int depth = sd->s_depth;
+
+ if (depth > 0) {
+ if (depth <= ARRAY_SIZE(default_group_class)) {
+ lockdep_set_class(&inode->i_mutex,
+ &default_group_class[depth - 1]);
+ } else {
+ /*
+ * In practice the maximum level of locking depth is
+ * already reached. Just inform about possible reasons.
+ */
+ printk(KERN_INFO "configfs: Too many levels of inodes"
+ " for the locking correctness validator.\n");
+ printk(KERN_INFO "Spurious warnings may appear.\n");
+ }
+ }
+}
+
+#else /* CONFIG_LOCKDEP */
+
+static void configfs_set_inode_lock_class(struct configfs_dirent *sd,
+ struct inode *inode)
+{
+}
+
+#endif /* CONFIG_LOCKDEP */
+
int configfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
{
int error = 0;
@@ -162,6 +199,7 @@ int configfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *
struct inode *p_inode = dentry->d_parent->d_inode;
p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
}
+ configfs_set_inode_lock_class(sd, inode);
goto Proceed;
}
else
diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c
index 932a92b31483..c8afa6b1d91d 100644
--- a/fs/configfs/symlink.c
+++ b/fs/configfs/symlink.c
@@ -135,7 +135,7 @@ int configfs_symlink(struct inode *dir, struct dentry *dentry, const char *symna
struct path path;
struct configfs_dirent *sd;
struct config_item *parent_item;
- struct config_item *target_item;
+ struct config_item *target_item = NULL;
struct config_item_type *type;
ret = -EPERM; /* What lack-of-symlink returns */
diff --git a/fs/dcache.c b/fs/dcache.c
index 761d30be2683..9e5cd3c3a6ba 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -481,7 +481,7 @@ restart:
if ((flags & DCACHE_REFERENCED)
&& (dentry->d_flags & DCACHE_REFERENCED)) {
dentry->d_flags &= ~DCACHE_REFERENCED;
- list_move_tail(&dentry->d_lru, &referenced);
+ list_move(&dentry->d_lru, &referenced);
spin_unlock(&dentry->d_lock);
} else {
list_move_tail(&dentry->d_lru, &tmp);
@@ -1910,7 +1910,7 @@ char *__d_path(const struct path *path, struct path *root,
spin_lock(&vfsmount_lock);
prepend(&end, &buflen, "\0", 1);
- if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
+ if (d_unlinked(dentry) &&
(prepend(&end, &buflen, " (deleted)", 10) != 0))
goto Elong;
@@ -2035,7 +2035,7 @@ char *dentry_path(struct dentry *dentry, char *buf, int buflen)
spin_lock(&dcache_lock);
prepend(&end, &buflen, "\0", 1);
- if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
+ if (d_unlinked(dentry) &&
(prepend(&end, &buflen, "//deleted", 9) != 0))
goto Elong;
if (buflen < 1)
@@ -2097,9 +2097,8 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
read_unlock(&current->fs->lock);
error = -ENOENT;
- /* Has the current directory has been unlinked? */
spin_lock(&dcache_lock);
- if (IS_ROOT(pwd.dentry) || !d_unhashed(pwd.dentry)) {
+ if (!d_unlinked(pwd.dentry)) {
unsigned long len;
struct path tmp = root;
char * cwd;
@@ -2149,7 +2148,6 @@ int is_subdir(struct dentry *new_dentry, struct dentry *old_dentry)
int result;
unsigned long seq;
- /* FIXME: This is old behavior, needed? Please check callers. */
if (new_dentry == old_dentry)
return 1;
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 63a4a59e4148..21165cf934ff 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -389,11 +389,10 @@ static int devpts_get_sb(struct file_system_type *fs_type,
return 0;
out_dput:
- dput(s->s_root);
+ dput(s->s_root); /* undo dget() in simple_set_mnt() */
out_undo_sget:
- up_write(&s->s_umount);
- deactivate_super(s);
+ deactivate_locked_super(s);
return error;
}
diff --git a/fs/direct-io.c b/fs/direct-io.c
index da258e7249cc..05763bbc2050 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -307,8 +307,6 @@ dio_bio_alloc(struct dio *dio, struct block_device *bdev,
struct bio *bio;
bio = bio_alloc(GFP_KERNEL, nr_vecs);
- if (bio == NULL)
- return -ENOMEM;
bio->bi_bdev = bdev;
bio->bi_sector = first_sector;
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index cd8e2df3c295..d489fcc86713 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -384,7 +384,7 @@ static void threads_stop(void)
dlm_astd_stop();
}
-static int new_lockspace(char *name, int namelen, void **lockspace,
+static int new_lockspace(const char *name, int namelen, void **lockspace,
uint32_t flags, int lvblen)
{
struct dlm_ls *ls;
@@ -419,16 +419,14 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
break;
}
ls->ls_create_count++;
- module_put(THIS_MODULE);
- error = 1; /* not an error, return 0 */
+ *lockspace = ls;
+ error = 1;
break;
}
spin_unlock(&lslist_lock);
- if (error < 0)
- goto out;
if (error)
- goto ret_zero;
+ goto out;
error = -ENOMEM;
@@ -583,7 +581,6 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
dlm_create_debug_file(ls);
log_debug(ls, "join complete");
- ret_zero:
*lockspace = ls;
return 0;
@@ -614,7 +611,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
return error;
}
-int dlm_new_lockspace(char *name, int namelen, void **lockspace,
+int dlm_new_lockspace(const char *name, int namelen, void **lockspace,
uint32_t flags, int lvblen)
{
int error = 0;
@@ -628,7 +625,9 @@ int dlm_new_lockspace(char *name, int namelen, void **lockspace,
error = new_lockspace(name, namelen, lockspace, flags, lvblen);
if (!error)
ls_count++;
- else if (!ls_count)
+ if (error > 0)
+ error = 0;
+ if (!ls_count)
threads_stop();
out:
mutex_unlock(&ls_lock);
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 8b65f289ee00..b91851f1cda3 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -483,15 +483,7 @@ int ecryptfs_encrypt_page(struct page *page)
ecryptfs_inode = page->mapping->host;
crypt_stat =
&(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat);
- if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
- rc = ecryptfs_write_lower_page_segment(ecryptfs_inode, page,
- 0, PAGE_CACHE_SIZE);
- if (rc)
- printk(KERN_ERR "%s: Error attempting to copy "
- "page at index [%ld]\n", __func__,
- page->index);
- goto out;
- }
+ BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED));
enc_extent_page = alloc_page(GFP_USER);
if (!enc_extent_page) {
rc = -ENOMEM;
@@ -620,16 +612,7 @@ int ecryptfs_decrypt_page(struct page *page)
ecryptfs_inode = page->mapping->host;
crypt_stat =
&(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat);
- if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
- rc = ecryptfs_read_lower_page_segment(page, page->index, 0,
- PAGE_CACHE_SIZE,
- ecryptfs_inode);
- if (rc)
- printk(KERN_ERR "%s: Error attempting to copy "
- "page at index [%ld]\n", __func__,
- page->index);
- goto out;
- }
+ BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED));
enc_extent_page = alloc_page(GFP_USER);
if (!enc_extent_page) {
rc = -ENOMEM;
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 064c5820e4e5..00b30a2d5466 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -269,6 +269,7 @@ struct ecryptfs_crypt_stat {
#define ECRYPTFS_ENCRYPT_FILENAMES 0x00000800
#define ECRYPTFS_ENCFN_USE_MOUNT_FNEK 0x00001000
#define ECRYPTFS_ENCFN_USE_FEK 0x00002000
+#define ECRYPTFS_UNLINK_SIGS 0x00004000
u32 flags;
unsigned int file_version;
size_t iv_bytes;
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 55b3145b8072..2f0945d63297 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -379,9 +379,11 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
goto out_d_drop;
}
lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent);
+ mutex_lock(&lower_dir_dentry->d_inode->i_mutex);
lower_dentry = lookup_one_len(ecryptfs_dentry->d_name.name,
lower_dir_dentry,
ecryptfs_dentry->d_name.len);
+ mutex_unlock(&lower_dir_dentry->d_inode->i_mutex);
if (IS_ERR(lower_dentry)) {
rc = PTR_ERR(lower_dentry);
printk(KERN_ERR "%s: lookup_one_len() returned [%d] on "
@@ -406,9 +408,11 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
"filename; rc = [%d]\n", __func__, rc);
goto out_d_drop;
}
+ mutex_lock(&lower_dir_dentry->d_inode->i_mutex);
lower_dentry = lookup_one_len(encrypted_and_encoded_name,
lower_dir_dentry,
encrypted_and_encoded_name_size - 1);
+ mutex_unlock(&lower_dir_dentry->d_inode->i_mutex);
if (IS_ERR(lower_dentry)) {
rc = PTR_ERR(lower_dentry);
printk(KERN_ERR "%s: lookup_one_len() returned [%d] on "
@@ -636,8 +640,9 @@ static int
ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
{
char *lower_buf;
+ size_t lower_bufsiz;
struct dentry *lower_dentry;
- struct ecryptfs_crypt_stat *crypt_stat;
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
char *plaintext_name;
size_t plaintext_name_size;
mm_segment_t old_fs;
@@ -648,12 +653,21 @@ ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
rc = -EINVAL;
goto out;
}
- crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
+ mount_crypt_stat = &ecryptfs_superblock_to_private(
+ dentry->d_sb)->mount_crypt_stat;
+ /*
+ * If the lower filename is encrypted, it will result in a significantly
+ * longer name. If needed, truncate the name after decode and decrypt.
+ */
+ if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)
+ lower_bufsiz = PATH_MAX;
+ else
+ lower_bufsiz = bufsiz;
/* Released in this function */
- lower_buf = kmalloc(bufsiz, GFP_KERNEL);
+ lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL);
if (lower_buf == NULL) {
printk(KERN_ERR "%s: Out of memory whilst attempting to "
- "kmalloc [%d] bytes\n", __func__, bufsiz);
+ "kmalloc [%zd] bytes\n", __func__, lower_bufsiz);
rc = -ENOMEM;
goto out;
}
@@ -661,7 +675,7 @@ ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
set_fs(get_ds());
rc = lower_dentry->d_inode->i_op->readlink(lower_dentry,
(char __user *)lower_buf,
- bufsiz);
+ lower_bufsiz);
set_fs(old_fs);
if (rc >= 0) {
rc = ecryptfs_decode_and_decrypt_filename(&plaintext_name,
@@ -674,7 +688,9 @@ ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
rc);
goto out_free_lower_buf;
}
- rc = copy_to_user(buf, plaintext_name, plaintext_name_size);
+ /* Check for bufsiz <= 0 done in sys_readlinkat() */
+ rc = copy_to_user(buf, plaintext_name,
+ min((size_t) bufsiz, plaintext_name_size));
if (rc)
rc = -EFAULT;
else
@@ -814,6 +830,13 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
size_t num_zeros = (PAGE_CACHE_SIZE
- (new_length & ~PAGE_CACHE_MASK));
+ if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
+ rc = vmtruncate(inode, new_length);
+ if (rc)
+ goto out_free;
+ rc = vmtruncate(lower_dentry->d_inode, new_length);
+ goto out_free;
+ }
if (num_zeros) {
char *zeros_virt;
@@ -915,8 +938,6 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
}
rc = 0;
crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
- mutex_unlock(&crypt_stat->cs_mutex);
- goto out;
}
}
mutex_unlock(&crypt_stat->cs_mutex);
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index aed56c25539b..9f0aa9883c28 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -190,14 +190,14 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
init_special_inode(inode, lower_inode->i_mode,
lower_inode->i_rdev);
dentry->d_op = &ecryptfs_dops;
- if (flags & ECRYPTFS_INTERPOSE_FLAG_D_ADD)
- d_add(dentry, inode);
- else
- d_instantiate(dentry, inode);
fsstack_copy_attr_all(inode, lower_inode, NULL);
/* This size will be overwritten for real files w/ headers and
* other metadata */
fsstack_copy_inode_size(inode, lower_inode);
+ if (flags & ECRYPTFS_INTERPOSE_FLAG_D_ADD)
+ d_add(dentry, inode);
+ else
+ d_instantiate(dentry, inode);
out:
return rc;
}
@@ -208,7 +208,7 @@ enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig,
ecryptfs_opt_passthrough, ecryptfs_opt_xattr_metadata,
ecryptfs_opt_encrypted_view, ecryptfs_opt_fnek_sig,
ecryptfs_opt_fn_cipher, ecryptfs_opt_fn_cipher_key_bytes,
- ecryptfs_opt_err };
+ ecryptfs_opt_unlink_sigs, ecryptfs_opt_err };
static const match_table_t tokens = {
{ecryptfs_opt_sig, "sig=%s"},
@@ -222,6 +222,7 @@ static const match_table_t tokens = {
{ecryptfs_opt_fnek_sig, "ecryptfs_fnek_sig=%s"},
{ecryptfs_opt_fn_cipher, "ecryptfs_fn_cipher=%s"},
{ecryptfs_opt_fn_cipher_key_bytes, "ecryptfs_fn_key_bytes=%u"},
+ {ecryptfs_opt_unlink_sigs, "ecryptfs_unlink_sigs"},
{ecryptfs_opt_err, NULL}
};
@@ -402,6 +403,9 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
fn_cipher_key_bytes;
fn_cipher_key_bytes_set = 1;
break;
+ case ecryptfs_opt_unlink_sigs:
+ mount_crypt_stat->flags |= ECRYPTFS_UNLINK_SIGS;
+ break;
case ecryptfs_opt_err:
default:
printk(KERN_WARNING
@@ -610,9 +614,8 @@ static int ecryptfs_get_sb(struct file_system_type *fs_type, int flags,
}
goto out;
out_abort:
- dput(sb->s_root);
- up_write(&sb->s_umount);
- deactivate_super(sb);
+ dput(sb->s_root); /* aka mnt->mnt_root, as set by get_sb_nodev() */
+ deactivate_locked_super(sb);
out:
return rc;
}
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c
index 295e7fa56755..f1c17e87c5fb 100644
--- a/fs/ecryptfs/messaging.c
+++ b/fs/ecryptfs/messaging.c
@@ -133,45 +133,6 @@ out:
return rc;
}
-static int
-ecryptfs_send_message_locked(char *data, int data_len, u8 msg_type,
- struct ecryptfs_msg_ctx **msg_ctx);
-
-/**
- * ecryptfs_send_raw_message
- * @msg_type: Message type
- * @daemon: Daemon struct for recipient of message
- *
- * A raw message is one that does not include an ecryptfs_message
- * struct. It simply has a type.
- *
- * Must be called with ecryptfs_daemon_hash_mux held.
- *
- * Returns zero on success; non-zero otherwise
- */
-static int ecryptfs_send_raw_message(u8 msg_type,
- struct ecryptfs_daemon *daemon)
-{
- struct ecryptfs_msg_ctx *msg_ctx;
- int rc;
-
- rc = ecryptfs_send_message_locked(NULL, 0, msg_type, &msg_ctx);
- if (rc) {
- printk(KERN_ERR "%s: Error whilst attempting to send "
- "message to ecryptfsd; rc = [%d]\n", __func__, rc);
- goto out;
- }
- /* Raw messages are logically context-free (e.g., no
- * reply is expected), so we set the state of the
- * ecryptfs_msg_ctx object to indicate that it should
- * be freed as soon as the message is sent. */
- mutex_lock(&msg_ctx->mux);
- msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_NO_REPLY;
- mutex_unlock(&msg_ctx->mux);
-out:
- return rc;
-}
-
/**
* ecryptfs_spawn_daemon - Create and initialize a new daemon struct
* @daemon: Pointer to set to newly allocated daemon struct
@@ -212,49 +173,6 @@ out:
}
/**
- * ecryptfs_process_helo
- * @euid: The user ID owner of the message
- * @user_ns: The namespace in which @euid applies
- * @pid: The process ID for the userspace program that sent the
- * message
- *
- * Adds the euid and pid values to the daemon euid hash. If an euid
- * already has a daemon pid registered, the daemon will be
- * unregistered before the new daemon is put into the hash list.
- * Returns zero after adding a new daemon to the hash list;
- * non-zero otherwise.
- */
-int ecryptfs_process_helo(uid_t euid, struct user_namespace *user_ns,
- struct pid *pid)
-{
- struct ecryptfs_daemon *new_daemon;
- struct ecryptfs_daemon *old_daemon;
- int rc;
-
- mutex_lock(&ecryptfs_daemon_hash_mux);
- rc = ecryptfs_find_daemon_by_euid(&old_daemon, euid, user_ns);
- if (rc != 0) {
- printk(KERN_WARNING "Received request from user [%d] "
- "to register daemon [0x%p]; unregistering daemon "
- "[0x%p]\n", euid, pid, old_daemon->pid);
- rc = ecryptfs_send_raw_message(ECRYPTFS_MSG_QUIT, old_daemon);
- if (rc)
- printk(KERN_WARNING "Failed to send QUIT "
- "message to daemon [0x%p]; rc = [%d]\n",
- old_daemon->pid, rc);
- hlist_del(&old_daemon->euid_chain);
- kfree(old_daemon);
- }
- rc = ecryptfs_spawn_daemon(&new_daemon, euid, user_ns, pid);
- if (rc)
- printk(KERN_ERR "%s: The gods are displeased with this attempt "
- "to create a new daemon object for euid [%d]; pid "
- "[0x%p]; rc = [%d]\n", __func__, euid, pid, rc);
- mutex_unlock(&ecryptfs_daemon_hash_mux);
- return rc;
-}
-
-/**
* ecryptfs_exorcise_daemon - Destroy the daemon struct
*
* Must be called ceremoniously while in possession of
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c
index a67fea655f49..4ec8f61ccf5a 100644
--- a/fs/ecryptfs/miscdev.c
+++ b/fs/ecryptfs/miscdev.c
@@ -193,26 +193,20 @@ int ecryptfs_send_miscdev(char *data, size_t data_size,
int rc = 0;
mutex_lock(&msg_ctx->mux);
- if (data) {
- msg_ctx->msg = kmalloc((sizeof(*msg_ctx->msg) + data_size),
- GFP_KERNEL);
- if (!msg_ctx->msg) {
- rc = -ENOMEM;
- printk(KERN_ERR "%s: Out of memory whilst attempting "
- "to kmalloc(%zd, GFP_KERNEL)\n", __func__,
- (sizeof(*msg_ctx->msg) + data_size));
- goto out_unlock;
- }
- } else
- msg_ctx->msg = NULL;
+ msg_ctx->msg = kmalloc((sizeof(*msg_ctx->msg) + data_size),
+ GFP_KERNEL);
+ if (!msg_ctx->msg) {
+ rc = -ENOMEM;
+ printk(KERN_ERR "%s: Out of memory whilst attempting "
+ "to kmalloc(%zd, GFP_KERNEL)\n", __func__,
+ (sizeof(*msg_ctx->msg) + data_size));
+ goto out_unlock;
+ }
msg_ctx->msg->index = msg_ctx->index;
msg_ctx->msg->data_len = data_size;
msg_ctx->type = msg_type;
- if (data) {
- memcpy(msg_ctx->msg->data, data, data_size);
- msg_ctx->msg_size = (sizeof(*msg_ctx->msg) + data_size);
- } else
- msg_ctx->msg_size = 0;
+ memcpy(msg_ctx->msg->data, data, data_size);
+ msg_ctx->msg_size = (sizeof(*msg_ctx->msg) + data_size);
mutex_lock(&daemon->mux);
list_add_tail(&msg_ctx->daemon_out_list, &daemon->msg_ctx_out_queue);
daemon->num_queued_msg_ctx++;
@@ -418,18 +412,13 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
if (count == 0)
goto out;
- data = kmalloc(count, GFP_KERNEL);
- if (!data) {
- printk(KERN_ERR "%s: Out of memory whilst attempting to "
- "kmalloc([%zd], GFP_KERNEL)\n", __func__, count);
+
+ data = memdup_user(buf, count);
+ if (IS_ERR(data)) {
+ printk(KERN_ERR "%s: memdup_user returned error [%ld]\n",
+ __func__, PTR_ERR(data));
goto out;
}
- rc = copy_from_user(data, buf, count);
- if (rc) {
- printk(KERN_ERR "%s: copy_from_user returned error [%d]\n",
- __func__, rc);
- goto out_free;
- }
sz = count;
i = 0;
switch (data[i++]) {
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 46cec2b69796..5c6bab9786e3 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -449,6 +449,7 @@ int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode)
struct ecryptfs_crypt_stat *crypt_stat;
crypt_stat = &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
+ BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED));
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
return ecryptfs_write_inode_size_to_xattr(ecryptfs_inode);
else
@@ -490,6 +491,16 @@ static int ecryptfs_write_end(struct file *file,
ecryptfs_printk(KERN_DEBUG, "Not a new file\n");
ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page"
"(page w/ index = [0x%.16x], to = [%d])\n", index, to);
+ if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
+ rc = ecryptfs_write_lower_page_segment(ecryptfs_inode, page, 0,
+ to);
+ if (!rc) {
+ rc = copied;
+ fsstack_copy_inode_size(ecryptfs_inode,
+ ecryptfs_inode_to_lower(ecryptfs_inode));
+ }
+ goto out;
+ }
/* Fills in zeros if 'to' goes beyond inode size */
rc = fill_zeros_to_end_of_page(page, to);
if (rc) {
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c
index 75c2ea9fee35..a137c6ea2fee 100644
--- a/fs/ecryptfs/read_write.c
+++ b/fs/ecryptfs/read_write.c
@@ -117,13 +117,15 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
size_t size)
{
struct page *ecryptfs_page;
+ struct ecryptfs_crypt_stat *crypt_stat;
+ struct inode *ecryptfs_inode = ecryptfs_file->f_dentry->d_inode;
char *ecryptfs_page_virt;
- loff_t ecryptfs_file_size =
- i_size_read(ecryptfs_file->f_dentry->d_inode);
+ loff_t ecryptfs_file_size = i_size_read(ecryptfs_inode);
loff_t data_offset = 0;
loff_t pos;
int rc = 0;
+ crypt_stat = &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
/*
* if we are writing beyond current size, then start pos
* at the current size - we'll fill in zeros from there.
@@ -184,7 +186,13 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
flush_dcache_page(ecryptfs_page);
SetPageUptodate(ecryptfs_page);
unlock_page(ecryptfs_page);
- rc = ecryptfs_encrypt_page(ecryptfs_page);
+ if (crypt_stat->flags & ECRYPTFS_ENCRYPTED)
+ rc = ecryptfs_encrypt_page(ecryptfs_page);
+ else
+ rc = ecryptfs_write_lower_page_segment(ecryptfs_inode,
+ ecryptfs_page,
+ start_offset_in_page,
+ data_offset);
page_cache_release(ecryptfs_page);
if (rc) {
printk(KERN_ERR "%s: Error encrypting "
@@ -194,14 +202,16 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
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;
+ i_size_write(ecryptfs_inode, (offset + size));
+ if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) {
+ rc = ecryptfs_write_inode_size_to_metadata(
+ ecryptfs_inode);
+ if (rc) {
+ printk(KERN_ERR "Problem with "
+ "ecryptfs_write_inode_size_to_metadata; "
+ "rc = [%d]\n", rc);
+ goto out;
+ }
}
}
out:
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c
index c27ac2b358a1..12d649602d3a 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/smp_lock.h>
#include <linux/file.h>
#include <linux/crypto.h>
#include "ecryptfs_kernel.h"
@@ -120,9 +121,13 @@ static void ecryptfs_put_super(struct super_block *sb)
{
struct ecryptfs_sb_info *sb_info = ecryptfs_superblock_to_private(sb);
+ lock_kernel();
+
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);
+
+ unlock_kernel();
}
/**
@@ -170,7 +175,10 @@ static int ecryptfs_show_options(struct seq_file *m, struct vfsmount *mnt)
list_for_each_entry(walker,
&mount_crypt_stat->global_auth_tok_list,
mount_crypt_stat_list) {
- seq_printf(m, ",ecryptfs_sig=%s", walker->sig);
+ if (walker->flags & ECRYPTFS_AUTH_TOK_FNEK)
+ seq_printf(m, ",ecryptfs_fnek_sig=%s", walker->sig);
+ else
+ seq_printf(m, ",ecryptfs_sig=%s", walker->sig);
}
mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
@@ -186,6 +194,8 @@ static int ecryptfs_show_options(struct seq_file *m, struct vfsmount *mnt)
seq_printf(m, ",ecryptfs_xattr_metadata");
if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED)
seq_printf(m, ",ecryptfs_encrypted_view");
+ if (mount_crypt_stat->flags & ECRYPTFS_UNLINK_SIGS)
+ seq_printf(m, ",ecryptfs_unlink_sigs");
return 0;
}
diff --git a/fs/exec.c b/fs/exec.c
index 052a961e41aa..a7fcd975c6b2 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -69,17 +69,18 @@ int suid_dumpable = 0;
static LIST_HEAD(formats);
static DEFINE_RWLOCK(binfmt_lock);
-int register_binfmt(struct linux_binfmt * fmt)
+int __register_binfmt(struct linux_binfmt * fmt, int insert)
{
if (!fmt)
return -EINVAL;
write_lock(&binfmt_lock);
- list_add(&fmt->lh, &formats);
+ insert ? list_add(&fmt->lh, &formats) :
+ list_add_tail(&fmt->lh, &formats);
write_unlock(&binfmt_lock);
return 0;
}
-EXPORT_SYMBOL(register_binfmt);
+EXPORT_SYMBOL(__register_binfmt);
void unregister_binfmt(struct linux_binfmt * fmt)
{
@@ -104,40 +105,28 @@ static inline void put_binfmt(struct linux_binfmt * fmt)
SYSCALL_DEFINE1(uselib, const char __user *, library)
{
struct file *file;
- struct nameidata nd;
char *tmp = getname(library);
int error = PTR_ERR(tmp);
- if (!IS_ERR(tmp)) {
- error = path_lookup_open(AT_FDCWD, tmp,
- LOOKUP_FOLLOW, &nd,
- FMODE_READ|FMODE_EXEC);
- putname(tmp);
- }
- if (error)
+ if (IS_ERR(tmp))
+ goto out;
+
+ file = do_filp_open(AT_FDCWD, tmp,
+ O_LARGEFILE | O_RDONLY | FMODE_EXEC, 0,
+ MAY_READ | MAY_EXEC | MAY_OPEN);
+ putname(tmp);
+ error = PTR_ERR(file);
+ if (IS_ERR(file))
goto out;
error = -EINVAL;
- if (!S_ISREG(nd.path.dentry->d_inode->i_mode))
+ if (!S_ISREG(file->f_path.dentry->d_inode->i_mode))
goto exit;
error = -EACCES;
- if (nd.path.mnt->mnt_flags & MNT_NOEXEC)
+ if (file->f_path.mnt->mnt_flags & MNT_NOEXEC)
goto exit;
- error = inode_permission(nd.path.dentry->d_inode,
- MAY_READ | MAY_EXEC | MAY_OPEN);
- if (error)
- goto exit;
- error = ima_path_check(&nd.path, MAY_READ | MAY_EXEC | MAY_OPEN);
- if (error)
- goto exit;
-
- file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE);
- error = PTR_ERR(file);
- if (IS_ERR(file))
- goto out;
-
fsnotify_open(file->f_path.dentry);
error = -ENOEXEC;
@@ -159,13 +148,10 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
}
read_unlock(&binfmt_lock);
}
+exit:
fput(file);
out:
return error;
-exit:
- release_open_intent(&nd);
- path_put(&nd.path);
- goto out;
}
#ifdef CONFIG_MMU
@@ -660,47 +646,33 @@ EXPORT_SYMBOL(setup_arg_pages);
struct file *open_exec(const char *name)
{
- struct nameidata nd;
struct file *file;
int err;
- err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd,
- FMODE_READ|FMODE_EXEC);
- if (err)
+ file = do_filp_open(AT_FDCWD, name,
+ O_LARGEFILE | O_RDONLY | FMODE_EXEC, 0,
+ MAY_EXEC | MAY_OPEN);
+ if (IS_ERR(file))
goto out;
err = -EACCES;
- if (!S_ISREG(nd.path.dentry->d_inode->i_mode))
- goto out_path_put;
-
- if (nd.path.mnt->mnt_flags & MNT_NOEXEC)
- goto out_path_put;
-
- err = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_OPEN);
- if (err)
- goto out_path_put;
- err = ima_path_check(&nd.path, MAY_EXEC | MAY_OPEN);
- if (err)
- goto out_path_put;
+ if (!S_ISREG(file->f_path.dentry->d_inode->i_mode))
+ goto exit;
- file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE);
- if (IS_ERR(file))
- return file;
+ if (file->f_path.mnt->mnt_flags & MNT_NOEXEC)
+ goto exit;
fsnotify_open(file->f_path.dentry);
err = deny_write_access(file);
- if (err) {
- fput(file);
- goto out;
- }
+ if (err)
+ goto exit;
+out:
return file;
- out_path_put:
- release_open_intent(&nd);
- path_put(&nd.path);
- out:
+exit:
+ fput(file);
return ERR_PTR(err);
}
EXPORT_SYMBOL(open_exec);
@@ -1044,7 +1016,7 @@ void install_exec_creds(struct linux_binprm *bprm)
commit_creds(bprm->cred);
bprm->cred = NULL;
- /* cred_exec_mutex must be held at least to this point to prevent
+ /* cred_guard_mutex must be held at least to this point to prevent
* ptrace_attach() from altering our determination of the task's
* credentials; any time after this it may be unlocked */
@@ -1054,13 +1026,12 @@ EXPORT_SYMBOL(install_exec_creds);
/*
* determine how safe it is to execute the proposed program
- * - the caller must hold current->cred_exec_mutex to protect against
+ * - the caller must hold current->cred_guard_mutex to protect against
* PTRACE_ATTACH
*/
int check_unsafe_exec(struct linux_binprm *bprm)
{
struct task_struct *p = current, *t;
- unsigned long flags;
unsigned n_fs;
int res = 0;
@@ -1068,21 +1039,22 @@ int check_unsafe_exec(struct linux_binprm *bprm)
n_fs = 1;
write_lock(&p->fs->lock);
- lock_task_sighand(p, &flags);
+ rcu_read_lock();
for (t = next_thread(p); t != p; t = next_thread(t)) {
if (t->fs == p->fs)
n_fs++;
}
+ rcu_read_unlock();
if (p->fs->users > n_fs) {
bprm->unsafe |= LSM_UNSAFE_SHARE;
} else {
- if (p->fs->in_exec)
- res = -EAGAIN;
- p->fs->in_exec = 1;
+ res = -EAGAIN;
+ if (!p->fs->in_exec) {
+ p->fs->in_exec = 1;
+ res = 1;
+ }
}
-
- unlock_task_sighand(p, &flags);
write_unlock(&p->fs->lock);
return res;
@@ -1284,6 +1256,7 @@ int do_execve(char * filename,
struct linux_binprm *bprm;
struct file *file;
struct files_struct *displaced;
+ bool clear_in_exec;
int retval;
retval = unshare_files(&displaced);
@@ -1295,7 +1268,7 @@ int do_execve(char * filename,
if (!bprm)
goto out_files;
- retval = mutex_lock_interruptible(&current->cred_exec_mutex);
+ retval = mutex_lock_interruptible(&current->cred_guard_mutex);
if (retval < 0)
goto out_free;
current->in_execve = 1;
@@ -1306,8 +1279,9 @@ int do_execve(char * filename,
goto out_unlock;
retval = check_unsafe_exec(bprm);
- if (retval)
+ if (retval < 0)
goto out_unlock;
+ clear_in_exec = retval;
file = open_exec(filename);
retval = PTR_ERR(file);
@@ -1355,11 +1329,9 @@ int do_execve(char * filename,
goto out;
/* execve succeeded */
- write_lock(&current->fs->lock);
current->fs->in_exec = 0;
- write_unlock(&current->fs->lock);
current->in_execve = 0;
- mutex_unlock(&current->cred_exec_mutex);
+ mutex_unlock(&current->cred_guard_mutex);
acct_update_integrals(current);
free_bprm(bprm);
if (displaced)
@@ -1377,13 +1349,12 @@ out_file:
}
out_unmark:
- write_lock(&current->fs->lock);
- current->fs->in_exec = 0;
- write_unlock(&current->fs->lock);
+ if (clear_in_exec)
+ current->fs->in_exec = 0;
out_unlock:
current->in_execve = 0;
- mutex_unlock(&current->cred_exec_mutex);
+ mutex_unlock(&current->cred_guard_mutex);
out_free:
free_bprm(bprm);
diff --git a/fs/exofs/super.c b/fs/exofs/super.c
index 9f1985e857e2..cd1f8b18a218 100644
--- a/fs/exofs/super.c
+++ b/fs/exofs/super.c
@@ -258,6 +258,11 @@ static void exofs_put_super(struct super_block *sb)
int num_pend;
struct exofs_sb_info *sbi = sb->s_fs_info;
+ lock_kernel();
+
+ if (sb->s_dirt)
+ exofs_write_super(sb);
+
/* make sure there are no pending commands */
for (num_pend = atomic_read(&sbi->s_curr_pending); num_pend > 0;
num_pend = atomic_read(&sbi->s_curr_pending)) {
@@ -271,6 +276,8 @@ static void exofs_put_super(struct super_block *sb)
osduld_put_device(sbi->s_dev);
kfree(sb->s_fs_info);
sb->s_fs_info = NULL;
+
+ unlock_kernel();
}
/*
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 3203042b36ef..6888b2d7c5b1 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -27,7 +27,7 @@ struct ext2_inode_info {
/*
* i_block_group is the number of the block group which contains
* this file's inode. Constant across the lifetime of the inode,
- * it is ued for making block allocation decisions - we try to
+ * it is used for making block allocation decisions - we try to
* place a file's data blocks near its inode block, and new inodes
* near to their parent directory's inode.
*/
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index b43b95563663..acf678831103 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -590,9 +590,8 @@ static int ext2_get_blocks(struct inode *inode,
if (depth == 0)
return (err);
-reread:
- partial = ext2_get_branch(inode, depth, offsets, chain, &err);
+ partial = ext2_get_branch(inode, depth, offsets, chain, &err);
/* Simplest case - block found, no allocation needed */
if (!partial) {
first_block = le32_to_cpu(chain[depth - 1].key);
@@ -602,15 +601,16 @@ reread:
while (count < maxblocks && count <= blocks_to_boundary) {
ext2_fsblk_t blk;
- if (!verify_chain(chain, partial)) {
+ if (!verify_chain(chain, chain + depth - 1)) {
/*
* 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.
*/
+ err = -EAGAIN;
count = 0;
- goto changed;
+ break;
}
blk = le32_to_cpu(*(chain[depth-1].p + count));
if (blk == first_block + count)
@@ -618,7 +618,8 @@ reread:
else
break;
}
- goto got_it;
+ if (err != -EAGAIN)
+ goto got_it;
}
/* Next simple case - plain lookup or failed read of indirect block */
@@ -626,6 +627,33 @@ reread:
goto cleanup;
mutex_lock(&ei->truncate_mutex);
+ /*
+ * If the indirect block is missing while we are reading
+ * the chain(ext3_get_branch() returns -EAGAIN err), or
+ * if the chain has been changed after we grab the semaphore,
+ * (either because another process truncated this branch, or
+ * another get_block allocated this branch) re-grab the chain to see if
+ * the request block has been allocated or not.
+ *
+ * Since we already block the truncate/other get_block
+ * at this point, we will have the current copy of the chain when we
+ * splice the branch into the tree.
+ */
+ if (err == -EAGAIN || !verify_chain(chain, partial)) {
+ while (partial > chain) {
+ brelse(partial->bh);
+ partial--;
+ }
+ partial = ext2_get_branch(inode, depth, offsets, chain, &err);
+ if (!partial) {
+ count++;
+ mutex_unlock(&ei->truncate_mutex);
+ if (err)
+ goto cleanup;
+ clear_buffer_new(bh_result);
+ goto got_it;
+ }
+ }
/*
* Okay, we need to do block allocation. Lazily initialize the block
@@ -683,12 +711,6 @@ cleanup:
partial--;
}
return err;
-changed:
- while (partial > chain) {
- brelse(partial->bh);
- partial--;
- }
- goto reread;
}
int ext2_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create)
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index f983225266dc..f5b7fadd2c07 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -114,6 +114,11 @@ static void ext2_put_super (struct super_block * sb)
int i;
struct ext2_sb_info *sbi = EXT2_SB(sb);
+ lock_kernel();
+
+ if (sb->s_dirt)
+ ext2_write_super(sb);
+
ext2_xattr_put_super(sb);
if (!(sb->s_flags & MS_RDONLY)) {
struct ext2_super_block *es = sbi->s_es;
@@ -135,7 +140,7 @@ static void ext2_put_super (struct super_block * sb)
kfree(sbi->s_blockgroup_lock);
kfree(sbi);
- return;
+ unlock_kernel();
}
static struct kmem_cache * ext2_inode_cachep;
@@ -1395,8 +1400,10 @@ static ssize_t ext2_quota_write(struct super_block *sb, int type,
blk++;
}
out:
- if (len == towrite)
+ if (len == towrite) {
+ mutex_unlock(&inode->i_mutex);
return err;
+ }
if (inode->i_size < off+len-towrite)
i_size_write(inode, off+len-towrite);
inode->i_version++;
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index d81ef2fdb08e..e0c745451715 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -129,12 +129,15 @@ fail:
static inline struct posix_acl *
ext3_iget_acl(struct inode *inode, struct posix_acl **i_acl)
{
- struct posix_acl *acl = EXT3_ACL_NOT_CACHED;
+ struct posix_acl *acl = ACCESS_ONCE(*i_acl);
- spin_lock(&inode->i_lock);
- if (*i_acl != EXT3_ACL_NOT_CACHED)
- acl = posix_acl_dup(*i_acl);
- spin_unlock(&inode->i_lock);
+ if (acl) {
+ spin_lock(&inode->i_lock);
+ acl = *i_acl;
+ if (acl != EXT3_ACL_NOT_CACHED)
+ acl = posix_acl_dup(acl);
+ spin_unlock(&inode->i_lock);
+ }
return acl;
}
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index 225202db8974..27967f92e820 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -649,7 +649,7 @@ do_more:
count = overflow;
goto do_more;
}
- sb->s_dirt = 1;
+
error_return:
brelse(bitmap_bh);
ext3_std_error(sb, err);
@@ -1708,7 +1708,6 @@ allocated:
if (!fatal)
fatal = err;
- sb->s_dirt = 1;
if (fatal)
goto out;
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index dd13d60d524b..b39991285136 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -181,7 +181,7 @@ void ext3_free_inode (handle_t *handle, struct inode * inode)
err = ext3_journal_dirty_metadata(handle, bitmap_bh);
if (!fatal)
fatal = err;
- sb->s_dirt = 1;
+
error_return:
brelse(bitmap_bh);
ext3_std_error(sb, fatal);
@@ -537,7 +537,6 @@ got:
percpu_counter_dec(&sbi->s_freeinodes_counter);
if (S_ISDIR(mode))
percpu_counter_inc(&sbi->s_dirs_counter);
- sb->s_dirt = 1;
inode->i_uid = current_fsuid();
if (test_opt (sb, GRPID))
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index fcfa24361856..b0248c6d5d4c 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -2960,7 +2960,6 @@ static int ext3_do_update_inode(handle_t *handle,
ext3_update_dynamic_rev(sb);
EXT3_SET_RO_COMPAT_FEATURE(sb,
EXT3_FEATURE_RO_COMPAT_LARGE_FILE);
- sb->s_dirt = 1;
handle->h_sync = 1;
err = ext3_journal_dirty_metadata(handle,
EXT3_SB(sb)->s_sbh);
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c
index 78fdf3836370..8a0b26340b54 100644
--- a/fs/ext3/resize.c
+++ b/fs/ext3/resize.c
@@ -934,7 +934,6 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
EXT3_INODES_PER_GROUP(sb));
ext3_journal_dirty_metadata(handle, sbi->s_sbh);
- sb->s_dirt = 1;
exit_journal:
unlock_super(sb);
@@ -1066,7 +1065,6 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
}
es->s_blocks_count = cpu_to_le32(o_blocks_count + add);
ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
- sb->s_dirt = 1;
unlock_super(sb);
ext3_debug("freeing blocks %lu through "E3FSBLK"\n", o_blocks_count,
o_blocks_count + add);
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 599dbfe504c3..0ca949dcc1ab 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -67,7 +67,6 @@ static const char *ext3_decode_error(struct super_block * sb, int errno,
static int ext3_remount (struct super_block * sb, int * flags, char * data);
static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf);
static int ext3_unfreeze(struct super_block *sb);
-static void ext3_write_super (struct super_block * sb);
static int ext3_freeze(struct super_block *sb);
/*
@@ -399,6 +398,8 @@ static void ext3_put_super (struct super_block * sb)
struct ext3_super_block *es = sbi->s_es;
int i, err;
+ lock_kernel();
+
ext3_xattr_put_super(sb);
err = journal_destroy(sbi->s_journal);
sbi->s_journal = NULL;
@@ -447,7 +448,8 @@ static void ext3_put_super (struct super_block * sb)
sb->s_fs_info = NULL;
kfree(sbi->s_blockgroup_lock);
kfree(sbi);
- return;
+
+ unlock_kernel();
}
static struct kmem_cache *ext3_inode_cachep;
@@ -761,7 +763,6 @@ static const struct super_operations ext3_sops = {
.dirty_inode = ext3_dirty_inode,
.delete_inode = ext3_delete_inode,
.put_super = ext3_put_super,
- .write_super = ext3_write_super,
.sync_fs = ext3_sync_fs,
.freeze_fs = ext3_freeze,
.unfreeze_fs = ext3_unfreeze,
@@ -1785,7 +1786,6 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
#else
es->s_flags |= cpu_to_le32(EXT2_FLAGS_SIGNED_HASH);
#endif
- sb->s_dirt = 1;
}
if (sbi->s_blocks_per_group > blocksize * 8) {
@@ -2264,7 +2264,6 @@ static int ext3_load_journal(struct super_block *sb,
if (journal_devnum &&
journal_devnum != le32_to_cpu(es->s_journal_dev)) {
es->s_journal_dev = cpu_to_le32(journal_devnum);
- sb->s_dirt = 1;
/* Make sure we flush the recovery flag to disk. */
ext3_commit_super(sb, es, 1);
@@ -2307,7 +2306,6 @@ static int ext3_create_journal(struct super_block * sb,
EXT3_SET_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL);
es->s_journal_inum = cpu_to_le32(journal_inum);
- sb->s_dirt = 1;
/* Make sure we flush the recovery flag to disk. */
ext3_commit_super(sb, es, 1);
@@ -2353,7 +2351,6 @@ static void ext3_mark_recovery_complete(struct super_block * sb,
if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER) &&
sb->s_flags & MS_RDONLY) {
EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
- sb->s_dirt = 0;
ext3_commit_super(sb, es, 1);
}
unlock_super(sb);
@@ -2412,29 +2409,14 @@ int ext3_force_commit(struct super_block *sb)
return 0;
journal = EXT3_SB(sb)->s_journal;
- sb->s_dirt = 0;
ret = ext3_journal_force_commit(journal);
return ret;
}
-/*
- * Ext3 always journals updates to the superblock itself, so we don't
- * have to propagate any other updates to the superblock on disk at this
- * point. (We can probably nuke this function altogether, and remove
- * any mention to sb->s_dirt in all of fs/ext3; eventual cleanup...)
- */
-static void ext3_write_super (struct super_block * sb)
-{
- if (mutex_trylock(&sb->s_lock) != 0)
- BUG();
- sb->s_dirt = 0;
-}
-
static int ext3_sync_fs(struct super_block *sb, int wait)
{
tid_t target;
- sb->s_dirt = 0;
if (journal_start_commit(EXT3_SB(sb)->s_journal, &target)) {
if (wait)
log_wait_commit(EXT3_SB(sb)->s_journal, target);
@@ -2450,7 +2432,6 @@ static int ext3_freeze(struct super_block *sb)
{
int error = 0;
journal_t *journal;
- sb->s_dirt = 0;
if (!(sb->s_flags & MS_RDONLY)) {
journal = EXT3_SB(sb)->s_journal;
@@ -2509,6 +2490,7 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
#endif
/* Store the original options */
+ lock_super(sb);
old_sb_flags = sb->s_flags;
old_opts.s_mount_opt = sbi->s_mount_opt;
old_opts.s_resuid = sbi->s_resuid;
@@ -2616,6 +2598,7 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
old_opts.s_qf_names[i] != sbi->s_qf_names[i])
kfree(old_opts.s_qf_names[i]);
#endif
+ unlock_super(sb);
return 0;
restore_opts:
sb->s_flags = old_sb_flags;
@@ -2632,6 +2615,7 @@ restore_opts:
sbi->s_qf_names[i] = old_opts.s_qf_names[i];
}
#endif
+ unlock_super(sb);
return err;
}
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 83b7be849bd5..545e37c4b91e 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -463,7 +463,6 @@ static void ext3_xattr_update_super_block(handle_t *handle,
if (ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh) == 0) {
EXT3_SET_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR);
- sb->s_dirt = 1;
ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
}
}
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
index 647e0d65a284..605aeed96d68 100644
--- a/fs/ext4/acl.c
+++ b/fs/ext4/acl.c
@@ -129,12 +129,15 @@ fail:
static inline struct posix_acl *
ext4_iget_acl(struct inode *inode, struct posix_acl **i_acl)
{
- struct posix_acl *acl = EXT4_ACL_NOT_CACHED;
+ struct posix_acl *acl = ACCESS_ONCE(*i_acl);
- spin_lock(&inode->i_lock);
- if (*i_acl != EXT4_ACL_NOT_CACHED)
- acl = posix_acl_dup(*i_acl);
- spin_unlock(&inode->i_lock);
+ if (acl) {
+ spin_lock(&inode->i_lock);
+ acl = *i_acl;
+ if (acl != EXT4_ACL_NOT_CACHED)
+ acl = posix_acl_dup(acl);
+ spin_unlock(&inode->i_lock);
+ }
return acl;
}
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 53c72ad85877..e2126d70dff5 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -19,7 +19,6 @@
#include <linux/buffer_head.h>
#include "ext4.h"
#include "ext4_jbd2.h"
-#include "group.h"
#include "mballoc.h"
/*
@@ -88,6 +87,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
ext4_group_t block_group, struct ext4_group_desc *gdp)
{
int bit, bit_max;
+ ext4_group_t ngroups = ext4_get_groups_count(sb);
unsigned free_blocks, group_blocks;
struct ext4_sb_info *sbi = EXT4_SB(sb);
@@ -123,7 +123,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
bit_max += ext4_bg_num_gdb(sb, block_group);
}
- if (block_group == sbi->s_groups_count - 1) {
+ if (block_group == ngroups - 1) {
/*
* Even though mke2fs always initialize first and last group
* if some other tool enabled the EXT4_BG_BLOCK_UNINIT we need
@@ -131,7 +131,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
*/
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));
+ (EXT4_BLOCKS_PER_GROUP(sb) * (ngroups - 1));
} else {
group_blocks = EXT4_BLOCKS_PER_GROUP(sb);
}
@@ -205,18 +205,18 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
{
unsigned int group_desc;
unsigned int offset;
+ ext4_group_t ngroups = ext4_get_groups_count(sb);
struct ext4_group_desc *desc;
struct ext4_sb_info *sbi = EXT4_SB(sb);
- if (block_group >= sbi->s_groups_count) {
+ if (block_group >= ngroups) {
ext4_error(sb, "ext4_get_group_desc",
"block_group >= groups_count - "
"block_group = %u, groups_count = %u",
- block_group, sbi->s_groups_count);
+ block_group, ngroups);
return NULL;
}
- smp_rmb();
group_desc = block_group >> EXT4_DESC_PER_BLOCK_BITS(sb);
offset = block_group & (EXT4_DESC_PER_BLOCK(sb) - 1);
@@ -326,16 +326,16 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
unlock_buffer(bh);
return bh;
}
- spin_lock(sb_bgl_lock(EXT4_SB(sb), block_group));
+ ext4_lock_group(sb, block_group);
if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
ext4_init_block_bitmap(sb, bh, block_group, desc);
set_bitmap_uptodate(bh);
set_buffer_uptodate(bh);
- spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group));
+ ext4_unlock_group(sb, block_group);
unlock_buffer(bh);
return bh;
}
- spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group));
+ ext4_unlock_group(sb, block_group);
if (buffer_uptodate(bh)) {
/*
* if not uninit if bh is uptodate,
@@ -451,7 +451,7 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
down_write(&grp->alloc_sem);
for (i = 0, blocks_freed = 0; i < count; i++) {
BUFFER_TRACE(bitmap_bh, "clear bit");
- if (!ext4_clear_bit_atomic(sb_bgl_lock(sbi, block_group),
+ if (!ext4_clear_bit_atomic(ext4_group_lock_ptr(sb, block_group),
bit + i, bitmap_bh->b_data)) {
ext4_error(sb, __func__,
"bit already cleared for block %llu",
@@ -461,11 +461,11 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
blocks_freed++;
}
}
- spin_lock(sb_bgl_lock(sbi, block_group));
+ ext4_lock_group(sb, block_group);
blk_free_count = blocks_freed + ext4_free_blks_count(sb, desc);
ext4_free_blks_set(sb, desc, blk_free_count);
desc->bg_checksum = ext4_group_desc_csum(sbi, block_group, desc);
- spin_unlock(sb_bgl_lock(sbi, block_group));
+ ext4_unlock_group(sb, block_group);
percpu_counter_add(&sbi->s_freeblocks_counter, blocks_freed);
if (sbi->s_log_groups_per_flex) {
@@ -665,7 +665,7 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
ext4_fsblk_t desc_count;
struct ext4_group_desc *gdp;
ext4_group_t i;
- ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count;
+ ext4_group_t ngroups = ext4_get_groups_count(sb);
#ifdef EXT4FS_DEBUG
struct ext4_super_block *es;
ext4_fsblk_t bitmap_count;
@@ -677,7 +677,6 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
bitmap_count = 0;
gdp = NULL;
- smp_rmb();
for (i = 0; i < ngroups; i++) {
gdp = ext4_get_group_desc(sb, i, NULL);
if (!gdp)
@@ -700,7 +699,6 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
return bitmap_count;
#else
desc_count = 0;
- smp_rmb();
for (i = 0; i < ngroups; i++) {
gdp = ext4_get_group_desc(sb, i, NULL);
if (!gdp)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index d0f15ef56de1..149e02dc3606 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -21,7 +21,14 @@
#include <linux/magic.h>
#include <linux/jbd2.h>
#include <linux/quota.h>
-#include "ext4_i.h"
+#include <linux/rwsem.h>
+#include <linux/rbtree.h>
+#include <linux/seqlock.h>
+#include <linux/mutex.h>
+#include <linux/timer.h>
+#include <linux/wait.h>
+#include <linux/blockgroup_lock.h>
+#include <linux/percpu_counter.h>
/*
* The fourth extended filesystem constants/structures
@@ -46,6 +53,19 @@
#define ext4_debug(f, a...) do {} while (0)
#endif
+/* data type for block offset of block group */
+typedef int ext4_grpblk_t;
+
+/* data type for filesystem-wide blocks number */
+typedef unsigned long long ext4_fsblk_t;
+
+/* data type for file logical block number */
+typedef __u32 ext4_lblk_t;
+
+/* data type for block group number */
+typedef unsigned int ext4_group_t;
+
+
/* prefer goal again. length */
#define EXT4_MB_HINT_MERGE 1
/* blocks already reserved */
@@ -179,9 +199,6 @@ struct flex_groups {
#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 "ext4_sb.h"
-#endif
/*
* Macro-instructions used to manage group descriptors
*/
@@ -516,6 +533,110 @@ do { \
#endif /* defined(__KERNEL__) || defined(__linux__) */
/*
+ * storage for cached extent
+ */
+struct ext4_ext_cache {
+ ext4_fsblk_t ec_start;
+ ext4_lblk_t ec_block;
+ __u32 ec_len; /* must be 32bit to return holes */
+ __u32 ec_type;
+};
+
+/*
+ * fourth extended file system inode data in memory
+ */
+struct ext4_inode_info {
+ __le32 i_data[15]; /* unconverted */
+ __u32 i_flags;
+ ext4_fsblk_t i_file_acl;
+ __u32 i_dtime;
+
+ /*
+ * i_block_group is the number of the block group which contains
+ * this file's inode. Constant across the lifetime of the inode,
+ * it is ued for making block allocation decisions - we try to
+ * place a file's data blocks near its inode block, and new inodes
+ * near to their parent directory's inode.
+ */
+ ext4_group_t i_block_group;
+ __u32 i_state; /* Dynamic state flags for ext4 */
+
+ ext4_lblk_t i_dir_start_lookup;
+#ifdef CONFIG_EXT4_FS_XATTR
+ /*
+ * Extended attributes can be read independently of the main file
+ * data. Taking i_mutex even when reading would cause contention
+ * between readers of EAs and writers of regular file data, so
+ * instead we synchronize on xattr_sem when reading or changing
+ * EAs.
+ */
+ struct rw_semaphore xattr_sem;
+#endif
+#ifdef CONFIG_EXT4_FS_POSIX_ACL
+ struct posix_acl *i_acl;
+ struct posix_acl *i_default_acl;
+#endif
+
+ struct list_head i_orphan; /* unlinked but open inodes */
+
+ /*
+ * i_disksize keeps track of what the inode size is ON DISK, not
+ * in memory. During truncate, i_size is set to the new size by
+ * the VFS prior to calling ext4_truncate(), but the filesystem won't
+ * set i_disksize to 0 until the truncate is actually under way.
+ *
+ * The intent is that i_disksize always represents the blocks which
+ * are used by this file. This allows recovery to restart truncate
+ * on orphans if we crash during truncate. We actually write i_disksize
+ * into the on-disk inode when writing inodes out, instead of i_size.
+ *
+ * The only time when i_disksize and i_size may be different is when
+ * a truncate is in progress. The only things which change i_disksize
+ * are ext4_get_block (growth) and ext4_truncate (shrinkth).
+ */
+ loff_t i_disksize;
+
+ /*
+ * i_data_sem is for serialising ext4_truncate() against
+ * ext4_getblock(). In the 2.4 ext2 design, great chunks of inode's
+ * data tree are chopped off during truncate. We can't do that in
+ * ext4 because whenever we perform intermediate commits during
+ * truncate, the inode and all the metadata blocks *must* be in a
+ * consistent state which allows truncation of the orphans to restart
+ * during recovery. Hence we must fix the get_block-vs-truncate race
+ * by other means, so we have i_data_sem.
+ */
+ struct rw_semaphore i_data_sem;
+ struct inode vfs_inode;
+ struct jbd2_inode jinode;
+
+ struct ext4_ext_cache i_cached_extent;
+ /*
+ * File creation time. Its function is same as that of
+ * struct timespec i_{a,c,m}time in the generic inode.
+ */
+ struct timespec i_crtime;
+
+ /* mballoc */
+ struct list_head i_prealloc_list;
+ spinlock_t i_prealloc_lock;
+
+ /* ialloc */
+ ext4_group_t i_last_alloc_group;
+
+ /* allocation reservation info for delalloc */
+ unsigned int i_reserved_data_blocks;
+ unsigned int i_reserved_meta_blocks;
+ unsigned int i_allocated_meta_blocks;
+ unsigned short i_delalloc_reserved_flag;
+
+ /* on-disk additional length */
+ __u16 i_extra_isize;
+
+ spinlock_t i_block_reservation_lock;
+};
+
+/*
* File system states
*/
#define EXT4_VALID_FS 0x0001 /* Unmounted cleanly */
@@ -689,6 +810,136 @@ struct ext4_super_block {
};
#ifdef __KERNEL__
+/*
+ * fourth extended-fs super-block data in memory
+ */
+struct ext4_sb_info {
+ unsigned long s_desc_size; /* Size of a group descriptor in bytes */
+ unsigned long s_inodes_per_block;/* Number of inodes per block */
+ 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 */
+ unsigned long s_gdb_count; /* Number of group descriptor blocks */
+ unsigned long s_desc_per_block; /* Number of group descriptors per block */
+ ext4_group_t s_groups_count; /* Number of groups in the fs */
+ unsigned long s_overhead_last; /* Last calculated overhead */
+ unsigned long s_blocks_last; /* Last seen block count */
+ loff_t s_bitmap_maxbytes; /* max bytes for bitmap files */
+ struct buffer_head * s_sbh; /* Buffer containing the super block */
+ 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;
+ unsigned short s_pad;
+ int s_addr_per_block_bits;
+ int s_desc_per_block_bits;
+ int s_inode_size;
+ int s_first_ino;
+ unsigned int s_inode_readahead_blks;
+ spinlock_t s_next_gen_lock;
+ u32 s_next_generation;
+ u32 s_hash_seed[4];
+ int s_def_hash_version;
+ int s_hash_unsigned; /* 3 if hash should be signed, 0 if not */
+ struct percpu_counter s_freeblocks_counter;
+ struct percpu_counter s_freeinodes_counter;
+ struct percpu_counter s_dirs_counter;
+ struct percpu_counter s_dirtyblocks_counter;
+ struct blockgroup_lock *s_blockgroup_lock;
+ struct proc_dir_entry *s_proc;
+ struct kobject s_kobj;
+ struct completion s_kobj_unregister;
+
+ /* Journaling */
+ struct inode *s_journal_inode;
+ struct journal_s *s_journal;
+ struct list_head s_orphan;
+ struct mutex s_orphan_lock;
+ struct mutex s_resize_lock;
+ unsigned long s_commit_interval;
+ u32 s_max_batch_time;
+ u32 s_min_batch_time;
+ struct block_device *journal_bdev;
+#ifdef CONFIG_JBD2_DEBUG
+ struct timer_list turn_ro_timer; /* For turning read-only (crash simulation) */
+ wait_queue_head_t ro_wait_queue; /* For people waiting for the fs to go read-only */
+#endif
+#ifdef CONFIG_QUOTA
+ char *s_qf_names[MAXQUOTAS]; /* Names of quota files with journalled quota */
+ int s_jquota_fmt; /* Format of quota to use */
+#endif
+ unsigned int s_want_extra_isize; /* New inodes should reserve # bytes */
+
+#ifdef EXTENTS_STATS
+ /* ext4 extents stats */
+ unsigned long s_ext_min;
+ unsigned long s_ext_max;
+ unsigned long s_depth_max;
+ spinlock_t s_ext_stats_lock;
+ unsigned long s_ext_blocks;
+ unsigned long s_ext_extents;
+#endif
+
+ /* for buddy allocator */
+ struct ext4_group_info ***s_group_info;
+ struct inode *s_buddy_cache;
+ long s_blocks_reserved;
+ spinlock_t s_reserve_lock;
+ spinlock_t s_md_lock;
+ tid_t s_last_transaction;
+ unsigned short *s_mb_offsets;
+ unsigned int *s_mb_maxs;
+
+ /* tunables */
+ unsigned long s_stripe;
+ unsigned int s_mb_stream_request;
+ unsigned int s_mb_max_to_scan;
+ unsigned int s_mb_min_to_scan;
+ unsigned int s_mb_stats;
+ unsigned int s_mb_order2_reqs;
+ unsigned int s_mb_group_prealloc;
+ /* where last allocation was done - for stream allocation */
+ unsigned long s_mb_last_group;
+ unsigned long s_mb_last_start;
+
+ /* history to debug policy */
+ struct ext4_mb_history *s_mb_history;
+ int s_mb_history_cur;
+ int s_mb_history_max;
+ int s_mb_history_num;
+ spinlock_t s_mb_history_lock;
+ int s_mb_history_filter;
+
+ /* stats for buddy allocator */
+ spinlock_t s_mb_pa_lock;
+ atomic_t s_bal_reqs; /* number of reqs with len > 1 */
+ atomic_t s_bal_success; /* we found long enough chunks */
+ atomic_t s_bal_allocated; /* in blocks */
+ atomic_t s_bal_ex_scanned; /* total extents scanned */
+ atomic_t s_bal_goals; /* goal hits */
+ atomic_t s_bal_breaks; /* too long searches */
+ atomic_t s_bal_2orders; /* 2^order hits */
+ spinlock_t s_bal_lock;
+ unsigned long s_mb_buddies_generated;
+ unsigned long long s_mb_generation_time;
+ atomic_t s_mb_lost_chunks;
+ atomic_t s_mb_preallocated;
+ atomic_t s_mb_discarded;
+
+ /* locality groups */
+ struct ext4_locality_group *s_locality_groups;
+
+ /* for write statistics */
+ unsigned long s_sectors_written_start;
+ u64 s_kbytes_written;
+
+ unsigned int s_log_groups_per_flex;
+ struct flex_groups *s_flex_groups;
+};
+
static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb)
{
return sb->s_fs_info;
@@ -704,7 +955,6 @@ static inline struct timespec ext4_current_time(struct inode *inode)
current_fs_time(inode->i_sb) : CURRENT_TIME_SEC;
}
-
static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
{
return ino == EXT4_ROOT_INO ||
@@ -1014,6 +1264,14 @@ extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
ext4_group_t block_group,
struct buffer_head ** bh);
extern int ext4_should_retry_alloc(struct super_block *sb, int *retries);
+struct buffer_head *ext4_read_block_bitmap(struct super_block *sb,
+ ext4_group_t block_group);
+extern unsigned ext4_init_block_bitmap(struct super_block *sb,
+ struct buffer_head *bh,
+ ext4_group_t group,
+ struct ext4_group_desc *desc);
+#define ext4_free_blocks_after_init(sb, group, desc) \
+ ext4_init_block_bitmap(sb, NULL, group, desc)
/* dir.c */
extern int ext4_check_dir_entry(const char *, struct inode *,
@@ -1038,6 +1296,11 @@ extern struct inode * ext4_orphan_get(struct super_block *, unsigned long);
extern unsigned long ext4_count_free_inodes(struct super_block *);
extern unsigned long ext4_count_dirs(struct super_block *);
extern void ext4_check_inodes_bitmap(struct super_block *);
+extern unsigned ext4_init_inode_bitmap(struct super_block *sb,
+ struct buffer_head *bh,
+ ext4_group_t group,
+ struct ext4_group_desc *desc);
+extern void mark_bitmap_end(int start_bit, int end_bit, char *bitmap);
/* mballoc.c */
extern long ext4_mb_stats;
@@ -1161,6 +1424,10 @@ extern void ext4_used_dirs_set(struct super_block *sb,
struct ext4_group_desc *bg, __u32 count);
extern void ext4_itable_unused_set(struct super_block *sb,
struct ext4_group_desc *bg, __u32 count);
+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);
static inline ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es)
{
@@ -1228,6 +1495,18 @@ struct ext4_group_info *ext4_get_group_info(struct super_block *sb,
return grp_info[indexv][indexh];
}
+/*
+ * Reading s_groups_count requires using smp_rmb() afterwards. See
+ * the locking protocol documented in the comments of ext4_group_add()
+ * in resize.c
+ */
+static inline ext4_group_t ext4_get_groups_count(struct super_block *sb)
+{
+ ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count;
+
+ smp_rmb();
+ return ngroups;
+}
static inline ext4_group_t ext4_flex_group(struct ext4_sb_info *sbi,
ext4_group_t block_group)
@@ -1283,33 +1562,31 @@ struct ext4_group_info {
};
#define EXT4_GROUP_INFO_NEED_INIT_BIT 0
-#define EXT4_GROUP_INFO_LOCKED_BIT 1
#define EXT4_MB_GRP_NEED_INIT(grp) \
(test_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &((grp)->bb_state)))
-static inline void ext4_lock_group(struct super_block *sb, ext4_group_t group)
+static inline spinlock_t *ext4_group_lock_ptr(struct super_block *sb,
+ ext4_group_t group)
{
- struct ext4_group_info *grinfo = ext4_get_group_info(sb, group);
+ return bgl_lock_ptr(EXT4_SB(sb)->s_blockgroup_lock, group);
+}
- bit_spin_lock(EXT4_GROUP_INFO_LOCKED_BIT, &(grinfo->bb_state));
+static inline void ext4_lock_group(struct super_block *sb, ext4_group_t group)
+{
+ spin_lock(ext4_group_lock_ptr(sb, group));
}
static inline void ext4_unlock_group(struct super_block *sb,
ext4_group_t group)
{
- struct ext4_group_info *grinfo = ext4_get_group_info(sb, group);
-
- bit_spin_unlock(EXT4_GROUP_INFO_LOCKED_BIT, &(grinfo->bb_state));
+ spin_unlock(ext4_group_lock_ptr(sb, group));
}
static inline int ext4_is_group_locked(struct super_block *sb,
ext4_group_t group)
{
- struct ext4_group_info *grinfo = ext4_get_group_info(sb, group);
-
- return bit_spin_is_locked(EXT4_GROUP_INFO_LOCKED_BIT,
- &(grinfo->bb_state));
+ return spin_is_locked(ext4_group_lock_ptr(sb, group));
}
/*
@@ -1326,6 +1603,7 @@ extern const struct file_operations ext4_file_operations;
/* namei.c */
extern const struct inode_operations ext4_dir_inode_operations;
extern const struct inode_operations ext4_special_inode_operations;
+extern struct dentry *ext4_get_parent(struct dentry *child);
/* symlink.c */
extern const struct inode_operations ext4_symlink_inode_operations;
diff --git a/fs/ext4/ext4_i.h b/fs/ext4/ext4_i.h
deleted file mode 100644
index 4ce2187123aa..000000000000
--- a/fs/ext4/ext4_i.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * ext4_i.h
- *
- * Copyright (C) 1992, 1993, 1994, 1995
- * Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * from
- *
- * linux/include/linux/minix_fs_i.h
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- */
-
-#ifndef _EXT4_I
-#define _EXT4_I
-
-#include <linux/rwsem.h>
-#include <linux/rbtree.h>
-#include <linux/seqlock.h>
-#include <linux/mutex.h>
-
-/* data type for block offset of block group */
-typedef int ext4_grpblk_t;
-
-/* data type for filesystem-wide blocks number */
-typedef unsigned long long ext4_fsblk_t;
-
-/* data type for file logical block number */
-typedef __u32 ext4_lblk_t;
-
-/* data type for block group number */
-typedef unsigned int ext4_group_t;
-
-/*
- * storage for cached extent
- */
-struct ext4_ext_cache {
- ext4_fsblk_t ec_start;
- ext4_lblk_t ec_block;
- __u32 ec_len; /* must be 32bit to return holes */
- __u32 ec_type;
-};
-
-/*
- * fourth extended file system inode data in memory
- */
-struct ext4_inode_info {
- __le32 i_data[15]; /* unconverted */
- __u32 i_flags;
- ext4_fsblk_t i_file_acl;
- __u32 i_dtime;
-
- /*
- * i_block_group is the number of the block group which contains
- * this file's inode. Constant across the lifetime of the inode,
- * it is ued for making block allocation decisions - we try to
- * place a file's data blocks near its inode block, and new inodes
- * near to their parent directory's inode.
- */
- ext4_group_t i_block_group;
- __u32 i_state; /* Dynamic state flags for ext4 */
-
- ext4_lblk_t i_dir_start_lookup;
-#ifdef CONFIG_EXT4_FS_XATTR
- /*
- * Extended attributes can be read independently of the main file
- * data. Taking i_mutex even when reading would cause contention
- * between readers of EAs and writers of regular file data, so
- * instead we synchronize on xattr_sem when reading or changing
- * EAs.
- */
- struct rw_semaphore xattr_sem;
-#endif
-#ifdef CONFIG_EXT4_FS_POSIX_ACL
- struct posix_acl *i_acl;
- struct posix_acl *i_default_acl;
-#endif
-
- struct list_head i_orphan; /* unlinked but open inodes */
-
- /*
- * i_disksize keeps track of what the inode size is ON DISK, not
- * in memory. During truncate, i_size is set to the new size by
- * the VFS prior to calling ext4_truncate(), but the filesystem won't
- * set i_disksize to 0 until the truncate is actually under way.
- *
- * The intent is that i_disksize always represents the blocks which
- * are used by this file. This allows recovery to restart truncate
- * on orphans if we crash during truncate. We actually write i_disksize
- * into the on-disk inode when writing inodes out, instead of i_size.
- *
- * The only time when i_disksize and i_size may be different is when
- * a truncate is in progress. The only things which change i_disksize
- * are ext4_get_block (growth) and ext4_truncate (shrinkth).
- */
- loff_t i_disksize;
-
- /*
- * i_data_sem is for serialising ext4_truncate() against
- * ext4_getblock(). In the 2.4 ext2 design, great chunks of inode's
- * data tree are chopped off during truncate. We can't do that in
- * ext4 because whenever we perform intermediate commits during
- * truncate, the inode and all the metadata blocks *must* be in a
- * consistent state which allows truncation of the orphans to restart
- * during recovery. Hence we must fix the get_block-vs-truncate race
- * by other means, so we have i_data_sem.
- */
- struct rw_semaphore i_data_sem;
- struct inode vfs_inode;
- struct jbd2_inode jinode;
-
- struct ext4_ext_cache i_cached_extent;
- /*
- * File creation time. Its function is same as that of
- * struct timespec i_{a,c,m}time in the generic inode.
- */
- struct timespec i_crtime;
-
- /* mballoc */
- struct list_head i_prealloc_list;
- spinlock_t i_prealloc_lock;
-
- /* ialloc */
- ext4_group_t i_last_alloc_group;
-
- /* allocation reservation info for delalloc */
- unsigned int i_reserved_data_blocks;
- unsigned int i_reserved_meta_blocks;
- unsigned int i_allocated_meta_blocks;
- unsigned short i_delalloc_reserved_flag;
-
- /* on-disk additional length */
- __u16 i_extra_isize;
-
- spinlock_t i_block_reservation_lock;
-};
-
-#endif /* _EXT4_I */
diff --git a/fs/ext4/ext4_sb.h b/fs/ext4/ext4_sb.h
deleted file mode 100644
index 57b71fefbccf..000000000000
--- a/fs/ext4/ext4_sb.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * ext4_sb.h
- *
- * Copyright (C) 1992, 1993, 1994, 1995
- * Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * from
- *
- * linux/include/linux/minix_fs_sb.h
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- */
-
-#ifndef _EXT4_SB
-#define _EXT4_SB
-
-#ifdef __KERNEL__
-#include <linux/timer.h>
-#include <linux/wait.h>
-#include <linux/blockgroup_lock.h>
-#include <linux/percpu_counter.h>
-#endif
-#include <linux/rbtree.h>
-
-/*
- * fourth extended-fs super-block data in memory
- */
-struct ext4_sb_info {
- unsigned long s_desc_size; /* Size of a group descriptor in bytes */
- unsigned long s_inodes_per_block;/* Number of inodes per block */
- 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 */
- unsigned long s_gdb_count; /* Number of group descriptor blocks */
- unsigned long s_desc_per_block; /* Number of group descriptors per block */
- ext4_group_t s_groups_count; /* Number of groups in the fs */
- unsigned long s_overhead_last; /* Last calculated overhead */
- unsigned long s_blocks_last; /* Last seen block count */
- loff_t s_bitmap_maxbytes; /* max bytes for bitmap files */
- struct buffer_head * s_sbh; /* Buffer containing the super block */
- 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;
- unsigned short s_pad;
- int s_addr_per_block_bits;
- int s_desc_per_block_bits;
- int s_inode_size;
- int s_first_ino;
- unsigned int s_inode_readahead_blks;
- spinlock_t s_next_gen_lock;
- u32 s_next_generation;
- u32 s_hash_seed[4];
- int s_def_hash_version;
- int s_hash_unsigned; /* 3 if hash should be signed, 0 if not */
- struct percpu_counter s_freeblocks_counter;
- struct percpu_counter s_freeinodes_counter;
- struct percpu_counter s_dirs_counter;
- struct percpu_counter s_dirtyblocks_counter;
- struct blockgroup_lock *s_blockgroup_lock;
- struct proc_dir_entry *s_proc;
- struct kobject s_kobj;
- struct completion s_kobj_unregister;
-
- /* Journaling */
- struct inode *s_journal_inode;
- struct journal_s *s_journal;
- struct list_head s_orphan;
- unsigned long s_commit_interval;
- u32 s_max_batch_time;
- u32 s_min_batch_time;
- struct block_device *journal_bdev;
-#ifdef CONFIG_JBD2_DEBUG
- struct timer_list turn_ro_timer; /* For turning read-only (crash simulation) */
- wait_queue_head_t ro_wait_queue; /* For people waiting for the fs to go read-only */
-#endif
-#ifdef CONFIG_QUOTA
- char *s_qf_names[MAXQUOTAS]; /* Names of quota files with journalled quota */
- int s_jquota_fmt; /* Format of quota to use */
-#endif
- unsigned int s_want_extra_isize; /* New inodes should reserve # bytes */
-
-#ifdef EXTENTS_STATS
- /* ext4 extents stats */
- unsigned long s_ext_min;
- unsigned long s_ext_max;
- unsigned long s_depth_max;
- spinlock_t s_ext_stats_lock;
- unsigned long s_ext_blocks;
- unsigned long s_ext_extents;
-#endif
-
- /* for buddy allocator */
- struct ext4_group_info ***s_group_info;
- struct inode *s_buddy_cache;
- long s_blocks_reserved;
- spinlock_t s_reserve_lock;
- spinlock_t s_md_lock;
- tid_t s_last_transaction;
- unsigned short *s_mb_offsets;
- unsigned int *s_mb_maxs;
-
- /* tunables */
- unsigned long s_stripe;
- unsigned int s_mb_stream_request;
- unsigned int s_mb_max_to_scan;
- unsigned int s_mb_min_to_scan;
- unsigned int s_mb_stats;
- unsigned int s_mb_order2_reqs;
- unsigned int s_mb_group_prealloc;
- /* where last allocation was done - for stream allocation */
- unsigned long s_mb_last_group;
- unsigned long s_mb_last_start;
-
- /* history to debug policy */
- struct ext4_mb_history *s_mb_history;
- int s_mb_history_cur;
- int s_mb_history_max;
- int s_mb_history_num;
- spinlock_t s_mb_history_lock;
- int s_mb_history_filter;
-
- /* stats for buddy allocator */
- spinlock_t s_mb_pa_lock;
- atomic_t s_bal_reqs; /* number of reqs with len > 1 */
- atomic_t s_bal_success; /* we found long enough chunks */
- atomic_t s_bal_allocated; /* in blocks */
- atomic_t s_bal_ex_scanned; /* total extents scanned */
- atomic_t s_bal_goals; /* goal hits */
- atomic_t s_bal_breaks; /* too long searches */
- atomic_t s_bal_2orders; /* 2^order hits */
- spinlock_t s_bal_lock;
- unsigned long s_mb_buddies_generated;
- unsigned long long s_mb_generation_time;
- atomic_t s_mb_lost_chunks;
- atomic_t s_mb_preallocated;
- atomic_t s_mb_discarded;
-
- /* locality groups */
- struct ext4_locality_group *s_locality_groups;
-
- /* for write statistics */
- unsigned long s_sectors_written_start;
- u64 s_kbytes_written;
-
- unsigned int s_log_groups_per_flex;
- struct flex_groups *s_flex_groups;
-};
-
-static inline spinlock_t *
-sb_bgl_lock(struct ext4_sb_info *sbi, unsigned int block_group)
-{
- return bgl_lock_ptr(sbi->s_blockgroup_lock, block_group);
-}
-
-#endif /* _EXT4_SB */
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 6132353dcf62..e963870eac7a 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -326,11 +326,14 @@ ext4_ext_max_entries(struct inode *inode, int depth)
static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext)
{
- ext4_fsblk_t block = ext_pblock(ext);
+ ext4_fsblk_t block = ext_pblock(ext), valid_block;
int len = ext4_ext_get_actual_len(ext);
struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
- if (unlikely(block < le32_to_cpu(es->s_first_data_block) ||
- ((block + len) > ext4_blocks_count(es))))
+
+ valid_block = le32_to_cpu(es->s_first_data_block) +
+ EXT4_SB(inode->i_sb)->s_gdb_count;
+ if (unlikely(block <= valid_block ||
+ ((block + len) > ext4_blocks_count(es))))
return 0;
else
return 1;
@@ -339,10 +342,13 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext)
static int ext4_valid_extent_idx(struct inode *inode,
struct ext4_extent_idx *ext_idx)
{
- ext4_fsblk_t block = idx_pblock(ext_idx);
+ ext4_fsblk_t block = idx_pblock(ext_idx), valid_block;
struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
- if (unlikely(block < le32_to_cpu(es->s_first_data_block) ||
- (block >= ext4_blocks_count(es))))
+
+ valid_block = le32_to_cpu(es->s_first_data_block) +
+ EXT4_SB(inode->i_sb)->s_gdb_count;
+ if (unlikely(block <= valid_block ||
+ (block >= ext4_blocks_count(es))))
return 0;
else
return 1;
@@ -2416,8 +2422,6 @@ static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex)
len = ee_len;
bio = bio_alloc(GFP_NOIO, len);
- if (!bio)
- return -ENOMEM;
bio->bi_sector = ee_pblock;
bio->bi_bdev = inode->i_sb->s_bdev;
@@ -3182,7 +3186,7 @@ static int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path,
void *data)
{
struct fiemap_extent_info *fieinfo = data;
- unsigned long blksize_bits = inode->i_sb->s_blocksize_bits;
+ unsigned char blksize_bits = inode->i_sb->s_blocksize_bits;
__u64 logical;
__u64 physical;
__u64 length;
@@ -3229,9 +3233,16 @@ static int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path,
*
* XXX this might miss a single-block extent at EXT_MAX_BLOCK
*/
- if (logical + length - 1 == EXT_MAX_BLOCK ||
- ext4_ext_next_allocated_block(path) == EXT_MAX_BLOCK)
+ if (ext4_ext_next_allocated_block(path) == EXT_MAX_BLOCK ||
+ newex->ec_block + newex->ec_len - 1 == EXT_MAX_BLOCK) {
+ loff_t size = i_size_read(inode);
+ loff_t bs = EXT4_BLOCK_SIZE(inode->i_sb);
+
flags |= FIEMAP_EXTENT_LAST;
+ if ((flags & FIEMAP_EXTENT_DELALLOC) &&
+ logical+length > size)
+ length = (size - logical + bs - 1) & ~(bs-1);
+ }
error = fiemap_fill_next_extent(fieinfo, logical, physical,
length, flags);
diff --git a/fs/ext4/group.h b/fs/ext4/group.h
deleted file mode 100644
index c2c0a8d06d0e..000000000000
--- a/fs/ext4/group.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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 *ext4_read_block_bitmap(struct super_block *sb,
- ext4_group_t block_group);
-extern unsigned ext4_init_block_bitmap(struct super_block *sb,
- struct buffer_head *bh,
- ext4_group_t 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,
- ext4_group_t 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 47b84e8df568..82f7d1d7eae0 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -27,7 +27,6 @@
#include "ext4_jbd2.h"
#include "xattr.h"
#include "acl.h"
-#include "group.h"
/*
* ialloc.c contains the inodes allocation and deallocation routines
@@ -123,16 +122,16 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
unlock_buffer(bh);
return bh;
}
- spin_lock(sb_bgl_lock(EXT4_SB(sb), block_group));
+ ext4_lock_group(sb, block_group);
if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
ext4_init_inode_bitmap(sb, bh, block_group, desc);
set_bitmap_uptodate(bh);
set_buffer_uptodate(bh);
- spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group));
+ ext4_unlock_group(sb, block_group);
unlock_buffer(bh);
return bh;
}
- spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group));
+ ext4_unlock_group(sb, block_group);
if (buffer_uptodate(bh)) {
/*
* if not uninit if bh is uptodate,
@@ -247,9 +246,8 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
goto error_return;
/* Ok, now we can actually update the inode bitmaps.. */
- spin_lock(sb_bgl_lock(sbi, block_group));
- cleared = ext4_clear_bit(bit, bitmap_bh->b_data);
- spin_unlock(sb_bgl_lock(sbi, block_group));
+ cleared = ext4_clear_bit_atomic(ext4_group_lock_ptr(sb, block_group),
+ bit, bitmap_bh->b_data);
if (!cleared)
ext4_error(sb, "ext4_free_inode",
"bit already cleared for inode %lu", ino);
@@ -261,7 +259,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
if (fatal) goto error_return;
if (gdp) {
- spin_lock(sb_bgl_lock(sbi, block_group));
+ ext4_lock_group(sb, block_group);
count = ext4_free_inodes_count(sb, gdp) + 1;
ext4_free_inodes_set(sb, gdp, count);
if (is_directory) {
@@ -277,7 +275,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
}
gdp->bg_checksum = ext4_group_desc_csum(sbi,
block_group, gdp);
- spin_unlock(sb_bgl_lock(sbi, block_group));
+ ext4_unlock_group(sb, block_group);
percpu_counter_inc(&sbi->s_freeinodes_counter);
if (is_directory)
percpu_counter_dec(&sbi->s_dirs_counter);
@@ -316,7 +314,7 @@ error_return:
static int find_group_dir(struct super_block *sb, struct inode *parent,
ext4_group_t *best_group)
{
- ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count;
+ ext4_group_t ngroups = ext4_get_groups_count(sb);
unsigned int freei, avefreei;
struct ext4_group_desc *desc, *best_desc = NULL;
ext4_group_t group;
@@ -353,7 +351,7 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,
struct flex_groups *flex_group = sbi->s_flex_groups;
ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
ext4_group_t parent_fbg_group = ext4_flex_group(sbi, parent_group);
- ext4_group_t ngroups = sbi->s_groups_count;
+ ext4_group_t ngroups = ext4_get_groups_count(sb);
int flex_size = ext4_flex_bg_size(sbi);
ext4_group_t best_flex = parent_fbg_group;
int blocks_per_flex = sbi->s_blocks_per_group * flex_size;
@@ -362,7 +360,7 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,
ext4_group_t n_fbg_groups;
ext4_group_t i;
- n_fbg_groups = (sbi->s_groups_count + flex_size - 1) >>
+ n_fbg_groups = (ngroups + flex_size - 1) >>
sbi->s_log_groups_per_flex;
find_close_to_parent:
@@ -478,20 +476,21 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
{
ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
struct ext4_sb_info *sbi = EXT4_SB(sb);
- ext4_group_t ngroups = sbi->s_groups_count;
+ ext4_group_t real_ngroups = ext4_get_groups_count(sb);
int inodes_per_group = EXT4_INODES_PER_GROUP(sb);
unsigned int freei, avefreei;
ext4_fsblk_t freeb, avefreeb;
unsigned int ndirs;
int max_dirs, min_inodes;
ext4_grpblk_t min_blocks;
- ext4_group_t i, grp, g;
+ ext4_group_t i, grp, g, ngroups;
struct ext4_group_desc *desc;
struct orlov_stats stats;
int flex_size = ext4_flex_bg_size(sbi);
+ ngroups = real_ngroups;
if (flex_size > 1) {
- ngroups = (ngroups + flex_size - 1) >>
+ ngroups = (real_ngroups + flex_size - 1) >>
sbi->s_log_groups_per_flex;
parent_group >>= sbi->s_log_groups_per_flex;
}
@@ -543,7 +542,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
*/
grp *= flex_size;
for (i = 0; i < flex_size; i++) {
- if (grp+i >= sbi->s_groups_count)
+ if (grp+i >= real_ngroups)
break;
desc = ext4_get_group_desc(sb, grp+i, NULL);
if (desc && ext4_free_inodes_count(sb, desc)) {
@@ -583,8 +582,9 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
}
fallback:
- ngroups = sbi->s_groups_count;
+ ngroups = real_ngroups;
avefreei = freei / ngroups;
+fallback_retry:
parent_group = EXT4_I(parent)->i_block_group;
for (i = 0; i < ngroups; i++) {
grp = (parent_group + i) % ngroups;
@@ -602,7 +602,7 @@ fallback:
* filesystems the above test can fail to find any blockgroups
*/
avefreei = 0;
- goto fallback;
+ goto fallback_retry;
}
return -1;
@@ -612,9 +612,8 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
ext4_group_t *group, int mode)
{
ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
- ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count;
+ ext4_group_t i, last, ngroups = ext4_get_groups_count(sb);
struct ext4_group_desc *desc;
- ext4_group_t i, last;
int flex_size = ext4_flex_bg_size(EXT4_SB(sb));
/*
@@ -707,10 +706,10 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
/*
* claim the inode from the inode bitmap. If the group
- * is uninit we need to take the groups's sb_bgl_lock
+ * is uninit we need to take the groups's ext4_group_lock
* and clear the uninit flag. The inode bitmap update
* and group desc uninit flag clear should be done
- * after holding sb_bgl_lock so that ext4_read_inode_bitmap
+ * after holding ext4_group_lock so that ext4_read_inode_bitmap
* doesn't race with the ext4_claim_inode
*/
static int ext4_claim_inode(struct super_block *sb,
@@ -721,7 +720,7 @@ static int ext4_claim_inode(struct super_block *sb,
struct ext4_sb_info *sbi = EXT4_SB(sb);
struct ext4_group_desc *gdp = ext4_get_group_desc(sb, group, NULL);
- spin_lock(sb_bgl_lock(sbi, group));
+ ext4_lock_group(sb, group);
if (ext4_set_bit(ino, inode_bitmap_bh->b_data)) {
/* not a free inode */
retval = 1;
@@ -730,7 +729,7 @@ static int ext4_claim_inode(struct super_block *sb,
ino++;
if ((group == 0 && ino < EXT4_FIRST_INO(sb)) ||
ino > EXT4_INODES_PER_GROUP(sb)) {
- spin_unlock(sb_bgl_lock(sbi, group));
+ ext4_unlock_group(sb, group);
ext4_error(sb, __func__,
"reserved inode or inode > inodes count - "
"block_group = %u, inode=%lu", group,
@@ -779,7 +778,7 @@ static int ext4_claim_inode(struct super_block *sb,
}
gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp);
err_ret:
- spin_unlock(sb_bgl_lock(sbi, group));
+ ext4_unlock_group(sb, group);
return retval;
}
@@ -798,11 +797,10 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
struct super_block *sb;
struct buffer_head *inode_bitmap_bh = NULL;
struct buffer_head *group_desc_bh;
- ext4_group_t group = 0;
+ ext4_group_t ngroups, group = 0;
unsigned long ino = 0;
struct inode *inode;
struct ext4_group_desc *gdp = NULL;
- struct ext4_super_block *es;
struct ext4_inode_info *ei;
struct ext4_sb_info *sbi;
int ret2, err = 0;
@@ -817,25 +815,25 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
return ERR_PTR(-EPERM);
sb = dir->i_sb;
+ ngroups = ext4_get_groups_count(sb);
trace_mark(ext4_request_inode, "dev %s dir %lu mode %d", sb->s_id,
dir->i_ino, mode);
inode = new_inode(sb);
if (!inode)
return ERR_PTR(-ENOMEM);
ei = EXT4_I(inode);
-
sbi = EXT4_SB(sb);
- es = sbi->s_es;
if (sbi->s_log_groups_per_flex && test_opt(sb, OLDALLOC)) {
ret2 = find_group_flex(sb, dir, &group);
if (ret2 == -1) {
ret2 = find_group_other(sb, dir, &group, mode);
- if (ret2 == 0 && once)
+ if (ret2 == 0 && once) {
once = 0;
printk(KERN_NOTICE "ext4: find_group_flex "
"failed, fallback succeeded dir %lu\n",
dir->i_ino);
+ }
}
goto got_group;
}
@@ -854,7 +852,7 @@ got_group:
if (ret2 == -1)
goto out;
- for (i = 0; i < sbi->s_groups_count; i++) {
+ for (i = 0; i < ngroups; i++) {
err = -EIO;
gdp = ext4_get_group_desc(sb, group, &group_desc_bh);
@@ -915,7 +913,7 @@ repeat_in_this_group:
* group descriptor metadata has not yet been updated.
* So we just go onto the next blockgroup.
*/
- if (++group == sbi->s_groups_count)
+ if (++group == ngroups)
group = 0;
}
err = -ENOSPC;
@@ -936,7 +934,7 @@ got:
}
free = 0;
- spin_lock(sb_bgl_lock(sbi, group));
+ ext4_lock_group(sb, group);
/* recheck and clear flag under lock if we still need to */
if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
free = ext4_free_blocks_after_init(sb, group, gdp);
@@ -945,7 +943,7 @@ got:
gdp->bg_checksum = ext4_group_desc_csum(sbi, group,
gdp);
}
- spin_unlock(sb_bgl_lock(sbi, group));
+ ext4_unlock_group(sb, group);
/* Don't need to dirty bitmap block if we didn't change it */
if (free) {
@@ -1156,7 +1154,7 @@ unsigned long ext4_count_free_inodes(struct super_block *sb)
{
unsigned long desc_count;
struct ext4_group_desc *gdp;
- ext4_group_t i;
+ ext4_group_t i, ngroups = ext4_get_groups_count(sb);
#ifdef EXT4FS_DEBUG
struct ext4_super_block *es;
unsigned long bitmap_count, x;
@@ -1166,7 +1164,7 @@ unsigned long ext4_count_free_inodes(struct super_block *sb)
desc_count = 0;
bitmap_count = 0;
gdp = NULL;
- for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) {
+ for (i = 0; i < ngroups; i++) {
gdp = ext4_get_group_desc(sb, i, NULL);
if (!gdp)
continue;
@@ -1188,7 +1186,7 @@ unsigned long ext4_count_free_inodes(struct super_block *sb)
return desc_count;
#else
desc_count = 0;
- for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) {
+ for (i = 0; i < ngroups; i++) {
gdp = ext4_get_group_desc(sb, i, NULL);
if (!gdp)
continue;
@@ -1203,9 +1201,9 @@ unsigned long ext4_count_free_inodes(struct super_block *sb)
unsigned long ext4_count_dirs(struct super_block * sb)
{
unsigned long count = 0;
- ext4_group_t i;
+ ext4_group_t i, ngroups = ext4_get_groups_count(sb);
- for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) {
+ for (i = 0; i < ngroups; i++) {
struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, NULL);
if (!gdp)
continue;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index c6bd6ced3bb7..3e90965683fc 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -2318,11 +2318,21 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
/* not enough space to reserve */
return ret;
- map_bh(bh_result, inode->i_sb, 0);
+ map_bh(bh_result, inode->i_sb, ~0);
set_buffer_new(bh_result);
set_buffer_delay(bh_result);
} else if (ret > 0) {
bh_result->b_size = (ret << inode->i_blkbits);
+ /*
+ * With sub-block writes into unwritten extents
+ * we also need to mark the buffer as new so that
+ * the unwritten parts of the buffer gets correctly zeroed.
+ */
+ if (buffer_unwritten(bh_result)) {
+ bh_result->b_bdev = inode->i_sb->s_bdev;
+ set_buffer_new(bh_result);
+ bh_result->b_blocknr = ~0;
+ }
ret = 0;
}
@@ -4357,11 +4367,9 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
ei->i_flags = le32_to_cpu(raw_inode->i_flags);
inode->i_blocks = ext4_inode_blocks(raw_inode, ei);
ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl_lo);
- if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
- cpu_to_le32(EXT4_OS_HURD)) {
+ if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_64BIT))
ei->i_file_acl |=
((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32;
- }
inode->i_size = ext4_isize(raw_inode);
ei->i_disksize = inode->i_size;
inode->i_generation = le32_to_cpu(raw_inode->i_generation);
@@ -4409,9 +4417,23 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
(__u64)(le32_to_cpu(raw_inode->i_version_hi)) << 32;
}
- if (ei->i_flags & EXT4_EXTENTS_FL) {
- /* Validate extent which is part of inode */
- ret = ext4_ext_check_inode(inode);
+ ret = 0;
+ if (ei->i_file_acl &&
+ ((ei->i_file_acl <
+ (le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) +
+ EXT4_SB(sb)->s_gdb_count)) ||
+ (ei->i_file_acl >= ext4_blocks_count(EXT4_SB(sb)->s_es)))) {
+ ext4_error(sb, __func__,
+ "bad extended attribute block %llu in inode #%lu",
+ ei->i_file_acl, inode->i_ino);
+ ret = -EIO;
+ goto bad_inode;
+ } else if (ei->i_flags & EXT4_EXTENTS_FL) {
+ if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+ (S_ISLNK(inode->i_mode) &&
+ !ext4_inode_is_fast_symlink(inode)))
+ /* Validate extent which is part of inode */
+ ret = ext4_ext_check_inode(inode);
} else if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
(S_ISLNK(inode->i_mode) &&
!ext4_inode_is_fast_symlink(inode))) {
@@ -4894,7 +4916,8 @@ static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
*/
int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk)
{
- int groups, gdpblocks;
+ ext4_group_t groups, ngroups = ext4_get_groups_count(inode->i_sb);
+ int gdpblocks;
int idxblocks;
int ret = 0;
@@ -4921,8 +4944,8 @@ int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk)
groups += nrblocks;
gdpblocks = groups;
- if (groups > EXT4_SB(inode->i_sb)->s_groups_count)
- groups = EXT4_SB(inode->i_sb)->s_groups_count;
+ if (groups > ngroups)
+ groups = ngroups;
if (groups > EXT4_SB(inode->i_sb)->s_gdb_count)
gdpblocks = EXT4_SB(inode->i_sb)->s_gdb_count;
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index f871677a7984..e76459cedcdb 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -372,24 +372,12 @@ static inline void mb_set_bit(int bit, void *addr)
ext4_set_bit(bit, addr);
}
-static inline void mb_set_bit_atomic(spinlock_t *lock, int bit, void *addr)
-{
- addr = mb_correct_addr_and_bit(&bit, addr);
- ext4_set_bit_atomic(lock, bit, addr);
-}
-
static inline void mb_clear_bit(int bit, void *addr)
{
addr = mb_correct_addr_and_bit(&bit, addr);
ext4_clear_bit(bit, addr);
}
-static inline void mb_clear_bit_atomic(spinlock_t *lock, int bit, void *addr)
-{
- addr = mb_correct_addr_and_bit(&bit, addr);
- ext4_clear_bit_atomic(lock, bit, addr);
-}
-
static inline int mb_find_next_zero_bit(void *addr, int max, int start)
{
int fix = 0, ret, tmpmax;
@@ -739,6 +727,7 @@ static void ext4_mb_generate_buddy(struct super_block *sb,
static int ext4_mb_init_cache(struct page *page, char *incore)
{
+ ext4_group_t ngroups;
int blocksize;
int blocks_per_page;
int groups_per_page;
@@ -757,6 +746,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
inode = page->mapping->host;
sb = inode->i_sb;
+ ngroups = ext4_get_groups_count(sb);
blocksize = 1 << inode->i_blkbits;
blocks_per_page = PAGE_CACHE_SIZE / blocksize;
@@ -780,7 +770,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
for (i = 0; i < groups_per_page; i++) {
struct ext4_group_desc *desc;
- if (first_group + i >= EXT4_SB(sb)->s_groups_count)
+ if (first_group + i >= ngroups)
break;
err = -EIO;
@@ -801,17 +791,17 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
unlock_buffer(bh[i]);
continue;
}
- spin_lock(sb_bgl_lock(EXT4_SB(sb), first_group + i));
+ ext4_lock_group(sb, first_group + i);
if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
ext4_init_block_bitmap(sb, bh[i],
first_group + i, desc);
set_bitmap_uptodate(bh[i]);
set_buffer_uptodate(bh[i]);
- spin_unlock(sb_bgl_lock(EXT4_SB(sb), first_group + i));
+ ext4_unlock_group(sb, first_group + i);
unlock_buffer(bh[i]);
continue;
}
- spin_unlock(sb_bgl_lock(EXT4_SB(sb), first_group + i));
+ ext4_unlock_group(sb, first_group + i);
if (buffer_uptodate(bh[i])) {
/*
* if not uninit if bh is uptodate,
@@ -852,7 +842,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
struct ext4_group_info *grinfo;
group = (first_block + i) >> 1;
- if (group >= EXT4_SB(sb)->s_groups_count)
+ if (group >= ngroups)
break;
/*
@@ -1078,7 +1068,7 @@ static int mb_find_order_for_block(struct ext4_buddy *e4b, int block)
return 0;
}
-static void mb_clear_bits(spinlock_t *lock, void *bm, int cur, int len)
+static void mb_clear_bits(void *bm, int cur, int len)
{
__u32 *addr;
@@ -1091,15 +1081,12 @@ static void mb_clear_bits(spinlock_t *lock, void *bm, int cur, int len)
cur += 32;
continue;
}
- if (lock)
- mb_clear_bit_atomic(lock, cur, bm);
- else
- mb_clear_bit(cur, bm);
+ mb_clear_bit(cur, bm);
cur++;
}
}
-static void mb_set_bits(spinlock_t *lock, void *bm, int cur, int len)
+static void mb_set_bits(void *bm, int cur, int len)
{
__u32 *addr;
@@ -1112,10 +1099,7 @@ static void mb_set_bits(spinlock_t *lock, void *bm, int cur, int len)
cur += 32;
continue;
}
- if (lock)
- mb_set_bit_atomic(lock, cur, bm);
- else
- mb_set_bit(cur, bm);
+ mb_set_bit(cur, bm);
cur++;
}
}
@@ -1330,8 +1314,7 @@ static int mb_mark_used(struct ext4_buddy *e4b, struct ext4_free_extent *ex)
e4b->bd_info->bb_counters[ord]++;
}
- mb_set_bits(sb_bgl_lock(EXT4_SB(e4b->bd_sb), ex->fe_group),
- EXT4_MB_BITMAP(e4b), ex->fe_start, len0);
+ mb_set_bits(EXT4_MB_BITMAP(e4b), ex->fe_start, len0);
mb_check_buddy(e4b);
return ret;
@@ -1726,7 +1709,6 @@ static int ext4_mb_good_group(struct ext4_allocation_context *ac,
unsigned free, fragments;
unsigned i, bits;
int flex_size = ext4_flex_bg_size(EXT4_SB(ac->ac_sb));
- struct ext4_group_desc *desc;
struct ext4_group_info *grp = ext4_get_group_info(ac->ac_sb, group);
BUG_ON(cr < 0 || cr >= 4);
@@ -1742,10 +1724,6 @@ static int ext4_mb_good_group(struct ext4_allocation_context *ac,
switch (cr) {
case 0:
BUG_ON(ac->ac_2order == 0);
- /* If this group is uninitialized, skip it initially */
- desc = ext4_get_group_desc(ac->ac_sb, group, NULL);
- if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))
- return 0;
/* Avoid using the first bg of a flexgroup for data files */
if ((ac->ac_flags & EXT4_MB_HINT_DATA) &&
@@ -1788,6 +1766,7 @@ int ext4_mb_get_buddy_cache_lock(struct super_block *sb, ext4_group_t group)
int block, pnum;
int blocks_per_page;
int groups_per_page;
+ ext4_group_t ngroups = ext4_get_groups_count(sb);
ext4_group_t first_group;
struct ext4_group_info *grp;
@@ -1807,7 +1786,7 @@ int ext4_mb_get_buddy_cache_lock(struct super_block *sb, ext4_group_t group)
/* read all groups the page covers into the cache */
for (i = 0; i < groups_per_page; i++) {
- if ((first_group + i) >= EXT4_SB(sb)->s_groups_count)
+ if ((first_group + i) >= ngroups)
break;
grp = ext4_get_group_info(sb, first_group + i);
/* take all groups write allocation
@@ -1945,8 +1924,7 @@ err:
static noinline_for_stack int
ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
{
- ext4_group_t group;
- ext4_group_t i;
+ ext4_group_t ngroups, group, i;
int cr;
int err = 0;
int bsbits;
@@ -1957,6 +1935,7 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
sb = ac->ac_sb;
sbi = EXT4_SB(sb);
+ ngroups = ext4_get_groups_count(sb);
BUG_ON(ac->ac_status == AC_STATUS_FOUND);
/* first, try the goal */
@@ -2017,11 +1996,11 @@ repeat:
*/
group = ac->ac_g_ex.fe_group;
- for (i = 0; i < EXT4_SB(sb)->s_groups_count; group++, i++) {
+ for (i = 0; i < ngroups; group++, i++) {
struct ext4_group_info *grp;
struct ext4_group_desc *desc;
- if (group == EXT4_SB(sb)->s_groups_count)
+ if (group == ngroups)
group = 0;
/* quick check to skip empty groups */
@@ -2064,9 +2043,7 @@ repeat:
ac->ac_groups_scanned++;
desc = ext4_get_group_desc(sb, group, NULL);
- if (cr == 0 || (desc->bg_flags &
- cpu_to_le16(EXT4_BG_BLOCK_UNINIT) &&
- ac->ac_2order != 0))
+ if (cr == 0)
ext4_mb_simple_scan_group(ac, &e4b);
else if (cr == 1 &&
ac->ac_g_ex.fe_len == sbi->s_stripe)
@@ -2315,12 +2292,10 @@ static struct file_operations ext4_mb_seq_history_fops = {
static void *ext4_mb_seq_groups_start(struct seq_file *seq, loff_t *pos)
{
struct super_block *sb = seq->private;
- struct ext4_sb_info *sbi = EXT4_SB(sb);
ext4_group_t group;
- if (*pos < 0 || *pos >= sbi->s_groups_count)
+ if (*pos < 0 || *pos >= ext4_get_groups_count(sb))
return NULL;
-
group = *pos + 1;
return (void *) ((unsigned long) group);
}
@@ -2328,11 +2303,10 @@ static void *ext4_mb_seq_groups_start(struct seq_file *seq, loff_t *pos)
static void *ext4_mb_seq_groups_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct super_block *sb = seq->private;
- struct ext4_sb_info *sbi = EXT4_SB(sb);
ext4_group_t group;
++*pos;
- if (*pos < 0 || *pos >= sbi->s_groups_count)
+ if (*pos < 0 || *pos >= ext4_get_groups_count(sb))
return NULL;
group = *pos + 1;
return (void *) ((unsigned long) group);
@@ -2420,7 +2394,8 @@ static void ext4_mb_history_release(struct super_block *sb)
if (sbi->s_proc != NULL) {
remove_proc_entry("mb_groups", sbi->s_proc);
- remove_proc_entry("mb_history", sbi->s_proc);
+ if (sbi->s_mb_history_max)
+ remove_proc_entry("mb_history", sbi->s_proc);
}
kfree(sbi->s_mb_history);
}
@@ -2431,17 +2406,17 @@ static void ext4_mb_history_init(struct super_block *sb)
int i;
if (sbi->s_proc != NULL) {
- proc_create_data("mb_history", S_IRUGO, sbi->s_proc,
- &ext4_mb_seq_history_fops, sb);
+ if (sbi->s_mb_history_max)
+ proc_create_data("mb_history", S_IRUGO, sbi->s_proc,
+ &ext4_mb_seq_history_fops, sb);
proc_create_data("mb_groups", S_IRUGO, sbi->s_proc,
&ext4_mb_seq_groups_fops, sb);
}
- sbi->s_mb_history_max = 1000;
sbi->s_mb_history_cur = 0;
spin_lock_init(&sbi->s_mb_history_lock);
i = sbi->s_mb_history_max * sizeof(struct ext4_mb_history);
- sbi->s_mb_history = kzalloc(i, GFP_KERNEL);
+ sbi->s_mb_history = i ? kzalloc(i, GFP_KERNEL) : NULL;
/* if we can't allocate history, then we simple won't use it */
}
@@ -2451,7 +2426,7 @@ ext4_mb_store_history(struct ext4_allocation_context *ac)
struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
struct ext4_mb_history h;
- if (unlikely(sbi->s_mb_history == NULL))
+ if (sbi->s_mb_history == NULL)
return;
if (!(ac->ac_op & sbi->s_mb_history_filter))
@@ -2587,6 +2562,7 @@ void ext4_mb_update_group_info(struct ext4_group_info *grp, ext4_grpblk_t add)
static int ext4_mb_init_backend(struct super_block *sb)
{
+ ext4_group_t ngroups = ext4_get_groups_count(sb);
ext4_group_t i;
int metalen;
struct ext4_sb_info *sbi = EXT4_SB(sb);
@@ -2598,7 +2574,7 @@ static int ext4_mb_init_backend(struct super_block *sb)
struct ext4_group_desc *desc;
/* This is the number of blocks used by GDT */
- num_meta_group_infos = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) -
+ num_meta_group_infos = (ngroups + EXT4_DESC_PER_BLOCK(sb) -
1) >> EXT4_DESC_PER_BLOCK_BITS(sb);
/*
@@ -2644,7 +2620,7 @@ static int ext4_mb_init_backend(struct super_block *sb)
for (i = 0; i < num_meta_group_infos; i++) {
if ((i + 1) == num_meta_group_infos)
metalen = sizeof(*meta_group_info) *
- (sbi->s_groups_count -
+ (ngroups -
(i << EXT4_DESC_PER_BLOCK_BITS(sb)));
meta_group_info = kmalloc(metalen, GFP_KERNEL);
if (meta_group_info == NULL) {
@@ -2655,7 +2631,7 @@ static int ext4_mb_init_backend(struct super_block *sb)
sbi->s_group_info[i] = meta_group_info;
}
- for (i = 0; i < sbi->s_groups_count; i++) {
+ for (i = 0; i < ngroups; i++) {
desc = ext4_get_group_desc(sb, i, NULL);
if (desc == NULL) {
printk(KERN_ERR
@@ -2761,7 +2737,7 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
return 0;
}
-/* need to called with ext4 group lock (ext4_lock_group) */
+/* need to called with the ext4 group lock held */
static void ext4_mb_cleanup_pa(struct ext4_group_info *grp)
{
struct ext4_prealloc_space *pa;
@@ -2781,13 +2757,14 @@ static void ext4_mb_cleanup_pa(struct ext4_group_info *grp)
int ext4_mb_release(struct super_block *sb)
{
+ ext4_group_t ngroups = ext4_get_groups_count(sb);
ext4_group_t i;
int num_meta_group_infos;
struct ext4_group_info *grinfo;
struct ext4_sb_info *sbi = EXT4_SB(sb);
if (sbi->s_group_info) {
- for (i = 0; i < sbi->s_groups_count; i++) {
+ for (i = 0; i < ngroups; i++) {
grinfo = ext4_get_group_info(sb, i);
#ifdef DOUBLE_CHECK
kfree(grinfo->bb_bitmap);
@@ -2797,7 +2774,7 @@ int ext4_mb_release(struct super_block *sb)
ext4_unlock_group(sb, i);
kfree(grinfo);
}
- num_meta_group_infos = (sbi->s_groups_count +
+ num_meta_group_infos = (ngroups +
EXT4_DESC_PER_BLOCK(sb) - 1) >>
EXT4_DESC_PER_BLOCK_BITS(sb);
for (i = 0; i < num_meta_group_infos; i++)
@@ -2997,14 +2974,17 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
* Fix the bitmap and repeat the block allocation
* We leak some of the blocks here.
*/
- mb_set_bits(sb_bgl_lock(sbi, ac->ac_b_ex.fe_group),
- bitmap_bh->b_data, ac->ac_b_ex.fe_start,
- ac->ac_b_ex.fe_len);
+ ext4_lock_group(sb, ac->ac_b_ex.fe_group);
+ mb_set_bits(bitmap_bh->b_data, ac->ac_b_ex.fe_start,
+ ac->ac_b_ex.fe_len);
+ ext4_unlock_group(sb, ac->ac_b_ex.fe_group);
err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
if (!err)
err = -EAGAIN;
goto out_err;
}
+
+ ext4_lock_group(sb, ac->ac_b_ex.fe_group);
#ifdef AGGRESSIVE_CHECK
{
int i;
@@ -3014,9 +2994,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
}
}
#endif
- spin_lock(sb_bgl_lock(sbi, ac->ac_b_ex.fe_group));
- mb_set_bits(NULL, bitmap_bh->b_data,
- ac->ac_b_ex.fe_start, ac->ac_b_ex.fe_len);
+ mb_set_bits(bitmap_bh->b_data, ac->ac_b_ex.fe_start,ac->ac_b_ex.fe_len);
if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
ext4_free_blks_set(sb, gdp,
@@ -3026,7 +3004,8 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
len = ext4_free_blks_count(sb, gdp) - ac->ac_b_ex.fe_len;
ext4_free_blks_set(sb, gdp, len);
gdp->bg_checksum = ext4_group_desc_csum(sbi, ac->ac_b_ex.fe_group, gdp);
- spin_unlock(sb_bgl_lock(sbi, ac->ac_b_ex.fe_group));
+
+ ext4_unlock_group(sb, ac->ac_b_ex.fe_group);
percpu_counter_sub(&sbi->s_freeblocks_counter, ac->ac_b_ex.fe_len);
/*
* Now reduce the dirty block count also. Should not go negative
@@ -3459,7 +3438,7 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
* the function goes through all block freed in the group
* but not yet committed and marks them used in in-core bitmap.
* buddy must be generated from this bitmap
- * Need to be called with ext4 group lock (ext4_lock_group)
+ * Need to be called with the ext4 group lock held
*/
static void ext4_mb_generate_from_freelist(struct super_block *sb, void *bitmap,
ext4_group_t group)
@@ -3473,9 +3452,7 @@ static void ext4_mb_generate_from_freelist(struct super_block *sb, void *bitmap,
while (n) {
entry = rb_entry(n, struct ext4_free_data, node);
- mb_set_bits(sb_bgl_lock(EXT4_SB(sb), group),
- bitmap, entry->start_blk,
- entry->count);
+ mb_set_bits(bitmap, entry->start_blk, entry->count);
n = rb_next(n);
}
return;
@@ -3484,7 +3461,7 @@ static void ext4_mb_generate_from_freelist(struct super_block *sb, void *bitmap,
/*
* the function goes through all preallocation in this group and marks them
* used in in-core bitmap. buddy must be generated from this bitmap
- * Need to be called with ext4 group lock (ext4_lock_group)
+ * Need to be called with ext4 group lock held
*/
static void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap,
ext4_group_t group)
@@ -3516,8 +3493,7 @@ static void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap,
if (unlikely(len == 0))
continue;
BUG_ON(groupnr != group);
- mb_set_bits(sb_bgl_lock(EXT4_SB(sb), group),
- bitmap, start, len);
+ mb_set_bits(bitmap, start, len);
preallocated += len;
count++;
}
@@ -4121,7 +4097,7 @@ static void ext4_mb_return_to_preallocation(struct inode *inode,
static void ext4_mb_show_ac(struct ext4_allocation_context *ac)
{
struct super_block *sb = ac->ac_sb;
- ext4_group_t i;
+ ext4_group_t ngroups, i;
printk(KERN_ERR "EXT4-fs: Can't allocate:"
" Allocation context details:\n");
@@ -4145,7 +4121,8 @@ static void ext4_mb_show_ac(struct ext4_allocation_context *ac)
printk(KERN_ERR "EXT4-fs: %lu scanned, %d found\n", ac->ac_ex_scanned,
ac->ac_found);
printk(KERN_ERR "EXT4-fs: groups: \n");
- for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) {
+ ngroups = ext4_get_groups_count(sb);
+ for (i = 0; i < ngroups; i++) {
struct ext4_group_info *grp = ext4_get_group_info(sb, i);
struct ext4_prealloc_space *pa;
ext4_grpblk_t start;
@@ -4469,13 +4446,13 @@ static int ext4_mb_release_context(struct ext4_allocation_context *ac)
static int ext4_mb_discard_preallocations(struct super_block *sb, int needed)
{
- ext4_group_t i;
+ ext4_group_t i, ngroups = ext4_get_groups_count(sb);
int ret;
int freed = 0;
trace_mark(ext4_mb_discard_preallocations, "dev %s needed %d",
sb->s_id, needed);
- for (i = 0; i < EXT4_SB(sb)->s_groups_count && needed > 0; i++) {
+ for (i = 0; i < ngroups && needed > 0; i++) {
ret = ext4_mb_discard_group_preallocations(sb, i, needed);
freed += ret;
needed -= ret;
@@ -4859,29 +4836,25 @@ do_more:
new_entry->group = block_group;
new_entry->count = count;
new_entry->t_tid = handle->h_transaction->t_tid;
+
ext4_lock_group(sb, block_group);
- mb_clear_bits(sb_bgl_lock(sbi, block_group), bitmap_bh->b_data,
- bit, count);
+ mb_clear_bits(bitmap_bh->b_data, bit, count);
ext4_mb_free_metadata(handle, &e4b, new_entry);
- ext4_unlock_group(sb, block_group);
} else {
- ext4_lock_group(sb, block_group);
/* need to update group_info->bb_free and bitmap
* with group lock held. generate_buddy look at
* them with group lock_held
*/
- mb_clear_bits(sb_bgl_lock(sbi, block_group), bitmap_bh->b_data,
- bit, count);
+ ext4_lock_group(sb, block_group);
+ mb_clear_bits(bitmap_bh->b_data, bit, count);
mb_free_blocks(inode, &e4b, bit, count);
ext4_mb_return_to_preallocation(inode, &e4b, block, count);
- ext4_unlock_group(sb, block_group);
}
- spin_lock(sb_bgl_lock(sbi, block_group));
ret = ext4_free_blks_count(sb, gdp) + count;
ext4_free_blks_set(sb, gdp, ret);
gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp);
- spin_unlock(sb_bgl_lock(sbi, block_group));
+ ext4_unlock_group(sb, block_group);
percpu_counter_add(&sbi->s_freeblocks_counter, count);
if (sbi->s_log_groups_per_flex) {
diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
index dd9e6cd5f6cf..75e34f69215b 100644
--- a/fs/ext4/mballoc.h
+++ b/fs/ext4/mballoc.h
@@ -23,7 +23,6 @@
#include <linux/mutex.h>
#include "ext4_jbd2.h"
#include "ext4.h"
-#include "group.h"
/*
* with AGGRESSIVE_CHECK allocator runs consistency checks over
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 22098e1cd085..f2bc160463b7 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -37,7 +37,6 @@
#include "ext4.h"
#include "ext4_jbd2.h"
-#include "namei.h"
#include "xattr.h"
#include "acl.h"
@@ -1997,7 +1996,7 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
if (!ext4_handle_valid(handle))
return 0;
- lock_super(sb);
+ mutex_lock(&EXT4_SB(sb)->s_orphan_lock);
if (!list_empty(&EXT4_I(inode)->i_orphan))
goto out_unlock;
@@ -2006,9 +2005,13 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
/* @@@ FIXME: Observation from aviro:
* I think I can trigger J_ASSERT in ext4_orphan_add(). We block
- * here (on lock_super()), so race with ext4_link() which might bump
+ * here (on s_orphan_lock), so race with ext4_link() which might bump
* ->i_nlink. For, say it, character device. Not a regular file,
* not a directory, not a symlink and ->i_nlink > 0.
+ *
+ * tytso, 4/25/2009: I'm not sure how that could happen;
+ * shouldn't the fs core protect us from these sort of
+ * unlink()/link() races?
*/
J_ASSERT((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode)) || inode->i_nlink == 0);
@@ -2045,7 +2048,7 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
jbd_debug(4, "orphan inode %lu will point to %d\n",
inode->i_ino, NEXT_ORPHAN(inode));
out_unlock:
- unlock_super(sb);
+ mutex_unlock(&EXT4_SB(sb)->s_orphan_lock);
ext4_std_error(inode->i_sb, err);
return err;
}
@@ -2066,11 +2069,9 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode)
if (!ext4_handle_valid(handle))
return 0;
- lock_super(inode->i_sb);
- if (list_empty(&ei->i_orphan)) {
- unlock_super(inode->i_sb);
- return 0;
- }
+ mutex_lock(&EXT4_SB(inode->i_sb)->s_orphan_lock);
+ if (list_empty(&ei->i_orphan))
+ goto out;
ino_next = NEXT_ORPHAN(inode);
prev = ei->i_orphan.prev;
@@ -2120,7 +2121,7 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode)
out_err:
ext4_std_error(inode->i_sb, err);
out:
- unlock_super(inode->i_sb);
+ mutex_unlock(&EXT4_SB(inode->i_sb)->s_orphan_lock);
return err;
out_brelse:
@@ -2533,6 +2534,7 @@ const struct inode_operations ext4_dir_inode_operations = {
.removexattr = generic_removexattr,
#endif
.permission = ext4_permission,
+ .fiemap = ext4_fiemap,
};
const struct inode_operations ext4_special_inode_operations = {
diff --git a/fs/ext4/namei.h b/fs/ext4/namei.h
deleted file mode 100644
index 5e4dfff36a00..000000000000
--- a/fs/ext4/namei.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* linux/fs/ext4/namei.h
- *
- * Copyright (C) 2005 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
-*/
-
-extern struct dentry *ext4_get_parent(struct dentry *child);
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index 546c7dd869e1..27eb289eea37 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -15,7 +15,6 @@
#include <linux/slab.h>
#include "ext4_jbd2.h"
-#include "group.h"
#define outside(b, first, last) ((b) < (first) || (b) >= (last))
#define inside(b, first, last) ((b) >= (first) && (b) < (last))
@@ -193,7 +192,7 @@ static int setup_new_group_blocks(struct super_block *sb,
if (IS_ERR(handle))
return PTR_ERR(handle);
- lock_super(sb);
+ mutex_lock(&sbi->s_resize_lock);
if (input->group != sbi->s_groups_count) {
err = -EBUSY;
goto exit_journal;
@@ -302,7 +301,7 @@ exit_bh:
brelse(bh);
exit_journal:
- unlock_super(sb);
+ mutex_unlock(&sbi->s_resize_lock);
if ((err2 = ext4_journal_stop(handle)) && !err)
err = err2;
@@ -643,11 +642,12 @@ exit_free:
* important part is that the new block and inode counts are in the backup
* superblocks, and the location of the new group metadata in the GDT backups.
*
- * We do not need lock_super() for this, because these blocks are not
- * otherwise touched by the filesystem code when it is mounted. We don't
- * need to worry about last changing from sbi->s_groups_count, because the
- * worst that can happen is that we do not copy the full number of backups
- * at this time. The resize which changed s_groups_count will backup again.
+ * We do not need take the s_resize_lock for this, because these
+ * blocks are not otherwise touched by the filesystem code when it is
+ * mounted. We don't need to worry about last changing from
+ * sbi->s_groups_count, because the worst that can happen is that we
+ * do not copy the full number of backups at this time. The resize
+ * which changed s_groups_count will backup again.
*/
static void update_backups(struct super_block *sb,
int blk_off, char *data, int size)
@@ -809,7 +809,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
goto exit_put;
}
- lock_super(sb);
+ mutex_lock(&sbi->s_resize_lock);
if (input->group != sbi->s_groups_count) {
ext4_warning(sb, __func__,
"multiple resizers run on filesystem!");
@@ -840,7 +840,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
/*
* OK, now we've set up the new group. Time to make it active.
*
- * Current kernels don't lock all allocations via lock_super(),
+ * We do not lock all allocations via s_resize_lock
* so we have to be safe wrt. concurrent accesses the group
* data. So we need to be careful to set all of the relevant
* group descriptor data etc. *before* we enable the group.
@@ -900,12 +900,12 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
*
* The precise rules we use are:
*
- * * Writers of s_groups_count *must* hold lock_super
+ * * Writers of s_groups_count *must* hold s_resize_lock
* AND
* * Writers must perform a smp_wmb() after updating all dependent
* data and before modifying the groups count
*
- * * Readers must hold lock_super() over the access
+ * * Readers must hold s_resize_lock over the access
* OR
* * Readers must perform an smp_rmb() after reading the groups count
* and before reading any dependent data.
@@ -948,7 +948,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
sb->s_dirt = 1;
exit_journal:
- unlock_super(sb);
+ mutex_unlock(&sbi->s_resize_lock);
if ((err2 = ext4_journal_stop(handle)) && !err)
err = err2;
if (!err) {
@@ -986,7 +986,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
/* We don't need to worry about locking wrt other resizers just
* yet: we're going to revalidate es->s_blocks_count after
- * taking lock_super() below. */
+ * taking the s_resize_lock below. */
o_blocks_count = ext4_blocks_count(es);
o_groups_count = EXT4_SB(sb)->s_groups_count;
@@ -1056,11 +1056,11 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
goto exit_put;
}
- lock_super(sb);
+ mutex_lock(&EXT4_SB(sb)->s_resize_lock);
if (o_blocks_count != ext4_blocks_count(es)) {
ext4_warning(sb, __func__,
"multiple resizers run on filesystem!");
- unlock_super(sb);
+ mutex_unlock(&EXT4_SB(sb)->s_resize_lock);
ext4_journal_stop(handle);
err = -EBUSY;
goto exit_put;
@@ -1070,14 +1070,14 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
EXT4_SB(sb)->s_sbh))) {
ext4_warning(sb, __func__,
"error %d on journal write access", err);
- unlock_super(sb);
+ mutex_unlock(&EXT4_SB(sb)->s_resize_lock);
ext4_journal_stop(handle);
goto exit_put;
}
ext4_blocks_count_set(es, o_blocks_count + add);
ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
sb->s_dirt = 1;
- unlock_super(sb);
+ mutex_unlock(&EXT4_SB(sb)->s_resize_lock);
ext4_debug("freeing blocks %llu through %llu\n", o_blocks_count,
o_blocks_count + add);
/* We add the blocks to the bitmap and set the group need init bit */
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 2958f4e6f222..4f28b8aa8de5 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -20,6 +20,7 @@
#include <linux/string.h>
#include <linux/fs.h>
#include <linux/time.h>
+#include <linux/vmalloc.h>
#include <linux/jbd2.h>
#include <linux/slab.h>
#include <linux/init.h>
@@ -45,16 +46,20 @@
#include "ext4_jbd2.h"
#include "xattr.h"
#include "acl.h"
-#include "namei.h"
-#include "group.h"
+
+static int default_mb_history_length = 1000;
+
+module_param_named(default_mb_history_length, default_mb_history_length,
+ int, 0644);
+MODULE_PARM_DESC(default_mb_history_length,
+ "Default number of entries saved for mb_history");
struct proc_dir_entry *ext4_proc_root;
static struct kset *ext4_kset;
static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
unsigned long journal_devnum);
-static int ext4_commit_super(struct super_block *sb,
- struct ext4_super_block *es, int sync);
+static int ext4_commit_super(struct super_block *sb, int sync);
static void ext4_mark_recovery_complete(struct super_block *sb,
struct ext4_super_block *es);
static void ext4_clear_journal_err(struct super_block *sb,
@@ -305,7 +310,7 @@ static void ext4_handle_error(struct super_block *sb)
printk(KERN_CRIT "Remounting filesystem read-only\n");
sb->s_flags |= MS_RDONLY;
}
- ext4_commit_super(sb, es, 1);
+ ext4_commit_super(sb, 1);
if (test_opt(sb, ERRORS_PANIC))
panic("EXT4-fs (device %s): panic forced after error\n",
sb->s_id);
@@ -447,7 +452,7 @@ __acquires(bitlock)
if (test_opt(sb, ERRORS_CONT)) {
EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
- ext4_commit_super(sb, es, 0);
+ ext4_commit_super(sb, 0);
return;
}
ext4_unlock_group(sb, grp);
@@ -563,6 +568,11 @@ static void ext4_put_super(struct super_block *sb)
struct ext4_super_block *es = sbi->s_es;
int i, err;
+ lock_super(sb);
+ lock_kernel();
+ if (sb->s_dirt)
+ ext4_write_super(sb);
+
ext4_mb_release(sb);
ext4_ext_release(sb);
ext4_xattr_put_super(sb);
@@ -576,7 +586,7 @@ static void ext4_put_super(struct super_block *sb)
if (!(sb->s_flags & MS_RDONLY)) {
EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
es->s_state = cpu_to_le16(sbi->s_mount_state);
- ext4_commit_super(sb, es, 1);
+ ext4_commit_super(sb, 1);
}
if (sbi->s_proc) {
remove_proc_entry(sb->s_id, ext4_proc_root);
@@ -586,7 +596,10 @@ static void ext4_put_super(struct super_block *sb)
for (i = 0; i < sbi->s_gdb_count; i++)
brelse(sbi->s_group_desc[i]);
kfree(sbi->s_group_desc);
- kfree(sbi->s_flex_groups);
+ if (is_vmalloc_addr(sbi->s_flex_groups))
+ vfree(sbi->s_flex_groups);
+ else
+ kfree(sbi->s_flex_groups);
percpu_counter_destroy(&sbi->s_freeblocks_counter);
percpu_counter_destroy(&sbi->s_freeinodes_counter);
percpu_counter_destroy(&sbi->s_dirs_counter);
@@ -625,11 +638,8 @@ static void ext4_put_super(struct super_block *sb)
unlock_super(sb);
kobject_put(&sbi->s_kobj);
wait_for_completion(&sbi->s_kobj_unregister);
- lock_super(sb);
- lock_kernel();
kfree(sbi->s_blockgroup_lock);
kfree(sbi);
- return;
}
static struct kmem_cache *ext4_inode_cachep;
@@ -992,7 +1002,6 @@ static const struct super_operations ext4_sops = {
.dirty_inode = ext4_dirty_inode,
.delete_inode = ext4_delete_inode,
.put_super = ext4_put_super,
- .write_super = ext4_write_super,
.sync_fs = ext4_sync_fs,
.freeze_fs = ext4_freeze,
.unfreeze_fs = ext4_unfreeze,
@@ -1007,6 +1016,25 @@ static const struct super_operations ext4_sops = {
.bdev_try_to_free_page = bdev_try_to_free_page,
};
+static const struct super_operations ext4_nojournal_sops = {
+ .alloc_inode = ext4_alloc_inode,
+ .destroy_inode = ext4_destroy_inode,
+ .write_inode = ext4_write_inode,
+ .dirty_inode = ext4_dirty_inode,
+ .delete_inode = ext4_delete_inode,
+ .write_super = ext4_write_super,
+ .put_super = ext4_put_super,
+ .statfs = ext4_statfs,
+ .remount_fs = ext4_remount,
+ .clear_inode = ext4_clear_inode,
+ .show_options = ext4_show_options,
+#ifdef CONFIG_QUOTA
+ .quota_read = ext4_quota_read,
+ .quota_write = ext4_quota_write,
+#endif
+ .bdev_try_to_free_page = bdev_try_to_free_page,
+};
+
static const struct export_operations ext4_export_ops = {
.fh_to_dentry = ext4_fh_to_dentry,
.fh_to_parent = ext4_fh_to_parent,
@@ -1023,7 +1051,7 @@ enum {
Opt_journal_update, Opt_journal_dev,
Opt_journal_checksum, Opt_journal_async_commit,
Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
- Opt_data_err_abort, Opt_data_err_ignore,
+ Opt_data_err_abort, Opt_data_err_ignore, Opt_mb_history_length,
Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err, Opt_resize,
@@ -1069,6 +1097,7 @@ static const match_table_t tokens = {
{Opt_data_writeback, "data=writeback"},
{Opt_data_err_abort, "data_err=abort"},
{Opt_data_err_ignore, "data_err=ignore"},
+ {Opt_mb_history_length, "mb_history_length=%u"},
{Opt_offusrjquota, "usrjquota="},
{Opt_usrjquota, "usrjquota=%s"},
{Opt_offgrpjquota, "grpjquota="},
@@ -1310,6 +1339,13 @@ static int parse_options(char *options, struct super_block *sb,
case Opt_data_err_ignore:
clear_opt(sbi->s_mount_opt, DATA_ERR_ABORT);
break;
+ case Opt_mb_history_length:
+ if (match_int(&args[0], &option))
+ return 0;
+ if (option < 0)
+ return 0;
+ sbi->s_mb_history_max = option;
+ break;
#ifdef CONFIG_QUOTA
case Opt_usrjquota:
qtype = USRQUOTA;
@@ -1479,7 +1515,7 @@ set_qf_format:
return 0;
if (option < 0 || option > (1 << 30))
return 0;
- if (option & (option - 1)) {
+ if (!is_power_of_2(option)) {
printk(KERN_ERR "EXT4-fs: inode_readahead_blks"
" must be a power of 2\n");
return 0;
@@ -1592,7 +1628,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
if (sbi->s_journal)
EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
- ext4_commit_super(sb, es, 1);
+ ext4_commit_super(sb, 1);
if (test_opt(sb, DEBUG))
printk(KERN_INFO "[EXT4 FS bs=%lu, gc=%u, "
"bpg=%lu, ipg=%lu, mo=%04lx]\n",
@@ -1620,6 +1656,7 @@ static int ext4_fill_flex_info(struct super_block *sb)
ext4_group_t flex_group_count;
ext4_group_t flex_group;
int groups_per_flex = 0;
+ size_t size;
int i;
if (!sbi->s_es->s_log_groups_per_flex) {
@@ -1634,8 +1671,13 @@ static int ext4_fill_flex_info(struct super_block *sb)
flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) +
((le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) + 1) <<
EXT4_DESC_PER_BLOCK_BITS(sb))) / groups_per_flex;
- sbi->s_flex_groups = kzalloc(flex_group_count *
- sizeof(struct flex_groups), GFP_KERNEL);
+ size = flex_group_count * sizeof(struct flex_groups);
+ sbi->s_flex_groups = kzalloc(size, GFP_KERNEL);
+ if (sbi->s_flex_groups == NULL) {
+ sbi->s_flex_groups = vmalloc(size);
+ if (sbi->s_flex_groups)
+ memset(sbi->s_flex_groups, 0, size);
+ }
if (sbi->s_flex_groups == NULL) {
printk(KERN_ERR "EXT4-fs: not enough memory for "
"%u flex groups\n", flex_group_count);
@@ -1744,18 +1786,18 @@ static int ext4_check_descriptors(struct super_block *sb)
"(block %llu)!\n", i, inode_table);
return 0;
}
- spin_lock(sb_bgl_lock(sbi, i));
+ ext4_lock_group(sb, i);
if (!ext4_group_desc_csum_verify(sbi, i, gdp)) {
printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
"Checksum for group %u failed (%u!=%u)\n",
i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
gdp)), le16_to_cpu(gdp->bg_checksum));
if (!(sb->s_flags & MS_RDONLY)) {
- spin_unlock(sb_bgl_lock(sbi, i));
+ ext4_unlock_group(sb, i);
return 0;
}
}
- spin_unlock(sb_bgl_lock(sbi, i));
+ ext4_unlock_group(sb, i);
if (!flexbg_flag)
first_block += EXT4_BLOCKS_PER_GROUP(sb);
}
@@ -2091,8 +2133,7 @@ static ssize_t inode_readahead_blks_store(struct ext4_attr *a,
if (parse_strtoul(buf, 0x40000000, &t))
return -EINVAL;
- /* inode_readahead_blks must be a power of 2 */
- if (t & (t-1))
+ if (!is_power_of_2(t))
return -EINVAL;
sbi->s_inode_readahead_blks = t;
@@ -2321,6 +2362,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
sbi->s_commit_interval = JBD2_DEFAULT_MAX_COMMIT_AGE * HZ;
sbi->s_min_batch_time = EXT4_DEF_MIN_BATCH_TIME;
sbi->s_max_batch_time = EXT4_DEF_MAX_BATCH_TIME;
+ sbi->s_mb_history_max = default_mb_history_length;
set_opt(sbi->s_mount_opt, BARRIER);
@@ -2607,7 +2649,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
/*
* set up enough so that it can read an inode
*/
- sb->s_op = &ext4_sops;
+ if (!test_opt(sb, NOLOAD) &&
+ EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL))
+ sb->s_op = &ext4_sops;
+ else
+ sb->s_op = &ext4_nojournal_sops;
sb->s_export_op = &ext4_export_ops;
sb->s_xattr = ext4_xattr_handlers;
#ifdef CONFIG_QUOTA
@@ -2615,6 +2661,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
sb->dq_op = &ext4_quota_operations;
#endif
INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
+ mutex_init(&sbi->s_orphan_lock);
+ mutex_init(&sbi->s_resize_lock);
sb->s_root = NULL;
@@ -2646,7 +2694,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
if (test_opt(sb, ERRORS_PANIC)) {
EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
- ext4_commit_super(sb, es, 1);
+ ext4_commit_super(sb, 1);
goto failed_mount4;
}
}
@@ -2798,14 +2846,6 @@ no_journal:
goto failed_mount4;
};
- /*
- * akpm: core read_super() calls in here with the superblock locked.
- * That deadlocks, because orphan cleanup needs to lock the superblock
- * in numerous places. Here we just pop the lock - it's relatively
- * harmless, because we are now ready to accept write_super() requests,
- * and aviro says that's the only reason for hanging onto the
- * superblock lock.
- */
EXT4_SB(sb)->s_mount_state |= EXT4_ORPHAN_FS;
ext4_orphan_cleanup(sb, es);
EXT4_SB(sb)->s_mount_state &= ~EXT4_ORPHAN_FS;
@@ -2842,6 +2882,12 @@ failed_mount4:
sbi->s_journal = NULL;
}
failed_mount3:
+ if (sbi->s_flex_groups) {
+ if (is_vmalloc_addr(sbi->s_flex_groups))
+ vfree(sbi->s_flex_groups);
+ else
+ kfree(sbi->s_flex_groups);
+ }
percpu_counter_destroy(&sbi->s_freeblocks_counter);
percpu_counter_destroy(&sbi->s_freeinodes_counter);
percpu_counter_destroy(&sbi->s_dirs_counter);
@@ -3114,18 +3160,17 @@ static int ext4_load_journal(struct super_block *sb,
if (journal_devnum &&
journal_devnum != le32_to_cpu(es->s_journal_dev)) {
es->s_journal_dev = cpu_to_le32(journal_devnum);
- sb->s_dirt = 1;
/* Make sure we flush the recovery flag to disk. */
- ext4_commit_super(sb, es, 1);
+ ext4_commit_super(sb, 1);
}
return 0;
}
-static int ext4_commit_super(struct super_block *sb,
- struct ext4_super_block *es, int sync)
+static int ext4_commit_super(struct super_block *sb, int sync)
{
+ struct ext4_super_block *es = EXT4_SB(sb)->s_es;
struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;
int error = 0;
@@ -3154,7 +3199,7 @@ static int ext4_commit_super(struct super_block *sb,
&EXT4_SB(sb)->s_freeblocks_counter));
es->s_free_inodes_count = cpu_to_le32(percpu_counter_sum_positive(
&EXT4_SB(sb)->s_freeinodes_counter));
-
+ sb->s_dirt = 0;
BUFFER_TRACE(sbh, "marking dirty");
mark_buffer_dirty(sbh);
if (sync) {
@@ -3192,14 +3237,11 @@ static void ext4_mark_recovery_complete(struct super_block *sb,
if (jbd2_journal_flush(journal) < 0)
goto out;
- lock_super(sb);
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) &&
sb->s_flags & MS_RDONLY) {
EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
- sb->s_dirt = 0;
- ext4_commit_super(sb, es, 1);
+ ext4_commit_super(sb, 1);
}
- unlock_super(sb);
out:
jbd2_journal_unlock_updates(journal);
@@ -3238,7 +3280,7 @@ static void ext4_clear_journal_err(struct super_block *sb,
EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
- ext4_commit_super(sb, es, 1);
+ ext4_commit_super(sb, 1);
jbd2_journal_clear_err(journal);
}
@@ -3257,29 +3299,15 @@ int ext4_force_commit(struct super_block *sb)
return 0;
journal = EXT4_SB(sb)->s_journal;
- if (journal) {
- sb->s_dirt = 0;
+ if (journal)
ret = ext4_journal_force_commit(journal);
- }
return ret;
}
-/*
- * Ext4 always journals updates to the superblock itself, so we don't
- * have to propagate any other updates to the superblock on disk at this
- * point. (We can probably nuke this function altogether, and remove
- * any mention to sb->s_dirt in all of fs/ext4; eventual cleanup...)
- */
static void ext4_write_super(struct super_block *sb)
{
- if (EXT4_SB(sb)->s_journal) {
- if (mutex_trylock(&sb->s_lock) != 0)
- BUG();
- sb->s_dirt = 0;
- } else {
- ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1);
- }
+ ext4_commit_super(sb, 1);
}
static int ext4_sync_fs(struct super_block *sb, int wait)
@@ -3288,16 +3316,9 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
tid_t target;
trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait);
- sb->s_dirt = 0;
- if (EXT4_SB(sb)->s_journal) {
- if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal,
- &target)) {
- if (wait)
- jbd2_log_wait_commit(EXT4_SB(sb)->s_journal,
- target);
- }
- } else {
- ext4_commit_super(sb, EXT4_SB(sb)->s_es, wait);
+ if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) {
+ if (wait)
+ jbd2_log_wait_commit(EXT4_SB(sb)->s_journal, target);
}
return ret;
}
@@ -3310,34 +3331,32 @@ static int ext4_freeze(struct super_block *sb)
{
int error = 0;
journal_t *journal;
- sb->s_dirt = 0;
- if (!(sb->s_flags & MS_RDONLY)) {
- journal = EXT4_SB(sb)->s_journal;
+ if (sb->s_flags & MS_RDONLY)
+ return 0;
- if (journal) {
- /* Now we set up the journal barrier. */
- jbd2_journal_lock_updates(journal);
+ journal = EXT4_SB(sb)->s_journal;
- /*
- * We don't want to clear needs_recovery flag when we
- * failed to flush the journal.
- */
- error = jbd2_journal_flush(journal);
- if (error < 0)
- goto out;
- }
+ /* Now we set up the journal barrier. */
+ jbd2_journal_lock_updates(journal);
- /* Journal blocked and flushed, clear needs_recovery flag. */
- EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
- error = ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1);
- if (error)
- goto out;
+ /*
+ * Don't clear the needs_recovery flag if we failed to flush
+ * the journal.
+ */
+ error = jbd2_journal_flush(journal);
+ if (error < 0) {
+ out:
+ jbd2_journal_unlock_updates(journal);
+ return error;
}
+
+ /* Journal blocked and flushed, clear needs_recovery flag. */
+ EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+ error = ext4_commit_super(sb, 1);
+ if (error)
+ goto out;
return 0;
-out:
- jbd2_journal_unlock_updates(journal);
- return error;
}
/*
@@ -3346,14 +3365,15 @@ out:
*/
static int ext4_unfreeze(struct super_block *sb)
{
- if (EXT4_SB(sb)->s_journal && !(sb->s_flags & MS_RDONLY)) {
- lock_super(sb);
- /* Reser the needs_recovery flag before the fs is unlocked. */
- EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
- ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1);
- unlock_super(sb);
- jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
- }
+ if (sb->s_flags & MS_RDONLY)
+ return 0;
+
+ lock_super(sb);
+ /* Reset the needs_recovery flag before the fs is unlocked. */
+ EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+ ext4_commit_super(sb, 1);
+ unlock_super(sb);
+ jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
return 0;
}
@@ -3372,6 +3392,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
#endif
/* Store the original options */
+ lock_super(sb);
old_sb_flags = sb->s_flags;
old_opts.s_mount_opt = sbi->s_mount_opt;
old_opts.s_resuid = sbi->s_resuid;
@@ -3432,15 +3453,8 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
(sbi->s_mount_state & EXT4_VALID_FS))
es->s_state = cpu_to_le16(sbi->s_mount_state);
- /*
- * We have to unlock super so that we can wait for
- * transactions.
- */
- if (sbi->s_journal) {
- unlock_super(sb);
+ if (sbi->s_journal)
ext4_mark_recovery_complete(sb, es);
- lock_super(sb);
- }
} else {
int ret;
if ((ret = EXT4_HAS_RO_COMPAT_FEATURE(sb,
@@ -3505,7 +3519,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
}
}
if (sbi->s_journal == NULL)
- ext4_commit_super(sb, es, 1);
+ ext4_commit_super(sb, 1);
#ifdef CONFIG_QUOTA
/* Release old quota file names */
@@ -3514,6 +3528,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
old_opts.s_qf_names[i] != sbi->s_qf_names[i])
kfree(old_opts.s_qf_names[i]);
#endif
+ unlock_super(sb);
return 0;
restore_opts:
sb->s_flags = old_sb_flags;
@@ -3532,6 +3547,7 @@ restore_opts:
sbi->s_qf_names[i] = old_opts.s_qf_names[i];
}
#endif
+ unlock_super(sb);
return err;
}
@@ -3545,9 +3561,8 @@ 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 != ext4_blocks_count(es)) {
- ext4_group_t ngroups = sbi->s_groups_count, i;
+ ext4_group_t i, ngroups = ext4_get_groups_count(sb);
ext4_fsblk_t overhead = 0;
- smp_rmb();
/*
* Compute the overhead (FS structures). This is constant
diff --git a/fs/fat/Kconfig b/fs/fat/Kconfig
index d0a69ff25375..182f9ffe2b51 100644
--- a/fs/fat/Kconfig
+++ b/fs/fat/Kconfig
@@ -95,3 +95,6 @@ config FAT_DEFAULT_IOCHARSET
Note that "utf8" is not recommended for FAT filesystems.
If unsure, you shouldn't set "utf8" here.
See <file:Documentation/filesystems/vfat.txt> for more information.
+
+ Enable any character sets you need in File Systems/Native Language
+ Support.
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 296785a0dec8..2b88c93af227 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -451,6 +451,11 @@ static void fat_put_super(struct super_block *sb)
{
struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ lock_kernel();
+
+ if (sb->s_dirt)
+ fat_write_super(sb);
+
if (sbi->nls_disk) {
unload_nls(sbi->nls_disk);
sbi->nls_disk = NULL;
@@ -467,6 +472,8 @@ static void fat_put_super(struct super_block *sb)
sb->s_fs_info = NULL;
kfree(sbi);
+
+ unlock_kernel();
}
static struct kmem_cache *fat_inode_cachep;
diff --git a/fs/fcntl.c b/fs/fcntl.c
index cc8e4de2fee5..1ad703150dee 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -117,11 +117,13 @@ SYSCALL_DEFINE2(dup2, unsigned int, oldfd, unsigned int, newfd)
{
if (unlikely(newfd == oldfd)) { /* corner case */
struct files_struct *files = current->files;
+ int retval = oldfd;
+
rcu_read_lock();
if (!fcheck_files(files, oldfd))
- oldfd = -EBADF;
+ retval = -EBADF;
rcu_read_unlock();
- return oldfd;
+ return retval;
}
return sys_dup3(oldfd, newfd, 0);
}
diff --git a/fs/file_table.c b/fs/file_table.c
index 54018fe48840..334ce39881f8 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -214,7 +214,7 @@ int init_file(struct file *file, struct vfsmount *mnt, struct dentry *dentry,
*/
if ((mode & FMODE_WRITE) && !special_file(dentry->d_inode->i_mode)) {
file_take_write(file);
- error = mnt_want_write(mnt);
+ error = mnt_clone_write(mnt);
WARN_ON(error);
}
return error;
@@ -399,6 +399,44 @@ too_bad:
return 0;
}
+/**
+ * mark_files_ro - mark all files read-only
+ * @sb: superblock in question
+ *
+ * All files are marked read-only. We don't care about pending
+ * delete files so this should be used in 'force' mode only.
+ */
+void mark_files_ro(struct super_block *sb)
+{
+ struct file *f;
+
+retry:
+ file_list_lock();
+ list_for_each_entry(f, &sb->s_files, f_u.fu_list) {
+ struct vfsmount *mnt;
+ if (!S_ISREG(f->f_path.dentry->d_inode->i_mode))
+ continue;
+ if (!file_count(f))
+ continue;
+ if (!(f->f_mode & FMODE_WRITE))
+ continue;
+ f->f_mode &= ~FMODE_WRITE;
+ if (file_check_writeable(f) != 0)
+ continue;
+ file_release_write(f);
+ mnt = mntget(f->f_path.mnt);
+ file_list_unlock();
+ /*
+ * This can sleep, so we can't hold
+ * the file_list_lock() spinlock.
+ */
+ mnt_drop_write(mnt);
+ mntput(mnt);
+ goto retry;
+ }
+ file_list_unlock();
+}
+
void __init files_init(unsigned long mempages)
{
int n;
diff --git a/fs/filesystems.c b/fs/filesystems.c
index 1aa70260e6d1..a24c58e181db 100644
--- a/fs/filesystems.c
+++ b/fs/filesystems.c
@@ -199,7 +199,7 @@ SYSCALL_DEFINE3(sysfs, int, option, unsigned long, arg1, unsigned long, arg2)
return retval;
}
-int get_filesystem_list(char * buf)
+int __init get_filesystem_list(char *buf)
{
int len = 0;
struct file_system_type * tmp;
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index 1dacda831577..cdbd1654e4cd 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -80,12 +80,16 @@ vxfs_put_super(struct super_block *sbp)
{
struct vxfs_sb_info *infp = VXFS_SBI(sbp);
+ lock_kernel();
+
vxfs_put_fake_inode(infp->vsi_fship);
vxfs_put_fake_inode(infp->vsi_ilist);
vxfs_put_fake_inode(infp->vsi_stilist);
brelse(infp->vsi_bp);
kfree(infp);
+
+ unlock_kernel();
}
/**
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 91013ff7dd53..e0fb2e789598 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -679,55 +679,6 @@ void sync_inodes_sb(struct super_block *sb, int wait)
}
/**
- * sync_inodes - writes all inodes to disk
- * @wait: wait for completion
- *
- * sync_inodes() goes through each super block's dirty inode list, writes the
- * inodes out, waits on the writeout and puts the inodes back on the normal
- * list.
- *
- * This is for sys_sync(). fsync_dev() uses the same algorithm. The subtle
- * part of the sync functions is that the blockdev "superblock" is processed
- * last. This is because the write_inode() function of a typical fs will
- * perform no I/O, but will mark buffers in the blockdev mapping as dirty.
- * What we want to do is to perform all that dirtying first, and then write
- * back all those inode blocks via the blockdev mapping in one sweep. So the
- * additional (somewhat redundant) sync_blockdev() calls here are to make
- * sure that really happens. Because if we call sync_inodes_sb(wait=1) with
- * outstanding dirty inodes, the writeback goes block-at-a-time within the
- * filesystem's write_inode(). This is extremely slow.
- */
-static void __sync_inodes(int wait)
-{
- struct super_block *sb;
-
- spin_lock(&sb_lock);
-restart:
- list_for_each_entry(sb, &super_blocks, s_list) {
- sb->s_count++;
- spin_unlock(&sb_lock);
- down_read(&sb->s_umount);
- if (sb->s_root) {
- sync_inodes_sb(sb, wait);
- sync_blockdev(sb->s_bdev);
- }
- up_read(&sb->s_umount);
- spin_lock(&sb_lock);
- if (__put_super_and_need_restart(sb))
- goto restart;
- }
- spin_unlock(&sb_lock);
-}
-
-void sync_inodes(int wait)
-{
- __sync_inodes(0);
-
- if (wait)
- __sync_inodes(1);
-}
-
-/**
* write_inode_now - write an inode to disk
* @inode: inode to write to disk
* @sync: whether the write should be synchronous or not
diff --git a/fs/fuse/Makefile b/fs/fuse/Makefile
index 72437065f6ad..e95eeb445e58 100644
--- a/fs/fuse/Makefile
+++ b/fs/fuse/Makefile
@@ -3,5 +3,6 @@
#
obj-$(CONFIG_FUSE_FS) += fuse.o
+obj-$(CONFIG_CUSE) += cuse.o
fuse-objs := dev.o dir.o file.o inode.o control.o
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
new file mode 100644
index 000000000000..de792dcf3274
--- /dev/null
+++ b/fs/fuse/cuse.c
@@ -0,0 +1,610 @@
+/*
+ * CUSE: Character device in Userspace
+ *
+ * Copyright (C) 2008-2009 SUSE Linux Products GmbH
+ * Copyright (C) 2008-2009 Tejun Heo <tj@kernel.org>
+ *
+ * This file is released under the GPLv2.
+ *
+ * CUSE enables character devices to be implemented from userland much
+ * like FUSE allows filesystems. On initialization /dev/cuse is
+ * created. By opening the file and replying to the CUSE_INIT request
+ * userland CUSE server can create a character device. After that the
+ * operation is very similar to FUSE.
+ *
+ * A CUSE instance involves the following objects.
+ *
+ * cuse_conn : contains fuse_conn and serves as bonding structure
+ * channel : file handle connected to the userland CUSE server
+ * cdev : the implemented character device
+ * dev : generic device for cdev
+ *
+ * Note that 'channel' is what 'dev' is in FUSE. As CUSE deals with
+ * devices, it's called 'channel' to reduce confusion.
+ *
+ * channel determines when the character device dies. When channel is
+ * closed, everything begins to destruct. The cuse_conn is taken off
+ * the lookup table preventing further access from cdev, cdev and
+ * generic device are removed and the base reference of cuse_conn is
+ * put.
+ *
+ * On each open, the matching cuse_conn is looked up and if found an
+ * additional reference is taken which is released when the file is
+ * closed.
+ */
+
+#include <linux/fuse.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/kdev_t.h>
+#include <linux/kthread.h>
+#include <linux/list.h>
+#include <linux/magic.h>
+#include <linux/miscdevice.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/stat.h>
+
+#include "fuse_i.h"
+
+#define CUSE_CONNTBL_LEN 64
+
+struct cuse_conn {
+ struct list_head list; /* linked on cuse_conntbl */
+ struct fuse_conn fc; /* fuse connection */
+ struct cdev *cdev; /* associated character device */
+ struct device *dev; /* device representing @cdev */
+
+ /* init parameters, set once during initialization */
+ bool unrestricted_ioctl;
+};
+
+static DEFINE_SPINLOCK(cuse_lock); /* protects cuse_conntbl */
+static struct list_head cuse_conntbl[CUSE_CONNTBL_LEN];
+static struct class *cuse_class;
+
+static struct cuse_conn *fc_to_cc(struct fuse_conn *fc)
+{
+ return container_of(fc, struct cuse_conn, fc);
+}
+
+static struct list_head *cuse_conntbl_head(dev_t devt)
+{
+ return &cuse_conntbl[(MAJOR(devt) + MINOR(devt)) % CUSE_CONNTBL_LEN];
+}
+
+
+/**************************************************************************
+ * CUSE frontend operations
+ *
+ * These are file operations for the character device.
+ *
+ * On open, CUSE opens a file from the FUSE mnt and stores it to
+ * private_data of the open file. All other ops call FUSE ops on the
+ * FUSE file.
+ */
+
+static ssize_t cuse_read(struct file *file, char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ loff_t pos = 0;
+
+ return fuse_direct_io(file, buf, count, &pos, 0);
+}
+
+static ssize_t cuse_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ loff_t pos = 0;
+ /*
+ * No locking or generic_write_checks(), the server is
+ * responsible for locking and sanity checks.
+ */
+ return fuse_direct_io(file, buf, count, &pos, 1);
+}
+
+static int cuse_open(struct inode *inode, struct file *file)
+{
+ dev_t devt = inode->i_cdev->dev;
+ struct cuse_conn *cc = NULL, *pos;
+ int rc;
+
+ /* look up and get the connection */
+ spin_lock(&cuse_lock);
+ list_for_each_entry(pos, cuse_conntbl_head(devt), list)
+ if (pos->dev->devt == devt) {
+ fuse_conn_get(&pos->fc);
+ cc = pos;
+ break;
+ }
+ spin_unlock(&cuse_lock);
+
+ /* dead? */
+ if (!cc)
+ return -ENODEV;
+
+ /*
+ * Generic permission check is already done against the chrdev
+ * file, proceed to open.
+ */
+ rc = fuse_do_open(&cc->fc, 0, file, 0);
+ if (rc)
+ fuse_conn_put(&cc->fc);
+ return rc;
+}
+
+static int cuse_release(struct inode *inode, struct file *file)
+{
+ struct fuse_file *ff = file->private_data;
+ struct fuse_conn *fc = ff->fc;
+
+ fuse_sync_release(ff, file->f_flags);
+ fuse_conn_put(fc);
+
+ return 0;
+}
+
+static long cuse_file_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct fuse_file *ff = file->private_data;
+ struct cuse_conn *cc = fc_to_cc(ff->fc);
+ unsigned int flags = 0;
+
+ if (cc->unrestricted_ioctl)
+ flags |= FUSE_IOCTL_UNRESTRICTED;
+
+ return fuse_do_ioctl(file, cmd, arg, flags);
+}
+
+static long cuse_file_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct fuse_file *ff = file->private_data;
+ struct cuse_conn *cc = fc_to_cc(ff->fc);
+ unsigned int flags = FUSE_IOCTL_COMPAT;
+
+ if (cc->unrestricted_ioctl)
+ flags |= FUSE_IOCTL_UNRESTRICTED;
+
+ return fuse_do_ioctl(file, cmd, arg, flags);
+}
+
+static const struct file_operations cuse_frontend_fops = {
+ .owner = THIS_MODULE,
+ .read = cuse_read,
+ .write = cuse_write,
+ .open = cuse_open,
+ .release = cuse_release,
+ .unlocked_ioctl = cuse_file_ioctl,
+ .compat_ioctl = cuse_file_compat_ioctl,
+ .poll = fuse_file_poll,
+};
+
+
+/**************************************************************************
+ * CUSE channel initialization and destruction
+ */
+
+struct cuse_devinfo {
+ const char *name;
+};
+
+/**
+ * cuse_parse_one - parse one key=value pair
+ * @pp: i/o parameter for the current position
+ * @end: points to one past the end of the packed string
+ * @keyp: out parameter for key
+ * @valp: out parameter for value
+ *
+ * *@pp points to packed strings - "key0=val0\0key1=val1\0" which ends
+ * at @end - 1. This function parses one pair and set *@keyp to the
+ * start of the key and *@valp to the start of the value. Note that
+ * the original string is modified such that the key string is
+ * terminated with '\0'. *@pp is updated to point to the next string.
+ *
+ * RETURNS:
+ * 1 on successful parse, 0 on EOF, -errno on failure.
+ */
+static int cuse_parse_one(char **pp, char *end, char **keyp, char **valp)
+{
+ char *p = *pp;
+ char *key, *val;
+
+ while (p < end && *p == '\0')
+ p++;
+ if (p == end)
+ return 0;
+
+ if (end[-1] != '\0') {
+ printk(KERN_ERR "CUSE: info not properly terminated\n");
+ return -EINVAL;
+ }
+
+ key = val = p;
+ p += strlen(p);
+
+ if (valp) {
+ strsep(&val, "=");
+ if (!val)
+ val = key + strlen(key);
+ key = strstrip(key);
+ val = strstrip(val);
+ } else
+ key = strstrip(key);
+
+ if (!strlen(key)) {
+ printk(KERN_ERR "CUSE: zero length info key specified\n");
+ return -EINVAL;
+ }
+
+ *pp = p;
+ *keyp = key;
+ if (valp)
+ *valp = val;
+
+ return 1;
+}
+
+/**
+ * cuse_parse_dev_info - parse device info
+ * @p: device info string
+ * @len: length of device info string
+ * @devinfo: out parameter for parsed device info
+ *
+ * Parse @p to extract device info and store it into @devinfo. String
+ * pointed to by @p is modified by parsing and @devinfo points into
+ * them, so @p shouldn't be freed while @devinfo is in use.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+static int cuse_parse_devinfo(char *p, size_t len, struct cuse_devinfo *devinfo)
+{
+ char *end = p + len;
+ char *key, *val;
+ int rc;
+
+ while (true) {
+ rc = cuse_parse_one(&p, end, &key, &val);
+ if (rc < 0)
+ return rc;
+ if (!rc)
+ break;
+ if (strcmp(key, "DEVNAME") == 0)
+ devinfo->name = val;
+ else
+ printk(KERN_WARNING "CUSE: unknown device info \"%s\"\n",
+ key);
+ }
+
+ if (!devinfo->name || !strlen(devinfo->name)) {
+ printk(KERN_ERR "CUSE: DEVNAME unspecified\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void cuse_gendev_release(struct device *dev)
+{
+ kfree(dev);
+}
+
+/**
+ * cuse_process_init_reply - finish initializing CUSE channel
+ *
+ * This function creates the character device and sets up all the
+ * required data structures for it. Please read the comment at the
+ * top of this file for high level overview.
+ */
+static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
+{
+ struct cuse_conn *cc = fc_to_cc(fc);
+ struct cuse_init_out *arg = &req->misc.cuse_init_out;
+ struct page *page = req->pages[0];
+ struct cuse_devinfo devinfo = { };
+ struct device *dev;
+ struct cdev *cdev;
+ dev_t devt;
+ int rc;
+
+ if (req->out.h.error ||
+ arg->major != FUSE_KERNEL_VERSION || arg->minor < 11) {
+ goto err;
+ }
+
+ fc->minor = arg->minor;
+ fc->max_read = max_t(unsigned, arg->max_read, 4096);
+ fc->max_write = max_t(unsigned, arg->max_write, 4096);
+
+ /* parse init reply */
+ cc->unrestricted_ioctl = arg->flags & CUSE_UNRESTRICTED_IOCTL;
+
+ rc = cuse_parse_devinfo(page_address(page), req->out.args[1].size,
+ &devinfo);
+ if (rc)
+ goto err;
+
+ /* determine and reserve devt */
+ devt = MKDEV(arg->dev_major, arg->dev_minor);
+ if (!MAJOR(devt))
+ rc = alloc_chrdev_region(&devt, MINOR(devt), 1, devinfo.name);
+ else
+ rc = register_chrdev_region(devt, 1, devinfo.name);
+ if (rc) {
+ printk(KERN_ERR "CUSE: failed to register chrdev region\n");
+ goto err;
+ }
+
+ /* devt determined, create device */
+ rc = -ENOMEM;
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ goto err_region;
+
+ device_initialize(dev);
+ dev_set_uevent_suppress(dev, 1);
+ dev->class = cuse_class;
+ dev->devt = devt;
+ dev->release = cuse_gendev_release;
+ dev_set_drvdata(dev, cc);
+ dev_set_name(dev, "%s", devinfo.name);
+
+ rc = device_add(dev);
+ if (rc)
+ goto err_device;
+
+ /* register cdev */
+ rc = -ENOMEM;
+ cdev = cdev_alloc();
+ if (!cdev)
+ goto err_device;
+
+ cdev->owner = THIS_MODULE;
+ cdev->ops = &cuse_frontend_fops;
+
+ rc = cdev_add(cdev, devt, 1);
+ if (rc)
+ goto err_cdev;
+
+ cc->dev = dev;
+ cc->cdev = cdev;
+
+ /* make the device available */
+ spin_lock(&cuse_lock);
+ list_add(&cc->list, cuse_conntbl_head(devt));
+ spin_unlock(&cuse_lock);
+
+ /* announce device availability */
+ dev_set_uevent_suppress(dev, 0);
+ kobject_uevent(&dev->kobj, KOBJ_ADD);
+out:
+ __free_page(page);
+ return;
+
+err_cdev:
+ cdev_del(cdev);
+err_device:
+ put_device(dev);
+err_region:
+ unregister_chrdev_region(devt, 1);
+err:
+ fc->conn_error = 1;
+ goto out;
+}
+
+static int cuse_send_init(struct cuse_conn *cc)
+{
+ int rc;
+ struct fuse_req *req;
+ struct page *page;
+ struct fuse_conn *fc = &cc->fc;
+ struct cuse_init_in *arg;
+
+ BUILD_BUG_ON(CUSE_INIT_INFO_MAX > PAGE_SIZE);
+
+ req = fuse_get_req(fc);
+ if (IS_ERR(req)) {
+ rc = PTR_ERR(req);
+ goto err;
+ }
+
+ rc = -ENOMEM;
+ page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+ if (!page)
+ goto err_put_req;
+
+ arg = &req->misc.cuse_init_in;
+ arg->major = FUSE_KERNEL_VERSION;
+ arg->minor = FUSE_KERNEL_MINOR_VERSION;
+ arg->flags |= CUSE_UNRESTRICTED_IOCTL;
+ req->in.h.opcode = CUSE_INIT;
+ req->in.numargs = 1;
+ req->in.args[0].size = sizeof(struct cuse_init_in);
+ req->in.args[0].value = arg;
+ req->out.numargs = 2;
+ req->out.args[0].size = sizeof(struct cuse_init_out);
+ req->out.args[0].value = &req->misc.cuse_init_out;
+ req->out.args[1].size = CUSE_INIT_INFO_MAX;
+ req->out.argvar = 1;
+ req->out.argpages = 1;
+ req->pages[0] = page;
+ req->num_pages = 1;
+ req->end = cuse_process_init_reply;
+ fuse_request_send_background(fc, req);
+
+ return 0;
+
+err_put_req:
+ fuse_put_request(fc, req);
+err:
+ return rc;
+}
+
+static void cuse_fc_release(struct fuse_conn *fc)
+{
+ struct cuse_conn *cc = fc_to_cc(fc);
+ kfree(cc);
+}
+
+/**
+ * cuse_channel_open - open method for /dev/cuse
+ * @inode: inode for /dev/cuse
+ * @file: file struct being opened
+ *
+ * Userland CUSE server can create a CUSE device by opening /dev/cuse
+ * and replying to the initilaization request kernel sends. This
+ * function is responsible for handling CUSE device initialization.
+ * Because the fd opened by this function is used during
+ * initialization, this function only creates cuse_conn and sends
+ * init. The rest is delegated to a kthread.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+static int cuse_channel_open(struct inode *inode, struct file *file)
+{
+ struct cuse_conn *cc;
+ int rc;
+
+ /* set up cuse_conn */
+ cc = kzalloc(sizeof(*cc), GFP_KERNEL);
+ if (!cc)
+ return -ENOMEM;
+
+ fuse_conn_init(&cc->fc);
+
+ INIT_LIST_HEAD(&cc->list);
+ cc->fc.release = cuse_fc_release;
+
+ cc->fc.connected = 1;
+ cc->fc.blocked = 0;
+ rc = cuse_send_init(cc);
+ if (rc) {
+ fuse_conn_put(&cc->fc);
+ return rc;
+ }
+ file->private_data = &cc->fc; /* channel owns base reference to cc */
+
+ return 0;
+}
+
+/**
+ * cuse_channel_release - release method for /dev/cuse
+ * @inode: inode for /dev/cuse
+ * @file: file struct being closed
+ *
+ * Disconnect the channel, deregister CUSE device and initiate
+ * destruction by putting the default reference.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+static int cuse_channel_release(struct inode *inode, struct file *file)
+{
+ struct cuse_conn *cc = fc_to_cc(file->private_data);
+ int rc;
+
+ /* remove from the conntbl, no more access from this point on */
+ spin_lock(&cuse_lock);
+ list_del_init(&cc->list);
+ spin_unlock(&cuse_lock);
+
+ /* remove device */
+ if (cc->dev)
+ device_unregister(cc->dev);
+ if (cc->cdev) {
+ unregister_chrdev_region(cc->cdev->dev, 1);
+ cdev_del(cc->cdev);
+ }
+
+ /* kill connection and shutdown channel */
+ fuse_conn_kill(&cc->fc);
+ rc = fuse_dev_release(inode, file); /* puts the base reference */
+
+ return rc;
+}
+
+static struct file_operations cuse_channel_fops; /* initialized during init */
+
+
+/**************************************************************************
+ * Misc stuff and module initializatiion
+ *
+ * CUSE exports the same set of attributes to sysfs as fusectl.
+ */
+
+static ssize_t cuse_class_waiting_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct cuse_conn *cc = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", atomic_read(&cc->fc.num_waiting));
+}
+
+static ssize_t cuse_class_abort_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct cuse_conn *cc = dev_get_drvdata(dev);
+
+ fuse_abort_conn(&cc->fc);
+ return count;
+}
+
+static struct device_attribute cuse_class_dev_attrs[] = {
+ __ATTR(waiting, S_IFREG | 0400, cuse_class_waiting_show, NULL),
+ __ATTR(abort, S_IFREG | 0200, NULL, cuse_class_abort_store),
+ { }
+};
+
+static struct miscdevice cuse_miscdev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "cuse",
+ .fops = &cuse_channel_fops,
+};
+
+static int __init cuse_init(void)
+{
+ int i, rc;
+
+ /* init conntbl */
+ for (i = 0; i < CUSE_CONNTBL_LEN; i++)
+ INIT_LIST_HEAD(&cuse_conntbl[i]);
+
+ /* inherit and extend fuse_dev_operations */
+ cuse_channel_fops = fuse_dev_operations;
+ cuse_channel_fops.owner = THIS_MODULE;
+ cuse_channel_fops.open = cuse_channel_open;
+ cuse_channel_fops.release = cuse_channel_release;
+
+ cuse_class = class_create(THIS_MODULE, "cuse");
+ if (IS_ERR(cuse_class))
+ return PTR_ERR(cuse_class);
+
+ cuse_class->dev_attrs = cuse_class_dev_attrs;
+
+ rc = misc_register(&cuse_miscdev);
+ if (rc) {
+ class_destroy(cuse_class);
+ return rc;
+ }
+
+ return 0;
+}
+
+static void __exit cuse_exit(void)
+{
+ misc_deregister(&cuse_miscdev);
+ class_destroy(cuse_class);
+}
+
+module_init(cuse_init);
+module_exit(cuse_exit);
+
+MODULE_AUTHOR("Tejun Heo <tj@kernel.org>");
+MODULE_DESCRIPTION("Character device in Userspace");
+MODULE_LICENSE("GPL");
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index ba76b68c52ff..8fed2ed12f38 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -46,6 +46,7 @@ struct fuse_req *fuse_request_alloc(void)
fuse_request_init(req);
return req;
}
+EXPORT_SYMBOL_GPL(fuse_request_alloc);
struct fuse_req *fuse_request_alloc_nofs(void)
{
@@ -124,6 +125,7 @@ struct fuse_req *fuse_get_req(struct fuse_conn *fc)
atomic_dec(&fc->num_waiting);
return ERR_PTR(err);
}
+EXPORT_SYMBOL_GPL(fuse_get_req);
/*
* Return request in fuse_file->reserved_req. However that may
@@ -208,6 +210,7 @@ void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
fuse_request_free(req);
}
}
+EXPORT_SYMBOL_GPL(fuse_put_request);
static unsigned len_args(unsigned numargs, struct fuse_arg *args)
{
@@ -282,7 +285,7 @@ __releases(&fc->lock)
wake_up_all(&fc->blocked_waitq);
}
if (fc->num_background == FUSE_CONGESTION_THRESHOLD &&
- fc->connected) {
+ fc->connected && fc->bdi_initialized) {
clear_bdi_congested(&fc->bdi, READ);
clear_bdi_congested(&fc->bdi, WRITE);
}
@@ -400,6 +403,7 @@ void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req)
}
spin_unlock(&fc->lock);
}
+EXPORT_SYMBOL_GPL(fuse_request_send);
static void fuse_request_send_nowait_locked(struct fuse_conn *fc,
struct fuse_req *req)
@@ -408,7 +412,8 @@ static void fuse_request_send_nowait_locked(struct fuse_conn *fc,
fc->num_background++;
if (fc->num_background == FUSE_MAX_BACKGROUND)
fc->blocked = 1;
- if (fc->num_background == FUSE_CONGESTION_THRESHOLD) {
+ if (fc->num_background == FUSE_CONGESTION_THRESHOLD &&
+ fc->bdi_initialized) {
set_bdi_congested(&fc->bdi, READ);
set_bdi_congested(&fc->bdi, WRITE);
}
@@ -439,6 +444,7 @@ void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req)
req->isreply = 1;
fuse_request_send_nowait(fc, req);
}
+EXPORT_SYMBOL_GPL(fuse_request_send_background);
/*
* Called under fc->lock
@@ -1105,8 +1111,9 @@ void fuse_abort_conn(struct fuse_conn *fc)
}
spin_unlock(&fc->lock);
}
+EXPORT_SYMBOL_GPL(fuse_abort_conn);
-static int fuse_dev_release(struct inode *inode, struct file *file)
+int fuse_dev_release(struct inode *inode, struct file *file)
{
struct fuse_conn *fc = fuse_get_conn(file);
if (fc) {
@@ -1120,6 +1127,7 @@ static int fuse_dev_release(struct inode *inode, struct file *file)
return 0;
}
+EXPORT_SYMBOL_GPL(fuse_dev_release);
static int fuse_dev_fasync(int fd, struct file *file, int on)
{
@@ -1142,6 +1150,7 @@ const struct file_operations fuse_dev_operations = {
.release = fuse_dev_release,
.fasync = fuse_dev_fasync,
};
+EXPORT_SYMBOL_GPL(fuse_dev_operations);
static struct miscdevice fuse_miscdevice = {
.minor = FUSE_MINOR,
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 8b8eebc5614b..b3089a083d30 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -362,19 +362,6 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
}
/*
- * Synchronous release for the case when something goes wrong in CREATE_OPEN
- */
-static void fuse_sync_release(struct fuse_conn *fc, struct fuse_file *ff,
- u64 nodeid, int flags)
-{
- fuse_release_fill(ff, nodeid, flags, FUSE_RELEASE);
- ff->reserved_req->force = 1;
- fuse_request_send(fc, ff->reserved_req);
- fuse_put_request(fc, ff->reserved_req);
- kfree(ff);
-}
-
-/*
* Atomic create+open operation
*
* If the filesystem doesn't support this, then fall back to separate
@@ -445,12 +432,14 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
goto out_free_ff;
fuse_put_request(fc, req);
+ ff->fh = outopen.fh;
+ ff->nodeid = outentry.nodeid;
+ ff->open_flags = outopen.open_flags;
inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
&outentry.attr, entry_attr_timeout(&outentry), 0);
if (!inode) {
flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
- ff->fh = outopen.fh;
- fuse_sync_release(fc, ff, outentry.nodeid, flags);
+ fuse_sync_release(ff, flags);
fuse_send_forget(fc, forget_req, outentry.nodeid, 1);
return -ENOMEM;
}
@@ -460,11 +449,11 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
fuse_invalidate_attr(dir);
file = lookup_instantiate_filp(nd, entry, generic_file_open);
if (IS_ERR(file)) {
- ff->fh = outopen.fh;
- fuse_sync_release(fc, ff, outentry.nodeid, flags);
+ fuse_sync_release(ff, flags);
return PTR_ERR(file);
}
- fuse_finish_open(inode, file, ff, &outopen);
+ file->private_data = fuse_file_get(ff);
+ fuse_finish_open(inode, file);
return 0;
out_free_ff:
@@ -1035,7 +1024,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
req->out.argpages = 1;
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, file, file->f_pos, PAGE_SIZE, FUSE_READDIR);
fuse_request_send(fc, req);
nbytes = req->out.args[0].size;
err = req->out.h.error;
@@ -1101,12 +1090,14 @@ static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
static int fuse_dir_open(struct inode *inode, struct file *file)
{
- return fuse_open_common(inode, file, 1);
+ return fuse_open_common(inode, file, true);
}
static int fuse_dir_release(struct inode *inode, struct file *file)
{
- return fuse_release_common(inode, file, 1);
+ fuse_release_common(file, FUSE_RELEASEDIR);
+
+ return 0;
}
static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 2b25133524a3..fce6ce694fde 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -12,13 +12,13 @@
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/module.h>
static const struct file_operations fuse_direct_io_file_operations;
-static int fuse_send_open(struct inode *inode, struct file *file, int isdir,
- struct fuse_open_out *outargp)
+static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
+ int opcode, struct fuse_open_out *outargp)
{
- struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_open_in inarg;
struct fuse_req *req;
int err;
@@ -31,8 +31,8 @@ static int fuse_send_open(struct inode *inode, struct file *file, int isdir,
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.h.opcode = opcode;
+ req->in.h.nodeid = nodeid;
req->in.numargs = 1;
req->in.args[0].size = sizeof(inarg);
req->in.args[0].value = &inarg;
@@ -49,22 +49,27 @@ static int fuse_send_open(struct inode *inode, struct file *file, int isdir,
struct fuse_file *fuse_file_alloc(struct fuse_conn *fc)
{
struct fuse_file *ff;
+
ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL);
- if (ff) {
- ff->reserved_req = fuse_request_alloc();
- if (!ff->reserved_req) {
- kfree(ff);
- return NULL;
- } else {
- INIT_LIST_HEAD(&ff->write_entry);
- atomic_set(&ff->count, 0);
- spin_lock(&fc->lock);
- ff->kh = ++fc->khctr;
- spin_unlock(&fc->lock);
- }
- RB_CLEAR_NODE(&ff->polled_node);
- init_waitqueue_head(&ff->poll_wait);
+ if (unlikely(!ff))
+ return NULL;
+
+ ff->fc = fc;
+ ff->reserved_req = fuse_request_alloc();
+ if (unlikely(!ff->reserved_req)) {
+ kfree(ff);
+ return NULL;
}
+
+ INIT_LIST_HEAD(&ff->write_entry);
+ atomic_set(&ff->count, 0);
+ RB_CLEAR_NODE(&ff->polled_node);
+ init_waitqueue_head(&ff->poll_wait);
+
+ spin_lock(&fc->lock);
+ ff->kh = ++fc->khctr;
+ spin_unlock(&fc->lock);
+
return ff;
}
@@ -74,7 +79,7 @@ void fuse_file_free(struct fuse_file *ff)
kfree(ff);
}
-static struct fuse_file *fuse_file_get(struct fuse_file *ff)
+struct fuse_file *fuse_file_get(struct fuse_file *ff)
{
atomic_inc(&ff->count);
return ff;
@@ -82,40 +87,65 @@ static struct fuse_file *fuse_file_get(struct fuse_file *ff)
static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req)
{
- dput(req->misc.release.dentry);
- mntput(req->misc.release.vfsmount);
+ path_put(&req->misc.release.path);
}
static void fuse_file_put(struct fuse_file *ff)
{
if (atomic_dec_and_test(&ff->count)) {
struct fuse_req *req = ff->reserved_req;
- struct inode *inode = req->misc.release.dentry->d_inode;
- struct fuse_conn *fc = get_fuse_conn(inode);
+
req->end = fuse_release_end;
- fuse_request_send_background(fc, req);
+ fuse_request_send_background(ff->fc, req);
kfree(ff);
}
}
-void fuse_finish_open(struct inode *inode, struct file *file,
- struct fuse_file *ff, struct fuse_open_out *outarg)
+int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
+ bool isdir)
{
- if (outarg->open_flags & FOPEN_DIRECT_IO)
+ struct fuse_open_out outarg;
+ struct fuse_file *ff;
+ int err;
+ int opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN;
+
+ ff = fuse_file_alloc(fc);
+ if (!ff)
+ return -ENOMEM;
+
+ err = fuse_send_open(fc, nodeid, file, opcode, &outarg);
+ if (err) {
+ fuse_file_free(ff);
+ return err;
+ }
+
+ if (isdir)
+ outarg.open_flags &= ~FOPEN_DIRECT_IO;
+
+ ff->fh = outarg.fh;
+ ff->nodeid = nodeid;
+ ff->open_flags = outarg.open_flags;
+ file->private_data = fuse_file_get(ff);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(fuse_do_open);
+
+void fuse_finish_open(struct inode *inode, struct file *file)
+{
+ struct fuse_file *ff = file->private_data;
+
+ if (ff->open_flags & FOPEN_DIRECT_IO)
file->f_op = &fuse_direct_io_file_operations;
- if (!(outarg->open_flags & FOPEN_KEEP_CACHE))
+ if (!(ff->open_flags & FOPEN_KEEP_CACHE))
invalidate_inode_pages2(inode->i_mapping);
- if (outarg->open_flags & FOPEN_NONSEEKABLE)
+ if (ff->open_flags & FOPEN_NONSEEKABLE)
nonseekable_open(inode, file);
- ff->fh = outarg->fh;
- file->private_data = fuse_file_get(ff);
}
-int fuse_open_common(struct inode *inode, struct file *file, int isdir)
+int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
{
struct fuse_conn *fc = get_fuse_conn(inode);
- struct fuse_open_out outarg;
- struct fuse_file *ff;
int err;
/* VFS checks this, but only _after_ ->open() */
@@ -126,78 +156,85 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir)
if (err)
return err;
- ff = fuse_file_alloc(fc);
- if (!ff)
- return -ENOMEM;
-
- err = fuse_send_open(inode, file, isdir, &outarg);
+ err = fuse_do_open(fc, get_node_id(inode), file, isdir);
if (err)
- fuse_file_free(ff);
- else {
- if (isdir)
- outarg.open_flags &= ~FOPEN_DIRECT_IO;
- fuse_finish_open(inode, file, ff, &outarg);
- }
+ return err;
- return err;
+ fuse_finish_open(inode, file);
+
+ return 0;
}
-void fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags, int opcode)
+static void fuse_prepare_release(struct fuse_file *ff, int flags, int opcode)
{
+ struct fuse_conn *fc = ff->fc;
struct fuse_req *req = ff->reserved_req;
struct fuse_release_in *inarg = &req->misc.release.in;
+ spin_lock(&fc->lock);
+ list_del(&ff->write_entry);
+ if (!RB_EMPTY_NODE(&ff->polled_node))
+ rb_erase(&ff->polled_node, &fc->polled_files);
+ spin_unlock(&fc->lock);
+
+ wake_up_interruptible_sync(&ff->poll_wait);
+
inarg->fh = ff->fh;
inarg->flags = flags;
req->in.h.opcode = opcode;
- req->in.h.nodeid = nodeid;
+ req->in.h.nodeid = ff->nodeid;
req->in.numargs = 1;
req->in.args[0].size = sizeof(struct fuse_release_in);
req->in.args[0].value = inarg;
}
-int fuse_release_common(struct inode *inode, struct file *file, int isdir)
+void fuse_release_common(struct file *file, int opcode)
{
- struct fuse_file *ff = file->private_data;
- if (ff) {
- struct fuse_conn *fc = get_fuse_conn(inode);
- struct fuse_req *req = ff->reserved_req;
-
- fuse_release_fill(ff, get_node_id(inode), file->f_flags,
- isdir ? FUSE_RELEASEDIR : FUSE_RELEASE);
+ struct fuse_file *ff;
+ struct fuse_req *req;
- /* Hold vfsmount and dentry until release is finished */
- req->misc.release.vfsmount = mntget(file->f_path.mnt);
- req->misc.release.dentry = dget(file->f_path.dentry);
+ ff = file->private_data;
+ if (unlikely(!ff))
+ return;
- spin_lock(&fc->lock);
- list_del(&ff->write_entry);
- if (!RB_EMPTY_NODE(&ff->polled_node))
- rb_erase(&ff->polled_node, &fc->polled_files);
- spin_unlock(&fc->lock);
+ req = ff->reserved_req;
+ fuse_prepare_release(ff, file->f_flags, opcode);
- wake_up_interruptible_sync(&ff->poll_wait);
- /*
- * 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);
- }
+ /* Hold vfsmount and dentry until release is finished */
+ path_get(&file->f_path);
+ req->misc.release.path = file->f_path;
- /* Return value is ignored by VFS */
- return 0;
+ /*
+ * 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);
}
static int fuse_open(struct inode *inode, struct file *file)
{
- return fuse_open_common(inode, file, 0);
+ return fuse_open_common(inode, file, false);
}
static int fuse_release(struct inode *inode, struct file *file)
{
- return fuse_release_common(inode, file, 0);
+ fuse_release_common(file, FUSE_RELEASE);
+
+ /* return value is ignored by VFS */
+ return 0;
+}
+
+void fuse_sync_release(struct fuse_file *ff, int flags)
+{
+ WARN_ON(atomic_read(&ff->count) > 1);
+ fuse_prepare_release(ff, flags, FUSE_RELEASE);
+ ff->reserved_req->force = 1;
+ fuse_request_send(ff->fc, ff->reserved_req);
+ fuse_put_request(ff->fc, ff->reserved_req);
+ kfree(ff);
}
+EXPORT_SYMBOL_GPL(fuse_sync_release);
/*
* Scramble the ID space with XTEA, so that the value of the files_struct
@@ -371,8 +408,8 @@ 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,
- struct inode *inode, loff_t pos, size_t count, int opcode)
+void fuse_read_fill(struct fuse_req *req, struct file *file, loff_t pos,
+ size_t count, int opcode)
{
struct fuse_read_in *inarg = &req->misc.read.in;
struct fuse_file *ff = file->private_data;
@@ -382,7 +419,7 @@ void fuse_read_fill(struct fuse_req *req, struct file *file,
inarg->size = count;
inarg->flags = file->f_flags;
req->in.h.opcode = opcode;
- req->in.h.nodeid = get_node_id(inode);
+ req->in.h.nodeid = ff->nodeid;
req->in.numargs = 1;
req->in.args[0].size = sizeof(struct fuse_read_in);
req->in.args[0].value = inarg;
@@ -392,12 +429,12 @@ 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,
- fl_owner_t owner)
+ loff_t pos, size_t count, fl_owner_t owner)
{
- struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_file *ff = file->private_data;
+ struct fuse_conn *fc = ff->fc;
- fuse_read_fill(req, file, inode, pos, count, FUSE_READ);
+ fuse_read_fill(req, file, pos, count, FUSE_READ);
if (owner != NULL) {
struct fuse_read_in *inarg = &req->misc.read.in;
@@ -455,7 +492,7 @@ static int fuse_readpage(struct file *file, struct page *page)
req->out.argpages = 1;
req->num_pages = 1;
req->pages[0] = page;
- num_read = fuse_send_read(req, file, inode, pos, count, NULL);
+ num_read = fuse_send_read(req, file, pos, count, NULL);
err = req->out.h.error;
fuse_put_request(fc, req);
@@ -504,19 +541,18 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req)
fuse_file_put(req->ff);
}
-static void fuse_send_readpages(struct fuse_req *req, struct file *file,
- struct inode *inode)
+static void fuse_send_readpages(struct fuse_req *req, struct file *file)
{
- struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_file *ff = file->private_data;
+ struct fuse_conn *fc = ff->fc;
loff_t pos = page_offset(req->pages[0]);
size_t count = req->num_pages << PAGE_CACHE_SHIFT;
req->out.argpages = 1;
req->out.page_zeroing = 1;
- fuse_read_fill(req, file, inode, pos, count, FUSE_READ);
+ fuse_read_fill(req, file, pos, count, FUSE_READ);
req->misc.read.attr_ver = fuse_get_attr_version(fc);
if (fc->async_read) {
- struct fuse_file *ff = file->private_data;
req->ff = fuse_file_get(ff);
req->end = fuse_readpages_end;
fuse_request_send_background(fc, req);
@@ -546,7 +582,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->file);
data->req = req = fuse_get_req(fc);
if (IS_ERR(req)) {
unlock_page(page);
@@ -580,7 +616,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, file);
else
fuse_put_request(fc, data.req);
}
@@ -607,24 +643,19 @@ static ssize_t fuse_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
return generic_file_aio_read(iocb, iov, nr_segs, pos);
}
-static void fuse_write_fill(struct fuse_req *req, struct file *file,
- struct fuse_file *ff, struct inode *inode,
- loff_t pos, size_t count, int writepage)
+static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff,
+ loff_t pos, size_t count)
{
- struct fuse_conn *fc = get_fuse_conn(inode);
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;
- inarg->write_flags = writepage ? FUSE_WRITE_CACHE : 0;
- inarg->flags = file ? file->f_flags : 0;
req->in.h.opcode = FUSE_WRITE;
- req->in.h.nodeid = get_node_id(inode);
+ req->in.h.nodeid = ff->nodeid;
req->in.numargs = 2;
- if (fc->minor < 9)
+ if (ff->fc->minor < 9)
req->in.args[0].size = FUSE_COMPAT_WRITE_IN_SIZE;
else
req->in.args[0].size = sizeof(struct fuse_write_in);
@@ -636,13 +667,15 @@ static void fuse_write_fill(struct fuse_req *req, struct file *file,
}
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)
+ loff_t pos, size_t count, fl_owner_t owner)
{
- struct fuse_conn *fc = get_fuse_conn(inode);
- fuse_write_fill(req, file, file->private_data, inode, pos, count, 0);
+ struct fuse_file *ff = file->private_data;
+ struct fuse_conn *fc = ff->fc;
+ struct fuse_write_in *inarg = &req->misc.write.in;
+
+ fuse_write_fill(req, ff, pos, count);
+ inarg->flags = file->f_flags;
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);
}
@@ -700,7 +733,7 @@ static int fuse_buffered_write(struct file *file, struct inode *inode,
req->num_pages = 1;
req->pages[0] = page;
req->page_offset = offset;
- nres = fuse_send_write(req, file, inode, pos, count, NULL);
+ nres = fuse_send_write(req, file, pos, count, NULL);
err = req->out.h.error;
fuse_put_request(fc, req);
if (!err && !nres)
@@ -741,7 +774,7 @@ static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file,
for (i = 0; i < req->num_pages; i++)
fuse_wait_on_page_writeback(inode, req->pages[i]->index);
- res = fuse_send_write(req, file, inode, pos, count, NULL);
+ res = fuse_send_write(req, file, pos, count, NULL);
offset = req->page_offset;
count = res;
@@ -938,9 +971,9 @@ static void fuse_release_user_pages(struct fuse_req *req, int write)
}
static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf,
- unsigned *nbytesp, int write)
+ size_t *nbytesp, int write)
{
- unsigned nbytes = *nbytesp;
+ size_t nbytes = *nbytesp;
unsigned long user_addr = (unsigned long) buf;
unsigned offset = user_addr & ~PAGE_MASK;
int npages;
@@ -955,7 +988,7 @@ static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf,
return 0;
}
- nbytes = min(nbytes, (unsigned) FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT);
+ nbytes = min_t(size_t, nbytes, FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT);
npages = (nbytes + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
npages = clamp(npages, 1, FUSE_MAX_PAGES_PER_REQ);
down_read(&current->mm->mmap_sem);
@@ -979,25 +1012,23 @@ static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf,
return 0;
}
-static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos, int write)
+ssize_t fuse_direct_io(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos, int write)
{
- 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_conn *fc = ff->fc;
size_t nmax = write ? fc->max_write : fc->max_read;
loff_t pos = *ppos;
ssize_t res = 0;
struct fuse_req *req;
- if (is_bad_inode(inode))
- return -EIO;
-
req = fuse_get_req(fc);
if (IS_ERR(req))
return PTR_ERR(req);
while (count) {
size_t nres;
+ fl_owner_t owner = current->files;
size_t nbytes = min(count, nmax);
int err = fuse_get_user_pages(req, buf, &nbytes, write);
if (err) {
@@ -1006,11 +1037,10 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
}
if (write)
- nres = fuse_send_write(req, file, inode, pos, nbytes,
- current->files);
+ nres = fuse_send_write(req, file, pos, nbytes, owner);
else
- nres = fuse_send_read(req, file, inode, pos, nbytes,
- current->files);
+ nres = fuse_send_read(req, file, pos, nbytes, owner);
+
fuse_release_user_pages(req, !write);
if (req->out.h.error) {
if (!res)
@@ -1034,20 +1064,27 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
}
}
fuse_put_request(fc, req);
- if (res > 0) {
- if (write)
- fuse_write_update_size(inode, pos);
+ if (res > 0)
*ppos = pos;
- }
- fuse_invalidate_attr(inode);
return res;
}
+EXPORT_SYMBOL_GPL(fuse_direct_io);
static ssize_t fuse_direct_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- return fuse_direct_io(file, buf, count, ppos, 0);
+ ssize_t res;
+ struct inode *inode = file->f_path.dentry->d_inode;
+
+ if (is_bad_inode(inode))
+ return -EIO;
+
+ res = fuse_direct_io(file, buf, count, ppos, 0);
+
+ fuse_invalidate_attr(inode);
+
+ return res;
}
static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
@@ -1055,12 +1092,22 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
{
struct inode *inode = file->f_path.dentry->d_inode;
ssize_t res;
+
+ if (is_bad_inode(inode))
+ return -EIO;
+
/* Don't allow parallel writes to the same file */
mutex_lock(&inode->i_mutex);
res = generic_write_checks(file, ppos, &count, 0);
- if (!res)
+ if (!res) {
res = fuse_direct_io(file, buf, count, ppos, 1);
+ if (res > 0)
+ fuse_write_update_size(inode, *ppos);
+ }
mutex_unlock(&inode->i_mutex);
+
+ fuse_invalidate_attr(inode);
+
return res;
}
@@ -1177,9 +1224,10 @@ static int fuse_writepage_locked(struct page *page)
req->ff = fuse_file_get(ff);
spin_unlock(&fc->lock);
- fuse_write_fill(req, NULL, ff, inode, page_offset(page), 0, 1);
+ fuse_write_fill(req, ff, page_offset(page), 0);
copy_highpage(tmp_page, page);
+ req->misc.write.in.write_flags |= FUSE_WRITE_CACHE;
req->in.argpages = 1;
req->num_pages = 1;
req->pages[0] = tmp_page;
@@ -1298,6 +1346,8 @@ static int fuse_direct_mmap(struct file *file, struct vm_area_struct *vma)
if (vma->vm_flags & VM_MAYSHARE)
return -ENODEV;
+ invalidate_inode_pages2(file->f_mapping);
+
return generic_file_mmap(file, vma);
}
@@ -1601,12 +1651,11 @@ static int fuse_ioctl_copy_user(struct page **pages, struct iovec *iov,
* limits ioctl data transfers to well-formed ioctls and is the forced
* behavior for all FUSE servers.
*/
-static long fuse_file_do_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg, unsigned int flags)
+long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
+ unsigned int flags)
{
- struct inode *inode = file->f_dentry->d_inode;
struct fuse_file *ff = file->private_data;
- struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_conn *fc = ff->fc;
struct fuse_ioctl_in inarg = {
.fh = ff->fh,
.cmd = cmd,
@@ -1625,13 +1674,6 @@ static long fuse_file_do_ioctl(struct file *file, unsigned int cmd,
/* assume all the iovs returned by client always fits in a page */
BUILD_BUG_ON(sizeof(struct iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE);
- if (!fuse_allow_task(fc, current))
- return -EACCES;
-
- err = -EIO;
- if (is_bad_inode(inode))
- goto out;
-
err = -ENOMEM;
pages = kzalloc(sizeof(pages[0]) * FUSE_MAX_PAGES_PER_REQ, GFP_KERNEL);
iov_page = alloc_page(GFP_KERNEL);
@@ -1692,7 +1734,7 @@ static long fuse_file_do_ioctl(struct file *file, unsigned int cmd,
/* okay, let's send it to the client */
req->in.h.opcode = FUSE_IOCTL;
- req->in.h.nodeid = get_node_id(inode);
+ req->in.h.nodeid = ff->nodeid;
req->in.numargs = 1;
req->in.args[0].size = sizeof(inarg);
req->in.args[0].value = &inarg;
@@ -1775,17 +1817,33 @@ static long fuse_file_do_ioctl(struct file *file, unsigned int cmd,
return err ? err : outarg.result;
}
+EXPORT_SYMBOL_GPL(fuse_do_ioctl);
+
+static long fuse_file_ioctl_common(struct file *file, unsigned int cmd,
+ unsigned long arg, unsigned int flags)
+{
+ struct inode *inode = file->f_dentry->d_inode;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+
+ if (!fuse_allow_task(fc, current))
+ return -EACCES;
+
+ if (is_bad_inode(inode))
+ return -EIO;
+
+ return fuse_do_ioctl(file, cmd, arg, flags);
+}
static long fuse_file_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
- return fuse_file_do_ioctl(file, cmd, arg, 0);
+ return fuse_file_ioctl_common(file, cmd, arg, 0);
}
static long fuse_file_compat_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
- return fuse_file_do_ioctl(file, cmd, arg, FUSE_IOCTL_COMPAT);
+ return fuse_file_ioctl_common(file, cmd, arg, FUSE_IOCTL_COMPAT);
}
/*
@@ -1839,11 +1897,10 @@ static void fuse_register_polled_file(struct fuse_conn *fc,
spin_unlock(&fc->lock);
}
-static unsigned fuse_file_poll(struct file *file, poll_table *wait)
+unsigned fuse_file_poll(struct file *file, poll_table *wait)
{
- struct inode *inode = file->f_dentry->d_inode;
struct fuse_file *ff = file->private_data;
- struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_conn *fc = ff->fc;
struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh };
struct fuse_poll_out outarg;
struct fuse_req *req;
@@ -1868,7 +1925,7 @@ static unsigned fuse_file_poll(struct file *file, poll_table *wait)
return PTR_ERR(req);
req->in.h.opcode = FUSE_POLL;
- req->in.h.nodeid = get_node_id(inode);
+ req->in.h.nodeid = ff->nodeid;
req->in.numargs = 1;
req->in.args[0].size = sizeof(inarg);
req->in.args[0].value = &inarg;
@@ -1887,6 +1944,7 @@ static unsigned fuse_file_poll(struct file *file, poll_table *wait)
}
return POLLERR;
}
+EXPORT_SYMBOL_GPL(fuse_file_poll);
/*
* This is called from fuse_handle_notify() on FUSE_NOTIFY_POLL and
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 6fc5aedaa0d5..aaf2f9ff970e 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -97,8 +97,13 @@ struct fuse_inode {
struct list_head writepages;
};
+struct fuse_conn;
+
/** FUSE specific file data */
struct fuse_file {
+ /** Fuse connection for this file */
+ struct fuse_conn *fc;
+
/** Request reserved for flush and release */
struct fuse_req *reserved_req;
@@ -108,9 +113,15 @@ struct fuse_file {
/** File handle used by userspace */
u64 fh;
+ /** Node id of this file */
+ u64 nodeid;
+
/** Refcount */
atomic_t count;
+ /** FOPEN_* flags returned by open */
+ u32 open_flags;
+
/** Entry on inode's write_files list */
struct list_head write_entry;
@@ -185,8 +196,6 @@ enum fuse_req_state {
FUSE_REQ_FINISHED
};
-struct fuse_conn;
-
/**
* A request to the client
*/
@@ -248,11 +257,12 @@ struct fuse_req {
struct fuse_forget_in forget_in;
struct {
struct fuse_release_in in;
- struct vfsmount *vfsmount;
- struct dentry *dentry;
+ struct path path;
} release;
struct fuse_init_in init_in;
struct fuse_init_out init_out;
+ struct cuse_init_in cuse_init_in;
+ struct cuse_init_out cuse_init_out;
struct {
struct fuse_read_in in;
u64 attr_ver;
@@ -386,6 +396,9 @@ struct fuse_conn {
/** Filesystem supports NFS exporting. Only set in INIT */
unsigned export_support:1;
+ /** Set if bdi is valid */
+ unsigned bdi_initialized:1;
+
/*
* The following bitfields are only for optimization purposes
* and hence races in setting them will not cause malfunction
@@ -515,25 +528,24 @@ 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,
- struct inode *inode, loff_t pos, size_t count, int opcode);
+ loff_t pos, size_t count, int opcode);
/**
* Send OPEN or OPENDIR request
*/
-int fuse_open_common(struct inode *inode, struct file *file, int isdir);
+int fuse_open_common(struct inode *inode, struct file *file, bool isdir);
struct fuse_file *fuse_file_alloc(struct fuse_conn *fc);
+struct fuse_file *fuse_file_get(struct fuse_file *ff);
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);
+void fuse_finish_open(struct inode *inode, struct file *file);
-/** Fill in ff->reserved_req with a RELEASE request */
-void fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags, int opcode);
+void fuse_sync_release(struct fuse_file *ff, int flags);
/**
* Send RELEASE or RELEASEDIR request
*/
-int fuse_release_common(struct inode *inode, struct file *file, int isdir);
+void fuse_release_common(struct file *file, int opcode);
/**
* Send FSYNC or FSYNCDIR request
@@ -652,10 +664,12 @@ void fuse_invalidate_entry_cache(struct dentry *entry);
*/
struct fuse_conn *fuse_conn_get(struct fuse_conn *fc);
+void fuse_conn_kill(struct fuse_conn *fc);
+
/**
* Initialize fuse_conn
*/
-int fuse_conn_init(struct fuse_conn *fc, struct super_block *sb);
+void fuse_conn_init(struct fuse_conn *fc);
/**
* Release reference to fuse_conn
@@ -694,4 +708,13 @@ void fuse_release_nowrite(struct inode *inode);
u64 fuse_get_attr_version(struct fuse_conn *fc);
+int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
+ bool isdir);
+ssize_t fuse_direct_io(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos, int write);
+long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
+ unsigned int flags);
+unsigned fuse_file_poll(struct file *file, poll_table *wait);
+int fuse_dev_release(struct inode *inode, struct file *file);
+
#endif /* _FS_FUSE_I_H */
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 459b73dd45e1..aeaefca38dea 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -19,6 +19,7 @@
#include <linux/random.h>
#include <linux/sched.h>
#include <linux/exportfs.h>
+#include <linux/smp_lock.h>
MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
MODULE_DESCRIPTION("Filesystem in Userspace");
@@ -259,7 +260,9 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
static void fuse_umount_begin(struct super_block *sb)
{
+ lock_kernel();
fuse_abort_conn(get_fuse_conn_super(sb));
+ unlock_kernel();
}
static void fuse_send_destroy(struct fuse_conn *fc)
@@ -274,11 +277,14 @@ static void fuse_send_destroy(struct fuse_conn *fc)
}
}
-static void fuse_put_super(struct super_block *sb)
+static void fuse_bdi_destroy(struct fuse_conn *fc)
{
- struct fuse_conn *fc = get_fuse_conn_super(sb);
+ if (fc->bdi_initialized)
+ bdi_destroy(&fc->bdi);
+}
- fuse_send_destroy(fc);
+void fuse_conn_kill(struct fuse_conn *fc)
+{
spin_lock(&fc->lock);
fc->connected = 0;
fc->blocked = 0;
@@ -292,8 +298,21 @@ static void fuse_put_super(struct super_block *sb)
list_del(&fc->entry);
fuse_ctl_remove_conn(fc);
mutex_unlock(&fuse_mutex);
- bdi_destroy(&fc->bdi);
+ fuse_bdi_destroy(fc);
+}
+EXPORT_SYMBOL_GPL(fuse_conn_kill);
+
+static void fuse_put_super(struct super_block *sb)
+{
+ struct fuse_conn *fc = get_fuse_conn_super(sb);
+
+ lock_kernel();
+
+ fuse_send_destroy(fc);
+ fuse_conn_kill(fc);
fuse_conn_put(fc);
+
+ unlock_kernel();
}
static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr)
@@ -463,10 +482,8 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt)
return 0;
}
-int fuse_conn_init(struct fuse_conn *fc, struct super_block *sb)
+void fuse_conn_init(struct fuse_conn *fc)
{
- int err;
-
memset(fc, 0, sizeof(*fc));
spin_lock_init(&fc->lock);
mutex_init(&fc->inst_mutex);
@@ -481,49 +498,12 @@ int fuse_conn_init(struct fuse_conn *fc, struct super_block *sb)
INIT_LIST_HEAD(&fc->bg_queue);
INIT_LIST_HEAD(&fc->entry);
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;
- /* fuse does it's own writeback accounting */
- fc->bdi.capabilities = BDI_CAP_NO_ACCT_WB;
fc->khctr = 0;
fc->polled_files = RB_ROOT;
- fc->dev = sb->s_dev;
- err = bdi_init(&fc->bdi);
- if (err)
- goto error_mutex_destroy;
- if (sb->s_bdev) {
- err = bdi_register(&fc->bdi, NULL, "%u:%u-fuseblk",
- MAJOR(fc->dev), MINOR(fc->dev));
- } else {
- err = bdi_register_dev(&fc->bdi, fc->dev);
- }
- if (err)
- goto error_bdi_destroy;
- /*
- * For a single fuse filesystem use max 1% of dirty +
- * writeback threshold.
- *
- * This gives about 1M of write buffer for memory maps on a
- * machine with 1G and 10% dirty_ratio, which should be more
- * than enough.
- *
- * Privileged users can raise it by writing to
- *
- * /sys/class/bdi/<bdi>/max_ratio
- */
- bdi_set_max_ratio(&fc->bdi, 1);
fc->reqctr = 0;
fc->blocked = 1;
fc->attr_version = 1;
get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key));
-
- return 0;
-
- error_bdi_destroy:
- bdi_destroy(&fc->bdi);
- error_mutex_destroy:
- mutex_destroy(&fc->inst_mutex);
- return err;
}
EXPORT_SYMBOL_GPL(fuse_conn_init);
@@ -536,12 +516,14 @@ void fuse_conn_put(struct fuse_conn *fc)
fc->release(fc);
}
}
+EXPORT_SYMBOL_GPL(fuse_conn_put);
struct fuse_conn *fuse_conn_get(struct fuse_conn *fc)
{
atomic_inc(&fc->count);
return fc;
}
+EXPORT_SYMBOL_GPL(fuse_conn_get);
static struct inode *fuse_get_root_inode(struct super_block *sb, unsigned mode)
{
@@ -794,6 +776,48 @@ static void fuse_free_conn(struct fuse_conn *fc)
kfree(fc);
}
+static int fuse_bdi_init(struct fuse_conn *fc, struct super_block *sb)
+{
+ int err;
+
+ fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
+ fc->bdi.unplug_io_fn = default_unplug_io_fn;
+ /* fuse does it's own writeback accounting */
+ fc->bdi.capabilities = BDI_CAP_NO_ACCT_WB;
+
+ err = bdi_init(&fc->bdi);
+ if (err)
+ return err;
+
+ fc->bdi_initialized = 1;
+
+ if (sb->s_bdev) {
+ err = bdi_register(&fc->bdi, NULL, "%u:%u-fuseblk",
+ MAJOR(fc->dev), MINOR(fc->dev));
+ } else {
+ err = bdi_register_dev(&fc->bdi, fc->dev);
+ }
+
+ if (err)
+ return err;
+
+ /*
+ * For a single fuse filesystem use max 1% of dirty +
+ * writeback threshold.
+ *
+ * This gives about 1M of write buffer for memory maps on a
+ * machine with 1G and 10% dirty_ratio, which should be more
+ * than enough.
+ *
+ * Privileged users can raise it by writing to
+ *
+ * /sys/class/bdi/<bdi>/max_ratio
+ */
+ bdi_set_max_ratio(&fc->bdi, 1);
+
+ return 0;
+}
+
static int fuse_fill_super(struct super_block *sb, void *data, int silent)
{
struct fuse_conn *fc;
@@ -840,11 +864,12 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
if (!fc)
goto err_fput;
- err = fuse_conn_init(fc, sb);
- if (err) {
- kfree(fc);
- goto err_fput;
- }
+ fuse_conn_init(fc);
+
+ fc->dev = sb->s_dev;
+ err = fuse_bdi_init(fc, sb);
+ if (err)
+ goto err_put_conn;
fc->release = fuse_free_conn;
fc->flags = d.flags;
@@ -908,6 +933,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
err_put_root:
dput(root_dentry);
err_put_conn:
+ fuse_bdi_destroy(fc);
fuse_conn_put(fc);
err_fput:
fput(file);
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 3984e47d1d33..ff4981090489 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -597,7 +597,6 @@ __acquires(&gl->gl_spin)
GLOCK_BUG_ON(gl, test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags));
- down_read(&gfs2_umount_flush_sem);
if (test_bit(GLF_DEMOTE, &gl->gl_flags) &&
gl->gl_demote_state != gl->gl_state) {
if (find_first_holder(gl))
@@ -614,15 +613,14 @@ __acquires(&gl->gl_spin)
if (ret == 0)
goto out_unlock;
if (ret == 2)
- goto out_sem;
+ goto out;
gh = find_first_waiter(gl);
gl->gl_target = gh->gh_state;
if (!(gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)))
do_error(gl, 0); /* Fail queued try locks */
}
do_xmote(gl, gh, gl->gl_target);
-out_sem:
- up_read(&gfs2_umount_flush_sem);
+out:
return;
out_sched:
@@ -631,7 +629,7 @@ out_sched:
gfs2_glock_put(gl);
out_unlock:
clear_bit(GLF_LOCK, &gl->gl_flags);
- goto out_sem;
+ goto out;
}
static void glock_work_func(struct work_struct *work)
@@ -641,6 +639,7 @@ static void glock_work_func(struct work_struct *work)
if (test_and_clear_bit(GLF_REPLY_PENDING, &gl->gl_flags))
finish_xmote(gl, gl->gl_reply);
+ down_read(&gfs2_umount_flush_sem);
spin_lock(&gl->gl_spin);
if (test_and_clear_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) &&
gl->gl_state != LM_ST_UNLOCKED &&
@@ -653,6 +652,7 @@ static void glock_work_func(struct work_struct *work)
}
run_queue(gl, 0);
spin_unlock(&gl->gl_spin);
+ up_read(&gfs2_umount_flush_sem);
if (!delay ||
queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0)
gfs2_glock_put(gl);
@@ -1304,6 +1304,7 @@ static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask)
nr--;
if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
gfs2_glock_put(gl);
+ got_ref = 0;
}
spin_lock(&lru_lock);
if (may_demote)
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index bf23a62aa925..70f87f43afa2 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -156,6 +156,12 @@ static void inode_go_sync(struct gfs2_glock *gl)
error = filemap_fdatawait(metamapping);
mapping_set_error(metamapping, error);
gfs2_ail_empty_gl(gl);
+ /*
+ * Writeback of the data mapping may cause the dirty flag to be set
+ * so we have to clear it again here.
+ */
+ smp_mb__before_clear_bit();
+ clear_bit(GLF_DIRTY, &gl->gl_flags);
}
/**
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 7b277d449155..5a31d426116f 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -137,15 +137,15 @@ void gfs2_set_iop(struct inode *inode)
if (S_ISREG(mode)) {
inode->i_op = &gfs2_file_iops;
if (gfs2_localflocks(sdp))
- inode->i_fop = gfs2_file_fops_nolock;
+ inode->i_fop = &gfs2_file_fops_nolock;
else
- inode->i_fop = gfs2_file_fops;
+ inode->i_fop = &gfs2_file_fops;
} else if (S_ISDIR(mode)) {
inode->i_op = &gfs2_dir_iops;
if (gfs2_localflocks(sdp))
- inode->i_fop = gfs2_dir_fops_nolock;
+ inode->i_fop = &gfs2_dir_fops_nolock;
else
- inode->i_fop = gfs2_dir_fops;
+ inode->i_fop = &gfs2_dir_fops;
} else if (S_ISLNK(mode)) {
inode->i_op = &gfs2_symlink_iops;
} else {
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h
index dca4fee3078b..c30be2b66580 100644
--- a/fs/gfs2/inode.h
+++ b/fs/gfs2/inode.h
@@ -101,21 +101,23 @@ void gfs2_dinode_print(const struct gfs2_inode *ip);
extern const struct inode_operations gfs2_file_iops;
extern const struct inode_operations gfs2_dir_iops;
extern const struct inode_operations gfs2_symlink_iops;
-extern const struct file_operations *gfs2_file_fops_nolock;
-extern const struct file_operations *gfs2_dir_fops_nolock;
+extern const struct file_operations gfs2_file_fops_nolock;
+extern const struct file_operations gfs2_dir_fops_nolock;
extern void gfs2_set_inode_flags(struct inode *inode);
#ifdef CONFIG_GFS2_FS_LOCKING_DLM
-extern const struct file_operations *gfs2_file_fops;
-extern const struct file_operations *gfs2_dir_fops;
+extern const struct file_operations gfs2_file_fops;
+extern const struct file_operations gfs2_dir_fops;
+
static inline int gfs2_localflocks(const struct gfs2_sbd *sdp)
{
return sdp->sd_args.ar_localflocks;
}
#else /* Single node only */
-#define gfs2_file_fops NULL
-#define gfs2_dir_fops NULL
+#define gfs2_file_fops gfs2_file_fops_nolock
+#define gfs2_dir_fops gfs2_dir_fops_nolock
+
static inline int gfs2_localflocks(const struct gfs2_sbd *sdp)
{
return 1;
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 98918a756410..f2e449c595b4 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -120,7 +120,7 @@ __acquires(&sdp->sd_log_lock)
lock_buffer(bh);
if (test_clear_buffer_dirty(bh)) {
bh->b_end_io = end_buffer_write_sync;
- submit_bh(WRITE, bh);
+ submit_bh(WRITE_SYNC_PLUG, bh);
} else {
unlock_buffer(bh);
brelse(bh);
@@ -604,7 +604,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull)
if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags))
goto skip_barrier;
get_bh(bh);
- submit_bh(WRITE_BARRIER | (1 << BIO_RW_META), bh);
+ submit_bh(WRITE_SYNC | (1 << BIO_RW_BARRIER) | (1 << BIO_RW_META), bh);
wait_on_buffer(bh);
if (buffer_eopnotsupp(bh)) {
clear_buffer_eopnotsupp(bh);
@@ -664,7 +664,7 @@ static void gfs2_ordered_write(struct gfs2_sbd *sdp)
lock_buffer(bh);
if (buffer_mapped(bh) && test_clear_buffer_dirty(bh)) {
bh->b_end_io = end_buffer_write_sync;
- submit_bh(WRITE, bh);
+ submit_bh(WRITE_SYNC_PLUG, bh);
} else {
unlock_buffer(bh);
brelse(bh);
@@ -764,7 +764,6 @@ void __gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
}
gfs2_log_unlock(sdp);
- sdp->sd_vfs->s_dirt = 0;
up_write(&sdp->sd_log_flush_lock);
kfree(ai);
@@ -823,7 +822,6 @@ void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
log_refund(sdp, tr);
buf_lo_incore_commit(sdp, tr);
- sdp->sd_vfs->s_dirt = 1;
up_read(&sdp->sd_log_flush_lock);
gfs2_log_lock(sdp);
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index 80e4f5f898bb..00315f50fa46 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -13,6 +13,8 @@
#include <linux/completion.h>
#include <linux/buffer_head.h>
#include <linux/gfs2_ondisk.h>
+#include <linux/bio.h>
+#include <linux/fs.h>
#include "gfs2.h"
#include "incore.h"
@@ -189,7 +191,7 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp)
}
gfs2_log_unlock(sdp);
- submit_bh(WRITE, bh);
+ submit_bh(WRITE_SYNC_PLUG, bh);
gfs2_log_lock(sdp);
n = 0;
@@ -199,7 +201,7 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp)
gfs2_log_unlock(sdp);
lock_buffer(bd2->bd_bh);
bh = gfs2_log_fake_buf(sdp, bd2->bd_bh);
- submit_bh(WRITE, bh);
+ submit_bh(WRITE_SYNC_PLUG, bh);
gfs2_log_lock(sdp);
if (++n >= num)
break;
@@ -341,7 +343,7 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp)
sdp->sd_log_num_revoke--;
if (offset + sizeof(u64) > sdp->sd_sb.sb_bsize) {
- submit_bh(WRITE, bh);
+ submit_bh(WRITE_SYNC_PLUG, bh);
bh = gfs2_log_get_buf(sdp);
mh = (struct gfs2_meta_header *)bh->b_data;
@@ -358,7 +360,7 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp)
}
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke);
- submit_bh(WRITE, bh);
+ submit_bh(WRITE_SYNC_PLUG, bh);
}
static void revoke_lo_before_scan(struct gfs2_jdesc *jd,
@@ -560,7 +562,7 @@ static void gfs2_write_blocks(struct gfs2_sbd *sdp, struct buffer_head *bh,
ptr = bh_log_ptr(bh);
get_bh(bh);
- submit_bh(WRITE, bh);
+ submit_bh(WRITE_SYNC_PLUG, bh);
gfs2_log_lock(sdp);
while(!list_empty(list)) {
bd = list_entry(list->next, struct gfs2_bufdata, bd_le.le_list);
@@ -586,7 +588,7 @@ static void gfs2_write_blocks(struct gfs2_sbd *sdp, struct buffer_head *bh,
} else {
bh1 = gfs2_log_fake_buf(sdp, bd->bd_bh);
}
- submit_bh(WRITE, bh1);
+ submit_bh(WRITE_SYNC_PLUG, bh1);
gfs2_log_lock(sdp);
ptr += 2;
}
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index 8d6f13256b26..78a5f4312667 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -33,17 +33,65 @@
#include "util.h"
#include "ops_address.h"
-static int aspace_get_block(struct inode *inode, sector_t lblock,
- struct buffer_head *bh_result, int create)
+static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wbc)
{
- gfs2_assert_warn(inode->i_sb->s_fs_info, 0);
- return -EOPNOTSUPP;
-}
+ int err;
+ struct buffer_head *bh, *head;
+ int nr_underway = 0;
+ int write_op = (1 << BIO_RW_META) | ((wbc->sync_mode == WB_SYNC_ALL ?
+ WRITE_SYNC_PLUG : WRITE));
+
+ BUG_ON(!PageLocked(page));
+ BUG_ON(!page_has_buffers(page));
+
+ head = page_buffers(page);
+ bh = head;
+
+ do {
+ if (!buffer_mapped(bh))
+ continue;
+ /*
+ * If it's a fully non-blocking write attempt and we cannot
+ * lock the buffer then redirty the page. Note that this can
+ * potentially cause a busy-wait loop from pdflush and kswapd
+ * activity, but those code paths have their own higher-level
+ * throttling.
+ */
+ if (wbc->sync_mode != WB_SYNC_NONE || !wbc->nonblocking) {
+ lock_buffer(bh);
+ } else if (!trylock_buffer(bh)) {
+ redirty_page_for_writepage(wbc, page);
+ continue;
+ }
+ if (test_clear_buffer_dirty(bh)) {
+ mark_buffer_async_write(bh);
+ } else {
+ unlock_buffer(bh);
+ }
+ } while ((bh = bh->b_this_page) != head);
+
+ /*
+ * The page and its buffers are protected by PageWriteback(), so we can
+ * drop the bh refcounts early.
+ */
+ BUG_ON(PageWriteback(page));
+ set_page_writeback(page);
+
+ do {
+ struct buffer_head *next = bh->b_this_page;
+ if (buffer_async_write(bh)) {
+ submit_bh(write_op, bh);
+ nr_underway++;
+ }
+ bh = next;
+ } while (bh != head);
+ unlock_page(page);
-static int gfs2_aspace_writepage(struct page *page,
- struct writeback_control *wbc)
-{
- return block_write_full_page(page, aspace_get_block, wbc);
+ err = 0;
+ if (nr_underway == 0)
+ end_page_writeback(page);
+
+ return err;
}
static const struct address_space_operations aspace_aops = {
@@ -201,16 +249,32 @@ struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno)
int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,
struct buffer_head **bhp)
{
- *bhp = gfs2_getbuf(gl, blkno, CREATE);
- if (!buffer_uptodate(*bhp)) {
- ll_rw_block(READ_META, 1, bhp);
- if (flags & DIO_WAIT) {
- int error = gfs2_meta_wait(gl->gl_sbd, *bhp);
- if (error) {
- brelse(*bhp);
- return error;
- }
- }
+ struct gfs2_sbd *sdp = gl->gl_sbd;
+ struct buffer_head *bh;
+
+ if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+ return -EIO;
+
+ *bhp = bh = gfs2_getbuf(gl, blkno, CREATE);
+
+ lock_buffer(bh);
+ if (buffer_uptodate(bh)) {
+ unlock_buffer(bh);
+ return 0;
+ }
+ bh->b_end_io = end_buffer_read_sync;
+ get_bh(bh);
+ submit_bh(READ_SYNC | (1 << BIO_RW_META), bh);
+ if (!(flags & DIO_WAIT))
+ return 0;
+
+ wait_on_buffer(bh);
+ if (unlikely(!buffer_uptodate(bh))) {
+ struct gfs2_trans *tr = current->journal_info;
+ if (tr && tr->tr_touched)
+ gfs2_io_error_bh(sdp, bh);
+ brelse(bh);
+ return -EIO;
}
return 0;
@@ -404,7 +468,7 @@ struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)
if (buffer_uptodate(first_bh))
goto out;
if (!buffer_locked(first_bh))
- ll_rw_block(READ_META, 1, &first_bh);
+ ll_rw_block(READ_SYNC | (1 << BIO_RW_META), 1, &first_bh);
dblock++;
extlen--;
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index 70b9b8548945..0ee7bd287c5a 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -413,7 +413,9 @@ out_unlock:
gfs2_glock_dq(&gh);
out:
gfs2_holder_uninit(&gh);
- if (ret)
+ if (ret == -ENOMEM)
+ ret = VM_FAULT_OOM;
+ else if (ret)
ret = VM_FAULT_SIGBUS;
return ret;
}
@@ -423,33 +425,36 @@ static struct vm_operations_struct gfs2_vm_ops = {
.page_mkwrite = gfs2_page_mkwrite,
};
-
/**
* gfs2_mmap -
* @file: The file to map
* @vma: The VMA which described the mapping
*
- * Returns: 0 or error code
+ * There is no need to get a lock here unless we should be updating
+ * atime. We ignore any locking errors since the only consequence is
+ * a missed atime update (which will just be deferred until later).
+ *
+ * Returns: 0
*/
static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)
{
struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
- struct gfs2_holder i_gh;
- int error;
- gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh);
- error = gfs2_glock_nq(&i_gh);
- if (error) {
- gfs2_holder_uninit(&i_gh);
- return error;
- }
+ if (!(file->f_flags & O_NOATIME)) {
+ struct gfs2_holder i_gh;
+ int error;
+ gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
+ error = gfs2_glock_nq(&i_gh);
+ file_accessed(file);
+ if (error == 0)
+ gfs2_glock_dq_uninit(&i_gh);
+ }
vma->vm_ops = &gfs2_vm_ops;
+ vma->vm_flags |= VM_CAN_NONLINEAR;
- gfs2_glock_dq_uninit(&i_gh);
-
- return error;
+ return 0;
}
/**
@@ -705,7 +710,7 @@ static int gfs2_flock(struct file *file, int cmd, struct file_lock *fl)
}
}
-const struct file_operations *gfs2_file_fops = &(const struct file_operations){
+const struct file_operations gfs2_file_fops = {
.llseek = gfs2_llseek,
.read = do_sync_read,
.aio_read = generic_file_aio_read,
@@ -723,7 +728,7 @@ const struct file_operations *gfs2_file_fops = &(const struct file_operations){
.setlease = gfs2_setlease,
};
-const struct file_operations *gfs2_dir_fops = &(const struct file_operations){
+const struct file_operations gfs2_dir_fops = {
.readdir = gfs2_readdir,
.unlocked_ioctl = gfs2_ioctl,
.open = gfs2_open,
@@ -735,7 +740,7 @@ const struct file_operations *gfs2_dir_fops = &(const struct file_operations){
#endif /* CONFIG_GFS2_FS_LOCKING_DLM */
-const struct file_operations *gfs2_file_fops_nolock = &(const struct file_operations){
+const struct file_operations gfs2_file_fops_nolock = {
.llseek = gfs2_llseek,
.read = do_sync_read,
.aio_read = generic_file_aio_read,
@@ -751,7 +756,7 @@ const struct file_operations *gfs2_file_fops_nolock = &(const struct file_operat
.setlease = generic_setlease,
};
-const struct file_operations *gfs2_dir_fops_nolock = &(const struct file_operations){
+const struct file_operations gfs2_dir_fops_nolock = {
.readdir = gfs2_readdir,
.unlocked_ioctl = gfs2_ioctl,
.open = gfs2_open,
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 51883b3ad89c..1ff9473ea753 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -272,11 +272,6 @@ static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector)
lock_page(page);
bio = bio_alloc(GFP_NOFS, 1);
- if (unlikely(!bio)) {
- __free_page(page);
- return -ENOBUFS;
- }
-
bio->bi_sector = sector * (sb->s_blocksize >> 9);
bio->bi_bdev = sb->s_bdev;
bio_add_page(bio, page, PAGE_SIZE, 0);
@@ -1287,21 +1282,21 @@ static int gfs2_get_sb(struct file_system_type *fs_type, int flags,
static struct super_block *get_gfs2_sb(const char *dev_name)
{
struct super_block *sb;
- struct nameidata nd;
+ struct path path;
int error;
- error = path_lookup(dev_name, LOOKUP_FOLLOW, &nd);
+ error = kern_path(dev_name, LOOKUP_FOLLOW, &path);
if (error) {
printk(KERN_WARNING "GFS2: path_lookup on %s returned error %d\n",
dev_name, error);
return NULL;
}
- sb = nd.path.dentry->d_inode->i_sb;
+ sb = path.dentry->d_inode->i_sb;
if (sb && (sb->s_type == &gfs2_fs_type))
atomic_inc(&sb->s_active);
else
sb = NULL;
- path_put(&nd.path);
+ path_put(&path);
return sb;
}
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index abd5429ae285..1c70fa5168d6 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -371,6 +371,7 @@ static int gfs2_symlink(struct inode *dir, struct dentry *dentry,
ip = ghs[1].gh_gl->gl_object;
ip->i_disksize = size;
+ i_size_write(inode, size);
error = gfs2_meta_inode_buffer(ip, &dibh);
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c
index 458019569dcb..1331f070520a 100644
--- a/fs/gfs2/ops_super.c
+++ b/fs/gfs2/ops_super.c
@@ -132,6 +132,8 @@ static void gfs2_put_super(struct super_block *sb)
struct gfs2_sbd *sdp = sb->s_fs_info;
int error;
+ lock_kernel();
+
/* Unfreeze the filesystem, if we need to */
mutex_lock(&sdp->sd_freeze_lock);
@@ -182,17 +184,8 @@ static void gfs2_put_super(struct super_block *sb)
/* At this point, we're through participating in the lockspace */
gfs2_sys_fs_del(sdp);
-}
-
-/**
- * gfs2_write_super
- * @sb: the superblock
- *
- */
-static void gfs2_write_super(struct super_block *sb)
-{
- sb->s_dirt = 0;
+ unlock_kernel();
}
/**
@@ -204,7 +197,6 @@ static void gfs2_write_super(struct super_block *sb)
static int gfs2_sync_fs(struct super_block *sb, int wait)
{
- sb->s_dirt = 0;
if (wait && sb->s_fs_info)
gfs2_log_flush(sb->s_fs_info, NULL);
return 0;
@@ -710,7 +702,6 @@ const struct super_operations gfs2_super_ops = {
.write_inode = gfs2_write_inode,
.delete_inode = gfs2_delete_inode,
.put_super = gfs2_put_super,
- .write_super = gfs2_write_super,
.sync_fs = gfs2_sync_fs,
.freeze_fs = gfs2_freeze,
.unfreeze_fs = gfs2_unfreeze,
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 8d53f66b5bcc..152e6c4a0dca 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -81,7 +81,7 @@ struct gfs2_quota_change_host {
static LIST_HEAD(qd_lru_list);
static atomic_t qd_lru_count = ATOMIC_INIT(0);
-static spinlock_t qd_lru_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(qd_lru_lock);
int gfs2_shrink_qd_memory(int nr, gfp_t gfp_mask)
{
@@ -1364,7 +1364,7 @@ int gfs2_quotad(void *data)
refrigerator();
t = min(quotad_timeo, statfs_timeo);
- prepare_to_wait(&sdp->sd_quota_wait, &wait, TASK_UNINTERRUPTIBLE);
+ prepare_to_wait(&sdp->sd_quota_wait, &wait, TASK_INTERRUPTIBLE);
spin_lock(&sdp->sd_trunc_lock);
empty = list_empty(&sdp->sd_trunc_list);
spin_unlock(&sdp->sd_trunc_lock);
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index f03d024038ea..565038243fa2 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -212,8 +212,7 @@ static u32 gfs2_bitfit(const u8 *buf, const unsigned int len,
if (tmp == 0)
return BFITNOENT;
ptr--;
- bit = fls64(tmp);
- bit--; /* fls64 always adds one to the bit count */
+ bit = __ffs64(tmp);
bit /= 2; /* two bits per entry in the bitmap */
return (((const unsigned char *)ptr - buf) * GFS2_NBBY) + bit;
}
@@ -1445,10 +1444,12 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart,
u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+ struct buffer_head *dibh;
struct gfs2_alloc *al = ip->i_alloc;
struct gfs2_rgrpd *rgd = al->al_rgd;
u32 goal, blk;
u64 block;
+ int error;
if (rgrp_contains_block(rgd, ip->i_goal))
goal = ip->i_goal - rgd->rd_data0;
@@ -1461,7 +1462,13 @@ u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n)
rgd->rd_last_alloc = blk;
block = rgd->rd_data0 + blk;
ip->i_goal = block;
-
+ error = gfs2_meta_inode_buffer(ip, &dibh);
+ if (error == 0) {
+ struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data;
+ gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+ di->di_goal_meta = di->di_goal_data = cpu_to_be64(ip->i_goal);
+ brelse(dibh);
+ }
gfs2_assert_withdraw(sdp, rgd->rd_free >= *n);
rgd->rd_free -= *n;
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 9435dda8f1e0..a1cbff2b4d99 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -70,6 +70,10 @@ static int hfs_releasepage(struct page *page, gfp_t mask)
BUG();
return 0;
}
+
+ if (!tree)
+ return 0;
+
if (tree->node_size >= PAGE_CACHE_SIZE) {
nidx = page->index >> (tree->node_size_shift - PAGE_CACHE_SHIFT);
spin_lock(&tree->hash_lock);
diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c
index 36ca2e1a4fa3..7b6165f25fbe 100644
--- a/fs/hfs/mdb.c
+++ b/fs/hfs/mdb.c
@@ -349,6 +349,7 @@ void hfs_mdb_put(struct super_block *sb)
if (HFS_SB(sb)->nls_disk)
unload_nls(HFS_SB(sb)->nls_disk);
+ free_pages((unsigned long)HFS_SB(sb)->bitmap, PAGE_SIZE < 8192 ? 1 : 0);
kfree(HFS_SB(sb));
sb->s_fs_info = NULL;
}
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index a36bb749926d..9f5eaa01cc77 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -65,9 +65,15 @@ static void hfs_write_super(struct super_block *sb)
*/
static void hfs_put_super(struct super_block *sb)
{
+ lock_kernel();
+
+ if (sb->s_dirt)
+ hfs_write_super(sb);
hfs_mdb_close(sb);
/* release the MDB's resources */
hfs_mdb_put(sb);
+
+ unlock_kernel();
}
/*
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index f2a64020f42e..9b292dcc39c8 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -199,6 +199,11 @@ static void hfsplus_put_super(struct super_block *sb)
dprint(DBG_SUPER, "hfsplus_put_super\n");
if (!sb->s_fs_info)
return;
+
+ lock_kernel();
+
+ if (sb->s_dirt)
+ hfsplus_write_super(sb);
if (!(sb->s_flags & MS_RDONLY) && HFSPLUS_SB(sb).s_vhdr) {
struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr;
@@ -218,6 +223,8 @@ static void hfsplus_put_super(struct super_block *sb)
unload_nls(HFSPLUS_SB(sb).nls);
kfree(sb->s_fs_info);
sb->s_fs_info = NULL;
+
+ unlock_kernel();
}
static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf)
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index fecf402d7b8a..f68193cf0811 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -99,11 +99,16 @@ int hpfs_stop_cycles(struct super_block *s, int key, int *c1, int *c2,
static void hpfs_put_super(struct super_block *s)
{
struct hpfs_sb_info *sbi = hpfs_sb(s);
+
+ lock_kernel();
+
kfree(sbi->sb_cp_table);
kfree(sbi->sb_bmp_dir);
unmark_dirty(s);
s->s_fs_info = NULL;
kfree(sbi);
+
+ unlock_kernel();
}
unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno)
@@ -393,6 +398,7 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
*flags |= MS_NOATIME;
+ lock_super(s);
uid = sbi->sb_uid; gid = sbi->sb_gid;
umask = 0777 & ~sbi->sb_mode;
lowercase = sbi->sb_lowercase; conv = sbi->sb_conv;
@@ -423,12 +429,13 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
if (!(*flags & MS_RDONLY)) mark_dirty(s);
- kfree(s->s_options);
- s->s_options = new_opts;
+ replace_mount_options(s, new_opts);
+ unlock_super(s);
return 0;
out_err:
+ unlock_super(s);
kfree(new_opts);
return -EINVAL;
}
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 23a3c76711e0..153d9681192b 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -26,7 +26,6 @@
#include <linux/pagevec.h>
#include <linux/parser.h>
#include <linux/mman.h>
-#include <linux/quotaops.h>
#include <linux/slab.h>
#include <linux/dnotify.h>
#include <linux/statfs.h>
@@ -842,7 +841,7 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
bad_val:
printk(KERN_ERR "hugetlbfs: Bad value '%s' for mount option '%s'\n",
args[0].from, p);
- return 1;
+ return -EINVAL;
}
static int
diff --git a/fs/inode.c b/fs/inode.c
index d06d6d268de9..03de16a904b5 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -99,7 +99,7 @@ static DEFINE_MUTEX(iprune_mutex);
*/
struct inodes_stat_t inodes_stat;
-static struct kmem_cache * inode_cachep __read_mostly;
+static struct kmem_cache *inode_cachep __read_mostly;
static void wake_up_inode(struct inode *inode)
{
@@ -124,7 +124,7 @@ struct inode *inode_init_always(struct super_block *sb, struct inode *inode)
static struct inode_operations empty_iops;
static const struct file_operations empty_fops;
- struct address_space * const mapping = &inode->i_data;
+ struct address_space *const mapping = &inode->i_data;
inode->i_sb = sb;
inode->i_blkbits = sb->s_blocksize_bits;
@@ -216,7 +216,7 @@ static struct inode *alloc_inode(struct super_block *sb)
return NULL;
}
-void destroy_inode(struct inode *inode)
+void destroy_inode(struct inode *inode)
{
BUG_ON(inode_has_buffers(inode));
security_inode_free(inode);
@@ -252,12 +252,11 @@ void inode_init_once(struct inode *inode)
mutex_init(&inode->inotify_mutex);
#endif
}
-
EXPORT_SYMBOL(inode_init_once);
static void init_once(void *foo)
{
- struct inode * inode = (struct inode *) foo;
+ struct inode *inode = (struct inode *) foo;
inode_init_once(inode);
}
@@ -265,7 +264,7 @@ static void init_once(void *foo)
/*
* inode_lock must be held
*/
-void __iget(struct inode * inode)
+void __iget(struct inode *inode)
{
if (atomic_read(&inode->i_count)) {
atomic_inc(&inode->i_count);
@@ -289,7 +288,7 @@ void clear_inode(struct inode *inode)
{
might_sleep();
invalidate_inode_buffers(inode);
-
+
BUG_ON(inode->i_data.nrpages);
BUG_ON(!(inode->i_state & I_FREEING));
BUG_ON(inode->i_state & I_CLEAR);
@@ -303,7 +302,6 @@ void clear_inode(struct inode *inode)
cd_forget(inode);
inode->i_state = I_CLEAR;
}
-
EXPORT_SYMBOL(clear_inode);
/*
@@ -351,8 +349,8 @@ static int invalidate_list(struct list_head *head, struct list_head *dispose)
next = head->next;
for (;;) {
- struct list_head * tmp = next;
- struct inode * inode;
+ struct list_head *tmp = next;
+ struct inode *inode;
/*
* We can reschedule here without worrying about the list's
@@ -391,7 +389,7 @@ static int invalidate_list(struct list_head *head, struct list_head *dispose)
* fails because there are busy inodes then a non zero value is returned.
* If the discard is successful all the inodes have been discarded.
*/
-int invalidate_inodes(struct super_block * sb)
+int invalidate_inodes(struct super_block *sb)
{
int busy;
LIST_HEAD(throw_away);
@@ -407,7 +405,6 @@ int invalidate_inodes(struct super_block * sb)
return busy;
}
-
EXPORT_SYMBOL(invalidate_inodes);
static int can_unuse(struct inode *inode)
@@ -504,7 +501,7 @@ static int shrink_icache_memory(int nr, gfp_t gfp_mask)
* Nasty deadlock avoidance. We may hold various FS locks,
* and we don't want to recurse into the FS that called us
* in clear_inode() and friends..
- */
+ */
if (!(gfp_mask & __GFP_FS))
return -1;
prune_icache(nr);
@@ -524,10 +521,13 @@ static void __wait_on_freeing_inode(struct inode *inode);
* by hand after calling find_inode now! This simplifies iunique and won't
* add any additional branch in the common code.
*/
-static struct inode * find_inode(struct super_block * sb, struct hlist_head *head, int (*test)(struct inode *, void *), void *data)
+static struct inode *find_inode(struct super_block *sb,
+ struct hlist_head *head,
+ int (*test)(struct inode *, void *),
+ void *data)
{
struct hlist_node *node;
- struct inode * inode = NULL;
+ struct inode *inode = NULL;
repeat:
hlist_for_each_entry(inode, node, head, i_hash) {
@@ -548,10 +548,11 @@ repeat:
* find_inode_fast is the fast path version of find_inode, see the comment at
* iget_locked for details.
*/
-static struct inode * find_inode_fast(struct super_block * sb, struct hlist_head *head, unsigned long ino)
+static struct inode *find_inode_fast(struct super_block *sb,
+ struct hlist_head *head, unsigned long ino)
{
struct hlist_node *node;
- struct inode * inode = NULL;
+ struct inode *inode = NULL;
repeat:
hlist_for_each_entry(inode, node, head, i_hash) {
@@ -631,10 +632,10 @@ struct inode *new_inode(struct super_block *sb)
* here to attempt to avoid that.
*/
static unsigned int last_ino;
- struct inode * inode;
+ struct inode *inode;
spin_lock_prefetch(&inode_lock);
-
+
inode = alloc_inode(sb);
if (inode) {
spin_lock(&inode_lock);
@@ -645,7 +646,6 @@ struct inode *new_inode(struct super_block *sb)
}
return inode;
}
-
EXPORT_SYMBOL(new_inode);
void unlock_new_inode(struct inode *inode)
@@ -674,7 +674,6 @@ void unlock_new_inode(struct inode *inode)
inode->i_state &= ~(I_LOCK|I_NEW);
wake_up_inode(inode);
}
-
EXPORT_SYMBOL(unlock_new_inode);
/*
@@ -683,13 +682,17 @@ EXPORT_SYMBOL(unlock_new_inode);
* We no longer cache the sb_flags in i_flags - see fs.h
* -- rmk@arm.uk.linux.org
*/
-static struct inode * get_new_inode(struct super_block *sb, struct hlist_head *head, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data)
+static struct inode *get_new_inode(struct super_block *sb,
+ struct hlist_head *head,
+ int (*test)(struct inode *, void *),
+ int (*set)(struct inode *, void *),
+ void *data)
{
- struct inode * inode;
+ struct inode *inode;
inode = alloc_inode(sb);
if (inode) {
- struct inode * old;
+ struct inode *old;
spin_lock(&inode_lock);
/* We released the lock, so.. */
@@ -731,13 +734,14 @@ set_failed:
* get_new_inode_fast is the fast path version of get_new_inode, see the
* comment at iget_locked for details.
*/
-static struct inode * get_new_inode_fast(struct super_block *sb, struct hlist_head *head, unsigned long ino)
+static struct inode *get_new_inode_fast(struct super_block *sb,
+ struct hlist_head *head, unsigned long ino)
{
- struct inode * inode;
+ struct inode *inode;
inode = alloc_inode(sb);
if (inode) {
- struct inode * old;
+ struct inode *old;
spin_lock(&inode_lock);
/* We released the lock, so.. */
@@ -823,7 +827,6 @@ struct inode *igrab(struct inode *inode)
spin_unlock(&inode_lock);
return inode;
}
-
EXPORT_SYMBOL(igrab);
/**
@@ -924,7 +927,6 @@ struct inode *ilookup5_nowait(struct super_block *sb, unsigned long hashval,
return ifind(sb, head, test, data, 0);
}
-
EXPORT_SYMBOL(ilookup5_nowait);
/**
@@ -953,7 +955,6 @@ struct inode *ilookup5(struct super_block *sb, unsigned long hashval,
return ifind(sb, head, test, data, 1);
}
-
EXPORT_SYMBOL(ilookup5);
/**
@@ -976,7 +977,6 @@ struct inode *ilookup(struct super_block *sb, unsigned long ino)
return ifind_fast(sb, head, ino);
}
-
EXPORT_SYMBOL(ilookup);
/**
@@ -1015,7 +1015,6 @@ struct inode *iget5_locked(struct super_block *sb, unsigned long hashval,
*/
return get_new_inode(sb, head, test, set, data);
}
-
EXPORT_SYMBOL(iget5_locked);
/**
@@ -1047,7 +1046,6 @@ struct inode *iget_locked(struct super_block *sb, unsigned long ino)
*/
return get_new_inode_fast(sb, head, ino);
}
-
EXPORT_SYMBOL(iget_locked);
int insert_inode_locked(struct inode *inode)
@@ -1076,7 +1074,6 @@ int insert_inode_locked(struct inode *inode)
iput(old);
}
}
-
EXPORT_SYMBOL(insert_inode_locked);
int insert_inode_locked4(struct inode *inode, unsigned long hashval,
@@ -1106,7 +1103,6 @@ int insert_inode_locked4(struct inode *inode, unsigned long hashval,
iput(old);
}
}
-
EXPORT_SYMBOL(insert_inode_locked4);
/**
@@ -1124,7 +1120,6 @@ void __insert_inode_hash(struct inode *inode, unsigned long hashval)
hlist_add_head(&inode->i_hash, head);
spin_unlock(&inode_lock);
}
-
EXPORT_SYMBOL(__insert_inode_hash);
/**
@@ -1139,7 +1134,6 @@ void remove_inode_hash(struct inode *inode)
hlist_del_init(&inode->i_hash);
spin_unlock(&inode_lock);
}
-
EXPORT_SYMBOL(remove_inode_hash);
/*
@@ -1187,7 +1181,6 @@ void generic_delete_inode(struct inode *inode)
BUG_ON(inode->i_state != I_CLEAR);
destroy_inode(inode);
}
-
EXPORT_SYMBOL(generic_delete_inode);
static void generic_forget_inode(struct inode *inode)
@@ -1237,12 +1230,11 @@ void generic_drop_inode(struct inode *inode)
else
generic_forget_inode(inode);
}
-
EXPORT_SYMBOL_GPL(generic_drop_inode);
/*
* Called when we're dropping the last reference
- * to an inode.
+ * to an inode.
*
* Call the FS "drop()" function, defaulting to
* the legacy UNIX filesystem behaviour..
@@ -1262,7 +1254,7 @@ static inline void iput_final(struct inode *inode)
}
/**
- * iput - put an inode
+ * iput - put an inode
* @inode: inode to put
*
* Puts an inode, dropping its usage count. If the inode use count hits
@@ -1279,7 +1271,6 @@ void iput(struct inode *inode)
iput_final(inode);
}
}
-
EXPORT_SYMBOL(iput);
/**
@@ -1290,10 +1281,10 @@ EXPORT_SYMBOL(iput);
* Returns the block number on the device holding the inode that
* is the disk block number for the block of the file requested.
* That is, asked for block 4 of inode 1 the function will return the
- * disk block relative to the disk start that holds that block of the
+ * disk block relative to the disk start that holds that block of the
* file.
*/
-sector_t bmap(struct inode * inode, sector_t block)
+sector_t bmap(struct inode *inode, sector_t block)
{
sector_t res = 0;
if (inode->i_mapping->a_ops->bmap)
@@ -1387,7 +1378,7 @@ EXPORT_SYMBOL(touch_atime);
* for writeback. Note that this function is meant exclusively for
* usage in the file write path of filesystems, and filesystems may
* choose to explicitly ignore update via this function with the
- * S_NOCTIME inode flag, e.g. for network filesystem where these
+ * S_NOCMTIME inode flag, e.g. for network filesystem where these
* timestamps are handled by the server.
*/
@@ -1401,7 +1392,7 @@ void file_update_time(struct file *file)
if (IS_NOCMTIME(inode))
return;
- err = mnt_want_write(file->f_path.mnt);
+ err = mnt_want_write_file(file);
if (err)
return;
@@ -1425,7 +1416,6 @@ void file_update_time(struct file *file)
mark_inode_dirty_sync(inode);
mnt_drop_write(file->f_path.mnt);
}
-
EXPORT_SYMBOL(file_update_time);
int inode_needs_sync(struct inode *inode)
@@ -1436,7 +1426,6 @@ int inode_needs_sync(struct inode *inode)
return 1;
return 0;
}
-
EXPORT_SYMBOL(inode_needs_sync);
int inode_wait(void *word)
@@ -1470,42 +1459,6 @@ static void __wait_on_freeing_inode(struct inode *inode)
spin_lock(&inode_lock);
}
-/*
- * We rarely want to lock two inodes that do not have a parent/child
- * relationship (such as directory, child inode) simultaneously. The
- * vast majority of file systems should be able to get along fine
- * without this. Do not use these functions except as a last resort.
- */
-void inode_double_lock(struct inode *inode1, struct inode *inode2)
-{
- if (inode1 == NULL || inode2 == NULL || inode1 == inode2) {
- if (inode1)
- mutex_lock(&inode1->i_mutex);
- else if (inode2)
- mutex_lock(&inode2->i_mutex);
- return;
- }
-
- if (inode1 < inode2) {
- mutex_lock_nested(&inode1->i_mutex, I_MUTEX_PARENT);
- mutex_lock_nested(&inode2->i_mutex, I_MUTEX_CHILD);
- } else {
- mutex_lock_nested(&inode2->i_mutex, I_MUTEX_PARENT);
- mutex_lock_nested(&inode1->i_mutex, I_MUTEX_CHILD);
- }
-}
-EXPORT_SYMBOL(inode_double_lock);
-
-void inode_double_unlock(struct inode *inode1, struct inode *inode2)
-{
- if (inode1)
- mutex_unlock(&inode1->i_mutex);
-
- if (inode2 && inode2 != inode1)
- mutex_unlock(&inode2->i_mutex);
-}
-EXPORT_SYMBOL(inode_double_unlock);
-
static __initdata unsigned long ihash_entries;
static int __init set_ihash_entries(char *str)
{
diff --git a/fs/internal.h b/fs/internal.h
index b4dac4fb6b61..d55ef562f0bb 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -25,6 +25,8 @@ static inline int sb_is_blkdev_sb(struct super_block *sb)
return sb == blockdev_superblock;
}
+extern int __sync_blockdev(struct block_device *bdev, int wait);
+
#else
static inline void bdev_cache_init(void)
{
@@ -34,6 +36,11 @@ static inline int sb_is_blkdev_sb(struct super_block *sb)
{
return 0;
}
+
+static inline int __sync_blockdev(struct block_device *bdev, int wait)
+{
+ return 0;
+}
#endif
/*
@@ -66,3 +73,13 @@ extern void __init mnt_init(void);
* fs_struct.c
*/
extern void chroot_fs_refs(struct path *, struct path *);
+
+/*
+ * file_table.c
+ */
+extern void mark_files_ro(struct super_block *);
+
+/*
+ * super.c
+ */
+extern int do_remount_sb(struct super_block *, int, void *, int);
diff --git a/fs/ioctl.c b/fs/ioctl.c
index ac2d47e43926..82d9c42b8bac 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -258,7 +258,7 @@ int __generic_block_fiemap(struct inode *inode,
long long length = 0, map_len = 0;
u64 logical = 0, phys = 0, size = 0;
u32 flags = FIEMAP_EXTENT_MERGED;
- int ret = 0;
+ int ret = 0, past_eof = 0, whole_file = 0;
if ((ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC)))
return ret;
@@ -266,6 +266,9 @@ int __generic_block_fiemap(struct inode *inode,
start_blk = logical_to_blk(inode, start);
length = (long long)min_t(u64, len, i_size_read(inode));
+ if (length < len)
+ whole_file = 1;
+
map_len = length;
do {
@@ -282,11 +285,26 @@ int __generic_block_fiemap(struct inode *inode,
/* HOLE */
if (!buffer_mapped(&tmp)) {
+ length -= blk_to_logical(inode, 1);
+ start_blk++;
+
+ /*
+ * we want to handle the case where there is an
+ * allocated block at the front of the file, and then
+ * nothing but holes up to the end of the file properly,
+ * to make sure that extent at the front gets properly
+ * marked with FIEMAP_EXTENT_LAST
+ */
+ if (!past_eof &&
+ blk_to_logical(inode, start_blk) >=
+ blk_to_logical(inode, 0)+i_size_read(inode))
+ past_eof = 1;
+
/*
* first hole after going past the EOF, this is our
* last extent
*/
- if (length <= 0) {
+ if (past_eof && size) {
flags = FIEMAP_EXTENT_MERGED|FIEMAP_EXTENT_LAST;
ret = fiemap_fill_next_extent(fieinfo, logical,
phys, size,
@@ -294,15 +312,37 @@ int __generic_block_fiemap(struct inode *inode,
break;
}
- length -= blk_to_logical(inode, 1);
-
/* if we have holes up to/past EOF then we're done */
- if (length <= 0)
+ if (length <= 0 || past_eof)
break;
-
- start_blk++;
} else {
- if (length <= 0 && size) {
+ /*
+ * we have gone over the length of what we wanted to
+ * map, and it wasn't the entire file, so add the extent
+ * we got last time and exit.
+ *
+ * This is for the case where say we want to map all the
+ * way up to the second to the last block in a file, but
+ * the last block is a hole, making the second to last
+ * block FIEMAP_EXTENT_LAST. In this case we want to
+ * see if there is a hole after the second to last block
+ * so we can mark it properly. If we found data after
+ * we exceeded the length we were requesting, then we
+ * are good to go, just add the extent to the fieinfo
+ * and break
+ */
+ if (length <= 0 && !whole_file) {
+ ret = fiemap_fill_next_extent(fieinfo, logical,
+ phys, size,
+ flags);
+ break;
+ }
+
+ /*
+ * if size != 0 then we know we already have an extent
+ * to add, so add it.
+ */
+ if (size) {
ret = fiemap_fill_next_extent(fieinfo, logical,
phys, size,
flags);
@@ -319,19 +359,14 @@ int __generic_block_fiemap(struct inode *inode,
start_blk += logical_to_blk(inode, size);
/*
- * if we are past the EOF we need to loop again to see
- * if there is a hole so we can mark this extent as the
- * last one, and if not keep mapping things until we
- * find a hole, or we run out of slots in the extent
- * array
+ * If we are past the EOF, then we need to make sure as
+ * soon as we find a hole that the last extent we found
+ * is marked with FIEMAP_EXTENT_LAST
*/
- if (length <= 0)
- continue;
-
- ret = fiemap_fill_next_extent(fieinfo, logical, phys,
- size, flags);
- if (ret)
- break;
+ if (!past_eof &&
+ logical+size >=
+ blk_to_logical(inode, 0)+i_size_read(inode))
+ past_eof = 1;
}
cond_resched();
} while (1);
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index b4cbe9603c7d..068b34b5a107 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -42,11 +42,16 @@ static int isofs_dentry_cmp_ms(struct dentry *dentry, struct qstr *a, struct qst
static void isofs_put_super(struct super_block *sb)
{
struct isofs_sb_info *sbi = ISOFS_SB(sb);
+
#ifdef CONFIG_JOLIET
+ lock_kernel();
+
if (sbi->s_nls_iocharset) {
unload_nls(sbi->s_nls_iocharset);
sbi->s_nls_iocharset = NULL;
}
+
+ unlock_kernel();
#endif
kfree(sbi);
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index a8e8513a78a9..06560c520f49 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -502,7 +502,7 @@ void journal_commit_transaction(journal_t *journal)
err = 0;
}
- journal_write_revoke_records(journal, commit_transaction);
+ journal_write_revoke_records(journal, commit_transaction, write_op);
/*
* If we found any dirty or locked buffers, then we should have
diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c
index c7bd649bbbdc..da6cd9bdaabc 100644
--- a/fs/jbd/revoke.c
+++ b/fs/jbd/revoke.c
@@ -55,6 +55,25 @@
* need do nothing.
* RevokeValid set, Revoked set:
* buffer has been revoked.
+ *
+ * Locking rules:
+ * We keep two hash tables of revoke records. One hashtable belongs to the
+ * running transaction (is pointed to by journal->j_revoke), the other one
+ * belongs to the committing transaction. Accesses to the second hash table
+ * happen only from the kjournald and no other thread touches this table. Also
+ * journal_switch_revoke_table() which switches which hashtable belongs to the
+ * running and which to the committing transaction is called only from
+ * kjournald. Therefore we need no locks when accessing the hashtable belonging
+ * to the committing transaction.
+ *
+ * All users operating on the hash table belonging to the running transaction
+ * have a handle to the transaction. Therefore they are safe from kjournald
+ * switching hash tables under them. For operations on the lists of entries in
+ * the hash table j_revoke_lock is used.
+ *
+ * Finally, also replay code uses the hash tables but at this moment noone else
+ * can touch them (filesystem isn't mounted yet) and hence no locking is
+ * needed.
*/
#ifndef __KERNEL__
@@ -67,6 +86,7 @@
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/init.h>
+#include <linux/bio.h>
#endif
#include <linux/log2.h>
@@ -99,8 +119,8 @@ struct jbd_revoke_table_s
#ifdef __KERNEL__
static void write_one_revoke_record(journal_t *, transaction_t *,
struct journal_head **, int *,
- struct jbd_revoke_record_s *);
-static void flush_descriptor(journal_t *, struct journal_head *, int);
+ struct jbd_revoke_record_s *, int);
+static void flush_descriptor(journal_t *, struct journal_head *, int, int);
#endif
/* Utility functions to maintain the revoke table */
@@ -402,8 +422,6 @@ int journal_revoke(handle_t *handle, unsigned long blocknr,
* the second time we would still have a pending revoke to cancel. So,
* do not trust the Revoked bit on buffers unless RevokeValid is also
* set.
- *
- * The caller must have the journal locked.
*/
int journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
{
@@ -481,12 +499,9 @@ void journal_switch_revoke_table(journal_t *journal)
/*
* Write revoke records to the journal for all entries in the current
* revoke hash, deleting the entries as we go.
- *
- * Called with the journal lock held.
*/
-
void journal_write_revoke_records(journal_t *journal,
- transaction_t *transaction)
+ transaction_t *transaction, int write_op)
{
struct journal_head *descriptor;
struct jbd_revoke_record_s *record;
@@ -510,14 +525,14 @@ void journal_write_revoke_records(journal_t *journal,
hash_list->next;
write_one_revoke_record(journal, transaction,
&descriptor, &offset,
- record);
+ record, write_op);
count++;
list_del(&record->hash);
kmem_cache_free(revoke_record_cache, record);
}
}
if (descriptor)
- flush_descriptor(journal, descriptor, offset);
+ flush_descriptor(journal, descriptor, offset, write_op);
jbd_debug(1, "Wrote %d revoke records\n", count);
}
@@ -530,7 +545,8 @@ static void write_one_revoke_record(journal_t *journal,
transaction_t *transaction,
struct journal_head **descriptorp,
int *offsetp,
- struct jbd_revoke_record_s *record)
+ struct jbd_revoke_record_s *record,
+ int write_op)
{
struct journal_head *descriptor;
int offset;
@@ -549,7 +565,7 @@ static void write_one_revoke_record(journal_t *journal,
/* Make sure we have a descriptor with space left for the record */
if (descriptor) {
if (offset == journal->j_blocksize) {
- flush_descriptor(journal, descriptor, offset);
+ flush_descriptor(journal, descriptor, offset, write_op);
descriptor = NULL;
}
}
@@ -586,7 +602,7 @@ static void write_one_revoke_record(journal_t *journal,
static void flush_descriptor(journal_t *journal,
struct journal_head *descriptor,
- int offset)
+ int offset, int write_op)
{
journal_revoke_header_t *header;
struct buffer_head *bh = jh2bh(descriptor);
@@ -601,7 +617,7 @@ static void flush_descriptor(journal_t *journal,
set_buffer_jwrite(bh);
BUFFER_TRACE(bh, "write");
set_buffer_dirty(bh);
- ll_rw_block(SWRITE, 1, &bh);
+ ll_rw_block((write_op == WRITE) ? SWRITE : SWRITE_SYNC_PLUG, 1, &bh);
}
#endif
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 073c8c3df7cd..0b7d3b8226fd 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -506,7 +506,8 @@ void jbd2_journal_commit_transaction(journal_t *journal)
if (err)
jbd2_journal_abort(journal, err);
- jbd2_journal_write_revoke_records(journal, commit_transaction);
+ jbd2_journal_write_revoke_records(journal, commit_transaction,
+ write_op);
jbd_debug(3, "JBD: commit phase 2\n");
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
index bbe6d592d8b3..a360b06af2e3 100644
--- a/fs/jbd2/revoke.c
+++ b/fs/jbd2/revoke.c
@@ -86,6 +86,7 @@
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/init.h>
+#include <linux/bio.h>
#endif
#include <linux/log2.h>
@@ -118,8 +119,8 @@ struct jbd2_revoke_table_s
#ifdef __KERNEL__
static void write_one_revoke_record(journal_t *, transaction_t *,
struct journal_head **, int *,
- struct jbd2_revoke_record_s *);
-static void flush_descriptor(journal_t *, struct journal_head *, int);
+ struct jbd2_revoke_record_s *, int);
+static void flush_descriptor(journal_t *, struct journal_head *, int, int);
#endif
/* Utility functions to maintain the revoke table */
@@ -499,7 +500,8 @@ void jbd2_journal_switch_revoke_table(journal_t *journal)
* revoke hash, deleting the entries as we go.
*/
void jbd2_journal_write_revoke_records(journal_t *journal,
- transaction_t *transaction)
+ transaction_t *transaction,
+ int write_op)
{
struct journal_head *descriptor;
struct jbd2_revoke_record_s *record;
@@ -523,14 +525,14 @@ void jbd2_journal_write_revoke_records(journal_t *journal,
hash_list->next;
write_one_revoke_record(journal, transaction,
&descriptor, &offset,
- record);
+ record, write_op);
count++;
list_del(&record->hash);
kmem_cache_free(jbd2_revoke_record_cache, record);
}
}
if (descriptor)
- flush_descriptor(journal, descriptor, offset);
+ flush_descriptor(journal, descriptor, offset, write_op);
jbd_debug(1, "Wrote %d revoke records\n", count);
}
@@ -543,7 +545,8 @@ static void write_one_revoke_record(journal_t *journal,
transaction_t *transaction,
struct journal_head **descriptorp,
int *offsetp,
- struct jbd2_revoke_record_s *record)
+ struct jbd2_revoke_record_s *record,
+ int write_op)
{
struct journal_head *descriptor;
int offset;
@@ -562,7 +565,7 @@ static void write_one_revoke_record(journal_t *journal,
/* Make sure we have a descriptor with space left for the record */
if (descriptor) {
if (offset == journal->j_blocksize) {
- flush_descriptor(journal, descriptor, offset);
+ flush_descriptor(journal, descriptor, offset, write_op);
descriptor = NULL;
}
}
@@ -607,7 +610,7 @@ static void write_one_revoke_record(journal_t *journal,
static void flush_descriptor(journal_t *journal,
struct journal_head *descriptor,
- int offset)
+ int offset, int write_op)
{
jbd2_journal_revoke_header_t *header;
struct buffer_head *bh = jh2bh(descriptor);
@@ -622,7 +625,7 @@ static void flush_descriptor(journal_t *journal,
set_buffer_jwrite(bh);
BUFFER_TRACE(bh, "write");
set_buffer_dirty(bh);
- ll_rw_block(SWRITE, 1, &bh);
+ ll_rw_block((write_op == WRITE) ? SWRITE : SWRITE_SYNC_PLUG, 1, &bh);
}
#endif
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 4c4e18c54a51..37b12125c127 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -174,6 +174,11 @@ static void jffs2_put_super (struct super_block *sb)
D2(printk(KERN_DEBUG "jffs2: jffs2_put_super()\n"));
+ lock_kernel();
+
+ if (sb->s_dirt)
+ jffs2_write_super(sb);
+
mutex_lock(&c->alloc_sem);
jffs2_flush_wbuf_pad(c);
mutex_unlock(&c->alloc_sem);
@@ -192,6 +197,8 @@ static void jffs2_put_super (struct super_block *sb)
if (c->mtd->sync)
c->mtd->sync(c->mtd);
+ unlock_kernel();
+
D1(printk(KERN_DEBUG "jffs2_put_super returning\n"));
}
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 6f21adf9479a..3eb13adf3862 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -183,6 +183,9 @@ static void jfs_put_super(struct super_block *sb)
int rc;
jfs_info("In jfs_put_super");
+
+ lock_kernel();
+
rc = jfs_umount(sb);
if (rc)
jfs_err("jfs_umount failed with return code %d", rc);
@@ -195,6 +198,8 @@ static void jfs_put_super(struct super_block *sb)
sbi->direct_inode = NULL;
kfree(sbi);
+
+ unlock_kernel();
}
enum {
@@ -720,8 +725,10 @@ static ssize_t jfs_quota_write(struct super_block *sb, int type,
blk++;
}
out:
- if (len == towrite)
+ if (len == towrite) {
+ mutex_unlock(&inode->i_mutex);
return err;
+ }
if (inode->i_size < off+len-towrite)
i_size_write(inode, off+len-towrite);
inode->i_version++;
diff --git a/fs/libfs.c b/fs/libfs.c
index cd223190c4e9..80046ddf5063 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -246,8 +246,7 @@ int get_sb_pseudo(struct file_system_type *fs_type, char *name,
return 0;
Enomem:
- up_write(&s->s_umount);
- deactivate_super(s);
+ deactivate_locked_super(s);
return -ENOMEM;
}
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index abf83881f68a..1a54ae14a192 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -104,6 +104,16 @@ static void set_grace_period(void)
schedule_delayed_work(&grace_period_end, grace_period);
}
+static void restart_grace(void)
+{
+ if (nlmsvc_ops) {
+ cancel_delayed_work_sync(&grace_period_end);
+ locks_end_grace(&lockd_manager);
+ nlmsvc_invalidate_all();
+ set_grace_period();
+ }
+}
+
/*
* This is the lockd kernel thread
*/
@@ -149,10 +159,7 @@ lockd(void *vrqstp)
if (signalled()) {
flush_signals(current);
- if (nlmsvc_ops) {
- nlmsvc_invalidate_all();
- set_grace_period();
- }
+ restart_grace();
continue;
}
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 83ee34203bd7..e577a78d7bac 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -326,6 +326,8 @@ static void nlmsvc_freegrantargs(struct nlm_rqst *call)
{
if (call->a_args.lock.oh.data != call->a_owner)
kfree(call->a_args.lock.oh.data);
+
+ locks_release_private(&call->a_args.lock.fl);
}
/*
diff --git a/fs/locks.c b/fs/locks.c
index ec3deea29e37..b6440f52178f 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -151,7 +151,7 @@ static struct file_lock *locks_alloc_lock(void)
return kmem_cache_alloc(filelock_cache, GFP_KERNEL);
}
-static void locks_release_private(struct file_lock *fl)
+void locks_release_private(struct file_lock *fl)
{
if (fl->fl_ops) {
if (fl->fl_ops->fl_release_private)
@@ -165,6 +165,7 @@ static void locks_release_private(struct file_lock *fl)
}
}
+EXPORT_SYMBOL_GPL(locks_release_private);
/* Free a lock which is not in use. */
static void locks_free_lock(struct file_lock *fl)
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index daad3c2740db..7eb53970f4bc 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -35,6 +35,8 @@ static void minix_put_super(struct super_block *sb)
int i;
struct minix_sb_info *sbi = minix_sb(sb);
+ lock_kernel();
+
if (!(sb->s_flags & MS_RDONLY)) {
if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */
sbi->s_ms->s_state = sbi->s_mount_state;
@@ -49,7 +51,7 @@ static void minix_put_super(struct super_block *sb)
sb->s_fs_info = NULL;
kfree(sbi);
- return;
+ unlock_kernel();
}
static struct kmem_cache * minix_inode_cachep;
diff --git a/fs/namei.c b/fs/namei.c
index b8433ebfae05..5472ed04ad79 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -552,6 +552,17 @@ static __always_inline int link_path_walk(const char *name, struct nameidata *nd
return result;
}
+static __always_inline void set_root(struct nameidata *nd)
+{
+ if (!nd->root.mnt) {
+ struct fs_struct *fs = current->fs;
+ read_lock(&fs->lock);
+ nd->root = fs->root;
+ path_get(&nd->root);
+ read_unlock(&fs->lock);
+ }
+}
+
static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link)
{
int res = 0;
@@ -560,14 +571,10 @@ static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *l
goto fail;
if (*link == '/') {
- struct fs_struct *fs = current->fs;
-
+ set_root(nd);
path_put(&nd->path);
-
- read_lock(&fs->lock);
- nd->path = fs->root;
- path_get(&fs->root);
- read_unlock(&fs->lock);
+ nd->path = nd->root;
+ path_get(&nd->root);
}
res = link_path_walk(link, nd);
@@ -668,23 +675,23 @@ loop:
return err;
}
-int follow_up(struct vfsmount **mnt, struct dentry **dentry)
+int follow_up(struct path *path)
{
struct vfsmount *parent;
struct dentry *mountpoint;
spin_lock(&vfsmount_lock);
- parent=(*mnt)->mnt_parent;
- if (parent == *mnt) {
+ parent = path->mnt->mnt_parent;
+ if (parent == path->mnt) {
spin_unlock(&vfsmount_lock);
return 0;
}
mntget(parent);
- mountpoint=dget((*mnt)->mnt_mountpoint);
+ mountpoint = dget(path->mnt->mnt_mountpoint);
spin_unlock(&vfsmount_lock);
- dput(*dentry);
- *dentry = mountpoint;
- mntput(*mnt);
- *mnt = parent;
+ dput(path->dentry);
+ path->dentry = mountpoint;
+ mntput(path->mnt);
+ path->mnt = parent;
return 1;
}
@@ -695,7 +702,7 @@ static int __follow_mount(struct path *path)
{
int res = 0;
while (d_mountpoint(path->dentry)) {
- struct vfsmount *mounted = lookup_mnt(path->mnt, path->dentry);
+ struct vfsmount *mounted = lookup_mnt(path);
if (!mounted)
break;
dput(path->dentry);
@@ -708,32 +715,32 @@ static int __follow_mount(struct path *path)
return res;
}
-static void follow_mount(struct vfsmount **mnt, struct dentry **dentry)
+static void follow_mount(struct path *path)
{
- while (d_mountpoint(*dentry)) {
- struct vfsmount *mounted = lookup_mnt(*mnt, *dentry);
+ while (d_mountpoint(path->dentry)) {
+ struct vfsmount *mounted = lookup_mnt(path);
if (!mounted)
break;
- dput(*dentry);
- mntput(*mnt);
- *mnt = mounted;
- *dentry = dget(mounted->mnt_root);
+ dput(path->dentry);
+ mntput(path->mnt);
+ path->mnt = mounted;
+ path->dentry = dget(mounted->mnt_root);
}
}
/* no need for dcache_lock, as serialization is taken care in
* namespace.c
*/
-int follow_down(struct vfsmount **mnt, struct dentry **dentry)
+int follow_down(struct path *path)
{
struct vfsmount *mounted;
- mounted = lookup_mnt(*mnt, *dentry);
+ mounted = lookup_mnt(path);
if (mounted) {
- dput(*dentry);
- mntput(*mnt);
- *mnt = mounted;
- *dentry = dget(mounted->mnt_root);
+ dput(path->dentry);
+ mntput(path->mnt);
+ path->mnt = mounted;
+ path->dentry = dget(mounted->mnt_root);
return 1;
}
return 0;
@@ -741,19 +748,16 @@ int follow_down(struct vfsmount **mnt, struct dentry **dentry)
static __always_inline void follow_dotdot(struct nameidata *nd)
{
- struct fs_struct *fs = current->fs;
+ set_root(nd);
while(1) {
struct vfsmount *parent;
struct dentry *old = nd->path.dentry;
- read_lock(&fs->lock);
- if (nd->path.dentry == fs->root.dentry &&
- nd->path.mnt == fs->root.mnt) {
- read_unlock(&fs->lock);
+ if (nd->path.dentry == nd->root.dentry &&
+ nd->path.mnt == nd->root.mnt) {
break;
}
- read_unlock(&fs->lock);
spin_lock(&dcache_lock);
if (nd->path.dentry != nd->path.mnt->mnt_root) {
nd->path.dentry = dget(nd->path.dentry->d_parent);
@@ -775,7 +779,7 @@ static __always_inline void follow_dotdot(struct nameidata *nd)
mntput(nd->path.mnt);
nd->path.mnt = parent;
}
- follow_mount(&nd->path.mnt, &nd->path.dentry);
+ follow_mount(&nd->path);
}
/*
@@ -1016,25 +1020,23 @@ static int path_walk(const char *name, struct nameidata *nd)
return link_path_walk(name, nd);
}
-/* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
-static int do_path_lookup(int dfd, const char *name,
- unsigned int flags, struct nameidata *nd)
+static int path_init(int dfd, const char *name, unsigned int flags, struct nameidata *nd)
{
int retval = 0;
int fput_needed;
struct file *file;
- struct fs_struct *fs = current->fs;
nd->last_type = LAST_ROOT; /* if there are only slashes... */
nd->flags = flags;
nd->depth = 0;
+ nd->root.mnt = NULL;
if (*name=='/') {
- read_lock(&fs->lock);
- nd->path = fs->root;
- path_get(&fs->root);
- read_unlock(&fs->lock);
+ set_root(nd);
+ nd->path = nd->root;
+ path_get(&nd->root);
} else if (dfd == AT_FDCWD) {
+ struct fs_struct *fs = current->fs;
read_lock(&fs->lock);
nd->path = fs->pwd;
path_get(&fs->pwd);
@@ -1062,17 +1064,29 @@ static int do_path_lookup(int dfd, const char *name,
fput_light(file, fput_needed);
}
+ return 0;
- retval = path_walk(name, nd);
+fput_fail:
+ fput_light(file, fput_needed);
+out_fail:
+ return retval;
+}
+
+/* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
+static int do_path_lookup(int dfd, const char *name,
+ unsigned int flags, struct nameidata *nd)
+{
+ int retval = path_init(dfd, name, flags, nd);
+ if (!retval)
+ retval = path_walk(name, nd);
if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry &&
nd->path.dentry->d_inode))
audit_inode(name, nd->path.dentry);
-out_fail:
+ if (nd->root.mnt) {
+ path_put(&nd->root);
+ nd->root.mnt = NULL;
+ }
return retval;
-
-fput_fail:
- fput_light(file, fput_needed);
- goto out_fail;
}
int path_lookup(const char *name, unsigned int flags,
@@ -1112,14 +1126,18 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
nd->path.dentry = dentry;
nd->path.mnt = mnt;
path_get(&nd->path);
+ nd->root = nd->path;
+ path_get(&nd->root);
retval = path_walk(name, nd);
if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry &&
nd->path.dentry->d_inode))
audit_inode(name, nd->path.dentry);
- return retval;
+ path_put(&nd->root);
+ nd->root.mnt = NULL;
+ return retval;
}
/**
@@ -1130,8 +1148,8 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
* @nd: pointer to nameidata
* @open_flags: open intent flags
*/
-int path_lookup_open(int dfd, const char *name, unsigned int lookup_flags,
- struct nameidata *nd, int open_flags)
+static int path_lookup_open(int dfd, const char *name,
+ unsigned int lookup_flags, struct nameidata *nd, int open_flags)
{
struct file *filp = get_empty_filp();
int err;
@@ -1248,6 +1266,8 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
int err;
struct qstr this;
+ WARN_ON_ONCE(!mutex_is_locked(&base->d_inode->i_mutex));
+
err = __lookup_one_len(name, &this, base, len);
if (err)
return ERR_PTR(err);
@@ -1635,18 +1655,19 @@ static int open_will_write_to_fs(int flag, struct inode *inode)
* open_to_namei_flags() for more details.
*/
struct file *do_filp_open(int dfd, const char *pathname,
- int open_flag, int mode)
+ int open_flag, int mode, int acc_mode)
{
struct file *filp;
struct nameidata nd;
- int acc_mode, error;
+ int error;
struct path path;
struct dentry *dir;
int count = 0;
int will_write;
int flag = open_to_namei_flags(open_flag);
- acc_mode = MAY_OPEN | ACC_MODE(flag);
+ if (!acc_mode)
+ acc_mode = MAY_OPEN | ACC_MODE(flag);
/* O_TRUNC implies we need access checks for write permissions */
if (flag & O_TRUNC)
@@ -1671,9 +1692,14 @@ struct file *do_filp_open(int dfd, const char *pathname,
/*
* Create - we need to know the parent.
*/
- error = do_path_lookup(dfd, pathname, LOOKUP_PARENT, &nd);
+ error = path_init(dfd, pathname, LOOKUP_PARENT, &nd);
if (error)
return ERR_PTR(error);
+ error = path_walk(pathname, &nd);
+ if (error)
+ return ERR_PTR(error);
+ if (unlikely(!audit_dummy_context()))
+ audit_inode(pathname, nd.path.dentry);
/*
* We have the parent and last component. First of all, check
@@ -1801,6 +1827,8 @@ exit:
if (!IS_ERR(nd.intent.open.file))
release_open_intent(&nd);
exit_parent:
+ if (nd.root.mnt)
+ path_put(&nd.root);
path_put(&nd.path);
return ERR_PTR(error);
@@ -1867,7 +1895,7 @@ do_link:
*/
struct file *filp_open(const char *filename, int flags, int mode)
{
- return do_filp_open(AT_FDCWD, filename, flags, mode);
+ return do_filp_open(AT_FDCWD, filename, flags, mode, 0);
}
EXPORT_SYMBOL(filp_open);
diff --git a/fs/namespace.c b/fs/namespace.c
index c6f54e4c4290..2dd333b0fe7f 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -131,10 +131,20 @@ struct vfsmount *alloc_vfsmnt(const char *name)
INIT_LIST_HEAD(&mnt->mnt_share);
INIT_LIST_HEAD(&mnt->mnt_slave_list);
INIT_LIST_HEAD(&mnt->mnt_slave);
- atomic_set(&mnt->__mnt_writers, 0);
+#ifdef CONFIG_SMP
+ mnt->mnt_writers = alloc_percpu(int);
+ if (!mnt->mnt_writers)
+ goto out_free_devname;
+#else
+ mnt->mnt_writers = 0;
+#endif
}
return mnt;
+#ifdef CONFIG_SMP
+out_free_devname:
+ kfree(mnt->mnt_devname);
+#endif
out_free_id:
mnt_free_id(mnt);
out_free_cache:
@@ -171,65 +181,38 @@ int __mnt_is_readonly(struct vfsmount *mnt)
}
EXPORT_SYMBOL_GPL(__mnt_is_readonly);
-struct mnt_writer {
- /*
- * If holding multiple instances of this lock, they
- * must be ordered by cpu number.
- */
- spinlock_t lock;
- struct lock_class_key lock_class; /* compiles out with !lockdep */
- unsigned long count;
- struct vfsmount *mnt;
-} ____cacheline_aligned_in_smp;
-static DEFINE_PER_CPU(struct mnt_writer, mnt_writers);
+static inline void inc_mnt_writers(struct vfsmount *mnt)
+{
+#ifdef CONFIG_SMP
+ (*per_cpu_ptr(mnt->mnt_writers, smp_processor_id()))++;
+#else
+ mnt->mnt_writers++;
+#endif
+}
-static int __init init_mnt_writers(void)
+static inline void dec_mnt_writers(struct vfsmount *mnt)
{
- int cpu;
- for_each_possible_cpu(cpu) {
- struct mnt_writer *writer = &per_cpu(mnt_writers, cpu);
- spin_lock_init(&writer->lock);
- lockdep_set_class(&writer->lock, &writer->lock_class);
- writer->count = 0;
- }
- return 0;
+#ifdef CONFIG_SMP
+ (*per_cpu_ptr(mnt->mnt_writers, smp_processor_id()))--;
+#else
+ mnt->mnt_writers--;
+#endif
}
-fs_initcall(init_mnt_writers);
-static void unlock_mnt_writers(void)
+static unsigned int count_mnt_writers(struct vfsmount *mnt)
{
+#ifdef CONFIG_SMP
+ unsigned int count = 0;
int cpu;
- struct mnt_writer *cpu_writer;
for_each_possible_cpu(cpu) {
- cpu_writer = &per_cpu(mnt_writers, cpu);
- spin_unlock(&cpu_writer->lock);
+ count += *per_cpu_ptr(mnt->mnt_writers, cpu);
}
-}
-static inline void __clear_mnt_count(struct mnt_writer *cpu_writer)
-{
- if (!cpu_writer->mnt)
- return;
- /*
- * This is in case anyone ever leaves an invalid,
- * old ->mnt and a count of 0.
- */
- if (!cpu_writer->count)
- return;
- atomic_add(cpu_writer->count, &cpu_writer->mnt->__mnt_writers);
- cpu_writer->count = 0;
-}
- /*
- * must hold cpu_writer->lock
- */
-static inline void use_cpu_writer_for_mount(struct mnt_writer *cpu_writer,
- struct vfsmount *mnt)
-{
- if (cpu_writer->mnt == mnt)
- return;
- __clear_mnt_count(cpu_writer);
- cpu_writer->mnt = mnt;
+ return count;
+#else
+ return mnt->mnt_writers;
+#endif
}
/*
@@ -253,74 +236,73 @@ static inline void use_cpu_writer_for_mount(struct mnt_writer *cpu_writer,
int mnt_want_write(struct vfsmount *mnt)
{
int ret = 0;
- struct mnt_writer *cpu_writer;
- cpu_writer = &get_cpu_var(mnt_writers);
- spin_lock(&cpu_writer->lock);
+ preempt_disable();
+ inc_mnt_writers(mnt);
+ /*
+ * The store to inc_mnt_writers must be visible before we pass
+ * MNT_WRITE_HOLD loop below, so that the slowpath can see our
+ * incremented count after it has set MNT_WRITE_HOLD.
+ */
+ smp_mb();
+ while (mnt->mnt_flags & MNT_WRITE_HOLD)
+ cpu_relax();
+ /*
+ * After the slowpath clears MNT_WRITE_HOLD, mnt_is_readonly will
+ * be set to match its requirements. So we must not load that until
+ * MNT_WRITE_HOLD is cleared.
+ */
+ smp_rmb();
if (__mnt_is_readonly(mnt)) {
+ dec_mnt_writers(mnt);
ret = -EROFS;
goto out;
}
- use_cpu_writer_for_mount(cpu_writer, mnt);
- cpu_writer->count++;
out:
- spin_unlock(&cpu_writer->lock);
- put_cpu_var(mnt_writers);
+ preempt_enable();
return ret;
}
EXPORT_SYMBOL_GPL(mnt_want_write);
-static void lock_mnt_writers(void)
-{
- int cpu;
- struct mnt_writer *cpu_writer;
-
- for_each_possible_cpu(cpu) {
- cpu_writer = &per_cpu(mnt_writers, cpu);
- spin_lock(&cpu_writer->lock);
- __clear_mnt_count(cpu_writer);
- cpu_writer->mnt = NULL;
- }
+/**
+ * mnt_clone_write - get write access to a mount
+ * @mnt: the mount on which to take a write
+ *
+ * This is effectively like mnt_want_write, except
+ * it must only be used to take an extra write reference
+ * on a mountpoint that we already know has a write reference
+ * on it. This allows some optimisation.
+ *
+ * After finished, mnt_drop_write must be called as usual to
+ * drop the reference.
+ */
+int mnt_clone_write(struct vfsmount *mnt)
+{
+ /* superblock may be r/o */
+ if (__mnt_is_readonly(mnt))
+ return -EROFS;
+ preempt_disable();
+ inc_mnt_writers(mnt);
+ preempt_enable();
+ return 0;
}
+EXPORT_SYMBOL_GPL(mnt_clone_write);
-/*
- * These per-cpu write counts are not guaranteed to have
- * matched increments and decrements on any given cpu.
- * A file open()ed for write on one cpu and close()d on
- * another cpu will imbalance this count. Make sure it
- * does not get too far out of whack.
+/**
+ * mnt_want_write_file - get write access to a file's mount
+ * @file: the file who's mount on which to take a write
+ *
+ * This is like mnt_want_write, but it takes a file and can
+ * do some optimisations if the file is open for write already
*/
-static void handle_write_count_underflow(struct vfsmount *mnt)
+int mnt_want_write_file(struct file *file)
{
- if (atomic_read(&mnt->__mnt_writers) >=
- MNT_WRITER_UNDERFLOW_LIMIT)
- return;
- /*
- * It isn't necessary to hold all of the locks
- * at the same time, but doing it this way makes
- * us share a lot more code.
- */
- lock_mnt_writers();
- /*
- * vfsmount_lock is for mnt_flags.
- */
- spin_lock(&vfsmount_lock);
- /*
- * If coalescing the per-cpu writer counts did not
- * get us back to a positive writer count, we have
- * a bug.
- */
- if ((atomic_read(&mnt->__mnt_writers) < 0) &&
- !(mnt->mnt_flags & MNT_IMBALANCED_WRITE_COUNT)) {
- WARN(1, KERN_DEBUG "leak detected on mount(%p) writers "
- "count: %d\n",
- mnt, atomic_read(&mnt->__mnt_writers));
- /* use the flag to keep the dmesg spam down */
- mnt->mnt_flags |= MNT_IMBALANCED_WRITE_COUNT;
- }
- spin_unlock(&vfsmount_lock);
- unlock_mnt_writers();
+ if (!(file->f_mode & FMODE_WRITE))
+ return mnt_want_write(file->f_path.mnt);
+ else
+ return mnt_clone_write(file->f_path.mnt);
}
+EXPORT_SYMBOL_GPL(mnt_want_write_file);
/**
* mnt_drop_write - give up write access to a mount
@@ -332,37 +314,9 @@ static void handle_write_count_underflow(struct vfsmount *mnt)
*/
void mnt_drop_write(struct vfsmount *mnt)
{
- int must_check_underflow = 0;
- struct mnt_writer *cpu_writer;
-
- cpu_writer = &get_cpu_var(mnt_writers);
- spin_lock(&cpu_writer->lock);
-
- use_cpu_writer_for_mount(cpu_writer, mnt);
- if (cpu_writer->count > 0) {
- cpu_writer->count--;
- } else {
- must_check_underflow = 1;
- atomic_dec(&mnt->__mnt_writers);
- }
-
- spin_unlock(&cpu_writer->lock);
- /*
- * Logically, we could call this each time,
- * but the __mnt_writers cacheline tends to
- * be cold, and makes this expensive.
- */
- if (must_check_underflow)
- handle_write_count_underflow(mnt);
- /*
- * This could be done right after the spinlock
- * is taken because the spinlock keeps us on
- * the cpu, and disables preemption. However,
- * putting it here bounds the amount that
- * __mnt_writers can underflow. Without it,
- * we could theoretically wrap __mnt_writers.
- */
- put_cpu_var(mnt_writers);
+ preempt_disable();
+ dec_mnt_writers(mnt);
+ preempt_enable();
}
EXPORT_SYMBOL_GPL(mnt_drop_write);
@@ -370,24 +324,41 @@ static int mnt_make_readonly(struct vfsmount *mnt)
{
int ret = 0;
- lock_mnt_writers();
+ spin_lock(&vfsmount_lock);
+ mnt->mnt_flags |= MNT_WRITE_HOLD;
/*
- * With all the locks held, this value is stable
+ * After storing MNT_WRITE_HOLD, we'll read the counters. This store
+ * should be visible before we do.
*/
- if (atomic_read(&mnt->__mnt_writers) > 0) {
- ret = -EBUSY;
- goto out;
- }
+ smp_mb();
+
/*
- * nobody can do a successful mnt_want_write() with all
- * of the counts in MNT_DENIED_WRITE and the locks held.
+ * With writers on hold, if this value is zero, then there are
+ * definitely no active writers (although held writers may subsequently
+ * increment the count, they'll have to wait, and decrement it after
+ * seeing MNT_READONLY).
+ *
+ * It is OK to have counter incremented on one CPU and decremented on
+ * another: the sum will add up correctly. The danger would be when we
+ * sum up each counter, if we read a counter before it is incremented,
+ * but then read another CPU's count which it has been subsequently
+ * decremented from -- we would see more decrements than we should.
+ * MNT_WRITE_HOLD protects against this scenario, because
+ * mnt_want_write first increments count, then smp_mb, then spins on
+ * MNT_WRITE_HOLD, so it can't be decremented by another CPU while
+ * we're counting up here.
*/
- spin_lock(&vfsmount_lock);
- if (!ret)
+ if (count_mnt_writers(mnt) > 0)
+ ret = -EBUSY;
+ else
mnt->mnt_flags |= MNT_READONLY;
+ /*
+ * MNT_READONLY must become visible before ~MNT_WRITE_HOLD, so writers
+ * that become unheld will see MNT_READONLY.
+ */
+ smp_wmb();
+ mnt->mnt_flags &= ~MNT_WRITE_HOLD;
spin_unlock(&vfsmount_lock);
-out:
- unlock_mnt_writers();
return ret;
}
@@ -410,6 +381,9 @@ void free_vfsmnt(struct vfsmount *mnt)
{
kfree(mnt->mnt_devname);
mnt_free_id(mnt);
+#ifdef CONFIG_SMP
+ free_percpu(mnt->mnt_writers);
+#endif
kmem_cache_free(mnt_cache, mnt);
}
@@ -442,11 +416,11 @@ struct vfsmount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry,
* lookup_mnt increments the ref count before returning
* the vfsmount struct.
*/
-struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry)
+struct vfsmount *lookup_mnt(struct path *path)
{
struct vfsmount *child_mnt;
spin_lock(&vfsmount_lock);
- if ((child_mnt = __lookup_mnt(mnt, dentry, 1)))
+ if ((child_mnt = __lookup_mnt(path->mnt, path->dentry, 1)))
mntget(child_mnt);
spin_unlock(&vfsmount_lock);
return child_mnt;
@@ -604,38 +578,18 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
static inline void __mntput(struct vfsmount *mnt)
{
- int cpu;
struct super_block *sb = mnt->mnt_sb;
/*
- * We don't have to hold all of the locks at the
- * same time here because we know that we're the
- * last reference to mnt and that no new writers
- * can come in.
- */
- for_each_possible_cpu(cpu) {
- struct mnt_writer *cpu_writer = &per_cpu(mnt_writers, cpu);
- spin_lock(&cpu_writer->lock);
- if (cpu_writer->mnt != mnt) {
- spin_unlock(&cpu_writer->lock);
- continue;
- }
- atomic_add(cpu_writer->count, &mnt->__mnt_writers);
- cpu_writer->count = 0;
- /*
- * Might as well do this so that no one
- * ever sees the pointer and expects
- * it to be valid.
- */
- cpu_writer->mnt = NULL;
- spin_unlock(&cpu_writer->lock);
- }
- /*
* This probably indicates that somebody messed
* up a mnt_want/drop_write() pair. If this
* happens, the filesystem was probably unable
* to make r/w->r/o transitions.
*/
- WARN_ON(atomic_read(&mnt->__mnt_writers));
+ /*
+ * atomic_dec_and_lock() used to deal with ->mnt_count decrements
+ * provides barriers, so count_mnt_writers() below is safe. AV
+ */
+ WARN_ON(count_mnt_writers(mnt));
dput(mnt->mnt_root);
free_vfsmnt(mnt);
deactivate_super(sb);
@@ -695,12 +649,16 @@ static inline void mangle(struct seq_file *m, const char *s)
*/
int generic_show_options(struct seq_file *m, struct vfsmount *mnt)
{
- const char *options = mnt->mnt_sb->s_options;
+ const char *options;
+
+ rcu_read_lock();
+ options = rcu_dereference(mnt->mnt_sb->s_options);
if (options != NULL && options[0]) {
seq_putc(m, ',');
mangle(m, options);
}
+ rcu_read_unlock();
return 0;
}
@@ -721,11 +679,22 @@ EXPORT_SYMBOL(generic_show_options);
*/
void save_mount_options(struct super_block *sb, char *options)
{
- kfree(sb->s_options);
- sb->s_options = kstrdup(options, GFP_KERNEL);
+ BUG_ON(sb->s_options);
+ rcu_assign_pointer(sb->s_options, kstrdup(options, GFP_KERNEL));
}
EXPORT_SYMBOL(save_mount_options);
+void replace_mount_options(struct super_block *sb, char *options)
+{
+ char *old = sb->s_options;
+ rcu_assign_pointer(sb->s_options, options);
+ if (old) {
+ synchronize_rcu();
+ kfree(old);
+ }
+}
+EXPORT_SYMBOL(replace_mount_options);
+
#ifdef CONFIG_PROC_FS
/* iterator */
static void *m_start(struct seq_file *m, loff_t *pos)
@@ -1073,9 +1042,7 @@ static int do_umount(struct vfsmount *mnt, int flags)
*/
if (flags & MNT_FORCE && sb->s_op->umount_begin) {
- lock_kernel();
sb->s_op->umount_begin(sb);
- unlock_kernel();
}
/*
@@ -1093,11 +1060,8 @@ static int do_umount(struct vfsmount *mnt, int flags)
* we just try to remount it readonly.
*/
down_write(&sb->s_umount);
- if (!(sb->s_flags & MS_RDONLY)) {
- lock_kernel();
+ if (!(sb->s_flags & MS_RDONLY))
retval = do_remount_sb(sb, MS_RDONLY, NULL, 0);
- unlock_kernel();
- }
up_write(&sb->s_umount);
return retval;
}
@@ -1240,11 +1204,11 @@ Enomem:
return NULL;
}
-struct vfsmount *collect_mounts(struct vfsmount *mnt, struct dentry *dentry)
+struct vfsmount *collect_mounts(struct path *path)
{
struct vfsmount *tree;
down_write(&namespace_sem);
- tree = copy_tree(mnt, dentry, CL_COPY_ALL | CL_PRIVATE);
+ tree = copy_tree(path->mnt, path->dentry, CL_COPY_ALL | CL_PRIVATE);
up_write(&namespace_sem);
return tree;
}
@@ -1377,7 +1341,7 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt,
if (parent_path) {
detach_mnt(source_mnt, parent_path);
attach_mnt(source_mnt, path);
- touch_mnt_namespace(current->nsproxy->mnt_ns);
+ touch_mnt_namespace(parent_path->mnt->mnt_ns);
} else {
mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt);
commit_tree(source_mnt);
@@ -1417,7 +1381,7 @@ static int graft_tree(struct vfsmount *mnt, struct path *path)
goto out_unlock;
err = -ENOENT;
- if (IS_ROOT(path->dentry) || !d_unhashed(path->dentry))
+ if (!d_unlinked(path->dentry))
err = attach_recursive_mnt(mnt, path, NULL);
out_unlock:
mutex_unlock(&path->dentry->d_inode->i_mutex);
@@ -1588,7 +1552,7 @@ static int do_move_mount(struct path *path, char *old_name)
down_write(&namespace_sem);
while (d_mountpoint(path->dentry) &&
- follow_down(&path->mnt, &path->dentry))
+ follow_down(path))
;
err = -EINVAL;
if (!check_mnt(path->mnt) || !check_mnt(old_path.mnt))
@@ -1599,7 +1563,7 @@ static int do_move_mount(struct path *path, char *old_name)
if (IS_DEADDIR(path->dentry->d_inode))
goto out1;
- if (!IS_ROOT(path->dentry) && d_unhashed(path->dentry))
+ if (d_unlinked(path->dentry))
goto out1;
err = -EINVAL;
@@ -1663,7 +1627,9 @@ static int do_new_mount(struct path *path, char *type, int flags,
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
+ lock_kernel();
mnt = do_kern_mount(type, flags, name, data);
+ unlock_kernel();
if (IS_ERR(mnt))
return PTR_ERR(mnt);
@@ -1682,10 +1648,10 @@ int do_add_mount(struct vfsmount *newmnt, struct path *path,
down_write(&namespace_sem);
/* Something was mounted here while we slept */
while (d_mountpoint(path->dentry) &&
- follow_down(&path->mnt, &path->dentry))
+ follow_down(path))
;
err = -EINVAL;
- if (!check_mnt(path->mnt))
+ if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(path->mnt))
goto unlock;
/* Refuse the same filesystem on the same mount point */
@@ -1920,8 +1886,9 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
if (data_page)
((char *)data_page)[PAGE_SIZE - 1] = 0;
- /* Default to relatime */
- mnt_flags |= MNT_RELATIME;
+ /* Default to relatime unless overriden */
+ if (!(flags & MS_NOATIME))
+ mnt_flags |= MNT_RELATIME;
/* Separate the per-mountpoint flags */
if (flags & MS_NOSUID)
@@ -2078,10 +2045,8 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
if (retval < 0)
goto out3;
- lock_kernel();
retval = do_mount((char *)dev_page, dir_page, (char *)type_page,
flags, (void *)data_page);
- unlock_kernel();
free_page(data_page);
out3:
@@ -2161,9 +2126,9 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
error = -ENOENT;
if (IS_DEADDIR(new.dentry->d_inode))
goto out2;
- if (d_unhashed(new.dentry) && !IS_ROOT(new.dentry))
+ if (d_unlinked(new.dentry))
goto out2;
- if (d_unhashed(old.dentry) && !IS_ROOT(old.dentry))
+ if (d_unlinked(old.dentry))
goto out2;
error = -EBUSY;
if (new.mnt == root.mnt ||
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index d642f0e5b365..b99ce205b1bd 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -736,6 +736,8 @@ static void ncp_put_super(struct super_block *sb)
{
struct ncp_server *server = NCP_SBP(sb);
+ lock_kernel();
+
ncp_lock_server(server);
ncp_disconnect(server);
ncp_unlock_server(server);
@@ -769,6 +771,8 @@ static void ncp_put_super(struct super_block *sb)
vfree(server->packet);
sb->s_fs_info = NULL;
kfree(server);
+
+ unlock_kernel();
}
static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
index f54360f50a9c..fa038df63ac8 100644
--- a/fs/ncpfs/ioctl.c
+++ b/fs/ncpfs/ioctl.c
@@ -660,13 +660,10 @@ outrel:
if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN)
return -ENOMEM;
if (user.object_name_len) {
- newname = kmalloc(user.object_name_len, GFP_USER);
- if (!newname)
- return -ENOMEM;
- if (copy_from_user(newname, user.object_name, user.object_name_len)) {
- kfree(newname);
- return -EFAULT;
- }
+ newname = memdup_user(user.object_name,
+ user.object_name_len);
+ if (IS_ERR(newname))
+ return PTR_ERR(newname);
} else {
newname = NULL;
}
@@ -760,13 +757,9 @@ outrel:
if (user.len > NCP_PRIVATE_DATA_MAX_LEN)
return -ENOMEM;
if (user.len) {
- new = kmalloc(user.len, GFP_USER);
- if (!new)
- return -ENOMEM;
- if (copy_from_user(new, user.data, user.len)) {
- kfree(new);
- return -EFAULT;
- }
+ new = memdup_user(user.data, user.len);
+ if (IS_ERR(new))
+ return PTR_ERR(new);
} else {
new = NULL;
}
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index e67f3ec07736..5d6d6f415935 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -74,6 +74,15 @@ config NFS_V4
If unsure, say N.
+config NFS_V4_1
+ bool "NFS client support for NFSv4.1 (DEVELOPER ONLY)"
+ depends on NFS_V4 && EXPERIMENTAL
+ help
+ This option enables support for minor version 1 of the NFSv4 protocol
+ (draft-ietf-nfsv4-minorversion1) in the kernel's NFS client.
+
+ Unless you're an NFS developer, say N.
+
config ROOT_NFS
bool "Root file system on NFS"
depends on NFS_FS=y && IP_PNP
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 75c9cd2aa119..3e232bf56dfb 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -102,6 +102,7 @@ struct nfs_client_initdata {
size_t addrlen;
const struct nfs_rpc_ops *rpc_ops;
int proto;
+ u32 minorversion;
};
/*
@@ -150,6 +151,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
clp->cl_boot_time = CURRENT_TIME;
clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
+ clp->cl_minorversion = cl_init->minorversion;
#endif
cred = rpc_lookup_machine_cred();
if (!IS_ERR(cred))
@@ -182,12 +184,29 @@ static void nfs4_shutdown_client(struct nfs_client *clp)
}
/*
+ * Clears/puts all minor version specific parts from an nfs_client struct
+ * reverting it to minorversion 0.
+ */
+static void nfs4_clear_client_minor_version(struct nfs_client *clp)
+{
+#ifdef CONFIG_NFS_V4_1
+ if (nfs4_has_session(clp)) {
+ nfs4_destroy_session(clp->cl_session);
+ clp->cl_session = NULL;
+ }
+
+ clp->cl_call_sync = _nfs4_call_sync;
+#endif /* CONFIG_NFS_V4_1 */
+}
+
+/*
* Destroy a shared client record
*/
static void nfs_free_client(struct nfs_client *clp)
{
dprintk("--> nfs_free_client(%u)\n", clp->rpc_ops->version);
+ nfs4_clear_client_minor_version(clp);
nfs4_shutdown_client(clp);
nfs_fscache_release_client_cookie(clp);
@@ -347,7 +366,8 @@ struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion)
struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
/* Don't match clients that failed to initialise properly */
- if (clp->cl_cons_state != NFS_CS_READY)
+ if (!(clp->cl_cons_state == NFS_CS_READY ||
+ clp->cl_cons_state == NFS_CS_SESSION_INITING))
continue;
/* Different NFS versions cannot share the same nfs_client */
@@ -420,7 +440,9 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
if (clp->cl_proto != data->proto)
continue;
-
+ /* Match nfsv4 minorversion */
+ if (clp->cl_minorversion != data->minorversion)
+ continue;
/* Match the full socket address */
if (!nfs_sockaddr_cmp(sap, clap))
continue;
@@ -478,7 +500,7 @@ found_client:
nfs_free_client(new);
error = wait_event_killable(nfs_client_active_wq,
- clp->cl_cons_state != NFS_CS_INITING);
+ clp->cl_cons_state < NFS_CS_INITING);
if (error < 0) {
nfs_put_client(clp);
return ERR_PTR(-ERESTARTSYS);
@@ -499,13 +521,29 @@ found_client:
/*
* Mark a server as ready or failed
*/
-static void nfs_mark_client_ready(struct nfs_client *clp, int state)
+void nfs_mark_client_ready(struct nfs_client *clp, int state)
{
clp->cl_cons_state = state;
wake_up_all(&nfs_client_active_wq);
}
/*
+ * With sessions, the client is not marked ready until after a
+ * successful EXCHANGE_ID and CREATE_SESSION.
+ *
+ * Map errors cl_cons_state errors to EPROTONOSUPPORT to indicate
+ * other versions of NFS can be tried.
+ */
+int nfs4_check_client_ready(struct nfs_client *clp)
+{
+ if (!nfs4_has_session(clp))
+ return 0;
+ if (clp->cl_cons_state < NFS_CS_READY)
+ return -EPROTONOSUPPORT;
+ return 0;
+}
+
+/*
* Initialise the timeout values for a connection
*/
static void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
@@ -1050,6 +1088,33 @@ error:
#ifdef CONFIG_NFS_V4
/*
+ * Initialize the minor version specific parts of an NFS4 client record
+ */
+static int nfs4_init_client_minor_version(struct nfs_client *clp)
+{
+ clp->cl_call_sync = _nfs4_call_sync;
+
+#if defined(CONFIG_NFS_V4_1)
+ if (clp->cl_minorversion) {
+ struct nfs4_session *session = NULL;
+ /*
+ * Create the session and mark it expired.
+ * When a SEQUENCE operation encounters the expired session
+ * it will do session recovery to initialize it.
+ */
+ session = nfs4_alloc_session(clp);
+ if (!session)
+ return -ENOMEM;
+
+ clp->cl_session = session;
+ clp->cl_call_sync = _nfs4_call_sync_session;
+ }
+#endif /* CONFIG_NFS_V4_1 */
+
+ return 0;
+}
+
+/*
* Initialise an NFS4 client record
*/
static int nfs4_init_client(struct nfs_client *clp,
@@ -1083,7 +1148,12 @@ static int nfs4_init_client(struct nfs_client *clp,
}
__set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
- nfs_mark_client_ready(clp, NFS_CS_READY);
+ error = nfs4_init_client_minor_version(clp);
+ if (error < 0)
+ goto error;
+
+ if (!nfs4_has_session(clp))
+ nfs_mark_client_ready(clp, NFS_CS_READY);
return 0;
error:
@@ -1101,7 +1171,8 @@ static int nfs4_set_client(struct nfs_server *server,
const size_t addrlen,
const char *ip_addr,
rpc_authflavor_t authflavour,
- int proto, const struct rpc_timeout *timeparms)
+ int proto, const struct rpc_timeout *timeparms,
+ u32 minorversion)
{
struct nfs_client_initdata cl_init = {
.hostname = hostname,
@@ -1109,6 +1180,7 @@ static int nfs4_set_client(struct nfs_server *server,
.addrlen = addrlen,
.rpc_ops = &nfs_v4_clientops,
.proto = proto,
+ .minorversion = minorversion,
};
struct nfs_client *clp;
int error;
@@ -1138,6 +1210,36 @@ error:
}
/*
+ * Initialize a session.
+ * Note: save the mount rsize and wsize for create_server negotiation.
+ */
+static void nfs4_init_session(struct nfs_client *clp,
+ unsigned int wsize, unsigned int rsize)
+{
+#if defined(CONFIG_NFS_V4_1)
+ if (nfs4_has_session(clp)) {
+ clp->cl_session->fc_attrs.max_rqst_sz = wsize;
+ clp->cl_session->fc_attrs.max_resp_sz = rsize;
+ }
+#endif /* CONFIG_NFS_V4_1 */
+}
+
+/*
+ * Session has been established, and the client marked ready.
+ * Set the mount rsize and wsize with negotiated fore channel
+ * attributes which will be bound checked in nfs_server_set_fsinfo.
+ */
+static void nfs4_session_set_rwsize(struct nfs_server *server)
+{
+#ifdef CONFIG_NFS_V4_1
+ if (!nfs4_has_session(server->nfs_client))
+ return;
+ server->rsize = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
+ server->wsize = server->nfs_client->cl_session->fc_attrs.max_rqst_sz;
+#endif /* CONFIG_NFS_V4_1 */
+}
+
+/*
* Create a version 4 volume record
*/
static int nfs4_init_server(struct nfs_server *server,
@@ -1164,7 +1266,8 @@ static int nfs4_init_server(struct nfs_server *server,
data->client_address,
data->auth_flavors[0],
data->nfs_server.protocol,
- &timeparms);
+ &timeparms,
+ data->minorversion);
if (error < 0)
goto error;
@@ -1214,6 +1317,8 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
BUG_ON(!server->nfs_client->rpc_ops);
BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
+ nfs4_init_session(server->nfs_client, server->wsize, server->rsize);
+
/* Probe the root fh to retrieve its FSID */
error = nfs4_path_walk(server, mntfh, data->nfs_server.export_path);
if (error < 0)
@@ -1224,6 +1329,8 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
(unsigned long long) server->fsid.minor);
dprintk("Mount FH: %d\n", mntfh->size);
+ nfs4_session_set_rwsize(server);
+
error = nfs_probe_fsinfo(server, mntfh, &fattr);
if (error < 0)
goto error;
@@ -1282,7 +1389,8 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
parent_client->cl_ipaddr,
data->authflavor,
parent_server->client->cl_xprt->prot,
- parent_server->client->cl_timeout);
+ parent_server->client->cl_timeout,
+ parent_client->cl_minorversion);
if (error < 0)
goto error;
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 08f6b040d289..489fc01a3204 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -259,6 +259,9 @@ static void nfs_direct_read_release(void *calldata)
}
static const struct rpc_call_ops nfs_read_direct_ops = {
+#if defined(CONFIG_NFS_V4_1)
+ .rpc_call_prepare = nfs_read_prepare,
+#endif /* CONFIG_NFS_V4_1 */
.rpc_call_done = nfs_direct_read_result,
.rpc_release = nfs_direct_read_release,
};
@@ -535,6 +538,9 @@ static void nfs_direct_commit_release(void *calldata)
}
static const struct rpc_call_ops nfs_commit_direct_ops = {
+#if defined(CONFIG_NFS_V4_1)
+ .rpc_call_prepare = nfs_write_prepare,
+#endif /* CONFIG_NFS_V4_1 */
.rpc_call_done = nfs_direct_commit_result,
.rpc_release = nfs_direct_commit_release,
};
@@ -673,6 +679,9 @@ out_unlock:
}
static const struct rpc_call_ops nfs_write_direct_ops = {
+#if defined(CONFIG_NFS_V4_1)
+ .rpc_call_prepare = nfs_write_prepare,
+#endif /* CONFIG_NFS_V4_1 */
.rpc_call_done = nfs_direct_write_result,
.rpc_release = nfs_direct_write_release,
};
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 5a97bcfe03e5..ec7e27d00bc6 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -517,10 +517,10 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
ret = nfs_updatepage(filp, page, 0, pagelen);
out_unlock:
+ if (!ret)
+ return VM_FAULT_LOCKED;
unlock_page(page);
- if (ret)
- ret = VM_FAULT_SIGBUS;
- return ret;
+ return VM_FAULT_SIGBUS;
}
static struct vm_operations_struct nfs_file_vm_ops = {
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index e4d6a8348adf..acee3274d275 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -2,6 +2,7 @@
* NFS internal definitions
*/
+#include "nfs4_fs.h"
#include <linux/mount.h>
#include <linux/security.h>
@@ -17,6 +18,18 @@ struct nfs_string;
*/
#define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1)
+/*
+ * Determine if sessions are in use.
+ */
+static inline int nfs4_has_session(const struct nfs_client *clp)
+{
+#ifdef CONFIG_NFS_V4_1
+ if (clp->cl_session)
+ return 1;
+#endif /* CONFIG_NFS_V4_1 */
+ return 0;
+}
+
struct nfs_clone_mount {
const struct super_block *sb;
const struct dentry *dentry;
@@ -44,6 +57,7 @@ struct nfs_parsed_mount_data {
unsigned int auth_flavor_len;
rpc_authflavor_t auth_flavors[1];
char *client_address;
+ unsigned int minorversion;
char *fscache_uniq;
struct {
@@ -99,6 +113,8 @@ extern void nfs_free_server(struct nfs_server *server);
extern struct nfs_server *nfs_clone_server(struct nfs_server *,
struct nfs_fh *,
struct nfs_fattr *);
+extern void nfs_mark_client_ready(struct nfs_client *clp, int state);
+extern int nfs4_check_client_ready(struct nfs_client *clp);
#ifdef CONFIG_PROC_FS
extern int __init nfs_fs_proc_init(void);
extern void nfs_fs_proc_exit(void);
@@ -146,6 +162,20 @@ extern __be32 * nfs_decode_dirent(__be32 *, struct nfs_entry *, int);
extern struct rpc_procinfo nfs3_procedures[];
extern __be32 *nfs3_decode_dirent(__be32 *, struct nfs_entry *, int);
+/* nfs4proc.c */
+static inline void nfs4_restart_rpc(struct rpc_task *task,
+ const struct nfs_client *clp)
+{
+#ifdef CONFIG_NFS_V4_1
+ if (nfs4_has_session(clp) &&
+ test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)) {
+ rpc_restart_call_prepare(task);
+ return;
+ }
+#endif /* CONFIG_NFS_V4_1 */
+ rpc_restart_call(task);
+}
+
/* nfs4xdr.c */
#ifdef CONFIG_NFS_V4
extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus);
@@ -205,6 +235,38 @@ extern int nfs4_path_walk(struct nfs_server *server,
const char *path);
#endif
+/* read.c */
+extern void nfs_read_prepare(struct rpc_task *task, void *calldata);
+
+/* write.c */
+extern void nfs_write_prepare(struct rpc_task *task, void *calldata);
+
+/* nfs4proc.c */
+extern int _nfs4_call_sync(struct nfs_server *server,
+ struct rpc_message *msg,
+ struct nfs4_sequence_args *args,
+ struct nfs4_sequence_res *res,
+ int cache_reply);
+extern int _nfs4_call_sync_session(struct nfs_server *server,
+ struct rpc_message *msg,
+ struct nfs4_sequence_args *args,
+ struct nfs4_sequence_res *res,
+ int cache_reply);
+
+#ifdef CONFIG_NFS_V4_1
+extern void nfs41_sequence_free_slot(const struct nfs_client *,
+ struct nfs4_sequence_res *res);
+#endif /* CONFIG_NFS_V4_1 */
+
+static inline void nfs4_sequence_free_slot(const struct nfs_client *clp,
+ struct nfs4_sequence_res *res)
+{
+#ifdef CONFIG_NFS_V4_1
+ if (nfs4_has_session(clp))
+ nfs41_sequence_free_slot(clp, res);
+#endif /* CONFIG_NFS_V4_1 */
+}
+
/*
* Determine the device name as a string
*/
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 64a288ee046d..f01caec84463 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -154,7 +154,7 @@ out_err:
goto out;
out_follow:
while (d_mountpoint(nd->path.dentry) &&
- follow_down(&nd->path.mnt, &nd->path.dentry))
+ follow_down(&nd->path))
;
err = 0;
goto out;
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index e6a1932c7110..35869a4921f1 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -713,7 +713,8 @@ nfs3_xdr_setaclargs(struct rpc_rqst *req, __be32 *p,
if (args->npages != 0)
xdr_encode_pages(buf, args->pages, 0, args->len);
else
- req->rq_slen += args->len;
+ req->rq_slen = xdr_adjust_iovec(req->rq_svec,
+ p + XDR_QUADLEN(args->len));
err = nfsacl_encode(buf, base, args->inode,
(args->mask & NFS_ACL) ?
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 84345deab26f..61bc3a32e1e2 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -44,6 +44,7 @@ enum nfs4_client_state {
NFS4CLNT_RECLAIM_REBOOT,
NFS4CLNT_RECLAIM_NOGRACE,
NFS4CLNT_DELEGRETURN,
+ NFS4CLNT_SESSION_SETUP,
};
/*
@@ -177,6 +178,14 @@ struct nfs4_state_recovery_ops {
int state_flag_bit;
int (*recover_open)(struct nfs4_state_owner *, struct nfs4_state *);
int (*recover_lock)(struct nfs4_state *, struct file_lock *);
+ int (*establish_clid)(struct nfs_client *, struct rpc_cred *);
+ struct rpc_cred * (*get_clid_cred)(struct nfs_client *);
+};
+
+struct nfs4_state_maintenance_ops {
+ int (*sched_state_renewal)(struct nfs_client *, struct rpc_cred *);
+ struct rpc_cred * (*get_state_renewal_cred_locked)(struct nfs_client *);
+ int (*renew_lease)(struct nfs_client *, struct rpc_cred *);
};
extern const struct dentry_operations nfs4_dentry_operations;
@@ -193,6 +202,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_init_clientid(struct nfs_client *, struct rpc_cred *);
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 *);
@@ -200,8 +210,26 @@ extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fh
extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
struct nfs4_fs_locations *fs_locations, struct page *page);
-extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
-extern struct nfs4_state_recovery_ops nfs4_nograce_recovery_ops;
+extern struct nfs4_state_recovery_ops *nfs4_reboot_recovery_ops[];
+extern struct nfs4_state_recovery_ops *nfs4_nograce_recovery_ops[];
+#if defined(CONFIG_NFS_V4_1)
+extern int nfs4_setup_sequence(struct nfs_client *clp,
+ struct nfs4_sequence_args *args, struct nfs4_sequence_res *res,
+ int cache_reply, struct rpc_task *task);
+extern void nfs4_destroy_session(struct nfs4_session *session);
+extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp);
+extern int nfs4_proc_create_session(struct nfs_client *, int reset);
+extern int nfs4_proc_destroy_session(struct nfs4_session *);
+#else /* CONFIG_NFS_v4_1 */
+static inline int nfs4_setup_sequence(struct nfs_client *clp,
+ struct nfs4_sequence_args *args, struct nfs4_sequence_res *res,
+ int cache_reply, struct rpc_task *task)
+{
+ return 0;
+}
+#endif /* CONFIG_NFS_V4_1 */
+
+extern struct nfs4_state_maintenance_ops *nfs4_state_renewal_ops[];
extern const u32 nfs4_fattr_bitmap[2];
extern const u32 nfs4_statfs_bitmap[2];
@@ -216,7 +244,12 @@ extern void nfs4_kill_renewd(struct nfs_client *);
extern void nfs4_renew_state(struct work_struct *);
/* nfs4state.c */
+struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp);
struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp);
+#if defined(CONFIG_NFS_V4_1)
+struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp);
+struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp);
+#endif /* CONFIG_NFS_V4_1 */
extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
extern void nfs4_put_state_owner(struct nfs4_state_owner *);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index a4d242680299..530ebb1e84fe 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -48,11 +48,13 @@
#include <linux/smp_lock.h>
#include <linux/namei.h>
#include <linux/mount.h>
+#include <linux/module.h>
#include "nfs4_fs.h"
#include "delegation.h"
#include "internal.h"
#include "iostat.h"
+#include "callback.h"
#define NFSDBG_FACILITY NFSDBG_PROC
@@ -247,7 +249,25 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
ret = nfs4_wait_clnt_recover(clp);
if (ret == 0)
exception->retry = 1;
+#if !defined(CONFIG_NFS_V4_1)
break;
+#else /* !defined(CONFIG_NFS_V4_1) */
+ if (!nfs4_has_session(server->nfs_client))
+ break;
+ /* FALLTHROUGH */
+ case -NFS4ERR_BADSESSION:
+ case -NFS4ERR_BADSLOT:
+ case -NFS4ERR_BAD_HIGH_SLOT:
+ case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
+ case -NFS4ERR_DEADSESSION:
+ case -NFS4ERR_SEQ_FALSE_RETRY:
+ case -NFS4ERR_SEQ_MISORDERED:
+ dprintk("%s ERROR: %d Reset session\n", __func__,
+ errorcode);
+ set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
+ exception->retry = 1;
+ /* FALLTHROUGH */
+#endif /* !defined(CONFIG_NFS_V4_1) */
case -NFS4ERR_FILE_OPEN:
case -NFS4ERR_GRACE:
case -NFS4ERR_DELAY:
@@ -271,6 +291,353 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp
spin_unlock(&clp->cl_lock);
}
+#if defined(CONFIG_NFS_V4_1)
+
+/*
+ * nfs4_free_slot - free a slot and efficiently update slot table.
+ *
+ * freeing a slot is trivially done by clearing its respective bit
+ * in the bitmap.
+ * If the freed slotid equals highest_used_slotid we want to update it
+ * so that the server would be able to size down the slot table if needed,
+ * otherwise we know that the highest_used_slotid is still in use.
+ * When updating highest_used_slotid there may be "holes" in the bitmap
+ * so we need to scan down from highest_used_slotid to 0 looking for the now
+ * highest slotid in use.
+ * If none found, highest_used_slotid is set to -1.
+ */
+static void
+nfs4_free_slot(struct nfs4_slot_table *tbl, u8 free_slotid)
+{
+ int slotid = free_slotid;
+
+ spin_lock(&tbl->slot_tbl_lock);
+ /* clear used bit in bitmap */
+ __clear_bit(slotid, tbl->used_slots);
+
+ /* update highest_used_slotid when it is freed */
+ if (slotid == tbl->highest_used_slotid) {
+ slotid = find_last_bit(tbl->used_slots, tbl->max_slots);
+ if (slotid >= 0 && slotid < tbl->max_slots)
+ tbl->highest_used_slotid = slotid;
+ else
+ tbl->highest_used_slotid = -1;
+ }
+ rpc_wake_up_next(&tbl->slot_tbl_waitq);
+ spin_unlock(&tbl->slot_tbl_lock);
+ dprintk("%s: free_slotid %u highest_used_slotid %d\n", __func__,
+ free_slotid, tbl->highest_used_slotid);
+}
+
+void nfs41_sequence_free_slot(const struct nfs_client *clp,
+ struct nfs4_sequence_res *res)
+{
+ struct nfs4_slot_table *tbl;
+
+ if (!nfs4_has_session(clp)) {
+ dprintk("%s: No session\n", __func__);
+ return;
+ }
+ tbl = &clp->cl_session->fc_slot_table;
+ if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) {
+ dprintk("%s: No slot\n", __func__);
+ /* just wake up the next guy waiting since
+ * we may have not consumed a slot after all */
+ rpc_wake_up_next(&tbl->slot_tbl_waitq);
+ return;
+ }
+ nfs4_free_slot(tbl, res->sr_slotid);
+ res->sr_slotid = NFS4_MAX_SLOT_TABLE;
+}
+
+static void nfs41_sequence_done(struct nfs_client *clp,
+ struct nfs4_sequence_res *res,
+ int rpc_status)
+{
+ unsigned long timestamp;
+ struct nfs4_slot_table *tbl;
+ struct nfs4_slot *slot;
+
+ /*
+ * sr_status remains 1 if an RPC level error occurred. The server
+ * may or may not have processed the sequence operation..
+ * Proceed as if the server received and processed the sequence
+ * operation.
+ */
+ if (res->sr_status == 1)
+ res->sr_status = NFS_OK;
+
+ /* -ERESTARTSYS can result in skipping nfs41_sequence_setup */
+ if (res->sr_slotid == NFS4_MAX_SLOT_TABLE)
+ goto out;
+
+ tbl = &clp->cl_session->fc_slot_table;
+ slot = tbl->slots + res->sr_slotid;
+
+ if (res->sr_status == 0) {
+ /* Update the slot's sequence and clientid lease timer */
+ ++slot->seq_nr;
+ timestamp = res->sr_renewal_time;
+ spin_lock(&clp->cl_lock);
+ if (time_before(clp->cl_last_renewal, timestamp))
+ clp->cl_last_renewal = timestamp;
+ spin_unlock(&clp->cl_lock);
+ return;
+ }
+out:
+ /* The session may be reset by one of the error handlers. */
+ dprintk("%s: Error %d free the slot \n", __func__, res->sr_status);
+ nfs41_sequence_free_slot(clp, res);
+}
+
+/*
+ * nfs4_find_slot - efficiently look for a free slot
+ *
+ * nfs4_find_slot looks for an unset bit in the used_slots bitmap.
+ * If found, we mark the slot as used, update the highest_used_slotid,
+ * and respectively set up the sequence operation args.
+ * The slot number is returned if found, or NFS4_MAX_SLOT_TABLE otherwise.
+ *
+ * Note: must be called with under the slot_tbl_lock.
+ */
+static u8
+nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task)
+{
+ int slotid;
+ u8 ret_id = NFS4_MAX_SLOT_TABLE;
+ BUILD_BUG_ON((u8)NFS4_MAX_SLOT_TABLE != (int)NFS4_MAX_SLOT_TABLE);
+
+ dprintk("--> %s used_slots=%04lx highest_used=%d max_slots=%d\n",
+ __func__, tbl->used_slots[0], tbl->highest_used_slotid,
+ tbl->max_slots);
+ slotid = find_first_zero_bit(tbl->used_slots, tbl->max_slots);
+ if (slotid >= tbl->max_slots)
+ goto out;
+ __set_bit(slotid, tbl->used_slots);
+ if (slotid > tbl->highest_used_slotid)
+ tbl->highest_used_slotid = slotid;
+ ret_id = slotid;
+out:
+ dprintk("<-- %s used_slots=%04lx highest_used=%d slotid=%d \n",
+ __func__, tbl->used_slots[0], tbl->highest_used_slotid, ret_id);
+ return ret_id;
+}
+
+static int nfs4_recover_session(struct nfs4_session *session)
+{
+ struct nfs_client *clp = session->clp;
+ int ret;
+
+ for (;;) {
+ ret = nfs4_wait_clnt_recover(clp);
+ if (ret != 0)
+ return ret;
+ if (!test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state))
+ break;
+ nfs4_schedule_state_manager(clp);
+ }
+ return 0;
+}
+
+static int nfs41_setup_sequence(struct nfs4_session *session,
+ struct nfs4_sequence_args *args,
+ struct nfs4_sequence_res *res,
+ int cache_reply,
+ struct rpc_task *task)
+{
+ struct nfs4_slot *slot;
+ struct nfs4_slot_table *tbl;
+ int status = 0;
+ u8 slotid;
+
+ dprintk("--> %s\n", __func__);
+ /* slot already allocated? */
+ if (res->sr_slotid != NFS4_MAX_SLOT_TABLE)
+ return 0;
+
+ memset(res, 0, sizeof(*res));
+ res->sr_slotid = NFS4_MAX_SLOT_TABLE;
+ tbl = &session->fc_slot_table;
+
+ spin_lock(&tbl->slot_tbl_lock);
+ if (test_bit(NFS4CLNT_SESSION_SETUP, &session->clp->cl_state)) {
+ if (tbl->highest_used_slotid != -1) {
+ rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
+ spin_unlock(&tbl->slot_tbl_lock);
+ dprintk("<-- %s: Session reset: draining\n", __func__);
+ return -EAGAIN;
+ }
+
+ /* The slot table is empty; start the reset thread */
+ dprintk("%s Session Reset\n", __func__);
+ spin_unlock(&tbl->slot_tbl_lock);
+ status = nfs4_recover_session(session);
+ if (status)
+ return status;
+ spin_lock(&tbl->slot_tbl_lock);
+ }
+
+ slotid = nfs4_find_slot(tbl, task);
+ if (slotid == NFS4_MAX_SLOT_TABLE) {
+ rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
+ spin_unlock(&tbl->slot_tbl_lock);
+ dprintk("<-- %s: no free slots\n", __func__);
+ return -EAGAIN;
+ }
+ spin_unlock(&tbl->slot_tbl_lock);
+
+ slot = tbl->slots + slotid;
+ args->sa_session = session;
+ args->sa_slotid = slotid;
+ args->sa_cache_this = cache_reply;
+
+ dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr);
+
+ res->sr_session = session;
+ res->sr_slotid = slotid;
+ res->sr_renewal_time = jiffies;
+ /*
+ * sr_status is only set in decode_sequence, and so will remain
+ * set to 1 if an rpc level failure occurs.
+ */
+ res->sr_status = 1;
+ return 0;
+}
+
+int nfs4_setup_sequence(struct nfs_client *clp,
+ struct nfs4_sequence_args *args,
+ struct nfs4_sequence_res *res,
+ int cache_reply,
+ struct rpc_task *task)
+{
+ int ret = 0;
+
+ dprintk("--> %s clp %p session %p sr_slotid %d\n",
+ __func__, clp, clp->cl_session, res->sr_slotid);
+
+ if (!nfs4_has_session(clp))
+ goto out;
+ ret = nfs41_setup_sequence(clp->cl_session, args, res, cache_reply,
+ task);
+ if (ret != -EAGAIN) {
+ /* terminate rpc task */
+ task->tk_status = ret;
+ task->tk_action = NULL;
+ }
+out:
+ dprintk("<-- %s status=%d\n", __func__, ret);
+ return ret;
+}
+
+struct nfs41_call_sync_data {
+ struct nfs_client *clp;
+ struct nfs4_sequence_args *seq_args;
+ struct nfs4_sequence_res *seq_res;
+ int cache_reply;
+};
+
+static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata)
+{
+ struct nfs41_call_sync_data *data = calldata;
+
+ dprintk("--> %s data->clp->cl_session %p\n", __func__,
+ data->clp->cl_session);
+ if (nfs4_setup_sequence(data->clp, data->seq_args,
+ data->seq_res, data->cache_reply, task))
+ return;
+ rpc_call_start(task);
+}
+
+static void nfs41_call_sync_done(struct rpc_task *task, void *calldata)
+{
+ struct nfs41_call_sync_data *data = calldata;
+
+ nfs41_sequence_done(data->clp, data->seq_res, task->tk_status);
+ nfs41_sequence_free_slot(data->clp, data->seq_res);
+}
+
+struct rpc_call_ops nfs41_call_sync_ops = {
+ .rpc_call_prepare = nfs41_call_sync_prepare,
+ .rpc_call_done = nfs41_call_sync_done,
+};
+
+static int nfs4_call_sync_sequence(struct nfs_client *clp,
+ struct rpc_clnt *clnt,
+ struct rpc_message *msg,
+ struct nfs4_sequence_args *args,
+ struct nfs4_sequence_res *res,
+ int cache_reply)
+{
+ int ret;
+ struct rpc_task *task;
+ struct nfs41_call_sync_data data = {
+ .clp = clp,
+ .seq_args = args,
+ .seq_res = res,
+ .cache_reply = cache_reply,
+ };
+ struct rpc_task_setup task_setup = {
+ .rpc_client = clnt,
+ .rpc_message = msg,
+ .callback_ops = &nfs41_call_sync_ops,
+ .callback_data = &data
+ };
+
+ res->sr_slotid = NFS4_MAX_SLOT_TABLE;
+ task = rpc_run_task(&task_setup);
+ if (IS_ERR(task))
+ ret = PTR_ERR(task);
+ else {
+ ret = task->tk_status;
+ rpc_put_task(task);
+ }
+ return ret;
+}
+
+int _nfs4_call_sync_session(struct nfs_server *server,
+ struct rpc_message *msg,
+ struct nfs4_sequence_args *args,
+ struct nfs4_sequence_res *res,
+ int cache_reply)
+{
+ return nfs4_call_sync_sequence(server->nfs_client, server->client,
+ msg, args, res, cache_reply);
+}
+
+#endif /* CONFIG_NFS_V4_1 */
+
+int _nfs4_call_sync(struct nfs_server *server,
+ struct rpc_message *msg,
+ struct nfs4_sequence_args *args,
+ struct nfs4_sequence_res *res,
+ int cache_reply)
+{
+ args->sa_session = res->sr_session = NULL;
+ return rpc_call_sync(server->client, msg, 0);
+}
+
+#define nfs4_call_sync(server, msg, args, res, cache_reply) \
+ (server)->nfs_client->cl_call_sync((server), (msg), &(args)->seq_args, \
+ &(res)->seq_res, (cache_reply))
+
+static void nfs4_sequence_done(const struct nfs_server *server,
+ struct nfs4_sequence_res *res, int rpc_status)
+{
+#ifdef CONFIG_NFS_V4_1
+ if (nfs4_has_session(server->nfs_client))
+ nfs41_sequence_done(server->nfs_client, res, rpc_status);
+#endif /* CONFIG_NFS_V4_1 */
+}
+
+/* no restart, therefore free slot here */
+static void nfs4_sequence_done_free_slot(const struct nfs_server *server,
+ struct nfs4_sequence_res *res,
+ int rpc_status)
+{
+ nfs4_sequence_done(server, res, rpc_status);
+ nfs4_sequence_free_slot(server->nfs_client, res);
+}
+
static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
{
struct nfs_inode *nfsi = NFS_I(dir);
@@ -343,6 +710,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
p->o_arg.server = server;
p->o_arg.bitmask = server->attr_bitmask;
p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
+ p->o_res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
if (flags & O_EXCL) {
u32 *s = (u32 *) p->o_arg.u.verifier.data;
s[0] = jiffies;
@@ -929,6 +1297,10 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
nfs_copy_fh(&data->o_res.fh, data->o_arg.fh);
}
data->timestamp = jiffies;
+ if (nfs4_setup_sequence(data->o_arg.server->nfs_client,
+ &data->o_arg.seq_args,
+ &data->o_res.seq_res, 1, task))
+ return;
rpc_call_start(task);
return;
out_no_action:
@@ -941,6 +1313,10 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata)
struct nfs4_opendata *data = calldata;
data->rpc_status = task->tk_status;
+
+ nfs4_sequence_done_free_slot(data->o_arg.server, &data->o_res.seq_res,
+ task->tk_status);
+
if (RPC_ASSASSINATED(task))
return;
if (task->tk_status == 0) {
@@ -1269,7 +1645,7 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
} else
memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));
- status = rpc_call_sync(server->client, &msg, 0);
+ status = nfs4_call_sync(server, &msg, &arg, &res, 1);
if (status == 0 && state != NULL)
renew_lease(server, timestamp);
return status;
@@ -1318,6 +1694,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
struct nfs4_state *state = calldata->state;
struct nfs_server *server = NFS_SERVER(calldata->inode);
+ nfs4_sequence_done(server, &calldata->res.seq_res, task->tk_status);
if (RPC_ASSASSINATED(task))
return;
/* hmm. we are done with the inode, and in the process of freeing
@@ -1336,10 +1713,11 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
break;
default:
if (nfs4_async_handle_error(task, server, state) == -EAGAIN) {
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, server->nfs_client);
return;
}
}
+ nfs4_sequence_free_slot(server->nfs_client, &calldata->res.seq_res);
nfs_refresh_inode(calldata->inode, calldata->res.fattr);
}
@@ -1380,6 +1758,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
calldata->arg.fmode = FMODE_WRITE;
}
calldata->timestamp = jiffies;
+ if (nfs4_setup_sequence((NFS_SERVER(calldata->inode))->nfs_client,
+ &calldata->arg.seq_args, &calldata->res.seq_res,
+ 1, task))
+ return;
rpc_call_start(task);
}
@@ -1419,13 +1801,15 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
};
int status = -ENOMEM;
- calldata = kmalloc(sizeof(*calldata), GFP_KERNEL);
+ calldata = kzalloc(sizeof(*calldata), GFP_KERNEL);
if (calldata == NULL)
goto out;
calldata->inode = state->inode;
calldata->state = state;
calldata->arg.fh = NFS_FH(state->inode);
calldata->arg.stateid = &state->open_stateid;
+ if (nfs4_has_session(server->nfs_client))
+ memset(calldata->arg.stateid->data, 0, 4); /* clear seqid */
/* Serialization for the sequence id */
calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid);
if (calldata->arg.seqid == NULL)
@@ -1435,6 +1819,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
calldata->res.fattr = &calldata->fattr;
calldata->res.seqid = calldata->arg.seqid;
calldata->res.server = server;
+ calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
calldata->path.mnt = mntget(path->mnt);
calldata->path.dentry = dget(path->dentry);
@@ -1584,15 +1969,18 @@ void nfs4_close_context(struct nfs_open_context *ctx, int is_sync)
static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
{
+ struct nfs4_server_caps_arg args = {
+ .fhandle = fhandle,
+ };
struct nfs4_server_caps_res res = {};
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SERVER_CAPS],
- .rpc_argp = fhandle,
+ .rpc_argp = &args,
.rpc_resp = &res,
};
int status;
- status = rpc_call_sync(server->client, &msg, 0);
+ status = nfs4_call_sync(server, &msg, &args, &res, 0);
if (status == 0) {
memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask));
if (res.attr_bitmask[0] & FATTR4_WORD0_ACL)
@@ -1606,6 +1994,7 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
server->acl_bitmask = res.acl_bitmask;
}
+
return status;
}
@@ -1637,8 +2026,15 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
.rpc_argp = &args,
.rpc_resp = &res,
};
+ int status;
+
nfs_fattr_init(info->fattr);
- return rpc_call_sync(server->client, &msg, 0);
+ status = nfs4_recover_expired_lease(server);
+ if (!status)
+ status = nfs4_check_client_ready(server->nfs_client);
+ if (!status)
+ status = nfs4_call_sync(server, &msg, &args, &res, 0);
+ return status;
}
static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
@@ -1728,7 +2124,7 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
};
nfs_fattr_init(fattr);
- return rpc_call_sync(server->client, &msg, 0);
+ return nfs4_call_sync(server, &msg, &args, &res, 0);
}
static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
@@ -1812,7 +2208,7 @@ static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *d
nfs_fattr_init(fattr);
dprintk("NFS call lookupfh %s\n", name->name);
- status = rpc_call_sync(server->client, &msg, 0);
+ status = nfs4_call_sync(server, &msg, &args, &res, 0);
dprintk("NFS reply lookupfh: %d\n", status);
return status;
}
@@ -1898,7 +2294,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
args.access |= NFS4_ACCESS_EXECUTE;
}
nfs_fattr_init(&fattr);
- status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+ status = nfs4_call_sync(server, &msg, &args, &res, 0);
if (!status) {
entry->mask = 0;
if (res.access & NFS4_ACCESS_READ)
@@ -1957,13 +2353,14 @@ static int _nfs4_proc_readlink(struct inode *inode, struct page *page,
.pglen = pglen,
.pages = &page,
};
+ struct nfs4_readlink_res res;
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READLINK],
.rpc_argp = &args,
- .rpc_resp = NULL,
+ .rpc_resp = &res,
};
- return rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+ return nfs4_call_sync(NFS_SERVER(inode), &msg, &args, &res, 0);
}
static int nfs4_proc_readlink(struct inode *inode, struct page *page,
@@ -2057,7 +2454,7 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
int status;
nfs_fattr_init(&res.dir_attr);
- status = rpc_call_sync(server->client, &msg, 0);
+ status = nfs4_call_sync(server, &msg, &args, &res, 1);
if (status == 0) {
update_changeattr(dir, &res.cinfo);
nfs_post_op_update_inode(dir, &res.dir_attr);
@@ -2092,8 +2489,10 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
{
struct nfs_removeres *res = task->tk_msg.rpc_resp;
+ nfs4_sequence_done(res->server, &res->seq_res, task->tk_status);
if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN)
return 0;
+ nfs4_sequence_free_slot(res->server->nfs_client, &res->seq_res);
update_changeattr(dir, &res->cinfo);
nfs_post_op_update_inode(dir, &res->dir_attr);
return 1;
@@ -2125,7 +2524,7 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
nfs_fattr_init(res.old_fattr);
nfs_fattr_init(res.new_fattr);
- status = rpc_call_sync(server->client, &msg, 0);
+ status = nfs4_call_sync(server, &msg, &arg, &res, 1);
if (!status) {
update_changeattr(old_dir, &res.old_cinfo);
@@ -2174,7 +2573,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *
nfs_fattr_init(res.fattr);
nfs_fattr_init(res.dir_attr);
- status = rpc_call_sync(server->client, &msg, 0);
+ status = nfs4_call_sync(server, &msg, &arg, &res, 1);
if (!status) {
update_changeattr(dir, &res.cinfo);
nfs_post_op_update_inode(dir, res.dir_attr);
@@ -2235,7 +2634,8 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data)
{
- int status = rpc_call_sync(NFS_CLIENT(dir), &data->msg, 0);
+ int status = nfs4_call_sync(NFS_SERVER(dir), &data->msg,
+ &data->arg, &data->res, 1);
if (status == 0) {
update_changeattr(dir, &data->res.dir_cinfo);
nfs_post_op_update_inode(dir, data->res.dir_fattr);
@@ -2344,7 +2744,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
(unsigned long long)cookie);
nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args);
res.pgbase = args.pgbase;
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = nfs4_call_sync(NFS_SERVER(dir), &msg, &args, &res, 0);
if (status == 0)
memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE);
@@ -2422,14 +2822,17 @@ static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
.fh = fhandle,
.bitmask = server->attr_bitmask,
};
+ struct nfs4_statfs_res res = {
+ .fsstat = fsstat,
+ };
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_STATFS],
.rpc_argp = &args,
- .rpc_resp = fsstat,
+ .rpc_resp = &res,
};
nfs_fattr_init(fsstat->fattr);
- return rpc_call_sync(server->client, &msg, 0);
+ return nfs4_call_sync(server, &msg, &args, &res, 0);
}
static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat)
@@ -2451,13 +2854,16 @@ static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
.fh = fhandle,
.bitmask = server->attr_bitmask,
};
+ struct nfs4_fsinfo_res res = {
+ .fsinfo = fsinfo,
+ };
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FSINFO],
.rpc_argp = &args,
- .rpc_resp = fsinfo,
+ .rpc_resp = &res,
};
- return rpc_call_sync(server->client, &msg, 0);
+ return nfs4_call_sync(server, &msg, &args, &res, 0);
}
static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
@@ -2486,10 +2892,13 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle
.fh = fhandle,
.bitmask = server->attr_bitmask,
};
+ struct nfs4_pathconf_res res = {
+ .pathconf = pathconf,
+ };
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_PATHCONF],
.rpc_argp = &args,
- .rpc_resp = pathconf,
+ .rpc_resp = &res,
};
/* None of the pathconf attributes are mandatory to implement */
@@ -2499,7 +2908,7 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle
}
nfs_fattr_init(pathconf->fattr);
- return rpc_call_sync(server->client, &msg, 0);
+ return nfs4_call_sync(server, &msg, &args, &res, 0);
}
static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
@@ -2520,8 +2929,13 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
{
struct nfs_server *server = NFS_SERVER(data->inode);
+ dprintk("--> %s\n", __func__);
+
+ /* nfs4_sequence_free_slot called in the read rpc_call_done */
+ nfs4_sequence_done(server, &data->res.seq_res, task->tk_status);
+
if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) {
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, server->nfs_client);
return -EAGAIN;
}
@@ -2541,8 +2955,12 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
{
struct inode *inode = data->inode;
+ /* slot is freed in nfs_writeback_done */
+ nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res,
+ task->tk_status);
+
if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) {
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
return -EAGAIN;
}
if (task->tk_status >= 0) {
@@ -2567,10 +2985,14 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
{
struct inode *inode = data->inode;
+ nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res,
+ task->tk_status);
if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) {
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
return -EAGAIN;
}
+ nfs4_sequence_free_slot(NFS_SERVER(inode)->nfs_client,
+ &data->res.seq_res);
nfs_refresh_inode(inode, data->res.fattr);
return 0;
}
@@ -2606,6 +3028,9 @@ static void nfs4_renew_done(struct rpc_task *task, void *data)
if (time_before(clp->cl_last_renewal,timestamp))
clp->cl_last_renewal = timestamp;
spin_unlock(&clp->cl_lock);
+ dprintk("%s calling put_rpccred on rpc_cred %p\n", __func__,
+ task->tk_msg.rpc_cred);
+ put_rpccred(task->tk_msg.rpc_cred);
}
static const struct rpc_call_ops nfs4_renew_ops = {
@@ -2745,12 +3170,14 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
.acl_pages = pages,
.acl_len = buflen,
};
- size_t resp_len = buflen;
+ struct nfs_getaclres res = {
+ .acl_len = buflen,
+ };
void *resp_buf;
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL],
.rpc_argp = &args,
- .rpc_resp = &resp_len,
+ .rpc_resp = &res,
};
struct page *localpage = NULL;
int ret;
@@ -2764,26 +3191,26 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
return -ENOMEM;
args.acl_pages[0] = localpage;
args.acl_pgbase = 0;
- resp_len = args.acl_len = PAGE_SIZE;
+ args.acl_len = PAGE_SIZE;
} else {
resp_buf = buf;
buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase);
}
- ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+ ret = nfs4_call_sync(NFS_SERVER(inode), &msg, &args, &res, 0);
if (ret)
goto out_free;
- if (resp_len > args.acl_len)
- nfs4_write_cached_acl(inode, NULL, resp_len);
+ if (res.acl_len > args.acl_len)
+ nfs4_write_cached_acl(inode, NULL, res.acl_len);
else
- nfs4_write_cached_acl(inode, resp_buf, resp_len);
+ nfs4_write_cached_acl(inode, resp_buf, res.acl_len);
if (buf) {
ret = -ERANGE;
- if (resp_len > buflen)
+ if (res.acl_len > buflen)
goto out_free;
if (localpage)
- memcpy(buf, resp_buf, resp_len);
+ memcpy(buf, resp_buf, res.acl_len);
}
- ret = resp_len;
+ ret = res.acl_len;
out_free:
if (localpage)
__free_page(localpage);
@@ -2830,10 +3257,11 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
.acl_pages = pages,
.acl_len = buflen,
};
+ struct nfs_setaclres res;
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETACL],
.rpc_argp = &arg,
- .rpc_resp = NULL,
+ .rpc_resp = &res,
};
int ret;
@@ -2841,7 +3269,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
return -EOPNOTSUPP;
nfs_inode_return_delegation(inode);
buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
- ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+ ret = nfs4_call_sync(server, &msg, &arg, &res, 1);
nfs_access_zap_cache(inode);
nfs_zap_acl_cache(inode);
return ret;
@@ -2860,10 +3288,8 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen
}
static int
-nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state)
+_nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs_client *clp, struct nfs4_state *state)
{
- struct nfs_client *clp = server->nfs_client;
-
if (!clp || task->tk_status >= 0)
return 0;
switch(task->tk_status) {
@@ -2882,8 +3308,23 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
task->tk_status = 0;
return -EAGAIN;
+#if defined(CONFIG_NFS_V4_1)
+ case -NFS4ERR_BADSESSION:
+ case -NFS4ERR_BADSLOT:
+ case -NFS4ERR_BAD_HIGH_SLOT:
+ case -NFS4ERR_DEADSESSION:
+ case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
+ case -NFS4ERR_SEQ_FALSE_RETRY:
+ case -NFS4ERR_SEQ_MISORDERED:
+ dprintk("%s ERROR %d, Reset session\n", __func__,
+ task->tk_status);
+ set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
+ task->tk_status = 0;
+ return -EAGAIN;
+#endif /* CONFIG_NFS_V4_1 */
case -NFS4ERR_DELAY:
- nfs_inc_server_stats(server, NFSIOS_DELAY);
+ if (server)
+ nfs_inc_server_stats(server, NFSIOS_DELAY);
case -NFS4ERR_GRACE:
rpc_delay(task, NFS4_POLL_RETRY_MAX);
task->tk_status = 0;
@@ -2896,6 +3337,12 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
return 0;
}
+static int
+nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state)
+{
+ return _nfs4_async_handle_error(task, server, server->nfs_client, state);
+}
+
int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short port, struct rpc_cred *cred)
{
nfs4_verifier sc_verifier;
@@ -3003,6 +3450,10 @@ struct nfs4_delegreturndata {
static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
{
struct nfs4_delegreturndata *data = calldata;
+
+ nfs4_sequence_done_free_slot(data->res.server, &data->res.seq_res,
+ task->tk_status);
+
data->rpc_status = task->tk_status;
if (data->rpc_status == 0)
renew_lease(data->res.server, data->timestamp);
@@ -3013,7 +3464,25 @@ static void nfs4_delegreturn_release(void *calldata)
kfree(calldata);
}
+#if defined(CONFIG_NFS_V4_1)
+static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data)
+{
+ struct nfs4_delegreturndata *d_data;
+
+ d_data = (struct nfs4_delegreturndata *)data;
+
+ if (nfs4_setup_sequence(d_data->res.server->nfs_client,
+ &d_data->args.seq_args,
+ &d_data->res.seq_res, 1, task))
+ return;
+ rpc_call_start(task);
+}
+#endif /* CONFIG_NFS_V4_1 */
+
static const struct rpc_call_ops nfs4_delegreturn_ops = {
+#if defined(CONFIG_NFS_V4_1)
+ .rpc_call_prepare = nfs4_delegreturn_prepare,
+#endif /* CONFIG_NFS_V4_1 */
.rpc_call_done = nfs4_delegreturn_done,
.rpc_release = nfs4_delegreturn_release,
};
@@ -3035,7 +3504,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
};
int status = 0;
- data = kmalloc(sizeof(*data), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
data->args.fhandle = &data->fh;
@@ -3045,6 +3514,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
memcpy(&data->stateid, stateid, sizeof(data->stateid));
data->res.fattr = &data->fattr;
data->res.server = server;
+ data->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
nfs_fattr_init(data->res.fattr);
data->timestamp = jiffies;
data->rpc_status = 0;
@@ -3130,7 +3600,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
goto out;
lsp = request->fl_u.nfs4_fl.owner;
arg.lock_owner.id = lsp->ls_id.id;
- status = rpc_call_sync(server->client, &msg, 0);
+ status = nfs4_call_sync(server, &msg, &arg, &res, 1);
switch (status) {
case 0:
request->fl_type = F_UNLCK;
@@ -3190,13 +3660,14 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
struct nfs4_unlockdata *p;
struct inode *inode = lsp->ls_state->inode;
- p = kmalloc(sizeof(*p), GFP_KERNEL);
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
if (p == NULL)
return NULL;
p->arg.fh = NFS_FH(inode);
p->arg.fl = &p->fl;
p->arg.seqid = seqid;
p->res.seqid = seqid;
+ p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
p->arg.stateid = &lsp->ls_stateid;
p->lsp = lsp;
atomic_inc(&lsp->ls_count);
@@ -3220,6 +3691,8 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
{
struct nfs4_unlockdata *calldata = data;
+ nfs4_sequence_done(calldata->server, &calldata->res.seq_res,
+ task->tk_status);
if (RPC_ASSASSINATED(task))
return;
switch (task->tk_status) {
@@ -3236,8 +3709,11 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
break;
default:
if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN)
- rpc_restart_call(task);
+ nfs4_restart_rpc(task,
+ calldata->server->nfs_client);
}
+ nfs4_sequence_free_slot(calldata->server->nfs_client,
+ &calldata->res.seq_res);
}
static void nfs4_locku_prepare(struct rpc_task *task, void *data)
@@ -3252,6 +3728,10 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)
return;
}
calldata->timestamp = jiffies;
+ if (nfs4_setup_sequence(calldata->server->nfs_client,
+ &calldata->arg.seq_args,
+ &calldata->res.seq_res, 1, task))
+ return;
rpc_call_start(task);
}
@@ -3344,6 +3824,7 @@ struct nfs4_lockdata {
unsigned long timestamp;
int rpc_status;
int cancelled;
+ struct nfs_server *server;
};
static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
@@ -3369,7 +3850,9 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
p->arg.lock_owner.clientid = server->nfs_client->cl_clientid;
p->arg.lock_owner.id = lsp->ls_id.id;
p->res.lock_seqid = p->arg.lock_seqid;
+ p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
p->lsp = lsp;
+ p->server = server;
atomic_inc(&lsp->ls_count);
p->ctx = get_nfs_open_context(ctx);
memcpy(&p->fl, fl, sizeof(p->fl));
@@ -3399,6 +3882,9 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
} else
data->arg.new_lock_owner = 0;
data->timestamp = jiffies;
+ if (nfs4_setup_sequence(data->server->nfs_client, &data->arg.seq_args,
+ &data->res.seq_res, 1, task))
+ return;
rpc_call_start(task);
dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status);
}
@@ -3409,6 +3895,9 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
dprintk("%s: begin!\n", __func__);
+ nfs4_sequence_done_free_slot(data->server, &data->res.seq_res,
+ task->tk_status);
+
data->rpc_status = task->tk_status;
if (RPC_ASSASSINATED(task))
goto out;
@@ -3709,10 +4198,13 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
.page = page,
.bitmask = bitmask,
};
+ struct nfs4_fs_locations_res res = {
+ .fs_locations = fs_locations,
+ };
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS],
.rpc_argp = &args,
- .rpc_resp = fs_locations,
+ .rpc_resp = &res,
};
int status;
@@ -3720,24 +4212,663 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
nfs_fattr_init(&fs_locations->fattr);
fs_locations->server = server;
fs_locations->nlocations = 0;
- status = rpc_call_sync(server->client, &msg, 0);
+ status = nfs4_call_sync(server, &msg, &args, &res, 0);
nfs_fixup_referral_attributes(&fs_locations->fattr);
dprintk("%s: returned status = %d\n", __func__, status);
return status;
}
-struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {
+#ifdef CONFIG_NFS_V4_1
+/*
+ * nfs4_proc_exchange_id()
+ *
+ * Since the clientid has expired, all compounds using sessions
+ * associated with the stale clientid will be returning
+ * NFS4ERR_BADSESSION in the sequence operation, and will therefore
+ * be in some phase of session reset.
+ */
+static int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
+{
+ nfs4_verifier verifier;
+ struct nfs41_exchange_id_args args = {
+ .client = clp,
+ .flags = clp->cl_exchange_flags,
+ };
+ struct nfs41_exchange_id_res res = {
+ .client = clp,
+ };
+ int status;
+ struct rpc_message msg = {
+ .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_EXCHANGE_ID],
+ .rpc_argp = &args,
+ .rpc_resp = &res,
+ .rpc_cred = cred,
+ };
+ __be32 *p;
+
+ dprintk("--> %s\n", __func__);
+ BUG_ON(clp == NULL);
+
+ p = (u32 *)verifier.data;
+ *p++ = htonl((u32)clp->cl_boot_time.tv_sec);
+ *p = htonl((u32)clp->cl_boot_time.tv_nsec);
+ args.verifier = &verifier;
+
+ while (1) {
+ args.id_len = scnprintf(args.id, sizeof(args.id),
+ "%s/%s %u",
+ clp->cl_ipaddr,
+ rpc_peeraddr2str(clp->cl_rpcclient,
+ RPC_DISPLAY_ADDR),
+ clp->cl_id_uniquifier);
+
+ status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+
+ if (status != NFS4ERR_CLID_INUSE)
+ break;
+
+ if (signalled())
+ break;
+
+ if (++clp->cl_id_uniquifier == 0)
+ break;
+ }
+
+ dprintk("<-- %s status= %d\n", __func__, status);
+ return status;
+}
+
+struct nfs4_get_lease_time_data {
+ struct nfs4_get_lease_time_args *args;
+ struct nfs4_get_lease_time_res *res;
+ struct nfs_client *clp;
+};
+
+static void nfs4_get_lease_time_prepare(struct rpc_task *task,
+ void *calldata)
+{
+ int ret;
+ struct nfs4_get_lease_time_data *data =
+ (struct nfs4_get_lease_time_data *)calldata;
+
+ dprintk("--> %s\n", __func__);
+ /* just setup sequence, do not trigger session recovery
+ since we're invoked within one */
+ ret = nfs41_setup_sequence(data->clp->cl_session,
+ &data->args->la_seq_args,
+ &data->res->lr_seq_res, 0, task);
+
+ BUG_ON(ret == -EAGAIN);
+ rpc_call_start(task);
+ dprintk("<-- %s\n", __func__);
+}
+
+/*
+ * Called from nfs4_state_manager thread for session setup, so don't recover
+ * from sequence operation or clientid errors.
+ */
+static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata)
+{
+ struct nfs4_get_lease_time_data *data =
+ (struct nfs4_get_lease_time_data *)calldata;
+
+ dprintk("--> %s\n", __func__);
+ nfs41_sequence_done(data->clp, &data->res->lr_seq_res, task->tk_status);
+ switch (task->tk_status) {
+ case -NFS4ERR_DELAY:
+ case -NFS4ERR_GRACE:
+ dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status);
+ rpc_delay(task, NFS4_POLL_RETRY_MIN);
+ task->tk_status = 0;
+ nfs4_restart_rpc(task, data->clp);
+ return;
+ }
+ nfs41_sequence_free_slot(data->clp, &data->res->lr_seq_res);
+ dprintk("<-- %s\n", __func__);
+}
+
+struct rpc_call_ops nfs4_get_lease_time_ops = {
+ .rpc_call_prepare = nfs4_get_lease_time_prepare,
+ .rpc_call_done = nfs4_get_lease_time_done,
+};
+
+int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
+{
+ struct rpc_task *task;
+ struct nfs4_get_lease_time_args args;
+ struct nfs4_get_lease_time_res res = {
+ .lr_fsinfo = fsinfo,
+ };
+ struct nfs4_get_lease_time_data data = {
+ .args = &args,
+ .res = &res,
+ .clp = clp,
+ };
+ struct rpc_message msg = {
+ .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GET_LEASE_TIME],
+ .rpc_argp = &args,
+ .rpc_resp = &res,
+ };
+ struct rpc_task_setup task_setup = {
+ .rpc_client = clp->cl_rpcclient,
+ .rpc_message = &msg,
+ .callback_ops = &nfs4_get_lease_time_ops,
+ .callback_data = &data
+ };
+ int status;
+
+ res.lr_seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
+ dprintk("--> %s\n", __func__);
+ task = rpc_run_task(&task_setup);
+
+ if (IS_ERR(task))
+ status = PTR_ERR(task);
+ else {
+ status = task->tk_status;
+ rpc_put_task(task);
+ }
+ dprintk("<-- %s return %d\n", __func__, status);
+
+ return status;
+}
+
+/* Reset a slot table */
+static int nfs4_reset_slot_table(struct nfs4_session *session)
+{
+ struct nfs4_slot_table *tbl = &session->fc_slot_table;
+ int i, max_slots = session->fc_attrs.max_reqs;
+ int old_max_slots = session->fc_slot_table.max_slots;
+ int ret = 0;
+
+ dprintk("--> %s: max_reqs=%u, tbl %p\n", __func__,
+ session->fc_attrs.max_reqs, tbl);
+
+ /* Until we have dynamic slot table adjustment, insist
+ * upon the same slot table size */
+ if (max_slots != old_max_slots) {
+ dprintk("%s reset slot table does't match old\n",
+ __func__);
+ ret = -EINVAL; /*XXX NFS4ERR_REQ_TOO_BIG ? */
+ goto out;
+ }
+ spin_lock(&tbl->slot_tbl_lock);
+ for (i = 0; i < max_slots; ++i)
+ tbl->slots[i].seq_nr = 1;
+ tbl->highest_used_slotid = -1;
+ spin_unlock(&tbl->slot_tbl_lock);
+ dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
+ tbl, tbl->slots, tbl->max_slots);
+out:
+ dprintk("<-- %s: return %d\n", __func__, ret);
+ return ret;
+}
+
+/*
+ * Initialize slot table
+ */
+static int nfs4_init_slot_table(struct nfs4_session *session)
+{
+ struct nfs4_slot_table *tbl = &session->fc_slot_table;
+ int i, max_slots = session->fc_attrs.max_reqs;
+ struct nfs4_slot *slot;
+ int ret = -ENOMEM;
+
+ BUG_ON(max_slots > NFS4_MAX_SLOT_TABLE);
+
+ dprintk("--> %s: max_reqs=%u\n", __func__,
+ session->fc_attrs.max_reqs);
+
+ slot = kcalloc(max_slots, sizeof(struct nfs4_slot), GFP_KERNEL);
+ if (!slot)
+ goto out;
+ for (i = 0; i < max_slots; ++i)
+ slot[i].seq_nr = 1;
+ ret = 0;
+
+ spin_lock(&tbl->slot_tbl_lock);
+ if (tbl->slots != NULL) {
+ spin_unlock(&tbl->slot_tbl_lock);
+ dprintk("%s: slot table already initialized. tbl=%p slots=%p\n",
+ __func__, tbl, tbl->slots);
+ WARN_ON(1);
+ goto out_free;
+ }
+ tbl->max_slots = max_slots;
+ tbl->slots = slot;
+ tbl->highest_used_slotid = -1; /* no slot is currently used */
+ spin_unlock(&tbl->slot_tbl_lock);
+ dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
+ tbl, tbl->slots, tbl->max_slots);
+out:
+ dprintk("<-- %s: return %d\n", __func__, ret);
+ return ret;
+out_free:
+ kfree(slot);
+ goto out;
+}
+
+/* Destroy the slot table */
+static void nfs4_destroy_slot_table(struct nfs4_session *session)
+{
+ if (session->fc_slot_table.slots == NULL)
+ return;
+ kfree(session->fc_slot_table.slots);
+ session->fc_slot_table.slots = NULL;
+ return;
+}
+
+struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp)
+{
+ struct nfs4_session *session;
+ struct nfs4_slot_table *tbl;
+
+ session = kzalloc(sizeof(struct nfs4_session), GFP_KERNEL);
+ if (!session)
+ return NULL;
+
+ set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
+ /*
+ * The create session reply races with the server back
+ * channel probe. Mark the client NFS_CS_SESSION_INITING
+ * so that the client back channel can find the
+ * nfs_client struct
+ */
+ clp->cl_cons_state = NFS_CS_SESSION_INITING;
+
+ tbl = &session->fc_slot_table;
+ spin_lock_init(&tbl->slot_tbl_lock);
+ rpc_init_wait_queue(&tbl->slot_tbl_waitq, "Slot table");
+ session->clp = clp;
+ return session;
+}
+
+void nfs4_destroy_session(struct nfs4_session *session)
+{
+ nfs4_destroy_slot_table(session);
+ kfree(session);
+}
+
+/*
+ * Initialize the values to be used by the client in CREATE_SESSION
+ * If nfs4_init_session set the fore channel request and response sizes,
+ * use them.
+ *
+ * Set the back channel max_resp_sz_cached to zero to force the client to
+ * always set csa_cachethis to FALSE because the current implementation
+ * of the back channel DRC only supports caching the CB_SEQUENCE operation.
+ */
+static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args)
+{
+ struct nfs4_session *session = args->client->cl_session;
+ unsigned int mxrqst_sz = session->fc_attrs.max_rqst_sz,
+ mxresp_sz = session->fc_attrs.max_resp_sz;
+
+ if (mxrqst_sz == 0)
+ mxrqst_sz = NFS_MAX_FILE_IO_SIZE;
+ if (mxresp_sz == 0)
+ mxresp_sz = NFS_MAX_FILE_IO_SIZE;
+ /* Fore channel attributes */
+ args->fc_attrs.headerpadsz = 0;
+ args->fc_attrs.max_rqst_sz = mxrqst_sz;
+ args->fc_attrs.max_resp_sz = mxresp_sz;
+ args->fc_attrs.max_resp_sz_cached = mxresp_sz;
+ args->fc_attrs.max_ops = NFS4_MAX_OPS;
+ args->fc_attrs.max_reqs = session->clp->cl_rpcclient->cl_xprt->max_reqs;
+
+ dprintk("%s: Fore Channel : max_rqst_sz=%u max_resp_sz=%u "
+ "max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n",
+ __func__,
+ args->fc_attrs.max_rqst_sz, args->fc_attrs.max_resp_sz,
+ args->fc_attrs.max_resp_sz_cached, args->fc_attrs.max_ops,
+ args->fc_attrs.max_reqs);
+
+ /* Back channel attributes */
+ args->bc_attrs.headerpadsz = 0;
+ args->bc_attrs.max_rqst_sz = PAGE_SIZE;
+ args->bc_attrs.max_resp_sz = PAGE_SIZE;
+ args->bc_attrs.max_resp_sz_cached = 0;
+ args->bc_attrs.max_ops = NFS4_MAX_BACK_CHANNEL_OPS;
+ args->bc_attrs.max_reqs = 1;
+
+ dprintk("%s: Back Channel : max_rqst_sz=%u max_resp_sz=%u "
+ "max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n",
+ __func__,
+ args->bc_attrs.max_rqst_sz, args->bc_attrs.max_resp_sz,
+ args->bc_attrs.max_resp_sz_cached, args->bc_attrs.max_ops,
+ args->bc_attrs.max_reqs);
+}
+
+static int _verify_channel_attr(char *chan, char *attr_name, u32 sent, u32 rcvd)
+{
+ if (rcvd <= sent)
+ return 0;
+ printk(KERN_WARNING "%s: Session INVALID: %s channel %s increased. "
+ "sent=%u rcvd=%u\n", __func__, chan, attr_name, sent, rcvd);
+ return -EINVAL;
+}
+
+#define _verify_fore_channel_attr(_name_) \
+ _verify_channel_attr("fore", #_name_, \
+ args->fc_attrs._name_, \
+ session->fc_attrs._name_)
+
+#define _verify_back_channel_attr(_name_) \
+ _verify_channel_attr("back", #_name_, \
+ args->bc_attrs._name_, \
+ session->bc_attrs._name_)
+
+/*
+ * The server is not allowed to increase the fore channel header pad size,
+ * maximum response size, or maximum number of operations.
+ *
+ * The back channel attributes are only negotiatied down: We send what the
+ * (back channel) server insists upon.
+ */
+static int nfs4_verify_channel_attrs(struct nfs41_create_session_args *args,
+ struct nfs4_session *session)
+{
+ int ret = 0;
+
+ ret |= _verify_fore_channel_attr(headerpadsz);
+ ret |= _verify_fore_channel_attr(max_resp_sz);
+ ret |= _verify_fore_channel_attr(max_ops);
+
+ ret |= _verify_back_channel_attr(headerpadsz);
+ ret |= _verify_back_channel_attr(max_rqst_sz);
+ ret |= _verify_back_channel_attr(max_resp_sz);
+ ret |= _verify_back_channel_attr(max_resp_sz_cached);
+ ret |= _verify_back_channel_attr(max_ops);
+ ret |= _verify_back_channel_attr(max_reqs);
+
+ return ret;
+}
+
+static int _nfs4_proc_create_session(struct nfs_client *clp)
+{
+ struct nfs4_session *session = clp->cl_session;
+ struct nfs41_create_session_args args = {
+ .client = clp,
+ .cb_program = NFS4_CALLBACK,
+ };
+ struct nfs41_create_session_res res = {
+ .client = clp,
+ };
+ struct rpc_message msg = {
+ .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE_SESSION],
+ .rpc_argp = &args,
+ .rpc_resp = &res,
+ };
+ int status;
+
+ nfs4_init_channel_attrs(&args);
+ args.flags = (SESSION4_PERSIST);
+
+ status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0);
+
+ if (!status)
+ /* Verify the session's negotiated channel_attrs values */
+ status = nfs4_verify_channel_attrs(&args, session);
+ if (!status) {
+ /* Increment the clientid slot sequence id */
+ clp->cl_seqid++;
+ }
+
+ return status;
+}
+
+/*
+ * Issues a CREATE_SESSION operation to the server.
+ * It is the responsibility of the caller to verify the session is
+ * expired before calling this routine.
+ */
+int nfs4_proc_create_session(struct nfs_client *clp, int reset)
+{
+ int status;
+ unsigned *ptr;
+ struct nfs_fsinfo fsinfo;
+ struct nfs4_session *session = clp->cl_session;
+
+ dprintk("--> %s clp=%p session=%p\n", __func__, clp, session);
+
+ status = _nfs4_proc_create_session(clp);
+ if (status)
+ goto out;
+
+ /* Init or reset the fore channel */
+ if (reset)
+ status = nfs4_reset_slot_table(session);
+ else
+ status = nfs4_init_slot_table(session);
+ dprintk("fore channel slot table initialization returned %d\n", status);
+ if (status)
+ goto out;
+
+ ptr = (unsigned *)&session->sess_id.data[0];
+ dprintk("%s client>seqid %d sessionid %u:%u:%u:%u\n", __func__,
+ clp->cl_seqid, ptr[0], ptr[1], ptr[2], ptr[3]);
+
+ if (reset)
+ /* Lease time is aleady set */
+ goto out;
+
+ /* Get the lease time */
+ status = nfs4_proc_get_lease_time(clp, &fsinfo);
+ if (status == 0) {
+ /* Update lease time and schedule renewal */
+ spin_lock(&clp->cl_lock);
+ clp->cl_lease_time = fsinfo.lease_time * HZ;
+ clp->cl_last_renewal = jiffies;
+ clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
+ spin_unlock(&clp->cl_lock);
+
+ nfs4_schedule_state_renewal(clp);
+ }
+out:
+ dprintk("<-- %s\n", __func__);
+ return status;
+}
+
+/*
+ * Issue the over-the-wire RPC DESTROY_SESSION.
+ * The caller must serialize access to this routine.
+ */
+int nfs4_proc_destroy_session(struct nfs4_session *session)
+{
+ int status = 0;
+ struct rpc_message msg;
+
+ dprintk("--> nfs4_proc_destroy_session\n");
+
+ /* session is still being setup */
+ if (session->clp->cl_cons_state != NFS_CS_READY)
+ return status;
+
+ msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DESTROY_SESSION];
+ msg.rpc_argp = session;
+ msg.rpc_resp = NULL;
+ msg.rpc_cred = NULL;
+ status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0);
+
+ if (status)
+ printk(KERN_WARNING
+ "Got error %d from the server on DESTROY_SESSION. "
+ "Session has been destroyed regardless...\n", status);
+
+ dprintk("<-- nfs4_proc_destroy_session\n");
+ return status;
+}
+
+/*
+ * Renew the cl_session lease.
+ */
+static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred)
+{
+ struct nfs4_sequence_args args;
+ struct nfs4_sequence_res res;
+
+ struct rpc_message msg = {
+ .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SEQUENCE],
+ .rpc_argp = &args,
+ .rpc_resp = &res,
+ .rpc_cred = cred,
+ };
+
+ args.sa_cache_this = 0;
+
+ return nfs4_call_sync_sequence(clp, clp->cl_rpcclient, &msg, &args,
+ &res, 0);
+}
+
+void nfs41_sequence_call_done(struct rpc_task *task, void *data)
+{
+ struct nfs_client *clp = (struct nfs_client *)data;
+
+ nfs41_sequence_done(clp, task->tk_msg.rpc_resp, task->tk_status);
+
+ if (task->tk_status < 0) {
+ dprintk("%s ERROR %d\n", __func__, task->tk_status);
+
+ if (_nfs4_async_handle_error(task, NULL, clp, NULL)
+ == -EAGAIN) {
+ nfs4_restart_rpc(task, clp);
+ return;
+ }
+ }
+ nfs41_sequence_free_slot(clp, task->tk_msg.rpc_resp);
+ dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred);
+
+ put_rpccred(task->tk_msg.rpc_cred);
+ kfree(task->tk_msg.rpc_argp);
+ kfree(task->tk_msg.rpc_resp);
+
+ dprintk("<-- %s\n", __func__);
+}
+
+static void nfs41_sequence_prepare(struct rpc_task *task, void *data)
+{
+ struct nfs_client *clp;
+ struct nfs4_sequence_args *args;
+ struct nfs4_sequence_res *res;
+
+ clp = (struct nfs_client *)data;
+ args = task->tk_msg.rpc_argp;
+ res = task->tk_msg.rpc_resp;
+
+ if (nfs4_setup_sequence(clp, args, res, 0, task))
+ return;
+ rpc_call_start(task);
+}
+
+static const struct rpc_call_ops nfs41_sequence_ops = {
+ .rpc_call_done = nfs41_sequence_call_done,
+ .rpc_call_prepare = nfs41_sequence_prepare,
+};
+
+static int nfs41_proc_async_sequence(struct nfs_client *clp,
+ struct rpc_cred *cred)
+{
+ struct nfs4_sequence_args *args;
+ struct nfs4_sequence_res *res;
+ struct rpc_message msg = {
+ .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SEQUENCE],
+ .rpc_cred = cred,
+ };
+
+ args = kzalloc(sizeof(*args), GFP_KERNEL);
+ if (!args)
+ return -ENOMEM;
+ res = kzalloc(sizeof(*res), GFP_KERNEL);
+ if (!res) {
+ kfree(args);
+ return -ENOMEM;
+ }
+ res->sr_slotid = NFS4_MAX_SLOT_TABLE;
+ msg.rpc_argp = args;
+ msg.rpc_resp = res;
+
+ return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT,
+ &nfs41_sequence_ops, (void *)clp);
+}
+
+#endif /* CONFIG_NFS_V4_1 */
+
+struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {
+ .owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT,
+ .state_flag_bit = NFS_STATE_RECLAIM_REBOOT,
+ .recover_open = nfs4_open_reclaim,
+ .recover_lock = nfs4_lock_reclaim,
+ .establish_clid = nfs4_init_clientid,
+ .get_clid_cred = nfs4_get_setclientid_cred,
+};
+
+#if defined(CONFIG_NFS_V4_1)
+struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = {
.owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT,
.state_flag_bit = NFS_STATE_RECLAIM_REBOOT,
.recover_open = nfs4_open_reclaim,
.recover_lock = nfs4_lock_reclaim,
+ .establish_clid = nfs4_proc_exchange_id,
+ .get_clid_cred = nfs4_get_exchange_id_cred,
+};
+#endif /* CONFIG_NFS_V4_1 */
+
+struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = {
+ .owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE,
+ .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE,
+ .recover_open = nfs4_open_expired,
+ .recover_lock = nfs4_lock_expired,
+ .establish_clid = nfs4_init_clientid,
+ .get_clid_cred = nfs4_get_setclientid_cred,
};
-struct nfs4_state_recovery_ops nfs4_nograce_recovery_ops = {
+#if defined(CONFIG_NFS_V4_1)
+struct nfs4_state_recovery_ops nfs41_nograce_recovery_ops = {
.owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE,
.state_flag_bit = NFS_STATE_RECLAIM_NOGRACE,
.recover_open = nfs4_open_expired,
.recover_lock = nfs4_lock_expired,
+ .establish_clid = nfs4_proc_exchange_id,
+ .get_clid_cred = nfs4_get_exchange_id_cred,
+};
+#endif /* CONFIG_NFS_V4_1 */
+
+struct nfs4_state_maintenance_ops nfs40_state_renewal_ops = {
+ .sched_state_renewal = nfs4_proc_async_renew,
+ .get_state_renewal_cred_locked = nfs4_get_renew_cred_locked,
+ .renew_lease = nfs4_proc_renew,
+};
+
+#if defined(CONFIG_NFS_V4_1)
+struct nfs4_state_maintenance_ops nfs41_state_renewal_ops = {
+ .sched_state_renewal = nfs41_proc_async_sequence,
+ .get_state_renewal_cred_locked = nfs4_get_machine_cred_locked,
+ .renew_lease = nfs4_proc_sequence,
+};
+#endif
+
+/*
+ * Per minor version reboot and network partition recovery ops
+ */
+
+struct nfs4_state_recovery_ops *nfs4_reboot_recovery_ops[] = {
+ &nfs40_reboot_recovery_ops,
+#if defined(CONFIG_NFS_V4_1)
+ &nfs41_reboot_recovery_ops,
+#endif
+};
+
+struct nfs4_state_recovery_ops *nfs4_nograce_recovery_ops[] = {
+ &nfs40_nograce_recovery_ops,
+#if defined(CONFIG_NFS_V4_1)
+ &nfs41_nograce_recovery_ops,
+#endif
+};
+
+struct nfs4_state_maintenance_ops *nfs4_state_renewal_ops[] = {
+ &nfs40_state_renewal_ops,
+#if defined(CONFIG_NFS_V4_1)
+ &nfs41_state_renewal_ops,
+#endif
};
static const struct inode_operations nfs4_file_inode_operations = {
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index f524e932ff7b..e27c6cef18f2 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -59,12 +59,14 @@
void
nfs4_renew_state(struct work_struct *work)
{
+ struct nfs4_state_maintenance_ops *ops;
struct nfs_client *clp =
container_of(work, struct nfs_client, cl_renewd.work);
struct rpc_cred *cred;
long lease, timeout;
unsigned long last, now;
+ ops = nfs4_state_renewal_ops[clp->cl_minorversion];
dprintk("%s: start\n", __func__);
/* Are there any active superblocks? */
if (list_empty(&clp->cl_superblocks))
@@ -76,7 +78,7 @@ nfs4_renew_state(struct work_struct *work)
timeout = (2 * lease) / 3 + (long)last - (long)now;
/* Are we close to a lease timeout? */
if (time_after(now, last + lease/3)) {
- cred = nfs4_get_renew_cred_locked(clp);
+ cred = ops->get_state_renewal_cred_locked(clp);
spin_unlock(&clp->cl_lock);
if (cred == NULL) {
if (list_empty(&clp->cl_delegations)) {
@@ -86,7 +88,7 @@ nfs4_renew_state(struct work_struct *work)
nfs_expire_all_delegations(clp);
} else {
/* Queue an asynchronous RENEW. */
- nfs4_proc_async_renew(clp, cred);
+ ops->sched_state_renewal(clp, cred);
put_rpccred(cred);
}
timeout = (2 * lease) / 3;
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 0298e909559f..c16f24dd0e3e 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -60,7 +60,7 @@ const nfs4_stateid zero_stateid;
static LIST_HEAD(nfs4_clientid_list);
-static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred)
+int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
{
unsigned short port;
int status;
@@ -77,7 +77,7 @@ static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred)
return status;
}
-static struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp)
+struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp)
{
struct rpc_cred *cred = NULL;
@@ -114,17 +114,21 @@ struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp)
return cred;
}
-static struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp)
+#if defined(CONFIG_NFS_V4_1)
+
+struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp)
{
struct rpc_cred *cred;
spin_lock(&clp->cl_lock);
- cred = nfs4_get_renew_cred_locked(clp);
+ cred = nfs4_get_machine_cred_locked(clp);
spin_unlock(&clp->cl_lock);
return cred;
}
-static struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp)
+#endif /* CONFIG_NFS_V4_1 */
+
+struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp)
{
struct nfs4_state_owner *sp;
struct rb_node *pos;
@@ -738,12 +742,14 @@ static void nfs_increment_seqid(int status, struct nfs_seqid *seqid)
void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid)
{
- if (status == -NFS4ERR_BAD_SEQID) {
- struct nfs4_state_owner *sp = container_of(seqid->sequence,
- struct nfs4_state_owner, so_seqid);
+ struct nfs4_state_owner *sp = container_of(seqid->sequence,
+ struct nfs4_state_owner, so_seqid);
+ struct nfs_server *server = sp->so_server;
+
+ if (status == -NFS4ERR_BAD_SEQID)
nfs4_drop_state_owner(sp);
- }
- nfs_increment_seqid(status, seqid);
+ if (!nfs4_has_session(server->nfs_client))
+ nfs_increment_seqid(status, seqid);
}
/*
@@ -1042,6 +1048,14 @@ static void nfs4_recovery_handle_error(struct nfs_client *clp, int error)
case -NFS4ERR_EXPIRED:
set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
nfs4_state_start_reclaim_nograce(clp);
+ case -NFS4ERR_BADSESSION:
+ case -NFS4ERR_BADSLOT:
+ case -NFS4ERR_BAD_HIGH_SLOT:
+ case -NFS4ERR_DEADSESSION:
+ case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
+ case -NFS4ERR_SEQ_FALSE_RETRY:
+ case -NFS4ERR_SEQ_MISORDERED:
+ set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
}
}
@@ -1075,18 +1089,22 @@ restart:
static int nfs4_check_lease(struct nfs_client *clp)
{
struct rpc_cred *cred;
+ struct nfs4_state_maintenance_ops *ops =
+ nfs4_state_renewal_ops[clp->cl_minorversion];
int status = -NFS4ERR_EXPIRED;
/* Is the client already known to have an expired lease? */
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
return 0;
- cred = nfs4_get_renew_cred(clp);
+ spin_lock(&clp->cl_lock);
+ cred = ops->get_state_renewal_cred_locked(clp);
+ spin_unlock(&clp->cl_lock);
if (cred == NULL) {
cred = nfs4_get_setclientid_cred(clp);
if (cred == NULL)
goto out;
}
- status = nfs4_proc_renew(clp, cred);
+ status = ops->renew_lease(clp, cred);
put_rpccred(cred);
out:
nfs4_recovery_handle_error(clp, status);
@@ -1096,21 +1114,77 @@ out:
static int nfs4_reclaim_lease(struct nfs_client *clp)
{
struct rpc_cred *cred;
+ struct nfs4_state_recovery_ops *ops =
+ nfs4_reboot_recovery_ops[clp->cl_minorversion];
int status = -ENOENT;
- cred = nfs4_get_setclientid_cred(clp);
+ cred = ops->get_clid_cred(clp);
if (cred != NULL) {
- status = nfs4_init_client(clp, cred);
+ status = ops->establish_clid(clp, cred);
put_rpccred(cred);
/* Handle case where the user hasn't set up machine creds */
if (status == -EACCES && cred == clp->cl_machine_cred) {
nfs4_clear_machine_cred(clp);
status = -EAGAIN;
}
+ if (status == -NFS4ERR_MINOR_VERS_MISMATCH)
+ status = -EPROTONOSUPPORT;
}
return status;
}
+#ifdef CONFIG_NFS_V4_1
+static void nfs4_session_recovery_handle_error(struct nfs_client *clp, int err)
+{
+ switch (err) {
+ case -NFS4ERR_STALE_CLIENTID:
+ set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
+ set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
+ }
+}
+
+static int nfs4_reset_session(struct nfs_client *clp)
+{
+ int status;
+
+ status = nfs4_proc_destroy_session(clp->cl_session);
+ if (status && status != -NFS4ERR_BADSESSION &&
+ status != -NFS4ERR_DEADSESSION) {
+ nfs4_session_recovery_handle_error(clp, status);
+ goto out;
+ }
+
+ memset(clp->cl_session->sess_id.data, 0, NFS4_MAX_SESSIONID_LEN);
+ status = nfs4_proc_create_session(clp, 1);
+ if (status)
+ nfs4_session_recovery_handle_error(clp, status);
+ /* fall through*/
+out:
+ /* Wake up the next rpc task even on error */
+ rpc_wake_up_next(&clp->cl_session->fc_slot_table.slot_tbl_waitq);
+ return status;
+}
+
+static int nfs4_initialize_session(struct nfs_client *clp)
+{
+ int status;
+
+ status = nfs4_proc_create_session(clp, 0);
+ if (!status) {
+ nfs_mark_client_ready(clp, NFS_CS_READY);
+ } else if (status == -NFS4ERR_STALE_CLIENTID) {
+ set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
+ set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
+ } else {
+ nfs_mark_client_ready(clp, status);
+ }
+ return status;
+}
+#else /* CONFIG_NFS_V4_1 */
+static int nfs4_reset_session(struct nfs_client *clp) { return 0; }
+static int nfs4_initialize_session(struct nfs_client *clp) { return 0; }
+#endif /* CONFIG_NFS_V4_1 */
+
static void nfs4_state_manager(struct nfs_client *clp)
{
int status = 0;
@@ -1124,6 +1198,9 @@ static void nfs4_state_manager(struct nfs_client *clp)
set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
if (status == -EAGAIN)
continue;
+ if (clp->cl_cons_state ==
+ NFS_CS_SESSION_INITING)
+ nfs_mark_client_ready(clp, status);
goto out_error;
}
clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state);
@@ -1134,25 +1211,44 @@ static void nfs4_state_manager(struct nfs_client *clp)
if (status != 0)
continue;
}
-
+ /* Initialize or reset the session */
+ if (nfs4_has_session(clp) &&
+ test_and_clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)) {
+ if (clp->cl_cons_state == NFS_CS_SESSION_INITING)
+ status = nfs4_initialize_session(clp);
+ else
+ status = nfs4_reset_session(clp);
+ if (status) {
+ if (status == -NFS4ERR_STALE_CLIENTID)
+ continue;
+ goto out_error;
+ }
+ }
/* First recover reboot state... */
if (test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) {
- status = nfs4_do_reclaim(clp, &nfs4_reboot_recovery_ops);
+ status = nfs4_do_reclaim(clp,
+ nfs4_reboot_recovery_ops[clp->cl_minorversion]);
if (status == -NFS4ERR_STALE_CLIENTID)
continue;
+ if (test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state))
+ continue;
nfs4_state_end_reclaim_reboot(clp);
continue;
}
/* Now recover expired state... */
if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) {
- status = nfs4_do_reclaim(clp, &nfs4_nograce_recovery_ops);
+ status = nfs4_do_reclaim(clp,
+ nfs4_nograce_recovery_ops[clp->cl_minorversion]);
if (status < 0) {
set_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
if (status == -NFS4ERR_STALE_CLIENTID)
continue;
if (status == -NFS4ERR_EXPIRED)
continue;
+ if (test_bit(NFS4CLNT_SESSION_SETUP,
+ &clp->cl_state))
+ continue;
goto out_error;
} else
nfs4_state_end_reclaim_nograce(clp);
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 1690f0e44b91..80af0aeaaf7d 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -192,12 +192,16 @@ static int nfs4_stat_to_errno(int);
decode_verifier_maxsz)
#define encode_remove_maxsz (op_encode_hdr_maxsz + \
nfs4_name_maxsz)
+#define decode_remove_maxsz (op_decode_hdr_maxsz + \
+ decode_change_info_maxsz)
#define encode_rename_maxsz (op_encode_hdr_maxsz + \
2 * nfs4_name_maxsz)
-#define decode_rename_maxsz (op_decode_hdr_maxsz + 5 + 5)
+#define decode_rename_maxsz (op_decode_hdr_maxsz + \
+ decode_change_info_maxsz + \
+ decode_change_info_maxsz)
#define encode_link_maxsz (op_encode_hdr_maxsz + \
nfs4_name_maxsz)
-#define decode_link_maxsz (op_decode_hdr_maxsz + 5)
+#define decode_link_maxsz (op_decode_hdr_maxsz + decode_change_info_maxsz)
#define encode_lock_maxsz (op_encode_hdr_maxsz + \
7 + \
1 + encode_stateid_maxsz + 8)
@@ -240,43 +244,115 @@ static int nfs4_stat_to_errno(int);
(encode_getattr_maxsz)
#define decode_fs_locations_maxsz \
(0)
+
+#if defined(CONFIG_NFS_V4_1)
+#define NFS4_MAX_MACHINE_NAME_LEN (64)
+
+#define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \
+ encode_verifier_maxsz + \
+ 1 /* co_ownerid.len */ + \
+ XDR_QUADLEN(NFS4_EXCHANGE_ID_LEN) + \
+ 1 /* flags */ + \
+ 1 /* spa_how */ + \
+ 0 /* SP4_NONE (for now) */ + \
+ 1 /* zero implemetation id array */)
+#define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \
+ 2 /* eir_clientid */ + \
+ 1 /* eir_sequenceid */ + \
+ 1 /* eir_flags */ + \
+ 1 /* spr_how */ + \
+ 0 /* SP4_NONE (for now) */ + \
+ 2 /* eir_server_owner.so_minor_id */ + \
+ /* eir_server_owner.so_major_id<> */ \
+ XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \
+ /* eir_server_scope<> */ \
+ XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \
+ 1 /* eir_server_impl_id array length */ + \
+ 0 /* ignored eir_server_impl_id contents */)
+#define encode_channel_attrs_maxsz (6 + 1 /* ca_rdma_ird.len (0) */)
+#define decode_channel_attrs_maxsz (6 + \
+ 1 /* ca_rdma_ird.len */ + \
+ 1 /* ca_rdma_ird */)
+#define encode_create_session_maxsz (op_encode_hdr_maxsz + \
+ 2 /* csa_clientid */ + \
+ 1 /* csa_sequence */ + \
+ 1 /* csa_flags */ + \
+ encode_channel_attrs_maxsz + \
+ encode_channel_attrs_maxsz + \
+ 1 /* csa_cb_program */ + \
+ 1 /* csa_sec_parms.len (1) */ + \
+ 1 /* cb_secflavor (AUTH_SYS) */ + \
+ 1 /* stamp */ + \
+ 1 /* machinename.len */ + \
+ XDR_QUADLEN(NFS4_MAX_MACHINE_NAME_LEN) + \
+ 1 /* uid */ + \
+ 1 /* gid */ + \
+ 1 /* gids.len (0) */)
+#define decode_create_session_maxsz (op_decode_hdr_maxsz + \
+ XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
+ 1 /* csr_sequence */ + \
+ 1 /* csr_flags */ + \
+ decode_channel_attrs_maxsz + \
+ decode_channel_attrs_maxsz)
+#define encode_destroy_session_maxsz (op_encode_hdr_maxsz + 4)
+#define decode_destroy_session_maxsz (op_decode_hdr_maxsz)
+#define encode_sequence_maxsz (op_encode_hdr_maxsz + \
+ XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4)
+#define decode_sequence_maxsz (op_decode_hdr_maxsz + \
+ XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5)
+#else /* CONFIG_NFS_V4_1 */
+#define encode_sequence_maxsz 0
+#define decode_sequence_maxsz 0
+#endif /* CONFIG_NFS_V4_1 */
+
#define NFS4_enc_compound_sz (1024) /* XXX: large enough? */
#define NFS4_dec_compound_sz (1024) /* XXX: large enough? */
#define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_read_maxsz)
#define NFS4_dec_read_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_read_maxsz)
#define NFS4_enc_readlink_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_readlink_maxsz)
#define NFS4_dec_readlink_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_readlink_maxsz)
#define NFS4_enc_readdir_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_readdir_maxsz)
#define NFS4_dec_readdir_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_readdir_maxsz)
#define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_write_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_write_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_commit_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_commit_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_savefh_maxsz + \
encode_open_maxsz + \
@@ -285,6 +361,7 @@ static int nfs4_stat_to_errno(int);
encode_restorefh_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_savefh_maxsz + \
decode_open_maxsz + \
@@ -301,43 +378,53 @@ static int nfs4_stat_to_errno(int);
decode_putfh_maxsz + \
decode_open_confirm_maxsz)
#define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_open_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_open_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_open_downgrade_sz \
(compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_open_downgrade_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_open_downgrade_sz \
(compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_open_downgrade_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_close_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_close_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_setattr_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_setattr_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_fsinfo_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_fsinfo_maxsz)
#define NFS4_dec_fsinfo_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_fsinfo_maxsz)
#define NFS4_enc_renew_sz (compound_encode_hdr_maxsz + \
@@ -359,64 +446,81 @@ static int nfs4_stat_to_errno(int);
decode_putrootfh_maxsz + \
decode_fsinfo_maxsz)
#define NFS4_enc_lock_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_lock_maxsz)
#define NFS4_dec_lock_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_lock_maxsz)
#define NFS4_enc_lockt_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_lockt_maxsz)
#define NFS4_dec_lockt_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_lockt_maxsz)
#define NFS4_enc_locku_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_locku_maxsz)
#define NFS4_dec_locku_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_locku_maxsz)
#define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_access_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_access_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_lookup_maxsz + \
encode_getattr_maxsz + \
encode_getfh_maxsz)
#define NFS4_dec_lookup_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_lookup_maxsz + \
decode_getattr_maxsz + \
decode_getfh_maxsz)
#define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putrootfh_maxsz + \
encode_getattr_maxsz + \
encode_getfh_maxsz)
#define NFS4_dec_lookup_root_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putrootfh_maxsz + \
decode_getattr_maxsz + \
decode_getfh_maxsz)
#define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_remove_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
- op_decode_hdr_maxsz + 5 + \
+ decode_remove_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_savefh_maxsz + \
encode_putfh_maxsz + \
@@ -425,6 +529,7 @@ static int nfs4_stat_to_errno(int);
encode_restorefh_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_savefh_maxsz + \
decode_putfh_maxsz + \
@@ -433,6 +538,7 @@ static int nfs4_stat_to_errno(int);
decode_restorefh_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_savefh_maxsz + \
encode_putfh_maxsz + \
@@ -441,6 +547,7 @@ static int nfs4_stat_to_errno(int);
encode_restorefh_maxsz + \
decode_getattr_maxsz)
#define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_savefh_maxsz + \
decode_putfh_maxsz + \
@@ -449,16 +556,19 @@ static int nfs4_stat_to_errno(int);
decode_restorefh_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_symlink_maxsz + \
encode_getattr_maxsz + \
encode_getfh_maxsz)
#define NFS4_dec_symlink_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_symlink_maxsz + \
decode_getattr_maxsz + \
decode_getfh_maxsz)
#define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_savefh_maxsz + \
encode_create_maxsz + \
@@ -467,6 +577,7 @@ static int nfs4_stat_to_errno(int);
encode_restorefh_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_savefh_maxsz + \
decode_create_maxsz + \
@@ -475,52 +586,98 @@ static int nfs4_stat_to_errno(int);
decode_restorefh_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_pathconf_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_statfs_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_statfs_maxsz)
#define NFS4_dec_statfs_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_statfs_maxsz)
#define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_delegreturn_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_delegreturn_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_getacl_maxsz)
#define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_getacl_maxsz)
#define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_setacl_maxsz)
#define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_setacl_maxsz)
#define NFS4_enc_fs_locations_sz \
(compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_lookup_maxsz + \
encode_fs_locations_maxsz)
#define NFS4_dec_fs_locations_sz \
(compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_lookup_maxsz + \
decode_fs_locations_maxsz)
+#if defined(CONFIG_NFS_V4_1)
+#define NFS4_enc_exchange_id_sz \
+ (compound_encode_hdr_maxsz + \
+ encode_exchange_id_maxsz)
+#define NFS4_dec_exchange_id_sz \
+ (compound_decode_hdr_maxsz + \
+ decode_exchange_id_maxsz)
+#define NFS4_enc_create_session_sz \
+ (compound_encode_hdr_maxsz + \
+ encode_create_session_maxsz)
+#define NFS4_dec_create_session_sz \
+ (compound_decode_hdr_maxsz + \
+ decode_create_session_maxsz)
+#define NFS4_enc_destroy_session_sz (compound_encode_hdr_maxsz + \
+ encode_destroy_session_maxsz)
+#define NFS4_dec_destroy_session_sz (compound_decode_hdr_maxsz + \
+ decode_destroy_session_maxsz)
+#define NFS4_enc_sequence_sz \
+ (compound_decode_hdr_maxsz + \
+ encode_sequence_maxsz)
+#define NFS4_dec_sequence_sz \
+ (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz)
+#define NFS4_enc_get_lease_time_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
+ encode_putrootfh_maxsz + \
+ encode_fsinfo_maxsz)
+#define NFS4_dec_get_lease_time_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
+ decode_putrootfh_maxsz + \
+ decode_fsinfo_maxsz)
+#endif /* CONFIG_NFS_V4_1 */
static const umode_t nfs_type2fmt[] = {
[NF4BAD] = 0,
@@ -541,6 +698,8 @@ struct compound_hdr {
__be32 * nops_p;
uint32_t taglen;
char * tag;
+ uint32_t replen; /* expected reply words */
+ u32 minorversion;
};
/*
@@ -576,22 +735,31 @@ static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *
xdr_encode_opaque(p, str, len);
}
-static void encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
+static void encode_compound_hdr(struct xdr_stream *xdr,
+ struct rpc_rqst *req,
+ struct compound_hdr *hdr)
{
__be32 *p;
+ struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
+
+ /* initialize running count of expected bytes in reply.
+ * NOTE: the replied tag SHOULD be the same is the one sent,
+ * but this is not required as a MUST for the server to do so. */
+ hdr->replen = RPC_REPHDRSIZE + auth->au_rslack + 3 + hdr->taglen;
dprintk("encode_compound: tag=%.*s\n", (int)hdr->taglen, hdr->tag);
BUG_ON(hdr->taglen > NFS4_MAXTAGLEN);
RESERVE_SPACE(12+(XDR_QUADLEN(hdr->taglen)<<2));
WRITE32(hdr->taglen);
WRITEMEM(hdr->tag, hdr->taglen);
- WRITE32(NFS4_MINOR_VERSION);
+ WRITE32(hdr->minorversion);
hdr->nops_p = p;
WRITE32(hdr->nops);
}
static void encode_nops(struct compound_hdr *hdr)
{
+ BUG_ON(hdr->nops > NFS4_MAX_OPS);
*hdr->nops_p = htonl(hdr->nops);
}
@@ -736,6 +904,7 @@ static void encode_access(struct xdr_stream *xdr, u32 access, struct compound_hd
WRITE32(OP_ACCESS);
WRITE32(access);
hdr->nops++;
+ hdr->replen += decode_access_maxsz;
}
static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr)
@@ -747,6 +916,7 @@ static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg
WRITE32(arg->seqid->sequence->counter);
WRITEMEM(arg->stateid->data, NFS4_STATEID_SIZE);
hdr->nops++;
+ hdr->replen += decode_close_maxsz;
}
static void encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr)
@@ -758,6 +928,7 @@ static void encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *ar
WRITE64(args->offset);
WRITE32(args->count);
hdr->nops++;
+ hdr->replen += decode_commit_maxsz;
}
static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create, struct compound_hdr *hdr)
@@ -789,6 +960,7 @@ static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *
WRITE32(create->name->len);
WRITEMEM(create->name->name, create->name->len);
hdr->nops++;
+ hdr->replen += decode_create_maxsz;
encode_attrs(xdr, create->attrs, create->server);
}
@@ -802,6 +974,7 @@ static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct c
WRITE32(1);
WRITE32(bitmap);
hdr->nops++;
+ hdr->replen += decode_getattr_maxsz;
}
static void encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1, struct compound_hdr *hdr)
@@ -814,6 +987,7 @@ static void encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm
WRITE32(bm0);
WRITE32(bm1);
hdr->nops++;
+ hdr->replen += decode_getattr_maxsz;
}
static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
@@ -841,6 +1015,7 @@ static void encode_getfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
RESERVE_SPACE(4);
WRITE32(OP_GETFH);
hdr->nops++;
+ hdr->replen += decode_getfh_maxsz;
}
static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
@@ -852,6 +1027,7 @@ static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct
WRITE32(name->len);
WRITEMEM(name->name, name->len);
hdr->nops++;
+ hdr->replen += decode_link_maxsz;
}
static inline int nfs4_lock_type(struct file_lock *fl, int block)
@@ -899,6 +1075,7 @@ static void encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args
WRITE32(args->lock_seqid->sequence->counter);
}
hdr->nops++;
+ hdr->replen += decode_lock_maxsz;
}
static void encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args, struct compound_hdr *hdr)
@@ -915,6 +1092,7 @@ static void encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *ar
WRITEMEM("lock id:", 8);
WRITE64(args->lock_owner.id);
hdr->nops++;
+ hdr->replen += decode_lockt_maxsz;
}
static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args, struct compound_hdr *hdr)
@@ -929,6 +1107,7 @@ static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *ar
WRITE64(args->fl->fl_start);
WRITE64(nfs4_lock_length(args->fl));
hdr->nops++;
+ hdr->replen += decode_locku_maxsz;
}
static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
@@ -941,6 +1120,7 @@ static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struc
WRITE32(len);
WRITEMEM(name->name, len);
hdr->nops++;
+ hdr->replen += decode_lookup_maxsz;
}
static void encode_share_access(struct xdr_stream *xdr, fmode_t fmode)
@@ -1080,6 +1260,7 @@ static void encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg,
BUG();
}
hdr->nops++;
+ hdr->replen += decode_open_maxsz;
}
static void encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg, struct compound_hdr *hdr)
@@ -1091,6 +1272,7 @@ static void encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_co
WRITEMEM(arg->stateid->data, NFS4_STATEID_SIZE);
WRITE32(arg->seqid->sequence->counter);
hdr->nops++;
+ hdr->replen += decode_open_confirm_maxsz;
}
static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr)
@@ -1103,6 +1285,7 @@ static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_close
WRITE32(arg->seqid->sequence->counter);
encode_share_access(xdr, arg->fmode);
hdr->nops++;
+ hdr->replen += decode_open_downgrade_maxsz;
}
static void
@@ -1116,6 +1299,7 @@ encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh, struct compound_hd
WRITE32(len);
WRITEMEM(fh->data, len);
hdr->nops++;
+ hdr->replen += decode_putfh_maxsz;
}
static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
@@ -1125,6 +1309,7 @@ static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
RESERVE_SPACE(4);
WRITE32(OP_PUTROOTFH);
hdr->nops++;
+ hdr->replen += decode_putrootfh_maxsz;
}
static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx)
@@ -1153,6 +1338,7 @@ static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args,
WRITE64(args->offset);
WRITE32(args->count);
hdr->nops++;
+ hdr->replen += decode_read_maxsz;
}
static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr)
@@ -1178,6 +1364,7 @@ static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
WRITE32(attrs[0] & readdir->bitmask[0]);
WRITE32(attrs[1] & readdir->bitmask[1]);
hdr->nops++;
+ hdr->replen += decode_readdir_maxsz;
dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n",
__func__,
(unsigned long long)readdir->cookie,
@@ -1194,6 +1381,7 @@ static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *
RESERVE_SPACE(4);
WRITE32(OP_READLINK);
hdr->nops++;
+ hdr->replen += decode_readlink_maxsz;
}
static void encode_remove(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
@@ -1205,6 +1393,7 @@ static void encode_remove(struct xdr_stream *xdr, const struct qstr *name, struc
WRITE32(name->len);
WRITEMEM(name->name, name->len);
hdr->nops++;
+ hdr->replen += decode_remove_maxsz;
}
static void encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, const struct qstr *newname, struct compound_hdr *hdr)
@@ -1220,6 +1409,7 @@ static void encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, co
WRITE32(newname->len);
WRITEMEM(newname->name, newname->len);
hdr->nops++;
+ hdr->replen += decode_rename_maxsz;
}
static void encode_renew(struct xdr_stream *xdr, const struct nfs_client *client_stateid, struct compound_hdr *hdr)
@@ -1230,6 +1420,7 @@ static void encode_renew(struct xdr_stream *xdr, const struct nfs_client *client
WRITE32(OP_RENEW);
WRITE64(client_stateid->cl_clientid);
hdr->nops++;
+ hdr->replen += decode_renew_maxsz;
}
static void
@@ -1240,6 +1431,7 @@ encode_restorefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
RESERVE_SPACE(4);
WRITE32(OP_RESTOREFH);
hdr->nops++;
+ hdr->replen += decode_restorefh_maxsz;
}
static int
@@ -1259,6 +1451,7 @@ encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg, struct compoun
WRITE32(arg->acl_len);
xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len);
hdr->nops++;
+ hdr->replen += decode_setacl_maxsz;
return 0;
}
@@ -1270,6 +1463,7 @@ encode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
RESERVE_SPACE(4);
WRITE32(OP_SAVEFH);
hdr->nops++;
+ hdr->replen += decode_savefh_maxsz;
}
static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server, struct compound_hdr *hdr)
@@ -1280,6 +1474,7 @@ static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs
WRITE32(OP_SETATTR);
WRITEMEM(arg->stateid.data, NFS4_STATEID_SIZE);
hdr->nops++;
+ hdr->replen += decode_setattr_maxsz;
encode_attrs(xdr, arg->iap, server);
}
@@ -1299,6 +1494,7 @@ static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclie
RESERVE_SPACE(4);
WRITE32(setclientid->sc_cb_ident);
hdr->nops++;
+ hdr->replen += decode_setclientid_maxsz;
}
static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_client *client_state, struct compound_hdr *hdr)
@@ -1310,6 +1506,7 @@ static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_
WRITE64(client_state->cl_clientid);
WRITEMEM(client_state->cl_confirm.data, NFS4_VERIFIER_SIZE);
hdr->nops++;
+ hdr->replen += decode_setclientid_confirm_maxsz;
}
static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr)
@@ -1328,6 +1525,7 @@ static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *arg
xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
hdr->nops++;
+ hdr->replen += decode_write_maxsz;
}
static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid, struct compound_hdr *hdr)
@@ -1339,11 +1537,163 @@ static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *state
WRITE32(OP_DELEGRETURN);
WRITEMEM(stateid->data, NFS4_STATEID_SIZE);
hdr->nops++;
+ hdr->replen += decode_delegreturn_maxsz;
+}
+
+#if defined(CONFIG_NFS_V4_1)
+/* NFSv4.1 operations */
+static void encode_exchange_id(struct xdr_stream *xdr,
+ struct nfs41_exchange_id_args *args,
+ struct compound_hdr *hdr)
+{
+ uint32_t *p;
+
+ RESERVE_SPACE(4 + sizeof(args->verifier->data));
+ WRITE32(OP_EXCHANGE_ID);
+ WRITEMEM(args->verifier->data, sizeof(args->verifier->data));
+
+ encode_string(xdr, args->id_len, args->id);
+
+ RESERVE_SPACE(12);
+ WRITE32(args->flags);
+ WRITE32(0); /* zero length state_protect4_a */
+ WRITE32(0); /* zero length implementation id array */
+ hdr->nops++;
+ hdr->replen += decode_exchange_id_maxsz;
+}
+
+static void encode_create_session(struct xdr_stream *xdr,
+ struct nfs41_create_session_args *args,
+ struct compound_hdr *hdr)
+{
+ uint32_t *p;
+ char machine_name[NFS4_MAX_MACHINE_NAME_LEN];
+ uint32_t len;
+ struct nfs_client *clp = args->client;
+
+ RESERVE_SPACE(4);
+ WRITE32(OP_CREATE_SESSION);
+
+ RESERVE_SPACE(8);
+ WRITE64(clp->cl_ex_clid);
+
+ RESERVE_SPACE(8);
+ WRITE32(clp->cl_seqid); /*Sequence id */
+ WRITE32(args->flags); /*flags */
+
+ RESERVE_SPACE(2*28); /* 2 channel_attrs */
+ /* Fore Channel */
+ WRITE32(args->fc_attrs.headerpadsz); /* header padding size */
+ WRITE32(args->fc_attrs.max_rqst_sz); /* max req size */
+ WRITE32(args->fc_attrs.max_resp_sz); /* max resp size */
+ WRITE32(args->fc_attrs.max_resp_sz_cached); /* Max resp sz cached */
+ WRITE32(args->fc_attrs.max_ops); /* max operations */
+ WRITE32(args->fc_attrs.max_reqs); /* max requests */
+ WRITE32(0); /* rdmachannel_attrs */
+
+ /* Back Channel */
+ WRITE32(args->fc_attrs.headerpadsz); /* header padding size */
+ WRITE32(args->bc_attrs.max_rqst_sz); /* max req size */
+ WRITE32(args->bc_attrs.max_resp_sz); /* max resp size */
+ WRITE32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */
+ WRITE32(args->bc_attrs.max_ops); /* max operations */
+ WRITE32(args->bc_attrs.max_reqs); /* max requests */
+ WRITE32(0); /* rdmachannel_attrs */
+
+ RESERVE_SPACE(4);
+ WRITE32(args->cb_program); /* cb_program */
+
+ RESERVE_SPACE(4); /* # of security flavors */
+ WRITE32(1);
+
+ RESERVE_SPACE(4);
+ WRITE32(RPC_AUTH_UNIX); /* auth_sys */
+
+ /* authsys_parms rfc1831 */
+ RESERVE_SPACE(4);
+ WRITE32((u32)clp->cl_boot_time.tv_nsec); /* stamp */
+ len = scnprintf(machine_name, sizeof(machine_name), "%s",
+ clp->cl_ipaddr);
+ RESERVE_SPACE(16 + len);
+ WRITE32(len);
+ WRITEMEM(machine_name, len);
+ WRITE32(0); /* UID */
+ WRITE32(0); /* GID */
+ WRITE32(0); /* No more gids */
+ hdr->nops++;
+ hdr->replen += decode_create_session_maxsz;
}
+
+static void encode_destroy_session(struct xdr_stream *xdr,
+ struct nfs4_session *session,
+ struct compound_hdr *hdr)
+{
+ uint32_t *p;
+ RESERVE_SPACE(4 + NFS4_MAX_SESSIONID_LEN);
+ WRITE32(OP_DESTROY_SESSION);
+ WRITEMEM(session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
+ hdr->nops++;
+ hdr->replen += decode_destroy_session_maxsz;
+}
+#endif /* CONFIG_NFS_V4_1 */
+
+static void encode_sequence(struct xdr_stream *xdr,
+ const struct nfs4_sequence_args *args,
+ struct compound_hdr *hdr)
+{
+#if defined(CONFIG_NFS_V4_1)
+ struct nfs4_session *session = args->sa_session;
+ struct nfs4_slot_table *tp;
+ struct nfs4_slot *slot;
+ __be32 *p;
+
+ if (!session)
+ return;
+
+ tp = &session->fc_slot_table;
+
+ WARN_ON(args->sa_slotid == NFS4_MAX_SLOT_TABLE);
+ slot = tp->slots + args->sa_slotid;
+
+ RESERVE_SPACE(4);
+ WRITE32(OP_SEQUENCE);
+
+ /*
+ * Sessionid + seqid + slotid + max slotid + cache_this
+ */
+ dprintk("%s: sessionid=%u:%u:%u:%u seqid=%d slotid=%d "
+ "max_slotid=%d cache_this=%d\n",
+ __func__,
+ ((u32 *)session->sess_id.data)[0],
+ ((u32 *)session->sess_id.data)[1],
+ ((u32 *)session->sess_id.data)[2],
+ ((u32 *)session->sess_id.data)[3],
+ slot->seq_nr, args->sa_slotid,
+ tp->highest_used_slotid, args->sa_cache_this);
+ RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 16);
+ WRITEMEM(session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
+ WRITE32(slot->seq_nr);
+ WRITE32(args->sa_slotid);
+ WRITE32(tp->highest_used_slotid);
+ WRITE32(args->sa_cache_this);
+ hdr->nops++;
+ hdr->replen += decode_sequence_maxsz;
+#endif /* CONFIG_NFS_V4_1 */
+}
+
/*
* END OF "GENERIC" ENCODE ROUTINES.
*/
+static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args)
+{
+#if defined(CONFIG_NFS_V4_1)
+ if (args->sa_session)
+ return args->sa_session->clp->cl_minorversion;
+#endif /* CONFIG_NFS_V4_1 */
+ return 0;
+}
+
/*
* Encode an ACCESS request
*/
@@ -1351,11 +1701,12 @@ static int nfs4_xdr_enc_access(struct rpc_rqst *req, __be32 *p, const struct nfs
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
encode_access(&xdr, args->access, &hdr);
encode_getfattr(&xdr, args->bitmask, &hdr);
@@ -1370,11 +1721,12 @@ static int nfs4_xdr_enc_lookup(struct rpc_rqst *req, __be32 *p, const struct nfs
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->dir_fh, &hdr);
encode_lookup(&xdr, args->name, &hdr);
encode_getfh(&xdr, &hdr);
@@ -1390,11 +1742,12 @@ static int nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, __be32 *p, const struc
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putrootfh(&xdr, &hdr);
encode_getfh(&xdr, &hdr);
encode_getfattr(&xdr, args->bitmask, &hdr);
@@ -1409,11 +1762,12 @@ static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p, const struct nfs
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
encode_remove(&xdr, &args->name, &hdr);
encode_getfattr(&xdr, args->bitmask, &hdr);
@@ -1428,11 +1782,12 @@ static int nfs4_xdr_enc_rename(struct rpc_rqst *req, __be32 *p, const struct nfs
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->old_dir, &hdr);
encode_savefh(&xdr, &hdr);
encode_putfh(&xdr, args->new_dir, &hdr);
@@ -1451,11 +1806,12 @@ static int nfs4_xdr_enc_link(struct rpc_rqst *req, __be32 *p, const struct nfs4_
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
encode_savefh(&xdr, &hdr);
encode_putfh(&xdr, args->dir_fh, &hdr);
@@ -1474,11 +1830,12 @@ static int nfs4_xdr_enc_create(struct rpc_rqst *req, __be32 *p, const struct nfs
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->dir_fh, &hdr);
encode_savefh(&xdr, &hdr);
encode_create(&xdr, args, &hdr);
@@ -1505,11 +1862,12 @@ static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, __be32 *p, const struct nf
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
encode_getfattr(&xdr, args->bitmask, &hdr);
encode_nops(&hdr);
@@ -1523,11 +1881,12 @@ static int nfs4_xdr_enc_close(struct rpc_rqst *req, __be32 *p, struct nfs_closea
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
encode_close(&xdr, args, &hdr);
encode_getfattr(&xdr, args->bitmask, &hdr);
@@ -1542,11 +1901,12 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, __be32 *p, struct nfs_openarg
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
encode_savefh(&xdr, &hdr);
encode_open(&xdr, args, &hdr);
@@ -1569,7 +1929,7 @@ static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, __be32 *p, struct nfs
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
encode_open_confirm(&xdr, args, &hdr);
encode_nops(&hdr);
@@ -1583,11 +1943,12 @@ static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, __be32 *p, struct nfs_
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
encode_open(&xdr, args, &hdr);
encode_getfattr(&xdr, args->bitmask, &hdr);
@@ -1602,11 +1963,12 @@ static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, __be32 *p, struct n
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
encode_open_downgrade(&xdr, args, &hdr);
encode_getfattr(&xdr, args->bitmask, &hdr);
@@ -1621,11 +1983,12 @@ static int nfs4_xdr_enc_lock(struct rpc_rqst *req, __be32 *p, struct nfs_lock_ar
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
encode_lock(&xdr, args, &hdr);
encode_nops(&hdr);
@@ -1639,11 +2002,12 @@ static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, __be32 *p, struct nfs_lockt_
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
encode_lockt(&xdr, args, &hdr);
encode_nops(&hdr);
@@ -1657,11 +2021,12 @@ static int nfs4_xdr_enc_locku(struct rpc_rqst *req, __be32 *p, struct nfs_locku_
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
encode_locku(&xdr, args, &hdr);
encode_nops(&hdr);
@@ -1675,22 +2040,16 @@ static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct n
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
- struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
- unsigned int replen;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
encode_readlink(&xdr, args, req, &hdr);
- /* set up reply kvec
- * toplevel_status + taglen + rescount + OP_PUTFH + status
- * + OP_READLINK + status + string length = 8
- */
- replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_readlink_sz) << 2;
- xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages,
+ xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages,
args->pgbase, args->pglen);
encode_nops(&hdr);
return 0;
@@ -1703,25 +2062,19 @@ static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nf
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
- struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
- int replen;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
encode_readdir(&xdr, args, req, &hdr);
- /* set up reply kvec
- * toplevel_status + taglen + rescount + OP_PUTFH + status
- * + OP_READDIR + status + verifer(2) = 9
- */
- replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_readdir_sz) << 2;
- xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages,
+ xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages,
args->pgbase, args->count);
dprintk("%s: inlined page args = (%u, %p, %u, %u)\n",
- __func__, replen, args->pages,
+ __func__, hdr.replen << 2, args->pages,
args->pgbase, args->count);
encode_nops(&hdr);
return 0;
@@ -1732,24 +2085,18 @@ static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nf
*/
static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
{
- struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
- int replen;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
encode_read(&xdr, args, &hdr);
- /* set up reply kvec
- * toplevel status + taglen=0 + rescount + OP_PUTFH + status
- * + OP_READ + status + eof + datalen = 9
- */
- replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_read_sz) << 2;
- xdr_inline_pages(&req->rq_rcv_buf, replen,
+ xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
args->pages, args->pgbase, args->count);
req->rq_rcv_buf.flags |= XDRBUF_READ;
encode_nops(&hdr);
@@ -1763,11 +2110,12 @@ static int nfs4_xdr_enc_setattr(struct rpc_rqst *req, __be32 *p, struct nfs_seta
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
encode_setattr(&xdr, args, args->server, &hdr);
encode_getfattr(&xdr, args->bitmask, &hdr);
@@ -1783,20 +2131,19 @@ nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p,
struct nfs_getaclargs *args)
{
struct xdr_stream xdr;
- struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
- int replen;
+ uint32_t replen;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
+ replen = hdr.replen + nfs4_fattr_bitmap_maxsz + 1;
encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0, &hdr);
- /* set up reply buffer: */
- replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_getacl_sz) << 2;
- xdr_inline_pages(&req->rq_rcv_buf, replen,
+ xdr_inline_pages(&req->rq_rcv_buf, replen << 2,
args->acl_pages, args->acl_pgbase, args->acl_len);
encode_nops(&hdr);
return 0;
@@ -1809,11 +2156,12 @@ static int nfs4_xdr_enc_write(struct rpc_rqst *req, __be32 *p, struct nfs_writea
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
encode_write(&xdr, args, &hdr);
req->rq_snd_buf.flags |= XDRBUF_WRITE;
@@ -1829,11 +2177,12 @@ static int nfs4_xdr_enc_commit(struct rpc_rqst *req, __be32 *p, struct nfs_write
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
encode_commit(&xdr, args, &hdr);
encode_getfattr(&xdr, args->bitmask, &hdr);
@@ -1848,11 +2197,12 @@ static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs4_fsin
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
encode_fsinfo(&xdr, args->bitmask, &hdr);
encode_nops(&hdr);
@@ -1866,11 +2216,12 @@ static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, __be32 *p, const struct n
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
encode_getattr_one(&xdr, args->bitmask[0] & nfs4_pathconf_bitmap[0],
&hdr);
@@ -1885,11 +2236,12 @@ static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, __be32 *p, const struct nfs
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
encode_getattr_two(&xdr, args->bitmask[0] & nfs4_statfs_bitmap[0],
args->bitmask[1] & nfs4_statfs_bitmap[1], &hdr);
@@ -1900,16 +2252,18 @@ static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, __be32 *p, const struct nfs
/*
* GETATTR_BITMAP request
*/
-static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, __be32 *p, const struct nfs_fh *fhandle)
+static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, __be32 *p,
+ struct nfs4_server_caps_arg *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- encode_putfh(&xdr, fhandle, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
+ encode_putfh(&xdr, args->fhandle, &hdr);
encode_getattr_one(&xdr, FATTR4_WORD0_SUPPORTED_ATTRS|
FATTR4_WORD0_LINK_SUPPORT|
FATTR4_WORD0_SYMLINK_SUPPORT|
@@ -1929,7 +2283,7 @@ static int nfs4_xdr_enc_renew(struct rpc_rqst *req, __be32 *p, struct nfs_client
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
encode_renew(&xdr, clp, &hdr);
encode_nops(&hdr);
return 0;
@@ -1946,7 +2300,7 @@ static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, __be32 *p, struct nfs4
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
encode_setclientid(&xdr, sc, &hdr);
encode_nops(&hdr);
return 0;
@@ -1964,7 +2318,7 @@ static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str
const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
encode_setclientid_confirm(&xdr, clp, &hdr);
encode_putrootfh(&xdr, &hdr);
encode_fsinfo(&xdr, lease_bitmap, &hdr);
@@ -1979,11 +2333,12 @@ static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, __be32 *p, const struc
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fhandle, &hdr);
encode_delegreturn(&xdr, args->stateid, &hdr);
encode_getfattr(&xdr, args->bitmask, &hdr);
@@ -1998,28 +2353,119 @@ static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
- struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
- int replen;
+ uint32_t replen;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->dir_fh, &hdr);
encode_lookup(&xdr, args->name, &hdr);
+ replen = hdr.replen; /* get the attribute into args->page */
encode_fs_locations(&xdr, args->bitmask, &hdr);
- /* set up reply
- * toplevel_status + OP_PUTFH + status
- * + OP_LOOKUP + status + OP_GETATTR + status = 7
- */
- replen = (RPC_REPHDRSIZE + auth->au_rslack + 7) << 2;
- xdr_inline_pages(&req->rq_rcv_buf, replen, &args->page,
+ xdr_inline_pages(&req->rq_rcv_buf, replen << 2, &args->page,
0, PAGE_SIZE);
encode_nops(&hdr);
return 0;
}
+#if defined(CONFIG_NFS_V4_1)
+/*
+ * EXCHANGE_ID request
+ */
+static int nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, uint32_t *p,
+ struct nfs41_exchange_id_args *args)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr = {
+ .minorversion = args->client->cl_minorversion,
+ };
+
+ xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_exchange_id(&xdr, args, &hdr);
+ encode_nops(&hdr);
+ return 0;
+}
+
+/*
+ * a CREATE_SESSION request
+ */
+static int nfs4_xdr_enc_create_session(struct rpc_rqst *req, uint32_t *p,
+ struct nfs41_create_session_args *args)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr = {
+ .minorversion = args->client->cl_minorversion,
+ };
+
+ xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_create_session(&xdr, args, &hdr);
+ encode_nops(&hdr);
+ return 0;
+}
+
+/*
+ * a DESTROY_SESSION request
+ */
+static int nfs4_xdr_enc_destroy_session(struct rpc_rqst *req, uint32_t *p,
+ struct nfs4_session *session)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr = {
+ .minorversion = session->clp->cl_minorversion,
+ };
+
+ xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_destroy_session(&xdr, session, &hdr);
+ encode_nops(&hdr);
+ return 0;
+}
+
+/*
+ * a SEQUENCE request
+ */
+static int nfs4_xdr_enc_sequence(struct rpc_rqst *req, uint32_t *p,
+ struct nfs4_sequence_args *args)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr = {
+ .minorversion = nfs4_xdr_minorversion(args),
+ };
+
+ xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, args, &hdr);
+ encode_nops(&hdr);
+ return 0;
+}
+
+/*
+ * a GET_LEASE_TIME request
+ */
+static int nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, uint32_t *p,
+ struct nfs4_get_lease_time_args *args)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr = {
+ .minorversion = nfs4_xdr_minorversion(&args->la_seq_args),
+ };
+ const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
+
+ xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->la_seq_args, &hdr);
+ encode_putrootfh(&xdr, &hdr);
+ encode_fsinfo(&xdr, lease_bitmap, &hdr);
+ encode_nops(&hdr);
+ return 0;
+}
+#endif /* CONFIG_NFS_V4_1 */
+
/*
* START OF "GENERIC" DECODE ROUTINES.
* These may look a little ugly since they are imported from a "generic"
@@ -3657,7 +4103,7 @@ decode_savefh(struct xdr_stream *xdr)
return decode_op_hdr(xdr, OP_SAVEFH);
}
-static int decode_setattr(struct xdr_stream *xdr, struct nfs_setattrres *res)
+static int decode_setattr(struct xdr_stream *xdr)
{
__be32 *p;
uint32_t bmlen;
@@ -3735,6 +4181,175 @@ static int decode_delegreturn(struct xdr_stream *xdr)
return decode_op_hdr(xdr, OP_DELEGRETURN);
}
+#if defined(CONFIG_NFS_V4_1)
+static int decode_exchange_id(struct xdr_stream *xdr,
+ struct nfs41_exchange_id_res *res)
+{
+ uint32_t *p;
+ int status, dummy;
+ struct nfs_client *clp = res->client;
+
+ status = decode_op_hdr(xdr, OP_EXCHANGE_ID);
+ if (status)
+ return status;
+
+ READ_BUF(8);
+ READ64(clp->cl_ex_clid);
+ READ_BUF(12);
+ READ32(clp->cl_seqid);
+ READ32(clp->cl_exchange_flags);
+
+ /* We ask for SP4_NONE */
+ READ32(dummy);
+ if (dummy != SP4_NONE)
+ return -EIO;
+
+ /* minor_id */
+ READ_BUF(8);
+ READ64(res->server_owner.minor_id);
+
+ /* Major id */
+ READ_BUF(4);
+ READ32(res->server_owner.major_id_sz);
+ READ_BUF(res->server_owner.major_id_sz);
+ COPYMEM(res->server_owner.major_id, res->server_owner.major_id_sz);
+
+ /* server_scope */
+ READ_BUF(4);
+ READ32(res->server_scope.server_scope_sz);
+ READ_BUF(res->server_scope.server_scope_sz);
+ COPYMEM(res->server_scope.server_scope,
+ res->server_scope.server_scope_sz);
+ /* Throw away Implementation id array */
+ READ_BUF(4);
+ READ32(dummy);
+ p += XDR_QUADLEN(dummy);
+
+ return 0;
+}
+
+static int decode_create_session(struct xdr_stream *xdr,
+ struct nfs41_create_session_res *res)
+{
+ uint32_t *p;
+ int status;
+ u32 nr_attrs;
+ struct nfs_client *clp = res->client;
+ struct nfs4_session *session = clp->cl_session;
+
+ status = decode_op_hdr(xdr, OP_CREATE_SESSION);
+
+ if (status)
+ return status;
+
+ /* sessionid */
+ READ_BUF(NFS4_MAX_SESSIONID_LEN);
+ COPYMEM(&session->sess_id, NFS4_MAX_SESSIONID_LEN);
+
+ /* seqid, flags */
+ READ_BUF(8);
+ READ32(clp->cl_seqid);
+ READ32(session->flags);
+
+ /* Channel attributes */
+ /* fore channel */
+ READ_BUF(24);
+ READ32(session->fc_attrs.headerpadsz);
+ READ32(session->fc_attrs.max_rqst_sz);
+ READ32(session->fc_attrs.max_resp_sz);
+ READ32(session->fc_attrs.max_resp_sz_cached);
+ READ32(session->fc_attrs.max_ops);
+ READ32(session->fc_attrs.max_reqs);
+ READ_BUF(4);
+ READ32(nr_attrs);
+ if (nr_attrs == 1) {
+ READ_BUF(4);
+ p++; /* skip rdma_attrs */
+ }
+
+ /* back channel */
+ READ_BUF(24);
+ READ32(session->bc_attrs.headerpadsz);
+ READ32(session->bc_attrs.max_rqst_sz);
+ READ32(session->bc_attrs.max_resp_sz);
+ READ32(session->bc_attrs.max_resp_sz_cached);
+ READ32(session->bc_attrs.max_ops);
+ READ32(session->bc_attrs.max_reqs);
+ READ_BUF(4);
+ READ32(nr_attrs);
+ if (nr_attrs == 1) {
+ READ_BUF(4);
+ p++; /* skip rdma_attrs */
+ }
+
+ return 0;
+}
+
+static int decode_destroy_session(struct xdr_stream *xdr, void *dummy)
+{
+ return decode_op_hdr(xdr, OP_DESTROY_SESSION);
+}
+#endif /* CONFIG_NFS_V4_1 */
+
+static int decode_sequence(struct xdr_stream *xdr,
+ struct nfs4_sequence_res *res,
+ struct rpc_rqst *rqstp)
+{
+#if defined(CONFIG_NFS_V4_1)
+ struct nfs4_slot *slot;
+ struct nfs4_sessionid id;
+ u32 dummy;
+ int status;
+ __be32 *p;
+
+ if (!res->sr_session)
+ return 0;
+
+ status = decode_op_hdr(xdr, OP_SEQUENCE);
+ if (status)
+ goto out_err;
+
+ /*
+ * If the server returns different values for sessionID, slotID or
+ * sequence number, the server is looney tunes.
+ */
+ status = -ESERVERFAULT;
+
+ slot = &res->sr_session->fc_slot_table.slots[res->sr_slotid];
+ READ_BUF(NFS4_MAX_SESSIONID_LEN + 20);
+ COPYMEM(id.data, NFS4_MAX_SESSIONID_LEN);
+ if (memcmp(id.data, res->sr_session->sess_id.data,
+ NFS4_MAX_SESSIONID_LEN)) {
+ dprintk("%s Invalid session id\n", __func__);
+ goto out_err;
+ }
+ /* seqid */
+ READ32(dummy);
+ if (dummy != slot->seq_nr) {
+ dprintk("%s Invalid sequence number\n", __func__);
+ goto out_err;
+ }
+ /* slot id */
+ READ32(dummy);
+ if (dummy != res->sr_slotid) {
+ dprintk("%s Invalid slot id\n", __func__);
+ goto out_err;
+ }
+ /* highest slot id - currently not processed */
+ READ32(dummy);
+ /* target highest slot id - currently not processed */
+ READ32(dummy);
+ /* result flags - currently not processed */
+ READ32(dummy);
+ status = 0;
+out_err:
+ res->sr_status = status;
+ return status;
+#else /* CONFIG_NFS_V4_1 */
+ return 0;
+#endif /* CONFIG_NFS_V4_1 */
+}
+
/*
* END OF "GENERIC" DECODE ROUTINES.
*/
@@ -3752,6 +4367,9 @@ static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, __be32 *p, struct
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -3773,7 +4391,11 @@ static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_ac
int status;
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
- if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
goto out;
status = decode_putfh(&xdr);
if (status != 0)
@@ -3796,7 +4418,11 @@ static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_lo
int status;
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
- if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
goto out;
if ((status = decode_putfh(&xdr)) != 0)
goto out;
@@ -3819,7 +4445,11 @@ static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, __be32 *p, struct nf
int status;
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
- if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
goto out;
if ((status = decode_putrootfh(&xdr)) != 0)
goto out;
@@ -3839,7 +4469,11 @@ static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, __be32 *p, struct nfs_rem
int status;
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
- if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
goto out;
if ((status = decode_putfh(&xdr)) != 0)
goto out;
@@ -3860,7 +4494,11 @@ static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_re
int status;
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
- if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
goto out;
if ((status = decode_putfh(&xdr)) != 0)
goto out;
@@ -3890,7 +4528,11 @@ static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_link
int status;
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
- if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
goto out;
if ((status = decode_putfh(&xdr)) != 0)
goto out;
@@ -3923,7 +4565,11 @@ static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_cr
int status;
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
- if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
goto out;
if ((status = decode_putfh(&xdr)) != 0)
goto out;
@@ -3963,6 +4609,9 @@ static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_g
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -3979,12 +4628,13 @@ nfs4_xdr_enc_setacl(struct rpc_rqst *req, __be32 *p, struct nfs_setaclargs *args
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
int status;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
+ encode_compound_hdr(&xdr, req, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr);
status = encode_setacl(&xdr, args, &hdr);
encode_nops(&hdr);
@@ -3995,7 +4645,8 @@ nfs4_xdr_enc_setacl(struct rpc_rqst *req, __be32 *p, struct nfs_setaclargs *args
* Decode SETACL response
*/
static int
-nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, __be32 *p, void *res)
+nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs_setaclres *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4005,10 +4656,13 @@ nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, __be32 *p, void *res)
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
- status = decode_setattr(&xdr, res);
+ status = decode_setattr(&xdr);
out:
return status;
}
@@ -4017,7 +4671,8 @@ out:
* Decode GETACL response
*/
static int
-nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, __be32 *p, size_t *acl_len)
+nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs_getaclres *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4027,10 +4682,13 @@ nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, __be32 *p, size_t *acl_len)
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
- status = decode_getacl(&xdr, rqstp, acl_len);
+ status = decode_getacl(&xdr, rqstp, &res->acl_len);
out:
return status;
@@ -4049,6 +4707,9 @@ static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, __be32 *p, struct nfs_clos
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4079,6 +4740,9 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openr
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4133,6 +4797,9 @@ static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, __be32 *p, struct nf
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4157,10 +4824,13 @@ static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs_se
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
- status = decode_setattr(&xdr, res);
+ status = decode_setattr(&xdr);
if (status)
goto out;
decode_getfattr(&xdr, res->fattr, res->server);
@@ -4181,6 +4851,9 @@ static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock_
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4202,6 +4875,9 @@ static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4223,6 +4899,9 @@ static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4234,7 +4913,8 @@ out:
/*
* Decode READLINK response
*/
-static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, __be32 *p, void *res)
+static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs4_readlink_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4244,6 +4924,9 @@ static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, __be32 *p, void *res)
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4265,6 +4948,9 @@ static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_r
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4286,6 +4972,9 @@ static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, __be32 *p, struct nfs_readr
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4309,6 +4998,9 @@ static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writ
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4335,6 +5027,9 @@ static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, __be32 *p, struct nfs_wri
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4349,7 +5044,8 @@ out:
/*
* FSINFO request
*/
-static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *fsinfo)
+static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p,
+ struct nfs4_fsinfo_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4358,16 +5054,19 @@ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs_fsinf
xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
status = decode_compound_hdr(&xdr, &hdr);
if (!status)
+ status = decode_sequence(&xdr, &res->seq_res, req);
+ if (!status)
status = decode_putfh(&xdr);
if (!status)
- status = decode_fsinfo(&xdr, fsinfo);
+ status = decode_fsinfo(&xdr, res->fsinfo);
return status;
}
/*
* PATHCONF request
*/
-static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *pathconf)
+static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p,
+ struct nfs4_pathconf_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4376,16 +5075,19 @@ static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p, struct nfs_pat
xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
status = decode_compound_hdr(&xdr, &hdr);
if (!status)
+ status = decode_sequence(&xdr, &res->seq_res, req);
+ if (!status)
status = decode_putfh(&xdr);
if (!status)
- status = decode_pathconf(&xdr, pathconf);
+ status = decode_pathconf(&xdr, res->pathconf);
return status;
}
/*
* STATFS request
*/
-static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *fsstat)
+static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p,
+ struct nfs4_statfs_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4394,9 +5096,11 @@ static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p, struct nfs_fssta
xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
status = decode_compound_hdr(&xdr, &hdr);
if (!status)
+ status = decode_sequence(&xdr, &res->seq_res, req);
+ if (!status)
status = decode_putfh(&xdr);
if (!status)
- status = decode_statfs(&xdr, fsstat);
+ status = decode_statfs(&xdr, res->fsstat);
return status;
}
@@ -4410,7 +5114,11 @@ static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, __be32 *p, struct nfs4
int status;
xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
- if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, req);
+ if (status)
goto out;
if ((status = decode_putfh(&xdr)) != 0)
goto out;
@@ -4483,7 +5191,10 @@ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p, struct nf
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
status = decode_compound_hdr(&xdr, &hdr);
- if (status != 0)
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
goto out;
status = decode_putfh(&xdr);
if (status != 0)
@@ -4497,7 +5208,8 @@ out:
/*
* FS_LOCATIONS request
*/
-static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs4_fs_locations *res)
+static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p,
+ struct nfs4_fs_locations_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4505,18 +5217,113 @@ static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs
xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
status = decode_compound_hdr(&xdr, &hdr);
- if (status != 0)
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, req);
+ if (status)
goto out;
if ((status = decode_putfh(&xdr)) != 0)
goto out;
if ((status = decode_lookup(&xdr)) != 0)
goto out;
xdr_enter_page(&xdr, PAGE_SIZE);
- status = decode_getfattr(&xdr, &res->fattr, res->server);
+ status = decode_getfattr(&xdr, &res->fs_locations->fattr,
+ res->fs_locations->server);
out:
return status;
}
+#if defined(CONFIG_NFS_V4_1)
+/*
+ * EXCHANGE_ID request
+ */
+static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, uint32_t *p,
+ void *res)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr;
+ int status;
+
+ xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (!status)
+ status = decode_exchange_id(&xdr, res);
+ return status;
+}
+
+/*
+ * a CREATE_SESSION request
+ */
+static int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp, uint32_t *p,
+ struct nfs41_create_session_res *res)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr;
+ int status;
+
+ xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (!status)
+ status = decode_create_session(&xdr, res);
+ return status;
+}
+
+/*
+ * a DESTROY_SESSION request
+ */
+static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp, uint32_t *p,
+ void *dummy)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr;
+ int status;
+
+ xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (!status)
+ status = decode_destroy_session(&xdr, dummy);
+ return status;
+}
+
+/*
+ * a SEQUENCE request
+ */
+static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp, uint32_t *p,
+ struct nfs4_sequence_res *res)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr;
+ int status;
+
+ xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (!status)
+ status = decode_sequence(&xdr, res, rqstp);
+ return status;
+}
+
+/*
+ * a GET_LEASE_TIME request
+ */
+static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, uint32_t *p,
+ struct nfs4_get_lease_time_res *res)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr;
+ int status;
+
+ xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (!status)
+ status = decode_sequence(&xdr, &res->lr_seq_res, rqstp);
+ if (!status)
+ status = decode_putrootfh(&xdr);
+ if (!status)
+ status = decode_fsinfo(&xdr, res->lr_fsinfo);
+ return status;
+}
+#endif /* CONFIG_NFS_V4_1 */
+
__be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
{
uint32_t bitmap[2] = {0};
@@ -4686,6 +5493,13 @@ struct rpc_procinfo nfs4_procedures[] = {
PROC(GETACL, enc_getacl, dec_getacl),
PROC(SETACL, enc_setacl, dec_setacl),
PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations),
+#if defined(CONFIG_NFS_V4_1)
+ PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id),
+ PROC(CREATE_SESSION, enc_create_session, dec_create_session),
+ PROC(DESTROY_SESSION, enc_destroy_session, dec_destroy_session),
+ PROC(SEQUENCE, enc_sequence, dec_sequence),
+ PROC(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time),
+#endif /* CONFIG_NFS_V4_1 */
};
struct rpc_version nfs_version4 = {
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 4ace3c50a8eb..96c4ebfa46f4 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -22,6 +22,7 @@
#include <asm/system.h>
+#include "nfs4_fs.h"
#include "internal.h"
#include "iostat.h"
#include "fscache.h"
@@ -46,6 +47,7 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
memset(p, 0, sizeof(*p));
INIT_LIST_HEAD(&p->pages);
p->npages = pagecount;
+ p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
if (pagecount <= ARRAY_SIZE(p->page_array))
p->pagevec = p->page_array;
else {
@@ -357,19 +359,25 @@ static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data
struct nfs_readres *resp = &data->res;
if (resp->eof || resp->count == argp->count)
- return;
+ goto out;
/* This is a short read! */
nfs_inc_stats(data->inode, NFSIOS_SHORTREAD);
/* Has the server at least made some progress? */
if (resp->count == 0)
- return;
+ goto out;
/* Yes, so retry the read at the end of the data */
argp->offset += resp->count;
argp->pgbase += resp->count;
argp->count -= resp->count;
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, NFS_SERVER(data->inode)->nfs_client);
+ return;
+out:
+ nfs4_sequence_free_slot(NFS_SERVER(data->inode)->nfs_client,
+ &data->res.seq_res);
+ return;
+
}
/*
@@ -406,7 +414,23 @@ static void nfs_readpage_release_partial(void *calldata)
nfs_readdata_release(calldata);
}
+#if defined(CONFIG_NFS_V4_1)
+void nfs_read_prepare(struct rpc_task *task, void *calldata)
+{
+ struct nfs_read_data *data = calldata;
+
+ if (nfs4_setup_sequence(NFS_SERVER(data->inode)->nfs_client,
+ &data->args.seq_args, &data->res.seq_res,
+ 0, task))
+ return;
+ rpc_call_start(task);
+}
+#endif /* CONFIG_NFS_V4_1 */
+
static const struct rpc_call_ops nfs_read_partial_ops = {
+#if defined(CONFIG_NFS_V4_1)
+ .rpc_call_prepare = nfs_read_prepare,
+#endif /* CONFIG_NFS_V4_1 */
.rpc_call_done = nfs_readpage_result_partial,
.rpc_release = nfs_readpage_release_partial,
};
@@ -470,6 +494,9 @@ static void nfs_readpage_release_full(void *calldata)
}
static const struct rpc_call_ops nfs_read_full_ops = {
+#if defined(CONFIG_NFS_V4_1)
+ .rpc_call_prepare = nfs_read_prepare,
+#endif /* CONFIG_NFS_V4_1 */
.rpc_call_done = nfs_readpage_result_full,
.rpc_release = nfs_readpage_release_full,
};
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 6717200923fe..73db6f8c145a 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -90,6 +90,7 @@ enum {
Opt_mountport,
Opt_mountvers,
Opt_nfsvers,
+ Opt_minorversion,
/* Mount options that take string arguments */
Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost,
@@ -155,6 +156,7 @@ static const match_table_t nfs_mount_option_tokens = {
{ Opt_mountvers, "mountvers=%u" },
{ Opt_nfsvers, "nfsvers=%u" },
{ Opt_nfsvers, "vers=%u" },
+ { Opt_minorversion, "minorversion=%u" },
{ Opt_sec, "sec=%s" },
{ Opt_proto, "proto=%s" },
@@ -683,9 +685,12 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
*/
static void nfs_umount_begin(struct super_block *sb)
{
- struct nfs_server *server = NFS_SB(sb);
+ struct nfs_server *server;
struct rpc_clnt *rpc;
+ lock_kernel();
+
+ server = NFS_SB(sb);
/* -EIO all pending I/O */
rpc = server->client_acl;
if (!IS_ERR(rpc))
@@ -693,6 +698,8 @@ static void nfs_umount_begin(struct super_block *sb)
rpc = server->client;
if (!IS_ERR(rpc))
rpc_killall_tasks(rpc);
+
+ unlock_kernel();
}
/*
@@ -1206,6 +1213,13 @@ static int nfs_parse_mount_options(char *raw,
nfs_parse_invalid_value("nfsvers");
}
break;
+ case Opt_minorversion:
+ if (match_int(args, &option))
+ return 0;
+ if (option < 0 || option > NFS4_MAX_MINOR_VERSION)
+ return 0;
+ mnt->minorversion = option;
+ break;
/*
* options that take text values
@@ -2106,8 +2120,7 @@ out_err_nosb:
error_splat_root:
dput(mntroot);
error_splat_super:
- up_write(&s->s_umount);
- deactivate_super(s);
+ deactivate_locked_super(s);
goto out;
}
@@ -2203,8 +2216,7 @@ out_err_noserver:
return error;
error_splat_super:
- up_write(&s->s_umount);
- deactivate_super(s);
+ deactivate_locked_super(s);
dprintk("<-- nfs_xdev_get_sb() = %d [splat]\n", error);
return error;
}
@@ -2258,6 +2270,7 @@ static int nfs4_validate_mount_data(void *options,
args->nfs_server.port = NFS_PORT; /* 2049 unless user set port= */
args->auth_flavors[0] = RPC_AUTH_UNIX;
args->auth_flavor_len = 0;
+ args->minorversion = 0;
switch (data->version) {
case 1:
@@ -2464,8 +2477,7 @@ out_free:
error_splat_root:
dput(mntroot);
error_splat_super:
- up_write(&s->s_umount);
- deactivate_super(s);
+ deactivate_locked_super(s);
goto out;
}
@@ -2473,12 +2485,14 @@ static void nfs4_kill_super(struct super_block *sb)
{
struct nfs_server *server = NFS_SB(sb);
+ dprintk("--> %s\n", __func__);
nfs_super_return_all_delegations(sb);
kill_anon_super(sb);
nfs4_renewd_prepare_shutdown(server);
nfs_fscache_release_super_cookie(sb);
nfs_free_server(server);
+ dprintk("<-- %s\n", __func__);
}
/*
@@ -2559,8 +2573,7 @@ out_err_noserver:
return error;
error_splat_super:
- up_write(&s->s_umount);
- deactivate_super(s);
+ deactivate_locked_super(s);
dprintk("<-- nfs4_xdev_get_sb() = %d [splat]\n", error);
return error;
}
@@ -2644,8 +2657,7 @@ out_err_noserver:
return error;
error_splat_super:
- up_write(&s->s_umount);
- deactivate_super(s);
+ deactivate_locked_super(s);
dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error);
return error;
}
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index ecc295347775..1064c91ae810 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -15,6 +15,7 @@
#include <linux/wait.h>
#include "internal.h"
+#include "nfs4_fs.h"
struct nfs_unlinkdata {
struct hlist_node list;
@@ -82,7 +83,7 @@ static void nfs_async_unlink_done(struct rpc_task *task, void *calldata)
struct inode *dir = data->dir;
if (!NFS_PROTO(dir)->unlink_done(task, dir))
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, NFS_SERVER(dir)->nfs_client);
}
/**
@@ -102,9 +103,25 @@ static void nfs_async_unlink_release(void *calldata)
nfs_sb_deactive(sb);
}
+#if defined(CONFIG_NFS_V4_1)
+void nfs_unlink_prepare(struct rpc_task *task, void *calldata)
+{
+ struct nfs_unlinkdata *data = calldata;
+ struct nfs_server *server = NFS_SERVER(data->dir);
+
+ if (nfs4_setup_sequence(server->nfs_client, &data->args.seq_args,
+ &data->res.seq_res, 1, task))
+ return;
+ rpc_call_start(task);
+}
+#endif /* CONFIG_NFS_V4_1 */
+
static const struct rpc_call_ops nfs_unlink_ops = {
.rpc_call_done = nfs_async_unlink_done,
.rpc_release = nfs_async_unlink_release,
+#if defined(CONFIG_NFS_V4_1)
+ .rpc_call_prepare = nfs_unlink_prepare,
+#endif /* CONFIG_NFS_V4_1 */
};
static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct nfs_unlinkdata *data)
@@ -241,6 +258,7 @@ nfs_async_unlink(struct inode *dir, struct dentry *dentry)
status = PTR_ERR(data->cred);
goto out_free;
}
+ data->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
status = -EBUSY;
spin_lock(&dentry->d_lock);
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index e560a78995a3..ce728829f79a 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -25,6 +25,7 @@
#include "delegation.h"
#include "internal.h"
#include "iostat.h"
+#include "nfs4_fs.h"
#define NFSDBG_FACILITY NFSDBG_PAGECACHE
@@ -52,6 +53,7 @@ struct nfs_write_data *nfs_commitdata_alloc(void)
if (p) {
memset(p, 0, sizeof(*p));
INIT_LIST_HEAD(&p->pages);
+ p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
}
return p;
}
@@ -71,6 +73,7 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
memset(p, 0, sizeof(*p));
INIT_LIST_HEAD(&p->pages);
p->npages = pagecount;
+ p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
if (pagecount <= ARRAY_SIZE(p->page_array))
p->pagevec = p->page_array;
else {
@@ -1048,7 +1051,23 @@ out:
nfs_writedata_release(calldata);
}
+#if defined(CONFIG_NFS_V4_1)
+void nfs_write_prepare(struct rpc_task *task, void *calldata)
+{
+ struct nfs_write_data *data = calldata;
+ struct nfs_client *clp = (NFS_SERVER(data->inode))->nfs_client;
+
+ if (nfs4_setup_sequence(clp, &data->args.seq_args,
+ &data->res.seq_res, 1, task))
+ return;
+ rpc_call_start(task);
+}
+#endif /* CONFIG_NFS_V4_1 */
+
static const struct rpc_call_ops nfs_write_partial_ops = {
+#if defined(CONFIG_NFS_V4_1)
+ .rpc_call_prepare = nfs_write_prepare,
+#endif /* CONFIG_NFS_V4_1 */
.rpc_call_done = nfs_writeback_done_partial,
.rpc_release = nfs_writeback_release_partial,
};
@@ -1111,6 +1130,9 @@ remove_request:
}
static const struct rpc_call_ops nfs_write_full_ops = {
+#if defined(CONFIG_NFS_V4_1)
+ .rpc_call_prepare = nfs_write_prepare,
+#endif /* CONFIG_NFS_V4_1 */
.rpc_call_done = nfs_writeback_done_full,
.rpc_release = nfs_writeback_release_full,
};
@@ -1123,6 +1145,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
{
struct nfs_writeargs *argp = &data->args;
struct nfs_writeres *resp = &data->res;
+ struct nfs_server *server = NFS_SERVER(data->inode);
int status;
dprintk("NFS: %5u nfs_writeback_done (status %d)\n",
@@ -1155,7 +1178,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
if (time_before(complain, jiffies)) {
dprintk("NFS: faulty NFS server %s:"
" (committed = %d) != (stable = %d)\n",
- NFS_SERVER(data->inode)->nfs_client->cl_hostname,
+ server->nfs_client->cl_hostname,
resp->verf->committed, argp->stable);
complain = jiffies + 300 * HZ;
}
@@ -1181,7 +1204,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
*/
argp->stable = NFS_FILE_SYNC;
}
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, server->nfs_client);
return -EAGAIN;
}
if (time_before(complain, jiffies)) {
@@ -1193,6 +1216,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
/* Can't do anything about it except throw an error. */
task->tk_status = -EIO;
}
+ nfs4_sequence_free_slot(server->nfs_client, &data->res.seq_res);
return 0;
}
@@ -1349,6 +1373,9 @@ static void nfs_commit_release(void *calldata)
}
static const struct rpc_call_ops nfs_commit_ops = {
+#if defined(CONFIG_NFS_V4_1)
+ .rpc_call_prepare = nfs_write_prepare,
+#endif /* CONFIG_NFS_V4_1 */
.rpc_call_done = nfs_commit_done,
.rpc_release = nfs_commit_release,
};
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 5839b229cd0e..b92a27629fb7 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -464,16 +464,11 @@ static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp)
if (err)
return err;
/*
- * Just a quick sanity check; we could also try to check
- * whether this pseudoflavor is supported, but at worst
- * an unsupported pseudoflavor on the export would just
- * be a pseudoflavor that won't match the flavor of any
- * authenticated request. The administrator will
- * probably discover the problem when someone fails to
- * authenticate.
+ * XXX: It would be nice to also check whether this
+ * pseudoflavor is supported, so we can discover the
+ * problem at export time instead of when a client fails
+ * to authenticate.
*/
- if (f->pseudoflavor < 0)
- return -EINVAL;
err = get_int(mesg, &f->flags);
if (err)
return err;
@@ -847,9 +842,8 @@ exp_get_fsid_key(svc_client *clp, int fsid)
return exp_find_key(clp, FSID_NUM, fsidv, NULL);
}
-static 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, const struct path *path,
+ struct cache_req *reqp)
{
struct svc_export *exp, key;
int err;
@@ -858,8 +852,7 @@ static svc_export *exp_get_by_name(svc_client *clp, struct vfsmount *mnt,
return ERR_PTR(-ENOENT);
key.ex_client = clp;
- key.ex_path.mnt = mnt;
- key.ex_path.dentry = dentry;
+ key.ex_path = *path;
exp = svc_export_lookup(&key);
if (exp == NULL)
@@ -873,24 +866,19 @@ static svc_export *exp_get_by_name(svc_client *clp, struct vfsmount *mnt,
/*
* Find the export entry for a given dentry.
*/
-static 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 path *path)
{
- svc_export *exp;
-
- dget(dentry);
- exp = exp_get_by_name(clp, mnt, dentry, reqp);
-
- while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(dentry)) {
- struct dentry *parent;
-
- parent = dget_parent(dentry);
- dput(dentry);
- dentry = parent;
- exp = exp_get_by_name(clp, mnt, dentry, reqp);
+ struct dentry *saved = dget(path->dentry);
+ svc_export *exp = exp_get_by_name(clp, path, NULL);
+
+ while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(path->dentry)) {
+ struct dentry *parent = dget_parent(path->dentry);
+ dput(path->dentry);
+ path->dentry = parent;
+ exp = exp_get_by_name(clp, path, NULL);
}
- dput(dentry);
+ dput(path->dentry);
+ path->dentry = saved;
return exp;
}
@@ -1018,7 +1006,7 @@ exp_export(struct nfsctl_export *nxp)
goto out_put_clp;
err = -EINVAL;
- exp = exp_get_by_name(clp, path.mnt, path.dentry, NULL);
+ exp = exp_get_by_name(clp, &path, NULL);
memset(&new, 0, sizeof(new));
@@ -1135,7 +1123,7 @@ exp_unexport(struct nfsctl_export *nxp)
goto out_domain;
err = -EINVAL;
- exp = exp_get_by_name(dom, path.mnt, path.dentry, NULL);
+ exp = exp_get_by_name(dom, &path, NULL);
path_put(&path);
if (IS_ERR(exp))
goto out_domain;
@@ -1177,7 +1165,7 @@ exp_rootfh(svc_client *clp, char *name, struct knfsd_fh *f, int maxsize)
dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n",
name, path.dentry, clp->name,
inode->i_sb->s_id, inode->i_ino);
- exp = exp_parent(clp, path.mnt, path.dentry, NULL);
+ exp = exp_parent(clp, &path);
if (IS_ERR(exp)) {
err = PTR_ERR(exp);
goto out;
@@ -1207,7 +1195,7 @@ static struct svc_export *exp_find(struct auth_domain *clp, int fsid_type,
if (IS_ERR(ek))
return ERR_CAST(ek);
- exp = exp_get_by_name(clp, ek->ek_path.mnt, ek->ek_path.dentry, reqp);
+ exp = exp_get_by_name(clp, &ek->ek_path, reqp);
cache_put(&ek->h, &svc_expkey_cache);
if (IS_ERR(exp))
@@ -1247,8 +1235,7 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
* use exp_get_by_name() or exp_find().
*/
struct svc_export *
-rqst_exp_get_by_name(struct svc_rqst *rqstp, struct vfsmount *mnt,
- struct dentry *dentry)
+rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path)
{
struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT);
@@ -1256,8 +1243,7 @@ rqst_exp_get_by_name(struct svc_rqst *rqstp, struct vfsmount *mnt,
goto gss;
/* First try the auth_unix client: */
- exp = exp_get_by_name(rqstp->rq_client, mnt, dentry,
- &rqstp->rq_chandle);
+ exp = exp_get_by_name(rqstp->rq_client, path, &rqstp->rq_chandle);
if (PTR_ERR(exp) == -ENOENT)
goto gss;
if (IS_ERR(exp))
@@ -1269,8 +1255,7 @@ gss:
/* Otherwise, try falling back on gss client */
if (rqstp->rq_gssclient == NULL)
return exp;
- gssexp = exp_get_by_name(rqstp->rq_gssclient, mnt, dentry,
- &rqstp->rq_chandle);
+ gssexp = exp_get_by_name(rqstp->rq_gssclient, path, &rqstp->rq_chandle);
if (PTR_ERR(gssexp) == -ENOENT)
return exp;
if (!IS_ERR(exp))
@@ -1309,23 +1294,19 @@ gss:
}
struct svc_export *
-rqst_exp_parent(struct svc_rqst *rqstp, struct vfsmount *mnt,
- struct dentry *dentry)
+rqst_exp_parent(struct svc_rqst *rqstp, struct path *path)
{
- struct svc_export *exp;
-
- dget(dentry);
- exp = rqst_exp_get_by_name(rqstp, mnt, dentry);
-
- while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(dentry)) {
- struct dentry *parent;
-
- parent = dget_parent(dentry);
- dput(dentry);
- dentry = parent;
- exp = rqst_exp_get_by_name(rqstp, mnt, dentry);
+ struct dentry *saved = dget(path->dentry);
+ struct svc_export *exp = rqst_exp_get_by_name(rqstp, path);
+
+ while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(path->dentry)) {
+ struct dentry *parent = dget_parent(path->dentry);
+ dput(path->dentry);
+ path->dentry = parent;
+ exp = rqst_exp_get_by_name(rqstp, path);
}
- dput(dentry);
+ dput(path->dentry);
+ path->dentry = saved;
return exp;
}
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 17d0dd997204..01d4ec1c88e0 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -272,6 +272,7 @@ void fill_post_wcc(struct svc_fh *fhp)
err = vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry,
&fhp->fh_post_attr);
+ fhp->fh_post_change = fhp->fh_dentry->d_inode->i_version;
if (err)
fhp->fh_post_saved = 0;
else
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 290289bd44f7..f4fab69a8c30 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -215,18 +215,18 @@ encode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr)
}
static int
-encode_cb_recall(struct xdr_stream *xdr, struct nfs4_cb_recall *cb_rec)
+encode_cb_recall(struct xdr_stream *xdr, struct nfs4_delegation *dp)
{
__be32 *p;
- int len = cb_rec->cbr_fh.fh_size;
+ int len = dp->dl_fh.fh_size;
- RESERVE_SPACE(12+sizeof(cb_rec->cbr_stateid) + len);
+ RESERVE_SPACE(12+sizeof(dp->dl_stateid) + len);
WRITE32(OP_CB_RECALL);
- WRITE32(cb_rec->cbr_stateid.si_generation);
- WRITEMEM(&cb_rec->cbr_stateid.si_opaque, sizeof(stateid_opaque_t));
- WRITE32(cb_rec->cbr_trunc);
+ WRITE32(dp->dl_stateid.si_generation);
+ WRITEMEM(&dp->dl_stateid.si_opaque, sizeof(stateid_opaque_t));
+ WRITE32(0); /* truncate optimization not implemented */
WRITE32(len);
- WRITEMEM(&cb_rec->cbr_fh.fh_base, len);
+ WRITEMEM(&dp->dl_fh.fh_base, len);
return 0;
}
@@ -241,11 +241,11 @@ nfs4_xdr_enc_cb_null(struct rpc_rqst *req, __be32 *p)
}
static int
-nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p, struct nfs4_cb_recall *args)
+nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p, struct nfs4_delegation *args)
{
struct xdr_stream xdr;
struct nfs4_cb_compound_hdr hdr = {
- .ident = args->cbr_ident,
+ .ident = args->dl_ident,
.nops = 1,
};
@@ -358,18 +358,21 @@ static struct rpc_program cb_program = {
.pipe_dir_name = "/nfsd4_cb",
};
+static int max_cb_time(void)
+{
+ return max(NFSD_LEASE_TIME/10, (time_t)1) * HZ;
+}
+
/* Reference counting, callback cleanup, etc., all look racy as heck.
* And why is cb_set an atomic? */
-static struct rpc_clnt *setup_callback_client(struct nfs4_client *clp)
+int setup_callback_client(struct nfs4_client *clp)
{
struct sockaddr_in addr;
- struct nfs4_callback *cb = &clp->cl_callback;
+ struct nfs4_cb_conn *cb = &clp->cl_cb_conn;
struct rpc_timeout timeparms = {
- .to_initval = (NFSD_LEASE_TIME/4) * HZ,
- .to_retries = 5,
- .to_maxval = (NFSD_LEASE_TIME/2) * HZ,
- .to_exponential = 1,
+ .to_initval = max_cb_time(),
+ .to_retries = 0,
};
struct rpc_create_args args = {
.protocol = IPPROTO_TCP,
@@ -386,7 +389,7 @@ static struct rpc_clnt *setup_callback_client(struct nfs4_client *clp)
struct rpc_clnt *client;
if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5))
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
/* Initialize address */
memset(&addr, 0, sizeof(addr));
@@ -396,48 +399,77 @@ static struct rpc_clnt *setup_callback_client(struct nfs4_client *clp)
/* Create RPC client */
client = rpc_create(&args);
- if (IS_ERR(client))
+ if (IS_ERR(client)) {
dprintk("NFSD: couldn't create callback client: %ld\n",
PTR_ERR(client));
- return client;
+ return PTR_ERR(client);
+ }
+ cb->cb_client = client;
+ return 0;
+
+}
+
+static void warn_no_callback_path(struct nfs4_client *clp, int reason)
+{
+ dprintk("NFSD: warning: no callback path to client %.*s: error %d\n",
+ (int)clp->cl_name.len, clp->cl_name.data, reason);
+}
+
+static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata)
+{
+ struct nfs4_client *clp = calldata;
+
+ if (task->tk_status)
+ warn_no_callback_path(clp, task->tk_status);
+ else
+ atomic_set(&clp->cl_cb_conn.cb_set, 1);
+ put_nfs4_client(clp);
+}
+
+static const struct rpc_call_ops nfsd4_cb_probe_ops = {
+ .rpc_call_done = nfsd4_cb_probe_done,
+};
+static struct rpc_cred *lookup_cb_cred(struct nfs4_cb_conn *cb)
+{
+ struct auth_cred acred = {
+ .machine_cred = 1
+ };
+
+ /*
+ * Note in the gss case this doesn't actually have to wait for a
+ * gss upcall (or any calls to the client); this just creates a
+ * non-uptodate cred which the rpc state machine will fill in with
+ * a refresh_upcall later.
+ */
+ return rpcauth_lookup_credcache(cb->cb_client->cl_auth, &acred,
+ RPCAUTH_LOOKUP_NEW);
}
-static int do_probe_callback(void *data)
+void do_probe_callback(struct nfs4_client *clp)
{
- struct nfs4_client *clp = data;
- struct nfs4_callback *cb = &clp->cl_callback;
+ struct nfs4_cb_conn *cb = &clp->cl_cb_conn;
struct rpc_message msg = {
.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
.rpc_argp = clp,
};
- struct rpc_clnt *client;
+ struct rpc_cred *cred;
int status;
- client = setup_callback_client(clp);
- if (IS_ERR(client)) {
- status = PTR_ERR(client);
- dprintk("NFSD: couldn't create callback client: %d\n",
- status);
- goto out_err;
+ cred = lookup_cb_cred(cb);
+ if (IS_ERR(cred)) {
+ status = PTR_ERR(cred);
+ goto out;
+ }
+ cb->cb_cred = cred;
+ msg.rpc_cred = cb->cb_cred;
+ status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_SOFT,
+ &nfsd4_cb_probe_ops, (void *)clp);
+out:
+ if (status) {
+ warn_no_callback_path(clp, status);
+ put_nfs4_client(clp);
}
-
- status = rpc_call_sync(client, &msg, RPC_TASK_SOFT);
-
- if (status)
- goto out_release_client;
-
- cb->cb_client = client;
- atomic_set(&cb->cb_set, 1);
- put_nfs4_client(clp);
- return 0;
-out_release_client:
- rpc_shutdown_client(client);
-out_err:
- dprintk("NFSD: warning: no callback path to client %.*s: error %d\n",
- (int)clp->cl_name.len, clp->cl_name.data, status);
- put_nfs4_client(clp);
- return 0;
}
/*
@@ -446,21 +478,65 @@ out_err:
void
nfsd4_probe_callback(struct nfs4_client *clp)
{
- struct task_struct *t;
+ int status;
+
+ BUG_ON(atomic_read(&clp->cl_cb_conn.cb_set));
- BUG_ON(atomic_read(&clp->cl_callback.cb_set));
+ status = setup_callback_client(clp);
+ if (status) {
+ warn_no_callback_path(clp, status);
+ return;
+ }
/* the task holds a reference to the nfs4_client struct */
atomic_inc(&clp->cl_count);
- t = kthread_run(do_probe_callback, clp, "nfs4_cb_probe");
+ do_probe_callback(clp);
+}
- if (IS_ERR(t))
- atomic_dec(&clp->cl_count);
+static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
+{
+ struct nfs4_delegation *dp = calldata;
+ struct nfs4_client *clp = dp->dl_client;
- return;
+ switch (task->tk_status) {
+ case -EIO:
+ /* Network partition? */
+ atomic_set(&clp->cl_cb_conn.cb_set, 0);
+ warn_no_callback_path(clp, task->tk_status);
+ case -EBADHANDLE:
+ case -NFS4ERR_BAD_STATEID:
+ /* Race: client probably got cb_recall
+ * before open reply granting delegation */
+ break;
+ default:
+ /* success, or error we can't handle */
+ return;
+ }
+ if (dp->dl_retries--) {
+ rpc_delay(task, 2*HZ);
+ task->tk_status = 0;
+ rpc_restart_call(task);
+ } else {
+ atomic_set(&clp->cl_cb_conn.cb_set, 0);
+ warn_no_callback_path(clp, task->tk_status);
+ }
}
+static void nfsd4_cb_recall_release(void *calldata)
+{
+ struct nfs4_delegation *dp = calldata;
+ struct nfs4_client *clp = dp->dl_client;
+
+ nfs4_put_delegation(dp);
+ put_nfs4_client(clp);
+}
+
+static const struct rpc_call_ops nfsd4_cb_recall_ops = {
+ .rpc_call_done = nfsd4_cb_recall_done,
+ .rpc_release = nfsd4_cb_recall_release,
+};
+
/*
* called with dp->dl_count inc'ed.
*/
@@ -468,41 +544,19 @@ void
nfsd4_cb_recall(struct nfs4_delegation *dp)
{
struct nfs4_client *clp = dp->dl_client;
- struct rpc_clnt *clnt = clp->cl_callback.cb_client;
- struct nfs4_cb_recall *cbr = &dp->dl_recall;
+ struct rpc_clnt *clnt = clp->cl_cb_conn.cb_client;
struct rpc_message msg = {
.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
- .rpc_argp = cbr,
+ .rpc_argp = dp,
+ .rpc_cred = clp->cl_cb_conn.cb_cred
};
- int retries = 1;
- int status = 0;
-
- cbr->cbr_trunc = 0; /* XXX need to implement truncate optimization */
- cbr->cbr_dp = dp;
-
- status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
- while (retries--) {
- switch (status) {
- case -EIO:
- /* Network partition? */
- atomic_set(&clp->cl_callback.cb_set, 0);
- case -EBADHANDLE:
- case -NFS4ERR_BAD_STATEID:
- /* Race: client probably got cb_recall
- * before open reply granting delegation */
- break;
- default:
- goto out_put_cred;
- }
- ssleep(2);
- status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
+ int status;
+
+ dp->dl_retries = 1;
+ status = rpc_call_async(clnt, &msg, RPC_TASK_SOFT,
+ &nfsd4_cb_recall_ops, dp);
+ if (status) {
+ put_nfs4_client(clp);
+ nfs4_put_delegation(dp);
}
-out_put_cred:
- /*
- * Success or failure, now we're either waiting for lease expiration
- * or deleg_return.
- */
- put_nfs4_client(clp);
- nfs4_put_delegation(dp);
- return;
}
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 3444c0052a87..5275097a7565 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -229,21 +229,23 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
goto out;
status = vfs_readdir(filp, nfsd4_build_namelist, &names);
fput(filp);
+ mutex_lock(&dir->d_inode->i_mutex);
while (!list_empty(&names)) {
entry = list_entry(names.next, struct name_list, list);
dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1);
if (IS_ERR(dentry)) {
status = PTR_ERR(dentry);
- goto out;
+ break;
}
status = f(dir, dentry);
dput(dentry);
if (status)
- goto out;
+ break;
list_del(&entry->list);
kfree(entry);
}
+ mutex_unlock(&dir->d_inode->i_mutex);
out:
while (!list_empty(&names)) {
entry = list_entry(names.next, struct name_list, list);
@@ -255,36 +257,6 @@ out:
}
static int
-nfsd4_remove_clid_file(struct dentry *dir, struct dentry *dentry)
-{
- int status;
-
- if (!S_ISREG(dir->d_inode->i_mode)) {
- printk("nfsd4: non-file found in client recovery directory\n");
- return -EINVAL;
- }
- mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
- status = vfs_unlink(dir->d_inode, dentry);
- mutex_unlock(&dir->d_inode->i_mutex);
- return status;
-}
-
-static int
-nfsd4_clear_clid_dir(struct dentry *dir, struct dentry *dentry)
-{
- int status;
-
- /* For now this directory should already be empty, but we empty it of
- * any regular files anyway, just in case the directory was created by
- * a kernel from the future.... */
- nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file);
- mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
- status = vfs_rmdir(dir->d_inode, dentry);
- mutex_unlock(&dir->d_inode->i_mutex);
- return status;
-}
-
-static int
nfsd4_unlink_clid_dir(char *name, int namlen)
{
struct dentry *dentry;
@@ -294,18 +266,18 @@ nfsd4_unlink_clid_dir(char *name, int namlen)
mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
dentry = lookup_one_len(name, rec_dir.dentry, namlen);
- mutex_unlock(&rec_dir.dentry->d_inode->i_mutex);
if (IS_ERR(dentry)) {
status = PTR_ERR(dentry);
- return status;
+ goto out_unlock;
}
status = -ENOENT;
if (!dentry->d_inode)
goto out;
-
- status = nfsd4_clear_clid_dir(rec_dir.dentry, dentry);
+ status = vfs_rmdir(rec_dir.dentry->d_inode, dentry);
out:
dput(dentry);
+out_unlock:
+ mutex_unlock(&rec_dir.dentry->d_inode->i_mutex);
return status;
}
@@ -348,7 +320,7 @@ purge_old(struct dentry *parent, struct dentry *child)
if (nfs4_has_reclaimed_state(child->d_name.name, false))
return 0;
- status = nfsd4_clear_clid_dir(parent, child);
+ status = vfs_rmdir(parent->d_inode, child);
if (status)
printk("failed to remove client recovery directory %s\n",
child->d_name.name);
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index c65a27b76a9d..89d9ac55c034 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -182,7 +182,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
{
struct nfs4_delegation *dp;
struct nfs4_file *fp = stp->st_file;
- struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback;
+ struct nfs4_cb_conn *cb = &stp->st_stateowner->so_client->cl_cb_conn;
dprintk("NFSD alloc_init_deleg\n");
if (fp->fi_had_conflict)
@@ -203,10 +203,8 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
get_file(stp->st_vfs_file);
dp->dl_vfs_file = stp->st_vfs_file;
dp->dl_type = type;
- dp->dl_recall.cbr_dp = NULL;
- dp->dl_recall.cbr_ident = cb->cb_ident;
- dp->dl_recall.cbr_trunc = 0;
- dp->dl_stateid.si_boot = boot_time;
+ dp->dl_ident = cb->cb_ident;
+ dp->dl_stateid.si_boot = get_seconds();
dp->dl_stateid.si_stateownerid = current_delegid++;
dp->dl_stateid.si_fileid = 0;
dp->dl_stateid.si_generation = 0;
@@ -580,7 +578,6 @@ free_session(struct kref *kref)
struct nfsd4_cache_entry *e = &ses->se_slots[i].sl_cache_entry;
nfsd4_release_respages(e->ce_respages, e->ce_resused);
}
- kfree(ses->se_slots);
kfree(ses);
}
@@ -633,16 +630,20 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)
static void
shutdown_callback_client(struct nfs4_client *clp)
{
- struct rpc_clnt *clnt = clp->cl_callback.cb_client;
+ struct rpc_clnt *clnt = clp->cl_cb_conn.cb_client;
if (clnt) {
/*
* Callback threads take a reference on the client, so there
* should be no outstanding callbacks at this point.
*/
- clp->cl_callback.cb_client = NULL;
+ clp->cl_cb_conn.cb_client = NULL;
rpc_shutdown_client(clnt);
}
+ if (clp->cl_cb_conn.cb_cred) {
+ put_rpccred(clp->cl_cb_conn.cb_cred);
+ clp->cl_cb_conn.cb_cred = NULL;
+ }
}
static inline void
@@ -715,7 +716,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir)
return NULL;
memcpy(clp->cl_recdir, recdir, HEXDIR_LEN);
atomic_set(&clp->cl_count, 1);
- atomic_set(&clp->cl_callback.cb_set, 0);
+ atomic_set(&clp->cl_cb_conn.cb_set, 0);
INIT_LIST_HEAD(&clp->cl_idhash);
INIT_LIST_HEAD(&clp->cl_strhash);
INIT_LIST_HEAD(&clp->cl_openowners);
@@ -967,7 +968,7 @@ parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigne
static void
gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
{
- struct nfs4_callback *cb = &clp->cl_callback;
+ struct nfs4_cb_conn *cb = &clp->cl_cb_conn;
/* Currently, we only support tcp for the callback channel */
if ((se->se_callback_netid_len != 3) || memcmp((char *)se->se_callback_netid_val, "tcp", 3))
@@ -1687,9 +1688,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
else {
/* XXX: We just turn off callbacks until we can handle
* change request correctly. */
- atomic_set(&conf->cl_callback.cb_set, 0);
- gen_confirm(conf);
- nfsd4_remove_clid_dir(unconf);
+ atomic_set(&conf->cl_cb_conn.cb_set, 0);
expire_client(unconf);
status = nfs_ok;
@@ -1883,7 +1882,7 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *
stp->st_stateowner = sop;
get_nfs4_file(fp);
stp->st_file = fp;
- stp->st_stateid.si_boot = boot_time;
+ stp->st_stateid.si_boot = get_seconds();
stp->st_stateid.si_stateownerid = sop->so_id;
stp->st_stateid.si_fileid = fp->fi_id;
stp->st_stateid.si_generation = 0;
@@ -2060,19 +2059,6 @@ nfs4_file_downgrade(struct file *filp, unsigned int share_access)
}
/*
- * Recall a delegation
- */
-static int
-do_recall(void *__dp)
-{
- struct nfs4_delegation *dp = __dp;
-
- dp->dl_file->fi_had_conflict = true;
- nfsd4_cb_recall(dp);
- return 0;
-}
-
-/*
* Spawn a thread to perform a recall on the delegation represented
* by the lease (file_lock)
*
@@ -2083,8 +2069,7 @@ do_recall(void *__dp)
static
void nfsd_break_deleg_cb(struct file_lock *fl)
{
- struct nfs4_delegation *dp= (struct nfs4_delegation *)fl->fl_owner;
- struct task_struct *t;
+ struct nfs4_delegation *dp = (struct nfs4_delegation *)fl->fl_owner;
dprintk("NFSD nfsd_break_deleg_cb: dp %p fl %p\n",dp,fl);
if (!dp)
@@ -2112,16 +2097,8 @@ void nfsd_break_deleg_cb(struct file_lock *fl)
*/
fl->fl_break_time = 0;
- t = kthread_run(do_recall, dp, "%s", "nfs4_cb_recall");
- if (IS_ERR(t)) {
- struct nfs4_client *clp = dp->dl_client;
-
- printk(KERN_INFO "NFSD: Callback thread failed for "
- "for client (clientid %08x/%08x)\n",
- clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
- put_nfs4_client(dp->dl_client);
- nfs4_put_delegation(dp);
- }
+ dp->dl_file->fi_had_conflict = true;
+ nfsd4_cb_recall(dp);
}
/*
@@ -2423,7 +2400,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
{
struct nfs4_delegation *dp;
struct nfs4_stateowner *sop = stp->st_stateowner;
- struct nfs4_callback *cb = &sop->so_client->cl_callback;
+ struct nfs4_cb_conn *cb = &sop->so_client->cl_cb_conn;
struct file_lock fl, *flp = &fl;
int status, flag = 0;
@@ -2615,7 +2592,7 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
renew_client(clp);
status = nfserr_cb_path_down;
if (!list_empty(&clp->cl_delegations)
- && !atomic_read(&clp->cl_callback.cb_set))
+ && !atomic_read(&clp->cl_cb_conn.cb_set))
goto out;
status = nfs_ok;
out:
@@ -2739,12 +2716,42 @@ nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
static int
STALE_STATEID(stateid_t *stateid)
{
- if (stateid->si_boot == boot_time)
- return 0;
- dprintk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n",
- stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid,
- stateid->si_generation);
- return 1;
+ if (time_after((unsigned long)boot_time,
+ (unsigned long)stateid->si_boot)) {
+ dprintk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n",
+ stateid->si_boot, stateid->si_stateownerid,
+ stateid->si_fileid, stateid->si_generation);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+EXPIRED_STATEID(stateid_t *stateid)
+{
+ if (time_before((unsigned long)boot_time,
+ ((unsigned long)stateid->si_boot)) &&
+ time_before((unsigned long)(stateid->si_boot + lease_time), get_seconds())) {
+ dprintk("NFSD: expired stateid (%08x/%08x/%08x/%08x)!\n",
+ stateid->si_boot, stateid->si_stateownerid,
+ stateid->si_fileid, stateid->si_generation);
+ return 1;
+ }
+ return 0;
+}
+
+static __be32
+stateid_error_map(stateid_t *stateid)
+{
+ if (STALE_STATEID(stateid))
+ return nfserr_stale_stateid;
+ if (EXPIRED_STATEID(stateid))
+ return nfserr_expired;
+
+ dprintk("NFSD: bad stateid (%08x/%08x/%08x/%08x)!\n",
+ stateid->si_boot, stateid->si_stateownerid,
+ stateid->si_fileid, stateid->si_generation);
+ return nfserr_bad_stateid;
}
static inline int
@@ -2868,8 +2875,10 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
status = nfserr_bad_stateid;
if (is_delegation_stateid(stateid)) {
dp = find_delegation_stateid(ino, stateid);
- if (!dp)
+ if (!dp) {
+ status = stateid_error_map(stateid);
goto out;
+ }
status = check_stateid_generation(stateid, &dp->dl_stateid,
flags);
if (status)
@@ -2882,8 +2891,10 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
*filpp = dp->dl_vfs_file;
} else { /* open or lock stateid */
stp = find_stateid(stateid, flags);
- if (!stp)
+ if (!stp) {
+ status = stateid_error_map(stateid);
goto out;
+ }
if (nfs4_check_fh(current_fh, stp))
goto out;
if (!stp->st_stateowner->so_confirmed)
@@ -2957,7 +2968,7 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
*/
sop = search_close_lru(stateid->si_stateownerid, flags);
if (sop == NULL)
- return nfserr_bad_stateid;
+ return stateid_error_map(stateid);
*sopp = sop;
goto check_replay;
}
@@ -3228,8 +3239,10 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
if (!is_delegation_stateid(stateid))
goto out;
dp = find_delegation_stateid(inode, stateid);
- if (!dp)
+ if (!dp) {
+ status = stateid_error_map(stateid);
goto out;
+ }
status = check_stateid_generation(stateid, &dp->dl_stateid, flags);
if (status)
goto out;
@@ -3456,7 +3469,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
stp->st_stateowner = sop;
get_nfs4_file(fp);
stp->st_file = fp;
- stp->st_stateid.si_boot = boot_time;
+ stp->st_stateid.si_boot = get_seconds();
stp->st_stateid.si_stateownerid = sop->so_id;
stp->st_stateid.si_fileid = fp->fi_id;
stp->st_stateid.si_generation = 0;
@@ -3988,6 +4001,7 @@ nfs4_state_init(void)
INIT_LIST_HEAD(&conf_str_hashtbl[i]);
INIT_LIST_HEAD(&unconf_str_hashtbl[i]);
INIT_LIST_HEAD(&unconf_id_hashtbl[i]);
+ INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
}
for (i = 0; i < SESSION_HASH_SIZE; i++)
INIT_LIST_HEAD(&sessionid_hashtbl[i]);
@@ -4010,8 +4024,6 @@ nfs4_state_init(void)
INIT_LIST_HEAD(&close_lru);
INIT_LIST_HEAD(&client_lru);
INIT_LIST_HEAD(&del_recall_lru);
- for (i = 0; i < CLIENT_HASH_SIZE; i++)
- INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
reclaim_str_hashtbl_size = 0;
return 0;
}
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index b820c311931c..fefb993654bb 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -83,16 +83,6 @@ check_filename(char *str, int len, __be32 err)
return 0;
}
-/*
- * START OF "GENERIC" DECODE ROUTINES.
- * These may look a little ugly since they are imported from a "generic"
- * set of XDR encode/decode routines which are intended to be shared by
- * all of our NFSv4 implementations (OpenBSD, MacOS X...).
- *
- * If the pain of reading these is too great, it should be a straightforward
- * task to translate them into Linux-specific versions which are more
- * consistent with the style used in NFSv2/v3...
- */
#define DECODE_HEAD \
__be32 *p; \
__be32 status
@@ -1328,64 +1318,64 @@ static nfsd4_dec nfsd4_dec_ops[] = {
};
static nfsd4_dec nfsd41_dec_ops[] = {
- [OP_ACCESS] (nfsd4_dec)nfsd4_decode_access,
- [OP_CLOSE] (nfsd4_dec)nfsd4_decode_close,
- [OP_COMMIT] (nfsd4_dec)nfsd4_decode_commit,
- [OP_CREATE] (nfsd4_dec)nfsd4_decode_create,
- [OP_DELEGPURGE] (nfsd4_dec)nfsd4_decode_notsupp,
- [OP_DELEGRETURN] (nfsd4_dec)nfsd4_decode_delegreturn,
- [OP_GETATTR] (nfsd4_dec)nfsd4_decode_getattr,
- [OP_GETFH] (nfsd4_dec)nfsd4_decode_noop,
- [OP_LINK] (nfsd4_dec)nfsd4_decode_link,
- [OP_LOCK] (nfsd4_dec)nfsd4_decode_lock,
- [OP_LOCKT] (nfsd4_dec)nfsd4_decode_lockt,
- [OP_LOCKU] (nfsd4_dec)nfsd4_decode_locku,
- [OP_LOOKUP] (nfsd4_dec)nfsd4_decode_lookup,
- [OP_LOOKUPP] (nfsd4_dec)nfsd4_decode_noop,
- [OP_NVERIFY] (nfsd4_dec)nfsd4_decode_verify,
- [OP_OPEN] (nfsd4_dec)nfsd4_decode_open,
- [OP_OPENATTR] (nfsd4_dec)nfsd4_decode_notsupp,
- [OP_OPEN_CONFIRM] (nfsd4_dec)nfsd4_decode_notsupp,
- [OP_OPEN_DOWNGRADE] (nfsd4_dec)nfsd4_decode_open_downgrade,
- [OP_PUTFH] (nfsd4_dec)nfsd4_decode_putfh,
- [OP_PUTPUBFH] (nfsd4_dec)nfsd4_decode_notsupp,
- [OP_PUTROOTFH] (nfsd4_dec)nfsd4_decode_noop,
- [OP_READ] (nfsd4_dec)nfsd4_decode_read,
- [OP_READDIR] (nfsd4_dec)nfsd4_decode_readdir,
- [OP_READLINK] (nfsd4_dec)nfsd4_decode_noop,
- [OP_REMOVE] (nfsd4_dec)nfsd4_decode_remove,
- [OP_RENAME] (nfsd4_dec)nfsd4_decode_rename,
- [OP_RENEW] (nfsd4_dec)nfsd4_decode_notsupp,
- [OP_RESTOREFH] (nfsd4_dec)nfsd4_decode_noop,
- [OP_SAVEFH] (nfsd4_dec)nfsd4_decode_noop,
- [OP_SECINFO] (nfsd4_dec)nfsd4_decode_secinfo,
- [OP_SETATTR] (nfsd4_dec)nfsd4_decode_setattr,
- [OP_SETCLIENTID] (nfsd4_dec)nfsd4_decode_notsupp,
- [OP_SETCLIENTID_CONFIRM](nfsd4_dec)nfsd4_decode_notsupp,
- [OP_VERIFY] (nfsd4_dec)nfsd4_decode_verify,
- [OP_WRITE] (nfsd4_dec)nfsd4_decode_write,
- [OP_RELEASE_LOCKOWNER] (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_ACCESS] = (nfsd4_dec)nfsd4_decode_access,
+ [OP_CLOSE] = (nfsd4_dec)nfsd4_decode_close,
+ [OP_COMMIT] = (nfsd4_dec)nfsd4_decode_commit,
+ [OP_CREATE] = (nfsd4_dec)nfsd4_decode_create,
+ [OP_DELEGPURGE] = (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_DELEGRETURN] = (nfsd4_dec)nfsd4_decode_delegreturn,
+ [OP_GETATTR] = (nfsd4_dec)nfsd4_decode_getattr,
+ [OP_GETFH] = (nfsd4_dec)nfsd4_decode_noop,
+ [OP_LINK] = (nfsd4_dec)nfsd4_decode_link,
+ [OP_LOCK] = (nfsd4_dec)nfsd4_decode_lock,
+ [OP_LOCKT] = (nfsd4_dec)nfsd4_decode_lockt,
+ [OP_LOCKU] = (nfsd4_dec)nfsd4_decode_locku,
+ [OP_LOOKUP] = (nfsd4_dec)nfsd4_decode_lookup,
+ [OP_LOOKUPP] = (nfsd4_dec)nfsd4_decode_noop,
+ [OP_NVERIFY] = (nfsd4_dec)nfsd4_decode_verify,
+ [OP_OPEN] = (nfsd4_dec)nfsd4_decode_open,
+ [OP_OPENATTR] = (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_OPEN_CONFIRM] = (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_OPEN_DOWNGRADE] = (nfsd4_dec)nfsd4_decode_open_downgrade,
+ [OP_PUTFH] = (nfsd4_dec)nfsd4_decode_putfh,
+ [OP_PUTPUBFH] = (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_PUTROOTFH] = (nfsd4_dec)nfsd4_decode_noop,
+ [OP_READ] = (nfsd4_dec)nfsd4_decode_read,
+ [OP_READDIR] = (nfsd4_dec)nfsd4_decode_readdir,
+ [OP_READLINK] = (nfsd4_dec)nfsd4_decode_noop,
+ [OP_REMOVE] = (nfsd4_dec)nfsd4_decode_remove,
+ [OP_RENAME] = (nfsd4_dec)nfsd4_decode_rename,
+ [OP_RENEW] = (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_RESTOREFH] = (nfsd4_dec)nfsd4_decode_noop,
+ [OP_SAVEFH] = (nfsd4_dec)nfsd4_decode_noop,
+ [OP_SECINFO] = (nfsd4_dec)nfsd4_decode_secinfo,
+ [OP_SETATTR] = (nfsd4_dec)nfsd4_decode_setattr,
+ [OP_SETCLIENTID] = (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_SETCLIENTID_CONFIRM]= (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_VERIFY] = (nfsd4_dec)nfsd4_decode_verify,
+ [OP_WRITE] = (nfsd4_dec)nfsd4_decode_write,
+ [OP_RELEASE_LOCKOWNER] = (nfsd4_dec)nfsd4_decode_notsupp,
/* new operations for NFSv4.1 */
- [OP_BACKCHANNEL_CTL] (nfsd4_dec)nfsd4_decode_notsupp,
- [OP_BIND_CONN_TO_SESSION](nfsd4_dec)nfsd4_decode_notsupp,
- [OP_EXCHANGE_ID] (nfsd4_dec)nfsd4_decode_exchange_id,
- [OP_CREATE_SESSION] (nfsd4_dec)nfsd4_decode_create_session,
- [OP_DESTROY_SESSION] (nfsd4_dec)nfsd4_decode_destroy_session,
- [OP_FREE_STATEID] (nfsd4_dec)nfsd4_decode_notsupp,
- [OP_GET_DIR_DELEGATION] (nfsd4_dec)nfsd4_decode_notsupp,
- [OP_GETDEVICEINFO] (nfsd4_dec)nfsd4_decode_notsupp,
- [OP_GETDEVICELIST] (nfsd4_dec)nfsd4_decode_notsupp,
- [OP_LAYOUTCOMMIT] (nfsd4_dec)nfsd4_decode_notsupp,
- [OP_LAYOUTGET] (nfsd4_dec)nfsd4_decode_notsupp,
- [OP_LAYOUTRETURN] (nfsd4_dec)nfsd4_decode_notsupp,
- [OP_SECINFO_NO_NAME] (nfsd4_dec)nfsd4_decode_notsupp,
- [OP_SEQUENCE] (nfsd4_dec)nfsd4_decode_sequence,
- [OP_SET_SSV] (nfsd4_dec)nfsd4_decode_notsupp,
- [OP_TEST_STATEID] (nfsd4_dec)nfsd4_decode_notsupp,
- [OP_WANT_DELEGATION] (nfsd4_dec)nfsd4_decode_notsupp,
- [OP_DESTROY_CLIENTID] (nfsd4_dec)nfsd4_decode_notsupp,
- [OP_RECLAIM_COMPLETE] (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_BACKCHANNEL_CTL] = (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_BIND_CONN_TO_SESSION]= (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_EXCHANGE_ID] = (nfsd4_dec)nfsd4_decode_exchange_id,
+ [OP_CREATE_SESSION] = (nfsd4_dec)nfsd4_decode_create_session,
+ [OP_DESTROY_SESSION] = (nfsd4_dec)nfsd4_decode_destroy_session,
+ [OP_FREE_STATEID] = (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_GET_DIR_DELEGATION] = (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_GETDEVICEINFO] = (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_GETDEVICELIST] = (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_LAYOUTCOMMIT] = (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_LAYOUTGET] = (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_LAYOUTRETURN] = (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_SECINFO_NO_NAME] = (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_SEQUENCE] = (nfsd4_dec)nfsd4_decode_sequence,
+ [OP_SET_SSV] = (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_TEST_STATEID] = (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_WANT_DELEGATION] = (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_DESTROY_CLIENTID] = (nfsd4_dec)nfsd4_decode_notsupp,
+ [OP_RECLAIM_COMPLETE] = (nfsd4_dec)nfsd4_decode_notsupp,
};
struct nfsd4_minorversion_ops {
@@ -1489,21 +1479,6 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
DECODE_TAIL;
}
-/*
- * END OF "GENERIC" DECODE ROUTINES.
- */
-
-/*
- * START OF "GENERIC" ENCODE ROUTINES.
- * These may look a little ugly since they are imported from a "generic"
- * set of XDR encode/decode routines which are intended to be shared by
- * all of our NFSv4 implementations (OpenBSD, MacOS X...).
- *
- * If the pain of reading these is too great, it should be a straightforward
- * task to translate them into Linux-specific versions which are more
- * consistent with the style used in NFSv2/v3...
- */
-#define ENCODE_HEAD __be32 *p
#define WRITE32(n) *p++ = htonl(n)
#define WRITE64(n) do { \
@@ -1515,13 +1490,41 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
memcpy(p, ptr, nbytes); \
p += XDR_QUADLEN(nbytes); \
}} while (0)
-#define WRITECINFO(c) do { \
- *p++ = htonl(c.atomic); \
- *p++ = htonl(c.before_ctime_sec); \
- *p++ = htonl(c.before_ctime_nsec); \
- *p++ = htonl(c.after_ctime_sec); \
- *p++ = htonl(c.after_ctime_nsec); \
-} while (0)
+
+static void write32(__be32 **p, u32 n)
+{
+ *(*p)++ = n;
+}
+
+static void write64(__be32 **p, u64 n)
+{
+ write32(p, (u32)(n >> 32));
+ write32(p, (u32)n);
+}
+
+static void write_change(__be32 **p, struct kstat *stat, struct inode *inode)
+{
+ if (IS_I_VERSION(inode)) {
+ write64(p, inode->i_version);
+ } else {
+ write32(p, stat->ctime.tv_sec);
+ write32(p, stat->ctime.tv_nsec);
+ }
+}
+
+static void write_cinfo(__be32 **p, struct nfsd4_change_info *c)
+{
+ write32(p, c->atomic);
+ if (c->change_supported) {
+ write64(p, c->before_change);
+ write64(p, c->after_change);
+ } else {
+ write32(p, c->before_ctime_sec);
+ write32(p, c->before_ctime_nsec);
+ write32(p, c->after_ctime_sec);
+ write32(p, c->after_ctime_nsec);
+ }
+}
#define RESERVE_SPACE(nbytes) do { \
p = resp->p; \
@@ -1874,16 +1877,9 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
WRITE32(NFS4_FH_PERSISTENT|NFS4_FH_VOL_RENAME);
}
if (bmval0 & FATTR4_WORD0_CHANGE) {
- /*
- * Note: This _must_ be consistent with the scheme for writing
- * change_info, so any changes made here must be reflected there
- * as well. (See xdr4.h:set_change_info() and the WRITECINFO()
- * macro above.)
- */
if ((buflen -= 8) < 0)
goto out_resource;
- WRITE32(stat.ctime.tv_sec);
- WRITE32(stat.ctime.tv_nsec);
+ write_change(&p, &stat, dentry->d_inode);
}
if (bmval0 & FATTR4_WORD0_SIZE) {
if ((buflen -= 8) < 0)
@@ -2214,6 +2210,15 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen);
if (IS_ERR(dentry))
return nfserrno(PTR_ERR(dentry));
+ if (!dentry->d_inode) {
+ /*
+ * nfsd_buffered_readdir drops the i_mutex between
+ * readdir and calling this callback, leaving a window
+ * where this directory entry could have gone away.
+ */
+ dput(dentry);
+ return nfserr_noent;
+ }
exp_get(exp);
/*
@@ -2276,6 +2281,7 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common);
int buflen;
__be32 *p = cd->buffer;
+ __be32 *cookiep;
__be32 nfserr = nfserr_toosmall;
/* In nfsv4, "." and ".." never make it onto the wire.. */
@@ -2292,7 +2298,7 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
goto fail;
*p++ = xdr_one; /* mark entry present */
- cd->offset = p; /* remember pointer */
+ cookiep = p;
p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */
p = xdr_encode_array(p, name, namlen); /* name length & name */
@@ -2306,6 +2312,8 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
goto fail;
case nfserr_dropit:
goto fail;
+ case nfserr_noent:
+ goto skip_entry;
default:
/*
* If the client requested the RDATTR_ERROR attribute,
@@ -2324,6 +2332,8 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
}
cd->buflen -= (p - cd->buffer);
cd->buffer = p;
+ cd->offset = cookiep;
+skip_entry:
cd->common.err = nfs_ok;
return 0;
fail:
@@ -2334,7 +2344,7 @@ fail:
static void
nfsd4_encode_stateid(struct nfsd4_compoundres *resp, stateid_t *sid)
{
- ENCODE_HEAD;
+ __be32 *p;
RESERVE_SPACE(sizeof(stateid_t));
WRITE32(sid->si_generation);
@@ -2345,7 +2355,7 @@ nfsd4_encode_stateid(struct nfsd4_compoundres *resp, stateid_t *sid)
static __be32
nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_access *access)
{
- ENCODE_HEAD;
+ __be32 *p;
if (!nfserr) {
RESERVE_SPACE(8);
@@ -2372,7 +2382,7 @@ nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_c
static __be32
nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_commit *commit)
{
- ENCODE_HEAD;
+ __be32 *p;
if (!nfserr) {
RESERVE_SPACE(8);
@@ -2385,11 +2395,11 @@ nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
static __be32
nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_create *create)
{
- ENCODE_HEAD;
+ __be32 *p;
if (!nfserr) {
RESERVE_SPACE(32);
- WRITECINFO(create->cr_cinfo);
+ write_cinfo(&p, &create->cr_cinfo);
WRITE32(2);
WRITE32(create->cr_bmval[0]);
WRITE32(create->cr_bmval[1]);
@@ -2421,7 +2431,7 @@ nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh
{
struct svc_fh *fhp = *fhpp;
unsigned int len;
- ENCODE_HEAD;
+ __be32 *p;
if (!nfserr) {
len = fhp->fh_handle.fh_size;
@@ -2440,7 +2450,7 @@ nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh
static void
nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denied *ld)
{
- ENCODE_HEAD;
+ __be32 *p;
RESERVE_SPACE(32 + XDR_LEN(ld->ld_sop ? ld->ld_sop->so_owner.len : 0));
WRITE64(ld->ld_start);
@@ -2496,11 +2506,11 @@ nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_l
static __be32
nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_link *link)
{
- ENCODE_HEAD;
+ __be32 *p;
if (!nfserr) {
RESERVE_SPACE(20);
- WRITECINFO(link->li_cinfo);
+ write_cinfo(&p, &link->li_cinfo);
ADJUST_ARGS();
}
return nfserr;
@@ -2510,7 +2520,7 @@ nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_li
static __be32
nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open)
{
- ENCODE_HEAD;
+ __be32 *p;
ENCODE_SEQID_OP_HEAD;
if (nfserr)
@@ -2518,7 +2528,7 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op
nfsd4_encode_stateid(resp, &open->op_stateid);
RESERVE_SPACE(40);
- WRITECINFO(open->op_cinfo);
+ write_cinfo(&p, &open->op_cinfo);
WRITE32(open->op_rflags);
WRITE32(2);
WRITE32(open->op_bmval[0]);
@@ -2605,7 +2615,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
int v, pn;
unsigned long maxcount;
long len;
- ENCODE_HEAD;
+ __be32 *p;
if (nfserr)
return nfserr;
@@ -2667,7 +2677,7 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd
{
int maxcount;
char *page;
- ENCODE_HEAD;
+ __be32 *p;
if (nfserr)
return nfserr;
@@ -2716,7 +2726,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
int maxcount;
loff_t offset;
__be32 *page, *savep, *tailbase;
- ENCODE_HEAD;
+ __be32 *p;
if (nfserr)
return nfserr;
@@ -2792,11 +2802,11 @@ err_no_verf:
static __be32
nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_remove *remove)
{
- ENCODE_HEAD;
+ __be32 *p;
if (!nfserr) {
RESERVE_SPACE(20);
- WRITECINFO(remove->rm_cinfo);
+ write_cinfo(&p, &remove->rm_cinfo);
ADJUST_ARGS();
}
return nfserr;
@@ -2805,12 +2815,12 @@ nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
static __be32
nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_rename *rename)
{
- ENCODE_HEAD;
+ __be32 *p;
if (!nfserr) {
RESERVE_SPACE(40);
- WRITECINFO(rename->rn_sinfo);
- WRITECINFO(rename->rn_tinfo);
+ write_cinfo(&p, &rename->rn_sinfo);
+ write_cinfo(&p, &rename->rn_tinfo);
ADJUST_ARGS();
}
return nfserr;
@@ -2825,7 +2835,7 @@ nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
u32 nflavs;
struct exp_flavor_info *flavs;
struct exp_flavor_info def_flavs[2];
- ENCODE_HEAD;
+ __be32 *p;
if (nfserr)
goto out;
@@ -2890,7 +2900,7 @@ out:
static __be32
nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setattr *setattr)
{
- ENCODE_HEAD;
+ __be32 *p;
RESERVE_SPACE(12);
if (nfserr) {
@@ -2910,7 +2920,7 @@ nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
static __be32
nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setclientid *scd)
{
- ENCODE_HEAD;
+ __be32 *p;
if (!nfserr) {
RESERVE_SPACE(8 + sizeof(nfs4_verifier));
@@ -2930,7 +2940,7 @@ nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct n
static __be32
nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_write *write)
{
- ENCODE_HEAD;
+ __be32 *p;
if (!nfserr) {
RESERVE_SPACE(16);
@@ -2946,7 +2956,7 @@ static __be32
nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, int nfserr,
struct nfsd4_exchange_id *exid)
{
- ENCODE_HEAD;
+ __be32 *p;
char *major_id;
char *server_scope;
int major_id_sz;
@@ -3001,7 +3011,7 @@ static __be32
nfsd4_encode_create_session(struct nfsd4_compoundres *resp, int nfserr,
struct nfsd4_create_session *sess)
{
- ENCODE_HEAD;
+ __be32 *p;
if (nfserr)
return nfserr;
@@ -3057,7 +3067,7 @@ __be32
nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr,
struct nfsd4_sequence *seq)
{
- ENCODE_HEAD;
+ __be32 *p;
if (nfserr)
return nfserr;
@@ -3205,7 +3215,7 @@ void
nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
{
__be32 *statp;
- ENCODE_HEAD;
+ __be32 *p;
RESERVE_SPACE(8);
WRITE32(op->opnum);
@@ -3239,7 +3249,7 @@ status:
void
nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
{
- ENCODE_HEAD;
+ __be32 *p;
struct nfs4_replay *rp = op->replay;
BUG_ON(!rp);
@@ -3254,10 +3264,6 @@ nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
ADJUST_ARGS();
}
-/*
- * END OF "GENERIC" ENCODE ROUTINES.
- */
-
int
nfs4svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
{
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index af16849d243a..877e713a0fd6 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -695,8 +695,9 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
if (rv)
return rv;
}
- sprintf(buf, "%d\n", nfsd_nrthreads());
- return strlen(buf);
+
+ return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n",
+ nfsd_nrthreads());
}
/**
@@ -793,7 +794,7 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
{
char *mesg = buf;
char *vers, *minorp, sign;
- int len, num;
+ int len, num, remaining;
unsigned minor;
ssize_t tlen = 0;
char *sep;
@@ -840,32 +841,50 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
}
next:
vers += len + 1;
- tlen += len;
} while ((len = qword_get(&mesg, vers, size)) > 0);
/* If all get turned off, turn them back on, as
* having no versions is BAD
*/
nfsd_reset_versions();
}
+
/* Now write current state into reply buffer */
len = 0;
sep = "";
+ remaining = SIMPLE_TRANSACTION_LIMIT;
for (num=2 ; num <= 4 ; num++)
if (nfsd_vers(num, NFSD_AVAIL)) {
- len += sprintf(buf+len, "%s%c%d", sep,
+ len = snprintf(buf, remaining, "%s%c%d", sep,
nfsd_vers(num, NFSD_TEST)?'+':'-',
num);
sep = " ";
+
+ if (len > remaining)
+ break;
+ remaining -= len;
+ buf += len;
+ tlen += len;
}
if (nfsd_vers(4, NFSD_AVAIL))
- for (minor = 1; minor <= NFSD_SUPPORTED_MINOR_VERSION; minor++)
- len += sprintf(buf+len, " %c4.%u",
+ for (minor = 1; minor <= NFSD_SUPPORTED_MINOR_VERSION;
+ minor++) {
+ len = snprintf(buf, remaining, " %c4.%u",
(nfsd_vers(4, NFSD_TEST) &&
nfsd_minorversion(minor, NFSD_TEST)) ?
'+' : '-',
minor);
- len += sprintf(buf+len, "\n");
- return len;
+
+ if (len > remaining)
+ break;
+ remaining -= len;
+ buf += len;
+ tlen += len;
+ }
+
+ len = snprintf(buf, remaining, "\n");
+ if (len > remaining)
+ return -EINVAL;
+ return tlen + len;
}
/**
@@ -910,104 +929,143 @@ static ssize_t write_versions(struct file *file, char *buf, size_t size)
return rv;
}
-static ssize_t __write_ports(struct file *file, char *buf, size_t size)
+/*
+ * Zero-length write. Return a list of NFSD's current listener
+ * transports.
+ */
+static ssize_t __write_ports_names(char *buf)
{
- if (size == 0) {
- int len = 0;
+ if (nfsd_serv == NULL)
+ return 0;
+ return svc_xprt_names(nfsd_serv, buf, SIMPLE_TRANSACTION_LIMIT);
+}
- if (nfsd_serv)
- len = svc_xprt_names(nfsd_serv, buf, 0);
- return len;
- }
- /* Either a single 'fd' number is written, in which
- * case it must be for a socket of a supported family/protocol,
- * and we use it as an nfsd socket, or
- * A '-' followed by the 'name' of a socket in which case
- * we close the socket.
- */
- if (isdigit(buf[0])) {
- char *mesg = buf;
- int fd;
- int err;
- err = get_int(&mesg, &fd);
- if (err)
- return -EINVAL;
- if (fd < 0)
- return -EINVAL;
- err = nfsd_create_serv();
- if (!err) {
- err = svc_addsock(nfsd_serv, fd, buf);
- if (err >= 0) {
- err = lockd_up();
- if (err < 0)
- svc_sock_names(buf+strlen(buf)+1, nfsd_serv, buf);
- }
- /* Decrease the count, but don't shutdown the
- * the service
- */
- nfsd_serv->sv_nrthreads--;
- }
- return err < 0 ? err : 0;
- }
- if (buf[0] == '-' && isdigit(buf[1])) {
- char *toclose = kstrdup(buf+1, GFP_KERNEL);
- int len = 0;
- if (!toclose)
- return -ENOMEM;
- if (nfsd_serv)
- len = svc_sock_names(buf, nfsd_serv, toclose);
- if (len >= 0)
- lockd_down();
- kfree(toclose);
- return len;
- }
- /*
- * Add a transport listener by writing it's transport name
- */
- if (isalpha(buf[0])) {
- int err;
- char transport[16];
- int port;
- if (sscanf(buf, "%15s %4d", transport, &port) == 2) {
- if (port < 1 || port > 65535)
- return -EINVAL;
- err = nfsd_create_serv();
- if (!err) {
- err = svc_create_xprt(nfsd_serv,
- transport, PF_INET, port,
- SVC_SOCK_ANONYMOUS);
- if (err == -ENOENT)
- /* Give a reasonable perror msg for
- * bad transport string */
- err = -EPROTONOSUPPORT;
- }
- return err < 0 ? err : 0;
- }
- }
- /*
- * Remove a transport by writing it's transport name and port number
- */
- if (buf[0] == '-' && isalpha(buf[1])) {
- struct svc_xprt *xprt;
- int err = -EINVAL;
- char transport[16];
- int port;
- if (sscanf(&buf[1], "%15s %4d", transport, &port) == 2) {
- if (port < 1 || port > 65535)
- return -EINVAL;
- if (nfsd_serv) {
- xprt = svc_find_xprt(nfsd_serv, transport,
- AF_UNSPEC, port);
- if (xprt) {
- svc_close_xprt(xprt);
- svc_xprt_put(xprt);
- err = 0;
- } else
- err = -ENOTCONN;
- }
- return err < 0 ? err : 0;
- }
+/*
+ * A single 'fd' number was written, in which case it must be for
+ * a socket of a supported family/protocol, and we use it as an
+ * nfsd listener.
+ */
+static ssize_t __write_ports_addfd(char *buf)
+{
+ char *mesg = buf;
+ int fd, err;
+
+ err = get_int(&mesg, &fd);
+ if (err != 0 || fd < 0)
+ return -EINVAL;
+
+ err = nfsd_create_serv();
+ if (err != 0)
+ return err;
+
+ err = lockd_up();
+ if (err != 0)
+ goto out;
+
+ err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT);
+ if (err < 0)
+ lockd_down();
+
+out:
+ /* Decrease the count, but don't shut down the service */
+ nfsd_serv->sv_nrthreads--;
+ return err;
+}
+
+/*
+ * A '-' followed by the 'name' of a socket means we close the socket.
+ */
+static ssize_t __write_ports_delfd(char *buf)
+{
+ char *toclose;
+ int len = 0;
+
+ toclose = kstrdup(buf + 1, GFP_KERNEL);
+ if (toclose == NULL)
+ return -ENOMEM;
+
+ if (nfsd_serv != NULL)
+ len = svc_sock_names(nfsd_serv, buf,
+ SIMPLE_TRANSACTION_LIMIT, toclose);
+ if (len >= 0)
+ lockd_down();
+
+ kfree(toclose);
+ return len;
+}
+
+/*
+ * A transport listener is added by writing it's transport name and
+ * a port number.
+ */
+static ssize_t __write_ports_addxprt(char *buf)
+{
+ char transport[16];
+ int port, err;
+
+ if (sscanf(buf, "%15s %4u", transport, &port) != 2)
+ return -EINVAL;
+
+ if (port < 1 || port > USHORT_MAX)
+ return -EINVAL;
+
+ err = nfsd_create_serv();
+ if (err != 0)
+ return err;
+
+ err = svc_create_xprt(nfsd_serv, transport,
+ PF_INET, port, SVC_SOCK_ANONYMOUS);
+ if (err < 0) {
+ /* Give a reasonable perror msg for bad transport string */
+ if (err == -ENOENT)
+ err = -EPROTONOSUPPORT;
+ return err;
}
+ return 0;
+}
+
+/*
+ * A transport listener is removed by writing a "-", it's transport
+ * name, and it's port number.
+ */
+static ssize_t __write_ports_delxprt(char *buf)
+{
+ struct svc_xprt *xprt;
+ char transport[16];
+ int port;
+
+ if (sscanf(&buf[1], "%15s %4u", transport, &port) != 2)
+ return -EINVAL;
+
+ if (port < 1 || port > USHORT_MAX || nfsd_serv == NULL)
+ return -EINVAL;
+
+ xprt = svc_find_xprt(nfsd_serv, transport, AF_UNSPEC, port);
+ if (xprt == NULL)
+ return -ENOTCONN;
+
+ svc_close_xprt(xprt);
+ svc_xprt_put(xprt);
+ return 0;
+}
+
+static ssize_t __write_ports(struct file *file, char *buf, size_t size)
+{
+ if (size == 0)
+ return __write_ports_names(buf);
+
+ if (isdigit(buf[0]))
+ return __write_ports_addfd(buf);
+
+ if (buf[0] == '-' && isdigit(buf[1]))
+ return __write_ports_delfd(buf);
+
+ if (isalpha(buf[0]))
+ return __write_ports_addxprt(buf);
+
+ if (buf[0] == '-' && isalpha(buf[1]))
+ return __write_ports_delxprt(buf);
+
return -EINVAL;
}
@@ -1030,7 +1088,9 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size)
* buf: C string containing an unsigned
* integer value representing a bound
* but unconnected socket that is to be
- * used as an NFSD listener
+ * used as an NFSD listener; listen(3)
+ * must be called for a SOCK_STREAM
+ * socket, otherwise it is ignored
* size: non-zero length of C string in @buf
* Output:
* On success: NFS service is started;
@@ -1138,7 +1198,9 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
nfsd_max_blksize = bsize;
mutex_unlock(&nfsd_mutex);
}
- return sprintf(buf, "%d\n", nfsd_max_blksize);
+
+ return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n",
+ nfsd_max_blksize);
}
#ifdef CONFIG_NFSD_V4
@@ -1162,8 +1224,9 @@ static ssize_t __write_leasetime(struct file *file, char *buf, size_t size)
return -EINVAL;
nfs4_reset_lease(lease);
}
- sprintf(buf, "%ld\n", nfs4_lease_time());
- return strlen(buf);
+
+ return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%ld\n",
+ nfs4_lease_time());
}
/**
@@ -1219,8 +1282,9 @@ static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
status = nfs4_reset_recoverydir(recdir);
}
- sprintf(buf, "%s\n", nfs4_recoverydir());
- return strlen(buf);
+
+ return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%s\n",
+ nfs4_recoverydir());
}
/**
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index ab93fcfef254..6ef2b1dd3a2a 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -100,31 +100,35 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
{
struct svc_export *exp = *expp, *exp2 = NULL;
struct dentry *dentry = *dpp;
- struct vfsmount *mnt = mntget(exp->ex_path.mnt);
- struct dentry *mounts = dget(dentry);
+ struct path path = {.mnt = mntget(exp->ex_path.mnt),
+ .dentry = dget(dentry)};
int err = 0;
- while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts));
+ while (d_mountpoint(path.dentry) && follow_down(&path))
+ ;
- exp2 = rqst_exp_get_by_name(rqstp, mnt, mounts);
+ exp2 = rqst_exp_get_by_name(rqstp, &path);
if (IS_ERR(exp2)) {
if (PTR_ERR(exp2) != -ENOENT)
err = PTR_ERR(exp2);
- dput(mounts);
- mntput(mnt);
+ path_put(&path);
goto out;
}
if ((exp->ex_flags & NFSEXP_CROSSMOUNT) || EX_NOHIDE(exp2)) {
/* successfully crossed mount point */
- exp_put(exp);
+ /*
+ * This is subtle: path.dentry is *not* on path.mnt
+ * at this point. The only reason we are safe is that
+ * original mnt is pinned down by exp, so we should
+ * put path *before* putting exp
+ */
+ *dpp = path.dentry;
+ path.dentry = dentry;
*expp = exp2;
- dput(dentry);
- *dpp = mounts;
- } else {
- exp_put(exp2);
- dput(mounts);
+ exp2 = exp;
}
- mntput(mnt);
+ path_put(&path);
+ exp_put(exp2);
out:
return err;
}
@@ -163,28 +167,29 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
/* checking mountpoint crossing is very different when stepping up */
struct svc_export *exp2 = NULL;
struct dentry *dp;
- struct vfsmount *mnt = mntget(exp->ex_path.mnt);
- dentry = dget(dparent);
- while(dentry == mnt->mnt_root && follow_up(&mnt, &dentry))
+ struct path path = {.mnt = mntget(exp->ex_path.mnt),
+ .dentry = dget(dparent)};
+
+ while (path.dentry == path.mnt->mnt_root &&
+ follow_up(&path))
;
- dp = dget_parent(dentry);
- dput(dentry);
- dentry = dp;
+ dp = dget_parent(path.dentry);
+ dput(path.dentry);
+ path.dentry = dp;
- exp2 = rqst_exp_parent(rqstp, mnt, dentry);
+ exp2 = rqst_exp_parent(rqstp, &path);
if (PTR_ERR(exp2) == -ENOENT) {
- dput(dentry);
dentry = dget(dparent);
} else if (IS_ERR(exp2)) {
host_err = PTR_ERR(exp2);
- dput(dentry);
- mntput(mnt);
+ path_put(&path);
goto out_nfserr;
} else {
+ dentry = dget(path.dentry);
exp_put(exp);
exp = exp2;
}
- mntput(mnt);
+ path_put(&path);
}
} else {
fh_lock(fhp);
@@ -1885,8 +1890,8 @@ static int nfsd_buffered_filldir(void *__buf, const char *name, int namlen,
return 0;
}
-static int nfsd_buffered_readdir(struct file *file, filldir_t func,
- struct readdir_cd *cdp, loff_t *offsetp)
+static __be32 nfsd_buffered_readdir(struct file *file, filldir_t func,
+ struct readdir_cd *cdp, loff_t *offsetp)
{
struct readdir_data buf;
struct buffered_dirent *de;
@@ -1896,11 +1901,12 @@ static int nfsd_buffered_readdir(struct file *file, filldir_t func,
buf.dirent = (void *)__get_free_page(GFP_KERNEL);
if (!buf.dirent)
- return -ENOMEM;
+ return nfserrno(-ENOMEM);
offset = *offsetp;
while (1) {
+ struct inode *dir_inode = file->f_path.dentry->d_inode;
unsigned int reclen;
cdp->err = nfserr_eof; /* will be cleared on successful read */
@@ -1919,26 +1925,38 @@ static int nfsd_buffered_readdir(struct file *file, filldir_t func,
if (!size)
break;
+ /*
+ * Various filldir functions may end up calling back into
+ * lookup_one_len() and the file system's ->lookup() method.
+ * These expect i_mutex to be held, as it would within readdir.
+ */
+ host_err = mutex_lock_killable(&dir_inode->i_mutex);
+ if (host_err)
+ break;
+
de = (struct buffered_dirent *)buf.dirent;
while (size > 0) {
offset = de->offset;
if (func(cdp, de->name, de->namlen, de->offset,
de->ino, de->d_type))
- goto done;
+ break;
if (cdp->err != nfs_ok)
- goto done;
+ break;
reclen = ALIGN(sizeof(*de) + de->namlen,
sizeof(u64));
size -= reclen;
de = (struct buffered_dirent *)((char *)de + reclen);
}
+ mutex_unlock(&dir_inode->i_mutex);
+ if (size > 0) /* We bailed out early */
+ break;
+
offset = vfs_llseek(file, 0, SEEK_CUR);
}
- done:
free_page((unsigned long)(buf.dirent));
if (host_err)
diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c
index 24638e059bf3..064279e33bbb 100644
--- a/fs/nilfs2/bmap.c
+++ b/fs/nilfs2/bmap.c
@@ -688,6 +688,8 @@ static const struct nilfs_bmap_ptr_operations nilfs_bmap_ptr_ops_gc = {
.bpop_translate = NULL,
};
+static struct lock_class_key nilfs_bmap_dat_lock_key;
+
/**
* nilfs_bmap_read - read a bmap from an inode
* @bmap: bmap
@@ -715,6 +717,7 @@ int nilfs_bmap_read(struct nilfs_bmap *bmap, struct nilfs_inode *raw_inode)
bmap->b_pops = &nilfs_bmap_ptr_ops_p;
bmap->b_last_allocated_key = 0; /* XXX: use macro */
bmap->b_last_allocated_ptr = NILFS_BMAP_NEW_PTR_INIT;
+ lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key);
break;
case NILFS_CPFILE_INO:
case NILFS_SUFILE_INO:
@@ -772,6 +775,7 @@ void nilfs_bmap_init_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap)
{
memcpy(gcbmap, bmap, sizeof(union nilfs_bmap_union));
init_rwsem(&gcbmap->b_sem);
+ lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key);
gcbmap->b_inode = &NILFS_BMAP_I(gcbmap)->vfs_inode;
}
@@ -779,5 +783,6 @@ void nilfs_bmap_commit_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap)
{
memcpy(bmap, gcbmap, sizeof(union nilfs_bmap_union));
init_rwsem(&bmap->b_sem);
+ lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key);
bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode;
}
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
index 108d281ebca5..50ff3f2cdf24 100644
--- a/fs/nilfs2/ioctl.c
+++ b/fs/nilfs2/ioctl.c
@@ -25,6 +25,7 @@
#include <linux/smp_lock.h> /* lock_kernel(), unlock_kernel() */
#include <linux/capability.h> /* capable() */
#include <linux/uaccess.h> /* copy_from_user(), copy_to_user() */
+#include <linux/vmalloc.h>
#include <linux/nilfs2_fs.h>
#include "nilfs.h"
#include "segment.h"
@@ -147,29 +148,12 @@ static ssize_t
nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
void *buf, size_t size, size_t nmembs)
{
- return nilfs_cpfile_get_cpinfo(nilfs->ns_cpfile, posp, flags, buf,
- nmembs);
-}
-
-static int nilfs_ioctl_get_cpinfo(struct inode *inode, struct file *filp,
- unsigned int cmd, void __user *argp)
-{
- struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
- struct nilfs_argv argv;
int ret;
- if (copy_from_user(&argv, argp, sizeof(argv)))
- return -EFAULT;
-
down_read(&nilfs->ns_segctor_sem);
- ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd),
- nilfs_ioctl_do_get_cpinfo);
+ ret = nilfs_cpfile_get_cpinfo(nilfs->ns_cpfile, posp, flags, buf,
+ nmembs);
up_read(&nilfs->ns_segctor_sem);
- if (ret < 0)
- return ret;
-
- if (copy_to_user(argp, &argv, sizeof(argv)))
- ret = -EFAULT;
return ret;
}
@@ -195,28 +179,11 @@ static ssize_t
nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
void *buf, size_t size, size_t nmembs)
{
- return nilfs_sufile_get_suinfo(nilfs->ns_sufile, *posp, buf, nmembs);
-}
-
-static int nilfs_ioctl_get_suinfo(struct inode *inode, struct file *filp,
- unsigned int cmd, void __user *argp)
-{
- struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
- struct nilfs_argv argv;
int ret;
- if (copy_from_user(&argv, argp, sizeof(argv)))
- return -EFAULT;
-
down_read(&nilfs->ns_segctor_sem);
- ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd),
- nilfs_ioctl_do_get_suinfo);
+ ret = nilfs_sufile_get_suinfo(nilfs->ns_sufile, *posp, buf, nmembs);
up_read(&nilfs->ns_segctor_sem);
- if (ret < 0)
- return ret;
-
- if (copy_to_user(argp, &argv, sizeof(argv)))
- ret = -EFAULT;
return ret;
}
@@ -242,28 +209,11 @@ static ssize_t
nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
void *buf, size_t size, size_t nmembs)
{
- return nilfs_dat_get_vinfo(nilfs_dat_inode(nilfs), buf, nmembs);
-}
-
-static int nilfs_ioctl_get_vinfo(struct inode *inode, struct file *filp,
- unsigned int cmd, void __user *argp)
-{
- struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
- struct nilfs_argv argv;
int ret;
- if (copy_from_user(&argv, argp, sizeof(argv)))
- return -EFAULT;
-
down_read(&nilfs->ns_segctor_sem);
- ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd),
- nilfs_ioctl_do_get_vinfo);
+ ret = nilfs_dat_get_vinfo(nilfs_dat_inode(nilfs), buf, nmembs);
up_read(&nilfs->ns_segctor_sem);
- if (ret < 0)
- return ret;
-
- if (copy_to_user(argp, &argv, sizeof(argv)))
- ret = -EFAULT;
return ret;
}
@@ -276,17 +226,21 @@ nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags,
struct nilfs_bdesc *bdescs = buf;
int ret, i;
+ down_read(&nilfs->ns_segctor_sem);
for (i = 0; i < nmembs; i++) {
ret = nilfs_bmap_lookup_at_level(bmap,
bdescs[i].bd_offset,
bdescs[i].bd_level + 1,
&bdescs[i].bd_blocknr);
if (ret < 0) {
- if (ret != -ENOENT)
+ if (ret != -ENOENT) {
+ up_read(&nilfs->ns_segctor_sem);
return ret;
+ }
bdescs[i].bd_blocknr = 0;
}
}
+ up_read(&nilfs->ns_segctor_sem);
return nmembs;
}
@@ -300,10 +254,11 @@ static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp,
if (copy_from_user(&argv, argp, sizeof(argv)))
return -EFAULT;
- down_read(&nilfs->ns_segctor_sem);
+ if (argv.v_size != sizeof(struct nilfs_bdesc))
+ return -EINVAL;
+
ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd),
nilfs_ioctl_do_get_bdescs);
- up_read(&nilfs->ns_segctor_sem);
if (ret < 0)
return ret;
@@ -346,10 +301,10 @@ static int nilfs_ioctl_move_inode_block(struct inode *inode,
return 0;
}
-static ssize_t
-nilfs_ioctl_do_move_blocks(struct the_nilfs *nilfs, __u64 *posp, int flags,
- void *buf, size_t size, size_t nmembs)
+static int nilfs_ioctl_move_blocks(struct the_nilfs *nilfs,
+ struct nilfs_argv *argv, void *buf)
{
+ size_t nmembs = argv->v_nmembs;
struct inode *inode;
struct nilfs_vdesc *vdesc;
struct buffer_head *bh, *n;
@@ -410,19 +365,10 @@ nilfs_ioctl_do_move_blocks(struct the_nilfs *nilfs, __u64 *posp, int flags,
return ret;
}
-static inline int nilfs_ioctl_move_blocks(struct the_nilfs *nilfs,
- struct nilfs_argv *argv,
- int dir)
-{
- return nilfs_ioctl_wrap_copy(nilfs, argv, dir,
- nilfs_ioctl_do_move_blocks);
-}
-
-static ssize_t
-nilfs_ioctl_do_delete_checkpoints(struct the_nilfs *nilfs, __u64 *posp,
- int flags, void *buf, size_t size,
- size_t nmembs)
+static int nilfs_ioctl_delete_checkpoints(struct the_nilfs *nilfs,
+ struct nilfs_argv *argv, void *buf)
{
+ size_t nmembs = argv->v_nmembs;
struct inode *cpfile = nilfs->ns_cpfile;
struct nilfs_period *periods = buf;
int ret, i;
@@ -436,36 +382,21 @@ nilfs_ioctl_do_delete_checkpoints(struct the_nilfs *nilfs, __u64 *posp,
return nmembs;
}
-static inline int nilfs_ioctl_delete_checkpoints(struct the_nilfs *nilfs,
- struct nilfs_argv *argv,
- int dir)
+static int nilfs_ioctl_free_vblocknrs(struct the_nilfs *nilfs,
+ struct nilfs_argv *argv, void *buf)
{
- return nilfs_ioctl_wrap_copy(nilfs, argv, dir,
- nilfs_ioctl_do_delete_checkpoints);
-}
+ size_t nmembs = argv->v_nmembs;
+ int ret;
-static ssize_t
-nilfs_ioctl_do_free_vblocknrs(struct the_nilfs *nilfs, __u64 *posp, int flags,
- void *buf, size_t size, size_t nmembs)
-{
- int ret = nilfs_dat_freev(nilfs_dat_inode(nilfs), buf, nmembs);
+ ret = nilfs_dat_freev(nilfs_dat_inode(nilfs), buf, nmembs);
return (ret < 0) ? ret : nmembs;
}
-static inline int nilfs_ioctl_free_vblocknrs(struct the_nilfs *nilfs,
- struct nilfs_argv *argv,
- int dir)
-{
- return nilfs_ioctl_wrap_copy(nilfs, argv, dir,
- nilfs_ioctl_do_free_vblocknrs);
-}
-
-static ssize_t
-nilfs_ioctl_do_mark_blocks_dirty(struct the_nilfs *nilfs, __u64 *posp,
- int flags, void *buf, size_t size,
- size_t nmembs)
+static int nilfs_ioctl_mark_blocks_dirty(struct the_nilfs *nilfs,
+ struct nilfs_argv *argv, void *buf)
{
+ size_t nmembs = argv->v_nmembs;
struct inode *dat = nilfs_dat_inode(nilfs);
struct nilfs_bmap *bmap = NILFS_I(dat)->i_bmap;
struct nilfs_bdesc *bdescs = buf;
@@ -504,55 +435,37 @@ nilfs_ioctl_do_mark_blocks_dirty(struct the_nilfs *nilfs, __u64 *posp,
return nmembs;
}
-static inline int nilfs_ioctl_mark_blocks_dirty(struct the_nilfs *nilfs,
- struct nilfs_argv *argv,
- int dir)
+static int nilfs_ioctl_free_segments(struct the_nilfs *nilfs,
+ struct nilfs_argv *argv, void *buf)
{
- return nilfs_ioctl_wrap_copy(nilfs, argv, dir,
- nilfs_ioctl_do_mark_blocks_dirty);
-}
-
-static ssize_t
-nilfs_ioctl_do_free_segments(struct the_nilfs *nilfs, __u64 *posp, int flags,
- void *buf, size_t size, size_t nmembs)
-{
- struct nilfs_sb_info *sbi = nilfs_get_writer(nilfs);
+ size_t nmembs = argv->v_nmembs;
+ struct nilfs_sb_info *sbi = nilfs->ns_writer;
int ret;
- if (unlikely(!sbi))
+ if (unlikely(!sbi)) {
+ /* never happens because called for a writable mount */
+ WARN_ON(1);
return -EROFS;
+ }
ret = nilfs_segctor_add_segments_to_be_freed(
NILFS_SC(sbi), buf, nmembs);
- nilfs_put_writer(nilfs);
return (ret < 0) ? ret : nmembs;
}
-static inline int nilfs_ioctl_free_segments(struct the_nilfs *nilfs,
- struct nilfs_argv *argv,
- int dir)
-{
- return nilfs_ioctl_wrap_copy(nilfs, argv, dir,
- nilfs_ioctl_do_free_segments);
-}
-
int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
- void __user *argp)
+ struct nilfs_argv *argv, void **kbufs)
{
- struct nilfs_argv argv[5];
const char *msg;
- int dir, ret;
-
- if (copy_from_user(argv, argp, sizeof(argv)))
- return -EFAULT;
+ int ret;
- dir = _IOC_WRITE;
- ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], dir);
+ ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], kbufs[0]);
if (ret < 0) {
msg = "cannot read source blocks";
goto failed;
}
- ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], dir);
+
+ ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], kbufs[1]);
if (ret < 0) {
/*
* can safely abort because checkpoints can be removed
@@ -561,7 +474,7 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
msg = "cannot delete checkpoints";
goto failed;
}
- ret = nilfs_ioctl_free_vblocknrs(nilfs, &argv[2], dir);
+ ret = nilfs_ioctl_free_vblocknrs(nilfs, &argv[2], kbufs[2]);
if (ret < 0) {
/*
* can safely abort because DAT file is updated atomically
@@ -570,7 +483,7 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
msg = "cannot delete virtual blocks from DAT file";
goto failed;
}
- ret = nilfs_ioctl_mark_blocks_dirty(nilfs, &argv[3], dir);
+ ret = nilfs_ioctl_mark_blocks_dirty(nilfs, &argv[3], kbufs[3]);
if (ret < 0) {
/*
* can safely abort because the operation is nondestructive.
@@ -578,7 +491,7 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
msg = "cannot mark copying blocks dirty";
goto failed;
}
- ret = nilfs_ioctl_free_segments(nilfs, &argv[4], dir);
+ ret = nilfs_ioctl_free_segments(nilfs, &argv[4], kbufs[4]);
if (ret < 0) {
/*
* can safely abort because this operation is atomic.
@@ -598,9 +511,75 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
unsigned int cmd, void __user *argp)
{
+ struct nilfs_argv argv[5];
+ const static size_t argsz[5] = {
+ sizeof(struct nilfs_vdesc),
+ sizeof(struct nilfs_period),
+ sizeof(__u64),
+ sizeof(struct nilfs_bdesc),
+ sizeof(__u64),
+ };
+ void __user *base;
+ void *kbufs[5];
+ struct the_nilfs *nilfs;
+ size_t len, nsegs;
+ int n, ret;
+
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- return nilfs_clean_segments(inode->i_sb, argp);
+
+ if (copy_from_user(argv, argp, sizeof(argv)))
+ return -EFAULT;
+
+ nsegs = argv[4].v_nmembs;
+ if (argv[4].v_size != argsz[4])
+ return -EINVAL;
+ /*
+ * argv[4] points to segment numbers this ioctl cleans. We
+ * use kmalloc() for its buffer because memory used for the
+ * segment numbers is enough small.
+ */
+ kbufs[4] = memdup_user((void __user *)(unsigned long)argv[4].v_base,
+ nsegs * sizeof(__u64));
+ if (IS_ERR(kbufs[4]))
+ return PTR_ERR(kbufs[4]);
+
+ nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
+
+ for (n = 0; n < 4; n++) {
+ ret = -EINVAL;
+ if (argv[n].v_size != argsz[n])
+ goto out_free;
+
+ if (argv[n].v_nmembs > nsegs * nilfs->ns_blocks_per_segment)
+ goto out_free;
+
+ len = argv[n].v_size * argv[n].v_nmembs;
+ base = (void __user *)(unsigned long)argv[n].v_base;
+ if (len == 0) {
+ kbufs[n] = NULL;
+ continue;
+ }
+
+ kbufs[n] = vmalloc(len);
+ if (!kbufs[n]) {
+ ret = -ENOMEM;
+ goto out_free;
+ }
+ if (copy_from_user(kbufs[n], base, len)) {
+ ret = -EFAULT;
+ vfree(kbufs[n]);
+ goto out_free;
+ }
+ }
+
+ ret = nilfs_clean_segments(inode->i_sb, argv, kbufs);
+
+ out_free:
+ while (--n > 0)
+ vfree(kbufs[n]);
+ kfree(kbufs[4]);
+ return ret;
}
static int nilfs_ioctl_sync(struct inode *inode, struct file *filp,
@@ -621,6 +600,33 @@ static int nilfs_ioctl_sync(struct inode *inode, struct file *filp,
return 0;
}
+static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp,
+ unsigned int cmd, void __user *argp,
+ size_t membsz,
+ ssize_t (*dofunc)(struct the_nilfs *,
+ __u64 *, int,
+ void *, size_t, size_t))
+
+{
+ struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
+ struct nilfs_argv argv;
+ int ret;
+
+ if (copy_from_user(&argv, argp, sizeof(argv)))
+ return -EFAULT;
+
+ if (argv.v_size != membsz)
+ return -EINVAL;
+
+ ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), dofunc);
+ if (ret < 0)
+ return ret;
+
+ if (copy_to_user(argp, &argv, sizeof(argv)))
+ ret = -EFAULT;
+ return ret;
+}
+
long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct inode *inode = filp->f_dentry->d_inode;
@@ -632,16 +638,21 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
case NILFS_IOCTL_DELETE_CHECKPOINT:
return nilfs_ioctl_delete_checkpoint(inode, filp, cmd, argp);
case NILFS_IOCTL_GET_CPINFO:
- return nilfs_ioctl_get_cpinfo(inode, filp, cmd, argp);
+ return nilfs_ioctl_get_info(inode, filp, cmd, argp,
+ sizeof(struct nilfs_cpinfo),
+ nilfs_ioctl_do_get_cpinfo);
case NILFS_IOCTL_GET_CPSTAT:
return nilfs_ioctl_get_cpstat(inode, filp, cmd, argp);
case NILFS_IOCTL_GET_SUINFO:
- return nilfs_ioctl_get_suinfo(inode, filp, cmd, argp);
+ return nilfs_ioctl_get_info(inode, filp, cmd, argp,
+ sizeof(struct nilfs_suinfo),
+ nilfs_ioctl_do_get_suinfo);
case NILFS_IOCTL_GET_SUSTAT:
return nilfs_ioctl_get_sustat(inode, filp, cmd, argp);
case NILFS_IOCTL_GET_VINFO:
- /* XXX: rename to ??? */
- return nilfs_ioctl_get_vinfo(inode, filp, cmd, argp);
+ return nilfs_ioctl_get_info(inode, filp, cmd, argp,
+ sizeof(struct nilfs_vinfo),
+ nilfs_ioctl_do_get_vinfo);
case NILFS_IOCTL_GET_BDESCS:
return nilfs_ioctl_get_bdescs(inode, filp, cmd, argp);
case NILFS_IOCTL_CLEAN_SEGMENTS:
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c
index 47dd815433fd..bb78745a0e30 100644
--- a/fs/nilfs2/mdt.c
+++ b/fs/nilfs2/mdt.c
@@ -77,19 +77,22 @@ static int nilfs_mdt_create_block(struct inode *inode, unsigned long block,
void *))
{
struct the_nilfs *nilfs = NILFS_MDT(inode)->mi_nilfs;
- struct nilfs_sb_info *writer = NULL;
struct super_block *sb = inode->i_sb;
struct nilfs_transaction_info ti;
struct buffer_head *bh;
int err;
if (!sb) {
- writer = nilfs_get_writer(nilfs);
- if (!writer) {
+ /*
+ * Make sure this function is not called from any
+ * read-only context.
+ */
+ if (!nilfs->ns_writer) {
+ WARN_ON(1);
err = -EROFS;
goto out;
}
- sb = writer->s_super;
+ sb = nilfs->ns_writer->s_super;
}
nilfs_transaction_begin(sb, &ti, 0);
@@ -127,8 +130,6 @@ static int nilfs_mdt_create_block(struct inode *inode, unsigned long block,
err = nilfs_transaction_commit(sb);
else
nilfs_transaction_abort(sb);
- if (writer)
- nilfs_put_writer(nilfs);
out:
return err;
}
@@ -299,7 +300,7 @@ int nilfs_mdt_delete_block(struct inode *inode, unsigned long block)
int err;
err = nilfs_bmap_delete(ii->i_bmap, block);
- if (likely(!err)) {
+ if (!err || err == -ENOENT) {
nilfs_mdt_mark_dirty(inode);
nilfs_mdt_forget_block(inode, block);
}
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
index 7558c977db02..da6fc0bba2e5 100644
--- a/fs/nilfs2/nilfs.h
+++ b/fs/nilfs2/nilfs.h
@@ -35,11 +35,6 @@
#include "bmap_union.h"
/*
- * NILFS filesystem version
- */
-#define NILFS_VERSION "2.0.5"
-
-/*
* nilfs inode data in memory
*/
struct nilfs_inode_info {
@@ -241,7 +236,8 @@ extern int nilfs_sync_file(struct file *, struct dentry *, int);
/* ioctl.c */
long nilfs_ioctl(struct file *, unsigned int, unsigned long);
-int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *, void __user *);
+int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *, struct nilfs_argv *,
+ void **);
/* inode.c */
extern struct inode *nilfs_new_inode(struct inode *, int);
diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c
index 1bfbba9c0e9a..a2692bbc7b50 100644
--- a/fs/nilfs2/page.c
+++ b/fs/nilfs2/page.c
@@ -128,7 +128,8 @@ void nilfs_forget_buffer(struct buffer_head *bh)
lock_buffer(bh);
clear_buffer_nilfs_volatile(bh);
- if (test_clear_buffer_dirty(bh) && nilfs_page_buffers_clean(page))
+ clear_buffer_dirty(bh);
+ if (nilfs_page_buffers_clean(page))
__nilfs_clear_page_dirty(page);
clear_buffer_uptodate(bh);
diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c
index 6ade0963fc1d..57afa9d24061 100644
--- a/fs/nilfs2/recovery.c
+++ b/fs/nilfs2/recovery.c
@@ -407,13 +407,13 @@ void nilfs_dispose_segment_list(struct list_head *head)
}
static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
+ struct nilfs_sb_info *sbi,
struct nilfs_recovery_info *ri)
{
struct list_head *head = &ri->ri_used_segments;
struct nilfs_segment_entry *ent, *n;
struct inode *sufile = nilfs->ns_sufile;
__u64 segnum[4];
- time_t mtime;
int err;
int i;
@@ -422,6 +422,7 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
segnum[2] = ri->ri_segnum;
segnum[3] = ri->ri_nextnum;
+ nilfs_attach_writer(nilfs, sbi);
/*
* Releasing the next segment of the latest super root.
* The next segment is invalidated by this recovery.
@@ -442,24 +443,13 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
* Collecting segments written after the latest super root.
* These are marked dirty to avoid being reallocated in the next write.
*/
- mtime = get_seconds();
list_for_each_entry_safe(ent, n, head, list) {
- if (ent->segnum == segnum[0]) {
- list_del(&ent->list);
- nilfs_free_segment_entry(ent);
- continue;
- }
- err = nilfs_open_segment_entry(ent, sufile);
- if (unlikely(err))
- goto failed;
- if (!nilfs_segment_usage_dirty(ent->raw_su)) {
- /* make the segment garbage */
- ent->raw_su->su_nblocks = cpu_to_le32(0);
- ent->raw_su->su_lastmod = cpu_to_le32(mtime);
- nilfs_segment_usage_set_dirty(ent->raw_su);
+ if (ent->segnum != segnum[0]) {
+ err = nilfs_sufile_scrap(sufile, ent->segnum);
+ if (unlikely(err))
+ goto failed;
}
list_del(&ent->list);
- nilfs_close_segment_entry(ent, sufile);
nilfs_free_segment_entry(ent);
}
@@ -471,10 +461,10 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
nilfs->ns_pseg_offset = 0;
nilfs->ns_seg_seq = ri->ri_seq + 2;
nilfs->ns_nextnum = nilfs->ns_segnum = segnum[0];
- return 0;
failed:
/* No need to recover sufile because it will be destroyed on error */
+ nilfs_detach_writer(nilfs, sbi);
return err;
}
@@ -740,7 +730,7 @@ int nilfs_recover_logical_segments(struct the_nilfs *nilfs,
goto failed;
if (ri->ri_need_recovery == NILFS_RECOVERY_ROLLFORWARD_DONE) {
- err = nilfs_prepare_segment_for_recovery(nilfs, ri);
+ err = nilfs_prepare_segment_for_recovery(nilfs, sbi, ri);
if (unlikely(err)) {
printk(KERN_ERR "NILFS: Error preparing segments for "
"recovery.\n");
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index fb70ec3be20e..22c7f65c2403 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -2589,7 +2589,8 @@ nilfs_remove_written_gcinodes(struct the_nilfs *nilfs, struct list_head *head)
}
}
-int nilfs_clean_segments(struct super_block *sb, void __user *argp)
+int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
+ void **kbufs)
{
struct nilfs_sb_info *sbi = NILFS_SB(sb);
struct nilfs_sc_info *sci = NILFS_SC(sbi);
@@ -2606,7 +2607,7 @@ int nilfs_clean_segments(struct super_block *sb, void __user *argp)
err = nilfs_init_gcdat_inode(nilfs);
if (unlikely(err))
goto out_unlock;
- err = nilfs_ioctl_prepare_clean_segments(nilfs, argp);
+ err = nilfs_ioctl_prepare_clean_segments(nilfs, argv, kbufs);
if (unlikely(err))
goto out_unlock;
diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h
index a98fc1ed0bbb..476bdd5df5be 100644
--- a/fs/nilfs2/segment.h
+++ b/fs/nilfs2/segment.h
@@ -222,7 +222,8 @@ extern int nilfs_construct_segment(struct super_block *);
extern int nilfs_construct_dsync_segment(struct super_block *, struct inode *,
loff_t, loff_t);
extern void nilfs_flush_segment(struct super_block *, ino_t);
-extern int nilfs_clean_segments(struct super_block *, void __user *);
+extern int nilfs_clean_segments(struct super_block *, struct nilfs_argv *,
+ void **);
extern int nilfs_segctor_add_segments_to_be_freed(struct nilfs_sc_info *,
__u64 *, size_t);
diff --git a/fs/nilfs2/sufile.c b/fs/nilfs2/sufile.c
index c774cf397e2f..98e68677f045 100644
--- a/fs/nilfs2/sufile.c
+++ b/fs/nilfs2/sufile.c
@@ -93,6 +93,52 @@ nilfs_sufile_get_segment_usage_block(struct inode *sufile, __u64 segnum,
create, NULL, bhp);
}
+static void nilfs_sufile_mod_counter(struct buffer_head *header_bh,
+ u64 ncleanadd, u64 ndirtyadd)
+{
+ struct nilfs_sufile_header *header;
+ void *kaddr;
+
+ kaddr = kmap_atomic(header_bh->b_page, KM_USER0);
+ header = kaddr + bh_offset(header_bh);
+ le64_add_cpu(&header->sh_ncleansegs, ncleanadd);
+ le64_add_cpu(&header->sh_ndirtysegs, ndirtyadd);
+ kunmap_atomic(kaddr, KM_USER0);
+
+ nilfs_mdt_mark_buffer_dirty(header_bh);
+}
+
+int nilfs_sufile_update(struct inode *sufile, __u64 segnum, int create,
+ void (*dofunc)(struct inode *, __u64,
+ struct buffer_head *,
+ struct buffer_head *))
+{
+ struct buffer_head *header_bh, *bh;
+ int ret;
+
+ if (unlikely(segnum >= nilfs_sufile_get_nsegments(sufile))) {
+ printk(KERN_WARNING "%s: invalid segment number: %llu\n",
+ __func__, (unsigned long long)segnum);
+ return -EINVAL;
+ }
+ down_write(&NILFS_MDT(sufile)->mi_sem);
+
+ ret = nilfs_sufile_get_header_block(sufile, &header_bh);
+ if (ret < 0)
+ goto out_sem;
+
+ ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, create, &bh);
+ if (!ret) {
+ dofunc(sufile, segnum, header_bh, bh);
+ brelse(bh);
+ }
+ brelse(header_bh);
+
+ out_sem:
+ up_write(&NILFS_MDT(sufile)->mi_sem);
+ return ret;
+}
+
/**
* nilfs_sufile_alloc - allocate a segment
* @sufile: inode of segment usage file
@@ -113,7 +159,6 @@ nilfs_sufile_get_segment_usage_block(struct inode *sufile, __u64 segnum,
int nilfs_sufile_alloc(struct inode *sufile, __u64 *segnump)
{
struct buffer_head *header_bh, *su_bh;
- struct the_nilfs *nilfs;
struct nilfs_sufile_header *header;
struct nilfs_segment_usage *su;
size_t susz = NILFS_MDT(sufile)->mi_entry_size;
@@ -124,8 +169,6 @@ int nilfs_sufile_alloc(struct inode *sufile, __u64 *segnump)
down_write(&NILFS_MDT(sufile)->mi_sem);
- nilfs = NILFS_MDT(sufile)->mi_nilfs;
-
ret = nilfs_sufile_get_header_block(sufile, &header_bh);
if (ret < 0)
goto out_sem;
@@ -192,165 +235,84 @@ int nilfs_sufile_alloc(struct inode *sufile, __u64 *segnump)
return ret;
}
-/**
- * nilfs_sufile_cancel_free -
- * @sufile: inode of segment usage file
- * @segnum: segment number
- *
- * Description:
- *
- * Return Value: On success, 0 is returned. On error, one of the following
- * negative error codes is returned.
- *
- * %-EIO - I/O error.
- *
- * %-ENOMEM - Insufficient amount of memory available.
- */
-int nilfs_sufile_cancel_free(struct inode *sufile, __u64 segnum)
+void nilfs_sufile_do_cancel_free(struct inode *sufile, __u64 segnum,
+ struct buffer_head *header_bh,
+ struct buffer_head *su_bh)
{
- struct buffer_head *header_bh, *su_bh;
- struct the_nilfs *nilfs;
- struct nilfs_sufile_header *header;
struct nilfs_segment_usage *su;
void *kaddr;
- int ret;
-
- down_write(&NILFS_MDT(sufile)->mi_sem);
-
- nilfs = NILFS_MDT(sufile)->mi_nilfs;
-
- ret = nilfs_sufile_get_header_block(sufile, &header_bh);
- if (ret < 0)
- goto out_sem;
-
- ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0, &su_bh);
- if (ret < 0)
- goto out_header;
kaddr = kmap_atomic(su_bh->b_page, KM_USER0);
- su = nilfs_sufile_block_get_segment_usage(
- sufile, segnum, su_bh, kaddr);
+ su = nilfs_sufile_block_get_segment_usage(sufile, segnum, su_bh, kaddr);
if (unlikely(!nilfs_segment_usage_clean(su))) {
printk(KERN_WARNING "%s: segment %llu must be clean\n",
__func__, (unsigned long long)segnum);
kunmap_atomic(kaddr, KM_USER0);
- goto out_su_bh;
+ return;
}
nilfs_segment_usage_set_dirty(su);
kunmap_atomic(kaddr, KM_USER0);
- kaddr = kmap_atomic(header_bh->b_page, KM_USER0);
- header = nilfs_sufile_block_get_header(sufile, header_bh, kaddr);
- le64_add_cpu(&header->sh_ncleansegs, -1);
- le64_add_cpu(&header->sh_ndirtysegs, 1);
- kunmap_atomic(kaddr, KM_USER0);
-
- nilfs_mdt_mark_buffer_dirty(header_bh);
+ nilfs_sufile_mod_counter(header_bh, -1, 1);
nilfs_mdt_mark_buffer_dirty(su_bh);
nilfs_mdt_mark_dirty(sufile);
-
- out_su_bh:
- brelse(su_bh);
- out_header:
- brelse(header_bh);
- out_sem:
- up_write(&NILFS_MDT(sufile)->mi_sem);
- return ret;
}
-/**
- * nilfs_sufile_freev - free segments
- * @sufile: inode of segment usage file
- * @segnum: array of segment numbers
- * @nsegs: number of segments
- *
- * Description: nilfs_sufile_freev() frees segments specified by @segnum and
- * @nsegs, which must have been returned by a previous call to
- * nilfs_sufile_alloc().
- *
- * Return Value: On success, 0 is returned. On error, one of the following
- * negative error codes is returned.
- *
- * %-EIO - I/O error.
- *
- * %-ENOMEM - Insufficient amount of memory available.
- */
-#define NILFS_SUFILE_FREEV_PREALLOC 16
-int nilfs_sufile_freev(struct inode *sufile, __u64 *segnum, size_t nsegs)
+void nilfs_sufile_do_scrap(struct inode *sufile, __u64 segnum,
+ struct buffer_head *header_bh,
+ struct buffer_head *su_bh)
{
- struct buffer_head *header_bh, **su_bh,
- *su_bh_prealloc[NILFS_SUFILE_FREEV_PREALLOC];
- struct the_nilfs *nilfs;
- struct nilfs_sufile_header *header;
struct nilfs_segment_usage *su;
void *kaddr;
- int ret, i;
+ int clean, dirty;
- down_write(&NILFS_MDT(sufile)->mi_sem);
-
- nilfs = NILFS_MDT(sufile)->mi_nilfs;
-
- /* prepare resources */
- if (nsegs <= NILFS_SUFILE_FREEV_PREALLOC)
- su_bh = su_bh_prealloc;
- else {
- su_bh = kmalloc(sizeof(*su_bh) * nsegs, GFP_NOFS);
- if (su_bh == NULL) {
- ret = -ENOMEM;
- goto out_sem;
- }
- }
-
- ret = nilfs_sufile_get_header_block(sufile, &header_bh);
- if (ret < 0)
- goto out_su_bh;
- for (i = 0; i < nsegs; i++) {
- ret = nilfs_sufile_get_segment_usage_block(sufile, segnum[i],
- 0, &su_bh[i]);
- if (ret < 0)
- goto out_bh;
- }
-
- /* free segments */
- for (i = 0; i < nsegs; i++) {
- kaddr = kmap_atomic(su_bh[i]->b_page, KM_USER0);
- su = nilfs_sufile_block_get_segment_usage(
- sufile, segnum[i], su_bh[i], kaddr);
- WARN_ON(nilfs_segment_usage_error(su));
- nilfs_segment_usage_set_clean(su);
+ kaddr = kmap_atomic(su_bh->b_page, KM_USER0);
+ su = nilfs_sufile_block_get_segment_usage(sufile, segnum, su_bh, kaddr);
+ if (su->su_flags == cpu_to_le32(1UL << NILFS_SEGMENT_USAGE_DIRTY) &&
+ su->su_nblocks == cpu_to_le32(0)) {
kunmap_atomic(kaddr, KM_USER0);
- nilfs_mdt_mark_buffer_dirty(su_bh[i]);
+ return;
}
- kaddr = kmap_atomic(header_bh->b_page, KM_USER0);
- header = nilfs_sufile_block_get_header(sufile, header_bh, kaddr);
- le64_add_cpu(&header->sh_ncleansegs, nsegs);
- le64_add_cpu(&header->sh_ndirtysegs, -(u64)nsegs);
+ clean = nilfs_segment_usage_clean(su);
+ dirty = nilfs_segment_usage_dirty(su);
+
+ /* make the segment garbage */
+ su->su_lastmod = cpu_to_le64(0);
+ su->su_nblocks = cpu_to_le32(0);
+ su->su_flags = cpu_to_le32(1UL << NILFS_SEGMENT_USAGE_DIRTY);
kunmap_atomic(kaddr, KM_USER0);
- nilfs_mdt_mark_buffer_dirty(header_bh);
+
+ nilfs_sufile_mod_counter(header_bh, clean ? (u64)-1 : 0, dirty ? 0 : 1);
+ nilfs_mdt_mark_buffer_dirty(su_bh);
nilfs_mdt_mark_dirty(sufile);
+}
- out_bh:
- for (i--; i >= 0; i--)
- brelse(su_bh[i]);
- brelse(header_bh);
+void nilfs_sufile_do_free(struct inode *sufile, __u64 segnum,
+ struct buffer_head *header_bh,
+ struct buffer_head *su_bh)
+{
+ struct nilfs_segment_usage *su;
+ void *kaddr;
+ int sudirty;
- out_su_bh:
- if (su_bh != su_bh_prealloc)
- kfree(su_bh);
+ kaddr = kmap_atomic(su_bh->b_page, KM_USER0);
+ su = nilfs_sufile_block_get_segment_usage(sufile, segnum, su_bh, kaddr);
+ if (nilfs_segment_usage_clean(su)) {
+ printk(KERN_WARNING "%s: segment %llu is already clean\n",
+ __func__, (unsigned long long)segnum);
+ kunmap_atomic(kaddr, KM_USER0);
+ return;
+ }
+ WARN_ON(nilfs_segment_usage_error(su));
+ WARN_ON(!nilfs_segment_usage_dirty(su));
- out_sem:
- up_write(&NILFS_MDT(sufile)->mi_sem);
- return ret;
-}
+ sudirty = nilfs_segment_usage_dirty(su);
+ nilfs_segment_usage_set_clean(su);
+ kunmap_atomic(kaddr, KM_USER0);
+ nilfs_mdt_mark_buffer_dirty(su_bh);
-/**
- * nilfs_sufile_free -
- * @sufile:
- * @segnum:
- */
-int nilfs_sufile_free(struct inode *sufile, __u64 segnum)
-{
- return nilfs_sufile_freev(sufile, &segnum, 1);
+ nilfs_sufile_mod_counter(header_bh, 1, sudirty ? (u64)-1 : 0);
+ nilfs_mdt_mark_dirty(sufile);
}
/**
@@ -500,72 +462,28 @@ int nilfs_sufile_get_ncleansegs(struct inode *sufile, unsigned long *nsegsp)
return ret;
}
-/**
- * nilfs_sufile_set_error - mark a segment as erroneous
- * @sufile: inode of segment usage file
- * @segnum: segment number
- *
- * Description: nilfs_sufile_set_error() marks the segment specified by
- * @segnum as erroneous. The error segment will never be used again.
- *
- * Return Value: On success, 0 is returned. On error, one of the following
- * negative error codes is returned.
- *
- * %-EIO - I/O error.
- *
- * %-ENOMEM - Insufficient amount of memory available.
- *
- * %-EINVAL - Invalid segment usage number.
- */
-int nilfs_sufile_set_error(struct inode *sufile, __u64 segnum)
+void nilfs_sufile_do_set_error(struct inode *sufile, __u64 segnum,
+ struct buffer_head *header_bh,
+ struct buffer_head *su_bh)
{
- struct buffer_head *header_bh, *su_bh;
struct nilfs_segment_usage *su;
- struct nilfs_sufile_header *header;
void *kaddr;
- int ret;
-
- if (unlikely(segnum >= nilfs_sufile_get_nsegments(sufile))) {
- printk(KERN_WARNING "%s: invalid segment number: %llu\n",
- __func__, (unsigned long long)segnum);
- return -EINVAL;
- }
- down_write(&NILFS_MDT(sufile)->mi_sem);
-
- ret = nilfs_sufile_get_header_block(sufile, &header_bh);
- if (ret < 0)
- goto out_sem;
- ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0, &su_bh);
- if (ret < 0)
- goto out_header;
+ int suclean;
kaddr = kmap_atomic(su_bh->b_page, KM_USER0);
su = nilfs_sufile_block_get_segment_usage(sufile, segnum, su_bh, kaddr);
if (nilfs_segment_usage_error(su)) {
kunmap_atomic(kaddr, KM_USER0);
- brelse(su_bh);
- goto out_header;
+ return;
}
-
+ suclean = nilfs_segment_usage_clean(su);
nilfs_segment_usage_set_error(su);
kunmap_atomic(kaddr, KM_USER0);
- brelse(su_bh);
- kaddr = kmap_atomic(header_bh->b_page, KM_USER0);
- header = nilfs_sufile_block_get_header(sufile, header_bh, kaddr);
- le64_add_cpu(&header->sh_ndirtysegs, -1);
- kunmap_atomic(kaddr, KM_USER0);
- nilfs_mdt_mark_buffer_dirty(header_bh);
+ if (suclean)
+ nilfs_sufile_mod_counter(header_bh, -1, 0);
nilfs_mdt_mark_buffer_dirty(su_bh);
nilfs_mdt_mark_dirty(sufile);
- brelse(su_bh);
-
- out_header:
- brelse(header_bh);
-
- out_sem:
- up_write(&NILFS_MDT(sufile)->mi_sem);
- return ret;
}
/**
@@ -625,7 +543,7 @@ ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum,
si[i + j].sui_nblocks = le32_to_cpu(su->su_nblocks);
si[i + j].sui_flags = le32_to_cpu(su->su_flags) &
~(1UL << NILFS_SEGMENT_USAGE_ACTIVE);
- if (nilfs_segment_is_active(nilfs, segnum + i + j))
+ if (nilfs_segment_is_active(nilfs, segnum + j))
si[i + j].sui_flags |=
(1UL << NILFS_SEGMENT_USAGE_ACTIVE);
}
diff --git a/fs/nilfs2/sufile.h b/fs/nilfs2/sufile.h
index d595f33a768d..a2e2efd4ade1 100644
--- a/fs/nilfs2/sufile.h
+++ b/fs/nilfs2/sufile.h
@@ -36,9 +36,6 @@ static inline unsigned long nilfs_sufile_get_nsegments(struct inode *sufile)
}
int nilfs_sufile_alloc(struct inode *, __u64 *);
-int nilfs_sufile_cancel_free(struct inode *, __u64);
-int nilfs_sufile_freev(struct inode *, __u64 *, size_t);
-int nilfs_sufile_free(struct inode *, __u64);
int nilfs_sufile_get_segment_usage(struct inode *, __u64,
struct nilfs_segment_usage **,
struct buffer_head **);
@@ -46,9 +43,83 @@ void nilfs_sufile_put_segment_usage(struct inode *, __u64,
struct buffer_head *);
int nilfs_sufile_get_stat(struct inode *, struct nilfs_sustat *);
int nilfs_sufile_get_ncleansegs(struct inode *, unsigned long *);
-int nilfs_sufile_set_error(struct inode *, __u64);
ssize_t nilfs_sufile_get_suinfo(struct inode *, __u64, struct nilfs_suinfo *,
size_t);
+int nilfs_sufile_update(struct inode *, __u64, int,
+ void (*dofunc)(struct inode *, __u64,
+ struct buffer_head *,
+ struct buffer_head *));
+void nilfs_sufile_do_cancel_free(struct inode *, __u64, struct buffer_head *,
+ struct buffer_head *);
+void nilfs_sufile_do_scrap(struct inode *, __u64, struct buffer_head *,
+ struct buffer_head *);
+void nilfs_sufile_do_free(struct inode *, __u64, struct buffer_head *,
+ struct buffer_head *);
+void nilfs_sufile_do_set_error(struct inode *, __u64, struct buffer_head *,
+ struct buffer_head *);
+
+/**
+ * nilfs_sufile_cancel_free -
+ * @sufile: inode of segment usage file
+ * @segnum: segment number
+ *
+ * Description:
+ *
+ * Return Value: On success, 0 is returned. On error, one of the following
+ * negative error codes is returned.
+ *
+ * %-EIO - I/O error.
+ *
+ * %-ENOMEM - Insufficient amount of memory available.
+ */
+static inline int nilfs_sufile_cancel_free(struct inode *sufile, __u64 segnum)
+{
+ return nilfs_sufile_update(sufile, segnum, 0,
+ nilfs_sufile_do_cancel_free);
+}
+
+/**
+ * nilfs_sufile_scrap - make a segment garbage
+ * @sufile: inode of segment usage file
+ * @segnum: segment number to be freed
+ */
+static inline int nilfs_sufile_scrap(struct inode *sufile, __u64 segnum)
+{
+ return nilfs_sufile_update(sufile, segnum, 1, nilfs_sufile_do_scrap);
+}
+
+/**
+ * nilfs_sufile_free - free segment
+ * @sufile: inode of segment usage file
+ * @segnum: segment number to be freed
+ */
+static inline int nilfs_sufile_free(struct inode *sufile, __u64 segnum)
+{
+ return nilfs_sufile_update(sufile, segnum, 0, nilfs_sufile_do_free);
+}
+
+/**
+ * nilfs_sufile_set_error - mark a segment as erroneous
+ * @sufile: inode of segment usage file
+ * @segnum: segment number
+ *
+ * Description: nilfs_sufile_set_error() marks the segment specified by
+ * @segnum as erroneous. The error segment will never be used again.
+ *
+ * Return Value: On success, 0 is returned. On error, one of the following
+ * negative error codes is returned.
+ *
+ * %-EIO - I/O error.
+ *
+ * %-ENOMEM - Insufficient amount of memory available.
+ *
+ * %-EINVAL - Invalid segment usage number.
+ */
+static inline int nilfs_sufile_set_error(struct inode *sufile, __u64 segnum)
+{
+ return nilfs_sufile_update(sufile, segnum, 0,
+ nilfs_sufile_do_set_error);
+}
#endif /* _NILFS_SUFILE_H */
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index e117e1ea9bff..7262e8427c20 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -63,9 +63,9 @@
MODULE_AUTHOR("NTT Corp.");
MODULE_DESCRIPTION("A New Implementation of the Log-structured Filesystem "
"(NILFS)");
-MODULE_VERSION(NILFS_VERSION);
MODULE_LICENSE("GPL");
+static void nilfs_write_super(struct super_block *sb);
static int nilfs_remount(struct super_block *sb, int *flags, char *data);
static int test_exclusive_mount(struct file_system_type *fs_type,
struct block_device *bdev, int flags);
@@ -316,6 +316,11 @@ static void nilfs_put_super(struct super_block *sb)
struct nilfs_sb_info *sbi = NILFS_SB(sb);
struct the_nilfs *nilfs = sbi->s_nilfs;
+ lock_kernel();
+
+ if (sb->s_dirt)
+ nilfs_write_super(sb);
+
nilfs_detach_segment_constructor(sbi);
if (!(sb->s_flags & MS_RDONLY)) {
@@ -330,6 +335,8 @@ static void nilfs_put_super(struct super_block *sb)
sbi->s_super = NULL;
sb->s_fs_info = NULL;
kfree(sbi);
+
+ unlock_kernel();
}
/**
@@ -476,11 +483,12 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
struct super_block *sb = dentry->d_sb;
struct nilfs_sb_info *sbi = NILFS_SB(sb);
+ struct the_nilfs *nilfs = sbi->s_nilfs;
+ u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
unsigned long long blocks;
unsigned long overhead;
unsigned long nrsvblocks;
sector_t nfreeblocks;
- struct the_nilfs *nilfs = sbi->s_nilfs;
int err;
/*
@@ -514,6 +522,9 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf)
buf->f_files = atomic_read(&sbi->s_inodes_count);
buf->f_ffree = 0; /* nilfs_count_free_inodes(sb); */
buf->f_namelen = NILFS_NAME_LEN;
+ buf->f_fsid.val[0] = (u32)id;
+ buf->f_fsid.val[1] = (u32)(id >> 32);
+
return 0;
}
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index 33400cf0bbe2..7f65b3be4aa9 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -115,6 +115,7 @@ void put_nilfs(struct the_nilfs *nilfs)
static int nilfs_load_super_root(struct the_nilfs *nilfs,
struct nilfs_sb_info *sbi, sector_t sr_block)
{
+ static struct lock_class_key dat_lock_key;
struct buffer_head *bh_sr;
struct nilfs_super_root *raw_sr;
struct nilfs_super_block **sbp = nilfs->ns_sbp;
@@ -163,6 +164,9 @@ static int nilfs_load_super_root(struct the_nilfs *nilfs,
if (unlikely(err))
goto failed_sufile;
+ lockdep_set_class(&NILFS_MDT(nilfs->ns_dat)->mi_sem, &dat_lock_key);
+ lockdep_set_class(&NILFS_MDT(nilfs->ns_gc_dat)->mi_sem, &dat_lock_key);
+
nilfs_mdt_set_shadow(nilfs->ns_dat, nilfs->ns_gc_dat);
nilfs_mdt_set_entry_size(nilfs->ns_cpfile, checkpoint_size,
sizeof(struct nilfs_cpfile_header));
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index bed766e435b5..1634319e2404 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -220,7 +220,7 @@ static struct inotify_kernel_event * kernel_event(s32 wd, u32 mask, u32 cookie,
rem = 0;
}
- kevent->name = kmalloc(len + rem, GFP_KERNEL);
+ kevent->name = kmalloc(len + rem, GFP_NOFS);
if (unlikely(!kevent->name)) {
kmem_cache_free(event_cachep, kevent);
return NULL;
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index f76951dcd4a6..8013eb36abc9 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -2246,6 +2246,9 @@ static void ntfs_put_super(struct super_block *sb)
ntfs_volume *vol = NTFS_SB(sb);
ntfs_debug("Entering.");
+
+ lock_kernel();
+
#ifdef NTFS_RW
/*
* Commit all inodes while they are still open in case some of them
@@ -2444,7 +2447,8 @@ static void ntfs_put_super(struct super_block *sb)
}
sb->s_fs_info = NULL;
kfree(vol);
- return;
+
+ unlock_kernel();
}
/**
diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h
index 7e72a81bc2d4..696c32e50716 100644
--- a/fs/ocfs2/cluster/masklog.h
+++ b/fs/ocfs2/cluster/masklog.h
@@ -48,34 +48,33 @@
* only emit the appropriage printk() when the caller passes in a constant
* mask, as is almost always the case.
*
- * All this bitmask nonsense is hidden from the /proc interface so that Joel
- * doesn't have an aneurism. Reading the file gives a straight forward
- * indication of which bits are on or off:
- * ENTRY off
- * EXIT off
+ * All this bitmask nonsense is managed from the files under
+ * /sys/fs/o2cb/logmask/. Reading the files gives a straightforward
+ * indication of which bits are allowed (allow) or denied (off/deny).
+ * ENTRY deny
+ * EXIT deny
* TCP off
* MSG off
* SOCKET off
- * ERROR off
- * NOTICE on
+ * ERROR allow
+ * NOTICE allow
*
* Writing changes the state of a given bit and requires a strictly formatted
* single write() call:
*
- * write(fd, "ENTRY on", 8);
+ * write(fd, "allow", 5);
*
- * would turn the entry bit on. "1" is also accepted in the place of "on", and
- * "off" and "0" behave as expected.
+ * Echoing allow/deny/off string into the logmask files can flip the bits
+ * on or off as expected; here is the bash script for example:
*
- * Some trivial shell can flip all the bits on or off:
+ * log_mask="/sys/fs/o2cb/log_mask"
+ * for node in ENTRY EXIT TCP MSG SOCKET ERROR NOTICE; do
+ * echo allow >"$log_mask"/"$node"
+ * done
*
- * log_mask="/proc/fs/ocfs2_nodemanager/log_mask"
- * cat $log_mask | (
- * while read bit status; do
- * # $1 is "on" or "off", say
- * echo "$bit $1" > $log_mask
- * done
- * )
+ * The debugfs.ocfs2 tool can also flip the bits with the -l option:
+ *
+ * debugfs.ocfs2 -l TCP allow
*/
/* for task_struct */
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c
index 7d604480557a..b574431a031d 100644
--- a/fs/ocfs2/dcache.c
+++ b/fs/ocfs2/dcache.c
@@ -290,6 +290,21 @@ out_attach:
else
mlog_errno(ret);
+ /*
+ * In case of error, manually free the allocation and do the iput().
+ * We need to do this because error here means no d_instantiate(),
+ * which means iput() will not be called during dput(dentry).
+ */
+ if (ret < 0 && !alias) {
+ ocfs2_lock_res_free(&dl->dl_lockres);
+ BUG_ON(dl->dl_count != 1);
+ spin_lock(&dentry_attach_lock);
+ dentry->d_fsdata = NULL;
+ spin_unlock(&dentry_attach_lock);
+ kfree(dl);
+ iput(inode);
+ }
+
dput(alias);
return ret;
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index e71160cda110..c5752305627c 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -2697,7 +2697,7 @@ static int ocfs2_dx_dir_index_block(struct inode *dir,
u32 *num_dx_entries,
struct buffer_head *dirent_bh)
{
- int ret, namelen, i;
+ int ret = 0, namelen, i;
char *de_buf, *limit;
struct ocfs2_dir_entry *de;
struct buffer_head *dx_leaf_bh;
@@ -2934,7 +2934,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
*/
BUG_ON(alloc > 2);
- ret = ocfs2_reserve_clusters(osb, alloc, &data_ac);
+ ret = ocfs2_reserve_clusters(osb, alloc + dx_alloc, &data_ac);
if (ret) {
mlog_errno(ret);
goto out;
diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c
index de3da8eb558c..15713cbb865c 100644
--- a/fs/ocfs2/export.c
+++ b/fs/ocfs2/export.c
@@ -100,7 +100,8 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb,
/* If the inode allocator bit is clear, this inode must be stale */
if (!set) {
- mlog(0, "inode %llu suballoc bit is clear\n", blkno);
+ mlog(0, "inode %llu suballoc bit is clear\n",
+ (unsigned long long)blkno);
status = -ESTALE;
goto unlock_nfs_sync;
}
@@ -114,7 +115,7 @@ check_err:
if (status < 0) {
if (status == -ESTALE) {
mlog(0, "stale inode ino: %llu generation: %u\n",
- blkno, handle->ih_generation);
+ (unsigned long long)blkno, handle->ih_generation);
}
result = ERR_PTR(status);
goto bail;
@@ -129,8 +130,8 @@ check_err:
check_gen:
if (handle->ih_generation != inode->i_generation) {
iput(inode);
- mlog(0, "stale inode ino: %llu generation: %u\n", blkno,
- handle->ih_generation);
+ mlog(0, "stale inode ino: %llu generation: %u\n",
+ (unsigned long long)blkno, handle->ih_generation);
result = ERR_PTR(-ESTALE);
goto bail;
}
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 8672b9536039..c2a87c885b73 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -1912,6 +1912,22 @@ out_sems:
return written ? written : ret;
}
+static int ocfs2_splice_to_file(struct pipe_inode_info *pipe,
+ struct file *out,
+ struct splice_desc *sd)
+{
+ int ret;
+
+ ret = ocfs2_prepare_inode_for_write(out->f_path.dentry, &sd->pos,
+ sd->total_len, 0, NULL);
+ if (ret < 0) {
+ mlog_errno(ret);
+ return ret;
+ }
+
+ return splice_from_pipe_feed(pipe, sd, pipe_to_file);
+}
+
static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe,
struct file *out,
loff_t *ppos,
@@ -1919,38 +1935,76 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe,
unsigned int flags)
{
int ret;
- struct inode *inode = out->f_path.dentry->d_inode;
+ 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,
+ };
mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", out, pipe,
(unsigned int)len,
out->f_path.dentry->d_name.len,
out->f_path.dentry->d_name.name);
- mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT);
+ if (pipe->inode)
+ mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_PARENT);
- ret = ocfs2_rw_lock(inode, 1);
- if (ret < 0) {
- mlog_errno(ret);
- goto out;
- }
+ splice_from_pipe_begin(&sd);
+ do {
+ ret = splice_from_pipe_next(pipe, &sd);
+ if (ret <= 0)
+ break;
- ret = ocfs2_prepare_inode_for_write(out->f_path.dentry, ppos, len, 0,
- NULL);
- if (ret < 0) {
- mlog_errno(ret);
- goto out_unlock;
- }
+ mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
+ ret = ocfs2_rw_lock(inode, 1);
+ if (ret < 0)
+ mlog_errno(ret);
+ else {
+ ret = ocfs2_splice_to_file(pipe, out, &sd);
+ ocfs2_rw_unlock(inode, 1);
+ }
+ mutex_unlock(&inode->i_mutex);
+ } while (ret > 0);
+ splice_from_pipe_end(pipe, &sd);
if (pipe->inode)
- mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_CHILD);
- ret = generic_file_splice_write_nolock(pipe, out, ppos, len, flags);
- if (pipe->inode)
mutex_unlock(&pipe->inode->i_mutex);
-out_unlock:
- ocfs2_rw_unlock(inode, 1);
-out:
- mutex_unlock(&inode->i_mutex);
+ if (sd.num_spliced)
+ ret = sd.num_spliced;
+
+ if (ret > 0) {
+ unsigned long nr_pages;
+
+ *ppos += ret;
+ nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+
+ /*
+ * If file or inode is SYNC and we actually wrote some data,
+ * sync it.
+ */
+ if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) {
+ int err;
+
+ mutex_lock(&inode->i_mutex);
+ err = ocfs2_rw_lock(inode, 1);
+ if (err < 0) {
+ mlog_errno(err);
+ } else {
+ err = generic_osync_inode(inode, mapping,
+ OSYNC_METADATA|OSYNC_DATA);
+ ocfs2_rw_unlock(inode, 1);
+ }
+ mutex_unlock(&inode->i_mutex);
+
+ if (err)
+ ret = err;
+ }
+ balance_dirty_pages_ratelimited_nr(mapping, nr_pages);
+ }
mlog_exit(ret);
return ret;
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h
index 619dd7f6c053..eb7b76331eb7 100644
--- a/fs/ocfs2/journal.h
+++ b/fs/ocfs2/journal.h
@@ -437,8 +437,9 @@ static inline int ocfs2_unlink_credits(struct super_block *sb)
}
/* dinode + orphan dir dinode + inode alloc dinode + orphan dir entry +
- * inode alloc group descriptor + orphan dir index leaf */
-#define OCFS2_DELETE_INODE_CREDITS (3 * OCFS2_INODE_UPDATE_CREDITS + 3)
+ * inode alloc group descriptor + orphan dir index root +
+ * orphan dir index leaf */
+#define OCFS2_DELETE_INODE_CREDITS (3 * OCFS2_INODE_UPDATE_CREDITS + 4)
/* dinode update, old dir dinode update, new dir dinode update, old
* dir dir entry, new dir dir entry, dir entry update for renaming
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 2220f93f668b..33464c6b60a2 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -1025,10 +1025,8 @@ static int ocfs2_rename(struct inode *old_dir,
struct inode *orphan_dir = NULL;
struct ocfs2_dinode *newfe = NULL;
char orphan_name[OCFS2_ORPHAN_NAMELEN + 1];
- struct buffer_head *orphan_entry_bh = NULL;
struct buffer_head *newfe_bh = NULL;
struct buffer_head *old_inode_bh = NULL;
- struct buffer_head *insert_entry_bh = NULL;
struct ocfs2_super *osb = NULL;
u64 newfe_blkno, old_de_ino;
handle_t *handle = NULL;
@@ -1455,8 +1453,6 @@ bail:
brelse(old_inode_bh);
brelse(old_dir_bh);
brelse(new_dir_bh);
- brelse(orphan_entry_bh);
- brelse(insert_entry_bh);
mlog_exit(status);
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index b4ca5911caaf..8439f6b324b9 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -2197,26 +2197,29 @@ static int ocfs2_get_suballoc_slot_bit(struct ocfs2_super *osb, u64 blkno,
struct buffer_head *inode_bh = NULL;
struct ocfs2_dinode *inode_fe;
- mlog_entry("blkno: %llu\n", blkno);
+ mlog_entry("blkno: %llu\n", (unsigned long long)blkno);
/* dirty read disk */
status = ocfs2_read_blocks_sync(osb, blkno, 1, &inode_bh);
if (status < 0) {
- mlog(ML_ERROR, "read block %llu failed %d\n", blkno, status);
+ mlog(ML_ERROR, "read block %llu failed %d\n",
+ (unsigned long long)blkno, status);
goto bail;
}
inode_fe = (struct ocfs2_dinode *) inode_bh->b_data;
if (!OCFS2_IS_VALID_DINODE(inode_fe)) {
- mlog(ML_ERROR, "invalid inode %llu requested\n", blkno);
+ mlog(ML_ERROR, "invalid inode %llu requested\n",
+ (unsigned long long)blkno);
status = -EINVAL;
goto bail;
}
- if (le16_to_cpu(inode_fe->i_suballoc_slot) != OCFS2_INVALID_SLOT &&
+ if (le16_to_cpu(inode_fe->i_suballoc_slot) != (u16)OCFS2_INVALID_SLOT &&
(u32)le16_to_cpu(inode_fe->i_suballoc_slot) > osb->max_slots - 1) {
mlog(ML_ERROR, "inode %llu has invalid suballoc slot %u\n",
- blkno, (u32)le16_to_cpu(inode_fe->i_suballoc_slot));
+ (unsigned long long)blkno,
+ (u32)le16_to_cpu(inode_fe->i_suballoc_slot));
status = -EINVAL;
goto bail;
}
@@ -2251,7 +2254,8 @@ static int ocfs2_test_suballoc_bit(struct ocfs2_super *osb,
u64 bg_blkno;
int status;
- mlog_entry("blkno: %llu bit: %u\n", blkno, (unsigned int)bit);
+ mlog_entry("blkno: %llu bit: %u\n", (unsigned long long)blkno,
+ (unsigned int)bit);
alloc_fe = (struct ocfs2_dinode *)alloc_bh->b_data;
if ((bit + 1) > ocfs2_bits_per_group(&alloc_fe->id2.i_chain)) {
@@ -2266,7 +2270,8 @@ static int ocfs2_test_suballoc_bit(struct ocfs2_super *osb,
status = ocfs2_read_group_descriptor(suballoc, alloc_fe, bg_blkno,
&group_bh);
if (status < 0) {
- mlog(ML_ERROR, "read group %llu failed %d\n", bg_blkno, status);
+ mlog(ML_ERROR, "read group %llu failed %d\n",
+ (unsigned long long)bg_blkno, status);
goto bail;
}
@@ -2300,7 +2305,7 @@ int ocfs2_test_inode_bit(struct ocfs2_super *osb, u64 blkno, int *res)
struct inode *inode_alloc_inode;
struct buffer_head *alloc_bh = NULL;
- mlog_entry("blkno: %llu", blkno);
+ mlog_entry("blkno: %llu", (unsigned long long)blkno);
status = ocfs2_get_suballoc_slot_bit(osb, blkno, &suballoc_slot,
&suballoc_bit);
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 79ff8d9d37e0..4a79de13b663 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -126,7 +126,6 @@ static int ocfs2_get_sector(struct super_block *sb,
struct buffer_head **bh,
int block,
int sect_size);
-static void ocfs2_write_super(struct super_block *sb);
static struct inode *ocfs2_alloc_inode(struct super_block *sb);
static void ocfs2_destroy_inode(struct inode *inode);
static int ocfs2_susp_quotas(struct ocfs2_super *osb, int unsuspend);
@@ -141,7 +140,6 @@ static const struct super_operations ocfs2_sops = {
.clear_inode = ocfs2_clear_inode,
.delete_inode = ocfs2_delete_inode,
.sync_fs = ocfs2_sync_fs,
- .write_super = ocfs2_write_super,
.put_super = ocfs2_put_super,
.remount_fs = ocfs2_remount,
.show_options = ocfs2_show_options,
@@ -365,24 +363,12 @@ static struct file_operations ocfs2_osb_debug_fops = {
.llseek = generic_file_llseek,
};
-/*
- * write_super and sync_fs ripped right out of ext3.
- */
-static void ocfs2_write_super(struct super_block *sb)
-{
- if (mutex_trylock(&sb->s_lock) != 0)
- BUG();
- sb->s_dirt = 0;
-}
-
static int ocfs2_sync_fs(struct super_block *sb, int wait)
{
int status;
tid_t target;
struct ocfs2_super *osb = OCFS2_SB(sb);
- sb->s_dirt = 0;
-
if (ocfs2_is_hard_readonly(osb))
return -EROFS;
@@ -1550,9 +1536,13 @@ static void ocfs2_put_super(struct super_block *sb)
{
mlog_entry("(0x%p)\n", sb);
+ lock_kernel();
+
ocfs2_sync_blockdev(sb);
ocfs2_dismount_volume(sb, 0);
+ unlock_kernel();
+
mlog_exit_void();
}
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c
index ed0a0cfd68d2..579dd1b1110f 100644
--- a/fs/ocfs2/symlink.c
+++ b/fs/ocfs2/symlink.c
@@ -39,6 +39,7 @@
#include <linux/slab.h>
#include <linux/pagemap.h>
#include <linux/utsname.h>
+#include <linux/namei.h>
#define MLOG_MASK_PREFIX ML_NAMEI
#include <cluster/masklog.h>
@@ -54,26 +55,6 @@
#include "buffer_head_io.h"
-static char *ocfs2_page_getlink(struct dentry * dentry,
- struct page **ppage);
-static char *ocfs2_fast_symlink_getlink(struct inode *inode,
- struct buffer_head **bh);
-
-/* get the link contents into pagecache */
-static char *ocfs2_page_getlink(struct dentry * dentry,
- struct page **ppage)
-{
- struct page * page;
- struct address_space *mapping = dentry->d_inode->i_mapping;
- page = read_mapping_page(mapping, 0, NULL);
- if (IS_ERR(page))
- goto sync_fail;
- *ppage = page;
- return kmap(page);
-
-sync_fail:
- return (char*)page;
-}
static char *ocfs2_fast_symlink_getlink(struct inode *inode,
struct buffer_head **bh)
@@ -128,40 +109,55 @@ out:
return ret;
}
-static void *ocfs2_follow_link(struct dentry *dentry,
- struct nameidata *nd)
+static void *ocfs2_fast_follow_link(struct dentry *dentry,
+ struct nameidata *nd)
{
- int status;
- char *link;
+ int status = 0;
+ int len;
+ char *target, *link = ERR_PTR(-ENOMEM);
struct inode *inode = dentry->d_inode;
- struct page *page = NULL;
struct buffer_head *bh = NULL;
-
- if (ocfs2_inode_is_fast_symlink(inode))
- link = ocfs2_fast_symlink_getlink(inode, &bh);
- else
- link = ocfs2_page_getlink(dentry, &page);
- if (IS_ERR(link)) {
- status = PTR_ERR(link);
+
+ mlog_entry_void();
+
+ BUG_ON(!ocfs2_inode_is_fast_symlink(inode));
+ target = ocfs2_fast_symlink_getlink(inode, &bh);
+ if (IS_ERR(target)) {
+ status = PTR_ERR(target);
mlog_errno(status);
goto bail;
}
- status = vfs_follow_link(nd, link);
+ /* Fast symlinks can't be large */
+ len = strlen(target);
+ link = kzalloc(len + 1, GFP_NOFS);
+ if (!link) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ memcpy(link, target, len);
+ nd_set_link(nd, link);
bail:
- if (page) {
- kunmap(page);
- page_cache_release(page);
- }
brelse(bh);
- return ERR_PTR(status);
+ mlog_exit(status);
+ return status ? ERR_PTR(status) : link;
+}
+
+static void ocfs2_fast_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
+{
+ char *link = cookie;
+
+ kfree(link);
}
const struct inode_operations ocfs2_symlink_inode_operations = {
.readlink = page_readlink,
- .follow_link = ocfs2_follow_link,
+ .follow_link = page_follow_link_light,
+ .put_link = page_put_link,
.getattr = ocfs2_getattr,
.setattr = ocfs2_setattr,
.setxattr = generic_setxattr,
@@ -171,7 +167,8 @@ const struct inode_operations ocfs2_symlink_inode_operations = {
};
const struct inode_operations ocfs2_fast_symlink_inode_operations = {
.readlink = ocfs2_readlink,
- .follow_link = ocfs2_follow_link,
+ .follow_link = ocfs2_fast_follow_link,
+ .put_link = ocfs2_fast_put_link,
.getattr = ocfs2_getattr,
.setattr = ocfs2_setattr,
.setxattr = generic_setxattr,
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 15631019dc63..ba320e250747 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -3154,7 +3154,7 @@ static int ocfs2_iterate_xattr_buckets(struct inode *inode,
le32_to_cpu(bucket_xh(bucket)->xh_entries[0].xe_name_hash));
if (func) {
ret = func(inode, bucket, para);
- if (ret)
+ if (ret && ret != -ERANGE)
mlog_errno(ret);
/* Fall through to bucket_relse() */
}
@@ -3261,7 +3261,8 @@ static int ocfs2_xattr_tree_list_index_block(struct inode *inode,
ocfs2_list_xattr_bucket,
&xl);
if (ret) {
- mlog_errno(ret);
+ if (ret != -ERANGE)
+ mlog_errno(ret);
goto out;
}
diff --git a/fs/open.c b/fs/open.c
index 377eb25b6abf..7200e23d9258 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -612,7 +612,7 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode)
audit_inode(NULL, dentry);
- err = mnt_want_write(file->f_path.mnt);
+ err = mnt_want_write_file(file);
if (err)
goto out_putf;
mutex_lock(&inode->i_mutex);
@@ -761,7 +761,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
if (!file)
goto out;
- error = mnt_want_write(file->f_path.mnt);
+ error = mnt_want_write_file(file);
if (error)
goto out_fput;
dentry = file->f_path.dentry;
@@ -1033,7 +1033,7 @@ long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
if (!IS_ERR(tmp)) {
fd = get_unused_fd_flags(flags);
if (fd >= 0) {
- struct file *f = do_filp_open(dfd, tmp, flags, mode);
+ struct file *f = do_filp_open(dfd, tmp, flags, mode, 0);
if (IS_ERR(f)) {
put_unused_fd(fd);
fd = PTR_ERR(f);
diff --git a/fs/pipe.c b/fs/pipe.c
index 4af7aa521813..13414ec45b8d 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -37,6 +37,42 @@
* -- Manfred Spraul <manfred@colorfullife.com> 2002-05-09
*/
+static void pipe_lock_nested(struct pipe_inode_info *pipe, int subclass)
+{
+ if (pipe->inode)
+ mutex_lock_nested(&pipe->inode->i_mutex, subclass);
+}
+
+void pipe_lock(struct pipe_inode_info *pipe)
+{
+ /*
+ * pipe_lock() nests non-pipe inode locks (for writing to a file)
+ */
+ pipe_lock_nested(pipe, I_MUTEX_PARENT);
+}
+EXPORT_SYMBOL(pipe_lock);
+
+void pipe_unlock(struct pipe_inode_info *pipe)
+{
+ if (pipe->inode)
+ mutex_unlock(&pipe->inode->i_mutex);
+}
+EXPORT_SYMBOL(pipe_unlock);
+
+void pipe_double_lock(struct pipe_inode_info *pipe1,
+ struct pipe_inode_info *pipe2)
+{
+ BUG_ON(pipe1 == pipe2);
+
+ if (pipe1 < pipe2) {
+ pipe_lock_nested(pipe1, I_MUTEX_PARENT);
+ pipe_lock_nested(pipe2, I_MUTEX_CHILD);
+ } else {
+ pipe_lock_nested(pipe2, I_MUTEX_CHILD);
+ pipe_lock_nested(pipe1, I_MUTEX_PARENT);
+ }
+}
+
/* Drop the inode semaphore and wait for a pipe event, atomically */
void pipe_wait(struct pipe_inode_info *pipe)
{
@@ -47,12 +83,10 @@ void pipe_wait(struct pipe_inode_info *pipe)
* is considered a noninteractive wait:
*/
prepare_to_wait(&pipe->wait, &wait, TASK_INTERRUPTIBLE);
- if (pipe->inode)
- mutex_unlock(&pipe->inode->i_mutex);
+ pipe_unlock(pipe);
schedule();
finish_wait(&pipe->wait, &wait);
- if (pipe->inode)
- mutex_lock(&pipe->inode->i_mutex);
+ pipe_lock(pipe);
}
static int
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 7e4877d9dcb5..725a650bbbb8 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -80,6 +80,7 @@
#include <linux/delayacct.h>
#include <linux/seq_file.h>
#include <linux/pid_namespace.h>
+#include <linux/ptrace.h>
#include <linux/tracehook.h>
#include <asm/pgtable.h>
@@ -352,6 +353,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
char state;
pid_t ppid = 0, pgid = -1, sid = -1;
int num_threads = 0;
+ int permitted;
struct mm_struct *mm;
unsigned long long start_time;
unsigned long cmin_flt = 0, cmaj_flt = 0;
@@ -364,11 +366,14 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
state = *get_task_state(task);
vsize = eip = esp = 0;
+ permitted = ptrace_may_access(task, PTRACE_MODE_READ);
mm = get_task_mm(task);
if (mm) {
vsize = task_vsize(mm);
- eip = KSTK_EIP(task);
- esp = KSTK_ESP(task);
+ if (permitted) {
+ eip = KSTK_EIP(task);
+ esp = KSTK_ESP(task);
+ }
}
get_task_comm(tcomm, task);
@@ -424,7 +429,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
unlock_task_sighand(task, &flags);
}
- if (!whole || num_threads < 2)
+ if (permitted && (!whole || num_threads < 2))
wchan = get_wchan(task);
if (!whole) {
min_flt = task->min_flt;
@@ -476,7 +481,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
rsslim,
mm ? mm->start_code : 0,
mm ? mm->end_code : 0,
- mm ? mm->start_stack : 0,
+ (permitted && mm) ? mm->start_stack : 0,
esp,
eip,
/* The signal information here is obsolete.
diff --git a/fs/proc/base.c b/fs/proc/base.c
index f71559784bfb..23342e188a66 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -322,7 +322,10 @@ static int proc_pid_wchan(struct task_struct *task, char *buffer)
wchan = get_wchan(task);
if (lookup_symbol_name(wchan, symname) < 0)
- return sprintf(buffer, "%lu", wchan);
+ if (!ptrace_may_access(task, PTRACE_MODE_READ))
+ return 0;
+ else
+ return sprintf(buffer, "%lu", wchan);
else
return sprintf(buffer, "%s", symname);
}
@@ -648,14 +651,14 @@ static unsigned mounts_poll(struct file *file, poll_table *wait)
{
struct proc_mounts *p = file->private_data;
struct mnt_namespace *ns = p->ns;
- unsigned res = 0;
+ unsigned res = POLLIN | POLLRDNORM;
poll_wait(file, &ns->poll, wait);
spin_lock(&vfsmount_lock);
if (p->event != ns->event) {
p->event = ns->event;
- res = POLLERR;
+ res |= POLLERR | POLLPRI;
}
spin_unlock(&vfsmount_lock);
@@ -2125,9 +2128,15 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
if (copy_from_user(page, buf, count))
goto out_free;
+ /* Guard against adverse ptrace interaction */
+ length = mutex_lock_interruptible(&task->cred_guard_mutex);
+ if (length < 0)
+ goto out_free;
+
length = security_setprocattr(task,
(char*)file->f_path.dentry->d_name.name,
(void*)page, count);
+ mutex_unlock(&task->cred_guard_mutex);
out_free:
free_page((unsigned long) page);
out:
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index f6db9618a888..753ca37002c8 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -92,3 +92,28 @@ struct pde_opener {
struct list_head lh;
};
void pde_users_dec(struct proc_dir_entry *pde);
+
+extern spinlock_t proc_subdir_lock;
+
+struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *);
+int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir);
+unsigned long task_vsize(struct mm_struct *);
+int task_statm(struct mm_struct *, int *, int *, int *, int *);
+void task_mem(struct seq_file *, struct mm_struct *);
+
+struct proc_dir_entry *de_get(struct proc_dir_entry *de);
+void de_put(struct proc_dir_entry *de);
+
+extern struct vfsmount *proc_mnt;
+int proc_fill_super(struct super_block *);
+struct inode *proc_get_inode(struct super_block *, unsigned int, struct proc_dir_entry *);
+
+/*
+ * These are generic /proc routines that use the internal
+ * "struct proc_dir_entry" tree to traverse the filesystem.
+ *
+ * The /proc root directory has extended versions to take care
+ * of the /proc/<pid> subdirectories.
+ */
+int proc_readdir(struct file *, void *, filldir_t);
+struct dentry *proc_lookup(struct inode *, struct dentry *, struct nameidata *);
diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c
index 74ea974f5ca6..c6b0302af4c4 100644
--- a/fs/proc/meminfo.c
+++ b/fs/proc/meminfo.c
@@ -35,7 +35,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
#define K(x) ((x) << (PAGE_SHIFT - 10))
si_meminfo(&i);
si_swapinfo(&i);
- committed = atomic_long_read(&vm_committed_space);
+ committed = percpu_counter_read_positive(&vm_committed_as);
allowed = ((totalram_pages - hugetlb_total_pages())
* sysctl_overcommit_ratio / 100) + total_swap_pages;
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index de2bba5a3440..fc6c3025befd 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -11,6 +11,7 @@
#include <linux/string.h>
#include <asm/prom.h>
#include <asm/uaccess.h>
+#include "internal.h"
#ifndef HAVE_ARCH_DEVTREE_FIXUPS
static inline void set_node_proc_entry(struct device_node *np,
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 1e15a2b176e8..b080b791d9e3 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -67,8 +67,7 @@ static int proc_get_sb(struct file_system_type *fs_type,
sb->s_flags = flags;
err = proc_fill_super(sb);
if (err) {
- up_write(&sb->s_umount);
- deactivate_super(sb);
+ deactivate_locked_super(sb);
return err;
}
diff --git a/fs/proc/stat.c b/fs/proc/stat.c
index f75efa22df5e..81e4eb60972e 100644
--- a/fs/proc/stat.c
+++ b/fs/proc/stat.c
@@ -18,6 +18,9 @@
#ifndef arch_irq_stat
#define arch_irq_stat() 0
#endif
+#ifndef arch_idle_time
+#define arch_idle_time(cpu) 0
+#endif
static int show_stat(struct seq_file *p, void *v)
{
@@ -40,6 +43,7 @@ static int show_stat(struct seq_file *p, void *v)
nice = cputime64_add(nice, kstat_cpu(i).cpustat.nice);
system = cputime64_add(system, kstat_cpu(i).cpustat.system);
idle = cputime64_add(idle, kstat_cpu(i).cpustat.idle);
+ idle = cputime64_add(idle, arch_idle_time(i));
iowait = cputime64_add(iowait, kstat_cpu(i).cpustat.iowait);
irq = cputime64_add(irq, kstat_cpu(i).cpustat.irq);
softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq);
@@ -69,6 +73,7 @@ static int show_stat(struct seq_file *p, void *v)
nice = kstat_cpu(i).cpustat.nice;
system = kstat_cpu(i).cpustat.system;
idle = kstat_cpu(i).cpustat.idle;
+ idle = cputime64_add(idle, arch_idle_time(i));
iowait = kstat_cpu(i).cpustat.iowait;
irq = kstat_cpu(i).cpustat.irq;
softirq = kstat_cpu(i).cpustat.softirq;
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 39e4ad4f59f4..6f61b7cc32e0 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -665,6 +665,10 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
goto out_task;
ret = 0;
+
+ if (!count)
+ goto out_task;
+
mm = get_task_mm(task);
if (!mm)
goto out_task;
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index fe1f0f31d11c..95c12fc613f1 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -70,14 +70,6 @@ static void qnx4_delete_inode(struct inode *inode)
unlock_kernel();
}
-static void qnx4_write_super(struct super_block *sb)
-{
- lock_kernel();
- QNX4DEBUG(("qnx4: write_super\n"));
- sb->s_dirt = 0;
- unlock_kernel();
-}
-
static int qnx4_write_inode(struct inode *inode, int unused)
{
struct qnx4_inode_entry *raw_inode;
@@ -138,7 +130,6 @@ static const struct super_operations qnx4_sops =
#ifdef CONFIG_QNX4FS_RW
.write_inode = qnx4_write_inode,
.delete_inode = qnx4_delete_inode,
- .write_super = qnx4_write_super,
#endif
};
diff --git a/fs/quota/Makefile b/fs/quota/Makefile
index 385a0831cc99..68d4f6dc0578 100644
--- a/fs/quota/Makefile
+++ b/fs/quota/Makefile
@@ -1,12 +1,3 @@
-#
-# Makefile for the Linux filesystems.
-#
-# 14 Sep 2000, Christoph Hellwig <hch@infradead.org>
-# Rewritten to use lists instead of if-statements.
-#
-
-obj-y :=
-
obj-$(CONFIG_QUOTA) += dquot.o
obj-$(CONFIG_QFMT_V1) += quota_v1.o
obj-$(CONFIG_QFMT_V2) += quota_v2.o
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index b7f5a468f076..95c5b42384b2 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -159,10 +159,14 @@ static int check_quotactl_valid(struct super_block *sb, int type, int cmd,
return error;
}
-static void quota_sync_sb(struct super_block *sb, int type)
+#ifdef CONFIG_QUOTA
+void sync_quota_sb(struct super_block *sb, int type)
{
int cnt;
+ if (!sb->s_qcop->quota_sync)
+ return;
+
sb->s_qcop->quota_sync(sb, type);
if (sb_dqopt(sb)->flags & DQUOT_QUOTA_SYS_FILE)
@@ -191,17 +195,13 @@ static void quota_sync_sb(struct super_block *sb, int type)
}
mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
}
+#endif
-void sync_dquots(struct super_block *sb, int type)
+static void sync_dquots(int type)
{
+ struct super_block *sb;
int cnt;
- if (sb) {
- if (sb->s_qcop->quota_sync)
- quota_sync_sb(sb, type);
- return;
- }
-
spin_lock(&sb_lock);
restart:
list_for_each_entry(sb, &super_blocks, s_list) {
@@ -222,8 +222,8 @@ restart:
sb->s_count++;
spin_unlock(&sb_lock);
down_read(&sb->s_umount);
- if (sb->s_root && sb->s_qcop->quota_sync)
- quota_sync_sb(sb, type);
+ if (sb->s_root)
+ sync_quota_sb(sb, type);
up_read(&sb->s_umount);
spin_lock(&sb_lock);
if (__put_super_and_need_restart(sb))
@@ -301,7 +301,10 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
return sb->s_qcop->set_dqblk(sb, type, id, &idq);
}
case Q_SYNC:
- sync_dquots(sb, type);
+ if (sb)
+ sync_quota_sb(sb, type);
+ else
+ sync_dquots(type);
return 0;
case Q_XQUOTAON:
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c
index 67a80d7e59e2..45ee3d357c70 100644
--- a/fs/reiserfs/dir.c
+++ b/fs/reiserfs/dir.c
@@ -41,6 +41,18 @@ static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry,
#define store_ih(where,what) copy_item_head (where, what)
+static inline bool is_privroot_deh(struct dentry *dir,
+ struct reiserfs_de_head *deh)
+{
+ int ret = 0;
+#ifdef CONFIG_REISERFS_FS_XATTR
+ struct dentry *privroot = REISERFS_SB(dir->d_sb)->priv_root;
+ ret = (dir == dir->d_parent && privroot->d_inode &&
+ deh->deh_objectid == INODE_PKEY(privroot->d_inode)->k_objectid);
+#endif
+ return ret;
+}
+
int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent,
filldir_t filldir, loff_t *pos)
{
@@ -138,18 +150,8 @@ int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent,
}
/* Ignore the .reiserfs_priv entry */
- if (reiserfs_xattrs(inode->i_sb) &&
- !old_format_only(inode->i_sb) &&
- dentry == inode->i_sb->s_root &&
- REISERFS_SB(inode->i_sb)->priv_root &&
- REISERFS_SB(inode->i_sb)->priv_root->d_inode
- && deh_objectid(deh) ==
- le32_to_cpu(INODE_PKEY
- (REISERFS_SB(inode->i_sb)->
- priv_root->d_inode)->
- k_objectid)) {
+ if (is_privroot_deh(dentry, deh))
continue;
- }
d_off = deh_offset(deh);
*pos = d_off;
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index efd4d720718e..271579128634 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -338,21 +338,8 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
&path_to_entry, &de);
pathrelse(&path_to_entry);
if (retval == NAME_FOUND) {
- /* Hide the .reiserfs_priv directory */
- if (reiserfs_xattrs(dir->i_sb) &&
- !old_format_only(dir->i_sb) &&
- REISERFS_SB(dir->i_sb)->priv_root &&
- REISERFS_SB(dir->i_sb)->priv_root->d_inode &&
- de.de_objectid ==
- le32_to_cpu(INODE_PKEY
- (REISERFS_SB(dir->i_sb)->priv_root->d_inode)->
- k_objectid)) {
- reiserfs_write_unlock(dir->i_sb);
- return ERR_PTR(-EACCES);
- }
-
- inode =
- reiserfs_iget(dir->i_sb, (struct cpu_key *)&(de.de_dir_id));
+ inode = reiserfs_iget(dir->i_sb,
+ (struct cpu_key *)&(de.de_dir_id));
if (!inode || IS_ERR(inode)) {
reiserfs_write_unlock(dir->i_sb);
return ERR_PTR(-EACCES);
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 0ae6486d9046..83a25710e855 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -64,18 +64,15 @@ static int reiserfs_statfs(struct dentry *dentry, struct kstatfs *buf);
static int reiserfs_sync_fs(struct super_block *s, int wait)
{
- if (!(s->s_flags & MS_RDONLY)) {
- struct reiserfs_transaction_handle th;
- reiserfs_write_lock(s);
- if (!journal_begin(&th, s, 1))
- if (!journal_end_sync(&th, s, 1))
- reiserfs_flush_old_commits(s);
- s->s_dirt = 0; /* Even if it's not true.
- * We'll loop forever in sync_supers otherwise */
- reiserfs_write_unlock(s);
- } else {
- s->s_dirt = 0;
- }
+ struct reiserfs_transaction_handle th;
+
+ reiserfs_write_lock(s);
+ if (!journal_begin(&th, s, 1))
+ if (!journal_end_sync(&th, s, 1))
+ reiserfs_flush_old_commits(s);
+ s->s_dirt = 0; /* Even if it's not true.
+ * We'll loop forever in sync_supers otherwise */
+ reiserfs_write_unlock(s);
return 0;
}
@@ -470,6 +467,11 @@ static void reiserfs_put_super(struct super_block *s)
struct reiserfs_transaction_handle th;
th.t_trans_id = 0;
+ lock_kernel();
+
+ if (s->s_dirt)
+ reiserfs_write_super(s);
+
/* change file system state to current state if it was mounted with read-write permissions */
if (!(s->s_flags & MS_RDONLY)) {
if (!journal_begin(&th, s, 10)) {
@@ -502,7 +504,7 @@ static void reiserfs_put_super(struct super_block *s)
kfree(s->s_fs_info);
s->s_fs_info = NULL;
- return;
+ unlock_kernel();
}
static struct kmem_cache *reiserfs_inode_cachep;
@@ -1316,8 +1318,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
}
out_ok:
- kfree(s->s_options);
- s->s_options = new_opts;
+ replace_mount_options(s, new_opts);
return 0;
out_err:
@@ -1842,7 +1843,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
goto error;
}
- if ((errval = reiserfs_xattr_init(s, s->s_flags))) {
+ if ((errval = reiserfs_lookup_privroot(s)) ||
+ (errval = reiserfs_xattr_init(s, s->s_flags))) {
dput(s->s_root);
s->s_root = NULL;
goto error;
@@ -1855,7 +1857,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
reiserfs_info(s, "using 3.5.x disk format\n");
}
- if ((errval = reiserfs_xattr_init(s, s->s_flags))) {
+ if ((errval = reiserfs_lookup_privroot(s)) ||
+ (errval = reiserfs_xattr_init(s, s->s_flags))) {
dput(s->s_root);
s->s_root = NULL;
goto error;
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index f83f52bae390..2237e10c7c7c 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -113,41 +113,28 @@ static int xattr_rmdir(struct inode *dir, struct dentry *dentry)
#define xattr_may_create(flags) (!flags || flags & XATTR_CREATE)
-/* Returns and possibly creates the xattr dir. */
-static struct dentry *lookup_or_create_dir(struct dentry *parent,
- const char *name, int flags)
+static struct dentry *open_xa_root(struct super_block *sb, int flags)
{
- struct dentry *dentry;
- BUG_ON(!parent);
+ struct dentry *privroot = REISERFS_SB(sb)->priv_root;
+ struct dentry *xaroot;
+ if (!privroot->d_inode)
+ return ERR_PTR(-ENODATA);
- dentry = lookup_one_len(name, parent, strlen(name));
- if (IS_ERR(dentry))
- return dentry;
- else if (!dentry->d_inode) {
- int err = -ENODATA;
-
- if (xattr_may_create(flags)) {
- mutex_lock_nested(&parent->d_inode->i_mutex,
- I_MUTEX_XATTR);
- err = xattr_mkdir(parent->d_inode, dentry, 0700);
- mutex_unlock(&parent->d_inode->i_mutex);
- }
+ mutex_lock_nested(&privroot->d_inode->i_mutex, I_MUTEX_XATTR);
+ xaroot = dget(REISERFS_SB(sb)->xattr_root);
+ if (!xaroot->d_inode) {
+ int err = -ENODATA;
+ if (xattr_may_create(flags))
+ err = xattr_mkdir(privroot->d_inode, xaroot, 0700);
if (err) {
- dput(dentry);
- dentry = ERR_PTR(err);
+ dput(xaroot);
+ xaroot = ERR_PTR(err);
}
}
- return dentry;
-}
-
-static struct dentry *open_xa_root(struct super_block *sb, int flags)
-{
- struct dentry *privroot = REISERFS_SB(sb)->priv_root;
- if (!privroot)
- return ERR_PTR(-ENODATA);
- return lookup_or_create_dir(privroot, XAROOT_NAME, flags);
+ mutex_unlock(&privroot->d_inode->i_mutex);
+ return xaroot;
}
static struct dentry *open_xa_dir(const struct inode *inode, int flags)
@@ -163,10 +150,22 @@ static struct dentry *open_xa_dir(const struct inode *inode, int flags)
le32_to_cpu(INODE_PKEY(inode)->k_objectid),
inode->i_generation);
- xadir = lookup_or_create_dir(xaroot, namebuf, flags);
+ mutex_lock_nested(&xaroot->d_inode->i_mutex, I_MUTEX_XATTR);
+
+ xadir = lookup_one_len(namebuf, xaroot, strlen(namebuf));
+ if (!IS_ERR(xadir) && !xadir->d_inode) {
+ int err = -ENODATA;
+ if (xattr_may_create(flags))
+ err = xattr_mkdir(xaroot->d_inode, xadir, 0700);
+ if (err) {
+ dput(xadir);
+ xadir = ERR_PTR(err);
+ }
+ }
+
+ mutex_unlock(&xaroot->d_inode->i_mutex);
dput(xaroot);
return xadir;
-
}
/* The following are side effects of other operations that aren't explicitly
@@ -184,6 +183,7 @@ fill_with_dentries(void *buf, const char *name, int namelen, loff_t offset,
{
struct reiserfs_dentry_buf *dbuf = buf;
struct dentry *dentry;
+ WARN_ON_ONCE(!mutex_is_locked(&dbuf->xadir->d_inode->i_mutex));
if (dbuf->count == ARRAY_SIZE(dbuf->dentries))
return -ENOSPC;
@@ -349,6 +349,7 @@ static struct dentry *xattr_lookup(struct inode *inode, const char *name,
if (IS_ERR(xadir))
return ERR_CAST(xadir);
+ mutex_lock_nested(&xadir->d_inode->i_mutex, I_MUTEX_XATTR);
xafile = lookup_one_len(name, xadir, strlen(name));
if (IS_ERR(xafile)) {
err = PTR_ERR(xafile);
@@ -360,18 +361,15 @@ static struct dentry *xattr_lookup(struct inode *inode, const char *name,
if (!xafile->d_inode) {
err = -ENODATA;
- if (xattr_may_create(flags)) {
- mutex_lock_nested(&xadir->d_inode->i_mutex,
- I_MUTEX_XATTR);
+ if (xattr_may_create(flags))
err = xattr_create(xadir->d_inode, xafile,
0700|S_IFREG);
- mutex_unlock(&xadir->d_inode->i_mutex);
- }
}
if (err)
dput(xafile);
out:
+ mutex_unlock(&xadir->d_inode->i_mutex);
dput(xadir);
if (err)
return ERR_PTR(err);
@@ -435,6 +433,7 @@ static int lookup_and_delete_xattr(struct inode *inode, const char *name)
if (IS_ERR(xadir))
return PTR_ERR(xadir);
+ mutex_lock_nested(&xadir->d_inode->i_mutex, I_MUTEX_XATTR);
dentry = lookup_one_len(name, xadir, strlen(name));
if (IS_ERR(dentry)) {
err = PTR_ERR(dentry);
@@ -442,14 +441,13 @@ static int lookup_and_delete_xattr(struct inode *inode, const char *name)
}
if (dentry->d_inode) {
- mutex_lock_nested(&xadir->d_inode->i_mutex, I_MUTEX_XATTR);
err = xattr_unlink(xadir->d_inode, dentry);
- mutex_unlock(&xadir->d_inode->i_mutex);
update_ctime(inode);
}
dput(dentry);
out_dput:
+ mutex_unlock(&xadir->d_inode->i_mutex);
dput(xadir);
return err;
}
@@ -843,7 +841,7 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size)
if (!dentry->d_inode)
return -EINVAL;
- if (!reiserfs_xattrs(dentry->d_sb) ||
+ if (!dentry->d_sb->s_xattr ||
get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
return -EOPNOTSUPP;
@@ -906,19 +904,22 @@ static int create_privroot(struct dentry *dentry)
{
int err;
struct inode *inode = dentry->d_parent->d_inode;
- mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR);
+ WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex));
+
err = xattr_mkdir(inode, dentry, 0700);
- mutex_unlock(&inode->i_mutex);
- if (err) {
- dput(dentry);
- dentry = NULL;
+ if (err || !dentry->d_inode) {
+ reiserfs_warning(dentry->d_sb, "jdm-20006",
+ "xattrs/ACLs enabled and couldn't "
+ "find/create .reiserfs_priv. "
+ "Failing mount.");
+ return -EOPNOTSUPP;
}
- if (dentry && dentry->d_inode)
- reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr "
- "storage.\n", PRIVROOT_NAME);
+ dentry->d_inode->i_flags |= S_PRIVATE;
+ reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr "
+ "storage.\n", PRIVROOT_NAME);
- return err;
+ return 0;
}
static int xattr_mount_check(struct super_block *s)
@@ -950,11 +951,9 @@ static int
xattr_lookup_poison(struct dentry *dentry, struct qstr *q1, struct qstr *name)
{
struct dentry *priv_root = REISERFS_SB(dentry->d_sb)->priv_root;
- if (name->len == priv_root->d_name.len &&
- name->hash == priv_root->d_name.hash &&
- !memcmp(name->name, priv_root->d_name.name, name->len)) {
+ if (container_of(q1, struct dentry, d_name) == priv_root)
return -ENOENT;
- } else if (q1->len == name->len &&
+ if (q1->len == name->len &&
!memcmp(q1->name, name->name, name->len))
return 0;
return 1;
@@ -964,59 +963,60 @@ static const struct dentry_operations xattr_lookup_poison_ops = {
.d_compare = xattr_lookup_poison,
};
+int reiserfs_lookup_privroot(struct super_block *s)
+{
+ struct dentry *dentry;
+ int err = 0;
+
+ /* If we don't have the privroot located yet - go find it */
+ mutex_lock(&s->s_root->d_inode->i_mutex);
+ dentry = lookup_one_len(PRIVROOT_NAME, s->s_root,
+ strlen(PRIVROOT_NAME));
+ if (!IS_ERR(dentry)) {
+ REISERFS_SB(s)->priv_root = dentry;
+ s->s_root->d_op = &xattr_lookup_poison_ops;
+ if (dentry->d_inode)
+ dentry->d_inode->i_flags |= S_PRIVATE;
+ } else
+ err = PTR_ERR(dentry);
+ mutex_unlock(&s->s_root->d_inode->i_mutex);
+
+ return err;
+}
+
/* We need to take a copy of the mount flags since things like
* MS_RDONLY don't get set until *after* we're called.
* mount_flags != mount_options */
int reiserfs_xattr_init(struct super_block *s, int mount_flags)
{
int err = 0;
+ struct dentry *privroot = REISERFS_SB(s)->priv_root;
#ifdef CONFIG_REISERFS_FS_XATTR
err = xattr_mount_check(s);
if (err)
goto error;
-#endif
- /* If we don't have the privroot located yet - go find it */
- if (!REISERFS_SB(s)->priv_root) {
- struct dentry *dentry;
- dentry = lookup_one_len(PRIVROOT_NAME, s->s_root,
- strlen(PRIVROOT_NAME));
- if (!IS_ERR(dentry)) {
-#ifdef CONFIG_REISERFS_FS_XATTR
- if (!(mount_flags & MS_RDONLY) && !dentry->d_inode)
- err = create_privroot(dentry);
-#endif
- if (!dentry->d_inode) {
- dput(dentry);
- dentry = NULL;
- }
- } else
- err = PTR_ERR(dentry);
-
- if (!err && dentry) {
- s->s_root->d_op = &xattr_lookup_poison_ops;
- dentry->d_inode->i_flags |= S_PRIVATE;
- REISERFS_SB(s)->priv_root = dentry;
-#ifdef CONFIG_REISERFS_FS_XATTR
- /* xattrs are unavailable */
- } else if (!(mount_flags & MS_RDONLY)) {
- /* If we're read-only it just means that the dir
- * hasn't been created. Not an error -- just no
- * xattrs on the fs. We'll check again if we
- * go read-write */
- reiserfs_warning(s, "jdm-20006",
- "xattrs/ACLs enabled and couldn't "
- "find/create .reiserfs_priv. "
- "Failing mount.");
- err = -EOPNOTSUPP;
-#endif
- }
+ if (!privroot->d_inode && !(mount_flags & MS_RDONLY)) {
+ mutex_lock(&s->s_root->d_inode->i_mutex);
+ err = create_privroot(REISERFS_SB(s)->priv_root);
+ mutex_unlock(&s->s_root->d_inode->i_mutex);
}
-#ifdef CONFIG_REISERFS_FS_XATTR
- if (!err)
+ if (privroot->d_inode) {
s->s_xattr = reiserfs_xattr_handlers;
+ mutex_lock(&privroot->d_inode->i_mutex);
+ if (!REISERFS_SB(s)->xattr_root) {
+ struct dentry *dentry;
+ dentry = lookup_one_len(XAROOT_NAME, privroot,
+ strlen(XAROOT_NAME));
+ if (!IS_ERR(dentry))
+ REISERFS_SB(s)->xattr_root = dentry;
+ else
+ err = PTR_ERR(dentry);
+ }
+ mutex_unlock(&privroot->d_inode->i_mutex);
+ }
error:
if (err) {
@@ -1026,11 +1026,12 @@ error:
#endif
/* The super_block MS_POSIXACL must mirror the (no)acl mount option. */
- s->s_flags = s->s_flags & ~MS_POSIXACL;
#ifdef CONFIG_REISERFS_FS_POSIX_ACL
if (reiserfs_posixacl(s))
s->s_flags |= MS_POSIXACL;
+ else
#endif
+ s->s_flags &= ~MS_POSIXACL;
return err;
}
diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c
index 4d3c20e787c3..a92c8792c0f6 100644
--- a/fs/reiserfs/xattr_security.c
+++ b/fs/reiserfs/xattr_security.c
@@ -55,8 +55,16 @@ int reiserfs_security_init(struct inode *dir, struct inode *inode,
struct reiserfs_security_handle *sec)
{
int blocks = 0;
- int error = security_inode_init_security(inode, dir, &sec->name,
- &sec->value, &sec->length);
+ int error;
+
+ sec->name = NULL;
+
+ /* Don't add selinux attributes on xattrs - they'll never get used */
+ if (IS_PRIVATE(dir))
+ return 0;
+
+ error = security_inode_init_security(inode, dir, &sec->name,
+ &sec->value, &sec->length);
if (error) {
if (error == -EOPNOTSUPP)
error = 0;
diff --git a/fs/romfs/internal.h b/fs/romfs/internal.h
index 06044a9dc62d..95217b830118 100644
--- a/fs/romfs/internal.h
+++ b/fs/romfs/internal.h
@@ -43,5 +43,5 @@ extern int romfs_dev_read(struct super_block *sb, unsigned long pos,
void *buf, size_t buflen);
extern ssize_t romfs_dev_strnlen(struct super_block *sb,
unsigned long pos, size_t maxlen);
-extern int romfs_dev_strncmp(struct super_block *sb, unsigned long pos,
- const char *str, size_t size);
+extern int romfs_dev_strcmp(struct super_block *sb, unsigned long pos,
+ const char *str, size_t size);
diff --git a/fs/romfs/storage.c b/fs/romfs/storage.c
index 7e3e1e12a081..b3208adf8e71 100644
--- a/fs/romfs/storage.c
+++ b/fs/romfs/storage.c
@@ -67,26 +67,35 @@ static ssize_t romfs_mtd_strnlen(struct super_block *sb,
* compare a string to one in a romfs image on MTD
* - return 1 if matched, 0 if differ, -ve if error
*/
-static int romfs_mtd_strncmp(struct super_block *sb, unsigned long pos,
- const char *str, size_t size)
+static int romfs_mtd_strcmp(struct super_block *sb, unsigned long pos,
+ const char *str, size_t size)
{
- u_char buf[16];
+ u_char buf[17];
size_t len, segment;
int ret;
- /* scan the string up to 16 bytes at a time */
+ /* scan the string up to 16 bytes at a time, and attempt to grab the
+ * trailing NUL whilst we're at it */
+ buf[0] = 0xff;
+
while (size > 0) {
- segment = min_t(size_t, size, 16);
+ segment = min_t(size_t, size + 1, 17);
ret = ROMFS_MTD_READ(sb, pos, segment, &len, buf);
if (ret < 0)
return ret;
+ len--;
if (memcmp(buf, str, len) != 0)
return 0;
+ buf[0] = buf[len];
size -= len;
pos += len;
str += len;
}
+ /* check the trailing NUL was */
+ if (buf[0])
+ return 0;
+
return 1;
}
#endif /* CONFIG_ROMFS_ON_MTD */
@@ -111,6 +120,7 @@ static int romfs_blk_read(struct super_block *sb, unsigned long pos,
return -EIO;
memcpy(buf, bh->b_data + offset, segment);
brelse(bh);
+ buf += segment;
buflen -= segment;
pos += segment;
}
@@ -154,28 +164,48 @@ static ssize_t romfs_blk_strnlen(struct super_block *sb,
* compare a string to one in a romfs image on a block device
* - return 1 if matched, 0 if differ, -ve if error
*/
-static int romfs_blk_strncmp(struct super_block *sb, unsigned long pos,
- const char *str, size_t size)
+static int romfs_blk_strcmp(struct super_block *sb, unsigned long pos,
+ const char *str, size_t size)
{
struct buffer_head *bh;
unsigned long offset;
size_t segment;
- bool x;
+ bool matched, terminated = false;
- /* scan the string up to 16 bytes at a time */
+ /* compare string up to a block at a time */
while (size > 0) {
offset = pos & (ROMBSIZE - 1);
segment = min_t(size_t, size, ROMBSIZE - offset);
bh = sb_bread(sb, pos >> ROMBSBITS);
if (!bh)
return -EIO;
- x = (memcmp(bh->b_data + offset, str, segment) != 0);
- brelse(bh);
- if (x)
- return 0;
+ matched = (memcmp(bh->b_data + offset, str, segment) == 0);
+
size -= segment;
pos += segment;
str += segment;
+ if (matched && size == 0 && offset + segment < ROMBSIZE) {
+ if (!bh->b_data[offset + segment])
+ terminated = true;
+ else
+ matched = false;
+ }
+ brelse(bh);
+ if (!matched)
+ return 0;
+ }
+
+ if (!terminated) {
+ /* the terminating NUL must be on the first byte of the next
+ * block */
+ BUG_ON((pos & (ROMBSIZE - 1)) != 0);
+ bh = sb_bread(sb, pos >> ROMBSBITS);
+ if (!bh)
+ return -EIO;
+ matched = !bh->b_data[0];
+ brelse(bh);
+ if (!matched)
+ return 0;
}
return 1;
@@ -234,10 +264,12 @@ ssize_t romfs_dev_strnlen(struct super_block *sb,
/*
* compare a string to one in romfs
+ * - the string to be compared to, str, may not be NUL-terminated; instead the
+ * string is of the specified size
* - return 1 if matched, 0 if differ, -ve if error
*/
-int romfs_dev_strncmp(struct super_block *sb, unsigned long pos,
- const char *str, size_t size)
+int romfs_dev_strcmp(struct super_block *sb, unsigned long pos,
+ const char *str, size_t size)
{
size_t limit;
@@ -246,16 +278,16 @@ int romfs_dev_strncmp(struct super_block *sb, unsigned long pos,
return -EIO;
if (size > ROMFS_MAXFN)
return -ENAMETOOLONG;
- if (size > limit - pos)
+ if (size + 1 > limit - pos)
return -EIO;
#ifdef CONFIG_ROMFS_ON_MTD
if (sb->s_mtd)
- return romfs_mtd_strncmp(sb, pos, str, size);
+ return romfs_mtd_strcmp(sb, pos, str, size);
#endif
#ifdef CONFIG_ROMFS_ON_BLOCK
if (sb->s_bdev)
- return romfs_blk_strncmp(sb, pos, str, size);
+ return romfs_blk_strcmp(sb, pos, str, size);
#endif
return -EIO;
}
diff --git a/fs/romfs/super.c b/fs/romfs/super.c
index 10ca7d984a8b..4ab3c03d8f95 100644
--- a/fs/romfs/super.c
+++ b/fs/romfs/super.c
@@ -240,8 +240,8 @@ static struct dentry *romfs_lookup(struct inode *dir, struct dentry *dentry,
goto error;
/* try to match the first 16 bytes of name */
- ret = romfs_dev_strncmp(dir->i_sb, offset + ROMFH_SIZE, name,
- len);
+ ret = romfs_dev_strcmp(dir->i_sb, offset + ROMFH_SIZE, name,
+ len);
if (ret < 0)
goto error;
if (ret == 1)
@@ -298,7 +298,8 @@ static struct inode *romfs_iget(struct super_block *sb, unsigned long pos)
struct romfs_inode ri;
struct inode *i;
unsigned long nlen;
- unsigned nextfh, ret;
+ unsigned nextfh;
+ int ret;
umode_t mode;
/* we might have to traverse a chain of "hard link" file entries to get
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index fc27fbfc5397..1402d2d54f52 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -474,6 +474,8 @@ smb_put_super(struct super_block *sb)
{
struct smb_sb_info *server = SMB_SB(sb);
+ lock_kernel();
+
smb_lock_server(server);
server->state = CONN_INVALID;
smbiod_unregister_server(server);
@@ -489,6 +491,8 @@ smb_put_super(struct super_block *sb)
smb_unlock_server(server);
put_pid(server->conn_pid);
kfree(server);
+
+ unlock_kernel();
}
static int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
diff --git a/fs/splice.c b/fs/splice.c
index c18aa7e03e2b..666953d59a35 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -182,8 +182,7 @@ ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
do_wakeup = 0;
page_nr = 0;
- if (pipe->inode)
- mutex_lock(&pipe->inode->i_mutex);
+ pipe_lock(pipe);
for (;;) {
if (!pipe->readers) {
@@ -245,15 +244,13 @@ ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
pipe->waiting_writers--;
}
- if (pipe->inode) {
- mutex_unlock(&pipe->inode->i_mutex);
+ pipe_unlock(pipe);
- if (do_wakeup) {
- smp_mb();
- if (waitqueue_active(&pipe->wait))
- wake_up_interruptible(&pipe->wait);
- kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
- }
+ if (do_wakeup) {
+ smp_mb();
+ if (waitqueue_active(&pipe->wait))
+ wake_up_interruptible(&pipe->wait);
+ kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
}
while (page_nr < spd_pages)
@@ -555,8 +552,8 @@ static int pipe_to_sendpage(struct pipe_inode_info *pipe,
* SPLICE_F_MOVE isn't set, or we cannot move the page, we simply create
* a new page in the output file page cache and fill/dirty that.
*/
-static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
- struct splice_desc *sd)
+int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
+ struct splice_desc *sd)
{
struct file *file = sd->u.file;
struct address_space *mapping = file->f_mapping;
@@ -600,108 +597,177 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
out:
return ret;
}
+EXPORT_SYMBOL(pipe_to_file);
+
+static void wakeup_pipe_writers(struct pipe_inode_info *pipe)
+{
+ smp_mb();
+ if (waitqueue_active(&pipe->wait))
+ wake_up_interruptible(&pipe->wait);
+ kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
+}
/**
- * __splice_from_pipe - splice data from a pipe to given actor
+ * splice_from_pipe_feed - feed available data from a pipe to a file
* @pipe: pipe to splice from
* @sd: information to @actor
* @actor: handler that splices the data
*
* Description:
- * This function does little more than loop over the pipe and call
- * @actor to do the actual moving of a single struct pipe_buffer to
- * the desired destination. See pipe_to_file, pipe_to_sendpage, or
- * pipe_to_user.
+ * This function loops over the pipe and calls @actor to do the
+ * actual moving of a single struct pipe_buffer to the desired
+ * destination. It returns when there's no more buffers left in
+ * the pipe or if the requested number of bytes (@sd->total_len)
+ * have been copied. It returns a positive number (one) if the
+ * pipe needs to be filled with more data, zero if the required
+ * number of bytes have been copied and -errno on error.
*
+ * This, together with splice_from_pipe_{begin,end,next}, may be
+ * used to implement the functionality of __splice_from_pipe() when
+ * locking is required around copying the pipe buffers to the
+ * destination.
*/
-ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd,
- splice_actor *actor)
+int splice_from_pipe_feed(struct pipe_inode_info *pipe, struct splice_desc *sd,
+ splice_actor *actor)
{
- int ret, do_wakeup, err;
-
- ret = 0;
- do_wakeup = 0;
-
- for (;;) {
- if (pipe->nrbufs) {
- struct pipe_buffer *buf = pipe->bufs + pipe->curbuf;
- const struct pipe_buf_operations *ops = buf->ops;
+ int ret;
- sd->len = buf->len;
- if (sd->len > sd->total_len)
- sd->len = sd->total_len;
+ while (pipe->nrbufs) {
+ struct pipe_buffer *buf = pipe->bufs + pipe->curbuf;
+ const struct pipe_buf_operations *ops = buf->ops;
- err = actor(pipe, buf, sd);
- if (err <= 0) {
- if (!ret && err != -ENODATA)
- ret = err;
+ sd->len = buf->len;
+ if (sd->len > sd->total_len)
+ sd->len = sd->total_len;
- break;
- }
+ ret = actor(pipe, buf, sd);
+ if (ret <= 0) {
+ if (ret == -ENODATA)
+ ret = 0;
+ return ret;
+ }
+ buf->offset += ret;
+ buf->len -= ret;
- ret += err;
- buf->offset += err;
- buf->len -= err;
+ sd->num_spliced += ret;
+ sd->len -= ret;
+ sd->pos += ret;
+ sd->total_len -= ret;
- sd->len -= err;
- sd->pos += err;
- sd->total_len -= err;
- if (sd->len)
- continue;
+ if (!buf->len) {
+ buf->ops = NULL;
+ ops->release(pipe, buf);
+ pipe->curbuf = (pipe->curbuf + 1) & (PIPE_BUFFERS - 1);
+ pipe->nrbufs--;
+ if (pipe->inode)
+ sd->need_wakeup = true;
+ }
- if (!buf->len) {
- buf->ops = NULL;
- ops->release(pipe, buf);
- pipe->curbuf = (pipe->curbuf + 1) & (PIPE_BUFFERS - 1);
- pipe->nrbufs--;
- if (pipe->inode)
- do_wakeup = 1;
- }
+ if (!sd->total_len)
+ return 0;
+ }
- if (!sd->total_len)
- break;
- }
+ return 1;
+}
+EXPORT_SYMBOL(splice_from_pipe_feed);
- if (pipe->nrbufs)
- continue;
+/**
+ * splice_from_pipe_next - wait for some data to splice from
+ * @pipe: pipe to splice from
+ * @sd: information about the splice operation
+ *
+ * Description:
+ * This function will wait for some data and return a positive
+ * value (one) if pipe buffers are available. It will return zero
+ * or -errno if no more data needs to be spliced.
+ */
+int splice_from_pipe_next(struct pipe_inode_info *pipe, struct splice_desc *sd)
+{
+ while (!pipe->nrbufs) {
if (!pipe->writers)
- break;
- if (!pipe->waiting_writers) {
- if (ret)
- break;
- }
+ return 0;
- if (sd->flags & SPLICE_F_NONBLOCK) {
- if (!ret)
- ret = -EAGAIN;
- break;
- }
+ if (!pipe->waiting_writers && sd->num_spliced)
+ return 0;
- if (signal_pending(current)) {
- if (!ret)
- ret = -ERESTARTSYS;
- break;
- }
+ if (sd->flags & SPLICE_F_NONBLOCK)
+ return -EAGAIN;
- if (do_wakeup) {
- smp_mb();
- if (waitqueue_active(&pipe->wait))
- wake_up_interruptible_sync(&pipe->wait);
- kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
- do_wakeup = 0;
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+
+ if (sd->need_wakeup) {
+ wakeup_pipe_writers(pipe);
+ sd->need_wakeup = false;
}
pipe_wait(pipe);
}
- if (do_wakeup) {
- smp_mb();
- if (waitqueue_active(&pipe->wait))
- wake_up_interruptible(&pipe->wait);
- kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
- }
+ return 1;
+}
+EXPORT_SYMBOL(splice_from_pipe_next);
- return ret;
+/**
+ * splice_from_pipe_begin - start splicing from pipe
+ * @sd: information about the splice operation
+ *
+ * Description:
+ * This function should be called before a loop containing
+ * splice_from_pipe_next() and splice_from_pipe_feed() to
+ * initialize the necessary fields of @sd.
+ */
+void splice_from_pipe_begin(struct splice_desc *sd)
+{
+ sd->num_spliced = 0;
+ sd->need_wakeup = false;
+}
+EXPORT_SYMBOL(splice_from_pipe_begin);
+
+/**
+ * splice_from_pipe_end - finish splicing from pipe
+ * @pipe: pipe to splice from
+ * @sd: information about the splice operation
+ *
+ * Description:
+ * This function will wake up pipe writers if necessary. It should
+ * be called after a loop containing splice_from_pipe_next() and
+ * splice_from_pipe_feed().
+ */
+void splice_from_pipe_end(struct pipe_inode_info *pipe, struct splice_desc *sd)
+{
+ if (sd->need_wakeup)
+ wakeup_pipe_writers(pipe);
+}
+EXPORT_SYMBOL(splice_from_pipe_end);
+
+/**
+ * __splice_from_pipe - splice data from a pipe to given actor
+ * @pipe: pipe to splice from
+ * @sd: information to @actor
+ * @actor: handler that splices the data
+ *
+ * Description:
+ * This function does little more than loop over the pipe and call
+ * @actor to do the actual moving of a single struct pipe_buffer to
+ * the desired destination. See pipe_to_file, pipe_to_sendpage, or
+ * pipe_to_user.
+ *
+ */
+ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd,
+ splice_actor *actor)
+{
+ int ret;
+
+ splice_from_pipe_begin(sd);
+ do {
+ ret = splice_from_pipe_next(pipe, sd);
+ if (ret > 0)
+ ret = splice_from_pipe_feed(pipe, sd, actor);
+ } while (ret > 0);
+ splice_from_pipe_end(pipe, sd);
+
+ return sd->num_spliced ? sd->num_spliced : ret;
}
EXPORT_SYMBOL(__splice_from_pipe);
@@ -715,7 +781,7 @@ EXPORT_SYMBOL(__splice_from_pipe);
* @actor: handler that splices the data
*
* Description:
- * See __splice_from_pipe. This function locks the input and output inodes,
+ * See __splice_from_pipe. This function locks the pipe inode,
* otherwise it's identical to __splice_from_pipe().
*
*/
@@ -724,7 +790,6 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
splice_actor *actor)
{
ssize_t ret;
- struct inode *inode = out->f_mapping->host;
struct splice_desc sd = {
.total_len = len,
.flags = flags,
@@ -732,30 +797,15 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
.u.file = out,
};
- /*
- * The actor worker might be calling ->write_begin and
- * ->write_end. Most of the time, these expect i_mutex to
- * be held. Since this may result in an ABBA deadlock with
- * pipe->inode, we have to order lock acquiry here.
- *
- * Outer lock must be inode->i_mutex, as pipe_wait() will
- * release and reacquire pipe->inode->i_mutex, AND inode must
- * never be a pipe.
- */
- WARN_ON(S_ISFIFO(inode->i_mode));
- mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT);
- if (pipe->inode)
- mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_CHILD);
+ pipe_lock(pipe);
ret = __splice_from_pipe(pipe, &sd, actor);
- if (pipe->inode)
- mutex_unlock(&pipe->inode->i_mutex);
- mutex_unlock(&inode->i_mutex);
+ pipe_unlock(pipe);
return ret;
}
/**
- * generic_file_splice_write_nolock - generic_file_splice_write without mutexes
+ * generic_file_splice_write - splice data from a pipe to a file
* @pipe: pipe info
* @out: file to write to
* @ppos: position in @out
@@ -764,13 +814,12 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
*
* Description:
* Will either move or copy pages (determined by @flags options) from
- * the given pipe inode to the given file. The caller is responsible
- * for acquiring i_mutex on both inodes.
+ * the given pipe inode to the given file.
*
*/
ssize_t
-generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out,
- loff_t *ppos, size_t len, unsigned int flags)
+generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
+ loff_t *ppos, size_t len, unsigned int flags)
{
struct address_space *mapping = out->f_mapping;
struct inode *inode = mapping->host;
@@ -781,76 +830,28 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out,
.u.file = out,
};
ssize_t ret;
- int err;
-
- err = file_remove_suid(out);
- if (unlikely(err))
- return err;
-
- ret = __splice_from_pipe(pipe, &sd, pipe_to_file);
- if (ret > 0) {
- unsigned long nr_pages;
- *ppos += ret;
- nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-
- /*
- * If file or inode is SYNC and we actually wrote some data,
- * sync it.
- */
- if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) {
- err = generic_osync_inode(inode, mapping,
- OSYNC_METADATA|OSYNC_DATA);
+ pipe_lock(pipe);
- if (err)
- ret = err;
- }
- balance_dirty_pages_ratelimited_nr(mapping, nr_pages);
- }
+ splice_from_pipe_begin(&sd);
+ do {
+ ret = splice_from_pipe_next(pipe, &sd);
+ if (ret <= 0)
+ break;
- return ret;
-}
+ mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
+ ret = file_remove_suid(out);
+ if (!ret)
+ ret = splice_from_pipe_feed(pipe, &sd, pipe_to_file);
+ mutex_unlock(&inode->i_mutex);
+ } while (ret > 0);
+ splice_from_pipe_end(pipe, &sd);
-EXPORT_SYMBOL(generic_file_splice_write_nolock);
+ pipe_unlock(pipe);
-/**
- * generic_file_splice_write - splice data from a pipe to a file
- * @pipe: pipe info
- * @out: file to write to
- * @ppos: position in @out
- * @len: number of bytes to splice
- * @flags: splice modifier flags
- *
- * Description:
- * Will either move or copy pages (determined by @flags options) from
- * the given pipe inode to the given file.
- *
- */
-ssize_t
-generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
- loff_t *ppos, size_t len, unsigned int flags)
-{
- 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,
- };
- ssize_t ret;
+ if (sd.num_spliced)
+ ret = sd.num_spliced;
- WARN_ON(S_ISFIFO(inode->i_mode));
- mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT);
- ret = file_remove_suid(out);
- if (likely(!ret)) {
- if (pipe->inode)
- mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_CHILD);
- ret = __splice_from_pipe(pipe, &sd, pipe_to_file);
- if (pipe->inode)
- mutex_unlock(&pipe->inode->i_mutex);
- }
- mutex_unlock(&inode->i_mutex);
if (ret > 0) {
unsigned long nr_pages;
@@ -1339,8 +1340,7 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *iov,
if (!pipe)
return -EBADF;
- if (pipe->inode)
- mutex_lock(&pipe->inode->i_mutex);
+ pipe_lock(pipe);
error = ret = 0;
while (nr_segs) {
@@ -1395,8 +1395,7 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *iov,
iov++;
}
- if (pipe->inode)
- mutex_unlock(&pipe->inode->i_mutex);
+ pipe_unlock(pipe);
if (!ret)
ret = error;
@@ -1524,7 +1523,7 @@ static int link_ipipe_prep(struct pipe_inode_info *pipe, unsigned int flags)
return 0;
ret = 0;
- mutex_lock(&pipe->inode->i_mutex);
+ pipe_lock(pipe);
while (!pipe->nrbufs) {
if (signal_pending(current)) {
@@ -1542,7 +1541,7 @@ static int link_ipipe_prep(struct pipe_inode_info *pipe, unsigned int flags)
pipe_wait(pipe);
}
- mutex_unlock(&pipe->inode->i_mutex);
+ pipe_unlock(pipe);
return ret;
}
@@ -1562,7 +1561,7 @@ static int link_opipe_prep(struct pipe_inode_info *pipe, unsigned int flags)
return 0;
ret = 0;
- mutex_lock(&pipe->inode->i_mutex);
+ pipe_lock(pipe);
while (pipe->nrbufs >= PIPE_BUFFERS) {
if (!pipe->readers) {
@@ -1583,7 +1582,7 @@ static int link_opipe_prep(struct pipe_inode_info *pipe, unsigned int flags)
pipe->waiting_writers--;
}
- mutex_unlock(&pipe->inode->i_mutex);
+ pipe_unlock(pipe);
return ret;
}
@@ -1599,10 +1598,10 @@ static int link_pipe(struct pipe_inode_info *ipipe,
/*
* Potential ABBA deadlock, work around it by ordering lock
- * grabbing by inode address. Otherwise two different processes
+ * grabbing by pipe info address. Otherwise two different processes
* could deadlock (one doing tee from A -> B, the other from B -> A).
*/
- inode_double_lock(ipipe->inode, opipe->inode);
+ pipe_double_lock(ipipe, opipe);
do {
if (!opipe->readers) {
@@ -1653,7 +1652,8 @@ static int link_pipe(struct pipe_inode_info *ipipe,
if (!ret && ipipe->waiting_writers && (flags & SPLICE_F_NONBLOCK))
ret = -EAGAIN;
- inode_double_unlock(ipipe->inode, opipe->inode);
+ pipe_unlock(ipipe);
+ pipe_unlock(opipe);
/*
* If we put data in the output pipe, wakeup any potential readers.
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index ffa6edcd2d0c..f12e78f5ab0d 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -328,6 +328,8 @@ static int squashfs_remount(struct super_block *sb, int *flags, char *data)
static void squashfs_put_super(struct super_block *sb)
{
+ lock_kernel();
+
if (sb->s_fs_info) {
struct squashfs_sb_info *sbi = sb->s_fs_info;
squashfs_cache_delete(sbi->block_cache);
@@ -340,6 +342,8 @@ static void squashfs_put_super(struct super_block *sb)
kfree(sb->s_fs_info);
sb->s_fs_info = NULL;
}
+
+ unlock_kernel();
}
diff --git a/fs/stat.c b/fs/stat.c
index 2db740a0cfb5..075694e31d8b 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -55,59 +55,54 @@ int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
EXPORT_SYMBOL(vfs_getattr);
-int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat)
+int vfs_fstat(unsigned int fd, struct kstat *stat)
{
- struct path path;
- int error;
+ struct file *f = fget(fd);
+ int error = -EBADF;
- error = user_path_at(dfd, name, LOOKUP_FOLLOW, &path);
- if (!error) {
- error = vfs_getattr(path.mnt, path.dentry, stat);
- path_put(&path);
+ if (f) {
+ error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat);
+ fput(f);
}
return error;
}
+EXPORT_SYMBOL(vfs_fstat);
-int vfs_stat(char __user *name, struct kstat *stat)
+int vfs_fstatat(int dfd, char __user *filename, struct kstat *stat, int flag)
{
- return vfs_stat_fd(AT_FDCWD, name, stat);
-}
+ struct path path;
+ int error = -EINVAL;
+ int lookup_flags = 0;
-EXPORT_SYMBOL(vfs_stat);
+ if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+ goto out;
-int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat)
-{
- struct path path;
- int error;
+ if (!(flag & AT_SYMLINK_NOFOLLOW))
+ lookup_flags |= LOOKUP_FOLLOW;
- error = user_path_at(dfd, name, 0, &path);
- if (!error) {
- error = vfs_getattr(path.mnt, path.dentry, stat);
- path_put(&path);
- }
+ error = user_path_at(dfd, filename, lookup_flags, &path);
+ if (error)
+ goto out;
+
+ error = vfs_getattr(path.mnt, path.dentry, stat);
+ path_put(&path);
+out:
return error;
}
+EXPORT_SYMBOL(vfs_fstatat);
-int vfs_lstat(char __user *name, struct kstat *stat)
+int vfs_stat(char __user *name, struct kstat *stat)
{
- return vfs_lstat_fd(AT_FDCWD, name, stat);
+ return vfs_fstatat(AT_FDCWD, name, stat, 0);
}
+EXPORT_SYMBOL(vfs_stat);
-EXPORT_SYMBOL(vfs_lstat);
-
-int vfs_fstat(unsigned int fd, struct kstat *stat)
+int vfs_lstat(char __user *name, struct kstat *stat)
{
- struct file *f = fget(fd);
- int error = -EBADF;
-
- if (f) {
- error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat);
- fput(f);
- }
- return error;
+ return vfs_fstatat(AT_FDCWD, name, stat, AT_SYMLINK_NOFOLLOW);
}
+EXPORT_SYMBOL(vfs_lstat);
-EXPORT_SYMBOL(vfs_fstat);
#ifdef __ARCH_WANT_OLD_STAT
@@ -155,23 +150,25 @@ static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * sta
SYSCALL_DEFINE2(stat, char __user *, filename, struct __old_kernel_stat __user *, statbuf)
{
struct kstat stat;
- int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
+ int error;
- if (!error)
- error = cp_old_stat(&stat, statbuf);
+ error = vfs_stat(filename, &stat);
+ if (error)
+ return error;
- return error;
+ return cp_old_stat(&stat, statbuf);
}
SYSCALL_DEFINE2(lstat, char __user *, filename, struct __old_kernel_stat __user *, statbuf)
{
struct kstat stat;
- int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
+ int error;
- if (!error)
- error = cp_old_stat(&stat, statbuf);
+ error = vfs_lstat(filename, &stat);
+ if (error)
+ return error;
- return error;
+ return cp_old_stat(&stat, statbuf);
}
SYSCALL_DEFINE2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, statbuf)
@@ -240,23 +237,23 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
SYSCALL_DEFINE2(newstat, char __user *, filename, struct stat __user *, statbuf)
{
struct kstat stat;
- int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
-
- if (!error)
- error = cp_new_stat(&stat, statbuf);
+ int error = vfs_stat(filename, &stat);
- return error;
+ if (error)
+ return error;
+ return cp_new_stat(&stat, statbuf);
}
SYSCALL_DEFINE2(newlstat, char __user *, filename, struct stat __user *, statbuf)
{
struct kstat stat;
- int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
+ int error;
- if (!error)
- error = cp_new_stat(&stat, statbuf);
+ error = vfs_lstat(filename, &stat);
+ if (error)
+ return error;
- return error;
+ return cp_new_stat(&stat, statbuf);
}
#if !defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_SYS_NEWFSTATAT)
@@ -264,21 +261,12 @@ SYSCALL_DEFINE4(newfstatat, int, dfd, char __user *, filename,
struct stat __user *, statbuf, int, flag)
{
struct kstat stat;
- int error = -EINVAL;
-
- if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
- goto out;
-
- if (flag & AT_SYMLINK_NOFOLLOW)
- error = vfs_lstat_fd(dfd, filename, &stat);
- else
- error = vfs_stat_fd(dfd, filename, &stat);
-
- if (!error)
- error = cp_new_stat(&stat, statbuf);
+ int error;
-out:
- return error;
+ error = vfs_fstatat(dfd, filename, &stat, flag);
+ if (error)
+ return error;
+ return cp_new_stat(&stat, statbuf);
}
#endif
@@ -404,21 +392,12 @@ SYSCALL_DEFINE4(fstatat64, int, dfd, char __user *, filename,
struct stat64 __user *, statbuf, int, flag)
{
struct kstat stat;
- int error = -EINVAL;
-
- if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
- goto out;
-
- if (flag & AT_SYMLINK_NOFOLLOW)
- error = vfs_lstat_fd(dfd, filename, &stat);
- else
- error = vfs_stat_fd(dfd, filename, &stat);
-
- if (!error)
- error = cp_new_stat64(&stat, statbuf);
+ int error;
-out:
- return error;
+ error = vfs_fstatat(dfd, filename, &stat, flag);
+ if (error)
+ return error;
+ return cp_new_stat64(&stat, statbuf);
}
#endif /* __ARCH_WANT_STAT64 */
diff --git a/fs/super.c b/fs/super.c
index 786fe7d72790..e4a0c5bd6e3c 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -28,7 +28,6 @@
#include <linux/blkdev.h>
#include <linux/quotaops.h>
#include <linux/namei.h>
-#include <linux/buffer_head.h> /* for fsync_super() */
#include <linux/mount.h>
#include <linux/security.h>
#include <linux/syscalls.h>
@@ -38,7 +37,6 @@
#include <linux/kobject.h>
#include <linux/mutex.h>
#include <linux/file.h>
-#include <linux/async.h>
#include <asm/uaccess.h>
#include "internal.h"
@@ -72,7 +70,6 @@ static struct super_block *alloc_super(struct file_system_type *type)
INIT_HLIST_HEAD(&s->s_anon);
INIT_LIST_HEAD(&s->s_inodes);
INIT_LIST_HEAD(&s->s_dentry_lru);
- INIT_LIST_HEAD(&s->s_async_list);
init_rwsem(&s->s_umount);
mutex_init(&s->s_lock);
lockdep_set_class(&s->s_umount, &type->s_umount_key);
@@ -208,6 +205,34 @@ void deactivate_super(struct super_block *s)
EXPORT_SYMBOL(deactivate_super);
/**
+ * deactivate_locked_super - drop an active reference to superblock
+ * @s: superblock to deactivate
+ *
+ * Equivalent of up_write(&s->s_umount); deactivate_super(s);, except that
+ * it does not unlock it until it's all over. As the result, it's safe to
+ * use to dispose of new superblock on ->get_sb() failure exits - nobody
+ * will see the sucker until it's all over. Equivalent using up_write +
+ * deactivate_super is safe for that purpose only if superblock is either
+ * safe to use or has NULL ->s_root when we unlock.
+ */
+void deactivate_locked_super(struct super_block *s)
+{
+ struct file_system_type *fs = s->s_type;
+ if (atomic_dec_and_lock(&s->s_active, &sb_lock)) {
+ s->s_count -= S_BIAS-1;
+ spin_unlock(&sb_lock);
+ vfs_dq_off(s, 0);
+ fs->kill_sb(s);
+ put_filesystem(fs);
+ put_super(s);
+ } else {
+ up_write(&s->s_umount);
+ }
+}
+
+EXPORT_SYMBOL(deactivate_locked_super);
+
+/**
* grab_super - acquire an active reference
* @s: reference we are trying to make active
*
@@ -257,38 +282,6 @@ void unlock_super(struct super_block * sb)
EXPORT_SYMBOL(lock_super);
EXPORT_SYMBOL(unlock_super);
-/*
- * Write out and wait upon all dirty data associated with this
- * superblock. Filesystem data as well as the underlying block
- * device. Takes the superblock lock. Requires a second blkdev
- * flush by the caller to complete the operation.
- */
-void __fsync_super(struct super_block *sb)
-{
- sync_inodes_sb(sb, 0);
- vfs_dq_sync(sb);
- lock_super(sb);
- if (sb->s_dirt && sb->s_op->write_super)
- sb->s_op->write_super(sb);
- unlock_super(sb);
- if (sb->s_op->sync_fs)
- sb->s_op->sync_fs(sb, 1);
- sync_blockdev(sb->s_bdev);
- sync_inodes_sb(sb, 1);
-}
-
-/*
- * Write out and wait upon all dirty data associated with this
- * superblock. Filesystem data as well as the underlying block
- * device. Takes the superblock lock.
- */
-int fsync_super(struct super_block *sb)
-{
- __fsync_super(sb);
- return sync_blockdev(sb->s_bdev);
-}
-EXPORT_SYMBOL_GPL(fsync_super);
-
/**
* generic_shutdown_super - common helper for ->kill_sb()
* @sb: superblock to kill
@@ -310,21 +303,13 @@ void generic_shutdown_super(struct super_block *sb)
if (sb->s_root) {
shrink_dcache_for_umount(sb);
- fsync_super(sb);
- lock_super(sb);
+ sync_filesystem(sb);
+ get_fs_excl();
sb->s_flags &= ~MS_ACTIVE;
- /*
- * wait for asynchronous fs operations to finish before going further
- */
- async_synchronize_full_domain(&sb->s_async_list);
-
/* bad name - it should be evict_inodes() */
invalidate_inodes(sb);
- lock_kernel();
- if (sop->write_super && sb->s_dirt)
- sop->write_super(sb);
if (sop->put_super)
sop->put_super(sb);
@@ -334,9 +319,7 @@ void generic_shutdown_super(struct super_block *sb)
"Self-destruct in 5 seconds. Have a nice day...\n",
sb->s_id);
}
-
- unlock_kernel();
- unlock_super(sb);
+ put_fs_excl();
}
spin_lock(&sb_lock);
/* should be initialized for __put_super_and_need_restart() */
@@ -413,16 +396,14 @@ void drop_super(struct super_block *sb)
EXPORT_SYMBOL(drop_super);
-static inline void write_super(struct super_block *sb)
-{
- lock_super(sb);
- if (sb->s_root && sb->s_dirt)
- if (sb->s_op->write_super)
- sb->s_op->write_super(sb);
- unlock_super(sb);
-}
-
-/*
+/**
+ * sync_supers - helper for periodic superblock writeback
+ *
+ * Call the write_super method if present on all dirty superblocks in
+ * the system. This is for the periodic writeback used by most older
+ * filesystems. For data integrity superblock writeback use
+ * sync_filesystems() instead.
+ *
* Note: check the dirty flag before waiting, so we don't
* hold up the sync while mounting a device. (The newly
* mounted device won't need syncing.)
@@ -434,12 +415,17 @@ void sync_supers(void)
spin_lock(&sb_lock);
restart:
list_for_each_entry(sb, &super_blocks, s_list) {
- if (sb->s_dirt) {
+ if (sb->s_op->write_super && sb->s_dirt) {
sb->s_count++;
spin_unlock(&sb_lock);
+
down_read(&sb->s_umount);
- write_super(sb);
+ lock_super(sb);
+ if (sb->s_root && sb->s_dirt)
+ sb->s_op->write_super(sb);
+ unlock_super(sb);
up_read(&sb->s_umount);
+
spin_lock(&sb_lock);
if (__put_super_and_need_restart(sb))
goto restart;
@@ -448,60 +434,6 @@ restart:
spin_unlock(&sb_lock);
}
-/*
- * 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
- * if two or more filesystems are being continuously dirtied. s_need_sync_fs
- * 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_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.
- *
- * (Fabian) Avoid sync_fs with clean fs & wait mode 0
- */
-void sync_filesystems(int wait)
-{
- struct super_block *sb;
- static DEFINE_MUTEX(mutex);
-
- mutex_lock(&mutex); /* Could be down_interruptible */
- spin_lock(&sb_lock);
- list_for_each_entry(sb, &super_blocks, s_list) {
- if (!sb->s_op->sync_fs)
- continue;
- if (sb->s_flags & MS_RDONLY)
- continue;
- sb->s_need_sync_fs = 1;
- }
-
-restart:
- list_for_each_entry(sb, &super_blocks, s_list) {
- if (!sb->s_need_sync_fs)
- continue;
- sb->s_need_sync_fs = 0;
- if (sb->s_flags & MS_RDONLY)
- continue; /* hm. Was remounted r/o meanwhile */
- sb->s_count++;
- spin_unlock(&sb_lock);
- down_read(&sb->s_umount);
- async_synchronize_full_domain(&sb->s_async_list);
- if (sb->s_root && (wait || sb->s_dirt))
- sb->s_op->sync_fs(sb, wait);
- up_read(&sb->s_umount);
- /* restart only when sb is no longer on the list */
- spin_lock(&sb_lock);
- if (__put_super_and_need_restart(sb))
- goto restart;
- }
- spin_unlock(&sb_lock);
- mutex_unlock(&mutex);
-}
-
/**
* get_super - get the superblock of a device
* @bdev: device to get the superblock for
@@ -588,45 +520,6 @@ out:
}
/**
- * mark_files_ro - mark all files read-only
- * @sb: superblock in question
- *
- * All files are marked read-only. We don't care about pending
- * delete files so this should be used in 'force' mode only.
- */
-
-static void mark_files_ro(struct super_block *sb)
-{
- struct file *f;
-
-retry:
- file_list_lock();
- list_for_each_entry(f, &sb->s_files, f_u.fu_list) {
- struct vfsmount *mnt;
- if (!S_ISREG(f->f_path.dentry->d_inode->i_mode))
- continue;
- if (!file_count(f))
- continue;
- if (!(f->f_mode & FMODE_WRITE))
- continue;
- f->f_mode &= ~FMODE_WRITE;
- if (file_check_writeable(f) != 0)
- continue;
- file_release_write(f);
- mnt = mntget(f->f_path.mnt);
- file_list_unlock();
- /*
- * This can sleep, so we can't hold
- * the file_list_lock() spinlock.
- */
- mnt_drop_write(mnt);
- mntput(mnt);
- goto retry;
- }
- file_list_unlock();
-}
-
-/**
* do_remount_sb - asks filesystem to change mount options.
* @sb: superblock in question
* @flags: numeric part of options
@@ -647,8 +540,9 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
if (flags & MS_RDONLY)
acct_auto_close(sb);
shrink_dcache_sb(sb);
- fsync_super(sb);
+ sync_filesystem(sb);
+ lock_kernel();
/* If we are remounting RDONLY and current sb is read/write,
make sure there are no rw files opened */
if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY)) {
@@ -663,13 +557,12 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
remount_rw = !(flags & MS_RDONLY) && (sb->s_flags & MS_RDONLY);
if (sb->s_op->remount_fs) {
- lock_super(sb);
retval = sb->s_op->remount_fs(sb, &flags, data);
- unlock_super(sb);
if (retval)
return retval;
}
sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
+ unlock_kernel();
if (remount_rw)
vfs_dq_quota_on_remount(sb);
return 0;
@@ -683,18 +576,17 @@ static void do_emergency_remount(struct work_struct *work)
list_for_each_entry(sb, &super_blocks, s_list) {
sb->s_count++;
spin_unlock(&sb_lock);
- down_read(&sb->s_umount);
+ down_write(&sb->s_umount);
if (sb->s_root && sb->s_bdev && !(sb->s_flags & MS_RDONLY)) {
/*
* ->remount_fs needs lock_kernel().
*
* What lock protects sb->s_flags??
*/
- lock_kernel();
do_remount_sb(sb, MS_RDONLY, NULL, 1);
- unlock_kernel();
}
- drop_super(sb);
+ up_write(&sb->s_umount);
+ put_super(sb);
spin_lock(&sb_lock);
}
spin_unlock(&sb_lock);
@@ -797,8 +689,7 @@ int get_sb_ns(struct file_system_type *fs_type, int flags, void *data,
sb->s_flags = flags;
err = fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
if (err) {
- up_write(&sb->s_umount);
- deactivate_super(sb);
+ deactivate_locked_super(sb);
return err;
}
@@ -854,8 +745,7 @@ int get_sb_bdev(struct file_system_type *fs_type,
if (s->s_root) {
if ((flags ^ s->s_flags) & MS_RDONLY) {
- up_write(&s->s_umount);
- deactivate_super(s);
+ deactivate_locked_super(s);
error = -EBUSY;
goto error_bdev;
}
@@ -870,8 +760,7 @@ int get_sb_bdev(struct file_system_type *fs_type,
sb_set_blocksize(s, block_size(bdev));
error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
if (error) {
- up_write(&s->s_umount);
- deactivate_super(s);
+ deactivate_locked_super(s);
goto error;
}
@@ -897,7 +786,7 @@ void kill_block_super(struct super_block *sb)
struct block_device *bdev = sb->s_bdev;
fmode_t mode = sb->s_mode;
- bdev->bd_super = 0;
+ bdev->bd_super = NULL;
generic_shutdown_super(sb);
sync_blockdev(bdev);
close_bdev_exclusive(bdev, mode);
@@ -921,8 +810,7 @@ int get_sb_nodev(struct file_system_type *fs_type,
error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
if (error) {
- up_write(&s->s_umount);
- deactivate_super(s);
+ deactivate_locked_super(s);
return error;
}
s->s_flags |= MS_ACTIVE;
@@ -952,8 +840,7 @@ int get_sb_single(struct file_system_type *fs_type,
s->s_flags = flags;
error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
if (error) {
- up_write(&s->s_umount);
- deactivate_super(s);
+ deactivate_locked_super(s);
return error;
}
s->s_flags |= MS_ACTIVE;
@@ -1006,8 +893,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
return mnt;
out_sb:
dput(mnt->mnt_root);
- up_write(&mnt->mnt_sb->s_umount);
- deactivate_super(mnt->mnt_sb);
+ deactivate_locked_super(mnt->mnt_sb);
out_free_secdata:
free_secdata(secdata);
out_mnt:
diff --git a/fs/sync.c b/fs/sync.c
index 7abc65fbf21d..89c37f732afa 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -13,38 +13,127 @@
#include <linux/pagemap.h>
#include <linux/quotaops.h>
#include <linux/buffer_head.h>
+#include "internal.h"
#define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \
SYNC_FILE_RANGE_WAIT_AFTER)
/*
- * sync everything. Start out by waking pdflush, because that writes back
- * all queues in parallel.
+ * Do the filesystem syncing work. For simple filesystems sync_inodes_sb(sb, 0)
+ * just dirties buffers with inodes so we have to submit IO for these buffers
+ * via __sync_blockdev(). This also speeds up the wait == 1 case since in that
+ * case write_inode() functions do sync_dirty_buffer() and thus effectively
+ * write one block at a time.
*/
-static void do_sync(unsigned long wait)
+static int __sync_filesystem(struct super_block *sb, int wait)
{
- wakeup_pdflush(0);
- sync_inodes(0); /* All mappings, inodes and their blockdevs */
- vfs_dq_sync(NULL);
- sync_supers(); /* Write the superblocks */
- sync_filesystems(0); /* Start syncing the filesystems */
- sync_filesystems(wait); /* Waitingly sync the filesystems */
- sync_inodes(wait); /* Mappings, inodes and blockdevs, again. */
+ /* Avoid doing twice syncing and cache pruning for quota sync */
if (!wait)
- printk("Emergency Sync complete\n");
- if (unlikely(laptop_mode))
- laptop_sync_completion();
+ writeout_quota_sb(sb, -1);
+ else
+ sync_quota_sb(sb, -1);
+ sync_inodes_sb(sb, wait);
+ lock_super(sb);
+ if (sb->s_dirt && sb->s_op->write_super)
+ sb->s_op->write_super(sb);
+ unlock_super(sb);
+ if (sb->s_op->sync_fs)
+ sb->s_op->sync_fs(sb, wait);
+ return __sync_blockdev(sb->s_bdev, wait);
+}
+
+/*
+ * Write out and wait upon all dirty data associated with this
+ * superblock. Filesystem data as well as the underlying block
+ * device. Takes the superblock lock.
+ */
+int sync_filesystem(struct super_block *sb)
+{
+ int ret;
+
+ /*
+ * We need to be protected against the filesystem going from
+ * r/o to r/w or vice versa.
+ */
+ WARN_ON(!rwsem_is_locked(&sb->s_umount));
+
+ /*
+ * No point in syncing out anything if the filesystem is read-only.
+ */
+ if (sb->s_flags & MS_RDONLY)
+ return 0;
+
+ ret = __sync_filesystem(sb, 0);
+ if (ret < 0)
+ return ret;
+ return __sync_filesystem(sb, 1);
+}
+EXPORT_SYMBOL_GPL(sync_filesystem);
+
+/*
+ * Sync all the data for all the filesystems (called by sys_sync() and
+ * emergency sync)
+ *
+ * This operation is careful to avoid the livelock which could easily happen
+ * if two or more filesystems are being continuously dirtied. s_need_sync
+ * 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_filesystems and then process B
+ * calls sync_filesystems as well, process B will set all the s_need_sync
+ * flags again, which will cause process A to resync everything. Fix that with
+ * a local mutex.
+ */
+static void sync_filesystems(int wait)
+{
+ struct super_block *sb;
+ static DEFINE_MUTEX(mutex);
+
+ mutex_lock(&mutex); /* Could be down_interruptible */
+ spin_lock(&sb_lock);
+ list_for_each_entry(sb, &super_blocks, s_list)
+ sb->s_need_sync = 1;
+
+restart:
+ list_for_each_entry(sb, &super_blocks, s_list) {
+ if (!sb->s_need_sync)
+ continue;
+ sb->s_need_sync = 0;
+ sb->s_count++;
+ spin_unlock(&sb_lock);
+
+ down_read(&sb->s_umount);
+ if (!(sb->s_flags & MS_RDONLY) && sb->s_root)
+ __sync_filesystem(sb, wait);
+ up_read(&sb->s_umount);
+
+ /* restart only when sb is no longer on the list */
+ spin_lock(&sb_lock);
+ if (__put_super_and_need_restart(sb))
+ goto restart;
+ }
+ spin_unlock(&sb_lock);
+ mutex_unlock(&mutex);
}
SYSCALL_DEFINE0(sync)
{
- do_sync(1);
+ sync_filesystems(0);
+ sync_filesystems(1);
+ if (unlikely(laptop_mode))
+ laptop_sync_completion();
return 0;
}
static void do_sync_work(struct work_struct *work)
{
- do_sync(0);
+ /*
+ * Sync twice to reduce the possibility we skipped some inodes / pages
+ * because they were temporarily locked
+ */
+ sync_filesystems(0);
+ sync_filesystems(0);
+ printk("Emergency Sync complete\n");
kfree(work);
}
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index 93e0c0281d45..9345806c8853 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -157,14 +157,9 @@ static ssize_t write(struct file *file, const char __user *userbuf,
count = size - offs;
}
- temp = kmalloc(count, GFP_KERNEL);
- if (!temp)
- return -ENOMEM;
-
- if (copy_from_user(temp, userbuf, count)) {
- count = -EFAULT;
- goto out_free;
- }
+ temp = memdup_user(userbuf, count);
+ if (IS_ERR(temp))
+ return PTR_ERR(temp);
mutex_lock(&bb->mutex);
@@ -176,8 +171,6 @@ static ssize_t write(struct file *file, const char __user *userbuf,
if (count > 0)
*off = offs + count;
-out_free:
- kfree(temp);
return count;
}
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 289c43a47263..b1606e07b7a3 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -446,11 +446,11 @@ static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
if (buffer->event != atomic_read(&od->event))
goto trigger;
- return 0;
+ return DEFAULT_POLLMASK;
trigger:
buffer->needs_read_fill = 1;
- return POLLERR|POLLPRI;
+ return DEFAULT_POLLMASK|POLLERR|POLLPRI;
}
void sysfs_notify_dirent(struct sysfs_dirent *sd)
@@ -667,6 +667,7 @@ struct sysfs_schedule_callback_struct {
struct work_struct work;
};
+static struct workqueue_struct *sysfs_workqueue;
static DEFINE_MUTEX(sysfs_workq_mutex);
static LIST_HEAD(sysfs_workq);
static void sysfs_schedule_callback_work(struct work_struct *work)
@@ -715,11 +716,20 @@ int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
mutex_lock(&sysfs_workq_mutex);
list_for_each_entry_safe(ss, tmp, &sysfs_workq, workq_list)
if (ss->kobj == kobj) {
+ module_put(owner);
mutex_unlock(&sysfs_workq_mutex);
return -EAGAIN;
}
mutex_unlock(&sysfs_workq_mutex);
+ if (sysfs_workqueue == NULL) {
+ sysfs_workqueue = create_workqueue("sysfsd");
+ if (sysfs_workqueue == NULL) {
+ module_put(owner);
+ return -ENOMEM;
+ }
+ }
+
ss = kmalloc(sizeof(*ss), GFP_KERNEL);
if (!ss) {
module_put(owner);
@@ -735,7 +745,7 @@ int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
mutex_lock(&sysfs_workq_mutex);
list_add_tail(&ss->workq_list, &sysfs_workq);
mutex_unlock(&sysfs_workq_mutex);
- schedule_work(&ss->work);
+ queue_work(sysfs_workqueue, &ss->work);
return 0;
}
EXPORT_SYMBOL_GPL(sysfs_schedule_callback);
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index da20b48d350f..e0a39f1fb88e 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -61,10 +61,12 @@ clean:
static int sysv_remount(struct super_block *sb, int *flags, char *data)
{
struct sysv_sb_info *sbi = SYSV_SB(sb);
+ lock_super(sb);
if (sbi->s_forced_ro)
*flags |= MS_RDONLY;
if (!(*flags & MS_RDONLY))
sb->s_dirt = 1;
+ unlock_super(sb);
return 0;
}
@@ -72,6 +74,11 @@ static void sysv_put_super(struct super_block *sb)
{
struct sysv_sb_info *sbi = SYSV_SB(sb);
+ lock_kernel();
+
+ if (sb->s_dirt)
+ sysv_write_super(sb);
+
if (!(sb->s_flags & MS_RDONLY)) {
/* XXX ext2 also updates the state here */
mark_buffer_dirty(sbi->s_bh1);
@@ -84,6 +91,8 @@ static void sysv_put_super(struct super_block *sb)
brelse(sbi->s_bh2);
kfree(sbi);
+
+ unlock_kernel();
}
static int sysv_statfs(struct dentry *dentry, struct kstatfs *buf)
diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c
index af1914462f02..d0231ba783df 100644
--- a/fs/ubifs/budget.c
+++ b/fs/ubifs/budget.c
@@ -628,7 +628,7 @@ void ubifs_convert_page_budget(struct ubifs_info *c)
*
* This function releases budget corresponding to a dirty inode. It is usually
* called when after the inode has been written to the media and marked as
- * clean.
+ * clean. It also causes the "no space" flags to be cleared.
*/
void ubifs_release_dirty_inode_budget(struct ubifs_info *c,
struct ubifs_inode *ui)
@@ -636,6 +636,7 @@ void ubifs_release_dirty_inode_budget(struct ubifs_info *c,
struct ubifs_budget_req req;
memset(&req, 0, sizeof(struct ubifs_budget_req));
+ /* The "no space" flags will be cleared because dd_growth is > 0 */
req.dd_growth = c->inode_budget + ALIGN(ui->data_len, 8);
ubifs_release_budget(c, &req);
}
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index faa44f90608a..592e1d11bd20 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -360,6 +360,11 @@ static void ubifs_delete_inode(struct inode *inode)
out:
if (ui->dirty)
ubifs_release_dirty_inode_budget(c, ui);
+ else {
+ /* We've deleted something - clean the "no space" flags */
+ c->nospace = c->nospace_rp = 0;
+ smp_wmb();
+ }
clear_inode(inode);
}
@@ -447,9 +452,6 @@ static int ubifs_sync_fs(struct super_block *sb, int wait)
if (!wait)
return 0;
- if (sb->s_flags & MS_RDONLY)
- return 0;
-
/*
* VFS calls '->sync_fs()' before synchronizing all dirty inodes and
* pages, so synchronize them first, then commit the journal. Strictly
@@ -1687,6 +1689,9 @@ static void ubifs_put_super(struct super_block *sb)
ubifs_msg("un-mount UBI device %d, volume %d", c->vi.ubi_num,
c->vi.vol_id);
+
+ lock_kernel();
+
/*
* The following asserts are only valid if there has not been a failure
* of the media. For example, there will be dirty inodes if we failed
@@ -1753,6 +1758,8 @@ static void ubifs_put_super(struct super_block *sb)
ubi_close_volume(c->ubi);
mutex_unlock(&c->umount_mutex);
kfree(c);
+
+ unlock_kernel();
}
static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
@@ -2055,8 +2062,7 @@ static int ubifs_get_sb(struct file_system_type *fs_type, int flags,
return 0;
out_deact:
- up_write(&sb->s_umount);
- deactivate_super(sb);
+ deactivate_locked_super(sb);
out_close:
ubi_close_volume(ubi);
return err;
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 72348cc855a4..e2e06b0ea565 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -2062,6 +2062,9 @@ static void udf_put_super(struct super_block *sb)
struct udf_sb_info *sbi;
sbi = UDF_SB(sb);
+
+ lock_kernel();
+
if (sbi->s_vat_inode)
iput(sbi->s_vat_inode);
if (sbi->s_partitions)
@@ -2077,6 +2080,8 @@ static void udf_put_super(struct super_block *sb)
kfree(sbi->s_partmaps);
kfree(sb->s_fs_info);
sb->s_fs_info = NULL;
+
+ unlock_kernel();
}
static int udf_sync_fs(struct super_block *sb, int wait)
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
index dbbbc4668769..6321b797061b 100644
--- a/fs/ufs/dir.c
+++ b/fs/ufs/dir.c
@@ -666,6 +666,6 @@ not_empty:
const struct file_operations ufs_dir_operations = {
.read = generic_read_dir,
.readdir = ufs_readdir,
- .fsync = file_fsync,
+ .fsync = ufs_sync_file,
.llseek = generic_file_llseek,
};
diff --git a/fs/ufs/file.c b/fs/ufs/file.c
index 625ef17c6f83..2bd3a1615714 100644
--- a/fs/ufs/file.c
+++ b/fs/ufs/file.c
@@ -30,7 +30,7 @@
#include "ufs.h"
-static int ufs_sync_file(struct file *file, struct dentry *dentry, int datasync)
+int ufs_sync_file(struct file *file, struct dentry *dentry, int datasync)
{
struct inode *inode = dentry->d_inode;
int err;
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 60359291761f..a5ecabfdc976 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -594,6 +594,9 @@ static void ufs_put_super_internal(struct super_block *sb)
UFSD("ENTER\n");
+
+ lock_kernel();
+
ufs_put_cstotal(sb);
size = uspi->s_cssize;
blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift;
@@ -621,6 +624,9 @@ static void ufs_put_super_internal(struct super_block *sb)
brelse (sbi->s_ucg[i]);
kfree (sbi->s_ucg);
kfree (base);
+
+ unlock_kernel();
+
UFSD("EXIT\n");
}
@@ -1152,6 +1158,9 @@ static void ufs_put_super(struct super_block *sb)
UFSD("ENTER\n");
+ if (sb->s_dirt)
+ ufs_write_super(sb);
+
if (!(sb->s_flags & MS_RDONLY))
ufs_put_super_internal(sb);
@@ -1172,6 +1181,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
unsigned new_mount_opt, ufstype;
unsigned flags;
+ lock_super(sb);
uspi = UFS_SB(sb)->s_uspi;
flags = UFS_SB(sb)->s_flags;
usb1 = ubh_get_usb_first(uspi);
@@ -1184,17 +1194,21 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
ufstype = UFS_SB(sb)->s_mount_opt & UFS_MOUNT_UFSTYPE;
new_mount_opt = 0;
ufs_set_opt (new_mount_opt, ONERROR_LOCK);
- if (!ufs_parse_options (data, &new_mount_opt))
+ if (!ufs_parse_options (data, &new_mount_opt)) {
+ unlock_super(sb);
return -EINVAL;
+ }
if (!(new_mount_opt & UFS_MOUNT_UFSTYPE)) {
new_mount_opt |= ufstype;
} else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) {
printk("ufstype can't be changed during remount\n");
+ unlock_super(sb);
return -EINVAL;
}
if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
UFS_SB(sb)->s_mount_opt = new_mount_opt;
+ unlock_super(sb);
return 0;
}
@@ -1219,6 +1233,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
#ifndef CONFIG_UFS_FS_WRITE
printk("ufs was compiled with read-only support, "
"can't be mounted as read-write\n");
+ unlock_super(sb);
return -EINVAL;
#else
if (ufstype != UFS_MOUNT_UFSTYPE_SUN &&
@@ -1227,16 +1242,19 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
ufstype != UFS_MOUNT_UFSTYPE_SUNx86 &&
ufstype != UFS_MOUNT_UFSTYPE_UFS2) {
printk("this ufstype is read-only supported\n");
+ unlock_super(sb);
return -EINVAL;
}
if (!ufs_read_cylinder_structures(sb)) {
printk("failed during remounting\n");
+ unlock_super(sb);
return -EPERM;
}
sb->s_flags &= ~MS_RDONLY;
#endif
}
UFS_SB(sb)->s_mount_opt = new_mount_opt;
+ unlock_super(sb);
return 0;
}
diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h
index 69b3427d7885..d0c4acd4f1f3 100644
--- a/fs/ufs/ufs.h
+++ b/fs/ufs/ufs.h
@@ -98,8 +98,8 @@ extern void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
/* 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;
+extern int ufs_sync_file(struct file *, struct dentry *, int);
/* ialloc.c */
extern void ufs_free_inode (struct inode *inode);
diff --git a/fs/xattr.c b/fs/xattr.c
index 197c4fcac032..1c3d0af59ddf 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -237,13 +237,9 @@ setxattr(struct dentry *d, const char __user *name, const void __user *value,
if (size) {
if (size > XATTR_SIZE_MAX)
return -E2BIG;
- kvalue = kmalloc(size, GFP_KERNEL);
- if (!kvalue)
- return -ENOMEM;
- if (copy_from_user(kvalue, value, size)) {
- kfree(kvalue);
- return -EFAULT;
- }
+ kvalue = memdup_user(value, size);
+ if (IS_ERR(kvalue))
+ return PTR_ERR(kvalue);
}
error = vfs_setxattr(d, kname, kvalue, size, flags);
@@ -301,7 +297,7 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name,
return error;
dentry = f->f_path.dentry;
audit_inode(NULL, dentry);
- error = mnt_want_write(f->f_path.mnt);
+ error = mnt_want_write_file(f);
if (!error) {
error = setxattr(dentry, name, value, size, flags);
mnt_drop_write(f->f_path.mnt);
@@ -528,7 +524,7 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
return error;
dentry = f->f_path.dentry;
audit_inode(NULL, dentry);
- error = mnt_want_write(f->f_path.mnt);
+ error = mnt_want_write_file(f);
if (!error) {
error = removexattr(dentry, name);
mnt_drop_write(f->f_path.mnt);
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index c13f67300fe7..7ec89fc05b2b 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -153,23 +153,6 @@ xfs_find_bdev_for_inode(
}
/*
- * Schedule IO completion handling on a xfsdatad if this was
- * the final hold on this ioend. If we are asked to wait,
- * flush the workqueue.
- */
-STATIC void
-xfs_finish_ioend(
- xfs_ioend_t *ioend,
- int wait)
-{
- if (atomic_dec_and_test(&ioend->io_remaining)) {
- queue_work(xfsdatad_workqueue, &ioend->io_work);
- if (wait)
- flush_workqueue(xfsdatad_workqueue);
- }
-}
-
-/*
* We're now finished for good with this ioend structure.
* Update the page state via the associated buffer_heads,
* release holds on the inode and bio, and finally free
@@ -310,6 +293,27 @@ xfs_end_bio_read(
}
/*
+ * Schedule IO completion handling on a xfsdatad if this was
+ * the final hold on this ioend. If we are asked to wait,
+ * flush the workqueue.
+ */
+STATIC void
+xfs_finish_ioend(
+ xfs_ioend_t *ioend,
+ int wait)
+{
+ if (atomic_dec_and_test(&ioend->io_remaining)) {
+ struct workqueue_struct *wq = xfsdatad_workqueue;
+ if (ioend->io_work.func == xfs_end_bio_unwritten)
+ wq = xfsconvertd_workqueue;
+
+ queue_work(wq, &ioend->io_work);
+ if (wait)
+ flush_workqueue(wq);
+ }
+}
+
+/*
* Allocate and initialise an IO completion structure.
* We need to track unwritten extent write completion here initially.
* We'll need to extend this for updating the ondisk inode size later
diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h
index 1dd528849755..221b3e66ceef 100644
--- a/fs/xfs/linux-2.6/xfs_aops.h
+++ b/fs/xfs/linux-2.6/xfs_aops.h
@@ -19,6 +19,7 @@
#define __XFS_AOPS_H__
extern struct workqueue_struct *xfsdatad_workqueue;
+extern struct workqueue_struct *xfsconvertd_workqueue;
extern mempool_t *xfs_ioend_pool;
/*
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index aa1016bb9134..e28800a9f2b5 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -51,6 +51,7 @@ static struct shrinker xfs_buf_shake = {
static struct workqueue_struct *xfslogd_workqueue;
struct workqueue_struct *xfsdatad_workqueue;
+struct workqueue_struct *xfsconvertd_workqueue;
#ifdef XFS_BUF_TRACE
void
@@ -1775,6 +1776,7 @@ xfs_flush_buftarg(
xfs_buf_t *bp, *n;
int pincount = 0;
+ xfs_buf_runall_queues(xfsconvertd_workqueue);
xfs_buf_runall_queues(xfsdatad_workqueue);
xfs_buf_runall_queues(xfslogd_workqueue);
@@ -1831,9 +1833,15 @@ xfs_buf_init(void)
if (!xfsdatad_workqueue)
goto out_destroy_xfslogd_workqueue;
+ xfsconvertd_workqueue = create_workqueue("xfsconvertd");
+ if (!xfsconvertd_workqueue)
+ goto out_destroy_xfsdatad_workqueue;
+
register_shrinker(&xfs_buf_shake);
return 0;
+ out_destroy_xfsdatad_workqueue:
+ destroy_workqueue(xfsdatad_workqueue);
out_destroy_xfslogd_workqueue:
destroy_workqueue(xfslogd_workqueue);
out_free_buf_zone:
@@ -1849,6 +1857,7 @@ void
xfs_buf_terminate(void)
{
unregister_shrinker(&xfs_buf_shake);
+ destroy_workqueue(xfsconvertd_workqueue);
destroy_workqueue(xfsdatad_workqueue);
destroy_workqueue(xfslogd_workqueue);
kmem_zone_destroy(xfs_buf_zone);
diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c
index 5aeb77776961..08be36d7326c 100644
--- a/fs/xfs/linux-2.6/xfs_fs_subr.c
+++ b/fs/xfs/linux-2.6/xfs_fs_subr.c
@@ -74,14 +74,14 @@ xfs_flush_pages(
if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
xfs_iflags_clear(ip, XFS_ITRUNCATED);
- ret = filemap_fdatawrite(mapping);
- if (flags & XFS_B_ASYNC)
- return -ret;
- ret2 = filemap_fdatawait(mapping);
- if (!ret)
- ret = ret2;
+ ret = -filemap_fdatawrite(mapping);
}
- return -ret;
+ if (flags & XFS_B_ASYNC)
+ return ret;
+ ret2 = xfs_wait_on_pages(ip, first, last);
+ if (!ret)
+ ret = ret2;
+ return ret;
}
int
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index d0b499418a7d..34eaab608e6e 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -489,17 +489,12 @@ xfs_attrmulti_attr_set(
if (len > XATTR_SIZE_MAX)
return EINVAL;
- kbuf = kmalloc(len, GFP_KERNEL);
- if (!kbuf)
- return ENOMEM;
-
- if (copy_from_user(kbuf, ubuf, len))
- goto out_kfree;
+ kbuf = memdup_user(ubuf, len);
+ if (IS_ERR(kbuf))
+ return PTR_ERR(kbuf);
error = xfs_attr_set(XFS_I(inode), name, kbuf, len, flags);
- out_kfree:
- kfree(kbuf);
return error;
}
@@ -540,20 +535,16 @@ xfs_attrmulti_by_handle(
if (!size || size > 16 * PAGE_SIZE)
goto out_dput;
- error = ENOMEM;
- ops = kmalloc(size, GFP_KERNEL);
- if (!ops)
+ ops = memdup_user(am_hreq.ops, size);
+ if (IS_ERR(ops)) {
+ error = PTR_ERR(ops);
goto out_dput;
-
- error = EFAULT;
- if (copy_from_user(ops, am_hreq.ops, size))
- goto out_kfree_ops;
+ }
attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL);
if (!attr_name)
goto out_kfree_ops;
-
error = 0;
for (i = 0; i < am_hreq.opcount; i++) {
ops[i].am_error = strncpy_from_user(attr_name,
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index c70c4e3db790..0882d166239a 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -427,20 +427,16 @@ xfs_compat_attrmulti_by_handle(
if (!size || size > 16 * PAGE_SIZE)
goto out_dput;
- error = ENOMEM;
- ops = kmalloc(size, GFP_KERNEL);
- if (!ops)
+ ops = memdup_user(compat_ptr(am_hreq.ops), size);
+ if (IS_ERR(ops)) {
+ error = PTR_ERR(ops);
goto out_dput;
-
- error = EFAULT;
- if (copy_from_user(ops, compat_ptr(am_hreq.ops), size))
- goto out_kfree_ops;
+ }
attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL);
if (!attr_name)
goto out_kfree_ops;
-
error = 0;
for (i = 0; i < am_hreq.opcount; i++) {
ops[i].am_error = strncpy_from_user(attr_name,
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 7e90daa0d1d1..9142192ccbe6 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -751,10 +751,26 @@ start:
goto relock;
}
} else {
+ int enospc = 0;
+ ssize_t ret2 = 0;
+
+write_retry:
xfs_rw_enter_trace(XFS_WRITE_ENTER, xip, (void *)iovp, segs,
*offset, ioflags);
- ret = generic_file_buffered_write(iocb, iovp, segs,
+ ret2 = generic_file_buffered_write(iocb, iovp, segs,
pos, offset, count, ret);
+ /*
+ * if we just got an ENOSPC, flush the inode now we
+ * aren't holding any page locks and retry *once*
+ */
+ if (ret2 == -ENOSPC && !enospc) {
+ error = xfs_flush_pages(xip, 0, -1, 0, FI_NONE);
+ if (error)
+ goto out_unlock_internal;
+ enospc = 1;
+ goto write_retry;
+ }
+ ret = ret2;
}
current->backing_dev_info = NULL;
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index bb685269f832..d29218edd81e 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -1062,6 +1062,8 @@ xfs_fs_put_super(
struct xfs_inode *rip = mp->m_rootip;
int unmount_event_flags = 0;
+ lock_kernel();
+
xfs_syncd_stop(mp);
xfs_sync_inodes(mp, SYNC_ATTR|SYNC_DELWRI);
@@ -1102,6 +1104,8 @@ xfs_fs_put_super(
xfs_dmops_put(mp);
xfs_free_fsname(mp);
kfree(mp);
+
+ unlock_kernel();
}
STATIC void
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index a608e72fa405..f7ba76633c29 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -62,12 +62,6 @@ xfs_sync_inodes_ag(
uint32_t first_index = 0;
int error = 0;
int last_error = 0;
- int fflag = XFS_B_ASYNC;
-
- if (flags & SYNC_DELWRI)
- fflag = XFS_B_DELWRI;
- if (flags & SYNC_WAIT)
- fflag = 0; /* synchronous overrides all */
do {
struct inode *inode;
@@ -128,11 +122,23 @@ xfs_sync_inodes_ag(
* If we have to flush data or wait for I/O completion
* we need to hold the iolock.
*/
- if ((flags & SYNC_DELWRI) && VN_DIRTY(inode)) {
- xfs_ilock(ip, XFS_IOLOCK_SHARED);
- lock_flags |= XFS_IOLOCK_SHARED;
- error = xfs_flush_pages(ip, 0, -1, fflag, FI_NONE);
- if (flags & SYNC_IOWAIT)
+ if (flags & SYNC_DELWRI) {
+ if (VN_DIRTY(inode)) {
+ if (flags & SYNC_TRYLOCK) {
+ if (xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED))
+ lock_flags |= XFS_IOLOCK_SHARED;
+ } else {
+ xfs_ilock(ip, XFS_IOLOCK_SHARED);
+ lock_flags |= XFS_IOLOCK_SHARED;
+ }
+ if (lock_flags & XFS_IOLOCK_SHARED) {
+ error = xfs_flush_pages(ip, 0, -1,
+ (flags & SYNC_WAIT) ? 0
+ : XFS_B_ASYNC,
+ FI_NONE);
+ }
+ }
+ if (VN_CACHED(inode) && (flags & SYNC_IOWAIT))
xfs_ioend_wait(ip);
}
xfs_ilock(ip, XFS_ILOCK_SHARED);
@@ -398,15 +404,17 @@ STATIC void
xfs_syncd_queue_work(
struct xfs_mount *mp,
void *data,
- void (*syncer)(struct xfs_mount *, void *))
+ void (*syncer)(struct xfs_mount *, void *),
+ struct completion *completion)
{
- struct bhv_vfs_sync_work *work;
+ struct xfs_sync_work *work;
- work = kmem_alloc(sizeof(struct bhv_vfs_sync_work), KM_SLEEP);
+ work = kmem_alloc(sizeof(struct xfs_sync_work), KM_SLEEP);
INIT_LIST_HEAD(&work->w_list);
work->w_syncer = syncer;
work->w_data = data;
work->w_mount = mp;
+ work->w_completion = completion;
spin_lock(&mp->m_sync_lock);
list_add_tail(&work->w_list, &mp->m_sync_list);
spin_unlock(&mp->m_sync_lock);
@@ -420,49 +428,26 @@ xfs_syncd_queue_work(
* heads, looking about for more room...
*/
STATIC void
-xfs_flush_inode_work(
- struct xfs_mount *mp,
- void *arg)
-{
- struct inode *inode = arg;
- filemap_flush(inode->i_mapping);
- iput(inode);
-}
-
-void
-xfs_flush_inode(
- xfs_inode_t *ip)
-{
- struct inode *inode = VFS_I(ip);
-
- igrab(inode);
- xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inode_work);
- delay(msecs_to_jiffies(500));
-}
-
-/*
- * This is the "bigger hammer" version of xfs_flush_inode_work...
- * (IOW, "If at first you don't succeed, use a Bigger Hammer").
- */
-STATIC void
-xfs_flush_device_work(
+xfs_flush_inodes_work(
struct xfs_mount *mp,
void *arg)
{
struct inode *inode = arg;
- sync_blockdev(mp->m_super->s_bdev);
+ xfs_sync_inodes(mp, SYNC_DELWRI | SYNC_TRYLOCK);
+ xfs_sync_inodes(mp, SYNC_DELWRI | SYNC_TRYLOCK | SYNC_IOWAIT);
iput(inode);
}
void
-xfs_flush_device(
+xfs_flush_inodes(
xfs_inode_t *ip)
{
struct inode *inode = VFS_I(ip);
+ DECLARE_COMPLETION_ONSTACK(completion);
igrab(inode);
- xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_device_work);
- delay(msecs_to_jiffies(500));
+ xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inodes_work, &completion);
+ wait_for_completion(&completion);
xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
}
@@ -497,7 +482,7 @@ xfssyncd(
{
struct xfs_mount *mp = arg;
long timeleft;
- bhv_vfs_sync_work_t *work, *n;
+ xfs_sync_work_t *work, *n;
LIST_HEAD (tmp);
set_freezable();
@@ -532,6 +517,8 @@ xfssyncd(
list_del(&work->w_list);
if (work == &mp->m_sync_work)
continue;
+ if (work->w_completion)
+ complete(work->w_completion);
kmem_free(work);
}
}
@@ -545,6 +532,7 @@ xfs_syncd_init(
{
mp->m_sync_work.w_syncer = xfs_sync_worker;
mp->m_sync_work.w_mount = mp;
+ mp->m_sync_work.w_completion = NULL;
mp->m_sync_task = kthread_run(xfssyncd, mp, "xfssyncd");
if (IS_ERR(mp->m_sync_task))
return -PTR_ERR(mp->m_sync_task);
diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h
index 04f058c848ae..308d5bf6dfbd 100644
--- a/fs/xfs/linux-2.6/xfs_sync.h
+++ b/fs/xfs/linux-2.6/xfs_sync.h
@@ -21,18 +21,20 @@
struct xfs_mount;
struct xfs_perag;
-typedef struct bhv_vfs_sync_work {
+typedef struct xfs_sync_work {
struct list_head w_list;
struct xfs_mount *w_mount;
void *w_data; /* syncer routine argument */
void (*w_syncer)(struct xfs_mount *, void *);
-} bhv_vfs_sync_work_t;
+ struct completion *w_completion;
+} xfs_sync_work_t;
#define SYNC_ATTR 0x0001 /* sync attributes */
#define SYNC_DELWRI 0x0002 /* look at delayed writes */
#define SYNC_WAIT 0x0004 /* wait for i/o to complete */
#define SYNC_BDFLUSH 0x0008 /* BDFLUSH is calling -- don't block */
#define SYNC_IOWAIT 0x0010 /* wait for all I/O to complete */
+#define SYNC_TRYLOCK 0x0020 /* only try to lock inodes */
int xfs_syncd_init(struct xfs_mount *mp);
void xfs_syncd_stop(struct xfs_mount *mp);
@@ -43,8 +45,7 @@ int xfs_sync_fsdata(struct xfs_mount *mp, int flags);
int xfs_quiesce_data(struct xfs_mount *mp);
void xfs_quiesce_attr(struct xfs_mount *mp);
-void xfs_flush_inode(struct xfs_inode *ip);
-void xfs_flush_device(struct xfs_inode *ip);
+void xfs_flush_inodes(struct xfs_inode *ip);
int xfs_reclaim_inode(struct xfs_inode *ip, int locked, int sync_mode);
int xfs_reclaim_inodes(struct xfs_mount *mp, int noblock, int mode);
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 3a6ed426327a..ca7c6005a487 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -5880,7 +5880,7 @@ xfs_getbmap(
void *arg) /* formatter arg */
{
__int64_t bmvend; /* last block requested */
- int error; /* return value */
+ int error = 0; /* return value */
__int64_t fixlen; /* length for -1 case */
int i; /* extent number */
int lock; /* lock state */
@@ -5890,39 +5890,18 @@ xfs_getbmap(
int nexleft; /* # of user extents left */
int subnex; /* # of bmapi's can do */
int nmap; /* number of map entries */
- struct getbmapx out; /* output structure */
+ struct getbmapx *out; /* output structure */
int whichfork; /* data or attr fork */
int prealloced; /* this is a file with
* preallocated data space */
int iflags; /* interface flags */
int bmapi_flags; /* flags for xfs_bmapi */
+ int cur_ext = 0;
mp = ip->i_mount;
iflags = bmv->bmv_iflags;
-
whichfork = iflags & BMV_IF_ATTRFORK ? XFS_ATTR_FORK : XFS_DATA_FORK;
- /* If the BMV_IF_NO_DMAPI_READ interface bit specified, do not
- * generate a DMAPI read event. Otherwise, if the DM_EVENT_READ
- * bit is set for the file, generate a read event in order
- * that the DMAPI application may do its thing before we return
- * the extents. Usually this means restoring user file data to
- * regions of the file that look like holes.
- *
- * The "old behavior" (from XFS_IOC_GETBMAP) is to not specify
- * BMV_IF_NO_DMAPI_READ so that read events are generated.
- * If this were not true, callers of ioctl( XFS_IOC_GETBMAP )
- * could misinterpret holes in a DMAPI file as true holes,
- * when in fact they may represent offline user data.
- */
- if ((iflags & 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, ip, 0, 0, 0, NULL);
- if (error)
- return XFS_ERROR(error);
- }
-
if (whichfork == XFS_ATTR_FORK) {
if (XFS_IFORK_Q(ip)) {
if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS &&
@@ -5936,11 +5915,37 @@ xfs_getbmap(
ip->i_mount);
return XFS_ERROR(EFSCORRUPTED);
}
- } else if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS &&
- ip->i_d.di_format != XFS_DINODE_FMT_BTREE &&
- ip->i_d.di_format != XFS_DINODE_FMT_LOCAL)
- return XFS_ERROR(EINVAL);
- if (whichfork == XFS_DATA_FORK) {
+
+ prealloced = 0;
+ fixlen = 1LL << 32;
+ } else {
+ /*
+ * If the BMV_IF_NO_DMAPI_READ interface bit specified, do
+ * not generate a DMAPI read event. Otherwise, if the
+ * DM_EVENT_READ bit is set for the file, generate a read
+ * event in order that the DMAPI application may do its thing
+ * before we return the extents. Usually this means restoring
+ * user file data to regions of the file that look like holes.
+ *
+ * The "old behavior" (from XFS_IOC_GETBMAP) is to not specify
+ * BMV_IF_NO_DMAPI_READ so that read events are generated.
+ * If this were not true, callers of ioctl(XFS_IOC_GETBMAP)
+ * could misinterpret holes in a DMAPI file as true holes,
+ * when in fact they may represent offline user data.
+ */
+ if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) &&
+ !(iflags & BMV_IF_NO_DMAPI_READ)) {
+ error = XFS_SEND_DATA(mp, DM_EVENT_READ, ip,
+ 0, 0, 0, NULL);
+ if (error)
+ return XFS_ERROR(error);
+ }
+
+ if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS &&
+ ip->i_d.di_format != XFS_DINODE_FMT_BTREE &&
+ ip->i_d.di_format != XFS_DINODE_FMT_LOCAL)
+ return XFS_ERROR(EINVAL);
+
if (xfs_get_extsz_hint(ip) ||
ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)){
prealloced = 1;
@@ -5949,42 +5954,41 @@ xfs_getbmap(
prealloced = 0;
fixlen = ip->i_size;
}
- } else {
- prealloced = 0;
- fixlen = 1LL << 32;
}
if (bmv->bmv_length == -1) {
fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, fixlen));
- bmv->bmv_length = MAX( (__int64_t)(fixlen - bmv->bmv_offset),
- (__int64_t)0);
- } else if (bmv->bmv_length < 0)
- return XFS_ERROR(EINVAL);
- if (bmv->bmv_length == 0) {
+ bmv->bmv_length =
+ max_t(__int64_t, fixlen - bmv->bmv_offset, 0);
+ } else if (bmv->bmv_length == 0) {
bmv->bmv_entries = 0;
return 0;
+ } else if (bmv->bmv_length < 0) {
+ return XFS_ERROR(EINVAL);
}
+
nex = bmv->bmv_count - 1;
if (nex <= 0)
return XFS_ERROR(EINVAL);
bmvend = bmv->bmv_offset + bmv->bmv_length;
- xfs_ilock(ip, XFS_IOLOCK_SHARED);
- if (((iflags & BMV_IF_DELALLOC) == 0) &&
- (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 = xfs_flush_pages(ip, (xfs_off_t)0,
- -1, 0, FI_REMAPF);
- if (error) {
- xfs_iunlock(ip, XFS_IOLOCK_SHARED);
- return error;
+ if (bmv->bmv_count > ULONG_MAX / sizeof(struct getbmapx))
+ return XFS_ERROR(ENOMEM);
+ out = kmem_zalloc(bmv->bmv_count * sizeof(struct getbmapx), KM_MAYFAIL);
+ if (!out)
+ return XFS_ERROR(ENOMEM);
+
+ xfs_ilock(ip, XFS_IOLOCK_SHARED);
+ if (whichfork == XFS_DATA_FORK && !(iflags & BMV_IF_DELALLOC)) {
+ if (ip->i_delayed_blks || ip->i_size > ip->i_d.di_size) {
+ error = xfs_flush_pages(ip, 0, -1, 0, FI_REMAPF);
+ if (error)
+ goto out_unlock_iolock;
}
- }
- ASSERT(whichfork == XFS_ATTR_FORK || (iflags & BMV_IF_DELALLOC) ||
- ip->i_delayed_blks == 0);
+ ASSERT(ip->i_delayed_blks == 0);
+ }
lock = xfs_ilock_map_shared(ip);
@@ -5995,23 +5999,25 @@ xfs_getbmap(
if (nex > XFS_IFORK_NEXTENTS(ip, whichfork) * 2 + 1)
nex = XFS_IFORK_NEXTENTS(ip, whichfork) * 2 + 1;
- bmapi_flags = xfs_bmapi_aflag(whichfork) |
- ((iflags & BMV_IF_PREALLOC) ? 0 : XFS_BMAPI_IGSTATE);
+ bmapi_flags = xfs_bmapi_aflag(whichfork);
+ if (!(iflags & BMV_IF_PREALLOC))
+ bmapi_flags |= XFS_BMAPI_IGSTATE;
/*
* Allocate enough space to handle "subnex" maps at a time.
*/
+ error = ENOMEM;
subnex = 16;
- map = kmem_alloc(subnex * sizeof(*map), KM_SLEEP);
+ map = kmem_alloc(subnex * sizeof(*map), KM_MAYFAIL);
+ if (!map)
+ goto out_unlock_ilock;
bmv->bmv_entries = 0;
- if ((XFS_IFORK_NEXTENTS(ip, whichfork) == 0)) {
- if (((iflags & BMV_IF_DELALLOC) == 0) ||
- whichfork == XFS_ATTR_FORK) {
- error = 0;
- goto unlock_and_return;
- }
+ if (XFS_IFORK_NEXTENTS(ip, whichfork) == 0 &&
+ (whichfork == XFS_ATTR_FORK || !(iflags & BMV_IF_DELALLOC))) {
+ error = 0;
+ goto out_free_map;
}
nexleft = nex;
@@ -6023,53 +6029,61 @@ xfs_getbmap(
bmapi_flags, NULL, 0, map, &nmap,
NULL, NULL);
if (error)
- goto unlock_and_return;
+ goto out_free_map;
ASSERT(nmap <= subnex);
for (i = 0; i < nmap && nexleft && bmv->bmv_length; i++) {
- out.bmv_oflags = 0;
+ out[cur_ext].bmv_oflags = 0;
if (map[i].br_state == XFS_EXT_UNWRITTEN)
- out.bmv_oflags |= BMV_OF_PREALLOC;
+ out[cur_ext].bmv_oflags |= BMV_OF_PREALLOC;
else if (map[i].br_startblock == DELAYSTARTBLOCK)
- out.bmv_oflags |= BMV_OF_DELALLOC;
- out.bmv_offset = XFS_FSB_TO_BB(mp, map[i].br_startoff);
- out.bmv_length = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
- out.bmv_unused1 = out.bmv_unused2 = 0;
+ out[cur_ext].bmv_oflags |= BMV_OF_DELALLOC;
+ out[cur_ext].bmv_offset =
+ XFS_FSB_TO_BB(mp, map[i].br_startoff);
+ out[cur_ext].bmv_length =
+ XFS_FSB_TO_BB(mp, map[i].br_blockcount);
+ out[cur_ext].bmv_unused1 = 0;
+ out[cur_ext].bmv_unused2 = 0;
ASSERT(((iflags & BMV_IF_DELALLOC) != 0) ||
(map[i].br_startblock != DELAYSTARTBLOCK));
if (map[i].br_startblock == HOLESTARTBLOCK &&
whichfork == XFS_ATTR_FORK) {
/* came to the end of attribute fork */
- out.bmv_oflags |= BMV_OF_LAST;
- goto unlock_and_return;
- } else {
- int full = 0; /* user array is full */
-
- if (!xfs_getbmapx_fix_eof_hole(ip, &out,
- prealloced, bmvend,
- map[i].br_startblock)) {
- goto unlock_and_return;
- }
-
- /* format results & advance arg */
- error = formatter(&arg, &out, &full);
- if (error || full)
- goto unlock_and_return;
- nexleft--;
- bmv->bmv_offset =
- out.bmv_offset + out.bmv_length;
- bmv->bmv_length = MAX((__int64_t)0,
- (__int64_t)(bmvend - bmv->bmv_offset));
- bmv->bmv_entries++;
+ out[cur_ext].bmv_oflags |= BMV_OF_LAST;
+ goto out_free_map;
}
+
+ if (!xfs_getbmapx_fix_eof_hole(ip, &out[cur_ext],
+ prealloced, bmvend,
+ map[i].br_startblock))
+ goto out_free_map;
+
+ nexleft--;
+ bmv->bmv_offset =
+ out[cur_ext].bmv_offset +
+ out[cur_ext].bmv_length;
+ bmv->bmv_length =
+ max_t(__int64_t, 0, bmvend - bmv->bmv_offset);
+ bmv->bmv_entries++;
+ cur_ext++;
}
} while (nmap && nexleft && bmv->bmv_length);
-unlock_and_return:
+ out_free_map:
+ kmem_free(map);
+ out_unlock_ilock:
xfs_iunlock_map_shared(ip, lock);
+ out_unlock_iolock:
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
- kmem_free(map);
+ for (i = 0; i < cur_ext; i++) {
+ int full = 0; /* user array is full */
+
+ /* format results & advance arg */
+ error = formatter(&arg, &out[i], &full);
+ if (error || full)
+ break;
+ }
return error;
}
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index e6d839bddbf0..7465f9ee125f 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -347,13 +347,15 @@ xfs_swap_extents(
error = xfs_trans_commit(tp, XFS_TRANS_SWAPEXT);
-out_unlock:
- xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
- xfs_iunlock(tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
out:
kmem_free(tempifp);
return error;
+out_unlock:
+ xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
+ xfs_iunlock(tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
+ goto out;
+
out_trans_cancel:
xfs_trans_cancel(tp, 0);
goto out_unlock;
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index 478e587087fe..89b81eedce6a 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -69,15 +69,6 @@ xfs_inode_alloc(
ASSERT(!spin_is_locked(&ip->i_flags_lock));
ASSERT(completion_done(&ip->i_flush));
- /*
- * initialise the VFS inode here to get failures
- * out of the way early.
- */
- if (!inode_init_always(mp->m_super, VFS_I(ip))) {
- kmem_zone_free(xfs_inode_zone, ip);
- return NULL;
- }
-
/* initialise the xfs inode */
ip->i_ino = ino;
ip->i_mount = mp;
@@ -113,6 +104,20 @@ xfs_inode_alloc(
#ifdef XFS_DIR2_TRACE
ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS);
#endif
+ /*
+ * Now initialise the VFS inode. We do this after the xfs_inode
+ * initialisation as internal failures will result in ->destroy_inode
+ * being called and that will pass down through the reclaim path and
+ * free the XFS inode. This path requires the XFS inode to already be
+ * initialised. Hence if this call fails, the xfs_inode has already
+ * been freed and we should not reference it at all in the error
+ * handling.
+ */
+ if (!inode_init_always(mp->m_super, VFS_I(ip)))
+ return NULL;
+
+ /* prevent anyone from using this yet */
+ VFS_I(ip)->i_state = I_NEW|I_LOCK;
return ip;
}
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index e7ae08d1df48..123b20c8cbf2 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1258,8 +1258,10 @@ xfs_file_last_byte(
* necessary.
*/
if (ip->i_df.if_flags & XFS_IFEXTENTS) {
+ xfs_ilock(ip, XFS_ILOCK_SHARED);
error = xfs_bmap_last_offset(NULL, ip, &last_block,
XFS_DATA_FORK);
+ xfs_iunlock(ip, XFS_ILOCK_SHARED);
if (error) {
last_block = 0;
}
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 08ce72316bfe..5aaa2d7ec155 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -338,38 +338,6 @@ xfs_iomap_eof_align_last_fsb(
}
STATIC int
-xfs_flush_space(
- xfs_inode_t *ip,
- int *fsynced,
- int *ioflags)
-{
- switch (*fsynced) {
- case 0:
- if (ip->i_delayed_blks) {
- xfs_iunlock(ip, XFS_ILOCK_EXCL);
- xfs_flush_inode(ip);
- xfs_ilock(ip, XFS_ILOCK_EXCL);
- *fsynced = 1;
- } else {
- *ioflags |= BMAPI_SYNC;
- *fsynced = 2;
- }
- return 0;
- case 1:
- *fsynced = 2;
- *ioflags |= BMAPI_SYNC;
- return 0;
- case 2:
- xfs_iunlock(ip, XFS_ILOCK_EXCL);
- xfs_flush_device(ip);
- xfs_ilock(ip, XFS_ILOCK_EXCL);
- *fsynced = 3;
- return 0;
- }
- return 1;
-}
-
-STATIC int
xfs_cmn_err_fsblock_zero(
xfs_inode_t *ip,
xfs_bmbt_irec_t *imap)
@@ -538,15 +506,9 @@ error_out:
}
/*
- * If the caller is doing a write at the end of the file,
- * then extend the allocation out to the file system's write
- * iosize. We clean up any extra space left over when the
- * file is closed in xfs_inactive().
- *
- * For sync writes, we are flushing delayed allocate space to
- * try to make additional space available for allocation near
- * the filesystem full boundary - preallocation hurts in that
- * situation, of course.
+ * If the caller is doing a write at the end of the file, then extend the
+ * allocation out to the file system's write iosize. We clean up any extra
+ * space left over when the file is closed in xfs_inactive().
*/
STATIC int
xfs_iomap_eof_want_preallocate(
@@ -565,7 +527,7 @@ xfs_iomap_eof_want_preallocate(
int n, error, imaps;
*prealloc = 0;
- if ((ioflag & BMAPI_SYNC) || (offset + count) <= ip->i_size)
+ if ((offset + count) <= ip->i_size)
return 0;
/*
@@ -611,7 +573,7 @@ xfs_iomap_write_delay(
xfs_extlen_t extsz;
int nimaps;
xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS];
- int prealloc, fsynced = 0;
+ int prealloc, flushed = 0;
int error;
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
@@ -627,12 +589,12 @@ xfs_iomap_write_delay(
extsz = xfs_get_extsz_hint(ip);
offset_fsb = XFS_B_TO_FSBT(mp, offset);
-retry:
error = xfs_iomap_eof_want_preallocate(mp, ip, offset, count,
ioflag, imap, XFS_WRITE_IMAPS, &prealloc);
if (error)
return error;
+retry:
if (prealloc) {
aligned_offset = XFS_WRITEIO_ALIGN(mp, (offset + count - 1));
ioalign = XFS_B_TO_FSBT(mp, aligned_offset);
@@ -659,15 +621,22 @@ retry:
/*
* If bmapi returned us nothing, and if we didn't get back EDQUOT,
- * then we must have run out of space - flush delalloc, and retry..
+ * then we must have run out of space - flush all other inodes with
+ * delalloc blocks and retry without EOF preallocation.
*/
if (nimaps == 0) {
xfs_iomap_enter_trace(XFS_IOMAP_WRITE_NOSPACE,
ip, offset, count);
- if (xfs_flush_space(ip, &fsynced, &ioflag))
+ if (flushed)
return XFS_ERROR(ENOSPC);
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ xfs_flush_inodes(ip);
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+
+ flushed = 1;
error = 0;
+ prealloc = 0;
goto retry;
}
diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h
index a1cc1322fc0f..fdcf7b82747f 100644
--- a/fs/xfs/xfs_iomap.h
+++ b/fs/xfs/xfs_iomap.h
@@ -40,8 +40,7 @@ typedef enum {
BMAPI_IGNSTATE = (1 << 4), /* ignore unwritten state on read */
BMAPI_DIRECT = (1 << 5), /* direct instead of buffered write */
BMAPI_MMAP = (1 << 6), /* allocate for mmap write */
- BMAPI_SYNC = (1 << 7), /* sync write to flush delalloc space */
- BMAPI_TRYLOCK = (1 << 8), /* non-blocking request */
+ BMAPI_TRYLOCK = (1 << 7), /* non-blocking request */
} bmapi_flags_t;
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index f76c6d7cea21..3750f04ede0b 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -562,9 +562,8 @@ xfs_log_mount(
}
mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks);
- if (!mp->m_log) {
- cmn_err(CE_WARN, "XFS: Log allocation failed: No memory!");
- error = ENOMEM;
+ if (IS_ERR(mp->m_log)) {
+ error = -PTR_ERR(mp->m_log);
goto out;
}
@@ -1180,10 +1179,13 @@ xlog_alloc_log(xfs_mount_t *mp,
xfs_buf_t *bp;
int i;
int iclogsize;
+ int error = ENOMEM;
log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL);
- if (!log)
- return NULL;
+ if (!log) {
+ xlog_warn("XFS: Log allocation failed: No memory!");
+ goto out;
+ }
log->l_mp = mp;
log->l_targ = log_target;
@@ -1201,19 +1203,35 @@ xlog_alloc_log(xfs_mount_t *mp,
log->l_grant_reserve_cycle = 1;
log->l_grant_write_cycle = 1;
+ error = EFSCORRUPTED;
if (xfs_sb_version_hassector(&mp->m_sb)) {
log->l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT;
- ASSERT(log->l_sectbb_log <= mp->m_sectbb_log);
+ if (log->l_sectbb_log < 0 ||
+ log->l_sectbb_log > mp->m_sectbb_log) {
+ xlog_warn("XFS: Log sector size (0x%x) out of range.",
+ log->l_sectbb_log);
+ goto out_free_log;
+ }
+
/* for larger sector sizes, must have v2 or external log */
- ASSERT(log->l_sectbb_log == 0 ||
- log->l_logBBstart == 0 ||
- xfs_sb_version_haslogv2(&mp->m_sb));
- ASSERT(mp->m_sb.sb_logsectlog >= BBSHIFT);
+ if (log->l_sectbb_log != 0 &&
+ (log->l_logBBstart != 0 &&
+ !xfs_sb_version_haslogv2(&mp->m_sb))) {
+ xlog_warn("XFS: log sector size (0x%x) invalid "
+ "for configuration.", log->l_sectbb_log);
+ goto out_free_log;
+ }
+ if (mp->m_sb.sb_logsectlog < BBSHIFT) {
+ xlog_warn("XFS: Log sector log (0x%x) too small.",
+ mp->m_sb.sb_logsectlog);
+ goto out_free_log;
+ }
}
log->l_sectbb_mask = (1 << log->l_sectbb_log) - 1;
xlog_get_iclog_buffer_size(mp, log);
+ error = ENOMEM;
bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp);
if (!bp)
goto out_free_log;
@@ -1313,7 +1331,8 @@ out_free_iclog:
xfs_buf_free(log->l_xbuf);
out_free_log:
kmem_free(log);
- return NULL;
+out:
+ return ERR_PTR(-error);
} /* xlog_alloc_log */
@@ -2541,18 +2560,19 @@ redo:
xlog_ins_ticketq(&log->l_reserve_headq, tic);
xlog_trace_loggrant(log, tic,
"xlog_grant_log_space: sleep 2");
+ spin_unlock(&log->l_grant_lock);
+ xlog_grant_push_ail(log->l_mp, need_bytes);
+ spin_lock(&log->l_grant_lock);
+
XFS_STATS_INC(xs_sleep_logspace);
sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s);
- if (XLOG_FORCED_SHUTDOWN(log)) {
- spin_lock(&log->l_grant_lock);
+ spin_lock(&log->l_grant_lock);
+ if (XLOG_FORCED_SHUTDOWN(log))
goto error_return;
- }
xlog_trace_loggrant(log, tic,
"xlog_grant_log_space: wake 2");
- xlog_grant_push_ail(log->l_mp, need_bytes);
- spin_lock(&log->l_grant_lock);
goto redo;
} else if (tic->t_flags & XLOG_TIC_IN_Q)
xlog_del_ticketq(&log->l_reserve_headq, tic);
@@ -2631,7 +2651,7 @@ xlog_regrant_write_log_space(xlog_t *log,
* for more free space, otherwise try to get some space for
* this transaction.
*/
-
+ need_bytes = tic->t_unit_res;
if ((ntic = log->l_write_headq)) {
free_bytes = xlog_space_left(log, log->l_grant_write_cycle,
log->l_grant_write_bytes);
@@ -2651,26 +2671,25 @@ xlog_regrant_write_log_space(xlog_t *log,
xlog_trace_loggrant(log, tic,
"xlog_regrant_write_log_space: sleep 1");
+ spin_unlock(&log->l_grant_lock);
+ xlog_grant_push_ail(log->l_mp, need_bytes);
+ spin_lock(&log->l_grant_lock);
+
XFS_STATS_INC(xs_sleep_logspace);
sv_wait(&tic->t_wait, PINOD|PLTWAIT,
&log->l_grant_lock, s);
/* If we're shutting down, this tic is already
* off the queue */
- if (XLOG_FORCED_SHUTDOWN(log)) {
- spin_lock(&log->l_grant_lock);
+ spin_lock(&log->l_grant_lock);
+ if (XLOG_FORCED_SHUTDOWN(log))
goto error_return;
- }
xlog_trace_loggrant(log, tic,
"xlog_regrant_write_log_space: wake 1");
- xlog_grant_push_ail(log->l_mp, tic->t_unit_res);
- spin_lock(&log->l_grant_lock);
}
}
- need_bytes = tic->t_unit_res;
-
redo:
if (XLOG_FORCED_SHUTDOWN(log))
goto error_return;
@@ -2680,19 +2699,20 @@ redo:
if (free_bytes < need_bytes) {
if ((tic->t_flags & XLOG_TIC_IN_Q) == 0)
xlog_ins_ticketq(&log->l_write_headq, tic);
+ spin_unlock(&log->l_grant_lock);
+ xlog_grant_push_ail(log->l_mp, need_bytes);
+ spin_lock(&log->l_grant_lock);
+
XFS_STATS_INC(xs_sleep_logspace);
sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s);
/* If we're shutting down, this tic is already off the queue */
- if (XLOG_FORCED_SHUTDOWN(log)) {
- spin_lock(&log->l_grant_lock);
+ spin_lock(&log->l_grant_lock);
+ if (XLOG_FORCED_SHUTDOWN(log))
goto error_return;
- }
xlog_trace_loggrant(log, tic,
"xlog_regrant_write_log_space: wake 2");
- xlog_grant_push_ail(log->l_mp, need_bytes);
- spin_lock(&log->l_grant_lock);
goto redo;
} else if (tic->t_flags & XLOG_TIC_IN_Q)
xlog_del_ticketq(&log->l_write_headq, tic);
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index b101990df027..65a99725d0cc 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -291,14 +291,17 @@ xfs_mount_validate_sb(
sbp->sb_sectsize > XFS_MAX_SECTORSIZE ||
sbp->sb_sectlog < XFS_MIN_SECTORSIZE_LOG ||
sbp->sb_sectlog > XFS_MAX_SECTORSIZE_LOG ||
+ sbp->sb_sectsize != (1 << sbp->sb_sectlog) ||
sbp->sb_blocksize < XFS_MIN_BLOCKSIZE ||
sbp->sb_blocksize > XFS_MAX_BLOCKSIZE ||
sbp->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG ||
sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG ||
+ sbp->sb_blocksize != (1 << sbp->sb_blocklog) ||
sbp->sb_inodesize < XFS_DINODE_MIN_SIZE ||
sbp->sb_inodesize > XFS_DINODE_MAX_SIZE ||
sbp->sb_inodelog < XFS_DINODE_MIN_LOG ||
sbp->sb_inodelog > XFS_DINODE_MAX_LOG ||
+ sbp->sb_inodesize != (1 << sbp->sb_inodelog) ||
(sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog) ||
(sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) ||
(sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) ||
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 7af44adffc8f..d6a64392f983 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -313,7 +313,7 @@ typedef struct xfs_mount {
#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 */
+ xfs_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. */
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 7394c7af5de5..19cf90a9c762 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -1457,6 +1457,13 @@ xfs_create(
error = xfs_trans_reserve(tp, resblks, log_res, 0,
XFS_TRANS_PERM_LOG_RES, log_count);
if (error == ENOSPC) {
+ /* flush outstanding delalloc blocks and retry */
+ xfs_flush_inodes(dp);
+ error = xfs_trans_reserve(tp, resblks, XFS_CREATE_LOG_RES(mp), 0,
+ XFS_TRANS_PERM_LOG_RES, XFS_CREATE_LOG_COUNT);
+ }
+ if (error == ENOSPC) {
+ /* No space at all so try a "no-allocation" reservation */
resblks = 0;
error = xfs_trans_reserve(tp, 0, log_res, 0,
XFS_TRANS_PERM_LOG_RES, log_count);
diff --git a/include/Kbuild b/include/Kbuild
index d8c3e3cbf416..8d226bfa2696 100644
--- a/include/Kbuild
+++ b/include/Kbuild
@@ -8,3 +8,5 @@ header-y += mtd/
header-y += rdma/
header-y += video/
header-y += drm/
+header-y += xen/
+header-y += scsi/
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 4db89e98535d..60b76a3fb3a1 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -47,7 +47,7 @@
/* Current ACPICA subsystem version in YYYYMMDD format */
-#define ACPI_CA_VERSION 0x20090320
+#define ACPI_CA_VERSION 0x20090422
#include "actypes.h"
#include "actbl.h"
@@ -375,7 +375,7 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state);
acpi_status acpi_leave_sleep_state(u8 sleep_state);
/*
- * Debug output
+ * Error/Warning output
*/
void ACPI_INTERNAL_VAR_XFACE
acpi_error(const char *module_name,
@@ -394,6 +394,9 @@ void ACPI_INTERNAL_VAR_XFACE
acpi_info(const char *module_name,
u32 line_number, const char *format, ...) ACPI_PRINTF_LIKE(3);
+/*
+ * Debug output
+ */
#ifdef ACPI_DEBUG_OUTPUT
void ACPI_INTERNAL_VAR_XFACE
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index f555d927f7c0..37ba576d06e8 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -429,20 +429,12 @@ typedef unsigned long long acpi_integer;
/* Data manipulation */
-#define ACPI_LOWORD(l) ((u16)(u32)(l))
-#define ACPI_HIWORD(l) ((u16)((((u32)(l)) >> 16) & 0xFFFF))
-#define ACPI_LOBYTE(l) ((u8)(u16)(l))
-#define ACPI_HIBYTE(l) ((u8)((((u16)(l)) >> 8) & 0xFF))
-
-/* Full 64-bit integer must be available on both 32-bit and 64-bit platforms */
-
-struct acpi_integer_overlay {
- u32 lo_dword;
- u32 hi_dword;
-};
-
-#define ACPI_LODWORD(integer) (ACPI_CAST_PTR (struct acpi_integer_overlay, &integer)->lo_dword)
-#define ACPI_HIDWORD(integer) (ACPI_CAST_PTR (struct acpi_integer_overlay, &integer)->hi_dword)
+#define ACPI_LOBYTE(integer) ((u8) (u16)(integer))
+#define ACPI_HIBYTE(integer) ((u8) (((u16)(integer)) >> 8))
+#define ACPI_LOWORD(integer) ((u16) (u32)(integer))
+#define ACPI_HIWORD(integer) ((u16)(((u32)(integer)) >> 16))
+#define ACPI_LODWORD(integer64) ((u32) (u64)(integer64))
+#define ACPI_HIDWORD(integer64) ((u32)(((u64)(integer64)) >> 32))
#define ACPI_SET_BIT(target,bit) ((target) |= (bit))
#define ACPI_CLEAR_BIT(target,bit) ((target) &= ~(bit))
diff --git a/include/acpi/platform/acgcc.h b/include/acpi/platform/acgcc.h
index 8e2cdc57b197..935c5d7fc86e 100644
--- a/include/acpi/platform/acgcc.h
+++ b/include/acpi/platform/acgcc.h
@@ -62,4 +62,8 @@
*/
#define ACPI_UNUSED_VAR __attribute__ ((unused))
+#ifdef _ANSI
+#define inline
+#endif
+
#endif /* __ACGCC_H__ */
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h
index 6d49b2a498c4..fcb8e4b159b1 100644
--- a/include/acpi/platform/aclinux.h
+++ b/include/acpi/platform/aclinux.h
@@ -1,11 +1,11 @@
/******************************************************************************
*
- * Name: aclinux.h - OS specific defines, etc.
+ * Name: aclinux.h - OS specific defines, etc. for Linux
*
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2008, Intel Corp.
+ * Copyright (C) 2000 - 2009, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -44,10 +44,13 @@
#ifndef __ACLINUX_H__
#define __ACLINUX_H__
+/* Common (in-kernel/user-space) ACPICA configuration */
+
#define ACPI_USE_SYSTEM_CLIBRARY
#define ACPI_USE_DO_WHILE_0
#define ACPI_MUTEX_TYPE ACPI_BINARY_SEMAPHORE
+
#ifdef __KERNEL__
#include <linux/string.h>
@@ -63,15 +66,18 @@
#include <linux/spinlock_types.h>
#include <asm/current.h>
-/* Host-dependent types and defines */
+/* Host-dependent types and defines for in-kernel ACPICA */
#define ACPI_MACHINE_WIDTH BITS_PER_LONG
-#define acpi_cache_t struct kmem_cache
-#define acpi_spinlock spinlock_t *
#define ACPI_EXPORT_SYMBOL(symbol) EXPORT_SYMBOL(symbol);
#define strtoul simple_strtoul
-#else /* !__KERNEL__ */
+#define acpi_cache_t struct kmem_cache
+#define acpi_spinlock spinlock_t *
+#define acpi_cpu_flags unsigned long
+#define acpi_thread_id struct task_struct *
+
+#else /* !__KERNEL__ */
#include <stdarg.h>
#include <string.h>
@@ -79,6 +85,11 @@
#include <ctype.h>
#include <unistd.h>
+/* Host-dependent types and defines for user-space ACPICA */
+
+#define ACPI_FLUSH_CPU_CACHE()
+#define acpi_thread_id pthread_t
+
#if defined(__ia64__) || defined(__x86_64__)
#define ACPI_MACHINE_WIDTH 64
#define COMPILER_DEPENDENT_INT64 long
@@ -94,17 +105,17 @@
#define __cdecl
#endif
-#define ACPI_FLUSH_CPU_CACHE()
-#endif /* __KERNEL__ */
+#endif /* __KERNEL__ */
/* Linux uses GCC */
#include "acgcc.h"
-#define acpi_cpu_flags unsigned long
-
-#define acpi_thread_id struct task_struct *
+#ifdef __KERNEL__
+/*
+ * Overrides for in-kernel ACPICA
+ */
static inline acpi_thread_id acpi_os_get_thread_id(void)
{
return current;
@@ -119,30 +130,32 @@ static inline acpi_thread_id acpi_os_get_thread_id(void)
#include <acpi/actypes.h>
static inline void *acpi_os_allocate(acpi_size size)
{
- return kmalloc(size, irqs_disabled()? GFP_ATOMIC : GFP_KERNEL);
+ return kmalloc(size, irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL);
}
+
static inline void *acpi_os_allocate_zeroed(acpi_size size)
{
- return kzalloc(size, irqs_disabled()? GFP_ATOMIC : GFP_KERNEL);
+ return kzalloc(size, irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL);
}
static inline void *acpi_os_acquire_object(acpi_cache_t * cache)
{
return kmem_cache_zalloc(cache,
- irqs_disabled()? GFP_ATOMIC : GFP_KERNEL);
+ irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL);
}
-#define ACPI_ALLOCATE(a) acpi_os_allocate(a)
-#define ACPI_ALLOCATE_ZEROED(a) acpi_os_allocate_zeroed(a)
-#define ACPI_FREE(a) kfree(a)
+#define ACPI_ALLOCATE(a) acpi_os_allocate(a)
+#define ACPI_ALLOCATE_ZEROED(a) acpi_os_allocate_zeroed(a)
+#define ACPI_FREE(a) kfree(a)
-/*
- * We need to show where it is safe to preempt execution of ACPICA
- */
-#define ACPI_PREEMPTION_POINT() \
- do { \
- if (!irqs_disabled()) \
- cond_resched(); \
+/* Used within ACPICA to show where it is safe to preempt execution */
+
+#define ACPI_PREEMPTION_POINT() \
+ do { \
+ if (!irqs_disabled()) \
+ cond_resched(); \
} while (0)
-#endif /* __ACLINUX_H__ */
+#endif /* __KERNEL__ */
+
+#endif /* __ACLINUX_H__ */
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index b09c4fde9725..4927c063347c 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -84,7 +84,6 @@ struct acpi_processor_power {
struct acpi_processor_cx *state;
unsigned long bm_check_timestamp;
u32 default_state;
- u32 bm_activity;
int count;
struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER];
int timer_broadcast_on_state;
diff --git a/include/acpi/video.h b/include/acpi/video.h
index f0275bb79ce4..af6fe95fd3d0 100644
--- a/include/acpi/video.h
+++ b/include/acpi/video.h
@@ -3,8 +3,10 @@
#if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE)
extern int acpi_video_register(void);
+extern int acpi_video_exit(void);
#else
static inline int acpi_video_register(void) { return 0; }
+static inline void acpi_video_exit(void) { return; }
#endif
#endif
diff --git a/include/asm-arm/.gitignore b/include/asm-arm/.gitignore
deleted file mode 100644
index e02c15d158fc..000000000000
--- a/include/asm-arm/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-arch
-mach-types.h
diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h
index 7abdaa91ccd3..3673a13b6703 100644
--- a/include/asm-generic/atomic.h
+++ b/include/asm-generic/atomic.h
@@ -132,9 +132,9 @@ static inline long atomic_long_add_unless(atomic_long_t *l, long a, long u)
#define atomic_long_inc_not_zero(l) atomic64_inc_not_zero((atomic64_t *)(l))
#define atomic_long_cmpxchg(l, old, new) \
- (atomic_cmpxchg((atomic64_t *)(l), (old), (new)))
+ (atomic64_cmpxchg((atomic64_t *)(l), (old), (new)))
#define atomic_long_xchg(v, new) \
- (atomic_xchg((atomic64_t *)(l), (new)))
+ (atomic64_xchg((atomic64_t *)(l), (new)))
#else /* BITS_PER_LONG == 64 */
diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
index 37b82cb96c89..4b6755984d24 100644
--- a/include/asm-generic/bug.h
+++ b/include/asm-generic/bug.h
@@ -58,12 +58,13 @@ struct bug_entry {
*/
#ifndef __WARN
#ifndef __ASSEMBLY__
-extern void warn_slowpath(const char *file, const int line,
+extern void warn_slowpath_fmt(const char *file, const int line,
const char *fmt, ...) __attribute__((format(printf, 3, 4)));
+extern void warn_slowpath_null(const char *file, const int line);
#define WANT_WARN_ON_SLOWPATH
#endif
-#define __WARN() warn_slowpath(__FILE__, __LINE__, NULL)
-#define __WARN_printf(arg...) warn_slowpath(__FILE__, __LINE__, arg)
+#define __WARN() warn_slowpath_null(__FILE__, __LINE__)
+#define __WARN_printf(arg...) warn_slowpath_fmt(__FILE__, __LINE__, arg)
#else
#define __WARN_printf(arg...) do { printk(arg); __WARN(); } while (0)
#endif
@@ -88,7 +89,7 @@ extern void warn_slowpath(const char *file, const int line,
#else /* !CONFIG_BUG */
#ifndef HAVE_ARCH_BUG
-#define BUG()
+#define BUG() do {} while(0)
#endif
#ifndef HAVE_ARCH_BUG_ON
diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h
index b0e63c672ebd..d7d50d7ee51e 100644
--- a/include/asm-generic/percpu.h
+++ b/include/asm-generic/percpu.h
@@ -1,13 +1,9 @@
#ifndef _ASM_GENERIC_PERCPU_H_
#define _ASM_GENERIC_PERCPU_H_
+
#include <linux/compiler.h>
#include <linux/threads.h>
-
-/*
- * Determine the real variable name from the name visible in the
- * kernel sources.
- */
-#define per_cpu_var(var) per_cpu__##var
+#include <linux/percpu-defs.h>
#ifdef CONFIG_SMP
@@ -73,11 +69,32 @@ extern void setup_per_cpu_areas(void);
#endif /* SMP */
+#ifndef PER_CPU_BASE_SECTION
+#ifdef CONFIG_SMP
+#define PER_CPU_BASE_SECTION ".data.percpu"
+#else
+#define PER_CPU_BASE_SECTION ".data"
+#endif
+#endif
+
+#ifdef CONFIG_SMP
+
+#ifdef MODULE
+#define PER_CPU_SHARED_ALIGNED_SECTION ""
+#else
+#define PER_CPU_SHARED_ALIGNED_SECTION ".shared_aligned"
+#endif
+#define PER_CPU_FIRST_SECTION ".first"
+
+#else
+
+#define PER_CPU_SHARED_ALIGNED_SECTION ""
+#define PER_CPU_FIRST_SECTION ""
+
+#endif
+
#ifndef PER_CPU_ATTRIBUTES
#define PER_CPU_ATTRIBUTES
#endif
-#define DECLARE_PER_CPU(type, name) extern PER_CPU_ATTRIBUTES \
- __typeof__(type) per_cpu_var(name)
-
#endif /* _ASM_GENERIC_PERCPU_H_ */
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 8e6d0ca70aba..e410f602cab1 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -280,17 +280,18 @@ static inline void ptep_modify_prot_commit(struct mm_struct *mm,
#endif
/*
- * A facility to provide batching of the reload of page tables with the
- * actual context switch code for paravirtualized guests. By convention,
- * only one of the lazy modes (CPU, MMU) should be active at any given
- * time, entry should never be nested, and entry and exits should always
- * be paired. This is for sanity of maintaining and reasoning about the
- * kernel code.
+ * A facility to provide batching of the reload of page tables and
+ * other process state with the actual context switch code for
+ * paravirtualized guests. By convention, only one of the batched
+ * update (lazy) modes (CPU, MMU) should be active at any given time,
+ * entry should never be nested, and entry and exits should always be
+ * paired. This is for sanity of maintaining and reasoning about the
+ * kernel code. In this case, the exit (end of the context switch) is
+ * in architecture-specific code, and so doesn't need a generic
+ * definition.
*/
-#ifndef __HAVE_ARCH_ENTER_LAZY_CPU_MODE
-#define arch_enter_lazy_cpu_mode() do {} while (0)
-#define arch_leave_lazy_cpu_mode() do {} while (0)
-#define arch_flush_lazy_cpu_mode() do {} while (0)
+#ifndef __HAVE_ARCH_START_CONTEXT_SWITCH
+#define arch_start_context_switch(prev) do {} while (0)
#endif
#ifndef __HAVE_PFNMAP_TRACKING
diff --git a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h
index 35752dadd6df..c840719a8c59 100644
--- a/include/asm-generic/siginfo.h
+++ b/include/asm-generic/siginfo.h
@@ -201,7 +201,7 @@ typedef struct siginfo {
#define TRAP_TRACE (__SI_FAULT|2) /* process trace trap */
#define TRAP_BRANCH (__SI_FAULT|3) /* process taken branch trap */
#define TRAP_HWBKPT (__SI_FAULT|4) /* hardware breakpoint/watchpoint */
-#define NSIGTRAP 2
+#define NSIGTRAP 4
/*
* SIGCHLD si_codes
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 7fa660fd449c..f1736ca7922c 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -1,3 +1,5 @@
+#include <linux/section-names.h>
+
#ifndef LOAD_OFFSET
#define LOAD_OFFSET 0
#endif
@@ -61,7 +63,7 @@
#define BRANCH_PROFILE()
#endif
-#ifdef CONFIG_EVENT_TRACER
+#ifdef CONFIG_EVENT_TRACING
#define FTRACE_EVENTS() VMLINUX_SYMBOL(__start_ftrace_events) = .; \
*(_ftrace_events) \
VMLINUX_SYMBOL(__stop_ftrace_events) = .;
@@ -88,7 +90,6 @@
/* .data section */
#define DATA_DATA \
*(.data) \
- *(.data.init.refok) \
*(.ref.data) \
DEV_KEEP(init.data) \
DEV_KEEP(exit.data) \
@@ -287,8 +288,6 @@
*(.text.hot) \
*(.text) \
*(.ref.text) \
- *(.text.init.refok) \
- *(.exit.text.refok) \
DEV_KEEP(init.text) \
DEV_KEEP(exit.text) \
CPU_KEEP(init.text) \
@@ -331,7 +330,7 @@
#endif
/* Section used for early init (in .S files) */
-#define HEAD_TEXT *(.head.text)
+#define HEAD_TEXT *(HEAD_TEXT_SECTION)
/* init and exit section handling */
#define INIT_DATA \
diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h
index 2df74eb09563..fc55db780199 100644
--- a/include/drm/drm_pciids.h
+++ b/include/drm/drm_pciids.h
@@ -472,6 +472,7 @@
{0x8086, 0x2562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x8086, 0x3582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x8086, 0x358e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0, 0, 0}
#define gamma_PCI_IDS \
@@ -531,6 +532,8 @@
{0x8086, 0x2e02, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
{0x8086, 0x2e12, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
{0x8086, 0x2e22, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
+ {0x8086, 0x2e32, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
{0x8086, 0xa001, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
{0x8086, 0xa011, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
+ {0x8086, 0x35e8, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
{0, 0, 0}
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index 67e3353a56d6..95962fa8398a 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -594,6 +594,9 @@ struct drm_i915_gem_busy {
#define I915_BIT_6_SWIZZLE_9_10_11 4
/* Not seen by userland */
#define I915_BIT_6_SWIZZLE_UNKNOWN 5
+/* Seen by userland. */
+#define I915_BIT_6_SWIZZLE_9_17 6
+#define I915_BIT_6_SWIZZLE_9_10_17 7
struct drm_i915_gem_set_tiling {
/** Handle of the buffer to have its tiling state updated */
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index ca9b9b9bd331..3f0eaa397ef5 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -138,6 +138,7 @@ header-y += qnxtypes.h
header-y += radeonfb.h
header-y += raw.h
header-y += resource.h
+header-y += romfs_fs.h
header-y += rose.h
header-y += serial_reg.h
header-y += smbno.h
@@ -314,7 +315,6 @@ unifdef-y += irqnr.h
unifdef-y += reboot.h
unifdef-y += reiserfs_fs.h
unifdef-y += reiserfs_xattr.h
-unifdef-y += romfs_fs.h
unifdef-y += route.h
unifdef-y += rtc.h
unifdef-y += rtnetlink.h
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 6586cbd0d4af..51b4b0a5ce8c 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -111,6 +111,7 @@ int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base);
int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base);
void acpi_irq_stats_init(void);
extern u32 acpi_irq_handled;
+extern u32 acpi_irq_not_handled;
extern struct acpi_mcfg_allocation *pci_mmcfg_config;
extern int pci_mmcfg_config_num;
@@ -118,7 +119,7 @@ extern int pci_mmcfg_config_num;
extern int sbf_port;
extern unsigned long acpi_realmode_flags;
-int acpi_register_gsi (u32 gsi, int triggering, int polarity);
+int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity);
int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
#ifdef CONFIG_X86_IO_APIC
diff --git a/include/linux/atmel-mci.h b/include/linux/atmel-mci.h
index 2f1f95737acb..57b1846a3c87 100644
--- a/include/linux/atmel-mci.h
+++ b/include/linux/atmel-mci.h
@@ -10,6 +10,7 @@
* @bus_width: Number of data lines wired up the slot
* @detect_pin: GPIO pin wired to the card detect switch
* @wp_pin: GPIO pin wired to the write protect sensor
+ * @detect_is_active_high: The state of the detect pin when it is active
*
* If a given slot is not present on the board, @bus_width should be
* set to 0. The other fields are ignored in this case.
@@ -24,6 +25,7 @@ struct mci_slot_pdata {
unsigned int bus_width;
int detect_pin;
int wp_pin;
+ bool detect_is_active_high;
};
/**
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 6638b8148de7..61ee18c1bdb4 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -82,7 +82,19 @@ struct linux_binfmt {
int hasvdso;
};
-extern int register_binfmt(struct linux_binfmt *);
+extern int __register_binfmt(struct linux_binfmt *fmt, int insert);
+
+/* Registration of default binfmt handlers */
+static inline int register_binfmt(struct linux_binfmt *fmt)
+{
+ return __register_binfmt(fmt, 0);
+}
+/* Same as above, but adds a new binfmt at the top of the list */
+static inline int insert_binfmt(struct linux_binfmt *fmt)
+{
+ return __register_binfmt(fmt, 1);
+}
+
extern void unregister_binfmt(struct linux_binfmt *);
extern int prepare_binprm(struct linux_binprm *);
diff --git a/include/linux/bio.h b/include/linux/bio.h
index b900d2c67d29..f37ca8c726ba 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -132,6 +132,7 @@ struct bio {
* top 4 bits of bio flags indicate the pool this bio came from
*/
#define BIO_POOL_BITS (4)
+#define BIO_POOL_NONE ((1UL << BIO_POOL_BITS) - 1)
#define BIO_POOL_OFFSET (BITS_PER_LONG - BIO_POOL_BITS)
#define BIO_POOL_MASK (1UL << BIO_POOL_OFFSET)
#define BIO_POOL_IDX(bio) ((bio)->bi_flags >> BIO_POOL_OFFSET)
@@ -504,6 +505,115 @@ static inline int bio_has_data(struct bio *bio)
return bio && bio->bi_io_vec != NULL;
}
+/*
+ * BIO list management for use by remapping drivers (e.g. DM or MD) and loop.
+ *
+ * A bio_list anchors a singly-linked list of bios chained through the bi_next
+ * member of the bio. The bio_list also caches the last list member to allow
+ * fast access to the tail.
+ */
+struct bio_list {
+ struct bio *head;
+ struct bio *tail;
+};
+
+static inline int bio_list_empty(const struct bio_list *bl)
+{
+ return bl->head == NULL;
+}
+
+static inline void bio_list_init(struct bio_list *bl)
+{
+ bl->head = bl->tail = NULL;
+}
+
+#define bio_list_for_each(bio, bl) \
+ for (bio = (bl)->head; bio; bio = bio->bi_next)
+
+static inline unsigned bio_list_size(const struct bio_list *bl)
+{
+ unsigned sz = 0;
+ struct bio *bio;
+
+ bio_list_for_each(bio, bl)
+ sz++;
+
+ return sz;
+}
+
+static inline void bio_list_add(struct bio_list *bl, struct bio *bio)
+{
+ bio->bi_next = NULL;
+
+ if (bl->tail)
+ bl->tail->bi_next = bio;
+ else
+ bl->head = bio;
+
+ bl->tail = bio;
+}
+
+static inline void bio_list_add_head(struct bio_list *bl, struct bio *bio)
+{
+ bio->bi_next = bl->head;
+
+ bl->head = bio;
+
+ if (!bl->tail)
+ bl->tail = bio;
+}
+
+static inline void bio_list_merge(struct bio_list *bl, struct bio_list *bl2)
+{
+ if (!bl2->head)
+ return;
+
+ if (bl->tail)
+ bl->tail->bi_next = bl2->head;
+ else
+ bl->head = bl2->head;
+
+ bl->tail = bl2->tail;
+}
+
+static inline void bio_list_merge_head(struct bio_list *bl,
+ struct bio_list *bl2)
+{
+ if (!bl2->head)
+ return;
+
+ if (bl->head)
+ bl2->tail->bi_next = bl->head;
+ else
+ bl->tail = bl2->tail;
+
+ bl->head = bl2->head;
+}
+
+static inline struct bio *bio_list_pop(struct bio_list *bl)
+{
+ struct bio *bio = bl->head;
+
+ if (bio) {
+ bl->head = bl->head->bi_next;
+ if (!bl->head)
+ bl->tail = NULL;
+
+ bio->bi_next = NULL;
+ }
+
+ return bio;
+}
+
+static inline struct bio *bio_list_get(struct bio_list *bl)
+{
+ struct bio *bio = bl->head;
+
+ bl->head = bl->tail = NULL;
+
+ return bio;
+}
+
#if defined(CONFIG_BLK_DEV_INTEGRITY)
#define bip_vec_idx(bip, idx) (&(bip->bip_vec[(idx)]))
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 61829139795a..c05a29cb9bb2 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -112,6 +112,25 @@ static inline unsigned fls_long(unsigned long l)
return fls64(l);
}
+/**
+ * __ffs64 - find first set bit in a 64 bit word
+ * @word: The 64 bit word
+ *
+ * On 64 bit arches this is a synomyn for __ffs
+ * The result is not defined if no bits are set, so check that @word
+ * is non-zero before calling this.
+ */
+static inline unsigned long __ffs64(u64 word)
+{
+#if BITS_PER_LONG == 32
+ if (((u32)word) == 0UL)
+ return __ffs((u32)(word >> 32)) + 32;
+#elif BITS_PER_LONG != 64
+#error BITS_PER_LONG not 32 or 64
+#endif
+ return __ffs((unsigned long)word);
+}
+
#ifdef __KERNEL__
#ifdef CONFIG_GENERIC_FIND_FIRST_BIT
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index ba54c834a590..e3726d6fe1f7 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -118,6 +118,7 @@ enum rq_flag_bits {
__REQ_COPY_USER, /* contains copies of user pages */
__REQ_INTEGRITY, /* integrity metadata has been remapped */
__REQ_NOIDLE, /* Don't anticipate more IO after this one */
+ __REQ_IO_STAT, /* account I/O stat */
__REQ_NR_BITS, /* stops here */
};
@@ -145,6 +146,7 @@ enum rq_flag_bits {
#define REQ_COPY_USER (1 << __REQ_COPY_USER)
#define REQ_INTEGRITY (1 << __REQ_INTEGRITY)
#define REQ_NOIDLE (1 << __REQ_NOIDLE)
+#define REQ_IO_STAT (1 << __REQ_IO_STAT)
#define BLK_MAX_CDB 16
@@ -209,8 +211,8 @@ struct request {
unsigned short ioprio;
- void *special;
- char *buffer;
+ void *special; /* opaque pointer available for LLD use */
+ char *buffer; /* kaddr of the current segment if available */
int tag;
int errors;
@@ -227,7 +229,6 @@ struct request {
unsigned int data_len;
unsigned int extra_len; /* length of alignment and padding */
unsigned int sense_len;
- void *data;
void *sense;
unsigned long deadline;
@@ -598,6 +599,8 @@ enum {
blk_failfast_transport(rq) || \
blk_failfast_driver(rq))
#define blk_rq_started(rq) ((rq)->cmd_flags & REQ_STARTED)
+#define blk_rq_io_stat(rq) ((rq)->cmd_flags & REQ_IO_STAT)
+#define blk_rq_quiet(rq) ((rq)->cmd_flags & REQ_QUIET)
#define blk_account_rq(rq) (blk_rq_started(rq) && (blk_fs_request(rq) || blk_discard_rq(rq)))
@@ -794,7 +797,6 @@ extern void blk_sync_queue(struct request_queue *q);
extern void __blk_stop_queue(struct request_queue *q);
extern void __blk_run_queue(struct request_queue *);
extern void blk_run_queue(struct request_queue *);
-extern void blk_start_queueing(struct request_queue *);
extern int blk_rq_map_user(struct request_queue *, struct request *,
struct rq_map_data *, void __user *, unsigned long,
gfp_t);
@@ -830,38 +832,145 @@ static inline void blk_run_address_space(struct address_space *mapping)
extern void blkdev_dequeue_request(struct request *req);
/*
- * blk_end_request() and friends.
- * __blk_end_request() and end_request() must be called with
- * the request queue spinlock acquired.
+ * blk_end_request() takes bytes instead of sectors as a complete size.
+ * blk_rq_bytes() returns bytes left to complete in the entire request.
+ * blk_rq_cur_bytes() returns bytes left to complete in the current segment.
+ */
+extern unsigned int blk_rq_bytes(struct request *rq);
+extern unsigned int blk_rq_cur_bytes(struct request *rq);
+
+/*
+ * Request completion related functions.
+ *
+ * blk_update_request() completes given number of bytes and updates
+ * the request without completing it.
+ *
+ * blk_end_request() and friends. __blk_end_request() must be called
+ * with the request queue spinlock acquired.
*
* Several drivers define their own end_request and call
* blk_end_request() for parts of the original function.
* This prevents code duplication in drivers.
*/
-extern int blk_end_request(struct request *rq, int error,
- unsigned int nr_bytes);
-extern int __blk_end_request(struct request *rq, int error,
- unsigned int nr_bytes);
-extern int blk_end_bidi_request(struct request *rq, int error,
- unsigned int nr_bytes, unsigned int bidi_bytes);
-extern void end_request(struct request *, int);
-extern int blk_end_request_callback(struct request *rq, int error,
- unsigned int nr_bytes,
- int (drv_callback)(struct request *));
+extern bool blk_update_request(struct request *rq, int error,
+ unsigned int nr_bytes);
+extern bool blk_end_bidi_request(struct request *rq, int error,
+ unsigned int nr_bytes,
+ unsigned int bidi_bytes);
+extern bool __blk_end_bidi_request(struct request *rq, int error,
+ unsigned int nr_bytes,
+ unsigned int bidi_bytes);
+
+/**
+ * blk_end_request - Helper function for drivers to complete the request.
+ * @rq: the request being processed
+ * @error: %0 for success, < %0 for error
+ * @nr_bytes: number of bytes to complete
+ *
+ * Description:
+ * Ends I/O on a number of bytes attached to @rq.
+ * If @rq has leftover, sets it up for the next range of segments.
+ *
+ * Return:
+ * %false - we are done with this request
+ * %true - still buffers pending for this request
+ **/
+static inline bool blk_end_request(struct request *rq, int error,
+ unsigned int nr_bytes)
+{
+ return blk_end_bidi_request(rq, error, nr_bytes, 0);
+}
+
+/**
+ * blk_end_request_all - Helper function for drives to finish the request.
+ * @rq: the request to finish
+ * @err: %0 for success, < %0 for error
+ *
+ * Description:
+ * Completely finish @rq.
+ */
+static inline void blk_end_request_all(struct request *rq, int error)
+{
+ bool pending;
+
+ pending = blk_end_request(rq, error, blk_rq_bytes(rq));
+ BUG_ON(pending);
+}
+
+/**
+ * blk_end_request_cur - Helper function to finish the current request chunk.
+ * @rq: the request to finish the current chunk for
+ * @err: %0 for success, < %0 for error
+ *
+ * Description:
+ * Complete the current consecutively mapped chunk from @rq.
+ *
+ * Return:
+ * %false - we are done with this request
+ * %true - still buffers pending for this request
+ */
+static inline bool blk_end_request_cur(struct request *rq, int error)
+{
+ return blk_end_request(rq, error, rq->hard_cur_sectors << 9);
+}
+
+/**
+ * __blk_end_request - Helper function for drivers to complete the request.
+ * @rq: the request being processed
+ * @error: %0 for success, < %0 for error
+ * @nr_bytes: number of bytes to complete
+ *
+ * Description:
+ * Must be called with queue lock held unlike blk_end_request().
+ *
+ * Return:
+ * %false - we are done with this request
+ * %true - still buffers pending for this request
+ **/
+static inline bool __blk_end_request(struct request *rq, int error,
+ unsigned int nr_bytes)
+{
+ return __blk_end_bidi_request(rq, error, nr_bytes, 0);
+}
+
+/**
+ * __blk_end_request_all - Helper function for drives to finish the request.
+ * @rq: the request to finish
+ * @err: %0 for success, < %0 for error
+ *
+ * Description:
+ * Completely finish @rq. Must be called with queue lock held.
+ */
+static inline void __blk_end_request_all(struct request *rq, int error)
+{
+ bool pending;
+
+ pending = __blk_end_request(rq, error, blk_rq_bytes(rq));
+ BUG_ON(pending);
+}
+
+/**
+ * __blk_end_request_cur - Helper function to finish the current request chunk.
+ * @rq: the request to finish the current chunk for
+ * @err: %0 for success, < %0 for error
+ *
+ * Description:
+ * Complete the current consecutively mapped chunk from @rq. Must
+ * be called with queue lock held.
+ *
+ * Return:
+ * %false - we are done with this request
+ * %true - still buffers pending for this request
+ */
+static inline bool __blk_end_request_cur(struct request *rq, int error)
+{
+ return __blk_end_request(rq, error, rq->hard_cur_sectors << 9);
+}
+
extern void blk_complete_request(struct request *);
extern void __blk_complete_request(struct request *);
extern void blk_abort_request(struct request *);
extern void blk_abort_queue(struct request_queue *);
-extern void blk_update_request(struct request *rq, int error,
- unsigned int nr_bytes);
-
-/*
- * blk_end_request() takes bytes instead of sectors as a complete size.
- * blk_rq_bytes() returns bytes left to complete in the entire request.
- * blk_rq_cur_bytes() returns bytes left to complete in the current segment.
- */
-extern unsigned int blk_rq_bytes(struct request *rq);
-extern unsigned int blk_rq_cur_bytes(struct request *rq);
/*
* Access functions for manipulating queue properties
diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h
index d960889e92ef..82b4636030e9 100644
--- a/include/linux/blktrace_api.h
+++ b/include/linux/blktrace_api.h
@@ -116,9 +116,9 @@ struct blk_io_trace {
* The remap event
*/
struct blk_io_trace_remap {
- __be32 device;
__be32 device_from;
- __be64 sector;
+ __be32 device_to;
+ __be64 sector_from;
};
enum {
@@ -165,8 +165,9 @@ struct blk_trace {
extern int blk_trace_ioctl(struct block_device *, unsigned, char __user *);
extern void blk_trace_shutdown(struct request_queue *);
-extern int do_blk_trace_setup(struct request_queue *q,
- char *name, dev_t dev, struct blk_user_trace_setup *buts);
+extern int do_blk_trace_setup(struct request_queue *q, char *name,
+ dev_t dev, struct block_device *bdev,
+ struct blk_user_trace_setup *buts);
extern void __trace_note_message(struct blk_trace *, const char *fmt, ...);
/**
@@ -193,22 +194,29 @@ extern void __trace_note_message(struct blk_trace *, const char *fmt, ...);
extern void blk_add_driver_data(struct request_queue *q, struct request *rq,
void *data, size_t len);
extern int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
+ struct block_device *bdev,
char __user *arg);
extern int blk_trace_startstop(struct request_queue *q, int start);
extern int blk_trace_remove(struct request_queue *q);
+extern int blk_trace_init_sysfs(struct device *dev);
extern struct attribute_group blk_trace_attr_group;
#else /* !CONFIG_BLK_DEV_IO_TRACE */
-#define blk_trace_ioctl(bdev, cmd, arg) (-ENOTTY)
-#define blk_trace_shutdown(q) do { } while (0)
-#define do_blk_trace_setup(q, name, dev, buts) (-ENOTTY)
-#define blk_add_driver_data(q, rq, data, len) do {} while (0)
-#define blk_trace_setup(q, name, dev, arg) (-ENOTTY)
-#define blk_trace_startstop(q, start) (-ENOTTY)
-#define blk_trace_remove(q) (-ENOTTY)
-#define blk_add_trace_msg(q, fmt, ...) do { } while (0)
+# define blk_trace_ioctl(bdev, cmd, arg) (-ENOTTY)
+# define blk_trace_shutdown(q) do { } while (0)
+# define do_blk_trace_setup(q, name, dev, bdev, buts) (-ENOTTY)
+# define blk_add_driver_data(q, rq, data, len) do {} while (0)
+# define blk_trace_setup(q, name, dev, bdev, arg) (-ENOTTY)
+# define blk_trace_startstop(q, start) (-ENOTTY)
+# define blk_trace_remove(q) (-ENOTTY)
+# define blk_add_trace_msg(q, fmt, ...) do { } while (0)
+static inline int blk_trace_init_sysfs(struct device *dev)
+{
+ return 0;
+}
#endif /* CONFIG_BLK_DEV_IO_TRACE */
+
#endif /* __KERNEL__ */
#endif
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 7b73bb8f1970..16ed0284d780 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -155,6 +155,7 @@ void create_empty_buffers(struct page *, unsigned long,
unsigned long b_state);
void end_buffer_read_sync(struct buffer_head *bh, int uptodate);
void end_buffer_write_sync(struct buffer_head *bh, int uptodate);
+void end_buffer_async_write(struct buffer_head *bh, int uptodate);
/* Things to do with buffers at mapping->private_list */
void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode);
@@ -197,6 +198,8 @@ extern int buffer_heads_over_limit;
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_write_full_page_endio(struct page *page, get_block_t *get_block,
+ struct writeback_control *wbc, bh_end_io_t *handler);
int block_read_full_page(struct page*, get_block_t*);
int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc,
unsigned long from);
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 573819ef4cc0..c56457c8334e 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -143,7 +143,9 @@ extern u64 timecounter_cyc2time(struct timecounter *tc,
* 400-499: Perfect
* The ideal clocksource. A must-use where
* available.
- * @read: returns a cycle value
+ * @read: returns a cycle value, passes clocksource as argument
+ * @enable: optional function to enable the clocksource
+ * @disable: optional function to disable the clocksource
* @mask: bitmask for two's complement
* subtraction of non 64 bit counters
* @mult: cycle to nanosecond multiplier (adjusted by NTP)
@@ -162,7 +164,9 @@ struct clocksource {
char *name;
struct list_head list;
int rating;
- cycle_t (*read)(void);
+ cycle_t (*read)(struct clocksource *cs);
+ int (*enable)(struct clocksource *cs);
+ void (*disable)(struct clocksource *cs);
cycle_t mask;
u32 mult;
u32 mult_orig;
@@ -271,7 +275,42 @@ static inline u32 clocksource_hz2mult(u32 hz, u32 shift_constant)
*/
static inline cycle_t clocksource_read(struct clocksource *cs)
{
- return cs->read();
+ return cs->read(cs);
+}
+
+/**
+ * clocksource_enable: - enable clocksource
+ * @cs: pointer to clocksource
+ *
+ * Enables the specified clocksource. The clocksource callback
+ * function should start up the hardware and setup mult and field
+ * members of struct clocksource to reflect hardware capabilities.
+ */
+static inline int clocksource_enable(struct clocksource *cs)
+{
+ int ret = 0;
+
+ if (cs->enable)
+ ret = cs->enable(cs);
+
+ /* save mult_orig on enable */
+ cs->mult_orig = cs->mult;
+
+ return ret;
+}
+
+/**
+ * clocksource_disable: - disable clocksource
+ * @cs: pointer to clocksource
+ *
+ * Disables the specified clocksource. The clocksource callback
+ * function should power down the now unused hardware block to
+ * save power.
+ */
+static inline void clocksource_disable(struct clocksource *cs)
+{
+ if (cs->disable)
+ cs->disable(cs);
}
/**
diff --git a/include/linux/compat.h b/include/linux/compat.h
index f2ded21f9a3c..af931ee43dd8 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -222,6 +222,8 @@ int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from);
int copy_siginfo_to_user32(struct compat_siginfo __user *to, siginfo_t *from);
int get_compat_sigevent(struct sigevent *event,
const struct compat_sigevent __user *u_event);
+long compat_sys_rt_tgsigqueueinfo(compat_pid_t tgid, compat_pid_t pid, int sig,
+ struct compat_siginfo __user *uinfo);
static inline int compat_timeval_compare(struct compat_timeval *lhs,
struct compat_timeval *rhs)
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 37bcb50a4d7c..04fb5135b4e1 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -261,6 +261,11 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
# define __section(S) __attribute__ ((__section__(#S)))
#endif
+/* Are two types/vars the same type (ignoring qualifiers)? */
+#ifndef __same_type
+# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
+#endif
+
/*
* Prevent the compiler from merging or refetching accesses. The compiler
* is also forbidden from reordering successive instances of ACCESS_ONCE(),
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 2643d848df90..4d668e05d458 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -69,7 +69,6 @@ static inline void unregister_cpu_notifier(struct notifier_block *nb)
int cpu_up(unsigned int cpu);
void notify_cpu_starting(unsigned int cpu);
-extern void cpu_hotplug_init(void);
extern void cpu_maps_update_begin(void);
extern void cpu_maps_update_done(void);
@@ -84,10 +83,6 @@ static inline void unregister_cpu_notifier(struct notifier_block *nb)
{
}
-static inline void cpu_hotplug_init(void)
-{
-}
-
static inline void cpu_maps_update_begin(void)
{
}
diff --git a/include/linux/cyclades.h b/include/linux/cyclades.h
index 788850ba4e75..1fbdea4f08eb 100644
--- a/include/linux/cyclades.h
+++ b/include/linux/cyclades.h
@@ -142,19 +142,6 @@ struct CYZ_BOOT_CTRL {
#ifndef DP_WINDOW_SIZE
-/* #include "cyclomz.h" */
-/****************** ****************** *******************/
-/*
- * The data types defined below are used in all ZFIRM interface
- * data structures. They accomodate differences between HW
- * architectures and compilers.
- */
-
-typedef __u64 ucdouble; /* 64 bits, unsigned */
-typedef __u32 uclong; /* 32 bits, unsigned */
-typedef __u16 ucshort; /* 16 bits, unsigned */
-typedef __u8 ucchar; /* 8 bits, unsigned */
-
/*
* Memory Window Sizes
*/
@@ -507,16 +494,20 @@ struct ZFW_CTRL {
/* Per card data structure */
struct cyclades_card {
- void __iomem *base_addr;
- void __iomem *ctl_addr;
- int irq;
- 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;
+ void __iomem *base_addr;
+ union {
+ void __iomem *p9050;
+ struct RUNTIME_9060 __iomem *p9060;
+ } ctl_addr;
+ int irq;
+ 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 */
+ u32 hw_ver;
+ spinlock_t card_lock;
+ struct cyclades_port *ports;
};
/***************************************
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 15156364d196..da8066cf357f 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -351,6 +351,11 @@ static inline int d_unhashed(struct dentry *dentry)
return (dentry->d_flags & DCACHE_UNHASHED);
}
+static inline int d_unlinked(struct dentry *dentry)
+{
+ return d_unhashed(dentry) && !IS_ROOT(dentry);
+}
+
static inline struct dentry *dget_parent(struct dentry *dentry)
{
struct dentry *ret;
@@ -368,7 +373,7 @@ static inline int d_mountpoint(struct dentry *dentry)
return dentry->d_mounted;
}
-extern struct vfsmount *lookup_mnt(struct vfsmount *, struct dentry *);
+extern struct vfsmount *lookup_mnt(struct path *);
extern struct dentry *lookup_create(struct nameidata *nd, int is_dir);
extern int sysctl_vfs_cache_pressure;
diff --git a/include/linux/debug_locks.h b/include/linux/debug_locks.h
index 493dedb7a67b..29b3ce3f2a1d 100644
--- a/include/linux/debug_locks.h
+++ b/include/linux/debug_locks.h
@@ -3,6 +3,7 @@
#include <linux/kernel.h>
#include <asm/atomic.h>
+#include <asm/system.h>
struct task_struct;
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index ded2d7c42668..8e70c704a497 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -21,6 +21,7 @@ typedef enum { STATUSTYPE_INFO, STATUSTYPE_TABLE } status_type_t;
union map_info {
void *ptr;
unsigned long long ll;
+ unsigned flush_request;
};
/*
@@ -168,6 +169,16 @@ struct dm_target {
sector_t split_io;
/*
+ * A number of zero-length barrier requests that will be submitted
+ * to the target for the purpose of flushing cache.
+ *
+ * The request number will be placed in union map_info->flush_request.
+ * It is a responsibility of the target driver to remap these requests
+ * to the real underlying devices.
+ */
+ unsigned num_flush_requests;
+
+ /*
* These are automatically filled in by
* dm_table_get_device.
*/
diff --git a/include/linux/device.h b/include/linux/device.h
index 2918c0e8fdfd..5d5c197bad45 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -384,13 +384,8 @@ struct device {
struct device_driver *driver; /* which driver has allocated this
device */
void *driver_data; /* data private to the driver */
-
- void *platform_data; /* We will remove platform_data
- field if all platform devices
- pass its platform specific data
- from platform_device->platform_data,
- other kind of devices should not
- use platform_data. */
+ void *platform_data; /* Platform specific data, device
+ core doesn't touch it */
struct dev_pm_info power;
#ifdef CONFIG_NUMA
@@ -551,6 +546,7 @@ extern int (*platform_notify_remove)(struct device *dev);
extern struct device *get_device(struct device *dev);
extern void put_device(struct device *dev);
+extern void wait_for_device_probe(void);
/* drivers/base/power/shutdown.c */
extern void device_shutdown(void);
diff --git a/include/linux/dlm.h b/include/linux/dlm.h
index b9cd38603fd8..0b3518c42356 100644
--- a/include/linux/dlm.h
+++ b/include/linux/dlm.h
@@ -81,8 +81,8 @@ struct dlm_lksb {
* the cluster, the calling node joins it.
*/
-int dlm_new_lockspace(char *name, int namelen, dlm_lockspace_t **lockspace,
- uint32_t flags, int lvblen);
+int dlm_new_lockspace(const char *name, int namelen,
+ dlm_lockspace_t **lockspace, uint32_t flags, int lvblen);
/*
* dlm_release_lockspace
diff --git a/include/linux/dma-debug.h b/include/linux/dma-debug.h
index 28d53cb7b5a2..171ad8aedc83 100644
--- a/include/linux/dma-debug.h
+++ b/include/linux/dma-debug.h
@@ -32,6 +32,8 @@ extern void dma_debug_add_bus(struct bus_type *bus);
extern void dma_debug_init(u32 num_entries);
+extern int dma_debug_resize_entries(u32 num_entries);
+
extern void debug_dma_map_page(struct device *dev, struct page *page,
size_t offset, size_t size,
int direction, dma_addr_t dma_addr,
@@ -91,6 +93,11 @@ static inline void dma_debug_init(u32 num_entries)
{
}
+static inline int dma_debug_resize_entries(u32 num_entries)
+{
+ return 0;
+}
+
static inline void debug_dma_map_page(struct device *dev, struct page *page,
size_t offset, size_t size,
int direction, dma_addr_t dma_addr,
diff --git a/include/linux/dma_remapping.h b/include/linux/dma_remapping.h
index 1a455f1f86d7..e0a03aff63d9 100644
--- a/include/linux/dma_remapping.h
+++ b/include/linux/dma_remapping.h
@@ -13,6 +13,9 @@
#define DMA_PTE_WRITE (2)
#define DMA_PTE_SNP (1 << 11)
+#define CONTEXT_TT_MULTI_LEVEL 0
+#define CONTEXT_TT_PASS_THROUGH 2
+
struct intel_iommu;
struct dmar_domain;
struct root_entry;
@@ -21,11 +24,16 @@ extern void free_dmar_iommu(struct intel_iommu *iommu);
#ifdef CONFIG_DMAR
extern int iommu_calculate_agaw(struct intel_iommu *iommu);
+extern int iommu_calculate_max_sagaw(struct intel_iommu *iommu);
#else
static inline int iommu_calculate_agaw(struct intel_iommu *iommu)
{
return 0;
}
+static inline int iommu_calculate_max_sagaw(struct intel_iommu *iommu)
+{
+ return 0;
+}
#endif
extern int dmar_disabled;
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 2e2aa3df170c..ffefba81c818 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -78,12 +78,18 @@ enum dma_transaction_type {
* dependency chains
* @DMA_COMPL_SKIP_SRC_UNMAP - set to disable dma-unmapping the source buffer(s)
* @DMA_COMPL_SKIP_DEST_UNMAP - set to disable dma-unmapping the destination(s)
+ * @DMA_COMPL_SRC_UNMAP_SINGLE - set to do the source dma-unmapping as single
+ * (if not set, do the source dma-unmapping as page)
+ * @DMA_COMPL_DEST_UNMAP_SINGLE - set to do the destination dma-unmapping as single
+ * (if not set, do the destination dma-unmapping as page)
*/
enum dma_ctrl_flags {
DMA_PREP_INTERRUPT = (1 << 0),
DMA_CTRL_ACK = (1 << 1),
DMA_COMPL_SKIP_SRC_UNMAP = (1 << 2),
DMA_COMPL_SKIP_DEST_UNMAP = (1 << 3),
+ DMA_COMPL_SRC_UNMAP_SINGLE = (1 << 4),
+ DMA_COMPL_DEST_UNMAP_SINGLE = (1 << 5),
};
/**
diff --git a/include/linux/dmar.h b/include/linux/dmar.h
index e397dc342cda..10ff5c498824 100644
--- a/include/linux/dmar.h
+++ b/include/linux/dmar.h
@@ -108,6 +108,7 @@ struct irte {
};
#ifdef CONFIG_INTR_REMAP
extern int intr_remapping_enabled;
+extern int intr_remapping_supported(void);
extern int enable_intr_remapping(int);
extern void disable_intr_remapping(void);
extern int reenable_intr_remapping(int);
@@ -157,6 +158,8 @@ static inline struct intel_iommu *map_ioapic_to_ir(int apic)
}
#define irq_remapped(irq) (0)
#define enable_intr_remapping(mode) (-1)
+#define disable_intr_remapping() (0)
+#define reenable_intr_remapping(mode) (0)
#define intr_remapping_enabled (0)
#endif
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index baabf33be244..a0d9422a1569 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -70,7 +70,7 @@ extern int ddebug_remove_module(char *mod_name);
DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT }; \
if (__dynamic_dbg_enabled(descriptor)) \
dev_printk(KERN_DEBUG, dev, \
- KBUILD_MODNAME ": " pr_fmt(fmt),\
+ KBUILD_MODNAME ": " fmt, \
##__VA_ARGS__); \
} while (0)
diff --git a/include/linux/fb.h b/include/linux/fb.h
index f563c5013932..330c4b1bfcaa 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -173,8 +173,12 @@ struct fb_fix_screeninfo {
/* Interpretation of offset for color fields: All offsets are from the right,
* inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you
* can use the offset as right argument to <<). A pixel afterwards is a bit
- * stream and is written to video memory as that unmodified. This implies
- * big-endian byte order if bits_per_pixel is greater than 8.
+ * stream and is written to video memory as that unmodified.
+ *
+ * For pseudocolor: offset and length should be the same for all color
+ * components. Offset specifies the position of the least significant bit
+ * of the pallette index in a pixel value. Length indicates the number
+ * of available palette entries (i.e. # of entries = 1 << length).
*/
struct fb_bitfield {
__u32 offset; /* beginning of bitfield */
diff --git a/include/linux/fiemap.h b/include/linux/fiemap.h
index 671decbd2aeb..934e22d65801 100644
--- a/include/linux/fiemap.h
+++ b/include/linux/fiemap.h
@@ -11,6 +11,8 @@
#ifndef _LINUX_FIEMAP_H
#define _LINUX_FIEMAP_H
+#include <linux/types.h>
+
struct fiemap_extent {
__u64 fe_logical; /* logical offset in bytes for the start of
* the extent from the beginning of the file */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 562d2855cf30..50f319ac59af 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -87,6 +87,60 @@ struct inodes_stat_t {
*/
#define FMODE_NOCMTIME ((__force fmode_t)2048)
+/*
+ * The below are the various read and write types that we support. Some of
+ * them include behavioral modifiers that send information down to the
+ * block layer and IO scheduler. Terminology:
+ *
+ * The block layer uses device plugging to defer IO a little bit, in
+ * the hope that we will see more IO very shortly. This increases
+ * coalescing of adjacent IO and thus reduces the number of IOs we
+ * have to send to the device. It also allows for better queuing,
+ * if the IO isn't mergeable. If the caller is going to be waiting
+ * for the IO, then he must ensure that the device is unplugged so
+ * that the IO is dispatched to the driver.
+ *
+ * All IO is handled async in Linux. This is fine for background
+ * writes, but for reads or writes that someone waits for completion
+ * on, we want to notify the block layer and IO scheduler so that they
+ * know about it. That allows them to make better scheduling
+ * decisions. So when the below references 'sync' and 'async', it
+ * is referencing this priority hint.
+ *
+ * With that in mind, the available types are:
+ *
+ * READ A normal read operation. Device will be plugged.
+ * READ_SYNC A synchronous read. Device is not plugged, caller can
+ * immediately wait on this read without caring about
+ * unplugging.
+ * READA Used for read-ahead operations. Lower priority, and the
+ * block layer could (in theory) choose to ignore this
+ * request if it runs into resource problems.
+ * WRITE A normal async write. Device will be plugged.
+ * SWRITE Like WRITE, but a special case for ll_rw_block() that
+ * tells it to lock the buffer first. Normally a buffer
+ * must be locked before doing IO.
+ * WRITE_SYNC_PLUG Synchronous write. Identical to WRITE, but passes down
+ * the hint that someone will be waiting on this IO
+ * shortly. The device must still be unplugged explicitly,
+ * WRITE_SYNC_PLUG does not do this as we could be
+ * submitting more writes before we actually wait on any
+ * of them.
+ * WRITE_SYNC Like WRITE_SYNC_PLUG, but also unplugs the device
+ * immediately after submission. The write equivalent
+ * of READ_SYNC.
+ * WRITE_ODIRECT Special case write for O_DIRECT only.
+ * SWRITE_SYNC
+ * SWRITE_SYNC_PLUG Like WRITE_SYNC/WRITE_SYNC_PLUG, but locks the buffer.
+ * See SWRITE.
+ * WRITE_BARRIER Like WRITE, but tells the block layer that all
+ * previously submitted writes must be safely on storage
+ * before this one is started. Also guarantees that when
+ * this write is complete, it itself is also safely on
+ * storage. Prevents reordering of writes on both sides
+ * of this IO.
+ *
+ */
#define RW_MASK 1
#define RWA_MASK 2
#define READ 0
@@ -102,6 +156,11 @@ struct inodes_stat_t {
(SWRITE | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_NOIDLE))
#define SWRITE_SYNC (SWRITE_SYNC_PLUG | (1 << BIO_RW_UNPLUG))
#define WRITE_BARRIER (WRITE | (1 << BIO_RW_BARRIER))
+
+/*
+ * These aren't really reads or writes, they pass down information about
+ * parts of device that are now unused by the file system.
+ */
#define DISCARD_NOBARRIER (1 << BIO_RW_DISCARD)
#define DISCARD_BARRIER ((1 << BIO_RW_DISCARD) | (1 << BIO_RW_BARRIER))
@@ -738,9 +797,6 @@ enum inode_i_mutex_lock_class
I_MUTEX_QUOTA
};
-extern void inode_double_lock(struct inode *inode1, struct inode *inode2);
-extern void inode_double_unlock(struct inode *inode1, struct inode *inode2);
-
/*
* NOTE: in a 32bit arch with a preemptable kernel and
* an UP compile the i_size_read/write must be atomic
@@ -1052,6 +1108,7 @@ extern void locks_copy_lock(struct file_lock *, struct file_lock *);
extern void __locks_copy_lock(struct file_lock *, const struct file_lock *);
extern void locks_remove_posix(struct file *, fl_owner_t);
extern void locks_remove_flock(struct file *);
+extern void locks_release_private(struct file_lock *);
extern void posix_test_lock(struct file *, struct file_lock *);
extern int posix_lock_file(struct file *, struct file_lock *, struct file_lock *);
extern int posix_lock_file_wait(struct file *, struct file_lock *);
@@ -1265,7 +1322,7 @@ struct super_block {
struct rw_semaphore s_umount;
struct mutex s_lock;
int s_count;
- int s_need_sync_fs;
+ int s_need_sync;
atomic_t s_active;
#ifdef CONFIG_SECURITY
void *s_security;
@@ -1316,11 +1373,6 @@ struct super_block {
* generic_show_options()
*/
char *s_options;
-
- /*
- * storage for asynchronous operations
- */
- struct list_head s_async_list;
};
extern struct timespec current_fs_time(struct super_block *sb);
@@ -1719,6 +1771,7 @@ void kill_block_super(struct super_block *sb);
void kill_anon_super(struct super_block *sb);
void kill_litter_super(struct super_block *sb);
void deactivate_super(struct super_block *sb);
+void deactivate_locked_super(struct super_block *sb);
int set_anon_super(struct super_block *s, void *data);
struct super_block *sget(struct file_system_type *type,
int (*test)(struct super_block *,void *),
@@ -1743,7 +1796,7 @@ extern struct vfsmount *kern_mount_data(struct file_system_type *, void *data);
extern int may_umount_tree(struct vfsmount *);
extern int may_umount(struct vfsmount *);
extern long do_mount(char *, char *, char *, unsigned long, void *);
-extern struct vfsmount *collect_mounts(struct vfsmount *, struct dentry *);
+extern struct vfsmount *collect_mounts(struct path *);
extern void drop_collected_mounts(struct vfsmount *);
extern int vfs_statfs(struct dentry *, struct kstatfs *);
@@ -1890,8 +1943,6 @@ extern struct super_block *freeze_bdev(struct block_device *);
extern void emergency_thaw_all(void);
extern int thaw_bdev(struct block_device *bdev, struct super_block *sb);
extern int fsync_bdev(struct block_device *);
-extern int fsync_super(struct super_block *);
-extern int fsync_no_super(struct block_device *);
#else
static inline void bd_forget(struct inode *inode) {}
static inline int sync_blockdev(struct block_device *bdev) { return 0; }
@@ -1907,6 +1958,7 @@ static inline int thaw_bdev(struct block_device *bdev, struct super_block *sb)
return 0;
}
#endif
+extern int sync_filesystem(struct super_block *);
extern const struct file_operations def_blk_fops;
extern const struct file_operations def_chr_fops;
extern const struct file_operations bad_sock_fops;
@@ -2025,12 +2077,8 @@ extern int filemap_fdatawrite_range(struct address_space *mapping,
extern int vfs_fsync(struct file *file, struct dentry *dentry, int datasync);
extern void sync_supers(void);
-extern void sync_filesystems(int wait);
-extern void __fsync_super(struct super_block *sb);
extern void emergency_sync(void);
extern void emergency_remount(void);
-extern int do_remount_sb(struct super_block *sb, int flags,
- void *data, int force);
#ifdef CONFIG_BLOCK
extern sector_t bmap(struct inode *, sector_t);
#endif
@@ -2061,7 +2109,7 @@ extern struct file *create_write_pipe(int flags);
extern void free_write_pipe(struct file *);
extern struct file *do_filp_open(int dfd, const char *pathname,
- int open_flag, int mode);
+ int open_flag, int mode, int acc_mode);
extern int may_open(struct path *, int, int);
extern int kernel_read(struct file *, unsigned long, char *, unsigned long);
@@ -2150,8 +2198,6 @@ extern ssize_t generic_file_splice_read(struct file *, loff_t *,
struct pipe_inode_info *, size_t, unsigned int);
extern ssize_t generic_file_splice_write(struct pipe_inode_info *,
struct file *, loff_t *, size_t, unsigned int);
-extern ssize_t generic_file_splice_write_nolock(struct pipe_inode_info *,
- struct file *, loff_t *, size_t, unsigned int);
extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe,
struct file *out, loff_t *, size_t len, unsigned int flags);
extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
@@ -2245,9 +2291,8 @@ extern int vfs_readdir(struct file *, filldir_t, void *);
extern int vfs_stat(char __user *, struct kstat *);
extern int vfs_lstat(char __user *, struct kstat *);
-extern int vfs_stat_fd(int dfd, char __user *, struct kstat *);
-extern int vfs_lstat_fd(int dfd, char __user *, struct kstat *);
extern int vfs_fstat(unsigned int, struct kstat *);
+extern int vfs_fstatat(int , char __user *, struct kstat *, int);
extern int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
unsigned long arg);
@@ -2314,6 +2359,7 @@ extern void file_update_time(struct file *file);
extern int generic_show_options(struct seq_file *m, struct vfsmount *mnt);
extern void save_mount_options(struct super_block *sb, char *options);
+extern void replace_mount_options(struct super_block *sb, char *options);
static inline ino_t parent_ino(struct dentry *dentry)
{
@@ -2395,7 +2441,7 @@ 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);
-int get_filesystem_list(char * buf);
+int __init get_filesystem_list(char *buf);
#endif /* __KERNEL__ */
#endif /* _LINUX_FS_H */
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index f2a78b5e8b55..244677cc082b 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -43,10 +43,6 @@
*
*/
-/* Flags related to I2C device features */
-#define FSL_I2C_DEV_SEPARATE_DFSRR 0x00000001
-#define FSL_I2C_DEV_CLOCK_5200 0x00000002
-
enum fsl_usb2_operating_modes {
FSL_USB2_MPH_HOST,
FSL_USB2_DR_HOST,
@@ -83,6 +79,10 @@ struct fsl_spi_platform_data {
u16 max_chipselect;
void (*cs_control)(struct spi_device *spi, bool on);
u32 sysclk;
+
+ /* Legacy hooks, used by mpc52xx_psc_spi driver. */
+ void (*activate_cs)(u8 cs, u8 polarity);
+ void (*deactivate_cs)(u8 cs, u8 polarity);
};
struct mpc8xx_pcmcia_ops {
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 8a0c2f221e6b..39b95c56587e 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -233,8 +233,6 @@ extern int ftrace_arch_read_dyn_info(char *buf, int size);
extern int skip_trace(unsigned long ip);
-extern void ftrace_release(void *start, unsigned long size);
-
extern void ftrace_disable_daemon(void);
extern void ftrace_enable_daemon(void);
#else
@@ -325,13 +323,8 @@ static inline void __ftrace_enabled_restore(int enabled)
#ifdef CONFIG_FTRACE_MCOUNT_RECORD
extern void ftrace_init(void);
-extern void ftrace_init_module(struct module *mod,
- unsigned long *start, unsigned long *end);
#else
static inline void ftrace_init(void) { }
-static inline void
-ftrace_init_module(struct module *mod,
- unsigned long *start, unsigned long *end) { }
#endif
/*
@@ -368,6 +361,7 @@ struct ftrace_ret_stack {
unsigned long ret;
unsigned long func;
unsigned long long calltime;
+ unsigned long long subtime;
};
/*
@@ -379,8 +373,6 @@ extern void return_to_handler(void);
extern int
ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth);
-extern void
-ftrace_pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret);
/*
* Sometimes we don't want to trace a function with the function
@@ -496,8 +488,15 @@ static inline int test_tsk_trace_graph(struct task_struct *tsk)
extern int ftrace_dump_on_oops;
+#ifdef CONFIG_PREEMPT
+#define INIT_TRACE_RECURSION .trace_recursion = 0,
+#endif
+
#endif /* CONFIG_TRACING */
+#ifndef INIT_TRACE_RECURSION
+#define INIT_TRACE_RECURSION
+#endif
#ifdef CONFIG_HW_BRANCH_TRACER
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
new file mode 100644
index 000000000000..662c1becf367
--- /dev/null
+++ b/include/linux/ftrace_event.h
@@ -0,0 +1,156 @@
+#ifndef _LINUX_FTRACE_EVENT_H
+#define _LINUX_FTRACE_EVENT_H
+
+#include <linux/trace_seq.h>
+#include <linux/ring_buffer.h>
+
+
+struct trace_array;
+struct tracer;
+struct dentry;
+
+/*
+ * The trace entry - the most basic unit of tracing. This is what
+ * is printed in the end as a single line in the trace output, such as:
+ *
+ * bash-15816 [01] 235.197585: idle_cpu <- irq_enter
+ */
+struct trace_entry {
+ unsigned short type;
+ unsigned char flags;
+ unsigned char preempt_count;
+ int pid;
+ int tgid;
+};
+
+#define FTRACE_MAX_EVENT \
+ ((1 << (sizeof(((struct trace_entry *)0)->type) * 8)) - 1)
+
+/*
+ * Trace iterator - used by printout routines who present trace
+ * results to users and which routines might sleep, etc:
+ */
+struct trace_iterator {
+ struct trace_array *tr;
+ struct tracer *trace;
+ void *private;
+ int cpu_file;
+ struct mutex mutex;
+ struct ring_buffer_iter *buffer_iter[NR_CPUS];
+
+ /* The below is zeroed out in pipe_read */
+ struct trace_seq seq;
+ struct trace_entry *ent;
+ int cpu;
+ u64 ts;
+
+ unsigned long iter_flags;
+ loff_t pos;
+ long idx;
+
+ cpumask_var_t started;
+};
+
+
+typedef enum print_line_t (*trace_print_func)(struct trace_iterator *iter,
+ int flags);
+struct trace_event {
+ struct hlist_node node;
+ struct list_head list;
+ int type;
+ trace_print_func trace;
+ trace_print_func raw;
+ trace_print_func hex;
+ trace_print_func binary;
+};
+
+extern int register_ftrace_event(struct trace_event *event);
+extern int unregister_ftrace_event(struct trace_event *event);
+
+/* Return values for print_line callback */
+enum print_line_t {
+ TRACE_TYPE_PARTIAL_LINE = 0, /* Retry after flushing the seq */
+ TRACE_TYPE_HANDLED = 1,
+ TRACE_TYPE_UNHANDLED = 2, /* Relay to other output functions */
+ TRACE_TYPE_NO_CONSUME = 3 /* Handled but ask to not consume */
+};
+
+
+struct ring_buffer_event *
+trace_current_buffer_lock_reserve(int type, unsigned long len,
+ unsigned long flags, int pc);
+void trace_current_buffer_unlock_commit(struct ring_buffer_event *event,
+ unsigned long flags, int pc);
+void trace_nowake_buffer_unlock_commit(struct ring_buffer_event *event,
+ unsigned long flags, int pc);
+void trace_current_buffer_discard_commit(struct ring_buffer_event *event);
+
+void tracing_record_cmdline(struct task_struct *tsk);
+
+struct ftrace_event_call {
+ struct list_head list;
+ char *name;
+ char *system;
+ struct dentry *dir;
+ struct trace_event *event;
+ int enabled;
+ int (*regfunc)(void);
+ void (*unregfunc)(void);
+ int id;
+ int (*raw_init)(void);
+ int (*show_format)(struct trace_seq *s);
+ int (*define_fields)(void);
+ struct list_head fields;
+ int filter_active;
+ void *filter;
+ void *mod;
+
+#ifdef CONFIG_EVENT_PROFILE
+ atomic_t profile_count;
+ int (*profile_enable)(struct ftrace_event_call *);
+ void (*profile_disable)(struct ftrace_event_call *);
+#endif
+};
+
+#define MAX_FILTER_PRED 32
+#define MAX_FILTER_STR_VAL 128
+
+extern int init_preds(struct ftrace_event_call *call);
+extern void destroy_preds(struct ftrace_event_call *call);
+extern int filter_match_preds(struct ftrace_event_call *call, void *rec);
+extern int filter_current_check_discard(struct ftrace_event_call *call,
+ void *rec,
+ struct ring_buffer_event *event);
+
+extern int trace_define_field(struct ftrace_event_call *call, char *type,
+ char *name, int offset, int size, int is_signed);
+
+#define is_signed_type(type) (((type)(-1)) < 0)
+
+/*
+ * The double __builtin_constant_p is because gcc will give us an error
+ * if we try to allocate the static variable to fmt if it is not a
+ * constant. Even with the outer if statement optimizing out.
+ */
+#define event_trace_printk(ip, fmt, args...) \
+do { \
+ __trace_printk_check_format(fmt, ##args); \
+ tracing_record_cmdline(current); \
+ if (__builtin_constant_p(fmt)) { \
+ static const char *trace_printk_fmt \
+ __attribute__((section("__trace_printk_fmt"))) = \
+ __builtin_constant_p(fmt) ? fmt : NULL; \
+ \
+ __trace_bprintk(ip, trace_printk_fmt, ##args); \
+ } else \
+ __trace_printk(ip, fmt, ##args); \
+} while (0)
+
+#define __common_field(type, item, is_signed) \
+ ret = trace_define_field(event_call, #type, "common_" #item, \
+ offsetof(typeof(field.ent), item), \
+ sizeof(field.ent.item), is_signed); \
+ if (ret) \
+ return ret;
+
+#endif /* _LINUX_FTRACE_EVENT_H */
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index 162e5defe683..d41ed593f79f 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -121,6 +121,13 @@ struct fuse_file_lock {
#define FUSE_BIG_WRITES (1 << 5)
/**
+ * CUSE INIT request/reply flags
+ *
+ * CUSE_UNRESTRICTED_IOCTL: use unrestricted ioctl
+ */
+#define CUSE_UNRESTRICTED_IOCTL (1 << 0)
+
+/**
* Release flags
*/
#define FUSE_RELEASE_FLUSH (1 << 0)
@@ -210,6 +217,9 @@ enum fuse_opcode {
FUSE_DESTROY = 38,
FUSE_IOCTL = 39,
FUSE_POLL = 40,
+
+ /* CUSE specific operations */
+ CUSE_INIT = 4096,
};
enum fuse_notify_code {
@@ -401,6 +411,27 @@ struct fuse_init_out {
__u32 max_write;
};
+#define CUSE_INIT_INFO_MAX 4096
+
+struct cuse_init_in {
+ __u32 major;
+ __u32 minor;
+ __u32 unused;
+ __u32 flags;
+};
+
+struct cuse_init_out {
+ __u32 major;
+ __u32 minor;
+ __u32 unused;
+ __u32 flags;
+ __u32 max_read;
+ __u32 max_write;
+ __u32 dev_major; /* chardev major */
+ __u32 dev_minor; /* chardev minor */
+ __u32 spare[10];
+};
+
struct fuse_interrupt_in {
__u64 unique;
};
diff --git a/include/linux/futex.h b/include/linux/futex.h
index 3bf5bb5a34f9..34956c8fdebf 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -23,6 +23,8 @@ union ktime;
#define FUTEX_TRYLOCK_PI 8
#define FUTEX_WAIT_BITSET 9
#define FUTEX_WAKE_BITSET 10
+#define FUTEX_WAIT_REQUEUE_PI 11
+#define FUTEX_CMP_REQUEUE_PI 12
#define FUTEX_PRIVATE_FLAG 128
#define FUTEX_CLOCK_REALTIME 256
@@ -38,6 +40,10 @@ union ktime;
#define FUTEX_TRYLOCK_PI_PRIVATE (FUTEX_TRYLOCK_PI | FUTEX_PRIVATE_FLAG)
#define FUTEX_WAIT_BITSET_PRIVATE (FUTEX_WAIT_BITS | FUTEX_PRIVATE_FLAG)
#define FUTEX_WAKE_BITSET_PRIVATE (FUTEX_WAKE_BITS | FUTEX_PRIVATE_FLAG)
+#define FUTEX_WAIT_REQUEUE_PI_PRIVATE (FUTEX_WAIT_REQUEUE_PI | \
+ FUTEX_PRIVATE_FLAG)
+#define FUTEX_CMP_REQUEUE_PI_PRIVATE (FUTEX_CMP_REQUEUE_PI | \
+ FUTEX_PRIVATE_FLAG)
/*
* Support for robust futexes: the kernel cleans up held futexes at
diff --git a/include/linux/gameport.h b/include/linux/gameport.h
index 0cd825f7363a..1bc08541c2b9 100644
--- a/include/linux/gameport.h
+++ b/include/linux/gameport.h
@@ -11,6 +11,7 @@
#ifdef __KERNEL__
#include <asm/io.h>
+#include <linux/types.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/device.h>
@@ -62,7 +63,7 @@ struct gameport_driver {
struct device_driver driver;
- unsigned int ignore;
+ bool ignore;
};
#define to_gameport_driver(d) container_of(d, struct gameport_driver, driver)
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 634c53028fb8..a1a28caed23d 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -214,6 +214,7 @@ static inline void disk_put_part(struct hd_struct *part)
#define DISK_PITER_REVERSE (1 << 0) /* iterate in the reverse direction */
#define DISK_PITER_INCL_EMPTY (1 << 1) /* include 0-sized parts */
#define DISK_PITER_INCL_PART0 (1 << 2) /* include partition 0 */
+#define DISK_PITER_INCL_EMPTY_PART0 (1 << 3) /* include empty partition 0 */
struct disk_part_iter {
struct gendisk *disk;
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index ad2580596033..844d2662a875 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -100,9 +100,8 @@ extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client,
* @class: What kind of i2c device we instantiate (for detect)
* @attach_adapter: Callback for bus addition (for legacy drivers)
* @detach_adapter: Callback for bus removal (for legacy drivers)
- * @detach_client: Callback for device removal (for legacy drivers)
- * @probe: Callback for device binding (new-style drivers)
- * @remove: Callback for device unbinding (new-style drivers)
+ * @probe: Callback for device binding
+ * @remove: Callback for device unbinding
* @shutdown: Callback for device shutdown
* @suspend: Callback for device suspend
* @resume: Callback for device resume
@@ -137,26 +136,14 @@ struct i2c_driver {
int id;
unsigned int class;
- /* Notifies the driver that a new bus has appeared. This routine
- * can be used by the driver to test if the bus meets its conditions
- * & seek for the presence of the chip(s) it supports. If found, it
- * registers the client(s) that are on the bus to the i2c admin. via
- * i2c_attach_client. (LEGACY I2C DRIVERS ONLY)
+ /* Notifies the driver that a new bus has appeared or is about to be
+ * removed. You should avoid using this if you can, it will probably
+ * be removed in a near future.
*/
int (*attach_adapter)(struct i2c_adapter *);
int (*detach_adapter)(struct i2c_adapter *);
- /* tells the driver that a client is about to be deleted & gives it
- * the chance to remove its private data. Also, if the client struct
- * has been dynamically allocated by the driver in the function above,
- * it must be freed here. (LEGACY I2C DRIVERS ONLY)
- */
- int (*detach_client)(struct i2c_client *) __deprecated;
-
- /* Standard driver model interfaces, for "new style" i2c drivers.
- * With the driver model, device enumeration is NEVER done by drivers;
- * it's done by infrastructure. (NEW STYLE DRIVERS ONLY)
- */
+ /* Standard driver model interfaces */
int (*probe)(struct i2c_client *, const struct i2c_device_id *);
int (*remove)(struct i2c_client *);
@@ -191,9 +178,8 @@ struct i2c_driver {
* @driver: device's driver, hence pointer to access routines
* @dev: Driver model device node for the slave.
* @irq: indicates the IRQ generated by this device (if any)
- * @list: list of active/busy clients (DEPRECATED)
- * @detected: member of an i2c_driver.clients list
- * @released: used to synchronize client releases & detaches and references
+ * @detected: member of an i2c_driver.clients list or i2c-core's
+ * userspace_devices list
*
* An i2c_client identifies a single device (i.e. chip) connected to an
* i2c bus. The behaviour exposed to Linux is defined by the driver
@@ -209,9 +195,7 @@ struct i2c_client {
struct i2c_driver *driver; /* and our access routines */
struct device dev; /* the device structure */
int irq; /* irq issued by device */
- struct list_head list; /* DEPRECATED */
struct list_head detected;
- struct completion released;
};
#define to_i2c_client(d) container_of(d, struct i2c_client, dev)
@@ -248,11 +232,10 @@ static inline void i2c_set_clientdata(struct i2c_client *dev, void *data)
* that, such as chip type, configuration, associated IRQ, and so on.
*
* i2c_board_info is used to build tables of information listing I2C devices
- * that are present. This information is used to grow the driver model tree
- * for "new style" I2C drivers. For mainboards this is done statically using
- * i2c_register_board_info(); bus numbers identify adapters that aren't
- * yet available. For add-on boards, i2c_new_device() does this dynamically
- * with the adapter already known.
+ * that are present. This information is used to grow the driver model tree.
+ * For mainboards this is done statically using i2c_register_board_info();
+ * bus numbers identify adapters that aren't yet available. For add-on boards,
+ * i2c_new_device() does this dynamically with the adapter already known.
*/
struct i2c_board_info {
char type[I2C_NAME_SIZE];
@@ -352,21 +335,15 @@ struct i2c_adapter {
const struct i2c_algorithm *algo; /* the algorithm to access the bus */
void *algo_data;
- /* --- administration stuff. */
- int (*client_register)(struct i2c_client *) __deprecated;
- int (*client_unregister)(struct i2c_client *) __deprecated;
-
/* data fields that are valid for all devices */
u8 level; /* nesting level for lockdep */
struct mutex bus_lock;
- struct mutex clist_lock;
int timeout; /* in jiffies */
int retries;
struct device dev; /* the adapter device */
int nr;
- struct list_head clients; /* DEPRECATED */
char name[48];
struct completion dev_released;
};
@@ -429,11 +406,6 @@ static inline int i2c_add_driver(struct i2c_driver *driver)
return i2c_register_driver(THIS_MODULE, driver);
}
-/* These are deprecated, your driver should use the standard .probe()
- * and .remove() methods instead. */
-extern int __deprecated i2c_attach_client(struct i2c_client *);
-extern int __deprecated i2c_detach_client(struct i2c_client *);
-
extern struct i2c_client *i2c_use_client(struct i2c_client *client);
extern void i2c_release_client(struct i2c_client *client);
@@ -442,14 +414,6 @@ extern void i2c_release_client(struct i2c_client *client);
extern void i2c_clients_command(struct i2c_adapter *adap,
unsigned int cmd, void *arg);
-/* 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);
- */
-extern int i2c_probe(struct i2c_adapter *adapter,
- const struct i2c_client_address_data *address_data,
- int (*found_proc) (struct i2c_adapter *, int, int));
-
extern struct i2c_adapter *i2c_get_adapter(int id);
extern void i2c_put_adapter(struct i2c_adapter *adap);
diff --git a/include/linux/ide.h b/include/linux/ide.h
index ff65fffb078f..34c128f0a33c 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -26,6 +26,9 @@
#include <asm/io.h>
#include <asm/mutex.h>
+/* for request_sense */
+#include <linux/cdrom.h>
+
#if defined(CONFIG_CRIS) || defined(CONFIG_FRV) || defined(CONFIG_MN10300)
# define SUPPORT_VLB_SYNC 0
#else
@@ -324,7 +327,6 @@ struct ide_cmd {
unsigned int cursg_ofs;
struct request *rq; /* copy of request */
- void *special; /* valid_t generally */
};
/* ATAPI packet command flags */
@@ -360,11 +362,7 @@ struct ide_atapi_pc {
/* data buffer */
u8 *buf;
- /* current buffer position */
- u8 *cur_pos;
int buf_size;
- /* missing/available data on the current buffer */
- int b_count;
/* the corresponding request */
struct request *rq;
@@ -377,10 +375,6 @@ struct ide_atapi_pc {
*/
u8 pc_buf[IDE_PC_BUFFER_SIZE];
- /* idetape only */
- struct idetape_bh *bh;
- char *b_data;
-
unsigned long timeout;
};
@@ -593,16 +587,16 @@ struct ide_drive_s {
/* callback for packet commands */
int (*pc_callback)(struct ide_drive_s *, int);
- void (*pc_update_buffers)(struct ide_drive_s *, struct ide_atapi_pc *);
- int (*pc_io_buffers)(struct ide_drive_s *, struct ide_atapi_pc *,
- unsigned int, int);
-
ide_startstop_t (*irq_handler)(struct ide_drive_s *);
unsigned long atapi_flags;
struct ide_atapi_pc request_sense_pc;
- struct request request_sense_rq;
+
+ /* current sense rq and buffer */
+ bool sense_rq_armed;
+ struct request sense_rq;
+ struct request_sense sense_data;
};
typedef struct ide_drive_s ide_drive_t;
@@ -1174,7 +1168,10 @@ int ide_do_test_unit_ready(ide_drive_t *, struct gendisk *);
int ide_do_start_stop(ide_drive_t *, struct gendisk *, int);
int ide_set_media_lock(ide_drive_t *, struct gendisk *, int);
void ide_create_request_sense_cmd(ide_drive_t *, struct ide_atapi_pc *);
-void ide_retry_pc(ide_drive_t *, struct gendisk *);
+void ide_retry_pc(ide_drive_t *drive);
+
+void ide_prep_sense(ide_drive_t *drive, struct request *rq);
+int ide_queue_sense_rq(ide_drive_t *drive, void *special);
int ide_cd_expiry(ide_drive_t *);
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index dc92359f37e6..05c29c01174c 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1068,8 +1068,12 @@ enum ieee80211_category {
WLAN_CATEGORY_DLS = 2,
WLAN_CATEGORY_BACK = 3,
WLAN_CATEGORY_PUBLIC = 4,
+ WLAN_CATEGORY_HT = 7,
WLAN_CATEGORY_SA_QUERY = 8,
+ WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION = 9,
WLAN_CATEGORY_WMM = 17,
+ WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126,
+ WLAN_CATEGORY_VENDOR_SPECIFIC = 127,
};
/* SPECTRUM_MGMT action code */
@@ -1261,7 +1265,9 @@ static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
if (ieee80211_has_protected(hdr->frame_control))
return true;
category = ((u8 *) hdr) + 24;
- return *category != WLAN_CATEGORY_PUBLIC;
+ return *category != WLAN_CATEGORY_PUBLIC &&
+ *category != WLAN_CATEGORY_HT &&
+ *category != WLAN_CATEGORY_VENDOR_SPECIFIC;
}
return false;
diff --git a/include/linux/init.h b/include/linux/init.h
index 68cb0265d009..0e06c176f185 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -2,6 +2,8 @@
#define _LINUX_INIT_H
#include <linux/compiler.h>
+#include <linux/section-names.h>
+#include <linux/stringify.h>
/* These macros are used to mark some functions or
* initialized data (doesn't apply to uninitialized data)
@@ -60,14 +62,6 @@
#define __refdata __section(.ref.data)
#define __refconst __section(.ref.rodata)
-/* backward compatibility note
- * A few places hardcode the old section names:
- * .text.init.refok
- * .data.init.refok
- * .exit.text.refok
- * They should be converted to use the defines from this file
- */
-
/* compatibility defines */
#define __init_refok __ref
#define __initdata_refok __refdata
@@ -107,7 +101,7 @@
#define __memexitconst __section(.memexit.rodata)
/* For assembly routines */
-#define __HEAD .section ".head.text","ax"
+#define __HEAD .section __stringify(HEAD_TEXT_SECTION),"ax"
#define __INIT .section ".init.text","ax"
#define __FINIT .previous
@@ -247,6 +241,7 @@ struct obs_kernel_param {
/* Relies on boot_command_line being set */
void __init parse_early_param(void);
+void __init parse_early_options(char *cmdline);
#endif /* __ASSEMBLY__ */
/**
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index dcfb93337e9a..6646bfc7b892 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -15,19 +15,6 @@
extern struct files_struct init_files;
extern struct fs_struct init_fs;
-#define INIT_KIOCTX(name, which_mm) \
-{ \
- .users = ATOMIC_INIT(1), \
- .dead = 0, \
- .mm = &which_mm, \
- .user_id = 0, \
- .next = NULL, \
- .wait = __WAIT_QUEUE_HEAD_INITIALIZER(name.wait), \
- .ctx_lock = __SPIN_LOCK_UNLOCKED(name.ctx_lock), \
- .reqs_active = 0U, \
- .max_reqs = ~0U, \
-}
-
#define INIT_MM(name) \
{ \
.mm_rb = RB_ROOT, \
@@ -158,8 +145,8 @@ extern struct cred init_cred;
.group_leader = &tsk, \
.real_cred = &init_cred, \
.cred = &init_cred, \
- .cred_exec_mutex = \
- __MUTEX_INITIALIZER(tsk.cred_exec_mutex), \
+ .cred_guard_mutex = \
+ __MUTEX_INITIALIZER(tsk.cred_guard_mutex), \
.comm = "swapper", \
.thread = INIT_THREAD, \
.fs = &init_fs, \
@@ -187,6 +174,7 @@ extern struct cred init_cred;
INIT_TRACE_IRQFLAGS \
INIT_LOCKDEP \
INIT_FTRACE_GRAPH \
+ INIT_TRACE_RECURSION \
}
diff --git a/include/linux/input.h b/include/linux/input.h
index 6b28048fc568..0e6ff5de3588 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -106,6 +106,7 @@ struct input_absinfo {
#define SYN_REPORT 0
#define SYN_CONFIG 1
+#define SYN_MT_REPORT 2
/*
* Keys and buttons
@@ -445,6 +446,7 @@ struct input_absinfo {
#define BTN_STYLUS2 0x14c
#define BTN_TOOL_DOUBLETAP 0x14d
#define BTN_TOOL_TRIPLETAP 0x14e
+#define BTN_TOOL_QUADTAP 0x14f /* Four fingers on trackpad */
#define BTN_WHEEL 0x150
#define BTN_GEAR_DOWN 0x150
@@ -644,6 +646,17 @@ struct input_absinfo {
#define ABS_TOOL_WIDTH 0x1c
#define ABS_VOLUME 0x20
#define ABS_MISC 0x28
+
+#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
+#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
+#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */
+#define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */
+#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */
+#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
+#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
+#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */
+#define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */
+
#define ABS_MAX 0x3f
#define ABS_CNT (ABS_MAX+1)
@@ -743,6 +756,12 @@ struct input_absinfo {
#define BUS_ATARI 0x1B
/*
+ * MT_TOOL types
+ */
+#define MT_TOOL_FINGER 0
+#define MT_TOOL_PEN 1
+
+/*
* Values describing the status of a force-feedback effect
*/
#define FF_STATUS_STOPPED 0x00
@@ -1311,6 +1330,11 @@ static inline void input_sync(struct input_dev *dev)
input_event(dev, EV_SYN, SYN_REPORT, 0);
}
+static inline void input_mt_sync(struct input_dev *dev)
+{
+ input_event(dev, EV_SYN, SYN_MT_REPORT, 0);
+}
+
void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code);
static inline void input_set_abs_params(struct input_dev *dev, int axis, int min, int max, int fuzz, int flat)
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index aa8c53171233..29e05a034c09 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -120,6 +120,7 @@ static inline void dmar_writeq(void __iomem *addr, u64 val)
(ecap_iotlb_offset(e) + ecap_niotlb_iunits(e) * 16)
#define ecap_coherent(e) ((e) & 0x1)
#define ecap_qis(e) ((e) & 0x2)
+#define ecap_pass_through(e) ((e >> 6) & 0x1)
#define ecap_eim_support(e) ((e >> 4) & 0x1)
#define ecap_ir_support(e) ((e >> 3) & 0x1)
#define ecap_max_handle_mask(e) ((e >> 20) & 0xf)
@@ -280,10 +281,10 @@ struct ir_table {
#endif
struct iommu_flush {
- int (*flush_context)(struct intel_iommu *iommu, u16 did, u16 sid, u8 fm,
- u64 type, int non_present_entry_flush);
- int (*flush_iotlb)(struct intel_iommu *iommu, u16 did, u64 addr,
- unsigned int size_order, u64 type, int non_present_entry_flush);
+ void (*flush_context)(struct intel_iommu *iommu, u16 did, u16 sid,
+ u8 fm, u64 type);
+ void (*flush_iotlb)(struct intel_iommu *iommu, u16 did, u64 addr,
+ unsigned int size_order, u64 type);
};
enum {
@@ -302,6 +303,7 @@ struct intel_iommu {
spinlock_t register_lock; /* protect register handling */
int seq_id; /* sequence id of the iommu */
int agaw; /* agaw of this iommu */
+ int msagaw; /* max sagaw of this iommu */
unsigned int irq;
unsigned char name[13]; /* Device Name */
@@ -337,11 +339,10 @@ extern void dmar_disable_qi(struct intel_iommu *iommu);
extern int dmar_reenable_qi(struct intel_iommu *iommu);
extern void qi_global_iec(struct intel_iommu *iommu);
-extern int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid,
- u8 fm, u64 type, int non_present_entry_flush);
-extern int qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
- unsigned int size_order, u64 type,
- int non_present_entry_flush);
+extern void qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid,
+ u8 fm, u64 type);
+extern void qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
+ unsigned int size_order, u64 type);
extern int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu);
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 91bb76f44f14..ff374ceface0 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -566,6 +566,6 @@ struct irq_desc;
extern int early_irq_init(void);
extern int arch_probe_nr_irqs(void);
extern int arch_early_irq_init(void);
-extern int arch_init_chip_data(struct irq_desc *desc, int cpu);
+extern int arch_init_chip_data(struct irq_desc *desc, int node);
#endif
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 32e4b2f72294..786e7b8cece9 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -49,6 +49,8 @@ struct resource_list {
#define IORESOURCE_SIZEALIGN 0x00020000 /* size indicates alignment */
#define IORESOURCE_STARTALIGN 0x00040000 /* start field is alignment */
+#define IORESOURCE_MEM_64 0x00100000
+
#define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */
#define IORESOURCE_DISABLED 0x10000000
#define IORESOURCE_UNSET 0x20000000
diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h
index 7ebdb4fb4e54..65aae34759de 100644
--- a/include/linux/ipmi.h
+++ b/include/linux/ipmi.h
@@ -198,6 +198,8 @@ struct kernel_ipmi_msg {
response. When you send a
response message, this will
be returned. */
+#define IPMI_OEM_RECV_TYPE 5 /* The response for OEM Channels */
+
/* Note that async events and received commands do not have a completion
code as the first byte of the incoming data, unlike a response. */
diff --git a/include/linux/ipmi_msgdefs.h b/include/linux/ipmi_msgdefs.h
index b56a158d587a..df97e6e31e87 100644
--- a/include/linux/ipmi_msgdefs.h
+++ b/include/linux/ipmi_msgdefs.h
@@ -58,6 +58,12 @@
#define IPMI_READ_EVENT_MSG_BUFFER_CMD 0x35
#define IPMI_GET_CHANNEL_INFO_CMD 0x42
+/* Bit for BMC global enables. */
+#define IPMI_BMC_RCV_MSG_INTR 0x01
+#define IPMI_BMC_EVT_MSG_INTR 0x02
+#define IPMI_BMC_EVT_MSG_BUFF 0x04
+#define IPMI_BMC_SYS_LOG 0x08
+
#define IPMI_NETFN_STORAGE_REQUEST 0x0a
#define IPMI_NETFN_STORAGE_RESPONSE 0x0b
#define IPMI_ADD_SEL_ENTRY_CMD 0x44
@@ -109,5 +115,7 @@
#define IPMI_CHANNEL_MEDIUM_USB1 10
#define IPMI_CHANNEL_MEDIUM_USB2 11
#define IPMI_CHANNEL_MEDIUM_SYSINTF 12
+#define IPMI_CHANNEL_MEDIUM_OEM_MIN 0x60
+#define IPMI_CHANNEL_MEDIUM_OEM_MAX 0x7f
#endif /* __LINUX_IPMI_MSGDEFS_H */
diff --git a/include/linux/irq.h b/include/linux/irq.h
index b7cbeed972e4..eedbb8e5e0cc 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -117,7 +117,7 @@ struct irq_chip {
void (*eoi)(unsigned int irq);
void (*end)(unsigned int irq);
- void (*set_affinity)(unsigned int irq,
+ int (*set_affinity)(unsigned int irq,
const struct cpumask *dest);
int (*retrigger)(unsigned int irq);
int (*set_type)(unsigned int irq, unsigned int flow_type);
@@ -187,7 +187,7 @@ struct irq_desc {
spinlock_t lock;
#ifdef CONFIG_SMP
cpumask_var_t affinity;
- unsigned int cpu;
+ unsigned int node;
#ifdef CONFIG_GENERIC_PENDING_IRQ
cpumask_var_t pending_mask;
#endif
@@ -201,26 +201,23 @@ struct irq_desc {
} ____cacheline_internodealigned_in_smp;
extern void arch_init_copy_chip_data(struct irq_desc *old_desc,
- struct irq_desc *desc, int cpu);
+ struct irq_desc *desc, int node);
extern void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc);
#ifndef CONFIG_SPARSE_IRQ
extern struct irq_desc irq_desc[NR_IRQS];
-#else /* CONFIG_SPARSE_IRQ */
-extern struct irq_desc *move_irq_desc(struct irq_desc *old_desc, int cpu);
-#endif /* CONFIG_SPARSE_IRQ */
-
-extern struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu);
+#endif
-static inline struct irq_desc *
-irq_remap_to_desc(unsigned int irq, struct irq_desc *desc)
-{
-#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
- return irq_to_desc(irq);
+#ifdef CONFIG_NUMA_IRQ_DESC
+extern struct irq_desc *move_irq_desc(struct irq_desc *old_desc, int node);
#else
+static inline struct irq_desc *move_irq_desc(struct irq_desc *desc, int node)
+{
return desc;
-#endif
}
+#endif
+
+extern struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node);
/*
* Migration helpers for obsolete names, they will go away:
@@ -386,7 +383,7 @@ extern void set_irq_noprobe(unsigned int irq);
extern void set_irq_probe(unsigned int irq);
/* Handle dynamic irq creation and destruction */
-extern unsigned int create_irq_nr(unsigned int irq_want);
+extern unsigned int create_irq_nr(unsigned int irq_want, int node);
extern int create_irq(void);
extern void destroy_irq(unsigned int irq);
@@ -424,47 +421,48 @@ extern int set_irq_msi(unsigned int irq, struct msi_desc *entry);
#ifdef CONFIG_SMP
/**
- * init_alloc_desc_masks - allocate cpumasks for irq_desc
+ * alloc_desc_masks - allocate cpumasks for irq_desc
* @desc: pointer to irq_desc struct
* @cpu: cpu which will be handling the cpumasks
* @boot: true if need bootmem
*
* Allocates affinity and pending_mask cpumask if required.
* Returns true if successful (or not required).
- * Side effect: affinity has all bits set, pending_mask has all bits clear.
*/
-static inline bool init_alloc_desc_masks(struct irq_desc *desc, int cpu,
+static inline bool alloc_desc_masks(struct irq_desc *desc, int node,
bool boot)
{
- int node;
-
+#ifdef CONFIG_CPUMASK_OFFSTACK
if (boot) {
alloc_bootmem_cpumask_var(&desc->affinity);
- cpumask_setall(desc->affinity);
#ifdef CONFIG_GENERIC_PENDING_IRQ
alloc_bootmem_cpumask_var(&desc->pending_mask);
- cpumask_clear(desc->pending_mask);
#endif
return true;
}
- node = cpu_to_node(cpu);
-
if (!alloc_cpumask_var_node(&desc->affinity, GFP_ATOMIC, node))
return false;
- cpumask_setall(desc->affinity);
#ifdef CONFIG_GENERIC_PENDING_IRQ
if (!alloc_cpumask_var_node(&desc->pending_mask, GFP_ATOMIC, node)) {
free_cpumask_var(desc->affinity);
return false;
}
- cpumask_clear(desc->pending_mask);
+#endif
#endif
return true;
}
+static inline void init_desc_masks(struct irq_desc *desc)
+{
+ cpumask_setall(desc->affinity);
+#ifdef CONFIG_GENERIC_PENDING_IRQ
+ cpumask_clear(desc->pending_mask);
+#endif
+}
+
/**
* init_copy_desc_masks - copy cpumasks for irq_desc
* @old_desc: pointer to old irq_desc struct
@@ -478,7 +476,7 @@ static inline bool init_alloc_desc_masks(struct irq_desc *desc, int cpu,
static inline void init_copy_desc_masks(struct irq_desc *old_desc,
struct irq_desc *new_desc)
{
-#ifdef CONFIG_CPUMASKS_OFFSTACK
+#ifdef CONFIG_CPUMASK_OFFSTACK
cpumask_copy(new_desc->affinity, old_desc->affinity);
#ifdef CONFIG_GENERIC_PENDING_IRQ
@@ -499,12 +497,16 @@ static inline void free_desc_masks(struct irq_desc *old_desc,
#else /* !CONFIG_SMP */
-static inline bool init_alloc_desc_masks(struct irq_desc *desc, int cpu,
+static inline bool alloc_desc_masks(struct irq_desc *desc, int node,
bool boot)
{
return true;
}
+static inline void init_desc_masks(struct irq_desc *desc)
+{
+}
+
static inline void init_copy_desc_masks(struct irq_desc *old_desc,
struct irq_desc *new_desc)
{
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index 53ae4399da2d..c2049a04fa0b 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -978,7 +978,8 @@ extern void journal_destroy_revoke(journal_t *);
extern int journal_revoke (handle_t *,
unsigned long, struct buffer_head *);
extern int journal_cancel_revoke(handle_t *, struct journal_head *);
-extern void journal_write_revoke_records(journal_t *, transaction_t *);
+extern void journal_write_revoke_records(journal_t *,
+ transaction_t *, int);
/* Recovery revoke support */
extern int journal_set_revoke(journal_t *, unsigned long, tid_t);
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index 8815a3456b3b..cc02393bfce8 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -1193,7 +1193,8 @@ extern int jbd2_journal_init_revoke_caches(void);
extern void jbd2_journal_destroy_revoke(journal_t *);
extern int jbd2_journal_revoke (handle_t *, unsigned long long, struct buffer_head *);
extern int jbd2_journal_cancel_revoke(handle_t *, struct journal_head *);
-extern void jbd2_journal_write_revoke_records(journal_t *, transaction_t *);
+extern void jbd2_journal_write_revoke_records(journal_t *,
+ transaction_t *, int);
/* Recovery revoke support */
extern int jbd2_journal_set_revoke(journal_t *, unsigned long long, tid_t);
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index d9e75ec7def5..883cd44ff765 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -377,6 +377,15 @@ static inline char *pack_hex_byte(char *buf, u8 byte)
#define pr_cont(fmt, ...) \
printk(KERN_CONT fmt, ##__VA_ARGS__)
+/* pr_devel() should produce zero code unless DEBUG is defined */
+#ifdef DEBUG
+#define pr_devel(fmt, ...) \
+ printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
+#else
+#define pr_devel(fmt, ...) \
+ ({ if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); 0; })
+#endif
+
/* If you are writing a driver, please use dev_dbg instead */
#if defined(DEBUG)
#define pr_debug(fmt, ...) \
diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h
index 6adcc297e354..3318b9416c66 100644
--- a/include/linux/kgdb.h
+++ b/include/linux/kgdb.h
@@ -29,8 +29,7 @@ struct pt_regs;
*
* On some architectures it is required to skip a breakpoint
* exception when it occurs after a breakpoint has been removed.
- * This can be implemented in the architecture specific portion of
- * for kgdb.
+ * This can be implemented in the architecture specific portion of kgdb.
*/
extern int kgdb_skipexception(int exception, struct pt_regs *regs);
@@ -42,7 +41,7 @@ extern int kgdb_skipexception(int exception, struct pt_regs *regs);
*
* This is usually needed on architectures which support SMP and
* KGDB. This function is called after all the secondary cpus have
- * been put to a know spin state and the primary CPU has control over
+ * been put to a known spin state and the primary CPU has control over
* KGDB.
*/
extern void kgdb_post_primary_code(struct pt_regs *regs, int e_vector,
@@ -65,7 +64,7 @@ struct uart_port;
/**
* kgdb_breakpoint - compiled in breakpoint
*
- * This will be impelmented a static inline per architecture. This
+ * This will be implemented as a static inline per architecture. This
* function is called by the kgdb core to execute an architecture
* specific trap to cause kgdb to enter the exception processing.
*
@@ -190,7 +189,7 @@ kgdb_arch_handle_exception(int vector, int signo, int err_code,
* @flags: Current IRQ state
*
* On SMP systems, we need to get the attention of the other CPUs
- * and get them be in a known state. This should do what is needed
+ * and get them into a known state. This should do what is needed
* to get the other CPUs to call kgdb_wait(). Note that on some arches,
* the NMI approach is not used for rounding up all the CPUs. For example,
* in case of MIPS, smp_call_function() is used to roundup CPUs. In
@@ -267,8 +266,45 @@ extern int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops);
extern void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops);
extern int kgdb_hex2long(char **ptr, unsigned long *long_val);
-extern int kgdb_mem2hex(char *mem, char *buf, int count);
-extern int kgdb_hex2mem(char *buf, char *mem, int count);
+
+/**
+ * kgdb_mem2hex - (optional arch override) translate bin to hex chars
+ * @mem: source buffer
+ * @buf: target buffer
+ * @count: number of bytes in mem
+ *
+ * Architectures which do not support probe_kernel_(read|write),
+ * can make an alternate implementation of this function.
+ * This function safely reads memory into hex
+ * characters for use with the kgdb protocol.
+ */
+extern int __weak kgdb_mem2hex(char *mem, char *buf, int count);
+
+/**
+ * kgdb_hex2mem - (optional arch override) translate hex chars to bin
+ * @buf: source buffer
+ * @mem: target buffer
+ * @count: number of bytes in mem
+ *
+ * Architectures which do not support probe_kernel_(read|write),
+ * can make an alternate implementation of this function.
+ * This function safely writes hex characters into memory
+ * for use with the kgdb protocol.
+ */
+extern int __weak kgdb_hex2mem(char *buf, char *mem, int count);
+
+/**
+ * kgdb_ebin2mem - (optional arch override) Copy binary array from @buf into @mem
+ * @buf: source buffer
+ * @mem: target buffer
+ * @count: number of bytes in mem
+ *
+ * Architectures which do not support probe_kernel_(read|write),
+ * can make an alternate implementation of this function.
+ * This function safely copies binary array into memory
+ * for use with the kgdb protocol.
+ */
+extern int __weak kgdb_ebin2mem(char *buf, char *mem, int count);
extern int kgdb_isremovedbreak(unsigned long addr);
diff --git a/include/linux/kmemleak.h b/include/linux/kmemleak.h
new file mode 100644
index 000000000000..7796aed6cdd5
--- /dev/null
+++ b/include/linux/kmemleak.h
@@ -0,0 +1,96 @@
+/*
+ * include/linux/kmemleak.h
+ *
+ * Copyright (C) 2008 ARM Limited
+ * Written by Catalin Marinas <catalin.marinas@arm.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.
+ *
+ * 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
+ */
+
+#ifndef __KMEMLEAK_H
+#define __KMEMLEAK_H
+
+#ifdef CONFIG_DEBUG_KMEMLEAK
+
+extern void kmemleak_init(void);
+extern void kmemleak_alloc(const void *ptr, size_t size, int min_count,
+ gfp_t gfp);
+extern void kmemleak_free(const void *ptr);
+extern void kmemleak_padding(const void *ptr, unsigned long offset,
+ size_t size);
+extern void kmemleak_not_leak(const void *ptr);
+extern void kmemleak_ignore(const void *ptr);
+extern void kmemleak_scan_area(const void *ptr, unsigned long offset,
+ size_t length, gfp_t gfp);
+extern void kmemleak_no_scan(const void *ptr);
+
+static inline void kmemleak_alloc_recursive(const void *ptr, size_t size,
+ int min_count, unsigned long flags,
+ gfp_t gfp)
+{
+ if (!(flags & SLAB_NOLEAKTRACE))
+ kmemleak_alloc(ptr, size, min_count, gfp);
+}
+
+static inline void kmemleak_free_recursive(const void *ptr, unsigned long flags)
+{
+ if (!(flags & SLAB_NOLEAKTRACE))
+ kmemleak_free(ptr);
+}
+
+static inline void kmemleak_erase(void **ptr)
+{
+ *ptr = NULL;
+}
+
+#else
+
+static inline void kmemleak_init(void)
+{
+}
+static inline void kmemleak_alloc(const void *ptr, size_t size, int min_count,
+ gfp_t gfp)
+{
+}
+static inline void kmemleak_alloc_recursive(const void *ptr, size_t size,
+ int min_count, unsigned long flags,
+ gfp_t gfp)
+{
+}
+static inline void kmemleak_free(const void *ptr)
+{
+}
+static inline void kmemleak_free_recursive(const void *ptr, unsigned long flags)
+{
+}
+static inline void kmemleak_not_leak(const void *ptr)
+{
+}
+static inline void kmemleak_ignore(const void *ptr)
+{
+}
+static inline void kmemleak_scan_area(const void *ptr, unsigned long offset,
+ size_t length, gfp_t gfp)
+{
+}
+static inline void kmemleak_erase(void **ptr)
+{
+}
+static inline void kmemleak_no_scan(const void *ptr)
+{
+}
+
+#endif /* CONFIG_DEBUG_KMEMLEAK */
+
+#endif /* __KMEMLEAK_H */
diff --git a/include/linux/kmemtrace.h b/include/linux/kmemtrace.h
new file mode 100644
index 000000000000..b616d3930c3b
--- /dev/null
+++ b/include/linux/kmemtrace.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2008 Eduard - Gabriel Munteanu
+ *
+ * This file is released under GPL version 2.
+ */
+
+#ifndef _LINUX_KMEMTRACE_H
+#define _LINUX_KMEMTRACE_H
+
+#ifdef __KERNEL__
+
+#include <trace/events/kmem.h>
+
+#ifdef CONFIG_KMEMTRACE
+extern void kmemtrace_init(void);
+#else
+static inline void kmemtrace_init(void)
+{
+}
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_KMEMTRACE_H */
+
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 311a073afe8a..3db5d8d37485 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -119,7 +119,7 @@ struct kvm_run {
__u32 error_code;
} ex;
/* KVM_EXIT_IO */
- struct kvm_io {
+ struct {
#define KVM_EXIT_IO_IN 0
#define KVM_EXIT_IO_OUT 1
__u8 direction;
@@ -224,10 +224,10 @@ struct kvm_interrupt {
/* for KVM_GET_DIRTY_LOG */
struct kvm_dirty_log {
__u32 slot;
- __u32 padding;
+ __u32 padding1;
union {
void __user *dirty_bitmap; /* one bit per page */
- __u64 padding;
+ __u64 padding2;
};
};
@@ -409,6 +409,12 @@ struct kvm_trace_rec {
#ifdef __KVM_HAVE_DEVICE_ASSIGNMENT
#define KVM_CAP_DEVICE_DEASSIGNMENT 27
#endif
+#ifdef __KVM_HAVE_MSIX
+#define KVM_CAP_DEVICE_MSIX 28
+#endif
+#define KVM_CAP_ASSIGN_DEV_IRQ 29
+/* Another bug in KVM_SET_USER_MEMORY_REGION fixed: */
+#define KVM_CAP_JOIN_MEMORY_REGIONS_WORKS 30
#ifdef KVM_CAP_IRQ_ROUTING
@@ -480,11 +486,18 @@ struct kvm_irq_routing {
#define KVM_ASSIGN_PCI_DEVICE _IOR(KVMIO, 0x69, \
struct kvm_assigned_pci_dev)
#define KVM_SET_GSI_ROUTING _IOW(KVMIO, 0x6a, struct kvm_irq_routing)
+/* deprecated, replaced by KVM_ASSIGN_DEV_IRQ */
#define KVM_ASSIGN_IRQ _IOR(KVMIO, 0x70, \
struct kvm_assigned_irq)
+#define KVM_ASSIGN_DEV_IRQ _IOW(KVMIO, 0x70, struct kvm_assigned_irq)
#define KVM_REINJECT_CONTROL _IO(KVMIO, 0x71)
#define KVM_DEASSIGN_PCI_DEVICE _IOW(KVMIO, 0x72, \
struct kvm_assigned_pci_dev)
+#define KVM_ASSIGN_SET_MSIX_NR \
+ _IOW(KVMIO, 0x73, struct kvm_assigned_msix_nr)
+#define KVM_ASSIGN_SET_MSIX_ENTRY \
+ _IOW(KVMIO, 0x74, struct kvm_assigned_msix_entry)
+#define KVM_DEASSIGN_DEV_IRQ _IOW(KVMIO, 0x75, struct kvm_assigned_irq)
/*
* ioctls for vcpu fds
@@ -575,6 +588,8 @@ struct kvm_debug_guest {
#define KVM_TRC_STLB_INVAL (KVM_TRC_HANDLER + 0x18)
#define KVM_TRC_PPC_INSTR (KVM_TRC_HANDLER + 0x19)
+#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
+
struct kvm_assigned_pci_dev {
__u32 assigned_dev_id;
__u32 busnr;
@@ -585,6 +600,17 @@ struct kvm_assigned_pci_dev {
};
};
+#define KVM_DEV_IRQ_HOST_INTX (1 << 0)
+#define KVM_DEV_IRQ_HOST_MSI (1 << 1)
+#define KVM_DEV_IRQ_HOST_MSIX (1 << 2)
+
+#define KVM_DEV_IRQ_GUEST_INTX (1 << 8)
+#define KVM_DEV_IRQ_GUEST_MSI (1 << 9)
+#define KVM_DEV_IRQ_GUEST_MSIX (1 << 10)
+
+#define KVM_DEV_IRQ_HOST_MASK 0x00ff
+#define KVM_DEV_IRQ_GUEST_MASK 0xff00
+
struct kvm_assigned_irq {
__u32 assigned_dev_id;
__u32 host_irq;
@@ -600,9 +626,19 @@ struct kvm_assigned_irq {
};
};
-#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
-#define KVM_DEV_IRQ_ASSIGN_MSI_ACTION KVM_DEV_IRQ_ASSIGN_ENABLE_MSI
-#define KVM_DEV_IRQ_ASSIGN_ENABLE_MSI (1 << 0)
+struct kvm_assigned_msix_nr {
+ __u32 assigned_dev_id;
+ __u16 entry_nr;
+ __u16 padding;
+};
+
+#define KVM_MAX_MSIX_PER_DEV 512
+struct kvm_assigned_msix_entry {
+ __u32 assigned_dev_id;
+ __u32 gsi;
+ __u16 entry; /* The index of entry in the MSI-X table */
+ __u16 padding[3];
+};
#endif
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 894a56e365e8..2b8df0cadac7 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -38,6 +38,7 @@
#define KVM_REQ_UNHALT 6
#define KVM_REQ_MMU_SYNC 7
#define KVM_REQ_KVMCLOCK_UPDATE 8
+#define KVM_REQ_KICK 9
#define KVM_USERSPACE_IRQ_SOURCE_ID 0
@@ -72,7 +73,6 @@ struct kvm_vcpu {
struct mutex mutex;
int cpu;
struct kvm_run *run;
- int guest_mode;
unsigned long requests;
unsigned long guest_debug;
int fpu_active;
@@ -298,6 +298,7 @@ int kvm_arch_hardware_setup(void);
void kvm_arch_hardware_unsetup(void);
void kvm_arch_check_processor_compat(void *rtn);
int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu);
+int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu);
void kvm_free_physmem(struct kvm *kvm);
@@ -319,6 +320,13 @@ struct kvm_irq_ack_notifier {
void (*irq_acked)(struct kvm_irq_ack_notifier *kian);
};
+#define KVM_ASSIGNED_MSIX_PENDING 0x1
+struct kvm_guest_msix_entry {
+ u32 vector;
+ u16 entry;
+ u16 flags;
+};
+
struct kvm_assigned_dev_kernel {
struct kvm_irq_ack_notifier ack_notifier;
struct work_struct interrupt_work;
@@ -326,18 +334,18 @@ struct kvm_assigned_dev_kernel {
int assigned_dev_id;
int host_busnr;
int host_devfn;
+ unsigned int entries_nr;
int host_irq;
bool host_irq_disabled;
+ struct msix_entry *host_msix_entries;
int guest_irq;
-#define KVM_ASSIGNED_DEV_GUEST_INTX (1 << 0)
-#define KVM_ASSIGNED_DEV_GUEST_MSI (1 << 1)
-#define KVM_ASSIGNED_DEV_HOST_INTX (1 << 8)
-#define KVM_ASSIGNED_DEV_HOST_MSI (1 << 9)
+ struct kvm_guest_msix_entry *guest_msix_entries;
unsigned long irq_requested_type;
int irq_source_id;
int flags;
struct pci_dev *dev;
struct kvm *kvm;
+ spinlock_t assigned_dev_lock;
};
struct kvm_irq_mask_notifier {
@@ -352,6 +360,11 @@ void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq,
struct kvm_irq_mask_notifier *kimn);
void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, bool mask);
+#ifdef __KVM_HAVE_IOAPIC
+void kvm_get_intr_delivery_bitmask(struct kvm_ioapic *ioapic,
+ union kvm_ioapic_redirect_entry *entry,
+ unsigned long *deliver_bitmask);
+#endif
int kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level);
void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin);
void kvm_register_irq_ack_notifier(struct kvm *kvm,
diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
index 2b8318c83e53..fb46efbeabec 100644
--- a/include/linux/kvm_types.h
+++ b/include/linux/kvm_types.h
@@ -40,4 +40,31 @@ typedef unsigned long hfn_t;
typedef hfn_t pfn_t;
+union kvm_ioapic_redirect_entry {
+ u64 bits;
+ struct {
+ u8 vector;
+ u8 delivery_mode:3;
+ u8 dest_mode:1;
+ u8 delivery_status:1;
+ u8 polarity:1;
+ u8 remote_irr:1;
+ u8 trig_mode:1;
+ u8 mask:1;
+ u8 reserve:7;
+ u8 reserved[4];
+ u8 dest_id;
+ } fields;
+};
+
+struct kvm_lapic_irq {
+ u32 vector;
+ u32 delivery_mode;
+ u32 dest_mode;
+ u32 level;
+ u32 trig_mode;
+ u32 shorthand;
+ u32 dest_id;
+};
+
#endif /* __KVM_TYPES_H__ */
diff --git a/include/linux/libata.h b/include/linux/libata.h
index b450a2628855..3d501db36a26 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -209,6 +209,7 @@ enum {
/* bits 24:31 of ap->flags are reserved for LLD specific flags */
+
/* struct ata_port pflags */
ATA_PFLAG_EH_PENDING = (1 << 0), /* EH pending */
ATA_PFLAG_EH_IN_PROGRESS = (1 << 1), /* EH in progress */
@@ -225,6 +226,9 @@ enum {
ATA_PFLAG_PM_PENDING = (1 << 18), /* PM operation pending */
ATA_PFLAG_INIT_GTM_VALID = (1 << 19), /* initial gtm data valid */
+ ATA_PFLAG_PIO32 = (1 << 20), /* 32bit PIO */
+ ATA_PFLAG_PIO32CHANGE = (1 << 21), /* 32bit PIO can be turned on/off */
+
/* struct ata_queued_cmd flags */
ATA_QCFLAG_ACTIVE = (1 << 0), /* cmd not yet ack'd to scsi lyer */
ATA_QCFLAG_DMAMAP = (1 << 1), /* SG table is DMA mapped */
@@ -689,7 +693,10 @@ struct ata_port {
struct Scsi_Host *scsi_host; /* our co-allocated scsi host */
struct ata_port_operations *ops;
spinlock_t *lock;
+ /* Flags owned by the EH context. Only EH should touch these once the
+ port is active */
unsigned long flags; /* ATA_FLAG_xxx */
+ /* Flags that change dynamically, protected by ap->lock */
unsigned int pflags; /* ATA_PFLAG_xxx */
unsigned int print_id; /* user visible unique port ID */
unsigned int port_no; /* 0 based port no. inside the host */
@@ -1595,6 +1602,7 @@ extern void ata_sff_drain_fifo(struct ata_queued_cmd *qc);
extern void ata_sff_error_handler(struct ata_port *ap);
extern void ata_sff_post_internal_cmd(struct ata_queued_cmd *qc);
extern int ata_sff_port_start(struct ata_port *ap);
+extern int ata_sff_port_start32(struct ata_port *ap);
extern void ata_sff_std_ports(struct ata_ioports *ioaddr);
extern unsigned long ata_bmdma_mode_filter(struct ata_device *dev,
unsigned long xfer_mask);
diff --git a/include/linux/loop.h b/include/linux/loop.h
index 40725447f5e0..66c194e2d9b9 100644
--- a/include/linux/loop.h
+++ b/include/linux/loop.h
@@ -56,8 +56,7 @@ struct loop_device {
gfp_t old_gfp_mask;
spinlock_t lo_lock;
- struct bio *lo_bio;
- struct bio *lo_biotail;
+ struct bio_list lo_bio_list;
int lo_state;
struct mutex lo_ctl_mutex;
struct task_struct *lo_thread;
diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
new file mode 100644
index 000000000000..e461b2c3d711
--- /dev/null
+++ b/include/linux/lsm_audit.h
@@ -0,0 +1,111 @@
+/*
+ * Common LSM logging functions
+ * Heavily borrowed from selinux/avc.h
+ *
+ * Author : Etienne BASSET <etienne.basset@ensta.org>
+ *
+ * All credits to : Stephen Smalley, <sds@epoch.ncsc.mil>
+ * All BUGS to : Etienne BASSET <etienne.basset@ensta.org>
+ */
+#ifndef _LSM_COMMON_LOGGING_
+#define _LSM_COMMON_LOGGING_
+
+#include <linux/stddef.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/audit.h>
+#include <linux/in6.h>
+#include <linux/path.h>
+#include <linux/key.h>
+#include <linux/skbuff.h>
+#include <asm/system.h>
+
+
+/* Auxiliary data to use in generating the audit record. */
+struct common_audit_data {
+ char type;
+#define LSM_AUDIT_DATA_FS 1
+#define LSM_AUDIT_DATA_NET 2
+#define LSM_AUDIT_DATA_CAP 3
+#define LSM_AUDIT_DATA_IPC 4
+#define LSM_AUDIT_DATA_TASK 5
+#define LSM_AUDIT_DATA_KEY 6
+ struct task_struct *tsk;
+ union {
+ struct {
+ struct path path;
+ struct inode *inode;
+ } fs;
+ struct {
+ int netif;
+ struct sock *sk;
+ u16 family;
+ __be16 dport;
+ __be16 sport;
+ union {
+ struct {
+ __be32 daddr;
+ __be32 saddr;
+ } v4;
+ struct {
+ struct in6_addr daddr;
+ struct in6_addr saddr;
+ } v6;
+ } fam;
+ } net;
+ int cap;
+ int ipc_id;
+ struct task_struct *tsk;
+#ifdef CONFIG_KEYS
+ struct {
+ key_serial_t key;
+ char *key_desc;
+ } key_struct;
+#endif
+ } u;
+ const char *function;
+ /* this union contains LSM specific data */
+ union {
+ /* SMACK data */
+ struct smack_audit_data {
+ char *subject;
+ char *object;
+ char *request;
+ int result;
+ } smack_audit_data;
+ /* SELinux data */
+ struct {
+ u32 ssid;
+ u32 tsid;
+ u16 tclass;
+ u32 requested;
+ u32 audited;
+ struct av_decision *avd;
+ int result;
+ } selinux_audit_data;
+ } lsm_priv;
+ /* these callback will be implemented by a specific LSM */
+ void (*lsm_pre_audit)(struct audit_buffer *, void *);
+ void (*lsm_post_audit)(struct audit_buffer *, void *);
+};
+
+#define v4info fam.v4
+#define v6info fam.v6
+
+int ipv4_skb_to_auditdata(struct sk_buff *skb,
+ struct common_audit_data *ad, u8 *proto);
+
+int ipv6_skb_to_auditdata(struct sk_buff *skb,
+ struct common_audit_data *ad, u8 *proto);
+
+/* Initialize an LSM audit data structure. */
+#define COMMON_AUDIT_DATA_INIT(_d, _t) \
+ { memset((_d), 0, sizeof(struct common_audit_data)); \
+ (_d)->type = LSM_AUDIT_DATA_##_t; (_d)->function = __func__; }
+
+void common_lsm_audit(struct common_audit_data *a);
+
+#endif
diff --git a/include/linux/magic.h b/include/linux/magic.h
index 5b4e28bcb788..4596c9e25e09 100644
--- a/include/linux/magic.h
+++ b/include/linux/magic.h
@@ -3,10 +3,11 @@
#define ADFS_SUPER_MAGIC 0xadf5
#define AFFS_SUPER_MAGIC 0xadff
-#define AFS_SUPER_MAGIC 0x5346414F
+#define AFS_SUPER_MAGIC 0x5346414F
#define AUTOFS_SUPER_MAGIC 0x0187
#define CODA_SUPER_MAGIC 0x73757245
-#define DEBUGFS_MAGIC 0x64626720
+#define CUSE_SUPER_MAGIC 0x43555345
+#define DEBUGFS_MAGIC 0x64626720
#define SYSFS_MAGIC 0x62656572
#define SECURITYFS_MAGIC 0x73636673
#define TMPFS_MAGIC 0x01021994
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 18146c980b68..25b9ca93d232 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -56,7 +56,7 @@ extern void mem_cgroup_move_lists(struct page *page,
enum lru_list from, enum lru_list to);
extern void mem_cgroup_uncharge_page(struct page *page);
extern void mem_cgroup_uncharge_cache_page(struct page *page);
-extern int mem_cgroup_shrink_usage(struct page *page,
+extern int mem_cgroup_shmem_charge_fallback(struct page *page,
struct mm_struct *mm, gfp_t gfp_mask);
extern unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
@@ -75,7 +75,7 @@ int mm_match_cgroup(const struct mm_struct *mm, const struct mem_cgroup *cgroup)
{
struct mem_cgroup *mem;
rcu_read_lock();
- mem = mem_cgroup_from_task((mm)->owner);
+ mem = mem_cgroup_from_task(rcu_dereference((mm)->owner));
rcu_read_unlock();
return cgroup == mem;
}
@@ -155,7 +155,7 @@ static inline void mem_cgroup_uncharge_cache_page(struct page *page)
{
}
-static inline int mem_cgroup_shrink_usage(struct page *page,
+static inline int mem_cgroup_shmem_charge_fallback(struct page *page,
struct mm_struct *mm, gfp_t gfp_mask)
{
return 0;
diff --git a/include/linux/mg_disk.h b/include/linux/mg_disk.h
deleted file mode 100644
index 1f76b1ebf627..000000000000
--- a/include/linux/mg_disk.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * include/linux/mg_disk.c
- *
- * Support for the mGine m[g]flash IO mode.
- * Based on legacy hd.c
- *
- * (c) 2008 mGine Co.,LTD
- * (c) 2008 unsik Kim <donari75@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 __MG_DISK_H__
-#define __MG_DISK_H__
-
-#include <linux/blkdev.h>
-#include <linux/ata.h>
-
-/* name for block device */
-#define MG_DISK_NAME "mgd"
-/* name for platform device */
-#define MG_DEV_NAME "mg_disk"
-
-#define MG_DISK_MAJ 0
-#define MG_DISK_MAX_PART 16
-#define MG_SECTOR_SIZE 512
-#define MG_MAX_SECTS 256
-
-/* Register offsets */
-#define MG_BUFF_OFFSET 0x8000
-#define MG_STORAGE_BUFFER_SIZE 0x200
-#define MG_REG_OFFSET 0xC000
-#define MG_REG_FEATURE (MG_REG_OFFSET + 2) /* write case */
-#define MG_REG_ERROR (MG_REG_OFFSET + 2) /* read case */
-#define MG_REG_SECT_CNT (MG_REG_OFFSET + 4)
-#define MG_REG_SECT_NUM (MG_REG_OFFSET + 6)
-#define MG_REG_CYL_LOW (MG_REG_OFFSET + 8)
-#define MG_REG_CYL_HIGH (MG_REG_OFFSET + 0xA)
-#define MG_REG_DRV_HEAD (MG_REG_OFFSET + 0xC)
-#define MG_REG_COMMAND (MG_REG_OFFSET + 0xE) /* write case */
-#define MG_REG_STATUS (MG_REG_OFFSET + 0xE) /* read case */
-#define MG_REG_DRV_CTRL (MG_REG_OFFSET + 0x10)
-#define MG_REG_BURST_CTRL (MG_REG_OFFSET + 0x12)
-
-/* "Drive Select/Head Register" bit values */
-#define MG_REG_HEAD_MUST_BE_ON 0xA0 /* These 2 bits are always on */
-#define MG_REG_HEAD_DRIVE_MASTER (0x00 | MG_REG_HEAD_MUST_BE_ON)
-#define MG_REG_HEAD_DRIVE_SLAVE (0x10 | MG_REG_HEAD_MUST_BE_ON)
-#define MG_REG_HEAD_LBA_MODE (0x40 | MG_REG_HEAD_MUST_BE_ON)
-
-
-/* "Device Control Register" bit values */
-#define MG_REG_CTRL_INTR_ENABLE 0x0
-#define MG_REG_CTRL_INTR_DISABLE (0x1<<1)
-#define MG_REG_CTRL_RESET (0x1<<2)
-#define MG_REG_CTRL_INTR_POLA_ACTIVE_HIGH 0x0
-#define MG_REG_CTRL_INTR_POLA_ACTIVE_LOW (0x1<<4)
-#define MG_REG_CTRL_DPD_POLA_ACTIVE_LOW 0x0
-#define MG_REG_CTRL_DPD_POLA_ACTIVE_HIGH (0x1<<5)
-#define MG_REG_CTRL_DPD_DISABLE 0x0
-#define MG_REG_CTRL_DPD_ENABLE (0x1<<6)
-
-/* Status register bit */
-/* error bit in status register */
-#define MG_REG_STATUS_BIT_ERROR 0x01
-/* corrected error in status register */
-#define MG_REG_STATUS_BIT_CORRECTED_ERROR 0x04
-/* data request bit in status register */
-#define MG_REG_STATUS_BIT_DATA_REQ 0x08
-/* DSC - Drive Seek Complete */
-#define MG_REG_STATUS_BIT_SEEK_DONE 0x10
-/* DWF - Drive Write Fault */
-#define MG_REG_STATUS_BIT_WRITE_FAULT 0x20
-#define MG_REG_STATUS_BIT_READY 0x40
-#define MG_REG_STATUS_BIT_BUSY 0x80
-
-/* handy status */
-#define MG_STAT_READY (MG_REG_STATUS_BIT_READY | MG_REG_STATUS_BIT_SEEK_DONE)
-#define MG_READY_OK(s) (((s) & (MG_STAT_READY | \
- (MG_REG_STATUS_BIT_BUSY | \
- MG_REG_STATUS_BIT_WRITE_FAULT | \
- MG_REG_STATUS_BIT_ERROR))) == MG_STAT_READY)
-
-/* Error register */
-#define MG_REG_ERR_AMNF 0x01
-#define MG_REG_ERR_ABRT 0x04
-#define MG_REG_ERR_IDNF 0x10
-#define MG_REG_ERR_UNC 0x40
-#define MG_REG_ERR_BBK 0x80
-
-/* error code for others */
-#define MG_ERR_NONE 0
-#define MG_ERR_TIMEOUT 0x100
-#define MG_ERR_INIT_STAT 0x101
-#define MG_ERR_TRANSLATION 0x102
-#define MG_ERR_CTRL_RST 0x103
-#define MG_ERR_INV_STAT 0x104
-#define MG_ERR_RSTOUT 0x105
-
-#define MG_MAX_ERRORS 6 /* Max read/write errors */
-
-/* command */
-#define MG_CMD_RD 0x20
-#define MG_CMD_WR 0x30
-#define MG_CMD_SLEEP 0x99
-#define MG_CMD_WAKEUP 0xC3
-#define MG_CMD_ID 0xEC
-#define MG_CMD_WR_CONF 0x3C
-#define MG_CMD_RD_CONF 0x40
-
-/* operation mode */
-#define MG_OP_CASCADE (1 << 0)
-#define MG_OP_CASCADE_SYNC_RD (1 << 1)
-#define MG_OP_CASCADE_SYNC_WR (1 << 2)
-#define MG_OP_INTERLEAVE (1 << 3)
-
-/* synchronous */
-#define MG_BURST_LAT_4 (3 << 4)
-#define MG_BURST_LAT_5 (4 << 4)
-#define MG_BURST_LAT_6 (5 << 4)
-#define MG_BURST_LAT_7 (6 << 4)
-#define MG_BURST_LAT_8 (7 << 4)
-#define MG_BURST_LEN_4 (1 << 1)
-#define MG_BURST_LEN_8 (2 << 1)
-#define MG_BURST_LEN_16 (3 << 1)
-#define MG_BURST_LEN_32 (4 << 1)
-#define MG_BURST_LEN_CONT (0 << 1)
-
-/* timeout value (unit: ms) */
-#define MG_TMAX_CONF_TO_CMD 1
-#define MG_TMAX_WAIT_RD_DRQ 10
-#define MG_TMAX_WAIT_WR_DRQ 500
-#define MG_TMAX_RST_TO_BUSY 10
-#define MG_TMAX_HDRST_TO_RDY 500
-#define MG_TMAX_SWRST_TO_RDY 500
-#define MG_TMAX_RSTOUT 3000
-
-/* device attribution */
-/* use mflash as boot device */
-#define MG_BOOT_DEV (1 << 0)
-/* use mflash as storage device */
-#define MG_STORAGE_DEV (1 << 1)
-/* same as MG_STORAGE_DEV, but bootloader already done reset sequence */
-#define MG_STORAGE_DEV_SKIP_RST (1 << 2)
-
-#define MG_DEV_MASK (MG_BOOT_DEV | MG_STORAGE_DEV | MG_STORAGE_DEV_SKIP_RST)
-
-/* names of GPIO resource */
-#define MG_RST_PIN "mg_rst"
-/* except MG_BOOT_DEV, reset-out pin should be assigned */
-#define MG_RSTOUT_PIN "mg_rstout"
-
-/* private driver data */
-struct mg_drv_data {
- /* disk resource */
- u32 use_polling;
-
- /* device attribution */
- u32 dev_attr;
-
- /* internally used */
- struct mg_host *host;
-};
-
-/* main structure for mflash driver */
-struct mg_host {
- struct device *dev;
-
- struct request_queue *breq;
- spinlock_t lock;
- struct gendisk *gd;
-
- struct timer_list timer;
- void (*mg_do_intr) (struct mg_host *);
-
- u16 id[ATA_ID_WORDS];
-
- u16 cyls;
- u16 heads;
- u16 sectors;
- u32 n_sectors;
- u32 nres_sectors;
-
- void __iomem *dev_base;
- unsigned int irq;
- unsigned int rst;
- unsigned int rstout;
-
- u32 major;
- u32 error;
-};
-
-/*
- * Debugging macro and defines
- */
-#undef DO_MG_DEBUG
-#ifdef DO_MG_DEBUG
-# define MG_DBG(fmt, args...) \
- printk(KERN_DEBUG "%s:%d "fmt, __func__, __LINE__, ##args)
-#else /* CONFIG_MG_DEBUG */
-# define MG_DBG(fmt, args...) do { } while (0)
-#endif /* CONFIG_MG_DEBUG */
-
-#endif
diff --git a/include/linux/mm.h b/include/linux/mm.h
index bff1f0d475c7..009eabd3c21c 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -19,6 +19,7 @@ struct anon_vma;
struct file_ra_state;
struct user_struct;
struct writeback_control;
+struct rlimit;
#ifndef CONFIG_DISCONTIGMEM /* Don't use mapnrs, do it properly */
extern unsigned long max_mapnr;
@@ -1319,8 +1320,8 @@ int vmemmap_populate_basepages(struct page *start_page,
int vmemmap_populate(struct page *start_page, unsigned long pages, int node);
void vmemmap_populate_print_last(void);
-extern void *alloc_locked_buffer(size_t size);
-extern void free_locked_buffer(void *buffer, size_t size);
-extern void release_locked_buffer(void *buffer, size_t size);
+extern int account_locked_memory(struct mm_struct *mm, struct rlimit *rlim,
+ size_t size);
+extern void refund_locked_memory(struct mm_struct *mm, size_t size);
#endif /* __KERNEL__ */
#endif /* _LINUX_MM_H */
diff --git a/include/linux/mman.h b/include/linux/mman.h
index 30d1073bac3b..9872d6ca58ae 100644
--- a/include/linux/mman.h
+++ b/include/linux/mman.h
@@ -12,21 +12,18 @@
#ifdef __KERNEL__
#include <linux/mm.h>
+#include <linux/percpu_counter.h>
#include <asm/atomic.h>
extern int sysctl_overcommit_memory;
extern int sysctl_overcommit_ratio;
-extern atomic_long_t vm_committed_space;
+extern struct percpu_counter vm_committed_as;
-#ifdef CONFIG_SMP
-extern void vm_acct_memory(long pages);
-#else
static inline void vm_acct_memory(long pages)
{
- atomic_long_add(pages, &vm_committed_space);
+ percpu_counter_add(&vm_committed_as, pages);
}
-#endif
static inline void vm_unacct_memory(long pages)
{
diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h
index c7211ab6dd4b..b2c73cdabd05 100644
--- a/include/linux/mmc/sdio_ids.h
+++ b/include/linux/mmc/sdio_ids.h
@@ -24,8 +24,16 @@
*/
#define SDIO_VENDOR_ID_MARVELL 0x02df
+#define SDIO_VENDOR_ID_SIANO 0x039a
+
#define SDIO_DEVICE_ID_MARVELL_LIBERTAS 0x9103
#define SDIO_DEVICE_ID_MARVELL_8688WLAN 0x9104
#define SDIO_DEVICE_ID_MARVELL_8688BT 0x9105
+#define SDIO_DEVICE_ID_SIANO_STELLAR 0x5347
+#define SDIO_DEVICE_ID_SIANO_NOVA_A0 0x1100
+#define SDIO_DEVICE_ID_SIANO_NOVA_B0 0x0201
+#define SDIO_DEVICE_ID_SIANO_NICE 0x0202
+#define SDIO_DEVICE_ID_SIANO_VEGA_A0 0x0300
+#define SDIO_DEVICE_ID_SIANO_VENICE 0x0301
#endif
diff --git a/include/linux/mmiotrace.h b/include/linux/mmiotrace.h
index 3d1b7bde1283..97491f78b08c 100644
--- a/include/linux/mmiotrace.h
+++ b/include/linux/mmiotrace.h
@@ -30,6 +30,8 @@ extern unsigned int kmmio_count;
extern int register_kmmio_probe(struct kmmio_probe *p);
extern void unregister_kmmio_probe(struct kmmio_probe *p);
+extern int kmmio_init(void);
+extern void kmmio_cleanup(void);
#ifdef CONFIG_MMIOTRACE
/* kmmio is active by some kmmio_probes? */
diff --git a/include/linux/module.h b/include/linux/module.h
index 627ac082e2a6..a8f2c0aa4c32 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -337,6 +337,14 @@ struct module
const char **trace_bprintk_fmt_start;
unsigned int num_trace_bprintk_fmt;
#endif
+#ifdef CONFIG_EVENT_TRACING
+ struct ftrace_event_call *trace_events;
+ unsigned int num_trace_events;
+#endif
+#ifdef CONFIG_FTRACE_MCOUNT_RECORD
+ unsigned long *ftrace_callsites;
+ unsigned int num_ftrace_callsites;
+#endif
#ifdef CONFIG_MODULE_UNLOAD
/* What modules depend on me? */
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index a4f0b931846c..6547c3cdbc4c 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -36,9 +36,14 @@ typedef int (*param_set_fn)(const char *val, struct kernel_param *kp);
/* Returns length written or -errno. Buffer is 4k (ie. be short!) */
typedef int (*param_get_fn)(char *buffer, struct kernel_param *kp);
+/* Flag bits for kernel_param.flags */
+#define KPARAM_KMALLOCED 1
+#define KPARAM_ISBOOL 2
+
struct kernel_param {
const char *name;
- unsigned int perm;
+ u16 perm;
+ u16 flags;
param_set_fn set;
param_get_fn get;
union {
@@ -79,7 +84,7 @@ struct kparam_array
parameters. perm sets the visibility in sysfs: 000 means it's
not there, read bits mean it's readable, write bits mean it's
writable. */
-#define __module_param_call(prefix, name, set, get, arg, perm) \
+#define __module_param_call(prefix, name, set, get, arg, isbool, perm) \
/* Default value instead of permissions? */ \
static int __param_perm_check_##name __attribute__((unused)) = \
BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)) \
@@ -88,10 +93,13 @@ struct kparam_array
static struct kernel_param __moduleparam_const __param_##name \
__used \
__attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \
- = { __param_str_##name, perm, set, get, { arg } }
+ = { __param_str_##name, perm, isbool ? KPARAM_ISBOOL : 0, \
+ set, get, { arg } }
#define module_param_call(name, set, get, arg, perm) \
- __module_param_call(MODULE_PARAM_PREFIX, name, set, get, arg, perm)
+ __module_param_call(MODULE_PARAM_PREFIX, \
+ name, set, get, arg, \
+ __same_type(*(arg), bool), perm)
/* Helper functions: type is byte, short, ushort, int, uint, long,
ulong, charp, bool or invbool, or XXX if you define param_get_XXX,
@@ -120,15 +128,16 @@ struct kparam_array
#define core_param(name, var, type, perm) \
param_check_##type(name, &(var)); \
__module_param_call("", name, param_set_##type, param_get_##type, \
- &var, perm)
+ &var, __same_type(var, bool), perm)
#endif /* !MODULE */
/* Actually copy string: maxlen param is usually sizeof(string). */
#define module_param_string(name, string, len, perm) \
static const struct kparam_string __param_string_##name \
= { len, string }; \
- module_param_call(name, param_set_copystring, param_get_string, \
- .str = &__param_string_##name, perm); \
+ __module_param_call(MODULE_PARAM_PREFIX, name, \
+ param_set_copystring, param_get_string, \
+ .str = &__param_string_##name, 0, perm); \
__MODULE_PARM_TYPE(name, "string")
/* Called on module insert or kernel boot */
@@ -186,21 +195,30 @@ extern int param_set_charp(const char *val, struct kernel_param *kp);
extern int param_get_charp(char *buffer, struct kernel_param *kp);
#define param_check_charp(name, p) __param_check(name, p, char *)
+/* For historical reasons "bool" parameters can be (unsigned) "int". */
extern int param_set_bool(const char *val, struct kernel_param *kp);
extern int param_get_bool(char *buffer, struct kernel_param *kp);
-#define param_check_bool(name, p) __param_check(name, p, int)
+#define param_check_bool(name, p) \
+ static inline void __check_##name(void) \
+ { \
+ BUILD_BUG_ON(!__same_type(*(p), bool) && \
+ !__same_type(*(p), unsigned int) && \
+ !__same_type(*(p), int)); \
+ }
extern int param_set_invbool(const char *val, struct kernel_param *kp);
extern int param_get_invbool(char *buffer, struct kernel_param *kp);
-#define param_check_invbool(name, p) __param_check(name, p, int)
+#define param_check_invbool(name, p) __param_check(name, p, bool)
/* Comma-separated array: *nump is set to number they actually specified. */
#define module_param_array_named(name, array, type, nump, perm) \
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, \
- .arr = &__param_arr_##name, perm); \
+ __module_param_call(MODULE_PARAM_PREFIX, name, \
+ param_array_set, param_array_get, \
+ .arr = &__param_arr_##name, \
+ __same_type(array[0], bool), perm); \
__MODULE_PARM_TYPE(name, "array of " #type)
#define module_param_array(name, type, nump, perm) \
diff --git a/include/linux/mount.h b/include/linux/mount.h
index 51f55f903aff..5d5275364867 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -30,7 +30,7 @@ struct mnt_namespace;
#define MNT_STRICTATIME 0x80
#define MNT_SHRINKABLE 0x100
-#define MNT_IMBALANCED_WRITE_COUNT 0x200 /* just for debugging */
+#define MNT_WRITE_HOLD 0x200
#define MNT_SHARED 0x1000 /* if the vfsmount is a shared mount */
#define MNT_UNBINDABLE 0x2000 /* if the vfsmount is a unbindable mount */
@@ -65,13 +65,22 @@ struct vfsmount {
int mnt_expiry_mark; /* true if marked for expiry */
int mnt_pinned;
int mnt_ghosts;
- /*
- * This value is not stable unless all of the mnt_writers[] spinlocks
- * are held, and all mnt_writer[]s on this mount have 0 as their ->count
- */
- atomic_t __mnt_writers;
+#ifdef CONFIG_SMP
+ int *mnt_writers;
+#else
+ int mnt_writers;
+#endif
};
+static inline int *get_mnt_writers_ptr(struct vfsmount *mnt)
+{
+#ifdef CONFIG_SMP
+ return mnt->mnt_writers;
+#else
+ return &mnt->mnt_writers;
+#endif
+}
+
static inline struct vfsmount *mntget(struct vfsmount *mnt)
{
if (mnt)
@@ -79,7 +88,11 @@ static inline struct vfsmount *mntget(struct vfsmount *mnt)
return mnt;
}
+struct file; /* forward dec */
+
extern int mnt_want_write(struct vfsmount *mnt);
+extern int mnt_want_write_file(struct file *file);
+extern int mnt_clone_write(struct vfsmount *mnt);
extern void mnt_drop_write(struct vfsmount *mnt);
extern void mntput_no_expire(struct vfsmount *mnt);
extern void mnt_pin(struct vfsmount *mnt);
diff --git a/include/linux/mutex.h b/include/linux/mutex.h
index 3069ec7e0ab8..878cab4f5fcc 100644
--- a/include/linux/mutex.h
+++ b/include/linux/mutex.h
@@ -150,5 +150,6 @@ extern int __must_check mutex_lock_killable(struct mutex *lock);
*/
extern int mutex_trylock(struct mutex *lock);
extern void mutex_unlock(struct mutex *lock);
+extern int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock);
#endif
diff --git a/include/linux/namei.h b/include/linux/namei.h
index fc2e03579877..d870ae2faedc 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -18,6 +18,7 @@ enum { MAX_NESTED_LINKS = 8 };
struct nameidata {
struct path path;
struct qstr last;
+ struct path root;
unsigned int flags;
int last_type;
unsigned depth;
@@ -69,7 +70,6 @@ extern int path_lookup(const char *, unsigned, struct nameidata *);
extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
const char *, unsigned int, struct nameidata *);
-extern int path_lookup_open(int dfd, const char *name, unsigned lookup_flags, struct nameidata *, int open_flags);
extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
int (*open)(struct inode *, struct file *));
extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
@@ -78,8 +78,8 @@ extern void release_open_intent(struct nameidata *);
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 **);
+extern int follow_down(struct path *);
+extern int follow_up(struct path *);
extern struct dentry *lock_rename(struct dentry *, struct dentry *);
extern void unlock_rename(struct dentry *, struct dentry *);
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index e3f0cbcbd0db..bd2eba530667 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -21,6 +21,7 @@
#define NFS4_FHSIZE 128
#define NFS4_MAXPATHLEN PATH_MAX
#define NFS4_MAXNAMLEN NAME_MAX
+#define NFS4_OPAQUE_LIMIT 1024
#define NFS4_MAX_SESSIONID_LEN 16
#define NFS4_ACCESS_READ 0x0001
@@ -130,6 +131,16 @@
#define NFS4_MAX_UINT64 (~(u64)0)
+/* An NFS4 sessions server must support at least NFS4_MAX_OPS operations.
+ * If a compound requires more operations, adjust NFS4_MAX_OPS accordingly.
+ */
+#define NFS4_MAX_OPS 8
+
+/* Our NFS4 client back channel server only wants the cb_sequene and the
+ * actual operation per compound
+ */
+#define NFS4_MAX_BACK_CHANNEL_OPS 2
+
enum nfs4_acl_whotype {
NFS4_ACL_WHO_NAMED = 0,
NFS4_ACL_WHO_OWNER,
@@ -462,6 +473,13 @@ enum lock_type4 {
#define NFSPROC4_NULL 0
#define NFSPROC4_COMPOUND 1
#define NFS4_MINOR_VERSION 0
+
+#if defined(CONFIG_NFS_V4_1)
+#define NFS4_MAX_MINOR_VERSION 1
+#else
+#define NFS4_MAX_MINOR_VERSION 0
+#endif /* CONFIG_NFS_V4_1 */
+
#define NFS4_DEBUG 1
/* Index of predefined Linux client operations */
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 6ad75948cbf7..d0902ccec9ce 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -4,11 +4,17 @@
#include <linux/list.h>
#include <linux/backing-dev.h>
#include <linux/wait.h>
+#include <linux/nfs_xdr.h>
+#include <linux/sunrpc/xprt.h>
#include <asm/atomic.h>
+struct nfs4_session;
struct nfs_iostats;
struct nlm_host;
+struct nfs4_sequence_args;
+struct nfs4_sequence_res;
+struct nfs_server;
/*
* The nfs_client identifies our client state to the server.
@@ -18,6 +24,7 @@ struct nfs_client {
int cl_cons_state; /* current construction state (-ve: init error) */
#define NFS_CS_READY 0 /* ready to be used */
#define NFS_CS_INITING 1 /* busy initialising */
+#define NFS_CS_SESSION_INITING 2 /* busy initialising session */
unsigned long cl_res_state; /* NFS resources state */
#define NFS_CS_CALLBACK 1 /* - callback started */
#define NFS_CS_IDMAP 2 /* - idmap started */
@@ -32,6 +39,7 @@ struct nfs_client {
const struct nfs_rpc_ops *rpc_ops; /* NFS protocol vector */
int cl_proto; /* Network transport protocol */
+ u32 cl_minorversion;/* NFSv4 minorversion */
struct rpc_cred *cl_machine_cred;
#ifdef CONFIG_NFS_V4
@@ -63,7 +71,22 @@ struct nfs_client {
*/
char cl_ipaddr[48];
unsigned char cl_id_uniquifier;
-#endif
+ int (* cl_call_sync)(struct nfs_server *server,
+ struct rpc_message *msg,
+ struct nfs4_sequence_args *args,
+ struct nfs4_sequence_res *res,
+ int cache_reply);
+#endif /* CONFIG_NFS_V4 */
+
+#ifdef CONFIG_NFS_V4_1
+ /* clientid returned from EXCHANGE_ID, used by session operations */
+ u64 cl_ex_clid;
+ /* The sequence id to use for the next CREATE_SESSION */
+ u32 cl_seqid;
+ /* The flags used for obtaining the clientid during EXCHANGE_ID */
+ u32 cl_exchange_flags;
+ struct nfs4_session *cl_session; /* sharred session */
+#endif /* CONFIG_NFS_V4_1 */
#ifdef CONFIG_NFS_FSCACHE
struct fscache_cookie *fscache; /* client index cache cookie */
@@ -145,4 +168,46 @@ struct nfs_server {
#define NFS_CAP_ACLS (1U << 3)
#define NFS_CAP_ATOMIC_OPEN (1U << 4)
+
+/* maximum number of slots to use */
+#define NFS4_MAX_SLOT_TABLE RPC_MAX_SLOT_TABLE
+
+#if defined(CONFIG_NFS_V4_1)
+
+/* Sessions */
+#define SLOT_TABLE_SZ (NFS4_MAX_SLOT_TABLE/(8*sizeof(long)))
+struct nfs4_slot_table {
+ struct nfs4_slot *slots; /* seqid per slot */
+ unsigned long used_slots[SLOT_TABLE_SZ]; /* used/unused bitmap */
+ spinlock_t slot_tbl_lock;
+ struct rpc_wait_queue slot_tbl_waitq; /* allocators may wait here */
+ int max_slots; /* # slots in table */
+ int highest_used_slotid; /* sent to server on each SEQ.
+ * op for dynamic resizing */
+};
+
+static inline int slot_idx(struct nfs4_slot_table *tbl, struct nfs4_slot *sp)
+{
+ return sp - tbl->slots;
+}
+
+/*
+ * Session related parameters
+ */
+struct nfs4_session {
+ struct nfs4_sessionid sess_id;
+ u32 flags;
+ unsigned long session_state;
+ u32 hash_alg;
+ u32 ssv_len;
+
+ /* The fore and back channel */
+ struct nfs4_channel_attrs fc_attrs;
+ struct nfs4_slot_table fc_slot_table;
+ struct nfs4_channel_attrs bc_attrs;
+ /* back channel has one slot */
+ struct nfs_client *clp;
+};
+
+#endif /* CONFIG_NFS_V4_1 */
#endif
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index b89c34e40bc2..071a6d10ae13 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -145,6 +145,44 @@ struct nfs4_change_info {
};
struct nfs_seqid;
+
+/* nfs41 sessions channel attributes */
+struct nfs4_channel_attrs {
+ u32 headerpadsz;
+ u32 max_rqst_sz;
+ u32 max_resp_sz;
+ u32 max_resp_sz_cached;
+ u32 max_ops;
+ u32 max_reqs;
+};
+
+/* nfs41 sessions slot seqid */
+struct nfs4_slot {
+ u32 seq_nr;
+};
+
+struct nfs4_sequence_args {
+ struct nfs4_session *sa_session;
+ u8 sa_slotid;
+ u8 sa_cache_this;
+};
+
+struct nfs4_sequence_res {
+ struct nfs4_session *sr_session;
+ u8 sr_slotid; /* slot used to send request */
+ unsigned long sr_renewal_time;
+ int sr_status; /* sequence operation status */
+};
+
+struct nfs4_get_lease_time_args {
+ struct nfs4_sequence_args la_seq_args;
+};
+
+struct nfs4_get_lease_time_res {
+ struct nfs_fsinfo *lr_fsinfo;
+ struct nfs4_sequence_res lr_seq_res;
+};
+
/*
* Arguments to the open call.
*/
@@ -165,6 +203,7 @@ struct nfs_openargs {
const struct nfs_server *server; /* Needed for ID mapping */
const u32 * bitmask;
__u32 claim;
+ struct nfs4_sequence_args seq_args;
};
struct nfs_openres {
@@ -181,6 +220,7 @@ struct nfs_openres {
__u32 do_recall;
__u64 maxsize;
__u32 attrset[NFS4_BITMAP_SIZE];
+ struct nfs4_sequence_res seq_res;
};
/*
@@ -206,6 +246,7 @@ struct nfs_closeargs {
struct nfs_seqid * seqid;
fmode_t fmode;
const u32 * bitmask;
+ struct nfs4_sequence_args seq_args;
};
struct nfs_closeres {
@@ -213,6 +254,7 @@ struct nfs_closeres {
struct nfs_fattr * fattr;
struct nfs_seqid * seqid;
const struct nfs_server *server;
+ struct nfs4_sequence_res seq_res;
};
/*
* * Arguments to the lock,lockt, and locku call.
@@ -233,12 +275,14 @@ struct nfs_lock_args {
unsigned char block : 1;
unsigned char reclaim : 1;
unsigned char new_lock_owner : 1;
+ struct nfs4_sequence_args seq_args;
};
struct nfs_lock_res {
nfs4_stateid stateid;
struct nfs_seqid * lock_seqid;
struct nfs_seqid * open_seqid;
+ struct nfs4_sequence_res seq_res;
};
struct nfs_locku_args {
@@ -246,32 +290,38 @@ struct nfs_locku_args {
struct file_lock * fl;
struct nfs_seqid * seqid;
nfs4_stateid * stateid;
+ struct nfs4_sequence_args seq_args;
};
struct nfs_locku_res {
nfs4_stateid stateid;
struct nfs_seqid * seqid;
+ struct nfs4_sequence_res seq_res;
};
struct nfs_lockt_args {
struct nfs_fh * fh;
struct file_lock * fl;
struct nfs_lowner lock_owner;
+ struct nfs4_sequence_args seq_args;
};
struct nfs_lockt_res {
struct file_lock * denied; /* LOCK, LOCKT failed */
+ struct nfs4_sequence_res seq_res;
};
struct nfs4_delegreturnargs {
const struct nfs_fh *fhandle;
const nfs4_stateid *stateid;
const u32 * bitmask;
+ struct nfs4_sequence_args seq_args;
};
struct nfs4_delegreturnres {
struct nfs_fattr * fattr;
const struct nfs_server *server;
+ struct nfs4_sequence_res seq_res;
};
/*
@@ -284,12 +334,14 @@ struct nfs_readargs {
__u32 count;
unsigned int pgbase;
struct page ** pages;
+ struct nfs4_sequence_args seq_args;
};
struct nfs_readres {
struct nfs_fattr * fattr;
__u32 count;
int eof;
+ struct nfs4_sequence_res seq_res;
};
/*
@@ -304,6 +356,7 @@ struct nfs_writeargs {
unsigned int pgbase;
struct page ** pages;
const u32 * bitmask;
+ struct nfs4_sequence_args seq_args;
};
struct nfs_writeverf {
@@ -316,6 +369,7 @@ struct nfs_writeres {
struct nfs_writeverf * verf;
__u32 count;
const struct nfs_server *server;
+ struct nfs4_sequence_res seq_res;
};
/*
@@ -325,12 +379,14 @@ struct nfs_removeargs {
const struct nfs_fh *fh;
struct qstr name;
const u32 * bitmask;
+ struct nfs4_sequence_args seq_args;
};
struct nfs_removeres {
const struct nfs_server *server;
struct nfs4_change_info cinfo;
struct nfs_fattr dir_attr;
+ struct nfs4_sequence_res seq_res;
};
/*
@@ -383,6 +439,7 @@ struct nfs_setattrargs {
struct iattr * iap;
const struct nfs_server * server; /* Needed for name mapping */
const u32 * bitmask;
+ struct nfs4_sequence_args seq_args;
};
struct nfs_setaclargs {
@@ -390,6 +447,11 @@ struct nfs_setaclargs {
size_t acl_len;
unsigned int acl_pgbase;
struct page ** acl_pages;
+ struct nfs4_sequence_args seq_args;
+};
+
+struct nfs_setaclres {
+ struct nfs4_sequence_res seq_res;
};
struct nfs_getaclargs {
@@ -397,11 +459,18 @@ struct nfs_getaclargs {
size_t acl_len;
unsigned int acl_pgbase;
struct page ** acl_pages;
+ struct nfs4_sequence_args seq_args;
+};
+
+struct nfs_getaclres {
+ size_t acl_len;
+ struct nfs4_sequence_res seq_res;
};
struct nfs_setattrres {
struct nfs_fattr * fattr;
const struct nfs_server * server;
+ struct nfs4_sequence_res seq_res;
};
struct nfs_linkargs {
@@ -583,6 +652,7 @@ struct nfs4_accessargs {
const struct nfs_fh * fh;
const u32 * bitmask;
u32 access;
+ struct nfs4_sequence_args seq_args;
};
struct nfs4_accessres {
@@ -590,6 +660,7 @@ struct nfs4_accessres {
struct nfs_fattr * fattr;
u32 supported;
u32 access;
+ struct nfs4_sequence_res seq_res;
};
struct nfs4_create_arg {
@@ -609,6 +680,7 @@ struct nfs4_create_arg {
const struct iattr * attrs;
const struct nfs_fh * dir_fh;
const u32 * bitmask;
+ struct nfs4_sequence_args seq_args;
};
struct nfs4_create_res {
@@ -617,21 +689,30 @@ struct nfs4_create_res {
struct nfs_fattr * fattr;
struct nfs4_change_info dir_cinfo;
struct nfs_fattr * dir_fattr;
+ struct nfs4_sequence_res seq_res;
};
struct nfs4_fsinfo_arg {
const struct nfs_fh * fh;
const u32 * bitmask;
+ struct nfs4_sequence_args seq_args;
+};
+
+struct nfs4_fsinfo_res {
+ struct nfs_fsinfo *fsinfo;
+ struct nfs4_sequence_res seq_res;
};
struct nfs4_getattr_arg {
const struct nfs_fh * fh;
const u32 * bitmask;
+ struct nfs4_sequence_args seq_args;
};
struct nfs4_getattr_res {
const struct nfs_server * server;
struct nfs_fattr * fattr;
+ struct nfs4_sequence_res seq_res;
};
struct nfs4_link_arg {
@@ -639,6 +720,7 @@ struct nfs4_link_arg {
const struct nfs_fh * dir_fh;
const struct qstr * name;
const u32 * bitmask;
+ struct nfs4_sequence_args seq_args;
};
struct nfs4_link_res {
@@ -646,6 +728,7 @@ struct nfs4_link_res {
struct nfs_fattr * fattr;
struct nfs4_change_info cinfo;
struct nfs_fattr * dir_attr;
+ struct nfs4_sequence_res seq_res;
};
@@ -653,21 +736,30 @@ struct nfs4_lookup_arg {
const struct nfs_fh * dir_fh;
const struct qstr * name;
const u32 * bitmask;
+ struct nfs4_sequence_args seq_args;
};
struct nfs4_lookup_res {
const struct nfs_server * server;
struct nfs_fattr * fattr;
struct nfs_fh * fh;
+ struct nfs4_sequence_res seq_res;
};
struct nfs4_lookup_root_arg {
const u32 * bitmask;
+ struct nfs4_sequence_args seq_args;
};
struct nfs4_pathconf_arg {
const struct nfs_fh * fh;
const u32 * bitmask;
+ struct nfs4_sequence_args seq_args;
+};
+
+struct nfs4_pathconf_res {
+ struct nfs_pathconf *pathconf;
+ struct nfs4_sequence_res seq_res;
};
struct nfs4_readdir_arg {
@@ -678,11 +770,13 @@ struct nfs4_readdir_arg {
struct page ** pages; /* zero-copy data */
unsigned int pgbase; /* zero-copy data */
const u32 * bitmask;
+ struct nfs4_sequence_args seq_args;
};
struct nfs4_readdir_res {
nfs4_verifier verifier;
unsigned int pgbase;
+ struct nfs4_sequence_res seq_res;
};
struct nfs4_readlink {
@@ -690,6 +784,11 @@ struct nfs4_readlink {
unsigned int pgbase;
unsigned int pglen; /* zero-copy data */
struct page ** pages; /* zero-copy data */
+ struct nfs4_sequence_args seq_args;
+};
+
+struct nfs4_readlink_res {
+ struct nfs4_sequence_res seq_res;
};
struct nfs4_rename_arg {
@@ -698,6 +797,7 @@ struct nfs4_rename_arg {
const struct qstr * old_name;
const struct qstr * new_name;
const u32 * bitmask;
+ struct nfs4_sequence_args seq_args;
};
struct nfs4_rename_res {
@@ -706,6 +806,7 @@ struct nfs4_rename_res {
struct nfs_fattr * old_fattr;
struct nfs4_change_info new_cinfo;
struct nfs_fattr * new_fattr;
+ struct nfs4_sequence_res seq_res;
};
#define NFS4_SETCLIENTID_NAMELEN (127)
@@ -724,6 +825,17 @@ struct nfs4_setclientid {
struct nfs4_statfs_arg {
const struct nfs_fh * fh;
const u32 * bitmask;
+ struct nfs4_sequence_args seq_args;
+};
+
+struct nfs4_statfs_res {
+ struct nfs_fsstat *fsstat;
+ struct nfs4_sequence_res seq_res;
+};
+
+struct nfs4_server_caps_arg {
+ struct nfs_fh *fhandle;
+ struct nfs4_sequence_args seq_args;
};
struct nfs4_server_caps_res {
@@ -731,6 +843,7 @@ struct nfs4_server_caps_res {
u32 acl_bitmask;
u32 has_links;
u32 has_symlinks;
+ struct nfs4_sequence_res seq_res;
};
struct nfs4_string {
@@ -765,10 +878,71 @@ struct nfs4_fs_locations_arg {
const struct qstr *name;
struct page *page;
const u32 *bitmask;
+ struct nfs4_sequence_args seq_args;
+};
+
+struct nfs4_fs_locations_res {
+ struct nfs4_fs_locations *fs_locations;
+ struct nfs4_sequence_res seq_res;
};
#endif /* CONFIG_NFS_V4 */
+struct nfstime4 {
+ u64 seconds;
+ u32 nseconds;
+};
+
+#ifdef CONFIG_NFS_V4_1
+struct nfs_impl_id4 {
+ u32 domain_len;
+ char *domain;
+ u32 name_len;
+ char *name;
+ struct nfstime4 date;
+};
+
+#define NFS4_EXCHANGE_ID_LEN (48)
+struct nfs41_exchange_id_args {
+ struct nfs_client *client;
+ nfs4_verifier *verifier;
+ unsigned int id_len;
+ char id[NFS4_EXCHANGE_ID_LEN];
+ u32 flags;
+};
+
+struct server_owner {
+ uint64_t minor_id;
+ uint32_t major_id_sz;
+ char major_id[NFS4_OPAQUE_LIMIT];
+};
+
+struct server_scope {
+ uint32_t server_scope_sz;
+ char server_scope[NFS4_OPAQUE_LIMIT];
+};
+
+struct nfs41_exchange_id_res {
+ struct nfs_client *client;
+ u32 flags;
+ struct server_owner server_owner;
+ struct server_scope server_scope;
+ struct nfs_impl_id4 impl_id;
+};
+
+struct nfs41_create_session_args {
+ struct nfs_client *client;
+ uint32_t flags;
+ uint32_t cb_program;
+ struct nfs4_channel_attrs fc_attrs; /* Fore Channel */
+ struct nfs4_channel_attrs bc_attrs; /* Back Channel */
+};
+
+struct nfs41_create_session_res {
+ struct nfs_client *client;
+};
+#endif /* CONFIG_NFS_V4_1 */
+
struct nfs_page;
#define NFS_PAGEVEC_SIZE (8U)
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
index bcd0201589f8..a6d9ef2bb34a 100644
--- a/include/linux/nfsd/export.h
+++ b/include/linux/nfsd/export.h
@@ -125,11 +125,9 @@ void nfsd_export_flush(void);
void exp_readlock(void);
void exp_readunlock(void);
struct svc_export * rqst_exp_get_by_name(struct svc_rqst *,
- struct vfsmount *,
- struct dentry *);
+ struct path *);
struct svc_export * rqst_exp_parent(struct svc_rqst *,
- struct vfsmount *mnt,
- struct dentry *dentry);
+ struct path *);
int exp_rootfh(struct auth_domain *,
char *path, struct knfsd_fh *, int maxsize);
__be32 exp_pseudoroot(struct svc_rqst *, struct svc_fh *);
diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h
index afa19016c4a8..8f641c908450 100644
--- a/include/linux/nfsd/nfsfh.h
+++ b/include/linux/nfsd/nfsfh.h
@@ -151,9 +151,15 @@ typedef struct svc_fh {
__u64 fh_pre_size; /* size before operation */
struct timespec fh_pre_mtime; /* mtime before oper */
struct timespec fh_pre_ctime; /* ctime before oper */
+ /*
+ * pre-op nfsv4 change attr: note must check IS_I_VERSION(inode)
+ * to find out if it is valid.
+ */
+ u64 fh_pre_change;
/* Post-op attributes saved in fh_unlock */
struct kstat fh_post_attr; /* full attrs after operation */
+ u64 fh_post_change; /* nfsv4 change; see above */
#endif /* CONFIG_NFSD_V3 */
} svc_fh;
@@ -298,6 +304,7 @@ fill_pre_wcc(struct svc_fh *fhp)
fhp->fh_pre_mtime = inode->i_mtime;
fhp->fh_pre_ctime = inode->i_ctime;
fhp->fh_pre_size = inode->i_size;
+ fhp->fh_pre_change = inode->i_version;
fhp->fh_pre_saved = 1;
}
}
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index 4d61c873feed..b60ba43df041 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -41,7 +41,6 @@
#include <linux/kref.h>
#include <linux/sunrpc/clnt.h>
-#define NFS4_OPAQUE_LIMIT 1024
typedef struct {
u32 cl_boot;
u32 cl_id;
@@ -61,15 +60,6 @@ typedef struct {
#define si_stateownerid si_opaque.so_stateownerid
#define si_fileid si_opaque.so_fileid
-
-struct nfs4_cb_recall {
- u32 cbr_ident;
- int cbr_trunc;
- stateid_t cbr_stateid;
- struct knfsd_fh cbr_fh;
- struct nfs4_delegation *cbr_dp;
-};
-
struct nfs4_delegation {
struct list_head dl_perfile;
struct list_head dl_perclnt;
@@ -81,14 +71,15 @@ struct nfs4_delegation {
struct file *dl_vfs_file;
u32 dl_type;
time_t dl_time;
- struct nfs4_cb_recall dl_recall;
+/* For recall: */
+ u32 dl_ident;
+ stateid_t dl_stateid;
+ struct knfsd_fh dl_fh;
+ int dl_retries;
};
-#define dl_stateid dl_recall.cbr_stateid
-#define dl_fh dl_recall.cbr_fh
-
/* client delegation callback info */
-struct nfs4_callback {
+struct nfs4_cb_conn {
/* SETCLIENTID info */
u32 cb_addr;
unsigned short cb_port;
@@ -97,6 +88,7 @@ struct nfs4_callback {
/* RPC client info */
atomic_t cb_set; /* successful CB_NULL call */
struct rpc_clnt * cb_client;
+ struct rpc_cred * cb_cred;
};
/* Maximum number of slots per session. 128 is useful for long haul TCP */
@@ -185,7 +177,7 @@ struct nfs4_client {
struct svc_cred cl_cred; /* setclientid principal */
clientid_t cl_clientid; /* generated by server */
nfs4_verifier cl_confirm; /* generated by server */
- struct nfs4_callback cl_callback; /* callback info */
+ struct nfs4_cb_conn cl_cb_conn; /* callback info */
atomic_t cl_count; /* ref count */
u32 cl_firststate; /* recovery dir creation */
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index f80d6013fdc3..d0f050f01eca 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -64,10 +64,13 @@ static inline bool nfsd4_has_session(struct nfsd4_compound_state *cs)
struct nfsd4_change_info {
u32 atomic;
+ bool change_supported;
u32 before_ctime_sec;
u32 before_ctime_nsec;
+ u64 before_change;
u32 after_ctime_sec;
u32 after_ctime_nsec;
+ u64 after_change;
};
struct nfsd4_access {
@@ -503,10 +506,16 @@ set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)
{
BUG_ON(!fhp->fh_pre_saved || !fhp->fh_post_saved);
cinfo->atomic = 1;
- cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
- cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
- cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec;
- cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec;
+ cinfo->change_supported = IS_I_VERSION(fhp->fh_dentry->d_inode);
+ if (cinfo->change_supported) {
+ cinfo->before_change = fhp->fh_pre_change;
+ cinfo->after_change = fhp->fh_post_change;
+ } else {
+ cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
+ cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
+ cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec;
+ cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec;
+ }
}
int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *);
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index e9fd13aa79f0..58c4ee1822d3 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -494,6 +494,11 @@ enum nl80211_commands {
* @NL80211_ATTR_TIMED_OUT: a flag indicating than an operation timed out; this
* is used, e.g., with %NL80211_CMD_AUTHENTICATE event
*
+ * @NL80211_ATTR_USE_MFP: Whether management frame protection (IEEE 802.11w) is
+ * used for the association (&enum nl80211_mfp, represented as a u32);
+ * this attribute can be used
+ * with %NL80211_CMD_ASSOCIATE request
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -596,6 +601,8 @@ enum nl80211_attrs {
NL80211_ATTR_TIMED_OUT,
+ NL80211_ATTR_USE_MFP,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -1179,4 +1186,14 @@ enum nl80211_key_type {
NL80211_KEYTYPE_PEERKEY,
};
+/**
+ * enum nl80211_mfp - Management frame protection state
+ * @NL80211_MFP_NO: Management frame protection not used
+ * @NL80211_MFP_REQUIRED: Management frame protection required
+ */
+enum nl80211_mfp {
+ NL80211_MFP_NO,
+ NL80211_MFP_REQUIRED,
+};
+
#endif /* __LINUX_NL80211_H */
diff --git a/include/linux/nls.h b/include/linux/nls.h
index 6a882208301a..52b1a76c1b43 100644
--- a/include/linux/nls.h
+++ b/include/linux/nls.h
@@ -58,6 +58,25 @@ static inline int nls_strnicmp(struct nls_table *t, const unsigned char *s1,
return 0;
}
+/*
+ * nls_nullsize - return length of null character for codepage
+ * @codepage - codepage for which to return length of NULL terminator
+ *
+ * Since we can't guarantee that the null terminator will be a particular
+ * length, we have to check against the codepage. If there's a problem
+ * determining it, assume a single-byte NULL terminator.
+ */
+static inline int
+nls_nullsize(const struct nls_table *codepage)
+{
+ int charlen;
+ char tmp[NLS_MAX_CHARSET_SIZE];
+
+ charlen = codepage->uni2char(0, tmp, NLS_MAX_CHARSET_SIZE);
+
+ return charlen > 0 ? charlen : 1;
+}
+
#define MODULE_ALIAS_NLS(name) MODULE_ALIAS("nls_" __stringify(name))
#endif /* _LINUX_NLS_H */
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
index 3d327b67d7e2..908406651330 100644
--- a/include/linux/of_platform.h
+++ b/include/linux/of_platform.h
@@ -51,6 +51,16 @@ extern int of_register_driver(struct of_platform_driver *drv,
struct bus_type *bus);
extern void of_unregister_driver(struct of_platform_driver *drv);
+/* Platform drivers register/unregister */
+static inline int of_register_platform_driver(struct of_platform_driver *drv)
+{
+ return of_register_driver(drv, &of_platform_bus_type);
+}
+static inline void of_unregister_platform_driver(struct of_platform_driver *drv)
+{
+ of_unregister_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/page-flags.h b/include/linux/page-flags.h
index 62214c7d2d93..f036dfbdad54 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -120,7 +120,6 @@ enum pageflags {
PG_savepinned = PG_dirty,
/* SLOB */
- PG_slob_page = PG_active,
PG_slob_free = PG_private,
/* SLUB */
@@ -203,7 +202,6 @@ PAGEFLAG(SavePinned, savepinned); /* Xen */
PAGEFLAG(Reserved, reserved) __CLEARPAGEFLAG(Reserved, reserved)
PAGEFLAG(SwapBacked, swapbacked) __CLEARPAGEFLAG(SwapBacked, swapbacked)
-__PAGEFLAG(SlobPage, slob_page)
__PAGEFLAG(SlobFree, slob_free)
__PAGEFLAG(SlubFrozen, slub_frozen)
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 72698d89e767..19ee92c53ef7 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -599,8 +599,6 @@ extern void pci_sort_breadthfirst(void);
struct pci_dev __deprecated *pci_find_device(unsigned int vendor,
unsigned int device,
struct pci_dev *from);
-struct pci_dev __deprecated *pci_find_slot(unsigned int bus,
- unsigned int devfn);
#endif /* CONFIG_PCI_LEGACY */
enum pci_lost_interrupt_reason {
@@ -936,12 +934,6 @@ static inline struct pci_dev *pci_find_device(unsigned int vendor,
return NULL;
}
-static inline struct pci_dev *pci_find_slot(unsigned int bus,
- unsigned int devfn)
-{
- return NULL;
-}
-
static inline struct pci_dev *pci_get_device(unsigned int vendor,
unsigned int device,
struct pci_dev *from)
@@ -1097,6 +1089,10 @@ static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus,
#include <asm/pci.h>
+#ifndef PCIBIOS_MAX_MEM_32
+#define PCIBIOS_MAX_MEM_32 (-1)
+#endif
+
/* these helpers provide future and backwards compatibility
* for accessing popular PCI BAR info */
#define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start)
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index ea061e290d02..53156d0a4621 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1005,6 +1005,7 @@
#define PCI_DEVICE_ID_PLX_PCI200SYN 0x3196
#define PCI_DEVICE_ID_PLX_9030 0x9030
#define PCI_DEVICE_ID_PLX_9050 0x9050
+#define PCI_DEVICE_ID_PLX_9056 0x9056
#define PCI_DEVICE_ID_PLX_9080 0x9080
#define PCI_DEVICE_ID_PLX_GTEK_SERIAL2 0xa001
@@ -1847,6 +1848,10 @@
#define PCI_SUBDEVICE_ID_HYPERCOPE_METRO 0x0107
#define PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2 0x0108
+#define PCI_VENDOR_ID_DIGIGRAM 0x1369
+#define PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ES_SERIAL_SUBSYSTEM 0xc001
+#define PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ES_CAE_SERIAL_SUBSYSTEM 0xc002
+
#define PCI_VENDOR_ID_KAWASAKI 0x136b
#define PCI_DEVICE_ID_MCHIP_KL5A72002 0xff01
@@ -2274,6 +2279,8 @@
#define PCI_DEVICE_ID_MPC8547E 0x0018
#define PCI_DEVICE_ID_MPC8545E 0x0019
#define PCI_DEVICE_ID_MPC8545 0x001a
+#define PCI_DEVICE_ID_MPC8569E 0x0061
+#define PCI_DEVICE_ID_MPC8569 0x0060
#define PCI_DEVICE_ID_MPC8568E 0x0020
#define PCI_DEVICE_ID_MPC8568 0x0021
#define PCI_DEVICE_ID_MPC8567E 0x0022
@@ -2516,6 +2523,8 @@
#define PCI_DEVICE_ID_INTEL_IOAT_TBG3 0x3433
#define PCI_DEVICE_ID_INTEL_82830_HB 0x3575
#define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577
+#define PCI_DEVICE_ID_INTEL_82854_HB 0x358c
+#define PCI_DEVICE_ID_INTEL_82854_IG 0x358e
#define PCI_DEVICE_ID_INTEL_82855GM_HB 0x3580
#define PCI_DEVICE_ID_INTEL_82855GM_IG 0x3582
#define PCI_DEVICE_ID_INTEL_E7520_MCH 0x3590
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
index e4d08c1b2e0b..83b02f5a25b2 100644
--- a/include/linux/pci_regs.h
+++ b/include/linux/pci_regs.h
@@ -295,8 +295,9 @@
#define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */
#define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
#define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */
+#define PCI_MSI_MASK_32 12 /* Mask bits register for 32-bit devices */
#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */
-#define PCI_MSI_MASK_BIT 16 /* Mask bits register */
+#define PCI_MSI_MASK_64 16 /* Mask bits register for 64-bit devices */
/* MSI-X registers (these are at offset PCI_MSIX_FLAGS) */
#define PCI_MSIX_FLAGS 2
@@ -304,7 +305,6 @@
#define PCI_MSIX_FLAGS_ENABLE (1 << 15)
#define PCI_MSIX_FLAGS_MASKALL (1 << 14)
#define PCI_MSIX_FLAGS_BIRMASK (7 << 0)
-#define PCI_MSIX_FLAGS_BITMASK (1 << 0)
/* CompactPCI Hotswap Register */
@@ -376,6 +376,7 @@
#define PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */
#define PCI_EXP_TYPE_PCI_BRIDGE 0x7 /* PCI/PCI-X Bridge */
#define PCI_EXP_TYPE_RC_END 0x9 /* Root Complex Integrated Endpoint */
+#define PCI_EXP_TYPE_RC_EC 0x10 /* Root Complex Event Collector */
#define PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */
#define PCI_EXP_FLAGS_IRQ 0x3e00 /* Interrupt message number */
#define PCI_EXP_DEVCAP 4 /* Device capabilities */
diff --git a/include/linux/percpu-defs.h b/include/linux/percpu-defs.h
new file mode 100644
index 000000000000..8f921d74f49f
--- /dev/null
+++ b/include/linux/percpu-defs.h
@@ -0,0 +1,84 @@
+#ifndef _LINUX_PERCPU_DEFS_H
+#define _LINUX_PERCPU_DEFS_H
+
+/*
+ * Determine the real variable name from the name visible in the
+ * kernel sources.
+ */
+#define per_cpu_var(var) per_cpu__##var
+
+/*
+ * Base implementations of per-CPU variable declarations and definitions, where
+ * the section in which the variable is to be placed is provided by the
+ * 'section' argument. This may be used to affect the parameters governing the
+ * variable's storage.
+ *
+ * NOTE! The sections for the DECLARE and for the DEFINE must match, lest
+ * linkage errors occur due the compiler generating the wrong code to access
+ * that section.
+ */
+#define DECLARE_PER_CPU_SECTION(type, name, section) \
+ extern \
+ __attribute__((__section__(PER_CPU_BASE_SECTION section))) \
+ PER_CPU_ATTRIBUTES __typeof__(type) per_cpu__##name
+
+#define DEFINE_PER_CPU_SECTION(type, name, section) \
+ __attribute__((__section__(PER_CPU_BASE_SECTION section))) \
+ PER_CPU_ATTRIBUTES __typeof__(type) per_cpu__##name
+
+/*
+ * Variant on the per-CPU variable declaration/definition theme used for
+ * ordinary per-CPU variables.
+ */
+#define DECLARE_PER_CPU(type, name) \
+ DECLARE_PER_CPU_SECTION(type, name, "")
+
+#define DEFINE_PER_CPU(type, name) \
+ DEFINE_PER_CPU_SECTION(type, name, "")
+
+/*
+ * Declaration/definition used for per-CPU variables that must come first in
+ * the set of variables.
+ */
+#define DECLARE_PER_CPU_FIRST(type, name) \
+ DECLARE_PER_CPU_SECTION(type, name, PER_CPU_FIRST_SECTION)
+
+#define DEFINE_PER_CPU_FIRST(type, name) \
+ DEFINE_PER_CPU_SECTION(type, name, PER_CPU_FIRST_SECTION)
+
+/*
+ * Declaration/definition used for per-CPU variables that must be cacheline
+ * aligned under SMP conditions so that, whilst a particular instance of the
+ * data corresponds to a particular CPU, inefficiencies due to direct access by
+ * other CPUs are reduced by preventing the data from unnecessarily spanning
+ * cachelines.
+ *
+ * An example of this would be statistical data, where each CPU's set of data
+ * is updated by that CPU alone, but the data from across all CPUs is collated
+ * by a CPU processing a read from a proc file.
+ */
+#define DECLARE_PER_CPU_SHARED_ALIGNED(type, name) \
+ DECLARE_PER_CPU_SECTION(type, name, PER_CPU_SHARED_ALIGNED_SECTION) \
+ ____cacheline_aligned_in_smp
+
+#define DEFINE_PER_CPU_SHARED_ALIGNED(type, name) \
+ DEFINE_PER_CPU_SECTION(type, name, PER_CPU_SHARED_ALIGNED_SECTION) \
+ ____cacheline_aligned_in_smp
+
+/*
+ * Declaration/definition used for per-CPU variables that must be page aligned.
+ */
+#define DECLARE_PER_CPU_PAGE_ALIGNED(type, name) \
+ DECLARE_PER_CPU_SECTION(type, name, ".page_aligned")
+
+#define DEFINE_PER_CPU_PAGE_ALIGNED(type, name) \
+ DEFINE_PER_CPU_SECTION(type, name, ".page_aligned")
+
+/*
+ * Intermodule exports for per-CPU variables.
+ */
+#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var)
+#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var)
+
+
+#endif /* _LINUX_PERCPU_DEFS_H */
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index cfda2d5ad319..26fd9d12f050 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -9,50 +9,6 @@
#include <asm/percpu.h>
-#ifndef PER_CPU_BASE_SECTION
-#ifdef CONFIG_SMP
-#define PER_CPU_BASE_SECTION ".data.percpu"
-#else
-#define PER_CPU_BASE_SECTION ".data"
-#endif
-#endif
-
-#ifdef CONFIG_SMP
-
-#ifdef MODULE
-#define PER_CPU_SHARED_ALIGNED_SECTION ""
-#else
-#define PER_CPU_SHARED_ALIGNED_SECTION ".shared_aligned"
-#endif
-#define PER_CPU_FIRST_SECTION ".first"
-
-#else
-
-#define PER_CPU_SHARED_ALIGNED_SECTION ""
-#define PER_CPU_FIRST_SECTION ""
-
-#endif
-
-#define DEFINE_PER_CPU_SECTION(type, name, section) \
- __attribute__((__section__(PER_CPU_BASE_SECTION section))) \
- PER_CPU_ATTRIBUTES __typeof__(type) per_cpu__##name
-
-#define DEFINE_PER_CPU(type, name) \
- DEFINE_PER_CPU_SECTION(type, name, "")
-
-#define DEFINE_PER_CPU_SHARED_ALIGNED(type, name) \
- DEFINE_PER_CPU_SECTION(type, name, PER_CPU_SHARED_ALIGNED_SECTION) \
- ____cacheline_aligned_in_smp
-
-#define DEFINE_PER_CPU_PAGE_ALIGNED(type, name) \
- DEFINE_PER_CPU_SECTION(type, name, ".page_aligned")
-
-#define DEFINE_PER_CPU_FIRST(type, name) \
- DEFINE_PER_CPU_SECTION(type, name, PER_CPU_FIRST_SECTION)
-
-#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var)
-#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var)
-
/* enough to cover all DEFINE_PER_CPUs in modules */
#ifdef CONFIG_MODULES
#define PERCPU_MODULE_RESERVE (8 << 10)
@@ -130,7 +86,12 @@ struct percpu_data {
void *ptrs[1];
};
+/* pointer disguising messes up the kmemleak objects tracking */
+#ifndef CONFIG_DEBUG_KMEMLEAK
#define __percpu_disguise(pdata) (struct percpu_data *)~(unsigned long)(pdata)
+#else
+#define __percpu_disguise(pdata) (struct percpu_data *)(pdata)
+#endif
#define per_cpu_ptr(ptr, cpu) \
({ \
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index 8e4120285f72..c8f038554e80 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -134,6 +134,11 @@ struct pipe_buf_operations {
memory allocation, whereas PIPE_BUF makes atomicity guarantees. */
#define PIPE_SIZE PAGE_SIZE
+/* Pipe lock and unlock operations */
+void pipe_lock(struct pipe_inode_info *);
+void pipe_unlock(struct pipe_inode_info *);
+void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *);
+
/* Drop the inode semaphore and wait for a pipe event, atomically */
void pipe_wait(struct pipe_inode_info *pipe);
diff --git a/include/linux/pktcdvd.h b/include/linux/pktcdvd.h
index 04b4d7330e6d..d745f5b6c7b0 100644
--- a/include/linux/pktcdvd.h
+++ b/include/linux/pktcdvd.h
@@ -113,6 +113,7 @@ struct pkt_ctrl_command {
#include <linux/cdrom.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
+#include <linux/mempool.h>
/* default bio write queue congestion marks */
#define PKT_WRITE_CONGESTION_ON 10000
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 76e470a299bf..b67bb5d7b221 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -20,7 +20,6 @@ struct platform_device {
struct device dev;
u32 num_resources;
struct resource * resource;
- void *platform_data;
struct platform_device_id *id_entry;
};
@@ -77,4 +76,46 @@ extern int platform_driver_probe(struct platform_driver *driver,
#define platform_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev)
#define platform_set_drvdata(_dev,data) dev_set_drvdata(&(_dev)->dev, (data))
+/* early platform driver interface */
+struct early_platform_driver {
+ const char *class_str;
+ struct platform_driver *pdrv;
+ struct list_head list;
+ int requested_id;
+};
+
+#define EARLY_PLATFORM_ID_UNSET -2
+#define EARLY_PLATFORM_ID_ERROR -3
+
+extern int early_platform_driver_register(struct early_platform_driver *epdrv,
+ char *buf);
+extern void early_platform_add_devices(struct platform_device **devs, int num);
+
+static inline int is_early_platform_device(struct platform_device *pdev)
+{
+ return !pdev->dev.driver;
+}
+
+extern void early_platform_driver_register_all(char *class_str);
+extern int early_platform_driver_probe(char *class_str,
+ int nr_probe, int user_only);
+extern void early_platform_cleanup(void);
+
+
+#ifndef MODULE
+#define early_platform_init(class_string, platform_driver) \
+static __initdata struct early_platform_driver early_driver = { \
+ .class_str = class_string, \
+ .pdrv = platform_driver, \
+ .requested_id = EARLY_PLATFORM_ID_UNSET, \
+}; \
+static int __init early_platform_driver_setup_func(char *buf) \
+{ \
+ return early_platform_driver_register(&early_driver, buf); \
+} \
+early_param(class_string, early_platform_driver_setup_func)
+#else /* MODULE */
+#define early_platform_init(class_string, platform_driver)
+#endif /* MODULE */
+
#endif /* _PLATFORM_DEVICE_H_ */
diff --git a/include/linux/poison.h b/include/linux/poison.h
index 6729f7dcd60e..229322707f5f 100644
--- a/include/linux/poison.h
+++ b/include/linux/poison.h
@@ -2,13 +2,25 @@
#define _LINUX_POISON_H
/********** include/linux/list.h **********/
+
+/*
+ * Architectures might want to move the poison pointer offset
+ * into some well-recognized area such as 0xdead000000000000,
+ * that is also not mappable by user-space exploits:
+ */
+#ifdef CONFIG_ILLEGAL_POINTER_VALUE
+# define POISON_POINTER_DELTA _AC(CONFIG_ILLEGAL_POINTER_VALUE, UL)
+#else
+# define POISON_POINTER_DELTA 0
+#endif
+
/*
* These are non-NULL pointers that will result in page faults
* under normal circumstances, used to verify that nobody uses
* non-initialized list entries.
*/
-#define LIST_POISON1 ((void *) 0x00100100)
-#define LIST_POISON2 ((void *) 0x00200200)
+#define LIST_POISON1 ((void *) 0x00100100 + POISON_POINTER_DELTA)
+#define LIST_POISON2 ((void *) 0x00200200 + POISON_POINTER_DELTA)
/********** include/linux/timer.h **********/
/*
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index fbfa3d44d33d..e6e77d31c418 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -93,20 +93,9 @@ struct vmcore {
#ifdef CONFIG_PROC_FS
-extern spinlock_t proc_subdir_lock;
-
extern void proc_root_init(void);
void proc_flush_task(struct task_struct *task);
-struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *);
-int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir);
-unsigned long task_vsize(struct mm_struct *);
-int task_statm(struct mm_struct *, int *, int *, int *, int *);
-void task_mem(struct seq_file *, struct mm_struct *);
-void clear_refs_smap(struct mm_struct *mm);
-
-struct proc_dir_entry *de_get(struct proc_dir_entry *de);
-void de_put(struct proc_dir_entry *de);
extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
struct proc_dir_entry *parent);
@@ -116,20 +105,7 @@ struct proc_dir_entry *proc_create_data(const char *name, mode_t mode,
void *data);
extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
-extern struct vfsmount *proc_mnt;
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 *);
-
-/*
- * These are generic /proc routines that use the internal
- * "struct proc_dir_entry" tree to traverse the filesystem.
- *
- * The /proc root directory has extended versions to take care
- * of the /proc/<pid> subdirectories.
- */
-extern int proc_readdir(struct file *, void *, filldir_t);
-extern struct dentry *proc_lookup(struct inode *, struct dentry *, struct nameidata *);
extern int pid_ns_prepare_proc(struct pid_namespace *ns);
extern void pid_ns_release_proc(struct pid_namespace *ns);
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 67c15653fc23..59e133d39d50 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -95,7 +95,6 @@ extern void __ptrace_link(struct task_struct *child,
struct task_struct *new_parent);
extern void __ptrace_unlink(struct task_struct *child);
extern void exit_ptrace(struct task_struct *tracer);
-extern void ptrace_fork(struct task_struct *task, unsigned long clone_flags);
#define PTRACE_MODE_READ 1
#define PTRACE_MODE_ATTACH 2
/* Returns 0 on success, -errno on denial. */
@@ -327,15 +326,6 @@ static inline void user_enable_block_step(struct task_struct *task)
#define arch_ptrace_untrace(task) do { } while (0)
#endif
-#ifndef arch_ptrace_fork
-/*
- * Do machine-specific work to initialize a new task.
- *
- * This is called from copy_process().
- */
-#define arch_ptrace_fork(child, clone_flags) do { } while (0)
-#endif
-
extern int task_current_syscall(struct task_struct *target, long *callno,
unsigned long args[6], unsigned int maxargs,
unsigned long *sp, unsigned long *pc);
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 36353d95c8db..7bc457593684 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -20,7 +20,12 @@ static inline struct quota_info *sb_dqopt(struct super_block *sb)
/*
* declaration of quota_function calls in kernel.
*/
-void sync_dquots(struct super_block *sb, int type);
+void sync_quota_sb(struct super_block *sb, int type);
+static inline void writeout_quota_sb(struct super_block *sb, int type)
+{
+ if (sb->s_qcop->quota_sync)
+ sb->s_qcop->quota_sync(sb, type);
+}
int dquot_initialize(struct inode *inode, int type);
int dquot_drop(struct inode *inode);
@@ -253,12 +258,7 @@ static inline void vfs_dq_free_inode(struct inode *inode)
inode->i_sb->dq_op->free_inode(inode, 1);
}
-/* The following two functions cannot be called inside a transaction */
-static inline void vfs_dq_sync(struct super_block *sb)
-{
- sync_dquots(sb, -1);
-}
-
+/* Cannot be called inside a transaction */
static inline int vfs_dq_off(struct super_block *sb, int remount)
{
int ret = -ENOSYS;
@@ -334,7 +334,11 @@ static inline void vfs_dq_free_inode(struct inode *inode)
{
}
-static inline void vfs_dq_sync(struct super_block *sb)
+static inline void sync_quota_sb(struct super_block *sb, int type)
+{
+}
+
+static inline void writeout_quota_sb(struct super_block *sb, int type)
{
}
diff --git a/include/linux/rcu_types.h b/include/linux/rcu_types.h
new file mode 100644
index 000000000000..fd3570d0e6c1
--- /dev/null
+++ b/include/linux/rcu_types.h
@@ -0,0 +1,18 @@
+#ifndef __LINUX_RCU_TYPES_H
+#define __LINUX_RCU_TYPES_H
+
+#ifdef __KERNEL__
+
+/**
+ * struct rcu_head - callback structure for use with RCU
+ * @next: next update requests in a list
+ * @func: actual update function to call after the grace period.
+ */
+struct rcu_head {
+ struct rcu_head *next;
+ void (*func)(struct rcu_head *head);
+};
+
+#endif
+
+#endif
diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index e649bd3f2c97..5710f43bbc9e 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -198,6 +198,32 @@ static inline void list_splice_init_rcu(struct list_head *list,
at->prev = last;
}
+/**
+ * list_entry_rcu - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ *
+ * This primitive may safely run concurrently with the _rcu list-mutation
+ * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock().
+ */
+#define list_entry_rcu(ptr, type, member) \
+ container_of(rcu_dereference(ptr), type, member)
+
+/**
+ * list_first_entry_rcu - get the first element from a list
+ * @ptr: the list head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ *
+ * This primitive may safely run concurrently with the _rcu list-mutation
+ * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock().
+ */
+#define list_first_entry_rcu(ptr, type, member) \
+ list_entry_rcu((ptr)->next, type, member)
+
#define __list_for_each_rcu(pos, head) \
for (pos = rcu_dereference((head)->next); \
pos != (head); \
@@ -214,9 +240,9 @@ static inline void list_splice_init_rcu(struct list_head *list,
* as long as the traversal is guarded by rcu_read_lock().
*/
#define list_for_each_entry_rcu(pos, head, member) \
- for (pos = list_entry(rcu_dereference((head)->next), typeof(*pos), member); \
+ for (pos = list_entry_rcu((head)->next, typeof(*pos), member); \
prefetch(pos->member.next), &pos->member != (head); \
- pos = list_entry(rcu_dereference(pos->member.next), typeof(*pos), member))
+ pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
/**
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 15fbb3ca634d..19b82b96affa 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -33,6 +33,7 @@
#ifndef __LINUX_RCUPDATE_H
#define __LINUX_RCUPDATE_H
+#include <linux/rcu_types.h>
#include <linux/cache.h>
#include <linux/spinlock.h>
#include <linux/threads.h>
@@ -41,16 +42,6 @@
#include <linux/lockdep.h>
#include <linux/completion.h>
-/**
- * struct rcu_head - callback structure for use with RCU
- * @next: next update requests in a list
- * @func: actual update function to call after the grace period.
- */
-struct rcu_head {
- struct rcu_head *next;
- void (*func)(struct rcu_head *head);
-};
-
/* Internal to kernel, but needed by rcupreempt.h. */
extern int rcu_scheduler_active;
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
index 0cdda00f2b2a..5a5153806c42 100644
--- a/include/linux/rcutree.h
+++ b/include/linux/rcutree.h
@@ -161,9 +161,15 @@ struct rcu_data {
unsigned long offline_fqs; /* Kicked due to being offline. */
unsigned long resched_ipi; /* Sent a resched IPI. */
- /* 5) state to allow this CPU to force_quiescent_state on others */
+ /* 5) __rcu_pending() statistics. */
long n_rcu_pending; /* rcu_pending() calls since boot. */
- long n_rcu_pending_force_qs; /* when to force quiescent states. */
+ long n_rp_qs_pending;
+ long n_rp_cb_ready;
+ long n_rp_cpu_needs_gp;
+ long n_rp_gp_completed;
+ long n_rp_gp_started;
+ long n_rp_need_fqs;
+ long n_rp_need_nothing;
int cpu;
};
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index 4848d8dacd90..225f733e7533 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -50,6 +50,7 @@ enum regulator_status {
* @set_current_limit: Configure a limit for a current-limited regulator.
* @get_current_limit: Get the configured limit for a current-limited regulator.
*
+ * @set_mode: Set the configured operating mode for the regulator.
* @get_mode: Get the configured operating mode for the regulator.
* @get_status: Return actual (not as-configured) status of regulator, as a
* REGULATOR_STATUS value (or negative errno)
diff --git a/include/linux/regulator/max1586.h b/include/linux/regulator/max1586.h
new file mode 100644
index 000000000000..2056973396b6
--- /dev/null
+++ b/include/linux/regulator/max1586.h
@@ -0,0 +1,52 @@
+/*
+ * max1586.h -- Voltage regulation for the Maxim 1586
+ *
+ * Copyright (C) 2008 Robert Jarzmik
+ *
+ * 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
+ */
+
+#ifndef REGULATOR_MAX1586
+#define REGULATOR_MAX1586
+
+#include <linux/regulator/machine.h>
+
+#define MAX1586_V3 0
+#define MAX1586_V6 1
+
+/**
+ * max1586_subdev_data - regulator data
+ * @id: regulator Id (either MAX1586_V3 or MAX1586_V6)
+ * @name: regulator cute name (example for V3: "vcc_core")
+ * @platform_data: regulator init data (contraints, supplies, ...)
+ */
+struct max1586_subdev_data {
+ int id;
+ char *name;
+ struct regulator_init_data *platform_data;
+};
+
+/**
+ * max1586_platform_data - platform data for max1586
+ * @num_subdevs: number of regultors used (may be 1 or 2)
+ * @subdevs: regulator used
+ * At most, there will be a regulator for V3 and one for V6 voltages.
+ */
+struct max1586_platform_data {
+ int num_subdevs;
+ struct max1586_subdev_data *subdevs;
+};
+
+#endif
diff --git a/include/linux/regulator/userspace-consumer.h b/include/linux/regulator/userspace-consumer.h
new file mode 100644
index 000000000000..b4554ce9d4bb
--- /dev/null
+++ b/include/linux/regulator/userspace-consumer.h
@@ -0,0 +1,25 @@
+#ifndef __REGULATOR_PLATFORM_CONSUMER_H_
+#define __REGULATOR_PLATFORM_CONSUMER_H_
+
+struct regulator_consumer_supply;
+
+/**
+ * struct regulator_userspace_consumer_data - line consumer
+ * initialisation data.
+ *
+ * @name: Name for the consumer line
+ * @num_supplies: Number of supplies feeding the line
+ * @supplies: Supplies configuration.
+ * @init_on: Set if the regulators supplying the line should be
+ * enabled during initialisation
+ */
+struct regulator_userspace_consumer_data {
+ const char *name;
+
+ int num_supplies;
+ struct regulator_bulk_data *supplies;
+
+ bool init_on;
+};
+
+#endif /* __REGULATOR_PLATFORM_CONSUMER_H_ */
diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
index 5621d87c4479..6473650c28f1 100644
--- a/include/linux/reiserfs_fs_sb.h
+++ b/include/linux/reiserfs_fs_sb.h
@@ -193,7 +193,7 @@ struct reiserfs_journal {
atomic_t j_wcount; /* count of writers for current commit */
unsigned long j_bcount; /* batch count. allows turning X transactions into 1 */
unsigned long j_first_unflushed_offset; /* first unflushed transactions offset */
- unsigned long j_last_flush_trans_id; /* last fully flushed journal timestamp */
+ unsigned j_last_flush_trans_id; /* last fully flushed journal timestamp */
struct buffer_head *j_header_bh;
time_t j_trans_start_time; /* time this transaction started */
@@ -402,7 +402,7 @@ struct reiserfs_sb_info {
int reserved_blocks; /* amount of blocks reserved for further allocations */
spinlock_t bitmap_lock; /* this lock on now only used to protect reserved_blocks variable */
struct dentry *priv_root; /* root of /.reiserfs_priv */
- struct dentry *xattr_root; /* root of /.reiserfs_priv/.xa */
+ struct dentry *xattr_root; /* root of /.reiserfs_priv/xattrs */
int j_errno;
#ifdef CONFIG_QUOTA
char *s_qf_names[MAXQUOTAS];
@@ -488,7 +488,6 @@ enum reiserfs_mount_options {
#define reiserfs_data_log(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_LOG))
#define reiserfs_data_ordered(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_ORDERED))
#define reiserfs_data_writeback(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_WRITEBACK))
-#define reiserfs_xattrs(s) ((s)->s_xattr != NULL)
#define reiserfs_xattrs_user(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_XATTRS_USER))
#define reiserfs_posixacl(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_POSIXACL))
#define reiserfs_xattrs_optional(s) (reiserfs_xattrs_user(s) || reiserfs_posixacl(s))
diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h
index dcae01e63e40..cdedc01036e4 100644
--- a/include/linux/reiserfs_xattr.h
+++ b/include/linux/reiserfs_xattr.h
@@ -38,6 +38,7 @@ struct nameidata;
int reiserfs_xattr_register_handlers(void) __init;
void reiserfs_xattr_unregister_handlers(void);
int reiserfs_xattr_init(struct super_block *sb, int mount_flags);
+int reiserfs_lookup_privroot(struct super_block *sb);
int reiserfs_delete_xattrs(struct inode *inode);
int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs);
@@ -97,7 +98,7 @@ static inline size_t reiserfs_xattr_jcreate_nblocks(struct inode *inode)
if ((REISERFS_I(inode)->i_flags & i_has_xattr_dir) == 0) {
nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
- if (REISERFS_SB(inode->i_sb)->xattr_root == NULL)
+ if (!REISERFS_SB(inode->i_sb)->xattr_root->d_inode)
nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
}
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h
index de18ef227e00..e1ec7d9aa49c 100644
--- a/include/linux/rfkill.h
+++ b/include/linux/rfkill.h
@@ -58,6 +58,9 @@ enum rfkill_state {
* @type: Radio type which the button controls, the value stored
* here should be a value from enum rfkill_type.
* @state: State of the switch, "UNBLOCKED" means radio can operate.
+ * @user_claim_unsupported: Whether the hardware supports exclusive
+ * RF-kill control by userspace. Set this before registering.
+ * @user_claim: Set when the switch is controlled exlusively by userspace.
* @mutex: Guards switch state transitions. It serializes callbacks
* and also protects the state.
* @data: Pointer to the RF button drivers private data which will be
@@ -80,6 +83,9 @@ struct rfkill {
const char *name;
enum rfkill_type type;
+ bool user_claim_unsupported;
+ bool user_claim;
+
/* the mutex serializes callbacks and also protects
* the state */
struct mutex mutex;
diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h
index e1b7b2173885..f1345828c7c5 100644
--- a/include/linux/ring_buffer.h
+++ b/include/linux/ring_buffer.h
@@ -11,7 +11,7 @@ struct ring_buffer_iter;
* Don't refer to this struct directly, use functions below.
*/
struct ring_buffer_event {
- u32 type:2, len:3, time_delta:27;
+ u32 type_len:5, time_delta:27;
u32 array[];
};
@@ -24,7 +24,8 @@ struct ring_buffer_event {
* size is variable depending on how much
* padding is needed
* If time_delta is non zero:
- * everything else same as RINGBUF_TYPE_DATA
+ * array[0] holds the actual length
+ * size = 4 + length (bytes)
*
* @RINGBUF_TYPE_TIME_EXTEND: Extend the time delta
* array[0] = time delta (28 .. 59)
@@ -35,22 +36,23 @@ struct ring_buffer_event {
* array[1..2] = tv_sec
* size = 16 bytes
*
- * @RINGBUF_TYPE_DATA: Data record
- * If len is zero:
+ * <= @RINGBUF_TYPE_DATA_TYPE_LEN_MAX:
+ * Data record
+ * If type_len is zero:
* array[0] holds the actual length
* array[1..(length+3)/4] holds data
- * size = 4 + 4 + length (bytes)
+ * size = 4 + length (bytes)
* else
- * length = len << 2
+ * length = type_len << 2
* array[0..(length+3)/4-1] holds data
* size = 4 + length (bytes)
*/
enum ring_buffer_type {
+ RINGBUF_TYPE_DATA_TYPE_LEN_MAX = 28,
RINGBUF_TYPE_PADDING,
RINGBUF_TYPE_TIME_EXTEND,
/* FIXME: RINGBUF_TYPE_TIME_STAMP not implemented */
RINGBUF_TYPE_TIME_STAMP,
- RINGBUF_TYPE_DATA,
};
unsigned ring_buffer_event_length(struct ring_buffer_event *event);
@@ -68,9 +70,38 @@ ring_buffer_event_time_delta(struct ring_buffer_event *event)
return event->time_delta;
}
+/*
+ * ring_buffer_event_discard can discard any event in the ring buffer.
+ * it is up to the caller to protect against a reader from
+ * consuming it or a writer from wrapping and replacing it.
+ *
+ * No external protection is needed if this is called before
+ * the event is commited. But in that case it would be better to
+ * use ring_buffer_discard_commit.
+ *
+ * Note, if an event that has not been committed is discarded
+ * with ring_buffer_event_discard, it must still be committed.
+ */
void ring_buffer_event_discard(struct ring_buffer_event *event);
/*
+ * ring_buffer_discard_commit will remove an event that has not
+ * ben committed yet. If this is used, then ring_buffer_unlock_commit
+ * must not be called on the discarded event. This function
+ * will try to remove the event from the ring buffer completely
+ * if another event has not been written after it.
+ *
+ * Example use:
+ *
+ * if (some_condition)
+ * ring_buffer_discard_commit(buffer, event);
+ * else
+ * ring_buffer_unlock_commit(buffer, event);
+ */
+void ring_buffer_discard_commit(struct ring_buffer *buffer,
+ struct ring_buffer_event *event);
+
+/*
* size is in bytes for each per CPU buffer.
*/
struct ring_buffer *
@@ -122,6 +153,8 @@ unsigned long ring_buffer_entries(struct ring_buffer *buffer);
unsigned long ring_buffer_overruns(struct ring_buffer *buffer);
unsigned long ring_buffer_entries_cpu(struct ring_buffer *buffer, int cpu);
unsigned long ring_buffer_overrun_cpu(struct ring_buffer *buffer, int cpu);
+unsigned long ring_buffer_commit_overrun_cpu(struct ring_buffer *buffer, int cpu);
+unsigned long ring_buffer_nmi_dropped_cpu(struct ring_buffer *buffer, int cpu);
u64 ring_buffer_time_stamp(struct ring_buffer *buffer, int cpu);
void ring_buffer_normalize_time_stamp(struct ring_buffer *buffer,
@@ -137,6 +170,11 @@ void ring_buffer_free_read_page(struct ring_buffer *buffer, void *data);
int ring_buffer_read_page(struct ring_buffer *buffer, void **data_page,
size_t len, int cpu, int full);
+struct trace_seq;
+
+int ring_buffer_print_entry_header(struct trace_seq *s);
+int ring_buffer_print_page_header(struct trace_seq *s);
+
enum ring_buffer_flags {
RB_FL_OVERWRITE = 1 << 0,
};
diff --git a/include/linux/romfs_fs.h b/include/linux/romfs_fs.h
index e20bbf9eb365..c490fbc43fe2 100644
--- a/include/linux/romfs_fs.h
+++ b/include/linux/romfs_fs.h
@@ -53,9 +53,4 @@ struct romfs_inode {
#define ROMFH_PAD (ROMFH_SIZE-1)
#define ROMFH_MASK (~ROMFH_PAD)
-#ifdef __KERNEL__
-
-/* Not much now */
-
-#endif /* __KERNEL__ */
#endif
diff --git a/include/linux/rotary_encoder.h b/include/linux/rotary_encoder.h
index 12d63a30c347..215278b8df2a 100644
--- a/include/linux/rotary_encoder.h
+++ b/include/linux/rotary_encoder.h
@@ -8,6 +8,8 @@ struct rotary_encoder_platform_data {
unsigned int gpio_b;
unsigned int inverted_a;
unsigned int inverted_b;
+ bool relative_axis;
+ bool rollover;
};
#endif /* __ROTARY_ENCODER_H__ */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index b4c38bc8049c..efd2470c0915 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -77,6 +77,7 @@ struct sched_param {
#include <linux/proportions.h>
#include <linux/seccomp.h>
#include <linux/rcupdate.h>
+#include <linux/rculist.h>
#include <linux/rtmutex.h>
#include <linux/time.h>
@@ -96,8 +97,8 @@ struct exec_domain;
struct futex_pi_state;
struct robust_list_head;
struct bio;
-struct bts_tracer;
struct fs_struct;
+struct bts_context;
/*
* List of flags we want to share for kernel threads,
@@ -1209,18 +1210,11 @@ struct task_struct {
struct list_head ptraced;
struct list_head ptrace_entry;
-#ifdef CONFIG_X86_PTRACE_BTS
/*
* This is the tracer handle for the ptrace BTS extension.
* This field actually belongs to the ptracer task.
*/
- struct bts_tracer *bts;
- /*
- * The buffer to hold the BTS data.
- */
- void *bts_buffer;
- size_t bts_size;
-#endif /* CONFIG_X86_PTRACE_BTS */
+ struct bts_context *bts;
/* PID/PID hash table linkage. */
struct pid_link pids[PIDTYPE_MAX];
@@ -1247,7 +1241,9 @@ struct task_struct {
* credentials (COW) */
const struct cred *cred; /* effective (overridable) subjective task
* credentials (COW) */
- struct mutex cred_exec_mutex; /* execve vs ptrace cred calculation mutex */
+ struct mutex cred_guard_mutex; /* guard against foreign influences on
+ * credential calculations
+ * (notably. ptrace) */
char comm[TASK_COMM_LEN]; /* executable name excluding path
- access with [gs]et_task_comm (which lock
@@ -1428,7 +1424,9 @@ struct task_struct {
#ifdef CONFIG_TRACING
/* state flags for use by tracers */
unsigned long trace;
-#endif
+ /* bitmask of trace recursion */
+ unsigned long trace_recursion;
+#endif /* CONFIG_TRACING */
};
/* Future-safe accessor for struct task_struct's cpus_allowed. */
@@ -1885,6 +1883,7 @@ extern void sched_dead(struct task_struct *p);
extern void proc_caches_init(void);
extern void flush_signals(struct task_struct *);
+extern void __flush_signals(struct task_struct *);
extern void ignore_signals(struct task_struct *);
extern void flush_signal_handlers(struct task_struct *, int force_default);
extern int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info);
@@ -2001,8 +2000,10 @@ extern void set_task_comm(struct task_struct *tsk, char *from);
extern char *get_task_comm(char *to, struct task_struct *tsk);
#ifdef CONFIG_SMP
+extern void wait_task_context_switch(struct task_struct *p);
extern unsigned long wait_task_inactive(struct task_struct *, long match_state);
#else
+static inline void wait_task_context_switch(struct task_struct *p) {}
static inline unsigned long wait_task_inactive(struct task_struct *p,
long match_state)
{
@@ -2010,7 +2011,8 @@ static inline unsigned long wait_task_inactive(struct task_struct *p,
}
#endif
-#define next_task(p) list_entry(rcu_dereference((p)->tasks.next), struct task_struct, tasks)
+#define next_task(p) \
+ list_entry_rcu((p)->tasks.next, struct task_struct, tasks)
#define for_each_process(p) \
for (p = &init_task ; (p = next_task(p)) != &init_task ; )
@@ -2049,8 +2051,8 @@ int same_thread_group(struct task_struct *p1, struct task_struct *p2)
static inline struct task_struct *next_thread(const struct task_struct *p)
{
- return list_entry(rcu_dereference(p->thread_group.next),
- struct task_struct, thread_group);
+ return list_entry_rcu(p->thread_group.next,
+ struct task_struct, thread_group);
}
static inline int thread_group_empty(struct task_struct *p)
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index 262a8dccfa81..167c33361d9c 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -21,6 +21,8 @@ extern long prctl_set_seccomp(unsigned long);
#else /* CONFIG_SECCOMP */
+#include <linux/errno.h>
+
typedef struct { } seccomp_t;
#define secure_computing(x) do { } while (0)
diff --git a/include/linux/section-names.h b/include/linux/section-names.h
new file mode 100644
index 000000000000..c956f4eb2adf
--- /dev/null
+++ b/include/linux/section-names.h
@@ -0,0 +1,6 @@
+#ifndef __LINUX_SECTION_NAMES_H
+#define __LINUX_SECTION_NAMES_H
+
+#define HEAD_TEXT_SECTION .head.text
+
+#endif /* !__LINUX_SECTION_NAMES_H */
diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h
index 893cc53486bc..1c297ddc9d5a 100644
--- a/include/linux/serial_sci.h
+++ b/include/linux/serial_sci.h
@@ -25,8 +25,7 @@ struct plat_sci_port {
unsigned int irqs[SCIx_NR_IRQS]; /* ERI, RXI, TXI, BRI */
unsigned int type; /* SCI / SCIF / IRDA */
upf_t flags; /* UPF_* flags */
+ char *clk; /* clock string */
};
-int early_sci_setup(struct uart_port *port);
-
#endif /* __LINUX_SERIAL_SCI_H */
diff --git a/include/linux/serio.h b/include/linux/serio.h
index e0417e4d3f15..126d24c9eaa8 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -15,6 +15,7 @@
#ifdef __KERNEL__
+#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/spinlock.h>
@@ -28,7 +29,10 @@ struct serio {
char name[32];
char phys[32];
- unsigned int manual_bind;
+ bool manual_bind;
+ bool registered; /* port has been fully registered with driver core */
+ bool suspended; /* port is suspended */
+
struct serio_device_id id;
@@ -47,7 +51,6 @@ struct serio {
struct mutex drv_mutex; /* protects serio->drv so attributes can pin driver */
struct device dev;
- unsigned int registered; /* port has been fully registered with driver core */
struct list_head node;
};
@@ -58,7 +61,7 @@ struct serio_driver {
char *description;
struct serio_device_id *id_table;
- unsigned int manual_bind;
+ bool manual_bind;
void (*write_wakeup)(struct serio *);
irqreturn_t (*interrupt)(struct serio *, unsigned char, unsigned int);
diff --git a/include/linux/sh_cmt.h b/include/linux/sh_cmt.h
deleted file mode 100644
index 68cacde5954f..000000000000
--- a/include/linux/sh_cmt.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __SH_CMT_H__
-#define __SH_CMT_H__
-
-struct sh_cmt_config {
- char *name;
- unsigned long channel_offset;
- int timer_bit;
- char *clk;
- unsigned long clockevent_rating;
- unsigned long clocksource_rating;
-};
-
-#endif /* __SH_CMT_H__ */
diff --git a/include/linux/sh_timer.h b/include/linux/sh_timer.h
new file mode 100644
index 000000000000..864bd56bd3b0
--- /dev/null
+++ b/include/linux/sh_timer.h
@@ -0,0 +1,13 @@
+#ifndef __SH_TIMER_H__
+#define __SH_TIMER_H__
+
+struct sh_timer_config {
+ char *name;
+ long channel_offset;
+ int timer_bit;
+ char *clk;
+ unsigned long clockevent_rating;
+ unsigned long clocksource_rating;
+};
+
+#endif /* __SH_TIMER_H__ */
diff --git a/include/linux/sht15.h b/include/linux/sht15.h
new file mode 100644
index 000000000000..046bce05ecab
--- /dev/null
+++ b/include/linux/sht15.h
@@ -0,0 +1,24 @@
+/*
+ * sht15.h - support for the SHT15 Temperature and Humidity Sensor
+ *
+ * Copyright (c) 2009 Jonathan Cameron
+ *
+ * Copyright (c) 2007 Wouter Horre
+ *
+ * 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.
+ */
+
+/**
+ * struct sht15_platform_data - sht15 connectivity info
+ * @gpio_data: no. of gpio to which bidirectional data line is connected
+ * @gpio_sck: no. of gpio to which the data clock is connected.
+ * @supply_mv: supply voltage in mv. Overridden by regulator if available.
+ **/
+struct sht15_platform_data {
+ int gpio_data;
+ int gpio_sck;
+ int supply_mv;
+};
+
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 84f997f8aa53..c7552836bd95 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -235,6 +235,8 @@ static inline int valid_signal(unsigned long sig)
extern int next_signal(struct sigpending *pending, sigset_t *mask);
extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p);
extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *);
+extern long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig,
+ siginfo_t *info);
extern long do_sigpending(void __user *, unsigned long);
extern int sigprocmask(int, sigset_t *, sigset_t *);
extern int show_unhandled_signals;
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 24c5602bee99..76f21a61db32 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -62,9 +62,15 @@
# define SLAB_DEBUG_OBJECTS 0x00000000UL
#endif
+#define SLAB_NOLEAKTRACE 0x00800000UL /* Avoid kmemleak tracing */
+
/* 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 */
+
+/* Following flags should only be used by allocator specific flags */
+#define SLAB_ALLOC_PRIVATE 0x000000ffUL
+
/*
* ZERO_SIZE_PTR will be returned for zero sized kmalloc requests.
*
@@ -151,6 +157,8 @@ size_t ksize(const void *);
*/
#ifdef CONFIG_SLUB
#include <linux/slub_def.h>
+#elif defined(CONFIG_SLQB)
+#include <linux/slqb_def.h>
#elif defined(CONFIG_SLOB)
#include <linux/slob_def.h>
#else
@@ -253,7 +261,7 @@ static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep,
* allocator where we care about the real place the memory allocation
* request comes from.
*/
-#if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_SLUB)
+#if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_SLUB) || defined(CONFIG_SLQB_DEBUG)
extern void *__kmalloc_track_caller(size_t, gfp_t, unsigned long);
#define kmalloc_track_caller(size, flags) \
__kmalloc_track_caller(size, flags, _RET_IP_)
@@ -271,7 +279,7 @@ extern void *__kmalloc_track_caller(size_t, gfp_t, unsigned long);
* standard allocator where we care about the real place the memory
* allocation request comes from.
*/
-#if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_SLUB)
+#if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_SLUB) || defined(CONFIG_SLQB_DEBUG)
extern void *__kmalloc_node_track_caller(size_t, gfp_t, int, unsigned long);
#define kmalloc_node_track_caller(size, flags, node) \
__kmalloc_node_track_caller(size, flags, node, \
diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h
index 5ac9b0bcaf9a..713f841ecaa9 100644
--- a/include/linux/slab_def.h
+++ b/include/linux/slab_def.h
@@ -14,7 +14,7 @@
#include <asm/page.h> /* kmalloc_sizes.h needs PAGE_SIZE */
#include <asm/cache.h> /* kmalloc_sizes.h needs L1_CACHE_BYTES */
#include <linux/compiler.h>
-#include <trace/kmemtrace.h>
+#include <linux/kmemtrace.h>
/* Size description struct for general caches. */
struct cache_sizes {
diff --git a/include/linux/slow-work.h b/include/linux/slow-work.h
index 85958277f83d..b65c8881f07a 100644
--- a/include/linux/slow-work.h
+++ b/include/linux/slow-work.h
@@ -67,7 +67,7 @@ static inline void slow_work_init(struct slow_work *work,
}
/**
- * slow_work_init - Initialise a very slow work item
+ * vslow_work_init - Initialise a very slow work item
* @work: The work item to initialise
* @ops: The operations to use to handle the slow work item
*
diff --git a/include/linux/slqb_def.h b/include/linux/slqb_def.h
new file mode 100644
index 000000000000..7b4a601fd87e
--- /dev/null
+++ b/include/linux/slqb_def.h
@@ -0,0 +1,298 @@
+#ifndef _LINUX_SLQB_DEF_H
+#define _LINUX_SLQB_DEF_H
+
+/*
+ * SLQB : A slab allocator with object queues.
+ *
+ * (C) 2008 Nick Piggin <npiggin@suse.de>
+ */
+#include <linux/types.h>
+#include <linux/gfp.h>
+#include <linux/workqueue.h>
+#include <linux/kobject.h>
+#include <linux/rcu_types.h>
+#include <linux/mm_types.h>
+#include <linux/kernel.h>
+#include <linux/kobject.h>
+
+#define SLAB_NUMA 0x00000001UL /* shortcut */
+
+enum stat_item {
+ ALLOC, /* Allocation count */
+ ALLOC_SLAB_FILL, /* Fill freelist from page list */
+ ALLOC_SLAB_NEW, /* New slab acquired from page allocator */
+ FREE, /* Free count */
+ FREE_REMOTE, /* NUMA: freeing to remote list */
+ FLUSH_FREE_LIST, /* Freelist flushed */
+ FLUSH_FREE_LIST_OBJECTS, /* Objects flushed from freelist */
+ FLUSH_FREE_LIST_REMOTE, /* Objects flushed from freelist to remote */
+ FLUSH_SLAB_PARTIAL, /* Freeing moves slab to partial list */
+ FLUSH_SLAB_FREE, /* Slab freed to the page allocator */
+ FLUSH_RFREE_LIST, /* Rfree list flushed */
+ FLUSH_RFREE_LIST_OBJECTS, /* Rfree objects flushed */
+ CLAIM_REMOTE_LIST, /* Remote freed list claimed */
+ CLAIM_REMOTE_LIST_OBJECTS, /* Remote freed objects claimed */
+ NR_SLQB_STAT_ITEMS
+};
+
+/*
+ * Singly-linked list with head, tail, and nr
+ */
+struct kmlist {
+ unsigned long nr;
+ void **head;
+ void **tail;
+};
+
+/*
+ * Every kmem_cache_list has a kmem_cache_remote_free structure, by which
+ * objects can be returned to the kmem_cache_list from remote CPUs.
+ */
+struct kmem_cache_remote_free {
+ spinlock_t lock;
+ struct kmlist list;
+} ____cacheline_aligned;
+
+/*
+ * A kmem_cache_list manages all the slabs and objects allocated from a given
+ * source. Per-cpu kmem_cache_lists allow node-local allocations. Per-node
+ * kmem_cache_lists allow off-node allocations (but require locking).
+ */
+struct kmem_cache_list {
+ /* Fastpath LIFO freelist of objects */
+ struct kmlist freelist;
+#ifdef CONFIG_SMP
+ /* remote_free has reached a watermark */
+ int remote_free_check;
+#endif
+ /* kmem_cache corresponding to this list */
+ struct kmem_cache *cache;
+
+ /* Number of partial slabs (pages) */
+ unsigned long nr_partial;
+
+ /* Slabs which have some free objects */
+ struct list_head partial;
+
+ /* Total number of slabs allocated */
+ unsigned long nr_slabs;
+
+ /* Protects nr_partial, nr_slabs, and partial */
+ spinlock_t page_lock;
+
+#ifdef CONFIG_SMP
+ /*
+ * In the case of per-cpu lists, remote_free is for objects freed by
+ * non-owner CPU back to its home list. For per-node lists, remote_free
+ * is always used to free objects.
+ */
+ struct kmem_cache_remote_free remote_free;
+#endif
+
+#ifdef CONFIG_SLQB_STATS
+ unsigned long stats[NR_SLQB_STAT_ITEMS];
+#endif
+} ____cacheline_aligned;
+
+/*
+ * Primary per-cpu, per-kmem_cache structure.
+ */
+struct kmem_cache_cpu {
+ struct kmem_cache_list list; /* List for node-local slabs */
+ unsigned int colour_next; /* Next colour offset to use */
+
+#ifdef CONFIG_SMP
+ /*
+ * rlist is a list of objects that don't fit on list.freelist (ie.
+ * wrong node). The objects all correspond to a given kmem_cache_list,
+ * remote_cache_list. To free objects to another list, we must first
+ * flush the existing objects, then switch remote_cache_list.
+ *
+ * An NR_CPUS or MAX_NUMNODES array would be nice here, but then we
+ * get to O(NR_CPUS^2) memory consumption situation.
+ */
+ struct kmlist rlist;
+ struct kmem_cache_list *remote_cache_list;
+#endif
+} ____cacheline_aligned_in_smp;
+
+/*
+ * Per-node, per-kmem_cache structure. Used for node-specific allocations.
+ */
+struct kmem_cache_node {
+ struct kmem_cache_list list;
+ spinlock_t list_lock; /* protects access to list */
+} ____cacheline_aligned;
+
+/*
+ * Management object for a slab cache.
+ */
+struct kmem_cache {
+ unsigned long flags;
+ int hiwater; /* LIFO list high watermark */
+ int freebatch; /* LIFO freelist batch flush size */
+#ifdef CONFIG_SMP
+ struct kmem_cache_cpu **cpu_slab; /* dynamic per-cpu structures */
+#else
+ struct kmem_cache_cpu cpu_slab;
+#endif
+ int objsize; /* Size of object without meta data */
+ int offset; /* Free pointer offset. */
+ int objects; /* Number of objects in slab */
+
+#ifdef CONFIG_NUMA
+ struct kmem_cache_node **node_slab; /* dynamic per-node structures */
+#endif
+
+ int size; /* Size of object including meta data */
+ int order; /* Allocation order */
+ gfp_t allocflags; /* gfp flags to use on allocation */
+ unsigned int colour_range; /* range of colour counter */
+ unsigned int colour_off; /* offset per colour */
+ void (*ctor)(void *);
+
+ const char *name; /* Name (only for display!) */
+ struct list_head list; /* List of slab caches */
+
+ int align; /* Alignment */
+ int inuse; /* Offset to metadata */
+
+#ifdef CONFIG_SLQB_SYSFS
+ struct kobject kobj; /* For sysfs */
+#endif
+} ____cacheline_aligned;
+
+/*
+ * Kmalloc subsystem.
+ */
+#if defined(ARCH_KMALLOC_MINALIGN) && ARCH_KMALLOC_MINALIGN > 8
+#define KMALLOC_MIN_SIZE ARCH_KMALLOC_MINALIGN
+#else
+#define KMALLOC_MIN_SIZE 8
+#endif
+
+#define KMALLOC_SHIFT_LOW ilog2(KMALLOC_MIN_SIZE)
+#define KMALLOC_SHIFT_SLQB_HIGH (PAGE_SHIFT + \
+ ((9 <= (MAX_ORDER - 1)) ? 9 : (MAX_ORDER - 1)))
+
+extern struct kmem_cache kmalloc_caches[KMALLOC_SHIFT_SLQB_HIGH + 1];
+extern struct kmem_cache kmalloc_caches_dma[KMALLOC_SHIFT_SLQB_HIGH + 1];
+
+/*
+ * Constant size allocations use this path to find index into kmalloc caches
+ * arrays. get_slab() function is used for non-constant sizes.
+ */
+static __always_inline int kmalloc_index(size_t size)
+{
+ if (unlikely(!size))
+ return 0;
+ if (unlikely(size > 1UL << KMALLOC_SHIFT_SLQB_HIGH))
+ return 0;
+
+ if (unlikely(size <= KMALLOC_MIN_SIZE))
+ return KMALLOC_SHIFT_LOW;
+
+#if L1_CACHE_BYTES < 64
+ if (size > 64 && size <= 96)
+ return 1;
+#endif
+#if L1_CACHE_BYTES < 128
+ if (size > 128 && size <= 192)
+ return 2;
+#endif
+ if (size <= 8) return 3;
+ if (size <= 16) return 4;
+ if (size <= 32) return 5;
+ if (size <= 64) return 6;
+ if (size <= 128) return 7;
+ if (size <= 256) return 8;
+ if (size <= 512) return 9;
+ if (size <= 1024) return 10;
+ if (size <= 2 * 1024) return 11;
+ if (size <= 4 * 1024) return 12;
+ if (size <= 8 * 1024) return 13;
+ if (size <= 16 * 1024) return 14;
+ if (size <= 32 * 1024) return 15;
+ 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 <= 1024 * 1024) return 20;
+ if (size <= 2 * 1024 * 1024) return 21;
+ return -1;
+}
+
+#ifdef CONFIG_ZONE_DMA
+#define SLQB_DMA __GFP_DMA
+#else
+/* Disable "DMA slabs" */
+#define SLQB_DMA (__force gfp_t)0
+#endif
+
+/*
+ * Find the kmalloc slab cache for a given combination of allocation flags and
+ * size. Should really only be used for constant 'size' arguments, due to
+ * bloat.
+ */
+static __always_inline struct kmem_cache *kmalloc_slab(size_t size, gfp_t flags)
+{
+ int index;
+
+ index = kmalloc_index(size);
+ if (unlikely(index == 0))
+ return ZERO_SIZE_PTR;
+
+ if (likely(!(flags & SLQB_DMA)))
+ return &kmalloc_caches[index];
+ else
+ return &kmalloc_caches_dma[index];
+}
+
+void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
+void *__kmalloc(size_t size, gfp_t flags);
+
+#ifndef ARCH_KMALLOC_MINALIGN
+#define ARCH_KMALLOC_MINALIGN __alignof__(unsigned long long)
+#endif
+
+#ifndef ARCH_SLAB_MINALIGN
+#define ARCH_SLAB_MINALIGN __alignof__(unsigned long long)
+#endif
+
+#define KMALLOC_HEADER (ARCH_KMALLOC_MINALIGN < sizeof(void *) ? \
+ sizeof(void *) : ARCH_KMALLOC_MINALIGN)
+
+static __always_inline void *kmalloc(size_t size, gfp_t flags)
+{
+ if (__builtin_constant_p(size)) {
+ struct kmem_cache *s;
+
+ s = kmalloc_slab(size, flags);
+ if (unlikely(ZERO_OR_NULL_PTR(s)))
+ return s;
+
+ return kmem_cache_alloc(s, flags);
+ }
+ return __kmalloc(size, flags);
+}
+
+#ifdef CONFIG_NUMA
+void *__kmalloc_node(size_t size, gfp_t flags, int node);
+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)) {
+ struct kmem_cache *s;
+
+ s = kmalloc_slab(size, flags);
+ if (unlikely(ZERO_OR_NULL_PTR(s)))
+ return s;
+
+ return kmem_cache_alloc_node(s, flags, node);
+ }
+ return __kmalloc_node(size, flags, node);
+}
+#endif
+
+#endif /* _LINUX_SLQB_DEF_H */
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index 5046f90c1171..be5d40c43bd2 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -10,7 +10,7 @@
#include <linux/gfp.h>
#include <linux/workqueue.h>
#include <linux/kobject.h>
-#include <trace/kmemtrace.h>
+#include <linux/kmemtrace.h>
enum stat_item {
ALLOC_FASTPATH, /* Allocation from cpu slab */
diff --git a/include/linux/spi/ads7846.h b/include/linux/spi/ads7846.h
index 05eab2f11e63..2ea20320c093 100644
--- a/include/linux/spi/ads7846.h
+++ b/include/linux/spi/ads7846.h
@@ -51,5 +51,6 @@ struct ads7846_platform_data {
void **filter_data);
int (*filter) (void *filter_data, int data_idx, int *val);
void (*filter_cleanup)(void *filter_data);
+ void (*wait_for_sync)(void);
};
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 2cc43fa380cb..a0faa18f7b1b 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -245,7 +245,12 @@ struct spi_master {
*/
u16 dma_alignment;
- /* setup mode and clock, etc (spi driver may call many times) */
+ /* Setup mode and clock, etc (spi driver may call many times).
+ *
+ * IMPORTANT: this may be called when transfers to another
+ * device are active. DO NOT UPDATE SHARED REGISTERS in ways
+ * which could break those transfers.
+ */
int (*setup)(struct spi_device *spi);
/* bidirectional bulk transfers
diff --git a/include/linux/splice.h b/include/linux/splice.h
index 528dcb93c2f2..5f3faa9d15ae 100644
--- a/include/linux/splice.h
+++ b/include/linux/splice.h
@@ -36,6 +36,8 @@ struct splice_desc {
void *data; /* cookie */
} u;
loff_t pos; /* file position */
+ size_t num_spliced; /* number of bytes already spliced */
+ bool need_wakeup; /* need to wake up writer */
};
struct partial_page {
@@ -66,6 +68,16 @@ extern ssize_t splice_from_pipe(struct pipe_inode_info *, struct file *,
splice_actor *);
extern ssize_t __splice_from_pipe(struct pipe_inode_info *,
struct splice_desc *, splice_actor *);
+extern int splice_from_pipe_feed(struct pipe_inode_info *, struct splice_desc *,
+ splice_actor *);
+extern int splice_from_pipe_next(struct pipe_inode_info *,
+ struct splice_desc *);
+extern void splice_from_pipe_begin(struct splice_desc *);
+extern void splice_from_pipe_end(struct pipe_inode_info *,
+ struct splice_desc *);
+extern int pipe_to_file(struct pipe_inode_info *, struct pipe_buffer *,
+ struct splice_desc *);
+
extern ssize_t splice_to_pipe(struct pipe_inode_info *,
struct splice_pipe_desc *);
extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *,
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index c39a21040dcb..37881f1a0bd7 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -143,6 +143,7 @@ int rpc_call_sync(struct rpc_clnt *clnt,
const struct rpc_message *msg, int flags);
struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred,
int flags);
+void rpc_restart_call_prepare(struct rpc_task *);
void rpc_restart_call(struct rpc_task *);
void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
size_t rpc_max_payload(struct rpc_clnt *);
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 64981a2f1cae..177376880fab 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -237,6 +237,7 @@ void rpc_show_tasks(void);
int rpc_init_mempool(void);
void rpc_destroy_mempool(void);
extern struct workqueue_struct *rpciod_workqueue;
+void rpc_prepare_task(struct rpc_task *task);
static inline void rpc_exit(struct rpc_task *task, int status)
{
diff --git a/include/linux/sunrpc/svc_xprt.h b/include/linux/sunrpc/svc_xprt.h
index 0d9cb6ef28b0..2223ae0b5ed5 100644
--- a/include/linux/sunrpc/svc_xprt.h
+++ b/include/linux/sunrpc/svc_xprt.h
@@ -83,7 +83,7 @@ int svc_port_is_privileged(struct sockaddr *sin);
int svc_print_xprts(char *buf, int maxlen);
struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name,
const sa_family_t af, const unsigned short port);
-int svc_xprt_names(struct svc_serv *serv, char *buf, int buflen);
+int svc_xprt_names(struct svc_serv *serv, char *buf, const int buflen);
static inline void svc_xprt_get(struct svc_xprt *xprt)
{
@@ -118,7 +118,7 @@ static inline unsigned short svc_addr_port(const struct sockaddr *sa)
return 0;
}
-static inline size_t svc_addr_len(struct sockaddr *sa)
+static inline size_t svc_addr_len(const struct sockaddr *sa)
{
switch (sa->sa_family) {
case AF_INET:
@@ -126,7 +126,8 @@ static inline size_t svc_addr_len(struct sockaddr *sa)
case AF_INET6:
return sizeof(struct sockaddr_in6);
}
- return -EAFNOSUPPORT;
+
+ return 0;
}
static inline unsigned short svc_xprt_local_port(const struct svc_xprt *xprt)
diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
index 483e10380aae..827163138949 100644
--- a/include/linux/sunrpc/svcsock.h
+++ b/include/linux/sunrpc/svcsock.h
@@ -38,8 +38,11 @@ int svc_recv(struct svc_rqst *, long);
int svc_send(struct svc_rqst *);
void svc_drop(struct svc_rqst *);
void svc_sock_update_bufs(struct svc_serv *serv);
-int svc_sock_names(char *buf, struct svc_serv *serv, char *toclose);
-int svc_addsock(struct svc_serv *serv, int fd, char *name_return);
+int svc_sock_names(struct svc_serv *serv, char *buf,
+ const size_t buflen,
+ const char *toclose);
+int svc_addsock(struct svc_serv *serv, const int fd,
+ char *name_return, const size_t len);
void svc_init_xprt_sock(void);
void svc_cleanup_xprt_sock(void);
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 1758d9f5b5c3..08afe43118f4 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -261,6 +261,7 @@ void xprt_conditional_disconnect(struct rpc_xprt *xprt, unsigned int cookie);
#define XPRT_BINDING (5)
#define XPRT_CLOSING (6)
#define XPRT_CONNECTION_ABORT (7)
+#define XPRT_CONNECTION_CLOSE (8)
static inline void xprt_set_connected(struct rpc_xprt *xprt)
{
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 3e3a4364cbff..795032edfc46 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -58,10 +58,17 @@ typedef int __bitwise suspend_state_t;
* by @begin().
* @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).
+ * before device drivers' late suspend callbacks are executed. It returns
+ * 0 on success or a negative error code otherwise, in which case the
+ * system cannot enter the desired sleep state (@prepare_late(), @enter(),
+ * @wake(), and @finish() will not be called in that case).
+ *
+ * @prepare_late: Finish preparing the platform for entering the system sleep
+ * state indicated by @begin().
+ * @prepare_late is called before disabling nonboot CPUs and after
+ * device drivers' late suspend callbacks have been executed. It returns
+ * 0 on success or a negative error code otherwise, in which case the
+ * system cannot enter the desired sleep state (@enter() and @wake()).
*
* @enter: Enter the system sleep state indicated by @begin() or represented by
* the argument if @begin() is not implemented.
@@ -69,19 +76,26 @@ typedef int __bitwise suspend_state_t;
* 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).
+ * @wake: Called when the system has just left a sleep state, right after
+ * the nonboot CPUs have been enabled and before device drivers' early
+ * resume callbacks are executed.
+ * This callback is optional, but should be implemented by the platforms
+ * that implement @prepare_late(). If implemented, it is always called
+ * after @enter(), even if @enter() fails.
+ *
+ * @finish: Finish wake-up of the platform.
+ * @finish is called right prior to calling device drivers' regular suspend
+ * callbacks.
* 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).
+ * @enter() and @wake(), if implemented, even if any of them fails.
*
* @end: Called by the PM core right after resuming devices, to indicate to
* the platform that the system has returned to the working state or
* the transition to the sleep state has been aborted.
* This callback is optional, but should be implemented by the platforms
- * that implement @begin(), but platforms implementing @begin() should
- * also provide a @end() which cleans up transitions aborted before
+ * that implement @begin(). Accordingly, platforms implementing @begin()
+ * should also provide a @end() which cleans up transitions aborted before
* @enter().
*
* @recover: Recover the platform from a suspend failure.
@@ -93,7 +107,9 @@ struct platform_suspend_ops {
int (*valid)(suspend_state_t state);
int (*begin)(suspend_state_t state);
int (*prepare)(void);
+ int (*prepare_late)(void);
int (*enter)(suspend_state_t state);
+ void (*wake)(void);
void (*finish)(void);
void (*end)(void);
void (*recover)(void);
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index ac9ff54f7cb3..cb1a6631b8f4 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -29,7 +29,8 @@ extern void *swiotlb_alloc(unsigned order, unsigned long nslabs);
extern dma_addr_t swiotlb_phys_to_bus(struct device *hwdev,
phys_addr_t address);
-extern phys_addr_t swiotlb_bus_to_phys(dma_addr_t address);
+extern phys_addr_t swiotlb_bus_to_phys(struct device *hwdev,
+ dma_addr_t address);
extern int swiotlb_arch_range_needs_mapping(phys_addr_t paddr, size_t size);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index dabe4ad89141..40617c1d8976 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -148,7 +148,7 @@ struct old_linux_dirent;
asm ("\t.globl " #alias "\n\t.set " #alias ", " #name "\n" \
"\t.globl ." #alias "\n\t.set ." #alias ", ." #name)
#else
-#ifdef CONFIG_ALPHA
+#if defined(CONFIG_ALPHA) || defined(CONFIG_MIPS)
#define SYSCALL_ALIAS(alias, name) \
asm ( #alias " = " #name "\n\t.globl " #alias)
#else
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index e6b820f8b56b..a8cc4e13434c 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -21,13 +21,14 @@ struct restart_block {
struct {
unsigned long arg0, arg1, arg2, arg3;
};
- /* For futex_wait */
+ /* For futex_wait and futex_wait_requeue_pi */
struct {
u32 *uaddr;
u32 val;
u32 flags;
u32 bitset;
u64 time;
+ u32 *uaddr2;
} futex;
/* For nanosleep */
struct {
diff --git a/include/linux/time.h b/include/linux/time.h
index 242f62499bb7..ea16c1a01d51 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -113,6 +113,21 @@ struct timespec current_kernel_time(void);
#define CURRENT_TIME (current_kernel_time())
#define CURRENT_TIME_SEC ((struct timespec) { get_seconds(), 0 })
+/* Some architectures do not supply their own clocksource.
+ * This is mainly the case in architectures that get their
+ * inter-tick times by reading the counter on their interval
+ * timer. Since these timers wrap every tick, they're not really
+ * useful as clocksources. Wrapping them to act like one is possible
+ * but not very efficient. So we provide a callout these arches
+ * can implement for use with the jiffies clocksource to provide
+ * finer then tick granular time.
+ */
+#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
+extern u32 arch_gettimeoffset(void);
+#else
+static inline u32 arch_gettimeoffset(void) { return 0; }
+#endif
+
extern void do_gettimeofday(struct timeval *tv);
extern int do_settimeofday(struct timespec *tv);
extern int do_sys_settimeofday(struct timespec *tv, struct timezone *tz);
diff --git a/include/linux/timex.h b/include/linux/timex.h
index aa3475fcff64..0daf9611ef4f 100644
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -170,17 +170,37 @@ struct timex {
#include <asm/timex.h>
/*
- * SHIFT_KG and SHIFT_KF establish the damping of the PLL and are chosen
- * for a slightly underdamped convergence characteristic. SHIFT_KH
- * establishes the damping of the FLL and is chosen by wisdom and black
- * art.
+ * SHIFT_PLL is used as a dampening factor to define how much we
+ * adjust the frequency correction for a given offset in PLL mode.
+ * It also used in dampening the offset correction, to define how
+ * much of the current value in time_offset we correct for each
+ * second. Changing this value changes the stiffness of the ntp
+ * adjustment code. A lower value makes it more flexible, reducing
+ * NTP convergence time. A higher value makes it stiffer, increasing
+ * convergence time, but making the clock more stable.
*
- * MAXTC establishes the maximum time constant of the PLL. With the
- * SHIFT_KG and SHIFT_KF values given and a time constant range from
- * zero to MAXTC, the PLL will converge in 15 minutes to 16 hours,
- * respectively.
+ * In David Mills' nanokenrel reference implmentation SHIFT_PLL is 4.
+ * However this seems to increase convergence time much too long.
+ *
+ * https://lists.ntp.org/pipermail/hackers/2008-January/003487.html
+ *
+ * In the above mailing list discussion, it seems the value of 4
+ * was appropriate for other Unix systems with HZ=100, and that
+ * SHIFT_PLL should be decreased as HZ increases. However, Linux's
+ * clock steering implementation is HZ independent.
+ *
+ * Through experimentation, a SHIFT_PLL value of 2 was found to allow
+ * for fast convergence (very similar to the NTPv3 code used prior to
+ * v2.6.19), with good clock stability.
+ *
+ *
+ * SHIFT_FLL is used as a dampening factor to define how much we
+ * adjust the frequency correction for a given offset in FLL mode.
+ * In David Mills' nanokenrel reference implmentation SHIFT_PLL is 2.
+ *
+ * MAXTC establishes the maximum time constant of the PLL.
*/
-#define SHIFT_PLL 4 /* PLL frequency factor (shift) */
+#define SHIFT_PLL 2 /* PLL frequency factor (shift) */
#define SHIFT_FLL 2 /* FLL frequency factor (shift) */
#define MAXTC 10 /* maximum time constant (shift) */
@@ -192,10 +212,10 @@ struct timex {
#define SHIFT_USEC 16 /* frequency offset scale (shift) */
#define PPM_SCALE ((s64)NSEC_PER_USEC << (NTP_SCALE_SHIFT - SHIFT_USEC))
#define PPM_SCALE_INV_SHIFT 19
-#define PPM_SCALE_INV ((1ll << (PPM_SCALE_INV_SHIFT + NTP_SCALE_SHIFT)) / \
+#define PPM_SCALE_INV ((1LL << (PPM_SCALE_INV_SHIFT + NTP_SCALE_SHIFT)) / \
PPM_SCALE + 1)
-#define MAXPHASE 500000000l /* max phase error (ns) */
+#define MAXPHASE 500000000L /* max phase error (ns) */
#define MAXFREQ 500000 /* max frequency error (ns/s) */
#define MAXFREQ_SCALED ((s64)MAXFREQ << NTP_SCALE_SHIFT)
#define MINSEC 256 /* min interval between updates (s) */
diff --git a/include/linux/trace_seq.h b/include/linux/trace_seq.h
new file mode 100644
index 000000000000..ba9627f00d3f
--- /dev/null
+++ b/include/linux/trace_seq.h
@@ -0,0 +1,90 @@
+#ifndef _LINUX_TRACE_SEQ_H
+#define _LINUX_TRACE_SEQ_H
+
+#include <linux/fs.h>
+
+/*
+ * Trace sequences are used to allow a function to call several other functions
+ * to create a string of data to use (up to a max of PAGE_SIZE.
+ */
+
+struct trace_seq {
+ unsigned char buffer[PAGE_SIZE];
+ unsigned int len;
+ unsigned int readpos;
+};
+
+static inline void
+trace_seq_init(struct trace_seq *s)
+{
+ s->len = 0;
+ s->readpos = 0;
+}
+
+/*
+ * Currently only defined when tracing is enabled.
+ */
+#ifdef CONFIG_TRACING
+extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+extern int
+trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary);
+extern void trace_print_seq(struct seq_file *m, struct trace_seq *s);
+extern ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf,
+ size_t cnt);
+extern int trace_seq_puts(struct trace_seq *s, const char *str);
+extern int trace_seq_putc(struct trace_seq *s, unsigned char c);
+extern int trace_seq_putmem(struct trace_seq *s, const void *mem, size_t len);
+extern int trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
+ size_t len);
+extern void *trace_seq_reserve(struct trace_seq *s, size_t len);
+extern int trace_seq_path(struct trace_seq *s, struct path *path);
+
+#else /* CONFIG_TRACING */
+static inline int trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
+{
+ return 0;
+}
+static inline int
+trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary)
+{
+ return 0;
+}
+
+static inline void trace_print_seq(struct seq_file *m, struct trace_seq *s)
+{
+}
+static inline ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf,
+ size_t cnt)
+{
+ return 0;
+}
+static inline int trace_seq_puts(struct trace_seq *s, const char *str)
+{
+ return 0;
+}
+static inline int trace_seq_putc(struct trace_seq *s, unsigned char c)
+{
+ return 0;
+}
+static inline int
+trace_seq_putmem(struct trace_seq *s, const void *mem, size_t len)
+{
+ return 0;
+}
+static inline int trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
+ size_t len)
+{
+ return 0;
+}
+static inline void *trace_seq_reserve(struct trace_seq *s, size_t len)
+{
+ return NULL;
+}
+static inline int trace_seq_path(struct trace_seq *s, struct path *path)
+{
+ return 0;
+}
+#endif /* CONFIG_TRACING */
+
+#endif /* _LINUX_TRACE_SEQ_H */
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index d35a7ee7611f..14df7e635d43 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -31,6 +31,8 @@ struct tracepoint {
* Keep in sync with vmlinux.lds.h.
*/
+#ifndef DECLARE_TRACE
+
#define TP_PROTO(args...) args
#define TP_ARGS(args...) args
@@ -114,6 +116,7 @@ static inline void tracepoint_update_probe_range(struct tracepoint *begin,
struct tracepoint *end)
{ }
#endif /* CONFIG_TRACEPOINTS */
+#endif /* DECLARE_TRACE */
/*
* Connect a probe to a tracepoint.
@@ -154,10 +157,8 @@ static inline void tracepoint_synchronize_unregister(void)
}
#define PARAMS(args...) args
-#define TRACE_FORMAT(name, proto, args, fmt) \
- DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
-
+#ifndef TRACE_EVENT
/*
* For use with the TRACE_EVENT macro:
*
@@ -262,5 +263,6 @@ static inline void tracepoint_synchronize_unregister(void)
#define TRACE_EVENT(name, proto, args, struct, assign, print) \
DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
+#endif
#endif
diff --git a/include/linux/tty.h b/include/linux/tty.h
index fc39db95499f..bed5a3d40307 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -185,7 +185,7 @@ struct tty_port;
struct tty_port_operations {
/* Return 1 if the carrier is raised */
int (*carrier_raised)(struct tty_port *port);
- void (*raise_dtr_rts)(struct tty_port *port);
+ void (*dtr_rts)(struct tty_port *port, int raise);
};
struct tty_port {
@@ -201,6 +201,9 @@ struct tty_port {
unsigned char *xmit_buf; /* Optional buffer */
int close_delay; /* Close port delay */
int closing_wait; /* Delay for output */
+ int drain_delay; /* Set to zero if no pure time
+ based drain is needed else
+ set to size of fifo */
};
/*
@@ -438,6 +441,7 @@ extern struct tty_struct *tty_port_tty_get(struct tty_port *port);
extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty);
extern int tty_port_carrier_raised(struct tty_port *port);
extern void tty_port_raise_dtr_rts(struct tty_port *port);
+extern void tty_port_lower_dtr_rts(struct tty_port *port);
extern void tty_port_hangup(struct tty_port *port);
extern int tty_port_block_til_ready(struct tty_port *port,
struct tty_struct *tty, struct file *filp);
diff --git a/include/linux/ultrasound.h b/include/linux/ultrasound.h
index 6b7703e75cec..71339dc531c5 100644
--- a/include/linux/ultrasound.h
+++ b/include/linux/ultrasound.h
@@ -34,7 +34,7 @@
* _GUS_VOICEOFF - Stops voice (no parameters)
* _GUS_VOICEFADE - Stops the voice smoothly.
* _GUS_VOICEMODE - Alters the voice mode, don't start or stop voice (P1=voice mode)
- * _GUS_VOICEBALA - Sets voice balence (P1, 0=left, 7=middle and 15=right, default 7)
+ * _GUS_VOICEBALA - Sets voice balance (P1, 0=left, 7=middle and 15=right, default 7)
* _GUS_VOICEFREQ - Sets voice (sample) playback frequency (P1=Hz)
* _GUS_VOICEVOL - Sets voice volume (P1=volume, 0xfff=max, 0xeff=half, 0x000=off)
* _GUS_VOICEVOL2 - Sets voice volume (P1=volume, 0xfff=max, 0xeff=half, 0x000=off)
diff --git a/include/linux/usb.h b/include/linux/usb.h
index c6b2ab41b908..3aa2cd1f8d08 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1387,6 +1387,7 @@ extern int usb_string(struct usb_device *dev, int index,
extern int usb_clear_halt(struct usb_device *dev, int pipe);
extern int usb_reset_configuration(struct usb_device *dev);
extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
+extern void usb_reset_endpoint(struct usb_device *dev, unsigned int epaddr);
/* this request isn't really synchronous, but it belongs with the others */
extern int usb_driver_set_configuration(struct usb_device *udev, int config);
@@ -1491,14 +1492,6 @@ void usb_sg_wait(struct usb_sg_request *io);
#define usb_pipecontrol(pipe) (usb_pipetype((pipe)) == PIPE_CONTROL)
#define usb_pipebulk(pipe) (usb_pipetype((pipe)) == PIPE_BULK)
-/* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */
-#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1)
-#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << (ep)))
-#define usb_settoggle(dev, ep, out, bit) \
- ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | \
- ((bit) << (ep)))
-
-
static inline unsigned int __create_pipe(struct usb_device *dev,
unsigned int endpoint)
{
diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h
index d6aad0ea6033..d43755669261 100644
--- a/include/linux/usb/musb.h
+++ b/include/linux/usb/musb.h
@@ -7,6 +7,9 @@
* key configuration differences between boards.
*/
+#ifndef __LINUX_USB_MUSB_H
+#define __LINUX_USB_MUSB_H
+
/* The USB role is defined by the connector used on the board, so long as
* standards are being followed. (Developer boards sometimes won't.)
*/
@@ -101,3 +104,5 @@ extern int __init tusb6010_setup_interface(
extern int tusb6010_platform_retime(unsigned is_refclk);
#endif /* OMAP2 */
+
+#endif /* __LINUX_USB_MUSB_H */
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index b95842542590..8cdfed738fe4 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -29,7 +29,7 @@
/**
* usb_serial_port: structure for the specific ports of a device.
* @serial: pointer back to the struct usb_serial owner of this port.
- * @tty: pointer to the corresponding tty for this port.
+ * @port: pointer to the corresponding tty_port for this port.
* @lock: spinlock to grab when updating portions of this structure.
* @mutex: mutex used to synchronize serial_open() and serial_close()
* access for this port.
@@ -44,19 +44,22 @@
* @interrupt_out_endpointAddress: endpoint address for the interrupt out pipe
* for this port.
* @bulk_in_buffer: pointer to the bulk in buffer for this port.
+ * @bulk_in_size: the size of the bulk_in_buffer, in bytes.
* @read_urb: pointer to the bulk in struct urb for this port.
* @bulk_in_endpointAddress: endpoint address for the bulk in pipe for this
* port.
* @bulk_out_buffer: pointer to the bulk out buffer for this port.
* @bulk_out_size: the size of the bulk_out_buffer, in bytes.
* @write_urb: pointer to the bulk out struct urb for this port.
+ * @write_urb_busy: port`s writing status
* @bulk_out_endpointAddress: endpoint address for the bulk out pipe for this
* port.
* @write_wait: a wait_queue_head_t used by the port.
* @work: work queue entry for the line discipline waking up.
- * @open_count: number of times this port has been opened.
* @throttled: nonzero if the read urb is inactive to throttle the device
* @throttle_req: nonzero if the tty wants to throttle us
+ * @console: attached usb serial console
+ * @dev: pointer to the serial device
*
* This structure is used by the usb-serial core and drivers for the specific
* ports of a device.
@@ -221,8 +224,7 @@ struct usb_serial_driver {
/* Called by console with tty = NULL and by tty */
int (*open)(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
- void (*close)(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp);
+ void (*close)(struct usb_serial_port *port);
int (*write)(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
/* Called only by the tty layer */
@@ -238,6 +240,10 @@ struct usb_serial_driver {
int (*tiocmget)(struct tty_struct *tty, struct file *file);
int (*tiocmset)(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
+ /* Called by the tty layer for port level work. There may or may not
+ be an attached tty at this point */
+ void (*dtr_rts)(struct usb_serial_port *port, int on);
+ int (*carrier_raised)(struct usb_serial_port *port);
/* USB events */
void (*read_int_callback)(struct urb *urb);
void (*write_int_callback)(struct urb *urb);
@@ -280,8 +286,7 @@ extern int usb_serial_generic_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
extern int usb_serial_generic_write(struct tty_struct *tty,
struct usb_serial_port *port, const unsigned char *buf, int count);
-extern void usb_serial_generic_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp);
+extern void usb_serial_generic_close(struct usb_serial_port *port);
extern int usb_serial_generic_resume(struct usb_serial *serial);
extern int usb_serial_generic_write_room(struct tty_struct *tty);
extern int usb_serial_generic_chars_in_buffer(struct tty_struct *tty);
diff --git a/include/linux/wait.h b/include/linux/wait.h
index bc024632f365..6788e1a4d4ca 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -132,8 +132,6 @@ static inline void __remove_wait_queue(wait_queue_head_t *head,
list_del(&old->task_list);
}
-void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
- int nr_exclusive, int sync, void *key);
void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr, void *key);
void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, void *key);
void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode, int nr,
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 9c1ed1fb6ddb..943d1c9fca9b 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -79,7 +79,6 @@ struct writeback_control {
void writeback_inodes(struct writeback_control *wbc);
int inode_wait(void *);
void sync_inodes_sb(struct super_block *, int wait);
-void sync_inodes(int wait);
/* writeback.h requires fs.h; it, too, is not included from here. */
static inline void wait_on_inode(struct inode *inode)
diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h
index 07963d705400..3ad4ed5402fb 100644
--- a/include/media/ir-kbd-i2c.h
+++ b/include/media/ir-kbd-i2c.h
@@ -7,7 +7,7 @@ struct IR_i2c;
struct IR_i2c {
IR_KEYTAB_TYPE *ir_codes;
- struct i2c_client c;
+ struct i2c_client *c;
struct input_dev *input;
struct ir_input_state ir;
@@ -15,7 +15,15 @@ struct IR_i2c {
unsigned char old;
struct delayed_work work;
+ char name[32];
char phys[32];
int (*get_key)(struct IR_i2c*, u32*, u32*);
};
+
+/* Can be passed when instantiating an ir_video i2c device */
+struct IR_i2c_init_data {
+ IR_KEYTAB_TYPE *ir_codes;
+ const char *name;
+ int (*get_key)(struct IR_i2c*, u32*, u32*);
+};
#endif
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index 37013688af44..23ecead35e7a 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -60,7 +60,7 @@ struct soc_camera_file {
struct soc_camera_host {
struct list_head list;
- struct device dev;
+ struct device *dev;
unsigned char nr; /* Host number */
void *priv;
const char *drv_name;
@@ -92,11 +92,16 @@ struct soc_camera_host_ops {
#define SOCAM_SENSOR_INVERT_VSYNC (1 << 3)
#define SOCAM_SENSOR_INVERT_DATA (1 << 4)
+struct i2c_board_info;
+
struct soc_camera_link {
/* Camera bus id, used to match a camera and a bus */
int bus_id;
/* Per camera SOCAM_SENSOR_* bus flags */
unsigned long flags;
+ int i2c_adapter_id;
+ struct i2c_board_info *board_info;
+ const char *module_name;
/* Optional callbacks to power on or off and reset the sensor */
int (*power)(struct device *, int);
int (*reset)(struct device *);
@@ -107,6 +112,7 @@ struct soc_camera_link {
*/
int (*set_bus_param)(struct soc_camera_link *, unsigned long flags);
unsigned long (*query_bus_param)(struct soc_camera_link *);
+ void (*free_bus)(struct soc_camera_link *);
};
static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev)
@@ -116,7 +122,7 @@ static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev)
static inline struct soc_camera_host *to_soc_camera_host(struct device *dev)
{
- return container_of(dev, struct soc_camera_host, dev);
+ return dev_get_drvdata(dev);
}
extern int soc_camera_host_register(struct soc_camera_host *ici);
diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h
index 0dd3e8e8653e..5d5d550e63ad 100644
--- a/include/media/v4l2-device.h
+++ b/include/media/v4l2-device.h
@@ -30,7 +30,7 @@
basic V4L2 device-level support.
*/
-#define V4L2_DEVICE_NAME_SIZE (BUS_ID_SIZE + 16)
+#define V4L2_DEVICE_NAME_SIZE (20 + 16)
struct v4l2_device {
/* dev->driver_data points to this struct.
@@ -53,10 +53,31 @@ struct v4l2_device {
dev may be NULL in rare cases (ISA devices). In that case you
must fill in the v4l2_dev->name field before calling this function. */
int __must_check v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev);
+
+/* Optional function to initialize the name field of struct v4l2_device using
+ the driver name and a driver-global atomic_t instance.
+ This function will increment the instance counter and returns the instance
+ value used in the name.
+
+ Example:
+
+ static atomic_t drv_instance = ATOMIC_INIT(0);
+
+ ...
+
+ instance = v4l2_device_set_name(&v4l2_dev, "foo", &drv_instance);
+
+ The first time this is called the name field will be set to foo0 and
+ this function returns 0. If the name ends with a digit (e.g. cx18),
+ then the name will be set to cx18-0 since cx180 looks really odd. */
+int v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename,
+ atomic_t *instance);
+
/* Set v4l2_dev->dev to NULL. Call when the USB parent disconnects.
Since the parent disappears this ensures that v4l2_dev doesn't have an
invalid parent pointer. */
void v4l2_device_disconnect(struct v4l2_device *v4l2_dev);
+
/* Unregister all sub-devices and any other resources related to v4l2_dev. */
void v4l2_device_unregister(struct v4l2_device *v4l2_dev);
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 17856081c809..a503e1cee78b 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -230,12 +230,16 @@ struct v4l2_subdev_ops {
#define V4L2_SUBDEV_NAME_SIZE 32
+/* Set this flag if this subdev is a i2c device. */
+#define V4L2_SUBDEV_FL_IS_I2C (1U << 0)
+
/* Each instance of a subdev driver should create this struct, either
stand-alone or embedded in a larger struct.
*/
struct v4l2_subdev {
struct list_head list;
struct module *owner;
+ u32 flags;
struct v4l2_device *v4l2_dev;
const struct v4l2_subdev_ops *ops;
/* name must be unique */
@@ -264,6 +268,7 @@ static inline void v4l2_subdev_init(struct v4l2_subdev *sd,
BUG_ON(!ops || !ops->core);
sd->ops = ops;
sd->v4l2_dev = NULL;
+ sd->flags = 0;
sd->name[0] = '\0';
sd->grp_id = 0;
sd->priv = NULL;
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index 4012e07162e5..e26812274b75 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -98,7 +98,6 @@ enum p9_req_status_t {
struct p9_req_t {
int status;
int t_err;
- u16 flush_tag;
wait_queue_head_t *wq;
struct p9_fcall *tc;
struct p9_fcall *rc;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index b8a76764e1c5..e69e6c66dd16 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -672,6 +672,7 @@ struct cfg80211_auth_request {
* @ssid_len: Length of ssid in octets
* @ie: Extra IEs to add to (Re)Association Request frame or %NULL
* @ie_len: Length of ie buffer in octets
+ * @use_mfp: Use management frame protection (IEEE 802.11w) in this association
*/
struct cfg80211_assoc_request {
struct ieee80211_channel *chan;
@@ -680,6 +681,7 @@ struct cfg80211_assoc_request {
size_t ssid_len;
const u8 *ie;
size_t ie_len;
+ bool use_mfp;
};
/**
@@ -858,13 +860,13 @@ struct cfg80211_ops {
struct vif_params *params);
int (*add_key)(struct wiphy *wiphy, struct net_device *netdev,
- u8 key_index, u8 *mac_addr,
+ u8 key_index, const u8 *mac_addr,
struct key_params *params);
int (*get_key)(struct wiphy *wiphy, struct net_device *netdev,
- u8 key_index, u8 *mac_addr, void *cookie,
+ u8 key_index, const u8 *mac_addr, void *cookie,
void (*callback)(void *cookie, struct key_params*));
int (*del_key)(struct wiphy *wiphy, struct net_device *netdev,
- u8 key_index, u8 *mac_addr);
+ u8 key_index, const u8 *mac_addr);
int (*set_default_key)(struct wiphy *wiphy,
struct net_device *netdev,
u8 key_index);
@@ -1145,8 +1147,11 @@ struct wireless_dev {
#ifdef CONFIG_WIRELESS_EXT
/* wext data */
- struct cfg80211_ibss_params wext;
- u8 wext_bssid[ETH_ALEN];
+ struct {
+ struct cfg80211_ibss_params ibss;
+ u8 bssid[ETH_ALEN];
+ s8 default_key, default_mgmt_key;
+ } wext;
#endif
};
@@ -1396,6 +1401,15 @@ int cfg80211_wext_siwretry(struct net_device *dev,
int cfg80211_wext_giwretry(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *retry, char *extra);
+int cfg80211_wext_siwencodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *erq, char *extra);
+int cfg80211_wext_siwencode(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *erq, char *keybuf);
+int cfg80211_wext_giwencode(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *erq, char *keybuf);
/*
* callbacks for asynchronous cfg80211 methods, notification
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 38dc1cd10270..d10ed1776fcd 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -73,22 +73,6 @@
*/
/**
- * struct ieee80211_ht_bss_info - describing BSS's HT characteristics
- *
- * This structure describes most essential parameters needed
- * to describe 802.11n HT characteristics in a BSS.
- *
- * @primary_channel: channel number of primery channel
- * @bss_cap: 802.11n's general BSS capabilities (e.g. channel width)
- * @bss_op_mode: 802.11n's BSS operation modes (e.g. HT protection)
- */
-struct ieee80211_ht_bss_info {
- u8 primary_channel;
- u8 bss_cap; /* use IEEE80211_HT_IE_CHA_ */
- u8 bss_op_mode; /* use IEEE80211_HT_IE_ */
-};
-
-/**
* enum ieee80211_max_queues - maximum number of queues
*
* @IEEE80211_MAX_QUEUES: Maximum number of regular device queues.
@@ -171,14 +155,6 @@ enum ieee80211_bss_change {
};
/**
- * struct ieee80211_bss_ht_conf - BSS's changing HT configuration
- * @operation_mode: HT operation mode (like in &struct ieee80211_ht_info)
- */
-struct ieee80211_bss_ht_conf {
- u16 operation_mode;
-};
-
-/**
* struct ieee80211_bss_conf - holds the BSS's changing parameters
*
* This structure keeps information about a BSS (and an association
@@ -203,6 +179,8 @@ struct ieee80211_bss_ht_conf {
* the current band.
* @bssid: The BSSID for this BSS
* @enable_beacon: whether beaconing should be enabled or not
+ * @ht_operation_mode: HT operation mode (like in &struct ieee80211_ht_info).
+ * This field is only valid when the channel type is one of the HT types.
*/
struct ieee80211_bss_conf {
const u8 *bssid;
@@ -219,7 +197,7 @@ struct ieee80211_bss_conf {
u16 assoc_capability;
u64 timestamp;
u32 basic_rates;
- struct ieee80211_bss_ht_conf ht;
+ u16 ht_operation_mode;
};
/**
diff --git a/include/scsi/Kbuild b/include/scsi/Kbuild
new file mode 100644
index 000000000000..33b2750e9283
--- /dev/null
+++ b/include/scsi/Kbuild
@@ -0,0 +1,4 @@
+header-y += scsi.h
+header-y += scsi_netlink.h
+header-y += scsi_netlink_fc.h
+header-y += scsi_bsg_fc.h
diff --git a/include/scsi/fc/fc_fs.h b/include/scsi/fc/fc_fs.h
index 1b7af3a64c7c..ac4cd38c860e 100644
--- a/include/scsi/fc/fc_fs.h
+++ b/include/scsi/fc/fc_fs.h
@@ -149,6 +149,7 @@ enum fc_rctl {
* Well-known fabric addresses.
*/
enum fc_well_known_fid {
+ FC_FID_NONE = 0x000000, /* No destination */
FC_FID_BCAST = 0xffffff, /* broadcast */
FC_FID_FLOGI = 0xfffffe, /* fabric login */
FC_FID_FCTRL = 0xfffffd, /* fabric controller */
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 0303a6a098cc..45f9cc642c46 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -637,6 +637,7 @@ struct fc_disc {
enum fc_disc_event);
struct list_head rports;
+ struct list_head rogue_rports;
struct fc_lport *lport;
struct mutex disc_mutex;
struct fc_gpn_ft_resp partial_buf; /* partial name buffer */
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index 7ffaed2f94dd..0289f5745fb9 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -36,6 +36,7 @@ struct scsi_transport_template;
struct scsi_host_template;
struct scsi_device;
struct Scsi_Host;
+struct scsi_target;
struct scsi_cmnd;
struct socket;
struct iscsi_transport;
@@ -350,6 +351,7 @@ extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
bool xmit_can_sleep);
extern void iscsi_host_remove(struct Scsi_Host *shost);
extern void iscsi_host_free(struct Scsi_Host *shost);
+extern int iscsi_target_alloc(struct scsi_target *starget);
/*
* session management
diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
index cd3cbf764650..62b2ab8c69d4 100644
--- a/include/scsi/osd_protocol.h
+++ b/include/scsi/osd_protocol.h
@@ -24,17 +24,18 @@ enum {
OSDv1_ADDITIONAL_CDB_LENGTH = 192,
OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
OSDv1_CAP_LEN = 80,
+
/* Latest supported version */
-/* OSD_ADDITIONAL_CDB_LENGTH = 216,*/
+ OSDv2_ADDITIONAL_CDB_LENGTH = 228,
OSD_ADDITIONAL_CDB_LENGTH =
- OSDv1_ADDITIONAL_CDB_LENGTH, /* FIXME: Pete rev-001 sup */
+ OSDv2_ADDITIONAL_CDB_LENGTH,
OSD_TOTAL_CDB_LEN = OSD_ADDITIONAL_CDB_LENGTH + 8,
-/* OSD_CAP_LEN = 104,*/
- OSD_CAP_LEN = OSDv1_CAP_LEN,/* FIXME: Pete rev-001 sup */
+ OSD_CAP_LEN = 104,
OSD_SYSTEMID_LEN = 20,
- OSD_CRYPTO_KEYID_SIZE = 20,
- /*FIXME: OSDv2_CRYPTO_KEYID_SIZE = 32,*/
+ OSDv1_CRYPTO_KEYID_SIZE = 20,
+ OSDv2_CRYPTO_KEYID_SIZE = 32,
+ OSD_CRYPTO_KEYID_SIZE = OSDv2_CRYPTO_KEYID_SIZE,
OSD_CRYPTO_SEED_SIZE = 4,
OSD_CRYPTO_NONCE_SIZE = 12,
OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */
@@ -164,7 +165,11 @@ struct osd_cdb_head {
/* called allocation_length in some commands */
/*32*/ __be64 length;
/*40*/ __be64 start_address;
-/*48*/ __be32 list_identifier;/* Rarely used */
+ union {
+/*48*/ __be32 list_identifier;/* Rarely used */
+ /* OSD2r05 5.2.5 CDB continuation length */
+/*48*/ __be32 cdb_continuation_length;
+ };
} __packed v2;
};
/*52*/ union { /* selected attributes mode Page/List/Single */
@@ -204,29 +209,40 @@ struct osd_cdb_head {
/*80*/
/*160 v1*/
-/*184 v2*/
-struct osd_security_parameters {
-/*160*/u8 integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
+struct osdv1_security_parameters {
+/*160*/u8 integrity_check_value[OSDv1_CRYPTO_KEYID_SIZE];
/*180*/u8 request_nonce[OSD_CRYPTO_NONCE_SIZE];
/*192*/osd_cdb_offset data_in_integrity_check_offset;
/*196*/osd_cdb_offset data_out_integrity_check_offset;
} __packed;
/*200 v1*/
-/*224 v2*/
-/* FIXME: osdv2_security_parameters */
+/*184 v2*/
+struct osdv2_security_parameters {
+/*184*/u8 integrity_check_value[OSDv2_CRYPTO_KEYID_SIZE];
+/*216*/u8 request_nonce[OSD_CRYPTO_NONCE_SIZE];
+/*228*/osd_cdb_offset data_in_integrity_check_offset;
+/*232*/osd_cdb_offset data_out_integrity_check_offset;
+} __packed;
+/*236 v2*/
+
+struct osd_security_parameters {
+ union {
+ struct osdv1_security_parameters v1;
+ struct osdv2_security_parameters v2;
+ };
+};
struct osdv1_cdb {
struct osd_cdb_head h;
u8 caps[OSDv1_CAP_LEN];
- struct osd_security_parameters sec_params;
+ struct osdv1_security_parameters sec_params;
} __packed;
struct osdv2_cdb {
struct osd_cdb_head h;
u8 caps[OSD_CAP_LEN];
- struct osd_security_parameters sec_params;
- /* FIXME: osdv2_security_parameters */
+ struct osdv2_security_parameters sec_params;
} __packed;
struct osd_cdb {
@@ -301,14 +317,25 @@ struct osd_attributes_list_attrid {
} __packed;
/*
+ * NOTE: v1: is not aligned.
+ */
+struct osdv1_attributes_list_element {
+ __be32 attr_page;
+ __be32 attr_id;
+ __be16 attr_bytes; /* valid bytes at attr_val without padding */
+ u8 attr_val[0];
+} __packed;
+
+/*
* osd2r03: 7.1.3.3 List entry format for retrieved attributes and
* for setting attributes
- * NOTE: v2 is 8-bytes aligned, v1 is not aligned.
+ * NOTE: v2 is 8-bytes aligned
*/
-struct osd_attributes_list_element {
+struct osdv2_attributes_list_element {
__be32 attr_page;
__be32 attr_id;
- __be16 attr_bytes;
+ u8 reserved[6];
+ __be16 attr_bytes; /* valid bytes at attr_val without padding */
u8 attr_val[0];
} __packed;
@@ -324,13 +351,13 @@ enum {
static inline unsigned osdv1_attr_list_elem_size(unsigned len)
{
- return ALIGN(len + sizeof(struct osd_attributes_list_element),
+ return ALIGN(len + sizeof(struct osdv1_attributes_list_element),
OSDv1_ATTRIBUTES_ELEM_ALIGN);
}
static inline unsigned osdv2_attr_list_elem_size(unsigned len)
{
- return ALIGN(len + sizeof(struct osd_attributes_list_element),
+ return ALIGN(len + sizeof(struct osdv2_attributes_list_element),
OSD_ATTRIBUTES_ELEM_ALIGN);
}
@@ -419,15 +446,35 @@ struct osd_data_out_integrity_info {
__be64 data_bytes;
__be64 set_attributes_bytes;
__be64 get_attributes_bytes;
- __be64 integrity_check_value;
+ __u8 integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
} __packed;
+/* Same osd_data_out_integrity_info is used for OSD2/OSD1. The only difference
+ * Is the sizeof the structure since in OSD1 the last array is smaller. Use
+ * below for version independent handling of this structure
+ */
+static inline int osd_data_out_integrity_info_sizeof(bool is_ver1)
+{
+ return sizeof(struct osd_data_out_integrity_info) -
+ (is_ver1 * (OSDv2_CRYPTO_KEYID_SIZE - OSDv1_CRYPTO_KEYID_SIZE));
+}
+
struct osd_data_in_integrity_info {
__be64 data_bytes;
__be64 retrieved_attributes_bytes;
- __be64 integrity_check_value;
+ __u8 integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
} __packed;
+/* Same osd_data_in_integrity_info is used for OSD2/OSD1. The only difference
+ * Is the sizeof the structure since in OSD1 the last array is smaller. Use
+ * below for version independent handling of this structure
+ */
+static inline int osd_data_in_integrity_info_sizeof(bool is_ver1)
+{
+ return sizeof(struct osd_data_in_integrity_info) -
+ (is_ver1 * (OSDv2_CRYPTO_KEYID_SIZE - OSDv1_CRYPTO_KEYID_SIZE));
+}
+
struct osd_timestamp {
u8 time[6]; /* number of milliseconds since 1/1/1970 UT (big endian) */
} __packed;
@@ -477,7 +524,7 @@ enum osd_capability_bit_masks {
OSD_SEC_CAP_NONE1 = BIT(8),
OSD_SEC_CAP_NONE2 = BIT(9),
- OSD_SEC_CAP_NONE3 = BIT(10),
+ OSD_SEC_GBL_REM = BIT(10), /*v2 only*/
OSD_SEC_CAP_QUERY = BIT(11), /*v2 only*/
OSD_SEC_CAP_M_OBJECT = BIT(12), /*v2 only*/
OSD_SEC_CAP_POL_SEC = BIT(13),
@@ -552,8 +599,7 @@ struct osdv1_capability {
struct osd_capability {
struct osd_capability_head h;
-/* struct osd_cap_object_descriptor od;*/
- struct osdv1_cap_object_descriptor od; /* FIXME: Pete rev-001 sup */
+ struct osd_cap_object_descriptor od;
} __packed;
/**
diff --git a/include/scsi/scsi_bsg_fc.h b/include/scsi/scsi_bsg_fc.h
new file mode 100644
index 000000000000..a4b233318179
--- /dev/null
+++ b/include/scsi/scsi_bsg_fc.h
@@ -0,0 +1,322 @@
+/*
+ * FC Transport BSG Interface
+ *
+ * Copyright (C) 2008 James Smart, Emulex 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
+ *
+ */
+
+#ifndef SCSI_BSG_FC_H
+#define SCSI_BSG_FC_H
+
+/*
+ * This file intended to be included by both kernel and user space
+ */
+
+#include <scsi/scsi.h>
+
+/*
+ * FC Transport SGIO v4 BSG Message Support
+ */
+
+/* Default BSG request timeout (in seconds) */
+#define FC_DEFAULT_BSG_TIMEOUT (10 * HZ)
+
+
+/*
+ * Request Message Codes supported by the FC Transport
+ */
+
+/* define the class masks for the message codes */
+#define FC_BSG_CLS_MASK 0xF0000000 /* find object class */
+#define FC_BSG_HST_MASK 0x80000000 /* fc host class */
+#define FC_BSG_RPT_MASK 0x40000000 /* fc rport class */
+
+ /* fc_host Message Codes */
+#define FC_BSG_HST_ADD_RPORT (FC_BSG_HST_MASK | 0x00000001)
+#define FC_BSG_HST_DEL_RPORT (FC_BSG_HST_MASK | 0x00000002)
+#define FC_BSG_HST_ELS_NOLOGIN (FC_BSG_HST_MASK | 0x00000003)
+#define FC_BSG_HST_CT (FC_BSG_HST_MASK | 0x00000004)
+#define FC_BSG_HST_VENDOR (FC_BSG_HST_MASK | 0x000000FF)
+
+ /* fc_rport Message Codes */
+#define FC_BSG_RPT_ELS (FC_BSG_RPT_MASK | 0x00000001)
+#define FC_BSG_RPT_CT (FC_BSG_RPT_MASK | 0x00000002)
+
+
+
+/*
+ * FC Address Identifiers in Message Structures :
+ *
+ * Whenever a command payload contains a FC Address Identifier
+ * (aka port_id), the value is effectively in big-endian
+ * order, thus the array elements are decoded as follows:
+ * element [0] is bits 23:16 of the FC Address Identifier
+ * element [1] is bits 15:8 of the FC Address Identifier
+ * element [2] is bits 7:0 of the FC Address Identifier
+ */
+
+
+/*
+ * FC Host Messages
+ */
+
+/* FC_BSG_HST_ADDR_PORT : */
+
+/* Request:
+ * This message requests the FC host to login to the remote port
+ * at the specified N_Port_Id. The remote port is to be enumerated
+ * with the transport upon completion of the login.
+ */
+struct fc_bsg_host_add_rport {
+ uint8_t reserved;
+
+ /* FC Address Identier of the remote port to login to */
+ uint8_t port_id[3];
+};
+
+/* Response:
+ * There is no additional response data - fc_bsg_reply->result is sufficient
+ */
+
+
+/* FC_BSG_HST_DEL_RPORT : */
+
+/* Request:
+ * This message requests the FC host to remove an enumerated
+ * remote port and to terminate the login to it.
+ *
+ * Note: The driver is free to reject this request if it desires to
+ * remain logged in with the remote port.
+ */
+struct fc_bsg_host_del_rport {
+ uint8_t reserved;
+
+ /* FC Address Identier of the remote port to logout of */
+ uint8_t port_id[3];
+};
+
+/* Response:
+ * There is no additional response data - fc_bsg_reply->result is sufficient
+ */
+
+
+/* FC_BSG_HST_ELS_NOLOGIN : */
+
+/* Request:
+ * This message requests the FC_Host to send an ELS to a specific
+ * N_Port_ID. The host does not need to log into the remote port,
+ * nor does it need to enumerate the rport for further traffic
+ * (although, the FC host is free to do so if it desires).
+ */
+struct fc_bsg_host_els {
+ /*
+ * ELS Command Code being sent (must be the same as byte 0
+ * of the payload)
+ */
+ uint8_t command_code;
+
+ /* FC Address Identier of the remote port to send the ELS to */
+ uint8_t port_id[3];
+};
+
+/* Response:
+ */
+/* fc_bsg_ctels_reply->status values */
+#define FC_CTELS_STATUS_OK 0x00000000
+#define FC_CTELS_STATUS_REJECT 0x00000001
+#define FC_CTELS_STATUS_P_RJT 0x00000002
+#define FC_CTELS_STATUS_F_RJT 0x00000003
+#define FC_CTELS_STATUS_P_BSY 0x00000004
+#define FC_CTELS_STATUS_F_BSY 0x00000006
+struct fc_bsg_ctels_reply {
+ /*
+ * Note: An ELS LS_RJT may be reported in 2 ways:
+ * a) A status of FC_CTELS_STATUS_OK is returned. The caller
+ * is to look into the ELS receive payload to determine
+ * LS_ACC or LS_RJT (by contents of word 0). The reject
+ * data will be in word 1.
+ * b) A status of FC_CTELS_STATUS_REJECT is returned, The
+ * rjt_data field will contain valid data.
+ *
+ * Note: ELS LS_ACC is determined by an FC_CTELS_STATUS_OK, and
+ * the receive payload word 0 indicates LS_ACC
+ * (e.g. value is 0x02xxxxxx).
+ *
+ * Note: Similarly, a CT Reject may be reported in 2 ways:
+ * a) A status of FC_CTELS_STATUS_OK is returned. The caller
+ * is to look into the CT receive payload to determine
+ * Accept or Reject (by contents of word 2). The reject
+ * data will be in word 3.
+ * b) A status of FC_CTELS_STATUS_REJECT is returned, The
+ * rjt_data field will contain valid data.
+ *
+ * Note: x_RJT/BSY status will indicae that the rjt_data field
+ * is valid and contains the reason/explanation values.
+ */
+ uint32_t status; /* See FC_CTELS_STATUS_xxx */
+
+ /* valid if status is not FC_CTELS_STATUS_OK */
+ struct {
+ uint8_t action; /* fragment_id for CT REJECT */
+ uint8_t reason_code;
+ uint8_t reason_explanation;
+ uint8_t vendor_unique;
+ } rjt_data;
+};
+
+
+/* FC_BSG_HST_CT : */
+
+/* Request:
+ * This message requests that a CT Request be performed with the
+ * indicated N_Port_ID. The driver is responsible for logging in with
+ * the fabric and/or N_Port_ID, etc as per FC rules. This request does
+ * not mandate that the driver must enumerate the destination in the
+ * transport. The driver is allowed to decide whether to enumerate it,
+ * and whether to tear it down after the request.
+ */
+struct fc_bsg_host_ct {
+ uint8_t reserved;
+
+ /* FC Address Identier of the remote port to send the ELS to */
+ uint8_t port_id[3];
+
+ /*
+ * We need words 0-2 of the generic preamble for the LLD's
+ */
+ uint32_t preamble_word0; /* revision & IN_ID */
+ uint32_t preamble_word1; /* GS_Type, GS_SubType, Options, Rsvd */
+ uint32_t preamble_word2; /* Cmd Code, Max Size */
+
+};
+/* Response:
+ *
+ * The reply structure is an fc_bsg_ctels_reply structure
+ */
+
+
+/* FC_BSG_HST_VENDOR : */
+
+/* Request:
+ * Note: When specifying vendor_id, be sure to read the Vendor Type and ID
+ * formatting requirements specified in scsi_netlink.h
+ */
+struct fc_bsg_host_vendor {
+ /*
+ * Identifies the vendor that the message is formatted for. This
+ * should be the recipient of the message.
+ */
+ uint64_t vendor_id;
+
+ /* start of vendor command area */
+ uint32_t vendor_cmd[0];
+};
+
+/* Response:
+ */
+struct fc_bsg_host_vendor_reply {
+ /* start of vendor response area */
+ uint32_t vendor_rsp[0];
+};
+
+
+
+/*
+ * FC Remote Port Messages
+ */
+
+/* FC_BSG_RPT_ELS : */
+
+/* Request:
+ * This message requests that an ELS be performed with the rport.
+ */
+struct fc_bsg_rport_els {
+ /*
+ * ELS Command Code being sent (must be the same as
+ * byte 0 of the payload)
+ */
+ uint8_t els_code;
+};
+
+/* Response:
+ *
+ * The reply structure is an fc_bsg_ctels_reply structure
+ */
+
+
+/* FC_BSG_RPT_CT : */
+
+/* Request:
+ * This message requests that a CT Request be performed with the rport.
+ */
+struct fc_bsg_rport_ct {
+ /*
+ * We need words 0-2 of the generic preamble for the LLD's
+ */
+ uint32_t preamble_word0; /* revision & IN_ID */
+ uint32_t preamble_word1; /* GS_Type, GS_SubType, Options, Rsvd */
+ uint32_t preamble_word2; /* Cmd Code, Max Size */
+};
+/* Response:
+ *
+ * The reply structure is an fc_bsg_ctels_reply structure
+ */
+
+
+
+
+/* request (CDB) structure of the sg_io_v4 */
+struct fc_bsg_request {
+ uint32_t msgcode;
+ union {
+ struct fc_bsg_host_add_rport h_addrport;
+ struct fc_bsg_host_del_rport h_delrport;
+ struct fc_bsg_host_els h_els;
+ struct fc_bsg_host_ct h_ct;
+ struct fc_bsg_host_vendor h_vendor;
+
+ struct fc_bsg_rport_els r_els;
+ struct fc_bsg_rport_ct r_ct;
+ } rqst_data;
+};
+
+
+/* response (request sense data) structure of the sg_io_v4 */
+struct fc_bsg_reply {
+ /*
+ * The completion result. Result exists in two forms:
+ * if negative, it is an -Exxx system errno value. There will
+ * be no further reply information supplied.
+ * else, it's the 4-byte scsi error result, with driver, host,
+ * msg and status fields. The per-msgcode reply structure
+ * will contain valid data.
+ */
+ uint32_t result;
+
+ /* If there was reply_payload, how much was recevied ? */
+ uint32_t reply_payload_rcv_len;
+
+ union {
+ struct fc_bsg_host_vendor_reply vendor_reply;
+
+ struct fc_bsg_ctels_reply ctels_reply;
+ } reply_data;
+};
+
+
+#endif /* SCSI_BSG_FC_H */
+
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index d123ca84e732..b62a097b3ecb 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -478,6 +478,15 @@ struct scsi_host_template {
* module_init/module_exit.
*/
struct list_head legacy_hosts;
+
+ /*
+ * Vendor Identifier associated with the host
+ *
+ * Note: When specifying vendor_id, be sure to read the
+ * Vendor Type and ID formatting requirements specified in
+ * scsi_netlink.h
+ */
+ u64 vendor_id;
};
/*
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index c9184f756cad..620db73889c1 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -33,7 +33,6 @@
struct scsi_transport_template;
-
/*
* FC Port definitions - Following FC HBAAPI guidelines
*
@@ -352,6 +351,7 @@ struct fc_rport { /* aka fc_starget_attrs */
struct delayed_work fail_io_work;
struct work_struct stgt_delete_work;
struct work_struct rport_delete_work;
+ struct request_queue *rqst_q; /* bsg support */
} __attribute__((aligned(sizeof(unsigned long))));
/* bit field values for struct fc_rport "flags" field: */
@@ -514,6 +514,9 @@ struct fc_host_attrs {
struct workqueue_struct *work_q;
char devloss_work_q_name[20];
struct workqueue_struct *devloss_work_q;
+
+ /* bsg support */
+ struct request_queue *rqst_q;
};
#define shost_to_fc_host(x) \
@@ -579,6 +582,47 @@ struct fc_host_attrs {
(((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q)
+struct fc_bsg_buffer {
+ unsigned int payload_len;
+ int sg_cnt;
+ struct scatterlist *sg_list;
+};
+
+/* Values for fc_bsg_job->state_flags (bitflags) */
+#define FC_RQST_STATE_INPROGRESS 0
+#define FC_RQST_STATE_DONE 1
+
+struct fc_bsg_job {
+ struct Scsi_Host *shost;
+ struct fc_rport *rport;
+ struct device *dev;
+ struct request *req;
+ spinlock_t job_lock;
+ unsigned int state_flags;
+ unsigned int ref_cnt;
+ void (*job_done)(struct fc_bsg_job *);
+
+ struct fc_bsg_request *request;
+ struct fc_bsg_reply *reply;
+ unsigned int request_len;
+ unsigned int reply_len;
+ /*
+ * On entry : reply_len indicates the buffer size allocated for
+ * the reply.
+ *
+ * Upon completion : the message handler must set reply_len
+ * to indicates the size of the reply to be returned to the
+ * caller.
+ */
+
+ /* DMA payloads for the request/response */
+ struct fc_bsg_buffer request_payload;
+ struct fc_bsg_buffer reply_payload;
+
+ void *dd_data; /* Used for driver-specific storage */
+};
+
+
/* The functions by which the transport class and the driver communicate */
struct fc_function_template {
void (*get_rport_dev_loss_tmo)(struct fc_rport *);
@@ -614,9 +658,14 @@ struct fc_function_template {
int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int);
int (* it_nexus_response)(struct Scsi_Host *, u64, int);
+ /* bsg support */
+ int (*bsg_request)(struct fc_bsg_job *);
+ int (*bsg_timeout)(struct fc_bsg_job *);
+
/* allocation lengths for host-specific data */
u32 dd_fcrport_size;
u32 dd_fcvport_size;
+ u32 dd_bsg_size;
/*
* The driver sets these to tell the transport class it
@@ -737,7 +786,6 @@ fc_vport_set_state(struct fc_vport *vport, enum fc_vport_state new_state)
vport->vport_state = new_state;
}
-
struct scsi_transport_template *fc_attach_transport(
struct fc_function_template *);
void fc_release_transport(struct scsi_transport_template *);
diff --git a/include/sound/core.h b/include/sound/core.h
index 3dea79829acc..a26bbdcc6765 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -300,16 +300,6 @@ int snd_card_create(int idx, const char *id,
struct module *module, int extra_size,
struct snd_card **card_ret);
-static inline __deprecated
-struct snd_card *snd_card_new(int idx, const char *id,
- struct module *module, int extra_size)
-{
- struct snd_card *card;
- if (snd_card_create(idx, id, module, extra_size, &card) < 0)
- return NULL;
- return card;
-}
-
int snd_card_disconnect(struct snd_card *card);
int snd_card_free(struct snd_card *card);
int snd_card_free_when_closed(struct snd_card *card);
diff --git a/include/sound/driver.h b/include/sound/driver.h
deleted file mode 100644
index f0359437d01a..000000000000
--- a/include/sound/driver.h
+++ /dev/null
@@ -1 +0,0 @@
-#warning "This file is deprecated"
diff --git a/include/sound/jack.h b/include/sound/jack.h
index 6b013c6f6a04..f236e426a706 100644
--- a/include/sound/jack.h
+++ b/include/sound/jack.h
@@ -50,6 +50,8 @@ struct snd_jack {
int type;
const char *id;
char name[100];
+ void *private_data;
+ void (*private_free)(struct snd_jack *);
};
#ifdef CONFIG_SND_JACK
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 8904b1900d7f..267effddb070 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -268,7 +268,9 @@ struct snd_pcm_runtime {
int overrange;
snd_pcm_uframes_t avail_max;
snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */
- snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time*/
+ snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time */
+ unsigned long hw_ptr_jiffies; /* Time when hw_ptr is updated */
+ snd_pcm_sframes_t delay; /* extra delay; typically FIFO size */
/* -- HW params -- */
snd_pcm_access_t access; /* access mode */
diff --git a/include/sound/pxa2xx-lib.h b/include/sound/pxa2xx-lib.h
index 2c894b600e5b..2fd3d251d9a5 100644
--- a/include/sound/pxa2xx-lib.h
+++ b/include/sound/pxa2xx-lib.h
@@ -42,19 +42,4 @@ extern int pxa2xx_ac97_hw_resume(void);
extern int pxa2xx_ac97_hw_probe(struct platform_device *dev);
extern void pxa2xx_ac97_hw_remove(struct platform_device *dev);
-/* AC97 platform_data */
-/**
- * struct pxa2xx_ac97_platform_data - pxa ac97 platform data
- * @reset_gpio: AC97 reset gpio (normally gpio113 or gpio95)
- * a -1 value means no gpio will be used for reset
- *
- * Platform data should only be specified for pxa27x CPUs where a silicon bug
- * prevents correct operation of the reset line. If not specified, the default
- * behaviour is to consider gpio 113 as the AC97 reset line, which is the
- * default on most boards.
- */
-struct pxa2xx_ac97_platform_data {
- int reset_gpio;
-};
-
#endif
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 13676472ddfc..496dc30457b7 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -45,24 +45,6 @@ struct snd_pcm_substream;
#define SND_SOC_DAIFMT_GATED (1 << 4) /* clock is gated */
/*
- * DAI Left/Right Clocks.
- *
- * Specifies whether the DAI can support different samples for similtanious
- * playback and capture. This usually requires a seperate physical frame
- * clock for playback and capture.
- */
-#define SND_SOC_DAIFMT_SYNC (0 << 5) /* Tx FRM = Rx FRM */
-#define SND_SOC_DAIFMT_ASYNC (1 << 5) /* Tx FRM ~ Rx FRM */
-
-/*
- * TDM
- *
- * Time Division Multiplexing. Allows PCM data to be multplexed with other
- * data on the DAI.
- */
-#define SND_SOC_DAIFMT_TDM (1 << 6)
-
-/*
* DAI hardware signal inversions.
*
* Specifies whether the DAI can also support inverted clocks for the specified
@@ -96,6 +78,9 @@ struct snd_pcm_substream;
#define SND_SOC_CLOCK_IN 0
#define SND_SOC_CLOCK_OUT 1
+#define SND_SOC_STD_AC97_FMTS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S32_LE)
+
struct snd_soc_dai_ops;
struct snd_soc_dai;
struct snd_ac97_bus_ops;
@@ -208,6 +193,7 @@ struct snd_soc_dai {
/* DAI capabilities */
struct snd_soc_pcm_stream capture;
struct snd_soc_pcm_stream playback;
+ unsigned int symmetric_rates:1;
/* DAI runtime info */
struct snd_pcm_runtime *runtime;
@@ -219,11 +205,8 @@ struct snd_soc_dai {
/* DAI private data */
void *private_data;
- /* parent codec/platform */
- union {
- struct snd_soc_codec *codec;
- struct snd_soc_platform *platform;
- };
+ /* parent platform */
+ struct snd_soc_platform *platform;
struct list_head list;
};
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index a7def6a9a030..533f9f256496 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -140,16 +140,30 @@
#define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \
{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \
.shift = wshift, .invert = winvert}
+#define SND_SOC_DAPM_DAC_E(wname, stname, wreg, wshift, winvert, \
+ wevent, wflags) \
+{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \
+ .shift = wshift, .invert = winvert, \
+ .event = wevent, .event_flags = wflags}
#define SND_SOC_DAPM_ADC(wname, stname, wreg, wshift, winvert) \
{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \
.shift = wshift, .invert = winvert}
+#define SND_SOC_DAPM_ADC_E(wname, stname, wreg, wshift, winvert, \
+ wevent, wflags) \
+{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \
+ .shift = wshift, .invert = winvert, \
+ .event = wevent, .event_flags = wflags}
-/* generic register modifier widget */
+/* generic widgets */
#define SND_SOC_DAPM_REG(wid, wname, wreg, wshift, wmask, won_val, woff_val) \
{ .id = wid, .name = wname, .kcontrols = NULL, .num_kcontrols = 0, \
.reg = -((wreg) + 1), .shift = wshift, .mask = wmask, \
.on_val = won_val, .off_val = woff_val, .event = dapm_reg_event, \
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD}
+#define SND_SOC_DAPM_SUPPLY(wname, wreg, wshift, winvert, wevent, wflags) \
+{ .id = snd_soc_dapm_supply, .name = wname, .reg = wreg, \
+ .shift = wshift, .invert = winvert, .event = wevent, \
+ .event_flags = wflags}
/* dapm kcontrol types */
#define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \
@@ -298,6 +312,7 @@ enum snd_soc_dapm_type {
snd_soc_dapm_vmid, /* codec bias/vmid - to minimise pops */
snd_soc_dapm_pre, /* machine specific pre widget - exec first */
snd_soc_dapm_post, /* machine specific post widget - exec last */
+ snd_soc_dapm_supply, /* power/clock supply */
};
/*
@@ -357,6 +372,8 @@ struct snd_soc_dapm_widget {
unsigned char suspend:1; /* was active before suspend */
unsigned char pmdown:1; /* waiting for timeout */
+ int (*power_check)(struct snd_soc_dapm_widget *w);
+
/* external events */
unsigned short event_flags; /* flags to specify event types */
int (*event)(struct snd_soc_dapm_widget*, struct snd_kcontrol *, int);
diff --git a/include/sound/soc.h b/include/sound/soc.h
index a40bc6f316fc..6ab80bf7abd2 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -118,6 +118,14 @@
.info = snd_soc_info_volsw, \
.get = xhandler_get, .put = xhandler_put, \
.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) }
+#define SOC_DOUBLE_EXT(xname, xreg, shift_left, shift_right, xmax, xinvert,\
+ xhandler_get, xhandler_put) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
+ .info = snd_soc_info_volsw, \
+ .get = xhandler_get, .put = xhandler_put, \
+ .private_value = (unsigned long)&(struct soc_mixer_control) \
+ {.reg = xreg, .shift = shift_left, .rshift = shift_right, \
+ .max = xmax, .invert = xinvert} }
#define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\
xhandler_get, xhandler_put, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@ -417,6 +425,12 @@ struct snd_soc_dai_link {
/* codec/machine specific init - e.g. add machine controls */
int (*init)(struct snd_soc_codec *codec);
+ /* Symmetry requirements */
+ unsigned int symmetric_rates:1;
+
+ /* Symmetry data - only valid if symmetry is being enforced */
+ unsigned int rate;
+
/* DAI pcm */
struct snd_pcm *pcm;
};
diff --git a/include/sound/version.h b/include/sound/version.h
index a7e74e23ad2e..456f1359e1c0 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
/* include/version.h */
-#define CONFIG_SND_VERSION "1.0.19"
+#define CONFIG_SND_VERSION "1.0.20"
#define CONFIG_SND_DATE ""
diff --git a/include/trace/block.h b/include/trace/block.h
index 25b7068b819e..8ac945b7746e 100644
--- a/include/trace/block.h
+++ b/include/trace/block.h
@@ -70,7 +70,7 @@ DECLARE_TRACE(block_split,
DECLARE_TRACE(block_remap,
TP_PROTO(struct request_queue *q, struct bio *bio, dev_t dev,
- sector_t from, sector_t to),
- TP_ARGS(q, bio, dev, from, to));
+ sector_t to),
+ TP_ARGS(q, bio, dev, to));
#endif
diff --git a/include/trace/define_trace.h b/include/trace/define_trace.h
new file mode 100644
index 000000000000..f7a7ae1e8f90
--- /dev/null
+++ b/include/trace/define_trace.h
@@ -0,0 +1,75 @@
+/*
+ * Trace files that want to automate creationg of all tracepoints defined
+ * in their file should include this file. The following are macros that the
+ * trace file may define:
+ *
+ * TRACE_SYSTEM defines the system the tracepoint is for
+ *
+ * TRACE_INCLUDE_FILE if the file name is something other than TRACE_SYSTEM.h
+ * This macro may be defined to tell define_trace.h what file to include.
+ * Note, leave off the ".h".
+ *
+ * TRACE_INCLUDE_PATH if the path is something other than core kernel include/trace
+ * then this macro can define the path to use. Note, the path is relative to
+ * define_trace.h, not the file including it. Full path names for out of tree
+ * modules must be used.
+ */
+
+#ifdef CREATE_TRACE_POINTS
+
+/* Prevent recursion */
+#undef CREATE_TRACE_POINTS
+
+#include <linux/stringify.h>
+
+#undef TRACE_EVENT
+#define TRACE_EVENT(name, proto, args, tstruct, assign, print) \
+ DEFINE_TRACE(name)
+
+#undef DECLARE_TRACE
+#define DECLARE_TRACE(name, proto, args) \
+ DEFINE_TRACE(name)
+
+#undef TRACE_INCLUDE
+#undef __TRACE_INCLUDE
+
+#ifndef TRACE_INCLUDE_FILE
+# define TRACE_INCLUDE_FILE TRACE_SYSTEM
+# define UNDEF_TRACE_INCLUDE_FILE
+#endif
+
+#ifndef TRACE_INCLUDE_PATH
+# define __TRACE_INCLUDE(system) <trace/events/system.h>
+# define UNDEF_TRACE_INCLUDE_PATH
+#else
+# define __TRACE_INCLUDE(system) __stringify(TRACE_INCLUDE_PATH/system.h)
+#endif
+
+# define TRACE_INCLUDE(system) __TRACE_INCLUDE(system)
+
+/* Let the trace headers be reread */
+#define TRACE_HEADER_MULTI_READ
+
+#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
+
+#ifdef CONFIG_EVENT_TRACING
+#include <trace/ftrace.h>
+#endif
+
+#undef TRACE_HEADER_MULTI_READ
+
+/* Only undef what we defined in this file */
+#ifdef UNDEF_TRACE_INCLUDE_FILE
+# undef TRACE_INCLUDE_FILE
+# undef UNDEF_TRACE_INCLUDE_FILE
+#endif
+
+#ifdef UNDEF_TRACE_INCLUDE_PATH
+# undef TRACE_INCLUDE_PATH
+# undef UNDEF_TRACE_INCLUDE_PATH
+#endif
+
+/* We may be processing more files */
+#define CREATE_TRACE_POINTS
+
+#endif /* CREATE_TRACE_POINTS */
diff --git a/include/trace/events/irq.h b/include/trace/events/irq.h
new file mode 100644
index 000000000000..32a9f7ef432b
--- /dev/null
+++ b/include/trace/events/irq.h
@@ -0,0 +1,134 @@
+#if !defined(_TRACE_IRQ_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_IRQ_H
+
+#include <linux/tracepoint.h>
+#include <linux/interrupt.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM irq
+
+/**
+ * irq_handler_entry - called immediately before the irq action handler
+ * @irq: irq number
+ * @action: pointer to struct irqaction
+ *
+ * The struct irqaction pointed to by @action contains various
+ * information about the handler, including the device name,
+ * @action->name, and the device id, @action->dev_id. When used in
+ * conjunction with the irq_handler_exit tracepoint, we can figure
+ * out irq handler latencies.
+ */
+TRACE_EVENT(irq_handler_entry,
+
+ TP_PROTO(int irq, struct irqaction *action),
+
+ TP_ARGS(irq, action),
+
+ TP_STRUCT__entry(
+ __field( int, irq )
+ __string( name, action->name )
+ ),
+
+ TP_fast_assign(
+ __entry->irq = irq;
+ __assign_str(name, action->name);
+ ),
+
+ TP_printk("irq=%d handler=%s", __entry->irq, __get_str(name))
+);
+
+/**
+ * irq_handler_exit - called immediately after the irq action handler returns
+ * @irq: irq number
+ * @action: pointer to struct irqaction
+ * @ret: return value
+ *
+ * If the @ret value is set to IRQ_HANDLED, then we know that the corresponding
+ * @action->handler scuccessully handled this irq. Otherwise, the irq might be
+ * a shared irq line, or the irq was not handled successfully. Can be used in
+ * conjunction with the irq_handler_entry to understand irq handler latencies.
+ */
+TRACE_EVENT(irq_handler_exit,
+
+ TP_PROTO(int irq, struct irqaction *action, int ret),
+
+ TP_ARGS(irq, action, ret),
+
+ TP_STRUCT__entry(
+ __field( int, irq )
+ __field( int, ret )
+ ),
+
+ TP_fast_assign(
+ __entry->irq = irq;
+ __entry->ret = ret;
+ ),
+
+ TP_printk("irq=%d return=%s",
+ __entry->irq, __entry->ret ? "handled" : "unhandled")
+);
+
+/**
+ * softirq_entry - called immediately before the softirq handler
+ * @h: pointer to struct softirq_action
+ * @vec: pointer to first struct softirq_action in softirq_vec array
+ *
+ * The @h parameter, contains a pointer to the struct softirq_action
+ * which has a pointer to the action handler that is called. By subtracting
+ * the @vec pointer from the @h pointer, we can determine the softirq
+ * number. Also, when used in combination with the softirq_exit tracepoint
+ * we can determine the softirq latency.
+ */
+TRACE_EVENT(softirq_entry,
+
+ TP_PROTO(struct softirq_action *h, struct softirq_action *vec),
+
+ TP_ARGS(h, vec),
+
+ TP_STRUCT__entry(
+ __field( int, vec )
+ __string( name, softirq_to_name[h-vec] )
+ ),
+
+ TP_fast_assign(
+ __entry->vec = (int)(h - vec);
+ __assign_str(name, softirq_to_name[h-vec]);
+ ),
+
+ TP_printk("softirq=%d action=%s", __entry->vec, __get_str(name))
+);
+
+/**
+ * softirq_exit - called immediately after the softirq handler returns
+ * @h: pointer to struct softirq_action
+ * @vec: pointer to first struct softirq_action in softirq_vec array
+ *
+ * The @h parameter contains a pointer to the struct softirq_action
+ * that has handled the softirq. By subtracting the @vec pointer from
+ * the @h pointer, we can determine the softirq number. Also, when used in
+ * combination with the softirq_entry tracepoint we can determine the softirq
+ * latency.
+ */
+TRACE_EVENT(softirq_exit,
+
+ TP_PROTO(struct softirq_action *h, struct softirq_action *vec),
+
+ TP_ARGS(h, vec),
+
+ TP_STRUCT__entry(
+ __field( int, vec )
+ __string( name, softirq_to_name[h-vec] )
+ ),
+
+ TP_fast_assign(
+ __entry->vec = (int)(h - vec);
+ __assign_str(name, softirq_to_name[h-vec]);
+ ),
+
+ TP_printk("softirq=%d action=%s", __entry->vec, __get_str(name))
+);
+
+#endif /* _TRACE_IRQ_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/kmem.h b/include/trace/events/kmem.h
new file mode 100644
index 000000000000..c22c42f980b5
--- /dev/null
+++ b/include/trace/events/kmem.h
@@ -0,0 +1,194 @@
+#if !defined(_TRACE_KMEM_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_KMEM_H
+
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM kmem
+
+TRACE_EVENT(kmalloc,
+
+ TP_PROTO(unsigned long call_site,
+ const void *ptr,
+ size_t bytes_req,
+ size_t bytes_alloc,
+ gfp_t gfp_flags),
+
+ TP_ARGS(call_site, ptr, bytes_req, bytes_alloc, gfp_flags),
+
+ TP_STRUCT__entry(
+ __field( unsigned long, call_site )
+ __field( const void *, ptr )
+ __field( size_t, bytes_req )
+ __field( size_t, bytes_alloc )
+ __field( gfp_t, gfp_flags )
+ ),
+
+ TP_fast_assign(
+ __entry->call_site = call_site;
+ __entry->ptr = ptr;
+ __entry->bytes_req = bytes_req;
+ __entry->bytes_alloc = bytes_alloc;
+ __entry->gfp_flags = gfp_flags;
+ ),
+
+ TP_printk("call_site=%lx ptr=%p bytes_req=%zu bytes_alloc=%zu gfp_flags=%08x",
+ __entry->call_site,
+ __entry->ptr,
+ __entry->bytes_req,
+ __entry->bytes_alloc,
+ __entry->gfp_flags)
+);
+
+TRACE_EVENT(kmem_cache_alloc,
+
+ TP_PROTO(unsigned long call_site,
+ const void *ptr,
+ size_t bytes_req,
+ size_t bytes_alloc,
+ gfp_t gfp_flags),
+
+ TP_ARGS(call_site, ptr, bytes_req, bytes_alloc, gfp_flags),
+
+ TP_STRUCT__entry(
+ __field( unsigned long, call_site )
+ __field( const void *, ptr )
+ __field( size_t, bytes_req )
+ __field( size_t, bytes_alloc )
+ __field( gfp_t, gfp_flags )
+ ),
+
+ TP_fast_assign(
+ __entry->call_site = call_site;
+ __entry->ptr = ptr;
+ __entry->bytes_req = bytes_req;
+ __entry->bytes_alloc = bytes_alloc;
+ __entry->gfp_flags = gfp_flags;
+ ),
+
+ TP_printk("call_site=%lx ptr=%p bytes_req=%zu bytes_alloc=%zu gfp_flags=%08x",
+ __entry->call_site,
+ __entry->ptr,
+ __entry->bytes_req,
+ __entry->bytes_alloc,
+ __entry->gfp_flags)
+);
+
+TRACE_EVENT(kmalloc_node,
+
+ TP_PROTO(unsigned long call_site,
+ const void *ptr,
+ size_t bytes_req,
+ size_t bytes_alloc,
+ gfp_t gfp_flags,
+ int node),
+
+ TP_ARGS(call_site, ptr, bytes_req, bytes_alloc, gfp_flags, node),
+
+ TP_STRUCT__entry(
+ __field( unsigned long, call_site )
+ __field( const void *, ptr )
+ __field( size_t, bytes_req )
+ __field( size_t, bytes_alloc )
+ __field( gfp_t, gfp_flags )
+ __field( int, node )
+ ),
+
+ TP_fast_assign(
+ __entry->call_site = call_site;
+ __entry->ptr = ptr;
+ __entry->bytes_req = bytes_req;
+ __entry->bytes_alloc = bytes_alloc;
+ __entry->gfp_flags = gfp_flags;
+ __entry->node = node;
+ ),
+
+ TP_printk("call_site=%lx ptr=%p bytes_req=%zu bytes_alloc=%zu gfp_flags=%08x node=%d",
+ __entry->call_site,
+ __entry->ptr,
+ __entry->bytes_req,
+ __entry->bytes_alloc,
+ __entry->gfp_flags,
+ __entry->node)
+);
+
+TRACE_EVENT(kmem_cache_alloc_node,
+
+ TP_PROTO(unsigned long call_site,
+ const void *ptr,
+ size_t bytes_req,
+ size_t bytes_alloc,
+ gfp_t gfp_flags,
+ int node),
+
+ TP_ARGS(call_site, ptr, bytes_req, bytes_alloc, gfp_flags, node),
+
+ TP_STRUCT__entry(
+ __field( unsigned long, call_site )
+ __field( const void *, ptr )
+ __field( size_t, bytes_req )
+ __field( size_t, bytes_alloc )
+ __field( gfp_t, gfp_flags )
+ __field( int, node )
+ ),
+
+ TP_fast_assign(
+ __entry->call_site = call_site;
+ __entry->ptr = ptr;
+ __entry->bytes_req = bytes_req;
+ __entry->bytes_alloc = bytes_alloc;
+ __entry->gfp_flags = gfp_flags;
+ __entry->node = node;
+ ),
+
+ TP_printk("call_site=%lx ptr=%p bytes_req=%zu bytes_alloc=%zu gfp_flags=%08x node=%d",
+ __entry->call_site,
+ __entry->ptr,
+ __entry->bytes_req,
+ __entry->bytes_alloc,
+ __entry->gfp_flags,
+ __entry->node)
+);
+
+TRACE_EVENT(kfree,
+
+ TP_PROTO(unsigned long call_site, const void *ptr),
+
+ TP_ARGS(call_site, ptr),
+
+ TP_STRUCT__entry(
+ __field( unsigned long, call_site )
+ __field( const void *, ptr )
+ ),
+
+ TP_fast_assign(
+ __entry->call_site = call_site;
+ __entry->ptr = ptr;
+ ),
+
+ TP_printk("call_site=%lx ptr=%p", __entry->call_site, __entry->ptr)
+);
+
+TRACE_EVENT(kmem_cache_free,
+
+ TP_PROTO(unsigned long call_site, const void *ptr),
+
+ TP_ARGS(call_site, ptr),
+
+ TP_STRUCT__entry(
+ __field( unsigned long, call_site )
+ __field( const void *, ptr )
+ ),
+
+ TP_fast_assign(
+ __entry->call_site = call_site;
+ __entry->ptr = ptr;
+ ),
+
+ TP_printk("call_site=%lx ptr=%p", __entry->call_site, __entry->ptr)
+);
+#endif /* _TRACE_KMEM_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/lockdep.h b/include/trace/events/lockdep.h
new file mode 100644
index 000000000000..0e956c9dfd7e
--- /dev/null
+++ b/include/trace/events/lockdep.h
@@ -0,0 +1,96 @@
+#if !defined(_TRACE_LOCKDEP_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_LOCKDEP_H
+
+#include <linux/lockdep.h>
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM lockdep
+
+#ifdef CONFIG_LOCKDEP
+
+TRACE_EVENT(lock_acquire,
+
+ TP_PROTO(struct lockdep_map *lock, unsigned int subclass,
+ int trylock, int read, int check,
+ struct lockdep_map *next_lock, unsigned long ip),
+
+ TP_ARGS(lock, subclass, trylock, read, check, next_lock, ip),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, flags)
+ __string(name, lock->name)
+ ),
+
+ TP_fast_assign(
+ __entry->flags = (trylock ? 1 : 0) | (read ? 2 : 0);
+ __assign_str(name, lock->name);
+ ),
+
+ TP_printk("%s%s%s", (__entry->flags & 1) ? "try " : "",
+ (__entry->flags & 2) ? "read " : "",
+ __get_str(name))
+);
+
+TRACE_EVENT(lock_release,
+
+ TP_PROTO(struct lockdep_map *lock, int nested, unsigned long ip),
+
+ TP_ARGS(lock, nested, ip),
+
+ TP_STRUCT__entry(
+ __string(name, lock->name)
+ ),
+
+ TP_fast_assign(
+ __assign_str(name, lock->name);
+ ),
+
+ TP_printk("%s", __get_str(name))
+);
+
+#ifdef CONFIG_LOCK_STAT
+
+TRACE_EVENT(lock_contended,
+
+ TP_PROTO(struct lockdep_map *lock, unsigned long ip),
+
+ TP_ARGS(lock, ip),
+
+ TP_STRUCT__entry(
+ __string(name, lock->name)
+ ),
+
+ TP_fast_assign(
+ __assign_str(name, lock->name);
+ ),
+
+ TP_printk("%s", __get_str(name))
+);
+
+TRACE_EVENT(lock_acquired,
+ TP_PROTO(struct lockdep_map *lock, unsigned long ip, s64 waittime),
+
+ TP_ARGS(lock, ip, waittime),
+
+ TP_STRUCT__entry(
+ __string(name, lock->name)
+ __field(unsigned long, wait_usec)
+ __field(unsigned long, wait_nsec_rem)
+ ),
+ TP_fast_assign(
+ __assign_str(name, lock->name);
+ __entry->wait_nsec_rem = do_div(waittime, NSEC_PER_USEC);
+ __entry->wait_usec = (unsigned long) waittime;
+ ),
+ TP_printk("%s (%lu.%03lu us)", __get_str(name), __entry->wait_usec,
+ __entry->wait_nsec_rem)
+);
+
+#endif
+#endif
+
+#endif /* _TRACE_LOCKDEP_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/sched_event_types.h b/include/trace/events/sched.h
index 63547dc1125f..dd4033cf5b09 100644
--- a/include/trace/sched_event_types.h
+++ b/include/trace/events/sched.h
@@ -1,9 +1,8 @@
+#if !defined(_TRACE_SCHED_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_SCHED_H
-/* use <trace/sched.h> instead */
-#ifndef TRACE_EVENT
-# error Do not include this file directly.
-# error Unless you know what you are doing.
-#endif
+#include <linux/sched.h>
+#include <linux/tracepoint.h>
#undef TRACE_SYSTEM
#define TRACE_SYSTEM sched
@@ -181,9 +180,9 @@ TRACE_EVENT(sched_switch,
*/
TRACE_EVENT(sched_migrate_task,
- TP_PROTO(struct task_struct *p, int orig_cpu, int dest_cpu),
+ TP_PROTO(struct task_struct *p, int dest_cpu),
- TP_ARGS(p, orig_cpu, dest_cpu),
+ TP_ARGS(p, dest_cpu),
TP_STRUCT__entry(
__array( char, comm, TASK_COMM_LEN )
@@ -197,7 +196,7 @@ TRACE_EVENT(sched_migrate_task,
memcpy(__entry->comm, p->comm, TASK_COMM_LEN);
__entry->pid = p->pid;
__entry->prio = p->prio;
- __entry->orig_cpu = orig_cpu;
+ __entry->orig_cpu = task_cpu(p);
__entry->dest_cpu = dest_cpu;
),
@@ -334,4 +333,7 @@ TRACE_EVENT(sched_signal_send,
__entry->sig, __entry->comm, __entry->pid)
);
-#undef TRACE_SYSTEM
+#endif /* _TRACE_SCHED_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/skb.h b/include/trace/events/skb.h
new file mode 100644
index 000000000000..1e8fabb57c06
--- /dev/null
+++ b/include/trace/events/skb.h
@@ -0,0 +1,40 @@
+#if !defined(_TRACE_SKB_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_SKB_H
+
+#include <linux/skbuff.h>
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM skb
+
+/*
+ * Tracepoint for free an sk_buff:
+ */
+TRACE_EVENT(kfree_skb,
+
+ TP_PROTO(struct sk_buff *skb, void *location),
+
+ TP_ARGS(skb, location),
+
+ TP_STRUCT__entry(
+ __field( void *, skbaddr )
+ __field( unsigned short, protocol )
+ __field( void *, location )
+ ),
+
+ TP_fast_assign(
+ __entry->skbaddr = skb;
+ if (skb) {
+ __entry->protocol = ntohs(skb->protocol);
+ }
+ __entry->location = location;
+ ),
+
+ TP_printk("skbaddr=%p protocol=%u location=%p",
+ __entry->skbaddr, __entry->protocol, __entry->location)
+);
+
+#endif /* _TRACE_SKB_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
new file mode 100644
index 000000000000..edb02bc9f8ff
--- /dev/null
+++ b/include/trace/ftrace.h
@@ -0,0 +1,509 @@
+/*
+ * Stage 1 of the trace events.
+ *
+ * Override the macros in <trace/trace_events.h> to include the following:
+ *
+ * struct ftrace_raw_<call> {
+ * struct trace_entry ent;
+ * <type> <item>;
+ * <type2> <item2>[<len>];
+ * [...]
+ * };
+ *
+ * The <type> <item> is created by the __field(type, item) macro or
+ * the __array(type2, item2, len) macro.
+ * We simply do "type item;", and that will create the fields
+ * in the structure.
+ */
+
+#include <linux/ftrace_event.h>
+
+#undef __array
+#define __array(type, item, len) type item[len];
+
+#undef __field
+#define __field(type, item) type item;
+
+#undef __string
+#define __string(item, src) int __str_loc_##item;
+
+#undef TP_STRUCT__entry
+#define TP_STRUCT__entry(args...) args
+
+#undef TRACE_EVENT
+#define TRACE_EVENT(name, proto, args, tstruct, assign, print) \
+ struct ftrace_raw_##name { \
+ struct trace_entry ent; \
+ tstruct \
+ char __str_data[0]; \
+ }; \
+ static struct ftrace_event_call event_##name
+
+#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
+
+
+/*
+ * Stage 2 of the trace events.
+ *
+ * Include the following:
+ *
+ * struct ftrace_str_offsets_<call> {
+ * int <str1>;
+ * int <str2>;
+ * [...]
+ * };
+ *
+ * The __string() macro will create each int <str>, this is to
+ * keep the offset of each string from the beggining of the event
+ * once we perform the strlen() of the src strings.
+ *
+ */
+
+#undef __array
+#define __array(type, item, len)
+
+#undef __field
+#define __field(type, item);
+
+#undef __string
+#define __string(item, src) int item;
+
+#undef TRACE_EVENT
+#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
+ struct ftrace_str_offsets_##call { \
+ tstruct; \
+ };
+
+#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
+
+/*
+ * Stage 3 of the trace events.
+ *
+ * Override the macros in <trace/trace_events.h> to include the following:
+ *
+ * enum print_line_t
+ * ftrace_raw_output_<call>(struct trace_iterator *iter, int flags)
+ * {
+ * struct trace_seq *s = &iter->seq;
+ * struct ftrace_raw_<call> *field; <-- defined in stage 1
+ * struct trace_entry *entry;
+ * int ret;
+ *
+ * entry = iter->ent;
+ *
+ * if (entry->type != event_<call>.id) {
+ * WARN_ON_ONCE(1);
+ * return TRACE_TYPE_UNHANDLED;
+ * }
+ *
+ * field = (typeof(field))entry;
+ *
+ * ret = trace_seq_printf(s, <TP_printk> "\n");
+ * if (!ret)
+ * return TRACE_TYPE_PARTIAL_LINE;
+ *
+ * return TRACE_TYPE_HANDLED;
+ * }
+ *
+ * This is the method used to print the raw event to the trace
+ * output format. Note, this is not needed if the data is read
+ * in binary.
+ */
+
+#undef __entry
+#define __entry field
+
+#undef TP_printk
+#define TP_printk(fmt, args...) fmt "\n", args
+
+#undef __get_str
+#define __get_str(field) ((char *)__entry + __entry->__str_loc_##field)
+
+#undef TRACE_EVENT
+#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
+enum print_line_t \
+ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \
+{ \
+ struct trace_seq *s = &iter->seq; \
+ struct ftrace_raw_##call *field; \
+ struct trace_entry *entry; \
+ int ret; \
+ \
+ entry = iter->ent; \
+ \
+ if (entry->type != event_##call.id) { \
+ WARN_ON_ONCE(1); \
+ return TRACE_TYPE_UNHANDLED; \
+ } \
+ \
+ field = (typeof(field))entry; \
+ \
+ ret = trace_seq_printf(s, #call ": " print); \
+ if (!ret) \
+ return TRACE_TYPE_PARTIAL_LINE; \
+ \
+ return TRACE_TYPE_HANDLED; \
+}
+
+#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
+
+/*
+ * Setup the showing format of trace point.
+ *
+ * int
+ * ftrace_format_##call(struct trace_seq *s)
+ * {
+ * struct ftrace_raw_##call field;
+ * int ret;
+ *
+ * ret = trace_seq_printf(s, #type " " #item ";"
+ * " offset:%u; size:%u;\n",
+ * offsetof(struct ftrace_raw_##call, item),
+ * sizeof(field.type));
+ *
+ * }
+ */
+
+#undef TP_STRUCT__entry
+#define TP_STRUCT__entry(args...) args
+
+#undef __field
+#define __field(type, item) \
+ ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \
+ "offset:%u;\tsize:%u;\n", \
+ (unsigned int)offsetof(typeof(field), item), \
+ (unsigned int)sizeof(field.item)); \
+ if (!ret) \
+ return 0;
+
+#undef __array
+#define __array(type, item, len) \
+ ret = trace_seq_printf(s, "\tfield:" #type " " #item "[" #len "];\t" \
+ "offset:%u;\tsize:%u;\n", \
+ (unsigned int)offsetof(typeof(field), item), \
+ (unsigned int)sizeof(field.item)); \
+ if (!ret) \
+ return 0;
+
+#undef __string
+#define __string(item, src) \
+ ret = trace_seq_printf(s, "\tfield: __str_loc " #item ";\t" \
+ "offset:%u;tsize:%u;\n", \
+ (unsigned int)offsetof(typeof(field), \
+ __str_loc_##item), \
+ (unsigned int)sizeof(field.__str_loc_##item)); \
+ if (!ret) \
+ return 0;
+
+#undef __entry
+#define __entry REC
+
+#undef TP_printk
+#define TP_printk(fmt, args...) "%s, %s\n", #fmt, __stringify(args)
+
+#undef TP_fast_assign
+#define TP_fast_assign(args...) args
+
+#undef TRACE_EVENT
+#define TRACE_EVENT(call, proto, args, tstruct, func, print) \
+static int \
+ftrace_format_##call(struct trace_seq *s) \
+{ \
+ struct ftrace_raw_##call field __attribute__((unused)); \
+ int ret = 0; \
+ \
+ tstruct; \
+ \
+ trace_seq_printf(s, "\nprint fmt: " print); \
+ \
+ return ret; \
+}
+
+#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
+
+#undef __field
+#define __field(type, item) \
+ ret = trace_define_field(event_call, #type, #item, \
+ offsetof(typeof(field), item), \
+ sizeof(field.item), is_signed_type(type)); \
+ if (ret) \
+ return ret;
+
+#undef __array
+#define __array(type, item, len) \
+ BUILD_BUG_ON(len > MAX_FILTER_STR_VAL); \
+ ret = trace_define_field(event_call, #type "[" #len "]", #item, \
+ offsetof(typeof(field), item), \
+ sizeof(field.item), 0); \
+ if (ret) \
+ return ret;
+
+#undef __string
+#define __string(item, src) \
+ ret = trace_define_field(event_call, "__str_loc", #item, \
+ offsetof(typeof(field), __str_loc_##item), \
+ sizeof(field.__str_loc_##item), 0);
+
+#undef TRACE_EVENT
+#define TRACE_EVENT(call, proto, args, tstruct, func, print) \
+int \
+ftrace_define_fields_##call(void) \
+{ \
+ struct ftrace_raw_##call field; \
+ struct ftrace_event_call *event_call = &event_##call; \
+ int ret; \
+ \
+ __common_field(int, type, 1); \
+ __common_field(unsigned char, flags, 0); \
+ __common_field(unsigned char, preempt_count, 0); \
+ __common_field(int, pid, 1); \
+ __common_field(int, tgid, 1); \
+ \
+ tstruct; \
+ \
+ return ret; \
+}
+
+#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
+
+/*
+ * Stage 4 of the trace events.
+ *
+ * Override the macros in <trace/trace_events.h> to include the following:
+ *
+ * static void ftrace_event_<call>(proto)
+ * {
+ * event_trace_printk(_RET_IP_, "<call>: " <fmt>);
+ * }
+ *
+ * static int ftrace_reg_event_<call>(void)
+ * {
+ * int ret;
+ *
+ * ret = register_trace_<call>(ftrace_event_<call>);
+ * if (!ret)
+ * pr_info("event trace: Could not activate trace point "
+ * "probe to <call>");
+ * return ret;
+ * }
+ *
+ * static void ftrace_unreg_event_<call>(void)
+ * {
+ * unregister_trace_<call>(ftrace_event_<call>);
+ * }
+ *
+ *
+ * For those macros defined with TRACE_EVENT:
+ *
+ * static struct ftrace_event_call event_<call>;
+ *
+ * static void ftrace_raw_event_<call>(proto)
+ * {
+ * struct ring_buffer_event *event;
+ * struct ftrace_raw_<call> *entry; <-- defined in stage 1
+ * unsigned long irq_flags;
+ * int pc;
+ *
+ * local_save_flags(irq_flags);
+ * pc = preempt_count();
+ *
+ * event = trace_current_buffer_lock_reserve(event_<call>.id,
+ * sizeof(struct ftrace_raw_<call>),
+ * irq_flags, pc);
+ * if (!event)
+ * return;
+ * entry = ring_buffer_event_data(event);
+ *
+ * <assign>; <-- Here we assign the entries by the __field and
+ * __array macros.
+ *
+ * trace_current_buffer_unlock_commit(event, irq_flags, pc);
+ * }
+ *
+ * static int ftrace_raw_reg_event_<call>(void)
+ * {
+ * int ret;
+ *
+ * ret = register_trace_<call>(ftrace_raw_event_<call>);
+ * if (!ret)
+ * pr_info("event trace: Could not activate trace point "
+ * "probe to <call>");
+ * return ret;
+ * }
+ *
+ * static void ftrace_unreg_event_<call>(void)
+ * {
+ * unregister_trace_<call>(ftrace_raw_event_<call>);
+ * }
+ *
+ * static struct trace_event ftrace_event_type_<call> = {
+ * .trace = ftrace_raw_output_<call>, <-- stage 2
+ * };
+ *
+ * static int ftrace_raw_init_event_<call>(void)
+ * {
+ * int id;
+ *
+ * id = register_ftrace_event(&ftrace_event_type_<call>);
+ * if (!id)
+ * return -ENODEV;
+ * event_<call>.id = id;
+ * return 0;
+ * }
+ *
+ * static struct ftrace_event_call __used
+ * __attribute__((__aligned__(4)))
+ * __attribute__((section("_ftrace_events"))) event_<call> = {
+ * .name = "<call>",
+ * .system = "<system>",
+ * .raw_init = ftrace_raw_init_event_<call>,
+ * .regfunc = ftrace_reg_event_<call>,
+ * .unregfunc = ftrace_unreg_event_<call>,
+ * .show_format = ftrace_format_<call>,
+ * }
+ *
+ */
+
+#undef TP_FMT
+#define TP_FMT(fmt, args...) fmt "\n", ##args
+
+#ifdef CONFIG_EVENT_PROFILE
+#define _TRACE_PROFILE(call, proto, args) \
+static void ftrace_profile_##call(proto) \
+{ \
+ extern void perf_tpcounter_event(int); \
+ perf_tpcounter_event(event_##call.id); \
+} \
+ \
+static int ftrace_profile_enable_##call(struct ftrace_event_call *call) \
+{ \
+ int ret = 0; \
+ \
+ if (!atomic_inc_return(&call->profile_count)) \
+ ret = register_trace_##call(ftrace_profile_##call); \
+ \
+ return ret; \
+} \
+ \
+static void ftrace_profile_disable_##call(struct ftrace_event_call *call) \
+{ \
+ if (atomic_add_negative(-1, &call->profile_count)) \
+ unregister_trace_##call(ftrace_profile_##call); \
+}
+
+#define _TRACE_PROFILE_INIT(call) \
+ .profile_count = ATOMIC_INIT(-1), \
+ .profile_enable = ftrace_profile_enable_##call, \
+ .profile_disable = ftrace_profile_disable_##call,
+
+#else
+#define _TRACE_PROFILE(call, proto, args)
+#define _TRACE_PROFILE_INIT(call)
+#endif
+
+#undef __entry
+#define __entry entry
+
+#undef __field
+#define __field(type, item)
+
+#undef __array
+#define __array(type, item, len)
+
+#undef __string
+#define __string(item, src) \
+ __str_offsets.item = __str_size + \
+ offsetof(typeof(*entry), __str_data); \
+ __str_size += strlen(src) + 1;
+
+#undef __assign_str
+#define __assign_str(dst, src) \
+ __entry->__str_loc_##dst = __str_offsets.dst; \
+ strcpy(__get_str(dst), src);
+
+#undef TRACE_EVENT
+#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
+_TRACE_PROFILE(call, PARAMS(proto), PARAMS(args)) \
+ \
+static struct ftrace_event_call event_##call; \
+ \
+static void ftrace_raw_event_##call(proto) \
+{ \
+ struct ftrace_str_offsets_##call __maybe_unused __str_offsets; \
+ struct ftrace_event_call *call = &event_##call; \
+ struct ring_buffer_event *event; \
+ struct ftrace_raw_##call *entry; \
+ unsigned long irq_flags; \
+ int __str_size = 0; \
+ int pc; \
+ \
+ local_save_flags(irq_flags); \
+ pc = preempt_count(); \
+ \
+ tstruct; \
+ \
+ event = trace_current_buffer_lock_reserve(event_##call.id, \
+ sizeof(struct ftrace_raw_##call) + __str_size,\
+ irq_flags, pc); \
+ if (!event) \
+ return; \
+ entry = ring_buffer_event_data(event); \
+ \
+ assign; \
+ \
+ if (!filter_current_check_discard(call, entry, event)) \
+ trace_nowake_buffer_unlock_commit(event, irq_flags, pc); \
+} \
+ \
+static int ftrace_raw_reg_event_##call(void) \
+{ \
+ int ret; \
+ \
+ ret = register_trace_##call(ftrace_raw_event_##call); \
+ if (ret) \
+ pr_info("event trace: Could not activate trace point " \
+ "probe to " #call "\n"); \
+ return ret; \
+} \
+ \
+static void ftrace_raw_unreg_event_##call(void) \
+{ \
+ unregister_trace_##call(ftrace_raw_event_##call); \
+} \
+ \
+static struct trace_event ftrace_event_type_##call = { \
+ .trace = ftrace_raw_output_##call, \
+}; \
+ \
+static int ftrace_raw_init_event_##call(void) \
+{ \
+ int id; \
+ \
+ id = register_ftrace_event(&ftrace_event_type_##call); \
+ if (!id) \
+ return -ENODEV; \
+ event_##call.id = id; \
+ INIT_LIST_HEAD(&event_##call.fields); \
+ init_preds(&event_##call); \
+ return 0; \
+} \
+ \
+static struct ftrace_event_call __used \
+__attribute__((__aligned__(4))) \
+__attribute__((section("_ftrace_events"))) event_##call = { \
+ .name = #call, \
+ .system = __stringify(TRACE_SYSTEM), \
+ .event = &ftrace_event_type_##call, \
+ .raw_init = ftrace_raw_init_event_##call, \
+ .regfunc = ftrace_raw_reg_event_##call, \
+ .unregfunc = ftrace_raw_unreg_event_##call, \
+ .show_format = ftrace_format_##call, \
+ .define_fields = ftrace_define_fields_##call, \
+ _TRACE_PROFILE_INIT(call) \
+}
+
+#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
+
+#undef _TRACE_PROFILE
+#undef _TRACE_PROFILE_INIT
+
diff --git a/include/trace/irq.h b/include/trace/irq.h
deleted file mode 100644
index ff5d4495dc37..000000000000
--- a/include/trace/irq.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _TRACE_IRQ_H
-#define _TRACE_IRQ_H
-
-#include <linux/interrupt.h>
-#include <linux/tracepoint.h>
-
-#include <trace/irq_event_types.h>
-
-#endif
diff --git a/include/trace/irq_event_types.h b/include/trace/irq_event_types.h
deleted file mode 100644
index 85964ebd47ec..000000000000
--- a/include/trace/irq_event_types.h
+++ /dev/null
@@ -1,55 +0,0 @@
-
-/* use <trace/irq.h> instead */
-#ifndef TRACE_FORMAT
-# error Do not include this file directly.
-# error Unless you know what you are doing.
-#endif
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM irq
-
-/*
- * Tracepoint for entry of interrupt handler:
- */
-TRACE_FORMAT(irq_handler_entry,
- TP_PROTO(int irq, struct irqaction *action),
- TP_ARGS(irq, action),
- TP_FMT("irq=%d handler=%s", irq, action->name)
- );
-
-/*
- * Tracepoint for return of an interrupt handler:
- */
-TRACE_EVENT(irq_handler_exit,
-
- TP_PROTO(int irq, struct irqaction *action, int ret),
-
- TP_ARGS(irq, action, ret),
-
- TP_STRUCT__entry(
- __field( int, irq )
- __field( int, ret )
- ),
-
- TP_fast_assign(
- __entry->irq = irq;
- __entry->ret = ret;
- ),
-
- TP_printk("irq=%d return=%s",
- __entry->irq, __entry->ret ? "handled" : "unhandled")
-);
-
-TRACE_FORMAT(softirq_entry,
- TP_PROTO(struct softirq_action *h, struct softirq_action *vec),
- TP_ARGS(h, vec),
- TP_FMT("softirq=%d action=%s", (int)(h - vec), softirq_to_name[h-vec])
- );
-
-TRACE_FORMAT(softirq_exit,
- TP_PROTO(struct softirq_action *h, struct softirq_action *vec),
- TP_ARGS(h, vec),
- TP_FMT("softirq=%d action=%s", (int)(h - vec), softirq_to_name[h-vec])
- );
-
-#undef TRACE_SYSTEM
diff --git a/include/trace/kmemtrace.h b/include/trace/kmemtrace.h
deleted file mode 100644
index 28ee69f9cd46..000000000000
--- a/include/trace/kmemtrace.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2008 Eduard - Gabriel Munteanu
- *
- * This file is released under GPL version 2.
- */
-
-#ifndef _LINUX_KMEMTRACE_H
-#define _LINUX_KMEMTRACE_H
-
-#ifdef __KERNEL__
-
-#include <linux/tracepoint.h>
-#include <linux/types.h>
-
-#ifdef CONFIG_KMEMTRACE
-extern void kmemtrace_init(void);
-#else
-static inline void kmemtrace_init(void)
-{
-}
-#endif
-
-DECLARE_TRACE(kmalloc,
- TP_PROTO(unsigned long call_site,
- const void *ptr,
- size_t bytes_req,
- size_t bytes_alloc,
- gfp_t gfp_flags),
- TP_ARGS(call_site, ptr, bytes_req, bytes_alloc, gfp_flags));
-DECLARE_TRACE(kmem_cache_alloc,
- TP_PROTO(unsigned long call_site,
- const void *ptr,
- size_t bytes_req,
- size_t bytes_alloc,
- gfp_t gfp_flags),
- TP_ARGS(call_site, ptr, bytes_req, bytes_alloc, gfp_flags));
-DECLARE_TRACE(kmalloc_node,
- TP_PROTO(unsigned long call_site,
- const void *ptr,
- size_t bytes_req,
- size_t bytes_alloc,
- gfp_t gfp_flags,
- int node),
- TP_ARGS(call_site, ptr, bytes_req, bytes_alloc, gfp_flags, node));
-DECLARE_TRACE(kmem_cache_alloc_node,
- TP_PROTO(unsigned long call_site,
- const void *ptr,
- size_t bytes_req,
- size_t bytes_alloc,
- gfp_t gfp_flags,
- int node),
- TP_ARGS(call_site, ptr, bytes_req, bytes_alloc, gfp_flags, node));
-DECLARE_TRACE(kfree,
- TP_PROTO(unsigned long call_site, const void *ptr),
- TP_ARGS(call_site, ptr));
-DECLARE_TRACE(kmem_cache_free,
- TP_PROTO(unsigned long call_site, const void *ptr),
- TP_ARGS(call_site, ptr));
-
-#endif /* __KERNEL__ */
-
-#endif /* _LINUX_KMEMTRACE_H */
-
diff --git a/include/trace/lockdep.h b/include/trace/lockdep.h
deleted file mode 100644
index 5ca67df87f2a..000000000000
--- a/include/trace/lockdep.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _TRACE_LOCKDEP_H
-#define _TRACE_LOCKDEP_H
-
-#include <linux/lockdep.h>
-#include <linux/tracepoint.h>
-
-#include <trace/lockdep_event_types.h>
-
-#endif
diff --git a/include/trace/lockdep_event_types.h b/include/trace/lockdep_event_types.h
deleted file mode 100644
index adccfcd2ec8f..000000000000
--- a/include/trace/lockdep_event_types.h
+++ /dev/null
@@ -1,44 +0,0 @@
-
-#ifndef TRACE_FORMAT
-# error Do not include this file directly.
-# error Unless you know what you are doing.
-#endif
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM lock
-
-#ifdef CONFIG_LOCKDEP
-
-TRACE_FORMAT(lock_acquire,
- TP_PROTO(struct lockdep_map *lock, unsigned int subclass,
- int trylock, int read, int check,
- struct lockdep_map *next_lock, unsigned long ip),
- TP_ARGS(lock, subclass, trylock, read, check, next_lock, ip),
- TP_FMT("%s%s%s", trylock ? "try " : "",
- read ? "read " : "", lock->name)
- );
-
-TRACE_FORMAT(lock_release,
- TP_PROTO(struct lockdep_map *lock, int nested, unsigned long ip),
- TP_ARGS(lock, nested, ip),
- TP_FMT("%s", lock->name)
- );
-
-#ifdef CONFIG_LOCK_STAT
-
-TRACE_FORMAT(lock_contended,
- TP_PROTO(struct lockdep_map *lock, unsigned long ip),
- TP_ARGS(lock, ip),
- TP_FMT("%s", lock->name)
- );
-
-TRACE_FORMAT(lock_acquired,
- TP_PROTO(struct lockdep_map *lock, unsigned long ip),
- TP_ARGS(lock, ip),
- TP_FMT("%s", lock->name)
- );
-
-#endif
-#endif
-
-#undef TRACE_SYSTEM
diff --git a/include/trace/sched.h b/include/trace/sched.h
deleted file mode 100644
index 4e372a1a29bf..000000000000
--- a/include/trace/sched.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _TRACE_SCHED_H
-#define _TRACE_SCHED_H
-
-#include <linux/sched.h>
-#include <linux/tracepoint.h>
-
-#include <trace/sched_event_types.h>
-
-#endif
diff --git a/include/trace/skb.h b/include/trace/skb.h
deleted file mode 100644
index b66206d9be72..000000000000
--- a/include/trace/skb.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _TRACE_SKB_H_
-#define _TRACE_SKB_H_
-
-#include <linux/skbuff.h>
-#include <linux/tracepoint.h>
-
-DECLARE_TRACE(kfree_skb,
- TP_PROTO(struct sk_buff *skb, void *location),
- TP_ARGS(skb, location));
-
-#endif
diff --git a/include/trace/trace_event_types.h b/include/trace/trace_event_types.h
deleted file mode 100644
index df56f5694be6..000000000000
--- a/include/trace/trace_event_types.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/* trace/<type>_event_types.h here */
-
-#include <trace/sched_event_types.h>
-#include <trace/irq_event_types.h>
-#include <trace/lockdep_event_types.h>
diff --git a/include/trace/trace_events.h b/include/trace/trace_events.h
deleted file mode 100644
index fd13750ca4ba..000000000000
--- a/include/trace/trace_events.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/* trace/<type>.h here */
-
-#include <trace/sched.h>
-#include <trace/irq.h>
-#include <trace/lockdep.h>
diff --git a/include/video/cyblafb.h b/include/video/cyblafb.h
deleted file mode 100644
index d3c1d4e2c8e3..000000000000
--- a/include/video/cyblafb.h
+++ /dev/null
@@ -1,175 +0,0 @@
-
-#ifndef CYBLAFB_DEBUG
-#define CYBLAFB_DEBUG 0
-#endif
-
-#if CYBLAFB_DEBUG
-#define debug(f,a...) printk("%s:" f, __func__ , ## a);
-#else
-#define debug(f,a...)
-#endif
-
-#define output(f, a...) printk("cyblafb: " f, ## a)
-
-#define Kb (1024)
-#define Mb (Kb*Kb)
-
-/* PCI IDS of supported cards temporarily here */
-
-#define CYBERBLADEi1 0x8500
-
-/* these defines are for 'lcd' variable */
-#define LCD_STRETCH 0
-#define LCD_CENTER 1
-#define LCD_BIOS 2
-
-/* display types */
-#define DISPLAY_CRT 0
-#define DISPLAY_FP 1
-
-#define ROP_S 0xCC
-
-#define point(x,y) ((y)<<16|(x))
-
-//
-// Attribute Regs, ARxx, 3c0/3c1
-//
-#define AR00 0x00
-#define AR01 0x01
-#define AR02 0x02
-#define AR03 0x03
-#define AR04 0x04
-#define AR05 0x05
-#define AR06 0x06
-#define AR07 0x07
-#define AR08 0x08
-#define AR09 0x09
-#define AR0A 0x0A
-#define AR0B 0x0B
-#define AR0C 0x0C
-#define AR0D 0x0D
-#define AR0E 0x0E
-#define AR0F 0x0F
-#define AR10 0x10
-#define AR12 0x12
-#define AR13 0x13
-
-//
-// Sequencer Regs, SRxx, 3c4/3c5
-//
-#define SR00 0x00
-#define SR01 0x01
-#define SR02 0x02
-#define SR03 0x03
-#define SR04 0x04
-#define SR0D 0x0D
-#define SR0E 0x0E
-#define SR11 0x11
-#define SR18 0x18
-#define SR19 0x19
-
-//
-//
-//
-#define CR00 0x00
-#define CR01 0x01
-#define CR02 0x02
-#define CR03 0x03
-#define CR04 0x04
-#define CR05 0x05
-#define CR06 0x06
-#define CR07 0x07
-#define CR08 0x08
-#define CR09 0x09
-#define CR0A 0x0A
-#define CR0B 0x0B
-#define CR0C 0x0C
-#define CR0D 0x0D
-#define CR0E 0x0E
-#define CR0F 0x0F
-#define CR10 0x10
-#define CR11 0x11
-#define CR12 0x12
-#define CR13 0x13
-#define CR14 0x14
-#define CR15 0x15
-#define CR16 0x16
-#define CR17 0x17
-#define CR18 0x18
-#define CR19 0x19
-#define CR1A 0x1A
-#define CR1B 0x1B
-#define CR1C 0x1C
-#define CR1D 0x1D
-#define CR1E 0x1E
-#define CR1F 0x1F
-#define CR20 0x20
-#define CR21 0x21
-#define CR27 0x27
-#define CR29 0x29
-#define CR2A 0x2A
-#define CR2B 0x2B
-#define CR2D 0x2D
-#define CR2F 0x2F
-#define CR36 0x36
-#define CR38 0x38
-#define CR39 0x39
-#define CR3A 0x3A
-#define CR55 0x55
-#define CR56 0x56
-#define CR57 0x57
-#define CR58 0x58
-
-//
-//
-//
-
-#define GR00 0x01
-#define GR01 0x01
-#define GR02 0x02
-#define GR03 0x03
-#define GR04 0x04
-#define GR05 0x05
-#define GR06 0x06
-#define GR07 0x07
-#define GR08 0x08
-#define GR0F 0x0F
-#define GR20 0x20
-#define GR23 0x23
-#define GR2F 0x2F
-#define GR30 0x30
-#define GR31 0x31
-#define GR33 0x33
-#define GR52 0x52
-#define GR53 0x53
-#define GR5D 0x5d
-
-
-//
-// Graphics Engine
-//
-#define GEBase 0x2100 // could be mapped elsewhere if we like it
-#define GE00 (GEBase+0x00) // source 1, p 111
-#define GE04 (GEBase+0x04) // source 2, p 111
-#define GE08 (GEBase+0x08) // destination 1, p 111
-#define GE0C (GEBase+0x0C) // destination 2, p 112
-#define GE10 (GEBase+0x10) // right view base & enable, p 112
-#define GE13 (GEBase+0x13) // left view base & enable, p 112
-#define GE18 (GEBase+0x18) // block write start address, p 112
-#define GE1C (GEBase+0x1C) // block write end address, p 112
-#define GE20 (GEBase+0x20) // engine status, p 113
-#define GE24 (GEBase+0x24) // reset all GE pointers
-#define GE44 (GEBase+0x44) // command register, p 126
-#define GE48 (GEBase+0x48) // raster operation, p 127
-#define GE60 (GEBase+0x60) // foreground color, p 128
-#define GE64 (GEBase+0x64) // background color, p 128
-#define GE6C (GEBase+0x6C) // Pattern and Style, p 129, ok
-#define GE9C (GEBase+0x9C) // pixel engine data port, p 125
-#define GEB8 (GEBase+0xB8) // Destination Stride / Buffer Base 0, p 133
-#define GEBC (GEBase+0xBC) // Destination Stride / Buffer Base 1, p 133
-#define GEC0 (GEBase+0xC0) // Destination Stride / Buffer Base 2, p 133
-#define GEC4 (GEBase+0xC4) // Destination Stride / Buffer Base 3, p 133
-#define GEC8 (GEBase+0xC8) // Source Stride / Buffer Base 0, p 133
-#define GECC (GEBase+0xCC) // Source Stride / Buffer Base 1, p 133
-#define GED0 (GEBase+0xD0) // Source Stride / Buffer Base 2, p 133
-#define GED4 (GEBase+0xD4) // Source Stride / Buffer Base 3, p 133
diff --git a/include/xen/Kbuild b/include/xen/Kbuild
new file mode 100644
index 000000000000..4e65c16a445b
--- /dev/null
+++ b/include/xen/Kbuild
@@ -0,0 +1 @@
+header-y += evtchn.h
diff --git a/include/xen/events.h b/include/xen/events.h
index 0d5f1adc0363..e68d59a90ca8 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -53,4 +53,7 @@ bool xen_test_irq_pending(int irq);
irq will be disabled so it won't deliver an interrupt. */
void xen_poll_irq(int irq);
+/* Determine the IRQ which is bound to an event channel */
+unsigned irq_from_evtchn(unsigned int evtchn);
+
#endif /* _XEN_EVENTS_H */
diff --git a/include/xen/evtchn.h b/include/xen/evtchn.h
new file mode 100644
index 000000000000..14e833ee4e0b
--- /dev/null
+++ b/include/xen/evtchn.h
@@ -0,0 +1,88 @@
+/******************************************************************************
+ * evtchn.h
+ *
+ * Interface to /dev/xen/evtchn.
+ *
+ * Copyright (c) 2003-2005, K A Fraser
+ *
+ * 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; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __LINUX_PUBLIC_EVTCHN_H__
+#define __LINUX_PUBLIC_EVTCHN_H__
+
+/*
+ * Bind a fresh port to VIRQ @virq.
+ * Return allocated port.
+ */
+#define IOCTL_EVTCHN_BIND_VIRQ \
+ _IOC(_IOC_NONE, 'E', 0, sizeof(struct ioctl_evtchn_bind_virq))
+struct ioctl_evtchn_bind_virq {
+ unsigned int virq;
+};
+
+/*
+ * Bind a fresh port to remote <@remote_domain, @remote_port>.
+ * Return allocated port.
+ */
+#define IOCTL_EVTCHN_BIND_INTERDOMAIN \
+ _IOC(_IOC_NONE, 'E', 1, sizeof(struct ioctl_evtchn_bind_interdomain))
+struct ioctl_evtchn_bind_interdomain {
+ unsigned int remote_domain, remote_port;
+};
+
+/*
+ * Allocate a fresh port for binding to @remote_domain.
+ * Return allocated port.
+ */
+#define IOCTL_EVTCHN_BIND_UNBOUND_PORT \
+ _IOC(_IOC_NONE, 'E', 2, sizeof(struct ioctl_evtchn_bind_unbound_port))
+struct ioctl_evtchn_bind_unbound_port {
+ unsigned int remote_domain;
+};
+
+/*
+ * Unbind previously allocated @port.
+ */
+#define IOCTL_EVTCHN_UNBIND \
+ _IOC(_IOC_NONE, 'E', 3, sizeof(struct ioctl_evtchn_unbind))
+struct ioctl_evtchn_unbind {
+ unsigned int port;
+};
+
+/*
+ * Unbind previously allocated @port.
+ */
+#define IOCTL_EVTCHN_NOTIFY \
+ _IOC(_IOC_NONE, 'E', 4, sizeof(struct ioctl_evtchn_notify))
+struct ioctl_evtchn_notify {
+ unsigned int port;
+};
+
+/* Clear and reinitialise the event buffer. Clear error condition. */
+#define IOCTL_EVTCHN_RESET \
+ _IOC(_IOC_NONE, 'E', 5, 0)
+
+#endif /* __LINUX_PUBLIC_EVTCHN_H__ */
diff --git a/include/xen/interface/version.h b/include/xen/interface/version.h
index 453235e923f0..e8b6519d47e9 100644
--- a/include/xen/interface/version.h
+++ b/include/xen/interface/version.h
@@ -57,4 +57,7 @@ struct xen_feature_info {
/* Declares the features reported by XENVER_get_features. */
#include "features.h"
+/* arg == NULL; returns host memory page size. */
+#define XENVER_pagesize 7
+
#endif /* __XEN_PUBLIC_VERSION_H__ */
diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h
index f87f9614844d..b9763badbd77 100644
--- a/include/xen/xenbus.h
+++ b/include/xen/xenbus.h
@@ -91,8 +91,7 @@ struct xenbus_driver {
void (*otherend_changed)(struct xenbus_device *dev,
enum xenbus_state backend_state);
int (*remove)(struct xenbus_device *dev);
- int (*suspend)(struct xenbus_device *dev);
- int (*suspend_cancel)(struct xenbus_device *dev);
+ int (*suspend)(struct xenbus_device *dev, pm_message_t state);
int (*resume)(struct xenbus_device *dev);
int (*uevent)(struct xenbus_device *, char **, int, char *, int);
struct device_driver driver;
diff --git a/init/Kconfig b/init/Kconfig
index 7be4d3836745..57651e305a4c 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -308,7 +308,7 @@ menu "RCU Subsystem"
choice
prompt "RCU Implementation"
- default CLASSIC_RCU
+ default TREE_RCU
config CLASSIC_RCU
bool "Classic RCU"
@@ -975,18 +975,23 @@ config COMPAT_BRK
choice
prompt "Choose SLAB allocator"
- default SLUB
+ default SLQB_ALLOCATOR
help
This option allows to select a slab allocator.
-config SLAB
+config SLAB_ALLOCATOR
bool "SLAB"
help
The regular slab allocator that is established and known to work
well in all environments. It organizes cache hot objects in
per cpu and per node queues.
-config SLUB
+config SLAB
+ bool
+ default y
+ depends on SLAB_ALLOCATOR
+
+config SLUB_ALLOCATOR
bool "SLUB (Unqueued Allocator)"
help
SLUB is a slab allocator that minimizes cache line usage
@@ -996,6 +1001,21 @@ config SLUB
and has enhanced diagnostics. SLUB is the default choice for
a slab allocator.
+config SLUB
+ bool
+ default y
+ depends on SLUB_ALLOCATOR
+
+config SLQB_ALLOCATOR
+ bool "SLQB (Queued allocator)"
+ help
+ SLQB is a proposed new slab allocator.
+
+config SLQB
+ bool
+ default y
+ depends on SLQB_ALLOCATOR
+
config SLOB
depends on EMBEDDED
bool "SLOB (Simple Allocator)"
@@ -1051,7 +1071,7 @@ config HAVE_GENERIC_DMA_COHERENT
config SLABINFO
bool
depends on PROC_FS
- depends on SLAB || SLUB_DEBUG
+ depends on SLAB || SLUB_DEBUG || SLQB
default y
config RT_MUTEXES
diff --git a/init/initramfs.c b/init/initramfs.c
index 80cd713f6cc5..4c00edc59689 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -310,7 +310,8 @@ static int __init do_name(void)
if (wfd >= 0) {
sys_fchown(wfd, uid, gid);
sys_fchmod(wfd, mode);
- sys_ftruncate(wfd, body_len);
+ if (body_len)
+ sys_ftruncate(wfd, body_len);
vcollected = kstrdup(collected, GFP_KERNEL);
state = CopyFile;
}
@@ -515,6 +516,7 @@ skip:
initrd_end = 0;
}
+#ifdef CONFIG_BLK_DEV_RAM
#define BUF_SIZE 1024
static void __init clean_rootfs(void)
{
@@ -561,6 +563,7 @@ static void __init clean_rootfs(void)
sys_close(fd);
kfree(buf);
}
+#endif
static int __init populate_rootfs(void)
{
@@ -571,11 +574,10 @@ static int __init populate_rootfs(void)
if (initrd_start) {
#ifdef CONFIG_BLK_DEV_RAM
int fd;
- printk(KERN_INFO "checking if image is initramfs...\n");
+ printk(KERN_INFO "Trying to unpack rootfs image as initramfs...\n");
err = unpack_to_rootfs((char *)initrd_start,
initrd_end - initrd_start);
if (!err) {
- printk(KERN_INFO "rootfs image is initramfs; unpacking...\n");
free_initrd();
return 0;
} else {
@@ -593,15 +595,11 @@ static int __init populate_rootfs(void)
free_initrd();
}
#else
- printk(KERN_INFO "Unpacking initramfs...");
+ printk(KERN_INFO "Unpacking initramfs...\n");
err = unpack_to_rootfs((char *)initrd_start,
initrd_end - initrd_start);
- if (err) {
- printk(" failed!\n");
- printk(KERN_EMERG "%s\n", err);
- } else {
- printk(" done\n");
- }
+ if (err)
+ printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);
free_initrd();
#endif
}
diff --git a/init/main.c b/init/main.c
index 3585f073d636..cc619415fa9a 100644
--- a/init/main.c
+++ b/init/main.c
@@ -56,6 +56,7 @@
#include <linux/debug_locks.h>
#include <linux/debugobjects.h>
#include <linux/lockdep.h>
+#include <linux/kmemleak.h>
#include <linux/pid_namespace.h>
#include <linux/device.h>
#include <linux/kthread.h>
@@ -64,6 +65,7 @@
#include <linux/idr.h>
#include <linux/ftrace.h>
#include <linux/async.h>
+#include <linux/kmemtrace.h>
#include <trace/boot.h>
#include <asm/io.h>
@@ -71,7 +73,6 @@
#include <asm/setup.h>
#include <asm/sections.h>
#include <asm/cacheflush.h>
-#include <trace/kmemtrace.h>
#ifdef CONFIG_X86_LOCAL_APIC
#include <asm/smp.h>
@@ -492,6 +493,11 @@ static int __init do_early_param(char *param, char *val)
return 0;
}
+void __init parse_early_options(char *cmdline)
+{
+ parse_args("early options", cmdline, NULL, 0, do_early_param);
+}
+
/* Arch code calls this early on, or if not, just before other parsing. */
void __init parse_early_param(void)
{
@@ -503,7 +509,7 @@ void __init parse_early_param(void)
/* All fall through to do_early_param. */
strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
- parse_args("early options", tmp_cmdline, NULL, 0, do_early_param);
+ parse_early_options(tmp_cmdline);
done = 1;
}
@@ -599,6 +605,7 @@ asmlinkage void __init start_kernel(void)
/* init some links before init_ISA_irqs() */
early_irq_init();
init_IRQ();
+ prio_tree_init();
pidhash_init();
init_timers();
hrtimers_init();
@@ -647,9 +654,9 @@ asmlinkage void __init start_kernel(void)
page_cgroup_init();
mem_init();
enable_debug_pagealloc();
- cpu_hotplug_init();
kmem_cache_init();
kmemtrace_init();
+ kmemleak_init();
debug_objects_mem_init();
idr_init_cache();
setup_per_cpu_pageset();
@@ -659,7 +666,6 @@ asmlinkage void __init start_kernel(void)
calibrate_delay();
pidmap_init();
pgtable_cache_init();
- prio_tree_init();
anon_vma_init();
#ifdef CONFIG_X86
if (efi_enabled)
diff --git a/ipc/mq_sysctl.c b/ipc/mq_sysctl.c
index 89f60ec8ee54..24ae46dfe45d 100644
--- a/ipc/mq_sysctl.c
+++ b/ipc/mq_sysctl.c
@@ -22,6 +22,7 @@
#define MIN_MSGSIZEMAX 128 /* min value for msgsize_max */
#define MAX_MSGSIZEMAX (8192*128) /* max value for msgsize_max */
+#ifdef CONFIG_PROC_SYSCTL
static void *get_mq(ctl_table *table)
{
char *which = table->data;
@@ -30,7 +31,6 @@ static void *get_mq(ctl_table *table)
return which;
}
-#ifdef CONFIG_PROC_SYSCTL
static int proc_mq_dointvec(ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
diff --git a/ipc/sem.c b/ipc/sem.c
index 16a2189e96f9..87c2b641fd7b 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -1290,8 +1290,8 @@ void exit_sem(struct task_struct *tsk)
int i;
rcu_read_lock();
- un = list_entry(rcu_dereference(ulp->list_proc.next),
- struct sem_undo, list_proc);
+ un = list_entry_rcu(ulp->list_proc.next,
+ struct sem_undo, list_proc);
if (&un->list_proc == &ulp->list_proc)
semid = -1;
else
diff --git a/kernel/Makefile b/kernel/Makefile
index 42423665660a..a35eee3436de 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -93,6 +93,7 @@ obj-$(CONFIG_LATENCYTOP) += latencytop.o
obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
obj-$(CONFIG_FUNCTION_TRACER) += trace/
obj-$(CONFIG_TRACING) += trace/
+obj-$(CONFIG_X86_DS) += trace/
obj-$(CONFIG_SMP) += sched_cpupri.o
obj-$(CONFIG_SLOW_WORK) += slow-work.o
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index 917ab9525568..1f6396d76687 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -568,7 +568,7 @@ void audit_trim_trees(void)
if (err)
goto skip_it;
- root_mnt = collect_mounts(path.mnt, path.dentry);
+ root_mnt = collect_mounts(&path);
path_put(&path);
if (!root_mnt)
goto skip_it;
@@ -660,7 +660,7 @@ int audit_add_tree_rule(struct audit_krule *rule)
err = kern_path(tree->pathname, 0, &path);
if (err)
goto Err;
- mnt = collect_mounts(path.mnt, path.dentry);
+ mnt = collect_mounts(&path);
path_put(&path);
if (!mnt) {
err = -ENOMEM;
@@ -720,7 +720,7 @@ int audit_tag_tree(char *old, char *new)
err = kern_path(new, 0, &path);
if (err)
return err;
- tagged = collect_mounts(path.mnt, path.dentry);
+ tagged = collect_mounts(&path);
path_put(&path);
if (!tagged)
return -ENOMEM;
@@ -734,9 +734,6 @@ int audit_tag_tree(char *old, char *new)
dentry = dget(path.dentry);
path_put(&path);
- 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);
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index a6fe71fd5d1b..713098ee5a02 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1028,7 +1028,7 @@ static void audit_update_watch(struct audit_parent *parent,
if (audit_enabled) {
struct audit_buffer *ab;
- ab = audit_log_start(NULL, GFP_KERNEL,
+ ab = audit_log_start(NULL, GFP_NOFS,
AUDIT_CONFIG_CHANGE);
audit_log_format(ab, "auid=%u ses=%u",
audit_get_loginuid(current),
@@ -1067,7 +1067,7 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
e = container_of(r, struct audit_entry, rule);
if (audit_enabled) {
struct audit_buffer *ab;
- ab = audit_log_start(NULL, GFP_KERNEL,
+ ab = audit_log_start(NULL, GFP_NOFS,
AUDIT_CONFIG_CHANGE);
audit_log_format(ab, "auid=%u ses=%u",
audit_get_loginuid(current),
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 382109b5baeb..a7267bfd3765 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1133,8 +1133,7 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
free_cg_links:
free_cg_links(&tmp_cg_links);
drop_new_super:
- up_write(&sb->s_umount);
- deactivate_super(sb);
+ deactivate_locked_super(sb);
return ret;
}
diff --git a/kernel/compat.c b/kernel/compat.c
index 42d56544460f..f6c204f07ea6 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -882,6 +882,17 @@ compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese,
}
+asmlinkage long
+compat_sys_rt_tgsigqueueinfo(compat_pid_t tgid, compat_pid_t pid, int sig,
+ struct compat_siginfo __user *uinfo)
+{
+ siginfo_t info;
+
+ if (copy_siginfo_from_user32(&info, uinfo))
+ return -EFAULT;
+ return do_rt_tgsigqueueinfo(tgid, pid, sig, &info);
+}
+
#ifdef __ARCH_WANT_COMPAT_SYS_TIME
/* compat_time_t is a 32 bit "long" and needs to get converted. */
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 395b6974dc8d..609fae119e57 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -34,14 +34,9 @@ static struct {
* an ongoing cpu hotplug operation.
*/
int refcount;
-} cpu_hotplug;
-
-void __init cpu_hotplug_init(void)
-{
- cpu_hotplug.active_writer = NULL;
- mutex_init(&cpu_hotplug.lock);
- cpu_hotplug.refcount = 0;
-}
+} cpu_hotplug = {
+ .lock = __MUTEX_INITIALIZER(cpu_hotplug.lock),
+};
#ifdef CONFIG_HOTPLUG_CPU
diff --git a/kernel/cred.c b/kernel/cred.c
index 3a039189d707..1bb4d7e5d616 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -167,7 +167,7 @@ EXPORT_SYMBOL(prepare_creds);
/*
* Prepare credentials for current to perform an execve()
- * - The caller must hold current->cred_exec_mutex
+ * - The caller must hold current->cred_guard_mutex
*/
struct cred *prepare_exec_creds(void)
{
@@ -276,7 +276,7 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
struct cred *new;
int ret;
- mutex_init(&p->cred_exec_mutex);
+ mutex_init(&p->cred_guard_mutex);
if (
#ifdef CONFIG_KEYS
diff --git a/kernel/exit.c b/kernel/exit.c
index abf9cf3b95c6..51d1fe3fb7ad 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -48,7 +48,7 @@
#include <linux/tracehook.h>
#include <linux/fs_struct.h>
#include <linux/init_task.h>
-#include <trace/sched.h>
+#include <trace/events/sched.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -56,10 +56,6 @@
#include <asm/mmu_context.h>
#include "cred-internals.h"
-DEFINE_TRACE(sched_process_free);
-DEFINE_TRACE(sched_process_exit);
-DEFINE_TRACE(sched_process_wait);
-
static void exit_mm(struct task_struct * tsk);
static void __unhash_process(struct task_struct *p)
@@ -1476,6 +1472,7 @@ static int wait_consider_task(struct task_struct *parent, int ptrace,
*/
if (*notask_error)
*notask_error = ret;
+ return 0;
}
if (likely(!ptrace) && unlikely(p->ptrace)) {
diff --git a/kernel/fork.c b/kernel/fork.c
index b9e2edd00726..711468f3db2a 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -61,7 +61,6 @@
#include <linux/proc_fs.h>
#include <linux/blkdev.h>
#include <linux/fs_struct.h>
-#include <trace/sched.h>
#include <linux/magic.h>
#include <asm/pgtable.h>
@@ -71,6 +70,8 @@
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
+#include <trace/events/sched.h>
+
/*
* Protected counters by write_lock_irq(&tasklist_lock)
*/
@@ -83,8 +84,6 @@ DEFINE_PER_CPU(unsigned long, process_counts) = 0;
__cacheline_aligned DEFINE_RWLOCK(tasklist_lock); /* outer */
-DEFINE_TRACE(sched_process_fork);
-
int nr_processes(void)
{
int cpu;
@@ -1089,8 +1088,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
#ifdef CONFIG_DEBUG_MUTEXES
p->blocked_on = NULL; /* not blocked yet */
#endif
- if (unlikely(current->ptrace))
- ptrace_fork(p, clone_flags);
+
+ p->bts = NULL;
/* Perform scheduler related setup. Assign this task to a CPU. */
sched_fork(p, clone_flags);
diff --git a/kernel/futex.c b/kernel/futex.c
index eef8cd26b5e5..0c406a3ddc37 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -19,6 +19,10 @@
* PRIVATE futexes by Eric Dumazet
* Copyright (C) 2007 Eric Dumazet <dada1@cosmosbay.com>
*
+ * Requeue-PI support by Darren Hart <dvhltc@us.ibm.com>
+ * Copyright (C) IBM Corporation, 2009
+ * Thanks to Thomas Gleixner for conceptual design and careful reviews.
+ *
* Thanks to Ben LaHaise for yelling "hashed waitqueues" loudly
* enough at me, Linus for the original (flawed) idea, Matthew
* Kirkwood for proof-of-concept implementation.
@@ -109,6 +113,9 @@ struct futex_q {
struct futex_pi_state *pi_state;
struct task_struct *task;
+ /* rt_waiter storage for requeue_pi: */
+ struct rt_mutex_waiter *rt_waiter;
+
/* Bitset for the optional bitmasked wakeup */
u32 bitset;
};
@@ -276,6 +283,25 @@ void put_futex_key(int fshared, union futex_key *key)
drop_futex_key_refs(key);
}
+/**
+ * futex_top_waiter() - Return the highest priority waiter on a futex
+ * @hb: the hash bucket the futex_q's reside in
+ * @key: the futex key (to distinguish it from other futex futex_q's)
+ *
+ * Must be called with the hb lock held.
+ */
+static struct futex_q *futex_top_waiter(struct futex_hash_bucket *hb,
+ union futex_key *key)
+{
+ struct futex_q *this;
+
+ plist_for_each_entry(this, &hb->chain, list) {
+ if (match_futex(&this->key, key))
+ return this;
+ }
+ return NULL;
+}
+
static u32 cmpxchg_futex_value_locked(u32 __user *uaddr, u32 uval, u32 newval)
{
u32 curval;
@@ -537,6 +563,131 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
return 0;
}
+/**
+ * futex_lock_pi_atomic() - atomic work required to acquire a pi aware futex
+ * @uaddr: the pi futex user address
+ * @hb: the pi futex hash bucket
+ * @key: the futex key associated with uaddr and hb
+ * @ps: the pi_state pointer where we store the result of the
+ * lookup
+ * @task: the task to perform the atomic lock work for. This will
+ * be "current" except in the case of requeue pi.
+ * @set_waiters: force setting the FUTEX_WAITERS bit (1) or not (0)
+ *
+ * Returns:
+ * 0 - ready to wait
+ * 1 - acquired the lock
+ * <0 - error
+ *
+ * The hb->lock and futex_key refs shall be held by the caller.
+ */
+static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb,
+ union futex_key *key,
+ struct futex_pi_state **ps,
+ struct task_struct *task, int set_waiters)
+{
+ int lock_taken, ret, ownerdied = 0;
+ u32 uval, newval, curval;
+
+retry:
+ ret = lock_taken = 0;
+
+ /*
+ * To avoid races, we attempt to take the lock here again
+ * (by doing a 0 -> TID atomic cmpxchg), while holding all
+ * the locks. It will most likely not succeed.
+ */
+ newval = task_pid_vnr(task);
+ if (set_waiters)
+ newval |= FUTEX_WAITERS;
+
+ curval = cmpxchg_futex_value_locked(uaddr, 0, newval);
+
+ if (unlikely(curval == -EFAULT))
+ return -EFAULT;
+
+ /*
+ * Detect deadlocks.
+ */
+ if ((unlikely((curval & FUTEX_TID_MASK) == task_pid_vnr(task))))
+ return -EDEADLK;
+
+ /*
+ * Surprise - we got the lock. Just return to userspace:
+ */
+ if (unlikely(!curval))
+ return 1;
+
+ uval = curval;
+
+ /*
+ * Set the FUTEX_WAITERS flag, so the owner will know it has someone
+ * to wake at the next unlock.
+ */
+ newval = curval | FUTEX_WAITERS;
+
+ /*
+ * There are two cases, where a futex might have no owner (the
+ * owner TID is 0): OWNER_DIED. We take over the futex in this
+ * case. We also do an unconditional take over, when the owner
+ * of the futex died.
+ *
+ * This is safe as we are protected by the hash bucket lock !
+ */
+ if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) {
+ /* Keep the OWNER_DIED bit */
+ newval = (curval & ~FUTEX_TID_MASK) | task_pid_vnr(task);
+ ownerdied = 0;
+ lock_taken = 1;
+ }
+
+ curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
+
+ if (unlikely(curval == -EFAULT))
+ return -EFAULT;
+ if (unlikely(curval != uval))
+ goto retry;
+
+ /*
+ * We took the lock due to owner died take over.
+ */
+ if (unlikely(lock_taken))
+ return 1;
+
+ /*
+ * We dont have the lock. Look up the PI state (or create it if
+ * we are the first waiter):
+ */
+ ret = lookup_pi_state(uval, hb, key, ps);
+
+ if (unlikely(ret)) {
+ switch (ret) {
+ case -ESRCH:
+ /*
+ * No owner found for this futex. Check if the
+ * OWNER_DIED bit is set to figure out whether
+ * this is a robust futex or not.
+ */
+ if (get_futex_value_locked(&curval, uaddr))
+ return -EFAULT;
+
+ /*
+ * We simply start over in case of a robust
+ * futex. The code above will take the futex
+ * and return happy.
+ */
+ if (curval & FUTEX_OWNER_DIED) {
+ ownerdied = 1;
+ goto retry;
+ }
+ default:
+ break;
+ }
+ }
+
+ return ret;
+}
+
/*
* The hash bucket lock must be held when this is called.
* Afterwards, the futex_q must not be accessed.
@@ -687,7 +838,7 @@ static int futex_wake(u32 __user *uaddr, int fshared, int nr_wake, u32 bitset)
plist_for_each_entry_safe(this, next, head, list) {
if (match_futex (&this->key, &key)) {
- if (this->pi_state) {
+ if (this->pi_state || this->rt_waiter) {
ret = -EINVAL;
break;
}
@@ -800,20 +951,180 @@ out:
return ret;
}
-/*
- * Requeue all waiters hashed on one physical page to another
- * physical page.
+/**
+ * requeue_futex() - Requeue a futex_q from one hb to another
+ * @q: the futex_q to requeue
+ * @hb1: the source hash_bucket
+ * @hb2: the target hash_bucket
+ * @key2: the new key for the requeued futex_q
+ */
+static inline
+void requeue_futex(struct futex_q *q, struct futex_hash_bucket *hb1,
+ struct futex_hash_bucket *hb2, union futex_key *key2)
+{
+
+ /*
+ * If key1 and key2 hash to the same bucket, no need to
+ * requeue.
+ */
+ if (likely(&hb1->chain != &hb2->chain)) {
+ plist_del(&q->list, &hb1->chain);
+ plist_add(&q->list, &hb2->chain);
+ q->lock_ptr = &hb2->lock;
+#ifdef CONFIG_DEBUG_PI_LIST
+ q->list.plist.lock = &hb2->lock;
+#endif
+ }
+ get_futex_key_refs(key2);
+ q->key = *key2;
+}
+
+/**
+ * requeue_pi_wake_futex() - Wake a task that acquired the lock during requeue
+ * q: the futex_q
+ * key: the key of the requeue target futex
+ *
+ * During futex_requeue, with requeue_pi=1, it is possible to acquire the
+ * target futex if it is uncontended or via a lock steal. Set the futex_q key
+ * to the requeue target futex so the waiter can detect the wakeup on the right
+ * futex, but remove it from the hb and NULL the rt_waiter so it can detect
+ * atomic lock acquisition. Must be called with the q->lock_ptr held.
+ */
+static inline
+void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key)
+{
+ drop_futex_key_refs(&q->key);
+ get_futex_key_refs(key);
+ q->key = *key;
+
+ WARN_ON(plist_node_empty(&q->list));
+ plist_del(&q->list, &q->list.plist);
+
+ WARN_ON(!q->rt_waiter);
+ q->rt_waiter = NULL;
+
+ wake_up(&q->waiter);
+}
+
+/**
+ * futex_proxy_trylock_atomic() - Attempt an atomic lock for the top waiter
+ * @pifutex: the user address of the to futex
+ * @hb1: the from futex hash bucket, must be locked by the caller
+ * @hb2: the to futex hash bucket, must be locked by the caller
+ * @key1: the from futex key
+ * @key2: the to futex key
+ * @ps: address to store the pi_state pointer
+ * @set_waiters: force setting the FUTEX_WAITERS bit (1) or not (0)
+ *
+ * Try and get the lock on behalf of the top waiter if we can do it atomically.
+ * Wake the top waiter if we succeed. If the caller specified set_waiters,
+ * then direct futex_lock_pi_atomic() to force setting the FUTEX_WAITERS bit.
+ * hb1 and hb2 must be held by the caller.
+ *
+ * Returns:
+ * 0 - failed to acquire the lock atomicly
+ * 1 - acquired the lock
+ * <0 - error
+ */
+static int futex_proxy_trylock_atomic(u32 __user *pifutex,
+ struct futex_hash_bucket *hb1,
+ struct futex_hash_bucket *hb2,
+ union futex_key *key1, union futex_key *key2,
+ struct futex_pi_state **ps, int set_waiters)
+{
+ struct futex_q *top_waiter = NULL;
+ u32 curval;
+ int ret;
+
+ if (get_futex_value_locked(&curval, pifutex))
+ return -EFAULT;
+
+ /*
+ * Find the top_waiter and determine if there are additional waiters.
+ * If the caller intends to requeue more than 1 waiter to pifutex,
+ * force futex_lock_pi_atomic() to set the FUTEX_WAITERS bit now,
+ * as we have means to handle the possible fault. If not, don't set
+ * the bit unecessarily as it will force the subsequent unlock to enter
+ * the kernel.
+ */
+ top_waiter = futex_top_waiter(hb1, key1);
+
+ /* There are no waiters, nothing for us to do. */
+ if (!top_waiter)
+ return 0;
+
+ /*
+ * Try to take the lock for top_waiter. Set the FUTEX_WAITERS bit in
+ * the contended case or if set_waiters is 1. The pi_state is returned
+ * in ps in contended cases.
+ */
+ ret = futex_lock_pi_atomic(pifutex, hb2, key2, ps, top_waiter->task,
+ set_waiters);
+ if (ret == 1)
+ requeue_pi_wake_futex(top_waiter, key2);
+
+ return ret;
+}
+
+/**
+ * futex_requeue() - Requeue waiters from uaddr1 to uaddr2
+ * uaddr1: source futex user address
+ * uaddr2: target futex user address
+ * nr_wake: number of waiters to wake (must be 1 for requeue_pi)
+ * nr_requeue: number of waiters to requeue (0-INT_MAX)
+ * requeue_pi: if we are attempting to requeue from a non-pi futex to a
+ * pi futex (pi to pi requeue is not supported)
+ *
+ * Requeue waiters on uaddr1 to uaddr2. In the requeue_pi case, try to acquire
+ * uaddr2 atomically on behalf of the top waiter.
+ *
+ * Returns:
+ * >=0 - on success, the number of tasks requeued or woken
+ * <0 - on error
*/
static int futex_requeue(u32 __user *uaddr1, int fshared, u32 __user *uaddr2,
- int nr_wake, int nr_requeue, u32 *cmpval)
+ int nr_wake, int nr_requeue, u32 *cmpval,
+ int requeue_pi)
{
union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT;
+ int drop_count = 0, task_count = 0, ret;
+ struct futex_pi_state *pi_state = NULL;
struct futex_hash_bucket *hb1, *hb2;
struct plist_head *head1;
struct futex_q *this, *next;
- int ret, drop_count = 0;
+ u32 curval2;
+
+ if (requeue_pi) {
+ /*
+ * requeue_pi requires a pi_state, try to allocate it now
+ * without any locks in case it fails.
+ */
+ if (refill_pi_state_cache())
+ return -ENOMEM;
+ /*
+ * requeue_pi must wake as many tasks as it can, up to nr_wake
+ * + nr_requeue, since it acquires the rt_mutex prior to
+ * returning to userspace, so as to not leave the rt_mutex with
+ * waiters and no owner. However, second and third wake-ups
+ * cannot be predicted as they involve race conditions with the
+ * first wake and a fault while looking up the pi_state. Both
+ * pthread_cond_signal() and pthread_cond_broadcast() should
+ * use nr_wake=1.
+ */
+ if (nr_wake != 1)
+ return -EINVAL;
+ }
retry:
+ if (pi_state != NULL) {
+ /*
+ * We will have to lookup the pi_state again, so free this one
+ * to keep the accounting correct.
+ */
+ free_pi_state(pi_state);
+ pi_state = NULL;
+ }
+
ret = get_futex_key(uaddr1, fshared, &key1);
if (unlikely(ret != 0))
goto out;
@@ -852,32 +1163,99 @@ retry_private:
}
}
+ if (requeue_pi && (task_count - nr_wake < nr_requeue)) {
+ /*
+ * Attempt to acquire uaddr2 and wake the top waiter. If we
+ * intend to requeue waiters, force setting the FUTEX_WAITERS
+ * bit. We force this here where we are able to easily handle
+ * faults rather in the requeue loop below.
+ */
+ ret = futex_proxy_trylock_atomic(uaddr2, hb1, hb2, &key1,
+ &key2, &pi_state, nr_requeue);
+
+ /*
+ * At this point the top_waiter has either taken uaddr2 or is
+ * waiting on it. If the former, then the pi_state will not
+ * exist yet, look it up one more time to ensure we have a
+ * reference to it.
+ */
+ if (ret == 1) {
+ WARN_ON(pi_state);
+ task_count++;
+ ret = get_futex_value_locked(&curval2, uaddr2);
+ if (!ret)
+ ret = lookup_pi_state(curval2, hb2, &key2,
+ &pi_state);
+ }
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EFAULT:
+ double_unlock_hb(hb1, hb2);
+ put_futex_key(fshared, &key2);
+ put_futex_key(fshared, &key1);
+ ret = get_user(curval2, uaddr2);
+ if (!ret)
+ goto retry;
+ goto out;
+ case -EAGAIN:
+ /* The owner was exiting, try again. */
+ double_unlock_hb(hb1, hb2);
+ put_futex_key(fshared, &key2);
+ put_futex_key(fshared, &key1);
+ cond_resched();
+ goto retry;
+ default:
+ goto out_unlock;
+ }
+ }
+
head1 = &hb1->chain;
plist_for_each_entry_safe(this, next, head1, list) {
- if (!match_futex (&this->key, &key1))
+ if (task_count - nr_wake >= nr_requeue)
+ break;
+
+ if (!match_futex(&this->key, &key1))
continue;
- if (++ret <= nr_wake) {
+
+ WARN_ON(!requeue_pi && this->rt_waiter);
+ WARN_ON(requeue_pi && !this->rt_waiter);
+
+ /*
+ * Wake nr_wake waiters. For requeue_pi, if we acquired the
+ * lock, we already woke the top_waiter. If not, it will be
+ * woken by futex_unlock_pi().
+ */
+ if (++task_count <= nr_wake && !requeue_pi) {
wake_futex(this);
- } else {
- /*
- * If key1 and key2 hash to the same bucket, no need to
- * requeue.
- */
- if (likely(head1 != &hb2->chain)) {
- plist_del(&this->list, &hb1->chain);
- plist_add(&this->list, &hb2->chain);
- this->lock_ptr = &hb2->lock;
-#ifdef CONFIG_DEBUG_PI_LIST
- this->list.plist.lock = &hb2->lock;
-#endif
- }
- this->key = key2;
- get_futex_key_refs(&key2);
- drop_count++;
+ continue;
+ }
- if (ret - nr_wake >= nr_requeue)
- break;
+ /*
+ * Requeue nr_requeue waiters and possibly one more in the case
+ * of requeue_pi if we couldn't acquire the lock atomically.
+ */
+ if (requeue_pi) {
+ /* Prepare the waiter to take the rt_mutex. */
+ atomic_inc(&pi_state->refcount);
+ this->pi_state = pi_state;
+ ret = rt_mutex_start_proxy_lock(&pi_state->pi_mutex,
+ this->rt_waiter,
+ this->task, 1);
+ if (ret == 1) {
+ /* We got the lock. */
+ requeue_pi_wake_futex(this, &key2);
+ continue;
+ } else if (ret) {
+ /* -EDEADLK */
+ this->pi_state = NULL;
+ free_pi_state(pi_state);
+ goto out_unlock;
+ }
}
+ requeue_futex(this, hb1, hb2, &key2);
+ drop_count++;
}
out_unlock:
@@ -897,7 +1275,9 @@ out_put_keys:
out_put_key1:
put_futex_key(fshared, &key1);
out:
- return ret;
+ if (pi_state != NULL)
+ free_pi_state(pi_state);
+ return ret ? ret : task_count;
}
/* The key must be already stored in q->key. */
@@ -1117,35 +1497,160 @@ handle_fault:
*/
#define FLAGS_SHARED 0x01
#define FLAGS_CLOCKRT 0x02
+#define FLAGS_HAS_TIMEOUT 0x04
static long futex_wait_restart(struct restart_block *restart);
+static long futex_lock_pi_restart(struct restart_block *restart);
-static int futex_wait(u32 __user *uaddr, int fshared,
- u32 val, ktime_t *abs_time, u32 bitset, int clockrt)
+/**
+ * fixup_owner() - Post lock pi_state and corner case management
+ * @uaddr: user address of the futex
+ * @fshared: whether the futex is shared (1) or not (0)
+ * @q: futex_q (contains pi_state and access to the rt_mutex)
+ * @locked: if the attempt to take the rt_mutex succeeded (1) or not (0)
+ *
+ * After attempting to lock an rt_mutex, this function is called to cleanup
+ * the pi_state owner as well as handle race conditions that may allow us to
+ * acquire the lock. Must be called with the hb lock held.
+ *
+ * Returns:
+ * 1 - success, lock taken
+ * 0 - success, lock not taken
+ * <0 - on error (-EFAULT)
+ */
+static int fixup_owner(u32 __user *uaddr, int fshared, struct futex_q *q,
+ int locked)
{
- struct task_struct *curr = current;
- struct restart_block *restart;
- DECLARE_WAITQUEUE(wait, curr);
- struct futex_hash_bucket *hb;
- struct futex_q q;
- u32 uval;
- int ret;
- struct hrtimer_sleeper t;
- int rem = 0;
+ struct task_struct *owner;
+ int ret = 0;
- if (!bitset)
- return -EINVAL;
+ if (locked) {
+ /*
+ * Got the lock. We might not be the anticipated owner if we
+ * did a lock-steal - fix up the PI-state in that case:
+ */
+ if (q->pi_state->owner != current)
+ ret = fixup_pi_state_owner(uaddr, q, current, fshared);
+ goto out;
+ }
- q.pi_state = NULL;
- q.bitset = bitset;
-retry:
- q.key = FUTEX_KEY_INIT;
- ret = get_futex_key(uaddr, fshared, &q.key);
- if (unlikely(ret != 0))
+ /*
+ * Catch the rare case, where the lock was released when we were on the
+ * way back before we locked the hash bucket.
+ */
+ if (q->pi_state->owner == current) {
+ /*
+ * Try to get the rt_mutex now. This might fail as some other
+ * task acquired the rt_mutex after we removed ourself from the
+ * rt_mutex waiters list.
+ */
+ if (rt_mutex_trylock(&q->pi_state->pi_mutex)) {
+ locked = 1;
+ goto out;
+ }
+
+ /*
+ * pi_state is incorrect, some other task did a lock steal and
+ * we returned due to timeout or signal without taking the
+ * rt_mutex. Too late. We can access the rt_mutex_owner without
+ * locking, as the other task is now blocked on the hash bucket
+ * lock. Fix the state up.
+ */
+ owner = rt_mutex_owner(&q->pi_state->pi_mutex);
+ ret = fixup_pi_state_owner(uaddr, q, owner, fshared);
goto out;
+ }
-retry_private:
- hb = queue_lock(&q);
+ /*
+ * Paranoia check. If we did not take the lock, then we should not be
+ * the owner, nor the pending owner, of the rt_mutex.
+ */
+ if (rt_mutex_owner(&q->pi_state->pi_mutex) == current)
+ printk(KERN_ERR "fixup_owner: ret = %d pi-mutex: %p "
+ "pi-state %p\n", ret,
+ q->pi_state->pi_mutex.owner,
+ q->pi_state->owner);
+
+out:
+ return ret ? ret : locked;
+}
+
+/**
+ * futex_wait_queue_me() - queue_me() and wait for wakeup, timeout, or signal
+ * @hb: the futex hash bucket, must be locked by the caller
+ * @q: the futex_q to queue up on
+ * @timeout: the prepared hrtimer_sleeper, or null for no timeout
+ * @wait: the wait_queue to add to the futex_q after queueing in the hb
+ */
+static void futex_wait_queue_me(struct futex_hash_bucket *hb, struct futex_q *q,
+ struct hrtimer_sleeper *timeout,
+ wait_queue_t *wait)
+{
+ queue_me(q, hb);
+
+ /*
+ * There might have been scheduling since the queue_me(), as we
+ * cannot hold a spinlock across the get_user() in case it
+ * faults, and we cannot just set TASK_INTERRUPTIBLE state when
+ * queueing ourselves into the futex hash. This code thus has to
+ * rely on the futex_wake() code removing us from hash when it
+ * wakes us up.
+ */
+
+ /* add_wait_queue is the barrier after __set_current_state. */
+ __set_current_state(TASK_INTERRUPTIBLE);
+
+ /*
+ * Add current as the futex_q waiter. We don't remove ourselves from
+ * the wait_queue because we are the only user of it.
+ */
+ add_wait_queue(&q->waiter, wait);
+
+ /* Arm the timer */
+ if (timeout) {
+ hrtimer_start_expires(&timeout->timer, HRTIMER_MODE_ABS);
+ if (!hrtimer_active(&timeout->timer))
+ timeout->task = NULL;
+ }
+
+ /*
+ * !plist_node_empty() is safe here without any lock.
+ * q.lock_ptr != 0 is not safe, because of ordering against wakeup.
+ */
+ if (likely(!plist_node_empty(&q->list))) {
+ /*
+ * If the timer has already expired, current will already be
+ * flagged for rescheduling. Only call schedule if there
+ * is no timeout, or if it has yet to expire.
+ */
+ if (!timeout || timeout->task)
+ schedule();
+ }
+ __set_current_state(TASK_RUNNING);
+}
+
+/**
+ * futex_wait_setup() - Prepare to wait on a futex
+ * @uaddr: the futex userspace address
+ * @val: the expected value
+ * @fshared: whether the futex is shared (1) or not (0)
+ * @q: the associated futex_q
+ * @hb: storage for hash_bucket pointer to be returned to caller
+ *
+ * Setup the futex_q and locate the hash_bucket. Get the futex value and
+ * compare it with the expected value. Handle atomic faults internally.
+ * Return with the hb lock held and a q.key reference on success, and unlocked
+ * with no q.key reference on failure.
+ *
+ * Returns:
+ * 0 - uaddr contains val and hb has been locked
+ * <1 - -EFAULT or -EWOULDBLOCK (uaddr does not contain val) and hb is unlcoked
+ */
+static int futex_wait_setup(u32 __user *uaddr, u32 val, int fshared,
+ struct futex_q *q, struct futex_hash_bucket **hb)
+{
+ u32 uval;
+ int ret;
/*
* Access the page AFTER the hash-bucket is locked.
@@ -1163,95 +1668,84 @@ retry_private:
* A consequence is that futex_wait() can return zero and absorb
* a wakeup when *uaddr != val on entry to the syscall. This is
* rare, but normal.
- *
- * For shared futexes, we hold the mmap semaphore, so the mapping
- * cannot have changed since we looked it up in get_futex_key.
*/
+retry:
+ q->key = FUTEX_KEY_INIT;
+ ret = get_futex_key(uaddr, fshared, &q->key);
+ if (unlikely(ret != 0))
+ return ret;
+
+retry_private:
+ *hb = queue_lock(q);
+
ret = get_futex_value_locked(&uval, uaddr);
- if (unlikely(ret)) {
- queue_unlock(&q, hb);
+ if (ret) {
+ queue_unlock(q, *hb);
ret = get_user(uval, uaddr);
if (ret)
- goto out_put_key;
+ goto out;
if (!fshared)
goto retry_private;
- put_futex_key(fshared, &q.key);
+ put_futex_key(fshared, &q->key);
goto retry;
}
- ret = -EWOULDBLOCK;
- if (unlikely(uval != val)) {
- queue_unlock(&q, hb);
- goto out_put_key;
- }
- /* Only actually queue if *uaddr contained val. */
- queue_me(&q, hb);
+ if (uval != val) {
+ queue_unlock(q, *hb);
+ ret = -EWOULDBLOCK;
+ }
- /*
- * There might have been scheduling since the queue_me(), as we
- * cannot hold a spinlock across the get_user() in case it
- * faults, and we cannot just set TASK_INTERRUPTIBLE state when
- * queueing ourselves into the futex hash. This code thus has to
- * rely on the futex_wake() code removing us from hash when it
- * wakes us up.
- */
+out:
+ if (ret)
+ put_futex_key(fshared, &q->key);
+ return ret;
+}
- /* add_wait_queue is the barrier after __set_current_state. */
- __set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&q.waiter, &wait);
- /*
- * !plist_node_empty() is safe here without any lock.
- * q.lock_ptr != 0 is not safe, because of ordering against wakeup.
- */
- if (likely(!plist_node_empty(&q.list))) {
- if (!abs_time)
- schedule();
- else {
- hrtimer_init_on_stack(&t.timer,
- clockrt ? CLOCK_REALTIME :
- CLOCK_MONOTONIC,
- HRTIMER_MODE_ABS);
- hrtimer_init_sleeper(&t, current);
- hrtimer_set_expires_range_ns(&t.timer, *abs_time,
- current->timer_slack_ns);
-
- hrtimer_start_expires(&t.timer, HRTIMER_MODE_ABS);
- if (!hrtimer_active(&t.timer))
- t.task = NULL;
+static int futex_wait(u32 __user *uaddr, int fshared,
+ u32 val, ktime_t *abs_time, u32 bitset, int clockrt)
+{
+ struct hrtimer_sleeper timeout, *to = NULL;
+ DECLARE_WAITQUEUE(wait, current);
+ struct restart_block *restart;
+ struct futex_hash_bucket *hb;
+ struct futex_q q;
+ int ret;
- /*
- * the timer could have already expired, in which
- * case current would be flagged for rescheduling.
- * Don't bother calling schedule.
- */
- if (likely(t.task))
- schedule();
+ if (!bitset)
+ return -EINVAL;
- hrtimer_cancel(&t.timer);
+ q.pi_state = NULL;
+ q.bitset = bitset;
+ q.rt_waiter = NULL;
- /* Flag if a timeout occured */
- rem = (t.task == NULL);
+ if (abs_time) {
+ to = &timeout;
- destroy_hrtimer_on_stack(&t.timer);
- }
+ hrtimer_init_on_stack(&to->timer, clockrt ? CLOCK_REALTIME :
+ CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+ hrtimer_init_sleeper(to, current);
+ hrtimer_set_expires_range_ns(&to->timer, *abs_time,
+ current->timer_slack_ns);
}
- __set_current_state(TASK_RUNNING);
- /*
- * NOTE: we don't remove ourselves from the waitqueue because
- * we are the only user of it.
- */
+ /* Prepare to wait on uaddr. */
+ ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
+ if (ret)
+ goto out;
+
+ /* queue_me and wait for wakeup, timeout, or a signal. */
+ futex_wait_queue_me(hb, &q, to, &wait);
/* If we were woken (and unqueued), we succeeded, whatever. */
ret = 0;
if (!unqueue_me(&q))
goto out_put_key;
ret = -ETIMEDOUT;
- if (rem)
+ if (to && !to->task)
goto out_put_key;
/*
@@ -1268,7 +1762,7 @@ retry_private:
restart->futex.val = val;
restart->futex.time = abs_time->tv64;
restart->futex.bitset = bitset;
- restart->futex.flags = 0;
+ restart->futex.flags = FLAGS_HAS_TIMEOUT;
if (fshared)
restart->futex.flags |= FLAGS_SHARED;
@@ -1280,6 +1774,10 @@ retry_private:
out_put_key:
put_futex_key(fshared, &q.key);
out:
+ if (to) {
+ hrtimer_cancel(&to->timer);
+ destroy_hrtimer_on_stack(&to->timer);
+ }
return ret;
}
@@ -1288,13 +1786,16 @@ static long futex_wait_restart(struct restart_block *restart)
{
u32 __user *uaddr = (u32 __user *)restart->futex.uaddr;
int fshared = 0;
- ktime_t t;
+ ktime_t t, *tp = NULL;
- t.tv64 = restart->futex.time;
+ if (restart->futex.flags & FLAGS_HAS_TIMEOUT) {
+ t.tv64 = restart->futex.time;
+ tp = &t;
+ }
restart->fn = do_no_restart_syscall;
if (restart->futex.flags & FLAGS_SHARED)
fshared = 1;
- return (long)futex_wait(uaddr, fshared, restart->futex.val, &t,
+ return (long)futex_wait(uaddr, fshared, restart->futex.val, tp,
restart->futex.bitset,
restart->futex.flags & FLAGS_CLOCKRT);
}
@@ -1310,11 +1811,10 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared,
int detect, ktime_t *time, int trylock)
{
struct hrtimer_sleeper timeout, *to = NULL;
- struct task_struct *curr = current;
struct futex_hash_bucket *hb;
- u32 uval, newval, curval;
+ u32 uval;
struct futex_q q;
- int ret, lock_taken, ownerdied = 0;
+ int res, ret;
if (refill_pi_state_cache())
return -ENOMEM;
@@ -1328,6 +1828,7 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared,
}
q.pi_state = NULL;
+ q.rt_waiter = NULL;
retry:
q.key = FUTEX_KEY_INIT;
ret = get_futex_key(uaddr, fshared, &q.key);
@@ -1337,81 +1838,15 @@ retry:
retry_private:
hb = queue_lock(&q);
-retry_locked:
- ret = lock_taken = 0;
-
- /*
- * To avoid races, we attempt to take the lock here again
- * (by doing a 0 -> TID atomic cmpxchg), while holding all
- * the locks. It will most likely not succeed.
- */
- newval = task_pid_vnr(current);
-
- curval = cmpxchg_futex_value_locked(uaddr, 0, newval);
-
- if (unlikely(curval == -EFAULT))
- goto uaddr_faulted;
-
- /*
- * 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) == task_pid_vnr(current))) {
- ret = -EDEADLK;
- goto out_unlock_put_key;
- }
-
- /*
- * Surprise - we got the lock. Just return to userspace:
- */
- if (unlikely(!curval))
- goto out_unlock_put_key;
-
- uval = curval;
-
- /*
- * Set the WAITERS flag, so the owner will know it has someone
- * to wake at next unlock
- */
- newval = curval | FUTEX_WAITERS;
-
- /*
- * There are two cases, where a futex might have no owner (the
- * owner TID is 0): OWNER_DIED. We take over the futex in this
- * case. We also do an unconditional take over, when the owner
- * of the futex died.
- *
- * This is safe as we are protected by the hash bucket lock !
- */
- if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) {
- /* Keep the OWNER_DIED bit */
- newval = (curval & ~FUTEX_TID_MASK) | task_pid_vnr(current);
- ownerdied = 0;
- lock_taken = 1;
- }
-
- curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
-
- if (unlikely(curval == -EFAULT))
- goto uaddr_faulted;
- if (unlikely(curval != uval))
- goto retry_locked;
-
- /*
- * We took the lock due to owner died take over.
- */
- if (unlikely(lock_taken))
- goto out_unlock_put_key;
-
- /*
- * We dont have the lock. Look up the PI state (or create it if
- * we are the first waiter):
- */
- ret = lookup_pi_state(uval, hb, &q.key, &q.pi_state);
-
+ ret = futex_lock_pi_atomic(uaddr, hb, &q.key, &q.pi_state, current, 0);
if (unlikely(ret)) {
switch (ret) {
-
+ case 1:
+ /* We got the lock. */
+ ret = 0;
+ goto out_unlock_put_key;
+ case -EFAULT:
+ goto uaddr_faulted;
case -EAGAIN:
/*
* Task is exiting and we just wait for the
@@ -1421,25 +1856,6 @@ retry_locked:
put_futex_key(fshared, &q.key);
cond_resched();
goto retry;
-
- case -ESRCH:
- /*
- * No owner found for this futex. Check if the
- * OWNER_DIED bit is set to figure out whether
- * this is a robust futex or not.
- */
- if (get_futex_value_locked(&curval, uaddr))
- goto uaddr_faulted;
-
- /*
- * We simply start over in case of a robust
- * futex. The code above will take the futex
- * and return happy.
- */
- if (curval & FUTEX_OWNER_DIED) {
- ownerdied = 1;
- goto retry_locked;
- }
default:
goto out_unlock_put_key;
}
@@ -1463,71 +1879,21 @@ retry_locked:
}
spin_lock(q.lock_ptr);
-
- if (!ret) {
- /*
- * Got the lock. We might not be the anticipated owner
- * if we did a lock-steal - fix up the PI-state in
- * that case:
- */
- if (q.pi_state->owner != curr)
- ret = fixup_pi_state_owner(uaddr, &q, curr, fshared);
- } else {
- /*
- * Catch the rare case, where the lock was released
- * when we were on the way back before we locked the
- * hash bucket.
- */
- if (q.pi_state->owner == curr) {
- /*
- * Try to get the rt_mutex now. This might
- * fail as some other task acquired the
- * rt_mutex after we removed ourself from the
- * rt_mutex waiters list.
- */
- if (rt_mutex_trylock(&q.pi_state->pi_mutex))
- ret = 0;
- else {
- /*
- * pi_state is incorrect, some other
- * task did a lock steal and we
- * returned due to timeout or signal
- * without taking the rt_mutex. Too
- * late. We can access the
- * rt_mutex_owner without locking, as
- * the other task is now blocked on
- * the hash bucket lock. Fix the state
- * up.
- */
- struct task_struct *owner;
- int res;
-
- owner = rt_mutex_owner(&q.pi_state->pi_mutex);
- res = fixup_pi_state_owner(uaddr, &q, owner,
- fshared);
-
- /* propagate -EFAULT, if the fixup failed */
- if (res)
- ret = res;
- }
- } else {
- /*
- * Paranoia check. If we did not take the lock
- * in the trylock above, then we should not be
- * the owner of the rtmutex, neither the real
- * nor the pending one:
- */
- if (rt_mutex_owner(&q.pi_state->pi_mutex) == curr)
- printk(KERN_ERR "futex_lock_pi: ret = %d "
- "pi-mutex: %p pi-state %p\n", ret,
- q.pi_state->pi_mutex.owner,
- q.pi_state->owner);
- }
- }
+ /*
+ * Fixup the pi_state owner and possibly acquire the lock if we
+ * haven't already.
+ */
+ res = fixup_owner(uaddr, fshared, &q, !ret);
+ /*
+ * If fixup_owner() returned an error, proprogate that. If it acquired
+ * the lock, clear our -ETIMEDOUT or -EINTR.
+ */
+ if (res)
+ ret = (res < 0) ? res : 0;
/*
- * If fixup_pi_state_owner() faulted and was unable to handle the
- * fault, unlock it and return the fault to userspace.
+ * If fixup_owner() faulted and was unable to handle the fault, unlock
+ * it and return the fault to userspace.
*/
if (ret && (rt_mutex_owner(&q.pi_state->pi_mutex) == current))
rt_mutex_unlock(&q.pi_state->pi_mutex);
@@ -1535,9 +1901,7 @@ retry_locked:
/* Unqueue and drop the lock */
unqueue_me_pi(&q);
- if (to)
- destroy_hrtimer_on_stack(&to->timer);
- return ret != -EINTR ? ret : -ERESTARTNOINTR;
+ goto out;
out_unlock_put_key:
queue_unlock(&q, hb);
@@ -1547,7 +1911,7 @@ out_put_key:
out:
if (to)
destroy_hrtimer_on_stack(&to->timer);
- return ret;
+ return ret != -EINTR ? ret : -ERESTARTNOINTR;
uaddr_faulted:
/*
@@ -1570,6 +1934,20 @@ uaddr_faulted:
goto retry;
}
+static long futex_lock_pi_restart(struct restart_block *restart)
+{
+ u32 __user *uaddr = (u32 __user *)restart->futex.uaddr;
+ ktime_t t, *tp = NULL;
+ int fshared = restart->futex.flags & FLAGS_SHARED;
+
+ if (restart->futex.flags & FLAGS_HAS_TIMEOUT) {
+ t.tv64 = restart->futex.time;
+ tp = &t;
+ }
+ restart->fn = do_no_restart_syscall;
+
+ return (long)futex_lock_pi(uaddr, fshared, restart->futex.val, tp, 0);
+}
/*
* Userspace attempted a TID -> 0 atomic transition, and failed.
@@ -1672,6 +2050,253 @@ pi_faulted:
return ret;
}
+/**
+ * handle_early_requeue_pi_wakeup() - Detect early wakeup on the initial futex
+ * @hb: the hash_bucket futex_q was original enqueued on
+ * @q: the futex_q woken while waiting to be requeued
+ * @key2: the futex_key of the requeue target futex
+ * @timeout: the timeout associated with the wait (NULL if none)
+ *
+ * Detect if the task was woken on the initial futex as opposed to the requeue
+ * target futex. If so, determine if it was a timeout or a signal that caused
+ * the wakeup and return the appropriate error code to the caller. Must be
+ * called with the hb lock held.
+ *
+ * Returns
+ * 0 - no early wakeup detected
+ * <0 - -ETIMEDOUT or -ERESTARTSYS (FIXME: or ERESTARTNOINTR?)
+ */
+static inline
+int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,
+ struct futex_q *q, union futex_key *key2,
+ struct hrtimer_sleeper *timeout)
+{
+ int ret = 0;
+
+ /*
+ * With the hb lock held, we avoid races while we process the wakeup.
+ * We only need to hold hb (and not hb2) to ensure atomicity as the
+ * wakeup code can't change q.key from uaddr to uaddr2 if we hold hb.
+ * It can't be requeued from uaddr2 to something else since we don't
+ * support a PI aware source futex for requeue.
+ */
+ if (!match_futex(&q->key, key2)) {
+ WARN_ON(q->lock_ptr && (&hb->lock != q->lock_ptr));
+ /*
+ * We were woken prior to requeue by a timeout or a signal.
+ * Unqueue the futex_q and determine which it was.
+ */
+ plist_del(&q->list, &q->list.plist);
+ drop_futex_key_refs(&q->key);
+
+ if (timeout && !timeout->task)
+ ret = -ETIMEDOUT;
+ else {
+ /*
+ * We expect signal_pending(current), but another
+ * thread may have handled it for us already.
+ */
+ /* FIXME: ERESTARTSYS or ERESTARTNOINTR? Do we care if
+ * the user specified SA_RESTART or not? */
+ ret = -ERESTARTSYS;
+ }
+ }
+ return ret;
+}
+
+/**
+ * futex_wait_requeue_pi() - Wait on uaddr and take uaddr2
+ * @uaddr: the futex we initialyl wait on (non-pi)
+ * @fshared: whether the futexes are shared (1) or not (0). They must be
+ * the same type, no requeueing from private to shared, etc.
+ * @val: the expected value of uaddr
+ * @abs_time: absolute timeout
+ * @bitset: 32 bit wakeup bitset set by userspace, defaults to all.
+ * @clockrt: whether to use CLOCK_REALTIME (1) or CLOCK_MONOTONIC (0)
+ * @uaddr2: the pi futex we will take prior to returning to user-space
+ *
+ * The caller will wait on uaddr and will be requeued by futex_requeue() to
+ * uaddr2 which must be PI aware. Normal wakeup will wake on uaddr2 and
+ * complete the acquisition of the rt_mutex prior to returning to userspace.
+ * This ensures the rt_mutex maintains an owner when it has waiters; without
+ * one, the pi logic wouldn't know which task to boost/deboost, if there was a
+ * need to.
+ *
+ * We call schedule in futex_wait_queue_me() when we enqueue and return there
+ * via the following:
+ * 1) wakeup on uaddr2 after an atomic lock acquisition by futex_requeue()
+ * 2) wakeup on uaddr2 after a requeue and subsequent unlock
+ * 3) signal (before or after requeue)
+ * 4) timeout (before or after requeue)
+ *
+ * If 3, we setup a restart_block with futex_wait_requeue_pi() as the function.
+ *
+ * If 2, we may then block on trying to take the rt_mutex and return via:
+ * 5) successful lock
+ * 6) signal
+ * 7) timeout
+ * 8) other lock acquisition failure
+ *
+ * If 6, we setup a restart_block with futex_lock_pi() as the function.
+ *
+ * If 4 or 7, we cleanup and return with -ETIMEDOUT.
+ *
+ * Returns:
+ * 0 - On success
+ * <0 - On error
+ */
+static int futex_wait_requeue_pi(u32 __user *uaddr, int fshared,
+ u32 val, ktime_t *abs_time, u32 bitset,
+ int clockrt, u32 __user *uaddr2)
+{
+ struct hrtimer_sleeper timeout, *to = NULL;
+ struct rt_mutex_waiter rt_waiter;
+ struct rt_mutex *pi_mutex = NULL;
+ DECLARE_WAITQUEUE(wait, current);
+ struct restart_block *restart;
+ struct futex_hash_bucket *hb;
+ union futex_key key2;
+ struct futex_q q;
+ int res, ret;
+ u32 uval;
+
+ if (!bitset)
+ return -EINVAL;
+
+ if (abs_time) {
+ to = &timeout;
+ hrtimer_init_on_stack(&to->timer, clockrt ? CLOCK_REALTIME :
+ CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+ hrtimer_init_sleeper(to, current);
+ hrtimer_set_expires_range_ns(&to->timer, *abs_time,
+ current->timer_slack_ns);
+ }
+
+ /*
+ * The waiter is allocated on our stack, manipulated by the requeue
+ * code while we sleep on uaddr.
+ */
+ debug_rt_mutex_init_waiter(&rt_waiter);
+ rt_waiter.task = NULL;
+
+ q.pi_state = NULL;
+ q.bitset = bitset;
+ q.rt_waiter = &rt_waiter;
+
+ key2 = FUTEX_KEY_INIT;
+ ret = get_futex_key(uaddr2, fshared, &key2);
+ if (unlikely(ret != 0))
+ goto out;
+
+ /* Prepare to wait on uaddr. */
+ ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
+ if (ret) {
+ put_futex_key(fshared, &key2);
+ goto out;
+ }
+
+ /* Queue the futex_q, drop the hb lock, wait for wakeup. */
+ futex_wait_queue_me(hb, &q, to, &wait);
+
+ spin_lock(&hb->lock);
+ ret = handle_early_requeue_pi_wakeup(hb, &q, &key2, to);
+ spin_unlock(&hb->lock);
+ if (ret)
+ goto out_put_keys;
+
+ /*
+ * In order for us to be here, we know our q.key == key2, and since
+ * we took the hb->lock above, we also know that futex_requeue() has
+ * completed and we no longer have to concern ourselves with a wakeup
+ * race with the atomic proxy lock acquition by the requeue code.
+ */
+
+ /* Check if the requeue code acquired the second futex for us. */
+ if (!q.rt_waiter) {
+ /*
+ * Got the lock. We might not be the anticipated owner if we
+ * did a lock-steal - fix up the PI-state in that case.
+ */
+ if (q.pi_state && (q.pi_state->owner != current)) {
+ spin_lock(q.lock_ptr);
+ ret = fixup_pi_state_owner(uaddr2, &q, current,
+ fshared);
+ spin_unlock(q.lock_ptr);
+ }
+ } else {
+ /*
+ * We have been woken up by futex_unlock_pi(), a timeout, or a
+ * signal. futex_unlock_pi() will not destroy the lock_ptr nor
+ * the pi_state.
+ */
+ WARN_ON(!&q.pi_state);
+ pi_mutex = &q.pi_state->pi_mutex;
+ ret = rt_mutex_finish_proxy_lock(pi_mutex, to, &rt_waiter, 1);
+ debug_rt_mutex_free_waiter(&rt_waiter);
+
+ spin_lock(q.lock_ptr);
+ /*
+ * Fixup the pi_state owner and possibly acquire the lock if we
+ * haven't already.
+ */
+ res = fixup_owner(uaddr2, fshared, &q, !ret);
+ /*
+ * If fixup_owner() returned an error, proprogate that. If it
+ * acquired the lock, clear our -ETIMEDOUT or -EINTR.
+ */
+ if (res)
+ ret = (res < 0) ? res : 0;
+
+ /* Unqueue and drop the lock. */
+ unqueue_me_pi(&q);
+ }
+
+ /*
+ * If fixup_pi_state_owner() faulted and was unable to handle the
+ * fault, unlock the rt_mutex and return the fault to userspace.
+ */
+ if (ret == -EFAULT) {
+ if (rt_mutex_owner(pi_mutex) == current)
+ rt_mutex_unlock(pi_mutex);
+ } else if (ret == -EINTR) {
+ ret = -EFAULT;
+ if (get_user(uval, uaddr2))
+ goto out_put_keys;
+
+ /*
+ * We've already been requeued, so restart by calling
+ * futex_lock_pi() directly, rather then returning to this
+ * function.
+ */
+ ret = -ERESTART_RESTARTBLOCK;
+ restart = &current_thread_info()->restart_block;
+ restart->fn = futex_lock_pi_restart;
+ restart->futex.uaddr = (u32 *)uaddr2;
+ restart->futex.val = uval;
+ restart->futex.flags = 0;
+ if (abs_time) {
+ restart->futex.flags |= FLAGS_HAS_TIMEOUT;
+ restart->futex.time = abs_time->tv64;
+ }
+
+ if (fshared)
+ restart->futex.flags |= FLAGS_SHARED;
+ if (clockrt)
+ restart->futex.flags |= FLAGS_CLOCKRT;
+ }
+
+out_put_keys:
+ put_futex_key(fshared, &q.key);
+ put_futex_key(fshared, &key2);
+
+out:
+ if (to) {
+ hrtimer_cancel(&to->timer);
+ destroy_hrtimer_on_stack(&to->timer);
+ }
+ return ret;
+}
+
/*
* Support for robust futexes: the kernel cleans up held futexes at
* thread exit time.
@@ -1894,7 +2519,7 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
fshared = 1;
clockrt = op & FUTEX_CLOCK_REALTIME;
- if (clockrt && cmd != FUTEX_WAIT_BITSET)
+ if (clockrt && cmd != FUTEX_WAIT_BITSET && cmd != FUTEX_WAIT_REQUEUE_PI)
return -ENOSYS;
switch (cmd) {
@@ -1909,10 +2534,11 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
ret = futex_wake(uaddr, fshared, val, val3);
break;
case FUTEX_REQUEUE:
- ret = futex_requeue(uaddr, fshared, uaddr2, val, val2, NULL);
+ ret = futex_requeue(uaddr, fshared, uaddr2, val, val2, NULL, 0);
break;
case FUTEX_CMP_REQUEUE:
- ret = futex_requeue(uaddr, fshared, uaddr2, val, val2, &val3);
+ ret = futex_requeue(uaddr, fshared, uaddr2, val, val2, &val3,
+ 0);
break;
case FUTEX_WAKE_OP:
ret = futex_wake_op(uaddr, fshared, uaddr2, val, val2, val3);
@@ -1929,6 +2555,15 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
if (futex_cmpxchg_enabled)
ret = futex_lock_pi(uaddr, fshared, 0, timeout, 1);
break;
+ case FUTEX_WAIT_REQUEUE_PI:
+ val3 = FUTEX_BITSET_MATCH_ANY;
+ ret = futex_wait_requeue_pi(uaddr, fshared, val, timeout, val3,
+ clockrt, uaddr2);
+ break;
+ case FUTEX_CMP_REQUEUE_PI:
+ ret = futex_requeue(uaddr, fshared, uaddr2, val, val2, &val3,
+ 1);
+ break;
default:
ret = -ENOSYS;
}
@@ -1946,7 +2581,8 @@ SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val,
int cmd = op & FUTEX_CMD_MASK;
if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI ||
- cmd == FUTEX_WAIT_BITSET)) {
+ cmd == FUTEX_WAIT_BITSET ||
+ cmd == FUTEX_WAIT_REQUEUE_PI)) {
if (copy_from_user(&ts, utime, sizeof(ts)) != 0)
return -EFAULT;
if (!timespec_valid(&ts))
@@ -1958,11 +2594,11 @@ SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val,
tp = &t;
}
/*
- * requeue parameter in 'utime' if cmd == FUTEX_REQUEUE.
+ * requeue parameter in 'utime' if cmd == FUTEX_*_REQUEUE_*.
* number of waiters to wake in 'utime' if cmd == FUTEX_WAKE_OP.
*/
if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE ||
- cmd == FUTEX_WAKE_OP)
+ cmd == FUTEX_CMP_REQUEUE_PI || cmd == FUTEX_WAKE_OP)
val2 = (u32) (unsigned long) utime;
return do_futex(uaddr, op, val, tp, uaddr2, val2, val3);
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile
index 3394f8f52964..7d047808419d 100644
--- a/kernel/irq/Makefile
+++ b/kernel/irq/Makefile
@@ -3,5 +3,5 @@ obj-y := handle.o manage.o spurious.o resend.o chip.o devres.o
obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
-obj-$(CONFIG_NUMA_MIGRATE_IRQ_DESC) += numa_migrate.o
+obj-$(CONFIG_NUMA_IRQ_DESC) += numa_migrate.o
obj-$(CONFIG_PM_SLEEP) += pm.o
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index c687ba4363f2..13c68e71b726 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -359,7 +359,6 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
spin_lock(&desc->lock);
mask_ack_irq(desc, irq);
- desc = irq_remap_to_desc(irq, desc);
if (unlikely(desc->status & IRQ_INPROGRESS))
goto out_unlock;
@@ -438,7 +437,6 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
desc->status &= ~IRQ_INPROGRESS;
out:
desc->chip->eoi(irq);
- desc = irq_remap_to_desc(irq, desc);
spin_unlock(&desc->lock);
}
@@ -475,7 +473,6 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
!desc->action)) {
desc->status |= (IRQ_PENDING | IRQ_MASKED);
mask_ack_irq(desc, irq);
- desc = irq_remap_to_desc(irq, desc);
goto out_unlock;
}
kstat_incr_irqs_this_cpu(irq, desc);
@@ -483,7 +480,6 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
/* Start handling the irq */
if (desc->chip->ack)
desc->chip->ack(irq);
- desc = irq_remap_to_desc(irq, desc);
/* Mark the IRQ currently in progress.*/
desc->status |= IRQ_INPROGRESS;
@@ -544,10 +540,8 @@ handle_percpu_irq(unsigned int irq, struct irq_desc *desc)
if (!noirqdebug)
note_interrupt(irq, desc, action_ret);
- if (desc->chip->eoi) {
+ if (desc->chip->eoi)
desc->chip->eoi(irq);
- desc = irq_remap_to_desc(irq, desc);
- }
}
void
@@ -582,10 +576,8 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
/* Uninstall? */
if (handle == handle_bad_irq) {
- if (desc->chip != &no_irq_chip) {
+ if (desc->chip != &no_irq_chip)
mask_ack_irq(desc, irq);
- desc = irq_remap_to_desc(irq, desc);
- }
desc->status |= IRQ_DISABLED;
desc->depth = 1;
}
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index d82142be8dd2..33ff8f55befe 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -17,8 +17,8 @@
#include <linux/kernel_stat.h>
#include <linux/rculist.h>
#include <linux/hash.h>
-#include <trace/irq.h>
#include <linux/bootmem.h>
+#include <trace/events/irq.h>
#include "internals.h"
@@ -81,12 +81,10 @@ static struct irq_desc irq_desc_init = {
.lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
};
-void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr)
+void init_kstat_irqs(struct irq_desc *desc, int node, int nr)
{
- int node;
void *ptr;
- node = cpu_to_node(cpu);
ptr = kzalloc_node(nr * sizeof(*desc->kstat_irqs), GFP_ATOMIC, node);
/*
@@ -94,32 +92,32 @@ void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr)
* init_copy_kstat_irqs() could still use old one
*/
if (ptr) {
- printk(KERN_DEBUG " alloc kstat_irqs on cpu %d node %d\n",
- cpu, node);
+ printk(KERN_DEBUG " alloc kstat_irqs on node %d\n", node);
desc->kstat_irqs = ptr;
}
}
-static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu)
+static void init_one_irq_desc(int irq, struct irq_desc *desc, int node)
{
memcpy(desc, &irq_desc_init, sizeof(struct irq_desc));
spin_lock_init(&desc->lock);
desc->irq = irq;
#ifdef CONFIG_SMP
- desc->cpu = cpu;
+ desc->node = node;
#endif
lockdep_set_class(&desc->lock, &irq_desc_lock_class);
- init_kstat_irqs(desc, cpu, nr_cpu_ids);
+ init_kstat_irqs(desc, node, nr_cpu_ids);
if (!desc->kstat_irqs) {
printk(KERN_ERR "can not alloc kstat_irqs\n");
BUG_ON(1);
}
- if (!init_alloc_desc_masks(desc, cpu, false)) {
+ if (!alloc_desc_masks(desc, node, false)) {
printk(KERN_ERR "can not alloc irq_desc cpumasks\n");
BUG_ON(1);
}
- arch_init_chip_data(desc, cpu);
+ init_desc_masks(desc);
+ arch_init_chip_data(desc, node);
}
/*
@@ -169,7 +167,8 @@ int __init early_irq_init(void)
desc[i].irq = i;
desc[i].kstat_irqs = kstat_irqs_legacy + i * nr_cpu_ids;
lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
- init_alloc_desc_masks(&desc[i], 0, true);
+ alloc_desc_masks(&desc[i], 0, true);
+ init_desc_masks(&desc[i]);
irq_desc_ptrs[i] = desc + i;
}
@@ -187,11 +186,10 @@ struct irq_desc *irq_to_desc(unsigned int irq)
return NULL;
}
-struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu)
+struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node)
{
struct irq_desc *desc;
unsigned long flags;
- int node;
if (irq >= nr_irqs) {
WARN(1, "irq (%d) >= nr_irqs (%d) in irq_to_desc_alloc\n",
@@ -210,15 +208,13 @@ struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu)
if (desc)
goto out_unlock;
- node = cpu_to_node(cpu);
desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node);
- printk(KERN_DEBUG " alloc irq_desc for %d on cpu %d node %d\n",
- irq, cpu, node);
+ printk(KERN_DEBUG " alloc irq_desc for %d on node %d\n", irq, node);
if (!desc) {
printk(KERN_ERR "can not alloc irq_desc\n");
BUG_ON(1);
}
- init_one_irq_desc(irq, desc, cpu);
+ init_one_irq_desc(irq, desc, node);
irq_desc_ptrs[irq] = desc;
@@ -256,7 +252,8 @@ int __init early_irq_init(void)
for (i = 0; i < count; i++) {
desc[i].irq = i;
- init_alloc_desc_masks(&desc[i], 0, true);
+ alloc_desc_masks(&desc[i], 0, true);
+ init_desc_masks(&desc[i]);
desc[i].kstat_irqs = kstat_irqs_all[i];
}
return arch_early_irq_init();
@@ -267,7 +264,7 @@ struct irq_desc *irq_to_desc(unsigned int irq)
return (irq < NR_IRQS) ? irq_desc + irq : NULL;
}
-struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu)
+struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node)
{
return irq_to_desc(irq);
}
@@ -348,9 +345,6 @@ static void warn_no_thread(unsigned int irq, struct irqaction *action)
"but no thread function available.", irq, action->name);
}
-DEFINE_TRACE(irq_handler_entry);
-DEFINE_TRACE(irq_handler_exit);
-
/**
* handle_IRQ_event - irq action chain handler
* @irq: the interrupt number
@@ -363,8 +357,6 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
irqreturn_t ret, retval = IRQ_NONE;
unsigned int status = 0;
- WARN_ONCE(!in_irq(), "BUG: IRQ handler called from non-hardirq context!");
-
if (!(action->flags & IRQF_DISABLED))
local_irq_enable_in_hardirq();
@@ -455,11 +447,8 @@ unsigned int __do_IRQ(unsigned int irq)
/*
* No locking required for CPU-local interrupts:
*/
- if (desc->chip->ack) {
+ if (desc->chip->ack)
desc->chip->ack(irq);
- /* get new one */
- desc = irq_remap_to_desc(irq, desc);
- }
if (likely(!(desc->status & IRQ_DISABLED))) {
action_ret = handle_IRQ_event(irq, desc->action);
if (!noirqdebug)
@@ -470,10 +459,8 @@ unsigned int __do_IRQ(unsigned int irq)
}
spin_lock(&desc->lock);
- if (desc->chip->ack) {
+ if (desc->chip->ack)
desc->chip->ack(irq);
- desc = irq_remap_to_desc(irq, desc);
- }
/*
* REPLAY is when Linux resends an IRQ that was dropped earlier
* WAITING is used by probe to mark irqs that are being tested
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index 01ce20eab38f..73468253143b 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -16,7 +16,7 @@ extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp);
extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume);
extern struct lock_class_key irq_desc_lock_class;
-extern void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr);
+extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr);
extern void clear_kstat_irqs(struct irq_desc *desc);
extern spinlock_t sparse_irq_lock;
@@ -42,6 +42,9 @@ static inline void unregister_handler_proc(unsigned int irq,
extern int irq_select_affinity_usr(unsigned int irq);
+extern void
+irq_set_thread_affinity(struct irq_desc *desc, const struct cpumask *cpumask);
+
/*
* Debugging printout:
*/
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 7e2e7dd4cd2f..5524ec07089c 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -80,7 +80,7 @@ int irq_can_set_affinity(unsigned int irq)
return 1;
}
-static void
+void
irq_set_thread_affinity(struct irq_desc *desc, const struct cpumask *cpumask)
{
struct irqaction *action = desc->action;
@@ -109,18 +109,22 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
spin_lock_irqsave(&desc->lock, flags);
#ifdef CONFIG_GENERIC_PENDING_IRQ
- if (desc->status & IRQ_MOVE_PCNTXT || desc->status & IRQ_DISABLED) {
- cpumask_copy(desc->affinity, cpumask);
- desc->chip->set_affinity(irq, cpumask);
- } else {
+ if (desc->status & IRQ_MOVE_PCNTXT) {
+ if (!desc->chip->set_affinity(irq, cpumask)) {
+ cpumask_copy(desc->affinity, cpumask);
+ irq_set_thread_affinity(desc, cpumask);
+ }
+ }
+ else {
desc->status |= IRQ_MOVE_PENDING;
cpumask_copy(desc->pending_mask, cpumask);
}
#else
- cpumask_copy(desc->affinity, cpumask);
- desc->chip->set_affinity(irq, cpumask);
+ if (!desc->chip->set_affinity(irq, cpumask)) {
+ cpumask_copy(desc->affinity, cpumask);
+ irq_set_thread_affinity(desc, cpumask);
+ }
#endif
- irq_set_thread_affinity(desc, cpumask);
desc->status |= IRQ_AFFINITY_SET;
spin_unlock_irqrestore(&desc->lock, flags);
return 0;
@@ -931,7 +935,7 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler,
kfree(action);
#ifdef CONFIG_DEBUG_SHIRQ
- if (irqflags & IRQF_SHARED) {
+ if (!retval && (irqflags & IRQF_SHARED)) {
/*
* It's a shared IRQ -- the driver ought to be prepared for it
* to happen immediately, so let's make sure....
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c
index e05ad9be43b7..cfe767ca1545 100644
--- a/kernel/irq/migration.c
+++ b/kernel/irq/migration.c
@@ -1,5 +1,8 @@
#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include "internals.h"
void move_masked_irq(int irq)
{
@@ -39,11 +42,12 @@ void move_masked_irq(int irq)
* masking the irqs.
*/
if (likely(cpumask_any_and(desc->pending_mask, cpu_online_mask)
- < nr_cpu_ids)) {
- cpumask_and(desc->affinity,
- desc->pending_mask, cpu_online_mask);
- desc->chip->set_affinity(irq, desc->affinity);
- }
+ < nr_cpu_ids))
+ if (!desc->chip->set_affinity(irq, desc->pending_mask)) {
+ cpumask_copy(desc->affinity, desc->pending_mask);
+ irq_set_thread_affinity(desc, desc->pending_mask);
+ }
+
cpumask_clear(desc->pending_mask);
}
diff --git a/kernel/irq/numa_migrate.c b/kernel/irq/numa_migrate.c
index 44bbdcbaf8d2..2f69bee57bf2 100644
--- a/kernel/irq/numa_migrate.c
+++ b/kernel/irq/numa_migrate.c
@@ -15,9 +15,9 @@
static void init_copy_kstat_irqs(struct irq_desc *old_desc,
struct irq_desc *desc,
- int cpu, int nr)
+ int node, int nr)
{
- init_kstat_irqs(desc, cpu, nr);
+ init_kstat_irqs(desc, node, nr);
if (desc->kstat_irqs != old_desc->kstat_irqs)
memcpy(desc->kstat_irqs, old_desc->kstat_irqs,
@@ -34,20 +34,20 @@ static void free_kstat_irqs(struct irq_desc *old_desc, struct irq_desc *desc)
}
static bool init_copy_one_irq_desc(int irq, struct irq_desc *old_desc,
- struct irq_desc *desc, int cpu)
+ struct irq_desc *desc, int node)
{
memcpy(desc, old_desc, sizeof(struct irq_desc));
- if (!init_alloc_desc_masks(desc, cpu, false)) {
+ if (!alloc_desc_masks(desc, node, false)) {
printk(KERN_ERR "irq %d: can not get new irq_desc cpumask "
"for migration.\n", irq);
return false;
}
spin_lock_init(&desc->lock);
- desc->cpu = cpu;
+ desc->node = node;
lockdep_set_class(&desc->lock, &irq_desc_lock_class);
- init_copy_kstat_irqs(old_desc, desc, cpu, nr_cpu_ids);
+ init_copy_kstat_irqs(old_desc, desc, node, nr_cpu_ids);
init_copy_desc_masks(old_desc, desc);
- arch_init_copy_chip_data(old_desc, desc, cpu);
+ arch_init_copy_chip_data(old_desc, desc, node);
return true;
}
@@ -59,12 +59,11 @@ static void free_one_irq_desc(struct irq_desc *old_desc, struct irq_desc *desc)
}
static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
- int cpu)
+ int node)
{
struct irq_desc *desc;
unsigned int irq;
unsigned long flags;
- int node;
irq = old_desc->irq;
@@ -76,7 +75,6 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
if (desc && old_desc != desc)
goto out_unlock;
- node = cpu_to_node(cpu);
desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node);
if (!desc) {
printk(KERN_ERR "irq %d: can not get new irq_desc "
@@ -85,7 +83,7 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
desc = old_desc;
goto out_unlock;
}
- if (!init_copy_one_irq_desc(irq, old_desc, desc, cpu)) {
+ if (!init_copy_one_irq_desc(irq, old_desc, desc, node)) {
/* still use old one */
kfree(desc);
desc = old_desc;
@@ -97,9 +95,7 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
/* free the old one */
free_one_irq_desc(old_desc, desc);
- spin_unlock(&old_desc->lock);
kfree(old_desc);
- spin_lock(&desc->lock);
return desc;
@@ -109,24 +105,14 @@ out_unlock:
return desc;
}
-struct irq_desc *move_irq_desc(struct irq_desc *desc, int cpu)
+struct irq_desc *move_irq_desc(struct irq_desc *desc, int node)
{
- int old_cpu;
- int node, old_node;
-
/* those all static, do move them */
if (desc->irq < NR_IRQS_LEGACY)
return desc;
- old_cpu = desc->cpu;
- if (old_cpu != cpu) {
- node = cpu_to_node(cpu);
- old_node = cpu_to_node(old_cpu);
- if (old_node != node)
- desc = __real_move_irq_desc(desc, cpu);
- else
- desc->cpu = cpu;
- }
+ if (desc->node != node)
+ desc = __real_move_irq_desc(desc, node);
return desc;
}
diff --git a/kernel/kgdb.c b/kernel/kgdb.c
index e4dcfb2272a4..b5ea4650f2ea 100644
--- a/kernel/kgdb.c
+++ b/kernel/kgdb.c
@@ -363,7 +363,7 @@ static void put_packet(char *buffer)
* Convert the memory pointed to by mem into hex, placing result in buf.
* Return a pointer to the last char put in buf (null). May return an error.
*/
-int kgdb_mem2hex(char *mem, char *buf, int count)
+int __weak kgdb_mem2hex(char *mem, char *buf, int count)
{
char *tmp;
int err;
@@ -393,7 +393,7 @@ int kgdb_mem2hex(char *mem, char *buf, int count)
* 0x7d escaped with 0x7d. Return a pointer to the character after
* the last byte written.
*/
-static int kgdb_ebin2mem(char *buf, char *mem, int count)
+int __weak kgdb_ebin2mem(char *buf, char *mem, int count)
{
int err = 0;
char c;
@@ -418,7 +418,7 @@ static int kgdb_ebin2mem(char *buf, char *mem, int count)
* Return a pointer to the character AFTER the last byte written.
* May return an error.
*/
-int kgdb_hex2mem(char *buf, char *mem, int count)
+int __weak kgdb_hex2mem(char *buf, char *mem, int count)
{
char *tmp_raw;
char *tmp_hex;
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index a5e74ddee0e2..c0fa54b276d9 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -319,6 +319,22 @@ struct kprobe __kprobes *get_kprobe(void *addr)
return NULL;
}
+/* Arm a kprobe with text_mutex */
+static void __kprobes arm_kprobe(struct kprobe *kp)
+{
+ mutex_lock(&text_mutex);
+ arch_arm_kprobe(kp);
+ mutex_unlock(&text_mutex);
+}
+
+/* Disarm a kprobe with text_mutex */
+static void __kprobes disarm_kprobe(struct kprobe *kp)
+{
+ mutex_lock(&text_mutex);
+ arch_disarm_kprobe(kp);
+ mutex_unlock(&text_mutex);
+}
+
/*
* Aggregate handlers for multiple kprobes support - these handlers
* take care of invoking the individual kprobe handlers on p->list
@@ -538,7 +554,7 @@ static int __kprobes add_new_kprobe(struct kprobe *ap, struct kprobe *p)
ap->flags &= ~KPROBE_FLAG_DISABLED;
if (!kprobes_all_disarmed)
/* Arm the breakpoint again. */
- arch_arm_kprobe(ap);
+ arm_kprobe(ap);
}
return 0;
}
@@ -789,11 +805,8 @@ static int __kprobes __unregister_kprobe_top(struct kprobe *p)
* enabled and not gone - otherwise, the breakpoint would
* already have been removed. We save on flushing icache.
*/
- if (!kprobes_all_disarmed && !kprobe_disabled(old_p)) {
- mutex_lock(&text_mutex);
- arch_disarm_kprobe(p);
- mutex_unlock(&text_mutex);
- }
+ if (!kprobes_all_disarmed && !kprobe_disabled(old_p))
+ disarm_kprobe(p);
hlist_del_rcu(&old_p->hlist);
} else {
if (p->break_handler && !kprobe_gone(p))
@@ -810,7 +823,7 @@ noclean:
if (!kprobe_disabled(old_p)) {
try_to_disable_aggr_kprobe(old_p);
if (!kprobes_all_disarmed && kprobe_disabled(old_p))
- arch_disarm_kprobe(old_p);
+ disarm_kprobe(old_p);
}
}
return 0;
@@ -1364,7 +1377,7 @@ int __kprobes disable_kprobe(struct kprobe *kp)
try_to_disable_aggr_kprobe(p);
if (!kprobes_all_disarmed && kprobe_disabled(p))
- arch_disarm_kprobe(p);
+ disarm_kprobe(p);
out:
mutex_unlock(&kprobe_mutex);
return ret;
@@ -1393,7 +1406,7 @@ int __kprobes enable_kprobe(struct kprobe *kp)
}
if (!kprobes_all_disarmed && kprobe_disabled(p))
- arch_arm_kprobe(p);
+ arm_kprobe(p);
p->flags &= ~KPROBE_FLAG_DISABLED;
if (p != kp)
diff --git a/kernel/kthread.c b/kernel/kthread.c
index 4ebaf8519abf..41c88fe40500 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -13,7 +13,7 @@
#include <linux/file.h>
#include <linux/module.h>
#include <linux/mutex.h>
-#include <trace/sched.h>
+#include <trace/events/sched.h>
#define KTHREAD_NICE_LEVEL (-5)
@@ -21,9 +21,6 @@ static DEFINE_SPINLOCK(kthread_create_lock);
static LIST_HEAD(kthread_create_list);
struct task_struct *kthreadd_task;
-DEFINE_TRACE(sched_kthread_stop);
-DEFINE_TRACE(sched_kthread_stop_ret);
-
struct kthread_create_info
{
/* Information passed to kthread() from kthreadd. */
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index b0f011866969..8bbeef996c76 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -42,12 +42,14 @@
#include <linux/hash.h>
#include <linux/ftrace.h>
#include <linux/stringify.h>
-#include <trace/lockdep.h>
#include <asm/sections.h>
#include "lockdep_internals.h"
+#define CREATE_TRACE_POINTS
+#include <trace/events/lockdep.h>
+
#ifdef CONFIG_PROVE_LOCKING
int prove_locking = 1;
module_param(prove_locking, int, 0644);
@@ -2490,13 +2492,20 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
void lockdep_init_map(struct lockdep_map *lock, const char *name,
struct lock_class_key *key, int subclass)
{
- if (unlikely(!debug_locks))
+ lock->class_cache = NULL;
+#ifdef CONFIG_LOCK_STAT
+ lock->cpu = raw_smp_processor_id();
+#endif
+
+ if (DEBUG_LOCKS_WARN_ON(!name)) {
+ lock->name = "NULL";
return;
+ }
+
+ lock->name = name;
if (DEBUG_LOCKS_WARN_ON(!key))
return;
- if (DEBUG_LOCKS_WARN_ON(!name))
- return;
/*
* Sanity check, the lock-class key must be persistent:
*/
@@ -2505,12 +2514,11 @@ void lockdep_init_map(struct lockdep_map *lock, const char *name,
DEBUG_LOCKS_WARN_ON(1);
return;
}
- lock->name = name;
lock->key = key;
- lock->class_cache = NULL;
-#ifdef CONFIG_LOCK_STAT
- lock->cpu = raw_smp_processor_id();
-#endif
+
+ if (unlikely(!debug_locks))
+ return;
+
if (subclass)
register_lock_class(lock, subclass, 1);
}
@@ -2929,8 +2937,6 @@ void lock_set_class(struct lockdep_map *lock, const char *name,
}
EXPORT_SYMBOL_GPL(lock_set_class);
-DEFINE_TRACE(lock_acquire);
-
/*
* We are not always called with irqs disabled - do that here,
* and also avoid lockdep recursion:
@@ -2957,8 +2963,6 @@ void lock_acquire(struct lockdep_map *lock, unsigned int subclass,
}
EXPORT_SYMBOL_GPL(lock_acquire);
-DEFINE_TRACE(lock_release);
-
void lock_release(struct lockdep_map *lock, int nested,
unsigned long ip)
{
@@ -3099,6 +3103,8 @@ found_it:
hlock->holdtime_stamp = now;
}
+ trace_lock_acquired(lock, ip, waittime);
+
stats = get_lock_stats(hlock_class(hlock));
if (waittime) {
if (hlock->read)
@@ -3114,8 +3120,6 @@ found_it:
lock->ip = ip;
}
-DEFINE_TRACE(lock_contended);
-
void lock_contended(struct lockdep_map *lock, unsigned long ip)
{
unsigned long flags;
@@ -3137,14 +3141,10 @@ void lock_contended(struct lockdep_map *lock, unsigned long ip)
}
EXPORT_SYMBOL_GPL(lock_contended);
-DEFINE_TRACE(lock_acquired);
-
void lock_acquired(struct lockdep_map *lock, unsigned long ip)
{
unsigned long flags;
- trace_lock_acquired(lock, ip);
-
if (unlikely(!lock_stat))
return;
diff --git a/kernel/module.c b/kernel/module.c
index e797812a4d95..35f7de00bf0d 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -18,6 +18,7 @@
*/
#include <linux/module.h>
#include <linux/moduleloader.h>
+#include <linux/ftrace_event.h>
#include <linux/init.h>
#include <linux/kallsyms.h>
#include <linux/fs.h>
@@ -52,6 +53,7 @@
#include <linux/ftrace.h>
#include <linux/async.h>
#include <linux/percpu.h>
+#include <linux/kmemleak.h>
#if 0
#define DEBUGP printk
@@ -72,6 +74,9 @@ DEFINE_MUTEX(module_mutex);
EXPORT_SYMBOL_GPL(module_mutex);
static LIST_HEAD(modules);
+/* Block module loading/unloading? */
+int modules_disabled = 0;
+
/* Waiting for a module to finish initializing? */
static DECLARE_WAIT_QUEUE_HEAD(module_wq);
@@ -429,6 +434,7 @@ static void *percpu_modalloc(unsigned long size, unsigned long align,
unsigned long extra;
unsigned int i;
void *ptr;
+ int cpu;
if (align > PAGE_SIZE) {
printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n",
@@ -458,6 +464,11 @@ static void *percpu_modalloc(unsigned long size, unsigned long align,
if (!split_block(i, size))
return NULL;
+ /* add the per-cpu scanning areas */
+ for_each_possible_cpu(cpu)
+ kmemleak_alloc(ptr + per_cpu_offset(cpu), size, 0,
+ GFP_KERNEL);
+
/* Mark allocated */
pcpu_size[i] = -pcpu_size[i];
return ptr;
@@ -472,6 +483,7 @@ static void percpu_modfree(void *freeme)
{
unsigned int i;
void *ptr = __per_cpu_start + block_size(pcpu_size[0]);
+ int cpu;
/* First entry is core kernel percpu data. */
for (i = 1; i < pcpu_num_used; ptr += block_size(pcpu_size[i]), i++) {
@@ -483,6 +495,10 @@ static void percpu_modfree(void *freeme)
BUG();
free:
+ /* remove the per-cpu scanning areas */
+ for_each_possible_cpu(cpu)
+ kmemleak_free(freeme + per_cpu_offset(cpu));
+
/* Merge with previous? */
if (pcpu_size[i-1] >= 0) {
pcpu_size[i-1] += pcpu_size[i];
@@ -777,7 +793,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
char name[MODULE_NAME_LEN];
int ret, forced = 0;
- if (!capable(CAP_SYS_MODULE))
+ if (!capable(CAP_SYS_MODULE) || modules_disabled)
return -EPERM;
if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
@@ -1489,9 +1505,6 @@ static void free_module(struct module *mod)
/* Free any allocated parameters. */
destroy_params(mod->kp, mod->num_kp);
- /* release any pointers to mcount in this module */
- ftrace_release(mod->module_core, mod->core_size);
-
/* This may be NULL, but that's OK */
module_free(mod, mod->module_init);
kfree(mod->args);
@@ -1878,6 +1891,36 @@ static void *module_alloc_update_bounds(unsigned long size)
return ret;
}
+#ifdef CONFIG_DEBUG_KMEMLEAK
+static void kmemleak_load_module(struct module *mod, Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs, char *secstrings)
+{
+ unsigned int i;
+
+ /* only scan the sections containing data */
+ kmemleak_scan_area(mod->module_core, (unsigned long)mod -
+ (unsigned long)mod->module_core,
+ sizeof(struct module), GFP_KERNEL);
+
+ for (i = 1; i < hdr->e_shnum; i++) {
+ if (!(sechdrs[i].sh_flags & SHF_ALLOC))
+ continue;
+ if (strncmp(secstrings + sechdrs[i].sh_name, ".data", 5) != 0
+ && strncmp(secstrings + sechdrs[i].sh_name, ".bss", 4) != 0)
+ continue;
+
+ kmemleak_scan_area(mod->module_core, sechdrs[i].sh_addr -
+ (unsigned long)mod->module_core,
+ sechdrs[i].sh_size, GFP_KERNEL);
+ }
+}
+#else
+static inline void kmemleak_load_module(struct module *mod, Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs, char *secstrings)
+{
+}
+#endif
+
/* Allocate and load the module: note that size of section 0 is always
zero, and we rely on this for optional sections. */
static noinline struct module *load_module(void __user *umod,
@@ -1892,11 +1935,9 @@ static noinline struct module *load_module(void __user *umod,
unsigned int symindex = 0;
unsigned int strindex = 0;
unsigned int modindex, versindex, infoindex, pcpuindex;
- unsigned int num_mcount;
struct module *mod;
long err = 0;
void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
- unsigned long *mseg;
mm_segment_t old_fs;
DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
@@ -2050,6 +2091,12 @@ static noinline struct module *load_module(void __user *umod,
/* Do the allocs. */
ptr = module_alloc_update_bounds(mod->core_size);
+ /*
+ * The pointer to this block is stored in the module structure
+ * which is inside the block. Just mark it as not being a
+ * leak.
+ */
+ kmemleak_not_leak(ptr);
if (!ptr) {
err = -ENOMEM;
goto free_percpu;
@@ -2058,6 +2105,13 @@ static noinline struct module *load_module(void __user *umod,
mod->module_core = ptr;
ptr = module_alloc_update_bounds(mod->init_size);
+ /*
+ * The pointer to this block is stored in the module structure
+ * which is inside the block. This block doesn't need to be
+ * scanned as it contains data and code that will be freed
+ * after the module is initialized.
+ */
+ kmemleak_ignore(ptr);
if (!ptr && mod->init_size) {
err = -ENOMEM;
goto free_core;
@@ -2088,6 +2142,7 @@ static noinline struct module *load_module(void __user *umod,
}
/* Module has been moved. */
mod = (void *)sechdrs[modindex].sh_addr;
+ kmemleak_load_module(mod, hdr, sechdrs, secstrings);
#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP)
mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t),
@@ -2172,7 +2227,19 @@ static noinline struct module *load_module(void __user *umod,
sizeof(*mod->tracepoints),
&mod->num_tracepoints);
#endif
-
+#ifdef CONFIG_EVENT_TRACING
+ mod->trace_events = section_objs(hdr, sechdrs, secstrings,
+ "_ftrace_events",
+ sizeof(*mod->trace_events),
+ &mod->num_trace_events);
+#endif
+#ifdef CONFIG_FTRACE_MCOUNT_RECORD
+ /* sechdrs[0].sh_size is always zero */
+ mod->ftrace_callsites = section_objs(hdr, sechdrs, secstrings,
+ "__mcount_loc",
+ sizeof(*mod->ftrace_callsites),
+ &mod->num_ftrace_callsites);
+#endif
#ifdef CONFIG_MODVERSIONS
if ((mod->num_syms && !mod->crcs)
|| (mod->num_gpl_syms && !mod->gpl_crcs)
@@ -2237,11 +2304,6 @@ static noinline struct module *load_module(void __user *umod,
dynamic_debug_setup(debug, num_debug);
}
- /* sechdrs[0].sh_size is always zero */
- mseg = section_objs(hdr, sechdrs, secstrings, "__mcount_loc",
- sizeof(*mseg), &num_mcount);
- ftrace_init_module(mod, mseg, mseg + num_mcount);
-
err = module_finalize(hdr, sechdrs, mod);
if (err < 0)
goto cleanup;
@@ -2302,7 +2364,6 @@ static noinline struct module *load_module(void __user *umod,
cleanup:
kobject_del(&mod->mkobj.kobj);
kobject_put(&mod->mkobj.kobj);
- ftrace_release(mod->module_core, mod->core_size);
free_unload:
module_unload_free(mod);
#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP)
@@ -2336,7 +2397,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
int ret = 0;
/* Must have permission */
- if (!capable(CAP_SYS_MODULE))
+ if (!capable(CAP_SYS_MODULE) || modules_disabled)
return -EPERM;
/* Only one module load at a time, please */
diff --git a/kernel/mutex.c b/kernel/mutex.c
index 507cf2b5e9f1..e5cc0cd28d54 100644
--- a/kernel/mutex.c
+++ b/kernel/mutex.c
@@ -249,7 +249,9 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
/* didnt get the lock, go to sleep: */
spin_unlock_mutex(&lock->wait_lock, flags);
- __schedule();
+ preempt_enable_no_resched();
+ schedule();
+ preempt_disable();
spin_lock_mutex(&lock->wait_lock, flags);
}
@@ -471,5 +473,28 @@ int __sched mutex_trylock(struct mutex *lock)
return ret;
}
-
EXPORT_SYMBOL(mutex_trylock);
+
+/**
+ * atomic_dec_and_mutex_lock - return holding mutex if we dec to 0
+ * @cnt: the atomic which we are to dec
+ * @lock: the mutex to return holding if we dec to 0
+ *
+ * return true and hold lock if we dec to 0, return false otherwise
+ */
+int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock)
+{
+ /* dec if we can't possibly hit 0 */
+ if (atomic_add_unless(cnt, -1, 1))
+ return 0;
+ /* we might hit 0, so take the lock */
+ mutex_lock(lock);
+ if (!atomic_dec_and_test(cnt)) {
+ /* when we actually did the dec, we didn't hit 0 */
+ mutex_unlock(lock);
+ return 0;
+ }
+ /* we hit 0, and we hold the lock */
+ return 1;
+}
+EXPORT_SYMBOL(atomic_dec_and_mutex_lock);
diff --git a/kernel/panic.c b/kernel/panic.c
index 934fb377f4b3..874ecf1307ae 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -221,7 +221,7 @@ void add_taint(unsigned flag)
* post-warning case.
*/
if (flag != TAINT_CRAP && flag != TAINT_WARN && __debug_locks_off())
- printk(KERN_WARNING "Disabling lockdep due to kernel taint\n");
+ printk(KERN_WARNING "Disabling lock debugging due to kernel taint\n");
set_bit(flag, &tainted_mask);
}
@@ -340,7 +340,7 @@ void oops_exit(void)
}
#ifdef WANT_WARN_ON_SLOWPATH
-void warn_slowpath(const char *file, int line, const char *fmt, ...)
+void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...)
{
va_list args;
char function[KSYM_SYMBOL_LEN];
@@ -356,7 +356,7 @@ void warn_slowpath(const char *file, int line, const char *fmt, ...)
if (board)
printk(KERN_WARNING "Hardware name: %s\n", board);
- if (fmt) {
+ if (*fmt) {
va_start(args, fmt);
vprintk(fmt, args);
va_end(args);
@@ -367,7 +367,14 @@ void warn_slowpath(const char *file, int line, const char *fmt, ...)
print_oops_end_marker();
add_taint(TAINT_WARN);
}
-EXPORT_SYMBOL(warn_slowpath);
+EXPORT_SYMBOL(warn_slowpath_fmt);
+
+void warn_slowpath_null(const char *file, int line)
+{
+ static const char *empty = "";
+ warn_slowpath_fmt(file, line, empty);
+}
+EXPORT_SYMBOL(warn_slowpath_null);
#endif
#ifdef CONFIG_CC_STACKPROTECTOR
diff --git a/kernel/params.c b/kernel/params.c
index de273ec85bd2..7f6912ced2ba 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -24,9 +24,6 @@
#include <linux/err.h>
#include <linux/slab.h>
-/* We abuse the high bits of "perm" to record whether we kmalloc'ed. */
-#define KPARAM_KMALLOCED 0x80000000
-
#if 0
#define DEBUGP printk
#else
@@ -220,13 +217,13 @@ int param_set_charp(const char *val, struct kernel_param *kp)
return -ENOSPC;
}
- if (kp->perm & KPARAM_KMALLOCED)
+ if (kp->flags & KPARAM_KMALLOCED)
kfree(*(char **)kp->arg);
/* This is a hack. We can't need to strdup in early boot, and we
* don't need to; this mangled commandline is preserved. */
if (slab_is_available()) {
- kp->perm |= KPARAM_KMALLOCED;
+ kp->flags |= KPARAM_KMALLOCED;
*(char **)kp->arg = kstrdup(val, GFP_KERNEL);
if (!kp->arg)
return -ENOMEM;
@@ -241,44 +238,63 @@ int param_get_charp(char *buffer, struct kernel_param *kp)
return sprintf(buffer, "%s", *((char **)kp->arg));
}
+/* Actually could be a bool or an int, for historical reasons. */
int param_set_bool(const char *val, struct kernel_param *kp)
{
+ bool v;
+
/* No equals means "set"... */
if (!val) val = "1";
/* One of =[yYnN01] */
switch (val[0]) {
case 'y': case 'Y': case '1':
- *(int *)kp->arg = 1;
- return 0;
+ v = true;
+ break;
case 'n': case 'N': case '0':
- *(int *)kp->arg = 0;
- return 0;
+ v = false;
+ break;
+ default:
+ return -EINVAL;
}
- return -EINVAL;
+
+ if (kp->flags & KPARAM_ISBOOL)
+ *(bool *)kp->arg = v;
+ else
+ *(int *)kp->arg = v;
+ return 0;
}
int param_get_bool(char *buffer, struct kernel_param *kp)
{
+ bool val;
+ if (kp->flags & KPARAM_ISBOOL)
+ val = *(bool *)kp->arg;
+ else
+ val = *(int *)kp->arg;
+
/* Y and N chosen as being relatively non-coder friendly */
- return sprintf(buffer, "%c", (*(int *)kp->arg) ? 'Y' : 'N');
+ return sprintf(buffer, "%c", val ? 'Y' : 'N');
}
+/* This one must be bool. */
int param_set_invbool(const char *val, struct kernel_param *kp)
{
- int boolval, ret;
+ int ret;
+ bool boolval;
struct kernel_param dummy;
dummy.arg = &boolval;
+ dummy.flags = KPARAM_ISBOOL;
ret = param_set_bool(val, &dummy);
if (ret == 0)
- *(int *)kp->arg = !boolval;
+ *(bool *)kp->arg = !boolval;
return ret;
}
int param_get_invbool(char *buffer, struct kernel_param *kp)
{
- return sprintf(buffer, "%c", (*(int *)kp->arg) ? 'N' : 'Y');
+ return sprintf(buffer, "%c", (*(bool *)kp->arg) ? 'N' : 'Y');
}
/* We break the rule and mangle the string. */
@@ -591,7 +607,7 @@ void destroy_params(const struct kernel_param *params, unsigned num)
unsigned int i;
for (i = 0; i < num; i++)
- if (params[i].perm & KPARAM_KMALLOCED)
+ if (params[i].flags & KPARAM_KMALLOCED)
kfree(*(char **)params[i].arg);
}
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index c9dcf98b4463..bece7c0b67b2 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -1420,19 +1420,19 @@ void run_posix_cpu_timers(struct task_struct *tsk)
* timer call will interfere.
*/
list_for_each_entry_safe(timer, next, &firing, it.cpu.entry) {
- int firing;
+ int cpu_firing;
+
spin_lock(&timer->it_lock);
list_del_init(&timer->it.cpu.entry);
- firing = timer->it.cpu.firing;
+ cpu_firing = timer->it.cpu.firing;
timer->it.cpu.firing = 0;
/*
* The firing flag is -1 if we collided with a reset
* of the timer, which already reported this
* almost-firing as an overrun. So don't generate an event.
*/
- if (likely(firing >= 0)) {
+ if (likely(cpu_firing >= 0))
cpu_timer_fire(timer);
- }
spin_unlock(&timer->it_lock);
}
}
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 0854770b63b9..e71ca9cd81b2 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -646,13 +646,6 @@ static int software_resume(void)
return 0;
/*
- * We can't depend on SCSI devices being available after loading one of
- * their modules if scsi_complete_async_scans() is not called and the
- * resume device usually is a SCSI one.
- */
- scsi_complete_async_scans();
-
- /*
* 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
@@ -663,32 +656,42 @@ static int software_resume(void)
* here to avoid lockdep complaining.
*/
mutex_lock_nested(&pm_mutex, SINGLE_DEPTH_NESTING);
+
+ if (swsusp_resume_device)
+ goto Check_image;
+
+ if (!strlen(resume_file)) {
+ error = -ENOENT;
+ goto Unlock;
+ }
+
+ pr_debug("PM: Checking image partition %s\n", resume_file);
+
+ /* Check if the device is there */
+ swsusp_resume_device = name_to_dev_t(resume_file);
if (!swsusp_resume_device) {
- if (!strlen(resume_file)) {
- mutex_unlock(&pm_mutex);
- return -ENOENT;
- }
/*
* Some device discovery might still be in progress; we need
* to wait for this to finish.
*/
wait_for_device_probe();
+ /*
+ * We can't depend on SCSI devices being available after loading
+ * one of their modules until scsi_complete_async_scans() is
+ * called and the resume device usually is a SCSI one.
+ */
+ scsi_complete_async_scans();
+
swsusp_resume_device = name_to_dev_t(resume_file);
- pr_debug("PM: Resume from partition %s\n", resume_file);
- } else {
- pr_debug("PM: Resume from partition %d:%d\n",
- MAJOR(swsusp_resume_device),
- MINOR(swsusp_resume_device));
+ if (!swsusp_resume_device) {
+ error = -ENODEV;
+ goto Unlock;
+ }
}
- if (noresume) {
- /**
- * FIXME: If noresume is specified, we need to find the
- * partition and reset it back to normal swap space.
- */
- mutex_unlock(&pm_mutex);
- return 0;
- }
+ Check_image:
+ pr_debug("PM: Resume from partition %d:%d\n",
+ MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device));
pr_debug("PM: Checking hibernation image.\n");
error = swsusp_check();
diff --git a/kernel/power/main.c b/kernel/power/main.c
index f172f41858bb..f99ed6a75eac 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -291,20 +291,26 @@ static int suspend_enter(suspend_state_t state)
device_pm_lock();
+ if (suspend_ops->prepare) {
+ error = suspend_ops->prepare();
+ if (error)
+ goto Done;
+ }
+
error = device_power_down(PMSG_SUSPEND);
if (error) {
printk(KERN_ERR "PM: Some devices failed to power down\n");
- goto Done;
+ goto Platfrom_finish;
}
- if (suspend_ops->prepare) {
- error = suspend_ops->prepare();
+ if (suspend_ops->prepare_late) {
+ error = suspend_ops->prepare_late();
if (error)
goto Power_up_devices;
}
if (suspend_test(TEST_PLATFORM))
- goto Platfrom_finish;
+ goto Platform_wake;
error = disable_nonboot_cpus();
if (error || suspend_test(TEST_CPUS))
@@ -326,13 +332,17 @@ static int suspend_enter(suspend_state_t state)
Enable_cpus:
enable_nonboot_cpus();
- Platfrom_finish:
- if (suspend_ops->finish)
- suspend_ops->finish();
+ Platform_wake:
+ if (suspend_ops->wake)
+ suspend_ops->wake();
Power_up_devices:
device_power_up(PMSG_RESUME);
+ Platfrom_finish:
+ if (suspend_ops->finish)
+ suspend_ops->finish();
+
Done:
device_pm_unlock();
diff --git a/kernel/power/poweroff.c b/kernel/power/poweroff.c
index 97890831e1b5..e8b337006276 100644
--- a/kernel/power/poweroff.c
+++ b/kernel/power/poweroff.c
@@ -34,7 +34,7 @@ static struct sysrq_key_op sysrq_poweroff_op = {
.handler = handle_poweroff,
.help_msg = "powerOff",
.action_msg = "Power Off",
- .enable_mask = SYSRQ_ENABLE_BOOT,
+ .enable_mask = SYSRQ_ENABLE_BOOT,
};
static int pm_sysrq_init(void)
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 505f319e489c..8ba052c86d48 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -64,8 +64,6 @@ static int submit(int rw, pgoff_t page_off, struct page *page,
struct bio *bio;
bio = bio_alloc(__GFP_WAIT | __GFP_HIGH, 1);
- if (!bio)
- return -ENOMEM;
bio->bi_sector = page_off * (PAGE_SIZE >> 9);
bio->bi_bdev = resume_bdev;
bio->bi_end_io = end_swap_bio_read;
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 64191fa09b7e..37a8d813f223 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -25,16 +25,6 @@
/*
- * Initialize a new task whose father had been ptraced.
- *
- * Called from copy_process().
- */
-void ptrace_fork(struct task_struct *child, unsigned long clone_flags)
-{
- arch_ptrace_fork(child, clone_flags);
-}
-
-/*
* ptrace a task: make the debugger its new parent and
* move it to the ptrace list.
*
@@ -185,10 +175,11 @@ int ptrace_attach(struct task_struct *task)
if (same_thread_group(task, current))
goto out;
- /* Protect exec's credential calculations against our interference;
- * SUID, SGID and LSM creds get determined differently under ptrace.
+ /* Protect the target's credential calculations against our
+ * interference; SUID, SGID and LSM creds get determined differently
+ * under ptrace.
*/
- retval = mutex_lock_interruptible(&current->cred_exec_mutex);
+ retval = mutex_lock_interruptible(&task->cred_guard_mutex);
if (retval < 0)
goto out;
@@ -232,7 +223,7 @@ repeat:
bad:
write_unlock_irqrestore(&tasklist_lock, flags);
task_unlock(task);
- mutex_unlock(&current->cred_exec_mutex);
+ mutex_unlock(&task->cred_guard_mutex);
out:
return retval;
}
@@ -604,10 +595,11 @@ repeat:
ret = security_ptrace_traceme(current->parent);
/*
- * Set the ptrace bit in the process ptrace flags.
- * Then link us on our parent's ptraced list.
+ * Check PF_EXITING to ensure ->real_parent has not passed
+ * exit_ptrace(). Otherwise we don't report the error but
+ * pretend ->real_parent untraces us right after return.
*/
- if (!ret) {
+ if (!ret && !(current->real_parent->flags & PF_EXITING)) {
current->ptrace |= PT_PTRACED;
__ptrace_link(current, current->real_parent);
}
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index 2c7b8457d0d2..a967c9feb90a 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -58,6 +58,10 @@ static DEFINE_MUTEX(rcu_barrier_mutex);
static struct completion rcu_barrier_completion;
int rcu_scheduler_active __read_mostly;
+static atomic_t rcu_migrate_type_count = ATOMIC_INIT(0);
+static struct rcu_head rcu_migrate_head[3];
+static DECLARE_WAIT_QUEUE_HEAD(rcu_migrate_wq);
+
/*
* Awaken the corresponding synchronize_rcu() instance now that a
* grace period has elapsed.
@@ -122,7 +126,10 @@ static void rcu_barrier_func(void *type)
}
}
-static inline void wait_migrated_callbacks(void);
+static inline void wait_migrated_callbacks(void)
+{
+ wait_event(rcu_migrate_wq, !atomic_read(&rcu_migrate_type_count));
+}
/*
* Orchestrate the specified type of RCU barrier, waiting for all
@@ -179,21 +186,12 @@ void rcu_barrier_sched(void)
}
EXPORT_SYMBOL_GPL(rcu_barrier_sched);
-static atomic_t rcu_migrate_type_count = ATOMIC_INIT(0);
-static struct rcu_head rcu_migrate_head[3];
-static DECLARE_WAIT_QUEUE_HEAD(rcu_migrate_wq);
-
static void rcu_migrate_callback(struct rcu_head *notused)
{
if (atomic_dec_and_test(&rcu_migrate_type_count))
wake_up(&rcu_migrate_wq);
}
-static inline void wait_migrated_callbacks(void)
-{
- wait_event(rcu_migrate_wq, !atomic_read(&rcu_migrate_type_count));
-}
-
static int __cpuinit rcu_barrier_cpu_hotplug(struct notifier_block *self,
unsigned long action, void *hcpu)
{
diff --git a/kernel/rcupreempt.c b/kernel/rcupreempt.c
index ce97a4df64d3..beb0e659adcc 100644
--- a/kernel/rcupreempt.c
+++ b/kernel/rcupreempt.c
@@ -1356,17 +1356,11 @@ static int rcu_sched_grace_period(void *arg)
rcu_ctrlblk.sched_sleep = rcu_sched_sleeping;
spin_unlock_irqrestore(&rcu_ctrlblk.schedlock, flags);
- ret = 0;
+ ret = 0; /* unused */
__wait_event_interruptible(rcu_ctrlblk.sched_wq,
rcu_ctrlblk.sched_sleep != rcu_sched_sleeping,
ret);
- /*
- * Signals would prevent us from sleeping, and we cannot
- * do much with them in any case. So flush them.
- */
- if (ret)
- flush_signals(current);
couldsleepnext = 0;
} while (!kthread_should_stop());
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index 7f3266922572..0dccfbba6d26 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -530,8 +530,6 @@ static void note_new_gpnum(struct rcu_state *rsp, struct rcu_data *rdp)
rdp->qs_pending = 1;
rdp->passed_quiesc = 0;
rdp->gpnum = rsp->gpnum;
- rdp->n_rcu_pending_force_qs = rdp->n_rcu_pending +
- RCU_JIFFIES_TILL_FORCE_QS;
}
/*
@@ -578,8 +576,6 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)
rsp->gpnum++;
rsp->signaled = RCU_GP_INIT; /* Hold off force_quiescent_state. */
rsp->jiffies_force_qs = jiffies + RCU_JIFFIES_TILL_FORCE_QS;
- rdp->n_rcu_pending_force_qs = rdp->n_rcu_pending +
- RCU_JIFFIES_TILL_FORCE_QS;
record_gp_stall_check_time(rsp);
dyntick_record_completed(rsp, rsp->completed - 1);
note_new_gpnum(rsp, rdp);
@@ -1055,7 +1051,6 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed)
{
unsigned long flags;
long lastcomp;
- struct rcu_data *rdp = rsp->rda[smp_processor_id()];
struct rcu_node *rnp = rcu_get_root(rsp);
u8 signaled;
@@ -1066,16 +1061,13 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed)
return; /* Someone else is already on the job. */
}
if (relaxed &&
- (long)(rsp->jiffies_force_qs - jiffies) >= 0 &&
- (rdp->n_rcu_pending_force_qs - rdp->n_rcu_pending) >= 0)
+ (long)(rsp->jiffies_force_qs - jiffies) >= 0)
goto unlock_ret; /* no emergency and done recently. */
rsp->n_force_qs++;
spin_lock(&rnp->lock);
lastcomp = rsp->completed;
signaled = rsp->signaled;
rsp->jiffies_force_qs = jiffies + RCU_JIFFIES_TILL_FORCE_QS;
- rdp->n_rcu_pending_force_qs = rdp->n_rcu_pending +
- RCU_JIFFIES_TILL_FORCE_QS;
if (lastcomp == rsp->gpnum) {
rsp->n_force_qs_ngp++;
spin_unlock(&rnp->lock);
@@ -1144,8 +1136,7 @@ __rcu_process_callbacks(struct rcu_state *rsp, struct rcu_data *rdp)
* If an RCU GP has gone long enough, go check for dyntick
* idle CPUs and, if needed, send resched IPIs.
*/
- if ((long)(ACCESS_ONCE(rsp->jiffies_force_qs) - jiffies) < 0 ||
- (rdp->n_rcu_pending_force_qs - rdp->n_rcu_pending) < 0)
+ if ((long)(ACCESS_ONCE(rsp->jiffies_force_qs) - jiffies) < 0)
force_quiescent_state(rsp, 1);
/*
@@ -1230,8 +1221,7 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
if (unlikely(++rdp->qlen > qhimark)) {
rdp->blimit = LONG_MAX;
force_quiescent_state(rsp, 0);
- } else if ((long)(ACCESS_ONCE(rsp->jiffies_force_qs) - jiffies) < 0 ||
- (rdp->n_rcu_pending_force_qs - rdp->n_rcu_pending) < 0)
+ } else if ((long)(ACCESS_ONCE(rsp->jiffies_force_qs) - jiffies) < 0)
force_quiescent_state(rsp, 1);
local_irq_restore(flags);
}
@@ -1269,32 +1259,44 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp)
check_cpu_stall(rsp, rdp);
/* Is the RCU core waiting for a quiescent state from this CPU? */
- if (rdp->qs_pending)
+ if (rdp->qs_pending) {
+ rdp->n_rp_qs_pending++;
return 1;
+ }
/* Does this CPU have callbacks ready to invoke? */
- if (cpu_has_callbacks_ready_to_invoke(rdp))
+ if (cpu_has_callbacks_ready_to_invoke(rdp)) {
+ rdp->n_rp_cb_ready++;
return 1;
+ }
/* Has RCU gone idle with this CPU needing another grace period? */
- if (cpu_needs_another_gp(rsp, rdp))
+ if (cpu_needs_another_gp(rsp, rdp)) {
+ rdp->n_rp_cpu_needs_gp++;
return 1;
+ }
/* Has another RCU grace period completed? */
- if (ACCESS_ONCE(rsp->completed) != rdp->completed) /* outside of lock */
+ if (ACCESS_ONCE(rsp->completed) != rdp->completed) { /* outside lock */
+ rdp->n_rp_gp_completed++;
return 1;
+ }
/* Has a new RCU grace period started? */
- if (ACCESS_ONCE(rsp->gpnum) != rdp->gpnum) /* outside of lock */
+ if (ACCESS_ONCE(rsp->gpnum) != rdp->gpnum) { /* outside lock */
+ rdp->n_rp_gp_started++;
return 1;
+ }
/* Has an RCU GP gone long enough to send resched IPIs &c? */
if (ACCESS_ONCE(rsp->completed) != ACCESS_ONCE(rsp->gpnum) &&
- ((long)(ACCESS_ONCE(rsp->jiffies_force_qs) - jiffies) < 0 ||
- (rdp->n_rcu_pending_force_qs - rdp->n_rcu_pending) < 0))
+ ((long)(ACCESS_ONCE(rsp->jiffies_force_qs) - jiffies) < 0)) {
+ rdp->n_rp_need_fqs++;
return 1;
+ }
/* nothing to do */
+ rdp->n_rp_need_nothing++;
return 0;
}
diff --git a/kernel/rcutree_trace.c b/kernel/rcutree_trace.c
index 4ee954f6a8d5..fe1dcdbf1ca3 100644
--- a/kernel/rcutree_trace.c
+++ b/kernel/rcutree_trace.c
@@ -49,14 +49,12 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp)
{
if (!rdp->beenonline)
return;
- seq_printf(m, "%3d%cc=%ld g=%ld pq=%d pqc=%ld qp=%d rpfq=%ld rp=%x",
+ seq_printf(m, "%3d%cc=%ld g=%ld pq=%d pqc=%ld qp=%d",
rdp->cpu,
cpu_is_offline(rdp->cpu) ? '!' : ' ',
rdp->completed, rdp->gpnum,
rdp->passed_quiesc, rdp->passed_quiesc_completed,
- rdp->qs_pending,
- rdp->n_rcu_pending_force_qs - rdp->n_rcu_pending,
- (int)(rdp->n_rcu_pending & 0xffff));
+ rdp->qs_pending);
#ifdef CONFIG_NO_HZ
seq_printf(m, " dt=%d/%d dn=%d df=%lu",
rdp->dynticks->dynticks,
@@ -102,14 +100,12 @@ static void print_one_rcu_data_csv(struct seq_file *m, struct rcu_data *rdp)
{
if (!rdp->beenonline)
return;
- seq_printf(m, "%d,%s,%ld,%ld,%d,%ld,%d,%ld,%ld",
+ seq_printf(m, "%d,%s,%ld,%ld,%d,%ld,%d",
rdp->cpu,
cpu_is_offline(rdp->cpu) ? "\"Y\"" : "\"N\"",
rdp->completed, rdp->gpnum,
rdp->passed_quiesc, rdp->passed_quiesc_completed,
- rdp->qs_pending,
- rdp->n_rcu_pending_force_qs - rdp->n_rcu_pending,
- rdp->n_rcu_pending);
+ rdp->qs_pending);
#ifdef CONFIG_NO_HZ
seq_printf(m, ",%d,%d,%d,%lu",
rdp->dynticks->dynticks,
@@ -123,7 +119,7 @@ static void print_one_rcu_data_csv(struct seq_file *m, struct rcu_data *rdp)
static int show_rcudata_csv(struct seq_file *m, void *unused)
{
- seq_puts(m, "\"CPU\",\"Online?\",\"c\",\"g\",\"pq\",\"pqc\",\"pq\",\"rpfq\",\"rp\",");
+ seq_puts(m, "\"CPU\",\"Online?\",\"c\",\"g\",\"pq\",\"pqc\",\"pq\",");
#ifdef CONFIG_NO_HZ
seq_puts(m, "\"dt\",\"dt nesting\",\"dn\",\"df\",");
#endif /* #ifdef CONFIG_NO_HZ */
@@ -217,7 +213,63 @@ static struct file_operations rcugp_fops = {
.release = single_release,
};
-static struct dentry *rcudir, *datadir, *datadir_csv, *hierdir, *gpdir;
+static void print_one_rcu_pending(struct seq_file *m, struct rcu_data *rdp)
+{
+ seq_printf(m, "%3d%cnp=%ld "
+ "qsp=%ld cbr=%ld cng=%ld gpc=%ld gps=%ld nf=%ld nn=%ld\n",
+ rdp->cpu,
+ cpu_is_offline(rdp->cpu) ? '!' : ' ',
+ rdp->n_rcu_pending,
+ rdp->n_rp_qs_pending,
+ rdp->n_rp_cb_ready,
+ rdp->n_rp_cpu_needs_gp,
+ rdp->n_rp_gp_completed,
+ rdp->n_rp_gp_started,
+ rdp->n_rp_need_fqs,
+ rdp->n_rp_need_nothing);
+}
+
+static void print_rcu_pendings(struct seq_file *m, struct rcu_state *rsp)
+{
+ int cpu;
+ struct rcu_data *rdp;
+
+ for_each_possible_cpu(cpu) {
+ rdp = rsp->rda[cpu];
+ if (rdp->beenonline)
+ print_one_rcu_pending(m, rdp);
+ }
+}
+
+static int show_rcu_pending(struct seq_file *m, void *unused)
+{
+ seq_puts(m, "rcu:\n");
+ print_rcu_pendings(m, &rcu_state);
+ seq_puts(m, "rcu_bh:\n");
+ print_rcu_pendings(m, &rcu_bh_state);
+ return 0;
+}
+
+static int rcu_pending_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, show_rcu_pending, NULL);
+}
+
+static struct file_operations rcu_pending_fops = {
+ .owner = THIS_MODULE,
+ .open = rcu_pending_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static struct dentry *rcudir;
+static struct dentry *datadir;
+static struct dentry *datadir_csv;
+static struct dentry *gpdir;
+static struct dentry *hierdir;
+static struct dentry *rcu_pendingdir;
+
static int __init rcuclassic_trace_init(void)
{
rcudir = debugfs_create_dir("rcu", NULL);
@@ -242,6 +294,11 @@ static int __init rcuclassic_trace_init(void)
NULL, &rcuhier_fops);
if (!hierdir)
goto free_out;
+
+ rcu_pendingdir = debugfs_create_file("rcu_pending", 0444, rcudir,
+ NULL, &rcu_pending_fops);
+ if (!rcu_pendingdir)
+ goto free_out;
return 0;
free_out:
if (datadir)
@@ -261,6 +318,7 @@ static void __exit rcuclassic_trace_cleanup(void)
debugfs_remove(datadir_csv);
debugfs_remove(gpdir);
debugfs_remove(hierdir);
+ debugfs_remove(rcu_pendingdir);
debugfs_remove(rcudir);
}
diff --git a/kernel/resource.c b/kernel/resource.c
index fd5d7d574bb9..ac5f3a36923f 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -533,43 +533,21 @@ static void __init __reserve_region_with_split(struct resource *root,
res->end = end;
res->flags = IORESOURCE_BUSY;
- for (;;) {
- conflict = __request_resource(parent, res);
- if (!conflict)
- break;
- if (conflict != parent) {
- parent = conflict;
- if (!(conflict->flags & IORESOURCE_BUSY))
- continue;
- }
-
- /* Uhhuh, that didn't work out.. */
- kfree(res);
- res = NULL;
- break;
- }
-
- if (!res) {
- /* failed, split and try again */
-
- /* conflict covered whole area */
- if (conflict->start <= start && conflict->end >= end)
- return;
+ conflict = __request_resource(parent, res);
+ if (!conflict)
+ return;
- if (conflict->start > start)
- __reserve_region_with_split(root, start, conflict->start-1, name);
- if (!(conflict->flags & IORESOURCE_BUSY)) {
- resource_size_t common_start, common_end;
+ /* failed, split and try again */
+ kfree(res);
- common_start = max(conflict->start, start);
- common_end = min(conflict->end, end);
- if (common_start < common_end)
- __reserve_region_with_split(root, common_start, common_end, name);
- }
- if (conflict->end < end)
- __reserve_region_with_split(root, conflict->end+1, end, name);
- }
+ /* conflict covered whole area */
+ if (conflict->start <= start && conflict->end >= end)
+ return;
+ if (conflict->start > start)
+ __reserve_region_with_split(root, start, conflict->start-1, name);
+ if (conflict->end < end)
+ __reserve_region_with_split(root, conflict->end+1, end, name);
}
void __init reserve_region_with_split(struct resource *root,
diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c
index 69d9cb921ffa..820c5af44f3e 100644
--- a/kernel/rtmutex.c
+++ b/kernel/rtmutex.c
@@ -300,7 +300,8 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
* assigned pending owner [which might not have taken the
* lock yet]:
*/
-static inline int try_to_steal_lock(struct rt_mutex *lock)
+static inline int try_to_steal_lock(struct rt_mutex *lock,
+ struct task_struct *task)
{
struct task_struct *pendowner = rt_mutex_owner(lock);
struct rt_mutex_waiter *next;
@@ -309,11 +310,11 @@ static inline int try_to_steal_lock(struct rt_mutex *lock)
if (!rt_mutex_owner_pending(lock))
return 0;
- if (pendowner == current)
+ if (pendowner == task)
return 1;
spin_lock_irqsave(&pendowner->pi_lock, flags);
- if (current->prio >= pendowner->prio) {
+ if (task->prio >= pendowner->prio) {
spin_unlock_irqrestore(&pendowner->pi_lock, flags);
return 0;
}
@@ -338,21 +339,21 @@ static inline int try_to_steal_lock(struct rt_mutex *lock)
* We are going to steal the lock and a waiter was
* enqueued on the pending owners pi_waiters queue. So
* we have to enqueue this waiter into
- * current->pi_waiters list. This covers the case,
- * where current is boosted because it holds another
+ * task->pi_waiters list. This covers the case,
+ * where task is boosted because it holds another
* lock and gets unboosted because the booster is
* interrupted, so we would delay a waiter with higher
- * priority as current->normal_prio.
+ * priority as task->normal_prio.
*
* Note: in the rare case of a SCHED_OTHER task changing
* its priority and thus stealing the lock, next->task
- * might be current:
+ * might be task:
*/
- if (likely(next->task != current)) {
- spin_lock_irqsave(&current->pi_lock, flags);
- plist_add(&next->pi_list_entry, &current->pi_waiters);
- __rt_mutex_adjust_prio(current);
- spin_unlock_irqrestore(&current->pi_lock, flags);
+ if (likely(next->task != task)) {
+ spin_lock_irqsave(&task->pi_lock, flags);
+ plist_add(&next->pi_list_entry, &task->pi_waiters);
+ __rt_mutex_adjust_prio(task);
+ spin_unlock_irqrestore(&task->pi_lock, flags);
}
return 1;
}
@@ -389,7 +390,7 @@ static int try_to_take_rt_mutex(struct rt_mutex *lock)
*/
mark_rt_mutex_waiters(lock);
- if (rt_mutex_owner(lock) && !try_to_steal_lock(lock))
+ if (rt_mutex_owner(lock) && !try_to_steal_lock(lock, current))
return 0;
/* We got the lock. */
@@ -411,6 +412,7 @@ static int try_to_take_rt_mutex(struct rt_mutex *lock)
*/
static int task_blocks_on_rt_mutex(struct rt_mutex *lock,
struct rt_mutex_waiter *waiter,
+ struct task_struct *task,
int detect_deadlock)
{
struct task_struct *owner = rt_mutex_owner(lock);
@@ -418,21 +420,21 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock,
unsigned long flags;
int chain_walk = 0, res;
- spin_lock_irqsave(&current->pi_lock, flags);
- __rt_mutex_adjust_prio(current);
- waiter->task = current;
+ spin_lock_irqsave(&task->pi_lock, flags);
+ __rt_mutex_adjust_prio(task);
+ waiter->task = task;
waiter->lock = lock;
- plist_node_init(&waiter->list_entry, current->prio);
- plist_node_init(&waiter->pi_list_entry, current->prio);
+ plist_node_init(&waiter->list_entry, task->prio);
+ plist_node_init(&waiter->pi_list_entry, task->prio);
/* Get the top priority waiter on the lock */
if (rt_mutex_has_waiters(lock))
top_waiter = rt_mutex_top_waiter(lock);
plist_add(&waiter->list_entry, &lock->wait_list);
- current->pi_blocked_on = waiter;
+ task->pi_blocked_on = waiter;
- spin_unlock_irqrestore(&current->pi_lock, flags);
+ spin_unlock_irqrestore(&task->pi_lock, flags);
if (waiter == rt_mutex_top_waiter(lock)) {
spin_lock_irqsave(&owner->pi_lock, flags);
@@ -460,7 +462,7 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock,
spin_unlock(&lock->wait_lock);
res = rt_mutex_adjust_prio_chain(owner, detect_deadlock, lock, waiter,
- current);
+ task);
spin_lock(&lock->wait_lock);
@@ -605,37 +607,25 @@ void rt_mutex_adjust_pi(struct task_struct *task)
rt_mutex_adjust_prio_chain(task, 0, NULL, NULL, task);
}
-/*
- * Slow path lock function:
+/**
+ * __rt_mutex_slowlock() - Perform the wait-wake-try-to-take loop
+ * @lock: the rt_mutex to take
+ * @state: the state the task should block in (TASK_INTERRUPTIBLE
+ * or TASK_UNINTERRUPTIBLE)
+ * @timeout: the pre-initialized and started timer, or NULL for none
+ * @waiter: the pre-initialized rt_mutex_waiter
+ * @detect_deadlock: passed to task_blocks_on_rt_mutex
+ *
+ * lock->wait_lock must be held by the caller.
*/
static int __sched
-rt_mutex_slowlock(struct rt_mutex *lock, int state,
- struct hrtimer_sleeper *timeout,
- int detect_deadlock)
+__rt_mutex_slowlock(struct rt_mutex *lock, int state,
+ struct hrtimer_sleeper *timeout,
+ struct rt_mutex_waiter *waiter,
+ int detect_deadlock)
{
- struct rt_mutex_waiter waiter;
int ret = 0;
- debug_rt_mutex_init_waiter(&waiter);
- waiter.task = NULL;
-
- spin_lock(&lock->wait_lock);
-
- /* Try to acquire the lock again: */
- if (try_to_take_rt_mutex(lock)) {
- spin_unlock(&lock->wait_lock);
- return 0;
- }
-
- set_current_state(state);
-
- /* Setup the timer, when timeout != NULL */
- if (unlikely(timeout)) {
- hrtimer_start_expires(&timeout->timer, HRTIMER_MODE_ABS);
- if (!hrtimer_active(&timeout->timer))
- timeout->task = NULL;
- }
-
for (;;) {
/* Try to acquire the lock: */
if (try_to_take_rt_mutex(lock))
@@ -656,19 +646,19 @@ rt_mutex_slowlock(struct rt_mutex *lock, int state,
}
/*
- * waiter.task is NULL the first time we come here and
+ * waiter->task is NULL the first time we come here and
* when we have been woken up by the previous owner
* but the lock got stolen by a higher prio task.
*/
- if (!waiter.task) {
- ret = task_blocks_on_rt_mutex(lock, &waiter,
+ if (!waiter->task) {
+ ret = task_blocks_on_rt_mutex(lock, waiter, current,
detect_deadlock);
/*
* If we got woken up by the owner then start loop
* all over without going into schedule to try
* to get the lock now:
*/
- if (unlikely(!waiter.task)) {
+ if (unlikely(!waiter->task)) {
/*
* Reset the return value. We might
* have returned with -EDEADLK and the
@@ -684,15 +674,52 @@ rt_mutex_slowlock(struct rt_mutex *lock, int state,
spin_unlock(&lock->wait_lock);
- debug_rt_mutex_print_deadlock(&waiter);
+ debug_rt_mutex_print_deadlock(waiter);
- if (waiter.task)
+ if (waiter->task)
schedule_rt_mutex(lock);
spin_lock(&lock->wait_lock);
set_current_state(state);
}
+ return ret;
+}
+
+/*
+ * Slow path lock function:
+ */
+static int __sched
+rt_mutex_slowlock(struct rt_mutex *lock, int state,
+ struct hrtimer_sleeper *timeout,
+ int detect_deadlock)
+{
+ struct rt_mutex_waiter waiter;
+ int ret = 0;
+
+ debug_rt_mutex_init_waiter(&waiter);
+ waiter.task = NULL;
+
+ spin_lock(&lock->wait_lock);
+
+ /* Try to acquire the lock again: */
+ if (try_to_take_rt_mutex(lock)) {
+ spin_unlock(&lock->wait_lock);
+ return 0;
+ }
+
+ set_current_state(state);
+
+ /* Setup the timer, when timeout != NULL */
+ if (unlikely(timeout)) {
+ hrtimer_start_expires(&timeout->timer, HRTIMER_MODE_ABS);
+ if (!hrtimer_active(&timeout->timer))
+ timeout->task = NULL;
+ }
+
+ ret = __rt_mutex_slowlock(lock, state, timeout, &waiter,
+ detect_deadlock);
+
set_current_state(TASK_RUNNING);
if (unlikely(waiter.task))
@@ -864,9 +891,9 @@ int __sched rt_mutex_lock_interruptible(struct rt_mutex *lock,
EXPORT_SYMBOL_GPL(rt_mutex_lock_interruptible);
/**
- * rt_mutex_lock_interruptible_ktime - lock a rt_mutex interruptible
- * the timeout structure is provided
- * by the caller
+ * rt_mutex_timed_lock - lock a rt_mutex interruptible
+ * the timeout structure is provided
+ * by the caller
*
* @lock: the rt_mutex to be locked
* @timeout: timeout structure or NULL (no timeout)
@@ -913,7 +940,7 @@ void __sched rt_mutex_unlock(struct rt_mutex *lock)
}
EXPORT_SYMBOL_GPL(rt_mutex_unlock);
-/***
+/**
* rt_mutex_destroy - mark a mutex unusable
* @lock: the mutex to be destroyed
*
@@ -986,6 +1013,59 @@ void rt_mutex_proxy_unlock(struct rt_mutex *lock,
}
/**
+ * rt_mutex_start_proxy_lock() - Start lock acquisition for another task
+ * @lock: the rt_mutex to take
+ * @waiter: the pre-initialized rt_mutex_waiter
+ * @task: the task to prepare
+ * @detect_deadlock: perform deadlock detection (1) or not (0)
+ *
+ * Returns:
+ * 0 - task blocked on lock
+ * 1 - acquired the lock for task, caller should wake it up
+ * <0 - error
+ *
+ * Special API call for FUTEX_REQUEUE_PI support.
+ */
+int rt_mutex_start_proxy_lock(struct rt_mutex *lock,
+ struct rt_mutex_waiter *waiter,
+ struct task_struct *task, int detect_deadlock)
+{
+ int ret;
+
+ spin_lock(&lock->wait_lock);
+
+ mark_rt_mutex_waiters(lock);
+
+ if (!rt_mutex_owner(lock) || try_to_steal_lock(lock, task)) {
+ /* We got the lock for task. */
+ debug_rt_mutex_lock(lock);
+
+ rt_mutex_set_owner(lock, task, 0);
+
+ rt_mutex_deadlock_account_lock(lock, task);
+ return 1;
+ }
+
+ ret = task_blocks_on_rt_mutex(lock, waiter, task, detect_deadlock);
+
+
+ if (ret && !waiter->task) {
+ /*
+ * Reset the return value. We might have
+ * returned with -EDEADLK and the owner
+ * released the lock while we were walking the
+ * pi chain. Let the waiter sort it out.
+ */
+ ret = 0;
+ }
+ spin_unlock(&lock->wait_lock);
+
+ debug_rt_mutex_print_deadlock(waiter);
+
+ return ret;
+}
+
+/**
* rt_mutex_next_owner - return the next owner of the lock
*
* @lock: the rt lock query
@@ -1004,3 +1084,57 @@ struct task_struct *rt_mutex_next_owner(struct rt_mutex *lock)
return rt_mutex_top_waiter(lock)->task;
}
+
+/**
+ * rt_mutex_finish_proxy_lock() - Complete lock acquisition
+ * @lock: the rt_mutex we were woken on
+ * @to: the timeout, null if none. hrtimer should already have
+ * been started.
+ * @waiter: the pre-initialized rt_mutex_waiter
+ * @detect_deadlock: perform deadlock detection (1) or not (0)
+ *
+ * Complete the lock acquisition started our behalf by another thread.
+ *
+ * Returns:
+ * 0 - success
+ * <0 - error, one of -EINTR, -ETIMEDOUT, or -EDEADLK
+ *
+ * Special API call for PI-futex requeue support
+ */
+int rt_mutex_finish_proxy_lock(struct rt_mutex *lock,
+ struct hrtimer_sleeper *to,
+ struct rt_mutex_waiter *waiter,
+ int detect_deadlock)
+{
+ int ret;
+
+ spin_lock(&lock->wait_lock);
+
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ ret = __rt_mutex_slowlock(lock, TASK_INTERRUPTIBLE, to, waiter,
+ detect_deadlock);
+
+ set_current_state(TASK_RUNNING);
+
+ if (unlikely(waiter->task))
+ remove_waiter(lock, waiter);
+
+ /*
+ * try_to_take_rt_mutex() sets the waiter bit unconditionally. We might
+ * have to fix that up.
+ */
+ fixup_rt_mutex_waiters(lock);
+
+ spin_unlock(&lock->wait_lock);
+
+ /*
+ * Readjust priority, when we did not get the lock. We might have been
+ * the pending owner and boosted. Since we did not take the lock, the
+ * PI boost has to go.
+ */
+ if (unlikely(ret))
+ rt_mutex_adjust_prio(current);
+
+ return ret;
+}
diff --git a/kernel/rtmutex_common.h b/kernel/rtmutex_common.h
index e124bf5800ea..97a2f81866af 100644
--- a/kernel/rtmutex_common.h
+++ b/kernel/rtmutex_common.h
@@ -120,6 +120,14 @@ extern void rt_mutex_init_proxy_locked(struct rt_mutex *lock,
struct task_struct *proxy_owner);
extern void rt_mutex_proxy_unlock(struct rt_mutex *lock,
struct task_struct *proxy_owner);
+extern int rt_mutex_start_proxy_lock(struct rt_mutex *lock,
+ struct rt_mutex_waiter *waiter,
+ struct task_struct *task,
+ int detect_deadlock);
+extern int rt_mutex_finish_proxy_lock(struct rt_mutex *lock,
+ struct hrtimer_sleeper *to,
+ struct rt_mutex_waiter *waiter,
+ int detect_deadlock);
#ifdef CONFIG_DEBUG_RT_MUTEXES
# include "rtmutex-debug.h"
diff --git a/kernel/sched.c b/kernel/sched.c
index 5724508c3b66..d6fa89ce687b 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -72,13 +72,15 @@
#include <linux/debugfs.h>
#include <linux/ctype.h>
#include <linux/ftrace.h>
-#include <trace/sched.h>
#include <asm/tlb.h>
#include <asm/irq_regs.h>
#include "sched_cpupri.h"
+#define CREATE_TRACE_POINTS
+#include <trace/events/sched.h>
+
/*
* Convert user-nice values [ -20 ... 0 ... 19 ]
* to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
@@ -118,12 +120,6 @@
*/
#define RUNTIME_INF ((u64)~0ULL)
-DEFINE_TRACE(sched_wait_task);
-DEFINE_TRACE(sched_wakeup);
-DEFINE_TRACE(sched_wakeup_new);
-DEFINE_TRACE(sched_switch);
-DEFINE_TRACE(sched_migrate_task);
-
#ifdef CONFIG_SMP
static void double_rq_lock(struct rq *rq1, struct rq *rq2);
@@ -1958,7 +1954,7 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
clock_offset = old_rq->clock - new_rq->clock;
- trace_sched_migrate_task(p, task_cpu(p), new_cpu);
+ trace_sched_migrate_task(p, new_cpu);
#ifdef CONFIG_SCHEDSTATS
if (p->se.wait_start)
@@ -2015,6 +2011,49 @@ migrate_task(struct task_struct *p, int dest_cpu, struct migration_req *req)
}
/*
+ * wait_task_context_switch - wait for a thread to complete at least one
+ * context switch.
+ *
+ * @p must not be current.
+ */
+void wait_task_context_switch(struct task_struct *p)
+{
+ unsigned long nvcsw, nivcsw, flags;
+ int running;
+ struct rq *rq;
+
+ nvcsw = p->nvcsw;
+ nivcsw = p->nivcsw;
+ for (;;) {
+ /*
+ * The runqueue is assigned before the actual context
+ * switch. We need to take the runqueue lock.
+ *
+ * We could check initially without the lock but it is
+ * very likely that we need to take the lock in every
+ * iteration.
+ */
+ rq = task_rq_lock(p, &flags);
+ running = task_running(rq, p);
+ task_rq_unlock(rq, &flags);
+
+ if (likely(!running))
+ break;
+ /*
+ * The switch count is incremented before the actual
+ * context switch. We thus wait for two switches to be
+ * sure at least one completed.
+ */
+ if ((p->nvcsw - nvcsw) > 1)
+ break;
+ if ((p->nivcsw - nivcsw) > 1)
+ break;
+
+ cpu_relax();
+ }
+}
+
+/*
* wait_task_inactive - wait for a thread to unschedule.
*
* If @match_state is nonzero, it's the @p->state value just checked and
@@ -2458,6 +2497,17 @@ out:
return success;
}
+/**
+ * wake_up_process - Wake up a specific process
+ * @p: The process to be woken up.
+ *
+ * Attempt to wake up the nominated process and move it to the set of runnable
+ * processes. Returns 1 if the process was woken up, 0 if it was already
+ * running.
+ *
+ * It may be assumed that this function implies a write memory barrier before
+ * changing the task state if and only if any tasks are woken up.
+ */
int wake_up_process(struct task_struct *p)
{
return try_to_wake_up(p, TASK_ALL, 0);
@@ -2766,7 +2816,7 @@ context_switch(struct rq *rq, struct task_struct *prev,
* combine the page table reload and the switch backend into
* one hypercall.
*/
- arch_enter_lazy_cpu_mode();
+ arch_start_context_switch(prev);
if (unlikely(!mm)) {
next->active_mm = oldmm;
@@ -4240,10 +4290,126 @@ static void active_load_balance(struct rq *busiest_rq, int busiest_cpu)
static struct {
atomic_t load_balancer;
cpumask_var_t cpu_mask;
+ cpumask_var_t ilb_grp_nohz_mask;
} nohz ____cacheline_aligned = {
.load_balancer = ATOMIC_INIT(-1),
};
+#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
+/**
+ * lowest_flag_domain - Return lowest sched_domain containing flag.
+ * @cpu: The cpu whose lowest level of sched domain is to
+ * be returned.
+ * @flag: The flag to check for the lowest sched_domain
+ * for the given cpu.
+ *
+ * Returns the lowest sched_domain of a cpu which contains the given flag.
+ */
+static inline struct sched_domain *lowest_flag_domain(int cpu, int flag)
+{
+ struct sched_domain *sd;
+
+ for_each_domain(cpu, sd)
+ if (sd && (sd->flags & flag))
+ break;
+
+ return sd;
+}
+
+/**
+ * for_each_flag_domain - Iterates over sched_domains containing the flag.
+ * @cpu: The cpu whose domains we're iterating over.
+ * @sd: variable holding the value of the power_savings_sd
+ * for cpu.
+ * @flag: The flag to filter the sched_domains to be iterated.
+ *
+ * Iterates over all the scheduler domains for a given cpu that has the 'flag'
+ * set, starting from the lowest sched_domain to the highest.
+ */
+#define for_each_flag_domain(cpu, sd, flag) \
+ for (sd = lowest_flag_domain(cpu, flag); \
+ (sd && (sd->flags & flag)); sd = sd->parent)
+
+/**
+ * is_semi_idle_group - Checks if the given sched_group is semi-idle.
+ * @ilb_group: group to be checked for semi-idleness
+ *
+ * Returns: 1 if the group is semi-idle. 0 otherwise.
+ *
+ * We define a sched_group to be semi idle if it has atleast one idle-CPU
+ * and atleast one non-idle CPU. This helper function checks if the given
+ * sched_group is semi-idle or not.
+ */
+static inline int is_semi_idle_group(struct sched_group *ilb_group)
+{
+ cpumask_and(nohz.ilb_grp_nohz_mask, nohz.cpu_mask,
+ sched_group_cpus(ilb_group));
+
+ /*
+ * A sched_group is semi-idle when it has atleast one busy cpu
+ * and atleast one idle cpu.
+ */
+ if (cpumask_empty(nohz.ilb_grp_nohz_mask))
+ return 0;
+
+ if (cpumask_equal(nohz.ilb_grp_nohz_mask, sched_group_cpus(ilb_group)))
+ return 0;
+
+ return 1;
+}
+/**
+ * find_new_ilb - Finds the optimum idle load balancer for nomination.
+ * @cpu: The cpu which is nominating a new idle_load_balancer.
+ *
+ * Returns: Returns the id of the idle load balancer if it exists,
+ * Else, returns >= nr_cpu_ids.
+ *
+ * This algorithm picks the idle load balancer such that it belongs to a
+ * semi-idle powersavings sched_domain. The idea is to try and avoid
+ * completely idle packages/cores just for the purpose of idle load balancing
+ * when there are other idle cpu's which are better suited for that job.
+ */
+static int find_new_ilb(int cpu)
+{
+ struct sched_domain *sd;
+ struct sched_group *ilb_group;
+
+ /*
+ * Have idle load balancer selection from semi-idle packages only
+ * when power-aware load balancing is enabled
+ */
+ if (!(sched_smt_power_savings || sched_mc_power_savings))
+ goto out_done;
+
+ /*
+ * Optimize for the case when we have no idle CPUs or only one
+ * idle CPU. Don't walk the sched_domain hierarchy in such cases
+ */
+ if (cpumask_weight(nohz.cpu_mask) < 2)
+ goto out_done;
+
+ for_each_flag_domain(cpu, sd, SD_POWERSAVINGS_BALANCE) {
+ ilb_group = sd->groups;
+
+ do {
+ if (is_semi_idle_group(ilb_group))
+ return cpumask_first(nohz.ilb_grp_nohz_mask);
+
+ ilb_group = ilb_group->next;
+
+ } while (ilb_group != sd->groups);
+ }
+
+out_done:
+ return cpumask_first(nohz.cpu_mask);
+}
+#else /* (CONFIG_SCHED_MC || CONFIG_SCHED_SMT) */
+static inline int find_new_ilb(int call_cpu)
+{
+ return cpumask_first(nohz.cpu_mask);
+}
+#endif
+
/*
* This routine will try to nominate the ilb (idle load balancing)
* owner among the cpus whose ticks are stopped. ilb owner will do the idle
@@ -4298,8 +4464,24 @@ int select_nohz_load_balancer(int stop_tick)
/* make me the ilb owner */
if (atomic_cmpxchg(&nohz.load_balancer, -1, cpu) == -1)
return 1;
- } else if (atomic_read(&nohz.load_balancer) == cpu)
+ } else if (atomic_read(&nohz.load_balancer) == cpu) {
+ int new_ilb;
+
+ if (!(sched_smt_power_savings ||
+ sched_mc_power_savings))
+ return 1;
+ /*
+ * Check to see if there is a more power-efficient
+ * ilb.
+ */
+ new_ilb = find_new_ilb(cpu);
+ if (new_ilb < nr_cpu_ids && new_ilb != cpu) {
+ atomic_set(&nohz.load_balancer, -1);
+ resched_cpu(new_ilb);
+ return 0;
+ }
return 1;
+ }
} else {
if (!cpumask_test_cpu(cpu, nohz.cpu_mask))
return 0;
@@ -4468,15 +4650,7 @@ static inline void trigger_load_balance(struct rq *rq, int cpu)
}
if (atomic_read(&nohz.load_balancer) == -1) {
- /*
- * simple selection for now: Nominate the
- * first cpu in the nohz list to be the next
- * ilb owner.
- *
- * TBD: Traverse the sched domains and nominate
- * the nearest cpu in the nohz.cpu_mask.
- */
- int ilb = cpumask_first(nohz.cpu_mask);
+ int ilb = find_new_ilb(cpu);
if (ilb < nr_cpu_ids)
resched_cpu(ilb);
@@ -4732,7 +4906,7 @@ void account_process_tick(struct task_struct *p, int user_tick)
if (user_tick)
account_user_time(p, one_jiffy, one_jiffy_scaled);
- else if (p != rq->idle)
+ else if ((p != rq->idle) || (irq_count() != HARDIRQ_OFFSET))
account_system_time(p, HARDIRQ_OFFSET, one_jiffy,
one_jiffy_scaled);
else
@@ -4846,7 +5020,7 @@ void scheduler_tick(void)
#endif
}
-unsigned long get_parent_ip(unsigned long addr)
+notrace unsigned long get_parent_ip(unsigned long addr)
{
if (in_lock_functions(addr)) {
addr = CALLER_ADDR2;
@@ -5007,13 +5181,15 @@ pick_next_task(struct rq *rq)
/*
* schedule() is the main scheduler function.
*/
-asmlinkage void __sched __schedule(void)
+asmlinkage void __sched schedule(void)
{
struct task_struct *prev, *next;
unsigned long *switch_count;
struct rq *rq;
int cpu;
+need_resched:
+ preempt_disable();
cpu = smp_processor_id();
rq = cpu_rq(cpu);
rcu_qsctr_inc(cpu);
@@ -5070,15 +5246,9 @@ need_resched_nonpreemptible:
if (unlikely(reacquire_kernel_lock(current) < 0))
goto need_resched_nonpreemptible;
-}
-asmlinkage void __sched schedule(void)
-{
-need_resched:
- preempt_disable();
- __schedule();
preempt_enable_no_resched();
- if (unlikely(test_thread_flag(TIF_NEED_RESCHED)))
+ if (need_resched())
goto need_resched;
}
EXPORT_SYMBOL(schedule);
@@ -5221,7 +5391,7 @@ EXPORT_SYMBOL(default_wake_function);
* started to run but is not in state TASK_RUNNING. try_to_wake_up() returns
* zero in this (rare) case, and we handle it by continuing to scan the queue.
*/
-void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
+static void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
int nr_exclusive, int sync, void *key)
{
wait_queue_t *curr, *next;
@@ -5241,6 +5411,9 @@ void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
* @mode: which threads
* @nr_exclusive: how many wake-one or wake-many threads to wake up
* @key: is directly passed to the wakeup function
+ *
+ * It may be assumed that this function implies a write memory barrier before
+ * changing the task state if and only if any tasks are woken up.
*/
void __wake_up(wait_queue_head_t *q, unsigned int mode,
int nr_exclusive, void *key)
@@ -5279,6 +5452,9 @@ void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, void *key)
* with each other. This can prevent needless bouncing between CPUs.
*
* On UP it can prevent extra preemption.
+ *
+ * It may be assumed that this function implies a write memory barrier before
+ * changing the task state if and only if any tasks are woken up.
*/
void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode,
int nr_exclusive, void *key)
@@ -5315,6 +5491,9 @@ EXPORT_SYMBOL_GPL(__wake_up_sync); /* For internal use only */
* awakened in the same order in which they were queued.
*
* See also complete_all(), wait_for_completion() and related routines.
+ *
+ * It may be assumed that this function implies a write memory barrier before
+ * changing the task state if and only if any tasks are woken up.
*/
void complete(struct completion *x)
{
@@ -5332,6 +5511,9 @@ EXPORT_SYMBOL(complete);
* @x: holds the state of this particular completion
*
* This will wake up all threads waiting on this particular completion event.
+ *
+ * It may be assumed that this function implies a write memory barrier before
+ * changing the task state if and only if any tasks are woken up.
*/
void complete_all(struct completion *x)
{
@@ -6490,8 +6672,9 @@ void sched_show_task(struct task_struct *p)
#ifdef CONFIG_DEBUG_STACK_USAGE
free = stack_not_used(p);
#endif
- printk(KERN_CONT "%5lu %5d %6d\n", free,
- task_pid_nr(p), task_pid_nr(p->real_parent));
+ printk(KERN_CONT "%5lu %5d %6d 0x%08lx\n", free,
+ task_pid_nr(p), task_pid_nr(p->real_parent),
+ (unsigned long)task_thread_info(p)->flags);
show_stack(p, NULL);
}
@@ -7367,8 +7550,12 @@ static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level,
cpumask_or(groupmask, groupmask, sched_group_cpus(group));
cpulist_scnprintf(str, sizeof(str), sched_group_cpus(group));
- printk(KERN_CONT " %s (__cpu_power = %d)", str,
- group->__cpu_power);
+
+ printk(KERN_CONT " %s", str);
+ if (group->__cpu_power != SCHED_LOAD_SCALE) {
+ printk(KERN_CONT " (__cpu_power = %d)",
+ group->__cpu_power);
+ }
group = group->next;
} while (group != sd->groups);
@@ -7871,7 +8058,7 @@ static void init_numa_sched_groups_power(struct sched_group *group_head)
struct sched_domain *sd;
sd = &per_cpu(phys_domains, j).sd;
- if (j != cpumask_first(sched_group_cpus(sd->groups))) {
+ if (j != group_first_cpu(sd->groups)) {
/*
* Only add "power" once for each
* physical package.
@@ -7949,7 +8136,7 @@ static void init_sched_groups_power(int cpu, struct sched_domain *sd)
WARN_ON(!sd || !sd->groups);
- if (cpu != cpumask_first(sched_group_cpus(sd->groups)))
+ if (cpu != group_first_cpu(sd->groups))
return;
child = sd->child;
@@ -9051,6 +9238,7 @@ void __init sched_init(void)
#ifdef CONFIG_SMP
#ifdef CONFIG_NO_HZ
alloc_bootmem_cpumask_var(&nohz.cpu_mask);
+ alloc_bootmem_cpumask_var(&nohz.ilb_grp_nohz_mask);
#endif
alloc_bootmem_cpumask_var(&cpu_isolated_map);
#endif /* SMP */
@@ -9796,6 +9984,13 @@ static int sched_rt_global_constraints(void)
if (sysctl_sched_rt_period <= 0)
return -EINVAL;
+ /*
+ * There's always some RT tasks in the root group
+ * -- migration, kstopmachine etc..
+ */
+ if (sysctl_sched_rt_runtime == 0)
+ return -EBUSY;
+
spin_lock_irqsave(&def_rt_bandwidth.rt_runtime_lock, flags);
for_each_possible_cpu(i) {
struct rt_rq *rt_rq = &cpu_rq(i)->rt;
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index 3816f217f119..5f9650e8fe75 100644
--- a/kernel/sched_fair.c
+++ b/kernel/sched_fair.c
@@ -1487,17 +1487,10 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int sync)
find_matching_se(&se, &pse);
- while (se) {
- BUG_ON(!pse);
+ BUG_ON(!pse);
- if (wakeup_preempt_entity(se, pse) == 1) {
- resched_task(curr);
- break;
- }
-
- se = parent_entity(se);
- pse = parent_entity(pse);
- }
+ if (wakeup_preempt_entity(se, pse) == 1)
+ resched_task(curr);
}
static struct task_struct *pick_next_task_fair(struct rq *rq)
diff --git a/kernel/signal.c b/kernel/signal.c
index d8034737db4c..809a228019ad 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -27,7 +27,7 @@
#include <linux/freezer.h>
#include <linux/pid_namespace.h>
#include <linux/nsproxy.h>
-#include <trace/sched.h>
+#include <trace/events/sched.h>
#include <asm/param.h>
#include <asm/uaccess.h>
@@ -41,8 +41,6 @@
static struct kmem_cache *sigqueue_cachep;
-DEFINE_TRACE(sched_signal_send);
-
static void __user *sig_handler(struct task_struct *t, int sig)
{
return t->sighand->action[sig - 1].sa.sa_handler;
@@ -249,14 +247,19 @@ void flush_sigqueue(struct sigpending *queue)
/*
* Flush all pending signals for a task.
*/
+void __flush_signals(struct task_struct *t)
+{
+ clear_tsk_thread_flag(t, TIF_SIGPENDING);
+ flush_sigqueue(&t->pending);
+ flush_sigqueue(&t->signal->shared_pending);
+}
+
void flush_signals(struct task_struct *t)
{
unsigned long flags;
spin_lock_irqsave(&t->sighand->siglock, flags);
- clear_tsk_thread_flag(t, TIF_SIGPENDING);
- flush_sigqueue(&t->pending);
- flush_sigqueue(&t->signal->shared_pending);
+ __flush_signals(t);
spin_unlock_irqrestore(&t->sighand->siglock, flags);
}
@@ -2278,24 +2281,17 @@ SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)
return kill_something_info(sig, &info, pid);
}
-static int do_tkill(pid_t tgid, pid_t pid, int sig)
+static int
+do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info)
{
- int error;
- struct siginfo info;
struct task_struct *p;
unsigned long flags;
-
- error = -ESRCH;
- info.si_signo = sig;
- info.si_errno = 0;
- info.si_code = SI_TKILL;
- info.si_pid = task_tgid_vnr(current);
- info.si_uid = current_uid();
+ int error = -ESRCH;
rcu_read_lock();
p = find_task_by_vpid(pid);
if (p && (tgid <= 0 || task_tgid_vnr(p) == tgid)) {
- error = check_kill_permission(sig, &info, p);
+ error = check_kill_permission(sig, info, p);
/*
* The null signal is a permissions and process existence
* probe. No signal is actually delivered.
@@ -2305,7 +2301,7 @@ static int do_tkill(pid_t tgid, pid_t pid, int sig)
* signal is private anyway.
*/
if (!error && sig && lock_task_sighand(p, &flags)) {
- error = specific_send_sig_info(sig, &info, p);
+ error = specific_send_sig_info(sig, info, p);
unlock_task_sighand(p, &flags);
}
}
@@ -2314,6 +2310,19 @@ static int do_tkill(pid_t tgid, pid_t pid, int sig)
return error;
}
+static int do_tkill(pid_t tgid, pid_t pid, int sig)
+{
+ struct siginfo info;
+
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_code = SI_TKILL;
+ info.si_pid = task_tgid_vnr(current);
+ info.si_uid = current_uid();
+
+ return do_send_specific(tgid, pid, sig, &info);
+}
+
/**
* sys_tgkill - send signal to one specific thread
* @tgid: the thread group ID of the thread
@@ -2363,6 +2372,32 @@ SYSCALL_DEFINE3(rt_sigqueueinfo, pid_t, pid, int, sig,
return kill_proc_info(sig, &info, pid);
}
+long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info)
+{
+ /* This is only valid for single tasks */
+ if (pid <= 0 || tgid <= 0)
+ return -EINVAL;
+
+ /* Not even root can pretend to send signals from the kernel.
+ Nor can they impersonate a kill(), which adds source info. */
+ if (info->si_code >= 0)
+ return -EPERM;
+ info->si_signo = sig;
+
+ return do_send_specific(tgid, pid, sig, info);
+}
+
+SYSCALL_DEFINE4(rt_tgsigqueueinfo, pid_t, tgid, pid_t, pid, int, sig,
+ siginfo_t __user *, uinfo)
+{
+ siginfo_t info;
+
+ if (copy_from_user(&info, uinfo, sizeof(siginfo_t)))
+ return -EFAULT;
+
+ return do_rt_tgsigqueueinfo(tgid, pid, sig, &info);
+}
+
int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
{
struct task_struct *t = current;
diff --git a/kernel/slow-work.c b/kernel/slow-work.c
index cf2bc01186ef..b28d19135f43 100644
--- a/kernel/slow-work.c
+++ b/kernel/slow-work.c
@@ -609,14 +609,14 @@ void slow_work_unregister_user(void)
if (slow_work_user_count == 0) {
printk(KERN_NOTICE "Slow work thread pool: Shutting down\n");
slow_work_threads_should_exit = true;
+ del_timer_sync(&slow_work_cull_timer);
+ del_timer_sync(&slow_work_oom_timer);
wake_up_all(&slow_work_thread_wq);
wait_for_completion(&slow_work_last_thread_exited);
printk(KERN_NOTICE "Slow work thread pool:"
" Shut down complete\n");
}
- del_timer_sync(&slow_work_cull_timer);
-
mutex_unlock(&slow_work_user_lock);
}
EXPORT_SYMBOL(slow_work_unregister_user);
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 2fecefacdc5b..258885a543db 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -24,7 +24,9 @@
#include <linux/ftrace.h>
#include <linux/smp.h>
#include <linux/tick.h>
-#include <trace/irq.h>
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/irq.h>
#include <asm/irq.h>
/*
@@ -186,9 +188,6 @@ EXPORT_SYMBOL(local_bh_enable_ip);
*/
#define MAX_SOFTIRQ_RESTART 10
-DEFINE_TRACE(softirq_entry);
-DEFINE_TRACE(softirq_exit);
-
asmlinkage void __do_softirq(void)
{
struct softirq_action *h;
@@ -472,9 +471,9 @@ void tasklet_kill(struct tasklet_struct *t)
printk("Attempt to kill tasklet from interrupt\n");
while (test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) {
- do
+ do {
yield();
- while (test_bit(TASKLET_STATE_SCHED, &t->state));
+ } while (test_bit(TASKLET_STATE_SCHED, &t->state));
}
tasklet_unlock_wait(t);
clear_bit(TASKLET_STATE_SCHED, &t->state);
@@ -828,7 +827,7 @@ int __init __weak arch_early_irq_init(void)
return 0;
}
-int __weak arch_init_chip_data(struct irq_desc *desc, int cpu)
+int __weak arch_init_chip_data(struct irq_desc *desc, int node)
{
return 0;
}
diff --git a/kernel/sys.c b/kernel/sys.c
index 51dbb55604e8..e7998cf31498 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -360,6 +360,7 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
void __user *, arg)
{
char buffer[256];
+ int ret = 0;
/* We only trust the superuser with rebooting the system. */
if (!capable(CAP_SYS_BOOT))
@@ -397,7 +398,7 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
kernel_halt();
unlock_kernel();
do_exit(0);
- break;
+ panic("cannot halt");
case LINUX_REBOOT_CMD_POWER_OFF:
kernel_power_off();
@@ -417,29 +418,22 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
#ifdef CONFIG_KEXEC
case LINUX_REBOOT_CMD_KEXEC:
- {
- int ret;
- ret = kernel_kexec();
- unlock_kernel();
- return ret;
- }
+ ret = kernel_kexec();
+ break;
#endif
#ifdef CONFIG_HIBERNATION
case LINUX_REBOOT_CMD_SW_SUSPEND:
- {
- int ret = hibernate();
- unlock_kernel();
- return ret;
- }
+ ret = hibernate();
+ break;
#endif
default:
- unlock_kernel();
- return -EINVAL;
+ ret = -EINVAL;
+ break;
}
unlock_kernel();
- return 0;
+ return ret;
}
static void deferred_cad(struct work_struct *dummy)
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 4286b62b34a0..98ecf35d5bf2 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -103,6 +103,9 @@ static unsigned long one_ul = 1;
static int one_hundred = 100;
static int one_thousand = 1000;
+/* this is needed for the proc_doulongvec_minmax of vm_dirty_bytes */
+static unsigned long dirty_bytes_min = 2 * PAGE_SIZE;
+
/* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
static int maxolduid = 65535;
static int minolduid;
@@ -112,6 +115,7 @@ static int ngroups_max = NGROUPS_MAX;
#ifdef CONFIG_MODULES
extern char modprobe_path[];
+extern int modules_disabled;
#endif
#ifdef CONFIG_CHR_DEV_SG
extern int sg_big_buff;
@@ -532,6 +536,17 @@ static struct ctl_table kern_table[] = {
.proc_handler = &proc_dostring,
.strategy = &sysctl_string,
},
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "modules_disabled",
+ .data = &modules_disabled,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ /* only handle a transition from default "0" to "1" */
+ .proc_handler = &proc_dointvec_minmax,
+ .extra1 = &one,
+ .extra2 = &one,
+ },
#endif
#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
{
@@ -902,16 +917,6 @@ static struct ctl_table kern_table[] = {
.proc_handler = &proc_dointvec,
},
#endif
-#ifdef CONFIG_UNEVICTABLE_LRU
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "scan_unevictable_pages",
- .data = &scan_unevictable_pages,
- .maxlen = sizeof(scan_unevictable_pages),
- .mode = 0644,
- .proc_handler = &scan_unevictable_handler,
- },
-#endif
#ifdef CONFIG_SLOW_WORK
{
.ctl_name = CTL_UNNUMBERED,
@@ -1016,7 +1021,7 @@ static struct ctl_table vm_table[] = {
.mode = 0644,
.proc_handler = &dirty_bytes_handler,
.strategy = &sysctl_intvec,
- .extra1 = &one_ul,
+ .extra1 = &dirty_bytes_min,
},
{
.procname = "dirty_writeback_centisecs",
@@ -1302,6 +1307,16 @@ static struct ctl_table vm_table[] = {
.extra2 = &one,
},
#endif
+#ifdef CONFIG_UNEVICTABLE_LRU
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "scan_unevictable_pages",
+ .data = &scan_unevictable_pages,
+ .maxlen = sizeof(scan_unevictable_pages),
+ .mode = 0644,
+ .proc_handler = &scan_unevictable_handler,
+ },
+#endif
/*
* NOTE: do not add new entries to this table unless you have read
* Documentation/sysctl/ctl_unnumbered.txt
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
index d13be216a790..3948fa644a2d 100644
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -54,6 +54,7 @@ unsigned long clockevent_delta2ns(unsigned long latch,
return (unsigned long) clc;
}
+EXPORT_SYMBOL_GPL(clockevent_delta2ns);
/**
* clockevents_set_mode - set the operating mode of a clock event device
@@ -187,6 +188,7 @@ void clockevents_register_device(struct clock_event_device *dev)
spin_unlock(&clockevents_lock);
}
+EXPORT_SYMBOL_GPL(clockevents_register_device);
/*
* Noop handler when we shut down an event device
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index c46c931a7fe7..80189f6f1c5a 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -181,12 +181,12 @@ static void clocksource_watchdog(unsigned long data)
resumed = test_and_clear_bit(0, &watchdog_resumed);
- wdnow = watchdog->read();
+ wdnow = watchdog->read(watchdog);
wd_nsec = cyc2ns(watchdog, (wdnow - watchdog_last) & watchdog->mask);
watchdog_last = wdnow;
list_for_each_entry_safe(cs, tmp, &watchdog_list, wd_list) {
- csnow = cs->read();
+ csnow = cs->read(cs);
if (unlikely(resumed)) {
cs->wd_last = csnow;
@@ -247,7 +247,7 @@ static void clocksource_check_watchdog(struct clocksource *cs)
list_add(&cs->wd_list, &watchdog_list);
if (!started && watchdog) {
- watchdog_last = watchdog->read();
+ watchdog_last = watchdog->read(watchdog);
watchdog_timer.expires = jiffies + WATCHDOG_INTERVAL;
add_timer_on(&watchdog_timer,
cpumask_first(cpu_online_mask));
@@ -268,7 +268,7 @@ static void clocksource_check_watchdog(struct clocksource *cs)
cse->flags &= ~CLOCK_SOURCE_WATCHDOG;
/* Start if list is not empty */
if (!list_empty(&watchdog_list)) {
- watchdog_last = watchdog->read();
+ watchdog_last = watchdog->read(watchdog);
watchdog_timer.expires =
jiffies + WATCHDOG_INTERVAL;
add_timer_on(&watchdog_timer,
@@ -402,9 +402,6 @@ int clocksource_register(struct clocksource *c)
unsigned long flags;
int ret;
- /* save mult_orig on registration */
- c->mult_orig = c->mult;
-
spin_lock_irqsave(&clocksource_lock, flags);
ret = clocksource_enqueue(c);
if (!ret)
diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c
index 06f197560f3b..c3f6c30816e3 100644
--- a/kernel/time/jiffies.c
+++ b/kernel/time/jiffies.c
@@ -50,7 +50,7 @@
*/
#define JIFFIES_SHIFT 8
-static cycle_t jiffies_read(void)
+static cycle_t jiffies_read(struct clocksource *cs)
{
return (cycle_t) jiffies;
}
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index 118a3b3b3f9a..877dbedc3118 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -27,7 +27,7 @@
* timer stops in C3 state.
*/
-struct tick_device tick_broadcast_device;
+static struct tick_device tick_broadcast_device;
/* FIXME: Use cpumask_var_t. */
static DECLARE_BITMAP(tick_broadcast_mask, NR_CPUS);
static DECLARE_BITMAP(tmpmask, NR_CPUS);
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index 21a5ca849514..83c4417b6a3c 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -93,7 +93,17 @@ void tick_handle_periodic(struct clock_event_device *dev)
for (;;) {
if (!clockevents_program_event(dev, next, ktime_get()))
return;
- tick_periodic(cpu);
+ /*
+ * Have to be careful here. If we're in oneshot mode,
+ * before we call tick_periodic() in a loop, we need
+ * to be sure we're using a real hardware clocksource.
+ * Otherwise we could get trapped in an infinite
+ * loop, as the tick_periodic() increments jiffies,
+ * when then will increment time, posibly causing
+ * the loop to trigger again and again.
+ */
+ if (timekeeping_valid_for_hres())
+ tick_periodic(cpu);
next = ktime_add(next, tick_period);
}
}
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 900f1b6598d1..e97c50f8458b 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -77,6 +77,10 @@ static void clocksource_forward_now(void)
clock->cycle_last = cycle_now;
nsec = cyc2ns(clock, cycle_delta);
+
+ /* If arch requires, add in gettimeoffset() */
+ nsec += arch_gettimeoffset();
+
timespec_add_ns(&xtime, nsec);
nsec = ((s64)cycle_delta * clock->mult_orig) >> clock->shift;
@@ -111,6 +115,9 @@ void getnstimeofday(struct timespec *ts)
/* convert to nanoseconds: */
nsecs = cyc2ns(clock, cycle_delta);
+ /* If arch requires, add in gettimeoffset() */
+ nsecs += arch_gettimeoffset();
+
} while (read_seqretry(&xtime_lock, seq));
timespec_add_ns(ts, nsecs);
@@ -182,7 +189,7 @@ EXPORT_SYMBOL(do_settimeofday);
*/
static void change_clocksource(void)
{
- struct clocksource *new;
+ struct clocksource *new, *old;
new = clocksource_get_next();
@@ -191,11 +198,16 @@ static void change_clocksource(void)
clocksource_forward_now();
- new->raw_time = clock->raw_time;
+ if (clocksource_enable(new))
+ return;
+ new->raw_time = clock->raw_time;
+ old = clock;
clock = new;
+ clocksource_disable(old);
+
clock->cycle_last = 0;
- clock->cycle_last = clocksource_read(new);
+ clock->cycle_last = clocksource_read(clock);
clock->error = 0;
clock->xtime_nsec = 0;
clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
@@ -292,6 +304,7 @@ void __init timekeeping_init(void)
ntp_init();
clock = clocksource_get_next();
+ clocksource_enable(clock);
clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
clock->cycle_last = clocksource_read(clock);
diff --git a/kernel/timer.c b/kernel/timer.c
index cffffad01c31..5c1e84beaf4a 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -1015,6 +1015,9 @@ cascade:
index = slot = timer_jiffies & TVN_MASK;
do {
list_for_each_entry(nte, varp->vec + slot, entry) {
+ if (tbase_get_deferrable(nte->base))
+ continue;
+
found = 1;
if (time_before(nte->expires, expires))
expires = nte->expires;
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index 417d1985e299..50f62a296e1d 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -48,6 +48,9 @@ config FTRACE_NMI_ENTER
depends on HAVE_FTRACE_NMI_ENTER
default y
+config EVENT_TRACING
+ bool
+
config TRACING
bool
select DEBUG_FS
@@ -56,6 +59,7 @@ config TRACING
select TRACEPOINTS
select NOP_TRACER
select BINARY_PRINTF
+ select EVENT_TRACING
#
# Minimum requirements an architecture has to meet for us to
@@ -73,7 +77,12 @@ config TRACING_SUPPORT
if TRACING_SUPPORT
-menu "Tracers"
+menuconfig FTRACE
+ bool "Tracers"
+ help
+ Enable the kernel tracing infrastructure.
+
+if FTRACE
config FUNCTION_TRACER
bool "Kernel Function Tracer"
@@ -104,6 +113,7 @@ config FUNCTION_GRAPH_TRACER
the return value. This is done by setting the current return
address on the current task structure into a stack of calls.
+
config IRQSOFF_TRACER
bool "Interrupts-off Latency Tracer"
default n
@@ -173,7 +183,7 @@ config CONTEXT_SWITCH_TRACER
This tracer gets called from the context switch and records
all switching of tasks.
-config EVENT_TRACER
+config ENABLE_EVENT_TRACING
bool "Trace various events in the kernel"
select TRACING
help
@@ -181,6 +191,10 @@ config EVENT_TRACER
allowing the user to pick and choose which trace point they
want to trace.
+ Note, all tracers enable event tracing. This option is
+ only a convenience to enable event tracing when no other
+ tracers are selected.
+
config FTRACE_SYSCALLS
bool "Trace syscalls"
depends on HAVE_FTRACE_SYSCALLS
@@ -207,8 +221,36 @@ config BOOT_TRACER
to enable this on bootup.
config TRACE_BRANCH_PROFILING
- bool "Trace likely/unlikely profiler"
+ bool
select TRACING
+
+choice
+ prompt "Branch Profiling"
+ default BRANCH_PROFILE_NONE
+ help
+ The branch profiling is a software profiler. It will add hooks
+ into the C conditionals to test which path a branch takes.
+
+ The likely/unlikely profiler only looks at the conditions that
+ are annotated with a likely or unlikely macro.
+
+ The "all branch" profiler will profile every if statement in the
+ kernel. This profiler will also enable the likely/unlikely
+ profiler as well.
+
+ Either of the above profilers add a bit of overhead to the system.
+ If unsure choose "No branch profiling".
+
+config BRANCH_PROFILE_NONE
+ bool "No branch profiling"
+ help
+ No branch profiling. Branch profiling adds a bit of overhead.
+ Only enable it if you want to analyse the branching behavior.
+ Otherwise keep it disabled.
+
+config PROFILE_ANNOTATED_BRANCHES
+ bool "Trace likely/unlikely profiler"
+ select TRACE_BRANCH_PROFILING
help
This tracer profiles all the the likely and unlikely macros
in the kernel. It will display the results in:
@@ -218,11 +260,9 @@ config TRACE_BRANCH_PROFILING
Note: this will add a significant overhead, only turn this
on if you need to profile the system's use of these macros.
- Say N if unsure.
-
config PROFILE_ALL_BRANCHES
bool "Profile all if conditionals"
- depends on TRACE_BRANCH_PROFILING
+ select TRACE_BRANCH_PROFILING
help
This tracer profiles all branch conditions. Every if ()
taken in the kernel is recorded whether it hit or miss.
@@ -230,11 +270,12 @@ config PROFILE_ALL_BRANCHES
/debugfs/tracing/profile_branch
+ This option also enables the likely/unlikely profiler.
+
This configuration, when enabled, will impose a great overhead
on the system. This should only be enabled when the system
is to be analyzed
-
- Say N if unsure.
+endchoice
config TRACING_BRANCHES
bool
@@ -375,6 +416,20 @@ config DYNAMIC_FTRACE
were made. If so, it runs stop_machine (stops all CPUS)
and modifies the code to jump over the call to ftrace.
+config FUNCTION_PROFILER
+ bool "Kernel function profiler"
+ depends on FUNCTION_TRACER
+ default n
+ help
+ This option enables the kernel function profiler. A file is created
+ in debugfs called function_profile_enabled which defaults to zero.
+ When a 1 is echoed into this file profiling begins, and when a
+ zero is entered, profiling stops. A file in the trace_stats
+ directory called functions, that show the list of functions that
+ have been hit and their counters.
+
+ If in doubt, say N
+
config FTRACE_MCOUNT_RECORD
def_bool y
depends on DYNAMIC_FTRACE
@@ -416,7 +471,23 @@ config MMIOTRACE_TEST
Say N, unless you absolutely know what you are doing.
-endmenu
+config RING_BUFFER_BENCHMARK
+ tristate "Ring buffer benchmark stress tester"
+ depends on RING_BUFFER
+ help
+ This option creates a test to stress the ring buffer and bench mark it.
+ It creates its own ring buffer such that it will not interfer with
+ any other users of the ring buffer (such as ftrace). It then creates
+ a producer and consumer that will run for 10 seconds and sleep for
+ 10 seconds. Each interval it will print out the number of events
+ it recorded and give a rough estimate of how long each iteration took.
+
+ It does not disable interrupts or raise its priority, so it may be
+ affected by processes that are running.
+
+ If unsure, say N
+
+endif # FTRACE
endif # TRACING_SUPPORT
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index 2630f5121ec1..06b85850fab4 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -15,11 +15,17 @@ ifdef CONFIG_TRACING_BRANCHES
KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
endif
+#
+# Make the trace clocks available generally: it's infrastructure
+# relied on by ptrace for example:
+#
+obj-y += trace_clock.o
+
obj-$(CONFIG_FUNCTION_TRACER) += libftrace.o
obj-$(CONFIG_RING_BUFFER) += ring_buffer.o
+obj-$(CONFIG_RING_BUFFER_BENCHMARK) += ring_buffer_benchmark.o
obj-$(CONFIG_TRACING) += trace.o
-obj-$(CONFIG_TRACING) += trace_clock.o
obj-$(CONFIG_TRACING) += trace_output.o
obj-$(CONFIG_TRACING) += trace_stat.o
obj-$(CONFIG_TRACING) += trace_printk.o
@@ -40,11 +46,10 @@ obj-$(CONFIG_POWER_TRACER) += trace_power.o
obj-$(CONFIG_KMEMTRACE) += kmemtrace.o
obj-$(CONFIG_WORKQUEUE_TRACER) += trace_workqueue.o
obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o
-obj-$(CONFIG_EVENT_TRACER) += trace_events.o
-obj-$(CONFIG_EVENT_TRACER) += events.o
-obj-$(CONFIG_EVENT_TRACER) += trace_export.o
+obj-$(CONFIG_EVENT_TRACING) += trace_events.o
+obj-$(CONFIG_EVENT_TRACING) += trace_export.o
obj-$(CONFIG_FTRACE_SYSCALLS) += trace_syscalls.o
obj-$(CONFIG_EVENT_PROFILE) += trace_event_profile.o
-obj-$(CONFIG_EVENT_TRACER) += trace_events_filter.o
+obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o
libftrace-y := ftrace.o
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c
index 921ef5d1f0ba..e099f8cc1d1c 100644
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -147,7 +147,7 @@ static int act_log_check(struct blk_trace *bt, u32 what, sector_t sector,
{
if (((bt->act_mask << BLK_TC_SHIFT) & what) == 0)
return 1;
- if (sector < bt->start_lba || sector > bt->end_lba)
+ if (sector && (sector < bt->start_lba || sector > bt->end_lba))
return 1;
if (bt->pid && pid != bt->pid)
return 1;
@@ -192,7 +192,7 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
what |= MASK_TC_BIT(rw, DISCARD);
pid = tsk->pid;
- if (unlikely(act_log_check(bt, what, sector, pid)))
+ if (act_log_check(bt, what, sector, pid))
return;
cpu = raw_smp_processor_id();
@@ -403,11 +403,29 @@ static struct rchan_callbacks blk_relay_callbacks = {
.remove_buf_file = blk_remove_buf_file_callback,
};
+static void blk_trace_setup_lba(struct blk_trace *bt,
+ struct block_device *bdev)
+{
+ struct hd_struct *part = NULL;
+
+ if (bdev)
+ part = bdev->bd_part;
+
+ if (part) {
+ bt->start_lba = part->start_sect;
+ bt->end_lba = part->start_sect + part->nr_sects;
+ } else {
+ bt->start_lba = 0;
+ bt->end_lba = -1ULL;
+ }
+}
+
/*
* Setup everything required to start tracing
*/
int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
- struct blk_user_trace_setup *buts)
+ struct block_device *bdev,
+ struct blk_user_trace_setup *buts)
{
struct blk_trace *old_bt, *bt = NULL;
struct dentry *dir = NULL;
@@ -480,10 +498,13 @@ int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
if (!bt->act_mask)
bt->act_mask = (u16) -1;
- bt->start_lba = buts->start_lba;
- bt->end_lba = buts->end_lba;
- if (!bt->end_lba)
- bt->end_lba = -1ULL;
+ blk_trace_setup_lba(bt, bdev);
+
+ /* overwrite with user settings */
+ if (buts->start_lba)
+ bt->start_lba = buts->start_lba;
+ if (buts->end_lba)
+ bt->end_lba = buts->end_lba;
bt->pid = buts->pid;
bt->trace_state = Blktrace_setup;
@@ -505,6 +526,7 @@ err:
}
int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
+ struct block_device *bdev,
char __user *arg)
{
struct blk_user_trace_setup buts;
@@ -514,7 +536,7 @@ int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
if (ret)
return -EFAULT;
- ret = do_blk_trace_setup(q, name, dev, &buts);
+ ret = do_blk_trace_setup(q, name, dev, bdev, &buts);
if (ret)
return ret;
@@ -582,7 +604,7 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
switch (cmd) {
case BLKTRACESETUP:
bdevname(bdev, b);
- ret = blk_trace_setup(q, b, bdev->bd_dev, arg);
+ ret = blk_trace_setup(q, b, bdev->bd_dev, bdev, arg);
break;
case BLKTRACESTART:
start = 1;
@@ -809,7 +831,6 @@ static void blk_add_trace_split(struct request_queue *q, struct bio *bio,
* @bio: the source bio
* @dev: target device
* @from: source sector
- * @to: target sector
*
* Description:
* Device mapper or raid target sometimes need to split a bio because
@@ -817,7 +838,7 @@ static void blk_add_trace_split(struct request_queue *q, struct bio *bio,
*
**/
static void blk_add_trace_remap(struct request_queue *q, struct bio *bio,
- dev_t dev, sector_t from, sector_t to)
+ dev_t dev, sector_t from)
{
struct blk_trace *bt = q->blk_trace;
struct blk_io_trace_remap r;
@@ -825,12 +846,13 @@ static void blk_add_trace_remap(struct request_queue *q, struct bio *bio,
if (likely(!bt))
return;
- r.device = cpu_to_be32(dev);
- r.device_from = cpu_to_be32(bio->bi_bdev->bd_dev);
- r.sector = cpu_to_be64(to);
+ r.device_from = cpu_to_be32(dev);
+ r.device_to = cpu_to_be32(bio->bi_bdev->bd_dev);
+ r.sector_from = cpu_to_be64(from);
- __blk_add_trace(bt, from, bio->bi_size, bio->bi_rw, BLK_TA_REMAP,
- !bio_flagged(bio, BIO_UPTODATE), sizeof(r), &r);
+ __blk_add_trace(bt, bio->bi_sector, bio->bi_size, bio->bi_rw,
+ BLK_TA_REMAP, !bio_flagged(bio, BIO_UPTODATE),
+ sizeof(r), &r);
}
/**
@@ -971,6 +993,16 @@ static inline const void *pdu_start(const struct trace_entry *ent)
return te_blk_io_trace(ent) + 1;
}
+static inline u32 t_action(const struct trace_entry *ent)
+{
+ return te_blk_io_trace(ent)->action;
+}
+
+static inline u32 t_bytes(const struct trace_entry *ent)
+{
+ return te_blk_io_trace(ent)->bytes;
+}
+
static inline u32 t_sec(const struct trace_entry *ent)
{
return te_blk_io_trace(ent)->bytes >> 9;
@@ -996,11 +1028,11 @@ static void get_pdu_remap(const struct trace_entry *ent,
struct blk_io_trace_remap *r)
{
const struct blk_io_trace_remap *__r = pdu_start(ent);
- __u64 sector = __r->sector;
+ __u64 sector_from = __r->sector_from;
- r->device = be32_to_cpu(__r->device);
r->device_from = be32_to_cpu(__r->device_from);
- r->sector = be64_to_cpu(sector);
+ r->device_to = be32_to_cpu(__r->device_to);
+ r->sector_from = be64_to_cpu(sector_from);
}
typedef int (blk_log_action_t) (struct trace_iterator *iter, const char *act);
@@ -1031,36 +1063,98 @@ static int blk_log_action(struct trace_iterator *iter, const char *act)
MAJOR(t->device), MINOR(t->device), act, rwbs);
}
+static int blk_log_dump_pdu(struct trace_seq *s, const struct trace_entry *ent)
+{
+ const char *pdu_buf;
+ int pdu_len;
+ int i, end, ret;
+
+ pdu_buf = pdu_start(ent);
+ pdu_len = te_blk_io_trace(ent)->pdu_len;
+
+ if (!pdu_len)
+ return 1;
+
+ /* find the last zero that needs to be printed */
+ for (end = pdu_len - 1; end >= 0; end--)
+ if (pdu_buf[end])
+ break;
+ end++;
+
+ if (!trace_seq_putc(s, '('))
+ return 0;
+
+ for (i = 0; i < pdu_len; i++) {
+
+ ret = trace_seq_printf(s, "%s%02x",
+ i == 0 ? "" : " ", pdu_buf[i]);
+ if (!ret)
+ return ret;
+
+ /*
+ * stop when the rest is just zeroes and indicate so
+ * with a ".." appended
+ */
+ if (i == end && end != pdu_len - 1)
+ return trace_seq_puts(s, " ..) ");
+ }
+
+ return trace_seq_puts(s, ") ");
+}
+
static int blk_log_generic(struct trace_seq *s, const struct trace_entry *ent)
{
char cmd[TASK_COMM_LEN];
trace_find_cmdline(ent->pid, cmd);
- if (t_sec(ent))
- return trace_seq_printf(s, "%llu + %u [%s]\n",
- t_sector(ent), t_sec(ent), cmd);
- return trace_seq_printf(s, "[%s]\n", cmd);
+ if (t_action(ent) & BLK_TC_ACT(BLK_TC_PC)) {
+ int ret;
+
+ ret = trace_seq_printf(s, "%u ", t_bytes(ent));
+ if (!ret)
+ return 0;
+ ret = blk_log_dump_pdu(s, ent);
+ if (!ret)
+ return 0;
+ return trace_seq_printf(s, "[%s]\n", cmd);
+ } else {
+ if (t_sec(ent))
+ return trace_seq_printf(s, "%llu + %u [%s]\n",
+ t_sector(ent), t_sec(ent), cmd);
+ return trace_seq_printf(s, "[%s]\n", cmd);
+ }
}
static int blk_log_with_error(struct trace_seq *s,
const struct trace_entry *ent)
{
- if (t_sec(ent))
- return trace_seq_printf(s, "%llu + %u [%d]\n", t_sector(ent),
- t_sec(ent), t_error(ent));
- return trace_seq_printf(s, "%llu [%d]\n", t_sector(ent), t_error(ent));
+ if (t_action(ent) & BLK_TC_ACT(BLK_TC_PC)) {
+ int ret;
+
+ ret = blk_log_dump_pdu(s, ent);
+ if (ret)
+ return trace_seq_printf(s, "[%d]\n", t_error(ent));
+ return 0;
+ } else {
+ if (t_sec(ent))
+ return trace_seq_printf(s, "%llu + %u [%d]\n",
+ t_sector(ent),
+ t_sec(ent), t_error(ent));
+ return trace_seq_printf(s, "%llu [%d]\n",
+ t_sector(ent), t_error(ent));
+ }
}
static int blk_log_remap(struct trace_seq *s, const struct trace_entry *ent)
{
- struct blk_io_trace_remap r = { .device = 0, };
+ struct blk_io_trace_remap r = { .device_from = 0, };
get_pdu_remap(ent, &r);
return trace_seq_printf(s, "%llu + %u <- (%d,%d) %llu\n",
- t_sector(ent),
- t_sec(ent), MAJOR(r.device), MINOR(r.device),
- (unsigned long long)r.sector);
+ t_sector(ent), t_sec(ent),
+ MAJOR(r.device_from), MINOR(r.device_from),
+ (unsigned long long)r.sector_from);
}
static int blk_log_plug(struct trace_seq *s, const struct trace_entry *ent)
@@ -1117,7 +1211,6 @@ static void blk_tracer_print_header(struct seq_file *m)
static void blk_tracer_start(struct trace_array *tr)
{
blk_tracer_enabled = true;
- trace_flags &= ~TRACE_ITER_CONTEXT_INFO;
}
static int blk_tracer_init(struct trace_array *tr)
@@ -1130,7 +1223,6 @@ static int blk_tracer_init(struct trace_array *tr)
static void blk_tracer_stop(struct trace_array *tr)
{
blk_tracer_enabled = false;
- trace_flags |= TRACE_ITER_CONTEXT_INFO;
}
static void blk_tracer_reset(struct trace_array *tr)
@@ -1182,7 +1274,7 @@ static enum print_line_t print_one_line(struct trace_iterator *iter,
}
if (unlikely(what == 0 || what >= ARRAY_SIZE(what2act)))
- ret = trace_seq_printf(s, "Bad pc action %x\n", what);
+ ret = trace_seq_printf(s, "Unknown action %x\n", what);
else {
ret = log_action(iter, what2act[what].act[long_act]);
if (ret)
@@ -1195,9 +1287,6 @@ out:
static enum print_line_t blk_trace_event_print(struct trace_iterator *iter,
int flags)
{
- if (!trace_print_context(iter))
- return TRACE_TYPE_PARTIAL_LINE;
-
return print_one_line(iter, false);
}
@@ -1232,6 +1321,18 @@ static enum print_line_t blk_tracer_print_line(struct trace_iterator *iter)
return print_one_line(iter, true);
}
+static int blk_tracer_set_flag(u32 old_flags, u32 bit, int set)
+{
+ /* don't output context-info for blk_classic output */
+ if (bit == TRACE_BLK_OPT_CLASSIC) {
+ if (set)
+ trace_flags &= ~TRACE_ITER_CONTEXT_INFO;
+ else
+ trace_flags |= TRACE_ITER_CONTEXT_INFO;
+ }
+ return 0;
+}
+
static struct tracer blk_tracer __read_mostly = {
.name = "blk",
.init = blk_tracer_init,
@@ -1241,6 +1342,7 @@ static struct tracer blk_tracer __read_mostly = {
.print_header = blk_tracer_print_header,
.print_line = blk_tracer_print_line,
.flags = &blk_tracer_flags,
+ .set_flag = blk_tracer_set_flag,
};
static struct trace_event trace_blk_event = {
@@ -1285,7 +1387,8 @@ static int blk_trace_remove_queue(struct request_queue *q)
/*
* Setup everything required to start tracing
*/
-static int blk_trace_setup_queue(struct request_queue *q, dev_t dev)
+static int blk_trace_setup_queue(struct request_queue *q,
+ struct block_device *bdev)
{
struct blk_trace *old_bt, *bt = NULL;
int ret = -ENOMEM;
@@ -1298,9 +1401,10 @@ static int blk_trace_setup_queue(struct request_queue *q, dev_t dev)
if (!bt->msg_data)
goto free_bt;
- bt->dev = dev;
+ bt->dev = bdev->bd_dev;
bt->act_mask = (u16)-1;
- bt->end_lba = -1ULL;
+
+ blk_trace_setup_lba(bt, bdev);
old_bt = xchg(&q->blk_trace, bt);
if (old_bt != NULL) {
@@ -1517,7 +1621,7 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
if (attr == &dev_attr_enable) {
if (value)
- ret = blk_trace_setup_queue(q, bdev->bd_dev);
+ ret = blk_trace_setup_queue(q, bdev);
else
ret = blk_trace_remove_queue(q);
goto out_unlock_bdev;
@@ -1525,7 +1629,7 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
ret = 0;
if (q->blk_trace == NULL)
- ret = blk_trace_setup_queue(q, bdev->bd_dev);
+ ret = blk_trace_setup_queue(q, bdev);
if (ret == 0) {
if (attr == &dev_attr_act_mask)
@@ -1548,3 +1652,8 @@ out:
return ret ? ret : count;
}
+int blk_trace_init_sysfs(struct device *dev)
+{
+ return sysfs_create_group(&dev->kobj, &blk_trace_attr_group);
+}
+
diff --git a/kernel/trace/events.c b/kernel/trace/events.c
deleted file mode 100644
index 246f2aa6dc46..000000000000
--- a/kernel/trace/events.c
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * This is the place to register all trace points as events.
- */
-
-#include <linux/stringify.h>
-
-#include <trace/trace_events.h>
-
-#include "trace_output.h"
-
-#include "trace_events_stage_1.h"
-#include "trace_events_stage_2.h"
-#include "trace_events_stage_3.h"
-
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index f1ed080406c3..5b606f45b6c4 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -29,11 +29,12 @@
#include <linux/list.h>
#include <linux/hash.h>
-#include <trace/sched.h>
+#include <trace/events/sched.h>
#include <asm/ftrace.h>
-#include "trace.h"
+#include "trace_output.h"
+#include "trace_stat.h"
#define FTRACE_WARN_ON(cond) \
do { \
@@ -68,7 +69,7 @@ static DEFINE_MUTEX(ftrace_lock);
static struct ftrace_ops ftrace_list_end __read_mostly =
{
- .func = ftrace_stub,
+ .func = ftrace_stub,
};
static struct ftrace_ops *ftrace_list __read_mostly = &ftrace_list_end;
@@ -240,6 +241,576 @@ static void ftrace_update_pid_func(void)
#endif
}
+#ifdef CONFIG_FUNCTION_PROFILER
+struct ftrace_profile {
+ struct hlist_node node;
+ unsigned long ip;
+ unsigned long counter;
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ unsigned long long time;
+#endif
+};
+
+struct ftrace_profile_page {
+ struct ftrace_profile_page *next;
+ unsigned long index;
+ struct ftrace_profile records[];
+};
+
+struct ftrace_profile_stat {
+ atomic_t disabled;
+ struct hlist_head *hash;
+ struct ftrace_profile_page *pages;
+ struct ftrace_profile_page *start;
+ struct tracer_stat stat;
+};
+
+#define PROFILE_RECORDS_SIZE \
+ (PAGE_SIZE - offsetof(struct ftrace_profile_page, records))
+
+#define PROFILES_PER_PAGE \
+ (PROFILE_RECORDS_SIZE / sizeof(struct ftrace_profile))
+
+static int ftrace_profile_bits __read_mostly;
+static int ftrace_profile_enabled __read_mostly;
+
+/* ftrace_profile_lock - synchronize the enable and disable of the profiler */
+static DEFINE_MUTEX(ftrace_profile_lock);
+
+static DEFINE_PER_CPU(struct ftrace_profile_stat, ftrace_profile_stats);
+
+#define FTRACE_PROFILE_HASH_SIZE 1024 /* must be power of 2 */
+
+static void *
+function_stat_next(void *v, int idx)
+{
+ struct ftrace_profile *rec = v;
+ struct ftrace_profile_page *pg;
+
+ pg = (struct ftrace_profile_page *)((unsigned long)rec & PAGE_MASK);
+
+ again:
+ rec++;
+ if ((void *)rec >= (void *)&pg->records[pg->index]) {
+ pg = pg->next;
+ if (!pg)
+ return NULL;
+ rec = &pg->records[0];
+ if (!rec->counter)
+ goto again;
+ }
+
+ return rec;
+}
+
+static void *function_stat_start(struct tracer_stat *trace)
+{
+ struct ftrace_profile_stat *stat =
+ container_of(trace, struct ftrace_profile_stat, stat);
+
+ if (!stat || !stat->start)
+ return NULL;
+
+ return function_stat_next(&stat->start->records[0], 0);
+}
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/* function graph compares on total time */
+static int function_stat_cmp(void *p1, void *p2)
+{
+ struct ftrace_profile *a = p1;
+ struct ftrace_profile *b = p2;
+
+ if (a->time < b->time)
+ return -1;
+ if (a->time > b->time)
+ return 1;
+ else
+ return 0;
+}
+#else
+/* not function graph compares against hits */
+static int function_stat_cmp(void *p1, void *p2)
+{
+ struct ftrace_profile *a = p1;
+ struct ftrace_profile *b = p2;
+
+ if (a->counter < b->counter)
+ return -1;
+ if (a->counter > b->counter)
+ return 1;
+ else
+ return 0;
+}
+#endif
+
+static int function_stat_headers(struct seq_file *m)
+{
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ seq_printf(m, " Function "
+ "Hit Time Avg\n"
+ " -------- "
+ "--- ---- ---\n");
+#else
+ seq_printf(m, " Function Hit\n"
+ " -------- ---\n");
+#endif
+ return 0;
+}
+
+static int function_stat_show(struct seq_file *m, void *v)
+{
+ struct ftrace_profile *rec = v;
+ char str[KSYM_SYMBOL_LEN];
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ static DEFINE_MUTEX(mutex);
+ static struct trace_seq s;
+ unsigned long long avg;
+#endif
+
+ kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
+ seq_printf(m, " %-30.30s %10lu", str, rec->counter);
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ seq_printf(m, " ");
+ avg = rec->time;
+ do_div(avg, rec->counter);
+
+ mutex_lock(&mutex);
+ trace_seq_init(&s);
+ trace_print_graph_duration(rec->time, &s);
+ trace_seq_puts(&s, " ");
+ trace_print_graph_duration(avg, &s);
+ trace_print_seq(m, &s);
+ mutex_unlock(&mutex);
+#endif
+ seq_putc(m, '\n');
+
+ return 0;
+}
+
+static void ftrace_profile_reset(struct ftrace_profile_stat *stat)
+{
+ struct ftrace_profile_page *pg;
+
+ pg = stat->pages = stat->start;
+
+ while (pg) {
+ memset(pg->records, 0, PROFILE_RECORDS_SIZE);
+ pg->index = 0;
+ pg = pg->next;
+ }
+
+ memset(stat->hash, 0,
+ FTRACE_PROFILE_HASH_SIZE * sizeof(struct hlist_head));
+}
+
+int ftrace_profile_pages_init(struct ftrace_profile_stat *stat)
+{
+ struct ftrace_profile_page *pg;
+ int functions;
+ int pages;
+ int i;
+
+ /* If we already allocated, do nothing */
+ if (stat->pages)
+ return 0;
+
+ stat->pages = (void *)get_zeroed_page(GFP_KERNEL);
+ if (!stat->pages)
+ return -ENOMEM;
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+ functions = ftrace_update_tot_cnt;
+#else
+ /*
+ * We do not know the number of functions that exist because
+ * dynamic tracing is what counts them. With past experience
+ * we have around 20K functions. That should be more than enough.
+ * It is highly unlikely we will execute every function in
+ * the kernel.
+ */
+ functions = 20000;
+#endif
+
+ pg = stat->start = stat->pages;
+
+ pages = DIV_ROUND_UP(functions, PROFILES_PER_PAGE);
+
+ for (i = 0; i < pages; i++) {
+ pg->next = (void *)get_zeroed_page(GFP_KERNEL);
+ if (!pg->next)
+ goto out_free;
+ pg = pg->next;
+ }
+
+ return 0;
+
+ out_free:
+ pg = stat->start;
+ while (pg) {
+ unsigned long tmp = (unsigned long)pg;
+
+ pg = pg->next;
+ free_page(tmp);
+ }
+
+ free_page((unsigned long)stat->pages);
+ stat->pages = NULL;
+ stat->start = NULL;
+
+ return -ENOMEM;
+}
+
+static int ftrace_profile_init_cpu(int cpu)
+{
+ struct ftrace_profile_stat *stat;
+ int size;
+
+ stat = &per_cpu(ftrace_profile_stats, cpu);
+
+ if (stat->hash) {
+ /* If the profile is already created, simply reset it */
+ ftrace_profile_reset(stat);
+ return 0;
+ }
+
+ /*
+ * We are profiling all functions, but usually only a few thousand
+ * functions are hit. We'll make a hash of 1024 items.
+ */
+ size = FTRACE_PROFILE_HASH_SIZE;
+
+ stat->hash = kzalloc(sizeof(struct hlist_head) * size, GFP_KERNEL);
+
+ if (!stat->hash)
+ return -ENOMEM;
+
+ if (!ftrace_profile_bits) {
+ size--;
+
+ for (; size; size >>= 1)
+ ftrace_profile_bits++;
+ }
+
+ /* Preallocate the function profiling pages */
+ if (ftrace_profile_pages_init(stat) < 0) {
+ kfree(stat->hash);
+ stat->hash = NULL;
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int ftrace_profile_init(void)
+{
+ int cpu;
+ int ret = 0;
+
+ for_each_online_cpu(cpu) {
+ ret = ftrace_profile_init_cpu(cpu);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+/* interrupts must be disabled */
+static struct ftrace_profile *
+ftrace_find_profiled_func(struct ftrace_profile_stat *stat, unsigned long ip)
+{
+ struct ftrace_profile *rec;
+ struct hlist_head *hhd;
+ struct hlist_node *n;
+ unsigned long key;
+
+ key = hash_long(ip, ftrace_profile_bits);
+ hhd = &stat->hash[key];
+
+ if (hlist_empty(hhd))
+ return NULL;
+
+ hlist_for_each_entry_rcu(rec, n, hhd, node) {
+ if (rec->ip == ip)
+ return rec;
+ }
+
+ return NULL;
+}
+
+static void ftrace_add_profile(struct ftrace_profile_stat *stat,
+ struct ftrace_profile *rec)
+{
+ unsigned long key;
+
+ key = hash_long(rec->ip, ftrace_profile_bits);
+ hlist_add_head_rcu(&rec->node, &stat->hash[key]);
+}
+
+/*
+ * The memory is already allocated, this simply finds a new record to use.
+ */
+static struct ftrace_profile *
+ftrace_profile_alloc(struct ftrace_profile_stat *stat, unsigned long ip)
+{
+ struct ftrace_profile *rec = NULL;
+
+ /* prevent recursion (from NMIs) */
+ if (atomic_inc_return(&stat->disabled) != 1)
+ goto out;
+
+ /*
+ * Try to find the function again since an NMI
+ * could have added it
+ */
+ rec = ftrace_find_profiled_func(stat, ip);
+ if (rec)
+ goto out;
+
+ if (stat->pages->index == PROFILES_PER_PAGE) {
+ if (!stat->pages->next)
+ goto out;
+ stat->pages = stat->pages->next;
+ }
+
+ rec = &stat->pages->records[stat->pages->index++];
+ rec->ip = ip;
+ ftrace_add_profile(stat, rec);
+
+ out:
+ atomic_dec(&stat->disabled);
+
+ return rec;
+}
+
+static void
+function_profile_call(unsigned long ip, unsigned long parent_ip)
+{
+ struct ftrace_profile_stat *stat;
+ struct ftrace_profile *rec;
+ unsigned long flags;
+
+ if (!ftrace_profile_enabled)
+ return;
+
+ local_irq_save(flags);
+
+ stat = &__get_cpu_var(ftrace_profile_stats);
+ if (!stat->hash)
+ goto out;
+
+ rec = ftrace_find_profiled_func(stat, ip);
+ if (!rec) {
+ rec = ftrace_profile_alloc(stat, ip);
+ if (!rec)
+ goto out;
+ }
+
+ rec->counter++;
+ out:
+ local_irq_restore(flags);
+}
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+static int profile_graph_entry(struct ftrace_graph_ent *trace)
+{
+ function_profile_call(trace->func, 0);
+ return 1;
+}
+
+static void profile_graph_return(struct ftrace_graph_ret *trace)
+{
+ struct ftrace_profile_stat *stat;
+ unsigned long long calltime;
+ struct ftrace_profile *rec;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ stat = &__get_cpu_var(ftrace_profile_stats);
+ if (!stat->hash)
+ goto out;
+
+ calltime = trace->rettime - trace->calltime;
+
+ if (!(trace_flags & TRACE_ITER_GRAPH_TIME)) {
+ int index;
+
+ index = trace->depth;
+
+ /* Append this call time to the parent time to subtract */
+ if (index)
+ current->ret_stack[index - 1].subtime += calltime;
+
+ if (current->ret_stack[index].subtime < calltime)
+ calltime -= current->ret_stack[index].subtime;
+ else
+ calltime = 0;
+ }
+
+ rec = ftrace_find_profiled_func(stat, trace->func);
+ if (rec)
+ rec->time += calltime;
+
+ out:
+ local_irq_restore(flags);
+}
+
+static int register_ftrace_profiler(void)
+{
+ return register_ftrace_graph(&profile_graph_return,
+ &profile_graph_entry);
+}
+
+static void unregister_ftrace_profiler(void)
+{
+ unregister_ftrace_graph();
+}
+#else
+static struct ftrace_ops ftrace_profile_ops __read_mostly =
+{
+ .func = function_profile_call,
+};
+
+static int register_ftrace_profiler(void)
+{
+ return register_ftrace_function(&ftrace_profile_ops);
+}
+
+static void unregister_ftrace_profiler(void)
+{
+ unregister_ftrace_function(&ftrace_profile_ops);
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
+static ssize_t
+ftrace_profile_write(struct file *filp, const char __user *ubuf,
+ size_t cnt, loff_t *ppos)
+{
+ unsigned long val;
+ char buf[64]; /* big enough to hold a number */
+ int ret;
+
+ if (cnt >= sizeof(buf))
+ return -EINVAL;
+
+ if (copy_from_user(&buf, ubuf, cnt))
+ return -EFAULT;
+
+ buf[cnt] = 0;
+
+ ret = strict_strtoul(buf, 10, &val);
+ if (ret < 0)
+ return ret;
+
+ val = !!val;
+
+ mutex_lock(&ftrace_profile_lock);
+ if (ftrace_profile_enabled ^ val) {
+ if (val) {
+ ret = ftrace_profile_init();
+ if (ret < 0) {
+ cnt = ret;
+ goto out;
+ }
+
+ ret = register_ftrace_profiler();
+ if (ret < 0) {
+ cnt = ret;
+ goto out;
+ }
+ ftrace_profile_enabled = 1;
+ } else {
+ ftrace_profile_enabled = 0;
+ unregister_ftrace_profiler();
+ }
+ }
+ out:
+ mutex_unlock(&ftrace_profile_lock);
+
+ filp->f_pos += cnt;
+
+ return cnt;
+}
+
+static ssize_t
+ftrace_profile_read(struct file *filp, char __user *ubuf,
+ size_t cnt, loff_t *ppos)
+{
+ char buf[64]; /* big enough to hold a number */
+ int r;
+
+ r = sprintf(buf, "%u\n", ftrace_profile_enabled);
+ return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+}
+
+static const struct file_operations ftrace_profile_fops = {
+ .open = tracing_open_generic,
+ .read = ftrace_profile_read,
+ .write = ftrace_profile_write,
+};
+
+/* used to initialize the real stat files */
+static struct tracer_stat function_stats __initdata = {
+ .name = "functions",
+ .stat_start = function_stat_start,
+ .stat_next = function_stat_next,
+ .stat_cmp = function_stat_cmp,
+ .stat_headers = function_stat_headers,
+ .stat_show = function_stat_show
+};
+
+static void ftrace_profile_debugfs(struct dentry *d_tracer)
+{
+ struct ftrace_profile_stat *stat;
+ struct dentry *entry;
+ char *name;
+ int ret;
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ stat = &per_cpu(ftrace_profile_stats, cpu);
+
+ /* allocate enough for function name + cpu number */
+ name = kmalloc(32, GFP_KERNEL);
+ if (!name) {
+ /*
+ * The files created are permanent, if something happens
+ * we still do not free memory.
+ */
+ kfree(stat);
+ WARN(1,
+ "Could not allocate stat file for cpu %d\n",
+ cpu);
+ return;
+ }
+ stat->stat = function_stats;
+ snprintf(name, 32, "function%d", cpu);
+ stat->stat.name = name;
+ ret = register_stat_tracer(&stat->stat);
+ if (ret) {
+ WARN(1,
+ "Could not register function stat for cpu %d\n",
+ cpu);
+ kfree(name);
+ return;
+ }
+ }
+
+ entry = debugfs_create_file("function_profile_enabled", 0644,
+ d_tracer, NULL, &ftrace_profile_fops);
+ if (!entry)
+ pr_warning("Could not create debugfs "
+ "'function_profile_enabled' entry\n");
+}
+
+#else /* CONFIG_FUNCTION_PROFILER */
+static void ftrace_profile_debugfs(struct dentry *d_tracer)
+{
+}
+#endif /* CONFIG_FUNCTION_PROFILER */
+
/* set when tracing only a pid */
struct pid *ftrace_pid_trace;
static struct pid * const ftrace_swapper_pid = &init_struct_pid;
@@ -261,7 +832,6 @@ struct ftrace_func_probe {
struct rcu_head rcu;
};
-
enum {
FTRACE_ENABLE_CALLS = (1 << 0),
FTRACE_DISABLE_CALLS = (1 << 1),
@@ -346,30 +916,6 @@ static void ftrace_free_rec(struct dyn_ftrace *rec)
rec->flags |= FTRACE_FL_FREE;
}
-void ftrace_release(void *start, unsigned long size)
-{
- struct dyn_ftrace *rec;
- struct ftrace_page *pg;
- unsigned long s = (unsigned long)start;
- unsigned long e = s + size;
-
- if (ftrace_disabled || !start)
- return;
-
- mutex_lock(&ftrace_lock);
- do_for_each_ftrace_rec(pg, rec) {
- if ((rec->ip >= s) && (rec->ip < e)) {
- /*
- * rec->ip is changed in ftrace_free_rec()
- * It should not between s and e if record was freed.
- */
- FTRACE_WARN_ON(rec->flags & FTRACE_FL_FREE);
- ftrace_free_rec(rec);
- }
- } while_for_each_ftrace_rec();
- mutex_unlock(&ftrace_lock);
-}
-
static struct dyn_ftrace *ftrace_alloc_dyn_node(unsigned long ip)
{
struct dyn_ftrace *rec;
@@ -1408,7 +1954,7 @@ function_trace_probe_call(unsigned long ip, unsigned long parent_ip)
static struct ftrace_ops trace_probe_ops __read_mostly =
{
- .func = function_trace_probe_call,
+ .func = function_trace_probe_call,
};
static int ftrace_probe_registered;
@@ -2128,38 +2674,23 @@ static const struct file_operations ftrace_graph_fops = {
static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer)
{
- struct dentry *entry;
- entry = debugfs_create_file("available_filter_functions", 0444,
- d_tracer, NULL, &ftrace_avail_fops);
- if (!entry)
- pr_warning("Could not create debugfs "
- "'available_filter_functions' entry\n");
+ trace_create_file("available_filter_functions", 0444,
+ d_tracer, NULL, &ftrace_avail_fops);
- entry = debugfs_create_file("failures", 0444,
- d_tracer, NULL, &ftrace_failures_fops);
- if (!entry)
- pr_warning("Could not create debugfs 'failures' entry\n");
+ trace_create_file("failures", 0444,
+ d_tracer, NULL, &ftrace_failures_fops);
- entry = debugfs_create_file("set_ftrace_filter", 0644, d_tracer,
- NULL, &ftrace_filter_fops);
- if (!entry)
- pr_warning("Could not create debugfs "
- "'set_ftrace_filter' entry\n");
+ trace_create_file("set_ftrace_filter", 0644, d_tracer,
+ NULL, &ftrace_filter_fops);
- entry = debugfs_create_file("set_ftrace_notrace", 0644, d_tracer,
+ trace_create_file("set_ftrace_notrace", 0644, d_tracer,
NULL, &ftrace_notrace_fops);
- if (!entry)
- pr_warning("Could not create debugfs "
- "'set_ftrace_notrace' entry\n");
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
- entry = debugfs_create_file("set_graph_function", 0444, d_tracer,
+ trace_create_file("set_graph_function", 0444, d_tracer,
NULL,
&ftrace_graph_fops);
- if (!entry)
- pr_warning("Could not create debugfs "
- "'set_graph_function' entry\n");
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
return 0;
@@ -2197,14 +2728,72 @@ static int ftrace_convert_nops(struct module *mod,
return 0;
}
-void ftrace_init_module(struct module *mod,
- unsigned long *start, unsigned long *end)
+#ifdef CONFIG_MODULES
+void ftrace_release(void *start, void *end)
+{
+ struct dyn_ftrace *rec;
+ struct ftrace_page *pg;
+ unsigned long s = (unsigned long)start;
+ unsigned long e = (unsigned long)end;
+
+ if (ftrace_disabled || !start || start == end)
+ return;
+
+ mutex_lock(&ftrace_lock);
+ do_for_each_ftrace_rec(pg, rec) {
+ if ((rec->ip >= s) && (rec->ip < e)) {
+ /*
+ * rec->ip is changed in ftrace_free_rec()
+ * It should not between s and e if record was freed.
+ */
+ FTRACE_WARN_ON(rec->flags & FTRACE_FL_FREE);
+ ftrace_free_rec(rec);
+ }
+ } while_for_each_ftrace_rec();
+ mutex_unlock(&ftrace_lock);
+}
+
+static void ftrace_init_module(struct module *mod,
+ unsigned long *start, unsigned long *end)
{
if (ftrace_disabled || start == end)
return;
ftrace_convert_nops(mod, start, end);
}
+static int ftrace_module_notify(struct notifier_block *self,
+ unsigned long val, void *data)
+{
+ struct module *mod = data;
+
+ switch (val) {
+ case MODULE_STATE_COMING:
+ ftrace_init_module(mod, mod->ftrace_callsites,
+ mod->ftrace_callsites +
+ mod->num_ftrace_callsites);
+ break;
+ case MODULE_STATE_GOING:
+ ftrace_release(mod->ftrace_callsites,
+ mod->ftrace_callsites +
+ mod->num_ftrace_callsites);
+ break;
+ }
+
+ return 0;
+}
+#else
+static int ftrace_module_notify(struct notifier_block *self,
+ unsigned long val, void *data)
+{
+ return 0;
+}
+#endif /* CONFIG_MODULES */
+
+struct notifier_block ftrace_module_nb = {
+ .notifier_call = ftrace_module_notify,
+ .priority = 0,
+};
+
extern unsigned long __start_mcount_loc[];
extern unsigned long __stop_mcount_loc[];
@@ -2236,6 +2825,10 @@ void __init ftrace_init(void)
__start_mcount_loc,
__stop_mcount_loc);
+ ret = register_module_notifier(&ftrace_module_nb);
+ if (!ret)
+ pr_warning("Failed to register trace ftrace module notifier\n");
+
return;
failed:
ftrace_disabled = 1;
@@ -2417,7 +3010,6 @@ static const struct file_operations ftrace_pid_fops = {
static __init int ftrace_init_debugfs(void)
{
struct dentry *d_tracer;
- struct dentry *entry;
d_tracer = tracing_init_dentry();
if (!d_tracer)
@@ -2425,11 +3017,11 @@ static __init int ftrace_init_debugfs(void)
ftrace_init_dyn_debugfs(d_tracer);
- entry = debugfs_create_file("set_ftrace_pid", 0644, d_tracer,
- NULL, &ftrace_pid_fops);
- if (!entry)
- pr_warning("Could not create debugfs "
- "'set_ftrace_pid' entry\n");
+ trace_create_file("set_ftrace_pid", 0644, d_tracer,
+ NULL, &ftrace_pid_fops);
+
+ ftrace_profile_debugfs(d_tracer);
+
return 0;
}
fs_initcall(ftrace_init_debugfs);
@@ -2538,7 +3130,7 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-static atomic_t ftrace_graph_active;
+static int ftrace_graph_active;
static struct notifier_block ftrace_suspend_notifier;
int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace)
@@ -2690,7 +3282,7 @@ int register_ftrace_graph(trace_func_graph_ret_t retfunc,
mutex_lock(&ftrace_lock);
/* we currently allow only one tracer registered at a time */
- if (atomic_read(&ftrace_graph_active)) {
+ if (ftrace_graph_active) {
ret = -EBUSY;
goto out;
}
@@ -2698,10 +3290,10 @@ int register_ftrace_graph(trace_func_graph_ret_t retfunc,
ftrace_suspend_notifier.notifier_call = ftrace_suspend_notifier_call;
register_pm_notifier(&ftrace_suspend_notifier);
- atomic_inc(&ftrace_graph_active);
+ ftrace_graph_active++;
ret = start_graph_tracing();
if (ret) {
- atomic_dec(&ftrace_graph_active);
+ ftrace_graph_active--;
goto out;
}
@@ -2719,10 +3311,10 @@ void unregister_ftrace_graph(void)
{
mutex_lock(&ftrace_lock);
- if (!unlikely(atomic_read(&ftrace_graph_active)))
+ if (unlikely(!ftrace_graph_active))
goto out;
- atomic_dec(&ftrace_graph_active);
+ ftrace_graph_active--;
unregister_trace_sched_switch(ftrace_graph_probe_sched_switch);
ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub;
ftrace_graph_entry = ftrace_graph_entry_stub;
@@ -2736,7 +3328,7 @@ void unregister_ftrace_graph(void)
/* Allocate a return stack for newly created task */
void ftrace_graph_init_task(struct task_struct *t)
{
- if (atomic_read(&ftrace_graph_active)) {
+ if (ftrace_graph_active) {
t->ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH
* sizeof(struct ftrace_ret_stack),
GFP_KERNEL);
diff --git a/kernel/trace/kmemtrace.c b/kernel/trace/kmemtrace.c
index 5011f4d91e37..86cdf671d7e2 100644
--- a/kernel/trace/kmemtrace.c
+++ b/kernel/trace/kmemtrace.c
@@ -12,7 +12,7 @@
#include <linux/dcache.h>
#include <linux/fs.h>
-#include <trace/kmemtrace.h>
+#include <linux/kmemtrace.h>
#include "trace_output.h"
#include "trace.h"
@@ -42,6 +42,7 @@ static inline void kmemtrace_alloc(enum kmemtrace_type_id type_id,
gfp_t gfp_flags,
int node)
{
+ struct ftrace_event_call *call = &event_kmem_alloc;
struct trace_array *tr = kmemtrace_array;
struct kmemtrace_alloc_entry *entry;
struct ring_buffer_event *event;
@@ -62,7 +63,8 @@ static inline void kmemtrace_alloc(enum kmemtrace_type_id type_id,
entry->gfp_flags = gfp_flags;
entry->node = node;
- ring_buffer_unlock_commit(tr->buffer, event);
+ if (!filter_check_discard(call, entry, tr->buffer, event))
+ ring_buffer_unlock_commit(tr->buffer, event);
trace_wake_up();
}
@@ -71,6 +73,7 @@ static inline void kmemtrace_free(enum kmemtrace_type_id type_id,
unsigned long call_site,
const void *ptr)
{
+ struct ftrace_event_call *call = &event_kmem_free;
struct trace_array *tr = kmemtrace_array;
struct kmemtrace_free_entry *entry;
struct ring_buffer_event *event;
@@ -86,7 +89,8 @@ static inline void kmemtrace_free(enum kmemtrace_type_id type_id,
entry->call_site = call_site;
entry->ptr = ptr;
- ring_buffer_unlock_commit(tr->buffer, event);
+ if (!filter_check_discard(call, entry, tr->buffer, event))
+ ring_buffer_unlock_commit(tr->buffer, event);
trace_wake_up();
}
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 960cbf44c844..3ae5ccf2c0fc 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -22,6 +22,28 @@
#include "trace.h"
/*
+ * The ring buffer header is special. We must manually up keep it.
+ */
+int ring_buffer_print_entry_header(struct trace_seq *s)
+{
+ int ret;
+
+ ret = trace_seq_printf(s, "# compressed entry header\n");
+ ret = trace_seq_printf(s, "\ttype_len : 5 bits\n");
+ ret = trace_seq_printf(s, "\ttime_delta : 27 bits\n");
+ ret = trace_seq_printf(s, "\tarray : 32 bits\n");
+ ret = trace_seq_printf(s, "\n");
+ ret = trace_seq_printf(s, "\tpadding : type == %d\n",
+ RINGBUF_TYPE_PADDING);
+ ret = trace_seq_printf(s, "\ttime_extend : type == %d\n",
+ RINGBUF_TYPE_TIME_EXTEND);
+ ret = trace_seq_printf(s, "\tdata max type_len == %d\n",
+ RINGBUF_TYPE_DATA_TYPE_LEN_MAX);
+
+ return ret;
+}
+
+/*
* The ring buffer is made up of a list of pages. A separate list of pages is
* allocated for each CPU. A writer may only write to a buffer that is
* associated with the CPU it is currently executing on. A reader may read
@@ -182,7 +204,10 @@ EXPORT_SYMBOL_GPL(tracing_is_on);
#define RB_EVNT_HDR_SIZE (offsetof(struct ring_buffer_event, array))
#define RB_ALIGNMENT 4U
-#define RB_MAX_SMALL_DATA 28
+#define RB_MAX_SMALL_DATA (RB_ALIGNMENT * RINGBUF_TYPE_DATA_TYPE_LEN_MAX)
+
+/* define RINGBUF_TYPE_DATA for 'case RINGBUF_TYPE_DATA:' */
+#define RINGBUF_TYPE_DATA 0 ... RINGBUF_TYPE_DATA_TYPE_LEN_MAX
enum {
RB_LEN_TIME_EXTEND = 8,
@@ -191,48 +216,28 @@ enum {
static inline int rb_null_event(struct ring_buffer_event *event)
{
- return event->type == RINGBUF_TYPE_PADDING && event->time_delta == 0;
+ return event->type_len == RINGBUF_TYPE_PADDING
+ && event->time_delta == 0;
}
static inline int rb_discarded_event(struct ring_buffer_event *event)
{
- return event->type == RINGBUF_TYPE_PADDING && event->time_delta;
+ return event->type_len == RINGBUF_TYPE_PADDING && event->time_delta;
}
static void rb_event_set_padding(struct ring_buffer_event *event)
{
- event->type = RINGBUF_TYPE_PADDING;
+ event->type_len = RINGBUF_TYPE_PADDING;
event->time_delta = 0;
}
-/**
- * ring_buffer_event_discard - discard an event in the ring buffer
- * @buffer: the ring buffer
- * @event: the event to discard
- *
- * Sometimes a event that is in the ring buffer needs to be ignored.
- * This function lets the user discard an event in the ring buffer
- * and then that event will not be read later.
- *
- * Note, it is up to the user to be careful with this, and protect
- * against races. If the user discards an event that has been consumed
- * it is possible that it could corrupt the ring buffer.
- */
-void ring_buffer_event_discard(struct ring_buffer_event *event)
-{
- event->type = RINGBUF_TYPE_PADDING;
- /* time delta must be non zero */
- if (!event->time_delta)
- event->time_delta = 1;
-}
-
static unsigned
rb_event_data_length(struct ring_buffer_event *event)
{
unsigned length;
- if (event->len)
- length = event->len * RB_ALIGNMENT;
+ if (event->type_len)
+ length = event->type_len * RB_ALIGNMENT;
else
length = event->array[0];
return length + RB_EVNT_HDR_SIZE;
@@ -242,12 +247,12 @@ rb_event_data_length(struct ring_buffer_event *event)
static unsigned
rb_event_length(struct ring_buffer_event *event)
{
- switch (event->type) {
+ switch (event->type_len) {
case RINGBUF_TYPE_PADDING:
if (rb_null_event(event))
/* undefined */
return -1;
- return rb_event_data_length(event);
+ return event->array[0] + RB_EVNT_HDR_SIZE;
case RINGBUF_TYPE_TIME_EXTEND:
return RB_LEN_TIME_EXTEND;
@@ -271,7 +276,7 @@ rb_event_length(struct ring_buffer_event *event)
unsigned ring_buffer_event_length(struct ring_buffer_event *event)
{
unsigned length = rb_event_length(event);
- if (event->type != RINGBUF_TYPE_DATA)
+ if (event->type_len > RINGBUF_TYPE_DATA_TYPE_LEN_MAX)
return length;
length -= RB_EVNT_HDR_SIZE;
if (length > RB_MAX_SMALL_DATA + sizeof(event->array[0]))
@@ -284,9 +289,9 @@ EXPORT_SYMBOL_GPL(ring_buffer_event_length);
static void *
rb_event_data(struct ring_buffer_event *event)
{
- BUG_ON(event->type != RINGBUF_TYPE_DATA);
+ BUG_ON(event->type_len > RINGBUF_TYPE_DATA_TYPE_LEN_MAX);
/* If length is in len field, then array[0] has the data */
- if (event->len)
+ if (event->type_len)
return (void *)&event->array[0];
/* Otherwise length is in array[0] and array[1] has the data */
return (void *)&event->array[1];
@@ -316,9 +321,10 @@ struct buffer_data_page {
};
struct buffer_page {
+ struct list_head list; /* list of buffer pages */
local_t write; /* index for next write */
unsigned read; /* index for next read */
- struct list_head list; /* list of free pages */
+ local_t entries; /* entries on this page */
struct buffer_data_page *page; /* Actual data page */
};
@@ -361,6 +367,28 @@ static inline int test_time_stamp(u64 delta)
#define BUF_PAGE_SIZE (PAGE_SIZE - BUF_PAGE_HDR_SIZE)
+int ring_buffer_print_page_header(struct trace_seq *s)
+{
+ struct buffer_data_page field;
+ int ret;
+
+ ret = trace_seq_printf(s, "\tfield: u64 timestamp;\t"
+ "offset:0;\tsize:%u;\n",
+ (unsigned int)sizeof(field.time_stamp));
+
+ ret = trace_seq_printf(s, "\tfield: local_t commit;\t"
+ "offset:%u;\tsize:%u;\n",
+ (unsigned int)offsetof(typeof(field), commit),
+ (unsigned int)sizeof(field.commit));
+
+ ret = trace_seq_printf(s, "\tfield: char data;\t"
+ "offset:%u;\tsize:%u;\n",
+ (unsigned int)offsetof(typeof(field), data),
+ (unsigned int)BUF_PAGE_SIZE);
+
+ return ret;
+}
+
/*
* head_page == tail_page && head == tail then buffer is empty.
*/
@@ -375,8 +403,11 @@ struct ring_buffer_per_cpu {
struct buffer_page *tail_page; /* write to tail */
struct buffer_page *commit_page; /* committed pages */
struct buffer_page *reader_page;
+ unsigned long nmi_dropped;
+ unsigned long commit_overrun;
unsigned long overrun;
- unsigned long entries;
+ unsigned long read;
+ local_t entries;
u64 write_stamp;
u64 read_stamp;
atomic_t record_disabled;
@@ -947,31 +978,6 @@ static inline unsigned rb_head_size(struct ring_buffer_per_cpu *cpu_buffer)
return rb_page_commit(cpu_buffer->head_page);
}
-/*
- * When the tail hits the head and the buffer is in overwrite mode,
- * the head jumps to the next page and all content on the previous
- * page is discarded. But before doing so, we update the overrun
- * variable of the buffer.
- */
-static void rb_update_overflow(struct ring_buffer_per_cpu *cpu_buffer)
-{
- struct ring_buffer_event *event;
- unsigned long head;
-
- for (head = 0; head < rb_head_size(cpu_buffer);
- head += rb_event_length(event)) {
-
- event = __rb_page_index(cpu_buffer->head_page, head);
- if (RB_WARN_ON(cpu_buffer, rb_null_event(event)))
- return;
- /* Only count data entries */
- if (event->type != RINGBUF_TYPE_DATA)
- continue;
- cpu_buffer->overrun++;
- cpu_buffer->entries--;
- }
-}
-
static inline void rb_inc_page(struct ring_buffer_per_cpu *cpu_buffer,
struct buffer_page **bpage)
{
@@ -1110,28 +1116,21 @@ static void
rb_update_event(struct ring_buffer_event *event,
unsigned type, unsigned length)
{
- event->type = type;
+ event->type_len = type;
switch (type) {
case RINGBUF_TYPE_PADDING:
- break;
-
case RINGBUF_TYPE_TIME_EXTEND:
- event->len = DIV_ROUND_UP(RB_LEN_TIME_EXTEND, RB_ALIGNMENT);
- break;
-
case RINGBUF_TYPE_TIME_STAMP:
- event->len = DIV_ROUND_UP(RB_LEN_TIME_STAMP, RB_ALIGNMENT);
break;
- case RINGBUF_TYPE_DATA:
+ case 0:
length -= RB_EVNT_HDR_SIZE;
- if (length > RB_MAX_SMALL_DATA) {
- event->len = 0;
+ if (length > RB_MAX_SMALL_DATA)
event->array[0] = length;
- } else
- event->len = DIV_ROUND_UP(length, RB_ALIGNMENT);
+ else
+ event->type_len = DIV_ROUND_UP(length, RB_ALIGNMENT);
break;
default:
BUG();
@@ -1155,131 +1154,156 @@ static unsigned rb_calculate_event_length(unsigned length)
return length;
}
+
static struct ring_buffer_event *
-__rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,
- unsigned type, unsigned long length, u64 *ts)
+rb_move_tail(struct ring_buffer_per_cpu *cpu_buffer,
+ unsigned long length, unsigned long tail,
+ struct buffer_page *commit_page,
+ struct buffer_page *tail_page, u64 *ts)
{
- struct buffer_page *tail_page, *head_page, *reader_page, *commit_page;
- unsigned long tail, write;
+ struct buffer_page *next_page, *head_page, *reader_page;
struct ring_buffer *buffer = cpu_buffer->buffer;
struct ring_buffer_event *event;
- unsigned long flags;
bool lock_taken = false;
+ unsigned long flags;
- commit_page = cpu_buffer->commit_page;
- /* we just need to protect against interrupts */
- barrier();
- tail_page = cpu_buffer->tail_page;
- write = local_add_return(length, &tail_page->write);
- tail = write - length;
+ next_page = tail_page;
- /* See if we shot pass the end of this buffer page */
- if (write > BUF_PAGE_SIZE) {
- struct buffer_page *next_page = tail_page;
+ local_irq_save(flags);
+ /*
+ * Since the write to the buffer is still not
+ * fully lockless, we must be careful with NMIs.
+ * The locks in the writers are taken when a write
+ * crosses to a new page. The locks protect against
+ * races with the readers (this will soon be fixed
+ * with a lockless solution).
+ *
+ * Because we can not protect against NMIs, and we
+ * want to keep traces reentrant, we need to manage
+ * what happens when we are in an NMI.
+ *
+ * NMIs can happen after we take the lock.
+ * If we are in an NMI, only take the lock
+ * if it is not already taken. Otherwise
+ * simply fail.
+ */
+ if (unlikely(in_nmi())) {
+ if (!__raw_spin_trylock(&cpu_buffer->lock)) {
+ cpu_buffer->nmi_dropped++;
+ goto out_reset;
+ }
+ } else
+ __raw_spin_lock(&cpu_buffer->lock);
- local_irq_save(flags);
- /*
- * Since the write to the buffer is still not
- * fully lockless, we must be careful with NMIs.
- * The locks in the writers are taken when a write
- * crosses to a new page. The locks protect against
- * races with the readers (this will soon be fixed
- * with a lockless solution).
- *
- * Because we can not protect against NMIs, and we
- * want to keep traces reentrant, we need to manage
- * what happens when we are in an NMI.
- *
- * NMIs can happen after we take the lock.
- * If we are in an NMI, only take the lock
- * if it is not already taken. Otherwise
- * simply fail.
- */
- if (unlikely(in_nmi())) {
- if (!__raw_spin_trylock(&cpu_buffer->lock))
- goto out_reset;
- } else
- __raw_spin_lock(&cpu_buffer->lock);
+ lock_taken = true;
- lock_taken = true;
+ rb_inc_page(cpu_buffer, &next_page);
- rb_inc_page(cpu_buffer, &next_page);
+ head_page = cpu_buffer->head_page;
+ reader_page = cpu_buffer->reader_page;
- head_page = cpu_buffer->head_page;
- reader_page = cpu_buffer->reader_page;
+ /* we grabbed the lock before incrementing */
+ if (RB_WARN_ON(cpu_buffer, next_page == reader_page))
+ goto out_reset;
- /* we grabbed the lock before incrementing */
- if (RB_WARN_ON(cpu_buffer, next_page == reader_page))
- goto out_reset;
+ /*
+ * If for some reason, we had an interrupt storm that made
+ * it all the way around the buffer, bail, and warn
+ * about it.
+ */
+ if (unlikely(next_page == commit_page)) {
+ cpu_buffer->commit_overrun++;
+ goto out_reset;
+ }
- /*
- * If for some reason, we had an interrupt storm that made
- * it all the way around the buffer, bail, and warn
- * about it.
- */
- if (unlikely(next_page == commit_page)) {
- WARN_ON_ONCE(1);
+ if (next_page == head_page) {
+ if (!(buffer->flags & RB_FL_OVERWRITE))
goto out_reset;
- }
-
- if (next_page == head_page) {
- if (!(buffer->flags & RB_FL_OVERWRITE))
- goto out_reset;
- /* tail_page has not moved yet? */
- if (tail_page == cpu_buffer->tail_page) {
- /* count overflows */
- rb_update_overflow(cpu_buffer);
+ /* tail_page has not moved yet? */
+ if (tail_page == cpu_buffer->tail_page) {
+ /* count overflows */
+ cpu_buffer->overrun +=
+ local_read(&head_page->entries);
- rb_inc_page(cpu_buffer, &head_page);
- cpu_buffer->head_page = head_page;
- cpu_buffer->head_page->read = 0;
- }
+ rb_inc_page(cpu_buffer, &head_page);
+ cpu_buffer->head_page = head_page;
+ cpu_buffer->head_page->read = 0;
}
+ }
- /*
- * If the tail page is still the same as what we think
- * it is, then it is up to us to update the tail
- * pointer.
- */
- if (tail_page == cpu_buffer->tail_page) {
- local_set(&next_page->write, 0);
- local_set(&next_page->page->commit, 0);
- cpu_buffer->tail_page = next_page;
+ /*
+ * If the tail page is still the same as what we think
+ * it is, then it is up to us to update the tail
+ * pointer.
+ */
+ if (tail_page == cpu_buffer->tail_page) {
+ local_set(&next_page->write, 0);
+ local_set(&next_page->entries, 0);
+ local_set(&next_page->page->commit, 0);
+ cpu_buffer->tail_page = next_page;
+
+ /* reread the time stamp */
+ *ts = ring_buffer_time_stamp(buffer, cpu_buffer->cpu);
+ cpu_buffer->tail_page->page->time_stamp = *ts;
+ }
- /* reread the time stamp */
- *ts = ring_buffer_time_stamp(buffer, cpu_buffer->cpu);
- cpu_buffer->tail_page->page->time_stamp = *ts;
- }
+ /*
+ * The actual tail page has moved forward.
+ */
+ if (tail < BUF_PAGE_SIZE) {
+ /* Mark the rest of the page with padding */
+ event = __rb_page_index(tail_page, tail);
+ rb_event_set_padding(event);
+ }
- /*
- * The actual tail page has moved forward.
- */
- if (tail < BUF_PAGE_SIZE) {
- /* Mark the rest of the page with padding */
- event = __rb_page_index(tail_page, tail);
- rb_event_set_padding(event);
- }
+ /* Set the write back to the previous setting */
+ local_sub(length, &tail_page->write);
- if (tail <= BUF_PAGE_SIZE)
- /* Set the write back to the previous setting */
- local_set(&tail_page->write, tail);
+ /*
+ * If this was a commit entry that failed,
+ * increment that too
+ */
+ if (tail_page == cpu_buffer->commit_page &&
+ tail == rb_commit_index(cpu_buffer)) {
+ rb_set_commit_to_write(cpu_buffer);
+ }
- /*
- * If this was a commit entry that failed,
- * increment that too
- */
- if (tail_page == cpu_buffer->commit_page &&
- tail == rb_commit_index(cpu_buffer)) {
- rb_set_commit_to_write(cpu_buffer);
- }
+ __raw_spin_unlock(&cpu_buffer->lock);
+ local_irq_restore(flags);
+
+ /* fail and let the caller try again */
+ return ERR_PTR(-EAGAIN);
+
+ out_reset:
+ /* reset write */
+ local_sub(length, &tail_page->write);
+ if (likely(lock_taken))
__raw_spin_unlock(&cpu_buffer->lock);
- local_irq_restore(flags);
+ local_irq_restore(flags);
+ return NULL;
+}
- /* fail and let the caller try again */
- return ERR_PTR(-EAGAIN);
- }
+static struct ring_buffer_event *
+__rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,
+ unsigned type, unsigned long length, u64 *ts)
+{
+ struct buffer_page *tail_page, *commit_page;
+ struct ring_buffer_event *event;
+ unsigned long tail, write;
+
+ commit_page = cpu_buffer->commit_page;
+ /* we just need to protect against interrupts */
+ barrier();
+ tail_page = cpu_buffer->tail_page;
+ write = local_add_return(length, &tail_page->write);
+ tail = write - length;
+
+ /* See if we shot pass the end of this buffer page */
+ if (write > BUF_PAGE_SIZE)
+ return rb_move_tail(cpu_buffer, length, tail,
+ commit_page, tail_page, ts);
/* We reserved something on the buffer */
@@ -1289,6 +1313,10 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,
event = __rb_page_index(tail_page, tail);
rb_update_event(event, type, length);
+ /* The passed in type is zero for DATA */
+ if (likely(!type))
+ local_inc(&tail_page->entries);
+
/*
* If this is a commit and the tail is zero, then update
* this page's time stamp.
@@ -1297,16 +1325,6 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,
cpu_buffer->commit_page->page->time_stamp = *ts;
return event;
-
- out_reset:
- /* reset write */
- if (tail <= BUF_PAGE_SIZE)
- local_set(&tail_page->write, tail);
-
- if (likely(lock_taken))
- __raw_spin_unlock(&cpu_buffer->lock);
- local_irq_restore(flags);
- return NULL;
}
static int
@@ -1458,6 +1476,36 @@ rb_reserve_next_event(struct ring_buffer_per_cpu *cpu_buffer,
return event;
}
+#define TRACE_RECURSIVE_DEPTH 16
+
+static int trace_recursive_lock(void)
+{
+ current->trace_recursion++;
+
+ if (likely(current->trace_recursion < TRACE_RECURSIVE_DEPTH))
+ return 0;
+
+ /* Disable all tracing before we do anything else */
+ tracing_off_permanent();
+
+ printk_once(KERN_WARNING "Tracing recursion: depth[%ld]:"
+ "HC[%lu]:SC[%lu]:NMI[%lu]\n",
+ current->trace_recursion,
+ hardirq_count() >> HARDIRQ_SHIFT,
+ softirq_count() >> SOFTIRQ_SHIFT,
+ in_nmi());
+
+ WARN_ON_ONCE(1);
+ return -1;
+}
+
+static void trace_recursive_unlock(void)
+{
+ WARN_ON_ONCE(!current->trace_recursion);
+
+ current->trace_recursion--;
+}
+
static DEFINE_PER_CPU(int, rb_need_resched);
/**
@@ -1491,6 +1539,9 @@ ring_buffer_lock_reserve(struct ring_buffer *buffer, unsigned long length)
/* If we are tracing schedule, we don't want to recurse */
resched = ftrace_preempt_disable();
+ if (trace_recursive_lock())
+ goto out_nocheck;
+
cpu = raw_smp_processor_id();
if (!cpumask_test_cpu(cpu, buffer->cpumask))
@@ -1505,7 +1556,7 @@ ring_buffer_lock_reserve(struct ring_buffer *buffer, unsigned long length)
if (length > BUF_PAGE_SIZE)
goto out;
- event = rb_reserve_next_event(cpu_buffer, RINGBUF_TYPE_DATA, length);
+ event = rb_reserve_next_event(cpu_buffer, 0, length);
if (!event)
goto out;
@@ -1520,6 +1571,9 @@ ring_buffer_lock_reserve(struct ring_buffer *buffer, unsigned long length)
return event;
out:
+ trace_recursive_unlock();
+
+ out_nocheck:
ftrace_preempt_enable(resched);
return NULL;
}
@@ -1528,7 +1582,7 @@ EXPORT_SYMBOL_GPL(ring_buffer_lock_reserve);
static void rb_commit(struct ring_buffer_per_cpu *cpu_buffer,
struct ring_buffer_event *event)
{
- cpu_buffer->entries++;
+ local_inc(&cpu_buffer->entries);
/* Only process further if we own the commit */
if (!rb_is_commit(cpu_buffer, event))
@@ -1558,6 +1612,8 @@ int ring_buffer_unlock_commit(struct ring_buffer *buffer,
rb_commit(cpu_buffer, event);
+ trace_recursive_unlock();
+
/*
* Only the last preempt count needs to restore preemption.
*/
@@ -1570,6 +1626,119 @@ int ring_buffer_unlock_commit(struct ring_buffer *buffer,
}
EXPORT_SYMBOL_GPL(ring_buffer_unlock_commit);
+static inline void rb_event_discard(struct ring_buffer_event *event)
+{
+ /* array[0] holds the actual length for the discarded event */
+ event->array[0] = rb_event_data_length(event) - RB_EVNT_HDR_SIZE;
+ event->type_len = RINGBUF_TYPE_PADDING;
+ /* time delta must be non zero */
+ if (!event->time_delta)
+ event->time_delta = 1;
+}
+
+/**
+ * ring_buffer_event_discard - discard any event in the ring buffer
+ * @event: the event to discard
+ *
+ * Sometimes a event that is in the ring buffer needs to be ignored.
+ * This function lets the user discard an event in the ring buffer
+ * and then that event will not be read later.
+ *
+ * Note, it is up to the user to be careful with this, and protect
+ * against races. If the user discards an event that has been consumed
+ * it is possible that it could corrupt the ring buffer.
+ */
+void ring_buffer_event_discard(struct ring_buffer_event *event)
+{
+ rb_event_discard(event);
+}
+EXPORT_SYMBOL_GPL(ring_buffer_event_discard);
+
+/**
+ * ring_buffer_commit_discard - discard an event that has not been committed
+ * @buffer: the ring buffer
+ * @event: non committed event to discard
+ *
+ * This is similar to ring_buffer_event_discard but must only be
+ * performed on an event that has not been committed yet. The difference
+ * is that this will also try to free the event from the ring buffer
+ * if another event has not been added behind it.
+ *
+ * If another event has been added behind it, it will set the event
+ * up as discarded, and perform the commit.
+ *
+ * If this function is called, do not call ring_buffer_unlock_commit on
+ * the event.
+ */
+void ring_buffer_discard_commit(struct ring_buffer *buffer,
+ struct ring_buffer_event *event)
+{
+ struct ring_buffer_per_cpu *cpu_buffer;
+ unsigned long new_index, old_index;
+ struct buffer_page *bpage;
+ unsigned long index;
+ unsigned long addr;
+ int cpu;
+
+ /* The event is discarded regardless */
+ rb_event_discard(event);
+
+ /*
+ * This must only be called if the event has not been
+ * committed yet. Thus we can assume that preemption
+ * is still disabled.
+ */
+ RB_WARN_ON(buffer, !preempt_count());
+
+ cpu = smp_processor_id();
+ cpu_buffer = buffer->buffers[cpu];
+
+ new_index = rb_event_index(event);
+ old_index = new_index + rb_event_length(event);
+ addr = (unsigned long)event;
+ addr &= PAGE_MASK;
+
+ bpage = cpu_buffer->tail_page;
+
+ if (bpage == (void *)addr && rb_page_write(bpage) == old_index) {
+ /*
+ * This is on the tail page. It is possible that
+ * a write could come in and move the tail page
+ * and write to the next page. That is fine
+ * because we just shorten what is on this page.
+ */
+ index = local_cmpxchg(&bpage->write, old_index, new_index);
+ if (index == old_index)
+ goto out;
+ }
+
+ /*
+ * The commit is still visible by the reader, so we
+ * must increment entries.
+ */
+ local_inc(&cpu_buffer->entries);
+ out:
+ /*
+ * If a write came in and pushed the tail page
+ * we still need to update the commit pointer
+ * if we were the commit.
+ */
+ if (rb_is_commit(cpu_buffer, event))
+ rb_set_commit_to_write(cpu_buffer);
+
+ trace_recursive_unlock();
+
+ /*
+ * Only the last preempt count needs to restore preemption.
+ */
+ if (preempt_count() == 1)
+ ftrace_preempt_enable(per_cpu(rb_need_resched, cpu));
+ else
+ preempt_enable_no_resched_notrace();
+
+}
+EXPORT_SYMBOL_GPL(ring_buffer_discard_commit);
+
/**
* ring_buffer_write - write data to the buffer without reserving
* @buffer: The ring buffer to write to.
@@ -1613,8 +1782,7 @@ int ring_buffer_write(struct ring_buffer *buffer,
goto out;
event_length = rb_calculate_event_length(length);
- event = rb_reserve_next_event(cpu_buffer,
- RINGBUF_TYPE_DATA, event_length);
+ event = rb_reserve_next_event(cpu_buffer, 0, event_length);
if (!event)
goto out;
@@ -1728,7 +1896,8 @@ unsigned long ring_buffer_entries_cpu(struct ring_buffer *buffer, int cpu)
return 0;
cpu_buffer = buffer->buffers[cpu];
- ret = cpu_buffer->entries;
+ ret = (local_read(&cpu_buffer->entries) - cpu_buffer->overrun)
+ - cpu_buffer->read;
return ret;
}
@@ -1755,6 +1924,47 @@ unsigned long ring_buffer_overrun_cpu(struct ring_buffer *buffer, int cpu)
EXPORT_SYMBOL_GPL(ring_buffer_overrun_cpu);
/**
+ * ring_buffer_nmi_dropped_cpu - get the number of nmis that were dropped
+ * @buffer: The ring buffer
+ * @cpu: The per CPU buffer to get the number of overruns from
+ */
+unsigned long ring_buffer_nmi_dropped_cpu(struct ring_buffer *buffer, int cpu)
+{
+ struct ring_buffer_per_cpu *cpu_buffer;
+ unsigned long ret;
+
+ if (!cpumask_test_cpu(cpu, buffer->cpumask))
+ return 0;
+
+ cpu_buffer = buffer->buffers[cpu];
+ ret = cpu_buffer->nmi_dropped;
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(ring_buffer_nmi_dropped_cpu);
+
+/**
+ * ring_buffer_commit_overrun_cpu - get the number of overruns caused by commits
+ * @buffer: The ring buffer
+ * @cpu: The per CPU buffer to get the number of overruns from
+ */
+unsigned long
+ring_buffer_commit_overrun_cpu(struct ring_buffer *buffer, int cpu)
+{
+ struct ring_buffer_per_cpu *cpu_buffer;
+ unsigned long ret;
+
+ if (!cpumask_test_cpu(cpu, buffer->cpumask))
+ return 0;
+
+ cpu_buffer = buffer->buffers[cpu];
+ ret = cpu_buffer->commit_overrun;
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(ring_buffer_commit_overrun_cpu);
+
+/**
* ring_buffer_entries - get the number of entries in a buffer
* @buffer: The ring buffer
*
@@ -1770,7 +1980,8 @@ unsigned long ring_buffer_entries(struct ring_buffer *buffer)
/* if you care about this being correct, lock the buffer */
for_each_buffer_cpu(buffer, cpu) {
cpu_buffer = buffer->buffers[cpu];
- entries += cpu_buffer->entries;
+ entries += (local_read(&cpu_buffer->entries) -
+ cpu_buffer->overrun) - cpu_buffer->read;
}
return entries;
@@ -1862,7 +2073,7 @@ rb_update_read_stamp(struct ring_buffer_per_cpu *cpu_buffer,
{
u64 delta;
- switch (event->type) {
+ switch (event->type_len) {
case RINGBUF_TYPE_PADDING:
return;
@@ -1893,7 +2104,7 @@ rb_update_iter_read_stamp(struct ring_buffer_iter *iter,
{
u64 delta;
- switch (event->type) {
+ switch (event->type_len) {
case RINGBUF_TYPE_PADDING:
return;
@@ -1966,6 +2177,7 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer)
cpu_buffer->reader_page->list.prev = reader->list.prev;
local_set(&cpu_buffer->reader_page->write, 0);
+ local_set(&cpu_buffer->reader_page->entries, 0);
local_set(&cpu_buffer->reader_page->page->commit, 0);
/* Make the reader page now replace the head */
@@ -2008,8 +2220,9 @@ static void rb_advance_reader(struct ring_buffer_per_cpu *cpu_buffer)
event = rb_reader_event(cpu_buffer);
- if (event->type == RINGBUF_TYPE_DATA || rb_discarded_event(event))
- cpu_buffer->entries--;
+ if (event->type_len <= RINGBUF_TYPE_DATA_TYPE_LEN_MAX
+ || rb_discarded_event(event))
+ cpu_buffer->read++;
rb_update_read_stamp(cpu_buffer, event);
@@ -2089,7 +2302,7 @@ rb_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts)
event = rb_reader_event(cpu_buffer);
- switch (event->type) {
+ switch (event->type_len) {
case RINGBUF_TYPE_PADDING:
if (rb_null_event(event))
RB_WARN_ON(cpu_buffer, 1);
@@ -2161,7 +2374,7 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts)
event = rb_iter_head_event(iter);
- switch (event->type) {
+ switch (event->type_len) {
case RINGBUF_TYPE_PADDING:
if (rb_null_event(event)) {
rb_inc_iter(iter);
@@ -2220,7 +2433,7 @@ ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts)
event = rb_buffer_peek(buffer, cpu, ts);
spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
- if (event && event->type == RINGBUF_TYPE_PADDING) {
+ if (event && event->type_len == RINGBUF_TYPE_PADDING) {
cpu_relax();
goto again;
}
@@ -2248,7 +2461,7 @@ ring_buffer_iter_peek(struct ring_buffer_iter *iter, u64 *ts)
event = rb_iter_peek(iter, ts);
spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
- if (event && event->type == RINGBUF_TYPE_PADDING) {
+ if (event && event->type_len == RINGBUF_TYPE_PADDING) {
cpu_relax();
goto again;
}
@@ -2293,7 +2506,7 @@ ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts)
out:
preempt_enable();
- if (event && event->type == RINGBUF_TYPE_PADDING) {
+ if (event && event->type_len == RINGBUF_TYPE_PADDING) {
cpu_relax();
goto again;
}
@@ -2386,7 +2599,7 @@ ring_buffer_read(struct ring_buffer_iter *iter, u64 *ts)
out:
spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
- if (event && event->type == RINGBUF_TYPE_PADDING) {
+ if (event && event->type_len == RINGBUF_TYPE_PADDING) {
cpu_relax();
goto again;
}
@@ -2411,6 +2624,7 @@ rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer)
cpu_buffer->head_page
= list_entry(cpu_buffer->pages.next, struct buffer_page, list);
local_set(&cpu_buffer->head_page->write, 0);
+ local_set(&cpu_buffer->head_page->entries, 0);
local_set(&cpu_buffer->head_page->page->commit, 0);
cpu_buffer->head_page->read = 0;
@@ -2420,11 +2634,15 @@ rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer)
INIT_LIST_HEAD(&cpu_buffer->reader_page->list);
local_set(&cpu_buffer->reader_page->write, 0);
+ local_set(&cpu_buffer->reader_page->entries, 0);
local_set(&cpu_buffer->reader_page->page->commit, 0);
cpu_buffer->reader_page->read = 0;
+ cpu_buffer->nmi_dropped = 0;
+ cpu_buffer->commit_overrun = 0;
cpu_buffer->overrun = 0;
- cpu_buffer->entries = 0;
+ cpu_buffer->read = 0;
+ local_set(&cpu_buffer->entries, 0);
cpu_buffer->write_stamp = 0;
cpu_buffer->read_stamp = 0;
@@ -2443,6 +2661,8 @@ void ring_buffer_reset_cpu(struct ring_buffer *buffer, int cpu)
if (!cpumask_test_cpu(cpu, buffer->cpumask))
return;
+ atomic_inc(&cpu_buffer->record_disabled);
+
spin_lock_irqsave(&cpu_buffer->reader_lock, flags);
__raw_spin_lock(&cpu_buffer->lock);
@@ -2452,6 +2672,8 @@ void ring_buffer_reset_cpu(struct ring_buffer *buffer, int cpu)
__raw_spin_unlock(&cpu_buffer->lock);
spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
+
+ atomic_dec(&cpu_buffer->record_disabled);
}
EXPORT_SYMBOL_GPL(ring_buffer_reset_cpu);
@@ -2578,28 +2800,6 @@ out:
}
EXPORT_SYMBOL_GPL(ring_buffer_swap_cpu);
-static void rb_remove_entries(struct ring_buffer_per_cpu *cpu_buffer,
- struct buffer_data_page *bpage,
- unsigned int offset)
-{
- struct ring_buffer_event *event;
- unsigned long head;
-
- __raw_spin_lock(&cpu_buffer->lock);
- for (head = offset; head < local_read(&bpage->commit);
- head += rb_event_length(event)) {
-
- event = __rb_data_page_index(bpage, head);
- if (RB_WARN_ON(cpu_buffer, rb_null_event(event)))
- return;
- /* Only count data entries */
- if (event->type != RINGBUF_TYPE_DATA)
- continue;
- cpu_buffer->entries--;
- }
- __raw_spin_unlock(&cpu_buffer->lock);
-}
-
/**
* ring_buffer_alloc_read_page - allocate a page to read from buffer
* @buffer: the buffer to allocate for.
@@ -2630,6 +2830,7 @@ void *ring_buffer_alloc_read_page(struct ring_buffer *buffer)
return bpage;
}
+EXPORT_SYMBOL_GPL(ring_buffer_alloc_read_page);
/**
* ring_buffer_free_read_page - free an allocated read page
@@ -2642,6 +2843,7 @@ void ring_buffer_free_read_page(struct ring_buffer *buffer, void *data)
{
free_page((unsigned long)data);
}
+EXPORT_SYMBOL_GPL(ring_buffer_free_read_page);
/**
* ring_buffer_read_page - extract a page from the ring buffer
@@ -2768,16 +2970,17 @@ int ring_buffer_read_page(struct ring_buffer *buffer,
/* we copied everything to the beginning */
read = 0;
} else {
+ /* update the entry counter */
+ cpu_buffer->read += local_read(&reader->entries);
+
/* swap the pages */
rb_init_page(bpage);
bpage = reader->page;
reader->page = *data_page;
local_set(&reader->write, 0);
+ local_set(&reader->entries, 0);
reader->read = 0;
*data_page = bpage;
-
- /* update the entry counter */
- rb_remove_entries(cpu_buffer, bpage, read);
}
ret = read;
@@ -2787,6 +2990,7 @@ int ring_buffer_read_page(struct ring_buffer *buffer,
out:
return ret;
}
+EXPORT_SYMBOL_GPL(ring_buffer_read_page);
static ssize_t
rb_simple_read(struct file *filp, char __user *ubuf,
@@ -2845,14 +3049,11 @@ static const struct file_operations rb_simple_fops = {
static __init int rb_init_debugfs(void)
{
struct dentry *d_tracer;
- struct dentry *entry;
d_tracer = tracing_init_dentry();
- entry = debugfs_create_file("tracing_on", 0644, d_tracer,
- &ring_buffer_flags, &rb_simple_fops);
- if (!entry)
- pr_warning("Could not create debugfs 'tracing_on' entry\n");
+ trace_create_file("tracing_on", 0644, d_tracer,
+ &ring_buffer_flags, &rb_simple_fops);
return 0;
}
diff --git a/kernel/trace/ring_buffer_benchmark.c b/kernel/trace/ring_buffer_benchmark.c
new file mode 100644
index 000000000000..a26fc67b63bb
--- /dev/null
+++ b/kernel/trace/ring_buffer_benchmark.c
@@ -0,0 +1,413 @@
+/*
+ * ring buffer tester and benchmark
+ *
+ * Copyright (C) 2009 Steven Rostedt <srostedt@redhat.com>
+ */
+#include <linux/ring_buffer.h>
+#include <linux/completion.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/time.h>
+
+struct rb_page {
+ u64 ts;
+ local_t commit;
+ char data[4080];
+};
+
+/* run time and sleep time in seconds */
+#define RUN_TIME 10
+#define SLEEP_TIME 10
+
+/* number of events for writer to wake up the reader */
+static int wakeup_interval = 100;
+
+static int reader_finish;
+static struct completion read_start;
+static struct completion read_done;
+
+static struct ring_buffer *buffer;
+static struct task_struct *producer;
+static struct task_struct *consumer;
+static unsigned long read;
+
+static int disable_reader;
+module_param(disable_reader, uint, 0644);
+MODULE_PARM_DESC(disable_reader, "only run producer");
+
+static int read_events;
+
+static int kill_test;
+
+#define KILL_TEST() \
+ do { \
+ if (!kill_test) { \
+ kill_test = 1; \
+ WARN_ON(1); \
+ } \
+ } while (0)
+
+enum event_status {
+ EVENT_FOUND,
+ EVENT_DROPPED,
+};
+
+static enum event_status read_event(int cpu)
+{
+ struct ring_buffer_event *event;
+ int *entry;
+ u64 ts;
+
+ event = ring_buffer_consume(buffer, cpu, &ts);
+ if (!event)
+ return EVENT_DROPPED;
+
+ entry = ring_buffer_event_data(event);
+ if (*entry != cpu) {
+ KILL_TEST();
+ return EVENT_DROPPED;
+ }
+
+ read++;
+ return EVENT_FOUND;
+}
+
+static enum event_status read_page(int cpu)
+{
+ struct ring_buffer_event *event;
+ struct rb_page *rpage;
+ unsigned long commit;
+ void *bpage;
+ int *entry;
+ int ret;
+ int inc;
+ int i;
+
+ bpage = ring_buffer_alloc_read_page(buffer);
+ if (!bpage)
+ return EVENT_DROPPED;
+
+ ret = ring_buffer_read_page(buffer, &bpage, PAGE_SIZE, cpu, 1);
+ if (ret >= 0) {
+ rpage = bpage;
+ commit = local_read(&rpage->commit);
+ for (i = 0; i < commit && !kill_test; i += inc) {
+
+ if (i >= (PAGE_SIZE - offsetof(struct rb_page, data))) {
+ KILL_TEST();
+ break;
+ }
+
+ inc = -1;
+ event = (void *)&rpage->data[i];
+ switch (event->type_len) {
+ case RINGBUF_TYPE_PADDING:
+ /* We don't expect any padding */
+ KILL_TEST();
+ break;
+ case RINGBUF_TYPE_TIME_EXTEND:
+ inc = 8;
+ break;
+ case 0:
+ entry = ring_buffer_event_data(event);
+ if (*entry != cpu) {
+ KILL_TEST();
+ break;
+ }
+ read++;
+ if (!event->array[0]) {
+ KILL_TEST();
+ break;
+ }
+ inc = event->array[0];
+ break;
+ default:
+ entry = ring_buffer_event_data(event);
+ if (*entry != cpu) {
+ KILL_TEST();
+ break;
+ }
+ read++;
+ inc = ((event->type_len + 1) * 4);
+ }
+ if (kill_test)
+ break;
+
+ if (inc <= 0) {
+ KILL_TEST();
+ break;
+ }
+ }
+ }
+ ring_buffer_free_read_page(buffer, bpage);
+
+ if (ret < 0)
+ return EVENT_DROPPED;
+ return EVENT_FOUND;
+}
+
+static void ring_buffer_consumer(void)
+{
+ /* toggle between reading pages and events */
+ read_events ^= 1;
+
+ read = 0;
+ while (!reader_finish && !kill_test) {
+ int found;
+
+ do {
+ int cpu;
+
+ found = 0;
+ for_each_online_cpu(cpu) {
+ enum event_status stat;
+
+ if (read_events)
+ stat = read_event(cpu);
+ else
+ stat = read_page(cpu);
+
+ if (kill_test)
+ break;
+ if (stat == EVENT_FOUND)
+ found = 1;
+ }
+ } while (found && !kill_test);
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (reader_finish)
+ break;
+
+ schedule();
+ __set_current_state(TASK_RUNNING);
+ }
+ reader_finish = 0;
+ complete(&read_done);
+}
+
+/*
+ * If we are a non preempt kernel, the 10 second run will
+ * stop everything while it runs. Instead, we will call cond_resched
+ * and also add any time that was lost by a rescedule.
+ */
+#ifdef CONFIG_PREEMPT
+static void sched_if_needed(struct timeval *start_tv, struct timeval *end_tv)
+{
+}
+#else
+static void sched_if_needed(struct timeval *start_tv, struct timeval *end_tv)
+{
+ struct timeval tv;
+
+ cond_resched();
+ do_gettimeofday(&tv);
+ if (tv.tv_usec < end_tv->tv_usec) {
+ tv.tv_usec += 1000000;
+ tv.tv_sec--;
+ }
+ start_tv->tv_sec += tv.tv_sec - end_tv->tv_sec;
+ start_tv->tv_usec += tv.tv_usec - end_tv->tv_usec;
+ if (start_tv->tv_usec > 1000000) {
+ start_tv->tv_usec -= 1000000;
+ start_tv->tv_sec++;
+ }
+}
+#endif
+
+static void ring_buffer_producer(void)
+{
+ struct timeval start_tv;
+ struct timeval end_tv;
+ unsigned long long time;
+ unsigned long long entries;
+ unsigned long long overruns;
+ unsigned long missed = 0;
+ unsigned long hit = 0;
+ unsigned long avg;
+ int cnt = 0;
+
+ /*
+ * Hammer the buffer for 10 secs (this may
+ * make the system stall)
+ */
+ pr_info("Starting ring buffer hammer\n");
+ do_gettimeofday(&start_tv);
+ do {
+ struct ring_buffer_event *event;
+ int *entry;
+
+ event = ring_buffer_lock_reserve(buffer, 10);
+ if (!event) {
+ missed++;
+ } else {
+ hit++;
+ entry = ring_buffer_event_data(event);
+ *entry = smp_processor_id();
+ ring_buffer_unlock_commit(buffer, event);
+ }
+ do_gettimeofday(&end_tv);
+
+ if (consumer && !(++cnt % wakeup_interval))
+ wake_up_process(consumer);
+
+ sched_if_needed(&start_tv, &end_tv);
+
+ } while (end_tv.tv_sec < (start_tv.tv_sec + RUN_TIME) && !kill_test);
+ pr_info("End ring buffer hammer\n");
+
+ if (consumer) {
+ /* Init both completions here to avoid races */
+ init_completion(&read_start);
+ init_completion(&read_done);
+ /* the completions must be visible before the finish var */
+ smp_wmb();
+ reader_finish = 1;
+ /* finish var visible before waking up the consumer */
+ smp_wmb();
+ wake_up_process(consumer);
+ wait_for_completion(&read_done);
+ }
+
+ time = end_tv.tv_sec - start_tv.tv_sec;
+ time *= 1000000;
+ time += (long long)((long)end_tv.tv_usec - (long)start_tv.tv_usec);
+
+ entries = ring_buffer_entries(buffer);
+ overruns = ring_buffer_overruns(buffer);
+
+ if (kill_test)
+ pr_info("ERROR!\n");
+ pr_info("Time: %lld (usecs)\n", time);
+ pr_info("Overruns: %lld\n", overruns);
+ if (disable_reader)
+ pr_info("Read: (reader disabled)\n");
+ else
+ pr_info("Read: %ld (by %s)\n", read,
+ read_events ? "events" : "pages");
+ pr_info("Entries: %lld\n", entries);
+ pr_info("Total: %lld\n", entries + overruns + read);
+ pr_info("Missed: %ld\n", missed);
+ pr_info("Hit: %ld\n", hit);
+
+ do_div(time, 1000);
+ if (time)
+ hit /= (long)time;
+ else
+ pr_info("TIME IS ZERO??\n");
+
+ pr_info("Entries per millisec: %ld\n", hit);
+
+ if (hit) {
+ avg = 1000000 / hit;
+ pr_info("%ld ns per entry\n", avg);
+ }
+}
+
+static void wait_to_die(void)
+{
+ set_current_state(TASK_INTERRUPTIBLE);
+ while (!kthread_should_stop()) {
+ schedule();
+ set_current_state(TASK_INTERRUPTIBLE);
+ }
+ __set_current_state(TASK_RUNNING);
+}
+
+static int ring_buffer_consumer_thread(void *arg)
+{
+ while (!kthread_should_stop() && !kill_test) {
+ complete(&read_start);
+
+ ring_buffer_consumer();
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (kthread_should_stop() || kill_test)
+ break;
+
+ schedule();
+ __set_current_state(TASK_RUNNING);
+ }
+ __set_current_state(TASK_RUNNING);
+
+ if (kill_test)
+ wait_to_die();
+
+ return 0;
+}
+
+static int ring_buffer_producer_thread(void *arg)
+{
+ init_completion(&read_start);
+
+ while (!kthread_should_stop() && !kill_test) {
+ ring_buffer_reset(buffer);
+
+ if (consumer) {
+ smp_wmb();
+ wake_up_process(consumer);
+ wait_for_completion(&read_start);
+ }
+
+ ring_buffer_producer();
+
+ pr_info("Sleeping for 10 secs\n");
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ * SLEEP_TIME);
+ __set_current_state(TASK_RUNNING);
+ }
+
+ if (kill_test)
+ wait_to_die();
+
+ return 0;
+}
+
+static int __init ring_buffer_benchmark_init(void)
+{
+ int ret;
+
+ /* make a one meg buffer in overwite mode */
+ buffer = ring_buffer_alloc(1000000, RB_FL_OVERWRITE);
+ if (!buffer)
+ return -ENOMEM;
+
+ if (!disable_reader) {
+ consumer = kthread_create(ring_buffer_consumer_thread,
+ NULL, "rb_consumer");
+ ret = PTR_ERR(consumer);
+ if (IS_ERR(consumer))
+ goto out_fail;
+ }
+
+ producer = kthread_run(ring_buffer_producer_thread,
+ NULL, "rb_producer");
+ ret = PTR_ERR(producer);
+
+ if (IS_ERR(producer))
+ goto out_kill;
+
+ return 0;
+
+ out_kill:
+ if (consumer)
+ kthread_stop(consumer);
+
+ out_fail:
+ ring_buffer_free(buffer);
+ return ret;
+}
+
+static void __exit ring_buffer_benchmark_exit(void)
+{
+ kthread_stop(producer);
+ if (consumer)
+ kthread_stop(consumer);
+ ring_buffer_free(buffer);
+}
+
+module_init(ring_buffer_benchmark_init);
+module_exit(ring_buffer_benchmark_exit);
+
+MODULE_AUTHOR("Steven Rostedt");
+MODULE_DESCRIPTION("ring_buffer_benchmark");
+MODULE_LICENSE("GPL");
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 1ce5dc6372b8..dd40d2320346 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -171,6 +171,13 @@ static struct trace_array global_trace;
static DEFINE_PER_CPU(struct trace_array_cpu, global_trace_cpu);
+int filter_current_check_discard(struct ftrace_event_call *call, void *rec,
+ struct ring_buffer_event *event)
+{
+ return filter_check_discard(call, rec, global_trace.buffer, event);
+}
+EXPORT_SYMBOL_GPL(filter_current_check_discard);
+
cycle_t ftrace_now(int cpu)
{
u64 ts;
@@ -255,7 +262,8 @@ static DECLARE_WAIT_QUEUE_HEAD(trace_wait);
/* trace_flags holds trace_options default values */
unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK |
- TRACE_ITER_ANNOTATE | TRACE_ITER_CONTEXT_INFO | TRACE_ITER_SLEEP_TIME;
+ TRACE_ITER_ANNOTATE | TRACE_ITER_CONTEXT_INFO | TRACE_ITER_SLEEP_TIME |
+ TRACE_ITER_GRAPH_TIME;
/**
* trace_wake_up - wake up tasks waiting for trace input
@@ -317,6 +325,7 @@ static const char *trace_options[] = {
"latency-format",
"global-clock",
"sleep-time",
+ "graph-time",
NULL
};
@@ -402,17 +411,6 @@ static ssize_t trace_seq_to_buffer(struct trace_seq *s, void *buf, size_t cnt)
return cnt;
}
-static void
-trace_print_seq(struct seq_file *m, struct trace_seq *s)
-{
- int len = s->len >= PAGE_SIZE ? PAGE_SIZE - 1 : s->len;
-
- s->buffer[len] = 0;
- seq_puts(m, s->buffer);
-
- trace_seq_init(s);
-}
-
/**
* update_max_tr - snapshot all trace buffers from global_trace to max_tr
* @tr: tracer
@@ -641,6 +639,16 @@ void tracing_reset_online_cpus(struct trace_array *tr)
tracing_reset(tr, cpu);
}
+void tracing_reset_current(int cpu)
+{
+ tracing_reset(&global_trace, cpu);
+}
+
+void tracing_reset_current_online_cpus(void)
+{
+ tracing_reset_online_cpus(&global_trace);
+}
+
#define SAVED_CMDLINES 128
#define NO_CMDLINE_MAP UINT_MAX
static unsigned map_pid_to_cmdline[PID_MAX_DEFAULT+1];
@@ -840,7 +848,7 @@ tracing_generic_entry_update(struct trace_entry *entry, unsigned long flags,
}
struct ring_buffer_event *trace_buffer_lock_reserve(struct trace_array *tr,
- unsigned char type,
+ int type,
unsigned long len,
unsigned long flags, int pc)
{
@@ -883,30 +891,40 @@ void trace_buffer_unlock_commit(struct trace_array *tr,
}
struct ring_buffer_event *
-trace_current_buffer_lock_reserve(unsigned char type, unsigned long len,
+trace_current_buffer_lock_reserve(int type, unsigned long len,
unsigned long flags, int pc)
{
return trace_buffer_lock_reserve(&global_trace,
type, len, flags, pc);
}
+EXPORT_SYMBOL_GPL(trace_current_buffer_lock_reserve);
void trace_current_buffer_unlock_commit(struct ring_buffer_event *event,
unsigned long flags, int pc)
{
- return __trace_buffer_unlock_commit(&global_trace, event, flags, pc, 1);
+ __trace_buffer_unlock_commit(&global_trace, event, flags, pc, 1);
}
+EXPORT_SYMBOL_GPL(trace_current_buffer_unlock_commit);
void trace_nowake_buffer_unlock_commit(struct ring_buffer_event *event,
unsigned long flags, int pc)
{
- return __trace_buffer_unlock_commit(&global_trace, event, flags, pc, 0);
+ __trace_buffer_unlock_commit(&global_trace, event, flags, pc, 0);
}
+EXPORT_SYMBOL_GPL(trace_nowake_buffer_unlock_commit);
+
+void trace_current_buffer_discard_commit(struct ring_buffer_event *event)
+{
+ ring_buffer_discard_commit(global_trace.buffer, event);
+}
+EXPORT_SYMBOL_GPL(trace_current_buffer_discard_commit);
void
trace_function(struct trace_array *tr,
unsigned long ip, unsigned long parent_ip, unsigned long flags,
int pc)
{
+ struct ftrace_event_call *call = &event_function;
struct ring_buffer_event *event;
struct ftrace_entry *entry;
@@ -921,7 +939,9 @@ trace_function(struct trace_array *tr,
entry = ring_buffer_event_data(event);
entry->ip = ip;
entry->parent_ip = parent_ip;
- ring_buffer_unlock_commit(tr->buffer, event);
+
+ if (!filter_check_discard(call, entry, tr->buffer, event))
+ ring_buffer_unlock_commit(tr->buffer, event);
}
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
@@ -930,6 +950,7 @@ static int __trace_graph_entry(struct trace_array *tr,
unsigned long flags,
int pc)
{
+ struct ftrace_event_call *call = &event_funcgraph_entry;
struct ring_buffer_event *event;
struct ftrace_graph_ent_entry *entry;
@@ -942,7 +963,8 @@ static int __trace_graph_entry(struct trace_array *tr,
return 0;
entry = ring_buffer_event_data(event);
entry->graph_ent = *trace;
- ring_buffer_unlock_commit(global_trace.buffer, event);
+ if (!filter_current_check_discard(call, entry, event))
+ ring_buffer_unlock_commit(global_trace.buffer, event);
return 1;
}
@@ -952,6 +974,7 @@ static void __trace_graph_return(struct trace_array *tr,
unsigned long flags,
int pc)
{
+ struct ftrace_event_call *call = &event_funcgraph_exit;
struct ring_buffer_event *event;
struct ftrace_graph_ret_entry *entry;
@@ -964,7 +987,8 @@ static void __trace_graph_return(struct trace_array *tr,
return;
entry = ring_buffer_event_data(event);
entry->ret = *trace;
- ring_buffer_unlock_commit(global_trace.buffer, event);
+ if (!filter_current_check_discard(call, entry, event))
+ ring_buffer_unlock_commit(global_trace.buffer, event);
}
#endif
@@ -982,6 +1006,7 @@ static void __ftrace_trace_stack(struct trace_array *tr,
int skip, int pc)
{
#ifdef CONFIG_STACKTRACE
+ struct ftrace_event_call *call = &event_kernel_stack;
struct ring_buffer_event *event;
struct stack_entry *entry;
struct stack_trace trace;
@@ -999,7 +1024,8 @@ static void __ftrace_trace_stack(struct trace_array *tr,
trace.entries = entry->caller;
save_stack_trace(&trace);
- ring_buffer_unlock_commit(tr->buffer, event);
+ if (!filter_check_discard(call, entry, tr->buffer, event))
+ ring_buffer_unlock_commit(tr->buffer, event);
#endif
}
@@ -1024,6 +1050,7 @@ static void ftrace_trace_userstack(struct trace_array *tr,
unsigned long flags, int pc)
{
#ifdef CONFIG_STACKTRACE
+ struct ftrace_event_call *call = &event_user_stack;
struct ring_buffer_event *event;
struct userstack_entry *entry;
struct stack_trace trace;
@@ -1045,7 +1072,8 @@ static void ftrace_trace_userstack(struct trace_array *tr,
trace.entries = entry->caller;
save_stack_trace_user(&trace);
- ring_buffer_unlock_commit(tr->buffer, event);
+ if (!filter_check_discard(call, entry, tr->buffer, event))
+ ring_buffer_unlock_commit(tr->buffer, event);
#endif
}
@@ -1089,6 +1117,7 @@ tracing_sched_switch_trace(struct trace_array *tr,
struct task_struct *next,
unsigned long flags, int pc)
{
+ struct ftrace_event_call *call = &event_context_switch;
struct ring_buffer_event *event;
struct ctx_switch_entry *entry;
@@ -1104,7 +1133,9 @@ tracing_sched_switch_trace(struct trace_array *tr,
entry->next_prio = next->prio;
entry->next_state = next->state;
entry->next_cpu = task_cpu(next);
- trace_buffer_unlock_commit(tr, event, flags, pc);
+
+ if (!filter_check_discard(call, entry, tr->buffer, event))
+ trace_buffer_unlock_commit(tr, event, flags, pc);
}
void
@@ -1113,6 +1144,7 @@ tracing_sched_wakeup_trace(struct trace_array *tr,
struct task_struct *curr,
unsigned long flags, int pc)
{
+ struct ftrace_event_call *call = &event_wakeup;
struct ring_buffer_event *event;
struct ctx_switch_entry *entry;
@@ -1129,7 +1161,8 @@ tracing_sched_wakeup_trace(struct trace_array *tr,
entry->next_state = wakee->state;
entry->next_cpu = task_cpu(wakee);
- ring_buffer_unlock_commit(tr->buffer, event);
+ if (!filter_check_discard(call, entry, tr->buffer, event))
+ ring_buffer_unlock_commit(tr->buffer, event);
ftrace_trace_stack(tr, flags, 6, pc);
ftrace_trace_userstack(tr, flags, pc);
}
@@ -1230,11 +1263,13 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
(raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
static u32 trace_buf[TRACE_BUF_SIZE];
+ struct ftrace_event_call *call = &event_bprint;
struct ring_buffer_event *event;
struct trace_array *tr = &global_trace;
struct trace_array_cpu *data;
struct bprint_entry *entry;
unsigned long flags;
+ int disable;
int resched;
int cpu, len = 0, size, pc;
@@ -1249,7 +1284,8 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
cpu = raw_smp_processor_id();
data = tr->data[cpu];
- if (unlikely(atomic_read(&data->disabled)))
+ disable = atomic_inc_return(&data->disabled);
+ if (unlikely(disable != 1))
goto out;
/* Lockdep uses trace_printk for lock tracing */
@@ -1269,13 +1305,15 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
entry->fmt = fmt;
memcpy(entry->buf, trace_buf, sizeof(u32) * len);
- ring_buffer_unlock_commit(tr->buffer, event);
+ if (!filter_check_discard(call, entry, tr->buffer, event))
+ ring_buffer_unlock_commit(tr->buffer, event);
out_unlock:
__raw_spin_unlock(&trace_buf_lock);
local_irq_restore(flags);
out:
+ atomic_dec_return(&data->disabled);
ftrace_preempt_enable(resched);
unpause_graph_tracing();
@@ -1288,12 +1326,14 @@ int trace_vprintk(unsigned long ip, const char *fmt, va_list args)
static raw_spinlock_t trace_buf_lock = __RAW_SPIN_LOCK_UNLOCKED;
static char trace_buf[TRACE_BUF_SIZE];
+ struct ftrace_event_call *call = &event_print;
struct ring_buffer_event *event;
struct trace_array *tr = &global_trace;
struct trace_array_cpu *data;
int cpu, len = 0, size, pc;
struct print_entry *entry;
unsigned long irq_flags;
+ int disable;
if (tracing_disabled || tracing_selftest_running)
return 0;
@@ -1303,7 +1343,8 @@ int trace_vprintk(unsigned long ip, const char *fmt, va_list args)
cpu = raw_smp_processor_id();
data = tr->data[cpu];
- if (unlikely(atomic_read(&data->disabled)))
+ disable = atomic_inc_return(&data->disabled);
+ if (unlikely(disable != 1))
goto out;
pause_graph_tracing();
@@ -1323,13 +1364,15 @@ int trace_vprintk(unsigned long ip, const char *fmt, va_list args)
memcpy(&entry->buf, trace_buf, len);
entry->buf[len] = 0;
- ring_buffer_unlock_commit(tr->buffer, event);
+ if (!filter_check_discard(call, entry, tr->buffer, event))
+ ring_buffer_unlock_commit(tr->buffer, event);
out_unlock:
__raw_spin_unlock(&trace_buf_lock);
raw_local_irq_restore(irq_flags);
unpause_graph_tracing();
out:
+ atomic_dec_return(&data->disabled);
preempt_enable_notrace();
return len;
@@ -2397,6 +2440,56 @@ static const struct file_operations tracing_readme_fops = {
};
static ssize_t
+tracing_saved_cmdlines_read(struct file *file, char __user *ubuf,
+ size_t cnt, loff_t *ppos)
+{
+ char *buf_comm;
+ char *file_buf;
+ char *buf;
+ int len = 0;
+ int pid;
+ int i;
+
+ file_buf = kmalloc(SAVED_CMDLINES*(16+TASK_COMM_LEN), GFP_KERNEL);
+ if (!file_buf)
+ return -ENOMEM;
+
+ buf_comm = kmalloc(TASK_COMM_LEN, GFP_KERNEL);
+ if (!buf_comm) {
+ kfree(file_buf);
+ return -ENOMEM;
+ }
+
+ buf = file_buf;
+
+ for (i = 0; i < SAVED_CMDLINES; i++) {
+ int r;
+
+ pid = map_cmdline_to_pid[i];
+ if (pid == -1 || pid == NO_CMDLINE_MAP)
+ continue;
+
+ trace_find_cmdline(pid, buf_comm);
+ r = sprintf(buf, "%d %s\n", pid, buf_comm);
+ buf += r;
+ len += r;
+ }
+
+ len = simple_read_from_buffer(ubuf, cnt, ppos,
+ file_buf, len);
+
+ kfree(file_buf);
+ kfree(buf_comm);
+
+ return len;
+}
+
+static const struct file_operations tracing_saved_cmdlines_fops = {
+ .open = tracing_open_generic,
+ .read = tracing_saved_cmdlines_read,
+};
+
+static ssize_t
tracing_ctrl_read(struct file *filp, char __user *ubuf,
size_t cnt, loff_t *ppos)
{
@@ -3425,7 +3518,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
.spd_release = buffer_spd_release,
};
struct buffer_ref *ref;
- int size, i;
+ int entries, size, i;
size_t ret;
if (*ppos & (PAGE_SIZE - 1)) {
@@ -3440,7 +3533,9 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
len &= PAGE_MASK;
}
- for (i = 0; i < PIPE_BUFFERS && len; i++, len -= PAGE_SIZE) {
+ entries = ring_buffer_entries_cpu(info->tr->buffer, info->cpu);
+
+ for (i = 0; i < PIPE_BUFFERS && len && entries; i++, len -= PAGE_SIZE) {
struct page *page;
int r;
@@ -3448,6 +3543,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
if (!ref)
break;
+ ref->ref = 1;
ref->buffer = info->tr->buffer;
ref->page = ring_buffer_alloc_read_page(ref->buffer);
if (!ref->page) {
@@ -3456,7 +3552,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
}
r = ring_buffer_read_page(ref->buffer, &ref->page,
- len, info->cpu, 0);
+ len, info->cpu, 1);
if (r < 0) {
ring_buffer_free_read_page(ref->buffer,
ref->page);
@@ -3480,6 +3576,8 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
spd.partial[i].private = (unsigned long)ref;
spd.nr_pages++;
*ppos += PAGE_SIZE;
+
+ entries = ring_buffer_entries_cpu(info->tr->buffer, info->cpu);
}
spd.nr_pages = i;
@@ -3507,6 +3605,45 @@ static const struct file_operations tracing_buffers_fops = {
.llseek = no_llseek,
};
+static ssize_t
+tracing_stats_read(struct file *filp, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ unsigned long cpu = (unsigned long)filp->private_data;
+ struct trace_array *tr = &global_trace;
+ struct trace_seq *s;
+ unsigned long cnt;
+
+ s = kmalloc(sizeof(*s), GFP_ATOMIC);
+ if (!s)
+ return ENOMEM;
+
+ trace_seq_init(s);
+
+ cnt = ring_buffer_entries_cpu(tr->buffer, cpu);
+ trace_seq_printf(s, "entries: %ld\n", cnt);
+
+ cnt = ring_buffer_overrun_cpu(tr->buffer, cpu);
+ trace_seq_printf(s, "overrun: %ld\n", cnt);
+
+ cnt = ring_buffer_commit_overrun_cpu(tr->buffer, cpu);
+ trace_seq_printf(s, "commit overrun: %ld\n", cnt);
+
+ cnt = ring_buffer_nmi_dropped_cpu(tr->buffer, cpu);
+ trace_seq_printf(s, "nmi dropped: %ld\n", cnt);
+
+ count = simple_read_from_buffer(ubuf, count, ppos, s->buffer, s->len);
+
+ kfree(s);
+
+ return count;
+}
+
+static const struct file_operations tracing_stats_fops = {
+ .open = tracing_open_generic,
+ .read = tracing_stats_read,
+};
+
#ifdef CONFIG_DYNAMIC_FTRACE
int __weak ftrace_arch_read_dyn_info(char *buf, int size)
@@ -3596,7 +3733,7 @@ struct dentry *tracing_dentry_percpu(void)
static void tracing_init_debugfs_percpu(long cpu)
{
struct dentry *d_percpu = tracing_dentry_percpu();
- struct dentry *entry, *d_cpu;
+ struct dentry *d_cpu;
/* strlen(cpu) + MAX(log10(cpu)) + '\0' */
char cpu_dir[7];
@@ -3611,21 +3748,18 @@ static void tracing_init_debugfs_percpu(long cpu)
}
/* per cpu trace_pipe */
- entry = debugfs_create_file("trace_pipe", 0444, d_cpu,
- (void *) cpu, &tracing_pipe_fops);
- if (!entry)
- pr_warning("Could not create debugfs 'trace_pipe' entry\n");
+ trace_create_file("trace_pipe", 0444, d_cpu,
+ (void *) cpu, &tracing_pipe_fops);
/* per cpu trace */
- entry = debugfs_create_file("trace", 0644, d_cpu,
- (void *) cpu, &tracing_fops);
- if (!entry)
- pr_warning("Could not create debugfs 'trace' entry\n");
+ trace_create_file("trace", 0644, d_cpu,
+ (void *) cpu, &tracing_fops);
- entry = debugfs_create_file("trace_pipe_raw", 0444, d_cpu,
- (void *) cpu, &tracing_buffers_fops);
- if (!entry)
- pr_warning("Could not create debugfs 'trace_pipe_raw' entry\n");
+ trace_create_file("trace_pipe_raw", 0444, d_cpu,
+ (void *) cpu, &tracing_buffers_fops);
+
+ trace_create_file("stats", 0444, d_cpu,
+ (void *) cpu, &tracing_stats_fops);
}
#ifdef CONFIG_FTRACE_SELFTEST
@@ -3781,6 +3915,22 @@ static const struct file_operations trace_options_core_fops = {
.write = trace_options_core_write,
};
+struct dentry *trace_create_file(const char *name,
+ mode_t mode,
+ struct dentry *parent,
+ void *data,
+ const struct file_operations *fops)
+{
+ struct dentry *ret;
+
+ ret = debugfs_create_file(name, mode, parent, data, fops);
+ if (!ret)
+ pr_warning("Could not create debugfs '%s' entry\n", name);
+
+ return ret;
+}
+
+
static struct dentry *trace_options_init_dentry(void)
{
struct dentry *d_tracer;
@@ -3808,7 +3958,6 @@ create_trace_option_file(struct trace_option_dentry *topt,
struct tracer_opt *opt)
{
struct dentry *t_options;
- struct dentry *entry;
t_options = trace_options_init_dentry();
if (!t_options)
@@ -3817,11 +3966,9 @@ create_trace_option_file(struct trace_option_dentry *topt,
topt->flags = flags;
topt->opt = opt;
- entry = debugfs_create_file(opt->name, 0644, t_options, topt,
+ topt->entry = trace_create_file(opt->name, 0644, t_options, topt,
&trace_options_fops);
- topt->entry = entry;
-
}
static struct trace_option_dentry *
@@ -3876,123 +4023,84 @@ static struct dentry *
create_trace_option_core_file(const char *option, long index)
{
struct dentry *t_options;
- struct dentry *entry;
t_options = trace_options_init_dentry();
if (!t_options)
return NULL;
- entry = debugfs_create_file(option, 0644, t_options, (void *)index,
+ return trace_create_file(option, 0644, t_options, (void *)index,
&trace_options_core_fops);
-
- return entry;
}
static __init void create_trace_options_dir(void)
{
struct dentry *t_options;
- struct dentry *entry;
int i;
t_options = trace_options_init_dentry();
if (!t_options)
return;
- for (i = 0; trace_options[i]; i++) {
- entry = create_trace_option_core_file(trace_options[i], i);
- if (!entry)
- pr_warning("Could not create debugfs %s entry\n",
- trace_options[i]);
- }
+ for (i = 0; trace_options[i]; i++)
+ create_trace_option_core_file(trace_options[i], i);
}
static __init int tracer_init_debugfs(void)
{
struct dentry *d_tracer;
- struct dentry *entry;
int cpu;
d_tracer = tracing_init_dentry();
- entry = debugfs_create_file("tracing_enabled", 0644, d_tracer,
- &global_trace, &tracing_ctrl_fops);
- if (!entry)
- pr_warning("Could not create debugfs 'tracing_enabled' entry\n");
+ trace_create_file("tracing_enabled", 0644, d_tracer,
+ &global_trace, &tracing_ctrl_fops);
- entry = debugfs_create_file("trace_options", 0644, d_tracer,
- NULL, &tracing_iter_fops);
- if (!entry)
- pr_warning("Could not create debugfs 'trace_options' entry\n");
+ trace_create_file("trace_options", 0644, d_tracer,
+ NULL, &tracing_iter_fops);
- create_trace_options_dir();
+ trace_create_file("tracing_cpumask", 0644, d_tracer,
+ NULL, &tracing_cpumask_fops);
+
+ trace_create_file("trace", 0644, d_tracer,
+ (void *) TRACE_PIPE_ALL_CPU, &tracing_fops);
+
+ trace_create_file("available_tracers", 0444, d_tracer,
+ &global_trace, &show_traces_fops);
- entry = debugfs_create_file("tracing_cpumask", 0644, d_tracer,
- NULL, &tracing_cpumask_fops);
- if (!entry)
- pr_warning("Could not create debugfs 'tracing_cpumask' entry\n");
-
- entry = debugfs_create_file("trace", 0644, d_tracer,
- (void *) TRACE_PIPE_ALL_CPU, &tracing_fops);
- if (!entry)
- pr_warning("Could not create debugfs 'trace' entry\n");
-
- entry = debugfs_create_file("available_tracers", 0444, d_tracer,
- &global_trace, &show_traces_fops);
- if (!entry)
- pr_warning("Could not create debugfs 'available_tracers' entry\n");
-
- entry = debugfs_create_file("current_tracer", 0444, d_tracer,
- &global_trace, &set_tracer_fops);
- if (!entry)
- pr_warning("Could not create debugfs 'current_tracer' entry\n");
-
- entry = debugfs_create_file("tracing_max_latency", 0644, d_tracer,
- &tracing_max_latency,
- &tracing_max_lat_fops);
- if (!entry)
- pr_warning("Could not create debugfs "
- "'tracing_max_latency' entry\n");
-
- entry = debugfs_create_file("tracing_thresh", 0644, d_tracer,
- &tracing_thresh, &tracing_max_lat_fops);
- if (!entry)
- pr_warning("Could not create debugfs "
- "'tracing_thresh' entry\n");
- entry = debugfs_create_file("README", 0644, d_tracer,
- NULL, &tracing_readme_fops);
- if (!entry)
- pr_warning("Could not create debugfs 'README' entry\n");
-
- entry = debugfs_create_file("trace_pipe", 0444, d_tracer,
+ trace_create_file("current_tracer", 0644, d_tracer,
+ &global_trace, &set_tracer_fops);
+
+ trace_create_file("tracing_max_latency", 0644, d_tracer,
+ &tracing_max_latency, &tracing_max_lat_fops);
+
+ trace_create_file("tracing_thresh", 0644, d_tracer,
+ &tracing_thresh, &tracing_max_lat_fops);
+
+ trace_create_file("README", 0444, d_tracer,
+ NULL, &tracing_readme_fops);
+
+ trace_create_file("trace_pipe", 0444, d_tracer,
(void *) TRACE_PIPE_ALL_CPU, &tracing_pipe_fops);
- if (!entry)
- pr_warning("Could not create debugfs "
- "'trace_pipe' entry\n");
-
- entry = debugfs_create_file("buffer_size_kb", 0644, d_tracer,
- &global_trace, &tracing_entries_fops);
- if (!entry)
- pr_warning("Could not create debugfs "
- "'buffer_size_kb' entry\n");
-
- entry = debugfs_create_file("trace_marker", 0220, d_tracer,
- NULL, &tracing_mark_fops);
- if (!entry)
- pr_warning("Could not create debugfs "
- "'trace_marker' entry\n");
+
+ trace_create_file("buffer_size_kb", 0644, d_tracer,
+ &global_trace, &tracing_entries_fops);
+
+ trace_create_file("trace_marker", 0220, d_tracer,
+ NULL, &tracing_mark_fops);
+
+ trace_create_file("saved_cmdlines", 0444, d_tracer,
+ NULL, &tracing_saved_cmdlines_fops);
#ifdef CONFIG_DYNAMIC_FTRACE
- entry = debugfs_create_file("dyn_ftrace_total_info", 0444, d_tracer,
- &ftrace_update_tot_cnt,
- &tracing_dyn_info_fops);
- if (!entry)
- pr_warning("Could not create debugfs "
- "'dyn_ftrace_total_info' entry\n");
+ trace_create_file("dyn_ftrace_total_info", 0444, d_tracer,
+ &ftrace_update_tot_cnt, &tracing_dyn_info_fops);
#endif
#ifdef CONFIG_SYSPROF_TRACER
init_tracer_sysprof_debugfs(d_tracer);
#endif
+ create_trace_options_dir();
+
for_each_tracing_cpu(cpu)
tracing_init_debugfs_percpu(cpu);
@@ -4063,7 +4171,8 @@ trace_printk_seq(struct trace_seq *s)
static void __ftrace_dump(bool disable_tracing)
{
- static DEFINE_SPINLOCK(ftrace_dump_lock);
+ static raw_spinlock_t ftrace_dump_lock =
+ (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
/* use static because iter can be a bit big for the stack */
static struct trace_iterator iter;
unsigned int old_userobj;
@@ -4072,7 +4181,8 @@ static void __ftrace_dump(bool disable_tracing)
int cnt = 0, cpu;
/* only one dump */
- spin_lock_irqsave(&ftrace_dump_lock, flags);
+ local_irq_save(flags);
+ __raw_spin_lock(&ftrace_dump_lock);
if (dump_ran)
goto out;
@@ -4144,7 +4254,8 @@ static void __ftrace_dump(bool disable_tracing)
}
out:
- spin_unlock_irqrestore(&ftrace_dump_lock, flags);
+ __raw_spin_unlock(&ftrace_dump_lock);
+ local_irq_restore(flags);
}
/* By default: disable tracing after the dump */
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index e685ac2b2ba1..6e735d4771f8 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -9,9 +9,12 @@
#include <linux/mmiotrace.h>
#include <linux/ftrace.h>
#include <trace/boot.h>
-#include <trace/kmemtrace.h>
+#include <linux/kmemtrace.h>
#include <trace/power.h>
+#include <linux/trace_seq.h>
+#include <linux/ftrace_event.h>
+
enum trace_type {
__TRACE_FIRST_TYPE = 0,
@@ -42,20 +45,6 @@ enum trace_type {
};
/*
- * The trace entry - the most basic unit of tracing. This is what
- * is printed in the end as a single line in the trace output, such as:
- *
- * bash-15816 [01] 235.197585: idle_cpu <- irq_enter
- */
-struct trace_entry {
- unsigned char type;
- unsigned char flags;
- unsigned char preempt_count;
- int pid;
- int tgid;
-};
-
-/*
* Function trace entry - function address and parent function addres:
*/
struct ftrace_entry {
@@ -263,8 +252,6 @@ struct trace_array_cpu {
char comm[TASK_COMM_LEN];
};
-struct trace_iterator;
-
/*
* The trace array - an array of per-CPU trace arrays. This is the
* highest level data structure that individual tracers deal with.
@@ -339,15 +326,6 @@ extern void __ftrace_bad_type(void);
__ftrace_bad_type(); \
} while (0)
-/* Return values for print_line callback */
-enum print_line_t {
- TRACE_TYPE_PARTIAL_LINE = 0, /* Retry after flushing the seq */
- TRACE_TYPE_HANDLED = 1,
- TRACE_TYPE_UNHANDLED = 2, /* Relay to other output functions */
- TRACE_TYPE_NO_CONSUME = 3 /* Handled but ask to not consume */
-};
-
-
/*
* An option specific to a tracer. This is a boolean value.
* The bit is the bit index that sets its value on the
@@ -423,60 +401,30 @@ struct tracer {
struct tracer_stat *stats;
};
-struct trace_seq {
- unsigned char buffer[PAGE_SIZE];
- unsigned int len;
- unsigned int readpos;
-};
-
-static inline void
-trace_seq_init(struct trace_seq *s)
-{
- s->len = 0;
- s->readpos = 0;
-}
-
#define TRACE_PIPE_ALL_CPU -1
-/*
- * Trace iterator - used by printout routines who present trace
- * results to users and which routines might sleep, etc:
- */
-struct trace_iterator {
- struct trace_array *tr;
- struct tracer *trace;
- void *private;
- int cpu_file;
- struct mutex mutex;
- struct ring_buffer_iter *buffer_iter[NR_CPUS];
-
- /* The below is zeroed out in pipe_read */
- struct trace_seq seq;
- struct trace_entry *ent;
- int cpu;
- u64 ts;
-
- unsigned long iter_flags;
- loff_t pos;
- long idx;
-
- cpumask_var_t started;
-};
-
int tracer_init(struct tracer *t, struct trace_array *tr);
int tracing_is_enabled(void);
void trace_wake_up(void);
void tracing_reset(struct trace_array *tr, int cpu);
void tracing_reset_online_cpus(struct trace_array *tr);
+void tracing_reset_current(int cpu);
+void tracing_reset_current_online_cpus(void);
int tracing_open_generic(struct inode *inode, struct file *filp);
+struct dentry *trace_create_file(const char *name,
+ mode_t mode,
+ struct dentry *parent,
+ void *data,
+ const struct file_operations *fops);
+
struct dentry *tracing_init_dentry(void);
void init_tracer_sysprof_debugfs(struct dentry *d_tracer);
struct ring_buffer_event;
struct ring_buffer_event *trace_buffer_lock_reserve(struct trace_array *tr,
- unsigned char type,
+ int type,
unsigned long len,
unsigned long flags,
int pc);
@@ -484,14 +432,6 @@ void trace_buffer_unlock_commit(struct trace_array *tr,
struct ring_buffer_event *event,
unsigned long flags, int pc);
-struct ring_buffer_event *
-trace_current_buffer_lock_reserve(unsigned char type, unsigned long len,
- unsigned long flags, int pc);
-void trace_current_buffer_unlock_commit(struct ring_buffer_event *event,
- unsigned long flags, int pc);
-void trace_nowake_buffer_unlock_commit(struct ring_buffer_event *event,
- unsigned long flags, int pc);
-
struct trace_entry *tracing_get_trace_entry(struct trace_array *tr,
struct trace_array_cpu *data);
@@ -514,7 +454,6 @@ void tracing_sched_switch_trace(struct trace_array *tr,
struct task_struct *prev,
struct task_struct *next,
unsigned long flags, int pc);
-void tracing_record_cmdline(struct task_struct *tsk);
void tracing_sched_wakeup_trace(struct trace_array *tr,
struct task_struct *wakee,
@@ -599,6 +538,8 @@ extern int trace_selftest_startup_sysprof(struct tracer *trace,
struct trace_array *tr);
extern int trace_selftest_startup_branch(struct tracer *trace,
struct trace_array *tr);
+extern int trace_selftest_startup_hw_branches(struct tracer *trace,
+ struct trace_array *tr);
#endif /* CONFIG_FTRACE_STARTUP_TEST */
extern void *head_page(struct trace_array_cpu *data);
@@ -613,6 +554,8 @@ extern unsigned long trace_flags;
/* Standard output formatting function used for function return traces */
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
extern enum print_line_t print_graph_function(struct trace_iterator *iter);
+extern enum print_line_t
+trace_print_graph_duration(unsigned long long duration, struct trace_seq *s);
#ifdef CONFIG_DYNAMIC_FTRACE
/* TODO: make this variable */
@@ -644,7 +587,6 @@ static inline int ftrace_graph_addr(unsigned long addr)
return 1;
}
#endif /* CONFIG_DYNAMIC_FTRACE */
-
#else /* CONFIG_FUNCTION_GRAPH_TRACER */
static inline enum print_line_t
print_graph_function(struct trace_iterator *iter)
@@ -692,6 +634,7 @@ enum trace_iterator_flags {
TRACE_ITER_LATENCY_FMT = 0x40000,
TRACE_ITER_GLOBAL_CLK = 0x80000,
TRACE_ITER_SLEEP_TIME = 0x100000,
+ TRACE_ITER_GRAPH_TIME = 0x200000,
};
/*
@@ -790,103 +733,113 @@ struct ftrace_event_field {
char *type;
int offset;
int size;
+ int is_signed;
};
-struct ftrace_event_call {
- char *name;
- char *system;
- struct dentry *dir;
- int enabled;
- int (*regfunc)(void);
- void (*unregfunc)(void);
- int id;
- int (*raw_init)(void);
- int (*show_format)(struct trace_seq *s);
- int (*define_fields)(void);
- struct list_head fields;
+struct event_filter {
+ int n_preds;
struct filter_pred **preds;
-
-#ifdef CONFIG_EVENT_PROFILE
- atomic_t profile_count;
- int (*profile_enable)(struct ftrace_event_call *);
- void (*profile_disable)(struct ftrace_event_call *);
-#endif
+ char *filter_string;
};
struct event_subsystem {
struct list_head list;
const char *name;
struct dentry *entry;
- struct filter_pred **preds;
+ void *filter;
};
-#define events_for_each(event) \
- for (event = __start_ftrace_events; \
- (unsigned long)event < (unsigned long)__stop_ftrace_events; \
- event++)
-
-#define MAX_FILTER_PRED 8
-
struct filter_pred;
-typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event);
+typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event,
+ int val1, int val2);
struct filter_pred {
filter_pred_fn_t fn;
u64 val;
- char *str_val;
+ char str_val[MAX_FILTER_STR_VAL];
int str_len;
char *field_name;
int offset;
int not;
- int or;
- int compound;
- int clear;
+ int op;
+ int pop_n;
};
-int trace_define_field(struct ftrace_event_call *call, char *type,
- char *name, int offset, int size);
-extern void filter_free_pred(struct filter_pred *pred);
-extern void filter_print_preds(struct filter_pred **preds,
+extern void print_event_filter(struct ftrace_event_call *call,
struct trace_seq *s);
-extern int filter_parse(char **pbuf, struct filter_pred *pred);
-extern int filter_add_pred(struct ftrace_event_call *call,
- struct filter_pred *pred);
-extern void filter_free_preds(struct ftrace_event_call *call);
-extern int filter_match_preds(struct ftrace_event_call *call, void *rec);
-extern void filter_free_subsystem_preds(struct event_subsystem *system);
-extern int filter_add_subsystem_pred(struct event_subsystem *system,
- struct filter_pred *pred);
-
-void event_trace_printk(unsigned long ip, const char *fmt, ...);
-extern struct ftrace_event_call __start_ftrace_events[];
-extern struct ftrace_event_call __stop_ftrace_events[];
-
-#define for_each_event(event) \
- for (event = __start_ftrace_events; \
- (unsigned long)event < (unsigned long)__stop_ftrace_events; \
- event++)
+extern int apply_event_filter(struct ftrace_event_call *call,
+ char *filter_string);
+extern int apply_subsystem_event_filter(struct event_subsystem *system,
+ char *filter_string);
+extern void print_subsystem_event_filter(struct event_subsystem *system,
+ struct trace_seq *s);
+
+static inline int
+filter_check_discard(struct ftrace_event_call *call, void *rec,
+ struct ring_buffer *buffer,
+ struct ring_buffer_event *event)
+{
+ if (unlikely(call->filter_active) && !filter_match_preds(call, rec)) {
+ ring_buffer_discard_commit(buffer, event);
+ return 1;
+ }
+
+ return 0;
+}
+
+#define DEFINE_COMPARISON_PRED(type) \
+static int filter_pred_##type(struct filter_pred *pred, void *event, \
+ int val1, int val2) \
+{ \
+ type *addr = (type *)(event + pred->offset); \
+ type val = (type)pred->val; \
+ int match = 0; \
+ \
+ switch (pred->op) { \
+ case OP_LT: \
+ match = (*addr < val); \
+ break; \
+ case OP_LE: \
+ match = (*addr <= val); \
+ break; \
+ case OP_GT: \
+ match = (*addr > val); \
+ break; \
+ case OP_GE: \
+ match = (*addr >= val); \
+ break; \
+ default: \
+ break; \
+ } \
+ \
+ return match; \
+}
+
+#define DEFINE_EQUALITY_PRED(size) \
+static int filter_pred_##size(struct filter_pred *pred, void *event, \
+ int val1, int val2) \
+{ \
+ u##size *addr = (u##size *)(event + pred->offset); \
+ u##size val = (u##size)pred->val; \
+ int match; \
+ \
+ match = (val == *addr) ^ pred->not; \
+ \
+ return match; \
+}
+
+extern struct mutex event_mutex;
+extern struct list_head ftrace_events;
extern const char *__start___trace_bprintk_fmt[];
extern const char *__stop___trace_bprintk_fmt[];
-/*
- * The double __builtin_constant_p is because gcc will give us an error
- * if we try to allocate the static variable to fmt if it is not a
- * constant. Even with the outer if statement optimizing out.
- */
-#define event_trace_printk(ip, fmt, args...) \
-do { \
- __trace_printk_check_format(fmt, ##args); \
- tracing_record_cmdline(current); \
- if (__builtin_constant_p(fmt)) { \
- static const char *trace_printk_fmt \
- __attribute__((section("__trace_printk_fmt"))) = \
- __builtin_constant_p(fmt) ? fmt : NULL; \
- \
- __trace_bprintk(ip, trace_printk_fmt, ##args); \
- } else \
- __trace_printk(ip, fmt, ##args); \
-} while (0)
+#undef TRACE_EVENT_FORMAT
+#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt) \
+ extern struct ftrace_event_call event_##call;
+#undef TRACE_EVENT_FORMAT_NOFILTER
+#define TRACE_EVENT_FORMAT_NOFILTER(call, proto, args, fmt, tstruct, tpfmt)
+#include "trace_event_types.h"
#endif /* _LINUX_KERNEL_TRACE_H */
diff --git a/kernel/trace/trace_boot.c b/kernel/trace/trace_boot.c
index 7a30fc4c3642..a29ef23ffb47 100644
--- a/kernel/trace/trace_boot.c
+++ b/kernel/trace/trace_boot.c
@@ -9,6 +9,7 @@
#include <linux/debugfs.h>
#include <linux/ftrace.h>
#include <linux/kallsyms.h>
+#include <linux/time.h>
#include "trace.h"
#include "trace_output.h"
@@ -67,7 +68,7 @@ initcall_call_print_line(struct trace_iterator *iter)
trace_assign_type(field, entry);
call = &field->boot_call;
ts = iter->ts;
- nsec_rem = do_div(ts, 1000000000);
+ nsec_rem = do_div(ts, NSEC_PER_SEC);
ret = trace_seq_printf(s, "[%5ld.%09ld] calling %s @ %i\n",
(unsigned long)ts, nsec_rem, call->func, call->caller);
@@ -92,7 +93,7 @@ initcall_ret_print_line(struct trace_iterator *iter)
trace_assign_type(field, entry);
init_ret = &field->boot_ret;
ts = iter->ts;
- nsec_rem = do_div(ts, 1000000000);
+ nsec_rem = do_div(ts, NSEC_PER_SEC);
ret = trace_seq_printf(s, "[%5ld.%09ld] initcall %s "
"returned %d after %llu msecs\n",
diff --git a/kernel/trace/trace_branch.c b/kernel/trace/trace_branch.c
index ad8c22efff41..7a7a9fd249a9 100644
--- a/kernel/trace/trace_branch.c
+++ b/kernel/trace/trace_branch.c
@@ -30,6 +30,7 @@ static struct trace_array *branch_tracer;
static void
probe_likely_condition(struct ftrace_branch_data *f, int val, int expect)
{
+ struct ftrace_event_call *call = &event_branch;
struct trace_array *tr = branch_tracer;
struct ring_buffer_event *event;
struct trace_branch *entry;
@@ -73,7 +74,8 @@ probe_likely_condition(struct ftrace_branch_data *f, int val, int expect)
entry->line = f->line;
entry->correct = val == expect;
- ring_buffer_unlock_commit(tr->buffer, event);
+ if (!filter_check_discard(call, entry, tr->buffer, event))
+ ring_buffer_unlock_commit(tr->buffer, event);
out:
atomic_dec(&tr->data[cpu]->disabled);
@@ -155,6 +157,13 @@ static enum print_line_t trace_branch_print(struct trace_iterator *iter,
return TRACE_TYPE_HANDLED;
}
+static void branch_print_header(struct seq_file *s)
+{
+ seq_puts(s, "# TASK-PID CPU# TIMESTAMP CORRECT"
+ " FUNC:FILE:LINE\n");
+ seq_puts(s, "# | | | | | "
+ " |\n");
+}
static struct trace_event trace_branch_event = {
.type = TRACE_BRANCH,
@@ -169,6 +178,7 @@ static struct tracer branch_trace __read_mostly =
#ifdef CONFIG_FTRACE_SELFTEST
.selftest = trace_selftest_startup_branch,
#endif /* CONFIG_FTRACE_SELFTEST */
+ .print_header = branch_print_header,
};
__init static int init_branch_tracer(void)
@@ -263,7 +273,7 @@ static int branch_stat_show(struct seq_file *m, void *v)
return 0;
}
-static void *annotated_branch_stat_start(void)
+static void *annotated_branch_stat_start(struct tracer_stat *trace)
{
return __start_annotated_branch_profile;
}
@@ -338,7 +348,7 @@ static int all_branch_stat_headers(struct seq_file *m)
return 0;
}
-static void *all_branch_stat_start(void)
+static void *all_branch_stat_start(struct tracer_stat *trace)
{
return __start_branch_profile;
}
diff --git a/kernel/trace/trace_event_profile.c b/kernel/trace/trace_event_profile.c
index 22cba9970776..5b5895afecfe 100644
--- a/kernel/trace/trace_event_profile.c
+++ b/kernel/trace/trace_event_profile.c
@@ -10,22 +10,30 @@
int ftrace_profile_enable(int event_id)
{
struct ftrace_event_call *event;
+ int ret = -EINVAL;
- for_each_event(event) {
- if (event->id == event_id)
- return event->profile_enable(event);
+ mutex_lock(&event_mutex);
+ list_for_each_entry(event, &ftrace_events, list) {
+ if (event->id == event_id) {
+ ret = event->profile_enable(event);
+ break;
+ }
}
+ mutex_unlock(&event_mutex);
- return -EINVAL;
+ return ret;
}
void ftrace_profile_disable(int event_id)
{
struct ftrace_event_call *event;
- for_each_event(event) {
- if (event->id == event_id)
- return event->profile_disable(event);
+ mutex_lock(&event_mutex);
+ list_for_each_entry(event, &ftrace_events, list) {
+ if (event->id == event_id) {
+ event->profile_disable(event);
+ break;
+ }
}
+ mutex_unlock(&event_mutex);
}
-
diff --git a/kernel/trace/trace_event_types.h b/kernel/trace/trace_event_types.h
index fd78bee71dd7..5e32e375134d 100644
--- a/kernel/trace/trace_event_types.h
+++ b/kernel/trace/trace_event_types.h
@@ -57,7 +57,7 @@ TRACE_EVENT_FORMAT(context_switch, TRACE_CTX, ctx_switch_entry, ignore,
TP_RAW_FMT("%u:%u:%u ==+ %u:%u:%u [%03u]")
);
-TRACE_EVENT_FORMAT(special, TRACE_SPECIAL, special_entry, ignore,
+TRACE_EVENT_FORMAT_NOFILTER(special, TRACE_SPECIAL, special_entry, ignore,
TRACE_STRUCT(
TRACE_FIELD(unsigned long, arg1, arg1)
TRACE_FIELD(unsigned long, arg2, arg2)
@@ -122,8 +122,10 @@ TRACE_EVENT_FORMAT(print, TRACE_PRINT, print_entry, ignore,
TRACE_EVENT_FORMAT(branch, TRACE_BRANCH, trace_branch, ignore,
TRACE_STRUCT(
TRACE_FIELD(unsigned int, line, line)
- TRACE_FIELD_SPECIAL(char func[TRACE_FUNC_SIZE+1], func, func)
- TRACE_FIELD_SPECIAL(char file[TRACE_FUNC_SIZE+1], file, file)
+ TRACE_FIELD_SPECIAL(char func[TRACE_FUNC_SIZE+1], func,
+ TRACE_FUNC_SIZE+1, func)
+ TRACE_FIELD_SPECIAL(char file[TRACE_FUNC_SIZE+1], file,
+ TRACE_FUNC_SIZE+1, file)
TRACE_FIELD(char, correct, correct)
),
TP_RAW_FMT("%u:%s:%s (%u)")
@@ -139,8 +141,8 @@ TRACE_EVENT_FORMAT(hw_branch, TRACE_HW_BRANCHES, hw_branch_entry, ignore,
TRACE_EVENT_FORMAT(power, TRACE_POWER, trace_power, ignore,
TRACE_STRUCT(
- TRACE_FIELD(ktime_t, state_data.stamp, stamp)
- TRACE_FIELD(ktime_t, state_data.end, end)
+ TRACE_FIELD_SIGN(ktime_t, state_data.stamp, stamp, 1)
+ TRACE_FIELD_SIGN(ktime_t, state_data.end, end, 1)
TRACE_FIELD(int, state_data.type, type)
TRACE_FIELD(int, state_data.state, state)
),
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 576f4fa2af0d..87feb0117ce2 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -8,19 +8,25 @@
*
*/
+#include <linux/workqueue.h>
+#include <linux/spinlock.h>
+#include <linux/kthread.h>
#include <linux/debugfs.h>
#include <linux/uaccess.h>
#include <linux/module.h>
#include <linux/ctype.h>
+#include <linux/delay.h>
#include "trace_output.h"
#define TRACE_SYSTEM "TRACE_SYSTEM"
-static DEFINE_MUTEX(event_mutex);
+DEFINE_MUTEX(event_mutex);
+
+LIST_HEAD(ftrace_events);
int trace_define_field(struct ftrace_event_call *call, char *type,
- char *name, int offset, int size)
+ char *name, int offset, int size, int is_signed)
{
struct ftrace_event_field *field;
@@ -38,6 +44,7 @@ int trace_define_field(struct ftrace_event_call *call, char *type,
field->offset = offset;
field->size = size;
+ field->is_signed = is_signed;
list_add(&field->link, &call->fields);
return 0;
@@ -51,20 +58,37 @@ err:
return -ENOMEM;
}
+EXPORT_SYMBOL_GPL(trace_define_field);
-static void ftrace_clear_events(void)
+#ifdef CONFIG_MODULES
+
+static void trace_destroy_fields(struct ftrace_event_call *call)
{
- struct ftrace_event_call *call = (void *)__start_ftrace_events;
+ struct ftrace_event_field *field, *next;
+ list_for_each_entry_safe(field, next, &call->fields, link) {
+ list_del(&field->link);
+ kfree(field->type);
+ kfree(field->name);
+ kfree(field);
+ }
+}
+
+#endif /* CONFIG_MODULES */
+
+static void ftrace_clear_events(void)
+{
+ struct ftrace_event_call *call;
- while ((unsigned long)call < (unsigned long)__stop_ftrace_events) {
+ mutex_lock(&event_mutex);
+ list_for_each_entry(call, &ftrace_events, list) {
if (call->enabled) {
call->enabled = 0;
call->unregfunc();
}
- call++;
}
+ mutex_unlock(&event_mutex);
}
static void ftrace_event_enable_disable(struct ftrace_event_call *call,
@@ -89,7 +113,7 @@ static void ftrace_event_enable_disable(struct ftrace_event_call *call,
static int ftrace_set_clr_event(char *buf, int set)
{
- struct ftrace_event_call *call = __start_ftrace_events;
+ struct ftrace_event_call *call;
char *event = NULL, *sub = NULL, *match;
int ret = -EINVAL;
@@ -118,7 +142,7 @@ static int ftrace_set_clr_event(char *buf, int set)
}
mutex_lock(&event_mutex);
- for_each_event(call) {
+ list_for_each_entry(call, &ftrace_events, list) {
if (!call->name || !call->regfunc)
continue;
@@ -224,15 +248,17 @@ ftrace_event_write(struct file *file, const char __user *ubuf,
static void *
t_next(struct seq_file *m, void *v, loff_t *pos)
{
- struct ftrace_event_call *call = m->private;
- struct ftrace_event_call *next = call;
+ struct list_head *list = m->private;
+ struct ftrace_event_call *call;
(*pos)++;
for (;;) {
- if ((unsigned long)call >= (unsigned long)__stop_ftrace_events)
+ if (list == &ftrace_events)
return NULL;
+ call = list_entry(list, struct ftrace_event_call, list);
+
/*
* The ftrace subsystem is for showing formats only.
* They can not be enabled or disabled via the event files.
@@ -240,45 +266,51 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
if (call->regfunc)
break;
- call++;
- next = call;
+ list = list->next;
}
- m->private = ++next;
+ m->private = list->next;
return call;
}
static void *t_start(struct seq_file *m, loff_t *pos)
{
+ mutex_lock(&event_mutex);
+ if (*pos == 0)
+ m->private = ftrace_events.next;
return t_next(m, NULL, pos);
}
static void *
s_next(struct seq_file *m, void *v, loff_t *pos)
{
- struct ftrace_event_call *call = m->private;
- struct ftrace_event_call *next;
+ struct list_head *list = m->private;
+ struct ftrace_event_call *call;
(*pos)++;
retry:
- if ((unsigned long)call >= (unsigned long)__stop_ftrace_events)
+ if (list == &ftrace_events)
return NULL;
+ call = list_entry(list, struct ftrace_event_call, list);
+
if (!call->enabled) {
- call++;
+ list = list->next;
goto retry;
}
- next = call;
- m->private = ++next;
+ m->private = list->next;
return call;
}
static void *s_start(struct seq_file *m, loff_t *pos)
{
+ mutex_lock(&event_mutex);
+ if (*pos == 0)
+ m->private = ftrace_events.next;
return s_next(m, NULL, pos);
}
@@ -295,12 +327,12 @@ static int t_show(struct seq_file *m, void *v)
static void t_stop(struct seq_file *m, void *p)
{
+ mutex_unlock(&event_mutex);
}
static int
ftrace_event_seq_open(struct inode *inode, struct file *file)
{
- int ret;
const struct seq_operations *seq_ops;
if ((file->f_mode & FMODE_WRITE) &&
@@ -308,13 +340,7 @@ ftrace_event_seq_open(struct inode *inode, struct file *file)
ftrace_clear_events();
seq_ops = inode->i_private;
- ret = seq_open(file, seq_ops);
- if (!ret) {
- struct seq_file *m = file->private_data;
-
- m->private = __start_ftrace_events;
- }
- return ret;
+ return seq_open(file, seq_ops);
}
static ssize_t
@@ -374,8 +400,138 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
return cnt;
}
+static ssize_t
+system_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
+ loff_t *ppos)
+{
+ const char *system = filp->private_data;
+ struct ftrace_event_call *call;
+ char buf[2];
+ int set = -1;
+ int all = 0;
+ int ret;
+
+ if (system[0] == '*')
+ all = 1;
+
+ mutex_lock(&event_mutex);
+ list_for_each_entry(call, &ftrace_events, list) {
+ if (!call->name || !call->regfunc)
+ continue;
+
+ if (!all && strcmp(call->system, system) != 0)
+ continue;
+
+ /*
+ * We need to find out if all the events are set
+ * or if all events or cleared, or if we have
+ * a mixture.
+ */
+ if (call->enabled) {
+ switch (set) {
+ case -1:
+ set = 1;
+ break;
+ case 0:
+ set = 2;
+ break;
+ }
+ } else {
+ switch (set) {
+ case -1:
+ set = 0;
+ break;
+ case 1:
+ set = 2;
+ break;
+ }
+ }
+ /*
+ * If we have a mixture, no need to look further.
+ */
+ if (set == 2)
+ break;
+ }
+ mutex_unlock(&event_mutex);
+
+ buf[1] = '\n';
+ switch (set) {
+ case 0:
+ buf[0] = '0';
+ break;
+ case 1:
+ buf[0] = '1';
+ break;
+ case 2:
+ buf[0] = 'X';
+ break;
+ default:
+ buf[0] = '?';
+ }
+
+ ret = simple_read_from_buffer(ubuf, cnt, ppos, buf, 2);
+
+ return ret;
+}
+
+static ssize_t
+system_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
+ loff_t *ppos)
+{
+ const char *system = filp->private_data;
+ unsigned long val;
+ char *command;
+ char buf[64];
+ ssize_t ret;
+
+ if (cnt >= sizeof(buf))
+ return -EINVAL;
+
+ if (copy_from_user(&buf, ubuf, cnt))
+ return -EFAULT;
+
+ buf[cnt] = 0;
+
+ ret = strict_strtoul(buf, 10, &val);
+ if (ret < 0)
+ return ret;
+
+ ret = tracing_update_buffers();
+ if (ret < 0)
+ return ret;
+
+ switch (val) {
+ case 0:
+ case 1:
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ command = kstrdup(system, GFP_KERNEL);
+ if (!command)
+ return -ENOMEM;
+
+ ret = ftrace_set_clr_event(command, val);
+ if (ret)
+ goto out_free;
+
+ ret = cnt;
+
+ out_free:
+ kfree(command);
+
+ *ppos += cnt;
+
+ return ret;
+}
+
+extern char *__bad_type_size(void);
+
#undef FIELD
#define FIELD(type, name) \
+ sizeof(type) != sizeof(field.name) ? __bad_type_size() : \
#type, "common_" #name, offsetof(typeof(field), name), \
sizeof(field.name)
@@ -391,7 +547,7 @@ static int trace_write_header(struct trace_seq *s)
"\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n"
"\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n"
"\n",
- FIELD(unsigned char, type),
+ FIELD(unsigned short, type),
FIELD(unsigned char, flags),
FIELD(unsigned char, preempt_count),
FIELD(int, pid),
@@ -481,7 +637,7 @@ event_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
trace_seq_init(s);
- filter_print_preds(call->preds, s);
+ print_event_filter(call, s);
r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len);
kfree(s);
@@ -494,38 +650,26 @@ event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt,
loff_t *ppos)
{
struct ftrace_event_call *call = filp->private_data;
- char buf[64], *pbuf = buf;
- struct filter_pred *pred;
+ char *buf;
int err;
- if (cnt >= sizeof(buf))
+ if (cnt >= PAGE_SIZE)
return -EINVAL;
- if (copy_from_user(&buf, ubuf, cnt))
- return -EFAULT;
- buf[cnt] = '\0';
-
- pred = kzalloc(sizeof(*pred), GFP_KERNEL);
- if (!pred)
+ buf = (char *)__get_free_page(GFP_TEMPORARY);
+ if (!buf)
return -ENOMEM;
- err = filter_parse(&pbuf, pred);
- if (err < 0) {
- filter_free_pred(pred);
- return err;
- }
-
- if (pred->clear) {
- filter_free_preds(call);
- filter_free_pred(pred);
- return cnt;
+ if (copy_from_user(buf, ubuf, cnt)) {
+ free_page((unsigned long) buf);
+ return -EFAULT;
}
+ buf[cnt] = '\0';
- err = filter_add_pred(call, pred);
- if (err < 0) {
- filter_free_pred(pred);
+ err = apply_event_filter(call, buf);
+ free_page((unsigned long) buf);
+ if (err < 0)
return err;
- }
*ppos += cnt;
@@ -549,7 +693,7 @@ subsystem_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
trace_seq_init(s);
- filter_print_preds(system->preds, s);
+ print_subsystem_event_filter(system, s);
r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len);
kfree(s);
@@ -562,45 +706,56 @@ subsystem_filter_write(struct file *filp, const char __user *ubuf, size_t cnt,
loff_t *ppos)
{
struct event_subsystem *system = filp->private_data;
- char buf[64], *pbuf = buf;
- struct filter_pred *pred;
+ char *buf;
int err;
- if (cnt >= sizeof(buf))
+ if (cnt >= PAGE_SIZE)
return -EINVAL;
- if (copy_from_user(&buf, ubuf, cnt))
- return -EFAULT;
- buf[cnt] = '\0';
-
- pred = kzalloc(sizeof(*pred), GFP_KERNEL);
- if (!pred)
+ buf = (char *)__get_free_page(GFP_TEMPORARY);
+ if (!buf)
return -ENOMEM;
- err = filter_parse(&pbuf, pred);
- if (err < 0) {
- filter_free_pred(pred);
- return err;
- }
-
- if (pred->clear) {
- filter_free_subsystem_preds(system);
- filter_free_pred(pred);
- return cnt;
+ if (copy_from_user(buf, ubuf, cnt)) {
+ free_page((unsigned long) buf);
+ return -EFAULT;
}
+ buf[cnt] = '\0';
- err = filter_add_subsystem_pred(system, pred);
- if (err < 0) {
- filter_free_subsystem_preds(system);
- filter_free_pred(pred);
+ err = apply_subsystem_event_filter(system, buf);
+ free_page((unsigned long) buf);
+ if (err < 0)
return err;
- }
*ppos += cnt;
return cnt;
}
+static ssize_t
+show_header(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+ int (*func)(struct trace_seq *s) = filp->private_data;
+ struct trace_seq *s;
+ int r;
+
+ if (*ppos)
+ return 0;
+
+ s = kmalloc(sizeof(*s), GFP_KERNEL);
+ if (!s)
+ return -ENOMEM;
+
+ trace_seq_init(s);
+
+ func(s);
+ r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len);
+
+ kfree(s);
+
+ return r;
+}
+
static const struct seq_operations show_event_seq_ops = {
.start = t_start,
.next = t_next,
@@ -658,6 +813,17 @@ static const struct file_operations ftrace_subsystem_filter_fops = {
.write = subsystem_filter_write,
};
+static const struct file_operations ftrace_system_enable_fops = {
+ .open = tracing_open_generic,
+ .read = system_enable_read,
+ .write = system_enable_write,
+};
+
+static const struct file_operations ftrace_show_header_fops = {
+ .open = tracing_open_generic,
+ .read = show_header,
+};
+
static struct dentry *event_trace_events_dir(void)
{
static struct dentry *d_tracer;
@@ -684,6 +850,7 @@ static struct dentry *
event_subsystem_dir(const char *name, struct dentry *d_events)
{
struct event_subsystem *system;
+ struct dentry *entry;
/* First see if we did not already create this dir */
list_for_each_entry(system, &event_subsystems, list) {
@@ -707,16 +874,46 @@ event_subsystem_dir(const char *name, struct dentry *d_events)
return d_events;
}
- system->name = name;
+ system->name = kstrdup(name, GFP_KERNEL);
+ if (!system->name) {
+ debugfs_remove(system->entry);
+ kfree(system);
+ return d_events;
+ }
+
list_add(&system->list, &event_subsystems);
- system->preds = NULL;
+ system->filter = NULL;
+
+ system->filter = kzalloc(sizeof(struct event_filter), GFP_KERNEL);
+ if (!system->filter) {
+ pr_warning("Could not allocate filter for subsystem "
+ "'%s'\n", name);
+ return system->entry;
+ }
+
+ entry = debugfs_create_file("filter", 0644, system->entry, system,
+ &ftrace_subsystem_filter_fops);
+ if (!entry) {
+ kfree(system->filter);
+ system->filter = NULL;
+ pr_warning("Could not create debugfs "
+ "'%s/filter' entry\n", name);
+ }
+
+ entry = trace_create_file("enable", 0644, system->entry,
+ (void *)system->name,
+ &ftrace_system_enable_fops);
return system->entry;
}
static int
-event_create_dir(struct ftrace_event_call *call, struct dentry *d_events)
+event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
+ const struct file_operations *id,
+ const struct file_operations *enable,
+ const struct file_operations *filter,
+ const struct file_operations *format)
{
struct dentry *entry;
int ret;
@@ -725,7 +922,7 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events)
* If the trace point header did not define TRACE_SYSTEM
* then the system would be called "TRACE_SYSTEM".
*/
- if (strcmp(call->system, "TRACE_SYSTEM") != 0)
+ if (strcmp(call->system, TRACE_SYSTEM) != 0)
d_events = event_subsystem_dir(call->system, d_events);
if (call->raw_init) {
@@ -744,21 +941,13 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events)
return -1;
}
- if (call->regfunc) {
- entry = debugfs_create_file("enable", 0644, call->dir, call,
- &ftrace_enable_fops);
- if (!entry)
- pr_warning("Could not create debugfs "
- "'%s/enable' entry\n", call->name);
- }
+ if (call->regfunc)
+ entry = trace_create_file("enable", 0644, call->dir, call,
+ enable);
- if (call->id) {
- entry = debugfs_create_file("id", 0444, call->dir, call,
- &ftrace_event_id_fops);
- if (!entry)
- pr_warning("Could not create debugfs '%s/id' entry\n",
- call->name);
- }
+ if (call->id)
+ entry = trace_create_file("id", 0444, call->dir, call,
+ id);
if (call->define_fields) {
ret = call->define_fields();
@@ -767,32 +956,196 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events)
" events/%s\n", call->name);
return ret;
}
- entry = debugfs_create_file("filter", 0644, call->dir, call,
- &ftrace_event_filter_fops);
- if (!entry)
- pr_warning("Could not create debugfs "
- "'%s/filter' entry\n", call->name);
+ entry = trace_create_file("filter", 0644, call->dir, call,
+ filter);
}
/* A trace may not want to export its format */
if (!call->show_format)
return 0;
- entry = debugfs_create_file("format", 0444, call->dir, call,
- &ftrace_event_format_fops);
- if (!entry)
- pr_warning("Could not create debugfs "
- "'%s/format' entry\n", call->name);
+ entry = trace_create_file("format", 0444, call->dir, call,
+ format);
+
+ return 0;
+}
+
+#define for_each_event(event, start, end) \
+ for (event = start; \
+ (unsigned long)event < (unsigned long)end; \
+ event++)
+
+#ifdef CONFIG_MODULES
+
+static LIST_HEAD(ftrace_module_file_list);
+
+/*
+ * Modules must own their file_operations to keep up with
+ * reference counting.
+ */
+struct ftrace_module_file_ops {
+ struct list_head list;
+ struct module *mod;
+ struct file_operations id;
+ struct file_operations enable;
+ struct file_operations format;
+ struct file_operations filter;
+};
+
+static struct ftrace_module_file_ops *
+trace_create_file_ops(struct module *mod)
+{
+ struct ftrace_module_file_ops *file_ops;
+
+ /*
+ * This is a bit of a PITA. To allow for correct reference
+ * counting, modules must "own" their file_operations.
+ * To do this, we allocate the file operations that will be
+ * used in the event directory.
+ */
+
+ file_ops = kmalloc(sizeof(*file_ops), GFP_KERNEL);
+ if (!file_ops)
+ return NULL;
+
+ file_ops->mod = mod;
+
+ file_ops->id = ftrace_event_id_fops;
+ file_ops->id.owner = mod;
+
+ file_ops->enable = ftrace_enable_fops;
+ file_ops->enable.owner = mod;
+
+ file_ops->filter = ftrace_event_filter_fops;
+ file_ops->filter.owner = mod;
+
+ file_ops->format = ftrace_event_format_fops;
+ file_ops->format.owner = mod;
+
+ list_add(&file_ops->list, &ftrace_module_file_list);
+
+ return file_ops;
+}
+
+static void trace_module_add_events(struct module *mod)
+{
+ struct ftrace_module_file_ops *file_ops = NULL;
+ struct ftrace_event_call *call, *start, *end;
+ struct dentry *d_events;
+
+ start = mod->trace_events;
+ end = mod->trace_events + mod->num_trace_events;
+
+ if (start == end)
+ return;
+
+ d_events = event_trace_events_dir();
+ if (!d_events)
+ return;
+
+ for_each_event(call, start, end) {
+ /* The linker may leave blanks */
+ if (!call->name)
+ continue;
+
+ /*
+ * This module has events, create file ops for this module
+ * if not already done.
+ */
+ if (!file_ops) {
+ file_ops = trace_create_file_ops(mod);
+ if (!file_ops)
+ return;
+ }
+ call->mod = mod;
+ list_add(&call->list, &ftrace_events);
+ event_create_dir(call, d_events,
+ &file_ops->id, &file_ops->enable,
+ &file_ops->filter, &file_ops->format);
+ }
+}
+
+static void trace_module_remove_events(struct module *mod)
+{
+ struct ftrace_module_file_ops *file_ops;
+ struct ftrace_event_call *call, *p;
+ bool found = false;
+
+ list_for_each_entry_safe(call, p, &ftrace_events, list) {
+ if (call->mod == mod) {
+ found = true;
+ if (call->enabled) {
+ call->enabled = 0;
+ call->unregfunc();
+ }
+ if (call->event)
+ unregister_ftrace_event(call->event);
+ debugfs_remove_recursive(call->dir);
+ list_del(&call->list);
+ trace_destroy_fields(call);
+ destroy_preds(call);
+ }
+ }
+
+ /* Now free the file_operations */
+ list_for_each_entry(file_ops, &ftrace_module_file_list, list) {
+ if (file_ops->mod == mod)
+ break;
+ }
+ if (&file_ops->list != &ftrace_module_file_list) {
+ list_del(&file_ops->list);
+ kfree(file_ops);
+ }
+
+ /*
+ * It is safest to reset the ring buffer if the module being unloaded
+ * registered any events.
+ */
+ if (found)
+ tracing_reset_current_online_cpus();
+}
+
+static int trace_module_notify(struct notifier_block *self,
+ unsigned long val, void *data)
+{
+ struct module *mod = data;
+ mutex_lock(&event_mutex);
+ switch (val) {
+ case MODULE_STATE_COMING:
+ trace_module_add_events(mod);
+ break;
+ case MODULE_STATE_GOING:
+ trace_module_remove_events(mod);
+ break;
+ }
+ mutex_unlock(&event_mutex);
+
+ return 0;
+}
+#else
+static int trace_module_notify(struct notifier_block *self,
+ unsigned long val, void *data)
+{
return 0;
}
+#endif /* CONFIG_MODULES */
+
+struct notifier_block trace_module_nb = {
+ .notifier_call = trace_module_notify,
+ .priority = 0,
+};
+
+extern struct ftrace_event_call __start_ftrace_events[];
+extern struct ftrace_event_call __stop_ftrace_events[];
static __init int event_trace_init(void)
{
- struct ftrace_event_call *call = __start_ftrace_events;
+ struct ftrace_event_call *call;
struct dentry *d_tracer;
struct dentry *entry;
struct dentry *d_events;
+ int ret;
d_tracer = tracing_init_dentry();
if (!d_tracer)
@@ -816,13 +1169,272 @@ static __init int event_trace_init(void)
if (!d_events)
return 0;
- for_each_event(call) {
+ /* ring buffer internal formats */
+ trace_create_file("header_page", 0444, d_events,
+ ring_buffer_print_page_header,
+ &ftrace_show_header_fops);
+
+ trace_create_file("header_event", 0444, d_events,
+ ring_buffer_print_entry_header,
+ &ftrace_show_header_fops);
+
+ trace_create_file("enable", 0644, d_events,
+ "*:*", &ftrace_system_enable_fops);
+
+ for_each_event(call, __start_ftrace_events, __stop_ftrace_events) {
/* The linker may leave blanks */
if (!call->name)
continue;
- event_create_dir(call, d_events);
+ list_add(&call->list, &ftrace_events);
+ event_create_dir(call, d_events, &ftrace_event_id_fops,
+ &ftrace_enable_fops, &ftrace_event_filter_fops,
+ &ftrace_event_format_fops);
}
+ ret = register_module_notifier(&trace_module_nb);
+ if (!ret)
+ pr_warning("Failed to register trace events module notifier\n");
+
return 0;
}
fs_initcall(event_trace_init);
+
+#ifdef CONFIG_FTRACE_STARTUP_TEST
+
+static DEFINE_SPINLOCK(test_spinlock);
+static DEFINE_SPINLOCK(test_spinlock_irq);
+static DEFINE_MUTEX(test_mutex);
+
+static __init void test_work(struct work_struct *dummy)
+{
+ spin_lock(&test_spinlock);
+ spin_lock_irq(&test_spinlock_irq);
+ udelay(1);
+ spin_unlock_irq(&test_spinlock_irq);
+ spin_unlock(&test_spinlock);
+
+ mutex_lock(&test_mutex);
+ msleep(1);
+ mutex_unlock(&test_mutex);
+}
+
+static __init int event_test_thread(void *unused)
+{
+ void *test_malloc;
+
+ test_malloc = kmalloc(1234, GFP_KERNEL);
+ if (!test_malloc)
+ pr_info("failed to kmalloc\n");
+
+ schedule_on_each_cpu(test_work);
+
+ kfree(test_malloc);
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ while (!kthread_should_stop())
+ schedule();
+
+ return 0;
+}
+
+/*
+ * Do various things that may trigger events.
+ */
+static __init void event_test_stuff(void)
+{
+ struct task_struct *test_thread;
+
+ test_thread = kthread_run(event_test_thread, NULL, "test-events");
+ msleep(1);
+ kthread_stop(test_thread);
+}
+
+/*
+ * For every trace event defined, we will test each trace point separately,
+ * and then by groups, and finally all trace points.
+ */
+static __init void event_trace_self_tests(void)
+{
+ struct ftrace_event_call *call;
+ struct event_subsystem *system;
+ char *sysname;
+ int ret;
+
+ pr_info("Running tests on trace events:\n");
+
+ list_for_each_entry(call, &ftrace_events, list) {
+
+ /* Only test those that have a regfunc */
+ if (!call->regfunc)
+ continue;
+
+ pr_info("Testing event %s: ", call->name);
+
+ /*
+ * If an event is already enabled, someone is using
+ * it and the self test should not be on.
+ */
+ if (call->enabled) {
+ pr_warning("Enabled event during self test!\n");
+ WARN_ON_ONCE(1);
+ continue;
+ }
+
+ call->enabled = 1;
+ call->regfunc();
+
+ event_test_stuff();
+
+ call->unregfunc();
+ call->enabled = 0;
+
+ pr_cont("OK\n");
+ }
+
+ /* Now test at the sub system level */
+
+ pr_info("Running tests on trace event systems:\n");
+
+ list_for_each_entry(system, &event_subsystems, list) {
+
+ /* the ftrace system is special, skip it */
+ if (strcmp(system->name, "ftrace") == 0)
+ continue;
+
+ pr_info("Testing event system %s: ", system->name);
+
+ /* ftrace_set_clr_event can modify the name passed in. */
+ sysname = kstrdup(system->name, GFP_KERNEL);
+ if (WARN_ON(!sysname)) {
+ pr_warning("Can't allocate memory, giving up!\n");
+ return;
+ }
+ ret = ftrace_set_clr_event(sysname, 1);
+ kfree(sysname);
+ if (WARN_ON_ONCE(ret)) {
+ pr_warning("error enabling system %s\n",
+ system->name);
+ continue;
+ }
+
+ event_test_stuff();
+
+ sysname = kstrdup(system->name, GFP_KERNEL);
+ if (WARN_ON(!sysname)) {
+ pr_warning("Can't allocate memory, giving up!\n");
+ return;
+ }
+ ret = ftrace_set_clr_event(sysname, 0);
+ kfree(sysname);
+
+ if (WARN_ON_ONCE(ret))
+ pr_warning("error disabling system %s\n",
+ system->name);
+
+ pr_cont("OK\n");
+ }
+
+ /* Test with all events enabled */
+
+ pr_info("Running tests on all trace events:\n");
+ pr_info("Testing all events: ");
+
+ sysname = kmalloc(4, GFP_KERNEL);
+ if (WARN_ON(!sysname)) {
+ pr_warning("Can't allocate memory, giving up!\n");
+ return;
+ }
+ memcpy(sysname, "*:*", 4);
+ ret = ftrace_set_clr_event(sysname, 1);
+ if (WARN_ON_ONCE(ret)) {
+ kfree(sysname);
+ pr_warning("error enabling all events\n");
+ return;
+ }
+
+ event_test_stuff();
+
+ /* reset sysname */
+ memcpy(sysname, "*:*", 4);
+ ret = ftrace_set_clr_event(sysname, 0);
+ kfree(sysname);
+
+ if (WARN_ON_ONCE(ret)) {
+ pr_warning("error disabling all events\n");
+ return;
+ }
+
+ pr_cont("OK\n");
+}
+
+#ifdef CONFIG_FUNCTION_TRACER
+
+static DEFINE_PER_CPU(atomic_t, test_event_disable);
+
+static void
+function_test_events_call(unsigned long ip, unsigned long parent_ip)
+{
+ struct ring_buffer_event *event;
+ struct ftrace_entry *entry;
+ unsigned long flags;
+ long disabled;
+ int resched;
+ int cpu;
+ int pc;
+
+ pc = preempt_count();
+ resched = ftrace_preempt_disable();
+ cpu = raw_smp_processor_id();
+ disabled = atomic_inc_return(&per_cpu(test_event_disable, cpu));
+
+ if (disabled != 1)
+ goto out;
+
+ local_save_flags(flags);
+
+ event = trace_current_buffer_lock_reserve(TRACE_FN, sizeof(*entry),
+ flags, pc);
+ if (!event)
+ goto out;
+ entry = ring_buffer_event_data(event);
+ entry->ip = ip;
+ entry->parent_ip = parent_ip;
+
+ trace_nowake_buffer_unlock_commit(event, flags, pc);
+
+ out:
+ atomic_dec(&per_cpu(test_event_disable, cpu));
+ ftrace_preempt_enable(resched);
+}
+
+static struct ftrace_ops trace_ops __initdata =
+{
+ .func = function_test_events_call,
+};
+
+static __init void event_trace_self_test_with_function(void)
+{
+ register_ftrace_function(&trace_ops);
+ pr_info("Running tests again, along with the function tracer\n");
+ event_trace_self_tests();
+ unregister_ftrace_function(&trace_ops);
+}
+#else
+static __init void event_trace_self_test_with_function(void)
+{
+}
+#endif
+
+static __init int event_trace_self_tests_init(void)
+{
+
+ event_trace_self_tests();
+
+ event_trace_self_test_with_function();
+
+ return 0;
+}
+
+late_initcall(event_trace_self_tests_init);
+
+#endif
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index e03cbf1e38f3..85ad6a8939ad 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -22,119 +22,297 @@
#include <linux/uaccess.h>
#include <linux/module.h>
#include <linux/ctype.h>
+#include <linux/mutex.h>
#include "trace.h"
#include "trace_output.h"
-static int filter_pred_64(struct filter_pred *pred, void *event)
+static DEFINE_MUTEX(filter_mutex);
+
+enum filter_op_ids
+{
+ OP_OR,
+ OP_AND,
+ OP_NE,
+ OP_EQ,
+ OP_LT,
+ OP_LE,
+ OP_GT,
+ OP_GE,
+ OP_NONE,
+ OP_OPEN_PAREN,
+};
+
+struct filter_op {
+ int id;
+ char *string;
+ int precedence;
+};
+
+static struct filter_op filter_ops[] = {
+ { OP_OR, "||", 1 },
+ { OP_AND, "&&", 2 },
+ { OP_NE, "!=", 4 },
+ { OP_EQ, "==", 4 },
+ { OP_LT, "<", 5 },
+ { OP_LE, "<=", 5 },
+ { OP_GT, ">", 5 },
+ { OP_GE, ">=", 5 },
+ { OP_NONE, "OP_NONE", 0 },
+ { OP_OPEN_PAREN, "(", 0 },
+};
+
+enum {
+ FILT_ERR_NONE,
+ FILT_ERR_INVALID_OP,
+ FILT_ERR_UNBALANCED_PAREN,
+ FILT_ERR_TOO_MANY_OPERANDS,
+ FILT_ERR_OPERAND_TOO_LONG,
+ FILT_ERR_FIELD_NOT_FOUND,
+ FILT_ERR_ILLEGAL_FIELD_OP,
+ FILT_ERR_ILLEGAL_INTVAL,
+ FILT_ERR_BAD_SUBSYS_FILTER,
+ FILT_ERR_TOO_MANY_PREDS,
+ FILT_ERR_MISSING_FIELD,
+ FILT_ERR_INVALID_FILTER,
+};
+
+static char *err_text[] = {
+ "No error",
+ "Invalid operator",
+ "Unbalanced parens",
+ "Too many operands",
+ "Operand too long",
+ "Field not found",
+ "Illegal operation for field type",
+ "Illegal integer value",
+ "Couldn't find or set field in one of a subsystem's events",
+ "Too many terms in predicate expression",
+ "Missing field name and/or value",
+ "Meaningless filter expression",
+};
+
+struct opstack_op {
+ int op;
+ struct list_head list;
+};
+
+struct postfix_elt {
+ int op;
+ char *operand;
+ struct list_head list;
+};
+
+struct filter_parse_state {
+ struct filter_op *ops;
+ struct list_head opstack;
+ struct list_head postfix;
+ int lasterr;
+ int lasterr_pos;
+
+ struct {
+ char *string;
+ unsigned int cnt;
+ unsigned int tail;
+ } infix;
+
+ struct {
+ char string[MAX_FILTER_STR_VAL];
+ int pos;
+ unsigned int tail;
+ } operand;
+};
+
+DEFINE_COMPARISON_PRED(s64);
+DEFINE_COMPARISON_PRED(u64);
+DEFINE_COMPARISON_PRED(s32);
+DEFINE_COMPARISON_PRED(u32);
+DEFINE_COMPARISON_PRED(s16);
+DEFINE_COMPARISON_PRED(u16);
+DEFINE_COMPARISON_PRED(s8);
+DEFINE_COMPARISON_PRED(u8);
+
+DEFINE_EQUALITY_PRED(64);
+DEFINE_EQUALITY_PRED(32);
+DEFINE_EQUALITY_PRED(16);
+DEFINE_EQUALITY_PRED(8);
+
+static int filter_pred_and(struct filter_pred *pred __attribute((unused)),
+ void *event __attribute((unused)),
+ int val1, int val2)
+{
+ return val1 && val2;
+}
+
+static int filter_pred_or(struct filter_pred *pred __attribute((unused)),
+ void *event __attribute((unused)),
+ int val1, int val2)
+{
+ return val1 || val2;
+}
+
+/* Filter predicate for fixed sized arrays of characters */
+static int filter_pred_string(struct filter_pred *pred, void *event,
+ int val1, int val2)
{
- u64 *addr = (u64 *)(event + pred->offset);
- u64 val = (u64)pred->val;
- int match;
+ char *addr = (char *)(event + pred->offset);
+ int cmp, match;
+
+ cmp = strncmp(addr, pred->str_val, pred->str_len);
- match = (val == *addr) ^ pred->not;
+ match = (!cmp) ^ pred->not;
return match;
}
-static int filter_pred_32(struct filter_pred *pred, void *event)
+/*
+ * Filter predicate for dynamic sized arrays of characters.
+ * These are implemented through a list of strings at the end
+ * of the entry.
+ * Also each of these strings have a field in the entry which
+ * contains its offset from the beginning of the entry.
+ * We have then first to get this field, dereference it
+ * and add it to the address of the entry, and at last we have
+ * the address of the string.
+ */
+static int filter_pred_strloc(struct filter_pred *pred, void *event,
+ int val1, int val2)
{
- u32 *addr = (u32 *)(event + pred->offset);
- u32 val = (u32)pred->val;
- int match;
+ int str_loc = *(int *)(event + pred->offset);
+ char *addr = (char *)(event + str_loc);
+ int cmp, match;
+
+ cmp = strncmp(addr, pred->str_val, pred->str_len);
- match = (val == *addr) ^ pred->not;
+ match = (!cmp) ^ pred->not;
return match;
}
-static int filter_pred_16(struct filter_pred *pred, void *event)
+static int filter_pred_none(struct filter_pred *pred, void *event,
+ int val1, int val2)
+{
+ return 0;
+}
+
+/* return 1 if event matches, 0 otherwise (discard) */
+int filter_match_preds(struct ftrace_event_call *call, void *rec)
{
- u16 *addr = (u16 *)(event + pred->offset);
- u16 val = (u16)pred->val;
- int match;
+ struct event_filter *filter = call->filter;
+ int match, top = 0, val1 = 0, val2 = 0;
+ int stack[MAX_FILTER_PRED];
+ struct filter_pred *pred;
+ int i;
+
+ for (i = 0; i < filter->n_preds; i++) {
+ pred = filter->preds[i];
+ if (!pred->pop_n) {
+ match = pred->fn(pred, rec, val1, val2);
+ stack[top++] = match;
+ continue;
+ }
+ if (pred->pop_n > top) {
+ WARN_ON_ONCE(1);
+ return 0;
+ }
+ val1 = stack[--top];
+ val2 = stack[--top];
+ match = pred->fn(pred, rec, val1, val2);
+ stack[top++] = match;
+ }
- match = (val == *addr) ^ pred->not;
+ return stack[--top];
+}
+EXPORT_SYMBOL_GPL(filter_match_preds);
- return match;
+static void parse_error(struct filter_parse_state *ps, int err, int pos)
+{
+ ps->lasterr = err;
+ ps->lasterr_pos = pos;
}
-static int filter_pred_8(struct filter_pred *pred, void *event)
+static void remove_filter_string(struct event_filter *filter)
{
- u8 *addr = (u8 *)(event + pred->offset);
- u8 val = (u8)pred->val;
- int match;
+ kfree(filter->filter_string);
+ filter->filter_string = NULL;
+}
- match = (val == *addr) ^ pred->not;
+static int replace_filter_string(struct event_filter *filter,
+ char *filter_string)
+{
+ kfree(filter->filter_string);
+ filter->filter_string = kstrdup(filter_string, GFP_KERNEL);
+ if (!filter->filter_string)
+ return -ENOMEM;
- return match;
+ return 0;
}
-static int filter_pred_string(struct filter_pred *pred, void *event)
+static int append_filter_string(struct event_filter *filter,
+ char *string)
{
- char *addr = (char *)(event + pred->offset);
- int cmp, match;
+ int newlen;
+ char *new_filter_string;
- cmp = strncmp(addr, pred->str_val, pred->str_len);
+ BUG_ON(!filter->filter_string);
+ newlen = strlen(filter->filter_string) + strlen(string) + 1;
+ new_filter_string = kmalloc(newlen, GFP_KERNEL);
+ if (!new_filter_string)
+ return -ENOMEM;
- match = (!cmp) ^ pred->not;
+ strcpy(new_filter_string, filter->filter_string);
+ strcat(new_filter_string, string);
+ kfree(filter->filter_string);
+ filter->filter_string = new_filter_string;
- return match;
+ return 0;
}
-/* return 1 if event matches, 0 otherwise (discard) */
-int filter_match_preds(struct ftrace_event_call *call, void *rec)
+static void append_filter_err(struct filter_parse_state *ps,
+ struct event_filter *filter)
{
- int i, matched, and_failed = 0;
- struct filter_pred *pred;
+ int pos = ps->lasterr_pos;
+ char *buf, *pbuf;
- for (i = 0; i < MAX_FILTER_PRED; i++) {
- if (call->preds[i]) {
- pred = call->preds[i];
- if (and_failed && !pred->or)
- continue;
- matched = pred->fn(pred, rec);
- if (!matched && !pred->or) {
- and_failed = 1;
- continue;
- } else if (matched && pred->or)
- return 1;
- } else
- break;
- }
+ buf = (char *)__get_free_page(GFP_TEMPORARY);
+ if (!buf)
+ return;
- if (and_failed)
- return 0;
+ append_filter_string(filter, "\n");
+ memset(buf, ' ', PAGE_SIZE);
+ if (pos > PAGE_SIZE - 128)
+ pos = 0;
+ buf[pos] = '^';
+ pbuf = &buf[pos] + 1;
- return 1;
+ sprintf(pbuf, "\nparse_error: %s\n", err_text[ps->lasterr]);
+ append_filter_string(filter, buf);
+ free_page((unsigned long) buf);
}
-void filter_print_preds(struct filter_pred **preds, struct trace_seq *s)
+void print_event_filter(struct ftrace_event_call *call, struct trace_seq *s)
{
- char *field_name;
- struct filter_pred *pred;
- int i;
+ struct event_filter *filter = call->filter;
- if (!preds) {
+ mutex_lock(&filter_mutex);
+ if (filter->filter_string)
+ trace_seq_printf(s, "%s\n", filter->filter_string);
+ else
trace_seq_printf(s, "none\n");
- return;
- }
+ mutex_unlock(&filter_mutex);
+}
- for (i = 0; i < MAX_FILTER_PRED; i++) {
- if (preds[i]) {
- pred = preds[i];
- field_name = pred->field_name;
- if (i)
- trace_seq_printf(s, pred->or ? "|| " : "&& ");
- trace_seq_printf(s, "%s ", field_name);
- trace_seq_printf(s, pred->not ? "!= " : "== ");
- if (pred->str_val)
- trace_seq_printf(s, "%s\n", pred->str_val);
- else
- trace_seq_printf(s, "%llu\n", pred->val);
- } else
- break;
- }
+void print_subsystem_event_filter(struct event_subsystem *system,
+ struct trace_seq *s)
+{
+ struct event_filter *filter = system->filter;
+
+ mutex_lock(&filter_mutex);
+ if (filter->filter_string)
+ trace_seq_printf(s, "%s\n", filter->filter_string);
+ else
+ trace_seq_printf(s, "none\n");
+ mutex_unlock(&filter_mutex);
}
static struct ftrace_event_field *
@@ -150,284 +328,826 @@ find_event_field(struct ftrace_event_call *call, char *name)
return NULL;
}
-void filter_free_pred(struct filter_pred *pred)
+static void filter_free_pred(struct filter_pred *pred)
{
if (!pred)
return;
kfree(pred->field_name);
- kfree(pred->str_val);
kfree(pred);
}
-void filter_free_preds(struct ftrace_event_call *call)
+static void filter_clear_pred(struct filter_pred *pred)
{
- int i;
+ kfree(pred->field_name);
+ pred->field_name = NULL;
+ pred->str_len = 0;
+}
- if (call->preds) {
- for (i = 0; i < MAX_FILTER_PRED; i++)
- filter_free_pred(call->preds[i]);
- kfree(call->preds);
- call->preds = NULL;
+static int filter_set_pred(struct filter_pred *dest,
+ struct filter_pred *src,
+ filter_pred_fn_t fn)
+{
+ *dest = *src;
+ if (src->field_name) {
+ dest->field_name = kstrdup(src->field_name, GFP_KERNEL);
+ if (!dest->field_name)
+ return -ENOMEM;
}
+ dest->fn = fn;
+
+ return 0;
}
-void filter_free_subsystem_preds(struct event_subsystem *system)
+static void filter_disable_preds(struct ftrace_event_call *call)
{
- struct ftrace_event_call *call = __start_ftrace_events;
+ struct event_filter *filter = call->filter;
int i;
- if (system->preds) {
- for (i = 0; i < MAX_FILTER_PRED; i++)
- filter_free_pred(system->preds[i]);
- kfree(system->preds);
- system->preds = NULL;
- }
+ call->filter_active = 0;
+ filter->n_preds = 0;
- events_for_each(call) {
- if (!call->name || !call->regfunc)
- continue;
+ for (i = 0; i < MAX_FILTER_PRED; i++)
+ filter->preds[i]->fn = filter_pred_none;
+}
+
+void destroy_preds(struct ftrace_event_call *call)
+{
+ struct event_filter *filter = call->filter;
+ int i;
- if (!strcmp(call->system, system->name))
- filter_free_preds(call);
+ for (i = 0; i < MAX_FILTER_PRED; i++) {
+ if (filter->preds[i])
+ filter_free_pred(filter->preds[i]);
}
+ kfree(filter->preds);
+ kfree(filter);
+ call->filter = NULL;
}
-static int __filter_add_pred(struct ftrace_event_call *call,
- struct filter_pred *pred)
+int init_preds(struct ftrace_event_call *call)
{
+ struct event_filter *filter;
+ struct filter_pred *pred;
int i;
- if (call->preds && !pred->compound)
- filter_free_preds(call);
+ filter = call->filter = kzalloc(sizeof(*filter), GFP_KERNEL);
+ if (!call->filter)
+ return -ENOMEM;
- if (!call->preds) {
- call->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred),
- GFP_KERNEL);
- if (!call->preds)
- return -ENOMEM;
- }
+ call->filter_active = 0;
+ filter->n_preds = 0;
+
+ filter->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred), GFP_KERNEL);
+ if (!filter->preds)
+ goto oom;
for (i = 0; i < MAX_FILTER_PRED; i++) {
- if (!call->preds[i]) {
- call->preds[i] = pred;
- return 0;
+ pred = kzalloc(sizeof(*pred), GFP_KERNEL);
+ if (!pred)
+ goto oom;
+ pred->fn = filter_pred_none;
+ filter->preds[i] = pred;
+ }
+
+ return 0;
+
+oom:
+ destroy_preds(call);
+
+ return -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(init_preds);
+
+static void filter_free_subsystem_preds(struct event_subsystem *system)
+{
+ struct event_filter *filter = system->filter;
+ struct ftrace_event_call *call;
+ int i;
+
+ if (filter->n_preds) {
+ for (i = 0; i < filter->n_preds; i++)
+ filter_free_pred(filter->preds[i]);
+ kfree(filter->preds);
+ filter->preds = NULL;
+ filter->n_preds = 0;
+ }
+
+ mutex_lock(&event_mutex);
+ list_for_each_entry(call, &ftrace_events, list) {
+ if (!call->define_fields)
+ continue;
+
+ if (!strcmp(call->system, system->name)) {
+ filter_disable_preds(call);
+ remove_filter_string(call->filter);
}
}
+ mutex_unlock(&event_mutex);
+}
+
+static int filter_add_pred_fn(struct filter_parse_state *ps,
+ struct ftrace_event_call *call,
+ struct filter_pred *pred,
+ filter_pred_fn_t fn)
+{
+ struct event_filter *filter = call->filter;
+ int idx, err;
+
+ if (filter->n_preds == MAX_FILTER_PRED) {
+ parse_error(ps, FILT_ERR_TOO_MANY_PREDS, 0);
+ return -ENOSPC;
+ }
+
+ idx = filter->n_preds;
+ filter_clear_pred(filter->preds[idx]);
+ err = filter_set_pred(filter->preds[idx], pred, fn);
+ if (err)
+ return err;
- return -ENOSPC;
+ filter->n_preds++;
+ call->filter_active = 1;
+
+ return 0;
}
+enum {
+ FILTER_STATIC_STRING = 1,
+ FILTER_DYN_STRING
+};
+
static int is_string_field(const char *type)
{
if (strchr(type, '[') && strstr(type, "char"))
- return 1;
+ return FILTER_STATIC_STRING;
+
+ if (!strcmp(type, "__str_loc"))
+ return FILTER_DYN_STRING;
return 0;
}
-int filter_add_pred(struct ftrace_event_call *call, struct filter_pred *pred)
+static int is_legal_op(struct ftrace_event_field *field, int op)
+{
+ if (is_string_field(field->type) && (op != OP_EQ && op != OP_NE))
+ return 0;
+
+ return 1;
+}
+
+static filter_pred_fn_t select_comparison_fn(int op, int field_size,
+ int field_is_signed)
+{
+ filter_pred_fn_t fn = NULL;
+
+ switch (field_size) {
+ case 8:
+ if (op == OP_EQ || op == OP_NE)
+ fn = filter_pred_64;
+ else if (field_is_signed)
+ fn = filter_pred_s64;
+ else
+ fn = filter_pred_u64;
+ break;
+ case 4:
+ if (op == OP_EQ || op == OP_NE)
+ fn = filter_pred_32;
+ else if (field_is_signed)
+ fn = filter_pred_s32;
+ else
+ fn = filter_pred_u32;
+ break;
+ case 2:
+ if (op == OP_EQ || op == OP_NE)
+ fn = filter_pred_16;
+ else if (field_is_signed)
+ fn = filter_pred_s16;
+ else
+ fn = filter_pred_u16;
+ break;
+ case 1:
+ if (op == OP_EQ || op == OP_NE)
+ fn = filter_pred_8;
+ else if (field_is_signed)
+ fn = filter_pred_s8;
+ else
+ fn = filter_pred_u8;
+ break;
+ }
+
+ return fn;
+}
+
+static int filter_add_pred(struct filter_parse_state *ps,
+ struct ftrace_event_call *call,
+ struct filter_pred *pred)
{
struct ftrace_event_field *field;
+ filter_pred_fn_t fn;
+ unsigned long long val;
+ int string_type;
+
+ pred->fn = filter_pred_none;
+
+ if (pred->op == OP_AND) {
+ pred->pop_n = 2;
+ return filter_add_pred_fn(ps, call, pred, filter_pred_and);
+ } else if (pred->op == OP_OR) {
+ pred->pop_n = 2;
+ return filter_add_pred_fn(ps, call, pred, filter_pred_or);
+ }
field = find_event_field(call, pred->field_name);
- if (!field)
+ if (!field) {
+ parse_error(ps, FILT_ERR_FIELD_NOT_FOUND, 0);
return -EINVAL;
+ }
pred->offset = field->offset;
- if (is_string_field(field->type)) {
- if (!pred->str_val)
- return -EINVAL;
- pred->fn = filter_pred_string;
+ if (!is_legal_op(field, pred->op)) {
+ parse_error(ps, FILT_ERR_ILLEGAL_FIELD_OP, 0);
+ return -EINVAL;
+ }
+
+ string_type = is_string_field(field->type);
+ if (string_type) {
+ if (string_type == FILTER_STATIC_STRING)
+ fn = filter_pred_string;
+ else
+ fn = filter_pred_strloc;
pred->str_len = field->size;
- return __filter_add_pred(call, pred);
+ if (pred->op == OP_NE)
+ pred->not = 1;
+ return filter_add_pred_fn(ps, call, pred, fn);
} else {
- if (pred->str_val)
+ if (strict_strtoull(pred->str_val, 0, &val)) {
+ parse_error(ps, FILT_ERR_ILLEGAL_INTVAL, 0);
return -EINVAL;
+ }
+ pred->val = val;
}
- switch (field->size) {
- case 8:
- pred->fn = filter_pred_64;
- break;
- case 4:
- pred->fn = filter_pred_32;
- break;
- case 2:
- pred->fn = filter_pred_16;
- break;
- case 1:
- pred->fn = filter_pred_8;
- break;
- default:
+ fn = select_comparison_fn(pred->op, field->size, field->is_signed);
+ if (!fn) {
+ parse_error(ps, FILT_ERR_INVALID_OP, 0);
return -EINVAL;
}
- return __filter_add_pred(call, pred);
+ if (pred->op == OP_NE)
+ pred->not = 1;
+
+ return filter_add_pred_fn(ps, call, pred, fn);
}
-static struct filter_pred *copy_pred(struct filter_pred *pred)
+static int filter_add_subsystem_pred(struct filter_parse_state *ps,
+ struct event_subsystem *system,
+ struct filter_pred *pred,
+ char *filter_string)
{
- struct filter_pred *new_pred = kmalloc(sizeof(*pred), GFP_KERNEL);
- if (!new_pred)
- return NULL;
+ struct event_filter *filter = system->filter;
+ struct ftrace_event_call *call;
+ int err = 0;
+
+ if (!filter->preds) {
+ filter->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred),
+ GFP_KERNEL);
- memcpy(new_pred, pred, sizeof(*pred));
+ if (!filter->preds)
+ return -ENOMEM;
+ }
- if (pred->field_name) {
- new_pred->field_name = kstrdup(pred->field_name, GFP_KERNEL);
- if (!new_pred->field_name) {
- kfree(new_pred);
- return NULL;
- }
+ if (filter->n_preds == MAX_FILTER_PRED) {
+ parse_error(ps, FILT_ERR_TOO_MANY_PREDS, 0);
+ return -ENOSPC;
}
- if (pred->str_val) {
- new_pred->str_val = kstrdup(pred->str_val, GFP_KERNEL);
- if (!new_pred->str_val) {
- filter_free_pred(new_pred);
- return NULL;
+ filter->preds[filter->n_preds] = pred;
+ filter->n_preds++;
+
+ mutex_lock(&event_mutex);
+ list_for_each_entry(call, &ftrace_events, list) {
+
+ if (!call->define_fields)
+ continue;
+
+ if (strcmp(call->system, system->name))
+ continue;
+
+ err = filter_add_pred(ps, call, pred);
+ if (err) {
+ mutex_unlock(&event_mutex);
+ filter_free_subsystem_preds(system);
+ parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0);
+ goto out;
}
+ replace_filter_string(call->filter, filter_string);
}
+ mutex_unlock(&event_mutex);
+out:
+ return err;
+}
+
+static void parse_init(struct filter_parse_state *ps,
+ struct filter_op *ops,
+ char *infix_string)
+{
+ memset(ps, '\0', sizeof(*ps));
- return new_pred;
+ ps->infix.string = infix_string;
+ ps->infix.cnt = strlen(infix_string);
+ ps->ops = ops;
+
+ INIT_LIST_HEAD(&ps->opstack);
+ INIT_LIST_HEAD(&ps->postfix);
}
-int filter_add_subsystem_pred(struct event_subsystem *system,
- struct filter_pred *pred)
+static char infix_next(struct filter_parse_state *ps)
{
- struct ftrace_event_call *call = __start_ftrace_events;
- struct filter_pred *event_pred;
- int i;
+ ps->infix.cnt--;
- if (system->preds && !pred->compound)
- filter_free_subsystem_preds(system);
+ return ps->infix.string[ps->infix.tail++];
+}
- if (!system->preds) {
- system->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred),
- GFP_KERNEL);
- if (!system->preds)
- return -ENOMEM;
+static char infix_peek(struct filter_parse_state *ps)
+{
+ if (ps->infix.tail == strlen(ps->infix.string))
+ return 0;
+
+ return ps->infix.string[ps->infix.tail];
+}
+
+static void infix_advance(struct filter_parse_state *ps)
+{
+ ps->infix.cnt--;
+ ps->infix.tail++;
+}
+
+static inline int is_precedence_lower(struct filter_parse_state *ps,
+ int a, int b)
+{
+ return ps->ops[a].precedence < ps->ops[b].precedence;
+}
+
+static inline int is_op_char(struct filter_parse_state *ps, char c)
+{
+ int i;
+
+ for (i = 0; strcmp(ps->ops[i].string, "OP_NONE"); i++) {
+ if (ps->ops[i].string[0] == c)
+ return 1;
}
- for (i = 0; i < MAX_FILTER_PRED; i++) {
- if (!system->preds[i]) {
- system->preds[i] = pred;
- break;
+ return 0;
+}
+
+static int infix_get_op(struct filter_parse_state *ps, char firstc)
+{
+ char nextc = infix_peek(ps);
+ char opstr[3];
+ int i;
+
+ opstr[0] = firstc;
+ opstr[1] = nextc;
+ opstr[2] = '\0';
+
+ for (i = 0; strcmp(ps->ops[i].string, "OP_NONE"); i++) {
+ if (!strcmp(opstr, ps->ops[i].string)) {
+ infix_advance(ps);
+ return ps->ops[i].id;
}
}
- if (i == MAX_FILTER_PRED)
- return -ENOSPC;
+ opstr[1] = '\0';
+
+ for (i = 0; strcmp(ps->ops[i].string, "OP_NONE"); i++) {
+ if (!strcmp(opstr, ps->ops[i].string))
+ return ps->ops[i].id;
+ }
+
+ return OP_NONE;
+}
+
+static inline void clear_operand_string(struct filter_parse_state *ps)
+{
+ memset(ps->operand.string, '\0', MAX_FILTER_STR_VAL);
+ ps->operand.tail = 0;
+}
+
+static inline int append_operand_char(struct filter_parse_state *ps, char c)
+{
+ if (ps->operand.tail == MAX_FILTER_STR_VAL)
+ return -EINVAL;
+
+ ps->operand.string[ps->operand.tail++] = c;
+
+ return 0;
+}
+
+static int filter_opstack_push(struct filter_parse_state *ps, int op)
+{
+ struct opstack_op *opstack_op;
+
+ opstack_op = kmalloc(sizeof(*opstack_op), GFP_KERNEL);
+ if (!opstack_op)
+ return -ENOMEM;
+
+ opstack_op->op = op;
+ list_add(&opstack_op->list, &ps->opstack);
+
+ return 0;
+}
+
+static int filter_opstack_empty(struct filter_parse_state *ps)
+{
+ return list_empty(&ps->opstack);
+}
+
+static int filter_opstack_top(struct filter_parse_state *ps)
+{
+ struct opstack_op *opstack_op;
+
+ if (filter_opstack_empty(ps))
+ return OP_NONE;
+
+ opstack_op = list_first_entry(&ps->opstack, struct opstack_op, list);
+
+ return opstack_op->op;
+}
+
+static int filter_opstack_pop(struct filter_parse_state *ps)
+{
+ struct opstack_op *opstack_op;
+ int op;
+
+ if (filter_opstack_empty(ps))
+ return OP_NONE;
+
+ opstack_op = list_first_entry(&ps->opstack, struct opstack_op, list);
+ op = opstack_op->op;
+ list_del(&opstack_op->list);
+
+ kfree(opstack_op);
+
+ return op;
+}
+
+static void filter_opstack_clear(struct filter_parse_state *ps)
+{
+ while (!filter_opstack_empty(ps))
+ filter_opstack_pop(ps);
+}
+
+static char *curr_operand(struct filter_parse_state *ps)
+{
+ return ps->operand.string;
+}
+
+static int postfix_append_operand(struct filter_parse_state *ps, char *operand)
+{
+ struct postfix_elt *elt;
+
+ elt = kmalloc(sizeof(*elt), GFP_KERNEL);
+ if (!elt)
+ return -ENOMEM;
+
+ elt->op = OP_NONE;
+ elt->operand = kstrdup(operand, GFP_KERNEL);
+ if (!elt->operand) {
+ kfree(elt);
+ return -ENOMEM;
+ }
+
+ list_add_tail(&elt->list, &ps->postfix);
+
+ return 0;
+}
+
+static int postfix_append_op(struct filter_parse_state *ps, int op)
+{
+ struct postfix_elt *elt;
+
+ elt = kmalloc(sizeof(*elt), GFP_KERNEL);
+ if (!elt)
+ return -ENOMEM;
+
+ elt->op = op;
+ elt->operand = NULL;
+
+ list_add_tail(&elt->list, &ps->postfix);
+
+ return 0;
+}
+
+static void postfix_clear(struct filter_parse_state *ps)
+{
+ struct postfix_elt *elt;
+
+ while (!list_empty(&ps->postfix)) {
+ elt = list_first_entry(&ps->postfix, struct postfix_elt, list);
+ kfree(elt->operand);
+ list_del(&elt->list);
+ }
+}
- events_for_each(call) {
- int err;
+static int filter_parse(struct filter_parse_state *ps)
+{
+ int in_string = 0;
+ int op, top_op;
+ char ch;
- if (!call->name || !call->regfunc)
+ while ((ch = infix_next(ps))) {
+ if (ch == '"') {
+ in_string ^= 1;
continue;
+ }
- if (strcmp(call->system, system->name))
+ if (in_string)
+ goto parse_operand;
+
+ if (isspace(ch))
continue;
- if (!find_event_field(call, pred->field_name))
+ if (is_op_char(ps, ch)) {
+ op = infix_get_op(ps, ch);
+ if (op == OP_NONE) {
+ parse_error(ps, FILT_ERR_INVALID_OP, 0);
+ return -EINVAL;
+ }
+
+ if (strlen(curr_operand(ps))) {
+ postfix_append_operand(ps, curr_operand(ps));
+ clear_operand_string(ps);
+ }
+
+ while (!filter_opstack_empty(ps)) {
+ top_op = filter_opstack_top(ps);
+ if (!is_precedence_lower(ps, top_op, op)) {
+ top_op = filter_opstack_pop(ps);
+ postfix_append_op(ps, top_op);
+ continue;
+ }
+ break;
+ }
+
+ filter_opstack_push(ps, op);
continue;
+ }
- event_pred = copy_pred(pred);
- if (!event_pred)
- goto oom;
+ if (ch == '(') {
+ filter_opstack_push(ps, OP_OPEN_PAREN);
+ continue;
+ }
- err = filter_add_pred(call, event_pred);
- if (err)
- filter_free_pred(event_pred);
- if (err == -ENOMEM)
- goto oom;
+ if (ch == ')') {
+ if (strlen(curr_operand(ps))) {
+ postfix_append_operand(ps, curr_operand(ps));
+ clear_operand_string(ps);
+ }
+
+ top_op = filter_opstack_pop(ps);
+ while (top_op != OP_NONE) {
+ if (top_op == OP_OPEN_PAREN)
+ break;
+ postfix_append_op(ps, top_op);
+ top_op = filter_opstack_pop(ps);
+ }
+ if (top_op == OP_NONE) {
+ parse_error(ps, FILT_ERR_UNBALANCED_PAREN, 0);
+ return -EINVAL;
+ }
+ continue;
+ }
+parse_operand:
+ if (append_operand_char(ps, ch)) {
+ parse_error(ps, FILT_ERR_OPERAND_TOO_LONG, 0);
+ return -EINVAL;
+ }
+ }
+
+ if (strlen(curr_operand(ps)))
+ postfix_append_operand(ps, curr_operand(ps));
+
+ while (!filter_opstack_empty(ps)) {
+ top_op = filter_opstack_pop(ps);
+ if (top_op == OP_NONE)
+ break;
+ if (top_op == OP_OPEN_PAREN) {
+ parse_error(ps, FILT_ERR_UNBALANCED_PAREN, 0);
+ return -EINVAL;
+ }
+ postfix_append_op(ps, top_op);
}
return 0;
+}
-oom:
- system->preds[i] = NULL;
- return -ENOMEM;
+static struct filter_pred *create_pred(int op, char *operand1, char *operand2)
+{
+ struct filter_pred *pred;
+
+ pred = kzalloc(sizeof(*pred), GFP_KERNEL);
+ if (!pred)
+ return NULL;
+
+ pred->field_name = kstrdup(operand1, GFP_KERNEL);
+ if (!pred->field_name) {
+ kfree(pred);
+ return NULL;
+ }
+
+ strcpy(pred->str_val, operand2);
+ pred->str_len = strlen(operand2);
+
+ pred->op = op;
+
+ return pred;
}
-int filter_parse(char **pbuf, struct filter_pred *pred)
+static struct filter_pred *create_logical_pred(int op)
{
- char *tmp, *tok, *val_str = NULL;
- int tok_n = 0;
+ struct filter_pred *pred;
- /* field ==/!= number, or/and field ==/!= number, number */
- while ((tok = strsep(pbuf, " \n"))) {
- if (tok_n == 0) {
- if (!strcmp(tok, "0")) {
- pred->clear = 1;
- return 0;
- } else if (!strcmp(tok, "&&")) {
- pred->or = 0;
- pred->compound = 1;
- } else if (!strcmp(tok, "||")) {
- pred->or = 1;
- pred->compound = 1;
- } else
- pred->field_name = tok;
- tok_n = 1;
+ pred = kzalloc(sizeof(*pred), GFP_KERNEL);
+ if (!pred)
+ return NULL;
+
+ pred->op = op;
+
+ return pred;
+}
+
+static int check_preds(struct filter_parse_state *ps)
+{
+ int n_normal_preds = 0, n_logical_preds = 0;
+ struct postfix_elt *elt;
+
+ list_for_each_entry(elt, &ps->postfix, list) {
+ if (elt->op == OP_NONE)
+ continue;
+
+ if (elt->op == OP_AND || elt->op == OP_OR) {
+ n_logical_preds++;
continue;
}
- if (tok_n == 1) {
- if (!pred->field_name)
- pred->field_name = tok;
- else if (!strcmp(tok, "!="))
- pred->not = 1;
- else if (!strcmp(tok, "=="))
- pred->not = 0;
+ n_normal_preds++;
+ }
+
+ if (!n_normal_preds || n_logical_preds >= n_normal_preds) {
+ parse_error(ps, FILT_ERR_INVALID_FILTER, 0);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int replace_preds(struct event_subsystem *system,
+ struct ftrace_event_call *call,
+ struct filter_parse_state *ps,
+ char *filter_string)
+{
+ char *operand1 = NULL, *operand2 = NULL;
+ struct filter_pred *pred;
+ struct postfix_elt *elt;
+ int err;
+
+ err = check_preds(ps);
+ if (err)
+ return err;
+
+ list_for_each_entry(elt, &ps->postfix, list) {
+ if (elt->op == OP_NONE) {
+ if (!operand1)
+ operand1 = elt->operand;
+ else if (!operand2)
+ operand2 = elt->operand;
else {
- pred->field_name = NULL;
+ parse_error(ps, FILT_ERR_TOO_MANY_OPERANDS, 0);
return -EINVAL;
}
- tok_n = 2;
continue;
}
- if (tok_n == 2) {
- if (pred->compound) {
- if (!strcmp(tok, "!="))
- pred->not = 1;
- else if (!strcmp(tok, "=="))
- pred->not = 0;
- else {
- pred->field_name = NULL;
- return -EINVAL;
- }
- } else {
- val_str = tok;
- break; /* done */
- }
- tok_n = 3;
+
+ if (elt->op == OP_AND || elt->op == OP_OR) {
+ pred = create_logical_pred(elt->op);
+ if (call) {
+ err = filter_add_pred(ps, call, pred);
+ filter_free_pred(pred);
+ } else
+ err = filter_add_subsystem_pred(ps, system,
+ pred, filter_string);
+ if (err)
+ return err;
+
+ operand1 = operand2 = NULL;
continue;
}
- if (tok_n == 3) {
- val_str = tok;
- break; /* done */
+
+ if (!operand1 || !operand2) {
+ parse_error(ps, FILT_ERR_MISSING_FIELD, 0);
+ return -EINVAL;
}
+
+ pred = create_pred(elt->op, operand1, operand2);
+ if (call) {
+ err = filter_add_pred(ps, call, pred);
+ filter_free_pred(pred);
+ } else
+ err = filter_add_subsystem_pred(ps, system, pred,
+ filter_string);
+ if (err)
+ return err;
+
+ operand1 = operand2 = NULL;
}
- if (!val_str) {
- pred->field_name = NULL;
- return -EINVAL;
+ return 0;
+}
+
+int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
+{
+ int err;
+
+ struct filter_parse_state *ps;
+
+ mutex_lock(&filter_mutex);
+
+ if (!strcmp(strstrip(filter_string), "0")) {
+ filter_disable_preds(call);
+ remove_filter_string(call->filter);
+ mutex_unlock(&filter_mutex);
+ return 0;
}
- pred->field_name = kstrdup(pred->field_name, GFP_KERNEL);
- if (!pred->field_name)
+ ps = kzalloc(sizeof(*ps), GFP_KERNEL);
+ if (!ps)
return -ENOMEM;
- pred->val = simple_strtoull(val_str, &tmp, 0);
- if (tmp == val_str) {
- pred->str_val = kstrdup(val_str, GFP_KERNEL);
- if (!pred->str_val)
- return -ENOMEM;
- } else if (*tmp != '\0')
- return -EINVAL;
+ filter_disable_preds(call);
+ replace_filter_string(call->filter, filter_string);
- return 0;
+ parse_init(ps, filter_ops, filter_string);
+ err = filter_parse(ps);
+ if (err) {
+ append_filter_err(ps, call->filter);
+ goto out;
+ }
+
+ err = replace_preds(NULL, call, ps, filter_string);
+ if (err)
+ append_filter_err(ps, call->filter);
+
+out:
+ filter_opstack_clear(ps);
+ postfix_clear(ps);
+ kfree(ps);
+
+ mutex_unlock(&filter_mutex);
+
+ return err;
}
+int apply_subsystem_event_filter(struct event_subsystem *system,
+ char *filter_string)
+{
+ int err;
+
+ struct filter_parse_state *ps;
+
+ mutex_lock(&filter_mutex);
+
+ if (!strcmp(strstrip(filter_string), "0")) {
+ filter_free_subsystem_preds(system);
+ remove_filter_string(system->filter);
+ mutex_unlock(&filter_mutex);
+ return 0;
+ }
+
+ ps = kzalloc(sizeof(*ps), GFP_KERNEL);
+ if (!ps)
+ return -ENOMEM;
+
+ filter_free_subsystem_preds(system);
+ replace_filter_string(system->filter, filter_string);
+
+ parse_init(ps, filter_ops, filter_string);
+ err = filter_parse(ps);
+ if (err) {
+ append_filter_err(ps, system->filter);
+ goto out;
+ }
+
+ err = replace_preds(system, NULL, ps, filter_string);
+ if (err)
+ append_filter_err(ps, system->filter);
+
+out:
+ filter_opstack_clear(ps);
+ postfix_clear(ps);
+ kfree(ps);
+
+ mutex_unlock(&filter_mutex);
+
+ return err;
+}
diff --git a/kernel/trace/trace_events_stage_1.h b/kernel/trace/trace_events_stage_1.h
deleted file mode 100644
index 38985f9b379c..000000000000
--- a/kernel/trace/trace_events_stage_1.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Stage 1 of the trace events.
- *
- * Override the macros in <trace/trace_event_types.h> to include the following:
- *
- * struct ftrace_raw_<call> {
- * struct trace_entry ent;
- * <type> <item>;
- * <type2> <item2>[<len>];
- * [...]
- * };
- *
- * The <type> <item> is created by the __field(type, item) macro or
- * the __array(type2, item2, len) macro.
- * We simply do "type item;", and that will create the fields
- * in the structure.
- */
-
-#undef TRACE_FORMAT
-#define TRACE_FORMAT(call, proto, args, fmt)
-
-#undef __array
-#define __array(type, item, len) type item[len];
-
-#undef __field
-#define __field(type, item) type item;
-
-#undef TP_STRUCT__entry
-#define TP_STRUCT__entry(args...) args
-
-#undef TRACE_EVENT
-#define TRACE_EVENT(name, proto, args, tstruct, assign, print) \
- struct ftrace_raw_##name { \
- struct trace_entry ent; \
- tstruct \
- }; \
- static struct ftrace_event_call event_##name
-
-#include <trace/trace_event_types.h>
diff --git a/kernel/trace/trace_events_stage_2.h b/kernel/trace/trace_events_stage_2.h
deleted file mode 100644
index d363c6672c6c..000000000000
--- a/kernel/trace/trace_events_stage_2.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Stage 2 of the trace events.
- *
- * Override the macros in <trace/trace_event_types.h> to include the following:
- *
- * enum print_line_t
- * ftrace_raw_output_<call>(struct trace_iterator *iter, int flags)
- * {
- * struct trace_seq *s = &iter->seq;
- * struct ftrace_raw_<call> *field; <-- defined in stage 1
- * struct trace_entry *entry;
- * int ret;
- *
- * entry = iter->ent;
- *
- * if (entry->type != event_<call>.id) {
- * WARN_ON_ONCE(1);
- * return TRACE_TYPE_UNHANDLED;
- * }
- *
- * field = (typeof(field))entry;
- *
- * ret = trace_seq_printf(s, <TP_printk> "\n");
- * if (!ret)
- * return TRACE_TYPE_PARTIAL_LINE;
- *
- * return TRACE_TYPE_HANDLED;
- * }
- *
- * This is the method used to print the raw event to the trace
- * output format. Note, this is not needed if the data is read
- * in binary.
- */
-
-#undef __entry
-#define __entry field
-
-#undef TP_printk
-#define TP_printk(fmt, args...) fmt "\n", args
-
-#undef TRACE_EVENT
-#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
-enum print_line_t \
-ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \
-{ \
- struct trace_seq *s = &iter->seq; \
- struct ftrace_raw_##call *field; \
- struct trace_entry *entry; \
- int ret; \
- \
- entry = iter->ent; \
- \
- if (entry->type != event_##call.id) { \
- WARN_ON_ONCE(1); \
- return TRACE_TYPE_UNHANDLED; \
- } \
- \
- field = (typeof(field))entry; \
- \
- ret = trace_seq_printf(s, #call ": " print); \
- if (!ret) \
- return TRACE_TYPE_PARTIAL_LINE; \
- \
- return TRACE_TYPE_HANDLED; \
-}
-
-#include <trace/trace_event_types.h>
-
-/*
- * Setup the showing format of trace point.
- *
- * int
- * ftrace_format_##call(struct trace_seq *s)
- * {
- * struct ftrace_raw_##call field;
- * int ret;
- *
- * ret = trace_seq_printf(s, #type " " #item ";"
- * " offset:%u; size:%u;\n",
- * offsetof(struct ftrace_raw_##call, item),
- * sizeof(field.type));
- *
- * }
- */
-
-#undef TP_STRUCT__entry
-#define TP_STRUCT__entry(args...) args
-
-#undef __field
-#define __field(type, item) \
- ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \
- "offset:%u;\tsize:%u;\n", \
- (unsigned int)offsetof(typeof(field), item), \
- (unsigned int)sizeof(field.item)); \
- if (!ret) \
- return 0;
-
-#undef __array
-#define __array(type, item, len) \
- ret = trace_seq_printf(s, "\tfield:" #type " " #item "[" #len "];\t" \
- "offset:%u;\tsize:%u;\n", \
- (unsigned int)offsetof(typeof(field), item), \
- (unsigned int)sizeof(field.item)); \
- if (!ret) \
- return 0;
-
-#undef __entry
-#define __entry REC
-
-#undef TP_printk
-#define TP_printk(fmt, args...) "%s, %s\n", #fmt, __stringify(args)
-
-#undef TP_fast_assign
-#define TP_fast_assign(args...) args
-
-#undef TRACE_EVENT
-#define TRACE_EVENT(call, proto, args, tstruct, func, print) \
-static int \
-ftrace_format_##call(struct trace_seq *s) \
-{ \
- struct ftrace_raw_##call field; \
- int ret; \
- \
- tstruct; \
- \
- trace_seq_printf(s, "\nprint fmt: " print); \
- \
- return ret; \
-}
-
-#include <trace/trace_event_types.h>
-
-#undef __field
-#define __field(type, item) \
- ret = trace_define_field(event_call, #type, #item, \
- offsetof(typeof(field), item), \
- sizeof(field.item)); \
- if (ret) \
- return ret;
-
-#undef __array
-#define __array(type, item, len) \
- ret = trace_define_field(event_call, #type "[" #len "]", #item, \
- offsetof(typeof(field), item), \
- sizeof(field.item)); \
- if (ret) \
- return ret;
-
-#define __common_field(type, item) \
- ret = trace_define_field(event_call, #type, "common_" #item, \
- offsetof(typeof(field.ent), item), \
- sizeof(field.ent.item)); \
- if (ret) \
- return ret;
-
-#undef TRACE_EVENT
-#define TRACE_EVENT(call, proto, args, tstruct, func, print) \
-int \
-ftrace_define_fields_##call(void) \
-{ \
- struct ftrace_raw_##call field; \
- struct ftrace_event_call *event_call = &event_##call; \
- int ret; \
- \
- __common_field(unsigned char, type); \
- __common_field(unsigned char, flags); \
- __common_field(unsigned char, preempt_count); \
- __common_field(int, pid); \
- __common_field(int, tgid); \
- \
- tstruct; \
- \
- return ret; \
-}
-
-#include <trace/trace_event_types.h>
diff --git a/kernel/trace/trace_events_stage_3.h b/kernel/trace/trace_events_stage_3.h
deleted file mode 100644
index 9d2fa78cecca..000000000000
--- a/kernel/trace/trace_events_stage_3.h
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Stage 3 of the trace events.
- *
- * Override the macros in <trace/trace_event_types.h> to include the following:
- *
- * static void ftrace_event_<call>(proto)
- * {
- * event_trace_printk(_RET_IP_, "<call>: " <fmt>);
- * }
- *
- * static int ftrace_reg_event_<call>(void)
- * {
- * int ret;
- *
- * ret = register_trace_<call>(ftrace_event_<call>);
- * if (!ret)
- * pr_info("event trace: Could not activate trace point "
- * "probe to <call>");
- * return ret;
- * }
- *
- * static void ftrace_unreg_event_<call>(void)
- * {
- * unregister_trace_<call>(ftrace_event_<call>);
- * }
- *
- * For those macros defined with TRACE_FORMAT:
- *
- * static struct ftrace_event_call __used
- * __attribute__((__aligned__(4)))
- * __attribute__((section("_ftrace_events"))) event_<call> = {
- * .name = "<call>",
- * .regfunc = ftrace_reg_event_<call>,
- * .unregfunc = ftrace_unreg_event_<call>,
- * }
- *
- *
- * For those macros defined with TRACE_EVENT:
- *
- * static struct ftrace_event_call event_<call>;
- *
- * static void ftrace_raw_event_<call>(proto)
- * {
- * struct ring_buffer_event *event;
- * struct ftrace_raw_<call> *entry; <-- defined in stage 1
- * unsigned long irq_flags;
- * int pc;
- *
- * local_save_flags(irq_flags);
- * pc = preempt_count();
- *
- * event = trace_current_buffer_lock_reserve(event_<call>.id,
- * sizeof(struct ftrace_raw_<call>),
- * irq_flags, pc);
- * if (!event)
- * return;
- * entry = ring_buffer_event_data(event);
- *
- * <assign>; <-- Here we assign the entries by the __field and
- * __array macros.
- *
- * trace_current_buffer_unlock_commit(event, irq_flags, pc);
- * }
- *
- * static int ftrace_raw_reg_event_<call>(void)
- * {
- * int ret;
- *
- * ret = register_trace_<call>(ftrace_raw_event_<call>);
- * if (!ret)
- * pr_info("event trace: Could not activate trace point "
- * "probe to <call>");
- * return ret;
- * }
- *
- * static void ftrace_unreg_event_<call>(void)
- * {
- * unregister_trace_<call>(ftrace_raw_event_<call>);
- * }
- *
- * static struct trace_event ftrace_event_type_<call> = {
- * .trace = ftrace_raw_output_<call>, <-- stage 2
- * };
- *
- * static int ftrace_raw_init_event_<call>(void)
- * {
- * int id;
- *
- * id = register_ftrace_event(&ftrace_event_type_<call>);
- * if (!id)
- * return -ENODEV;
- * event_<call>.id = id;
- * return 0;
- * }
- *
- * static struct ftrace_event_call __used
- * __attribute__((__aligned__(4)))
- * __attribute__((section("_ftrace_events"))) event_<call> = {
- * .name = "<call>",
- * .system = "<system>",
- * .raw_init = ftrace_raw_init_event_<call>,
- * .regfunc = ftrace_reg_event_<call>,
- * .unregfunc = ftrace_unreg_event_<call>,
- * .show_format = ftrace_format_<call>,
- * }
- *
- */
-
-#undef TP_FMT
-#define TP_FMT(fmt, args...) fmt "\n", ##args
-
-#ifdef CONFIG_EVENT_PROFILE
-#define _TRACE_PROFILE(call, proto, args) \
-static void ftrace_profile_##call(proto) \
-{ \
- extern void perf_tpcounter_event(int); \
- perf_tpcounter_event(event_##call.id); \
-} \
- \
-static int ftrace_profile_enable_##call(struct ftrace_event_call *call) \
-{ \
- int ret = 0; \
- \
- if (!atomic_inc_return(&call->profile_count)) \
- ret = register_trace_##call(ftrace_profile_##call); \
- \
- return ret; \
-} \
- \
-static void ftrace_profile_disable_##call(struct ftrace_event_call *call) \
-{ \
- if (atomic_add_negative(-1, &call->profile_count)) \
- unregister_trace_##call(ftrace_profile_##call); \
-}
-
-#define _TRACE_PROFILE_INIT(call) \
- .profile_count = ATOMIC_INIT(-1), \
- .profile_enable = ftrace_profile_enable_##call, \
- .profile_disable = ftrace_profile_disable_##call,
-
-#else
-#define _TRACE_PROFILE(call, proto, args)
-#define _TRACE_PROFILE_INIT(call)
-#endif
-
-#define _TRACE_FORMAT(call, proto, args, fmt) \
-static void ftrace_event_##call(proto) \
-{ \
- event_trace_printk(_RET_IP_, #call ": " fmt); \
-} \
- \
-static int ftrace_reg_event_##call(void) \
-{ \
- int ret; \
- \
- ret = register_trace_##call(ftrace_event_##call); \
- if (ret) \
- pr_info("event trace: Could not activate trace point " \
- "probe to " #call "\n"); \
- return ret; \
-} \
- \
-static void ftrace_unreg_event_##call(void) \
-{ \
- unregister_trace_##call(ftrace_event_##call); \
-} \
- \
-static struct ftrace_event_call event_##call; \
- \
-static int ftrace_init_event_##call(void) \
-{ \
- int id; \
- \
- id = register_ftrace_event(NULL); \
- if (!id) \
- return -ENODEV; \
- event_##call.id = id; \
- return 0; \
-}
-
-#undef TRACE_FORMAT
-#define TRACE_FORMAT(call, proto, args, fmt) \
-_TRACE_FORMAT(call, PARAMS(proto), PARAMS(args), PARAMS(fmt)) \
-_TRACE_PROFILE(call, PARAMS(proto), PARAMS(args)) \
-static struct ftrace_event_call __used \
-__attribute__((__aligned__(4))) \
-__attribute__((section("_ftrace_events"))) event_##call = { \
- .name = #call, \
- .system = __stringify(TRACE_SYSTEM), \
- .raw_init = ftrace_init_event_##call, \
- .regfunc = ftrace_reg_event_##call, \
- .unregfunc = ftrace_unreg_event_##call, \
- _TRACE_PROFILE_INIT(call) \
-}
-
-#undef __entry
-#define __entry entry
-
-#undef TRACE_EVENT
-#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
-_TRACE_PROFILE(call, PARAMS(proto), PARAMS(args)) \
- \
-static struct ftrace_event_call event_##call; \
- \
-static void ftrace_raw_event_##call(proto) \
-{ \
- struct ftrace_event_call *call = &event_##call; \
- struct ring_buffer_event *event; \
- struct ftrace_raw_##call *entry; \
- unsigned long irq_flags; \
- int pc; \
- \
- local_save_flags(irq_flags); \
- pc = preempt_count(); \
- \
- event = trace_current_buffer_lock_reserve(event_##call.id, \
- sizeof(struct ftrace_raw_##call), \
- irq_flags, pc); \
- if (!event) \
- return; \
- entry = ring_buffer_event_data(event); \
- \
- assign; \
- \
- if (call->preds && !filter_match_preds(call, entry)) \
- ring_buffer_event_discard(event); \
- \
- trace_nowake_buffer_unlock_commit(event, irq_flags, pc); \
- \
-} \
- \
-static int ftrace_raw_reg_event_##call(void) \
-{ \
- int ret; \
- \
- ret = register_trace_##call(ftrace_raw_event_##call); \
- if (ret) \
- pr_info("event trace: Could not activate trace point " \
- "probe to " #call "\n"); \
- return ret; \
-} \
- \
-static void ftrace_raw_unreg_event_##call(void) \
-{ \
- unregister_trace_##call(ftrace_raw_event_##call); \
-} \
- \
-static struct trace_event ftrace_event_type_##call = { \
- .trace = ftrace_raw_output_##call, \
-}; \
- \
-static int ftrace_raw_init_event_##call(void) \
-{ \
- int id; \
- \
- id = register_ftrace_event(&ftrace_event_type_##call); \
- if (!id) \
- return -ENODEV; \
- event_##call.id = id; \
- INIT_LIST_HEAD(&event_##call.fields); \
- return 0; \
-} \
- \
-static struct ftrace_event_call __used \
-__attribute__((__aligned__(4))) \
-__attribute__((section("_ftrace_events"))) event_##call = { \
- .name = #call, \
- .system = __stringify(TRACE_SYSTEM), \
- .raw_init = ftrace_raw_init_event_##call, \
- .regfunc = ftrace_raw_reg_event_##call, \
- .unregfunc = ftrace_raw_unreg_event_##call, \
- .show_format = ftrace_format_##call, \
- .define_fields = ftrace_define_fields_##call, \
- _TRACE_PROFILE_INIT(call) \
-}
-
-#include <trace/trace_event_types.h>
-
-#undef _TRACE_PROFILE
-#undef _TRACE_PROFILE_INIT
-
diff --git a/kernel/trace/trace_export.c b/kernel/trace/trace_export.c
index 07a22c33ebf3..d06cf898dc86 100644
--- a/kernel/trace/trace_export.c
+++ b/kernel/trace/trace_export.c
@@ -19,8 +19,12 @@
#undef TRACE_STRUCT
#define TRACE_STRUCT(args...) args
+extern void __bad_type_size(void);
+
#undef TRACE_FIELD
#define TRACE_FIELD(type, item, assign) \
+ if (sizeof(type) != sizeof(field.item)) \
+ __bad_type_size(); \
ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \
"offset:%u;\tsize:%u;\n", \
(unsigned int)offsetof(typeof(field), item), \
@@ -30,7 +34,7 @@
#undef TRACE_FIELD_SPECIAL
-#define TRACE_FIELD_SPECIAL(type_item, item, cmd) \
+#define TRACE_FIELD_SPECIAL(type_item, item, len, cmd) \
ret = trace_seq_printf(s, "\tfield special:" #type_item ";\t" \
"offset:%u;\tsize:%u;\n", \
(unsigned int)offsetof(typeof(field), item), \
@@ -46,6 +50,9 @@
if (!ret) \
return 0;
+#undef TRACE_FIELD_SIGN
+#define TRACE_FIELD_SIGN(type, item, assign, is_signed) \
+ TRACE_FIELD(type, item, assign)
#undef TP_RAW_FMT
#define TP_RAW_FMT(args...) args
@@ -65,6 +72,22 @@ ftrace_format_##call(struct trace_seq *s) \
return ret; \
}
+#undef TRACE_EVENT_FORMAT_NOFILTER
+#define TRACE_EVENT_FORMAT_NOFILTER(call, proto, args, fmt, tstruct, \
+ tpfmt) \
+static int \
+ftrace_format_##call(struct trace_seq *s) \
+{ \
+ struct args field; \
+ int ret; \
+ \
+ tstruct; \
+ \
+ trace_seq_printf(s, "\nprint fmt: \"%s\"\n", tpfmt); \
+ \
+ return ret; \
+}
+
#include "trace_event_types.h"
#undef TRACE_ZERO_CHAR
@@ -78,6 +101,10 @@ ftrace_format_##call(struct trace_seq *s) \
#define TRACE_FIELD(type, item, assign)\
entry->item = assign;
+#undef TRACE_FIELD_SIGN
+#define TRACE_FIELD_SIGN(type, item, assign, is_signed) \
+ TRACE_FIELD(type, item, assign)
+
#undef TP_CMD
#define TP_CMD(cmd...) cmd
@@ -85,18 +112,95 @@ ftrace_format_##call(struct trace_seq *s) \
#define TRACE_ENTRY entry
#undef TRACE_FIELD_SPECIAL
-#define TRACE_FIELD_SPECIAL(type_item, item, cmd) \
+#define TRACE_FIELD_SPECIAL(type_item, item, len, cmd) \
cmd;
#undef TRACE_EVENT_FORMAT
#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt) \
+int ftrace_define_fields_##call(void); \
+static int ftrace_raw_init_event_##call(void); \
+ \
+struct ftrace_event_call __used \
+__attribute__((__aligned__(4))) \
+__attribute__((section("_ftrace_events"))) event_##call = { \
+ .name = #call, \
+ .id = proto, \
+ .system = __stringify(TRACE_SYSTEM), \
+ .raw_init = ftrace_raw_init_event_##call, \
+ .show_format = ftrace_format_##call, \
+ .define_fields = ftrace_define_fields_##call, \
+}; \
+static int ftrace_raw_init_event_##call(void) \
+{ \
+ INIT_LIST_HEAD(&event_##call.fields); \
+ init_preds(&event_##call); \
+ return 0; \
+} \
+
+#undef TRACE_EVENT_FORMAT_NOFILTER
+#define TRACE_EVENT_FORMAT_NOFILTER(call, proto, args, fmt, tstruct, \
+ tpfmt) \
\
-static struct ftrace_event_call __used \
+struct ftrace_event_call __used \
__attribute__((__aligned__(4))) \
__attribute__((section("_ftrace_events"))) event_##call = { \
.name = #call, \
.id = proto, \
.system = __stringify(TRACE_SYSTEM), \
.show_format = ftrace_format_##call, \
+};
+
+#include "trace_event_types.h"
+
+#undef TRACE_FIELD
+#define TRACE_FIELD(type, item, assign) \
+ ret = trace_define_field(event_call, #type, #item, \
+ offsetof(typeof(field), item), \
+ sizeof(field.item), is_signed_type(type)); \
+ if (ret) \
+ return ret;
+
+#undef TRACE_FIELD_SPECIAL
+#define TRACE_FIELD_SPECIAL(type, item, len, cmd) \
+ ret = trace_define_field(event_call, #type "[" #len "]", #item, \
+ offsetof(typeof(field), item), \
+ sizeof(field.item), 0); \
+ if (ret) \
+ return ret;
+
+#undef TRACE_FIELD_SIGN
+#define TRACE_FIELD_SIGN(type, item, assign, is_signed) \
+ ret = trace_define_field(event_call, #type, #item, \
+ offsetof(typeof(field), item), \
+ sizeof(field.item), is_signed); \
+ if (ret) \
+ return ret;
+
+#undef TRACE_FIELD_ZERO_CHAR
+#define TRACE_FIELD_ZERO_CHAR(item)
+
+#undef TRACE_EVENT_FORMAT
+#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt) \
+int \
+ftrace_define_fields_##call(void) \
+{ \
+ struct ftrace_event_call *event_call = &event_##call; \
+ struct args field; \
+ int ret; \
+ \
+ __common_field(unsigned char, type, 0); \
+ __common_field(unsigned char, flags, 0); \
+ __common_field(unsigned char, preempt_count, 0); \
+ __common_field(int, pid, 1); \
+ __common_field(int, tgid, 1); \
+ \
+ tstruct; \
+ \
+ return ret; \
}
+
+#undef TRACE_EVENT_FORMAT_NOFILTER
+#define TRACE_EVENT_FORMAT_NOFILTER(call, proto, args, fmt, tstruct, \
+ tpfmt)
+
#include "trace_event_types.h"
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index d28687e7b3a7..10f6ad7d85f6 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -78,13 +78,14 @@ ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth)
current->ret_stack[index].ret = ret;
current->ret_stack[index].func = func;
current->ret_stack[index].calltime = calltime;
+ current->ret_stack[index].subtime = 0;
*depth = index;
return 0;
}
/* Retrieve a function return address to the trace stack on thread info.*/
-void
+static void
ftrace_pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret)
{
int index;
@@ -104,9 +105,6 @@ ftrace_pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret)
trace->calltime = current->ret_stack[index].calltime;
trace->overrun = atomic_read(&current->trace_overrun);
trace->depth = index;
- barrier();
- current->curr_ret_stack--;
-
}
/*
@@ -121,6 +119,8 @@ unsigned long ftrace_return_to_handler(void)
ftrace_pop_return_trace(&trace, &ret);
trace.rettime = trace_clock_local();
ftrace_graph_return(&trace);
+ barrier();
+ current->curr_ret_stack--;
if (unlikely(!ret)) {
ftrace_graph_stop();
@@ -426,8 +426,8 @@ print_graph_irq(struct trace_iterator *iter, unsigned long addr,
return TRACE_TYPE_HANDLED;
}
-static enum print_line_t
-print_graph_duration(unsigned long long duration, struct trace_seq *s)
+enum print_line_t
+trace_print_graph_duration(unsigned long long duration, struct trace_seq *s)
{
unsigned long nsecs_rem = do_div(duration, 1000);
/* log10(ULONG_MAX) + '\0' */
@@ -464,12 +464,23 @@ print_graph_duration(unsigned long long duration, struct trace_seq *s)
if (!ret)
return TRACE_TYPE_PARTIAL_LINE;
}
+ return TRACE_TYPE_HANDLED;
+}
+
+static enum print_line_t
+print_graph_duration(unsigned long long duration, struct trace_seq *s)
+{
+ int ret;
+
+ ret = trace_print_graph_duration(duration, s);
+ if (ret != TRACE_TYPE_HANDLED)
+ return ret;
ret = trace_seq_printf(s, "| ");
if (!ret)
return TRACE_TYPE_PARTIAL_LINE;
- return TRACE_TYPE_HANDLED;
+ return TRACE_TYPE_HANDLED;
}
/* Case of a leaf function on its call entry */
diff --git a/kernel/trace/trace_hw_branches.c b/kernel/trace/trace_hw_branches.c
index 7bfdf4c2347f..ca7d7c4d0c2a 100644
--- a/kernel/trace/trace_hw_branches.c
+++ b/kernel/trace/trace_hw_branches.c
@@ -1,10 +1,9 @@
/*
- * h/w branch tracer for x86 based on bts
+ * h/w branch tracer for x86 based on BTS
*
* Copyright (C) 2008-2009 Intel Corporation.
* Markus Metzger <markus.t.metzger@gmail.com>, 2008-2009
*/
-#include <linux/spinlock.h>
#include <linux/kallsyms.h>
#include <linux/debugfs.h>
#include <linux/ftrace.h>
@@ -15,110 +14,119 @@
#include <asm/ds.h>
-#include "trace.h"
#include "trace_output.h"
+#include "trace.h"
-#define SIZEOF_BTS (1 << 13)
+#define BTS_BUFFER_SIZE (1 << 13)
-/*
- * The tracer lock protects the below per-cpu tracer array.
- * It needs to be held to:
- * - start tracing on all cpus
- * - stop tracing on all cpus
- * - start tracing on a single hotplug cpu
- * - stop tracing on a single hotplug cpu
- * - read the trace from all cpus
- * - read the trace from a single cpu
- */
-static DEFINE_SPINLOCK(bts_tracer_lock);
static DEFINE_PER_CPU(struct bts_tracer *, tracer);
-static DEFINE_PER_CPU(unsigned char[SIZEOF_BTS], buffer);
+static DEFINE_PER_CPU(unsigned char[BTS_BUFFER_SIZE], buffer);
#define this_tracer per_cpu(tracer, smp_processor_id())
-#define this_buffer per_cpu(buffer, smp_processor_id())
-static int __read_mostly trace_hw_branches_enabled;
+static int trace_hw_branches_enabled __read_mostly;
+static int trace_hw_branches_suspended __read_mostly;
static struct trace_array *hw_branch_trace __read_mostly;
-/*
- * Start tracing on the current cpu.
- * The argument is ignored.
- *
- * pre: bts_tracer_lock must be locked.
- */
-static void bts_trace_start_cpu(void *arg)
+static void bts_trace_init_cpu(int cpu)
{
- if (this_tracer)
- ds_release_bts(this_tracer);
-
- this_tracer =
- ds_request_bts(/* task = */ NULL, this_buffer, SIZEOF_BTS,
- /* ovfl = */ NULL, /* th = */ (size_t)-1,
- BTS_KERNEL);
- if (IS_ERR(this_tracer)) {
- this_tracer = NULL;
- return;
- }
+ per_cpu(tracer, cpu) =
+ ds_request_bts_cpu(cpu, per_cpu(buffer, cpu), BTS_BUFFER_SIZE,
+ NULL, (size_t)-1, BTS_KERNEL);
+
+ if (IS_ERR(per_cpu(tracer, cpu)))
+ per_cpu(tracer, cpu) = NULL;
}
-static void bts_trace_start(struct trace_array *tr)
+static int bts_trace_init(struct trace_array *tr)
{
- spin_lock(&bts_tracer_lock);
+ int cpu;
+
+ hw_branch_trace = tr;
+ trace_hw_branches_enabled = 0;
- on_each_cpu(bts_trace_start_cpu, NULL, 1);
- trace_hw_branches_enabled = 1;
+ get_online_cpus();
+ for_each_online_cpu(cpu) {
+ bts_trace_init_cpu(cpu);
- spin_unlock(&bts_tracer_lock);
+ if (likely(per_cpu(tracer, cpu)))
+ trace_hw_branches_enabled = 1;
+ }
+ trace_hw_branches_suspended = 0;
+ put_online_cpus();
+
+ /* If we could not enable tracing on a single cpu, we fail. */
+ return trace_hw_branches_enabled ? 0 : -EOPNOTSUPP;
}
-/*
- * Stop tracing on the current cpu.
- * The argument is ignored.
- *
- * pre: bts_tracer_lock must be locked.
- */
-static void bts_trace_stop_cpu(void *arg)
+static void bts_trace_reset(struct trace_array *tr)
{
- if (this_tracer) {
- ds_release_bts(this_tracer);
- this_tracer = NULL;
+ int cpu;
+
+ get_online_cpus();
+ for_each_online_cpu(cpu) {
+ if (likely(per_cpu(tracer, cpu))) {
+ ds_release_bts(per_cpu(tracer, cpu));
+ per_cpu(tracer, cpu) = NULL;
+ }
}
+ trace_hw_branches_enabled = 0;
+ trace_hw_branches_suspended = 0;
+ put_online_cpus();
}
-static void bts_trace_stop(struct trace_array *tr)
+static void bts_trace_start(struct trace_array *tr)
{
- spin_lock(&bts_tracer_lock);
+ int cpu;
- trace_hw_branches_enabled = 0;
- on_each_cpu(bts_trace_stop_cpu, NULL, 1);
+ get_online_cpus();
+ for_each_online_cpu(cpu)
+ if (likely(per_cpu(tracer, cpu)))
+ ds_resume_bts(per_cpu(tracer, cpu));
+ trace_hw_branches_suspended = 0;
+ put_online_cpus();
+}
- spin_unlock(&bts_tracer_lock);
+static void bts_trace_stop(struct trace_array *tr)
+{
+ int cpu;
+
+ get_online_cpus();
+ for_each_online_cpu(cpu)
+ if (likely(per_cpu(tracer, cpu)))
+ ds_suspend_bts(per_cpu(tracer, cpu));
+ trace_hw_branches_suspended = 1;
+ put_online_cpus();
}
static int __cpuinit bts_hotcpu_handler(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
- unsigned int cpu = (unsigned long)hcpu;
-
- spin_lock(&bts_tracer_lock);
-
- if (!trace_hw_branches_enabled)
- goto out;
+ int cpu = (long)hcpu;
switch (action) {
case CPU_ONLINE:
case CPU_DOWN_FAILED:
- smp_call_function_single(cpu, bts_trace_start_cpu, NULL, 1);
+ /* The notification is sent with interrupts enabled. */
+ if (trace_hw_branches_enabled) {
+ bts_trace_init_cpu(cpu);
+
+ if (trace_hw_branches_suspended &&
+ likely(per_cpu(tracer, cpu)))
+ ds_suspend_bts(per_cpu(tracer, cpu));
+ }
break;
+
case CPU_DOWN_PREPARE:
- smp_call_function_single(cpu, bts_trace_stop_cpu, NULL, 1);
- break;
+ /* The notification is sent with interrupts enabled. */
+ if (likely(per_cpu(tracer, cpu))) {
+ ds_release_bts(per_cpu(tracer, cpu));
+ per_cpu(tracer, cpu) = NULL;
+ }
}
- out:
- spin_unlock(&bts_tracer_lock);
return NOTIFY_DONE;
}
@@ -126,20 +134,6 @@ static struct notifier_block bts_hotcpu_notifier __cpuinitdata = {
.notifier_call = bts_hotcpu_handler
};
-static int bts_trace_init(struct trace_array *tr)
-{
- hw_branch_trace = tr;
-
- bts_trace_start(tr);
-
- return 0;
-}
-
-static void bts_trace_reset(struct trace_array *tr)
-{
- bts_trace_stop(tr);
-}
-
static void bts_trace_print_header(struct seq_file *m)
{
seq_puts(m, "# CPU# TO <- FROM\n");
@@ -147,10 +141,10 @@ static void bts_trace_print_header(struct seq_file *m)
static enum print_line_t bts_trace_print_line(struct trace_iterator *iter)
{
+ unsigned long symflags = TRACE_ITER_SYM_OFFSET;
struct trace_entry *entry = iter->ent;
struct trace_seq *seq = &iter->seq;
struct hw_branch_entry *it;
- unsigned long symflags = TRACE_ITER_SYM_OFFSET;
trace_assign_type(it, entry);
@@ -168,6 +162,7 @@ static enum print_line_t bts_trace_print_line(struct trace_iterator *iter)
void trace_hw_branch(u64 from, u64 to)
{
+ struct ftrace_event_call *call = &event_hw_branch;
struct trace_array *tr = hw_branch_trace;
struct ring_buffer_event *event;
struct hw_branch_entry *entry;
@@ -194,7 +189,8 @@ void trace_hw_branch(u64 from, u64 to)
entry->ent.type = TRACE_HW_BRANCHES;
entry->from = from;
entry->to = to;
- trace_buffer_unlock_commit(tr, event, 0, 0);
+ if (!filter_check_discard(call, entry, tr->buffer, event))
+ trace_buffer_unlock_commit(tr, event, 0, 0);
out:
atomic_dec(&tr->data[cpu]->disabled);
@@ -224,11 +220,11 @@ static void trace_bts_at(const struct bts_trace *trace, void *at)
/*
* Collect the trace on the current cpu and write it into the ftrace buffer.
*
- * pre: bts_tracer_lock must be locked
+ * pre: tracing must be suspended on the current cpu
*/
static void trace_bts_cpu(void *arg)
{
- struct trace_array *tr = (struct trace_array *) arg;
+ struct trace_array *tr = (struct trace_array *)arg;
const struct bts_trace *trace;
unsigned char *at;
@@ -241,10 +237,9 @@ static void trace_bts_cpu(void *arg)
if (unlikely(!this_tracer))
return;
- ds_suspend_bts(this_tracer);
trace = ds_read_bts(this_tracer);
if (!trace)
- goto out;
+ return;
for (at = trace->ds.top; (void *)at < trace->ds.end;
at += trace->ds.size)
@@ -253,18 +248,27 @@ static void trace_bts_cpu(void *arg)
for (at = trace->ds.begin; (void *)at < trace->ds.top;
at += trace->ds.size)
trace_bts_at(trace, at);
-
-out:
- ds_resume_bts(this_tracer);
}
static void trace_bts_prepare(struct trace_iterator *iter)
{
- spin_lock(&bts_tracer_lock);
+ int cpu;
+ get_online_cpus();
+ for_each_online_cpu(cpu)
+ if (likely(per_cpu(tracer, cpu)))
+ ds_suspend_bts(per_cpu(tracer, cpu));
+ /*
+ * We need to collect the trace on the respective cpu since ftrace
+ * implicitly adds the record for the current cpu.
+ * Once that is more flexible, we could collect the data from any cpu.
+ */
on_each_cpu(trace_bts_cpu, iter->tr, 1);
- spin_unlock(&bts_tracer_lock);
+ for_each_online_cpu(cpu)
+ if (likely(per_cpu(tracer, cpu)))
+ ds_resume_bts(per_cpu(tracer, cpu));
+ put_online_cpus();
}
static void trace_bts_close(struct trace_iterator *iter)
@@ -274,11 +278,11 @@ static void trace_bts_close(struct trace_iterator *iter)
void trace_hw_branch_oops(void)
{
- spin_lock(&bts_tracer_lock);
-
- trace_bts_cpu(hw_branch_trace);
-
- spin_unlock(&bts_tracer_lock);
+ if (this_tracer) {
+ ds_suspend_bts_noirq(this_tracer);
+ trace_bts_cpu(hw_branch_trace);
+ ds_resume_bts_noirq(this_tracer);
+ }
}
struct tracer bts_tracer __read_mostly =
@@ -291,7 +295,10 @@ struct tracer bts_tracer __read_mostly =
.start = bts_trace_start,
.stop = bts_trace_stop,
.open = trace_bts_prepare,
- .close = trace_bts_close
+ .close = trace_bts_close,
+#ifdef CONFIG_FTRACE_SELFTEST
+ .selftest = trace_selftest_startup_hw_branches,
+#endif /* CONFIG_FTRACE_SELFTEST */
};
__init static int init_bts_trace(void)
diff --git a/kernel/trace/trace_mmiotrace.c b/kernel/trace/trace_mmiotrace.c
index 8e37fcddd8b4..d53b45ed0806 100644
--- a/kernel/trace/trace_mmiotrace.c
+++ b/kernel/trace/trace_mmiotrace.c
@@ -9,6 +9,8 @@
#include <linux/kernel.h>
#include <linux/mmiotrace.h>
#include <linux/pci.h>
+#include <linux/time.h>
+
#include <asm/atomic.h>
#include "trace.h"
@@ -174,7 +176,7 @@ static enum print_line_t mmio_print_rw(struct trace_iterator *iter)
struct mmiotrace_rw *rw;
struct trace_seq *s = &iter->seq;
unsigned long long t = ns2usecs(iter->ts);
- unsigned long usec_rem = do_div(t, 1000000ULL);
+ unsigned long usec_rem = do_div(t, USEC_PER_SEC);
unsigned secs = (unsigned long)t;
int ret = 1;
@@ -221,7 +223,7 @@ static enum print_line_t mmio_print_map(struct trace_iterator *iter)
struct mmiotrace_map *m;
struct trace_seq *s = &iter->seq;
unsigned long long t = ns2usecs(iter->ts);
- unsigned long usec_rem = do_div(t, 1000000ULL);
+ unsigned long usec_rem = do_div(t, USEC_PER_SEC);
unsigned secs = (unsigned long)t;
int ret;
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
index 64b54a59c55b..8bd9a2c1a46a 100644
--- a/kernel/trace/trace_output.c
+++ b/kernel/trace/trace_output.c
@@ -19,6 +19,16 @@ static struct hlist_head event_hash[EVENT_HASHSIZE] __read_mostly;
static int next_event_type = __TRACE_LAST_TYPE + 1;
+void trace_print_seq(struct seq_file *m, struct trace_seq *s)
+{
+ int len = s->len >= PAGE_SIZE ? PAGE_SIZE - 1 : s->len;
+
+ s->buffer[len] = 0;
+ seq_puts(m, s->buffer);
+
+ trace_seq_init(s);
+}
+
enum print_line_t trace_print_bprintk_msg_only(struct trace_iterator *iter)
{
struct trace_seq *s = &iter->seq;
@@ -84,6 +94,7 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
return len;
}
+EXPORT_SYMBOL_GPL(trace_seq_printf);
int trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary)
{
@@ -472,6 +483,36 @@ struct trace_event *ftrace_find_event(int type)
return NULL;
}
+static LIST_HEAD(ftrace_event_list);
+
+static int trace_search_list(struct list_head **list)
+{
+ struct trace_event *e;
+ int last = __TRACE_LAST_TYPE;
+
+ if (list_empty(&ftrace_event_list)) {
+ *list = &ftrace_event_list;
+ return last + 1;
+ }
+
+ /*
+ * We used up all possible max events,
+ * lets see if somebody freed one.
+ */
+ list_for_each_entry(e, &ftrace_event_list, list) {
+ if (e->type != last + 1)
+ break;
+ last++;
+ }
+
+ /* Did we used up all 65 thousand events??? */
+ if ((last + 1) > FTRACE_MAX_EVENT)
+ return 0;
+
+ *list = &e->list;
+ return last + 1;
+}
+
/**
* register_ftrace_event - register output for an event type
* @event: the event type to register
@@ -494,20 +535,40 @@ int register_ftrace_event(struct trace_event *event)
mutex_lock(&trace_event_mutex);
- if (!event) {
- ret = next_event_type++;
+ if (WARN_ON(!event))
goto out;
- }
- if (!event->type)
- event->type = next_event_type++;
- else if (event->type > __TRACE_LAST_TYPE) {
+ INIT_LIST_HEAD(&event->list);
+
+ if (!event->type) {
+ struct list_head *list = NULL;
+
+ if (next_event_type > FTRACE_MAX_EVENT) {
+
+ event->type = trace_search_list(&list);
+ if (!event->type)
+ goto out;
+
+ } else {
+
+ event->type = next_event_type++;
+ list = &ftrace_event_list;
+ }
+
+ if (WARN_ON(ftrace_find_event(event->type)))
+ goto out;
+
+ list_add_tail(&event->list, list);
+
+ } else if (event->type > __TRACE_LAST_TYPE) {
printk(KERN_WARNING "Need to add type to trace.h\n");
WARN_ON(1);
- }
-
- if (ftrace_find_event(event->type))
goto out;
+ } else {
+ /* Is this event already used */
+ if (ftrace_find_event(event->type))
+ goto out;
+ }
if (event->trace == NULL)
event->trace = trace_nop_print;
@@ -528,6 +589,7 @@ int register_ftrace_event(struct trace_event *event)
return ret;
}
+EXPORT_SYMBOL_GPL(register_ftrace_event);
/**
* unregister_ftrace_event - remove a no longer used event
@@ -537,10 +599,12 @@ int unregister_ftrace_event(struct trace_event *event)
{
mutex_lock(&trace_event_mutex);
hlist_del(&event->node);
+ list_del(&event->list);
mutex_unlock(&trace_event_mutex);
return 0;
}
+EXPORT_SYMBOL_GPL(unregister_ftrace_event);
/*
* Standard events
diff --git a/kernel/trace/trace_output.h b/kernel/trace/trace_output.h
index e0bde39c2dd9..6e220a8e5706 100644
--- a/kernel/trace/trace_output.h
+++ b/kernel/trace/trace_output.h
@@ -1,41 +1,17 @@
#ifndef __TRACE_EVENTS_H
#define __TRACE_EVENTS_H
+#include <linux/trace_seq.h>
#include "trace.h"
-typedef enum print_line_t (*trace_print_func)(struct trace_iterator *iter,
- int flags);
-
-struct trace_event {
- struct hlist_node node;
- int type;
- trace_print_func trace;
- trace_print_func raw;
- trace_print_func hex;
- trace_print_func binary;
-};
-
extern enum print_line_t
trace_print_bprintk_msg_only(struct trace_iterator *iter);
extern enum print_line_t
trace_print_printk_msg_only(struct trace_iterator *iter);
-extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
- __attribute__ ((format (printf, 2, 3)));
-extern int
-trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary);
extern int
seq_print_ip_sym(struct trace_seq *s, unsigned long ip,
unsigned long sym_flags);
-extern ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf,
- size_t cnt);
-extern int trace_seq_puts(struct trace_seq *s, const char *str);
-extern int trace_seq_putc(struct trace_seq *s, unsigned char c);
-extern int trace_seq_putmem(struct trace_seq *s, const void *mem, size_t len);
-extern int trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
- size_t len);
-extern void *trace_seq_reserve(struct trace_seq *s, size_t len);
-extern int trace_seq_path(struct trace_seq *s, struct path *path);
extern int seq_print_userip_objs(const struct userstack_entry *entry,
struct trace_seq *s, unsigned long sym_flags);
extern int seq_print_user_ip(struct trace_seq *s, struct mm_struct *mm,
@@ -45,8 +21,6 @@ extern int trace_print_context(struct trace_iterator *iter);
extern int trace_print_lat_context(struct trace_iterator *iter);
extern struct trace_event *ftrace_find_event(int type);
-extern int register_ftrace_event(struct trace_event *event);
-extern int unregister_ftrace_event(struct trace_event *event);
extern enum print_line_t trace_nop_print(struct trace_iterator *iter,
int flags);
diff --git a/kernel/trace/trace_power.c b/kernel/trace/trace_power.c
index bae791ebcc51..8a30d9874cd4 100644
--- a/kernel/trace/trace_power.c
+++ b/kernel/trace/trace_power.c
@@ -36,6 +36,7 @@ static void probe_power_start(struct power_trace *it, unsigned int type,
static void probe_power_end(struct power_trace *it)
{
+ struct ftrace_event_call *call = &event_power;
struct ring_buffer_event *event;
struct trace_power *entry;
struct trace_array_cpu *data;
@@ -54,7 +55,8 @@ static void probe_power_end(struct power_trace *it)
goto out;
entry = ring_buffer_event_data(event);
entry->state_data = *it;
- trace_buffer_unlock_commit(tr, event, 0, 0);
+ if (!filter_check_discard(call, entry, tr->buffer, event))
+ trace_buffer_unlock_commit(tr, event, 0, 0);
out:
preempt_enable();
}
@@ -62,6 +64,7 @@ static void probe_power_end(struct power_trace *it)
static void probe_power_mark(struct power_trace *it, unsigned int type,
unsigned int level)
{
+ struct ftrace_event_call *call = &event_power;
struct ring_buffer_event *event;
struct trace_power *entry;
struct trace_array_cpu *data;
@@ -84,7 +87,8 @@ static void probe_power_mark(struct power_trace *it, unsigned int type,
goto out;
entry = ring_buffer_event_data(event);
entry->state_data = *it;
- trace_buffer_unlock_commit(tr, event, 0, 0);
+ if (!filter_check_discard(call, entry, tr->buffer, event))
+ trace_buffer_unlock_commit(tr, event, 0, 0);
out:
preempt_enable();
}
@@ -186,6 +190,12 @@ static enum print_line_t power_print_line(struct trace_iterator *iter)
return TRACE_TYPE_UNHANDLED;
}
+static void power_print_header(struct seq_file *s)
+{
+ seq_puts(s, "# TIMESTAMP STATE EVENT\n");
+ seq_puts(s, "# | | |\n");
+}
+
static struct tracer power_tracer __read_mostly =
{
.name = "power",
@@ -194,6 +204,7 @@ static struct tracer power_tracer __read_mostly =
.stop = stop_power_trace,
.reset = power_trace_reset,
.print_line = power_print_line,
+ .print_header = power_print_header,
};
static int init_power_trace(void)
diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c
index eb81556107fe..9bece9687b62 100644
--- a/kernel/trace/trace_printk.c
+++ b/kernel/trace/trace_printk.c
@@ -245,17 +245,13 @@ static const struct file_operations ftrace_formats_fops = {
static __init int init_trace_printk_function_export(void)
{
struct dentry *d_tracer;
- struct dentry *entry;
d_tracer = tracing_init_dentry();
if (!d_tracer)
return 0;
- entry = debugfs_create_file("printk_formats", 0444, d_tracer,
+ trace_create_file("printk_formats", 0444, d_tracer,
NULL, &ftrace_formats_fops);
- if (!entry)
- pr_warning("Could not create debugfs "
- "'printk_formats' entry\n");
return 0;
}
diff --git a/kernel/trace/trace_sched_switch.c b/kernel/trace/trace_sched_switch.c
index 9117cea6f1ae..a98106dd979c 100644
--- a/kernel/trace/trace_sched_switch.c
+++ b/kernel/trace/trace_sched_switch.c
@@ -10,7 +10,7 @@
#include <linux/kallsyms.h>
#include <linux/uaccess.h>
#include <linux/ftrace.h>
-#include <trace/sched.h>
+#include <trace/events/sched.h>
#include "trace.h"
@@ -29,13 +29,13 @@ probe_sched_switch(struct rq *__rq, struct task_struct *prev,
int cpu;
int pc;
- if (!sched_ref || sched_stopped)
+ if (unlikely(!sched_ref))
return;
tracing_record_cmdline(prev);
tracing_record_cmdline(next);
- if (!tracer_enabled)
+ if (!tracer_enabled || sched_stopped)
return;
pc = preempt_count();
@@ -56,15 +56,15 @@ probe_sched_wakeup(struct rq *__rq, struct task_struct *wakee, int success)
unsigned long flags;
int cpu, pc;
- if (!likely(tracer_enabled))
+ if (unlikely(!sched_ref))
return;
- pc = preempt_count();
tracing_record_cmdline(current);
- if (sched_stopped)
+ if (!tracer_enabled || sched_stopped)
return;
+ pc = preempt_count();
local_irq_save(flags);
cpu = raw_smp_processor_id();
data = ctx_trace->data[cpu];
diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c
index 5bc00e8f153e..eacb27225173 100644
--- a/kernel/trace/trace_sched_wakeup.c
+++ b/kernel/trace/trace_sched_wakeup.c
@@ -15,7 +15,7 @@
#include <linux/kallsyms.h>
#include <linux/uaccess.h>
#include <linux/ftrace.h>
-#include <trace/sched.h>
+#include <trace/events/sched.h>
#include "trace.h"
@@ -138,9 +138,6 @@ probe_wakeup_sched_switch(struct rq *rq, struct task_struct *prev,
pc = preempt_count();
- /* The task we are waiting for is waking up */
- data = wakeup_trace->data[wakeup_cpu];
-
/* disable local data, not wakeup_cpu data */
cpu = raw_smp_processor_id();
disabled = atomic_inc_return(&wakeup_trace->data[cpu]->disabled);
@@ -154,6 +151,9 @@ probe_wakeup_sched_switch(struct rq *rq, struct task_struct *prev,
if (unlikely(!tracer_enabled || next != wakeup_task))
goto out_unlock;
+ /* The task we are waiting for is waking up */
+ data = wakeup_trace->data[wakeup_cpu];
+
trace_function(wakeup_trace, CALLER_ADDR0, CALLER_ADDR1, flags, pc);
tracing_sched_switch_trace(wakeup_trace, prev, next, flags, pc);
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c
index 08f4eb2763d1..00dd6485bdd7 100644
--- a/kernel/trace/trace_selftest.c
+++ b/kernel/trace/trace_selftest.c
@@ -16,6 +16,7 @@ static inline int trace_valid_entry(struct trace_entry *entry)
case TRACE_BRANCH:
case TRACE_GRAPH_ENT:
case TRACE_GRAPH_RET:
+ case TRACE_HW_BRANCHES:
return 1;
}
return 0;
@@ -188,6 +189,7 @@ int trace_selftest_startup_dynamic_tracing(struct tracer *trace,
#else
# define trace_selftest_startup_dynamic_tracing(trace, tr, func) ({ 0; })
#endif /* CONFIG_DYNAMIC_FTRACE */
+
/*
* Simple verification test of ftrace function tracer.
* Enable ftrace, sleep 1/10 second, and then read the trace
@@ -749,3 +751,59 @@ trace_selftest_startup_branch(struct tracer *trace, struct trace_array *tr)
return ret;
}
#endif /* CONFIG_BRANCH_TRACER */
+
+#ifdef CONFIG_HW_BRANCH_TRACER
+int
+trace_selftest_startup_hw_branches(struct tracer *trace,
+ struct trace_array *tr)
+{
+ struct trace_iterator *iter;
+ struct tracer tracer;
+ unsigned long count;
+ int ret;
+
+ if (!trace->open) {
+ printk(KERN_CONT "missing open function...");
+ return -1;
+ }
+
+ ret = tracer_init(trace, tr);
+ if (ret) {
+ warn_failed_init_tracer(trace, ret);
+ return ret;
+ }
+
+ /*
+ * The hw-branch tracer needs to collect the trace from the various
+ * cpu trace buffers - before tracing is stopped.
+ */
+ iter = kzalloc(sizeof(*iter), GFP_KERNEL);
+ if (!iter)
+ return -ENOMEM;
+
+ memcpy(&tracer, trace, sizeof(tracer));
+
+ iter->trace = &tracer;
+ iter->tr = tr;
+ iter->pos = -1;
+ mutex_init(&iter->mutex);
+
+ trace->open(iter);
+
+ mutex_destroy(&iter->mutex);
+ kfree(iter);
+
+ tracing_stop();
+
+ ret = trace_test_buffer(tr, &count);
+ trace->reset(tr);
+ tracing_start();
+
+ if (!ret && !count) {
+ printk(KERN_CONT "no entries found..");
+ ret = -1;
+ }
+
+ return ret;
+}
+#endif /* CONFIG_HW_BRANCH_TRACER */
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c
index c750f65f9661..1796f00524e1 100644
--- a/kernel/trace/trace_stack.c
+++ b/kernel/trace/trace_stack.c
@@ -352,19 +352,14 @@ __setup("stacktrace", enable_stacktrace);
static __init int stack_trace_init(void)
{
struct dentry *d_tracer;
- struct dentry *entry;
d_tracer = tracing_init_dentry();
- entry = debugfs_create_file("stack_max_size", 0644, d_tracer,
- &max_stack_size, &stack_max_size_fops);
- if (!entry)
- pr_warning("Could not create debugfs 'stack_max_size' entry\n");
+ trace_create_file("stack_max_size", 0644, d_tracer,
+ &max_stack_size, &stack_max_size_fops);
- entry = debugfs_create_file("stack_trace", 0444, d_tracer,
- NULL, &stack_trace_fops);
- if (!entry)
- pr_warning("Could not create debugfs 'stack_trace' entry\n");
+ trace_create_file("stack_trace", 0444, d_tracer,
+ NULL, &stack_trace_fops);
if (stack_tracer_enabled)
register_ftrace_function(&trace_ops);
diff --git a/kernel/trace/trace_stat.c b/kernel/trace/trace_stat.c
index acdebd771a93..fdde3a4a94cd 100644
--- a/kernel/trace/trace_stat.c
+++ b/kernel/trace/trace_stat.c
@@ -85,7 +85,7 @@ static int stat_seq_init(struct tracer_stat_session *session)
if (!ts->stat_cmp)
ts->stat_cmp = dummy_cmp;
- stat = ts->stat_start();
+ stat = ts->stat_start(ts);
if (!stat)
goto exit;
diff --git a/kernel/trace/trace_stat.h b/kernel/trace/trace_stat.h
index 202274cf7f3d..f3546a2cd826 100644
--- a/kernel/trace/trace_stat.h
+++ b/kernel/trace/trace_stat.h
@@ -12,7 +12,7 @@ struct tracer_stat {
/* The name of your stat file */
const char *name;
/* Iteration over statistic entries */
- void *(*stat_start)(void);
+ void *(*stat_start)(struct tracer_stat *trace);
void *(*stat_next)(void *prev, int idx);
/* Compare two entries for stats sorting */
int (*stat_cmp)(void *p1, void *p2);
diff --git a/kernel/trace/trace_sysprof.c b/kernel/trace/trace_sysprof.c
index 91fd19c2149f..e04b76cc238a 100644
--- a/kernel/trace/trace_sysprof.c
+++ b/kernel/trace/trace_sysprof.c
@@ -321,11 +321,7 @@ static const struct file_operations sysprof_sample_fops = {
void init_tracer_sysprof_debugfs(struct dentry *d_tracer)
{
- struct dentry *entry;
- entry = debugfs_create_file("sysprof_sample_period", 0644,
+ trace_create_file("sysprof_sample_period", 0644,
d_tracer, NULL, &sysprof_sample_fops);
- if (entry)
- return;
- pr_warning("Could not create debugfs 'sysprof_sample_period' entry\n");
}
diff --git a/kernel/trace/trace_workqueue.c b/kernel/trace/trace_workqueue.c
index 797201e4a137..984b9175c13d 100644
--- a/kernel/trace/trace_workqueue.c
+++ b/kernel/trace/trace_workqueue.c
@@ -152,7 +152,7 @@ static struct cpu_workqueue_stats *workqueue_stat_start_cpu(int cpu)
return ret;
}
-static void *workqueue_stat_start(void)
+static void *workqueue_stat_start(struct tracer_stat *trace)
{
int cpu;
void *ret = NULL;
diff --git a/kernel/wait.c b/kernel/wait.c
index 42a2dbc181c8..ea7c3b4275cf 100644
--- a/kernel/wait.c
+++ b/kernel/wait.c
@@ -154,7 +154,7 @@ void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait,
if (!list_empty(&wait->task_list))
list_del_init(&wait->task_list);
else if (waitqueue_active(q))
- __wake_up_common(q, mode, 1, 0, key);
+ __wake_up_locked_key(q, mode, key);
spin_unlock_irqrestore(&q->lock, flags);
}
EXPORT_SYMBOL(abort_exclusive_wait);
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index c6e854f215fa..444002b18f5d 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -336,6 +336,58 @@ config SLUB_STATS
out which slabs are relevant to a particular load.
Try running: slabinfo -DA
+config SLQB_DEBUG
+ default y
+ bool "Enable SLQB debugging support"
+ depends on SLQB
+
+config SLQB_DEBUG_ON
+ default n
+ bool "SLQB debugging on by default"
+ depends on SLQB_DEBUG
+
+config SLQB_SYSFS
+ bool "Create SYSFS entries for slab caches"
+ default n
+ depends on SLQB
+
+config SLQB_STATS
+ bool "Enable SLQB performance statistics"
+ default n
+ depends on SLQB_SYSFS
+
+config DEBUG_KMEMLEAK
+ bool "Kernel memory leak detector"
+ depends on DEBUG_KERNEL && EXPERIMENTAL && (X86 || ARM) && \
+ !MEMORY_HOTPLUG
+ select DEBUG_SLAB if SLAB
+ select SLUB_DEBUG if SLUB
+ select DEBUG_FS if SYSFS
+ select STACKTRACE if STACKTRACE_SUPPORT
+ select KALLSYMS
+ help
+ Say Y here if you want to enable the memory leak
+ detector. The memory allocation/freeing is traced in a way
+ similar to the Boehm's conservative garbage collector, the
+ difference being that the orphan objects are not freed but
+ only shown in /sys/kernel/debug/kmemleak. Enabling this
+ feature will introduce an overhead to memory
+ allocations. See Documentation/kmemleak.txt for more
+ details.
+
+ In order to access the kmemleak file, debugfs needs to be
+ mounted (usually at /sys/kernel/debug).
+
+config DEBUG_KMEMLEAK_TEST
+ tristate "Simple test for the kernel memory leak detector"
+ depends on DEBUG_KMEMLEAK
+ help
+ Say Y or M here to build a test for the kernel memory leak
+ detector. This option enables a module that explicitly leaks
+ memory.
+
+ If unsure, say N.
+
config DEBUG_PREEMPT
bool "Debug preemptible kernel"
depends on DEBUG_KERNEL && PREEMPT && (TRACE_IRQFLAGS_SUPPORT || PPC64)
@@ -440,7 +492,7 @@ config LOCKDEP
bool
depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
select STACKTRACE
- select FRAME_POINTER if !X86 && !MIPS && !PPC && !ARM_UNWIND
+ select FRAME_POINTER if !X86 && !MIPS && !PPC && !ARM_UNWIND && !S390
select KALLSYMS
select KALLSYMS_ALL
@@ -620,7 +672,7 @@ config ARCH_WANT_FRAME_POINTERS
config FRAME_POINTER
bool "Compile the kernel with frame pointers"
depends on DEBUG_KERNEL && \
- (CRIS || M68K || M68KNOMMU || FRV || UML || S390 || \
+ (CRIS || M68K || M68KNOMMU || FRV || UML || \
AVR32 || SUPERH || BLACKFIN || MN10300) || \
ARCH_WANT_FRAME_POINTERS
default y if (DEBUG_INFO && UML) || ARCH_WANT_FRAME_POINTERS
@@ -809,13 +861,13 @@ config FAULT_INJECTION_STACKTRACE_FILTER
depends on FAULT_INJECTION_DEBUG_FS && STACKTRACE_SUPPORT
depends on !X86_64
select STACKTRACE
- select FRAME_POINTER if !PPC
+ select FRAME_POINTER if !PPC && !S390
help
Provide stacktrace filter for fault-injection capabilities
config LATENCYTOP
bool "Latency measuring infrastructure"
- select FRAME_POINTER if !MIPS && !PPC
+ select FRAME_POINTER if !MIPS && !PPC && !S390
select KALLSYMS
select KALLSYMS_ALL
select STACKTRACE
@@ -891,7 +943,6 @@ config DYNAMIC_DEBUG
default n
depends on PRINTK
depends on DEBUG_FS
- select PRINTK_DEBUG
help
Compiles debug level messages into the kernel, which would not
diff --git a/lib/Makefile b/lib/Makefile
index d6edd6753f40..33a40e40e3ee 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -38,7 +38,7 @@ lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
lib-$(CONFIG_GENERIC_FIND_FIRST_BIT) += find_next_bit.o
lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
-lib-$(CONFIG_GENERIC_FIND_LAST_BIT) += find_last_bit.o
+obj-$(CONFIG_GENERIC_FIND_LAST_BIT) += find_last_bit.o
obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index d3da7edc034f..cdd205d6bf7c 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -85,6 +85,7 @@ static u32 show_num_errors = 1;
static u32 num_free_entries;
static u32 min_free_entries;
+static u32 nr_total_entries;
/* number of preallocated entries requested by kernel cmdline */
static u32 req_entries;
@@ -257,6 +258,21 @@ static void add_dma_entry(struct dma_debug_entry *entry)
put_hash_bucket(bucket, &flags);
}
+static struct dma_debug_entry *__dma_entry_alloc(void)
+{
+ struct dma_debug_entry *entry;
+
+ entry = list_entry(free_entries.next, struct dma_debug_entry, list);
+ list_del(&entry->list);
+ memset(entry, 0, sizeof(*entry));
+
+ num_free_entries -= 1;
+ if (num_free_entries < min_free_entries)
+ min_free_entries = num_free_entries;
+
+ return entry;
+}
+
/* struct dma_entry allocator
*
* The next two functions implement the allocator for
@@ -276,9 +292,7 @@ static struct dma_debug_entry *dma_entry_alloc(void)
goto out;
}
- entry = list_entry(free_entries.next, struct dma_debug_entry, list);
- list_del(&entry->list);
- memset(entry, 0, sizeof(*entry));
+ entry = __dma_entry_alloc();
#ifdef CONFIG_STACKTRACE
entry->stacktrace.max_entries = DMA_DEBUG_STACKTRACE_ENTRIES;
@@ -286,9 +300,6 @@ static struct dma_debug_entry *dma_entry_alloc(void)
entry->stacktrace.skip = 2;
save_stack_trace(&entry->stacktrace);
#endif
- num_free_entries -= 1;
- if (num_free_entries < min_free_entries)
- min_free_entries = num_free_entries;
out:
spin_unlock_irqrestore(&free_entries_lock, flags);
@@ -310,6 +321,53 @@ static void dma_entry_free(struct dma_debug_entry *entry)
spin_unlock_irqrestore(&free_entries_lock, flags);
}
+int dma_debug_resize_entries(u32 num_entries)
+{
+ int i, delta, ret = 0;
+ unsigned long flags;
+ struct dma_debug_entry *entry;
+ LIST_HEAD(tmp);
+
+ spin_lock_irqsave(&free_entries_lock, flags);
+
+ if (nr_total_entries < num_entries) {
+ delta = num_entries - nr_total_entries;
+
+ spin_unlock_irqrestore(&free_entries_lock, flags);
+
+ for (i = 0; i < delta; i++) {
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ break;
+
+ list_add_tail(&entry->list, &tmp);
+ }
+
+ spin_lock_irqsave(&free_entries_lock, flags);
+
+ list_splice(&tmp, &free_entries);
+ nr_total_entries += i;
+ num_free_entries += i;
+ } else {
+ delta = nr_total_entries - num_entries;
+
+ for (i = 0; i < delta && !list_empty(&free_entries); i++) {
+ entry = __dma_entry_alloc();
+ kfree(entry);
+ }
+
+ nr_total_entries -= i;
+ }
+
+ if (nr_total_entries != num_entries)
+ ret = 1;
+
+ spin_unlock_irqrestore(&free_entries_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(dma_debug_resize_entries);
+
/*
* DMA-API debugging init code
*
@@ -400,60 +458,9 @@ out_err:
return -ENOMEM;
}
-static int device_dma_allocations(struct device *dev)
-{
- struct dma_debug_entry *entry;
- unsigned long flags;
- int count = 0, i;
-
- for (i = 0; i < HASH_SIZE; ++i) {
- spin_lock_irqsave(&dma_entry_hash[i].lock, flags);
- list_for_each_entry(entry, &dma_entry_hash[i].list, list) {
- if (entry->dev == dev)
- count += 1;
- }
- spin_unlock_irqrestore(&dma_entry_hash[i].lock, flags);
- }
-
- return count;
-}
-
-static int dma_debug_device_change(struct notifier_block *nb,
- unsigned long action, void *data)
-{
- struct device *dev = data;
- int count;
-
-
- switch (action) {
- case BUS_NOTIFY_UNBIND_DRIVER:
- count = device_dma_allocations(dev);
- if (count == 0)
- break;
- err_printk(dev, NULL, "DMA-API: device driver has pending "
- "DMA allocations while released from device "
- "[count=%d]\n", count);
- break;
- default:
- break;
- }
-
- return 0;
-}
-
void dma_debug_add_bus(struct bus_type *bus)
{
- struct notifier_block *nb;
-
- nb = kzalloc(sizeof(struct notifier_block), GFP_KERNEL);
- if (nb == NULL) {
- printk(KERN_ERR "dma_debug_add_bus: out of memory\n");
- return;
- }
-
- nb->notifier_call = dma_debug_device_change;
-
- bus_register_notifier(bus, nb);
+ /* FIXME: register notifier */
}
/*
@@ -490,6 +497,8 @@ void dma_debug_init(u32 num_entries)
return;
}
+ nr_total_entries = num_free_entries;
+
printk(KERN_INFO "DMA-API: debugging enabled by kernel config\n");
}
diff --git a/lib/kobject.c b/lib/kobject.c
index a6dec32f2ddd..bacf6fe4f7a0 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -218,6 +218,9 @@ int kobject_set_name_vargs(struct kobject *kobj, const char *fmt,
const char *old_name = kobj->name;
char *s;
+ if (kobj->name && !fmt)
+ return 0;
+
kobj->name = kvasprintf(GFP_KERNEL, fmt, vargs);
if (!kobj->name)
return -ENOMEM;
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 97a777ad4f59..920a3ca6e259 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -258,7 +258,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
goto exit;
retval = call_usermodehelper(argv[0], argv,
- env->envp, UMH_NO_WAIT);
+ env->envp, UMH_WAIT_EXEC);
}
exit:
@@ -328,7 +328,7 @@ static int __init kobject_uevent_init(void)
"kobject_uevent: unable to create netlink socket!\n");
return -ENODEV;
}
-
+ netlink_set_nonroot(NETLINK_KOBJECT_UEVENT, NL_NONROOT_RECV);
return 0;
}
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index b7b449dafbe5..a295e404e908 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -347,9 +347,12 @@ bool sg_miter_next(struct sg_mapping_iter *miter)
sg_miter_stop(miter);
/* get to the next sg if necessary. __offset is adjusted by stop */
- if (miter->__offset == miter->__sg->length && --miter->__nents) {
- miter->__sg = sg_next(miter->__sg);
- miter->__offset = 0;
+ while (miter->__offset == miter->__sg->length) {
+ if (--miter->__nents) {
+ miter->__sg = sg_next(miter->__sg);
+ miter->__offset = 0;
+ } else
+ return false;
}
/* map the next page */
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 2b0b5a7d2ced..bffe6d7ef9d9 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -60,8 +60,8 @@ enum dma_sync_target {
int swiotlb_force;
/*
- * Used to do a quick range check in swiotlb_unmap_single and
- * swiotlb_sync_single_*, to see if the memory was in fact allocated by this
+ * Used to do a quick range check in unmap_single and
+ * sync_single_*, to see if the memory was in fact allocated by this
* API.
*/
static char *io_tlb_start, *io_tlb_end;
@@ -129,7 +129,7 @@ dma_addr_t __weak swiotlb_phys_to_bus(struct device *hwdev, phys_addr_t paddr)
return paddr;
}
-phys_addr_t __weak swiotlb_bus_to_phys(dma_addr_t baddr)
+phys_addr_t __weak swiotlb_bus_to_phys(struct device *hwdev, dma_addr_t baddr)
{
return baddr;
}
@@ -140,9 +140,15 @@ static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
return swiotlb_phys_to_bus(hwdev, virt_to_phys(address));
}
-static void *swiotlb_bus_to_virt(dma_addr_t address)
+void * __weak swiotlb_bus_to_virt(struct device *hwdev, dma_addr_t address)
{
- return phys_to_virt(swiotlb_bus_to_phys(address));
+ return phys_to_virt(swiotlb_bus_to_phys(hwdev, address));
+}
+
+int __weak swiotlb_arch_address_needs_mapping(struct device *hwdev,
+ dma_addr_t addr, size_t size)
+{
+ return !is_buffer_dma_capable(dma_get_mask(hwdev), addr, size);
}
int __weak swiotlb_arch_range_needs_mapping(phys_addr_t paddr, size_t size)
@@ -309,10 +315,10 @@ cleanup1:
return -ENOMEM;
}
-static int
+static inline int
address_needs_mapping(struct device *hwdev, dma_addr_t addr, size_t size)
{
- return !is_buffer_dma_capable(dma_get_mask(hwdev), addr, size);
+ return swiotlb_arch_address_needs_mapping(hwdev, addr, size);
}
static inline int range_needs_mapping(phys_addr_t paddr, size_t size)
@@ -341,7 +347,7 @@ static void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
unsigned long flags;
while (size) {
- sz = min(PAGE_SIZE - offset, size);
+ sz = min_t(size_t, PAGE_SIZE - offset, size);
local_irq_save(flags);
buffer = kmap_atomic(pfn_to_page(pfn),
@@ -476,7 +482,7 @@ found:
* dma_addr is the kernel virtual address of the bounce buffer to unmap.
*/
static void
-unmap_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
+do_unmap_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
{
unsigned long flags;
int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
@@ -560,7 +566,6 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
size)) {
/*
* The allocated memory isn't reachable by the device.
- * Fall back on swiotlb_map_single().
*/
free_pages((unsigned long) ret, order);
ret = NULL;
@@ -568,9 +573,8 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
if (!ret) {
/*
* We are either out of memory or the device can't DMA
- * to GFP_DMA memory; fall back on
- * swiotlb_map_single(), which will grab memory from
- * the lowest available address range.
+ * to GFP_DMA memory; fall back on map_single(), which
+ * will grab memory from the lowest available address range.
*/
ret = map_single(hwdev, 0, size, DMA_FROM_DEVICE);
if (!ret)
@@ -587,7 +591,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
(unsigned long long)dev_addr);
/* DMA_TO_DEVICE to avoid memcpy in unmap_single */
- unmap_single(hwdev, ret, size, DMA_TO_DEVICE);
+ do_unmap_single(hwdev, ret, size, DMA_TO_DEVICE);
return NULL;
}
*dma_handle = dev_addr;
@@ -604,7 +608,7 @@ swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
free_pages((unsigned long) vaddr, get_order(size));
else
/* DMA_TO_DEVICE to avoid memcpy in unmap_single */
- unmap_single(hwdev, vaddr, size, DMA_TO_DEVICE);
+ do_unmap_single(hwdev, vaddr, size, DMA_TO_DEVICE);
}
EXPORT_SYMBOL(swiotlb_free_coherent);
@@ -634,7 +638,7 @@ swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
* physical address to use is returned.
*
* Once the device is given the dma address, the device owns this memory until
- * either swiotlb_unmap_single or swiotlb_dma_sync_single is performed.
+ * either swiotlb_unmap_page or swiotlb_dma_sync_single is performed.
*/
dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
@@ -642,18 +646,17 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
struct dma_attrs *attrs)
{
phys_addr_t phys = page_to_phys(page) + offset;
- void *ptr = page_address(page) + offset;
dma_addr_t dev_addr = swiotlb_phys_to_bus(dev, phys);
void *map;
BUG_ON(dir == DMA_NONE);
/*
- * If the pointer passed in happens to be in the device's DMA window,
+ * If the address happens to be in the device's DMA window,
* we can safely return the device addr and not worry about bounce
* buffering it.
*/
if (!address_needs_mapping(dev, dev_addr, size) &&
- !range_needs_mapping(virt_to_phys(ptr), size))
+ !range_needs_mapping(phys, size))
return dev_addr;
/*
@@ -679,23 +682,35 @@ EXPORT_SYMBOL_GPL(swiotlb_map_page);
/*
* Unmap a single streaming mode DMA translation. The dma_addr and size must
- * match what was provided for in a previous swiotlb_map_single call. All
+ * match what was provided for in a previous swiotlb_map_page call. All
* other usages are undefined.
*
* After this call, reads by the cpu to the buffer are guaranteed to see
* whatever the device wrote there.
*/
+static void unmap_single(struct device *hwdev, dma_addr_t dev_addr,
+ size_t size, int dir)
+{
+ char *dma_addr = swiotlb_bus_to_virt(hwdev, dev_addr);
+
+ BUG_ON(dir == DMA_NONE);
+
+ if (is_swiotlb_buffer(dma_addr)) {
+ do_unmap_single(hwdev, dma_addr, size, dir);
+ return;
+ }
+
+ if (dir != DMA_FROM_DEVICE)
+ return;
+
+ dma_mark_clean(dma_addr, size);
+}
+
void swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
size_t size, enum dma_data_direction dir,
struct dma_attrs *attrs)
{
- char *dma_addr = swiotlb_bus_to_virt(dev_addr);
-
- BUG_ON(dir == DMA_NONE);
- if (is_swiotlb_buffer(dma_addr))
- unmap_single(hwdev, dma_addr, size, dir);
- else if (dir == DMA_FROM_DEVICE)
- dma_mark_clean(dma_addr, size);
+ unmap_single(hwdev, dev_addr, size, dir);
}
EXPORT_SYMBOL_GPL(swiotlb_unmap_page);
@@ -703,7 +718,7 @@ EXPORT_SYMBOL_GPL(swiotlb_unmap_page);
* Make physical memory consistent for a single streaming mode DMA translation
* after a transfer.
*
- * If you perform a swiotlb_map_single() but wish to interrogate the buffer
+ * If you perform a swiotlb_map_page() but wish to interrogate the buffer
* using the cpu, yet do not wish to teardown the dma mapping, you must
* call this function before doing so. At the next point you give the dma
* address back to the card, you must first perform a
@@ -713,13 +728,19 @@ static void
swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
size_t size, int dir, int target)
{
- char *dma_addr = swiotlb_bus_to_virt(dev_addr);
+ char *dma_addr = swiotlb_bus_to_virt(hwdev, dev_addr);
BUG_ON(dir == DMA_NONE);
- if (is_swiotlb_buffer(dma_addr))
+
+ if (is_swiotlb_buffer(dma_addr)) {
sync_single(hwdev, dma_addr, size, dir, target);
- else if (dir == DMA_FROM_DEVICE)
- dma_mark_clean(dma_addr, size);
+ return;
+ }
+
+ if (dir != DMA_FROM_DEVICE)
+ return;
+
+ dma_mark_clean(dma_addr, size);
}
void
@@ -746,13 +767,7 @@ swiotlb_sync_single_range(struct device *hwdev, dma_addr_t dev_addr,
unsigned long offset, size_t size,
int dir, int target)
{
- char *dma_addr = swiotlb_bus_to_virt(dev_addr) + offset;
-
- BUG_ON(dir == DMA_NONE);
- if (is_swiotlb_buffer(dma_addr))
- sync_single(hwdev, dma_addr, size, dir, target);
- else if (dir == DMA_FROM_DEVICE)
- dma_mark_clean(dma_addr, size);
+ swiotlb_sync_single(hwdev, dev_addr + offset, size, dir, target);
}
void
@@ -777,7 +792,7 @@ EXPORT_SYMBOL_GPL(swiotlb_sync_single_range_for_device);
/*
* Map a set of buffers described by scatterlist in streaming mode for DMA.
- * This is the scatter-gather version of the above swiotlb_map_single
+ * This is the scatter-gather version of the above swiotlb_map_page
* interface. Here the scatter gather list elements are each tagged with the
* appropriate dma address and length. They are obtained via
* sg_dma_{address,length}(SG).
@@ -788,7 +803,7 @@ EXPORT_SYMBOL_GPL(swiotlb_sync_single_range_for_device);
* The routine returns the number of addr/length pairs actually
* used, at most nents.
*
- * Device ownership issues as mentioned above for swiotlb_map_single are the
+ * Device ownership issues as mentioned above for swiotlb_map_page are the
* same here.
*/
int
@@ -836,7 +851,7 @@ EXPORT_SYMBOL(swiotlb_map_sg);
/*
* Unmap a set of streaming mode DMA translations. Again, cpu read rules
- * concerning calls here are the same as for swiotlb_unmap_single() above.
+ * concerning calls here are the same as for swiotlb_unmap_page() above.
*/
void
swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
@@ -847,13 +862,9 @@ swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
BUG_ON(dir == DMA_NONE);
- for_each_sg(sgl, sg, nelems, i) {
- if (sg->dma_address != swiotlb_phys_to_bus(hwdev, sg_phys(sg)))
- unmap_single(hwdev, swiotlb_bus_to_virt(sg->dma_address),
- sg->dma_length, dir);
- else if (dir == DMA_FROM_DEVICE)
- dma_mark_clean(swiotlb_bus_to_virt(sg->dma_address), sg->dma_length);
- }
+ for_each_sg(sgl, sg, nelems, i)
+ unmap_single(hwdev, sg->dma_address, sg->dma_length, dir);
+
}
EXPORT_SYMBOL(swiotlb_unmap_sg_attrs);
@@ -879,15 +890,9 @@ swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sgl,
struct scatterlist *sg;
int i;
- BUG_ON(dir == DMA_NONE);
-
- for_each_sg(sgl, sg, nelems, i) {
- if (sg->dma_address != swiotlb_phys_to_bus(hwdev, sg_phys(sg)))
- sync_single(hwdev, swiotlb_bus_to_virt(sg->dma_address),
+ for_each_sg(sgl, sg, nelems, i)
+ swiotlb_sync_single(hwdev, sg->dma_address,
sg->dma_length, dir, target);
- else if (dir == DMA_FROM_DEVICE)
- dma_mark_clean(swiotlb_bus_to_virt(sg->dma_address), sg->dma_length);
- }
}
void
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 7536acea135b..756ccafa9cec 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -408,6 +408,8 @@ enum format_type {
FORMAT_TYPE_LONG_LONG,
FORMAT_TYPE_ULONG,
FORMAT_TYPE_LONG,
+ FORMAT_TYPE_UBYTE,
+ FORMAT_TYPE_BYTE,
FORMAT_TYPE_USHORT,
FORMAT_TYPE_SHORT,
FORMAT_TYPE_UINT,
@@ -573,12 +575,15 @@ static char *string(char *buf, char *end, char *s, struct printf_spec spec)
}
static char *symbol_string(char *buf, char *end, void *ptr,
- struct printf_spec spec)
+ struct printf_spec spec, char ext)
{
unsigned long value = (unsigned long) ptr;
#ifdef CONFIG_KALLSYMS
char sym[KSYM_SYMBOL_LEN];
- sprint_symbol(sym, value);
+ if (ext != 'f')
+ sprint_symbol(sym, value);
+ else
+ kallsyms_lookup(value, NULL, NULL, NULL, sym);
return string(buf, end, sym, spec);
#else
spec.field_width = 2*sizeof(void *);
@@ -690,7 +695,8 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr,
*
* Right now we handle:
*
- * - 'F' For symbolic function descriptor pointers
+ * - 'F' For symbolic function descriptor pointers with offset
+ * - 'f' For simple symbolic function names without offset
* - 'S' For symbolic direct pointers
* - 'R' For a struct resource pointer, it prints the range of
* addresses (not the name nor the flags)
@@ -713,10 +719,11 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
switch (*fmt) {
case 'F':
+ case 'f':
ptr = dereference_function_descriptor(ptr);
/* Fallthrough */
case 'S':
- return symbol_string(buf, end, ptr, spec);
+ return symbol_string(buf, end, ptr, spec, *fmt);
case 'R':
return resource_string(buf, end, ptr, spec);
case 'm':
@@ -853,11 +860,15 @@ qualifier:
spec->qualifier = -1;
if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
*fmt == 'Z' || *fmt == 'z' || *fmt == 't') {
- spec->qualifier = *fmt;
- ++fmt;
- if (spec->qualifier == 'l' && *fmt == 'l') {
- spec->qualifier = 'L';
- ++fmt;
+ spec->qualifier = *fmt++;
+ if (unlikely(spec->qualifier == *fmt)) {
+ if (spec->qualifier == 'l') {
+ spec->qualifier = 'L';
+ ++fmt;
+ } else if (spec->qualifier == 'h') {
+ spec->qualifier = 'H';
+ ++fmt;
+ }
}
}
@@ -919,6 +930,11 @@ qualifier:
spec->type = FORMAT_TYPE_SIZE_T;
} else if (spec->qualifier == 't') {
spec->type = FORMAT_TYPE_PTRDIFF;
+ } else if (spec->qualifier == 'H') {
+ if (spec->flags & SIGN)
+ spec->type = FORMAT_TYPE_BYTE;
+ else
+ spec->type = FORMAT_TYPE_UBYTE;
} else if (spec->qualifier == 'h') {
if (spec->flags & SIGN)
spec->type = FORMAT_TYPE_SHORT;
@@ -943,7 +959,8 @@ qualifier:
*
* This function follows C99 vsnprintf, but has some extensions:
* %pS output the name of a text symbol
- * %pF output the name of a function pointer
+ * %pF output the name of a function pointer with its offset
+ * %pf output the name of a function pointer without its offset
* %pR output the address range in a struct resource
*
* The return value is the number of characters which would
@@ -1087,6 +1104,12 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
case FORMAT_TYPE_PTRDIFF:
num = va_arg(args, ptrdiff_t);
break;
+ case FORMAT_TYPE_UBYTE:
+ num = (unsigned char) va_arg(args, int);
+ break;
+ case FORMAT_TYPE_BYTE:
+ num = (signed char) va_arg(args, int);
+ break;
case FORMAT_TYPE_USHORT:
num = (unsigned short) va_arg(args, int);
break;
@@ -1363,6 +1386,10 @@ do { \
case FORMAT_TYPE_PTRDIFF:
save_arg(ptrdiff_t);
break;
+ case FORMAT_TYPE_UBYTE:
+ case FORMAT_TYPE_BYTE:
+ save_arg(char);
+ break;
case FORMAT_TYPE_USHORT:
case FORMAT_TYPE_SHORT:
save_arg(short);
@@ -1391,7 +1418,8 @@ EXPORT_SYMBOL_GPL(vbin_printf);
*
* The format follows C99 vsnprintf, but has some extensions:
* %pS output the name of a text symbol
- * %pF output the name of a function pointer
+ * %pF output the name of a function pointer with its offset
+ * %pf output the name of a function pointer without its offset
* %pR output the address range in a struct resource
* %n is ignored
*
@@ -1538,6 +1566,12 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
case FORMAT_TYPE_PTRDIFF:
num = get_arg(ptrdiff_t);
break;
+ case FORMAT_TYPE_UBYTE:
+ num = get_arg(unsigned char);
+ break;
+ case FORMAT_TYPE_BYTE:
+ num = get_arg(signed char);
+ break;
case FORMAT_TYPE_USHORT:
num = get_arg(unsigned short);
break;
diff --git a/mm/Kconfig b/mm/Kconfig
index b53427ad30a3..c2b57d81e153 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -213,6 +213,8 @@ config UNEVICTABLE_LRU
will use one page flag and increase the code size a little,
say Y unless you know what you are doing.
+ See Documentation/vm/unevictable-lru.txt for more information.
+
config HAVE_MLOCK
bool
default y if MMU=y
@@ -223,3 +225,31 @@ config HAVE_MLOCKED_PAGE_BIT
config MMU_NOTIFIER
bool
+
+config NOMMU_INITIAL_TRIM_EXCESS
+ int "Turn on mmap() excess space trimming before booting"
+ depends on !MMU
+ default 1
+ help
+ The NOMMU mmap() frequently needs to allocate large contiguous chunks
+ of memory on which to store mappings, but it can only ask the system
+ allocator for chunks in 2^N*PAGE_SIZE amounts - which is frequently
+ more than it requires. To deal with this, mmap() is able to trim off
+ the excess and return it to the allocator.
+
+ If trimming is enabled, the excess is trimmed off and returned to the
+ system allocator, which can cause extra fragmentation, particularly
+ if there are a lot of transient processes.
+
+ If trimming is disabled, the excess is kept, but not used, which for
+ long-term mappings means that the space is wasted.
+
+ Trimming can be dynamically controlled through a sysctl option
+ (/proc/sys/vm/nr_trim_pages) which specifies the minimum number of
+ excess pages there must be before trimming should occur, or zero if
+ no trimming is to occur.
+
+ This option specifies the initial value of this option. The default
+ of 1 says that all excess pages should be trimmed.
+
+ See Documentation/nommu-mmap.txt for more information.
diff --git a/mm/Makefile b/mm/Makefile
index ec73c68b6015..fe8ebc2fdb7a 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o
obj-$(CONFIG_PAGE_POISONING) += debug-pagealloc.o
obj-$(CONFIG_SLAB) += slab.o
obj-$(CONFIG_SLUB) += slub.o
+obj-$(CONFIG_SLQB) += slqb.o
obj-$(CONFIG_FAILSLAB) += failslab.o
obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o
obj-$(CONFIG_FS_XIP) += filemap_xip.o
@@ -38,3 +39,5 @@ obj-$(CONFIG_SMP) += allocpercpu.o
endif
obj-$(CONFIG_QUICKLIST) += quicklist.o
obj-$(CONFIG_CGROUP_MEM_RES_CTLR) += memcontrol.o page_cgroup.o
+obj-$(CONFIG_DEBUG_KMEMLEAK) += kmemleak.o
+obj-$(CONFIG_DEBUG_KMEMLEAK_TEST) += kmemleak-test.o
diff --git a/mm/filemap.c b/mm/filemap.c
index 2e2d38ebda4b..379ff0bcbf6e 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -441,6 +441,7 @@ int filemap_write_and_wait_range(struct address_space *mapping,
}
return err;
}
+EXPORT_SYMBOL(filemap_write_and_wait_range);
/**
* add_to_page_cache_locked - add a locked page to the pagecache
@@ -567,8 +568,8 @@ EXPORT_SYMBOL(wait_on_page_bit);
/**
* add_page_wait_queue - Add an arbitrary waiter to a page's wait queue
- * @page - Page defining the wait queue of interest
- * @waiter - Waiter to add to the queue
+ * @page: Page defining the wait queue of interest
+ * @waiter: Waiter to add to the queue
*
* Add an arbitrary @waiter to the wait queue for the nominated @page.
*/
diff --git a/mm/kmemleak-test.c b/mm/kmemleak-test.c
new file mode 100644
index 000000000000..d5292fc6f523
--- /dev/null
+++ b/mm/kmemleak-test.c
@@ -0,0 +1,111 @@
+/*
+ * mm/kmemleak-test.c
+ *
+ * Copyright (C) 2008 ARM Limited
+ * Written by Catalin Marinas <catalin.marinas@arm.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.
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/list.h>
+#include <linux/percpu.h>
+#include <linux/fdtable.h>
+
+#include <linux/kmemleak.h>
+
+struct test_node {
+ long header[25];
+ struct list_head list;
+ long footer[25];
+};
+
+static LIST_HEAD(test_list);
+static DEFINE_PER_CPU(void *, test_pointer);
+
+/*
+ * Some very simple testing. This function needs to be extended for
+ * proper testing.
+ */
+static int __init kmemleak_test_init(void)
+{
+ struct test_node *elem;
+ int i;
+
+ printk(KERN_INFO "Kmemleak testing\n");
+
+ /* make some orphan objects */
+ pr_info("kmemleak: kmalloc(32) = %p\n", kmalloc(32, GFP_KERNEL));
+ pr_info("kmemleak: kmalloc(32) = %p\n", kmalloc(32, GFP_KERNEL));
+ pr_info("kmemleak: kmalloc(1024) = %p\n", kmalloc(1024, GFP_KERNEL));
+ pr_info("kmemleak: kmalloc(1024) = %p\n", kmalloc(1024, GFP_KERNEL));
+ pr_info("kmemleak: kmalloc(2048) = %p\n", kmalloc(2048, GFP_KERNEL));
+ pr_info("kmemleak: kmalloc(2048) = %p\n", kmalloc(2048, GFP_KERNEL));
+ pr_info("kmemleak: kmalloc(4096) = %p\n", kmalloc(4096, GFP_KERNEL));
+ pr_info("kmemleak: kmalloc(4096) = %p\n", kmalloc(4096, GFP_KERNEL));
+#ifndef CONFIG_MODULES
+ pr_info("kmemleak: kmem_cache_alloc(files_cachep) = %p\n",
+ kmem_cache_alloc(files_cachep, GFP_KERNEL));
+ pr_info("kmemleak: kmem_cache_alloc(files_cachep) = %p\n",
+ kmem_cache_alloc(files_cachep, GFP_KERNEL));
+#endif
+ pr_info("kmemleak: vmalloc(64) = %p\n", vmalloc(64));
+ pr_info("kmemleak: vmalloc(64) = %p\n", vmalloc(64));
+ pr_info("kmemleak: vmalloc(64) = %p\n", vmalloc(64));
+ pr_info("kmemleak: vmalloc(64) = %p\n", vmalloc(64));
+ pr_info("kmemleak: vmalloc(64) = %p\n", vmalloc(64));
+
+ /*
+ * Add elements to a list. They should only appear as orphan
+ * after the module is removed.
+ */
+ for (i = 0; i < 10; i++) {
+ elem = kmalloc(sizeof(*elem), GFP_KERNEL);
+ pr_info("kmemleak: kmalloc(sizeof(*elem)) = %p\n", elem);
+ if (!elem)
+ return -ENOMEM;
+ memset(elem, 0, sizeof(*elem));
+ INIT_LIST_HEAD(&elem->list);
+
+ list_add_tail(&elem->list, &test_list);
+ }
+
+ for_each_possible_cpu(i) {
+ per_cpu(test_pointer, i) = kmalloc(129, GFP_KERNEL);
+ pr_info("kmemleak: kmalloc(129) = %p\n",
+ per_cpu(test_pointer, i));
+ }
+
+ return 0;
+}
+module_init(kmemleak_test_init);
+
+static void __exit kmemleak_test_exit(void)
+{
+ struct test_node *elem, *tmp;
+
+ /*
+ * Remove the list elements without actually freeing the
+ * memory.
+ */
+ list_for_each_entry_safe(elem, tmp, &test_list, list)
+ list_del(&elem->list);
+}
+module_exit(kmemleak_test_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
new file mode 100644
index 000000000000..c93484711147
--- /dev/null
+++ b/mm/kmemleak.c
@@ -0,0 +1,1498 @@
+/*
+ * mm/kmemleak.c
+ *
+ * Copyright (C) 2008 ARM Limited
+ * Written by Catalin Marinas <catalin.marinas@arm.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.
+ *
+ * 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
+ *
+ *
+ * For more information on the algorithm and kmemleak usage, please see
+ * Documentation/kmemleak.txt.
+ *
+ * Notes on locking
+ * ----------------
+ *
+ * The following locks and mutexes are used by kmemleak:
+ *
+ * - kmemleak_lock (rwlock): protects the object_list modifications and
+ * accesses to the object_tree_root. The object_list is the main list
+ * holding the metadata (struct kmemleak_object) for the allocated memory
+ * blocks. The object_tree_root is a priority search tree used to look-up
+ * metadata based on a pointer to the corresponding memory block. The
+ * kmemleak_object structures are added to the object_list and
+ * object_tree_root in the create_object() function called from the
+ * kmemleak_alloc() callback and removed in delete_object() called from the
+ * kmemleak_free() callback
+ * - kmemleak_object.lock (spinlock): protects a kmemleak_object. Accesses to
+ * the metadata (e.g. count) are protected by this lock. Note that some
+ * members of this structure may be protected by other means (atomic or
+ * kmemleak_lock). This lock is also held when scanning the corresponding
+ * memory block to avoid the kernel freeing it via the kmemleak_free()
+ * callback. This is less heavyweight than holding a global lock like
+ * kmemleak_lock during scanning
+ * - scan_mutex (mutex): ensures that only one thread may scan the memory for
+ * unreferenced objects at a time. The gray_list contains the objects which
+ * are already referenced or marked as false positives and need to be
+ * scanned. This list is only modified during a scanning episode when the
+ * scan_mutex is held. At the end of a scan, the gray_list is always empty.
+ * Note that the kmemleak_object.use_count is incremented when an object is
+ * added to the gray_list and therefore cannot be freed
+ * - kmemleak_mutex (mutex): prevents multiple users of the "kmemleak" debugfs
+ * file together with modifications to the memory scanning parameters
+ * including the scan_thread pointer
+ *
+ * The kmemleak_object structures have a use_count incremented or decremented
+ * using the get_object()/put_object() functions. When the use_count becomes
+ * 0, this count can no longer be incremented and put_object() schedules the
+ * kmemleak_object freeing via an RCU callback. All calls to the get_object()
+ * function must be protected by rcu_read_lock() to avoid accessing a freed
+ * structure.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/sched.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include <linux/prio_tree.h>
+#include <linux/gfp.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/cpumask.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/rcupdate.h>
+#include <linux/stacktrace.h>
+#include <linux/cache.h>
+#include <linux/percpu.h>
+#include <linux/hardirq.h>
+#include <linux/mmzone.h>
+#include <linux/slab.h>
+#include <linux/thread_info.h>
+#include <linux/err.h>
+#include <linux/uaccess.h>
+#include <linux/string.h>
+#include <linux/nodemask.h>
+#include <linux/mm.h>
+
+#include <asm/sections.h>
+#include <asm/processor.h>
+#include <asm/atomic.h>
+
+#include <linux/kmemleak.h>
+
+/*
+ * Kmemleak configuration and common defines.
+ */
+#define MAX_TRACE 16 /* stack trace length */
+#define REPORTS_NR 50 /* maximum number of reported leaks */
+#define MSECS_MIN_AGE 5000 /* minimum object age for reporting */
+#define MSECS_SCAN_YIELD 10 /* CPU yielding period */
+#define SECS_FIRST_SCAN 60 /* delay before the first scan */
+#define SECS_SCAN_WAIT 600 /* subsequent auto scanning delay */
+
+#define BYTES_PER_POINTER sizeof(void *)
+
+/* scanning area inside a memory block */
+struct kmemleak_scan_area {
+ struct hlist_node node;
+ unsigned long offset;
+ size_t length;
+};
+
+/*
+ * Structure holding the metadata for each allocated memory block.
+ * Modifications to such objects should be made while holding the
+ * object->lock. Insertions or deletions from object_list, gray_list or
+ * tree_node are already protected by the corresponding locks or mutex (see
+ * the notes on locking above). These objects are reference-counted
+ * (use_count) and freed using the RCU mechanism.
+ */
+struct kmemleak_object {
+ spinlock_t lock;
+ unsigned long flags; /* object status flags */
+ struct list_head object_list;
+ struct list_head gray_list;
+ struct prio_tree_node tree_node;
+ struct rcu_head rcu; /* object_list lockless traversal */
+ /* object usage count; object freed when use_count == 0 */
+ atomic_t use_count;
+ unsigned long pointer;
+ size_t size;
+ /* minimum number of a pointers found before it is considered leak */
+ int min_count;
+ /* the total number of pointers found pointing to this object */
+ int count;
+ /* memory ranges to be scanned inside an object (empty for all) */
+ struct hlist_head area_list;
+ unsigned long trace[MAX_TRACE];
+ unsigned int trace_len;
+ unsigned long jiffies; /* creation timestamp */
+ pid_t pid; /* pid of the current task */
+ char comm[TASK_COMM_LEN]; /* executable name */
+};
+
+/* flag representing the memory block allocation status */
+#define OBJECT_ALLOCATED (1 << 0)
+/* flag set after the first reporting of an unreference object */
+#define OBJECT_REPORTED (1 << 1)
+/* flag set to not scan the object */
+#define OBJECT_NO_SCAN (1 << 2)
+
+/* the list of all allocated objects */
+static LIST_HEAD(object_list);
+/* the list of gray-colored objects (see color_gray comment below) */
+static LIST_HEAD(gray_list);
+/* prio search tree for object boundaries */
+static struct prio_tree_root object_tree_root;
+/* rw_lock protecting the access to object_list and prio_tree_root */
+static DEFINE_RWLOCK(kmemleak_lock);
+
+/* allocation caches for kmemleak internal data */
+static struct kmem_cache *object_cache;
+static struct kmem_cache *scan_area_cache;
+
+/* set if tracing memory operations is enabled */
+static atomic_t kmemleak_enabled = ATOMIC_INIT(0);
+/* set in the late_initcall if there were no errors */
+static atomic_t kmemleak_initialized = ATOMIC_INIT(0);
+/* enables or disables early logging of the memory operations */
+static atomic_t kmemleak_early_log = ATOMIC_INIT(1);
+/* set if a fata kmemleak error has occurred */
+static atomic_t kmemleak_error = ATOMIC_INIT(0);
+
+/* minimum and maximum address that may be valid pointers */
+static unsigned long min_addr = ULONG_MAX;
+static unsigned long max_addr;
+
+/* used for yielding the CPU to other tasks during scanning */
+static unsigned long next_scan_yield;
+static struct task_struct *scan_thread;
+static unsigned long jiffies_scan_yield;
+static unsigned long jiffies_min_age;
+/* delay between automatic memory scannings */
+static signed long jiffies_scan_wait;
+/* enables or disables the task stacks scanning */
+static int kmemleak_stack_scan;
+/* mutex protecting the memory scanning */
+static DEFINE_MUTEX(scan_mutex);
+/* mutex protecting the access to the /sys/kernel/debug/kmemleak file */
+static DEFINE_MUTEX(kmemleak_mutex);
+
+/* number of leaks reported (for limitation purposes) */
+static int reported_leaks;
+
+/*
+ * Early object allocation/freeing logging. Kkmemleak is initialized after the
+ * kernel allocator. However, both the kernel allocator and kmemleak may
+ * allocate memory blocks which need to be tracked. Kkmemleak defines an
+ * arbitrary buffer to hold the allocation/freeing information before it is
+ * fully initialized.
+ */
+
+/* kmemleak operation type for early logging */
+enum {
+ KMEMLEAK_ALLOC,
+ KMEMLEAK_FREE,
+ KMEMLEAK_NOT_LEAK,
+ KMEMLEAK_IGNORE,
+ KMEMLEAK_SCAN_AREA,
+ KMEMLEAK_NO_SCAN
+};
+
+/*
+ * Structure holding the information passed to kmemleak callbacks during the
+ * early logging.
+ */
+struct early_log {
+ int op_type; /* kmemleak operation type */
+ const void *ptr; /* allocated/freed memory block */
+ size_t size; /* memory block size */
+ int min_count; /* minimum reference count */
+ unsigned long offset; /* scan area offset */
+ size_t length; /* scan area length */
+};
+
+/* early logging buffer and current position */
+static struct early_log early_log[200];
+static int crt_early_log;
+
+static void kmemleak_disable(void);
+
+/*
+ * Print a warning and dump the stack trace.
+ */
+#define kmemleak_warn(x...) do { \
+ pr_warning(x); \
+ dump_stack(); \
+} while (0)
+
+/*
+ * Macro invoked when a serious kmemleak condition occured and cannot be
+ * recovered from. Kkmemleak will be disabled and further allocation/freeing
+ * tracing no longer available.
+ */
+#define kmemleak_panic(x...) do { \
+ kmemleak_warn(x); \
+ kmemleak_disable(); \
+} while (0)
+
+/*
+ * Object colors, encoded with count and min_count:
+ * - white - orphan object, not enough references to it (count < min_count)
+ * - gray - not orphan, not marked as false positive (min_count == 0) or
+ * sufficient references to it (count >= min_count)
+ * - black - ignore, it doesn't contain references (e.g. text section)
+ * (min_count == -1). No function defined for this color.
+ * Newly created objects don't have any color assigned (object->count == -1)
+ * before the next memory scan when they become white.
+ */
+static int color_white(const struct kmemleak_object *object)
+{
+ return object->count != -1 && object->count < object->min_count;
+}
+
+static int color_gray(const struct kmemleak_object *object)
+{
+ return object->min_count != -1 && object->count >= object->min_count;
+}
+
+/*
+ * Objects are considered referenced if their color is gray and they have not
+ * been deleted.
+ */
+static int referenced_object(struct kmemleak_object *object)
+{
+ return (object->flags & OBJECT_ALLOCATED) && color_gray(object);
+}
+
+/*
+ * Objects are considered unreferenced only if their color is white, they have
+ * not be deleted and have a minimum age to avoid false positives caused by
+ * pointers temporarily stored in CPU registers.
+ */
+static int unreferenced_object(struct kmemleak_object *object)
+{
+ return (object->flags & OBJECT_ALLOCATED) && color_white(object) &&
+ time_is_before_eq_jiffies(object->jiffies + jiffies_min_age);
+}
+
+/*
+ * Printing of the (un)referenced objects information, either to the seq file
+ * or to the kernel log. The print_referenced/print_unreferenced functions
+ * must be called with the object->lock held.
+ */
+#define print_helper(seq, x...) do { \
+ struct seq_file *s = (seq); \
+ if (s) \
+ seq_printf(s, x); \
+ else \
+ pr_info(x); \
+} while (0)
+
+static void print_referenced(struct kmemleak_object *object)
+{
+ pr_info("kmemleak: referenced object 0x%08lx (size %zu)\n",
+ object->pointer, object->size);
+}
+
+static void print_unreferenced(struct seq_file *seq,
+ struct kmemleak_object *object)
+{
+ int i;
+
+ print_helper(seq, "kmemleak: unreferenced object 0x%08lx (size %zu):\n",
+ object->pointer, object->size);
+ print_helper(seq, " comm \"%s\", pid %d, jiffies %lu\n",
+ object->comm, object->pid, object->jiffies);
+ print_helper(seq, " backtrace:\n");
+
+ for (i = 0; i < object->trace_len; i++) {
+ void *ptr = (void *)object->trace[i];
+ print_helper(seq, " [<%p>] %pS\n", ptr, ptr);
+ }
+}
+
+/*
+ * Print the kmemleak_object information. This function is used mainly for
+ * debugging special cases when kmemleak operations. It must be called with
+ * the object->lock held.
+ */
+static void dump_object_info(struct kmemleak_object *object)
+{
+ struct stack_trace trace;
+
+ trace.nr_entries = object->trace_len;
+ trace.entries = object->trace;
+
+ pr_notice("kmemleak: Object 0x%08lx (size %zu):\n",
+ object->tree_node.start, object->size);
+ pr_notice(" comm \"%s\", pid %d, jiffies %lu\n",
+ object->comm, object->pid, object->jiffies);
+ pr_notice(" min_count = %d\n", object->min_count);
+ pr_notice(" count = %d\n", object->count);
+ pr_notice(" backtrace:\n");
+ print_stack_trace(&trace, 4);
+}
+
+/*
+ * Look-up a memory block metadata (kmemleak_object) in the priority search
+ * tree based on a pointer value. If alias is 0, only values pointing to the
+ * beginning of the memory block are allowed. The kmemleak_lock must be held
+ * when calling this function.
+ */
+static struct kmemleak_object *lookup_object(unsigned long ptr, int alias)
+{
+ struct prio_tree_node *node;
+ struct prio_tree_iter iter;
+ struct kmemleak_object *object;
+
+ prio_tree_iter_init(&iter, &object_tree_root, ptr, ptr);
+ node = prio_tree_next(&iter);
+ if (node) {
+ object = prio_tree_entry(node, struct kmemleak_object,
+ tree_node);
+ if (!alias && object->pointer != ptr) {
+ kmemleak_warn("kmemleak: Found object by alias");
+ object = NULL;
+ }
+ } else
+ object = NULL;
+
+ return object;
+}
+
+/*
+ * Increment the object use_count. Return 1 if successful or 0 otherwise. Note
+ * that once an object's use_count reached 0, the RCU freeing was already
+ * registered and the object should no longer be used. This function must be
+ * called under the protection of rcu_read_lock().
+ */
+static int get_object(struct kmemleak_object *object)
+{
+ return atomic_inc_not_zero(&object->use_count);
+}
+
+/*
+ * RCU callback to free a kmemleak_object.
+ */
+static void free_object_rcu(struct rcu_head *rcu)
+{
+ struct hlist_node *elem, *tmp;
+ struct kmemleak_scan_area *area;
+ struct kmemleak_object *object =
+ container_of(rcu, struct kmemleak_object, rcu);
+
+ /*
+ * Once use_count is 0 (guaranteed by put_object), there is no other
+ * code accessing this object, hence no need for locking.
+ */
+ hlist_for_each_entry_safe(area, elem, tmp, &object->area_list, node) {
+ hlist_del(elem);
+ kmem_cache_free(scan_area_cache, area);
+ }
+ kmem_cache_free(object_cache, object);
+}
+
+/*
+ * Decrement the object use_count. Once the count is 0, free the object using
+ * an RCU callback. Since put_object() may be called via the kmemleak_free() ->
+ * delete_object() path, the delayed RCU freeing ensures that there is no
+ * recursive call to the kernel allocator. Lock-less RCU object_list traversal
+ * is also possible.
+ */
+static void put_object(struct kmemleak_object *object)
+{
+ if (!atomic_dec_and_test(&object->use_count))
+ return;
+
+ /* should only get here after delete_object was called */
+ WARN_ON(object->flags & OBJECT_ALLOCATED);
+
+ call_rcu(&object->rcu, free_object_rcu);
+}
+
+/*
+ * Look up an object in the prio search tree and increase its use_count.
+ */
+static struct kmemleak_object *find_and_get_object(unsigned long ptr, int alias)
+{
+ unsigned long flags;
+ struct kmemleak_object *object = NULL;
+
+ rcu_read_lock();
+ read_lock_irqsave(&kmemleak_lock, flags);
+ if (ptr >= min_addr && ptr < max_addr)
+ object = lookup_object(ptr, alias);
+ read_unlock_irqrestore(&kmemleak_lock, flags);
+
+ /* check whether the object is still available */
+ if (object && !get_object(object))
+ object = NULL;
+ rcu_read_unlock();
+
+ return object;
+}
+
+/*
+ * Create the metadata (struct kmemleak_object) corresponding to an allocated
+ * memory block and add it to the object_list and object_tree_root.
+ */
+static void create_object(unsigned long ptr, size_t size, int min_count,
+ gfp_t gfp)
+{
+ unsigned long flags;
+ struct kmemleak_object *object;
+ struct prio_tree_node *node;
+ struct stack_trace trace;
+
+ object = kmem_cache_alloc(object_cache, gfp & ~GFP_SLAB_BUG_MASK);
+ if (!object) {
+ kmemleak_panic("kmemleak: Cannot allocate a kmemleak_object "
+ "structure\n");
+ return;
+ }
+
+ INIT_LIST_HEAD(&object->object_list);
+ INIT_LIST_HEAD(&object->gray_list);
+ INIT_HLIST_HEAD(&object->area_list);
+ spin_lock_init(&object->lock);
+ atomic_set(&object->use_count, 1);
+ object->flags = OBJECT_ALLOCATED;
+ object->pointer = ptr;
+ object->size = size;
+ object->min_count = min_count;
+ object->count = -1; /* no color initially */
+ object->jiffies = jiffies;
+
+ /* task information */
+ if (in_irq()) {
+ object->pid = 0;
+ strncpy(object->comm, "hardirq", sizeof(object->comm));
+ } else if (in_softirq()) {
+ object->pid = 0;
+ strncpy(object->comm, "softirq", sizeof(object->comm));
+ } else {
+ object->pid = current->pid;
+ /*
+ * There is a small chance of a race with set_task_comm(),
+ * however using get_task_comm() here may cause locking
+ * dependency issues with current->alloc_lock. In the worst
+ * case, the command line is not correct.
+ */
+ strncpy(object->comm, current->comm, sizeof(object->comm));
+ }
+
+ /* kernel backtrace */
+ trace.max_entries = MAX_TRACE;
+ trace.nr_entries = 0;
+ trace.entries = object->trace;
+ trace.skip = 1;
+ save_stack_trace(&trace);
+ object->trace_len = trace.nr_entries;
+
+ INIT_PRIO_TREE_NODE(&object->tree_node);
+ object->tree_node.start = ptr;
+ object->tree_node.last = ptr + size - 1;
+
+ write_lock_irqsave(&kmemleak_lock, flags);
+ min_addr = min(min_addr, ptr);
+ max_addr = max(max_addr, ptr + size);
+ node = prio_tree_insert(&object_tree_root, &object->tree_node);
+ /*
+ * The code calling the kernel does not yet have the pointer to the
+ * memory block to be able to free it. However, we still hold the
+ * kmemleak_lock here in case parts of the kernel started freeing
+ * random memory blocks.
+ */
+ if (node != &object->tree_node) {
+ unsigned long flags;
+
+ kmemleak_panic("kmemleak: Cannot insert 0x%lx into the object "
+ "search tree (already existing)\n", ptr);
+ object = lookup_object(ptr, 1);
+ spin_lock_irqsave(&object->lock, flags);
+ dump_object_info(object);
+ spin_unlock_irqrestore(&object->lock, flags);
+
+ goto out;
+ }
+ list_add_tail_rcu(&object->object_list, &object_list);
+out:
+ write_unlock_irqrestore(&kmemleak_lock, flags);
+}
+
+/*
+ * Remove the metadata (struct kmemleak_object) for a memory block from the
+ * object_list and object_tree_root and decrement its use_count.
+ */
+static void delete_object(unsigned long ptr)
+{
+ unsigned long flags;
+ struct kmemleak_object *object;
+
+ write_lock_irqsave(&kmemleak_lock, flags);
+ object = lookup_object(ptr, 0);
+ if (!object) {
+ kmemleak_warn("kmemleak: Freeing unknown object at 0x%08lx\n",
+ ptr);
+ write_unlock_irqrestore(&kmemleak_lock, flags);
+ return;
+ }
+ prio_tree_remove(&object_tree_root, &object->tree_node);
+ list_del_rcu(&object->object_list);
+ write_unlock_irqrestore(&kmemleak_lock, flags);
+
+ WARN_ON(!(object->flags & OBJECT_ALLOCATED));
+ WARN_ON(atomic_read(&object->use_count) < 1);
+
+ /*
+ * Locking here also ensures that the corresponding memory block
+ * cannot be freed when it is being scanned.
+ */
+ spin_lock_irqsave(&object->lock, flags);
+ if (object->flags & OBJECT_REPORTED)
+ print_referenced(object);
+ object->flags &= ~OBJECT_ALLOCATED;
+ spin_unlock_irqrestore(&object->lock, flags);
+ put_object(object);
+}
+
+/*
+ * Make a object permanently as gray-colored so that it can no longer be
+ * reported as a leak. This is used in general to mark a false positive.
+ */
+static void make_gray_object(unsigned long ptr)
+{
+ unsigned long flags;
+ struct kmemleak_object *object;
+
+ object = find_and_get_object(ptr, 0);
+ if (!object) {
+ kmemleak_warn("kmemleak: Graying unknown object at 0x%08lx\n",
+ ptr);
+ return;
+ }
+
+ spin_lock_irqsave(&object->lock, flags);
+ object->min_count = 0;
+ spin_unlock_irqrestore(&object->lock, flags);
+ put_object(object);
+}
+
+/*
+ * Mark the object as black-colored so that it is ignored from scans and
+ * reporting.
+ */
+static void make_black_object(unsigned long ptr)
+{
+ unsigned long flags;
+ struct kmemleak_object *object;
+
+ object = find_and_get_object(ptr, 0);
+ if (!object) {
+ kmemleak_warn("kmemleak: Blacking unknown object at 0x%08lx\n",
+ ptr);
+ return;
+ }
+
+ spin_lock_irqsave(&object->lock, flags);
+ object->min_count = -1;
+ spin_unlock_irqrestore(&object->lock, flags);
+ put_object(object);
+}
+
+/*
+ * Add a scanning area to the object. If at least one such area is added,
+ * kmemleak will only scan these ranges rather than the whole memory block.
+ */
+static void add_scan_area(unsigned long ptr, unsigned long offset,
+ size_t length, gfp_t gfp)
+{
+ unsigned long flags;
+ struct kmemleak_object *object;
+ struct kmemleak_scan_area *area;
+
+ object = find_and_get_object(ptr, 0);
+ if (!object) {
+ kmemleak_warn("kmemleak: Adding scan area to unknown "
+ "object at 0x%08lx\n", ptr);
+ return;
+ }
+
+ area = kmem_cache_alloc(scan_area_cache, gfp & ~GFP_SLAB_BUG_MASK);
+ if (!area) {
+ kmemleak_warn("kmemleak: Cannot allocate a scan area\n");
+ goto out;
+ }
+
+ spin_lock_irqsave(&object->lock, flags);
+ if (offset + length > object->size) {
+ kmemleak_warn("kmemleak: Scan area larger than object "
+ "0x%08lx\n", ptr);
+ dump_object_info(object);
+ kmem_cache_free(scan_area_cache, area);
+ goto out_unlock;
+ }
+
+ INIT_HLIST_NODE(&area->node);
+ area->offset = offset;
+ area->length = length;
+
+ hlist_add_head(&area->node, &object->area_list);
+out_unlock:
+ spin_unlock_irqrestore(&object->lock, flags);
+out:
+ put_object(object);
+}
+
+/*
+ * Set the OBJECT_NO_SCAN flag for the object corresponding to the give
+ * pointer. Such object will not be scanned by kmemleak but references to it
+ * are searched.
+ */
+static void object_no_scan(unsigned long ptr)
+{
+ unsigned long flags;
+ struct kmemleak_object *object;
+
+ object = find_and_get_object(ptr, 0);
+ if (!object) {
+ kmemleak_warn("kmemleak: Not scanning unknown object at "
+ "0x%08lx\n", ptr);
+ return;
+ }
+
+ spin_lock_irqsave(&object->lock, flags);
+ object->flags |= OBJECT_NO_SCAN;
+ spin_unlock_irqrestore(&object->lock, flags);
+ put_object(object);
+}
+
+/*
+ * Log an early kmemleak_* call to the early_log buffer. These calls will be
+ * processed later once kmemleak is fully initialized.
+ */
+static void log_early(int op_type, const void *ptr, size_t size,
+ int min_count, unsigned long offset, size_t length)
+{
+ unsigned long flags;
+ struct early_log *log;
+
+ if (crt_early_log >= ARRAY_SIZE(early_log)) {
+ kmemleak_panic("kmemleak: Early log buffer exceeded\n");
+ return;
+ }
+
+ /*
+ * There is no need for locking since the kernel is still in UP mode
+ * at this stage. Disabling the IRQs is enough.
+ */
+ local_irq_save(flags);
+ log = &early_log[crt_early_log];
+ log->op_type = op_type;
+ log->ptr = ptr;
+ log->size = size;
+ log->min_count = min_count;
+ log->offset = offset;
+ log->length = length;
+ crt_early_log++;
+ local_irq_restore(flags);
+}
+
+/*
+ * Memory allocation function callback. This function is called from the
+ * kernel allocators when a new block is allocated (kmem_cache_alloc, kmalloc,
+ * vmalloc etc.).
+ */
+void kmemleak_alloc(const void *ptr, size_t size, int min_count, gfp_t gfp)
+{
+ pr_debug("%s(0x%p, %zu, %d)\n", __func__, ptr, size, min_count);
+
+ if (atomic_read(&kmemleak_enabled) && !IS_ERR(ptr))
+ create_object((unsigned long)ptr, size, min_count, gfp);
+ else if (atomic_read(&kmemleak_early_log))
+ log_early(KMEMLEAK_ALLOC, ptr, size, min_count, 0, 0);
+}
+EXPORT_SYMBOL_GPL(kmemleak_alloc);
+
+/*
+ * Memory freeing function callback. This function is called from the kernel
+ * allocators when a block is freed (kmem_cache_free, kfree, vfree etc.).
+ */
+void kmemleak_free(const void *ptr)
+{
+ pr_debug("%s(0x%p)\n", __func__, ptr);
+
+ if (atomic_read(&kmemleak_enabled) && !IS_ERR(ptr))
+ delete_object((unsigned long)ptr);
+ else if (atomic_read(&kmemleak_early_log))
+ log_early(KMEMLEAK_FREE, ptr, 0, 0, 0, 0);
+}
+EXPORT_SYMBOL_GPL(kmemleak_free);
+
+/*
+ * Mark an already allocated memory block as a false positive. This will cause
+ * the block to no longer be reported as leak and always be scanned.
+ */
+void kmemleak_not_leak(const void *ptr)
+{
+ pr_debug("%s(0x%p)\n", __func__, ptr);
+
+ if (atomic_read(&kmemleak_enabled) && !IS_ERR(ptr))
+ make_gray_object((unsigned long)ptr);
+ else if (atomic_read(&kmemleak_early_log))
+ log_early(KMEMLEAK_NOT_LEAK, ptr, 0, 0, 0, 0);
+}
+EXPORT_SYMBOL(kmemleak_not_leak);
+
+/*
+ * Ignore a memory block. This is usually done when it is known that the
+ * corresponding block is not a leak and does not contain any references to
+ * other allocated memory blocks.
+ */
+void kmemleak_ignore(const void *ptr)
+{
+ pr_debug("%s(0x%p)\n", __func__, ptr);
+
+ if (atomic_read(&kmemleak_enabled) && !IS_ERR(ptr))
+ make_black_object((unsigned long)ptr);
+ else if (atomic_read(&kmemleak_early_log))
+ log_early(KMEMLEAK_IGNORE, ptr, 0, 0, 0, 0);
+}
+EXPORT_SYMBOL(kmemleak_ignore);
+
+/*
+ * Limit the range to be scanned in an allocated memory block.
+ */
+void kmemleak_scan_area(const void *ptr, unsigned long offset, size_t length,
+ gfp_t gfp)
+{
+ pr_debug("%s(0x%p)\n", __func__, ptr);
+
+ if (atomic_read(&kmemleak_enabled) && !IS_ERR(ptr))
+ add_scan_area((unsigned long)ptr, offset, length, gfp);
+ else if (atomic_read(&kmemleak_early_log))
+ log_early(KMEMLEAK_SCAN_AREA, ptr, 0, 0, offset, length);
+}
+EXPORT_SYMBOL(kmemleak_scan_area);
+
+/*
+ * Inform kmemleak not to scan the given memory block.
+ */
+void kmemleak_no_scan(const void *ptr)
+{
+ pr_debug("%s(0x%p)\n", __func__, ptr);
+
+ if (atomic_read(&kmemleak_enabled) && !IS_ERR(ptr))
+ object_no_scan((unsigned long)ptr);
+ else if (atomic_read(&kmemleak_early_log))
+ log_early(KMEMLEAK_NO_SCAN, ptr, 0, 0, 0, 0);
+}
+EXPORT_SYMBOL(kmemleak_no_scan);
+
+/*
+ * Yield the CPU so that other tasks get a chance to run. The yielding is
+ * rate-limited to avoid excessive number of calls to the schedule() function
+ * during memory scanning.
+ */
+static void scan_yield(void)
+{
+ might_sleep();
+
+ if (time_is_before_eq_jiffies(next_scan_yield)) {
+ schedule();
+ next_scan_yield = jiffies + jiffies_scan_yield;
+ }
+}
+
+/*
+ * Memory scanning is a long process and it needs to be interruptable. This
+ * function checks whether such interrupt condition occured.
+ */
+static int scan_should_stop(void)
+{
+ if (!atomic_read(&kmemleak_enabled))
+ return 1;
+
+ /*
+ * This function may be called from either process or kthread context,
+ * hence the need to check for both stop conditions.
+ */
+ if (current->mm)
+ return signal_pending(current);
+ else
+ return kthread_should_stop();
+
+ return 0;
+}
+
+/*
+ * Scan a memory block (exclusive range) for valid pointers and add those
+ * found to the gray list.
+ */
+static void scan_block(void *_start, void *_end,
+ struct kmemleak_object *scanned)
+{
+ unsigned long *ptr;
+ unsigned long *start = PTR_ALIGN(_start, BYTES_PER_POINTER);
+ unsigned long *end = _end - (BYTES_PER_POINTER - 1);
+
+ for (ptr = start; ptr < end; ptr++) {
+ unsigned long flags;
+ unsigned long pointer = *ptr;
+ struct kmemleak_object *object;
+
+ if (scan_should_stop())
+ break;
+
+ /*
+ * When scanning a memory block with a corresponding
+ * kmemleak_object, the CPU yielding is handled in the calling
+ * code since it holds the object->lock to avoid the block
+ * freeing.
+ */
+ if (!scanned)
+ scan_yield();
+
+ object = find_and_get_object(pointer, 1);
+ if (!object)
+ continue;
+ if (object == scanned) {
+ /* self referenced, ignore */
+ put_object(object);
+ continue;
+ }
+
+ /*
+ * Avoid the lockdep recursive warning on object->lock being
+ * previously acquired in scan_object(). These locks are
+ * enclosed by scan_mutex.
+ */
+ spin_lock_irqsave_nested(&object->lock, flags,
+ SINGLE_DEPTH_NESTING);
+ if (!color_white(object)) {
+ /* non-orphan, ignored or new */
+ spin_unlock_irqrestore(&object->lock, flags);
+ put_object(object);
+ continue;
+ }
+
+ /*
+ * Increase the object's reference count (number of pointers
+ * to the memory block). If this count reaches the required
+ * minimum, the object's color will become gray and it will be
+ * added to the gray_list.
+ */
+ object->count++;
+ if (color_gray(object))
+ list_add_tail(&object->gray_list, &gray_list);
+ else
+ put_object(object);
+ spin_unlock_irqrestore(&object->lock, flags);
+ }
+}
+
+/*
+ * Scan a memory block corresponding to a kmemleak_object. A condition is
+ * that object->use_count >= 1.
+ */
+static void scan_object(struct kmemleak_object *object)
+{
+ struct kmemleak_scan_area *area;
+ struct hlist_node *elem;
+ unsigned long flags;
+
+ /*
+ * Once the object->lock is aquired, the corresponding memory block
+ * cannot be freed (the same lock is aquired in delete_object).
+ */
+ spin_lock_irqsave(&object->lock, flags);
+ if (object->flags & OBJECT_NO_SCAN)
+ goto out;
+ if (!(object->flags & OBJECT_ALLOCATED))
+ /* already freed object */
+ goto out;
+ if (hlist_empty(&object->area_list))
+ scan_block((void *)object->pointer,
+ (void *)(object->pointer + object->size), object);
+ else
+ hlist_for_each_entry(area, elem, &object->area_list, node)
+ scan_block((void *)(object->pointer + area->offset),
+ (void *)(object->pointer + area->offset
+ + area->length), object);
+out:
+ spin_unlock_irqrestore(&object->lock, flags);
+}
+
+/*
+ * Scan data sections and all the referenced memory blocks allocated via the
+ * kernel's standard allocators. This function must be called with the
+ * scan_mutex held.
+ */
+static void kmemleak_scan(void)
+{
+ unsigned long flags;
+ struct kmemleak_object *object, *tmp;
+ struct task_struct *task;
+ int i;
+
+ /* prepare the kmemleak_object's */
+ rcu_read_lock();
+ list_for_each_entry_rcu(object, &object_list, object_list) {
+ spin_lock_irqsave(&object->lock, flags);
+#ifdef DEBUG
+ /*
+ * With a few exceptions there should be a maximum of
+ * 1 reference to any object at this point.
+ */
+ if (atomic_read(&object->use_count) > 1) {
+ pr_debug("kmemleak: object->use_count = %d\n",
+ atomic_read(&object->use_count));
+ dump_object_info(object);
+ }
+#endif
+ /* reset the reference count (whiten the object) */
+ object->count = 0;
+ if (color_gray(object) && get_object(object))
+ list_add_tail(&object->gray_list, &gray_list);
+
+ spin_unlock_irqrestore(&object->lock, flags);
+ }
+ rcu_read_unlock();
+
+ /* data/bss scanning */
+ scan_block(_sdata, _edata, NULL);
+ scan_block(__bss_start, __bss_stop, NULL);
+
+#ifdef CONFIG_SMP
+ /* per-cpu sections scanning */
+ for_each_possible_cpu(i)
+ scan_block(__per_cpu_start + per_cpu_offset(i),
+ __per_cpu_end + per_cpu_offset(i), NULL);
+#endif
+
+ /*
+ * Struct page scanning for each node. The code below is not yet safe
+ * with MEMORY_HOTPLUG.
+ */
+ for_each_online_node(i) {
+ pg_data_t *pgdat = NODE_DATA(i);
+ unsigned long start_pfn = pgdat->node_start_pfn;
+ unsigned long end_pfn = start_pfn + pgdat->node_spanned_pages;
+ unsigned long pfn;
+
+ for (pfn = start_pfn; pfn < end_pfn; pfn++) {
+ struct page *page;
+
+ if (!pfn_valid(pfn))
+ continue;
+ page = pfn_to_page(pfn);
+ /* only scan if page is in use */
+ if (page_count(page) == 0)
+ continue;
+ scan_block(page, page + 1, NULL);
+ }
+ }
+
+ /*
+ * Scanning the task stacks may introduce false negatives and it is
+ * not enabled by default.
+ */
+ if (kmemleak_stack_scan) {
+ read_lock(&tasklist_lock);
+ for_each_process(task)
+ scan_block(task_stack_page(task),
+ task_stack_page(task) + THREAD_SIZE, NULL);
+ read_unlock(&tasklist_lock);
+ }
+
+ /*
+ * Scan the objects already referenced from the sections scanned
+ * above. More objects will be referenced and, if there are no memory
+ * leaks, all the objects will be scanned. The list traversal is safe
+ * for both tail additions and removals from inside the loop. The
+ * kmemleak objects cannot be freed from outside the loop because their
+ * use_count was increased.
+ */
+ object = list_entry(gray_list.next, typeof(*object), gray_list);
+ while (&object->gray_list != &gray_list) {
+ scan_yield();
+
+ /* may add new objects to the list */
+ if (!scan_should_stop())
+ scan_object(object);
+
+ tmp = list_entry(object->gray_list.next, typeof(*object),
+ gray_list);
+
+ /* remove the object from the list and release it */
+ list_del(&object->gray_list);
+ put_object(object);
+
+ object = tmp;
+ }
+ WARN_ON(!list_empty(&gray_list));
+}
+
+/*
+ * Thread function performing automatic memory scanning. Unreferenced objects
+ * at the end of a memory scan are reported but only the first time.
+ */
+static int kmemleak_scan_thread(void *arg)
+{
+ static int first_run = 1;
+
+ pr_info("kmemleak: Automatic memory scanning thread started\n");
+
+ /*
+ * Wait before the first scan to allow the system to fully initialize.
+ */
+ if (first_run) {
+ first_run = 0;
+ ssleep(SECS_FIRST_SCAN);
+ }
+
+ while (!kthread_should_stop()) {
+ struct kmemleak_object *object;
+ signed long timeout = jiffies_scan_wait;
+
+ mutex_lock(&scan_mutex);
+
+ kmemleak_scan();
+ reported_leaks = 0;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(object, &object_list, object_list) {
+ unsigned long flags;
+
+ if (reported_leaks >= REPORTS_NR)
+ break;
+ spin_lock_irqsave(&object->lock, flags);
+ if (!(object->flags & OBJECT_REPORTED) &&
+ unreferenced_object(object)) {
+ print_unreferenced(NULL, object);
+ object->flags |= OBJECT_REPORTED;
+ reported_leaks++;
+ } else if ((object->flags & OBJECT_REPORTED) &&
+ referenced_object(object)) {
+ print_referenced(object);
+ object->flags &= ~OBJECT_REPORTED;
+ }
+ spin_unlock_irqrestore(&object->lock, flags);
+ }
+ rcu_read_unlock();
+
+ mutex_unlock(&scan_mutex);
+ /* wait before the next scan */
+ while (timeout && !kthread_should_stop())
+ timeout = schedule_timeout_interruptible(timeout);
+ }
+
+ pr_info("kmemleak: Automatic memory scanning thread ended\n");
+
+ return 0;
+}
+
+/*
+ * Start the automatic memory scanning thread. This function must be called
+ * with the kmemleak_mutex held.
+ */
+void start_scan_thread(void)
+{
+ if (scan_thread)
+ return;
+ scan_thread = kthread_run(kmemleak_scan_thread, NULL, "kmemleak");
+ if (IS_ERR(scan_thread)) {
+ pr_warning("kmemleak: Failed to create the scan thread\n");
+ scan_thread = NULL;
+ }
+}
+
+/*
+ * Stop the automatic memory scanning thread. This function must be called
+ * with the kmemleak_mutex held.
+ */
+void stop_scan_thread(void)
+{
+ if (scan_thread) {
+ kthread_stop(scan_thread);
+ scan_thread = NULL;
+ }
+}
+
+/*
+ * Iterate over the object_list and return the first valid object at or after
+ * the required position with its use_count incremented. The function triggers
+ * a memory scanning when the pos argument points to the first position.
+ */
+static void *kmemleak_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ struct kmemleak_object *object;
+ loff_t n = *pos;
+
+ if (!n) {
+ kmemleak_scan();
+ reported_leaks = 0;
+ }
+ if (reported_leaks >= REPORTS_NR)
+ return NULL;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(object, &object_list, object_list) {
+ if (n-- > 0)
+ continue;
+ if (get_object(object))
+ goto out;
+ }
+ object = NULL;
+out:
+ rcu_read_unlock();
+ return object;
+}
+
+/*
+ * Return the next object in the object_list. The function decrements the
+ * use_count of the previous object and increases that of the next one.
+ */
+static void *kmemleak_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ struct kmemleak_object *prev_obj = v;
+ struct kmemleak_object *next_obj = NULL;
+ struct list_head *n = &prev_obj->object_list;
+
+ ++(*pos);
+ if (reported_leaks >= REPORTS_NR)
+ goto out;
+
+ rcu_read_lock();
+ list_for_each_continue_rcu(n, &object_list) {
+ next_obj = list_entry(n, struct kmemleak_object, object_list);
+ if (get_object(next_obj))
+ break;
+ }
+ rcu_read_unlock();
+out:
+ put_object(prev_obj);
+ return next_obj;
+}
+
+/*
+ * Decrement the use_count of the last object required, if any.
+ */
+static void kmemleak_seq_stop(struct seq_file *seq, void *v)
+{
+ if (v)
+ put_object(v);
+}
+
+/*
+ * Print the information for an unreferenced object to the seq file.
+ */
+static int kmemleak_seq_show(struct seq_file *seq, void *v)
+{
+ struct kmemleak_object *object = v;
+ unsigned long flags;
+
+ spin_lock_irqsave(&object->lock, flags);
+ if (!unreferenced_object(object))
+ goto out;
+ print_unreferenced(seq, object);
+ reported_leaks++;
+out:
+ spin_unlock_irqrestore(&object->lock, flags);
+ return 0;
+}
+
+static const struct seq_operations kmemleak_seq_ops = {
+ .start = kmemleak_seq_start,
+ .next = kmemleak_seq_next,
+ .stop = kmemleak_seq_stop,
+ .show = kmemleak_seq_show,
+};
+
+static int kmemleak_open(struct inode *inode, struct file *file)
+{
+ int ret = 0;
+
+ if (!atomic_read(&kmemleak_enabled))
+ return -EBUSY;
+
+ ret = mutex_lock_interruptible(&kmemleak_mutex);
+ if (ret < 0)
+ goto out;
+ if (file->f_mode & FMODE_READ) {
+ ret = mutex_lock_interruptible(&scan_mutex);
+ if (ret < 0)
+ goto kmemleak_unlock;
+ ret = seq_open(file, &kmemleak_seq_ops);
+ if (ret < 0)
+ goto scan_unlock;
+ }
+ return ret;
+
+scan_unlock:
+ mutex_unlock(&scan_mutex);
+kmemleak_unlock:
+ mutex_unlock(&kmemleak_mutex);
+out:
+ return ret;
+}
+
+static int kmemleak_release(struct inode *inode, struct file *file)
+{
+ int ret = 0;
+
+ if (file->f_mode & FMODE_READ) {
+ seq_release(inode, file);
+ mutex_unlock(&scan_mutex);
+ }
+ mutex_unlock(&kmemleak_mutex);
+
+ return ret;
+}
+
+/*
+ * File write operation to configure kmemleak at run-time. The following
+ * commands can be written to the /sys/kernel/debug/kmemleak file:
+ * off - disable kmemleak (irreversible)
+ * stack=on - enable the task stacks scanning
+ * stack=off - disable the tasks stacks scanning
+ * scan=on - start the automatic memory scanning thread
+ * scan=off - stop the automatic memory scanning thread
+ * scan=... - set the automatic memory scanning period in seconds (0 to
+ * disable it)
+ */
+static ssize_t kmemleak_write(struct file *file, const char __user *user_buf,
+ size_t size, loff_t *ppos)
+{
+ char buf[64];
+ int buf_size;
+
+ if (!atomic_read(&kmemleak_enabled))
+ return -EBUSY;
+
+ buf_size = min(size, (sizeof(buf) - 1));
+ if (strncpy_from_user(buf, user_buf, buf_size) < 0)
+ return -EFAULT;
+ buf[buf_size] = 0;
+
+ if (strncmp(buf, "off", 3) == 0)
+ kmemleak_disable();
+ else if (strncmp(buf, "stack=on", 8) == 0)
+ kmemleak_stack_scan = 1;
+ else if (strncmp(buf, "stack=off", 9) == 0)
+ kmemleak_stack_scan = 0;
+ else if (strncmp(buf, "scan=on", 7) == 0)
+ start_scan_thread();
+ else if (strncmp(buf, "scan=off", 8) == 0)
+ stop_scan_thread();
+ else if (strncmp(buf, "scan=", 5) == 0) {
+ unsigned long secs;
+ int err;
+
+ err = strict_strtoul(buf + 5, 0, &secs);
+ if (err < 0)
+ return err;
+ stop_scan_thread();
+ if (secs) {
+ jiffies_scan_wait = msecs_to_jiffies(secs * 1000);
+ start_scan_thread();
+ }
+ } else
+ return -EINVAL;
+
+ /* ignore the rest of the buffer, only one command at a time */
+ *ppos += size;
+ return size;
+}
+
+static const struct file_operations kmemleak_fops = {
+ .owner = THIS_MODULE,
+ .open = kmemleak_open,
+ .read = seq_read,
+ .write = kmemleak_write,
+ .llseek = seq_lseek,
+ .release = kmemleak_release,
+};
+
+/*
+ * Perform the freeing of the kmemleak internal objects after waiting for any
+ * current memory scan to complete.
+ */
+static int kmemleak_cleanup_thread(void *arg)
+{
+ struct kmemleak_object *object;
+
+ mutex_lock(&kmemleak_mutex);
+ stop_scan_thread();
+ mutex_unlock(&kmemleak_mutex);
+
+ mutex_lock(&scan_mutex);
+ rcu_read_lock();
+ list_for_each_entry_rcu(object, &object_list, object_list)
+ delete_object(object->pointer);
+ rcu_read_unlock();
+ mutex_unlock(&scan_mutex);
+
+ return 0;
+}
+
+/*
+ * Start the clean-up thread.
+ */
+static void kmemleak_cleanup(void)
+{
+ struct task_struct *cleanup_thread;
+
+ cleanup_thread = kthread_run(kmemleak_cleanup_thread, NULL,
+ "kmemleak-clean");
+ if (IS_ERR(cleanup_thread))
+ pr_warning("kmemleak: Failed to create the clean-up thread\n");
+}
+
+/*
+ * Disable kmemleak. No memory allocation/freeing will be traced once this
+ * function is called. Disabling kmemleak is an irreversible operation.
+ */
+static void kmemleak_disable(void)
+{
+ /* atomically check whether it was already invoked */
+ if (atomic_cmpxchg(&kmemleak_error, 0, 1))
+ return;
+
+ /* stop any memory operation tracing */
+ atomic_set(&kmemleak_early_log, 0);
+ atomic_set(&kmemleak_enabled, 0);
+
+ /* check whether it is too early for a kernel thread */
+ if (atomic_read(&kmemleak_initialized))
+ kmemleak_cleanup();
+
+ pr_info("Kernel memory leak detector disabled\n");
+}
+
+/*
+ * Allow boot-time kmemleak disabling (enabled by default).
+ */
+static int kmemleak_boot_config(char *str)
+{
+ if (!str)
+ return -EINVAL;
+ if (strcmp(str, "off") == 0)
+ kmemleak_disable();
+ else if (strcmp(str, "on") != 0)
+ return -EINVAL;
+ return 0;
+}
+early_param("kmemleak", kmemleak_boot_config);
+
+/*
+ * Kkmemleak initialization.
+ */
+void __init kmemleak_init(void)
+{
+ int i;
+ unsigned long flags;
+
+ jiffies_scan_yield = msecs_to_jiffies(MSECS_SCAN_YIELD);
+ jiffies_min_age = msecs_to_jiffies(MSECS_MIN_AGE);
+ jiffies_scan_wait = msecs_to_jiffies(SECS_SCAN_WAIT * 1000);
+
+ object_cache = KMEM_CACHE(kmemleak_object, SLAB_NOLEAKTRACE);
+ scan_area_cache = KMEM_CACHE(kmemleak_scan_area, SLAB_NOLEAKTRACE);
+ INIT_PRIO_TREE_ROOT(&object_tree_root);
+
+ /* the kernel is still in UP mode, so disabling the IRQs is enough */
+ local_irq_save(flags);
+ if (!atomic_read(&kmemleak_error)) {
+ atomic_set(&kmemleak_enabled, 1);
+ atomic_set(&kmemleak_early_log, 0);
+ }
+ local_irq_restore(flags);
+
+ /*
+ * This is the point where tracking allocations is safe. Automatic
+ * scanning is started during the late initcall. Add the early logged
+ * callbacks to the kmemleak infrastructure.
+ */
+ for (i = 0; i < crt_early_log; i++) {
+ struct early_log *log = &early_log[i];
+
+ switch (log->op_type) {
+ case KMEMLEAK_ALLOC:
+ kmemleak_alloc(log->ptr, log->size, log->min_count,
+ GFP_KERNEL);
+ break;
+ case KMEMLEAK_FREE:
+ kmemleak_free(log->ptr);
+ break;
+ case KMEMLEAK_NOT_LEAK:
+ kmemleak_not_leak(log->ptr);
+ break;
+ case KMEMLEAK_IGNORE:
+ kmemleak_ignore(log->ptr);
+ break;
+ case KMEMLEAK_SCAN_AREA:
+ kmemleak_scan_area(log->ptr, log->offset, log->length,
+ GFP_KERNEL);
+ break;
+ case KMEMLEAK_NO_SCAN:
+ kmemleak_no_scan(log->ptr);
+ break;
+ default:
+ WARN_ON(1);
+ }
+ }
+}
+
+/*
+ * Late initialization function.
+ */
+static int __init kmemleak_late_init(void)
+{
+ struct dentry *dentry;
+
+ atomic_set(&kmemleak_initialized, 1);
+
+ if (atomic_read(&kmemleak_error)) {
+ /*
+ * Some error occured and kmemleak was disabled. There is a
+ * small chance that kmemleak_disable() was called immediately
+ * after setting kmemleak_initialized and we may end up with
+ * two clean-up threads but serialized by scan_mutex.
+ */
+ kmemleak_cleanup();
+ return -ENOMEM;
+ }
+
+ dentry = debugfs_create_file("kmemleak", S_IRUGO, NULL, NULL,
+ &kmemleak_fops);
+ if (!dentry)
+ pr_warning("kmemleak: Failed to create the debugfs kmemleak "
+ "file\n");
+ mutex_lock(&kmemleak_mutex);
+ start_scan_thread();
+ mutex_unlock(&kmemleak_mutex);
+
+ pr_info("Kernel memory leak detector initialized\n");
+
+ return 0;
+}
+late_initcall(kmemleak_late_init);
diff --git a/mm/madvise.c b/mm/madvise.c
index b9ce574827c8..36d6ea2b6340 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -112,6 +112,14 @@ static long madvise_willneed(struct vm_area_struct * vma,
if (!file)
return -EBADF;
+ /*
+ * Page cache readahead assumes page cache pages are order-0 which
+ * is not the case for hugetlbfs. Do not give a bad return value
+ * but ignore the advice.
+ */
+ if (vma->vm_flags & VM_HUGETLB)
+ return 0;
+
if (file->f_mapping->a_ops->get_xip_mem) {
/* no bad return value, but ignore advice */
return 0;
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 2fc6d6c48238..01c2d8f14685 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -932,7 +932,7 @@ static int __mem_cgroup_try_charge(struct mm_struct *mm,
if (unlikely(!mem))
return 0;
- VM_BUG_ON(mem_cgroup_is_obsolete(mem));
+ VM_BUG_ON(!mem || mem_cgroup_is_obsolete(mem));
while (1) {
int ret;
@@ -1024,9 +1024,7 @@ static struct mem_cgroup *try_get_mem_cgroup_from_swapcache(struct page *page)
return NULL;
pc = lookup_page_cgroup(page);
- /*
- * Used bit of swapcache is solid under page lock.
- */
+ lock_page_cgroup(pc);
if (PageCgroupUsed(pc)) {
mem = pc->mem_cgroup;
if (mem && !css_tryget(&mem->css))
@@ -1040,6 +1038,7 @@ static struct mem_cgroup *try_get_mem_cgroup_from_swapcache(struct page *page)
mem = NULL;
rcu_read_unlock();
}
+ unlock_page_cgroup(pc);
return mem;
}
@@ -1618,37 +1617,28 @@ void mem_cgroup_end_migration(struct mem_cgroup *mem,
}
/*
- * A call to try to shrink memory usage under specified resource controller.
- * This is typically used for page reclaiming for shmem for reducing side
- * effect of page allocation from shmem, which is used by some mem_cgroup.
+ * A call to try to shrink memory usage on charge failure at shmem's swapin.
+ * Calling hierarchical_reclaim is not enough because we should update
+ * last_oom_jiffies to prevent pagefault_out_of_memory from invoking global OOM.
+ * Moreover considering hierarchy, we should reclaim from the mem_over_limit,
+ * not from the memcg which this page would be charged to.
+ * try_charge_swapin does all of these works properly.
*/
-int mem_cgroup_shrink_usage(struct page *page,
+int mem_cgroup_shmem_charge_fallback(struct page *page,
struct mm_struct *mm,
gfp_t gfp_mask)
{
struct mem_cgroup *mem = NULL;
- int progress = 0;
- int retry = MEM_CGROUP_RECLAIM_RETRIES;
+ int ret;
if (mem_cgroup_disabled())
return 0;
- if (page)
- mem = try_get_mem_cgroup_from_swapcache(page);
- if (!mem && mm)
- mem = try_get_mem_cgroup_from_mm(mm);
- if (unlikely(!mem))
- return 0;
- do {
- progress = mem_cgroup_hierarchical_reclaim(mem,
- gfp_mask, true, false);
- progress += mem_cgroup_check_under_limit(mem);
- } while (!progress && --retry);
+ ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &mem);
+ if (!ret)
+ mem_cgroup_cancel_charge_swapin(mem); /* it does !mem check */
- css_put(&mem->css);
- if (!retry)
- return -ENOMEM;
- return 0;
+ return ret;
}
static DEFINE_MUTEX(set_limit_mutex);
diff --git a/mm/memory.c b/mm/memory.c
index cf6873e91c6a..4126dd16778c 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1971,6 +1971,15 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
ret = tmp;
goto unwritable_page;
}
+ if (unlikely(!(tmp & VM_FAULT_LOCKED))) {
+ lock_page(old_page);
+ if (!old_page->mapping) {
+ ret = 0; /* retry the fault */
+ unlock_page(old_page);
+ goto unwritable_page;
+ }
+ } else
+ VM_BUG_ON(!PageLocked(old_page));
/*
* Since we dropped the lock we need to revalidate
@@ -1980,9 +1989,11 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
*/
page_table = pte_offset_map_lock(mm, pmd, address,
&ptl);
- page_cache_release(old_page);
- if (!pte_same(*page_table, orig_pte))
+ if (!pte_same(*page_table, orig_pte)) {
+ unlock_page(old_page);
+ page_cache_release(old_page);
goto unlock;
+ }
page_mkwrite = 1;
}
@@ -2094,9 +2105,6 @@ gotten:
unlock:
pte_unmap_unlock(page_table, ptl);
if (dirty_page) {
- if (vma->vm_file)
- file_update_time(vma->vm_file);
-
/*
* Yes, Virginia, this is actually required to prevent a race
* with clear_page_dirty_for_io() from clearing the page dirty
@@ -2105,16 +2113,41 @@ unlock:
*
* do_no_page is protected similarly.
*/
- wait_on_page_locked(dirty_page);
- set_page_dirty_balance(dirty_page, page_mkwrite);
+ if (!page_mkwrite) {
+ wait_on_page_locked(dirty_page);
+ set_page_dirty_balance(dirty_page, page_mkwrite);
+ }
put_page(dirty_page);
+ if (page_mkwrite) {
+ struct address_space *mapping = dirty_page->mapping;
+
+ set_page_dirty(dirty_page);
+ unlock_page(dirty_page);
+ page_cache_release(dirty_page);
+ if (mapping) {
+ /*
+ * Some device drivers do not set page.mapping
+ * but still dirty their pages
+ */
+ balance_dirty_pages_ratelimited(mapping);
+ }
+ }
+
+ /* file_update_time outside page_lock */
+ if (vma->vm_file)
+ file_update_time(vma->vm_file);
}
return ret;
oom_free_new:
page_cache_release(new_page);
oom:
- if (old_page)
+ if (old_page) {
+ if (page_mkwrite) {
+ unlock_page(old_page);
+ page_cache_release(old_page);
+ }
page_cache_release(old_page);
+ }
return VM_FAULT_OOM;
unwritable_page:
@@ -2458,8 +2491,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
if (mem_cgroup_try_charge_swapin(mm, page, GFP_KERNEL, &ptr)) {
ret = VM_FAULT_OOM;
- unlock_page(page);
- goto out;
+ goto out_page;
}
/*
@@ -2521,6 +2553,7 @@ out:
out_nomap:
mem_cgroup_cancel_charge_swapin(ptr);
pte_unmap_unlock(page_table, ptl);
+out_page:
unlock_page(page);
page_cache_release(page);
return ret;
@@ -2664,27 +2697,22 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
int tmp;
unlock_page(page);
- vmf.flags |= FAULT_FLAG_MKWRITE;
+ vmf.flags = FAULT_FLAG_WRITE|FAULT_FLAG_MKWRITE;
tmp = vma->vm_ops->page_mkwrite(vma, &vmf);
if (unlikely(tmp &
(VM_FAULT_ERROR | VM_FAULT_NOPAGE))) {
ret = tmp;
- anon = 1; /* no anon but release vmf.page */
- goto out_unlocked;
- }
- lock_page(page);
- /*
- * XXX: this is not quite right (racy vs
- * invalidate) to unlock and relock the page
- * like this, however a better fix requires
- * reworking page_mkwrite locking API, which
- * is better done later.
- */
- if (!page->mapping) {
- ret = 0;
- anon = 1; /* no anon but release vmf.page */
- goto out;
+ goto unwritable_page;
}
+ if (unlikely(!(tmp & VM_FAULT_LOCKED))) {
+ lock_page(page);
+ if (!page->mapping) {
+ ret = 0; /* retry the fault */
+ unlock_page(page);
+ goto unwritable_page;
+ }
+ } else
+ VM_BUG_ON(!PageLocked(page));
page_mkwrite = 1;
}
}
@@ -2736,19 +2764,35 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
pte_unmap_unlock(page_table, ptl);
out:
- unlock_page(vmf.page);
-out_unlocked:
- if (anon)
- page_cache_release(vmf.page);
- else if (dirty_page) {
- if (vma->vm_file)
- file_update_time(vma->vm_file);
+ if (dirty_page) {
+ struct address_space *mapping = page->mapping;
- set_page_dirty_balance(dirty_page, page_mkwrite);
+ if (set_page_dirty(dirty_page))
+ page_mkwrite = 1;
+ unlock_page(dirty_page);
put_page(dirty_page);
+ if (page_mkwrite && mapping) {
+ /*
+ * Some device drivers do not set page.mapping but still
+ * dirty their pages
+ */
+ balance_dirty_pages_ratelimited(mapping);
+ }
+
+ /* file_update_time outside page_lock */
+ if (vma->vm_file)
+ file_update_time(vma->vm_file);
+ } else {
+ unlock_page(vmf.page);
+ if (anon)
+ page_cache_release(vmf.page);
}
return ret;
+
+unwritable_page:
+ page_cache_release(page);
+ return ret;
}
static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma,
diff --git a/mm/mlock.c b/mm/mlock.c
index cbe9e0581b75..ac130433c7d3 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -629,52 +629,43 @@ void user_shm_unlock(size_t size, struct user_struct *user)
free_uid(user);
}
-void *alloc_locked_buffer(size_t size)
+int account_locked_memory(struct mm_struct *mm, struct rlimit *rlim,
+ size_t size)
{
- unsigned long rlim, vm, pgsz;
- void *buffer = NULL;
+ unsigned long lim, vm, pgsz;
+ int error = -ENOMEM;
pgsz = PAGE_ALIGN(size) >> PAGE_SHIFT;
- down_write(&current->mm->mmap_sem);
-
- rlim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT;
- vm = current->mm->total_vm + pgsz;
- if (rlim < vm)
- goto out;
+ down_write(&mm->mmap_sem);
- rlim = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT;
- vm = current->mm->locked_vm + pgsz;
- if (rlim < vm)
+ lim = rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT;
+ vm = mm->total_vm + pgsz;
+ if (lim < vm)
goto out;
- buffer = kzalloc(size, GFP_KERNEL);
- if (!buffer)
+ lim = rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT;
+ vm = mm->locked_vm + pgsz;
+ if (lim < vm)
goto out;
- current->mm->total_vm += pgsz;
- current->mm->locked_vm += pgsz;
+ mm->total_vm += pgsz;
+ mm->locked_vm += pgsz;
+ error = 0;
out:
- up_write(&current->mm->mmap_sem);
- return buffer;
+ up_write(&mm->mmap_sem);
+ return error;
}
-void release_locked_buffer(void *buffer, size_t size)
+void refund_locked_memory(struct mm_struct *mm, size_t size)
{
unsigned long pgsz = PAGE_ALIGN(size) >> PAGE_SHIFT;
- down_write(&current->mm->mmap_sem);
-
- current->mm->total_vm -= pgsz;
- current->mm->locked_vm -= pgsz;
-
- up_write(&current->mm->mmap_sem);
-}
+ down_write(&mm->mmap_sem);
-void free_locked_buffer(void *buffer, size_t size)
-{
- release_locked_buffer(buffer, size);
+ mm->total_vm -= pgsz;
+ mm->locked_vm -= pgsz;
- kfree(buffer);
+ up_write(&mm->mmap_sem);
}
diff --git a/mm/mmap.c b/mm/mmap.c
index 4a3841186c11..6b7b1a95944b 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -85,7 +85,7 @@ EXPORT_SYMBOL(vm_get_page_prot);
int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */
int sysctl_overcommit_ratio = 50; /* default is 50% */
int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT;
-atomic_long_t vm_committed_space = ATOMIC_LONG_INIT(0);
+struct percpu_counter vm_committed_as;
/*
* Check that a process has enough memory to allocate a new virtual
@@ -179,11 +179,7 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
if (mm)
allowed -= mm->total_vm / 32;
- /*
- * cast `allowed' as a signed long because vm_committed_space
- * sometimes has a negative value
- */
- if (atomic_long_read(&vm_committed_space) < (long)allowed)
+ if (percpu_counter_read_positive(&vm_committed_as) < allowed)
return 0;
error:
vm_unacct_memory(pages);
@@ -1575,7 +1571,7 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns
* Overcommit.. This must be the final test, as it will
* update security statistics.
*/
- if (security_vm_enough_memory(grow))
+ if (security_vm_enough_memory_mm(mm, grow))
return -ENOMEM;
/* Ok, everything looks good - let it rip */
@@ -2481,4 +2477,8 @@ void mm_drop_all_locks(struct mm_struct *mm)
*/
void __init mmap_init(void)
{
+ int ret;
+
+ ret = percpu_counter_init(&vm_committed_as, 0);
+ VM_BUG_ON(ret);
}
diff --git a/mm/nommu.c b/mm/nommu.c
index 72eda4aee2cb..b571ef707428 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -62,11 +62,11 @@ void *high_memory;
struct page *mem_map;
unsigned long max_mapnr;
unsigned long num_physpages;
-atomic_long_t vm_committed_space = ATOMIC_LONG_INIT(0);
+struct percpu_counter vm_committed_as;
int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */
int sysctl_overcommit_ratio = 50; /* default is 50% */
int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT;
-int sysctl_nr_trim_pages = 1; /* page trimming behaviour */
+int sysctl_nr_trim_pages = CONFIG_NOMMU_INITIAL_TRIM_EXCESS;
int heap_stack_gap = 0;
atomic_long_t mmap_pages_allocated;
@@ -463,6 +463,10 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
*/
void __init mmap_init(void)
{
+ int ret;
+
+ ret = percpu_counter_init(&vm_committed_as, 0);
+ VM_BUG_ON(ret);
vm_region_jar = KMEM_CACHE(vm_region, SLAB_PANIC);
}
@@ -511,8 +515,6 @@ static void add_nommu_region(struct vm_region *region)
validate_nommu_regions();
- BUG_ON(region->vm_start & ~PAGE_MASK);
-
parent = NULL;
p = &nommu_region_tree.rb_node;
while (*p) {
@@ -1847,12 +1849,9 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
if (mm)
allowed -= mm->total_vm / 32;
- /*
- * cast `allowed' as a signed long because vm_committed_space
- * sometimes has a negative value
- */
- if (atomic_long_read(&vm_committed_space) < (long)allowed)
+ if (percpu_counter_read_positive(&vm_committed_as) < allowed)
return 0;
+
error:
vm_unacct_memory(pages);
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 2f3166e308d9..92bcf1db16b2 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -514,34 +514,32 @@ void clear_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_mask)
*/
static void __out_of_memory(gfp_t gfp_mask, int order)
{
- if (sysctl_oom_kill_allocating_task) {
- oom_kill_process(current, gfp_mask, order, 0, NULL,
- "Out of memory (oom_kill_allocating_task)");
-
- } else {
- unsigned long points;
- struct task_struct *p;
-
-retry:
- /*
- * Rambo mode: Shoot down a process and hope it solves whatever
- * issues we may have.
- */
- p = select_bad_process(&points, NULL);
+ struct task_struct *p;
+ unsigned long points;
- if (PTR_ERR(p) == -1UL)
+ if (sysctl_oom_kill_allocating_task)
+ if (!oom_kill_process(current, gfp_mask, order, 0, NULL,
+ "Out of memory (oom_kill_allocating_task)"))
return;
+retry:
+ /*
+ * Rambo mode: Shoot down a process and hope it solves whatever
+ * issues we may have.
+ */
+ p = select_bad_process(&points, NULL);
- /* Found nothing?!?! Either we hang forever, or we panic. */
- if (!p) {
- read_unlock(&tasklist_lock);
- panic("Out of memory and no killable processes...\n");
- }
+ if (PTR_ERR(p) == -1UL)
+ return;
- if (oom_kill_process(p, gfp_mask, order, points, NULL,
- "Out of memory"))
- goto retry;
+ /* Found nothing?!?! Either we hang forever, or we panic. */
+ if (!p) {
+ read_unlock(&tasklist_lock);
+ panic("Out of memory and no killable processes...\n");
}
+
+ if (oom_kill_process(p, gfp_mask, order, points, NULL,
+ "Out of memory"))
+ goto retry;
}
/*
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index e2f26991fff1..2a8f25921b56 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -46,6 +46,7 @@
#include <linux/page-isolation.h>
#include <linux/page_cgroup.h>
#include <linux/debugobjects.h>
+#include <linux/kmemleak.h>
#include <asm/tlbflush.h>
#include <asm/div64.h>
@@ -2681,6 +2682,7 @@ static void __meminit zone_init_free_lists(struct zone *zone)
static int zone_batchsize(struct zone *zone)
{
+#ifdef CONFIG_MMU
int batch;
/*
@@ -2706,9 +2708,26 @@ static int zone_batchsize(struct zone *zone)
* of pages of one half of the possible page colors
* and the other with pages of the other colors.
*/
- batch = (1 << (fls(batch + batch/2)-1)) - 1;
+ batch = rounddown_pow_of_two(batch + batch/2) - 1;
return batch;
+
+#else
+ /* The deferral and batching of frees should be suppressed under NOMMU
+ * conditions.
+ *
+ * The problem is that NOMMU needs to be able to allocate large chunks
+ * of contiguous memory as there's no hardware page translation to
+ * assemble apparent contiguous memory from discontiguous pages.
+ *
+ * Queueing large contiguous runs of pages for batching, however,
+ * causes the pages to actually be freed in smaller chunks. As there
+ * can be a significant delay between the individual batches being
+ * recycled, this leads to the once large chunks of space being
+ * fragmented and becoming unavailable for high-order allocations.
+ */
+ return 0;
+#endif
}
static void setup_pageset(struct per_cpu_pageset *p, unsigned long batch)
@@ -4597,6 +4616,16 @@ void *__init alloc_large_system_hash(const char *tablename,
if (_hash_mask)
*_hash_mask = (1 << log2qty) - 1;
+ /*
+ * If hashdist is set, the table allocation is done with __vmalloc()
+ * which invokes the kmemleak_alloc() callback. This function may also
+ * be called before the slab and kmemleak are initialised when
+ * kmemleak simply buffers the request to be executed later
+ * (GFP_ATOMIC flag ignored in this case).
+ */
+ if (!hashdist)
+ kmemleak_alloc(table, size, 1, GFP_ATOMIC);
+
return table;
}
diff --git a/mm/percpu.c b/mm/percpu.c
index 1aa5d8fbca12..c0b2c1a76e81 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -23,7 +23,7 @@
* Allocation is done in offset-size areas of single unit space. Ie,
* an area of 512 bytes at 6k in c1 occupies 512 bytes at 6k of c1:u0,
* c1:u1, c1:u2 and c1:u3. Percpu access can be done by configuring
- * percpu base registers UNIT_SIZE apart.
+ * percpu base registers pcpu_unit_size apart.
*
* There are usually many small percpu allocations many of them as
* small as 4 bytes. The allocator organizes chunks into lists
@@ -38,8 +38,8 @@
* region and negative allocated. Allocation inside a chunk is done
* by scanning this map sequentially and serving the first matching
* entry. This is mostly copied from the percpu_modalloc() allocator.
- * Chunks are also linked into a rb tree to ease address to chunk
- * mapping during free.
+ * Chunks can be determined from the address using the index field
+ * in the page struct. The index field contains a pointer to the chunk.
*
* To use this allocator, arch code should do the followings.
*
@@ -61,7 +61,6 @@
#include <linux/mutex.h>
#include <linux/percpu.h>
#include <linux/pfn.h>
-#include <linux/rbtree.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/vmalloc.h>
@@ -88,7 +87,6 @@
struct pcpu_chunk {
struct list_head list; /* linked to pcpu_slot lists */
- struct rb_node rb_node; /* key is chunk->vm->addr */
int free_size; /* free bytes in the chunk */
int contig_hint; /* max contiguous size hint */
struct vm_struct *vm; /* mapped vmalloc region */
@@ -110,9 +108,21 @@ static size_t pcpu_chunk_struct_size __read_mostly;
void *pcpu_base_addr __read_mostly;
EXPORT_SYMBOL_GPL(pcpu_base_addr);
-/* optional reserved chunk, only accessible for reserved allocations */
+/*
+ * The first chunk which always exists. Note that unlike other
+ * chunks, this one can be allocated and mapped in several different
+ * ways and thus often doesn't live in the vmalloc area.
+ */
+static struct pcpu_chunk *pcpu_first_chunk;
+
+/*
+ * Optional reserved chunk. This chunk reserves part of the first
+ * chunk and serves it for reserved allocations. The amount of
+ * reserved offset is in pcpu_reserved_chunk_limit. When reserved
+ * area doesn't exist, the following variables contain NULL and 0
+ * respectively.
+ */
static struct pcpu_chunk *pcpu_reserved_chunk;
-/* offset limit of the reserved chunk */
static int pcpu_reserved_chunk_limit;
/*
@@ -121,7 +131,7 @@ static int pcpu_reserved_chunk_limit;
* There are two locks - pcpu_alloc_mutex and pcpu_lock. The former
* protects allocation/reclaim paths, chunks and chunk->page arrays.
* The latter is a spinlock and protects the index data structures -
- * chunk slots, rbtree, chunks and area maps in chunks.
+ * chunk slots, chunks and area maps in chunks.
*
* During allocation, pcpu_alloc_mutex is kept locked all the time and
* pcpu_lock is grabbed and released as necessary. All actual memory
@@ -140,7 +150,6 @@ static DEFINE_MUTEX(pcpu_alloc_mutex); /* protects whole alloc and reclaim */
static DEFINE_SPINLOCK(pcpu_lock); /* protects index data structures */
static struct list_head *pcpu_slot __read_mostly; /* chunk list slots */
-static struct rb_root pcpu_addr_root = RB_ROOT; /* chunks by address */
/* reclaim work to release fully free chunks, scheduled from free path */
static void pcpu_reclaim(struct work_struct *work);
@@ -191,6 +200,18 @@ static bool pcpu_chunk_page_occupied(struct pcpu_chunk *chunk,
return *pcpu_chunk_pagep(chunk, 0, page_idx) != NULL;
}
+/* set the pointer to a chunk in a page struct */
+static void pcpu_set_page_chunk(struct page *page, struct pcpu_chunk *pcpu)
+{
+ page->index = (unsigned long)pcpu;
+}
+
+/* obtain pointer to a chunk from a page struct */
+static struct pcpu_chunk *pcpu_get_page_chunk(struct page *page)
+{
+ return (struct pcpu_chunk *)page->index;
+}
+
/**
* pcpu_mem_alloc - allocate memory
* @size: bytes to allocate
@@ -257,93 +278,26 @@ static void pcpu_chunk_relocate(struct pcpu_chunk *chunk, int oslot)
}
}
-static struct rb_node **pcpu_chunk_rb_search(void *addr,
- struct rb_node **parentp)
-{
- struct rb_node **p = &pcpu_addr_root.rb_node;
- struct rb_node *parent = NULL;
- struct pcpu_chunk *chunk;
-
- while (*p) {
- parent = *p;
- chunk = rb_entry(parent, struct pcpu_chunk, rb_node);
-
- if (addr < chunk->vm->addr)
- p = &(*p)->rb_left;
- else if (addr > chunk->vm->addr)
- p = &(*p)->rb_right;
- else
- break;
- }
-
- if (parentp)
- *parentp = parent;
- return p;
-}
-
/**
- * pcpu_chunk_addr_search - search for chunk containing specified address
- * @addr: address to search for
- *
- * Look for chunk which might contain @addr. More specifically, it
- * searchs for the chunk with the highest start address which isn't
- * beyond @addr.
- *
- * CONTEXT:
- * pcpu_lock.
+ * pcpu_chunk_addr_search - determine chunk containing specified address
+ * @addr: address for which the chunk needs to be determined.
*
* RETURNS:
* The address of the found chunk.
*/
static struct pcpu_chunk *pcpu_chunk_addr_search(void *addr)
{
- struct rb_node *n, *parent;
- struct pcpu_chunk *chunk;
+ void *first_start = pcpu_first_chunk->vm->addr;
- /* is it in the reserved chunk? */
- if (pcpu_reserved_chunk) {
- void *start = pcpu_reserved_chunk->vm->addr;
-
- if (addr >= start && addr < start + pcpu_reserved_chunk_limit)
+ /* is it in the first chunk? */
+ if (addr >= first_start && addr < first_start + pcpu_chunk_size) {
+ /* is it in the reserved area? */
+ if (addr < first_start + pcpu_reserved_chunk_limit)
return pcpu_reserved_chunk;
+ return pcpu_first_chunk;
}
- /* nah... search the regular ones */
- n = *pcpu_chunk_rb_search(addr, &parent);
- if (!n) {
- /* no exactly matching chunk, the parent is the closest */
- n = parent;
- BUG_ON(!n);
- }
- chunk = rb_entry(n, struct pcpu_chunk, rb_node);
-
- if (addr < chunk->vm->addr) {
- /* the parent was the next one, look for the previous one */
- n = rb_prev(n);
- BUG_ON(!n);
- chunk = rb_entry(n, struct pcpu_chunk, rb_node);
- }
-
- return chunk;
-}
-
-/**
- * pcpu_chunk_addr_insert - insert chunk into address rb tree
- * @new: chunk to insert
- *
- * Insert @new into address rb tree.
- *
- * CONTEXT:
- * pcpu_lock.
- */
-static void pcpu_chunk_addr_insert(struct pcpu_chunk *new)
-{
- struct rb_node **p, *parent;
-
- p = pcpu_chunk_rb_search(new->vm->addr, &parent);
- BUG_ON(*p);
- rb_link_node(&new->rb_node, parent, p);
- rb_insert_color(&new->rb_node, &pcpu_addr_root);
+ return pcpu_get_page_chunk(vmalloc_to_page(addr));
}
/**
@@ -755,6 +709,7 @@ static int pcpu_populate_chunk(struct pcpu_chunk *chunk, int off, int size)
alloc_mask, 0);
if (!*pagep)
goto err;
+ pcpu_set_page_chunk(*pagep, chunk);
}
}
@@ -879,7 +834,6 @@ restart:
spin_lock_irq(&pcpu_lock);
pcpu_chunk_relocate(chunk, -1);
- pcpu_chunk_addr_insert(chunk);
goto restart;
area_found:
@@ -968,7 +922,6 @@ static void pcpu_reclaim(struct work_struct *work)
if (chunk == list_first_entry(head, struct pcpu_chunk, list))
continue;
- rb_erase(&chunk->rb_node, &pcpu_addr_root);
list_move(&chunk->list, &todo);
}
@@ -1147,7 +1100,8 @@ size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn,
if (reserved_size) {
schunk->free_size = reserved_size;
- pcpu_reserved_chunk = schunk; /* not for dynamic alloc */
+ pcpu_reserved_chunk = schunk;
+ pcpu_reserved_chunk_limit = static_size + reserved_size;
} else {
schunk->free_size = dyn_size;
dyn_size = 0; /* dynamic area covered */
@@ -1158,8 +1112,6 @@ size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn,
if (schunk->free_size)
schunk->map[schunk->map_used++] = schunk->free_size;
- pcpu_reserved_chunk_limit = static_size + schunk->free_size;
-
/* init dynamic chunk if necessary */
if (dyn_size) {
dchunk = alloc_bootmem(sizeof(struct pcpu_chunk));
@@ -1226,13 +1178,8 @@ size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn,
}
/* link the first chunk in */
- if (!dchunk) {
- pcpu_chunk_relocate(schunk, -1);
- pcpu_chunk_addr_insert(schunk);
- } else {
- pcpu_chunk_relocate(dchunk, -1);
- pcpu_chunk_addr_insert(dchunk);
- }
+ pcpu_first_chunk = dchunk ?: schunk;
+ pcpu_chunk_relocate(pcpu_first_chunk, -1);
/* we're done */
pcpu_base_addr = (void *)pcpu_chunk_addr(schunk, 0, 0);
diff --git a/mm/shmem.c b/mm/shmem.c
index d94d2e9146bc..b25f95ce3db7 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/vfs.h>
#include <linux/mount.h>
+#include <linux/pagemap.h>
#include <linux/file.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -43,7 +44,6 @@ static struct vfsmount *shm_mnt;
#include <linux/exportfs.h>
#include <linux/generic_acl.h>
#include <linux/mman.h>
-#include <linux/pagemap.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/backing-dev.h>
@@ -65,13 +65,28 @@ static struct vfsmount *shm_mnt;
#include <asm/div64.h>
#include <asm/pgtable.h>
+/*
+ * The maximum size of a shmem/tmpfs file is limited by the maximum size of
+ * its triple-indirect swap vector - see illustration at shmem_swp_entry().
+ *
+ * With 4kB page size, maximum file size is just over 2TB on a 32-bit kernel,
+ * but one eighth of that on a 64-bit kernel. With 8kB page size, maximum
+ * file size is just over 4TB on a 64-bit kernel, but 16TB on a 32-bit kernel,
+ * MAX_LFS_FILESIZE being then more restrictive than swap vector layout.
+ *
+ * We use / and * instead of shifts in the definitions below, so that the swap
+ * vector can be tested with small even values (e.g. 20) for ENTRIES_PER_PAGE.
+ */
#define ENTRIES_PER_PAGE (PAGE_CACHE_SIZE/sizeof(unsigned long))
-#define ENTRIES_PER_PAGEPAGE (ENTRIES_PER_PAGE*ENTRIES_PER_PAGE)
-#define BLOCKS_PER_PAGE (PAGE_CACHE_SIZE/512)
+#define ENTRIES_PER_PAGEPAGE ((unsigned long long)ENTRIES_PER_PAGE*ENTRIES_PER_PAGE)
-#define SHMEM_MAX_INDEX (SHMEM_NR_DIRECT + (ENTRIES_PER_PAGEPAGE/2) * (ENTRIES_PER_PAGE+1))
-#define SHMEM_MAX_BYTES ((unsigned long long)SHMEM_MAX_INDEX << PAGE_CACHE_SHIFT)
+#define SHMSWP_MAX_INDEX (SHMEM_NR_DIRECT + (ENTRIES_PER_PAGEPAGE/2) * (ENTRIES_PER_PAGE+1))
+#define SHMSWP_MAX_BYTES (SHMSWP_MAX_INDEX << PAGE_CACHE_SHIFT)
+#define SHMEM_MAX_BYTES min_t(unsigned long long, SHMSWP_MAX_BYTES, MAX_LFS_FILESIZE)
+#define SHMEM_MAX_INDEX ((unsigned long)((SHMEM_MAX_BYTES+1) >> PAGE_CACHE_SHIFT))
+
+#define BLOCKS_PER_PAGE (PAGE_CACHE_SIZE/512)
#define VM_ACCT(size) (PAGE_CACHE_ALIGN(size) >> PAGE_SHIFT)
/* info->flags needs VM_flags to handle pagein/truncate races efficiently */
@@ -1325,8 +1340,12 @@ repeat:
shmem_swp_unmap(entry);
spin_unlock(&info->lock);
if (error == -ENOMEM) {
- /* allow reclaim from this memory cgroup */
- error = mem_cgroup_shrink_usage(swappage,
+ /*
+ * reclaim from proper memory cgroup and
+ * call memcg's OOM if needed.
+ */
+ error = mem_cgroup_shmem_charge_fallback(
+ swappage,
current->mm,
gfp);
if (error) {
@@ -2581,7 +2600,7 @@ int shmem_unuse(swp_entry_t entry, struct page *page)
#define shmem_get_inode(sb, mode, dev, flags) ramfs_get_inode(sb, mode, dev)
#define shmem_acct_size(flags, size) 0
#define shmem_unacct_size(flags, size) do {} while (0)
-#define SHMEM_MAX_BYTES LLONG_MAX
+#define SHMEM_MAX_BYTES MAX_LFS_FILESIZE
#endif /* CONFIG_SHMEM */
diff --git a/mm/slab.c b/mm/slab.c
index 9a90b00d2f91..859067f8e4fd 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -102,11 +102,12 @@
#include <linux/cpu.h>
#include <linux/sysctl.h>
#include <linux/module.h>
-#include <trace/kmemtrace.h>
+#include <linux/kmemtrace.h>
#include <linux/rcupdate.h>
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/nodemask.h>
+#include <linux/kmemleak.h>
#include <linux/mempolicy.h>
#include <linux/mutex.h>
#include <linux/fault-inject.h>
@@ -178,13 +179,13 @@
SLAB_STORE_USER | \
SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \
SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD | \
- SLAB_DEBUG_OBJECTS)
+ SLAB_DEBUG_OBJECTS | SLAB_NOLEAKTRACE)
#else
# define CREATE_MASK (SLAB_HWCACHE_ALIGN | \
SLAB_CACHE_DMA | \
SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \
SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD | \
- SLAB_DEBUG_OBJECTS)
+ SLAB_DEBUG_OBJECTS | SLAB_NOLEAKTRACE)
#endif
/*
@@ -964,6 +965,14 @@ static struct array_cache *alloc_arraycache(int node, int entries,
struct array_cache *nc = NULL;
nc = kmalloc_node(memsize, GFP_KERNEL, node);
+ /*
+ * The array_cache structures contain pointers to free object.
+ * However, when such objects are allocated or transfered to another
+ * cache the pointers are not cleared and they could be counted as
+ * valid references during a kmemleak scan. Therefore, kmemleak must
+ * not scan such objects.
+ */
+ kmemleak_no_scan(nc);
if (nc) {
nc->avail = 0;
nc->limit = entries;
@@ -2621,6 +2630,14 @@ static struct slab *alloc_slabmgmt(struct kmem_cache *cachep, void *objp,
/* Slab management obj is off-slab. */
slabp = kmem_cache_alloc_node(cachep->slabp_cache,
local_flags, nodeid);
+ /*
+ * If the first object in the slab is leaked (it's allocated
+ * but no one has a reference to it), we want to make sure
+ * kmemleak does not treat the ->s_mem pointer as a reference
+ * to the object. Otherwise we will not report the leak.
+ */
+ kmemleak_scan_area(slabp, offsetof(struct slab, list),
+ sizeof(struct list_head), local_flags);
if (!slabp)
return NULL;
} else {
@@ -3141,6 +3158,12 @@ static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags)
STATS_INC_ALLOCMISS(cachep);
objp = cache_alloc_refill(cachep, flags);
}
+ /*
+ * To avoid a false negative, if an object that is in one of the
+ * per-CPU caches is leaked, we need to make sure kmemleak doesn't
+ * treat the array pointers as a reference to the object.
+ */
+ kmemleak_erase(&ac->entry[ac->avail]);
return objp;
}
@@ -3360,6 +3383,8 @@ __cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid,
out:
local_irq_restore(save_flags);
ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, caller);
+ kmemleak_alloc_recursive(ptr, obj_size(cachep), 1, cachep->flags,
+ flags);
if (unlikely((flags & __GFP_ZERO) && ptr))
memset(ptr, 0, obj_size(cachep));
@@ -3415,6 +3440,8 @@ __cache_alloc(struct kmem_cache *cachep, gfp_t flags, void *caller)
objp = __do_cache_alloc(cachep, flags);
local_irq_restore(save_flags);
objp = cache_alloc_debugcheck_after(cachep, flags, objp, caller);
+ kmemleak_alloc_recursive(objp, obj_size(cachep), 1, cachep->flags,
+ flags);
prefetchw(objp);
if (unlikely((flags & __GFP_ZERO) && objp))
@@ -3530,6 +3557,7 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp)
struct array_cache *ac = cpu_cache_get(cachep);
check_irq_off();
+ kmemleak_free_recursive(objp, cachep->flags);
objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));
/*
diff --git a/mm/slob.c b/mm/slob.c
index a2d4ab32198d..90a934c5bae3 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -60,12 +60,14 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/mm.h>
+#include <linux/swap.h> /* struct reclaim_state */
+#include <linux/kmemleak.h>
#include <linux/cache.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/rcupdate.h>
#include <linux/list.h>
-#include <trace/kmemtrace.h>
+#include <linux/kmemtrace.h>
#include <asm/atomic.h>
/*
@@ -131,17 +133,17 @@ static LIST_HEAD(free_slob_large);
*/
static inline int is_slob_page(struct slob_page *sp)
{
- return PageSlobPage((struct page *)sp);
+ return PageSlab((struct page *)sp);
}
static inline void set_slob_page(struct slob_page *sp)
{
- __SetPageSlobPage((struct page *)sp);
+ __SetPageSlab((struct page *)sp);
}
static inline void clear_slob_page(struct slob_page *sp)
{
- __ClearPageSlobPage((struct page *)sp);
+ __ClearPageSlab((struct page *)sp);
}
static inline struct slob_page *slob_page(const void *addr)
@@ -255,6 +257,8 @@ static void *slob_new_pages(gfp_t gfp, int order, int node)
static void slob_free_pages(void *b, int order)
{
+ if (current->reclaim_state)
+ current->reclaim_state->reclaimed_slab += 1 << order;
free_pages((unsigned long)b, order);
}
@@ -407,7 +411,7 @@ static void slob_free(void *block, int size)
spin_unlock_irqrestore(&slob_lock, flags);
clear_slob_page(sp);
free_slob_page(sp);
- free_page((unsigned long)b);
+ slob_free_pages(b, 0);
return;
}
@@ -506,6 +510,7 @@ void *__kmalloc_node(size_t size, gfp_t gfp, int node)
size, PAGE_SIZE << order, gfp, node);
}
+ kmemleak_alloc(ret, size, 1, gfp);
return ret;
}
EXPORT_SYMBOL(__kmalloc_node);
@@ -518,6 +523,7 @@ void kfree(const void *block)
if (unlikely(ZERO_OR_NULL_PTR(block)))
return;
+ kmemleak_free(block);
sp = slob_page(block);
if (is_slob_page(sp)) {
@@ -581,12 +587,14 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size,
} else if (flags & SLAB_PANIC)
panic("Cannot create slab cache %s\n", name);
+ kmemleak_alloc(c, sizeof(struct kmem_cache), 1, GFP_KERNEL);
return c;
}
EXPORT_SYMBOL(kmem_cache_create);
void kmem_cache_destroy(struct kmem_cache *c)
{
+ kmemleak_free(c);
slob_free(c, sizeof(struct kmem_cache));
}
EXPORT_SYMBOL(kmem_cache_destroy);
@@ -610,6 +618,7 @@ void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
if (c->ctor)
c->ctor(b);
+ kmemleak_alloc_recursive(b, c->size, 1, c->flags, flags);
return b;
}
EXPORT_SYMBOL(kmem_cache_alloc_node);
@@ -632,6 +641,7 @@ static void kmem_rcu_free(struct rcu_head *head)
void kmem_cache_free(struct kmem_cache *c, void *b)
{
+ kmemleak_free_recursive(b, c->flags);
if (unlikely(c->flags & SLAB_DESTROY_BY_RCU)) {
struct slob_rcu *slob_rcu;
slob_rcu = b + (c->size - sizeof(struct slob_rcu));
diff --git a/mm/slqb.c b/mm/slqb.c
new file mode 100644
index 000000000000..5d0642fb6f01
--- /dev/null
+++ b/mm/slqb.c
@@ -0,0 +1,3746 @@
+/*
+ * SLQB: A slab allocator that focuses on per-CPU scaling, and good performance
+ * with order-0 allocations. Fastpaths emphasis is placed on local allocaiton
+ * and freeing, but with a secondary goal of good remote freeing (freeing on
+ * another CPU from that which allocated).
+ *
+ * Using ideas and code from mm/slab.c, mm/slob.c, and mm/slub.c.
+ */
+
+#include <linux/mm.h>
+#include <linux/swap.h> /* struct reclaim_state */
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/seq_file.h>
+#include <linux/cpu.h>
+#include <linux/cpuset.h>
+#include <linux/mempolicy.h>
+#include <linux/ctype.h>
+#include <linux/kallsyms.h>
+#include <linux/memory.h>
+
+/*
+ * TODO
+ * - fix up releasing of offlined data structures. Not a big deal because
+ * they don't get cumulatively leaked with successive online/offline cycles
+ * - allow OOM conditions to flush back per-CPU pages to common lists to be
+ * reused by other CPUs.
+ * - investiage performance with memoryless nodes. Perhaps CPUs can be given
+ * a default closest home node via which it can use fastpath functions.
+ * Perhaps it is not a big problem.
+ */
+
+/*
+ * slqb_page overloads struct page, and is used to manage some slob allocation
+ * aspects, however to avoid the horrible mess in include/linux/mm_types.h,
+ * we'll just define our own struct slqb_page type variant here.
+ */
+struct slqb_page {
+ union {
+ struct {
+ unsigned long flags; /* mandatory */
+ atomic_t _count; /* mandatory */
+ unsigned int inuse; /* Nr of objects */
+ struct kmem_cache_list *list; /* Pointer to list */
+ void **freelist; /* LIFO freelist */
+ union {
+ struct list_head lru; /* misc. list */
+ struct rcu_head rcu_head; /* for rcu freeing */
+ };
+ };
+ struct page page;
+ };
+};
+static inline void struct_slqb_page_wrong_size(void)
+{ BUILD_BUG_ON(sizeof(struct slqb_page) != sizeof(struct page)); }
+
+#define PG_SLQB_BIT (1 << PG_slab)
+
+/*
+ * slqb_min_order: minimum allocation order for slabs
+ */
+static int slqb_min_order;
+
+/*
+ * slqb_min_objects: minimum number of objects per slab. Increasing this
+ * will increase the allocation order for slabs with larger objects
+ */
+static int slqb_min_objects = 1;
+
+#ifdef CONFIG_NUMA
+static inline int slab_numa(struct kmem_cache *s)
+{
+ return s->flags & SLAB_NUMA;
+}
+#else
+static inline int slab_numa(struct kmem_cache *s)
+{
+ return 0;
+}
+#endif
+
+static inline int slab_hiwater(struct kmem_cache *s)
+{
+ return s->hiwater;
+}
+
+static inline int slab_freebatch(struct kmem_cache *s)
+{
+ return s->freebatch;
+}
+
+/*
+ * Lock order:
+ * kmem_cache_node->list_lock
+ * kmem_cache_remote_free->lock
+ *
+ * Data structures:
+ * SLQB is primarily per-cpu. For each kmem_cache, each CPU has:
+ *
+ * - A LIFO list of node-local objects. Allocation and freeing of node local
+ * objects goes first to this list.
+ *
+ * - 2 Lists of slab pages, free and partial pages. If an allocation misses
+ * the object list, it tries from the partial list, then the free list.
+ * After freeing an object to the object list, if it is over a watermark,
+ * some objects are freed back to pages. If an allocation misses these lists,
+ * a new slab page is allocated from the page allocator. If the free list
+ * reaches a watermark, some of its pages are returned to the page allocator.
+ *
+ * - A remote free queue, where objects freed that did not come from the local
+ * node are queued to. When this reaches a watermark, the objects are
+ * flushed.
+ *
+ * - A remotely freed queue, where objects allocated from this CPU are flushed
+ * to from other CPUs' remote free queues. kmem_cache_remote_free->lock is
+ * used to protect access to this queue.
+ *
+ * When the remotely freed queue reaches a watermark, a flag is set to tell
+ * the owner CPU to check it. The owner CPU will then check the queue on the
+ * next allocation that misses the object list. It will move all objects from
+ * this list onto the object list and then allocate one.
+ *
+ * This system of remote queueing is intended to reduce lock and remote
+ * cacheline acquisitions, and give a cooling off period for remotely freed
+ * objects before they are re-allocated.
+ *
+ * node specific allocations from somewhere other than the local node are
+ * handled by a per-node list which is the same as the above per-CPU data
+ * structures except for the following differences:
+ *
+ * - kmem_cache_node->list_lock is used to protect access for multiple CPUs to
+ * allocate from a given node.
+ *
+ * - There is no remote free queue. Nodes don't free objects, CPUs do.
+ */
+
+static inline void slqb_stat_inc(struct kmem_cache_list *list,
+ enum stat_item si)
+{
+#ifdef CONFIG_SLQB_STATS
+ list->stats[si]++;
+#endif
+}
+
+static inline void slqb_stat_add(struct kmem_cache_list *list,
+ enum stat_item si, unsigned long nr)
+{
+#ifdef CONFIG_SLQB_STATS
+ list->stats[si] += nr;
+#endif
+}
+
+static inline int slqb_page_to_nid(struct slqb_page *page)
+{
+ return page_to_nid(&page->page);
+}
+
+static inline void *slqb_page_address(struct slqb_page *page)
+{
+ return page_address(&page->page);
+}
+
+static inline struct zone *slqb_page_zone(struct slqb_page *page)
+{
+ return page_zone(&page->page);
+}
+
+static inline int virt_to_nid(const void *addr)
+{
+ return page_to_nid(virt_to_page(addr));
+}
+
+static inline struct slqb_page *virt_to_head_slqb_page(const void *addr)
+{
+ struct page *p;
+
+ p = virt_to_head_page(addr);
+ return (struct slqb_page *)p;
+}
+
+static inline void __free_slqb_pages(struct slqb_page *page, unsigned int order,
+ int pages)
+{
+ struct page *p = &page->page;
+
+ reset_page_mapcount(p);
+ p->mapping = NULL;
+ VM_BUG_ON(!(p->flags & PG_SLQB_BIT));
+ p->flags &= ~PG_SLQB_BIT;
+
+ if (current->reclaim_state)
+ current->reclaim_state->reclaimed_slab += pages;
+ __free_pages(p, order);
+}
+
+#ifdef CONFIG_SLQB_DEBUG
+static inline int slab_debug(struct kmem_cache *s)
+{
+ return s->flags &
+ (SLAB_DEBUG_FREE |
+ SLAB_RED_ZONE |
+ SLAB_POISON |
+ SLAB_STORE_USER |
+ SLAB_TRACE);
+}
+static inline int slab_poison(struct kmem_cache *s)
+{
+ return s->flags & SLAB_POISON;
+}
+#else
+static inline int slab_debug(struct kmem_cache *s)
+{
+ return 0;
+}
+static inline int slab_poison(struct kmem_cache *s)
+{
+ return 0;
+}
+#endif
+
+#define DEBUG_DEFAULT_FLAGS (SLAB_DEBUG_FREE | SLAB_RED_ZONE | \
+ SLAB_POISON | SLAB_STORE_USER)
+
+/* Internal SLQB flags */
+#define __OBJECT_POISON 0x80000000 /* Poison object */
+
+/* Not all arches define cache_line_size */
+#ifndef cache_line_size
+#define cache_line_size() L1_CACHE_BYTES
+#endif
+
+#ifdef CONFIG_SMP
+static struct notifier_block slab_notifier;
+#endif
+
+/*
+ * slqb_lock protects slab_caches list and serialises hotplug operations.
+ * hotplug operations take lock for write, other operations can hold off
+ * hotplug by taking it for read (or write).
+ */
+static DECLARE_RWSEM(slqb_lock);
+
+/*
+ * A list of all slab caches on the system
+ */
+static LIST_HEAD(slab_caches);
+
+/*
+ * Tracking user of a slab.
+ */
+struct track {
+ unsigned long addr; /* Called from address */
+ int cpu; /* Was running on cpu */
+ int pid; /* Pid context */
+ unsigned long when; /* When did the operation occur */
+};
+
+enum track_item { TRACK_ALLOC, TRACK_FREE };
+
+static struct kmem_cache kmem_cache_cache;
+
+#ifdef CONFIG_SLQB_SYSFS
+static int sysfs_slab_add(struct kmem_cache *s);
+static void sysfs_slab_remove(struct kmem_cache *s);
+#else
+static inline int sysfs_slab_add(struct kmem_cache *s)
+{
+ return 0;
+}
+static inline void sysfs_slab_remove(struct kmem_cache *s)
+{
+ kmem_cache_free(&kmem_cache_cache, s);
+}
+#endif
+
+/********************************************************************
+ * Core slab cache functions
+ *******************************************************************/
+
+static int __slab_is_available __read_mostly;
+int slab_is_available(void)
+{
+ return __slab_is_available;
+}
+
+static inline struct kmem_cache_cpu *get_cpu_slab(struct kmem_cache *s, int cpu)
+{
+#ifdef CONFIG_SMP
+ VM_BUG_ON(!s->cpu_slab[cpu]);
+ return s->cpu_slab[cpu];
+#else
+ return &s->cpu_slab;
+#endif
+}
+
+static inline int check_valid_pointer(struct kmem_cache *s,
+ struct slqb_page *page, const void *object)
+{
+ void *base;
+
+ base = slqb_page_address(page);
+ if (object < base || object >= base + s->objects * s->size ||
+ (object - base) % s->size) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static inline void *get_freepointer(struct kmem_cache *s, void *object)
+{
+ return *(void **)(object + s->offset);
+}
+
+static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp)
+{
+ *(void **)(object + s->offset) = fp;
+}
+
+/* Loop over all objects in a slab */
+#define for_each_object(__p, __s, __addr) \
+ for (__p = (__addr); __p < (__addr) + (__s)->objects * (__s)->size;\
+ __p += (__s)->size)
+
+/* Scan freelist */
+#define for_each_free_object(__p, __s, __free) \
+ for (__p = (__free); (__p) != NULL; __p = get_freepointer((__s),\
+ __p))
+
+#ifdef CONFIG_SLQB_DEBUG
+/*
+ * Debug settings:
+ */
+#ifdef CONFIG_SLQB_DEBUG_ON
+static int slqb_debug __read_mostly = DEBUG_DEFAULT_FLAGS;
+#else
+static int slqb_debug __read_mostly;
+#endif
+
+static char *slqb_debug_slabs;
+
+/*
+ * Object debugging
+ */
+static void print_section(char *text, u8 *addr, unsigned int length)
+{
+ int i, offset;
+ int newline = 1;
+ char ascii[17];
+
+ ascii[16] = 0;
+
+ for (i = 0; i < length; i++) {
+ if (newline) {
+ printk(KERN_ERR "%8s 0x%p: ", text, addr + i);
+ newline = 0;
+ }
+ printk(KERN_CONT " %02x", addr[i]);
+ offset = i % 16;
+ ascii[offset] = isgraph(addr[i]) ? addr[i] : '.';
+ if (offset == 15) {
+ printk(KERN_CONT " %s\n", ascii);
+ newline = 1;
+ }
+ }
+ if (!newline) {
+ i %= 16;
+ while (i < 16) {
+ printk(KERN_CONT " ");
+ ascii[i] = ' ';
+ i++;
+ }
+ printk(KERN_CONT " %s\n", ascii);
+ }
+}
+
+static struct track *get_track(struct kmem_cache *s, void *object,
+ enum track_item alloc)
+{
+ struct track *p;
+
+ if (s->offset)
+ p = object + s->offset + sizeof(void *);
+ else
+ p = object + s->inuse;
+
+ return p + alloc;
+}
+
+static void set_track(struct kmem_cache *s, void *object,
+ enum track_item alloc, unsigned long addr)
+{
+ struct track *p;
+
+ if (s->offset)
+ p = object + s->offset + sizeof(void *);
+ else
+ p = object + s->inuse;
+
+ p += alloc;
+ if (addr) {
+ p->addr = addr;
+ p->cpu = raw_smp_processor_id();
+ p->pid = current ? current->pid : -1;
+ p->when = jiffies;
+ } else
+ memset(p, 0, sizeof(struct track));
+}
+
+static void init_tracking(struct kmem_cache *s, void *object)
+{
+ if (!(s->flags & SLAB_STORE_USER))
+ return;
+
+ set_track(s, object, TRACK_FREE, 0UL);
+ set_track(s, object, TRACK_ALLOC, 0UL);
+}
+
+static void print_track(const char *s, struct track *t)
+{
+ if (!t->addr)
+ return;
+
+ printk(KERN_ERR "INFO: %s in ", s);
+ __print_symbol("%s", (unsigned long)t->addr);
+ printk(" age=%lu cpu=%u pid=%d\n", jiffies - t->when, t->cpu, t->pid);
+}
+
+static void print_tracking(struct kmem_cache *s, void *object)
+{
+ if (!(s->flags & SLAB_STORE_USER))
+ return;
+
+ print_track("Allocated", get_track(s, object, TRACK_ALLOC));
+ print_track("Freed", get_track(s, object, TRACK_FREE));
+}
+
+static void print_page_info(struct slqb_page *page)
+{
+ printk(KERN_ERR "INFO: Slab 0x%p used=%u fp=0x%p flags=0x%04lx\n",
+ page, page->inuse, page->freelist, page->flags);
+
+}
+
+#define MAX_ERR_STR 100
+static void slab_bug(struct kmem_cache *s, char *fmt, ...)
+{
+ va_list args;
+ char buf[MAX_ERR_STR];
+
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+ printk(KERN_ERR "========================================"
+ "=====================================\n");
+ printk(KERN_ERR "BUG %s: %s\n", s->name, buf);
+ printk(KERN_ERR "----------------------------------------"
+ "-------------------------------------\n\n");
+}
+
+static void slab_fix(struct kmem_cache *s, char *fmt, ...)
+{
+ va_list args;
+ char buf[100];
+
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+ printk(KERN_ERR "FIX %s: %s\n", s->name, buf);
+}
+
+static void print_trailer(struct kmem_cache *s, struct slqb_page *page, u8 *p)
+{
+ unsigned int off; /* Offset of last byte */
+ u8 *addr = slqb_page_address(page);
+
+ print_tracking(s, p);
+
+ print_page_info(page);
+
+ printk(KERN_ERR "INFO: Object 0x%p @offset=%tu fp=0x%p\n\n",
+ p, p - addr, get_freepointer(s, p));
+
+ if (p > addr + 16)
+ print_section("Bytes b4", p - 16, 16);
+
+ print_section("Object", p, min(s->objsize, 128));
+
+ if (s->flags & SLAB_RED_ZONE)
+ print_section("Redzone", p + s->objsize, s->inuse - s->objsize);
+
+ if (s->offset)
+ off = s->offset + sizeof(void *);
+ else
+ off = s->inuse;
+
+ if (s->flags & SLAB_STORE_USER)
+ off += 2 * sizeof(struct track);
+
+ if (off != s->size) {
+ /* Beginning of the filler is the free pointer */
+ print_section("Padding", p + off, s->size - off);
+ }
+
+ dump_stack();
+}
+
+static void object_err(struct kmem_cache *s, struct slqb_page *page,
+ u8 *object, char *reason)
+{
+ slab_bug(s, reason);
+ print_trailer(s, page, object);
+}
+
+static void slab_err(struct kmem_cache *s, struct slqb_page *page,
+ char *fmt, ...)
+{
+ slab_bug(s, fmt);
+ print_page_info(page);
+ dump_stack();
+}
+
+static void init_object(struct kmem_cache *s, void *object, int active)
+{
+ u8 *p = object;
+
+ if (s->flags & __OBJECT_POISON) {
+ memset(p, POISON_FREE, s->objsize - 1);
+ p[s->objsize - 1] = POISON_END;
+ }
+
+ if (s->flags & SLAB_RED_ZONE) {
+ memset(p + s->objsize,
+ active ? SLUB_RED_ACTIVE : SLUB_RED_INACTIVE,
+ s->inuse - s->objsize);
+ }
+}
+
+static u8 *check_bytes(u8 *start, unsigned int value, unsigned int bytes)
+{
+ while (bytes) {
+ if (*start != (u8)value)
+ return start;
+ start++;
+ bytes--;
+ }
+ return NULL;
+}
+
+static void restore_bytes(struct kmem_cache *s, char *message, u8 data,
+ void *from, void *to)
+{
+ slab_fix(s, "Restoring 0x%p-0x%p=0x%x\n", from, to - 1, data);
+ memset(from, data, to - from);
+}
+
+static int check_bytes_and_report(struct kmem_cache *s, struct slqb_page *page,
+ u8 *object, char *what,
+ u8 *start, unsigned int value, unsigned int bytes)
+{
+ u8 *fault;
+ u8 *end;
+
+ fault = check_bytes(start, value, bytes);
+ if (!fault)
+ return 1;
+
+ end = start + bytes;
+ while (end > fault && end[-1] == value)
+ end--;
+
+ slab_bug(s, "%s overwritten", what);
+ printk(KERN_ERR "INFO: 0x%p-0x%p. First byte 0x%x instead of 0x%x\n",
+ fault, end - 1, fault[0], value);
+ print_trailer(s, page, object);
+
+ restore_bytes(s, what, value, fault, end);
+ return 0;
+}
+
+/*
+ * Object layout:
+ *
+ * object address
+ * Bytes of the object to be managed.
+ * If the freepointer may overlay the object then the free
+ * pointer is the first word of the object.
+ *
+ * Poisoning uses 0x6b (POISON_FREE) and the last byte is
+ * 0xa5 (POISON_END)
+ *
+ * object + s->objsize
+ * Padding to reach word boundary. This is also used for Redzoning.
+ * Padding is extended by another word if Redzoning is enabled and
+ * objsize == inuse.
+ *
+ * We fill with 0xbb (RED_INACTIVE) for inactive objects and with
+ * 0xcc (RED_ACTIVE) for objects in use.
+ *
+ * object + s->inuse
+ * Meta data starts here.
+ *
+ * A. Free pointer (if we cannot overwrite object on free)
+ * B. Tracking data for SLAB_STORE_USER
+ * C. Padding to reach required alignment boundary or at mininum
+ * one word if debuggin is on to be able to detect writes
+ * before the word boundary.
+ *
+ * Padding is done using 0x5a (POISON_INUSE)
+ *
+ * object + s->size
+ * Nothing is used beyond s->size.
+ */
+
+static int check_pad_bytes(struct kmem_cache *s, struct slqb_page *page, u8 *p)
+{
+ unsigned long off = s->inuse; /* The end of info */
+
+ if (s->offset) {
+ /* Freepointer is placed after the object. */
+ off += sizeof(void *);
+ }
+
+ if (s->flags & SLAB_STORE_USER) {
+ /* We also have user information there */
+ off += 2 * sizeof(struct track);
+ }
+
+ if (s->size == off)
+ return 1;
+
+ return check_bytes_and_report(s, page, p, "Object padding",
+ p + off, POISON_INUSE, s->size - off);
+}
+
+static int slab_pad_check(struct kmem_cache *s, struct slqb_page *page)
+{
+ u8 *start;
+ u8 *fault;
+ u8 *end;
+ int length;
+ int remainder;
+
+ if (!(s->flags & SLAB_POISON))
+ return 1;
+
+ start = slqb_page_address(page);
+ end = start + (PAGE_SIZE << s->order);
+ length = s->objects * s->size;
+ remainder = end - (start + length);
+ if (!remainder)
+ return 1;
+
+ fault = check_bytes(start + length, POISON_INUSE, remainder);
+ if (!fault)
+ return 1;
+
+ while (end > fault && end[-1] == POISON_INUSE)
+ end--;
+
+ slab_err(s, page, "Padding overwritten. 0x%p-0x%p", fault, end - 1);
+ print_section("Padding", start, length);
+
+ restore_bytes(s, "slab padding", POISON_INUSE, start, end);
+ return 0;
+}
+
+static int check_object(struct kmem_cache *s, struct slqb_page *page,
+ void *object, int active)
+{
+ u8 *p = object;
+ u8 *endobject = object + s->objsize;
+
+ if (s->flags & SLAB_RED_ZONE) {
+ unsigned int red =
+ active ? SLUB_RED_ACTIVE : SLUB_RED_INACTIVE;
+
+ if (!check_bytes_and_report(s, page, object, "Redzone",
+ endobject, red, s->inuse - s->objsize))
+ return 0;
+ } else {
+ if ((s->flags & SLAB_POISON) && s->objsize < s->inuse) {
+ check_bytes_and_report(s, page, p, "Alignment padding",
+ endobject, POISON_INUSE, s->inuse - s->objsize);
+ }
+ }
+
+ if (s->flags & SLAB_POISON) {
+ if (!active && (s->flags & __OBJECT_POISON)) {
+ if (!check_bytes_and_report(s, page, p, "Poison", p,
+ POISON_FREE, s->objsize - 1))
+ return 0;
+
+ if (!check_bytes_and_report(s, page, p, "Poison",
+ p + s->objsize - 1, POISON_END, 1))
+ return 0;
+ }
+
+ /*
+ * check_pad_bytes cleans up on its own.
+ */
+ check_pad_bytes(s, page, p);
+ }
+
+ return 1;
+}
+
+static int check_slab(struct kmem_cache *s, struct slqb_page *page)
+{
+ if (!(page->flags & PG_SLQB_BIT)) {
+ slab_err(s, page, "Not a valid slab page");
+ return 0;
+ }
+ if (page->inuse == 0) {
+ slab_err(s, page, "inuse before free / after alloc", s->name);
+ return 0;
+ }
+ if (page->inuse > s->objects) {
+ slab_err(s, page, "inuse %u > max %u",
+ s->name, page->inuse, s->objects);
+ return 0;
+ }
+ /* Slab_pad_check fixes things up after itself */
+ slab_pad_check(s, page);
+ return 1;
+}
+
+static void trace(struct kmem_cache *s, struct slqb_page *page,
+ void *object, int alloc)
+{
+ if (s->flags & SLAB_TRACE) {
+ printk(KERN_INFO "TRACE %s %s 0x%p inuse=%d fp=0x%p\n",
+ s->name,
+ alloc ? "alloc" : "free",
+ object, page->inuse,
+ page->freelist);
+
+ if (!alloc)
+ print_section("Object", (void *)object, s->objsize);
+
+ dump_stack();
+ }
+}
+
+static void setup_object_debug(struct kmem_cache *s, struct slqb_page *page,
+ void *object)
+{
+ if (!slab_debug(s))
+ return;
+
+ if (!(s->flags & (SLAB_STORE_USER|SLAB_RED_ZONE|__OBJECT_POISON)))
+ return;
+
+ init_object(s, object, 0);
+ init_tracking(s, object);
+}
+
+static int alloc_debug_processing(struct kmem_cache *s,
+ void *object, unsigned long addr)
+{
+ struct slqb_page *page;
+ page = virt_to_head_slqb_page(object);
+
+ if (!check_slab(s, page))
+ goto bad;
+
+ if (!check_valid_pointer(s, page, object)) {
+ object_err(s, page, object, "Freelist Pointer check fails");
+ goto bad;
+ }
+
+ if (object && !check_object(s, page, object, 0))
+ goto bad;
+
+ /* Success perform special debug activities for allocs */
+ if (s->flags & SLAB_STORE_USER)
+ set_track(s, object, TRACK_ALLOC, addr);
+ trace(s, page, object, 1);
+ init_object(s, object, 1);
+ return 1;
+
+bad:
+ return 0;
+}
+
+static int free_debug_processing(struct kmem_cache *s,
+ void *object, unsigned long addr)
+{
+ struct slqb_page *page;
+ page = virt_to_head_slqb_page(object);
+
+ if (!check_slab(s, page))
+ goto fail;
+
+ if (!check_valid_pointer(s, page, object)) {
+ slab_err(s, page, "Invalid object pointer 0x%p", object);
+ goto fail;
+ }
+
+ if (!check_object(s, page, object, 1))
+ return 0;
+
+ /* Special debug activities for freeing objects */
+ if (s->flags & SLAB_STORE_USER)
+ set_track(s, object, TRACK_FREE, addr);
+ trace(s, page, object, 0);
+ init_object(s, object, 0);
+ return 1;
+
+fail:
+ slab_fix(s, "Object at 0x%p not freed", object);
+ return 0;
+}
+
+static int __init setup_slqb_debug(char *str)
+{
+ slqb_debug = DEBUG_DEFAULT_FLAGS;
+ if (*str++ != '=' || !*str) {
+ /*
+ * No options specified. Switch on full debugging.
+ */
+ goto out;
+ }
+
+ if (*str == ',') {
+ /*
+ * No options but restriction on slabs. This means full
+ * debugging for slabs matching a pattern.
+ */
+ goto check_slabs;
+ }
+
+ slqb_debug = 0;
+ if (*str == '-') {
+ /*
+ * Switch off all debugging measures.
+ */
+ goto out;
+ }
+
+ /*
+ * Determine which debug features should be switched on
+ */
+ for (; *str && *str != ','; str++) {
+ switch (tolower(*str)) {
+ case 'f':
+ slqb_debug |= SLAB_DEBUG_FREE;
+ break;
+ case 'z':
+ slqb_debug |= SLAB_RED_ZONE;
+ break;
+ case 'p':
+ slqb_debug |= SLAB_POISON;
+ break;
+ case 'u':
+ slqb_debug |= SLAB_STORE_USER;
+ break;
+ case 't':
+ slqb_debug |= SLAB_TRACE;
+ break;
+ default:
+ printk(KERN_ERR "slqb_debug option '%c' "
+ "unknown. skipped\n", *str);
+ }
+ }
+
+check_slabs:
+ if (*str == ',')
+ slqb_debug_slabs = str + 1;
+out:
+ return 1;
+}
+__setup("slqb_debug", setup_slqb_debug);
+
+static int __init setup_slqb_min_order(char *str)
+{
+ get_option(&str, &slqb_min_order);
+ slqb_min_order = min(slqb_min_order, MAX_ORDER - 1);
+
+ return 1;
+}
+__setup("slqb_min_order=", setup_slqb_min_order);
+
+static int __init setup_slqb_min_objects(char *str)
+{
+ get_option(&str, &slqb_min_objects);
+
+ return 1;
+}
+
+__setup("slqb_min_objects=", setup_slqb_min_objects);
+
+static unsigned long kmem_cache_flags(unsigned long objsize,
+ unsigned long flags, const char *name,
+ void (*ctor)(void *))
+{
+ /*
+ * Enable debugging if selected on the kernel commandline.
+ */
+ if (slqb_debug && (!slqb_debug_slabs ||
+ strncmp(slqb_debug_slabs, name,
+ strlen(slqb_debug_slabs)) == 0))
+ flags |= slqb_debug;
+
+ if (num_possible_nodes() > 1)
+ flags |= SLAB_NUMA;
+
+ return flags;
+}
+#else
+static inline void setup_object_debug(struct kmem_cache *s,
+ struct slqb_page *page, void *object)
+{
+}
+
+static inline int alloc_debug_processing(struct kmem_cache *s,
+ void *object, unsigned long addr)
+{
+ return 0;
+}
+
+static inline int free_debug_processing(struct kmem_cache *s,
+ void *object, unsigned long addr)
+{
+ return 0;
+}
+
+static inline int slab_pad_check(struct kmem_cache *s, struct slqb_page *page)
+{
+ return 1;
+}
+
+static inline int check_object(struct kmem_cache *s, struct slqb_page *page,
+ void *object, int active)
+{
+ return 1;
+}
+
+static inline void add_full(struct kmem_cache_node *n, struct slqb_page *page)
+{
+}
+
+static inline unsigned long kmem_cache_flags(unsigned long objsize,
+ unsigned long flags, const char *name, void (*ctor)(void *))
+{
+ if (num_possible_nodes() > 1)
+ flags |= SLAB_NUMA;
+ return flags;
+}
+
+static const int slqb_debug;
+#endif
+
+/*
+ * allocate a new slab (return its corresponding struct slqb_page)
+ */
+static struct slqb_page *allocate_slab(struct kmem_cache *s,
+ gfp_t flags, int node)
+{
+ struct slqb_page *page;
+ int pages = 1 << s->order;
+
+ flags |= s->allocflags;
+
+ page = (struct slqb_page *)alloc_pages_node(node, flags, s->order);
+ if (!page)
+ return NULL;
+
+ mod_zone_page_state(slqb_page_zone(page),
+ (s->flags & SLAB_RECLAIM_ACCOUNT) ?
+ NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE,
+ pages);
+
+ return page;
+}
+
+/*
+ * Called once for each object on a new slab page
+ */
+static void setup_object(struct kmem_cache *s,
+ struct slqb_page *page, void *object)
+{
+ setup_object_debug(s, page, object);
+ if (unlikely(s->ctor))
+ s->ctor(object);
+}
+
+/*
+ * Allocate a new slab, set up its object list.
+ */
+static struct slqb_page *new_slab_page(struct kmem_cache *s,
+ gfp_t flags, int node, unsigned int colour)
+{
+ struct slqb_page *page;
+ void *start;
+ void *last;
+ void *p;
+
+ BUG_ON(flags & GFP_SLAB_BUG_MASK);
+
+ page = allocate_slab(s,
+ flags & (GFP_RECLAIM_MASK | GFP_CONSTRAINT_MASK), node);
+ if (!page)
+ goto out;
+
+ page->flags |= PG_SLQB_BIT;
+
+ start = page_address(&page->page);
+
+ if (unlikely(slab_poison(s)))
+ memset(start, POISON_INUSE, PAGE_SIZE << s->order);
+
+ start += colour;
+
+ last = start;
+ for_each_object(p, s, start) {
+ setup_object(s, page, p);
+ set_freepointer(s, last, p);
+ last = p;
+ }
+ set_freepointer(s, last, NULL);
+
+ page->freelist = start;
+ page->inuse = 0;
+out:
+ return page;
+}
+
+/*
+ * Free a slab page back to the page allocator
+ */
+static void __free_slab(struct kmem_cache *s, struct slqb_page *page)
+{
+ int pages = 1 << s->order;
+
+ if (unlikely(slab_debug(s))) {
+ void *p;
+
+ slab_pad_check(s, page);
+ for_each_free_object(p, s, page->freelist)
+ check_object(s, page, p, 0);
+ }
+
+ mod_zone_page_state(slqb_page_zone(page),
+ (s->flags & SLAB_RECLAIM_ACCOUNT) ?
+ NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE,
+ -pages);
+
+ __free_slqb_pages(page, s->order, pages);
+}
+
+static void rcu_free_slab(struct rcu_head *h)
+{
+ struct slqb_page *page;
+
+ page = container_of(h, struct slqb_page, rcu_head);
+ __free_slab(page->list->cache, page);
+}
+
+static void free_slab(struct kmem_cache *s, struct slqb_page *page)
+{
+ VM_BUG_ON(page->inuse);
+ if (unlikely(s->flags & SLAB_DESTROY_BY_RCU))
+ call_rcu(&page->rcu_head, rcu_free_slab);
+ else
+ __free_slab(s, page);
+}
+
+/*
+ * Return an object to its slab.
+ *
+ * Caller must be the owner CPU in the case of per-CPU list, or hold the node's
+ * list_lock in the case of per-node list.
+ */
+static int free_object_to_page(struct kmem_cache *s,
+ struct kmem_cache_list *l, struct slqb_page *page,
+ void *object)
+{
+ VM_BUG_ON(page->list != l);
+
+ set_freepointer(s, object, page->freelist);
+ page->freelist = object;
+ page->inuse--;
+
+ if (!page->inuse) {
+ if (likely(s->objects > 1)) {
+ l->nr_partial--;
+ list_del(&page->lru);
+ }
+ l->nr_slabs--;
+ free_slab(s, page);
+ slqb_stat_inc(l, FLUSH_SLAB_FREE);
+ return 1;
+
+ } else if (page->inuse + 1 == s->objects) {
+ l->nr_partial++;
+ list_add(&page->lru, &l->partial);
+ slqb_stat_inc(l, FLUSH_SLAB_PARTIAL);
+ return 0;
+ }
+ return 0;
+}
+
+#ifdef CONFIG_SMP
+static void slab_free_to_remote(struct kmem_cache *s, struct slqb_page *page,
+ void *object, struct kmem_cache_cpu *c);
+#endif
+
+/*
+ * Flush the LIFO list of objects on a list. They are sent back to their pages
+ * in case the pages also belong to the list, or to our CPU's remote-free list
+ * in the case they do not.
+ *
+ * Doesn't flush the entire list. flush_free_list_all does.
+ *
+ * Caller must be the owner CPU in the case of per-CPU list, or hold the node's
+ * list_lock in the case of per-node list.
+ */
+static void flush_free_list(struct kmem_cache *s, struct kmem_cache_list *l)
+{
+ void **head;
+ int nr;
+ int locked = 0;
+
+ nr = l->freelist.nr;
+ if (unlikely(!nr))
+ return;
+
+ nr = min(slab_freebatch(s), nr);
+
+ slqb_stat_inc(l, FLUSH_FREE_LIST);
+ slqb_stat_add(l, FLUSH_FREE_LIST_OBJECTS, nr);
+
+ l->freelist.nr -= nr;
+ head = l->freelist.head;
+
+ do {
+ struct slqb_page *page;
+ void **object;
+
+ object = head;
+ VM_BUG_ON(!object);
+ head = get_freepointer(s, object);
+ page = virt_to_head_slqb_page(object);
+
+#ifdef CONFIG_SMP
+ if (page->list != l) {
+ struct kmem_cache_cpu *c;
+
+ if (locked) {
+ spin_unlock(&l->page_lock);
+ locked = 0;
+ }
+
+ c = get_cpu_slab(s, smp_processor_id());
+
+ slab_free_to_remote(s, page, object, c);
+ slqb_stat_inc(l, FLUSH_FREE_LIST_REMOTE);
+ } else
+#endif
+ {
+ if (!locked) {
+ spin_lock(&l->page_lock);
+ locked = 1;
+ }
+ free_object_to_page(s, l, page, object);
+ }
+
+ nr--;
+ } while (nr);
+
+ if (locked)
+ spin_unlock(&l->page_lock);
+
+ l->freelist.head = head;
+ if (!l->freelist.nr)
+ l->freelist.tail = NULL;
+}
+
+static void flush_free_list_all(struct kmem_cache *s, struct kmem_cache_list *l)
+{
+ while (l->freelist.nr)
+ flush_free_list(s, l);
+}
+
+#ifdef CONFIG_SMP
+/*
+ * If enough objects have been remotely freed back to this list,
+ * remote_free_check will be set. In which case, we'll eventually come here
+ * to take those objects off our remote_free list and onto our LIFO freelist.
+ *
+ * Caller must be the owner CPU in the case of per-CPU list, or hold the node's
+ * list_lock in the case of per-node list.
+ */
+static void claim_remote_free_list(struct kmem_cache *s,
+ struct kmem_cache_list *l)
+{
+ void **head, **tail;
+ int nr;
+
+ if (!l->remote_free.list.nr)
+ return;
+
+ spin_lock(&l->remote_free.lock);
+
+ l->remote_free_check = 0;
+ head = l->remote_free.list.head;
+ l->remote_free.list.head = NULL;
+ tail = l->remote_free.list.tail;
+ l->remote_free.list.tail = NULL;
+ nr = l->remote_free.list.nr;
+ l->remote_free.list.nr = 0;
+
+ spin_unlock(&l->remote_free.lock);
+
+ VM_BUG_ON(!nr);
+
+ if (!l->freelist.nr) {
+ /* Get head hot for likely subsequent allocation or flush */
+ prefetchw(head);
+ l->freelist.head = head;
+ } else
+ set_freepointer(s, l->freelist.tail, head);
+ l->freelist.tail = tail;
+
+ l->freelist.nr += nr;
+
+ slqb_stat_inc(l, CLAIM_REMOTE_LIST);
+ slqb_stat_add(l, CLAIM_REMOTE_LIST_OBJECTS, nr);
+}
+#else
+static inline void claim_remote_free_list(struct kmem_cache *s,
+ struct kmem_cache_list *l)
+{
+}
+#endif
+
+/*
+ * Allocation fastpath. Get an object from the list's LIFO freelist, or
+ * return NULL if it is empty.
+ *
+ * Caller must be the owner CPU in the case of per-CPU list, or hold the node's
+ * list_lock in the case of per-node list.
+ */
+static __always_inline void *__cache_list_get_object(struct kmem_cache *s,
+ struct kmem_cache_list *l)
+{
+ void *object;
+
+ object = l->freelist.head;
+ if (likely(object)) {
+ void *next = get_freepointer(s, object);
+
+ VM_BUG_ON(!l->freelist.nr);
+ l->freelist.nr--;
+ l->freelist.head = next;
+
+ return object;
+ }
+ VM_BUG_ON(l->freelist.nr);
+
+#ifdef CONFIG_SMP
+ if (unlikely(l->remote_free_check)) {
+ claim_remote_free_list(s, l);
+
+ if (l->freelist.nr > slab_hiwater(s))
+ flush_free_list(s, l);
+
+ /* repetition here helps gcc :( */
+ object = l->freelist.head;
+ if (likely(object)) {
+ void *next = get_freepointer(s, object);
+
+ VM_BUG_ON(!l->freelist.nr);
+ l->freelist.nr--;
+ l->freelist.head = next;
+
+ return object;
+ }
+ VM_BUG_ON(l->freelist.nr);
+ }
+#endif
+
+ return NULL;
+}
+
+/*
+ * Slow(er) path. Get a page from this list's existing pages. Will be a
+ * new empty page in the case that __slab_alloc_page has just been called
+ * (empty pages otherwise never get queued up on the lists), or a partial page
+ * already on the list.
+ *
+ * Caller must be the owner CPU in the case of per-CPU list, or hold the node's
+ * list_lock in the case of per-node list.
+ */
+static noinline void *__cache_list_get_page(struct kmem_cache *s,
+ struct kmem_cache_list *l)
+{
+ struct slqb_page *page;
+ void *object;
+
+ if (unlikely(!l->nr_partial))
+ return NULL;
+
+ page = list_first_entry(&l->partial, struct slqb_page, lru);
+ VM_BUG_ON(page->inuse == s->objects);
+ if (page->inuse + 1 == s->objects) {
+ l->nr_partial--;
+ list_del(&page->lru);
+ }
+
+ VM_BUG_ON(!page->freelist);
+
+ page->inuse++;
+
+ object = page->freelist;
+ page->freelist = get_freepointer(s, object);
+ if (page->freelist)
+ prefetchw(page->freelist);
+ VM_BUG_ON((page->inuse == s->objects) != (page->freelist == NULL));
+ slqb_stat_inc(l, ALLOC_SLAB_FILL);
+
+ return object;
+}
+
+static void *cache_list_get_page(struct kmem_cache *s,
+ struct kmem_cache_list *l)
+{
+ void *object;
+
+ if (unlikely(!l->nr_partial))
+ return NULL;
+
+ spin_lock(&l->page_lock);
+ object = __cache_list_get_page(s, l);
+ spin_unlock(&l->page_lock);
+
+ return object;
+}
+
+/*
+ * Allocation slowpath. Allocate a new slab page from the page allocator, and
+ * put it on the list's partial list. Must be followed by an allocation so
+ * that we don't have dangling empty pages on the partial list.
+ *
+ * Returns 0 on allocation failure.
+ *
+ * Must be called with interrupts disabled.
+ */
+static noinline void *__slab_alloc_page(struct kmem_cache *s,
+ gfp_t gfpflags, int node)
+{
+ struct slqb_page *page;
+ struct kmem_cache_list *l;
+ struct kmem_cache_cpu *c;
+ unsigned int colour;
+ void *object;
+
+ c = get_cpu_slab(s, smp_processor_id());
+ colour = c->colour_next;
+ c->colour_next += s->colour_off;
+ if (c->colour_next >= s->colour_range)
+ c->colour_next = 0;
+
+ /* Caller handles __GFP_ZERO */
+ gfpflags &= ~__GFP_ZERO;
+
+ if (gfpflags & __GFP_WAIT)
+ local_irq_enable();
+ page = new_slab_page(s, gfpflags, node, colour);
+ if (gfpflags & __GFP_WAIT)
+ local_irq_disable();
+ if (unlikely(!page))
+ return page;
+
+ if (!NUMA_BUILD || likely(slqb_page_to_nid(page) == numa_node_id())) {
+ struct kmem_cache_cpu *c;
+ int cpu = smp_processor_id();
+
+ c = get_cpu_slab(s, cpu);
+ l = &c->list;
+ page->list = l;
+
+ spin_lock(&l->page_lock);
+ l->nr_slabs++;
+ l->nr_partial++;
+ list_add(&page->lru, &l->partial);
+ slqb_stat_inc(l, ALLOC);
+ slqb_stat_inc(l, ALLOC_SLAB_NEW);
+ object = __cache_list_get_page(s, l);
+ spin_unlock(&l->page_lock);
+ } else {
+#ifdef CONFIG_NUMA
+ struct kmem_cache_node *n;
+
+ n = s->node_slab[slqb_page_to_nid(page)];
+ l = &n->list;
+ page->list = l;
+
+ spin_lock(&n->list_lock);
+ l->nr_slabs++;
+ l->nr_partial++;
+ list_add(&page->lru, &l->partial);
+ slqb_stat_inc(l, ALLOC);
+ slqb_stat_inc(l, ALLOC_SLAB_NEW);
+ object = __cache_list_get_page(s, l);
+ spin_unlock(&n->list_lock);
+#endif
+ }
+ VM_BUG_ON(!object);
+ return object;
+}
+
+#ifdef CONFIG_NUMA
+static noinline int alternate_nid(struct kmem_cache *s,
+ gfp_t gfpflags, int node)
+{
+ if (in_interrupt() || (gfpflags & __GFP_THISNODE))
+ return node;
+ if (cpuset_do_slab_mem_spread() && (s->flags & SLAB_MEM_SPREAD))
+ return cpuset_mem_spread_node();
+ else if (current->mempolicy)
+ return slab_node(current->mempolicy);
+ return node;
+}
+
+/*
+ * Allocate an object from a remote node. Return NULL if none could be found
+ * (in which case, caller should allocate a new slab)
+ *
+ * Must be called with interrupts disabled.
+ */
+static void *__remote_slab_alloc_node(struct kmem_cache *s,
+ gfp_t gfpflags, int node)
+{
+ struct kmem_cache_node *n;
+ struct kmem_cache_list *l;
+ void *object;
+
+ n = s->node_slab[node];
+ if (unlikely(!n)) /* node has no memory */
+ return NULL;
+ l = &n->list;
+
+ spin_lock(&n->list_lock);
+
+ object = __cache_list_get_object(s, l);
+ if (unlikely(!object)) {
+ object = cache_list_get_page(s, l);
+ if (unlikely(!object)) {
+ spin_unlock(&n->list_lock);
+ return __slab_alloc_page(s, gfpflags, node);
+ }
+ }
+ if (likely(object))
+ slqb_stat_inc(l, ALLOC);
+ spin_unlock(&n->list_lock);
+ return object;
+}
+
+static noinline void *__remote_slab_alloc(struct kmem_cache *s,
+ gfp_t gfpflags, int node)
+{
+ void *object;
+ struct zonelist *zonelist;
+ struct zoneref *z;
+ struct zone *zone;
+ enum zone_type high_zoneidx = gfp_zone(gfpflags);
+
+ object = __remote_slab_alloc_node(s, gfpflags, node);
+ if (likely(object || (gfpflags & __GFP_THISNODE)))
+ return object;
+
+ zonelist = node_zonelist(slab_node(current->mempolicy), gfpflags);
+ for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) {
+ if (!cpuset_zone_allowed_hardwall(zone, gfpflags))
+ continue;
+
+ node = zone_to_nid(zone);
+ object = __remote_slab_alloc_node(s, gfpflags, node);
+ if (likely(object))
+ return object;
+ }
+ return NULL;
+}
+#endif
+
+/*
+ * Main allocation path. Return an object, or NULL on allocation failure.
+ *
+ * Must be called with interrupts disabled.
+ */
+static __always_inline void *__slab_alloc(struct kmem_cache *s,
+ gfp_t gfpflags, int node)
+{
+ void *object;
+ struct kmem_cache_cpu *c;
+ struct kmem_cache_list *l;
+
+#ifdef CONFIG_NUMA
+ if (unlikely(node != -1) && unlikely(node != numa_node_id())) {
+try_remote:
+ return __remote_slab_alloc(s, gfpflags, node);
+ }
+#endif
+
+ c = get_cpu_slab(s, smp_processor_id());
+ VM_BUG_ON(!c);
+ l = &c->list;
+ object = __cache_list_get_object(s, l);
+ if (unlikely(!object)) {
+ object = cache_list_get_page(s, l);
+ if (unlikely(!object)) {
+ object = __slab_alloc_page(s, gfpflags, node);
+#ifdef CONFIG_NUMA
+ if (unlikely(!object)) {
+ node = numa_node_id();
+ goto try_remote;
+ }
+#endif
+ return object;
+ }
+ }
+ if (likely(object))
+ slqb_stat_inc(l, ALLOC);
+ return object;
+}
+
+/*
+ * Perform some interrupts-on processing around the main allocation path
+ * (debug checking and memset()ing).
+ */
+static __always_inline void *slab_alloc(struct kmem_cache *s,
+ gfp_t gfpflags, int node, unsigned long addr)
+{
+ void *object;
+ unsigned long flags;
+
+again:
+ local_irq_save(flags);
+ object = __slab_alloc(s, gfpflags, node);
+ local_irq_restore(flags);
+
+ if (unlikely(slab_debug(s)) && likely(object)) {
+ if (unlikely(!alloc_debug_processing(s, object, addr)))
+ goto again;
+ }
+
+ if (unlikely(gfpflags & __GFP_ZERO) && likely(object))
+ memset(object, 0, s->objsize);
+
+ return object;
+}
+
+static __always_inline void *__kmem_cache_alloc(struct kmem_cache *s,
+ gfp_t gfpflags, unsigned long caller)
+{
+ int node = -1;
+#ifdef CONFIG_NUMA
+ if (unlikely(current->flags & (PF_SPREAD_SLAB | PF_MEMPOLICY)))
+ node = alternate_nid(s, gfpflags, node);
+#endif
+ return slab_alloc(s, gfpflags, node, caller);
+}
+
+void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags)
+{
+ return __kmem_cache_alloc(s, gfpflags, _RET_IP_);
+}
+EXPORT_SYMBOL(kmem_cache_alloc);
+
+#ifdef CONFIG_NUMA
+void *kmem_cache_alloc_node(struct kmem_cache *s, gfp_t gfpflags, int node)
+{
+ return slab_alloc(s, gfpflags, node, _RET_IP_);
+}
+EXPORT_SYMBOL(kmem_cache_alloc_node);
+#endif
+
+#ifdef CONFIG_SMP
+/*
+ * Flush this CPU's remote free list of objects back to the list from where
+ * they originate. They end up on that list's remotely freed list, and
+ * eventually we set it's remote_free_check if there are enough objects on it.
+ *
+ * This seems convoluted, but it keeps is from stomping on the target CPU's
+ * fastpath cachelines.
+ *
+ * Must be called with interrupts disabled.
+ */
+static void flush_remote_free_cache(struct kmem_cache *s,
+ struct kmem_cache_cpu *c)
+{
+ struct kmlist *src;
+ struct kmem_cache_list *dst;
+ unsigned int nr;
+ int set;
+
+ src = &c->rlist;
+ nr = src->nr;
+ if (unlikely(!nr))
+ return;
+
+#ifdef CONFIG_SLQB_STATS
+ {
+ struct kmem_cache_list *l = &c->list;
+
+ slqb_stat_inc(l, FLUSH_RFREE_LIST);
+ slqb_stat_add(l, FLUSH_RFREE_LIST_OBJECTS, nr);
+ }
+#endif
+
+ dst = c->remote_cache_list;
+
+ /*
+ * Less common case, dst is filling up so free synchronously.
+ * No point in having remote CPU free thse as it will just
+ * free them back to the page list anyway.
+ */
+ if (unlikely(dst->remote_free.list.nr > (slab_hiwater(s) >> 1))) {
+ void **head;
+
+ head = src->head;
+ spin_lock(&dst->page_lock);
+ do {
+ struct slqb_page *page;
+ void **object;
+
+ object = head;
+ VM_BUG_ON(!object);
+ head = get_freepointer(s, object);
+ page = virt_to_head_slqb_page(object);
+
+ free_object_to_page(s, dst, page, object);
+ nr--;
+ } while (nr);
+ spin_unlock(&dst->page_lock);
+
+ src->head = NULL;
+ src->tail = NULL;
+ src->nr = 0;
+
+ return;
+ }
+
+ spin_lock(&dst->remote_free.lock);
+
+ if (!dst->remote_free.list.head)
+ dst->remote_free.list.head = src->head;
+ else
+ set_freepointer(s, dst->remote_free.list.tail, src->head);
+ dst->remote_free.list.tail = src->tail;
+
+ src->head = NULL;
+ src->tail = NULL;
+ src->nr = 0;
+
+ if (dst->remote_free.list.nr < slab_freebatch(s))
+ set = 1;
+ else
+ set = 0;
+
+ dst->remote_free.list.nr += nr;
+
+ if (unlikely(dst->remote_free.list.nr >= slab_freebatch(s) && set))
+ dst->remote_free_check = 1;
+
+ spin_unlock(&dst->remote_free.lock);
+}
+
+/*
+ * Free an object to this CPU's remote free list.
+ *
+ * Must be called with interrupts disabled.
+ */
+static noinline void slab_free_to_remote(struct kmem_cache *s,
+ struct slqb_page *page, void *object,
+ struct kmem_cache_cpu *c)
+{
+ struct kmlist *r;
+
+ /*
+ * Our remote free list corresponds to a different list. Must
+ * flush it and switch.
+ */
+ if (page->list != c->remote_cache_list) {
+ flush_remote_free_cache(s, c);
+ c->remote_cache_list = page->list;
+ }
+
+ r = &c->rlist;
+ if (!r->head)
+ r->head = object;
+ else
+ set_freepointer(s, r->tail, object);
+ set_freepointer(s, object, NULL);
+ r->tail = object;
+ r->nr++;
+
+ if (unlikely(r->nr >= slab_freebatch(s)))
+ flush_remote_free_cache(s, c);
+}
+#endif
+
+/*
+ * Main freeing path. Return an object, or NULL on allocation failure.
+ *
+ * Must be called with interrupts disabled.
+ */
+static __always_inline void __slab_free(struct kmem_cache *s,
+ struct slqb_page *page, void *object)
+{
+ struct kmem_cache_cpu *c;
+ struct kmem_cache_list *l;
+ int thiscpu = smp_processor_id();
+
+ c = get_cpu_slab(s, thiscpu);
+ l = &c->list;
+
+ slqb_stat_inc(l, FREE);
+
+ if (!NUMA_BUILD || !slab_numa(s) ||
+ likely(slqb_page_to_nid(page) == numa_node_id())) {
+ /*
+ * Freeing fastpath. Collects all local-node objects, not
+ * just those allocated from our per-CPU list. This allows
+ * fast transfer of objects from one CPU to another within
+ * a given node.
+ */
+ set_freepointer(s, object, l->freelist.head);
+ l->freelist.head = object;
+ if (!l->freelist.nr)
+ l->freelist.tail = object;
+ l->freelist.nr++;
+
+ if (unlikely(l->freelist.nr > slab_hiwater(s)))
+ flush_free_list(s, l);
+
+ } else {
+#ifdef CONFIG_SMP
+ /*
+ * Freeing an object that was allocated on a remote node.
+ */
+ slab_free_to_remote(s, page, object, c);
+ slqb_stat_inc(l, FREE_REMOTE);
+#endif
+ }
+}
+
+/*
+ * Perform some interrupts-on processing around the main freeing path
+ * (debug checking).
+ */
+static __always_inline void slab_free(struct kmem_cache *s,
+ struct slqb_page *page, void *object)
+{
+ unsigned long flags;
+
+ prefetchw(object);
+
+ debug_check_no_locks_freed(object, s->objsize);
+ if (likely(object) && unlikely(slab_debug(s))) {
+ if (unlikely(!free_debug_processing(s, object, _RET_IP_)))
+ return;
+ }
+
+ local_irq_save(flags);
+ __slab_free(s, page, object);
+ local_irq_restore(flags);
+}
+
+void kmem_cache_free(struct kmem_cache *s, void *object)
+{
+ struct slqb_page *page = NULL;
+
+ if (slab_numa(s))
+ page = virt_to_head_slqb_page(object);
+ slab_free(s, page, object);
+}
+EXPORT_SYMBOL(kmem_cache_free);
+
+/*
+ * Calculate the order of allocation given an slab object size.
+ *
+ * Order 0 allocations are preferred since order 0 does not cause fragmentation
+ * in the page allocator, and they have fastpaths in the page allocator. But
+ * also minimise external fragmentation with large objects.
+ */
+static int slab_order(int size, int max_order, int frac)
+{
+ int order;
+
+ if (fls(size - 1) <= PAGE_SHIFT)
+ order = 0;
+ else
+ order = fls(size - 1) - PAGE_SHIFT;
+ if (order < slqb_min_order)
+ order = slqb_min_order;
+
+ while (order <= max_order) {
+ unsigned long slab_size = PAGE_SIZE << order;
+ unsigned long objects;
+ unsigned long waste;
+
+ objects = slab_size / size;
+ if (!objects)
+ goto next;
+
+ if (order < MAX_ORDER && objects < slqb_min_objects) {
+ /*
+ * if we don't have enough objects for min_objects,
+ * then try the next size up. Unless we have reached
+ * our maximum possible page size.
+ */
+ goto next;
+ }
+
+ waste = slab_size - (objects * size);
+
+ if (waste * frac <= slab_size)
+ break;
+
+next:
+ order++;
+ }
+
+ return order;
+}
+
+static int calculate_order(int size)
+{
+ int order;
+
+ /*
+ * Attempt to find best configuration for a slab. This
+ * works by first attempting to generate a layout with
+ * the best configuration and backing off gradually.
+ */
+ order = slab_order(size, 1, 4);
+ if (order <= 1)
+ return order;
+
+ /*
+ * This size cannot fit in order-1. Allow bigger orders, but
+ * forget about trying to save space.
+ */
+ order = slab_order(size, MAX_ORDER - 1, 0);
+ if (order < MAX_ORDER)
+ return order;
+
+ return -ENOSYS;
+}
+
+/*
+ * Figure out what the alignment of the objects will be.
+ */
+static unsigned long calculate_alignment(unsigned long flags,
+ unsigned long align, unsigned long size)
+{
+ /*
+ * If the user wants hardware cache aligned objects then follow that
+ * suggestion if the object is sufficiently large.
+ *
+ * The hardware cache alignment cannot override the specified
+ * alignment though. If that is greater then use it.
+ */
+ if (flags & SLAB_HWCACHE_ALIGN) {
+ unsigned long ralign = cache_line_size();
+
+ while (size <= ralign / 2)
+ ralign /= 2;
+ align = max(align, ralign);
+ }
+
+ if (align < ARCH_SLAB_MINALIGN)
+ align = ARCH_SLAB_MINALIGN;
+
+ return ALIGN(align, sizeof(void *));
+}
+
+static void init_kmem_cache_list(struct kmem_cache *s,
+ struct kmem_cache_list *l)
+{
+ l->cache = s;
+ l->freelist.nr = 0;
+ l->freelist.head = NULL;
+ l->freelist.tail = NULL;
+ l->nr_partial = 0;
+ l->nr_slabs = 0;
+ INIT_LIST_HEAD(&l->partial);
+ spin_lock_init(&l->page_lock);
+
+#ifdef CONFIG_SMP
+ l->remote_free_check = 0;
+ spin_lock_init(&l->remote_free.lock);
+ l->remote_free.list.nr = 0;
+ l->remote_free.list.head = NULL;
+ l->remote_free.list.tail = NULL;
+#endif
+
+#ifdef CONFIG_SLQB_STATS
+ memset(l->stats, 0, sizeof(l->stats));
+#endif
+}
+
+static void init_kmem_cache_cpu(struct kmem_cache *s,
+ struct kmem_cache_cpu *c)
+{
+ init_kmem_cache_list(s, &c->list);
+
+ c->colour_next = 0;
+#ifdef CONFIG_SMP
+ c->rlist.nr = 0;
+ c->rlist.head = NULL;
+ c->rlist.tail = NULL;
+ c->remote_cache_list = NULL;
+#endif
+}
+
+#ifdef CONFIG_NUMA
+static void init_kmem_cache_node(struct kmem_cache *s,
+ struct kmem_cache_node *n)
+{
+ spin_lock_init(&n->list_lock);
+ init_kmem_cache_list(s, &n->list);
+}
+#endif
+
+/* Initial slabs. */
+#ifdef CONFIG_SMP
+static DEFINE_PER_CPU(struct kmem_cache_cpu, kmem_cache_cpus);
+#endif
+#ifdef CONFIG_NUMA
+/* XXX: really need a DEFINE_PER_NODE for per-node data, but this is better than
+ * a static array */
+static DEFINE_PER_CPU(struct kmem_cache_node, kmem_cache_nodes);
+#endif
+
+#ifdef CONFIG_SMP
+static struct kmem_cache kmem_cpu_cache;
+static DEFINE_PER_CPU(struct kmem_cache_cpu, kmem_cpu_cpus);
+#ifdef CONFIG_NUMA
+static DEFINE_PER_CPU(struct kmem_cache_node, kmem_cpu_nodes); /* XXX per-nid */
+#endif
+#endif
+
+#ifdef CONFIG_NUMA
+static struct kmem_cache kmem_node_cache;
+#ifdef CONFIG_SMP
+static DEFINE_PER_CPU(struct kmem_cache_cpu, kmem_node_cpus);
+#endif
+static DEFINE_PER_CPU(struct kmem_cache_node, kmem_node_nodes); /*XXX per-nid */
+#endif
+
+#ifdef CONFIG_SMP
+static struct kmem_cache_cpu *alloc_kmem_cache_cpu(struct kmem_cache *s,
+ int cpu)
+{
+ struct kmem_cache_cpu *c;
+ int node;
+
+ node = cpu_to_node(cpu);
+
+ c = kmem_cache_alloc_node(&kmem_cpu_cache, GFP_KERNEL, node);
+ if (!c)
+ return NULL;
+
+ init_kmem_cache_cpu(s, c);
+ return c;
+}
+
+static void free_kmem_cache_cpus(struct kmem_cache *s)
+{
+ int cpu;
+
+ for_each_online_cpu(cpu) {
+ struct kmem_cache_cpu *c;
+
+ c = s->cpu_slab[cpu];
+ if (c) {
+ kmem_cache_free(&kmem_cpu_cache, c);
+ s->cpu_slab[cpu] = NULL;
+ }
+ }
+}
+
+static int alloc_kmem_cache_cpus(struct kmem_cache *s)
+{
+ int cpu;
+
+ for_each_online_cpu(cpu) {
+ struct kmem_cache_cpu *c;
+
+ c = s->cpu_slab[cpu];
+ if (c)
+ continue;
+
+ c = alloc_kmem_cache_cpu(s, cpu);
+ if (!c) {
+ free_kmem_cache_cpus(s);
+ return 0;
+ }
+ s->cpu_slab[cpu] = c;
+ }
+ return 1;
+}
+
+#else
+static inline void free_kmem_cache_cpus(struct kmem_cache *s)
+{
+}
+
+static inline int alloc_kmem_cache_cpus(struct kmem_cache *s)
+{
+ init_kmem_cache_cpu(s, &s->cpu_slab);
+ return 1;
+}
+#endif
+
+#ifdef CONFIG_NUMA
+static void free_kmem_cache_nodes(struct kmem_cache *s)
+{
+ int node;
+
+ for_each_node_state(node, N_NORMAL_MEMORY) {
+ struct kmem_cache_node *n;
+
+ n = s->node_slab[node];
+ if (n) {
+ kmem_cache_free(&kmem_node_cache, n);
+ s->node_slab[node] = NULL;
+ }
+ }
+}
+
+static int alloc_kmem_cache_nodes(struct kmem_cache *s)
+{
+ int node;
+
+ for_each_node_state(node, N_NORMAL_MEMORY) {
+ struct kmem_cache_node *n;
+
+ n = kmem_cache_alloc_node(&kmem_node_cache, GFP_KERNEL, node);
+ if (!n) {
+ free_kmem_cache_nodes(s);
+ return 0;
+ }
+ init_kmem_cache_node(s, n);
+ s->node_slab[node] = n;
+ }
+ return 1;
+}
+#else
+static void free_kmem_cache_nodes(struct kmem_cache *s)
+{
+}
+
+static int alloc_kmem_cache_nodes(struct kmem_cache *s)
+{
+ return 1;
+}
+#endif
+
+/*
+ * calculate_sizes() determines the order and the distribution of data within
+ * a slab object.
+ */
+static int calculate_sizes(struct kmem_cache *s)
+{
+ unsigned long flags = s->flags;
+ unsigned long size = s->objsize;
+ unsigned long align = s->align;
+
+ /*
+ * Determine if we can poison the object itself. If the user of
+ * the slab may touch the object after free or before allocation
+ * then we should never poison the object itself.
+ */
+ if (slab_poison(s) && !(flags & SLAB_DESTROY_BY_RCU) && !s->ctor)
+ s->flags |= __OBJECT_POISON;
+ else
+ s->flags &= ~__OBJECT_POISON;
+
+ /*
+ * Round up object size to the next word boundary. We can only
+ * place the free pointer at word boundaries and this determines
+ * the possible location of the free pointer.
+ */
+ size = ALIGN(size, sizeof(void *));
+
+#ifdef CONFIG_SLQB_DEBUG
+ /*
+ * If we are Redzoning then check if there is some space between the
+ * end of the object and the free pointer. If not then add an
+ * additional word to have some bytes to store Redzone information.
+ */
+ if ((flags & SLAB_RED_ZONE) && size == s->objsize)
+ size += sizeof(void *);
+#endif
+
+ /*
+ * With that we have determined the number of bytes in actual use
+ * by the object. This is the potential offset to the free pointer.
+ */
+ s->inuse = size;
+
+ if (((flags & (SLAB_DESTROY_BY_RCU | SLAB_POISON)) || s->ctor)) {
+ /*
+ * Relocate free pointer after the object if it is not
+ * permitted to overwrite the first word of the object on
+ * kmem_cache_free.
+ *
+ * This is the case if we do RCU, have a constructor or
+ * destructor or are poisoning the objects.
+ */
+ s->offset = size;
+ size += sizeof(void *);
+ }
+
+#ifdef CONFIG_SLQB_DEBUG
+ if (flags & SLAB_STORE_USER) {
+ /*
+ * Need to store information about allocs and frees after
+ * the object.
+ */
+ size += 2 * sizeof(struct track);
+ }
+
+ if (flags & SLAB_RED_ZONE) {
+ /*
+ * Add some empty padding so that we can catch
+ * overwrites from earlier objects rather than let
+ * tracking information or the free pointer be
+ * corrupted if an user writes before the start
+ * of the object.
+ */
+ size += sizeof(void *);
+ }
+#endif
+
+ /*
+ * Determine the alignment based on various parameters that the
+ * user specified and the dynamic determination of cache line size
+ * on bootup.
+ */
+ align = calculate_alignment(flags, align, s->objsize);
+
+ /*
+ * SLQB stores one object immediately after another beginning from
+ * offset 0. In order to align the objects we have to simply size
+ * each object to conform to the alignment.
+ */
+ size = ALIGN(size, align);
+ s->size = size;
+ s->order = calculate_order(size);
+
+ if (s->order < 0)
+ return 0;
+
+ s->allocflags = 0;
+ if (s->order)
+ s->allocflags |= __GFP_COMP;
+
+ if (s->flags & SLAB_CACHE_DMA)
+ s->allocflags |= SLQB_DMA;
+
+ if (s->flags & SLAB_RECLAIM_ACCOUNT)
+ s->allocflags |= __GFP_RECLAIMABLE;
+
+ /*
+ * Determine the number of objects per slab
+ */
+ s->objects = (PAGE_SIZE << s->order) / size;
+
+ s->freebatch = max(4UL*PAGE_SIZE / size,
+ min(256UL, 64*PAGE_SIZE / size));
+ if (!s->freebatch)
+ s->freebatch = 1;
+ s->hiwater = s->freebatch << 2;
+
+ return !!s->objects;
+
+}
+
+#ifdef CONFIG_SMP
+/*
+ * Per-cpu allocator can't be used because it always uses slab allocator,
+ * and it can't do per-node allocations.
+ */
+static void *kmem_cache_dyn_array_alloc(int ids)
+{
+ size_t size = sizeof(void *) * ids;
+
+ BUG_ON(!size);
+
+ if (unlikely(!slab_is_available())) {
+ static void *nextmem;
+ static size_t nextleft;
+ void *ret;
+
+ /*
+ * Special case for setting up initial caches. These will
+ * never get freed by definition so we can do it rather
+ * simply.
+ */
+ if (size > nextleft) {
+ nextmem = alloc_pages_exact(size, GFP_KERNEL);
+ if (!nextmem)
+ return NULL;
+ nextleft = roundup(size, PAGE_SIZE);
+ }
+
+ ret = nextmem;
+ nextleft -= size;
+ nextmem += size;
+ memset(ret, 0, size);
+ return ret;
+ } else {
+ return kzalloc(size, GFP_KERNEL);
+ }
+}
+
+static void kmem_cache_dyn_array_free(void *array)
+{
+ if (unlikely(!slab_is_available()))
+ return; /* error case without crashing here (will panic soon) */
+ kfree(array);
+}
+#endif
+
+static int kmem_cache_open(struct kmem_cache *s,
+ const char *name, size_t size, size_t align,
+ unsigned long flags, void (*ctor)(void *), int alloc)
+{
+ unsigned int left_over;
+
+ memset(s, 0, sizeof(struct kmem_cache));
+ s->name = name;
+ s->ctor = ctor;
+ s->objsize = size;
+ s->align = align;
+ s->flags = kmem_cache_flags(size, flags, name, ctor);
+
+ if (!calculate_sizes(s))
+ goto error;
+
+ if (!slab_debug(s)) {
+ left_over = (PAGE_SIZE << s->order) - (s->objects * s->size);
+ s->colour_off = max(cache_line_size(), s->align);
+ s->colour_range = left_over;
+ } else {
+ s->colour_off = 0;
+ s->colour_range = 0;
+ }
+
+ /*
+ * Protect all alloc_kmem_cache_cpus/nodes allocations with slqb_lock
+ * to lock out hotplug, just in case (probably not strictly needed
+ * here).
+ */
+ down_write(&slqb_lock);
+#ifdef CONFIG_SMP
+ s->cpu_slab = kmem_cache_dyn_array_alloc(nr_cpu_ids);
+ if (!s->cpu_slab)
+ goto error_lock;
+# ifdef CONFIG_NUMA
+ s->node_slab = kmem_cache_dyn_array_alloc(nr_node_ids);
+ if (!s->node_slab)
+ goto error_cpu_array;
+# endif
+#endif
+
+ if (likely(alloc)) {
+ if (!alloc_kmem_cache_nodes(s))
+ goto error_node_array;
+
+ if (!alloc_kmem_cache_cpus(s))
+ goto error_nodes;
+ }
+
+ sysfs_slab_add(s);
+ list_add(&s->list, &slab_caches);
+ up_write(&slqb_lock);
+
+ return 1;
+
+error_nodes:
+ free_kmem_cache_nodes(s);
+error_node_array:
+#if defined(CONFIG_NUMA) && defined(CONFIG_SMP)
+ kmem_cache_dyn_array_free(s->node_slab);
+error_cpu_array:
+#endif
+#ifdef CONFIG_SMP
+ kmem_cache_dyn_array_free(s->cpu_slab);
+error_lock:
+#endif
+ up_write(&slqb_lock);
+error:
+ if (flags & SLAB_PANIC)
+ panic("%s: failed to create slab `%s'\n", __func__, name);
+ return 0;
+}
+
+/**
+ * kmem_ptr_validate - check if an untrusted pointer might be a slab entry.
+ * @s: the cache we're checking against
+ * @ptr: pointer to validate
+ *
+ * This verifies that the untrusted pointer looks sane;
+ * it is _not_ a guarantee that the pointer is actually
+ * part of the slab cache in question, but it at least
+ * validates that the pointer can be dereferenced and
+ * looks half-way sane.
+ *
+ * Currently only used for dentry validation.
+ */
+int kmem_ptr_validate(struct kmem_cache *s, const void *ptr)
+{
+ unsigned long addr = (unsigned long)ptr;
+ struct slqb_page *page;
+
+ if (unlikely(addr < PAGE_OFFSET))
+ goto out;
+ if (unlikely(addr > (unsigned long)high_memory - s->size))
+ goto out;
+ if (unlikely(!IS_ALIGNED(addr, s->align)))
+ goto out;
+ if (unlikely(!kern_addr_valid(addr)))
+ goto out;
+ if (unlikely(!kern_addr_valid(addr + s->size - 1)))
+ goto out;
+ if (unlikely(!pfn_valid(addr >> PAGE_SHIFT)))
+ goto out;
+ page = virt_to_head_slqb_page(ptr);
+ if (unlikely(!(page->flags & PG_SLQB_BIT)))
+ goto out;
+ if (unlikely(page->list->cache != s)) /* XXX: ouch, racy */
+ goto out;
+ return 1;
+out:
+ return 0;
+}
+EXPORT_SYMBOL(kmem_ptr_validate);
+
+/*
+ * Determine the size of a slab object
+ */
+unsigned int kmem_cache_size(struct kmem_cache *s)
+{
+ return s->objsize;
+}
+EXPORT_SYMBOL(kmem_cache_size);
+
+const char *kmem_cache_name(struct kmem_cache *s)
+{
+ return s->name;
+}
+EXPORT_SYMBOL(kmem_cache_name);
+
+/*
+ * Release all resources used by a slab cache. No more concurrency on the
+ * slab, so we can touch remote kmem_cache_cpu structures.
+ */
+void kmem_cache_destroy(struct kmem_cache *s)
+{
+#ifdef CONFIG_NUMA
+ int node;
+#endif
+ int cpu;
+
+ down_write(&slqb_lock);
+ list_del(&s->list);
+
+ local_irq_disable();
+#ifdef CONFIG_SMP
+ for_each_online_cpu(cpu) {
+ struct kmem_cache_cpu *c = get_cpu_slab(s, cpu);
+ struct kmem_cache_list *l = &c->list;
+
+ flush_free_list_all(s, l);
+ flush_remote_free_cache(s, c);
+ }
+#endif
+
+ for_each_online_cpu(cpu) {
+ struct kmem_cache_cpu *c = get_cpu_slab(s, cpu);
+ struct kmem_cache_list *l = &c->list;
+
+ claim_remote_free_list(s, l);
+ flush_free_list_all(s, l);
+
+ WARN_ON(l->freelist.nr);
+ WARN_ON(l->nr_slabs);
+ WARN_ON(l->nr_partial);
+ }
+
+ free_kmem_cache_cpus(s);
+
+#ifdef CONFIG_NUMA
+ for_each_node_state(node, N_NORMAL_MEMORY) {
+ struct kmem_cache_node *n;
+ struct kmem_cache_list *l;
+
+ n = s->node_slab[node];
+ if (!n)
+ continue;
+ l = &n->list;
+
+ claim_remote_free_list(s, l);
+ flush_free_list_all(s, l);
+
+ WARN_ON(l->freelist.nr);
+ WARN_ON(l->nr_slabs);
+ WARN_ON(l->nr_partial);
+ }
+
+ free_kmem_cache_nodes(s);
+#endif
+ local_irq_enable();
+
+ sysfs_slab_remove(s);
+ up_write(&slqb_lock);
+}
+EXPORT_SYMBOL(kmem_cache_destroy);
+
+/********************************************************************
+ * Kmalloc subsystem
+ *******************************************************************/
+
+struct kmem_cache kmalloc_caches[KMALLOC_SHIFT_SLQB_HIGH + 1] __cacheline_aligned;
+EXPORT_SYMBOL(kmalloc_caches);
+
+#ifdef CONFIG_ZONE_DMA
+struct kmem_cache kmalloc_caches_dma[KMALLOC_SHIFT_SLQB_HIGH + 1] __cacheline_aligned;
+EXPORT_SYMBOL(kmalloc_caches_dma);
+#endif
+
+#ifndef ARCH_KMALLOC_FLAGS
+#define ARCH_KMALLOC_FLAGS SLAB_HWCACHE_ALIGN
+#endif
+
+static struct kmem_cache *open_kmalloc_cache(struct kmem_cache *s,
+ const char *name, int size, gfp_t gfp_flags)
+{
+ unsigned int flags = ARCH_KMALLOC_FLAGS | SLAB_PANIC;
+
+ if (gfp_flags & SLQB_DMA)
+ flags |= SLAB_CACHE_DMA;
+
+ kmem_cache_open(s, name, size, ARCH_KMALLOC_MINALIGN, flags, NULL, 1);
+
+ return s;
+}
+
+/*
+ * Conversion table for small slabs sizes / 8 to the index in the
+ * kmalloc array. This is necessary for slabs < 192 since we have non power
+ * of two cache sizes there. The size of larger slabs can be determined using
+ * fls.
+ */
+static s8 size_index[24] __cacheline_aligned = {
+ 3, /* 8 */
+ 4, /* 16 */
+ 5, /* 24 */
+ 5, /* 32 */
+ 6, /* 40 */
+ 6, /* 48 */
+ 6, /* 56 */
+ 6, /* 64 */
+#if L1_CACHE_BYTES < 64
+ 1, /* 72 */
+ 1, /* 80 */
+ 1, /* 88 */
+ 1, /* 96 */
+#else
+ 7,
+ 7,
+ 7,
+ 7,
+#endif
+ 7, /* 104 */
+ 7, /* 112 */
+ 7, /* 120 */
+ 7, /* 128 */
+#if L1_CACHE_BYTES < 128
+ 2, /* 136 */
+ 2, /* 144 */
+ 2, /* 152 */
+ 2, /* 160 */
+ 2, /* 168 */
+ 2, /* 176 */
+ 2, /* 184 */
+ 2 /* 192 */
+#else
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1
+#endif
+};
+
+static struct kmem_cache *get_slab(size_t size, gfp_t flags)
+{
+ int index;
+
+#if L1_CACHE_BYTES >= 128
+ if (size <= 128) {
+#else
+ if (size <= 192) {
+#endif
+ if (unlikely(!size))
+ return ZERO_SIZE_PTR;
+
+ index = size_index[(size - 1) / 8];
+ } else
+ index = fls(size - 1);
+
+ if (unlikely((flags & SLQB_DMA)))
+ return &kmalloc_caches_dma[index];
+ else
+ return &kmalloc_caches[index];
+}
+
+void *__kmalloc(size_t size, gfp_t flags)
+{
+ struct kmem_cache *s;
+
+ s = get_slab(size, flags);
+ if (unlikely(ZERO_OR_NULL_PTR(s)))
+ return s;
+
+ return __kmem_cache_alloc(s, flags, _RET_IP_);
+}
+EXPORT_SYMBOL(__kmalloc);
+
+#ifdef CONFIG_NUMA
+void *__kmalloc_node(size_t size, gfp_t flags, int node)
+{
+ struct kmem_cache *s;
+
+ s = get_slab(size, flags);
+ if (unlikely(ZERO_OR_NULL_PTR(s)))
+ return s;
+
+ return kmem_cache_alloc_node(s, flags, node);
+}
+EXPORT_SYMBOL(__kmalloc_node);
+#endif
+
+size_t ksize(const void *object)
+{
+ struct slqb_page *page;
+ struct kmem_cache *s;
+
+ BUG_ON(!object);
+ if (unlikely(object == ZERO_SIZE_PTR))
+ return 0;
+
+ page = virt_to_head_slqb_page(object);
+ BUG_ON(!(page->flags & PG_SLQB_BIT));
+
+ s = page->list->cache;
+
+ /*
+ * Debugging requires use of the padding between object
+ * and whatever may come after it.
+ */
+ if (s->flags & (SLAB_RED_ZONE | SLAB_POISON))
+ return s->objsize;
+
+ /*
+ * If we have the need to store the freelist pointer
+ * back there or track user information then we can
+ * only use the space before that information.
+ */
+ if (s->flags & (SLAB_DESTROY_BY_RCU | SLAB_STORE_USER))
+ return s->inuse;
+
+ /*
+ * Else we can use all the padding etc for the allocation
+ */
+ return s->size;
+}
+EXPORT_SYMBOL(ksize);
+
+void kfree(const void *object)
+{
+ struct kmem_cache *s;
+ struct slqb_page *page;
+
+ if (unlikely(ZERO_OR_NULL_PTR(object)))
+ return;
+
+ page = virt_to_head_slqb_page(object);
+ s = page->list->cache;
+
+ slab_free(s, page, (void *)object);
+}
+EXPORT_SYMBOL(kfree);
+
+static void kmem_cache_trim_percpu(void *arg)
+{
+ int cpu = smp_processor_id();
+ struct kmem_cache *s = arg;
+ struct kmem_cache_cpu *c = get_cpu_slab(s, cpu);
+ struct kmem_cache_list *l = &c->list;
+
+ claim_remote_free_list(s, l);
+ flush_free_list(s, l);
+#ifdef CONFIG_SMP
+ flush_remote_free_cache(s, c);
+#endif
+}
+
+int kmem_cache_shrink(struct kmem_cache *s)
+{
+#ifdef CONFIG_NUMA
+ int node;
+#endif
+
+ on_each_cpu(kmem_cache_trim_percpu, s, 1);
+
+#ifdef CONFIG_NUMA
+ for_each_node_state(node, N_NORMAL_MEMORY) {
+ struct kmem_cache_node *n;
+ struct kmem_cache_list *l;
+
+ n = s->node_slab[node];
+ if (!n)
+ continue;
+ l = &n->list;
+
+ spin_lock_irq(&n->list_lock);
+ claim_remote_free_list(s, l);
+ flush_free_list(s, l);
+ spin_unlock_irq(&n->list_lock);
+ }
+#endif
+
+ return 0;
+}
+EXPORT_SYMBOL(kmem_cache_shrink);
+
+#if defined(CONFIG_NUMA) && defined(CONFIG_MEMORY_HOTPLUG)
+static void kmem_cache_reap_percpu(void *arg)
+{
+ int cpu = smp_processor_id();
+ struct kmem_cache *s;
+ long phase = (long)arg;
+
+ list_for_each_entry(s, &slab_caches, list) {
+ struct kmem_cache_cpu *c = get_cpu_slab(s, cpu);
+ struct kmem_cache_list *l = &c->list;
+
+ if (phase == 0) {
+ flush_free_list_all(s, l);
+ flush_remote_free_cache(s, c);
+ }
+
+ if (phase == 1) {
+ claim_remote_free_list(s, l);
+ flush_free_list_all(s, l);
+ }
+ }
+}
+
+static void kmem_cache_reap(void)
+{
+ struct kmem_cache *s;
+ int node;
+
+ down_read(&slqb_lock);
+ on_each_cpu(kmem_cache_reap_percpu, (void *)0, 1);
+ on_each_cpu(kmem_cache_reap_percpu, (void *)1, 1);
+
+ list_for_each_entry(s, &slab_caches, list) {
+ for_each_node_state(node, N_NORMAL_MEMORY) {
+ struct kmem_cache_node *n;
+ struct kmem_cache_list *l;
+
+ n = s->node_slab[node];
+ if (!n)
+ continue;
+ l = &n->list;
+
+ spin_lock_irq(&n->list_lock);
+ claim_remote_free_list(s, l);
+ flush_free_list_all(s, l);
+ spin_unlock_irq(&n->list_lock);
+ }
+ }
+ up_read(&slqb_lock);
+}
+#endif
+
+static void cache_trim_worker(struct work_struct *w)
+{
+ struct delayed_work *work =
+ container_of(w, struct delayed_work, work);
+ struct kmem_cache *s;
+
+ if (!down_read_trylock(&slqb_lock))
+ goto out;
+
+ list_for_each_entry(s, &slab_caches, list) {
+#ifdef CONFIG_NUMA
+ int node = numa_node_id();
+ struct kmem_cache_node *n = s->node_slab[node];
+
+ if (n) {
+ struct kmem_cache_list *l = &n->list;
+
+ spin_lock_irq(&n->list_lock);
+ claim_remote_free_list(s, l);
+ flush_free_list(s, l);
+ spin_unlock_irq(&n->list_lock);
+ }
+#endif
+
+ local_irq_disable();
+ kmem_cache_trim_percpu(s);
+ local_irq_enable();
+ }
+
+ up_read(&slqb_lock);
+out:
+ schedule_delayed_work(work, round_jiffies_relative(3*HZ));
+}
+
+static DEFINE_PER_CPU(struct delayed_work, cache_trim_work);
+
+static void __cpuinit start_cpu_timer(int cpu)
+{
+ struct delayed_work *cache_trim_work = &per_cpu(cache_trim_work, cpu);
+
+ /*
+ * When this gets called from do_initcalls via cpucache_init(),
+ * init_workqueues() has already run, so keventd will be setup
+ * at that time.
+ */
+ if (keventd_up() && cache_trim_work->work.func == NULL) {
+ INIT_DELAYED_WORK(cache_trim_work, cache_trim_worker);
+ schedule_delayed_work_on(cpu, cache_trim_work,
+ __round_jiffies_relative(HZ, cpu));
+ }
+}
+
+static int __init cpucache_init(void)
+{
+ int cpu;
+
+ for_each_online_cpu(cpu)
+ start_cpu_timer(cpu);
+
+ return 0;
+}
+device_initcall(cpucache_init);
+
+#if defined(CONFIG_NUMA) && defined(CONFIG_MEMORY_HOTPLUG)
+static void slab_mem_going_offline_callback(void *arg)
+{
+ kmem_cache_reap();
+}
+
+static void slab_mem_offline_callback(void *arg)
+{
+ /* XXX: should release structures, see CPU offline comment */
+}
+
+static int slab_mem_going_online_callback(void *arg)
+{
+ struct kmem_cache *s;
+ struct kmem_cache_node *n;
+ 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_write(&slqb_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.
+ */
+ if (s->node_slab[nid]) /* could be lefover from last online */
+ continue;
+ n = kmem_cache_alloc(&kmem_node_cache, GFP_KERNEL);
+ if (!n) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ init_kmem_cache_node(s, n);
+ s->node_slab[nid] = n;
+ }
+out:
+ up_write(&slqb_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:
+ 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
+ *******************************************************************/
+
+void __init kmem_cache_init(void)
+{
+ int i;
+ unsigned int flags = SLAB_HWCACHE_ALIGN|SLAB_PANIC;
+
+ /*
+ * All the ifdefs are rather ugly here, but it's just the setup code,
+ * so it doesn't have to be too readable :)
+ */
+ kmem_cache_open(&kmem_cache_cache, "kmem_cache",
+ sizeof(struct kmem_cache), 0, flags, NULL, 0);
+#ifdef CONFIG_SMP
+ kmem_cache_open(&kmem_cpu_cache, "kmem_cache_cpu",
+ sizeof(struct kmem_cache_cpu), 0, flags, NULL, 0);
+#endif
+#ifdef CONFIG_NUMA
+ kmem_cache_open(&kmem_node_cache, "kmem_cache_node",
+ sizeof(struct kmem_cache_node), 0, flags, NULL, 0);
+#endif
+
+#ifdef CONFIG_SMP
+ for_each_possible_cpu(i) {
+ struct kmem_cache_cpu *c;
+
+ c = &per_cpu(kmem_cache_cpus, i);
+ init_kmem_cache_cpu(&kmem_cache_cache, c);
+ kmem_cache_cache.cpu_slab[i] = c;
+
+ c = &per_cpu(kmem_cpu_cpus, i);
+ init_kmem_cache_cpu(&kmem_cpu_cache, c);
+ kmem_cpu_cache.cpu_slab[i] = c;
+
+#ifdef CONFIG_NUMA
+ c = &per_cpu(kmem_node_cpus, i);
+ init_kmem_cache_cpu(&kmem_node_cache, c);
+ kmem_node_cache.cpu_slab[i] = c;
+#endif
+ }
+#else
+ init_kmem_cache_cpu(&kmem_cache_cache, &kmem_cache_cache.cpu_slab);
+#endif
+
+#ifdef CONFIG_NUMA
+ for_each_node_state(i, N_NORMAL_MEMORY) {
+ struct kmem_cache_node *n;
+
+ n = &per_cpu(kmem_cache_nodes, i);
+ init_kmem_cache_node(&kmem_cache_cache, n);
+ kmem_cache_cache.node_slab[i] = n;
+#ifdef CONFIG_SMP
+ n = &per_cpu(kmem_cpu_nodes, i);
+ init_kmem_cache_node(&kmem_cpu_cache, n);
+ kmem_cpu_cache.node_slab[i] = n;
+#endif
+ n = &per_cpu(kmem_node_nodes, i);
+ init_kmem_cache_node(&kmem_node_cache, n);
+ kmem_node_cache.node_slab[i] = n;
+ }
+#endif
+
+ /* Caches that are not of the two-to-the-power-of size */
+ if (L1_CACHE_BYTES < 64 && KMALLOC_MIN_SIZE <= 64) {
+ open_kmalloc_cache(&kmalloc_caches[1],
+ "kmalloc-96", 96, GFP_KERNEL);
+#ifdef CONFIG_ZONE_DMA
+ open_kmalloc_cache(&kmalloc_caches_dma[1],
+ "kmalloc_dma-96", 96, GFP_KERNEL|SLQB_DMA);
+#endif
+ }
+ if (L1_CACHE_BYTES < 128 && KMALLOC_MIN_SIZE <= 128) {
+ open_kmalloc_cache(&kmalloc_caches[2],
+ "kmalloc-192", 192, GFP_KERNEL);
+#ifdef CONFIG_ZONE_DMA
+ open_kmalloc_cache(&kmalloc_caches_dma[2],
+ "kmalloc_dma-192", 192, GFP_KERNEL|SLQB_DMA);
+#endif
+ }
+
+ for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_SLQB_HIGH; i++) {
+ open_kmalloc_cache(&kmalloc_caches[i],
+ "kmalloc", 1 << i, GFP_KERNEL);
+#ifdef CONFIG_ZONE_DMA
+ open_kmalloc_cache(&kmalloc_caches_dma[i],
+ "kmalloc_dma", 1 << i, GFP_KERNEL|SLQB_DMA);
+#endif
+ }
+
+ /*
+ * Patch up the size_index table if we have strange large alignment
+ * requirements for the kmalloc array. This is only the case for
+ * mips it seems. The standard arches will not generate any code here.
+ *
+ * Largest permitted alignment is 256 bytes due to the way we
+ * handle the index determination for the smaller caches.
+ *
+ * Make sure that nothing crazy happens if someone starts tinkering
+ * around with ARCH_KMALLOC_MINALIGN
+ */
+ BUILD_BUG_ON(KMALLOC_MIN_SIZE > 256 ||
+ (KMALLOC_MIN_SIZE & (KMALLOC_MIN_SIZE - 1)));
+
+ for (i = 8; i < KMALLOC_MIN_SIZE; i += 8)
+ size_index[(i - 1) / 8] = KMALLOC_SHIFT_LOW;
+
+ /* Provide the correct kmalloc names now that the caches are up */
+ for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_SLQB_HIGH; i++) {
+ kmalloc_caches[i].name =
+ kasprintf(GFP_KERNEL, "kmalloc-%d", 1 << i);
+#ifdef CONFIG_ZONE_DMA
+ kmalloc_caches_dma[i].name =
+ kasprintf(GFP_KERNEL, "kmalloc_dma-%d", 1 << i);
+#endif
+ }
+
+#ifdef CONFIG_SMP
+ register_cpu_notifier(&slab_notifier);
+#endif
+#ifdef CONFIG_NUMA
+ hotplug_memory_notifier(slab_memory_callback, 1);
+#endif
+ /*
+ * smp_init() has not yet been called, so no worries about memory
+ * ordering with __slab_is_available.
+ */
+ __slab_is_available = 1;
+}
+
+/*
+ * Some basic slab creation sanity checks
+ */
+static int kmem_cache_create_ok(const char *name, size_t size,
+ size_t align, unsigned long flags)
+{
+ struct kmem_cache *tmp;
+
+ /*
+ * Sanity checks... these are all serious usage bugs.
+ */
+ if (!name || in_interrupt() || (size < sizeof(void *))) {
+ printk(KERN_ERR "kmem_cache_create(): early error in slab %s\n",
+ name);
+ dump_stack();
+
+ return 0;
+ }
+
+ down_read(&slqb_lock);
+
+ list_for_each_entry(tmp, &slab_caches, list) {
+ char x;
+ int res;
+
+ /*
+ * This happens when the module gets unloaded and doesn't
+ * destroy its slab cache and no-one else reuses the vmalloc
+ * area of the module. Print a warning.
+ */
+ res = probe_kernel_address(tmp->name, x);
+ if (res) {
+ printk(KERN_ERR
+ "SLAB: cache with size %d has lost its name\n",
+ tmp->size);
+ continue;
+ }
+
+ if (!strcmp(tmp->name, name)) {
+ printk(KERN_ERR
+ "SLAB: duplicate cache %s\n", name);
+ dump_stack();
+ up_read(&slqb_lock);
+
+ return 0;
+ }
+ }
+
+ up_read(&slqb_lock);
+
+ WARN_ON(strchr(name, ' ')); /* It confuses parsers */
+ if (flags & SLAB_DESTROY_BY_RCU)
+ WARN_ON(flags & SLAB_POISON);
+
+ return 1;
+}
+
+struct kmem_cache *kmem_cache_create(const char *name, size_t size,
+ size_t align, unsigned long flags, void (*ctor)(void *))
+{
+ struct kmem_cache *s;
+
+ if (!kmem_cache_create_ok(name, size, align, flags))
+ goto err;
+
+ s = kmem_cache_alloc(&kmem_cache_cache, GFP_KERNEL);
+ if (!s)
+ goto err;
+
+ if (kmem_cache_open(s, name, size, align, flags, ctor, 1))
+ return s;
+
+ kmem_cache_free(&kmem_cache_cache, s);
+
+err:
+ if (flags & SLAB_PANIC)
+ panic("%s: failed to create slab `%s'\n", __func__, name);
+
+ return NULL;
+}
+EXPORT_SYMBOL(kmem_cache_create);
+
+#ifdef CONFIG_SMP
+/*
+ * Use the cpu notifier to insure that the cpu slabs are flushed when
+ * necessary.
+ */
+static int __cpuinit slab_cpuup_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ long cpu = (long)hcpu;
+ struct kmem_cache *s;
+
+ switch (action) {
+ case CPU_UP_PREPARE:
+ case CPU_UP_PREPARE_FROZEN:
+ down_write(&slqb_lock);
+ list_for_each_entry(s, &slab_caches, list) {
+ if (s->cpu_slab[cpu]) /* could be lefover last online */
+ continue;
+ s->cpu_slab[cpu] = alloc_kmem_cache_cpu(s, cpu);
+ if (!s->cpu_slab[cpu]) {
+ up_read(&slqb_lock);
+ return NOTIFY_BAD;
+ }
+ }
+ up_write(&slqb_lock);
+ break;
+
+ case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
+ case CPU_DOWN_FAILED:
+ case CPU_DOWN_FAILED_FROZEN:
+ start_cpu_timer(cpu);
+ break;
+
+ case CPU_DOWN_PREPARE:
+ case CPU_DOWN_PREPARE_FROZEN:
+ cancel_rearming_delayed_work(&per_cpu(cache_trim_work, cpu));
+ per_cpu(cache_trim_work, cpu).work.func = NULL;
+ break;
+
+ case CPU_UP_CANCELED:
+ case CPU_UP_CANCELED_FROZEN:
+ case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
+ /*
+ * XXX: Freeing here doesn't work because objects can still be
+ * on this CPU's list. periodic timer needs to check if a CPU
+ * is offline and then try to cleanup from there. Same for node
+ * offline.
+ */
+ default:
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata slab_notifier = {
+ .notifier_call = slab_cpuup_callback
+};
+
+#endif
+
+#ifdef CONFIG_SLQB_DEBUG
+void *__kmalloc_track_caller(size_t size, gfp_t flags, unsigned long caller)
+{
+ struct kmem_cache *s;
+ int node = -1;
+
+ s = get_slab(size, flags);
+ if (unlikely(ZERO_OR_NULL_PTR(s)))
+ return s;
+
+#ifdef CONFIG_NUMA
+ if (unlikely(current->flags & (PF_SPREAD_SLAB | PF_MEMPOLICY)))
+ node = alternate_nid(s, flags, node);
+#endif
+ return slab_alloc(s, flags, node, caller);
+}
+
+void *__kmalloc_node_track_caller(size_t size, gfp_t flags, int node,
+ unsigned long caller)
+{
+ struct kmem_cache *s;
+
+ s = get_slab(size, flags);
+ if (unlikely(ZERO_OR_NULL_PTR(s)))
+ return s;
+
+ return slab_alloc(s, flags, node, caller);
+}
+#endif
+
+#if defined(CONFIG_SLQB_SYSFS) || defined(CONFIG_SLABINFO)
+struct stats_gather {
+ struct kmem_cache *s;
+ spinlock_t lock;
+ unsigned long nr_slabs;
+ unsigned long nr_partial;
+ unsigned long nr_inuse;
+ unsigned long nr_objects;
+
+#ifdef CONFIG_SLQB_STATS
+ unsigned long stats[NR_SLQB_STAT_ITEMS];
+#endif
+};
+
+static void __gather_stats(void *arg)
+{
+ unsigned long nr_slabs;
+ unsigned long nr_partial;
+ unsigned long nr_inuse;
+ struct stats_gather *gather = arg;
+ int cpu = smp_processor_id();
+ struct kmem_cache *s = gather->s;
+ struct kmem_cache_cpu *c = get_cpu_slab(s, cpu);
+ struct kmem_cache_list *l = &c->list;
+ struct slqb_page *page;
+#ifdef CONFIG_SLQB_STATS
+ int i;
+#endif
+
+ spin_lock(&l->page_lock);
+ nr_slabs = l->nr_slabs;
+ nr_partial = l->nr_partial;
+ nr_inuse = (nr_slabs - nr_partial) * s->objects;
+
+ list_for_each_entry(page, &l->partial, lru) {
+ nr_inuse += page->inuse;
+ }
+ spin_unlock(&l->page_lock);
+
+ spin_lock(&gather->lock);
+ gather->nr_slabs += nr_slabs;
+ gather->nr_partial += nr_partial;
+ gather->nr_inuse += nr_inuse;
+#ifdef CONFIG_SLQB_STATS
+ for (i = 0; i < NR_SLQB_STAT_ITEMS; i++)
+ gather->stats[i] += l->stats[i];
+#endif
+ spin_unlock(&gather->lock);
+}
+
+/* must be called with slqb_lock held */
+static void gather_stats_locked(struct kmem_cache *s,
+ struct stats_gather *stats)
+{
+#ifdef CONFIG_NUMA
+ int node;
+#endif
+
+ memset(stats, 0, sizeof(struct stats_gather));
+ stats->s = s;
+ spin_lock_init(&stats->lock);
+
+ on_each_cpu(__gather_stats, stats, 1);
+
+#ifdef CONFIG_NUMA
+ for_each_online_node(node) {
+ struct kmem_cache_node *n = s->node_slab[node];
+ struct kmem_cache_list *l = &n->list;
+ struct slqb_page *page;
+ unsigned long flags;
+#ifdef CONFIG_SLQB_STATS
+ int i;
+#endif
+
+ spin_lock_irqsave(&n->list_lock, flags);
+#ifdef CONFIG_SLQB_STATS
+ for (i = 0; i < NR_SLQB_STAT_ITEMS; i++)
+ stats->stats[i] += l->stats[i];
+#endif
+ stats->nr_slabs += l->nr_slabs;
+ stats->nr_partial += l->nr_partial;
+ stats->nr_inuse += (l->nr_slabs - l->nr_partial) * s->objects;
+
+ list_for_each_entry(page, &l->partial, lru) {
+ stats->nr_inuse += page->inuse;
+ }
+ spin_unlock_irqrestore(&n->list_lock, flags);
+ }
+#endif
+
+ stats->nr_objects = stats->nr_slabs * s->objects;
+}
+
+#ifdef CONFIG_SLQB_SYSFS
+static void gather_stats(struct kmem_cache *s, struct stats_gather *stats)
+{
+ down_read(&slqb_lock); /* hold off hotplug */
+ gather_stats_locked(s, stats);
+ up_read(&slqb_lock);
+}
+#endif
+#endif
+
+/*
+ * The /proc/slabinfo ABI
+ */
+#ifdef CONFIG_SLABINFO
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+ssize_t slabinfo_write(struct file *file, const char __user * buffer,
+ size_t count, loff_t *ppos)
+{
+ return -EINVAL;
+}
+
+static void print_slabinfo_header(struct seq_file *m)
+{
+ seq_puts(m, "slabinfo - version: 2.1\n");
+ seq_puts(m, "# name <active_objs> <num_objs> <objsize> "
+ "<objperslab> <pagesperslab>");
+ seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>");
+ seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>");
+ seq_putc(m, '\n');
+}
+
+static void *s_start(struct seq_file *m, loff_t *pos)
+{
+ loff_t n = *pos;
+
+ down_read(&slqb_lock);
+ if (!n)
+ print_slabinfo_header(m);
+
+ return seq_list_start(&slab_caches, *pos);
+}
+
+static void *s_next(struct seq_file *m, void *p, loff_t *pos)
+{
+ return seq_list_next(p, &slab_caches, pos);
+}
+
+static void s_stop(struct seq_file *m, void *p)
+{
+ up_read(&slqb_lock);
+}
+
+static int s_show(struct seq_file *m, void *p)
+{
+ struct stats_gather stats;
+ struct kmem_cache *s;
+
+ s = list_entry(p, struct kmem_cache, list);
+
+ gather_stats_locked(s, &stats);
+
+ seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", s->name, stats.nr_inuse,
+ stats.nr_objects, s->size, s->objects, (1 << s->order));
+ seq_printf(m, " : tunables %4u %4u %4u", slab_hiwater(s),
+ slab_freebatch(s), 0);
+ seq_printf(m, " : slabdata %6lu %6lu %6lu", stats.nr_slabs,
+ stats.nr_slabs, 0UL);
+ seq_putc(m, '\n');
+ return 0;
+}
+
+static const struct seq_operations slabinfo_op = {
+ .start = s_start,
+ .next = s_next,
+ .stop = s_stop,
+ .show = s_show,
+};
+
+static int slabinfo_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &slabinfo_op);
+}
+
+static const struct file_operations proc_slabinfo_operations = {
+ .open = slabinfo_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static int __init slab_proc_init(void)
+{
+ proc_create("slabinfo", S_IWUSR|S_IRUGO, NULL,
+ &proc_slabinfo_operations);
+ return 0;
+}
+module_init(slab_proc_init);
+#endif /* CONFIG_SLABINFO */
+
+#ifdef CONFIG_SLQB_SYSFS
+/*
+ * sysfs API
+ */
+#define to_slab_attr(n) container_of(n, struct slab_attribute, attr)
+#define to_slab(n) container_of(n, struct kmem_cache, kobj);
+
+struct slab_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct kmem_cache *s, char *buf);
+ ssize_t (*store)(struct kmem_cache *s, const char *x, size_t count);
+};
+
+#define SLAB_ATTR_RO(_name) \
+ static struct slab_attribute _name##_attr = __ATTR_RO(_name)
+
+#define SLAB_ATTR(_name) \
+ static struct slab_attribute _name##_attr = \
+ __ATTR(_name, 0644, _name##_show, _name##_store)
+
+static ssize_t slab_size_show(struct kmem_cache *s, char *buf)
+{
+ return sprintf(buf, "%d\n", s->size);
+}
+SLAB_ATTR_RO(slab_size);
+
+static ssize_t align_show(struct kmem_cache *s, char *buf)
+{
+ return sprintf(buf, "%d\n", s->align);
+}
+SLAB_ATTR_RO(align);
+
+static ssize_t object_size_show(struct kmem_cache *s, char *buf)
+{
+ return sprintf(buf, "%d\n", s->objsize);
+}
+SLAB_ATTR_RO(object_size);
+
+static ssize_t objs_per_slab_show(struct kmem_cache *s, char *buf)
+{
+ return sprintf(buf, "%d\n", s->objects);
+}
+SLAB_ATTR_RO(objs_per_slab);
+
+static ssize_t order_show(struct kmem_cache *s, char *buf)
+{
+ return sprintf(buf, "%d\n", s->order);
+}
+SLAB_ATTR_RO(order);
+
+static ssize_t ctor_show(struct kmem_cache *s, char *buf)
+{
+ if (s->ctor) {
+ int n = sprint_symbol(buf, (unsigned long)s->ctor);
+
+ return n + sprintf(buf + n, "\n");
+ }
+ return 0;
+}
+SLAB_ATTR_RO(ctor);
+
+static ssize_t slabs_show(struct kmem_cache *s, char *buf)
+{
+ struct stats_gather stats;
+
+ gather_stats(s, &stats);
+
+ return sprintf(buf, "%lu\n", stats.nr_slabs);
+}
+SLAB_ATTR_RO(slabs);
+
+static ssize_t objects_show(struct kmem_cache *s, char *buf)
+{
+ struct stats_gather stats;
+
+ gather_stats(s, &stats);
+
+ return sprintf(buf, "%lu\n", stats.nr_inuse);
+}
+SLAB_ATTR_RO(objects);
+
+static ssize_t total_objects_show(struct kmem_cache *s, char *buf)
+{
+ struct stats_gather stats;
+
+ gather_stats(s, &stats);
+
+ return sprintf(buf, "%lu\n", stats.nr_objects);
+}
+SLAB_ATTR_RO(total_objects);
+
+static ssize_t reclaim_account_show(struct kmem_cache *s, char *buf)
+{
+ return sprintf(buf, "%d\n", !!(s->flags & SLAB_RECLAIM_ACCOUNT));
+}
+SLAB_ATTR_RO(reclaim_account);
+
+static ssize_t hwcache_align_show(struct kmem_cache *s, char *buf)
+{
+ return sprintf(buf, "%d\n", !!(s->flags & SLAB_HWCACHE_ALIGN));
+}
+SLAB_ATTR_RO(hwcache_align);
+
+#ifdef CONFIG_ZONE_DMA
+static ssize_t cache_dma_show(struct kmem_cache *s, char *buf)
+{
+ return sprintf(buf, "%d\n", !!(s->flags & SLAB_CACHE_DMA));
+}
+SLAB_ATTR_RO(cache_dma);
+#endif
+
+static ssize_t destroy_by_rcu_show(struct kmem_cache *s, char *buf)
+{
+ return sprintf(buf, "%d\n", !!(s->flags & SLAB_DESTROY_BY_RCU));
+}
+SLAB_ATTR_RO(destroy_by_rcu);
+
+static ssize_t red_zone_show(struct kmem_cache *s, char *buf)
+{
+ return sprintf(buf, "%d\n", !!(s->flags & SLAB_RED_ZONE));
+}
+SLAB_ATTR_RO(red_zone);
+
+static ssize_t poison_show(struct kmem_cache *s, char *buf)
+{
+ return sprintf(buf, "%d\n", !!(s->flags & SLAB_POISON));
+}
+SLAB_ATTR_RO(poison);
+
+static ssize_t store_user_show(struct kmem_cache *s, char *buf)
+{
+ return sprintf(buf, "%d\n", !!(s->flags & SLAB_STORE_USER));
+}
+SLAB_ATTR_RO(store_user);
+
+static ssize_t hiwater_store(struct kmem_cache *s,
+ const char *buf, size_t length)
+{
+ long hiwater;
+ int err;
+
+ err = strict_strtol(buf, 10, &hiwater);
+ if (err)
+ return err;
+
+ if (hiwater < 0)
+ return -EINVAL;
+
+ s->hiwater = hiwater;
+
+ return length;
+}
+
+static ssize_t hiwater_show(struct kmem_cache *s, char *buf)
+{
+ return sprintf(buf, "%d\n", slab_hiwater(s));
+}
+SLAB_ATTR(hiwater);
+
+static ssize_t freebatch_store(struct kmem_cache *s,
+ const char *buf, size_t length)
+{
+ long freebatch;
+ int err;
+
+ err = strict_strtol(buf, 10, &freebatch);
+ if (err)
+ return err;
+
+ if (freebatch <= 0 || freebatch - 1 > s->hiwater)
+ return -EINVAL;
+
+ s->freebatch = freebatch;
+
+ return length;
+}
+
+static ssize_t freebatch_show(struct kmem_cache *s, char *buf)
+{
+ return sprintf(buf, "%d\n", slab_freebatch(s));
+}
+SLAB_ATTR(freebatch);
+
+#ifdef CONFIG_SLQB_STATS
+static int show_stat(struct kmem_cache *s, char *buf, enum stat_item si)
+{
+ struct stats_gather stats;
+ int len;
+#ifdef CONFIG_SMP
+ int cpu;
+#endif
+
+ gather_stats(s, &stats);
+
+ len = sprintf(buf, "%lu", stats.stats[si]);
+
+#ifdef CONFIG_SMP
+ for_each_online_cpu(cpu) {
+ struct kmem_cache_cpu *c = get_cpu_slab(s, cpu);
+ struct kmem_cache_list *l = &c->list;
+
+ if (len < PAGE_SIZE - 20)
+ len += sprintf(buf+len, " C%d=%lu", cpu, l->stats[si]);
+ }
+#endif
+ return len + sprintf(buf + len, "\n");
+}
+
+#define STAT_ATTR(si, text) \
+static ssize_t text##_show(struct kmem_cache *s, char *buf) \
+{ \
+ return show_stat(s, buf, si); \
+} \
+SLAB_ATTR_RO(text); \
+
+STAT_ATTR(ALLOC, alloc);
+STAT_ATTR(ALLOC_SLAB_FILL, alloc_slab_fill);
+STAT_ATTR(ALLOC_SLAB_NEW, alloc_slab_new);
+STAT_ATTR(FREE, free);
+STAT_ATTR(FREE_REMOTE, free_remote);
+STAT_ATTR(FLUSH_FREE_LIST, flush_free_list);
+STAT_ATTR(FLUSH_FREE_LIST_OBJECTS, flush_free_list_objects);
+STAT_ATTR(FLUSH_FREE_LIST_REMOTE, flush_free_list_remote);
+STAT_ATTR(FLUSH_SLAB_PARTIAL, flush_slab_partial);
+STAT_ATTR(FLUSH_SLAB_FREE, flush_slab_free);
+STAT_ATTR(FLUSH_RFREE_LIST, flush_rfree_list);
+STAT_ATTR(FLUSH_RFREE_LIST_OBJECTS, flush_rfree_list_objects);
+STAT_ATTR(CLAIM_REMOTE_LIST, claim_remote_list);
+STAT_ATTR(CLAIM_REMOTE_LIST_OBJECTS, claim_remote_list_objects);
+#endif
+
+static struct attribute *slab_attrs[] = {
+ &slab_size_attr.attr,
+ &object_size_attr.attr,
+ &objs_per_slab_attr.attr,
+ &order_attr.attr,
+ &objects_attr.attr,
+ &total_objects_attr.attr,
+ &slabs_attr.attr,
+ &ctor_attr.attr,
+ &align_attr.attr,
+ &hwcache_align_attr.attr,
+ &reclaim_account_attr.attr,
+ &destroy_by_rcu_attr.attr,
+ &red_zone_attr.attr,
+ &poison_attr.attr,
+ &store_user_attr.attr,
+ &hiwater_attr.attr,
+ &freebatch_attr.attr,
+#ifdef CONFIG_ZONE_DMA
+ &cache_dma_attr.attr,
+#endif
+#ifdef CONFIG_SLQB_STATS
+ &alloc_attr.attr,
+ &alloc_slab_fill_attr.attr,
+ &alloc_slab_new_attr.attr,
+ &free_attr.attr,
+ &free_remote_attr.attr,
+ &flush_free_list_attr.attr,
+ &flush_free_list_objects_attr.attr,
+ &flush_free_list_remote_attr.attr,
+ &flush_slab_partial_attr.attr,
+ &flush_slab_free_attr.attr,
+ &flush_rfree_list_attr.attr,
+ &flush_rfree_list_objects_attr.attr,
+ &claim_remote_list_attr.attr,
+ &claim_remote_list_objects_attr.attr,
+#endif
+ NULL
+};
+
+static struct attribute_group slab_attr_group = {
+ .attrs = slab_attrs,
+};
+
+static ssize_t slab_attr_show(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ struct slab_attribute *attribute;
+ struct kmem_cache *s;
+ int err;
+
+ attribute = to_slab_attr(attr);
+ s = to_slab(kobj);
+
+ if (!attribute->show)
+ return -EIO;
+
+ err = attribute->show(s, buf);
+
+ return err;
+}
+
+static ssize_t slab_attr_store(struct kobject *kobj,
+ struct attribute *attr, const char *buf, size_t len)
+{
+ struct slab_attribute *attribute;
+ struct kmem_cache *s;
+ int err;
+
+ attribute = to_slab_attr(attr);
+ s = to_slab(kobj);
+
+ if (!attribute->store)
+ return -EIO;
+
+ err = attribute->store(s, buf, len);
+
+ return err;
+}
+
+static void kmem_cache_release(struct kobject *kobj)
+{
+ struct kmem_cache *s = to_slab(kobj);
+
+ kmem_cache_free(&kmem_cache_cache, s);
+}
+
+static struct sysfs_ops slab_sysfs_ops = {
+ .show = slab_attr_show,
+ .store = slab_attr_store,
+};
+
+static struct kobj_type slab_ktype = {
+ .sysfs_ops = &slab_sysfs_ops,
+ .release = kmem_cache_release
+};
+
+static int uevent_filter(struct kset *kset, struct kobject *kobj)
+{
+ struct kobj_type *ktype = get_ktype(kobj);
+
+ if (ktype == &slab_ktype)
+ return 1;
+ return 0;
+}
+
+static struct kset_uevent_ops slab_uevent_ops = {
+ .filter = uevent_filter,
+};
+
+static struct kset *slab_kset;
+
+static int sysfs_available __read_mostly;
+
+static int sysfs_slab_add(struct kmem_cache *s)
+{
+ int err;
+
+ if (!sysfs_available)
+ return 0;
+
+ s->kobj.kset = slab_kset;
+ err = kobject_init_and_add(&s->kobj, &slab_ktype, NULL, s->name);
+ if (err) {
+ kobject_put(&s->kobj);
+ return err;
+ }
+
+ err = sysfs_create_group(&s->kobj, &slab_attr_group);
+ if (err)
+ return err;
+
+ kobject_uevent(&s->kobj, KOBJ_ADD);
+
+ return 0;
+}
+
+static void sysfs_slab_remove(struct kmem_cache *s)
+{
+ kobject_uevent(&s->kobj, KOBJ_REMOVE);
+ kobject_del(&s->kobj);
+ kobject_put(&s->kobj);
+}
+
+static int __init slab_sysfs_init(void)
+{
+ struct kmem_cache *s;
+ int err;
+
+ slab_kset = kset_create_and_add("slab", &slab_uevent_ops, kernel_kobj);
+ if (!slab_kset) {
+ printk(KERN_ERR "Cannot register slab subsystem.\n");
+ return -ENOSYS;
+ }
+
+ down_write(&slqb_lock);
+
+ sysfs_available = 1;
+
+ list_for_each_entry(s, &slab_caches, list) {
+ err = sysfs_slab_add(s);
+ if (err)
+ printk(KERN_ERR "SLQB: Unable to add boot slab %s"
+ " to sysfs\n", s->name);
+ }
+
+ up_write(&slqb_lock);
+
+ return 0;
+}
+device_initcall(slab_sysfs_init);
+
+#endif
diff --git a/mm/slub.c b/mm/slub.c
index 7ab54ecbd3f3..6674a7907b0c 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -9,6 +9,7 @@
*/
#include <linux/mm.h>
+#include <linux/swap.h> /* struct reclaim_state */
#include <linux/module.h>
#include <linux/bit_spinlock.h>
#include <linux/interrupt.h>
@@ -16,9 +17,10 @@
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
-#include <trace/kmemtrace.h>
+#include <linux/kmemtrace.h>
#include <linux/cpu.h>
#include <linux/cpuset.h>
+#include <linux/kmemleak.h>
#include <linux/mempolicy.h>
#include <linux/ctype.h>
#include <linux/debugobjects.h>
@@ -142,7 +144,7 @@
* Set of flags that will prevent slab merging
*/
#define SLUB_NEVER_MERGE (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \
- SLAB_TRACE | SLAB_DESTROY_BY_RCU)
+ SLAB_TRACE | SLAB_DESTROY_BY_RCU | SLAB_NOLEAKTRACE)
#define SLUB_MERGE_SAME (SLAB_DEBUG_FREE | SLAB_RECLAIM_ACCOUNT | \
SLAB_CACHE_DMA)
@@ -1170,6 +1172,8 @@ static void __free_slab(struct kmem_cache *s, struct page *page)
__ClearPageSlab(page);
reset_page_mapcount(page);
+ if (current->reclaim_state)
+ current->reclaim_state->reclaimed_slab += pages;
__free_pages(page, order);
}
@@ -1614,6 +1618,7 @@ static __always_inline void *slab_alloc(struct kmem_cache *s,
if (unlikely((gfpflags & __GFP_ZERO) && object))
memset(object, 0, objsize);
+ kmemleak_alloc_recursive(object, objsize, 1, s->flags, gfpflags);
return object;
}
@@ -1743,6 +1748,7 @@ static __always_inline void slab_free(struct kmem_cache *s,
struct kmem_cache_cpu *c;
unsigned long flags;
+ kmemleak_free_recursive(x, s->flags);
local_irq_save(flags);
c = get_cpu_slab(s, smp_processor_id());
debug_check_no_locks_freed(object, c->objsize);
@@ -1909,7 +1915,7 @@ static inline int calculate_order(int size)
* Doh this slab cannot be placed using slub_max_order.
*/
order = slab_order(size, 1, MAX_ORDER, 1);
- if (order <= MAX_ORDER)
+ if (order < MAX_ORDER)
return order;
return -ENOSYS;
}
@@ -2522,6 +2528,7 @@ __setup("slub_min_order=", setup_slub_min_order);
static int __init setup_slub_max_order(char *str)
{
get_option(&str, &slub_max_order);
+ slub_max_order = min(slub_max_order, MAX_ORDER - 1);
return 1;
}
diff --git a/mm/swap.c b/mm/swap.c
index bede23ce64ea..cb29ae5d33ab 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -491,49 +491,6 @@ unsigned pagevec_lookup_tag(struct pagevec *pvec, struct address_space *mapping,
EXPORT_SYMBOL(pagevec_lookup_tag);
-#ifdef CONFIG_SMP
-/*
- * We tolerate a little inaccuracy to avoid ping-ponging the counter between
- * CPUs
- */
-#define ACCT_THRESHOLD max(16, NR_CPUS * 2)
-
-static DEFINE_PER_CPU(long, committed_space);
-
-void vm_acct_memory(long pages)
-{
- long *local;
-
- preempt_disable();
- local = &__get_cpu_var(committed_space);
- *local += pages;
- if (*local > ACCT_THRESHOLD || *local < -ACCT_THRESHOLD) {
- atomic_long_add(*local, &vm_committed_space);
- *local = 0;
- }
- preempt_enable();
-}
-
-#ifdef CONFIG_HOTPLUG_CPU
-
-/* Drop the CPU's cached committed space back into the central pool. */
-static int cpu_swap_callback(struct notifier_block *nfb,
- unsigned long action,
- void *hcpu)
-{
- long *committed;
-
- committed = &per_cpu(committed_space, (long)hcpu);
- if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
- atomic_long_add(*committed, &vm_committed_space);
- *committed = 0;
- drain_cpu_pagevecs((long)hcpu);
- }
- return NOTIFY_OK;
-}
-#endif /* CONFIG_HOTPLUG_CPU */
-#endif /* CONFIG_SMP */
-
/*
* Perform any setup for the swap system
*/
@@ -554,7 +511,4 @@ void __init swap_setup(void)
* Right now other parts of the system means that we
* _really_ don't want to cluster much more
*/
-#ifdef CONFIG_HOTPLUG_CPU
- hotcpu_notifier(cpu_swap_callback, 0);
-#endif
}
diff --git a/mm/util.c b/mm/util.c
index 2599e83eea17..abc65aa7cdfc 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -4,9 +4,11 @@
#include <linux/module.h>
#include <linux/err.h>
#include <linux/sched.h>
-#include <linux/tracepoint.h>
#include <asm/uaccess.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/kmem.h>
+
/**
* kstrdup - allocate space for and copy an existing string
* @s: the string to duplicate
@@ -223,6 +225,22 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
}
#endif
+/**
+ * get_user_pages_fast() - pin user pages in memory
+ * @start: starting user address
+ * @nr_pages: number of pages from start to pin
+ * @write: whether pages will be written to
+ * @pages: array that receives pointers to the pages pinned.
+ * Should be at least nr_pages long.
+ *
+ * Attempt to pin user pages in memory without taking mm->mmap_sem.
+ * If not successful, it will fall back to taking the lock and
+ * calling get_user_pages().
+ *
+ * Returns number of pages pinned. This may be fewer than the number
+ * requested. If nr_pages is 0 or negative, returns 0. If no pages
+ * were pinned, returns -errno.
+ */
int __attribute__((weak)) get_user_pages_fast(unsigned long start,
int nr_pages, int write, struct page **pages)
{
@@ -239,13 +257,6 @@ int __attribute__((weak)) get_user_pages_fast(unsigned long start,
EXPORT_SYMBOL_GPL(get_user_pages_fast);
/* Tracepoints definitions. */
-DEFINE_TRACE(kmalloc);
-DEFINE_TRACE(kmem_cache_alloc);
-DEFINE_TRACE(kmalloc_node);
-DEFINE_TRACE(kmem_cache_alloc_node);
-DEFINE_TRACE(kfree);
-DEFINE_TRACE(kmem_cache_free);
-
EXPORT_TRACEPOINT_SYMBOL(kmalloc);
EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc);
EXPORT_TRACEPOINT_SYMBOL(kmalloc_node);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index fab19876b4d1..b7db93572797 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -25,6 +25,7 @@
#include <linux/rcupdate.h>
#include <linux/bootmem.h>
#include <linux/pfn.h>
+#include <linux/kmemleak.h>
#include <asm/atomic.h>
#include <asm/uaccess.h>
@@ -402,6 +403,7 @@ overflow:
printk(KERN_WARNING
"vmap allocation for size %lu failed: "
"use vmalloc=<size> to increase size.\n", size);
+ kfree(va);
return ERR_PTR(-EBUSY);
}
@@ -1326,6 +1328,9 @@ static void __vunmap(const void *addr, int deallocate_pages)
void vfree(const void *addr)
{
BUG_ON(in_interrupt());
+
+ kmemleak_free(addr);
+
__vunmap(addr, 1);
}
EXPORT_SYMBOL(vfree);
@@ -1438,8 +1443,17 @@ fail:
void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask, pgprot_t prot)
{
- return __vmalloc_area_node(area, gfp_mask, prot, -1,
- __builtin_return_address(0));
+ void *addr = __vmalloc_area_node(area, gfp_mask, prot, -1,
+ __builtin_return_address(0));
+
+ /*
+ * A ref_count = 3 is needed because the vm_struct and vmap_area
+ * structures allocated in the __get_vm_area_node() function contain
+ * references to the virtual address of the vmalloc'ed block.
+ */
+ kmemleak_alloc(addr, area->size - PAGE_SIZE, 3, gfp_mask);
+
+ return addr;
}
/**
@@ -1458,6 +1472,8 @@ static void *__vmalloc_node(unsigned long size, gfp_t gfp_mask, pgprot_t prot,
int node, void *caller)
{
struct vm_struct *area;
+ void *addr;
+ unsigned long real_size = size;
size = PAGE_ALIGN(size);
if (!size || (size >> PAGE_SHIFT) > num_physpages)
@@ -1469,7 +1485,16 @@ static void *__vmalloc_node(unsigned long size, gfp_t gfp_mask, pgprot_t prot,
if (!area)
return NULL;
- return __vmalloc_area_node(area, gfp_mask, prot, node, caller);
+ addr = __vmalloc_area_node(area, gfp_mask, prot, node, caller);
+
+ /*
+ * A ref_count = 3 is needed because the vm_struct and vmap_area
+ * structures allocated in the __get_vm_area_node() function contain
+ * references to the virtual address of the vmalloc'ed block.
+ */
+ kmemleak_alloc(addr, real_size, 3, gfp_mask);
+
+ return addr;
}
void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 39fdfb14eeaa..5fa3eda1f03f 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -63,6 +63,9 @@ struct scan_control {
/* Can mapped pages be reclaimed? */
int may_unmap;
+ /* Can pages be swapped as part of reclaim? */
+ int may_swap;
+
/* This context's SWAP_CLUSTER_MAX. If freeing memory for
* suspend, we effectively ignore SWAP_CLUSTER_MAX.
* In this context, it doesn't matter that we scan the
@@ -1380,7 +1383,7 @@ static void get_scan_ratio(struct zone *zone, struct scan_control *sc,
struct zone_reclaim_stat *reclaim_stat = get_reclaim_stat(zone, sc);
/* If we have no swap space, do not bother scanning anon pages. */
- if (nr_swap_pages <= 0) {
+ if (!sc->may_swap || (nr_swap_pages <= 0)) {
percent[0] = 0;
percent[1] = 100;
return;
@@ -1468,7 +1471,7 @@ static void shrink_zone(int priority, struct zone *zone,
for_each_evictable_lru(l) {
int file = is_file_lru(l);
- int scan;
+ unsigned long scan;
scan = zone_nr_pages(zone, sc, l);
if (priority) {
@@ -1697,6 +1700,7 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
.may_writepage = !laptop_mode,
.swap_cluster_max = SWAP_CLUSTER_MAX,
.may_unmap = 1,
+ .may_swap = 1,
.swappiness = vm_swappiness,
.order = order,
.mem_cgroup = NULL,
@@ -1717,6 +1721,7 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont,
struct scan_control sc = {
.may_writepage = !laptop_mode,
.may_unmap = 1,
+ .may_swap = !noswap,
.swap_cluster_max = SWAP_CLUSTER_MAX,
.swappiness = swappiness,
.order = 0,
@@ -1726,9 +1731,6 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont,
};
struct zonelist *zonelist;
- if (noswap)
- sc.may_unmap = 0;
-
sc.gfp_mask = (gfp_mask & GFP_RECLAIM_MASK) |
(GFP_HIGHUSER_MOVABLE & ~GFP_RECLAIM_MASK);
zonelist = NODE_DATA(numa_node_id())->node_zonelists;
@@ -1767,6 +1769,7 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order)
struct scan_control sc = {
.gfp_mask = GFP_KERNEL,
.may_unmap = 1,
+ .may_swap = 1,
.swap_cluster_max = SWAP_CLUSTER_MAX,
.swappiness = vm_swappiness,
.order = order,
@@ -2088,13 +2091,13 @@ static void shrink_all_zones(unsigned long nr_pages, int prio,
nr_reclaimed += shrink_list(l, nr_to_scan, zone,
sc, prio);
if (nr_reclaimed >= nr_pages) {
- sc->nr_reclaimed = nr_reclaimed;
+ sc->nr_reclaimed += nr_reclaimed;
return;
}
}
}
}
- sc->nr_reclaimed = nr_reclaimed;
+ sc->nr_reclaimed += nr_reclaimed;
}
/*
@@ -2115,6 +2118,7 @@ unsigned long shrink_all_memory(unsigned long nr_pages)
.may_unmap = 0,
.may_writepage = 1,
.isolate_pages = isolate_pages_global,
+ .nr_reclaimed = 0,
};
current->reclaim_state = &reclaim_state;
@@ -2297,6 +2301,7 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
struct scan_control sc = {
.may_writepage = !!(zone_reclaim_mode & RECLAIM_WRITE),
.may_unmap = !!(zone_reclaim_mode & RECLAIM_SWAP),
+ .may_swap = 1,
.swap_cluster_max = max_t(unsigned long, nr_pages,
SWAP_CLUSTER_MAX),
.gfp_mask = gfp_mask,
diff --git a/net/9p/client.c b/net/9p/client.c
index 1eb580c38fbb..dd43a8289b0d 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -203,7 +203,6 @@ static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
p9pdu_reset(req->tc);
p9pdu_reset(req->rc);
- req->flush_tag = 0;
req->tc->tag = tag-1;
req->status = REQ_STATUS_ALLOC;
@@ -324,35 +323,9 @@ static void p9_free_req(struct p9_client *c, struct p9_req_t *r)
*/
void p9_client_cb(struct p9_client *c, struct p9_req_t *req)
{
- struct p9_req_t *other_req;
- unsigned long flags;
-
P9_DPRINTK(P9_DEBUG_MUX, " tag %d\n", req->tc->tag);
-
- if (req->status == REQ_STATUS_ERROR)
- wake_up(req->wq);
-
- if (req->flush_tag) { /* flush receive path */
- P9_DPRINTK(P9_DEBUG_9P, "<<< RFLUSH %d\n", req->tc->tag);
- spin_lock_irqsave(&c->lock, flags);
- other_req = p9_tag_lookup(c, req->flush_tag);
- if (other_req->status != REQ_STATUS_FLSH) /* stale flush */
- spin_unlock_irqrestore(&c->lock, flags);
- else {
- other_req->status = REQ_STATUS_FLSHD;
- spin_unlock_irqrestore(&c->lock, flags);
- wake_up(other_req->wq);
- }
- p9_free_req(c, req);
- } else { /* normal receive path */
- P9_DPRINTK(P9_DEBUG_MUX, "normal: tag %d\n", req->tc->tag);
- spin_lock_irqsave(&c->lock, flags);
- if (req->status != REQ_STATUS_FLSHD)
- req->status = REQ_STATUS_RCVD;
- spin_unlock_irqrestore(&c->lock, flags);
- wake_up(req->wq);
- P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag);
- }
+ wake_up(req->wq);
+ P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag);
}
EXPORT_SYMBOL(p9_client_cb);
@@ -486,9 +459,15 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
if (IS_ERR(req))
return PTR_ERR(req);
- req->flush_tag = oldtag;
- /* we don't free anything here because RPC isn't complete */
+ /* if we haven't received a response for oldreq,
+ remove it from the list. */
+ spin_lock(&c->lock);
+ if (oldreq->status == REQ_STATUS_FLSH)
+ list_del(&oldreq->req_list);
+ spin_unlock(&c->lock);
+
+ p9_free_req(c, req);
return 0;
}
@@ -509,7 +488,6 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
struct p9_req_t *req;
unsigned long flags;
int sigpending;
- int flushed = 0;
P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type);
@@ -546,42 +524,28 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
goto reterr;
}
- /* if it was a flush we just transmitted, return our tag */
- if (type == P9_TFLUSH)
- return req;
-again:
P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d\n", req->wq, tag);
err = wait_event_interruptible(*req->wq,
req->status >= REQ_STATUS_RCVD);
- P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d (flushed=%d)\n",
- req->wq, tag, err, flushed);
+ P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d\n",
+ req->wq, tag, err);
if (req->status == REQ_STATUS_ERROR) {
P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
err = req->t_err;
- } else if (err == -ERESTARTSYS && flushed) {
- P9_DPRINTK(P9_DEBUG_MUX, "flushed - going again\n");
- goto again;
- } else if (req->status == REQ_STATUS_FLSHD) {
- P9_DPRINTK(P9_DEBUG_MUX, "flushed - erestartsys\n");
- err = -ERESTARTSYS;
}
- if ((err == -ERESTARTSYS) && (c->status == Connected) && (!flushed)) {
+ if ((err == -ERESTARTSYS) && (c->status == Connected)) {
P9_DPRINTK(P9_DEBUG_MUX, "flushing\n");
- spin_lock_irqsave(&c->lock, flags);
- if (req->status == REQ_STATUS_SENT)
- req->status = REQ_STATUS_FLSH;
- spin_unlock_irqrestore(&c->lock, flags);
sigpending = 1;
- flushed = 1;
clear_thread_flag(TIF_SIGPENDING);
- if (c->trans_mod->cancel(c, req)) {
- err = p9_client_flush(c, req);
- if (err == 0)
- goto again;
- }
+ if (c->trans_mod->cancel(c, req))
+ p9_client_flush(c, req);
+
+ /* if we received the response anyway, don't signal error */
+ if (req->status == REQ_STATUS_RCVD)
+ err = 0;
}
if (sigpending) {
@@ -1244,19 +1208,53 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid)
ret->name, ret->uid, ret->gid, ret->muid, ret->extension,
ret->n_uid, ret->n_gid, ret->n_muid);
+ p9_free_req(clnt, req);
+ return ret;
+
free_and_error:
p9_free_req(clnt, req);
error:
- return ret;
+ kfree(ret);
+ return ERR_PTR(err);
}
EXPORT_SYMBOL(p9_client_stat);
+static int p9_client_statsize(struct p9_wstat *wst, int optional)
+{
+ int ret;
+
+ /* size[2] type[2] dev[4] qid[13] */
+ /* mode[4] atime[4] mtime[4] length[8]*/
+ /* name[s] uid[s] gid[s] muid[s] */
+ ret = 2+2+4+13+4+4+4+8+2+2+2+2;
+
+ if (wst->name)
+ ret += strlen(wst->name);
+ if (wst->uid)
+ ret += strlen(wst->uid);
+ if (wst->gid)
+ ret += strlen(wst->gid);
+ if (wst->muid)
+ ret += strlen(wst->muid);
+
+ if (optional) {
+ ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */
+ if (wst->extension)
+ ret += strlen(wst->extension);
+ }
+
+ return ret;
+}
+
int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
{
int err;
struct p9_req_t *req;
struct p9_client *clnt;
+ err = 0;
+ clnt = fid->clnt;
+ wst->size = p9_client_statsize(wst, clnt->dotu);
P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid);
P9_DPRINTK(P9_DEBUG_9P,
" sz=%x type=%x dev=%x qid=%x.%llx.%x\n"
@@ -1268,10 +1266,8 @@ int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
wst->atime, wst->mtime, (unsigned long long)wst->length,
wst->name, wst->uid, wst->gid, wst->muid, wst->extension,
wst->n_uid, wst->n_gid, wst->n_muid);
- err = 0;
- clnt = fid->clnt;
- req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, 0, wst);
+ req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size, wst);
if (IS_ERR(req)) {
err = PTR_ERR(req);
goto error;
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index c613ed08a5ee..a2a1814c7a8d 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -213,8 +213,8 @@ static void p9_conn_cancel(struct p9_conn *m, int err)
spin_unlock_irqrestore(&m->client->lock, flags);
list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) {
- list_del(&req->req_list);
P9_DPRINTK(P9_DEBUG_ERROR, "call back req %p\n", req);
+ list_del(&req->req_list);
p9_client_cb(m->client, req);
}
}
@@ -336,7 +336,8 @@ static void p9_read_work(struct work_struct *work)
"mux %p pkt: size: %d bytes tag: %d\n", m, n, tag);
m->req = p9_tag_lookup(m->client, tag);
- if (!m->req) {
+ if (!m->req || (m->req->status != REQ_STATUS_SENT &&
+ m->req->status != REQ_STATUS_FLSH)) {
P9_DPRINTK(P9_DEBUG_ERROR, "Unexpected packet tag %d\n",
tag);
err = -EIO;
@@ -361,10 +362,11 @@ static void p9_read_work(struct work_struct *work)
if ((m->req) && (m->rpos == m->rsize)) { /* packet is read in */
P9_DPRINTK(P9_DEBUG_TRANS, "got new packet\n");
spin_lock(&m->client->lock);
+ if (m->req->status != REQ_STATUS_ERROR)
+ m->req->status = REQ_STATUS_RCVD;
list_del(&m->req->req_list);
spin_unlock(&m->client->lock);
p9_client_cb(m->client, m->req);
-
m->rbuf = NULL;
m->rpos = 0;
m->rsize = 0;
@@ -454,6 +456,7 @@ static void p9_write_work(struct work_struct *work)
req = list_entry(m->unsent_req_list.next, struct p9_req_t,
req_list);
req->status = REQ_STATUS_SENT;
+ P9_DPRINTK(P9_DEBUG_TRANS, "move req %p\n", req);
list_move_tail(&req->req_list, &m->req_list);
m->wbuf = req->tc->sdata;
@@ -683,12 +686,13 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req)
P9_DPRINTK(P9_DEBUG_TRANS, "client %p req %p\n", client, req);
spin_lock(&client->lock);
- list_del(&req->req_list);
if (req->status == REQ_STATUS_UNSENT) {
+ list_del(&req->req_list);
req->status = REQ_STATUS_FLSHD;
ret = 0;
- }
+ } else if (req->status == REQ_STATUS_SENT)
+ req->status = REQ_STATUS_FLSH;
spin_unlock(&client->lock);
diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c
index 7fa0eb20b2f6..ac4990041ebb 100644
--- a/net/9p/trans_rdma.c
+++ b/net/9p/trans_rdma.c
@@ -295,6 +295,7 @@ handle_recv(struct p9_client *client, struct p9_trans_rdma *rdma,
goto err_out;
req->rc = c->rc;
+ req->status = REQ_STATUS_RCVD;
p9_client_cb(client, req);
return;
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index 2d7781ec663b..bb8579a141a8 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -134,6 +134,7 @@ static void req_done(struct virtqueue *vq)
P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc);
P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag);
req = p9_tag_lookup(chan->client, rc->tag);
+ req->status = REQ_STATUS_RCVD;
p9_client_cb(chan->client, req);
}
}
diff --git a/net/core/dev.c b/net/core/dev.c
index 637ea71b0a0d..14dd725aaab7 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5007,13 +5007,16 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
if (!tx) {
printk(KERN_ERR "alloc_netdev: Unable to allocate "
"tx qdiscs.\n");
- kfree(p);
- return NULL;
+ goto free_p;
}
dev = (struct net_device *)
(((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
dev->padded = (char *)dev - (char *)p;
+
+ if (dev_addr_init(dev))
+ goto free_tx;
+
dev_net_set(dev, &init_net);
dev->_tx = tx;
@@ -5022,13 +5025,19 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
dev->gso_max_size = GSO_MAX_SIZE;
- dev_addr_init(dev);
netdev_init_queues(dev);
INIT_LIST_HEAD(&dev->napi_list);
setup(dev);
strcpy(dev->name, name);
return dev;
+
+free_tx:
+ kfree(tx);
+
+free_p:
+ kfree(p);
+ return NULL;
}
EXPORT_SYMBOL(alloc_netdev_mq);
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
index 2797b711a978..7668ff543123 100644
--- a/net/core/drop_monitor.c
+++ b/net/core/drop_monitor.c
@@ -23,7 +23,7 @@
#include <linux/bitops.h>
#include <net/genetlink.h>
-#include <trace/skb.h>
+#include <trace/events/skb.h>
#include <asm/unaligned.h>
diff --git a/net/core/net-traces.c b/net/core/net-traces.c
index c8fb45665e4f..499a67eaf3ae 100644
--- a/net/core/net-traces.c
+++ b/net/core/net-traces.c
@@ -19,11 +19,11 @@
#include <linux/workqueue.h>
#include <linux/netlink.h>
#include <linux/net_dropmon.h>
-#include <trace/skb.h>
#include <asm/unaligned.h>
#include <asm/bitops.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/skb.h>
-DEFINE_TRACE(kfree_skb);
EXPORT_TRACEPOINT_SYMBOL_GPL(kfree_skb);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index d152394b2611..c4906bbcd60e 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -65,7 +65,7 @@
#include <asm/uaccess.h>
#include <asm/system.h>
-#include <trace/skb.h>
+#include <trace/events/skb.h>
#include "kmap_skb.h"
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
index 5d8a2a56fd39..932408dca86d 100644
--- a/net/decnet/dn_nsp_in.c
+++ b/net/decnet/dn_nsp_in.c
@@ -578,6 +578,7 @@ out:
static __inline__ int dn_queue_skb(struct sock *sk, struct sk_buff *skb, int sig, struct sk_buff_head *queue)
{
int err;
+ int skb_len;
/* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
number of warnings when compiling with -W --ANK
@@ -592,22 +593,12 @@ static __inline__ int dn_queue_skb(struct sock *sk, struct sk_buff *skb, int sig
if (err)
goto out;
+ skb_len = skb->len;
skb_set_owner_r(skb, sk);
skb_queue_tail(queue, skb);
- /* This code only runs from BH or BH protected context.
- * Therefore the plain read_lock is ok here. -DaveM
- */
- read_lock(&sk->sk_callback_lock);
- if (!sock_flag(sk, SOCK_DEAD)) {
- struct socket *sock = sk->sk_socket;
- wake_up_interruptible(sk->sk_sleep);
- if (sock && sock->fasync_list &&
- !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
- __kill_fasync(sock->fasync_list, sig,
- (sig == SIGURG) ? POLL_PRI : POLL_IN);
- }
- read_unlock(&sk->sk_callback_lock);
+ if (!sock_flag(sk, SOCK_DEAD))
+ sk->sk_data_ready(sk, skb_len);
out:
return err;
}
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index b2cf91e4ccaa..9d26a3da37e5 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -407,7 +407,7 @@ config INET_XFRM_MODE_BEET
If unsure, say Y.
config INET_LRO
- tristate "Large Receive Offload (ipv4/tcp)"
+ bool "Large Receive Offload (ipv4/tcp)"
---help---
Support for Large Receive Offload (ipv4/tcp).
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index d0ca6da33ca9..be86e159e6ef 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -112,7 +112,7 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
}
static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
- u8 key_idx, u8 *mac_addr,
+ u8 key_idx, const u8 *mac_addr,
struct key_params *params)
{
struct ieee80211_sub_if_data *sdata;
@@ -166,7 +166,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
}
static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
- u8 key_idx, u8 *mac_addr)
+ u8 key_idx, const u8 *mac_addr)
{
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
@@ -208,7 +208,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
}
static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
- u8 key_idx, u8 *mac_addr, void *cookie,
+ u8 key_idx, const u8 *mac_addr, void *cookie,
void (*callback)(void *cookie,
struct key_params *params))
{
@@ -1253,6 +1253,14 @@ static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev,
if (ret)
return ret;
+ if (req->use_mfp) {
+ sdata->u.mgd.mfp = IEEE80211_MFP_REQUIRED;
+ sdata->u.mgd.flags |= IEEE80211_STA_MFP_ENABLED;
+ } else {
+ sdata->u.mgd.mfp = IEEE80211_MFP_DISABLED;
+ sdata->u.mgd.flags &= ~IEEE80211_STA_MFP_ENABLED;
+ }
+
sdata->u.mgd.flags |= IEEE80211_STA_EXT_SME;
sdata->u.mgd.state = IEEE80211_STA_MLME_ASSOCIATE;
ieee80211_sta_req_auth(sdata);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 03e0d22603c8..081c57427308 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -427,6 +427,12 @@ struct ieee80211_sub_if_data {
int drop_unencrypted;
+ /*
+ * keep track of whether the HT opmode (stored in
+ * vif.bss_info.ht_operation_mode) is valid.
+ */
+ bool ht_opmode_valid;
+
/* Fragment table for host-based reassembly */
struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX];
unsigned int fragment_next;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 8b6daf0219f4..8c9f1c722cdb 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -964,5 +964,6 @@ void ieee80211_recalc_idle(struct ieee80211_local *local)
mutex_lock(&local->iflist_mtx);
chg = __ieee80211_recalc_idle(local);
mutex_unlock(&local->iflist_mtx);
- ieee80211_hw_config(local, chg);
+ if (chg)
+ ieee80211_hw_config(local, chg);
}
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index b80bc80e46cf..76df5eabf268 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -154,15 +154,17 @@ static void ieee80211_master_set_multicast_list(struct net_device *dev)
int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
{
- struct ieee80211_channel *chan;
+ struct ieee80211_channel *chan, *scan_chan;
int ret = 0;
int power;
enum nl80211_channel_type channel_type;
might_sleep();
- if (local->sw_scanning) {
- chan = local->scan_channel;
+ scan_chan = local->scan_channel;
+
+ if (scan_chan) {
+ chan = scan_chan;
channel_type = NL80211_CHAN_NO_HT;
} else {
chan = local->oper_channel;
@@ -176,7 +178,7 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
changed |= IEEE80211_CONF_CHANGE_CHANNEL;
}
- if (local->sw_scanning)
+ if (scan_chan)
power = chan->max_power;
else
power = local->power_constr_level ?
@@ -859,8 +861,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
if (!local->oper_channel) {
/* init channel we're on */
local->hw.conf.channel =
- local->oper_channel =
- local->scan_channel = &sband->channels[0];
+ local->oper_channel = &sband->channels[0];
+ local->hw.conf.channel_type = NL80211_CHAN_NO_HT;
}
channels += sband->n_channels;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 75c487229f2e..6d00e3f738c0 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -95,16 +95,14 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
struct ieee80211_supported_band *sband;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- struct ieee80211_bss_ht_conf ht;
struct sta_info *sta;
u32 changed = 0;
+ u16 ht_opmode;
bool enable_ht = true, ht_changed;
enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
- memset(&ht, 0, sizeof(ht));
-
/* HT is not supported */
if (!sband->ht_cap.ht_supported)
enable_ht = false;
@@ -148,19 +146,20 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
IEEE80211_RC_HT_CHANGED);
rcu_read_unlock();
-
}
/* disable HT */
if (!enable_ht)
return 0;
- ht.operation_mode = le16_to_cpu(hti->operation_mode);
+ ht_opmode = le16_to_cpu(hti->operation_mode);
/* if bss configuration changed store the new one */
- if (memcmp(&sdata->vif.bss_conf.ht, &ht, sizeof(ht))) {
+ if (!sdata->ht_opmode_valid ||
+ sdata->vif.bss_conf.ht_operation_mode != ht_opmode) {
changed |= BSS_CHANGED_HT;
- sdata->vif.bss_conf.ht = ht;
+ sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
+ sdata->ht_opmode_valid = true;
}
return changed;
@@ -1043,11 +1042,16 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
rcu_read_unlock();
+ ieee80211_set_wmm_default(sdata);
+
ieee80211_recalc_idle(local);
/* channel(_type) changes are handled by ieee80211_hw_config */
local->oper_channel_type = NL80211_CHAN_NO_HT;
+ /* on the next assoc, re-program HT parameters */
+ sdata->ht_opmode_valid = false;
+
local->power_constr_level = 0;
del_timer_sync(&local->dynamic_ps_timer);
@@ -1658,6 +1662,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
if (elems.wmm_param)
ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param,
elems.wmm_param_len);
+ else
+ ieee80211_set_wmm_default(sdata);
if (elems.ht_info_elem && elems.wmm_param &&
(ifmgd->flags & IEEE80211_STA_WMM_ENABLED) &&
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index efaf38349731..0a11515341ba 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -479,7 +479,7 @@ minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
sband = hw->wiphy->bands[i];
- if (sband->n_bitrates > max_rates)
+ if (sband && sband->n_bitrates > max_rates)
max_rates = sband->n_bitrates;
}
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c
index 6704fb55c6b2..a0bef767ceb5 100644
--- a/net/mac80211/rc80211_pid_algo.c
+++ b/net/mac80211/rc80211_pid_algo.c
@@ -380,7 +380,7 @@ static void *rate_control_pid_alloc(struct ieee80211_hw *hw,
for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
sband = hw->wiphy->bands[i];
- if (sband->n_bitrates > max_rates)
+ if (sband && sband->n_bitrates > max_rates)
max_rates = sband->n_bitrates;
}
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index d052f4004829..f962bd1b16e2 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -630,15 +630,6 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
* possible.
*/
- if (!ieee80211_has_protected(hdr->frame_control)) {
- if (!ieee80211_is_mgmt(hdr->frame_control) ||
- rx->sta == NULL || !test_sta_flags(rx->sta, WLAN_STA_MFP))
- return RX_CONTINUE;
- mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb);
- if (mmie_keyidx < 0)
- return RX_CONTINUE;
- }
-
/*
* No point in finding a key and decrypting if the frame is neither
* addressed to us nor a multicast frame.
@@ -649,8 +640,14 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
if (rx->sta)
stakey = rcu_dereference(rx->sta->key);
+ if (!ieee80211_has_protected(hdr->frame_control))
+ mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb);
+
if (!is_multicast_ether_addr(hdr->addr1) && stakey) {
rx->key = stakey;
+ /* Skip decryption if the frame is not protected. */
+ if (!ieee80211_has_protected(hdr->frame_control))
+ return RX_CONTINUE;
} else if (mmie_keyidx >= 0) {
/* Broadcast/multicast robust management frame / BIP */
if ((rx->status->flag & RX_FLAG_DECRYPTED) &&
@@ -661,6 +658,21 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
return RX_DROP_MONITOR; /* unexpected BIP keyidx */
rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]);
+ } else if (!ieee80211_has_protected(hdr->frame_control)) {
+ /*
+ * The frame was not protected, so skip decryption. However, we
+ * need to set rx->key if there is a key that could have been
+ * used so that the frame may be dropped if encryption would
+ * have been expected.
+ */
+ struct ieee80211_key *key = NULL;
+ if (ieee80211_is_mgmt(hdr->frame_control) &&
+ is_multicast_ether_addr(hdr->addr1) &&
+ (key = rcu_dereference(rx->sdata->default_mgmt_key)))
+ rx->key = key;
+ else if ((key = rcu_dereference(rx->sdata->default_key)))
+ rx->key = key;
+ return RX_CONTINUE;
} else {
/*
* The device doesn't give us the IV so we won't be
@@ -1209,17 +1221,27 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
/* Drop unencrypted frames if key is set. */
if (unlikely(!ieee80211_has_protected(fc) &&
!ieee80211_is_nullfunc(fc) &&
- (!ieee80211_is_mgmt(fc) ||
- (ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
- rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP))) &&
- (rx->key || rx->sdata->drop_unencrypted)))
- return -EACCES;
- /* BIP does not use Protected field, so need to check MMIE */
- if (unlikely(rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP) &&
- ieee80211_is_multicast_robust_mgmt_frame(rx->skb) &&
- ieee80211_get_mmie_keyidx(rx->skb) < 0 &&
+ ieee80211_is_data(fc) &&
(rx->key || rx->sdata->drop_unencrypted)))
return -EACCES;
+ if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) {
+ if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
+ rx->key))
+ return -EACCES;
+ /* BIP does not use Protected field, so need to check MMIE */
+ if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb)
+ && ieee80211_get_mmie_keyidx(rx->skb) < 0 &&
+ rx->key))
+ return -EACCES;
+ /*
+ * When using MFP, Action frames are not allowed prior to
+ * having configured keys.
+ */
+ if (unlikely(ieee80211_is_action(fc) && !rx->key &&
+ ieee80211_is_robust_mgmt_frame(
+ (struct ieee80211_hdr *) rx->skb->data)))
+ return -EACCES;
+ }
return 0;
}
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index c99ef8d04d3d..e65d74ba404b 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -298,6 +298,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
was_hw_scan = local->hw_scanning;
local->hw_scanning = false;
local->sw_scanning = false;
+ local->scan_channel = NULL;
/* we only have to protect scan_req and hw/sw scan */
mutex_unlock(&local->scan_mtx);
@@ -558,24 +559,39 @@ void ieee80211_scan_work(struct work_struct *work)
if (skip)
break;
- next_delay = IEEE80211_PROBE_DELAY +
- usecs_to_jiffies(local->hw.channel_change_time);
+ /*
+ * Probe delay is used to update the NAV, cf. 11.1.3.2.2
+ * (which unfortunately doesn't say _why_ step a) is done,
+ * but it waits for the probe delay or until a frame is
+ * received - and the received frame would update the NAV).
+ * For now, we do not support waiting until a frame is
+ * received.
+ *
+ * In any case, it is not necessary for a passive scan.
+ */
+ if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
+ !local->scan_req->n_ssids) {
+ next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
+ break;
+ }
+
+ next_delay = IEEE80211_PROBE_DELAY;
local->scan_state = SCAN_SEND_PROBE;
break;
case SCAN_SEND_PROBE:
- next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
- local->scan_state = SCAN_SET_CHANNEL;
-
- if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
- !local->scan_req->n_ssids)
- break;
for (i = 0; i < local->scan_req->n_ssids; i++)
ieee80211_send_probe_req(
sdata, NULL,
local->scan_req->ssids[i].ssid,
local->scan_req->ssids[i].ssid_len,
local->scan_req->ie, local->scan_req->ie_len);
+
+ /*
+ * After sending probe requests, wait for probe responses
+ * on the channel.
+ */
next_delay = IEEE80211_CHANNEL_TIME;
+ local->scan_state = SCAN_SET_CHANNEL;
break;
}
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 97b613affe08..0689a8fbd1e6 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -708,26 +708,62 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_tx_queue_params qparam;
- int i;
+ int queue;
+ bool use_11b;
+ int aCWmin, aCWmax;
if (!local->ops->conf_tx)
return;
memset(&qparam, 0, sizeof(qparam));
- qparam.aifs = 2;
-
- if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ &&
- !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE))
- qparam.cw_min = 31;
- else
- qparam.cw_min = 15;
+ use_11b = (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) &&
+ !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE);
- qparam.cw_max = 1023;
- qparam.txop = 0;
+ for (queue = 0; queue < local_to_hw(local)->queues; queue++) {
+ /* Set defaults according to 802.11-2007 Table 7-37 */
+ aCWmax = 1023;
+ if (use_11b)
+ aCWmin = 31;
+ else
+ aCWmin = 15;
+
+ switch (queue) {
+ case 3: /* AC_BK */
+ qparam.cw_max = aCWmin;
+ qparam.cw_min = aCWmax;
+ qparam.txop = 0;
+ qparam.aifs = 7;
+ break;
+ default: /* never happens but let's not leave undefined */
+ case 2: /* AC_BE */
+ qparam.cw_max = aCWmin;
+ qparam.cw_min = aCWmax;
+ qparam.txop = 0;
+ qparam.aifs = 3;
+ break;
+ case 1: /* AC_VI */
+ qparam.cw_max = aCWmin;
+ qparam.cw_min = (aCWmin + 1) / 2 - 1;
+ if (use_11b)
+ qparam.txop = 6016/32;
+ else
+ qparam.txop = 3008/32;
+ qparam.aifs = 2;
+ break;
+ case 0: /* AC_VO */
+ qparam.cw_max = (aCWmin + 1) / 2 - 1;
+ qparam.cw_min = (aCWmin + 1) / 4 - 1;
+ if (use_11b)
+ qparam.txop = 3264/32;
+ else
+ qparam.txop = 1504/32;
+ qparam.aifs = 2;
+ break;
+ }
- for (i = 0; i < local_to_hw(local)->queues; i++)
- drv_conf_tx(local, i, &qparam);
+ drv_conf_tx(local, queue, &qparam);
+ }
}
void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index 6b4eb8d43a4e..d84502644686 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -27,100 +27,6 @@
#include "aes_ccm.h"
-static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta_addr,
- int idx, int alg, int remove,
- int set_tx_key, const u8 *_key,
- size_t key_len)
-{
- struct ieee80211_local *local = sdata->local;
- struct sta_info *sta;
- struct ieee80211_key *key;
- int err;
-
- if (alg == ALG_AES_CMAC) {
- if (idx < NUM_DEFAULT_KEYS ||
- idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) {
- printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d "
- "(BIP)\n", sdata->dev->name, idx);
- return -EINVAL;
- }
- } else if (idx < 0 || idx >= NUM_DEFAULT_KEYS) {
- printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
- sdata->dev->name, idx);
- return -EINVAL;
- }
-
- if (remove) {
- rcu_read_lock();
-
- err = 0;
-
- if (is_broadcast_ether_addr(sta_addr)) {
- key = sdata->keys[idx];
- } else {
- sta = sta_info_get(local, sta_addr);
- if (!sta) {
- err = -ENOENT;
- goto out_unlock;
- }
- key = sta->key;
- }
-
- ieee80211_key_free(key);
- } else {
- key = ieee80211_key_alloc(alg, idx, key_len, _key);
- if (!key)
- return -ENOMEM;
-
- sta = NULL;
- err = 0;
-
- rcu_read_lock();
-
- if (!is_broadcast_ether_addr(sta_addr)) {
- set_tx_key = 0;
- /*
- * According to the standard, the key index of a
- * pairwise key must be zero. However, some AP are
- * broken when it comes to WEP key indices, so we
- * work around this.
- */
- if (idx != 0 && alg != ALG_WEP) {
- ieee80211_key_free(key);
- err = -EINVAL;
- goto out_unlock;
- }
-
- sta = sta_info_get(local, sta_addr);
- if (!sta) {
- ieee80211_key_free(key);
- err = -ENOENT;
- goto out_unlock;
- }
- }
-
- if (alg == ALG_WEP &&
- key_len != LEN_WEP40 && key_len != LEN_WEP104) {
- ieee80211_key_free(key);
- err = -EINVAL;
- goto out_unlock;
- }
-
- ieee80211_key_link(key, sdata, sta);
-
- if (set_tx_key || (!sta && !sdata->default_key && key))
- ieee80211_set_default_key(sdata, idx);
- if (alg == ALG_AES_CMAC &&
- (set_tx_key || (!sta && !sdata->default_mgmt_key && key)))
- ieee80211_set_default_mgmt_key(sdata, idx);
- }
-
- out_unlock:
- rcu_read_unlock();
-
- return err;
-}
-
static int ieee80211_ioctl_siwgenie(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *data, char *extra)
@@ -472,109 +378,6 @@ static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
return 0;
}
-static int ieee80211_ioctl_siwencode(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *erq, char *keybuf)
-{
- struct ieee80211_sub_if_data *sdata;
- int idx, i, alg = ALG_WEP;
- u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
- int remove = 0, ret;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- idx = erq->flags & IW_ENCODE_INDEX;
- if (idx == 0) {
- if (sdata->default_key)
- for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
- if (sdata->default_key == sdata->keys[i]) {
- idx = i;
- break;
- }
- }
- } else if (idx < 1 || idx > 4)
- return -EINVAL;
- else
- idx--;
-
- if (erq->flags & IW_ENCODE_DISABLED)
- remove = 1;
- else if (erq->length == 0) {
- /* No key data - just set the default TX key index */
- ieee80211_set_default_key(sdata, idx);
- return 0;
- }
-
- ret = ieee80211_set_encryption(
- sdata, bcaddr,
- idx, alg, remove,
- !sdata->default_key,
- keybuf, erq->length);
-
- if (!ret && sdata->vif.type == NL80211_IFTYPE_STATION) {
- if (remove)
- sdata->u.mgd.flags &= ~IEEE80211_STA_TKIP_WEP_USED;
- else
- sdata->u.mgd.flags |= IEEE80211_STA_TKIP_WEP_USED;
- }
-
- return ret;
-}
-
-
-static int ieee80211_ioctl_giwencode(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *erq, char *key)
-{
- struct ieee80211_sub_if_data *sdata;
- int idx, i;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- idx = erq->flags & IW_ENCODE_INDEX;
- if (idx < 1 || idx > 4) {
- idx = -1;
- if (!sdata->default_key)
- idx = 0;
- else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
- if (sdata->default_key == sdata->keys[i]) {
- idx = i;
- break;
- }
- }
- if (idx < 0)
- return -EINVAL;
- } else
- idx--;
-
- erq->flags = idx + 1;
-
- if (!sdata->keys[idx]) {
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- return 0;
- }
-
- memcpy(key, sdata->keys[idx]->conf.key,
- min_t(int, erq->length, sdata->keys[idx]->conf.keylen));
- erq->length = sdata->keys[idx]->conf.keylen;
- erq->flags |= IW_ENCODE_ENABLED;
-
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- switch (sdata->u.mgd.auth_alg) {
- case WLAN_AUTH_OPEN:
- case WLAN_AUTH_LEAP:
- erq->flags |= IW_ENCODE_OPEN;
- break;
- case WLAN_AUTH_SHARED_KEY:
- erq->flags |= IW_ENCODE_RESTRICTED;
- break;
- }
- }
-
- return 0;
-}
-
static int ieee80211_ioctl_siwpower(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *wrq,
@@ -809,82 +612,6 @@ static int ieee80211_ioctl_giwauth(struct net_device *dev,
}
-static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *erq, char *extra)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
- int uninitialized_var(alg), idx, i, remove = 0;
-
- switch (ext->alg) {
- case IW_ENCODE_ALG_NONE:
- remove = 1;
- break;
- case IW_ENCODE_ALG_WEP:
- alg = ALG_WEP;
- break;
- case IW_ENCODE_ALG_TKIP:
- alg = ALG_TKIP;
- break;
- case IW_ENCODE_ALG_CCMP:
- alg = ALG_CCMP;
- break;
- case IW_ENCODE_ALG_AES_CMAC:
- alg = ALG_AES_CMAC;
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- if (erq->flags & IW_ENCODE_DISABLED)
- remove = 1;
-
- idx = erq->flags & IW_ENCODE_INDEX;
- if (alg == ALG_AES_CMAC) {
- if (idx < NUM_DEFAULT_KEYS + 1 ||
- idx > NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) {
- idx = -1;
- if (!sdata->default_mgmt_key)
- idx = 0;
- else for (i = NUM_DEFAULT_KEYS;
- i < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS;
- i++) {
- if (sdata->default_mgmt_key == sdata->keys[i])
- {
- idx = i;
- break;
- }
- }
- if (idx < 0)
- return -EINVAL;
- } else
- idx--;
- } else {
- if (idx < 1 || idx > 4) {
- idx = -1;
- if (!sdata->default_key)
- idx = 0;
- else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
- if (sdata->default_key == sdata->keys[i]) {
- idx = i;
- break;
- }
- }
- if (idx < 0)
- return -EINVAL;
- } else
- idx--;
- }
-
- return ieee80211_set_encryption(sdata, ext->addr.sa_data, idx, alg,
- remove,
- ext->ext_flags &
- IW_ENCODE_EXT_SET_TX_KEY,
- ext->key, ext->key_len);
-}
-
-
/* Structures to export the Wireless Handlers */
static const iw_handler ieee80211_handler[] =
@@ -931,8 +658,8 @@ static const iw_handler ieee80211_handler[] =
(iw_handler) ieee80211_ioctl_giwtxpower, /* SIOCGIWTXPOW */
(iw_handler) cfg80211_wext_siwretry, /* SIOCSIWRETRY */
(iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */
- (iw_handler) ieee80211_ioctl_siwencode, /* SIOCSIWENCODE */
- (iw_handler) ieee80211_ioctl_giwencode, /* SIOCGIWENCODE */
+ (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */
+ (iw_handler) cfg80211_wext_giwencode, /* SIOCGIWENCODE */
(iw_handler) ieee80211_ioctl_siwpower, /* SIOCSIWPOWER */
(iw_handler) ieee80211_ioctl_giwpower, /* SIOCGIWPOWER */
(iw_handler) NULL, /* -- hole -- */
@@ -941,7 +668,7 @@ static const iw_handler ieee80211_handler[] =
(iw_handler) NULL, /* SIOCGIWGENIE */
(iw_handler) ieee80211_ioctl_siwauth, /* SIOCSIWAUTH */
(iw_handler) ieee80211_ioctl_giwauth, /* SIOCGIWAUTH */
- (iw_handler) ieee80211_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */
+ (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */
(iw_handler) NULL, /* SIOCGIWENCODEEXT */
(iw_handler) NULL, /* SIOCSIWPMKSA */
(iw_handler) NULL, /* -- hole -- */
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index 60aba45023ff..77bfdfeb966e 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -260,7 +260,10 @@ struct ip_vs_conn *ip_vs_ct_in_get
list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
if (cp->af == af &&
ip_vs_addr_equal(af, s_addr, &cp->caddr) &&
- ip_vs_addr_equal(af, d_addr, &cp->vaddr) &&
+ /* protocol should only be IPPROTO_IP if
+ * d_addr is a fwmark */
+ ip_vs_addr_equal(protocol == IPPROTO_IP ? AF_UNSPEC : af,
+ d_addr, &cp->vaddr) &&
s_port == cp->cport && d_port == cp->vport &&
cp->flags & IP_VS_CONN_F_TEMPLATE &&
protocol == cp->protocol) {
@@ -698,7 +701,9 @@ ip_vs_conn_new(int af, int proto, const union nf_inet_addr *caddr, __be16 cport,
cp->cport = cport;
ip_vs_addr_copy(af, &cp->vaddr, vaddr);
cp->vport = vport;
- ip_vs_addr_copy(af, &cp->daddr, daddr);
+ /* proto should only be IPPROTO_IP if d_addr is a fwmark */
+ ip_vs_addr_copy(proto == IPPROTO_IP ? AF_UNSPEC : af,
+ &cp->daddr, daddr);
cp->dport = dport;
cp->flags = flags;
spin_lock_init(&cp->lock);
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index cb3e031335eb..8dddb17a947a 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -278,7 +278,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
*/
if (svc->fwmark) {
union nf_inet_addr fwmark = {
- .all = { 0, 0, 0, htonl(svc->fwmark) }
+ .ip = htonl(svc->fwmark)
};
ct = ip_vs_ct_in_get(svc->af, IPPROTO_IP, &snet, 0,
@@ -306,7 +306,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
*/
if (svc->fwmark) {
union nf_inet_addr fwmark = {
- .all = { 0, 0, 0, htonl(svc->fwmark) }
+ .ip = htonl(svc->fwmark)
};
ct = ip_vs_conn_new(svc->af, IPPROTO_IP,
diff --git a/net/netfilter/nf_conntrack_acct.c b/net/netfilter/nf_conntrack_acct.c
index 9fe8982bd7c9..4a1d94aac20b 100644
--- a/net/netfilter/nf_conntrack_acct.c
+++ b/net/netfilter/nf_conntrack_acct.c
@@ -116,7 +116,7 @@ int nf_conntrack_acct_init(struct net *net)
if (net_eq(net, &init_net)) {
#ifdef CONFIG_NF_CT_ACCT
printk(KERN_WARNING "CONFIG_NF_CT_ACCT is deprecated and will be removed soon. Please use\n");
- printk(KERN_WARNING "nf_conntrack.acct=1 kernel paramater, acct=1 nf_conntrack module option or\n");
+ printk(KERN_WARNING "nf_conntrack.acct=1 kernel parameter, acct=1 nf_conntrack module option or\n");
printk(KERN_WARNING "sysctl net.netfilter.nf_conntrack_acct=1 to enable it.\n");
#endif
diff --git a/net/rds/rds.h b/net/rds/rds.h
index 1f82ec0d2066..dbe111236783 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -638,7 +638,7 @@ struct rds_message *rds_send_get_message(struct rds_connection *,
void rds_rdma_unuse(struct rds_sock *rs, u32 r_key, int force);
/* stats.c */
-DECLARE_PER_CPU(struct rds_statistics, rds_stats);
+DECLARE_PER_CPU_SHARED_ALIGNED(struct rds_statistics, rds_stats);
#define rds_stats_inc_which(which, member) do { \
per_cpu(which, get_cpu()).member++; \
put_cpu(); \
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index 4f5a83183c95..b770401b5bd0 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -208,7 +208,7 @@ static void __rfkill_switch_all(const enum rfkill_type type,
rfkill_global_states[type].current_state = state;
list_for_each_entry(rfkill, &rfkill_list, node) {
- if (rfkill->type == type) {
+ if ((!rfkill->user_claim) && (rfkill->type == type)) {
mutex_lock(&rfkill->mutex);
rfkill_toggle_radio(rfkill, state, 0);
mutex_unlock(&rfkill->mutex);
@@ -458,14 +458,53 @@ static ssize_t rfkill_claim_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- return sprintf(buf, "%d\n", 0);
+ struct rfkill *rfkill = to_rfkill(dev);
+
+ return sprintf(buf, "%d\n", rfkill->user_claim);
}
static ssize_t rfkill_claim_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- return -EOPNOTSUPP;
+ struct rfkill *rfkill = to_rfkill(dev);
+ unsigned long claim_tmp;
+ bool claim;
+ int error;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ if (rfkill->user_claim_unsupported)
+ return -EOPNOTSUPP;
+
+ error = strict_strtoul(buf, 0, &claim_tmp);
+ if (error)
+ return error;
+ claim = !!claim_tmp;
+
+ /*
+ * Take the global lock to make sure the kernel is not in
+ * the middle of rfkill_switch_all
+ */
+ error = mutex_lock_killable(&rfkill_global_mutex);
+ if (error)
+ return error;
+
+ if (rfkill->user_claim != claim) {
+ if (!claim && !rfkill_epo_lock_active) {
+ mutex_lock(&rfkill->mutex);
+ rfkill_toggle_radio(rfkill,
+ rfkill_global_states[rfkill->type].current_state,
+ 0);
+ mutex_unlock(&rfkill->mutex);
+ }
+ rfkill->user_claim = claim;
+ }
+
+ mutex_unlock(&rfkill_global_mutex);
+
+ return error ? error : count;
}
static struct device_attribute rfkill_dev_attrs[] = {
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 5abab094441f..d00e8135f866 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -695,6 +695,19 @@ void rpc_force_rebind(struct rpc_clnt *clnt)
EXPORT_SYMBOL_GPL(rpc_force_rebind);
/*
+ * Restart an (async) RPC call from the call_prepare state.
+ * Usually called from within the exit handler.
+ */
+void
+rpc_restart_call_prepare(struct rpc_task *task)
+{
+ if (RPC_ASSASSINATED(task))
+ return;
+ task->tk_action = rpc_prepare_task;
+}
+EXPORT_SYMBOL_GPL(rpc_restart_call_prepare);
+
+/*
* Restart an (async) RPC call. Usually called from within the
* exit handler.
*/
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index ff50a0546865..1102ce1251f7 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -569,7 +569,7 @@ EXPORT_SYMBOL_GPL(rpc_delay);
/*
* Helper to call task->tk_ops->rpc_call_prepare
*/
-static void rpc_prepare_task(struct rpc_task *task)
+void rpc_prepare_task(struct rpc_task *task)
{
task->tk_ops->rpc_call_prepare(task, task->tk_calldata);
}
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index c200d92e57e4..6f33d33cc064 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -11,6 +11,7 @@
#include <net/sock.h>
#include <linux/sunrpc/stats.h>
#include <linux/sunrpc/svc_xprt.h>
+#include <linux/sunrpc/svcsock.h>
#define RPCDBG_FACILITY RPCDBG_SVCXPRT
@@ -1097,36 +1098,58 @@ struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name,
}
EXPORT_SYMBOL_GPL(svc_find_xprt);
-/*
- * Format a buffer with a list of the active transports. A zero for
- * the buflen parameter disables target buffer overflow checking.
+static int svc_one_xprt_name(const struct svc_xprt *xprt,
+ char *pos, int remaining)
+{
+ int len;
+
+ len = snprintf(pos, remaining, "%s %u\n",
+ xprt->xpt_class->xcl_name,
+ svc_xprt_local_port(xprt));
+ if (len >= remaining)
+ return -ENAMETOOLONG;
+ return len;
+}
+
+/**
+ * svc_xprt_names - format a buffer with a list of transport names
+ * @serv: pointer to an RPC service
+ * @buf: pointer to a buffer to be filled in
+ * @buflen: length of buffer to be filled in
+ *
+ * Fills in @buf with a string containing a list of transport names,
+ * each name terminated with '\n'.
+ *
+ * Returns positive length of the filled-in string on success; otherwise
+ * a negative errno value is returned if an error occurs.
*/
-int svc_xprt_names(struct svc_serv *serv, char *buf, int buflen)
+int svc_xprt_names(struct svc_serv *serv, char *buf, const int buflen)
{
struct svc_xprt *xprt;
- char xprt_str[64];
- int totlen = 0;
- int len;
+ int len, totlen;
+ char *pos;
/* Sanity check args */
if (!serv)
return 0;
spin_lock_bh(&serv->sv_lock);
+
+ pos = buf;
+ totlen = 0;
list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) {
- len = snprintf(xprt_str, sizeof(xprt_str),
- "%s %d\n", xprt->xpt_class->xcl_name,
- svc_xprt_local_port(xprt));
- /* If the string was truncated, replace with error string */
- if (len >= sizeof(xprt_str))
- strcpy(xprt_str, "name-too-long\n");
- /* Don't overflow buffer */
- len = strlen(xprt_str);
- if (buflen && (len + totlen >= buflen))
+ len = svc_one_xprt_name(xprt, pos, buflen - totlen);
+ if (len < 0) {
+ *buf = '\0';
+ totlen = len;
+ }
+ if (len <= 0)
break;
- strcpy(buf+totlen, xprt_str);
+
+ pos += len;
totlen += len;
}
+
spin_unlock_bh(&serv->sv_lock);
return totlen;
}
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index af3198814c15..4e6d406264a0 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -240,42 +240,76 @@ out:
/*
* Report socket names for nfsdfs
*/
-static int one_sock_name(char *buf, struct svc_sock *svsk)
+static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining)
{
+ const struct sock *sk = svsk->sk_sk;
+ const char *proto_name = sk->sk_protocol == IPPROTO_UDP ?
+ "udp" : "tcp";
int len;
- switch(svsk->sk_sk->sk_family) {
- case AF_INET:
- len = sprintf(buf, "ipv4 %s %pI4 %d\n",
- svsk->sk_sk->sk_protocol == IPPROTO_UDP ?
- "udp" : "tcp",
- &inet_sk(svsk->sk_sk)->rcv_saddr,
- inet_sk(svsk->sk_sk)->num);
+ switch (sk->sk_family) {
+ case PF_INET:
+ len = snprintf(buf, remaining, "ipv4 %s %pI4 %d\n",
+ proto_name,
+ &inet_sk(sk)->rcv_saddr,
+ inet_sk(sk)->num);
+ break;
+ case PF_INET6:
+ len = snprintf(buf, remaining, "ipv6 %s %pI6 %d\n",
+ proto_name,
+ &inet6_sk(sk)->rcv_saddr,
+ inet_sk(sk)->num);
break;
default:
- len = sprintf(buf, "*unknown-%d*\n",
- svsk->sk_sk->sk_family);
+ len = snprintf(buf, remaining, "*unknown-%d*\n",
+ sk->sk_family);
+ }
+
+ if (len >= remaining) {
+ *buf = '\0';
+ return -ENAMETOOLONG;
}
return len;
}
-int
-svc_sock_names(char *buf, struct svc_serv *serv, char *toclose)
+/**
+ * svc_sock_names - construct a list of listener names in a string
+ * @serv: pointer to RPC service
+ * @buf: pointer to a buffer to fill in with socket names
+ * @buflen: size of the buffer to be filled
+ * @toclose: pointer to '\0'-terminated C string containing the name
+ * of a listener to be closed
+ *
+ * Fills in @buf with a '\n'-separated list of names of listener
+ * sockets. If @toclose is not NULL, the socket named by @toclose
+ * is closed, and is not included in the output list.
+ *
+ * Returns positive length of the socket name string, or a negative
+ * errno value on error.
+ */
+int svc_sock_names(struct svc_serv *serv, char *buf, const size_t buflen,
+ const char *toclose)
{
struct svc_sock *svsk, *closesk = NULL;
int len = 0;
if (!serv)
return 0;
+
spin_lock_bh(&serv->sv_lock);
list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) {
- int onelen = one_sock_name(buf+len, svsk);
- if (toclose && strcmp(toclose, buf+len) == 0)
+ int onelen = svc_one_sock_name(svsk, buf + len, buflen - len);
+ if (onelen < 0) {
+ len = onelen;
+ break;
+ }
+ if (toclose && strcmp(toclose, buf + len) == 0)
closesk = svsk;
else
len += onelen;
}
spin_unlock_bh(&serv->sv_lock);
+
if (closesk)
/* Should unregister with portmap, but you cannot
* unregister just one protocol...
@@ -426,13 +460,14 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
long all[SVC_PKTINFO_SPACE / sizeof(long)];
} buffer;
struct cmsghdr *cmh = &buffer.hdr;
- int err, len;
struct msghdr msg = {
.msg_name = svc_addr(rqstp),
.msg_control = cmh,
.msg_controllen = sizeof(buffer),
.msg_flags = MSG_DONTWAIT,
};
+ size_t len;
+ int err;
if (test_and_clear_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags))
/* udp sockets need large rcvbuf as all pending
@@ -464,8 +499,8 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
return -EAGAIN;
}
len = svc_addr_len(svc_addr(rqstp));
- if (len < 0)
- return len;
+ if (len == 0)
+ return -EAFNOSUPPORT;
rqstp->rq_addrlen = len;
if (skb->tstamp.tv64 == 0) {
skb->tstamp = ktime_get_real();
@@ -1127,9 +1162,19 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
return svsk;
}
-int svc_addsock(struct svc_serv *serv,
- int fd,
- char *name_return)
+/**
+ * svc_addsock - add a listener socket to an RPC service
+ * @serv: pointer to RPC service to which to add a new listener
+ * @fd: file descriptor of the new listener
+ * @name_return: pointer to buffer to fill in with name of listener
+ * @len: size of the buffer
+ *
+ * Fills in socket name and returns positive length of name if successful.
+ * Name is terminated with '\n'. On error, returns a negative errno
+ * value.
+ */
+int svc_addsock(struct svc_serv *serv, const int fd, char *name_return,
+ const size_t len)
{
int err = 0;
struct socket *so = sockfd_lookup(fd, &err);
@@ -1169,7 +1214,7 @@ int svc_addsock(struct svc_serv *serv,
sockfd_put(so);
return err;
}
- return one_sock_name(name_return, svsk);
+ return svc_one_sock_name(svsk, name_return, len);
}
EXPORT_SYMBOL_GPL(svc_addsock);
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index a0bfe53f1621..06ca058572f2 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -672,10 +672,8 @@ xprt_init_autodisconnect(unsigned long data)
if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
goto out_abort;
spin_unlock(&xprt->transport_lock);
- if (xprt_connecting(xprt))
- xprt_release_write(xprt, NULL);
- else
- queue_work(rpciod_workqueue, &xprt->task_cleanup);
+ set_bit(XPRT_CONNECTION_CLOSE, &xprt->state);
+ queue_work(rpciod_workqueue, &xprt->task_cleanup);
return;
out_abort:
spin_unlock(&xprt->transport_lock);
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
index 629a28764da9..42a6f9f20285 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
@@ -265,7 +265,7 @@ static int fast_reg_read_chunks(struct svcxprt_rdma *xprt,
frmr->page_list->page_list[page_no] =
ib_dma_map_single(xprt->sc_cm_id->device,
page_address(rqstp->rq_arg.pages[page_no]),
- PAGE_SIZE, DMA_TO_DEVICE);
+ PAGE_SIZE, DMA_FROM_DEVICE);
if (ib_dma_mapping_error(xprt->sc_cm_id->device,
frmr->page_list->page_list[page_no]))
goto fatal_err;
diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
index 6c26a675435a..8b510c5e8777 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
@@ -183,6 +183,7 @@ static int fast_reg_xdr(struct svcxprt_rdma *xprt,
fatal_err:
printk("svcrdma: Error fast registering memory for xprt %p\n", xprt);
+ vec->frmr = NULL;
svc_rdma_put_frmr(xprt, frmr);
return -EIO;
}
@@ -516,6 +517,7 @@ static int send_reply(struct svcxprt_rdma *rdma,
"svcrdma: could not post a receive buffer, err=%d."
"Closing transport %p.\n", ret, rdma);
set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags);
+ svc_rdma_put_frmr(rdma, vec->frmr);
svc_rdma_put_context(ctxt, 0);
return -ENOTCONN;
}
@@ -606,6 +608,7 @@ static int send_reply(struct svcxprt_rdma *rdma,
return 0;
err:
+ svc_rdma_unmap_dma(ctxt);
svc_rdma_put_frmr(rdma, vec->frmr);
svc_rdma_put_context(ctxt, 1);
return -EIO;
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c
index 3d810e7df3fb..4b0c2fa15e0b 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_transport.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c
@@ -520,8 +520,9 @@ int svc_rdma_post_recv(struct svcxprt_rdma *xprt)
svc_xprt_get(&xprt->sc_xprt);
ret = ib_post_recv(xprt->sc_qp, &recv_wr, &bad_recv_wr);
if (ret) {
- svc_xprt_put(&xprt->sc_xprt);
+ svc_rdma_unmap_dma(ctxt);
svc_rdma_put_context(ctxt, 1);
+ svc_xprt_put(&xprt->sc_xprt);
}
return ret;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index d40ff50887aa..e18596146013 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -807,6 +807,9 @@ static void xs_reset_transport(struct sock_xprt *transport)
*
* This is used when all requests are complete; ie, no DRC state remains
* on the server we want to save.
+ *
+ * The caller _must_ be holding XPRT_LOCKED in order to avoid issues with
+ * xs_reset_transport() zeroing the socket from underneath a writer.
*/
static void xs_close(struct rpc_xprt *xprt)
{
@@ -824,6 +827,14 @@ static void xs_close(struct rpc_xprt *xprt)
xprt_disconnect_done(xprt);
}
+static void xs_tcp_close(struct rpc_xprt *xprt)
+{
+ if (test_and_clear_bit(XPRT_CONNECTION_CLOSE, &xprt->state))
+ xs_close(xprt);
+ else
+ xs_tcp_shutdown(xprt);
+}
+
/**
* xs_destroy - prepare to shutdown a transport
* @xprt: doomed transport
@@ -1772,6 +1783,15 @@ static void xs_tcp_setup_socket(struct rpc_xprt *xprt,
xprt, -status, xprt_connected(xprt),
sock->sk->sk_state);
switch (status) {
+ default:
+ printk("%s: connect returned unhandled error %d\n",
+ __func__, status);
+ case -EADDRNOTAVAIL:
+ /* We're probably in TIME_WAIT. Get rid of existing socket,
+ * and retry
+ */
+ set_bit(XPRT_CONNECTION_CLOSE, &xprt->state);
+ xprt_force_disconnect(xprt);
case -ECONNREFUSED:
case -ECONNRESET:
case -ENETUNREACH:
@@ -1782,10 +1802,6 @@ static void xs_tcp_setup_socket(struct rpc_xprt *xprt,
xprt_clear_connecting(xprt);
return;
}
- /* get rid of existing socket, and retry */
- xs_tcp_shutdown(xprt);
- printk("%s: connect returned unhandled error %d\n",
- __func__, status);
out_eagain:
status = -EAGAIN;
out:
@@ -1994,7 +2010,7 @@ static struct rpc_xprt_ops xs_tcp_ops = {
.buf_free = rpc_free,
.send_request = xs_tcp_send_request,
.set_retrans_timeout = xprt_set_retrans_timeout_def,
- .close = xs_tcp_shutdown,
+ .close = xs_tcp_close,
.destroy = xs_destroy,
.print_stats = xs_tcp_print_stats,
};
diff --git a/net/wimax/op-rfkill.c b/net/wimax/op-rfkill.c
index a3616e2ccb8a..870032faece2 100644
--- a/net/wimax/op-rfkill.c
+++ b/net/wimax/op-rfkill.c
@@ -364,6 +364,7 @@ int wimax_rfkill_add(struct wimax_dev *wimax_dev)
rfkill->state = RFKILL_STATE_UNBLOCKED;
rfkill->data = wimax_dev;
rfkill->toggle_radio = wimax_rfkill_toggle_radio;
+ rfkill->user_claim_unsupported = 1;
/* Initialize the input device for the hw key */
input_dev = input_allocate_device();
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 2006a4ee60eb..47c20eb0c04d 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1,7 +1,7 @@
/*
* This is the linux wireless configuration interface.
*
- * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2006-2009 Johannes Berg <johannes@sipsolutions.net>
*/
#include <linux/if.h>
@@ -457,6 +457,10 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
"symlink to netdev!\n");
}
dev->ieee80211_ptr->netdev = dev;
+#ifdef CONFIG_WIRELESS_EXT
+ dev->ieee80211_ptr->wext.default_key = -1;
+ dev->ieee80211_ptr->wext.default_mgmt_key = -1;
+#endif
mutex_unlock(&rdev->devlist_mtx);
break;
case NETDEV_GOING_DOWN:
@@ -470,9 +474,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
#ifdef CONFIG_WIRELESS_EXT
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
break;
- if (!dev->ieee80211_ptr->wext.ssid_len)
+ if (!dev->ieee80211_ptr->wext.ibss.ssid_len)
break;
- cfg80211_join_ibss(rdev, dev, &dev->ieee80211_ptr->wext);
+ cfg80211_join_ibss(rdev, dev, &dev->ieee80211_ptr->wext.ibss);
break;
#endif
case NETDEV_UNREGISTER:
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 3e49d3399311..f14b6c5f4221 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -1,7 +1,7 @@
/*
* Wireless configuration interface internals.
*
- * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2006-2009 Johannes Berg <johannes@sipsolutions.net>
*/
#ifndef __NET_WIRELESS_CORE_H
#define __NET_WIRELESS_CORE_H
@@ -151,4 +151,8 @@ void cfg80211_clear_ibss(struct net_device *dev, bool nowext);
int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
struct net_device *dev, bool nowext);
+/* internal helpers */
+int cfg80211_validate_key_settings(struct key_params *params, int key_idx,
+ const u8 *mac_addr);
+
#endif /* __NET_WIRELESS_CORE_H */
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 3c38afaed28a..a4a1c3498ff2 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -63,7 +63,7 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
return -EALREADY;
#ifdef CONFIG_WIRELESS_EXT
- wdev->wext.channel = params->channel;
+ wdev->wext.ibss.channel = params->channel;
#endif
err = rdev->ops->join_ibss(&rdev->wiphy, dev, params);
@@ -90,7 +90,7 @@ void cfg80211_clear_ibss(struct net_device *dev, bool nowext)
memset(wdev->bssid, 0, ETH_ALEN);
#ifdef CONFIG_WIRELESS_EXT
if (!nowext)
- wdev->wext.ssid_len = 0;
+ wdev->wext.ibss.ssid_len = 0;
#endif
}
@@ -116,11 +116,11 @@ static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
enum ieee80211_band band;
int i;
- if (!wdev->wext.beacon_interval)
- wdev->wext.beacon_interval = 100;
+ if (!wdev->wext.ibss.beacon_interval)
+ wdev->wext.ibss.beacon_interval = 100;
/* try to find an IBSS channel if none requested ... */
- if (!wdev->wext.channel) {
+ if (!wdev->wext.ibss.channel) {
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
struct ieee80211_supported_band *sband;
struct ieee80211_channel *chan;
@@ -135,27 +135,27 @@ static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
continue;
if (chan->flags & IEEE80211_CHAN_DISABLED)
continue;
- wdev->wext.channel = chan;
+ wdev->wext.ibss.channel = chan;
break;
}
- if (wdev->wext.channel)
+ if (wdev->wext.ibss.channel)
break;
}
- if (!wdev->wext.channel)
+ if (!wdev->wext.ibss.channel)
return -EINVAL;
}
/* don't join -- SSID is not there */
- if (!wdev->wext.ssid_len)
+ if (!wdev->wext.ibss.ssid_len)
return 0;
if (!netif_running(wdev->netdev))
return 0;
return cfg80211_join_ibss(wiphy_to_dev(wdev->wiphy),
- wdev->netdev, &wdev->wext);
+ wdev->netdev, &wdev->wext.ibss);
}
int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
@@ -182,7 +182,7 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
chan->flags & IEEE80211_CHAN_DISABLED))
return -EINVAL;
- if (wdev->wext.channel == chan)
+ if (wdev->wext.ibss.channel == chan)
return 0;
if (wdev->ssid_len) {
@@ -193,11 +193,11 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
}
if (chan) {
- wdev->wext.channel = chan;
- wdev->wext.channel_fixed = true;
+ wdev->wext.ibss.channel = chan;
+ wdev->wext.ibss.channel_fixed = true;
} else {
/* cfg80211_ibss_wext_join will pick one if needed */
- wdev->wext.channel_fixed = false;
+ wdev->wext.ibss.channel_fixed = false;
}
return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
@@ -218,8 +218,8 @@ int cfg80211_ibss_wext_giwfreq(struct net_device *dev,
if (wdev->current_bss)
chan = wdev->current_bss->channel;
- else if (wdev->wext.channel)
- chan = wdev->wext.channel;
+ else if (wdev->wext.ibss.channel)
+ chan = wdev->wext.ibss.channel;
if (chan) {
freq->m = chan->center_freq;
@@ -259,9 +259,9 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev,
if (len > 0 && ssid[len - 1] == '\0')
len--;
- wdev->wext.ssid = wdev->ssid;
- memcpy(wdev->wext.ssid, ssid, len);
- wdev->wext.ssid_len = len;
+ wdev->wext.ibss.ssid = wdev->ssid;
+ memcpy(wdev->wext.ibss.ssid, ssid, len);
+ wdev->wext.ibss.ssid_len = len;
return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
}
@@ -284,10 +284,10 @@ int cfg80211_ibss_wext_giwessid(struct net_device *dev,
data->flags = 1;
data->length = wdev->ssid_len;
memcpy(ssid, wdev->ssid, data->length);
- } else if (wdev->wext.ssid && wdev->wext.ssid_len) {
+ } else if (wdev->wext.ibss.ssid && wdev->wext.ibss.ssid_len) {
data->flags = 1;
- data->length = wdev->wext.ssid_len;
- memcpy(ssid, wdev->wext.ssid, data->length);
+ data->length = wdev->wext.ibss.ssid_len;
+ memcpy(ssid, wdev->wext.ibss.ssid, data->length);
}
return 0;
@@ -318,12 +318,12 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
bssid = NULL;
/* both automatic */
- if (!bssid && !wdev->wext.bssid)
+ if (!bssid && !wdev->wext.ibss.bssid)
return 0;
/* fixed already - and no change */
- if (wdev->wext.bssid && bssid &&
- compare_ether_addr(bssid, wdev->wext.bssid) == 0)
+ if (wdev->wext.ibss.bssid && bssid &&
+ compare_ether_addr(bssid, wdev->wext.ibss.bssid) == 0)
return 0;
if (wdev->ssid_len) {
@@ -334,10 +334,10 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
}
if (bssid) {
- memcpy(wdev->wext_bssid, bssid, ETH_ALEN);
- wdev->wext.bssid = wdev->wext_bssid;
+ memcpy(wdev->wext.bssid, bssid, ETH_ALEN);
+ wdev->wext.ibss.bssid = wdev->wext.bssid;
} else
- wdev->wext.bssid = NULL;
+ wdev->wext.ibss.bssid = NULL;
return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
}
@@ -356,8 +356,8 @@ int cfg80211_ibss_wext_giwap(struct net_device *dev,
ap_addr->sa_family = ARPHRD_ETHER;
- if (wdev->wext.bssid) {
- memcpy(ap_addr->sa_data, wdev->wext.bssid, ETH_ALEN);
+ if (wdev->wext.ibss.bssid) {
+ memcpy(ap_addr->sa_data, wdev->wext.ibss.bssid, ETH_ALEN);
return 0;
}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 3c53c5cbc3a9..f88dbbec7521 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1,7 +1,7 @@
/*
* This is the new netlink-based wireless configuration interface.
*
- * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2006-2009 Johannes Berg <johannes@sipsolutions.net>
*/
#include <linux/if.h>
@@ -122,6 +122,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
[NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 },
[NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG },
[NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG },
+ [NL80211_ATTR_USE_MFP] = { .type = NLA_U32 },
};
/* IE validation */
@@ -1072,6 +1073,14 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
}
err = func(&drv->wiphy, dev, key_idx);
+#ifdef CONFIG_WIRELESS_EXT
+ if (!err) {
+ if (func == drv->ops->set_default_key)
+ dev->ieee80211_ptr->wext.default_key = key_idx;
+ else
+ dev->ieee80211_ptr->wext.default_mgmt_key = key_idx;
+ }
+#endif
out:
cfg80211_put_dev(drv);
@@ -1110,44 +1119,8 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_MAC])
mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
- if (key_idx > 5)
- return -EINVAL;
-
- /*
- * Disallow pairwise keys with non-zero index unless it's WEP
- * (because current deployments use pairwise WEP keys with
- * non-zero indizes but 802.11i clearly specifies to use zero)
- */
- if (mac_addr && key_idx &&
- params.cipher != WLAN_CIPHER_SUITE_WEP40 &&
- params.cipher != WLAN_CIPHER_SUITE_WEP104)
- return -EINVAL;
-
- /* TODO: add definitions for the lengths to linux/ieee80211.h */
- switch (params.cipher) {
- case WLAN_CIPHER_SUITE_WEP40:
- if (params.key_len != 5)
- return -EINVAL;
- break;
- case WLAN_CIPHER_SUITE_TKIP:
- if (params.key_len != 32)
- return -EINVAL;
- break;
- case WLAN_CIPHER_SUITE_CCMP:
- if (params.key_len != 16)
- return -EINVAL;
- break;
- case WLAN_CIPHER_SUITE_WEP104:
- if (params.key_len != 13)
- return -EINVAL;
- break;
- case WLAN_CIPHER_SUITE_AES_CMAC:
- if (params.key_len != 16)
- return -EINVAL;
- break;
- default:
+ if (cfg80211_validate_key_settings(&params, key_idx, mac_addr))
return -EINVAL;
- }
rtnl_lock();
@@ -1209,6 +1182,15 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr);
+#ifdef CONFIG_WIRELESS_EXT
+ if (!err) {
+ if (key_idx == dev->ieee80211_ptr->wext.default_key)
+ dev->ieee80211_ptr->wext.default_key = -1;
+ else if (key_idx == dev->ieee80211_ptr->wext.default_mgmt_key)
+ dev->ieee80211_ptr->wext.default_mgmt_key = -1;
+ }
+#endif
+
out:
cfg80211_put_dev(drv);
dev_put(dev);
@@ -1745,6 +1727,12 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
if (err)
goto out_rtnl;
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
+ dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) {
+ err = -EINVAL;
+ goto out;
+ }
+
err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
if (err)
goto out;
@@ -1788,6 +1776,12 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
if (err)
goto out_rtnl;
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
+ dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) {
+ err = -EINVAL;
+ goto out;
+ }
+
if (!drv->ops->del_station) {
err = -EOPNOTSUPP;
goto out;
@@ -3012,6 +3006,17 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
}
+ if (info->attrs[NL80211_ATTR_USE_MFP]) {
+ enum nl80211_mfp use_mfp =
+ nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
+ if (use_mfp == NL80211_MFP_REQUIRED)
+ req.use_mfp = true;
+ else if (use_mfp != NL80211_MFP_NO) {
+ err = -EINVAL;
+ goto out;
+ }
+ }
+
err = drv->ops->assoc(&drv->wiphy, dev, &req);
out:
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 5f7e997195c7..beb226e78cd7 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -138,3 +138,48 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy)
if (wiphy->bands[band])
set_mandatory_flags_band(wiphy->bands[band], band);
}
+
+int cfg80211_validate_key_settings(struct key_params *params, int key_idx,
+ const u8 *mac_addr)
+{
+ if (key_idx > 5)
+ return -EINVAL;
+
+ /*
+ * Disallow pairwise keys with non-zero index unless it's WEP
+ * (because current deployments use pairwise WEP keys with
+ * non-zero indizes but 802.11i clearly specifies to use zero)
+ */
+ if (mac_addr && key_idx &&
+ params->cipher != WLAN_CIPHER_SUITE_WEP40 &&
+ params->cipher != WLAN_CIPHER_SUITE_WEP104)
+ return -EINVAL;
+
+ /* TODO: add definitions for the lengths to linux/ieee80211.h */
+ switch (params->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ if (params->key_len != 5)
+ return -EINVAL;
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ if (params->key_len != 32)
+ return -EINVAL;
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ if (params->key_len != 16)
+ return -EINVAL;
+ break;
+ case WLAN_CIPHER_SUITE_WEP104:
+ if (params->key_len != 13)
+ return -EINVAL;
+ break;
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ if (params->key_len != 16)
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 5ef82f2ca88f..d435645d1359 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -5,12 +5,13 @@
* into cfg80211, when that happens all the exports here go away and
* we directly assign the wireless handlers of wireless interfaces.
*
- * Copyright 2008 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2008-2009 Johannes Berg <johannes@sipsolutions.net>
*/
#include <linux/wireless.h>
#include <linux/nl80211.h>
#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
#include <net/iw_handler.h>
#include <net/cfg80211.h>
#include "core.h"
@@ -296,22 +297,34 @@ EXPORT_SYMBOL_GPL(cfg80211_wext_siwmlme);
struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy,
struct iw_freq *freq)
{
+ struct ieee80211_channel *chan;
+ int f;
+
+ /*
+ * Parse frequency - return NULL for auto and
+ * -EINVAL for impossible things.
+ */
if (freq->e == 0) {
if (freq->m < 0)
return NULL;
- else
- return ieee80211_get_channel(wiphy,
- ieee80211_channel_to_frequency(freq->m));
+ f = ieee80211_channel_to_frequency(freq->m);
} else {
int i, div = 1000000;
for (i = 0; i < freq->e; i++)
div /= 10;
- if (div > 0)
- return ieee80211_get_channel(wiphy, freq->m / div);
- else
+ if (div <= 0)
return ERR_PTR(-EINVAL);
+ f = freq->m / div;
}
+ /*
+ * Look up channel struct and return -EINVAL when
+ * it cannot be found.
+ */
+ chan = ieee80211_get_channel(wiphy, f);
+ if (!chan)
+ return ERR_PTR(-EINVAL);
+ return chan;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_freq);
@@ -465,3 +478,261 @@ int cfg80211_wext_giwretry(struct net_device *dev,
return 0;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry);
+
+static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, const u8 *addr,
+ bool remove, bool tx_key, int idx,
+ struct key_params *params)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ int err;
+
+ if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
+ if (!rdev->ops->set_default_mgmt_key)
+ return -EOPNOTSUPP;
+
+ if (idx < 4 || idx > 5)
+ return -EINVAL;
+ } else if (idx < 0 || idx > 3)
+ return -EINVAL;
+
+ if (remove) {
+ err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr);
+ if (!err) {
+ if (idx == wdev->wext.default_key)
+ wdev->wext.default_key = -1;
+ else if (idx == wdev->wext.default_mgmt_key)
+ wdev->wext.default_mgmt_key = -1;
+ }
+ return err;
+ } else {
+ if (addr)
+ tx_key = false;
+
+ if (cfg80211_validate_key_settings(params, idx, addr))
+ return -EINVAL;
+
+ err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params);
+ if (err)
+ return err;
+
+ if (tx_key || (!addr && wdev->wext.default_key == -1)) {
+ err = rdev->ops->set_default_key(&rdev->wiphy,
+ dev, idx);
+ if (!err)
+ wdev->wext.default_key = idx;
+ return err;
+ }
+
+ if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC &&
+ (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) {
+ err = rdev->ops->set_default_mgmt_key(&rdev->wiphy,
+ dev, idx);
+ if (!err)
+ wdev->wext.default_mgmt_key = idx;
+ return err;
+ }
+
+ return 0;
+ }
+}
+
+int cfg80211_wext_siwencode(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *erq, char *keybuf)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ int idx, err;
+ bool remove = false;
+ struct key_params params;
+
+ /* no use -- only MFP (set_default_mgmt_key) is optional */
+ if (!rdev->ops->del_key ||
+ !rdev->ops->add_key ||
+ !rdev->ops->set_default_key)
+ return -EOPNOTSUPP;
+
+ idx = erq->flags & IW_ENCODE_INDEX;
+ if (idx == 0) {
+ idx = wdev->wext.default_key;
+ if (idx < 0)
+ return -EINVAL;
+ } else if (idx < 1 || idx > 4)
+ return -EINVAL;
+ else
+ idx--;
+
+ if (erq->flags & IW_ENCODE_DISABLED)
+ remove = true;
+ else if (erq->length == 0) {
+ /* No key data - just set the default TX key index */
+ err = rdev->ops->set_default_key(&rdev->wiphy, dev, idx);
+ if (!err)
+ wdev->wext.default_key = idx;
+ return err;
+ }
+
+ memset(&params, 0, sizeof(params));
+ params.key = keybuf;
+ params.key_len = erq->length;
+ if (erq->length == 5)
+ params.cipher = WLAN_CIPHER_SUITE_WEP40;
+ else if (erq->length == 13)
+ params.cipher = WLAN_CIPHER_SUITE_WEP104;
+ else
+ return -EINVAL;
+
+ return cfg80211_set_encryption(rdev, dev, NULL, remove,
+ wdev->wext.default_key == -1,
+ idx, &params);
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_siwencode);
+
+int cfg80211_wext_siwencodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *erq, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
+ const u8 *addr;
+ int idx;
+ bool remove = false;
+ struct key_params params;
+ u32 cipher;
+
+ /* no use -- only MFP (set_default_mgmt_key) is optional */
+ if (!rdev->ops->del_key ||
+ !rdev->ops->add_key ||
+ !rdev->ops->set_default_key)
+ return -EOPNOTSUPP;
+
+ switch (ext->alg) {
+ case IW_ENCODE_ALG_NONE:
+ remove = true;
+ cipher = 0;
+ break;
+ case IW_ENCODE_ALG_WEP:
+ if (erq->length == 5)
+ cipher = WLAN_CIPHER_SUITE_WEP40;
+ else if (erq->length == 13)
+ cipher = WLAN_CIPHER_SUITE_WEP104;
+ else
+ return -EINVAL;
+ break;
+ case IW_ENCODE_ALG_TKIP:
+ cipher = WLAN_CIPHER_SUITE_TKIP;
+ break;
+ case IW_ENCODE_ALG_CCMP:
+ cipher = WLAN_CIPHER_SUITE_CCMP;
+ break;
+ case IW_ENCODE_ALG_AES_CMAC:
+ cipher = WLAN_CIPHER_SUITE_AES_CMAC;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ if (erq->flags & IW_ENCODE_DISABLED)
+ remove = true;
+
+ idx = erq->flags & IW_ENCODE_INDEX;
+ if (cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
+ if (idx < 4 || idx > 5) {
+ /*
+ * XXX: Only wpa_supplicant ever used this
+ * can we still change the ABI a little
+ * so we do not need to keep track of
+ * the default key?
+ */
+ return -EINVAL;
+ } else
+ idx--;
+ } else {
+ if (idx < 1 || idx > 4) {
+ idx = wdev->wext.default_key;
+ if (idx < 0)
+ return -EINVAL;
+ } else
+ idx--;
+ }
+
+ addr = ext->addr.sa_data;
+ if (is_broadcast_ether_addr(addr))
+ addr = NULL;
+
+ memset(&params, 0, sizeof(params));
+ params.key = ext->key;
+ params.key_len = ext->key_len;
+ params.cipher = cipher;
+
+ return cfg80211_set_encryption(
+ rdev, dev, addr, remove,
+ ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
+ idx, &params);
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_siwencodeext);
+
+struct giwencode_cookie {
+ size_t buflen;
+ char *keybuf;
+};
+
+static void giwencode_get_key_cb(void *cookie, struct key_params *params)
+{
+ struct giwencode_cookie *data = cookie;
+
+ if (!params->key) {
+ data->buflen = 0;
+ return;
+ }
+
+ data->buflen = min_t(size_t, data->buflen, params->key_len);
+ memcpy(data->keybuf, params->key, data->buflen);
+}
+
+int cfg80211_wext_giwencode(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *erq, char *keybuf)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ int idx, err;
+ struct giwencode_cookie data = {
+ .keybuf = keybuf,
+ .buflen = erq->length,
+ };
+
+ if (!rdev->ops->get_key)
+ return -EOPNOTSUPP;
+
+ idx = erq->flags & IW_ENCODE_INDEX;
+ if (idx == 0) {
+ idx = wdev->wext.default_key;
+ if (idx < 0)
+ idx = 0;
+ } else if (idx < 1 || idx > 4)
+ return -EINVAL;
+ else
+ idx--;
+
+ erq->flags = idx + 1;
+
+ err = rdev->ops->get_key(&rdev->wiphy, dev, idx, NULL, &data,
+ giwencode_get_key_cb);
+ if (!err) {
+ erq->length = data.buflen;
+ erq->flags |= IW_ENCODE_ENABLED;
+ return 0;
+ }
+
+ if (err == -ENOENT) {
+ erq->flags |= IW_ENCODE_DISABLED;
+ erq->length = 0;
+ return 0;
+ }
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode);
diff --git a/net/wireless/wext.c b/net/wireless/wext.c
index cb6a5bb85d80..dc5b47e84a3d 100644
--- a/net/wireless/wext.c
+++ b/net/wireless/wext.c
@@ -649,14 +649,28 @@ static int wireless_seq_show(struct seq_file *seq, void *v)
return 0;
}
+static void *wireless_dev_seq_start(struct seq_file *seq, loff_t *pos)
+ __acquires(dev_base_lock)
+{
+ rtnl_lock();
+ return dev_seq_start(seq, pos);
+}
+
+static void wireless_dev_seq_stop(struct seq_file *seq, void *v)
+ __releases(dev_base_lock)
+{
+ dev_seq_stop(seq, v);
+ rtnl_unlock();
+}
+
static const struct seq_operations wireless_seq_ops = {
- .start = dev_seq_start,
+ .start = wireless_dev_seq_start,
.next = dev_seq_next,
- .stop = dev_seq_stop,
+ .stop = wireless_dev_seq_stop,
.show = wireless_seq_show,
};
-static int wireless_seq_open(struct inode *inode, struct file *file)
+static int seq_open_wireless(struct inode *inode, struct file *file)
{
return seq_open_net(inode, file, &wireless_seq_ops,
sizeof(struct seq_net_private));
@@ -664,7 +678,7 @@ static int wireless_seq_open(struct inode *inode, struct file *file)
static const struct file_operations wireless_seq_fops = {
.owner = THIS_MODULE,
- .open = wireless_seq_open,
+ .open = seq_open_wireless,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release_net,
diff --git a/samples/Kconfig b/samples/Kconfig
index 4b02f5a0e656..b75d28cba3f7 100644
--- a/samples/Kconfig
+++ b/samples/Kconfig
@@ -19,6 +19,12 @@ config SAMPLE_TRACEPOINTS
help
This build tracepoints example modules.
+config SAMPLE_TRACE_EVENTS
+ tristate "Build trace_events examples -- loadable modules only"
+ depends on EVENT_TRACING && m
+ help
+ This build trace event example modules.
+
config SAMPLE_KOBJECT
tristate "Build kobject examples"
help
diff --git a/samples/Makefile b/samples/Makefile
index 10eaca89fe17..13e4b470b539 100644
--- a/samples/Makefile
+++ b/samples/Makefile
@@ -1,3 +1,3 @@
# Makefile for Linux samples code
-obj-$(CONFIG_SAMPLES) += markers/ kobject/ kprobes/ tracepoints/
+obj-$(CONFIG_SAMPLES) += markers/ kobject/ kprobes/ tracepoints/ trace_events/
diff --git a/samples/trace_events/Makefile b/samples/trace_events/Makefile
new file mode 100644
index 000000000000..0d428dc67283
--- /dev/null
+++ b/samples/trace_events/Makefile
@@ -0,0 +1,6 @@
+# builds the trace events example kernel modules;
+# then to use one (as root): insmod <module_name.ko>
+
+CFLAGS_trace-events-sample.o := -I$(src)
+
+obj-$(CONFIG_SAMPLE_TRACE_EVENTS) += trace-events-sample.o
diff --git a/samples/trace_events/trace-events-sample.c b/samples/trace_events/trace-events-sample.c
new file mode 100644
index 000000000000..aabc4e970911
--- /dev/null
+++ b/samples/trace_events/trace-events-sample.c
@@ -0,0 +1,52 @@
+#include <linux/module.h>
+#include <linux/kthread.h>
+
+/*
+ * Any file that uses trace points, must include the header.
+ * But only one file, must include the header by defining
+ * CREATE_TRACE_POINTS first. This will make the C code that
+ * creates the handles for the trace points.
+ */
+#define CREATE_TRACE_POINTS
+#include "trace-events-sample.h"
+
+
+static void simple_thread_func(int cnt)
+{
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ);
+ trace_foo_bar("hello", cnt);
+}
+
+static int simple_thread(void *arg)
+{
+ int cnt = 0;
+
+ while (!kthread_should_stop())
+ simple_thread_func(cnt++);
+
+ return 0;
+}
+
+static struct task_struct *simple_tsk;
+
+static int __init trace_event_init(void)
+{
+ simple_tsk = kthread_run(simple_thread, NULL, "event-sample");
+ if (IS_ERR(simple_tsk))
+ return -1;
+
+ return 0;
+}
+
+static void __exit trace_event_exit(void)
+{
+ kthread_stop(simple_tsk);
+}
+
+module_init(trace_event_init);
+module_exit(trace_event_exit);
+
+MODULE_AUTHOR("Steven Rostedt");
+MODULE_DESCRIPTION("trace-events-sample");
+MODULE_LICENSE("GPL");
diff --git a/samples/trace_events/trace-events-sample.h b/samples/trace_events/trace-events-sample.h
new file mode 100644
index 000000000000..128a897687c5
--- /dev/null
+++ b/samples/trace_events/trace-events-sample.h
@@ -0,0 +1,129 @@
+/*
+ * Notice that this file is not protected like a normal header.
+ * We also must allow for rereading of this file. The
+ *
+ * || defined(TRACE_HEADER_MULTI_READ)
+ *
+ * serves this purpose.
+ */
+#if !defined(_TRACE_EVENT_SAMPLE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_EVENT_SAMPLE_H
+
+/*
+ * All trace headers should include tracepoint.h, until we finally
+ * make it into a standard header.
+ */
+#include <linux/tracepoint.h>
+
+/*
+ * If TRACE_SYSTEM is defined, that will be the directory created
+ * in the ftrace directory under /debugfs/tracing/events/<system>
+ *
+ * The define_trace.h belowe will also look for a file name of
+ * TRACE_SYSTEM.h where TRACE_SYSTEM is what is defined here.
+ *
+ * If you want a different system than file name, you can override
+ * the header name by defining TRACE_INCLUDE_FILE
+ *
+ * If this file was called, goofy.h, then we would define:
+ *
+ * #define TRACE_INCLUDE_FILE goofy
+ *
+ */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM sample
+
+/*
+ * The TRACE_EVENT macro is broken up into 5 parts.
+ *
+ * name: name of the trace point. This is also how to enable the tracepoint.
+ * A function called trace_foo_bar() will be created.
+ *
+ * proto: the prototype of the function trace_foo_bar()
+ * Here it is trace_foo_bar(char *foo, int bar).
+ *
+ * args: must match the arguments in the prototype.
+ * Here it is simply "foo, bar".
+ *
+ * struct: This defines the way the data will be stored in the ring buffer.
+ * There are currently two types of elements. __field and __array.
+ * a __field is broken up into (type, name). Where type can be any
+ * type but an array.
+ * For an array. there are three fields. (type, name, size). The
+ * type of elements in the array, the name of the field and the size
+ * of the array.
+ *
+ * __array( char, foo, 10) is the same as saying char foo[10].
+ *
+ * fast_assign: This is a C like function that is used to store the items
+ * into the ring buffer.
+ *
+ * printk: This is a way to print out the data in pretty print. This is
+ * useful if the system crashes and you are logging via a serial line,
+ * the data can be printed to the console using this "printk" method.
+ *
+ * Note, that for both the assign and the printk, __entry is the handler
+ * to the data structure in the ring buffer, and is defined by the
+ * TP_STRUCT__entry.
+ */
+TRACE_EVENT(foo_bar,
+
+ TP_PROTO(char *foo, int bar),
+
+ TP_ARGS(foo, bar),
+
+ TP_STRUCT__entry(
+ __array( char, foo, 10 )
+ __field( int, bar )
+ ),
+
+ TP_fast_assign(
+ strncpy(__entry->foo, foo, 10);
+ __entry->bar = bar;
+ ),
+
+ TP_printk("foo %s %d", __entry->foo, __entry->bar)
+);
+#endif
+
+/***** NOTICE! The #if protection ends here. *****/
+
+
+/*
+ * There are several ways I could have done this. If I left out the
+ * TRACE_INCLUDE_PATH, then it would default to the kernel source
+ * include/trace/events directory.
+ *
+ * I could specify a path from the define_trace.h file back to this
+ * file.
+ *
+ * #define TRACE_INCLUDE_PATH ../../samples/trace_events
+ *
+ * But I chose to simply make it use the current directory and then in
+ * the Makefile I added:
+ *
+ * CFLAGS_trace-events-sample.o := -I$(PWD)/samples/trace_events/
+ *
+ * This will make sure the current path is part of the include
+ * structure for our file so that we can find it.
+ *
+ * I could have made only the top level directory the include:
+ *
+ * CFLAGS_trace-events-sample.o := -I$(PWD)
+ *
+ * And then let the path to this directory be the TRACE_INCLUDE_PATH:
+ *
+ * #define TRACE_INCLUDE_PATH samples/trace_events
+ *
+ * But then if something defines "samples" or "trace_events" then we
+ * could risk that being converted too, and give us an unexpected
+ * result.
+ */
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH .
+/*
+ * TRACE_INCLUDE_FILE is not needed if the filename and TRACE_SYSTEM are equal
+ */
+#define TRACE_INCLUDE_FILE trace-events-sample
+#include <trace/define_trace.h>
diff --git a/scripts/Makefile b/scripts/Makefile
index aafdf064feef..9dd5b25a1d53 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -21,6 +21,7 @@ hostprogs-y += unifdef
subdir-$(CONFIG_MODVERSIONS) += genksyms
subdir-y += mod
subdir-$(CONFIG_SECURITY_SELINUX) += selinux
+subdir-$(CONFIG_DTC) += dtc
# Let clean descend into subdirs
subdir- += basic kconfig package selinux
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 39a9642927d3..5c4b7a400c18 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -27,6 +27,9 @@ ccflags-y :=
cppflags-y :=
ldflags-y :=
+subdir-asflags-y :=
+subdir-ccflags-y :=
+
# Read auto.conf if it exists, otherwise ignore
-include include/config/auto.conf
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 979619574f70..cba61ca403ca 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -4,6 +4,11 @@ ccflags-y += $(EXTRA_CFLAGS)
cppflags-y += $(EXTRA_CPPFLAGS)
ldflags-y += $(EXTRA_LDFLAGS)
+#
+# flags that take effect in sub directories
+export KBUILD_SUBDIR_ASFLAGS := $(KBUILD_SUBDIR_ASFLAGS) $(subdir-asflags-y)
+export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y)
+
# Figure out what we need to build from the various variables
# ===========================================================================
@@ -104,10 +109,10 @@ else
debug_flags =
endif
-orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) \
+orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \
$(ccflags-y) $(CFLAGS_$(basetarget).o)
_c_flags = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags))
-_a_flags = $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) \
+_a_flags = $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) $(KBUILD_SUBDIR_ASFLAGS) \
$(asflags-y) $(AFLAGS_$(basetarget).o)
_cpp_flags = $(KBUILD_CPPFLAGS) $(cppflags-y) $(CPPFLAGS_$(@F))
diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile
new file mode 100644
index 000000000000..01cdb36fc583
--- /dev/null
+++ b/scripts/dtc/Makefile
@@ -0,0 +1,54 @@
+# scripts/dtc makefile
+
+hostprogs-y := dtc
+always := $(hostprogs-y)
+
+dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \
+ srcpos.o checks.o
+dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o
+
+# Source files need to get at the userspace version of libfdt_env.h to compile
+
+HOSTCFLAGS_DTC := -I$(src) -I$(src)/libfdt
+
+HOSTCFLAGS_checks.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_data.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_dtc.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_flattree.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_fstree.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_livetree.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_srcpos.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_treesource.o := $(HOSTCFLAGS_DTC)
+
+HOSTCFLAGS_dtc-lexer.lex.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC)
+
+# dependencies on generated files need to be listed explicitly
+$(obj)/dtc-parser.tab.o: $(obj)/dtc-parser.tab.c $(obj)/dtc-parser.tab.h
+$(obj)/dtc-lexer.lex.o: $(obj)/dtc-lexer.lex.c $(obj)/dtc-parser.tab.h
+
+targets += dtc-parser.tab.c dtc-lexer.lex.c
+
+clean-files += dtc-parser.tab.h
+
+# GENERATE_PARSER := 1 # Uncomment to rebuild flex/bison output
+
+ifdef GENERATE_PARSER
+
+BISON = bison
+FLEX = flex
+
+quiet_cmd_bison = BISON $@
+ cmd_bison = $(BISON) -o$@ -d $<; cp $@ $@_shipped
+quiet_cmd_flex = FLEX $@
+ cmd_flex = $(FLEX) -o$@ $<; cp $@ $@_shipped
+
+$(obj)/dtc-parser.tab.c: $(src)/dtc-parser.y FORCE
+ $(call if_changed,bison)
+
+$(obj)/dtc-parser.tab.h: $(obj)/dtc-parser.tab.c
+
+$(obj)/dtc-lexer.lex.c: $(src)/dtc-lexer.l FORCE
+ $(call if_changed,flex)
+
+endif
diff --git a/arch/powerpc/boot/dtc-src/Makefile.dtc b/scripts/dtc/Makefile.dtc
index 6ddf9ecac669..6ddf9ecac669 100644
--- a/arch/powerpc/boot/dtc-src/Makefile.dtc
+++ b/scripts/dtc/Makefile.dtc
diff --git a/arch/powerpc/boot/dtc-src/checks.c b/scripts/dtc/checks.c
index 95485796f253..95485796f253 100644
--- a/arch/powerpc/boot/dtc-src/checks.c
+++ b/scripts/dtc/checks.c
diff --git a/arch/powerpc/boot/dtc-src/data.c b/scripts/dtc/data.c
index dd2e3d39d4c1..dd2e3d39d4c1 100644
--- a/arch/powerpc/boot/dtc-src/data.c
+++ b/scripts/dtc/data.c
diff --git a/arch/powerpc/boot/dtc-src/dtc-lexer.l b/scripts/dtc/dtc-lexer.l
index 44dbfd3f0976..44dbfd3f0976 100644
--- a/arch/powerpc/boot/dtc-src/dtc-lexer.l
+++ b/scripts/dtc/dtc-lexer.l
diff --git a/arch/powerpc/boot/dtc-src/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped
index ac392cb040f6..ac392cb040f6 100644
--- a/arch/powerpc/boot/dtc-src/dtc-lexer.lex.c_shipped
+++ b/scripts/dtc/dtc-lexer.lex.c_shipped
diff --git a/arch/powerpc/boot/dtc-src/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped
index 27129377e5d2..27129377e5d2 100644
--- a/arch/powerpc/boot/dtc-src/dtc-parser.tab.c_shipped
+++ b/scripts/dtc/dtc-parser.tab.c_shipped
diff --git a/arch/powerpc/boot/dtc-src/dtc-parser.tab.h_shipped b/scripts/dtc/dtc-parser.tab.h_shipped
index ba99100d55c9..ba99100d55c9 100644
--- a/arch/powerpc/boot/dtc-src/dtc-parser.tab.h_shipped
+++ b/scripts/dtc/dtc-parser.tab.h_shipped
diff --git a/arch/powerpc/boot/dtc-src/dtc-parser.y b/scripts/dtc/dtc-parser.y
index b2ab562420ea..b2ab562420ea 100644
--- a/arch/powerpc/boot/dtc-src/dtc-parser.y
+++ b/scripts/dtc/dtc-parser.y
diff --git a/arch/powerpc/boot/dtc-src/dtc.c b/scripts/dtc/dtc.c
index d8fd43b4ac1a..d8fd43b4ac1a 100644
--- a/arch/powerpc/boot/dtc-src/dtc.c
+++ b/scripts/dtc/dtc.c
diff --git a/arch/powerpc/boot/dtc-src/dtc.h b/scripts/dtc/dtc.h
index 08d54c870086..08d54c870086 100644
--- a/arch/powerpc/boot/dtc-src/dtc.h
+++ b/scripts/dtc/dtc.h
diff --git a/arch/powerpc/boot/dtc-src/flattree.c b/scripts/dtc/flattree.c
index 76acd28c068d..76acd28c068d 100644
--- a/arch/powerpc/boot/dtc-src/flattree.c
+++ b/scripts/dtc/flattree.c
diff --git a/arch/powerpc/boot/dtc-src/fstree.c b/scripts/dtc/fstree.c
index 766b2694d935..766b2694d935 100644
--- a/arch/powerpc/boot/dtc-src/fstree.c
+++ b/scripts/dtc/fstree.c
diff --git a/arch/powerpc/boot/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt
index 6c42acfa21ec..6c42acfa21ec 100644
--- a/arch/powerpc/boot/libfdt/Makefile.libfdt
+++ b/scripts/dtc/libfdt/Makefile.libfdt
diff --git a/arch/powerpc/boot/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
index 2acaec5923ae..2acaec5923ae 100644
--- a/arch/powerpc/boot/libfdt/fdt.c
+++ b/scripts/dtc/libfdt/fdt.c
diff --git a/arch/powerpc/boot/libfdt/fdt.h b/scripts/dtc/libfdt/fdt.h
index 48ccfd910000..48ccfd910000 100644
--- a/arch/powerpc/boot/libfdt/fdt.h
+++ b/scripts/dtc/libfdt/fdt.h
diff --git a/arch/powerpc/boot/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
index fbbba44fcd0d..fbbba44fcd0d 100644
--- a/arch/powerpc/boot/libfdt/fdt_ro.c
+++ b/scripts/dtc/libfdt/fdt_ro.c
diff --git a/arch/powerpc/boot/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
index 8e7ec4cb7bcd..8e7ec4cb7bcd 100644
--- a/arch/powerpc/boot/libfdt/fdt_rw.c
+++ b/scripts/dtc/libfdt/fdt_rw.c
diff --git a/arch/powerpc/boot/libfdt/fdt_strerror.c b/scripts/dtc/libfdt/fdt_strerror.c
index e6c3ceee8c58..e6c3ceee8c58 100644
--- a/arch/powerpc/boot/libfdt/fdt_strerror.c
+++ b/scripts/dtc/libfdt/fdt_strerror.c
diff --git a/arch/powerpc/boot/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c
index 698329e0ccaf..698329e0ccaf 100644
--- a/arch/powerpc/boot/libfdt/fdt_sw.c
+++ b/scripts/dtc/libfdt/fdt_sw.c
diff --git a/arch/powerpc/boot/libfdt/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c
index a4652c6e787e..a4652c6e787e 100644
--- a/arch/powerpc/boot/libfdt/fdt_wip.c
+++ b/scripts/dtc/libfdt/fdt_wip.c
diff --git a/arch/powerpc/boot/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
index ce80e4fb41b2..ce80e4fb41b2 100644
--- a/arch/powerpc/boot/libfdt/libfdt.h
+++ b/scripts/dtc/libfdt/libfdt.h
diff --git a/arch/powerpc/boot/dtc-src/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h
index 449bf602daf1..449bf602daf1 100644
--- a/arch/powerpc/boot/dtc-src/libfdt_env.h
+++ b/scripts/dtc/libfdt/libfdt_env.h
diff --git a/arch/powerpc/boot/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h
index 46eb93e4af5c..46eb93e4af5c 100644
--- a/arch/powerpc/boot/libfdt/libfdt_internal.h
+++ b/scripts/dtc/libfdt/libfdt_internal.h
diff --git a/arch/powerpc/boot/dtc-src/livetree.c b/scripts/dtc/livetree.c
index 0ca3de550b3f..0ca3de550b3f 100644
--- a/arch/powerpc/boot/dtc-src/livetree.c
+++ b/scripts/dtc/livetree.c
diff --git a/arch/powerpc/boot/dtc-src/srcpos.c b/scripts/dtc/srcpos.c
index 9641b7628b4d..9641b7628b4d 100644
--- a/arch/powerpc/boot/dtc-src/srcpos.c
+++ b/scripts/dtc/srcpos.c
diff --git a/arch/powerpc/boot/dtc-src/srcpos.h b/scripts/dtc/srcpos.h
index e17c7c04db8e..e17c7c04db8e 100644
--- a/arch/powerpc/boot/dtc-src/srcpos.h
+++ b/scripts/dtc/srcpos.h
diff --git a/arch/powerpc/boot/dtc-src/treesource.c b/scripts/dtc/treesource.c
index ebeb6eb27907..ebeb6eb27907 100644
--- a/arch/powerpc/boot/dtc-src/treesource.c
+++ b/scripts/dtc/treesource.c
diff --git a/arch/powerpc/boot/dtc-src/version_gen.h b/scripts/dtc/version_gen.h
index 658ff42429d6..658ff42429d6 100644
--- a/arch/powerpc/boot/dtc-src/version_gen.h
+++ b/scripts/dtc/version_gen.h
diff --git a/scripts/kconfig/lxdialog/checklist.c b/scripts/kconfig/lxdialog/checklist.c
index b2a878c936d6..bcc6f19c3a35 100644
--- a/scripts/kconfig/lxdialog/checklist.c
+++ b/scripts/kconfig/lxdialog/checklist.c
@@ -41,7 +41,8 @@ static void print_item(WINDOW * win, int choice, int selected)
wmove(win, choice, check_x);
wattrset(win, selected ? dlg.check_selected.atr
: dlg.check.atr);
- wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' ');
+ if (!item_is_tag(':'))
+ wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' ');
wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr);
mvwaddch(win, choice, item_x, item_str()[0]);
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index 6841e95c0989..3bcacb4bfd3a 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -732,7 +732,12 @@ static void conf_choice(struct menu *menu)
for (child = menu->list; child; child = child->next) {
if (!menu_is_visible(child))
continue;
- item_make("%s", _(menu_get_prompt(child)));
+ if (child->sym)
+ item_make("%s", _(menu_get_prompt(child)));
+ else {
+ item_make("*** %s ***", _(menu_get_prompt(child)));
+ item_set_tag(':');
+ }
item_set_data(child);
if (child->sym == active)
item_set_selected(1);
@@ -748,6 +753,9 @@ static void conf_choice(struct menu *menu)
case 0:
if (selected) {
child = item_data();
+ if (!child->sym)
+ break;
+
sym_set_tristate_value(child->sym, yes);
}
return;
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 0f11870116dc..acd8c4a8e3e0 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -1411,7 +1411,8 @@ sub dump_struct($$) {
my $file = shift;
my $nested;
- if ($x =~/(struct|union)\s+(\w+)\s*{(.*)}/) {
+ if ($x =~ /(struct|union)\s+(\w+)\s*{(.*)}/) {
+ #my $decl_type = $1;
$declaration_name = $2;
my $members = $3;
@@ -1420,8 +1421,8 @@ sub dump_struct($$) {
$nested = $1;
# ignore members marked private:
- $members =~ s/\/\*.*?private:.*?public:.*?\*\///gos;
- $members =~ s/\/\*.*?private:.*//gos;
+ $members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gos;
+ $members =~ s/\/\*\s*private:.*//gos;
# strip comments:
$members =~ s/\/\*.*?\*\///gos;
$nested =~ s/\/\*.*?\*\///gos;
@@ -1827,6 +1828,25 @@ sub reset_state {
$state = 0;
}
+sub tracepoint_munge($) {
+ my $file = shift;
+ my $tracepointname = 0;
+ my $tracepointargs = 0;
+
+ if($prototype =~ m/TRACE_EVENT\((.*?),/) {
+ $tracepointname = $1;
+ }
+ if($prototype =~ m/TP_PROTO\((.*?)\)/) {
+ $tracepointargs = $1;
+ }
+ if (($tracepointname eq 0) || ($tracepointargs eq 0)) {
+ print STDERR "Warning(${file}:$.): Unrecognized tracepoint format: \n".
+ "$prototype\n";
+ } else {
+ $prototype = "static inline void trace_$tracepointname($tracepointargs)";
+ }
+}
+
sub syscall_munge() {
my $void = 0;
@@ -1881,6 +1901,9 @@ sub process_state3_function($$) {
if ($prototype =~ /SYSCALL_DEFINE/) {
syscall_munge();
}
+ if ($prototype =~ /TRACE_EVENT/) {
+ tracepoint_munge($file);
+ }
dump_function($prototype, $file);
reset_state();
}
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index df6e6286a065..161b7846733e 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -384,11 +384,19 @@ static int parse_elf(struct elf_info *info, const char *filename)
return 0;
}
/* Fix endianness in ELF header */
- hdr->e_shoff = TO_NATIVE(hdr->e_shoff);
- hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx);
- hdr->e_shnum = TO_NATIVE(hdr->e_shnum);
- hdr->e_machine = TO_NATIVE(hdr->e_machine);
- hdr->e_type = TO_NATIVE(hdr->e_type);
+ hdr->e_type = TO_NATIVE(hdr->e_type);
+ hdr->e_machine = TO_NATIVE(hdr->e_machine);
+ hdr->e_version = TO_NATIVE(hdr->e_version);
+ hdr->e_entry = TO_NATIVE(hdr->e_entry);
+ hdr->e_phoff = TO_NATIVE(hdr->e_phoff);
+ hdr->e_shoff = TO_NATIVE(hdr->e_shoff);
+ hdr->e_flags = TO_NATIVE(hdr->e_flags);
+ hdr->e_ehsize = TO_NATIVE(hdr->e_ehsize);
+ hdr->e_phentsize = TO_NATIVE(hdr->e_phentsize);
+ hdr->e_phnum = TO_NATIVE(hdr->e_phnum);
+ hdr->e_shentsize = TO_NATIVE(hdr->e_shentsize);
+ hdr->e_shnum = TO_NATIVE(hdr->e_shnum);
+ hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx);
sechdrs = (void *)hdr + hdr->e_shoff;
info->sechdrs = sechdrs;
@@ -402,13 +410,16 @@ static int parse_elf(struct elf_info *info, const char *filename)
/* Fix endianness in section headers */
for (i = 0; i < hdr->e_shnum; i++) {
- sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type);
- sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset);
- sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size);
- sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link);
- sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name);
- sechdrs[i].sh_info = TO_NATIVE(sechdrs[i].sh_info);
- sechdrs[i].sh_addr = TO_NATIVE(sechdrs[i].sh_addr);
+ sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name);
+ sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type);
+ sechdrs[i].sh_flags = TO_NATIVE(sechdrs[i].sh_flags);
+ sechdrs[i].sh_addr = TO_NATIVE(sechdrs[i].sh_addr);
+ sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset);
+ sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size);
+ sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link);
+ sechdrs[i].sh_info = TO_NATIVE(sechdrs[i].sh_info);
+ sechdrs[i].sh_addralign = TO_NATIVE(sechdrs[i].sh_addralign);
+ sechdrs[i].sh_entsize = TO_NATIVE(sechdrs[i].sh_entsize);
}
/* Find symbol table. */
for (i = 1; i < hdr->e_shnum; i++) {
@@ -716,41 +727,37 @@ int match(const char *sym, const char * const pat[])
/* sections that we do not want to do full section mismatch check on */
static const char *section_white_list[] =
- { ".debug*", ".stab*", ".note*", ".got*", ".toc*", NULL };
+{
+ ".comment*",
+ ".debug*",
+ ".mdebug*", /* alpha, score, mips etc. */
+ ".pdr", /* alpha, score, mips etc. */
+ ".stab*",
+ ".note*",
+ ".got*",
+ ".toc*",
+ NULL
+};
/*
- * Is this section one we do not want to check?
- * This is often debug sections.
- * If we are going to check this section then
- * test if section name ends with a dot and a number.
- * This is used to find sections where the linker have
- * appended a dot-number to make the name unique.
+ * This is used to find sections missing the SHF_ALLOC flag.
* The cause of this is often a section specified in assembler
- * without "ax" / "aw" and the same section used in .c
- * code where gcc add these.
+ * without "ax" / "aw".
*/
-static int check_section(const char *modname, const char *sec)
-{
- const char *e = sec + strlen(sec) - 1;
- if (match(sec, section_white_list))
- return 1;
-
- if (*e && isdigit(*e)) {
- /* consume all digits */
- while (*e && e != sec && isdigit(*e))
- e--;
- if (*e == '.' && !strstr(sec, ".linkonce")) {
- warn("%s (%s): unexpected section name.\n"
- "The (.[number]+) following section name are "
- "ld generated and not expected.\n"
- "Did you forget to use \"ax\"/\"aw\" "
- "in a .S file?\n"
- "Note that for example <linux/init.h> contains\n"
- "section definitions for use in .S files.\n\n",
- modname, sec);
- }
+static void check_section(const char *modname, struct elf_info *elf,
+ Elf_Shdr *sechdr)
+{
+ const char *sec = sech_name(elf, sechdr);
+
+ if (sechdr->sh_type == SHT_PROGBITS &&
+ !(sechdr->sh_flags & SHF_ALLOC) &&
+ !match(sec, section_white_list)) {
+ warn("%s (%s): unexpected non-allocatable section.\n"
+ "Did you forget to use \"ax\"/\"aw\" in a .S file?\n"
+ "Note that for example <linux/init.h> contains\n"
+ "section definitions for use in .S files.\n\n",
+ modname, sec);
}
- return 0;
}
@@ -794,15 +801,6 @@ static const char *init_exit_sections[] =
/* data section */
static const char *data_sections[] = { DATA_SECTIONS, NULL };
-/* sections that may refer to an init/exit section with no warning */
-static const char *initref_sections[] =
-{
- ".text.init.refok*",
- ".exit.text.refok*",
- ".data.init.refok*",
- NULL
-};
-
/* symbols in .data that may refer to init/exit sections */
static const char *symbol_white_list[] =
@@ -915,11 +913,6 @@ static int section_mismatch(const char *fromsec, const char *tosec)
/**
* Whitelist to allow certain references to pass with no warning.
*
- * Pattern 0:
- * Do not warn if funtion/data are marked with __init_refok/__initdata_refok.
- * The pattern is identified by:
- * fromsec = .text.init.refok* | .data.init.refok*
- *
* Pattern 1:
* If a module parameter is declared __initdata and permissions=0
* then this is legal despite the warning generated.
@@ -942,8 +935,7 @@ static int section_mismatch(const char *fromsec, const char *tosec)
* *probe_one, *_console, *_timer
*
* Pattern 3:
- * Whitelist all refereces from .text.head to .init.data
- * Whitelist all refereces from .text.head to .init.text
+ * Whitelist all references from .head.text to any init section
*
* Pattern 4:
* Some symbols belong to init section but still it is ok to reference
@@ -958,10 +950,6 @@ static int section_mismatch(const char *fromsec, const char *tosec)
static int secref_whitelist(const char *fromsec, const char *fromsym,
const char *tosec, const char *tosym)
{
- /* Check for pattern 0 */
- if (match(fromsec, initref_sections))
- return 0;
-
/* Check for pattern 1 */
if (match(tosec, init_data_sections) &&
match(fromsec, data_sections) &&
@@ -1377,7 +1365,7 @@ static void section_rela(const char *modname, struct elf_info *elf,
fromsec = sech_name(elf, sechdr);
fromsec += strlen(".rela");
/* if from section (name) is know good then skip it */
- if (check_section(modname, fromsec))
+ if (match(fromsec, section_white_list))
return;
for (rela = start; rela < stop; rela++) {
@@ -1421,7 +1409,7 @@ static void section_rel(const char *modname, struct elf_info *elf,
fromsec = sech_name(elf, sechdr);
fromsec += strlen(".rel");
/* if from section (name) is know good then skip it */
- if (check_section(modname, fromsec))
+ if (match(fromsec, section_white_list))
return;
for (rel = start; rel < stop; rel++) {
@@ -1484,6 +1472,7 @@ static void check_sec_ref(struct module *mod, const char *modname,
/* Walk through all sections */
for (i = 0; i < elf->hdr->e_shnum; i++) {
+ check_section(modname, elf, &elf->sechdrs[i]);
/* We want to process only relocation sections and not .init */
if (sechdrs[i].sh_type == SHT_RELA)
section_rela(modname, elf, &elf->sechdrs[i]);
@@ -2008,6 +1997,7 @@ static void read_markers(const char *fname)
if (!mod->skip)
add_marker(mod, marker, fmt);
}
+ release_file(file, size);
return;
fail:
fatal("parse error in markers list file\n");
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index 1264b8e2829d..01c2d13dd020 100644
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -1,38 +1,58 @@
#!/bin/sh
#
-# builddeb 1.2
+# builddeb 1.3
# Copyright 2003 Wichert Akkerman <wichert@wiggy.net>
#
# Simple script to generate a deb package for a Linux kernel. All the
-# complexity of what to do with a kernel after it is installer or removed
+# complexity of what to do with a kernel after it is installed or removed
# is left to other scripts and packages: they can install scripts in the
-# /etc/kernel/{pre,post}{inst,rm}.d/ directories that will be called on
-# package install and removal.
+# /etc/kernel/{pre,post}{inst,rm}.d/ directories (or an alternative location
+# specified in KDEB_HOOKDIR) that will be called on package install and
+# removal.
set -e
+create_package() {
+ local pname="$1" pdir="$2"
+
+ cp debian/copyright "$pdir/usr/share/doc/$pname/"
+
+ # Fix ownership and permissions
+ chown -R root:root "$pdir"
+ chmod -R go-w "$pdir"
+
+ # Create the package
+ dpkg-gencontrol -isp -p$pname -P"$pdir"
+ dpkg --build "$pdir" ..
+}
+
# Some variables and settings used throughout the script
version=$KERNELRELEASE
-revision=`cat .version`
+revision=$(cat .version)
+if [ -n "$KDEB_PKGVERSION" ]; then
+ packageversion=$KDEB_PKGVERSION
+else
+ packageversion=$version-$revision
+fi
tmpdir="$objtree/debian/tmp"
fwdir="$objtree/debian/fwtmp"
-packagename=linux-$version
+packagename=linux-image-$version
fwpackagename=linux-firmware-image
-if [ "$ARCH" == "um" ] ; then
+if [ "$ARCH" = "um" ] ; then
packagename=user-mode-linux-$version
fi
# Setup the directory structure
rm -rf "$tmpdir" "$fwdir"
-mkdir -p "$tmpdir/DEBIAN" "$tmpdir/lib" "$tmpdir/boot"
-mkdir -p "$fwdir/DEBIAN" "$fwdir/lib"
-if [ "$ARCH" == "um" ] ; then
- mkdir -p "$tmpdir/usr/lib/uml/modules/$version" "$tmpdir/usr/share/doc/$packagename" "$tmpdir/usr/bin"
+mkdir -p "$tmpdir/DEBIAN" "$tmpdir/lib" "$tmpdir/boot" "$tmpdir/usr/share/doc/$packagename"
+mkdir -p "$fwdir/DEBIAN" "$fwdir/lib" "$fwdir/usr/share/doc/$fwpackagename"
+if [ "$ARCH" = "um" ] ; then
+ mkdir -p "$tmpdir/usr/lib/uml/modules/$version" "$tmpdir/usr/bin"
fi
# Build and install the kernel
-if [ "$ARCH" == "um" ] ; then
+if [ "$ARCH" = "um" ] ; then
$MAKE linux
cp System.map "$tmpdir/usr/lib/uml/modules/$version/System.map"
cp .config "$tmpdir/usr/share/doc/$packagename/config"
@@ -41,53 +61,100 @@ if [ "$ARCH" == "um" ] ; then
else
cp System.map "$tmpdir/boot/System.map-$version"
cp .config "$tmpdir/boot/config-$version"
- cp $KBUILD_IMAGE "$tmpdir/boot/vmlinuz-$version"
+ # Not all arches include the boot path in KBUILD_IMAGE
+ if ! cp $KBUILD_IMAGE "$tmpdir/boot/vmlinuz-$version"; then
+ cp arch/$ARCH/boot/$KBUILD_IMAGE "$tmpdir/boot/vmlinuz-$version"
+ fi
fi
if grep -q '^CONFIG_MODULES=y' .config ; then
INSTALL_MOD_PATH="$tmpdir" make KBUILD_SRC= modules_install
- if [ "$ARCH" == "um" ] ; then
+ if [ "$ARCH" = "um" ] ; then
mv "$tmpdir/lib/modules/$version"/* "$tmpdir/usr/lib/uml/modules/$version/"
rmdir "$tmpdir/lib/modules/$version"
fi
fi
# Install the maintainer scripts
+# Note: hook scripts under /etc/kernel are also executed by official Debian
+# kernel packages, as well as kernel packages built using make-kpkg
+debhookdir=${KDEB_HOOKDIR:-/etc/kernel}
for script in postinst postrm preinst prerm ; do
- mkdir -p "$tmpdir/etc/kernel/$script.d"
+ mkdir -p "$tmpdir$debhookdir/$script.d"
cat <<EOF > "$tmpdir/DEBIAN/$script"
#!/bin/sh
set -e
-test -d /etc/kernel/$script.d && run-parts --arg="$version" /etc/kernel/$script.d
+# Pass maintainer script parameters to hook scripts
+export DEB_MAINT_PARAMS="\$@"
+
+test -d $debhookdir/$script.d && run-parts --arg="$version" $debhookdir/$script.d
exit 0
EOF
chmod 755 "$tmpdir/DEBIAN/$script"
done
-name="Kernel Compiler <$(id -nu)@$(hostname -f)>"
+# Try to determine maintainer and email values
+if [ -n "$DEBEMAIL" ]; then
+ email=$DEBEMAIL
+elif [ -n "$EMAIL" ]; then
+ email=$EMAIL
+else
+ email=$(id -nu)@$(hostname -f)
+fi
+if [ -n "$DEBFULLNAME" ]; then
+ name=$DEBFULLNAME
+elif [ -n "$NAME" ]; then
+ name=$NAME
+else
+ name="Anonymous"
+fi
+maintainer="$name <$email>"
+
# Generate a simple changelog template
cat <<EOF > debian/changelog
-linux ($version-$revision) unstable; urgency=low
+linux-upstream ($packageversion) unstable; urgency=low
- * A standard release
+ * Custom built Linux kernel.
- -- $name $(date -R)
+ -- $maintainer $(date -R)
EOF
-# Generate a control file
-if [ "$ARCH" == "um" ]; then
+# Generate copyright file
+cat <<EOF > debian/copyright
+This is a packacked upstream version of the Linux kernel.
+
+The sources may be found at most Linux ftp sites, including:
+ftp://ftp.kernel.org/pub/linux/kernel
+Copyright: 1991 - 2009 Linus Torvalds and others.
+
+The git repository for mainline kernel development is at:
+git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
+
+ 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 dated June, 1991.
+
+On Debian GNU/Linux systems, the complete text of the GNU General Public
+License version 2 can be found in \`/usr/share/common-licenses/GPL-2'.
+EOF
+
+# Generate a control file
cat <<EOF > debian/control
-Source: linux
-Section: base
+Source: linux-upstream
+Section: admin
Priority: optional
-Maintainer: $name
-Standards-Version: 3.6.1
+Maintainer: $maintainer
+Standards-Version: 3.8.1
+EOF
+
+if [ "$ARCH" = "um" ]; then
+ cat <<EOF >> debian/control
Package: $packagename
-Provides: kernel-image-$version, linux-image-$version
+Provides: linux-image, linux-image-2.6, linux-modules-$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
@@ -97,30 +164,22 @@ Description: User Mode Linux kernel, version $version
many other things.
.
This package contains the Linux kernel, modules and corresponding other
- files version $version
+ files, version: $version.
EOF
else
-cat <<EOF > debian/control
-Source: linux
-Section: base
-Priority: optional
-Maintainer: $name
-Standards-Version: 3.6.1
+ cat <<EOF >> debian/control
Package: $packagename
-Provides: kernel-image-$version, linux-image-$version
+Provides: linux-image, linux-image-2.6, linux-modules-$version
Suggests: $fwpackagename
Architecture: any
Description: Linux kernel, version $version
This package contains the Linux kernel, modules and corresponding other
- files version $version
+ files, version: $version.
EOF
-fi
-# Fix some ownership and permissions
-chown -R root:root "$tmpdir"
-chmod -R go-w "$tmpdir"
+fi
# Do we have firmware? Move it out of the way and build it into a package.
if [ -e "$tmpdir/lib/firmware" ]; then
@@ -131,16 +190,12 @@ if [ -e "$tmpdir/lib/firmware" ]; then
Package: $fwpackagename
Architecture: all
Description: Linux kernel firmware, version $version
- This package contains firmware from the Linux kernel, version $version
+ This package contains firmware from the Linux kernel, version $version.
EOF
- dpkg-gencontrol -isp -p$fwpackagename -P"$fwdir"
- dpkg --build "$fwdir" ..
+ create_package "$fwpackagename" "$fwdir"
fi
-# Perform the final magic
-dpkg-gencontrol -isp -p$packagename
-dpkg --build "$tmpdir" ..
+create_package "$packagename" "$tmpdir"
exit 0
-
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 409596eca124..0fae7da0529c 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -26,7 +26,7 @@
# which will also be the location of that section after final link.
# e.g.
#
-# .section ".text.sched"
+# .section ".sched.text", "ax"
# .globl my_func
# my_func:
# [...]
@@ -39,7 +39,7 @@
# [...]
#
# Both relocation offsets for the mcounts in the above example will be
-# offset from .text.sched. If we make another file called tmp.s with:
+# offset from .sched.text. If we make another file called tmp.s with:
#
# .section __mcount_loc
# .quad my_func + 0x5
@@ -51,7 +51,7 @@
# But this gets hard if my_func is not globl (a static function).
# In such a case we have:
#
-# .section ".text.sched"
+# .section ".sched.text", "ax"
# my_func:
# [...]
# call mcount (offset: 0x5)
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
index 47e75b69a2e9..32c8554f3946 100755
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -10,13 +10,12 @@ cd "${1:-.}" || usage
# Check for git and a git repo.
if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
- # Do we have an untagged version?
- if git name-rev --tags HEAD | grep -E '^HEAD[[:space:]]+(.*~[0-9]*|undefined)$' > /dev/null; then
- if tag=`git describe 2>/dev/null`; then
- echo $tag | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
- else
- printf '%s%s' -g $head
- fi
+ # Do we have an untagged tag?
+ if atag=`git describe 2>/dev/null`; then
+ echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
+ # add -g${head}, if there is no usable tag
+ else
+ printf '%s%s' -g $head
fi
# Is this git on svn?
diff --git a/scripts/tags.sh b/scripts/tags.sh
index 5bd8b1003d44..4a34ec591e8c 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -164,10 +164,12 @@ case "$1" in
;;
"tags")
+ rm -f tags
xtags ctags
;;
"TAGS")
+ rm -f TAGS
xtags etags
;;
esac
diff --git a/security/Makefile b/security/Makefile
index fa77021d9778..c67557cdaa85 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -16,6 +16,9 @@ obj-$(CONFIG_SECURITYFS) += inode.o
# Must precede capability.o in order to stack properly.
obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
+ifeq ($(CONFIG_AUDIT),y)
+obj-$(CONFIG_SECURITY_SMACK) += lsm_audit.o
+endif
obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o
obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o
obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
diff --git a/security/commoncap.c b/security/commoncap.c
index beac0258c2a8..48b7e0228fa3 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -28,6 +28,28 @@
#include <linux/prctl.h>
#include <linux/securebits.h>
+/*
+ * If a non-root user executes a setuid-root binary in
+ * !secure(SECURE_NOROOT) mode, then we raise capabilities.
+ * However if fE is also set, then the intent is for only
+ * the file capabilities to be applied, and the setuid-root
+ * bit is left on either to change the uid (plausible) or
+ * to get full privilege on a kernel without file capabilities
+ * support. So in that case we do not raise capabilities.
+ *
+ * Warn if that happens, once per boot.
+ */
+static void warn_setuid_and_fcaps_mixed(char *fname)
+{
+ static int warned;
+ if (!warned) {
+ printk(KERN_INFO "warning: `%s' has both setuid-root and"
+ " effective capabilities. Therefore not raising all"
+ " capabilities.\n", fname);
+ warned = 1;
+ }
+}
+
int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
{
NETLINK_CB(skb).eff_cap = current_cap();
@@ -464,6 +486,15 @@ int cap_bprm_set_creds(struct linux_binprm *bprm)
if (!issecure(SECURE_NOROOT)) {
/*
+ * If the legacy file capability is set, then don't set privs
+ * for a setuid root binary run by a non-root user. Do set it
+ * for a root user just to cause least surprise to an admin.
+ */
+ if (effective && new->uid != 0 && new->euid == 0) {
+ warn_setuid_and_fcaps_mixed(bprm->filename);
+ goto skip;
+ }
+ /*
* To support inheritance of root-permissions and suid-root
* executables under compatibility mode, we override the
* capability sets for the file.
@@ -478,6 +509,7 @@ int cap_bprm_set_creds(struct linux_binprm *bprm)
if (new->euid == 0)
effective = true;
}
+skip:
/* Don't let someone trace a set[ug]id/setpcap binary with the revised
* credentials unless they have the appropriate permit
diff --git a/security/integrity/ima/ima_audit.c b/security/integrity/ima/ima_audit.c
index 1e082bb987be..b628eea477a6 100644
--- a/security/integrity/ima/ima_audit.c
+++ b/security/integrity/ima/ima_audit.c
@@ -22,18 +22,9 @@ static int ima_audit;
static int __init ima_audit_setup(char *str)
{
unsigned long audit;
- int rc, result = 0;
- char *op = "ima_audit";
- char *cause;
- rc = strict_strtoul(str, 0, &audit);
- if (rc || audit > 1)
- result = 1;
- else
- ima_audit = audit;
- cause = ima_audit ? "enabled" : "not_enabled";
- integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
- op, cause, result, 0);
+ if (!strict_strtoul(str, 0, &audit))
+ ima_audit = audit ? 1 : 0;
return 1;
}
__setup("ima_audit=", ima_audit_setup);
@@ -54,19 +45,10 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
audit_get_loginuid(current),
audit_get_sessionid(current));
audit_log_task_context(ab);
- switch (audit_msgno) {
- case AUDIT_INTEGRITY_DATA:
- case AUDIT_INTEGRITY_METADATA:
- case AUDIT_INTEGRITY_PCR:
- case AUDIT_INTEGRITY_STATUS:
- audit_log_format(ab, " op=%s cause=%s", op, cause);
- break;
- case AUDIT_INTEGRITY_HASH:
- audit_log_format(ab, " op=%s hash=%s", op, cause);
- break;
- default:
- audit_log_format(ab, " op=%s", op);
- }
+ audit_log_format(ab, " op=");
+ audit_log_string(ab, op);
+ audit_log_format(ab, " cause=");
+ audit_log_string(ab, cause);
audit_log_format(ab, " comm=");
audit_log_untrustedstring(ab, current->comm);
if (fname) {
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index ffbe259700b1..510186f0b72e 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -84,8 +84,8 @@ static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *pos)
* against concurrent list-extension
*/
rcu_read_lock();
- qe = list_entry(rcu_dereference(qe->later.next),
- struct ima_queue_entry, later);
+ qe = list_entry_rcu(qe->later.next,
+ struct ima_queue_entry, later);
rcu_read_unlock();
(*pos)++;
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index f4e7266f5aee..122f17fc7fc1 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -29,20 +29,8 @@ int ima_initialized;
char *ima_hash = "sha1";
static int __init hash_setup(char *str)
{
- const char *op = "hash_setup";
- const char *hash = "sha1";
- int result = 0;
- int audit_info = 0;
-
- if (strncmp(str, "md5", 3) == 0) {
- hash = "md5";
- ima_hash = str;
- } else if (strncmp(str, "sha1", 4) != 0) {
- hash = "invalid_hash_type";
- result = 1;
- }
- integrity_audit_msg(AUDIT_INTEGRITY_HASH, NULL, NULL, op, hash,
- result, audit_info);
+ if (strncmp(str, "md5", 3) == 0)
+ ima_hash = "md5";
return 1;
}
__setup("ima_hash=", hash_setup);
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index b5291ad5ef56..b168c1d595ce 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -96,7 +96,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
if ((rule->flags & IMA_UID) && rule->uid != tsk->cred->uid)
return false;
for (i = 0; i < MAX_LSM_RULES; i++) {
- int rc;
+ int rc = 0;
u32 osid, sid;
if (!rule->lsm[i].rule)
@@ -109,7 +109,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
security_inode_getsecid(inode, &osid);
rc = security_filter_rule_match(osid,
rule->lsm[i].type,
- AUDIT_EQUAL,
+ Audit_equal,
rule->lsm[i].rule,
NULL);
break;
@@ -119,7 +119,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
security_task_getsecid(tsk, &sid);
rc = security_filter_rule_match(sid,
rule->lsm[i].type,
- AUDIT_EQUAL,
+ Audit_equal,
rule->lsm[i].rule,
NULL);
default:
@@ -227,7 +227,7 @@ static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry,
entry->lsm[lsm_rule].type = audit_type;
result = security_filter_rule_init(entry->lsm[lsm_rule].type,
- AUDIT_EQUAL, args,
+ Audit_equal, args,
&entry->lsm[lsm_rule].rule);
return result;
}
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
new file mode 100644
index 000000000000..94b868494b31
--- /dev/null
+++ b/security/lsm_audit.c
@@ -0,0 +1,386 @@
+/*
+ * common LSM auditing functions
+ *
+ * Based on code written for SELinux by :
+ * Stephen Smalley, <sds@epoch.ncsc.mil>
+ * James Morris <jmorris@redhat.com>
+ * Author : Etienne Basset, <etienne.basset@ensta.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/types.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <net/sock.h>
+#include <linux/un.h>
+#include <net/af_unix.h>
+#include <linux/audit.h>
+#include <linux/ipv6.h>
+#include <linux/ip.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/dccp.h>
+#include <linux/sctp.h>
+#include <linux/lsm_audit.h>
+
+/**
+ * ipv4_skb_to_auditdata : fill auditdata from skb
+ * @skb : the skb
+ * @ad : the audit data to fill
+ * @proto : the layer 4 protocol
+ *
+ * return 0 on success
+ */
+int ipv4_skb_to_auditdata(struct sk_buff *skb,
+ struct common_audit_data *ad, u8 *proto)
+{
+ int ret = 0;
+ struct iphdr *ih;
+
+ ih = ip_hdr(skb);
+ if (ih == NULL)
+ return -EINVAL;
+
+ ad->u.net.v4info.saddr = ih->saddr;
+ ad->u.net.v4info.daddr = ih->daddr;
+
+ if (proto)
+ *proto = ih->protocol;
+ /* non initial fragment */
+ if (ntohs(ih->frag_off) & IP_OFFSET)
+ return 0;
+
+ switch (ih->protocol) {
+ case IPPROTO_TCP: {
+ struct tcphdr *th = tcp_hdr(skb);
+ if (th == NULL)
+ break;
+
+ ad->u.net.sport = th->source;
+ ad->u.net.dport = th->dest;
+ break;
+ }
+ case IPPROTO_UDP: {
+ struct udphdr *uh = udp_hdr(skb);
+ if (uh == NULL)
+ break;
+
+ ad->u.net.sport = uh->source;
+ ad->u.net.dport = uh->dest;
+ break;
+ }
+ case IPPROTO_DCCP: {
+ struct dccp_hdr *dh = dccp_hdr(skb);
+ if (dh == NULL)
+ break;
+
+ ad->u.net.sport = dh->dccph_sport;
+ ad->u.net.dport = dh->dccph_dport;
+ break;
+ }
+ case IPPROTO_SCTP: {
+ struct sctphdr *sh = sctp_hdr(skb);
+ if (sh == NULL)
+ break;
+ ad->u.net.sport = sh->source;
+ ad->u.net.dport = sh->dest;
+ break;
+ }
+ default:
+ ret = -EINVAL;
+ }
+ return ret;
+}
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+/**
+ * ipv6_skb_to_auditdata : fill auditdata from skb
+ * @skb : the skb
+ * @ad : the audit data to fill
+ * @proto : the layer 4 protocol
+ *
+ * return 0 on success
+ */
+int ipv6_skb_to_auditdata(struct sk_buff *skb,
+ struct common_audit_data *ad, u8 *proto)
+{
+ int offset, ret = 0;
+ struct ipv6hdr *ip6;
+ u8 nexthdr;
+
+ ip6 = ipv6_hdr(skb);
+ if (ip6 == NULL)
+ return -EINVAL;
+ ipv6_addr_copy(&ad->u.net.v6info.saddr, &ip6->saddr);
+ ipv6_addr_copy(&ad->u.net.v6info.daddr, &ip6->daddr);
+ ret = 0;
+ /* IPv6 can have several extension header before the Transport header
+ * skip them */
+ offset = skb_network_offset(skb);
+ offset += sizeof(*ip6);
+ nexthdr = ip6->nexthdr;
+ offset = ipv6_skip_exthdr(skb, offset, &nexthdr);
+ if (offset < 0)
+ return 0;
+ if (proto)
+ *proto = nexthdr;
+ switch (nexthdr) {
+ case IPPROTO_TCP: {
+ struct tcphdr _tcph, *th;
+
+ th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
+ if (th == NULL)
+ break;
+
+ ad->u.net.sport = th->source;
+ ad->u.net.dport = th->dest;
+ break;
+ }
+ case IPPROTO_UDP: {
+ struct udphdr _udph, *uh;
+
+ uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
+ if (uh == NULL)
+ break;
+
+ ad->u.net.sport = uh->source;
+ ad->u.net.dport = uh->dest;
+ break;
+ }
+ case IPPROTO_DCCP: {
+ struct dccp_hdr _dccph, *dh;
+
+ dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
+ if (dh == NULL)
+ break;
+
+ ad->u.net.sport = dh->dccph_sport;
+ ad->u.net.dport = dh->dccph_dport;
+ break;
+ }
+ case IPPROTO_SCTP: {
+ struct sctphdr _sctph, *sh;
+
+ sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
+ if (sh == NULL)
+ break;
+ ad->u.net.sport = sh->source;
+ ad->u.net.dport = sh->dest;
+ break;
+ }
+ default:
+ ret = -EINVAL;
+ }
+ return ret;
+}
+#endif
+
+
+static inline void print_ipv6_addr(struct audit_buffer *ab,
+ struct in6_addr *addr, __be16 port,
+ char *name1, char *name2)
+{
+ if (!ipv6_addr_any(addr))
+ audit_log_format(ab, " %s=%pI6", name1, addr);
+ if (port)
+ audit_log_format(ab, " %s=%d", name2, ntohs(port));
+}
+
+static inline void print_ipv4_addr(struct audit_buffer *ab, __be32 addr,
+ __be16 port, char *name1, char *name2)
+{
+ if (addr)
+ audit_log_format(ab, " %s=%pI4", name1, &addr);
+ if (port)
+ audit_log_format(ab, " %s=%d", name2, ntohs(port));
+}
+
+/**
+ * dump_common_audit_data - helper to dump common audit data
+ * @a : common audit data
+ *
+ */
+static void dump_common_audit_data(struct audit_buffer *ab,
+ struct common_audit_data *a)
+{
+ struct inode *inode = NULL;
+ struct task_struct *tsk = current;
+
+ if (a->tsk)
+ tsk = a->tsk;
+ if (tsk && tsk->pid) {
+ audit_log_format(ab, " pid=%d comm=", tsk->pid);
+ audit_log_untrustedstring(ab, tsk->comm);
+ }
+
+ switch (a->type) {
+ case LSM_AUDIT_DATA_IPC:
+ audit_log_format(ab, " key=%d ", a->u.ipc_id);
+ break;
+ case LSM_AUDIT_DATA_CAP:
+ audit_log_format(ab, " capability=%d ", a->u.cap);
+ break;
+ case LSM_AUDIT_DATA_FS:
+ if (a->u.fs.path.dentry) {
+ struct dentry *dentry = a->u.fs.path.dentry;
+ if (a->u.fs.path.mnt) {
+ audit_log_d_path(ab, "path=", &a->u.fs.path);
+ } else {
+ audit_log_format(ab, " name=");
+ audit_log_untrustedstring(ab,
+ dentry->d_name.name);
+ }
+ inode = dentry->d_inode;
+ } else if (a->u.fs.inode) {
+ struct dentry *dentry;
+ inode = a->u.fs.inode;
+ dentry = d_find_alias(inode);
+ if (dentry) {
+ audit_log_format(ab, " name=");
+ audit_log_untrustedstring(ab,
+ dentry->d_name.name);
+ dput(dentry);
+ }
+ }
+ if (inode)
+ audit_log_format(ab, " dev=%s ino=%lu",
+ inode->i_sb->s_id,
+ inode->i_ino);
+ break;
+ case LSM_AUDIT_DATA_TASK:
+ tsk = a->u.tsk;
+ if (tsk && tsk->pid) {
+ audit_log_format(ab, " pid=%d comm=", tsk->pid);
+ audit_log_untrustedstring(ab, tsk->comm);
+ }
+ break;
+ case LSM_AUDIT_DATA_NET:
+ if (a->u.net.sk) {
+ struct sock *sk = a->u.net.sk;
+ struct unix_sock *u;
+ int len = 0;
+ char *p = NULL;
+
+ switch (sk->sk_family) {
+ case AF_INET: {
+ struct inet_sock *inet = inet_sk(sk);
+
+ print_ipv4_addr(ab, inet->rcv_saddr,
+ inet->sport,
+ "laddr", "lport");
+ print_ipv4_addr(ab, inet->daddr,
+ inet->dport,
+ "faddr", "fport");
+ break;
+ }
+ case AF_INET6: {
+ struct inet_sock *inet = inet_sk(sk);
+ struct ipv6_pinfo *inet6 = inet6_sk(sk);
+
+ print_ipv6_addr(ab, &inet6->rcv_saddr,
+ inet->sport,
+ "laddr", "lport");
+ print_ipv6_addr(ab, &inet6->daddr,
+ inet->dport,
+ "faddr", "fport");
+ break;
+ }
+ case AF_UNIX:
+ u = unix_sk(sk);
+ if (u->dentry) {
+ struct path path = {
+ .dentry = u->dentry,
+ .mnt = u->mnt
+ };
+ audit_log_d_path(ab, "path=", &path);
+ break;
+ }
+ if (!u->addr)
+ break;
+ len = u->addr->len-sizeof(short);
+ p = &u->addr->name->sun_path[0];
+ audit_log_format(ab, " path=");
+ if (*p)
+ audit_log_untrustedstring(ab, p);
+ else
+ audit_log_n_hex(ab, p, len);
+ break;
+ }
+ }
+
+ switch (a->u.net.family) {
+ case AF_INET:
+ print_ipv4_addr(ab, a->u.net.v4info.saddr,
+ a->u.net.sport,
+ "saddr", "src");
+ print_ipv4_addr(ab, a->u.net.v4info.daddr,
+ a->u.net.dport,
+ "daddr", "dest");
+ break;
+ case AF_INET6:
+ print_ipv6_addr(ab, &a->u.net.v6info.saddr,
+ a->u.net.sport,
+ "saddr", "src");
+ print_ipv6_addr(ab, &a->u.net.v6info.daddr,
+ a->u.net.dport,
+ "daddr", "dest");
+ break;
+ }
+ if (a->u.net.netif > 0) {
+ struct net_device *dev;
+
+ /* NOTE: we always use init's namespace */
+ dev = dev_get_by_index(&init_net, a->u.net.netif);
+ if (dev) {
+ audit_log_format(ab, " netif=%s", dev->name);
+ dev_put(dev);
+ }
+ }
+ break;
+#ifdef CONFIG_KEYS
+ case LSM_AUDIT_DATA_KEY:
+ audit_log_format(ab, " key_serial=%u", a->u.key_struct.key);
+ if (a->u.key_struct.key_desc) {
+ audit_log_format(ab, " key_desc=");
+ audit_log_untrustedstring(ab, a->u.key_struct.key_desc);
+ }
+ break;
+#endif
+ } /* switch (a->type) */
+}
+
+/**
+ * common_lsm_audit - generic LSM auditing function
+ * @a: auxiliary audit data
+ *
+ * setup the audit buffer for common security information
+ * uses callback to print LSM specific information
+ */
+void common_lsm_audit(struct common_audit_data *a)
+{
+ struct audit_buffer *ab;
+
+ if (a == NULL)
+ return;
+ /* we use GFP_ATOMIC so we won't sleep */
+ ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC);
+
+ if (ab == NULL)
+ return;
+
+ if (a->lsm_pre_audit)
+ a->lsm_pre_audit(ab, a);
+
+ dump_common_audit_data(ab, a);
+
+ if (a->lsm_post_audit)
+ a->lsm_post_audit(ab, a);
+
+ audit_log_end(ab);
+}
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 7f9b5fac8779..b2ab60859832 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -927,7 +927,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
if (denied) {
if (flags & AVC_STRICT)
rc = -EACCES;
- else if (!selinux_enforcing || security_permissive_sid(ssid))
+ else if (!selinux_enforcing || (avd->flags & AVD_FLAGS_PERMISSIVE))
avc_update_node(AVC_CALLBACK_GRANT, requested, ssid,
tsid, tclass, avd->seqno);
else
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index ba808ef6babb..195906bce266 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1980,10 +1980,6 @@ static int selinux_sysctl(ctl_table *table, int op)
u32 tsid, sid;
int rc;
- rc = secondary_ops->sysctl(table, op);
- if (rc)
- return rc;
-
sid = current_sid();
rc = selinux_sysctl_get_sid(table, (op == 0001) ?
@@ -2375,10 +2371,8 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
{
const struct task_security_struct *tsec = current_security();
struct itimerval itimer;
- struct sighand_struct *psig;
u32 osid, sid;
int rc, i;
- unsigned long flags;
osid = tsec->osid;
sid = tsec->sid;
@@ -2398,22 +2392,20 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
memset(&itimer, 0, sizeof itimer);
for (i = 0; i < 3; i++)
do_setitimer(i, &itimer, NULL);
- flush_signals(current);
spin_lock_irq(&current->sighand->siglock);
- flush_signal_handlers(current, 1);
- sigemptyset(&current->blocked);
- recalc_sigpending();
+ if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) {
+ __flush_signals(current);
+ flush_signal_handlers(current, 1);
+ sigemptyset(&current->blocked);
+ }
spin_unlock_irq(&current->sighand->siglock);
}
/* Wake up the parent if it is waiting so that it can recheck
* wait permission to the new task SID. */
- read_lock_irq(&tasklist_lock);
- psig = current->parent->sighand;
- spin_lock_irqsave(&psig->siglock, flags);
- wake_up_interruptible(&current->parent->signal->wait_chldexit);
- spin_unlock_irqrestore(&psig->siglock, flags);
- read_unlock_irq(&tasklist_lock);
+ read_lock(&tasklist_lock);
+ wake_up_interruptible(&current->real_parent->signal->wait_chldexit);
+ read_unlock(&tasklist_lock);
}
/* superblock security operations */
@@ -3153,7 +3145,7 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk,
struct fown_struct *fown, int signum)
{
struct file *file;
- u32 sid = current_sid();
+ u32 sid = task_sid(tsk);
u32 perm;
struct file_security_struct *fsec;
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 5c3434f7626f..a7be3f01fb08 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -91,9 +91,11 @@ struct av_decision {
u32 auditallow;
u32 auditdeny;
u32 seqno;
+ u32 flags;
};
-int security_permissive_sid(u32 sid);
+/* definitions of av_decision.flags */
+#define AVD_FLAGS_PERMISSIVE 0x0001
int security_compute_av(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 2d5136ec3d54..8d4007fbe0e9 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -527,10 +527,10 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size)
goto out2;
length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT,
- "%x %x %x %x %u",
+ "%x %x %x %x %u %x",
avd.allowed, 0xffffffff,
avd.auditallow, avd.auditdeny,
- avd.seqno);
+ avd.seqno, avd.flags);
out2:
kfree(tcon);
out:
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index deeec6c013ae..500e6f78e115 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -410,6 +410,7 @@ static int context_struct_compute_av(struct context *scontext,
avd->auditallow = 0;
avd->auditdeny = 0xffffffff;
avd->seqno = latest_granting;
+ avd->flags = 0;
/*
* Check for all the invalid cases.
@@ -528,31 +529,6 @@ inval_class:
return 0;
}
-/*
- * Given a sid find if the type has the permissive flag set
- */
-int security_permissive_sid(u32 sid)
-{
- struct context *context;
- u32 type;
- int rc;
-
- read_lock(&policy_rwlock);
-
- context = sidtab_search(&sidtab, sid);
- BUG_ON(!context);
-
- type = context->type;
- /*
- * we are intentionally using type here, not type-1, the 0th bit may
- * someday indicate that we are globally setting permissive in policy.
- */
- rc = ebitmap_get_bit(&policydb.permissive_map, type);
-
- read_unlock(&policy_rwlock);
- return rc;
-}
-
static int security_validtrans_handle_fail(struct context *ocontext,
struct context *ncontext,
struct context *tcontext,
@@ -767,6 +743,10 @@ int security_compute_av(u32 ssid,
rc = context_struct_compute_av(scontext, tcontext, tclass,
requested, avd);
+
+ /* permissive domain? */
+ if (ebitmap_get_bit(&policydb.permissive_map, scontext->type))
+ avd->flags |= AVD_FLAGS_PERMISSIVE;
out:
read_unlock(&policy_rwlock);
return rc;
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 42ef313f9856..243bec175be0 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -20,6 +20,7 @@
#include <net/netlabel.h>
#include <linux/list.h>
#include <linux/rculist.h>
+#include <linux/lsm_audit.h>
/*
* Why 23? CIPSO is constrained to 30, so a 32 byte buffer is
@@ -179,6 +180,20 @@ struct smack_known {
#define MAY_NOT 0
/*
+ * Number of access types used by Smack (rwxa)
+ */
+#define SMK_NUM_ACCESS_TYPE 4
+
+/*
+ * Smack audit data; is empty if CONFIG_AUDIT not set
+ * to save some stack
+ */
+struct smk_audit_info {
+#ifdef CONFIG_AUDIT
+ struct common_audit_data a;
+#endif
+};
+/*
* These functions are in smack_lsm.c
*/
struct inode_smack *new_inode_smack(char *);
@@ -186,8 +201,8 @@ struct inode_smack *new_inode_smack(char *);
/*
* These functions are in smack_access.c
*/
-int smk_access(char *, char *, int);
-int smk_curacc(char *, u32);
+int smk_access(char *, char *, int, struct smk_audit_info *);
+int smk_curacc(char *, u32, struct smk_audit_info *);
int smack_to_cipso(const char *, struct smack_cipso *);
void smack_from_cipso(u32, char *, char *);
char *smack_from_secid(const u32);
@@ -237,4 +252,93 @@ static inline char *smk_of_inode(const struct inode *isp)
return sip->smk_inode;
}
+/*
+ * logging functions
+ */
+#define SMACK_AUDIT_DENIED 0x1
+#define SMACK_AUDIT_ACCEPT 0x2
+extern int log_policy;
+
+void smack_log(char *subject_label, char *object_label,
+ int request,
+ int result, struct smk_audit_info *auditdata);
+
+#ifdef CONFIG_AUDIT
+
+/*
+ * some inline functions to set up audit data
+ * they do nothing if CONFIG_AUDIT is not set
+ *
+ */
+static inline void smk_ad_init(struct smk_audit_info *a, const char *func,
+ char type)
+{
+ memset(a, 0, sizeof(*a));
+ a->a.type = type;
+ a->a.function = func;
+}
+
+static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a,
+ struct task_struct *t)
+{
+ a->a.u.tsk = t;
+}
+static inline void smk_ad_setfield_u_fs_path_dentry(struct smk_audit_info *a,
+ struct dentry *d)
+{
+ a->a.u.fs.path.dentry = d;
+}
+static inline void smk_ad_setfield_u_fs_path_mnt(struct smk_audit_info *a,
+ struct vfsmount *m)
+{
+ a->a.u.fs.path.mnt = m;
+}
+static inline void smk_ad_setfield_u_fs_inode(struct smk_audit_info *a,
+ struct inode *i)
+{
+ a->a.u.fs.inode = i;
+}
+static inline void smk_ad_setfield_u_fs_path(struct smk_audit_info *a,
+ struct path p)
+{
+ a->a.u.fs.path = p;
+}
+static inline void smk_ad_setfield_u_net_sk(struct smk_audit_info *a,
+ struct sock *sk)
+{
+ a->a.u.net.sk = sk;
+}
+
+#else /* no AUDIT */
+
+static inline void smk_ad_init(struct smk_audit_info *a, const char *func,
+ char type)
+{
+}
+static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a,
+ struct task_struct *t)
+{
+}
+static inline void smk_ad_setfield_u_fs_path_dentry(struct smk_audit_info *a,
+ struct dentry *d)
+{
+}
+static inline void smk_ad_setfield_u_fs_path_mnt(struct smk_audit_info *a,
+ struct vfsmount *m)
+{
+}
+static inline void smk_ad_setfield_u_fs_inode(struct smk_audit_info *a,
+ struct inode *i)
+{
+}
+static inline void smk_ad_setfield_u_fs_path(struct smk_audit_info *a,
+ struct path p)
+{
+}
+static inline void smk_ad_setfield_u_net_sk(struct smk_audit_info *a,
+ struct sock *sk)
+{
+}
+#endif
+
#endif /* _SECURITY_SMACK_H */
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index ac0a2707f6d4..513dc1aa16dd 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -59,11 +59,18 @@ LIST_HEAD(smack_known_list);
*/
static u32 smack_next_secid = 10;
+/*
+ * what events do we log
+ * can be overwritten at run-time by /smack/logging
+ */
+int log_policy = SMACK_AUDIT_DENIED;
+
/**
* smk_access - determine if a subject has a specific access to an object
* @subject_label: a pointer to the subject's Smack label
* @object_label: a pointer to the object's Smack label
* @request: the access requested, in "MAY" format
+ * @a : a pointer to the audit data
*
* This function looks up the subject/object pair in the
* access rule list and returns 0 if the access is permitted,
@@ -78,10 +85,12 @@ static u32 smack_next_secid = 10;
* will be on the list, so checking the pointers may be a worthwhile
* optimization.
*/
-int smk_access(char *subject_label, char *object_label, int request)
+int smk_access(char *subject_label, char *object_label, int request,
+ struct smk_audit_info *a)
{
u32 may = MAY_NOT;
struct smack_rule *srp;
+ int rc = 0;
/*
* Hardcoded comparisons.
@@ -89,8 +98,10 @@ int smk_access(char *subject_label, char *object_label, int request)
* A star subject can't access any object.
*/
if (subject_label == smack_known_star.smk_known ||
- strcmp(subject_label, smack_known_star.smk_known) == 0)
- return -EACCES;
+ strcmp(subject_label, smack_known_star.smk_known) == 0) {
+ rc = -EACCES;
+ goto out_audit;
+ }
/*
* An internet object can be accessed by any subject.
* Tasks cannot be assigned the internet label.
@@ -100,20 +111,20 @@ int smk_access(char *subject_label, char *object_label, int request)
subject_label == smack_known_web.smk_known ||
strcmp(object_label, smack_known_web.smk_known) == 0 ||
strcmp(subject_label, smack_known_web.smk_known) == 0)
- return 0;
+ goto out_audit;
/*
* A star object can be accessed by any subject.
*/
if (object_label == smack_known_star.smk_known ||
strcmp(object_label, smack_known_star.smk_known) == 0)
- return 0;
+ goto out_audit;
/*
* An object can be accessed in any way by a subject
* with the same label.
*/
if (subject_label == object_label ||
strcmp(subject_label, object_label) == 0)
- return 0;
+ goto out_audit;
/*
* A hat subject can read any object.
* A floor object can be read by any subject.
@@ -121,10 +132,10 @@ int smk_access(char *subject_label, char *object_label, int request)
if ((request & MAY_ANYREAD) == request) {
if (object_label == smack_known_floor.smk_known ||
strcmp(object_label, smack_known_floor.smk_known) == 0)
- return 0;
+ goto out_audit;
if (subject_label == smack_known_hat.smk_known ||
strcmp(subject_label, smack_known_hat.smk_known) == 0)
- return 0;
+ goto out_audit;
}
/*
* Beyond here an explicit relationship is required.
@@ -148,28 +159,36 @@ int smk_access(char *subject_label, char *object_label, int request)
* This is a bit map operation.
*/
if ((request & may) == request)
- return 0;
-
- return -EACCES;
+ goto out_audit;
+
+ rc = -EACCES;
+out_audit:
+#ifdef CONFIG_AUDIT
+ if (a)
+ smack_log(subject_label, object_label, request, rc, a);
+#endif
+ return rc;
}
/**
* smk_curacc - determine if current has a specific access to an object
* @obj_label: a pointer to the object's Smack label
* @mode: the access requested, in "MAY" format
+ * @a : common audit data
*
* This function checks the current subject label/object label pair
* in the access rule list and returns 0 if the access is permitted,
* non zero otherwise. It allows that current may have the capability
* to override the rules.
*/
-int smk_curacc(char *obj_label, u32 mode)
+int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
{
int rc;
+ char *sp = current_security();
- rc = smk_access(current_security(), obj_label, mode);
+ rc = smk_access(sp, obj_label, mode, NULL);
if (rc == 0)
- return 0;
+ goto out_audit;
/*
* Return if a specific label has been designated as the
@@ -177,14 +196,105 @@ int smk_curacc(char *obj_label, u32 mode)
* have that label.
*/
if (smack_onlycap != NULL && smack_onlycap != current->cred->security)
- return rc;
+ goto out_audit;
if (capable(CAP_MAC_OVERRIDE))
return 0;
+out_audit:
+#ifdef CONFIG_AUDIT
+ if (a)
+ smack_log(sp, obj_label, mode, rc, a);
+#endif
return rc;
}
+#ifdef CONFIG_AUDIT
+/**
+ * smack_str_from_perm : helper to transalate an int to a
+ * readable string
+ * @string : the string to fill
+ * @access : the int
+ *
+ */
+static inline void smack_str_from_perm(char *string, int access)
+{
+ int i = 0;
+ if (access & MAY_READ)
+ string[i++] = 'r';
+ if (access & MAY_WRITE)
+ string[i++] = 'w';
+ if (access & MAY_EXEC)
+ string[i++] = 'x';
+ if (access & MAY_APPEND)
+ string[i++] = 'a';
+ string[i] = '\0';
+}
+/**
+ * smack_log_callback - SMACK specific information
+ * will be called by generic audit code
+ * @ab : the audit_buffer
+ * @a : audit_data
+ *
+ */
+static void smack_log_callback(struct audit_buffer *ab, void *a)
+{
+ struct common_audit_data *ad = a;
+ struct smack_audit_data *sad = &ad->lsm_priv.smack_audit_data;
+ audit_log_format(ab, "lsm=SMACK fn=%s action=%s", ad->function,
+ sad->result ? "denied" : "granted");
+ audit_log_format(ab, " subject=");
+ audit_log_untrustedstring(ab, sad->subject);
+ audit_log_format(ab, " object=");
+ audit_log_untrustedstring(ab, sad->object);
+ audit_log_format(ab, " requested=%s", sad->request);
+}
+
+/**
+ * smack_log - Audit the granting or denial of permissions.
+ * @subject_label : smack label of the requester
+ * @object_label : smack label of the object being accessed
+ * @request: requested permissions
+ * @result: result from smk_access
+ * @a: auxiliary audit data
+ *
+ * Audit the granting or denial of permissions in accordance
+ * with the policy.
+ */
+void smack_log(char *subject_label, char *object_label, int request,
+ int result, struct smk_audit_info *ad)
+{
+ char request_buffer[SMK_NUM_ACCESS_TYPE + 1];
+ struct smack_audit_data *sad;
+ struct common_audit_data *a = &ad->a;
+
+ /* check if we have to log the current event */
+ if (result != 0 && (log_policy & SMACK_AUDIT_DENIED) == 0)
+ return;
+ if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0)
+ return;
+
+ if (a->function == NULL)
+ a->function = "unknown";
+
+ /* end preparing the audit data */
+ sad = &a->lsm_priv.smack_audit_data;
+ smack_str_from_perm(request_buffer, request);
+ sad->subject = subject_label;
+ sad->object = object_label;
+ sad->request = request_buffer;
+ sad->result = result;
+ a->lsm_pre_audit = smack_log_callback;
+
+ common_lsm_audit(a);
+}
+#else /* #ifdef CONFIG_AUDIT */
+void smack_log(char *subject_label, char *object_label, int request,
+ int result, struct smk_audit_info *ad)
+{
+}
+#endif
+
static DEFINE_MUTEX(smack_known_lock);
/**
@@ -209,7 +319,8 @@ struct smack_known *smk_import_entry(const char *string, int len)
if (found)
smack[i] = '\0';
else if (i >= len || string[i] > '~' || string[i] <= ' ' ||
- string[i] == '/') {
+ string[i] == '/' || string[i] == '"' ||
+ string[i] == '\\' || string[i] == '\'') {
smack[i] = '\0';
found = 1;
} else
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 921514902eca..0d030b4513c8 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -30,7 +30,6 @@
#include <net/netlabel.h>
#include <net/cipso_ipv4.h>
#include <linux/audit.h>
-
#include "smack.h"
#define task_security(task) (task_cred_xxx((task), security))
@@ -103,14 +102,24 @@ struct inode_smack *new_inode_smack(char *smack)
static int smack_ptrace_may_access(struct task_struct *ctp, unsigned int mode)
{
int rc;
+ struct smk_audit_info ad;
+ char *sp, *tsp;
rc = cap_ptrace_may_access(ctp, mode);
if (rc != 0)
return rc;
- rc = smk_access(current_security(), task_security(ctp), MAY_READWRITE);
+ sp = current_security();
+ tsp = task_security(ctp);
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
+ smk_ad_setfield_u_tsk(&ad, ctp);
+
+ /* we won't log here, because rc can be overriden */
+ rc = smk_access(sp, tsp, MAY_READWRITE, NULL);
if (rc != 0 && capable(CAP_MAC_OVERRIDE))
- return 0;
+ rc = 0;
+
+ smack_log(sp, tsp, MAY_READWRITE, rc, &ad);
return rc;
}
@@ -125,14 +134,24 @@ static int smack_ptrace_may_access(struct task_struct *ctp, unsigned int mode)
static int smack_ptrace_traceme(struct task_struct *ptp)
{
int rc;
+ struct smk_audit_info ad;
+ char *sp, *tsp;
rc = cap_ptrace_traceme(ptp);
if (rc != 0)
return rc;
- rc = smk_access(task_security(ptp), current_security(), MAY_READWRITE);
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
+ smk_ad_setfield_u_tsk(&ad, ptp);
+
+ sp = current_security();
+ tsp = task_security(ptp);
+ /* we won't log here, because rc can be overriden */
+ rc = smk_access(tsp, sp, MAY_READWRITE, NULL);
if (rc != 0 && has_capability(ptp, CAP_MAC_OVERRIDE))
- return 0;
+ rc = 0;
+
+ smack_log(tsp, sp, MAY_READWRITE, rc, &ad);
return rc;
}
@@ -327,8 +346,14 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
static int smack_sb_statfs(struct dentry *dentry)
{
struct superblock_smack *sbp = dentry->d_sb->s_security;
+ int rc;
+ struct smk_audit_info ad;
+
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
+ smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
- return smk_curacc(sbp->smk_floor, MAY_READ);
+ rc = smk_curacc(sbp->smk_floor, MAY_READ, &ad);
+ return rc;
}
/**
@@ -346,8 +371,12 @@ static int smack_sb_mount(char *dev_name, struct path *path,
char *type, unsigned long flags, void *data)
{
struct superblock_smack *sbp = path->mnt->mnt_sb->s_security;
+ struct smk_audit_info ad;
+
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
+ smk_ad_setfield_u_fs_path(&ad, *path);
- return smk_curacc(sbp->smk_floor, MAY_WRITE);
+ return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad);
}
/**
@@ -361,10 +390,14 @@ static int smack_sb_mount(char *dev_name, struct path *path,
static int smack_sb_umount(struct vfsmount *mnt, int flags)
{
struct superblock_smack *sbp;
+ struct smk_audit_info ad;
- sbp = mnt->mnt_sb->s_security;
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
+ smk_ad_setfield_u_fs_path_dentry(&ad, mnt->mnt_mountpoint);
+ smk_ad_setfield_u_fs_path_mnt(&ad, mnt);
- return smk_curacc(sbp->smk_floor, MAY_WRITE);
+ sbp = mnt->mnt_sb->s_security;
+ return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad);
}
/*
@@ -441,15 +474,20 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
static int smack_inode_link(struct dentry *old_dentry, struct inode *dir,
struct dentry *new_dentry)
{
- int rc;
char *isp;
+ struct smk_audit_info ad;
+ int rc;
+
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
+ smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry);
isp = smk_of_inode(old_dentry->d_inode);
- rc = smk_curacc(isp, MAY_WRITE);
+ rc = smk_curacc(isp, MAY_WRITE, &ad);
if (rc == 0 && new_dentry->d_inode != NULL) {
isp = smk_of_inode(new_dentry->d_inode);
- rc = smk_curacc(isp, MAY_WRITE);
+ smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry);
+ rc = smk_curacc(isp, MAY_WRITE, &ad);
}
return rc;
@@ -466,18 +504,24 @@ static int smack_inode_link(struct dentry *old_dentry, struct inode *dir,
static int smack_inode_unlink(struct inode *dir, struct dentry *dentry)
{
struct inode *ip = dentry->d_inode;
+ struct smk_audit_info ad;
int rc;
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
+ smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
+
/*
* You need write access to the thing you're unlinking
*/
- rc = smk_curacc(smk_of_inode(ip), MAY_WRITE);
- if (rc == 0)
+ rc = smk_curacc(smk_of_inode(ip), MAY_WRITE, &ad);
+ if (rc == 0) {
/*
* You also need write access to the containing directory
*/
- rc = smk_curacc(smk_of_inode(dir), MAY_WRITE);
-
+ smk_ad_setfield_u_fs_path_dentry(&ad, NULL);
+ smk_ad_setfield_u_fs_inode(&ad, dir);
+ rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad);
+ }
return rc;
}
@@ -491,17 +535,24 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry)
*/
static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry)
{
+ struct smk_audit_info ad;
int rc;
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
+ smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
+
/*
* You need write access to the thing you're removing
*/
- rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
- if (rc == 0)
+ rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
+ if (rc == 0) {
/*
* You also need write access to the containing directory
*/
- rc = smk_curacc(smk_of_inode(dir), MAY_WRITE);
+ smk_ad_setfield_u_fs_path_dentry(&ad, NULL);
+ smk_ad_setfield_u_fs_inode(&ad, dir);
+ rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad);
+ }
return rc;
}
@@ -525,15 +576,19 @@ static int smack_inode_rename(struct inode *old_inode,
{
int rc;
char *isp;
+ struct smk_audit_info ad;
+
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
+ smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry);
isp = smk_of_inode(old_dentry->d_inode);
- rc = smk_curacc(isp, MAY_READWRITE);
+ rc = smk_curacc(isp, MAY_READWRITE, &ad);
if (rc == 0 && new_dentry->d_inode != NULL) {
isp = smk_of_inode(new_dentry->d_inode);
- rc = smk_curacc(isp, MAY_READWRITE);
+ smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry);
+ rc = smk_curacc(isp, MAY_READWRITE, &ad);
}
-
return rc;
}
@@ -548,13 +603,15 @@ static int smack_inode_rename(struct inode *old_inode,
*/
static int smack_inode_permission(struct inode *inode, int mask)
{
+ struct smk_audit_info ad;
/*
* No permission to check. Existence test. Yup, it's there.
*/
if (mask == 0)
return 0;
-
- return smk_curacc(smk_of_inode(inode), mask);
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
+ smk_ad_setfield_u_fs_inode(&ad, inode);
+ return smk_curacc(smk_of_inode(inode), mask, &ad);
}
/**
@@ -566,13 +623,16 @@ static int smack_inode_permission(struct inode *inode, int mask)
*/
static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
{
+ struct smk_audit_info ad;
/*
* Need to allow for clearing the setuid bit.
*/
if (iattr->ia_valid & ATTR_FORCE)
return 0;
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
+ smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
- return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
+ return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
}
/**
@@ -584,7 +644,12 @@ static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
*/
static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
{
- return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ);
+ struct smk_audit_info ad;
+
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
+ smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
+ smk_ad_setfield_u_fs_path_mnt(&ad, mnt);
+ return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad);
}
/**
@@ -602,6 +667,7 @@ static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
static int smack_inode_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
+ struct smk_audit_info ad;
int rc = 0;
if (strcmp(name, XATTR_NAME_SMACK) == 0 ||
@@ -609,14 +675,21 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) {
if (!capable(CAP_MAC_ADMIN))
rc = -EPERM;
- /* a label cannot be void and cannot begin with '-' */
- if (size == 0 || (size > 0 && ((char *)value)[0] == '-'))
+ /*
+ * check label validity here so import wont fail on
+ * post_setxattr
+ */
+ if (size == 0 || size >= SMK_LABELLEN ||
+ smk_import(value, size) == NULL)
rc = -EINVAL;
} else
rc = cap_inode_setxattr(dentry, name, value, size, flags);
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
+ smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
+
if (rc == 0)
- rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
+ rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
return rc;
}
@@ -644,9 +717,6 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
if (strcmp(name, XATTR_NAME_SMACK))
return;
- if (size >= SMK_LABELLEN)
- return;
-
isp = dentry->d_inode->i_security;
/*
@@ -671,7 +741,12 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
*/
static int smack_inode_getxattr(struct dentry *dentry, const char *name)
{
- return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ);
+ struct smk_audit_info ad;
+
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
+ smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
+
+ return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad);
}
/*
@@ -685,6 +760,7 @@ static int smack_inode_getxattr(struct dentry *dentry, const char *name)
*/
static int smack_inode_removexattr(struct dentry *dentry, const char *name)
{
+ struct smk_audit_info ad;
int rc = 0;
if (strcmp(name, XATTR_NAME_SMACK) == 0 ||
@@ -695,8 +771,10 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
} else
rc = cap_inode_removexattr(dentry, name);
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
+ smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
if (rc == 0)
- rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
+ rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
return rc;
}
@@ -855,12 +933,16 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
int rc = 0;
+ struct smk_audit_info ad;
+
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
+ smk_ad_setfield_u_fs_path(&ad, file->f_path);
if (_IOC_DIR(cmd) & _IOC_WRITE)
- rc = smk_curacc(file->f_security, MAY_WRITE);
+ rc = smk_curacc(file->f_security, MAY_WRITE, &ad);
if (rc == 0 && (_IOC_DIR(cmd) & _IOC_READ))
- rc = smk_curacc(file->f_security, MAY_READ);
+ rc = smk_curacc(file->f_security, MAY_READ, &ad);
return rc;
}
@@ -874,7 +956,11 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd,
*/
static int smack_file_lock(struct file *file, unsigned int cmd)
{
- return smk_curacc(file->f_security, MAY_WRITE);
+ struct smk_audit_info ad;
+
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
+ smk_ad_setfield_u_fs_path_dentry(&ad, file->f_path.dentry);
+ return smk_curacc(file->f_security, MAY_WRITE, &ad);
}
/**
@@ -888,8 +974,12 @@ static int smack_file_lock(struct file *file, unsigned int cmd)
static int smack_file_fcntl(struct file *file, unsigned int cmd,
unsigned long arg)
{
+ struct smk_audit_info ad;
int rc;
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
+ smk_ad_setfield_u_fs_path(&ad, file->f_path);
+
switch (cmd) {
case F_DUPFD:
case F_GETFD:
@@ -897,7 +987,7 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,
case F_GETLK:
case F_GETOWN:
case F_GETSIG:
- rc = smk_curacc(file->f_security, MAY_READ);
+ rc = smk_curacc(file->f_security, MAY_READ, &ad);
break;
case F_SETFD:
case F_SETFL:
@@ -905,10 +995,10 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,
case F_SETLKW:
case F_SETOWN:
case F_SETSIG:
- rc = smk_curacc(file->f_security, MAY_WRITE);
+ rc = smk_curacc(file->f_security, MAY_WRITE, &ad);
break;
default:
- rc = smk_curacc(file->f_security, MAY_READWRITE);
+ rc = smk_curacc(file->f_security, MAY_READWRITE, &ad);
}
return rc;
@@ -943,14 +1033,21 @@ static int smack_file_send_sigiotask(struct task_struct *tsk,
{
struct file *file;
int rc;
+ char *tsp = tsk->cred->security;
+ struct smk_audit_info ad;
/*
* struct fown_struct is never outside the context of a struct file
*/
file = container_of(fown, struct file, f_owner);
- rc = smk_access(file->f_security, tsk->cred->security, MAY_WRITE);
+ /* we don't log here as rc can be overriden */
+ rc = smk_access(file->f_security, tsp, MAY_WRITE, NULL);
if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE))
- return 0;
+ rc = 0;
+
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
+ smk_ad_setfield_u_tsk(&ad, tsk);
+ smack_log(file->f_security, tsp, MAY_WRITE, rc, &ad);
return rc;
}
@@ -963,7 +1060,10 @@ static int smack_file_send_sigiotask(struct task_struct *tsk,
static int smack_file_receive(struct file *file)
{
int may = 0;
+ struct smk_audit_info ad;
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
+ smk_ad_setfield_u_fs_path(&ad, file->f_path);
/*
* This code relies on bitmasks.
*/
@@ -972,7 +1072,7 @@ static int smack_file_receive(struct file *file)
if (file->f_mode & FMODE_WRITE)
may |= MAY_WRITE;
- return smk_curacc(file->f_security, may);
+ return smk_curacc(file->f_security, may, &ad);
}
/*
@@ -1052,6 +1152,22 @@ static int smack_kernel_create_files_as(struct cred *new,
}
/**
+ * smk_curacc_on_task - helper to log task related access
+ * @p: the task object
+ * @access : the access requested
+ *
+ * Return 0 if access is permitted
+ */
+static int smk_curacc_on_task(struct task_struct *p, int access)
+{
+ struct smk_audit_info ad;
+
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
+ smk_ad_setfield_u_tsk(&ad, p);
+ return smk_curacc(task_security(p), access, &ad);
+}
+
+/**
* smack_task_setpgid - Smack check on setting pgid
* @p: the task object
* @pgid: unused
@@ -1060,7 +1176,7 @@ static int smack_kernel_create_files_as(struct cred *new,
*/
static int smack_task_setpgid(struct task_struct *p, pid_t pgid)
{
- return smk_curacc(task_security(p), MAY_WRITE);
+ return smk_curacc_on_task(p, MAY_WRITE);
}
/**
@@ -1071,7 +1187,7 @@ static int smack_task_setpgid(struct task_struct *p, pid_t pgid)
*/
static int smack_task_getpgid(struct task_struct *p)
{
- return smk_curacc(task_security(p), MAY_READ);
+ return smk_curacc_on_task(p, MAY_READ);
}
/**
@@ -1082,7 +1198,7 @@ static int smack_task_getpgid(struct task_struct *p)
*/
static int smack_task_getsid(struct task_struct *p)
{
- return smk_curacc(task_security(p), MAY_READ);
+ return smk_curacc_on_task(p, MAY_READ);
}
/**
@@ -1110,7 +1226,7 @@ static int smack_task_setnice(struct task_struct *p, int nice)
rc = cap_task_setnice(p, nice);
if (rc == 0)
- rc = smk_curacc(task_security(p), MAY_WRITE);
+ rc = smk_curacc_on_task(p, MAY_WRITE);
return rc;
}
@@ -1127,7 +1243,7 @@ static int smack_task_setioprio(struct task_struct *p, int ioprio)
rc = cap_task_setioprio(p, ioprio);
if (rc == 0)
- rc = smk_curacc(task_security(p), MAY_WRITE);
+ rc = smk_curacc_on_task(p, MAY_WRITE);
return rc;
}
@@ -1139,7 +1255,7 @@ static int smack_task_setioprio(struct task_struct *p, int ioprio)
*/
static int smack_task_getioprio(struct task_struct *p)
{
- return smk_curacc(task_security(p), MAY_READ);
+ return smk_curacc_on_task(p, MAY_READ);
}
/**
@@ -1157,7 +1273,7 @@ static int smack_task_setscheduler(struct task_struct *p, int policy,
rc = cap_task_setscheduler(p, policy, lp);
if (rc == 0)
- rc = smk_curacc(task_security(p), MAY_WRITE);
+ rc = smk_curacc_on_task(p, MAY_WRITE);
return rc;
}
@@ -1169,7 +1285,7 @@ static int smack_task_setscheduler(struct task_struct *p, int policy,
*/
static int smack_task_getscheduler(struct task_struct *p)
{
- return smk_curacc(task_security(p), MAY_READ);
+ return smk_curacc_on_task(p, MAY_READ);
}
/**
@@ -1180,7 +1296,7 @@ static int smack_task_getscheduler(struct task_struct *p)
*/
static int smack_task_movememory(struct task_struct *p)
{
- return smk_curacc(task_security(p), MAY_WRITE);
+ return smk_curacc_on_task(p, MAY_WRITE);
}
/**
@@ -1198,18 +1314,23 @@ static int smack_task_movememory(struct task_struct *p)
static int smack_task_kill(struct task_struct *p, struct siginfo *info,
int sig, u32 secid)
{
+ struct smk_audit_info ad;
+
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
+ smk_ad_setfield_u_tsk(&ad, p);
/*
* Sending a signal requires that the sender
* can write the receiver.
*/
if (secid == 0)
- return smk_curacc(task_security(p), MAY_WRITE);
+ return smk_curacc(task_security(p), MAY_WRITE, &ad);
/*
* If the secid isn't 0 we're dealing with some USB IO
* specific behavior. This is not clean. For one thing
* we can't take privilege into account.
*/
- return smk_access(smack_from_secid(secid), task_security(p), MAY_WRITE);
+ return smk_access(smack_from_secid(secid), task_security(p),
+ MAY_WRITE, &ad);
}
/**
@@ -1220,11 +1341,15 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info,
*/
static int smack_task_wait(struct task_struct *p)
{
+ struct smk_audit_info ad;
+ char *sp = current_security();
+ char *tsp = task_security(p);
int rc;
- rc = smk_access(current_security(), task_security(p), MAY_WRITE);
+ /* we don't log here, we can be overriden */
+ rc = smk_access(sp, tsp, MAY_WRITE, NULL);
if (rc == 0)
- return 0;
+ goto out_log;
/*
* Allow the operation to succeed if either task
@@ -1238,8 +1363,12 @@ static int smack_task_wait(struct task_struct *p)
* the smack value.
*/
if (capable(CAP_MAC_OVERRIDE) || has_capability(p, CAP_MAC_OVERRIDE))
- return 0;
-
+ rc = 0;
+ /* we log only if we didn't get overriden */
+ out_log:
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
+ smk_ad_setfield_u_tsk(&ad, p);
+ smack_log(sp, tsp, MAY_WRITE, rc, &ad);
return rc;
}
@@ -1455,12 +1584,19 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
int sk_lbl;
char *hostsp;
struct socket_smack *ssp = sk->sk_security;
+ struct smk_audit_info ad;
rcu_read_lock();
hostsp = smack_host_label(sap);
if (hostsp != NULL) {
sk_lbl = SMACK_UNLABELED_SOCKET;
- rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE);
+#ifdef CONFIG_AUDIT
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
+ ad.a.u.net.family = sap->sin_family;
+ ad.a.u.net.dport = sap->sin_port;
+ ad.a.u.net.v4info.daddr = sap->sin_addr.s_addr;
+#endif
+ rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE, &ad);
} else {
sk_lbl = SMACK_CIPSO_SOCKET;
rc = 0;
@@ -1656,6 +1792,25 @@ static void smack_shm_free_security(struct shmid_kernel *shp)
}
/**
+ * smk_curacc_shm : check if current has access on shm
+ * @shp : the object
+ * @access : access requested
+ *
+ * Returns 0 if current has the requested access, error code otherwise
+ */
+static int smk_curacc_shm(struct shmid_kernel *shp, int access)
+{
+ char *ssp = smack_of_shm(shp);
+ struct smk_audit_info ad;
+
+#ifdef CONFIG_AUDIT
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
+ ad.a.u.ipc_id = shp->shm_perm.id;
+#endif
+ return smk_curacc(ssp, access, &ad);
+}
+
+/**
* smack_shm_associate - Smack access check for shm
* @shp: the object
* @shmflg: access requested
@@ -1664,11 +1819,10 @@ static void smack_shm_free_security(struct shmid_kernel *shp)
*/
static int smack_shm_associate(struct shmid_kernel *shp, int shmflg)
{
- char *ssp = smack_of_shm(shp);
int may;
may = smack_flags_to_may(shmflg);
- return smk_curacc(ssp, may);
+ return smk_curacc_shm(shp, may);
}
/**
@@ -1680,7 +1834,6 @@ static int smack_shm_associate(struct shmid_kernel *shp, int shmflg)
*/
static int smack_shm_shmctl(struct shmid_kernel *shp, int cmd)
{
- char *ssp;
int may;
switch (cmd) {
@@ -1703,9 +1856,7 @@ static int smack_shm_shmctl(struct shmid_kernel *shp, int cmd)
default:
return -EINVAL;
}
-
- ssp = smack_of_shm(shp);
- return smk_curacc(ssp, may);
+ return smk_curacc_shm(shp, may);
}
/**
@@ -1719,11 +1870,10 @@ static int smack_shm_shmctl(struct shmid_kernel *shp, int cmd)
static int smack_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr,
int shmflg)
{
- char *ssp = smack_of_shm(shp);
int may;
may = smack_flags_to_may(shmflg);
- return smk_curacc(ssp, may);
+ return smk_curacc_shm(shp, may);
}
/**
@@ -1765,6 +1915,25 @@ static void smack_sem_free_security(struct sem_array *sma)
}
/**
+ * smk_curacc_sem : check if current has access on sem
+ * @sma : the object
+ * @access : access requested
+ *
+ * Returns 0 if current has the requested access, error code otherwise
+ */
+static int smk_curacc_sem(struct sem_array *sma, int access)
+{
+ char *ssp = smack_of_sem(sma);
+ struct smk_audit_info ad;
+
+#ifdef CONFIG_AUDIT
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
+ ad.a.u.ipc_id = sma->sem_perm.id;
+#endif
+ return smk_curacc(ssp, access, &ad);
+}
+
+/**
* smack_sem_associate - Smack access check for sem
* @sma: the object
* @semflg: access requested
@@ -1773,11 +1942,10 @@ static void smack_sem_free_security(struct sem_array *sma)
*/
static int smack_sem_associate(struct sem_array *sma, int semflg)
{
- char *ssp = smack_of_sem(sma);
int may;
may = smack_flags_to_may(semflg);
- return smk_curacc(ssp, may);
+ return smk_curacc_sem(sma, may);
}
/**
@@ -1789,7 +1957,6 @@ static int smack_sem_associate(struct sem_array *sma, int semflg)
*/
static int smack_sem_semctl(struct sem_array *sma, int cmd)
{
- char *ssp;
int may;
switch (cmd) {
@@ -1818,8 +1985,7 @@ static int smack_sem_semctl(struct sem_array *sma, int cmd)
return -EINVAL;
}
- ssp = smack_of_sem(sma);
- return smk_curacc(ssp, may);
+ return smk_curacc_sem(sma, may);
}
/**
@@ -1836,9 +2002,7 @@ static int smack_sem_semctl(struct sem_array *sma, int cmd)
static int smack_sem_semop(struct sem_array *sma, struct sembuf *sops,
unsigned nsops, int alter)
{
- char *ssp = smack_of_sem(sma);
-
- return smk_curacc(ssp, MAY_READWRITE);
+ return smk_curacc_sem(sma, MAY_READWRITE);
}
/**
@@ -1880,6 +2044,25 @@ static char *smack_of_msq(struct msg_queue *msq)
}
/**
+ * smk_curacc_msq : helper to check if current has access on msq
+ * @msq : the msq
+ * @access : access requested
+ *
+ * return 0 if current has access, error otherwise
+ */
+static int smk_curacc_msq(struct msg_queue *msq, int access)
+{
+ char *msp = smack_of_msq(msq);
+ struct smk_audit_info ad;
+
+#ifdef CONFIG_AUDIT
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
+ ad.a.u.ipc_id = msq->q_perm.id;
+#endif
+ return smk_curacc(msp, access, &ad);
+}
+
+/**
* smack_msg_queue_associate - Smack access check for msg_queue
* @msq: the object
* @msqflg: access requested
@@ -1888,11 +2071,10 @@ static char *smack_of_msq(struct msg_queue *msq)
*/
static int smack_msg_queue_associate(struct msg_queue *msq, int msqflg)
{
- char *msp = smack_of_msq(msq);
int may;
may = smack_flags_to_may(msqflg);
- return smk_curacc(msp, may);
+ return smk_curacc_msq(msq, may);
}
/**
@@ -1904,7 +2086,6 @@ static int smack_msg_queue_associate(struct msg_queue *msq, int msqflg)
*/
static int smack_msg_queue_msgctl(struct msg_queue *msq, int cmd)
{
- char *msp;
int may;
switch (cmd) {
@@ -1926,8 +2107,7 @@ static int smack_msg_queue_msgctl(struct msg_queue *msq, int cmd)
return -EINVAL;
}
- msp = smack_of_msq(msq);
- return smk_curacc(msp, may);
+ return smk_curacc_msq(msq, may);
}
/**
@@ -1941,11 +2121,10 @@ static int smack_msg_queue_msgctl(struct msg_queue *msq, int cmd)
static int smack_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
int msqflg)
{
- char *msp = smack_of_msq(msq);
- int rc;
+ int may;
- rc = smack_flags_to_may(msqflg);
- return smk_curacc(msp, rc);
+ may = smack_flags_to_may(msqflg);
+ return smk_curacc_msq(msq, may);
}
/**
@@ -1961,9 +2140,7 @@ static int smack_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
static int smack_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
struct task_struct *target, long type, int mode)
{
- char *msp = smack_of_msq(msq);
-
- return smk_curacc(msp, MAY_READWRITE);
+ return smk_curacc_msq(msq, MAY_READWRITE);
}
/**
@@ -1976,10 +2153,14 @@ static int smack_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag)
{
char *isp = ipp->security;
- int may;
+ int may = smack_flags_to_may(flag);
+ struct smk_audit_info ad;
- may = smack_flags_to_may(flag);
- return smk_curacc(isp, may);
+#ifdef CONFIG_AUDIT
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
+ ad.a.u.ipc_id = ipp->id;
+#endif
+ return smk_curacc(isp, may, &ad);
}
/**
@@ -2238,8 +2419,12 @@ static int smack_unix_stream_connect(struct socket *sock,
{
struct inode *sp = SOCK_INODE(sock);
struct inode *op = SOCK_INODE(other);
+ struct smk_audit_info ad;
- return smk_access(smk_of_inode(sp), smk_of_inode(op), MAY_READWRITE);
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
+ smk_ad_setfield_u_net_sk(&ad, other->sk);
+ return smk_access(smk_of_inode(sp), smk_of_inode(op),
+ MAY_READWRITE, &ad);
}
/**
@@ -2254,8 +2439,11 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other)
{
struct inode *sp = SOCK_INODE(sock);
struct inode *op = SOCK_INODE(other);
+ struct smk_audit_info ad;
- return smk_access(smk_of_inode(sp), smk_of_inode(op), MAY_WRITE);
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
+ smk_ad_setfield_u_net_sk(&ad, other->sk);
+ return smk_access(smk_of_inode(sp), smk_of_inode(op), MAY_WRITE, &ad);
}
/**
@@ -2370,7 +2558,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
char smack[SMK_LABELLEN];
char *csp;
int rc;
-
+ struct smk_audit_info ad;
if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
return 0;
@@ -2388,13 +2576,19 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
netlbl_secattr_destroy(&secattr);
+#ifdef CONFIG_AUDIT
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
+ ad.a.u.net.family = sk->sk_family;
+ ad.a.u.net.netif = skb->iif;
+ ipv4_skb_to_auditdata(skb, &ad.a, NULL);
+#endif
/*
* Receiving a packet requires that the other end
* be able to write here. Read access is not required.
* This is the simplist possible security model
* for networking.
*/
- rc = smk_access(csp, ssp->smk_in, MAY_WRITE);
+ rc = smk_access(csp, ssp->smk_in, MAY_WRITE, &ad);
if (rc != 0)
netlbl_skbuff_err(skb, rc, 0);
return rc;
@@ -2523,6 +2717,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
struct iphdr *hdr;
char smack[SMK_LABELLEN];
int rc;
+ struct smk_audit_info ad;
/* handle mapped IPv4 packets arriving via IPv6 sockets */
if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
@@ -2536,11 +2731,17 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
strncpy(smack, smack_known_huh.smk_known, SMK_MAXLEN);
netlbl_secattr_destroy(&secattr);
+#ifdef CONFIG_AUDIT
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
+ ad.a.u.net.family = family;
+ ad.a.u.net.netif = skb->iif;
+ ipv4_skb_to_auditdata(skb, &ad.a, NULL);
+#endif
/*
* Receiving a packet requires that the other end be able to write
* here. Read access is not required.
*/
- rc = smk_access(smack, ssp->smk_in, MAY_WRITE);
+ rc = smk_access(smack, ssp->smk_in, MAY_WRITE, &ad);
if (rc != 0)
return rc;
@@ -2642,6 +2843,7 @@ static int smack_key_permission(key_ref_t key_ref,
const struct cred *cred, key_perm_t perm)
{
struct key *keyp;
+ struct smk_audit_info ad;
keyp = key_ref_to_ptr(key_ref);
if (keyp == NULL)
@@ -2657,8 +2859,13 @@ static int smack_key_permission(key_ref_t key_ref,
*/
if (cred->security == NULL)
return -EACCES;
-
- return smk_access(cred->security, keyp->security, MAY_READWRITE);
+#ifdef CONFIG_AUDIT
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_KEY);
+ ad.a.u.key_struct.key = keyp->serial;
+ ad.a.u.key_struct.key_desc = keyp->description;
+#endif
+ return smk_access(cred->security, keyp->security,
+ MAY_READWRITE, &ad);
}
#endif /* CONFIG_KEYS */
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index e03a7e19c73b..ee1c9c932934 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -41,6 +41,7 @@ enum smk_inos {
SMK_AMBIENT = 7, /* internet ambient label */
SMK_NETLBLADDR = 8, /* single label hosts */
SMK_ONLYCAP = 9, /* the only "capable" label */
+ SMK_LOGGING = 10, /* logging */
};
/*
@@ -734,8 +735,8 @@ static void smk_netlbladdr_insert(struct smk_netlbladdr *new)
return;
}
- m = list_entry(rcu_dereference(smk_netlbladdr_list.next),
- struct smk_netlbladdr, list);
+ m = list_entry_rcu(smk_netlbladdr_list.next,
+ struct smk_netlbladdr, list);
/* the comparison '>' is a bit hacky, but works */
if (new->smk_mask.s_addr > m->smk_mask.s_addr) {
@@ -748,8 +749,8 @@ static void smk_netlbladdr_insert(struct smk_netlbladdr *new)
list_add_rcu(&new->list, &m->list);
return;
}
- m_next = list_entry(rcu_dereference(m->list.next),
- struct smk_netlbladdr, list);
+ m_next = list_entry_rcu(m->list.next,
+ struct smk_netlbladdr, list);
if (new->smk_mask.s_addr > m_next->smk_mask.s_addr) {
list_add_rcu(&new->list, &m->list);
return;
@@ -1192,6 +1193,69 @@ static const struct file_operations smk_onlycap_ops = {
};
/**
+ * smk_read_logging - read() for /smack/logging
+ * @filp: file pointer, not actually used
+ * @buf: where to put the result
+ * @cn: maximum to send along
+ * @ppos: where to start
+ *
+ * Returns number of bytes read or error code, as appropriate
+ */
+static ssize_t smk_read_logging(struct file *filp, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char temp[32];
+ ssize_t rc;
+
+ if (*ppos != 0)
+ return 0;
+
+ sprintf(temp, "%d\n", log_policy);
+ rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
+ return rc;
+}
+
+/**
+ * smk_write_logging - write() for /smack/logging
+ * @file: file pointer, not actually used
+ * @buf: where to get the data from
+ * @count: bytes sent
+ * @ppos: where to start
+ *
+ * Returns number of bytes written or error code, as appropriate
+ */
+static ssize_t smk_write_logging(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char temp[32];
+ int i;
+
+ if (!capable(CAP_MAC_ADMIN))
+ return -EPERM;
+
+ if (count >= sizeof(temp) || count == 0)
+ return -EINVAL;
+
+ if (copy_from_user(temp, buf, count) != 0)
+ return -EFAULT;
+
+ temp[count] = '\0';
+
+ if (sscanf(temp, "%d", &i) != 1)
+ return -EINVAL;
+ if (i < 0 || i > 3)
+ return -EINVAL;
+ log_policy = i;
+ return count;
+}
+
+
+
+static const struct file_operations smk_logging_ops = {
+ .read = smk_read_logging,
+ .write = smk_write_logging,
+};
+/**
* smk_fill_super - fill the /smackfs superblock
* @sb: the empty superblock
* @data: unused
@@ -1221,6 +1285,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
{"netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR},
[SMK_ONLYCAP] =
{"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
+ [SMK_LOGGING] =
+ {"logging", &smk_logging_ops, S_IRUGO|S_IWUSR},
/* last one */ {""}
};
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index a0affd9cfca8..ddfb9cccf468 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -5,7 +5,7 @@
*
* Copyright (C) 2005-2009 NTT DATA CORPORATION
*
- * Version: 2.2.0-pre 2009/02/01
+ * Version: 2.2.0 2009/04/01
*
*/
@@ -1720,14 +1720,14 @@ static bool tomoyo_policy_loader_exists(void)
* policies are not loaded yet.
* Thus, let do_execve() call this function everytime.
*/
- struct nameidata nd;
+ struct path path;
- if (path_lookup(tomoyo_loader, LOOKUP_FOLLOW, &nd)) {
+ if (kern_path(tomoyo_loader, LOOKUP_FOLLOW, &path)) {
printk(KERN_INFO "Not activating Mandatory Access Control now "
"since %s doesn't exist.\n", tomoyo_loader);
return false;
}
- path_put(&nd.path);
+ path_put(&path);
return true;
}
@@ -1773,7 +1773,7 @@ void tomoyo_load_policy(const char *filename)
envp[2] = NULL;
call_usermodehelper(argv[0], argv, envp, 1);
- printk(KERN_INFO "TOMOYO: 2.2.0-pre 2009/02/01\n");
+ printk(KERN_INFO "TOMOYO: 2.2.0 2009/04/01\n");
printk(KERN_INFO "Mandatory Access Control activated.\n");
tomoyo_policy_loaded = true;
{ /* Check all profiles currently assigned to domains are defined. */
@@ -1800,7 +1800,7 @@ void tomoyo_load_policy(const char *filename)
static int tomoyo_read_version(struct tomoyo_io_buffer *head)
{
if (!head->read_eof) {
- tomoyo_io_printf(head, "2.2.0-pre");
+ tomoyo_io_printf(head, "2.2.0");
head->read_eof = true;
}
return 0;
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index e77e6a6de0f2..678f4ff16aa4 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -5,7 +5,7 @@
*
* Copyright (C) 2005-2009 NTT DATA CORPORATION
*
- * Version: 2.2.0-pre 2009/02/01
+ * Version: 2.2.0 2009/04/01
*
*/
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index 2f2b449ffd2d..2d6748741a26 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -5,7 +5,7 @@
*
* Copyright (C) 2005-2009 NTT DATA CORPORATION
*
- * Version: 2.2.0-pre 2009/02/01
+ * Version: 2.2.0 2009/04/01
*
*/
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index 65f50c1c5ee9..2316da8ec5bc 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -5,7 +5,7 @@
*
* Copyright (C) 2005-2009 NTT DATA CORPORATION
*
- * Version: 2.2.0-pre 2009/02/01
+ * Version: 2.2.0 2009/04/01
*
*/
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
index 3bbe01a7a4b5..40927a84cb6e 100644
--- a/security/tomoyo/realpath.c
+++ b/security/tomoyo/realpath.c
@@ -5,7 +5,7 @@
*
* Copyright (C) 2005-2009 NTT DATA CORPORATION
*
- * Version: 2.2.0-pre 2009/02/01
+ * Version: 2.2.0 2009/04/01
*
*/
@@ -165,11 +165,11 @@ char *tomoyo_realpath_from_path(struct path *path)
*/
char *tomoyo_realpath(const char *pathname)
{
- struct nameidata nd;
+ struct path path;
- if (pathname && path_lookup(pathname, LOOKUP_FOLLOW, &nd) == 0) {
- char *buf = tomoyo_realpath_from_path(&nd.path);
- path_put(&nd.path);
+ if (pathname && kern_path(pathname, LOOKUP_FOLLOW, &path) == 0) {
+ char *buf = tomoyo_realpath_from_path(&path);
+ path_put(&path);
return buf;
}
return NULL;
@@ -184,11 +184,11 @@ char *tomoyo_realpath(const char *pathname)
*/
char *tomoyo_realpath_nofollow(const char *pathname)
{
- struct nameidata nd;
+ struct path path;
- if (pathname && path_lookup(pathname, 0, &nd) == 0) {
- char *buf = tomoyo_realpath_from_path(&nd.path);
- path_put(&nd.path);
+ if (pathname && kern_path(pathname, 0, &path) == 0) {
+ char *buf = tomoyo_realpath_from_path(&path);
+ path_put(&path);
return buf;
}
return NULL;
diff --git a/security/tomoyo/realpath.h b/security/tomoyo/realpath.h
index 7ec9fc9cbc07..78217a37960b 100644
--- a/security/tomoyo/realpath.h
+++ b/security/tomoyo/realpath.h
@@ -5,7 +5,7 @@
*
* Copyright (C) 2005-2009 NTT DATA CORPORATION
*
- * Version: 2.2.0-pre 2009/02/01
+ * Version: 2.2.0 2009/04/01
*
*/
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index 3eeeae12c4dc..5b481912752a 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -5,7 +5,7 @@
*
* Copyright (C) 2005-2009 NTT DATA CORPORATION
*
- * Version: 2.2.0-pre 2009/02/01
+ * Version: 2.2.0 2009/04/01
*
*/
diff --git a/security/tomoyo/tomoyo.h b/security/tomoyo/tomoyo.h
index a0c8f6e0bea4..41c6ebafb9c5 100644
--- a/security/tomoyo/tomoyo.h
+++ b/security/tomoyo/tomoyo.h
@@ -5,7 +5,7 @@
*
* Copyright (C) 2005-2009 NTT DATA CORPORATION
*
- * Version: 2.2.0-pre 2009/02/01
+ * Version: 2.2.0 2009/04/01
*
*/
diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c
index 15500b9d2da0..84bb07d39a7f 100644
--- a/sound/aoa/codecs/onyx.c
+++ b/sound/aoa/codecs/onyx.c
@@ -47,7 +47,7 @@ MODULE_DESCRIPTION("pcm3052 (onyx) codec driver for snd-aoa");
struct onyx {
/* cache registers 65 to 80, they are write-only! */
u8 cache[16];
- struct i2c_client i2c;
+ struct i2c_client *i2c;
struct aoa_codec codec;
u32 initialised:1,
spdif_locked:1,
@@ -72,7 +72,7 @@ static int onyx_read_register(struct onyx *onyx, u8 reg, u8 *value)
*value = onyx->cache[reg-FIRSTREGISTER];
return 0;
}
- v = i2c_smbus_read_byte_data(&onyx->i2c, reg);
+ v = i2c_smbus_read_byte_data(onyx->i2c, reg);
if (v < 0)
return -1;
*value = (u8)v;
@@ -84,7 +84,7 @@ static int onyx_write_register(struct onyx *onyx, u8 reg, u8 value)
{
int result;
- result = i2c_smbus_write_byte_data(&onyx->i2c, reg, value);
+ result = i2c_smbus_write_byte_data(onyx->i2c, reg, value);
if (!result)
onyx->cache[reg-FIRSTREGISTER] = value;
return result;
@@ -996,12 +996,45 @@ static void onyx_exit_codec(struct aoa_codec *codec)
onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx);
}
-static struct i2c_driver onyx_driver;
-
static int onyx_create(struct i2c_adapter *adapter,
struct device_node *node,
int addr)
{
+ struct i2c_board_info info;
+ struct i2c_client *client;
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "aoa_codec_onyx", I2C_NAME_SIZE);
+ info.addr = addr;
+ info.platform_data = node;
+ client = i2c_new_device(adapter, &info);
+ if (!client)
+ return -ENODEV;
+
+ /*
+ * We know the driver is already loaded, so the device should be
+ * already bound. If not it means binding failed, which suggests
+ * the device doesn't really exist and should be deleted.
+ * Ideally this would be replaced by better checks _before_
+ * instantiating the device.
+ */
+ if (!client->driver) {
+ i2c_unregister_device(client);
+ return -ENODEV;
+ }
+
+ /*
+ * Let i2c-core delete that device on driver removal.
+ * This is safe because i2c-core holds the core_lock mutex for us.
+ */
+ list_add_tail(&client->detected, &client->driver->clients);
+ return 0;
+}
+
+static int onyx_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device_node *node = client->dev.platform_data;
struct onyx *onyx;
u8 dummy;
@@ -1011,20 +1044,12 @@ static int onyx_create(struct i2c_adapter *adapter,
return -ENOMEM;
mutex_init(&onyx->mutex);
- onyx->i2c.driver = &onyx_driver;
- onyx->i2c.adapter = adapter;
- onyx->i2c.addr = addr & 0x7f;
- strlcpy(onyx->i2c.name, "onyx audio codec", I2C_NAME_SIZE);
-
- if (i2c_attach_client(&onyx->i2c)) {
- printk(KERN_ERR PFX "failed to attach to i2c\n");
- goto fail;
- }
+ onyx->i2c = client;
+ i2c_set_clientdata(client, onyx);
/* we try to read from register ONYX_REG_CONTROL
* to check if the codec is present */
if (onyx_read_register(onyx, ONYX_REG_CONTROL, &dummy) != 0) {
- i2c_detach_client(&onyx->i2c);
printk(KERN_ERR PFX "failed to read control register\n");
goto fail;
}
@@ -1036,14 +1061,14 @@ static int onyx_create(struct i2c_adapter *adapter,
onyx->codec.node = of_node_get(node);
if (aoa_codec_register(&onyx->codec)) {
- i2c_detach_client(&onyx->i2c);
goto fail;
}
printk(KERN_DEBUG PFX "created and attached onyx instance\n");
return 0;
fail:
+ i2c_set_clientdata(client, NULL);
kfree(onyx);
- return -EINVAL;
+ return -ENODEV;
}
static int onyx_i2c_attach(struct i2c_adapter *adapter)
@@ -1080,28 +1105,33 @@ static int onyx_i2c_attach(struct i2c_adapter *adapter)
return onyx_create(adapter, NULL, 0x47);
}
-static int onyx_i2c_detach(struct i2c_client *client)
+static int onyx_i2c_remove(struct i2c_client *client)
{
- struct onyx *onyx = container_of(client, struct onyx, i2c);
- int err;
+ struct onyx *onyx = i2c_get_clientdata(client);
- if ((err = i2c_detach_client(client)))
- return err;
aoa_codec_unregister(&onyx->codec);
of_node_put(onyx->codec.node);
if (onyx->codec_info)
kfree(onyx->codec_info);
+ i2c_set_clientdata(client, onyx);
kfree(onyx);
return 0;
}
+static const struct i2c_device_id onyx_i2c_id[] = {
+ { "aoa_codec_onyx", 0 },
+ { }
+};
+
static struct i2c_driver onyx_driver = {
.driver = {
.name = "aoa_codec_onyx",
.owner = THIS_MODULE,
},
.attach_adapter = onyx_i2c_attach,
- .detach_client = onyx_i2c_detach,
+ .probe = onyx_i2c_probe,
+ .remove = onyx_i2c_remove,
+ .id_table = onyx_i2c_id,
};
static int __init onyx_init(void)
diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c
index 008e0f85097d..f0ebc971c686 100644
--- a/sound/aoa/codecs/tas.c
+++ b/sound/aoa/codecs/tas.c
@@ -82,7 +82,7 @@ MODULE_DESCRIPTION("tas codec driver for snd-aoa");
struct tas {
struct aoa_codec codec;
- struct i2c_client i2c;
+ struct i2c_client *i2c;
u32 mute_l:1, mute_r:1 ,
controls_created:1 ,
drc_enabled:1,
@@ -108,9 +108,9 @@ static struct tas *codec_to_tas(struct aoa_codec *codec)
static inline int tas_write_reg(struct tas *tas, u8 reg, u8 len, u8 *data)
{
if (len == 1)
- return i2c_smbus_write_byte_data(&tas->i2c, reg, *data);
+ return i2c_smbus_write_byte_data(tas->i2c, reg, *data);
else
- return i2c_smbus_write_i2c_block_data(&tas->i2c, reg, len, data);
+ return i2c_smbus_write_i2c_block_data(tas->i2c, reg, len, data);
}
static void tas3004_set_drc(struct tas *tas)
@@ -882,12 +882,34 @@ static void tas_exit_codec(struct aoa_codec *codec)
}
-static struct i2c_driver tas_driver;
-
static int tas_create(struct i2c_adapter *adapter,
struct device_node *node,
int addr)
{
+ struct i2c_board_info info;
+ struct i2c_client *client;
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "aoa_codec_tas", I2C_NAME_SIZE);
+ info.addr = addr;
+ info.platform_data = node;
+
+ client = i2c_new_device(adapter, &info);
+ if (!client)
+ return -ENODEV;
+
+ /*
+ * Let i2c-core delete that device on driver removal.
+ * This is safe because i2c-core holds the core_lock mutex for us.
+ */
+ list_add_tail(&client->detected, &client->driver->clients);
+ return 0;
+}
+
+static int tas_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device_node *node = client->dev.platform_data;
struct tas *tas;
tas = kzalloc(sizeof(struct tas), GFP_KERNEL);
@@ -896,17 +918,11 @@ static int tas_create(struct i2c_adapter *adapter,
return -ENOMEM;
mutex_init(&tas->mtx);
- tas->i2c.driver = &tas_driver;
- tas->i2c.adapter = adapter;
- tas->i2c.addr = addr;
+ tas->i2c = client;
+ i2c_set_clientdata(client, tas);
+
/* seems that half is a saner default */
tas->drc_range = TAS3004_DRC_MAX / 2;
- strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE);
-
- if (i2c_attach_client(&tas->i2c)) {
- printk(KERN_ERR PFX "failed to attach to i2c\n");
- goto fail;
- }
strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN);
tas->codec.owner = THIS_MODULE;
@@ -915,14 +931,12 @@ static int tas_create(struct i2c_adapter *adapter,
tas->codec.node = of_node_get(node);
if (aoa_codec_register(&tas->codec)) {
- goto detach;
+ goto fail;
}
printk(KERN_DEBUG
"snd-aoa-codec-tas: tas found, addr 0x%02x on %s\n",
- addr, node->full_name);
+ (unsigned int)client->addr, node->full_name);
return 0;
- detach:
- i2c_detach_client(&tas->i2c);
fail:
mutex_destroy(&tas->mtx);
kfree(tas);
@@ -970,14 +984,11 @@ static int tas_i2c_attach(struct i2c_adapter *adapter)
return -ENODEV;
}
-static int tas_i2c_detach(struct i2c_client *client)
+static int tas_i2c_remove(struct i2c_client *client)
{
- struct tas *tas = container_of(client, struct tas, i2c);
- int err;
+ struct tas *tas = i2c_get_clientdata(client);
u8 tmp = TAS_ACR_ANALOG_PDOWN;
- if ((err = i2c_detach_client(client)))
- return err;
aoa_codec_unregister(&tas->codec);
of_node_put(tas->codec.node);
@@ -989,13 +1000,20 @@ static int tas_i2c_detach(struct i2c_client *client)
return 0;
}
+static const struct i2c_device_id tas_i2c_id[] = {
+ { "aoa_codec_tas", 0 },
+ { }
+};
+
static struct i2c_driver tas_driver = {
.driver = {
.name = "aoa_codec_tas",
.owner = THIS_MODULE,
},
.attach_adapter = tas_i2c_attach,
- .detach_client = tas_i2c_detach,
+ .probe = tas_i2c_probe,
+ .remove = tas_i2c_remove,
+ .id_table = tas_i2c_id,
};
static int __init tas_init(void)
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c
index 0afd1a8226fb..a2c12d105c9a 100644
--- a/sound/arm/pxa2xx-ac97-lib.c
+++ b/sound/arm/pxa2xx-ac97-lib.c
@@ -364,7 +364,7 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume);
int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
{
int ret;
- struct pxa2xx_ac97_platform_data *pdata = dev->dev.platform_data;
+ pxa2xx_audio_ops_t *pdata = dev->dev.platform_data;
if (pdata) {
switch (pdata->reset_gpio) {
diff --git a/sound/core/control.c b/sound/core/control.c
index 4b20fa2b7e6d..17b8d47a5cd0 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -723,14 +723,11 @@ static int snd_ctl_elem_read_user(struct snd_card *card,
{
struct snd_ctl_elem_value *control;
int result;
-
- control = kmalloc(sizeof(*control), GFP_KERNEL);
- if (control == NULL)
- return -ENOMEM;
- if (copy_from_user(control, _control, sizeof(*control))) {
- kfree(control);
- return -EFAULT;
- }
+
+ control = memdup_user(_control, sizeof(*control));
+ if (IS_ERR(control))
+ return PTR_ERR(control);
+
snd_power_lock(card);
result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
if (result >= 0)
@@ -784,13 +781,10 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
struct snd_card *card;
int result;
- control = kmalloc(sizeof(*control), GFP_KERNEL);
- if (control == NULL)
- return -ENOMEM;
- if (copy_from_user(control, _control, sizeof(*control))) {
- kfree(control);
- return -EFAULT;
- }
+ control = memdup_user(_control, sizeof(*control));
+ if (IS_ERR(control))
+ return PTR_ERR(control);
+
card = file->card;
snd_power_lock(card);
result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
@@ -916,13 +910,10 @@ static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol,
if (op_flag > 0) {
if (size > 1024 * 128) /* sane value */
return -EINVAL;
- new_data = kmalloc(size, GFP_KERNEL);
- if (new_data == NULL)
- return -ENOMEM;
- if (copy_from_user(new_data, tlv, size)) {
- kfree(new_data);
- return -EFAULT;
- }
+
+ new_data = memdup_user(tlv, size);
+ if (IS_ERR(new_data))
+ return PTR_ERR(new_data);
change = ue->tlv_data_size != size;
if (!change)
change = memcmp(ue->tlv_data, new_data, size);
diff --git a/sound/core/jack.c b/sound/core/jack.c
index c8254c667c62..d54d1a05fe65 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -35,6 +35,9 @@ static int snd_jack_dev_free(struct snd_device *device)
{
struct snd_jack *jack = device->device_data;
+ if (jack->private_free)
+ jack->private_free(jack);
+
/* If the input device is registered with the input subsystem
* then we need to use a different deallocator. */
if (jack->registered)
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
index 36d7a5998234..08bfed594a83 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -232,14 +232,11 @@ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
if (! (runtime = substream->runtime))
return -ENOTTY;
- data = kmalloc(sizeof(*data), GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
/* only fifo_size is different, so just copy all */
- if (copy_from_user(data, data32, sizeof(*data32))) {
- err = -EFAULT;
- goto error;
- }
+ data = memdup_user(data32, sizeof(*data32));
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
if (refine)
err = snd_pcm_hw_refine(substream, data);
else
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index fbb2e391591e..a2a792c18c40 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -209,9 +209,11 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t pos;
- snd_pcm_uframes_t new_hw_ptr, hw_ptr_interrupt, hw_base;
- snd_pcm_sframes_t delta;
+ snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_ptr_interrupt, hw_base;
+ snd_pcm_sframes_t hdelta, delta;
+ unsigned long jdelta;
+ old_hw_ptr = runtime->status->hw_ptr;
pos = snd_pcm_update_hw_ptr_pos(substream, runtime);
if (pos == SNDRV_PCM_POS_XRUN) {
xrun(substream);
@@ -247,7 +249,37 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
new_hw_ptr = hw_base + pos;
}
}
- if (delta > runtime->period_size) {
+ /* Skip the jiffies check for hardwares with BATCH flag.
+ * Such hardware usually just increases the position at each IRQ,
+ * thus it can't give any strange position.
+ */
+ if (runtime->hw.info & SNDRV_PCM_INFO_BATCH)
+ goto no_jiffies_check;
+ hdelta = new_hw_ptr - old_hw_ptr;
+ jdelta = jiffies - runtime->hw_ptr_jiffies;
+ if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) {
+ delta = jdelta /
+ (((runtime->period_size * HZ) / runtime->rate)
+ + HZ/100);
+ hw_ptr_error(substream,
+ "hw_ptr skipping! [Q] "
+ "(pos=%ld, delta=%ld, period=%ld, "
+ "jdelta=%lu/%lu/%lu)\n",
+ (long)pos, (long)hdelta,
+ (long)runtime->period_size, jdelta,
+ ((hdelta * HZ) / runtime->rate), delta);
+ hw_ptr_interrupt = runtime->hw_ptr_interrupt +
+ runtime->period_size * delta;
+ if (hw_ptr_interrupt >= runtime->boundary)
+ hw_ptr_interrupt -= runtime->boundary;
+ /* rebase to interrupt position */
+ hw_base = new_hw_ptr = hw_ptr_interrupt;
+ /* align hw_base to buffer_size */
+ hw_base -= hw_base % runtime->buffer_size;
+ delta = 0;
+ }
+ no_jiffies_check:
+ if (delta > runtime->period_size + runtime->period_size / 2) {
hw_ptr_error(substream,
"Lost interrupts? "
"(stream=%i, delta=%ld, intr_ptr=%ld)\n",
@@ -263,6 +295,7 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
runtime->hw_ptr_base = hw_base;
runtime->status->hw_ptr = new_hw_ptr;
+ runtime->hw_ptr_jiffies = jiffies;
runtime->hw_ptr_interrupt = hw_ptr_interrupt;
return snd_pcm_update_hw_ptr_post(substream, runtime);
@@ -275,6 +308,7 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
snd_pcm_uframes_t pos;
snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base;
snd_pcm_sframes_t delta;
+ unsigned long jdelta;
old_hw_ptr = runtime->status->hw_ptr;
pos = snd_pcm_update_hw_ptr_pos(substream, runtime);
@@ -286,14 +320,15 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
new_hw_ptr = hw_base + pos;
delta = new_hw_ptr - old_hw_ptr;
+ jdelta = jiffies - runtime->hw_ptr_jiffies;
if (delta < 0) {
delta += runtime->buffer_size;
if (delta < 0) {
hw_ptr_error(substream,
"Unexpected hw_pointer value [2] "
- "(stream=%i, pos=%ld, old_ptr=%ld)\n",
+ "(stream=%i, pos=%ld, old_ptr=%ld, jdelta=%li)\n",
substream->stream, (long)pos,
- (long)old_hw_ptr);
+ (long)old_hw_ptr, jdelta);
return 0;
}
hw_base += runtime->buffer_size;
@@ -301,12 +336,13 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
hw_base = 0;
new_hw_ptr = hw_base + pos;
}
- if (delta > runtime->period_size && runtime->periods > 1) {
+ if (((delta * HZ) / runtime->rate) > jdelta + HZ/100) {
hw_ptr_error(substream,
"hw_ptr skipping! "
- "(pos=%ld, delta=%ld, period=%ld)\n",
+ "(pos=%ld, delta=%ld, period=%ld, jdelta=%lu/%lu)\n",
(long)pos, (long)delta,
- (long)runtime->period_size);
+ (long)runtime->period_size, jdelta,
+ ((delta * HZ) / runtime->rate));
return 0;
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
@@ -315,6 +351,7 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
runtime->hw_ptr_base = hw_base;
runtime->status->hw_ptr = new_hw_ptr;
+ runtime->hw_ptr_jiffies = jiffies;
return snd_pcm_update_hw_ptr_post(substream, runtime);
}
@@ -1441,6 +1478,7 @@ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
runtime->status->hw_ptr %= runtime->buffer_size;
else
runtime->status->hw_ptr = 0;
+ runtime->hw_ptr_jiffies = jiffies;
snd_pcm_stream_unlock_irqrestore(substream, flags);
return 0;
}
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index a151fb01ba82..cb769d415db7 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -327,21 +327,16 @@ static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params;
int err;
- params = kmalloc(sizeof(*params), GFP_KERNEL);
- if (!params) {
- err = -ENOMEM;
- goto out;
- }
- if (copy_from_user(params, _params, sizeof(*params))) {
- err = -EFAULT;
- goto out;
- }
+ params = memdup_user(_params, sizeof(*params));
+ if (IS_ERR(params))
+ return PTR_ERR(params);
+
err = snd_pcm_hw_refine(substream, params);
if (copy_to_user(_params, params, sizeof(*params))) {
if (!err)
err = -EFAULT;
}
-out:
+
kfree(params);
return err;
}
@@ -465,21 +460,16 @@ static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params;
int err;
- params = kmalloc(sizeof(*params), GFP_KERNEL);
- if (!params) {
- err = -ENOMEM;
- goto out;
- }
- if (copy_from_user(params, _params, sizeof(*params))) {
- err = -EFAULT;
- goto out;
- }
+ params = memdup_user(_params, sizeof(*params));
+ if (IS_ERR(params))
+ return PTR_ERR(params);
+
err = snd_pcm_hw_params(substream, params);
if (copy_to_user(_params, params, sizeof(*params))) {
if (!err)
err = -EFAULT;
}
-out:
+
kfree(params);
return err;
}
@@ -597,14 +587,15 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
status->avail = snd_pcm_playback_avail(runtime);
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING ||
- runtime->status->state == SNDRV_PCM_STATE_DRAINING)
+ runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
status->delay = runtime->buffer_size - status->avail;
- else
+ status->delay += runtime->delay;
+ } else
status->delay = 0;
} else {
status->avail = snd_pcm_capture_avail(runtime);
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
- status->delay = status->avail;
+ status->delay = status->avail + runtime->delay;
else
status->delay = 0;
}
@@ -2414,6 +2405,7 @@ static int snd_pcm_delay(struct snd_pcm_substream *substream,
n = snd_pcm_playback_hw_avail(runtime);
else
n = snd_pcm_capture_avail(runtime);
+ n += runtime->delay;
break;
case SNDRV_PCM_STATE_XRUN:
err = -EPIPE;
@@ -2593,13 +2585,11 @@ static int snd_pcm_playback_ioctl1(struct file *file,
return -EFAULT;
if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
return -EFAULT;
- bufs = kmalloc(sizeof(void *) * runtime->channels, GFP_KERNEL);
- if (bufs == NULL)
- return -ENOMEM;
- if (copy_from_user(bufs, xfern.bufs, sizeof(void *) * runtime->channels)) {
- kfree(bufs);
- return -EFAULT;
- }
+
+ bufs = memdup_user(xfern.bufs,
+ sizeof(void *) * runtime->channels);
+ if (IS_ERR(bufs))
+ return PTR_ERR(bufs);
result = snd_pcm_lib_writev(substream, bufs, xfern.frames);
kfree(bufs);
__put_user(result, &_xfern->result);
@@ -2675,13 +2665,11 @@ static int snd_pcm_capture_ioctl1(struct file *file,
return -EFAULT;
if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
return -EFAULT;
- bufs = kmalloc(sizeof(void *) * runtime->channels, GFP_KERNEL);
- if (bufs == NULL)
- return -ENOMEM;
- if (copy_from_user(bufs, xfern.bufs, sizeof(void *) * runtime->channels)) {
- kfree(bufs);
- return -EFAULT;
- }
+
+ bufs = memdup_user(xfern.bufs,
+ sizeof(void *) * runtime->channels);
+ if (IS_ERR(bufs))
+ return PTR_ERR(bufs);
result = snd_pcm_lib_readv(substream, bufs, xfern.frames);
kfree(bufs);
__put_user(result, &_xfern->result);
@@ -3312,18 +3300,12 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
int err;
params = kmalloc(sizeof(*params), GFP_KERNEL);
- if (!params) {
- err = -ENOMEM;
- goto out;
- }
- oparams = kmalloc(sizeof(*oparams), GFP_KERNEL);
- if (!oparams) {
- err = -ENOMEM;
- goto out;
- }
+ if (!params)
+ return -ENOMEM;
- if (copy_from_user(oparams, _oparams, sizeof(*oparams))) {
- err = -EFAULT;
+ oparams = memdup_user(_oparams, sizeof(*oparams));
+ if (IS_ERR(oparams)) {
+ err = PTR_ERR(oparams);
goto out;
}
snd_pcm_hw_convert_from_old_params(params, oparams);
@@ -3333,9 +3315,10 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
if (!err)
err = -EFAULT;
}
+
+ kfree(oparams);
out:
kfree(params);
- kfree(oparams);
return err;
}
@@ -3347,17 +3330,12 @@ static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
int err;
params = kmalloc(sizeof(*params), GFP_KERNEL);
- if (!params) {
- err = -ENOMEM;
- goto out;
- }
- oparams = kmalloc(sizeof(*oparams), GFP_KERNEL);
- if (!oparams) {
- err = -ENOMEM;
- goto out;
- }
- if (copy_from_user(oparams, _oparams, sizeof(*oparams))) {
- err = -EFAULT;
+ if (!params)
+ return -ENOMEM;
+
+ oparams = memdup_user(_oparams, sizeof(*oparams));
+ if (IS_ERR(oparams)) {
+ err = PTR_ERR(oparams);
goto out;
}
snd_pcm_hw_convert_from_old_params(params, oparams);
@@ -3367,9 +3345,10 @@ static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
if (!err)
err = -EFAULT;
}
+
+ kfree(oparams);
out:
kfree(params);
- kfree(oparams);
return err;
}
#endif /* CONFIG_SND_SUPPORT_OLD_API */
diff --git a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c
index 38693f47c262..c956fe462569 100644
--- a/sound/core/seq/seq_compat.c
+++ b/sound/core/seq/seq_compat.c
@@ -48,12 +48,11 @@ static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned
struct snd_seq_port_info *data;
mm_segment_t fs;
- data = kmalloc(sizeof(*data), GFP_KERNEL);
- if (! data)
- return -ENOMEM;
+ data = memdup_user(data32, sizeof(*data32));
+ if (IS_ERR(data))
+ return PTR_ERR(data);
- if (copy_from_user(data, data32, sizeof(*data32)) ||
- get_user(data->flags, &data32->flags) ||
+ if (get_user(data->flags, &data32->flags) ||
get_user(data->time_queue, &data32->time_queue))
goto error;
data->kernel = NULL;
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 3f0050d0b71e..8f8b17ac074d 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -1395,13 +1395,10 @@ static int snd_timer_user_ginfo(struct file *file,
struct list_head *p;
int err = 0;
- ginfo = kmalloc(sizeof(*ginfo), GFP_KERNEL);
- if (! ginfo)
- return -ENOMEM;
- if (copy_from_user(ginfo, _ginfo, sizeof(*ginfo))) {
- kfree(ginfo);
- return -EFAULT;
- }
+ ginfo = memdup_user(_ginfo, sizeof(*ginfo));
+ if (IS_ERR(ginfo))
+ return PTR_ERR(ginfo);
+
tid = ginfo->tid;
memset(ginfo, 0, sizeof(*ginfo));
ginfo->tid = tid;
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index b2b6d50c9425..a25fb7b1f441 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -963,16 +963,11 @@ static int __devinit snd_serial_probe(struct platform_device *devptr)
if (err < 0)
goto _err;
- sprintf(card->longname, "%s at 0x%lx, irq %d speed %d div %d outs %d ins %d adaptor %s droponfull %d",
+ sprintf(card->longname, "%s [%s] at %#lx, irq %d",
card->shortname,
- uart->base,
- uart->irq,
- uart->speed,
- (int)uart->divisor,
- outs[dev],
- ins[dev],
adaptor_names[uart->adaptor],
- uart->drop_on_full);
+ uart->base,
+ uart->irq);
snd_card_set_dev(card, &devptr->dev);
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index c6942a4de99b..51a7e3777e17 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -177,15 +177,18 @@ config SND_ES18XX
will be called snd-es18xx.
config SND_SC6000
- tristate "Gallant SC-6000, Audio Excel DSP 16"
+ tristate "Gallant SC-6000/6600/7000 and Audio Excel DSP 16"
depends on HAS_IOPORT
select SND_WSS_LIB
select SND_OPL3_LIB
select SND_MPU401_UART
help
- Say Y here to include support for Gallant SC-6000 card and clones:
+ Say Y here to include support for Gallant SC-6000, SC-6600, SC-7000
+ cards and clones:
Audio Excel DSP 16 and Zoltrix AV302.
+ These cards are based on CompuMedia ASC-9308 or ASC-9408 chips.
+
To compile this driver as a module, choose M here: the module
will be called snd-sc6000.
diff --git a/sound/isa/msnd/msnd.c b/sound/isa/msnd/msnd.c
index 906454413ed2..3a1526ae1729 100644
--- a/sound/isa/msnd/msnd.c
+++ b/sound/isa/msnd/msnd.c
@@ -438,7 +438,8 @@ static void snd_msnd_capture_reset_queue(struct snd_msnd *chip,
static struct snd_pcm_hardware snd_msnd_playback = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP_VALID,
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH,
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_8000_48000,
.rate_min = 8000,
@@ -456,7 +457,8 @@ static struct snd_pcm_hardware snd_msnd_playback = {
static struct snd_pcm_hardware snd_msnd_capture = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP_VALID,
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH,
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_8000_48000,
.rate_min = 8000,
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
index 49037d074c71..bdc8dde4e4a2 100644
--- a/sound/isa/sb/sb16_csp.c
+++ b/sound/isa/sb/sb16_csp.c
@@ -684,15 +684,16 @@ static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int
static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __user *buf, int size, int load_flags)
{
- int err = -ENOMEM;
- unsigned char *kbuf = kmalloc(size, GFP_KERNEL);
- if (kbuf) {
- if (copy_from_user(kbuf, buf, size))
- err = -EFAULT;
- else
- err = snd_sb_csp_load(p, kbuf, size, load_flags);
- kfree(kbuf);
- }
+ int err;
+ unsigned char *kbuf;
+
+ kbuf = memdup_user(buf, size);
+ if (IS_ERR(kbuf))
+ return PTR_ERR(kbuf);
+
+ err = snd_sb_csp_load(p, kbuf, size, load_flags);
+
+ kfree(kbuf);
return err;
}
diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c
index 782010608ef4..9a8bbf6dd62a 100644
--- a/sound/isa/sc6000.c
+++ b/sound/isa/sc6000.c
@@ -2,6 +2,8 @@
* 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.
+ * SC-6600 and SC-7000 cards are also supported. They are based on
+ * CompuMedia ASC-9408 chip and CS4231 codec.
*
* Copyright (C) 2007 Krzysztof Helt <krzysztof.h1@wp.pl>
*
@@ -54,6 +56,7 @@ 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 */
+static bool joystick[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = false };
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for sc-6000 based soundcard.");
@@ -73,6 +76,8 @@ 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.");
+module_param_array(joystick, bool, NULL, 0444);
+MODULE_PARM_DESC(joystick, "Enable gameport.");
/*
* Commands of SC6000's DSP (SBPRO+special).
@@ -191,7 +196,7 @@ static __devinit unsigned char sc6000_mpu_irq_to_softcfg(int mpu_irq)
return val;
}
-static __devinit int sc6000_wait_data(char __iomem *vport)
+static int sc6000_wait_data(char __iomem *vport)
{
int loop = 1000;
unsigned char val = 0;
@@ -206,7 +211,7 @@ static __devinit int sc6000_wait_data(char __iomem *vport)
return -EAGAIN;
}
-static __devinit int sc6000_read(char __iomem *vport)
+static int sc6000_read(char __iomem *vport)
{
if (sc6000_wait_data(vport))
return -EBUSY;
@@ -215,7 +220,7 @@ static __devinit int sc6000_read(char __iomem *vport)
}
-static __devinit int sc6000_write(char __iomem *vport, int cmd)
+static int sc6000_write(char __iomem *vport, int cmd)
{
unsigned char val;
int loop = 500000;
@@ -276,8 +281,33 @@ static int __devinit sc6000_dsp_reset(char __iomem *vport)
}
/* detection and initialization */
-static int __devinit sc6000_cfg_write(char __iomem *vport,
- unsigned char softcfg)
+static int __devinit sc6000_hw_cfg_write(char __iomem *vport, const int *cfg)
+{
+ if (sc6000_write(vport, COMMAND_6C) < 0) {
+ snd_printk(KERN_WARNING "CMD 0x%x: failed!\n", COMMAND_6C);
+ return -EIO;
+ }
+ if (sc6000_write(vport, COMMAND_5C) < 0) {
+ snd_printk(KERN_ERR "CMD 0x%x: failed!\n", COMMAND_5C);
+ return -EIO;
+ }
+ if (sc6000_write(vport, cfg[0]) < 0) {
+ snd_printk(KERN_ERR "DATA 0x%x: failed!\n", cfg[0]);
+ return -EIO;
+ }
+ if (sc6000_write(vport, cfg[1]) < 0) {
+ snd_printk(KERN_ERR "DATA 0x%x: failed!\n", cfg[1]);
+ return -EIO;
+ }
+ if (sc6000_write(vport, COMMAND_C5) < 0) {
+ snd_printk(KERN_ERR "CMD 0x%x: failed!\n", COMMAND_C5);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int sc6000_cfg_write(char __iomem *vport, unsigned char softcfg)
{
if (sc6000_write(vport, WRITE_MDIRQ_CFG)) {
@@ -291,7 +321,7 @@ static int __devinit sc6000_cfg_write(char __iomem *vport,
return 0;
}
-static int __devinit sc6000_setup_board(char __iomem *vport, int config)
+static int sc6000_setup_board(char __iomem *vport, int config)
{
int loop = 10;
@@ -334,16 +364,39 @@ static int __devinit sc6000_init_mss(char __iomem *vport, int config,
return 0;
}
-static int __devinit sc6000_init_board(char __iomem *vport, int irq, int dma,
- char __iomem *vmss_port, int mpu_irq)
+static void __devinit sc6000_hw_cfg_encode(char __iomem *vport, int *cfg,
+ long xport, long xmpu,
+ long xmss_port, int joystick)
+{
+ cfg[0] = 0;
+ cfg[1] = 0;
+ if (xport == 0x240)
+ cfg[0] |= 1;
+ if (xmpu != SNDRV_AUTO_PORT) {
+ cfg[0] |= (xmpu & 0x30) >> 2;
+ cfg[1] |= 0x20;
+ }
+ if (xmss_port == 0xe80)
+ cfg[0] |= 0x10;
+ cfg[0] |= 0x40; /* always set */
+ if (!joystick)
+ cfg[0] |= 0x02;
+ cfg[1] |= 0x80; /* enable WSS system */
+ cfg[1] &= ~0x40; /* disable IDE */
+ snd_printd("hw cfg %x, %x\n", cfg[0], cfg[1]);
+}
+
+static int __devinit sc6000_init_board(char __iomem *vport,
+ char __iomem *vmss_port, int dev)
{
char answer[15];
char version[2];
- int mss_config = sc6000_irq_to_softcfg(irq) |
- sc6000_dma_to_softcfg(dma);
+ int mss_config = sc6000_irq_to_softcfg(irq[dev]) |
+ sc6000_dma_to_softcfg(dma[dev]);
int config = mss_config |
- sc6000_mpu_irq_to_softcfg(mpu_irq);
+ sc6000_mpu_irq_to_softcfg(mpu_irq[dev]);
int err;
+ int old = 0;
err = sc6000_dsp_reset(vport);
if (err < 0) {
@@ -360,7 +413,6 @@ static int __devinit sc6000_init_board(char __iomem *vport, int irq, int dma,
/*
* 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");
@@ -372,13 +424,32 @@ static int __devinit sc6000_init_board(char __iomem *vport, int irq, int dma,
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);
+ /* set configuration */
+ sc6000_write(vport, COMMAND_5C);
+ if (sc6000_read(vport) < 0)
+ old = 1;
+
+ if (!old) {
+ int cfg[2];
+ sc6000_hw_cfg_encode(vport, &cfg[0], port[dev], mpu_port[dev],
+ mss_port[dev], joystick[dev]);
+ if (sc6000_hw_cfg_write(vport, cfg) < 0) {
+ snd_printk(KERN_ERR "sc6000_hw_cfg_write: failed!\n");
+ return -EIO;
+ }
+ }
+ err = sc6000_setup_board(vport, config);
if (err < 0) {
- snd_printk(KERN_ERR "sc6000_cfg_write: failed!\n");
- return -EFAULT;
+ snd_printk(KERN_ERR "sc6000_setup_board: failed!\n");
+ return -ENODEV;
+ }
+
+ sc6000_dsp_reset(vport);
+
+ if (!old) {
+ sc6000_write(vport, COMMAND_60);
+ sc6000_write(vport, 0x02);
+ sc6000_dsp_reset(vport);
}
err = sc6000_setup_board(vport, config);
@@ -386,10 +457,9 @@ static int __devinit sc6000_init_board(char __iomem *vport, int irq, int dma,
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 "
+ snd_printk(KERN_ERR "Cannot initialize "
"Microsoft Sound System mode.\n");
return -ENODEV;
}
@@ -485,14 +555,16 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev)
struct snd_card *card;
struct snd_wss *chip;
struct snd_opl3 *opl3;
- char __iomem *vport;
+ char __iomem **vport;
char __iomem *vmss_port;
- err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+ err = snd_card_create(index[dev], id[dev], THIS_MODULE, sizeof(vport),
+ &card);
if (err < 0)
return err;
+ vport = card->private_data;
if (xirq == SNDRV_AUTO_IRQ) {
xirq = snd_legacy_find_free_irq(possible_irqs);
if (xirq < 0) {
@@ -517,8 +589,8 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev)
err = -EBUSY;
goto err_exit;
}
- vport = devm_ioport_map(devptr, port[dev], 0x10);
- if (!vport) {
+ *vport = devm_ioport_map(devptr, port[dev], 0x10);
+ if (*vport == NULL) {
snd_printk(KERN_ERR PFX
"I/O port cannot be iomaped.\n");
err = -EBUSY;
@@ -533,7 +605,7 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev)
goto err_unmap1;
}
vmss_port = devm_ioport_map(devptr, mss_port[dev], 4);
- if (!vport) {
+ if (!vmss_port) {
snd_printk(KERN_ERR PFX
"MSS port I/O cannot be iomaped.\n");
err = -EBUSY;
@@ -544,7 +616,7 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev)
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]);
+ err = sc6000_init_board(*vport, vmss_port, dev);
if (err < 0)
goto err_unmap2;
@@ -552,7 +624,6 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev)
WSS_HW_DETECT, 0, &chip);
if (err < 0)
goto err_unmap2;
- card->private_data = chip;
err = snd_wss_pcm(chip, 0, NULL);
if (err < 0) {
@@ -608,6 +679,7 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev)
return 0;
err_unmap2:
+ sc6000_setup_board(*vport, 0);
release_region(mss_port[dev], 4);
err_unmap1:
release_region(port[dev], 0x10);
@@ -618,11 +690,17 @@ err_exit:
static int __devexit snd_sc6000_remove(struct device *devptr, unsigned int dev)
{
+ struct snd_card *card = dev_get_drvdata(devptr);
+ char __iomem **vport = card->private_data;
+
+ if (sc6000_setup_board(*vport, 0) < 0)
+ snd_printk(KERN_WARNING "sc6000_setup_board failed on exit!\n");
+
release_region(port[dev], 0x10);
release_region(mss_port[dev], 4);
- snd_card_free(dev_get_drvdata(devptr));
dev_set_drvdata(devptr, NULL);
+ snd_card_free(card);
return 0;
}
diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c
index a4345fc07561..2bb1cee09255 100644
--- a/sound/isa/wavefront/wavefront_fx.c
+++ b/sound/isa/wavefront/wavefront_fx.c
@@ -202,15 +202,11 @@ snd_wavefront_fx_ioctl (struct snd_hwdep *sdev, struct file *file,
"> 512 bytes to FX\n");
return -EIO;
}
- page_data = kmalloc(r.data[2] * sizeof(short), GFP_KERNEL);
- if (!page_data)
- return -ENOMEM;
- if (copy_from_user (page_data,
- (unsigned char __user *) r.data[3],
- r.data[2] * sizeof(short))) {
- kfree(page_data);
- return -EFAULT;
- }
+ page_data = memdup_user((unsigned char __user *)
+ r.data[3],
+ r.data[2] * sizeof(short));
+ if (IS_ERR(page_data))
+ return PTR_ERR(page_data);
pd = page_data;
}
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
index beb312cca75b..5d4ff48c4345 100644
--- a/sound/isa/wavefront/wavefront_synth.c
+++ b/sound/isa/wavefront/wavefront_synth.c
@@ -1664,12 +1664,11 @@ snd_wavefront_synth_ioctl (struct snd_hwdep *hw, struct file *file,
break;
case WFCTL_WFCMD:
- wc = kmalloc(sizeof(*wc), GFP_KERNEL);
- if (! wc)
- return -ENOMEM;
- if (copy_from_user (wc, argp, sizeof (*wc)))
- err = -EFAULT;
- else if (wavefront_synth_control (acard, wc) < 0)
+ wc = memdup_user(argp, sizeof(*wc));
+ if (IS_ERR(wc))
+ return PTR_ERR(wc);
+
+ if (wavefront_synth_control (acard, wc) < 0)
err = -EIO;
else if (copy_to_user (argp, wc, sizeof (*wc)))
err = -EFAULT;
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 93422e3a3f0c..e912b70b6f9c 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -622,6 +622,16 @@ config SND_KORG1212
To compile this driver as a module, choose M here: the module
will be called snd-korg1212.
+config SND_LX6464ES
+ tristate "Digigram LX6464ES"
+ select SND_PCM
+ help
+ Say Y here to include support for Digigram LX6464ES boards.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-lx6464es.
+
+
config SND_MAESTRO3
tristate "ESS Allegro/Maestro3"
select SND_AC97_CODEC
diff --git a/sound/pci/Makefile b/sound/pci/Makefile
index 65b25d221cd2..7d83e084dcf4 100644
--- a/sound/pci/Makefile
+++ b/sound/pci/Makefile
@@ -62,6 +62,7 @@ obj-$(CONFIG_SND) += \
ca0106/ \
cs46xx/ \
cs5535audio/ \
+ lx6464es/ \
echoaudio/ \
emu10k1/ \
hda/ \
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 97ee127ac33d..78288dbfc17a 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -2122,7 +2122,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 + msecs_to_jiffies(100);
+ end_time = jiffies + msecs_to_jiffies(120);
do {
if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f)
goto __ready_ok;
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 9ce8548c03e4..71515ddb4593 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1393,6 +1393,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
.name = "HP nx6125",
.type = AC97_TUNE_MUTE_LED
},
+ {
+ .subvendor = 0x103c,
+ .subdevice = 0x3091,
+ .name = "unknown HP",
+ .type = AC97_TUNE_MUTE_LED
+ },
{ } /* terminator */
};
diff --git a/sound/pci/aw2/aw2-saa7146.c b/sound/pci/aw2/aw2-saa7146.c
index 6a3891ab69dd..296123ab74f7 100644
--- a/sound/pci/aw2/aw2-saa7146.c
+++ b/sound/pci/aw2/aw2-saa7146.c
@@ -108,7 +108,7 @@ void snd_aw2_saa7146_setup(struct snd_aw2_saa7146 *chip,
#endif
/* WS0_CTRL, WS0_SYNC: input TSL1, I2S */
- /* At initialization WS1 and WS2 are disbaled (configured as input */
+ /* At initialization WS1 and WS2 are disabled (configured as input) */
acon1 |= 0 * WS1_CTRL;
acon1 |= 0 * WS2_CTRL;
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index a299340519df..ce3f2e90f4d7 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -349,7 +349,8 @@ static struct snd_pcm_hardware snd_bt87x_digital_hw = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID,
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = 0, /* set at runtime */
.channels_min = 2,
@@ -365,7 +366,8 @@ static struct snd_pcm_hardware snd_bt87x_analog_hw = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID,
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
.rates = SNDRV_PCM_RATE_KNOT,
.rate_min = ANALOG_CLOCK / CLOCK_DIV_MAX,
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index c7899c32aba1..449fe02f666e 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -3014,7 +3014,7 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc
.dev_free = snd_cmipci_dev_free,
};
unsigned int val;
- long iomidi;
+ long iomidi = 0;
int integrated_midi = 0;
char modelstr[16];
int pcm_index, pcm_spdif_index;
diff --git a/sound/pci/echoaudio/indigodjx.c b/sound/pci/echoaudio/indigodjx.c
index 3482ef69f491..2e44316530a2 100644
--- a/sound/pci/echoaudio/indigodjx.c
+++ b/sound/pci/echoaudio/indigodjx.c
@@ -88,6 +88,7 @@ static struct snd_pcm_hardware pcm_hardware_skel = {
.rates = SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_64000 |
SNDRV_PCM_RATE_88200 |
SNDRV_PCM_RATE_96000,
.rate_min = 32000,
diff --git a/sound/pci/echoaudio/indigoiox.c b/sound/pci/echoaudio/indigoiox.c
index aebee27a40ff..eb3819f9654a 100644
--- a/sound/pci/echoaudio/indigoiox.c
+++ b/sound/pci/echoaudio/indigoiox.c
@@ -89,6 +89,7 @@ static struct snd_pcm_hardware pcm_hardware_skel = {
.rates = SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_64000 |
SNDRV_PCM_RATE_88200 |
SNDRV_PCM_RATE_96000,
.rate_min = 32000,
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index 191e1cd9997d..4b302d86f5f2 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -2493,24 +2493,17 @@ static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, un
case SNDRV_EMU10K1_IOCTL_CODE_POKE:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- icode = kmalloc(sizeof(*icode), GFP_KERNEL);
- if (icode == NULL)
- return -ENOMEM;
- if (copy_from_user(icode, argp, sizeof(*icode))) {
- kfree(icode);
- return -EFAULT;
- }
+
+ icode = memdup_user(argp, sizeof(*icode));
+ if (IS_ERR(icode))
+ return PTR_ERR(icode);
res = snd_emu10k1_icode_poke(emu, icode);
kfree(icode);
return res;
case SNDRV_EMU10K1_IOCTL_CODE_PEEK:
- icode = kmalloc(sizeof(*icode), GFP_KERNEL);
- if (icode == NULL)
- return -ENOMEM;
- if (copy_from_user(icode, argp, sizeof(*icode))) {
- kfree(icode);
- return -EFAULT;
- }
+ icode = memdup_user(argp, sizeof(*icode));
+ if (IS_ERR(icode))
+ return PTR_ERR(icode);
res = snd_emu10k1_icode_peek(emu, icode);
if (res == 0 && copy_to_user(argp, icode, sizeof(*icode))) {
kfree(icode);
@@ -2519,24 +2512,16 @@ static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, un
kfree(icode);
return res;
case SNDRV_EMU10K1_IOCTL_PCM_POKE:
- ipcm = kmalloc(sizeof(*ipcm), GFP_KERNEL);
- if (ipcm == NULL)
- return -ENOMEM;
- if (copy_from_user(ipcm, argp, sizeof(*ipcm))) {
- kfree(ipcm);
- return -EFAULT;
- }
+ ipcm = memdup_user(argp, sizeof(*ipcm));
+ if (IS_ERR(ipcm))
+ return PTR_ERR(ipcm);
res = snd_emu10k1_ipcm_poke(emu, ipcm);
kfree(ipcm);
return res;
case SNDRV_EMU10K1_IOCTL_PCM_PEEK:
- ipcm = kzalloc(sizeof(*ipcm), GFP_KERNEL);
- if (ipcm == NULL)
- return -ENOMEM;
- if (copy_from_user(ipcm, argp, sizeof(*ipcm))) {
- kfree(ipcm);
- return -EFAULT;
- }
+ ipcm = memdup_user(argp, sizeof(*ipcm));
+ if (IS_ERR(ipcm))
+ return PTR_ERR(ipcm);
res = snd_emu10k1_ipcm_peek(emu, ipcm);
if (res == 0 && copy_to_user(argp, ipcm, sizeof(*ipcm))) {
kfree(ipcm);
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c
index 4bfc31d1b281..c1a5aa15af8f 100644
--- a/sound/pci/emu10k1/io.c
+++ b/sound/pci/emu10k1/io.c
@@ -490,7 +490,7 @@ void snd_emu10k1_wait(struct snd_emu10k1 *emu, unsigned int wait)
if (newtime != curtime)
break;
}
- if (count >= 16384)
+ if (count > 16384)
break;
curtime = newtime;
}
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index eb2a19b894a0..c710150d5065 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -139,6 +139,19 @@ config SND_HDA_CODEC_CONEXANT
snd-hda-codec-conexant.
This module is automatically loaded at probing.
+config SND_HDA_CODEC_CA0110
+ bool "Build Creative CA0110-IBG codec support"
+ depends on SND_HDA_INTEL
+ default y
+ help
+ Say Y here to include Creative CA0110-IBG codec support in
+ snd-hda-intel driver, found on some Creative X-Fi cards.
+
+ When the HD-audio driver is built as a module, the codec
+ support code is also built as another module,
+ snd-hda-codec-ca0110.
+ This module is automatically loaded at probing.
+
config SND_HDA_CODEC_CMEDIA
bool "Build C-Media HD-audio codec support"
default y
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 50f9d0967251..e3081d4586cc 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -13,6 +13,7 @@ snd-hda-codec-analog-objs := patch_analog.o
snd-hda-codec-idt-objs := patch_sigmatel.o
snd-hda-codec-si3054-objs := patch_si3054.o
snd-hda-codec-atihdmi-objs := patch_atihdmi.o
+snd-hda-codec-ca0110-objs := patch_ca0110.o
snd-hda-codec-conexant-objs := patch_conexant.o
snd-hda-codec-via-objs := patch_via.o
snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o
@@ -40,6 +41,9 @@ endif
ifdef CONFIG_SND_HDA_CODEC_ATIHDMI
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-atihdmi.o
endif
+ifdef CONFIG_SND_HDA_CODEC_CA0110
+obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-ca0110.o
+endif
ifdef CONFIG_SND_HDA_CODEC_CONEXANT
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-conexant.o
endif
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index a4e5e5952115..b91f6ed5cc58 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -48,6 +48,7 @@ static struct hda_vendor_id hda_vendor_ids[] = {
{ 0x1095, "Silicon Image" },
{ 0x10de, "Nvidia" },
{ 0x10ec, "Realtek" },
+ { 0x1102, "Creative" },
{ 0x1106, "VIA" },
{ 0x111d, "IDT" },
{ 0x11c1, "LSI" },
@@ -174,14 +175,23 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
unsigned int verb, unsigned int parm)
{
struct hda_bus *bus = codec->bus;
- unsigned int res;
+ unsigned int cmd, res;
+ int repeated = 0;
- res = make_codec_cmd(codec, nid, direct, verb, parm);
+ cmd = make_codec_cmd(codec, nid, direct, verb, parm);
snd_hda_power_up(codec);
mutex_lock(&bus->cmd_mutex);
- if (!bus->ops.command(bus, res))
+ again:
+ if (!bus->ops.command(bus, cmd)) {
res = bus->ops.get_response(bus);
- else
+ if (res == -1 && bus->rirb_error) {
+ if (repeated++ < 1) {
+ snd_printd(KERN_WARNING "hda_codec: "
+ "Trying verb 0x%08x again\n", cmd);
+ goto again;
+ }
+ }
+ } else
res = (unsigned int)-1;
mutex_unlock(&bus->cmd_mutex);
snd_hda_power_down(codec);
@@ -642,19 +652,21 @@ static int get_codec_name(struct hda_codec *codec)
*/
static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
{
- int i, total_nodes;
+ int i, total_nodes, function_id;
hda_nid_t nid;
total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
for (i = 0; i < total_nodes; i++, nid++) {
- codec->function_id = snd_hda_param_read(codec, nid,
+ function_id = snd_hda_param_read(codec, nid,
AC_PAR_FUNCTION_TYPE) & 0xff;
- switch (codec->function_id) {
+ switch (function_id) {
case AC_GRP_AUDIO_FUNCTION:
codec->afg = nid;
+ codec->function_id = function_id;
break;
case AC_GRP_MODEM_FUNCTION:
codec->mfg = nid;
+ codec->function_id = function_id;
break;
default:
break;
@@ -1053,6 +1065,8 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
/* FIXME: more better hash key? */
#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
+#define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
+#define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
#define INFO_AMP_CAPS (1<<0)
#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
@@ -1143,19 +1157,32 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
}
EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
-u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
+static unsigned int
+query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key,
+ unsigned int (*func)(struct hda_codec *, hda_nid_t))
{
struct hda_amp_info *info;
- info = get_alloc_amp_hash(codec, HDA_HASH_PINCAP_KEY(nid));
+ info = get_alloc_amp_hash(codec, key);
if (!info)
return 0;
if (!info->head.val) {
- info->amp_caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
info->head.val |= INFO_AMP_CAPS;
+ info->amp_caps = func(codec, nid);
}
return info->amp_caps;
}
+
+static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
+{
+ return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+}
+
+u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
+{
+ return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
+ read_pin_cap);
+}
EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
/*
@@ -1430,6 +1457,8 @@ _snd_hda_find_mixer_ctl(struct hda_codec *codec,
memset(&id, 0, sizeof(id));
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
id.index = idx;
+ if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
+ return NULL;
strcpy(id.name, name);
return snd_ctl_find_id(codec->bus->card, &id);
}
@@ -2250,7 +2279,11 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
err = bus->ops.command(bus, res);
if (!err) {
struct hda_cache_head *c;
- u32 key = build_cmd_cache_key(nid, verb);
+ u32 key;
+ /* parm may contain the verb stuff for get/set amp */
+ verb = verb | (parm >> 8);
+ parm &= 0xff;
+ key = build_cmd_cache_key(nid, verb);
c = get_alloc_hash(&codec->cmd_cache, key);
if (c)
c->val = parm;
@@ -2315,7 +2348,8 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
if (wcaps & AC_WCAP_POWER) {
unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
AC_WCAP_TYPE_SHIFT;
- if (wid_type == AC_WID_PIN) {
+ if (power_state == AC_PWRST_D3 &&
+ wid_type == AC_WID_PIN) {
unsigned int pincap;
/*
* don't power down the widget if it controls
@@ -2327,7 +2361,7 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
nid, 0,
AC_VERB_GET_EAPD_BTLENABLE, 0);
eapd &= 0x02;
- if (power_state == AC_PWRST_D3 && eapd)
+ if (eapd)
continue;
}
}
@@ -2538,6 +2572,41 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
}
EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
+static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
+{
+ unsigned int val = 0;
+ if (nid != codec->afg &&
+ (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
+ val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
+ if (!val || val == -1)
+ val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
+ if (!val || val == -1)
+ return 0;
+ return val;
+}
+
+static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
+{
+ return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
+ get_pcm_param);
+}
+
+static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
+{
+ unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
+ if (!streams || streams == -1)
+ streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
+ if (!streams || streams == -1)
+ return 0;
+ return streams;
+}
+
+static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
+{
+ return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
+ get_stream_param);
+}
+
/**
* snd_hda_query_supported_pcm - query the supported PCM rates and formats
* @codec: the HDA codec
@@ -2556,15 +2625,8 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
{
unsigned int i, val, wcaps;
- val = 0;
wcaps = get_wcaps(codec, nid);
- if (nid != codec->afg && (wcaps & AC_WCAP_FORMAT_OVRD)) {
- val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
- if (val == -1)
- return -EIO;
- }
- if (!val)
- val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
+ val = query_pcm_param(codec, nid);
if (ratesp) {
u32 rates = 0;
@@ -2586,15 +2648,9 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
u64 formats = 0;
unsigned int streams, bps;
- streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
- if (streams == -1)
+ streams = query_stream_param(codec, nid);
+ if (!streams)
return -EIO;
- if (!streams) {
- streams = snd_hda_param_read(codec, codec->afg,
- AC_PAR_STREAM);
- if (streams == -1)
- return -EIO;
- }
bps = 0;
if (streams & AC_SUPFMT_PCM) {
@@ -2668,17 +2724,9 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
int i;
unsigned int val = 0, rate, stream;
- if (nid != codec->afg &&
- (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) {
- val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
- if (val == -1)
- return 0;
- }
- if (!val) {
- val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
- if (val == -1)
- return 0;
- }
+ val = query_pcm_param(codec, nid);
+ if (!val)
+ return 0;
rate = format & 0xff00;
for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
@@ -2690,12 +2738,8 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
if (i >= AC_PAR_PCM_RATE_BITS)
return 0;
- stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
- if (stream == -1)
- return 0;
- if (!stream && nid != codec->afg)
- stream = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
- if (!stream || stream == -1)
+ stream = query_stream_param(codec, nid);
+ if (!stream)
return 0;
if (stream & AC_SUPFMT_PCM) {
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 2fdecf4b0eb6..cd8979c7670b 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -623,6 +623,7 @@ struct hda_bus {
/* misc op flags */
unsigned int needs_damn_long_delay :1;
unsigned int shutdown :1; /* being unloaded */
+ unsigned int rirb_error:1; /* error in codec communication */
};
/*
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 30829ee920c3..04f19f8cad84 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -312,6 +312,8 @@ struct azx_dev {
unsigned int period_bytes; /* size of the period in bytes */
unsigned int frags; /* number for period in the play buffer */
unsigned int fifo_size; /* FIFO size */
+ unsigned long start_jiffies; /* start + minimum jiffies */
+ unsigned long min_jiffies; /* minimum jiffies before position is valid */
void __iomem *sd_addr; /* stream descriptor pointer */
@@ -330,7 +332,7 @@ struct azx_dev {
unsigned int opened :1;
unsigned int running :1;
unsigned int irq_pending :1;
- unsigned int irq_ignore :1;
+ unsigned int start_flag: 1; /* stream full start flag */
/*
* For VIA:
* A flag to ensure DMA position is 0
@@ -604,6 +606,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
}
if (!chip->rirb.cmds) {
smp_rmb();
+ bus->rirb_error = 0;
return chip->rirb.res; /* the last value */
}
if (time_after(jiffies, timeout))
@@ -623,8 +626,10 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
chip->irq = -1;
pci_disable_msi(chip->pci);
chip->msi = 0;
- if (azx_acquire_irq(chip, 1) < 0)
+ if (azx_acquire_irq(chip, 1) < 0) {
+ bus->rirb_error = 1;
return -1;
+ }
goto again;
}
@@ -644,14 +649,12 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
return -1;
}
- snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, "
- "switching to single_cmd mode: last cmd=0x%08x\n",
- chip->last_cmd);
- chip->rirb.rp = azx_readb(chip, RIRBWP);
- chip->rirb.cmds = 0;
- /* switch to single_cmd mode */
- chip->single_cmd = 1;
- azx_free_cmd_io(chip);
+ snd_printk(KERN_ERR "hda_intel: azx_get_response timeout (ERROR): "
+ "last cmd=0x%08x\n", chip->last_cmd);
+ spin_lock_irq(&chip->reg_lock);
+ chip->rirb.cmds = 0; /* reset the index */
+ bus->rirb_error = 1;
+ spin_unlock_irq(&chip->reg_lock);
return -1;
}
@@ -975,7 +978,7 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
struct azx *chip = dev_id;
struct azx_dev *azx_dev;
u32 status;
- int i;
+ int i, ok;
spin_lock(&chip->reg_lock);
@@ -991,18 +994,14 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
if (!azx_dev->substream || !azx_dev->running)
continue;
- /* ignore the first dummy IRQ (due to pos_adj) */
- if (azx_dev->irq_ignore) {
- azx_dev->irq_ignore = 0;
- continue;
- }
/* check whether this IRQ is really acceptable */
- if (azx_position_ok(chip, azx_dev)) {
+ ok = azx_position_ok(chip, azx_dev);
+ if (ok == 1) {
azx_dev->irq_pending = 0;
spin_unlock(&chip->reg_lock);
snd_pcm_period_elapsed(azx_dev->substream);
spin_lock(&chip->reg_lock);
- } else if (chip->bus && chip->bus->workq) {
+ } else if (ok == 0 && chip->bus && chip->bus->workq) {
/* bogus IRQ, process it later */
azx_dev->irq_pending = 1;
queue_work(chip->bus->workq,
@@ -1088,7 +1087,6 @@ static int azx_setup_periods(struct azx *chip,
bdl = (u32 *)azx_dev->bdl.area;
ofs = 0;
azx_dev->frags = 0;
- azx_dev->irq_ignore = 0;
pos_adj = bdl_pos_adj[chip->dev_index];
if (pos_adj > 0) {
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -1109,7 +1107,6 @@ static int azx_setup_periods(struct azx *chip,
&bdl, ofs, pos_adj, 1);
if (ofs < 0)
goto error;
- azx_dev->irq_ignore = 1;
}
} else
pos_adj = 0;
@@ -1155,6 +1152,9 @@ static void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev)
while (((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) &&
--timeout)
;
+
+ /* reset first position - may not be synced with hw at this time */
+ *azx_dev->posbuf = 0;
}
/*
@@ -1409,7 +1409,6 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
snd_pcm_set_sync(substream);
mutex_unlock(&chip->open_mutex);
- azx_stream_reset(chip, azx_dev);
return 0;
}
@@ -1474,6 +1473,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
unsigned int bufsize, period_bytes, format_val;
int err;
+ azx_stream_reset(chip, azx_dev);
format_val = snd_hda_calc_stream_format(runtime->rate,
runtime->channels,
runtime->format,
@@ -1502,6 +1502,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
return err;
}
+ azx_dev->min_jiffies = (runtime->period_size * HZ) /
+ (runtime->rate * 2);
azx_setup_controller(chip, azx_dev);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1;
@@ -1518,13 +1520,14 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
struct azx *chip = apcm->chip;
struct azx_dev *azx_dev;
struct snd_pcm_substream *s;
- int start, nsync = 0, sbits = 0;
+ int rstart = 0, start, nsync = 0, sbits = 0;
int nwait, timeout;
switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ rstart = 1;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_START:
start = 1;
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -1554,6 +1557,10 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
if (s->pcm->card != substream->pcm->card)
continue;
azx_dev = get_azx_dev(s);
+ if (rstart) {
+ azx_dev->start_flag = 1;
+ azx_dev->start_jiffies = jiffies + azx_dev->min_jiffies;
+ }
if (start)
azx_stream_start(chip, azx_dev);
else
@@ -1703,6 +1710,11 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
{
unsigned int pos;
+ if (azx_dev->start_flag &&
+ time_before_eq(jiffies, azx_dev->start_jiffies))
+ return -1; /* bogus (too early) interrupt */
+ azx_dev->start_flag = 0;
+
pos = azx_get_position(chip, azx_dev);
if (chip->position_fix == POS_FIX_AUTO) {
if (!pos) {
@@ -1819,7 +1831,7 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
&pcm);
if (err < 0)
return err;
- strcpy(pcm->name, cpcm->name);
+ strlcpy(pcm->name, cpcm->name, sizeof(pcm->name));
apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
if (apcm == NULL)
return -ENOMEM;
@@ -2260,11 +2272,11 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
gcap &= ~0x01;
/* allow 64bit DMA address if supported by H/W */
- if ((gcap & 0x01) && !pci_set_dma_mask(pci, DMA_64BIT_MASK))
- pci_set_consistent_dma_mask(pci, DMA_64BIT_MASK);
+ if ((gcap & 0x01) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
+ pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64));
else {
- pci_set_dma_mask(pci, DMA_32BIT_MASK);
- pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK);
+ pci_set_dma_mask(pci, DMA_BIT_MASK(32));
+ pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32));
}
/* read number of streams from GCAP register instead of using
@@ -2347,9 +2359,11 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
}
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);
+ strlcpy(card->shortname, driver_short_names[chip->driver_type],
+ sizeof(card->shortname));
+ snprintf(card->longname, sizeof(card->longname),
+ "%s at 0x%lx irq %i",
+ card->shortname, chip->addr, chip->irq);
*rchip = chip;
return 0;
@@ -2502,6 +2516,11 @@ static struct pci_device_id azx_ids[] = {
{ PCI_DEVICE(0x10de, 0x0d97), .driver_data = AZX_DRIVER_NVIDIA },
/* Teradici */
{ PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA },
+ /* Creative X-Fi (CA0110-IBG) */
+ { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_ANY_ID),
+ .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
+ .class_mask = 0xffffff,
+ .driver_data = AZX_DRIVER_GENERIC },
/* AMD Generic, PCI class code and Vendor ID for HD Audio */
{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID),
.class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 38ad3f7b040f..84cc49ca9148 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -3817,6 +3817,49 @@ static struct hda_verb ad1884a_laptop_verbs[] = {
{ } /* end */
};
+static struct hda_verb ad1884a_mobile_verbs[] = {
+ /* DACs; unmute as default */
+ {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
+ {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
+ /* Port-A (HP) mixer - route only from analog mixer */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ /* Port-A pin */
+ {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ /* Port-A (HP) pin - always unmuted */
+ {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* Port-B (mic jack) pin */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
+ /* Port-C (int mic) pin */
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
+ /* Port-F (int speaker) mixer - route only from analog mixer */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ /* Port-F pin */
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ /* Analog mixer; mute as default */
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
+ /* Analog Mix output amp */
+ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ /* capture sources */
+ /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ /* unsolicited event for pin-sense */
+ {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
+ {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
+ { } /* end */
+};
+
/*
* Thinkpad X300
* 0x11 - HP
@@ -3977,10 +4020,18 @@ static int patch_ad1884a(struct hda_codec *codec)
spec->input_mux = &ad1884a_laptop_capture_source;
codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
codec->patch_ops.init = ad1884a_hp_init;
+ /* set the upper-limit for mixer amp to 0dB for avoiding the
+ * possible damage by overloading
+ */
+ snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
+ (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
+ (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
+ (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
+ (1 << AC_AMPCAP_MUTE_SHIFT));
break;
case AD1884A_MOBILE:
spec->mixers[0] = ad1884a_mobile_mixers;
- spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
+ spec->init_verbs[0] = ad1884a_mobile_verbs;
spec->multiout.dig_out_nid = 0;
codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
codec->patch_ops.init = ad1884a_hp_init;
diff --git a/sound/pci/hda/patch_ca0110.c b/sound/pci/hda/patch_ca0110.c
new file mode 100644
index 000000000000..392d108c3558
--- /dev/null
+++ b/sound/pci/hda/patch_ca0110.c
@@ -0,0 +1,573 @@
+/*
+ * HD audio interface patch for Creative X-Fi CA0110-IBG chip
+ *
+ * Copyright (c) 2008 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 <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+
+/*
+ */
+
+struct ca0110_spec {
+ struct auto_pin_cfg autocfg;
+ struct hda_multi_out multiout;
+ hda_nid_t out_pins[AUTO_CFG_MAX_OUTS];
+ hda_nid_t dacs[AUTO_CFG_MAX_OUTS];
+ hda_nid_t hp_dac;
+ hda_nid_t input_pins[AUTO_PIN_LAST];
+ hda_nid_t adcs[AUTO_PIN_LAST];
+ hda_nid_t dig_out;
+ hda_nid_t dig_in;
+ unsigned int num_inputs;
+ const char *input_labels[AUTO_PIN_LAST];
+ struct hda_pcm pcm_rec[2]; /* PCM information */
+};
+
+/*
+ * PCM callbacks
+ */
+static int ca0110_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ struct snd_pcm_substream *substream)
+{
+ struct ca0110_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
+ hinfo);
+}
+
+static int ca0110_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ unsigned int stream_tag,
+ unsigned int format,
+ struct snd_pcm_substream *substream)
+{
+ struct ca0110_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
+ stream_tag, format, substream);
+}
+
+static int ca0110_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ struct snd_pcm_substream *substream)
+{
+ struct ca0110_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
+}
+
+/*
+ * Digital out
+ */
+static int ca0110_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ struct snd_pcm_substream *substream)
+{
+ struct ca0110_spec *spec = codec->spec;
+ return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+}
+
+static int ca0110_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ struct snd_pcm_substream *substream)
+{
+ struct ca0110_spec *spec = codec->spec;
+ return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
+
+static int ca0110_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ unsigned int stream_tag,
+ unsigned int format,
+ struct snd_pcm_substream *substream)
+{
+ struct ca0110_spec *spec = codec->spec;
+ return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
+ format, substream);
+}
+
+/*
+ * Analog capture
+ */
+static int ca0110_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ unsigned int stream_tag,
+ unsigned int format,
+ struct snd_pcm_substream *substream)
+{
+ struct ca0110_spec *spec = codec->spec;
+
+ snd_hda_codec_setup_stream(codec, spec->adcs[substream->number],
+ stream_tag, 0, format);
+ return 0;
+}
+
+static int ca0110_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ struct snd_pcm_substream *substream)
+{
+ struct ca0110_spec *spec = codec->spec;
+
+ snd_hda_codec_cleanup_stream(codec, spec->adcs[substream->number]);
+ return 0;
+}
+
+/*
+ */
+
+static char *dirstr[2] = { "Playback", "Capture" };
+
+static int _add_switch(struct hda_codec *codec, hda_nid_t nid, const char *pfx,
+ int chan, int dir)
+{
+ char namestr[44];
+ int type = dir ? HDA_INPUT : HDA_OUTPUT;
+ struct snd_kcontrol_new knew =
+ HDA_CODEC_MUTE_MONO(namestr, nid, chan, 0, type);
+ sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]);
+ return snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec));
+}
+
+static int _add_volume(struct hda_codec *codec, hda_nid_t nid, const char *pfx,
+ int chan, int dir)
+{
+ char namestr[44];
+ int type = dir ? HDA_INPUT : HDA_OUTPUT;
+ struct snd_kcontrol_new knew =
+ HDA_CODEC_VOLUME_MONO(namestr, nid, chan, 0, type);
+ sprintf(namestr, "%s %s Volume", pfx, dirstr[dir]);
+ return snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec));
+}
+
+#define add_out_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 0)
+#define add_out_volume(codec, nid, pfx) _add_volume(codec, nid, pfx, 3, 0)
+#define add_in_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 1)
+#define add_in_volume(codec, nid, pfx) _add_volume(codec, nid, pfx, 3, 1)
+#define add_mono_switch(codec, nid, pfx, chan) \
+ _add_switch(codec, nid, pfx, chan, 0)
+#define add_mono_volume(codec, nid, pfx, chan) \
+ _add_volume(codec, nid, pfx, chan, 0)
+
+static int ca0110_build_controls(struct hda_codec *codec)
+{
+ struct ca0110_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ static char *prefix[AUTO_CFG_MAX_OUTS] = {
+ "Front", "Surround", NULL, "Side", "Multi"
+ };
+ hda_nid_t mutenid;
+ int i, err;
+
+ for (i = 0; i < spec->multiout.num_dacs; i++) {
+ if (get_wcaps(codec, spec->out_pins[i]) & AC_WCAP_OUT_AMP)
+ mutenid = spec->out_pins[i];
+ else
+ mutenid = spec->multiout.dac_nids[i];
+ if (!prefix[i]) {
+ err = add_mono_switch(codec, mutenid,
+ "Center", 1);
+ if (err < 0)
+ return err;
+ err = add_mono_switch(codec, mutenid,
+ "LFE", 1);
+ if (err < 0)
+ return err;
+ err = add_mono_volume(codec, spec->multiout.dac_nids[i],
+ "Center", 1);
+ if (err < 0)
+ return err;
+ err = add_mono_volume(codec, spec->multiout.dac_nids[i],
+ "LFE", 1);
+ if (err < 0)
+ return err;
+ } else {
+ err = add_out_switch(codec, mutenid,
+ prefix[i]);
+ if (err < 0)
+ return err;
+ err = add_out_volume(codec, spec->multiout.dac_nids[i],
+ prefix[i]);
+ if (err < 0)
+ return err;
+ }
+ }
+ if (cfg->hp_outs) {
+ if (get_wcaps(codec, cfg->hp_pins[0]) & AC_WCAP_OUT_AMP)
+ mutenid = cfg->hp_pins[0];
+ else
+ mutenid = spec->multiout.dac_nids[i];
+
+ err = add_out_switch(codec, mutenid, "Headphone");
+ if (err < 0)
+ return err;
+ if (spec->hp_dac) {
+ err = add_out_volume(codec, spec->hp_dac, "Headphone");
+ if (err < 0)
+ return err;
+ }
+ }
+ for (i = 0; i < spec->num_inputs; i++) {
+ const char *label = spec->input_labels[i];
+ if (get_wcaps(codec, spec->input_pins[i]) & AC_WCAP_IN_AMP)
+ mutenid = spec->input_pins[i];
+ else
+ mutenid = spec->adcs[i];
+ err = add_in_switch(codec, mutenid, label);
+ if (err < 0)
+ return err;
+ err = add_in_volume(codec, spec->adcs[i], label);
+ if (err < 0)
+ return err;
+ }
+
+ if (spec->dig_out) {
+ err = snd_hda_create_spdif_out_ctls(codec, spec->dig_out);
+ if (err < 0)
+ return err;
+ err = snd_hda_create_spdif_share_sw(codec, &spec->multiout);
+ if (err < 0)
+ return err;
+ spec->multiout.share_spdif = 1;
+ }
+ if (spec->dig_in) {
+ err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in);
+ if (err < 0)
+ return err;
+ err = add_in_volume(codec, spec->dig_in, "IEC958");
+ }
+ return 0;
+}
+
+/*
+ */
+static struct hda_pcm_stream ca0110_pcm_analog_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 8,
+ .ops = {
+ .open = ca0110_playback_pcm_open,
+ .prepare = ca0110_playback_pcm_prepare,
+ .cleanup = ca0110_playback_pcm_cleanup
+ },
+};
+
+static struct hda_pcm_stream ca0110_pcm_analog_capture = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 2,
+ .ops = {
+ .prepare = ca0110_capture_pcm_prepare,
+ .cleanup = ca0110_capture_pcm_cleanup
+ },
+};
+
+static struct hda_pcm_stream ca0110_pcm_digital_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 2,
+ .ops = {
+ .open = ca0110_dig_playback_pcm_open,
+ .close = ca0110_dig_playback_pcm_close,
+ .prepare = ca0110_dig_playback_pcm_prepare
+ },
+};
+
+static struct hda_pcm_stream ca0110_pcm_digital_capture = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 2,
+};
+
+static int ca0110_build_pcms(struct hda_codec *codec)
+{
+ struct ca0110_spec *spec = codec->spec;
+ struct hda_pcm *info = spec->pcm_rec;
+
+ codec->pcm_info = info;
+ codec->num_pcms = 0;
+
+ info->name = "CA0110 Analog";
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ca0110_pcm_analog_playback;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dacs[0];
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
+ spec->multiout.max_channels;
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0110_pcm_analog_capture;
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_inputs;
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0];
+ codec->num_pcms++;
+
+ if (!spec->dig_out && !spec->dig_in)
+ return 0;
+
+ info++;
+ info->name = "CA0110 Digital";
+ info->pcm_type = HDA_PCM_TYPE_SPDIF;
+ if (spec->dig_out) {
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
+ ca0110_pcm_digital_playback;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dig_out;
+ }
+ if (spec->dig_in) {
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] =
+ ca0110_pcm_digital_capture;
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in;
+ }
+ codec->num_pcms++;
+
+ return 0;
+}
+
+static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac)
+{
+ if (pin) {
+ snd_hda_codec_write(codec, pin, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
+ if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP)
+ snd_hda_codec_write(codec, pin, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE,
+ AMP_OUT_UNMUTE);
+ }
+ if (dac)
+ snd_hda_codec_write(codec, dac, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO);
+}
+
+static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc)
+{
+ if (pin) {
+ snd_hda_codec_write(codec, pin, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80);
+ if (get_wcaps(codec, pin) & AC_WCAP_IN_AMP)
+ snd_hda_codec_write(codec, pin, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE,
+ AMP_IN_UNMUTE(0));
+ }
+ if (adc)
+ snd_hda_codec_write(codec, adc, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+ AMP_IN_UNMUTE(0));
+}
+
+static int ca0110_init(struct hda_codec *codec)
+{
+ struct ca0110_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ int i;
+
+ for (i = 0; i < spec->multiout.num_dacs; i++)
+ init_output(codec, spec->out_pins[i],
+ spec->multiout.dac_nids[i]);
+ init_output(codec, cfg->hp_pins[0], spec->hp_dac);
+ init_output(codec, cfg->dig_out_pins[0], spec->dig_out);
+
+ for (i = 0; i < spec->num_inputs; i++)
+ init_input(codec, spec->input_pins[i], spec->adcs[i]);
+ init_input(codec, cfg->dig_in_pin, spec->dig_in);
+ return 0;
+}
+
+static void ca0110_free(struct hda_codec *codec)
+{
+ kfree(codec->spec);
+}
+
+static struct hda_codec_ops ca0110_patch_ops = {
+ .build_controls = ca0110_build_controls,
+ .build_pcms = ca0110_build_pcms,
+ .init = ca0110_init,
+ .free = ca0110_free,
+};
+
+
+static void parse_line_outs(struct hda_codec *codec)
+{
+ struct ca0110_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ int i, n;
+ unsigned int def_conf;
+ hda_nid_t nid;
+
+ n = 0;
+ for (i = 0; i < cfg->line_outs; i++) {
+ nid = cfg->line_out_pins[i];
+ def_conf = snd_hda_codec_get_pincfg(codec, nid);
+ if (!def_conf)
+ continue; /* invalid pin */
+ if (snd_hda_get_connections(codec, nid, &spec->dacs[i], 1) != 1)
+ continue;
+ spec->out_pins[n++] = nid;
+ }
+ spec->multiout.dac_nids = spec->dacs;
+ spec->multiout.num_dacs = n;
+ spec->multiout.max_channels = n * 2;
+}
+
+static void parse_hp_out(struct hda_codec *codec)
+{
+ struct ca0110_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ int i;
+ unsigned int def_conf;
+ hda_nid_t nid, dac;
+
+ if (!cfg->hp_outs)
+ return;
+ nid = cfg->hp_pins[0];
+ def_conf = snd_hda_codec_get_pincfg(codec, nid);
+ if (!def_conf) {
+ cfg->hp_outs = 0;
+ return;
+ }
+ if (snd_hda_get_connections(codec, nid, &dac, 1) != 1)
+ return;
+
+ for (i = 0; i < cfg->line_outs; i++)
+ if (dac == spec->dacs[i])
+ break;
+ if (i >= cfg->line_outs) {
+ spec->hp_dac = dac;
+ spec->multiout.hp_nid = dac;
+ }
+}
+
+static void parse_input(struct hda_codec *codec)
+{
+ struct ca0110_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ hda_nid_t nid, pin;
+ int n, i, j;
+
+ n = 0;
+ nid = codec->start_nid;
+ for (i = 0; i < codec->num_nodes; i++, nid++) {
+ unsigned int wcaps = get_wcaps(codec, nid);
+ unsigned int type = (wcaps & AC_WCAP_TYPE) >>
+ AC_WCAP_TYPE_SHIFT;
+ if (type != AC_WID_AUD_IN)
+ continue;
+ if (snd_hda_get_connections(codec, nid, &pin, 1) != 1)
+ continue;
+ if (pin == cfg->dig_in_pin) {
+ spec->dig_in = nid;
+ continue;
+ }
+ for (j = 0; j < AUTO_PIN_LAST; j++)
+ if (cfg->input_pins[j] == pin)
+ break;
+ if (j >= AUTO_PIN_LAST)
+ continue;
+ spec->input_pins[n] = pin;
+ spec->input_labels[n] = auto_pin_cfg_labels[j];
+ spec->adcs[n] = nid;
+ n++;
+ }
+ spec->num_inputs = n;
+}
+
+static void parse_digital(struct hda_codec *codec)
+{
+ struct ca0110_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+
+ if (cfg->dig_outs &&
+ snd_hda_get_connections(codec, cfg->dig_out_pins[0],
+ &spec->dig_out, 1) == 1)
+ spec->multiout.dig_out_nid = cfg->dig_out_pins[0];
+}
+
+static int ca0110_parse_auto_config(struct hda_codec *codec)
+{
+ struct ca0110_spec *spec = codec->spec;
+ int err;
+
+ err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
+ if (err < 0)
+ return err;
+
+ parse_line_outs(codec);
+ parse_hp_out(codec);
+ parse_digital(codec);
+ parse_input(codec);
+ return 0;
+}
+
+
+int patch_ca0110(struct hda_codec *codec)
+{
+ struct ca0110_spec *spec;
+ int err;
+
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+ if (!spec)
+ return -ENOMEM;
+ codec->spec = spec;
+
+ codec->bus->needs_damn_long_delay = 1;
+
+ err = ca0110_parse_auto_config(codec);
+ if (err < 0)
+ goto error;
+
+ codec->patch_ops = ca0110_patch_ops;
+
+ return 0;
+
+ error:
+ kfree(codec->spec);
+ codec->spec = NULL;
+ return err;
+}
+
+
+/*
+ * patch entries
+ */
+static struct hda_codec_preset snd_hda_preset_ca0110[] = {
+ { .id = 0x1102000a, .name = "CA0110-IBG", .patch = patch_ca0110 },
+ { .id = 0x1102000b, .name = "CA0110-IBG", .patch = patch_ca0110 },
+ { .id = 0x1102000d, .name = "SB0880 X-Fi", .patch = patch_ca0110 },
+ {} /* terminator */
+};
+
+MODULE_ALIAS("snd-hda-codec-id:1102000a");
+MODULE_ALIAS("snd-hda-codec-id:1102000b");
+MODULE_ALIAS("snd-hda-codec-id:1102000d");
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Creative CA0110-IBG HD-audio codec");
+
+static struct hda_codec_preset_list ca0110_list = {
+ .preset = snd_hda_preset_ca0110,
+ .owner = THIS_MODULE,
+};
+
+static int __init patch_ca0110_init(void)
+{
+ return snd_hda_add_codec_preset(&ca0110_list);
+}
+
+static void __exit patch_ca0110_exit(void)
+{
+ snd_hda_delete_codec_preset(&ca0110_list);
+}
+
+module_init(patch_ca0110_init)
+module_exit(patch_ca0110_exit)
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 1f2ad76ca94b..56ce19e68cb5 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -350,12 +350,20 @@ static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol,
}
#ifdef CONFIG_SND_JACK
+static void conexant_free_jack_priv(struct snd_jack *jack)
+{
+ struct conexant_jack *jacks = jack->private_data;
+ jacks->nid = 0;
+ jacks->jack = NULL;
+}
+
static int conexant_add_jack(struct hda_codec *codec,
hda_nid_t nid, int type)
{
struct conexant_spec *spec;
struct conexant_jack *jack;
const char *name;
+ int err;
spec = codec->spec;
snd_array_init(&spec->jacks, sizeof(*jack), 32);
@@ -368,7 +376,12 @@ static int conexant_add_jack(struct hda_codec *codec,
jack->nid = nid;
jack->type = type;
- return snd_jack_new(codec->bus->card, name, type, &jack->jack);
+ err = snd_jack_new(codec->bus->card, name, type, &jack->jack);
+ if (err < 0)
+ return err;
+ jack->jack->private_data = jack;
+ jack->jack->private_free = conexant_free_jack_priv;
+ return 0;
}
static void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid)
@@ -455,8 +468,10 @@ static void conexant_free(struct hda_codec *codec)
if (spec->jacks.list) {
struct conexant_jack *jacks = spec->jacks.list;
int i;
- for (i = 0; i < spec->jacks.used; i++)
- snd_device_free(codec->bus->card, &jacks[i].jack);
+ for (i = 0; i < spec->jacks.used; i++, jacks++) {
+ if (jacks->jack)
+ snd_device_free(codec->bus->card, jacks->jack);
+ }
snd_array_free(&spec->jacks);
}
#endif
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index f35e58a2d921..db896121535a 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -188,6 +188,8 @@ enum {
ALC663_ASUS_MODE4,
ALC663_ASUS_MODE5,
ALC663_ASUS_MODE6,
+ ALC272_DELL,
+ ALC272_DELL_ZM1,
ALC662_AUTO,
ALC662_MODEL_LAST,
};
@@ -203,6 +205,7 @@ enum {
ALC882_ASUS_A7M,
ALC885_MACPRO,
ALC885_MBP3,
+ ALC885_MB5,
ALC885_IMAC24,
ALC882_AUTO,
ALC882_MODEL_LAST,
@@ -251,6 +254,15 @@ enum {
/* for GPIO Poll */
#define GPIO_MASK 0x03
+/* extra amp-initialization sequence types */
+enum {
+ ALC_INIT_NONE,
+ ALC_INIT_DEFAULT,
+ ALC_INIT_GPIO1,
+ ALC_INIT_GPIO2,
+ ALC_INIT_GPIO3,
+};
+
struct alc_spec {
/* codec parameterization */
struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
@@ -320,6 +332,7 @@ struct alc_spec {
/* other flags */
unsigned int no_analog :1; /* digital I/O only */
+ int init_amp;
/* for virtual master */
hda_nid_t vmaster_nid;
@@ -913,20 +926,26 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
alc_fix_pll(codec);
}
-static void alc_sku_automute(struct hda_codec *codec)
+static void alc_automute_pin(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
unsigned int present;
- unsigned int hp_nid = spec->autocfg.hp_pins[0];
- unsigned int sp_nid = spec->autocfg.speaker_pins[0];
+ unsigned int nid = spec->autocfg.hp_pins[0];
+ int i;
/* 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,
+ snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0);
+ present = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_PIN_SENSE, 0);
- spec->jack_present = (present & 0x80000000) != 0;
- snd_hda_codec_write(codec, sp_nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- spec->jack_present ? 0 : PIN_OUT);
+ spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;
+ for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
+ nid = spec->autocfg.speaker_pins[i];
+ if (!nid)
+ break;
+ snd_hda_codec_write(codec, nid, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ spec->jack_present ? 0 : PIN_OUT);
+ }
}
#if 0 /* it's broken in some acses -- temporarily disabled */
@@ -961,16 +980,19 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
res >>= 28;
else
res >>= 26;
- if (res == ALC880_HP_EVENT)
- alc_sku_automute(codec);
-
- if (res == ALC880_MIC_EVENT)
+ switch (res) {
+ case ALC880_HP_EVENT:
+ alc_automute_pin(codec);
+ break;
+ case ALC880_MIC_EVENT:
alc_mic_automute(codec);
+ break;
+ }
}
static void alc_inithook(struct hda_codec *codec)
{
- alc_sku_automute(codec);
+ alc_automute_pin(codec);
alc_mic_automute(codec);
}
@@ -992,69 +1014,21 @@ static void alc888_coef_init(struct hda_codec *codec)
AC_VERB_SET_PROC_COEF, 0x3030);
}
-/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
- * 31 ~ 16 : Manufacture ID
- * 15 ~ 8 : SKU ID
- * 7 ~ 0 : Assembly ID
- * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
- */
-static void alc_subsystem_id(struct hda_codec *codec,
- unsigned int porta, unsigned int porte,
- unsigned int portd)
+static void alc_auto_init_amp(struct hda_codec *codec, int type)
{
- unsigned int ass, tmp, i;
- unsigned nid;
- struct alc_spec *spec = codec->spec;
-
- 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_get_pincfg(codec, nid);
- if (!(ass & 1) && !(ass & 0x100000))
- return;
- if ((ass >> 30) != 1) /* no physical connection */
- return;
+ unsigned int tmp;
- /* 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:
+ switch (type) {
+ case ALC_INIT_GPIO1:
snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
break;
- case 3:
+ case ALC_INIT_GPIO2:
snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
break;
- case 7:
+ case ALC_INIT_GPIO3:
snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
break;
- case 5: /* set EAPD output high */
+ case ALC_INIT_DEFAULT:
switch (codec->vendor_id) {
case 0x10ec0260:
snd_hda_codec_write(codec, 0x0f, 0,
@@ -1108,7 +1082,7 @@ do_sku:
tmp | 0x2010);
break;
case 0x10ec0888:
- /*alc888_coef_init(codec);*/ /* called in alc_init() */
+ alc888_coef_init(codec);
break;
case 0x10ec0267:
case 0x10ec0268:
@@ -1123,7 +1097,107 @@ do_sku:
tmp | 0x3000);
break;
}
- default:
+ break;
+ }
+}
+
+static void alc_init_auto_hp(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+
+ if (!spec->autocfg.hp_pins[0])
+ return;
+
+ if (!spec->autocfg.speaker_pins[0]) {
+ if (spec->autocfg.line_out_pins[0] &&
+ spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
+ spec->autocfg.speaker_pins[0] =
+ spec->autocfg.line_out_pins[0];
+ else
+ return;
+ }
+
+ snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
+ spec->autocfg.hp_pins[0]);
+ snd_hda_codec_write_cache(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;
+}
+
+/* check subsystem ID and set up device-specific initialization;
+ * return 1 if initialized, 0 if invalid SSID
+ */
+/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
+ * 31 ~ 16 : Manufacture ID
+ * 15 ~ 8 : SKU ID
+ * 7 ~ 0 : Assembly ID
+ * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
+ */
+static int alc_subsystem_id(struct hda_codec *codec,
+ hda_nid_t porta, hda_nid_t porte,
+ hda_nid_t portd)
+{
+ unsigned int ass, tmp, i;
+ unsigned nid;
+ struct alc_spec *spec = codec->spec;
+
+ ass = codec->subsystem_id & 0xffff;
+ if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
+ goto do_sku;
+
+ /* invalid SSID, check the special NID pin defcfg instead */
+ /*
+ * 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_get_pincfg(codec, nid);
+ snd_printd("realtek: No valid SSID, "
+ "checking pincfg 0x%08x for NID 0x%x\n",
+ ass, nid);
+ if (!(ass & 1) && !(ass & 0x100000))
+ return 0;
+ if ((ass >> 30) != 1) /* no physical connection */
+ return 0;
+
+ /* check sum */
+ tmp = 0;
+ for (i = 1; i < 16; i++) {
+ if ((ass >> i) & 1)
+ tmp++;
+ }
+ if (((ass >> 16) & 0xf) != tmp)
+ return 0;
+do_sku:
+ snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
+ ass & 0xffff, codec->vendor_id);
+ /*
+ * 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:
+ spec->init_amp = ALC_INIT_GPIO1;
+ break;
+ case 3:
+ spec->init_amp = ALC_INIT_GPIO2;
+ break;
+ case 7:
+ spec->init_amp = ALC_INIT_GPIO3;
+ break;
+ case 5:
+ spec->init_amp = ALC_INIT_DEFAULT;
break;
}
@@ -1131,7 +1205,7 @@ do_sku:
* when the external headphone out jack is plugged"
*/
if (!(ass & 0x8000))
- return;
+ return 1;
/*
* 10~8 : Jack location
* 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
@@ -1139,14 +1213,6 @@ do_sku:
* 15 : 1 --> enable the function "Mute internal speaker
* when the external headphone out jack is plugged"
*/
- if (!spec->autocfg.speaker_pins[0]) {
- if (spec->autocfg.line_out_pins[0])
- spec->autocfg.speaker_pins[0] =
- spec->autocfg.line_out_pins[0];
- else
- return;
- }
-
if (!spec->autocfg.hp_pins[0]) {
tmp = (ass >> 11) & 0x3; /* HP to chassis */
if (tmp == 0)
@@ -1156,23 +1222,23 @@ do_sku:
else if (tmp == 2)
spec->autocfg.hp_pins[0] = portd;
else
- return;
+ return 1;
}
- if (spec->autocfg.hp_pins[0])
- snd_hda_codec_write(codec, spec->autocfg.hp_pins[0], 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | ALC880_HP_EVENT);
-#if 0 /* it's broken in some acses -- temporarily disabled */
- if (spec->autocfg.input_pins[AUTO_PIN_MIC] &&
- spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC])
- snd_hda_codec_write(codec,
- spec->autocfg.input_pins[AUTO_PIN_MIC], 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | ALC880_MIC_EVENT);
-#endif /* disabled */
+ alc_init_auto_hp(codec);
+ return 1;
+}
- spec->unsol_event = alc_sku_unsol_event;
+static void alc_ssid_check(struct hda_codec *codec,
+ hda_nid_t porta, hda_nid_t porte, hda_nid_t portd)
+{
+ if (!alc_subsystem_id(codec, porta, porte, portd)) {
+ struct alc_spec *spec = codec->spec;
+ snd_printd("realtek: "
+ "Enable default setup for auto mode as fallback\n");
+ spec->init_amp = ALC_INIT_DEFAULT;
+ alc_init_auto_hp(codec);
+ }
}
/*
@@ -1307,32 +1373,58 @@ static struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
{}
};
-static void alc888_fujitsu_xa3530_automute(struct hda_codec *codec)
+static void alc_automute_amp(struct hda_codec *codec)
{
- unsigned int present;
- unsigned int bits;
- /* Line out presence */
- present = snd_hda_codec_read(codec, 0x17, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- /* HP out presence */
- present = present || snd_hda_codec_read(codec, 0x1b, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? HDA_AMP_MUTE : 0;
+ struct alc_spec *spec = codec->spec;
+ unsigned int val, mute;
+ hda_nid_t nid;
+ int i;
+
+ spec->jack_present = 0;
+ for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
+ nid = spec->autocfg.hp_pins[i];
+ if (!nid)
+ break;
+ val = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_PIN_SENSE, 0);
+ if (val & AC_PINSENSE_PRESENCE) {
+ spec->jack_present = 1;
+ break;
+ }
+ }
+
+ mute = spec->jack_present ? HDA_AMP_MUTE : 0;
/* Toggle internal speakers muting */
- snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, bits);
- /* Toggle internal bass muting */
- snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, bits);
+ for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
+ nid = spec->autocfg.speaker_pins[i];
+ if (!nid)
+ break;
+ snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, mute);
+ }
}
-static void alc888_fujitsu_xa3530_unsol_event(struct hda_codec *codec,
- unsigned int res)
+static void alc_automute_amp_unsol_event(struct hda_codec *codec,
+ unsigned int res)
{
- if (res >> 26 == ALC880_HP_EVENT)
- alc888_fujitsu_xa3530_automute(codec);
+ if (codec->vendor_id == 0x10ec0880)
+ res >>= 28;
+ else
+ res >>= 26;
+ if (res == ALC880_HP_EVENT)
+ alc_automute_amp(codec);
}
+static void alc888_fujitsu_xa3530_init_hook(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+
+ spec->autocfg.hp_pins[0] = 0x17; /* line-out */
+ spec->autocfg.hp_pins[1] = 0x1b; /* hp */
+ spec->autocfg.speaker_pins[0] = 0x14; /* speaker */
+ spec->autocfg.speaker_pins[1] = 0x15; /* bass */
+ alc_automute_amp(codec);
+}
/*
* ALC888 Acer Aspire 4930G model
@@ -1399,22 +1491,13 @@ static struct snd_kcontrol_new alc888_base_mixer[] = {
{ } /* end */
};
-static void alc888_acer_aspire_4930g_automute(struct hda_codec *codec)
+static void alc888_acer_aspire_4930g_init_hook(struct hda_codec *codec)
{
- unsigned int present;
- unsigned int bits;
- present = snd_hda_codec_read(codec, 0x15, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, bits);
-}
+ struct alc_spec *spec = codec->spec;
-static void alc888_acer_aspire_4930g_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if (res >> 26 == ALC880_HP_EVENT)
- alc888_acer_aspire_4930g_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ alc_automute_amp(codec);
}
/*
@@ -2382,21 +2465,6 @@ static struct hda_verb alc880_beep_init_verbs[] = {
{ }
};
-/* toggle speaker-output according to the hp-jack state */
-static void alc880_uniwill_hp_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_codec_read(codec, 0x14, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- 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 */
static void alc880_uniwill_mic_automute(struct hda_codec *codec)
{
@@ -2409,9 +2477,14 @@ static void alc880_uniwill_mic_automute(struct hda_codec *codec)
snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
}
-static void alc880_uniwill_automute(struct hda_codec *codec)
+static void alc880_uniwill_init_hook(struct hda_codec *codec)
{
- alc880_uniwill_hp_automute(codec);
+ struct alc_spec *spec = codec->spec;
+
+ spec->autocfg.hp_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x16;
+ alc_automute_amp(codec);
alc880_uniwill_mic_automute(codec);
}
@@ -2422,24 +2495,22 @@ static void alc880_uniwill_unsol_event(struct hda_codec *codec,
* definition. 4bit tag is placed at 28 bit!
*/
switch (res >> 28) {
- case ALC880_HP_EVENT:
- alc880_uniwill_hp_automute(codec);
- break;
case ALC880_MIC_EVENT:
alc880_uniwill_mic_automute(codec);
break;
+ default:
+ alc_automute_amp_unsol_event(codec, res);
+ break;
}
}
-static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec)
+static void alc880_uniwill_p53_init_hook(struct hda_codec *codec)
{
- unsigned int present;
- unsigned char bits;
+ struct alc_spec *spec = codec->spec;
- present = snd_hda_codec_read(codec, 0x14, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, HDA_AMP_MUTE, bits);
+ spec->autocfg.hp_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[0] = 0x15;
+ alc_automute_amp(codec);
}
static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
@@ -2461,10 +2532,10 @@ static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
/* Looks like the unsol event is incompatible with the standard
* definition. 4bit tag is placed at 28 bit!
*/
- if ((res >> 28) == ALC880_HP_EVENT)
- alc880_uniwill_p53_hp_automute(codec);
if ((res >> 28) == ALC880_DCVOL_EVENT)
alc880_uniwill_p53_dcvol_automute(codec);
+ else
+ alc_automute_amp_unsol_event(codec, res);
}
/*
@@ -2696,30 +2767,18 @@ static struct hda_verb alc880_lg_init_verbs[] = {
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
/* jack sense */
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1},
+ {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
{ }
};
/* toggle speaker-output according to the hp-jack state */
-static void alc880_lg_automute(struct hda_codec *codec)
+static void alc880_lg_init_hook(struct hda_codec *codec)
{
- unsigned int present;
- unsigned char bits;
+ struct alc_spec *spec = codec->spec;
- present = snd_hda_codec_read(codec, 0x1b, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- 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)
-{
- /* Looks like the unsol event is incompatible with the standard
- * definition. 4bit tag is placed at 28 bit!
- */
- if ((res >> 28) == 0x01)
- alc880_lg_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.speaker_pins[0] = 0x17;
+ alc_automute_amp(codec);
}
/*
@@ -2793,30 +2852,18 @@ static struct hda_verb alc880_lg_lw_init_verbs[] = {
{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
/* jack sense */
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1},
+ {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
{ }
};
/* toggle speaker-output according to the hp-jack state */
-static void alc880_lg_lw_automute(struct hda_codec *codec)
+static void alc880_lg_lw_init_hook(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 ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, bits);
-}
+ struct alc_spec *spec = codec->spec;
-static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- /* Looks like the unsol event is incompatible with the standard
- * definition. 4bit tag is placed at 28 bit!
- */
- if ((res >> 28) == 0x01)
- alc880_lg_lw_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ alc_automute_amp(codec);
}
static struct snd_kcontrol_new alc880_medion_rim_mixer[] = {
@@ -2863,16 +2910,10 @@ static struct hda_verb alc880_medion_rim_init_verbs[] = {
/* toggle speaker-output according to the hp-jack state */
static void alc880_medion_rim_automute(struct hda_codec *codec)
{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_codec_read(codec, 0x14, 0,
- AC_VERB_GET_PIN_SENSE, 0)
- & AC_PINSENSE_PRESENCE;
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, bits);
- if (present)
+ struct alc_spec *spec = codec->spec;
+ alc_automute_amp(codec);
+ /* toggle EAPD */
+ if (spec->jack_present)
snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
else
snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 2);
@@ -2888,6 +2929,15 @@ static void alc880_medion_rim_unsol_event(struct hda_codec *codec,
alc880_medion_rim_automute(codec);
}
+static void alc880_medion_rim_init_hook(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+
+ spec->autocfg.hp_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[0] = 0x1b;
+ alc880_medion_rim_automute(codec);
+}
+
#ifdef CONFIG_SND_HDA_POWER_SAVE
static struct hda_amp_list alc880_loopbacks[] = {
{ 0x0b, HDA_INPUT, 0 },
@@ -2916,8 +2966,7 @@ static int alc_init(struct hda_codec *codec)
unsigned int i;
alc_fix_pll(codec);
- if (codec->vendor_id == 0x10ec0888)
- alc888_coef_init(codec);
+ alc_auto_init_amp(codec, spec->init_amp);
for (i = 0; i < spec->num_init_verbs; i++)
snd_hda_sequence_write(codec, spec->init_verbs[i]);
@@ -3747,7 +3796,7 @@ static struct alc_config_preset alc880_presets[] = {
.channel_mode = alc880_2_jack_modes,
.input_mux = &alc880_f1734_capture_source,
.unsol_event = alc880_uniwill_p53_unsol_event,
- .init_hook = alc880_uniwill_p53_hp_automute,
+ .init_hook = alc880_uniwill_p53_init_hook,
},
[ALC880_ASUS] = {
.mixers = { alc880_asus_mixer },
@@ -3824,7 +3873,7 @@ static struct alc_config_preset alc880_presets[] = {
.need_dac_fix = 1,
.input_mux = &alc880_capture_source,
.unsol_event = alc880_uniwill_unsol_event,
- .init_hook = alc880_uniwill_automute,
+ .init_hook = alc880_uniwill_init_hook,
},
[ALC880_UNIWILL_P53] = {
.mixers = { alc880_uniwill_p53_mixer },
@@ -3836,7 +3885,7 @@ static struct alc_config_preset alc880_presets[] = {
.channel_mode = alc880_threestack_modes,
.input_mux = &alc880_capture_source,
.unsol_event = alc880_uniwill_p53_unsol_event,
- .init_hook = alc880_uniwill_p53_hp_automute,
+ .init_hook = alc880_uniwill_p53_init_hook,
},
[ALC880_FUJITSU] = {
.mixers = { alc880_fujitsu_mixer },
@@ -3850,7 +3899,7 @@ static struct alc_config_preset alc880_presets[] = {
.channel_mode = alc880_2_jack_modes,
.input_mux = &alc880_capture_source,
.unsol_event = alc880_uniwill_p53_unsol_event,
- .init_hook = alc880_uniwill_p53_hp_automute,
+ .init_hook = alc880_uniwill_p53_init_hook,
},
[ALC880_CLEVO] = {
.mixers = { alc880_three_stack_mixer },
@@ -3875,8 +3924,8 @@ static struct alc_config_preset alc880_presets[] = {
.channel_mode = alc880_lg_ch_modes,
.need_dac_fix = 1,
.input_mux = &alc880_lg_capture_source,
- .unsol_event = alc880_lg_unsol_event,
- .init_hook = alc880_lg_automute,
+ .unsol_event = alc_automute_amp_unsol_event,
+ .init_hook = alc880_lg_init_hook,
#ifdef CONFIG_SND_HDA_POWER_SAVE
.loopbacks = alc880_lg_loopbacks,
#endif
@@ -3891,8 +3940,8 @@ static struct alc_config_preset alc880_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc880_lg_lw_modes),
.channel_mode = alc880_lg_lw_modes,
.input_mux = &alc880_lg_lw_capture_source,
- .unsol_event = alc880_lg_lw_unsol_event,
- .init_hook = alc880_lg_lw_automute,
+ .unsol_event = alc_automute_amp_unsol_event,
+ .init_hook = alc880_lg_lw_init_hook,
},
[ALC880_MEDION_RIM] = {
.mixers = { alc880_medion_rim_mixer },
@@ -3906,7 +3955,7 @@ static struct alc_config_preset alc880_presets[] = {
.channel_mode = alc880_2_jack_modes,
.input_mux = &alc880_medion_rim_capture_source,
.unsol_event = alc880_medion_rim_unsol_event,
- .init_hook = alc880_medion_rim_automute,
+ .init_hook = alc880_medion_rim_init_hook,
},
#ifdef CONFIG_SND_DEBUG
[ALC880_TEST] = {
@@ -4191,7 +4240,6 @@ static void alc880_auto_init_multi_out(struct hda_codec *codec)
struct alc_spec *spec = codec->spec;
int i;
- alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
for (i = 0; i < spec->autocfg.line_outs; i++) {
hda_nid_t nid = spec->autocfg.line_out_pins[i];
int pin_type = get_pin_type(spec->autocfg.line_out_type);
@@ -4296,6 +4344,8 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux[0];
+ alc_ssid_check(codec, 0x15, 0x1b, 0x14);
+
return 1;
}
@@ -5671,7 +5721,6 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec)
struct alc_spec *spec = codec->spec;
hda_nid_t nid;
- alc_subsystem_id(codec, 0x10, 0x15, 0x0f);
nid = spec->autocfg.line_out_pins[0];
if (nid) {
int pin_type = get_pin_type(spec->autocfg.line_out_type);
@@ -5781,6 +5830,8 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux[0];
+ alc_ssid_check(codec, 0x10, 0x15, 0x0f);
+
return 1;
}
@@ -6107,6 +6158,16 @@ static struct hda_input_mux alc882_capture_source = {
{ "CD", 0x4 },
},
};
+
+static struct hda_input_mux mb5_capture_source = {
+ .num_items = 3,
+ .items = {
+ { "Mic", 0x1 },
+ { "Line", 0x2 },
+ { "CD", 0x4 },
+ },
+};
+
/*
* 2ch mode
*/
@@ -6236,6 +6297,20 @@ static struct snd_kcontrol_new alc885_mbp3_mixer[] = {
HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x00, HDA_INPUT),
{ } /* end */
};
+
+static struct snd_kcontrol_new alc885_mb5_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
+ HDA_BIND_MUTE ("Front Playback Switch", 0x0d, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line-Out Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
+ HDA_BIND_MUTE ("Line-Out Playback Switch", 0x0c, 0x02, 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, 0x01, HDA_INPUT),
+ HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line Boost", 0x15, 0x00, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Boost", 0x19, 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),
@@ -6463,6 +6538,38 @@ static struct hda_verb alc882_macpro_init_verbs[] = {
{ }
};
+/* Macbook 5,1 */
+static struct hda_verb alc885_mb5_init_verbs[] = {
+ /* Front 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)},
+ /* LineOut mixer */
+ {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)},
+ /* Front Pin: output 0 (0x0d) */
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x18, AC_VERB_SET_CONNECT_SEL, 0x01},
+ /* HP 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},
+ /* 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 */
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {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)},
+ { }
+};
+
/* Macbook Pro rev3 */
static struct hda_verb alc885_mbp3_init_verbs[] = {
/* Front mixer: unmute input/output amp left and right (volume = 0) */
@@ -6552,45 +6659,23 @@ static struct hda_verb alc885_imac24_init_verbs[] = {
};
/* Toggle speaker-output according to the hp-jack state */
-static void alc885_imac24_automute(struct hda_codec *codec)
+static void alc885_imac24_automute_init_hook(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, 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);
-}
+ struct alc_spec *spec = codec->spec;
-/* Processes unsolicited events. */
-static void alc885_imac24_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- /* Headphone insertion or removal. */
- if ((res >> 26) == ALC880_HP_EVENT)
- alc885_imac24_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[0] = 0x18;
+ spec->autocfg.speaker_pins[1] = 0x1a;
+ alc_automute_amp(codec);
}
-static void alc885_mbp3_automute(struct hda_codec *codec)
+static void alc885_mbp3_init_hook(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);
+ struct alc_spec *spec = codec->spec;
-}
-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);
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ alc_automute_amp(codec);
}
@@ -6615,24 +6700,25 @@ static struct hda_verb alc882_targa_verbs[] = {
/* toggle speaker-output according to the hp-jack state */
static void alc882_targa_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, 0x1b, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+ struct alc_spec *spec = codec->spec;
+ alc_automute_amp(codec);
snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
- present ? 1 : 3);
+ spec->jack_present ? 1 : 3);
+}
+
+static void alc882_targa_init_hook(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+
+ spec->autocfg.hp_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[0] = 0x1b;
+ alc882_targa_automute(codec);
}
static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)
{
- /* Looks like the unsol event is incompatible with the standard
- * definition. 4bit tag is placed at 26 bit!
- */
- if (((res >> 26) == ALC880_HP_EVENT)) {
+ if ((res >> 26) == ALC880_HP_EVENT)
alc882_targa_automute(codec);
- }
}
static struct hda_verb alc882_asus_a7j_verbs[] = {
@@ -6714,7 +6800,7 @@ static void alc885_macpro_init_hook(struct hda_codec *codec)
static void alc885_imac24_init_hook(struct hda_codec *codec)
{
alc885_macpro_init_hook(codec);
- alc885_imac24_automute(codec);
+ alc885_imac24_automute_init_hook(codec);
}
/*
@@ -6807,6 +6893,7 @@ static const char *alc882_models[ALC882_MODEL_LAST] = {
[ALC882_ASUS_A7J] = "asus-a7j",
[ALC882_ASUS_A7M] = "asus-a7m",
[ALC885_MACPRO] = "macpro",
+ [ALC885_MB5] = "mb5",
[ALC885_MBP3] = "mbp3",
[ALC885_IMAC24] = "imac24",
[ALC882_AUTO] = "auto",
@@ -6884,8 +6971,20 @@ static struct alc_config_preset alc882_presets[] = {
.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,
+ .unsol_event = alc_automute_amp_unsol_event,
+ .init_hook = alc885_mbp3_init_hook,
+ },
+ [ALC885_MB5] = {
+ .mixers = { alc885_mb5_mixer },
+ .init_verbs = { alc885_mb5_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 = &mb5_capture_source,
+ .dig_out_nid = ALC882_DIGOUT_NID,
+ .dig_in_nid = ALC882_DIGIN_NID,
},
[ALC885_MACPRO] = {
.mixers = { alc882_macpro_mixer },
@@ -6909,7 +7008,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,
- .unsol_event = alc885_imac24_unsol_event,
+ .unsol_event = alc_automute_amp_unsol_event,
.init_hook = alc885_imac24_init_hook,
},
[ALC882_TARGA] = {
@@ -6926,7 +7025,7 @@ static struct alc_config_preset alc882_presets[] = {
.need_dac_fix = 1,
.input_mux = &alc882_capture_source,
.unsol_event = alc882_targa_unsol_event,
- .init_hook = alc882_targa_automute,
+ .init_hook = alc882_targa_init_hook,
},
[ALC882_ASUS_A7J] = {
.mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer },
@@ -7006,7 +7105,6 @@ static void alc882_auto_init_multi_out(struct hda_codec *codec)
struct alc_spec *spec = codec->spec;
int i;
- alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
for (i = 0; i <= HDA_SIDE; i++) {
hda_nid_t nid = spec->autocfg.line_out_pins[i];
int pin_type = get_pin_type(spec->autocfg.line_out_type);
@@ -7193,6 +7291,9 @@ static int patch_alc882(struct hda_codec *codec)
case 0x106b3800: /* MacbookPro4,1 - latter revision */
board_config = ALC885_MBP3;
break;
+ case 0x106b3f00: /* Macbook 5,1 */
+ board_config = ALC885_MB5;
+ break;
default:
/* ALC889A is handled better as ALC888-compatible */
if (codec->revision_id == 0x100101 ||
@@ -7774,8 +7875,6 @@ static struct snd_kcontrol_new alc888_lenovo_sky_mixer[] = {
HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("iSpeaker Playback Switch", 0x1a, 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),
@@ -7924,16 +8023,14 @@ static struct hda_verb alc883_init_verbs[] = {
};
/* toggle speaker-output according to the hp-jack state */
-static void alc883_mitac_hp_automute(struct hda_codec *codec)
+static void alc883_mitac_init_hook(struct hda_codec *codec)
{
- unsigned int present;
+ struct alc_spec *spec = codec->spec;
- 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, 0x17, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[1] = 0x17;
+ alc_automute_amp(codec);
}
/* auto-toggle front mic */
@@ -7950,25 +8047,6 @@ static void alc883_mitac_mic_automute(struct hda_codec *codec)
}
*/
-static void alc883_mitac_automute(struct hda_codec *codec)
-{
- alc883_mitac_hp_automute(codec);
- /* alc883_mitac_mic_automute(codec); */
-}
-
-static void alc883_mitac_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc883_mitac_hp_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- /* alc883_mitac_mic_automute(codec); */
- break;
- }
-}
-
static struct hda_verb alc883_mitac_verbs[] = {
/* HP */
{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
@@ -8086,29 +8164,15 @@ static struct hda_verb alc888_6st_dell_verbs[] = {
{ }
};
-static void alc888_3st_hp_front_automute(struct hda_codec *codec)
+static void alc888_3st_hp_init_hook(struct hda_codec *codec)
{
- unsigned int present, bits;
-
- present = snd_hda_codec_read(codec, 0x1b, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x18, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, bits);
-}
+ struct alc_spec *spec = codec->spec;
-static void alc888_3st_hp_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc888_3st_hp_front_automute(codec);
- break;
- }
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[1] = 0x16;
+ spec->autocfg.speaker_pins[2] = 0x18;
+ alc_automute_amp(codec);
}
static struct hda_verb alc888_3st_hp_verbs[] = {
@@ -8205,56 +8269,18 @@ static struct hda_verb alc883_medion_md2_verbs[] = {
};
/* toggle speaker-output according to the hp-jack state */
-static void alc883_medion_md2_automute(struct hda_codec *codec)
+static void alc883_medion_md2_init_hook(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);
-}
-
-static void alc883_medion_md2_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) == ALC880_HP_EVENT)
- alc883_medion_md2_automute(codec);
-}
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc883_tagra_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_codec_read(codec, 0x14, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- 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);
-}
+ struct alc_spec *spec = codec->spec;
-static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- if ((res >> 26) == ALC880_HP_EVENT)
- alc883_tagra_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[0] = 0x15;
+ alc_automute_amp(codec);
}
/* toggle speaker-output according to the hp-jack state */
-static void alc883_clevo_m720_hp_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_PIN_SENSE, 0)
- & AC_PINSENSE_PRESENCE;
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, bits);
-}
+#define alc883_tagra_init_hook alc882_targa_init_hook
+#define alc883_tagra_unsol_event alc882_targa_unsol_event
static void alc883_clevo_m720_mic_automute(struct hda_codec *codec)
{
@@ -8266,9 +8292,13 @@ static void alc883_clevo_m720_mic_automute(struct hda_codec *codec)
HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
}
-static void alc883_clevo_m720_automute(struct hda_codec *codec)
+static void alc883_clevo_m720_init_hook(struct hda_codec *codec)
{
- alc883_clevo_m720_hp_automute(codec);
+ struct alc_spec *spec = codec->spec;
+
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ alc_automute_amp(codec);
alc883_clevo_m720_mic_automute(codec);
}
@@ -8276,52 +8306,32 @@ static void alc883_clevo_m720_unsol_event(struct hda_codec *codec,
unsigned int res)
{
switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc883_clevo_m720_hp_automute(codec);
- break;
case ALC880_MIC_EVENT:
alc883_clevo_m720_mic_automute(codec);
break;
+ default:
+ alc_automute_amp_unsol_event(codec, res);
+ break;
}
}
/* toggle speaker-output according to the hp-jack state */
-static void alc883_2ch_fujitsu_pi2515_automute(struct hda_codec *codec)
+static void alc883_2ch_fujitsu_pi2515_init_hook(struct hda_codec *codec)
{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_codec_read(codec, 0x14, 0, AC_VERB_GET_PIN_SENSE, 0)
- & AC_PINSENSE_PRESENCE;
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, bits);
-}
+ struct alc_spec *spec = codec->spec;
-static void alc883_2ch_fujitsu_pi2515_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) == ALC880_HP_EVENT)
- alc883_2ch_fujitsu_pi2515_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[0] = 0x15;
+ alc_automute_amp(codec);
}
-static void alc883_haier_w66_automute(struct hda_codec *codec)
+static void alc883_haier_w66_init_hook(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);
-}
+ struct alc_spec *spec = codec->spec;
-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);
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ alc_automute_amp(codec);
}
static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
@@ -8360,23 +8370,14 @@ static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec,
}
/* toggle speaker-output according to the hp-jack state */
-static void alc883_acer_aspire_automute(struct hda_codec *codec)
+static void alc883_acer_aspire_init_hook(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);
-}
+ struct alc_spec *spec = codec->spec;
-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);
+ spec->autocfg.hp_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[1] = 0x16;
+ alc_automute_amp(codec);
}
static struct hda_verb alc883_acer_eapd_verbs[] = {
@@ -8397,75 +8398,29 @@ static struct hda_verb alc883_acer_eapd_verbs[] = {
{ }
};
-static void alc888_6st_dell_front_automute(struct hda_codec *codec)
+static void alc888_6st_dell_init_hook(struct hda_codec *codec)
{
- unsigned int present;
+ struct alc_spec *spec = codec->spec;
- present = snd_hda_codec_read(codec, 0x1b, 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 ? HDA_AMP_MUTE : 0);
- snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
- snd_hda_codec_amp_stereo(codec, 0x17, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[1] = 0x15;
+ spec->autocfg.speaker_pins[2] = 0x16;
+ spec->autocfg.speaker_pins[3] = 0x17;
+ alc_automute_amp(codec);
}
-static void alc888_6st_dell_unsol_event(struct hda_codec *codec,
- unsigned int res)
+static void alc888_lenovo_sky_init_hook(struct hda_codec *codec)
{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- /* printk(KERN_DEBUG "hp_event\n"); */
- alc888_6st_dell_front_automute(codec);
- break;
- }
-}
-
-static void alc888_lenovo_sky_front_automute(struct hda_codec *codec)
-{
- unsigned int mute;
- unsigned int 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_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, HDA_AMP_MUTE);
- snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, HDA_AMP_MUTE);
- snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, HDA_AMP_MUTE);
- snd_hda_codec_amp_stereo(codec, 0x17, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, HDA_AMP_MUTE);
- snd_hda_codec_amp_stereo(codec, 0x1a, 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_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
- snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
- snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
- snd_hda_codec_amp_stereo(codec, 0x17, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
- snd_hda_codec_amp_stereo(codec, 0x1a, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
- }
-}
+ struct alc_spec *spec = codec->spec;
-static void alc883_lenovo_sky_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) == ALC880_HP_EVENT)
- alc888_lenovo_sky_front_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[1] = 0x15;
+ spec->autocfg.speaker_pins[2] = 0x16;
+ spec->autocfg.speaker_pins[3] = 0x17;
+ spec->autocfg.speaker_pins[4] = 0x1a;
+ alc_automute_amp(codec);
}
/*
@@ -8553,39 +8508,33 @@ static void alc883_nb_mic_automute(struct hda_codec *codec)
0x7000 | (0x01 << 8) | (present ? 0x80 : 0));
}
-static void alc883_M90V_speaker_automute(struct hda_codec *codec)
+static void alc883_M90V_init_hook(struct hda_codec *codec)
{
- unsigned int present;
- unsigned char bits;
+ struct alc_spec *spec = codec->spec;
- present = snd_hda_codec_read(codec, 0x1b, 0,
- AC_VERB_GET_PIN_SENSE, 0)
- & AC_PINSENSE_PRESENCE;
- bits = present ? 0 : PIN_OUT;
- snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- bits);
- snd_hda_codec_write(codec, 0x15, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- bits);
- snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- bits);
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[1] = 0x15;
+ spec->autocfg.speaker_pins[2] = 0x16;
+ alc_automute_pin(codec);
}
static void alc883_mode2_unsol_event(struct hda_codec *codec,
unsigned int res)
{
switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc883_M90V_speaker_automute(codec);
- break;
case ALC880_MIC_EVENT:
alc883_nb_mic_automute(codec);
break;
+ default:
+ alc_sku_unsol_event(codec, res);
+ break;
}
}
static void alc883_mode2_inithook(struct hda_codec *codec)
{
- alc883_M90V_speaker_automute(codec);
+ alc883_M90V_init_hook(codec);
alc883_nb_mic_automute(codec);
}
@@ -8602,32 +8551,13 @@ static struct hda_verb alc888_asus_eee1601_verbs[] = {
{ } /* end */
};
-static void alc883_eee1601_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_codec_read(codec, 0x14, 0,
- AC_VERB_GET_PIN_SENSE, 0)
- & AC_PINSENSE_PRESENCE;
- bits = present ? 0 : PIN_OUT;
- snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- bits);
-}
-
-static void alc883_eee1601_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc883_eee1601_speaker_automute(codec);
- break;
- }
-}
-
static void alc883_eee1601_inithook(struct hda_codec *codec)
{
- alc883_eee1601_speaker_automute(codec);
+ struct alc_spec *spec = codec->spec;
+
+ spec->autocfg.hp_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[0] = 0x1b;
+ alc_automute_pin(codec);
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -8742,10 +8672,9 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC883_LAPTOP_EAPD),
SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
- SND_PCI_QUIRK(0x1734, 0x1107, "FSC AMILO Xi2550",
+ SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1100, "FSC AMILO Xi/Pi25xx",
ALC883_FUJITSU_PI2515),
- SND_PCI_QUIRK(0x1734, 0x1108, "Fujitsu AMILO Pi2515", ALC883_FUJITSU_PI2515),
- SND_PCI_QUIRK(0x1734, 0x113d, "Fujitsu AMILO Xa3530",
+ SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1130, "Fujitsu AMILO Xa35xx",
ALC888_FUJITSU_XA3530),
SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch),
SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763),
@@ -8841,7 +8770,7 @@ static struct alc_config_preset alc883_presets[] = {
.need_dac_fix = 1,
.input_mux = &alc883_capture_source,
.unsol_event = alc883_tagra_unsol_event,
- .init_hook = alc883_tagra_automute,
+ .init_hook = alc883_tagra_init_hook,
},
[ALC883_TARGA_2ch_DIG] = {
.mixers = { alc883_tagra_2ch_mixer},
@@ -8855,7 +8784,7 @@ static struct alc_config_preset alc883_presets[] = {
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_capture_source,
.unsol_event = alc883_tagra_unsol_event,
- .init_hook = alc883_tagra_automute,
+ .init_hook = alc883_tagra_init_hook,
},
[ALC883_ACER] = {
.mixers = { alc883_base_mixer },
@@ -8880,8 +8809,8 @@ static struct alc_config_preset alc883_presets[] = {
.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,
+ .unsol_event = alc_automute_amp_unsol_event,
+ .init_hook = alc883_acer_aspire_init_hook,
},
[ALC888_ACER_ASPIRE_4930G] = {
.mixers = { alc888_base_mixer,
@@ -8900,8 +8829,8 @@ static struct alc_config_preset alc883_presets[] = {
.num_mux_defs =
ARRAY_SIZE(alc888_2_capture_sources),
.input_mux = alc888_2_capture_sources,
- .unsol_event = alc888_acer_aspire_4930g_unsol_event,
- .init_hook = alc888_acer_aspire_4930g_automute,
+ .unsol_event = alc_automute_amp_unsol_event,
+ .init_hook = alc888_acer_aspire_4930g_init_hook,
},
[ALC883_MEDION] = {
.mixers = { alc883_fivestack_mixer,
@@ -8925,8 +8854,8 @@ static struct alc_config_preset alc883_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_capture_source,
- .unsol_event = alc883_medion_md2_unsol_event,
- .init_hook = alc883_medion_md2_automute,
+ .unsol_event = alc_automute_amp_unsol_event,
+ .init_hook = alc883_medion_md2_init_hook,
},
[ALC883_LAPTOP_EAPD] = {
.mixers = { alc883_base_mixer },
@@ -8947,7 +8876,7 @@ static struct alc_config_preset alc883_presets[] = {
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_capture_source,
.unsol_event = alc883_clevo_m720_unsol_event,
- .init_hook = alc883_clevo_m720_automute,
+ .init_hook = alc883_clevo_m720_init_hook,
},
[ALC883_LENOVO_101E_2ch] = {
.mixers = { alc883_lenovo_101e_2ch_mixer},
@@ -8971,8 +8900,8 @@ static struct alc_config_preset alc883_presets[] = {
.channel_mode = alc883_3ST_2ch_modes,
.need_dac_fix = 1,
.input_mux = &alc883_lenovo_nb0763_capture_source,
- .unsol_event = alc883_medion_md2_unsol_event,
- .init_hook = alc883_medion_md2_automute,
+ .unsol_event = alc_automute_amp_unsol_event,
+ .init_hook = alc883_medion_md2_init_hook,
},
[ALC888_LENOVO_MS7195_DIG] = {
.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
@@ -8996,8 +8925,8 @@ static struct alc_config_preset alc883_presets[] = {
.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,
+ .unsol_event = alc_automute_amp_unsol_event,
+ .init_hook = alc883_haier_w66_init_hook,
},
[ALC888_3ST_HP] = {
.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
@@ -9008,8 +8937,8 @@ static struct alc_config_preset alc883_presets[] = {
.channel_mode = alc888_3st_hp_modes,
.need_dac_fix = 1,
.input_mux = &alc883_capture_source,
- .unsol_event = alc888_3st_hp_unsol_event,
- .init_hook = alc888_3st_hp_front_automute,
+ .unsol_event = alc_automute_amp_unsol_event,
+ .init_hook = alc888_3st_hp_init_hook,
},
[ALC888_6ST_DELL] = {
.mixers = { alc883_base_mixer, alc883_chmode_mixer },
@@ -9021,8 +8950,8 @@ static struct alc_config_preset alc883_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
.channel_mode = alc883_sixstack_modes,
.input_mux = &alc883_capture_source,
- .unsol_event = alc888_6st_dell_unsol_event,
- .init_hook = alc888_6st_dell_front_automute,
+ .unsol_event = alc_automute_amp_unsol_event,
+ .init_hook = alc888_6st_dell_init_hook,
},
[ALC883_MITAC] = {
.mixers = { alc883_mitac_mixer },
@@ -9032,8 +8961,8 @@ static struct alc_config_preset alc883_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_capture_source,
- .unsol_event = alc883_mitac_unsol_event,
- .init_hook = alc883_mitac_automute,
+ .unsol_event = alc_automute_amp_unsol_event,
+ .init_hook = alc883_mitac_init_hook,
},
[ALC883_FUJITSU_PI2515] = {
.mixers = { alc883_2ch_fujitsu_pi2515_mixer },
@@ -9045,8 +8974,8 @@ static struct alc_config_preset alc883_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_fujitsu_pi2515_capture_source,
- .unsol_event = alc883_2ch_fujitsu_pi2515_unsol_event,
- .init_hook = alc883_2ch_fujitsu_pi2515_automute,
+ .unsol_event = alc_automute_amp_unsol_event,
+ .init_hook = alc883_2ch_fujitsu_pi2515_init_hook,
},
[ALC888_FUJITSU_XA3530] = {
.mixers = { alc888_base_mixer, alc883_chmode_mixer },
@@ -9063,8 +8992,8 @@ static struct alc_config_preset alc883_presets[] = {
.num_mux_defs =
ARRAY_SIZE(alc888_2_capture_sources),
.input_mux = alc888_2_capture_sources,
- .unsol_event = alc888_fujitsu_xa3530_unsol_event,
- .init_hook = alc888_fujitsu_xa3530_automute,
+ .unsol_event = alc_automute_amp_unsol_event,
+ .init_hook = alc888_fujitsu_xa3530_init_hook,
},
[ALC888_LENOVO_SKY] = {
.mixers = { alc888_lenovo_sky_mixer, alc883_chmode_mixer },
@@ -9076,8 +9005,8 @@ static struct alc_config_preset alc883_presets[] = {
.channel_mode = alc883_sixstack_modes,
.need_dac_fix = 1,
.input_mux = &alc883_lenovo_sky_capture_source,
- .unsol_event = alc883_lenovo_sky_unsol_event,
- .init_hook = alc888_lenovo_sky_front_automute,
+ .unsol_event = alc_automute_amp_unsol_event,
+ .init_hook = alc888_lenovo_sky_init_hook,
},
[ALC888_ASUS_M90V] = {
.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
@@ -9105,7 +9034,7 @@ static struct alc_config_preset alc883_presets[] = {
.channel_mode = alc883_3ST_2ch_modes,
.need_dac_fix = 1,
.input_mux = &alc883_asus_eee1601_capture_source,
- .unsol_event = alc883_eee1601_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.init_hook = alc883_eee1601_inithook,
},
[ALC1200_ASUS_P5Q] = {
@@ -9148,7 +9077,6 @@ static void alc883_auto_init_multi_out(struct hda_codec *codec)
struct alc_spec *spec = codec->spec;
int i;
- alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
for (i = 0; i <= HDA_SIDE; i++) {
hda_nid_t nid = spec->autocfg.line_out_pins[i];
int pin_type = get_pin_type(spec->autocfg.line_out_type);
@@ -9311,6 +9239,7 @@ static int patch_alc883(struct hda_codec *codec)
if (!spec->capsrc_nids)
spec->capsrc_nids = alc883_capsrc_nids;
spec->capture_style = CAPT_MIX; /* matrix-style capture */
+ spec->init_amp = ALC_INIT_DEFAULT; /* always initialize */
break;
case 0x10ec0889:
spec->stream_name_analog = "ALC889 Analog";
@@ -9406,24 +9335,6 @@ static struct snd_kcontrol_new alc262_base_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc262_hippo1_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x14, 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_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, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
- /*HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),*/
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- { } /* end */
-};
-
/* update HP, line and mono-out pins according to the master switch */
static void alc262_hp_master_update(struct hda_codec *codec)
{
@@ -9479,14 +9390,7 @@ static void alc262_hp_wildwest_unsol_event(struct hda_codec *codec,
alc262_hp_wildwest_automute(codec);
}
-static int alc262_hp_master_sw_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct alc_spec *spec = codec->spec;
- *ucontrol->value.integer.value = spec->master_sw;
- return 0;
-}
+#define alc262_hp_master_sw_get alc260_hp_master_sw_get
static int alc262_hp_master_sw_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -9502,14 +9406,17 @@ static int alc262_hp_master_sw_put(struct snd_kcontrol *kcontrol,
return 1;
}
+#define ALC262_HP_MASTER_SWITCH \
+ { \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = "Master Playback Switch", \
+ .info = snd_ctl_boolean_mono_info, \
+ .get = alc262_hp_master_sw_get, \
+ .put = alc262_hp_master_sw_put, \
+ }
+
static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Switch",
- .info = snd_ctl_boolean_mono_info,
- .get = alc262_hp_master_sw_get,
- .put = alc262_hp_master_sw_put,
- },
+ ALC262_HP_MASTER_SWITCH,
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
@@ -9533,13 +9440,7 @@ static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
};
static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Switch",
- .info = snd_ctl_boolean_mono_info,
- .get = alc262_hp_master_sw_get,
- .put = alc262_hp_master_sw_put,
- },
+ ALC262_HP_MASTER_SWITCH,
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -9566,32 +9467,13 @@ static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = {
};
/* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc262_hp_t5735_automute(struct hda_codec *codec, int force)
+static void alc262_hp_t5735_init_hook(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- if (force || !spec->sense_updated) {
- unsigned int present;
- present = snd_hda_codec_read(codec, 0x15, 0,
- AC_VERB_GET_PIN_SENSE, 0);
- spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;
- spec->sense_updated = 1;
- }
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0, HDA_AMP_MUTE,
- spec->jack_present ? HDA_AMP_MUTE : 0);
-}
-
-static void alc262_hp_t5735_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) != ALC880_HP_EVENT)
- return;
- alc262_hp_t5735_automute(codec, 1);
-}
-
-static void alc262_hp_t5735_init_hook(struct hda_codec *codec)
-{
- alc262_hp_t5735_automute(codec, 1);
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x0c; /* HACK: not actually a pin */
+ alc_automute_amp(codec);
}
static struct snd_kcontrol_new alc262_hp_t5735_mixer[] = {
@@ -9644,46 +9526,132 @@ static struct hda_input_mux alc262_hp_rp5700_capture_source = {
},
};
-/* 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)
+/* bind hp and internal speaker mute (with plug check) as master switch */
+static void alc262_hippo_master_update(struct hda_codec *codec)
{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int change;
+ struct alc_spec *spec = codec->spec;
+ hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
+ hda_nid_t line_nid = spec->autocfg.line_out_pins[0];
+ hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0];
+ unsigned int mute;
- /* 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,
+ /* HP */
+ mute = spec->master_sw ? 0 : HDA_AMP_MUTE;
+ snd_hda_codec_amp_stereo(codec, hp_nid, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, mute);
+ /* mute internal speaker per jack sense */
+ if (spec->jack_present)
+ mute = HDA_AMP_MUTE;
+ if (line_nid)
+ snd_hda_codec_amp_stereo(codec, line_nid, HDA_OUTPUT, 0,
HDA_AMP_MUTE, mute);
+ if (speaker_nid && speaker_nid != line_nid)
+ snd_hda_codec_amp_stereo(codec, speaker_nid, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, mute);
+}
+
+#define alc262_hippo_master_sw_get alc262_hp_master_sw_get
+
+static int alc262_hippo_master_sw_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+ int val = !!*ucontrol->value.integer.value;
+
+ if (val == spec->master_sw)
+ return 0;
+ spec->master_sw = val;
+ alc262_hippo_master_update(codec);
+ return 1;
+}
+
+#define ALC262_HIPPO_MASTER_SWITCH \
+ { \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = "Master Playback Switch", \
+ .info = snd_ctl_boolean_mono_info, \
+ .get = alc262_hippo_master_sw_get, \
+ .put = alc262_hippo_master_sw_put, \
}
- return change;
+
+static struct snd_kcontrol_new alc262_hippo_mixer[] = {
+ ALC262_HIPPO_MASTER_SWITCH,
+ HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 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_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, 0x01, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+ HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+ { } /* end */
+};
+
+static struct snd_kcontrol_new alc262_hippo1_mixer[] = {
+ HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ ALC262_HIPPO_MASTER_SWITCH,
+ 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_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, 0x01, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+ HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
+ { } /* end */
+};
+
+/* mute/unmute internal speaker according to the hp jack and mute state */
+static void alc262_hippo_automute(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
+ unsigned int present;
+
+ /* 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;
+ alc262_hippo_master_update(codec);
+}
+
+static void alc262_hippo_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+ if ((res >> 26) != ALC880_HP_EVENT)
+ return;
+ alc262_hippo_automute(codec);
+}
+
+static void alc262_hippo_init_hook(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ alc262_hippo_automute(codec);
+}
+
+static void alc262_hippo1_init_hook(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ alc262_hippo_automute(codec);
}
+
static struct snd_kcontrol_new alc262_sony_mixer[] = {
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),
- },
+ ALC262_HIPPO_MASTER_SWITCH,
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),
@@ -9692,8 +9660,8 @@ static struct snd_kcontrol_new alc262_sony_mixer[] = {
};
static struct snd_kcontrol_new alc262_benq_t31_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ ALC262_HIPPO_MASTER_SWITCH,
HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
@@ -9734,34 +9702,15 @@ static struct hda_verb alc262_tyan_verbs[] = {
};
/* unsolicited event for HP jack sensing */
-static void alc262_tyan_automute(struct hda_codec *codec)
+static void alc262_tyan_init_hook(struct hda_codec *codec)
{
- unsigned int mute;
- unsigned int present;
+ struct alc_spec *spec = codec->spec;
- 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 line output on ATX panel */
- snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, HDA_AMP_MUTE);
- } else {
- /* unmute line output if necessary */
- mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
- snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
- }
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.speaker_pins[0] = 0x15;
+ alc_automute_amp(codec);
}
-static void alc262_tyan_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) != ALC880_HP_EVENT)
- return;
- alc262_tyan_automute(codec);
-}
#define alc262_capture_mixer alc882_capture_mixer
#define alc262_capture_alt_mixer alc882_capture_alt_mixer
@@ -9916,99 +9865,25 @@ static void alc262_dmic_automute(struct hda_codec *codec)
AC_VERB_SET_CONNECT_SEL, present ? 0x0 : 0x09);
}
-/* toggle speaker-output according to the hp-jack state */
-static void alc262_toshiba_s06_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_codec_read(codec, 0x15, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0 : PIN_OUT;
- snd_hda_codec_write(codec, 0x14, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, bits);
-}
-
-
/* unsolicited event for HP jack sensing */
static void alc262_toshiba_s06_unsol_event(struct hda_codec *codec,
unsigned int res)
{
- if ((res >> 26) == ALC880_HP_EVENT)
- alc262_toshiba_s06_speaker_automute(codec);
if ((res >> 26) == ALC880_MIC_EVENT)
alc262_dmic_automute(codec);
-
+ else
+ alc_sku_unsol_event(codec, res);
}
static void alc262_toshiba_s06_init_hook(struct hda_codec *codec)
{
- alc262_toshiba_s06_speaker_automute(codec);
- alc262_dmic_automute(codec);
-}
-
-/* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc262_hippo_automute(struct hda_codec *codec)
-{
struct alc_spec *spec = codec->spec;
- unsigned int mute;
- 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;
- if (spec->jack_present) {
- /* mute internal speaker */
- 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_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
- }
-}
-
-/* unsolicited event for HP jack sensing */
-static void alc262_hippo_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) != ALC880_HP_EVENT)
- return;
- alc262_hippo_automute(codec);
-}
-static void alc262_hippo1_automute(struct hda_codec *codec)
-{
- unsigned int mute;
- unsigned int 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_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_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
- }
-}
-
-/* unsolicited event for HP jack sensing */
-static void alc262_hippo1_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) != ALC880_HP_EVENT)
- return;
- alc262_hippo1_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ alc_automute_pin(codec);
+ alc262_dmic_automute(codec);
}
/*
@@ -10278,14 +10153,7 @@ static struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
static struct snd_kcontrol_new alc262_toshiba_rx1_mixer[] = {
HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_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 = alc262_sony_master_sw_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
- },
+ ALC262_HIPPO_MASTER_SWITCH,
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),
@@ -10836,6 +10704,8 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
if (err < 0)
return err;
+ alc_ssid_check(codec, 0x15, 0x14, 0x1b);
+
return 1;
}
@@ -10938,7 +10808,7 @@ static struct alc_config_preset alc262_presets[] = {
.input_mux = &alc262_capture_source,
},
[ALC262_HIPPO] = {
- .mixers = { alc262_base_mixer },
+ .mixers = { alc262_hippo_mixer },
.init_verbs = { alc262_init_verbs, alc262_hippo_unsol_verbs},
.num_dacs = ARRAY_SIZE(alc262_dac_nids),
.dac_nids = alc262_dac_nids,
@@ -10948,7 +10818,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,
+ .init_hook = alc262_hippo_init_hook,
},
[ALC262_HIPPO_1] = {
.mixers = { alc262_hippo1_mixer },
@@ -10960,8 +10830,8 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
- .unsol_event = alc262_hippo1_unsol_event,
- .init_hook = alc262_hippo1_automute,
+ .unsol_event = alc262_hippo_unsol_event,
+ .init_hook = alc262_hippo1_init_hook,
},
[ALC262_FUJITSU] = {
.mixers = { alc262_fujitsu_mixer },
@@ -11023,7 +10893,7 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
- .unsol_event = alc262_hp_t5735_unsol_event,
+ .unsol_event = alc_automute_amp_unsol_event,
.init_hook = alc262_hp_t5735_init_hook,
},
[ALC262_HP_RP5700] = {
@@ -11055,7 +10925,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,
+ .init_hook = alc262_hippo_init_hook,
},
[ALC262_BENQ_T31] = {
.mixers = { alc262_benq_t31_mixer },
@@ -11067,7 +10937,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,
+ .init_hook = alc262_hippo_init_hook,
},
[ALC262_ULTRA] = {
.mixers = { alc262_ultra_mixer },
@@ -11132,7 +11002,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,
+ .init_hook = alc262_hippo_init_hook,
},
[ALC262_TYAN] = {
.mixers = { alc262_tyan_mixer },
@@ -11144,8 +11014,8 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
- .unsol_event = alc262_tyan_unsol_event,
- .init_hook = alc262_tyan_automute,
+ .unsol_event = alc_automute_amp_unsol_event,
+ .init_hook = alc262_tyan_init_hook,
},
};
@@ -11289,6 +11159,17 @@ static struct snd_kcontrol_new alc268_base_mixer[] = {
{ }
};
+static struct snd_kcontrol_new alc268_toshiba_mixer[] = {
+ /* output mixer control */
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
+ ALC262_HIPPO_MASTER_SWITCH,
+ 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),
+ { }
+};
+
/* bind Beep switches of both NID 0x0f and 0x10 */
static struct hda_bind_ctls alc268_bind_beep_sw = {
.ops = &snd_hda_bind_sw,
@@ -11312,8 +11193,6 @@ static struct hda_verb alc268_eapd_verbs[] = {
};
/* 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 */
@@ -11449,13 +11328,8 @@ static struct hda_verb alc268_acer_verbs[] = {
};
/* 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);
-}
+#define alc268_toshiba_unsol_event alc262_hippo_unsol_event
+#define alc268_toshiba_init_hook alc262_hippo_init_hook
static void alc268_acer_unsol_event(struct hda_codec *codec,
unsigned int res)
@@ -11530,30 +11404,15 @@ static struct hda_verb alc268_dell_verbs[] = {
};
/* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc268_dell_automute(struct hda_codec *codec)
+static void alc268_dell_init_hook(struct hda_codec *codec)
{
- unsigned int present;
- unsigned int mute;
-
- present = snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_PIN_SENSE, 0);
- if (present & 0x80000000)
- 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);
-}
+ struct alc_spec *spec = codec->spec;
-static void alc268_dell_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) != ALC880_HP_EVENT)
- return;
- alc268_dell_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ alc_automute_pin(codec);
}
-#define alc268_dell_init_hook alc268_dell_automute
-
static struct snd_kcontrol_new alc267_quanta_il1_mixer[] = {
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x2, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
@@ -11572,16 +11431,6 @@ static struct hda_verb alc267_quanta_il1_verbs[] = {
{ }
};
-static void alc267_quanta_il1_hp_automute(struct hda_codec *codec)
-{
- unsigned int present;
-
- present = snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_PIN_SENSE, 0)
- & AC_PINSENSE_PRESENCE;
- snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- present ? 0 : PIN_OUT);
-}
-
static void alc267_quanta_il1_mic_automute(struct hda_codec *codec)
{
unsigned int present;
@@ -11593,9 +11442,13 @@ static void alc267_quanta_il1_mic_automute(struct hda_codec *codec)
present ? 0x00 : 0x01);
}
-static void alc267_quanta_il1_automute(struct hda_codec *codec)
+static void alc267_quanta_il1_init_hook(struct hda_codec *codec)
{
- alc267_quanta_il1_hp_automute(codec);
+ struct alc_spec *spec = codec->spec;
+
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ alc_automute_pin(codec);
alc267_quanta_il1_mic_automute(codec);
}
@@ -11603,12 +11456,12 @@ static void alc267_quanta_il1_unsol_event(struct hda_codec *codec,
unsigned int res)
{
switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc267_quanta_il1_hp_automute(codec);
- break;
case ALC880_MIC_EVENT:
alc267_quanta_il1_mic_automute(codec);
break;
+ default:
+ alc_sku_unsol_event(codec, res);
+ break;
}
}
@@ -12082,7 +11935,7 @@ static struct alc_config_preset alc268_presets[] = {
.channel_mode = alc268_modes,
.input_mux = &alc268_capture_source,
.unsol_event = alc267_quanta_il1_unsol_event,
- .init_hook = alc267_quanta_il1_automute,
+ .init_hook = alc267_quanta_il1_init_hook,
},
[ALC268_3ST] = {
.mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
@@ -12100,7 +11953,7 @@ static struct alc_config_preset alc268_presets[] = {
.input_mux = &alc268_capture_source,
},
[ALC268_TOSHIBA] = {
- .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
+ .mixers = { alc268_toshiba_mixer, alc268_capture_alt_mixer,
alc268_beep_mixer },
.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
alc268_toshiba_verbs },
@@ -12114,7 +11967,7 @@ static struct alc_config_preset alc268_presets[] = {
.channel_mode = alc268_modes,
.input_mux = &alc268_capture_source,
.unsol_event = alc268_toshiba_unsol_event,
- .init_hook = alc268_toshiba_automute,
+ .init_hook = alc268_toshiba_init_hook,
},
[ALC268_ACER] = {
.mixers = { alc268_acer_mixer, alc268_capture_alt_mixer,
@@ -12177,7 +12030,7 @@ static struct alc_config_preset alc268_presets[] = {
.hp_nid = 0x02,
.num_channel_mode = ARRAY_SIZE(alc268_modes),
.channel_mode = alc268_modes,
- .unsol_event = alc268_dell_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.init_hook = alc268_dell_init_hook,
.input_mux = &alc268_capture_source,
},
@@ -12197,7 +12050,7 @@ static struct alc_config_preset alc268_presets[] = {
.channel_mode = alc268_modes,
.input_mux = &alc268_capture_source,
.unsol_event = alc268_toshiba_unsol_event,
- .init_hook = alc268_toshiba_automute
+ .init_hook = alc268_toshiba_init_hook
},
#ifdef CONFIG_SND_DEBUG
[ALC268_TEST] = {
@@ -12977,10 +12830,17 @@ static struct snd_pci_quirk alc269_cfg_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1),
SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
ALC269_ASUS_EEEPC_P703),
+ SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_ASUS_EEEPC_P703),
+ SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_ASUS_EEEPC_P703),
+ SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_ASUS_EEEPC_P703),
+ SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_ASUS_EEEPC_P703),
+ SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_ASUS_EEEPC_P703),
+ SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_ASUS_EEEPC_P703),
SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901",
ALC269_ASUS_EEEPC_P901),
SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101",
ALC269_ASUS_EEEPC_P901),
+ SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_ASUS_EEEPC_P901),
SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU),
SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK),
{}
@@ -13912,7 +13772,6 @@ static void alc861_auto_init_multi_out(struct hda_codec *codec)
struct alc_spec *spec = codec->spec;
int i;
- alc_subsystem_id(codec, 0x0e, 0x0f, 0x0b);
for (i = 0; i < spec->autocfg.line_outs; i++) {
hda_nid_t nid = spec->autocfg.line_out_pins[i];
int pin_type = get_pin_type(spec->autocfg.line_out_type);
@@ -13995,6 +13854,8 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
set_capture_mixer(spec);
+ alc_ssid_check(codec, 0x0e, 0x0f, 0x0b);
+
return 1;
}
@@ -14603,19 +14464,6 @@ static struct hda_verb alc861vd_lenovo_unsol_verbs[] = {
{}
};
-/* toggle speaker-output according to the hp-jack state */
-static void alc861vd_lenovo_hp_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 ? 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)
{
unsigned int present;
@@ -14628,9 +14476,13 @@ static void alc861vd_lenovo_mic_automute(struct hda_codec *codec)
HDA_AMP_MUTE, bits);
}
-static void alc861vd_lenovo_automute(struct hda_codec *codec)
+static void alc861vd_lenovo_init_hook(struct hda_codec *codec)
{
- alc861vd_lenovo_hp_automute(codec);
+ struct alc_spec *spec = codec->spec;
+
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ alc_automute_amp(codec);
alc861vd_lenovo_mic_automute(codec);
}
@@ -14638,12 +14490,12 @@ static void alc861vd_lenovo_unsol_event(struct hda_codec *codec,
unsigned int res)
{
switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc861vd_lenovo_hp_automute(codec);
- break;
case ALC880_MIC_EVENT:
alc861vd_lenovo_mic_automute(codec);
break;
+ default:
+ alc_automute_amp_unsol_event(codec, res);
+ break;
}
}
@@ -14693,20 +14545,13 @@ static struct hda_verb alc861vd_dallas_verbs[] = {
};
/* toggle speaker-output according to the hp-jack state */
-static void alc861vd_dallas_automute(struct hda_codec *codec)
+static void alc861vd_dallas_init_hook(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);
-}
+ struct alc_spec *spec = codec->spec;
-static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- if ((res >> 26) == ALC880_HP_EVENT)
- alc861vd_dallas_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ alc_automute_amp(codec);
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -14820,7 +14665,7 @@ static struct alc_config_preset alc861vd_presets[] = {
.channel_mode = alc861vd_3stack_2ch_modes,
.input_mux = &alc861vd_capture_source,
.unsol_event = alc861vd_lenovo_unsol_event,
- .init_hook = alc861vd_lenovo_automute,
+ .init_hook = alc861vd_lenovo_init_hook,
},
[ALC861VD_DALLAS] = {
.mixers = { alc861vd_dallas_mixer },
@@ -14830,8 +14675,8 @@ static struct alc_config_preset alc861vd_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
.channel_mode = alc861vd_3stack_2ch_modes,
.input_mux = &alc861vd_dallas_capture_source,
- .unsol_event = alc861vd_dallas_unsol_event,
- .init_hook = alc861vd_dallas_automute,
+ .unsol_event = alc_automute_amp_unsol_event,
+ .init_hook = alc861vd_dallas_init_hook,
},
[ALC861VD_HP] = {
.mixers = { alc861vd_hp_mixer },
@@ -14842,8 +14687,8 @@ static struct alc_config_preset alc861vd_presets[] = {
.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,
+ .unsol_event = alc_automute_amp_unsol_event,
+ .init_hook = alc861vd_dallas_init_hook,
},
[ALC660VD_ASUS_V1S] = {
.mixers = { alc861vd_lenovo_mixer },
@@ -14858,7 +14703,7 @@ static struct alc_config_preset alc861vd_presets[] = {
.channel_mode = alc861vd_3stack_2ch_modes,
.input_mux = &alc861vd_capture_source,
.unsol_event = alc861vd_lenovo_unsol_event,
- .init_hook = alc861vd_lenovo_automute,
+ .init_hook = alc861vd_lenovo_init_hook,
},
};
@@ -14876,7 +14721,6 @@ static void alc861vd_auto_init_multi_out(struct hda_codec *codec)
struct alc_spec *spec = codec->spec;
int i;
- alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
for (i = 0; i <= HDA_SIDE; i++) {
hda_nid_t nid = spec->autocfg.line_out_pins[i];
int pin_type = get_pin_type(spec->autocfg.line_out_type);
@@ -15094,6 +14938,8 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
if (err < 0)
return err;
+ alc_ssid_check(codec, 0x15, 0x1b, 0x14);
+
return 1;
}
@@ -15211,12 +15057,23 @@ static hda_nid_t alc662_dac_nids[4] = {
0x02, 0x03, 0x04
};
+static hda_nid_t alc272_dac_nids[2] = {
+ 0x02, 0x03
+};
+
static hda_nid_t alc662_adc_nids[1] = {
/* ADC1-2 */
0x09,
};
+static hda_nid_t alc272_adc_nids[1] = {
+ /* ADC1-2 */
+ 0x08,
+};
+
static hda_nid_t alc662_capsrc_nids[1] = { 0x22 };
+static hda_nid_t alc272_capsrc_nids[1] = { 0x23 };
+
/* input MUX */
/* FIXME: should be a matrix-type input source selection */
@@ -15402,10 +15259,8 @@ static struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = {
};
static struct snd_kcontrol_new alc662_eeepc_p701_mixer[] = {
- HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-
- HDA_CODEC_VOLUME("Line-Out Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Line-Out Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+ ALC262_HIPPO_MASTER_SWITCH,
HDA_CODEC_VOLUME("e-Mic Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_VOLUME("e-Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
@@ -15418,15 +15273,11 @@ static struct snd_kcontrol_new alc662_eeepc_p701_mixer[] = {
};
static struct snd_kcontrol_new alc662_eeepc_ep20_mixer[] = {
- HDA_CODEC_VOLUME("Line-Out Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Line-Out Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+ ALC262_HIPPO_MASTER_SWITCH,
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x03, 2, HDA_INPUT),
HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Speaker Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("MuteCtrl Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
@@ -15642,14 +15493,7 @@ static struct hda_verb alc662_init_verbs[] = {
/* 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(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)},
/* always trun on EAPD */
{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
@@ -15844,12 +15688,48 @@ static struct hda_verb alc662_ecs_init_verbs[] = {
{}
};
+static struct hda_verb alc272_dell_zm1_init_verbs[] = {
+ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
+ {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
+ {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+ {}
+};
+
+static struct hda_verb alc272_dell_init_verbs[] = {
+ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
+ {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
+ {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+ {}
+};
+
static struct snd_kcontrol_new alc662_auto_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
{ } /* end */
};
+static struct snd_kcontrol_new alc272_auto_capture_mixer[] = {
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ { } /* end */
+};
+
static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
{
unsigned int present;
@@ -15905,51 +15785,25 @@ static void alc662_eeepc_mic_automute(struct hda_codec *codec)
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);
+ else
+ alc262_hippo_unsol_event(codec, res);
}
static void alc662_eeepc_inithook(struct hda_codec *codec)
{
- alc262_hippo1_automute( codec );
+ alc262_hippo1_init_hook(codec);
alc662_eeepc_mic_automute(codec);
}
-static void alc662_eeepc_ep20_automute(struct hda_codec *codec)
-{
- unsigned int mute;
- unsigned int present;
-
- snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0);
- present = snd_hda_codec_read(codec, 0x14, 0,
- AC_VERB_GET_PIN_SENSE, 0);
- present = (present & 0x80000000) != 0;
- if (present) {
- /* mute internal speaker */
- snd_hda_codec_amp_stereo(codec, 0x1b, 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_stereo(codec, 0x1b, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
- }
-}
-
-/* unsolicited event for HP jack sensing */
-static void alc662_eeepc_ep20_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) == ALC880_HP_EVENT)
- alc662_eeepc_ep20_automute(codec);
-}
-
static void alc662_eeepc_ep20_inithook(struct hda_codec *codec)
{
- alc662_eeepc_ep20_automute(codec);
+ struct alc_spec *spec = codec->spec;
+
+ spec->autocfg.hp_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[0] = 0x1b;
+ alc262_hippo_master_update(codec);
}
static void alc663_m51va_speaker_automute(struct hda_codec *codec)
@@ -16283,35 +16137,9 @@ static void alc663_g50v_inithook(struct hda_codec *codec)
alc662_eeepc_mic_automute(codec);
}
-/* bind hp and internal speaker mute (with plug check) */
-static int alc662_ecs_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, 0x1b, 0, HDA_OUTPUT, 0,
- HDA_AMP_MUTE,
- valp[0] ? 0 : HDA_AMP_MUTE);
- change |= snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0,
- HDA_AMP_MUTE,
- valp[1] ? 0 : HDA_AMP_MUTE);
- if (change)
- alc262_hippo1_automute(codec);
- return change;
-}
-
static struct snd_kcontrol_new alc662_ecs_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 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 = alc662_ecs_master_sw_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
- },
+ ALC262_HIPPO_MASTER_SWITCH,
HDA_CODEC_VOLUME("e-Mic/LineIn Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_VOLUME("e-Mic/LineIn Playback Volume", 0x0b, 0x0, HDA_INPUT),
@@ -16356,11 +16184,15 @@ static const char *alc662_models[ALC662_MODEL_LAST] = {
[ALC663_ASUS_MODE4] = "asus-mode4",
[ALC663_ASUS_MODE5] = "asus-mode5",
[ALC663_ASUS_MODE6] = "asus-mode6",
+ [ALC272_DELL] = "dell",
+ [ALC272_DELL_ZM1] = "dell-zm1",
[ALC662_AUTO] = "auto",
};
static struct snd_pci_quirk alc662_cfg_tbl[] = {
SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS),
+ SND_PCI_QUIRK(0x1028, 0x02d6, "DELL", ALC272_DELL),
+ SND_PCI_QUIRK(0x1028, 0x02f4, "DELL ZM1", ALC272_DELL_ZM1),
SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3),
SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3),
@@ -16373,26 +16205,36 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6),
SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6),
SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2),
+ SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC663_ASUS_MODE3),
+ SND_PCI_QUIRK(0x1043, 0x17c3, "ASUS UX20", ALC663_ASUS_M51VA),
+ SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_ASUS_MODE2),
SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_ASUS_MODE2),
SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC663_ASUS_MODE5),
SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC663_ASUS_MODE6),
SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_ASUS_MODE2),
+ SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_ASUS_MODE2),
SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_ASUS_MODE2),
SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA),
/*SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M50Vr", ALC663_ASUS_MODE1),*/
SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3),
SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3),
+ SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC663_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC663_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2),
SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_ASUS_MODE2),
+ SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC663_ASUS_MODE3),
+ SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS G50V", ALC663_ASUS_G50V),
/*SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS NB", ALC663_ASUS_MODE1),*/
SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2),
+ SND_PCI_QUIRK(0x1043, 0x19d3, "ASUS NB", ALC663_ASUS_M51VA),
SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC663_ASUS_MODE4),
SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG),
@@ -16404,6 +16246,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
ALC662_3ST_6ch_DIG),
SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG),
+ SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA),
SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
SND_PCI_QUIRK(0x1849, 0x3662, "ASROCK K10N78FullHD-hSLI R3.0",
ALC662_3ST_6ch_DIG),
@@ -16490,7 +16333,7 @@ static struct alc_config_preset alc662_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
.channel_mode = alc662_3ST_6ch_modes,
.input_mux = &alc662_lenovo_101e_capture_source,
- .unsol_event = alc662_eeepc_ep20_unsol_event,
+ .unsol_event = alc662_eeepc_unsol_event,
.init_hook = alc662_eeepc_ep20_inithook,
},
[ALC662_ECS] = {
@@ -16641,6 +16484,36 @@ static struct alc_config_preset alc662_presets[] = {
.unsol_event = alc663_mode6_unsol_event,
.init_hook = alc663_mode6_inithook,
},
+ [ALC272_DELL] = {
+ .mixers = { alc663_m51va_mixer },
+ .cap_mixer = alc272_auto_capture_mixer,
+ .init_verbs = { alc662_init_verbs, alc272_dell_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc272_dac_nids),
+ .dac_nids = alc662_dac_nids,
+ .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+ .adc_nids = alc272_adc_nids,
+ .num_adc_nids = ARRAY_SIZE(alc272_adc_nids),
+ .capsrc_nids = alc272_capsrc_nids,
+ .channel_mode = alc662_3ST_2ch_modes,
+ .input_mux = &alc663_m51va_capture_source,
+ .unsol_event = alc663_m51va_unsol_event,
+ .init_hook = alc663_m51va_inithook,
+ },
+ [ALC272_DELL_ZM1] = {
+ .mixers = { alc663_m51va_mixer },
+ .cap_mixer = alc662_auto_capture_mixer,
+ .init_verbs = { alc662_init_verbs, alc272_dell_zm1_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc272_dac_nids),
+ .dac_nids = alc662_dac_nids,
+ .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+ .adc_nids = alc662_adc_nids,
+ .num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
+ .capsrc_nids = alc662_capsrc_nids,
+ .channel_mode = alc662_3ST_2ch_modes,
+ .input_mux = &alc663_m51va_capture_source,
+ .unsol_event = alc663_m51va_unsol_event,
+ .init_hook = alc663_m51va_inithook,
+ },
};
@@ -16835,7 +16708,6 @@ static void alc662_auto_init_multi_out(struct hda_codec *codec)
struct alc_spec *spec = codec->spec;
int i;
- alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
for (i = 0; i <= HDA_SIDE; i++) {
hda_nid_t nid = spec->autocfg.line_out_pins[i];
int pin_type = get_pin_type(spec->autocfg.line_out_type);
@@ -16932,6 +16804,8 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
if (err < 0)
return err;
+ alc_ssid_check(codec, 0x15, 0x1b, 0x14);
+
return 1;
}
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 61996a2f45df..ecf53f755a09 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -100,6 +100,7 @@ enum {
STAC_HP_M4,
STAC_HP_DV5,
STAC_HP_HDX,
+ STAC_HP_DV4_1222NR,
STAC_92HD71BXX_MODELS
};
@@ -1836,6 +1837,7 @@ static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = {
[STAC_HP_M4] = NULL,
[STAC_HP_DV5] = NULL,
[STAC_HP_HDX] = NULL,
+ [STAC_HP_DV4_1222NR] = NULL,
};
static const char *stac92hd71bxx_models[STAC_92HD71BXX_MODELS] = {
@@ -1847,6 +1849,7 @@ static const char *stac92hd71bxx_models[STAC_92HD71BXX_MODELS] = {
[STAC_HP_M4] = "hp-m4",
[STAC_HP_DV5] = "hp-dv5",
[STAC_HP_HDX] = "hp-hdx",
+ [STAC_HP_DV4_1222NR] = "hp-dv4-1222nr",
};
static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = {
@@ -1855,6 +1858,8 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = {
"DFI LanParty", STAC_92HD71BXX_REF),
SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
"DFI LanParty", STAC_92HD71BXX_REF),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30fb,
+ "HP dv4-1222nr", STAC_HP_DV4_1222NR),
SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3080,
"HP", STAC_HP_DV5),
SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x30f0,
@@ -3076,6 +3081,11 @@ static int create_multi_out_ctls(struct hda_codec *codec, int num_outs,
unsigned int wid_caps;
for (i = 0; i < num_outs && i < ARRAY_SIZE(chname); i++) {
+ if (type == AUTO_PIN_HP_OUT && !spec->hp_detect) {
+ wid_caps = get_wcaps(codec, pins[i]);
+ if (wid_caps & AC_WCAP_UNSOL_CAP)
+ spec->hp_detect = 1;
+ }
nid = dac_nids[i];
if (!nid)
continue;
@@ -3119,11 +3129,6 @@ static int create_multi_out_ctls(struct hda_codec *codec, int num_outs,
err = create_controls_idx(codec, name, idx, nid, 3);
if (err < 0)
return err;
- if (type == AUTO_PIN_HP_OUT && !spec->hp_detect) {
- wid_caps = get_wcaps(codec, pins[i]);
- if (wid_caps & AC_WCAP_UNSOL_CAP)
- spec->hp_detect = 1;
- }
}
}
return 0;
@@ -3851,6 +3856,15 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,
AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */
}
+#ifdef CONFIG_SND_JACK
+static void stac92xx_free_jack_priv(struct snd_jack *jack)
+{
+ struct sigmatel_jack *jacks = jack->private_data;
+ jacks->nid = 0;
+ jacks->jack = NULL;
+}
+#endif
+
static int stac92xx_add_jack(struct hda_codec *codec,
hda_nid_t nid, int type)
{
@@ -3860,6 +3874,7 @@ static int stac92xx_add_jack(struct hda_codec *codec,
int def_conf = snd_hda_codec_get_pincfg(codec, nid);
int connectivity = get_defcfg_connect(def_conf);
char name[32];
+ int err;
if (connectivity && connectivity != AC_JACK_PORT_FIXED)
return 0;
@@ -3876,10 +3891,15 @@ static int stac92xx_add_jack(struct hda_codec *codec,
snd_hda_get_jack_connectivity(def_conf),
snd_hda_get_jack_location(def_conf));
- return snd_jack_new(codec->bus->card, name, type, &jack->jack);
-#else
- return 0;
+ err = snd_jack_new(codec->bus->card, name, type, &jack->jack);
+ if (err < 0) {
+ jack->nid = 0;
+ return err;
+ }
+ jack->jack->private_data = jack;
+ jack->jack->private_free = stac92xx_free_jack_priv;
#endif
+ return 0;
}
static int stac_add_event(struct sigmatel_spec *spec, hda_nid_t nid,
@@ -4064,7 +4084,12 @@ static int stac92xx_init(struct hda_codec *codec)
pinctl = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
/* if PINCTL already set then skip */
- if (!(pinctl & AC_PINCTL_IN_EN)) {
+ /* Also, if both INPUT and OUTPUT are set,
+ * it must be a BIOS bug; need to override, too
+ */
+ if (!(pinctl & AC_PINCTL_IN_EN) ||
+ (pinctl & AC_PINCTL_OUT_EN)) {
+ pinctl &= ~AC_PINCTL_OUT_EN;
pinctl |= AC_PINCTL_IN_EN;
stac92xx_auto_set_pinctl(codec, nid,
pinctl);
@@ -4138,8 +4163,10 @@ static void stac92xx_free_jacks(struct hda_codec *codec)
if (!codec->bus->shutdown && spec->jacks.list) {
struct sigmatel_jack *jacks = spec->jacks.list;
int i;
- for (i = 0; i < spec->jacks.used; i++)
- snd_device_free(codec->bus->card, &jacks[i].jack);
+ for (i = 0; i < spec->jacks.used; i++, jacks++) {
+ if (jacks->jack)
+ snd_device_free(codec->bus->card, jacks->jack);
+ }
}
snd_array_free(&spec->jacks);
#endif
@@ -4503,27 +4530,38 @@ static int stac92xx_resume(struct hda_codec *codec)
return 0;
}
-
/*
- * using power check for controlling mute led of HP HDX notebooks
+ * using power check for controlling mute led of HP notebooks
* check for mute state only on Speakers (nid = 0x10)
*
* For this feature CONFIG_SND_HDA_POWER_SAVE is needed, otherwise
* the LED is NOT working properly !
+ *
+ * Changed name to reflect that it now works for any designated
+ * model, not just HP HDX.
*/
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static int stac92xx_hp_hdx_check_power_status(struct hda_codec *codec,
+static int stac92xx_hp_check_power_status(struct hda_codec *codec,
hda_nid_t nid)
{
struct sigmatel_spec *spec = codec->spec;
+ unsigned int gpio_bit = 0; /* gets rid of compiler warning */
+
+ switch (spec->board_config) {
+ case STAC_HP_DV4_1222NR:
+ gpio_bit = 0x01;
+ break;
+ case STAC_HP_HDX:
+ gpio_bit = 0x08;
+ }
if (nid == 0x10) {
if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) &
HDA_AMP_MUTE)
- spec->gpio_data &= ~0x08; /* orange */
+ spec->gpio_data &= ~gpio_bit; /* orange */
else
- spec->gpio_data |= 0x08; /* white */
+ spec->gpio_data |= gpio_bit; /* white */
stac_gpio_set(codec, spec->gpio_mask,
spec->gpio_dir,
@@ -5202,6 +5240,22 @@ again:
spec->num_smuxes = 0;
spec->num_dmuxes = 1;
break;
+ case STAC_HP_DV4_1222NR:
+ spec->num_dmics = 1;
+ /* I don't know if it needs 1 or 2 smuxes - will wait for
+ * bug reports to fix if needed
+ */
+ spec->num_smuxes = 1;
+ spec->num_dmuxes = 1;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ /* This controls MUTE LED */
+ spec->gpio_mask |= 0x01;
+ spec->gpio_dir |= 0x01;
+ spec->gpio_data |= 0x01;
+ codec->patch_ops.check_power_status =
+ stac92xx_hp_check_power_status;
+#endif
+ /* fallthrough */
case STAC_HP_DV5:
snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010);
stac92xx_auto_set_pinctl(codec, 0x0d, AC_PINCTL_OUT_EN);
@@ -5222,7 +5276,7 @@ again:
/* register check_power_status callback. */
codec->patch_ops.check_power_status =
- stac92xx_hp_hdx_check_power_status;
+ stac92xx_hp_check_power_status;
#endif
break;
};
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index b25a5cc637d6..8e004fb6961a 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -205,7 +205,7 @@ struct via_spec {
/* playback */
struct hda_multi_out multiout;
- hda_nid_t extra_dig_out_nid;
+ hda_nid_t slave_dig_outs[2];
/* capture */
unsigned int num_adc_nids;
@@ -731,21 +731,6 @@ static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
return snd_hda_multi_out_dig_close(codec, &spec->multiout);
}
-/* setup SPDIF output stream */
-static void setup_dig_playback_stream(struct hda_codec *codec, hda_nid_t nid,
- unsigned int stream_tag, unsigned int format)
-{
- /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
- if (codec->spdif_ctls & AC_DIG1_ENABLE)
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
- codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
- snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
- /* turn on again (if needed) */
- if (codec->spdif_ctls & AC_DIG1_ENABLE)
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
- codec->spdif_ctls & 0xff);
-}
-
static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
unsigned int stream_tag,
@@ -753,19 +738,16 @@ static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
struct snd_pcm_substream *substream)
{
struct via_spec *spec = codec->spec;
- hda_nid_t nid;
-
- /* 1st or 2nd S/PDIF */
- if (substream->number == 0)
- nid = spec->multiout.dig_out_nid;
- else if (substream->number == 1)
- nid = spec->extra_dig_out_nid;
- else
- return -1;
+ return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
+ stream_tag, format, substream);
+}
- mutex_lock(&codec->spdif_mutex);
- setup_dig_playback_stream(codec, nid, stream_tag, format);
- mutex_unlock(&codec->spdif_mutex);
+static int via_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ struct snd_pcm_substream *substream)
+{
+ struct via_spec *spec = codec->spec;
+ snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
return 0;
}
@@ -842,7 +824,8 @@ static struct hda_pcm_stream vt1708_pcm_digital_playback = {
.ops = {
.open = via_dig_playback_pcm_open,
.close = via_dig_playback_pcm_close,
- .prepare = via_dig_playback_pcm_prepare
+ .prepare = via_dig_playback_pcm_prepare,
+ .cleanup = via_dig_playback_pcm_cleanup
},
};
@@ -874,13 +857,6 @@ static int via_build_controls(struct hda_codec *codec)
if (err < 0)
return err;
spec->multiout.share_spdif = 1;
-
- if (spec->extra_dig_out_nid) {
- err = snd_hda_create_spdif_out_ctls(codec,
- spec->extra_dig_out_nid);
- if (err < 0)
- return err;
- }
}
if (spec->dig_in_nid) {
err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
@@ -1013,10 +989,6 @@ static void via_unsol_event(struct hda_codec *codec,
via_gpio_control(codec);
}
-static hda_nid_t slave_dig_outs[] = {
- 0,
-};
-
static int via_init(struct hda_codec *codec)
{
struct via_spec *spec = codec->spec;
@@ -1051,8 +1023,9 @@ static int via_init(struct hda_codec *codec)
snd_hda_codec_write(codec, spec->autocfg.dig_in_pin, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
- /* no slave outs */
- codec->slave_dig_outs = slave_dig_outs;
+ /* assign slave outs */
+ if (spec->slave_dig_outs[0])
+ codec->slave_dig_outs = spec->slave_dig_outs;
return 0;
}
@@ -2134,7 +2107,8 @@ static struct hda_pcm_stream vt1708B_pcm_digital_playback = {
.ops = {
.open = via_dig_playback_pcm_open,
.close = via_dig_playback_pcm_close,
- .prepare = via_dig_playback_pcm_prepare
+ .prepare = via_dig_playback_pcm_prepare,
+ .cleanup = via_dig_playback_pcm_cleanup
},
};
@@ -2589,14 +2563,15 @@ static struct hda_pcm_stream vt1708S_pcm_analog_capture = {
};
static struct hda_pcm_stream vt1708S_pcm_digital_playback = {
- .substreams = 2,
+ .substreams = 1,
.channels_min = 2,
.channels_max = 2,
/* NID is set in via_build_pcms */
.ops = {
.open = via_dig_playback_pcm_open,
.close = via_dig_playback_pcm_close,
- .prepare = via_dig_playback_pcm_prepare
+ .prepare = via_dig_playback_pcm_prepare,
+ .cleanup = via_dig_playback_pcm_cleanup
},
};
@@ -2805,14 +2780,37 @@ static int vt1708S_auto_create_analog_input_ctls(struct via_spec *spec,
return 0;
}
+/* fill out digital output widgets; one for master and one for slave outputs */
+static void fill_dig_outs(struct hda_codec *codec)
+{
+ struct via_spec *spec = codec->spec;
+ int i;
+
+ for (i = 0; i < spec->autocfg.dig_outs; i++) {
+ hda_nid_t nid;
+ int conn;
+
+ nid = spec->autocfg.dig_out_pins[i];
+ if (!nid)
+ continue;
+ conn = snd_hda_get_connections(codec, nid, &nid, 1);
+ if (conn < 1)
+ continue;
+ if (!spec->multiout.dig_out_nid)
+ spec->multiout.dig_out_nid = nid;
+ else {
+ spec->slave_dig_outs[0] = nid;
+ break; /* at most two dig outs */
+ }
+ }
+}
+
static int vt1708S_parse_auto_config(struct hda_codec *codec)
{
struct via_spec *spec = codec->spec;
int err;
- static hda_nid_t vt1708s_ignore[] = {0x21, 0};
- err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
- vt1708s_ignore);
+ err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
if (err < 0)
return err;
err = vt1708S_auto_fill_dac_nids(spec, &spec->autocfg);
@@ -2833,10 +2831,7 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec)
spec->multiout.max_channels = spec->multiout.num_dacs * 2;
- if (spec->autocfg.dig_outs)
- spec->multiout.dig_out_nid = VT1708S_DIGOUT_NID;
-
- spec->extra_dig_out_nid = 0x15;
+ fill_dig_outs(codec);
if (spec->kctls.list)
spec->mixers[spec->num_mixers++] = spec->kctls.list;
@@ -3000,7 +2995,8 @@ static struct hda_pcm_stream vt1702_pcm_digital_playback = {
.ops = {
.open = via_dig_playback_pcm_open,
.close = via_dig_playback_pcm_close,
- .prepare = via_dig_playback_pcm_prepare
+ .prepare = via_dig_playback_pcm_prepare,
+ .cleanup = via_dig_playback_pcm_cleanup
},
};
@@ -3128,10 +3124,8 @@ static int vt1702_parse_auto_config(struct hda_codec *codec)
{
struct via_spec *spec = codec->spec;
int err;
- static hda_nid_t vt1702_ignore[] = {0x1C, 0};
- err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
- vt1702_ignore);
+ err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
if (err < 0)
return err;
err = vt1702_auto_fill_dac_nids(spec, &spec->autocfg);
@@ -3152,10 +3146,7 @@ static int vt1702_parse_auto_config(struct hda_codec *codec)
spec->multiout.max_channels = spec->multiout.num_dacs * 2;
- if (spec->autocfg.dig_outs)
- spec->multiout.dig_out_nid = VT1702_DIGOUT_NID;
-
- spec->extra_dig_out_nid = 0x1B;
+ fill_dig_outs(codec);
if (spec->kctls.list)
spec->mixers[spec->num_mixers++] = spec->kctls.list;
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 57648810eaf1..173bebf9f51d 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -355,6 +355,9 @@ struct ichdev {
unsigned int fragsize1;
unsigned int position;
unsigned int pos_shift;
+ unsigned int last_pos;
+ unsigned long last_pos_jiffies;
+ unsigned int jiffy_to_bytes;
int frags;
int lvi;
int lvi_frag;
@@ -838,7 +841,10 @@ static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd
ichdev->suspended = 0;
/* fallthru */
case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
val = ICH_IOCE | ICH_STARTBM;
+ ichdev->last_pos = ichdev->position;
+ ichdev->last_pos_jiffies = jiffies;
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
ichdev->suspended = 1;
@@ -849,9 +855,6 @@ static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
val = ICH_IOCE;
break;
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- val = ICH_IOCE | ICH_STARTBM;
- break;
default:
return -EINVAL;
}
@@ -1045,6 +1048,7 @@ static int snd_intel8x0_pcm_prepare(struct snd_pcm_substream *substream)
ichdev->pos_shift = (runtime->sample_bits > 16) ? 2 : 1;
}
snd_intel8x0_setup_periods(chip, ichdev);
+ ichdev->jiffy_to_bytes = (runtime->rate * 4 * ichdev->pos_shift) / HZ;
return 0;
}
@@ -1053,7 +1057,7 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *subs
struct intel8x0 *chip = snd_pcm_substream_chip(substream);
struct ichdev *ichdev = get_ichdev(substream);
size_t ptr1, ptr;
- int civ, timeout = 100;
+ int civ, timeout = 10;
unsigned int position;
spin_lock(&chip->reg_lock);
@@ -1069,9 +1073,19 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *subs
ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb))
break;
} while (timeout--);
- ptr1 <<= ichdev->pos_shift;
- ptr = ichdev->fragsize1 - ptr1;
- ptr += position;
+ if (ptr1 != 0) {
+ ptr1 <<= ichdev->pos_shift;
+ ptr = ichdev->fragsize1 - ptr1;
+ ptr += position;
+ ichdev->last_pos = ptr;
+ ichdev->last_pos_jiffies = jiffies;
+ } else {
+ ptr1 = jiffies - ichdev->last_pos_jiffies;
+ if (ptr1)
+ ptr1 -= 1;
+ ptr = ichdev->last_pos + ptr1 * ichdev->jiffy_to_bytes;
+ ptr %= ichdev->size;
+ }
spin_unlock(&chip->reg_lock);
if (ptr >= ichdev->size)
return 0;
@@ -1840,6 +1854,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
},
{
.subvendor = 0x1028,
+ .subdevice = 0x016a,
+ .name = "Dell Inspiron 8600", /* STAC9750/51 */
+ .type = AC97_TUNE_HP_ONLY
+ },
+ {
+ .subvendor = 0x1028,
.subdevice = 0x0186,
.name = "Dell Latitude D810", /* cf. Malone #41015 */
.type = AC97_TUNE_HP_MUTE_LED
@@ -1882,12 +1902,6 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
},
{
.subvendor = 0x103c,
- .subdevice = 0x0934,
- .name = "HP nx8220",
- .type = AC97_TUNE_MUTE_LED
- },
- {
- .subvendor = 0x103c,
.subdevice = 0x129d,
.name = "HP xw8000",
.type = AC97_TUNE_HP_ONLY
@@ -2661,12 +2675,14 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip)
struct snd_pcm_substream *subs;
struct ichdev *ichdev;
unsigned long port;
- unsigned long pos, t;
- struct timeval start_time, stop_time;
+ unsigned long pos, pos1, t;
+ int civ, timeout = 1000, attempt = 1;
+ struct timespec start_time, stop_time;
if (chip->ac97_bus->clock != 48000)
return; /* specified in module option */
+ __again:
subs = chip->pcm[0]->streams[0].substream;
if (! subs || subs->dma_buffer.bytes < INTEL8X0_TESTBUF_SIZE) {
snd_printk(KERN_WARNING "no playback buffer allocated - aborting measure ac97 clock\n");
@@ -2674,7 +2690,7 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip)
}
ichdev = &chip->ichd[ICHD_PCMOUT];
ichdev->physbuf = subs->dma_buffer.addr;
- ichdev->size = chip->ichd[ICHD_PCMOUT].fragsize = INTEL8X0_TESTBUF_SIZE;
+ ichdev->size = ichdev->fragsize = INTEL8X0_TESTBUF_SIZE;
ichdev->substream = NULL; /* don't process interrupts */
/* set rate */
@@ -2693,16 +2709,31 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip)
iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE);
iputdword(chip, ICHREG(ALI_DMACR), 1 << ichdev->ali_slot);
}
- do_gettimeofday(&start_time);
+ do_posix_clock_monotonic_gettime(&start_time);
spin_unlock_irq(&chip->reg_lock);
msleep(50);
spin_lock_irq(&chip->reg_lock);
/* check the position */
- pos = ichdev->fragsize1;
- pos -= igetword(chip, ichdev->reg_offset + ichdev->roff_picb) << ichdev->pos_shift;
- pos += ichdev->position;
+ do {
+ civ = igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV);
+ pos1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb);
+ if (pos1 == 0) {
+ udelay(10);
+ continue;
+ }
+ if (civ == igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV) &&
+ pos1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb))
+ break;
+ } while (timeout--);
+ if (pos1 == 0) { /* oops, this value is not reliable */
+ pos = 0;
+ } else {
+ pos = ichdev->fragsize1;
+ pos -= pos1 << ichdev->pos_shift;
+ pos += ichdev->position;
+ }
chip->in_measurement = 0;
- do_gettimeofday(&stop_time);
+ do_posix_clock_monotonic_gettime(&stop_time);
/* stop */
if (chip->device_type == DEVICE_ALI) {
iputdword(chip, ICHREG(ALI_DMACR), 1 << (ichdev->ali_slot + 16));
@@ -2717,22 +2748,42 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip)
iputbyte(chip, port + ICH_REG_OFF_CR, ICH_RESETREGS);
spin_unlock_irq(&chip->reg_lock);
+ if (pos == 0) {
+ snd_printk(KERN_ERR "intel8x0: measure - unreliable DMA position..\n");
+ __retry:
+ if (attempt < 3) {
+ msleep(300);
+ attempt++;
+ goto __again;
+ }
+ goto __end;
+ }
+
+ pos /= 4;
t = stop_time.tv_sec - start_time.tv_sec;
t *= 1000000;
- t += stop_time.tv_usec - start_time.tv_usec;
- printk(KERN_INFO "%s: measured %lu usecs\n", __func__, t);
+ t += (stop_time.tv_nsec - start_time.tv_nsec) / 1000;
+ printk(KERN_INFO "%s: measured %lu usecs (%lu samples)\n", __func__, t, pos);
if (t == 0) {
- snd_printk(KERN_ERR "?? calculation error..\n");
- return;
+ snd_printk(KERN_ERR "intel8x0: ?? calculation error..\n");
+ goto __retry;
}
- pos = (pos / 4) * 1000;
+ pos *= 1000;
pos = (pos / t) * 1000 + ((pos % t) * 1000) / t;
- if (pos < 40000 || pos >= 60000)
+ if (pos < 40000 || pos >= 60000) {
/* abnormal value. hw problem? */
printk(KERN_INFO "intel8x0: measured clock %ld rejected\n", pos);
+ goto __retry;
+ } else if (pos > 40500 && pos < 41500)
+ /* first exception - 41000Hz reference clock */
+ chip->ac97_bus->clock = 41000;
+ else if (pos > 43600 && pos < 44600)
+ /* second exception - 44100HZ reference clock */
+ chip->ac97_bus->clock = 44100;
else if (pos < 47500 || pos > 48500)
/* not 48000Hz, tuning the clock.. */
chip->ac97_bus->clock = (chip->ac97_bus->clock * 48000) / pos;
+ __end:
printk(KERN_INFO "intel8x0: clocking to %d\n", chip->ac97_bus->clock);
snd_ac97_update_power(chip->ac97[0], AC97_PCM_FRONT_DAC_RATE, 0);
}
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 8b79969034be..7cc38a11e997 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -1238,7 +1238,8 @@ static struct snd_pcm_hardware snd_korg1212_playback_info =
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED),
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BATCH),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = (SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000),
@@ -1258,7 +1259,8 @@ static struct snd_pcm_hardware snd_korg1212_capture_info =
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED),
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BATCH),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = (SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000),
diff --git a/sound/pci/lx6464es/Makefile b/sound/pci/lx6464es/Makefile
new file mode 100644
index 000000000000..eb04a6c73d8b
--- /dev/null
+++ b/sound/pci/lx6464es/Makefile
@@ -0,0 +1,2 @@
+snd-lx6464es-objs := lx6464es.o lx_core.o
+obj-$(CONFIG_SND_LX6464ES) += snd-lx6464es.o
diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c
new file mode 100644
index 000000000000..870bfc58c697
--- /dev/null
+++ b/sound/pci/lx6464es/lx6464es.c
@@ -0,0 +1,1152 @@
+/* -*- linux-c -*- *
+ *
+ * ALSA driver for the digigram lx6464es interface
+ *
+ * Copyright (c) 2008, 2009 Tim Blechmann <tim@klingt.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; see the file COPYING. 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/init.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+#include <sound/initval.h>
+#include <sound/control.h>
+#include <sound/info.h>
+
+#include "lx6464es.h"
+
+MODULE_AUTHOR("Tim Blechmann");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("digigram lx6464es");
+MODULE_SUPPORTED_DEVICE("{digigram lx6464es{}}");
+
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+static const char card_name[] = "LX6464ES";
+
+
+#define PCI_DEVICE_ID_PLX_LX6464ES PCI_DEVICE_ID_PLX_9056
+
+static struct pci_device_id snd_lx6464es_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_LX6464ES),
+ .subvendor = PCI_VENDOR_ID_DIGIGRAM,
+ .subdevice = PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ES_SERIAL_SUBSYSTEM
+ }, /* LX6464ES */
+ { PCI_DEVICE(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_LX6464ES),
+ .subvendor = PCI_VENDOR_ID_DIGIGRAM,
+ .subdevice = PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ES_CAE_SERIAL_SUBSYSTEM
+ }, /* LX6464ES-CAE */
+ { 0, },
+};
+
+MODULE_DEVICE_TABLE(pci, snd_lx6464es_ids);
+
+
+
+/* PGO pour USERo dans le registre pci_0x06/loc_0xEC */
+#define CHIPSC_RESET_XILINX (1L<<16)
+
+
+/* alsa callbacks */
+static struct snd_pcm_hardware lx_caps = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_SYNC_START),
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S16_BE |
+ SNDRV_PCM_FMTBIT_S24_3LE |
+ SNDRV_PCM_FMTBIT_S24_3BE),
+ .rates = (SNDRV_PCM_RATE_CONTINUOUS |
+ SNDRV_PCM_RATE_8000_192000),
+ .rate_min = 8000,
+ .rate_max = 192000,
+ .channels_min = 2,
+ .channels_max = 64,
+ .buffer_bytes_max = 64*2*3*MICROBLAZE_IBL_MAX*MAX_STREAM_BUFFER,
+ .period_bytes_min = (2*2*MICROBLAZE_IBL_MIN*2),
+ .period_bytes_max = (4*64*MICROBLAZE_IBL_MAX*MAX_STREAM_BUFFER),
+ .periods_min = 2,
+ .periods_max = MAX_STREAM_BUFFER,
+};
+
+static int lx_set_granularity(struct lx6464es *chip, u32 gran);
+
+
+static int lx_hardware_open(struct lx6464es *chip,
+ struct snd_pcm_substream *substream)
+{
+ int err = 0;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int channels = runtime->channels;
+ int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
+
+ snd_pcm_uframes_t period_size = runtime->period_size;
+
+ snd_printd(LXP "allocating pipe for %d channels\n", channels);
+ err = lx_pipe_allocate(chip, 0, is_capture, channels);
+ if (err < 0) {
+ snd_printk(KERN_ERR LXP "allocating pipe failed\n");
+ return err;
+ }
+
+ err = lx_set_granularity(chip, period_size);
+ if (err < 0) {
+ snd_printk(KERN_ERR LXP "setting granularity to %ld failed\n",
+ period_size);
+ return err;
+ }
+
+ return 0;
+}
+
+static int lx_hardware_start(struct lx6464es *chip,
+ struct snd_pcm_substream *substream)
+{
+ int err = 0;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
+
+ snd_printd(LXP "setting stream format\n");
+ err = lx_stream_set_format(chip, runtime, 0, is_capture);
+ if (err < 0) {
+ snd_printk(KERN_ERR LXP "setting stream format failed\n");
+ return err;
+ }
+
+ snd_printd(LXP "starting pipe\n");
+ err = lx_pipe_start(chip, 0, is_capture);
+ if (err < 0) {
+ snd_printk(KERN_ERR LXP "starting pipe failed\n");
+ return err;
+ }
+
+ snd_printd(LXP "waiting for pipe to start\n");
+ err = lx_pipe_wait_for_start(chip, 0, is_capture);
+ if (err < 0) {
+ snd_printk(KERN_ERR LXP "waiting for pipe failed\n");
+ return err;
+ }
+
+ return err;
+}
+
+
+static int lx_hardware_stop(struct lx6464es *chip,
+ struct snd_pcm_substream *substream)
+{
+ int err = 0;
+ int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
+
+ snd_printd(LXP "pausing pipe\n");
+ err = lx_pipe_pause(chip, 0, is_capture);
+ if (err < 0) {
+ snd_printk(KERN_ERR LXP "pausing pipe failed\n");
+ return err;
+ }
+
+ snd_printd(LXP "waiting for pipe to become idle\n");
+ err = lx_pipe_wait_for_idle(chip, 0, is_capture);
+ if (err < 0) {
+ snd_printk(KERN_ERR LXP "waiting for pipe failed\n");
+ return err;
+ }
+
+ snd_printd(LXP "stopping pipe\n");
+ err = lx_pipe_stop(chip, 0, is_capture);
+ if (err < 0) {
+ snd_printk(LXP "stopping pipe failed\n");
+ return err;
+ }
+
+ return err;
+}
+
+
+static int lx_hardware_close(struct lx6464es *chip,
+ struct snd_pcm_substream *substream)
+{
+ int err = 0;
+ int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
+
+ snd_printd(LXP "releasing pipe\n");
+ err = lx_pipe_release(chip, 0, is_capture);
+ if (err < 0) {
+ snd_printk(LXP "releasing pipe failed\n");
+ return err;
+ }
+
+ return err;
+}
+
+
+static int lx_pcm_open(struct snd_pcm_substream *substream)
+{
+ struct lx6464es *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int err = 0;
+ int board_rate;
+
+ snd_printdd("->lx_pcm_open\n");
+ mutex_lock(&chip->setup_mutex);
+
+ /* copy the struct snd_pcm_hardware struct */
+ runtime->hw = lx_caps;
+
+#if 0
+ /* buffer-size should better be multiple of period-size */
+ err = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (err < 0) {
+ snd_printk(KERN_WARNING LXP "could not constrain periods\n");
+ goto exit;
+ }
+#endif
+
+ /* the clock rate cannot be changed */
+ board_rate = chip->board_sample_rate;
+ err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE,
+ board_rate, board_rate);
+
+ if (err < 0) {
+ snd_printk(KERN_WARNING LXP "could not constrain periods\n");
+ goto exit;
+ }
+
+ /* constrain period size */
+ err = snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+ MICROBLAZE_IBL_MIN,
+ MICROBLAZE_IBL_MAX);
+ if (err < 0) {
+ snd_printk(KERN_WARNING LXP
+ "could not constrain period size\n");
+ goto exit;
+ }
+
+ snd_pcm_hw_constraint_step(runtime, 0,
+ SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 32);
+
+ snd_pcm_set_sync(substream);
+ err = 0;
+
+exit:
+ runtime->private_data = chip;
+
+ mutex_unlock(&chip->setup_mutex);
+ snd_printdd("<-lx_pcm_open, %d\n", err);
+ return err;
+}
+
+static int lx_pcm_close(struct snd_pcm_substream *substream)
+{
+ int err = 0;
+ snd_printdd("->lx_pcm_close\n");
+ return err;
+}
+
+static snd_pcm_uframes_t lx_pcm_stream_pointer(struct snd_pcm_substream
+ *substream)
+{
+ struct lx6464es *chip = snd_pcm_substream_chip(substream);
+ snd_pcm_uframes_t pos;
+ unsigned long flags;
+ int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
+
+ struct lx_stream *lx_stream = is_capture ? &chip->capture_stream :
+ &chip->playback_stream;
+
+ snd_printdd("->lx_pcm_stream_pointer\n");
+
+ spin_lock_irqsave(&chip->lock, flags);
+ pos = lx_stream->frame_pos * substream->runtime->period_size;
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ snd_printdd(LXP "stream_pointer at %ld\n", pos);
+ return pos;
+}
+
+static int lx_pcm_prepare(struct snd_pcm_substream *substream)
+{
+ struct lx6464es *chip = snd_pcm_substream_chip(substream);
+ int err = 0;
+ const int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
+
+ snd_printdd("->lx_pcm_prepare\n");
+
+ mutex_lock(&chip->setup_mutex);
+
+ if (chip->hardware_running[is_capture]) {
+ err = lx_hardware_stop(chip, substream);
+ if (err < 0) {
+ snd_printk(KERN_ERR LXP "failed to stop hardware. "
+ "Error code %d\n", err);
+ goto exit;
+ }
+
+ err = lx_hardware_close(chip, substream);
+ if (err < 0) {
+ snd_printk(KERN_ERR LXP "failed to close hardware. "
+ "Error code %d\n", err);
+ goto exit;
+ }
+ }
+
+ snd_printd(LXP "opening hardware\n");
+ err = lx_hardware_open(chip, substream);
+ if (err < 0) {
+ snd_printk(KERN_ERR LXP "failed to open hardware. "
+ "Error code %d\n", err);
+ goto exit;
+ }
+
+ err = lx_hardware_start(chip, substream);
+ if (err < 0) {
+ snd_printk(KERN_ERR LXP "failed to start hardware. "
+ "Error code %d\n", err);
+ goto exit;
+ }
+
+ chip->hardware_running[is_capture] = 1;
+
+ if (chip->board_sample_rate != substream->runtime->rate) {
+ if (!err)
+ chip->board_sample_rate = substream->runtime->rate;
+ }
+
+exit:
+ mutex_unlock(&chip->setup_mutex);
+ return err;
+}
+
+static int lx_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params, int is_capture)
+{
+ struct lx6464es *chip = snd_pcm_substream_chip(substream);
+ int err = 0;
+
+ snd_printdd("->lx_pcm_hw_params\n");
+
+ mutex_lock(&chip->setup_mutex);
+
+ /* set dma buffer */
+ err = snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+
+ if (is_capture)
+ chip->capture_stream.stream = substream;
+ else
+ chip->playback_stream.stream = substream;
+
+ mutex_unlock(&chip->setup_mutex);
+ return err;
+}
+
+static int lx_pcm_hw_params_playback(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
+{
+ return lx_pcm_hw_params(substream, hw_params, 0);
+}
+
+static int lx_pcm_hw_params_capture(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
+{
+ return lx_pcm_hw_params(substream, hw_params, 1);
+}
+
+static int lx_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ struct lx6464es *chip = snd_pcm_substream_chip(substream);
+ int err = 0;
+ int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
+
+ snd_printdd("->lx_pcm_hw_free\n");
+ mutex_lock(&chip->setup_mutex);
+
+ if (chip->hardware_running[is_capture]) {
+ err = lx_hardware_stop(chip, substream);
+ if (err < 0) {
+ snd_printk(KERN_ERR LXP "failed to stop hardware. "
+ "Error code %d\n", err);
+ goto exit;
+ }
+
+ err = lx_hardware_close(chip, substream);
+ if (err < 0) {
+ snd_printk(KERN_ERR LXP "failed to close hardware. "
+ "Error code %d\n", err);
+ goto exit;
+ }
+
+ chip->hardware_running[is_capture] = 0;
+ }
+
+ err = snd_pcm_lib_free_pages(substream);
+
+ if (is_capture)
+ chip->capture_stream.stream = 0;
+ else
+ chip->playback_stream.stream = 0;
+
+exit:
+ mutex_unlock(&chip->setup_mutex);
+ return err;
+}
+
+static void lx_trigger_start(struct lx6464es *chip, struct lx_stream *lx_stream)
+{
+ struct snd_pcm_substream *substream = lx_stream->stream;
+ const int is_capture = lx_stream->is_capture;
+
+ int err;
+
+ const u32 channels = substream->runtime->channels;
+ const u32 bytes_per_frame = channels * 3;
+ const u32 period_size = substream->runtime->period_size;
+ const u32 periods = substream->runtime->periods;
+ const u32 period_bytes = period_size * bytes_per_frame;
+
+ dma_addr_t buf = substream->dma_buffer.addr;
+ int i;
+
+ u32 needed, freed;
+ u32 size_array[5];
+
+ for (i = 0; i != periods; ++i) {
+ u32 buffer_index = 0;
+
+ err = lx_buffer_ask(chip, 0, is_capture, &needed, &freed,
+ size_array);
+ snd_printdd(LXP "starting: needed %d, freed %d\n",
+ needed, freed);
+
+ err = lx_buffer_give(chip, 0, is_capture, period_bytes,
+ lower_32_bits(buf), upper_32_bits(buf),
+ &buffer_index);
+
+ snd_printdd(LXP "starting: buffer index %x on %p (%d bytes)\n",
+ buffer_index, (void *)buf, period_bytes);
+ buf += period_bytes;
+ }
+
+ err = lx_buffer_ask(chip, 0, is_capture, &needed, &freed, size_array);
+ snd_printdd(LXP "starting: needed %d, freed %d\n", needed, freed);
+
+ snd_printd(LXP "starting: starting stream\n");
+ err = lx_stream_start(chip, 0, is_capture);
+ if (err < 0)
+ snd_printk(KERN_ERR LXP "couldn't start stream\n");
+ else
+ lx_stream->status = LX_STREAM_STATUS_RUNNING;
+
+ lx_stream->frame_pos = 0;
+}
+
+static void lx_trigger_stop(struct lx6464es *chip, struct lx_stream *lx_stream)
+{
+ const int is_capture = lx_stream->is_capture;
+ int err;
+
+ snd_printd(LXP "stopping: stopping stream\n");
+ err = lx_stream_stop(chip, 0, is_capture);
+ if (err < 0)
+ snd_printk(KERN_ERR LXP "couldn't stop stream\n");
+ else
+ lx_stream->status = LX_STREAM_STATUS_FREE;
+
+}
+
+static void lx_trigger_tasklet_dispatch_stream(struct lx6464es *chip,
+ struct lx_stream *lx_stream)
+{
+ switch (lx_stream->status) {
+ case LX_STREAM_STATUS_SCHEDULE_RUN:
+ lx_trigger_start(chip, lx_stream);
+ break;
+
+ case LX_STREAM_STATUS_SCHEDULE_STOP:
+ lx_trigger_stop(chip, lx_stream);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void lx_trigger_tasklet(unsigned long data)
+{
+ struct lx6464es *chip = (struct lx6464es *)data;
+ unsigned long flags;
+
+ snd_printdd("->lx_trigger_tasklet\n");
+
+ spin_lock_irqsave(&chip->lock, flags);
+ lx_trigger_tasklet_dispatch_stream(chip, &chip->capture_stream);
+ lx_trigger_tasklet_dispatch_stream(chip, &chip->playback_stream);
+ spin_unlock_irqrestore(&chip->lock, flags);
+}
+
+static int lx_pcm_trigger_dispatch(struct lx6464es *chip,
+ struct lx_stream *lx_stream, int cmd)
+{
+ int err = 0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ lx_stream->status = LX_STREAM_STATUS_SCHEDULE_RUN;
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ lx_stream->status = LX_STREAM_STATUS_SCHEDULE_STOP;
+ break;
+
+ default:
+ err = -EINVAL;
+ goto exit;
+ }
+ tasklet_schedule(&chip->trigger_tasklet);
+
+exit:
+ return err;
+}
+
+
+static int lx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct lx6464es *chip = snd_pcm_substream_chip(substream);
+ const int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
+ struct lx_stream *stream = is_capture ? &chip->capture_stream :
+ &chip->playback_stream;
+
+ snd_printdd("->lx_pcm_trigger\n");
+
+ return lx_pcm_trigger_dispatch(chip, stream, cmd);
+}
+
+static int snd_lx6464es_free(struct lx6464es *chip)
+{
+ snd_printdd("->snd_lx6464es_free\n");
+
+ lx_irq_disable(chip);
+
+ if (chip->irq >= 0)
+ free_irq(chip->irq, chip);
+
+ iounmap(chip->port_dsp_bar);
+ ioport_unmap(chip->port_plx_remapped);
+
+ pci_release_regions(chip->pci);
+ pci_disable_device(chip->pci);
+
+ kfree(chip);
+
+ return 0;
+}
+
+static int snd_lx6464es_dev_free(struct snd_device *device)
+{
+ return snd_lx6464es_free(device->device_data);
+}
+
+/* reset the dsp during initialization */
+static int __devinit lx_init_xilinx_reset(struct lx6464es *chip)
+{
+ int i;
+ u32 plx_reg = lx_plx_reg_read(chip, ePLX_CHIPSC);
+
+ snd_printdd("->lx_init_xilinx_reset\n");
+
+ /* activate reset of xilinx */
+ plx_reg &= ~CHIPSC_RESET_XILINX;
+
+ lx_plx_reg_write(chip, ePLX_CHIPSC, plx_reg);
+ msleep(1);
+
+ lx_plx_reg_write(chip, ePLX_MBOX3, 0);
+ msleep(1);
+
+ plx_reg |= CHIPSC_RESET_XILINX;
+ lx_plx_reg_write(chip, ePLX_CHIPSC, plx_reg);
+
+ /* deactivate reset of xilinx */
+ for (i = 0; i != 100; ++i) {
+ u32 reg_mbox3;
+ msleep(10);
+ reg_mbox3 = lx_plx_reg_read(chip, ePLX_MBOX3);
+ if (reg_mbox3) {
+ snd_printd(LXP "xilinx reset done\n");
+ snd_printdd(LXP "xilinx took %d loops\n", i);
+ break;
+ }
+ }
+
+ /* todo: add some error handling? */
+
+ /* clear mr */
+ lx_dsp_reg_write(chip, eReg_CSM, 0);
+
+ /* le xilinx ES peut ne pas etre encore pret, on attend. */
+ msleep(600);
+
+ return 0;
+}
+
+static int __devinit lx_init_xilinx_test(struct lx6464es *chip)
+{
+ u32 reg;
+
+ snd_printdd("->lx_init_xilinx_test\n");
+
+ /* TEST if we have access to Xilinx/MicroBlaze */
+ lx_dsp_reg_write(chip, eReg_CSM, 0);
+
+ reg = lx_dsp_reg_read(chip, eReg_CSM);
+
+ if (reg) {
+ snd_printk(KERN_ERR LXP "Problem: Reg_CSM %x.\n", reg);
+
+ /* PCI9056_SPACE0_REMAP */
+ lx_plx_reg_write(chip, ePLX_PCICR, 1);
+
+ reg = lx_dsp_reg_read(chip, eReg_CSM);
+ if (reg) {
+ snd_printk(KERN_ERR LXP "Error: Reg_CSM %x.\n", reg);
+ return -EAGAIN; /* seems to be appropriate */
+ }
+ }
+
+ snd_printd(LXP "Xilinx/MicroBlaze access test successful\n");
+
+ return 0;
+}
+
+/* initialize ethersound */
+static int __devinit lx_init_ethersound_config(struct lx6464es *chip)
+{
+ int i;
+ u32 orig_conf_es = lx_dsp_reg_read(chip, eReg_CONFES);
+
+ u32 default_conf_es = (64 << IOCR_OUTPUTS_OFFSET) |
+ (64 << IOCR_INPUTS_OFFSET) |
+ (FREQ_RATIO_SINGLE_MODE << FREQ_RATIO_OFFSET);
+
+ u32 conf_es = (orig_conf_es & CONFES_READ_PART_MASK)
+ | (default_conf_es & CONFES_WRITE_PART_MASK);
+
+ snd_printdd("->lx_init_ethersound\n");
+
+ chip->freq_ratio = FREQ_RATIO_SINGLE_MODE;
+
+ /*
+ * write it to the card !
+ * this actually kicks the ES xilinx, the first time since poweron.
+ * the MAC address in the Reg_ADMACESMSB Reg_ADMACESLSB registers
+ * is not ready before this is done, and the bit 2 in Reg_CSES is set.
+ * */
+ lx_dsp_reg_write(chip, eReg_CONFES, conf_es);
+
+ for (i = 0; i != 1000; ++i) {
+ if (lx_dsp_reg_read(chip, eReg_CSES) & 4) {
+ snd_printd(LXP "ethersound initialized after %dms\n",
+ i);
+ goto ethersound_initialized;
+ }
+ msleep(1);
+ }
+ snd_printk(KERN_WARNING LXP
+ "ethersound could not be initialized after %dms\n", i);
+ return -ETIMEDOUT;
+
+ ethersound_initialized:
+ snd_printd(LXP "ethersound initialized\n");
+ return 0;
+}
+
+static int __devinit lx_init_get_version_features(struct lx6464es *chip)
+{
+ u32 dsp_version;
+
+ int err;
+
+ snd_printdd("->lx_init_get_version_features\n");
+
+ err = lx_dsp_get_version(chip, &dsp_version);
+
+ if (err == 0) {
+ u32 freq;
+
+ snd_printk(LXP "DSP version: V%02d.%02d #%d\n",
+ (dsp_version>>16) & 0xff, (dsp_version>>8) & 0xff,
+ dsp_version & 0xff);
+
+ /* later: what firmware version do we expect? */
+
+ /* retrieve Play/Rec features */
+ /* done here because we may have to handle alternate
+ * DSP files. */
+ /* later */
+
+ /* init the EtherSound sample rate */
+ err = lx_dsp_get_clock_frequency(chip, &freq);
+ if (err == 0)
+ chip->board_sample_rate = freq;
+ snd_printd(LXP "actual clock frequency %d\n", freq);
+ } else {
+ snd_printk(KERN_ERR LXP "DSP corrupted \n");
+ err = -EAGAIN;
+ }
+
+ return err;
+}
+
+static int lx_set_granularity(struct lx6464es *chip, u32 gran)
+{
+ int err = 0;
+ u32 snapped_gran = MICROBLAZE_IBL_MIN;
+
+ snd_printdd("->lx_set_granularity\n");
+
+ /* blocksize is a power of 2 */
+ while ((snapped_gran < gran) &&
+ (snapped_gran < MICROBLAZE_IBL_MAX)) {
+ snapped_gran *= 2;
+ }
+
+ if (snapped_gran == chip->pcm_granularity)
+ return 0;
+
+ err = lx_dsp_set_granularity(chip, snapped_gran);
+ if (err < 0) {
+ snd_printk(KERN_WARNING LXP "could not set granularity\n");
+ err = -EAGAIN;
+ }
+
+ if (snapped_gran != gran)
+ snd_printk(LXP "snapped blocksize to %d\n", snapped_gran);
+
+ snd_printd(LXP "set blocksize on board %d\n", snapped_gran);
+ chip->pcm_granularity = snapped_gran;
+
+ return err;
+}
+
+/* initialize and test the xilinx dsp chip */
+static int __devinit lx_init_dsp(struct lx6464es *chip)
+{
+ int err;
+ u8 mac_address[6];
+ int i;
+
+ snd_printdd("->lx_init_dsp\n");
+
+ snd_printd(LXP "initialize board\n");
+ err = lx_init_xilinx_reset(chip);
+ if (err)
+ return err;
+
+ snd_printd(LXP "testing board\n");
+ err = lx_init_xilinx_test(chip);
+ if (err)
+ return err;
+
+ snd_printd(LXP "initialize ethersound configuration\n");
+ err = lx_init_ethersound_config(chip);
+ if (err)
+ return err;
+
+ lx_irq_enable(chip);
+
+ /** \todo the mac address should be ready by not, but it isn't,
+ * so we wait for it */
+ for (i = 0; i != 1000; ++i) {
+ err = lx_dsp_get_mac(chip, mac_address);
+ if (err)
+ return err;
+ if (mac_address[0] || mac_address[1] || mac_address[2] ||
+ mac_address[3] || mac_address[4] || mac_address[5])
+ goto mac_ready;
+ msleep(1);
+ }
+ return -ETIMEDOUT;
+
+mac_ready:
+ snd_printd(LXP "mac address ready read after: %dms\n", i);
+ snd_printk(LXP "mac address: %02X.%02X.%02X.%02X.%02X.%02X\n",
+ mac_address[0], mac_address[1], mac_address[2],
+ mac_address[3], mac_address[4], mac_address[5]);
+
+ err = lx_init_get_version_features(chip);
+ if (err)
+ return err;
+
+ lx_set_granularity(chip, MICROBLAZE_IBL_DEFAULT);
+
+ chip->playback_mute = 0;
+
+ return err;
+}
+
+static struct snd_pcm_ops lx_ops_playback = {
+ .open = lx_pcm_open,
+ .close = lx_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .prepare = lx_pcm_prepare,
+ .hw_params = lx_pcm_hw_params_playback,
+ .hw_free = lx_pcm_hw_free,
+ .trigger = lx_pcm_trigger,
+ .pointer = lx_pcm_stream_pointer,
+};
+
+static struct snd_pcm_ops lx_ops_capture = {
+ .open = lx_pcm_open,
+ .close = lx_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .prepare = lx_pcm_prepare,
+ .hw_params = lx_pcm_hw_params_capture,
+ .hw_free = lx_pcm_hw_free,
+ .trigger = lx_pcm_trigger,
+ .pointer = lx_pcm_stream_pointer,
+};
+
+static int __devinit lx_pcm_create(struct lx6464es *chip)
+{
+ int err;
+ struct snd_pcm *pcm;
+
+ u32 size = 64 * /* channels */
+ 3 * /* 24 bit samples */
+ MAX_STREAM_BUFFER * /* periods */
+ MICROBLAZE_IBL_MAX * /* frames per period */
+ 2; /* duplex */
+
+ size = PAGE_ALIGN(size);
+
+ /* hardcoded device name & channel count */
+ err = snd_pcm_new(chip->card, (char *)card_name, 0,
+ 1, 1, &pcm);
+
+ pcm->private_data = chip;
+
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &lx_ops_playback);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &lx_ops_capture);
+
+ pcm->info_flags = 0;
+ strcpy(pcm->name, card_name);
+
+ err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci),
+ size, size);
+ if (err < 0)
+ return err;
+
+ chip->pcm = pcm;
+ chip->capture_stream.is_capture = 1;
+
+ return 0;
+}
+
+static int lx_control_playback_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 lx_control_playback_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct lx6464es *chip = snd_kcontrol_chip(kcontrol);
+ ucontrol->value.integer.value[0] = chip->playback_mute;
+ return 0;
+}
+
+static int lx_control_playback_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct lx6464es *chip = snd_kcontrol_chip(kcontrol);
+ int changed = 0;
+ int current_value = chip->playback_mute;
+
+ if (current_value != ucontrol->value.integer.value[0]) {
+ lx_level_unmute(chip, 0, !current_value);
+ chip->playback_mute = !current_value;
+ changed = 1;
+ }
+ return changed;
+}
+
+static struct snd_kcontrol_new lx_control_playback_switch __devinitdata = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "PCM Playback Switch",
+ .index = 0,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .private_value = 0,
+ .info = lx_control_playback_info,
+ .get = lx_control_playback_get,
+ .put = lx_control_playback_put
+};
+
+
+
+static void lx_proc_levels_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+{
+ u32 levels[64];
+ int err;
+ int i, j;
+ struct lx6464es *chip = entry->private_data;
+
+ snd_iprintf(buffer, "capture levels:\n");
+ err = lx_level_peaks(chip, 1, 64, levels);
+ if (err < 0)
+ return;
+
+ for (i = 0; i != 8; ++i) {
+ for (j = 0; j != 8; ++j)
+ snd_iprintf(buffer, "%08x ", levels[i*8+j]);
+ snd_iprintf(buffer, "\n");
+ }
+
+ snd_iprintf(buffer, "\nplayback levels:\n");
+
+ err = lx_level_peaks(chip, 0, 64, levels);
+ if (err < 0)
+ return;
+
+ for (i = 0; i != 8; ++i) {
+ for (j = 0; j != 8; ++j)
+ snd_iprintf(buffer, "%08x ", levels[i*8+j]);
+ snd_iprintf(buffer, "\n");
+ }
+
+ snd_iprintf(buffer, "\n");
+}
+
+static int __devinit lx_proc_create(struct snd_card *card, struct lx6464es *chip)
+{
+ struct snd_info_entry *entry;
+ int err = snd_card_proc_new(card, "levels", &entry);
+ if (err < 0)
+ return err;
+
+ snd_info_set_text_ops(entry, chip, lx_proc_levels_read);
+ return 0;
+}
+
+
+static int __devinit snd_lx6464es_create(struct snd_card *card,
+ struct pci_dev *pci,
+ struct lx6464es **rchip)
+{
+ struct lx6464es *chip;
+ int err;
+
+ static struct snd_device_ops ops = {
+ .dev_free = snd_lx6464es_dev_free,
+ };
+
+ snd_printdd("->snd_lx6464es_create\n");
+
+ *rchip = NULL;
+
+ /* enable PCI device */
+ err = pci_enable_device(pci);
+ if (err < 0)
+ return err;
+
+ pci_set_master(pci);
+
+ /* check if we can restrict PCI DMA transfers to 32 bits */
+ err = pci_set_dma_mask(pci, DMA_32BIT_MASK);
+ if (err < 0) {
+ snd_printk(KERN_ERR "architecture does not support "
+ "32bit PCI busmaster DMA\n");
+ pci_disable_device(pci);
+ return -ENXIO;
+ }
+
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL) {
+ err = -ENOMEM;
+ goto alloc_failed;
+ }
+
+ chip->card = card;
+ chip->pci = pci;
+ chip->irq = -1;
+
+ /* initialize synchronization structs */
+ spin_lock_init(&chip->lock);
+ spin_lock_init(&chip->msg_lock);
+ mutex_init(&chip->setup_mutex);
+ tasklet_init(&chip->trigger_tasklet, lx_trigger_tasklet,
+ (unsigned long)chip);
+ tasklet_init(&chip->tasklet_capture, lx_tasklet_capture,
+ (unsigned long)chip);
+ tasklet_init(&chip->tasklet_playback, lx_tasklet_playback,
+ (unsigned long)chip);
+
+ /* request resources */
+ err = pci_request_regions(pci, card_name);
+ if (err < 0)
+ goto request_regions_failed;
+
+ /* plx port */
+ chip->port_plx = pci_resource_start(pci, 1);
+ chip->port_plx_remapped = ioport_map(chip->port_plx,
+ pci_resource_len(pci, 1));
+
+ /* dsp port */
+ chip->port_dsp_bar = pci_ioremap_bar(pci, 2);
+
+ err = request_irq(pci->irq, lx_interrupt, IRQF_SHARED,
+ card_name, chip);
+ if (err) {
+ snd_printk(KERN_ERR LXP "unable to grab IRQ %d\n", pci->irq);
+ goto request_irq_failed;
+ }
+ chip->irq = pci->irq;
+
+ err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+ if (err < 0)
+ goto device_new_failed;
+
+ err = lx_init_dsp(chip);
+ if (err < 0) {
+ snd_printk(KERN_ERR LXP "error during DSP initialization\n");
+ return err;
+ }
+
+ err = lx_pcm_create(chip);
+ if (err < 0)
+ return err;
+
+ err = lx_proc_create(card, chip);
+ if (err < 0)
+ return err;
+
+ err = snd_ctl_add(card, snd_ctl_new1(&lx_control_playback_switch,
+ chip));
+ if (err < 0)
+ return err;
+
+ snd_card_set_dev(card, &pci->dev);
+
+ *rchip = chip;
+ return 0;
+
+device_new_failed:
+ free_irq(pci->irq, chip);
+
+request_irq_failed:
+ pci_release_regions(pci);
+
+request_regions_failed:
+ kfree(chip);
+
+alloc_failed:
+ pci_disable_device(pci);
+
+ return err;
+}
+
+static int __devinit snd_lx6464es_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
+{
+ static int dev;
+ struct snd_card *card;
+ struct lx6464es *chip;
+ int err;
+
+ snd_printdd("->snd_lx6464es_probe\n");
+
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+ if (!enable[dev]) {
+ dev++;
+ return -ENOENT;
+ }
+
+ err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+ if (err < 0)
+ return err;
+
+ err = snd_lx6464es_create(card, pci, &chip);
+ if (err < 0) {
+ snd_printk(KERN_ERR LXP "error during snd_lx6464es_create\n");
+ goto out_free;
+ }
+
+ strcpy(card->driver, "lx6464es");
+ strcpy(card->shortname, "Digigram LX6464ES");
+ sprintf(card->longname, "%s at 0x%lx, 0x%p, irq %i",
+ card->shortname, chip->port_plx,
+ chip->port_dsp_bar, chip->irq);
+
+ err = snd_card_register(card);
+ if (err < 0)
+ goto out_free;
+
+ snd_printdd(LXP "initialization successful\n");
+ pci_set_drvdata(pci, card);
+ dev++;
+ return 0;
+
+out_free:
+ snd_card_free(card);
+ return err;
+
+}
+
+static void __devexit snd_lx6464es_remove(struct pci_dev *pci)
+{
+ snd_card_free(pci_get_drvdata(pci));
+ pci_set_drvdata(pci, NULL);
+}
+
+
+static struct pci_driver driver = {
+ .name = "Digigram LX6464ES",
+ .id_table = snd_lx6464es_ids,
+ .probe = snd_lx6464es_probe,
+ .remove = __devexit_p(snd_lx6464es_remove),
+};
+
+
+/* module initialization */
+static int __init mod_init(void)
+{
+ return pci_register_driver(&driver);
+}
+
+static void __exit mod_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
+module_init(mod_init);
+module_exit(mod_exit);
diff --git a/sound/pci/lx6464es/lx6464es.h b/sound/pci/lx6464es/lx6464es.h
new file mode 100644
index 000000000000..012c010c8c89
--- /dev/null
+++ b/sound/pci/lx6464es/lx6464es.h
@@ -0,0 +1,114 @@
+/* -*- linux-c -*- *
+ *
+ * ALSA driver for the digigram lx6464es interface
+ *
+ * Copyright (c) 2009 Tim Blechmann <tim@klingt.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; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef LX6464ES_H
+#define LX6464ES_H
+
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+
+#include "lx_core.h"
+
+#define LXP "LX6464ES: "
+
+enum {
+ ES_cmd_free = 0, /* no command executing */
+ ES_cmd_processing = 1, /* execution of a read/write command */
+ ES_read_pending = 2, /* a asynchron read command is pending */
+ ES_read_finishing = 3, /* a read command has finished waiting (set by
+ * Interrupt or CancelIrp) */
+};
+
+enum lx_stream_status {
+ LX_STREAM_STATUS_FREE,
+/* LX_STREAM_STATUS_OPEN, */
+ LX_STREAM_STATUS_SCHEDULE_RUN,
+/* LX_STREAM_STATUS_STARTED, */
+ LX_STREAM_STATUS_RUNNING,
+ LX_STREAM_STATUS_SCHEDULE_STOP,
+/* LX_STREAM_STATUS_STOPPED, */
+/* LX_STREAM_STATUS_PAUSED */
+};
+
+
+struct lx_stream {
+ struct snd_pcm_substream *stream;
+ snd_pcm_uframes_t frame_pos;
+ enum lx_stream_status status; /* free, open, running, draining
+ * pause */
+ int is_capture:1;
+};
+
+
+struct lx6464es {
+ struct snd_card *card;
+ struct pci_dev *pci;
+ int irq;
+
+ spinlock_t lock; /* interrupt spinlock */
+ struct mutex setup_mutex; /* mutex used in hw_params, open
+ * and close */
+
+ struct tasklet_struct trigger_tasklet; /* trigger tasklet */
+ struct tasklet_struct tasklet_capture;
+ struct tasklet_struct tasklet_playback;
+
+ /* ports */
+ unsigned long port_plx; /* io port (size=256) */
+ void __iomem *port_plx_remapped; /* remapped plx port */
+ void __iomem *port_dsp_bar; /* memory port (32-bit,
+ * non-prefetchable,
+ * size=8K) */
+
+ /* messaging */
+ spinlock_t msg_lock; /* message spinlock */
+ atomic_t send_message_locked;
+ struct lx_rmh rmh;
+
+ /* configuration */
+ uint freq_ratio : 2;
+ uint playback_mute : 1;
+ uint hardware_running[2];
+ u32 board_sample_rate; /* sample rate read from
+ * board */
+ u32 sample_rate; /* our sample rate */
+ u16 pcm_granularity; /* board blocksize */
+
+ /* dma */
+ struct snd_dma_buffer capture_dma_buf;
+ struct snd_dma_buffer playback_dma_buf;
+
+ /* pcm */
+ struct snd_pcm *pcm;
+
+ /* streams */
+ struct lx_stream capture_stream;
+ struct lx_stream playback_stream;
+};
+
+
+#endif /* LX6464ES_H */
diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c
new file mode 100644
index 000000000000..5812780d6e89
--- /dev/null
+++ b/sound/pci/lx6464es/lx_core.c
@@ -0,0 +1,1444 @@
+/* -*- linux-c -*- *
+ *
+ * ALSA driver for the digigram lx6464es interface
+ * low-level interface
+ *
+ * Copyright (c) 2009 Tim Blechmann <tim@klingt.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; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/* #define RMH_DEBUG 1 */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+#include "lx6464es.h"
+#include "lx_core.h"
+
+/* low-level register access */
+
+static const unsigned long dsp_port_offsets[] = {
+ 0,
+ 0x400,
+ 0x401,
+ 0x402,
+ 0x403,
+ 0x404,
+ 0x405,
+ 0x406,
+ 0x407,
+ 0x408,
+ 0x409,
+ 0x40a,
+ 0x40b,
+ 0x40c,
+
+ 0x410,
+ 0x411,
+ 0x412,
+ 0x413,
+ 0x414,
+ 0x415,
+ 0x416,
+
+ 0x420,
+ 0x430,
+ 0x431,
+ 0x432,
+ 0x433,
+ 0x434,
+ 0x440
+};
+
+static void __iomem *lx_dsp_register(struct lx6464es *chip, int port)
+{
+ void __iomem *base_address = chip->port_dsp_bar;
+ return base_address + dsp_port_offsets[port]*4;
+}
+
+unsigned long lx_dsp_reg_read(struct lx6464es *chip, int port)
+{
+ void __iomem *address = lx_dsp_register(chip, port);
+ return ioread32(address);
+}
+
+void lx_dsp_reg_readbuf(struct lx6464es *chip, int port, u32 *data, u32 len)
+{
+ void __iomem *address = lx_dsp_register(chip, port);
+ memcpy_fromio(data, address, len*sizeof(u32));
+}
+
+
+void lx_dsp_reg_write(struct lx6464es *chip, int port, unsigned data)
+{
+ void __iomem *address = lx_dsp_register(chip, port);
+ iowrite32(data, address);
+}
+
+void lx_dsp_reg_writebuf(struct lx6464es *chip, int port, const u32 *data,
+ u32 len)
+{
+ void __iomem *address = lx_dsp_register(chip, port);
+ memcpy_toio(address, data, len*sizeof(u32));
+}
+
+
+static const unsigned long plx_port_offsets[] = {
+ 0x04,
+ 0x40,
+ 0x44,
+ 0x48,
+ 0x4c,
+ 0x50,
+ 0x54,
+ 0x58,
+ 0x5c,
+ 0x64,
+ 0x68,
+ 0x6C
+};
+
+static void __iomem *lx_plx_register(struct lx6464es *chip, int port)
+{
+ void __iomem *base_address = chip->port_plx_remapped;
+ return base_address + plx_port_offsets[port];
+}
+
+unsigned long lx_plx_reg_read(struct lx6464es *chip, int port)
+{
+ void __iomem *address = lx_plx_register(chip, port);
+ return ioread32(address);
+}
+
+void lx_plx_reg_write(struct lx6464es *chip, int port, u32 data)
+{
+ void __iomem *address = lx_plx_register(chip, port);
+ iowrite32(data, address);
+}
+
+u32 lx_plx_mbox_read(struct lx6464es *chip, int mbox_nr)
+{
+ int index;
+
+ switch (mbox_nr) {
+ case 1:
+ index = ePLX_MBOX1; break;
+ case 2:
+ index = ePLX_MBOX2; break;
+ case 3:
+ index = ePLX_MBOX3; break;
+ case 4:
+ index = ePLX_MBOX4; break;
+ case 5:
+ index = ePLX_MBOX5; break;
+ case 6:
+ index = ePLX_MBOX6; break;
+ case 7:
+ index = ePLX_MBOX7; break;
+ case 0: /* reserved for HF flags */
+ snd_BUG();
+ default:
+ return 0xdeadbeef;
+ }
+
+ return lx_plx_reg_read(chip, index);
+}
+
+int lx_plx_mbox_write(struct lx6464es *chip, int mbox_nr, u32 value)
+{
+ int index = -1;
+
+ switch (mbox_nr) {
+ case 1:
+ index = ePLX_MBOX1; break;
+ case 3:
+ index = ePLX_MBOX3; break;
+ case 4:
+ index = ePLX_MBOX4; break;
+ case 5:
+ index = ePLX_MBOX5; break;
+ case 6:
+ index = ePLX_MBOX6; break;
+ case 7:
+ index = ePLX_MBOX7; break;
+ case 0: /* reserved for HF flags */
+ case 2: /* reserved for Pipe States
+ * the DSP keeps an image of it */
+ snd_BUG();
+ return -EBADRQC;
+ }
+
+ lx_plx_reg_write(chip, index, value);
+ return 0;
+}
+
+
+/* rmh */
+
+#ifdef CONFIG_SND_DEBUG
+#define CMD_NAME(a) a
+#else
+#define CMD_NAME(a) NULL
+#endif
+
+#define Reg_CSM_MR 0x00000002
+#define Reg_CSM_MC 0x00000001
+
+struct dsp_cmd_info {
+ u32 dcCodeOp; /* Op Code of the command (usually 1st 24-bits
+ * word).*/
+ u16 dcCmdLength; /* Command length in words of 24 bits.*/
+ u16 dcStatusType; /* Status type: 0 for fixed length, 1 for
+ * random. */
+ u16 dcStatusLength; /* Status length (if fixed).*/
+ char *dcOpName;
+};
+
+/*
+ Initialization and control data for the Microblaze interface
+ - OpCode:
+ the opcode field of the command set at the proper offset
+ - CmdLength
+ the number of command words
+ - StatusType
+ offset in the status registers: 0 means that the return value may be
+ different from 0, and must be read
+ - StatusLength
+ the number of status words (in addition to the return value)
+*/
+
+static struct dsp_cmd_info dsp_commands[] =
+{
+ { (CMD_00_INFO_DEBUG << OPCODE_OFFSET) , 1 /*custom*/
+ , 1 , 0 /**/ , CMD_NAME("INFO_DEBUG") },
+ { (CMD_01_GET_SYS_CFG << OPCODE_OFFSET) , 1 /**/
+ , 1 , 2 /**/ , CMD_NAME("GET_SYS_CFG") },
+ { (CMD_02_SET_GRANULARITY << OPCODE_OFFSET) , 1 /**/
+ , 1 , 0 /**/ , CMD_NAME("SET_GRANULARITY") },
+ { (CMD_03_SET_TIMER_IRQ << OPCODE_OFFSET) , 1 /**/
+ , 1 , 0 /**/ , CMD_NAME("SET_TIMER_IRQ") },
+ { (CMD_04_GET_EVENT << OPCODE_OFFSET) , 1 /**/
+ , 1 , 0 /*up to 10*/ , CMD_NAME("GET_EVENT") },
+ { (CMD_05_GET_PIPES << OPCODE_OFFSET) , 1 /**/
+ , 1 , 2 /*up to 4*/ , CMD_NAME("GET_PIPES") },
+ { (CMD_06_ALLOCATE_PIPE << OPCODE_OFFSET) , 1 /**/
+ , 0 , 0 /**/ , CMD_NAME("ALLOCATE_PIPE") },
+ { (CMD_07_RELEASE_PIPE << OPCODE_OFFSET) , 1 /**/
+ , 0 , 0 /**/ , CMD_NAME("RELEASE_PIPE") },
+ { (CMD_08_ASK_BUFFERS << OPCODE_OFFSET) , 1 /**/
+ , 1 , MAX_STREAM_BUFFER , CMD_NAME("ASK_BUFFERS") },
+ { (CMD_09_STOP_PIPE << OPCODE_OFFSET) , 1 /**/
+ , 0 , 0 /*up to 2*/ , CMD_NAME("STOP_PIPE") },
+ { (CMD_0A_GET_PIPE_SPL_COUNT << OPCODE_OFFSET) , 1 /**/
+ , 1 , 1 /*up to 2*/ , CMD_NAME("GET_PIPE_SPL_COUNT") },
+ { (CMD_0B_TOGGLE_PIPE_STATE << OPCODE_OFFSET) , 1 /*up to 5*/
+ , 1 , 0 /**/ , CMD_NAME("TOGGLE_PIPE_STATE") },
+ { (CMD_0C_DEF_STREAM << OPCODE_OFFSET) , 1 /*up to 4*/
+ , 1 , 0 /**/ , CMD_NAME("DEF_STREAM") },
+ { (CMD_0D_SET_MUTE << OPCODE_OFFSET) , 3 /**/
+ , 1 , 0 /**/ , CMD_NAME("SET_MUTE") },
+ { (CMD_0E_GET_STREAM_SPL_COUNT << OPCODE_OFFSET) , 1/**/
+ , 1 , 2 /**/ , CMD_NAME("GET_STREAM_SPL_COUNT") },
+ { (CMD_0F_UPDATE_BUFFER << OPCODE_OFFSET) , 3 /*up to 4*/
+ , 0 , 1 /**/ , CMD_NAME("UPDATE_BUFFER") },
+ { (CMD_10_GET_BUFFER << OPCODE_OFFSET) , 1 /**/
+ , 1 , 4 /**/ , CMD_NAME("GET_BUFFER") },
+ { (CMD_11_CANCEL_BUFFER << OPCODE_OFFSET) , 1 /**/
+ , 1 , 1 /*up to 4*/ , CMD_NAME("CANCEL_BUFFER") },
+ { (CMD_12_GET_PEAK << OPCODE_OFFSET) , 1 /**/
+ , 1 , 1 /**/ , CMD_NAME("GET_PEAK") },
+ { (CMD_13_SET_STREAM_STATE << OPCODE_OFFSET) , 1 /**/
+ , 1 , 0 /**/ , CMD_NAME("SET_STREAM_STATE") },
+};
+
+static void lx_message_init(struct lx_rmh *rmh, enum cmd_mb_opcodes cmd)
+{
+ snd_BUG_ON(cmd >= CMD_14_INVALID);
+
+ rmh->cmd[0] = dsp_commands[cmd].dcCodeOp;
+ rmh->cmd_len = dsp_commands[cmd].dcCmdLength;
+ rmh->stat_len = dsp_commands[cmd].dcStatusLength;
+ rmh->dsp_stat = dsp_commands[cmd].dcStatusType;
+ rmh->cmd_idx = cmd;
+ memset(&rmh->cmd[1], 0, (REG_CRM_NUMBER - 1) * sizeof(u32));
+
+#ifdef CONFIG_SND_DEBUG
+ memset(rmh->stat, 0, REG_CRM_NUMBER * sizeof(u32));
+#endif
+#ifdef RMH_DEBUG
+ rmh->cmd_idx = cmd;
+#endif
+}
+
+#ifdef RMH_DEBUG
+#define LXRMH "lx6464es rmh: "
+static void lx_message_dump(struct lx_rmh *rmh)
+{
+ u8 idx = rmh->cmd_idx;
+ int i;
+
+ snd_printk(LXRMH "command %s\n", dsp_commands[idx].dcOpName);
+
+ for (i = 0; i != rmh->cmd_len; ++i)
+ snd_printk(LXRMH "\tcmd[%d] %08x\n", i, rmh->cmd[i]);
+
+ for (i = 0; i != rmh->stat_len; ++i)
+ snd_printk(LXRMH "\tstat[%d]: %08x\n", i, rmh->stat[i]);
+ snd_printk("\n");
+}
+#else
+static inline void lx_message_dump(struct lx_rmh *rmh)
+{}
+#endif
+
+
+
+/* sleep 500 - 100 = 400 times 100us -> the timeout is >= 40 ms */
+#define XILINX_TIMEOUT_MS 40
+#define XILINX_POLL_NO_SLEEP 100
+#define XILINX_POLL_ITERATIONS 150
+
+#if 0 /* not used now */
+static int lx_message_send(struct lx6464es *chip, struct lx_rmh *rmh)
+{
+ u32 reg = ED_DSP_TIMED_OUT;
+ int dwloop;
+ int answer_received;
+
+ if (lx_dsp_reg_read(chip, eReg_CSM) & (Reg_CSM_MC | Reg_CSM_MR)) {
+ snd_printk(KERN_ERR LXP "PIOSendMessage eReg_CSM %x\n", reg);
+ return -EBUSY;
+ }
+
+ /* write command */
+ lx_dsp_reg_writebuf(chip, eReg_CRM1, rmh->cmd, rmh->cmd_len);
+
+ snd_BUG_ON(atomic_read(&chip->send_message_locked) != 0);
+ atomic_set(&chip->send_message_locked, 1);
+
+ /* MicoBlaze gogogo */
+ lx_dsp_reg_write(chip, eReg_CSM, Reg_CSM_MC);
+
+ /* wait for interrupt to answer */
+ for (dwloop = 0; dwloop != XILINX_TIMEOUT_MS; ++dwloop) {
+ answer_received = atomic_read(&chip->send_message_locked);
+ if (answer_received == 0)
+ break;
+ msleep(1);
+ }
+
+ if (answer_received == 0) {
+ /* in Debug mode verify Reg_CSM_MR */
+ snd_BUG_ON(!(lx_dsp_reg_read(chip, eReg_CSM) & Reg_CSM_MR));
+
+ /* command finished, read status */
+ if (rmh->dsp_stat == 0)
+ reg = lx_dsp_reg_read(chip, eReg_CRM1);
+ else
+ reg = 0;
+ } else {
+ int i;
+ snd_printk(KERN_WARNING LXP "TIMEOUT lx_message_send! "
+ "Interrupts disabled?\n");
+
+ /* attente bit Reg_CSM_MR */
+ for (i = 0; i != XILINX_POLL_ITERATIONS; i++) {
+ if ((lx_dsp_reg_read(chip, eReg_CSM) & Reg_CSM_MR)) {
+ if (rmh->dsp_stat == 0)
+ reg = lx_dsp_reg_read(chip, eReg_CRM1);
+ else
+ reg = 0;
+ goto polling_successful;
+ }
+
+ if (i > XILINX_POLL_NO_SLEEP)
+ msleep(1);
+ }
+ snd_printk(KERN_WARNING LXP "TIMEOUT lx_message_send! "
+ "polling failed\n");
+
+polling_successful:
+ atomic_set(&chip->send_message_locked, 0);
+ }
+
+ if ((reg & ERROR_VALUE) == 0) {
+ /* read response */
+ if (rmh->stat_len) {
+ snd_BUG_ON(rmh->stat_len >= (REG_CRM_NUMBER-1));
+
+ lx_dsp_reg_readbuf(chip, eReg_CRM2, rmh->stat,
+ rmh->stat_len);
+ }
+ } else
+ snd_printk(KERN_WARNING LXP "lx_message_send: error_value %x\n",
+ reg);
+
+ /* clear Reg_CSM_MR */
+ lx_dsp_reg_write(chip, eReg_CSM, 0);
+
+ switch (reg) {
+ case ED_DSP_TIMED_OUT:
+ snd_printk(KERN_WARNING LXP "lx_message_send: dsp timeout\n");
+ return -ETIMEDOUT;
+
+ case ED_DSP_CRASHED:
+ snd_printk(KERN_WARNING LXP "lx_message_send: dsp crashed\n");
+ return -EAGAIN;
+ }
+
+ lx_message_dump(rmh);
+ return 0;
+}
+#endif /* not used now */
+
+static int lx_message_send_atomic(struct lx6464es *chip, struct lx_rmh *rmh)
+{
+ u32 reg = ED_DSP_TIMED_OUT;
+ int dwloop;
+
+ if (lx_dsp_reg_read(chip, eReg_CSM) & (Reg_CSM_MC | Reg_CSM_MR)) {
+ snd_printk(KERN_ERR LXP "PIOSendMessage eReg_CSM %x\n", reg);
+ return -EBUSY;
+ }
+
+ /* write command */
+ lx_dsp_reg_writebuf(chip, eReg_CRM1, rmh->cmd, rmh->cmd_len);
+
+ /* MicoBlaze gogogo */
+ lx_dsp_reg_write(chip, eReg_CSM, Reg_CSM_MC);
+
+ /* wait for interrupt to answer */
+ for (dwloop = 0; dwloop != XILINX_TIMEOUT_MS * 1000; ++dwloop) {
+ if (lx_dsp_reg_read(chip, eReg_CSM) & Reg_CSM_MR) {
+ if (rmh->dsp_stat == 0)
+ reg = lx_dsp_reg_read(chip, eReg_CRM1);
+ else
+ reg = 0;
+ goto polling_successful;
+ } else
+ udelay(1);
+ }
+ snd_printk(KERN_WARNING LXP "TIMEOUT lx_message_send_atomic! "
+ "polling failed\n");
+
+polling_successful:
+ if ((reg & ERROR_VALUE) == 0) {
+ /* read response */
+ if (rmh->stat_len) {
+ snd_BUG_ON(rmh->stat_len >= (REG_CRM_NUMBER-1));
+ lx_dsp_reg_readbuf(chip, eReg_CRM2, rmh->stat,
+ rmh->stat_len);
+ }
+ } else
+ snd_printk(LXP "rmh error: %08x\n", reg);
+
+ /* clear Reg_CSM_MR */
+ lx_dsp_reg_write(chip, eReg_CSM, 0);
+
+ switch (reg) {
+ case ED_DSP_TIMED_OUT:
+ snd_printk(KERN_WARNING LXP "lx_message_send: dsp timeout\n");
+ return -ETIMEDOUT;
+
+ case ED_DSP_CRASHED:
+ snd_printk(KERN_WARNING LXP "lx_message_send: dsp crashed\n");
+ return -EAGAIN;
+ }
+
+ lx_message_dump(rmh);
+
+ return reg;
+}
+
+
+/* low-level dsp access */
+int __devinit lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version)
+{
+ u16 ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->msg_lock, flags);
+
+ lx_message_init(&chip->rmh, CMD_01_GET_SYS_CFG);
+ ret = lx_message_send_atomic(chip, &chip->rmh);
+
+ *rdsp_version = chip->rmh.stat[1];
+ spin_unlock_irqrestore(&chip->msg_lock, flags);
+ return ret;
+}
+
+int lx_dsp_get_clock_frequency(struct lx6464es *chip, u32 *rfreq)
+{
+ u16 ret = 0;
+ unsigned long flags;
+ u32 freq_raw = 0;
+ u32 freq = 0;
+ u32 frequency = 0;
+
+ spin_lock_irqsave(&chip->msg_lock, flags);
+
+ lx_message_init(&chip->rmh, CMD_01_GET_SYS_CFG);
+ ret = lx_message_send_atomic(chip, &chip->rmh);
+
+ if (ret == 0) {
+ freq_raw = chip->rmh.stat[0] >> FREQ_FIELD_OFFSET;
+ freq = freq_raw & XES_FREQ_COUNT8_MASK;
+
+ if ((freq < XES_FREQ_COUNT8_48_MAX) ||
+ (freq > XES_FREQ_COUNT8_44_MIN))
+ frequency = 0; /* unknown */
+ else if (freq >= XES_FREQ_COUNT8_44_MAX)
+ frequency = 44100;
+ else
+ frequency = 48000;
+ }
+
+ spin_unlock_irqrestore(&chip->msg_lock, flags);
+
+ *rfreq = frequency * chip->freq_ratio;
+
+ return ret;
+}
+
+int lx_dsp_get_mac(struct lx6464es *chip, u8 *mac_address)
+{
+ u32 macmsb, maclsb;
+
+ macmsb = lx_dsp_reg_read(chip, eReg_ADMACESMSB) & 0x00FFFFFF;
+ maclsb = lx_dsp_reg_read(chip, eReg_ADMACESLSB) & 0x00FFFFFF;
+
+ /* todo: endianess handling */
+ mac_address[5] = ((u8 *)(&maclsb))[0];
+ mac_address[4] = ((u8 *)(&maclsb))[1];
+ mac_address[3] = ((u8 *)(&maclsb))[2];
+ mac_address[2] = ((u8 *)(&macmsb))[0];
+ mac_address[1] = ((u8 *)(&macmsb))[1];
+ mac_address[0] = ((u8 *)(&macmsb))[2];
+
+ return 0;
+}
+
+
+int lx_dsp_set_granularity(struct lx6464es *chip, u32 gran)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&chip->msg_lock, flags);
+
+ lx_message_init(&chip->rmh, CMD_02_SET_GRANULARITY);
+ chip->rmh.cmd[0] |= gran;
+
+ ret = lx_message_send_atomic(chip, &chip->rmh);
+ spin_unlock_irqrestore(&chip->msg_lock, flags);
+ return ret;
+}
+
+int lx_dsp_read_async_events(struct lx6464es *chip, u32 *data)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&chip->msg_lock, flags);
+
+ lx_message_init(&chip->rmh, CMD_04_GET_EVENT);
+ chip->rmh.stat_len = 9; /* we don't necessarily need the full length */
+
+ ret = lx_message_send_atomic(chip, &chip->rmh);
+
+ if (!ret)
+ memcpy(data, chip->rmh.stat, chip->rmh.stat_len * sizeof(u32));
+
+ spin_unlock_irqrestore(&chip->msg_lock, flags);
+ return ret;
+}
+
+#define CSES_TIMEOUT 100 /* microseconds */
+#define CSES_CE 0x0001
+#define CSES_BROADCAST 0x0002
+#define CSES_UPDATE_LDSV 0x0004
+
+int lx_dsp_es_check_pipeline(struct lx6464es *chip)
+{
+ int i;
+
+ for (i = 0; i != CSES_TIMEOUT; ++i) {
+ /*
+ * le bit CSES_UPDATE_LDSV est à 1 dés que le macprog
+ * est pret. il re-passe à 0 lorsque le premier read a
+ * été fait. pour l'instant on retire le test car ce bit
+ * passe a 1 environ 200 à 400 ms aprés que le registre
+ * confES à été écrit (kick du xilinx ES).
+ *
+ * On ne teste que le bit CE.
+ * */
+
+ u32 cses = lx_dsp_reg_read(chip, eReg_CSES);
+
+ if ((cses & CSES_CE) == 0)
+ return 0;
+
+ udelay(1);
+ }
+
+ return -ETIMEDOUT;
+}
+
+
+#define PIPE_INFO_TO_CMD(capture, pipe) \
+ ((u32)((u32)(pipe) | ((capture) ? ID_IS_CAPTURE : 0L)) << ID_OFFSET)
+
+
+
+/* low-level pipe handling */
+int lx_pipe_allocate(struct lx6464es *chip, u32 pipe, int is_capture,
+ int channels)
+{
+ int err;
+ unsigned long flags;
+
+ u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
+
+ spin_lock_irqsave(&chip->msg_lock, flags);
+ lx_message_init(&chip->rmh, CMD_06_ALLOCATE_PIPE);
+
+ chip->rmh.cmd[0] |= pipe_cmd;
+ chip->rmh.cmd[0] |= channels;
+
+ err = lx_message_send_atomic(chip, &chip->rmh);
+ spin_unlock_irqrestore(&chip->msg_lock, flags);
+
+ if (err != 0)
+ snd_printk(KERN_ERR "lx6464es: could not allocate pipe\n");
+
+ return err;
+}
+
+int lx_pipe_release(struct lx6464es *chip, u32 pipe, int is_capture)
+{
+ int err;
+ unsigned long flags;
+
+ u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
+
+ spin_lock_irqsave(&chip->msg_lock, flags);
+ lx_message_init(&chip->rmh, CMD_07_RELEASE_PIPE);
+
+ chip->rmh.cmd[0] |= pipe_cmd;
+
+ err = lx_message_send_atomic(chip, &chip->rmh);
+ spin_unlock_irqrestore(&chip->msg_lock, flags);
+
+ return err;
+}
+
+int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture,
+ u32 *r_needed, u32 *r_freed, u32 *size_array)
+{
+ int err;
+ unsigned long flags;
+
+ u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
+
+#ifdef CONFIG_SND_DEBUG
+ if (size_array)
+ memset(size_array, 0, sizeof(u32)*MAX_STREAM_BUFFER);
+#endif
+
+ *r_needed = 0;
+ *r_freed = 0;
+
+ spin_lock_irqsave(&chip->msg_lock, flags);
+ lx_message_init(&chip->rmh, CMD_08_ASK_BUFFERS);
+
+ chip->rmh.cmd[0] |= pipe_cmd;
+
+ err = lx_message_send_atomic(chip, &chip->rmh);
+
+ if (!err) {
+ int i;
+ for (i = 0; i < MAX_STREAM_BUFFER; ++i) {
+ u32 stat = chip->rmh.stat[i];
+ if (stat & (BF_EOB << BUFF_FLAGS_OFFSET)) {
+ /* finished */
+ *r_freed += 1;
+ if (size_array)
+ size_array[i] = stat & MASK_DATA_SIZE;
+ } else if ((stat & (BF_VALID << BUFF_FLAGS_OFFSET))
+ == 0)
+ /* free */
+ *r_needed += 1;
+ }
+
+#if 0
+ snd_printdd(LXP "CMD_08_ASK_BUFFERS: needed %d, freed %d\n",
+ *r_needed, *r_freed);
+ for (i = 0; i < MAX_STREAM_BUFFER; ++i) {
+ for (i = 0; i != chip->rmh.stat_len; ++i)
+ snd_printdd(" stat[%d]: %x, %x\n", i,
+ chip->rmh.stat[i],
+ chip->rmh.stat[i] & MASK_DATA_SIZE);
+ }
+#endif
+ }
+
+ spin_unlock_irqrestore(&chip->msg_lock, flags);
+ return err;
+}
+
+
+int lx_pipe_stop(struct lx6464es *chip, u32 pipe, int is_capture)
+{
+ int err;
+ unsigned long flags;
+
+ u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
+
+ spin_lock_irqsave(&chip->msg_lock, flags);
+ lx_message_init(&chip->rmh, CMD_09_STOP_PIPE);
+
+ chip->rmh.cmd[0] |= pipe_cmd;
+
+ err = lx_message_send_atomic(chip, &chip->rmh);
+
+ spin_unlock_irqrestore(&chip->msg_lock, flags);
+ return err;
+}
+
+static int lx_pipe_toggle_state(struct lx6464es *chip, u32 pipe, int is_capture)
+{
+ int err;
+ unsigned long flags;
+
+ u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
+
+ spin_lock_irqsave(&chip->msg_lock, flags);
+ lx_message_init(&chip->rmh, CMD_0B_TOGGLE_PIPE_STATE);
+
+ chip->rmh.cmd[0] |= pipe_cmd;
+
+ err = lx_message_send_atomic(chip, &chip->rmh);
+
+ spin_unlock_irqrestore(&chip->msg_lock, flags);
+ return err;
+}
+
+
+int lx_pipe_start(struct lx6464es *chip, u32 pipe, int is_capture)
+{
+ int err;
+
+ err = lx_pipe_wait_for_idle(chip, pipe, is_capture);
+ if (err < 0)
+ return err;
+
+ err = lx_pipe_toggle_state(chip, pipe, is_capture);
+
+ return err;
+}
+
+int lx_pipe_pause(struct lx6464es *chip, u32 pipe, int is_capture)
+{
+ int err = 0;
+
+ err = lx_pipe_wait_for_start(chip, pipe, is_capture);
+ if (err < 0)
+ return err;
+
+ err = lx_pipe_toggle_state(chip, pipe, is_capture);
+
+ return err;
+}
+
+
+int lx_pipe_sample_count(struct lx6464es *chip, u32 pipe, int is_capture,
+ u64 *rsample_count)
+{
+ int err;
+ unsigned long flags;
+
+ u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
+
+ spin_lock_irqsave(&chip->msg_lock, flags);
+ lx_message_init(&chip->rmh, CMD_0A_GET_PIPE_SPL_COUNT);
+
+ chip->rmh.cmd[0] |= pipe_cmd;
+ chip->rmh.stat_len = 2; /* need all words here! */
+
+ err = lx_message_send_atomic(chip, &chip->rmh); /* don't sleep! */
+
+ if (err != 0)
+ snd_printk(KERN_ERR
+ "lx6464es: could not query pipe's sample count\n");
+ else {
+ *rsample_count = ((u64)(chip->rmh.stat[0] & MASK_SPL_COUNT_HI)
+ << 24) /* hi part */
+ + chip->rmh.stat[1]; /* lo part */
+ }
+
+ spin_unlock_irqrestore(&chip->msg_lock, flags);
+ return err;
+}
+
+int lx_pipe_state(struct lx6464es *chip, u32 pipe, int is_capture, u16 *rstate)
+{
+ int err;
+ unsigned long flags;
+
+ u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
+
+ spin_lock_irqsave(&chip->msg_lock, flags);
+ lx_message_init(&chip->rmh, CMD_0A_GET_PIPE_SPL_COUNT);
+
+ chip->rmh.cmd[0] |= pipe_cmd;
+
+ err = lx_message_send_atomic(chip, &chip->rmh);
+
+ if (err != 0)
+ snd_printk(KERN_ERR "lx6464es: could not query pipe's state\n");
+ else
+ *rstate = (chip->rmh.stat[0] >> PSTATE_OFFSET) & 0x0F;
+
+ spin_unlock_irqrestore(&chip->msg_lock, flags);
+ return err;
+}
+
+static int lx_pipe_wait_for_state(struct lx6464es *chip, u32 pipe,
+ int is_capture, u16 state)
+{
+ int i;
+
+ /* max 2*PCMOnlyGranularity = 2*1024 at 44100 = < 50 ms:
+ * timeout 50 ms */
+ for (i = 0; i != 50; ++i) {
+ u16 current_state;
+ int err = lx_pipe_state(chip, pipe, is_capture, &current_state);
+
+ if (err < 0)
+ return err;
+
+ if (current_state == state)
+ return 0;
+
+ mdelay(1);
+ }
+
+ return -ETIMEDOUT;
+}
+
+int lx_pipe_wait_for_start(struct lx6464es *chip, u32 pipe, int is_capture)
+{
+ return lx_pipe_wait_for_state(chip, pipe, is_capture, PSTATE_RUN);
+}
+
+int lx_pipe_wait_for_idle(struct lx6464es *chip, u32 pipe, int is_capture)
+{
+ return lx_pipe_wait_for_state(chip, pipe, is_capture, PSTATE_IDLE);
+}
+
+/* low-level stream handling */
+int lx_stream_set_state(struct lx6464es *chip, u32 pipe,
+ int is_capture, enum stream_state_t state)
+{
+ int err;
+ unsigned long flags;
+
+ u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
+
+ spin_lock_irqsave(&chip->msg_lock, flags);
+ lx_message_init(&chip->rmh, CMD_13_SET_STREAM_STATE);
+
+ chip->rmh.cmd[0] |= pipe_cmd;
+ chip->rmh.cmd[0] |= state;
+
+ err = lx_message_send_atomic(chip, &chip->rmh);
+ spin_unlock_irqrestore(&chip->msg_lock, flags);
+
+ return err;
+}
+
+int lx_stream_set_format(struct lx6464es *chip, struct snd_pcm_runtime *runtime,
+ u32 pipe, int is_capture)
+{
+ int err;
+ unsigned long flags;
+
+ u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
+
+ u32 channels = runtime->channels;
+
+ if (runtime->channels != channels)
+ snd_printk(KERN_ERR LXP "channel count mismatch: %d vs %d",
+ runtime->channels, channels);
+
+ spin_lock_irqsave(&chip->msg_lock, flags);
+ lx_message_init(&chip->rmh, CMD_0C_DEF_STREAM);
+
+ chip->rmh.cmd[0] |= pipe_cmd;
+
+ if (runtime->sample_bits == 16)
+ /* 16 bit format */
+ chip->rmh.cmd[0] |= (STREAM_FMT_16b << STREAM_FMT_OFFSET);
+
+ if (snd_pcm_format_little_endian(runtime->format))
+ /* little endian/intel format */
+ chip->rmh.cmd[0] |= (STREAM_FMT_intel << STREAM_FMT_OFFSET);
+
+ chip->rmh.cmd[0] |= channels-1;
+
+ err = lx_message_send_atomic(chip, &chip->rmh);
+ spin_unlock_irqrestore(&chip->msg_lock, flags);
+
+ return err;
+}
+
+int lx_stream_state(struct lx6464es *chip, u32 pipe, int is_capture,
+ int *rstate)
+{
+ int err;
+ unsigned long flags;
+
+ u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
+
+ spin_lock_irqsave(&chip->msg_lock, flags);
+ lx_message_init(&chip->rmh, CMD_0E_GET_STREAM_SPL_COUNT);
+
+ chip->rmh.cmd[0] |= pipe_cmd;
+
+ err = lx_message_send_atomic(chip, &chip->rmh);
+
+ *rstate = (chip->rmh.stat[0] & SF_START) ? START_STATE : PAUSE_STATE;
+
+ spin_unlock_irqrestore(&chip->msg_lock, flags);
+ return err;
+}
+
+int lx_stream_sample_position(struct lx6464es *chip, u32 pipe, int is_capture,
+ u64 *r_bytepos)
+{
+ int err;
+ unsigned long flags;
+
+ u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
+
+ spin_lock_irqsave(&chip->msg_lock, flags);
+ lx_message_init(&chip->rmh, CMD_0E_GET_STREAM_SPL_COUNT);
+
+ chip->rmh.cmd[0] |= pipe_cmd;
+
+ err = lx_message_send_atomic(chip, &chip->rmh);
+
+ *r_bytepos = ((u64) (chip->rmh.stat[0] & MASK_SPL_COUNT_HI)
+ << 32) /* hi part */
+ + chip->rmh.stat[1]; /* lo part */
+
+ spin_unlock_irqrestore(&chip->msg_lock, flags);
+ return err;
+}
+
+/* low-level buffer handling */
+int lx_buffer_give(struct lx6464es *chip, u32 pipe, int is_capture,
+ u32 buffer_size, u32 buf_address_lo, u32 buf_address_hi,
+ u32 *r_buffer_index)
+{
+ int err;
+ unsigned long flags;
+
+ u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
+
+ spin_lock_irqsave(&chip->msg_lock, flags);
+ lx_message_init(&chip->rmh, CMD_0F_UPDATE_BUFFER);
+
+ chip->rmh.cmd[0] |= pipe_cmd;
+ chip->rmh.cmd[0] |= BF_NOTIFY_EOB; /* request interrupt notification */
+
+ /* todo: pause request, circular buffer */
+
+ chip->rmh.cmd[1] = buffer_size & MASK_DATA_SIZE;
+ chip->rmh.cmd[2] = buf_address_lo;
+
+ if (buf_address_hi) {
+ chip->rmh.cmd_len = 4;
+ chip->rmh.cmd[3] = buf_address_hi;
+ chip->rmh.cmd[0] |= BF_64BITS_ADR;
+ }
+
+ err = lx_message_send_atomic(chip, &chip->rmh);
+
+ if (err == 0) {
+ *r_buffer_index = chip->rmh.stat[0];
+ goto done;
+ }
+
+ if (err == EB_RBUFFERS_TABLE_OVERFLOW)
+ snd_printk(LXP "lx_buffer_give EB_RBUFFERS_TABLE_OVERFLOW\n");
+
+ if (err == EB_INVALID_STREAM)
+ snd_printk(LXP "lx_buffer_give EB_INVALID_STREAM\n");
+
+ if (err == EB_CMD_REFUSED)
+ snd_printk(LXP "lx_buffer_give EB_CMD_REFUSED\n");
+
+ done:
+ spin_unlock_irqrestore(&chip->msg_lock, flags);
+ return err;
+}
+
+int lx_buffer_free(struct lx6464es *chip, u32 pipe, int is_capture,
+ u32 *r_buffer_size)
+{
+ int err;
+ unsigned long flags;
+
+ u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
+
+ spin_lock_irqsave(&chip->msg_lock, flags);
+ lx_message_init(&chip->rmh, CMD_11_CANCEL_BUFFER);
+
+ chip->rmh.cmd[0] |= pipe_cmd;
+ chip->rmh.cmd[0] |= MASK_BUFFER_ID; /* ask for the current buffer: the
+ * microblaze will seek for it */
+
+ err = lx_message_send_atomic(chip, &chip->rmh);
+
+ if (err == 0)
+ *r_buffer_size = chip->rmh.stat[0] & MASK_DATA_SIZE;
+
+ spin_unlock_irqrestore(&chip->msg_lock, flags);
+ return err;
+}
+
+int lx_buffer_cancel(struct lx6464es *chip, u32 pipe, int is_capture,
+ u32 buffer_index)
+{
+ int err;
+ unsigned long flags;
+
+ u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
+
+ spin_lock_irqsave(&chip->msg_lock, flags);
+ lx_message_init(&chip->rmh, CMD_11_CANCEL_BUFFER);
+
+ chip->rmh.cmd[0] |= pipe_cmd;
+ chip->rmh.cmd[0] |= buffer_index;
+
+ err = lx_message_send_atomic(chip, &chip->rmh);
+
+ spin_unlock_irqrestore(&chip->msg_lock, flags);
+ return err;
+}
+
+
+/* low-level gain/peak handling
+ *
+ * \todo: can we unmute capture/playback channels independently?
+ *
+ * */
+int lx_level_unmute(struct lx6464es *chip, int is_capture, int unmute)
+{
+ int err;
+ unsigned long flags;
+
+ /* bit set to 1: channel muted */
+ u64 mute_mask = unmute ? 0 : 0xFFFFFFFFFFFFFFFFLLU;
+
+ spin_lock_irqsave(&chip->msg_lock, flags);
+ lx_message_init(&chip->rmh, CMD_0D_SET_MUTE);
+
+ chip->rmh.cmd[0] |= PIPE_INFO_TO_CMD(is_capture, 0);
+
+ chip->rmh.cmd[1] = (u32)(mute_mask >> (u64)32); /* hi part */
+ chip->rmh.cmd[2] = (u32)(mute_mask & (u64)0xFFFFFFFF); /* lo part */
+
+ snd_printk("mute %x %x %x\n", chip->rmh.cmd[0], chip->rmh.cmd[1],
+ chip->rmh.cmd[2]);
+
+ err = lx_message_send_atomic(chip, &chip->rmh);
+
+ spin_unlock_irqrestore(&chip->msg_lock, flags);
+ return err;
+}
+
+static u32 peak_map[] = {
+ 0x00000109, /* -90.308dB */
+ 0x0000083B, /* -72.247dB */
+ 0x000020C4, /* -60.205dB */
+ 0x00008273, /* -48.030dB */
+ 0x00020756, /* -36.005dB */
+ 0x00040C37, /* -30.001dB */
+ 0x00081385, /* -24.002dB */
+ 0x00101D3F, /* -18.000dB */
+ 0x0016C310, /* -15.000dB */
+ 0x002026F2, /* -12.001dB */
+ 0x002D6A86, /* -9.000dB */
+ 0x004026E6, /* -6.004dB */
+ 0x005A9DF6, /* -3.000dB */
+ 0x0065AC8B, /* -2.000dB */
+ 0x00721481, /* -1.000dB */
+ 0x007FFFFF, /* FS */
+};
+
+int lx_level_peaks(struct lx6464es *chip, int is_capture, int channels,
+ u32 *r_levels)
+{
+ int err = 0;
+ unsigned long flags;
+ int i;
+ spin_lock_irqsave(&chip->msg_lock, flags);
+
+ for (i = 0; i < channels; i += 4) {
+ u32 s0, s1, s2, s3;
+
+ lx_message_init(&chip->rmh, CMD_12_GET_PEAK);
+ chip->rmh.cmd[0] |= PIPE_INFO_TO_CMD(is_capture, i);
+
+ err = lx_message_send_atomic(chip, &chip->rmh);
+
+ if (err == 0) {
+ s0 = peak_map[chip->rmh.stat[0] & 0x0F];
+ s1 = peak_map[(chip->rmh.stat[0] >> 4) & 0xf];
+ s2 = peak_map[(chip->rmh.stat[0] >> 8) & 0xf];
+ s3 = peak_map[(chip->rmh.stat[0] >> 12) & 0xf];
+ } else
+ s0 = s1 = s2 = s3 = 0;
+
+ r_levels[0] = s0;
+ r_levels[1] = s1;
+ r_levels[2] = s2;
+ r_levels[3] = s3;
+
+ r_levels += 4;
+ }
+
+ spin_unlock_irqrestore(&chip->msg_lock, flags);
+ return err;
+}
+
+/* interrupt handling */
+#define PCX_IRQ_NONE 0
+#define IRQCS_ACTIVE_PCIDB 0x00002000L /* Bit nø 13 */
+#define IRQCS_ENABLE_PCIIRQ 0x00000100L /* Bit nø 08 */
+#define IRQCS_ENABLE_PCIDB 0x00000200L /* Bit nø 09 */
+
+static u32 lx_interrupt_test_ack(struct lx6464es *chip)
+{
+ u32 irqcs = lx_plx_reg_read(chip, ePLX_IRQCS);
+
+ /* Test if PCI Doorbell interrupt is active */
+ if (irqcs & IRQCS_ACTIVE_PCIDB) {
+ u32 temp;
+ irqcs = PCX_IRQ_NONE;
+
+ while ((temp = lx_plx_reg_read(chip, ePLX_L2PCIDB))) {
+ /* RAZ interrupt */
+ irqcs |= temp;
+ lx_plx_reg_write(chip, ePLX_L2PCIDB, temp);
+ }
+
+ return irqcs;
+ }
+ return PCX_IRQ_NONE;
+}
+
+static int lx_interrupt_ack(struct lx6464es *chip, u32 *r_irqsrc,
+ int *r_async_pending, int *r_async_escmd)
+{
+ u32 irq_async;
+ u32 irqsrc = lx_interrupt_test_ack(chip);
+
+ if (irqsrc == PCX_IRQ_NONE)
+ return 0;
+
+ *r_irqsrc = irqsrc;
+
+ irq_async = irqsrc & MASK_SYS_ASYNC_EVENTS; /* + EtherSound response
+ * (set by xilinx) + EOB */
+
+ if (irq_async & MASK_SYS_STATUS_ESA) {
+ irq_async &= ~MASK_SYS_STATUS_ESA;
+ *r_async_escmd = 1;
+ }
+
+ if (irqsrc & MASK_SYS_STATUS_CMD_DONE)
+ /* xilinx command notification */
+ atomic_set(&chip->send_message_locked, 0);
+
+ if (irq_async) {
+ /* snd_printd("interrupt: async event pending\n"); */
+ *r_async_pending = 1;
+ }
+
+ return 1;
+}
+
+static int lx_interrupt_handle_async_events(struct lx6464es *chip, u32 irqsrc,
+ int *r_freq_changed,
+ u64 *r_notified_in_pipe_mask,
+ u64 *r_notified_out_pipe_mask)
+{
+ int err;
+ u32 stat[9]; /* answer from CMD_04_GET_EVENT */
+
+ /* On peut optimiser pour ne pas lire les evenements vides
+ * les mots de réponse sont dans l'ordre suivant :
+ * Stat[0] mot de status général
+ * Stat[1] fin de buffer OUT pF
+ * Stat[2] fin de buffer OUT pf
+ * Stat[3] fin de buffer IN pF
+ * Stat[4] fin de buffer IN pf
+ * Stat[5] underrun poid fort
+ * Stat[6] underrun poid faible
+ * Stat[7] overrun poid fort
+ * Stat[8] overrun poid faible
+ * */
+
+ u64 orun_mask;
+ u64 urun_mask;
+#if 0
+ int has_underrun = (irqsrc & MASK_SYS_STATUS_URUN) ? 1 : 0;
+ int has_overrun = (irqsrc & MASK_SYS_STATUS_ORUN) ? 1 : 0;
+#endif
+ int eb_pending_out = (irqsrc & MASK_SYS_STATUS_EOBO) ? 1 : 0;
+ int eb_pending_in = (irqsrc & MASK_SYS_STATUS_EOBI) ? 1 : 0;
+
+ *r_freq_changed = (irqsrc & MASK_SYS_STATUS_FREQ) ? 1 : 0;
+
+ err = lx_dsp_read_async_events(chip, stat);
+ if (err < 0)
+ return err;
+
+ if (eb_pending_in) {
+ *r_notified_in_pipe_mask = ((u64)stat[3] << 32)
+ + stat[4];
+ snd_printdd(LXP "interrupt: EOBI pending %llx\n",
+ *r_notified_in_pipe_mask);
+ }
+ if (eb_pending_out) {
+ *r_notified_out_pipe_mask = ((u64)stat[1] << 32)
+ + stat[2];
+ snd_printdd(LXP "interrupt: EOBO pending %llx\n",
+ *r_notified_out_pipe_mask);
+ }
+
+ orun_mask = ((u64)stat[7] << 32) + stat[8];
+ urun_mask = ((u64)stat[5] << 32) + stat[6];
+
+ /* todo: handle xrun notification */
+
+ return err;
+}
+
+static int lx_interrupt_request_new_buffer(struct lx6464es *chip,
+ struct lx_stream *lx_stream)
+{
+ struct snd_pcm_substream *substream = lx_stream->stream;
+ int is_capture = lx_stream->is_capture;
+ int err;
+ unsigned long flags;
+
+ const u32 channels = substream->runtime->channels;
+ const u32 bytes_per_frame = channels * 3;
+ const u32 period_size = substream->runtime->period_size;
+ const u32 period_bytes = period_size * bytes_per_frame;
+ const u32 pos = lx_stream->frame_pos;
+ const u32 next_pos = ((pos+1) == substream->runtime->periods) ?
+ 0 : pos + 1;
+
+ dma_addr_t buf = substream->dma_buffer.addr + pos * period_bytes;
+ u32 buf_hi = 0;
+ u32 buf_lo = 0;
+ u32 buffer_index = 0;
+
+ u32 needed, freed;
+ u32 size_array[MAX_STREAM_BUFFER];
+
+ snd_printdd("->lx_interrupt_request_new_buffer\n");
+
+ spin_lock_irqsave(&chip->lock, flags);
+
+ err = lx_buffer_ask(chip, 0, is_capture, &needed, &freed, size_array);
+ snd_printdd(LXP "interrupt: needed %d, freed %d\n", needed, freed);
+
+ unpack_pointer(buf, &buf_lo, &buf_hi);
+ err = lx_buffer_give(chip, 0, is_capture, period_bytes, buf_lo, buf_hi,
+ &buffer_index);
+ snd_printdd(LXP "interrupt: gave buffer index %x on %p (%d bytes)\n",
+ buffer_index, (void *)buf, period_bytes);
+
+ lx_stream->frame_pos = next_pos;
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ return err;
+}
+
+void lx_tasklet_playback(unsigned long data)
+{
+ struct lx6464es *chip = (struct lx6464es *)data;
+ struct lx_stream *lx_stream = &chip->playback_stream;
+ int err;
+
+ snd_printdd("->lx_tasklet_playback\n");
+
+ err = lx_interrupt_request_new_buffer(chip, lx_stream);
+ if (err < 0)
+ snd_printk(KERN_ERR LXP
+ "cannot request new buffer for playback\n");
+
+ snd_pcm_period_elapsed(lx_stream->stream);
+}
+
+void lx_tasklet_capture(unsigned long data)
+{
+ struct lx6464es *chip = (struct lx6464es *)data;
+ struct lx_stream *lx_stream = &chip->capture_stream;
+ int err;
+
+ snd_printdd("->lx_tasklet_capture\n");
+ err = lx_interrupt_request_new_buffer(chip, lx_stream);
+ if (err < 0)
+ snd_printk(KERN_ERR LXP
+ "cannot request new buffer for capture\n");
+
+ snd_pcm_period_elapsed(lx_stream->stream);
+}
+
+
+
+static int lx_interrupt_handle_audio_transfer(struct lx6464es *chip,
+ u64 notified_in_pipe_mask,
+ u64 notified_out_pipe_mask)
+{
+ int err = 0;
+
+ if (notified_in_pipe_mask) {
+ snd_printdd(LXP "requesting audio transfer for capture\n");
+ tasklet_hi_schedule(&chip->tasklet_capture);
+ }
+
+ if (notified_out_pipe_mask) {
+ snd_printdd(LXP "requesting audio transfer for playback\n");
+ tasklet_hi_schedule(&chip->tasklet_playback);
+ }
+
+ return err;
+}
+
+
+irqreturn_t lx_interrupt(int irq, void *dev_id)
+{
+ struct lx6464es *chip = dev_id;
+ int async_pending, async_escmd;
+ u32 irqsrc;
+
+ spin_lock(&chip->lock);
+
+ snd_printdd("**************************************************\n");
+
+ if (!lx_interrupt_ack(chip, &irqsrc, &async_pending, &async_escmd)) {
+ spin_unlock(&chip->lock);
+ snd_printdd("IRQ_NONE\n");
+ return IRQ_NONE; /* this device did not cause the interrupt */
+ }
+
+ if (irqsrc & MASK_SYS_STATUS_CMD_DONE)
+ goto exit;
+
+#if 0
+ if (irqsrc & MASK_SYS_STATUS_EOBI)
+ snd_printdd(LXP "interrupt: EOBI\n");
+
+ if (irqsrc & MASK_SYS_STATUS_EOBO)
+ snd_printdd(LXP "interrupt: EOBO\n");
+
+ if (irqsrc & MASK_SYS_STATUS_URUN)
+ snd_printdd(LXP "interrupt: URUN\n");
+
+ if (irqsrc & MASK_SYS_STATUS_ORUN)
+ snd_printdd(LXP "interrupt: ORUN\n");
+#endif
+
+ if (async_pending) {
+ u64 notified_in_pipe_mask = 0;
+ u64 notified_out_pipe_mask = 0;
+ int freq_changed;
+ int err;
+
+ /* handle async events */
+ err = lx_interrupt_handle_async_events(chip, irqsrc,
+ &freq_changed,
+ &notified_in_pipe_mask,
+ &notified_out_pipe_mask);
+ if (err)
+ snd_printk(KERN_ERR LXP
+ "error handling async events\n");
+
+ err = lx_interrupt_handle_audio_transfer(chip,
+ notified_in_pipe_mask,
+ notified_out_pipe_mask
+ );
+ if (err)
+ snd_printk(KERN_ERR LXP
+ "error during audio transfer\n");
+ }
+
+ if (async_escmd) {
+#if 0
+ /* backdoor for ethersound commands
+ *
+ * for now, we do not need this
+ *
+ * */
+
+ snd_printdd("lx6464es: interrupt requests escmd handling\n");
+#endif
+ }
+
+exit:
+ spin_unlock(&chip->lock);
+ return IRQ_HANDLED; /* this device caused the interrupt */
+}
+
+
+static void lx_irq_set(struct lx6464es *chip, int enable)
+{
+ u32 reg = lx_plx_reg_read(chip, ePLX_IRQCS);
+
+ /* enable/disable interrupts
+ *
+ * Set the Doorbell and PCI interrupt enable bits
+ *
+ * */
+ if (enable)
+ reg |= (IRQCS_ENABLE_PCIIRQ | IRQCS_ENABLE_PCIDB);
+ else
+ reg &= ~(IRQCS_ENABLE_PCIIRQ | IRQCS_ENABLE_PCIDB);
+ lx_plx_reg_write(chip, ePLX_IRQCS, reg);
+}
+
+void lx_irq_enable(struct lx6464es *chip)
+{
+ snd_printdd("->lx_irq_enable\n");
+ lx_irq_set(chip, 1);
+}
+
+void lx_irq_disable(struct lx6464es *chip)
+{
+ snd_printdd("->lx_irq_disable\n");
+ lx_irq_set(chip, 0);
+}
diff --git a/sound/pci/lx6464es/lx_core.h b/sound/pci/lx6464es/lx_core.h
new file mode 100644
index 000000000000..6bd9cbbbc68d
--- /dev/null
+++ b/sound/pci/lx6464es/lx_core.h
@@ -0,0 +1,242 @@
+/* -*- linux-c -*- *
+ *
+ * ALSA driver for the digigram lx6464es interface
+ * low-level interface
+ *
+ * Copyright (c) 2009 Tim Blechmann <tim@klingt.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; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef LX_CORE_H
+#define LX_CORE_H
+
+#include <linux/interrupt.h>
+
+#include "lx_defs.h"
+
+#define REG_CRM_NUMBER 12
+
+struct lx6464es;
+
+/* low-level register access */
+
+/* dsp register access */
+enum {
+ eReg_BASE,
+ eReg_CSM,
+ eReg_CRM1,
+ eReg_CRM2,
+ eReg_CRM3,
+ eReg_CRM4,
+ eReg_CRM5,
+ eReg_CRM6,
+ eReg_CRM7,
+ eReg_CRM8,
+ eReg_CRM9,
+ eReg_CRM10,
+ eReg_CRM11,
+ eReg_CRM12,
+
+ eReg_ICR,
+ eReg_CVR,
+ eReg_ISR,
+ eReg_RXHTXH,
+ eReg_RXMTXM,
+ eReg_RHLTXL,
+ eReg_RESETDSP,
+
+ eReg_CSUF,
+ eReg_CSES,
+ eReg_CRESMSB,
+ eReg_CRESLSB,
+ eReg_ADMACESMSB,
+ eReg_ADMACESLSB,
+ eReg_CONFES,
+
+ eMaxPortLx
+};
+
+unsigned long lx_dsp_reg_read(struct lx6464es *chip, int port);
+void lx_dsp_reg_readbuf(struct lx6464es *chip, int port, u32 *data, u32 len);
+void lx_dsp_reg_write(struct lx6464es *chip, int port, unsigned data);
+void lx_dsp_reg_writebuf(struct lx6464es *chip, int port, const u32 *data,
+ u32 len);
+
+/* plx register access */
+enum {
+ ePLX_PCICR,
+
+ ePLX_MBOX0,
+ ePLX_MBOX1,
+ ePLX_MBOX2,
+ ePLX_MBOX3,
+ ePLX_MBOX4,
+ ePLX_MBOX5,
+ ePLX_MBOX6,
+ ePLX_MBOX7,
+
+ ePLX_L2PCIDB,
+ ePLX_IRQCS,
+ ePLX_CHIPSC,
+
+ eMaxPort
+};
+
+unsigned long lx_plx_reg_read(struct lx6464es *chip, int port);
+void lx_plx_reg_write(struct lx6464es *chip, int port, u32 data);
+
+/* rhm */
+struct lx_rmh {
+ u16 cmd_len; /* length of the command to send (WORDs) */
+ u16 stat_len; /* length of the status received (WORDs) */
+ u16 dsp_stat; /* status type, RMP_SSIZE_XXX */
+ u16 cmd_idx; /* index of the command */
+ u32 cmd[REG_CRM_NUMBER];
+ u32 stat[REG_CRM_NUMBER];
+};
+
+
+/* low-level dsp access */
+int __devinit lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version);
+int lx_dsp_get_clock_frequency(struct lx6464es *chip, u32 *rfreq);
+int lx_dsp_set_granularity(struct lx6464es *chip, u32 gran);
+int lx_dsp_read_async_events(struct lx6464es *chip, u32 *data);
+int lx_dsp_get_mac(struct lx6464es *chip, u8 *mac_address);
+
+
+/* low-level pipe handling */
+int lx_pipe_allocate(struct lx6464es *chip, u32 pipe, int is_capture,
+ int channels);
+int lx_pipe_release(struct lx6464es *chip, u32 pipe, int is_capture);
+int lx_pipe_sample_count(struct lx6464es *chip, u32 pipe, int is_capture,
+ u64 *rsample_count);
+int lx_pipe_state(struct lx6464es *chip, u32 pipe, int is_capture, u16 *rstate);
+int lx_pipe_stop(struct lx6464es *chip, u32 pipe, int is_capture);
+int lx_pipe_start(struct lx6464es *chip, u32 pipe, int is_capture);
+int lx_pipe_pause(struct lx6464es *chip, u32 pipe, int is_capture);
+
+int lx_pipe_wait_for_start(struct lx6464es *chip, u32 pipe, int is_capture);
+int lx_pipe_wait_for_idle(struct lx6464es *chip, u32 pipe, int is_capture);
+
+/* low-level stream handling */
+int lx_stream_set_format(struct lx6464es *chip, struct snd_pcm_runtime *runtime,
+ u32 pipe, int is_capture);
+int lx_stream_state(struct lx6464es *chip, u32 pipe, int is_capture,
+ int *rstate);
+int lx_stream_sample_position(struct lx6464es *chip, u32 pipe, int is_capture,
+ u64 *r_bytepos);
+
+int lx_stream_set_state(struct lx6464es *chip, u32 pipe,
+ int is_capture, enum stream_state_t state);
+
+static inline int lx_stream_start(struct lx6464es *chip, u32 pipe,
+ int is_capture)
+{
+ snd_printdd("->lx_stream_start\n");
+ return lx_stream_set_state(chip, pipe, is_capture, SSTATE_RUN);
+}
+
+static inline int lx_stream_pause(struct lx6464es *chip, u32 pipe,
+ int is_capture)
+{
+ snd_printdd("->lx_stream_pause\n");
+ return lx_stream_set_state(chip, pipe, is_capture, SSTATE_PAUSE);
+}
+
+static inline int lx_stream_stop(struct lx6464es *chip, u32 pipe,
+ int is_capture)
+{
+ snd_printdd("->lx_stream_stop\n");
+ return lx_stream_set_state(chip, pipe, is_capture, SSTATE_STOP);
+}
+
+/* low-level buffer handling */
+int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture,
+ u32 *r_needed, u32 *r_freed, u32 *size_array);
+int lx_buffer_give(struct lx6464es *chip, u32 pipe, int is_capture,
+ u32 buffer_size, u32 buf_address_lo, u32 buf_address_hi,
+ u32 *r_buffer_index);
+int lx_buffer_free(struct lx6464es *chip, u32 pipe, int is_capture,
+ u32 *r_buffer_size);
+int lx_buffer_cancel(struct lx6464es *chip, u32 pipe, int is_capture,
+ u32 buffer_index);
+
+/* low-level gain/peak handling */
+int lx_level_unmute(struct lx6464es *chip, int is_capture, int unmute);
+int lx_level_peaks(struct lx6464es *chip, int is_capture, int channels,
+ u32 *r_levels);
+
+
+/* interrupt handling */
+irqreturn_t lx_interrupt(int irq, void *dev_id);
+void lx_irq_enable(struct lx6464es *chip);
+void lx_irq_disable(struct lx6464es *chip);
+
+void lx_tasklet_capture(unsigned long data);
+void lx_tasklet_playback(unsigned long data);
+
+
+/* Stream Format Header Defines (for LIN and IEEE754) */
+#define HEADER_FMT_BASE HEADER_FMT_BASE_LIN
+#define HEADER_FMT_BASE_LIN 0xFED00000
+#define HEADER_FMT_BASE_FLOAT 0xFAD00000
+#define HEADER_FMT_MONO 0x00000080 /* bit 23 in header_lo. WARNING: old
+ * bit 22 is ignored in float
+ * format */
+#define HEADER_FMT_INTEL 0x00008000
+#define HEADER_FMT_16BITS 0x00002000
+#define HEADER_FMT_24BITS 0x00004000
+#define HEADER_FMT_UPTO11 0x00000200 /* frequency is less or equ. to 11k.
+ * */
+#define HEADER_FMT_UPTO32 0x00000100 /* frequency is over 11k and less
+ * then 32k.*/
+
+
+#define BIT_FMP_HEADER 23
+#define BIT_FMP_SD 22
+#define BIT_FMP_MULTICHANNEL 19
+
+#define START_STATE 1
+#define PAUSE_STATE 0
+
+
+
+
+
+/* from PcxAll_e.h */
+/* Start/Pause condition for pipes (PCXStartPipe, PCXPausePipe) */
+#define START_PAUSE_IMMEDIATE 0
+#define START_PAUSE_ON_SYNCHRO 1
+#define START_PAUSE_ON_TIME_CODE 2
+
+
+/* Pipe / Stream state */
+#define START_STATE 1
+#define PAUSE_STATE 0
+
+static inline void unpack_pointer(dma_addr_t ptr, u32 *r_low, u32 *r_high)
+{
+ *r_low = (u32)(ptr & 0xffffffff);
+#if BITS_PER_LONG == 32
+ *r_high = 0;
+#else
+ *r_high = (u32)((u64)ptr>>32);
+#endif
+}
+
+#endif /* LX_CORE_H */
diff --git a/sound/pci/lx6464es/lx_defs.h b/sound/pci/lx6464es/lx_defs.h
new file mode 100644
index 000000000000..49d36bdd512c
--- /dev/null
+++ b/sound/pci/lx6464es/lx_defs.h
@@ -0,0 +1,376 @@
+/* -*- linux-c -*- *
+ *
+ * ALSA driver for the digigram lx6464es interface
+ * adapted upstream headers
+ *
+ * Copyright (c) 2009 Tim Blechmann <tim@klingt.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; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef LX_DEFS_H
+#define LX_DEFS_H
+
+/* code adapted from ethersound.h */
+#define XES_FREQ_COUNT8_MASK 0x00001FFF /* compteur 25MHz entre 8 ech. */
+#define XES_FREQ_COUNT8_44_MIN 0x00001288 /* 25M /
+ * [ 44k - ( 44.1k + 48k ) / 2 ]
+ * * 8 */
+#define XES_FREQ_COUNT8_44_MAX 0x000010F0 /* 25M / [ ( 44.1k + 48k ) / 2 ]
+ * * 8 */
+#define XES_FREQ_COUNT8_48_MAX 0x00000F08 /* 25M /
+ * [ 48k + ( 44.1k + 48k ) / 2 ]
+ * * 8 */
+
+/* code adapted from LXES_registers.h */
+
+#define IOCR_OUTPUTS_OFFSET 0 /* (rw) offset for the number of OUTs in the
+ * ConfES register. */
+#define IOCR_INPUTS_OFFSET 8 /* (rw) offset for the number of INs in the
+ * ConfES register. */
+#define FREQ_RATIO_OFFSET 19 /* (rw) offset for frequency ratio in the
+ * ConfES register. */
+#define FREQ_RATIO_SINGLE_MODE 0x01 /* value for single mode frequency ratio:
+ * sample rate = frequency rate. */
+
+#define CONFES_READ_PART_MASK 0x00070000
+#define CONFES_WRITE_PART_MASK 0x00F80000
+
+/* code adapted from if_drv_mb.h */
+
+#define MASK_SYS_STATUS_ERROR (1L << 31) /* events that lead to a PCI irq if
+ * not yet pending */
+#define MASK_SYS_STATUS_URUN (1L << 30)
+#define MASK_SYS_STATUS_ORUN (1L << 29)
+#define MASK_SYS_STATUS_EOBO (1L << 28)
+#define MASK_SYS_STATUS_EOBI (1L << 27)
+#define MASK_SYS_STATUS_FREQ (1L << 26)
+#define MASK_SYS_STATUS_ESA (1L << 25) /* reserved, this is set by the
+ * XES */
+#define MASK_SYS_STATUS_TIMER (1L << 24)
+
+#define MASK_SYS_ASYNC_EVENTS (MASK_SYS_STATUS_ERROR | \
+ MASK_SYS_STATUS_URUN | \
+ MASK_SYS_STATUS_ORUN | \
+ MASK_SYS_STATUS_EOBO | \
+ MASK_SYS_STATUS_EOBI | \
+ MASK_SYS_STATUS_FREQ | \
+ MASK_SYS_STATUS_ESA)
+
+#define MASK_SYS_PCI_EVENTS (MASK_SYS_ASYNC_EVENTS | \
+ MASK_SYS_STATUS_TIMER)
+
+#define MASK_SYS_TIMER_COUNT 0x0000FFFF
+
+#define MASK_SYS_STATUS_EOT_PLX (1L << 22) /* event that remains
+ * internal: reserved fo end
+ * of plx dma */
+#define MASK_SYS_STATUS_XES (1L << 21) /* event that remains
+ * internal: pending XES
+ * IRQ */
+#define MASK_SYS_STATUS_CMD_DONE (1L << 20) /* alternate command
+ * management: notify driver
+ * instead of polling */
+
+
+#define MAX_STREAM_BUFFER 5 /* max amount of stream buffers. */
+
+#define MICROBLAZE_IBL_MIN 32
+#define MICROBLAZE_IBL_DEFAULT 128
+#define MICROBLAZE_IBL_MAX 512
+/* #define MASK_GRANULARITY (2*MICROBLAZE_IBL_MAX-1) */
+
+
+
+/* command opcodes, see reference for details */
+
+/*
+ the capture bit position in the object_id field in driver commands
+ depends upon the number of managed channels. For now, 64 IN + 64 OUT are
+ supported. HOwever, the communication protocol forsees 1024 channels, hence
+ bit 10 indicates a capture (input) object).
+*/
+#define ID_IS_CAPTURE (1L << 10)
+#define ID_OFFSET 13 /* object ID is at the 13th bit in the
+ * 1st command word.*/
+#define ID_CH_MASK 0x3F
+#define OPCODE_OFFSET 24 /* offset of the command opcode in the first
+ * command word.*/
+
+enum cmd_mb_opcodes {
+ CMD_00_INFO_DEBUG = 0x00,
+ CMD_01_GET_SYS_CFG = 0x01,
+ CMD_02_SET_GRANULARITY = 0x02,
+ CMD_03_SET_TIMER_IRQ = 0x03,
+ CMD_04_GET_EVENT = 0x04,
+ CMD_05_GET_PIPES = 0x05,
+
+ CMD_06_ALLOCATE_PIPE = 0x06,
+ CMD_07_RELEASE_PIPE = 0x07,
+ CMD_08_ASK_BUFFERS = 0x08,
+ CMD_09_STOP_PIPE = 0x09,
+ CMD_0A_GET_PIPE_SPL_COUNT = 0x0a,
+ CMD_0B_TOGGLE_PIPE_STATE = 0x0b,
+
+ CMD_0C_DEF_STREAM = 0x0c,
+ CMD_0D_SET_MUTE = 0x0d,
+ CMD_0E_GET_STREAM_SPL_COUNT = 0x0e,
+ CMD_0F_UPDATE_BUFFER = 0x0f,
+ CMD_10_GET_BUFFER = 0x10,
+ CMD_11_CANCEL_BUFFER = 0x11,
+ CMD_12_GET_PEAK = 0x12,
+ CMD_13_SET_STREAM_STATE = 0x13,
+ CMD_14_INVALID = 0x14,
+};
+
+/* pipe states */
+enum pipe_state_t {
+ PSTATE_IDLE = 0, /* the pipe is not processed in the XES_IRQ
+ * (free or stopped, or paused). */
+ PSTATE_RUN = 1, /* sustained play/record state. */
+ PSTATE_PURGE = 2, /* the ES channels are now off, render pipes do
+ * not DMA, record pipe do a last DMA. */
+ PSTATE_ACQUIRE = 3, /* the ES channels are now on, render pipes do
+ * not yet increase their sample count, record
+ * pipes do not DMA. */
+ PSTATE_CLOSING = 4, /* the pipe is releasing, and may not yet
+ * receive an "alloc" command. */
+};
+
+/* stream states */
+enum stream_state_t {
+ SSTATE_STOP = 0x00, /* setting to stop resets the stream spl
+ * count.*/
+ SSTATE_RUN = (0x01 << 0), /* start DMA and spl count handling. */
+ SSTATE_PAUSE = (0x01 << 1), /* pause DMA and spl count handling. */
+};
+
+/* buffer flags */
+enum buffer_flags {
+ BF_VALID = 0x80, /* set if the buffer is valid, clear if free.*/
+ BF_CURRENT = 0x40, /* set if this is the current buffer (there is
+ * always a current buffer).*/
+ BF_NOTIFY_EOB = 0x20, /* set if this buffer must cause a PCI event
+ * when finished.*/
+ BF_CIRCULAR = 0x10, /* set if buffer[1] must be copied to buffer[0]
+ * by the end of this buffer.*/
+ BF_64BITS_ADR = 0x08, /* set if the hi part of the address is valid.*/
+ BF_xx = 0x04, /* future extension.*/
+ BF_EOB = 0x02, /* set if finished, but not yet free.*/
+ BF_PAUSE = 0x01, /* pause stream at buffer end.*/
+ BF_ZERO = 0x00, /* no flags (init).*/
+};
+
+/**
+* Stream Flags definitions
+*/
+enum stream_flags {
+ SF_ZERO = 0x00000000, /* no flags (stream invalid). */
+ SF_VALID = 0x10000000, /* the stream has a valid DMA_conf
+ * info (setstreamformat). */
+ SF_XRUN = 0x20000000, /* the stream is un x-run state. */
+ SF_START = 0x40000000, /* the DMA is running.*/
+ SF_ASIO = 0x80000000, /* ASIO.*/
+};
+
+
+#define MASK_SPL_COUNT_HI 0x00FFFFFF /* 4 MSBits are status bits */
+#define PSTATE_OFFSET 28 /* 4 MSBits are status bits */
+
+
+#define MASK_STREAM_HAS_MAPPING (1L << 12)
+#define MASK_STREAM_IS_ASIO (1L << 9)
+#define STREAM_FMT_OFFSET 10 /* the stream fmt bits start at the 10th
+ * bit in the command word. */
+
+#define STREAM_FMT_16b 0x02
+#define STREAM_FMT_intel 0x01
+
+#define FREQ_FIELD_OFFSET 15 /* offset of the freq field in the response
+ * word */
+
+#define BUFF_FLAGS_OFFSET 24 /* offset of the buffer flags in the
+ * response word. */
+#define MASK_DATA_SIZE 0x00FFFFFF /* this must match the field size of
+ * datasize in the buffer_t structure. */
+
+#define MASK_BUFFER_ID 0xFF /* the cancel command awaits a buffer ID,
+ * may be 0xFF for "current". */
+
+
+/* code adapted from PcxErr_e.h */
+
+/* Bits masks */
+
+#define ERROR_MASK 0x8000
+
+#define SOURCE_MASK 0x7800
+
+#define E_SOURCE_BOARD 0x4000 /* 8 >> 1 */
+#define E_SOURCE_DRV 0x2000 /* 4 >> 1 */
+#define E_SOURCE_API 0x1000 /* 2 >> 1 */
+/* Error tools */
+#define E_SOURCE_TOOLS 0x0800 /* 1 >> 1 */
+/* Error pcxaudio */
+#define E_SOURCE_AUDIO 0x1800 /* 3 >> 1 */
+/* Error virtual pcx */
+#define E_SOURCE_VPCX 0x2800 /* 5 >> 1 */
+/* Error dispatcher */
+#define E_SOURCE_DISPATCHER 0x3000 /* 6 >> 1 */
+/* Error from CobraNet firmware */
+#define E_SOURCE_COBRANET 0x3800 /* 7 >> 1 */
+
+#define E_SOURCE_USER 0x7800
+
+#define CLASS_MASK 0x0700
+
+#define CODE_MASK 0x00FF
+
+/* Bits values */
+
+/* Values for the error/warning bit */
+#define ERROR_VALUE 0x8000
+#define WARNING_VALUE 0x0000
+
+/* Class values */
+#define E_CLASS_GENERAL 0x0000
+#define E_CLASS_INVALID_CMD 0x0100
+#define E_CLASS_INVALID_STD_OBJECT 0x0200
+#define E_CLASS_RSRC_IMPOSSIBLE 0x0300
+#define E_CLASS_WRONG_CONTEXT 0x0400
+#define E_CLASS_BAD_SPECIFIC_PARAMETER 0x0500
+#define E_CLASS_REAL_TIME_ERROR 0x0600
+#define E_CLASS_DIRECTSHOW 0x0700
+#define E_CLASS_FREE 0x0700
+
+
+/* Complete DRV error code for the general class */
+#define ED_GN (ERROR_VALUE | E_SOURCE_DRV | E_CLASS_GENERAL)
+#define ED_CONCURRENCY (ED_GN | 0x01)
+#define ED_DSP_CRASHED (ED_GN | 0x02)
+#define ED_UNKNOWN_BOARD (ED_GN | 0x03)
+#define ED_NOT_INSTALLED (ED_GN | 0x04)
+#define ED_CANNOT_OPEN_SVC_MANAGER (ED_GN | 0x05)
+#define ED_CANNOT_READ_REGISTRY (ED_GN | 0x06)
+#define ED_DSP_VERSION_MISMATCH (ED_GN | 0x07)
+#define ED_UNAVAILABLE_FEATURE (ED_GN | 0x08)
+#define ED_CANCELLED (ED_GN | 0x09)
+#define ED_NO_RESPONSE_AT_IRQA (ED_GN | 0x10)
+#define ED_INVALID_ADDRESS (ED_GN | 0x11)
+#define ED_DSP_CORRUPTED (ED_GN | 0x12)
+#define ED_PENDING_OPERATION (ED_GN | 0x13)
+#define ED_NET_ALLOCATE_MEMORY_IMPOSSIBLE (ED_GN | 0x14)
+#define ED_NET_REGISTER_ERROR (ED_GN | 0x15)
+#define ED_NET_THREAD_ERROR (ED_GN | 0x16)
+#define ED_NET_OPEN_ERROR (ED_GN | 0x17)
+#define ED_NET_CLOSE_ERROR (ED_GN | 0x18)
+#define ED_NET_NO_MORE_PACKET (ED_GN | 0x19)
+#define ED_NET_NO_MORE_BUFFER (ED_GN | 0x1A)
+#define ED_NET_SEND_ERROR (ED_GN | 0x1B)
+#define ED_NET_RECEIVE_ERROR (ED_GN | 0x1C)
+#define ED_NET_WRONG_MSG_SIZE (ED_GN | 0x1D)
+#define ED_NET_WAIT_ERROR (ED_GN | 0x1E)
+#define ED_NET_EEPROM_ERROR (ED_GN | 0x1F)
+#define ED_INVALID_RS232_COM_NUMBER (ED_GN | 0x20)
+#define ED_INVALID_RS232_INIT (ED_GN | 0x21)
+#define ED_FILE_ERROR (ED_GN | 0x22)
+#define ED_INVALID_GPIO_CMD (ED_GN | 0x23)
+#define ED_RS232_ALREADY_OPENED (ED_GN | 0x24)
+#define ED_RS232_NOT_OPENED (ED_GN | 0x25)
+#define ED_GPIO_ALREADY_OPENED (ED_GN | 0x26)
+#define ED_GPIO_NOT_OPENED (ED_GN | 0x27)
+#define ED_REGISTRY_ERROR (ED_GN | 0x28) /* <- NCX */
+#define ED_INVALID_SERVICE (ED_GN | 0x29) /* <- NCX */
+
+#define ED_READ_FILE_ALREADY_OPENED (ED_GN | 0x2a) /* <- Decalage
+ * pour RCX
+ * (old 0x28)
+ * */
+#define ED_READ_FILE_INVALID_COMMAND (ED_GN | 0x2b) /* ~ */
+#define ED_READ_FILE_INVALID_PARAMETER (ED_GN | 0x2c) /* ~ */
+#define ED_READ_FILE_ALREADY_CLOSED (ED_GN | 0x2d) /* ~ */
+#define ED_READ_FILE_NO_INFORMATION (ED_GN | 0x2e) /* ~ */
+#define ED_READ_FILE_INVALID_HANDLE (ED_GN | 0x2f) /* ~ */
+#define ED_READ_FILE_END_OF_FILE (ED_GN | 0x30) /* ~ */
+#define ED_READ_FILE_ERROR (ED_GN | 0x31) /* ~ */
+
+#define ED_DSP_CRASHED_EXC_DSPSTACK_OVERFLOW (ED_GN | 0x32) /* <- Decalage pour
+ * PCX (old 0x14) */
+#define ED_DSP_CRASHED_EXC_SYSSTACK_OVERFLOW (ED_GN | 0x33) /* ~ */
+#define ED_DSP_CRASHED_EXC_ILLEGAL (ED_GN | 0x34) /* ~ */
+#define ED_DSP_CRASHED_EXC_TIMER_REENTRY (ED_GN | 0x35) /* ~ */
+#define ED_DSP_CRASHED_EXC_FATAL_ERROR (ED_GN | 0x36) /* ~ */
+
+#define ED_FLASH_PCCARD_NOT_PRESENT (ED_GN | 0x37)
+
+#define ED_NO_CURRENT_CLOCK (ED_GN | 0x38)
+
+/* Complete DRV error code for real time class */
+#define ED_RT (ERROR_VALUE | E_SOURCE_DRV | E_CLASS_REAL_TIME_ERROR)
+#define ED_DSP_TIMED_OUT (ED_RT | 0x01)
+#define ED_DSP_CHK_TIMED_OUT (ED_RT | 0x02)
+#define ED_STREAM_OVERRUN (ED_RT | 0x03)
+#define ED_DSP_BUSY (ED_RT | 0x04)
+#define ED_DSP_SEMAPHORE_TIME_OUT (ED_RT | 0x05)
+#define ED_BOARD_TIME_OUT (ED_RT | 0x06)
+#define ED_XILINX_ERROR (ED_RT | 0x07)
+#define ED_COBRANET_ITF_NOT_RESPONDING (ED_RT | 0x08)
+
+/* Complete BOARD error code for the invaid standard object class */
+#define EB_ISO (ERROR_VALUE | E_SOURCE_BOARD | \
+ E_CLASS_INVALID_STD_OBJECT)
+#define EB_INVALID_EFFECT (EB_ISO | 0x00)
+#define EB_INVALID_PIPE (EB_ISO | 0x40)
+#define EB_INVALID_STREAM (EB_ISO | 0x80)
+#define EB_INVALID_AUDIO (EB_ISO | 0xC0)
+
+/* Complete BOARD error code for impossible resource allocation class */
+#define EB_RI (ERROR_VALUE | E_SOURCE_BOARD | E_CLASS_RSRC_IMPOSSIBLE)
+#define EB_ALLOCATE_ALL_STREAM_TRANSFERT_BUFFERS_IMPOSSIBLE (EB_RI | 0x01)
+#define EB_ALLOCATE_PIPE_SAMPLE_BUFFER_IMPOSSIBLE (EB_RI | 0x02)
+
+#define EB_ALLOCATE_MEM_STREAM_IMPOSSIBLE \
+ EB_ALLOCATE_ALL_STREAM_TRANSFERT_BUFFERS_IMPOSSIBLE
+#define EB_ALLOCATE_MEM_PIPE_IMPOSSIBLE \
+ EB_ALLOCATE_PIPE_SAMPLE_BUFFER_IMPOSSIBLE
+
+#define EB_ALLOCATE_DIFFERED_CMD_IMPOSSIBLE (EB_RI | 0x03)
+#define EB_TOO_MANY_DIFFERED_CMD (EB_RI | 0x04)
+#define EB_RBUFFERS_TABLE_OVERFLOW (EB_RI | 0x05)
+#define EB_ALLOCATE_EFFECTS_IMPOSSIBLE (EB_RI | 0x08)
+#define EB_ALLOCATE_EFFECT_POS_IMPOSSIBLE (EB_RI | 0x09)
+#define EB_RBUFFER_NOT_AVAILABLE (EB_RI | 0x0A)
+#define EB_ALLOCATE_CONTEXT_LIII_IMPOSSIBLE (EB_RI | 0x0B)
+#define EB_STATUS_DIALOG_IMPOSSIBLE (EB_RI | 0x1D)
+#define EB_CONTROL_CMD_IMPOSSIBLE (EB_RI | 0x1E)
+#define EB_STATUS_SEND_IMPOSSIBLE (EB_RI | 0x1F)
+#define EB_ALLOCATE_PIPE_IMPOSSIBLE (EB_RI | 0x40)
+#define EB_ALLOCATE_STREAM_IMPOSSIBLE (EB_RI | 0x80)
+#define EB_ALLOCATE_AUDIO_IMPOSSIBLE (EB_RI | 0xC0)
+
+/* Complete BOARD error code for wrong call context class */
+#define EB_WCC (ERROR_VALUE | E_SOURCE_BOARD | E_CLASS_WRONG_CONTEXT)
+#define EB_CMD_REFUSED (EB_WCC | 0x00)
+#define EB_START_STREAM_REFUSED (EB_WCC | 0xFC)
+#define EB_SPC_REFUSED (EB_WCC | 0xFD)
+#define EB_CSN_REFUSED (EB_WCC | 0xFE)
+#define EB_CSE_REFUSED (EB_WCC | 0xFF)
+
+
+
+
+#endif /* LX_DEFS_H */
diff --git a/sound/pci/sis7019.h b/sound/pci/sis7019.h
index 013b6739a742..bc8c76819408 100644
--- a/sound/pci/sis7019.h
+++ b/sound/pci/sis7019.h
@@ -203,7 +203,7 @@
#define SIS_WEISR_B 0xac
-/* Playback DMA parameters (paramter RAM) */
+/* Playback DMA parameters (parameter RAM) */
#define SIS_PLAY_DMA_OFFSET 0x0000
#define SIS_PLAY_DMA_SIZE 0x10
#define SIS_PLAY_DMA_ADDR(addr, num) \
@@ -228,7 +228,7 @@
#define SIS_PLAY_DMA_SSO_MASK 0xffff0000
#define SIS_PLAY_DMA_ESO_MASK 0x0000ffff
-/* Capture DMA parameters (paramter RAM) */
+/* Capture DMA parameters (parameter RAM) */
#define SIS_CAPTURE_DMA_OFFSET 0x0800
#define SIS_CAPTURE_DMA_SIZE 0x10
#define SIS_CAPTURE_DMA_ADDR(addr, num) \
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 809b233dd4a3..1ef58c51c213 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -1687,7 +1687,7 @@ static int snd_via8233_pcmdxs_volume_put(struct snd_kcontrol *kcontrol,
return change;
}
-static const DECLARE_TLV_DB_SCALE(db_scale_dxs, -9450, 150, 1);
+static const DECLARE_TLV_DB_SCALE(db_scale_dxs, -4650, 150, 1);
static struct snd_kcontrol_new snd_via8233_pcmdxs_volume_control __devinitdata = {
.name = "PCM Playback Volume",
diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c
index c0efe4491116..6416d3f0c7be 100644
--- a/sound/pci/vx222/vx222_ops.c
+++ b/sound/pci/vx222/vx222_ops.c
@@ -367,7 +367,7 @@ static int vx2_load_xilinx_binary(struct vx_core *chip, const struct firmware *x
unsigned int port;
const unsigned char *image;
- /* XILINX reset (wait at least 1 milisecond between reset on and off). */
+ /* XILINX reset (wait at least 1 millisecond between reset on and off). */
vx_outl(chip, CNTRL, VX_CNTRL_REGISTER_VALUE | VX_XILINX_RESET_MASK);
vx_inl(chip, CNTRL);
msleep(10);
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
index 01066c95580e..d057e6489643 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
@@ -240,7 +240,8 @@ static int pdacf_pcm_prepare(struct snd_pcm_substream *subs)
static struct snd_pcm_hardware pdacf_pcm_capture_hw = {
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME |
- SNDRV_PCM_INFO_MMAP_VALID),
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH),
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |
SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE,
diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c
index 6ff99ed77516..a5afb2682e7f 100644
--- a/sound/ppc/keywest.c
+++ b/sound/ppc/keywest.c
@@ -33,26 +33,25 @@
static struct pmac_keywest *keywest_ctx;
-static int keywest_attach_adapter(struct i2c_adapter *adapter);
-static int keywest_detach_client(struct i2c_client *client);
-
-struct i2c_driver keywest_driver = {
- .driver = {
- .name = "PMac Keywest Audio",
- },
- .attach_adapter = &keywest_attach_adapter,
- .detach_client = &keywest_detach_client,
-};
-
-
#ifndef i2c_device_name
#define i2c_device_name(x) ((x)->name)
#endif
+static int keywest_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ i2c_set_clientdata(client, keywest_ctx);
+ return 0;
+}
+
+/*
+ * This is kind of a hack, best would be to turn powermac to fixed i2c
+ * bus numbers and declare the sound device as part of platform
+ * initialization
+ */
static int keywest_attach_adapter(struct i2c_adapter *adapter)
{
- int err;
- struct i2c_client *new_client;
+ struct i2c_board_info info;
if (! keywest_ctx)
return -EINVAL;
@@ -60,46 +59,47 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter)
if (strncmp(i2c_device_name(adapter), "mac-io", 6))
return 0; /* ignored */
- new_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (! new_client)
- return -ENOMEM;
-
- new_client->addr = keywest_ctx->addr;
- i2c_set_clientdata(new_client, keywest_ctx);
- new_client->adapter = adapter;
- new_client->driver = &keywest_driver;
- new_client->flags = 0;
-
- strcpy(i2c_device_name(new_client), keywest_ctx->name);
- keywest_ctx->client = new_client;
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "keywest", I2C_NAME_SIZE);
+ info.addr = keywest_ctx->addr;
+ keywest_ctx->client = i2c_new_device(adapter, &info);
- /* Tell the i2c layer a new client has arrived */
- if (i2c_attach_client(new_client)) {
- snd_printk(KERN_ERR "tumbler: cannot attach i2c client\n");
- err = -ENODEV;
- goto __err;
- }
-
+ /*
+ * Let i2c-core delete that device on driver removal.
+ * This is safe because i2c-core holds the core_lock mutex for us.
+ */
+ list_add_tail(&keywest_ctx->client->detected,
+ &keywest_ctx->client->driver->clients);
return 0;
-
- __err:
- kfree(new_client);
- keywest_ctx->client = NULL;
- return err;
}
-static int keywest_detach_client(struct i2c_client *client)
+static int keywest_remove(struct i2c_client *client)
{
+ i2c_set_clientdata(client, NULL);
if (! keywest_ctx)
return 0;
if (client == keywest_ctx->client)
keywest_ctx->client = NULL;
- i2c_detach_client(client);
- kfree(client);
return 0;
}
+
+static const struct i2c_device_id keywest_i2c_id[] = {
+ { "keywest", 0 },
+ { }
+};
+
+struct i2c_driver keywest_driver = {
+ .driver = {
+ .name = "PMac Keywest Audio",
+ },
+ .attach_adapter = keywest_attach_adapter,
+ .probe = keywest_probe,
+ .remove = keywest_remove,
+ .id_table = keywest_i2c_id,
+};
+
/* exported */
void snd_pmac_keywest_cleanup(struct pmac_keywest *i2c)
{
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 3d2bb6fc6dcc..3304f9dd92fa 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -32,6 +32,7 @@ source "sound/soc/fsl/Kconfig"
source "sound/soc/omap/Kconfig"
source "sound/soc/pxa/Kconfig"
source "sound/soc/s3c24xx/Kconfig"
+source "sound/soc/s6000/Kconfig"
source "sound/soc/sh/Kconfig"
# Supported codecs
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 0237879fd412..8943a140c818 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -10,4 +10,5 @@ obj-$(CONFIG_SND_SOC) += fsl/
obj-$(CONFIG_SND_SOC) += omap/
obj-$(CONFIG_SND_SOC) += pxa/
obj-$(CONFIG_SND_SOC) += s3c24xx/
+obj-$(CONFIG_SND_SOC) += s6000/
obj-$(CONFIG_SND_SOC) += sh/
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c
index 30490a259148..594c6c5b7838 100644
--- a/sound/soc/au1x/dbdma2.c
+++ b/sound/soc/au1x/dbdma2.c
@@ -82,7 +82,7 @@ static struct au1xpsc_audio_dmadata *au1xpsc_audio_pcmdma[2];
/* PCM hardware DMA capabilities - platform specific */
static const struct snd_pcm_hardware au1xpsc_pcm_hardware = {
.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED,
+ SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BATCH,
.formats = AU1XPSC_PCM_FMTS,
.period_bytes_min = AU1XPSC_PERIOD_MIN_BYTES,
.period_bytes_max = 4096 * 1024 - 1,
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index b6c7f7a01cb0..1c19ad54a9f9 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -35,7 +35,10 @@ config SND_SOC_ALL_CODECS
select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8900 if I2C
select SND_SOC_WM8903 if I2C
+ select SND_SOC_WM8940 if I2C
+ select SND_SOC_WM8960 if I2C
select SND_SOC_WM8971 if I2C
+ select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8990 if I2C
select SND_SOC_WM9705 if SND_SOC_AC97_BUS
select SND_SOC_WM9712 if SND_SOC_AC97_BUS
@@ -138,9 +141,18 @@ config SND_SOC_WM8900
config SND_SOC_WM8903
tristate
+config SND_SOC_WM8940
+ tristate
+
+config SND_SOC_WM8960
+ tristate
+
config SND_SOC_WM8971
tristate
+config SND_SOC_WM8988
+ tristate
+
config SND_SOC_WM8990
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 030d2454725f..3d31b6bea834 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -23,7 +23,10 @@ snd-soc-wm8750-objs := wm8750.o
snd-soc-wm8753-objs := wm8753.o
snd-soc-wm8900-objs := wm8900.o
snd-soc-wm8903-objs := wm8903.o
+snd-soc-wm8940-objs := wm8940.o
+snd-soc-wm8960-objs := wm8960.o
snd-soc-wm8971-objs := wm8971.o
+snd-soc-wm8988-objs := wm8988.o
snd-soc-wm8990-objs := wm8990.o
snd-soc-wm9705-objs := wm9705.o
snd-soc-wm9712-objs := wm9712.o
@@ -55,8 +58,10 @@ obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o
obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o
obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o
obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o
+obj-$(CONFIG_SND_SOC_WM8940) += snd-soc-wm8940.o
+obj-$(CONFIG_SND_SOC_WM8960) += snd-soc-wm8960.o
+obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o
obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o
-obj-$(CONFIG_SND_SOC_WM8991) += snd-soc-wm8991.o
obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o
obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index b0d4af145b87..932299bb5d1e 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -53,13 +53,13 @@ struct snd_soc_dai ac97_dai = {
.channels_min = 1,
.channels_max = 2,
.rates = STD_AC97_RATES,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+ .formats = SND_SOC_STD_AC97_FMTS,},
.capture = {
.stream_name = "AC97 Capture",
.channels_min = 1,
.channels_max = 2,
.rates = STD_AC97_RATES,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+ .formats = SND_SOC_STD_AC97_FMTS,},
.ops = &ac97_dai_ops,
};
EXPORT_SYMBOL_GPL(ac97_dai);
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index ddb3b08ac23c..d7440a982d22 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -137,13 +137,13 @@ struct snd_soc_dai ad1980_dai = {
.channels_min = 2,
.channels_max = 6,
.rates = SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE, },
+ .formats = SND_SOC_STD_AC97_FMTS, },
.capture = {
.stream_name = "Capture",
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE, },
+ .formats = SND_SOC_STD_AC97_FMTS, },
};
EXPORT_SYMBOL_GPL(ad1980_dai);
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 7fa09a387622..a32b8226c8a4 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -18,7 +18,7 @@
* - The machine driver's 'startup' function must call
* cs4270_set_dai_sysclk() with the value of MCLK.
* - Only I2S and left-justified modes are supported
- * - Power management is not supported
+ * - Power management is supported
*/
#include <linux/module.h>
@@ -27,6 +27,7 @@
#include <sound/soc.h>
#include <sound/initval.h>
#include <linux/i2c.h>
+#include <linux/delay.h>
#include "cs4270.h"
@@ -56,6 +57,7 @@
#define CS4270_FIRSTREG 0x01
#define CS4270_LASTREG 0x08
#define CS4270_NUMREGS (CS4270_LASTREG - CS4270_FIRSTREG + 1)
+#define CS4270_I2C_INCR 0x80
/* Bit masks for the CS4270 registers */
#define CS4270_CHIPID_ID 0xF0
@@ -64,6 +66,8 @@
#define CS4270_PWRCTL_PDN_ADC 0x20
#define CS4270_PWRCTL_PDN_DAC 0x02
#define CS4270_PWRCTL_PDN 0x01
+#define CS4270_PWRCTL_PDN_ALL \
+ (CS4270_PWRCTL_PDN_ADC | CS4270_PWRCTL_PDN_DAC | CS4270_PWRCTL_PDN)
#define CS4270_MODE_SPEED_MASK 0x30
#define CS4270_MODE_1X 0x00
#define CS4270_MODE_2X 0x10
@@ -109,6 +113,7 @@ struct cs4270_private {
unsigned int mclk; /* Input frequency of the MCLK pin */
unsigned int mode; /* The mode (I2S or left-justified) */
unsigned int slave_mode;
+ unsigned int manual_mute;
};
/**
@@ -295,7 +300,7 @@ static int cs4270_fill_cache(struct snd_soc_codec *codec)
s32 length;
length = i2c_smbus_read_i2c_block_data(i2c_client,
- CS4270_FIRSTREG | 0x80, CS4270_NUMREGS, cache);
+ CS4270_FIRSTREG | CS4270_I2C_INCR, CS4270_NUMREGS, cache);
if (length != CS4270_NUMREGS) {
dev_err(codec->dev, "i2c read failure, addr=0x%x\n",
@@ -453,7 +458,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
}
/**
- * cs4270_mute - enable/disable the CS4270 external mute
+ * cs4270_dai_mute - enable/disable the CS4270 external mute
* @dai: the SOC DAI
* @mute: 0 = disable mute, 1 = enable mute
*
@@ -462,21 +467,52 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
* 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_dai *dai, int mute)
+static int cs4270_dai_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
+ struct cs4270_private *cs4270 = codec->private_data;
int reg6;
reg6 = snd_soc_read(codec, CS4270_MUTE);
if (mute)
reg6 |= CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B;
- else
+ else {
reg6 &= ~(CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B);
+ reg6 |= cs4270->manual_mute;
+ }
return snd_soc_write(codec, CS4270_MUTE, reg6);
}
+/**
+ * cs4270_soc_put_mute - put callback for the 'Master Playback switch'
+ * alsa control.
+ * @kcontrol: mixer control
+ * @ucontrol: control element information
+ *
+ * This function basically passes the arguments on to the generic
+ * snd_soc_put_volsw() function and saves the mute information in
+ * our private data structure. This is because we want to prevent
+ * cs4270_dai_mute() neglecting the user's decision to manually
+ * mute the codec's output.
+ *
+ * Returns 0 for success.
+ */
+static int cs4270_soc_put_mute(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct cs4270_private *cs4270 = codec->private_data;
+ int left = !ucontrol->value.integer.value[0];
+ int right = !ucontrol->value.integer.value[1];
+
+ cs4270->manual_mute = (left ? CS4270_MUTE_DAC_A : 0) |
+ (right ? CS4270_MUTE_DAC_B : 0);
+
+ return snd_soc_put_volsw(kcontrol, ucontrol);
+}
+
/* 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",
@@ -486,7 +522,9 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = {
SOC_SINGLE("Zero Cross Switch", CS4270_TRANS, 5, 1, 0),
SOC_SINGLE("Popguard Switch", CS4270_MODE, 0, 1, 1),
SOC_SINGLE("Auto-Mute Switch", CS4270_MUTE, 5, 1, 0),
- SOC_DOUBLE("Master Capture Switch", CS4270_MUTE, 3, 4, 1, 0)
+ SOC_DOUBLE("Master Capture Switch", CS4270_MUTE, 3, 4, 1, 1),
+ SOC_DOUBLE_EXT("Master Playback Switch", CS4270_MUTE, 0, 1, 1, 1,
+ snd_soc_get_volsw, cs4270_soc_put_mute),
};
/*
@@ -506,7 +544,7 @@ static struct snd_soc_dai_ops cs4270_dai_ops = {
.hw_params = cs4270_hw_params,
.set_sysclk = cs4270_set_dai_sysclk,
.set_fmt = cs4270_set_dai_fmt,
- .digital_mute = cs4270_mute,
+ .digital_mute = cs4270_dai_mute,
};
struct snd_soc_dai cs4270_dai = {
@@ -753,6 +791,57 @@ static struct i2c_device_id cs4270_id[] = {
};
MODULE_DEVICE_TABLE(i2c, cs4270_id);
+#ifdef CONFIG_PM
+
+/* This suspend/resume implementation can handle both - a simple standby
+ * where the codec remains powered, and a full suspend, where the voltage
+ * domain the codec is connected to is teared down and/or any other hardware
+ * reset condition is asserted.
+ *
+ * The codec's own power saving features are enabled in the suspend callback,
+ * and all registers are written back to the hardware when resuming.
+ */
+
+static int cs4270_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+ struct cs4270_private *cs4270 = i2c_get_clientdata(client);
+ struct snd_soc_codec *codec = &cs4270->codec;
+ int reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL;
+
+ return snd_soc_write(codec, CS4270_PWRCTL, reg);
+}
+
+static int cs4270_i2c_resume(struct i2c_client *client)
+{
+ struct cs4270_private *cs4270 = i2c_get_clientdata(client);
+ struct snd_soc_codec *codec = &cs4270->codec;
+ int reg;
+
+ /* In case the device was put to hard reset during sleep, we need to
+ * wait 500ns here before any I2C communication. */
+ ndelay(500);
+
+ /* first restore the entire register cache ... */
+ for (reg = CS4270_FIRSTREG; reg <= CS4270_LASTREG; reg++) {
+ u8 val = snd_soc_read(codec, reg);
+
+ if (i2c_smbus_write_byte_data(client, reg, val)) {
+ dev_err(codec->dev, "i2c write failed\n");
+ return -EIO;
+ }
+ }
+
+ /* ... then disable the power-down bits */
+ reg = snd_soc_read(codec, CS4270_PWRCTL);
+ reg &= ~CS4270_PWRCTL_PDN_ALL;
+
+ return snd_soc_write(codec, CS4270_PWRCTL, reg);
+}
+#else
+#define cs4270_i2c_suspend NULL
+#define cs4270_i2c_resume NULL
+#endif /* CONFIG_PM */
+
/*
* cs4270_i2c_driver - I2C device identification
*
@@ -767,6 +856,8 @@ static struct i2c_driver cs4270_i2c_driver = {
.id_table = cs4270_id,
.probe = cs4270_i2c_probe,
.remove = cs4270_i2c_remove,
+ .suspend = cs4270_i2c_suspend,
+ .resume = cs4270_i2c_resume,
};
/*
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index c3f4afb5d017..21f69df9994c 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -523,6 +523,8 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
case SND_SOC_DAIFMT_I2S:
iface_reg |= TLV320AIC23_FOR_I2S;
break;
+ case SND_SOC_DAIFMT_DSP_A:
+ iface_reg |= TLV320AIC23_LRP_ON;
case SND_SOC_DAIFMT_DSP_B:
iface_reg |= TLV320AIC23_FOR_DSP;
break;
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 921b205de28a..fd392c65f475 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -125,6 +125,11 @@ struct twl4030_priv {
struct snd_pcm_substream *master_substream;
struct snd_pcm_substream *slave_substream;
+
+ unsigned int configured;
+ unsigned int rate;
+ unsigned int sample_bits;
+ unsigned int channels;
};
/*
@@ -232,7 +237,7 @@ static void twl4030_codec_mute(struct snd_soc_codec *codec, int mute)
TWL4030_REG_PRECKL_CTL);
reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKR_CTL);
twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
- reg_val & (~TWL4030_PRECKL_GAIN),
+ reg_val & (~TWL4030_PRECKR_GAIN),
TWL4030_REG_PRECKR_CTL);
/* Disable PLL */
@@ -316,104 +321,60 @@ static void twl4030_power_down(struct snd_soc_codec *codec)
}
/* Earpiece */
-static const char *twl4030_earpiece_texts[] =
- {"Off", "DACL1", "DACL2", "DACR1"};
-
-static const unsigned int twl4030_earpiece_values[] =
- {0x0, 0x1, 0x2, 0x4};
-
-static const struct soc_enum twl4030_earpiece_enum =
- SOC_VALUE_ENUM_SINGLE(TWL4030_REG_EAR_CTL, 1, 0x7,
- ARRAY_SIZE(twl4030_earpiece_texts),
- twl4030_earpiece_texts,
- twl4030_earpiece_values);
-
-static const struct snd_kcontrol_new twl4030_dapm_earpiece_control =
-SOC_DAPM_VALUE_ENUM("Route", twl4030_earpiece_enum);
+static const struct snd_kcontrol_new twl4030_dapm_earpiece_controls[] = {
+ SOC_DAPM_SINGLE("Voice", TWL4030_REG_EAR_CTL, 0, 1, 0),
+ SOC_DAPM_SINGLE("AudioL1", TWL4030_REG_EAR_CTL, 1, 1, 0),
+ SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_EAR_CTL, 2, 1, 0),
+ SOC_DAPM_SINGLE("AudioR1", TWL4030_REG_EAR_CTL, 3, 1, 0),
+};
/* PreDrive Left */
-static const char *twl4030_predrivel_texts[] =
- {"Off", "DACL1", "DACL2", "DACR2"};
-
-static const unsigned int twl4030_predrivel_values[] =
- {0x0, 0x1, 0x2, 0x4};
-
-static const struct soc_enum twl4030_predrivel_enum =
- SOC_VALUE_ENUM_SINGLE(TWL4030_REG_PREDL_CTL, 1, 0x7,
- ARRAY_SIZE(twl4030_predrivel_texts),
- twl4030_predrivel_texts,
- twl4030_predrivel_values);
-
-static const struct snd_kcontrol_new twl4030_dapm_predrivel_control =
-SOC_DAPM_VALUE_ENUM("Route", twl4030_predrivel_enum);
+static const struct snd_kcontrol_new twl4030_dapm_predrivel_controls[] = {
+ SOC_DAPM_SINGLE("Voice", TWL4030_REG_PREDL_CTL, 0, 1, 0),
+ SOC_DAPM_SINGLE("AudioL1", TWL4030_REG_PREDL_CTL, 1, 1, 0),
+ SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_PREDL_CTL, 2, 1, 0),
+ SOC_DAPM_SINGLE("AudioR2", TWL4030_REG_PREDL_CTL, 3, 1, 0),
+};
/* PreDrive Right */
-static const char *twl4030_predriver_texts[] =
- {"Off", "DACR1", "DACR2", "DACL2"};
-
-static const unsigned int twl4030_predriver_values[] =
- {0x0, 0x1, 0x2, 0x4};
-
-static const struct soc_enum twl4030_predriver_enum =
- SOC_VALUE_ENUM_SINGLE(TWL4030_REG_PREDR_CTL, 1, 0x7,
- ARRAY_SIZE(twl4030_predriver_texts),
- twl4030_predriver_texts,
- twl4030_predriver_values);
-
-static const struct snd_kcontrol_new twl4030_dapm_predriver_control =
-SOC_DAPM_VALUE_ENUM("Route", twl4030_predriver_enum);
+static const struct snd_kcontrol_new twl4030_dapm_predriver_controls[] = {
+ SOC_DAPM_SINGLE("Voice", TWL4030_REG_PREDR_CTL, 0, 1, 0),
+ SOC_DAPM_SINGLE("AudioR1", TWL4030_REG_PREDR_CTL, 1, 1, 0),
+ SOC_DAPM_SINGLE("AudioR2", TWL4030_REG_PREDR_CTL, 2, 1, 0),
+ SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_PREDR_CTL, 3, 1, 0),
+};
/* Headset Left */
-static const char *twl4030_hsol_texts[] =
- {"Off", "DACL1", "DACL2"};
-
-static const struct soc_enum twl4030_hsol_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_HS_SEL, 1,
- ARRAY_SIZE(twl4030_hsol_texts),
- twl4030_hsol_texts);
-
-static const struct snd_kcontrol_new twl4030_dapm_hsol_control =
-SOC_DAPM_ENUM("Route", twl4030_hsol_enum);
+static const struct snd_kcontrol_new twl4030_dapm_hsol_controls[] = {
+ SOC_DAPM_SINGLE("Voice", TWL4030_REG_HS_SEL, 0, 1, 0),
+ SOC_DAPM_SINGLE("AudioL1", TWL4030_REG_HS_SEL, 1, 1, 0),
+ SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_HS_SEL, 2, 1, 0),
+};
/* Headset Right */
-static const char *twl4030_hsor_texts[] =
- {"Off", "DACR1", "DACR2"};
-
-static const struct soc_enum twl4030_hsor_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_HS_SEL, 4,
- ARRAY_SIZE(twl4030_hsor_texts),
- twl4030_hsor_texts);
-
-static const struct snd_kcontrol_new twl4030_dapm_hsor_control =
-SOC_DAPM_ENUM("Route", twl4030_hsor_enum);
+static const struct snd_kcontrol_new twl4030_dapm_hsor_controls[] = {
+ SOC_DAPM_SINGLE("Voice", TWL4030_REG_HS_SEL, 3, 1, 0),
+ SOC_DAPM_SINGLE("AudioR1", TWL4030_REG_HS_SEL, 4, 1, 0),
+ SOC_DAPM_SINGLE("AudioR2", TWL4030_REG_HS_SEL, 5, 1, 0),
+};
/* Carkit Left */
-static const char *twl4030_carkitl_texts[] =
- {"Off", "DACL1", "DACL2"};
-
-static const struct soc_enum twl4030_carkitl_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_PRECKL_CTL, 1,
- ARRAY_SIZE(twl4030_carkitl_texts),
- twl4030_carkitl_texts);
-
-static const struct snd_kcontrol_new twl4030_dapm_carkitl_control =
-SOC_DAPM_ENUM("Route", twl4030_carkitl_enum);
+static const struct snd_kcontrol_new twl4030_dapm_carkitl_controls[] = {
+ SOC_DAPM_SINGLE("Voice", TWL4030_REG_PRECKL_CTL, 0, 1, 0),
+ SOC_DAPM_SINGLE("AudioL1", TWL4030_REG_PRECKL_CTL, 1, 1, 0),
+ SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_PRECKL_CTL, 2, 1, 0),
+};
/* Carkit Right */
-static const char *twl4030_carkitr_texts[] =
- {"Off", "DACR1", "DACR2"};
-
-static const struct soc_enum twl4030_carkitr_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_PRECKR_CTL, 1,
- ARRAY_SIZE(twl4030_carkitr_texts),
- twl4030_carkitr_texts);
-
-static const struct snd_kcontrol_new twl4030_dapm_carkitr_control =
-SOC_DAPM_ENUM("Route", twl4030_carkitr_enum);
+static const struct snd_kcontrol_new twl4030_dapm_carkitr_controls[] = {
+ SOC_DAPM_SINGLE("Voice", TWL4030_REG_PRECKR_CTL, 0, 1, 0),
+ SOC_DAPM_SINGLE("AudioR1", TWL4030_REG_PRECKR_CTL, 1, 1, 0),
+ SOC_DAPM_SINGLE("AudioR2", TWL4030_REG_PRECKR_CTL, 2, 1, 0),
+};
/* Handsfree Left */
static const char *twl4030_handsfreel_texts[] =
- {"Voice", "DACL1", "DACL2", "DACR2"};
+ {"Voice", "AudioL1", "AudioL2", "AudioR2"};
static const struct soc_enum twl4030_handsfreel_enum =
SOC_ENUM_SINGLE(TWL4030_REG_HFL_CTL, 0,
@@ -425,7 +386,7 @@ SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum);
/* Handsfree Right */
static const char *twl4030_handsfreer_texts[] =
- {"Voice", "DACR1", "DACR2", "DACL2"};
+ {"Voice", "AudioR1", "AudioR2", "AudioL2"};
static const struct soc_enum twl4030_handsfreer_enum =
SOC_ENUM_SINGLE(TWL4030_REG_HFR_CTL, 0,
@@ -435,6 +396,31 @@ static const struct soc_enum twl4030_handsfreer_enum =
static const struct snd_kcontrol_new twl4030_dapm_handsfreer_control =
SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum);
+/* Vibra */
+/* Vibra audio path selection */
+static const char *twl4030_vibra_texts[] =
+ {"AudioL1", "AudioR1", "AudioL2", "AudioR2"};
+
+static const struct soc_enum twl4030_vibra_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 2,
+ ARRAY_SIZE(twl4030_vibra_texts),
+ twl4030_vibra_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_vibra_control =
+SOC_DAPM_ENUM("Route", twl4030_vibra_enum);
+
+/* Vibra path selection: local vibrator (PWM) or audio driven */
+static const char *twl4030_vibrapath_texts[] =
+ {"Local vibrator", "Audio"};
+
+static const struct soc_enum twl4030_vibrapath_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 4,
+ ARRAY_SIZE(twl4030_vibrapath_texts),
+ twl4030_vibrapath_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_vibrapath_control =
+SOC_DAPM_ENUM("Route", twl4030_vibrapath_enum);
+
/* Left analog microphone selection */
static const char *twl4030_analoglmic_texts[] =
{"Off", "Main mic", "Headset mic", "AUXL", "Carkit mic"};
@@ -507,6 +493,10 @@ static const struct snd_kcontrol_new twl4030_dapm_abypassr2_control =
static const struct snd_kcontrol_new twl4030_dapm_abypassl2_control =
SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXL2_APGA_CTL, 2, 1, 0);
+/* Analog bypass for Voice */
+static const struct snd_kcontrol_new twl4030_dapm_abypassv_control =
+ SOC_DAPM_SINGLE("Switch", TWL4030_REG_VDL_APGA_CTL, 2, 1, 0);
+
/* Digital bypass gain, 0 mutes the bypass */
static const unsigned int twl4030_dapm_dbypass_tlv[] = {
TLV_DB_RANGE_HEAD(2),
@@ -526,6 +516,18 @@ static const struct snd_kcontrol_new twl4030_dapm_dbypassr_control =
TWL4030_REG_ATX2ARXPGA, 0, 7, 0,
twl4030_dapm_dbypass_tlv);
+/*
+ * Voice Sidetone GAIN volume control:
+ * from -51 to -10 dB in 1 dB steps (mute instead of -51 dB)
+ */
+static DECLARE_TLV_DB_SCALE(twl4030_dapm_dbypassv_tlv, -5100, 100, 1);
+
+/* Digital bypass voice: sidetone (VUL -> VDL)*/
+static const struct snd_kcontrol_new twl4030_dapm_dbypassv_control =
+ SOC_DAPM_SINGLE_TLV("Volume",
+ TWL4030_REG_VSTPGA, 0, 0x29, 0,
+ twl4030_dapm_dbypassv_tlv);
+
static int micpath_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -624,7 +626,7 @@ static int bypass_event(struct snd_soc_dapm_widget *w,
struct soc_mixer_control *m =
(struct soc_mixer_control *)w->kcontrols->private_value;
struct twl4030_priv *twl4030 = w->codec->private_data;
- unsigned char reg;
+ unsigned char reg, misc;
reg = twl4030_read_reg_cache(w->codec, m->reg);
@@ -636,14 +638,34 @@ static int bypass_event(struct snd_soc_dapm_widget *w,
else
twl4030->bypass_state &=
~(1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL));
+ } else if (m->reg == TWL4030_REG_VDL_APGA_CTL) {
+ /* Analog voice bypass */
+ if (reg & (1 << m->shift))
+ twl4030->bypass_state |= (1 << 4);
+ else
+ twl4030->bypass_state &= ~(1 << 4);
+ } else if (m->reg == TWL4030_REG_VSTPGA) {
+ /* Voice digital bypass */
+ if (reg)
+ twl4030->bypass_state |= (1 << 5);
+ else
+ twl4030->bypass_state &= ~(1 << 5);
} else {
/* Digital bypass */
if (reg & (0x7 << m->shift))
- twl4030->bypass_state |= (1 << (m->shift ? 5 : 4));
+ twl4030->bypass_state |= (1 << (m->shift ? 7 : 6));
else
- twl4030->bypass_state &= ~(1 << (m->shift ? 5 : 4));
+ twl4030->bypass_state &= ~(1 << (m->shift ? 7 : 6));
}
+ /* Enable master analog loopback mode if any analog switch is enabled*/
+ misc = twl4030_read_reg_cache(w->codec, TWL4030_REG_MISC_SET_1);
+ if (twl4030->bypass_state & 0x1F)
+ misc |= TWL4030_FMLOOP_EN;
+ else
+ misc &= ~TWL4030_FMLOOP_EN;
+ twl4030_write(w->codec, TWL4030_REG_MISC_SET_1, misc);
+
if (w->codec->bias_level == SND_SOC_BIAS_STANDBY) {
if (twl4030->bypass_state)
twl4030_codec_mute(w->codec, 0);
@@ -824,6 +846,12 @@ static DECLARE_TLV_DB_SCALE(digital_fine_tlv, -6300, 100, 1);
static DECLARE_TLV_DB_SCALE(digital_coarse_tlv, 0, 600, 0);
/*
+ * Voice Downlink GAIN volume control:
+ * from -37 to 12 dB in 1 dB steps (mute instead of -37 dB)
+ */
+static DECLARE_TLV_DB_SCALE(digital_voice_downlink_tlv, -3700, 100, 1);
+
+/*
* Analog playback gain
* -24 dB to 12 dB in 2 dB steps
*/
@@ -836,6 +864,12 @@ static DECLARE_TLV_DB_SCALE(analog_tlv, -2400, 200, 0);
static DECLARE_TLV_DB_SCALE(output_tvl, -1200, 600, 1);
/*
+ * Gain control for earpiece amplifier
+ * 0 dB to 12 dB in 6 dB steps (mute instead of -6)
+ */
+static DECLARE_TLV_DB_SCALE(output_ear_tvl, -600, 600, 1);
+
+/*
* Capture gain after the ADCs
* from 0 dB to 31 dB in 1 dB steps
*/
@@ -858,6 +892,26 @@ static const struct soc_enum twl4030_rampdelay_enum =
ARRAY_SIZE(twl4030_rampdelay_texts),
twl4030_rampdelay_texts);
+/* Vibra H-bridge direction mode */
+static const char *twl4030_vibradirmode_texts[] = {
+ "Vibra H-bridge direction", "Audio data MSB",
+};
+
+static const struct soc_enum twl4030_vibradirmode_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 5,
+ ARRAY_SIZE(twl4030_vibradirmode_texts),
+ twl4030_vibradirmode_texts);
+
+/* Vibra H-bridge direction */
+static const char *twl4030_vibradir_texts[] = {
+ "Positive polarity", "Negative polarity",
+};
+
+static const struct soc_enum twl4030_vibradir_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 1,
+ ARRAY_SIZE(twl4030_vibradir_texts),
+ twl4030_vibradir_texts);
+
static const struct snd_kcontrol_new twl4030_snd_controls[] = {
/* Common playback gain controls */
SOC_DOUBLE_R_TLV("DAC1 Digital Fine Playback Volume",
@@ -887,6 +941,16 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = {
TWL4030_REG_ARXL2_APGA_CTL, TWL4030_REG_ARXR2_APGA_CTL,
1, 1, 0),
+ /* Common voice downlink gain controls */
+ SOC_SINGLE_TLV("DAC Voice Digital Downlink Volume",
+ TWL4030_REG_VRXPGA, 0, 0x31, 0, digital_voice_downlink_tlv),
+
+ SOC_SINGLE_TLV("DAC Voice Analog Downlink Volume",
+ TWL4030_REG_VDL_APGA_CTL, 3, 0x12, 1, analog_tlv),
+
+ SOC_SINGLE("DAC Voice Analog Downlink Switch",
+ TWL4030_REG_VDL_APGA_CTL, 1, 1, 0),
+
/* Separate output gain controls */
SOC_DOUBLE_R_TLV_TWL4030("PreDriv Playback Volume",
TWL4030_REG_PREDL_CTL, TWL4030_REG_PREDR_CTL,
@@ -900,7 +964,7 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = {
4, 3, 0, output_tvl),
SOC_SINGLE_TLV_TWL4030("Earpiece Playback Volume",
- TWL4030_REG_EAR_CTL, 4, 3, 0, output_tvl),
+ TWL4030_REG_EAR_CTL, 4, 3, 0, output_ear_tvl),
/* Common capture gain controls */
SOC_DOUBLE_R_TLV("TX1 Digital Capture Volume",
@@ -914,6 +978,9 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = {
0, 3, 5, 0, input_gain_tlv),
SOC_ENUM("HS ramp delay", twl4030_rampdelay_enum),
+
+ SOC_ENUM("Vibra H-bridge mode", twl4030_vibradirmode_enum),
+ SOC_ENUM("Vibra H-bridge direction", twl4030_vibradir_enum),
};
static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
@@ -941,6 +1008,7 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("CARKITR"),
SND_SOC_DAPM_OUTPUT("HFL"),
SND_SOC_DAPM_OUTPUT("HFR"),
+ SND_SOC_DAPM_OUTPUT("VIBRA"),
/* DACs */
SND_SOC_DAPM_DAC("DAC Right1", "Right Front Playback",
@@ -951,6 +1019,8 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_DAC("DAC Left2", "Left Rear Playback",
SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_DAC("DAC Voice", "Voice Playback",
+ SND_SOC_NOPM, 0, 0),
/* Analog PGAs */
SND_SOC_DAPM_PGA("ARXR1_APGA", TWL4030_REG_ARXR1_APGA_CTL,
@@ -961,6 +1031,8 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
0, 0, NULL, 0),
SND_SOC_DAPM_PGA("ARXL2_APGA", TWL4030_REG_ARXL2_APGA_CTL,
0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("VDL_APGA", TWL4030_REG_VDL_APGA_CTL,
+ 0, 0, NULL, 0),
/* Analog bypasses */
SND_SOC_DAPM_SWITCH_E("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0,
@@ -975,6 +1047,9 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
SND_SOC_DAPM_SWITCH_E("Left2 Analog Loopback", SND_SOC_NOPM, 0, 0,
&twl4030_dapm_abypassl2_control,
bypass_event, SND_SOC_DAPM_POST_REG),
+ SND_SOC_DAPM_SWITCH_E("Voice Analog Loopback", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_abypassv_control,
+ bypass_event, SND_SOC_DAPM_POST_REG),
/* Digital bypasses */
SND_SOC_DAPM_SWITCH_E("Left Digital Loopback", SND_SOC_NOPM, 0, 0,
@@ -983,6 +1058,9 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
SND_SOC_DAPM_SWITCH_E("Right Digital Loopback", SND_SOC_NOPM, 0, 0,
&twl4030_dapm_dbypassr_control, bypass_event,
SND_SOC_DAPM_POST_REG),
+ SND_SOC_DAPM_SWITCH_E("Voice Digital Loopback", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_dbypassv_control, bypass_event,
+ SND_SOC_DAPM_POST_REG),
SND_SOC_DAPM_MIXER("Analog R1 Playback Mixer", TWL4030_REG_AVDAC_CTL,
0, 0, NULL, 0),
@@ -992,27 +1070,38 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
2, 0, NULL, 0),
SND_SOC_DAPM_MIXER("Analog L2 Playback Mixer", TWL4030_REG_AVDAC_CTL,
3, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("Analog Voice Playback Mixer", TWL4030_REG_AVDAC_CTL,
+ 4, 0, NULL, 0),
- /* Output MUX controls */
+ /* Output MIXER controls */
/* Earpiece */
- SND_SOC_DAPM_VALUE_MUX("Earpiece Mux", SND_SOC_NOPM, 0, 0,
- &twl4030_dapm_earpiece_control),
+ SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_earpiece_controls[0],
+ ARRAY_SIZE(twl4030_dapm_earpiece_controls)),
/* PreDrivL/R */
- SND_SOC_DAPM_VALUE_MUX("PredriveL Mux", SND_SOC_NOPM, 0, 0,
- &twl4030_dapm_predrivel_control),
- SND_SOC_DAPM_VALUE_MUX("PredriveR Mux", SND_SOC_NOPM, 0, 0,
- &twl4030_dapm_predriver_control),
+ SND_SOC_DAPM_MIXER("PredriveL Mixer", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_predrivel_controls[0],
+ ARRAY_SIZE(twl4030_dapm_predrivel_controls)),
+ SND_SOC_DAPM_MIXER("PredriveR Mixer", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_predriver_controls[0],
+ ARRAY_SIZE(twl4030_dapm_predriver_controls)),
/* HeadsetL/R */
- SND_SOC_DAPM_MUX_E("HeadsetL Mux", SND_SOC_NOPM, 0, 0,
- &twl4030_dapm_hsol_control, headsetl_event,
- SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MUX("HeadsetR Mux", SND_SOC_NOPM, 0, 0,
- &twl4030_dapm_hsor_control),
+ SND_SOC_DAPM_MIXER_E("HeadsetL Mixer", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_hsol_controls[0],
+ ARRAY_SIZE(twl4030_dapm_hsol_controls), headsetl_event,
+ SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MIXER("HeadsetR Mixer", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_hsor_controls[0],
+ ARRAY_SIZE(twl4030_dapm_hsor_controls)),
/* CarkitL/R */
- SND_SOC_DAPM_MUX("CarkitL Mux", SND_SOC_NOPM, 0, 0,
- &twl4030_dapm_carkitl_control),
- SND_SOC_DAPM_MUX("CarkitR Mux", SND_SOC_NOPM, 0, 0,
- &twl4030_dapm_carkitr_control),
+ SND_SOC_DAPM_MIXER("CarkitL Mixer", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_carkitl_controls[0],
+ ARRAY_SIZE(twl4030_dapm_carkitl_controls)),
+ SND_SOC_DAPM_MIXER("CarkitR Mixer", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_carkitr_controls[0],
+ ARRAY_SIZE(twl4030_dapm_carkitr_controls)),
+
+ /* Output MUX controls */
/* HandsfreeL/R */
SND_SOC_DAPM_MUX_E("HandsfreeL Mux", TWL4030_REG_HFL_CTL, 5, 0,
&twl4030_dapm_handsfreel_control, handsfree_event,
@@ -1020,6 +1109,11 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
SND_SOC_DAPM_MUX_E("HandsfreeR Mux", TWL4030_REG_HFR_CTL, 5, 0,
&twl4030_dapm_handsfreer_control, handsfree_event,
SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
+ /* Vibra */
+ SND_SOC_DAPM_MUX("Vibra Mux", TWL4030_REG_VIBRA_CTL, 0, 0,
+ &twl4030_dapm_vibra_control),
+ SND_SOC_DAPM_MUX("Vibra Route", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_vibrapath_control),
/* Introducing four virtual ADC, since TWL4030 have four channel for
capture */
@@ -1071,58 +1165,76 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Analog R1 Playback Mixer", NULL, "DAC Right1"},
{"Analog L2 Playback Mixer", NULL, "DAC Left2"},
{"Analog R2 Playback Mixer", NULL, "DAC Right2"},
+ {"Analog Voice Playback Mixer", NULL, "DAC Voice"},
{"ARXL1_APGA", NULL, "Analog L1 Playback Mixer"},
{"ARXR1_APGA", NULL, "Analog R1 Playback Mixer"},
{"ARXL2_APGA", NULL, "Analog L2 Playback Mixer"},
{"ARXR2_APGA", NULL, "Analog R2 Playback Mixer"},
+ {"VDL_APGA", NULL, "Analog Voice Playback Mixer"},
/* Internal playback routings */
/* Earpiece */
- {"Earpiece Mux", "DACL1", "ARXL1_APGA"},
- {"Earpiece Mux", "DACL2", "ARXL2_APGA"},
- {"Earpiece Mux", "DACR1", "ARXR1_APGA"},
+ {"Earpiece Mixer", "Voice", "VDL_APGA"},
+ {"Earpiece Mixer", "AudioL1", "ARXL1_APGA"},
+ {"Earpiece Mixer", "AudioL2", "ARXL2_APGA"},
+ {"Earpiece Mixer", "AudioR1", "ARXR1_APGA"},
/* PreDrivL */
- {"PredriveL Mux", "DACL1", "ARXL1_APGA"},
- {"PredriveL Mux", "DACL2", "ARXL2_APGA"},
- {"PredriveL Mux", "DACR2", "ARXR2_APGA"},
+ {"PredriveL Mixer", "Voice", "VDL_APGA"},
+ {"PredriveL Mixer", "AudioL1", "ARXL1_APGA"},
+ {"PredriveL Mixer", "AudioL2", "ARXL2_APGA"},
+ {"PredriveL Mixer", "AudioR2", "ARXR2_APGA"},
/* PreDrivR */
- {"PredriveR Mux", "DACR1", "ARXR1_APGA"},
- {"PredriveR Mux", "DACR2", "ARXR2_APGA"},
- {"PredriveR Mux", "DACL2", "ARXL2_APGA"},
+ {"PredriveR Mixer", "Voice", "VDL_APGA"},
+ {"PredriveR Mixer", "AudioR1", "ARXR1_APGA"},
+ {"PredriveR Mixer", "AudioR2", "ARXR2_APGA"},
+ {"PredriveR Mixer", "AudioL2", "ARXL2_APGA"},
/* HeadsetL */
- {"HeadsetL Mux", "DACL1", "ARXL1_APGA"},
- {"HeadsetL Mux", "DACL2", "ARXL2_APGA"},
+ {"HeadsetL Mixer", "Voice", "VDL_APGA"},
+ {"HeadsetL Mixer", "AudioL1", "ARXL1_APGA"},
+ {"HeadsetL Mixer", "AudioL2", "ARXL2_APGA"},
/* HeadsetR */
- {"HeadsetR Mux", "DACR1", "ARXR1_APGA"},
- {"HeadsetR Mux", "DACR2", "ARXR2_APGA"},
+ {"HeadsetR Mixer", "Voice", "VDL_APGA"},
+ {"HeadsetR Mixer", "AudioR1", "ARXR1_APGA"},
+ {"HeadsetR Mixer", "AudioR2", "ARXR2_APGA"},
/* CarkitL */
- {"CarkitL Mux", "DACL1", "ARXL1_APGA"},
- {"CarkitL Mux", "DACL2", "ARXL2_APGA"},
+ {"CarkitL Mixer", "Voice", "VDL_APGA"},
+ {"CarkitL Mixer", "AudioL1", "ARXL1_APGA"},
+ {"CarkitL Mixer", "AudioL2", "ARXL2_APGA"},
/* CarkitR */
- {"CarkitR Mux", "DACR1", "ARXR1_APGA"},
- {"CarkitR Mux", "DACR2", "ARXR2_APGA"},
+ {"CarkitR Mixer", "Voice", "VDL_APGA"},
+ {"CarkitR Mixer", "AudioR1", "ARXR1_APGA"},
+ {"CarkitR Mixer", "AudioR2", "ARXR2_APGA"},
/* HandsfreeL */
- {"HandsfreeL Mux", "DACL1", "ARXL1_APGA"},
- {"HandsfreeL Mux", "DACL2", "ARXL2_APGA"},
- {"HandsfreeL Mux", "DACR2", "ARXR2_APGA"},
+ {"HandsfreeL Mux", "Voice", "VDL_APGA"},
+ {"HandsfreeL Mux", "AudioL1", "ARXL1_APGA"},
+ {"HandsfreeL Mux", "AudioL2", "ARXL2_APGA"},
+ {"HandsfreeL Mux", "AudioR2", "ARXR2_APGA"},
/* HandsfreeR */
- {"HandsfreeR Mux", "DACR1", "ARXR1_APGA"},
- {"HandsfreeR Mux", "DACR2", "ARXR2_APGA"},
- {"HandsfreeR Mux", "DACL2", "ARXL2_APGA"},
+ {"HandsfreeR Mux", "Voice", "VDL_APGA"},
+ {"HandsfreeR Mux", "AudioR1", "ARXR1_APGA"},
+ {"HandsfreeR Mux", "AudioR2", "ARXR2_APGA"},
+ {"HandsfreeR Mux", "AudioL2", "ARXL2_APGA"},
+ /* Vibra */
+ {"Vibra Mux", "AudioL1", "DAC Left1"},
+ {"Vibra Mux", "AudioR1", "DAC Right1"},
+ {"Vibra Mux", "AudioL2", "DAC Left2"},
+ {"Vibra Mux", "AudioR2", "DAC Right2"},
/* outputs */
{"OUTL", NULL, "ARXL2_APGA"},
{"OUTR", NULL, "ARXR2_APGA"},
- {"EARPIECE", NULL, "Earpiece Mux"},
- {"PREDRIVEL", NULL, "PredriveL Mux"},
- {"PREDRIVER", NULL, "PredriveR Mux"},
- {"HSOL", NULL, "HeadsetL Mux"},
- {"HSOR", NULL, "HeadsetR Mux"},
- {"CARKITL", NULL, "CarkitL Mux"},
- {"CARKITR", NULL, "CarkitR Mux"},
+ {"EARPIECE", NULL, "Earpiece Mixer"},
+ {"PREDRIVEL", NULL, "PredriveL Mixer"},
+ {"PREDRIVER", NULL, "PredriveR Mixer"},
+ {"HSOL", NULL, "HeadsetL Mixer"},
+ {"HSOR", NULL, "HeadsetR Mixer"},
+ {"CARKITL", NULL, "CarkitL Mixer"},
+ {"CARKITR", NULL, "CarkitR Mixer"},
{"HFL", NULL, "HandsfreeL Mux"},
{"HFR", NULL, "HandsfreeR Mux"},
+ {"Vibra Route", "Audio", "Vibra Mux"},
+ {"VIBRA", NULL, "Vibra Route"},
/* Capture path */
{"Analog Left Capture Route", "Main mic", "MAINMIC"},
@@ -1162,18 +1274,22 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Left1 Analog Loopback", "Switch", "Analog Left Capture Route"},
{"Right2 Analog Loopback", "Switch", "Analog Right Capture Route"},
{"Left2 Analog Loopback", "Switch", "Analog Left Capture Route"},
+ {"Voice Analog Loopback", "Switch", "Analog Left Capture Route"},
{"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"},
{"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"},
{"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"},
{"Analog L2 Playback Mixer", NULL, "Left2 Analog Loopback"},
+ {"Analog Voice Playback Mixer", NULL, "Voice Analog Loopback"},
/* Digital bypass routes */
{"Right Digital Loopback", "Volume", "TX1 Capture Route"},
{"Left Digital Loopback", "Volume", "TX1 Capture Route"},
+ {"Voice Digital Loopback", "Volume", "TX2 Capture Route"},
{"Analog R2 Playback Mixer", NULL, "Right Digital Loopback"},
{"Analog L2 Playback Mixer", NULL, "Left Digital Loopback"},
+ {"Analog Voice Playback Mixer", NULL, "Voice Digital Loopback"},
};
@@ -1220,6 +1336,58 @@ static int twl4030_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
+static void twl4030_constraints(struct twl4030_priv *twl4030,
+ struct snd_pcm_substream *mst_substream)
+{
+ struct snd_pcm_substream *slv_substream;
+
+ /* Pick the stream, which need to be constrained */
+ if (mst_substream == twl4030->master_substream)
+ slv_substream = twl4030->slave_substream;
+ else if (mst_substream == twl4030->slave_substream)
+ slv_substream = twl4030->master_substream;
+ else /* This should not happen.. */
+ return;
+
+ /* Set the constraints according to the already configured stream */
+ snd_pcm_hw_constraint_minmax(slv_substream->runtime,
+ SNDRV_PCM_HW_PARAM_RATE,
+ twl4030->rate,
+ twl4030->rate);
+
+ snd_pcm_hw_constraint_minmax(slv_substream->runtime,
+ SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
+ twl4030->sample_bits,
+ twl4030->sample_bits);
+
+ snd_pcm_hw_constraint_minmax(slv_substream->runtime,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ twl4030->channels,
+ twl4030->channels);
+}
+
+/* In case of 4 channel mode, the RX1 L/R for playback and the TX2 L/R for
+ * capture has to be enabled/disabled. */
+static void twl4030_tdm_enable(struct snd_soc_codec *codec, int direction,
+ int enable)
+{
+ u8 reg, mask;
+
+ reg = twl4030_read_reg_cache(codec, TWL4030_REG_OPTION);
+
+ if (direction == SNDRV_PCM_STREAM_PLAYBACK)
+ mask = TWL4030_ARXL1_VRX_EN | TWL4030_ARXR1_EN;
+ else
+ mask = TWL4030_ATXL2_VTXL_EN | TWL4030_ATXR2_VTXR_EN;
+
+ if (enable)
+ reg |= mask;
+ else
+ reg &= ~mask;
+
+ twl4030_write(codec, TWL4030_REG_OPTION, reg);
+}
+
static int twl4030_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
@@ -1228,26 +1396,25 @@ static int twl4030_startup(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = socdev->card->codec;
struct twl4030_priv *twl4030 = codec->private_data;
- /* If we already have a playback or capture going then constrain
- * this substream to match it.
- */
if (twl4030->master_substream) {
- struct snd_pcm_runtime *master_runtime;
- master_runtime = twl4030->master_substream->runtime;
-
- snd_pcm_hw_constraint_minmax(substream->runtime,
- SNDRV_PCM_HW_PARAM_RATE,
- master_runtime->rate,
- master_runtime->rate);
-
- snd_pcm_hw_constraint_minmax(substream->runtime,
- SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
- master_runtime->sample_bits,
- master_runtime->sample_bits);
-
twl4030->slave_substream = substream;
- } else
+ /* The DAI has one configuration for playback and capture, so
+ * if the DAI has been already configured then constrain this
+ * substream to match it. */
+ if (twl4030->configured)
+ twl4030_constraints(twl4030, twl4030->master_substream);
+ } else {
+ if (!(twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE) &
+ TWL4030_OPTION_1)) {
+ /* In option2 4 channel is not supported, set the
+ * constraint for the first stream for channels, the
+ * second stream will 'inherit' this cosntraint */
+ snd_pcm_hw_constraint_minmax(substream->runtime,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ 2, 2);
+ }
twl4030->master_substream = substream;
+ }
return 0;
}
@@ -1264,6 +1431,17 @@ static void twl4030_shutdown(struct snd_pcm_substream *substream,
twl4030->master_substream = twl4030->slave_substream;
twl4030->slave_substream = NULL;
+
+ /* If all streams are closed, or the remaining stream has not yet
+ * been configured than set the DAI as not configured. */
+ if (!twl4030->master_substream)
+ twl4030->configured = 0;
+ else if (!twl4030->master_substream->runtime->channels)
+ twl4030->configured = 0;
+
+ /* If the closing substream had 4 channel, do the necessary cleanup */
+ if (substream->runtime->channels == 4)
+ twl4030_tdm_enable(codec, substream->stream, 0);
}
static int twl4030_hw_params(struct snd_pcm_substream *substream,
@@ -1276,8 +1454,18 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
struct twl4030_priv *twl4030 = codec->private_data;
u8 mode, old_mode, format, old_format;
- if (substream == twl4030->slave_substream)
- /* Ignoring hw_params for slave substream */
+ /* If the substream has 4 channel, do the necessary setup */
+ if (params_channels(params) == 4) {
+ /* Safety check: are we in the correct operating mode? */
+ if ((twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE) &
+ TWL4030_OPTION_1))
+ twl4030_tdm_enable(codec, substream->stream, 1);
+ else
+ return -EINVAL;
+ }
+
+ if (twl4030->configured)
+ /* Ignoring hw_params for already configured DAI */
return 0;
/* bit rate */
@@ -1357,6 +1545,21 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
/* set CODECPDZ afterwards */
twl4030_codec_enable(codec, 1);
}
+
+ /* Store the important parameters for the DAI configuration and set
+ * the DAI as configured */
+ twl4030->configured = 1;
+ twl4030->rate = params_rate(params);
+ twl4030->sample_bits = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min;
+ twl4030->channels = params_channels(params);
+
+ /* If both playback and capture streams are open, and one of them
+ * is setting the hw parameters right now (since we are here), set
+ * constraints to the other stream to match the current one. */
+ if (twl4030->slave_substream)
+ twl4030_constraints(twl4030, substream);
+
return 0;
}
@@ -1418,6 +1621,9 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
case SND_SOC_DAIFMT_I2S:
format |= TWL4030_AIF_FORMAT_CODEC;
break;
+ case SND_SOC_DAIFMT_DSP_A:
+ format |= TWL4030_AIF_FORMAT_TDM;
+ break;
default:
return -EINVAL;
}
@@ -1437,6 +1643,144 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
return 0;
}
+static int twl4030_voice_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->card->codec;
+ u8 infreq;
+ u8 mode;
+
+ /* If the system master clock is not 26MHz, the voice PCM interface is
+ * not avilable.
+ */
+ infreq = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL)
+ & TWL4030_APLL_INFREQ;
+
+ if (infreq != TWL4030_APLL_INFREQ_26000KHZ) {
+ printk(KERN_ERR "TWL4030 voice startup: "
+ "MCLK is not 26MHz, call set_sysclk() on init\n");
+ return -EINVAL;
+ }
+
+ /* If the codec mode is not option2, the voice PCM interface is not
+ * avilable.
+ */
+ mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE)
+ & TWL4030_OPT_MODE;
+
+ if (mode != TWL4030_OPTION_2) {
+ printk(KERN_ERR "TWL4030 voice startup: "
+ "the codec mode is not option2\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int twl4030_voice_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->card->codec;
+ u8 old_mode, mode;
+
+ /* bit rate */
+ old_mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE)
+ & ~(TWL4030_CODECPDZ);
+ mode = old_mode;
+
+ switch (params_rate(params)) {
+ case 8000:
+ mode &= ~(TWL4030_SEL_16K);
+ break;
+ case 16000:
+ mode |= TWL4030_SEL_16K;
+ break;
+ default:
+ printk(KERN_ERR "TWL4030 voice hw params: unknown rate %d\n",
+ params_rate(params));
+ return -EINVAL;
+ }
+
+ if (mode != old_mode) {
+ /* change rate and set CODECPDZ */
+ twl4030_codec_enable(codec, 0);
+ twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode);
+ twl4030_codec_enable(codec, 1);
+ }
+
+ return 0;
+}
+
+static int twl4030_voice_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u8 infreq;
+
+ switch (freq) {
+ case 26000000:
+ infreq = TWL4030_APLL_INFREQ_26000KHZ;
+ break;
+ default:
+ printk(KERN_ERR "TWL4030 voice set sysclk: unknown rate %d\n",
+ freq);
+ return -EINVAL;
+ }
+
+ infreq |= TWL4030_APLL_EN;
+ twl4030_write(codec, TWL4030_REG_APLL_CTL, infreq);
+
+ return 0;
+}
+
+static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u8 old_format, format;
+
+ /* get format */
+ old_format = twl4030_read_reg_cache(codec, TWL4030_REG_VOICE_IF);
+ format = old_format;
+
+ /* set master/slave audio interface */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFM:
+ format &= ~(TWL4030_VIF_SLAVE_EN);
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ format |= TWL4030_VIF_SLAVE_EN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* clock inversion */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_IB_NF:
+ format &= ~(TWL4030_VIF_FORMAT);
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ format |= TWL4030_VIF_FORMAT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (format != old_format) {
+ /* change format and set CODECPDZ */
+ twl4030_codec_enable(codec, 0);
+ twl4030_write(codec, TWL4030_REG_VOICE_IF, format);
+ twl4030_codec_enable(codec, 1);
+ }
+
+ return 0;
+}
+
#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000)
#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)
@@ -1448,21 +1792,46 @@ static struct snd_soc_dai_ops twl4030_dai_ops = {
.set_fmt = twl4030_set_dai_fmt,
};
-struct snd_soc_dai twl4030_dai = {
+static struct snd_soc_dai_ops twl4030_dai_voice_ops = {
+ .startup = twl4030_voice_startup,
+ .hw_params = twl4030_voice_hw_params,
+ .set_sysclk = twl4030_voice_set_dai_sysclk,
+ .set_fmt = twl4030_voice_set_dai_fmt,
+};
+
+struct snd_soc_dai twl4030_dai[] = {
+{
.name = "twl4030",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
- .channels_max = 2,
+ .channels_max = 4,
.rates = TWL4030_RATES | SNDRV_PCM_RATE_96000,
.formats = TWL4030_FORMATS,},
.capture = {
.stream_name = "Capture",
.channels_min = 2,
- .channels_max = 2,
+ .channels_max = 4,
.rates = TWL4030_RATES,
.formats = TWL4030_FORMATS,},
.ops = &twl4030_dai_ops,
+},
+{
+ .name = "twl4030 Voice",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+ .ops = &twl4030_dai_voice_ops,
+},
};
EXPORT_SYMBOL_GPL(twl4030_dai);
@@ -1503,8 +1872,8 @@ static int twl4030_init(struct snd_soc_device *socdev)
codec->read = twl4030_read_reg_cache;
codec->write = twl4030_write;
codec->set_bias_level = twl4030_set_bias_level;
- codec->dai = &twl4030_dai;
- codec->num_dai = 1;
+ codec->dai = twl4030_dai;
+ codec->num_dai = ARRAY_SIZE(twl4030_dai),
codec->reg_cache_size = sizeof(twl4030_reg);
codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg),
GFP_KERNEL);
@@ -1598,13 +1967,13 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030);
static int __init twl4030_modinit(void)
{
- return snd_soc_register_dai(&twl4030_dai);
+ return snd_soc_register_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai));
}
module_init(twl4030_modinit);
static void __exit twl4030_exit(void)
{
- snd_soc_unregister_dai(&twl4030_dai);
+ snd_soc_unregister_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai));
}
module_exit(twl4030_exit);
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h
index cb63765db1df..3441115136f6 100644
--- a/sound/soc/codecs/twl4030.h
+++ b/sound/soc/codecs/twl4030.h
@@ -113,6 +113,19 @@
#define TWL4030_SEL_16K 0x04
#define TWL4030_CODECPDZ 0x02
#define TWL4030_OPT_MODE 0x01
+#define TWL4030_OPTION_1 (1 << 0)
+#define TWL4030_OPTION_2 (0 << 0)
+
+/* TWL4030_OPTION (0x02) Fields */
+
+#define TWL4030_ATXL1_EN (1 << 0)
+#define TWL4030_ATXR1_EN (1 << 1)
+#define TWL4030_ATXL2_VTXL_EN (1 << 2)
+#define TWL4030_ATXR2_VTXR_EN (1 << 3)
+#define TWL4030_ARXL1_VRX_EN (1 << 4)
+#define TWL4030_ARXR1_EN (1 << 5)
+#define TWL4030_ARXL2_EN (1 << 6)
+#define TWL4030_ARXR2_EN (1 << 7)
/* TWL4030_REG_MICBIAS_CTL (0x04) Fields */
@@ -171,6 +184,17 @@
#define TWL4030_CLK256FS_EN 0x02
#define TWL4030_AIF_EN 0x01
+/* VOICE_IF (0x0F) Fields */
+
+#define TWL4030_VIF_SLAVE_EN 0x80
+#define TWL4030_VIF_DIN_EN 0x40
+#define TWL4030_VIF_DOUT_EN 0x20
+#define TWL4030_VIF_SWAP 0x10
+#define TWL4030_VIF_FORMAT 0x08
+#define TWL4030_VIF_TRI_EN 0x04
+#define TWL4030_VIF_SUB_EN 0x02
+#define TWL4030_VIF_EN 0x01
+
/* EAR_CTL (0x21) */
#define TWL4030_EAR_GAIN 0x30
@@ -236,7 +260,10 @@
#define TWL4030_SMOOTH_ANAVOL_EN 0x02
#define TWL4030_DIGMIC_LR_SWAP_EN 0x01
-extern struct snd_soc_dai twl4030_dai;
+#define TWL4030_DAI_HIFI 0
+#define TWL4030_DAI_VOICE 1
+
+extern struct snd_soc_dai twl4030_dai[2];
extern struct snd_soc_codec_device soc_codec_dev_twl4030;
#endif /* End of __TWL4030_AUDIO_H__ */
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 3b1d0993bed9..0275321ff8ab 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -968,7 +968,7 @@ static int wm8350_pcm_trigger(struct snd_pcm_substream *substream,
* required for LRC in master mode. The DACs or ADCs need a
* valid audio path i.e. pin -> ADC or DAC -> pin before
* the LRC will be enabled in master mode. */
- if (!master && cmd != SNDRV_PCM_TRIGGER_START)
+ if (!master || cmd != SNDRV_PCM_TRIGGER_START)
return 0;
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
diff --git a/sound/soc/codecs/wm8350.h b/sound/soc/codecs/wm8350.h
index d11bd9288cf9..d088eb4b88bb 100644
--- a/sound/soc/codecs/wm8350.h
+++ b/sound/soc/codecs/wm8350.h
@@ -13,6 +13,7 @@
#define _WM8350_H
#include <sound/soc.h>
+#include <linux/mfd/wm8350/audio.h>
extern struct snd_soc_dai wm8350_dai;
extern struct snd_soc_codec_device soc_codec_dev_wm8350;
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 442ea6f160fc..9f6be3d31ac0 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -268,9 +268,11 @@ static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- int reg = kcontrol->private_value & 0xff;
- int reg2 = (kcontrol->private_value >> 24) & 0xff;
+ unsigned int reg = mc->reg;
+ unsigned int reg2 = mc->rreg;
int ret;
u16 val;
@@ -292,15 +294,17 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
return 0;
}
-#define SOC_WM8580_OUT_DOUBLE_R_TLV(xname, reg_left, reg_right, shift, max, invert, tlv_array) \
+#define SOC_WM8580_OUT_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, \
+ xinvert, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
SNDRV_CTL_ELEM_ACCESS_READWRITE, \
.tlv.p = (tlv_array), \
.info = snd_soc_info_volsw_2r, \
.get = snd_soc_get_volsw_2r, .put = wm8580_out_vu, \
- .private_value = (reg_left) | ((shift) << 8) | \
- ((max) << 12) | ((invert) << 20) | ((reg_right) << 24) }
+ .private_value = (unsigned long)&(struct soc_mixer_control) \
+ {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
+ .max = xmax, .invert = xinvert} }
static const struct snd_kcontrol_new wm8580_snd_controls[] = {
SOC_WM8580_OUT_DOUBLE_R_TLV("DAC1 Playback Volume",
@@ -522,7 +526,7 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai,
reg = wm8580_read(codec, WM8580_PLLA4 + offset);
reg &= ~0x3f;
reg |= pll_div.prescale | pll_div.postscale << 1 |
- pll_div.freqmode << 4;
+ pll_div.freqmode << 3;
wm8580_write(codec, WM8580_PLLA4 + offset, reg);
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 8cf571f1a803..d8a9222fbf74 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -217,7 +217,6 @@ struct wm8903_priv {
int sysclk;
/* Reference counts */
- int charge_pump_users;
int class_w_users;
int playback_active;
int capture_active;
@@ -373,6 +372,15 @@ static void wm8903_reset(struct snd_soc_codec *codec)
#define WM8903_OUTPUT_INT 0x2
#define WM8903_OUTPUT_IN 0x1
+static int wm8903_cp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ WARN_ON(event != SND_SOC_DAPM_POST_PMU);
+ mdelay(4);
+
+ return 0;
+}
+
/*
* Event for headphone and line out amplifier power changes. Special
* power up/down sequences are required in order to maximise pop/click
@@ -382,19 +390,20 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
- struct wm8903_priv *wm8903 = codec->private_data;
- struct i2c_client *i2c = codec->control_data;
u16 val;
u16 reg;
+ u16 dcs_reg;
+ u16 dcs_bit;
int shift;
- u16 cp_reg = wm8903_read(codec, WM8903_CHARGE_PUMP_0);
switch (w->reg) {
case WM8903_POWER_MANAGEMENT_2:
reg = WM8903_ANALOGUE_HP_0;
+ dcs_bit = 0 + w->shift;
break;
case WM8903_POWER_MANAGEMENT_3:
reg = WM8903_ANALOGUE_LINEOUT_0;
+ dcs_bit = 2 + w->shift;
break;
default:
BUG();
@@ -419,18 +428,6 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w,
/* Short the output */
val &= ~(WM8903_OUTPUT_SHORT << shift);
wm8903_write(codec, reg, val);
-
- wm8903->charge_pump_users++;
-
- dev_dbg(&i2c->dev, "Charge pump use count now %d\n",
- wm8903->charge_pump_users);
-
- if (wm8903->charge_pump_users == 1) {
- dev_dbg(&i2c->dev, "Enabling charge pump\n");
- wm8903_write(codec, WM8903_CHARGE_PUMP_0,
- cp_reg | WM8903_CP_ENA);
- mdelay(4);
- }
}
if (event & SND_SOC_DAPM_POST_PMU) {
@@ -446,6 +443,11 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w,
val |= (WM8903_OUTPUT_OUT << shift);
wm8903_write(codec, reg, val);
+ /* Enable the DC servo */
+ dcs_reg = wm8903_read(codec, WM8903_DC_SERVO_0);
+ dcs_reg |= dcs_bit;
+ wm8903_write(codec, WM8903_DC_SERVO_0, dcs_reg);
+
/* Remove the short */
val |= (WM8903_OUTPUT_SHORT << shift);
wm8903_write(codec, reg, val);
@@ -458,25 +460,17 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w,
val &= ~(WM8903_OUTPUT_SHORT << shift);
wm8903_write(codec, reg, val);
+ /* Disable the DC servo */
+ dcs_reg = wm8903_read(codec, WM8903_DC_SERVO_0);
+ dcs_reg &= ~dcs_bit;
+ wm8903_write(codec, WM8903_DC_SERVO_0, dcs_reg);
+
/* Then disable the intermediate and output stages */
val &= ~((WM8903_OUTPUT_OUT | WM8903_OUTPUT_INT |
WM8903_OUTPUT_IN) << shift);
wm8903_write(codec, reg, val);
}
- if (event & SND_SOC_DAPM_POST_PMD) {
- wm8903->charge_pump_users--;
-
- dev_dbg(&i2c->dev, "Charge pump use count now %d\n",
- wm8903->charge_pump_users);
-
- if (wm8903->charge_pump_users == 0) {
- dev_dbg(&i2c->dev, "Disabling charge pump\n");
- wm8903_write(codec, WM8903_CHARGE_PUMP_0,
- cp_reg & ~WM8903_CP_ENA);
- }
- }
-
return 0;
}
@@ -539,6 +533,7 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
/* ALSA can only do steps of .01dB */
static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
+static const DECLARE_TLV_DB_SCALE(digital_sidetone_tlv, -3600, 300, 0);
static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
static const DECLARE_TLV_DB_SCALE(drc_tlv_thresh, 0, 75, 0);
@@ -657,6 +652,16 @@ static const struct soc_enum rinput_inv_enum =
SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 4, 3, rinput_mux_text);
+static const char *sidetone_text[] = {
+ "None", "Left", "Right"
+};
+
+static const struct soc_enum lsidetone_enum =
+ SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 2, 3, sidetone_text);
+
+static const struct soc_enum rsidetone_enum =
+ SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 0, 3, sidetone_text);
+
static const struct snd_kcontrol_new wm8903_snd_controls[] = {
/* Input PGAs - No TLV since the scale depends on PGA mode */
@@ -700,6 +705,9 @@ SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8903_ADC_DIGITAL_VOLUME_LEFT,
SOC_ENUM("ADC Companding Mode", adc_companding),
SOC_SINGLE("ADC Companding Switch", WM8903_AUDIO_INTERFACE_0, 3, 1, 0),
+SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8903_DAC_DIGITAL_0, 4, 8,
+ 12, 0, digital_sidetone_tlv),
+
/* DAC */
SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8903_DAC_DIGITAL_VOLUME_LEFT,
WM8903_DAC_DIGITAL_VOLUME_RIGHT, 1, 120, 0, digital_tlv),
@@ -762,6 +770,12 @@ static const struct snd_kcontrol_new rinput_mux =
static const struct snd_kcontrol_new rinput_inv_mux =
SOC_DAPM_ENUM("Right Inverting Input Mux", rinput_inv_enum);
+static const struct snd_kcontrol_new lsidetone_mux =
+ SOC_DAPM_ENUM("DACL Sidetone Mux", lsidetone_enum);
+
+static const struct snd_kcontrol_new rsidetone_mux =
+ SOC_DAPM_ENUM("DACR Sidetone Mux", rsidetone_enum);
+
static const struct snd_kcontrol_new left_output_mixer[] = {
SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0),
SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0),
@@ -828,6 +842,9 @@ SND_SOC_DAPM_PGA("Right Input PGA", WM8903_POWER_MANAGEMENT_0, 0, 0, NULL, 0),
SND_SOC_DAPM_ADC("ADCL", "Left HiFi Capture", WM8903_POWER_MANAGEMENT_6, 1, 0),
SND_SOC_DAPM_ADC("ADCR", "Right HiFi Capture", WM8903_POWER_MANAGEMENT_6, 0, 0),
+SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &lsidetone_mux),
+SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &rsidetone_mux),
+
SND_SOC_DAPM_DAC("DACL", "Left Playback", WM8903_POWER_MANAGEMENT_6, 3, 0),
SND_SOC_DAPM_DAC("DACR", "Right Playback", WM8903_POWER_MANAGEMENT_6, 2, 0),
@@ -844,26 +861,29 @@ SND_SOC_DAPM_MIXER("Right Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 0, 0,
SND_SOC_DAPM_PGA_E("Left Headphone Output PGA", WM8903_POWER_MANAGEMENT_2,
1, 0, NULL, 0, wm8903_output_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
- SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_PGA_E("Right Headphone Output PGA", WM8903_POWER_MANAGEMENT_2,
0, 0, NULL, 0, wm8903_output_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
- SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_PGA_E("Left Line Output PGA", WM8903_POWER_MANAGEMENT_3, 1, 0,
NULL, 0, wm8903_output_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
- SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_PGA_E("Right Line Output PGA", WM8903_POWER_MANAGEMENT_3, 0, 0,
NULL, 0, wm8903_output_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
- SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_PGA("Left Speaker PGA", WM8903_POWER_MANAGEMENT_5, 1, 0,
NULL, 0),
SND_SOC_DAPM_PGA("Right Speaker PGA", WM8903_POWER_MANAGEMENT_5, 0, 0,
NULL, 0),
+SND_SOC_DAPM_SUPPLY("Charge Pump", WM8903_CHARGE_PUMP_0, 0, 0,
+ wm8903_cp_event, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8903_CLOCK_RATES_2, 1, 0, NULL, 0),
};
static const struct snd_soc_dapm_route intercon[] = {
@@ -909,7 +929,19 @@ static const struct snd_soc_dapm_route intercon[] = {
{ "Right Input PGA", NULL, "Right Input Mode Mux" },
{ "ADCL", NULL, "Left Input PGA" },
+ { "ADCL", NULL, "CLK_DSP" },
{ "ADCR", NULL, "Right Input PGA" },
+ { "ADCR", NULL, "CLK_DSP" },
+
+ { "DACL Sidetone", "Left", "ADCL" },
+ { "DACL Sidetone", "Right", "ADCR" },
+ { "DACR Sidetone", "Left", "ADCL" },
+ { "DACR Sidetone", "Right", "ADCR" },
+
+ { "DACL", NULL, "DACL Sidetone" },
+ { "DACL", NULL, "CLK_DSP" },
+ { "DACR", NULL, "DACR Sidetone" },
+ { "DACR", NULL, "CLK_DSP" },
{ "Left Output Mixer", "Left Bypass Switch", "Left Input PGA" },
{ "Left Output Mixer", "Right Bypass Switch", "Right Input PGA" },
@@ -951,6 +983,11 @@ static const struct snd_soc_dapm_route intercon[] = {
{ "ROP", NULL, "Right Speaker PGA" },
{ "RON", NULL, "Right Speaker PGA" },
+
+ { "Left Headphone Output PGA", NULL, "Charge Pump" },
+ { "Right Headphone Output PGA", NULL, "Charge Pump" },
+ { "Left Line Output PGA", NULL, "Charge Pump" },
+ { "Right Line Output PGA", NULL, "Charge Pump" },
};
static int wm8903_add_widgets(struct snd_soc_codec *codec)
@@ -985,6 +1022,11 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec,
wm8903_write(codec, WM8903_CLOCK_RATES_2,
WM8903_CLK_SYS_ENA);
+ /* Change DC servo dither level in startup sequence */
+ wm8903_write(codec, WM8903_WRITE_SEQUENCER_0, 0x11);
+ wm8903_write(codec, WM8903_WRITE_SEQUENCER_1, 0x1257);
+ wm8903_write(codec, WM8903_WRITE_SEQUENCER_2, 0x2);
+
wm8903_run_sequence(codec, 0);
wm8903_sync_reg_cache(codec, codec->reg_cache);
@@ -1277,14 +1319,8 @@ static int wm8903_startup(struct snd_pcm_substream *substream,
if (wm8903->master_substream) {
master_runtime = wm8903->master_substream->runtime;
- dev_dbg(&i2c->dev, "Constraining to %d bits at %dHz\n",
- master_runtime->sample_bits,
- master_runtime->rate);
-
- snd_pcm_hw_constraint_minmax(substream->runtime,
- SNDRV_PCM_HW_PARAM_RATE,
- master_runtime->rate,
- master_runtime->rate);
+ dev_dbg(&i2c->dev, "Constraining to %d bits\n",
+ master_runtime->sample_bits);
snd_pcm_hw_constraint_minmax(substream->runtime,
SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
@@ -1523,6 +1559,7 @@ struct snd_soc_dai wm8903_dai = {
.formats = WM8903_FORMATS,
},
.ops = &wm8903_dai_ops,
+ .symmetric_rates = 1,
};
EXPORT_SYMBOL_GPL(wm8903_dai);
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
new file mode 100644
index 000000000000..a66dacc7cc83
--- /dev/null
+++ b/sound/soc/codecs/wm8940.c
@@ -0,0 +1,955 @@
+/*
+ * wm8940.c -- WM8940 ALSA Soc Audio driver
+ *
+ * Author: Jonathan Cameron <jic23@cam.ac.uk>
+ *
+ * Based on wm8510.c
+ * Copyright 2006 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
+ *
+ * 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.
+ *
+ * Not currently handled:
+ * Notch filter control
+ * AUXMode (inverting vs mixer)
+ * No means to obtain current gain if alc enabled.
+ * No use made of gpio
+ * Fast VMID discharge for power down
+ * Soft Start
+ * DLR and ALR Swaps not enabled
+ * Digital Sidetone not supported
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "wm8940.h"
+
+struct wm8940_priv {
+ unsigned int sysclk;
+ u16 reg_cache[WM8940_CACHEREGNUM];
+ struct snd_soc_codec codec;
+};
+
+static u16 wm8940_reg_defaults[] = {
+ 0x8940, /* Soft Reset */
+ 0x0000, /* Power 1 */
+ 0x0000, /* Power 2 */
+ 0x0000, /* Power 3 */
+ 0x0010, /* Interface Control */
+ 0x0000, /* Companding Control */
+ 0x0140, /* Clock Control */
+ 0x0000, /* Additional Controls */
+ 0x0000, /* GPIO Control */
+ 0x0002, /* Auto Increment Control */
+ 0x0000, /* DAC Control */
+ 0x00FF, /* DAC Volume */
+ 0,
+ 0,
+ 0x0100, /* ADC Control */
+ 0x00FF, /* ADC Volume */
+ 0x0000, /* Notch Filter 1 Control 1 */
+ 0x0000, /* Notch Filter 1 Control 2 */
+ 0x0000, /* Notch Filter 2 Control 1 */
+ 0x0000, /* Notch Filter 2 Control 2 */
+ 0x0000, /* Notch Filter 3 Control 1 */
+ 0x0000, /* Notch Filter 3 Control 2 */
+ 0x0000, /* Notch Filter 4 Control 1 */
+ 0x0000, /* Notch Filter 4 Control 2 */
+ 0x0032, /* DAC Limit Control 1 */
+ 0x0000, /* DAC Limit Control 2 */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0x0038, /* ALC Control 1 */
+ 0x000B, /* ALC Control 2 */
+ 0x0032, /* ALC Control 3 */
+ 0x0000, /* Noise Gate */
+ 0x0041, /* PLLN */
+ 0x000C, /* PLLK1 */
+ 0x0093, /* PLLK2 */
+ 0x00E9, /* PLLK3 */
+ 0,
+ 0,
+ 0x0030, /* ALC Control 4 */
+ 0,
+ 0x0002, /* Input Control */
+ 0x0050, /* PGA Gain */
+ 0,
+ 0x0002, /* ADC Boost Control */
+ 0,
+ 0x0002, /* Output Control */
+ 0x0000, /* Speaker Mixer Control */
+ 0,
+ 0,
+ 0,
+ 0x0079, /* Speaker Volume */
+ 0,
+ 0x0000, /* Mono Mixer Control */
+};
+
+static inline unsigned int wm8940_read_reg_cache(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ u16 *cache = codec->reg_cache;
+
+ if (reg >= ARRAY_SIZE(wm8940_reg_defaults))
+ return -1;
+
+ return cache[reg];
+}
+
+static inline int wm8940_write_reg_cache(struct snd_soc_codec *codec,
+ u16 reg, unsigned int value)
+{
+ u16 *cache = codec->reg_cache;
+
+ if (reg >= ARRAY_SIZE(wm8940_reg_defaults))
+ return -1;
+
+ cache[reg] = value;
+
+ return 0;
+}
+
+static int wm8940_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value)
+{
+ int ret;
+ u8 data[3] = { reg,
+ (value & 0xff00) >> 8,
+ (value & 0x00ff)
+ };
+
+ wm8940_write_reg_cache(codec, reg, value);
+
+ ret = codec->hw_write(codec->control_data, data, 3);
+
+ if (ret < 0)
+ return ret;
+ else if (ret != 3)
+ return -EIO;
+ return 0;
+}
+
+static const char *wm8940_companding[] = { "Off", "NC", "u-law", "A-law" };
+static const struct soc_enum wm8940_adc_companding_enum
+= SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 1, 4, wm8940_companding);
+static const struct soc_enum wm8940_dac_companding_enum
+= SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 3, 4, wm8940_companding);
+
+static const char *wm8940_alc_mode_text[] = {"ALC", "Limiter"};
+static const struct soc_enum wm8940_alc_mode_enum
+= SOC_ENUM_SINGLE(WM8940_ALC3, 8, 2, wm8940_alc_mode_text);
+
+static const char *wm8940_mic_bias_level_text[] = {"0.9", "0.65"};
+static const struct soc_enum wm8940_mic_bias_level_enum
+= SOC_ENUM_SINGLE(WM8940_INPUTCTL, 8, 2, wm8940_mic_bias_level_text);
+
+static const char *wm8940_filter_mode_text[] = {"Audio", "Application"};
+static const struct soc_enum wm8940_filter_mode_enum
+= SOC_ENUM_SINGLE(WM8940_ADC, 7, 2, wm8940_filter_mode_text);
+
+static DECLARE_TLV_DB_SCALE(wm8940_spk_vol_tlv, -5700, 100, 1);
+static DECLARE_TLV_DB_SCALE(wm8940_att_tlv, -1000, 1000, 0);
+static DECLARE_TLV_DB_SCALE(wm8940_pga_vol_tlv, -1200, 75, 0);
+static DECLARE_TLV_DB_SCALE(wm8940_alc_min_tlv, -1200, 600, 0);
+static DECLARE_TLV_DB_SCALE(wm8940_alc_max_tlv, 675, 600, 0);
+static DECLARE_TLV_DB_SCALE(wm8940_alc_tar_tlv, -2250, 50, 0);
+static DECLARE_TLV_DB_SCALE(wm8940_lim_boost_tlv, 0, 100, 0);
+static DECLARE_TLV_DB_SCALE(wm8940_lim_thresh_tlv, -600, 100, 0);
+static DECLARE_TLV_DB_SCALE(wm8940_adc_tlv, -12750, 50, 1);
+static DECLARE_TLV_DB_SCALE(wm8940_capture_boost_vol_tlv, 0, 2000, 0);
+
+static const struct snd_kcontrol_new wm8940_snd_controls[] = {
+ SOC_SINGLE("Digital Loopback Switch", WM8940_COMPANDINGCTL,
+ 6, 1, 0),
+ SOC_ENUM("DAC Companding", wm8940_dac_companding_enum),
+ SOC_ENUM("ADC Companding", wm8940_adc_companding_enum),
+
+ SOC_ENUM("ALC Mode", wm8940_alc_mode_enum),
+ SOC_SINGLE("ALC Switch", WM8940_ALC1, 8, 1, 0),
+ SOC_SINGLE_TLV("ALC Capture Max Gain", WM8940_ALC1,
+ 3, 7, 1, wm8940_alc_max_tlv),
+ SOC_SINGLE_TLV("ALC Capture Min Gain", WM8940_ALC1,
+ 0, 7, 0, wm8940_alc_min_tlv),
+ SOC_SINGLE_TLV("ALC Capture Target", WM8940_ALC2,
+ 0, 14, 0, wm8940_alc_tar_tlv),
+ SOC_SINGLE("ALC Capture Hold", WM8940_ALC2, 4, 10, 0),
+ SOC_SINGLE("ALC Capture Decay", WM8940_ALC3, 4, 10, 0),
+ SOC_SINGLE("ALC Capture Attach", WM8940_ALC3, 0, 10, 0),
+ SOC_SINGLE("ALC ZC Switch", WM8940_ALC4, 1, 1, 0),
+ SOC_SINGLE("ALC Capture Noise Gate Switch", WM8940_NOISEGATE,
+ 3, 1, 0),
+ SOC_SINGLE("ALC Capture Noise Gate Threshold", WM8940_NOISEGATE,
+ 0, 7, 0),
+
+ SOC_SINGLE("DAC Playback Limiter Switch", WM8940_DACLIM1, 8, 1, 0),
+ SOC_SINGLE("DAC Playback Limiter Attack", WM8940_DACLIM1, 0, 9, 0),
+ SOC_SINGLE("DAC Playback Limiter Decay", WM8940_DACLIM1, 4, 11, 0),
+ SOC_SINGLE_TLV("DAC Playback Limiter Threshold", WM8940_DACLIM2,
+ 4, 9, 1, wm8940_lim_thresh_tlv),
+ SOC_SINGLE_TLV("DAC Playback Limiter Boost", WM8940_DACLIM2,
+ 0, 12, 0, wm8940_lim_boost_tlv),
+
+ SOC_SINGLE("Capture PGA ZC Switch", WM8940_PGAGAIN, 7, 1, 0),
+ SOC_SINGLE_TLV("Capture PGA Volume", WM8940_PGAGAIN,
+ 0, 63, 0, wm8940_pga_vol_tlv),
+ SOC_SINGLE_TLV("Digital Playback Volume", WM8940_DACVOL,
+ 0, 255, 0, wm8940_adc_tlv),
+ SOC_SINGLE_TLV("Digital Capture Volume", WM8940_ADCVOL,
+ 0, 255, 0, wm8940_adc_tlv),
+ SOC_ENUM("Mic Bias Level", wm8940_mic_bias_level_enum),
+ SOC_SINGLE_TLV("Capture Boost Volue", WM8940_ADCBOOST,
+ 8, 1, 0, wm8940_capture_boost_vol_tlv),
+ SOC_SINGLE_TLV("Speaker Playback Volume", WM8940_SPKVOL,
+ 0, 63, 0, wm8940_spk_vol_tlv),
+ SOC_SINGLE("Speaker Playback Switch", WM8940_SPKVOL, 6, 1, 1),
+
+ SOC_SINGLE_TLV("Speaker Mixer Line Bypass Volume", WM8940_SPKVOL,
+ 8, 1, 1, wm8940_att_tlv),
+ SOC_SINGLE("Speaker Playback ZC Switch", WM8940_SPKVOL, 7, 1, 0),
+
+ SOC_SINGLE("Mono Out Switch", WM8940_MONOMIX, 6, 1, 1),
+ SOC_SINGLE_TLV("Mono Mixer Line Bypass Volume", WM8940_MONOMIX,
+ 7, 1, 1, wm8940_att_tlv),
+
+ SOC_SINGLE("High Pass Filter Switch", WM8940_ADC, 8, 1, 0),
+ SOC_ENUM("High Pass Filter Mode", wm8940_filter_mode_enum),
+ SOC_SINGLE("High Pass Filter Cut Off", WM8940_ADC, 4, 7, 0),
+ SOC_SINGLE("ADC Inversion Switch", WM8940_ADC, 0, 1, 0),
+ SOC_SINGLE("DAC Inversion Switch", WM8940_DAC, 0, 1, 0),
+ SOC_SINGLE("DAC Auto Mute Switch", WM8940_DAC, 2, 1, 0),
+ SOC_SINGLE("ZC Timeout Clock Switch", WM8940_ADDCNTRL, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new wm8940_speaker_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Line Bypass Switch", WM8940_SPKMIX, 1, 1, 0),
+ SOC_DAPM_SINGLE("Aux Playback Switch", WM8940_SPKMIX, 5, 1, 0),
+ SOC_DAPM_SINGLE("PCM Playback Switch", WM8940_SPKMIX, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new wm8940_mono_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Line Bypass Switch", WM8940_MONOMIX, 1, 1, 0),
+ SOC_DAPM_SINGLE("Aux Playback Switch", WM8940_MONOMIX, 2, 1, 0),
+ SOC_DAPM_SINGLE("PCM Playback Switch", WM8940_MONOMIX, 0, 1, 0),
+};
+
+static DECLARE_TLV_DB_SCALE(wm8940_boost_vol_tlv, -1500, 300, 1);
+static const struct snd_kcontrol_new wm8940_input_boost_controls[] = {
+ SOC_DAPM_SINGLE("Mic PGA Switch", WM8940_PGAGAIN, 6, 1, 1),
+ SOC_DAPM_SINGLE_TLV("Aux Volume", WM8940_ADCBOOST,
+ 0, 7, 0, wm8940_boost_vol_tlv),
+ SOC_DAPM_SINGLE_TLV("Mic Volume", WM8940_ADCBOOST,
+ 4, 7, 0, wm8940_boost_vol_tlv),
+};
+
+static const struct snd_kcontrol_new wm8940_micpga_controls[] = {
+ SOC_DAPM_SINGLE("AUX Switch", WM8940_INPUTCTL, 2, 1, 0),
+ SOC_DAPM_SINGLE("MICP Switch", WM8940_INPUTCTL, 0, 1, 0),
+ SOC_DAPM_SINGLE("MICN Switch", WM8940_INPUTCTL, 1, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget wm8940_dapm_widgets[] = {
+ SND_SOC_DAPM_MIXER("Speaker Mixer", WM8940_POWER3, 2, 0,
+ &wm8940_speaker_mixer_controls[0],
+ ARRAY_SIZE(wm8940_speaker_mixer_controls)),
+ SND_SOC_DAPM_MIXER("Mono Mixer", WM8940_POWER3, 3, 0,
+ &wm8940_mono_mixer_controls[0],
+ ARRAY_SIZE(wm8940_mono_mixer_controls)),
+ SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8940_POWER3, 0, 0),
+
+ SND_SOC_DAPM_PGA("SpkN Out", WM8940_POWER3, 5, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("SpkP Out", WM8940_POWER3, 6, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Mono Out", WM8940_POWER3, 7, 0, NULL, 0),
+ SND_SOC_DAPM_OUTPUT("MONOOUT"),
+ SND_SOC_DAPM_OUTPUT("SPKOUTP"),
+ SND_SOC_DAPM_OUTPUT("SPKOUTN"),
+
+ SND_SOC_DAPM_PGA("Aux Input", WM8940_POWER1, 6, 0, NULL, 0),
+ SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8940_POWER2, 0, 0),
+ SND_SOC_DAPM_MIXER("Mic PGA", WM8940_POWER2, 2, 0,
+ &wm8940_micpga_controls[0],
+ ARRAY_SIZE(wm8940_micpga_controls)),
+ SND_SOC_DAPM_MIXER("Boost Mixer", WM8940_POWER2, 4, 0,
+ &wm8940_input_boost_controls[0],
+ ARRAY_SIZE(wm8940_input_boost_controls)),
+ SND_SOC_DAPM_MICBIAS("Mic Bias", WM8940_POWER1, 4, 0),
+
+ SND_SOC_DAPM_INPUT("MICN"),
+ SND_SOC_DAPM_INPUT("MICP"),
+ SND_SOC_DAPM_INPUT("AUX"),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ /* Mono output mixer */
+ {"Mono Mixer", "PCM Playback Switch", "DAC"},
+ {"Mono Mixer", "Aux Playback Switch", "Aux Input"},
+ {"Mono Mixer", "Line Bypass Switch", "Boost Mixer"},
+
+ /* Speaker output mixer */
+ {"Speaker Mixer", "PCM Playback Switch", "DAC"},
+ {"Speaker Mixer", "Aux Playback Switch", "Aux Input"},
+ {"Speaker Mixer", "Line Bypass Switch", "Boost Mixer"},
+
+ /* Outputs */
+ {"Mono Out", NULL, "Mono Mixer"},
+ {"MONOOUT", NULL, "Mono Out"},
+ {"SpkN Out", NULL, "Speaker Mixer"},
+ {"SpkP Out", NULL, "Speaker Mixer"},
+ {"SPKOUTN", NULL, "SpkN Out"},
+ {"SPKOUTP", NULL, "SpkP Out"},
+
+ /* Microphone PGA */
+ {"Mic PGA", "MICN Switch", "MICN"},
+ {"Mic PGA", "MICP Switch", "MICP"},
+ {"Mic PGA", "AUX Switch", "AUX"},
+
+ /* Boost Mixer */
+ {"Boost Mixer", "Mic PGA Switch", "Mic PGA"},
+ {"Boost Mixer", "Mic Volume", "MICP"},
+ {"Boost Mixer", "Aux Volume", "Aux Input"},
+
+ {"ADC", NULL, "Boost Mixer"},
+};
+
+static int wm8940_add_widgets(struct snd_soc_codec *codec)
+{
+ int ret;
+
+ ret = snd_soc_dapm_new_controls(codec, wm8940_dapm_widgets,
+ ARRAY_SIZE(wm8940_dapm_widgets));
+ if (ret)
+ goto error_ret;
+ ret = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+ if (ret)
+ goto error_ret;
+ ret = snd_soc_dapm_new_widgets(codec);
+
+error_ret:
+ return ret;
+}
+
+#define wm8940_reset(c) wm8940_write(c, WM8940_SOFTRESET, 0);
+
+static int wm8940_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u16 iface = wm8940_read_reg_cache(codec, WM8940_IFACE) & 0xFE67;
+ u16 clk = wm8940_read_reg_cache(codec, WM8940_CLOCK) & 0x1fe;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ clk |= 1;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ break;
+ default:
+ return -EINVAL;
+ }
+ wm8940_write(codec, WM8940_CLOCK, clk);
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ iface |= (2 << 3);
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ iface |= (1 << 3);
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ iface |= (3 << 3);
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ iface |= (3 << 3) | (1 << 7);
+ break;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ iface |= (1 << 7);
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ iface |= (1 << 8);
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ iface |= (1 << 8) | (1 << 7);
+ break;
+ }
+
+ wm8940_write(codec, WM8940_IFACE, iface);
+
+ return 0;
+}
+
+static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->card->codec;
+ u16 iface = wm8940_read_reg_cache(codec, WM8940_IFACE) & 0xFD9F;
+ u16 addcntrl = wm8940_read_reg_cache(codec, WM8940_ADDCNTRL) & 0xFFF1;
+ u16 companding = wm8940_read_reg_cache(codec,
+ WM8940_COMPANDINGCTL) & 0xFFDF;
+ int ret;
+
+ /* LoutR control */
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE
+ && params_channels(params) == 2)
+ iface |= (1 << 9);
+
+ switch (params_rate(params)) {
+ case SNDRV_PCM_RATE_8000:
+ addcntrl |= (0x5 << 1);
+ break;
+ case SNDRV_PCM_RATE_11025:
+ addcntrl |= (0x4 << 1);
+ break;
+ case SNDRV_PCM_RATE_16000:
+ addcntrl |= (0x3 << 1);
+ break;
+ case SNDRV_PCM_RATE_22050:
+ addcntrl |= (0x2 << 1);
+ break;
+ case SNDRV_PCM_RATE_32000:
+ addcntrl |= (0x1 << 1);
+ break;
+ case SNDRV_PCM_RATE_44100:
+ case SNDRV_PCM_RATE_48000:
+ break;
+ }
+ ret = wm8940_write(codec, WM8940_ADDCNTRL, addcntrl);
+ if (ret)
+ goto error_ret;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S8:
+ companding = companding | (1 << 5);
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ iface |= (1 << 5);
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ iface |= (2 << 5);
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ iface |= (3 << 5);
+ break;
+ }
+ ret = wm8940_write(codec, WM8940_COMPANDINGCTL, companding);
+ if (ret)
+ goto error_ret;
+ ret = wm8940_write(codec, WM8940_IFACE, iface);
+
+error_ret:
+ return ret;
+}
+
+static int wm8940_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ u16 mute_reg = wm8940_read_reg_cache(codec, WM8940_DAC) & 0xffbf;
+
+ if (mute)
+ mute_reg |= 0x40;
+
+ return wm8940_write(codec, WM8940_DAC, mute_reg);
+}
+
+static int wm8940_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ u16 val;
+ u16 pwr_reg = wm8940_read_reg_cache(codec, WM8940_POWER1) & 0x1F0;
+ int ret = 0;
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ /* ensure bufioen and biasen */
+ pwr_reg |= (1 << 2) | (1 << 3);
+ /* Enable thermal shutdown */
+ val = wm8940_read_reg_cache(codec, WM8940_OUTPUTCTL);
+ ret = wm8940_write(codec, WM8940_OUTPUTCTL, val | 0x2);
+ if (ret)
+ break;
+ /* set vmid to 75k */
+ ret = wm8940_write(codec, WM8940_POWER1, pwr_reg | 0x1);
+ break;
+ case SND_SOC_BIAS_PREPARE:
+ /* ensure bufioen and biasen */
+ pwr_reg |= (1 << 2) | (1 << 3);
+ ret = wm8940_write(codec, WM8940_POWER1, pwr_reg | 0x1);
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ /* ensure bufioen and biasen */
+ pwr_reg |= (1 << 2) | (1 << 3);
+ /* set vmid to 300k for standby */
+ ret = wm8940_write(codec, WM8940_POWER1, pwr_reg | 0x2);
+ break;
+ case SND_SOC_BIAS_OFF:
+ ret = wm8940_write(codec, WM8940_POWER1, pwr_reg);
+ break;
+ }
+
+ return ret;
+}
+
+struct pll_ {
+ unsigned int pre_scale:2;
+ unsigned int n:4;
+ unsigned int k;
+};
+
+static struct pll_ pll_div;
+
+/* The size in bits of the pll divide multiplied by 10
+ * to allow rounding later */
+#define FIXED_PLL_SIZE ((1 << 24) * 10)
+static void pll_factors(unsigned int target, unsigned int source)
+{
+ unsigned long long Kpart;
+ unsigned int K, Ndiv, Nmod;
+ /* The left shift ist to avoid accuracy loss when right shifting */
+ Ndiv = target / source;
+
+ if (Ndiv > 12) {
+ source <<= 1;
+ /* Multiply by 2 */
+ pll_div.pre_scale = 0;
+ Ndiv = target / source;
+ } else if (Ndiv < 3) {
+ source >>= 2;
+ /* Divide by 4 */
+ pll_div.pre_scale = 3;
+ Ndiv = target / source;
+ } else if (Ndiv < 6) {
+ source >>= 1;
+ /* divide by 2 */
+ pll_div.pre_scale = 2;
+ Ndiv = target / source;
+ } else
+ pll_div.pre_scale = 1;
+
+ if ((Ndiv < 6) || (Ndiv > 12))
+ printk(KERN_WARNING
+ "WM8940 N value %d outwith recommended range!d\n",
+ Ndiv);
+
+ pll_div.n = Ndiv;
+ Nmod = target % source;
+ Kpart = FIXED_PLL_SIZE * (long long)Nmod;
+
+ do_div(Kpart, source);
+
+ K = Kpart & 0xFFFFFFFF;
+
+ /* Check if we need to round */
+ if ((K % 10) >= 5)
+ K += 5;
+
+ /* Move down to proper range now rounding is done */
+ K /= 10;
+
+ pll_div.k = K;
+}
+
+/* Untested at the moment */
+static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai,
+ int pll_id, unsigned int freq_in, unsigned int freq_out)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u16 reg;
+
+ /* Turn off PLL */
+ reg = wm8940_read_reg_cache(codec, WM8940_POWER1);
+ wm8940_write(codec, WM8940_POWER1, reg & 0x1df);
+
+ if (freq_in == 0 || freq_out == 0) {
+ /* Clock CODEC directly from MCLK */
+ reg = wm8940_read_reg_cache(codec, WM8940_CLOCK);
+ wm8940_write(codec, WM8940_CLOCK, reg & 0x0ff);
+ /* Pll power down */
+ wm8940_write(codec, WM8940_PLLN, (1 << 7));
+ return 0;
+ }
+
+ /* Pll is followed by a frequency divide by 4 */
+ pll_factors(freq_out*4, freq_in);
+ if (pll_div.k)
+ wm8940_write(codec, WM8940_PLLN,
+ (pll_div.pre_scale << 4) | pll_div.n | (1 << 6));
+ else /* No factional component */
+ wm8940_write(codec, WM8940_PLLN,
+ (pll_div.pre_scale << 4) | pll_div.n);
+ wm8940_write(codec, WM8940_PLLK1, pll_div.k >> 18);
+ wm8940_write(codec, WM8940_PLLK2, (pll_div.k >> 9) & 0x1ff);
+ wm8940_write(codec, WM8940_PLLK3, pll_div.k & 0x1ff);
+ /* Enable the PLL */
+ reg = wm8940_read_reg_cache(codec, WM8940_POWER1);
+ wm8940_write(codec, WM8940_POWER1, reg | 0x020);
+
+ /* Run CODEC from PLL instead of MCLK */
+ reg = wm8940_read_reg_cache(codec, WM8940_CLOCK);
+ wm8940_write(codec, WM8940_CLOCK, reg | 0x100);
+
+ return 0;
+}
+
+static int wm8940_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct wm8940_priv *wm8940 = codec->private_data;
+
+ switch (freq) {
+ case 11289600:
+ case 12000000:
+ case 12288000:
+ case 16934400:
+ case 18432000:
+ wm8940->sysclk = freq;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
+ int div_id, int div)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u16 reg;
+ int ret = 0;
+
+ switch (div_id) {
+ case WM8940_BCLKDIV:
+ reg = wm8940_read_reg_cache(codec, WM8940_CLOCK) & 0xFFEF3;
+ ret = wm8940_write(codec, WM8940_CLOCK, reg | (div << 2));
+ break;
+ case WM8940_MCLKDIV:
+ reg = wm8940_read_reg_cache(codec, WM8940_CLOCK) & 0xFF1F;
+ ret = wm8940_write(codec, WM8940_CLOCK, reg | (div << 5));
+ break;
+ case WM8940_OPCLKDIV:
+ reg = wm8940_read_reg_cache(codec, WM8940_ADDCNTRL) & 0xFFCF;
+ ret = wm8940_write(codec, WM8940_ADDCNTRL, reg | (div << 4));
+ break;
+ }
+ return ret;
+}
+
+#define WM8940_RATES SNDRV_PCM_RATE_8000_48000
+
+#define WM8940_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
+ SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_ops wm8940_dai_ops = {
+ .hw_params = wm8940_i2s_hw_params,
+ .set_sysclk = wm8940_set_dai_sysclk,
+ .digital_mute = wm8940_mute,
+ .set_fmt = wm8940_set_dai_fmt,
+ .set_clkdiv = wm8940_set_dai_clkdiv,
+ .set_pll = wm8940_set_dai_pll,
+};
+
+struct snd_soc_dai wm8940_dai = {
+ .name = "WM8940",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = WM8940_RATES,
+ .formats = WM8940_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = WM8940_RATES,
+ .formats = WM8940_FORMATS,
+ },
+ .ops = &wm8940_dai_ops,
+ .symmetric_rates = 1,
+};
+EXPORT_SYMBOL_GPL(wm8940_dai);
+
+static int wm8940_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->card->codec;
+
+ return wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF);
+}
+
+static int wm8940_resume(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->card->codec;
+ int i;
+ int ret;
+ u8 data[3];
+ u16 *cache = codec->reg_cache;
+
+ /* Sync reg_cache with the hardware
+ * Could use auto incremented writes to speed this up
+ */
+ for (i = 0; i < ARRAY_SIZE(wm8940_reg_defaults); i++) {
+ data[0] = i;
+ data[1] = (cache[i] & 0xFF00) >> 8;
+ data[2] = cache[i] & 0x00FF;
+ ret = codec->hw_write(codec->control_data, data, 3);
+ if (ret < 0)
+ goto error_ret;
+ else if (ret != 3) {
+ ret = -EIO;
+ goto error_ret;
+ }
+ }
+ ret = wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ if (ret)
+ goto error_ret;
+ ret = wm8940_set_bias_level(codec, codec->suspend_bias_level);
+
+error_ret:
+ return ret;
+}
+
+static struct snd_soc_codec *wm8940_codec;
+
+static int wm8940_probe(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec;
+
+ int ret = 0;
+
+ if (wm8940_codec == NULL) {
+ dev_err(&pdev->dev, "Codec device not registered\n");
+ return -ENODEV;
+ }
+
+ socdev->card->codec = wm8940_codec;
+ codec = wm8940_codec;
+
+ mutex_init(&codec->mutex);
+ /* register pcms */
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ dev_err(codec->dev, "failed to create pcms: %d\n", ret);
+ goto pcm_err;
+ }
+
+ ret = snd_soc_add_controls(codec, wm8940_snd_controls,
+ ARRAY_SIZE(wm8940_snd_controls));
+ if (ret)
+ goto error_free_pcms;
+ ret = wm8940_add_widgets(codec);
+ if (ret)
+ goto error_free_pcms;
+
+ ret = snd_soc_init_card(socdev);
+ if (ret < 0) {
+ dev_err(codec->dev, "failed to register card: %d\n", ret);
+ goto error_free_pcms;
+ }
+
+ return ret;
+
+error_free_pcms:
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+pcm_err:
+ return ret;
+}
+
+static int wm8940_remove(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+
+ return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_wm8940 = {
+ .probe = wm8940_probe,
+ .remove = wm8940_remove,
+ .suspend = wm8940_suspend,
+ .resume = wm8940_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm8940);
+
+static int wm8940_register(struct wm8940_priv *wm8940)
+{
+ struct wm8940_setup_data *pdata = wm8940->codec.dev->platform_data;
+ struct snd_soc_codec *codec = &wm8940->codec;
+ int ret;
+ u16 reg;
+ if (wm8940_codec) {
+ dev_err(codec->dev, "Another WM8940 is registered\n");
+ return -EINVAL;
+ }
+
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+
+ codec->private_data = wm8940;
+ codec->name = "WM8940";
+ codec->owner = THIS_MODULE;
+ codec->read = wm8940_read_reg_cache;
+ codec->write = wm8940_write;
+ codec->bias_level = SND_SOC_BIAS_OFF;
+ codec->set_bias_level = wm8940_set_bias_level;
+ codec->dai = &wm8940_dai;
+ codec->num_dai = 1;
+ codec->reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults);
+ codec->reg_cache = &wm8940->reg_cache;
+
+ memcpy(codec->reg_cache, wm8940_reg_defaults,
+ sizeof(wm8940_reg_defaults));
+
+ ret = wm8940_reset(codec);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to issue reset\n");
+ return ret;
+ }
+
+ wm8940_dai.dev = codec->dev;
+
+ wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ ret = wm8940_write(codec, WM8940_POWER1, 0x180);
+ if (ret < 0)
+ return ret;
+
+ if (!pdata)
+ dev_warn(codec->dev, "No platform data supplied\n");
+ else {
+ reg = wm8940_read_reg_cache(codec, WM8940_OUTPUTCTL);
+ ret = wm8940_write(codec, WM8940_OUTPUTCTL, reg | pdata->vroi);
+ if (ret < 0)
+ return ret;
+ }
+
+
+ wm8940_codec = codec;
+
+ ret = snd_soc_register_codec(codec);
+ if (ret) {
+ dev_err(codec->dev, "Failed to register codec: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_register_dai(&wm8940_dai);
+ if (ret) {
+ dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
+ snd_soc_unregister_codec(codec);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void wm8940_unregister(struct wm8940_priv *wm8940)
+{
+ wm8940_set_bias_level(&wm8940->codec, SND_SOC_BIAS_OFF);
+ snd_soc_unregister_dai(&wm8940_dai);
+ snd_soc_unregister_codec(&wm8940->codec);
+ kfree(wm8940);
+ wm8940_codec = NULL;
+}
+
+static int wm8940_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct wm8940_priv *wm8940;
+ struct snd_soc_codec *codec;
+
+ wm8940 = kzalloc(sizeof *wm8940, GFP_KERNEL);
+ if (wm8940 == NULL)
+ return -ENOMEM;
+
+ codec = &wm8940->codec;
+ codec->hw_write = (hw_write_t)i2c_master_send;
+ i2c_set_clientdata(i2c, wm8940);
+ codec->control_data = i2c;
+ codec->dev = &i2c->dev;
+
+ return wm8940_register(wm8940);
+}
+
+static int wm8940_i2c_remove(struct i2c_client *client)
+{
+ struct wm8940_priv *wm8940 = i2c_get_clientdata(client);
+
+ wm8940_unregister(wm8940);
+
+ return 0;
+}
+
+static const struct i2c_device_id wm8940_i2c_id[] = {
+ { "wm8940", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8940_i2c_id);
+
+static struct i2c_driver wm8940_i2c_driver = {
+ .driver = {
+ .name = "WM8940 I2C Codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8940_i2c_probe,
+ .remove = __devexit_p(wm8940_i2c_remove),
+ .id_table = wm8940_i2c_id,
+};
+
+static int __init wm8940_modinit(void)
+{
+ int ret;
+
+ ret = i2c_add_driver(&wm8940_i2c_driver);
+ if (ret)
+ printk(KERN_ERR "Failed to register WM8940 I2C driver: %d\n",
+ ret);
+ return ret;
+}
+module_init(wm8940_modinit);
+
+static void __exit wm8940_exit(void)
+{
+ i2c_del_driver(&wm8940_i2c_driver);
+}
+module_exit(wm8940_exit);
+
+MODULE_DESCRIPTION("ASoC WM8940 driver");
+MODULE_AUTHOR("Jonathan Cameron");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8940.h b/sound/soc/codecs/wm8940.h
new file mode 100644
index 000000000000..8410eed3ef84
--- /dev/null
+++ b/sound/soc/codecs/wm8940.h
@@ -0,0 +1,104 @@
+/*
+ * wm8940.h -- WM8940 Soc Audio driver
+ *
+ * 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 _WM8940_H
+#define _WM8940_H
+
+struct wm8940_setup_data {
+ /* Vref to analogue output resistance */
+#define WM8940_VROI_1K 0
+#define WM8940_VROI_30K 1
+ unsigned int vroi:1;
+};
+extern struct snd_soc_dai wm8940_dai;
+extern struct snd_soc_codec_device soc_codec_dev_wm8940;
+
+/* WM8940 register space */
+#define WM8940_SOFTRESET 0x00
+#define WM8940_POWER1 0x01
+#define WM8940_POWER2 0x02
+#define WM8940_POWER3 0x03
+#define WM8940_IFACE 0x04
+#define WM8940_COMPANDINGCTL 0x05
+#define WM8940_CLOCK 0x06
+#define WM8940_ADDCNTRL 0x07
+#define WM8940_GPIO 0x08
+#define WM8940_CTLINT 0x09
+#define WM8940_DAC 0x0A
+#define WM8940_DACVOL 0x0B
+
+#define WM8940_ADC 0x0E
+#define WM8940_ADCVOL 0x0F
+#define WM8940_NOTCH1 0x10
+#define WM8940_NOTCH2 0x11
+#define WM8940_NOTCH3 0x12
+#define WM8940_NOTCH4 0x13
+#define WM8940_NOTCH5 0x14
+#define WM8940_NOTCH6 0x15
+#define WM8940_NOTCH7 0x16
+#define WM8940_NOTCH8 0x17
+#define WM8940_DACLIM1 0x18
+#define WM8940_DACLIM2 0x19
+
+#define WM8940_ALC1 0x20
+#define WM8940_ALC2 0x21
+#define WM8940_ALC3 0x22
+#define WM8940_NOISEGATE 0x23
+#define WM8940_PLLN 0x24
+#define WM8940_PLLK1 0x25
+#define WM8940_PLLK2 0x26
+#define WM8940_PLLK3 0x27
+
+#define WM8940_ALC4 0x2A
+
+#define WM8940_INPUTCTL 0x2C
+#define WM8940_PGAGAIN 0x2D
+
+#define WM8940_ADCBOOST 0x2F
+
+#define WM8940_OUTPUTCTL 0x31
+#define WM8940_SPKMIX 0x32
+
+#define WM8940_SPKVOL 0x36
+
+#define WM8940_MONOMIX 0x38
+
+#define WM8940_CACHEREGNUM 0x57
+
+
+/* Clock divider Id's */
+#define WM8940_BCLKDIV 0
+#define WM8940_MCLKDIV 1
+#define WM8940_OPCLKDIV 2
+
+/* MCLK clock dividers */
+#define WM8940_MCLKDIV_1 0
+#define WM8940_MCLKDIV_1_5 1
+#define WM8940_MCLKDIV_2 2
+#define WM8940_MCLKDIV_3 3
+#define WM8940_MCLKDIV_4 4
+#define WM8940_MCLKDIV_6 5
+#define WM8940_MCLKDIV_8 6
+#define WM8940_MCLKDIV_12 7
+
+/* BCLK clock dividers */
+#define WM8940_BCLKDIV_1 0
+#define WM8940_BCLKDIV_2 1
+#define WM8940_BCLKDIV_4 2
+#define WM8940_BCLKDIV_8 3
+#define WM8940_BCLKDIV_16 4
+#define WM8940_BCLKDIV_32 5
+
+/* PLL Out Dividers */
+#define WM8940_OPCLKDIV_1 0
+#define WM8940_OPCLKDIV_2 1
+#define WM8940_OPCLKDIV_3 2
+#define WM8940_OPCLKDIV_4 3
+
+#endif /* _WM8940_H */
+
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
new file mode 100644
index 000000000000..e224d8add170
--- /dev/null
+++ b/sound/soc/codecs/wm8960.c
@@ -0,0 +1,969 @@
+/*
+ * wm8960.c -- WM8960 ALSA SoC Audio driver
+ *
+ * Author: Liam Girdwood
+ *
+ * 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/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "wm8960.h"
+
+#define AUDIO_NAME "wm8960"
+
+struct snd_soc_codec_device soc_codec_dev_wm8960;
+
+/* R25 - Power 1 */
+#define WM8960_VREF 0x40
+
+/* R28 - Anti-pop 1 */
+#define WM8960_POBCTRL 0x80
+#define WM8960_BUFDCOPEN 0x10
+#define WM8960_BUFIOEN 0x08
+#define WM8960_SOFT_ST 0x04
+#define WM8960_HPSTBY 0x01
+
+/* R29 - Anti-pop 2 */
+#define WM8960_DISOP 0x40
+
+/*
+ * wm8960 register cache
+ * We can't read the WM8960 register space when we are
+ * using 2 wire for device control, so we cache them instead.
+ */
+static const u16 wm8960_reg[WM8960_CACHEREGNUM] = {
+ 0x0097, 0x0097, 0x0000, 0x0000,
+ 0x0000, 0x0008, 0x0000, 0x000a,
+ 0x01c0, 0x0000, 0x00ff, 0x00ff,
+ 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x007b, 0x0100, 0x0032,
+ 0x0000, 0x00c3, 0x00c3, 0x01c0,
+ 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0100, 0x0100, 0x0050, 0x0050,
+ 0x0050, 0x0050, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0040, 0x0000,
+ 0x0000, 0x0050, 0x0050, 0x0000,
+ 0x0002, 0x0037, 0x004d, 0x0080,
+ 0x0008, 0x0031, 0x0026, 0x00e9,
+};
+
+struct wm8960_priv {
+ u16 reg_cache[WM8960_CACHEREGNUM];
+ struct snd_soc_codec codec;
+};
+
+/*
+ * read wm8960 register cache
+ */
+static inline unsigned int wm8960_read_reg_cache(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ u16 *cache = codec->reg_cache;
+ if (reg == WM8960_RESET)
+ return 0;
+ if (reg >= WM8960_CACHEREGNUM)
+ return -1;
+ return cache[reg];
+}
+
+/*
+ * write wm8960 register cache
+ */
+static inline void wm8960_write_reg_cache(struct snd_soc_codec *codec,
+ u16 reg, unsigned int value)
+{
+ u16 *cache = codec->reg_cache;
+ if (reg >= WM8960_CACHEREGNUM)
+ return;
+ cache[reg] = value;
+}
+
+static inline unsigned int wm8960_read(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ return wm8960_read_reg_cache(codec, reg);
+}
+
+/*
+ * write to the WM8960 register space
+ */
+static int wm8960_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value)
+{
+ u8 data[2];
+
+ /* data is
+ * D15..D9 WM8960 register offset
+ * D8...D0 register data
+ */
+ data[0] = (reg << 1) | ((value >> 8) & 0x0001);
+ data[1] = value & 0x00ff;
+
+ wm8960_write_reg_cache(codec, reg, value);
+ if (codec->hw_write(codec->control_data, data, 2) == 2)
+ return 0;
+ else
+ return -EIO;
+}
+
+#define wm8960_reset(c) wm8960_write(c, WM8960_RESET, 0)
+
+/* enumerated controls */
+static const char *wm8960_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
+static const char *wm8960_polarity[] = {"No Inversion", "Left Inverted",
+ "Right Inverted", "Stereo Inversion"};
+static const char *wm8960_3d_upper_cutoff[] = {"High", "Low"};
+static const char *wm8960_3d_lower_cutoff[] = {"Low", "High"};
+static const char *wm8960_alcfunc[] = {"Off", "Right", "Left", "Stereo"};
+static const char *wm8960_alcmode[] = {"ALC", "Limiter"};
+
+static const struct soc_enum wm8960_enum[] = {
+ SOC_ENUM_SINGLE(WM8960_DACCTL1, 1, 4, wm8960_deemph),
+ SOC_ENUM_SINGLE(WM8960_DACCTL1, 5, 4, wm8960_polarity),
+ SOC_ENUM_SINGLE(WM8960_DACCTL2, 5, 4, wm8960_polarity),
+ SOC_ENUM_SINGLE(WM8960_3D, 6, 2, wm8960_3d_upper_cutoff),
+ SOC_ENUM_SINGLE(WM8960_3D, 5, 2, wm8960_3d_lower_cutoff),
+ SOC_ENUM_SINGLE(WM8960_ALC1, 7, 4, wm8960_alcfunc),
+ SOC_ENUM_SINGLE(WM8960_ALC3, 8, 2, wm8960_alcmode),
+};
+
+static const DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 50, 0);
+static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1);
+static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0);
+static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
+
+static const struct snd_kcontrol_new wm8960_snd_controls[] = {
+SOC_DOUBLE_R_TLV("Capture Volume", WM8960_LINVOL, WM8960_RINVOL,
+ 0, 63, 0, adc_tlv),
+SOC_DOUBLE_R("Capture Volume ZC Switch", WM8960_LINVOL, WM8960_RINVOL,
+ 6, 1, 0),
+SOC_DOUBLE_R("Capture Switch", WM8960_LINVOL, WM8960_RINVOL,
+ 7, 1, 0),
+
+SOC_DOUBLE_R_TLV("Playback Volume", WM8960_LDAC, WM8960_RDAC,
+ 0, 255, 0, dac_tlv),
+
+SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8960_LOUT1, WM8960_ROUT1,
+ 0, 127, 0, out_tlv),
+SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8960_LOUT1, WM8960_ROUT1,
+ 7, 1, 0),
+
+SOC_DOUBLE_R_TLV("Speaker Playback Volume", WM8960_LOUT2, WM8960_ROUT2,
+ 0, 127, 0, out_tlv),
+SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8960_LOUT2, WM8960_ROUT2,
+ 7, 1, 0),
+SOC_SINGLE("Speaker DC Volume", WM8960_CLASSD3, 3, 5, 0),
+SOC_SINGLE("Speaker AC Volume", WM8960_CLASSD3, 0, 5, 0),
+
+SOC_SINGLE("PCM Playback -6dB Switch", WM8960_DACCTL1, 7, 1, 0),
+SOC_ENUM("ADC Polarity", wm8960_enum[1]),
+SOC_ENUM("Playback De-emphasis", wm8960_enum[0]),
+SOC_SINGLE("ADC High Pass Filter Switch", WM8960_DACCTL1, 0, 1, 0),
+
+SOC_ENUM("DAC Polarity", wm8960_enum[2]),
+
+SOC_ENUM("3D Filter Upper Cut-Off", wm8960_enum[3]),
+SOC_ENUM("3D Filter Lower Cut-Off", wm8960_enum[4]),
+SOC_SINGLE("3D Volume", WM8960_3D, 1, 15, 0),
+SOC_SINGLE("3D Switch", WM8960_3D, 0, 1, 0),
+
+SOC_ENUM("ALC Function", wm8960_enum[5]),
+SOC_SINGLE("ALC Max Gain", WM8960_ALC1, 4, 7, 0),
+SOC_SINGLE("ALC Target", WM8960_ALC1, 0, 15, 1),
+SOC_SINGLE("ALC Min Gain", WM8960_ALC2, 4, 7, 0),
+SOC_SINGLE("ALC Hold Time", WM8960_ALC2, 0, 15, 0),
+SOC_ENUM("ALC Mode", wm8960_enum[6]),
+SOC_SINGLE("ALC Decay", WM8960_ALC3, 4, 15, 0),
+SOC_SINGLE("ALC Attack", WM8960_ALC3, 0, 15, 0),
+
+SOC_SINGLE("Noise Gate Threshold", WM8960_NOISEG, 3, 31, 0),
+SOC_SINGLE("Noise Gate Switch", WM8960_NOISEG, 0, 1, 0),
+
+SOC_DOUBLE_R("ADC PCM Capture Volume", WM8960_LINPATH, WM8960_RINPATH,
+ 0, 127, 0),
+
+SOC_SINGLE_TLV("Left Output Mixer Boost Bypass Volume",
+ WM8960_BYPASS1, 4, 7, 1, bypass_tlv),
+SOC_SINGLE_TLV("Left Output Mixer LINPUT3 Volume",
+ WM8960_LOUTMIX, 4, 7, 1, bypass_tlv),
+SOC_SINGLE_TLV("Right Output Mixer Boost Bypass Volume",
+ WM8960_BYPASS2, 4, 7, 1, bypass_tlv),
+SOC_SINGLE_TLV("Right Output Mixer RINPUT3 Volume",
+ WM8960_ROUTMIX, 4, 7, 1, bypass_tlv),
+};
+
+static const struct snd_kcontrol_new wm8960_lin_boost[] = {
+SOC_DAPM_SINGLE("LINPUT2 Switch", WM8960_LINPATH, 6, 1, 0),
+SOC_DAPM_SINGLE("LINPUT3 Switch", WM8960_LINPATH, 7, 1, 0),
+SOC_DAPM_SINGLE("LINPUT1 Switch", WM8960_LINPATH, 8, 1, 0),
+};
+
+static const struct snd_kcontrol_new wm8960_lin[] = {
+SOC_DAPM_SINGLE("Boost Switch", WM8960_LINPATH, 3, 1, 0),
+};
+
+static const struct snd_kcontrol_new wm8960_rin_boost[] = {
+SOC_DAPM_SINGLE("RINPUT2 Switch", WM8960_RINPATH, 6, 1, 0),
+SOC_DAPM_SINGLE("RINPUT3 Switch", WM8960_RINPATH, 7, 1, 0),
+SOC_DAPM_SINGLE("RINPUT1 Switch", WM8960_RINPATH, 8, 1, 0),
+};
+
+static const struct snd_kcontrol_new wm8960_rin[] = {
+SOC_DAPM_SINGLE("Boost Switch", WM8960_RINPATH, 3, 1, 0),
+};
+
+static const struct snd_kcontrol_new wm8960_loutput_mixer[] = {
+SOC_DAPM_SINGLE("PCM Playback Switch", WM8960_LOUTMIX, 8, 1, 0),
+SOC_DAPM_SINGLE("LINPUT3 Switch", WM8960_LOUTMIX, 7, 1, 0),
+SOC_DAPM_SINGLE("Boost Bypass Switch", WM8960_BYPASS1, 7, 1, 0),
+};
+
+static const struct snd_kcontrol_new wm8960_routput_mixer[] = {
+SOC_DAPM_SINGLE("PCM Playback Switch", WM8960_ROUTMIX, 8, 1, 0),
+SOC_DAPM_SINGLE("RINPUT3 Switch", WM8960_ROUTMIX, 7, 1, 0),
+SOC_DAPM_SINGLE("Boost Bypass Switch", WM8960_BYPASS2, 7, 1, 0),
+};
+
+static const struct snd_kcontrol_new wm8960_mono_out[] = {
+SOC_DAPM_SINGLE("Left Switch", WM8960_MONOMIX1, 7, 1, 0),
+SOC_DAPM_SINGLE("Right Switch", WM8960_MONOMIX2, 7, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget wm8960_dapm_widgets[] = {
+SND_SOC_DAPM_INPUT("LINPUT1"),
+SND_SOC_DAPM_INPUT("RINPUT1"),
+SND_SOC_DAPM_INPUT("LINPUT2"),
+SND_SOC_DAPM_INPUT("RINPUT2"),
+SND_SOC_DAPM_INPUT("LINPUT3"),
+SND_SOC_DAPM_INPUT("RINPUT3"),
+
+SND_SOC_DAPM_MICBIAS("MICB", WM8960_POWER1, 1, 0),
+
+SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8960_POWER1, 5, 0,
+ wm8960_lin_boost, ARRAY_SIZE(wm8960_lin_boost)),
+SND_SOC_DAPM_MIXER("Right Boost Mixer", WM8960_POWER1, 4, 0,
+ wm8960_rin_boost, ARRAY_SIZE(wm8960_rin_boost)),
+
+SND_SOC_DAPM_MIXER("Left Input Mixer", WM8960_POWER3, 5, 0,
+ wm8960_lin, ARRAY_SIZE(wm8960_lin)),
+SND_SOC_DAPM_MIXER("Right Input Mixer", WM8960_POWER3, 4, 0,
+ wm8960_rin, ARRAY_SIZE(wm8960_rin)),
+
+SND_SOC_DAPM_ADC("Left ADC", "Capture", WM8960_POWER2, 3, 0),
+SND_SOC_DAPM_ADC("Right ADC", "Capture", WM8960_POWER2, 2, 0),
+
+SND_SOC_DAPM_DAC("Left DAC", "Playback", WM8960_POWER2, 8, 0),
+SND_SOC_DAPM_DAC("Right DAC", "Playback", WM8960_POWER2, 7, 0),
+
+SND_SOC_DAPM_MIXER("Left Output Mixer", WM8960_POWER3, 3, 0,
+ &wm8960_loutput_mixer[0],
+ ARRAY_SIZE(wm8960_loutput_mixer)),
+SND_SOC_DAPM_MIXER("Right Output Mixer", WM8960_POWER3, 2, 0,
+ &wm8960_routput_mixer[0],
+ ARRAY_SIZE(wm8960_routput_mixer)),
+
+SND_SOC_DAPM_MIXER("Mono Output Mixer", WM8960_POWER2, 1, 0,
+ &wm8960_mono_out[0],
+ ARRAY_SIZE(wm8960_mono_out)),
+
+SND_SOC_DAPM_PGA("LOUT1 PGA", WM8960_POWER2, 6, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ROUT1 PGA", WM8960_POWER2, 5, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("Left Speaker PGA", WM8960_POWER2, 4, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Right Speaker PGA", WM8960_POWER2, 3, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("Right Speaker Output", WM8960_CLASSD1, 7, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Left Speaker Output", WM8960_CLASSD1, 6, 0, NULL, 0),
+
+SND_SOC_DAPM_OUTPUT("SPK_LP"),
+SND_SOC_DAPM_OUTPUT("SPK_LN"),
+SND_SOC_DAPM_OUTPUT("HP_L"),
+SND_SOC_DAPM_OUTPUT("HP_R"),
+SND_SOC_DAPM_OUTPUT("SPK_RP"),
+SND_SOC_DAPM_OUTPUT("SPK_RN"),
+SND_SOC_DAPM_OUTPUT("OUT3"),
+};
+
+static const struct snd_soc_dapm_route audio_paths[] = {
+ { "Left Boost Mixer", "LINPUT1 Switch", "LINPUT1" },
+ { "Left Boost Mixer", "LINPUT2 Switch", "LINPUT2" },
+ { "Left Boost Mixer", "LINPUT3 Switch", "LINPUT3" },
+
+ { "Left Input Mixer", "Boost Switch", "Left Boost Mixer", },
+ { "Left Input Mixer", NULL, "LINPUT1", }, /* Really Boost Switch */
+ { "Left Input Mixer", NULL, "LINPUT2" },
+ { "Left Input Mixer", NULL, "LINPUT3" },
+
+ { "Right Boost Mixer", "RINPUT1 Switch", "RINPUT1" },
+ { "Right Boost Mixer", "RINPUT2 Switch", "RINPUT2" },
+ { "Right Boost Mixer", "RINPUT3 Switch", "RINPUT3" },
+
+ { "Right Input Mixer", "Boost Switch", "Right Boost Mixer", },
+ { "Right Input Mixer", NULL, "RINPUT1", }, /* Really Boost Switch */
+ { "Right Input Mixer", NULL, "RINPUT2" },
+ { "Right Input Mixer", NULL, "LINPUT3" },
+
+ { "Left ADC", NULL, "Left Input Mixer" },
+ { "Right ADC", NULL, "Right Input Mixer" },
+
+ { "Left Output Mixer", "LINPUT3 Switch", "LINPUT3" },
+ { "Left Output Mixer", "Boost Bypass Switch", "Left Boost Mixer"} ,
+ { "Left Output Mixer", "PCM Playback Switch", "Left DAC" },
+
+ { "Right Output Mixer", "RINPUT3 Switch", "RINPUT3" },
+ { "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" } ,
+ { "Right Output Mixer", "PCM Playback Switch", "Right DAC" },
+
+ { "Mono Output Mixer", "Left Switch", "Left Output Mixer" },
+ { "Mono Output Mixer", "Right Switch", "Right Output Mixer" },
+
+ { "LOUT1 PGA", NULL, "Left Output Mixer" },
+ { "ROUT1 PGA", NULL, "Right Output Mixer" },
+
+ { "HP_L", NULL, "LOUT1 PGA" },
+ { "HP_R", NULL, "ROUT1 PGA" },
+
+ { "Left Speaker PGA", NULL, "Left Output Mixer" },
+ { "Right Speaker PGA", NULL, "Right Output Mixer" },
+
+ { "Left Speaker Output", NULL, "Left Speaker PGA" },
+ { "Right Speaker Output", NULL, "Right Speaker PGA" },
+
+ { "SPK_LN", NULL, "Left Speaker Output" },
+ { "SPK_LP", NULL, "Left Speaker Output" },
+ { "SPK_RN", NULL, "Right Speaker Output" },
+ { "SPK_RP", NULL, "Right Speaker Output" },
+
+ { "OUT3", NULL, "Mono Output Mixer", }
+};
+
+static int wm8960_add_widgets(struct snd_soc_codec *codec)
+{
+ snd_soc_dapm_new_controls(codec, wm8960_dapm_widgets,
+ ARRAY_SIZE(wm8960_dapm_widgets));
+
+ snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
+
+ snd_soc_dapm_new_widgets(codec);
+ return 0;
+}
+
+static int wm8960_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u16 iface = 0;
+
+ /* set master/slave audio interface */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ iface |= 0x0040;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* interface format */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ iface |= 0x0002;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ iface |= 0x0001;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ iface |= 0x0003;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ iface |= 0x0013;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* clock inversion */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ iface |= 0x0090;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ iface |= 0x0080;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ iface |= 0x0010;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* set iface */
+ wm8960_write(codec, WM8960_IFACE1, iface);
+ return 0;
+}
+
+static int wm8960_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->card->codec;
+ u16 iface = wm8960_read(codec, WM8960_IFACE1) & 0xfff3;
+
+ /* bit size */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ iface |= 0x0004;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ iface |= 0x0008;
+ break;
+ }
+
+ /* set iface */
+ wm8960_write(codec, WM8960_IFACE1, iface);
+ return 0;
+}
+
+static int wm8960_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ u16 mute_reg = wm8960_read(codec, WM8960_DACCTL1) & 0xfff7;
+
+ if (mute)
+ wm8960_write(codec, WM8960_DACCTL1, mute_reg | 0x8);
+ else
+ wm8960_write(codec, WM8960_DACCTL1, mute_reg);
+ return 0;
+}
+
+static int wm8960_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct wm8960_data *pdata = codec->dev->platform_data;
+ u16 reg;
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ break;
+
+ case SND_SOC_BIAS_PREPARE:
+ /* Set VMID to 2x50k */
+ reg = wm8960_read(codec, WM8960_POWER1);
+ reg &= ~0x180;
+ reg |= 0x80;
+ wm8960_write(codec, WM8960_POWER1, reg);
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->bias_level == SND_SOC_BIAS_OFF) {
+ /* Enable anti-pop features */
+ wm8960_write(codec, WM8960_APOP1,
+ WM8960_POBCTRL | WM8960_SOFT_ST |
+ WM8960_BUFDCOPEN | WM8960_BUFIOEN);
+
+ /* Discharge HP output */
+ reg = WM8960_DISOP;
+ if (pdata)
+ reg |= pdata->dres << 4;
+ wm8960_write(codec, WM8960_APOP2, reg);
+
+ msleep(400);
+
+ wm8960_write(codec, WM8960_APOP2, 0);
+
+ /* Enable & ramp VMID at 2x50k */
+ reg = wm8960_read(codec, WM8960_POWER1);
+ reg |= 0x80;
+ wm8960_write(codec, WM8960_POWER1, reg);
+ msleep(100);
+
+ /* Enable VREF */
+ wm8960_write(codec, WM8960_POWER1, reg | WM8960_VREF);
+
+ /* Disable anti-pop features */
+ wm8960_write(codec, WM8960_APOP1, WM8960_BUFIOEN);
+ }
+
+ /* Set VMID to 2x250k */
+ reg = wm8960_read(codec, WM8960_POWER1);
+ reg &= ~0x180;
+ reg |= 0x100;
+ wm8960_write(codec, WM8960_POWER1, reg);
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ /* Enable anti-pop features */
+ wm8960_write(codec, WM8960_APOP1,
+ WM8960_POBCTRL | WM8960_SOFT_ST |
+ WM8960_BUFDCOPEN | WM8960_BUFIOEN);
+
+ /* Disable VMID and VREF, let them discharge */
+ wm8960_write(codec, WM8960_POWER1, 0);
+ msleep(600);
+
+ wm8960_write(codec, WM8960_APOP1, 0);
+ break;
+ }
+
+ codec->bias_level = level;
+
+ return 0;
+}
+
+/* PLL divisors */
+struct _pll_div {
+ u32 pre_div:1;
+ u32 n:4;
+ u32 k:24;
+};
+
+/* The size in bits of the pll divide multiplied by 10
+ * to allow rounding later */
+#define FIXED_PLL_SIZE ((1 << 24) * 10)
+
+static int pll_factors(unsigned int source, unsigned int target,
+ struct _pll_div *pll_div)
+{
+ unsigned long long Kpart;
+ unsigned int K, Ndiv, Nmod;
+
+ pr_debug("WM8960 PLL: setting %dHz->%dHz\n", source, target);
+
+ /* Scale up target to PLL operating frequency */
+ target *= 4;
+
+ Ndiv = target / source;
+ if (Ndiv < 6) {
+ source >>= 1;
+ pll_div->pre_div = 1;
+ Ndiv = target / source;
+ } else
+ pll_div->pre_div = 0;
+
+ if ((Ndiv < 6) || (Ndiv > 12)) {
+ pr_err("WM8960 PLL: Unsupported N=%d\n", Ndiv);
+ return -EINVAL;
+ }
+
+ pll_div->n = Ndiv;
+ Nmod = target % source;
+ Kpart = FIXED_PLL_SIZE * (long long)Nmod;
+
+ do_div(Kpart, source);
+
+ K = Kpart & 0xFFFFFFFF;
+
+ /* Check if we need to round */
+ if ((K % 10) >= 5)
+ K += 5;
+
+ /* Move down to proper range now rounding is done */
+ K /= 10;
+
+ pll_div->k = K;
+
+ pr_debug("WM8960 PLL: N=%x K=%x pre_div=%d\n",
+ pll_div->n, pll_div->k, pll_div->pre_div);
+
+ return 0;
+}
+
+static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai,
+ int pll_id, unsigned int freq_in, unsigned int freq_out)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u16 reg;
+ static struct _pll_div pll_div;
+ int ret;
+
+ if (freq_in && freq_out) {
+ ret = pll_factors(freq_in, freq_out, &pll_div);
+ if (ret != 0)
+ return ret;
+ }
+
+ /* Disable the PLL: even if we are changing the frequency the
+ * PLL needs to be disabled while we do so. */
+ wm8960_write(codec, WM8960_CLOCK1,
+ wm8960_read(codec, WM8960_CLOCK1) & ~1);
+ wm8960_write(codec, WM8960_POWER2,
+ wm8960_read(codec, WM8960_POWER2) & ~1);
+
+ if (!freq_in || !freq_out)
+ return 0;
+
+ reg = wm8960_read(codec, WM8960_PLL1) & ~0x3f;
+ reg |= pll_div.pre_div << 4;
+ reg |= pll_div.n;
+
+ if (pll_div.k) {
+ reg |= 0x20;
+
+ wm8960_write(codec, WM8960_PLL2, (pll_div.k >> 18) & 0x3f);
+ wm8960_write(codec, WM8960_PLL3, (pll_div.k >> 9) & 0x1ff);
+ wm8960_write(codec, WM8960_PLL4, pll_div.k & 0x1ff);
+ }
+ wm8960_write(codec, WM8960_PLL1, reg);
+
+ /* Turn it on */
+ wm8960_write(codec, WM8960_POWER2,
+ wm8960_read(codec, WM8960_POWER2) | 1);
+ msleep(250);
+ wm8960_write(codec, WM8960_CLOCK1,
+ wm8960_read(codec, WM8960_CLOCK1) | 1);
+
+ return 0;
+}
+
+static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
+ int div_id, int div)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u16 reg;
+
+ switch (div_id) {
+ case WM8960_SYSCLKSEL:
+ reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1fe;
+ wm8960_write(codec, WM8960_CLOCK1, reg | div);
+ break;
+ case WM8960_SYSCLKDIV:
+ reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1f9;
+ wm8960_write(codec, WM8960_CLOCK1, reg | div);
+ break;
+ case WM8960_DACDIV:
+ reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1c7;
+ wm8960_write(codec, WM8960_CLOCK1, reg | div);
+ break;
+ case WM8960_OPCLKDIV:
+ reg = wm8960_read(codec, WM8960_PLL1) & 0x03f;
+ wm8960_write(codec, WM8960_PLL1, reg | div);
+ break;
+ case WM8960_DCLKDIV:
+ reg = wm8960_read(codec, WM8960_CLOCK2) & 0x03f;
+ wm8960_write(codec, WM8960_CLOCK2, reg | div);
+ break;
+ case WM8960_TOCLKSEL:
+ reg = wm8960_read(codec, WM8960_ADDCTL1) & 0x1fd;
+ wm8960_write(codec, WM8960_ADDCTL1, reg | div);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+#define WM8960_RATES SNDRV_PCM_RATE_8000_48000
+
+#define WM8960_FORMATS \
+ (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_ops wm8960_dai_ops = {
+ .hw_params = wm8960_hw_params,
+ .digital_mute = wm8960_mute,
+ .set_fmt = wm8960_set_dai_fmt,
+ .set_clkdiv = wm8960_set_dai_clkdiv,
+ .set_pll = wm8960_set_dai_pll,
+};
+
+struct snd_soc_dai wm8960_dai = {
+ .name = "WM8960",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = WM8960_RATES,
+ .formats = WM8960_FORMATS,},
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = WM8960_RATES,
+ .formats = WM8960_FORMATS,},
+ .ops = &wm8960_dai_ops,
+ .symmetric_rates = 1,
+};
+EXPORT_SYMBOL_GPL(wm8960_dai);
+
+static int wm8960_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->card->codec;
+
+ wm8960_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+
+static int wm8960_resume(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->card->codec;
+ int i;
+ u8 data[2];
+ u16 *cache = codec->reg_cache;
+
+ /* Sync reg_cache with the hardware */
+ for (i = 0; i < ARRAY_SIZE(wm8960_reg); i++) {
+ data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
+ data[1] = cache[i] & 0x00ff;
+ codec->hw_write(codec->control_data, data, 2);
+ }
+
+ wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ wm8960_set_bias_level(codec, codec->suspend_bias_level);
+ return 0;
+}
+
+static struct snd_soc_codec *wm8960_codec;
+
+static int wm8960_probe(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec;
+ int ret = 0;
+
+ if (wm8960_codec == NULL) {
+ dev_err(&pdev->dev, "Codec device not registered\n");
+ return -ENODEV;
+ }
+
+ socdev->card->codec = wm8960_codec;
+ codec = wm8960_codec;
+
+ /* register pcms */
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ dev_err(codec->dev, "failed to create pcms: %d\n", ret);
+ goto pcm_err;
+ }
+
+ snd_soc_add_controls(codec, wm8960_snd_controls,
+ ARRAY_SIZE(wm8960_snd_controls));
+ wm8960_add_widgets(codec);
+ ret = snd_soc_init_card(socdev);
+ if (ret < 0) {
+ dev_err(codec->dev, "failed to register card: %d\n", ret);
+ goto card_err;
+ }
+
+ return ret;
+
+card_err:
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+pcm_err:
+ return ret;
+}
+
+/* power down chip */
+static int wm8960_remove(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+
+ return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_wm8960 = {
+ .probe = wm8960_probe,
+ .remove = wm8960_remove,
+ .suspend = wm8960_suspend,
+ .resume = wm8960_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm8960);
+
+static int wm8960_register(struct wm8960_priv *wm8960)
+{
+ struct wm8960_data *pdata = wm8960->codec.dev->platform_data;
+ struct snd_soc_codec *codec = &wm8960->codec;
+ int ret;
+ u16 reg;
+
+ if (wm8960_codec) {
+ dev_err(codec->dev, "Another WM8960 is registered\n");
+ return -EINVAL;
+ }
+
+ if (!pdata) {
+ dev_warn(codec->dev, "No platform data supplied\n");
+ } else {
+ if (pdata->dres > WM8960_DRES_MAX) {
+ dev_err(codec->dev, "Invalid DRES: %d\n", pdata->dres);
+ pdata->dres = 0;
+ }
+ }
+
+ mutex_init(&codec->mutex);
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+
+ codec->private_data = wm8960;
+ codec->name = "WM8960";
+ codec->owner = THIS_MODULE;
+ codec->read = wm8960_read_reg_cache;
+ codec->write = wm8960_write;
+ codec->bias_level = SND_SOC_BIAS_OFF;
+ codec->set_bias_level = wm8960_set_bias_level;
+ codec->dai = &wm8960_dai;
+ codec->num_dai = 1;
+ codec->reg_cache_size = WM8960_CACHEREGNUM;
+ codec->reg_cache = &wm8960->reg_cache;
+
+ memcpy(codec->reg_cache, wm8960_reg, sizeof(wm8960_reg));
+
+ ret = wm8960_reset(codec);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to issue reset\n");
+ return ret;
+ }
+
+ wm8960_dai.dev = codec->dev;
+
+ wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ /* Latch the update bits */
+ reg = wm8960_read(codec, WM8960_LINVOL);
+ wm8960_write(codec, WM8960_LINVOL, reg | 0x100);
+ reg = wm8960_read(codec, WM8960_RINVOL);
+ wm8960_write(codec, WM8960_RINVOL, reg | 0x100);
+ reg = wm8960_read(codec, WM8960_LADC);
+ wm8960_write(codec, WM8960_LADC, reg | 0x100);
+ reg = wm8960_read(codec, WM8960_RADC);
+ wm8960_write(codec, WM8960_RADC, reg | 0x100);
+ reg = wm8960_read(codec, WM8960_LDAC);
+ wm8960_write(codec, WM8960_LDAC, reg | 0x100);
+ reg = wm8960_read(codec, WM8960_RDAC);
+ wm8960_write(codec, WM8960_RDAC, reg | 0x100);
+ reg = wm8960_read(codec, WM8960_LOUT1);
+ wm8960_write(codec, WM8960_LOUT1, reg | 0x100);
+ reg = wm8960_read(codec, WM8960_ROUT1);
+ wm8960_write(codec, WM8960_ROUT1, reg | 0x100);
+ reg = wm8960_read(codec, WM8960_LOUT2);
+ wm8960_write(codec, WM8960_LOUT2, reg | 0x100);
+ reg = wm8960_read(codec, WM8960_ROUT2);
+ wm8960_write(codec, WM8960_ROUT2, reg | 0x100);
+
+ wm8960_codec = codec;
+
+ ret = snd_soc_register_codec(codec);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to register codec: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_register_dai(&wm8960_dai);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
+ snd_soc_unregister_codec(codec);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void wm8960_unregister(struct wm8960_priv *wm8960)
+{
+ wm8960_set_bias_level(&wm8960->codec, SND_SOC_BIAS_OFF);
+ snd_soc_unregister_dai(&wm8960_dai);
+ snd_soc_unregister_codec(&wm8960->codec);
+ kfree(wm8960);
+ wm8960_codec = NULL;
+}
+
+static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct wm8960_priv *wm8960;
+ struct snd_soc_codec *codec;
+
+ wm8960 = kzalloc(sizeof(struct wm8960_priv), GFP_KERNEL);
+ if (wm8960 == NULL)
+ return -ENOMEM;
+
+ codec = &wm8960->codec;
+ codec->hw_write = (hw_write_t)i2c_master_send;
+
+ i2c_set_clientdata(i2c, wm8960);
+ codec->control_data = i2c;
+
+ codec->dev = &i2c->dev;
+
+ return wm8960_register(wm8960);
+}
+
+static __devexit int wm8960_i2c_remove(struct i2c_client *client)
+{
+ struct wm8960_priv *wm8960 = i2c_get_clientdata(client);
+ wm8960_unregister(wm8960);
+ return 0;
+}
+
+static const struct i2c_device_id wm8960_i2c_id[] = {
+ { "wm8960", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id);
+
+static struct i2c_driver wm8960_i2c_driver = {
+ .driver = {
+ .name = "WM8960 I2C Codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8960_i2c_probe,
+ .remove = __devexit_p(wm8960_i2c_remove),
+ .id_table = wm8960_i2c_id,
+};
+
+static int __init wm8960_modinit(void)
+{
+ int ret;
+
+ ret = i2c_add_driver(&wm8960_i2c_driver);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n",
+ ret);
+ }
+
+ return ret;
+}
+module_init(wm8960_modinit);
+
+static void __exit wm8960_exit(void)
+{
+ i2c_del_driver(&wm8960_i2c_driver);
+}
+module_exit(wm8960_exit);
+
+
+MODULE_DESCRIPTION("ASoC WM8960 driver");
+MODULE_AUTHOR("Liam Girdwood");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8960.h b/sound/soc/codecs/wm8960.h
new file mode 100644
index 000000000000..c9af56c9d9d4
--- /dev/null
+++ b/sound/soc/codecs/wm8960.h
@@ -0,0 +1,127 @@
+/*
+ * wm8960.h -- WM8960 Soc Audio driver
+ *
+ * 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 _WM8960_H
+#define _WM8960_H
+
+/* WM8960 register space */
+
+
+#define WM8960_CACHEREGNUM 56
+
+#define WM8960_LINVOL 0x0
+#define WM8960_RINVOL 0x1
+#define WM8960_LOUT1 0x2
+#define WM8960_ROUT1 0x3
+#define WM8960_CLOCK1 0x4
+#define WM8960_DACCTL1 0x5
+#define WM8960_DACCTL2 0x6
+#define WM8960_IFACE1 0x7
+#define WM8960_CLOCK2 0x8
+#define WM8960_IFACE2 0x9
+#define WM8960_LDAC 0xa
+#define WM8960_RDAC 0xb
+
+#define WM8960_RESET 0xf
+#define WM8960_3D 0x10
+#define WM8960_ALC1 0x11
+#define WM8960_ALC2 0x12
+#define WM8960_ALC3 0x13
+#define WM8960_NOISEG 0x14
+#define WM8960_LADC 0x15
+#define WM8960_RADC 0x16
+#define WM8960_ADDCTL1 0x17
+#define WM8960_ADDCTL2 0x18
+#define WM8960_POWER1 0x19
+#define WM8960_POWER2 0x1a
+#define WM8960_ADDCTL3 0x1b
+#define WM8960_APOP1 0x1c
+#define WM8960_APOP2 0x1d
+
+#define WM8960_LINPATH 0x20
+#define WM8960_RINPATH 0x21
+#define WM8960_LOUTMIX 0x22
+
+#define WM8960_ROUTMIX 0x25
+#define WM8960_MONOMIX1 0x26
+#define WM8960_MONOMIX2 0x27
+#define WM8960_LOUT2 0x28
+#define WM8960_ROUT2 0x29
+#define WM8960_MONO 0x2a
+#define WM8960_INBMIX1 0x2b
+#define WM8960_INBMIX2 0x2c
+#define WM8960_BYPASS1 0x2d
+#define WM8960_BYPASS2 0x2e
+#define WM8960_POWER3 0x2f
+#define WM8960_ADDCTL4 0x30
+#define WM8960_CLASSD1 0x31
+
+#define WM8960_CLASSD3 0x33
+#define WM8960_PLL1 0x34
+#define WM8960_PLL2 0x35
+#define WM8960_PLL3 0x36
+#define WM8960_PLL4 0x37
+
+
+/*
+ * WM8960 Clock dividers
+ */
+#define WM8960_SYSCLKDIV 0
+#define WM8960_DACDIV 1
+#define WM8960_OPCLKDIV 2
+#define WM8960_DCLKDIV 3
+#define WM8960_TOCLKSEL 4
+#define WM8960_SYSCLKSEL 5
+
+#define WM8960_SYSCLK_DIV_1 (0 << 1)
+#define WM8960_SYSCLK_DIV_2 (2 << 1)
+
+#define WM8960_SYSCLK_MCLK (0 << 0)
+#define WM8960_SYSCLK_PLL (1 << 0)
+
+#define WM8960_DAC_DIV_1 (0 << 3)
+#define WM8960_DAC_DIV_1_5 (1 << 3)
+#define WM8960_DAC_DIV_2 (2 << 3)
+#define WM8960_DAC_DIV_3 (3 << 3)
+#define WM8960_DAC_DIV_4 (4 << 3)
+#define WM8960_DAC_DIV_5_5 (5 << 3)
+#define WM8960_DAC_DIV_6 (6 << 3)
+
+#define WM8960_DCLK_DIV_1_5 (0 << 6)
+#define WM8960_DCLK_DIV_2 (1 << 6)
+#define WM8960_DCLK_DIV_3 (2 << 6)
+#define WM8960_DCLK_DIV_4 (3 << 6)
+#define WM8960_DCLK_DIV_6 (4 << 6)
+#define WM8960_DCLK_DIV_8 (5 << 6)
+#define WM8960_DCLK_DIV_12 (6 << 6)
+#define WM8960_DCLK_DIV_16 (7 << 6)
+
+#define WM8960_TOCLK_F19 (0 << 1)
+#define WM8960_TOCLK_F21 (1 << 1)
+
+#define WM8960_OPCLK_DIV_1 (0 << 0)
+#define WM8960_OPCLK_DIV_2 (1 << 0)
+#define WM8960_OPCLK_DIV_3 (2 << 0)
+#define WM8960_OPCLK_DIV_4 (3 << 0)
+#define WM8960_OPCLK_DIV_5_5 (4 << 0)
+#define WM8960_OPCLK_DIV_6 (5 << 0)
+
+extern struct snd_soc_dai wm8960_dai;
+extern struct snd_soc_codec_device soc_codec_dev_wm8960;
+
+#define WM8960_DRES_400R 0
+#define WM8960_DRES_200R 1
+#define WM8960_DRES_600R 2
+#define WM8960_DRES_150R 3
+#define WM8960_DRES_MAX 3
+
+struct wm8960_data {
+ int dres;
+};
+
+#endif
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
new file mode 100644
index 000000000000..c05f71803aa8
--- /dev/null
+++ b/sound/soc/codecs/wm8988.c
@@ -0,0 +1,1097 @@
+/*
+ * wm8988.c -- WM8988 ALSA SoC audio driver
+ *
+ * Copyright 2009 Wolfson Microelectronics plc
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/tlv.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+
+#include "wm8988.h"
+
+/*
+ * wm8988 register cache
+ * We can't read the WM8988 register space when we
+ * are using 2 wire for device control, so we cache them instead.
+ */
+static const u16 wm8988_reg[] = {
+ 0x0097, 0x0097, 0x0079, 0x0079, /* 0 */
+ 0x0000, 0x0008, 0x0000, 0x000a, /* 4 */
+ 0x0000, 0x0000, 0x00ff, 0x00ff, /* 8 */
+ 0x000f, 0x000f, 0x0000, 0x0000, /* 12 */
+ 0x0000, 0x007b, 0x0000, 0x0032, /* 16 */
+ 0x0000, 0x00c3, 0x00c3, 0x00c0, /* 20 */
+ 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */
+ 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */
+ 0x0000, 0x0000, 0x0050, 0x0050, /* 32 */
+ 0x0050, 0x0050, 0x0050, 0x0050, /* 36 */
+ 0x0079, 0x0079, 0x0079, /* 40 */
+};
+
+/* codec private data */
+struct wm8988_priv {
+ unsigned int sysclk;
+ struct snd_soc_codec codec;
+ struct snd_pcm_hw_constraint_list *sysclk_constraints;
+ u16 reg_cache[WM8988_NUM_REG];
+};
+
+
+/*
+ * read wm8988 register cache
+ */
+static inline unsigned int wm8988_read_reg_cache(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ u16 *cache = codec->reg_cache;
+ if (reg > WM8988_NUM_REG)
+ return -1;
+ return cache[reg];
+}
+
+/*
+ * write wm8988 register cache
+ */
+static inline void wm8988_write_reg_cache(struct snd_soc_codec *codec,
+ unsigned int reg, unsigned int value)
+{
+ u16 *cache = codec->reg_cache;
+ if (reg > WM8988_NUM_REG)
+ return;
+ cache[reg] = value;
+}
+
+static int wm8988_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value)
+{
+ u8 data[2];
+
+ /* data is
+ * D15..D9 WM8753 register offset
+ * D8...D0 register data
+ */
+ data[0] = (reg << 1) | ((value >> 8) & 0x0001);
+ data[1] = value & 0x00ff;
+
+ wm8988_write_reg_cache(codec, reg, value);
+ if (codec->hw_write(codec->control_data, data, 2) == 2)
+ return 0;
+ else
+ return -EIO;
+}
+
+#define wm8988_reset(c) wm8988_write(c, WM8988_RESET, 0)
+
+/*
+ * WM8988 Controls
+ */
+
+static const char *bass_boost_txt[] = {"Linear Control", "Adaptive Boost"};
+static const struct soc_enum bass_boost =
+ SOC_ENUM_SINGLE(WM8988_BASS, 7, 2, bass_boost_txt);
+
+static const char *bass_filter_txt[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" };
+static const struct soc_enum bass_filter =
+ SOC_ENUM_SINGLE(WM8988_BASS, 6, 2, bass_filter_txt);
+
+static const char *treble_txt[] = {"8kHz", "4kHz"};
+static const struct soc_enum treble =
+ SOC_ENUM_SINGLE(WM8988_TREBLE, 6, 2, treble_txt);
+
+static const char *stereo_3d_lc_txt[] = {"200Hz", "500Hz"};
+static const struct soc_enum stereo_3d_lc =
+ SOC_ENUM_SINGLE(WM8988_3D, 5, 2, stereo_3d_lc_txt);
+
+static const char *stereo_3d_uc_txt[] = {"2.2kHz", "1.5kHz"};
+static const struct soc_enum stereo_3d_uc =
+ SOC_ENUM_SINGLE(WM8988_3D, 6, 2, stereo_3d_uc_txt);
+
+static const char *stereo_3d_func_txt[] = {"Capture", "Playback"};
+static const struct soc_enum stereo_3d_func =
+ SOC_ENUM_SINGLE(WM8988_3D, 7, 2, stereo_3d_func_txt);
+
+static const char *alc_func_txt[] = {"Off", "Right", "Left", "Stereo"};
+static const struct soc_enum alc_func =
+ SOC_ENUM_SINGLE(WM8988_ALC1, 7, 4, alc_func_txt);
+
+static const char *ng_type_txt[] = {"Constant PGA Gain",
+ "Mute ADC Output"};
+static const struct soc_enum ng_type =
+ SOC_ENUM_SINGLE(WM8988_NGATE, 1, 2, ng_type_txt);
+
+static const char *deemph_txt[] = {"None", "32Khz", "44.1Khz", "48Khz"};
+static const struct soc_enum deemph =
+ SOC_ENUM_SINGLE(WM8988_ADCDAC, 1, 4, deemph_txt);
+
+static const char *adcpol_txt[] = {"Normal", "L Invert", "R Invert",
+ "L + R Invert"};
+static const struct soc_enum adcpol =
+ SOC_ENUM_SINGLE(WM8988_ADCDAC, 5, 4, adcpol_txt);
+
+static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0);
+static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1);
+static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
+static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
+static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
+
+static const struct snd_kcontrol_new wm8988_snd_controls[] = {
+
+SOC_ENUM("Bass Boost", bass_boost),
+SOC_ENUM("Bass Filter", bass_filter),
+SOC_SINGLE("Bass Volume", WM8988_BASS, 0, 15, 1),
+
+SOC_SINGLE("Treble Volume", WM8988_TREBLE, 0, 15, 0),
+SOC_ENUM("Treble Cut-off", treble),
+
+SOC_SINGLE("3D Switch", WM8988_3D, 0, 1, 0),
+SOC_SINGLE("3D Volume", WM8988_3D, 1, 15, 0),
+SOC_ENUM("3D Lower Cut-off", stereo_3d_lc),
+SOC_ENUM("3D Upper Cut-off", stereo_3d_uc),
+SOC_ENUM("3D Mode", stereo_3d_func),
+
+SOC_SINGLE("ALC Capture Target Volume", WM8988_ALC1, 0, 7, 0),
+SOC_SINGLE("ALC Capture Max Volume", WM8988_ALC1, 4, 7, 0),
+SOC_ENUM("ALC Capture Function", alc_func),
+SOC_SINGLE("ALC Capture ZC Switch", WM8988_ALC2, 7, 1, 0),
+SOC_SINGLE("ALC Capture Hold Time", WM8988_ALC2, 0, 15, 0),
+SOC_SINGLE("ALC Capture Decay Time", WM8988_ALC3, 4, 15, 0),
+SOC_SINGLE("ALC Capture Attack Time", WM8988_ALC3, 0, 15, 0),
+SOC_SINGLE("ALC Capture NG Threshold", WM8988_NGATE, 3, 31, 0),
+SOC_ENUM("ALC Capture NG Type", ng_type),
+SOC_SINGLE("ALC Capture NG Switch", WM8988_NGATE, 0, 1, 0),
+
+SOC_SINGLE("ZC Timeout Switch", WM8988_ADCTL1, 0, 1, 0),
+
+SOC_DOUBLE_R_TLV("Capture Digital Volume", WM8988_LADC, WM8988_RADC,
+ 0, 255, 0, adc_tlv),
+SOC_DOUBLE_R_TLV("Capture Volume", WM8988_LINVOL, WM8988_RINVOL,
+ 0, 63, 0, pga_tlv),
+SOC_DOUBLE_R("Capture ZC Switch", WM8988_LINVOL, WM8988_RINVOL, 6, 1, 0),
+SOC_DOUBLE_R("Capture Switch", WM8988_LINVOL, WM8988_RINVOL, 7, 1, 1),
+
+SOC_ENUM("Playback De-emphasis", deemph),
+
+SOC_ENUM("Capture Polarity", adcpol),
+SOC_SINGLE("Playback 6dB Attenuate", WM8988_ADCDAC, 7, 1, 0),
+SOC_SINGLE("Capture 6dB Attenuate", WM8988_ADCDAC, 8, 1, 0),
+
+SOC_DOUBLE_R_TLV("PCM Volume", WM8988_LDAC, WM8988_RDAC, 0, 255, 0, dac_tlv),
+
+SOC_SINGLE_TLV("Left Mixer Left Bypass Volume", WM8988_LOUTM1, 4, 7, 1,
+ bypass_tlv),
+SOC_SINGLE_TLV("Left Mixer Right Bypass Volume", WM8988_LOUTM2, 4, 7, 1,
+ bypass_tlv),
+SOC_SINGLE_TLV("Right Mixer Left Bypass Volume", WM8988_ROUTM1, 4, 7, 1,
+ bypass_tlv),
+SOC_SINGLE_TLV("Right Mixer Right Bypass Volume", WM8988_ROUTM2, 4, 7, 1,
+ bypass_tlv),
+
+SOC_DOUBLE_R("Output 1 Playback ZC Switch", WM8988_LOUT1V,
+ WM8988_ROUT1V, 7, 1, 0),
+SOC_DOUBLE_R_TLV("Output 1 Playback Volume", WM8988_LOUT1V, WM8988_ROUT1V,
+ 0, 127, 0, out_tlv),
+
+SOC_DOUBLE_R("Output 2 Playback ZC Switch", WM8988_LOUT2V,
+ WM8988_ROUT2V, 7, 1, 0),
+SOC_DOUBLE_R_TLV("Output 2 Playback Volume", WM8988_LOUT2V, WM8988_ROUT2V,
+ 0, 127, 0, out_tlv),
+
+};
+
+/*
+ * DAPM Controls
+ */
+
+static int wm8988_lrc_control(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ u16 adctl2 = wm8988_read_reg_cache(codec, WM8988_ADCTL2);
+
+ /* Use the DAC to gate LRC if active, otherwise use ADC */
+ if (wm8988_read_reg_cache(codec, WM8988_PWR2) & 0x180)
+ adctl2 &= ~0x4;
+ else
+ adctl2 |= 0x4;
+
+ return wm8988_write(codec, WM8988_ADCTL2, adctl2);
+}
+
+static const char *wm8988_line_texts[] = {
+ "Line 1", "Line 2", "PGA", "Differential"};
+
+static const unsigned int wm8988_line_values[] = {
+ 0, 1, 3, 4};
+
+static const struct soc_enum wm8988_lline_enum =
+ SOC_VALUE_ENUM_SINGLE(WM8988_LOUTM1, 0, 7,
+ ARRAY_SIZE(wm8988_line_texts),
+ wm8988_line_texts,
+ wm8988_line_values);
+static const struct snd_kcontrol_new wm8988_left_line_controls =
+ SOC_DAPM_VALUE_ENUM("Route", wm8988_lline_enum);
+
+static const struct soc_enum wm8988_rline_enum =
+ SOC_VALUE_ENUM_SINGLE(WM8988_ROUTM1, 0, 7,
+ ARRAY_SIZE(wm8988_line_texts),
+ wm8988_line_texts,
+ wm8988_line_values);
+static const struct snd_kcontrol_new wm8988_right_line_controls =
+ SOC_DAPM_VALUE_ENUM("Route", wm8988_lline_enum);
+
+/* Left Mixer */
+static const struct snd_kcontrol_new wm8988_left_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Playback Switch", WM8988_LOUTM1, 8, 1, 0),
+ SOC_DAPM_SINGLE("Left Bypass Switch", WM8988_LOUTM1, 7, 1, 0),
+ SOC_DAPM_SINGLE("Right Playback Switch", WM8988_LOUTM2, 8, 1, 0),
+ SOC_DAPM_SINGLE("Right Bypass Switch", WM8988_LOUTM2, 7, 1, 0),
+};
+
+/* Right Mixer */
+static const struct snd_kcontrol_new wm8988_right_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Left Playback Switch", WM8988_ROUTM1, 8, 1, 0),
+ SOC_DAPM_SINGLE("Left Bypass Switch", WM8988_ROUTM1, 7, 1, 0),
+ SOC_DAPM_SINGLE("Playback Switch", WM8988_ROUTM2, 8, 1, 0),
+ SOC_DAPM_SINGLE("Right Bypass Switch", WM8988_ROUTM2, 7, 1, 0),
+};
+
+static const char *wm8988_pga_sel[] = {"Line 1", "Line 2", "Differential"};
+static const unsigned int wm8988_pga_val[] = { 0, 1, 3 };
+
+/* Left PGA Mux */
+static const struct soc_enum wm8988_lpga_enum =
+ SOC_VALUE_ENUM_SINGLE(WM8988_LADCIN, 6, 3,
+ ARRAY_SIZE(wm8988_pga_sel),
+ wm8988_pga_sel,
+ wm8988_pga_val);
+static const struct snd_kcontrol_new wm8988_left_pga_controls =
+ SOC_DAPM_VALUE_ENUM("Route", wm8988_lpga_enum);
+
+/* Right PGA Mux */
+static const struct soc_enum wm8988_rpga_enum =
+ SOC_VALUE_ENUM_SINGLE(WM8988_RADCIN, 6, 3,
+ ARRAY_SIZE(wm8988_pga_sel),
+ wm8988_pga_sel,
+ wm8988_pga_val);
+static const struct snd_kcontrol_new wm8988_right_pga_controls =
+ SOC_DAPM_VALUE_ENUM("Route", wm8988_rpga_enum);
+
+/* Differential Mux */
+static const char *wm8988_diff_sel[] = {"Line 1", "Line 2"};
+static const struct soc_enum diffmux =
+ SOC_ENUM_SINGLE(WM8988_ADCIN, 8, 2, wm8988_diff_sel);
+static const struct snd_kcontrol_new wm8988_diffmux_controls =
+ SOC_DAPM_ENUM("Route", diffmux);
+
+/* Mono ADC Mux */
+static const char *wm8988_mono_mux[] = {"Stereo", "Mono (Left)",
+ "Mono (Right)", "Digital Mono"};
+static const struct soc_enum monomux =
+ SOC_ENUM_SINGLE(WM8988_ADCIN, 6, 4, wm8988_mono_mux);
+static const struct snd_kcontrol_new wm8988_monomux_controls =
+ SOC_DAPM_ENUM("Route", monomux);
+
+static const struct snd_soc_dapm_widget wm8988_dapm_widgets[] = {
+ SND_SOC_DAPM_MICBIAS("Mic Bias", WM8988_PWR1, 1, 0),
+
+ SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0,
+ &wm8988_diffmux_controls),
+ SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0,
+ &wm8988_monomux_controls),
+ SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0,
+ &wm8988_monomux_controls),
+
+ SND_SOC_DAPM_MUX("Left PGA Mux", WM8988_PWR1, 5, 0,
+ &wm8988_left_pga_controls),
+ SND_SOC_DAPM_MUX("Right PGA Mux", WM8988_PWR1, 4, 0,
+ &wm8988_right_pga_controls),
+
+ SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0,
+ &wm8988_left_line_controls),
+ SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0,
+ &wm8988_right_line_controls),
+
+ SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8988_PWR1, 2, 0),
+ SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8988_PWR1, 3, 0),
+
+ SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8988_PWR2, 7, 0),
+ SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8988_PWR2, 8, 0),
+
+ SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0,
+ &wm8988_left_mixer_controls[0],
+ ARRAY_SIZE(wm8988_left_mixer_controls)),
+ SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0,
+ &wm8988_right_mixer_controls[0],
+ ARRAY_SIZE(wm8988_right_mixer_controls)),
+
+ SND_SOC_DAPM_PGA("Right Out 2", WM8988_PWR2, 3, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Left Out 2", WM8988_PWR2, 4, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Right Out 1", WM8988_PWR2, 5, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Left Out 1", WM8988_PWR2, 6, 0, NULL, 0),
+
+ SND_SOC_DAPM_POST("LRC control", wm8988_lrc_control),
+
+ SND_SOC_DAPM_OUTPUT("LOUT1"),
+ SND_SOC_DAPM_OUTPUT("ROUT1"),
+ SND_SOC_DAPM_OUTPUT("LOUT2"),
+ SND_SOC_DAPM_OUTPUT("ROUT2"),
+ SND_SOC_DAPM_OUTPUT("VREF"),
+
+ SND_SOC_DAPM_INPUT("LINPUT1"),
+ SND_SOC_DAPM_INPUT("LINPUT2"),
+ SND_SOC_DAPM_INPUT("RINPUT1"),
+ SND_SOC_DAPM_INPUT("RINPUT2"),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+
+ { "Left Line Mux", "Line 1", "LINPUT1" },
+ { "Left Line Mux", "Line 2", "LINPUT2" },
+ { "Left Line Mux", "PGA", "Left PGA Mux" },
+ { "Left Line Mux", "Differential", "Differential Mux" },
+
+ { "Right Line Mux", "Line 1", "RINPUT1" },
+ { "Right Line Mux", "Line 2", "RINPUT2" },
+ { "Right Line Mux", "PGA", "Right PGA Mux" },
+ { "Right Line Mux", "Differential", "Differential Mux" },
+
+ { "Left PGA Mux", "Line 1", "LINPUT1" },
+ { "Left PGA Mux", "Line 2", "LINPUT2" },
+ { "Left PGA Mux", "Differential", "Differential Mux" },
+
+ { "Right PGA Mux", "Line 1", "RINPUT1" },
+ { "Right PGA Mux", "Line 2", "RINPUT2" },
+ { "Right PGA Mux", "Differential", "Differential Mux" },
+
+ { "Differential Mux", "Line 1", "LINPUT1" },
+ { "Differential Mux", "Line 1", "RINPUT1" },
+ { "Differential Mux", "Line 2", "LINPUT2" },
+ { "Differential Mux", "Line 2", "RINPUT2" },
+
+ { "Left ADC Mux", "Stereo", "Left PGA Mux" },
+ { "Left ADC Mux", "Mono (Left)", "Left PGA Mux" },
+ { "Left ADC Mux", "Digital Mono", "Left PGA Mux" },
+
+ { "Right ADC Mux", "Stereo", "Right PGA Mux" },
+ { "Right ADC Mux", "Mono (Right)", "Right PGA Mux" },
+ { "Right ADC Mux", "Digital Mono", "Right PGA Mux" },
+
+ { "Left ADC", NULL, "Left ADC Mux" },
+ { "Right ADC", NULL, "Right ADC Mux" },
+
+ { "Left Line Mux", "Line 1", "LINPUT1" },
+ { "Left Line Mux", "Line 2", "LINPUT2" },
+ { "Left Line Mux", "PGA", "Left PGA Mux" },
+ { "Left Line Mux", "Differential", "Differential Mux" },
+
+ { "Right Line Mux", "Line 1", "RINPUT1" },
+ { "Right Line Mux", "Line 2", "RINPUT2" },
+ { "Right Line Mux", "PGA", "Right PGA Mux" },
+ { "Right Line Mux", "Differential", "Differential Mux" },
+
+ { "Left Mixer", "Playback Switch", "Left DAC" },
+ { "Left Mixer", "Left Bypass Switch", "Left Line Mux" },
+ { "Left Mixer", "Right Playback Switch", "Right DAC" },
+ { "Left Mixer", "Right Bypass Switch", "Right Line Mux" },
+
+ { "Right Mixer", "Left Playback Switch", "Left DAC" },
+ { "Right Mixer", "Left Bypass Switch", "Left Line Mux" },
+ { "Right Mixer", "Playback Switch", "Right DAC" },
+ { "Right Mixer", "Right Bypass Switch", "Right Line Mux" },
+
+ { "Left Out 1", NULL, "Left Mixer" },
+ { "LOUT1", NULL, "Left Out 1" },
+ { "Right Out 1", NULL, "Right Mixer" },
+ { "ROUT1", NULL, "Right Out 1" },
+
+ { "Left Out 2", NULL, "Left Mixer" },
+ { "LOUT2", NULL, "Left Out 2" },
+ { "Right Out 2", NULL, "Right Mixer" },
+ { "ROUT2", NULL, "Right Out 2" },
+};
+
+struct _coeff_div {
+ u32 mclk;
+ u32 rate;
+ u16 fs;
+ u8 sr:5;
+ u8 usb:1;
+};
+
+/* codec hifi mclk clock divider coefficients */
+static const struct _coeff_div coeff_div[] = {
+ /* 8k */
+ {12288000, 8000, 1536, 0x6, 0x0},
+ {11289600, 8000, 1408, 0x16, 0x0},
+ {18432000, 8000, 2304, 0x7, 0x0},
+ {16934400, 8000, 2112, 0x17, 0x0},
+ {12000000, 8000, 1500, 0x6, 0x1},
+
+ /* 11.025k */
+ {11289600, 11025, 1024, 0x18, 0x0},
+ {16934400, 11025, 1536, 0x19, 0x0},
+ {12000000, 11025, 1088, 0x19, 0x1},
+
+ /* 16k */
+ {12288000, 16000, 768, 0xa, 0x0},
+ {18432000, 16000, 1152, 0xb, 0x0},
+ {12000000, 16000, 750, 0xa, 0x1},
+
+ /* 22.05k */
+ {11289600, 22050, 512, 0x1a, 0x0},
+ {16934400, 22050, 768, 0x1b, 0x0},
+ {12000000, 22050, 544, 0x1b, 0x1},
+
+ /* 32k */
+ {12288000, 32000, 384, 0xc, 0x0},
+ {18432000, 32000, 576, 0xd, 0x0},
+ {12000000, 32000, 375, 0xa, 0x1},
+
+ /* 44.1k */
+ {11289600, 44100, 256, 0x10, 0x0},
+ {16934400, 44100, 384, 0x11, 0x0},
+ {12000000, 44100, 272, 0x11, 0x1},
+
+ /* 48k */
+ {12288000, 48000, 256, 0x0, 0x0},
+ {18432000, 48000, 384, 0x1, 0x0},
+ {12000000, 48000, 250, 0x0, 0x1},
+
+ /* 88.2k */
+ {11289600, 88200, 128, 0x1e, 0x0},
+ {16934400, 88200, 192, 0x1f, 0x0},
+ {12000000, 88200, 136, 0x1f, 0x1},
+
+ /* 96k */
+ {12288000, 96000, 128, 0xe, 0x0},
+ {18432000, 96000, 192, 0xf, 0x0},
+ {12000000, 96000, 125, 0xe, 0x1},
+};
+
+static inline int get_coeff(int mclk, int rate)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
+ if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
+ return i;
+ }
+
+ return -EINVAL;
+}
+
+/* The set of rates we can generate from the above for each SYSCLK */
+
+static unsigned int rates_12288[] = {
+ 8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_12288 = {
+ .count = ARRAY_SIZE(rates_12288),
+ .list = rates_12288,
+};
+
+static unsigned int rates_112896[] = {
+ 8000, 11025, 22050, 44100,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_112896 = {
+ .count = ARRAY_SIZE(rates_112896),
+ .list = rates_112896,
+};
+
+static unsigned int rates_12[] = {
+ 8000, 11025, 12000, 16000, 22050, 2400, 32000, 41100, 48000,
+ 48000, 88235, 96000,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_12 = {
+ .count = ARRAY_SIZE(rates_12),
+ .list = rates_12,
+};
+
+/*
+ * Note that this should be called from init rather than from hw_params.
+ */
+static int wm8988_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct wm8988_priv *wm8988 = codec->private_data;
+
+ switch (freq) {
+ case 11289600:
+ case 18432000:
+ case 22579200:
+ case 36864000:
+ wm8988->sysclk_constraints = &constraints_112896;
+ wm8988->sysclk = freq;
+ return 0;
+
+ case 12288000:
+ case 16934400:
+ case 24576000:
+ case 33868800:
+ wm8988->sysclk_constraints = &constraints_12288;
+ wm8988->sysclk = freq;
+ return 0;
+
+ case 12000000:
+ case 24000000:
+ wm8988->sysclk_constraints = &constraints_12;
+ wm8988->sysclk = freq;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int wm8988_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u16 iface = 0;
+
+ /* set master/slave audio interface */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ iface = 0x0040;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* interface format */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ iface |= 0x0002;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ iface |= 0x0001;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ iface |= 0x0003;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ iface |= 0x0013;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* clock inversion */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ iface |= 0x0090;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ iface |= 0x0080;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ iface |= 0x0010;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ wm8988_write(codec, WM8988_IFACE, iface);
+ return 0;
+}
+
+static int wm8988_pcm_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct wm8988_priv *wm8988 = codec->private_data;
+
+ /* The set of sample rates that can be supported depends on the
+ * MCLK supplied to the CODEC - enforce this.
+ */
+ if (!wm8988->sysclk) {
+ dev_err(codec->dev,
+ "No MCLK configured, call set_sysclk() on init\n");
+ return -EINVAL;
+ }
+
+ snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ wm8988->sysclk_constraints);
+
+ return 0;
+}
+
+static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->card->codec;
+ struct wm8988_priv *wm8988 = codec->private_data;
+ u16 iface = wm8988_read_reg_cache(codec, WM8988_IFACE) & 0x1f3;
+ u16 srate = wm8988_read_reg_cache(codec, WM8988_SRATE) & 0x180;
+ int coeff;
+
+ coeff = get_coeff(wm8988->sysclk, params_rate(params));
+ if (coeff < 0) {
+ coeff = get_coeff(wm8988->sysclk / 2, params_rate(params));
+ srate |= 0x40;
+ }
+ if (coeff < 0) {
+ dev_err(codec->dev,
+ "Unable to configure sample rate %dHz with %dHz MCLK\n",
+ params_rate(params), wm8988->sysclk);
+ return coeff;
+ }
+
+ /* bit size */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ iface |= 0x0004;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ iface |= 0x0008;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ iface |= 0x000c;
+ break;
+ }
+
+ /* set iface & srate */
+ wm8988_write(codec, WM8988_IFACE, iface);
+ if (coeff >= 0)
+ wm8988_write(codec, WM8988_SRATE, srate |
+ (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
+
+ return 0;
+}
+
+static int wm8988_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ u16 mute_reg = wm8988_read_reg_cache(codec, WM8988_ADCDAC) & 0xfff7;
+
+ if (mute)
+ wm8988_write(codec, WM8988_ADCDAC, mute_reg | 0x8);
+ else
+ wm8988_write(codec, WM8988_ADCDAC, mute_reg);
+ return 0;
+}
+
+static int wm8988_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ u16 pwr_reg = wm8988_read_reg_cache(codec, WM8988_PWR1) & ~0x1c1;
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ break;
+
+ case SND_SOC_BIAS_PREPARE:
+ /* VREF, VMID=2x50k, digital enabled */
+ wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x00c0);
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->bias_level == SND_SOC_BIAS_OFF) {
+ /* VREF, VMID=2x5k */
+ wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x1c1);
+
+ /* Charge caps */
+ msleep(100);
+ }
+
+ /* VREF, VMID=2*500k, digital stopped */
+ wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x0141);
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ wm8988_write(codec, WM8988_PWR1, 0x0000);
+ break;
+ }
+ codec->bias_level = level;
+ return 0;
+}
+
+#define WM8988_RATES SNDRV_PCM_RATE_8000_96000
+
+#define WM8988_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_ops wm8988_ops = {
+ .startup = wm8988_pcm_startup,
+ .hw_params = wm8988_pcm_hw_params,
+ .set_fmt = wm8988_set_dai_fmt,
+ .set_sysclk = wm8988_set_dai_sysclk,
+ .digital_mute = wm8988_mute,
+};
+
+struct snd_soc_dai wm8988_dai = {
+ .name = "WM8988",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = WM8988_RATES,
+ .formats = WM8988_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = WM8988_RATES,
+ .formats = WM8988_FORMATS,
+ },
+ .ops = &wm8988_ops,
+ .symmetric_rates = 1,
+};
+EXPORT_SYMBOL_GPL(wm8988_dai);
+
+static int wm8988_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->card->codec;
+
+ wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+
+static int wm8988_resume(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->card->codec;
+ int i;
+ u8 data[2];
+ u16 *cache = codec->reg_cache;
+
+ /* Sync reg_cache with the hardware */
+ for (i = 0; i < WM8988_NUM_REG; i++) {
+ if (i == WM8988_RESET)
+ continue;
+ data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
+ data[1] = cache[i] & 0x00ff;
+ codec->hw_write(codec->control_data, data, 2);
+ }
+
+ wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ return 0;
+}
+
+static struct snd_soc_codec *wm8988_codec;
+
+static int wm8988_probe(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec;
+ int ret = 0;
+
+ if (wm8988_codec == NULL) {
+ dev_err(&pdev->dev, "Codec device not registered\n");
+ return -ENODEV;
+ }
+
+ socdev->card->codec = wm8988_codec;
+ codec = wm8988_codec;
+
+ /* register pcms */
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ dev_err(codec->dev, "failed to create pcms: %d\n", ret);
+ goto pcm_err;
+ }
+
+ snd_soc_add_controls(codec, wm8988_snd_controls,
+ ARRAY_SIZE(wm8988_snd_controls));
+ snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets,
+ ARRAY_SIZE(wm8988_dapm_widgets));
+ snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+ snd_soc_dapm_new_widgets(codec);
+
+ ret = snd_soc_init_card(socdev);
+ if (ret < 0) {
+ dev_err(codec->dev, "failed to register card: %d\n", ret);
+ goto card_err;
+ }
+
+ return ret;
+
+card_err:
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+pcm_err:
+ return ret;
+}
+
+static int wm8988_remove(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+
+ return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_wm8988 = {
+ .probe = wm8988_probe,
+ .remove = wm8988_remove,
+ .suspend = wm8988_suspend,
+ .resume = wm8988_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm8988);
+
+static int wm8988_register(struct wm8988_priv *wm8988)
+{
+ struct snd_soc_codec *codec = &wm8988->codec;
+ int ret;
+ u16 reg;
+
+ if (wm8988_codec) {
+ dev_err(codec->dev, "Another WM8988 is registered\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ mutex_init(&codec->mutex);
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+
+ codec->private_data = wm8988;
+ codec->name = "WM8988";
+ codec->owner = THIS_MODULE;
+ codec->read = wm8988_read_reg_cache;
+ codec->write = wm8988_write;
+ codec->dai = &wm8988_dai;
+ codec->num_dai = 1;
+ codec->reg_cache_size = ARRAY_SIZE(wm8988->reg_cache);
+ codec->reg_cache = &wm8988->reg_cache;
+ codec->bias_level = SND_SOC_BIAS_OFF;
+ codec->set_bias_level = wm8988_set_bias_level;
+
+ memcpy(codec->reg_cache, wm8988_reg,
+ sizeof(wm8988_reg));
+
+ ret = wm8988_reset(codec);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to issue reset\n");
+ return ret;
+ }
+
+ /* set the update bits (we always update left then right) */
+ reg = wm8988_read_reg_cache(codec, WM8988_RADC);
+ wm8988_write(codec, WM8988_RADC, reg | 0x100);
+ reg = wm8988_read_reg_cache(codec, WM8988_RDAC);
+ wm8988_write(codec, WM8988_RDAC, reg | 0x0100);
+ reg = wm8988_read_reg_cache(codec, WM8988_ROUT1V);
+ wm8988_write(codec, WM8988_ROUT1V, reg | 0x0100);
+ reg = wm8988_read_reg_cache(codec, WM8988_ROUT2V);
+ wm8988_write(codec, WM8988_ROUT2V, reg | 0x0100);
+ reg = wm8988_read_reg_cache(codec, WM8988_RINVOL);
+ wm8988_write(codec, WM8988_RINVOL, reg | 0x0100);
+
+ wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_STANDBY);
+
+ wm8988_dai.dev = codec->dev;
+
+ wm8988_codec = codec;
+
+ ret = snd_soc_register_codec(codec);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to register codec: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_register_dai(&wm8988_dai);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
+ snd_soc_unregister_codec(codec);
+ return ret;
+ }
+
+ return 0;
+
+err:
+ kfree(wm8988);
+ return ret;
+}
+
+static void wm8988_unregister(struct wm8988_priv *wm8988)
+{
+ wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_OFF);
+ snd_soc_unregister_dai(&wm8988_dai);
+ snd_soc_unregister_codec(&wm8988->codec);
+ kfree(wm8988);
+ wm8988_codec = NULL;
+}
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static int wm8988_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct wm8988_priv *wm8988;
+ struct snd_soc_codec *codec;
+
+ wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
+ if (wm8988 == NULL)
+ return -ENOMEM;
+
+ codec = &wm8988->codec;
+ codec->hw_write = (hw_write_t)i2c_master_send;
+
+ i2c_set_clientdata(i2c, wm8988);
+ codec->control_data = i2c;
+
+ codec->dev = &i2c->dev;
+
+ return wm8988_register(wm8988);
+}
+
+static int wm8988_i2c_remove(struct i2c_client *client)
+{
+ struct wm8988_priv *wm8988 = i2c_get_clientdata(client);
+ wm8988_unregister(wm8988);
+ return 0;
+}
+
+static const struct i2c_device_id wm8988_i2c_id[] = {
+ { "wm8988", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id);
+
+static struct i2c_driver wm8988_i2c_driver = {
+ .driver = {
+ .name = "WM8988",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8988_i2c_probe,
+ .remove = wm8988_i2c_remove,
+ .id_table = wm8988_i2c_id,
+};
+#endif
+
+#if defined(CONFIG_SPI_MASTER)
+static int wm8988_spi_write(struct spi_device *spi, const char *data, int len)
+{
+ struct spi_transfer t;
+ struct spi_message m;
+ u8 msg[2];
+
+ if (len <= 0)
+ return 0;
+
+ msg[0] = data[0];
+ msg[1] = data[1];
+
+ spi_message_init(&m);
+ memset(&t, 0, (sizeof t));
+
+ t.tx_buf = &msg[0];
+ t.len = len;
+
+ spi_message_add_tail(&t, &m);
+ spi_sync(spi, &m);
+
+ return len;
+}
+
+static int __devinit wm8988_spi_probe(struct spi_device *spi)
+{
+ struct wm8988_priv *wm8988;
+ struct snd_soc_codec *codec;
+
+ wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
+ if (wm8988 == NULL)
+ return -ENOMEM;
+
+ codec = &wm8988->codec;
+ codec->hw_write = (hw_write_t)wm8988_spi_write;
+ codec->control_data = spi;
+ codec->dev = &spi->dev;
+
+ spi->dev.driver_data = wm8988;
+
+ return wm8988_register(wm8988);
+}
+
+static int __devexit wm8988_spi_remove(struct spi_device *spi)
+{
+ struct wm8988_priv *wm8988 = spi->dev.driver_data;
+
+ wm8988_unregister(wm8988);
+
+ return 0;
+}
+
+static struct spi_driver wm8988_spi_driver = {
+ .driver = {
+ .name = "wm8988",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8988_spi_probe,
+ .remove = __devexit_p(wm8988_spi_remove),
+};
+#endif
+
+static int __init wm8988_modinit(void)
+{
+ int ret;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ ret = i2c_add_driver(&wm8988_i2c_driver);
+ if (ret != 0)
+ pr_err("WM8988: Unable to register I2C driver: %d\n", ret);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+ ret = spi_register_driver(&wm8988_spi_driver);
+ if (ret != 0)
+ pr_err("WM8988: Unable to register SPI driver: %d\n", ret);
+#endif
+ return ret;
+}
+module_init(wm8988_modinit);
+
+static void __exit wm8988_exit(void)
+{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ i2c_del_driver(&wm8988_i2c_driver);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+ spi_unregister_driver(&wm8988_spi_driver);
+#endif
+}
+module_exit(wm8988_exit);
+
+
+MODULE_DESCRIPTION("ASoC WM8988 driver");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8988.h b/sound/soc/codecs/wm8988.h
new file mode 100644
index 000000000000..4552d37fdd41
--- /dev/null
+++ b/sound/soc/codecs/wm8988.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <richard@openedhand.com>
+ *
+ * Based on WM8753.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.
+ *
+ */
+
+#ifndef _WM8988_H
+#define _WM8988_H
+
+/* WM8988 register space */
+
+#define WM8988_LINVOL 0x00
+#define WM8988_RINVOL 0x01
+#define WM8988_LOUT1V 0x02
+#define WM8988_ROUT1V 0x03
+#define WM8988_ADCDAC 0x05
+#define WM8988_IFACE 0x07
+#define WM8988_SRATE 0x08
+#define WM8988_LDAC 0x0a
+#define WM8988_RDAC 0x0b
+#define WM8988_BASS 0x0c
+#define WM8988_TREBLE 0x0d
+#define WM8988_RESET 0x0f
+#define WM8988_3D 0x10
+#define WM8988_ALC1 0x11
+#define WM8988_ALC2 0x12
+#define WM8988_ALC3 0x13
+#define WM8988_NGATE 0x14
+#define WM8988_LADC 0x15
+#define WM8988_RADC 0x16
+#define WM8988_ADCTL1 0x17
+#define WM8988_ADCTL2 0x18
+#define WM8988_PWR1 0x19
+#define WM8988_PWR2 0x1a
+#define WM8988_ADCTL3 0x1b
+#define WM8988_ADCIN 0x1f
+#define WM8988_LADCIN 0x20
+#define WM8988_RADCIN 0x21
+#define WM8988_LOUTM1 0x22
+#define WM8988_LOUTM2 0x23
+#define WM8988_ROUTM1 0x24
+#define WM8988_ROUTM2 0x25
+#define WM8988_LOUT2V 0x28
+#define WM8988_ROUT2V 0x29
+#define WM8988_LPPB 0x43
+#define WM8988_NUM_REG 0x44
+
+#define WM8988_SYSCLK 0
+
+extern struct snd_soc_dai wm8988_dai;
+extern struct snd_soc_codec_device soc_codec_dev_wm8988;
+
+#endif
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index c518c3e5aa3f..40cd274eb1ef 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -729,7 +729,7 @@ SND_SOC_DAPM_MIXER_E("INMIXL", WM8990_INTDRIVBITS, WM8990_INMIXL_PWR_BIT, 0,
inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
/* AINLMUX */
-SND_SOC_DAPM_MUX_E("AILNMUX", WM8990_INTDRIVBITS, WM8990_AINLMUX_PWR_BIT, 0,
+SND_SOC_DAPM_MUX_E("AINLMUX", WM8990_INTDRIVBITS, WM8990_AINLMUX_PWR_BIT, 0,
&wm8990_dapm_ainlmux_controls, inmixer_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
@@ -740,7 +740,7 @@ SND_SOC_DAPM_MIXER_E("INMIXR", WM8990_INTDRIVBITS, WM8990_INMIXR_PWR_BIT, 0,
inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
/* AINRMUX */
-SND_SOC_DAPM_MUX_E("AIRNMUX", WM8990_INTDRIVBITS, WM8990_AINRMUX_PWR_BIT, 0,
+SND_SOC_DAPM_MUX_E("AINRMUX", WM8990_INTDRIVBITS, WM8990_AINRMUX_PWR_BIT, 0,
&wm8990_dapm_ainrmux_controls, inmixer_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
@@ -848,40 +848,40 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"LIN12 PGA", "LIN2 Switch", "LIN2"},
/* LIN34 PGA */
{"LIN34 PGA", "LIN3 Switch", "LIN3"},
- {"LIN34 PGA", "LIN4 Switch", "LIN4"},
+ {"LIN34 PGA", "LIN4 Switch", "LIN4/RXN"},
/* INMIXL */
{"INMIXL", "Record Left Volume", "LOMIX"},
{"INMIXL", "LIN2 Volume", "LIN2"},
{"INMIXL", "LINPGA12 Switch", "LIN12 PGA"},
{"INMIXL", "LINPGA34 Switch", "LIN34 PGA"},
- /* AILNMUX */
- {"AILNMUX", "INMIXL Mix", "INMIXL"},
- {"AILNMUX", "DIFFINL Mix", "LIN12PGA"},
- {"AILNMUX", "DIFFINL Mix", "LIN34PGA"},
- {"AILNMUX", "RXVOICE Mix", "LIN4/RXN"},
- {"AILNMUX", "RXVOICE Mix", "RIN4/RXP"},
+ /* AINLMUX */
+ {"AINLMUX", "INMIXL Mix", "INMIXL"},
+ {"AINLMUX", "DIFFINL Mix", "LIN12 PGA"},
+ {"AINLMUX", "DIFFINL Mix", "LIN34 PGA"},
+ {"AINLMUX", "RXVOICE Mix", "LIN4/RXN"},
+ {"AINLMUX", "RXVOICE Mix", "RIN4/RXP"},
/* ADC */
- {"Left ADC", NULL, "AILNMUX"},
+ {"Left ADC", NULL, "AINLMUX"},
/* RIN12 PGA */
{"RIN12 PGA", "RIN1 Switch", "RIN1"},
{"RIN12 PGA", "RIN2 Switch", "RIN2"},
/* RIN34 PGA */
{"RIN34 PGA", "RIN3 Switch", "RIN3"},
- {"RIN34 PGA", "RIN4 Switch", "RIN4"},
+ {"RIN34 PGA", "RIN4 Switch", "RIN4/RXP"},
/* INMIXL */
{"INMIXR", "Record Right Volume", "ROMIX"},
{"INMIXR", "RIN2 Volume", "RIN2"},
{"INMIXR", "RINPGA12 Switch", "RIN12 PGA"},
{"INMIXR", "RINPGA34 Switch", "RIN34 PGA"},
- /* AIRNMUX */
- {"AIRNMUX", "INMIXR Mix", "INMIXR"},
- {"AIRNMUX", "DIFFINR Mix", "RIN12PGA"},
- {"AIRNMUX", "DIFFINR Mix", "RIN34PGA"},
- {"AIRNMUX", "RXVOICE Mix", "RIN4/RXN"},
- {"AIRNMUX", "RXVOICE Mix", "RIN4/RXP"},
+ /* AINRMUX */
+ {"AINRMUX", "INMIXR Mix", "INMIXR"},
+ {"AINRMUX", "DIFFINR Mix", "RIN12 PGA"},
+ {"AINRMUX", "DIFFINR Mix", "RIN34 PGA"},
+ {"AINRMUX", "RXVOICE Mix", "LIN4/RXN"},
+ {"AINRMUX", "RXVOICE Mix", "RIN4/RXP"},
/* ADC */
- {"Right ADC", NULL, "AIRNMUX"},
+ {"Right ADC", NULL, "AINRMUX"},
/* LOMIX */
{"LOMIX", "LOMIX RIN3 Bypass Switch", "RIN3"},
@@ -922,7 +922,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"LOPMIX", "LOPMIX Left Mixer PGA Switch", "LOPGA"},
/* OUT3MIX */
- {"OUT3MIX", "OUT3MIX LIN4/RXP Bypass Switch", "LIN4/RXP"},
+ {"OUT3MIX", "OUT3MIX LIN4/RXP Bypass Switch", "LIN4/RXN"},
{"OUT3MIX", "OUT3MIX Left Out PGA Switch", "LOPGA"},
/* OUT4MIX */
@@ -949,7 +949,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
/* Output Pins */
{"LON", NULL, "LONMIX"},
{"LOP", NULL, "LOPMIX"},
- {"OUT", NULL, "OUT3MIX"},
+ {"OUT3", NULL, "OUT3MIX"},
{"LOUT", NULL, "LOUT PGA"},
{"SPKN", NULL, "SPKMIX"},
{"ROUT", NULL, "ROUT PGA"},
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index 6e23a81dba78..fa88b463e71f 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -282,14 +282,14 @@ struct snd_soc_dai wm9705_dai[] = {
.channels_min = 1,
.channels_max = 2,
.rates = WM9705_AC97_RATES,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .formats = SND_SOC_STD_AC97_FMTS,
},
.capture = {
.stream_name = "HiFi Capture",
.channels_min = 1,
.channels_max = 2,
.rates = WM9705_AC97_RATES,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .formats = SND_SOC_STD_AC97_FMTS,
},
.ops = &wm9705_dai_ops,
},
@@ -318,7 +318,7 @@ static int wm9705_reset(struct snd_soc_codec *codec)
}
#ifdef CONFIG_PM
-static int wm9705_soc_suspend(struct platform_device *pdev)
+static int wm9705_soc_suspend(struct platform_device *pdev, pm_message_t msg)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = socdev->card->codec;
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 765cf1e7369e..550c903f23bf 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -534,13 +534,13 @@ struct snd_soc_dai wm9712_dai[] = {
.channels_min = 1,
.channels_max = 2,
.rates = WM9712_AC97_RATES,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+ .formats = SND_SOC_STD_AC97_FMTS,},
.capture = {
.stream_name = "HiFi Capture",
.channels_min = 1,
.channels_max = 2,
.rates = WM9712_AC97_RATES,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+ .formats = SND_SOC_STD_AC97_FMTS,},
.ops = &wm9712_dai_ops_hifi,
},
{
@@ -550,7 +550,7 @@ struct snd_soc_dai wm9712_dai[] = {
.channels_min = 1,
.channels_max = 1,
.rates = WM9712_AC97_RATES,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+ .formats = SND_SOC_STD_AC97_FMTS,},
.ops = &wm9712_dai_ops_aux,
}
};
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 523bad077fa0..d1744e96f303 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -189,6 +189,26 @@ SOC_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0),
SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1),
};
+static int wm9713_voice_shutdown(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ u16 status, rate;
+
+ BUG_ON(event != SND_SOC_DAPM_PRE_PMD);
+
+ /* Gracefully shut down the voice interface. */
+ status = ac97_read(codec, AC97_EXTENDED_MID) | 0x1000;
+ rate = ac97_read(codec, AC97_HANDSET_RATE) & 0xF0FF;
+ ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0200);
+ schedule_timeout_interruptible(msecs_to_jiffies(1));
+ ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0F00);
+ ac97_write(codec, AC97_EXTENDED_MID, status);
+
+ return 0;
+}
+
+
/* We have to create a fake left and right HP mixers because
* the codec only has a single control that is shared by both channels.
* This makes it impossible to determine the audio path using the current
@@ -400,7 +420,8 @@ SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("HP Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("Line Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("Capture Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
-SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback", AC97_EXTENDED_MID, 12, 1),
+SND_SOC_DAPM_DAC_E("Voice DAC", "Voice Playback", AC97_EXTENDED_MID, 12, 1,
+ wm9713_voice_shutdown, SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", AC97_EXTENDED_MID, 11, 1),
SND_SOC_DAPM_PGA("Left ADC", AC97_EXTENDED_MID, 5, 1, NULL, 0),
SND_SOC_DAPM_PGA("Right ADC", AC97_EXTENDED_MID, 4, 1, NULL, 0),
@@ -936,21 +957,6 @@ static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static void wm9713_voiceshutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_codec *codec = dai->codec;
- u16 status, rate;
-
- /* Gracefully shut down the voice interface. */
- status = ac97_read(codec, AC97_EXTENDED_STATUS) | 0x1000;
- rate = ac97_read(codec, AC97_HANDSET_RATE) & 0xF0FF;
- ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0200);
- schedule_timeout_interruptible(msecs_to_jiffies(1));
- ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0F00);
- ac97_write(codec, AC97_EXTENDED_MID, status);
-}
-
static int ac97_hifi_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
@@ -1019,7 +1025,6 @@ static struct snd_soc_dai_ops wm9713_dai_ops_aux = {
static struct snd_soc_dai_ops wm9713_dai_ops_voice = {
.hw_params = wm9713_pcm_hw_params,
- .shutdown = wm9713_voiceshutdown,
.set_clkdiv = wm9713_set_dai_clkdiv,
.set_pll = wm9713_set_dai_pll,
.set_fmt = wm9713_set_dai_fmt,
@@ -1035,13 +1040,13 @@ struct snd_soc_dai wm9713_dai[] = {
.channels_min = 1,
.channels_max = 2,
.rates = WM9713_RATES,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+ .formats = SND_SOC_STD_AC97_FMTS,},
.capture = {
.stream_name = "HiFi Capture",
.channels_min = 1,
.channels_max = 2,
.rates = WM9713_RATES,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+ .formats = SND_SOC_STD_AC97_FMTS,},
.ops = &wm9713_dai_ops_hifi,
},
{
@@ -1051,7 +1056,7 @@ struct snd_soc_dai wm9713_dai[] = {
.channels_min = 1,
.channels_max = 1,
.rates = WM9713_RATES,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+ .formats = SND_SOC_STD_AC97_FMTS,},
.ops = &wm9713_dai_ops_aux,
},
{
@@ -1069,6 +1074,7 @@ struct snd_soc_dai wm9713_dai[] = {
.rates = WM9713_PCM_RATES,
.formats = WM9713_PCM_FORMATS,},
.ops = &wm9713_dai_ops_voice,
+ .symmetric_rates = 1,
},
};
EXPORT_SYMBOL_GPL(wm9713_dai);
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c
index 3aa729df27b5..1111c710118a 100644
--- a/sound/soc/fsl/mpc5200_psc_i2s.c
+++ b/sound/soc/fsl/mpc5200_psc_i2s.c
@@ -504,7 +504,8 @@ static struct snd_soc_dai psc_i2s_dai_template = {
static const struct snd_pcm_hardware psc_i2s_pcm_hardware = {
.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER,
+ SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_BATCH,
.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE |
SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE,
.rate_min = 8000,
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index a6d1178ce128..b60b1dfbc435 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2008 Nokia Corporation
*
- * Contact: Jarkko Nikula <jarkko.nikula@nokia.com>
+ * Contact: Jarkko Nikula <jhnikula@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -383,10 +383,9 @@ static int __init n810_soc_init(void)
clk_set_parent(sys_clkout2_src, func96m_clk);
clk_set_rate(sys_clkout2, 12000000);
- if (gpio_request(N810_HEADSET_AMP_GPIO, "hs_amp") < 0)
- BUG();
- if (gpio_request(N810_SPEAKER_AMP_GPIO, "spk_amp") < 0)
- BUG();
+ BUG_ON((gpio_request(N810_HEADSET_AMP_GPIO, "hs_amp") < 0) ||
+ (gpio_request(N810_SPEAKER_AMP_GPIO, "spk_amp") < 0));
+
gpio_direction_output(N810_HEADSET_AMP_GPIO, 0);
gpio_direction_output(N810_SPEAKER_AMP_GPIO, 0);
@@ -417,6 +416,6 @@ static void __exit n810_soc_exit(void)
module_init(n810_soc_init);
module_exit(n810_soc_exit);
-MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>");
+MODULE_AUTHOR("Jarkko Nikula <jhnikula@gmail.com>");
MODULE_DESCRIPTION("ALSA SoC Nokia N810");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 9c09b94f0cf8..a5d46a7b196a 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -3,7 +3,8 @@
*
* Copyright (C) 2008 Nokia Corporation
*
- * Contact: Jarkko Nikula <jarkko.nikula@nokia.com>
+ * Contact: Jarkko Nikula <jhnikula@gmail.com>
+ * Peter Ujfalusi <peter.ujfalusi@nokia.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -214,8 +215,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
- int wlen, channels;
+ int wlen, channels, wpf;
unsigned long port;
+ unsigned int format;
if (cpu_class_is_omap1()) {
dma = omap1_dma_reqs[bus_id][substream->stream];
@@ -243,18 +245,24 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
return 0;
}
- channels = params_channels(params);
+ format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+ wpf = channels = params_channels(params);
switch (channels) {
case 2:
- /* Use dual-phase frames */
- regs->rcr2 |= RPHASE;
- regs->xcr2 |= XPHASE;
+ if (format == SND_SOC_DAIFMT_I2S) {
+ /* Use dual-phase frames */
+ regs->rcr2 |= RPHASE;
+ regs->xcr2 |= XPHASE;
+ /* Set 1 word per (McBSP) frame for phase1 and phase2 */
+ wpf--;
+ regs->rcr2 |= RFRLEN2(wpf - 1);
+ regs->xcr2 |= XFRLEN2(wpf - 1);
+ }
case 1:
- /* Set 1 word per (McBSP) frame */
- regs->rcr2 |= RFRLEN2(1 - 1);
- regs->rcr1 |= RFRLEN1(1 - 1);
- regs->xcr2 |= XFRLEN2(1 - 1);
- regs->xcr1 |= XFRLEN1(1 - 1);
+ case 4:
+ /* Set word per (McBSP) frame for phase1 */
+ regs->rcr1 |= RFRLEN1(wpf - 1);
+ regs->xcr1 |= XFRLEN1(wpf - 1);
break;
default:
/* Unsupported number of channels */
@@ -276,14 +284,15 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
}
/* Set FS period and length in terms of bit clock periods */
- switch (mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ switch (format) {
case SND_SOC_DAIFMT_I2S:
- regs->srgr2 |= FPER(wlen * 2 - 1);
+ regs->srgr2 |= FPER(wlen * channels - 1);
regs->srgr1 |= FWID(wlen - 1);
break;
+ case SND_SOC_DAIFMT_DSP_A:
case SND_SOC_DAIFMT_DSP_B:
regs->srgr2 |= FPER(wlen * channels - 1);
- regs->srgr1 |= FWID(wlen * channels - 2);
+ regs->srgr1 |= FWID(0);
break;
}
@@ -302,6 +311,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
{
struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
+ unsigned int temp_fmt = fmt;
if (mcbsp_data->configured)
return 0;
@@ -324,10 +334,19 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
regs->rcr2 |= RDATDLY(1);
regs->xcr2 |= XDATDLY(1);
break;
+ case SND_SOC_DAIFMT_DSP_A:
+ /* 1-bit data delay */
+ regs->rcr2 |= RDATDLY(1);
+ regs->xcr2 |= XDATDLY(1);
+ /* Invert FS polarity configuration */
+ temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
+ break;
case SND_SOC_DAIFMT_DSP_B:
/* 0-bit data delay */
regs->rcr2 |= RDATDLY(0);
regs->xcr2 |= XDATDLY(0);
+ /* Invert FS polarity configuration */
+ temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
break;
default:
/* Unsupported data format */
@@ -351,7 +370,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
}
/* Set bit clock (CLKX/CLKR) and FS polarities */
- switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ switch (temp_fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
/*
* Normal BCLK + FS.
@@ -488,13 +507,13 @@ static struct snd_soc_dai_ops omap_mcbsp_dai_ops = {
.id = (link_id), \
.playback = { \
.channels_min = 1, \
- .channels_max = 2, \
+ .channels_max = 4, \
.rates = OMAP_MCBSP_RATES, \
.formats = SNDRV_PCM_FMTBIT_S16_LE, \
}, \
.capture = { \
.channels_min = 1, \
- .channels_max = 2, \
+ .channels_max = 4, \
.rates = OMAP_MCBSP_RATES, \
.formats = SNDRV_PCM_FMTBIT_S16_LE, \
}, \
@@ -529,6 +548,6 @@ static void __exit snd_omap_mcbsp_exit(void)
}
module_exit(snd_omap_mcbsp_exit);
-MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>");
+MODULE_AUTHOR("Jarkko Nikula <jhnikula@gmail.com>");
MODULE_DESCRIPTION("OMAP I2S SoC Interface");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h
index df7ad13ba73d..c8147aace813 100644
--- a/sound/soc/omap/omap-mcbsp.h
+++ b/sound/soc/omap/omap-mcbsp.h
@@ -3,7 +3,8 @@
*
* Copyright (C) 2008 Nokia Corporation
*
- * Contact: Jarkko Nikula <jarkko.nikula@nokia.com>
+ * Contact: Jarkko Nikula <jhnikula@gmail.com>
+ * Peter Ujfalusi <peter.ujfalusi@nokia.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 1bdbb0427183..6454e15f7d28 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -3,7 +3,8 @@
*
* Copyright (C) 2008 Nokia Corporation
*
- * Contact: Jarkko Nikula <jarkko.nikula@nokia.com>
+ * Contact: Jarkko Nikula <jhnikula@gmail.com>
+ * Peter Ujfalusi <peter.ujfalusi@nokia.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -86,8 +87,10 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
struct omap_pcm_dma_data *dma_data = rtd->dai->cpu_dai->dma_data;
int err = 0;
+ /* return if this is a bufferless transfer e.g.
+ * codec <--> BT codec or GSM modem -- lg FIXME */
if (!dma_data)
- return -ENODEV;
+ return 0;
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
runtime->dma_bytes = params_buffer_bytes(params);
@@ -133,6 +136,11 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
struct omap_pcm_dma_data *dma_data = prtd->dma_data;
struct omap_dma_channel_params dma_params;
+ /* return if this is a bufferless transfer e.g.
+ * codec <--> BT codec or GSM modem -- lg FIXME */
+ if (!prtd->dma_data)
+ return 0;
+
memset(&dma_params, 0, sizeof(dma_params));
/*
* Note: Regardless of interface data formats supported by OMAP McBSP
@@ -367,6 +375,6 @@ static void __exit omap_soc_platform_exit(void)
}
module_exit(omap_soc_platform_exit);
-MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>");
+MODULE_AUTHOR("Jarkko Nikula <jhnikula@gmail.com>");
MODULE_DESCRIPTION("OMAP PCM DMA module");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h
index e4369bdfd77d..8d9d26916b05 100644
--- a/sound/soc/omap/omap-pcm.h
+++ b/sound/soc/omap/omap-pcm.h
@@ -3,7 +3,8 @@
*
* Copyright (C) 2008 Nokia Corporation
*
- * Contact: Jarkko Nikula <jarkko.nikula@nokia.com>
+ * Contact: Jarkko Nikula <jhnikula@gmail.com>
+ * Peter Ujfalusi <peter.ujfalusi@nokia.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/sound/soc/omap/omap2evm.c b/sound/soc/omap/omap2evm.c
index 0c2322dcf02a..027e1a40f8a1 100644
--- a/sound/soc/omap/omap2evm.c
+++ b/sound/soc/omap/omap2evm.c
@@ -86,7 +86,7 @@ static struct snd_soc_dai_link omap2evm_dai = {
.name = "TWL4030",
.stream_name = "TWL4030",
.cpu_dai = &omap_mcbsp_dai[0],
- .codec_dai = &twl4030_dai,
+ .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
.ops = &omap2evm_ops,
};
diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c
index fd24a4acd2f5..b0cff9f33b7e 100644
--- a/sound/soc/omap/omap3beagle.c
+++ b/sound/soc/omap/omap3beagle.c
@@ -41,23 +41,33 @@ static int omap3beagle_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ unsigned int fmt;
int ret;
+ switch (params_channels(params)) {
+ case 2: /* Stereo I2S mode */
+ fmt = SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM;
+ break;
+ case 4: /* Four channel TDM mode */
+ fmt = SND_SOC_DAIFMT_DSP_A |
+ SND_SOC_DAIFMT_IB_NF |
+ SND_SOC_DAIFMT_CBM_CFM;
+ break;
+ default:
+ return -EINVAL;
+ }
+
/* Set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
+ ret = snd_soc_dai_set_fmt(codec_dai, fmt);
if (ret < 0) {
printk(KERN_ERR "can't set codec DAI configuration\n");
return ret;
}
/* Set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
+ ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
if (ret < 0) {
printk(KERN_ERR "can't set cpu DAI configuration\n");
return ret;
@@ -83,7 +93,7 @@ static struct snd_soc_dai_link omap3beagle_dai = {
.name = "TWL4030",
.stream_name = "TWL4030",
.cpu_dai = &omap_mcbsp_dai[0],
- .codec_dai = &twl4030_dai,
+ .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
.ops = &omap3beagle_ops,
};
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c
index fe282d4ef422..ad219aaf7cb8 100644
--- a/sound/soc/omap/omap3pandora.c
+++ b/sound/soc/omap/omap3pandora.c
@@ -228,14 +228,14 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
.name = "PCM1773",
.stream_name = "HiFi Out",
.cpu_dai = &omap_mcbsp_dai[0],
- .codec_dai = &twl4030_dai,
+ .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
.ops = &omap3pandora_out_ops,
.init = omap3pandora_out_init,
}, {
.name = "TWL4030",
.stream_name = "Line/Mic In",
.cpu_dai = &omap_mcbsp_dai[1],
- .codec_dai = &twl4030_dai,
+ .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
.ops = &omap3pandora_in_ops,
.init = omap3pandora_in_init,
}
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c
index a952a4eb3361..a4e149b7f0eb 100644
--- a/sound/soc/omap/osk5912.c
+++ b/sound/soc/omap/osk5912.c
@@ -62,7 +62,7 @@ static int osk_hw_params(struct snd_pcm_substream *substream,
/* Set codec DAI configuration */
err = snd_soc_dai_set_fmt(codec_dai,
SND_SOC_DAIFMT_DSP_B |
- SND_SOC_DAIFMT_NB_IF |
+ SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM);
if (err < 0) {
printk(KERN_ERR "can't set codec DAI configuration\n");
@@ -72,7 +72,7 @@ static int osk_hw_params(struct snd_pcm_substream *substream,
/* Set cpu DAI configuration */
err = snd_soc_dai_set_fmt(cpu_dai,
SND_SOC_DAIFMT_DSP_B |
- SND_SOC_DAIFMT_NB_IF |
+ SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM);
if (err < 0) {
printk(KERN_ERR "can't set cpu DAI configuration\n");
diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c
index a72dc4e159e5..ec4f8fd8b3a2 100644
--- a/sound/soc/omap/overo.c
+++ b/sound/soc/omap/overo.c
@@ -83,7 +83,7 @@ static struct snd_soc_dai_link overo_dai = {
.name = "TWL4030",
.stream_name = "TWL4030",
.cpu_dai = &omap_mcbsp_dai[0],
- .codec_dai = &twl4030_dai,
+ .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
.ops = &overo_ops,
};
diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c
index 10f1c867f11d..1c7974101a0b 100644
--- a/sound/soc/omap/sdp3430.c
+++ b/sound/soc/omap/sdp3430.c
@@ -197,7 +197,7 @@ static struct snd_soc_dai_link sdp3430_dai = {
.name = "TWL4030",
.stream_name = "TWL4030",
.cpu_dai = &omap_mcbsp_dai[0],
- .codec_dai = &twl4030_dai,
+ .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
.init = sdp3430_twl4030_init,
.ops = &sdp3430_ops,
};
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index ad8a10fe6298..19a6a6797dd5 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -98,13 +98,14 @@ config SND_PXA2XX_SOC_EM_X270
CompuLab EM-x270.
config SND_PXA2XX_SOC_PALM27X
- bool "SoC Audio support for Palm T|X, T5 and LifeDrive"
- depends on SND_PXA2XX_SOC && (MACH_PALMLD || MACH_PALMTX || MACH_PALMT5)
+ bool "SoC Audio support for Palm T|X, T5, E2 and LifeDrive"
+ depends on SND_PXA2XX_SOC && (MACH_PALMLD || MACH_PALMTX || \
+ MACH_PALMT5 || MACH_PALMTE2)
select SND_PXA2XX_SOC_AC97
select SND_SOC_WM9712
help
Say Y if you want to add support for SoC audio on
- Palm T|X, T5 or LifeDrive handheld computer.
+ Palm T|X, T5, E2 or LifeDrive handheld computer.
config SND_SOC_ZYLONITE
tristate "SoC Audio support for Marvell Zylonite"
@@ -134,3 +135,12 @@ config SND_PXA2XX_SOC_MIOA701
help
Say Y if you want to add support for SoC audio on the
MIO A701.
+
+config SND_PXA2XX_SOC_IMOTE2
+ tristate "SoC Audio support for IMote 2"
+ depends on SND_PXA2XX_SOC && MACH_INTELMOTE2
+ select SND_PXA2XX_SOC_I2S
+ select SND_SOC_WM8940
+ help
+ Say Y if you want to add support for SoC audio on the
+ IMote 2.
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index 4b90c3ccae45..6e096b480335 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
@@ -22,6 +22,7 @@ snd-soc-palm27x-objs := palm27x.o
snd-soc-zylonite-objs := zylonite.o
snd-soc-magician-objs := magician.o
snd-soc-mioa701-objs := mioa701_wm9713.o
+snd-soc-imote2-objs := imote2.o
obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o
obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o
@@ -35,3 +36,4 @@ obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o
obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o
obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o
obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o
+obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o
diff --git a/sound/soc/pxa/imote2.c b/sound/soc/pxa/imote2.c
new file mode 100644
index 000000000000..405587a01160
--- /dev/null
+++ b/sound/soc/pxa/imote2.c
@@ -0,0 +1,114 @@
+
+#include <linux/module.h>
+#include <sound/soc.h>
+
+#include <asm/mach-types.h>
+
+#include "../codecs/wm8940.h"
+#include "pxa2xx-i2s.h"
+#include "pxa2xx-pcm.h"
+
+static int imote2_asoc_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_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ unsigned int clk = 0;
+ int ret;
+
+ switch (params_rate(params)) {
+ case 8000:
+ case 16000:
+ case 48000:
+ case 96000:
+ clk = 12288000;
+ break;
+ case 11025:
+ case 22050:
+ case 44100:
+ clk = 11289600;
+ break;
+ }
+
+ /* set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
+ | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ /* CPU should be clock master */
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
+ | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0)
+ return ret;
+
+ /* set the I2S system clock as input (unused) */
+ ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, clk,
+ SND_SOC_CLOCK_OUT);
+
+ return ret;
+}
+
+static struct snd_soc_ops imote2_asoc_ops = {
+ .hw_params = imote2_asoc_hw_params,
+};
+
+static struct snd_soc_dai_link imote2_dai = {
+ .name = "WM8940",
+ .stream_name = "WM8940",
+ .cpu_dai = &pxa_i2s_dai,
+ .codec_dai = &wm8940_dai,
+ .ops = &imote2_asoc_ops,
+};
+
+static struct snd_soc_card snd_soc_imote2 = {
+ .name = "Imote2",
+ .platform = &pxa2xx_soc_platform,
+ .dai_link = &imote2_dai,
+ .num_links = 1,
+};
+
+static struct snd_soc_device imote2_snd_devdata = {
+ .card = &snd_soc_imote2,
+ .codec_dev = &soc_codec_dev_wm8940,
+};
+
+static struct platform_device *imote2_snd_device;
+
+static int __init imote2_asoc_init(void)
+{
+ int ret;
+
+ if (!machine_is_intelmote2())
+ return -ENODEV;
+ imote2_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!imote2_snd_device)
+ return -ENOMEM;
+
+ platform_set_drvdata(imote2_snd_device, &imote2_snd_devdata);
+ imote2_snd_devdata.dev = &imote2_snd_device->dev;
+ ret = platform_device_add(imote2_snd_device);
+ if (ret)
+ platform_device_put(imote2_snd_device);
+
+ return ret;
+}
+module_init(imote2_asoc_init);
+
+static void __exit imote2_asoc_exit(void)
+{
+ platform_device_unregister(imote2_snd_device);
+}
+module_exit(imote2_asoc_exit);
+
+MODULE_AUTHOR("Jonathan Cameron");
+MODULE_DESCRIPTION("ALSA SoC Imote 2");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c
index f7c4544f7859..0625c342a1c9 100644
--- a/sound/soc/pxa/magician.c
+++ b/sound/soc/pxa/magician.c
@@ -27,8 +27,6 @@
#include <sound/soc.h>
#include <sound/soc-dapm.h>
-#include <mach/pxa-regs.h>
-#include <mach/hardware.h>
#include <mach/magician.h>
#include <asm/mach-types.h>
#include "../codecs/uda1380.h"
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c
index 48a73f64500b..e6102fda0a7f 100644
--- a/sound/soc/pxa/palm27x.c
+++ b/sound/soc/pxa/palm27x.c
@@ -200,14 +200,18 @@ static struct snd_soc_device palm27x_snd_devdata = {
static struct platform_device *palm27x_snd_device;
-static int __init palm27x_asoc_init(void)
+static int palm27x_asoc_probe(struct platform_device *pdev)
{
int ret;
if (!(machine_is_palmtx() || machine_is_palmt5() ||
- machine_is_palmld()))
+ machine_is_palmld() || machine_is_palmte2()))
return -ENODEV;
+ if (pdev->dev.platform_data)
+ palm27x_ep_gpio = ((struct palm27x_asoc_info *)
+ (pdev->dev.platform_data))->jack_gpio;
+
ret = gpio_request(palm27x_ep_gpio, "Headphone Jack");
if (ret)
return ret;
@@ -245,16 +249,31 @@ err_alloc:
return ret;
}
-static void __exit palm27x_asoc_exit(void)
+static int __devexit palm27x_asoc_remove(struct platform_device *pdev)
{
free_irq(gpio_to_irq(palm27x_ep_gpio), NULL);
gpio_free(palm27x_ep_gpio);
platform_device_unregister(palm27x_snd_device);
+ return 0;
}
-void __init palm27x_asoc_set_pdata(struct palm27x_asoc_info *data)
+static struct platform_driver palm27x_wm9712_driver = {
+ .probe = palm27x_asoc_probe,
+ .remove = __devexit_p(palm27x_asoc_remove),
+ .driver = {
+ .name = "palm27x-asoc",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init palm27x_asoc_init(void)
+{
+ return platform_driver_register(&palm27x_wm9712_driver);
+}
+
+static void __exit palm27x_asoc_exit(void)
{
- palm27x_ep_gpio = data->jack_gpio;
+ platform_driver_unregister(&palm27x_wm9712_driver);
}
module_init(palm27x_asoc_init);
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 308a657928d2..6fc787610ad7 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -50,139 +50,6 @@ struct ssp_priv {
#endif
};
-#define PXA2xx_SSP1_BASE 0x41000000
-#define PXA27x_SSP2_BASE 0x41700000
-#define PXA27x_SSP3_BASE 0x41900000
-#define PXA3xx_SSP4_BASE 0x41a00000
-
-static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_mono_out = {
- .name = "SSP1 PCM Mono out",
- .dev_addr = PXA2xx_SSP1_BASE + SSDR,
- .drcmr = &DRCMR(14),
- .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
- DCMD_BURST16 | DCMD_WIDTH2,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_mono_in = {
- .name = "SSP1 PCM Mono in",
- .dev_addr = PXA2xx_SSP1_BASE + SSDR,
- .drcmr = &DRCMR(13),
- .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
- DCMD_BURST16 | DCMD_WIDTH2,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_stereo_out = {
- .name = "SSP1 PCM Stereo out",
- .dev_addr = PXA2xx_SSP1_BASE + SSDR,
- .drcmr = &DRCMR(14),
- .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
- DCMD_BURST16 | DCMD_WIDTH4,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_stereo_in = {
- .name = "SSP1 PCM Stereo in",
- .dev_addr = PXA2xx_SSP1_BASE + SSDR,
- .drcmr = &DRCMR(13),
- .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
- DCMD_BURST16 | DCMD_WIDTH4,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_mono_out = {
- .name = "SSP2 PCM Mono out",
- .dev_addr = PXA27x_SSP2_BASE + SSDR,
- .drcmr = &DRCMR(16),
- .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
- DCMD_BURST16 | DCMD_WIDTH2,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_mono_in = {
- .name = "SSP2 PCM Mono in",
- .dev_addr = PXA27x_SSP2_BASE + SSDR,
- .drcmr = &DRCMR(15),
- .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
- DCMD_BURST16 | DCMD_WIDTH2,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_stereo_out = {
- .name = "SSP2 PCM Stereo out",
- .dev_addr = PXA27x_SSP2_BASE + SSDR,
- .drcmr = &DRCMR(16),
- .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
- DCMD_BURST16 | DCMD_WIDTH4,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_stereo_in = {
- .name = "SSP2 PCM Stereo in",
- .dev_addr = PXA27x_SSP2_BASE + SSDR,
- .drcmr = &DRCMR(15),
- .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
- DCMD_BURST16 | DCMD_WIDTH4,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_mono_out = {
- .name = "SSP3 PCM Mono out",
- .dev_addr = PXA27x_SSP3_BASE + SSDR,
- .drcmr = &DRCMR(67),
- .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
- DCMD_BURST16 | DCMD_WIDTH2,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_mono_in = {
- .name = "SSP3 PCM Mono in",
- .dev_addr = PXA27x_SSP3_BASE + SSDR,
- .drcmr = &DRCMR(66),
- .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
- DCMD_BURST16 | DCMD_WIDTH2,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_stereo_out = {
- .name = "SSP3 PCM Stereo out",
- .dev_addr = PXA27x_SSP3_BASE + SSDR,
- .drcmr = &DRCMR(67),
- .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
- DCMD_BURST16 | DCMD_WIDTH4,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_stereo_in = {
- .name = "SSP3 PCM Stereo in",
- .dev_addr = PXA27x_SSP3_BASE + SSDR,
- .drcmr = &DRCMR(66),
- .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
- DCMD_BURST16 | DCMD_WIDTH4,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_mono_out = {
- .name = "SSP4 PCM Mono out",
- .dev_addr = PXA3xx_SSP4_BASE + SSDR,
- .drcmr = &DRCMR(67),
- .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
- DCMD_BURST16 | DCMD_WIDTH2,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_mono_in = {
- .name = "SSP4 PCM Mono in",
- .dev_addr = PXA3xx_SSP4_BASE + SSDR,
- .drcmr = &DRCMR(66),
- .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
- DCMD_BURST16 | DCMD_WIDTH2,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_stereo_out = {
- .name = "SSP4 PCM Stereo out",
- .dev_addr = PXA3xx_SSP4_BASE + SSDR,
- .drcmr = &DRCMR(67),
- .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
- DCMD_BURST16 | DCMD_WIDTH4,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_stereo_in = {
- .name = "SSP4 PCM Stereo in",
- .dev_addr = PXA3xx_SSP4_BASE + SSDR,
- .drcmr = &DRCMR(66),
- .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
- DCMD_BURST16 | DCMD_WIDTH4,
-};
-
static void dump_registers(struct ssp_device *ssp)
{
dev_dbg(&ssp->pdev->dev, "SSCR0 0x%08x SSCR1 0x%08x SSTO 0x%08x\n",
@@ -194,25 +61,33 @@ static void dump_registers(struct ssp_device *ssp)
ssp_read_reg(ssp, SSACD));
}
-static struct pxa2xx_pcm_dma_params *ssp_dma_params[4][4] = {
- {
- &pxa_ssp1_pcm_mono_out, &pxa_ssp1_pcm_mono_in,
- &pxa_ssp1_pcm_stereo_out, &pxa_ssp1_pcm_stereo_in,
- },
- {
- &pxa_ssp2_pcm_mono_out, &pxa_ssp2_pcm_mono_in,
- &pxa_ssp2_pcm_stereo_out, &pxa_ssp2_pcm_stereo_in,
- },
- {
- &pxa_ssp3_pcm_mono_out, &pxa_ssp3_pcm_mono_in,
- &pxa_ssp3_pcm_stereo_out, &pxa_ssp3_pcm_stereo_in,
- },
- {
- &pxa_ssp4_pcm_mono_out, &pxa_ssp4_pcm_mono_in,
- &pxa_ssp4_pcm_stereo_out, &pxa_ssp4_pcm_stereo_in,
- },
+struct pxa2xx_pcm_dma_data {
+ struct pxa2xx_pcm_dma_params params;
+ char name[20];
};
+static struct pxa2xx_pcm_dma_params *
+ssp_get_dma_params(struct ssp_device *ssp, int width4, int out)
+{
+ struct pxa2xx_pcm_dma_data *dma;
+
+ dma = kzalloc(sizeof(struct pxa2xx_pcm_dma_data), GFP_KERNEL);
+ if (dma == NULL)
+ return NULL;
+
+ snprintf(dma->name, 20, "SSP%d PCM %s %s", ssp->port_id,
+ width4 ? "32-bit" : "16-bit", out ? "out" : "in");
+
+ dma->params.name = dma->name;
+ dma->params.drcmr = &DRCMR(out ? ssp->drcmr_tx : ssp->drcmr_rx);
+ dma->params.dcmd = (out ? (DCMD_INCSRCADDR | DCMD_FLOWTRG) :
+ (DCMD_INCTRGADDR | DCMD_FLOWSRC)) |
+ (width4 ? DCMD_WIDTH4 : DCMD_WIDTH2) | DCMD_BURST16;
+ dma->params.dev_addr = ssp->phys_base + SSDR;
+
+ return &dma->params;
+}
+
static int pxa_ssp_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
@@ -227,6 +102,11 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream,
clk_enable(priv->dev.ssp->clk);
ssp_disable(&priv->dev);
}
+
+ if (cpu_dai->dma_data) {
+ kfree(cpu_dai->dma_data);
+ cpu_dai->dma_data = NULL;
+ }
return ret;
}
@@ -241,6 +121,11 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
ssp_disable(&priv->dev);
clk_disable(priv->dev.ssp->clk);
}
+
+ if (cpu_dai->dma_data) {
+ kfree(cpu_dai->dma_data);
+ cpu_dai->dma_data = NULL;
+ }
}
#ifdef CONFIG_PM
@@ -280,12 +165,33 @@ static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai)
* ssp_set_clkdiv - set SSP clock divider
* @div: serial clock rate divider
*/
-static void ssp_set_scr(struct ssp_dev *dev, u32 div)
+static void ssp_set_scr(struct ssp_device *ssp, u32 div)
+{
+ u32 sscr0 = ssp_read_reg(ssp, SSCR0);
+
+ if (cpu_is_pxa25x() && ssp->type == PXA25x_SSP) {
+ sscr0 &= ~0x0000ff00;
+ sscr0 |= ((div - 2)/2) << 8; /* 2..512 */
+ } else {
+ sscr0 &= ~0x000fff00;
+ sscr0 |= (div - 1) << 8; /* 1..4096 */
+ }
+ ssp_write_reg(ssp, SSCR0, sscr0);
+}
+
+/**
+ * ssp_get_clkdiv - get SSP clock divider
+ */
+static u32 ssp_get_scr(struct ssp_device *ssp)
{
- struct ssp_device *ssp = dev->ssp;
- u32 sscr0 = ssp_read_reg(dev->ssp, SSCR0) & ~SSCR0_SCR;
+ u32 sscr0 = ssp_read_reg(ssp, SSCR0);
+ u32 div;
- ssp_write_reg(ssp, SSCR0, (sscr0 | SSCR0_SerClkDiv(div)));
+ if (cpu_is_pxa25x() && ssp->type == PXA25x_SSP)
+ div = ((sscr0 >> 8) & 0xff) * 2 + 2;
+ else
+ div = ((sscr0 >> 8) & 0xfff) + 1;
+ return div;
}
/*
@@ -326,7 +232,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
break;
case PXA_SSP_CLK_AUDIO:
priv->sysclk = 0;
- ssp_set_scr(&priv->dev, 1);
+ ssp_set_scr(ssp, 1);
sscr0 |= SSCR0_ACS;
break;
default:
@@ -387,7 +293,7 @@ static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
ssp_write_reg(ssp, SSACD, val);
break;
case PXA_SSP_DIV_SCR:
- ssp_set_scr(&priv->dev, div);
+ ssp_set_scr(ssp, div);
break;
default:
return -ENODEV;
@@ -568,7 +474,10 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
case SND_SOC_DAIFMT_NB_IF:
break;
case SND_SOC_DAIFMT_IB_IF:
- sspsp |= SSPSP_SCMODE(3);
+ sspsp |= SSPSP_SCMODE(2);
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP;
break;
default:
return -EINVAL;
@@ -585,7 +494,13 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
case SND_SOC_DAIFMT_NB_NF:
sspsp |= SSPSP_SFRMP;
break;
+ case SND_SOC_DAIFMT_NB_IF:
+ break;
case SND_SOC_DAIFMT_IB_IF:
+ sspsp |= SSPSP_SCMODE(2);
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP;
break;
default:
return -EINVAL;
@@ -623,25 +538,23 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
struct ssp_priv *priv = cpu_dai->private_data;
struct ssp_device *ssp = priv->dev.ssp;
- int dma = 0, chn = params_channels(params);
+ int chn = params_channels(params);
u32 sscr0;
u32 sspsp;
int width = snd_pcm_format_physical_width(params_format(params));
int ttsa = ssp_read_reg(ssp, SSTSA) & 0xf;
- /* select correct DMA params */
- if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
- dma = 1; /* capture DMA offset is 1,3 */
+ /* generate correct DMA params */
+ if (cpu_dai->dma_data)
+ kfree(cpu_dai->dma_data);
+
/* Network mode with one active slot (ttsa == 1) can be used
* to force 16-bit frame width on the wire (for S16_LE), even
* with two channels. Use 16-bit DMA transfers for this case.
*/
- if (((chn == 2) && (ttsa != 1)) || (width == 32))
- dma += 2; /* 32-bit DMA offset is 2, 16-bit is 0 */
-
- cpu_dai->dma_data = ssp_dma_params[cpu_dai->id][dma];
-
- dev_dbg(&ssp->pdev->dev, "pxa_ssp_hw_params: dma %d\n", dma);
+ cpu_dai->dma_data = ssp_get_dma_params(ssp,
+ ((chn == 2) && (ttsa != 1)) || (width == 32),
+ substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
/* we can only change the settings if the port is not in use */
if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE)
@@ -674,8 +587,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
case SND_SOC_DAIFMT_I2S:
sspsp = ssp_read_reg(ssp, SSPSP);
- if (((sscr0 & SSCR0_SCR) == SSCR0_SerClkDiv(4)) &&
- (width == 16)) {
+ if ((ssp_get_scr(ssp) == 4) && (width == 16)) {
/* This is a special case where the bitclk is 64fs
* and we're not dealing with 2*32 bits of audio
* samples.
@@ -806,6 +718,7 @@ static int pxa_ssp_probe(struct platform_device *pdev,
goto err_priv;
}
+ priv->dai_fmt = (unsigned int) -1;
dai->private_data = priv;
return 0;
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig
index 2f3a21eee051..df494d1e346f 100644
--- a/sound/soc/s3c24xx/Kconfig
+++ b/sound/soc/s3c24xx/Kconfig
@@ -1,10 +1,10 @@
config SND_S3C24XX_SOC
tristate "SoC Audio for the Samsung S3CXXXX chips"
- depends on ARCH_S3C2410 || ARCH_S3C64XX
+ depends on ARCH_S3C2410
help
Say Y or M if you want to add support for codecs attached to
- the S3C24XX and S3C64XX AC97, I2S or SSP interface. You will
- also need to select the audio interfaces to support below.
+ the S3C24XX AC97 or I2S interfaces. You will also need to
+ select the audio interfaces to support below.
config SND_S3C24XX_SOC_I2S
tristate
diff --git a/sound/soc/s3c24xx/jive_wm8750.c b/sound/soc/s3c24xx/jive_wm8750.c
index 32063790d95b..93e6c87b7399 100644
--- a/sound/soc/s3c24xx/jive_wm8750.c
+++ b/sound/soc/s3c24xx/jive_wm8750.c
@@ -69,8 +69,8 @@ static int jive_hw_params(struct snd_pcm_substream *substream,
break;
}
- s3c_i2sv2_calc_rate(&div, NULL, params_rate(params),
- s3c2412_get_iisclk());
+ s3c_i2sv2_iis_calc_rate(&div, NULL, params_rate(params),
+ s3c2412_get_iisclk());
/* set codec DAI configuration */
ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
@@ -145,8 +145,9 @@ static struct snd_soc_dai_link jive_dai = {
};
/* jive audio machine driver */
-static struct snd_soc_machine snd_soc_machine_jive = {
+static struct snd_soc_card snd_soc_machine_jive = {
.name = "Jive",
+ .platform = &s3c24xx_soc_platform,
.dai_link = &jive_dai,
.num_links = 1,
};
@@ -157,9 +158,8 @@ static struct wm8750_setup_data jive_wm8750_setup = {
/* jive audio subsystem */
static struct snd_soc_device jive_snd_devdata = {
- .machine = &snd_soc_machine_jive,
- .platform = &s3c24xx_soc_platform,
- .codec_dev = &soc_codec_dev_wm8750_spi,
+ .card = &snd_soc_machine_jive,
+ .codec_dev = &soc_codec_dev_wm8750,
.codec_data = &jive_wm8750_setup,
};
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c
index 295a4c910262..972c27684198 100644
--- a/sound/soc/s3c24xx/s3c-i2s-v2.c
+++ b/sound/soc/s3c24xx/s3c-i2s-v2.c
@@ -37,6 +37,20 @@
#include "s3c-i2s-v2.h"
+#undef S3C_IIS_V2_SUPPORTED
+
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+#define S3C_IIS_V2_SUPPORTED
+#endif
+
+#ifdef CONFIG_PLAT_S3C64XX
+#define S3C_IIS_V2_SUPPORTED
+#endif
+
+#ifndef S3C_IIS_V2_SUPPORTED
+#error Unsupported CPU model
+#endif
+
#define S3C2412_I2S_DEBUG_CON 0
static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
@@ -75,7 +89,7 @@ static inline void dbg_showcon(const char *fn, u32 con)
/* Turn on or off the transmission path. */
-void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
+static void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
{
void __iomem *regs = i2s->regs;
u32 fic, con, mod;
@@ -105,7 +119,9 @@ void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
break;
default:
- dev_err(i2s->dev, "TXEN: Invalid MODE in IISMOD\n");
+ dev_err(i2s->dev, "TXEN: Invalid MODE %x in IISMOD\n",
+ mod & S3C2412_IISMOD_MODE_MASK);
+ break;
}
writel(con, regs + S3C2412_IISCON);
@@ -132,7 +148,9 @@ void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
break;
default:
- dev_err(i2s->dev, "TXDIS: Invalid MODE in IISMOD\n");
+ dev_err(i2s->dev, "TXDIS: Invalid MODE %x in IISMOD\n",
+ mod & S3C2412_IISMOD_MODE_MASK);
+ break;
}
writel(mod, regs + S3C2412_IISMOD);
@@ -143,9 +161,8 @@ void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
dbg_showcon(__func__, con);
pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
}
-EXPORT_SYMBOL_GPL(s3c2412_snd_txctrl);
-void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
+static void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
{
void __iomem *regs = i2s->regs;
u32 fic, con, mod;
@@ -175,7 +192,8 @@ void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
break;
default:
- dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n");
+ dev_err(i2s->dev, "RXEN: Invalid MODE %x in IISMOD\n",
+ mod & S3C2412_IISMOD_MODE_MASK);
}
writel(mod, regs + S3C2412_IISMOD);
@@ -199,7 +217,8 @@ void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
break;
default:
- dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n");
+ dev_err(i2s->dev, "RXDIS: Invalid MODE %x in IISMOD\n",
+ mod & S3C2412_IISMOD_MODE_MASK);
}
writel(con, regs + S3C2412_IISCON);
@@ -209,7 +228,6 @@ void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
fic = readl(regs + S3C2412_IISFIC);
pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
}
-EXPORT_SYMBOL_GPL(s3c2412_snd_rxctrl);
/*
* Wait for the LR signal to allow synchronisation to the L/R clock
@@ -266,7 +284,7 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
*/
#define IISMOD_MASTER_MASK (1 << 11)
#define IISMOD_SLAVE (1 << 11)
-#define IISMOD_MASTER (0x0)
+#define IISMOD_MASTER (0 << 11)
#endif
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -281,7 +299,7 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
iismod |= IISMOD_MASTER;
break;
default:
- pr_debug("unknwon master/slave format\n");
+ pr_err("unknwon master/slave format\n");
return -EINVAL;
}
@@ -298,7 +316,7 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
iismod |= S3C2412_IISMOD_SDF_IIS;
break;
default:
- pr_debug("Unknown data format\n");
+ pr_err("Unknown data format\n");
return -EINVAL;
}
@@ -327,6 +345,7 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
iismod = readl(i2s->regs + S3C2412_IISMOD);
pr_debug("%s: r: IISMOD: %x\n", __func__, iismod);
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S8:
iismod |= S3C2412_IISMOD_8BIT;
@@ -335,6 +354,25 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
iismod &= ~S3C2412_IISMOD_8BIT;
break;
}
+#endif
+
+#ifdef CONFIG_PLAT_S3C64XX
+ iismod &= ~0x606;
+ /* Sample size */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S8:
+ /* 8 bit sample, 16fs BCLK */
+ iismod |= 0x2004;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ /* 16 bit sample, 32fs BCLK */
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ /* 24 bit sample, 48fs BCLK */
+ iismod |= 0x4002;
+ break;
+ }
+#endif
writel(iismod, i2s->regs + S3C2412_IISMOD);
pr_debug("%s: w: IISMOD: %x\n", __func__, iismod);
@@ -473,9 +511,9 @@ static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
/* default table of all avaialable root fs divisors */
static unsigned int iis_fs_tab[] = { 256, 512, 384, 768 };
-int s3c2412_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
- unsigned int *fstab,
- unsigned int rate, struct clk *clk)
+int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
+ unsigned int *fstab,
+ unsigned int rate, struct clk *clk)
{
unsigned long clkrate = clk_get_rate(clk);
unsigned int div;
@@ -489,6 +527,8 @@ int s3c2412_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
unsigned int best_rate = 0;
unsigned int best_deviation = INT_MAX;
+ pr_debug("Input clock rate %ldHz\n", clkrate);
+
if (fstab == NULL)
fstab = iis_fs_tab;
@@ -531,7 +571,7 @@ int s3c2412_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
return 0;
}
-EXPORT_SYMBOL_GPL(s3c2412_iis_calc_rate);
+EXPORT_SYMBOL_GPL(s3c_i2sv2_iis_calc_rate);
int s3c_i2sv2_probe(struct platform_device *pdev,
struct snd_soc_dai *dai,
@@ -539,12 +579,31 @@ int s3c_i2sv2_probe(struct platform_device *pdev,
unsigned long base)
{
struct device *dev = &pdev->dev;
+ unsigned int iismod;
i2s->dev = dev;
/* record our i2s structure for later use in the callbacks */
dai->private_data = i2s;
+ if (!base) {
+ struct resource *res = platform_get_resource(pdev,
+ IORESOURCE_MEM,
+ 0);
+ if (!res) {
+ dev_err(dev, "Unable to get register resource\n");
+ return -ENXIO;
+ }
+
+ if (!request_mem_region(res->start, resource_size(res),
+ "s3c64xx-i2s-v4")) {
+ dev_err(dev, "Unable to request register region\n");
+ return -EBUSY;
+ }
+
+ base = res->start;
+ }
+
i2s->regs = ioremap(base, 0x100);
if (i2s->regs == NULL) {
dev_err(dev, "cannot ioremap registers\n");
@@ -560,12 +619,16 @@ int s3c_i2sv2_probe(struct platform_device *pdev,
clk_enable(i2s->iis_pclk);
+ /* Mark ourselves as in TXRX mode so we can run through our cleanup
+ * process without warnings. */
+ iismod = readl(i2s->regs + S3C2412_IISMOD);
+ iismod |= S3C2412_IISMOD_MODE_TXRX;
+ writel(iismod, i2s->regs + S3C2412_IISMOD);
s3c2412_snd_txctrl(i2s, 0);
s3c2412_snd_rxctrl(i2s, 0);
return 0;
}
-
EXPORT_SYMBOL_GPL(s3c_i2sv2_probe);
#ifdef CONFIG_PM
@@ -624,15 +687,18 @@ static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
int s3c_i2sv2_register_dai(struct snd_soc_dai *dai)
{
- dai->ops.trigger = s3c2412_i2s_trigger;
- dai->ops.hw_params = s3c2412_i2s_hw_params;
- dai->ops.set_fmt = s3c2412_i2s_set_fmt;
- dai->ops.set_clkdiv = s3c2412_i2s_set_clkdiv;
+ struct snd_soc_dai_ops *ops = dai->ops;
+
+ ops->trigger = s3c2412_i2s_trigger;
+ ops->hw_params = s3c2412_i2s_hw_params;
+ ops->set_fmt = s3c2412_i2s_set_fmt;
+ ops->set_clkdiv = s3c2412_i2s_set_clkdiv;
dai->suspend = s3c2412_i2s_suspend;
dai->resume = s3c2412_i2s_resume;
return snd_soc_register_dai(dai);
}
-
EXPORT_SYMBOL_GPL(s3c_i2sv2_register_dai);
+
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.c b/sound/soc/s3c24xx/s3c2412-i2s.c
index 1ca3cdaa8213..168a088ba761 100644
--- a/sound/soc/s3c24xx/s3c2412-i2s.c
+++ b/sound/soc/s3c24xx/s3c2412-i2s.c
@@ -33,8 +33,8 @@
#include <plat/regs-s3c2412-iis.h>
-#include <plat/regs-gpio.h>
#include <plat/audio.h>
+#include <mach/regs-gpio.h>
#include <mach/dma.h>
#include "s3c24xx-pcm.h"
@@ -120,7 +120,7 @@ static int s3c2412_i2s_probe(struct platform_device *pdev,
s3c2412_i2s.iis_cclk = clk_get(&pdev->dev, "i2sclk");
if (s3c2412_i2s.iis_cclk == NULL) {
- pr_debug("failed to get i2sclk clock\n");
+ pr_err("failed to get i2sclk clock\n");
iounmap(s3c2412_i2s.regs);
return -ENODEV;
}
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c
index 33c5de7e255f..3c06c401d0fb 100644
--- a/sound/soc/s3c24xx/s3c64xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.c
@@ -108,48 +108,19 @@ static int s3c64xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
return 0;
}
-
-unsigned long s3c64xx_i2s_get_clockrate(struct snd_soc_dai *dai)
+struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai)
{
struct s3c_i2sv2_info *i2s = to_info(dai);
- return clk_get_rate(i2s->iis_cclk);
+ return i2s->iis_cclk;
}
-EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clockrate);
+EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clock);
static int s3c64xx_i2s_probe(struct platform_device *pdev,
struct snd_soc_dai *dai)
{
- struct device *dev = &pdev->dev;
- struct s3c_i2sv2_info *i2s;
- int ret;
-
- dev_dbg(dev, "%s: probing dai %d\n", __func__, pdev->id);
-
- if (pdev->id < 0 || pdev->id > ARRAY_SIZE(s3c64xx_i2s)) {
- dev_err(dev, "id %d out of range\n", pdev->id);
- return -EINVAL;
- }
-
- i2s = &s3c64xx_i2s[pdev->id];
-
- ret = s3c_i2sv2_probe(pdev, dai, i2s,
- pdev->id ? S3C64XX_PA_IIS1 : S3C64XX_PA_IIS0);
- if (ret)
- return ret;
-
- i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id];
- i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id];
-
- i2s->iis_cclk = clk_get(dev, "audio-bus");
- if (IS_ERR(i2s->iis_cclk)) {
- dev_err(dev, "failed to get audio-bus");
- iounmap(i2s->regs);
- return -ENODEV;
- }
-
/* configure GPIO for i2s port */
- switch (pdev->id) {
+ switch (dai->id) {
case 0:
s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_I2S0_CLK);
s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_I2S0_CDCLK);
@@ -175,41 +146,122 @@ static int s3c64xx_i2s_probe(struct platform_device *pdev,
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
#define S3C64XX_I2S_FMTS \
- (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE)
+ (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE)
static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops = {
.set_sysclk = s3c64xx_i2s_set_sysclk,
};
-struct snd_soc_dai s3c64xx_i2s_dai = {
- .name = "s3c64xx-i2s",
- .id = 0,
- .probe = s3c64xx_i2s_probe,
- .playback = {
- .channels_min = 2,
- .channels_max = 2,
- .rates = S3C64XX_I2S_RATES,
- .formats = S3C64XX_I2S_FMTS,
+struct snd_soc_dai s3c64xx_i2s_dai[] = {
+ {
+ .name = "s3c64xx-i2s",
+ .id = 0,
+ .probe = s3c64xx_i2s_probe,
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = S3C64XX_I2S_RATES,
+ .formats = S3C64XX_I2S_FMTS,
+ },
+ .capture = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = S3C64XX_I2S_RATES,
+ .formats = S3C64XX_I2S_FMTS,
+ },
+ .ops = &s3c64xx_i2s_dai_ops,
+ .symmetric_rates = 1,
},
- .capture = {
- .channels_min = 2,
- .channels_max = 2,
- .rates = S3C64XX_I2S_RATES,
- .formats = S3C64XX_I2S_FMTS,
+ {
+ .name = "s3c64xx-i2s",
+ .id = 1,
+ .probe = s3c64xx_i2s_probe,
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = S3C64XX_I2S_RATES,
+ .formats = S3C64XX_I2S_FMTS,
+ },
+ .capture = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = S3C64XX_I2S_RATES,
+ .formats = S3C64XX_I2S_FMTS,
+ },
+ .ops = &s3c64xx_i2s_dai_ops,
+ .symmetric_rates = 1,
},
- .ops = &s3c64xx_i2s_dai_ops,
};
EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai);
+static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev)
+{
+ struct s3c_i2sv2_info *i2s;
+ struct snd_soc_dai *dai;
+ int ret;
+
+ if (pdev->id >= ARRAY_SIZE(s3c64xx_i2s)) {
+ dev_err(&pdev->dev, "id %d out of range\n", pdev->id);
+ return -EINVAL;
+ }
+
+ i2s = &s3c64xx_i2s[pdev->id];
+ dai = &s3c64xx_i2s_dai[pdev->id];
+ dai->dev = &pdev->dev;
+
+ i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id];
+ i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id];
+
+ i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus");
+ if (IS_ERR(i2s->iis_cclk)) {
+ dev_err(&pdev->dev, "failed to get audio-bus\n");
+ ret = PTR_ERR(i2s->iis_cclk);
+ goto err;
+ }
+
+ ret = s3c_i2sv2_probe(pdev, dai, i2s, 0);
+ if (ret)
+ goto err_clk;
+
+ ret = s3c_i2sv2_register_dai(dai);
+ if (ret != 0)
+ goto err_i2sv2;
+
+ return 0;
+
+err_i2sv2:
+ /* Not implemented for I2Sv2 core yet */
+err_clk:
+ clk_put(i2s->iis_cclk);
+err:
+ return ret;
+}
+
+static __devexit int s3c64xx_iis_dev_remove(struct platform_device *pdev)
+{
+ dev_err(&pdev->dev, "Device removal not yet supported\n");
+ return 0;
+}
+
+static struct platform_driver s3c64xx_iis_driver = {
+ .probe = s3c64xx_iis_dev_probe,
+ .remove = s3c64xx_iis_dev_remove,
+ .driver = {
+ .name = "s3c64xx-iis",
+ .owner = THIS_MODULE,
+ },
+};
+
static int __init s3c64xx_i2s_init(void)
{
- return s3c_i2sv2_register_dai(&s3c64xx_i2s_dai);
+ return platform_driver_register(&s3c64xx_iis_driver);
}
module_init(s3c64xx_i2s_init);
static void __exit s3c64xx_i2s_exit(void)
{
- snd_soc_unregister_dai(&s3c64xx_i2s_dai);
+ platform_driver_unregister(&s3c64xx_iis_driver);
}
module_exit(s3c64xx_i2s_exit);
@@ -217,6 +269,3 @@ module_exit(s3c64xx_i2s_exit);
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
MODULE_DESCRIPTION("S3C64XX I2S SoC Interface");
MODULE_LICENSE("GPL");
-
-
-
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.h b/sound/soc/s3c24xx/s3c64xx-i2s.h
index b7ffe3c38b66..02148cee2613 100644
--- a/sound/soc/s3c24xx/s3c64xx-i2s.h
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.h
@@ -15,6 +15,8 @@
#ifndef __SND_SOC_S3C24XX_S3C64XX_I2S_H
#define __SND_SOC_S3C24XX_S3C64XX_I2S_H __FILE__
+struct clk;
+
#include "s3c-i2s-v2.h"
#define S3C64XX_DIV_BCLK S3C_I2SV2_DIV_BCLK
@@ -24,8 +26,8 @@
#define S3C64XX_CLKSRC_PCLK (0)
#define S3C64XX_CLKSRC_MUX (1)
-extern struct snd_soc_dai s3c64xx_i2s_dai;
+extern struct snd_soc_dai s3c64xx_i2s_dai[];
-extern unsigned long s3c64xx_i2s_get_clockrate(struct snd_soc_dai *cpu_dai);
+extern struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai);
#endif /* __SND_SOC_S3C24XX_S3C64XX_I2S_H */
diff --git a/sound/soc/s6000/Kconfig b/sound/soc/s6000/Kconfig
new file mode 100644
index 000000000000..c74eb3d4a47c
--- /dev/null
+++ b/sound/soc/s6000/Kconfig
@@ -0,0 +1,19 @@
+config SND_S6000_SOC
+ tristate "SoC Audio for the Stretch s6000 family"
+ depends on XTENSA_VARIANT_S6000
+ help
+ Say Y or M if you want to add support for codecs attached to
+ s6000 family chips. You will also need to select the platform
+ to support below.
+
+config SND_S6000_SOC_I2S
+ tristate
+
+config SND_S6000_SOC_S6IPCAM
+ tristate "SoC Audio support for Stretch 6105 IP Camera"
+ depends on SND_S6000_SOC && XTENSA_PLATFORM_S6105
+ select SND_S6000_SOC_I2S
+ select SND_SOC_TLV320AIC3X
+ help
+ Say Y if you want to add support for SoC audio on the
+ Stretch s6105 IP Camera Reference Design.
diff --git a/sound/soc/s6000/Makefile b/sound/soc/s6000/Makefile
new file mode 100644
index 000000000000..7a613612e010
--- /dev/null
+++ b/sound/soc/s6000/Makefile
@@ -0,0 +1,11 @@
+# s6000 Platform Support
+snd-soc-s6000-objs := s6000-pcm.o
+snd-soc-s6000-i2s-objs := s6000-i2s.o
+
+obj-$(CONFIG_SND_S6000_SOC) += snd-soc-s6000.o
+obj-$(CONFIG_SND_S6000_SOC_I2S) += snd-soc-s6000-i2s.o
+
+# s6105 Machine Support
+snd-soc-s6ipcam-objs := s6105-ipcam.o
+
+obj-$(CONFIG_SND_S6000_SOC_S6IPCAM) += snd-soc-s6ipcam.o
diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c
new file mode 100644
index 000000000000..c5cda187ecab
--- /dev/null
+++ b/sound/soc/s6000/s6000-i2s.c
@@ -0,0 +1,629 @@
+/*
+ * ALSA SoC I2S Audio Layer for the Stretch S6000 family
+ *
+ * Author: Daniel Gloeckner, <dg@emlix.com>
+ * Copyright: (C) 2009 emlix GmbH <info@emlix.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/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include "s6000-i2s.h"
+#include "s6000-pcm.h"
+
+struct s6000_i2s_dev {
+ dma_addr_t sifbase;
+ u8 __iomem *scbbase;
+ unsigned int wide;
+ unsigned int channel_in;
+ unsigned int channel_out;
+ unsigned int lines_in;
+ unsigned int lines_out;
+ struct s6000_pcm_dma_params dma_params;
+};
+
+#define S6_I2S_INTERRUPT_STATUS 0x00
+#define S6_I2S_INT_OVERRUN 1
+#define S6_I2S_INT_UNDERRUN 2
+#define S6_I2S_INT_ALIGNMENT 4
+#define S6_I2S_INTERRUPT_ENABLE 0x04
+#define S6_I2S_INTERRUPT_RAW 0x08
+#define S6_I2S_INTERRUPT_CLEAR 0x0C
+#define S6_I2S_INTERRUPT_SET 0x10
+#define S6_I2S_MODE 0x20
+#define S6_I2S_DUAL 0
+#define S6_I2S_WIDE 1
+#define S6_I2S_TX_DEFAULT 0x24
+#define S6_I2S_DATA_CFG(c) (0x40 + 0x10 * (c))
+#define S6_I2S_IN 0
+#define S6_I2S_OUT 1
+#define S6_I2S_UNUSED 2
+#define S6_I2S_INTERFACE_CFG(c) (0x44 + 0x10 * (c))
+#define S6_I2S_DIV_MASK 0x001fff
+#define S6_I2S_16BIT 0x000000
+#define S6_I2S_20BIT 0x002000
+#define S6_I2S_24BIT 0x004000
+#define S6_I2S_32BIT 0x006000
+#define S6_I2S_BITS_MASK 0x006000
+#define S6_I2S_MEM_16BIT 0x000000
+#define S6_I2S_MEM_32BIT 0x008000
+#define S6_I2S_MEM_MASK 0x008000
+#define S6_I2S_CHANNELS_SHIFT 16
+#define S6_I2S_CHANNELS_MASK 0x030000
+#define S6_I2S_SCK_IN 0x000000
+#define S6_I2S_SCK_OUT 0x040000
+#define S6_I2S_SCK_DIR 0x040000
+#define S6_I2S_WS_IN 0x000000
+#define S6_I2S_WS_OUT 0x080000
+#define S6_I2S_WS_DIR 0x080000
+#define S6_I2S_LEFT_FIRST 0x000000
+#define S6_I2S_RIGHT_FIRST 0x100000
+#define S6_I2S_FIRST 0x100000
+#define S6_I2S_CUR_SCK 0x200000
+#define S6_I2S_CUR_WS 0x400000
+#define S6_I2S_ENABLE(c) (0x48 + 0x10 * (c))
+#define S6_I2S_DISABLE_IF 0x02
+#define S6_I2S_ENABLE_IF 0x03
+#define S6_I2S_IS_BUSY 0x04
+#define S6_I2S_DMA_ACTIVE 0x08
+#define S6_I2S_IS_ENABLED 0x10
+
+#define S6_I2S_NUM_LINES 4
+
+#define S6_I2S_SIF_PORT0 0x0000000
+#define S6_I2S_SIF_PORT1 0x0000080 /* docs say 0x0000010 */
+
+static inline void s6_i2s_write_reg(struct s6000_i2s_dev *dev, int reg, u32 val)
+{
+ writel(val, dev->scbbase + reg);
+}
+
+static inline u32 s6_i2s_read_reg(struct s6000_i2s_dev *dev, int reg)
+{
+ return readl(dev->scbbase + reg);
+}
+
+static inline void s6_i2s_mod_reg(struct s6000_i2s_dev *dev, int reg,
+ u32 mask, u32 val)
+{
+ val ^= s6_i2s_read_reg(dev, reg) & ~mask;
+ s6_i2s_write_reg(dev, reg, val);
+}
+
+static void s6000_i2s_start_channel(struct s6000_i2s_dev *dev, int channel)
+{
+ int i, j, cur, prev;
+
+ /*
+ * Wait for WCLK to toggle 5 times before enabling the channel
+ * s6000 Family Datasheet 3.6.4:
+ * "At least two cycles of WS must occur between commands
+ * to disable or enable the interface"
+ */
+ j = 0;
+ prev = ~S6_I2S_CUR_WS;
+ for (i = 1000000; --i && j < 6; ) {
+ cur = s6_i2s_read_reg(dev, S6_I2S_INTERFACE_CFG(channel))
+ & S6_I2S_CUR_WS;
+ if (prev != cur) {
+ prev = cur;
+ j++;
+ }
+ }
+ if (j < 6)
+ printk(KERN_WARNING "s6000-i2s: timeout waiting for WCLK\n");
+
+ s6_i2s_write_reg(dev, S6_I2S_ENABLE(channel), S6_I2S_ENABLE_IF);
+}
+
+static void s6000_i2s_stop_channel(struct s6000_i2s_dev *dev, int channel)
+{
+ s6_i2s_write_reg(dev, S6_I2S_ENABLE(channel), S6_I2S_DISABLE_IF);
+}
+
+static void s6000_i2s_start(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct s6000_i2s_dev *dev = rtd->dai->cpu_dai->private_data;
+ int channel;
+
+ channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+ dev->channel_out : dev->channel_in;
+
+ s6000_i2s_start_channel(dev, channel);
+}
+
+static void s6000_i2s_stop(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct s6000_i2s_dev *dev = rtd->dai->cpu_dai->private_data;
+ int channel;
+
+ channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+ dev->channel_out : dev->channel_in;
+
+ s6000_i2s_stop_channel(dev, channel);
+}
+
+static int s6000_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+ int after)
+{
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) ^ !after)
+ s6000_i2s_start(substream);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ if (!after)
+ s6000_i2s_stop(substream);
+ }
+ return 0;
+}
+
+static unsigned int s6000_i2s_int_sources(struct s6000_i2s_dev *dev)
+{
+ unsigned int pending;
+ pending = s6_i2s_read_reg(dev, S6_I2S_INTERRUPT_RAW);
+ pending &= S6_I2S_INT_ALIGNMENT |
+ S6_I2S_INT_UNDERRUN |
+ S6_I2S_INT_OVERRUN;
+ s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_CLEAR, pending);
+
+ return pending;
+}
+
+static unsigned int s6000_i2s_check_xrun(struct snd_soc_dai *cpu_dai)
+{
+ struct s6000_i2s_dev *dev = cpu_dai->private_data;
+ unsigned int errors;
+ unsigned int ret;
+
+ errors = s6000_i2s_int_sources(dev);
+ if (likely(!errors))
+ return 0;
+
+ ret = 0;
+ if (errors & S6_I2S_INT_ALIGNMENT)
+ printk(KERN_ERR "s6000-i2s: WCLK misaligned\n");
+ if (errors & S6_I2S_INT_UNDERRUN)
+ ret |= 1 << SNDRV_PCM_STREAM_PLAYBACK;
+ if (errors & S6_I2S_INT_OVERRUN)
+ ret |= 1 << SNDRV_PCM_STREAM_CAPTURE;
+ return ret;
+}
+
+static void s6000_i2s_wait_disabled(struct s6000_i2s_dev *dev)
+{
+ int channel;
+ int n = 50;
+ for (channel = 0; channel < 2; channel++) {
+ while (--n >= 0) {
+ int v = s6_i2s_read_reg(dev, S6_I2S_ENABLE(channel));
+ if ((v & S6_I2S_IS_ENABLED)
+ || !(v & (S6_I2S_DMA_ACTIVE | S6_I2S_IS_BUSY)))
+ break;
+ udelay(20);
+ }
+ }
+ if (n < 0)
+ printk(KERN_WARNING "s6000-i2s: timeout disabling interfaces");
+}
+
+static int s6000_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
+ unsigned int fmt)
+{
+ struct s6000_i2s_dev *dev = cpu_dai->private_data;
+ u32 w;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ w = S6_I2S_SCK_IN | S6_I2S_WS_IN;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFM:
+ w = S6_I2S_SCK_OUT | S6_I2S_WS_IN;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFS:
+ w = S6_I2S_SCK_IN | S6_I2S_WS_OUT;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ w = S6_I2S_SCK_OUT | S6_I2S_WS_OUT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ w |= S6_I2S_LEFT_FIRST;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ w |= S6_I2S_RIGHT_FIRST;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ s6_i2s_mod_reg(dev, S6_I2S_INTERFACE_CFG(0),
+ S6_I2S_FIRST | S6_I2S_WS_DIR | S6_I2S_SCK_DIR, w);
+ s6_i2s_mod_reg(dev, S6_I2S_INTERFACE_CFG(1),
+ S6_I2S_FIRST | S6_I2S_WS_DIR | S6_I2S_SCK_DIR, w);
+
+ return 0;
+}
+
+static int s6000_i2s_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
+{
+ struct s6000_i2s_dev *dev = dai->private_data;
+
+ if (!div || (div & 1) || div > (S6_I2S_DIV_MASK + 1) * 2)
+ return -EINVAL;
+
+ s6_i2s_mod_reg(dev, S6_I2S_INTERFACE_CFG(div_id),
+ S6_I2S_DIV_MASK, div / 2 - 1);
+ return 0;
+}
+
+static int s6000_i2s_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct s6000_i2s_dev *dev = dai->private_data;
+ int interf;
+ u32 w = 0;
+
+ if (dev->wide)
+ interf = 0;
+ else {
+ w |= (((params_channels(params) - 2) / 2)
+ << S6_I2S_CHANNELS_SHIFT) & S6_I2S_CHANNELS_MASK;
+ interf = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ ? dev->channel_out : dev->channel_in;
+ }
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ w |= S6_I2S_16BIT | S6_I2S_MEM_16BIT;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ w |= S6_I2S_32BIT | S6_I2S_MEM_32BIT;
+ break;
+ default:
+ printk(KERN_WARNING "s6000-i2s: unsupported PCM format %x\n",
+ params_format(params));
+ return -EINVAL;
+ }
+
+ if (s6_i2s_read_reg(dev, S6_I2S_INTERFACE_CFG(interf))
+ & S6_I2S_IS_ENABLED) {
+ printk(KERN_ERR "s6000-i2s: interface already enabled\n");
+ return -EBUSY;
+ }
+
+ s6_i2s_mod_reg(dev, S6_I2S_INTERFACE_CFG(interf),
+ S6_I2S_CHANNELS_MASK|S6_I2S_MEM_MASK|S6_I2S_BITS_MASK,
+ w);
+
+ return 0;
+}
+
+static int s6000_i2s_dai_probe(struct platform_device *pdev,
+ struct snd_soc_dai *dai)
+{
+ struct s6000_i2s_dev *dev = dai->private_data;
+ struct s6000_snd_platform_data *pdata = pdev->dev.platform_data;
+
+ if (!pdata)
+ return -EINVAL;
+
+ dev->wide = pdata->wide;
+ dev->channel_in = pdata->channel_in;
+ dev->channel_out = pdata->channel_out;
+ dev->lines_in = pdata->lines_in;
+ dev->lines_out = pdata->lines_out;
+
+ s6_i2s_write_reg(dev, S6_I2S_MODE,
+ dev->wide ? S6_I2S_WIDE : S6_I2S_DUAL);
+
+ if (dev->wide) {
+ int i;
+
+ if (dev->lines_in + dev->lines_out > S6_I2S_NUM_LINES)
+ return -EINVAL;
+
+ dev->channel_in = 0;
+ dev->channel_out = 1;
+ dai->capture.channels_min = 2 * dev->lines_in;
+ dai->capture.channels_max = dai->capture.channels_min;
+ dai->playback.channels_min = 2 * dev->lines_out;
+ dai->playback.channels_max = dai->playback.channels_min;
+
+ for (i = 0; i < dev->lines_out; i++)
+ s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i), S6_I2S_OUT);
+
+ for (; i < S6_I2S_NUM_LINES - dev->lines_in; i++)
+ s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i),
+ S6_I2S_UNUSED);
+
+ for (; i < S6_I2S_NUM_LINES; i++)
+ s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i), S6_I2S_IN);
+ } else {
+ unsigned int cfg[2] = {S6_I2S_UNUSED, S6_I2S_UNUSED};
+
+ if (dev->lines_in > 1 || dev->lines_out > 1)
+ return -EINVAL;
+
+ dai->capture.channels_min = 2 * dev->lines_in;
+ dai->capture.channels_max = 8 * dev->lines_in;
+ dai->playback.channels_min = 2 * dev->lines_out;
+ dai->playback.channels_max = 8 * dev->lines_out;
+
+ if (dev->lines_in)
+ cfg[dev->channel_in] = S6_I2S_IN;
+ if (dev->lines_out)
+ cfg[dev->channel_out] = S6_I2S_OUT;
+
+ s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(0), cfg[0]);
+ s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(1), cfg[1]);
+ }
+
+ if (dev->lines_out) {
+ if (dev->lines_in) {
+ if (!dev->dma_params.dma_out)
+ return -ENODEV;
+ } else {
+ dev->dma_params.dma_out = dev->dma_params.dma_in;
+ dev->dma_params.dma_in = 0;
+ }
+ }
+ dev->dma_params.sif_in = dev->sifbase + (dev->channel_in ?
+ S6_I2S_SIF_PORT1 : S6_I2S_SIF_PORT0);
+ dev->dma_params.sif_out = dev->sifbase + (dev->channel_out ?
+ S6_I2S_SIF_PORT1 : S6_I2S_SIF_PORT0);
+ dev->dma_params.same_rate = pdata->same_rate | pdata->wide;
+ return 0;
+}
+
+#define S6000_I2S_RATES (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_5512 | \
+ SNDRV_PCM_RATE_8000_192000)
+#define S6000_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_ops s6000_i2s_dai_ops = {
+ .set_fmt = s6000_i2s_set_dai_fmt,
+ .set_clkdiv = s6000_i2s_set_clkdiv,
+ .hw_params = s6000_i2s_hw_params,
+};
+
+struct snd_soc_dai s6000_i2s_dai = {
+ .name = "s6000-i2s",
+ .id = 0,
+ .probe = s6000_i2s_dai_probe,
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 8,
+ .formats = S6000_I2S_FORMATS,
+ .rates = S6000_I2S_RATES,
+ .rate_min = 0,
+ .rate_max = 1562500,
+ },
+ .capture = {
+ .channels_min = 2,
+ .channels_max = 8,
+ .formats = S6000_I2S_FORMATS,
+ .rates = S6000_I2S_RATES,
+ .rate_min = 0,
+ .rate_max = 1562500,
+ },
+ .ops = &s6000_i2s_dai_ops,
+}
+EXPORT_SYMBOL_GPL(s6000_i2s_dai);
+
+static int __devinit s6000_i2s_probe(struct platform_device *pdev)
+{
+ struct s6000_i2s_dev *dev;
+ struct resource *scbmem, *sifmem, *region, *dma1, *dma2;
+ u8 __iomem *mmio;
+ int ret;
+
+ scbmem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!scbmem) {
+ dev_err(&pdev->dev, "no mem resource?\n");
+ ret = -ENODEV;
+ goto err_release_none;
+ }
+
+ region = request_mem_region(scbmem->start,
+ scbmem->end - scbmem->start + 1,
+ pdev->name);
+ if (!region) {
+ dev_err(&pdev->dev, "I2S SCB region already claimed\n");
+ ret = -EBUSY;
+ goto err_release_none;
+ }
+
+ mmio = ioremap(scbmem->start, scbmem->end - scbmem->start + 1);
+ if (!mmio) {
+ dev_err(&pdev->dev, "can't ioremap SCB region\n");
+ ret = -ENOMEM;
+ goto err_release_scb;
+ }
+
+ sifmem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!sifmem) {
+ dev_err(&pdev->dev, "no second mem resource?\n");
+ ret = -ENODEV;
+ goto err_release_map;
+ }
+
+ region = request_mem_region(sifmem->start,
+ sifmem->end - sifmem->start + 1,
+ pdev->name);
+ if (!region) {
+ dev_err(&pdev->dev, "I2S SIF region already claimed\n");
+ ret = -EBUSY;
+ goto err_release_map;
+ }
+
+ dma1 = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (!dma1) {
+ dev_err(&pdev->dev, "no dma resource?\n");
+ ret = -ENODEV;
+ goto err_release_sif;
+ }
+
+ region = request_mem_region(dma1->start, dma1->end - dma1->start + 1,
+ pdev->name);
+ if (!region) {
+ dev_err(&pdev->dev, "I2S DMA region already claimed\n");
+ ret = -EBUSY;
+ goto err_release_sif;
+ }
+
+ dma2 = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+ if (dma2) {
+ region = request_mem_region(dma2->start,
+ dma2->end - dma2->start + 1,
+ pdev->name);
+ if (!region) {
+ dev_err(&pdev->dev,
+ "I2S DMA region already claimed\n");
+ ret = -EBUSY;
+ goto err_release_dma1;
+ }
+ }
+
+ dev = kzalloc(sizeof(struct s6000_i2s_dev), GFP_KERNEL);
+ if (!dev) {
+ ret = -ENOMEM;
+ goto err_release_dma2;
+ }
+
+ s6000_i2s_dai.dev = &pdev->dev;
+ s6000_i2s_dai.private_data = dev;
+ s6000_i2s_dai.dma_data = &dev->dma_params;
+
+ dev->sifbase = sifmem->start;
+ dev->scbbase = mmio;
+
+ s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE, 0);
+ s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_CLEAR,
+ S6_I2S_INT_ALIGNMENT |
+ S6_I2S_INT_UNDERRUN |
+ S6_I2S_INT_OVERRUN);
+
+ s6000_i2s_stop_channel(dev, 0);
+ s6000_i2s_stop_channel(dev, 1);
+ s6000_i2s_wait_disabled(dev);
+
+ dev->dma_params.check_xrun = s6000_i2s_check_xrun;
+ dev->dma_params.trigger = s6000_i2s_trigger;
+ dev->dma_params.dma_in = dma1->start;
+ dev->dma_params.dma_out = dma2 ? dma2->start : 0;
+ dev->dma_params.irq = platform_get_irq(pdev, 0);
+ if (dev->dma_params.irq < 0) {
+ dev_err(&pdev->dev, "no irq resource?\n");
+ ret = -ENODEV;
+ goto err_release_dev;
+ }
+
+ s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE,
+ S6_I2S_INT_ALIGNMENT |
+ S6_I2S_INT_UNDERRUN |
+ S6_I2S_INT_OVERRUN);
+
+ ret = snd_soc_register_dai(&s6000_i2s_dai);
+ if (ret)
+ goto err_release_dev;
+
+ return 0;
+
+err_release_dev:
+ kfree(dev);
+err_release_dma2:
+ if (dma2)
+ release_mem_region(dma2->start, dma2->end - dma2->start + 1);
+err_release_dma1:
+ release_mem_region(dma1->start, dma1->end - dma1->start + 1);
+err_release_sif:
+ release_mem_region(sifmem->start, (sifmem->end - sifmem->start) + 1);
+err_release_map:
+ iounmap(mmio);
+err_release_scb:
+ release_mem_region(scbmem->start, (scbmem->end - scbmem->start) + 1);
+err_release_none:
+ return ret;
+}
+
+static void __devexit s6000_i2s_remove(struct platform_device *pdev)
+{
+ struct s6000_i2s_dev *dev = s6000_i2s_dai.private_data;
+ struct resource *region;
+ void __iomem *mmio = dev->scbbase;
+
+ snd_soc_unregister_dai(&s6000_i2s_dai);
+
+ s6000_i2s_stop_channel(dev, 0);
+ s6000_i2s_stop_channel(dev, 1);
+
+ s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE, 0);
+ s6000_i2s_dai.private_data = 0;
+ kfree(dev);
+
+ region = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ release_mem_region(region->start, region->end - region->start + 1);
+
+ region = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+ if (region)
+ release_mem_region(region->start,
+ region->end - region->start + 1);
+
+ region = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(region->start, (region->end - region->start) + 1);
+
+ iounmap(mmio);
+ region = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ release_mem_region(region->start, (region->end - region->start) + 1);
+}
+
+static struct platform_driver s6000_i2s_driver = {
+ .probe = s6000_i2s_probe,
+ .remove = __devexit_p(s6000_i2s_remove),
+ .driver = {
+ .name = "s6000-i2s",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init s6000_i2s_init(void)
+{
+ return platform_driver_register(&s6000_i2s_driver);
+}
+module_init(s6000_i2s_init);
+
+static void __exit s6000_i2s_exit(void)
+{
+ platform_driver_unregister(&s6000_i2s_driver);
+}
+module_exit(s6000_i2s_exit);
+
+MODULE_AUTHOR("Daniel Gloeckner");
+MODULE_DESCRIPTION("Stretch s6000 family I2S SoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/s6000/s6000-i2s.h b/sound/soc/s6000/s6000-i2s.h
new file mode 100644
index 000000000000..2375fdfe6dba
--- /dev/null
+++ b/sound/soc/s6000/s6000-i2s.h
@@ -0,0 +1,25 @@
+/*
+ * ALSA SoC I2S Audio Layer for the Stretch s6000 family
+ *
+ * Author: Daniel Gloeckner, <dg@emlix.com>
+ * Copyright: (C) 2009 emlix GmbH <info@emlix.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 _S6000_I2S_H
+#define _S6000_I2S_H
+
+extern struct snd_soc_dai s6000_i2s_dai;
+
+struct s6000_snd_platform_data {
+ int lines_in;
+ int lines_out;
+ int channel_in;
+ int channel_out;
+ int wide;
+ int same_rate;
+};
+#endif
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c
new file mode 100644
index 000000000000..83b8028e209d
--- /dev/null
+++ b/sound/soc/s6000/s6000-pcm.c
@@ -0,0 +1,497 @@
+/*
+ * ALSA PCM interface for the Stetch s6000 family
+ *
+ * Author: Daniel Gloeckner, <dg@emlix.com>
+ * Copyright: (C) 2009 emlix GmbH <info@emlix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <asm/dma.h>
+#include <variant/dmac.h>
+
+#include "s6000-pcm.h"
+
+#define S6_PCM_PREALLOCATE_SIZE (96 * 1024)
+#define S6_PCM_PREALLOCATE_MAX (2048 * 1024)
+
+static struct snd_pcm_hardware s6000_pcm_hardware = {
+ .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_JOINT_DUPLEX),
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE),
+ .rates = (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_5512 | \
+ SNDRV_PCM_RATE_8000_192000),
+ .rate_min = 0,
+ .rate_max = 1562500,
+ .channels_min = 2,
+ .channels_max = 8,
+ .buffer_bytes_max = 0x7ffffff0,
+ .period_bytes_min = 16,
+ .period_bytes_max = 0xfffff0,
+ .periods_min = 2,
+ .periods_max = 1024, /* no limit */
+ .fifo_size = 0,
+};
+
+struct s6000_runtime_data {
+ spinlock_t lock;
+ int period; /* current DMA period */
+};
+
+static void s6000_pcm_enqueue_dma(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct s6000_runtime_data *prtd = runtime->private_data;
+ struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
+ struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
+ int channel;
+ unsigned int period_size;
+ unsigned int dma_offset;
+ dma_addr_t dma_pos;
+ dma_addr_t src, dst;
+
+ period_size = snd_pcm_lib_period_bytes(substream);
+ dma_offset = prtd->period * period_size;
+ dma_pos = runtime->dma_addr + dma_offset;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ src = dma_pos;
+ dst = par->sif_out;
+ channel = par->dma_out;
+ } else {
+ src = par->sif_in;
+ dst = dma_pos;
+ channel = par->dma_in;
+ }
+
+ if (!s6dmac_channel_enabled(DMA_MASK_DMAC(channel),
+ DMA_INDEX_CHNL(channel)))
+ return;
+
+ if (s6dmac_fifo_full(DMA_MASK_DMAC(channel), DMA_INDEX_CHNL(channel))) {
+ printk(KERN_ERR "s6000-pcm: fifo full\n");
+ return;
+ }
+
+ BUG_ON(period_size & 15);
+ s6dmac_put_fifo(DMA_MASK_DMAC(channel), DMA_INDEX_CHNL(channel),
+ src, dst, period_size);
+
+ prtd->period++;
+ if (unlikely(prtd->period >= runtime->periods))
+ prtd->period = 0;
+}
+
+static irqreturn_t s6000_pcm_irq(int irq, void *data)
+{
+ struct snd_pcm *pcm = data;
+ struct snd_soc_pcm_runtime *runtime = pcm->private_data;
+ struct s6000_pcm_dma_params *params = runtime->dai->cpu_dai->dma_data;
+ struct s6000_runtime_data *prtd;
+ unsigned int has_xrun;
+ int i, ret = IRQ_NONE;
+ u32 channel[2] = {
+ [SNDRV_PCM_STREAM_PLAYBACK] = params->dma_out,
+ [SNDRV_PCM_STREAM_CAPTURE] = params->dma_in
+ };
+
+ has_xrun = params->check_xrun(runtime->dai->cpu_dai);
+
+ for (i = 0; i < ARRAY_SIZE(channel); ++i) {
+ struct snd_pcm_substream *substream = pcm->streams[i].substream;
+ unsigned int pending;
+
+ if (!channel[i])
+ continue;
+
+ if (unlikely(has_xrun & (1 << i)) &&
+ substream->runtime &&
+ snd_pcm_running(substream)) {
+ dev_dbg(pcm->dev, "xrun\n");
+ snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+ ret = IRQ_HANDLED;
+ }
+
+ pending = s6dmac_int_sources(DMA_MASK_DMAC(channel[i]),
+ DMA_INDEX_CHNL(channel[i]));
+
+ if (pending & 1) {
+ ret = IRQ_HANDLED;
+ if (likely(substream->runtime &&
+ snd_pcm_running(substream))) {
+ snd_pcm_period_elapsed(substream);
+ dev_dbg(pcm->dev, "period elapsed %x %x\n",
+ s6dmac_cur_src(DMA_MASK_DMAC(channel[i]),
+ DMA_INDEX_CHNL(channel[i])),
+ s6dmac_cur_dst(DMA_MASK_DMAC(channel[i]),
+ DMA_INDEX_CHNL(channel[i])));
+ prtd = substream->runtime->private_data;
+ spin_lock(&prtd->lock);
+ s6000_pcm_enqueue_dma(substream);
+ spin_unlock(&prtd->lock);
+ }
+ }
+
+ if (unlikely(pending & ~7)) {
+ if (pending & (1 << 3))
+ printk(KERN_WARNING
+ "s6000-pcm: DMA %x Underflow\n",
+ channel[i]);
+ if (pending & (1 << 4))
+ printk(KERN_WARNING
+ "s6000-pcm: DMA %x Overflow\n",
+ channel[i]);
+ if (pending & 0x1e0)
+ printk(KERN_WARNING
+ "s6000-pcm: DMA %x Master Error "
+ "(mask %x)\n",
+ channel[i], pending >> 5);
+
+ }
+ }
+
+ return ret;
+}
+
+static int s6000_pcm_start(struct snd_pcm_substream *substream)
+{
+ struct s6000_runtime_data *prtd = substream->runtime->private_data;
+ struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
+ struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
+ unsigned long flags;
+ int srcinc;
+ u32 dma;
+
+ spin_lock_irqsave(&prtd->lock, flags);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ srcinc = 1;
+ dma = par->dma_out;
+ } else {
+ srcinc = 0;
+ dma = par->dma_in;
+ }
+ s6dmac_enable_chan(DMA_MASK_DMAC(dma), DMA_INDEX_CHNL(dma),
+ 1 /* priority 1 (0 is max) */,
+ 0 /* peripheral requests w/o xfer length mode */,
+ srcinc /* source address increment */,
+ srcinc^1 /* destination address increment */,
+ 0 /* chunksize 0 (skip impossible on this dma) */,
+ 0 /* source skip after chunk (impossible) */,
+ 0 /* destination skip after chunk (impossible) */,
+ 4 /* 16 byte burst size */,
+ -1 /* don't conserve bandwidth */,
+ 0 /* low watermark irq descriptor theshold */,
+ 0 /* disable hardware timestamps */,
+ 1 /* enable channel */);
+
+ s6000_pcm_enqueue_dma(substream);
+ s6000_pcm_enqueue_dma(substream);
+
+ spin_unlock_irqrestore(&prtd->lock, flags);
+
+ return 0;
+}
+
+static int s6000_pcm_stop(struct snd_pcm_substream *substream)
+{
+ struct s6000_runtime_data *prtd = substream->runtime->private_data;
+ struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
+ struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
+ unsigned long flags;
+ u32 channel;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ channel = par->dma_out;
+ else
+ channel = par->dma_in;
+
+ s6dmac_set_terminal_count(DMA_MASK_DMAC(channel),
+ DMA_INDEX_CHNL(channel), 0);
+
+ spin_lock_irqsave(&prtd->lock, flags);
+
+ s6dmac_disable_chan(DMA_MASK_DMAC(channel), DMA_INDEX_CHNL(channel));
+
+ spin_unlock_irqrestore(&prtd->lock, flags);
+
+ return 0;
+}
+
+static int s6000_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
+ struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
+ int ret;
+
+ ret = par->trigger(substream, cmd, 0);
+ if (ret < 0)
+ return ret;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ ret = s6000_pcm_start(substream);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ ret = s6000_pcm_stop(substream);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ if (ret < 0)
+ return ret;
+
+ return par->trigger(substream, cmd, 1);
+}
+
+static int s6000_pcm_prepare(struct snd_pcm_substream *substream)
+{
+ struct s6000_runtime_data *prtd = substream->runtime->private_data;
+
+ prtd->period = 0;
+
+ return 0;
+}
+
+static snd_pcm_uframes_t s6000_pcm_pointer(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
+ struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct s6000_runtime_data *prtd = runtime->private_data;
+ unsigned long flags;
+ unsigned int offset;
+ dma_addr_t count;
+
+ spin_lock_irqsave(&prtd->lock, flags);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ count = s6dmac_cur_src(DMA_MASK_DMAC(par->dma_out),
+ DMA_INDEX_CHNL(par->dma_out));
+ else
+ count = s6dmac_cur_dst(DMA_MASK_DMAC(par->dma_in),
+ DMA_INDEX_CHNL(par->dma_in));
+
+ count -= runtime->dma_addr;
+
+ spin_unlock_irqrestore(&prtd->lock, flags);
+
+ offset = bytes_to_frames(runtime, count);
+ if (unlikely(offset >= runtime->buffer_size))
+ offset = 0;
+
+ return offset;
+}
+
+static int s6000_pcm_open(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
+ struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct s6000_runtime_data *prtd;
+ int ret;
+
+ snd_soc_set_runtime_hwparams(substream, &s6000_pcm_hardware);
+
+ ret = snd_pcm_hw_constraint_step(runtime, 0,
+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 16);
+ if (ret < 0)
+ return ret;
+ ret = snd_pcm_hw_constraint_step(runtime, 0,
+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 16);
+ if (ret < 0)
+ return ret;
+ ret = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0)
+ return ret;
+
+ if (par->same_rate) {
+ int rate;
+ spin_lock(&par->lock); /* needed? */
+ rate = par->rate;
+ spin_unlock(&par->lock);
+ if (rate != -1) {
+ ret = snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_RATE,
+ rate, rate);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ prtd = kzalloc(sizeof(struct s6000_runtime_data), GFP_KERNEL);
+ if (prtd == NULL)
+ return -ENOMEM;
+
+ spin_lock_init(&prtd->lock);
+
+ runtime->private_data = prtd;
+
+ return 0;
+}
+
+static int s6000_pcm_close(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct s6000_runtime_data *prtd = runtime->private_data;
+
+ kfree(prtd);
+
+ return 0;
+}
+
+static int s6000_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
+{
+ struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
+ struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
+ int ret;
+ ret = snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+ if (ret < 0) {
+ printk(KERN_WARNING "s6000-pcm: allocation of memory failed\n");
+ return ret;
+ }
+
+ if (par->same_rate) {
+ spin_lock(&par->lock);
+ if (par->rate == -1 ||
+ !(par->in_use & ~(1 << substream->stream))) {
+ par->rate = params_rate(hw_params);
+ par->in_use |= 1 << substream->stream;
+ } else if (params_rate(hw_params) != par->rate) {
+ snd_pcm_lib_free_pages(substream);
+ par->in_use &= ~(1 << substream->stream);
+ ret = -EBUSY;
+ }
+ spin_unlock(&par->lock);
+ }
+ return ret;
+}
+
+static int s6000_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
+ struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
+
+ spin_lock(&par->lock);
+ par->in_use &= ~(1 << substream->stream);
+ if (!par->in_use)
+ par->rate = -1;
+ spin_unlock(&par->lock);
+
+ return snd_pcm_lib_free_pages(substream);
+}
+
+static struct snd_pcm_ops s6000_pcm_ops = {
+ .open = s6000_pcm_open,
+ .close = s6000_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = s6000_pcm_hw_params,
+ .hw_free = s6000_pcm_hw_free,
+ .trigger = s6000_pcm_trigger,
+ .prepare = s6000_pcm_prepare,
+ .pointer = s6000_pcm_pointer,
+};
+
+static void s6000_pcm_free(struct snd_pcm *pcm)
+{
+ struct snd_soc_pcm_runtime *runtime = pcm->private_data;
+ struct s6000_pcm_dma_params *params = runtime->dai->cpu_dai->dma_data;
+
+ free_irq(params->irq, pcm);
+ snd_pcm_lib_preallocate_free_for_all(pcm);
+}
+
+static u64 s6000_pcm_dmamask = DMA_32BIT_MASK;
+
+static int s6000_pcm_new(struct snd_card *card,
+ struct snd_soc_dai *dai, struct snd_pcm *pcm)
+{
+ struct snd_soc_pcm_runtime *runtime = pcm->private_data;
+ struct s6000_pcm_dma_params *params = runtime->dai->cpu_dai->dma_data;
+ int res;
+
+ if (!card->dev->dma_mask)
+ card->dev->dma_mask = &s6000_pcm_dmamask;
+ if (!card->dev->coherent_dma_mask)
+ card->dev->coherent_dma_mask = DMA_32BIT_MASK;
+
+ if (params->dma_in) {
+ s6dmac_disable_chan(DMA_MASK_DMAC(params->dma_in),
+ DMA_INDEX_CHNL(params->dma_in));
+ s6dmac_int_sources(DMA_MASK_DMAC(params->dma_in),
+ DMA_INDEX_CHNL(params->dma_in));
+ }
+
+ if (params->dma_out) {
+ s6dmac_disable_chan(DMA_MASK_DMAC(params->dma_out),
+ DMA_INDEX_CHNL(params->dma_out));
+ s6dmac_int_sources(DMA_MASK_DMAC(params->dma_out),
+ DMA_INDEX_CHNL(params->dma_out));
+ }
+
+ res = request_irq(params->irq, s6000_pcm_irq, IRQF_SHARED,
+ s6000_soc_platform.name, pcm);
+ if (res) {
+ printk(KERN_ERR "s6000-pcm couldn't get IRQ\n");
+ return res;
+ }
+
+ res = snd_pcm_lib_preallocate_pages_for_all(pcm,
+ SNDRV_DMA_TYPE_DEV,
+ card->dev,
+ S6_PCM_PREALLOCATE_SIZE,
+ S6_PCM_PREALLOCATE_MAX);
+ if (res)
+ printk(KERN_WARNING "s6000-pcm: preallocation failed\n");
+
+ spin_lock_init(&params->lock);
+ params->in_use = 0;
+ params->rate = -1;
+ return 0;
+}
+
+struct snd_soc_platform s6000_soc_platform = {
+ .name = "s6000-audio",
+ .pcm_ops = &s6000_pcm_ops,
+ .pcm_new = s6000_pcm_new,
+ .pcm_free = s6000_pcm_free,
+};
+EXPORT_SYMBOL_GPL(s6000_soc_platform);
+
+static int __init s6000_pcm_init(void)
+{
+ return snd_soc_register_platform(&s6000_soc_platform);
+}
+module_init(s6000_pcm_init);
+
+static void __exit s6000_pcm_exit(void)
+{
+ snd_soc_unregister_platform(&s6000_soc_platform);
+}
+module_exit(s6000_pcm_exit);
+
+MODULE_AUTHOR("Daniel Gloeckner");
+MODULE_DESCRIPTION("Stretch s6000 family PCM DMA module");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/s6000/s6000-pcm.h b/sound/soc/s6000/s6000-pcm.h
new file mode 100644
index 000000000000..96f23f6f52bf
--- /dev/null
+++ b/sound/soc/s6000/s6000-pcm.h
@@ -0,0 +1,35 @@
+/*
+ * ALSA PCM interface for the Stretch s6000 family
+ *
+ * Author: Daniel Gloeckner, <dg@emlix.com>
+ * Copyright: (C) 2009 emlix GmbH <info@emlix.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 _S6000_PCM_H
+#define _S6000_PCM_H
+
+struct snd_soc_dai;
+struct snd_pcm_substream;
+
+struct s6000_pcm_dma_params {
+ unsigned int (*check_xrun)(struct snd_soc_dai *cpu_dai);
+ int (*trigger)(struct snd_pcm_substream *substream, int cmd, int after);
+ dma_addr_t sif_in;
+ dma_addr_t sif_out;
+ u32 dma_in;
+ u32 dma_out;
+ int irq;
+ int same_rate;
+
+ spinlock_t lock;
+ int in_use;
+ int rate;
+};
+
+extern struct snd_soc_platform s6000_soc_platform;
+
+#endif
diff --git a/sound/soc/s6000/s6105-ipcam.c b/sound/soc/s6000/s6105-ipcam.c
new file mode 100644
index 000000000000..b5f95f9781c1
--- /dev/null
+++ b/sound/soc/s6000/s6105-ipcam.c
@@ -0,0 +1,244 @@
+/*
+ * ASoC driver for Stretch s6105 IP camera platform
+ *
+ * Author: Daniel Gloeckner, <dg@emlix.com>
+ * Copyright: (C) 2009 emlix GmbH <info@emlix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <variant/dmac.h>
+
+#include "../codecs/tlv320aic3x.h"
+#include "s6000-pcm.h"
+#include "s6000-i2s.h"
+
+#define S6105_CAM_CODEC_CLOCK 12288000
+
+static int s6105_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_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ int ret = 0;
+
+ /* set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0)
+ return ret;
+
+ /* set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM |
+ SND_SOC_DAIFMT_NB_NF);
+ if (ret < 0)
+ return ret;
+
+ /* set the codec system clock */
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, S6105_CAM_CODEC_CLOCK,
+ SND_SOC_CLOCK_OUT);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static struct snd_soc_ops s6105_ops = {
+ .hw_params = s6105_hw_params,
+};
+
+/* s6105 machine dapm widgets */
+static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
+ SND_SOC_DAPM_LINE("Audio Out Differential", NULL),
+ SND_SOC_DAPM_LINE("Audio Out Stereo", NULL),
+ SND_SOC_DAPM_LINE("Audio In", NULL),
+};
+
+/* s6105 machine audio_mapnections to the codec pins */
+static const struct snd_soc_dapm_route audio_map[] = {
+ /* Audio Out connected to HPLOUT, HPLCOM, HPROUT */
+ {"Audio Out Differential", NULL, "HPLOUT"},
+ {"Audio Out Differential", NULL, "HPLCOM"},
+ {"Audio Out Stereo", NULL, "HPLOUT"},
+ {"Audio Out Stereo", NULL, "HPROUT"},
+
+ /* Audio In connected to LINE1L, LINE1R */
+ {"LINE1L", NULL, "Audio In"},
+ {"LINE1R", NULL, "Audio In"},
+};
+
+static int output_type_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 2;
+ if (uinfo->value.enumerated.item) {
+ uinfo->value.enumerated.item = 1;
+ strcpy(uinfo->value.enumerated.name, "HPLOUT/HPROUT");
+ } else {
+ strcpy(uinfo->value.enumerated.name, "HPLOUT/HPLCOM");
+ }
+ return 0;
+}
+
+static int output_type_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.enumerated.item[0] = kcontrol->private_value;
+ return 0;
+}
+
+static int output_type_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = kcontrol->private_data;
+ unsigned int val = (ucontrol->value.enumerated.item[0] != 0);
+ char *differential = "Audio Out Differential";
+ char *stereo = "Audio Out Stereo";
+
+ if (kcontrol->private_value == val)
+ return 0;
+ kcontrol->private_value = val;
+ snd_soc_dapm_disable_pin(codec, val ? differential : stereo);
+ snd_soc_dapm_sync(codec);
+ snd_soc_dapm_enable_pin(codec, val ? stereo : differential);
+ snd_soc_dapm_sync(codec);
+
+ return 1;
+}
+
+static const struct snd_kcontrol_new audio_out_mux = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Master Output Mux",
+ .index = 0,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = output_type_info,
+ .get = output_type_get,
+ .put = output_type_put,
+ .private_value = 1 /* default to stereo */
+};
+
+/* Logic for a aic3x as connected on the s6105 ip camera ref design */
+static int s6105_aic3x_init(struct snd_soc_codec *codec)
+{
+ /* Add s6105 specific widgets */
+ snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets,
+ ARRAY_SIZE(aic3x_dapm_widgets));
+
+ /* Set up s6105 specific audio path audio_map */
+ snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+ /* not present */
+ snd_soc_dapm_nc_pin(codec, "MONO_LOUT");
+ snd_soc_dapm_nc_pin(codec, "LINE2L");
+ snd_soc_dapm_nc_pin(codec, "LINE2R");
+
+ /* not connected */
+ snd_soc_dapm_nc_pin(codec, "MIC3L"); /* LINE2L on this chip */
+ snd_soc_dapm_nc_pin(codec, "MIC3R"); /* LINE2R on this chip */
+ snd_soc_dapm_nc_pin(codec, "LLOUT");
+ snd_soc_dapm_nc_pin(codec, "RLOUT");
+ snd_soc_dapm_nc_pin(codec, "HPRCOM");
+
+ /* always connected */
+ snd_soc_dapm_enable_pin(codec, "Audio In");
+
+ /* must correspond to audio_out_mux.private_value initializer */
+ snd_soc_dapm_disable_pin(codec, "Audio Out Differential");
+ snd_soc_dapm_sync(codec);
+ snd_soc_dapm_enable_pin(codec, "Audio Out Stereo");
+
+ snd_soc_dapm_sync(codec);
+
+ snd_ctl_add(codec->card, snd_ctl_new1(&audio_out_mux, codec));
+
+ return 0;
+}
+
+/* s6105 digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link s6105_dai = {
+ .name = "TLV320AIC31",
+ .stream_name = "AIC31",
+ .cpu_dai = &s6000_i2s_dai,
+ .codec_dai = &aic3x_dai,
+ .init = s6105_aic3x_init,
+ .ops = &s6105_ops,
+};
+
+/* s6105 audio machine driver */
+static struct snd_soc_card snd_soc_card_s6105 = {
+ .name = "Stretch IP Camera",
+ .platform = &s6000_soc_platform,
+ .dai_link = &s6105_dai,
+ .num_links = 1,
+};
+
+/* s6105 audio private data */
+static struct aic3x_setup_data s6105_aic3x_setup = {
+ .i2c_bus = 0,
+ .i2c_address = 0x18,
+};
+
+/* s6105 audio subsystem */
+static struct snd_soc_device s6105_snd_devdata = {
+ .card = &snd_soc_card_s6105,
+ .codec_dev = &soc_codec_dev_aic3x,
+ .codec_data = &s6105_aic3x_setup,
+};
+
+static struct s6000_snd_platform_data __initdata s6105_snd_data = {
+ .wide = 0,
+ .channel_in = 0,
+ .channel_out = 1,
+ .lines_in = 1,
+ .lines_out = 1,
+ .same_rate = 1,
+};
+
+static struct platform_device *s6105_snd_device;
+
+static int __init s6105_init(void)
+{
+ int ret;
+
+ s6105_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!s6105_snd_device)
+ return -ENOMEM;
+
+ platform_set_drvdata(s6105_snd_device, &s6105_snd_devdata);
+ s6105_snd_devdata.dev = &s6105_snd_device->dev;
+ platform_device_add_data(s6105_snd_device, &s6105_snd_data,
+ sizeof(s6105_snd_data));
+
+ ret = platform_device_add(s6105_snd_device);
+ if (ret)
+ platform_device_put(s6105_snd_device);
+
+ return ret;
+}
+
+static void __exit s6105_exit(void)
+{
+ platform_device_unregister(s6105_snd_device);
+}
+
+module_init(s6105_init);
+module_exit(s6105_exit);
+
+MODULE_AUTHOR("Daniel Gloeckner");
+MODULE_DESCRIPTION("Stretch s6105 IP camera ASoC driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c
index 0dad3a0bb920..baddb1242c71 100644
--- a/sound/soc/sh/dma-sh7760.c
+++ b/sound/soc/sh/dma-sh7760.c
@@ -103,7 +103,8 @@ static struct snd_pcm_hardware camelot_pcm_hardware = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID),
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH),
.formats = DMABRG_FMTS,
.rates = DMABRG_RATES,
.rate_min = 8000,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 99712f652d0d..af11791a3b8c 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -113,6 +113,35 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
}
#endif
+static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_card *card = socdev->card;
+ struct snd_soc_dai_link *machine = rtd->dai;
+ struct snd_soc_dai *cpu_dai = machine->cpu_dai;
+ struct snd_soc_dai *codec_dai = machine->codec_dai;
+ int ret;
+
+ if (codec_dai->symmetric_rates || cpu_dai->symmetric_rates ||
+ machine->symmetric_rates) {
+ dev_dbg(card->dev, "Symmetry forces %dHz rate\n",
+ machine->rate);
+
+ ret = snd_pcm_hw_constraint_minmax(substream->runtime,
+ SNDRV_PCM_HW_PARAM_RATE,
+ machine->rate,
+ machine->rate);
+ if (ret < 0) {
+ dev_err(card->dev,
+ "Unable to apply rate symmetry constraint: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
/*
* Called by ALSA when a PCM substream is opened, the runtime->hw record is
* then initialized and any private data can be allocated. This also calls
@@ -221,6 +250,13 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
goto machine_err;
}
+ /* Symmetry only applies if we've already got an active stream. */
+ if (cpu_dai->active || codec_dai->active) {
+ ret = soc_pcm_apply_symmetry(substream);
+ if (ret != 0)
+ goto machine_err;
+ }
+
pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name);
pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);
pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
@@ -521,6 +557,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
}
}
+ machine->rate = params_rate(params);
+
out:
mutex_unlock(&pcm_mutex);
return ret;
@@ -1741,7 +1779,7 @@ int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,
{
int max = kcontrol->private_value;
- if (max == 1)
+ if (max == 1 && !strstr(kcontrol->id.name, " Volume"))
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
else
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -1771,7 +1809,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
unsigned int shift = mc->shift;
unsigned int rshift = mc->rshift;
- if (max == 1)
+ if (max == 1 && !strstr(kcontrol->id.name, " Volume"))
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
else
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -1878,7 +1916,7 @@ int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
(struct soc_mixer_control *)kcontrol->private_value;
int max = mc->max;
- if (max == 1)
+ if (max == 1 && !strstr(kcontrol->id.name, " Volume"))
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
else
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -2062,7 +2100,7 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
unsigned int freq, int dir)
{
- if (dai->ops->set_sysclk)
+ if (dai->ops && dai->ops->set_sysclk)
return dai->ops->set_sysclk(dai, clk_id, freq, dir);
else
return -EINVAL;
@@ -2082,7 +2120,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
int div_id, int div)
{
- if (dai->ops->set_clkdiv)
+ if (dai->ops && dai->ops->set_clkdiv)
return dai->ops->set_clkdiv(dai, div_id, div);
else
return -EINVAL;
@@ -2101,7 +2139,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
int pll_id, unsigned int freq_in, unsigned int freq_out)
{
- if (dai->ops->set_pll)
+ if (dai->ops && dai->ops->set_pll)
return dai->ops->set_pll(dai, pll_id, freq_in, freq_out);
else
return -EINVAL;
@@ -2117,7 +2155,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
*/
int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
- if (dai->ops->set_fmt)
+ if (dai->ops && dai->ops->set_fmt)
return dai->ops->set_fmt(dai, fmt);
else
return -EINVAL;
@@ -2136,7 +2174,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
unsigned int mask, int slots)
{
- if (dai->ops->set_sysclk)
+ if (dai->ops && dai->ops->set_tdm_slot)
return dai->ops->set_tdm_slot(dai, mask, slots);
else
return -EINVAL;
@@ -2152,7 +2190,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
*/
int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
{
- if (dai->ops->set_sysclk)
+ if (dai->ops && dai->ops->set_tristate)
return dai->ops->set_tristate(dai, tristate);
else
return -EINVAL;
@@ -2168,7 +2206,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
*/
int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute)
{
- if (dai->ops->digital_mute)
+ if (dai->ops && dai->ops->digital_mute)
return dai->ops->digital_mute(dai, mute);
else
return -EINVAL;
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 735903a74675..7847f80e96d1 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -52,17 +52,19 @@
/* dapm power sequences - make this per codec in the future */
static int dapm_up_seq[] = {
- snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic,
- snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_dac,
- snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_pga,
- snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, snd_soc_dapm_post
+ snd_soc_dapm_pre, snd_soc_dapm_supply, snd_soc_dapm_micbias,
+ snd_soc_dapm_mic, snd_soc_dapm_mux, snd_soc_dapm_value_mux,
+ snd_soc_dapm_dac, snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl,
+ snd_soc_dapm_pga, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
+ snd_soc_dapm_post
};
static int dapm_down_seq[] = {
snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer,
snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias,
- snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_post
+ snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_supply,
+ snd_soc_dapm_post
};
static int dapm_status = 1;
@@ -165,6 +167,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
case snd_soc_dapm_dac:
case snd_soc_dapm_micbias:
case snd_soc_dapm_vmid:
+ case snd_soc_dapm_supply:
p->connect = 1;
break;
/* does effect routing - dynamically connected */
@@ -357,8 +360,9 @@ static int dapm_new_mixer(struct snd_soc_codec *codec,
path->long_name);
ret = snd_ctl_add(codec->card, path->kcontrol);
if (ret < 0) {
- printk(KERN_ERR "asoc: failed to add dapm kcontrol %s\n",
- path->long_name);
+ printk(KERN_ERR "asoc: failed to add dapm kcontrol %s: %d\n",
+ path->long_name,
+ ret);
kfree(path->long_name);
path->long_name = NULL;
return ret;
@@ -434,6 +438,9 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
struct snd_soc_dapm_path *path;
int con = 0;
+ if (widget->id == snd_soc_dapm_supply)
+ return 0;
+
if (widget->id == snd_soc_dapm_adc && widget->active)
return 1;
@@ -470,6 +477,9 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
struct snd_soc_dapm_path *path;
int con = 0;
+ if (widget->id == snd_soc_dapm_supply)
+ return 0;
+
/* active stream ? */
if (widget->id == snd_soc_dapm_dac && widget->active)
return 1;
@@ -521,39 +531,137 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
}
EXPORT_SYMBOL_GPL(dapm_reg_event);
-/*
- * Scan a single DAPM widget for a complete audio path and update the
- * power status appropriately.
+/* Standard power change method, used to apply power changes to most
+ * widgets.
*/
-static int dapm_power_widget(struct snd_soc_codec *codec, int event,
- struct snd_soc_dapm_widget *w)
+static int dapm_generic_apply_power(struct snd_soc_dapm_widget *w)
{
- int in, out, power_change, power, ret;
+ int ret;
- /* vmid - no action */
- if (w->id == snd_soc_dapm_vmid)
- return 0;
+ /* call any power change event handlers */
+ if (w->event)
+ pr_debug("power %s event for %s flags %x\n",
+ w->power ? "on" : "off",
+ w->name, w->event_flags);
+
+ /* power up pre event */
+ if (w->power && w->event &&
+ (w->event_flags & SND_SOC_DAPM_PRE_PMU)) {
+ ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU);
+ if (ret < 0)
+ return ret;
+ }
- /* active ADC */
- if (w->id == snd_soc_dapm_adc && w->active) {
+ /* power down pre event */
+ if (!w->power && w->event &&
+ (w->event_flags & SND_SOC_DAPM_PRE_PMD)) {
+ ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* Lower PGA volume to reduce pops */
+ if (w->id == snd_soc_dapm_pga && !w->power)
+ dapm_set_pga(w, w->power);
+
+ dapm_update_bits(w);
+
+ /* Raise PGA volume to reduce pops */
+ if (w->id == snd_soc_dapm_pga && w->power)
+ dapm_set_pga(w, w->power);
+
+ /* power up post event */
+ if (w->power && w->event &&
+ (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
+ ret = w->event(w,
+ NULL, SND_SOC_DAPM_POST_PMU);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* power down post event */
+ if (!w->power && w->event &&
+ (w->event_flags & SND_SOC_DAPM_POST_PMD)) {
+ ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+/* Generic check to see if a widget should be powered.
+ */
+static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
+{
+ int in, out;
+
+ in = is_connected_input_ep(w);
+ dapm_clear_walk(w->codec);
+ out = is_connected_output_ep(w);
+ dapm_clear_walk(w->codec);
+ return out != 0 && in != 0;
+}
+
+/* Check to see if an ADC has power */
+static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
+{
+ int in;
+
+ if (w->active) {
in = is_connected_input_ep(w);
dapm_clear_walk(w->codec);
- w->power = (in != 0) ? 1 : 0;
- dapm_update_bits(w);
- return 0;
+ return in != 0;
+ } else {
+ return dapm_generic_check_power(w);
}
+}
- /* active DAC */
- if (w->id == snd_soc_dapm_dac && w->active) {
+/* Check to see if a DAC has power */
+static int dapm_dac_check_power(struct snd_soc_dapm_widget *w)
+{
+ int out;
+
+ if (w->active) {
out = is_connected_output_ep(w);
dapm_clear_walk(w->codec);
- w->power = (out != 0) ? 1 : 0;
- dapm_update_bits(w);
- return 0;
+ return out != 0;
+ } else {
+ return dapm_generic_check_power(w);
+ }
+}
+
+/* Check to see if a power supply is needed */
+static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
+{
+ struct snd_soc_dapm_path *path;
+ int power = 0;
+
+ /* Check if one of our outputs is connected */
+ list_for_each_entry(path, &w->sinks, list_source) {
+ if (path->sink && path->sink->power_check &&
+ path->sink->power_check(path->sink)) {
+ power = 1;
+ break;
+ }
}
- /* pre and post event widgets */
- if (w->id == snd_soc_dapm_pre) {
+ dapm_clear_walk(w->codec);
+
+ return power;
+}
+
+/*
+ * Scan a single DAPM widget for a complete audio path and update the
+ * power status appropriately.
+ */
+static int dapm_power_widget(struct snd_soc_codec *codec, int event,
+ struct snd_soc_dapm_widget *w)
+{
+ int power, ret;
+
+ switch (w->id) {
+ case snd_soc_dapm_pre:
if (!w->event)
return 0;
@@ -569,8 +677,8 @@ static int dapm_power_widget(struct snd_soc_codec *codec, int event,
return ret;
}
return 0;
- }
- if (w->id == snd_soc_dapm_post) {
+
+ case snd_soc_dapm_post:
if (!w->event)
return 0;
@@ -586,70 +694,20 @@ static int dapm_power_widget(struct snd_soc_codec *codec, int event,
return ret;
}
return 0;
- }
-
- /* all other widgets */
- in = is_connected_input_ep(w);
- dapm_clear_walk(w->codec);
- out = is_connected_output_ep(w);
- dapm_clear_walk(w->codec);
- power = (out != 0 && in != 0) ? 1 : 0;
- power_change = (w->power == power) ? 0 : 1;
- w->power = power;
- if (!power_change)
- return 0;
-
- /* call any power change event handlers */
- if (w->event)
- pr_debug("power %s event for %s flags %x\n",
- w->power ? "on" : "off",
- w->name, w->event_flags);
-
- /* power up pre event */
- if (power && w->event &&
- (w->event_flags & SND_SOC_DAPM_PRE_PMU)) {
- ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU);
- if (ret < 0)
- return ret;
- }
-
- /* power down pre event */
- if (!power && w->event &&
- (w->event_flags & SND_SOC_DAPM_PRE_PMD)) {
- ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD);
- if (ret < 0)
- return ret;
+ default:
+ break;
}
- /* Lower PGA volume to reduce pops */
- if (w->id == snd_soc_dapm_pga && !power)
- dapm_set_pga(w, power);
-
- dapm_update_bits(w);
-
- /* Raise PGA volume to reduce pops */
- if (w->id == snd_soc_dapm_pga && power)
- dapm_set_pga(w, power);
-
- /* power up post event */
- if (power && w->event &&
- (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
- ret = w->event(w,
- NULL, SND_SOC_DAPM_POST_PMU);
- if (ret < 0)
- return ret;
- }
+ if (!w->power_check)
+ return 0;
- /* power down post event */
- if (!power && w->event &&
- (w->event_flags & SND_SOC_DAPM_POST_PMD)) {
- ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD);
- if (ret < 0)
- return ret;
- }
+ power = w->power_check(w);
+ if (w->power == power)
+ return 0;
+ w->power = power;
- return 0;
+ return dapm_generic_apply_power(w);
}
/*
@@ -723,6 +781,7 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
case snd_soc_dapm_pga:
case snd_soc_dapm_mixer:
case snd_soc_dapm_mixer_named_ctl:
+ case snd_soc_dapm_supply:
if (w->name) {
in = is_connected_input_ep(w);
dapm_clear_walk(w->codec);
@@ -851,6 +910,7 @@ static ssize_t dapm_widget_show(struct device *dev,
case snd_soc_dapm_pga:
case snd_soc_dapm_mixer:
case snd_soc_dapm_mixer_named_ctl:
+ case snd_soc_dapm_supply:
if (w->name)
count += sprintf(buf + count, "%s: %s\n",
w->name, w->power ? "On":"Off");
@@ -1015,6 +1075,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
case snd_soc_dapm_vmid:
case snd_soc_dapm_pre:
case snd_soc_dapm_post:
+ case snd_soc_dapm_supply:
list_add(&path->list, &codec->dapm_paths);
list_add(&path->list_sink, &wsink->sources);
list_add(&path->list_source, &wsource->sinks);
@@ -1108,15 +1169,22 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec)
case snd_soc_dapm_switch:
case snd_soc_dapm_mixer:
case snd_soc_dapm_mixer_named_ctl:
+ w->power_check = dapm_generic_check_power;
dapm_new_mixer(codec, w);
break;
case snd_soc_dapm_mux:
case snd_soc_dapm_value_mux:
+ w->power_check = dapm_generic_check_power;
dapm_new_mux(codec, w);
break;
case snd_soc_dapm_adc:
+ w->power_check = dapm_adc_check_power;
+ break;
case snd_soc_dapm_dac:
+ w->power_check = dapm_dac_check_power;
+ break;
case snd_soc_dapm_pga:
+ w->power_check = dapm_generic_check_power;
dapm_new_pga(codec, w);
break;
case snd_soc_dapm_input:
@@ -1126,6 +1194,10 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec)
case snd_soc_dapm_hp:
case snd_soc_dapm_mic:
case snd_soc_dapm_line:
+ w->power_check = dapm_generic_check_power;
+ break;
+ case snd_soc_dapm_supply:
+ w->power_check = dapm_supply_check_power;
case snd_soc_dapm_vmid:
case snd_soc_dapm_pre:
case snd_soc_dapm_post:
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index af95ff1e126c..1d2e51b3f918 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -1975,7 +1975,8 @@ 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,
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH,
.formats = SNDRV_PCM_FMTBIT_MU_LAW |
SNDRV_PCM_FMTBIT_A_LAW |
SNDRV_PCM_FMTBIT_U8 |
diff --git a/sound/usb/caiaq/Makefile b/sound/usb/caiaq/Makefile
index 23dadd5a11cd..388999653aaa 100644
--- a/sound/usb/caiaq/Makefile
+++ b/sound/usb/caiaq/Makefile
@@ -1,4 +1,4 @@
-snd-usb-caiaq-y := caiaq-device.o caiaq-audio.o caiaq-midi.o caiaq-control.o
-snd-usb-caiaq-$(CONFIG_SND_USB_CAIAQ_INPUT) += caiaq-input.o
+snd-usb-caiaq-y := device.o audio.o midi.o control.o
+snd-usb-caiaq-$(CONFIG_SND_USB_CAIAQ_INPUT) += input.o
obj-$(CONFIG_SND_USB_CAIAQ) += snd-usb-caiaq.o
diff --git a/sound/usb/caiaq/caiaq-audio.c b/sound/usb/caiaq/audio.c
index 08d51e0c9fea..b13ce767ac72 100644
--- a/sound/usb/caiaq/caiaq-audio.c
+++ b/sound/usb/caiaq/audio.c
@@ -16,20 +16,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/spinlock.h>
#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/interrupt.h>
#include <linux/usb.h>
-#include <linux/spinlock.h>
#include <sound/core.h>
-#include <sound/initval.h>
#include <sound/pcm.h>
-#include <sound/rawmidi.h>
-#include <linux/input.h>
-#include "caiaq-device.h"
-#include "caiaq-audio.h"
+#include "device.h"
+#include "audio.h"
#define N_URBS 32
#define CLOCK_DRIFT_TOLERANCE 5
@@ -201,11 +195,14 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
debug("%s(%p)\n", __func__, substream);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ dev->period_out_count[index] = BYTES_PER_SAMPLE + 1;
dev->audio_out_buf_pos[index] = BYTES_PER_SAMPLE + 1;
- else
+ } else {
+ dev->period_in_count[index] = BYTES_PER_SAMPLE;
dev->audio_in_buf_pos[index] = BYTES_PER_SAMPLE;
-
+ }
+
if (dev->streaming)
return 0;
@@ -306,8 +303,7 @@ static void check_for_elapsed_periods(struct snd_usb_caiaqdev *dev,
if (!sub)
continue;
- pb = frames_to_bytes(sub->runtime,
- sub->runtime->period_size);
+ pb = snd_pcm_lib_period_bytes(sub);
cnt = (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
&dev->period_out_count[stream] :
&dev->period_in_count[stream];
diff --git a/sound/usb/caiaq/caiaq-audio.h b/sound/usb/caiaq/audio.h
index 8ab1f8d9529e..8ab1f8d9529e 100644
--- a/sound/usb/caiaq/caiaq-audio.h
+++ b/sound/usb/caiaq/audio.h
diff --git a/sound/usb/caiaq/caiaq-control.c b/sound/usb/caiaq/control.c
index e92c2bbf4fe9..537102ba6b9d 100644
--- a/sound/usb/caiaq/caiaq-control.c
+++ b/sound/usb/caiaq/control.c
@@ -18,17 +18,13 @@
*/
#include <linux/init.h>
-#include <linux/interrupt.h>
#include <linux/usb.h>
+#include <sound/control.h>
#include <sound/core.h>
-#include <sound/initval.h>
#include <sound/pcm.h>
-#include <sound/rawmidi.h>
-#include <sound/control.h>
-#include <linux/input.h>
-#include "caiaq-device.h"
-#include "caiaq-control.h"
+#include "device.h"
+#include "control.h"
#define CNT_INTVAL 0x10000
diff --git a/sound/usb/caiaq/caiaq-control.h b/sound/usb/caiaq/control.h
index 2e7ab1aa4fb3..2e7ab1aa4fb3 100644
--- a/sound/usb/caiaq/caiaq-control.h
+++ b/sound/usb/caiaq/control.h
diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/device.c
index cf573a982fdc..515de1cd2a3e 100644
--- a/sound/usb/caiaq/caiaq-device.c
+++ b/sound/usb/caiaq/device.c
@@ -19,30 +19,23 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/init.h>
-#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/init.h>
#include <linux/usb.h>
-#include <linux/input.h>
-#include <linux/spinlock.h>
-#include <sound/core.h>
#include <sound/initval.h>
+#include <sound/core.h>
#include <sound/pcm.h>
-#include <sound/rawmidi.h>
-#include <sound/control.h>
-
-#include "caiaq-device.h"
-#include "caiaq-audio.h"
-#include "caiaq-midi.h"
-#include "caiaq-control.h"
-#ifdef CONFIG_SND_USB_CAIAQ_INPUT
-#include "caiaq-input.h"
-#endif
+#include "device.h"
+#include "audio.h"
+#include "midi.h"
+#include "control.h"
+#include "input.h"
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
-MODULE_DESCRIPTION("caiaq USB audio, version 1.3.13");
+MODULE_DESCRIPTION("caiaq USB audio, version 1.3.14");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
"{Native Instruments, RigKontrol3},"
diff --git a/sound/usb/caiaq/caiaq-device.h b/sound/usb/caiaq/device.h
index 4cce1ad7493d..4cce1ad7493d 100644
--- a/sound/usb/caiaq/caiaq-device.h
+++ b/sound/usb/caiaq/device.h
diff --git a/sound/usb/caiaq/caiaq-input.c b/sound/usb/caiaq/input.c
index f743847a5e5a..a48d309bd94c 100644
--- a/sound/usb/caiaq/caiaq-input.c
+++ b/sound/usb/caiaq/input.c
@@ -17,17 +17,12 @@
*/
#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/input.h>
#include <linux/usb.h>
#include <linux/usb/input.h>
-#include <linux/spinlock.h>
-#include <sound/core.h>
-#include <sound/rawmidi.h>
#include <sound/pcm.h>
-#include "caiaq-device.h"
-#include "caiaq-input.h"
+
+#include "device.h"
+#include "input.h"
static unsigned short keycode_ak1[] = { KEY_C, KEY_B, KEY_A };
static unsigned short keycode_rk2[] = { KEY_1, KEY_2, KEY_3, KEY_4,
diff --git a/sound/usb/caiaq/caiaq-input.h b/sound/usb/caiaq/input.h
index ced535577864..ced535577864 100644
--- a/sound/usb/caiaq/caiaq-input.h
+++ b/sound/usb/caiaq/input.h
diff --git a/sound/usb/caiaq/caiaq-midi.c b/sound/usb/caiaq/midi.c
index f19fd360c936..8fa8cd88d763 100644
--- a/sound/usb/caiaq/caiaq-midi.c
+++ b/sound/usb/caiaq/midi.c
@@ -16,20 +16,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/interrupt.h>
#include <linux/usb.h>
-#include <linux/input.h>
-#include <linux/spinlock.h>
-#include <sound/core.h>
#include <sound/rawmidi.h>
+#include <sound/core.h>
#include <sound/pcm.h>
-#include "caiaq-device.h"
-#include "caiaq-midi.h"
-
+#include "device.h"
+#include "midi.h"
static int snd_usb_caiaq_midi_input_open(struct snd_rawmidi_substream *substream)
{
diff --git a/sound/usb/caiaq/caiaq-midi.h b/sound/usb/caiaq/midi.h
index 9d16db027fc3..9d16db027fc3 100644
--- a/sound/usb/caiaq/caiaq-midi.h
+++ b/sound/usb/caiaq/midi.h
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 823296d7d578..6c25fa23f702 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -627,6 +627,7 @@ static int prepare_playback_urb(struct snd_usb_substream *subs,
subs->hwptr_done += offs;
if (subs->hwptr_done >= runtime->buffer_size)
subs->hwptr_done -= runtime->buffer_size;
+ runtime->delay += offs;
spin_unlock_irqrestore(&subs->lock, flags);
urb->transfer_buffer_length = offs * stride;
if (period_elapsed)
@@ -636,12 +637,22 @@ static int prepare_playback_urb(struct snd_usb_substream *subs,
/*
* process after playback data complete
- * - nothing to do
+ * - decrease the delay count again
*/
static int retire_playback_urb(struct snd_usb_substream *subs,
struct snd_pcm_runtime *runtime,
struct urb *urb)
{
+ unsigned long flags;
+ int stride = runtime->frame_bits >> 3;
+ int processed = urb->transfer_buffer_length / stride;
+
+ spin_lock_irqsave(&subs->lock, flags);
+ if (processed > runtime->delay)
+ runtime->delay = 0;
+ else
+ runtime->delay -= processed;
+ spin_unlock_irqrestore(&subs->lock, flags);
return 0;
}
@@ -1520,6 +1531,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
subs->hwptr_done = 0;
subs->transfer_done = 0;
subs->phase = 0;
+ runtime->delay = 0;
/* clear urbs (to be sure) */
deactivate_urbs(subs, 0, 1);
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index ecb58e7a6245..4bd3a7a0edc1 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -423,7 +423,7 @@ static int set_ctl_value(struct usb_mixer_elem_info *cval, int request, int vali
value_set = convert_bytes_value(cval, value_set);
buf[0] = value_set & 0xff;
buf[1] = (value_set >> 8) & 0xff;
- while (timeout -- > 0)
+ while (timeout-- > 0)
if (snd_usb_ctl_msg(cval->mixer->chip->dev,
usb_sndctrlpipe(cval->mixer->chip->dev, 0),
request,
diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c
index 98276aafefe6..a5aae9d67f31 100644
--- a/sound/usb/usx2y/us122l.c
+++ b/sound/usb/usx2y/us122l.c
@@ -349,14 +349,10 @@ static int usb_stream_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
if (cmd != SNDRV_USB_STREAM_IOCTL_SET_PARAMS)
return -ENOTTY;
- cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
- if (!cfg)
- return -ENOMEM;
+ cfg = memdup_user((void *)arg, sizeof(*cfg));
+ if (IS_ERR(cfg))
+ return PTR_ERR(cfg);
- if (copy_from_user(cfg, (void *)arg, sizeof(*cfg))) {
- err = -EFAULT;
- goto free;
- }
if (cfg->version != USB_STREAM_INTERFACE_VERSION) {
err = -ENXIO;
goto free;
@@ -478,6 +474,14 @@ static bool us122l_create_card(struct snd_card *card)
return true;
}
+static void snd_us122l_free(struct snd_card *card)
+{
+ struct us122l *us122l = US122L(card);
+ int index = us122l->chip.index;
+ if (index >= 0 && index < SNDRV_CARDS)
+ snd_us122l_card_used[index] = 0;
+}
+
static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp)
{
int dev;
@@ -494,7 +498,7 @@ static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp)
if (err < 0)
return err;
snd_us122l_card_used[US122L(card)->chip.index = dev] = 1;
-
+ card->private_free = snd_us122l_free;
US122L(card)->chip.dev = device;
US122L(card)->chip.card = card;
mutex_init(&US122L(card)->mutex);
@@ -588,7 +592,7 @@ static void snd_us122l_disconnect(struct usb_interface *intf)
}
usb_put_intf(intf);
- usb_put_dev(US122L(card)->chip.dev);
+ usb_put_dev(us122l->chip.dev);
while (atomic_read(&us122l->mmap_count))
msleep(500);
diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c
index 4af8740db717..f3d8f71265dd 100644
--- a/sound/usb/usx2y/usX2Yhwdep.c
+++ b/sound/usb/usx2y/usX2Yhwdep.c
@@ -203,13 +203,12 @@ static int snd_usX2Y_hwdep_dsp_load(struct snd_hwdep *hw,
if (access_ok(VERIFY_READ, dsp->image, dsp->length)) {
struct usb_device* dev = priv->chip.dev;
- char *buf = kmalloc(dsp->length, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
- if (copy_from_user(buf, dsp->image, dsp->length)) {
- kfree(buf);
- return -EFAULT;
- }
+ char *buf;
+
+ buf = memdup_user(dsp->image, dsp->length);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
+
err = usb_set_interface(dev, 0, 1);
if (err)
snd_printk(KERN_ERR "usb_set_interface error \n");
diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c
index 24393dafcb6e..12ae0340adc0 100644
--- a/sound/usb/usx2y/usb_stream.c
+++ b/sound/usb/usx2y/usb_stream.c
@@ -33,32 +33,26 @@ static unsigned usb_stream_next_packet_size(struct usb_stream_kernel *sk)
static void playback_prep_freqn(struct usb_stream_kernel *sk, struct urb *urb)
{
struct usb_stream *s = sk->s;
- unsigned l = 0;
- int pack;
-
- urb->iso_frame_desc[0].offset = 0;
- urb->iso_frame_desc[0].length = usb_stream_next_packet_size(sk);
- sk->out_phase = sk->out_phase_peeked;
- urb->transfer_buffer_length = urb->iso_frame_desc[0].length;
-
- for (pack = 1; pack < sk->n_o_ps; pack++) {
- l = usb_stream_next_packet_size(sk);
- if (s->idle_outsize + urb->transfer_buffer_length + l >
- s->period_size)
+ int pack, lb = 0;
+
+ for (pack = 0; pack < sk->n_o_ps; pack++) {
+ int l = usb_stream_next_packet_size(sk);
+ if (s->idle_outsize + lb + l > s->period_size)
goto check;
sk->out_phase = sk->out_phase_peeked;
- urb->iso_frame_desc[pack].offset = urb->transfer_buffer_length;
+ urb->iso_frame_desc[pack].offset = lb;
urb->iso_frame_desc[pack].length = l;
- urb->transfer_buffer_length += l;
+ lb += l;
}
- snd_printdd(KERN_DEBUG "%i\n", urb->transfer_buffer_length);
+ snd_printdd(KERN_DEBUG "%i\n", lb);
check:
urb->number_of_packets = pack;
- s->idle_outsize += urb->transfer_buffer_length - s->period_size;
+ urb->transfer_buffer_length = lb;
+ s->idle_outsize += lb - s->period_size;
snd_printdd(KERN_DEBUG "idle=%i ul=%i ps=%i\n", s->idle_outsize,
- urb->transfer_buffer_length, s->period_size);
+ lb, s->period_size);
}
static void init_pipe_urbs(struct usb_stream_kernel *sk, unsigned use_packsize,
@@ -282,21 +276,20 @@ static int usb_stream_prepare_playback(struct usb_stream_kernel *sk,
struct usb_stream *s = sk->s;
struct urb *io;
struct usb_iso_packet_descriptor *id, *od;
- int p, l = 0;
+ int p = 0, lb = 0, l = 0;
io = sk->idle_outurb;
od = io->iso_frame_desc;
- io->transfer_buffer_length = 0;
- for (p = 0; s->sync_packet < 0; ++p, ++s->sync_packet) {
+ for (; s->sync_packet < 0; ++p, ++s->sync_packet) {
struct urb *ii = sk->completed_inurb;
id = ii->iso_frame_desc +
ii->number_of_packets + s->sync_packet;
l = id->actual_length;
od[p].length = l;
- od[p].offset = io->transfer_buffer_length;
- io->transfer_buffer_length += l;
+ od[p].offset = lb;
+ lb += l;
}
for (;
@@ -304,38 +297,38 @@ static int usb_stream_prepare_playback(struct usb_stream_kernel *sk,
++p, ++s->sync_packet) {
l = inurb->iso_frame_desc[s->sync_packet].actual_length;
- if (s->idle_outsize + io->transfer_buffer_length + l >
- s->period_size)
+ if (s->idle_outsize + lb + l > s->period_size)
goto check_ok;
od[p].length = l;
- od[p].offset = io->transfer_buffer_length;
- io->transfer_buffer_length += l;
+ od[p].offset = lb;
+ lb += l;
}
check_ok:
s->sync_packet -= inurb->number_of_packets;
- if (s->sync_packet < -2 || s->sync_packet > 0) {
+ if (unlikely(s->sync_packet < -2 || s->sync_packet > 0)) {
snd_printk(KERN_WARNING "invalid sync_packet = %i;"
" p=%i nop=%i %i %x %x %x > %x\n",
s->sync_packet, p, inurb->number_of_packets,
- s->idle_outsize + io->transfer_buffer_length + l,
- s->idle_outsize, io->transfer_buffer_length, l,
+ s->idle_outsize + lb + l,
+ s->idle_outsize, lb, l,
s->period_size);
return -1;
}
- if (io->transfer_buffer_length % s->cfg.frame_size) {
+ if (unlikely(lb % s->cfg.frame_size)) {
snd_printk(KERN_WARNING"invalid outsize = %i\n",
- io->transfer_buffer_length);
+ lb);
return -1;
}
- s->idle_outsize += io->transfer_buffer_length - s->period_size;
+ s->idle_outsize += lb - s->period_size;
io->number_of_packets = p;
- if (s->idle_outsize > 0) {
- snd_printk(KERN_WARNING "idle=%i\n", s->idle_outsize);
- return -1;
- }
- return 0;
+ io->transfer_buffer_length = lb;
+ if (s->idle_outsize <= 0)
+ return 0;
+
+ snd_printk(KERN_WARNING "idle=%i\n", s->idle_outsize);
+ return -1;
}
static void prepare_inurb(int number_of_packets, struct urb *iu)
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index 9a608fa85155..dd1ab6177840 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -870,7 +870,8 @@ static struct snd_pcm_hardware snd_usX2Y_2c =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID),
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH),
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE,
.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
.rate_min = 44100,
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index c3b99def9cbc..1eddae94bab3 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -85,7 +85,7 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic,
static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx)
{
- union ioapic_redir_entry *pent;
+ union kvm_ioapic_redirect_entry *pent;
int injected = -1;
pent = &ioapic->redirtbl[idx];
@@ -142,149 +142,40 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
}
}
-static int ioapic_inj_irq(struct kvm_ioapic *ioapic,
- struct kvm_vcpu *vcpu,
- u8 vector, u8 trig_mode, u8 delivery_mode)
-{
- ioapic_debug("irq %d trig %d deliv %d\n", vector, trig_mode,
- delivery_mode);
-
- ASSERT((delivery_mode == IOAPIC_FIXED) ||
- (delivery_mode == IOAPIC_LOWEST_PRIORITY));
-
- return kvm_apic_set_irq(vcpu, vector, trig_mode);
-}
-
-static void ioapic_inj_nmi(struct kvm_vcpu *vcpu)
-{
- kvm_inject_nmi(vcpu);
- kvm_vcpu_kick(vcpu);
-}
-
-u32 kvm_ioapic_get_delivery_bitmask(struct kvm_ioapic *ioapic, u8 dest,
- u8 dest_mode)
-{
- u32 mask = 0;
- int i;
- struct kvm *kvm = ioapic->kvm;
- struct kvm_vcpu *vcpu;
-
- ioapic_debug("dest %d dest_mode %d\n", dest, dest_mode);
-
- if (dest_mode == 0) { /* Physical mode. */
- if (dest == 0xFF) { /* Broadcast. */
- for (i = 0; i < KVM_MAX_VCPUS; ++i)
- if (kvm->vcpus[i] && kvm->vcpus[i]->arch.apic)
- mask |= 1 << i;
- return mask;
- }
- for (i = 0; i < KVM_MAX_VCPUS; ++i) {
- vcpu = kvm->vcpus[i];
- if (!vcpu)
- continue;
- if (kvm_apic_match_physical_addr(vcpu->arch.apic, dest)) {
- if (vcpu->arch.apic)
- mask = 1 << i;
- break;
- }
- }
- } else if (dest != 0) /* Logical mode, MDA non-zero. */
- for (i = 0; i < KVM_MAX_VCPUS; ++i) {
- vcpu = kvm->vcpus[i];
- if (!vcpu)
- continue;
- if (vcpu->arch.apic &&
- kvm_apic_match_logical_addr(vcpu->arch.apic, dest))
- mask |= 1 << vcpu->vcpu_id;
- }
- ioapic_debug("mask %x\n", mask);
- return mask;
-}
-
static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
{
- u8 dest = ioapic->redirtbl[irq].fields.dest_id;
- u8 dest_mode = ioapic->redirtbl[irq].fields.dest_mode;
- u8 delivery_mode = ioapic->redirtbl[irq].fields.delivery_mode;
- u8 vector = ioapic->redirtbl[irq].fields.vector;
- u8 trig_mode = ioapic->redirtbl[irq].fields.trig_mode;
- u32 deliver_bitmask;
- struct kvm_vcpu *vcpu;
- int vcpu_id, r = -1;
+ union kvm_ioapic_redirect_entry *entry = &ioapic->redirtbl[irq];
+ struct kvm_lapic_irq irqe;
ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x "
"vector=%x trig_mode=%x\n",
- dest, dest_mode, delivery_mode, vector, trig_mode);
-
- deliver_bitmask = kvm_ioapic_get_delivery_bitmask(ioapic, dest,
- dest_mode);
- if (!deliver_bitmask) {
- ioapic_debug("no target on destination\n");
- return 0;
- }
+ entry->fields.dest, entry->fields.dest_mode,
+ entry->fields.delivery_mode, entry->fields.vector,
+ entry->fields.trig_mode);
+
+ irqe.dest_id = entry->fields.dest_id;
+ irqe.vector = entry->fields.vector;
+ irqe.dest_mode = entry->fields.dest_mode;
+ irqe.trig_mode = entry->fields.trig_mode;
+ irqe.delivery_mode = entry->fields.delivery_mode << 8;
+ irqe.level = 1;
+ irqe.shorthand = 0;
- switch (delivery_mode) {
- case IOAPIC_LOWEST_PRIORITY:
- vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm, vector,
- deliver_bitmask);
#ifdef CONFIG_X86
- if (irq == 0)
- vcpu = ioapic->kvm->vcpus[0];
-#endif
- if (vcpu != NULL)
- r = ioapic_inj_irq(ioapic, vcpu, vector,
- trig_mode, delivery_mode);
- else
- ioapic_debug("null lowest prio vcpu: "
- "mask=%x vector=%x delivery_mode=%x\n",
- deliver_bitmask, vector, IOAPIC_LOWEST_PRIORITY);
- break;
- case IOAPIC_FIXED:
-#ifdef CONFIG_X86
- if (irq == 0)
- deliver_bitmask = 1;
-#endif
- for (vcpu_id = 0; deliver_bitmask != 0; vcpu_id++) {
- if (!(deliver_bitmask & (1 << vcpu_id)))
- continue;
- deliver_bitmask &= ~(1 << vcpu_id);
- vcpu = ioapic->kvm->vcpus[vcpu_id];
- if (vcpu) {
- if (r < 0)
- r = 0;
- r += ioapic_inj_irq(ioapic, vcpu, vector,
- trig_mode, delivery_mode);
- }
- }
- break;
- case IOAPIC_NMI:
- for (vcpu_id = 0; deliver_bitmask != 0; vcpu_id++) {
- if (!(deliver_bitmask & (1 << vcpu_id)))
- continue;
- deliver_bitmask &= ~(1 << vcpu_id);
- vcpu = ioapic->kvm->vcpus[vcpu_id];
- if (vcpu) {
- ioapic_inj_nmi(vcpu);
- r = 1;
- }
- else
- ioapic_debug("NMI to vcpu %d failed\n",
- vcpu->vcpu_id);
- }
- break;
- default:
- printk(KERN_WARNING "Unsupported delivery mode %d\n",
- delivery_mode);
- break;
+ /* Always delivery PIT interrupt to vcpu 0 */
+ if (irq == 0) {
+ irqe.dest_mode = 0; /* Physical mode. */
+ irqe.dest_id = ioapic->kvm->vcpus[0]->vcpu_id;
}
- return r;
+#endif
+ return kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe);
}
int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
{
u32 old_irr = ioapic->irr;
u32 mask = 1 << irq;
- union ioapic_redir_entry entry;
+ union kvm_ioapic_redirect_entry entry;
int ret = 1;
if (irq >= 0 && irq < IOAPIC_NUM_PINS) {
@@ -305,7 +196,7 @@ int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int pin,
int trigger_mode)
{
- union ioapic_redir_entry *ent;
+ union kvm_ioapic_redirect_entry *ent;
ent = &ioapic->redirtbl[pin];
diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h
index a34bd5e6436b..7080b713c160 100644
--- a/virt/kvm/ioapic.h
+++ b/virt/kvm/ioapic.h
@@ -40,22 +40,7 @@ struct kvm_ioapic {
u32 id;
u32 irr;
u32 pad;
- union ioapic_redir_entry {
- u64 bits;
- struct {
- u8 vector;
- u8 delivery_mode:3;
- u8 dest_mode:1;
- u8 delivery_status:1;
- u8 polarity:1;
- u8 remote_irr:1;
- u8 trig_mode:1;
- u8 mask:1;
- u8 reserve:7;
- u8 reserved[4];
- u8 dest_id;
- } fields;
- } redirtbl[IOAPIC_NUM_PINS];
+ union kvm_ioapic_redirect_entry redirtbl[IOAPIC_NUM_PINS];
struct kvm_io_device dev;
struct kvm *kvm;
void (*ack_notifier)(void *opaque, int irq);
@@ -79,13 +64,13 @@ static inline struct kvm_ioapic *ioapic_irqchip(struct kvm *kvm)
return kvm->arch.vioapic;
}
-struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
- unsigned long bitmap);
+int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
+ int short_hand, int dest, int dest_mode);
+int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2);
void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode);
int kvm_ioapic_init(struct kvm *kvm);
int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
void kvm_ioapic_reset(struct kvm_ioapic *ioapic);
-u32 kvm_ioapic_get_delivery_bitmask(struct kvm_ioapic *ioapic, u8 dest,
- u8 dest_mode);
-
+int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,
+ struct kvm_lapic_irq *irq);
#endif
diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c
index 4c4037503600..15147583abd1 100644
--- a/virt/kvm/iommu.c
+++ b/virt/kvm/iommu.c
@@ -39,11 +39,16 @@ int kvm_iommu_map_pages(struct kvm *kvm,
pfn_t pfn;
int i, r = 0;
struct iommu_domain *domain = kvm->arch.iommu_domain;
+ int flags;
/* check if iommu exists and in use */
if (!domain)
return 0;
+ flags = IOMMU_READ | IOMMU_WRITE;
+ if (kvm->arch.iommu_flags & KVM_IOMMU_CACHE_COHERENCY)
+ flags |= IOMMU_CACHE;
+
for (i = 0; i < npages; i++) {
/* check if already mapped */
if (iommu_iova_to_phys(domain, gfn_to_gpa(gfn)))
@@ -53,8 +58,7 @@ int kvm_iommu_map_pages(struct kvm *kvm,
r = iommu_map_range(domain,
gfn_to_gpa(gfn),
pfn_to_hpa(pfn),
- PAGE_SIZE,
- IOMMU_READ | IOMMU_WRITE);
+ PAGE_SIZE, flags);
if (r) {
printk(KERN_ERR "kvm_iommu_map_address:"
"iommu failed to map pfn=%lx\n", pfn);
@@ -88,7 +92,7 @@ int kvm_assign_device(struct kvm *kvm,
{
struct pci_dev *pdev = NULL;
struct iommu_domain *domain = kvm->arch.iommu_domain;
- int r;
+ int r, last_flags;
/* check if iommu exists and in use */
if (!domain)
@@ -107,12 +111,29 @@ int kvm_assign_device(struct kvm *kvm,
return r;
}
+ last_flags = kvm->arch.iommu_flags;
+ if (iommu_domain_has_cap(kvm->arch.iommu_domain,
+ IOMMU_CAP_CACHE_COHERENCY))
+ kvm->arch.iommu_flags |= KVM_IOMMU_CACHE_COHERENCY;
+
+ /* Check if need to update IOMMU page table for guest memory */
+ if ((last_flags ^ kvm->arch.iommu_flags) ==
+ KVM_IOMMU_CACHE_COHERENCY) {
+ kvm_iommu_unmap_memslots(kvm);
+ r = kvm_iommu_map_memslots(kvm);
+ if (r)
+ goto out_unmap;
+ }
+
printk(KERN_DEBUG "assign device: host bdf = %x:%x:%x\n",
assigned_dev->host_busnr,
PCI_SLOT(assigned_dev->host_devfn),
PCI_FUNC(assigned_dev->host_devfn));
return 0;
+out_unmap:
+ kvm_iommu_unmap_memslots(kvm);
+ return r;
}
int kvm_deassign_device(struct kvm *kvm,
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
index 864ac5483baa..a8bd466d00cc 100644
--- a/virt/kvm/irq_comm.c
+++ b/virt/kvm/irq_comm.c
@@ -22,6 +22,9 @@
#include <linux/kvm_host.h>
#include <asm/msidef.h>
+#ifdef CONFIG_IA64
+#include <asm/iosapic.h>
+#endif
#include "irq.h"
@@ -43,57 +46,73 @@ static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e,
return kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level);
}
-static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
- struct kvm *kvm, int level)
+inline static bool kvm_is_dm_lowest_prio(struct kvm_lapic_irq *irq)
{
- int vcpu_id, r = -1;
- struct kvm_vcpu *vcpu;
- struct kvm_ioapic *ioapic = ioapic_irqchip(kvm);
- int dest_id = (e->msi.address_lo & MSI_ADDR_DEST_ID_MASK)
- >> MSI_ADDR_DEST_ID_SHIFT;
- int vector = (e->msi.data & MSI_DATA_VECTOR_MASK)
- >> MSI_DATA_VECTOR_SHIFT;
- int dest_mode = test_bit(MSI_ADDR_DEST_MODE_SHIFT,
- (unsigned long *)&e->msi.address_lo);
- int trig_mode = test_bit(MSI_DATA_TRIGGER_SHIFT,
- (unsigned long *)&e->msi.data);
- int delivery_mode = test_bit(MSI_DATA_DELIVERY_MODE_SHIFT,
- (unsigned long *)&e->msi.data);
- u32 deliver_bitmask;
-
- BUG_ON(!ioapic);
-
- deliver_bitmask = kvm_ioapic_get_delivery_bitmask(ioapic,
- dest_id, dest_mode);
- /* IOAPIC delivery mode value is the same as MSI here */
- switch (delivery_mode) {
- case IOAPIC_LOWEST_PRIORITY:
- vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm, vector,
- deliver_bitmask);
- if (vcpu != NULL)
- r = kvm_apic_set_irq(vcpu, vector, trig_mode);
- else
- printk(KERN_INFO "kvm: null lowest priority vcpu!\n");
- break;
- case IOAPIC_FIXED:
- for (vcpu_id = 0; deliver_bitmask != 0; vcpu_id++) {
- if (!(deliver_bitmask & (1 << vcpu_id)))
- continue;
- deliver_bitmask &= ~(1 << vcpu_id);
- vcpu = ioapic->kvm->vcpus[vcpu_id];
- if (vcpu) {
- if (r < 0)
- r = 0;
- r += kvm_apic_set_irq(vcpu, vector, trig_mode);
- }
+#ifdef CONFIG_IA64
+ return irq->delivery_mode ==
+ (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT);
+#else
+ return irq->delivery_mode == APIC_DM_LOWEST;
+#endif
+}
+
+int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,
+ struct kvm_lapic_irq *irq)
+{
+ int i, r = -1;
+ struct kvm_vcpu *vcpu, *lowest = NULL;
+
+ if (irq->dest_mode == 0 && irq->dest_id == 0xff &&
+ kvm_is_dm_lowest_prio(irq))
+ printk(KERN_INFO "kvm: apic: phys broadcast and lowest prio\n");
+
+ for (i = 0; i < KVM_MAX_VCPUS; i++) {
+ vcpu = kvm->vcpus[i];
+
+ if (!vcpu || !kvm_apic_present(vcpu))
+ continue;
+
+ if (!kvm_apic_match_dest(vcpu, src, irq->shorthand,
+ irq->dest_id, irq->dest_mode))
+ continue;
+
+ if (!kvm_is_dm_lowest_prio(irq)) {
+ if (r < 0)
+ r = 0;
+ r += kvm_apic_set_irq(vcpu, irq);
+ } else {
+ if (!lowest)
+ lowest = vcpu;
+ else if (kvm_apic_compare_prio(vcpu, lowest) < 0)
+ lowest = vcpu;
}
- break;
- default:
- break;
}
+
+ if (lowest)
+ r = kvm_apic_set_irq(lowest, irq);
+
return r;
}
+static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
+ struct kvm *kvm, int level)
+{
+ struct kvm_lapic_irq irq;
+
+ irq.dest_id = (e->msi.address_lo &
+ MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
+ irq.vector = (e->msi.data &
+ MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT;
+ irq.dest_mode = (1 << MSI_ADDR_DEST_MODE_SHIFT) & e->msi.address_lo;
+ irq.trig_mode = (1 << MSI_DATA_TRIGGER_SHIFT) & e->msi.data;
+ irq.delivery_mode = e->msi.data & 0x700;
+ irq.level = 1;
+ irq.shorthand = 0;
+
+ /* TODO Deal with RH bit of MSI message address */
+ return kvm_irq_delivery_to_apic(kvm, NULL, &irq);
+}
+
/* This should be called with the kvm->lock mutex held
* Return value:
* < 0 Interrupt was ignored (masked or not delivered for other reasons)
@@ -252,7 +271,7 @@ static int setup_routing_entry(struct kvm_kernel_irq_routing_entry *e,
delta = 8;
break;
case KVM_IRQCHIP_IOAPIC:
- e->set = kvm_set_ioapic_irq;
+ e->set = kvm_set_ioapic_irq;
break;
default:
goto out;
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 605697e9c4dd..4d00942e5d0a 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -41,6 +41,8 @@
#include <linux/pagemap.h>
#include <linux/mman.h>
#include <linux/swap.h>
+#include <linux/bitops.h>
+#include <linux/spinlock.h>
#include <asm/processor.h>
#include <asm/io.h>
@@ -60,9 +62,6 @@
MODULE_AUTHOR("Qumranet");
MODULE_LICENSE("GPL");
-static int msi2intx = 1;
-module_param(msi2intx, bool, 0);
-
DEFINE_SPINLOCK(kvm_lock);
LIST_HEAD(vm_list);
@@ -95,38 +94,96 @@ static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct list_head *h
return NULL;
}
+static int find_index_from_host_irq(struct kvm_assigned_dev_kernel
+ *assigned_dev, int irq)
+{
+ int i, index;
+ struct msix_entry *host_msix_entries;
+
+ host_msix_entries = assigned_dev->host_msix_entries;
+
+ index = -1;
+ for (i = 0; i < assigned_dev->entries_nr; i++)
+ if (irq == host_msix_entries[i].vector) {
+ index = i;
+ break;
+ }
+ if (index < 0) {
+ printk(KERN_WARNING "Fail to find correlated MSI-X entry!\n");
+ return 0;
+ }
+
+ return index;
+}
+
static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work)
{
struct kvm_assigned_dev_kernel *assigned_dev;
+ struct kvm *kvm;
+ int irq, i;
assigned_dev = container_of(work, struct kvm_assigned_dev_kernel,
interrupt_work);
+ kvm = assigned_dev->kvm;
/* This is taken to safely inject irq inside the guest. When
* the interrupt injection (or the ioapic code) uses a
* finer-grained lock, update this
*/
- mutex_lock(&assigned_dev->kvm->lock);
- kvm_set_irq(assigned_dev->kvm, assigned_dev->irq_source_id,
- assigned_dev->guest_irq, 1);
-
- if (assigned_dev->irq_requested_type & KVM_ASSIGNED_DEV_GUEST_MSI) {
- enable_irq(assigned_dev->host_irq);
- assigned_dev->host_irq_disabled = false;
+ mutex_lock(&kvm->lock);
+ spin_lock_irq(&assigned_dev->assigned_dev_lock);
+ if (assigned_dev->irq_requested_type & KVM_DEV_IRQ_HOST_MSIX) {
+ struct kvm_guest_msix_entry *guest_entries =
+ assigned_dev->guest_msix_entries;
+ for (i = 0; i < assigned_dev->entries_nr; i++) {
+ if (!(guest_entries[i].flags &
+ KVM_ASSIGNED_MSIX_PENDING))
+ continue;
+ guest_entries[i].flags &= ~KVM_ASSIGNED_MSIX_PENDING;
+ kvm_set_irq(assigned_dev->kvm,
+ assigned_dev->irq_source_id,
+ guest_entries[i].vector, 1);
+ irq = assigned_dev->host_msix_entries[i].vector;
+ if (irq != 0)
+ enable_irq(irq);
+ assigned_dev->host_irq_disabled = false;
+ }
+ } else {
+ kvm_set_irq(assigned_dev->kvm, assigned_dev->irq_source_id,
+ assigned_dev->guest_irq, 1);
+ if (assigned_dev->irq_requested_type &
+ KVM_DEV_IRQ_GUEST_MSI) {
+ enable_irq(assigned_dev->host_irq);
+ assigned_dev->host_irq_disabled = false;
+ }
}
+
+ spin_unlock_irq(&assigned_dev->assigned_dev_lock);
mutex_unlock(&assigned_dev->kvm->lock);
}
static irqreturn_t kvm_assigned_dev_intr(int irq, void *dev_id)
{
+ unsigned long flags;
struct kvm_assigned_dev_kernel *assigned_dev =
(struct kvm_assigned_dev_kernel *) dev_id;
+ spin_lock_irqsave(&assigned_dev->assigned_dev_lock, flags);
+ if (assigned_dev->irq_requested_type & KVM_DEV_IRQ_HOST_MSIX) {
+ int index = find_index_from_host_irq(assigned_dev, irq);
+ if (index < 0)
+ goto out;
+ assigned_dev->guest_msix_entries[index].flags |=
+ KVM_ASSIGNED_MSIX_PENDING;
+ }
+
schedule_work(&assigned_dev->interrupt_work);
disable_irq_nosync(irq);
assigned_dev->host_irq_disabled = true;
+out:
+ spin_unlock_irqrestore(&assigned_dev->assigned_dev_lock, flags);
return IRQ_HANDLED;
}
@@ -134,6 +191,7 @@ static irqreturn_t kvm_assigned_dev_intr(int irq, void *dev_id)
static void kvm_assigned_dev_ack_irq(struct kvm_irq_ack_notifier *kian)
{
struct kvm_assigned_dev_kernel *dev;
+ unsigned long flags;
if (kian->gsi == -1)
return;
@@ -146,28 +204,30 @@ static void kvm_assigned_dev_ack_irq(struct kvm_irq_ack_notifier *kian)
/* The guest irq may be shared so this ack may be
* from another device.
*/
+ spin_lock_irqsave(&dev->assigned_dev_lock, flags);
if (dev->host_irq_disabled) {
enable_irq(dev->host_irq);
dev->host_irq_disabled = false;
}
+ spin_unlock_irqrestore(&dev->assigned_dev_lock, flags);
}
-/* The function implicit hold kvm->lock mutex due to cancel_work_sync() */
-static void kvm_free_assigned_irq(struct kvm *kvm,
- struct kvm_assigned_dev_kernel *assigned_dev)
+static void deassign_guest_irq(struct kvm *kvm,
+ struct kvm_assigned_dev_kernel *assigned_dev)
{
- if (!irqchip_in_kernel(kvm))
- return;
-
kvm_unregister_irq_ack_notifier(&assigned_dev->ack_notifier);
+ assigned_dev->ack_notifier.gsi = -1;
if (assigned_dev->irq_source_id != -1)
kvm_free_irq_source_id(kvm, assigned_dev->irq_source_id);
assigned_dev->irq_source_id = -1;
+ assigned_dev->irq_requested_type &= ~(KVM_DEV_IRQ_GUEST_MASK);
+}
- if (!assigned_dev->irq_requested_type)
- return;
-
+/* The function implicit hold kvm->lock mutex due to cancel_work_sync() */
+static void deassign_host_irq(struct kvm *kvm,
+ struct kvm_assigned_dev_kernel *assigned_dev)
+{
/*
* In kvm_free_device_irq, cancel_work_sync return true if:
* 1. work is scheduled, and then cancelled.
@@ -184,17 +244,64 @@ static void kvm_free_assigned_irq(struct kvm *kvm,
* now, the kvm state is still legal for probably we also have to wait
* interrupt_work done.
*/
- disable_irq_nosync(assigned_dev->host_irq);
- cancel_work_sync(&assigned_dev->interrupt_work);
+ if (assigned_dev->irq_requested_type & KVM_DEV_IRQ_HOST_MSIX) {
+ int i;
+ for (i = 0; i < assigned_dev->entries_nr; i++)
+ disable_irq_nosync(assigned_dev->
+ host_msix_entries[i].vector);
+
+ cancel_work_sync(&assigned_dev->interrupt_work);
+
+ for (i = 0; i < assigned_dev->entries_nr; i++)
+ free_irq(assigned_dev->host_msix_entries[i].vector,
+ (void *)assigned_dev);
+
+ assigned_dev->entries_nr = 0;
+ kfree(assigned_dev->host_msix_entries);
+ kfree(assigned_dev->guest_msix_entries);
+ pci_disable_msix(assigned_dev->dev);
+ } else {
+ /* Deal with MSI and INTx */
+ disable_irq_nosync(assigned_dev->host_irq);
+ cancel_work_sync(&assigned_dev->interrupt_work);
- free_irq(assigned_dev->host_irq, (void *)assigned_dev);
+ free_irq(assigned_dev->host_irq, (void *)assigned_dev);
- if (assigned_dev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_MSI)
- pci_disable_msi(assigned_dev->dev);
+ if (assigned_dev->irq_requested_type & KVM_DEV_IRQ_HOST_MSI)
+ pci_disable_msi(assigned_dev->dev);
+ }
- assigned_dev->irq_requested_type = 0;
+ assigned_dev->irq_requested_type &= ~(KVM_DEV_IRQ_HOST_MASK);
}
+static int kvm_deassign_irq(struct kvm *kvm,
+ struct kvm_assigned_dev_kernel *assigned_dev,
+ unsigned long irq_requested_type)
+{
+ unsigned long guest_irq_type, host_irq_type;
+
+ if (!irqchip_in_kernel(kvm))
+ return -EINVAL;
+ /* no irq assignment to deassign */
+ if (!assigned_dev->irq_requested_type)
+ return -ENXIO;
+
+ host_irq_type = irq_requested_type & KVM_DEV_IRQ_HOST_MASK;
+ guest_irq_type = irq_requested_type & KVM_DEV_IRQ_GUEST_MASK;
+
+ if (host_irq_type)
+ deassign_host_irq(kvm, assigned_dev);
+ if (guest_irq_type)
+ deassign_guest_irq(kvm, assigned_dev);
+
+ return 0;
+}
+
+static void kvm_free_assigned_irq(struct kvm *kvm,
+ struct kvm_assigned_dev_kernel *assigned_dev)
+{
+ kvm_deassign_irq(kvm, assigned_dev, assigned_dev->irq_requested_type);
+}
static void kvm_free_assigned_device(struct kvm *kvm,
struct kvm_assigned_dev_kernel
@@ -226,190 +333,244 @@ void kvm_free_all_assigned_devices(struct kvm *kvm)
}
}
-static int assigned_device_update_intx(struct kvm *kvm,
- struct kvm_assigned_dev_kernel *adev,
- struct kvm_assigned_irq *airq)
+static int assigned_device_enable_host_intx(struct kvm *kvm,
+ struct kvm_assigned_dev_kernel *dev)
{
- adev->guest_irq = airq->guest_irq;
- adev->ack_notifier.gsi = airq->guest_irq;
+ dev->host_irq = dev->dev->irq;
+ /* Even though this is PCI, we don't want to use shared
+ * interrupts. Sharing host devices with guest-assigned devices
+ * on the same interrupt line is not a happy situation: there
+ * are going to be long delays in accepting, acking, etc.
+ */
+ if (request_irq(dev->host_irq, kvm_assigned_dev_intr,
+ 0, "kvm_assigned_intx_device", (void *)dev))
+ return -EIO;
+ return 0;
+}
- if (adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_INTX)
- return 0;
+#ifdef __KVM_HAVE_MSI
+static int assigned_device_enable_host_msi(struct kvm *kvm,
+ struct kvm_assigned_dev_kernel *dev)
+{
+ int r;
- if (irqchip_in_kernel(kvm)) {
- if (!msi2intx &&
- (adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_MSI)) {
- free_irq(adev->host_irq, (void *)adev);
- pci_disable_msi(adev->dev);
- }
+ if (!dev->dev->msi_enabled) {
+ r = pci_enable_msi(dev->dev);
+ if (r)
+ return r;
+ }
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
+ dev->host_irq = dev->dev->irq;
+ if (request_irq(dev->host_irq, kvm_assigned_dev_intr, 0,
+ "kvm_assigned_msi_device", (void *)dev)) {
+ pci_disable_msi(dev->dev);
+ return -EIO;
+ }
- if (airq->host_irq)
- adev->host_irq = airq->host_irq;
- else
- adev->host_irq = adev->dev->irq;
+ return 0;
+}
+#endif
- /* Even though this is PCI, we don't want to use shared
- * interrupts. Sharing host devices with guest-assigned devices
- * on the same interrupt line is not a happy situation: there
- * are going to be long delays in accepting, acking, etc.
- */
- if (request_irq(adev->host_irq, kvm_assigned_dev_intr,
- 0, "kvm_assigned_intx_device", (void *)adev))
- return -EIO;
+#ifdef __KVM_HAVE_MSIX
+static int assigned_device_enable_host_msix(struct kvm *kvm,
+ struct kvm_assigned_dev_kernel *dev)
+{
+ int i, r = -EINVAL;
+
+ /* host_msix_entries and guest_msix_entries should have been
+ * initialized */
+ if (dev->entries_nr == 0)
+ return r;
+
+ r = pci_enable_msix(dev->dev, dev->host_msix_entries, dev->entries_nr);
+ if (r)
+ return r;
+
+ for (i = 0; i < dev->entries_nr; i++) {
+ r = request_irq(dev->host_msix_entries[i].vector,
+ kvm_assigned_dev_intr, 0,
+ "kvm_assigned_msix_device",
+ (void *)dev);
+ /* FIXME: free requested_irq's on failure */
+ if (r)
+ return r;
}
- adev->irq_requested_type = KVM_ASSIGNED_DEV_GUEST_INTX |
- KVM_ASSIGNED_DEV_HOST_INTX;
return 0;
}
-#ifdef CONFIG_X86
-static int assigned_device_update_msi(struct kvm *kvm,
- struct kvm_assigned_dev_kernel *adev,
- struct kvm_assigned_irq *airq)
+#endif
+
+static int assigned_device_enable_guest_intx(struct kvm *kvm,
+ struct kvm_assigned_dev_kernel *dev,
+ struct kvm_assigned_irq *irq)
{
- int r;
+ dev->guest_irq = irq->guest_irq;
+ dev->ack_notifier.gsi = irq->guest_irq;
+ return 0;
+}
- adev->guest_irq = airq->guest_irq;
- if (airq->flags & KVM_DEV_IRQ_ASSIGN_ENABLE_MSI) {
- /* x86 don't care upper address of guest msi message addr */
- adev->irq_requested_type |= KVM_ASSIGNED_DEV_GUEST_MSI;
- adev->irq_requested_type &= ~KVM_ASSIGNED_DEV_GUEST_INTX;
- adev->ack_notifier.gsi = -1;
- } else if (msi2intx) {
- adev->irq_requested_type |= KVM_ASSIGNED_DEV_GUEST_INTX;
- adev->irq_requested_type &= ~KVM_ASSIGNED_DEV_GUEST_MSI;
- adev->ack_notifier.gsi = airq->guest_irq;
- } else {
- /*
- * Guest require to disable device MSI, we disable MSI and
- * re-enable INTx by default again. Notice it's only for
- * non-msi2intx.
- */
- assigned_device_update_intx(kvm, adev, airq);
- return 0;
+#ifdef __KVM_HAVE_MSI
+static int assigned_device_enable_guest_msi(struct kvm *kvm,
+ struct kvm_assigned_dev_kernel *dev,
+ struct kvm_assigned_irq *irq)
+{
+ dev->guest_irq = irq->guest_irq;
+ dev->ack_notifier.gsi = -1;
+ return 0;
+}
+#endif
+#ifdef __KVM_HAVE_MSIX
+static int assigned_device_enable_guest_msix(struct kvm *kvm,
+ struct kvm_assigned_dev_kernel *dev,
+ struct kvm_assigned_irq *irq)
+{
+ dev->guest_irq = irq->guest_irq;
+ dev->ack_notifier.gsi = -1;
+ return 0;
+}
+#endif
+
+static int assign_host_irq(struct kvm *kvm,
+ struct kvm_assigned_dev_kernel *dev,
+ __u32 host_irq_type)
+{
+ int r = -EEXIST;
+
+ if (dev->irq_requested_type & KVM_DEV_IRQ_HOST_MASK)
+ return r;
+
+ switch (host_irq_type) {
+ case KVM_DEV_IRQ_HOST_INTX:
+ r = assigned_device_enable_host_intx(kvm, dev);
+ break;
+#ifdef __KVM_HAVE_MSI
+ case KVM_DEV_IRQ_HOST_MSI:
+ r = assigned_device_enable_host_msi(kvm, dev);
+ break;
+#endif
+#ifdef __KVM_HAVE_MSIX
+ case KVM_DEV_IRQ_HOST_MSIX:
+ r = assigned_device_enable_host_msix(kvm, dev);
+ break;
+#endif
+ default:
+ r = -EINVAL;
}
- if (adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_MSI)
- return 0;
+ if (!r)
+ dev->irq_requested_type |= host_irq_type;
+
+ return r;
+}
- if (irqchip_in_kernel(kvm)) {
- if (!msi2intx) {
- if (adev->irq_requested_type &
- KVM_ASSIGNED_DEV_HOST_INTX)
- free_irq(adev->host_irq, (void *)adev);
+static int assign_guest_irq(struct kvm *kvm,
+ struct kvm_assigned_dev_kernel *dev,
+ struct kvm_assigned_irq *irq,
+ unsigned long guest_irq_type)
+{
+ int id;
+ int r = -EEXIST;
- r = pci_enable_msi(adev->dev);
- if (r)
- return r;
- }
+ if (dev->irq_requested_type & KVM_DEV_IRQ_GUEST_MASK)
+ return r;
+
+ id = kvm_request_irq_source_id(kvm);
+ if (id < 0)
+ return id;
+
+ dev->irq_source_id = id;
- adev->host_irq = adev->dev->irq;
- if (request_irq(adev->host_irq, kvm_assigned_dev_intr, 0,
- "kvm_assigned_msi_device", (void *)adev))
- return -EIO;
+ switch (guest_irq_type) {
+ case KVM_DEV_IRQ_GUEST_INTX:
+ r = assigned_device_enable_guest_intx(kvm, dev, irq);
+ break;
+#ifdef __KVM_HAVE_MSI
+ case KVM_DEV_IRQ_GUEST_MSI:
+ r = assigned_device_enable_guest_msi(kvm, dev, irq);
+ break;
+#endif
+#ifdef __KVM_HAVE_MSIX
+ case KVM_DEV_IRQ_GUEST_MSIX:
+ r = assigned_device_enable_guest_msix(kvm, dev, irq);
+ break;
+#endif
+ default:
+ r = -EINVAL;
}
- if (!msi2intx)
- adev->irq_requested_type = KVM_ASSIGNED_DEV_GUEST_MSI;
+ if (!r) {
+ dev->irq_requested_type |= guest_irq_type;
+ kvm_register_irq_ack_notifier(kvm, &dev->ack_notifier);
+ } else
+ kvm_free_irq_source_id(kvm, dev->irq_source_id);
- adev->irq_requested_type |= KVM_ASSIGNED_DEV_HOST_MSI;
- return 0;
+ return r;
}
-#endif
+/* TODO Deal with KVM_DEV_IRQ_ASSIGNED_MASK_MSIX */
static int kvm_vm_ioctl_assign_irq(struct kvm *kvm,
- struct kvm_assigned_irq
- *assigned_irq)
+ struct kvm_assigned_irq *assigned_irq)
{
- int r = 0;
+ int r = -EINVAL;
struct kvm_assigned_dev_kernel *match;
- u32 current_flags = 0, changed_flags;
+ unsigned long host_irq_type, guest_irq_type;
- mutex_lock(&kvm->lock);
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ if (!irqchip_in_kernel(kvm))
+ return r;
+ mutex_lock(&kvm->lock);
+ r = -ENODEV;
match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head,
assigned_irq->assigned_dev_id);
- if (!match) {
- mutex_unlock(&kvm->lock);
- return -EINVAL;
- }
-
- if (!match->irq_requested_type) {
- INIT_WORK(&match->interrupt_work,
- kvm_assigned_dev_interrupt_work_handler);
- if (irqchip_in_kernel(kvm)) {
- /* Register ack nofitier */
- match->ack_notifier.gsi = -1;
- match->ack_notifier.irq_acked =
- kvm_assigned_dev_ack_irq;
- kvm_register_irq_ack_notifier(kvm,
- &match->ack_notifier);
-
- /* Request IRQ source ID */
- r = kvm_request_irq_source_id(kvm);
- if (r < 0)
- goto out_release;
- else
- match->irq_source_id = r;
-
-#ifdef CONFIG_X86
- /* Determine host device irq type, we can know the
- * result from dev->msi_enabled */
- if (msi2intx)
- pci_enable_msi(match->dev);
-#endif
- }
- }
+ if (!match)
+ goto out;
- if ((match->irq_requested_type & KVM_ASSIGNED_DEV_HOST_MSI) &&
- (match->irq_requested_type & KVM_ASSIGNED_DEV_GUEST_MSI))
- current_flags |= KVM_DEV_IRQ_ASSIGN_ENABLE_MSI;
+ host_irq_type = (assigned_irq->flags & KVM_DEV_IRQ_HOST_MASK);
+ guest_irq_type = (assigned_irq->flags & KVM_DEV_IRQ_GUEST_MASK);
- changed_flags = assigned_irq->flags ^ current_flags;
+ r = -EINVAL;
+ /* can only assign one type at a time */
+ if (hweight_long(host_irq_type) > 1)
+ goto out;
+ if (hweight_long(guest_irq_type) > 1)
+ goto out;
+ if (host_irq_type == 0 && guest_irq_type == 0)
+ goto out;
- if ((changed_flags & KVM_DEV_IRQ_ASSIGN_MSI_ACTION) ||
- (msi2intx && match->dev->msi_enabled)) {
-#ifdef CONFIG_X86
- r = assigned_device_update_msi(kvm, match, assigned_irq);
- if (r) {
- printk(KERN_WARNING "kvm: failed to enable "
- "MSI device!\n");
- goto out_release;
- }
-#else
- r = -ENOTTY;
-#endif
- } else if (assigned_irq->host_irq == 0 && match->dev->irq == 0) {
- /* Host device IRQ 0 means don't support INTx */
- if (!msi2intx) {
- printk(KERN_WARNING
- "kvm: wait device to enable MSI!\n");
- r = 0;
- } else {
- printk(KERN_WARNING
- "kvm: failed to enable MSI device!\n");
- r = -ENOTTY;
- goto out_release;
- }
- } else {
- /* Non-sharing INTx mode */
- r = assigned_device_update_intx(kvm, match, assigned_irq);
- if (r) {
- printk(KERN_WARNING "kvm: failed to enable "
- "INTx device!\n");
- goto out_release;
- }
- }
+ r = 0;
+ if (host_irq_type)
+ r = assign_host_irq(kvm, match, host_irq_type);
+ if (r)
+ goto out;
+ if (guest_irq_type)
+ r = assign_guest_irq(kvm, match, assigned_irq, guest_irq_type);
+out:
mutex_unlock(&kvm->lock);
return r;
-out_release:
+}
+
+static int kvm_vm_ioctl_deassign_dev_irq(struct kvm *kvm,
+ struct kvm_assigned_irq
+ *assigned_irq)
+{
+ int r = -ENODEV;
+ struct kvm_assigned_dev_kernel *match;
+
+ mutex_lock(&kvm->lock);
+
+ match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head,
+ assigned_irq->assigned_dev_id);
+ if (!match)
+ goto out;
+
+ r = kvm_deassign_irq(kvm, match, assigned_irq->flags);
+out:
mutex_unlock(&kvm->lock);
- kvm_free_assigned_device(kvm, match);
return r;
}
@@ -427,7 +588,7 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
assigned_dev->assigned_dev_id);
if (match) {
/* device already assigned */
- r = -EINVAL;
+ r = -EEXIST;
goto out;
}
@@ -464,8 +625,12 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
match->host_devfn = assigned_dev->devfn;
match->flags = assigned_dev->flags;
match->dev = dev;
+ spin_lock_init(&match->assigned_dev_lock);
match->irq_source_id = -1;
match->kvm = kvm;
+ match->ack_notifier.irq_acked = kvm_assigned_dev_ack_irq;
+ INIT_WORK(&match->interrupt_work,
+ kvm_assigned_dev_interrupt_work_handler);
list_add(&match->list, &kvm->arch.assigned_dev_head);
@@ -878,6 +1043,8 @@ static void kvm_destroy_vm(struct kvm *kvm)
#endif
#if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER)
mmu_notifier_unregister(&kvm->mmu_notifier, kvm->mm);
+#else
+ kvm_arch_flush_shadow(kvm);
#endif
kvm_arch_destroy_vm(kvm);
mmdrop(mm);
@@ -920,6 +1087,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
int r;
gfn_t base_gfn;
unsigned long npages;
+ int largepages;
unsigned long i;
struct kvm_memory_slot *memslot;
struct kvm_memory_slot old, new;
@@ -960,7 +1128,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
for (i = 0; i < KVM_MEMORY_SLOTS; ++i) {
struct kvm_memory_slot *s = &kvm->memslots[i];
- if (s == memslot)
+ if (s == memslot || !s->npages)
continue;
if (!((base_gfn + npages <= s->base_gfn) ||
(base_gfn >= s->base_gfn + s->npages)))
@@ -995,11 +1163,8 @@ int __kvm_set_memory_region(struct kvm *kvm,
new.userspace_addr = 0;
}
if (npages && !new.lpage_info) {
- int largepages = npages / KVM_PAGES_PER_HPAGE;
- if (npages % KVM_PAGES_PER_HPAGE)
- largepages++;
- if (base_gfn % KVM_PAGES_PER_HPAGE)
- largepages++;
+ largepages = 1 + (base_gfn + npages - 1) / KVM_PAGES_PER_HPAGE;
+ largepages -= base_gfn / KVM_PAGES_PER_HPAGE;
new.lpage_info = vmalloc(largepages * sizeof(*new.lpage_info));
@@ -1456,12 +1621,14 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
for (;;) {
prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE);
- if (kvm_cpu_has_interrupt(vcpu) ||
- kvm_cpu_has_pending_timer(vcpu) ||
- kvm_arch_vcpu_runnable(vcpu)) {
+ if ((kvm_arch_interrupt_allowed(vcpu) &&
+ kvm_cpu_has_interrupt(vcpu)) ||
+ kvm_arch_vcpu_runnable(vcpu)) {
set_bit(KVM_REQ_UNHALT, &vcpu->requests);
break;
}
+ if (kvm_cpu_has_pending_timer(vcpu))
+ break;
if (signal_pending(current))
break;
@@ -1595,6 +1762,88 @@ static int kvm_vcpu_ioctl_set_sigmask(struct kvm_vcpu *vcpu, sigset_t *sigset)
return 0;
}
+#ifdef __KVM_HAVE_MSIX
+static int kvm_vm_ioctl_set_msix_nr(struct kvm *kvm,
+ struct kvm_assigned_msix_nr *entry_nr)
+{
+ int r = 0;
+ struct kvm_assigned_dev_kernel *adev;
+
+ mutex_lock(&kvm->lock);
+
+ adev = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head,
+ entry_nr->assigned_dev_id);
+ if (!adev) {
+ r = -EINVAL;
+ goto msix_nr_out;
+ }
+
+ if (adev->entries_nr == 0) {
+ adev->entries_nr = entry_nr->entry_nr;
+ if (adev->entries_nr == 0 ||
+ adev->entries_nr >= KVM_MAX_MSIX_PER_DEV) {
+ r = -EINVAL;
+ goto msix_nr_out;
+ }
+
+ adev->host_msix_entries = kzalloc(sizeof(struct msix_entry) *
+ entry_nr->entry_nr,
+ GFP_KERNEL);
+ if (!adev->host_msix_entries) {
+ r = -ENOMEM;
+ goto msix_nr_out;
+ }
+ adev->guest_msix_entries = kzalloc(
+ sizeof(struct kvm_guest_msix_entry) *
+ entry_nr->entry_nr, GFP_KERNEL);
+ if (!adev->guest_msix_entries) {
+ kfree(adev->host_msix_entries);
+ r = -ENOMEM;
+ goto msix_nr_out;
+ }
+ } else /* Not allowed set MSI-X number twice */
+ r = -EINVAL;
+msix_nr_out:
+ mutex_unlock(&kvm->lock);
+ return r;
+}
+
+static int kvm_vm_ioctl_set_msix_entry(struct kvm *kvm,
+ struct kvm_assigned_msix_entry *entry)
+{
+ int r = 0, i;
+ struct kvm_assigned_dev_kernel *adev;
+
+ mutex_lock(&kvm->lock);
+
+ adev = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head,
+ entry->assigned_dev_id);
+
+ if (!adev) {
+ r = -EINVAL;
+ goto msix_entry_out;
+ }
+
+ for (i = 0; i < adev->entries_nr; i++)
+ if (adev->guest_msix_entries[i].vector == 0 ||
+ adev->guest_msix_entries[i].entry == entry->entry) {
+ adev->guest_msix_entries[i].entry = entry->entry;
+ adev->guest_msix_entries[i].vector = entry->gsi;
+ adev->host_msix_entries[i].entry = entry->entry;
+ break;
+ }
+ if (i == adev->entries_nr) {
+ r = -ENOSPC;
+ goto msix_entry_out;
+ }
+
+msix_entry_out:
+ mutex_unlock(&kvm->lock);
+
+ return r;
+}
+#endif
+
static long kvm_vcpu_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg)
{
@@ -1866,6 +2115,11 @@ static long kvm_vm_ioctl(struct file *filp,
break;
}
case KVM_ASSIGN_IRQ: {
+ r = -EOPNOTSUPP;
+ break;
+ }
+#ifdef KVM_CAP_ASSIGN_DEV_IRQ
+ case KVM_ASSIGN_DEV_IRQ: {
struct kvm_assigned_irq assigned_irq;
r = -EFAULT;
@@ -1876,6 +2130,18 @@ static long kvm_vm_ioctl(struct file *filp,
goto out;
break;
}
+ case KVM_DEASSIGN_DEV_IRQ: {
+ struct kvm_assigned_irq assigned_irq;
+
+ r = -EFAULT;
+ if (copy_from_user(&assigned_irq, argp, sizeof assigned_irq))
+ goto out;
+ r = kvm_vm_ioctl_deassign_dev_irq(kvm, &assigned_irq);
+ if (r)
+ goto out;
+ break;
+ }
+#endif
#endif
#ifdef KVM_CAP_DEVICE_DEASSIGNMENT
case KVM_DEASSIGN_PCI_DEVICE: {
@@ -1919,7 +2185,29 @@ static long kvm_vm_ioctl(struct file *filp,
vfree(entries);
break;
}
+#ifdef __KVM_HAVE_MSIX
+ case KVM_ASSIGN_SET_MSIX_NR: {
+ struct kvm_assigned_msix_nr entry_nr;
+ r = -EFAULT;
+ if (copy_from_user(&entry_nr, argp, sizeof entry_nr))
+ goto out;
+ r = kvm_vm_ioctl_set_msix_nr(kvm, &entry_nr);
+ if (r)
+ goto out;
+ break;
+ }
+ case KVM_ASSIGN_SET_MSIX_ENTRY: {
+ struct kvm_assigned_msix_entry entry;
+ r = -EFAULT;
+ if (copy_from_user(&entry, argp, sizeof entry))
+ goto out;
+ r = kvm_vm_ioctl_set_msix_entry(kvm, &entry);
+ if (r)
+ goto out;
+ break;
+ }
#endif
+#endif /* KVM_CAP_IRQ_ROUTING */
default:
r = kvm_arch_vm_ioctl(filp, ioctl, arg);
}
@@ -1985,6 +2273,7 @@ static long kvm_dev_ioctl_check_extension_generic(long arg)
switch (arg) {
case KVM_CAP_USER_MEMORY:
case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
+ case KVM_CAP_JOIN_MEMORY_REGIONS_WORKS:
return 1;
#ifdef CONFIG_HAVE_KVM_IRQCHIP
case KVM_CAP_IRQ_ROUTING:
@@ -2113,15 +2402,15 @@ EXPORT_SYMBOL_GPL(kvm_handle_fault_on_reboot);
static int kvm_reboot(struct notifier_block *notifier, unsigned long val,
void *v)
{
- if (val == SYS_RESTART) {
- /*
- * Some (well, at least mine) BIOSes hang on reboot if
- * in vmx root mode.
- */
- printk(KERN_INFO "kvm: exiting hardware virtualization\n");
- kvm_rebooting = true;
- on_each_cpu(hardware_disable, NULL, 1);
- }
+ /*
+ * Some (well, at least mine) BIOSes hang on reboot if
+ * in vmx root mode.
+ *
+ * And Intel TXT required VMX off for all cpu when system shutdown.
+ */
+ printk(KERN_INFO "kvm: exiting hardware virtualization\n");
+ kvm_rebooting = true;
+ on_each_cpu(hardware_disable, NULL, 1);
return NOTIFY_OK;
}
@@ -2354,9 +2643,6 @@ int kvm_init(void *opaque, unsigned int vcpu_size,
kvm_preempt_ops.sched_in = kvm_sched_in;
kvm_preempt_ops.sched_out = kvm_sched_out;
-#ifndef CONFIG_X86
- msi2intx = 0;
-#endif
return 0;